MODULE Serials;
IMPORT Streams, Modules, KernelLog, Commands;
CONST
Verbose = TRUE;
MaxPorts* = 64;
ParNo* = 0; ParOdd* = 1; ParEven* = 2; ParMark* = 3; ParSpace* = 4;
Stop1* = 1; Stop2* = 2; Stop1dot5* = 3;
DTR* = 0; RTS* = 1;
Break* = 2;
DSR* = 3; CTS* = 4; RI* = 5; DCD* = 6;
OverrunError* = 10;
ParityError* = 11;
FramingError* = 12;
BreakInterrupt* = 13;
Ok* = 0;
Closed* = -1;
TransportError* = -2;
PortInUse* = 1; NoSuchPort* = 2; WrongBPS* = 3; WrongData* = 4; WrongParity* = 5; WrongStop* = 6;
TYPE
Port* = OBJECT (Streams.Connection);
VAR
name- : ARRAY 6 OF CHAR;
description- : ARRAY 128 OF CHAR;
charactersSent*, charactersReceived* : LONGINT;
PROCEDURE Open* (bps, data, parity, stop : LONGINT; VAR res: LONGINT);
END Open;
PROCEDURE Close* ;
END Close;
PROCEDURE SendChar* (ch: CHAR; VAR res : LONGINT);
END SendChar;
PROCEDURE Send*(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: LONGINT);
VAR i : LONGINT;
BEGIN
i := 0;
WHILE i < len DO
SendChar(buf[ofs + i], res);
IF res # Ok THEN RETURN END;
INC(i)
END
END Send;
PROCEDURE ReceiveChar* (VAR ch: CHAR; VAR res: LONGINT);
END ReceiveChar;
PROCEDURE Receive*(VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
VAR ch: CHAR;
BEGIN
len := 0;
res := Ok;
WHILE (len < min) DO
ReceiveChar(ch, res);
IF res # Ok THEN RETURN END;
buf[ofs + len] := ch;
INC(len);
END;
WHILE (Available() > 0) & (len < size) DO
ReceiveChar(ch, res);
IF res # Ok THEN RETURN END;
buf[ofs + len] := ch;
INC(len)
END;
END Receive;
PROCEDURE Available*(): LONGINT;
END Available;
PROCEDURE GetPortState*(VAR openstat : BOOLEAN; VAR bps, data, parity, stop : LONGINT);
END GetPortState;
PROCEDURE ClearMC*(s: SET);
END ClearMC;
PROCEDURE SetMC*(s: SET);
END SetMC;
PROCEDURE GetMC*(VAR s: SET);
END GetMC;
PROCEDURE Show*;
BEGIN
KernelLog.String(name); KernelLog.String(" ("); KernelLog.String(description); KernelLog.String(")");
END Show;
END Port;
VAR
ports : ARRAY MaxPorts OF Port;
PROCEDURE RegisterPort* (port : Port; CONST description : ARRAY OF CHAR);
VAR name : ARRAY 6 OF CHAR; portNumber : LONGINT;
BEGIN {EXCLUSIVE}
ASSERT(port # NIL);
portNumber := 9;
WHILE (portNumber < LEN(ports)) & (ports[portNumber-1] # NIL) DO INC(portNumber); END;
IF portNumber < LEN(ports) THEN
ports[portNumber-1] := port;
name := "COM";
IF portNumber < 10 THEN
name[3] := CHR(ORD("0") + portNumber);
ELSE
name[3] := CHR(ORD("0") + portNumber DIV 10);
name[4] := CHR(ORD("0") + portNumber MOD 10);
END;
COPY(name, port.name);
COPY(description, port.description);
IF Verbose THEN KernelLog.String("Serials: "); port.Show; KernelLog.String(" is now available."); KernelLog.Ln; END;
ELSE
KernelLog.String("Serials: Could not register port: No free slots."); KernelLog.Ln;
END;
END RegisterPort;
PROCEDURE UnRegisterPort* (port : Port);
VAR i : LONGINT;
BEGIN {EXCLUSIVE}
i := 0; WHILE (i < LEN(ports)) & (ports[i] # port) DO INC(i); END;
IF i < LEN(ports) THEN
ports[i].Close;
ports[i] := NIL;
IF Verbose THEN KernelLog.String("Serials: "); port.Show; KernelLog.String(" has been removed."); KernelLog.Ln; END;
ELSE
KernelLog.String("Serials: Warning: UnRegisterPort: Port not found."); KernelLog.Ln;
END;
END UnRegisterPort;
PROCEDURE RegisterOnboardPort*(portNumber : LONGINT; port : Port; CONST name, description : ARRAY OF CHAR);
BEGIN {EXCLUSIVE}
IF (portNumber >= 1) & (portNumber <= LEN(ports)) & (ports[portNumber-1] = NIL) THEN
ports[portNumber-1] := port;
COPY(name, port.name);
COPY(description, port.description);
ELSE
KernelLog.String("Serials: Warning; Could not register onboard port."); KernelLog.Ln;
END;
END RegisterOnboardPort;
PROCEDURE GetPort* (portNumber : LONGINT) : Port;
VAR port : Port;
BEGIN {EXCLUSIVE}
IF (portNumber >= 1) & (portNumber <= LEN(ports)) & (ports[portNumber-1] # NIL) THEN
port := ports[portNumber-1];
END;
RETURN port;
END GetPort;
PROCEDURE Show*(context : Commands.Context);
VAR port : Port; noPortsAvailable : BOOLEAN; i : LONGINT;
BEGIN {EXCLUSIVE}
noPortsAvailable := TRUE;
context.out.String("Serials: "); context.out.Ln;
FOR i := 0 TO LEN(ports)-1 DO
port := ports[i];
IF port # NIL THEN
noPortsAvailable := FALSE;
context.out.String(port.name); context.out.Char(9X); context.out.String(port.description); context.out.Ln;
END;
END;
IF noPortsAvailable THEN context.out.String("No serial ports found."); END;
context.out.Ln;
END Show;
PROCEDURE Test*(context : Commands.Context);
VAR
result : LONGINT;
portgotten : Port;
BEGIN
context.out.String ("Testing availability of COM1 and COM2."); context.out.Ln;
context.out.String ("Testing COM1: ");
portgotten := GetPort (1);
IF portgotten # NIL THEN
portgotten.Open (4800, 8, 2, 2, result);
portgotten.Close ();
context.out.String ("available, result="); context.out.Int(result, 0); context.out.Ln;
context.out.String ("Testing COM2: ");
portgotten := GetPort (2);
IF portgotten # NIL THEN
portgotten.Open (9600, 8, 2, 2, result);
portgotten.Close ();
context.out.String ("available, result="); context.out.Int(result, 0); context.out.Ln
ELSE
context.out.String ("Could not get port 2"); context.out.Ln
END
ELSE
context.out.String ("Could not get port 1"); context.out.Ln;
context.out.String ("Not testing COM2 as it is likely not to work either."); context.out.Ln;
END;
END Test;
PROCEDURE CloseAllPorts*(context : Commands.Context);
VAR portNbr : LONGINT;
BEGIN {EXCLUSIVE}
FOR portNbr := 0 TO LEN(ports)-1 DO
IF ports[portNbr] # NIL THEN
ports[portNbr].Close;
END;
END;
IF (context # NIL) THEN context.out.String("All serial ports closed"); context.out.Ln; END;
END CloseAllPorts;
PROCEDURE Cleanup;
BEGIN
CloseAllPorts(NIL);
END Cleanup;
BEGIN
Modules.InstallTermHandler(Cleanup);
END Serials.
SystemTools.Free V24 Serials ~
V24.Install ~
Serials.Test ~
Serials.Show ~