Apple Extended Keyboard II USB Conversion

This page documents a USB conversion which I performed on an AEK2, by replacing the controller with a Teensy++ 2.0. The software supports multiple layers, in particular a media layer containing mouse keys, volume controls, and so on. The controller also acts as an ADB host, so the remaining ADB port works, but only supports keyboards for the moment (I don't have an ADB mouse to test).

Keyboard
USB B port
ADB port
LEDs

Hardware

There are three ICs on the board: a controller, inverter and decoder (the linked datasheets came from alldatasheet.com and the datasheet archive). The following images show their locations (or, in the case of the controller, its former location--I removed it):

Former controller location
Inverter
Decoder

The pin assignments for the controller are documented in this text file. The keyboard matrix has 8 rows and 16 columns, the latter of which are accessed through the decoder. Setting the four decoder data pins to the binary value of a column index will make the corresponding column low. For any switch in this column which is pressed, the corresponding row pin will then be pulled low, permitting the state of the switch to be read by the controller. This is not an NKRO keyboard matrix (no diodes!), so there can be ghosting, which must be handled in software. The keyboard matrix is given in the following table:

  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  
0 KP 9 numlk   scrlk prtscr F12 F10 F9 F7 F6 F5 F4 F3 F2 F1 esc 0
1 KP / KP = KP 8 pause pgup bksp F11 0) F8 7& 6^ 4$ 3# 2@ 1! `~ 1
2 KP *   KP 7   pgdn \| =+ O 9( 8* T 5%         2
3 KP -   KP 6   end home [{ -_     Y G         3
4 KP 3 right KP 5   del ins ]} P K I   R E W Q tab 4
5 KP enter   KP 4   up enter '" ;: L   U   D       5
6     KP + left   .> /? ,< J H B F     S A 6
7   KP .   down KP 2 KP 1 KP 0 M N   space V C X Z   7
  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  

Notice that some keys are missing: the modifiers, caps lock key, and the ADB power (PSW) button. All of these are connected directly to controller pins, and hence may be treated as simple (active low) pushbuttons (the PSW button is a bit of an exception, since it's potentially also connected to other peripherals via the ADB port).

This image outlines the changes I made on the PCB, with more zoomed-in views in the following images. I'm not a good solderer, but everything (miraculously) works.

PCB
Former controller location
LEDs and ADB port
Teensy++ and USB port

I first replaced the LEDs and the corresponding resistors. The controller was replaced with a Teensy++ 2.0, which I wired into the controller location based on the aforementioned text file, with one difference: both command keys are connected to the same pin, and I wanted my software to be able to distinguish between them, so I cut the trace for the left command (GUI) key, and wired it directly to the teensy. Also, as hasu/soarer (I forget which) suggested on the geekhack forums, I connected a 1kΩ external pull-up resistor to the ADB pin.

The teensy is located at the edge of the board so that it can fit into a small "channel" on the bottom of the case. It's snug--I had to tape a little piece of plastic around the teensy's button to prevent it from being pressed once the keyboard was assembled, and also dremel the portion of the case containing the USB port, in order to get it to fit. For such a large keyboard, there's suprisingly little room.

Software

My software's USB support is based loosely on the PJRC keyboard and mouse examples, but has been heavily-modified into a more object-oriented style. I wrote the ADB support myself, but was inspired by, and referred to, hasu's ADB-to-USB converter, as well as Chapter 6 of the Apple IIGS Hardware Reference, which hasu refers to in his documentation. All source code is copyrighted, and licensed under the GPLv3 (PJRC kindly permits relicensing under certain conditions). Be warned that the code is overcomplicated and poorly-documented--I hope to improve it in the future.

  TAR.GZ ZIP
Source code aek2_src.tgz (67K) aek2_src.zip (93K)

As is typical in such keyboard-controller projects, my software supports multiple layers. In particular, it's configured with a media layer (activated by pressing the right option key) and support for the Matias half-QWERTY layout (activated by pressing the spacebar in the media layer). This pdf file documents the current keyboard mapping, although of course it is configurable (by changing the tables in main.cc).

NKRO-over-USB is supported (although the AEK2's keyboard matrix is not NKRO, so this is of limited usefulness). You can find the HID descriptors in the code, but the basic idea is to have two keyboard interfaces, the first of which is a boot-mode interface. The second interface contains two seven-byte reports with bit flags for the (in my opinion) 112 most-useful keys, as well as a third report for consumer controls. Keypresses are sent through the boot-mode interface unless it is "full", in which case they fall-back to the extended interface. I've tested this on Linux, OSX and Windows, and it works (although perhaps it won't on older versions of these OSes). There is also a mouse interface, which is used by the mouse keys.