home *** CD-ROM | disk | FTP | other *** search
- {
- ════════════════════════════════════════════════════════════════════════════
-
- Visionix Serial Communictions Unit - 8250/16450/16550 UART (VUART)
- Version 0.8
- Copyright 1991,92,93 Visionix
- ALL RIGHTS RESERVED
-
- ────────────────────────────────────────────────────────────────────────────
-
- ** revision history in reverse chronological order **
-
- Initials Date Comment
- ──────── ──────── ────────────────────────────────────────────────────────
-
- mep 11/15/93 First logged revision.
-
- ────────────────────────────────────────────────────────────────────────────
- }
-
- (*-
-
- [TEXT]
-
- <Overview>
-
- This unit implements functions to interface with the PC/ATs 8250,
- 16450, or 16550 Univeral Asychronous Receiver/Transmitter, or UART
- chip. The UART chip is the PCs interface to the RS-232 world.
-
- Additionally, this unit impelements a function to interface the UART
- functions into the VSERu device-indepednent serial unit. This function,
- UartSerDriverProc, is a serial driver procedure for VDOSu serial channels.
-
- UartSerDriverProc can be specified as the serial-driver for a serial
- channel by calling VSerDriverNew and specifying UartSerDriverProc
- as the serial driver procedure.
-
- <Interface>
-
- -*)
-
-
- Unit VUartU;
-
- Interface
-
- Uses
-
- VTypesu,
- VSerlu,
- DOS;
-
-
-
- Procedure VUartBaudSet( BaudRate : LONGINT );
-
- Function VUartBaudGet : LONGINT;
-
- Function VUartInit( ComPort : BYTE;
- BaudRate : LONGINT ): WORD;
-
- Procedure VUartDeInit;
-
- Procedure VUartDTROn;
-
- Procedure VUartDTROff;
-
- Function VUartIsTXReady : BOOLEAN;
-
- Function VUartIsCarrier : BOOLEAN;
-
- Function VUartIsRXReady : BOOLEAN;
-
- Function VUartReadChar : CHAR;
-
- Procedure VUartWriteChar( Ch : CHAR );
-
- Procedure VUartOutFlush;
-
- Procedure VUartOutPurge;
-
- Procedure VUartInPurge;
-
- Procedure VUartBreak( DelayMS : WORD );
-
- Procedure VUartCtsRtsSet( ON : BOOLEAN );
-
-
- Procedure UartSerDriverProc( SDP : PSerDriverPacket );
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- IMPLEMENTATION
-
-
- Const
-
-
- cUartClockFreq = 115200;
-
- cMaxComPort = 7;
- cInBuffSize = 8196;
- cInBuffMax = 8195;
-
- cUartInt = $14;
- cIntMaskReg = $21; { 8259 interrupt mask register }
-
- {----------------------------}
- { 8250/16450/16550 registers }
- {----------------------------}
-
- cUartTHR = $00; { }
- cUartRBR = $00; { }
-
- cUartIER = $01; { Interrupt Enable Register }
-
- cUartIIR = $02; { Interrupt ID Register }
- cUartFCR = $02; { 16550 FIFO control register }
-
- cUartLCR = $03; { Line Control Register }
-
- cUartMCR = $04; { Modem Control Register }
-
- cUartLSR = $05; { Line Status Register }
-
- cUartMSR = $06; { Modem Status Register }
-
-
- {---------------------------------}
- { Interrupt Enable Register flags }
- {---------------------------------}
-
- cEnableRcvInt = $01; { enable receive interrupt }
- cEnableXfrInt = $02; { enable transfer interrupt }
- cEnableLSInt = $04; { enable line-status interrupt }
- cEnableMSInt = $08; { enable modem-status interrupt}
-
- {-----------------------------------}
- { Interrupt ID Register (IIR) Flags }
- {-----------------------------------}
-
- cIntPending = $01; { an interrupt is pending }
-
- cIntIDMask = $02+$04; { interrupt ID mask }
-
- cIntIDLookMSR = $00; { interrupt ID=look in MSR }
- cIntIDXfer = $02; { interrupt ID=transfered data }
- cIntIDRcv = $04; { interrupt ID=received data }
-
- cIntFifoTimeout = $08; { 16550 FIFO timeout }
-
- cFifoModeMask = $40+$80; { 16550 Mode Status Mask }
-
- cFifoModeChar = $00; { 16550 Mode=char (emu 16450) }
- cFifoModeDMA = $40; { 16550 Mode=type 3 DMA }
- cFifoModeFifo = $80+$40; { 16550 Mode=FIFO enabled }
-
- {-----------------------------------}
- { FIFO Control Register (FCR) Flags }
- {-----------------------------------}
-
- cFifoEnable = $01; { 16550 Fifo Enable flag }
- cFifoRcvBuffReset = $02; { 16550 Reset Receive buffer }
- cFifoXferBuffReset = $04; { 16550 Reset Transmit buffer }
-
- cFifoFTSMask = $80+$40; { 16550 FIFO Trigger Size mask }
-
- cFifoFTS1 = $00; { 16550 FIFO Trig Size=1 byte }
- cFifoFTS4 = $40; { 16550 FIFO Trig Size=4 bytes}
- cFifoFTS8 = $80; { 16550 FIFO Trig Size=8 bytes}
- cFifoFTS14 = $80+$40; { 16550 FIFO Trig Size=14 bytes}
-
-
- {-----------------------------------}
- { Line Control Register( LCR) Flags }
- {-----------------------------------}
-
- cDataBitsMask = $01+$02; { Data bits (wordsize) mask }
- cDataBits5 = $00; { Data bits = 5 }
- cDataBits6 = $01; { Data bits = 6 }
- cDataBits7 = $02; { Data bits = 7 }
- cDataBits8 = $01+$02; { Data bits = 8 }
-
- cStopBits1 = $00; { Stop bits = 1 }
- cStopBits2 = $04; { Stop bits = 2 }
-
- cParityEnable = $08; { Enable parity }
-
- cParityEven = $10; { even parity }
-
- cStickyParity = $20; { sticky parity }
-
- cBreakOn = $40; { turn break on }
-
- cAccessDivLatch = $80; { access divisor latch }
-
-
-
- {------------------------------------}
- { Modem Control Register (MCR) flags }
- {------------------------------------}
-
- cDTR = $01; { Data terminal ready }
- cRTS = $02; { Ready to send }
- cOut1 = $04; { Out 1 - not used in PCs }
-
- cOut2 = $08; { Out 2 - }
- cMasterEnableInts = $08; { master enables interrupts }
-
- cLoop = $10; { Loop enable (for testing) }
-
-
- {----------------------------------}
- { Line Status Register (LSR) Flags }
- {----------------------------------}
-
- cDataInRcvBuff = $01; { data in receive buffer }
- cOverrunError = $02; { overrrun error }
- cParityError = $04; { parity error }
- cFramingError = $08; { framing error }
- cIncomingBreak = $10; { incoming break detected }
- cTHREmpty = $20; { Transmit holding reg is empty}
- cTSREmpty = $40; { Transmit shift reg is empty}
- cFIFORcvError = $80; { 16550 Fifo receive error }
-
- {-----------------------------------}
- { Modem Status Register (MSR) Flags }
- {-----------------------------------}
-
- cdCTS = $01; { delta-clear to send }
- cdDSR = $02; { delta-Data Set Ready }
- cdRI = $04; { delta-Ring }
- cdDCD = $08; { delta-Data Carrier Detect }
- cCTS = $10; { Clear to send }
- cDSR = $20; { Data Set Ready }
- cRI = $40; { Ring Indicator }
- cDCD = $80; { Data Carrier Detect }
-
-
-
- Type
-
- TPortSettings = RECORD
-
- BasePort : WORD;
- IRQ : BYTE;
-
- END;
-
- PPortSettings = ^TPortSettings;
-
- TUartInBuffer = Array[0..cInBuffMax] of BYTE;
-
- PUartInBuffer = ^TUartInBuffer;
-
-
- Const
-
- PortSettings : Array[0..cMaxComPort] of TPortSettings=
- ( (BasePort : $3F8; IRQ : 4),
- (BasePort : $2F8; IRQ : 3),
- (BasePort : $3E8; IRQ : 4),
- (BasePort : $2E8; IRQ : 3),
- (BasePort : $000; IRQ : 0),
- (BasePort : $000; IRQ : 0),
- (BasePort : $000; IRQ : 0),
- (BasePort : $000; IRQ : 0) );
-
- Var
-
- ExitSave : POINTER;
- OriginalVector : POINTER;
-
- UartIsOpen : BOOLEAN;
- Overflow : BOOLEAN;
-
- Base : WORD; { current baseport }
- IRQ : BYTE; { current IRQ }
-
- Buffer : TUartInBuffer;
-
- BufferHead : WORD;
- BufferTail : WORD;
-
- SaveIER : BYTE;
- SaveMCR : BYTE;
- SaveLCr : BYTE;
-
- CtsRtsOn : Boolean;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Procedure VUartBaudSet( BaudRate : LONGINT );
-
- [PARAMETERS]
-
- baudrate new baud rate to use
-
- [RETURNS]
-
- nothing.
-
- [DESCRIPTION]
-
- This function will set the baud rate of the UART to the specified
- value.
-
- THIS FUNCTION IS NOT YET IMPLEMENTED!
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- VUartBaudSet( 19200 );
-
- -*)
-
-
- Procedure VUartBaudSet( BaudRate : LONGINT );
-
- BEGIN
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Function VUartBaudGet : LONGINT;
-
- [PARAMETERS]
-
- none.
-
- [RETURNS]
-
- current Baud rate of the UART.
-
- [DESCRIPTION]
-
- This function will get the current baud rate of the UART.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- WriteLn(' Baud Rate = ', VUartBaudGet );
-
- -*)
-
-
- Function VUartBaudGet : LONGINT;
-
- Var
-
- SaveLCR : WORD;
- BRD : WORD;
-
- BEGIN
-
- {-------------------------------------}
- { get the line control register value }
- {-------------------------------------}
-
- SaveLCR := Port[ cUartLCR + Base ];
-
- {----------------------------------}
- { set the access divsor latch flag }
- {----------------------------------}
-
- Port[ cUartLCR + Base ] := SaveLCR OR cAccessDivLatch;
-
- {-------------------------------------------------------------}
- { The THR and IER regs are now the Baud Rate Divisor register }
- { so we get the baud rate divisor }
- {-------------------------------------------------------------}
-
- TCastWord( BRD ).LowByte := Port[ cUartTHR + Base ];
- TCastWord( BRD ).HighByte := Port[ cUartIER + Base ];
-
- {--------------------------------------------------------------}
- { clear the access divisor latch / set LCR back to what it was }
- {--------------------------------------------------------------}
-
- Port[ cUartLCR + Base ] := SaveLCR;
-
- {-------------------------------------------------}
- { divide the input clock by the baud rate divisor }
- { to get the baud rate }
- {-------------------------------------------------}
-
- VUartBaudGet := cUartClockFreq DIV BRD;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Function VUartLSRGet : BYTE;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- Line Status Register.
-
- [DESCRIPTION]
-
- This function will get the line-status register of the UART.
-
- Line status register flags
- --------------------------
-
- cDataInRcvBuff = $01; { data in receive buffer }
- cOverrunError = $02; { overrrun error }
- cParityError = $04; { parity error }
- cFramingError = $08; { framing error }
- cIncomingBreak = $10; { incoming break detected }
- cTHREmpty = $20; { Transmit holding reg is empty}
- cTSREmpty = $40; { Transmit shift reg is empty}
- cFIFORcvError = $80; { 16550 Fifo receive error }
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- If (VUartLSRGet AND cParityError)>0 Then
- WriteLn('Parity error!')
- Else
- WriteLn('No parity error.');
-
- -*)
-
-
- Function VUartLSRGet : BYTE;
-
- BEGIN
-
- VUartLSRGet := (Port[ Base+cUartLSR ]);
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
-
- Function VUartMSRGet : BYTE;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- Modem Status Register.
-
- [DESCRIPTION]
-
- This function will get the modem-status register of the UART.
-
- Modem status register flags
- ---------------------------
-
- cdCTS = $01; { delta-clear to send }
- cdDSR = $02; { delta-Data Set Ready }
- cdRI = $04; { delta-Ring }
- cdDCD = $08; { delta-Data Carrier Detect }
- cCTS = $10; { Clear to send }
- cDSR = $20; { Data Set Ready }
- cRI = $40; { Ring Indicator }
- cDCD = $80; { Data Carrier Detect }
-
-
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- If (VUartMSRGet AND cCTS)>0 Then
- WriteLn('Clear to send!')
- Else
- WriteLn('cant send yet....');
-
- -*)
-
-
-
- Function VUartMSRGet : BYTE;
-
- BEGIN
-
- VUartMSRGet := (Port[ Base+cUartMSR ]);
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
-
- Function VUartLCRGet : BYTE;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- Line control Register.
-
- [DESCRIPTION]
-
- This function will get the line-control register of the UART.
-
- Line-Control register flags
- ---------------------------
-
- cDataBitsMask = $01+$02; { Data bits (wordsize) mask }
- cDataBits5 = $00; { Data bits = 5 }
- cDataBits6 = $01; { Data bits = 6 }
- cDataBits7 = $02; { Data bits = 7 }
- cDataBits8 = $01+$02; { Data bits = 8 }
-
- cStopBits1 = $00; { Stop bits = 1 }
- cStopBits2 = $04; { Stop bits = 2 }
-
- cParityEnable = $08; { Enable parity }
-
- cParityEven = $10; { even parity }
-
- cStickyParity = $20; { sticky parity }
-
- cBreakOn = $40; { turn break on }
-
- cAccessDivLatch = $80; { access divisor latch }
-
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
-
- Function VUartLCRGet : BYTE;
-
- BEGIN
-
- VUartLCRGet := (Port[ Base+cUartLCR ]);
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
-
- Function VUartMCRGet : BYTE;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- Line control Register.
-
- [DESCRIPTION]
-
- This function will get the modem-control register of the UART.
-
- modem-Control register flags
- ----------------------------
-
- cDTR = $01; { Data terminal ready }
- cRTS = $02; { Ready to send }
- cOut1 = $04; { Out 1 - not used in PCs }
-
- cOut2 = $08; { Out 2 - }
- cMasterEnableInts = $08; { master enables interrupts }
-
- cLoop = $10; { Loop enable (for testing) }
-
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
-
-
-
- Function VUartMCRGet : BYTE;
-
- BEGIN
-
- VUartMCRGet := (Port[ Base+cUartMCR ]);
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Function VUartIsCarrier : BOOLEAN;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- TRUE if a carrier is present,
- FALSE if a carrier is NOT present.
-
- [DESCRIPTION]
-
- This function will return TRUE if a data carrier is present.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Function VUartIsCarrier : BOOLEAN;
-
- BEGIN
-
- VUartISCarrier := (Port[ CUartMSR + Base ] AND cDCD)>0;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
-
- (*-
-
- [FUNCTION]
-
- Procedure CommIsr; Interrupt;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- Nothing.
-
- [DESCRIPTION]
-
- This procedure is the VUartU s internal interrupt service routine.
- It should NOT be called externally. This interrupt is called any time the
- UART receives a character.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
-
- Procedure CommIsr; Interrupt;
-
- BEGIN
-
- ASM
-
- { get the incoming character from the UART }
- { and put it into our incoming char buffer }
-
- @@GetTheChar:
-
- STI
-
- MOV DX, Base
- IN AL, DX
- MOV BX, BufferHead
- MOV byte PTR Buffer[BX], AL
-
- INC BX
-
- { check to see if we are at the end of the buffer }
-
- @@CheckAtEnd:
- CMP BX, cInBuffMax
- JLE @@CheckOver
- XOR BX, BX
-
- { check to see if an overflow occurred (head=tail) }
-
- @@CheckOver:
- CMP BX, BufferTail
- JNE @@CheckNextChar
- MOV Overflow,1
- JMP @@AllDone
-
- { check to see if more characters are waiting }
-
- @@CheckNextchar:
- MOV Bufferhead, BX
- ADD DX,5
- IN AL,DX
-
- AND AL, $01
- CMP AL, $01
- JE @@GetTheChar
-
- { clean up and leave }
-
- @@AllDone:
- CLI
- MOV AL,20h
- OUT 20h, AL
-
- END;
-
- END; { CommIsr }
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
-
- (*-
-
- [FUNCTION]
-
- Procedure VUartClose;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- Nothing.
-
- [DESCRIPTION]
-
- This function is used internally.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VUartClose;
-
- BEGIN
-
- If UartIsOpen Then
- BEGIN
-
- { begin critical code }
-
- ASM CLI; END;
-
- { turn off our int in the 8259 IRQ mask register }
-
- Port[ cIntMaskReg ] := ( Port[ cIntMaskReg ] or (1 SHL IRQ) );
-
- { restore the saved UART registers }
-
- Port[ Base + cUartIER ] := SaveIER;
-
- Port[ Base + cUartMCR ] := SaveMCR;
-
- Port[ Base + cUartLCR ] := SaveLCR;
-
- { restore the orignal interrupt vector }
-
- SetIntVec( IRQ+8, OriginalVector );
-
- { end of critical code }
-
- ASM STI; END;
-
- UartIsOpen := FALSE;
-
- END;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Function VUartOpen( ComPort : BYTE;
- BaudRate : LONGINT ):BOOLEAN;
-
- [PARAMETERS]
-
- comport comport to open (1-4)
- baudrate baudrate to use
-
- [RETURNS]
-
- TRUE if the open was successfull,
- FALSE if the open was not.
-
- [DESCRIPTION]
-
- This function is used internally.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
-
- Function VUartOpen( ComPort : BYTE;
- BaudRate : LONGINT ):BOOLEAN;
-
- Var
-
- SaveIIR : BYTE;
- Is16550 : BOOLEAN;
- PortGood : BOOLEAN;
-
- BEGIN
-
- { set the buffer head and tail to nada }
-
- BufferHead := 0;
- BufferTail := 0;
-
- { clear overflow and uartisopen flag }
-
- Overflow := FALSE;
-
- UartIsOpen := FALSE;
-
- { do we know the baseport for this com-port? }
-
- If PortSettings[ Pred( ComPort ) ].BasePort <>0 Then
- BEGIN
-
- { get out baseport and irq }
-
- Base := PortSettings[ Pred( ComPort ) ].BasePort;
- IRQ := PortSettings[ Pred( ComPort ) ].IRQ;
-
- { save various UART regs }
-
- SaveIER := Port[ Base + cUartIER ];
- SaveMCR := Port[ Base + cUartMCR ];
- SaveLCR := Port[ Base + cUartLCR ];
-
- { check for the port }
-
- Port[ Base+CUartLCR ] := $75;
-
- PortGood := (Port[ Base + CUartLCR ]=$75);
-
- { set port to n,8,1 }
-
- Port[ Base+cUartLCR ] := cDataBits8;
-
-
- If PortGood Then
- BEGIN
-
- { set the baud }
-
- VUartBaudSet( BaudRate );
-
- { turn on master ints, and set RTS and DTR }
-
- Port[ Base + CUartMCR ] := cMasterEnableInts + cRTS + cDTR;
-
- { save the interrupt ID register }
-
- SaveIIR := Port[ Base + cUartIIR ];
-
- { try to enable the fifos }
-
- Port[ Base + cUartIIR ] := 1;
-
- { did the Fifo mode status flags show up? }
-
- Is16550 := ( ( Port[ Base + cUartIIR ] AND
- cFifoModeMask ) = cFifoModeFifo );
-
- { if they didnt, set IIR back to what it was }
-
- If Is16550=FALSE Then
- Port[ Base + CUartIIR ] := SaveIIR;
-
- { save the original IRQ vector off }
-
- GetIntVec( IRQ+8, OriginalVector );
-
- { setup our IRQ vector }
-
- SetIntVec( IRQ+8, @CommIsr );
-
- { beginning of critical code }
-
- ASM CLI; END;
-
- { enable our IRQ in the 8259 IRQ mask register }
-
- Port[ cIntMaskReg ] := Port[ cIntMaskReg ] AND
- ( (1 SHL IRQ) XOR $FF );
-
- { enable the 8250s receive interrupt }
-
- Port[ Base + cUartIER ] := cEnableRcvInt;
-
- { end or critical code }
-
- ASM STI; END;
-
- UartIsOpen := TRUE;
-
- END; { if portthere }
-
- END; { if we found a base port in the settings table }
-
- VUartOpen := UartIsOpen;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- Procedure ExitUnit; Far;
-
- BEGIN
-
- VUartClose;
-
- ExitProc := ExitSave;
-
- END;
-
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
-
- (*-
-
- [FUNCTION]
-
- Function VUartInit( ComPort : BYTE;
- BaudRate : LONGINT ): WORD;
-
- [PARAMETERS]
-
- comport comport to open (1-4)
- baudrate baudrate to use
-
- [RETURNS]
-
- TRUE if the open was successfull,
- FALSE if the open was not.
-
- [DESCRIPTION]
-
- This function should be called before the other VUart functions are
- used. "Comport" should be the comport (1-4) that you wish to use.
- "baudrate" is the baud rate you would like the comport to be opened
- at. This function initializes the UART and sets up the Vuart
- interrupt service routine to service incoming characters.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Function VUartInit( ComPort : BYTE;
- BaudRate : LONGINT ): WORD;
-
- BEGIN
-
- If Not UartIsOpen Then
- BEGIN
-
-
- If VUartOpen( ComPort, BaudRate ) Then
- VUartInit := 0
- ELSE
- VUartInit := 1;
-
- END; { if not UartIsOpen }
-
- END; { VUartInit }
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Function VUartIsRXReady : BOOLEAN;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- TRUE if characters are available to be read from the receive buffer,
- FALSE if no characters are available.
-
- [DESCRIPTION]
-
- This function reports on the condition of the receiver buffer. It
- will return TRUE if characters are available, and FALSE if characters
- are not available.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Function VUartIsRXReady : BOOLEAN;
-
- BEGIN
- VUartIsRXReady := (BufferHead<>BufferTail);
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Procedure VUartDeInit;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- Nothing.
-
- [DESCRIPTION]
-
- This procedure should be called when your program is done with the
- UART. This function disposes of any dynamically memory that was
- allocated by VUartOpen and restores the UART back to the state
- it was in when open called. This function also restores the
- UARTS interrupt service routine back to what it previously was.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VUartDeInit;
-
- BEGIN
-
- VUartClose;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Function VUartReadChar : CHAR;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- The new character.
-
- [DESCRIPTION]
-
- This function reads the next available character from the receive buffer.
- If no characters are available, it waits until a character is received,
- and then returns it.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Function VUartReadChar : CHAR;
-
- BEGIN
-
- { wait till something is in the buffer }
-
- While BufferTail=BufferHead DO;
-
- { read a character }
-
- VUartReadChar := char( Buffer[ BufferTail ] );
-
- { move the tail }
-
- BufferTail := ( Succ( BufferTail ) MOD cInBuffSize );
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Function VUartIsTXReady : BOOLEAN;
-
- [PARAMETERS]
-
- None.
-
- [RETURNS]
-
- TRUE if the UART is ready to write another character,
- FALSE if it is not.
-
- [DESCRIPTION]
-
- This function returns TRUE if the UART is currently ready to send
- out another character, and FALSE if it is not.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Function VUartIsTXready : BOOLEAN;
-
- Var
-
- THR : BOOLEAN;
- CTS : BOOLEAN;
- Car : BOOLEAN;
-
- BEGIN
-
- { check THR, CTS, and CAR }
-
- THR := ( (Port[ Base+cUartLSR ] and cTHREmpty) >0 );
- CTS := ( (Port[ Base+cUartMSR ] and cCTS ) >0 );
- CAR := ( (Port[ Base+CUartMSR ] and cDCD ) >0 );
-
- { if cts/rts is on and their is a carrier ... }
-
- If CtsRtsOn and CAR Then
- VUartIsTXReady := THR AND CTS
- ELSE
- VUartIsTXReady := THR;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VUartWriteChar( Ch : CHAR );
-
- [PARAMETERS]
-
- ch character to write.
-
- [RETURNS]
-
- [DESCRIPTION]
-
-
- This function writes a charcter to the UART. Before using this
- function, you should first check to make sure the UART is ready to
- send another character.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
-
- Procedure VUartWriteChar( Ch : CHAR );
-
- BEGIN
-
- { wait until output is ready }
-
- While Not VUartIsTXReady DO;
-
- { send the char }
-
- Port[ Base+cUartTHR ] := Byte(Ch);
-
- END;
-
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VUartOutFlush;
-
- [PARAMETERS]
-
- [RETURNS]
-
- [DESCRIPTION]
-
- This function insures that any characters which are buffered
- and have not yet been sent are sent.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VUartOutFlush;
-
- BEGIN
-
- { flush 16550 fifos }
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VUartOutPurge;
-
- [PARAMETERS]
-
- [RETURNS]
-
- [DESCRIPTION]
-
- This function purges any characters which are in the transmit buffer.
- Since UART currently does not implement a transmit buffer, this function
- doesn't do anything.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
-
- Procedure VUartOutPurge;
-
- BEGIN
-
- { Purge 16550 fifos }
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VUartInPurge;
-
- [PARAMETERS]
-
- [RETURNS]
-
- [DESCRIPTION]
-
- This function purges any characters that are in the receive buffer.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VUartInPurge;
-
- BEGIN
- BufferHead := 0;
- BufferTail := 0;
- OverFlow := FALSE;
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- (*-
-
- [FUNCTION]
-
- Procedure VUartBreak( DelayMS : WORD );
-
- [PARAMETERS]
-
- delayms count of milliseconds to break for.
-
- [RETURNS]
-
- [DESCRIPTION]
-
- This function sends a break signal for the specified "delayMS".
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VUartBreak( DelayMS : WORD );
-
- Var
- LCR : BYTE;
-
- BEGIN
-
- { get the current LCR }
-
- LCR := Port[ Base+cUartLCR ];
-
- { put it back with BREAK ON set }
-
- Port[ Base+cUartLCR ] := ( (LCR AND $7F) OR cBreakOn );
-
- { delay... }
-
- { Delay( DelayMS ); }
-
- { set LCR back to what it was }
-
- Port[ Base+cUartLCR ] := LCR;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VUartDTROn;
-
- [PARAMETERS]
-
- [RETURNS]
-
- [DESCRIPTION]
-
- This function turns DTR (Data Terminal Ready) on.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
-
- Procedure VUartDTROn;
-
- BEGIN
-
- Port[ Base+cUartMCR ] := cMasterEnableInts + cRTS + cDTR;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Procedure VUartDTROff;
-
- BEGIN
-
- Port[ Base+cUartMCR ] := cMasterEnableInts + cRTS;
-
- END;
-
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Procedure VUartCtsRtsSet( ON : BOOLEAN );
-
- BEGIN
- CtsRtsOn := ON;
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Procedure VUartWriteBlock( Block : POINTER;
- Count : WORD );
-
- Var
- Z : INTEGER;
-
- BEGIN
-
- For Z := 1 to Count Do
- VUartWriteChar( PCharArray( Block )^[Z] );
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- Procedure VUartReadBlock( Block : POINTER;
- Count : WORD );
-
- Var
- Z : INTEGER;
-
- BEGIN
-
- For Z := 1 to Count Do
- PCharArray( Block )^[Z] := VUartReadChar;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- Procedure UartSerDriverProc( SDP : PSerDriverPacket );
-
- Type
-
- TUartIData = RECORD
-
- ComPort : BYTE; { Communications port }
- BaudRate : LONGINT; { Bits per second rate }
- Parity : CHAR; { Parity of hardware error checking }
- DataBits : BYTE; { Number of data bits }
- StopBits : BYTE; { Number of stop bits }
- PortStat : WORD; { Condition of UART. LoByte=MSR,HiByte=LSR }
-
- END;
-
- PUartIdata = ^TUartIdata;
-
- Var
-
- IData : PUartIData;
-
- BEGIN
-
- IData := SDP^.IData;
-
- If SDP^.Status = 0 Then
- BEGIN
-
- Case SDP^.Func of
-
- {--------}
-
- SDFDriverNew:
- BEGIN
-
- IF @SDP^.SerDriverProc = @UartSerDriverProc Then
- BEGIN
-
- New( IData );
-
- FillChar( IData^, SizeOf( TUartIData), 0 );
-
- {--------------------------}
- { build instance data here }
- {--------------------------}
-
- IData^.ComPort := Pred( SDP^.DriverInfo1 );
-
- {--------------------------}
-
- SDP^.IData := IData;
-
- SDP^.Error := 0;
-
- END;
-
- END; { Case SDF_DriverNew }
-
- {--------}
-
- SDFDriverOff:
- BEGIN
- END;
-
- {--------}
-
- SDFDriverOn:
- BEGIN
- END;
-
- {--------}
-
- SDFDriverDispose:
- BEGIN
-
- {--------------------------------}
- { Resolve any instance data here }
- {--------------------------------}
-
-
- {---------------------------}
- { Dispose all instance data }
- {---------------------------}
-
- If SDP^.IData <> NIL Then
- BEGIN
-
- Dispose( SDP^.IData );
- SDP^.IData := NIL;
-
- END;
-
- END;
-
- {--------}
-
- SDFActivate:
- BEGIN
-
- SDP^.Error := 0;
-
- If VUartInit( IData^.ComPort,
- SDP^.CommParam^.BaudRate )=0 Then
- BEGIN
-
-
- SDP^.Error := 0;
-
- END
- ELSE
- BEGIN
-
- SDP^.Error := $FFFF0000;
-
- END;
-
- END;
-
- {--------}
-
- SDFDeActivate:
- BEGIN
-
- VUartDeInit;
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- SDFSetCommParam:
- BEGIN
-
- (*
- IData^.BaudRate := SDP^.CommParam^.BaudRate;
- IData^.Parity := SDP^.CommParam^.Parity;
- IData^.DataBits := SDP^.CommParam^.DataBits;
- IData^.StopBits := SDP^.CommParam^.StopBits;
- *)
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- SDFGetCommParam:
- BEGIN
-
- SDP^.CommParam^.BaudRate := VUartBaudGet;
- SDP^.CommParam^.Parity := 'N';
- SDP^.CommParam^.DataBits := 8;
- SDP^.CommParam^.StopBits := 1;
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- SDFGetFlowConType:
- BEGIN
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- SDFSetFlowConType:
- BEGIN
-
- SDP^.Error := $FFFF0000;
-
- END;
-
- {--------}
-
- SDFTurnSendOnOff:
- BEGIN
-
- SDP^.Error := $FFFF0000;
-
- END;
-
- {--------}
-
- SDFTurnReceiveOnOff:
- BEGIN
-
- SDP^.Error := $FFFF0000;
-
- END;
-
-
- {--------}
-
- sdfGetFlowConChars:
- BEGIN
-
- SDP^.Error := $FFFF0000;
-
- END;
-
- {--------}
-
- sdfSetFlowConChars:
- BEGIN
-
- SDP^.Error := $FFFF0000;
-
- END;
-
- {--------}
-
-
- {--------}
- {--------}
-
- sdfGetLineControl:
- BEGIN
-
- SDP^.Val := VUartLCRGet;
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- sdfGetLineStatus:
- BEGIN
-
- SDP^.Val := VUartLSRGet;
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- sdfGetModemControl:
- BEGIN
-
- SDP^.Val := VUartMCRGet;
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- sdfGetModemStatus:
- BEGIN
-
- SDP^.Val := VUartMSRGet;
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- sdfGetBothStatus:
- BEGIN
-
- { msr in lower, lsr in higher }
-
- SDP^.Status := (Word(VUartLSRGet) SHL 8) +
- ( (VuartMSRGet) );
-
-
- SDP^.Status := ( SDP^.Status AND ($FFFF-$0100-$2000) );
-
- If VUartIsRXReady Then
- Inc( SDP^.Status, $0100 );
-
- If VuartIsTXReady Then
- Inc( SDP^.Status, $2000 );
-
-
-
- (*
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
-
- 1 2 4 5 1 3 6 1 2 5 1 2 4 8
- 6 2 4 2 5 1 0 0 0 1
- 8 6 2 2 4 9 9
- 4 8 6 2
-
- VUartIsRXReady := (BufferHead<>BufferTail);
- sbf_LSRRcvReady = 8; { Received data ready }
-
- $0100
-
-
- vuartistxready
- sbf_LSRXhReady = 13; { Transmit hold register empty }
-
- $2000
-
- *)
-
-
- END;
-
-
-
-
- {--------}
-
- {--------}
- {--------}
- {--------}
-
- {--------}
-
- SDFDTROnOff:
- BEGIN
-
- If SDP^.OnOff Then
- VUartDTROn
- ELSE
- VUartDTROff;
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- SDFBreakOnOff:
- BEGIN
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- SDFRTSOnOff:
- BEGIN
- (*
- If SDP^.OnOff Then
- VUartRTSOn
- ELSE
- VUartRTSOff;
- *)
- SDP^.Error := 0;
-
- END;
-
- {--------}
- {--------}
- {--------}
-
-
-
- SDFFlushOutBuff:
- BEGIN
-
- VUartOutFlush;
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- SDFPurgeOutBuff:
- BEGIN
-
- VUartOutPurge;
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- SDFPurgeInBuff:
- BEGIN
-
- VUartInPurge;
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- sdfGetOutBuffInfo:
- BEGIN
-
-
- { we can only hold 1 outgoing char }
-
- SDP^.BuffInfo.Size := 1;
-
- { is the output ready? }
-
- If VUartisTXReady Then
- BEGIN
- SDP^.BuffInfo.Used := 0;
- SDP^.BuffInfo.Free := 1;
- END
- ELSE
- BEGIN
- SDP^.BuffInfo.Used := 1;
- SDP^.BuffInfo.Free := 0;
- END;
-
- SDP^.BuffInfo.Changeable := FALSE;
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- sdfSetOutBuffInfo:
- BEGIN
-
-
- SDP^.Error := $FFFF0000;
-
- END;
-
- {--------}
-
- sdfGetInBuffInfo:
- BEGIN
-
- SDP^.BuffInfo.Size := SizeOf( Buffer );
-
- ASM CLI; END;
-
- If BufferTail<=BufferHead Then
- BEGIN
-
- SDP^.BuffInfo.Used := BufferHead-BufferTail;
- SDP^.BuffInfo.Free := SizeOf( Buffer ) - SDP^.BuffInfo.Used;
-
- END
- ELSE
- BEGIN
-
- SDP^.BuffInfo.Used := (Sizeof( Buffer ) - Succ(BufferTail)) +
- (Succ(BufferHead) );
-
- SDP^.BuffInfo.Free := SizeOf( Buffer ) - SDP^.BuffInfo.Used;
-
- END;
-
- ASM STI; END;
-
- SDP^.BuffInfo.Changeable := FALSE;
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- sdfSetInBuffInfo:
- BEGIN
-
- SDP^.Error := $FFFF0000;
-
- END;
-
- {--------}
- {--------}
- {--------}
-
-
-
- SDFEventProcNew:
- BEGIN
- END;
-
- {--------}
-
- SDFEventProcOff:
- BEGIN
- END;
-
- {--------}
-
- SDFEventProcOn:
- BEGIN
- END;
-
- {--------}
-
- SDFEventProcDispose:
- BEGIN
- END;
-
- {--------}
-
- sdfEventProcMaskSet:
- BEGIN
-
- SDP^.Error := $FFFF0000;
-
- END;
-
- {--------}
- {--------}
- {--------}
-
-
- SDFWriteCh:
- BEGIN
-
- VUartWriteChar( SDP^.CH );
-
- SDP^.Error := 0;
-
-
- END;
-
- {--------}
-
- SDFWriteBlock:
- BEGIN
-
- VUartWriteBlock( SDP^.Buf,
- SDP^.Count );
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- SDFReadCh:
- BEGIN
-
- SDP^.Error := 0;
-
- SDP^.CH := VUartReadChar;
-
- END;
-
- {--------}
-
- SDFReadBlock:
- BEGIN
-
- VUartReadBlock( SDP^.Buf,
- SDP^.Count );
-
- SDP^.Error := 0;
-
- END;
-
- {--------}
-
- sdfPeekCh:
- BEGIN
-
- SDP^.Error := $FFFF0000;
-
- END;
-
- {--------}
-
- End;
-
- END;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
- {────────────────────────────────────────────────────────────────────────────}
- {────────────────────────────────────────────────────────────────────────────}
-
-
- BEGIN
-
- ExitSave := ExitProc;
- ExitProc := @ExitUnit;
- UartIsOpen := FALSE;
- Overflow := FALSE;
- CtsRtsOn := TRUE;
-
- END.
-
-
-