You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1750 lines
38 KiB

.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
;
;[2018/11/8] v1.2 PMS Add boot option. Code optimization.
;
;[2019/06/21] v1.3 Finalized RC2014 Z180 support.
;
;[2019/08/11] v1.4 Support SCZ180 platform.
;
;[2020/02/02] v1.5 PMS Basic command line support
;
;[2020/05/15] v1.6 Added Warm Start option
;
; 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
PORT_RCZ80 .EQU $C0 ; RTC port for RC2014
PORT_RCZ180 .EQU $0C ; RTC port for RC2014
PORT_SCZ180 .EQU $0C ; RTC port for SBCZ180
PORT_EZZ80 .EQU $C0 ; RTC port for EZZ80 (actually does not have one!!!)
BDOS .EQU 5 ; BDOS invocation vector
FCB .EQU 05CH ; Start of command line
;BID_BOOT .EQU $00
;HB_BNKCALL .EQU $FFF9
BF_SYSRESET .EQU $F0 ; RESTART SYSTEM
BF_SYSRES_INT .EQU $00 ; RESET HBIOS INTERNAL
BF_SYSRES_WARM .EQU $01 ; WARM START (RESTART BOOT LOADER)
BF_SYSRES_COLD .EQU $02 ; COLD START
;
; 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
LD C,PORT_RCZ80
LD DE,PLT_RCZ80
CP $07 ; RC2014 w/ Z80
JR Z,RTC_INIT2
LD C,PORT_RCZ180
LD DE,PLT_RCZ180
CP $08 ; RC2014 w/ Z180
JR Z,RTC_INIT2
LD C,PORT_SCZ180
LD DE,PLT_SCZ180
CP $0A ; SCZ180
JR Z,RTC_INIT2
;LD C,PORT_EZZ80
;LD DE,PLT_EZZ80
;CP $09 ; Easy Z80
;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;
; Note:above code is not fully in sync with current menu code
RTC_TOP_LOOP:
CALL RTC_RESET_ON
CALL RTC_BIT_DELAY
CALL RTC_BIT_DELAY
CALL RTC_BIT_DELAY
LD A,(FCB+1) ; If there a command line tail
CP '/' ; get the command and feed it
LD A,(FCB+2) ; into the input stream
JR Z,RTC_UCL
LD DE,CRLF_MSG
LD C,09H ; CP/M write string to console call
CALL 0005H
CALL RTC_HELP
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
RTC_UCL:
AND %01011111 ; handle lower case responses to menu
CP 'L'
JP Z,RTC_TOP_LOOP_LOOP
CP 'R'
JP Z,RTC_TOP_LOOP_RAW
CP 'G'
JP Z,RTC_TOP_LOOP_GET
CP 'P'
JP Z,RTC_TOP_LOOP_PUT
CP 'E'
; JP Z,RTC_TOP_LOOP_EXIT
RET Z
CP 'H'
JP Z,RTC_TOP_LOOP_HELP
CP 'D'
JP Z,RTC_TOP_LOOP_DELAY
CP 'B'
JP Z,RTC_TOP_LOOP_BOOT
CP 'W'
JP Z,RTC_TOP_LOOP_WARMSTART
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 'S'
JP Z,RTC_TOP_LOOP_SET
CP 'I'
JP Z,RTC_TOP_LOOP_INIT
CP 'T'
JP Z,RTC_TOP_LOOP_TIME
LD DE,CRLF_MSG
LD C,09H ; CP/M write string to console call
CALL 0005H
JR RTC_TOP_LOOP_1
;RTC_TOP_LOOP_EXIT:
; RET
RTC_TOP_LOOP_HELP:
CALL RTC_HELP
JP RTC_TOP_LOOP_1
RTC_TOP_LOOP_DELAY:
CALL RTC_TEST_BIT_DELAY
JP RTC_TOP_LOOP_1
RTC_TOP_LOOP_BOOT:
LD DE,BOOTMSG ; BOOT message
LD C,9 ; BDOS string display function
CALL BDOS ; Do it
; WAIT FOR MESSAGE TO BE DISPLAYED
LD HL,10000
DELAY_LOOP: ; LOOP IS 26TS
DEC HL ; 6TS
LD A,H ; 4TS
OR L ; 4TS
JR NZ,DELAY_LOOP ; 12TS
; RESTART SYSTEM FROM ROM BANK 0, ADDRESS $0000
LD B,BF_SYSRESET ; SYSTEM RESTART
LD C,BF_SYSRES_COLD ; COLD START
CALL $FFF0 ; CALL HBIOS
RTC_TOP_LOOP_WARMSTART:
LD B,BF_SYSRESET ; SYSTEM RESTART
LD C,BF_SYSRES_WARM ; WARM START
CALL $FFF0 ; CALL HBIOS
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
LD A,(FCB+1) ; If we came from the
CP '/' ; command line
RET Z ; exit back to CP/M
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
LD A,(FCB+1) ; If we came from the
CP '/' ; command line
RET Z ; exit back to CP/M
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_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_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
LD A,(FCB+1) ; If we came from the
CP '/' ; command line
RET Z ; exit back to CP/M
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_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,CRLF_MSG
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"
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.5"
.DB 0Ah, 0Dh ; line feed and carriage return
.TEXT "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 B)oot W)arm-start H)elp"
.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_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 "\r\nUnknown BIOS, aborting...\r\n$"
PLTERR .TEXT "\r\n\r\nUnknown/unsupported hardware platform, aborting...\r\n$"
UBERR .TEXT "\r\nUNA UBIOS is not currently supported, aborting...\r\n$"
HBTAG .TEXT "RomWBW HBIOS$"
UBTAG .TEXT "UNA UBIOS"
BOOTMSG .TEXT "\r\n\r\nRebooting...$"
PLT_SBC .TEXT ", SBC/Zeta RTC Latch Port 0x70\r\n$"
PLT_N8 .TEXT ", N8 RTC Latch Port 0x88\r\n$"
PLT_MK4 .TEXT ", Mark 4 RTC Latch Port 0x8A\r\n$"
PLT_RCZ80 .TEXT ", RC2014 Z80 RTC Module Latch Port 0xC0\r\n$"
PLT_RCZ180 .TEXT ", RC2014 Z180 RTC Module Latch Port 0x0C\r\n$"
PLT_SCZ180 .TEXT ", SC Z180 RTC Module Latch Port 0x0C\r\n$"
PLT_EZZ80 .TEXT ", Easy Z80 RTC Module Latch Port 0xC0\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 $18
MONTH .DB $11
DATE .DB $08
HOURS .DB $00
MINUTES .DB $00
SECONDS .DB $00
DAY .DB $05
GET_PUT .DB $00
PUT_ADR .DB 0
.END