{ ROSMAC.INC - Remote Operating System Machine Dependent Routines } { Modified for Kaypro 4'84 with original clock } { By Kevin E. Karns - July 3, 1985 } Const sec = 2; {clk functions} min = 3; hour = 4; day = 6; mon = 7; year = 9; func = 32; {clk function port} clock = 36; {clk read/write port} init = 34; {Z80 PIO initialization port} initch = 15; {Z80 PIO initialization char} make_one_pass: boolean = false; Type abyte = byte; Var hours, minutes, seconds, months, days, years: abyte; Function Bcd(intval: abyte): abyte; (* convert an integer value (intval) to byte in packed BCD format before sending it to clock. *) Var hinybble, lonybble: byte; begin hinybble := intval div 10; lonybble := intval - (10 * hinybble); hinybble := hinybble * 16; Bcd := hinybble + lonybble; End; Function Ascii(bcdbyte: abyte): abyte; (* convert packed BCD byte read from clock to integer value that Turbo will display as an ASCII string. *) Var hinybble, lonybble: byte; begin lonybble := bcdbyte and $0F; hinybble := 10 * (bcdbyte div 16); Ascii := hinybble + lonybble; End; {ascii} Procedure GetTAD(var t : tad_array); { Return a 6 element byte array of the current system time in seconds, minutes, hours, day, month, and year. } begin port[init] := initch; {initialize PIO} port[func] := hour; hours := port[clock]; t[2] := Ascii(hours); port[func] := min; minutes := port[clock]; t[1] := Ascii(minutes); port[func] := sec; seconds := port[clock]; t[0] := Ascii(seconds); port[func] := mon; months := port[clock]; t[4] := Ascii(months); port[func] := day; days := port[clock]; t[3] := Ascii(days); port[func] := year; years := port[clock]; t[5] := Ascii(years); End; {GetTAD} Procedure SetTAD(var t : tad_array); { Set the system time using a 6 element byte array } begin port[init] := initch; {initialize PIO} port[func] := hour; hours := Bcd(t[2]); port[clock] := hours; port[func] := min; minutes := Bcd(t[1]); port[clock] := minutes; port[func] := sec; seconds := Bcd(t[0]); port[clock] := seconds; port[func] := mon; months := Bcd(t[4]); port[clock] := months; port[func] := day; days := Bcd(t[3]); port[clock] := days; port[func] := year; years := Bcd(t[5]); port[clock] := years; End; const { Machine specific constants } DataPort = $04; { Data port } StatusPort = $06; { Status port } RatePort = $00; { Data rate (bps) port } { StatusPort commands } RESCHN = $18; { reset channel } RESSTA = $10; { reset ext/status } WRREG1 = $00; { value to write to register 1 } WRREG3 = $C1; { 8 bits/char, rx enable } WRREG4 = $44; { 16x, 1 stop bit, no parity } DTROFF = $68; { dtr off, rts off } DTRON = $EA; { dtr on, 8 bits/char, tx enable, rts on } ONINS = $30; { error reset } { StatusPort status masks } DAV = $01; { data available } TRDY = $04; { transmit buffer empty } DCD = $08; { data carrier detect } PE = $10; { parity error } OE = $20; { overrun error } FE = $40; { framing error } ERR = $60; { parity, overrun and framing error } { Smartmodem result codes } OKAY = '0'; { Command executed with no errors } CONNECT300 = '1'; { Carrier detect at 300 bps } RING = '2'; { Ring signal detected } NOCARRIER = '3'; { Carrier lost or never heard } ERROR = '4'; { Error in command execution } CONNECT1200 = '5'; { Carrier detect at 1200 bps } { Rate setting commands } BD300 = 5; { 300 bps } BD1200 = 7; { 1200 bps } function mdcarck: boolean; { Check to see if carrier is present } begin port[StatusPort] := RESSTA; mdcarck := ((DCD and port[StatusPort]) <> 0) end; function mdinprdy: boolean; { Check for ready to input from modem } var bt: byte; begin if (DAV and port[StatusPort]) <> 0 then begin port[StatusPort] := 1; if (ERR and port[StatusPort]) <> 0 then begin port[StatusPort] := ONINS; bt := port[DataPort]; mdinprdy := FALSE end else mdinprdy := TRUE end else mdinprdy := FALSE end; function mdinp: byte; { Input a byte from modem - no wait - assumed ready } begin mdinp := port[DataPort] end; procedure mdout(b: byte); { Output a byte to modem - wait until ready } begin repeat until (TRDY and port[StatusPort]) <> 0; port[DataPort] := b end; procedure mdinit; { Initialize the sio channel and the Hayes Smartmodem 1200 } const sio_init: array[1..9] of byte = (RESCHN, 4, WRREG4, 1, WRREG1, 3, WRREG3, 5, DTROFF); var i: integer; mdm_attn : string[2]; mdm_init : string[38]; bt : byte; begin for i := 1 to 9 do port[StatusPort] := sio_init[i]; { initialize the SIO channel } port[StatusPort] := 5; { pull DTR high } port[StatusPort] := DTRON; mdm_attn := 'AT'; mdm_init := 'ATH0E0Q0V0M0X1 S0=0 S2=3 S4=255 S5=255'; port[RatePort] := BD1200; {set the 8116 to 1200 baud} delay (500); {let the modem settle for a bit} for i := 1 to 2 do begin bt := ord(mdm_attn[i]); {force the modem to 1200 baud} mdout(bt) end; bt := ord(CR); mdout(bt); delay (2000); {wait a sec...} for i := 1 to 38 do begin bt := ord(mdm_init[i]); {initialize the modem} mdout(bt) end; bt := ord(CR); mdout(bt); bt := mdinp; { clear any previous rings } bt := mdinp end; PROCEDURE MDBUSY; const sio_init: array[1..9] of byte = (RESCHN, 4, WRREG4, 1, WRREG1, 3, WRREG3, 5, DTROFF); var i: integer; mdm_attn : string[2]; mdm_local : string[6]; bt : byte; begin for i := 1 to 9 do port[StatusPort] := sio_init[i]; { initialize the SIO channel } port[StatusPort] := 5; { pull DTR high } port[StatusPort] := DTRON; mdm_attn := 'AT'; mdm_local := 'ATM0H1'; delay (500); {let the modem settle for a bit} for i := 1 to 2 do begin bt := ord(mdm_attn[i]); {force the modem to 1200 baud} mdout(bt) end; bt := ord(CR); mdout(bt); delay (2000); {wait a sec...} for i := 1 to 6 do begin bt := ord(mdm_local[i]); {initialize the modem} mdout(bt) end; bt := ord(CR); mdout(bt); end; function mdring: boolean; { Determine if the phone is ringing } begin if mdinprdy then mdring := (RING = chr(mdinp)) else mdring := FALSE end; procedure mdhangup; { Hangup modem } var i : integer; mdm_hang : string[4]; bt : byte; begin repeat port[StatusPort] := 5; { setup to write register 5 } port[StatusPort] := DTROFF; { clear DTR, causing hangup } delay(2000); port[StatusPort] := 5; port[StatusPort] := DTRON; if mdcarck then begin mdm_hang := 'ATH0'; for i := 1 to 3 do begin bt := ord(ETX); mdout(bt) end; delay(1500); for i := 1 to 4 do begin bt := ord(mdm_hang[i]); mdout(bt) end; bt := ord(CR); mdout(bt) end; until not(mdcarck) end; procedure mdans; { Detect and set system to rate at which modem answered phone } var mdm_answ : string[3]; code : char; i : integer; bt : byte; begin repeat until mdinprdy; bt := mdinp; mdm_answ := 'ATA'; for i := 1 to 3 do begin bt := ord(mdm_answ[i]); mdout(bt) end; bt := ord(CR); mdout(bt); repeat until mdinprdy; code := chr(mdinp); if code = CONNECT1200 then begin port[RatePort] := BD1200; rate := 0.02075; delay(500); bt := mdinp; bt := mdinp end; if code = CONNECT300 then begin port[RatePort] := BD300; rate := 0.083; delay(500); bt := mdinp; bt := mdinp end; if code = NOCARRIER then mdhangup end; {** System routines **} procedure system_init; { System particular initialization to be done once (when ROS first starts) } begin end; procedure putstat(st: StrStd); { Put 'st' on status line and return to normal display } const status_line = 1; { Line used for system status } last_line = 25; { Last line on screen } begin WRITE (CHR(27), 'C',7); WRITE(CHR(27), 'B',0); WRITE(CHR(27), 'B',6); WRITE(CHR(27), 'B',7); WRITE(CHR(27), '=8 '); ClrEol; LowVideo; write(st); HighVideo; Delay(1500); DelLine; WRITE(CHR(27), 'C',0); WRITE(CHR(27), 'C',6); end;