;==================================================================================================
; DS1307 PCF I2C CLOCK DRIVER
;
; LABELS STARTING WITH PCF ARE REFERENCING THE PCF8584 LIBRARY
;
;==================================================================================================
;
#IF (!PCFENABLE)
	.ECHO	"*** DS7 DRIVER REQUIRES PCF DRIVER.  SET PCFENABLE!!!\n"
	!!!	; FORCE AN ASSEMBLY ERROR
#ENDIF
;
DS7_OUT		.EQU	10000000B		; SELECT SQUARE WAVE FUNCTION
DS7_SQWE	.EQU	00010000B		; ENABLE SQUARE WAVE OUTPUT
DS7_RATE	.EQU	00000000B		; SET 1HZ OUPUT
;
DS7_DS1307    	.EQU  	11010000B   		; DEVICE IDENTIFIER
DS7_W   	.EQU  	00000000B   		; DEVICE WRITE
DS7_R   	.EQU  	00000001B   		; DEVICE READ
;
DS7_READ   	.EQU    (DS7_DS1307 | DS7_R)	; READ
DS7_WRITE 	.EQU    (DS7_DS1307 | DS7_W)	; WRITE
;
DS7_CTL		.EQU	(DS7_OUT | DS7_SQWE | DS7_RATE)
;
		DEVECHO	"DS1307: ENABLED\n"
;
;-----------------------------------------------------------------------------
; DS1307 INITIALIZATION
;
; ASSUMES PCF8584 I2C HAS ALREADY BEEN INITIALIZED
; CHECKS IF OSCILLATOR IS RUNNING. IF IT ISN'T THE
; CLOCK IS RESTARTED WITH DEFAULT VALUES.
;
; DRIVER WILL NOT BE INSTALLED AS PART OF HBIOS IF
; THERE IS ALREADY AND EXISTING RTC INSTALLED.
;
; 12HR MODE IS CURRENTLY ASSUMED
;
DS7RTC_INIT:
	CALL	NEWLINE			; Formatting
	PRTS("DS1307: $")		; ANNOUNCE DRIVER
;
	LD	A,(PCF_FAIL_FLAG)	; CHECK IF THE
	OR	A			; I2C DRIVER
	JR	NZ,RTC_INIT_FAIL	; INITIALIZED

	CALL	DS7_RDC			; READ CLOCK DATA
	LD	HL,DS7_BUF		; IF NOT RUNNING OR
	BIT	7,(HL)			; INVALID, RESTART
	JR	Z,DS7_CSET		; AND RESET.
	CALL	DS7_SETC
	CALL	DS7_RDC			; READ AND DISPLAY
DS7_CSET:
	CALL	DS7_DISP		; DATE AND TIME
;
	LD	A,(RTC_DISPACT)		; CHECK RTC DISPATCHER STATUS.
	OR	A			; RETURN NOW IF WE ALREADY HAVE
	RET	NZ			; A PRIMARY RTC INSTALLED.
;
	LD	BC,DS7_DISPATCH		; SETUP CLOCK HBIOS DISATCHER
	CALL	RTC_SETDISP
;
;	CALL	DS7_GETTIM
;
	XOR	A			; SIGNAL SUCCESS
	RET
;
RTC_INIT_FAIL:				; EXIT 
	CALL	PRTSTRD			; WITH 
	.DB	"NO I2C DRIVER$"	; ERROR
	PUSH	AF			; MESSAGE
RTC_INIT_ERR:				; EXIT
	POP	AF			; WITH
	LD	A,ERR_NOHW		; ERROR
	OR	A			; STATUS
	RET
;
;-----------------------------------------------------------------------------
; DS1307 HBIOS DISPATCHER
;
;   A: RESULT (OUT), 0=OK, Z=OK, NZ=ERROR
;   B: FUNCTION (IN)
;
DS7_DISPATCH:
	PUSH	AF				; CHECK IF WE
	LD	A,(PCF_FAIL_FLAG)		; HAVE HARDWARE
	OR	A				; AND ASSOCIATED
	JR	NZ,RTC_INIT_ERR			; DRIVER
	POP	AF
