;
; B3C-DD.INS - Clock routine for the Digital Dynamics card 08/22/85
;						-- by pst
; 
;	This insert should read the clock from a Digital Dynamics
;	SpeedPro5 clock card.  The SpeedPro5 uses a 5832 chip.
;
;	This clock routine needs:
;		BCD2BIN	- no
;		BIN2BCD - no
;
;	This routine NEEDS a Z80 processor to function properly.
;	It will NOT work with an 8080 or 8085.
;
;----------------------------------------------------------------
;
;	Note- This is an insert--not an overlay
;
	 IF	RTC
DDBASE	EQU	156		; Base port of PIO
ADATA	EQU	DDBASE		; Data port A
ACTRL	EQU	DDBASE+1	; Control port A
BDATA	EQU	DDBASE+2	; Data port B
BCTRL	EQU	DDBASE+3	; Control port B
;
NCS	EQU	00000001B	; Not chip select
CLKRD	EQU	00000010B	; Clock read
CLKWR	EQU	00000100B	; Clock write
ADWWR	EQU	00001000B	; Address write
CLKHD	EQU	00010000B	; Clock hold
;
TIME:	LXI	B,ACTRL		; Output mode - port A (reg B=0, C=port)
	CALL	SETMODE
;
	LXI	B,BCTRL		; Output mode - port B (reg B=0, C=port)
	CALL	SETMODE
;
	XRA	A
	OUT	ADATA		; Zero address/data lines
	MVI	A,NCS+CLKHD
	OUT	BDATA		; Deselect chip
;
	LXI	H,RTCBUF	; Point to RTC buffer
	MVI	D,5		; Set counter for hour tens
	CALL	RDIGIT		; Get hour tens
	CALL	SHFT4		; Save in buffer
	CALL	MULT10		; Multiply by 10
	STA	CCHOUR		; Save temporarily
	CALL	RDIGIT		; Get hour units in A reg
	CALL	ADDLOW		; Set BCD digit
	MOV	B,A
	LDA	CCHOUR
	ADD	B		; Add ones digit from B
	STA	CCHOUR		; Store for later use
;
;	Minutes
;
	CALL	RDIGIT		; Get minute tens in A reg
	CALL	SHFT4		; Save in buffer
	CALL	MULT10		; Multiply by 10
	STA	CCMIN		; Save in CCMIN
	CALL	RDIGIT		; Get minute units in A reg
	CALL	ADDLOW		; Set BCD digit
	MOV	B,A
	LDA	CCMIN
	ADD	B		; Add in minutes ones from B
	STA	CCMIN		; Store for later use
;
;	Seconds
;
	CALL	RDIGIT		; Second tens
	CALL	SHFT4
	CALL	RDIGIT		; Second units
	CALL	ADDLOW
;
;	Year
;
	INX	H		; Skip over "19"
	MVI	D,12		; Start with years tens
	CALL	RDIGIT
	CALL	SHFT4
	CALL	RDIGIT		; Years units
	CALL	ADDLOW
;
	CALL	RDIGIT		; Month tens
	CALL	SHFT4
	CALL	RDIGIT		; Month units
	CALL	ADDLOW
;
	CALL	RDIGIT		; Day tens
	CALL	SHFT4
	CALL	RDIGIT		; Day units
	CALL	ADDLOW
;
	MVI	A,0		; Turn off hold
	OUT	BDATA
	MVI	A,NCS		; Deselect chip
	OUT	BDATA
	RET
;
;	Read a digit
;		Command in D
;		Digit returned in A
;		D is decremented
;		Hold bit is set
;		Destroys: 'BCE'
;
RDIGIT:	LXI	B,ACTRL		; Output mode - port A (b=0, c=port)
	CALL	SETMODE
;
	MOV	A,D		; Get command byte
	OUT	ADATA		; Set address on lines
	MVI	A,CLKHD+ADWWR	; Hold & Write
	OUT	BDATA
	MVI	A,CLKHD		; Hold
	OUT	BDATA
;
	LXI	B,0FF00H+ACTRL	; Input mode - port A (b=255, c=port)
	CALL	SETMODE
;
	MVI	A,CLKHD+CLKRD	; Hold & Read
	OUT	BDATA
;
	MOV	A,D		; Check for hour tens digit
	DCR	D
	CPI	5		; Was it hour tens digit?
;
	IN	ADATA		; Read the digit
	PUSH	PSW
	MVI	A,CLKHD		; Set hold mode
	OUT	BDATA
	POP	PSW
	RNZ			; No, return
	ANI	3		; Yes, so kill 24 hour bit
	RET
;
;	Set for input or output mode of port A
;	Entry: mode in B -- 255=output, 0=input
;	       port to send to in C
;
SETMODE:MVI	A,207		; Mode 3, bit I/O
	DB	0EDh,079h	; Z80 instruction = OUT (C),A
	DB	0EDh,041h	; Z80 instruction = OUT (C),B
	MVI	A,7		; Interrupt control
	DB	0EDh,079h	; Z80 instruction = OUT (C),A
	MVI	A,3
	DB	0EDh,079h	; Z80 instruction = OUT (C),A
	RET
;
;	Multiply register A by 10
;	Destroys 'E'
;
MULT10:	ADD	A		; 2x
	MOV	E,A
	ADD	A		; 4x
	ADD	A		; 8x
	ADD	D		; 10x
	RET
;
;	Shift A to high nibble
;		Stores shifted value in 'M'
;		Destroys 'E'
;		A is left unchanged
;
SHFT4:	MOV	E,A
	ANI	15		; Only handle lower 4 bits
	RLC			; Shift A over 4 bits
	RLC
	RLC
	RLC			
	MOV	M,A		; Save it while we're at it
	MOV	A,E
	RET
;
;	Add in low BCD nibble
;		Gets high nibble from M
;		Stores new BCD byte in M
;		Increments HL
;		Destroyes 'E'
;
ADDLOW:	MOV	E,A
	ANI	15		; Deal with low nibble only
	ORA	M		; Add in high nibble from tens digit
	MOV	M,A		; Save new BCD byte in buffer
	INX	H		; Move on to next location
	MOV	A,E
	RET
	 ENDIF			; RTC
