Unit Comm;

{***************************************************************************}

{* Parts from p. 585 Complete Turbo Pascal 3rd ed.

{***************************************************************************}

interface

{***************************************************************************}

{***************************************************************************}



Function  InChar: char;

Function  InStat: boolean;

Procedure OutChar(Ch: char);

Procedure OutStr(SendStr: string);

Procedure SetupSerialPort(Baud: integer);

{$F+}Procedure ShutdownSerialPort;{$F-}



implementation

{***************************************************************************}

{***************************************************************************}



uses

  Dos,

  Crt,

  Glob;



const

  Com1Int = 12;

  RBR = $3F8;

  THR = $3F8;

  LCR = $3FB;

  IER = $3F9;

  MCR = $3FC;

  LSR = $3FD;

  DLL = $3F8;

  DLM = $3F9;

  DLAB = $80;



  NoParity = 0;

  Bits8 = $03;

  DTR = $01;

  RTS = $02;

  Out2 = $08;



  OCW1 = $21;

  OCW2 = $20;

  IRQ4 = $10;



type

  CircularBuffer = array[0..1023] of char;



var

  Buffer: CircularBuffer;

  LastRead,

  LastSaved: integer;

  OldVector: Pointer;



Procedure EnableInterrupts;

{***************************************************************************}

inline($FB);



Procedure Incoming(Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP: word);

interrupt;

{***************************************************************************}

begin

  EnableInterrupts;

  if LastSaved >= 1023 then

    LastSaved := 0

  else

    Inc(LastSaved);

  Buffer[LastSaved] := char(Port[RBR]);

  Port[OCW2] := $20;

end;



Function InStat: boolean;

{***************************************************************************}

begin

  if LastSaved <> LastRead then

    InStat := true

  else

    InStat := false;

end;



Function InChar: char;

{***************************************************************************}

begin

  if LastRead >= 1023 then

    LastRead := 0

  else

    LastRead := Succ(LastRead);

  InChar := Buffer[LastRead];

end;



Procedure OutChar(Ch: char);

{***************************************************************************}

begin

  Port[THR] := Byte(Ch);

end;



Procedure OutStr(SendStr: string);

{***************************************************************************}

var

  Index: byte;

begin

  for Index := 1 to length(SendStr) do

    OutChar(SendStr[Index]);

end;



Procedure SetupSerialPort(Baud: integer);

{***************************************************************************}

var

  Divisor: word;

begin

  Divisor := 115200 div Baud;

  LastRead := 0;

  LastSaved := 0;

  Port[IER] := 0;

  GetIntVec(Com1Int, OldVector);

  ExitProc := @ShutdownSerialPort;

  SetIntVec(Com1Int, @Incoming);

  Port[LCR] := Port[LCR] or DLAB;

  Port[DLL] := Lo(Divisor);

  Port[DLM] := Hi(Divisor);

  Port[LCR] := Bits8 or NoParity;

  Port[MCR] := DTR or RTS or Out2;

  Port[OCW1] :=Port[OCW1] and (not IRQ4);

  DumByte := Port[RBR];

  DumByte := Port[LSR];

  Port[IER] := $01;

end;



{$F+}

Procedure ShutdownSerialPort;

{***************************************************************************}

begin

  Port[IER] := 0;

  Port[OCW1] := Port[OCW1] or IRQ4;

  Port[MCR] := 0;

  SetIntVec(Com1Int, OldVector);

end;

{$F-}



{***************************************************************************}

{***************************************************************************}

{***************************************************************************}

begin

end.



