Module KermitLineIO; { This module contains routines to manage the RS232 communication port: { Character and packet level IO, status management etc. } {=============================} Exports {====================================} imports KermitGlobals from KermitGlobals; const R4AndAbove = False; { Conditional compilation switch: } { Generate versions for R.4, R.5 etc. } DelayTime = 0.01; { length of delay interval 10 ms } { -- Status and parameter maintenance -- } procedure InitLine; procedure CleanupLine; procedure RefreshParity; procedure RefreshBaud; procedure RefreshStopBits; procedure ShowStatus; { -- Miscellaneous utilities -- } procedure FlushBuffer( Idev : integer ); procedure SetTimer( Time : integer ); { -- Character level IO routines -- } procedure Outbt( Odev : integer; Ch : char ); function GetChar( Idev : integer; var InCh : char ) : boolean; function Inbt( Idev : integer ) : char; procedure SendBreak( NumMSecs : integer ); { -- Packet level IO routines -- } procedure SendPacket ( sptype : PacketType; num : integer; len : integer; VAR data : Packet ); function ReadPacket ( var num : integer; var len : integer; var data : Packet ) : PacketType; exception IOWrErr( IOStatus : integer ); { Write or read error } exception IORdErr( IOStatus : integer ); { during OUTBT/INBT } exception BadIdev( Idev : integer ); exception TimeOutExit; { Inbt timed out } exception BadChar; { Is raised when a character which is not a SOH } { or a printable data character is encountered. } { Must be handled by a "do nothing" handler if INBT } { is to be used as a general purpose character input } { routine. } {===========================} Private {====================================} const CountDwn = 45; { countdown for 10 ms DelayTime, will have to be adjusted if Inbt is modified } imports KermitParameters from KermitParameters; imports KermitScreen from KermitScreen; imports IOErrMessages from IOErrMessages; imports IOErrors from IOErrors; imports IO_Unit from IO_Unit; imports Screen from Screen; imports IO_Others from IO_Others; imports IO_Private from IO_Private; imports UtilProgress from UtilProgress; {************************** Status and parameters ************************} var InitRSI,InitRSO,RSStatus : DevStatusBlock; procedure InitLine; begin Idev := RS232In; Odev := RS232Out; Parity := EvenKparity; Baud := Sp4800; StopBits := Stop2Cmd; IOGetStatus( RS232Out, InitRSO); IOGetStatus( RS232In, InitRSI); with RSStatus do begin ByteCnt := 3; RSRcvEnable := true; RSFill := 0; RSSpeed := RS4800; RSParity := EvenParity; RSStopBits := Stop2; RSXmitBits := Send7; RSRcvBits := Rcv7; end; IOPutStatus(RS232Out,RSStatus); IOPutStatus(RS232In,RSStatus); ShowStatus; end; { InitLine } {==========================================================================} procedure CleanupLine; begin IOPutStatus(RS232Out, InitRSO); IOPutStatus(RS232In, InitRSI); end; {==========================================================================} procedure RefreshParity; procedure SetNoParity; begin with RSStatus do begin RSXmitBits := Send8; RSRcvBits := Rcv8; RSParity := NoParity; end; end; procedure SetEvenParity; begin with RSStatus do begin RSXmitBits := Send7; RSRcvBits := Rcv7; RSParity := EvenParity; end; end; procedure SetOddParity; begin with RSStatus do begin RSXmitBits := Send7; RSRcvBits := Rcv7; RSParity := OddParity; end; end; procedure SetMarkParity; begin with RSStatus do begin RSXmitBits := Send8; RSRcvBits := Rcv8; RSParity := NoParity; end; end; procedure SetSpaceParity; begin with RSStatus do begin RSXmitBits := Send8; RSRcvBits := Rcv8; RSParity := NoParity; end; end; begin case Parity of NoParComm : ; NoKParity : SetNoParity; OddKParity : SetOddParity; EvenKParity : SetEvenParity; MarkKParity : SetMarkParity; SpaceKParity : SetSpaceParity; end; IOPutStatus(RS232In,RSStatus); IOPutStatus(RS232Out,RSStatus); ShowStatus; end; { RefreshParity } {==========================================================================} procedure RefreshBaud; begin with RSStatus do case Baud of SP110 : RSSpeed := RS110; SP150 : RSSpeed := RS150; SP300 : RSSpeed := RS300; SP600 : RSSpeed := RS600; SP1200 : RSSpeed := RS1200; SP2400 : RSSpeed := RS2400; SP4800 : RSSpeed := RS4800; SP9600 : RSSpeed := RS9600; NoSpeed : ; end; IOPutStatus(RS232In,RSStatus); IOPutStatus(RS232Out,RSStatus); ShowStatus; end; { RefreshBaud } {==========================================================================} procedure RefreshStopBits; begin with RSStatus do case StopBits of SyncrCmd: RSStopBits := Syncr; Stop1Cmd: RSStopBits := Stop1; Stop1x5Cmd: RSStopBits := Stop1x5; Stop2Cmd: RSStopBits := Stop2; otherwise: ; end; IOPutStatus( RS232In, RSStatus ); IOPutStatus( RS232Out, RSStatus ); ShowStatus; end; { RefreshStopBits } {==========================================================================} procedure ShowStatus; var OldWindow : WinType; begin CurrentWindow( OldWindow ); SwitchWindow( StatusWindow ); with RSStatus do begin SPutChr(FF); { clear window } writeln; write(' Speed = '); case RSSpeed of RS110 : write(' 110'); RS150 : write(' 150'); RS300 : write(' 300'); RS600 : write(' 600'); RS1200 : write('1200'); RS2400 : write('2400'); RS4800 : write('4800'); RS9600 : write('9600'); end; writeln(' baud'); write(' Parity = '); case RSParity of NoParity : write('None '); OddParity : write('Odd '); IllegParity : write('Illeg'); EvenParity : write('Even '); end; writeln; write(' Send bits = '); case RSXMitBits of Send5 : write('5'); Send7 : write('7'); Send6 : write('6'); Send8 : write('8'); end; writeln; write(' Rcv. bits = '); case RSRcvBits of Rcv5 : write('5'); Rcv7 : write('7'); Rcv6 : write('6'); Rcv8 : write('8'); end; writeln; write(' Stop bits = '); case RSStopBits of Syncr : write('Syncr. (No stop bits)'); Stop1 : write('1'); Stop1x5 : write('1.5'); Stop2 : write('2'); end; end; SwitchWindow( OldWindow ); end; {==========================================================================} {************************* Utilities **************************************} procedure FlushBuffer( Idev : integer ); var dummy : char; Istat : integer; begin repeat Istat := IOCRead( Idev, dummy ); if not (Istat in [IOEIOC,IOEIOB]) then begin DbgWrite( 'Unexpected read error on flush of input buffer:' ); DbgInt( Istat ); DbgNL; DbgWrite( IOErrString( Istat ) ); DbgNL; raise IORdErr( Istat ); end; until Istat=IOEIOB; end; {==========================================================================} var TimeCounter, NumIntval : integer; procedure SetTimer( Time : integer ); { Set up timeout counters: Will generate timeout after Inbt has been called repeatedly for about