mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
410 lines
12 KiB
410 lines
12 KiB
;
|
|
;==================================================================================================
|
|
; DALLAS SEMICONDUCTOR DS1288X REAL TIME CLOCK
|
|
;==================================================================================================
|
|
;
|
|
; THIS DRIVER IS FOR THE DS1288X REAL-TIME CLOCK AND NVRAM.
|
|
; THE INTERFACE IS ASSUMED TO BE LIKE AN IBM PC AT PORT 0X70.
|
|
;
|
|
; TODO:
|
|
; CHECK CONTROL REG A, BIT 7 (VALID RAM/TIME) AND NOTIFY
|
|
; USER IF BATTERY IS DISCHARGED.
|
|
;
|
|
; REGISTER ADDRESSES (HEX / BCD):
|
|
;
|
|
; +---------+----------------------------------------------+--------+
|
|
; | REG | FUNCTION | RANGE |
|
|
; +---------+----------------------------------------------+--------+
|
|
; | $00 | SECONDS | 0-59 |
|
|
; | $01 | SECONDS ALARM | 0-59 |
|
|
; | $02 | MINUTES | 0-59 |
|
|
; | $03 | MINUTES ALARM | 0-59 |
|
|
; | $04 | HOURS | 00-23 |
|
|
; | $05 | HOURS ALARM | 00-23 |
|
|
; | $06 | DAY | 01-07 |
|
|
; | $07 | DATE | 01-31 |
|
|
; | $08 | MONTH | 01-12 |
|
|
; | $09 | YEAR | 00-99 |
|
|
; | $0A | CONTROL (SEE BELOW) | -- |
|
|
; | $0B | CONTROL (SEE BELOW) | -- |
|
|
; | $0C | CONTROL (SEE BELOW) | -- |
|
|
; | $0D | CONTROL (SEE BELOW) | -- |
|
|
; | $0E-$31 | RAM | -- |
|
|
; | $32 | CENTURY | 00-99 |
|
|
; | $33-$7F | RAM | -- |
|
|
; +---------+----------------------------------------------+--------+
|
|
;
|
|
; +-----+-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | REG | BIT 7 | BIT 6 | BIT 5 | BIT 4 | BIT 3 | BIT 2 | BIT 1 | BIT 0 |
|
|
; +-----+-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | $0A | UIP | DV2 | DV1 | DV0 | RS3 | RS2 | RS1 | RS0 |
|
|
; | $0B | SET | PIE | AIE | UIE | SQWE | DM | 24/12 | DSE |
|
|
; | $0C | IRQF | PF | AF | UF | 0 | 0 | 0 | 0 |
|
|
; | $0D | VRT | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
|
|
; +-----+-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; NOTE: THE IBM PC CMOS USES REGISTER ADDRESSES UP TO $5F. THIS RTC
|
|
; IS SOMETIMES USED IN SYSTEMS THAT HAVE A X86 BOARD, SO WE AVOID ANY
|
|
; CONFLICT BY OFFSETTING OUR REGISTER INDEXES BY $60. THIS MEANS WE
|
|
; MAP REQUESTS FOR $00-$1F TO NVRAM REGISTERS $60-$7F.
|
|
;
|
|
DS12RTC_SEL .EQU DS12RTC_BASE + 0
|
|
DS12RTC_DATA .EQU DS12RTC_BASE + 1
|
|
;
|
|
DS12RTC_NVBASE .EQU $10
|
|
DS12RTC_NVSIZE .EQU $30
|
|
;
|
|
DEVECHO "DS12RTC:"
|
|
;
|
|
DEVECHO " IO="
|
|
DEVECHO DS12RTC_BASE
|
|
DEVECHO "\n"
|
|
;
|
|
; RTC DEVICE PRE-INITIALIZATION ENTRY
|
|
;
|
|
DS12RTC_PREINIT:
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
; RTC DEVICE INITIALIZATION ENTRY
|
|
;
|
|
DS12RTC_INIT:
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("DS12RTC:$")
|
|
;
|
|
; PRINT RTC PORT ADDRESS
|
|
PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS
|
|
LD A,DS12RTC_BASE ; GET IO ADDRESS
|
|
CALL PRTHEXBYTE ; PRINT IT
|
|
;
|
|
CALL DS12RTC_DETECT ; HARDWARE DETECTION
|
|
JR Z,DS12RTC_INIT1 ; CONTINUE IF FOUND
|
|
;
|
|
; HANDLE HARDWARE MISSING
|
|
PRTS(" NOT PRESENT$") ; NOT ZERO, H/W NOT PRESENT
|
|
OR $FF ; SIGNAL FAILURE
|
|
RET ; BAIL OUT
|
|
;
|
|
DS12RTC_INIT1:
|
|
; INITIALIZE RTC
|
|
CALL DS12RTC_INITDEV
|
|
;
|
|
; DISPLAY CURRENT TIME
|
|
CALL PC_SPACE
|
|
LD HL,DS12RTC_TIMBUF
|
|
CALL DS12RTC_RDCLK
|
|
LD HL,DS12RTC_TIMBUF
|
|
CALL PRTDT
|
|
;
|
|
; REGISTER THE RTC
|
|
LD BC,DS12RTC_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)
|
|
;
|
|
DS12RTC_DISPATCH:
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
AND $0F ; ISOLATE SUB-FUNCTION
|
|
JP Z,DS12RTC_GETTIM ; GET TIME
|
|
DEC A
|
|
JP Z,DS12RTC_SETTIM ; SET TIME
|
|
DEC A
|
|
JP Z,DS12RTC_GETBYT ; GET NVRAM BYTE VALUE
|
|
DEC A
|
|
JP Z,DS12RTC_SETBYT ; SET NVRAM BYTE VALUE
|
|
DEC A
|
|
JP Z,DS12RTC_GETBLK ; GET NVRAM DATA BLOCK VALUES
|
|
DEC A
|
|
JP Z,DS12RTC_SETBLK ; SET NVRAM DATA BLOCK VALUES
|
|
DEC A
|
|
JP Z,DS12RTC_GETALM ; GET ALARM
|
|
DEC A
|
|
JP Z,DS12RTC_SETALM ; SET ALARM
|
|
DEC A
|
|
JP Z,DS12RTC_DEVICE ; REPORT RTC DEVICE INFO
|
|
;
|
|
SYSCHKERR(ERR_NOFUNC)
|
|
RET
|
|
;
|
|
; ALARM FUNCTIONALITY NOT IMPLEMENTED
|
|
;
|
|
DS12RTC_GETBLK:
|
|
DS12RTC_SETBLK:
|
|
DS12RTC_GETALM:
|
|
DS12RTC_SETALM:
|
|
SYSCHKERR(ERR_NOTIMPL)
|
|
RET
|
|
;
|
|
; RTC GET TIME
|
|
; BUFFER FORMAT IS BCD: YYMMDDHHMMSS
|
|
; 24 HOUR TIME FORMAT IS ASSUMED
|
|
;
|
|
DS12RTC_GETTIM:
|
|
PUSH HL ; SAVE ADR OF OUTPUT BUF
|
|
;
|
|
LD HL,DS12RTC_TIMBUF ; POINTER TO CLK DATA
|
|
CALL DS12RTC_RDCLK ; READ IT
|
|
;
|
|
; 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,DS12RTC_TIMBUF ; SOURCE ADR
|
|
POP DE ; DEST ADR
|
|
LD BC,6 ; LENGTH IS 6 BYTES
|
|
#IF (INTMODE == 1)
|
|
DI
|
|
#ENDIF
|
|
CALL HB_BNKCPY ; COPY THE CLOCK DATA
|
|
#IF (INTMODE == 1)
|
|
EI
|
|
#ENDIF
|
|
;
|
|
; CLEAN UP AND RETURN
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
; RTC SET TIME
|
|
; BUFFER FORMAT IS BCD: YYMMDDHHMMSS
|
|
; 24 HOUR TIME FORMAT IS ASSUMED
|
|
;
|
|
DS12RTC_SETTIM:
|
|
; COPY INCOMING TIME DATA TO OUR TIME BUFFER
|
|
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,DS12RTC_TIMBUF ; DEST ADR
|
|
LD BC,6 ; LENGTH IS 6 BYTES
|
|
#IF (INTMODE == 1)
|
|
DI
|
|
#ENDIF
|
|
CALL HB_BNKCPY ; COPY THE CLOCK DATA
|
|
#IF (INTMODE == 1)
|
|
EI
|
|
#ENDIF
|
|
;
|
|
; WRITE TO CLOCK
|
|
LD HL,DS12RTC_TIMBUF ; POINTER TO CLK DATA
|
|
CALL DS12RTC_WRCLK ; WRITE TO THE CLOCK
|
|
;
|
|
; CLEAN UP AND RETURN
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
; RTC GET NVRAM BYTE
|
|
; C: INDEX
|
|
; E: VALUE (OUTPUT)
|
|
;
|
|
DS12RTC_GETBYT:
|
|
LD A,C ; INDEX TO ACCUM
|
|
CP DS12RTC_NVSIZE ; COMPARE TO MAX
|
|
JR NC,DS12RTC_BADIDX ; HANDLE RANGE ERROR
|
|
;
|
|
ADD A,DS12RTC_NVBASE ; OFFSET TO START OF NVRAM
|
|
LD C,A ; INDEX BACK TO C
|
|
CALL DS12RTC_RDREG ; GET THE VALUE
|
|
LD E,A ; PUT IN E TO RETURN
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
; RTC SET NVRAM BYTE
|
|
; C: INDEX
|
|
; E: VALUE
|
|
;
|
|
DS12RTC_SETBYT:
|
|
LD A,C ; INDEX TO ACCUM
|
|
CP DS12RTC_NVSIZE ; COMPARE TO MAX
|
|
JR NC,DS12RTC_BADIDX ; HANDLE RANGE ERROR
|
|
;
|
|
ADD A,DS12RTC_NVBASE ; OFFSET TO START OF NVRAM
|
|
LD C,A ; INDEX BACK TO C
|
|
LD A,E ; PUT VALUE IN A
|
|
CALL DS12RTC_WRREG ; WRITE IT
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
; HANDLE RANGE ERROR
|
|
;
|
|
DS12RTC_BADIDX:
|
|
LD A,ERR_RANGE
|
|
OR A
|
|
RET
|
|
;
|
|
; REPORT RTC DEVICE INFO
|
|
;
|
|
DS12RTC_DEVICE:
|
|
LD D,RTCDEV_DS12 ; D := DEVICE TYPE
|
|
LD E,0 ; E := PHYSICAL DEVICE NUMBER
|
|
LD H,0 ; H := MODE
|
|
LD L,DS12RTC_BASE ; L := BASE I/O ADDRESS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; DETECT RTC HARDWARE PRESENCE
|
|
; RETURN Z IF PRESENT
|
|
;
|
|
DS12RTC_DETECT:
|
|
LD C,$7F ; USE LAST RAM BYTE FOR TESTING
|
|
CALL DS12RTC_RDREG ; GET CURRENT VALUE
|
|
LD B,A ; SAVE IT
|
|
LD A,$A5 ; TEST VALUE
|
|
CALL DS12RTC_WRREG ; WRITE IT
|
|
CALL DS12RTC_RDREG ; READ IT BACK
|
|
CP $A5 ; COMPARE TO TEST VALUE
|
|
PUSH AF ; SAVE RESULTS
|
|
LD A,B ; RECOVER ORIGINAL VALUE
|
|
CALL DS12RTC_WRREG ; RESTORE IT
|
|
POP AF ; RECOVER RESULT
|
|
RET ; AND RETURN
|
|
;
|
|
; READ CLOCK DATA INTO BUFFER AT HL (YYMMDDHHMMSS)
|
|
;
|
|
DS12RTC_RDCLK:
|
|
LD E,0 ; CLEAR UIP FLAG
|
|
PUSH HL ; SAVE IN CASE OF RESTART
|
|
LD C,$09 ; START WITH YEAR REG
|
|
CALL DS12RTC_RDCLK1 ; DO YEAR (REG $09)
|
|
CALL DS12RTC_RDCLK1 ; DO MONTH (REG $08)
|
|
CALL DS12RTC_RDCLK1 ; DO DAY OF MONTH (REG $07)
|
|
DEC C ; SKIP DAY OF WEEK (REG $06)
|
|
DEC C ; SKIP HOURS ALARM (REG $05)
|
|
CALL DS12RTC_RDCLK1 ; DO HOUR (REG $04)
|
|
DEC C ; SKIP MINUTES ALARM (REG $03)
|
|
CALL DS12RTC_RDCLK1 ; DO MINUTES (REG $02)
|
|
DEC C ; SKIP SECONDS ALARM (REG $01)
|
|
CALL DS12RTC_RDCLK1 ; DO SECONDS (REG $00)
|
|
POP HL ; RESTORE BUF PTR
|
|
LD A,E ; UIP FLAG TO ACCUM
|
|
OR A ; TEST IT
|
|
JR NZ,DS12RTC_RDCLK ; IF UIP WAS FLAGGED, TRY AGAIN
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
DS12RTC_RDCLK1:
|
|
CALL DS12RTC_UIP ; CHECK FOR UPDATE IN PROGRESS
|
|
JR Z,DS12RTC_RDCLK2 ; IF NO UIP, SKIP AHEAD
|
|
INC E ; FLAG UIP OCCURRED
|
|
DS12RTC_RDCLK2:
|
|
CALL DS12RTC_RDREG ; GET IT
|
|
LD (HL),A ; STORE IN BUF
|
|
INC HL ; BUMP BUF PTR
|
|
DEC C ; DEC REGISTER
|
|
RET
|
|
;
|
|
; WRITE CLOCK DATA FROM BUFFER AT HL
|
|
;
|
|
DS12RTC_WRCLK:
|
|
LD E,0 ; CLEAR UIP FLAG
|
|
PUSH HL ; SAVE IN CASE OF RESTART
|
|
LD C,$09 ; START WITH YEAR REG
|
|
CALL DS12RTC_WRCLK1 ; DO YEAR (REG $09)
|
|
CALL DS12RTC_WRCLK1 ; DO MONTH (REG $08)
|
|
CALL DS12RTC_WRCLK1 ; DO DAY OF MONTH (REG $07)
|
|
DEC C ; SKIP DAY OF WEEK (REG $06)
|
|
DEC C ; SKIP HOURS ALARM (REG $05)
|
|
CALL DS12RTC_WRCLK1 ; DO HOUR (REG $04)
|
|
DEC C ; SKIP MINUTES ALARM (REG $03)
|
|
CALL DS12RTC_WRCLK1 ; DO MINUTES (REG $02)
|
|
DEC C ; SKIP SECONDS ALARM (REG $01)
|
|
CALL DS12RTC_WRCLK1 ; DO SECONDS (REG $00)
|
|
POP HL ; RESTORE BUF PTR
|
|
LD A,E ; UIP FLAG TO ACCUM
|
|
OR A ; TEST IT
|
|
JR NZ,DS12RTC_WRCLK ; IF UIP WAS FLAGGED, TRY AGAIN
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
DS12RTC_WRCLK1:
|
|
CALL DS12RTC_UIP ; CHECK FOR UPDATE IN PROGRESS
|
|
JR Z,DS12RTC_WRCLK2 ; IF NO UIP, SKIP AHEAD
|
|
INC E ; FLAG UIP OCCURRED
|
|
DS12RTC_WRCLK2:
|
|
LD A,(HL) ; GET VALUE
|
|
CALL DS12RTC_WRREG ; WRITE IT
|
|
INC HL ; BUMP BUF PTR
|
|
DEC C ; DEC REGISTER
|
|
JR DS12RTC_UIP ; RETURN VIA CHECK FOR UPDATE IN PROGRESS
|
|
;
|
|
; INITIALIZE RTC
|
|
;
|
|
DS12RTC_INITDEV:
|
|
;
|
|
; GET CLOCK STATUS
|
|
LD C,$0A ; CONTROL REGISTER A
|
|
CALL DS12RTC_RDREG ; READ IT
|
|
PUSH AF ; SAVE IT
|
|
;
|
|
; SET THE CONTROL REGISTERS
|
|
LD C,$0A ; CONTROL REGISTER A
|
|
LD A,%00100110 ; START CLOCK, 1.024KHZ SQUARE WAVE OUTPOUT
|
|
CALL DS12RTC_WRREG ; SEND IT
|
|
INC C ; CONTROL REGISTER B
|
|
LD A,%00000010 ; NO INTS, NO ALM, NO SQW, BCD, 24HR, NO DS
|
|
CALL DS12RTC_WRREG ; SEND IT
|
|
;
|
|
POP AF ; RECOVER ORIGINAL STATUS
|
|
AND %01110000 ; ISOLATE DV BITS
|
|
CP %00100000 ; NORMAL RUNNING VALUE?
|
|
RET Z ; IF SO, DONE
|
|
;
|
|
; PROGRAM DEFAULT DATE/TIME
|
|
LD HL,DS12RTC_TIMDEF ; POINT TO DEFAULT DATE/TIME BUF
|
|
CALL DS12RTC_WRCLK ; WRITE TO THE CLOCK
|
|
RET ; DONE
|
|
;
|
|
; READ REGSITER
|
|
; C=REGISTER
|
|
; A=VALUE
|
|
;
|
|
DS12RTC_RDREG:
|
|
HB_DI ; NO INTS BETWEEN REG SEL AND DATA
|
|
LD A,C ; REGSITER TO A
|
|
OUT (DS12RTC_SEL),A ; SELECT IT
|
|
IN A,(DS12RTC_DATA) ; GET REG VALUE
|
|
HB_EI ; RESTORE INTS
|
|
RET ; DONE
|
|
;
|
|
; WRITE REGSITER
|
|
; C=REGSITER
|
|
; A=VALUE
|
|
;
|
|
DS12RTC_WRREG:
|
|
HB_DI ; NO INTS BETWEEN REG SEL AND DATA
|
|
PUSH AF ; SAVE VALUE TO WRITE
|
|
LD A,C ; REGSITER TO A
|
|
OUT (DS12RTC_SEL),A ; SELECT IT
|
|
POP AF ; RECOVER VALUE TO WRITE
|
|
OUT (DS12RTC_DATA),A ; GET REG VALUE
|
|
HB_EI ; RESTORE INTS
|
|
RET ; DONE
|
|
;
|
|
; CHECK FOR UPDATE IN PROGRESS
|
|
; RETURN NZ IF SO, RETURN Z IF CLEAR TO PROCEED
|
|
; ASSUMES THAT RTC EXISTS AND IS FUNCTIONING
|
|
;
|
|
; UIP BIT WILL BE SET 244US BEFORE AN UPDATE BEGINS.
|
|
; THE UIP BIT MAY NEED TO BE CHECKED REPEATEDLY DURING
|
|
; MULTIPLE BYTE READS/WRITES IF THE PROCESSING MAY
|
|
; TAKE MORE THAN 240US.
|
|
;
|
|
DS12RTC_UIP:
|
|
PUSH BC
|
|
LD C,$0A
|
|
CALL DS12RTC_RDREG ; GET CONTROL REG $0A
|
|
AND $80 ; ISOLATE UIP BIT
|
|
POP BC
|
|
RET
|
|
;
|
|
; DS12RTC_TIMBUF IS DRIVER'S INTERNAL CLOCK DATA BUFFER
|
|
;
|
|
DS12RTC_TIMBUF .FILL 6,0 ; 6 BYTES FOR GETTIM, YYMMDDHHMMSS
|
|
DS12RTC_TIMDEF .DB $00,$01,$01,$00,$00,$00 ; DEFAULT DATE/TIME
|
|
|