From 8173414bf53b013f10052fe242735e1e20e15ef9 Mon Sep 17 00:00:00 2001 From: Dean Netherton Date: Wed, 11 Nov 2020 19:36:59 +1100 Subject: [PATCH] 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 ;