;
	LD	A, B				; GET REQUESTED FUNCTION
	AND	$0F				; ISOLATE SUB-FUNCTION
	JP	Z, DS7_GETTIM			; GET TIME
	DEC	A
	JP	Z, DS7_SETTIM			; SET TIME 
	DEC	A
	JP	Z, DS7_GETBYT			; GET NVRAM BYTE VALUE
	DEC	A
	JP	Z, DS7_SETBYT			; SET NVRAM BYTE VALUE
	DEC	A
	JP	Z, DS7_GETBLK			; GET NVRAM DATA BLOCK VALUE
	DEC	A
	JP	Z, DS7_SETBLK			; SET NVRAM DATA BLOCK VALUE 
	DEC	A
	JP	Z, DS7_GETALM			; GET ALARM
	DEC	A
	JP	Z, DS7_SETALM			; SET ALARM
	DEC	A
	JP	Z, DS7_DEVICE			; REPORT RTC DEVICE INFO
	SYSCHKERR(ERR_NOFUNC)
	RET
;
;-----------------------------------------------------------------------------
; DS1307 GET TIME
;
; HL POINTS TO A BUFFER TO STORE THE CURRENT TIME AND DATE IN.
; THE TIME AND DATE INFORMATION MUST BE TRANSLATED TO THE
; HBIOS FORMAT AND COPIED FROM THE HBIOS DRIVER BANK TO
; CALLER INVOKED BANK.
;
; HBIOS FORMAT  = YYMMDDHHMMSS
; DS1307 FORMAT = SSMMHH..DDMMYY..
;
DS7_GETTIM:
	PUSH	HL				; SAVE DESTINATION
	CALL	DS7_RDC				; READ THE CLOCK INTO THE BUFFER
;
	LD	HL,DS7_BUF+2
	LD	DE,DS7_BUF+3			; TRANSLATE
	LD	B,3				; FORMAT
DS7_GT0:LD	A,(HL)
	LD	(DE),A	
	INC	DE
	LD	A,(DE)
	LD	(HL),A
	DEC	HL
	DJNZ	DS7_GT0
;
	INC	HL				; POINT TO SECONDS
	RES	7,(HL)				; REMOVE OSCILLATOR BIT
	POP	DE				; HL POINT TO SOURCE
;						; DE POINT TO DESTINATION
#IF (0)
	PUSH	HL
	PUSH	DE
	EX	DE,HL
	LD	A,6
	CALL	PRTHEXBUF
	POP	DE
	POP	HL
#ENDIF
;	
	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	BC, 6				; LENGTH IS 6 BYTES
#IF (INTMODE == 1)
	DI
#ENDIF
	CALL	HB_BNKCPY			; COPY THE CLOCK DATA
#IF (INTMODE == 1)
	EI
#ENDIF
	XOR	A				; SIGNAL SUCCESS
	RET	
;
;-----------------------------------------------------------------------------
; DS1307 SET TIME
;
;   A: RESULT (OUT), 0=OK, Z=OK, NZ=ERROR
;   HL: DATE/TIME BUFFER (IN)
;
; HBIOS FORMAT  = YYMMDDHHMMSS
; DS1307 FORMAT = SSMMHH..DDMMYY..
;
DS7_SETTIM:
;	CALL	PCF_DBG		; [0]


	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, DS7_BUF			; DESTINATION ADDRESS
	LD	BC,6				; LENGTH IS 6 BYTES
#IF (INTMODE == 1)
	DI
#ENDIF
	CALL	HB_BNKCPY			; Copy the clock data
#IF (INTMODE == 1)
	EI
#ENDIF
;
;	CALL	PCF_DBG		; [1]

	CALL	PCF_WAIT_FOR_BB
	JP	NZ,PCF_BBERR
;	
	LD	A,DS7_WRITE	; SET SLAVE ADDRESS
        OUT	(PCF_RS0),A
;
        CALL	PCF_START	; GENERATE START CONDITION
	CALL	PCF_WAIT_FOR_PIN; AND ISSUE THE SLAVE ADDRESS
	CALL	NZ,PCF_PINERR
;
	LD	A,00H		; REGISTER 00
        OUT    	(PCF_RS0),A    	; PUT ADDRESS ON BUS
	CALL	PCF_WAIT_FOR_PIN
	CALL	NZ,PCF_PINERR
;
	LD	DE,5
	CALL	DS7_SET3	; STARTING AT REGISTER 0
;
	CALL 	PCF_STOP

	CALL	PCF_WAIT_FOR_BB
	JP	NZ,PCF_BBERR

