;
;==================================================================================================
; SYSTEM TIMER BASED CLOCK DRIVER
;==================================================================================================
;
INTRTC_BUFSIZ	.EQU	6	; SIX BYTE BUFFER (YYMMDDHHMMSS)
;
		DEVECHO	"INTRTC: ENABLED\n"
;
; RTC DEVICE INITIALIZATION ENTRY
;
INTRTC_INIT:
	LD	A,(RTC_DISPACT)		; RTC DISPATCHER ALREADY SET?
	OR	A			; SET FLAGS
	RET	NZ			; IF ALREADY ACTIVE, ABORT
;
	CALL	NEWLINE		; FORMATTING
	PRTS("INTRTC: $")
;
	; HOOK THE HBIOS SECONDS VECTOR
	LD	HL,(VEC_SECOND+1)	; GET CUR SECONDS VECTOR
	LD	(INTRTC_VEC),HL		; SAVE IT INTERNALLY
	LD	HL,INTRTC_INT		; OUR SECONDS INT ENTRY
	LD	(VEC_SECOND+1),HL	; REPLACE IT
;
	; DISPLAY CURRENT TIME
	CALL	INTRTC_GETTIM0
	LD	HL,INTRTC_BCDBUF	; POINT TO BCD BUF
	CALL	PRTDT
;
	LD	BC,INTRTC_DISPATCH
	CALL	RTC_SETDISP
;
	XOR	A		; SIGNAL SUCCESS
	RET
;
; RTC DEVICE FUNCTION DISPATCH ENTRY
;   A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR
;   B: FUNCTION (IN)
;
INTRTC_DISPATCH:
	LD	A,B		; GET REQUESTED FUNCTION
	AND	$0F		; ISOLATE SUB-FUNCTION
	JP	Z,INTRTC_GETTIM	; GET TIME
	DEC	A
	JP	Z,INTRTC_SETTIM	; SET TIME
	DEC	A
	JP	Z,INTRTC_GETBYT	; GET NVRAM BYTE VALUE
	DEC	A
	JP	Z,INTRTC_SETBYT	; SET NVRAM BYTE VALUE
	DEC	A
	JP	Z,INTRTC_GETBLK	; GET NVRAM DATA BLOCK VALUES
	DEC	A
	JP	Z,INTRTC_SETBLK	; SET NVRAM DATA BLOCK VALUES 
	DEC	A
	JP	Z,INTRTC_GETALM	; GET ALARM
	DEC	A
	JP	Z,INTRTC_SETALM	; SET ALARM 
	DEC	A
	JP	Z,INTRTC_DEVICE	; REPORT RTC DEVICE INFO
	SYSCHKERR(ERR_NOFUNC)
	RET
;
; NVRAM FUNCTIONS ARE NOT AVAILABLE IN SIMULATOR
;
INTRTC_GETBYT:
INTRTC_SETBYT:
INTRTC_GETBLK:
INTRTC_SETBLK:
INTRTC_GETALM:
INTRTC_SETALM:
	SYSCHKERR(ERR_NOTIMPL)
	RET
;
; RTC GET TIME
;   A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR
;   HL: DATE/TIME BUFFER (OUT)
; BUFFER FORMAT IS BCD: YYMMDDHHMMSS
; 24 HOUR TIME FORMAT IS ASSUMED
;
INTRTC_GETTIM:
	; GET THE TIME INTO TEMP BUF
	PUSH	HL			; SAVE PTR TO CALLERS BUFFER
	CALL	INTRTC_GETTIM0		; GET TIME TO WORK BUFFER
;
	; NOW COPY TO REAL DESTINATION (INTERBANK SAFE)
	LD	A,BID_BIOS		; COPY FROM BIOS BANK
	LD	(HB_SRCBNK),A		; SET IT
	LD	A,(HB_INVBNK)		; COPY TO CURRENT USER BANK
	LD	(HB_DSTBNK),A		; SET IT
	LD	HL,INTRTC_BCDBUF	; SOURCE ADR
	POP	DE			; DEST ADR
	LD	BC,INTRTC_BUFSIZ	; LENGTH
	CALL	HB_BNKCPY		; COPY THE CLOCK DATA
;
	LD	DE,60			; DELAY 60 * 16US = ~1MS
	CALL	VDELAY			; SLOW DOWN SIMH FOR CLOCK TICKING TEST
	XOR	A			; SIGNAL SUCCESS
	RET				; AND RETURN
;
INTRTC_GETTIM0:
	LD	HL,INTRTC_BINBUF	; FROM BINARY BUFFER
	LD	DE,INTRTC_BCDBUF	; TO BCD BUFFER
	HB_DI
	CALL	INTRTC_BIN2BCD		; COPY AND CONVERT
	HB_EI
	RET
;
; RTC SET TIME
;   A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR
;   HL: DATE/TIME BUFFER (IN)
; BUFFER FORMAT IS BCD: YYMMDDHHMMSSWW
; 24 HOUR TIME FORMAT IS ASSUMED
;
INTRTC_SETTIM:
	; COPY TO BCD BUF
	LD	A,(HB_INVBNK)		; COPY FROM CURRENT USER BANK
	LD	(HB_SRCBNK),A		; SET IT
	LD	A,BID_BIOS		; COPY TO BIOS BANK
	LD	(HB_DSTBNK),A		; SET IT
	LD	DE,INTRTC_BCDBUF	; DEST ADR
	LD	BC,INTRTC_BUFSIZ	; LENGTH
	CALL	HB_BNKCPY		; COPY THE CLOCK DATA
