diff --git a/Source/Apps/Build.cmd b/Source/Apps/Build.cmd index be60f023..c308521a 100644 --- a/Source/Apps/Build.cmd +++ b/Source/Apps/Build.cmd @@ -17,6 +17,7 @@ call :asm Format || goto :eof call :asm Talk || goto :eof call :asm OSLdr || goto :eof call :asm Mode || goto :eof +call :asm RTC || goto :eof zx Z80ASM -SYSGEN/F diff --git a/Source/Apps/RTC.asm b/Source/Apps/RTC.asm new file mode 100644 index 00000000..4f2b1e03 --- /dev/null +++ b/Source/Apps/RTC.asm @@ -0,0 +1,1702 @@ + .Title "RTC" +; +; Program: rtc.asm +; Author: Andrew Lynch +; Date: 22 Feb 2007 +; Enviroment: TASM MS-DOS Z80 Cross Assembler source for CP/M +; +;[2011/8/11] VK5DG modified for N8 +; Changed base address to $88 +; Changed trickle charger value to 2k+2 diodes for DS1210s +; +;[2012/2/7] WBW modified to build for either +; traditional N8VEM/Zeta or N8 via conditionals +; +;[2013/12/29] WBW modified to build for MK4 +; +;[2017/11/29] WBW modified to adjust to RTC in use dynamically +; using HBIOS platform detection +; +; Constants +; + +mask_data .EQU %10000000 ; RTC data line +mask_clk .EQU %01000000 ; RTC Serial Clock line +mask_rd .EQU %00100000 ; Enable data read from RTC +mask_rst .EQU %00010000 ; De-activate RTC reset line + +PORT_SBC .EQU $70 ; RTC port for SBC/ZETA +PORT_N8 .EQU $88 ; RTC port for N8 +PORT_MK4 .EQU $8A ; RTC port for MK4 + +BDOS .EQU 5 ; BDOS invocation vector +; +; Program +; + .ORG 0100H + +LOOP: + LD DE,MSG + LD C,09H ; CP/M write string to console call + CALL 0005H + +; program starts here + + CALL RTC_INIT ; Program initialization + + CALL RTC_TOP_LOOP + + LD C,00H ; CP/M system reset call - shut down + CALL 0005H + + HALT ; This code is never reached + + +; function HEXSTR +; input number in A +; output upper nibble of number in ASCII in H +; output lower nibble of number in ASCII in L +; uses BC +; +; based on following algorithm: +: +; const +; hextab : string = ('0','1','2','3','4','5','6','7','8', +; '9','A','B','C','D','E','F'); +; +; PROCEDURE hexstr(n: int): ^string; +; BEGIN +; n := n and 255; +; tmpstr[1] := hextab[n / 16]; +; tmpstr[2] := hextab[n and 15]; +; tmpstr[0] := #2; +; return @tmpstr; +; END; + + +HEXSTR: + PUSH BC ;SAVE BC + LD B,A + RLC A ;DO HIGH NIBBLE FIRST + RLC A + RLC A + RLC A + AND 0FH ;ONLY THIS NOW + ADD A,30H ;TRY A NUMBER + CP 3AH ;TEST IT + JR C,HEXSTR1 ;IF CY SET SAVE 'NUMBER' in H + ADD A,07H ;MAKE IT AN ALPHA +HEXSTR1: + LD H,A ;SAVE 'ALPHA' in H + LD A,B ;NEXT NIBBLE + AND 0FH ;JUST THIS + ADD A,30H ;TRY A NUMBER + CP 3AH ;TEST IT + JR C,HEXSTR2 ;IF CY SET SAVE 'NUMBER' in L + ADD A,07H ;MAKE IT ALPHA + +HEXSTR2: + LD L,A ;SAVE 'ALPHA' in L + POP BC ;RESTORE BC + RET + + +;***************************************************** +;* GET K.B. DATA & MAKE IT 'HEX' +;***************************************************** + +HEXIN: + PUSH BC ;SAVE BC REGS. + CALL NIBL ;DO A NIBBLE + RLC A ;MOVE FIRST BYTE UPPER NIBBLE + RLC A + RLC A + RLC A + LD B,A ;SAVE ROTATED BYTE + PUSH BC + + CALL NIBL ;DO NEXT NIBBLE + POP BC + ADD A,B ;COMBINE NIBBLES IN ACC. + POP BC ;RESTORE BC + RET ;DONE +NIBL: + LD C,01H ; CP/M console input call + CALL 0005H ;GET K.B. DATA + CP 40H ;TEST FOR ALPHA + JR NC,ALPH + AND 0FH ;GET THE BITS + RET +ALPH: + AND 0FH ;GET THE BITS + ADD A,09H ;MAKE IT HEX A-F + RET + +; function RTC_IN +; +; read a byte from RTC port, return in A +; NOTE: port address is dynamically set in RTC_INIT + +RTC_IN: +INP .EQU $ + 1 + IN A,($FF) + RET + +; function RTC_OUT +; +; write a byte to RTC port, value in A +; NOTE: port address is dynamically set in RTC_INIT + +RTC_OUT: +OUTP .EQU $ + 1 + OUT ($FF),A + RET + +; function RTC_BIT_DELAY +; +; based on following algorithm: +; +; { Make a short delay } +; PROCEDURE rtc_bit_delay; +; var +; x : int; +; BEGIN +; x := 3; +; END; + +RTC_BIT_DELAY: ; purpose is to delay ~36 uS or 144 t-states at 4MHz + PUSH AF ; 11 t-states + LD A,07H ; 7 t-states ADJUST THE TIME 13h IS FOR 4 MHZ +RTC_BIT_DELAY1: + DEC A ; 4 t-states DEC COUNTER. 4 T-states = 1 uS. + JP NZ,RTC_BIT_DELAY1 ; 10 t-states JUMP TO PAUSELOOP2 IF A <> 0. + + NOP ; 4 t-states + NOP ; 4 t-states + POP AF ; 10 t-states + RET ; 10 t-states (144 t-states total) + + +; function RTC_RESET +; +; based on following algorithm: +; +; { Output a RTC reset signal } +; PROCEDURE rtc_reset; +; BEGIN +; out(rtc_base,mask_data + mask_rd); +; rtc_bit_delay(); +; rtc_bit_delay(); +; out(rtc_base,mask_data + mask_rd + mask_rst); +; rtc_bit_delay(); +; rtc_bit_delay(); +; END; +; +RTC_RESET: + LD A,mask_data + mask_rd + ;OUT (RTC),A + CALL RTC_OUT + CALL RTC_BIT_DELAY + CALL RTC_BIT_DELAY + LD A,mask_data + mask_rd + mask_rst + ;OUT (RTC),A + CALL RTC_OUT + CALL RTC_BIT_DELAY + CALL RTC_BIT_DELAY + RET + + +; function RTC_RESET_ON +; +; based on following algorithm: +; +; { Assert RTC reset signal } +; PROCEDURE rtc_reset_on; +; BEGIN +; out(rtc_base,mask_data + mask_rd); +; rtc_bit_delay(); +; rtc_bit_delay(); +; END; + +RTC_RESET_ON: + LD A,mask_data + mask_rd + ;OUT (RTC),A + CALL RTC_OUT + CALL RTC_BIT_DELAY + CALL RTC_BIT_DELAY + RET + +; function RTC_RESET_OFF +; +; based on following algorithm: +; +; { De-assert RTC reset signal } +; PROCEDURE rtc_reset_off; +; BEGIN +; out(rtc_base,mask_data + mask_rd + mask_rst); +; rtc_bit_delay(); +; rtc_bit_delay(); +; END; + +RTC_RESET_OFF: + LD A,mask_data + mask_rd + mask_rst + ;OUT (RTC),A + CALL RTC_OUT + CALL RTC_BIT_DELAY + CALL RTC_BIT_DELAY + RET + +; function RTC_WR +; input value in C +; uses A +; +; PROCEDURE rtc_wr(n : int); +; var +; i : int; +; BEGIN +; for i := 0 while i < 8 do inc(i) loop +; if (n and 1) <> 0 then +; out(rtc_base,mask_rst + mask_data); +; rtc_bit_delay(); +; out(rtc_base,mask_rst + mask_clk + mask_data); +; else +; out(rtc_base,mask_rst); +; rtc_bit_delay(); +; out(rtc_base,mask_rst + mask_clk); +; end; +; rtc_bit_delay(); +; n := shr(n,1); +; end loop; +; END; + +RTC_WR: + XOR A ; set A=0 index counter of FOR loop + +RTC_WR1: + PUSH AF ; save accumulator as it is the index counter in FOR loop + LD A,C ; get the value to be written in A from C (passed value to write in C) + BIT 0,A ; is LSB a 0 or 1? + JP Z,RTC_WR2 ; if it’s a 0, handle it at RTC_WR2. + ; LSB is a 1, handle it below + ; setup RTC latch with RST and DATA high, SCLK low + LD A,mask_rst + mask_data + ;OUT (RTC),A ; output to RTC latch + CALL RTC_OUT + CALL RTC_BIT_DELAY ; let it settle a while + ; setup RTC with RST, DATA, and SCLK high + LD A,mask_rst + mask_clk + mask_data + ;OUT (RTC),A ; output to RTC latch + CALL RTC_OUT + JP RTC_WR3 ; exit FOR loop + +RTC_WR2: + ; LSB is a 0, handle it below + LD A,mask_rst ; setup RTC latch with RST high, SCLK and DATA low + ;OUT (RTC),A ; output to RTC latch + CALL RTC_OUT + CALL RTC_BIT_DELAY ; let it settle a while + ; setup RTC with RST and SCLK high, DATA low + LD A,mask_rst + mask_clk + ;OUT (RTC),A ; output to RTC latch + CALL RTC_OUT + +RTC_WR3: + CALL RTC_BIT_DELAY ; let it settle a while + RRC C ; move next bit into LSB position for processing to RTC + POP AF ; recover accumulator as it is the index counter in FOR loop + INC A ; increment A in FOR loop (A=A+1) + CP $08 ; is A < $08 ? + JP NZ,RTC_WR1 ; No, do FOR loop again + RET ; Yes, end function and return + + +; function RTC_RD +; output value in C +; uses A +; +; function RTC_RD +; +; PROCEDURE rtc_rd(): int ; +; var +; i,n,mask : int; +; BEGIN +; n := 0; +; mask := 1; +; for i := 0 while i < 8 do inc(i) loop +; out(rtc_base,mask_rst + mask_rd); +; rtc_bit_delay(); +; if (in(rtc_base) and #1) <> #0 then +; { Data = 1 } +; n := n + mask; +; else +; { Data = 0 } +; end; +; mask := shl(mask,1); +; out(rtc_base,mask_rst + mask_clk + mask_rd); +; rtc_bit_delay(); +; end loop; +; return n; +; END; + +RTC_RD: + XOR A ; set A=0 index counter of FOR loop + LD C,$00 ; set C=0 output of RTC_RD is passed in C + LD B,$01 ; B is mask value + +RTC_RD1: + PUSH AF ; save accumulator as it is the index counter in FOR loop + ; setup RTC with RST and RD high, SCLK low + LD A,mask_rst + mask_rd + ;OUT (RTC),A ; output to RTC latch + CALL RTC_OUT + CALL RTC_BIT_DELAY ; let it settle a while + ;IN A,(RTC) ; input from RTC latch + CALL RTC_IN ; input from RTC latch + BIT 0,A ; is LSB a 0 or 1? + JP Z,RTC_RD2 ; if LSB is a 1, handle it below + LD A,C + ADD A,B + LD C,A +; INC C + ; if LSB is a 0, skip it (C=C+0) +RTC_RD2: + RLC B ; move input bit out of LSB position to save it in C + ; setup RTC with RST, SCLK high, and RD high + LD A,mask_rst + mask_clk + mask_rd + ;OUT (RTC),A ; output to RTC latch + CALL RTC_OUT + CALL RTC_BIT_DELAY ; let it settle + POP AF ; recover accumulator as it is the index counter in FOR loop + INC A ; increment A in FOR loop (A=A+1) + CP $08 ; is A < $08 ? + JP NZ,RTC_RD1 ; No, do FOR loop again + RET ; Yes, end function and return. Read RTC value is in C + +; function RTC_WRITE +; input address in D +; input value in E +; uses A +; +; based on following algorithm: +; +; PROCEDURE rtc_write(address, value: int); +; BEGIN +; lock(); +; rtc_reset_off(); +; { Write command } +; rtc_wr(128 + shl(address and $3f,1)); +; { Write data } +; rtc_wr(value and $ff); +; rtc_reset_on(); +; unlock(); +; END; + +RTC_WRITE: + DI ; disable interrupts during critical section + CALL RTC_RESET_OFF ; turn off RTC reset + LD A,D ; bring into A the address from D +; AND $3F ; keep only bits 6 LSBs, discard 2 MSBs + AND %00111111 ; keep only bits 6 LSBs, discard 2 MSBs + RLC A ; rotate address bits to the left +; ADD A,$80 ; set MSB to one for DS1302 COMMAND BYTE (WRITE) + ADD A,%10000000 ; set MSB to one for DS1302 COMMAND BYTE (WRITE) + LD C,A ; RTC_WR expects write data (address) in reg C + CALL RTC_WR ; write address to DS1302 + LD A,E ; start processing value + AND $FF ; seems unnecessary, probably delete since all values are 8-bit + LD C,A ; RTC_WR expects write data (value) in reg C + CALL RTC_WR ; write address to DS1302 + CALL RTC_RESET_ON ; turn on RTC reset + EI + RET + + +; function RTC_READ +; input address in D +; output value in C +; uses A +; +; based on following algorithm +; +; PROCEDURE rtc_read(address: int): int; +; var +; n : int; +; BEGIN +; lock(); +; rtc_reset_off(); +; { Write command } +; rtc_wr(128 + shl(address and $3f,1) + 1); +; { Read data } +; n := rtc_rd(); +; rtc_reset_on(); +; unlock(); +; return n; +; END; + +RTC_READ: + DI ; disable interrupts during critical section + CALL RTC_RESET_OFF ; turn off RTC reset + LD A,D ; bring into A the address from D + AND $3F ; keep only bits 6 LSBs, discard 2 MSBs + RLC A ; rotate address bits to the left + ADD A,$81 ; set MSB to one for DS1302 COMMAND BYTE (READ) + LD C,A ; RTC_WR expects write data (address) in reg C + CALL RTC_WR ; write address to DS1302 + CALL RTC_RD ; read value from DS1302 (value is in reg C) + CALL RTC_RESET_ON ; turn on RTC reset + EI + RET + + +; function RTC_WR_PROTECT +; input D (address) $07 +; input E (value) $80 +; uses A +; +; based on following algorithm +; +; PROCEDURE rtc_wr_protect; +; BEGIN +; rtc_write(7,128); +; END; + +RTC_WR_PROTECT: +; LD D,$07 + LD D,%00000111 +; LD E,$80 + LD E,%10000000 + CALL RTC_WRITE + RET + + +; function RTC_WR_UNPROTECT +; input D (address) $07 +; input E (value) $00 +; uses A +; +; based on following algorithm +; +; PROCEDURE rtc_wr_unprotect; +; BEGIN +; rtc_write(7,0); +; END; + +RTC_WR_UNPROTECT: +; LD D,$07 + LD D,%00000111 +; LD E,$00 + LD E,%00000000 + CALL RTC_WRITE + RET + + +; function RTC_GET_TIME +; input HL (memory address of buffer) +; uses A,C,D,E +; +; based on following algorithm +; +; PROCEDURE rtc_get_time(var buf: string); +; var +; n : int; +; BEGIN +; lock(); +; rtc_reset_off(); +; { Write command, burst read } +; rtc_wr(255 - 64); +; { Read seconds } +; n := rtc_rd(); 0 +; buf[16] := char(((n / 16) and $07)) + '0'; +; buf[17] := char((n and $0f)) + '0'; +; { Read minutes } +; n := rtc_rd(); 1 +; buf[13] := char(((n / 16) and $07)) + '0'; +; buf[14] := char((n and $0f)) + '0'; +; buf[15] := ':'; +; { Read hours } +; n := rtc_rd(); 2 +; buf[10] := char(((n / 16) and $03)) + '0'; +; buf[11] := char((n and $0f)) + '0'; +; buf[12] := ':'; +; { Read date } +; n := rtc_rd(); 3 +; buf[7] := char(((n / 16) and $03)) + '0'; +; buf[8] := char((n and $0f)) + '0'; +; buf[9] := ' '; +; { Read month } +; n := rtc_rd(); 4 +; buf[4] := char(((n / 16) and $03)) + '0'; +; buf[5] := char((n and $0f)) + '0'; +; buf[6] := '-'; +; { Read day } +; n := rtc_rd(); 5 +; { +; buf[4] := char(((n / 16) and $03)) + '0'; +; buf[4] := char((n and $0f)) + '0'; +; } +; { Read year } +; n := rtc_rd(); 6 +; buf[1] := char(((n / 16) and $0f)) + '0'; +; buf[2] := char((n and $0f)) + '0'; +; buf[3] := '-'; +; length(buf) := 17; +; rtc_reset_on(); +; unlock(); +; END rtc_get_time; + +RTC_GET_TIME: + DI ; disable interrupts during DS1302 read + CALL RTC_RESET_OFF ; turn of RTC reset + ; { Write command, burst read } + LD C,%10111111 ; (255 - 64) + CALL RTC_WR ; send COMMAND BYTE (BURST READ) to DS1302 + +; { Read seconds } + + CALL RTC_RD ; read value from DS1302, value is in Reg C + + ; digit 16 + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $07 + ADD A,'0' + LD (RTC_PRINT_BUFFER+15),A + + ; digit 17 + LD A,C ; put value output in Reg C into accumulator + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+16),A + +; { Read minutes } + + CALL RTC_RD ; read value from DS1302, value is in Reg C + + ; digit 13 + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $07 + ADD A,'0' + LD (RTC_PRINT_BUFFER+12),A + + ; digit 14 + LD A,C ; put value output in Reg C into accumulator + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+13),A + + ; digit 15 + LD A,':' + LD (RTC_PRINT_BUFFER+14),A + +; { Read hours } + + CALL RTC_RD ; read value from DS1302, value is in Reg C + + ; digit 10 + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $03 + ADD A,'0' + LD (RTC_PRINT_BUFFER+09),A + + ; digit 11 + LD A,C ; put value output in Reg C into accumulator + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+10),A + + ; digit 12 + LD A,':' + LD (RTC_PRINT_BUFFER+11),A + +; { Read date } + + CALL RTC_RD ; read value from DS1302, value is in Reg C + + ; digit 07 + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $03 + ADD A,'0' + LD (RTC_PRINT_BUFFER+06),A + + ; digit 08 + LD A,C ; put value output in Reg C into accumulator + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+07),A + + ; digit 09 + LD A,' ' + LD (RTC_PRINT_BUFFER+08),A + +; { Read month } + + CALL RTC_RD ; read value from DS1302, value is in Reg C + + ; digit 04 + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $03 + ADD A,'0' + LD (RTC_PRINT_BUFFER+03),A + + ; digit 05 + LD A,C ; put value output in Reg C into accumulator + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+04),A + + ; digit 06 + LD A,'-' + LD (RTC_PRINT_BUFFER+05),A + +; { Read day } + + CALL RTC_RD ; read value from DS1302, value is in Reg C + + ; digit 04 +; LD A,C ; put value output in Reg C into accumulator +; RLC A +; RLC A +; RLC A +; RLC A +; AND $03 +; ADD A,'0' +; LD (RTC_PRINT_BUFFER+03),A + + ; digit 04 +; LD A,C ; put value output in Reg C into accumulator +; AND $0F +; ADD A,'0' +; LD (RTC_PRINT_BUFFER+03),A + +; add special code to put "DAY" value at end of string until better solution known + + ; digit 18 + LD A,'-' + LD (RTC_PRINT_BUFFER+17),A + + ; digit 19 + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+18),A + + ; digit 20 + LD A,C ; put value output in Reg C into accumulator + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+19),A + + + + +; { Read year } + + CALL RTC_RD ; read value from DS1302, value is in Reg C + + ; digit 01 + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+00),A + + ; digit 02 + LD A,C ; put value output in Reg C into accumulator + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+01),A + + ; digit 03 + LD A,'-' + LD (RTC_PRINT_BUFFER+02),A + + CALL RTC_RESET_ON ; turn RTC reset back on + EI ; re-enable interrupts + + RET ; Yes, end function and return + + +; function RTC_SET_NOW +; uses A, D, E +; +; based on following algorithm +; +; { Set time to 96-02-18 19:43:00 } +; PROCEDURE rtc_set_now; +; BEGIN +; rtc_wr_unprotect(); +; { Set seconds } +; rtc_write(0,0); +; { Set minutes } +; rtc_write(1,$43); +; { Set hours } +; rtc_write(2,$19); +; { Set date } +; rtc_write(3,$18); +; { Set month } +; rtc_write(4,$02); +; { Set day } +; rtc_write(5,$07); +; { Set year } +; rtc_write(6,$96); +; rtc_wr_protect(); +; END; + +RTC_SET_NOW: +; set time to 07-02-23 19:45:00-05 <-Friday + CALL RTC_WR_UNPROTECT +; seconds + LD D,$00 + LD A,(SECONDS) + LD E,A + CALL RTC_WRITE + +; minutes + LD D,$01 + LD A,(MINUTES) + LD E,A + CALL RTC_WRITE + +; hours + LD D,$02 + LD A,(HOURS) + LD E,A + CALL RTC_WRITE + +; date + LD D,$03 + LD A,(DATE) + LD E,A + CALL RTC_WRITE + +; month + LD D,$04 + LD A,(MONTH) + LD E,A + CALL RTC_WRITE + +; day + LD D,$05 + LD A,(DAY) + LD E,A + CALL RTC_WRITE + +; year + LD D,$06 + LD A,(YEAR) + LD E,A + CALL RTC_WRITE + + CALL RTC_WR_PROTECT + RET + +RTC_INIT_NOW: +; set time to Current Time + +; year + LD DE,RTC_TOP_LOOP1_INIT_YEAR + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL HEXIN + LD (YEAR),A + +; month + LD DE,RTC_TOP_LOOP1_INIT_MONTH + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL HEXIN + LD (MONTH),A + +; date + LD DE,RTC_TOP_LOOP1_INIT_DATE + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL HEXIN + LD (DATE),A + +; hours + LD DE,RTC_TOP_LOOP1_INIT_HOURS + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL HEXIN + LD (HOURS),A + +; minutes + LD DE,RTC_TOP_LOOP1_INIT_MINUTES + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL HEXIN + LD (MINUTES),A + +; seconds + LD DE,RTC_TOP_LOOP1_INIT_SECONDS + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL HEXIN + LD (SECONDS),A + +; day + LD DE,RTC_TOP_LOOP1_INIT_DAY + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL HEXIN + LD (DAY),A + + RET + + +; function RTC_RESTART +; +; uses A, D, E, +; +; based on the following algorithm +; +; { Restart clock, set seconds to 00 } +; PROCEDURE rtc_restart; +; BEGIN +; rtc_wr_unprotect(); +; { Set seconds } +; rtc_write(0,0); +; rtc_wr_protect(); +; END; + +RTC_RESTART: + CALL RTC_WR_UNPROTECT + LD D,$00 + LD E,$00 + CALL RTC_WRITE + CALL RTC_WR_PROTECT + RET + + +; function RTC_CHARGE_ENABLE +; +; uses A, D, E +; +; based on following algorithm +; +; PROCEDURE rtc_charge_enable; +; BEGIN +; rtc_wr_unprotect(); +; { Enable trickle charger, 2kohm, 1 diode } +; rtc_write(8,$A5); +; rtc_wr_protect(); +; END; +; +; Trickle Charge Current: +; +; Imax = (5.0V - (0.7 * Ndiode)) / R +; (5.0 - (0.7 * 1)) / 2000 = .00215A = 2.15 milliamps +; (5.0 - (0.7 * 1)) / 8000 = 0.0005375A = .537 milliamps +; + +RTC_CHARGE_ENABLE + CALL RTC_WR_UNPROTECT + LD D,$08 + LD E,$A5 + CALL RTC_WRITE + CALL RTC_WR_PROTECT + RET + + +; function RTC_CHARGE_DISABLE +; +; uses A, D, E +; +; based on following algorithm +; +; PROCEDURE rtc_charge_disable; +; BEGIN +; rtc_wr_unprotect(); +; { Disable trickle charger} +; rtc_write(8,$00); +; rtc_wr_protect(); +; END; + +RTC_CHARGE_DISABLE + CALL RTC_WR_UNPROTECT + LD D,$08 + LD E,$00 + CALL RTC_WRITE + CALL RTC_WR_PROTECT + RET + + +; function TEST_BIT_DELAY +; +; based on the following algorithm +; +; +; PROCEDURE test_bit_delay(); +; var +; i,t0,t1 : int; +; BEGIN +; putln("Testing bit delay..."); +; t0 := sys_time(); +; for i := 0 while i < 1000 do inc(i) loop +; rtc_bit_delay(); +; end loop; +; t1 := sys_time(); +; putln(i," rtc_bit_delay calls took ",t1-t0," ms."); +; END; + +RTC_TEST_BIT_DELAY + LD DE,TESTING_BIT_DELAY_MSG + LD C,09H ; CP/M write string to console call + CALL 0005H + LD C,01H ; CP/M console input call + CALL 0005H + + ; test should take approximately 43 seconds based on the following code analysis + ; of Z80 T-states on a 4 MHz processor + ; =(4+15*(7+255*(7+255*(17+144+4+10)+4+10)+10)+7)/4/1000000 + + LD B,$0F +PAUSE: + LD C,$FF +PAUSE1: + LD A,$FF ; ADJUST THE TIME 13h IS FOR 4 MHZ +PAUSE2: + CALL RTC_BIT_DELAY ; CAUSE 36uS DELAY + DEC A ; DEC COUNTER. + JP NZ,PAUSE2 ; JUMP TO PAUSE2 IF A <> 0. + DEC C ; DEC COUNTER + JP NZ,PAUSE1 ; JUMP TO PAUSE1 IF C <> 0. + DJNZ PAUSE ; JUMP TO PAUSE IF B <> 0. + + LD DE,TESTING_BIT_DELAY_OVER + LD C,09H ; CP/M write string to console call + CALL 0005H + RET + + +; function RTC_HELP +; +; based on following algorithm +; +; PROCEDURE help(); +; BEGIN +; putln(); +; putln("rtc: ",version); +; putln("rtc: Commands: (E)xit (T)ime st(A)rt (S)et (R)aw (L)oop (C)harge (N)ocharge (H)elp"); +; END; + +RTC_HELP + LD DE,RTC_HELP_MSG + LD C,09H ; CP/M write string to console call + CALL 0005H + RET + +; function RTC_INIT +; +; Determine RTC port based on hardware platform +; and record it dynamically in code (see RTC_IN and RTC_OUT). +; + +RTC_INIT: + CALL IDBIO ; Id BIOS, 1=HBIOS, 2=UBIOS + DEC A ; Test for HBIOS + JR Z,HINIT ; Do HBIOS setup + DEC A ; Test for UBIOS + JR Z,UINIT ; Do UBIOS setup +; + ; Neither UNA nor RomWBW + LD DE,BIOERR ; BIOS error message + LD C,9 ; BDOS string display function + CALL BDOS ; Do it + JP 0 ; Bail out! +; +HINIT: +; + ; Display RomWBW notification string + LD DE,HBTAG ; BIOS notification string + LD C,9 ; BDOS string display function + CALL BDOS ; Do it +; + ; Get platform id from RomWBW HBIOS + LD B,0F1H ; HBIOS VER function 0xF1 + LD C,0 ; Required reserved value + RST 08 ; Do it, L := Platform ID + LD A,L ; Move to A +; + ; Assign correct port to C + LD C,PORT_SBC + LD DE,PLT_SBC + CP $01 ; SBC + JR Z,RTC_INIT2 + CP $02 ; ZETA + JR Z,RTC_INIT2 + CP $03 ; ZETA 2 + JR Z,RTC_INIT2 + LD C,PORT_N8 + LD DE,PLT_N8 + CP $04 ; N8 + JR Z,RTC_INIT2 + LD C,PORT_MK4 + LD DE,PLT_MK4 + CP $05 ; Mark IV + JR Z,RTC_INIT2 +; + ; Unknown platform + LD DE,PLTERR ; BIOS error message + LD C,9 ; BDOS string display function + CALL BDOS ; Do it + JP 0 ; Bail out! +; +UINIT: + ;; Display UNA notification string + ;LD DE,UBTAG ; BIOS notification string + ;LD C,9 ; BDOS string display function + ;CALL BDOS ; Do it +; + ; Notify UNA not supported at present + LD DE,UBERR ; BIOS not support message + LD C,9 ; BDOS string display function + CALL BDOS ; Do it + JP 0 ; Bail out! + +RTC_INIT2: + ; Record port number in code routines + LD A,C + LD (INP),A + LD (OUTP),A +; + ; Display platform + LD C,9 ; BDOS string display function + CALL BDOS ; Do it + RET + +; +; Identify active BIOS. RomWBW HBIOS=1, UNA UBIOS=2, else 0 +; +IDBIO: +; + ; Check for UNA (UBIOS) + LD A,(0FFFDH) ; fixed location of UNA API vector + CP 0C3H ; jp instruction? + JR NZ,IDBIO1 ; if not, not UNA + LD HL,(0FFFEH) ; get jp address + LD A,(HL) ; get byte at target address + CP 0FDH ; first byte of UNA push ix instruction + JR NZ,IDBIO1 ; if not, not UNA + INC HL ; point to next byte + LD A,(HL) ; get next byte + CP 0E5H ; second byte of UNA push ix instruction + JR NZ,IDBIO1 ; if not, not UNA, check others + LD A,2 ; UNA BIOS id = 2 + RET ; and done +; +IDBIO1: + ; Check for RomWBW (HBIOS) + LD HL,(0FFFEH) ; HL := HBIOS ident location + LD A,'W' ; First byte of ident + CP (HL) ; Compare + JR NZ,IDBIO2 ; Not HBIOS + INC HL ; Next byte of ident + LD A,~'W' ; Second byte of ident + CP (HL) ; Compare + JR NZ,IDBIO2 ; Not HBIOS + LD A,1 ; HBIOS BIOS id = 1 + RET ; and done +; +IDBIO2: + ; No idea what this is + XOR A ; Setup return value of 0 + RET ; and done + + +; function RTC_TOP_LOOP +; +; based on following algorithm +; +; PROCEDURE toploop(); +; var +; err,i,n,fd : int; +; BEGIN +; putln(); +; help(); +; rtc_reset_on(); +; hold(100); +; test_bit_delay(); +; rtc_charge_disable(); +; putln("rtc: trickle charger disabled."); +; loop +; put("rtc>"); +; gets(line); +; if line = "exit" then +; putln("Bye."); +; exit(0); +; elsif line = "charge" then +; putln("Trickle charger enabled."); +; rtc_charge_enable(); +; elsif line = "nocharge" then +; putln("Trickle charger disabled."); +; rtc_charge_disable(); +; elsif line = "start" then +; rtc_restart(); +; putln("Restarting RTC"); +; elsif line = "t" then +; rtc_get_time(line); +; putln("Current time: ",line); +; elsif line = "raw" then +; putln(); +; putln("Raw read loop, hit any key to stop..."); +; while read(0,@n,1 + RD_NOWAIT) = 0 loop +; put(#13,"sec=",hexstr(rtc_read(0))^); +; put(" min=",hexstr(rtc_read(1))^); +; hold(500); +; end loop; +; elsif line = "loop" then +; putln(); +; putln("Clock loop, hit any key to stop..."); +; while read(0,@n,1 + RD_NOWAIT) = 0 loop +; rtc_get_time(line); +; put(#13,line); +; hold(200); +; end loop; +; elsif line = "set" then +; putln("Setting RTC time to 96-02-18 19:43:00"); +; rtc_set_now(); +; elsif (line = "help") or (line = "?") then +; help(); +; elsif length(line) <> 0 then +; putln("You typed: """,line,""""); +; end; +; end loop; +; END toploop; + +RTC_TOP_LOOP: + LD DE,CRLF_MSG + LD C,09H ; CP/M write string to console call + CALL 0005H + + CALL RTC_HELP + + CALL RTC_RESET_ON + + CALL RTC_BIT_DELAY + CALL RTC_BIT_DELAY + CALL RTC_BIT_DELAY + +; CALL RTC_TEST_BIT_DELAY + +; CALL RTC_CHARGE_DISABLE ; *vk5dg* using supercap so leave on + +; LD DE,RTC_TOP_LOOP1_MSG +; LD C,09H ; CP/M write string to console call +; CALL 0005H + +RTC_TOP_LOOP_1: + LD DE,RTC_TOP_LOOP1_PROMPT + LD C,09H ; CP/M write string to console call + CALL 0005H + + LD C,01H ; CP/M console input call + CALL 0005H + + AND %01011111 ; handle lower case responses to menu + + CP 'E' + JP Z,RTC_TOP_LOOP_EXIT + + CP 'C' + JP Z,RTC_TOP_LOOP_CHARGE + + CP 'N' + JP Z,RTC_TOP_LOOP_NOCHARGE + + CP 'A' + JP Z,RTC_TOP_LOOP_START + + CP 'T' + JP Z,RTC_TOP_LOOP_TIME + + CP 'R' + JP Z,RTC_TOP_LOOP_RAW + + CP 'L' + JP Z,RTC_TOP_LOOP_LOOP + + CP 'H' + JP Z,RTC_TOP_LOOP_HELP + + CP 'D' + JP Z,RTC_TOP_LOOP_DELAY + + CP 'S' + JP Z,RTC_TOP_LOOP_SET + + CP 'I' + JP Z,RTC_TOP_LOOP_INIT + + CP 'G' + JP Z,RTC_TOP_LOOP_GET + + CP 'P' + JP Z,RTC_TOP_LOOP_PUT + + LD DE,RTC_TOP_LOOP1_OTHER1 + LD C,09H ; CP/M write string to console call + CALL 0005H + + LD E,A + LD C,02H ; CP/M Console output call + CALL 0005H + + LD DE,RTC_TOP_LOOP1_OTHER2 + LD C,09H ; CP/M write string to console call + CALL 0005H + + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_EXIT: + RET + +RTC_TOP_LOOP_CHARGE: + LD DE,RTC_TOP_LOOP1_CHARGE + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL RTC_CHARGE_ENABLE + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_NOCHARGE: + LD DE,RTC_TOP_LOOP1_NOCHARGE + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL RTC_CHARGE_DISABLE + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_START: + LD DE,RTC_TOP_LOOP1_START + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL RTC_RESTART + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_TIME: + LD DE,RTC_TOP_LOOP1_TIME + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL RTC_GET_TIME + LD DE,RTC_PRINT_BUFFER + LD C,09H ; CP/M write string to console call + CALL 0005H + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_RAW: + LD DE,RTC_TOP_LOOP1_RAW + LD C,09H ; CP/M write string to console call + CALL 0005H +RTC_TOP_LOOP_RAW1: + +; { Read seconds } + LD D,$00 ; seconds register in DS1302 + CALL RTC_READ ; read value from DS1302, value is in Reg C + + ; digit 16 + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $07 + ADD A,'0' + LD (RTC_PRINT_BUFFER+15),A + + ; digit 17 + LD A,C ; put value output in Reg C into accumulator + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+16),A + +; { Read minutes } + + LD D,$01 ; minutes register in DS1302 + CALL RTC_READ ; read value from DS1302, value is in Reg C + + ; digit 13 + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $07 + ADD A,'0' + LD (RTC_PRINT_BUFFER+12),A + + ; digit 14 + LD A,C ; put value output in Reg C into accumulator + AND $0F + ADD A,'0' + LD (RTC_PRINT_BUFFER+13),A + + ; digit 15 + LD A,':' + LD (RTC_PRINT_BUFFER+14),A + + ; digits 1-12 and 18-20 are spaces + LD A,' ' ; space + LD (RTC_PRINT_BUFFER+19),A + LD (RTC_PRINT_BUFFER+18),A + LD (RTC_PRINT_BUFFER+17),A + LD (RTC_PRINT_BUFFER+11),A + LD (RTC_PRINT_BUFFER+10),A + LD (RTC_PRINT_BUFFER+09),A + LD (RTC_PRINT_BUFFER+08),A + LD (RTC_PRINT_BUFFER+07),A + LD (RTC_PRINT_BUFFER+06),A + LD (RTC_PRINT_BUFFER+05),A + LD (RTC_PRINT_BUFFER+04),A + LD (RTC_PRINT_BUFFER+03),A + LD (RTC_PRINT_BUFFER+02),A + LD (RTC_PRINT_BUFFER+01),A + LD (RTC_PRINT_BUFFER+00),A + + LD DE,RTC_PRINT_BUFFER + LD C,09H ; CP/M write string to console call + CALL 0005H + + LD C,01H ; CP/M console input call + CALL 0005H + + CP ' ' ; space + JP Z,RTC_TOP_LOOP_RAW1 + + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_LOOP: + LD DE,RTC_TOP_LOOP1_LOOP + LD C,09H ; CP/M write string to console call + CALL 0005H + +RTC_TOP_LOOP_LOOP1: + CALL RTC_GET_TIME + + LD DE,RTC_PRINT_BUFFER + LD C,09H ; CP/M write string to console call + CALL 0005H + + LD C,01H ; CP/M console input call + CALL 0005H + + CP ' ' + JP Z,RTC_TOP_LOOP_LOOP1 + + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_SET: + LD DE,RTC_TOP_LOOP1_SET + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL RTC_SET_NOW + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_INIT: + LD DE,RTC_TOP_LOOP1_INIT + LD C,09H ; CP/M write string to console call + CALL 0005H + CALL RTC_INIT_NOW + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_DELAY: + CALL RTC_TEST_BIT_DELAY + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_HELP: + CALL RTC_HELP + JP RTC_TOP_LOOP_1 + +RTC_TOP_LOOP_PUT: + LD A,$01 ; set PUT as true + LD (GET_PUT),A +RTC_TOP_LOOP_GET: + LD DE,RTC_TOP_LOOP1_GET + LD C,09H ; CP/M write string to console call + CALL 0005H + + CALL HEXIN ; read NVRAM address + LD (PUT_ADR),A ; store for possible PUT later + +; { Read NVRAM address } + LD D,A ; seconds register in DS1302 + CALL RTC_READ ; read value from DS1302, value is in Reg C + + ; first digit + LD A,C ; put value output in Reg C into accumulator + RLC A + RLC A + RLC A + RLC A + AND $0F + CP 0AH ;TEST FOR NUMERIC & convert to ASCII + JR C,NUM1 ;if not ALPHA, its numeric and skip + ADD A,$07 + +NUM1: ADD A,'0' + LD (RTC_GET_BUFFER),A + + ; second digit + LD A,C ; put value output in Reg C into accumulator + AND $0F + CP 0AH ;TEST FOR NUMERIC & convert to ASCII + JR C,NUM2 ;if not ALPHA, its numeric and skip + ADD A,$07 + +NUM2: ADD A,'0' + LD (RTC_GET_BUFFER+1),A + + LD DE,RTC_TOP_LOOP1_OTHER2 + LD C,09H ; CP/M write string to console call + CALL 0005H + + LD DE,RTC_GET_BUFFER + LD C,09H ; CP/M write string to console call + CALL 0005H + + LD A,(GET_PUT) ; check if GET or PUT mode + CP $00 + JP Z,RTC_GET_PUT_EXIT ; if GET mode, exit + + LD DE,RTC_TOP_LOOP1_PUT + LD C,09H ; CP/M write string to console call + CALL 0005H + +; { Write NVRAM address } + + CALL RTC_WR_UNPROTECT + + CALL HEXIN ; read NVRAM address + LD E,A ; new data for NVRAM register in DS1302 + LD A,(PUT_ADR) + LD D,A ; load address from before + + CALL RTC_WRITE ; read value from DS1302, value is in Reg C + + CALL RTC_WR_PROTECT + +RTC_GET_PUT_EXIT: + LD A,$00 ; reset GET mode + LD (GET_PUT),A + JP RTC_TOP_LOOP_1 + + + + +; +; Text Strings +; + +MSG: + .TEXT "Start RTC Program" + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +CRLF_MSG: + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +TESTING_BIT_DELAY_MSG: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Testing bit delay. Successful test is ~43 sec." + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Start clock and press space bar." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +TESTING_BIT_DELAY_OVER: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Test complete. Stop clock." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_HELP_MSG: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "RTC: Version 1.1" + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "RTC: Commands: E)xit T)ime st(A)rt S)et R)aw L)oop C)harge N)ocharge D)elay I)nit G)et P)ut H)elp" + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_MSG: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "RTC: trickle charger disabled." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_PROMPT: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "RTC>" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_CHARGE: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Trickle charger enabled." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_NOCHARGE: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Trickle charger disabled." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_START: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Restart RTC." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_TIME: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Current time: " + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_RAW: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Raw read Loop. Press SPACE BAR for next." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_LOOP: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Clock Loop. Press SPACE BAR for next." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_SET: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Set RTC time." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_INIT: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Init date/time." + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_GET: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "Get NVRAM addr:" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_PUT: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "NVRAM data:" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_INIT_SECONDS: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "SECONDS:" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_INIT_MINUTES: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "MINUTES:" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_INIT_HOURS: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "HOURS:" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_INIT_DATE: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "DATE:" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_INIT_MONTH: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "MONTH:" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_INIT_DAY: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "DAY:" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_INIT_YEAR: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "YEAR:" + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_OTHER1: + .DB 0Ah, 0Dh ; line feed and carriage return + .TEXT "YOU TYPED: " + .DB "$" ; Line terminator + +RTC_TOP_LOOP1_OTHER2: + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; Line terminator + +RTC_PRINT_BUFFER: + .FILL 20,0 ; Buffer for formatted date & time to print + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; line terminator + +RTC_GET_BUFFER: + .FILL 2,0 ; Buffer for formatted NVRAM data to print + .DB 0Ah, 0Dh ; line feed and carriage return + .DB "$" ; line terminator + +BIOERR .TEXT "Unknown BIOS, aborting...\r\n$" +PLTERR .TEXT "Unknown hardware platform, aborting...\r\n$" +UBERR .TEXT "UNA UBIOS is not currently supported, aborting...\r\n$" +HBTAG .TEXT "RomWBW HBIOS$" +UBTAG .TEXT "UNA UBIOS" +PLT_SBC .TEXT ", RTC Latch Port 0x70\r\n$" +PLT_N8 .TEXT ", RTC Latch Port 0x88\r\n$" +PLT_MK4 .TEXT ", RTC Latch Port 0x8A\r\n$" + +; +; Generic FOR-NEXT loop algorithm +; +; LD A,$00 ; set A=0 index counter of FOR loop +;FOR_LOOP: +; PUSH AF ; save accumulator as it is the index counter in FOR loop +; { contents of FOR loop here } ; setup RTC with RST and RD high, SCLK low +; POP AF ; recover accumulator as it is the index counter in FOR loop +; INC A ; increment A in FOR loop (A=A+1) +; CP $08 ; is A < $08 ? +; JP NZ,FOR_LOOP ; No, do FOR loop again +; RET ; Yes, end function and return. Read RTC value is in C + +YEAR .DB $17 +MONTH .DB $11 +DATE .DB $29 +HOURS .DB $00 +MINUTES .DB $00 +SECONDS .DB $00 +DAY .DB $04 +GET_PUT .DB $00 + +PUT_ADR .DB 0 + + .END + diff --git a/Source/RomDsk/MK4/RTC.COM b/Source/RomDsk/MK4/RTC.COM deleted file mode 100644 index 64788f53..00000000 Binary files a/Source/RomDsk/MK4/RTC.COM and /dev/null differ diff --git a/Source/RomDsk/N8/RTC.COM b/Source/RomDsk/N8/RTC.COM deleted file mode 100644 index c644663a..00000000 Binary files a/Source/RomDsk/N8/RTC.COM and /dev/null differ diff --git a/Source/RomDsk/SBC/RTC.COM b/Source/RomDsk/SBC/RTC.COM deleted file mode 100644 index da0aebc1..00000000 Binary files a/Source/RomDsk/SBC/RTC.COM and /dev/null differ diff --git a/Source/RomDsk/ZETA/RTC.COM b/Source/RomDsk/ZETA/RTC.COM deleted file mode 100644 index b36725f3..00000000 Binary files a/Source/RomDsk/ZETA/RTC.COM and /dev/null differ diff --git a/Source/RomDsk/ZETA2/RTC.COM b/Source/RomDsk/ZETA2/RTC.COM deleted file mode 100644 index b36725f3..00000000 Binary files a/Source/RomDsk/ZETA2/RTC.COM and /dev/null differ