Files
linuxcnc/5i24/utils/dos/source/USERIAL.PAS
Thaddeus-Maximus f3953d66ae ?
2026-04-03 15:58:58 -05:00

361 lines
7.9 KiB
Plaintext
Executable File

{ USerial : Windows/DOS 16C450 or 16C550 or Mesa Serial port routines }
type
ComPortHardwareTypes = (STDComPort,MESAComPort,SSLBPPort,NOPort);
var
CharTimeOut : longint; { milliseconds }
ExitOnTimeout : boolean;
TheBaudRateMul : real;
TheBaudRate : longint;
SerError : boolean;
ComPortHardwareType : ComPortHardwareTypes;
{$IFNDEF WINDOWS}
{$I serial.pas }
{I MesaUart.pas }
{$I M32Uart.pas }
{$ENDIF}
procedure SerSetRTSHigh;
begin
{$IFDEF WINDOWS}
Ser.RTS := true;
{$ELSE}
case ComPortHardwareType of
STDComPort: ForceRTSHigh(TheComPort);
end;
{$ENDIF}
end;
procedure SerSetRTSLow;
begin
{$IFDEF WINDOWS}
Ser.RTS := false;
{$ELSE}
case ComPortHardwareType of
STDComPort: ForceRTSLow(TheComPort);
end;
{$ENDIF}
end;
{$IFDEF WINDOWS}
procedure SerTossChars;
var dummychar : char;
begin
ser.Purge;
repeat
delay(10);
if ser.WaitingData <> 0 then
begin
dummychar := char(ser.RecvByte(CharTimeOut));
end;
delay(10);
until ser.WaitingData = 0;
end;
{$ELSE NOT WINDOWS}
procedure SerTossChars;
begin
case ComPortHardwareType of
STDComPort: TossChars(TheComPort,20);
MESAComPort: MesaSerTossChars(TheComport);
end;
end;
function STDBaudRateValid(comport : word; br,bm : real) : boolean;
var ourbaud,testbaud,ratio : real;
divisor : word;
begin
STDBaudRateValid := true;
ourbaud := br/bm;
divisor := round(STDBRClock/round(br/bm*16.0));
testbaud := StdBRClock / divisor /16.0;
ratio := ourbaud / testbaud;
if (ratio > 1.0) and (ratio > 1.03) then STDBaudRateValid := false;
if (ratio < 1.0) and (ratio < 0.97) then STDBaudRateValid := false;
end;
function STDSetBaud(comport : word; br,bm : real) : boolean;
var ourbaud : real;
begin
if STDBaudRateValid(comport,br,bm) then
begin
ourbaud := br/bm;
{$IFDEF WINDOWS}
ser.Config(round(ourbaud),8,'N',0,false,false);
{$ELSE} { DOS }
SetBaudRate(comport,round(ourbaud));
{$ENDIF}
STDSetBaud := true;
end
else
begin
STDSetBaud := false;
writeln('Invalid Baud Rate');
end;
end;
{ dos }
function DosSerRecvChar(var c : char) : boolean;
var timeout : longint;
ourchar : char;
begin
timeout := CharTimeOut;
while ((port[TheComPort + LineStat] and DataReady) = 0) and (timeout <> 0) do timeout := timeout -1;
if timeout <> 0 then
begin
ourchar := char(port[TheComPort + RecReg]);
DosSerRecvChar := true;
c := ourchar;
{$IFDEF SDEBUG}
Hexprint(byte(ourchar),2);
write(' ');
{$ENDIF}
end
else
begin
DosSerRecvChar := false;
SerError := true;
if ExitOnTimeout then Error(CharTimeoutErr);
end;
end;
function DosSerRecvString(n : integer;var s : string) : boolean;
var
count : integer;
is : string;
timeout : longint;
ourchar : char;
charok : boolean;
begin
DosSerRecvString := false;
charok := true;
is := '';
for count := 1 to n do
begin
if DosSerRecvChar(ourchar) then
begin
is := is + ourchar;
end else charok := false;
end;
DosSerRecvString := charok;
s := is;
end;
procedure DosSerSendChar(c : char);
var dummy : char;
begin
if SerType = TwoWire then
begin
ForceRTSHigh(TheComPort);
{delay(1);}
end;
while (port[TheComPort + LineStat] and THRE) = 0 do {wait for xmit char} ;
port[TheComPort + TrHReg] := byte(c);
{$IFDEF SDEBUG}
DebugString := DebugString + HexString(longint(c),2) + ' ';
{$ENDIF}
if SerType = TwoWire then
begin
WaitForXmitDone(TheComPort);
ForceRTSLow(TheComPort);
DosSerRecvChar(dummy);
end;
end;
procedure DosSerSendString(s : string);
var i : integer;
begin
DisableInterrupts;
for i := 1 to length(s) do
begin
DosSerSendChar(s[i]);
end;
EnableInterrupts;
end;
procedure DosSerOpen(comport : word; br,bm : real);
begin
DefaultComInit(comport);
EnableFifos(comport); { don't check if fifos are there because it sends garbage }
STDSetBaud(comport,br,bm);
TossChars(comport,20); { make real sure there are no pending chars }
end;
function DosCanRead(ms : integer) : boolean;
var ctimeout : longint;
begin
if ms <> 0 then
begin
ctimeout := LoopsPermS * longint(ms);
while ((port[TheComPort + LineStat] and DataReady = 0) and (ctimeout <> 0)) do ctimeout := ctimeout -1;
if ctimeout <> 0 then DosCanRead := true else DosCanRead := false;
end
else if ((port[TheComPort + LineStat] and DataReady) <> 0) then DosCanRead := true else DosCanRead := false
end;
{$ENDIF WINDOWS}
{ all }
function SerOpen(var message : string) : boolean;
var openok : boolean;
begin
message := '';
SerOpen := false;
openok := false;
{$IFDEF WINDOWS}
{Writeln('Attempt to open serial port: ',TheComPort); }
ser:=TBlockserial.Create;
{ser.RaiseExcept:=True;}
ser.Connect(TheComPort);
ser.Config(round(TheBaudrate/TheBaudRateMul),8,'N',0,false,false);
if ser.LastError = 0 then openok := true else message := TheComPort;
SerTossChars;
{$ELSE} { DOS }
case ComPortHardwareType of
MESAComPort:
begin
if MesaComportThere(TheComPort) then
begin
MesaSerOpen(TheComPort,TheBaudRate,TheBaudRateMul);
openok := true;
end;
message := 'MesaCom port'
end;
STDComPort:
begin
if ComPortThere(TheComport) then
begin
DosSerOpen(TheComPort,TheBaudRate,TheBaudRateMul);
openok := true;
end;
message := 'Dos Com port'
end;
end; { case }
{$ENDIF}
if openok then
begin
message := message + ' open ok';
SerOpen := true;
end else message := message + ' open failed';
end;
procedure SerClose;
begin
{$IFDEF WINDOWS}
ser.free;
{$ELSE} { DOS }
{$ENDIF}
end;
function SerRecvChar(var c : char) : boolean;
begin
{$IFDEF WINDOWS}
SerError := true;
c := char(ser.RecvByte(CharTimeOut));
if ser.LastError = ErrTimeout then
begin
SerRecvChar := false;
if ExitOnTimeout then Error(CharTimeoutErr);
end
else
begin
SerRecvChar := true;
SerError := false;
end;
{$ELSE} { DOS }
case ComPortHardwareType of
MESAComPort: SerRecvChar := MesaSerRecvChar(c);
STDComPort: SerRecvChar := DosSerRecvChar(c);
end;
{$ENDIF}
{$IFDEF SERDEBUG}
Hexprint(byte(c),2);
writeln;
{$ENDIF}
end;
function SerRecvString(n : integer;var s : string) : boolean;
var index : integer;
begin
s := '';
{$IFDEF WINDOWS}
s := ser.RecvBufferStr(n,CharTimeOut);
if ser.LastError = ErrTimeout then SerRecvString := false else SerRecvString := true;
{$ELSE} { DOS }
case ComPortHardwareType of
MESAComPort: SerRecvString := MesaSerRecvString(n,s);
STDComPort: SerRecvString := DosSerRecvString(n,s);
end;
{$ENDIF}
{$IFDEF SERDEBUG}
write('Recv Data: ');
for index := 1 to length(s) do
begin
hexprint(byte(s[index]),2);
write(',');
end;
writeln;
{$ENDIF}
end;
procedure SerSendChar(c : char);
begin
{$IFDEF WINDOWS}
ser.SendByte(byte(c));
{$ELSE} { DOS }
case ComPortHardwareType of
MESAComPort: MesaSerSendChar(c);
STDComPort: DosSerSendChar(c);
end;
{$ENDIF}
end;
procedure SerSendString(s : string);
var index : integer;
begin
{$IFDEF SERDEBUG}
write('Send Data: ');
for index := 1 to length(s) do
begin
hexprint(byte(s[index]),2);
write(',');
end;
writeln;
{$ENDIF}
{$IFDEF WINDOWS}
ser.SendString(s);
{$ELSE}
case ComPortHardwareType of
MESAComPort: MesaSendString(s);
STDComPort: DosSerSendString(s);
end;
{$ENDIF}
end;
function SerCanRead(ms: longint) : boolean;
begin
{$IFDEF WINDOWS}
SerCanRead := ser.CanReadEx(ms);
{$ELSE} { DOS }
case ComPortHardwareType of
MESAComPort: SerCanRead := MesaCanRead(ms);
STDComPort: SerCanRead := DosCanRead(ms);
end;
{$ENDIF}
end;
{fixed toss char reversed paramaters range check error 12-16-2009}
{don't setrtshigh/low in mesa mode 2-3-2010 }