; B5C-SB.INS - Clock routine for SB-180
;
; Uses the the wallclock data area of the BIOS to return the current
; time to BYE5. The first time check after midnight will automatically
; update the BYE5 date area, but since the SB-180 does not store the
; current date, this area must first be intitialized to the correct date
; by some other means.
;
; (Dec 16 1986)	Initial release for BYE510 and above. Note that
;		this insert uses the Z80 "LDIR" instruction to
;		minimize the time that interrupts are disabled.
;		Since all SB-180s use the HD64180 CPU chip, this
;		should be no problem.
;						-- Stuart Rose
;
;----------------------------------------------------------------
;
; This clock insert uses BCDBIN and BINBCD subroutines.  It requires that
; configuration tags BCD2BIN and BIN2BCD as well as CLOCK be set to YES.
;
;	Note: This is an insert -- not an overlay
;
	 IF	CLOCK OR RSPEED

WBOOT	equ	0000H		; address of warm boot vector
CENTURY	equ	19H		; current century (19xx) in BCD
TIMOFF	equ	33		; offset to time routine in BIOS jump table

TIME:	call	getclk		; get the time from the system clock

	lda	TMPBUF+2	; get hours (binary)
	sta	CCHOUR		; save as current hour
	call	BINBCD		; convert to BCD
	sta	RTCBUF		; and store BCD hours in RTCBUF
	lda	TMPBUF+1	; get minutes (binary)
	sta	CCMIN		; save as current minute
	call	BINBCD		; convert to BCD
	STA	RTCBUF+1	; and store tore BCD minutes in RTCBUF
	lda	TMPBUF		; Get seconds (binary)
	call	BINBCD		; convert to BCD
	STA	RTCBUF+2	; and store BCD seconds in RTCBUF

	lda	OLDHRS		; get old system hours
	mov	B,A		; save it
	lda	TMPBUF + 2	; get new system hours
	sta	OLDHRS		; store it
	sub	B		; day rollover?
	rnc			; nope

	mvi	A,CENTURY	; yep, get current century
	sta	RTCBUF+3	; and store in RTC buffer

	lda	RTCBUF+6	; get the day of the month (BCD)
	adi	1		; bump up ...
	daa			; adjust to BCD ...
	sta	RTCBUF+6	; store the new day ...
	mov	B,A		; and save
	lxi	H,monmap	; point to the month map
	lda	RTCBUF+5	; get the month of the year (BCD)
	call	BCDBIN		; convert to binary
	dcr	A		; remove offset (for base zero)
	call	chkly		; check for leap year
	adc	A		; multiply by 2 (with carry for ly)
	mvi	D,0		; and create an offset
	mov	E,A		;
	dad	D		; add offset
	mov	A,M		; get number of days this month
	sub	B		; rollover?
	rnc			; nope
	mvi	A,01H		; yep reset the day of the month
	sta	RTCBUF+6	;

	lda	RTCBUF+5	; get the month of the year (BCD)
	adi	1		; bump up ...
	daa			; adjust to BCD ..
	sta	RTCBUF+5	; store the new month ...
	cpi	12+1		; rollover?
	rc			; nope
	mvi	A,01H		; yep reset the month of the year
	sta	RTCBUF+5	;

	lda	RTCBUF+4	; get the year (BCD)
	adi	1		; bump up ...
	daa			; adjust to BCD ...
	sta	RTCBUF+4	; and store the new year

	ret			; done
;
; This routine checks for leap years. If the current year is a leap
; year, then this routine returns with the CARRY set.
;
chkly:	lda	RTCBUF+4	; get the year (BCD)
	call	BCDBIN		; convert to binary
	mov	B,A		; save it
	ani	0FCH		; year = year mod 4
	cmp	B		; same as original?
	cmc			; set CARRY if so
	ret
;
; This routine will read from the SB-180 wallclock data area
;
getclk:	call	biosclk		; point to BIOS RTC data area
	lxi	D,TMPBUF	; point to temporary buffer
	lxi	B,3		; moving 3 bytes
	di			; disable interrupts
	db	0EDH,0B0H	; Z80 LDIR instruction
	ei			; enable interrupts
	ret			; done
;
; This routine will call the BIOS time routine and return with the
; the <HL> register pair pointing to the BIOS RTC data area
;
biosclk:lxi	H,WBOOT+1	; point to warmboot vector
	lxi	D,TIMOFF	; get offset to BIOS time routine
	dad	D		; add offset
	pchl			; and jump to it
;
; This is a month map for the number of day in each month of the
; year. The first value is for a standard year, the second for a
; leap year. Note all values are in BCD.
;
monmap:	db	31H,31H		; January   std,lpyr
	db	28H,29H		; February  std,lpyr
	db	31H,31H		; March     std,lpyr
	db	30H,30H		; April     std,lpyr
	db	31H,31H		; May       std,lpyr
	db	30H,30H		; June      std,lpyr
	db	31H,31H		; July      std,lpyr
	db	31H,31H		; August    std,lpyr
	db	30H,30H		; September std,lpyr
	db	31H,31H		; October   std,lpyr
	db	30H,30H		; November  std,lpyr
	db	31H,31H		; December  std,lpyr

OLDHRS:	db	0		; remember hours from last call
TMPBUF:	db	0		; temporary storage for the seconds
	db	0		; temporary storage for the minutes
	db	0		; temporary storage for the hours

	 ENDIF			; CLOCK OR RSPEED
