home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-386-Vol-2of3.iso / c / ctkit11.zip / ASYNC2.PAS next >
Pascal/Delphi Source File  |  1991-04-03  |  9KB  |  268 lines

  1. {$B-} { Short circuit boolean ON }
  2. {$I-} { I/O checking OFF }
  3. {$R-} { Range checking OFF }
  4. {$S-} { Stack checking OFF }
  5. {$V-} { Var-str checking OFF}
  6.  
  7. UNIT ASYNC2;
  8.   {PD async unit debugged and modified for doorgame use by Joel Bergen}
  9.   {added com3 & com4 support and xon/xoff handshaking                 }
  10.   {various bug fixes by Gary Gordon & Joel Bergen Jan 1990}
  11.   {Last revised:  1/14/90}
  12.   {still needs check for existance of comm port in Async_Open routine}
  13.  
  14. INTERFACE
  15.  
  16. USES DOS, CRT;
  17.  
  18. VAR
  19.   Async_CheckCTS, SaveFile,NoMem  : BOOLEAN;
  20. { TFile: text;
  21.   TFName: string;  }
  22.  
  23. PROCEDURE Async_Init;
  24.   { initialize variables, call first to initialize }
  25.  
  26. PROCEDURE Async_Close;
  27.   { reset the interrupt system when UART interrupts no longer needed }
  28.   { Turn off the COM port interrupts.                                }
  29.   { **MUST** BE CALLED BEFORE EXITING YOUR PROGRAM; otherwise you    }
  30.   { will see some really strange errors and have to re-boot.         }
  31.  
  32. FUNCTION Async_Open(ComPort,BaudRate : WORD) : BOOLEAN;
  33.   { open a communications port at 8/n/1 with supplied port & baud   }
  34.   { Sets up interrupt vector, initialies the COM port for           }
  35.   { processing, sets pointers to the buffer.  Returns FALSE if COM  }
  36.   { port not installed.                                             }
  37.  
  38. FUNCTION Async_Buffer_Check : BOOLEAN;
  39.   { see if a character has been received        }
  40.   { If a character is available, returns TRUE   }
  41.   { Otherwise, returns FALSE                    }
  42.  
  43. FUNCTION Async_Read : CHAR;
  44.   { read a character, assuming it is ready}
  45.  
  46. PROCEDURE Async_Send(C : CHAR);
  47.   { transmit a character }
  48.  
  49. PROCEDURE Async_Hangup;
  50.   { drop carrier by dropping DTR}
  51.  
  52. FUNCTION Async_CarrierDetect : BOOLEAN;
  53.   { true if carrier detected }
  54.  
  55. {----------------------------------------------------------------------------}
  56.  
  57. IMPLEMENTATION
  58.  
  59. CONST
  60.   I8088_IMR = $21;   { port address of the Interrupt Mask Register }
  61.   AsyncBasePort  : ARRAY[1..4] OF WORD = ($03F8,$02F8,$03E8,$02E8);
  62.   AsyncIRQ       : ARRAY[1..4] OF WORD = (4,3,4,3);
  63.   Async_Buffer_Max = 1024;          { size of input buffer }
  64.   Ier = 1;
  65.   Lcr = 3;
  66.   Mcr = 4;
  67.   Lsr = 5;
  68.   Msr = 6;
  69.  
  70. VAR
  71.   Async_OriginalVector : POINTER;
  72.   Async_OriginalLcr    : INTEGER;
  73.   Async_OriginalImr    : INTEGER;
  74.   Async_OriginalIer    : INTEGER;
  75.  
  76.   Async_Buffer         : ARRAY[0..Async_Buffer_Max] OF CHAR;
  77.  
  78.   Async_Open_Flag      : BOOLEAN;   { true if Open but no Close }
  79.   Async_Pause          : BOOLEAN;   { true if paused (Xoff received) }
  80.   Async_Port           : INTEGER;   { current Open port number (1..4) }
  81.   Async_Base           : INTEGER;   { base for current open port }
  82.   Async_Irq            : INTEGER;   { irq for current open port }
  83.  
  84.   Async_Buffer_Overflow: BOOLEAN;   { True if buffer overflow has happened }
  85.   Async_Buffer_Used    : WORD;      { number of characters in input buffer }
  86.  
  87.   { Async_Buffer is empty if Head = Tail }
  88.   Async_Buffer_Head    : WORD;   { Locn in Async_Buffer to put next char }
  89.   Async_Buffer_Tail    : WORD;   { Locn in Async_Buffer to get next char }
  90.  
  91. PROCEDURE DisableInterrupts; INLINE($FA {cli} );     {MACROS}
  92.  
  93. PROCEDURE EnableInterrupts;  INLINE($FB {sti} );
  94.  
  95. PROCEDURE Async_Isr;  INTERRUPT;
  96. { Interrupt Service Routine
  97.   Invoked when the UART has received a byte of data from the
  98.   communication line }
  99. CONST
  100.   Xon  = #17;  {^q resume}
  101.   Xoff = #19;  {^s pause}
  102. VAR
  103.   c : CHAR;
  104. BEGIN
  105.   EnableInterrupts;
  106.   IF Async_Buffer_Used < Async_Buffer_Max THEN BEGIN
  107.     c := CHR(PORT[Async_Base]);
  108. {   CASE c OF
  109.       Xoff : Async_Pause:=TRUE;
  110.       Xon  : Async_Pause:=FALSE;
  111.       ELSE BEGIN                }
  112.         Async_Pause:=FALSE;
  113. {        if not nomem then  }
  114.            begin
  115.            Async_Buffer[Async_Buffer_Head] := c;
  116.            IF Async_Buffer_Head < Async_Buffer_Max THEN
  117.              INC(Async_Buffer_Head)
  118.              ELSE
  119.              Async_Buffer_Head := 0;
  120.            INC(Async_Buffer_Used);
  121.            end;
  122. {      if SaveFile then
  123.            Write (TFile,c);
  124.       END;
  125.     END;                    }
  126.   END ELSE Async_Buffer_Overflow := TRUE;
  127.   DisableInterrupts;
  128.   PORT[$20] := $20;
  129. END; { Async_Isr }
  130.  
  131. PROCEDURE Async_Init;
  132. { initialize variables }
  133. BEGIN
  134.   Async_Open_Flag       := FALSE;
  135.   Async_Buffer_Head     := 0;
  136.   Async_Buffer_Tail     := 0;
  137.   Async_Buffer_Overflow := FALSE;
  138.   Async_Buffer_Used     := 0;
  139.   Async_Pause           := FALSE;
  140.   Async_CheckCTS        := TRUE;
  141. END; { Async_Init }
  142.  
  143. PROCEDURE Async_Close;
  144. { reset the interrupt system when UART interrupts no longer needed }
  145. VAR
  146.   i, m : INTEGER;
  147. BEGIN
  148.   IF Async_Open_Flag THEN BEGIN
  149.     DisableInterrupts;             { disable IRQ on 8259 }
  150.     PORT[Async_Base + Ier] := Async_OriginalIer;
  151.     PORT[Async_Base+Lcr]   := Async_OriginalLcr;
  152.     PORT[I8088_IMR]        := Async_OriginalImr;
  153.     EnableInterrupts;
  154.     SETINTVEC(Async_Irq + 8,Async_OriginalVector);
  155.     Async_Open_Flag := FALSE     { flag port as closed }
  156.   END;
  157. { Close (TFile); }
  158. END; { Async_Close }
  159.  
  160. FUNCTION Async_Open(ComPort,BaudRate : WORD) : BOOLEAN;
  161. VAR
  162.   i, m : INTEGER;
  163.   b    : BYTE;
  164. BEGIN
  165.     IF Async_Open_Flag THEN Async_Close;
  166.     Async_Port := ComPort;
  167.     Async_Base := AsyncBasePort[Async_Port];
  168.     Async_Irq  := AsyncIRQ[Async_Port];
  169.       { set comm parameters }
  170.     Async_OriginalLcr := PORT[Async_Base+Lcr];
  171.  
  172.     PORT[Async_Base+Lcr] := $03;  {set 8/n/1. This shouldn't be hardcoded}
  173.       { set ISR vector }
  174.     GETINTVEC(Async_Irq+8, Async_OriginalVector);
  175.     SETINTVEC(Async_Irq+8, @Async_Isr);
  176.       { read the RBR and reset any possible pending error conditions }
  177.       { first turn off the Divisor Access Latch Bit to allow access to RBR, etc. }
  178.     DisableInterrupts;
  179.     PORT[Async_Base+Lcr] := PORT[Async_Base+Lcr] AND $7F;
  180.       { read the Line Status Register to reset any errors it indicates }
  181.     i := PORT[Async_Base+Lsr];
  182.       { read the Receiver Buffer Register in case it contains a character }
  183.     i := PORT[Async_Base];
  184.       { enable the irq on the 8259 controller }
  185.     i := PORT[I8088_IMR];  { get the interrupt mask register }
  186.  
  187.     Async_OriginalImr := i;
  188.  
  189.     m := (1 shl Async_Irq) XOR $00FF;
  190.     PORT[I8088_IMR] := i AND m;
  191.       { enable the data ready interrupt on the 8250 }
  192.  
  193.     Async_OriginalIer := PORT[Async_Base + Ier];
  194.  
  195.     Port[Async_Base + Ier] := $01; { enable data ready interrupt }
  196.       { enable OUT2 on 8250 }
  197.     i := PORT[Async_Base + Mcr];
  198.     PORT[Async_Base + Mcr] := i OR $08;
  199.     EnableInterrupts;
  200.       { Set baudrate}
  201.     b := PORT[Async_Base+Lcr] OR 128;
  202.     PORT[Async_Base+Lcr]:= b;
  203.     PORT[Async_Base  ]  := LO(TRUNC(115200.0/BaudRate));
  204.     PORT[Async_Base+1]  := HI(TRUNC(115200.0/BaudRate));
  205.     PORT[Async_Base+Lcr]:= b AND 127;
  206.       { set flags }
  207.     Async_Open_Flag := TRUE;
  208.     Async_Open := TRUE;
  209. {   Assign (TFile,TFName);
  210.     ReWrite (TFile);  }
  211. END; { Async_Open }
  212.  
  213. FUNCTION Async_Buffer_Check : BOOLEAN;
  214. { return true if character ready to receive }
  215. BEGIN
  216.   Async_Buffer_Check := (Async_Buffer_Used <> 0);
  217. END; { Async_Buffer_Check }
  218.  
  219. FUNCTION Async_Read : CHAR;
  220. { return char, use Async_Buffer_Check first! }
  221. BEGIN
  222.   Async_Read := Async_Buffer[Async_Buffer_Tail];
  223.   INC(Async_Buffer_Tail);
  224.   IF Async_Buffer_Tail > Async_Buffer_Max THEN
  225.     Async_Buffer_Tail := 0;
  226.   DEC(Async_Buffer_Used);
  227. END; { Async_Buffer_Check }
  228.  
  229. PROCEDURE Async_Send(c : CHAR);
  230. { transmit a character }
  231. BEGIN
  232.   PORT[Async_Base + Mcr] := $0B;                 {turn on OUT2, DTR, and RTS}
  233.   IF Async_CheckCTS THEN
  234.     WHILE (Port[Async_Base + Msr] AND $10) = 0 DO;  {wait for CTS}
  235.   WHILE (Port[Async_Base + Lsr] AND $20) = 0 DO; {wait for Tx Holding Reg Empty}
  236.   WHILE Async_Pause AND Async_CarrierDetect DO;  {wait for Xon}
  237.   DisableInterrupts;
  238.   PORT[Async_Base] := ORD(c);                    {send the character}
  239.   EnableInterrupts;
  240. END; { Async_Send }
  241.  
  242. PROCEDURE Async_Hangup;
  243. BEGIN
  244.   PORT[Async_Base+Mcr] := $00;  {dtr off}
  245.   DELAY(1000);                  {wait 1 second}
  246.   PORT[Async_Base+Mcr] := $03;  {dtr on}
  247. END;
  248.  
  249. FUNCTION Async_CarrierDetect : BOOLEAN;
  250. {true if carrier}
  251. VAR
  252.   b : BOOLEAN;
  253.   w : WORD;
  254. BEGIN
  255.   w:=0; b:=TRUE;
  256.   WHILE (w<500) AND b DO BEGIN              {make sure carrier stays down}
  257.     INC(w);                                 {and is not just a fluke     }
  258.     b:=(PORT[Async_Base+Msr] AND 128) <> 128; {true = no carrier};
  259.   END;
  260.   Async_CarrierDetect := NOT b;
  261. END;
  262.  
  263. BEGIN
  264.   Async_Init;
  265. { TFName := 'CT.LOG';
  266.   SaveFile := false;   }
  267. END. { ASYNC UNIT }
  268.