; ;================================================================================================== ; DALLAS SEMICONDUCTOR DS1302 RTC DRIVER ;================================================================================================== ; ; CONSTANTS ; DSRTC_BASE .EQU RTC ; RTC PORT ON ALL N8VEM SERIES Z80 PLATFORMS ; DSRTC_DATA .EQU %10000000 ; BIT 7 CONTROLS RTC DATA (I/O) LINE DSRTC_CLK .EQU %01000000 ; BIT 6 CONTROLS RTC CLOCK LINE, 1 = HIGH DSRTC_RD .EQU %00100000 ; BIT 5 CONTROLS DATA DIRECTION, 1 = READ DSRTC_CE .EQU %00010000 ; BIT 4 CONTROLS RTC CE LINE, 1 = HIGH (ENABLED) ; DSRTC_BUFSIZ .EQU 7 ; 7 BYTE BUFFER (YYMMDDHHMMSSWW) ; ; RTC DEVICE INITIALIZATION ENTRY ; DSRTC_INIT: PRTS("DSRTC: $") ; ; CHECK FOR CLOCK HALTED CALL DSRTC_TSTCLK JR Z,DSRTC_INIT1 PRTS("INIT CLOCK $") LD HL,DSRTC_TIMDEF CALL DSRTC_SETTIM ; DSRTC_INIT1: ; DISPLAY CURRENT TIME LD HL,DSRTC_TIMBUF PUSH HL CALL DSRTC_GETTIM POP HL CALL PRTDT ; XOR A ; SIGNAL SUCCESS RET ; ; RTC DEVICE FUNCTION DISPATCH ENTRY ; A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR ; B: FUNCTION (IN) ; DSRTC_DISPATCH: LD A,B ; GET REQUESTED FUNCTION AND $0F ; ISOLATE SUB-FUNCTION JP Z,DSRTC_GETTIM ; GET TIME DEC A JP Z,DSRTC_SETTIM ; SET TIME DEC A JP Z,DSRTC_GETBYT ; GET NVRAM BYTE VALUE DEC A JP Z,DSRTC_SETBYT ; SET NVRAM BYTE VALUE DEC A JP Z,DSRTC_GETBLK ; GET NVRAM DATA BLOCK VALUES DEC A JP Z,DSRTC_SETBLK ; SET NVRAM DATA BLOCK VALUES CALL PANIC ; ; NVRAM FUNCTIONS ARE NOT AVAILABLE IN SIMULATOR ; DSRTC_GETBYT: DSRTC_SETBYT: DSRTC_GETBLK: DSRTC_SETBLK: CALL PANIC ; ; 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 ; DSRTC_GETTIM: ; ; READ THE CLOCK PUSH HL ; SAVE ADR OF OUTPUT BUF LD HL,DSRTC_BUF ; USE WORK BUF TO READ CLOCK CALL DSRTC_RDCLK ; READ THE CLOCK ; ; TRANSLATE FROM TEMP BUF TO OUTPUT BUF POP HL ; RESTORE THE OUTPUT BUF ADR LD A,(DSRTC_YR) LD (HL),A INC HL LD A,(DSRTC_MON) LD (HL),A INC HL LD A,(DSRTC_DT) LD (HL),A INC HL LD A,(DSRTC_HR) LD (HL),A INC HL LD A,(DSRTC_MIN) LD (HL),A INC HL LD A,(DSRTC_SEC) LD (HL),A ; ; CLEAN UP AND RETURN XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; ; RTC SET TIME ; A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR ; HL: DATE/TIME BUFFER (IN) ; BUFFER FORMAT IS BCD: YYMMDDHHMMSS ; 24 HOUR TIME FORMAT IS ASSUMED ; DSRTC_SETTIM: ; ; TRANSLATE FROM INPUT BUF TO WORK BUF LD A,(HL) LD (DSRTC_YR),A INC HL LD A,(HL) LD (DSRTC_MON),A INC HL LD A,(HL) LD (DSRTC_DT),A INC HL LD A,(HL) LD (DSRTC_HR),A INC HL LD A,(HL) LD (DSRTC_MIN),A INC HL LD A,(HL) LD (DSRTC_SEC),A XOR A ; FIX: DERIVE DAY OF WEEK!!! LD (DSRTC_DAY),A ; ; WRITE TO CLOCK LD HL,DSRTC_BUF ; POINT TO WORK BUF CALL DSRTC_WRCLK ; SEND IT TO RTC ; ; CLEAN UP AND RETURN XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; ; TEST CLOCK FOR VALID DATA ; READ CLOCK HALT BIT AND RETURN ZF BASED ON BIT VALUE ; 0 = RUNNING ; 1 = HALTED ; DSRTC_TSTCLK: LD C,$81 ; SECONDS REGISTER HAS CLOCK HALT FLAG CALL DSRTC_CMD ; SEND THE COMMAND CALL DSRTC_GET ; READ THE REGISTER AND %10000000 ; HIGH ORDER BIT IS CLOCK HALT RET ; ; BURST READ CLOCK DATA INTO BUFFER AT HL ; DSRTC_RDCLK: LD C,$BF ; COMMAND = $BF TO BURST READ CLOCK CALL DSRTC_CMD ; SEND COMMAND TO RTC LD B,DSRTC_BUFSIZ ; B IS LOOP COUNTER DSRTC_RDCLK1: PUSH BC ; PRESERVE BC CALL DSRTC_GET ; GET NEXT BYTE LD (HL),A ; SAVE IN BUFFER INC HL ; INC BUF POINTER POP BC ; RESTORE BC DJNZ DSRTC_RDCLK1 ; LOOP IF NOT DONE XOR A ; ALL LINES OFF TO CLEAN UP OUT (DSRTC_BASE),A ; WRITE TO RTC PORT RET ; ; BURST WRITE CLOCK DATA FROM BUFFER AT HL ; DSRTC_WRCLK: LD C,$8E ; COMMAND = $8E TO WRITE CONTROL REGISTER CALL DSRTC_CMD ; SEND COMMAND XOR A ; $00 = UNPROTECT CALL DSRTC_PUT ; SEND VALUE TO CONTROL REGISTER ; LD C,$BE ; COMMAND = $BE TO BURST WRITE CLOCK CALL DSRTC_CMD ; SEND COMMAND TO RTC LD B,DSRTC_BUFSIZ ; B IS LOOP COUNTER DSRTC_WRCLK1: PUSH BC ; PRESERVE BC LD A,(HL) ; GET NEXT BYTE TO WRITE CALL DSRTC_PUT ; PUT NEXT BYTE INC HL ; INC BUF POINTER POP BC ; RESTORE BC DJNZ DSRTC_WRCLK1 ; LOOP IF NOT DONE LD A,$80 ; ADD CONTROL REG BYTE, $80 = PROTECT ON CALL DSRTC_PUT ; WRITE REQUIRED 8TH BYTE XOR A ; ALL LINES OFF TO CLEAN UP OUT (DSRTC_BASE),A ; WRITE TO RTC PORT RET ; ; SEND COMMAND IN C TO RTC ; DSRTC_CMD: LD A,DSRTC_RD ; CE LOW TO RESET RTC OUT (DSRTC_BASE),A ; WRITE IT LD A,C ; LOAD COMMAND CALL DSRTC_PUT ; WRITE IT RET ; ; WRITE BYTE IN A TO THE RTC ; DSRTC_PUT: LD B,8 ; LOOP FOR 8 BITS DSRTC_PUT1: RRCA ; ROTATE NEXT BIT TO SEND INTO BIT 7 LD C,A ; SAVE WORKING VALUE AND %10000000 ; ISOLATE THE DATA BIT OR DSRTC_CE ; ADD CHIP ENABLE, CLOCK HIGH OUT (DSRTC_BASE),A ; WRITE TO PORT WITH CLOCK LOW XOR DSRTC_CLK ; TURN CLOCK BACK ON OUT (DSRTC_BASE),A ; WRITE TO PORT WITH CLOCK HIGH LD A,C ; RECOVER WORKING VALUE DJNZ DSRTC_PUT1 ; LOOP IF NOT DONE RET ; ; READ BYTE FROM RTC, RETURN VALUE IN A ; DSRTC_GET: LD C,0 ; INITIALIZE WORKING VALUE TO 0 LD B,8 ; LOOP FOR 8 BITS DSRTC_GET1: LD A,DSRTC_RD+DSRTC_CE ; LOWER CLOCK, CE STAYS HI, READ IS ON OUT (DSRTC_BASE),A ; WRITE TO RTC PORT NOP ; SETTLE IN A,(DSRTC_BASE) ; READ THE RTC PORT AND %00000001 ; ISOLATE THE DATA BIT OR C ; COMBINE WITH WORKING VALUE RRCA ; ROTATE FOR NEXT BIT LD C,A ; SAVE WORKING VALUE LD A,DSRTC_CLK+DSRTC_RD+DSRTC_CE ; CLOCK BACK TO HIGH NOW OUT (DSRTC_BASE),A ; WRITE TO RTC PORT DJNZ DSRTC_GET1 ; LOOP IF NOT DONE LD A,C ; GET RESULT INTO A RET ; ; WORKING VARIABLES ; ; DSRTC_BUF IS USED FOR BURST READ/WRITE OF CLOCK DATA TO DS-1302 ; FIELDS BELOW MATCH ORDER OF DS-1302 FIELDS (BCD) ; DSRTC_BUF: DSRTC_SEC: .DB 0 ; SECOND DSRTC_MIN: .DB 0 ; MINUTE DSRTC_HR: .DB 0 ; HOUR DSRTC_DT: .DB 0 ; DATE DSRTC_MON: .DB 0 ; MONTH DSRTC_DAY: .DB 0 ; DAY OF WEEK DSRTC_YR: .DB 0 ; YEAR ; ; DSRTC_TIMBUF IS TEMP BUF USED TO STORE TIME TEMPORARILY TO DISPLAY ; IT. ; DSRTC_TIMBUF .FILL 6,0 ; 6 BYTES FOR GETTIM ; ; DSRTC_TIMDEF IS DEFAULT TIME VALUE TO INITIALIZE CLOCK IF IT IS ; NOT RUNNING. ; DSRTC_TIMDEF: ; DEFAULT TIME VALUE TO INIT CLOCK .DB $00,$01,$01 ; 2000-01-01 .DB $00,$00,$00 ; 00:00:00