{ File: COMMLIB.INC - MS-DOS Version for Ver 2.05+ - 3/9/85 Function: Provide a library of functions needed for communications on a DEC Rainbow. Written by: Stew Stryker } Const Successful = 255; Unsuccessful = 0; Type { This is used when changing comm port parameters } __CommCtrlBlock = RECORD ModemCtrl, StopBits, DataBits, Parity, RCVBaud, XMTBaud,XONChar, XOFFChar, RCVXON, XMTXON : Byte; AltBufSize, BuffAddrOffset, BuffAddrSeg : INTEGER; END; { This is used for all comm port I/O } __IOCTLPacketType = RECORD Fnction, Func_retC : Byte; Character : Char; Char_Stat : Byte; Buffer: Byte; { either CCB or 0 } end; CommInType = RECORD { With each character read in, there's } Char : Char; { the character itself, and a byte } Error : Byte; { indicating any data errors } end; { These are the extended communications functions } __SubFunction = ( ProgramDev, ProgramDefault, SetDefBuf, ReadDevSetup, EnableRecvIntr, DisableRecvIntr, ReadInStat, ReadChar, GetChar, ReadOutStat, WriteChar, PutChar, XMTImmed, ReadModem, SetModem, XMTBreak, StopBreak, SetRecvIntr, ResetRecvIntr, EmptyBufIntr, ResetEmptyBufIntr, SetIntrRoutine, ResetDevIntr ); ParityType = ( NoChange, Even, Odd, None ); { Possible parity values } DataBitsType = (DBNoChange, DB5, DB6, DB7, DB8, DB7S, DB7M ); Var __Buffer1 : String[255]; { The next 4 lines set up communications } __Buffer2 : String[255]; { data buffer of 1024 bytes } __Buffer3 : String[255]; __Buffer4 : String[255]; DefaultBaud : Integer; DefaultDataBits : DataBitsType; DefaultParity : ParityType; DefaultStopBits : Real; CommIn : CommInType; __SetSerialIO : __IOCTLPacketType; { These two variables must be } __CCB : __CommCtrlBlock; { defined contiguously. } __IOCTLPacket : __IOCTLPacketType; Function __CallDOSIO(PortNumber : Byte; Command : __Subfunction; CharOut : Char; BufferOut : Byte) : Boolean; { Do an MS-DOS Communications Driver Interrupt } Begin { First set up IO Control Packet } With __IOCTLPacket Do Begin Fnction := Ord(Command); Buffer := BufferOut; Character := CharOut; end; With __Registers Do Begin AH := $44; AL := $02; BX := PortNumber; DS := Seg(__IOCTLPacket); DX := Ofs(__IOCTLPacket); end; Intr($21,__Registers); If __IOCTLPacket.Func_retC = Successful Then __CallDOSIO := True { This returns whether or } Else __CallDOSIO := False; { not the function was } { successful } end; { __CallDOSIO } Function SetSerial(PortNumber : Byte; BaudRate : Integer; StopBitsIn : Real; DataBitsIn : DataBitsType; ParityIn : ParityType; CharOut : Char) : Boolean; { Set serial parameters for a COM port } Begin With __Registers Do Begin AH := $44; AL := 2; BX := PortNumber; DS := Seg(__SetSerialIO); DX := Ofs(__SetSerialIO); end; __SetSerialIO.Fnction := Ord(ProgramDev); __SetSerialIO.Buffer := 1; With __CCB Do Begin ModemCtrl := 1; If StopBitsIn = 2 Then StopBits := 3 Else If StopBitsIn = 1.5 Then StopBits := 2 Else If StopBitsIn = 1 Then StopBits := 1 Else StopBits := 0; DataBits := Ord(DataBitsIn); Parity := Ord(ParityIn); Case BaudRate of 110: RCVBaud := 3; 150: RCVBaud := 5; 300: RCVBaud := 7; 600: RCVBaud := 8; 1200: RCVBaud := 9; 2400: RCVBaud := 12; 4800: RCVBaud := 14; else RCVBaud := 16; { Default to 9600 Baud } end; { Case of baud rate } XMTBaud := RCVBaud; { Transmit and Receive Rates are same } XONChar := 17; { ^Q } XOFFChar := 19; { ^S } RCVXON := 2; { Always set auto XON/XOFF on } XMTXON := 2; { The manual says this will turn XON/XOFF } { off. It's wrong. Try it if you want. } AltBufSize := 1024; { Set up 1024 byte buffer } BuffAddrOffset := Ofs(__Buffer1); BuffAddrSeg := Seg(__Buffer1); end; Intr($21,__Registers); If __SetSerialIO.Func_retC = Successful Then SetSerial := True Else SetSerial := False; end; { SetSerial } Function ReadCurrentCommSettings : Boolean; { Read the current Comm Setup values } Begin { Get the values } With __Registers Do Begin AH := $44; AL := 2; BX := 3; DS := Seg(__SetSerialIO); DX := Ofs(__SetSerialIO); end; __SetSerialIO.Fnction := Ord(ReadDevSetup); __SetSerialIO.Buffer := 1; Intr($21,__Registers); If __SetSerialIO.Func_retC = Successful Then Begin ReadCurrentCommSettings := True; { Now decode and save default values } Case __CCB.RCVBaud Of 3: DefaultBaud := 110; 5: DefaultBaud := 150; 7: DefaultBaud := 300; 8: DefaultBaud := 600; 9: DefaultBaud := 1200; 12: DefaultBaud := 2400; 14: DefaultBaud := 4800; 16: DefaultBaud := 9600; End; { Case of __CCB.RCVBaud } DefaultDataBits := DataBitsType(__CCB.DataBits); DefaultParity := ParityType(__CCB.Parity); Case __CCB.StopBits Of 3: DefaultStopBits := 2; 2: DefaultStopBits := 1.5; 1: DefaultStopBits := 1; 0: DefaultStopBits := 0; End; { Case statement } End { if successful } Else ReadCurrentCommSettings := False; End; { Function ReadCurrentCommSettings } Function ReplaceDefault : Boolean; { Replace current comm settings with default values } Var TempStatus : Boolean; Begin { Note: Since we're getting many functions status, we'll use } { an artificial method to determine the total status. With } { this method, if one function call is unsuccessful, TempStatus } { becomes, and stays unsuccessful. Sort of like a master AND. } { Disable Receiver Interrupts } TempStatus := __CallDOSIO(3, DisableRecvIntr, Chr(0), 1); { Next, Set device to use default buffer } TempStatus := TempStatus And __CallDOSIO(3, SetDefBuf, Chr(0), 1); { Last, program comm to default settings } TempStatus := TempStatus And __CallDOSIO(3, ProgramDefault, Chr(0), 1); { Now save final status } ReplaceDefault := TempStatus; end; { ReplaceDefault } Function DisconnectModem : Boolean; { Turn off DSR modem signal and reset it } Begin DisconnectModem := __CallDOSIO(3, SetModem, Chr(0), 1); End; { Function DisconnectModem } Function CheckInputStatus : Boolean; { Check the Input line Status of the comm port } Begin CheckInputStatus := __CallDOSIO(3, ReadInStat, Chr(0), 1); end; { CheckInputStatus } Function ReadCommChar : Boolean; { Read a character in from the comm port } Begin ReadCommChar := __CallDOSIO(3, ReadChar, Chr(0), 1); { If any character is returned, save it and any data errors } With CommIn Do Begin Char := __IOCTLPacket.Character; Error := __IOCTLPacket.Char_Stat; { I ignore the error byte. If Error > 0 => an error occurred } end; end; { ReadCommChar } Procedure GetCommChar; { Go for a character from the comm port, don't come back til you get it } { Note: This procedure is dangerous, just because it can wait forever } { for a character to come in. } Begin DummyLogical := __CallDOSIO(3,GetChar, Chr(0), 1); { When character is returned, save it and any data errors } With CommIn Do Begin Char := __IOCTLPacket.Character; Error := __IOCTLPacket.Char_Stat; end; End; Function CheckOutputStatus : Boolean; { Check whether it's ok to send a character out the comm port } Begin CheckOutputStatus := __CallDOSIO(3, ReadOutStat, Chr(0), 1); end; { Function CheckOutputStatus } Function WriteCommChar(OutChar : Char) : Boolean; { Write a char out the comm port } Begin WriteCommChar := __CallDOSIO(3, WriteChar, OutChar, 1); end; { Function WriteCommChar } Procedure PrintChar(OutChar : Char); { Print a character on the default printer } Begin DummyLogical := __CallDOSIO(4, WriteChar, OutChar, 1); End; { Procedure PrintCommChar } Procedure WriteCommString(InString: STRINGLONG); { Send a string of characters out the comm port } { I use this for sending text file to the host } Var Counter : Byte; Begin For Counter := 1 to Length(InString) Do Begin DummyLogical := WriteCommChar(InString[Counter]); { Pause until you can send the next character out } While Not CheckOutputStatus Do Delay(1); End; { Sending input keystroke } End; { Procedure WriteCommString } Function SendBreak : Boolean; { Send a break character out the comm port for standardized } { length of time. } Var TempStatus : Boolean; Begin TempStatus := __CallDOSIO(3, XMTBreak, Chr(0), 1); Delay(250); TempStatus := TempStatus And __CallDOSIO(3, StopBreak, Chr(0), 1); { Save total status } SendBreak := TempStatus; end; { SendBreak } Function InitPort : Boolean; { Initialize communications port with default values } Var TempStatus : Boolean; Begin { First, we'll program the device with our default values. } { TempStatus := SetSerial(3,1200,1,DB7S,none,Chr(0)); { Next, Enable Receiver Interrupts } TempStatus := TempStatus And __CallDOSIO(3,EnableRecvIntr,Chr(0),1); { Now, we'll tell it to set up the modem port for DTR, RTS & SRTS } TempStatus := TempStatus And __CallDOSIO(3,SetModem,Chr(14),1); { Save total status } InitPort := TempStatus; end; { InitPort }