Category : Modula II Source Code
Archive   : PCKERM.ZIP
Filename : DATALINK.MOD

 
Output of file : DATALINK.MOD contained in archive : PCKERM.ZIP
IMPLEMENTATION MODULE DataLink; (* Sends and Receives Packets for PCKermit *)

FROM InOut IMPORT
WriteString, WriteLn;

FROM Delay IMPORT
Delay; (* delay is in milliseconds *)

FROM BitByteOps IMPORT
ByteAnd;

IMPORT RS232Int; (* for RS232Int.BusyRead, RS232Int.Write *)

FROM PAD IMPORT
PacketType, yourNPAD, yourPADC, yourEOL;

IMPORT ASCII;


CONST
MAXtime = 10000;
MAXsohtrys = 100;

VAR
ch : CHAR;
GotChar : BOOLEAN;


PROCEDURE Char (c : INTEGER) : CHAR;
(* converts a number 0-95 into a printable character *)
BEGIN
RETURN (CHR (CARDINAL (ABS (c) + 32)));
END Char;


PROCEDURE UnChar (c : CHAR) : INTEGER;
(* converts a character into its corresponding number *)
BEGIN
RETURN (ABS (INTEGER (ORD (c)) - 32));
END UnChar;


PROCEDURE FlushUART;
(* ensure no characters left in UART holding registers *)
BEGIN
Delay (500);
REPEAT
RS232Int.BusyRead (ch, GotChar);
UNTIL NOT GotChar;
END FlushUART;


PROCEDURE SendPacket (s : PacketType);
(* Adds SOH and CheckSum to packet *)

VAR
i : INTEGER;
checksum : INTEGER;

BEGIN
Delay (10); (* give host a chance to catch its breath *)
FOR i := 1 TO yourNPAD DO
RS232Int.Write (yourPADC);
END;
RS232Int.Write (ASCII.soh);
i := 1;
checksum := 0;
WHILE s[i] # 0C DO
INC (checksum, ORD (s[i]));
RS232Int.Write (s[i]);
INC (i);
END;
checksum := checksum + (INTEGER (BITSET (checksum) * {7, 6}) DIV 64);
checksum := INTEGER (BITSET (checksum) * {5, 4, 3, 2, 1, 0});
RS232Int.Write (Char (checksum));
IF yourEOL # 0C THEN
RS232Int.Write (yourEOL);
END;
END SendPacket;


PROCEDURE ReceivePacket (VAR r : PacketType) : BOOLEAN;
(* strips SOH and checksum -- return FALSE if timed out or bad checksum *)

VAR
sohtrys, time : INTEGER;
i, len : INTEGER;
ch : CHAR;
checksum : INTEGER;
mycheck, yourcheck : CHAR;

BEGIN
sohtrys := MAXsohtrys;
REPEAT
time := MAXtime;
REPEAT
DEC (time);
RS232Int.BusyRead (ch, GotChar);
UNTIL GotChar OR (time = 0);
ch := CHAR (ByteAnd (ch, 177C)); (* mask off MSB *)
(* skip over up to MAXsohtrys padding characters, *)
(* but allow only MAXsohtrys/10 timeouts *)
IF GotChar THEN
DEC (sohtrys);
ELSE
DEC (sohtrys, 10);
END;
UNTIL (ch = ASCII.soh) OR (sohtrys <= 0);

IF ch = ASCII.soh THEN
(* receive rest of packet *)
time := MAXtime;
REPEAT
DEC (time);
RS232Int.BusyRead (ch, GotChar);
UNTIL GotChar OR (time = 0);
ch := CHAR (ByteAnd (ch, 177C));
len := UnChar (ch);
r[1] := ch;
checksum := ORD (ch);
i := 2; (* on to second character in packet -- after LEN *)
REPEAT
time := MAXtime;
REPEAT
DEC (time);
RS232Int.BusyRead (ch, GotChar);
UNTIL GotChar OR (time = 0);
ch := CHAR (ByteAnd (ch, 177C));
r[i] := ch; INC (i);
INC (checksum, (ORD (ch)));
UNTIL (i > len);
time := MAXtime;
REPEAT
DEC (time);
RS232Int.BusyRead (ch, GotChar);
UNTIL GotChar OR (time = 0); (* get checksum character *)
ch := CHAR (ByteAnd (ch, 177C));
yourcheck := ch;
r[i] := 0C;
checksum := checksum +
(INTEGER (BITSET (checksum) * {7, 6}) DIV 64);
checksum := INTEGER (BITSET (checksum) * {5, 4, 3, 2, 1, 0});
mycheck := Char (checksum);
IF mycheck = yourcheck THEN (* checksum OK *)
RETURN TRUE;
ELSE (* ERROR!!! *)
WriteString ("Bad Checksum"); WriteLn;
RETURN FALSE;
END;
ELSE
WriteString ("No SOH"); WriteLn;
RETURN FALSE;
END;
END ReceivePacket;

END DataLink.

  3 Responses to “Category : Modula II Source Code
Archive   : PCKERM.ZIP
Filename : DATALINK.MOD

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/