Advertisement
LarsFosdal

LFComm.pas - DOS Serial comms for TP4 - 1988

Jul 20th, 2016
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 10.11 KB | None | 0 0
  1. {$I CODEDEFS.PAS} {Include code generation definitions}
  2. {$O-} {Overlaying not allowed}
  3.  
  4. UNIT LFcomm; {.4 (c) 19880926 Lars Fosdal }
  5.  
  6. { This TP4 Unit supports Com1 and Com2 with a few simple routines...
  7.   ...the receive routine is interruptdriven and buffers input.
  8.  
  9.   Related info can be found in :
  10.  
  11.     "Product Handbook", Western Digital '81
  12.       Section 1  : "WD8250 Asynchronous Communications Element"
  13.  
  14.     "Intel Microsystems Components Handbook", Intel '86
  15.       Pages 2-95 ..2-132 : "8259A Programmable Interrupt Controller"
  16.       Pages 2-144..2-181 : Application Note "Using the 8259A"
  17.  
  18.     "Advanced Techniques in Turbo Pascal", Charles C.Edwards, SYBEX '87
  19.       Pages 220..233 : "Data Communications".
  20.  
  21.     BYTE magazine Vol.12/#12 : "Inside the IBM PC's"
  22.       Pages 173..180 : "IBM PC Family BIOS Comparison" by Jon Shiell.
  23.  
  24.     "Advanced MSDOS", Ray Duncan, MicroSoft Press '86
  25.       Reading the whole book is recommended !!!
  26.  
  27.     and in your TP4,TP5,TP55,TP60 Owner's handbooks.
  28. }
  29.  
  30. INTERFACE USES Dos,Crt,LFsystem;
  31.  
  32. CONST
  33.   Com1         = 1;
  34.   Com2         = 2;
  35.   Ready        = true;
  36.   NotReady     = false;
  37.   NoError      = 0;
  38.   AlreadyOpen  = 1;
  39.   AlreadyClosed= 2;
  40.   NotOpen      = 3;
  41.  
  42. TYPE
  43.   ComSpeed  = 110..38400;
  44.   ComDbits  = 7..8;
  45.   ComSbits  = 1..2;
  46.   ComPorts  = 1..2;
  47.   ComParity = (pNone,pOdd,pMark,pEven,pSpace);
  48.  
  49. VAR
  50.   LFcommSpeed  : ARRAY[ComPorts] OF ComSpeed;
  51.   LFcommDbits  : ARRAY[ComPorts] OF ComDbits;
  52.   LFcommSbits  : ARRAY[ComPorts] OF ComSbits;
  53.   LFcommParity : ARRAY[ComPorts] OF ComParity;
  54.   InverseRTS,
  55.   InverseDTR   : Boolean;
  56.  
  57. FUNCTION ComError:word;
  58. FUNCTION Received(Com:ComPorts):boolean;
  59. FUNCTION cRead(Com:ComPorts):char;
  60. FUNCTION RBused(Com:ComPorts):Word;
  61. PROCEDURE ResetRB(Com:ComPorts);
  62. PROCEDURE cProtocol(Com : ComPorts;  speed : ComSpeed;
  63.                     databits : ComDbits;  parity : ComParity;
  64.                     stopbits:ComSbits);
  65. PROCEDURE cOpen(Com : ComPorts;  RBsize : Word;
  66.                 speed : ComSpeed;  databits : ComDbits;
  67.                 parity : ComParity;  stopbits : ComSbits);
  68. PROCEDURE DTR(Com:ComPorts; state:boolean);
  69. PROCEDURE RTS(Com:ComPorts; state:boolean);
  70. PROCEDURE cBreak(Com:ComPorts);
  71. PROCEDURE cWrite(Com:ComPorts; msg:String);
  72. PROCEDURE cClose(Com:ComPorts);
  73.  
  74.  
  75. IMPLEMENTATION
  76.  
  77.  
  78. CONST
  79.   LFcommMsg = ' LFcomm.4 19880926 Lars Fosdal ';
  80.  
  81.   {--Interrupt consts-}
  82.   imr8259       = $21;
  83.   eoi8259       = $20;
  84.   EOI           = $20;
  85.   iComNo    : ARRAY[ComPorts] OF byte =($0C,$0B);
  86.   irqCom    : ARRAY[ComPorts] OF byte =($EF,$F7);
  87.  
  88.   {---UART registers-}
  89.   Data      : ARRAY[ComPorts] OF word = ($3F8,$2F8);
  90.   iEnable   : ARRAY[ComPorts] OF word = ($3F9,$2F9);
  91.   iIdentify : ARRAY[ComPorts] OF word = ($3FA,$2FA);
  92.   LineCtrl  : ARRAY[ComPorts] OF word = ($3FB,$2FB);
  93.   LineStat  : ARRAY[ComPorts] OF word = ($3FD,$2FD);
  94.   ModemCtrl : ARRAY[ComPorts] OF word = ($3FC,$2FC);
  95.   ModemStat : ARRAY[ComPorts] OF word = ($3FE,$2FE);
  96.   Reserved  : ARRAY[ComPorts] OF word = ($3FF,$2FF);
  97.  
  98.   {--Interupt Enable-}
  99.   InterruptsOff = $00;
  100.   DataReceived  = $01;
  101.   ReadyToSend   = $02;
  102.   LineStatChng  = $04;
  103.   ModemStatChng = $08;
  104.   {Bits 4..7 not used}
  105.  
  106.   {---Line Status----}
  107.   DataRecvReady = $01;
  108.   OverRunError  = $02;
  109.   ParityError   = $04;
  110.   FramingError  = $08;
  111.   BreakDetected = $10;
  112.   XmitHoldEmpty = $20;
  113.   XmitShftEmpty = $40;
  114.   {bit 7 always zero }
  115.  
  116.   {---Line Control---}
  117.   {Bits 0..1 : #DataBits : 0=5, 1=6, 2=7, 3=8 }
  118.   {Bit 2     : #StopBits : 0=1, 1=2 }
  119.   {Bit 3     : Enable Parity}
  120.   {Bit 4     : 0=Odd/Space, 1=Even/Mark}
  121.   {Bit 5     : Select Mark/Space Parity}
  122.   GenerateBreak = $40;
  123.   DivisorLatch  = $80;
  124.  
  125.   {---Modem Status---}
  126.   deltaCTS      = $01;
  127.   deltaDSR      = $02;
  128.   TrailEdgeRI   = $04;
  129.   deltaCD       = $08;
  130.   _CTS_         = $10;
  131.   _DSR_         = $20;
  132.   _RI_          = $40;
  133.   _CD_          = $80;
  134.  
  135.   {---Modem Control--}
  136.   _DTR_         = $01;
  137.   _RTS_         = $02;
  138.   Out1          = $04;
  139.   Out2          = $08;
  140.   LoopBackTest  = $10;
  141.   {bits 5..7 not used}
  142.  
  143. TYPE
  144.   ComBuffer = ARRAY[1..65535] OF byte;
  145.   ComStat   = (Closed,Open);
  146. VAR
  147.   rcvdBS,
  148.   stRcvd,
  149.   eoRcvd    : Array[ComPorts] OF word;
  150.   Rcvd      : Array[ComPorts] OF ^ComBuffer;
  151.   OldVec    : Array[ComPorts] OF Pointer;
  152.   Status    : ARRAY[ComPorts] OF ComStat;
  153.   cno       : Comports;
  154.   ErrorCom  : Byte;
  155.  
  156. PROCEDURE iHandler1(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP : word);
  157.  Interrupt;
  158. BEGIN
  159. { sti;}
  160.   Rcvd[Com1]^[eoRcvd[Com1]] := Port[Data[Com1]];
  161.   IF eoRcvd[Com1]<RcvdBS[Com1]
  162.   THEN inc(eoRcvd[Com1])
  163.   ELSE eoRcvd[Com1] := 1;
  164. { cli;}
  165.   Port[eoi8259] := EOI;
  166. END; {PROC iHandler1}
  167.  
  168. PROCEDURE iHandler2(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP : word);
  169.  Interrupt;
  170. BEGIN
  171. { sti;}
  172.   Rcvd[Com2]^[eoRcvd[Com2]] := Port[Data[Com2]];
  173.   IF eoRcvd[Com2]<RcvdBS[Com2]
  174.   THEN inc(eoRcvd[Com2])
  175.   ELSE eoRcvd[Com2] := 1;
  176. { cli;}
  177.   Port[eoi8259] := EOI;
  178. END; {PROC iHandler2}
  179.  
  180. PROCEDURE DTR(Com:ComPorts; State:Boolean);
  181. VAR
  182.   onOff,pval : Byte;
  183. BEGIN
  184.   pval := Port[ModemCtrl[com]];
  185.   CASE InverseDTR xor state OF
  186.     False : pval := pval and not _DTR_;
  187.     True  : pval := pval or _DTR_;
  188.   END;
  189.   Port[ModemCtrl[com]] := pval;
  190. END; {PROC DTR}
  191.  
  192. PROCEDURE RTS(Com:ComPorts; State:Boolean);
  193. VAR
  194.  pval : Byte;
  195. BEGIN
  196.   pval := Port[ModemCtrl[com]];
  197.   CASE InverseRTS xor state OF
  198.     False : pval := pval and not _RTS_;
  199.     True  : pval := pval or _RTS_;
  200.   END;
  201.   Port[ModemCtrl[com]] := pval;
  202. END; {PROC RTS}
  203.  
  204. PROCEDURE cBreak(Com:ComPorts);
  205. VAR
  206.   asBefore : byte;
  207. BEGIN
  208.   IF Status[Com]=Open THEN
  209.   BEGIN
  210.     asbefore := port[LineCtrl[Com]]; delay(10);
  211.     port[LineCtrl[Com]] := asBefore or GenerateBreak;
  212.     delay(200);
  213.     port[LineCtrl[Com]] := asBefore;
  214.     ErrorCom := NoError;
  215.   END
  216.    ELSE ErrorCom := NotOpen;
  217. END; {PROC cBreak}
  218.  
  219.  
  220. PROCEDURE cProtocol(Com : ComPorts;  speed : ComSpeed;
  221.                     databits : ComDbits;  parity : ComParity;
  222.                     stopbits : ComSbits);
  223. VAR
  224.   rate : word;
  225.   pval : byte;
  226. BEGIN
  227.   IF Status[Com]=Open THEN
  228.   BEGIN
  229.     cli;
  230.     rate := 115200 div speed;
  231.     pval := port[LineCtrl[Com]]; delay(10);
  232.     port[LineCtrl[Com]] := pval or DivisorLatch; delay(10);
  233.     port[Data[Com]]     := lo(rate); delay(10);
  234.     port[iEnable[Com]]  := hi(rate); delay(10);
  235.     pval := port[LineCtrl[Com]]; delay(10);
  236.     port[LineCtrl[Com]] := pval xor DivisorLatch; delay(10);
  237.     port[LineCtrl[Com]] := (databits-5)
  238.                               +((stopBits-1) shl 2)
  239.                               +(ord(parity) shl 3);
  240.     sti;
  241.     LFcommSpeed[com] := Speed;
  242.     LFcommDbits[com] := Databits;
  243.     LFcommSbits[com] := StopBits;
  244.     LFcommParity[com] := Parity;
  245.     ErrorCom := NoError;
  246.   END
  247.    ELSE ErrorCom := NotOpen;
  248. END; {PROC cProtocol}
  249.  
  250. PROCEDURE cOpen(Com : ComPorts;  RBsize : Word;
  251.                 speed : ComSpeed;  databits : ComDbits;
  252.                 parity : ComParity;  stopbits : ComSbits);
  253. VAR
  254.   pval : byte;
  255. BEGIN
  256.   IF Status[Com]=Closed THEN
  257.   BEGIN
  258.     CASE Com OF
  259.       Com1 : SetIntVec(iComNo[Com1],@iHandler1);
  260.       Com2 : SetIntVec(iComNo[Com2],@iHandler2);
  261.     END;
  262.     RcvdBS[com] := RBSize; GetMem(rcvd[com],RcvdBS[com]);
  263.     Status[Com] := Open;
  264.     cProtocol(Com,speed,databits,parity,stopbits);
  265.     cli;
  266.     pval := port[imr8259]; delay(10);
  267.     port[imr8259] := pval and IrqCom[Com]; delay(10);
  268.     pval := port[LineCtrl[Com]]; delay(10);
  269.     port[LineCtrl[Com]] := pval and $7F; delay(10);
  270.     port[iEnable[Com]] := DataReceived; delay(10);
  271.     pval := port[ModemCtrl[Com]]; delay(10);
  272.     Port[ModemCtrl[Com]] := pval OR (Out2);
  273.     pval := Port[LineStat[Com]];
  274.     ResetRB(Com);
  275.     sti;
  276.     ErrorCom := NoError;
  277.     DTR(Com,True);
  278.   END
  279.    ELSE
  280.   BEGIN
  281.     cProtocol(Com,speed,databits,parity,stopbits);
  282.     ErrorCom := AlreadyOpen;
  283.   END;
  284. END; {PROC cOpen}
  285.  
  286. PROCEDURE cClose(Com:ComPorts);
  287. BEGIN
  288.   IF Status[Com]=Open THEN
  289.   BEGIN
  290.     cli;
  291.     port[imr8259] := port[imr8259] or $18;
  292.     port[LineCtrl[Com]] := port[LineCtrl[Com]] and $7F;
  293.     port[iEnable[Com]] := InterruptsOff;
  294.     port[ModemCtrl[Com]] := 0;
  295.     sti;
  296.     SetIntVec(iComNo[Com],OldVec[Com]);
  297.     FreeMem(Rcvd[com],RcvdBS[com]); RcvdBS[com] := 1;
  298.     Status[Com] := Closed;
  299.     ErrorCom := NoError;
  300.   END ELSE ErrorCom := AlreadyClosed;
  301. END; {PROC cClose}
  302.  
  303. PROCEDURE ResetRB(Com:ComPorts);
  304. BEGIN
  305.   stRcvd[Com] := 1;
  306.   eoRcvd[Com] := 1;
  307. END; {PROC ResetRB}
  308.  
  309. FUNCTION Received(Com:ComPorts):Boolean;
  310. BEGIN
  311.   IF Status[Com]=Open THEN
  312.   BEGIN
  313.     Received := stRcvd[Com]<>eoRcvd[Com];
  314.     ErrorCom := NoError;
  315.   END
  316.    ELSE
  317.   BEGIN
  318.     Received := False;
  319.     ErrorCom := NotOpen;
  320.   END;
  321. END; {FUNC Received}
  322.  
  323. FUNCTION RBused(Com:ComPorts):Word;
  324. BEGIN
  325.   IF eoRcvd[Com]<stRcvd[Com] THEN
  326.    RBused := RcvdBS[Com]-stRcvd[Com]+eoRcvd[Com]
  327.     ELSE RBused := eoRcvd[Com]-stRcvd[Com];
  328. END; {FUNC RBused}
  329.  
  330. FUNCTION cRead(Com:ComPorts):Char;
  331. BEGIN
  332.   IF Status[Com]=Open THEN
  333.   BEGIN
  334.     CLI;
  335.     cRead := chr(Rcvd[Com]^[stRcvd[Com]]);
  336.     IF stRcvd[Com]<RcvdBS[Com] THEN inc(stRcvd[Com])
  337.      ELSE stRcvd[Com] := 1;
  338.     STI;
  339.     ErrorCom := NoError;
  340.   END
  341.    ELSE
  342.   BEGIN
  343.     cRead := #0;
  344.     ErrorCom := NotOpen;
  345.   END;
  346. END; {FUNC cRead}
  347.  
  348. PROCEDURE cWrite(Com:ComPorts; msg:String);
  349. VAR
  350.   n : byte;
  351.   HoldOK,DsrCtsOK : Boolean;
  352. BEGIN
  353.   IF Status[Com]=Open THEN
  354.   BEGIN
  355.     RTS(Com,True);
  356.     FOR n := 1 to length(msg) DO
  357.     BEGIN
  358.       REPEAT
  359.         HoldOK := Port[LineStat[Com]] and xmitHoldEmpty = xmitHoldEmpty;
  360.         {DsrCtsOK := Port[ModemStat[Com]] and (_DSR_+_CTS_) = _DSR_+_CTS_;}
  361.       UNTIL HoldOK { and DsrCtsOK};
  362.       Port[Data[Com]] := byte(msg[n]);
  363.     END;
  364.     RTS(Com,False);
  365.     ErrorCom := NoError;
  366.   END
  367.    ELSE ErrorCom := NotOpen;
  368. END; {PROC cWrite}
  369.  
  370. FUNCTION ComError;
  371. BEGIN
  372.   ComError := ErrorCom;
  373.   ErrorCom := 0;
  374. END; {FUNC ComError}
  375.  
  376. BEGIN {Initialisation part of Unit LFcomm}
  377.   Units.Enter(LFcommMsg,MemAvail,CSeg);
  378.   InverseRTS := False;
  379.   InverseDTR := False;
  380.   FOR cno := Com1 to Com2 DO
  381.   BEGIN
  382.     GetIntVec(iComNo[cno],OldVec[cno]);
  383.     Status[cno] := Closed;
  384.     RcvdBS[cno] := 1;
  385.   END;
  386.   ErrorCom := 0;
  387. END.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement