Hi all,
It's been a while since I posted here; but once again my electronics experiments have led me to the PICAXE
I'm building a Z80-based computer, and I'm using a 14M2 as a PS/2 keyboard controller to feed ASCII to an SCC2691 UART; for now I'm debugging over the programming link.
Initially I tried a simple lookup-table approach as per the keyin.bas sample.
This worked, but gave me double-hits on all keys with no way to discard the keycodes resulting from key-up events (as the key-up keycode preamble doesn't make it through to PICAXE basic). I can't just ignore every other keycode received from kbin, as I want to handle fast overlapping-keys typing (eg when typing "the" at speed, the keycodes received may be t-h-t-h-e-e instead of simply t-t-h-h-e-e).
So, I added an "isPressed" buffer in RAM for each key. When I receive a given keycode, I check if that key's currently marked as pressed. If so, this must be a keyup event I can ignore (and reset the pressed flag). If not, this must be a keypress, so I send the character and mark the key as pressed. This RAM buffer uses an entire byte per key; lazy and wasteful I know, it should be a single bit per key.
I also wanted to be able to press Shift for uppercase and symbols, so I added a flag to keep track of the status of the shift keys and used the remaining EEPROM space to have different lookup tables for shifted and unshifted keys.
This is a lot closer to where I want to be, and is presented below in the hope that it's useful to someone.
It handles "overlapping" typing well and allows Shift for uppercase. Latency between key press and a byte heading out the serial port is acceptable. Supporting Caps Lock would be easy and I'll probably add that. It's also got better lookup tables (more keys) than the ones in the manual.
However, it's still not perfect. When typing at even moderate speed it either misses character completely or gets two swapped around out of sequence. Missing the character I can understand, assuming there's no FIFO that kbin consumes; swapping two seems stranger though.
Anyway, my queries are:
(1) Does anyone have a better strategy for handling these requirements on a PICAXE, or am I on the right track?
(2) Can anyone think of any way I can speed up the code so that there's less chance of missing characters? I've already disabled the keyboard LED flashing and am running at 32MHz.
Great to see the PICAXE community as vibrant as ever
All the best,
Iain
It's been a while since I posted here; but once again my electronics experiments have led me to the PICAXE
I'm building a Z80-based computer, and I'm using a 14M2 as a PS/2 keyboard controller to feed ASCII to an SCC2691 UART; for now I'm debugging over the programming link.
Initially I tried a simple lookup-table approach as per the keyin.bas sample.
This worked, but gave me double-hits on all keys with no way to discard the keycodes resulting from key-up events (as the key-up keycode preamble doesn't make it through to PICAXE basic). I can't just ignore every other keycode received from kbin, as I want to handle fast overlapping-keys typing (eg when typing "the" at speed, the keycodes received may be t-h-t-h-e-e instead of simply t-t-h-h-e-e).
So, I added an "isPressed" buffer in RAM for each key. When I receive a given keycode, I check if that key's currently marked as pressed. If so, this must be a keyup event I can ignore (and reset the pressed flag). If not, this must be a keypress, so I send the character and mark the key as pressed. This RAM buffer uses an entire byte per key; lazy and wasteful I know, it should be a single bit per key.
I also wanted to be able to press Shift for uppercase and symbols, so I added a flag to keep track of the status of the shift keys and used the remaining EEPROM space to have different lookup tables for shifted and unshifted keys.
This is a lot closer to where I want to be, and is presented below in the hope that it's useful to someone.
It handles "overlapping" typing well and allows Shift for uppercase. Latency between key press and a byte heading out the serial port is acceptable. Supporting Caps Lock would be easy and I'll probably add that. It's also got better lookup tables (more keys) than the ones in the manual.
However, it's still not perfect. When typing at even moderate speed it either misses character completely or gets two swapped around out of sequence. Missing the character I can understand, assuming there's no FIFO that kbin consumes; swapping two seems stranger though.
Anyway, my queries are:
(1) Does anyone have a better strategy for handling these requirements on a PICAXE, or am I on the right track?
(2) Can anyone think of any way I can speed up the code so that there's less chance of missing characters? I've already disabled the keyboard LED flashing and am running at 32MHz.
Code:
; Keyboard controller firmware for PICAXE14M2
; Iain C, 18 April 2012
; Circuit: 14M2 with a programming interface, plus a PS/2 port connected as per circuit at bottom of p133, picaxe_manual2.pdf.
symbol serpin = 0 ; Pin to use for serial output
symbol serbaud = N38400_32 ; Serial baudrate to use for output
symbol shifted = b2 ; To store current shift state
symbol isPressedStart = $1C ; Mem address of isPressed buffer (1 byte per key; wasteful!)
kbled %10000010 ; Turn on just numlock led and disable flash
setfreq m32 ; Let's go fast :)
shifted = 0 ; Set shifted flag to false intially
b3 = isPressedStart
for b0=0 to 127 ; Init the isPressed array
poke b3,0
inc b3
next b0
main:
kbin b0
if b0=$12 or b0=$59 then ; Shift pressed/depressed?
if shifted=0 then ; Toggle shifted flag
shifted=1
else
shifted=0
endif
goto main ; Loop back to main; don't actually send a keycode for shift
endif
b4=b0+$1C ; Find mem address of this key's isPressed flag
peek b4,b3 ; Check the flag location
if b3=1 then ; If 1, it's been pressed -- this must be an onRelease hit...
poke b4,0 ; ... so reset the key's isPressed flag
goto main ; ... and loop back to main
else ; Otherwise, this must be an onPress hit...
poke b4,1 ; ... so set the isPressed flag and continue!
endif
if shifted=1 then ; Currently shifted? Amend b0 to use the shifted lookup table instead
b0=b0+$80
endif
read b0,b1 ; Do the table lookup
if b1="?" and b0!=$4A then ; Try and prevent spurious undefined chars (not sure why these happen when typing
goto main ; at speed -- keycodes being partially received by kbin?)
endif
serout serpin,serbaud,(b1) ; Send the char
goto main
; Unshifted keycodes
eeprom $00,("?9?5312c?a864?`?") ; Fn keys
eeprom $10,("?????q1???zsaw2?") ; Main keyboard keys
eeprom $20,("?cxde43?? vftr5?")
eeprom $30,("?nbhgy6???mju78?")
eeprom $40,("?,kio09??./l;p-?")
eeprom $50,("??'?[=?????]?#??")
eeprom $60,("?\\???????1?47???") ; Numpad keys
eeprom $70,("0.2568??b+3-*9??")
; Shifted keycodes
eeprom $80,("?9?5312C?A864?¬?") ; Function keys
eeprom $90,("?????Q!???ZSAW\"?") ; Main keyboard keys
eeprom $A0,("?CXDE$#?? VFTR%?") ; Sorry, no pound sign -- not part of ASCII! Another # instead.
eeprom $B0,("?NBHGY^???MJU&*?")
eeprom $C0,("?<KIO)(??>?L:P_?") ; Note the ACTUAL question mark is 4A :P
eeprom $D0,("??@?{+?????}?~??")
eeprom $E0,("?|???????1?47???") ; Numpad keys
eeprom $F0,("0.2568??B+3-*9??")
All the best,
Iain
Last edited: