Program JTerm;

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

{* From p. 585 Complete Turbo Pascal 3rd ed.

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



uses

  Dos,

  Crt;



const

  Com1Int = 12;

  RBR = $3F8;

  THR = $3F8;

  LCR = $3FB;

  IER = $3F9;

  MCR = $3FC;

  LSR = $3FD;

  DLL = $3F8;

  DLM = $3F9;

  DLAB = $80;



  BAUD300 = 384;

  BAUD1200 = 96;

  NoParity = 0;

  Bits8 = $03;

  DTR = $01;

  RTS = $02;

  Out2 = $08;



  OCW1 = $21;

  OCW2 = $20;

  IRQ4 = $10;



type

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



var

  Quit: boolean;

  HiBaud:  boolean;

  KeyChar: char;

  CommChar: char;

  Divisor: word;

  ClearIt: byte;

  Buffer: CircularBuffer;

  LastRead,

  LastSaved: Integer;

  NoShow: set of char;

  OldVector: pointer;



Procedure ShowHelp;

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

begin

  writeln('Help not installed.');

end;



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;



{$F+}

Procedure JTermExitProc;

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

begin

  Port[IER] := 0;

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

  Port[MCR] := 0;

  SetIntVec(Com1Int, OldVector);

end;

{$F-}



Procedure SetupSerialPort;

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

begin

  LastRead := 0;

  LastSaved := 0;

  Port[IER] := 0;

  GetIntVec(Com1Int, OldVector);

  ExitProc := @JTermExitProc;

  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);

  ClearIt := Port[RBR];

  ClearIt := Port[LSR];

  Port[IER] := $01;

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;



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

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

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

begin

  HiBaud := true;

  Divisor := Baud1200;

  if ParamCount > 0 then

    if ParamStr(1) = '300' then

      begin

        HiBaud := false;

        Divisor := Baud300;

      end;

  DirectVideo := true;

  NoShow := [#0, #127];

  SetupSerialPort;

  ClrScr;

  Writeln('>>>JTERM by Jeff Duntemann');

  Quit := false;

  repeat

    if InStat then

      begin

        CommChar := InChar;

        CommChar := Char(Byte(CommChar) and $7F);

        if not(CommChar in NoShow) then

          write(CommChar);

      end;

    if KeyPressed then

      begin

        KeyChar := ReadKey;

        if KeyChar = Chr(0) then

          begin

            KeyChar := ReadKey;

            case Ord(KeyChar) of

              59:  ShowHelp;

            end; {case}

          end

        else

          case ord(KeyChar) of

            24:  Quit := true;

            26:  ClrScr;

            else

              OutChar(KeyChar);

          end; {case}

      end;

  until Quit;

end.



