There are several translation routines found during the file sending stuff that translate one character value into another one. Some we understand, like this one:
F4DC sub_F4DC:
F4DC 84 7F anda #$7F ; reset high bit
F4DE 16 tab
F4DF 4F clra
F4E0 05 lsld
F4E1 05 lsld
F4E2 C3 F8 C5 addd #scanCodeStructs_F8C5
F4E5 8F xgdx ; X is scan code struct for scan code originally in A
F4E6 A6 01 ldaa 1,x
F4E8 39 rts
This is a straightforward translation of AlphSmart Pro scan code to the PS/2 scan code (since we have now figured out offset +1 is the PS/2 code). This is probably used when the device is operating as a conventional keyboard (i.e., not 'standalone mode').
This one's fancier, but we can see what's going on:
F4B6 sub_F4B6:
F4B6 84 7F anda #$7F ; reset high bit
F4B8 CE F8 C5 ldx #scanCodeStructs_F8C5
F4BB loop_F4BB:
F4BB 8C FA C5 cpx #byte_FAC5 ; (end of array)
F4BE 27 18 beq notfound_F4D8
F4C0 A1 02 cmpa 2,x ; match either lower case
F4C2 27 0A beq matchLower_F4CE
F4C4 A1 03 cmpa 3,x ; or upper case
F4C6 27 0A beq matchUpper_F4D2
F4C8 08 inx
F4C9 08 inx
F4CA 08 inx
F4CB 08 inx ; next struct...
F4CC 20 ED bra loop_F4BB
F4CE matchLower_F4CE:
F4CE A6 01 ldaa 1,x
F4D0 20 04 bra cont_F4D6
F4D2 matchUpper_F4D2:
F4D2 A6 01 ldaa 1,x
F4D4 8A 80 oraa #$80
F4D6 cont_F4D6:
F4D6 0A clv
F4D7 39 rts
F4D8 notfound_F4D8:
F4D8 86 4A ldaa #$4A
F4DA 0B sev
F4DB 39 rts
Here a linear search is done through the scanCodeStructs_F8C5 trying to match either the upper or lower case ASCII version of the entry, and then plucking out the PS/2 scan code. So this is an 'ASCII to PS/2' translation, and is probably used when sending files (which are in ASCII) over the keyboard port.
This one also involved the scanCodeStructs_F8C5 array, but it uses offset +0 that I do not yet understand:
F482 sub_F482:
F482 85 80 bita #$80 ; remember high bit status (using byte_71 scratch var) for later
F484 27 05 beq cont_F48B
F486 14 71 FF bset byte_71 $FF
F489 20 03 bra cont_F48E
F48B cont_F48B:
F48B 7F 00 71 clr byte_71
F48E cont_F48E:
F48E 84 7F anda #$7F ; mask off high bit in key scan code
F490 16 tab
F491 4F clra
F492 05 lsld
F493 05 lsld ; effectively scan code *= 4
F494 C3 F8 C5 addd #scanCodeStructs_F8C5
F497 8F xgdx ; X is now scan code structure pointer
F498 A6 00 ldaa 0,x ; F8C5[].0
F49A 81 FF cmpa #$FF
F49C 27 08 beq invalidKey_F4A6
F49E 13 71 01 02 brclr byte_71 1 loc_F4A4 ; restore high bit state
F4A2 8A 80 oraa #$80
F4A4 loc_F4A4:
F4A4 0A clv
F4A5 39 rts
F4A6 invalidKey_F4A6:
F4A6 86 2A ldaa #$2A
F4A8 0B sev
F4A9 39 rts
This is an AlphaSmart Pro scan code to +0 converter. It also takes care to preserve the high bit of the incoming code. (The high bit so far seems to be a flag indicating that shift is active.) We will see if I discover the mysteries of offset +0.
The last one is peculiar in that it involves a different array, 'byte_FAC5':
F4AA sub_F4AA:
F4AA 84 7F anda #$7F ; reset high bit
F4AC 80 20 suba #' ' ; offset to space = 0
F4AE CE FA C5 ldx #byte_FAC5 ; index into here
F4B1 16 tab
F4B2 3A abx
F4B3 A6 00 ldaa 0,x
F4B5 39 rts
This array is 95 bytes. 95 = 127 - 32. So it seems more than coincidental that this would map to the printable ASCII 20-7fh. Unlike the scanCodeStructs_F8C5 array, this is not a structure, just a byte.
On a hunch, I am guessing that this is for Apple keyboard ("ADB") support. Like PS/2, this protocol is documented. I marked off a few entries in the list denoting what ASCII they correspond to:
FAC5 31 byte_FAC5: fcb $31 ; 20h - space
...
FAD5 1D fcb $1D ; 30h - '0'
...
FAE6 80 fcb $80 ; 41h - 'A'
...
FAFF 86 fcb $86 ; 5ah - 'Z'
...
FB06 00 fcb 0 ; 61h - 'a'
...
FB1F 06 fcb 6 ; 7ah - 'z'
By checking against documentation these do correspond to the ADB key codes for these keys. It's interesting to note that the high bit is set to indicate if the shift key should be down. (e.g. difference between 'A' and 'a' and 'Z' and 'z' is just the high bit set for upper case.)
So that seems to solve one mystery. Hot on this ADB stuff, the new hypothesis is that the +0 entry is the ADB code. Cross-checking the entries above in the scanCodeStructs_F8C5 correlates once again, so I think this second mystery is solved as well. So in sum:
- F482 scanCodeToADB_F482: ; a table lookup
- F4AA xlatASCIItoADB_F4AA: ; a table lookup
- F4B6 xlatASCIItoPS2_F4B6: ; a linear search
- F4DC scanCodetoPS2_F4DC: ; a table lookup
and those are our 4 use-cases: ADB or PS/2, and file sending or keyboard emulation.
What is more interesting to me now is that there are many scan codes which are not valid ASCII (i.e. +2 and +3 are 0). These are doubtlessly the various function keys that I have not mapped out yet, so I should be able to use the PS/2 documentation to map out most of the remainder of the keyboard matrix.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.