	.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 RCBus 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
;
;[2021/07/10] v1.7 Support MBC (AJL)
;
;[2022/03/27] v1.8 Support RHYOPHYRE
;
;[2023/07/07] v1.9 Support DUODYNE
;
;[2024/09/02] v1.10  Support Genesis STD Z180
;
; 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 RCBus
PORT_RCZ180	.EQU	$0C		; RTC port for RCBus
PORT_EZZ80	.EQU	$C0		; RTC port for EZZ80 (actually does not have one!!!)
PORT_SCZ180	.EQU	$0C		; RTC port for SCZ180
PORT_DYNO	.EQU	$0C		; RTC port for DYNO
PORT_RCZ280	.EQU	$C0		; RTC port for RCZ280
PORT_MBC	.EQU	$70		; RTC port for MBC
PORT_RPH	.EQU	$84		; RTC port for RHYOPHYRE
PORT_DUO	.EQU	$94		; RTC port for DUODYNE
PORT_STDZ180 .EQU $84         ; RTC Port for STD Bus Z180 board


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
	JP	Z,HINIT		; Do HBIOS setup
	DEC	A		; Test for UBIOS
	JP	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
	JP	Z,RTC_INIT2
	CP	$02		; ZETA
	JP	Z,RTC_INIT2
	CP	$03		; ZETA 2
	JP	Z,RTC_INIT2
;
	LD	C,PORT_N8
	LD	DE,PLT_N8
	CP	$04		; N8
	JP	Z,RTC_INIT2
;
	LD	C,PORT_MK4
	LD	DE,PLT_MK4
	CP	$05		; Mark IV
	JP	Z,RTC_INIT2
;
	LD	C,PORT_RCZ80
	LD	DE,PLT_RCZ80
	CP	$07		; RCBus w/ Z80
	JP	Z,RTC_INIT2
;
	LD	C,PORT_RCZ180
	LD	DE,PLT_RCZ180
	CP	$08		; RCBus w/ Z180
	JP	Z,RTC_INIT2
;
	LD	C,PORT_EZZ80
	LD	DE,PLT_EZZ80
	CP	$09		; Easy Z80
	JP	Z,RTC_INIT2
;
	LD	C,PORT_SCZ180
	LD	DE,PLT_SCZ180
	CP	$0A		; SCZ180
	JP	Z,RTC_INIT2
;
	LD	C,PORT_DYNO
	LD	DE,PLT_DYNO
	CP	11		; DYNO
	JP	Z,RTC_INIT2
;
	LD	C,PORT_RCZ280
	LD	DE,PLT_RCZ280
	CP	12		; RCZ280
	JP	Z,RTC_INIT2
;
	LD	C,PORT_MBC
	LD	DE,PLT_MBC
	CP	13		; MBC
	JP	Z,RTC_INIT2
;
	LD	C,PORT_RPH
	LD	DE,PLT_RPH
	CP	14		; RHYOPHYRE
	JP	Z,RTC_INIT2
;
	LD	C,PORT_DUO
	LD	DE,PLT_DUO
	CP	17		; DUODYNE
	JP	Z,RTC_INIT2
;
	LD	C,PORT_STDZ180
	LD	DE,PLT_STDZ180
	CP	21		; STD Z180
	JP	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.9"
	.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	", RCBus Z80 RTC Module Latch Port 0xC0\r\n$"
PLT_RCZ180	.TEXT	", RCBus Z180 RTC Module Latch Port 0x0C\r\n$"
PLT_EZZ80	.TEXT	", Easy Z80 RTC Module Latch Port 0xC0\r\n$"
PLT_SCZ180	.TEXT	", SC Z180 RTC Module Latch Port 0x0C\r\n$"
PLT_DYNO	.TEXT	", DYNO RTC Module Latch Port 0x0C\r\n$"
PLT_RCZ280	.TEXT	", RCBus Z280 RTC Module Latch Port 0xC0\r\n$"
PLT_MBC		.TEXT	", MBC RTC Latch Port 0x70\r\n$"
PLT_RPH		.TEXT	", RHYOPHYRE RTC Latch Port 0x84\r\n$"
PLT_DUO		.TEXT	", DUODYNE RTC Latch Port 0x70\r\n$"
PLT_STDZ180 .TEXT ", STD Z180 RTC Module latch port 0x84\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