;
	LD	HL,INTRTC_BCDBUF	; FROM BCD BUF
	LD	DE,INTRTC_BINBUF	; TO BIN BUF
	HB_DI
	CALL	INTRTC_BCD2BIN		; COPY AND CONVERT
	HB_EI
;
	XOR	A			; SIGNAL SUCCESS
	RET				; AND RETURN
;
; REPORT RTC DEVICE INFO
;
INTRTC_DEVICE:
	LD	D,RTCDEV_INT		; D := DEVICE TYPE
	LD	E,0			; E := PHYSICAL DEVICE NUMBER
	LD	H,0			; H := 0, DRIVER HAS NO MODES
	LD	L,0			; L := 0, NO I/O ADDRESS
	XOR	A			; SIGNAL SUCCESS
	RET
;
; HANDLER FOR TIMER SECONDS INTERRUPT
;
INTRTC_INT:
	LD	HL,INTRTC_BINBUF + INTRTC_BUFSIZ - 1
	INC	(HL)			; INC SECONDS
	LD	A,59			; MAX VALUE
	CP	(HL)			; OVERFLOW?
	JR	NC,INTRTC_INTX		; NOPE, DONE
	LD	(HL),0			; BACK TO ZERO

	DEC	HL			; POINT TO MINUTES
	INC	(HL)			; INCREMENT MINUTE
	CP	(HL)			; OVERFLOW?
	JR	NC,INTRTC_INTX		; NOPE, DONE
	LD	(HL),0			; BACK TO ZERO

	DEC	HL			; POINT TO HOURS
	INC	(HL)			; INCREMENT HOURS
	LD	A,23			; MAX VALUE
	CP	(HL)			; OVERFLOW?
	JR	NC,INTRTC_INTX		; NOPE, DONE
	LD	(HL),0			; BACK TO ZERO

	DEC	HL			; POINT TO DATE
	LD	A,(INTRTC_MO)		; GET CURRENT MONTH
	DEC	A			; ZERO OFFSET
	LD	DE,INTRTC_MONTBL	; POINT TO DAYS IN MON TBL
	ADD	A,E			; ADD OFFSET
	LD	E,A			; BACK TO E
	JR	NC,INTRTC_INT1		; NO CARRY, SKIP
	INC	D			; HANDLE CARRY
INTRTC_INT1:
	LD	A,(DE)			; A := DAYS IN MONTH
	LD	C,A			; COPY TO C FOR LATER
	LD	A,(INTRTC_MO)		; GET CURRENT MONTH
	CP	2			; FEBRUARY?
	JR	NZ,INTRTC_INT2		; IF NOT, NOT LEAY, SKIP
	LD	A,(INTRTC_YR)		; GET CURRENT YEAR
	AND	$03			; CHECK FOR LEAP
	JR	NZ,INTRTC_INT2		; IF NOT LEAP, SKIP AHEAD
	INC	C			; BUMP DAYS IN FEB FOR LEAP
INTRTC_INT2:
	INC	(HL)			; INCREMENT DATE
	LD	A,C			; A := TRUE DAYS IN MONTH + 1
	CP	(HL)			; OVERFLOW?
	JR	NZ,INTRTC_INTX		; NOPE, DONE
	LD	(HL),1			; BACK TO DAY ONE

	DEC	HL			; POINT TO MONTH
	INC	(HL)			; INCREMENT MONTH
	LD	A,13			; PAST MAX?
	CP	(HL)			; OVERFLOW?
	JR	NZ,INTRTC_INTX		; NOPE, DONE
	LD	(HL),1			; BACK TO MONTH ONE

	DEC	HL			; POINT TO YEAR
	INC	(HL)			; INCREMENT YEAR
	LD	A,100			; PAST MAX?
	CP	(HL)			; OVERFLOW?
	JR	NZ,INTRTC_INTX		; NOPE, DONE
	LD	(HL),0			; BACK TO YEAR ZERO
INTRTC_INTX:
	JP	PANIC
INTRTC_VEC	.EQU	$-2
;
; CONVERT FROM BINARY BUF (HL) TO BCD BUF (DE)
;
INTRTC_BIN2BCD:
	LD	B,INTRTC_BUFSIZ
INTRTC_BIN2BCD1:
	LD	A,(HL)
	CALL	BYTE2BCD
	LD	(DE),A
	INC	HL
	INC	DE
	DJNZ	INTRTC_BIN2BCD1
	RET
;
; CONVERT FROM BCD BUF (HL) TO BINARY BUF (DE)
;
INTRTC_BCD2BIN
	LD	B,INTRTC_BUFSIZ
INTRTC_BCD2BIN1:
	LD	A,(HL)
	CALL	BCD2BYTE
	LD	(DE),A
	INC	HL
	INC	DE
	DJNZ	INTRTC_BCD2BIN1
	RET
;
; WORKING VARIABLES
;
INTRTC_BINBUF:	; ALL IN BINARY
INTRTC_YR	.DB	20
INTRTC_MO	.DB	01
INTRTC_DT	.DB	01
INTRTC_HH	.DB	00
INTRTC_MM	.DB	00
INTRTC_SS	.DB	00
;
INTRTC_BCDBUF	.FILL	INTRTC_BUFSIZ
;
INTRTC_MONTBL:	; DAYS IN MONTH + 1
		.DB	32	; JANUARY
		.DB	29	; FEBRUARY (NON-LEAP)
		.DB	32	; MARCH
		.DB	31	; APRIL
		.DB	32	; MAY
		.DB	31	; JUNE
		.DB	32	; JULY
		.DB	32	; AUGUST
		.DB	31	; SEPTEMBER
		.DB	32	; OCTOBER
		.DB	31	; NOVEMBER
		.DB	32	; DECEMBER
