UPDATE 2017-11-02: After messing with this some more (and using a better scope), I found that the timing is actually around 54us rather than 50. That clears up some confusion I had about timing for the alpha lock below. Also updated/fixed the KB packet description.
There isn’t much information about the NeXT non-ADB keyboard protocol around, so below are the things I’ve learned after messing around with it. The best resource out there was this site but it seems to be gone now. Thanks also to adafruit, this japanese site, and of course the NeXT Computers forums.
Signals go from the NeXT through a soundbox or monitor and then to the keyboard. Between the soundbox and keyboard it is a polled protocol consisting of queries from the computer and responses from the keyboard.
This page is focused on the protocol from the monitor/soundbox to the keyboard.
The pinout on the soundbox is a mini-DIN 5 and looks like this:
5 4 5: GND 4: Power Switch
3 2 3: From KB 2: To KB
1 1: +5V
If yours has 4 pins, that’s an ADB soundbox, but don’t worry, you can convert it. Massive thanks to Asterontech for the very useful info about that as well as building a 13W3 Y-cable.
The protocol seems to be made up of one or two bytes with a low start bit and a stop bit (which can be high or low) sent LSB first. Timing is around 54 microseconds, high is +5V, low is 0V. Multiple bytes from the keyboard are separated by 1 bit high. Two bytes from the ASIC have an extra bit in the middle, no idea why. The stop bit seems to change depending on the request.
The soundbox ASIC appears to tolerate TTL levels (3.3V high) just fine, but the keyboard is a CMOS device (it wants 5V high, 0V low).
KB Idle
-----_________--_________----- (0x00, 0x00, stop bit high for both bytes)
- = high
_ = low
~54us each character
The system continuously sends keyboard and mouse queries with a 1750us gap between them. If it doesn’t receive a response it will send a reset packet. Queries from the computer are a single byte, 0x10 for KB, 0x11 for mouse. In the trace above you can see a mouse request, set LEDs command, and a keyboard request.
The keyboard does not start responding after power up until it receives a reset packet, even though the sound box sends KB/mouse requests before that.
KB Query
-----_____-____----- (0x10 = 00010000)
Mouse Query
-----_-___-____----- (0x11 = 00010001)
KB Reset
-----_----_------__________----- (note the extra bit in the middle, 22 bits total)
The computer can also set the state of the alpha lock LEDs by sending a zero byte followed by the LED status.
LEDs Off
-----_________---__________----- 0x0, 0x0
Left LED On
-----_________---_-________----- 0x0, 0x1
Right LED On
-----_________---__-_______----- 0x0, 0x2
Both LEDs On
-----_________---_--_______----- 0x0, 0x3
2017-11-02: Correction! (again) The timing is actually about 54us per bit, which accounts for the weirdness I was seeing here.
Responses consist of a two-byte packet sent after the appropriate query. The keyboard packet is the 7-bit keycode with a make/break bit followed by a modifier status byte.
KB Packet
-----_CCCCCCCB_-_MMMMMMMM_----- (only 1 middle bit, 21 bits total)
B: Make/Break (0/1)
C: 7-bit keycode
M: Modifiers
The stop bit for the first byte is low whenever sending a keypress. Same for the second byte - it’s only high in the idle packet.
Modifier state is sent two ways: along with a keypress, or by itself with 0x80 as the first byte. It is not sent with the idle packet.
The first mouse byte contains bits for BTN1 and the X-axis movement, and the second contains BTN2 and Y-Axis bits. I had been messing around with some incorrect info that I found floating around the internet, but working with an old Mac and ADB led me to think that this was probably very similar.
The mouse sends the same idle packet as the keyboard. In a packet with mouse events, both stop bits are low.
Mouse Packet
-----_1XXXXXXX_-_2YYYYYYY_-----
1: Button 1, 0 = down
2: Button 2
XXXXXXX: X movement, 7 bit two's complement
YYYYYYY: Same thing for Y axis
Why do all of this? I didn’t have a NeXT keyboard and mouse and thought I could probably use my USB ones somehow. All I’d have to do is figure out the protocol and put together some sort of microcontroller thing to emulate it.
In the video I’m using a Vinculum-II USB microcontroller and an Arduino to accomplish this. The VNC2 couldn’t quite handle the timing for the interrupts so I’m using that just for USB, then it talks to the Arduino over serial and the Arduino can handle the precise timing piece.
Update: I have some products available over at drakware that will convert a NeXT keyboard to USB or vice versa!
Questions? Email: matt -at- drak.org