home *** CD-ROM | disk | FTP | other *** search
- {$R-,I-,S-}
- unit SERINOUT;
-
- interface
-
- uses Time,Dos;
-
- Const SerTimeOut :Longint =5; { in 0.5 sec Intervallen}
- DSR_Handshake:Boolean=true;
- CTS_Handshake:Boolean=false;
- XonXoff :Boolean=false;
- X_on =$11;
- X_off=$13;
-
-
-
- type
- ParityType=(Nopar,Oddpar,EvenPar);
-
- procedure SetSeriell(S_port:Word;
- BaudRate,StopBits,DataBits:Byte;Parity: Paritytype);
- {Baudrate 96 =9600}
-
- FUNCTION BusyRead (VAR ch : CHAR ): BOOLEAN;
-
- Function InSerPort(Var Error:Byte):Byte;
-
- procedure OutSerPort(C:Byte;Var Error :Byte);
-
-
- implementation
-
- Const TX_buffer =0;
- RX_buffer =0;
- Div_latch_L =0;
- Int_Enable=1;
- Div_latch_H =1;
- Int_Ident =2;
- Line_Ctrl =3;
- Modem_Ctrl=4;
- Line_Stat=5;
- Modem_Stat=6;
- RTS_DTR_On = $03;
- InitModemCtrl = $08; { set Out2, reset RTS DTR }
- EnableComInt = $01; { enable error and receive CHR }
- DisableComInt = $00; { disable interrupt 8250 }
-
- baseIO :Word=$3F8; { Com1}
- ActualPort:Word=0;
- Wait_Xon :Boolean=false;
-
- VAR StoreOldComInt : Pointer;
- ExitSave : POINTER; { Store old exitproc }
- { ComBuffer declarations: }
-
- CONST
- ComBufferSize = $100; { 256 Byte default buffer }
- ComBufferEnd = $0FF; { ComBufferSize - 1 }
- ComBufferFull : BOOLEAN = FALSE; { set to TRUE if buffer full }
- ComInIndx : INTEGER = 0; { input index to comm buffer }
- ComOutIndx : INTEGER = 0; { output index to comm buffer }
-
- VAR ComBuffer : ARRAY [0..ComBufferEnd] OF BYTE;
-
- CONST
- RS232installed : BOOLEAN = FALSE; { TRUE if interrupthandler active }
- ComUtilByte : BYTE = $00; { intermediate buffer variable }
- ComAuxInIndx : INTEGER = 0; { utlity variable for INT handler }
-
- { 8259 interrupt controller }
- CONST
- i8259ContrWord1 = $21; { Control Word 1 }
- i8259ContrWord2 = $20; { Control Word 2 }
- i8259EOFintrupt = $20; { signal END of interrupt }
-
- Rs232cDevNr : BYTE = $04; { Interrupt Mask Bit Nr for COM1 }
-
- VAR i8259Status : BYTE; { store device status }
-
- { 8250 communication controller }
- CONST
- CommInt : Byte =$0C; { Comm INT for COM1, use 0B for COM2 }
- { registers 8250 if COM1 used. Use 3F0 for COM1 and 2F0 for COM2 }
-
-
- Var OutTimeoutCnt :Longint;
- InTimeOutCnt :Longint;
- IoBaseTab :Array[1..4] of word absolute $0:$400;
-
-
- Procedure Ints_Freigabe;
- inline($FB); { sti }
-
- Procedure Ints_Sperre;
- inline($FA); { Cli }
-
- {$F+}
- PROCEDURE ComIntHandler; { never call this procedure }
- { it is an interrupt handler }
- INTERRUPT;
- BEGIN
- Ints_Freigabe;
- ComUtilByte := PORT[BaseIo{+Rx_buffer}];
- If ComUtilByte=X_on then Wait_xon:=false;
- If ComUtilByte=X_off then Wait_xon:=true;
- ComAuxInIndx := (ComInIndx+1) MOD ComBufferSize;
- IF ComAuxInIndx<>ComOutIndx THEN BEGIN
- ComBuffer[ComInIndx] := ComUtilByte;
- ComInIndx := ComAuxInIndx;
- END
- ELSE ComBufferFull := TRUE;
- PORT[i8259ContrWord2] := i8259EOFintrupt;
- Ints_Sperre;
- END; { ComIntHandler }
-
- PROCEDURE DeInstallComInt;
- BEGIN
- IF NOT RS232installed THEN EXIT;
-
- PORT[BaseIo+int_Enable] := DisableComInt; { disable interrupt in 8250 }
- PORT[BaseIo+Modem_Ctrl] := 00;
-
- i8259Status := PORT[i8259ContrWord1]; { disable interrupt in 8259 }
- PORT[i8259ContrWord1] := (i8259Status or ($01 shl Rs232cDevNr));
- SetIntVec(CommInt,StoreOldComInt); { restore old intvector }
- RS232installed := FALSE;
- ExitProc := ExitSave;
- END; { DeInstallComInt }
- {$F-}
-
-
- FUNCTION BusyRead (VAR ch : CHAR ): BOOLEAN;
-
- BEGIN
- IF ComInIndx<>ComOutIndx THEN BEGIN
- ch := CHR(ComBuffer[ComOutIndx]);
- ComOutIndx := (ComOutIndx + 1) MOD ComBufferSize;
- BusyRead := TRUE;
- END
- ELSE BEGIN
- ch := #0;
- BusyRead := FALSE;
- END;
- END; { BusyRead }
-
-
- procedure SetSeriell(S_port :word;
- BaudRate,StopBits,DataBits:Byte;Parity: Paritytype);
- var Divisor :Word;
- Control :Byte;
- begin
- S_port:=Succ(Pred(S_port) and 3);
- If (ActualPort<>S_port) then DeinstallComInt;
- ActualPort:=S_port;
- If IobaseTab[1]=0 then IobaseTab[1]:=$3F8;
- If IobaseTab[2]=0 then IobaseTab[2]:=$2F8;
- If IobaseTab[3]=0 then IobaseTab[3]:=$3E8;
- If IobaseTab[4]=0 then IobaseTab[4]:=$2E8;
- baseIo:=IobaseTab[S_port];
-
- { Get Port Address of Port 1 through 4 }
-
- Wait_Xon:=false;
- If Not Odd(S_port) then
- begin
- Rs232cDevNr := $03; { Interrupt Mask Bit Nr for COM2/4 }
- CommInt := $0B; { Comm INT for COM2 }
- end
- else
- begin
- Rs232cDevNr := $04; { Interrupt Mask Bit Nr for COM1/3 }
- CommInt := $0C; { Comm INT for COM1 }
- end;
- PORT [BaseIo+Int_Enable] := DisableComInt;
- PORT [BaseIo+Modem_Ctrl] := InitModemCtrl;
- IF Not Rs232installed THEN { you have to deinstall it first! }
- begin
- GetIntVec(CommInt,StoreOldComInt);
- SetIntVec(CommInt,@ComIntHandler); {Set own intvector }
- IF ((PORT[BaseIo+Line_Stat] and $01) = $01) { clear the controler }
- THEN ComUtilByte := PORT[BaseIo{+ Rx_buffer}];
- i8259Status := PORT[i8259ContrWord1]; { enable device interrupt }
- PORT[i8259ContrWord1] := (i8259Status AND (NOT($01 shl Rs232cDevNr)));
- RS232installed := TRUE;
- ExitSave := ExitProc;
- ExitProc := @DeInstallComInt;
- end;
- case BaudRate of
- 3: Divisor:=$180;
- 6: Divisor:=$C0;
- 12:Divisor:=$60;
- 24:Divisor:=$30;
- 48:Divisor:=$18;
- 192:Divisor:=$06;
- else Divisor:=$0C;
- end;
- Stopbits:=(Stopbits shr 1) and 1;
- Databits:=3 xor (Databits and 1);
- Control:=(StopBits Shl 2)+DataBits;
- case Parity of
- oddpar: Control:=Control+8;
- evenpar: Control:=Control+24;
- end;
- Ints_Sperre;
- ComBufferFull := FALSE; { reset ComBuffer }
- ComInIndx := 0;
- ComOutIndx := 0;
- Port[BaseIo+Line_Ctrl]:=$80;
- Port[BaseIo { +Div_latch_L } ]:=Lo(Divisor);
- Port[BaseIo+Div_latch_H]:=Hi(Divisor);
- Port[BaseIo+Line_ctrl]:=Control;
- Port[BaseIo+Modem_ctrl]:=InitmodemCtrl+RTS_DTR_on;
- PORT[BaseIo+int_Enable] := EnableComInt; { enable ComInt in 8250 }
- Ints_Freigabe;
- end;
-
- Function InSerPort(Var Error:Byte):Byte;
- var T :LongInt;
- NoTout :Boolean;
- ModemCt,LineSt :Word;
- N :Word;
- Ch :Char;
-
- begin
- InSerPort:=0;
- LineSt:=BaseIo+Line_Stat;
- ModemCt:=BaseIo+Modem_Ctrl;
- T:=Time_Ms;
- N:=0;
- NoTout:=true;
- Ints_Sperre;
- Port[ModemCt]:=RTS_DTR_on+InitModemCtrl; {Setze DTR,RTS auf High}
- { empfangsbereit }
- While NoTout and Not(BusyRead(Ch)) Do
- { Warte bis Zeichen da }
- begin
- Inc(N,1);
- If (N and $3FF)=0 then
- NoTout:=Time_Ms-T<SerTimeout*500;
- end;
- IF NoTout Then
- begin
- InserPort:=Ord(Ch);
- Error:=Port[LineSt] and $1E;
- end
- else Error:=$80;
- Port[ModemCt]:=InitModemCtrl; {Setze DTR,RTS auf Low}
- end;
-
- procedure OutSerPort(C:Byte;Var Error :Byte);
- var T :LongInt;
- NoTout :Boolean;
- NoXonOff:Boolean;
- N,
- LineSt,
- ModemSt :Word;
-
- begin
- LineSt:=BaseIo+Line_Stat;
- ModemSt:=BaseIo+Modem_Stat;
- N:=0;NoTout:=true;
- T:=Time_Ms;
- Error:=0;
- While ((DSR_Handshake and ((Port[ModemSt] and $20)=0)) or
- ( CTS_Handshake and ((Port[ModemSt] and $10)=0)) or
- ( XonXoff and Wait_xon ) or
- ((Port[LineSt] and $60)<>$60)) { Transmitter empty}
- and NoTout Do
- begin
- Inc(N,1);
- If (N and $3FF)=0 then
- NoTout:=Time_Ms-T<SerTimeout*500;
- end;
- IF NoTout Then
- Port[BaseIo { +Tx_Buffer} ]:=C
- else Error:=$80;
- end;
-
-
- end.
-