[Back to COMM SWAG index] [Back to Main SWAG index] [Original]

    { ---------------------------------------------------------------------------
      unit COM.PAS

      Turbo Pascal (version 4.0 or higher) unit for serial communication which
      is based on interrupt routines and includes buffering of incoming data.

      Features:

      - supports COM1 and COM2 in parallel
      - baudrates up to 115200 baud
      - RTS/CTS and XON/XOFF flow control

      Version 3.0 - May 1994

      Copyright 1994, Willem van Schaik - Oirschot - Netherlands

      ---------------------------------------------------------------------------
    }

      unit Com;

      interface

      uses Crt, Dos;

      type
        PortType = (COM1, COM2);
        BaudType = (B110, B150, B300, B600, B1200, B2400, B4800,
           B9600, B19200, B38400, B57600, B115200);
        ParityType = (None, Odd, Even, Mark, Space);
        LengthType = (D5, D6, D7, D8);
        StopType = (S1, S2);
        FlowType = (No, RtsCts, XonXoff);

      procedure InitCom (PortNumber : PortType;
             BaudRate : BaudType;
                         ParityBit : ParityType;
             DataLength : LengthType;
             StopBits : StopType;
             FlowControl : FlowType);
      procedure ExitCom (PortNumber : PortType);
      function  ComReceived (PortNumber : PortType) : boolean;
      function  ReadCom (PortNumber : PortType) : char;
      function  ComAllowed (PortNumber : PortType) : boolean;
      procedure WriteCom (PortNumber : PortType; OutByte : char);
      procedure BreakCom (PortNumber : PortType);

      implementation

      type
        IntBlock = record
          IntOldIP : integer;
          IntOldCS : integer;
          IntNumber : byte;
        end;

        INS8250 = record
          DLL : integer;  { divisor latch low register (if LCR bit7 = 1) }
          DLH : integer;  { divisor latch high register (if LCR bit7 = 1) }
          THR : integer;  { transmit holding register }
          RBR : integer;  { receive holding register }
          IER : integer;  { interrupt enable register }
          LCR : integer;  { line control register }
          MCR : integer;  { modem control register }
          LSR : integer;  { line status register }
          MSR : integer;  { modem status register }
        end;

      const
        IntDS : integer = 0;
        ComPort : array [COM1..COM2] of INS8250 =
          ((DLL : $3F8 ; DLH : $3F9 ; THR : $3F8 ; RBR : $3F8 ;
            IER : $3F9 ; LCR : $3FB ; MCR : $3FC ; LSR : $3FD ; MSR : $3FE),
           (DLL : $2F8 ; DLH : $2F9 ; THR : $2F8 ; RBR : $2F8 ;
            IER : $2F9 ; LCR : $2FB ; MCR : $2FC ; LSR : $2FD ; MSR : $2FE));
        { size of the input buffer and the amount of free space to disable flow
          from the other side and to enable it again }
        ComBufferSize = 4096;
        ComFlowLower = 256;
        ComFlowUpper = 1024;

      var
        ComBuffer : array [COM1 .. COM2, 0..(ComBufferSize-1)] of byte;
        ComBufferHead, ComBufferTail : array [COM1 .. COM2] of integer;
        ComFlowControl : array [COM1 .. COM2] of FlowType;
        ComFlowHalted : array [COM1 .. COM2] of boolean;
        ComXoffReceived : array [COM1 .. COM2] of boolean;
        ComBlock : array [COM1 .. COM2] of IntBlock;

    { ---------------------------------------------------------------------------
      InstallComInt

      To install an interrupt routine, first the old routine vector is read and
      stored using function 35 hex. Next the new routine is installed using
      function 25 hex.
      ---------------------------------------------------------------------------
    }

      procedure InstallComInt (IntNumber : byte; IntHandler : integer;
                               var Block : IntBlock);
      var
        Regs : Registers;

      begin
        IntDS := DSeg;
        Block.IntNumber := IntNumber;
        Regs.AH := $35;
        Regs.AL := IntNumber;
        MSDos (Dos.Registers(Regs));
        Block.IntOldCS := Regs.ES;
        Block.IntOldIP := Regs.BX;
        Regs.AH := $25;
        Regs.AL := IntNumber;
        Regs.DS := CSeg;
        Regs.DX := IntHandler;
        MSDos (Dos.Registers(Regs));
      end;

    { ---------------------------------------------------------------------------
      UnInstallComInt

      Uninstalling the interrupt routine is done by resetting the old interrupt
      vector using function 25.
      ---------------------------------------------------------------------------
    }

      procedure UnInstallComInt (var Block : IntBlock);

      var
        Regs : Registers;

      begin
        Regs.AH := $25;
        Regs.AL := Block.IntNumber;
        Regs.DS := Block.IntOldCS;
        Regs.DX := Block.IntOldIP;
        MSDos (Dos.Registers(Regs));
      end;

    { ---------------------------------------------------------------------------
      Com1IntHandler

      This routine is installed as the interrupt routine by InstallComInt, which
      in its turn is called by InitCom at initialisation of the unit.

      When a byte arrives at the COM-port, first action is to get the byte from
      the UART register and store it the buffer. Next the buffer pointer is
      increased. Depending on flow control being enabled or not, it is checked if
      the free space has become less then ComFlowLower and if that is the case the
      other party (the DCE) is signalled to stop transmitting data.

      When the type of flow control specified at calling InitCom is RtsCts (this
      is hardware flow control), the RTS bit of the MCR register is lowered. If
      flow control is XonXoff (software flow control), an XOFF character (13 hex)
      is send to the other party by calling WriteCom.

      Finally the routine must be ended with a CLI instruction and the interrupt
      flags must be cleared.
      ---------------------------------------------------------------------------
    }

      procedure Com1IntHandler (Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP
    : word);
      interrupt;

      begin
        ComBuffer[COM1, ComBufferHead[COM1]] := Port[ComPort[COM1].RBR];
        if ComFlowControl[COM1] = No then
        begin
          ComBufferHead[COM1] := (ComBufferHead[COM1] + 1) mod ComBufferSize;
        end
        else { when flow control increase buffer pointer later }
        begin
          { check for incoming XON/XOFF }
          if ComFlowControl[COM1] = XonXoff then
          begin
            if ComBuffer[COM1, ComBufferHead[COM1]] = $11 then { XON }
              ComXoffReceived[COM1] := false
            else if ComBuffer[COM1, ComBufferHead[COM1]] = $13 then { XOFF }
              ComXoffReceived[COM1] := true;
          end;
          ComBufferHead[COM1] := (ComBufferHead[COM1] + 1) mod ComBufferSize;
          { check if outgoing must be temporized }
          if not ComFlowHalted[COM1] then
            if (ComBufferHead[COM1] >= ComBufferTail[COM1]) and
       (ComBufferTail[COM1] - ComBufferHead[COM1] + ComBufferSize < ComFlowLower)
       or
       (ComBufferHead[COM1] < ComBufferTail[COM1]) and
       (ComBufferTail[COM1] - ComBufferHead[COM1] < ComFlowLower) then
            begin { buffer gets too full }
       if ComFlowControl[COM1] = RtsCts then
         Port[ComPort[COM1].MCR] := Port[ComPort[COM1].MCR] and $FD { lower RTS }
       else if ComFlowControl[COM1] = XonXoff then
         WriteCom (COM1, #$13); { send XOFF }
       ComFlowHalted[COM1] := true;
            end;
        end;
        inline ($FA);                         { CLI }
        Port[$20] := $20;                     { clear interrupt flag }
      end;

    { ---------------------------------------------------------------------------
      Com2IntHandler

      This routine is identical to Com1IntHandler, only for COM2.
      ---------------------------------------------------------------------------
    }

      procedure Com2IntHandler (Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP : word);
      interrupt;

      begin
        ComBuffer[COM2, ComBufferHead[COM2]] := Port[ComPort[COM2].RBR];
        if ComFlowControl[COM2] = No then
        begin
          ComBufferHead[COM2] := (ComBufferHead[COM2] + 1) mod ComBufferSize;
        end
        else { when flow control increase buffer pointer later }
        begin
          { check for incoming XON/XOFF }
          if ComFlowControl[COM2] = XonXoff then
          begin
            if ComBuffer[COM2, ComBufferHead[COM2]] = $11 then { XON }
              ComXoffReceived[COM2] := false
            else if ComBuffer[COM2, ComBufferHead[COM2]] = $13 then { XOFF }
              ComXoffReceived[COM2] := true;
          end;
          ComBufferHead[COM2] := (ComBufferHead[COM2] + 1) mod ComBufferSize;
          { check if outgoing must be temporized }
          if not ComFlowHalted[COM2] then
            if (ComBufferHead[COM2] >= ComBufferTail[COM2]) and
       (ComBufferTail[COM2] - ComBufferHead[COM2] + ComBufferSize < ComFlowLower)
       or
       (ComBufferHead[COM2] < ComBufferTail[COM2]) and
       (ComBufferTail[COM2] - ComBufferHead[COM2] < ComFlowLower) then
            begin { buffer gets too full }
       if ComFlowControl[COM2] = RtsCts then
         Port[ComPort[COM2].MCR] := Port[ComPort[COM2].MCR] and $FD { lower RTS }
       else if ComFlowControl[COM2] = XonXoff then
         WriteCom (COM2, #$13); { send XOFF }
       ComFlowHalted[COM2] := true;
            end;
        end;
        inline ($FA);                         { CLI }
        Port[$20] := $20;                     { clear interrupt flag }
      end;

    { ---------------------------------------------------------------------------
      InitCom;

      For each of the COM ports that will be used, this routine must be called
      to initialize the UART and to install the interrrupt routine. The first
      five parameters define the serial protocol (baudrate B150..B11500, parity
      None..Space, length D5..D8 and number of stop bits S1 or S2). The last
      parameter specifies the type of flow control, with allowed values No,
      RtsCts and XonXoff.

      The control signals DTR and RTS of the COM port (plus the OUT2 signal, which
      is used by some internal modems) are raised to signal the other end of the
      line that the port is ready to receive data.
      ---------------------------------------------------------------------------
    }

      procedure InitCom; { (PortNumber : PortType;
                BaudRate : BaudType;
                            ParityBit : ParityType;
                DataLength : LengthType;
                StopBits : StopType;
                FlowControl : FlowType); }
      const
        BaudReg : array [B110 .. B115200] of word =
          ($0417, $0300, $0180, $00C0, $0060, $0030,
           $0018, $000C, $0006, $0003, $0002, $0001);
        ParityReg : array [None..Space] of byte =
          ($00, $08, $18, $28, $38);
        LengthReg : array [D5 .. D8] of byte =
          ($00, $01, $02, $03);
        StopReg : array [S1 .. S2] of byte =
          ($00, $04);

      var
        Regs : Registers;

      begin
        { enable the interrupt (IRQ4 resp. IRQ3) for the specified COM port, by
          resetting the bits in the Interrupt Mask Register of the 8259 interrupt
          controller }
        if PortNumber = COM1 then
        begin
          InstallComInt($0C, Ofs(Com1IntHandler), ComBlock[COM1]);
          Port[$21] := Port[$21] and $EF
        end
        else if PortNumber = COM2 then
        begin
          InstallComInt($0B, Ofs(Com2IntHandler), ComBlock[COM2]);
          Port[$21] := Port[$21] and $F7
        end;

        Port[ComPort[PortNumber].LCR] := $80; { switch to write latch reg }
        Port[ComPort[PortNumber].DLH] := Hi (BaudReg [BaudRate]);
        Port[ComPort[PortNumber].DLL] := Lo (BaudReg [BaudRate]);
        Port[ComPort[PortNumber].LCR] := $00 or
             ParityReg [ParityBit] or
             LengthReg [DataLength] or
             StopReg [StopBits];
        Port[ComPort[PortNumber].IER] := $01; { enable interrupts }
        Port[ComPort[PortNumber].MCR] := $01 or { raise DTR }
                    $02 or { raise RTS }
             $08;   { raise OUT2 }
        ComBufferHead[PortNumber] := 0;
        ComBufferTail[PortNumber] := 0;
        ComFlowControl[PortNumber] := FlowControl;
        ComFlowHalted[PortNumber] := false;
        ComXoffReceived[PortNumber] := false;
      end;

    { ---------------------------------------------------------------------------
      ExitCom;

      This routine must be called for each COM port in use, to remove the
      interrupt routine and to reset the control lines.
      ---------------------------------------------------------------------------
    }

      procedure ExitCom; { (PortNumber : PortType) }

      var
        Regs : Registers;

      begin
        { disable the interrupt (IRQ4 resp. IRQ3) for the specified COM port, by
          setting the bits in the Interrupt Mask Register of the 8259 interrupt
          controller }
        if PortNumber = COM1 then
          Port[$21] := Port[$21] or $10
        else if PortNumber = COM2 then
          Port[$21] := Port[$21] or $08;

        Port[ComPort[PortNumber].LCR] := Port[ComPort[PortNumber].LCR] and $7F;
        Port[ComPort[PortNumber].IER] := 0; { disable interrupts }
        Port[ComPort[PortNumber].MCR] := 0; { lower DTR, RTS and OUT2 }
        UnInstallComInt(ComBlock[PortNumber]);
      end;

    { ---------------------------------------------------------------------------
      ComReceived;

      When the head and tail pointer (for writing resp. reading bytes) are not
      pointing to the same byte in the buffer, a byte has arrived from the UART
      and was stored in the buffer by the interrupt routine.
      ---------------------------------------------------------------------------
    }

      function ComReceived; { (PortNumber : PortType) : boolean; }

      begin
        ComReceived := ComBufferHead[PortNumber] <> ComBufferTail[PortNumber];
      end;

    { ---------------------------------------------------------------------------
      ReadCom;

      Calling this function will wait for a byte in the buffer (if there is not
      yet one present) and then return it. The tail buffer pointer is increased
      and if flow from the other side was stopped, a check is made if the free
      space has again become more then ComFlowUpper. In that situation, depending
      on the type of flow control, either the RTS line is raised or and XON byte
      (11 hex) is send to the other party.
      ---------------------------------------------------------------------------
    }

      function ReadCom; { (PortNumber : PortType) : char; }

      begin
        while ComBufferHead[PortNumber] = ComBufferTail[PortNumber] do Delay(10);
        ReadCom := char(ComBuffer[PortNumber, ComBufferTail[PortNumber]]);
        ComBufferTail[PortNumber] := (ComBufferTail[PortNumber] + 1) mod ComBufferSize;
        if (ComFlowControl[PortNumber] <> No) and ComFlowHalted[PortNumber] then
          if (ComBufferHead[PortNumber] >= ComBufferTail[PortNumber]) and
            (ComBufferTail[PortNumber] - ComBufferHead[PortNumber] + ComBufferSize > ComFlowUpper) or
            (ComBufferHead[PortNumber] < ComBufferTail[PortNumber]) and
            (ComBufferTail[PortNumber] - ComBufferHead[PortNumber] > ComFlowUpper)
    then
          begin { buffer has emptied enough }
            if ComFlowControl[PortNumber] = RtsCts then
       Port[ComPort[PortNumber].MCR] := Port[ComPort[PortNumber].MCR] or $02 {
    raise RTS }
            else if ComFlowControl[PortNumber] = XonXoff then
       WriteCom (PortNumber, #$11); { send XON }
            ComFlowHalted[PortNumber] := false;
          end;
      end;

    { ---------------------------------------------------------------------------
      ComAllowed;

      With this function it is possible to check if writing data to the COM port
      is allowed. When there is no flow control no check is made on any control
      line and the result will always be true. When hardware type flow control is
      enabled, DSR (and CD) and CTS must be high. In case of software flow
      control DSR must be high and a check is made if an XOFF byte was received.
      ---------------------------------------------------------------------------
    }

      function  ComAllowed; { (PortNumber : PortType) : boolean; }

      begin
        ComAllowed := true;
        if (ComFlowControl[PortNumber] = RtsCts) then
        begin
          { replace in next line both $30 with $B0 for checking on CD, DSR and CTS}
          if ((Port[ComPort[PortNumber].MSR] and $30) <> $30) then { no DSR or CTS}
            ComAllowed := false;
        end
        else if (ComFlowControl[PortNumber] = XonXoff) then
        begin
          { replace in next line both $20 with $A0 for checking on CD and DSR }
          if ((Port[ComPort[PortNumber].MSR] and $20) <> $20) or { no DSR }
             (ComXoffReceived[PortNumber]) then { XOFF received }
            ComAllowed := false;
        end
      end;

    { ---------------------------------------------------------------------------
      WriteCom;

      This routine is to write a byte to the COM port. However, when necessary
      this will be delayed until the previous output byte is out the the UART.
      ---------------------------------------------------------------------------
    }

      procedure WriteCom; { (PortNumber : PortType; OutByte : char); }

      begin
        while ((Port[ComPort[PortNumber].LSR] and $20) <> $20) do  { TD empty }
          Delay(1);
        Port[ComPort[PortNumber].THR] := byte(OutByte);
      end;

    { ---------------------------------------------------------------------------
      BreakCom;

      With this routine the TD line can be lowered for 200 msec, which is a so-
      called break signal.
      ---------------------------------------------------------------------------
    }

      procedure BreakCom; { (PortNumber : PortType); }

      begin
        Port[ComPort[PortNumber].LCR] := Port[ComPort[PortNumber].LCR] or $40;
        Delay (200);  { 0.2 seconds }
        Port[ComPort[PortNumber].LCR] := Port[ComPort[PortNumber].LCR] and $BF;
      end;

      end.

    { ---------------------------------------------------------------------------
      end of COM.PAS
      ---------------------------------------------------------------------------
    }

    { ---------------------------------------------------------------------------
      program TTY.PAS

      Sample terminal emulation using simple teletype protocol to be used with
      the unit COM.PAS for serial communnication.

      Features:

      - switching between COM1 and COM2
      - baudrates up to 115200 baud
      - RTS/CTS and XON/XOFF flow control
      - debug mode to display control characters

      Version 3.0 - May 1994

      Copyright 1994, Willem van Schaik - Oirschot - Netherlands

      ---------------------------------------------------------------------------
    }

      program Tty;

      uses Crt, Com;

      const
        Ascii : array [0..255] of string [5] =
          ('<NUL>','<SOH>','<STX>','<ETX>','<EOT>','<ENQ>','<ACK>','<BEL>',
           '<BS>','<HT>','<LF>','<VT>','<FF>','<CR>','<SO>','<SI>',
           '<DLE>','<DC1>','<DC2>','<DC3>','<DC4>','<NAK>','<SYN>','<ETB>',
           '<CAN>','<EM>','<SUB>','<ESC>','<FS>','<GS>','<RS>','<US>',
           ' ','!','"','#','$','%','&','''','(',')','*','+',',','-','.','/',
           '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
           '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
           'P','Q','R','S','T','U','V','W','X','Y','Z','[','\',']','^','_',
           '`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
           'p','q','r','s','t','u','v','w','x','y','z','{','|','}','~','<DEL>',
           '<128>','<129>','<130>','<131>','<132>','<133>','<134>','<135>',
           '<136>','<137>','<138>','<139>','<140>','<141>','<142>','<143>',
           '<144>','<145>','<146>','<147>','<148>','<149>','<150>','<151>',
           '<152>','<153>','<154>','<155>','<156>','<157>','<158>','<159>',
           '<160>','<161>','<162>','<163>','<164>','<165>','<166>','<167>',
           '<168>','<169>','<170>','<171>','<172>','<173>','<174>','<175>',
           '<176>','<177>','<178>','<179>','<180>','<181>','<182>','<183>',
           '<184>','<185>','<186>','<187>','<188>','<189>','<190>','<191>',
           '<192>','<193>','<194>','<195>','<196>','<197>','<198>','<199>',
           '<200>','<201>','<202>','<203>','<204>','<205>','<206>','<207>',
           '<208>','<209>','<210>','<211>','<212>','<213>','<214>','<215>',
           '<216>','<217>','<218>','<219>','<220>','<221>','<222>','<223>',
           '<224>','<225>','<226>','<227>','<228>','<229>','<230>','<231>',
           '<232>','<233>','<234>','<235>','<236>','<237>','<238>','<239>',
           '<240>','<241>','<242>','<243>','<244>','<245>','<246>','<247>',
           '<248>','<249>','<250>','<251>','<252>','<253>','<254>','<255>');

      var
        TtyPort : PortType;
        TtyBaud : BaudType;
        TtyParity : ParityType;
        TtyLength : LengthType;
        TtyStop : StopType;
        TtyFlow : FlowType;

        ChCom, ChKey : char;
        DoDebug : boolean;
        GoExit : boolean;

    { ---------------------------------------------------------------------------
      TtyGetPars

      Procedure to handle alt-key combinations that are used to change the
      settings of the terminal emulation protocol.
      ---------------------------------------------------------------------------
    }

      procedure TtyGetPars (AltKey : char);

      var
        ParsInput : string[16];

      begin
        case AltKey of

          #120:  { alt-1 }
          begin
            if WhereX > 1 then Writeln;
            Writeln ('TTY:  port = COM1:');
            if TtyPort <> COM1 then
            begin
              ExitCom (TtyPort);
              TtyPort := COM1;
              InitCom (TtyPort, TtyBaud, TtyParity, TtyLength, TtyStop, TtyFlow)
            end;
          end;

          #121:  { alt-2 }
          begin
            if WhereX > 1 then Writeln;
            Writeln ('TTY:  port = COM2:');
            if TtyPort <> COM2 then
            begin
              ExitCom (TtyPort);
              TtyPort := COM2;
              InitCom (TtyPort, TtyBaud, TtyParity, TtyLength, TtyStop, TtyFlow)
            end;
          end;

          #48:  { alt-B }
          begin
            if WhereX > 1 then Writeln;
            Write ('TTY:  baudrate = ');
            Readln (ParsInput);
            if (ParsInput = '3') or (ParsInput = '300') then TtyBaud := B300
            else if (ParsInput = '6') or (ParsInput = '600') then TtyBaud := B600
            else if (ParsInput = '12') or (ParsInput = '1200') then TtyBaud := B1200
            else if (ParsInput = '24') or (ParsInput = '2400') then TtyBaud := B2400
            else if (ParsInput = '48') or (ParsInput = '4800') then TtyBaud := B4800
            else if (ParsInput = '96') or (ParsInput = '9600') then TtyBaud := B9600
            else if (ParsInput = '192') or (ParsInput = '19200') then TtyBaud := B19200
            else if (ParsInput = '384') or (ParsInput = '38400') then TtyBaud := B38400
            else
              Writeln ('      baudrate = 300,600,1200,2400,4800,9600,19200,38400');
            ExitCom (TtyPort);
            InitCom (TtyPort, TtyBaud, TtyParity, TtyLength, TtyStop, TtyFlow);
          end;

          #38:  { alt-L }
          begin
            if WhereX > 1 then Writeln;
            Write ('TTY:  word length = ');
            Readln (ParsInput);
            case ParsInput[1] of
              '5': TtyLength := D5;
              '6': TtyLength := D6;
              '7': TtyLength := D7;
              '8': TtyLength := D8;
            else
              Writeln ('      word length = 5,6,7,8');
            end;
            ExitCom (TtyPort);
            InitCom (TtyPort, TtyBaud, TtyParity, TtyLength, TtyStop, TtyFlow);
          end;

          #25:  { alt-P }
          begin
            if WhereX > 1 then Writeln;
            Write ('TTY:  parity bit = ');
            Readln (ParsInput);
            case ParsInput[1] of
              'n', 'N': TtyParity := None;
              'o', 'O': TtyParity := Odd;
              'e', 'E': TtyParity := Even;
              'm', 'O': TtyParity := Mark;
              's', 'O': TtyParity := Space;
            else
              Writeln ('      parity bit = none,odd,even,mark,space');
            end;
            ExitCom (TtyPort);
            InitCom (TtyPort, TtyBaud, TtyParity, TtyLength, TtyStop, TtyFlow);
          end;

          #31:  { alt-S }
          begin
            if WhereX > 1 then Writeln;
            Write ('TTY:  stop bits = ');
            Readln (ParsInput);
            case ParsInput[1] of
              '1': TtyStop := S1;
              '2': TtyStop := S2;
            else
              Writeln ('      stop bits = 1,2');
            end;
            ExitCom (TtyPort);
            InitCom (TtyPort, TtyBaud, TtyParity, TtyLength, TtyStop, TtyFlow);
          end;

          #33:  { alt-F }
          begin
            if WhereX > 1 then Writeln;
            Write ('TTY:  flow control = ');
            Readln (ParsInput);
            case ParsInput[1] of
              'n', 'N': TtyFlow := No;
              'r', 'R': TtyFlow := RtsCts;
              'x', 'X': TtyFlow := XonXoff;
            else
              Writeln ('      flow control = no,rts/cts,xon/xoff');
            end;
            ExitCom (TtyPort);
            InitCom (TtyPort, TtyBaud, TtyParity, TtyLength, TtyStop, TtyFlow);
          end;

          #23:  { alt-I }
          begin
            if WhereX > 1 then Writeln;
            Write ('TTY:  port = COM', ord(TtyPort)+1, ':      ');
            case TtyBaud of
              B110: Write ('baudrate = 110          ');
              B150: Write ('baudrate = 150          ');
              B300: Write ('baudrate = 300          ');
              B600: Write ('baudrate = 600          ');
              B1200: Write ('baudrate = 1200         ');
              B2400: Write ('baudrate = 2400         ');
              B4800: Write ('baudrate = 4800         ');
              B9600: Write ('baudrate = 9600         ');
              B19200: Write ('baudrate = 19200        ');
              B38400: Write ('baudrate = 38400        ');
              B57600: Write ('baudrate = 57600        ');
              B115200: Write ('baudrate = 115200       ');
            end;
            case TtyParity of
              None: Writeln ('parity bit = none');
              Odd: Writeln ('parity bit = odd');
              Even: Writeln ('parity bit = even');
              Mark: Writeln ('parity bit = mark');
              Space: Writeln ('parity bit = space');
            end;
            case TtyFlow of
              No: Write ('      flow = no         ');
              RtsCts: Write ('      flow = rts/cts    ');
              XonXoff: Write ('      flow = xon/xoff   ');
            end;
            Write ('word length = ', ord(TtyLength)+5, '         ');
            Writeln ('stop bits = ', ord(TtyStop)+1);
          end;

          #35:  { alt-H }
          begin
            if WhereX > 1 then Writeln;
            Write ('TTY:  alt-1 - COM1      ');
            Write ('alt-B - baudrate        ');
            Write ('alt-I - info');
            Writeln;
            Write ('      alt-2 - COM2      ');
            Write ('alt-L - word length     ');
            Write ('alt-H - help');
            Writeln;
            Write ('      alt-F - flow      ');
            Write ('alt-P - parity bit');
            Writeln;
            Write ('      alt-D - debug     ');
            Write ('alt-S - stop bits       ');
            Write ('alt-X - exit');
            Writeln;
          end;

          #32:  { alt-D }
          begin
            DoDebug := not DoDebug;
            if WhereX > 1 then Writeln;
            if DoDebug then
              Writeln ('TTY:  debug = on')
            else
              Writeln ('TTY:  debug = off');
          end;

          #45:  { alt-X }
          begin
            if WhereX > 1 then Writeln;
            Writeln ('TTY:  exit');
            GoExit := true;
          end;

        end;  { case ChKey }
      end;  { procedure TtyGetPars }

    { ---------------------------------------------------------------------------

[Back to COMM SWAG index] [Back to Main SWAG index] [Original]