Browse Source

MSX-KEYBOARD: some optimisation of interrupt handler

patch
Dean Netherton 5 years ago
parent
commit
8173414bf5
  1. 267
      Source/HBIOS/msxkeyb.asm

267
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
;

Loading…
Cancel
Save