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

    {$O-} {This unit may >>>>NOT<<<< be overlaid}
    {$X+} {Extended syntax is ok}
    {$F+} {Allow far calls}
    {$A+} {Word Align Data}
    {$G+} {286 Code optimization - if you're using an 8088 get a real computer}
    {$R-} {Disable range checking}
    {$S+} {Enable Stack Checking}
    {$I-} {Disable IO Checking}
    {$Q-} {Disable Overflow Checking}
    {$D-} {Turn off debugging - use only if you modify this unit and get a bug}
    {$L-} {Turn off local symbols - again this unit has been thouroughly debuged}
    {$V-} {Turn off strict VAR strings}
    {$B-} {Allow short circuit boolean evaluations}
    {$T-} {Turn off typed @ operators}

    Unit Async;

    {This unit was written by Patrick Hunlock, 10/19/1994     }
    {Copyright @ 1994 by Patrick Hunlock - all rights reserved}

    {Software License Agreement: If you use this unit you are bound by it's terms}

    {You may use this unit in your programs without royalties. If you use this
     unit my name and the copyright notice must appear beneath your name and
     copyright notice even if you have made significant alterations to the
     source code in this unit.  This source code may only be transmitted via
     the telephone system.  It may not be distributed on any magnetic, optical,
     or any future computer media format without prior consent of the copyright
     holder.  No charge may ever be levied for the receipt of this source code
     other than normal phone charges and/or normal connect charges on a BBS which
     charges for access.  Any charges above and beyond what would be considered
     normal access charges to download this source is considered a SALE of this
     source code which is expressly prohibited by this License Agreement.
     You may distribute this source code via the telephone system (I.E.
     BBS or computer network) in it's original form only, you may not add or
     subtract to/from it in any way shape or form.}

    {This ASYNC unit implements a >COMPLETE< multi-port serial interface wrapped
     in a turbo pascal object.  Baud rates up to 110,000 are supported.  Up to
     four ports may be opened at a time, up to two ports may be active at any
     given time (four can be active so long as they do not share interrupts).
     Some considerations.  A com port which shares the same interrupt as a
     serial mouse will over-ride the mouse driver for the duration of the
     program.  If you have a mouse on Com1, avoid using Com3 in your program.
     Likewise if you have a mouse on Com2, avoid using Com4 in your program.
     A mouse on a BUS card will not be affected by this unit.  Default addresses
     for the 4 com ports dictate that com1 & com3, and com2 & com4 share an
     interrupt on the system bus.  As such while you can open both ports, make
     sure that only - ONE of the ports on the shared interrupt has been .ENABLED
     at any one time.  See the .ENABLE and .DISABLE procedures for more
     information.}

    Interface

    Type

       Com_Port      = Object
                             CPort   : Byte;          {Com Port for this port}

                          {Initializes the buffers and the object}
                          Function Init(ComPort: Byte; RBufSize,TBufSize: Word): Byte;
                          {Sets the baud,parity,wordsize, and stopbits}
                          Procedure SetParam(Baud: Longint; WordSize: Byte;
                                             Parity: Char; StopBits: Byte);
                          {Used for shared interrupts}
                          Procedure Disable;
                          {Enable a com port for use}
                          Procedure Enable;
                          {Returns true if there is data waiting}
                          Function Waiting: Boolean;
                          {Returns a character waiting in the buffer}
                          Function Read: Char;
                          {Waits for a character if necessary}
                          Function Readw: Char;
                          {Writes a character to the transmit buffer}
                          Procedure Write(C: CHar);
                          {Passes a string to the transmit buffer}
                          Procedure WriteS(S: String);
                          {Returns true if modem is "on-line" re DCD status}
                          Function OnLine: Boolean;
                          {Disconnects the modem connection}
                          Procedure Hangup;
                          {Sends a Break Signal to the other computer}
                          Procedure Break;
                          {Terminates the comm port}
                          Procedure Done;
                       End;

    Implementation

    Uses DOS,       {Turbo Pascal's DOS Unit}
         CRT;       {Turbo Pascal's CRT Unit}

    Const
                                         {Com1,Com2,Com3,Com4}
       PortBases : Array[1..4] Of Word = ($3F8,$2F8,$3E8,$2E8);
       Interrupts: Array[1..4] Of Byte = (   4,   3,   4,   3);

       Disable_Interrupts = $FA;       {Used in INLINE statements}
       Enable_Interrupts  = $FB;       {Used in INLINE statements}

    Type
       {Buf Type is never actually >declared< in this unit.  It is created only
        as a pointer to an area of memory which can actually only be 10 to 64000
        bytes long.  However by creating the pointer in this way, the contents
        of the pointer memory can be accessed like an array of chars simplifying
        the coding of this unit.  If you only create a 10000 byte buffer then
        it's valid to read BUFTYPE[0] through BufTYPE[10000] anything higher
        is dangerous since no memory was set aside for this buffer.  However
        the unit knows how much memory was set asside and it never references
        any data outside of the "safe" range}
       BufType = Array[0..64000] Of Char;

       {ComBufferType is the actual buffer used by the COM_ISR routine and the
        record which actually makes COM_PORT work.  In reality COM_PORT is just
        a shell which is wrapped around this record to give the illusion of
        OOP.  Take away COM_PORT, write your own procedures to reference
        ComBufferType and your program will work just fine}

       ComBufferType = Record
                          Active       : Boolean;  {True if this buffer is active}
                          R_Buffer     : ^BufType; {Recieve buffer pointer       }
                          R_Head,R_Tail: Word;     {Buffer Head and Buffer Tail  }
                          R_Size       : Word;     {Size of the recieve buffer   }
                          T_Buffer     : ^BufTYpe; {Transmit Buffer Pointer      }
                          T_Head,T_Tail: Word;     {Transmit Buffer Head & Tail  }
                          T_Size       : Word;     {Size of the transmit buffer  }
                          UART_Data    : Word;     {Uart data address            }
                          UART_IER     : Word;     {Uart interrupt enable registr}
                          UART_IIR     : Word;     {Uart interrupt identification}
                          UART_LCR     : Word;     {UArt Line Control Register   }
                          UART_MCR     : Word;     {UArt Modem COntrol Register  }
                          UART_LSR     : Word;     {UArt Line Status Register    }
                          UART_MSR     : Word;     {UArt Modem Status Register   }
                          OLD_MCR      : Byte;     {Old Modem control register   }
                          Org_Vector   : Pointer;  {Original interrupt vector    }
                       End;

    Var
       Bufs: Array[1..4] Of ComBufferType; {This declares 4 com buffers for  }
                                           {coms 1 - 4                       }

    Procedure COM_ISR; Interrupt;

    {COM_ISR is the main interrupt procedure which handles all the serial IO.
     This procedure is called >AUTOMATICALLY< by DOS whenever data arrives at
     the com port - or when it is clear to send data.  >SEVERE< restrictions
     as to what you can and can not add to this procedure apply.  You can not
     use WRITELN.  You can not reference any turbo pascal objects.  This unit
     may not be overlaid.  Etc, Etc, Etc}

    Const Ktr: Byte = 0;  {These are STATIC variables so pascal doesn't }
          IIR: Byte = 0;  {constantly have to redeclare them on the heap}

    Begin
       For Ktr:= 1 to 4 Do begin
          With Bufs[Ktr] Do Begin
             If Active Then Begin
                iir:= Port[UART_IIR];
                While Not Odd(IIR) Do Begin
                   Case (iir SHR 1) Of
                      0: iir:= Port[UART_MSR]; {Modem status change}
                      1: If T_Head = T_Tail Then Begin    {Ok to transmit      }
                            {Transmit buffer empty - disable transmit interrupt}
                            Port[UART_IER]:= Port[UART_IER] And Not 2;
                         End Else Begin
                            Port[UART_DATA]:= Byte(T_Buffer^[T_Head]);
                            Inc(T_Head);
                            If T_Head > T_Size Then T_Head:= 0;
                         End;
                      2: Begin                  {Recieve buffer}
                            R_Buffer^[R_Tail]:= Char(Port[Uart_Data]);
                            Inc(R_Tail);
                            If R_Tail > R_Size Then R_Tail:= 0;
                            If (R_Tail = R_Head) Then Begin
                               Inc(R_Head); {Overflow}
                               If R_Head > R_Size Then R_Head:= 0;
                            End;
                         End;
                      3: iir:= Port[UART_LSR]; {Line status change}
                   End;
                   iir:= Port[UART_IIR];
                End;
             End;
          End;
       End;
       Port[$20]:= $20;  {We're done processing the interrupt}
    End;

    Function Com_Port.Init(ComPort: Byte; RBufSize,TBufSize: Word): Byte;

    {Init is the standard object initialization routine. You must pass the
     comport (1-4) you want the object to be associated with and the buffer
     size (10-64000 bytes) you want the buffer to be.  Init returns the following
     codes based upon it's success or failure......

        0 - Com Port Initialized
        1 - ComPort is out of range - not 1, 2, 3, or 4.
        2 - ComPort is already active and in use.
        3 - Buffer size is either to small (10 bytes or more) or to large
            (greater than 64000) - Recieve Buffer
        4 - Transmit buffer size out of range (See #3)

     Init only sets up the buffers and prepares the interrupt vector.  You must
     follow this with a call to setparams (set baud rate, parity, etc), then
     a call to enable.  See enable and disable especially if you are going to
     use multiple comm ports simultaniously.
    }

    Var InUse: Boolean;     {Scratch variable to check for active interrupts}
        Ktr  : Byte;        {Counter Variable                               }

    Begin
       {Set the initial state of the return code to OK}
       Init:= 0;
       {Check the comport validity}
       If (ComPort < 1) Or (ComPort > 4) Then Begin
          Init:= 1;
          Exit;
       End;
       {Check to see if the comport is already in use by another object}
       If Bufs[ComPort].Active Then Begin
          Init:= 2;
          Exit;
       End;
       {Check to make sure the buffer size is valid}
       If (RBufSize > 64000) Or (RBufSize < 10) Then Begin
          Init:= 3;
          Exit;
       End;
       If (TBufSize > 64000) Or (TBufSize < 10) Then Begin
          Init:= 4;
          Exit;
       End;

       {Begin main setup}

       CPort:= ComPort;                        {Store the comport for future use}
       Getmem(Bufs[ComPort].R_Buffer,RBufSize);{Allocate memory for the buffer  }
       Bufs[ComPort].R_Size:= RBufSize;        {Store the size of the buffer    }
       GetMem(Bufs[ComPort].T_Buffer,TBufSize);{Allocate transmit buffer memory }
       Bufs[ComPort].T_Size:= TBufSize;        {Store the size of the buffer    }

       {This next section sets up the PORT addresses used by the comport
        requested.  The base addresses are stored in PORTBASES, a constant
        declared at the top of the implenetation section of this unit.  Your
        program may need to change the address and/or interrupts found in
        that section for serial cards with unusual addresses and interrupts.
        Since PortBases and Interrupts are typed constant arrays you can
        easilly add an object method to change the address or interrupt for
        a given comm port}

        Bufs[ComPort].UART_DATA:= PortBases[ComPort]+0;
        Bufs[ComPort].UART_IER := PortBases[ComPort]+1;
        Bufs[ComPort].UART_IIR := PortBases[ComPort]+2;
        Bufs[ComPort].UART_LCR := PortBases[ComPort]+3;
        Bufs[ComPort].UART_MCR := PortBases[ComPort]+4;
        Bufs[ComPort].UART_LSR := PortBases[ComPort]+5;
        Bufs[ComPort].UART_MSR := PortBases[ComPort]+6;

       {This next section sees if there is already an interrupt vector set for
        a shared interrupt com port.  For instance COM1 and COM3 both use
        interrupt 4 and COM2 and COM4 use interrupt 3.  If we are setting up
        COM1, but COM3 is already up and running we don't need to do anything
        since the interrupt service routine (Procedure COM_ISR) will
        automatically check the com ports on it's interrupt}

       InUse:= False;
       For Ktr:= 1 to 4 Do
          If (Interrupts[Ktr] = Interrupts[ComPort]) And Bufs[Ktr].Active Then
             InUse:= True;

       {This next section is run if, and only if a shared interrupt is not
        currently running.}

       InLine(Disable_Interrupts);

       If Not InUse Then Begin
          {Get the old DOS interrupt vector, save it then change it to point
           to the COM_ISR procedure in this unit}
          Port[$21] := Port[$21] Or (1 SHL Interrupts[ComPort]);
          GetIntVec(8+Interrupts[ComPort],Bufs[ComPort].Org_Vector);
          SetIntVec(8+Interrupts[ComPort],@COM_ISR);
          Port [$21] := Port [$21] AND NOT (1 SHL Interrupts[ComPort]);
       End;

       Bufs[ComPort].Old_MCR:= Port[Bufs[ComPort].UART_MCR]; {Store MCR        }
       Port[Bufs[ComPort].UART_LCR]:= 3; {Parity to none and turn off the break}
       PORT[Bufs[ComPort].UART_IER]:= 1; {Enable data recieved interrupts      }

       InLine(Enable_Interrupts);

       Bufs[ComPort].Active:= True;      {Let COM_ISR know to check this port  }
    End;

    Procedure Com_Port.SetParam(Baud: Longint; WordSize: Byte;
                                 Parity: Char; StopBits: Byte);

    Const
          MaxBaud      = 115200;  {Maximum baud rate                            }

    Var Divisor: Word;
        lcr    : Byte;

    {Sets the baud rate, wordsize, parity, and stop bits used by the port.  The
     most common setting especially with high speed modems is 38400 baud, word
     size is 8 bits (one byte), 'N' or no parity, and one stop bit.  Compuserve
     uses 7 bits and even parity.}

    Begin

       {This next section sets the baud rate based on the divisor of MAXBAUD}

       If Baud < 50 Then Baud:= 50;
       If Baud > MaxBaud Then Baud:= MaxBaud;
       Divisor:= MaxBaud Div Baud;
       InLine(Disable_Interrupts);
       Port [Bufs[CPort].uart_lcr ]:= Port[Bufs[Cport].uart_lcr] Or $80;
       Portw[Bufs[CPort].uart_Data]:= divisor;
       Port [Bufs[CPort].uart_lcr] := Port[Bufs[CPort].uart_lcr] And NOT $80;
       InLine(Enable_INterrupts);

       {This next section sets the parity}

       Case upcase(Parity) Of
          'N': lcr:= $00 or $03;
          'E': lcr:= $18 or $02;
          'O': lcr:= $08 Or $02;
          'S': lcr:= $38 Or $02;
          'M': lcr:= $28 OR $02;
          Else
             Lcr:= $00 or $03;
       End;
       If StopBits = 2 Then lcr:= Lcr OR $04;

       InLine(Disable_Interrupts);
       Port[Bufs[CPort].Uart_lcr]:= Port[Bufs[CPort].uart_lcr] And $40 Or LCR;
       InLine(Enable_Interrupts);
    End;

    Procedure Com_Port.Done;

    {Use this procedure when you are done with your program.  You >MUST< run
     this procedure for each COM variable you have initialized.  If you don't
     if any data comes in to the comm port DOS will still try to go to the
     place where the COM_ISR >>>USED<<< to be!  Meaning your computer >COULD<
     crash.  Since this is an OOP approach exit-proc wasn't used since there
     could be any number of variables open and running.  Therefore it is YOUR
     responsibility to call this procedure for each COM_PORT object you have
     created}

    Var InUse: Boolean;     {Scratch variable to test for shared interrupt}
        Ktr  : byte;        {Counter variable                             }

    Begin
       {Check for shared interrupt usage}

       InUse:= False;
       For Ktr:= 1 to 4 Do
          If (Interrupts[Ktr] = Interrupts[CPort]) And Bufs[Ktr].Active Then
             InUse:= True;

       InLine(Disable_interrupts);

       {Restore the old Modem Control Register and disable incomming data
        interrupts}
       Port[Bufs[CPort].UART_MCR] := Bufs[CPort].Old_MCR;
       Port[Bufs[CPort].UART_IER] := 0;

       If Not InUse Then Begin
          {Remove the interrupt only if another object is not using it}
          Port[$21] := Port[$21] Or ($01 SHR Interrupts[CPort]);
          SetIntVec(8+Interrupts[CPort],Bufs[CPort].Org_Vector);
       End;

       InLine(Enable_Interrupts);

       CPort:= 0;                {Set CPort variable to 0     }

       {Release the buffer memory and set the active flag to false}
       Freemem(Bufs[CPort].R_Buffer,Bufs[CPort].R_Size);
       Freemem(Bufs[CPort].T_Buffer,Bufs[CPort].T_Size);
       Bufs[CPort].Active:= False;
    End;

    Function Com_Port.Read: Char;

    {If a character is available on the buffer, this procedure will return the
     char.  If there is no character, char 0 (#0) will be returned.  If you
     expect #0 to be passed as part of the data call this routine only if
     function waiting returns true, or use readw - which will wait for
     a character from the com port if nothing is available}

    Begin
       With Bufs[CPort] Do Begin
          If R_Head = R_Tail Then Begin  {Nothing in the buffer}
             Read:= #0;
          End Else Begin                 {Data waiting in the buffer}
             Read:= R_Buffer^[R_Head];          {Get the waiting character}
             Inc(R_Head);                       {Increment the queue pointer}
             If R_Head > R_Size Then R_Head:= 0; {Check for out of range}
          End;
       End;
    End;

    Function Com_Port.Readw: Char;

    {Waits for a character from the comm port if none are available.  Passes
     back the first character it finds in the recieve buffer}

     Begin
        With Bufs[CPort] Do Begin
           While R_Head = R_Tail Do;
           Readw:= R_Buffer^[R_Head];
           Inc(R_Head);
           If R_Head > R_Size THen R_Head:= 0;
        End;
     End;

    Function Com_Port.Waiting: Boolean;

    {This function returns TRUE if there is data waiting in the recieve buffer}

    Begin
       Waiting:= (Bufs[CPort].R_Head <> Bufs[CPort].R_Tail);
    End;

    Procedure Com_Port.Enable;

    {This should be the third command you run after .INIT and .SETPARAM.  Enable
     and Disable are provided for multi-port use.  If you are using com1 and
     com2 together you can leave both ports enabled at the same time, likewise
     with com3 and com4.  However ports that share interrupts (Com1 & Com3)
     (com2 & com4) can not both be enabled at the same time.  This is the reason
     I wrote this unit because the most popular pascal com libraries
     (particularly the async libraries by rising sun which are otherwise
     extrodinarilly compitent packages) could not handle shared interrupts.
     This unit can, but it cheats by allowing you to "suspend" one of the ports
     on the shared interrupt.  While a port is suspended (disabled) you can not
     send or recieve data from that port.  Other considerations - a mouse on
     com1 will not work with this package when you use com3, likewise a mouse
     on com2 will not work when you run com4 this is because this package
     installs it's own interrupts - overwriting the mouse ports (although the
     mouse will begin working again once you call .DONE}

    Begin
       InLine(Disable_interrupts);
       Port[Bufs[CPort].Uart_MCR]:= 11;
       InLine(Enable_Interrupts);
    End;

    Procedure Com_Port.Disable;

    {Call this procedure only if you are about to enable another port which
     uses the same interrupt, see COM_PORT.Enable for more information}

    Begin
       InLine(Disable_interrupts);
       Port[Bufs[CPort].Uart_MCR]:= 3;
       InLine(Enable_Interrupts);
    End;

    Procedure Com_Port.Write(C: Char);

    {This procedure places a character on the transmit buffer}

    Begin
       With Bufs[CPort] Do Begin
          T_Buffer^[T_Tail]:= C;
          Inc(T_Tail);
          If T_Tail > T_Size Then T_Tail:=0;
          If (T_Tail = T_Head) Then Begin
             Inc(T_Head); {Overflow}
             If T_Head > T_Size Then T_Head:=0;
          End;
          InLine(Disable_interrupts);
          {Tell the modem to alert us when it is OK to send data}
          Port[UART_IER]:= Port[UART_IER] Or 2;
          InLine(Enable_Interrupts);
       End;
    End;

    Procedure Com_Port.WriteS(S: String);

    {Passes a string to the transmit buffer}

    Var Ktr: Byte;

    Begin
       For Ktr:= 1 to Length(S) Do
          Write(S[Ktr]);
    End;

    Procedure Com_Port.Break;

    {This procedure sends a >BREAK< signal down the line.  It is usefull
     primarilly for mainframe and unix based systems, DOS based machines
     do not look for or respond to the break signal.}

    Var
       Org_Data: byte;

    Begin
       InLine(Disable_Interrupts);
       With Bufs[CPort] Do Begin
          Org_Data:= Port[UART_LCR];   {Save the contents of the LCR            }
          Port[UART_LCR]:= 255;        {Load up the Line Control Register       }
          Delay(3);                    {CRT unit - Delay 3 thousands of a second}
          Port[UART_LCR]:= Org_Data;   {Restore the Line Control Register       }
       End;
       InLine(Enable_Interrupts);
    End;

    Function Com_Port.OnLine: Boolean;

    {This function returns TRUE if the Modem Status Register indicates a Data
     carrier detect signal.  Note that some modems always return true even when
     not connected, an AT command is needed to force DCD to return the true state
     of the modem.  Also note that some direct serial connections (I.E. no modem
     but hardwired to another machine, may not return the correct DCD stat or
     may be false even when connected - this is particularly true of three wire
     direct serial connections (pins 2, 3, and 7 wired all others unwired)}

    Begin
        OnLine := (Port[Bufs[CPort].UART_MSR] And $80) > 0;
    End;

    Procedure Com_Port.Hangup;

    {This procedure disconects the modem by lowering the DTR signal.  Note that
     some modems may not be affected by this procedure based on their AT
     configurations.  Direct serial lines are not usually affected by this
     signal.  Your best bet is to issue this command then send '+++' to the modem
     and wait five seconds and then issue 'ATH<return>'}

    Var Org_MCR: Byte;  {Scratch var to store the original MCR stuff}

    Begin
      With Bufs[CPort] Do Begin
         Org_Mcr := Port[UART_MCR];
         Port[UART_MCR]:= Org_MCR Or $FE;  {Lower the DTR signal  }
         Delay(100);                       {Delay 100 ms          }
         Port[UART_MCR]:= Org_MCR;         {Restore the DTR Signal}
      End;
    End;

    Var Ktr: Byte;

    Begin

       {Initialize the 4 comm buffers to an inactive state, this code is run
        the moment you start the program, automatically}

       For Ktr:= 1 to 4 Do Begin
          Bufs[Ktr].Active  := False;
          Bufs[Ktr].R_Buffer:= Nil;
          Bufs[Ktr].R_Head  := 0;
          Bufs[Ktr].R_Tail  := 0;
          Bufs[Ktr].R_Size  := 0;
          Bufs[Ktr].T_Buffer:= Nil;
          Bufs[Ktr].T_Head  := 0;
          Bufs[Ktr].T_Tail  := 0;
          Bufs[Ktr].T_Size  := 0;
       End;
    End.

    {This area is ignored by turbo pascal}

    Sample program:

    Program Sample;

    Uses Async,CRT;

    Var
       C: Char;
       Com1: Com_Port;

    Begin
       Com1.Init(1,10000,10000);            {Set up the buffers & Interrupt    }
       Com1.SetParam(38400,8,'N',1);        {Set up the baud,ws,parity,&stopbts}
       Com1.Enable;                         {Enable the com port               }
       C:= ' ';                             {Initialize the scratch variable   }
       WriteLn('Press ESC to exit dumb terminal');
       Loop
          If Keypressed Then Begin
            C:= Readkey;
            If C <> #27 Then Com1.Write(C);
         End;
         If Com1.Waiting Then Write(Com1.Read);
      Until C = #27;
      Com1.Done;
    End.
    }

    {An explination of the UART data areas   The PORT address is offset by the
     numbers.  So if you're on com1 and com1 as at 3f8, the uart_IER address is
     at port address 3f8+1, uart_iir is 3f8+2, etc}

          uart_data    = 0;       {Uart Data Offset                             }
                                     {Transmit/Recieve Data area                }
          uart_ier     = 1;       {Uart Interrupt Enable Register               }
                                     {Bits 7-4 always 0                         }
                                     {Bit    3  1 = enable change in modem stat }
                                     {Bit    2  1 = enable line-status interrupt}
                                     {Bit    1  1 = enable transmit reg empty   }
                                     {Bit    0  1 = data available interrupt    }
          uart_iir     = 2;       {Uart Interrupt Identification Register       }
                                     {Bits 7-3 always 0                         }
                                     {Bits 2-1 01 = transmit - register empty   }
                                     {         10 = data available              }
                                     {         11 = line status                 }
                                     {Bit    0  1 = No Interrupt pending        }
                                     {          0 = Interrupt Pending           }
          uart_lcr     = 3;       {Uart Line Control Register}
                                     {Bit    7  0 = Normal, 1=Address Baud rate }
                                     {Bit    6  0 = break disabled, 1 enabled   }
                                     {Bit    5  0 = Don't force parity          }
                                     {          1 = if bit 4-3 = 01 parity = 1  }
                                     {              if bit 4-3 = 11 parity = 0  }
                                     {              if bit   3 = 0 no parity    }
                                     {Bit    4  0 = odd parity,1=even parity    }
                                     {Bit    3  0 = no parity, 1=parity         }
                                     {Bit    2  0 = 1 stop bit                  }
                                     {          1 = 1.5 stop bits if 5bits/char }
                                     {              or 2 stop bits if 6-8 bits  }
                                     {Bits 1-0 00 = 5 bits/character            }
                                     {         01 = 6 bits/character            }
                                     {         10 = 7 bits/character            }
                                     {         11 = 8 bits/character            }
          uart_mcr     = 4;       {Uart Modem Control Register                  }
                                     {Bits 7-5 always 0                         }
                                     {Bit    4  0=normal,1=loop back test       }
                                     {Bit    3  1=interrupts to system bus      }
                                     {Bit    2  user designated output          }
                                     {Bit    1  1=active rts                    }
                                     {Bit    0  1=active dtr                    }
          uart_lsr     = 5;       {Uart line status register                    }
                                     {Bit    7  always 0                        }
                                     {Bit    6  1=transmit shift reg is empty   }
                                     {Bit    5  1=transmit hold reg is empty    }
                                     {Bit    4  1=break recieved                }
                                     {Bit    3  1=framing error recieved        }
                                     {Bit    2  1=parity error recieved         }
                                     {Bit    1  1=overrun error recieved        }
                                     {Bit    0  1=data received                 }
          uart_msr     = 6;       {Uart Modem Status Register                   }
                                     {Bit    7  1=recieve line signal detect    }
                                     {Bit    6  1=ring indicator                }
                                     {Bit    5  1=data signal ready             }
                                     {Bit    4  1=clear to send                 }
                                     {Bit    3  1=recieve line signal change    }
                                     {Bit    2  1=ring indicator has changed    }
                                     {Bit    1  1=dsr has changed state         }
                                     {Bit    0  1=cts has changed state         }

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