Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {$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]<RcvdBS[Com1]
- THEN inc(eoRcvd[Com1])
- ELSE eoRcvd[Com1] := 1;
- { cli;}
- Port[eoi8259] := EOI;
- END; {PROC iHandler1}
- PROCEDURE iHandler2(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP : word);
- Interrupt;
- BEGIN
- { sti;}
- Rcvd[Com2]^[eoRcvd[Com2]] := Port[Data[Com2]];
- IF eoRcvd[Com2]<RcvdBS[Com2]
- THEN inc(eoRcvd[Com2])
- ELSE eoRcvd[Com2] := 1;
- { cli;}
- Port[eoi8259] := EOI;
- END; {PROC iHandler2}
- PROCEDURE DTR(Com:ComPorts; State:Boolean);
- VAR
- onOff,pval : Byte;
- BEGIN
- pval := Port[ModemCtrl[com]];
- CASE InverseDTR xor state OF
- False : pval := pval and not _DTR_;
- True : pval := pval or _DTR_;
- END;
- Port[ModemCtrl[com]] := pval;
- END; {PROC DTR}
- PROCEDURE RTS(Com:ComPorts; State:Boolean);
- VAR
- pval : Byte;
- BEGIN
- pval := Port[ModemCtrl[com]];
- CASE InverseRTS xor state OF
- False : pval := pval and not _RTS_;
- True : pval := pval or _RTS_;
- END;
- Port[ModemCtrl[com]] := pval;
- END; {PROC RTS}
- PROCEDURE cBreak(Com:ComPorts);
- VAR
- asBefore : byte;
- BEGIN
- IF Status[Com]=Open THEN
- BEGIN
- asbefore := port[LineCtrl[Com]]; delay(10);
- port[LineCtrl[Com]] := asBefore or GenerateBreak;
- delay(200);
- port[LineCtrl[Com]] := asBefore;
- ErrorCom := NoError;
- END
- ELSE ErrorCom := NotOpen;
- END; {PROC cBreak}
- PROCEDURE cProtocol(Com : ComPorts; speed : ComSpeed;
- databits : ComDbits; parity : ComParity;
- stopbits : ComSbits);
- VAR
- rate : word;
- pval : byte;
- BEGIN
- IF Status[Com]=Open THEN
- BEGIN
- cli;
- rate := 115200 div speed;
- pval := port[LineCtrl[Com]]; delay(10);
- port[LineCtrl[Com]] := pval or DivisorLatch; delay(10);
- port[Data[Com]] := lo(rate); delay(10);
- port[iEnable[Com]] := hi(rate); delay(10);
- pval := port[LineCtrl[Com]]; delay(10);
- port[LineCtrl[Com]] := pval xor DivisorLatch; delay(10);
- port[LineCtrl[Com]] := (databits-5)
- +((stopBits-1) shl 2)
- +(ord(parity) shl 3);
- sti;
- LFcommSpeed[com] := Speed;
- LFcommDbits[com] := Databits;
- LFcommSbits[com] := StopBits;
- LFcommParity[com] := Parity;
- ErrorCom := NoError;
- END
- ELSE ErrorCom := NotOpen;
- END; {PROC cProtocol}
- PROCEDURE cOpen(Com : ComPorts; RBsize : Word;
- speed : ComSpeed; databits : ComDbits;
- parity : ComParity; stopbits : ComSbits);
- VAR
- pval : byte;
- BEGIN
- IF Status[Com]=Closed THEN
- BEGIN
- CASE Com OF
- Com1 : SetIntVec(iComNo[Com1],@iHandler1);
- Com2 : SetIntVec(iComNo[Com2],@iHandler2);
- END;
- RcvdBS[com] := RBSize; GetMem(rcvd[com],RcvdBS[com]);
- Status[Com] := Open;
- cProtocol(Com,speed,databits,parity,stopbits);
- cli;
- pval := port[imr8259]; delay(10);
- port[imr8259] := pval and IrqCom[Com]; delay(10);
- pval := port[LineCtrl[Com]]; delay(10);
- port[LineCtrl[Com]] := pval and $7F; delay(10);
- port[iEnable[Com]] := DataReceived; delay(10);
- pval := port[ModemCtrl[Com]]; delay(10);
- Port[ModemCtrl[Com]] := pval OR (Out2);
- pval := Port[LineStat[Com]];
- ResetRB(Com);
- sti;
- ErrorCom := NoError;
- DTR(Com,True);
- END
- ELSE
- BEGIN
- cProtocol(Com,speed,databits,parity,stopbits);
- ErrorCom := AlreadyOpen;
- END;
- END; {PROC cOpen}
- PROCEDURE cClose(Com:ComPorts);
- BEGIN
- IF Status[Com]=Open THEN
- BEGIN
- cli;
- port[imr8259] := port[imr8259] or $18;
- port[LineCtrl[Com]] := port[LineCtrl[Com]] and $7F;
- port[iEnable[Com]] := InterruptsOff;
- port[ModemCtrl[Com]] := 0;
- sti;
- SetIntVec(iComNo[Com],OldVec[Com]);
- FreeMem(Rcvd[com],RcvdBS[com]); RcvdBS[com] := 1;
- Status[Com] := Closed;
- ErrorCom := NoError;
- END ELSE ErrorCom := AlreadyClosed;
- END; {PROC cClose}
- PROCEDURE ResetRB(Com:ComPorts);
- BEGIN
- stRcvd[Com] := 1;
- eoRcvd[Com] := 1;
- END; {PROC ResetRB}
- FUNCTION Received(Com:ComPorts):Boolean;
- BEGIN
- IF Status[Com]=Open THEN
- BEGIN
- Received := stRcvd[Com]<>eoRcvd[Com];
- ErrorCom := NoError;
- END
- ELSE
- BEGIN
- Received := False;
- ErrorCom := NotOpen;
- END;
- END; {FUNC Received}
- FUNCTION RBused(Com:ComPorts):Word;
- BEGIN
- IF eoRcvd[Com]<stRcvd[Com] THEN
- RBused := RcvdBS[Com]-stRcvd[Com]+eoRcvd[Com]
- ELSE RBused := eoRcvd[Com]-stRcvd[Com];
- END; {FUNC RBused}
- FUNCTION cRead(Com:ComPorts):Char;
- BEGIN
- IF Status[Com]=Open THEN
- BEGIN
- CLI;
- cRead := chr(Rcvd[Com]^[stRcvd[Com]]);
- IF stRcvd[Com]<RcvdBS[Com] THEN inc(stRcvd[Com])
- ELSE stRcvd[Com] := 1;
- STI;
- ErrorCom := NoError;
- END
- ELSE
- BEGIN
- cRead := #0;
- ErrorCom := NotOpen;
- END;
- END; {FUNC cRead}
- PROCEDURE cWrite(Com:ComPorts; msg:String);
- VAR
- n : byte;
- HoldOK,DsrCtsOK : Boolean;
- BEGIN
- IF Status[Com]=Open THEN
- BEGIN
- RTS(Com,True);
- FOR n := 1 to length(msg) DO
- BEGIN
- REPEAT
- HoldOK := Port[LineStat[Com]] and xmitHoldEmpty = xmitHoldEmpty;
- {DsrCtsOK := Port[ModemStat[Com]] and (_DSR_+_CTS_) = _DSR_+_CTS_;}
- UNTIL HoldOK { and DsrCtsOK};
- Port[Data[Com]] := byte(msg[n]);
- END;
- RTS(Com,False);
- ErrorCom := NoError;
- END
- ELSE ErrorCom := NotOpen;
- END; {PROC cWrite}
- FUNCTION ComError;
- BEGIN
- ComError := ErrorCom;
- ErrorCom := 0;
- END; {FUNC ComError}
- BEGIN {Initialisation part of Unit LFcomm}
- Units.Enter(LFcommMsg,MemAvail,CSeg);
- InverseRTS := False;
- InverseDTR := False;
- FOR cno := Com1 to Com2 DO
- BEGIN
- GetIntVec(iComNo[cno],OldVec[cno]);
- Status[cno] := Closed;
- RcvdBS[cno] := 1;
- END;
- ErrorCom := 0;
- END.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement