; ;================================================================================================== ; NATIONAL SEMICONDUCTOR MM58167B MICROPROCESSOR REAL TIME CLOCK ;================================================================================================== ; ; THIS DRIVER IS FOR THE S100 INTERFACE TO THE MM58167B RTC. THE ; S100 INTERFACE USES 2 IO PORTS, ONE TO SELECT THE RTC REGISTER FOR ; SUBSEQUENT READ/WRITE AND ONE TO PERFORM THE READ/WRITE. ; ; THIS RTC HAS NO YEAR VALUE REGISTER. WE STORE THE YEAR VALUE IN ; REGISTER $09 AS A STATIC VALUE. ; ; THIS RTC DEVICE HAS NO NVRAM! ; ; REGISTER ADDRESSES (HEX / BCD): ; ; +-----+----------------------------------------------+--------+ ; | REG | FUNCTION | RANGE | ; +-----+----------------------------------------------+--------+ ; | $00 | COUNTER - MILLISECONDS | 0-9 | ; | $01 | COUNTER - HUNDREDTHS AND TENTHS OF SECONDS | 0-99 | ; | $02 | COUNTER - SECONDS | 0-59 | ; | $03 | COUNTER - MINUTES | 0-59 | ; | $04 | COUNTER - HOURS | 0-23 | ; | $05 | COUNTER - DAY OF WEEK | 1-7 | ; | $06 | COUNTER - DAY OF MONTH | 1-31 | ; | $07 | COUNTER - MONTH | 1-12 | ; | $08 | RAM - MILLISECONDS | 0-9 | ; | $09 | RAM - HUNDREDTHS AND TENTHS OF SECONDS | 0-99 | ; | $0A | RAM - SECONDS | 0-59 | ; | $0B | RAM - MINUTES | 0-59 | ; | $0C | RAM - HOURS | 0-23 | ; | $0D | RAM - DAY OF WEEK | 1-7 | ; | $0E | RAM - DAY OF MONTH | 1-31 | ; | $0F | RAM - MONTHS | 1-12 | ; | $10 | INTERRUPT STATUS REGISTER | | ; | $11 | INTERRUPT CONTROL REGISTER | | ; | $12 | COUNTERS RESET | | ; | $13 | RAM RESET | | ; | $14 | STATUS BIT | | ; | $15 | GO COMMAND | | ; | $16 | STANDBY INTERRUPT | | ; | $1F | TEST MODE | | ; +-----+----------------------------------------------+--------+ ; MMRTC_IO .EQU $A4 MMRTC_SEL .EQU MMRTC_IO + 0 MMRTC_DATA .EQU MMRTC_IO + 1 ; DEVECHO "MMRTC:" ; DEVECHO " IO=" DEVECHO MMRTC_IO DEVECHO "\n" ; ;-------------------------------------------------------------------------------------------------- ; HBIOS MODULE HEADER ;-------------------------------------------------------------------------------------------------- ; ORG_MMRTC .EQU $ ; .DW SIZ_MMRTC ; MODULE SIZE .DW MMRTC_INITPHASE ; ADR OF INIT PHASE HANDLER ; MMRTC_INITPHASE: ; INIT PHASE HANDLER, A=PHASE ;CP HB_PHASE_PREINIT ; PREINIT PHASE? ;JP Z,MMRTC_PREINIT ; DO PREINIT CP HB_PHASE_INIT ; INIT PHASE? JP Z,MMRTC_INIT ; DO INIT RET ; DONE ; ; RTC DEVICE PRE-INITIALIZATION ENTRY ; MMRTC_PREINIT: XOR A ; SIGNAL SUCCESS RET ; DONE ; ; RTC DEVICE INITIALIZATION ENTRY ; MMRTC_INIT: CALL NEWLINE ; FORMATTING PRTS("MMRTC: $") ; ; PRINT RTC PORT ADDRESS PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS LD A,MMRTC_IO ; GET IO ADDRESS CALL PRTHEXBYTE ; PRINT IT ; CALL MMRTC_DETECT ; HARDWARE DETECTION JR Z,MMRTC_INIT1 ; CONTINUE IF FOUND ; ; HANDLE HARDWARE MISSING PRTS(" NOT PRESENT$") ; NOT ZERO, H/W NOT PRESENT OR $FF ; SIGNAL FAILURE RET ; BAIL OUT ; MMRTC_INIT1: ; DISPLAY CURRENT TIME CALL PC_SPACE LD HL,MMRTC_TIMBUF CALL MMRTC_RDCLK LD HL,MMRTC_TIMBUF CALL PRTDT ; ; REGISTER THE RTC LD BC,MMRTC_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) ; MMRTC_DISPATCH: LD A,B ; GET REQUESTED FUNCTION AND $0F ; ISOLATE SUB-FUNCTION JP Z,MMRTC_GETTIM ; GET TIME DEC A JP Z,MMRTC_SETTIM ; SET TIME DEC A JP Z,MMRTC_GETBYT ; GET NVRAM BYTE VALUE DEC A JP Z,MMRTC_SETBYT ; SET NVRAM BYTE VALUE DEC A JP Z,MMRTC_GETBLK ; GET NVRAM DATA BLOCK VALUES DEC A JP Z,MMRTC_SETBLK ; SET NVRAM DATA BLOCK VALUES DEC A JP Z,MMRTC_GETALM ; GET ALARM DEC A JP Z,MMRTC_SETALM ; SET ALARM DEC A JP Z,MMRTC_DEVICE ; REPORT RTC DEVICE INFO ; SYSCHKERR(ERR_NOFUNC) RET ; ; NVRAM FUNCTIONS ARE NOT AVAILABLE ; ALARM FUNCTIONALITY NOT IMPLEMENTED ; MMRTC_GETBYT: MMRTC_SETBYT: MMRTC_GETBLK: MMRTC_SETBLK: MMRTC_GETALM: MMRTC_SETALM: SYSCHKERR(ERR_NOTIMPL) RET ; ; RTC GET TIME ; BUFFER FORMAT IS BCD: YYMMDDHHMMSS ; 24 HOUR TIME FORMAT IS ASSUMED ; MMRTC_GETTIM: PUSH HL ; SAVE ADR OF OUTPUT BUF ; LD HL,MMRTC_TIMBUF ; POINTER TO CLK DATA CALL MMRTC_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,MMRTC_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 ; MMRTC_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,MMRTC_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,MMRTC_TIMBUF ; POINTER TO CLK DATA CALL MMRTC_WRCLK ; WRITE TO THE CLOCK ; ; CLEAN UP AND RETURN XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; ; REPORT RTC DEVICE INFO ; MMRTC_DEVICE: LD D,RTCDEV_MM ; D := DEVICE TYPE LD E,0 ; E := PHYSICAL DEVICE NUMBER LD H,0 ; H := MODE LD L,MMRTC_IO ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ; DETECT RTC HARDWARE PRESENCE ; ; WE USE THE DAY OF WEEK RAM REGISTER WHICH WILL ONLY STORE THE ; LOW 4 BITS OF THE BYTE. ; MMRTC_DETECT: LD C,$0D ; RAM - DAY OF WEEK LD A,$AA ; TEST VALUE CALL MMRTC_WRREG ; WRITE IT CALL MMRTC_RDREG ; READ IT BACK CP $0A ; EXPECTED VALUE? RET ; ; READ CLOCK DATA INTO BUFFER AT HL (YYMMDDHHMMSS) ; MMRTC_RDCLK: PUSH HL ; SAVE IN CASE OF RE-READ LD C,$09 ; START WITH YEAR REG CALL MMRTC_RDCLK1 ; DO YEAR (REG $09) DEC C ; SKIP RAM MILLISECONDS (REG $08) CALL MMRTC_RDCLK1 ; DO MONTH (REG $07) CALL MMRTC_RDCLK1 ; DO DAY OF MONTH (REG $06) DEC C ; SKIP DAY OF WEEK (REG $05) CALL MMRTC_RDCLK1 ; DO HOUR (REG $04) CALL MMRTC_RDCLK1 ; DO MINUTE MONTH (REG $03) CALL MMRTC_RDCLK1 ; DO SECOND (REG $02) POP HL ; RESTORE IN CASE OF RE-READ ; ; CHECK FOR ROLLOVER IN PROGRESS LD C,$14 ; STATUS BIT CALL MMRTC_RDREG ; READ IT BIT 0,A ; BIT 0 IS ROLLOVER ACTIVE JR NZ,MMRTC_RDCLK ; IF ACTIVE, RE-READ CLOCK ; XOR A ; SIGNAL SUCCESS RET ; DONE ; MMRTC_RDCLK1: CALL MMRTC_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 ; MMRTC_WRCLK: ; LD C,$09 ; START WITH YEAR REG CALL MMRTC_WRCLK1 ; DO YEAR (REG $09) DEC C ; SKIP RAM MILLISECONDS (REG $08) CALL MMRTC_WRCLK1 ; DO MONTH (REG $07) CALL MMRTC_WRCLK1 ; DO DAY OF MONTH (REG $06) DEC C ; SKIP DAY OF WEEK (REG $05) CALL MMRTC_WRCLK1 ; DO HOUR (REG $04) CALL MMRTC_WRCLK1 ; DO MINUTE MONTH (REG $03) CALL MMRTC_WRCLK1 ; DO SECOND (REG $02) ; XOR A ; SIGNAL SUCCESS RET ; DONE ; MMRTC_WRCLK1: LD A,(HL) ; GET VALUE CALL MMRTC_WRREG ; WRITE IT INC HL ; BUMP BUF PTR DEC C ; DEC REGISTER RET ; ; READ REGSITER ; C=REGISTER ; A=VALUE ; MMRTC_RDREG: LD A,C ; REGSITER TO A OUT (MMRTC_SEL),A ; SELECT IT IN A,(MMRTC_DATA) ; GET REG VALUE RET ; DONE ; ; WRITE REGSITER ; C=REGSITER ; A=VALUE ; MMRTC_WRREG: PUSH AF ; SAVE VALUE TO WRITE LD A,C ; REGSITER TO A OUT (MMRTC_SEL),A ; SELECT IT POP AF ; RECOVER VALUE TO WRITE OUT (MMRTC_DATA),A ; GET REG VALUE RET ; DONE ; ; MMRTC_TIMBUF IS DRIVER'S INTERNAL CLOCK DATA BUFFER ; MMRTC_TIMBUF .FILL 6,0 ; 6 BYTES FOR GETTIM, YYMMDDHHMMSS ; ;-------------------------------------------------------------------------------------------------- ; HBIOS MODULE TRAILER ;-------------------------------------------------------------------------------------------------- ; END_MMRTC .EQU $ SIZ_MMRTC .EQU END_MMRTC - ORG_MMRTC ; MEMECHO "MMRTC occupies " MEMECHO SIZ_MMRTC MEMECHO " bytes.\n"