;	CALL	PCF_DBG		; [2]
;
	LD	A,DS7_WRITE	; SET SLAVE ADDRESS
        OUT	(PCF_RS0),A
;
        CALL	PCF_START	; GENERATE START CONDITION
	CALL	PCF_WAIT_FOR_PIN; AND ISSUE THE SLAVE ADDRESS
	CALL	NZ,PCF_PINERR

;	CALL	PCF_DBG		; [3]
;
	LD	A,04H		; REGISTER 04
        OUT    	(PCF_RS0),A    	; PUT ADDRESS ON BUS
	CALL	PCF_WAIT_FOR_PIN
	CALL	NZ,PCF_PINERR
;
	LD	DE,2
	CALL	DS7_SET3

;	CALL	PCF_DBG		; [4]
;
	CALL 	PCF_STOP
	XOR	A
	RET
;
DS7_SET3:
	LD	B,3
	LD	HL,DS7_BUF
	ADD	HL,DE
DS7_SC1:PUSH	BC

	LD	A,(HL)

;	CALL	PRTHEXBYTE

        OUT     (PCF_RS0),A    	; PUT DATA ON BUS
	CALL	PCF_WAIT_FOR_ACK
	CALL	NZ,PCF_ACKERR
	POP	BC
	DEC	HL
	DJNZ	DS7_SC1
	RET
;
; HBIOS FORMAT  = YYMMDDHHMMSS
;                 991122083100
; DS1307 FORMAT = SSMMHH..DDMMYY..
;                 003108..221199
;
;-----------------------------------------------------------------------------
; FUNCTIONS THAT ARE NOT AVAILABLE OR IMPLEMENTED
;
DS7_GETBYT:
DS7_SETBYT:
DS7_GETBLK:
DS7_SETBLK:
DS7_SETALM
DS7_GETALM
	SYSCHKERR(ERR_NOTIMPL)
	RET
;-----------------------------------------------------------------------------
; REPORT RTC DEVICE INFO
;
; THE I2C BUS ADDRESS IS REPORTED RATHER THAN THE I2C PORT ADDRESS.
; ONLY ONE CLOCK CAN BE INSTALLED IN HBIOS SO DEVICE NUMBER IS ALWAYS 0.
;
DS7_DEVICE:
	LD	D,RTCDEV_DS7		; D := DEVICE TYPE
	LD	E,0			; E := PHYSICAL DEVICE NUMBER
	LD	H,0			; H := 0, DRIVER HAS NO MODES
	LD	L,DS7_DS1307		; L := BUS ADDRESS
	XOR	A			; SIGNAL SUCCESS
	RET
;-----------------------------------------------------------------------------
; RTC READ
;
; 1.	ISSUE SLAVE ADDRESS WITH START CONDITION AND WRITE STATUS
; 2.	OUTPUT THE ADDRESS TO ACCESS. (00H = START OF DS1307 REGISTERS)
; 3.	OUTPUT REPEAT START TO TRANSITION TO READ PROCESS
; 4.	ISSUE SLAVE ADDRESS WITH READ STATUS
; 5. 	DO A DUMMY READ 
; 6.	READ 8 BYTES STARTING AT ADDRESS PREVIOUSLY SET
; 7.	END READ WITH NON-ACKNOWLEDGE
; 8.	ISSUE STOP AND RELEASE BUS 
;
DS7_RDC:LD	A,DS7_WRITE	; SET SLAVE ADDRESS
        OUT	(PCF_RS0),A
;
	CALL	PCF_WAIT_FOR_BB
	JP	NZ,PCF_BBERR
;
        CALL	PCF_START	; GENERATE START CONDITION
	CALL	PCF_WAIT_FOR_PIN; AND ISSUE THE SLAVE ADDRESS
	CALL	NZ,PCF_PINERR
;
        LD     	A,0
        OUT    	(PCF_RS0),A    	; PUT ADDRESS MSB ON BUS
	CALL	PCF_WAIT_FOR_PIN
	CALL	NZ,PCF_PINERR
;
	CALL	PCF_REPSTART    ; REPEAT START
;
        LD	A,DS7_READ	; ISSUE CONTROL BYTE + READ
        OUT	(PCF_RS0),A
;
	CALL	PCF_READI2C	; DUMMY READ
;
	LD	HL,DS7_BUF	; READ 8 BYTES INTO BUFFER
	LD	B,8
