From e29fb437546c902853511e59a7facd0a24499c1c Mon Sep 17 00:00:00 2001 From: Martin Giese Date: Fri, 6 Jun 2025 22:21:26 +0200 Subject: [PATCH 1/2] Code for MC146818/DS1285/DS12885 PC style CLOCK DRIVER --- Source/HBIOS/cfg_MASTER.asm | 3 + Source/HBIOS/hbios.asm | 21 ++ Source/HBIOS/hbios.inc | 1 + Source/HBIOS/pcrtc.asm | 368 ++++++++++++++++++++++++++++++++++++ 4 files changed, 393 insertions(+) create mode 100644 Source/HBIOS/pcrtc.asm diff --git a/Source/HBIOS/cfg_MASTER.asm b/Source/HBIOS/cfg_MASTER.asm index cad61333..6d7f7a4a 100644 --- a/Source/HBIOS/cfg_MASTER.asm +++ b/Source/HBIOS/cfg_MASTER.asm @@ -202,6 +202,9 @@ DS7RTCMODE .EQU DS7RTCMODE_PCF ; DS7RTC: OPERATING MODE: DS7RTCMODE_[PCF] ; DS5RTCENABLE .EQU FALSE ; DS5RTC: ENABLE DS-1305 SPI CLOCK DRIVER (DS5RTC.ASM) ; +PCRTCENABLE .SET FALSE ; PCRTC: DISABLE DS12885 etc. RTC +PCRTC_BASE .SET $C0 ; Default port for PCRTC, like DSRTC. +; SSERENABLE .EQU FALSE ; SSER: ENABLE SIMPLE SERIAL DRIVER (SSER.ASM) SSERCFG .EQU SER_9600_8N1 ; SSER: SERIAL LINE CONFIG SSERSTATUS .EQU $FF ; SSER: STATUS PORT diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index f261b53c..d2902a96 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -4062,6 +4062,9 @@ HB_INITTBL: #IF (EZ80RTCENABLE) .DW EZ80RTC_INIT #ENDIF +#IF (PCRTCENABLE) + .DW PCRTC_INIT +#ENDIF #IF (CPUFAM == CPU_EZ80) ; INITALISE ONE OF THE SUPPORTED SYSTEM TIMER TICKS DRIVERS .DW EZ80_TMR_INIT @@ -8977,6 +8980,15 @@ SIZ_DS5RTC .EQU $ - ORG_DS5RTC MEMECHO " bytes.\n" #ENDIF ; +#IF (PCRTCENABLE) +ORG_PCRTC .EQU $ + #INCLUDE "pcrtc.asm" +SIZ_PCRTC .EQU $ - ORG_PCRTC + MEMECHO "PCRTC occupies " + MEMECHO SIZ_PCRTC + MEMECHO " bytes.\n" +#ENDIF +; #IF (INTRTCENABLE) ORG_INTRTC .EQU $ #INCLUDE "intrtc.asm" @@ -9003,6 +9015,15 @@ SIZ_RP5RTC .EQU $ - ORG_RP5RTC MEMECHO SIZ_RP5RTC MEMECHO " bytes.\n" #ENDIF +#IF (DSRTCENABLE) +; +ORG_PCRTC .EQU $ + #INCLUDE "pcrtc.asm" +SIZ_PCRTC .EQU $ - ORG_PCRTC + MEMECHO "PCRTC occupies " + MEMECHO SIZ_PCRTC + MEMECHO " bytes.\n" +#ENDIF ; #IF (SSERENABLE) ORG_SSER .EQU $ diff --git a/Source/HBIOS/hbios.inc b/Source/HBIOS/hbios.inc index 425536b6..368aeaf7 100644 --- a/Source/HBIOS/hbios.inc +++ b/Source/HBIOS/hbios.inc @@ -431,6 +431,7 @@ RTCDEV_DS7 .EQU $04 ; DS1307 (I2C) RTCDEV_RP5 .EQU $05 ; RP5C01 RTCDEV_DS5 .EQU $06 ; DS1305 (SPI) RTCDEV_EZ80 .EQU $07 ; EZ80 ON-CHIP RTC +RTCDEV_PC .EQU $08 ; PC style parallel RTC ; ; DSKY DEVICE IDS ; diff --git a/Source/HBIOS/pcrtc.asm b/Source/HBIOS/pcrtc.asm new file mode 100644 index 00000000..cd117236 --- /dev/null +++ b/Source/HBIOS/pcrtc.asm @@ -0,0 +1,368 @@ +; +;================================================================================================== +; MC146818/DS1285/DS12885 PC style CLOCK DRIVER +;================================================================================================== +; +PCRTC_BUFSIZ .EQU 6 ; SIX BYTE BUFFER (YYMMDDHHMMSS) + + ;; Addressing is via first writing the address byte to IO port PCRTC_BASE + ;; Then read from or write to PCRTC_DAT + + ;; PCRTC_BASE must be set in config files +PCRTC_REG .EQU PCRTC_BASE +PCRTC_DAT .EQU PCRTC_BASE + $01 + +REG_SEC .EQU $00 +REG_SEC_ALM .EQU $01 +REG_MIN .EQU $02 +REG_MIN_ALM .EQU $03 +REG_HOUR .EQU $04 +REG_HOUR_ALM .EQU $05 +REG_DOW .EQU $06 ; day of week +REG_DAY .EQU $07 +REG_MONTH .EQU $08 +REG_YEAR .EQU $09 +REG_CTLA .EQU $0A +REG_CTLB .EQU $0B +REG_CTLC .EQU $0C +REG_CTLD .EQU $0D + +CTLA_VAL .EQU $2F +CTLB_VAL .EQU $0A + +PCRTC_NVBASE .EQU $10 +PCRTC_NVSIZE .EQU $30 ; 64 bytes in total is what DS1285 and MC146818 had + + DEVECHO "PCRTC: IO=" + DEVECHO PCRTC_BASE + DEVECHO "\n" + +PCRTC_INIT: + LD A, (RTC_DISPACT) ; RTC DISPATCHER ALREADY SET? + OR A ; SET FLAGS + RET NZ ; IF ALREADY ACTIVE, ABORT + + CALL NEWLINE ; FORMATTING + PRTS("PC RTC: $") + + ; PRINT RTC REGISTER NR PORT ADDRESS + PRTS("IO=0x$") ; LABEL FOR IO ADDRESS + LD A,PCRTC_REG ; GET IO ADDRESS + CALL PRTHEXBYTE ; PRINT IT + CALL PC_SPACE ; FORMATTING + + ; CHECK PRESENCE STATUS + CALL PCRTC_DETECT ; HARDWARE DETECTION + JR Z, PCRTC_INIT1 ; IF ZERO, ALL GOOD + PRTS("NOT PRESENT$") ; NOT ZERO, H/W NOT PRESENT + OR $FF ; SIGNAL FAILURE + RET ; BAIL OUT + +PCRTC_INIT1: + CALL PCRTC_RDTIM + + ; DISPLAY CURRENT TIME + LD HL, PCRTC_BCDBUF ; POINT TO BCD BUF + CALL PRTDT +; + LD BC, PCRTC_DISPATCH + CALL RTC_SETDISP +; + XOR A ; SIGNAL SUCCESS + RET +; +; DETECT RTC HARDWARE PRESENCE +; +PCRTC_DETECT: + LD C, 0 ; NVRAM INDEX 0 + CALL PCRTC_GETBYT ; GET VALUE + LD A, E ; TO ACCUM + LD L, A ; SAVE IT + XOR $FF ; FLIP ALL BITS + LD E, A ; TO E + LD C, 0 ; NVRAM INDEX 0 + CALL PCRTC_SETBYT ; WRITE IT + LD C, 0 ; NVRAM INDEX 0 + CALL PCRTC_GETBYT ; GET VALUE + LD A, L ; GET SAVED VALUE + XOR $FF ; FLIP ALL BITS + CP E ; COMPARE WITH VALUE READ + LD A, 0 ; ASSUME OK + JR Z, PCRTC_DETECT1 ; IF MATCH, GO AHEAD + LD A, $FF ; ELSE STATUS IS ERROR + +PCRTC_DETECT1: + PUSH AF ; SAVE STATUS + LD E, L ; GET SAVED VALUE + LD C, 0 ; NVRAM INDEX 0 + CALL PCRTC_SETBYT ; SAVE IT + POP AF ; RECOVER STATUS + OR A ; SET FLAGS + RET +; +; RTC DEVICE FUNCTION DISPATCH ENTRY +; A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR +; B: FUNCTION (IN) +; +PCRTC_DISPATCH: + LD A,B ; GET REQUESTED FUNCTION + AND $0F ; ISOLATE SUB-FUNCTION + JP Z,PCRTC_GETTIM ; GET TIME + DEC A + JP Z,PCRTC_SETTIM ; SET TIME + DEC A + JP Z,PCRTC_GETBYT ; GET NVRAM BYTE VALUE + DEC A + JP Z,PCRTC_SETBYT ; SET NVRAM BYTE VALUE + DEC A + JP Z,PCRTC_GETBLK ; GET NVRAM DATA BLOCK VALUES + DEC A + JP Z,PCRTC_SETBLK ; SET NVRAM DATA BLOCK VALUES + DEC A + JP Z,PCRTC_GETALM ; GET ALARM + DEC A + JP Z,PCRTC_SETALM ; SET ALARM + DEC A + JP Z,PCRTC_DEVICE ; REPORT RTC DEVICE INFO + SYSCHKERR(ERR_NOFUNC) + RET +; +; RTC GET NVRAM BYTE +; C: INDEX +; E: VALUE (OUTPUT) +; A:0 IF OK, ERR_RANGE IF OUT OF RANGE +; +PCRTC_GETBYT: + LD A, C + CP PCRTC_NVSIZE + JR NC, PCRTC_BADIDX + + ADD A, PCRTC_NVBASE + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD E, A + + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN + +PCRTC_BADIDX: + LD E, 00 + LD A, ERR_RANGE + RET +; +; RTC SET NVRAM BYTE +; C: INDEX +; E: VALUE +; A:0 IF OK, ERR_RANGE IF OUT OF RANGE +; +PCRTC_SETBYT: + LD A, C + CP PCRTC_NVSIZE + JR NC, PCRTC_BADIDX + + ADD A, PCRTC_NVBASE + EZ80_IO + OUT (PCRTC_REG), A + LD A, E + EZ80_IO + OUT (PCRTC_DAT), A + + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN + + +PCRTC_GETBLK: +PCRTC_SETBLK: +PCRTC_GETALM: +PCRTC_SETALM: + SYSCHKERR(ERR_NOTIMPL) + RET +; +; 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 +; +PCRTC_GETTIM: + ; GET THE TIME INTO TEMP BUF + PUSH HL ; SAVE PTR TO CALLERS BUFFER +; + CALL PCRTC_RDTIM + + ; 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,PCRTC_BCDBUF ; SOURCE ADR + POP DE ; DEST ADR + LD BC,PCRTC_BUFSIZ ; LENGTH + CALL HB_BNKCPY ; COPY THE CLOCK DATA + + 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: YYMMDDHHMMSSWW +; 24 HOUR TIME FORMAT IS ASSUMED +; +PCRTC_SETTIM: + ; COPY TO BCD BUF + 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,PCRTC_BCDBUF ; DEST ADR + LD BC,PCRTC_BUFSIZ ; LENGTH + CALL HB_BNKCPY ; COPY THE RPC DATA +; + LD A, REG_CTLA ; Set Ctl Reg A + EZ80_IO + OUT (PCRTC_REG), A + LD A, CTLA_VAL + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_CTLB ; Set Ctl Reg B + EZ80_IO + OUT (PCRTC_REG), A + LD A, CTLB_VAL|0x80 ; Set the SET bit to stop updates + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_SEC ; Set seconds + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_SS) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_MIN ; Set minutes + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_MM) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_HOUR ; Set hours + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_HH) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_DAY ; Set date + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_DT) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_MONTH ; Set month + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_MO) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_YEAR ; Set year + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_YR) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_CTLB ; Set Ctl Reg B + EZ80_IO + OUT (PCRTC_REG), A + LD A, CTLB_VAL ; Reset the SET bit to start clock + EZ80_IO + OUT (PCRTC_DAT), A + + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN +; +; REPORT RTC DEVICE INFO +; +PCRTC_DEVICE: + LD D,RTCDEV_PC ; D := DEVICE TYPE + LD E,0 ; E := PHYSICAL DEVICE NUMBER + LD H,0 ; H := 0, DRIVER HAS NO MODES + LD L, PCRTC_BASE ; L := 0, NO I/O ADDRESS + XOR A ; SIGNAL SUCCESS + RET + +; +; READ OUT THE TIME +PCRTC_RDTIM: + ;; Need to wait until update-in-progress flag is reset + LD A, REG_CTLA ; Set Ctl Reg A + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + BIT 7, A + JP NZ, PCRTC_RDTIM ; Jump back if update in progress. + + LD A, REG_SEC ; Set seconds + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_SS), A + + LD A, REG_MIN ; Set minutes + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_MM), A + + LD A, REG_HOUR ; Set hours + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_HH), A + + LD A, REG_DAY ; Set day + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_DT), A + + LD A, REG_MONTH ; Set month + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_MO), A + + LD A, REG_YEAR ; Set year + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_YR), A + + RET + + +; +; REGISTER EXTRACTED VALUES +; +PCRTC_BCDBUF: +PCRTC_YR .DB $25 +PCRTC_MO .DB $01 +PCRTC_DT .DB $01 +PCRTC_HH .DB $00 +PCRTC_MM .DB $00 +PCRTC_SS .DB $00 + From 1813100142d88226003318ece61dbb6ce262d571 Mon Sep 17 00:00:00 2001 From: Martin Giese Date: Fri, 6 Jun 2025 22:36:51 +0200 Subject: [PATCH 2/2] Documentation additions for PC style clock --- Source/Doc/Hardware.md | 1 + Source/Doc/SystemGuide.md | 1 + 2 files changed, 2 insertions(+) diff --git a/Source/Doc/Hardware.md b/Source/Doc/Hardware.md index c7702545..d67f9c3f 100644 --- a/Source/Doc/Hardware.md +++ b/Source/Doc/Hardware.md @@ -2318,6 +2318,7 @@ Note: | DSRTC | Maxim DS1302 Real-Time Clock w/ NVRAM | | EZ80RTC | eZ80 Real-Time Clock | | INTRTC | Interrupt-based Real Time Clock | +| PCRTC | MC146818/DS1285/DS12885 PC style | | PCF | PCF8584-based I2C Real-Time Clock | | RP5C01 | Ricoh RPC01A Real-Time Clock w/ NVRAM | | SIMRTC | SIMH Simulator Real-Time Clock | diff --git a/Source/Doc/SystemGuide.md b/Source/Doc/SystemGuide.md index d4acdb0e..59b40f32 100644 --- a/Source/Doc/SystemGuide.md +++ b/Source/Doc/SystemGuide.md @@ -1416,6 +1416,7 @@ unit. The table below enumerates these values. | RTCDEV_DS7 | 0x04 | Maxim DS1307 PCF I2C RTC w/ NVRAM | ds7rtc.asm | | RTCDEV_RP5 | 0x05 | Ricoh RPC01A Real-Time Clock w/ NVRAM | rp5rtc.asm | | RTCDEV_EZ80 | 0x07 | eZ80 on-chip RTC | ez80rtc.asm | +| RTCDEV_PC | 0x08 | MC146818/DS1285/DS12885 RTC w/ NVRAM | pcrtc.asm | The time functions to get and set the time (RTCGTM and RTCSTM) require a 6 byte date/time buffer in the following format. Each byte is BCD