The PCB has Cherry model number 4060-A. And an MTI manufacturing tag. That's a lot of 74-series TTL for a 32-key keyboard from the late '80s. The reason is that there aren't actually any programmable logic elements there: the 40-pin chip is a UART.
Which means that its function can be entirely derived from the schematic:
- U1, a GI UAR/T (sic), inverts SI to J1:3 and SO to J1:4.
- Y1, the crystal, clocks it for 9600 baud.
- U4, a 4-bit counter, divides that same clock signal.
- U5, a flip-flop, latches the 4 column scan signals and loads them for output into DB1-4.
- DB5,7-8 are held high.
- DB6 indicates counter wrap-around.
- U7-10, latch the LED states; inputs are bussed from U12, another flip-flop, loaded from RD1-4; the outputs go to the individual LEDs; only one row is clocked at a time.
- RD5 triggers U3, the row counter's, resets RO(1-2).
- DS is driven by U6, a flip-flop wired as a shift-register and acting as a delay-line from DAV.
- The keyboard only outputs a byte immediately after it receives one, so that the host is in charge of higher-level timing. Nothing will happen just connecting up the output serial.
- The keys and LEDs form eight rows of four columns each.
- Each received byte sets the current row's LEDs, with zero meaning on, and advances the row number, unless 0x10 is zero, in which case it resets the row number.
- It is therefore reasonable to initialize or reset communication by sending 0x0F and otherwise use 0x1x.
- Shortly after receiving an LED byte, the keyboard responds with a button byte for the same row, with one meaning pressed.
- When the transmitted row number wraps around, the keyboard response has the 0x20 clear.
- The other three bits are one, so 0xFx means incremented row and 0xDx means started over.
A Teensy converter. I used a 2.0 and a separate 74LS04N inverter, instead of a 3.x with invertable UART signals, out of respect for the three of them in the keypad itself.
For the QMK implementation, I hooked up the LEDs to the existing LED matrix API. There aren't a lot of interesting effects in the library out of the box. And this keypad originally meant to prompt the user though the LEDs, which requires host control, which is unfortunately quite limited in modern keyboards, even with all their backlight features. And, of course, completely unsupported on the operating system side.
So, by way of example, I added a user routine that lights and fades each LED as you press it, along with some default function key assignments.