DS7_RL1:CALL	PCF_READI2C
	LD	(HL),A
	INC	HL
	DJNZ    DS7_RL1
;
#IF (0)
	LD	A,8
	LD	DE,DS7_BUF	; DISPLAY DATA READ
	CALL	PRTHEXBUF	; 
	CALL   	NEWLINE
#ENDIF
;
	LD     	A,PCF_ES0	; END WITH NOT-ACKNOWLEDGE
	OUT    	(PCF_RS1),A       ; AND RELEASE BUS
	NOP
	IN    	A,(PCF_RS0)
	NOP
DS7_WTPIN:	
	IN	A,(PCF_RS1)	; READ S1 REGISTER
	BIT	7,A		; CHECK PIN STATUS
	JP	NZ,DS7_WTPIN
	CALL   	PCF_STOP
;
	IN    	A,(PCF_RS0)
        RET
;
;-----------------------------------------------------------------------------
; SET CLOCK
;
; IF THE CLOCK IS HALTED AS IDENTIFIED BY BIT 7 REGISTER 0, THEN ASSUME THE
; CLOCK HAS NOT BEEN SET AND SO SET THE CLOCK UP WITH A DEFAULT SET OF
; VALUES AS DEFINED IN THE DS7_CLKDATA TABLE.
;
DS7_SETC:
	CALL	PCF_WAIT_FOR_BB
	JP	NZ,PCF_BBERR
;	
	LD	A,DS7_WRITE	; SET SLAVE ADDRESS
        OUT	(PCF_RS0),A
;
        CALL	PCF_START	; GENERATE START CONDITION
	CALL	PCF_WAIT_FOR_PIN; AND ISSUE THE SLAVE ADDRESS
	CALL	NZ,PCF_PINERR
;
	LD	A,00H		; REGISTER 00
        OUT    	(PCF_RS0),A    	; PUT ADDRESS ON BUS
	CALL	PCF_WAIT_FOR_PIN
	CALL	NZ,PCF_PINERR
;
	LD	DE,DS7_CLKDATA
DS7_SC:	LD	A,(DE)
	CP	0FFH
	JR	Z,DS7_ESC
        OUT     (PCF_RS0),A    	; PUT DATA ON BUS
	CALL	PCF_WAIT_FOR_ACK
	CALL	NZ,PCF_ACKERR
	INC	DE
	JR	DS7_SC
;
DS7_ESC:CALL 	PCF_STOP
	RET
;
DS7_CLKDATA:
	.DB	00H		; SECONDS
	.DB	00H		; MINUTES
	.DB     00H		; HOURS
	.DB	01H		; DAY
	.DB	01H		; DATE
	.DB	01H		; MONTH
	.DB	21H		; YEAR
        .DB     DS7_CTL		; CONTROL (00010011B)
        .DB     0FFH            ; END FLAG  
;
;-----------------------------------------------------------------------------
; DISPLAY CLOCK INFORMATION FROM DATA STORED IN BUFFER
;
DS7_DISP:
	LD	HL,DS7_CLKTBL
DS7_CLP:LD	C,(HL)
	INC	HL
	LD	D,(HL)
	CALL	DS7_BCD
	INC	HL
	LD	A,(HL)
	OR      A
	RET	Z
        CALL	COUT
	INC	HL
	JR	DS7_CLP
	RET
;
DS7_CLKTBL:
	.DB	04H, 00111111B, '/'
	.DB	05H, 00011111B, '/'
	.DB	06H, 11111111B, ' '
	.DB	02H, 00011111B, ':'
	.DB	01H, 01111111B, ':'
	.DB	00H, 01111111B, 00H
;
DS7_BCD:PUSH	HL
	LD      HL,DS7_BUF     	; READ VALUE FROM
	LD      B,0           	; BUFFER, INDEXED BY A 
	ADD     HL,BC
	LD      A,(HL)
	AND     D             	; MASK OFF UNNEEDED
	SRL     A
	SRL     A
	SRL     A
	SRL     A      
	ADD     A,30H
	CALL    COUT
	LD      A,(HL)    
	AND     00001111B
	ADD     A,30H
	CALL    COUT
	POP	HL
	RET
;
DS7_BUF:	.FILL	8,0				; BUFFER FOR TIME, DATE AND CONTROL
;DS7_COLD	.DB	$80,$00,$00,$01,$01,$01,$00	; COLD START RTC SETTINGS
;
