mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 14:11:48 -06:00
Reintegrate wbw -> trunk
This commit is contained in:
@@ -77,6 +77,12 @@ INITSYS1:
|
||||
#IF (HDSKENABLE)
|
||||
CALL HDSK_INIT
|
||||
#ENDIF
|
||||
#IF (PPKENABLE)
|
||||
CALL PPK_INIT
|
||||
#ENDIF
|
||||
#IF (KBDENABLE)
|
||||
CALL KBD_INIT
|
||||
#ENDIF
|
||||
#IF (TTYENABLE)
|
||||
CALL TTY_INIT
|
||||
#ENDIF
|
||||
@@ -586,6 +592,24 @@ SIZ_HDSK .EQU $ - ORG_HDSK
|
||||
.ECHO " bytes.\n"
|
||||
#ENDIF
|
||||
|
||||
#IF (PPKENABLE)
|
||||
ORG_PPK .EQU $
|
||||
#INCLUDE "ppk.asm"
|
||||
SIZ_PPK .EQU $ - ORG_PPK
|
||||
.ECHO "PPK occupies "
|
||||
.ECHO SIZ_PPK
|
||||
.ECHO " bytes.\n"
|
||||
#ENDIF
|
||||
|
||||
#IF (KBDENABLE)
|
||||
ORG_KBD .EQU $
|
||||
#INCLUDE "kbd.asm"
|
||||
SIZ_KBD .EQU $ - ORG_KBD
|
||||
.ECHO "KBD occupies "
|
||||
.ECHO SIZ_KBD
|
||||
.ECHO " bytes.\n"
|
||||
#ENDIF
|
||||
|
||||
#IF (TTYENABLE)
|
||||
ORG_TTY .EQU $
|
||||
#INCLUDE "tty.asm"
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU TRUE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU TRUE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU TRUE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU TRUE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU TRUE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU TRUE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU TRUE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU TRUE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU TRUE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU TRUE ; TRUE FOR HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
@@ -78,6 +78,9 @@ HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT
|
||||
HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
|
||||
HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB)
|
||||
;
|
||||
PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD
|
||||
KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242
|
||||
;
|
||||
TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT
|
||||
ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT
|
||||
;
|
||||
|
||||
743
Source/kbd.asm
Normal file
743
Source/kbd.asm
Normal file
@@ -0,0 +1,743 @@
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
; 8242 BASED PS/2 KEYBOARD DRIVER FOR N8VEM
|
||||
;
|
||||
; ORIGINAL CODE BY DR JAMES MOXHAM
|
||||
; ROMWBW ADAPTATION BY WAYNE WARTHEN
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
; TODO:
|
||||
; CONSIDER DETECTING ERRORS IN STATUS BYTE (PERR, TO)
|
||||
;__________________________________________________________________________________________________
|
||||
; DATA CONSTANTS
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
; IO PORTS
|
||||
;
|
||||
KBD_IOBASE .EQU $E0
|
||||
;
|
||||
KBD_ST .EQU KBD_IOBASE + $0A
|
||||
KBD_CMD .EQU KBD_IOBASE + $0A
|
||||
KBD_DATA .EQU KBD_IOBASE + $02
|
||||
;
|
||||
; TIMING CONSTANTS
|
||||
;
|
||||
KBD_WAITTO .EQU 150
|
||||
;
|
||||
; STATUS BITS (FOR KBD_STATUS)
|
||||
;
|
||||
KBD_EXT .EQU 01H ; BIT 0, EXTENDED SCANCODE ACTIVE
|
||||
KBD_BREAK .EQU 02H ; BIT 1, THIS IS A KEY UP (BREAK) EVENT
|
||||
KBD_KEYRDY .EQU 80H ; BIT 7, INDICATES A DECODED KEYCODE IS READY
|
||||
;
|
||||
; STATE BITS (FOR KBD_STATE, KBD_LSTATE, KBD_RSTATE)
|
||||
;
|
||||
KBD_SHIFT .EQU 01H ; BIT 0, SHIFT ACTIVE (PRESSED)
|
||||
KBD_CTRL .EQU 02H ; BIT 1, CONTROL ACTIVE (PRESSED)
|
||||
KBD_ALT .EQU 04H ; BIT 2, ALT ACTIVE (PRESSED)
|
||||
KBD_WIN .EQU 08H ; BIT 3, WIN ACTIVE (PRESSED)
|
||||
KBD_SCRLCK .EQU 10H ; BIT 4, CAPS LOCK ACTIVE (TOGGLED ON)
|
||||
KBD_NUMLCK .EQU 20H ; BIT 5, NUM LOCK ACTIVE (TOGGLED ON)
|
||||
KBD_CAPSLCK .EQU 40H ; BIT 6, SCROLL LOCK ACTIVE (TOGGLED ON)
|
||||
KBD_NUMPAD .EQU 80H ; BIT 7, NUM PAD KEY (KEY PRESSED IS ON NUM PAD)
|
||||
;
|
||||
KBD_DEFRPT .EQU $40 ; DEFAULT REPEAT RATE (.5 SEC DELAY, 30CPS)
|
||||
KBD_DEFSTATE .EQU KBD_NUMLCK ; DEFAULT STATE (NUM LOCK ON)
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; DATA
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
KBD_SCANCODE .DB 0 ; RAW SCANCODE
|
||||
KBD_KEYCODE .DB 0 ; RESULTANT KEYCODE AFTER DECODING
|
||||
KBD_STATE .DB 0 ; STATE BITS (SEE ABOVE)
|
||||
KBD_LSTATE .DB 0 ; STATE BITS FOR "LEFT" KEYS
|
||||
KBD_RSTATE .DB 0 ; STATE BITS FOR "RIGHT" KEYS
|
||||
KBD_STATUS .DB 0 ; CURRENT STATUS BITS (SEE ABOVE)
|
||||
KBD_REPEAT .DB 0 ; CURRENT REPEAT RATE
|
||||
KBD_IDLE .DB 0 ; IDLE COUNT
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; KEYBOARD INITIALIZATION
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
KBD_INIT:
|
||||
LD A,KBD_DEFRPT ; GET DEFAULT REPEAT RATE
|
||||
LD (KBD_REPEAT),A ; SAVE IT
|
||||
LD A,KBD_DEFSTATE ; GET DEFAULT STATE
|
||||
LD (KBD_STATE),A ; SAVE IT
|
||||
|
||||
LD A,$AA ; CONTROLLER SELF TEST
|
||||
CALL KBD_PUTCMD ; SEND IT
|
||||
CALL KBD_GETDATA ; CONTROLLER SHOULD RESPOND WITH $55 (ACK)
|
||||
LD A,$60 ; SET COMMAND REGISTER
|
||||
CALL KBD_PUTCMD ; SEND IT
|
||||
LD A,$60 ; XLAT ENABLED, MOUSE DISABLED, NO INTS
|
||||
CALL KBD_PUTDATA ; SEND IT
|
||||
|
||||
CALL KBD_GETDATA ; GOBBLE UP $AA FROM POWER UP, AS NEEDED
|
||||
|
||||
; LD A,$AE ; COMMAND = ENABLE KEYBOARD
|
||||
; CALL KBD_PUTCMD ; SEND IT
|
||||
; LD A,$A7 ; COMMAND = DISABLE MOUSE
|
||||
; CALL KBD_PUTCMD ; SEND IT
|
||||
|
||||
CALL KBD_RESET ; RESET THE KEYBOARD
|
||||
CALL KBD_SETLEDS ; UPDATE LEDS BASED ON CURRENT TOGGLE STATE BITS
|
||||
CALL KBD_SETRPT ; UPDATE REPEAT RATE BASED ON CURRENT SETTING
|
||||
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; KEYBOARD STATUS
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
KBD_STAT:
|
||||
LD A,(KBD_STATUS) ; GET STATUS
|
||||
AND KBD_KEYRDY ; ISOLATE READY BIT
|
||||
JR NZ,KBD_STAT3 ; KEY READY, DONE
|
||||
|
||||
KBD_STAT2:
|
||||
CALL Z,KBD_DECODE ; NOT READY, RUN THE DECODING ENGINE
|
||||
LD A,(KBD_STATUS) ; GET STATUS
|
||||
AND KBD_KEYRDY ; ISOLATE READ BIT
|
||||
|
||||
KBD_STAT3:
|
||||
RLCA ; ROTATE READY BIT TO LOW ORDER BIT
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; KEYBOARD READ
|
||||
;
|
||||
; RETURNS ASCII VALUE IN E. SEE END OF FILE FOR VALUES RETURNED FOR SPECIAL KEYS
|
||||
; LIKE PGUP, ARROWS, FUNCTION KEYS, ETC.
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
KBD_READ:
|
||||
; CALL KBD_STAT ; CHECK TO SEE IF KEY READY
|
||||
LD A,(KBD_STATUS) ; GET STATUS
|
||||
AND KBD_KEYRDY ; ISOLIATE KEY READY BIT
|
||||
JR NZ,KBD_READ1 ; READY, GO GET THE KEY AND RETURN
|
||||
CALL KBD_DECODE ; TRY TO GET A KEY
|
||||
JR KBD_READ ; AND LOOP
|
||||
;
|
||||
KBD_READ1:
|
||||
LD A,(KBD_KEYCODE) ; GET KEYCODE
|
||||
LD E,A ; SAVE IT IN E
|
||||
LD A,(KBD_STATE) ; GET STATE FLAGS
|
||||
LD D,A ; SAVE THEM IN D
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
LD (KBD_STATUS),A ; CLEAR STATUS TO INDICATE BYTE RECEIVED
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; KEYBOARD FLUSH
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
KBD_FLUSH:
|
||||
XOR A ; A = 0
|
||||
LD (KBD_STATUS),A ; CLEAR STATUS
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; HARDWARE INTERFACE
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
KBD_IST:
|
||||
;
|
||||
; KEYBOARD INPUT STATUS
|
||||
; A=0, Z SET FOR NOTHING PENDING, OTHERWISE DATA PENDING
|
||||
;
|
||||
IN A,(KBD_ST) ; GET STATUS
|
||||
AND $01 ; ISOLATE INPUT PENDING BIT
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
KBD_OST:
|
||||
;
|
||||
; KEYBOARD OUTPUT STATUS
|
||||
; A=0, Z SET FOR NOT READY, OTHERWISE READY TO WRITE
|
||||
;
|
||||
IN A,(KBD_ST) ; GET STATUS
|
||||
AND $02 ; ISOLATE OUTPUT EMPTY BIT
|
||||
XOR $02 ; FLIP IT FOR APPROPRIATE RETURN VALUES
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
KBD_PUTCMD:
|
||||
;
|
||||
; PUT A CMD BYTE FROM A TO THE KEYBOARD INTERFACE WITH TIMEOUT
|
||||
;
|
||||
LD E,A ; SAVE INCOMING VALUE IN E
|
||||
LD B,KBD_WAITTO ; SETUP TO LOOP
|
||||
KBD_PUTCMD0:
|
||||
CALL KBD_OST ; GET OUTPUT REGISTER STATUS
|
||||
JR NZ,KBD_PUTCMD1 ; EMPTY, GO TO WRITE
|
||||
CALL DELAY ; WAIT A BIT
|
||||
DJNZ KBD_PUTCMD0 ; LOOP UNTIL COUNTER EXHAUSTED
|
||||
RET
|
||||
KBD_PUTCMD1:
|
||||
LD A,E ; RECOVER VALUE TO WRITE
|
||||
#IFDEF KBD_DEBUG
|
||||
CALL PC_SPACE
|
||||
CALL PC_GT
|
||||
CALL PC_GT
|
||||
CALL PRTHEXBYTE
|
||||
#ENDIF
|
||||
OUT (KBD_CMD),A ; WRITE IT
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
KBD_PUTDATA:
|
||||
;
|
||||
; PUT A DATA BYTE FROM A TO THE KEYBOARD INTERFACE WITH TIMEOUT
|
||||
;
|
||||
LD E,A ; SAVE INCOMING VALUE IN E
|
||||
LD B,KBD_WAITTO ; SETUP TO LOOP
|
||||
KBD_PUTDATA0:
|
||||
CALL KBD_OST ; GET OUTPUT REGISTER STATUS
|
||||
JR NZ,KBD_PUTDATA1 ; EMPTY, GO TO WRITE
|
||||
CALL DELAY ; WAIT A BIT
|
||||
DJNZ KBD_PUTDATA0 ; LOOP UNTIL COUNTER EXHAUSTED
|
||||
RET
|
||||
KBD_PUTDATA1:
|
||||
LD A,E ; RECOVER VALUE TO WRITE
|
||||
#IFDEF KBD_DEBUG
|
||||
CALL PC_SPACE
|
||||
CALL PC_GT
|
||||
CALL PRTHEXBYTE
|
||||
#ENDIF
|
||||
OUT (KBD_DATA),A ; WRITE IT
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
KBD_GETDATA:
|
||||
;
|
||||
; GET A RAW DATA BYTE FROM KEYBOARD INTERFACE INTO A WITH TIMEOUT
|
||||
;
|
||||
LD B,KBD_WAITTO ; SETUP TO LOOP
|
||||
KBD_GETDATA0:
|
||||
CALL KBD_IST ; GET INPUT REGISTER STATUS
|
||||
JR NZ,KBD_GETDATA1 ; BYTE PENDING, GO GET IT
|
||||
CALL DELAY ; WAIT A BIT
|
||||
DJNZ KBD_GETDATA0 ; LOOP UNTIL COUNTER EXHAUSTED
|
||||
XOR A ; NO DATA, RETURN ZERO
|
||||
RET
|
||||
KBD_GETDATA1:
|
||||
IN A,(KBD_DATA) ; GET THE DATA VALUE
|
||||
#IFDEF KBD_DEBUG
|
||||
PUSH AF
|
||||
CALL PC_SPACE
|
||||
CALL PC_LT
|
||||
CALL PRTHEXBYTE
|
||||
POP AF
|
||||
#ENDIF
|
||||
OR A ; SET FLAGS
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; RESET KEYBOARD
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
KBD_RESET:
|
||||
LD A,$FF ; RESET COMMAND
|
||||
CALL KBD_PUTDATA ; SEND IT
|
||||
CALL KBD_GETDATA ; GET THE ACK
|
||||
LD B,0 ; SETUP LOOP COUNTER
|
||||
PPK_RESET0:
|
||||
PUSH BC ; PRESERVE COUNTER
|
||||
CALL KBD_GETDATA ; TRY TO GET THE RESPONSE
|
||||
POP BC ; RECOVER COUNTER
|
||||
JR NZ,PPK_RESET1 ; GOT A BYTE? IF SO, GET OUT OF LOOP
|
||||
DJNZ PPK_RESET0 ; LOOP TILL COUNTER EXHAUSTED
|
||||
PPK_RESET1:
|
||||
LD A,B
|
||||
XOR A ; SIGNAL SUCCESS (RESPONSE IS IGNORED...)
|
||||
RET ; DONE
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; UPDATE KEYBOARD LEDS BASED ON CURRENT TOGGLE FLAGS
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
KBD_SETLEDS:
|
||||
LD A,$ED ; SET/RESET LED'S COMMAND
|
||||
CALL KBD_PUTDATA ; SEND THE COMMAND
|
||||
CALL KBD_GETDATA ; READ THE RESPONSE
|
||||
CP $FA ; MAKE SURE WE GET ACK
|
||||
RET NZ ; ABORT IF NO ACK
|
||||
LD A,(KBD_STATE) ; LOAD THE STATE BYTE
|
||||
RRCA ; ROTATE TOGGLE KEY BITS AS NEEDED
|
||||
RRCA
|
||||
RRCA
|
||||
RRCA
|
||||
AND $07 ; CLEAR THE IRRELEVANT BITS
|
||||
CALL KBD_PUTDATA ; SEND THE LED DATA
|
||||
CALL KBD_GETDATA ; READ THE ACK
|
||||
JP KBD_DECNEW ; RESTART DECODER FOR A NEW KEY
|
||||
RET ; DONE
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; UPDATE KEYBOARD REPEAT RATE BASED ON CURRENT SETTING
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
KBD_SETRPT:
|
||||
LD A,$F3 ; COMMAND = SET TYPEMATIC RATE/DELAY
|
||||
CALL KBD_PUTDATA ; SEND IT
|
||||
CALL KBD_GETDATA ; GET THE ACK
|
||||
CP $FA ; MAKE SURE WE GET ACK
|
||||
RET NZ ; ABORT IF NO ACK
|
||||
LD A,(KBD_REPEAT) ; LOAD THE CURRENT RATE/DELAY BYTE
|
||||
CALL KBD_PUTDATA ; SEND IT
|
||||
CALL KBD_GETDATA ; GET THE ACK
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; DECODING ENGINE
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
KBD_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 KBD_KEYCODE AND KBD_STATE.
|
||||
;
|
||||
; KBD_STATUS IS NOT CLEARED AT START. IT IS THE CALLER'S RESPONSIBILITY
|
||||
; TO CLEAR KBD_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[<modifier>] = 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[<toggle>]
|
||||
; 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
|
||||
;
|
||||
KBD_DEC0: ; CHECK KEYCODE BUFFER
|
||||
LD A,(KBD_STATUS) ; GET CURRENT STATUS
|
||||
AND KBD_KEYRDY ; ISOLATE KEY READY FLAG
|
||||
RET NZ ; ABORT IF KEY IS ALREADY PENDING
|
||||
|
||||
KBD_DEC1: ; PROCESS NEXT SCANCODE
|
||||
CALL KBD_IST ; IS A SCANCODE WAITING?
|
||||
RET Z ; NOPE, ABORT
|
||||
CALL KBD_GETDATA ; GET THE SCANCODE
|
||||
RET Z ; TIMEOUT, RETURN WITH A=0, Z SET
|
||||
LD (KBD_SCANCODE),A ; SAVE SCANCODE
|
||||
|
||||
KBD_DEC2: ; DETECT AND HANDLE SPECIAL KEYCODES
|
||||
LD A,(KBD_SCANCODE) ; GET THE CURRENT SCANCODE
|
||||
CP $AA ; KEYBOARD INSERTION?
|
||||
JR NZ,KBD_DEC3 ; NOPE, BYPASS
|
||||
CALL KBD_RESET ; RESET KEYBOARD
|
||||
CALL KBD_SETLEDS ; SET LEDS
|
||||
CALL KBD_SETRPT ; SET REPEAT RATE
|
||||
JP KBD_DECNEW ; RESTART THE ENGINE
|
||||
|
||||
KBD_DEC3: ; DETECT AND HANDLE SCANCODE PREFIXES
|
||||
LD A,(KBD_SCANCODE) ; GET THE CURRENT SCANCODE
|
||||
|
||||
KBD_DEC3A: ; HANDLE SCANCODE PREFIX $E0 (EXTENDED SCANCODE FOLLOWS)
|
||||
CP $E0 ; EXTENDED KEY PREFIX $E0?
|
||||
JR NZ,KBD_DEC3B ; NOPE MOVE ON
|
||||
LD A,(KBD_STATUS) ; GET STATUS
|
||||
OR KBD_EXT ; SET EXTENDED BIT
|
||||
LD (KBD_STATUS),A ; SAVE STATUS
|
||||
JR KBD_DEC1 ; LOOP TO DO NEXT SCANCODE
|
||||
|
||||
KBD_DEC3B: ; HANDLE SCANCODE PREFIX $E1 (PAUSE KEY)
|
||||
CP $E1 ; EXTENDED KEY PREFIX $E1
|
||||
JR NZ,KBD_DEC4 ; NOPE MOVE ON
|
||||
LD A,$EE ; MAP TO KEYCODE $EE
|
||||
LD (KBD_KEYCODE),A ; SAVE IT
|
||||
; SWALLOW NEXT 5 SCANCODES
|
||||
LD B,5 ; LOOP 5 TIMES
|
||||
KBD_DEC3B1:
|
||||
PUSH BC
|
||||
CALL KBD_GETDATA ; RETRIEVE NEXT SCANCODE
|
||||
POP BC
|
||||
DJNZ KBD_DEC3B1 ; LOOP AS NEEDED
|
||||
JP KBD_DEC6 ; RESUME AFTER MAPPING
|
||||
|
||||
KBD_DEC4: ; DETECT AND FLAG BREAK EVENT
|
||||
LD A,(KBD_SCANCODE)
|
||||
LD E,A ; SAVE SCANCODE IN E
|
||||
RES 7,A ; CLEAR THE BREAK BIT FROM THE KEYCODE
|
||||
LD (KBD_SCANCODE),A ; SAVE UPDATED SCANCODE
|
||||
LD A,E ; RECOVER ORIGINAL SCANCODE
|
||||
AND $80 ; ISOLATE BREAK BIT
|
||||
RLCA ; ROTATE BIT TO POSITION...
|
||||
RLCA ; OF BREAK BIT IN STATUS
|
||||
LD E,A ; SAVE IT IN E
|
||||
LD A,(KBD_STATUS) ; GET THE STATUS FLAGS
|
||||
AND ~KBD_BREAK ; CLEAR THE BREAK BIT
|
||||
OR E ; OR IN NEW BREAK BIT
|
||||
LD (KBD_STATUS),A ; SAVE IT
|
||||
|
||||
KBD_DEC5: ; MAP SCANCODE TO KEYCODE
|
||||
LD A,(KBD_STATUS) ; GET STATUS
|
||||
AND KBD_EXT ; EXTENDED BIT SET?
|
||||
JR Z,KBD_DEC5C ; NOPE, MOVE ON
|
||||
|
||||
; PERFORM EXTENDED KEY MAPPING
|
||||
LD A,(KBD_SCANCODE) ; GET SCANCODE
|
||||
LD E,A ; STASH IT IN E
|
||||
LD HL,KBD_MAPEXT ; POINT TO START OF EXT MAP TABLE
|
||||
KBD_DEC5A:
|
||||
LD A,(HL) ; GET FIRST BYTE OF PAIR
|
||||
CP $00 ; END OF TABLE?
|
||||
JP Z,KBD_DECNEW ; UNKNOWN OR BOGUS, START OVER
|
||||
INC HL ; INC HL FOR FUTURE
|
||||
CP E ; DOES MATCH BYTE EQUAL SCANCODE?
|
||||
JR Z,KBD_DEC5B ; YES! JUMP OUT
|
||||
INC HL ; BUMP TO START OF NEXT PAIR
|
||||
JR KBD_DEC5A ; LOOP TO CHECK NEXT TABLE ENTRY
|
||||
KBD_DEC5B:
|
||||
LD A,(HL) ; GET THE KEYCODE VIA MAPPING TABLE
|
||||
LD (KBD_KEYCODE),A ; SAVE IT
|
||||
JR KBD_DEC6
|
||||
|
||||
KBD_DEC5C: ; PERFORM REGULAR KEY (NOT EXTENDED) KEY MAPPING
|
||||
LD A,(KBD_SCANCODE) ; GET THE SCANCODE
|
||||
CP KBD_MAPSIZ ; COMPARE TO SIZE OF TABLE
|
||||
JR NC,KBD_DEC6 ; PAST END, SKIP OVER LOOKUP
|
||||
|
||||
; SETUP POINTER TO MAPPING TABLE BASED ON SHIFTED OR UNSHIFTED STATE
|
||||
LD A,(KBD_STATE) ; GET STATE
|
||||
AND KBD_SHIFT ; SHIFT ACTIVE?
|
||||
LD HL,KBD_MAPSTD ; LOAD ADDRESS OF NON-SHIFTED MAPPING TABLE
|
||||
JR Z,KBD_DEC5D ; NON-SHIFTED, MOVE ON
|
||||
LD HL,KBD_MAPSHIFT ; LOAD ADDRESS OF SHIFTED MAPPING TABLE
|
||||
KBD_DEC5D:
|
||||
LD A,(KBD_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 (KBD_KEYCODE),A ; SAVE IT
|
||||
|
||||
KBD_DEC6: ; HANDLE MODIFIER KEYS
|
||||
LD A,(KBD_KEYCODE) ; MAKE SURE WE HAVE KEYCODE
|
||||
CP $B8 ; END OF MODIFIER KEYS
|
||||
JR NC,KBD_DEC7 ; BYPASS MODIFIER KEY CHECKING
|
||||
CP $B0 ; START OF MODIFIER KEYS
|
||||
JR C,KBD_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
|
||||
|
||||
KBD_DEC6A:
|
||||
RLC E ; SHIFT TO NEXT MODIFIER STATE BIT
|
||||
DEC A ; L-MODIFIER?
|
||||
JR Z,KBD_DEC6B ; YES, HANDLE L-MODIFIER MAKE/BREAK
|
||||
DEC A ; R-MODIFIER?
|
||||
JR Z,KBD_DEC6C ; YES, HANDLE R-MODIFIER MAKE/BREAK
|
||||
DJNZ KBD_DEC6A ; LOOP THRU 4 MODIFIER BITS
|
||||
JR KBD_DEC7 ; FAILSAFE, SHOULD NEVER GET HERE!
|
||||
|
||||
KBD_DEC6B: ; LEFT STATE KEY MAKE/BREAK (STATE BIT TO SET/CLEAR IN E)
|
||||
LD HL,KBD_LSTATE ; POINT TO LEFT STATE BYTE
|
||||
JR KBD_DEC6D ; CONTINUE
|
||||
|
||||
KBD_DEC6C: ; RIGHT STATE KEY MAKE/BREAK (STATE BIT TO SET/CLEAR IN E)
|
||||
LD HL,KBD_RSTATE ; POINT TO RIGHT STATE BYTE
|
||||
JR KBD_DEC6D ; CONTINUE
|
||||
|
||||
KBD_DEC6D: ; BRANCH BASED ON WHETHER THIS IS A MAKE OR BREAK EVENT
|
||||
LD A,(KBD_STATUS) ; GET STATUS FLAGS
|
||||
AND KBD_BREAK ; BREAK EVENT?
|
||||
JR Z,KBD_DEC6E ; NO, HANDLE A MODIFIER KEY MAKE EVENT
|
||||
JR KBD_DEC6F ; YES, HANDLE A MODIFIER BREAK EVENT
|
||||
|
||||
KBD_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 KBD_DEC6G ; CONTINUE
|
||||
|
||||
KBD_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 KBD_DEC6G ; CONTINUE
|
||||
|
||||
KBD_DEC6G: ; COALESCE L/R STATE FLAGS
|
||||
LD A,(KBD_STATE) ; GET EXISTING STATE BITS
|
||||
AND $F0 ; GET RID OF OLD MODIFIER BITS
|
||||
LD DE,(KBD_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 (KBD_STATE),A ; SAVE IT
|
||||
JP KBD_DECNEW ; DONE WITH CURRENT KEYSTROKE
|
||||
|
||||
KBD_DEC7: ; COMPLETE PROCESSING OF EXTENDED AND KEY BREAK EVENTS
|
||||
LD A,(KBD_STATUS) ; GET CURRENT STATUS FLAGS
|
||||
AND KBD_BREAK ; IS THIS A KEY BREAK EVENT?
|
||||
JP NZ,KBD_DECNEW ; PROCESS NEXT KEY
|
||||
|
||||
KBD_DEC8: ; HANDLE TOGGLE KEYS
|
||||
LD A,(KBD_KEYCODE) ; GET THE CURRENT KEYCODE INTO A
|
||||
LD E,KBD_CAPSLCK ; SETUP E WITH CAPS LOCK STATE BIT
|
||||
CP $BC ; IS THIS THE CAPS LOCK KEY?
|
||||
JR Z,KBD_DEC8A ; YES, GO TO BIT SET ROUTINE
|
||||
LD E,KBD_NUMLCK ; SETUP E WITH NUM LOCK STATE BIT
|
||||
CP $BD ; IS THIS THE NUM LOCK KEY?
|
||||
JR Z,KBD_DEC8A ; YES, GO TO BIT SET ROUTINE
|
||||
LD E,KBD_SCRLCK ; SETUP E WITH SCROLL LOCK STATE BIT
|
||||
CP $BE ; IS THIS THE SCROLL LOCK KEY?
|
||||
JR Z,KBD_DEC8A ; YES, GO TO BIT SET ROUTINE
|
||||
JR KBD_DEC9 ; NOT A TOGGLE KEY, CONTINUE
|
||||
|
||||
KBD_DEC8A: ; RECORD THE TOGGLE
|
||||
LD A,(KBD_STATE) ; GET THE CURRENT STATE FLAGS
|
||||
XOR E ; SET THE TOGGLE KEY BIT FROM ABOVE
|
||||
LD (KBD_STATE),A ; SAVE IT
|
||||
CALL KBD_SETLEDS ; UPDATE LED LIGHTS ON KBD
|
||||
JP KBD_DECNEW ; RESTART DECODER FOR A NEW KEY
|
||||
|
||||
KBD_DEC9: ; ADJUST KEYCODE FOR CONTROL MODIFIER
|
||||
LD A,(KBD_STATE) ; GET THE CURRENT STATE BITS
|
||||
AND KBD_CTRL ; CHECK THE CONTROL BIT
|
||||
JR Z,KBD_DEC10 ; CONTROL KEY NOT PRESSED, MOVE ON
|
||||
LD A,(KBD_KEYCODE) ; GET CURRENT KEYCODE IN A
|
||||
CP 'a' ; COMPARE TO LOWERCASE A
|
||||
JR C,KBD_DEC9A ; BELOW IT, BYPASS
|
||||
CP 'z' + 1 ; COMPARE TO LOWERCASE Z
|
||||
JR NC,KBD_DEC9A ; ABOVE IT, BYPASS
|
||||
RES 5,A ; KEYCODE IN LOWERCASE A-Z RANGE CLEAR BIT 5 TO MAKE IT UPPERCASE
|
||||
KBD_DEC9A:
|
||||
CP '@' ; COMPARE TO @
|
||||
JR C,KBD_DEC10 ; BELOW IT, BYPASS
|
||||
CP '_' + 1 ; COMPARE TO _
|
||||
JR NC,KBD_DEC10 ; ABOVE IT, BYPASS
|
||||
RES 6,A ; CONVERT TO CONTROL VALUE BY CLEARING BIT 6
|
||||
LD (KBD_KEYCODE),A ; UPDATE KEYCODE TO CONTROL VALUE
|
||||
|
||||
KBD_DEC10: ; ADJUST KEYCODE FOR CAPS LOCK
|
||||
LD A,(KBD_STATE) ; LOAD THE STATE FLAGS
|
||||
AND KBD_CAPSLCK ; CHECK CAPS LOCK
|
||||
JR Z,KBD_DEC11 ; CAPS LOCK NOT ACTIVE, MOVE ON
|
||||
LD A,(KBD_KEYCODE) ; GET THE CURRENT KEYCODE VALUE
|
||||
CP 'a' ; COMPARE TO LOWERCASE A
|
||||
JR C,KBD_DEC10A ; BELOW IT, BYPASS
|
||||
CP 'z' + 1 ; COMPARE TO LOWERCASE Z
|
||||
JR NC,KBD_DEC10A ; ABOVE IT, BYPASS
|
||||
JR KBD_DEC10B ; IN RANGE LOWERCASE A-Z, GO TO CASE SWAPPING LOGIC
|
||||
KBD_DEC10A:
|
||||
CP 'A' ; COMPARE TO UPPERCASE A
|
||||
JR C,KBD_DEC11 ; BELOW IT, BYPASS
|
||||
CP 'Z' + 1 ; COMPARE TO UPPERCASE Z
|
||||
JR NC,KBD_DEC11 ; ABOVE IT, BYPASS
|
||||
JR KBD_DEC10B ; IN RANGE UPPERCASE A-Z, GO TO CASE SWAPPING LOGIC
|
||||
KBD_DEC10B:
|
||||
LD A,(KBD_KEYCODE) ; GET THE CURRENT KEYCODE
|
||||
XOR $20 ; FLIP BIT 5 TO SWAP UPPER/LOWER CASE
|
||||
LD (KBD_KEYCODE),A ; SAVE IT
|
||||
|
||||
KBD_DEC11: ; HANDLE NUM PAD KEYS
|
||||
LD A,(KBD_STATE) ; GET THE CURRENT STATE FLAGS
|
||||
AND ~KBD_NUMPAD ; ASSUME NOT A NUMPAD KEY, CLEAR THE NUMPAD BIT
|
||||
LD (KBD_STATE),A ; SAVE IT
|
||||
|
||||
LD A,(KBD_KEYCODE) ; GET THE CURRENT KEYCODE
|
||||
AND 11100000B ; ISOLATE TOP 3 BITS
|
||||
CP 11000000B ; IS IN NUMPAD RANGE?
|
||||
JR NZ,KBD_DEC12 ; NOPE, GET OUT
|
||||
|
||||
LD A,(KBD_STATE) ; LOAD THE CURRENT STATE FLAGS
|
||||
OR KBD_NUMPAD ; TURN ON THE NUMPAD BIT
|
||||
LD (KBD_STATE),A ; SAVE IT
|
||||
|
||||
AND KBD_NUMLCK ; IS NUM LOCK BIT SET?
|
||||
JR Z,KBD_DEC11A ; NO, SKIP NUMLOCK PROCESSING
|
||||
LD A,(KBD_KEYCODE) ; GET THE KEYCODE
|
||||
XOR $10 ; FLIP VALUES FOR NUMLOCK
|
||||
LD (KBD_KEYCODE),A ; SAVE IT
|
||||
|
||||
KBD_DEC11A: ; APPLY NUMPAD MAPPING
|
||||
LD A,(KBD_KEYCODE) ; GET THE CURRENT KEYCODE
|
||||
LD HL,KBD_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 (KBD_KEYCODE),A ; SAVE IT
|
||||
|
||||
KBD_DEC12: ; DETECT UNKNOWN/INVALID KEYCODES
|
||||
LD A,(KBD_KEYCODE) ; GET THE FINAL KEYCODE
|
||||
CP $FF ; IS IT $FF (UNKNOWN/INVALID)
|
||||
JP Z,KBD_DECNEW ; IF SO, JUST RESTART THE ENGINE
|
||||
|
||||
KBD_DEC13: ; DONE - RECORD RESULTS
|
||||
LD A,(KBD_STATUS) ; GET CURRENT STATUS
|
||||
OR KBD_KEYRDY ; SET KEY READY BIT
|
||||
LD (KBD_STATUS),A ; SAVE IT
|
||||
XOR A ; A=0
|
||||
INC A ; SIGNAL SUCCESS WITH A=1
|
||||
RET
|
||||
|
||||
KBD_DECNEW: ; START NEW KEYPRESS (CLEAR ALL STATUS BITS)
|
||||
XOR A ; A = 0
|
||||
LD (KBD_STATUS),A ; CLEAR STATUS
|
||||
JP KBD_DEC1 ; RESTART THE ENGINE
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; MAPPING TABLES
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
KBD_MAPSTD: ; SCANCODE IS INDEX INTO TABLE TO RESULTANT LOOKUP KEYCODE
|
||||
.DB $FF,$1B,'1','2','3','4','5','6','7','8','9','0','-','=',$08,$09
|
||||
.DB 'q','w','e','r','t','y','u','i','o','p','[',']',$0D,$B2,'a','s'
|
||||
.DB 'd','f','g','h','j','k','l',';',$27,'`',$B0,'\','z','x','c','v'
|
||||
.DB 'b','n','m',',','.','/',$B1,$CC,$B4,' ',$BC,$E0,$E1,$E2,$E3,$E4
|
||||
.DB $E5,$E6,$E7,$E8,$E9,$BD,$BE,$C6,$C7,$C8,$CD,$C3,$C4,$C5,$CE,$C0
|
||||
.DB $C1,$C2,$C9,$CA,$EC,$FF,$FF,$FA,$EB
|
||||
;
|
||||
KBD_MAPSIZ .EQU ($ - KBD_MAPSTD)
|
||||
;
|
||||
KBD_MAPSHIFT: ; SCANCODE IS INDEX INTO TABLE TO RESULTANT LOOKUP KEYCODE WHEN SHIFT ACTIVE
|
||||
.DB $FF,$1B,'!','@','#','$','%','^','&','*','(',')','_','+',$08,$09
|
||||
.DB 'Q','W','E','R','T','Y','U','I','O','P','{','}',$0D,$B2,'A','S'
|
||||
.DB 'D','F','G','H','J','K','L',':',$22,'~',$B0,'|','Z','X','C','V'
|
||||
.DB 'B','N','M','<','>','?',$B1,$DC,$B4,' ',$BC,$E0,$E1,$E2,$E3,$E4
|
||||
.DB $E5,$E6,$E7,$E8,$E9,$BD,$BE,$D6,$D7,$D8,$DD,$D3,$D4,$D5,$DE,$D0
|
||||
.DB $D1,$D2,$D9,$DA,$EC,$FF,$FF,$FA,$EB
|
||||
;
|
||||
KBD_MAPEXT: ; PAIRS ARE [SCANCODE,KEYCODE] FOR EXTENDED SCANCODES
|
||||
.DB $38,$B5, $1D,$B3, $5B,$B6, $5C,$B7
|
||||
.DB $5D,$EF, $5E,$FA, $5F,$FB, $35,$CB
|
||||
.DB $1C,$CF, $63,$FC, $4F,$F3, $4B,$F8
|
||||
.DB $47,$F2, $52,$F0, $53,$F1, $50,$F7
|
||||
.DB $4D,$F9, $48,$F6, $51,$F5, $37,$ED
|
||||
.DB $49,$F4, $46,$FD, $00,$00
|
||||
;
|
||||
KBD_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
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; 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
|
||||
@@ -386,11 +386,6 @@ RECOVER:
|
||||
POP BC
|
||||
RET
|
||||
|
||||
;__________________________________________________________________________________________________
|
||||
; IMBED COMMON PRALLEL PORT KEYBOARD DRIVER
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
#INCLUDE "ppk.asm"
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; LOCAL DRIVER DATA
|
||||
|
||||
393
Source/ppk.asm
393
Source/ppk.asm
@@ -7,10 +7,13 @@
|
||||
; ROMWBW ADAPTATION BY WAYNE WARTHEN
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
; TODO:
|
||||
;__________________________________________________________________________________________________
|
||||
; DATA CONSTANTS
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
; IO PORTS
|
||||
;
|
||||
#IF (PLATFORM == PLT_N8)
|
||||
PPK_PPI .EQU 084H ; PPI PORT BASE FOR N8
|
||||
#ELSE
|
||||
@@ -28,13 +31,55 @@ PPK_CLK .EQU 01111010B ; PPIX MASK TO MANAGE CLOCK LINE (C:5)
|
||||
PPK_WAITTO .EQU 50 * CPUFREQ ; TUNE!!! WANT SMALL AS POSSIBLE W/O ERRORS
|
||||
PPK_WAITRDY .EQU 10 * CPUFREQ ; TUNE!!! 100US LOOP DELAY TO ENSURE DEVICE READY
|
||||
;
|
||||
; STATUS BITS (FOR PPK_STATUS)
|
||||
;
|
||||
PPK_EXT .EQU 01H ; BIT 0, EXTENDED SCANCODE ACTIVE
|
||||
PPK_BREAK .EQU 02H ; BIT 1, THIS IS A KEY UP (BREAK) EVENT
|
||||
PPK_KEYRDY .EQU 80H ; BIT 7, INDICATES A DECODED KEYCODE IS READY
|
||||
;
|
||||
; STATE BITS (FOR PPK_STATE, PPK_LSTATE, PPK_RSTATE)
|
||||
;
|
||||
PPK_SHIFT .EQU 01H ; BIT 0, SHIFT ACTIVE (PRESSED)
|
||||
PPK_CTRL .EQU 02H ; BIT 1, CONTROL ACTIVE (PRESSED)
|
||||
PPK_ALT .EQU 04H ; BIT 2, ALT ACTIVE (PRESSED)
|
||||
PPK_WIN .EQU 08H ; BIT 3, WIN ACTIVE (PRESSED)
|
||||
PPK_SCRLCK .EQU 10H ; BIT 4, CAPS LOCK ACTIVE (TOGGLED ON)
|
||||
PPK_NUMLCK .EQU 20H ; BIT 5, NUM LOCK ACTIVE (TOGGLED ON)
|
||||
PPK_CAPSLCK .EQU 40H ; BIT 6, SCROLL LOCK ACTIVE (TOGGLED ON)
|
||||
PPK_NUMPAD .EQU 80H ; BIT 7, NUM PAD KEY (KEY PRESSED IS ON NUM PAD)
|
||||
;
|
||||
PPK_DEFRPT .EQU $40 ; DEFAULT REPEAT RATE (.5 SEC DELAY, 30CPS)
|
||||
PPK_DEFSTATE .EQU PPK_NUMLCK ; DEFAULT STATE (NUM LOCK ON)
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; DATA
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
PPK_SCANCODE .DB 0 ; RAW SCANCODE
|
||||
PPK_KEYCODE .DB 0 ; RESULTANT KEYCODE AFTER DECODING
|
||||
PPK_STATE .DB 0 ; STATE BITS (SEE ABOVE)
|
||||
PPK_LSTATE .DB 0 ; STATE BITS FOR "LEFT" KEYS
|
||||
PPK_RSTATE .DB 0 ; STATE BITS FOR "RIGHT" KEYS
|
||||
PPK_STATUS .DB 0 ; CURRENT STATUS BITS (SEE ABOVE)
|
||||
PPK_REPEAT .DB 0 ; CURRENT REPEAT RATE
|
||||
PPK_IDLE .DB 0 ; IDLE COUNT
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; KEYBOARD INITIALIZATION
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
PPK_INIT:
|
||||
CALL PPK_INITPORT ; SETS PORT C SO CAN INPUT AND OUTPUT
|
||||
CALL PPK_RESET ; RESET TO THE KEYBOARD
|
||||
|
||||
LD A,PPK_DEFRPT ; GET DEFAULT REPEAT RATE
|
||||
LD (PPK_REPEAT),A ; SAVE IT
|
||||
LD A,PPK_DEFSTATE ; GET DEFAULT STATE
|
||||
LD (PPK_STATE),A ; SAVE IT
|
||||
|
||||
CALL PPK_RESET ; RESET THE KEYBOARD
|
||||
CALL PPK_SETLEDS ; UPDATE LEDS BASED ON CURRENT TOGGLE STATE BITS
|
||||
CALL PPK_SETRPT ; UPDATE REPEAT RATE BASED ON CURRENT SETTING
|
||||
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET
|
||||
;
|
||||
@@ -48,7 +93,7 @@ PPK_INIT:
|
||||
;
|
||||
PPK_STAT:
|
||||
LD A,(PPK_STATUS) ; GET STATUS
|
||||
AND PPK_KEYRDY ; ISOLATE READ BIT
|
||||
AND PPK_KEYRDY ; ISOLATE READY BIT
|
||||
JR NZ,PPK_STAT3 ; KEY READY, DONE
|
||||
|
||||
PPK_STAT1:
|
||||
@@ -89,7 +134,7 @@ PPK_READ1:
|
||||
LD A,(PPK_STATE) ; GET STATE FLAGS
|
||||
LD D,A ; SAVE THEM IN D
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
LD (PPK_STATUS),A ; CLEAR STATE TO INDICATE BYTE RECEIVED
|
||||
LD (PPK_STATUS),A ; CLEAR STATUS TO INDICATE BYTE RECEIVED
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
@@ -98,7 +143,7 @@ PPK_READ1:
|
||||
;
|
||||
PPK_FLUSH:
|
||||
XOR A ; A = 0
|
||||
LD (PPK_STATE),A ; CLEAR STATE
|
||||
LD (PPK_STATUS),A ; CLEAR STATUS
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
@@ -106,26 +151,24 @@ PPK_FLUSH:
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
PPK_GETBYTE:
|
||||
PPK_GETDATA:
|
||||
;
|
||||
; GET RAW BYTE FROM KEYBOARD INTERFACE INTO A
|
||||
; IF TIMEOUT, RETURN WITH A=0 AND Z SET
|
||||
;
|
||||
; ALL REGISTERS ARE DESTROYED
|
||||
;
|
||||
CALL PPK_CLKHI ; ALLOW KEYBOARD TO XMIT
|
||||
CALL PPK_WTCLKLO ; WAIT FOR CLOCK LINE TO GO LOW
|
||||
JP NZ,PPK_GETBYTE1 ; IF IT WENT LOW, READ THE BYTE
|
||||
JP NZ,PPK_GETDATA1 ; IF IT WENT LOW, READ THE BYTE
|
||||
CALL PPK_CLKLO ; SUPPRESS KEYBOARD XMIT
|
||||
XOR A ; SIGNAL TIMEOUT
|
||||
RET
|
||||
|
||||
PPK_GETBYTE1:
|
||||
PPK_GETDATA1:
|
||||
CALL PPK_WTCLKHI ; WAIT FOR END OF START BIT
|
||||
LD B,8 ; SAMPLE 8 TIMES
|
||||
LD E,0 ; START WITH E=0
|
||||
|
||||
PPK_GETBYTE2:
|
||||
PPK_GETDATA2:
|
||||
CALL PPK_WTCLKLO ; WAIT TILL CLOCK GOES LOW
|
||||
IN A,(PPK_PPIB) ; SAMPLE THE DATA LINE
|
||||
RRA ; MOVE THE DATA BIT INTO THE CARRY REGISTER
|
||||
@@ -133,7 +176,7 @@ PPK_GETBYTE2:
|
||||
RRA ; MOVE THE CARRY BIT INTO BIT 7 AND SHIFT RIGHT
|
||||
LD E,A ; STORE IT BACK AFTER 8 CYCLES 1ST BIT READ WILL BE IN B0
|
||||
CALL PPK_WTCLKHI ; WAIT TILL GOES HIGH
|
||||
DJNZ PPK_GETBYTE2 ; DO THIS 8 TIMES
|
||||
DJNZ PPK_GETDATA2 ; DO THIS 8 TIMES
|
||||
CALL PPK_WTCLKLO ; GET THE PARITY BIT
|
||||
CALL PPK_WTCLKHI
|
||||
CALL PPK_WTCLKLO ; GET THE STOP BIT
|
||||
@@ -151,11 +194,9 @@ PPK_GETBYTE2:
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
PPK_PUTBYTE:
|
||||
PPK_PUTDATA:
|
||||
;
|
||||
; PUT A RAW BYTE FROM A TO THE KEYBOARD INTERFACE
|
||||
;
|
||||
; ALL REGISTERS ARE DESTROYED
|
||||
;
|
||||
LD E,A ; STASH INCOMING BYTE VALUE IN E
|
||||
|
||||
@@ -180,22 +221,22 @@ PPK_PUTBYTE:
|
||||
|
||||
; SEND DATA BITS
|
||||
LD B,8 ; 8 DATA BITS
|
||||
PPK_PUTBYTE1:
|
||||
PPK_PUTDATA1:
|
||||
RRC E ; ROTATE LOW BIT OF E TO CARRY (NEXT BIT TO SEND)
|
||||
LD A,PPK_DAT >> 1 ; INIT A WITH DATA MASK SHIFTED RIGHT BY ONE BIT
|
||||
RLA ; SHIFT CARRY INTO LOW BIT OF A
|
||||
OUT (PPK_PPIX),A ; SET/RESET DATA LINE FOR NEXT BIT VALUE
|
||||
CALL PPK_WTCLKHI ; WAIT FOR CLOCK TO TRANSTION HI
|
||||
CALL PPK_WTCLKLO ; THEN LO, BIT HAS NOW BEEN RECEIVED BY DEVICE
|
||||
DJNZ PPK_PUTBYTE1 ; LOOP TO SEND 8 DATA BITS
|
||||
DJNZ PPK_PUTDATA1 ; LOOP TO SEND 8 DATA BITS
|
||||
|
||||
; SEND PARITY BIT
|
||||
XOR A ; CLEAR A
|
||||
OR E ; OR WITH SENT VALUE, SETS PARITY FLAG!
|
||||
LD A,PPK_DAT ; PREPARE A WITH DATA MASK
|
||||
JP PO,PPK_PUTBYTE2 ; PARITY IS ALREADY ODD, LEAVE A ALONE
|
||||
JP PO,PPK_PUTDATA2 ; PARITY IS ALREADY ODD, LEAVE A ALONE
|
||||
INC A ; SET PARITY BIT BY INCREMENTING A
|
||||
PPK_PUTBYTE2:
|
||||
PPK_PUTDATA2:
|
||||
OUT (PPK_PPIX),A ; SET THE DATA LINE
|
||||
CALL PPK_WTCLKHI ; WAIT FOR CLOCK TO TRANSITION HI
|
||||
CALL PPK_WTCLKLO ; THEN LO, BIT HAS NOW BEEN RECEIVED BY DEVICE
|
||||
@@ -305,83 +346,104 @@ PPK_SETBIT:
|
||||
;
|
||||
PPK_RESET:
|
||||
LD A,$FF ; RESET COMMAND
|
||||
CALL PPK_PUTBYTE ; SEND IT
|
||||
CALL PPK_GETBYTE ; GET THE ACK
|
||||
CALL PPK_PUTDATA ; SEND IT
|
||||
CALL PPK_GETDATA ; GET THE ACK
|
||||
LD B,0 ; SETUP LOOP COUNTER
|
||||
PPK_RESET0:
|
||||
PUSH BC ; PRESERVE LOOP COUNTER
|
||||
PUSH BC ; PRESERVE COUNTER
|
||||
CALL DELAY ; DELAY 25MS
|
||||
CALL PPK_GETBYTE ; TRY TO GET $AA
|
||||
POP BC ; RESTORE LOOP COUNTER
|
||||
JR NZ,PPK_RESET1 ; GOT A BYTE? IF SO, DONE (WE IGNORE RESPONSE CODE VALUE)
|
||||
DJNZ PPK_RESET0 ; KEEP TRYING UNTIL COUNTER EXPIRES
|
||||
CALL PPK_GETDATA ; TRY TO GET THE RESPONSE
|
||||
POP BC ; RECOVER COUNTER
|
||||
JR NZ,PPK_RESET1 ; GOT A BYTE? IF SO, GET OUT OF LOOP
|
||||
DJNZ PPK_RESET0 ; LOOP TILL COUNTER EXHAUSTED
|
||||
PPK_RESET1:
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
LD A,B
|
||||
XOR A ; SIGNAL SUCCESS (RESPONSE IS IGNORED...)
|
||||
RET ; DONE
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; UPDATE KEYBOARD LEDS BASED ON CURRENT TOGGLE FLAGS
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
PPK_SETLEDS:
|
||||
LD A,$ED ; SET/RESET LED'S COMMAND
|
||||
CALL PPK_PUTDATA ; SEND THE COMMAND
|
||||
CALL PPK_GETDATA ; READ THE RESPONSE
|
||||
CP $FA ; MAKE SURE WE GET ACK
|
||||
RET NZ ; ABORT IF NO ACK
|
||||
LD A,(PPK_STATE) ; LOAD THE STATE BYTE
|
||||
RRCA ; ROTATE TOGGLE KEY BITS AS NEEDED
|
||||
RRCA
|
||||
RRCA
|
||||
RRCA
|
||||
AND $07 ; CLEAR THE IRRELEVANT BITS
|
||||
CALL PPK_PUTDATA ; SEND THE LED DATA
|
||||
CALL PPK_GETDATA ; READ THE ACK
|
||||
JP PPK_DECNEW ; RESTART DECODER FOR A NEW KEY
|
||||
RET ; DONE
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; UPDATE KEYBOARD REPEAT RATE BASED ON CURRENT SETTING
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
PPK_SETRPT:
|
||||
LD A,$F3 ; COMMAND = SET TYPEMATIC RATE/DELAY
|
||||
CALL PPK_PUTDATA ; SEND IT
|
||||
CALL PPK_GETDATA ; GET THE ACK
|
||||
CP $FA ; MAKE SURE WE GET ACK
|
||||
RET NZ ; ABORT IF NO ACK
|
||||
LD A,(PPK_REPEAT) ; LOAD THE CURRENT RATE/DELAY BYTE
|
||||
CALL PPK_PUTDATA ; SEND IT
|
||||
CALL PPK_GETDATA ; GET THE ACK
|
||||
RET
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; DECODING ENGINE
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
; STATUS BITS (FOR PPK_STATUS)
|
||||
;
|
||||
PPK_EXT .EQU 01H ; BIT 0, EXTENDED SCANCODE ACTIVE
|
||||
PPK_BREAK .EQU 02H ; BIT 1, THIS IS A KEY UP (BREAK) EVENT
|
||||
PPK_KEYRDY .EQU 80H ; BIT 7, INDICATES A DECODED KEYCODE IS READY
|
||||
;
|
||||
; STATE BITS (FOR PPK_STATE, PPK_LSTATE, PPK_RSTATE)
|
||||
;
|
||||
PPK_SHIFT .EQU 01H ; BIT 0, SHIFT ACTIVE (PRESSED)
|
||||
PPK_CTRL .EQU 02H ; BIT 1, CONTROL ACTIVE (PRESSED)
|
||||
PPK_ALT .EQU 04H ; BIT 2, ALT ACTIVE (PRESSED)
|
||||
PPK_WIN .EQU 08H ; BIT 3, WIN ACTIVE (PRESSED)
|
||||
PPK_SCRLCK .EQU 10H ; BIT 4, CAPS LOCK ACTIVE (TOGGLED ON)
|
||||
PPK_NUMLCK .EQU 20H ; BIT 5, NUM LOCK ACTIVE (TOGGLED ON)
|
||||
PPK_CAPSLCK .EQU 40H ; BIT 6, SCROLL LOCK ACTIVE (TOGGLED ON)
|
||||
PPK_NUMPAD .EQU 80H ; BIT 7, NUM PAD KEY (KEY PRESSED IS ON NUM PAD)
|
||||
;
|
||||
PPK_SCANCODE .DB 0 ; RAW SCANCODE
|
||||
PPK_KEYCODE .DB 0 ; RESULTANT KEYCODE AFTER DECODING
|
||||
PPK_STATE .DB 0 ; STATE BITS (SEE ABOVE)
|
||||
PPK_LSTATE .DB 0 ; STATE BITS FOR "LEFT" KEYS
|
||||
PPK_RSTATE .DB 0 ; STATE BITS FOR "RIGHT" KEYS
|
||||
PPK_STATUS .DB 0 ; CURRENT STATUS BITS (SEE ABOVE)
|
||||
PPK_IDLE .DB 0 ; IDLE COUNT
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
PPK_DECODE:
|
||||
;
|
||||
; RUN THE DECODING ENGINE UNTIL EITHER: 1) A TIMEOUT OCCURS TRYING TO GET SCANCODES
|
||||
; 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 TIMEOUT, OTHERWISE 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 PPK_KEYCODE AND PPK_STATE.
|
||||
;
|
||||
; PPK_KEYCODE AND PPK_STATUS ARE CLEARED AT START. IF IS THE CALLER'S RESPONSIBILITY
|
||||
; TO RETRIEVE ANY PRIOR VALUE BEFORE CALLING THIS FUNCTION AGAIN.
|
||||
; PPK_STATUS IS NOT CLEARED AT START. IT IS THE CALLER'S RESPONSIBILITY
|
||||
; TO CLEAR PPK_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: Initialize for next keypress
|
||||
; clear status ($00)
|
||||
; clear keycode ($FF)
|
||||
; Step 0: Check keycode buffer
|
||||
; if status[keyrdy]
|
||||
; return
|
||||
;
|
||||
; Step 1: Get scancode w/timeout
|
||||
; Step 1: Get scancode
|
||||
; if no scancode ready
|
||||
; return
|
||||
; read scancode
|
||||
; if timeout
|
||||
; return "timeout"
|
||||
;
|
||||
; Step 2: Detect and handle special keycodes
|
||||
; if scancode == $AA
|
||||
; *** handle hot insert somehow ***
|
||||
;
|
||||
; Step 2: Detect and flag break prefix
|
||||
; if scancode == $F0
|
||||
; set status[break]
|
||||
; goto Phase 1
|
||||
;
|
||||
; Step 3: Detect and flag extended prefix
|
||||
; Step 3: Detect and handle scancode prefixes
|
||||
; if scancode == $E0
|
||||
; set status[extended]
|
||||
; goto Phase 1
|
||||
; goto Step 1
|
||||
;
|
||||
; Step 4: Detect and handle $E1
|
||||
; if scancode == $E1
|
||||
; ***handle pause key somehow***
|
||||
; *** 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]
|
||||
@@ -396,75 +458,102 @@ PPK_DECODE:
|
||||
; set (l/r)state[<modifier>] = not status[break]
|
||||
; clear modifier bits in state
|
||||
; set state = (lstate OR rstate OR state)
|
||||
; goto Entry
|
||||
; goto New Key
|
||||
;
|
||||
; Step 7: Complete procesing of key break events
|
||||
; if status[break]
|
||||
; goto Entry
|
||||
; goto New Key
|
||||
;
|
||||
; Step 8: Handle toggle keys
|
||||
; if keycode is toggle (capslock, numlock, scrolllock)
|
||||
; invert (XOR) state[<toggle>]
|
||||
; update keyboard LED's
|
||||
; goto Entry
|
||||
; goto New Key
|
||||
;
|
||||
; Step 9: Handle control keys
|
||||
; 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 needed
|
||||
; 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
|
||||
; else
|
||||
; clear state[numpad]
|
||||
;
|
||||
; Step 12: Detect unknown/invalid keycodes
|
||||
; if keycode == $FF
|
||||
; goto Entry
|
||||
; goto New Key
|
||||
;
|
||||
; Step 13: Done
|
||||
; return "ready"
|
||||
; set status[keyrdy]
|
||||
; return
|
||||
;
|
||||
PPK_DEC0:
|
||||
XOR A ; A = ZERO
|
||||
LD (PPK_STATUS),A ; CLEAR STATUS
|
||||
DEC A ; A = $FF
|
||||
LD (PPK_KEYCODE),A ; CLEAR KEYCODE
|
||||
; New Key:
|
||||
; clear status
|
||||
; goto Step 1
|
||||
;
|
||||
PPK_DEC0: ; CHECK KEYCODE BUFFER
|
||||
LD A,(PPK_STATUS) ; GET CURRENT STATUS
|
||||
AND PPK_KEYRDY ; ISOLATE KEY READY FLAG
|
||||
RET NZ ; ABORT IF KEY IS ALREADY PENDING
|
||||
|
||||
PPK_DEC1: ; GET SCANCODE W/ TIMEOUT
|
||||
CALL PPK_GETBYTE ; GET A SCANCODE
|
||||
PPK_DEC1: ; PROCESS NEXT SCANCODE
|
||||
CALL PPK_GETDATA ; GET THE SCANCODE
|
||||
RET Z ; TIMEOUT, RETURN WITH A=0, Z SET
|
||||
LD (PPK_SCANCODE),A ; SAVE SCANCODE
|
||||
|
||||
PPK_DEC2: ; DETECT AND FLAG BREAK PREFIX $F0
|
||||
CP $F0 ; BREAK (KEY UP) PREFIX?
|
||||
JR NZ,PPK_DEC3 ; NOPE MOVE ON
|
||||
LD A,(PPK_STATUS) ; GET STATUS
|
||||
OR PPK_BREAK ; SET BREAK BIT
|
||||
LD (PPK_STATUS),A ; SAVE STATUS
|
||||
JR PPK_DEC1 ; LOOP TO DO NEXT SCANCODE
|
||||
PPK_DEC2: ; DETECT AND HANDLE SPECIAL KEYCODES
|
||||
LD A,(PPK_SCANCODE) ; GET THE CURRENT SCANCODE
|
||||
CP $AA ; KEYBOARD INSERTION?
|
||||
JR NZ,PPK_DEC3 ; NOPE, BYPASS
|
||||
CALL LDELAY ; WAIT A BIT
|
||||
CALL PPK_RESET ; RESET KEYBOARD
|
||||
CALL PPK_SETLEDS ; SET LEDS
|
||||
CALL PPK_SETRPT ; SET REPEAT RATE
|
||||
JP PPK_DECNEW ; RESTART THE ENGINE
|
||||
|
||||
PPK_DEC3: ; DETECT AND FLAG EXTENDED PREFIX $E0
|
||||
CP $E0 ; EXTENDED KEY PREFIX?
|
||||
JR NZ,PPK_DEC4 ; NOPE MOVE ON
|
||||
PPK_DEC3: ; DETECT AND HANDLE SCANCODE PREFIXES
|
||||
LD A,(PPK_SCANCODE) ; GET THE CURRENT SCANCODE
|
||||
|
||||
PPK_DEC3A: ; HANDLE SCANCODE PREFIX $E0 (EXTENDED SCANCODE FOLLOWS)
|
||||
CP $E0 ; EXTENDED KEY PREFIX $E0?
|
||||
JR NZ,PPK_DEC3B ; NOPE MOVE ON
|
||||
LD A,(PPK_STATUS) ; GET STATUS
|
||||
OR PPK_EXT ; SET EXTENDED BIT
|
||||
LD (PPK_STATUS),A ; SAVE STATUS
|
||||
JR PPK_DEC1 ; LOOP TO DO NEXT SCANCODE
|
||||
|
||||
PPK_DEC4: ; DETECT AND HANDLE EXTENDED PREFIX $E1
|
||||
; TODO: HANDLE PAUSE KEY HERE...
|
||||
PPK_DEC3B: ; HANDLE SCANCODE PREFIX $E1 (PAUSE KEY)
|
||||
CP $E1 ; EXTENDED KEY PREFIX $E1
|
||||
JR NZ,PPK_DEC4 ; NOPE MOVE ON
|
||||
LD A,$EE ; MAP TO KEYCODE $EE
|
||||
LD (PPK_KEYCODE),A ; SAVE IT
|
||||
; SWALLOW NEXT 7 SCANCODES
|
||||
LD B,7 ; LOOP 5 TIMES
|
||||
PPK_DEC3B1:
|
||||
PUSH BC
|
||||
CALL PPK_GETDATA ; RETRIEVE NEXT SCANCODE
|
||||
POP BC
|
||||
DJNZ PPK_DEC3B1 ; LOOP AS NEEDED
|
||||
JP PPK_DEC6 ; RESUME AFTER MAPPING
|
||||
|
||||
PPK_DEC4: ; DETECT AND FLAG BREAK EVENT
|
||||
CP $F0 ; BREAK (KEY UP) PREFIX?
|
||||
JR NZ,PPK_DEC5 ; NOPE MOVE ON
|
||||
LD A,(PPK_STATUS) ; GET STATUS
|
||||
OR PPK_BREAK ; SET BREAK BIT
|
||||
LD (PPK_STATUS),A ; SAVE STATUS
|
||||
JR PPK_DEC1 ; LOOP TO DO NEXT SCANCODE
|
||||
|
||||
PPK_DEC5: ; MAP SCANCODE TO KEYCODE
|
||||
LD A,(PPK_STATUS) ; GET STATUS
|
||||
@@ -478,7 +567,7 @@ PPK_DEC5: ; MAP SCANCODE TO KEYCODE
|
||||
PPK_DEC5A:
|
||||
LD A,(HL) ; GET FIRST BYTE OF PAIR
|
||||
CP $00 ; END OF TABLE?
|
||||
JP Z,PPK_DECODE ; UNKNOWN OR BOGUS, START OVER
|
||||
JP Z,PPK_DECNEW ; UNKNOWN OR BOGUS, START OVER
|
||||
INC HL ; INC HL FOR FUTURE
|
||||
CP E ; DOES MATCH BYTE EQUAL SCANCODE?
|
||||
JR Z,PPK_DEC5B ; YES! JUMP OUT
|
||||
@@ -491,8 +580,8 @@ PPK_DEC5B:
|
||||
|
||||
PPK_DEC5C: ; PERFORM REGULAR KEY (NOT EXTENDED) KEY MAPPING
|
||||
LD A,(PPK_SCANCODE) ; GET THE SCANCODE
|
||||
CP $85 ; PAST END OF TABLE?
|
||||
JR NC,PPK_DEC6 ; YES, SKIP OVER LOOKUP
|
||||
CP PPK_MAPSIZ ; COMPARE TO SIZE OF TABLE
|
||||
JR NC,PPK_DEC6 ; PAST END, SKIP OVER LOOKUP
|
||||
|
||||
; SETUP POINTER TO MAPPING TABLE BASED ON SHIFTED OR UNSHIFTED STATE
|
||||
LD A,(PPK_STATE) ; GET STATE
|
||||
@@ -515,76 +604,59 @@ PPK_DEC6: ; HANDLE MODIFIER KEYS
|
||||
CP $B0 ; START OF MODIFIER KEYS
|
||||
JR C,PPK_DEC7 ; BYPASS MODIFIER KEY CHECKING
|
||||
|
||||
; TODO: STUFF BELOW COULD BE A LOOP
|
||||
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
|
||||
|
||||
; HANDLE L/R SHIFT KEYS
|
||||
LD E,PPK_SHIFT ; SETUP TO SET/CLEAR SHIFT BIT
|
||||
SUB $B0 ; L-SHIFT?
|
||||
JR Z,PPK_DEC6A ; YES, HANDLE L-SHIFT MAKE/BREAK
|
||||
DEC A ; R-SHIFT?
|
||||
JR Z,PPK_DEC6B ; YES, HANDLE R-SHIFT MAKE/BREAK
|
||||
PPK_DEC6A:
|
||||
RLC E ; SHIFT TO NEXT MODIFIER STATE BIT
|
||||
DEC A ; L-MODIFIER?
|
||||
JR Z,PPK_DEC6B ; YES, HANDLE L-MODIFIER MAKE/BREAK
|
||||
DEC A ; R-MODIFIER?
|
||||
JR Z,PPK_DEC6C ; YES, HANDLE R-MODIFIER MAKE/BREAK
|
||||
DJNZ PPK_DEC6A ; LOOP THRU 4 MODIFIER BITS
|
||||
JR PPK_DEC7 ; FAILSAFE, SHOULD NEVER GET HERE!
|
||||
|
||||
; HANDLE L/R CONTROL KEYS
|
||||
LD E,PPK_CTRL ; SETUP TO SET/CLEAR CONTROL BIT
|
||||
DEC A ; L-CONTROL?
|
||||
JR Z,PPK_DEC6A ; YES, HANDLE L-CONTROL MAKE/BREAK
|
||||
DEC A ; R-CONTROL?
|
||||
JR Z,PPK_DEC6B ; YES, HANDLE R-CONTROL MAKE/BREAK
|
||||
|
||||
; HANDLE L/R ALT KEYS
|
||||
LD E,PPK_ALT ; SETUP TO SET/CLEAR ALT BIT
|
||||
DEC A ; L-ALT?
|
||||
JR Z,PPK_DEC6A ; YES, HANDLE L-ALT MAKE/BREAK
|
||||
DEC A ; R-ALT?
|
||||
JR Z,PPK_DEC6B ; YES, HANDLE R-ALT MAKE/BREAK
|
||||
|
||||
; HANDLE L/R WIN KEYS
|
||||
LD E,PPK_WIN ; SETUP TO SET/CLEAR WIN BIT
|
||||
DEC A ; L-WIN?
|
||||
JR Z,PPK_DEC6A ; YES, HANDLE L-WIN MAKE/BREAK
|
||||
DEC A ; R-WIN?
|
||||
JR Z,PPK_DEC6B ; YES, HANDLE R-WIN MAKE/BREAK
|
||||
|
||||
PPK_DEC6A: ; LEFT STATE KEY MAKE/BREAK (STATE BIT TO SET/CLEAR IN E)
|
||||
PPK_DEC6B: ; LEFT STATE KEY MAKE/BREAK (STATE BIT TO SET/CLEAR IN E)
|
||||
LD HL,PPK_LSTATE ; POINT TO LEFT STATE BYTE
|
||||
JR PPK_DEC6C ; CONTINUE
|
||||
JR PPK_DEC6D ; CONTINUE
|
||||
|
||||
PPK_DEC6B: ; RIGHT STATE KEY MAKE/BREAK (STATE BIT TO SET/CLEAR IN E)
|
||||
PPK_DEC6C: ; RIGHT STATE KEY MAKE/BREAK (STATE BIT TO SET/CLEAR IN E)
|
||||
LD HL,PPK_RSTATE ; POINT TO RIGHT STATE BYTE
|
||||
JR PPK_DEC6C ; CONTINUE
|
||||
JR PPK_DEC6D ; CONTINUE
|
||||
|
||||
PPK_DEC6C: ; BRANCH BASED ON WHETHER THIS IS A MAKE OR BREAK EVENT
|
||||
PPK_DEC6D: ; BRANCH BASED ON WHETHER THIS IS A MAKE OR BREAK EVENT
|
||||
LD A,(PPK_STATUS) ; GET STATUS FLAGS
|
||||
AND PPK_BREAK ; BREAK EVENT?
|
||||
JR Z,PPK_DEC6D ; NO, HANDLE A MODIFIER KEY MAKE EVENT
|
||||
JR PPK_DEC6E ; YES, HANDLE A MODIFIER BREAK EVENT
|
||||
JR Z,PPK_DEC6E ; NO, HANDLE A MODIFIER KEY MAKE EVENT
|
||||
JR PPK_DEC6F ; YES, HANDLE A MODIFIER BREAK EVENT
|
||||
|
||||
PPK_DEC6D: ; HANDLE STATE KEY MAKE EVENT
|
||||
PPK_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 PPK_DEC6F ; CONTINUE
|
||||
JR PPK_DEC6G ; CONTINUE
|
||||
|
||||
PPK_DEC6E: ; HANDLE STATE KEY BREAK EVENT
|
||||
PPK_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 PPK_DEC6F ; CONTINUE
|
||||
JR PPK_DEC6G ; CONTINUE
|
||||
|
||||
PPK_DEC6F: ; COALESCE L/R STATE FLAGS
|
||||
PPK_DEC6G: ; COALESCE L/R STATE FLAGS
|
||||
LD A,(PPK_STATE) ; GET EXISTING STATE BITS
|
||||
AND $F0 ; GET RID OF OLD MODIFIER BITS
|
||||
LD DE,(PPK_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 (PPK_STATE),A ; SAVE IT
|
||||
JP PPK_DECODE ; DONE WITH CURRENT KEYSTROKE
|
||||
JP PPK_DECNEW ; DONE WITH CURRENT KEYSTROKE
|
||||
|
||||
PPK_DEC7: ; COMPLETE PROCESSING OF KEY BREAK EVENTS
|
||||
PPK_DEC7: ; COMPLETE PROCESSING OF EXTENDED AND KEY BREAK EVENTS
|
||||
LD A,(PPK_STATUS) ; GET CURRENT STATUS FLAGS
|
||||
AND PPK_BREAK ; IS THIS A KEY BREAK EVENT?
|
||||
JP NZ,PPK_DECODE ; YES, RESTART TO PROCESS NEXT KEY
|
||||
JP NZ,PPK_DECNEW ; PROCESS NEXT KEY
|
||||
|
||||
PPK_DEC8: ; HANDLE TOGGLE KEYS
|
||||
LD A,(PPK_KEYCODE) ; GET THE CURRENT KEYCODE INTO A
|
||||
@@ -603,24 +675,10 @@ PPK_DEC8A: ; RECORD THE TOGGLE
|
||||
LD A,(PPK_STATE) ; GET THE CURRENT STATE FLAGS
|
||||
XOR E ; SET THE TOGGLE KEY BIT FROM ABOVE
|
||||
LD (PPK_STATE),A ; SAVE IT
|
||||
CALL PPK_SETLEDS ; UPDATE LED LIGHTS ON KBD
|
||||
JP PPK_DECNEW ; RESTART DECODER FOR A NEW KEY
|
||||
|
||||
; UPDATE KEYBOARD LED'S
|
||||
LD A,$ED ; SET/RESET LED'S COMMAND
|
||||
CALL PPK_PUTBYTE ; SEND THE COMMAND
|
||||
CALL PPK_GETBYTE ; READ THE RESPONSE
|
||||
CP $FA ; MAKE SURE WE GET ACK
|
||||
JP NZ,PPK_DECODE ; ABORT IF NO ACK
|
||||
LD A,(PPK_STATE) ; LOAD THE STATE BYTE
|
||||
RRCA ; ROTATE TOGGLE KEY BITS AS NEEDED
|
||||
RRCA
|
||||
RRCA
|
||||
RRCA
|
||||
AND $07 ; CLEAR THE IRRELEVANT BITS
|
||||
CALL PPK_PUTBYTE ; SEND THE LED DATA
|
||||
CALL PPK_GETBYTE ; READ THE ACK
|
||||
JP PPK_DECODE ; RESTART DECODER FOR A NEW KEY
|
||||
|
||||
PPK_DEC9: ; HANDLE CONTROL KEYS
|
||||
PPK_DEC9: ; ADJUST KEYCODE FOR CONTROL MODIFIER
|
||||
LD A,(PPK_STATE) ; GET THE CURRENT STATE BITS
|
||||
AND PPK_CTRL ; CHECK THE CONTROL BIT
|
||||
JR Z,PPK_DEC10 ; CONTROL KEY NOT PRESSED, MOVE ON
|
||||
@@ -638,7 +696,7 @@ PPK_DEC9A:
|
||||
RES 6,A ; CONVERT TO CONTROL VALUE BY CLEARING BIT 6
|
||||
LD (PPK_KEYCODE),A ; UPDATE KEYCODE TO CONTROL VALUE
|
||||
|
||||
PPK_DEC10: ; ADJUST KEYCODE FOR CAPS LOCK, IF NEEDED
|
||||
PPK_DEC10: ; ADJUST KEYCODE FOR CAPS LOCK
|
||||
LD A,(PPK_STATE) ; LOAD THE STATE FLAGS
|
||||
AND PPK_CAPSLCK ; CHECK CAPS LOCK
|
||||
JR Z,PPK_DEC11 ; CAPS LOCK NOT ACTIVE, MOVE ON
|
||||
@@ -692,7 +750,7 @@ PPK_DEC11A: ; APPLY NUMPAD MAPPING
|
||||
PPK_DEC12: ; DETECT UNKNOWN/INVALID KEYCODES
|
||||
LD A,(PPK_KEYCODE) ; GET THE FINAL KEYCODE
|
||||
CP $FF ; IS IT $FF (UNKNOWN/INVALID)
|
||||
JP Z,PPK_DECODE ; IF SO, JUST RESTART THE ENGINE
|
||||
JP Z,PPK_DECNEW ; IF SO, JUST RESTART THE ENGINE
|
||||
|
||||
PPK_DEC13: ; DONE - RECORD RESULTS
|
||||
LD A,(PPK_STATUS) ; GET CURRENT STATUS
|
||||
@@ -701,6 +759,11 @@ PPK_DEC13: ; DONE - RECORD RESULTS
|
||||
XOR A ; A=0
|
||||
INC A ; SIGNAL SUCCESS WITH A=1
|
||||
RET
|
||||
|
||||
PPK_DECNEW: ; START NEW KEYPRESS (CLEAR ALL STATUS BITS)
|
||||
XOR A ; A = 0
|
||||
LD (PPK_STATUS),A ; CLEAR STATUS
|
||||
JP PPK_DEC1 ; RESTART THE ENGINE
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; MAPPING TABLES
|
||||
@@ -717,12 +780,14 @@ PPK_MAPSTD: ; SCANCODE IS INDEX INTO TABLE TO RESULTANT LOOKUP KEYCODE
|
||||
.DB $C9,$CA,$C1,$C4,$C5,$C7,$1B,$BD,$FA,$CE,$C2,$CD,$CC,$C8,$BE,$FF
|
||||
.DB $FF,$FF,$FF,$E6,$EC
|
||||
;
|
||||
PPK_MAPSIZ .EQU ($ - PPK_MAPSTD)
|
||||
;
|
||||
PPK_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,'<','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
|
||||
|
||||
@@ -22,7 +22,6 @@ VDU_DATA .EQU 0F3h ; VDU DATA REGISTER
|
||||
;
|
||||
VDU_INIT:
|
||||
CALL INITVDU
|
||||
CALL PPK_INIT
|
||||
XOR A
|
||||
RET
|
||||
;
|
||||
@@ -178,12 +177,6 @@ VDU_WAITRDY:
|
||||
JR VDU_WAITRDY ; KEEP CHECKING
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; IMBED COMMON PARALLEL PORT KEYBOARD DRIVER
|
||||
;__________________________________________________________________________________________________
|
||||
;
|
||||
#INCLUDE "ppk.asm"
|
||||
;
|
||||
;__________________________________________________________________________________________________
|
||||
; INITIALIZATION
|
||||
;__________________________________________________________________________________________________
|
||||
INITVDU:
|
||||
|
||||
Reference in New Issue
Block a user