diff --git a/Source/HBIOS/mmrtc.asm b/Source/HBIOS/mmrtc.asm new file mode 100644 index 00000000..8da09b7e --- /dev/null +++ b/Source/HBIOS/mmrtc.asm @@ -0,0 +1,297 @@ +; +;================================================================================================== +; 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" +; +; 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