{ USB serial port wrapper services for Mikropascal PIC32 } { Copyright (C)2015-2018, Philip Munts, President, Munts AM Corp. } { } { Redistribution and use in source and binary forms, with or without } { modification, are permitted provided that the following conditions are met: } { } { * Redistributions of source code must retain the above copyright notice, } { this list of conditions and the following disclaimer. } { } { THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" } { AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE } { IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE } { ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE } { LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR } { CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF } { SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS } { INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN } { CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) } { ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE } { POSSIBILITY OF SUCH DAMAGE. } UNIT usb_serial; PROCEDURE USB_Serial_Init(); FUNCTION USB_Serial_Data_Ready() : boolean; FUNCTION USB_Serial_Read() : byte; FUNCTION USB_Serial_Tx_Idle() : boolean; PROCEDURE USB_Serial_Write(c : byte); PROCEDURE USB_Serial_Write_Text(VAR s : string); PROCEDURE USBDev_CDCParamsChanged(); PROCEDURE USBDev_CDCDataReceived(size : word); PROCEDURE USBDev_CDCDataSent(ep : byte); IMPLEMENTATION CONST QUEUE_SIZE = 256; VAR ReceiveBuffer : ARRAY [1 .. 64] OF byte; ReceiveQueue : ARRAY [0 .. QUEUE_SIZE-1] OF byte; head : integer; tail : integer; count : integer; sending : boolean; PROCEDURE USB_Serial_Init(); BEGIN head := 0; tail := 0; count := 0; sending := false; { Initialize the USB subsystem } USBDev_CDCInit(); USBDev_Init(); USBDev_RegisterDataSentHandler(@USBDev_CDCDataSent); USBIE_bit := 1; IPC11 := dword(7) shl USBIP0; EnableInterrupts(); { Wait until we have been enumerated by the USB host } REPEAT UNTIL USBDev_GetDeviceState() = _USB_DEV_STATE_CONFIGURED; USBDev_CDCSetReceiveBuffer(@ReceiveBuffer); END; FUNCTION USB_Serial_Data_Ready() : boolean; BEGIN IF count > 0 THEN USB_Serial_Data_Ready := true ELSE USB_Serial_Data_Ready := false; END; FUNCTION USB_Serial_Read() : byte; BEGIN REPEAT UNTIL count > 0; USB_Serial_Read := ReceiveQueue[head]; DisableInterrupts(); dec(count); EnableInterrupts(); inc(head); IF head = QUEUE_SIZE THEN head := 0; END; FUNCTION USB_Serial_Tx_Idle() : boolean; BEGIN USB_Serial_Tx_Idle := NOT sending; END; PROCEDURE USB_Serial_Write(c : byte); BEGIN REPEAT UNTIL NOT sending; sending := true; USBDev_CDCSendData(@c, 1); delay_ms(1); END; PROCEDURE USB_Serial_Write_Text(VAR s : string); BEGIN REPEAT UNTIL NOT sending; sending := true; USBDev_CDCSendData(@s, strlen(s)); delay_ms(1); END; FUNCTION Min(x, y : integer) : integer; BEGIN IF x < y THEN Min := x ELSE Min := y; END; PROCEDURE USBDev_CDCParamsChanged(); BEGIN END; PROCEDURE USBDev_CDCDataReceived(size : word); VAR i : integer; BEGIN size := Min(size, QUEUE_SIZE - count); FOR i := 1 TO size DO BEGIN ReceiveQueue[tail] := ReceiveBuffer[i]; inc(tail); inc(count); IF tail = QUEUE_SIZE THEN tail := 0; END; USBDev_CDCSetReceiveBuffer(@ReceiveBuffer); END; PROCEDURE USBDev_CDCDataSent(ep : byte); BEGIN sending := false; END; PROCEDURE USB0Interrupt(); iv IVT_USB_1; ilevel 7; ics ICS_SRS; BEGIN USBDev_IntHandler(); END; END.