home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
c
/
qk3mdm.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
2020-01-01
|
12KB
|
280 lines
Unit Modempro ;
(* ================================================================= *)
(* MODEM - Routines and Global variables for IBMPC compatiables. *)
(* ================================================================= *)
Interface
Uses Dos,Crt, (* Standard Turbo Pascal Units *)
KGlobals ; (* Kermit Globals - Execution control Flags *)
Type
ParityType = (OddP,EvenP,MarkP,NoneP) ;
Const
DefaultBaud = 9600 ;
Var
PrimaryPort : Boolean ;
Baudrate : Integer ;
Parity : ParityType ;
Procedure Initmodem ;
Procedure ResetModem;
Procedure SetModem ;
Procedure AnswerModem ;
Procedure DialModem ;
Function RecvChar (var mchar : byte) : boolean ;
Function CharsInBuffer : integer ;
Procedure EmptyBuffer ;
Procedure SendChar (char : byte ) ;
Procedure SendBreak ;
(* ================================================================= *)
Implementation
CONST
(* Modem Registers *)
LowOrderDiv = 0 ;
HiOrderDiv = 1 ; InterruptEnable = 1 ;
InterruptIdReg = 2 ;
LineControlReg = 3 ;
ModemControlReg = 4 ;
LineStatusReg = 5 ;
ModemStatusReg = 6 ;
ClockRate = 18430 ; (* CentiHertz. - use 17895 for PCjr *)
(* 8259 Interrupt Controller addresses *)
(* IC8259Reg1 = $20 ; IC8259Reg2 = $21 ; *)
MaxBuffsize = 32760 ;
VAR
Modem : Integer ;
IntNumber,
EnableMask,ResetMask,SaveMask : byte ;
DSRcheck : boolean ;
OldVector : pointer ;
Iout,Iin : integer ;
Buffer : Packed array [1..MaxBuffsize] of byte ;
(* ------------------------------------------------------------------ *)
(* IntHandler - Interrupt handler *)
(* This procedure handles the modem interrupts , *)
(* which occur for incomming data only. *)
(* ------------------------------------------------------------------ *)
Procedure IntHandler ;
Interrupt ;
Begin (* IntHandler *)
Inline($FB) ; (* STI set interrupt enable *)
While (Port[Modem+LineStatusReg] and $01) = $01 do
begin (* put char in buffer *)
buffer[Iin] := Port[Modem];
Iin := Iin + 1 ;
if Iin = MaxBuffsize then Iin := 1 ;
end ; (* put char in buffer *)
Port[$20] := ResetMask ;
End ; (* IntHandler *)
(* ------------------------------------------------------------------ *)
(* InitModem - Initialize the modem and setup interrupt procedure. *)
(* ------------------------------------------------------------------ *)
Procedure Initmodem ;
Var rate : integer ;
Begin (* Init modem *)
If PrimaryPort then
Begin (* Primary port *)
Modem := $3F8 ;
EnableMask := $EF ;
ResetMask := $64 ; (* end of interrupt for IRQ4 *)
IntNumber := 12 ;
End (* Primary Port *)
else
Begin (* Secondary Port *)
Modem := $2F8 ;
EnableMask := $F7 ;
ResetMask := $63 ; (* end of interrupt for IRQ3 *)
IntNumber := 11 ;
End ; (* Secondary Port *)
Iin := 1 ; Iout := 1 ;
(* Initialize the Serial port Interrupt Procedure *)
GetIntVec(IntNumber,Oldvector) ; (* save the Old interrupt handler *)
SetIntVec (IntNumber,@IntHandler) ; (* Use our own interrupt handler *)
SaveMask := Port[$21] ; (* save setting *)
Port[$21] := Port[$21] and EnableMask ; (* Enable serial port interrupt *)
Port[$20] := ResetMask ;
(* Initialize baud rates and bits and parity *)
Rate := round( (Clockrate/16) / (Baudrate/100)) ;
Port[Modem+LineControlReg] := $80 ; (* Enable baud rate setting *)
Port[Modem+LowOrderDiv] := (rate and $00FF) ;
Port[Modem+HiOrderDiv] := rate div $100 ;
Port[Modem+LineControlReg] := (ord(Parity) shl 4) OR $0A ;
(* parity, 7 bits,1 stop *)
Port[Modem+ModemControlReg] := $0B ; (* set OUT2, DTR ,RTS *)
Port[Modem+InterruptEnable] := $01 ; (* Data Avail. Interrupt set *)
End ; (* Init modem *)
(* ------------------------------------------------------------------ *)
(* ResetModem - Reset the Interrupt back to the original. *)
(* Global variables - Saveoffset,SaveSeq *)
(* ------------------------------------------------------------------ *)
Procedure ResetModem;
Begin (* Reset Modem Interrupt *)
SetIntVec(IntNumber,Oldvector) ; (* restore the Old interrupt handler *)
Port[$21] := SaveMask ;
Port[Modem+InterruptEnable] := $00 ; (* Data Avail. Interrupt reset *)
End; (* Reset Modem Interrupt *)
(* ------------------------------------------------------------------ *)
(* SetModem - Set the baud rate and parity for modem. *)
(* Global variables - Modem,Clockrate,Baudrate,Parity *)
(* ------------------------------------------------------------------ *)
Procedure SetModem ;
Var rate : integer ;
Begin (* SetModem *)
If PrimaryPort then
Begin (* Primary port *)
Modem := $3F8 ;
EnableMask := $EF ;
ResetMask := $64 ; (* end of interrupt for IRQ4 *)
End (* Primary Port *)
else
Begin (* Secondary Port *)
Modem := $2F8 ;
EnableMask := $F7 ;
ResetMask := $63 ; (* end of interrupt for IRQ3 *)
End ; (* Secondary Port *)
Rate := round( (Clockrate/16) / (Baudrate/100)) ;
Port[Modem+LineControlReg] := $80 ; (* Enable baud rate setting *)
Port[Modem+LowOrderDiv] := (rate and $00FF) ;
Port[Modem+HiOrderDiv] := rate div $100 ;
Port[Modem+LineControlReg] := (ord(Parity) shl 4) OR $0A ;
(* parity, 7 bits,1 stop *)
End ; (* SetModem *)
(* ------------------------------------------------------------------ *)
(* DialModem - Check and waits for modem to be connected. *)
(* It waits for DSR signals be detected. *)
(* Side Effect - global variable 'connected' is set true. *)
(* ------------------------------------------------------------------ *)
Procedure DialModem ;
var i : integer ;
Begin (* Dial Modem *)
While ((Port[Modem+ModemStatusReg] and $20) <> $20) and DSRcheck Do
Begin (* Connect modem please *)
(* writeln('modem status =',Port[Modem+ModemStatusReg]); *)
writeln(' Please connect your modem ');
delay (1000);
If KeyPressed then (* Bypass DSRcheck by hitting the space bar *)
DSRcheck := readkey <> ' ' ;
End ; (* Connect modem please *)
Port[Modem+ModemControlReg] := $0B ; (* set OUT2, DTR ,RTS *)
connected := true ;
If audioflag then
for i:=1 to 50 do begin sound(100*i); delay(5); end ; nosound;
Writeln(' Connection completed ');
End ; (* Dial Modem *)
(* ------------------------------------------------------------------ *)
(* AnswerModem - Check and waits for modem to be connected. *)
(* If DCD is off set RTS off. Wait for DCD to get set *)
(* then set RTS. ( similar to DIALMODEM ) *)
(* Side Effect - global variable 'connected' is set true. *)
(* ------------------------------------------------------------------ *)
Procedure AnswerModem ;
var count : integer ;
Begin (* Answer Modem *)
count := 0 ;
If (Port[Modem+ModemStatusReg] and $80) <> $80 then
Port[Modem+ModemControlReg] := $09 ; (* set OUT2,DTR reset RTS *)
clrscr ; GotoXY(10,10);
write(' Waiting for someone to connect ');
While ((Port[Modem+ModemStatusReg] and $80) <> $80) Do
Begin (* Connect modem please *)
Gotoxy( 44,10) ; write(count);
delay (1000); count := count + 1 ;
End ; (* Connect modem please *)
Port[Modem+ModemControlReg] := $0B ; (* set OUT2, DTR ,RTS *)
Writeln(' Answer completed ');
End ; (* Answer Modem *)
(* ------------------------------------------------------------------ *)
(* RecvChar - Receive a Character from the modem port. *)
(* TRUE - if there is a character from the modem and *)
(* the character is returned in the parmeter. *)
(* FALSE - if no character found . *)
(* *)
(* ------------------------------------------------------------------ *)
Function RecvChar (var mchar : byte) : boolean ;
Begin (* RecvChar *)
if Iin <> Iout then
begin (* get char from buffer *)
If Parity = NoneP then mchar := buffer[Iout]
else mchar := buffer[Iout] and $7F ;
Iout := Iout + 1 ;
If Iout = MaxBuffsize then Iout := 1 ;
RecvChar := true ;
if logging then
Begin {$I-}
write(Logfile,chr(mchar));
If IOresult <> 0 then
Begin (* IO error *)
Writeln(' Disk is Full - logging teminated');
logging := false ;
Close(Logfile);
End ; (* IO error *)
End ; {$I+}
end (* get char from buffer *)
else
RecvChar := false ;
End ; (* RecvChar *)
(* ------------------------------------------------------------------ *)
(* SendChar - Send a character thru the modem port. *)
(* It waits for the previous character to be sent before *)
(* sending the current character. *)
(* ------------------------------------------------------------------ *)
Procedure SendChar(char : byte ) ;
Begin (* Send Char *)
While (Port[Modem+LineStatusReg] and $20) <> $20 do delay(1);
Port[modem] := char ;
End ; (* Send Char *)
(* ------------------------------------------------------------------ *)
(* CharsInBuffer - Returns the number of unprocessed characters in *)
(* the Buffer. *)
(* ------------------------------------------------------------------ *)
Function CharsInBuffer : integer ;
Begin (* Chars In Buffer *)
If Iin >= Iout then CharsInBuffer := Iin - Iout
else CharsInBuffer := MaxBuffSize - Iout + Iin ;
End ; (* Chars In Buffer *)
(* ------------------------------------------------------------------ *)
(* EmptyBuffer - Mark the buffer as being empty. *)
(* ------------------------------------------------------------------ *)
Procedure EmptyBuffer ;
Begin (* Empty Buffer *)
Iout := Iin ;
End ; (* Empty Buffer *)
(* ------------------------------------------------------------------ *)
(* SendBreak- Send a break via the modem port . *)
(* ------------------------------------------------------------------ *)
Procedure SendBreak ;
Var Tbyte,dummy : byte ;
Begin (* Send Break *)
Tbyte := Port[Modem+LineControlReg] ; (* save setting *)
Port[Modem+InterruptEnable] := $00 ; (* Data Avail. Interrupt reset *)
Port[Modem+LineControlReg] := $40 ; (* break for 200 millsec *)
GoToXy(1,24); Write(' *** BREAK *** ',chr(07));
Delay(200) ;
Port[Modem+LineControlReg] := Tbyte ; (* restore setting *)
Delay(100) ;
dummy := Port[Modem] ; (* clear out incoming char *)
Port[Modem+InterruptEnable] := $01 ; (* Data Avail. Interrupt set *)
End ; (* Send Break *)
(* ================================================================= *)
(* End of MODEM routines for IBMPC compatiables. *)
(* ================================================================= *)
Begin
Baudrate := DefaultBaud ;
PrimaryPort := True ;
Parity := EvenP ;
InitModem ;
DSRcheck := True ;
End. (* Modempro *)