From 99358a7aaf6d670ab745e03716c01540685247a8 Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Sat, 24 Oct 2020 21:19:37 +1100 Subject: [PATCH 01/10] Initial commit for RP5C01 RTC driver --- Source/HBIOS/cfg_dyno.asm | 2 + Source/HBIOS/cfg_ezz80.asm | 2 + Source/HBIOS/cfg_master.asm | 2 + Source/HBIOS/cfg_mk4.asm | 2 + Source/HBIOS/cfg_n8.asm | 2 + Source/HBIOS/cfg_rcz180.asm | 2 + Source/HBIOS/cfg_rcz280.asm | 2 + Source/HBIOS/cfg_rcz80.asm | 2 + Source/HBIOS/cfg_sbc.asm | 2 + Source/HBIOS/cfg_scz180.asm | 2 + Source/HBIOS/cfg_zeta.asm | 2 + Source/HBIOS/cfg_zeta2.asm | 2 + Source/HBIOS/hbios.asm | 61 ++++++----- Source/HBIOS/hbios.inc | 3 +- Source/HBIOS/rp5rtc.asm | 203 ++++++++++++++++++++++++++++++++++++ 15 files changed, 265 insertions(+), 26 deletions(-) create mode 100644 Source/HBIOS/rp5rtc.asm diff --git a/Source/HBIOS/cfg_dyno.asm b/Source/HBIOS/cfg_dyno.asm index 43255017..e5f3174d 100644 --- a/Source/HBIOS/cfg_dyno.asm +++ b/Source/HBIOS/cfg_dyno.asm @@ -82,6 +82,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index b247529f..0cfa36dc 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -83,6 +83,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index 3b0b428b..0618dadb 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -114,6 +114,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index 892f05bc..7bfb167c 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -89,6 +89,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index 3948fc0e..3e70cf78 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -92,6 +92,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index a2f45aad..5715c783 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -85,6 +85,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index bd0e0281..653e282a 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -90,6 +90,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index 5c2a0c7a..e529f743 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -84,6 +84,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index 967b196d..de34c10f 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -84,6 +84,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index b6fe1c51..74976cdf 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -80,6 +80,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index 6eca0583..e5eff0d2 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -72,6 +72,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index 5be06627..cec7ef24 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -83,6 +83,8 @@ BQRTC_BASE .EQU $50 ; BQRTC: I/O BASE ADDRESS ; INTRTCENABLE .EQU FALSE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) ; +RP5RTCENABLE .EQU FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) +; HTIMENABLE .EQU FALSE ; ENABLE SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; ENABLE SIMH CLOCK DRIVER (SIMRTC.ASM) ; diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index f214d920..b4e0c6c5 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -327,13 +327,13 @@ HBX_INVOKE: ; LD A,(HB_CURBNK) ; GET CURRENT BANK LD (HB_INVBNK),A ; SAVE INVOCATION BANK -; +; LD A,BID_BIOS ; HBIOS BANK LD (HB_CURBNK),A ; SET AS CURRENT BANK ; .DB $ED,$71 ; SC .DW HB_DISPATCH ; SC PARAMETER -; +; PUSH AF LD A,(HB_INVBNK) LD (HB_CURBNK),A @@ -788,7 +788,7 @@ HBX_INT: ; COMMON INTERRUPT ROUTING CODE ; SYSTEM OR USER MODE WAS ACTIVE AT THE TIME OF THE INTERRUPT. ; EX (SP),HL ; SAVE HL AND GET INT JP TABLE OFFSET - + ; SAVE STATE (HL SAVED PREVIOUSLY ON ORIGINAL STACK FRAME) PUSH AF ; SAVE AF PUSH BC ; SAVE BC @@ -814,7 +814,7 @@ HBX_INT: ; COMMON INTERRUPT ROUTING CODE CALL HBX_RETI ; RETI FOR Z80 PERIPHERALS RETIL ; -HBX_RETI: +HBX_RETI: RETI ; #ELSE @@ -859,7 +859,7 @@ HBX_INT_SP .EQU $ - 2 RETI ; AND RETURN ; #ENDIF - + #ENDIF ; ; SMALL TEMPORARY STACK FOR USE BY HBX_BNKCPY @@ -1095,13 +1095,13 @@ Z280_BOOTPDRTBL: ; Z280_INITZ: ; - #ENDIF + #ENDIF ; ; RESTORE I/O PAGE TO $00 LD L,$00 ; NORMAL I/O REG IS $00 LD C,Z280_IOPR ; REG C POINTS TO I/O PAGE REGISTER LDCTL (C),HL -; +; #ENDIF ; #IF (CPUFAM == CPU_Z180) @@ -1152,7 +1152,7 @@ Z280_INITZ: ; ; SET DEFAULT CSIO SPEED (INTERNAL CLOCK, SLOW AS POSSIBLE) LD A,Z180_CNTR_DEF ; DIV 1280, 14KHZ @ 18MHZ CLK - OUT0 (Z180_CNTR),A + OUT0 (Z180_CNTR),A #ENDIF ; #ENDIF @@ -1738,7 +1738,7 @@ NOT_REC_M0: ; XOR A ; FAILSAFE VALUE FOR BOOT CONSOLE DEVICE LD (CB_CONDEV),A ; SAVE IT -; +; LD A,(CIO_CNT) ; GET COUNT OF CHAR DEVICES CP BOOTCON + 1 ; COUNT - (DEVICE + 1) JR C,HB_CONRDY ; IF TOO HIGH, JUST USE FAILSAFE @@ -1881,7 +1881,7 @@ HB_Z280BUS1: ; DISPLAY CPU CONFIG ; CALL NEWLINE - + #IF (CPUFAM == CPU_Z280) LD A,Z280_MEMLOWAIT CALL PRTDECB @@ -2285,6 +2285,9 @@ HB_INITTBL: .DW PCF8584_INIT .DW DS7RTC_INIT #ENDIF +#IF (RP5RTCENABLE) + .DW RP5RTC_INIT +#ENDIF #IF (VDUENABLE) .DW VDU_INIT #ENDIF @@ -2963,7 +2966,7 @@ SYS_RESINT: ; SYS_RESWARM: CALL SYS_RESINT -; +; #IF (MEMMGR == MM_Z280) JP INITSYS4 #ELSE @@ -3909,13 +3912,13 @@ Z280_PRIVINST: LD (HB_MSRSAV),HL ; SAVE IT POP HL ; RECOVER HL, POP STACK EX (SP),HL ; GET ADR, SAVE HL -; +; PUSH AF PUSH BC PUSH DE -; +; .DB $ED,$96 ; LDUP A,(HL) -; +; ; HANDLE DI CP $F3 ; DI? JR NZ,Z280_PRIVINST2 @@ -4251,7 +4254,7 @@ Z280_BNKSEL: PUSH HL ; SAVE IT LD L,$FF ; NEW I/O PAGE LDCTL (C),HL -; +; ; CONVERT BANK ID TO TOP 12 BITS OF PHYSICAL ADDRESS ; WITH $0A IN THE LOW ORDER NIBBLE: ; BANK ID: R000 BBBB @@ -4263,7 +4266,7 @@ Z280_BNKSEL: JR Z,Z280_BNKSEL2 ; IF NOT, ALL DONE RES 6,H ; OTHERWISE, MOVE RAM BIT SET RAMLOC-16,H ; HL=0000 RBBB B000 0000 -; +; Z280_BNKSEL2: ; ; SET LOW NIBBLE @@ -4332,19 +4335,19 @@ Z280_BNKCPY: ; PUSH BC ; SAVE COUNT PUSH HL ; SAVE SOURCE ADDRESS -; +; ; SELECT I/O PAGE $FF LD C,Z280_IOPR ; I/O PAGE REGISTER LDCTL HL,(C) ; GET CURRENT I/O PAGE LD (IOPRVAL),HL ; SAVE IT LD L,$FF ; I/O PAGE $FF LDCTL (C),HL -; +; LD C,Z280_DMA0_DSTL ; START WITH DEST REG LO ; LD A,(HB_DSTBNK) ; DEST BANK TO ACCUM CALL Z2DMAADR ; SETUP DEST ADR REGS -; +; POP DE ; SRC ADR TO DE LD A,(HB_SRCBNK) ; DEST BANK TO ACCUM CALL Z2DMAADR ; SETUP SOURCE ADR REGS @@ -4399,7 +4402,7 @@ Z2DMAADR1: LD A,$0F ; A=0000 1111 OR L ; A=BAAA 1111 LD L,A ; L=BAAA 1111 -; +; ; MOVE THE RAM/ROM BIT. ; RC2014 DMA HI=0000 RBBB BAAA 1111 LO=1111 AAAA AAAA AAAA ; ZZ80MB DMA HI=R000 0BBB BAAA 1111 LO=1111 AAAA AAAA AAAA @@ -4425,7 +4428,7 @@ Z2DMAADR2: POP HL ; RECOVER THE HI VAL OUTW (C),HL INC C ; BUMP TO NEXT REG -; +; RET #ENDIF ; @@ -4499,6 +4502,14 @@ SIZ_INTRTC .EQU $ - ORG_INTRTC .ECHO " bytes.\n" #ENDIF ; +#IF (RP5RTCENABLE) +ORG_RP5RTC .EQU $ + #INCLUDE "rp5rtc.asm" +SIZ_RP5RTC .EQU $ - ORG_RP5RTC + .ECHO "RP5RTC occupies " + .ECHO SIZ_RP5RTC + .ECHO " bytes.\n" +#ENDIF #IF (ASCIENABLE) ORG_ASCI .EQU $ #INCLUDE "asci.asm" @@ -4944,7 +4955,7 @@ SYSCHK: CP DL_ERROR ; >= ERROR LEVEL JR C,SYSCHK1 ; IF NOT, GO HOME POP AF ; RESTORE INCOMING AF VALUE -; +; ; DISPLAY SYSCHK MESSAGE PUSH DE ; PRESERVE DE VALUE LD DE,STR_SYSCHK ; POINT TO PREFIX STRING @@ -5151,7 +5162,7 @@ PS_PRTDC: CP 5 ; RAM DISK? JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB CP 7 ; FLASH DISK? - JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB + JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB ; ; PRINT HARD DISK STORAGE SIZE IN MB LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY @@ -5416,8 +5427,8 @@ PS_SOUND: PRTS(" $") ; PAD TO NEXT COLUMN ; DEVICE COLUMN - - PUSH BC ; + + PUSH BC ; LD E,C XOR A LD DE,PS_SDSND ; POINT TO DEVICE TYPE NAME TABLE diff --git a/Source/HBIOS/hbios.inc b/Source/HBIOS/hbios.inc index b52536d8..78678921 100644 --- a/Source/HBIOS/hbios.inc +++ b/Source/HBIOS/hbios.inc @@ -131,7 +131,7 @@ ERR_RANGE .EQU -6 ; PARAMETER OUT OF RANGE ERR_NOMEDIA .EQU -7 ; MEDIA NOT PRESENT ERR_NOHW .EQU -8 ; HARDWARE NOT PRESENT ERR_IO .EQU -9 ; I/O ERROR -ERR_READONLY .EQU -10 ; WRITE REQUEST TO READ-ONLY MEDIA +ERR_READONLY .EQU -10 ; WRITE REQUEST TO READ-ONLY MEDIA ERR_TIMEOUT .EQU -11 ; DEVICE TIMEOUT ERR_BADCFG .EQU -12 ; INVALID CONFIGURATION ERR_INTERNAL .EQU -13 ; INTERNAL ERROR @@ -191,6 +191,7 @@ RTCDEV_BQ .EQU $10 ; BQ4845P RTCDEV_SIMH .EQU $20 ; SIMH RTCDEV_INT .EQU $30 ; PERIODIC INT TIMER RTCDEV_DS7 .EQU $40 ; DS1302 (I2C) +RTCDEV_RP5 .EQU $50 ; RP5C01 ; ; VIDEO DEVICE IDS ; diff --git a/Source/HBIOS/rp5rtc.asm b/Source/HBIOS/rp5rtc.asm new file mode 100644 index 00000000..f4b83abf --- /dev/null +++ b/Source/HBIOS/rp5rtc.asm @@ -0,0 +1,203 @@ +; +;================================================================================================== +; RP5C01 CLOCK DRIVER +;================================================================================================== +; +RP5RTC_BUFSIZ .EQU 6 ; SIX BYTE BUFFER (YYMMDDHHMMSS) +; +; RTC DEVICE INITIALIZATION ENTRY +; + +RP5RTC_REG .EQU $B4 +RP5RTC_DAT .EQU $B5 + +REG_1SEC .EQU $00 +REG_10SEC .EQU $01 +REG_MODE .EQU $0D +REG_TEST .EQU $0E + +MD_TIM .EQU 8 +MD_ALM .EQU 4 + +RP5RTC_INIT: + LD A,(RTC_DISPACT) ; RTC DISPATCHER ALREADY SET? + OR A ; SET FLAGS + RET NZ ; IF ALREADY ACTIVE, ABORT +; + CALL NEWLINE ; FORMATTING + PRTS("RP5C01 RTC: $") +; + +; ENSURE DEVICE IS RESET AND NOT IN TEST MODE + LD A, REG_TEST ; SELECT TEST REGISTER + OUT (RP5RTC_REG), A + CALL DLY16 + XOR A + OUT (RP5RTC_DAT), A ; TURN OFF ALL TEST MODE BITS + + CALL RP5RTC_RDTIM + + ; DISPLAY CURRENT TIME + LD HL, RP5RTC_BCDBUF ; POINT TO BCD BUF + CALL PRTDT +; + LD BC, RP5RTC_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) +; +RP5RTC_DISPATCH: + LD A,B ; GET REQUESTED FUNCTION + AND $0F ; ISOLATE SUB-FUNCTION + JP Z,RP5RTC_GETTIM ; GET TIME + DEC A + JP Z,RP5RTC_SETTIM ; SET TIME + DEC A + JP Z,RP5RTC_GETBYT ; GET NVRAM BYTE VALUE + DEC A + JP Z,RP5RTC_SETBYT ; SET NVRAM BYTE VALUE + DEC A + JP Z,RP5RTC_GETBLK ; GET NVRAM DATA BLOCK VALUES + DEC A + JP Z,RP5RTC_SETBLK ; SET NVRAM DATA BLOCK VALUES + DEC A + JP Z,RP5RTC_GETALM ; GET ALARM + DEC A + JP Z,RP5RTC_SETALM ; SET ALARM + DEC A + JP Z,RP5RTC_DEVICE ; REPORT RTC DEVICE INFO + CALL SYSCHK + LD A,ERR_NOFUNC + OR A + RET +; +; NVRAM FUNCTIONS ARE NOT AVAILABLE IN SIMULATOR +; +RP5RTC_GETBYT: +RP5RTC_SETBYT: +RP5RTC_GETBLK: +RP5RTC_SETBLK: +RP5RTC_GETALM: +RP5RTC_SETALM: + CALL SYSCHK + LD A,ERR_NOTIMPL + OR A + 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 +; +RP5RTC_GETTIM: + ; GET THE TIME INTO TEMP BUF + PUSH HL ; SAVE PTR TO CALLERS BUFFER +; + CALL RP5RTC_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,RP5RTC_BCDBUF ; SOURCE ADR + POP DE ; DEST ADR + LD BC,RP5RTC_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 +; +RP5RTC_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,RP5RTC_BCDBUF ; DEST ADR + LD BC,RP5RTC_BUFSIZ ; LENGTH + CALL HB_BNKCPY ; COPY THE CLOCK DATA +; + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN +; +; REPORT RTC DEVICE INFO +; +RP5RTC_DEVICE: + LD D,RTCDEV_RP5 ; D := DEVICE TYPE + LD E,0 ; E := PHYSICAL DEVICE NUMBER + LD H,0 ; H := 0, DRIVER HAS NO MODES + LD L,0 ; L := 0, NO I/O ADDRESS + XOR A ; SIGNAL SUCCESS + RET + +; +; READ OUT THE TIME +RP5RTC_RDTIM: + LD A, REG_MODE ; SELECT MODE REGISTER + OUT (RP5RTC_REG), A + ; CALL DLY32 + LD A, MD_TIM | !MD_ALM | 0 ; TURN ON TIME AND TURN OFF ALARM + OUT (RP5RTC_DAT), A ; AND SET MODE 0 (REGISTER BANK 0) + ; CALL DLY32 + + LD A, REG_1SEC ; SELECT 1 SECOND REGISTER + OUT (RP5RTC_REG), A + ; CALL DLY32 + IN A, (RP5RTC_DAT) + AND $0F ; RETRIEVE 1 SECOND NIBBLE + LD L, A + + LD A, REG_10SEC ; SELECT 1 SECOND REGISTER + OUT (RP5RTC_REG), A + ; CALL DLY32 + IN A, (RP5RTC_DAT) + AND $0F + rlca + rlca + rlca + rlca ; MOVE TO TOP NIBBLE + OR L ; MERGE IN LOW NIBBLE + LD H, A + ; A = SECONDS AS BCD + LD (RP5RTC_SS), A + + RET + +; +; WORKING VARIABLES +; +RP5RTC_BCDBUF: ; ALL IN BINARY +RP5RTC_YR .DB 20 +RP5RTC_MO .DB 01 +RP5RTC_DT .DB 01 +RP5RTC_HH .DB 00 +RP5RTC_MM .DB 00 +RP5RTC_SS .DB 00 +;; +RP5RTC_MONTBL: ; DAYS IN MONTH + 1 + .DB 32 ; JANUARY + .DB 29 ; FEBRUARY (NON-LEAP) + .DB 32 ; MARCH + .DB 31 ; APRIL + .DB 32 ; MAY + .DB 31 ; JUNE + .DB 32 ; JULY + .DB 32 ; AUGUST + .DB 31 ; SEPTEMBER + .DB 32 ; OCTOBER + .DB 31 ; NOVEMBER + .DB 32 ; DECEMBER From 8981a255a7997153905fa54be8ba73960b84dcf2 Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Sat, 24 Oct 2020 22:48:05 +1100 Subject: [PATCH 02/10] RP5C01: Added support for assign date/time --- Source/HBIOS/rp5rtc.asm | 168 ++++++++++++++++++++++++++++++++-------- 1 file changed, 134 insertions(+), 34 deletions(-) diff --git a/Source/HBIOS/rp5rtc.asm b/Source/HBIOS/rp5rtc.asm index f4b83abf..fec5fc63 100644 --- a/Source/HBIOS/rp5rtc.asm +++ b/Source/HBIOS/rp5rtc.asm @@ -13,11 +13,30 @@ RP5RTC_DAT .EQU $B5 REG_1SEC .EQU $00 REG_10SEC .EQU $01 +REG_1MIN .EQU $02 +REG_10MIN .EQU $03 +REG_1HR .EQU $04 +REG_10HR .EQU $05 +REG_DAYWEEK .EQU $06 +REG_1DAY .EQU $07 +REG_10DAY .EQU $08 +REG_1MNTH .EQU $09 +REG_10MNTH .EQU $0A +REG_1YEAR .EQU $0B +REG_10YEAR .EQU $0C REG_MODE .EQU $0D REG_TEST .EQU $0E +REG_RESET .EQU $0F -MD_TIM .EQU 8 -MD_ALM .EQU 4 +REG_12_24 .EQU $0A + +MODE_TIMEST .EQU 0 +MODE_ALRMST .EQU 1 +MODE_RAM0 .EQU 2 +MODE_RAM1 .EQU 3 + +MD_TIME .EQU 8 +MD_ALRM .EQU 4 RP5RTC_INIT: LD A,(RTC_DISPACT) ; RTC DISPATCHER ALREADY SET? @@ -35,6 +54,16 @@ RP5RTC_INIT: XOR A OUT (RP5RTC_DAT), A ; TURN OFF ALL TEST MODE BITS + + LD B, MODE_ALRMST + CALL RP5RTC_SETMD + + LD A, REG_12_24 ; SET TO 24 HOUR CLOCK + OUT (RP5RTC_REG), A + LD A, 1 + OUT (RP5RTC_DAT), A + + CALL RP5RTC_RDTIM ; DISPLAY CURRENT TIME @@ -131,6 +160,33 @@ RP5RTC_SETTIM: LD BC,RP5RTC_BUFSIZ ; LENGTH CALL HB_BNKCPY ; COPY THE CLOCK DATA ; + LD B, MODE_TIMEST + CALL RP5RTC_SETMD + + LD B, REG_1SEC + LD A, (RP5RTC_SS) + CALL RP5RTC_WRVL + + LD B, REG_1MIN + LD A, (RP5RTC_MM) + CALL RP5RTC_WRVL + + LD B, REG_1HR + LD A, (RP5RTC_HH) + CALL RP5RTC_WRVL + + LD B, REG_1DAY + LD A, (RP5RTC_DT) + CALL RP5RTC_WRVL + + LD B, REG_1MNTH + LD A, (RP5RTC_MO) + CALL RP5RTC_WRVL + + LD B, REG_1YEAR + LD A, (RP5RTC_YR) + CALL RP5RTC_WRVL + XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; @@ -147,57 +203,101 @@ RP5RTC_DEVICE: ; ; READ OUT THE TIME RP5RTC_RDTIM: + LD B, MODE_TIMEST + CALL RP5RTC_SETMD + + LD B, REG_1SEC + CALL RP5RTC_RDVL + LD (RP5RTC_SS), A + + LD B, REG_1MIN + CALL RP5RTC_RDVL + LD (RP5RTC_MM), A + + LD B, REG_1HR + CALL RP5RTC_RDVL + LD (RP5RTC_HH), A + + LD B, REG_1DAY + CALL RP5RTC_RDVL + LD (RP5RTC_DT), A + + LD B, REG_1MNTH + CALL RP5RTC_RDVL + LD (RP5RTC_MO), A + + LD B, REG_1YEAR + CALL RP5RTC_RDVL + LD (RP5RTC_YR), A + + RET + +; SET MODE +; MODE IN B (MODE_TIMEST, MODE_ALRMST, MODE_RAM0, MODE_RAM1) +RP5RTC_SETMD: LD A, REG_MODE ; SELECT MODE REGISTER OUT (RP5RTC_REG), A - ; CALL DLY32 - LD A, MD_TIM | !MD_ALM | 0 ; TURN ON TIME AND TURN OFF ALARM - OUT (RP5RTC_DAT), A ; AND SET MODE 0 (REGISTER BANK 0) - ; CALL DLY32 - LD A, REG_1SEC ; SELECT 1 SECOND REGISTER + IN A, (RP5RTC_DAT) + AND MD_TIME | MD_ALRM + OR B + OUT (RP5RTC_DAT), A ; ASSIGN MODE + RET + + +; READ OUT 2 REGISTERS - 2 NIBBLES TO 1 BYTE +; REGISTER IN B +RP5RTC_RDVL: + LD A, B ; SELECT UNIT REGISTER OUT (RP5RTC_REG), A - ; CALL DLY32 IN A, (RP5RTC_DAT) - AND $0F ; RETRIEVE 1 SECOND NIBBLE + AND $0F ; RETRIEVE UNIT NIBBLE LD L, A - LD A, REG_10SEC ; SELECT 1 SECOND REGISTER + INC B + LD A, B ; SELECT TENS REGISTER OUT (RP5RTC_REG), A - ; CALL DLY32 IN A, (RP5RTC_DAT) AND $0F - rlca - rlca - rlca - rlca ; MOVE TO TOP NIBBLE + RLCA + RLCA + RLCA + RLCA ; MOVE TO TOP NIBBLE OR L ; MERGE IN LOW NIBBLE - LD H, A - ; A = SECONDS AS BCD - LD (RP5RTC_SS), A + LD H, A ; A = VALUE AS BCD RET +; WRITE OUT 2 REGISTERS - 1 BYTE TO 2 NIBBLES +; REGISTER IN B (B+1) +; VALUE IN A +RP5RTC_WRVL: + LD C, A + LD A, B ; SELECT UNIT REGISTER + OUT (RP5RTC_REG), A + + LD A, C ; WRITE C (ONLY LOW NIBBLE WILL BE USED) + OUT (RP5RTC_DAT), A + + INC B + LD A, B ; SELECT TENS REGISTER + OUT (RP5RTC_REG), A + + LD A, C ; SHIFT TOP NIBBLE TO LOW NIBBLE + RRCA + RRCA + RRCA + RRCA + OUT (RP5RTC_DAT), A ; WRITE IT + + RET ; -; WORKING VARIABLES +; REGISTER EXTRACTED VALUES ; -RP5RTC_BCDBUF: ; ALL IN BINARY +RP5RTC_BCDBUF: RP5RTC_YR .DB 20 RP5RTC_MO .DB 01 RP5RTC_DT .DB 01 RP5RTC_HH .DB 00 RP5RTC_MM .DB 00 RP5RTC_SS .DB 00 -;; -RP5RTC_MONTBL: ; DAYS IN MONTH + 1 - .DB 32 ; JANUARY - .DB 29 ; FEBRUARY (NON-LEAP) - .DB 32 ; MARCH - .DB 31 ; APRIL - .DB 32 ; MAY - .DB 31 ; JUNE - .DB 32 ; JULY - .DB 32 ; AUGUST - .DB 31 ; SEPTEMBER - .DB 32 ; OCTOBER - .DB 31 ; NOVEMBER - .DB 32 ; DECEMBER From 9aef5b0977bbc389480e0b822e615abbe1f8882b Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Wed, 28 Oct 2020 10:24:29 +1100 Subject: [PATCH 03/10] RPC501: Added leap year support --- Source/HBIOS/rp5rtc.asm | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Source/HBIOS/rp5rtc.asm b/Source/HBIOS/rp5rtc.asm index fec5fc63..6e8acae6 100644 --- a/Source/HBIOS/rp5rtc.asm +++ b/Source/HBIOS/rp5rtc.asm @@ -8,6 +8,15 @@ RP5RTC_BUFSIZ .EQU 6 ; SIX BYTE BUFFER (YYMMDDHHMMSS) ; RTC DEVICE INITIALIZATION ENTRY ; +; TODO: +; set the day of week register +; read from nvram +; write to nvram +; read block of nvram +; write block of nvram +; set alarm/get alarm???? + + RP5RTC_REG .EQU $B4 RP5RTC_DAT .EQU $B5 @@ -17,7 +26,7 @@ REG_1MIN .EQU $02 REG_10MIN .EQU $03 REG_1HR .EQU $04 REG_10HR .EQU $05 -REG_DAYWEEK .EQU $06 +REG_DAYWEEK .EQU $06 ; NOT USED BY THIS DRIVER REG_1DAY .EQU $07 REG_10DAY .EQU $08 REG_1MNTH .EQU $09 @@ -28,7 +37,9 @@ REG_MODE .EQU $0D REG_TEST .EQU $0E REG_RESET .EQU $0F + REG_12_24 .EQU $0A +REG_LEAPYR .EQU $0B MODE_TIMEST .EQU 0 MODE_ALRMST .EQU 1 @@ -187,6 +198,15 @@ RP5RTC_SETTIM: LD A, (RP5RTC_YR) CALL RP5RTC_WRVL + LD B, MODE_ALRMST + CALL RP5RTC_SETMD + + LD A, (RP5RTC_YR) + CALL BCD2BYTE + AND 3 + LD B, REG_LEAPYR + CALL RP5RTC_WRVL + XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; @@ -301,3 +321,6 @@ RP5RTC_DT .DB 01 RP5RTC_HH .DB 00 RP5RTC_MM .DB 00 RP5RTC_SS .DB 00 + +RP5RTC_DW .DB 00 ; THE DAY OF THE WEEK +RP5RTC_LP .DB 00 ; 1 IF IS LEAP YEAR, OTHERWISE 0 From 0c4f82c8813bc15580a9dd5fe2395cfc444c1e7c Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Wed, 28 Oct 2020 14:29:47 +1100 Subject: [PATCH 04/10] RP5C01: Added support for read/write nvram byte and detect board present --- Source/HBIOS/rp5rtc.asm | 172 +++++++++++++++++++++++++++++++++------- 1 file changed, 142 insertions(+), 30 deletions(-) diff --git a/Source/HBIOS/rp5rtc.asm b/Source/HBIOS/rp5rtc.asm index 6e8acae6..6b67b9e6 100644 --- a/Source/HBIOS/rp5rtc.asm +++ b/Source/HBIOS/rp5rtc.asm @@ -10,12 +10,18 @@ RP5RTC_BUFSIZ .EQU 6 ; SIX BYTE BUFFER (YYMMDDHHMMSS) ; TODO: ; set the day of week register -; read from nvram -; write to nvram ; read block of nvram ; write block of nvram ; set alarm/get alarm???? +;; NOTES FOR USING DRIVER IN Z-DOS +; First load the LDDS datestamper +; A:LDDS +; next prepare and drives with datestamper info: +; eg: a:putds -d=g: -V +; then view date time of files with: +; a:filedate + RP5RTC_REG .EQU $B4 RP5RTC_DAT .EQU $B5 @@ -46,35 +52,46 @@ MODE_ALRMST .EQU 1 MODE_RAM0 .EQU 2 MODE_RAM1 .EQU 3 -MD_TIME .EQU 8 -MD_ALRM .EQU 4 +MD_TIME .EQU 8 +MD_ALRM .EQU 4 RP5RTC_INIT: - LD A,(RTC_DISPACT) ; RTC DISPATCHER ALREADY SET? + LD A, (RTC_DISPACT) ; RTC DISPATCHER ALREADY SET? OR A ; SET FLAGS RET NZ ; IF ALREADY ACTIVE, ABORT -; - CALL NEWLINE ; FORMATTING + + CALL NEWLINE ; FORMATTING PRTS("RP5C01 RTC: $") -; + ; PRINT RTC LATCH PORT ADDRESS + PRTS("IO=0x$") ; LABEL FOR IO ADDRESS + LD A,RP5RTC_REG ; GET IO ADDRESS + CALL PRTHEXBYTE ; PRINT IT + CALL PC_SPACE ; FORMATTING + + ; CHECK PRESENCE STATUS + CALL RP5RTC_DETECT ; HARDWARE DETECTION + JR Z, RP5RTC_INIT1 ; IF ZERO, ALL GOOD + PRTS("NOT PRESENT$") ; NOT ZERO, H/W NOT PRESENT + OR $FF ; SIGNAL FAILURE + RET ; BAIL OUT + +RP5RTC_INIT1: ; ENSURE DEVICE IS RESET AND NOT IN TEST MODE - LD A, REG_TEST ; SELECT TEST REGISTER + LD A, REG_TEST ; SELECT TEST REGISTER OUT (RP5RTC_REG), A CALL DLY16 XOR A - OUT (RP5RTC_DAT), A ; TURN OFF ALL TEST MODE BITS - + OUT (RP5RTC_DAT), A ; TURN OFF ALL TEST MODE BITS LD B, MODE_ALRMST CALL RP5RTC_SETMD - LD A, REG_12_24 ; SET TO 24 HOUR CLOCK + LD A, REG_12_24 ; SET TO 24 HOUR CLOCK OUT (RP5RTC_REG), A LD A, 1 OUT (RP5RTC_DAT), A - CALL RP5RTC_RDTIM ; DISPLAY CURRENT TIME @@ -84,7 +101,36 @@ RP5RTC_INIT: LD BC, RP5RTC_DISPATCH CALL RTC_SETDISP ; - XOR A ; SIGNAL SUCCESS + XOR A ; SIGNAL SUCCESS + RET +; +; DETECT RTC HARDWARE PRESENCE +; +RP5RTC_DETECT: + LD C, 0 ; NVRAM INDEX 0 + CALL RP5RTC_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 RP5RTC_SETBYT ; WRITE IT + LD C, 0 ; NVRAM INDEX 0 + CALL RP5RTC_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, RP5RTC_DETECT1 ; IF MATCH, GO AHEAD + LD A, $FF ; ELSE STATUS IS ERROR + +RP5RTC_DETECT1: + PUSH AF ; SAVE STATUS + LD A, L ; GET SAVED VALUE + LD C, 0 ; NVRAM INDEX 0 + CALL RP5RTC_SETBYT ; SAVE IT + POP AF ; RECOVER STATUS + OR A ; SET FLAGS RET ; ; RTC DEVICE FUNCTION DISPATCH ENTRY @@ -92,40 +138,108 @@ RP5RTC_INIT: ; B: FUNCTION (IN) ; RP5RTC_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - JP Z,RP5RTC_GETTIM ; GET TIME + LD A,B ; GET REQUESTED FUNCTION + AND $0F ; ISOLATE SUB-FUNCTION + JP Z,RP5RTC_GETTIM ; GET TIME DEC A - JP Z,RP5RTC_SETTIM ; SET TIME + JP Z,RP5RTC_SETTIM ; SET TIME DEC A - JP Z,RP5RTC_GETBYT ; GET NVRAM BYTE VALUE + JP Z,RP5RTC_GETBYT ; GET NVRAM BYTE VALUE DEC A - JP Z,RP5RTC_SETBYT ; SET NVRAM BYTE VALUE + JP Z,RP5RTC_SETBYT ; SET NVRAM BYTE VALUE DEC A - JP Z,RP5RTC_GETBLK ; GET NVRAM DATA BLOCK VALUES + JP Z,RP5RTC_GETBLK ; GET NVRAM DATA BLOCK VALUES DEC A - JP Z,RP5RTC_SETBLK ; SET NVRAM DATA BLOCK VALUES + JP Z,RP5RTC_SETBLK ; SET NVRAM DATA BLOCK VALUES DEC A - JP Z,RP5RTC_GETALM ; GET ALARM + JP Z,RP5RTC_GETALM ; GET ALARM DEC A - JP Z,RP5RTC_SETALM ; SET ALARM + JP Z,RP5RTC_SETALM ; SET ALARM DEC A - JP Z,RP5RTC_DEVICE ; REPORT RTC DEVICE INFO + JP Z,RP5RTC_DEVICE ; REPORT RTC DEVICE INFO CALL SYSCHK - LD A,ERR_NOFUNC + LD A, ERR_NOFUNC OR A RET ; -; NVRAM FUNCTIONS ARE NOT AVAILABLE IN SIMULATOR +; RTC GET NVRAM BYTE +; C: INDEX +; E: VALUE (OUTPUT) +; A:0 IF OK, ERR_RANGE IF OUT OF RANGE ; RP5RTC_GETBYT: + LD A, C + CP $0D + JR NC, RP5RTC_BADIDX + + LD B, MODE_RAM0 + CALL RP5RTC_SETMD + LD A, C ; SELECT NVRAM INDEX + OUT (RP5RTC_REG), A + IN A, (RP5RTC_DAT) + AND $0F ; RETRIEVE UNIT NIBBLE + LD E, A + + LD B, MODE_RAM1 + CALL RP5RTC_SETMD + LD A, C ; SELECT NVRAM INDEX + OUT (RP5RTC_REG), A + IN A, (RP5RTC_DAT) + AND $0F ; RETRIEVE UNIT NIBBLE + RLCA + RLCA + RLCA + RLCA + OR E + LD E, A + + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN + +RP5RTC_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 +; RP5RTC_SETBYT: + LD A, C + CP $0D + JR NC, RP5RTC_BADIDX + + LD B, MODE_RAM0 + CALL RP5RTC_SETMD + LD A, C ; SELECT NVRAM INDEX + OUT (RP5RTC_REG), A + LD A, E + AND $0F + OUT (RP5RTC_DAT), A + + LD B, MODE_RAM1 + CALL RP5RTC_SETMD + LD A, C ; SELECT NVRAM INDEX + OUT (RP5RTC_REG), A + LD A, E + AND $F0 + RRCA + RRCA + RRCA + RRCA + OUT (RP5RTC_DAT), A + + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN + RP5RTC_GETBLK: RP5RTC_SETBLK: RP5RTC_GETALM: RP5RTC_SETALM: + LD A, ERR_NOTIMPL CALL SYSCHK - LD A,ERR_NOTIMPL OR A RET ; @@ -322,5 +436,3 @@ RP5RTC_HH .DB 00 RP5RTC_MM .DB 00 RP5RTC_SS .DB 00 -RP5RTC_DW .DB 00 ; THE DAY OF THE WEEK -RP5RTC_LP .DB 00 ; 1 IF IS LEAP YEAR, OTHERWISE 0 From 83529a7f769882123bb076b8074d555ab0e80731 Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Tue, 10 Nov 2020 18:02:08 +1100 Subject: [PATCH 05/10] RP5RTC: Fixed issue with clock not enabled --- Source/HBIOS/rp5rtc.asm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/HBIOS/rp5rtc.asm b/Source/HBIOS/rp5rtc.asm index 6b67b9e6..4fe0a677 100644 --- a/Source/HBIOS/rp5rtc.asm +++ b/Source/HBIOS/rp5rtc.asm @@ -87,6 +87,8 @@ RP5RTC_INIT1: LD B, MODE_ALRMST CALL RP5RTC_SETMD + CALL RP5RTC_ENTIME + LD A, REG_12_24 ; SET TO 24 HOUR CLOCK OUT (RP5RTC_REG), A LD A, 1 @@ -321,6 +323,8 @@ RP5RTC_SETTIM: LD B, REG_LEAPYR CALL RP5RTC_WRVL + CALL RP5RTC_ENTIME + XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; @@ -378,6 +382,10 @@ RP5RTC_SETMD: OUT (RP5RTC_DAT), A ; ASSIGN MODE RET +; ENABLE THE TIME COUNTER +RP5RTC_ENTIME: + LD B, MD_TIME + JP RP5RTC_SETMD ; READ OUT 2 REGISTERS - 2 NIBBLES TO 1 BYTE ; REGISTER IN B From a9192923869f6d8c9ae0806b61d3d6098f78f534 Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Thu, 5 Nov 2020 15:46:43 +1100 Subject: [PATCH 06/10] Added msx compatible keyboard driver for use in MSX --- Source/HBIOS/cfg_dyno.asm | 2 + Source/HBIOS/cfg_ezz80.asm | 2 + Source/HBIOS/cfg_master.asm | 3 + Source/HBIOS/cfg_mk4.asm | 3 + Source/HBIOS/cfg_n8.asm | 3 + Source/HBIOS/cfg_rcz180.asm | 2 + Source/HBIOS/cfg_rcz280.asm | 2 + Source/HBIOS/cfg_rcz80.asm | 3 + Source/HBIOS/cfg_sbc.asm | 3 + Source/HBIOS/cfg_scz180.asm | 2 + Source/HBIOS/cfg_zeta.asm | 2 + Source/HBIOS/cfg_zeta2.asm | 2 + Source/HBIOS/hbios.asm | 9 + Source/HBIOS/msxkeyb.asm | 1168 +++++++++++++++++++++++++++++++++++ Source/HBIOS/tms.asm | 17 + 15 files changed, 1223 insertions(+) create mode 100644 Source/HBIOS/msxkeyb.asm diff --git a/Source/HBIOS/cfg_dyno.asm b/Source/HBIOS/cfg_dyno.asm index e5f3174d..6f19b7e7 100644 --- a/Source/HBIOS/cfg_dyno.asm +++ b/Source/HBIOS/cfg_dyno.asm @@ -186,3 +186,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_RCZ180 ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index 0cfa36dc..79ab1aac 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -220,3 +220,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index 0618dadb..7de68192 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -104,6 +104,7 @@ PPKTRACE .EQU 1 ; PPK DRIVER TRACE LEVEL (0=NO,1=ERRORS,2=ALL) KBDTRACE .EQU 1 ; KBD DRIVER TRACE LEVEL (0=NO,1=ERRORS,2=ALL) PPKKBLOUT .EQU KBD_US ; PPK KEYBOARD LANGUAGE: KBD_[US|DE] KBDKBLOUT .EQU KBD_US ; KBD KEYBOARD LANGUAGE: KBD_[US|DE] +MKYKBLOUT .EQU KBD_US ; KBD KEYBOARD LANGUAGE: KBD_[US|DE] ; DSRTCENABLE .EQU FALSE ; DSRTC: ENABLE DS-1302 CLOCK DRIVER (DSRTC.ASM) DSRTCMODE .EQU DSRTCMODE_STD ; DSRTC: OPERATING MODE: DSRTC_[STD|MFPIC] @@ -288,3 +289,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index 7bfb167c..d4e51cfb 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -79,6 +79,7 @@ PPKTRACE .EQU 1 ; PPK DRIVER TRACE LEVEL (0=NO,1=ERRORS,2=ALL) KBDTRACE .EQU 1 ; KBD DRIVER TRACE LEVEL (0=NO,1=ERRORS,2=ALL) PPKKBLOUT .EQU KBD_US ; PPK KEYBOARD LANGUAGE: KBD_[US|DE] KBDKBLOUT .EQU KBD_US ; KBD KEYBOARD LANGUAGE: KBD_[US|DE] +MKYKBLOUT .EQU KBD_US ; KBD KEYBOARD LANGUAGE: KBD_[US|DE] ; DSRTCENABLE .EQU TRUE ; DSRTC: ENABLE DS-1302 CLOCK DRIVER (DSRTC.ASM) DSRTCMODE .EQU DSRTCMODE_STD ; DSRTC: OPERATING MODE: DSRTC_[STD|MFPIC] @@ -220,3 +221,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_SCG ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index 3e70cf78..4b620372 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -82,6 +82,7 @@ PPKTRACE .EQU 1 ; PPK DRIVER TRACE LEVEL (0=NO,1=ERRORS,2=ALL) KBDTRACE .EQU 1 ; KBD DRIVER TRACE LEVEL (0=NO,1=ERRORS,2=ALL) PPKKBLOUT .EQU KBD_US ; PPK KEYBOARD LANGUAGE: KBD_[US|DE] KBDKBLOUT .EQU KBD_US ; KBD KEYBOARD LANGUAGE: KBD_[US|DE] +MKYKBLOUT .EQU KBD_US ; KBD KEYBOARD LANGUAGE: KBD_[US|DE] ; DSRTCENABLE .EQU TRUE ; DSRTC: ENABLE DS-1302 CLOCK DRIVER (DSRTC.ASM) DSRTCMODE .EQU DSRTCMODE_STD ; DSRTC: OPERATING MODE: DSRTC_[STD|MFPIC] @@ -220,3 +221,5 @@ AY38910ENABLE .EQU TRUE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_N8 ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index 5715c783..873d2ea6 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -233,3 +233,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_RCZ180 ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index 653e282a..8d0bb0e5 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -249,3 +249,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU 7372800 / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index e529f743..7cf06c0f 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -74,6 +74,7 @@ BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI] ANSITRACE .EQU 1 ; ANSI DRIVER TRACE LEVEL (0=NO,1=ERRORS,2=ALL) +MKYKBLOUT .EQU KBD_US ; KBD KEYBOARD LANGUAGE: KBD_[US|DE] ; DSRTCENABLE .EQU TRUE ; DSRTC: ENABLE DS-1302 CLOCK DRIVER (DSRTC.ASM) DSRTCMODE .EQU DSRTCMODE_STD ; DSRTC: OPERATING MODE: DSRTC_[STD|MFPIC] @@ -238,3 +239,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index de34c10f..5f57e0b4 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -74,6 +74,7 @@ PPKTRACE .EQU 1 ; PPK DRIVER TRACE LEVEL (0=NO,1=ERRORS,2=ALL) KBDTRACE .EQU 1 ; KBD DRIVER TRACE LEVEL (0=NO,1=ERRORS,2=ALL) PPKKBLOUT .EQU KBD_US ; PPK KEYBOARD LANGUAGE: KBD_[US|DE] KBDKBLOUT .EQU KBD_US ; KBD KEYBOARD LANGUAGE: KBD_[US|DE] +MKYKBLOUT .EQU KBD_US ; KBD KEYBOARD LANGUAGE: KBD_[US|DE] ; DSRTCENABLE .EQU TRUE ; DSRTC: ENABLE DS-1302 CLOCK DRIVER (DSRTC.ASM) DSRTCMODE .EQU DSRTCMODE_STD ; DSRTC: OPERATING MODE: DSRTC_[STD|MFPIC] @@ -221,3 +222,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_SCG ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index 74976cdf..883750bf 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -228,3 +228,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_RCZ180 ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index e5eff0d2..9fcc1fe3 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -163,3 +163,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index cec7ef24..4cdd909f 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -174,3 +174,5 @@ AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) + +MSKENABLE .EQU FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER) diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index b4e0c6c5..bcca366c 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -4668,6 +4668,15 @@ SIZ_PPK .EQU $ - ORG_PPK .ECHO " bytes.\n" #ENDIF ; +#IF (MSKENABLE) +ORG_MSXKEYB .EQU $ + #INCLUDE "msxkeyb.asm" +SIZ_MSXKEYB .EQU $ - ORG_MSXKEYB + .ECHO "MSXKEYB occupies " + .ECHO SIZ_MSXKEYB + .ECHO " bytes.\n" +#ENDIF +; #IF (PRPENABLE) ORG_PRP .EQU $ #INCLUDE "prp.asm" diff --git a/Source/HBIOS/msxkeyb.asm b/Source/HBIOS/msxkeyb.asm new file mode 100644 index 00000000..8bf0f892 --- /dev/null +++ b/Source/HBIOS/msxkeyb.asm @@ -0,0 +1,1168 @@ +;====================================================================== +; MSX 8255 PPI KEYBOARD COMPATIBLE DRIVER +; +; CREATED BY: DEAN NETHERTON +; KBD.ASM DRIVER USED AS TEMPLATE +; +; +;====================================================================== +; USAGE: +; THIS DRIVER IS CAN BE ACTIVED WITHIN THE TMS VIDEO DRIVER +; ADD THE OPTION TO YOUR BUILD CONFIGURATION TO ACTIVATE THE KEYBOARD +; DRIVER: +; MSKENABLE .SET TRUE +; +;====================================================================== +; +; TODO: +; IMPLEMENT MULTIBYTE SCAN CODES (ARROW KEYS, ETC) +; +;====================================================================== +; DRIVER - CONSTANTS +;====================================================================== +; +MKY_REGA .EQU $A8 +MKY_REGB .EQU $A9 +MKY_REGC .EQU $AA +MKY_REGCMD .EQU $AB + +PPICMD_CLOW_IN .EQU 1 +PPICMD_CLOW_OUT .EQU 0 +PPICMD_B_IN .EQU 2 +PPICMD_B_OUT .EQU 0 +PPICMD_GB_MODE_0 .EQU 0 +PPICMD_GB_MODE_1 .EQU 4 +PPICMD_CHIGH_IN .EQU 8 +PPICMD_CHIGH_OUT .EQU 0 +PPICMD_A_IN .EQU 16 +PPICMD_A_OUT .EQU 0 +PPICMD_GA_MODE_0 .EQU 0 +PPICMD_GA_MODE_1 .EQU 32 +PPICMD_GA_MODE_2 .EQU 64 +PPICMD_COMMAND .EQU 128 + +; COUNT FOR PERIOD TO START REPEATING CHARACTERS +KEY_REPEAT_INIT: .EQU 20 + +; COUNT FOR PERIOD BETWEEN AUTO REPEATING CHARACTERS +KEY_REPEAT_PERIOD: .EQU 5 + +; COUNT FOR INTERRUPT HANDLER TO TRIGGER KEYBOARD SCANNER (EG: SCAN KEYBOARD ONLY EVERY 3RD INTERRUPT (3/60)) +SCAN_INT_PERIOD: .EQU 3 + +; NUMBER OF ROWS SUPPORTED BY THE KEYBOARD +MATRIX_ROW_COUNT: .EQU 9 + +; ASSEMBLER SEEMS TO HAVE WEIRD PROBLEM WITH "'" +SINGLE_QUOTE .EQU 39 + +; SPECIAL MADE UP VALUE TO MAP FOR CAPS LOCK +CAPS_CODE: .EQU $D8 + +; TIMING CONSTANTS +; +MKY_WAITTO .EQU 0 ; 0 IS MAX WAIT (256) +; +; STATUS BITS (FOR MKY_STATUS) +; +MKY_EXT .EQU 01H ; BIT 0, EXTENDED SCANCODE ACTIVE +MKY_BREAK .EQU 02H ; BIT 1, THIS IS A KEY UP (BREAK) EVENT +MKY_KEYRDY .EQU 80H ; BIT 7, INDICATES A DECODED KEYCODE IS READY +; +; STATE BITS (FOR MKY_STATE, MKY_LSTATE, MKY_RSTATE) +; +MKY_SHIFT .EQU 01H ; BIT 0, SHIFT ACTIVE (PRESSED) +MKY_CTRL .EQU 02H ; BIT 1, CONTROL ACTIVE (PRESSED) +MKY_ALT .EQU 04H ; BIT 2, ALT ACTIVE (PRESSED) +MKY_WIN .EQU 08H ; BIT 3, WIN ACTIVE (PRESSED) +MKY_SCRLCK .EQU 10H ; BIT 4, CAPS LOCK ACTIVE (TOGGLED ON) +MKY_NUMLCK .EQU 20H ; BIT 5, NUM LOCK ACTIVE (TOGGLED ON) +MKY_CAPSLCK .EQU 40H ; BIT 6, SCROLL LOCK ACTIVE (TOGGLED ON) +MKY_NUMPAD .EQU 80H ; BIT 7, NUM PAD KEY (KEY PRESSED IS ON NUM PAD) +; +MKY_DEFRPT .EQU $40 ; DEFAULT REPEAT RATE (.5 SEC DELAY, 30CPS) +MKY_DEFSTATE .EQU MKY_NUMLCK ; DEFAULT STATE (NUM LOCK ON) + +; --------------.----------------------- +; SCAN CODE TABL.ES + +S_A .EQU $1C +S_B .EQU $32 +S_C .EQU $21 +S_D .EQU $23 +S_E .EQU $24 +S_F .EQU $2B +S_G .EQU $34 +S_H .EQU $33 +S_I .EQU $43 +S_J .EQU $3B +S_K .EQU $42 +S_L .EQU $4B +S_M .EQU $3A +S_N .EQU $31 +S_O .EQU $44 +S_P .EQU $4D +S_Q .EQU $15 +S_R .EQU $2D +S_S .EQU $1B +S_T .EQU $2C +S_U .EQU $3C +S_V .EQU $2A +S_W .EQU $1D +S_X .EQU $22 +S_Y .EQU $35 +S_Z .EQU $1A +S_0 .EQU $45 +S_1 .EQU $16 +S_2 .EQU $1E +S_3 .EQU $26 +S_4 .EQU $25 +S_5 .EQU $2E +S_6 .EQU $36 +S_7 .EQU $3D +S_8 .EQU $3E +S_9 .EQU $46 +S_SEMICOLON .EQU $4C +S_RBRACKET .EQU $5B +S_LBRACKET .EQU $54 +S_BSLASH .EQU $5D +S_EQUALS .EQU $55 +S_MINUS .EQU $4E +S_SLASH .EQU $4A +S_PERIOD .EQU $49 +S_COMMA .EQU $41 +S_TILDA .EQU $0E +S_QUOTE .EQU $52 +S_SHIFT .EQU $12 +S_CTRL .EQU $14 +S_CAPSLOCK .EQU $58 +S_DEAD .EQU $00 +S_GRAPH .EQU $00 +S_CODE .EQU $00 ; perhaps can be mapped to RIGHT ALT +S_F1 .EQU $05 +S_F2 .EQU $06 +S_F3 .EQU $04 +S_F4 .EQU $0C +S_F5 .EQU $03 +S_ESC .EQU $76 +S_TAB .EQU $0D +S_STOP .EQU $00 ; MAKE -> E0 69, BREAK -> E0 F0 69 +S_BACKSPACE .EQU $66 +S_SELECT .EQU $00 +S_RETURN .EQU $5A + +S_RIGHT .EQU $00 ; E0 74 --- E0 F0 74 +S_DOWN .EQU $00 ; E0 72 --- E0 F0 72 +S_UP .EQU $00 ; E0 75 --- E0 F0 75 +S_LEFT .EQU $00 ; E0 6B --- E0 F0 6B +S_DELETE .EQU $00 ; E0 71 --- E0 F0 71 +S_INSERT .EQU $00 ; E0 70 --- E0 F0 70 +S_HOME .EQU $00 ; E0 6C --- E0 F0 6C +S_SPACE .EQU $29 + +SCANCODE_TBL: + .DB S_7, S_6, S_5, S_4, S_3, S_2, S_1, S_0 ; 00 + .DB S_SEMICOLON, S_RBRACKET, S_LBRACKET, S_BSLASH, S_EQUALS, S_MINUS, S_9, S_8 ; 01 + .DB S_B, S_A, S_DEAD, S_SLASH, S_PERIOD, S_COMMA, S_TILDA, S_QUOTE ; 02 + .DB S_J, S_I, S_H, S_G, S_F, S_E, S_D, S_C ; 03 + .DB S_R, S_Q, S_P, S_O, S_N, S_M, S_L, S_K ; 04 + .DB S_Z, S_Y, S_X, S_W, S_V, S_U, S_T, S_S ; 05 + .DB S_F3, S_F2, S_F1, S_CODE, S_CAPSLOCK, S_GRAPH, S_CTRL, S_SHIFT ; 06 + .DB S_RETURN, S_SELECT, S_BACKSPACE, S_STOP, S_TAB, S_ESC, S_F5, S_F4 ; 07 + .DB S_RIGHT, S_DOWN, S_UP, S_LEFT, S_DELETE, S_INSERT, S_HOME, S_SPACE ; 08 + +;__________________________________________________________________________________________________ +; KEYBOARD INITIALIZATION +;__________________________________________________________________________________________________ +; + +MKY_INIT: + CALL NEWLINE ; FORMATTING + PRTS("MSXKYB: IO=0x$") + LD A, MKY_REGA + CALL PRTHEXBYTE + CALL PC_SPACE ; FORMATTING + +#IF (MKYKBLOUT == KBD_US) + PRTS("US LAYOUT$") +#ELSE +#IF (MKYKBLOUT == KBD_DE) + PRTS("GERMAN LAYOUT$") +#ELSE + FAIL !!! + UKNOWN KEYBOARD TYPE +#ENDIF +#ENDIF + + ; CONFIGURE 8255 PPI PORTS + ; A - INPUT (NOT USED) + ; B - INPUT (COLUMN LINES) + ; C - OUTPUT (ROW LINE SELECTION) + + LD A, PPICMD_COMMAND | PPICMD_GA_MODE_0 | PPICMD_GB_MODE_0 | PPICMD_A_IN | PPICMD_B_IN | PPICMD_CLOW_OUT | PPICMD_CHIGH_OUT + OUT (MKY_REGCMD), A + + LD A, 64 ; CAPS OFF + OUT (MKY_REGC), A + + RET +; +;__________________________________________________________________________________________________ +; KEYBOARD FLUSH +;__________________________________________________________________________________________________ +; +MKY_FLUSH: + XOR A ; A = 0 + LD (MKY_STATUS),A ; CLEAR STATUS + RET +; +;__________________________________________________________________________________________________ +; KEYBOARD STATUS +;__________________________________________________________________________________________________ +; +MKY_STAT: + CALL MKY_DECODE ; CHECK THE KEYBOARD + JP Z,CIO_IDLE ; RET VIA IDLE PROCESSING IF NO KEY + RET +; +;__________________________________________________________________________________________________ +; KEYBOARD READ +; +; RETURNS ASCII VALUE IN E. SEE END OF FILE FOR VALUES RETURNED FOR SPECIAL KEYS +; LIKE PGUP, ARROWS, FUNCTION KEYS, ETC. +;__________________________________________________________________________________________________ +; +MKY_READ: + CALL MKY_STAT ; KEY READY? +; + JR Z, MKY_READ ; NOT READY, KEEP TRYING + LD A,(MKY_STATE) ; GET STATE + AND $01 ; ISOLATE EXTENDED SCANCODE BIT + RRCA ; ROTATE IT TO HIGH ORDER BIT + LD E,A ; SAVE IT IN E FOR NOW + LD A,(MKY_SCANCODE) ; GET SCANCODE + OR E ; COMBINE WITH EXTENDED BIT + LD C,A ; STORE IT IN C FOR RETURN + LD A,(MKY_KEYCODE) ; GET KEYCODE + LD E,A ; SAVE IT IN E + LD A,(MKY_STATE) ; GET STATE FLAGS + LD D,A ; SAVE THEM IN D + XOR A ; SIGNAL SUCCESS + LD (MKY_STATUS),A ; CLEAR STATUS TO INDICATE BYTE RECEIVED + RET +; +;__________________________________________________________________________________________________ +; RETRIEVE THE NEXT SCAN BYTES AVAILABLE +; +; RETURNS +; ; SUCUESS/FAILURE IN A +; ; NUMBER OF BYTES RETURNED IN B (ZERO IF NO SCAN CODES AVAILABLE) +; ; SCAN CODE BYTES IN D, E, H, L, C +; +;__________________________________________________________________________________________________ +MKY_RDSCAN: + LD A, (MKY_SCANBUFFLEN) + LD B, A + LD A, (MKY_SCANBUFF) + LD D, A + LD A, (MKY_SCANBUFF+1) + LD E, A + LD A, (MKY_SCANBUFF+2) + LD H, A + LD A, (MKY_SCANBUFF+3) + LD L, A + LD A, (MKY_SCANBUFF+4) + LD C, A + + XOR A + LD (MKY_SCANBUFFLEN), A + RET +; +;__________________________________________________________________________________________________ +; HARDWARE INTERFACE +; +; +; KEYBOARD INPUT STATUS +; A=0, Z SET FOR NOTHING PENDING, OTHERWISE DATA PENDING +; +MKY_IST: + LD A, (MKY_SCANBUFFLEN) + OR A + RET +;__________________________________________________________________________________________________ +; +; GET A RAW DATA BYTE FROM KEYBOARD INTERFACE INTO A WITH TIMEOUT +; +MKY_GETDATA: + LD B,MKY_WAITTO ; SETUP TO LOOP +MKY_GETDATA0: + CALL MKY_IST ; GET INPUT REGISTER STATUS + JR NZ,MKY_GETDATA1 ; BYTE PENDING, GO GET IT + CALL DELAY ; WAIT A BIT + DJNZ MKY_GETDATA0 ; LOOP UNTIL COUNTER EXHAUSTED + XOR A ; NO DATA, RETURN ZERO + RET +MKY_GETDATA1: + CALL MKY_READBYT + OR A ; SET FLAGS + RET +;__________________________________________________________________________________________________ +; +; GET A RAW DATA BYTE FROM KEYBOARD INTERFACE INTO A WITH NOTIMEOUT +; +MKY_GETDATAX: + CALL MKY_IST ; GET INPUT REGISTER STATUS + RET Z ; NOTHING THERE, DONE + JR MKY_GETDATA1 ; GO GET IT + +;__________________________________________________________________________________________________ +; UPDATE KEYBOARD LEDS BASED ON CURRENT TOGGLE FLAGS +;__________________________________________________________________________________________________ +; +MKY_SETLEDS: + LD A,(MKY_STATE) ; LOAD THE STATE FLAGS + AND MKY_CAPSLCK ; CHECK CAPS LOCK + JP Z, MKY_LEDCAPSOFF + JP MKY_LEDCAPSON + +;__________________________________________________________________________________________________ +; DECODING ENGINE +;__________________________________________________________________________________________________ +MKY_DECODE: +; +; RUN THE DECODING ENGINE UNTIL EITHER: 1) NO MORE SCANCODES ARE AVAILABLE +; FROM THE KEYBOARD, OR 2) A DECODED KEY VALUE IS AVAILABLE +; +; RETURNS A=0 AND Z SET IF NO KEYCODE READY, OTHERWISE A DECODED KEY VALUE IS AVAILABLE. +; THE DECODED KEY VALUE AND KEY STATE IS STORED IN MKY_KEYCODE AND MKY_STATE. +; +; MKY_STATUS IS NOT CLEARED AT START. IT IS THE CALLER'S RESPONSIBILITY +; TO CLEAR MKY_STATUS WHEN IT HAS RETRIEVED A PENDING VALUE. IF DECODE IS CALLED +; WITH A KEYCODE STILL PENDING, IT WILL JUST RETURN WITHOUT DOING ANYTHING. +; +; Step 0: Check keycode buffer +; if status[keyrdy] +; return +; +; Step 1: Get scancode +; if no scancode ready +; return +; read scancode +; +; Step 2: Detect and handle special keycodes +; if scancode == $AA +; *** handle hot insert somehow *** +; +; Step 3: Detect and handle scancode prefixes +; if scancode == $E0 +; set status[extended] +; goto Step 1 +; +; if scancode == $E1 +; *** handle pause key somehow *** +; +; Step 4: Detect and flag break event +; *** scancode set #1 variation *** +; set status[break] = high bit of scancode +; clear high order bit +; continue to Step 5 +; *** scancode set #2 variation *** +; if scancode == $F0 +; set status[break] +; goto Step 1 +; +; Step 5: Map scancode to keycode +; if status[extended] +; apply extended-map[scancode] -> keycode +; else if state[shifted] +; apply shifted-map[scancode] -> keycode +; else +; apply normal-map[scancode] -> keycode +; +; Step 6: Handle modifier keys +; if keycode is modifier (shift, ctrl, alt, win) +; set (l/r)state[] = not status[break] +; clear modifier bits in state +; set state = (lstate OR rstate OR state) +; goto New Key +; +; Step 7: Complete procesing of key break events +; if status[break] +; goto New Key +; +; Step 8: Handle toggle keys +; if keycode is toggle (capslock, numlock, scrolllock) +; invert (XOR) state[] +; update keyboard LED's +; goto New Key +; +; Step 9: Adjust keycode for control modifier +; if state[ctrl] +; if keycode is 'a'-'z' +; subtract 20 (clear bit 5) from keycode +; if keycode is '@'-'_' +; subtract 40 (clear bit 6) from keycode +; +; Step 10: Adjust keycode for caps lock +; if state[capslock] +; if keycode is 'a'-'z' OR 'A'-'Z' +; toggle (XOR) bit 5 of keycode +; +; Step 11: Handle num pad keys +; clear state[numpad] +; if keycode is numpad +; set state[numpad] +; if state[numlock] +; toggle (XOR) bit 4 of keycode +; apply numpad-map[keycode] -> keycode +; +; Step 12: Detect unknown/invalid keycodes +; if keycode == $FF +; goto New Key +; +; Step 13: Done +; set status[keyrdy] +; return +; +; New Key: +; clear status +; goto Step 1 +; +MKY_DEC0: ; CHECK KEYCODE BUFFER + LD A,(MKY_STATUS) ; GET CURRENT STATUS + AND MKY_KEYRDY ; ISOLATE KEY READY FLAG + RET NZ ; ABORT IF KEY IS ALREADY PENDING + +MKY_DEC1: ; PROCESS NEXT SCANCODE + CALL MKY_GETDATAX ; GET THE SCANCODE + RET Z ; NO KEY READY, RETURN WITH A=0, Z SET + LD (MKY_SCANCODE),A ; SAVE SCANCODE + +MKY_DEC2: ; DETECT AND HANDLE SPECIAL KEYCODES + LD A,(MKY_SCANCODE) ; GET THE CURRENT SCANCODE + CP $AA ; KEYBOARD INSERTION? + JR NZ,MKY_DEC3 ; NOPE, BYPASS + CALL MKY_SETLEDS ; SET LEDS + JP MKY_DECNEW ; RESTART THE ENGINE + +MKY_DEC3: ; DETECT AND HANDLE SCANCODE PREFIXES + LD A,(MKY_SCANCODE) ; GET THE CURRENT SCANCODE + +MKY_DEC3A: ; HANDLE SCANCODE PREFIX $E0 (EXTENDED SCANCODE FOLLOWS) + CP $E0 ; EXTENDED KEY PREFIX $E0? + JR NZ,MKY_DEC3B ; NOPE MOVE ON + LD A,(MKY_STATUS) ; GET STATUS + OR MKY_EXT ; SET EXTENDED BIT + LD (MKY_STATUS),A ; SAVE STATUS + JR MKY_DEC1 ; LOOP TO DO NEXT SCANCODE + +MKY_DEC3B: ; HANDLE SCANCODE PREFIX $E1 (PAUSE KEY) + CP $E1 ; EXTENDED KEY PREFIX $E1 + JR NZ,MKY_DEC4 ; NOPE MOVE ON + LD A,$EE ; MAP TO KEYCODE $EE + LD (MKY_KEYCODE),A ; SAVE IT + ; SWALLOW NEXT 7 SCANCODES + LD B,7 ; LOOP 5 TIMES +MKY_DEC3B1: + PUSH BC + CALL MKY_GETDATA ; RETRIEVE NEXT SCANCODE + POP BC + DJNZ MKY_DEC3B1 ; LOOP AS NEEDED + JP MKY_DEC6 ; RESUME AFTER MAPPING + +MKY_DEC4: ; DETECT AND FLAG BREAK EVENT + CP $F0 ; BREAK (KEY UP) PREFIX? + JR NZ,MKY_DEC5 ; NOPE MOVE ON + LD A,(MKY_STATUS) ; GET STATUS + OR MKY_BREAK ; SET BREAK BIT + LD (MKY_STATUS),A ; SAVE STATUS + JR MKY_DEC1 ; LOOP TO DO NEXT SCANCODE + +MKY_DEC5: ; MAP SCANCODE TO KEYCODE + LD A,(MKY_STATUS) ; GET STATUS + AND MKY_EXT ; EXTENDED BIT SET? + JR Z,MKY_DEC5C ; NOPE, MOVE ON + + ; PERFORM EXTENDED KEY MAPPING + LD A,(MKY_SCANCODE) ; GET SCANCODE + LD E,A ; STASH IT IN E + LD HL,MKY_MAPEXT ; POINT TO START OF EXT MAP TABLE +MKY_DEC5A: + LD A,(HL) ; GET FIRST BYTE OF PAIR + CP $00 ; END OF TABLE? + JP Z,MKY_DECNEW ; UNKNOWN OR BOGUS, START OVER + INC HL ; INC HL FOR FUTURE + CP E ; DOES MATCH BYTE EQUAL SCANCODE? + JR Z,MKY_DEC5B ; YES! JUMP OUT + INC HL ; BUMP TO START OF NEXT PAIR + JR MKY_DEC5A ; LOOP TO CHECK NEXT TABLE ENTRY +MKY_DEC5B: + LD A,(HL) ; GET THE KEYCODE VIA MAPPING TABLE + LD (MKY_KEYCODE),A ; SAVE IT + JR MKY_DEC6 + +MKY_DEC5C: ; PERFORM REGULAR KEY (NOT EXTENDED) KEY MAPPING + LD A,(MKY_SCANCODE) ; GET THE SCANCODE + CP MKY_MAPSIZ ; COMPARE TO SIZE OF TABLE + JR NC,MKY_DEC6 ; PAST END, SKIP OVER LOOKUP + + ; SETUP POINTER TO MAPPING TABLE BASED ON SHIFTED OR UNSHIFTED STATE + LD A,(MKY_STATE) ; GET STATE + AND MKY_SHIFT ; SHIFT ACTIVE? + LD HL,MKY_MAPSTD ; LOAD ADDRESS OF NON-SHIFTED MAPPING TABLE + JR Z,MKY_DEC5D ; NON-SHIFTED, MOVE ON + LD HL,MKY_MAPSHIFT ; LOAD ADDRESS OF SHIFTED MAPPING TABLE +MKY_DEC5D: + LD A,(MKY_SCANCODE) ; GET THE SCANCODE + LD E,A ; SCANCODE TO E FOR TABLE OFFSET + LD D,0 ; D -> 0 + ADD HL,DE ; COMMIT THE TABLE OFFSET TO HL + LD A,(HL) ; GET THE KEYCODE VIA MAPPING TABLE + LD (MKY_KEYCODE),A ; SAVE IT + +MKY_DEC6: ; HANDLE MODIFIER KEYS + LD A,(MKY_KEYCODE) ; MAKE SURE WE HAVE KEYCODE + CP $B8 ; END OF MODIFIER KEYS + JR NC,MKY_DEC7 ; BYPASS MODIFIER KEY CHECKING + CP $B0 ; START OF MODIFIER KEYS + JR C,MKY_DEC7 ; BYPASS MODIFIER KEY CHECKING + + LD B,4 ; LOOP COUNTER TO LOOP THRU 4 MODIFIER BITS + LD E,$80 ; SETUP E TO ROATE THROUGH MODIFIER STATE BITS + SUB $B0 - 1 ; SETUP A TO DECREMENT THROUGH MODIFIER VALUES + +MKY_DEC6A: + RLC E ; SHIFT TO NEXT MODIFIER STATE BIT + DEC A ; L-MODIFIER? + JR Z,MKY_DEC6B ; YES, HANDLE L-MODIFIER MAKE/BREAK + DEC A ; R-MODIFIER? + JR Z,MKY_DEC6C ; YES, HANDLE R-MODIFIER MAKE/BREAK + DJNZ MKY_DEC6A ; LOOP THRU 4 MODIFIER BITS + JR MKY_DEC7 ; FAILSAFE, SHOULD NEVER GET HERE! + +MKY_DEC6B: ; LEFT STATE KEY MAKE/BREAK (STATE BIT TO SET/CLEAR IN E) + LD HL,MKY_LSTATE ; POINT TO LEFT STATE BYTE + JR MKY_DEC6D ; CONTINUE + +MKY_DEC6C: ; RIGHT STATE KEY MAKE/BREAK (STATE BIT TO SET/CLEAR IN E) + LD HL,MKY_RSTATE ; POINT TO RIGHT STATE BYTE + JR MKY_DEC6D ; CONTINUE + +MKY_DEC6D: ; BRANCH BASED ON WHETHER THIS IS A MAKE OR BREAK EVENT + LD A,(MKY_STATUS) ; GET STATUS FLAGS + AND MKY_BREAK ; BREAK EVENT? + JR Z,MKY_DEC6E ; NO, HANDLE A MODIFIER KEY MAKE EVENT + JR MKY_DEC6F ; YES, HANDLE A MODIFIER BREAK EVENT + +MKY_DEC6E: ; HANDLE STATE KEY MAKE EVENT + LD A,E ; GET THE BIT TO SET + OR (HL) ; OR IN THE CURRENT BITS + LD (HL),A ; SAVE THE RESULT + JR MKY_DEC6G ; CONTINUE + +MKY_DEC6F: ; HANDLE STATE KEY BREAK EVENT + LD A,E ; GET THE BIT TO CLEAR + XOR $FF ; FLIP ALL BITS TO SETUP FOR A CLEAR OPERATION + AND (HL) ; AND IN THE FLIPPED BITS TO CLEAR DESIRED BIT + LD (HL),A ; SAVE THE RESULT + JR MKY_DEC6G ; CONTINUE + +MKY_DEC6G: ; COALESCE L/R STATE FLAGS + LD A,(MKY_STATE) ; GET EXISTING STATE BITS + AND $F0 ; GET RID OF OLD MODIFIER BITS + LD DE,(MKY_LSTATE) ; LOAD BOTH L/R STATE BYTES IN D/E + OR E ; MERGE IN LEFT STATE BITS + OR D ; MERGE IN RIGHT STATE BITS + LD (MKY_STATE),A ; SAVE IT + JP MKY_DECNEW ; DONE WITH CURRENT KEYSTROKE + +MKY_DEC7: ; COMPLETE PROCESSING OF EXTENDED AND KEY BREAK EVENTS + LD A,(MKY_STATUS) ; GET CURRENT STATUS FLAGS + AND MKY_BREAK ; IS THIS A KEY BREAK EVENT? + JP NZ,MKY_DECNEW ; PROCESS NEXT KEY + +MKY_DEC8: ; HANDLE TOGGLE KEYS + LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE INTO A + LD E,MKY_CAPSLCK ; SETUP E WITH CAPS LOCK STATE BIT + CP $BC ; IS THIS THE CAPS LOCK KEY? + JR Z,MKY_DEC8A ; YES, GO TO BIT SET ROUTINE + LD E,MKY_NUMLCK ; SETUP E WITH NUM LOCK STATE BIT + CP $BD ; IS THIS THE NUM LOCK KEY? + JR Z,MKY_DEC8A ; YES, GO TO BIT SET ROUTINE + LD E,MKY_SCRLCK ; SETUP E WITH SCROLL LOCK STATE BIT + CP $BE ; IS THIS THE SCROLL LOCK KEY? + JR Z,MKY_DEC8A ; YES, GO TO BIT SET ROUTINE + JR MKY_DEC9 ; NOT A TOGGLE KEY, CONTINUE + +MKY_DEC8A: ; RECORD THE TOGGLE + LD A,(MKY_STATE) ; GET THE CURRENT STATE FLAGS + XOR E ; SET THE TOGGLE KEY BIT FROM ABOVE + LD (MKY_STATE),A ; SAVE IT + CALL MKY_SETLEDS ; UPDATE LED LIGHTS ON KBD + JP MKY_DECNEW ; RESTART DECODER FOR A NEW KEY + +MKY_DEC9: ; ADJUST KEYCODE FOR CONTROL MODIFIER + LD A,(MKY_STATE) ; GET THE CURRENT STATE BITS + AND MKY_CTRL ; CHECK THE CONTROL BIT + JR Z,MKY_DEC10 ; CONTROL KEY NOT PRESSED, MOVE ON + LD A,(MKY_KEYCODE) ; GET CURRENT KEYCODE IN A + CP 'a' ; COMPARE TO LOWERCASE A + JR C,MKY_DEC9A ; BELOW IT, BYPASS + CP 'z' + 1 ; COMPARE TO LOWERCASE Z + JR NC,MKY_DEC9A ; ABOVE IT, BYPASS + RES 5,A ; KEYCODE IN LOWERCASE A-Z RANGE CLEAR BIT 5 TO MAKE IT UPPERCASE +MKY_DEC9A: + CP '@' ; COMPARE TO @ + JR C,MKY_DEC10 ; BELOW IT, BYPASS + CP '_' + 1 ; COMPARE TO _ + JR NC,MKY_DEC10 ; ABOVE IT, BYPASS + RES 6,A ; CONVERT TO CONTROL VALUE BY CLEARING BIT 6 + LD (MKY_KEYCODE),A ; UPDATE KEYCODE TO CONTROL VALUE + +MKY_DEC10: ; ADJUST KEYCODE FOR CAPS LOCK + LD A,(MKY_STATE) ; LOAD THE STATE FLAGS + AND MKY_CAPSLCK ; CHECK CAPS LOCK + JR Z,MKY_DEC11 ; CAPS LOCK NOT ACTIVE, MOVE ON + LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE VALUE + CP 'a' ; COMPARE TO LOWERCASE A + JR C,MKY_DEC10A ; BELOW IT, BYPASS + CP 'z' + 1 ; COMPARE TO LOWERCASE Z + JR NC,MKY_DEC10A ; ABOVE IT, BYPASS + JR MKY_DEC10B ; IN RANGE LOWERCASE A-Z, GO TO CASE SWAPPING LOGIC +MKY_DEC10A: + CP 'A' ; COMPARE TO UPPERCASE A + JR C,MKY_DEC11 ; BELOW IT, BYPASS + CP 'Z' + 1 ; COMPARE TO UPPERCASE Z + JR NC,MKY_DEC11 ; ABOVE IT, BYPASS + JR MKY_DEC10B ; IN RANGE UPPERCASE A-Z, GO TO CASE SWAPPING LOGIC +MKY_DEC10B: + LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE + XOR $20 ; FLIP BIT 5 TO SWAP UPPER/LOWER CASE + LD (MKY_KEYCODE),A ; SAVE IT + +MKY_DEC11: ; HANDLE NUM PAD KEYS + LD A,(MKY_STATE) ; GET THE CURRENT STATE FLAGS + AND $7F;~MKY_NUMPAD ; ASSUME NOT A NUMPAD KEY, CLEAR THE NUMPAD BIT + LD (MKY_STATE),A ; SAVE IT + + LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE + AND 11100000B ; ISOLATE TOP 3 BITS + CP 11000000B ; IS IN NUMPAD RANGE? + JR NZ,MKY_DEC12 ; NOPE, GET OUT + + LD A,(MKY_STATE) ; LOAD THE CURRENT STATE FLAGS + OR MKY_NUMPAD ; TURN ON THE NUMPAD BIT + LD (MKY_STATE),A ; SAVE IT + + AND MKY_NUMLCK ; IS NUM LOCK BIT SET? + JR Z,MKY_DEC11A ; NO, SKIP NUMLOCK PROCESSING + LD A,(MKY_KEYCODE) ; GET THE KEYCODE + XOR $10 ; FLIP VALUES FOR NUMLOCK + LD (MKY_KEYCODE),A ; SAVE IT + +MKY_DEC11A: ; APPLY NUMPAD MAPPING + LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE + LD HL,MKY_MAPNUMPAD ; LOAD THE START OF THE MAPPING TABLE + SUB $C0 ; KEYCODES START AT $C0 + LD E,A ; INDEX TO E + LD D,0 ; D IS ZERO + ADD HL,DE ; POINT TO RESULT OF MAPPING + LD A,(HL) ; GET IT IN A + LD (MKY_KEYCODE),A ; SAVE IT + +MKY_DEC12: ; DETECT UNKNOWN/INVALID KEYCODES + LD A,(MKY_KEYCODE) ; GET THE FINAL KEYCODE + CP $FF ; IS IT $FF (UNKNOWN/INVALID) + JP Z,MKY_DECNEW ; IF SO, JUST RESTART THE ENGINE + +MKY_DEC13: ; DONE - RECORD RESULTS + LD A,(MKY_STATUS) ; GET CURRENT STATUS + OR MKY_KEYRDY ; SET KEY READY BIT + LD (MKY_STATUS),A ; SAVE IT + XOR A ; A=0 + INC A ; SIGNAL SUCCESS WITH A=1 + RET + +MKY_DECNEW: ; START NEW KEYPRESS (CLEAR ALL STATUS BITS) + XOR A ; A = 0 + LD (MKY_STATUS),A ; CLEAR STATUS + JP MKY_DEC1 ; RESTART THE ENGINE + +; +;__________________________________________________________________________________________________ +; INTERRUPT HANDLER +; +; IF MKY_SCANBUFFF HAS CONTENT, DO NOTHING +; OTHERWISE, SCAN KEYBOARD AND IF A KEY EVENT IS DETECTED +; WRITE SCANCODES TO MKY_SCANBUFFF +; +; ALSO GENERATE KEY REPEAT EVENTS, IF KEY HELD DOWN +;__________________________________________________________________________________________________ +; +MKY_INT: + PUSH BC + PUSH DE + PUSH IX + + LD A, (SCNCNT) ; SCAN THE KEYBOARD EVERY 'SCAN_INT_PERIOD' INTERRUPTS. + DEC A + LD (SCNCNT), A + JR NZ, MKY_INT_END + + LD A, SCAN_INT_PERIOD + LD (SCNCNT), A + + LD A, (MKY_SCANBUFFLEN) ; SKIP SCANNING UNTIL CODE BUFFER IS EMPTY + OR A + JR NZ, MKY_INT_END + + CALL MKY_SCAN + CALL MKY_GENSCODE + +MKY_INT_END: + CALL MKY_RPTGEN + POP IX + POP DE + POP BC + RET +; +; SCAN KEYBOARD AND STORE ALL COLUMN RESULTS PER ROW AT NEWKEY +; +MKY_SCAN: + IN A, (MKY_REGC) ; READ AND MASK THE CURRENT STATE OF PPI PORT C + AND $F0 + LD C, A + LD B, MATRIX_ROW_COUNT ; PREPARE TO LOOP THRU THE SCAN ROWS + LD HL, NEWKEY + +MKY_SCAN_LP: + LD A, C + OUT (MKY_REGC), A ; SET ACTIVE ROW + IN A, (MKY_REGB) ; READ ACTIVE COLUMN DATA + LD (HL), A ; STORE COLUMN READ VALUE + INC HL + INC C + DJNZ MKY_SCAN_LP ; LOOP UNTIL ALL ROWS READ + RET +; +;__________________________________________________________________________________________________ +; COMPARE OLDKEY TO NEWKEY +; GENERATE SCAN CODES +; +; FOR EACH BIT IN OLDKEY AND NEWKEY +; IF BOTH = 1, THEN NO KEY PRESS - NOTHING CHANGED +; IF BOTH = 0, THEN KEY WAS AND IS STILL PRESSED - NOTHING CHANGED +; IF OLD = 1 AND NEW = 0, KEY WAS PRESSED +; IF OLD = 0 AND NEW = 1, KEY WAS RELEASED +; STOP OF FIRST CHANGE - STORE IN BUFFER - THEN NOTHING HAPPENS, +; UNTIL MKY_RDSCAN IS CALLED AND CLEARS THE SCAN BUFFER +; ALSO RESET MKY_RPTACTIVE IS A KEY IS HELD DOWN +MKY_GENSCODE: + XOR A + LD (MKY_RPTACTIVE), A ; CLEAR FLAG TO INDICATE A KEYHOLD STATE + + LD HL, OLDKEY + LD DE, NEWKEY + LD A, 0 + EX AF, AF' ; ROW COUNT IN A' + +MKY_GENSCODE_LPR: + LD B, 8 ; 8 COLUMN BITS + LD C, (HL) + LD A, (DE) + +MKY_GENSCODE_LPC: + RRCA ; ROTATE NEW COLUMN BIT INTO CARRY + JR NC, MKY_NEWDWN ; IS KEY DOWN? + + ; KEY IS UP + RRC C ; ROTATE OLD COLUMN BIT INTO CARRY + JR C, MKY_GENSCODENXT ; BOTH KEYS DOWN? + + ; NEW KEY IS UP, OLD KEY WAS DOWN + JP MKY_KEYUP ; STORE NEW KEY RELEASE IN BUFF (A' IF ROW, B IS COLUMN) + ; JR MKY_GENSCODENXT + +MKY_NEWDWN: + RRC C ; ROTATE OLD COLUMN BIT INTO CARRY + JR NC, MKY_KEYHOLD ; BOTH KEYS DOWN? + + ; NEW KEY IS DOWN, OLD KEY WAS UP + JP MKY_KEYDOWN ; STORE NEW KEY PRESS IN BUFF (A' IF ROW, B IS COLUMN) + +MKY_GENSCODENXT: + DJNZ MKY_GENSCODE_LPC + + EX AF, AF' + INC A + CP MATRIX_ROW_COUNT + RET Z + EX AF, AF' + + INC HL + INC DE + JR MKY_GENSCODE_LPR + + RET + + ; KEY IS PRESSED - TEST FOR REPEAT +MKY_KEYHOLD: + PUSH AF + + EX AF, AF' ; GET ROW COUNT + CP 6 + JR NC, MKY_NORPT ; IF >=6 THEN WE DONT REPEAT + + LD (MKY_NRPTROW), A + EX AF, AF' + + LD A, B + LD (MKY_NRPTCOL), A + + LD A, $FF + LD (MKY_RPTACTIVE), A + + POP AF + JR MKY_GENSCODENXT + +MKY_NORPT: + EX AF, AF' + POP AF + JR MKY_GENSCODENXT + +MKY_KEYDOWN: + CALL MKY_RESOLDBIT + CALL MKY_SCANADDR + LD A, (HL) + OR A ; IF NO SCANCODE - IGNORE IT + RET Z + LD (MKY_SCANBUFF), A + LD A, 1 + LD (MKY_SCANBUFFLEN), A + RET + +MKY_KEYUP: + CALL MKY_SETOLDBIT + CALL MKY_SCANADDR + + LD A, (HL) + OR A ; IF NO SCANCODE - IGNORE IT + RET Z + LD (MKY_SCANBUFF+1), A + LD A, $F0 + LD (MKY_SCANBUFF), A + LD A, 2 + LD (MKY_SCANBUFFLEN), A + RET + +MKY_RPTGEN: + LD A, (MKY_SCANBUFFLEN) ; IF ALREADY A CODE IN BUFFER + OR A ; THEN WE CANT GENERATE A REPEAT + JR NZ, MKY_RPTCLR + + LD A, (MKY_RPTACTIVE) ; NO KEY IS HELD + OR A + JR Z, MKY_RPTCLR + + LD A, (MKY_RPTCNT) + DEC A + JR Z, MKY_RPTADD + LD (MKY_RPTCNT), A + RET + +MKY_RPTADD: + LD A, KEY_REPEAT_PERIOD + LD (MKY_RPTCNT), A + LD A, (MKY_NRPTCOL) + LD B, A + LD A, (MKY_NRPTROW) + EX AF, AF' + JR MKY_KEYDOWN + +MKY_RPTCLR: + LD A, KEY_REPEAT_INIT + LD (MKY_RPTCNT), A + XOR A + LD (MKY_NRPTCOL), A + LD (MKY_NRPTROW), A + RET +; +;__________________________________________________________________________________________________ +; +; RETRIEVE ADDRESS AND BIT MASK WITHIN OLDKEY ARRAY +; +; INPUT: +; B = 1 TO 8 - COLUMN COUNT +; A' IS ROW COUNT - 0 TO MATRIX_ROW_COUNT +; OUTPUT: +; HL = BYTE WITHIN OLDKEY ARRAY +; A = BIT MASK FOR COLUMN COUNT (EG: B = 3, A = 8) +; PROTECTS: +; A' IS UNCHANGED +; B IS UNCHANGED +MKY_GETKEYIDX: + LD A, $80 + LD D, B ; SAVE B (COLUMN COUNT - 1 TO 8) +MKY_SETOLDBIT_LP: + DEC B + JR Z, SKIP + RRCA + JR MKY_SETOLDBIT_LP + +SKIP: + LD HL, OLDKEY + + EX AF, AF' ; RETRIEVE ROW COUNT + LD C, A + EX AF, AF' + LD B, 0 + ADD HL, BC + LD B, D ; RETORE B (COLUMN COUNT) + RET +; +;__________________________________________________________________________________________________ +; +; SET BIT WITHIN THE KEY MATRIX ARRAY +; HL -> ADDRESS WITHIN OLDKEY OR NEWKEY ARRAY +; C BIT MASK TO BE OR'ED +; +MKY_SETOLDBIT: + CALL MKY_GETKEYIDX + LD C, (HL) + OR C + LD (HL), A + RET +; +;__________________________________________________________________________________________________ +; +; RESET BIT WITHIN THE KEY MATRIX ARRAY +; HL -> ADDRESS WITHIN OLDKEY OR NEWKEY ARRAY +; C CPL BIT MASK TO BE AND'ED +; +MKY_RESOLDBIT: + CALL MKY_GETKEYIDX + LD C, (HL) + CPL + AND C + LD (HL), A + RET +; +;__________________________________________________________________________________________________ +; +; CALCULATE THE ADDRESS WITHIN THE SCANCODE_TABLE FOR A SPECIFIC KEY +; +MKY_SCANADDR: + ; ASSUMING SINGLE BYTE CODE CODE + EX AF, AF' ; RETRIVE ROW COUNT + + ; CODE ADDR = SCANCODE_TBL + (A * 8) + B - 1 + LD L, A + LD H, 0 + ADD HL, HL + ADD HL, HL + ADD HL, HL + DEC B + LD C, B + LD B, 0 + ADD HL, BC + LD DE, SCANCODE_TBL + ADD HL, DE + RET +; +;__________________________________________________________________________________________________ +; READ A SINGLE BYTE FROM THE SCANCODE BUFFER +; RETURNED IN A +; +MKY_READBYT: + ld a, (MKY_SCANBUFFLEN) + or a + ret z + + LD A, (MKY_SCANBUFF) + LD DE, MKY_SCANBUFF + LD HL, MKY_SCANBUFF + 1 + LD BC, 4 + LDIR + LD C, A + LD A, (MKY_SCANBUFFLEN) + DEC A + LD (MKY_SCANBUFFLEN), A + LD A, C + RET +; +;__________________________________________________________________________________________________ +; +; TURN THE CAPS LED LIGHT ON +; +MKY_LEDCAPSON: + IN A, (MKY_REGC) + RES 6, A + OUT (MKY_REGC), A + RET +; +;__________________________________________________________________________________________________ +; +; TURN THE CAPS LED LIGHT OFF +; +MKY_LEDCAPSOFF: + IN A, (MKY_REGC) + SET 6, A + OUT (MKY_REGC), A + RET + +; DYNAMIC DATA STORAGE: +; +; STORAGE OF KEYBOARD MATRIX, USED FOR DETECTING KEY REPETITION +OLDKEY: .FILL MATRIX_ROW_COUNT, $FF +; +; CURRENT STATE OF THE KEYBOARD MATRIX +NEWKEY: .FILL MATRIX_ROW_COUNT, $FF +; +; F3F6: VDP-INTERUPT COUNTER THAT COUNTS FROM SCAN_INT_PERIOD TO 0, WHEN IT REACHES ZERO, THE +; KEYBOARD MATRIX IS SCANNED, AND THE COUNTERS IS RESET AT SCAN_INT_PERIOD +SCNCNT: .DB SCAN_INT_PERIOD +; +MKY_NRPTCOL: .DB 0 +MKY_NRPTROW: .DB 0 +MKY_RPTCOL: .DB 0 +MKY_RPTROW: .DB 0 +MKY_RPTACTIVE: .DB 0 +MKY_RPTCNT: .DB KEY_REPEAT_INIT + +MKY_SCANBUFF: .FILL 5, 0 +MKY_SCANBUFFLEN: .DB 0 + +MKY_SCANCODE: .DB 0 ; RAW SCANCODE +MKY_KEYCODE: .DB 0 ; RESULTANT KEYCODE AFTER DECODING +MKY_STATE: .DB 0 ; STATE BITS (SEE ABOVE) +MKY_LSTATE: .DB 0 ; STATE BITS FOR "LEFT" KEYS +MKY_RSTATE: .DB 0 ; STATE BITS FOR "RIGHT" KEYS +MKY_STATUS: .DB 0 ; CURRENT STATUS BITS (SEE ABOVE) +MKY_REPEAT: .DB 0 ; CURRENT REPEAT RATE +MKY_IDLE: .DB 0 ; IDLE COUNT + +#IF (MKYKBLOUT == KBD_US) +;__________________________________________________________________________________________________ +; +; MAPPING TABLES US/ENGLISH +;__________________________________________________________________________________________________ +MKY_MAPSTD: ; SCANCODE IS INDEX INTO TABLE TO RESULTANT LOOKUP KEYCODE + .DB $FF,$E8,$FF,$E4,$E2,$E0,$E1,$EB,$FF,$E9,$E7,$E5,$E3,$09,'`',$FF + .DB $FF,$B4,$B0,$FF,$B2,'q','1',$FF,$FF,$FF,'z','s','a','w','2',$FF + .DB $FF,'c','x','d','e','4','3',$FF,$FF,' ','v','f','t','r','5',$FF + .DB $FF,'n','b','h','g','y','6',$FF,$FF,$FF,'m','j','u','7','8',$FF + .DB $FF,',','k','i','o','0','9',$FF,$FF,'.','/','l',';','p','-',$FF + .DB $FF,$FF,$27,$FF,'[','=',$FF,$FF,$BC,$B1,$0D,']',$FF,'\',$FF,$FF + .DB $FF,$FF,$FF,$FF,$FF,$FF,$08,$FF,$FF,$C0,$FF,$C3,$C6,$FF,$FF,$FF + .DB $C9,$CA,$C1,$C4,$C5,$C7,$1B,$BD,$FA,$CE,$C2,$CD,$CC,$C8,$BE,$FF + .DB $FF,$FF,$FF,$E6,$EC +; +MKY_MAPSIZ .EQU ($ - MKY_MAPSTD) +; +MKY_MAPSHIFT: ; SCANCODE IS INDEX INTO TABLE TO RESULTANT LOOKUP KEYCODE WHEN SHIFT ACTIVE + .DB $FF,$E8,$FF,$E4,$E2,$E0,$E1,$EB,$FF,$E9,$E7,$E5,$E3,$09,'~',$FF + .DB $FF,$B4,$B0,$FF,$B2,'Q','!',$FF,$FF,$FF,'Z','S','A','W','@',$FF + .DB $FF,'C','X','D','E','$','#',$FF,$FF,' ','V','F','T','R','%',$FF + .DB $FF,'N','B','H','G','Y','^',$FF,$FF,$FF,'M','J','U','&','*',$FF + .DB $FF,'<','K','I','O',')','(',$FF,$FF,'>','?','L',':','P','_',$FF + .DB $FF,$FF,$22,$FF,'{','+',$FF,$FF,$BC,$B1,$0D,'}',$FF,'|',$FF,$FF + .DB $FF,$FF,$FF,$FF,$FF,$FF,$08,$FF,$FF,$D0,$FF,$D3,$D6,$FF,$FF,$FF + .DB $D9,$DA,$D1,$D4,$D5,$D7,$1B,$BD,$FA,$DE,$D2,$DD,$DC,$D8,$BE,$FF + .DB $FF,$FF,$FF,$E6,$EC +; +MKY_MAPEXT: ; PAIRS ARE [SCANCODE,KEYCODE] FOR EXTENDED SCANCODES + .DB $11,$B5, $14,$B3, $1F,$B6, $27,$B7 + .DB $2F,$EF, $37,$FA, $3F,$FB, $4A,$CB + .DB $5A,$CF, $5E,$FC, $69,$F3, $6B,$F8 + .DB $6C,$F2, $70,$F0, $71,$F1, $72,$F7 + .DB $74,$F9, $75,$F6, $7A,$F5, $7C,$ED + .DB $7D,$F4, $7E,$FD, $00,$00 +; +MKY_MAPNUMPAD: ; KEYCODE TRANSLATION FROM NUMPAD RANGE TO STD ASCII/KEYCODES + .DB $F3,$F7,$F5,$F8,$FF,$F9,$F2,$F6,$F4,$F0,$F1,$2F,$2A,$2D,$2B,$0D + .DB $31,$32,$33,$34,$35,$36,$37,$38,$39,$30,$2E,$2F,$2A,$2D,$2B,$0D +#ENDIF +#IF (MKYKBLOUT == KBD_DE) +;__________________________________________________________________________________________________ +; +; MAPPING TABLES GERMAN +;__________________________________________________________________________________________________ +; +MKY_MAPSTD: ; SCANCODE IS INDEX INTO TABLE TO RESULTANT LOOKUP KEYCODE ROW + +; Column 0 1 2 3 4 5 6 7 8 9 A B C D E F ; Special adjustments listed below + .DB $FF,$E8,$FF,$E4,$E2,$E0,$E1,$EB,$FF,$E9,$E7,$E5,$E3,$09,'^',$FF ;0 for German keyboard keys that give + .DB $FF,$B4,$B0,$FF,$B2,'q','1',$FF,$FF,$FF,'y','s','a','w','2',$FF ;1 different characters than are printed + .DB $FF,'c','x','d','e','4','3',$FF,$FF,' ','v','f','t','r','5',$FF ;2 on the keys. + .DB $FF,'n','b','h','g','z','6',$FF,$FF,$FF,'m','j','u','7','8',$FF ;3 'german key' --> 'new occupied with' + .DB $FF,',','k','i','o','0','9',$FF,$FF,'.','-','l','[','p',$5C,$FF ;4 Assembler ERROR: '\'-->$5C ; 'ö'-->'[' + .DB $FF,$FF,'@',$FF,']','|',$FF,$FF,$BC,$B1,$0D,'+',$FF,'#',$FF,$FF ;5 'ä'-->'@' ; 'ü'-->']' + .DB $FF,'<',$FF,$FF,$FF,$FF,$08,$FF,$FF,$C0,$FF,$C3,$C6,'<',$FF,$FF ;6 + .DB $C9,$CA,$C1,$C4,$C5,$C7,$1B,$BD,$FA,$CE,$C2,$CD,$CC,$C8,$BE,$FF ;7 + .DB $FF,$FF,$FF,$E6,$EC ;8 + +MKY_MAPSIZ .EQU ($ - MKY_MAPSTD) +; +MKY_MAPSHIFT: ; SCANCODE IS INDEX INTO TABLE TO RESULTANT LOOKUP KEYCODE WHEN SHIFT ACTIVE + + .DB $FF,$E8,$FF,$E4,$E2,$E0,$E1,$EB,$FF,$E9,$E7,$E5,$E3,$09,'~',$FF ; '°' --> '~' + .DB $FF,$B4,$B0,$FF,$B2,'Q','!',$FF,$FF,$FF,'Y','S','A','W',$22,$FF + .DB $FF,'C','X','D','E','$',$20,$FF,$FF,' ','V','F','T','R','%',$FF ; '§'-->$20; '§'=Paragraph not used in CP/M + .DB $FF,'N','B','H','G','Z','&',$FF,$FF,$FF,'M','J','U','/','(',$FF + .DB $FF,';','K','I','O','=',')',$FF,$FF,':','_','L','{','P','?',$FF ; 'Ö'-->'{' + .DB $FF,$FF,'@',$FF,'}','`',$FF,$FF,$BC,$B1,$0D,'*',$FF,$27,$FF,$FF ; 'Ä'-->'@' ; 'Ü'-->'}' + .DB $FF,'>',$FF,$FF,$FF,$FF,$08,$FF,$FF,$D0,$FF,$D3,$D6,'>',$FF,$FF + .DB $D9,$DA,$D1,$D4,$D5,$D7,$1B,$BD,$FA,$DE,$D2,$DD,$DC,$D8,$BE,$FF + .DB $FF,$FF,$FF,$E6,$EC + +MKY_MAPEXT: ; PAIRS ARE [SCANCODE,KEYCODE] FOR EXTENDED SCANCODES + .DB $11,$B5, $14,$B3, $1F,$B6, $27,$B7 + .DB $2F,$EF, $37,$FA, $3F,$FB, $4A,$CB ; All keys listed below are customized for Wordstar. + .DB $5A,$CF, $5E,$FC, $69,$06, $6B,$13 ; n.a , n.a , word right , n.a. + .DB $6C,$01, $70,$16, $71,$07, $72,$18 ; Word left , Toggle Insert/Overwrite , Del Char , Cursor down + .DB $74,$04, $75,$05, $7A,$1A, $7C,$ED ; Cursor right , Cursor up , Page down + .DB $7D,$17, $7E,$FD, $00,$00 ; Page up , n.a. , END MKY_MAPEXT (Pairs end) +; +MKY_MAPNUMPAD: ; KEYCODE TRANSLATION FROM NUMPAD RANGE TO STD ASCII/KEYCODES + + .DB $F3,$F7,$F5,$F8,$FF,$F9,$F2,$F6,$F4,$F0,$F1,$2F,$2A,$2D,$2B,$0D + .DB $31,$32,$33,$34,$35,$36,$37,$38,$39,$30,$2E,$2F,$2A,$2D,$2B,$0D +; +#ENDIF +; +;__________________________________________________________________________________________________ +; KEYCODE VALUES RETURNED BY THE DECODER +;__________________________________________________________________________________________________ +; +; VALUES 0-127 ARE STANDARD ASCII, SPECIAL KEYS WILL HAVE THE FOLLOWING VALUES: +; +; F1 $E0 +; F2 $E1 +; F3 $E2 +; F4 $E3 +; F5 $E4 +; F6 $E5 +; F7 $E6 +; F8 $E7 +; F9 $E8 +; F10 $E9 +; F11 $EA +; F12 $EB +; SYSRQ $EC +; PRTSC $ED +; PAUSE $EE +; APP $EF +; INS $F0 +; DEL $F1 +; HOME $F2 +; END $F3 +; PGUP $F4 +; PGDN $F5 +; UP $F6 +; DOWN $F7 +; LEFT $F8 +; RIGHT $F9 +; POWER $FA +; SLEEP $FB +; WAKE $FC +; BREAK $FD diff --git a/Source/HBIOS/tms.asm b/Source/HBIOS/tms.asm index 9a97ec8c..62aab029 100644 --- a/Source/HBIOS/tms.asm +++ b/Source/HBIOS/tms.asm @@ -118,7 +118,12 @@ TMS_INIT1: CALL TMS_VDARES1 #IF (TMSMODE == TMSMODE_N8) CALL PPK_INIT ; INITIALIZE KEYBOARD DRIVER +#ELSE +#IF MSKENABLE + CALL MKY_INIT +#ENDIF #ENDIF + #IF (INTMODE == 1 & TMSTIMENABLE) ; ADD IM1 INT CALL LIST ENTRY LD HL, TMS_TSTINT ; GET INT VECTOR @@ -172,11 +177,18 @@ TMS_FNTBL: .DW PPK_STAT .DW PPK_FLUSH .DW PPK_READ +#ELSE +#IF MSKENABLE + .DW MKY_STAT + .DW MKY_FLUSH + .DW MKY_READ + #ELSE .DW TMS_STAT .DW TMS_FLUSH .DW TMS_READ #ENDIF +#ENDIF #IF (($ - TMS_FNTBL) != (VDA_FNCNT * 2)) .ECHO "*** INVALID TMS FUNCTION TABLE ***\n" !!!!! @@ -803,6 +815,11 @@ TMS_TSTINT: RET TMS_INTHNDL: + +#IF MSKENABLE + CALL MKY_INT +#ENDIF + CALL HB_TIMINT ; RETURN NZ - HANDLED OR $FF RET From 8173414bf53b013f10052fe242735e1e20e15ef9 Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Wed, 11 Nov 2020 19:36:59 +1100 Subject: [PATCH 07/10] MSX-KEYBOARD: some optimisation of interrupt handler --- Source/HBIOS/msxkeyb.asm | 267 ++++++++++++++++++++------------------- 1 file changed, 135 insertions(+), 132 deletions(-) diff --git a/Source/HBIOS/msxkeyb.asm b/Source/HBIOS/msxkeyb.asm index 8bf0f892..fc1ec30d 100644 --- a/Source/HBIOS/msxkeyb.asm +++ b/Source/HBIOS/msxkeyb.asm @@ -16,6 +16,10 @@ ; ; TODO: ; IMPLEMENT MULTIBYTE SCAN CODES (ARROW KEYS, ETC) +; OPTIMISE INTERRUPT HANDLER - HAS NEGATIVE IMPACT ON SERIAL IO AT 115200 FOR CPU @ 8MHZ +; BACKSPACE DOES NOT AUTO-REPEAT +; AUTO DETECT PPI +; ; ;====================================================================== ; DRIVER - CONSTANTS @@ -42,10 +46,10 @@ PPICMD_GA_MODE_2 .EQU 64 PPICMD_COMMAND .EQU 128 ; COUNT FOR PERIOD TO START REPEATING CHARACTERS -KEY_REPEAT_INIT: .EQU 20 +KEY_REPEAT_INIT: .EQU 10 ; COUNT FOR PERIOD BETWEEN AUTO REPEATING CHARACTERS -KEY_REPEAT_PERIOD: .EQU 5 +KEY_REPEAT_PERIOD: .EQU 2 ; COUNT FOR INTERRUPT HANDLER TO TRIGGER KEYBOARD SCANNER (EG: SCAN KEYBOARD ONLY EVERY 3RD INTERRUPT (3/60)) SCAN_INT_PERIOD: .EQU 3 @@ -221,6 +225,8 @@ MKY_FLUSH: ;__________________________________________________________________________________________________ ; MKY_STAT: + LD A, $FF + LD (MKY_SCANON), A CALL MKY_DECODE ; CHECK THE KEYBOARD JP Z,CIO_IDLE ; RET VIA IDLE PROCESSING IF NO KEY RET @@ -322,8 +328,27 @@ MKY_GETDATAX: MKY_SETLEDS: LD A,(MKY_STATE) ; LOAD THE STATE FLAGS AND MKY_CAPSLCK ; CHECK CAPS LOCK - JP Z, MKY_LEDCAPSOFF - JP MKY_LEDCAPSON + JR Z, MKY_LEDCAPSOFF +; +;__________________________________________________________________________________________________ +; +; TURN THE CAPS LED LIGHT ON +; +MKY_LEDCAPSON: + IN A, (MKY_REGC) + RES 6, A + OUT (MKY_REGC), A + RET +; +;__________________________________________________________________________________________________ +; +; TURN THE CAPS LED LIGHT OFF +; +MKY_LEDCAPSOFF: + IN A, (MKY_REGC) + SET 6, A + OUT (MKY_REGC), A + RET ;__________________________________________________________________________________________________ ; DECODING ENGINE @@ -409,12 +434,7 @@ MKY_DECODE: ; toggle (XOR) bit 5 of keycode ; ; Step 11: Handle num pad keys -; clear state[numpad] -; if keycode is numpad -; set state[numpad] -; if state[numlock] -; toggle (XOR) bit 4 of keycode -; apply numpad-map[keycode] -> keycode +; REMOVED ; ; Step 12: Detect unknown/invalid keycodes ; if keycode == $FF @@ -622,7 +642,7 @@ MKY_DEC9A: MKY_DEC10: ; ADJUST KEYCODE FOR CAPS LOCK LD A,(MKY_STATE) ; LOAD THE STATE FLAGS AND MKY_CAPSLCK ; CHECK CAPS LOCK - JR Z,MKY_DEC11 ; CAPS LOCK NOT ACTIVE, MOVE ON + JR Z,MKY_DEC12 ; CAPS LOCK NOT ACTIVE, MOVE ON LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE VALUE CP 'a' ; COMPARE TO LOWERCASE A JR C,MKY_DEC10A ; BELOW IT, BYPASS @@ -631,44 +651,44 @@ MKY_DEC10: ; ADJUST KEYCODE FOR CAPS LOCK JR MKY_DEC10B ; IN RANGE LOWERCASE A-Z, GO TO CASE SWAPPING LOGIC MKY_DEC10A: CP 'A' ; COMPARE TO UPPERCASE A - JR C,MKY_DEC11 ; BELOW IT, BYPASS + JR C,MKY_DEC12 ; BELOW IT, BYPASS CP 'Z' + 1 ; COMPARE TO UPPERCASE Z - JR NC,MKY_DEC11 ; ABOVE IT, BYPASS + JR NC,MKY_DEC12 ; ABOVE IT, BYPASS JR MKY_DEC10B ; IN RANGE UPPERCASE A-Z, GO TO CASE SWAPPING LOGIC MKY_DEC10B: LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE XOR $20 ; FLIP BIT 5 TO SWAP UPPER/LOWER CASE LD (MKY_KEYCODE),A ; SAVE IT -MKY_DEC11: ; HANDLE NUM PAD KEYS - LD A,(MKY_STATE) ; GET THE CURRENT STATE FLAGS - AND $7F;~MKY_NUMPAD ; ASSUME NOT A NUMPAD KEY, CLEAR THE NUMPAD BIT - LD (MKY_STATE),A ; SAVE IT - - LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE - AND 11100000B ; ISOLATE TOP 3 BITS - CP 11000000B ; IS IN NUMPAD RANGE? - JR NZ,MKY_DEC12 ; NOPE, GET OUT - - LD A,(MKY_STATE) ; LOAD THE CURRENT STATE FLAGS - OR MKY_NUMPAD ; TURN ON THE NUMPAD BIT - LD (MKY_STATE),A ; SAVE IT - - AND MKY_NUMLCK ; IS NUM LOCK BIT SET? - JR Z,MKY_DEC11A ; NO, SKIP NUMLOCK PROCESSING - LD A,(MKY_KEYCODE) ; GET THE KEYCODE - XOR $10 ; FLIP VALUES FOR NUMLOCK - LD (MKY_KEYCODE),A ; SAVE IT - -MKY_DEC11A: ; APPLY NUMPAD MAPPING - LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE - LD HL,MKY_MAPNUMPAD ; LOAD THE START OF THE MAPPING TABLE - SUB $C0 ; KEYCODES START AT $C0 - LD E,A ; INDEX TO E - LD D,0 ; D IS ZERO - ADD HL,DE ; POINT TO RESULT OF MAPPING - LD A,(HL) ; GET IT IN A - LD (MKY_KEYCODE),A ; SAVE IT +; MKY_DEC11: ; HANDLE NUM PAD KEYS +; LD A,(MKY_STATE) ; GET THE CURRENT STATE FLAGS +; AND $7F;~MKY_NUMPAD ; ASSUME NOT A NUMPAD KEY, CLEAR THE NUMPAD BIT +; LD (MKY_STATE),A ; SAVE IT + +; LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE +; AND 11100000B ; ISOLATE TOP 3 BITS +; CP 11000000B ; IS IN NUMPAD RANGE? +; JR NZ,MKY_DEC12 ; NOPE, GET OUT + +; LD A,(MKY_STATE) ; LOAD THE CURRENT STATE FLAGS +; OR MKY_NUMPAD ; TURN ON THE NUMPAD BIT +; LD (MKY_STATE),A ; SAVE IT + +; AND MKY_NUMLCK ; IS NUM LOCK BIT SET? +; JR Z,MKY_DEC11A ; NO, SKIP NUMLOCK PROCESSING +; LD A,(MKY_KEYCODE) ; GET THE KEYCODE +; XOR $10 ; FLIP VALUES FOR NUMLOCK +; LD (MKY_KEYCODE),A ; SAVE IT + +; MKY_DEC11A: ; APPLY NUMPAD MAPPING +; LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE +; LD HL,MKY_MAPNUMPAD ; LOAD THE START OF THE MAPPING TABLE +; SUB $C0 ; KEYCODES START AT $C0 +; LD E,A ; INDEX TO E +; LD D,0 ; D IS ZERO +; ADD HL,DE ; POINT TO RESULT OF MAPPING +; LD A,(HL) ; GET IT IN A +; LD (MKY_KEYCODE),A ; SAVE IT MKY_DEC12: ; DETECT UNKNOWN/INVALID KEYCODES LD A,(MKY_KEYCODE) ; GET THE FINAL KEYCODE @@ -697,59 +717,62 @@ MKY_DECNEW: ; START NEW KEYPRESS (CLEAR ALL STATUS BITS) ; WRITE SCANCODES TO MKY_SCANBUFFF ; ; ALSO GENERATE KEY REPEAT EVENTS, IF KEY HELD DOWN +; +; NB: THIS HANDLER IS QUITE EXPENSIVE IN TIME +; AND CAN IMPACT SERIAL OPERATION FOR 115200 BAUD RATE FOR CPU AT 8MHZ ;__________________________________________________________________________________________________ ; MKY_INT: - PUSH BC - PUSH DE - PUSH IX + LD A, (MKY_SCANON) ; OPTIMISATION - ONLY SCAN IF REQUIRED + OR A + RET Z - LD A, (SCNCNT) ; SCAN THE KEYBOARD EVERY 'SCAN_INT_PERIOD' INTERRUPTS. + LD A, (MKY_SCNCNT) ; SCAN THE KEYBOARD EVERY 'SCAN_INT_PERIOD' INTERRUPTS. DEC A - LD (SCNCNT), A - JR NZ, MKY_INT_END + LD (MKY_SCNCNT), A + RET NZ LD A, SCAN_INT_PERIOD - LD (SCNCNT), A + LD (MKY_SCNCNT), A LD A, (MKY_SCANBUFFLEN) ; SKIP SCANNING UNTIL CODE BUFFER IS EMPTY OR A - JR NZ, MKY_INT_END + RET NZ - CALL MKY_SCAN - CALL MKY_GENSCODE - -MKY_INT_END: - CALL MKY_RPTGEN - POP IX - POP DE - POP BC - RET + EX AF, AF' + PUSH AF ; -; SCAN KEYBOARD AND STORE ALL COLUMN RESULTS PER ROW AT NEWKEY +; SCAN KEYBOARD AND STORE ALL COLUMN RESULTS PER ROW AT MKY_NEWKEY ; -MKY_SCAN: +; MKY_SCAN: IN A, (MKY_REGC) ; READ AND MASK THE CURRENT STATE OF PPI PORT C AND $F0 - LD C, A + LD D, A LD B, MATRIX_ROW_COUNT ; PREPARE TO LOOP THRU THE SCAN ROWS - LD HL, NEWKEY - + LD HL, MKY_NEWKEY + LD C, MKY_REGC MKY_SCAN_LP: - LD A, C - OUT (MKY_REGC), A ; SET ACTIVE ROW + OUT (C), D ; SET ACTIVE ROW IN A, (MKY_REGB) ; READ ACTIVE COLUMN DATA LD (HL), A ; STORE COLUMN READ VALUE INC HL - INC C + INC D DJNZ MKY_SCAN_LP ; LOOP UNTIL ALL ROWS READ + + CALL MKY_GENSCODE + +MKY_INT_END: + CALL MKY_RPTGEN + POP AF + EX AF, AF' RET + ; ;__________________________________________________________________________________________________ -; COMPARE OLDKEY TO NEWKEY +; COMPARE MKY_OLDKEY O MKY_NEWKEY ; GENERATE SCAN CODES ; -; FOR EACH BIT IN OLDKEY AND NEWKEY +; FOR EACH BIT IN MKY_OLDKEY ND MKY_NEWKEY ; IF BOTH = 1, THEN NO KEY PRESS - NOTHING CHANGED ; IF BOTH = 0, THEN KEY WAS AND IS STILL PRESSED - NOTHING CHANGED ; IF OLD = 1 AND NEW = 0, KEY WAS PRESSED @@ -761,38 +784,44 @@ MKY_GENSCODE: XOR A LD (MKY_RPTACTIVE), A ; CLEAR FLAG TO INDICATE A KEYHOLD STATE - LD HL, OLDKEY - LD DE, NEWKEY - LD A, 0 + LD HL, MKY_OLDKEY + LD DE, MKY_NEWKEY + XOR A EX AF, AF' ; ROW COUNT IN A' MKY_GENSCODE_LPR: - LD B, 8 ; 8 COLUMN BITS LD C, (HL) LD A, (DE) + AND C + CP $FF + JR Z, MKY_GENSCODENXT1 ; ALL KEYS ARE UP AND WERE UP? + + LD B, 8 ; 8 COLUMN BITS + LD A, (DE) + MKY_GENSCODE_LPC: RRCA ; ROTATE NEW COLUMN BIT INTO CARRY JR NC, MKY_NEWDWN ; IS KEY DOWN? ; KEY IS UP RRC C ; ROTATE OLD COLUMN BIT INTO CARRY - JR C, MKY_GENSCODENXT ; BOTH KEYS DOWN? + JR C, MKY_GENSCODENXT ; BOTH KEYS UP? ; NEW KEY IS UP, OLD KEY WAS DOWN - JP MKY_KEYUP ; STORE NEW KEY RELEASE IN BUFF (A' IF ROW, B IS COLUMN) - ; JR MKY_GENSCODENXT + JR MKY_KEYUP ; STORE NEW KEY RELEASE IN BUFF (A' IF ROW, B IS COLUMN) MKY_NEWDWN: RRC C ; ROTATE OLD COLUMN BIT INTO CARRY JR NC, MKY_KEYHOLD ; BOTH KEYS DOWN? ; NEW KEY IS DOWN, OLD KEY WAS UP - JP MKY_KEYDOWN ; STORE NEW KEY PRESS IN BUFF (A' IF ROW, B IS COLUMN) + JR MKY_KEYDOWN ; STORE NEW KEY PRESS IN BUFF (A' IF ROW, B IS COLUMN) MKY_GENSCODENXT: DJNZ MKY_GENSCODE_LPC +MKY_GENSCODENXT1: EX AF, AF' INC A CP MATRIX_ROW_COUNT @@ -803,12 +832,8 @@ MKY_GENSCODENXT: INC DE JR MKY_GENSCODE_LPR - RET - - ; KEY IS PRESSED - TEST FOR REPEAT + ; KEY IS PRESSED MKY_KEYHOLD: - PUSH AF - EX AF, AF' ; GET ROW COUNT CP 6 JR NC, MKY_NORPT ; IF >=6 THEN WE DONT REPEAT @@ -816,18 +841,18 @@ MKY_KEYHOLD: LD (MKY_NRPTROW), A EX AF, AF' + PUSH AF LD A, B LD (MKY_NRPTCOL), A - LD A, $FF - LD (MKY_RPTACTIVE), A + LD A, $FF ; RECORD FACT THAT A KEY HAS BEEN HELD - FOR LATER TESTING + LD (MKY_RPTACTIVE), A ; OF REPEAT FUNCTION POP AF JR MKY_GENSCODENXT MKY_NORPT: EX AF, AF' - POP AF JR MKY_GENSCODENXT MKY_KEYDOWN: @@ -856,9 +881,9 @@ MKY_KEYUP: RET MKY_RPTGEN: - LD A, (MKY_SCANBUFFLEN) ; IF ALREADY A CODE IN BUFFER + LD A, (MKY_SCANBUFFLEN) ; IF ALREADY A CODE IN BUFFER OR A ; THEN WE CANT GENERATE A REPEAT - JR NZ, MKY_RPTCLR + RET NZ LD A, (MKY_RPTACTIVE) ; NO KEY IS HELD OR A @@ -882,20 +907,17 @@ MKY_RPTADD: MKY_RPTCLR: LD A, KEY_REPEAT_INIT LD (MKY_RPTCNT), A - XOR A - LD (MKY_NRPTCOL), A - LD (MKY_NRPTROW), A RET ; ;__________________________________________________________________________________________________ ; -; RETRIEVE ADDRESS AND BIT MASK WITHIN OLDKEY ARRAY +; RETRIEVE ADDRESS AND BIT MASK WITHIN MKY_OLDKEY RRAY ; ; INPUT: ; B = 1 TO 8 - COLUMN COUNT ; A' IS ROW COUNT - 0 TO MATRIX_ROW_COUNT ; OUTPUT: -; HL = BYTE WITHIN OLDKEY ARRAY +; HL = BYTE WITHIN MKY_OLDKEY RRAY ; A = BIT MASK FOR COLUMN COUNT (EG: B = 3, A = 8) ; PROTECTS: ; A' IS UNCHANGED @@ -910,8 +932,7 @@ MKY_SETOLDBIT_LP: JR MKY_SETOLDBIT_LP SKIP: - LD HL, OLDKEY - + LD HL, MKY_OLDKEY EX AF, AF' ; RETRIEVE ROW COUNT LD C, A EX AF, AF' @@ -923,7 +944,7 @@ SKIP: ;__________________________________________________________________________________________________ ; ; SET BIT WITHIN THE KEY MATRIX ARRAY -; HL -> ADDRESS WITHIN OLDKEY OR NEWKEY ARRAY +; HL -> ADDRESS WITHIN MKY_OLDKEY R MKY_NEWKEY ARRAY ; C BIT MASK TO BE OR'ED ; MKY_SETOLDBIT: @@ -936,7 +957,7 @@ MKY_SETOLDBIT: ;__________________________________________________________________________________________________ ; ; RESET BIT WITHIN THE KEY MATRIX ARRAY -; HL -> ADDRESS WITHIN OLDKEY OR NEWKEY ARRAY +; HL -> ADDRESS WITHIN MKY_OLDKEY R MKY_NEWKEY ARRAY ; C CPL BIT MASK TO BE AND'ED ; MKY_RESOLDBIT: @@ -974,9 +995,9 @@ MKY_SCANADDR: ; RETURNED IN A ; MKY_READBYT: - ld a, (MKY_SCANBUFFLEN) - or a - ret z + LD A, (MKY_SCANBUFFLEN) + OR A + RET Z LD A, (MKY_SCANBUFF) LD DE, MKY_SCANBUFF @@ -989,43 +1010,27 @@ MKY_READBYT: LD (MKY_SCANBUFFLEN), A LD A, C RET -; -;__________________________________________________________________________________________________ -; -; TURN THE CAPS LED LIGHT ON -; -MKY_LEDCAPSON: - IN A, (MKY_REGC) - RES 6, A - OUT (MKY_REGC), A - RET -; -;__________________________________________________________________________________________________ -; -; TURN THE CAPS LED LIGHT OFF -; -MKY_LEDCAPSOFF: - IN A, (MKY_REGC) - SET 6, A - OUT (MKY_REGC), A - RET ; DYNAMIC DATA STORAGE: ; ; STORAGE OF KEYBOARD MATRIX, USED FOR DETECTING KEY REPETITION -OLDKEY: .FILL MATRIX_ROW_COUNT, $FF +MKY_OLDKEY: .FILL MATRIX_ROW_COUNT, $FF ; ; CURRENT STATE OF THE KEYBOARD MATRIX -NEWKEY: .FILL MATRIX_ROW_COUNT, $FF +MKY_NEWKEY: .FILL MATRIX_ROW_COUNT, $FF ; ; F3F6: VDP-INTERUPT COUNTER THAT COUNTS FROM SCAN_INT_PERIOD TO 0, WHEN IT REACHES ZERO, THE ; KEYBOARD MATRIX IS SCANNED, AND THE COUNTERS IS RESET AT SCAN_INT_PERIOD -SCNCNT: .DB SCAN_INT_PERIOD +MKY_SCNCNT: .DB SCAN_INT_PERIOD + +; INITIALL SET TO FALSE, AND THUS DISABLING INTERRUPT HANDLER'S SCAN FUNCTION +; AS SOON AT THE KEY REQUEST FUNCTIONS (STATUS, READ), THIS IS SET AND INTERRUPT HANDLER +; IS PERMANETLY ON. +MKY_SCANON: .DB 0 + ; MKY_NRPTCOL: .DB 0 MKY_NRPTROW: .DB 0 -MKY_RPTCOL: .DB 0 -MKY_RPTROW: .DB 0 MKY_RPTACTIVE: .DB 0 MKY_RPTCNT: .DB KEY_REPEAT_INIT @@ -1038,8 +1043,6 @@ MKY_STATE: .DB 0 ; STATE BITS (SEE ABOVE) MKY_LSTATE: .DB 0 ; STATE BITS FOR "LEFT" KEYS MKY_RSTATE: .DB 0 ; STATE BITS FOR "RIGHT" KEYS MKY_STATUS: .DB 0 ; CURRENT STATUS BITS (SEE ABOVE) -MKY_REPEAT: .DB 0 ; CURRENT REPEAT RATE -MKY_IDLE: .DB 0 ; IDLE COUNT #IF (MKYKBLOUT == KBD_US) ;__________________________________________________________________________________________________ @@ -1078,9 +1081,9 @@ MKY_MAPEXT: ; PAIRS ARE [SCANCODE,KEYCODE] FOR EXTENDED SCANCODES .DB $74,$F9, $75,$F6, $7A,$F5, $7C,$ED .DB $7D,$F4, $7E,$FD, $00,$00 ; -MKY_MAPNUMPAD: ; KEYCODE TRANSLATION FROM NUMPAD RANGE TO STD ASCII/KEYCODES - .DB $F3,$F7,$F5,$F8,$FF,$F9,$F2,$F6,$F4,$F0,$F1,$2F,$2A,$2D,$2B,$0D - .DB $31,$32,$33,$34,$35,$36,$37,$38,$39,$30,$2E,$2F,$2A,$2D,$2B,$0D +; MKY_MAPNUMPAD: ; KEYCODE TRANSLATION FROM NUMPAD RANGE TO STD ASCII/KEYCODES +; .DB $F3,$F7,$F5,$F8,$FF,$F9,$F2,$F6,$F4,$F0,$F1,$2F,$2A,$2D,$2B,$0D +; .DB $31,$32,$33,$34,$35,$36,$37,$38,$39,$30,$2E,$2F,$2A,$2D,$2B,$0D #ENDIF #IF (MKYKBLOUT == KBD_DE) ;__________________________________________________________________________________________________ @@ -1123,10 +1126,10 @@ MKY_MAPEXT: ; PAIRS ARE [SCANCODE,KEYCODE] FOR EXTENDED SCANCODES .DB $74,$04, $75,$05, $7A,$1A, $7C,$ED ; Cursor right , Cursor up , Page down .DB $7D,$17, $7E,$FD, $00,$00 ; Page up , n.a. , END MKY_MAPEXT (Pairs end) ; -MKY_MAPNUMPAD: ; KEYCODE TRANSLATION FROM NUMPAD RANGE TO STD ASCII/KEYCODES +; MKY_MAPNUMPAD: ; KEYCODE TRANSLATION FROM NUMPAD RANGE TO STD ASCII/KEYCODES - .DB $F3,$F7,$F5,$F8,$FF,$F9,$F2,$F6,$F4,$F0,$F1,$2F,$2A,$2D,$2B,$0D - .DB $31,$32,$33,$34,$35,$36,$37,$38,$39,$30,$2E,$2F,$2A,$2D,$2B,$0D +; .DB $F3,$F7,$F5,$F8,$FF,$F9,$F2,$F6,$F4,$F0,$F1,$2F,$2A,$2D,$2B,$0D +; .DB $31,$32,$33,$34,$35,$36,$37,$38,$39,$30,$2E,$2F,$2A,$2D,$2B,$0D ; #ENDIF ; From ea1081093480bd0721c5fd6f552cb2abc9371a8a Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Thu, 19 Nov 2020 16:02:52 +1100 Subject: [PATCH 08/10] MSX-KEYBOARD: optimised interrupt handler --- Source/HBIOS/msxkeyb.asm | 257 ++++++++++++++++++--------------------- 1 file changed, 118 insertions(+), 139 deletions(-) diff --git a/Source/HBIOS/msxkeyb.asm b/Source/HBIOS/msxkeyb.asm index fc1ec30d..847d3557 100644 --- a/Source/HBIOS/msxkeyb.asm +++ b/Source/HBIOS/msxkeyb.asm @@ -4,10 +4,9 @@ ; CREATED BY: DEAN NETHERTON ; KBD.ASM DRIVER USED AS TEMPLATE ; -; ;====================================================================== ; USAGE: -; THIS DRIVER IS CAN BE ACTIVED WITHIN THE TMS VIDEO DRIVER +; THIS DRIVER CAN BE ACTIVED WITHIN THE TMS VIDEO DRIVER ; ADD THE OPTION TO YOUR BUILD CONFIGURATION TO ACTIVATE THE KEYBOARD ; DRIVER: ; MSKENABLE .SET TRUE @@ -16,11 +15,9 @@ ; ; TODO: ; IMPLEMENT MULTIBYTE SCAN CODES (ARROW KEYS, ETC) -; OPTIMISE INTERRUPT HANDLER - HAS NEGATIVE IMPACT ON SERIAL IO AT 115200 FOR CPU @ 8MHZ ; BACKSPACE DOES NOT AUTO-REPEAT ; AUTO DETECT PPI ; -; ;====================================================================== ; DRIVER - CONSTANTS ;====================================================================== @@ -46,10 +43,10 @@ PPICMD_GA_MODE_2 .EQU 64 PPICMD_COMMAND .EQU 128 ; COUNT FOR PERIOD TO START REPEATING CHARACTERS -KEY_REPEAT_INIT: .EQU 10 +KEY_REPEAT_INIT: .EQU 30 ; COUNT FOR PERIOD BETWEEN AUTO REPEATING CHARACTERS -KEY_REPEAT_PERIOD: .EQU 2 +KEY_REPEAT_PERIOD: .EQU 3 ; COUNT FOR INTERRUPT HANDLER TO TRIGGER KEYBOARD SCANNER (EG: SCAN KEYBOARD ONLY EVERY 3RD INTERRUPT (3/60)) SCAN_INT_PERIOD: .EQU 3 @@ -69,20 +66,20 @@ MKY_WAITTO .EQU 0 ; 0 IS MAX WAIT (256) ; ; STATUS BITS (FOR MKY_STATUS) ; -MKY_EXT .EQU 01H ; BIT 0, EXTENDED SCANCODE ACTIVE -MKY_BREAK .EQU 02H ; BIT 1, THIS IS A KEY UP (BREAK) EVENT -MKY_KEYRDY .EQU 80H ; BIT 7, INDICATES A DECODED KEYCODE IS READY +MKY_EXT .EQU 01H ; BIT 0, EXTENDED SCANCODE ACTIVE +MKY_BREAK .EQU 02H ; BIT 1, THIS IS A KEY UP (BREAK) EVENT +MKY_KEYRDY .EQU 80H ; BIT 7, INDICATES A DECODED KEYCODE IS READY ; ; STATE BITS (FOR MKY_STATE, MKY_LSTATE, MKY_RSTATE) ; -MKY_SHIFT .EQU 01H ; BIT 0, SHIFT ACTIVE (PRESSED) -MKY_CTRL .EQU 02H ; BIT 1, CONTROL ACTIVE (PRESSED) -MKY_ALT .EQU 04H ; BIT 2, ALT ACTIVE (PRESSED) -MKY_WIN .EQU 08H ; BIT 3, WIN ACTIVE (PRESSED) -MKY_SCRLCK .EQU 10H ; BIT 4, CAPS LOCK ACTIVE (TOGGLED ON) -MKY_NUMLCK .EQU 20H ; BIT 5, NUM LOCK ACTIVE (TOGGLED ON) -MKY_CAPSLCK .EQU 40H ; BIT 6, SCROLL LOCK ACTIVE (TOGGLED ON) -MKY_NUMPAD .EQU 80H ; BIT 7, NUM PAD KEY (KEY PRESSED IS ON NUM PAD) +MKY_SHIFT .EQU 01H ; BIT 0, SHIFT ACTIVE (PRESSED) +MKY_CTRL .EQU 02H ; BIT 1, CONTROL ACTIVE (PRESSED) +MKY_ALT .EQU 04H ; BIT 2, ALT ACTIVE (PRESSED) +MKY_WIN .EQU 08H ; BIT 3, WIN ACTIVE (PRESSED) +MKY_SCRLCK .EQU 10H ; BIT 4, CAPS LOCK ACTIVE (TOGGLED ON) +MKY_NUMLCK .EQU 20H ; BIT 5, NUM LOCK ACTIVE (TOGGLED ON) +MKY_CAPSLCK .EQU 40H ; BIT 6, SCROLL LOCK ACTIVE (TOGGLED ON) +MKY_NUMPAD .EQU 80H ; BIT 7, NUM PAD KEY (KEY PRESSED IS ON NUM PAD) ; MKY_DEFRPT .EQU $40 ; DEFAULT REPEAT RATE (.5 SEC DELAY, 30CPS) MKY_DEFSTATE .EQU MKY_NUMLCK ; DEFAULT STATE (NUM LOCK ON) @@ -205,10 +202,8 @@ MKY_INIT: LD A, PPICMD_COMMAND | PPICMD_GA_MODE_0 | PPICMD_GB_MODE_0 | PPICMD_A_IN | PPICMD_B_IN | PPICMD_CLOW_OUT | PPICMD_CHIGH_OUT OUT (MKY_REGCMD), A - - LD A, 64 ; CAPS OFF + LD A, 64 ; CAPS OFF OUT (MKY_REGC), A - RET ; ;__________________________________________________________________________________________________ @@ -225,10 +220,9 @@ MKY_FLUSH: ;__________________________________________________________________________________________________ ; MKY_STAT: - LD A, $FF - LD (MKY_SCANON), A - CALL MKY_DECODE ; CHECK THE KEYBOARD - JP Z,CIO_IDLE ; RET VIA IDLE PROCESSING IF NO KEY + CALL MKY_SCAN ; SCAN AND SET SCANCODE FOR DETECTED KEY EVENT + CALL MKY_DECODE ; DECODE THE SCANCODE INTO A KEYCODE + JP Z, CIO_IDLE ; RET VIA IDLE PROCESSING IF NO KEY RET ; ;__________________________________________________________________________________________________ @@ -242,19 +236,19 @@ MKY_READ: CALL MKY_STAT ; KEY READY? ; JR Z, MKY_READ ; NOT READY, KEEP TRYING - LD A,(MKY_STATE) ; GET STATE + LD A, (MKY_STATE) ; GET STATE AND $01 ; ISOLATE EXTENDED SCANCODE BIT RRCA ; ROTATE IT TO HIGH ORDER BIT - LD E,A ; SAVE IT IN E FOR NOW - LD A,(MKY_SCANCODE) ; GET SCANCODE + LD E, A ; SAVE IT IN E FOR NOW + LD A, (MKY_SCANCODE) ; GET SCANCODE OR E ; COMBINE WITH EXTENDED BIT - LD C,A ; STORE IT IN C FOR RETURN - LD A,(MKY_KEYCODE) ; GET KEYCODE - LD E,A ; SAVE IT IN E - LD A,(MKY_STATE) ; GET STATE FLAGS - LD D,A ; SAVE THEM IN D + LD C, A ; STORE IT IN C FOR RETURN + LD A, (MKY_KEYCODE) ; GET KEYCODE + LD E, A ; SAVE IT IN E + LD A, (MKY_STATE) ; GET STATE FLAGS + LD D, A ; SAVE THEM IN D XOR A ; SIGNAL SUCCESS - LD (MKY_STATUS),A ; CLEAR STATUS TO INDICATE BYTE RECEIVED + LD (MKY_STATUS), A ; CLEAR STATUS TO INDICATE BYTE RECEIVED RET ; ;__________________________________________________________________________________________________ @@ -264,9 +258,11 @@ MKY_READ: ; ; SUCUESS/FAILURE IN A ; ; NUMBER OF BYTES RETURNED IN B (ZERO IF NO SCAN CODES AVAILABLE) ; ; SCAN CODE BYTES IN D, E, H, L, C -; +; WORK - IN - PROGRESS ;__________________________________________________________________________________________________ MKY_RDSCAN: + LD A, (MKY_SCANBUFFLEN) + CALL Z, MKY_GENSCODE LD A, (MKY_SCANBUFFLEN) LD B, A LD A, (MKY_SCANBUFF) @@ -283,6 +279,36 @@ MKY_RDSCAN: XOR A LD (MKY_SCANBUFFLEN), A RET + +MKY_SCAN: + LD A, (MKY_SCANNED) ; NEED TO WAIT UNTIL A NEW SCAN HAS COMPLETED (MKY_INT) + OR A + RET Z + + DI ; CAPTURE THE LATEST KEYBOARD SCANNED STATE + XOR A ; CLEAR SCANNED STATE + LD (MKY_SCANNED), A + + LD DE, MKY_SCNKEY ; COPY NEWKEY TO SCNKEY + LD HL, MKY_NEWKEY ; AND RESET NEWKEY TO $FF + LD B, MATRIX_ROW_COUNT + LD C, 255 +MKY_SCAN_LP1: + LD A, (HL) + LD (DE), A + LD (HL), C + INC HL + INC DE + DJNZ MKY_SCAN_LP1 + EI + + EX AF, AF' + PUSH AF + CALL MKY_GENSCODE + CALL MKY_RPTGEN + POP AF + EX AF, AF' + RET ; ;__________________________________________________________________________________________________ ; HARDWARE INTERFACE @@ -291,19 +317,16 @@ MKY_RDSCAN: ; KEYBOARD INPUT STATUS ; A=0, Z SET FOR NOTHING PENDING, OTHERWISE DATA PENDING ; -MKY_IST: - LD A, (MKY_SCANBUFFLEN) - OR A - RET +#define MKY_IST LD A, (MKY_SCANBUFFLEN) \ OR A ;__________________________________________________________________________________________________ ; ; GET A RAW DATA BYTE FROM KEYBOARD INTERFACE INTO A WITH TIMEOUT ; MKY_GETDATA: - LD B,MKY_WAITTO ; SETUP TO LOOP + LD B, MKY_WAITTO ; SETUP TO LOOP MKY_GETDATA0: - CALL MKY_IST ; GET INPUT REGISTER STATUS - JR NZ,MKY_GETDATA1 ; BYTE PENDING, GO GET IT + MKY_IST ; GET INPUT REGISTER STATUS + JR NZ, MKY_GETDATA1 ; BYTE PENDING, GO GET IT CALL DELAY ; WAIT A BIT DJNZ MKY_GETDATA0 ; LOOP UNTIL COUNTER EXHAUSTED XOR A ; NO DATA, RETURN ZERO @@ -317,7 +340,7 @@ MKY_GETDATA1: ; GET A RAW DATA BYTE FROM KEYBOARD INTERFACE INTO A WITH NOTIMEOUT ; MKY_GETDATAX: - CALL MKY_IST ; GET INPUT REGISTER STATUS + MKY_IST ; GET INPUT REGISTER STATUS RET Z ; NOTHING THERE, DONE JR MKY_GETDATA1 ; GO GET IT @@ -660,36 +683,6 @@ MKY_DEC10B: XOR $20 ; FLIP BIT 5 TO SWAP UPPER/LOWER CASE LD (MKY_KEYCODE),A ; SAVE IT -; MKY_DEC11: ; HANDLE NUM PAD KEYS -; LD A,(MKY_STATE) ; GET THE CURRENT STATE FLAGS -; AND $7F;~MKY_NUMPAD ; ASSUME NOT A NUMPAD KEY, CLEAR THE NUMPAD BIT -; LD (MKY_STATE),A ; SAVE IT - -; LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE -; AND 11100000B ; ISOLATE TOP 3 BITS -; CP 11000000B ; IS IN NUMPAD RANGE? -; JR NZ,MKY_DEC12 ; NOPE, GET OUT - -; LD A,(MKY_STATE) ; LOAD THE CURRENT STATE FLAGS -; OR MKY_NUMPAD ; TURN ON THE NUMPAD BIT -; LD (MKY_STATE),A ; SAVE IT - -; AND MKY_NUMLCK ; IS NUM LOCK BIT SET? -; JR Z,MKY_DEC11A ; NO, SKIP NUMLOCK PROCESSING -; LD A,(MKY_KEYCODE) ; GET THE KEYCODE -; XOR $10 ; FLIP VALUES FOR NUMLOCK -; LD (MKY_KEYCODE),A ; SAVE IT - -; MKY_DEC11A: ; APPLY NUMPAD MAPPING -; LD A,(MKY_KEYCODE) ; GET THE CURRENT KEYCODE -; LD HL,MKY_MAPNUMPAD ; LOAD THE START OF THE MAPPING TABLE -; SUB $C0 ; KEYCODES START AT $C0 -; LD E,A ; INDEX TO E -; LD D,0 ; D IS ZERO -; ADD HL,DE ; POINT TO RESULT OF MAPPING -; LD A,(HL) ; GET IT IN A -; LD (MKY_KEYCODE),A ; SAVE IT - MKY_DEC12: ; DETECT UNKNOWN/INVALID KEYCODES LD A,(MKY_KEYCODE) ; GET THE FINAL KEYCODE CP $FF ; IS IT $FF (UNKNOWN/INVALID) @@ -712,21 +705,21 @@ MKY_DECNEW: ; START NEW KEYPRESS (CLEAR ALL STATUS BITS) ;__________________________________________________________________________________________________ ; INTERRUPT HANDLER ; -; IF MKY_SCANBUFFF HAS CONTENT, DO NOTHING -; OTHERWISE, SCAN KEYBOARD AND IF A KEY EVENT IS DETECTED -; WRITE SCANCODES TO MKY_SCANBUFFF +; SCAN KEYBOARD AND IN THE NEWKEY SCAN STATS ; -; ALSO GENERATE KEY REPEAT EVENTS, IF KEY HELD DOWN -; -; NB: THIS HANDLER IS QUITE EXPENSIVE IN TIME -; AND CAN IMPACT SERIAL OPERATION FOR 115200 BAUD RATE FOR CPU AT 8MHZ ;__________________________________________________________________________________________________ ; MKY_INT: - LD A, (MKY_SCANON) ; OPTIMISATION - ONLY SCAN IF REQUIRED + LD A, (MKY_RPTACTIVE) ; NO REPEAT KEY IS HELD? OR A - RET Z + JR Z, MKY_INTSCAN1 + LD A, (MKY_RPTCNT) ; DECREMENT REPEAT COUNTER + DEC A ; DOWN TO ZERO + CP $FF + JR Z, MKY_INTSCAN1 + LD (MKY_RPTCNT), A +MKY_INTSCAN1: LD A, (MKY_SCNCNT) ; SCAN THE KEYBOARD EVERY 'SCAN_INT_PERIOD' INTERRUPTS. DEC A LD (MKY_SCNCNT), A @@ -735,16 +728,8 @@ MKY_INT: LD A, SCAN_INT_PERIOD LD (MKY_SCNCNT), A - LD A, (MKY_SCANBUFFLEN) ; SKIP SCANNING UNTIL CODE BUFFER IS EMPTY - OR A - RET NZ - - EX AF, AF' - PUSH AF -; ; SCAN KEYBOARD AND STORE ALL COLUMN RESULTS PER ROW AT MKY_NEWKEY ; -; MKY_SCAN: IN A, (MKY_REGC) ; READ AND MASK THE CURRENT STATE OF PPI PORT C AND $F0 LD D, A @@ -759,12 +744,8 @@ MKY_SCAN_LP: INC D DJNZ MKY_SCAN_LP ; LOOP UNTIL ALL ROWS READ - CALL MKY_GENSCODE - -MKY_INT_END: - CALL MKY_RPTGEN - POP AF - EX AF, AF' + LD A, $FF ; NOTE THAT A SCAN HAS BEEN DONE + LD (MKY_SCANNED), A RET ; @@ -772,20 +753,20 @@ MKY_INT_END: ; COMPARE MKY_OLDKEY O MKY_NEWKEY ; GENERATE SCAN CODES ; -; FOR EACH BIT IN MKY_OLDKEY ND MKY_NEWKEY +; FOR EACH BIT IN MKY_OLDKEY CP WITH CORRESPONDING BIT IN MKY_SCNKEY ; IF BOTH = 1, THEN NO KEY PRESS - NOTHING CHANGED ; IF BOTH = 0, THEN KEY WAS AND IS STILL PRESSED - NOTHING CHANGED -; IF OLD = 1 AND NEW = 0, KEY WAS PRESSED -; IF OLD = 0 AND NEW = 1, KEY WAS RELEASED -; STOP OF FIRST CHANGE - STORE IN BUFFER - THEN NOTHING HAPPENS, -; UNTIL MKY_RDSCAN IS CALLED AND CLEARS THE SCAN BUFFER -; ALSO RESET MKY_RPTACTIVE IS A KEY IS HELD DOWN +; IF OLD = 1 AND SCN = 0, KEY WAS PRESSED +; IF OLD = 0 AND SCN = 1, KEY WAS RELEASED +; STOP OF FIRST CHANGE - STORE IN BUFFER, AND RESET/CLEAR BIT IN MKY_OLDKEY +; ALSO SET MKY_RPTACTIVE. NZ -> A KEY IS HELD DOWN, ZERO -> NO KEYS HELD DOWN +; MKY_GENSCODE: XOR A LD (MKY_RPTACTIVE), A ; CLEAR FLAG TO INDICATE A KEYHOLD STATE LD HL, MKY_OLDKEY - LD DE, MKY_NEWKEY + LD DE, MKY_SCNKEY XOR A EX AF, AF' ; ROW COUNT IN A' @@ -856,11 +837,18 @@ MKY_NORPT: JR MKY_GENSCODENXT MKY_KEYDOWN: + PUSH AF + LD A, KEY_REPEAT_INIT ; SET COUNTER FOR REPEAT TRIGGER + LD (MKY_RPTCNT), A + POP AF + +MKY_KEYDOWN_RPT: CALL MKY_RESOLDBIT CALL MKY_SCANADDR LD A, (HL) OR A ; IF NO SCANCODE - IGNORE IT RET Z + LD (MKY_SCANBUFF), A LD A, 1 LD (MKY_SCANBUFFLEN), A @@ -887,27 +875,20 @@ MKY_RPTGEN: LD A, (MKY_RPTACTIVE) ; NO KEY IS HELD OR A - JR Z, MKY_RPTCLR + RET Z LD A, (MKY_RPTCNT) - DEC A - JR Z, MKY_RPTADD - LD (MKY_RPTCNT), A - RET + OR A + RET NZ -MKY_RPTADD: + ; GENERATE THE KEY DOWN SCAN CODE FOR THE REPEATING KEY LD A, KEY_REPEAT_PERIOD LD (MKY_RPTCNT), A LD A, (MKY_NRPTCOL) LD B, A LD A, (MKY_NRPTROW) EX AF, AF' - JR MKY_KEYDOWN - -MKY_RPTCLR: - LD A, KEY_REPEAT_INIT - LD (MKY_RPTCNT), A - RET + JR MKY_KEYDOWN_RPT ; ;__________________________________________________________________________________________________ ; @@ -917,14 +898,16 @@ MKY_RPTCLR: ; B = 1 TO 8 - COLUMN COUNT ; A' IS ROW COUNT - 0 TO MATRIX_ROW_COUNT ; OUTPUT: -; HL = BYTE WITHIN MKY_OLDKEY RRAY +; HL = BYTE WITHIN MKY_OLDKEY ARRAY ; A = BIT MASK FOR COLUMN COUNT (EG: B = 3, A = 8) ; PROTECTS: ; A' IS UNCHANGED ; B IS UNCHANGED + MKY_GETKEYIDX: + LD HL, MKY_OLDKEY LD A, $80 - LD D, B ; SAVE B (COLUMN COUNT - 1 TO 8) + LD C, B ; SAVE B (COLUMN COUNT - 1 TO 8) MKY_SETOLDBIT_LP: DEC B JR Z, SKIP @@ -932,39 +915,36 @@ MKY_SETOLDBIT_LP: JR MKY_SETOLDBIT_LP SKIP: - LD HL, MKY_OLDKEY EX AF, AF' ; RETRIEVE ROW COUNT - LD C, A + LD E, A EX AF, AF' - LD B, 0 - ADD HL, BC - LD B, D ; RETORE B (COLUMN COUNT) + LD D, 0 + LD B, C ; RETORE B (COLUMN COUNT) + ADD HL, DE RET ; ;__________________________________________________________________________________________________ ; ; SET BIT WITHIN THE KEY MATRIX ARRAY -; HL -> ADDRESS WITHIN MKY_OLDKEY R MKY_NEWKEY ARRAY +; HL -> ADDRESS WITHIN MKY_OLDKEY ARRAY ; C BIT MASK TO BE OR'ED ; MKY_SETOLDBIT: CALL MKY_GETKEYIDX - LD C, (HL) - OR C + OR (HL) LD (HL), A RET ; ;__________________________________________________________________________________________________ ; ; RESET BIT WITHIN THE KEY MATRIX ARRAY -; HL -> ADDRESS WITHIN MKY_OLDKEY R MKY_NEWKEY ARRAY +; HL -> ADDRESS WITHIN MKY_OLDKEY ARRAY ; C CPL BIT MASK TO BE AND'ED ; MKY_RESOLDBIT: CALL MKY_GETKEYIDX - LD C, (HL) CPL - AND C + AND (HL) LD (HL), A RET ; @@ -1014,19 +994,26 @@ MKY_READBYT: ; DYNAMIC DATA STORAGE: ; ; STORAGE OF KEYBOARD MATRIX, USED FOR DETECTING KEY REPETITION -MKY_OLDKEY: .FILL MATRIX_ROW_COUNT, $FF +MKY_OLDKEY: .FILL MATRIX_ROW_COUNT, $FF ; ; CURRENT STATE OF THE KEYBOARD MATRIX -MKY_NEWKEY: .FILL MATRIX_ROW_COUNT, $FF +MKY_NEWKEY: .FILL MATRIX_ROW_COUNT, $FF +; +; COPY OF MKY_NEWKEY FOR USE IN GENERATING SCANCODE +MKY_SCNKEY: .FILL MATRIX_ROW_COUNT, $FF +; +; SET TO NZ WHEN A SCAN IS COMPLETED +; SET TO ZERO AFTER A SCAN CODE CONVERSION +MKY_SCANNED: .DB 0 ; ; F3F6: VDP-INTERUPT COUNTER THAT COUNTS FROM SCAN_INT_PERIOD TO 0, WHEN IT REACHES ZERO, THE ; KEYBOARD MATRIX IS SCANNED, AND THE COUNTERS IS RESET AT SCAN_INT_PERIOD -MKY_SCNCNT: .DB SCAN_INT_PERIOD +MKY_SCNCNT: .DB SCAN_INT_PERIOD ; INITIALL SET TO FALSE, AND THUS DISABLING INTERRUPT HANDLER'S SCAN FUNCTION ; AS SOON AT THE KEY REQUEST FUNCTIONS (STATUS, READ), THIS IS SET AND INTERRUPT HANDLER ; IS PERMANETLY ON. -MKY_SCANON: .DB 0 +; MKY_SCANON: .DB 0 ; MKY_NRPTCOL: .DB 0 @@ -1081,9 +1068,6 @@ MKY_MAPEXT: ; PAIRS ARE [SCANCODE,KEYCODE] FOR EXTENDED SCANCODES .DB $74,$F9, $75,$F6, $7A,$F5, $7C,$ED .DB $7D,$F4, $7E,$FD, $00,$00 ; -; MKY_MAPNUMPAD: ; KEYCODE TRANSLATION FROM NUMPAD RANGE TO STD ASCII/KEYCODES -; .DB $F3,$F7,$F5,$F8,$FF,$F9,$F2,$F6,$F4,$F0,$F1,$2F,$2A,$2D,$2B,$0D -; .DB $31,$32,$33,$34,$35,$36,$37,$38,$39,$30,$2E,$2F,$2A,$2D,$2B,$0D #ENDIF #IF (MKYKBLOUT == KBD_DE) ;__________________________________________________________________________________________________ @@ -1126,11 +1110,6 @@ MKY_MAPEXT: ; PAIRS ARE [SCANCODE,KEYCODE] FOR EXTENDED SCANCODES .DB $74,$04, $75,$05, $7A,$1A, $7C,$ED ; Cursor right , Cursor up , Page down .DB $7D,$17, $7E,$FD, $00,$00 ; Page up , n.a. , END MKY_MAPEXT (Pairs end) ; -; MKY_MAPNUMPAD: ; KEYCODE TRANSLATION FROM NUMPAD RANGE TO STD ASCII/KEYCODES - -; .DB $F3,$F7,$F5,$F8,$FF,$F9,$F2,$F6,$F4,$F0,$F1,$2F,$2A,$2D,$2B,$0D -; .DB $31,$32,$33,$34,$35,$36,$37,$38,$39,$30,$2E,$2F,$2A,$2D,$2B,$0D -; #ENDIF ; ;__________________________________________________________________________________________________ From 3e0771acf39f8ab46f97397b3a81ef61c54043fa Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Wed, 25 Nov 2020 23:18:49 +1100 Subject: [PATCH 09/10] V9958: Updated TMS driver to support V9958 --- Source/HBIOS/hbios.asm | 3 +- Source/HBIOS/hbios.inc | 1 + Source/HBIOS/std.asm | 5 +-- Source/HBIOS/tms.asm | 78 ++++++++++++++++++++++++++++++++---------- 4 files changed, 66 insertions(+), 21 deletions(-) diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index bcca366c..72d55f97 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -5635,13 +5635,14 @@ PIO_MODE_STR: .TEXT "Output$" ; VIDEO DEVICE STRINGS ; PS_VDSTRREF: - .DW PS_VDVDU, PS_VDCVDU, PS_VDNEC, PS_VDTMS, PS_VDVGA + .DW PS_VDVDU, PS_VDCVDU, PS_VDNEC, PS_VDTMS, PS_VDVGA, PS_VDV9958 ; PS_VDVDU .TEXT "VDU$" PS_VDCVDU .TEXT "CVDU$" PS_VDNEC .TEXT "NEC$" PS_VDTMS .TEXT "TMS$" PS_VDVGA .TEXT "VGA$" +PS_VDV9958 .TEXT "V9958-$" ; ; VIDEO TYPE STRINGS ; diff --git a/Source/HBIOS/hbios.inc b/Source/HBIOS/hbios.inc index 78678921..ffb6bb9d 100644 --- a/Source/HBIOS/hbios.inc +++ b/Source/HBIOS/hbios.inc @@ -200,6 +200,7 @@ VDADEV_CVDU .EQU $10 ; ECB COLOR VDU - MOS 8563 VDADEV_NEC .EQU $20 ; ECB UPD7220 - NEC UPD7220 VDADEV_TMS .EQU $30 ; N8 ONBOARD VDA SUBSYSTEM - TMS 9918 VDADEV_VGA .EQU $40 ; ECB VGA3 - HITACHI HD6445 +VDADEV_V9958 .EQU $50 ; V9958 VDU ; ; SOUND DEVICE IDS ; diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index f31412a2..c8e09bf9 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -199,7 +199,8 @@ AYMODE_MSX .EQU 5 ; RC2014 SOUND MODULE REV6 BY ED BRINDLEY ON Z80/Z180 AT MSX TMSMODE_NONE .EQU 0 TMSMODE_SCG .EQU 1 ; SCG ECB BOARD TMSMODE_N8 .EQU 2 ; N8 BUILT-IN VIDEO -TMSMODE_RC .EQU 3 ; RC2014 BUILT-IN VIDEO +TMSMODE_RC .EQU 3 ; RC2014 TMS9918 VIDEO BOARD +TMSMODE_RCV9958 .EQU 4 ; RC2014 V9958 VIDEO BOARD ; ; SERIAL DEVICE CONFIGURATION CONSTANTS ; @@ -427,7 +428,7 @@ SYSTIM .SET TM_CTC #IF (TMSENABLE & (INTMODE == 1)) #IF (TMSTIMENABLE) SYSTIM .SET TM_TMS - .ECHO " TMS9918" + .ECHO " TMS9918/V9958" #ENDIF #ENDIF ; diff --git a/Source/HBIOS/tms.asm b/Source/HBIOS/tms.asm index 62aab029..44d21d83 100644 --- a/Source/HBIOS/tms.asm +++ b/Source/HBIOS/tms.asm @@ -1,5 +1,5 @@ ;====================================================================== -; N8 VDU DRIVER FOR SBC PROJECT +; TM9918 AND V9958 VDU DRIVER ; ; WRITTEN BY: DOUGLAS GOODALL ; UPDATED BY: WAYNE WARTHEN -- 4/7/2013 @@ -19,10 +19,10 @@ TMSCTRL1: .EQU 1 ; CONTROL BITS TMSINTEN: .EQU 5 ; INTERRUPT ENABLE BIT #IF TMSTIMENABLE - .ECHO "TMS INTERRUPTS ENABLED\n" + .ECHO "TMS/V9958 INTERRUPTS ENABLED\n" #ENDIF -#IF (TMSMODE == TMSMODE_RC) +#IF ((TMSMODE == TMSMODE_RC) | (TMSMODE == TMSMODE_RCV9958)) TMS_DATREG .EQU $98 ; READ/WRITE DATA TMS_CMDREG .EQU $99 ; READ STATUS / WRITE REG SEL TMS_PPIA .EQU 0 ; PPI PORT A @@ -58,14 +58,21 @@ TMS_PPIX .EQU 0 ; PPI CONTROL PORT #ENDIF ; TMS_ROWS .EQU 24 + +#IF (TMSMODE == TMSMODE_RCV9958) +TMS_FNTVADDR .EQU $1000 ; VRAM ADDRESS OF FONT DATA +TMS_COLS .EQU 80 +#ELSE +TMS_FNTVADDR .EQU $0800 ; VRAM ADDRESS OF FONT DATA TMS_COLS .EQU 40 +#ENDIF ; #DEFINE USEFONT8X8 #DEFINE TMS_FONT FONT8X8 ; TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER ; -; TMS_IODELAY IS USED TO ADD RECOVERY TIME TO TMS9918 ACCESSES +; TMS_IODELAY IS USED TO ADD RECOVERY TIME TO TMS9918/V9958 ACCESSES ; IF YOU SEE SCREEN CORRUPTION, ADJUST THIS!!! ; #IF (CPUFAM == CPU_Z180) @@ -73,7 +80,11 @@ TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER #DEFINE TMS_IODELAY EX (SP),HL \ EX (SP),HL ; 38 W/S #ELSE ; BELOW WAS TUNED FOR SBC AT 8MHZ -#DEFINE TMS_IODELAY NOP \ NOP ; 8 W/S +#IF (TMSMODE == TMSMODE_RCV9958) +#DEFINE TMS_IODELAY NOP \ NOP \ NOP \ NOP \ NOP \ NOP \ NOP ; V9958 NEEDS AT WORST CASE, APPROX 4us (28T) DELAY BETWEEN I/O (WHEN IN TEXT MODE) +#ELSE +#DEFINE TMS_IODELAY NOP \ NOP ; 8 W/S +#ENDIF #ENDIF ; ;====================================================================== @@ -101,7 +112,11 @@ TMS_INIT: LD IY,TMS_IDAT ; POINTER TO INSTANCE DATA ; CALL NEWLINE ; FORMATTING +#IF (TMSMODE == TMSMODE_RCV9958) + PRTS("V9958: IO=0x$") +#ELSE PRTS("TMS: IO=0x$") +#ENDIF LD A,TMS_DATREG CALL PRTHEXBYTE CALL TMS_PROBE ; CHECK FOR HW EXISTENCE @@ -149,12 +164,6 @@ TMS_INIT1: ; XOR A ; SIGNAL SUCCESS RET - -#IF TMSTIMENABLE - ; DISABLE INTERRUPT -TMS_INT_DIS: - -#ENDIF ; ;====================================================================== ; TMS DRIVER - VIDEO DISPLAY ADAPTER (VDA) FUNCTIONS @@ -230,7 +239,11 @@ TMS_VDARES1: ; ENTRY POINT TO AVOID TMS_Z180IO RECURSION RET TMS_VDADEV: +#IF (TMSMODE == TMSMODE_RCV9958) + LD D, VDADEV_V9958 +#ELSE LD D,VDADEV_TMS ; D := DEVICE TYPE +#ENDIF LD E,0 ; E := PHYSICAL UNIT IS ALWAYS ZERO LD H,TMSMODE ; H := MODE LD L,TMS_DATREG ; L := BASE I/O ADDRESS @@ -366,6 +379,14 @@ TMS_SET: ;---------------------------------------------------------------------- ; TMS_WR: +#IF (TMSMODE == TMSMODE_RCV9958) + ; CLEAR R#14 FOR V9958 + XOR A + OUT (TMS_CMDREG), A + LD A, $80 | 14 + OUT (TMS_CMDREG), A +#ENDIF + PUSH HL SET 6,H ; SET WRITE BIT CALL TMS_RD @@ -450,8 +471,8 @@ TMS_CRTINIT2: ;---------------------------------------------------------------------- ; TMS_LOADFONT: - ; SET WRITE ADDRESS TO $800 - LD HL,$800 + ; SET WRITE ADDRESS TO TMS_FNTVADDR + LD HL,TMS_FNTVADDR CALL TMS_WR #IF USELZSA2 @@ -470,8 +491,8 @@ TMS_LOADFONT: LD HL,TMS_FONT ; START OF FONT DATA #ENDIF ; - ; FILL $800 BYTES FROM FONTDATA - LD DE,$800 + ; FILL TMS_FNTVADDR BYTES FROM FONTDATA + LD DE,TMS_FNTVADDR TMS_LOADFONT1: LD A,(HL) OUT (TMS_DATREG),A @@ -532,7 +553,7 @@ TMS_SETCUR0: ; MULT BY 8 FOR FONT INDEX SLA L ; SHIFT LSB INTO CARRY RL H ; SHFT MSB FROM CARRY DJNZ TMS_SETCUR0 ; LOOP 3 TIMES - LD DE,$800 ; OFFSET TO START OF FONT TABLE + LD DE,TMS_FNTVADDR ; OFFSET TO START OF FONT TABLE ADD HL,DE ; ADD TO FONT INDEX CALL TMS_RD ; SETUP TO READ GLYPH LD B,8 ; 8 BYTES @@ -545,7 +566,7 @@ TMS_SETCUR1: ; READ GLYPH LOOP DJNZ TMS_SETCUR1 ; LOOP FOR 8 BYTES ; ; NOW WRITE INVERTED GLYPH INTO FONT INDEX 255 - LD HL,$800 + (255 * 8) ; LOC OF GLPYPH DATA FOR CHAR 255 + LD HL,TMS_FNTVADDR + (255 * 8) ; LOC OF GLPYPH DATA FOR CHAR 255 CALL TMS_WR ; SETUP TO WRITE THE INVERTED GLYPH LD B,8 ; 8 BYTES PER GLYPH LD HL,TMS_BUF ; POINT TO BUFFER @@ -891,16 +912,33 @@ TMS_PORTS: ; 5S Fifth sprite (not displayed) detected. Value in FS* is valid. ; INT Set at each screen update, used for interrupts. ; +#IF (TMSMODE == TMSMODE_RCV9958) TMS_INIT9918: + .DB $04 ; REG 0 - NO EXTERNAL VID, SET M4 = 1 +TMS_INIT9918_REG_1: + .DB $50 ; REG 1 - ENABLE SCREEN, SET MODE 1 + .DB $03 ; REG 2 - PATTERN NAME TABLE := 0 + .DB $00 ; REG 3 - NO COLOR TABLE + .DB $02 ; REG 4 - SET PATTERN GENERATOR TABLE TO (TMS_FNTVADDR -> $1000) + .DB $00 ; REG 5 - SPRITE ATTRIBUTE IRRELEVANT + .DB $00 ; REG 6 - NO SPRITE GENERATOR TABLE + .DB $F0 ; REG 7 - WHITE ON BLACK + + .DB $88 ; REG 8 - COLOUR BUS INPUT, DRAM 64K + .DB $00 ; REG 9 + .DB $00 ; REG 10 - COLOUR TABLE A14-A16 (TMS_FNTVADDR - $1000) + +#ELSE ; TMS REGISTER SET .DB $00 ; REG 0 - NO EXTERNAL VID TMS_INIT9918_REG_1: .DB $50 ; REG 1 - ENABLE SCREEN, SET MODE 1 .DB $00 ; REG 2 - PATTERN NAME TABLE := 0 .DB $00 ; REG 3 - NO COLOR TABLE - .DB $01 ; REG 4 - SET PATTERN GENERATOR TABLE TO $800 + .DB $01 ; REG 4 - SET PATTERN GENERATOR TABLE TO (TMS_FNTVADDR -> $0800) .DB $00 ; REG 5 - SPRITE ATTRIBUTE IRRELEVANT .DB $00 ; REG 6 - NO SPRITE GENERATOR TABLE .DB $F0 ; REG 7 - WHITE ON BLACK +#ENDIF ; TMS_INIT9918LEN .EQU $ - TMS_INIT9918 ; @@ -909,6 +947,10 @@ TMS_INIT9918LEN .EQU $ - TMS_INIT9918 TMS_DCNTL .DB $00 ; SAVE Z180 DCNTL AS NEEDED #ENDIF +#IF (TMSMODE == TMSMODE_RCV9958) + .ECHO "V9958 instance data occupies " +#ELSE .ECHO "TMS instance data occupies " +#ENDIF .ECHO $ - TMS_IDAT .ECHO " bytes\n" From 53d4f657af84f9d1cbc8b711dae4a48a0c09da6e Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Sat, 22 May 2021 15:57:54 +1000 Subject: [PATCH 10/10] V9958/KEYBOARD: Added disabled entries in RCZ80_std.asm for the V9958, MSX-KEYBOARD and RP5C01 RTC modules --- Source/HBIOS/Config/RCZ80_std.asm | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Source/HBIOS/Config/RCZ80_std.asm b/Source/HBIOS/Config/RCZ80_std.asm index c0380d6b..efd68211 100644 --- a/Source/HBIOS/Config/RCZ80_std.asm +++ b/Source/HBIOS/Config/RCZ80_std.asm @@ -45,3 +45,14 @@ IDEENABLE .SET TRUE ; IDE: ENABLE IDE DISK DRIVER (IDE.ASM) PPIDEENABLE .SET TRUE ; PPIDE: ENABLE PARALLEL PORT IDE DISK DRIVER (PPIDE.ASM) ; PRPENABLE .SET FALSE ; PRP: ENABLE ECB PROPELLER IO BOARD DRIVER (PRP.ASM) + + +TMSENABLE .SET FALSE ; TMS: ENABLE TMS9918/V9958 VIDEO/KBD DRIVER (TMS.ASM) +TMSMODE .SET TMSMODE_RCV9958 ; TMS: DRIVER MODE: TMSMODE_[RC/RCV9958] +TMSTIMENABLE .SET FALSE ; MS: ENABLE TIMER INTERRUPTS (REQUIRES IM1) +CRTACT .SET FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP +VDAEMU .SET EMUTYP_TTY ; VDA EMULATION: EMUTYP_[TTY|ANSI] + +RP5RTCENABLE .SET FALSE ; RP5C01 RTC BASED CLOCK (RP5RTC.ASM) + +MSKENABLE .SET FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER)