Ever since I stopped using a Sun SparcStation as desktop (around 94 or so) I wanted a decent Type 4 or 5 on my pc - alas, the Type 4/5 are serial keyboards and hence not directly supported by normal pcs. Getting the Type 5 to work under Linux wouldn't have been too hard (it's serial after all), but that isn't good enough: I wanted a decent solution that also work for BIOS interaction and in Windows (and even the Linux-only solution would have required soldering up a TTL inverter).

So why not build a converter?

Being lazy until recently I compromised (sort-of) by using an IBM Model M: my Model M was made in 84, weighs a ton and a half, and works beautifully...but it's very very noisy (a consequence of the buckling spring mechanism) and that finally got on my nerves.

About eight or nine years ago I saw this Sun to PS/2 converter project, which unfortunately is rather complex to build and uses very obsolete hardware to pull it off...too much of a hassle. And the few commercial converters that I could find were ridiculously expensive.

So finally I built my own converter which needs only two active and one passive component: one PIC16F628a microprocessor to do the heavy lifting, one 7404 TTL inverter and one capacitor. Together with a bit of prototyping board, a PS/2 cable with plug and a female minidin-8 socket I estimate the total cost to be no higher than AUD15.

Mine actually cost less: I bought some 16F628s in bulk some time ago, the 7404 was an ancient left-over (markings indicate it was made in the 80s...), the PS/2 cable and plug came from a dead donor keyboard and the minidin-8 socket I recycled out of a dead Sun.

And what about the software? That's my contribution. (Open Source, of course.)

More recently, after having decided to build my own PS/2-based converter I found out that Marijn Kentie has created a PIC-based one that does Sun-Type-4/5-to-USB, with a PIC18F. *silly hat on* But his is written in C and therefore less cool than my handcrafted PIC assembler code. *silly hat off*

Preliminaries: Sun

The Type 4 and 5 Sun keyboards are very simple beasts explained nicely in the SPARC Keyboard Specs: they communicate with the host using RS-232 at 1200 bps, 8N1 - but with inverted TTL logic levels (0V = 1, 5V = 0). +5V power is provided together with the signal. All keys have a one-byte code that is sent on "make" (key pressed) and code+0x80 is sent on "break" (key release). No typematic repeat, that is handled by the host. The keyboard has a few more keys than normal pc keyboards, and one more LED, on the compose key. The keyboard also has only a few trivially simple commands (reset, led setting, beeper on/off and click on/off). The pinout of the minidin-8 connector is straightforward. And that's all there is to it. Neat, simple, efficient.

Dealing with this stuff on a PIC is easy, especially when you use one with USART built-in, like the 16F628 - the only necessary extra is a 7404 inverter to translate the signal levels.

Preliminaries: PS/2

The electrical PS/2 protocol is ugly, to put it politely. The PS/2 keyboard protocol is fucking horrible, and that's still putting it politely!

The electrical part is described very well by Adam Chapweske over there, but his treatise lacks precise timing information - that I found in this application note.

It's a two-wire bidirectional protocol, with a "master" (the host) that isn't mastering anything but the art of interrupting progress at any time it feels like it: the only thing the master ever does is tell the slave to stop whatever it's doing or to start clocking. With PS/2 it's the slave that outputs the clock pulses.

Device-to-host transmissions work different from host-to-device, adding to the fun for an implementor. At least all transmissions are done in bytes. Some of the borderline cases I didn't find any precise information on (e.g. the timing sequence of the host-to-device clocking request; the best I could find is 'host pulls clock low, then pulls data low, then releases clock'), but there seems to be a lot of leeway in the spec (e.g. pulse length can be anything between 25us and 50us).

And the electrical part is easy, compared to the backwards-compatible mess that the PS/2 keyboard protocol is: most of the crappy stuff dates back to 84-key PC/XT keyboards and contains lots of really lousy design decisions made by IBM.

IBM: It may be slow, but it's hard to use. -- Simon Cozens
The best explanation/material collection for the scan codes I found to be the one collected by John Savard.

In as few words as possible: keys send make and break codes ("scan codes" in PS/2 parlance), just like the Sun does - but the codes follow no useful scheme whatsoever and differ in size: anywhere from 1 to 8 bytes. One key sends no break code at all, and in theory there's three different set of codes for any single key (fortunately only Set 2 is required nowadays). And to make all this even more fun, the typematic repeat must be handled by the device, there's multiple repeat/delay rates as well, and there's a bunch of generally superfluous commands that a keyboard should understand as well. Lots of joy!

My students got a really good laugh out of it when I told them last week that I write code in assembler for fun (and indeed, the PS/2 part of this project was "lots" of fun, for masochistic values of lots).

My Converter

The PIC deals with the Sun using its built-in USART, with the 7404 inverter sitting inbetween. The PS/2 side is done "manually", bit-banging two ports of the PIC whose internal pullup resistors are enabled.

The mechanical layout of my converter is trivial: a small piece of prototyping board holds two sockets for the PIC and the 7404, and one 22uF electrolytic capacitor sits near the PIC. One end of the board holds a female minidin-8 socket for the Sun keyboard plug, and the PS/2 cable was soldered in at the other end. Power comes from the PS/2 connector, and powers everything: the PIC, the 7404 and the Sun keyboard.

Here is my prototype (with extra in-circuit programming sockets):

The electrical setup is about as trivial, and shown on this schema. I've even cooked up a small PCB design (untested, though). These PNGs are 300dpi and if you use this for a toner transfer you'll have to mirror the silk side but not the solder side.

Limitations

Code! Code! Code!

The code is as simple and robust as I could make it, and pretty well documented - I think.

The keycode to scancode translation is done with two tables, one 128 byte one (for the one-byte scancodes) and one 27 byte one (for the two byte scancodes). The Pause key is handled separately. As the 16F628 has only 128 byte of EEPROM the two tables are done using the trusty old computed-goto method.

Sun input is handled via an interrupt handler which pushes key codes into a small (8 byte) inbound fifo. The main loop monitors the PS/2 bus for activity (remember, the PIC has to clock for the host on request) and otherwise processes key codes from the input fifo: it translates them into scan codes and pushes those into an output fifo (16 bytes deep).

The main loop also empties that fifo by sending out pending scancodes whenever the PS/2 bus allows it, and furthermore deals with the few PS/2 commands that are implemented. Sending to the Sun keyboard is done via the USART, and due to the PIC hardware that's a fire-and-forget operation (for up to two sequential bytes).

Another part of the interrupt handler deals with timeouts: a timer is armed whenever a make code is processed (and disarmed on break) and when the timer expires the interrupt handler inserts another copy of the held-down key code into the inbound fifo and rearms the timer (initial 250ms, then 33ms). And that's about it.

For those of you who like to tinker with the source: go for it! It is, as usual, GPL-licensed and as such freely available for your use.

Here is the list of files:

Enjoy!

Update (Mon 21.02.2011 15:34):
Steve Powers noticed that I swapped the +5 and Gnd lines on the PCB design, and I've updated the images to correct that.
[ Thu 11.03.2010 17:45 | /mystuff | comment ]

Debian Silver Server Valid HTML 4.01! Valid CSS!
© Alexander Zangerl