Close

20230214c -- Keyboard, revisited

A project log for ROM Disassembly - AlphaSmart Pro

Wherein I disassemble the ROM from a vintage typewriter-thing

ziggurat29ziggurat29 02/16/2023 at 13:491 Comment

On the trail of the 8000/C000 and bit rotation thing, I found some stuff that looks a lot like keyboard scanning:

E5A0             scanKbd_E5A0:
E5A0 BD E5 90        jsr     sub_E590
E5A3 CC FF FE        ldd     #$FFFE          ; 16-bits, bit 0 low
E5A6 DD 5E           std     word_5E         ; store as (initial) /next/ scan column
E5A8             loopNextKbdCol_E5A8:
E5A8 DC 5E           ldd     word_5E         ; get next scan column
E5AA 1A 83 FF FF     cpd     #$FFFF
E5AE 27 74           beq     loc_E624        ; finished!
E5B0 B7 80 00        staa    $8000           ; XXX keyboard column latch high?
E5B3 F7 C0 00        stab    $C000           ; XXX keyboard column latch low?
E5B6 DD 4E           std     word_4E         ; (save for now)
E5B8 05              lsld                    ; shift up for next scan column
E5B9 CA 01           orab    #1              ; (set the low bit; can only have a single 0)
E5BB DD 5E           std     word_5E         ; save /next/ scan column
E5BD DC 4E           ldd     word_4E         ; (restore /this/ scan column)
E5BF 88 FF           eora    #$FF            ; (invert bits to have 1 in current column)
E5C1 C8 FF           eorb    #$FF
E5C3 DD 4E           std     word_4E         ; remember /this/ scan column; 'rectus'
E5C5 8F              xgdx                    ; get 'rectus' scan column in X
E5C6 F6 80 00        ldab    $8000           ; XXX read keyboard row latch into B???
E5C9 C8 FF           eorb    #$FF            ; complement to rectus row scan mask (1 in row keydown position)
E5CB 8C 80 00        cpx     #$8000
E5CE 27 5C           beq     handleCol15_E62C ; XXX ??? special handle column 15
E5D0 8C 02 00        cpx     #$200
E5D3 27 71           beq     handleCol9_E646 ; XXX ??? special handle column 9
E5D5 8C 01 00        cpx     #$100
E5D8 27 5F           beq     handleCol8_E639 ; XXX ??? special handle column 8
E5DA 8C 00 40        cpx     #$40
E5DD 27 76           beq     handleCol5_E655 ; XXX ??? special handle column 5
E5DF             loc_E5DF:
E5DF 37              pshb                    ; (save row scan mask)
E5E0 BD F5 7B        jsr     sub_F57B

The routine starts with a bit pattern FFFE -- one zero at b0.  Then this 16 bit pattern is put out on 8000/C000, shifting up for the next iteration of the loop.  The value at 8000 is read.  In both cases, the values are 'active low', and inversion is done to make it 'active high'.  The 'active high' versions are later passed to routines to convert to a bit number.  The process continues until all bits for a given column are consumed, and all columns have been iterated.

The default processing is at loc_E5DF, and consists of translating the column and row scan patterns to column and row numbers, and combining them into an 8-bit value which I call a 'scan code' with row number in the high nybble and column number in the low nybble.  These get pushed into a 16-byte buffer at 0x90, with a pull index at 0x8e and push index at 0xef.  The enqueue routine is at enqueueKbdScanCode_EBD7, and the dequeue routine is at dequeueKbdScanCode_EBEE.

Since these are scan codes, not ASCII, studying the reference to 'dequeue' will be interesting because it will give us some clues to the key matrix.  Most of the keystrokes do have to convert to ASCII.  The functional ones might be processed directly as scan codes, though, which will be trickier to puzzle out.

There's some special handling for columns 15, 9, 8, and 5.  I haven't explored these yet, but since they are exception paths, it might provide a clue as to the electrical layout.

Discussions

Eric Hertz wrote 02/17/2023 at 03:56 point

Whew! You're on a roll!

  Are you sure? yes | no