neon816 - experimental PS/2 keyboard decoder

This commit is contained in:
mgcaret 2020-03-22 21:25:23 -07:00
parent 6207ab7428
commit 465a697952
1 changed files with 563 additions and 1 deletions

View File

@ -2,6 +2,17 @@
;
.include "./Neon816-hw.inc"
PLATF_DP = DP_END
KEYMODS = PLATF_DP ; keyboard modifiers, 16 bits
; b15 = left shift
; b14 = right shift
; b7 = left ctrl
; b6 = right ctrl
; these 3 are same position as set LED command:
; b2 = scroll lock (reserved)
; b1 = num lock (reserved)
; b0 = caps lock
; Neon816 dictionary, a bit of a different approach than the other ports
; This will get set up by the post init function of the system interface
; The system interface functions are after this dictionary.
@ -11,7 +22,7 @@
; Lenore Byron places on them.
dstart "neon816"
dchain H_FORTH ; Make branch off the word FORTH
dchain H_FORTH ; Make branch off the word FORTH
dword PS2K_STORE,"PS2K!"
jsr _popay
@ -55,6 +66,12 @@ dword PS2K_FETCH,"PS2K@"
NEXT
eword
dword PS2KEY,"PS2KEY"
jsr ps2_keyin
jsr _pusha
NEXT
eword
dword PS2M_STORE,"PS2M!"
jsr _popay
tya
@ -604,3 +621,548 @@ list:
jmp _sf_fail
.endproc
; return carry set if data waiting at PS/2 keyboard port, clear otherwise
; destroys A
.proc ps2k_ready
sep #SHORT_A
.a8
lda f:PS2Kstat
ror
rep #SHORT_A
.a16
rts
.endproc
; read data from PS/2 keyboard port, blocking
; returns byte in A
.proc ps2k_read
sep #SHORT_A
.a8
: lda f:PS2Kstat
ror
bcc :-
lda f:PS2Kio
rep #SHORT_A
.a16
and #$00FF
rts
.endproc
; write data byte in A to PS/2 keyboard port
.proc ps2k_write
sep #SHORT_A
.a8
sta f:PS2Kio
: lda f:PS2Kstat
bit #$08
bne :-
rep #SHORT_A
.a16
rts
.endproc
; Keyboard translate tables
; unshifted and shifted codes
; if high bit set, jump to special handler routine
.proc mktab ; 'main' scan codes'
; $00
.byte $00,$00 ; none
.byte $00,$00 ; F9
.byte $00,$00 ; none
.byte $00,$00 ; F5
.byte $00,$00 ; F3
.byte $00,$00 ; F1
.byte $00,$00 ; F2
.byte $00,$00 ; F12
; $08
.byte $00,$00 ; none
.byte $00,$00 ; F10
.byte $00,$00 ; F8
.byte $00,$00 ; F6
.byte $00,$00 ; F4
.byte $09,$09 ; Tab
.byte '`','~'
.byte $00,$00 ; none
; $10
.byte $00,$00 ; none
.byte $00,$00 ; left alt
.byte $80,$80 ; left shift
.byte $00,$00 ; none
.byte $86,$86 ; left control
.byte 'q','Q'
.byte '1','!'
.byte $00,$00 ; none
; $18
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte 'z','Z'
.byte 's','S'
.byte 'a','A'
.byte 'w','W'
.byte '2','@'
.byte $00,$00 ; none
; $20
.byte $00,$00 ; none
.byte 'c','C'
.byte 'x','X'
.byte 'd','D'
.byte 'e','E'
.byte '4','$'
.byte '3','#'
.byte $00,$00 ; none
; $28
.byte $00,$00 ; none
.byte ' ',' '
.byte 'v','V'
.byte 'f','F'
.byte 't','T'
.byte 'r','R'
.byte '5','S'
.byte $00,$00 ; none
; $30
.byte $00,$00 ; none
.byte 'n','N'
.byte 'b','B'
.byte 'h','H'
.byte 'g','G'
.byte 'y','Y'
.byte '6','^'
.byte $00,$00 ; none
; $38
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte 'm','M'
.byte 'j','J'
.byte 'u','U'
.byte '7','&'
.byte '8','*'
.byte $00,$00 ; none
; $40
.byte $00,$00 ; none
.byte ',','<'
.byte 'k','K'
.byte 'i','I'
.byte 'o','O'
.byte '0',')'
.byte '9','('
.byte $00,$00 ; none
; $48
.byte $00,$00 ; none
.byte '.','>'
.byte '/','?'
.byte 'l','L'
.byte ';',':'
.byte 'p','P'
.byte '-','_'
.byte $00,$00 ; none
; $50
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $27,'"'
.byte $00,$00 ; none
.byte '[','{'
.byte '=','+'
.byte $00,$00 ; none
.byte $00,$00 ; none
; $58
.byte $00,$00 ; none
.byte $84,$84 ; caps lock
.byte $82,$82 ; right shift
.byte $0D,$0D ; enter
.byte ']','}'
.byte $00,$00 ; none
.byte '\','|'
.byte $00,$00 ; none
; $60
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $08,$7F ; backspace
.byte $00,$00 ; none
; $68
.byte $00,$00 ; none
.byte '1','1' ; keypad
.byte $00,$00 ; none
.byte '4','4' ; keypad
.byte '7','7' ; keypad
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
; $70
.byte '0','0' ; keypad
.byte '.','.' ; keypad
.byte '2','2' ; keypad
.byte '5','5' ; keypad
.byte '6','6' ; keypad
.byte '8','8' ; keypad
.byte $1B,$1B ; escape
.byte $00,$00 ; num lock
; $78
.byte $00,$00 ; F11
.byte '+','+' ; keypad
.byte '3','3' ; keypad
.byte '-','-' ; keypad
.byte '*','*' ; keypad
.byte '9','9' ; keypad
.byte $00,$00 ; scroll lock
.byte $00,$00 ; none
; $80
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; F7
.endproc
.proc ektab ; E0 scan codes
; $00
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
; $08
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
; $10
.byte $00,$00 ; MM WWW search
.byte $00,$00 ; right alt
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $88,$88 ; right control
.byte $00,$00 ; MM prev track
.byte $00,$00 ; none
.byte $00,$00 ; none
; $18
.byte $00,$00 ; MM WWW favorites
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; left GUI
; $20
.byte $00,$00 ; MM WWW refresh
.byte $00,$00 ; MM vol down
.byte $00,$00 ; MM mute
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; right GUI
; $28
.byte $00,$00 ; MM WWW stop
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; MM calculator
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; 'apps'
; $30
.byte $00,$00 ; MM WWW forward
.byte $00,$00 ; none
.byte $00,$00 ; MM vol up
.byte $00,$00 ; none
.byte $00,$00 ; MM play/pause
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; ACPI power
; $38
.byte $00,$00 ; MM WWW back
.byte $00,$00 ; none
.byte $00,$00 ; MM WWW home
.byte $00,$00 ; MM stop
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; ACPI sleep
; $40
.byte $00,$00 ; MM my computer
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
; $48
.byte $00,$00 ; MM email
.byte $00,$00 ; none
.byte '/','/' ; keypad
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; MM next track
.byte $00,$00 ; none
.byte $00,$00 ; none
; $50
.byte $00,$00 ; MM select
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
; $58
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $0D,$0D ; keypad 'enter'
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; ACPI wake
.byte $00,$00 ; none
; $60
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
; $68
.byte $00,$00 ; none
.byte $00,$00 ; end
.byte $00,$00 ; none
.byte $08,$08 ; cursor left
.byte $00,$00 ; home
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; none
; $70
.byte $00,$00 ; insert
.byte $7F,$7F ; delete
.byte $0A,$0A ; cursor down
.byte $00,$00 ; none
.byte $15,$15 ; cursor right
.byte $0B,$0B ; cursor up
.byte $00,$00 ; none
.byte $00,$00 ; none
; $78
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; page down
.byte $00,$00 ; none
.byte $00,$00 ; none
.byte $00,$00 ; page up
.endproc
; Tables of routines for special make/break of keys (values > $80)
; kmktbl and kbktbl must match up.
.proc kmktbl
.addr mk_lshift-1 ; $80
.addr mk_rshift-1 ; $82
.addr mk_caps-1 ; $84
.addr mk_lctrl-1 ; $86
.addr mk_rctrl-1 ; $88
.endproc
.proc kbktbl
.addr bk_lshift-1 ; $80
.addr bk_rshift-1 ; $82
.addr bk_caps-1 ; $84
.addr bk_lctrl-1 ; $88
.addr bk_rctrl-1 ; $88
.endproc
.proc mk_lshift
lda #%1000000000000000
bra makemod
.endproc
.proc mk_rshift
lda #%0100000000000000
bra makemod
.endproc
.proc mk_caps
lda #%0000000000000001
jsr makemod
; fall-through to ps2_setLEDs
.endproc
.proc ps2_setleds
lda #$ED ; set LEDs command
jsr ps2k_write
lda KEYMODS
jsr ps2k_write
bra nokey
.endproc
.proc mk_lctrl
lda #%0000000010000000
bra makemod
.endproc
.proc mk_rctrl
lda #%0000000001000000
;bra makemod
.endproc
.proc makemod
tsb KEYMODS
; fall through to nokey
.endproc
.proc nokey
lda #$0000
clc
rts
.endproc
.proc bk_lshift
lda #%1000000000000000
bra breakmod
.endproc
.proc bk_rshift
lda #%0100000000000000
bra breakmod
.endproc
.proc bk_caps
lda #%0000000000000001
jsr breakmod
bra ps2_setleds
.endproc
.proc bk_lctrl
lda #%0000000010000000
bra breakmod
.endproc
.proc bk_rctrl
lda #%0000000001000000
;bra breakmod
.endproc
.proc breakmod
trb KEYMODS
bra nokey
.endproc
; expects a 'make' code, either 00xx or E0xx
.proc ps2_keydn
lda #%1100000000000000 ; shift keys
bit KEYMODS
php ; save result (Z=1 if no shift)
ora #$0000 ; if high bit is set we will treat as $E0
php
and #$00FF
asl
tay
lda #$0000 ; anticipate failure of cpy
plp
bmi :+
cpy .sizeof(mktab)/2
bcs :++ ; bad value
lda mktab,y
bra :++
: cpy .sizeof(ektab)/2
bcs :+ ; bad value
lda ektab,y
: plp
beq :+ ; unshifted
xba
: and #$00FF
cmp #$0080
bcs special
pha
lda KEYMODS
ror ; caps lock into carry
pla
bcc nocaps ; if no caps lock
cmp #'a'
bcc nocaps
cmp #'z'+1
bcs nocaps
and #$DF ; make caps
nocaps: pha ; save on stack
lda #%0000000011000000 ; ctrl keys
bit KEYMODS
beq :+ ; if no ctrl
lda 1,s
and #%0000000000011111 ; make ctrl
sta 1,s
: pla
cmp #$01 ; set carry if >= 1
rts
special: and #$7f
tay
lda kmktbl,y
pha
rts
.endproc
; for the break we only care about modifiers, we aren't keeping track of anything else
; so we also ignore shifted values
; expects a 'make'-like code, either 00xx or E0xx
.proc ps2_keyup
ora #$0000
php
and #$00FF
asl
tay
plp
bmi :+
cpy .sizeof(mktab)/2
bcs :++
lda mktab,y
bra :++
: cpy .sizeof(ektab)/2
bcs :+
lda ektab,y
: and #$00FF
cmp #$0080
bcs special
lda #$0000
clc
rts
special: and #$7f
tay
lda kbktbl,y
pha
rts
.endproc
; Wait for a valid key, when we get one, decode and return
.proc ps2_keyin
: jsr ps2k_read
cmp #$F0
beq break
cmp #$FE
beq extended
cmp #$AA ; diags passed
beq :-
cmp #$FC ; diags failed
beq :- ; prob shouldn't do this
cmp #$FA ; ACK
beq :-
jmp ps2_keydn ; see if we can decode it
break: jsr ps2k_read
bra ps2_keyup
extended: jsr ps2k_read
cmp #$F0
beq :+ ; extended break
ora #$E000
jmp ps2_keydn
: jsr ps2k_read
ora #$E000
bra ps2_keyup
.endproc