kermit: do; declare true literally '0FFH'; declare false literally '00H'; declare port1cmd literally '0F5H'; declare port1dat literally '0F4H'; declare port1clk literally '0F0H'; declare timing1 literally '036H'; declare port2cmd literally '0F7H'; declare port2dat literally '0F6H'; declare port2clk literally '0F1H'; declare timing2 literally '076H'; declare modesel literally '0F3H'; declare reset literally '040H'; declare EnaTxRx literally '025H'; declare tx$rdy literally '01H'; declare rx$rdy literally '02H'; declare null literally '000H'; declare lf literally '0AH'; declare cr literally '0DH'; declare crlf literally 'cr,lf,null'; declare space literally '20H'; declare dollar literally '24H'; declare buflen literally '122'; declare buffer(buflen) byte; declare (cmdstr, temp, cmdptr, realspeed) address; declare cmd byte; declare speed byte public; declare port byte public; declare filename address public; declare debug byte public; /* here are the subroutines */ co: procedure(char)external; declare char byte; end co; ci: procedure byte external; end ci; read: procedure(jfn, buf, max, count, status)external; declare(jfn, buf, max, count, status)address; end read; error: procedure(errnum)external; declare(errnum)address; end error; exit: procedure external; end exit; connect: procedure external; end connect; send: procedure byte external; end send; recv: procedure external; end recv; newline: procedure public; call co(13); call co(10); end newline; spin: procedure(string)address public; declare string address; declare char based string byte; do while (char <> null) and (char < 021H); string = string + 1; end; return string; end spin; strcmp: procedure(s1,s2)byte public; declare(s1,s2)address; declare c1 based s1 byte; declare c2 based s2 byte; declare retval byte; retval = 0; s1 = spin(s1); s2 = spin(s2); if not(c1 = c2) then retval = c1 - c2; do while (c1 > 0) and (c2 > 0) and (retval=0); retval = c1 - c2; s1 = s1+1; s2 = s2+1; end; return retval; end strcmp; /* TOKEN: returns a pointer to a null-terminated token pointed */ /* to prior to the call by cmdptr. after the call, cmdptr points */ /* to the end of the original string, or the first character after */ /* the null character replacing the first whitespace after the first */ /* token. */ token: procedure address public; declare result address; declare char based cmdptr byte; result = 0; cmdptr = spin(cmdptr); if char <> null then do; result = cmdptr; do while char > ' '; cmdptr = cmdptr + 1; end; if char <> null then do; char = null; cmdptr = cmdptr + 1; end; end; return result; end token; nout: procedure(n) public; declare n address; declare (quotient, digit, curr) address; declare numbuf(20) byte; declare index byte; if n = 0 then do; call co('0'); return; end; index = 1; do while (n > 0); digit = n mod 10; numbuf(index) = digit+030H; index = index + 1; n = n / 10; end; do while ((index := index - 1) > 0); call co(numbuf(index)); end; end nout; nin: procedure(string) address public; declare string address; declare result address; declare c based string byte; result = 0; if (string <> 0) then do; string = spin(string); do while (c >= 030H) and (c <= 039H); result = result * 10 + (c - 030H); string = string + 1; end; end; return result; end nin; print: procedure(msg) public; declare msg address; declare c based msg byte; do while (c > 0) and (c <> '$'); if c = '\' then call newline; else call co(c); msg = msg + 1; end; end print; /* IOINIT: this routine takes a port number, 0,1 or 2, and a speed in the */ /* range 1-4 and initializes the require port to work at the required speed. */ /* The routine returns no parameters. */ ioinit: procedure; declare ispeed byte; declare baud structure (code(5) byte, mult(5) byte) data (40H, 10H, 20H, 10H, 08H, 0CFH, 0CFH, 0CEH, 0CEH, 0CEH); ispeed = speed - 1; if debug then do; call newline; call print(.('initializing serial port',crlf)); end; do case port; do; if debug then call print(.('port 0 initialized',crlf)); end; do; if debug then call print(.('port 1 initialized',crlf)); output(port1cmd) = reset; output(modesel) = timing1; output(port1clk) = baud.code(ispeed); output(port1clk) = 0H; output(port1cmd) = baud.mult(ispeed); output(port1cmd) = EnaTxRx; end; do; if debug then call print(.('port 2 initialized',crlf)); output(port2cmd) = reset; output(modesel) = timing2; output(port2clk) = baud.code(ispeed); output(port2clk) = 0H; output(port2cmd) = baud.mult(ispeed); output(port2cmd) = EnaTxRx; end; end; end ioinit; usage: procedure; call print(.('usage: kermit (300|1200|2400|4800|9600) (1|2)',crlf)); call exit; end usage; readln: procedure; declare (count, status) address; call read(1, .buffer, buflen, .count, .status); if status > 0 then do; call print(.('READLN FAILED',crlf)); call error(status); call exit; end; buffer(count-2) = 0; cmdptr = .buffer; end readln; /* *** main program *** */ debug = false; call readln; realspeed = 2400; port = 1; /* read desired baud rate, if supplied */ temp = token; if temp > 0 then realspeed = nin(temp); /* get desired port, if supplied */ temp = token; if temp > 0 then port = nin(temp); /* make sure there's garbage on the end of the line */ if token > 0 then call usage; if (port < 1) or (port > 2) then call usage; if realspeed = 9600 then speed = 5; else if realspeed = 4800 then speed = 4; else if realspeed = 2400 then speed = 3; else if realspeed = 1200 then speed = 2; else if realspeed = 300 then speed = 1; else call usage; call print(.('Serial port ',null)); call nout(port); call print(.(', Baud rate ',null)); call nout(realspeed); call newline; call ioinit; do while (true); cmdstr = 0; do while (cmdstr = 0); call print(.('ISIS-Kermit>',null)); call readln; cmdstr = token; end; if (strcmp(cmdstr,.('connect',null)) = 0) then cmd = 1; else if (strcmp(cmdstr,.('send',null)) = 0) then cmd = 2; else if (strcmp(cmdstr,.('receive',null)) = 0) then cmd = 3; else if (strcmp(cmdstr,.('exit',null)) = 0) then cmd = 4; else if (strcmp(cmdstr,.('debug',null)) = 0) then cmd = 5; else cmd = 0; if (cmd <> 2) then if token > 0 then cmd = 0; do case cmd; call print(.('Syntax error',crlf)); call connect; do; filename = token; if (filename = 0) then call print(.('No files specified',crlf)); else if send then call print(.(cr,lf,'OK',crlf)); else call print(.('Send failed',crlf)); end; do; call recv; call print(.(cr,lf,'OK',crlf)); end; call exit; debug = not debug; end; end; end kermit;