{ Example of bit twiddling in pre-OOP Turbo Pascal Note the ALL CAPS keywords - from before syntax highlighting. Took me a while to unlearn that :P } {$I CODEDEFS.PAS} {Include code generation definitions} {$O-} {Overlaying not allowed} UNIT LFcomm; {.4 (c) 19880926 Lars Fosdal } { This TP4 Unit supports Com1 and Com2 with a few simple routines... ...the receive routine is interruptdriven and buffers input. Related info can be found in : "Product Handbook", Western Digital '81 Section 1 : "WD8250 Asynchronous Communications Element" "Intel Microsystems Components Handbook", Intel '86 Pages 2-95 ..2-132 : "8259A Programmable Interrupt Controller" Pages 2-144..2-181 : Application Note "Using the 8259A" "Advanced Techniques in Turbo Pascal", Charles C.Edwards, SYBEX '87 Pages 220..233 : "Data Communications". BYTE magazine Vol.12/#12 : "Inside the IBM PC's" Pages 173..180 : "IBM PC Family BIOS Comparison" by Jon Shiell. "Advanced MSDOS", Ray Duncan, MicroSoft Press '86 Reading the whole book is recommended !!! and in your TP4,TP5,TP55,TP60 Owner's handbooks. } INTERFACE USES Dos,Crt,LFsystem; CONST Com1 = 1; Com2 = 2; Ready = true; NotReady = false; NoError = 0; AlreadyOpen = 1; AlreadyClosed= 2; NotOpen = 3; TYPE ComSpeed = 110..38400; ComDbits = 7..8; ComSbits = 1..2; ComPorts = 1..2; ComParity = (pNone,pOdd,pMark,pEven,pSpace); VAR LFcommSpeed : ARRAY[ComPorts] OF ComSpeed; LFcommDbits : ARRAY[ComPorts] OF ComDbits; LFcommSbits : ARRAY[ComPorts] OF ComSbits; LFcommParity : ARRAY[ComPorts] OF ComParity; InverseRTS, InverseDTR : Boolean; FUNCTION ComError:word; FUNCTION Received(Com:ComPorts):boolean; FUNCTION cRead(Com:ComPorts):char; FUNCTION RBused(Com:ComPorts):Word; PROCEDURE ResetRB(Com:ComPorts); PROCEDURE cProtocol(Com : ComPorts; speed : ComSpeed; databits : ComDbits; parity : ComParity; stopbits:ComSbits); PROCEDURE cOpen(Com : ComPorts; RBsize : Word; speed : ComSpeed; databits : ComDbits; parity : ComParity; stopbits : ComSbits); PROCEDURE DTR(Com:ComPorts; state:boolean); PROCEDURE RTS(Com:ComPorts; state:boolean); PROCEDURE cBreak(Com:ComPorts); PROCEDURE cWrite(Com:ComPorts; msg:String); PROCEDURE cClose(Com:ComPorts); IMPLEMENTATION CONST LFcommMsg = ' LFcomm.4 19880926 Lars Fosdal '; {--Interrupt consts-} imr8259 = $21; eoi8259 = $20; EOI = $20; iComNo : ARRAY[ComPorts] OF byte =($0C,$0B); irqCom : ARRAY[ComPorts] OF byte =($EF,$F7); {---UART registers-} Data : ARRAY[ComPorts] OF word = ($3F8,$2F8); iEnable : ARRAY[ComPorts] OF word = ($3F9,$2F9); iIdentify : ARRAY[ComPorts] OF word = ($3FA,$2FA); LineCtrl : ARRAY[ComPorts] OF word = ($3FB,$2FB); LineStat : ARRAY[ComPorts] OF word = ($3FD,$2FD); ModemCtrl : ARRAY[ComPorts] OF word = ($3FC,$2FC); ModemStat : ARRAY[ComPorts] OF word = ($3FE,$2FE); Reserved : ARRAY[ComPorts] OF word = ($3FF,$2FF); {--Interupt Enable-} InterruptsOff = $00; DataReceived = $01; ReadyToSend = $02; LineStatChng = $04; ModemStatChng = $08; {Bits 4..7 not used} {---Line Status----} DataRecvReady = $01; OverRunError = $02; ParityError = $04; FramingError = $08; BreakDetected = $10; XmitHoldEmpty = $20; XmitShftEmpty = $40; {bit 7 always zero } {---Line Control---} {Bits 0..1 : #DataBits : 0=5, 1=6, 2=7, 3=8 } {Bit 2 : #StopBits : 0=1, 1=2 } {Bit 3 : Enable Parity} {Bit 4 : 0=Odd/Space, 1=Even/Mark} {Bit 5 : Select Mark/Space Parity} GenerateBreak = $40; DivisorLatch = $80; {---Modem Status---} deltaCTS = $01; deltaDSR = $02; TrailEdgeRI = $04; deltaCD = $08; _CTS_ = $10; _DSR_ = $20; _RI_ = $40; _CD_ = $80; {---Modem Control--} _DTR_ = $01; _RTS_ = $02; Out1 = $04; Out2 = $08; LoopBackTest = $10; {bits 5..7 not used} TYPE ComBuffer = ARRAY[1..65535] OF byte; ComStat = (Closed,Open); VAR rcvdBS, stRcvd, eoRcvd : Array[ComPorts] OF word; Rcvd : Array[ComPorts] OF ^ComBuffer; OldVec : Array[ComPorts] OF Pointer; Status : ARRAY[ComPorts] OF ComStat; cno : Comports; ErrorCom : Byte; PROCEDURE iHandler1(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP : word); Interrupt; BEGIN { sti;} Rcvd[Com1]^[eoRcvd[Com1]] := Port[Data[Com1]]; IF eoRcvd[Com1]eoRcvd[Com]; ErrorCom := NoError; END ELSE BEGIN Received := False; ErrorCom := NotOpen; END; END; {FUNC Received} FUNCTION RBused(Com:ComPorts):Word; BEGIN IF eoRcvd[Com]