[SIZE=+1]How to build a USB controller for your keyboard.[/SIZE]
Some time ago I've noticed that my
IBM Personal System/2 Space Saving Keyboard (or just my "Mini") had a little problem:
the controller would heat up during operation, and I feared it could fail some time. So I replaced the original controller with a homebrew USB controller running my custom
Keyboard Upgrade firmware. I've done this before for another M, but this time I took some pictures of the progress and documented how I have built the controller.
Even though I only needed the controller for a Model M Mini (i.e., no LEDs), I thought it would be a good idea to build one that could also be used in a full-size 1391401, and hence make these instructions more useful for more people. I tested the controller in a 1391403 (which is a 1391401 with the annoying German layout) to make sure it would really fit in there and work as it should--which it does.
Since I didn't want to handle chemicals and also wasn't ready to spend serious money on a professionally etched PCB, I used
stripboard for making the controller. Unfortunately, stripboards are a mess, so most of this post describes how I treated a stripboard to recreate the design found on
this page. Scroll all way down to the end of this post for some notes on "real", etched PCBs.
Meanwhile, my industrial gray Model M Mini has arrived, which I am using now instead of my other Mini. I moved the USB controller over to the gray Mini, and this is what it looks like:


Must be the most modern industrial Mini in the world! :D
[SIZE=+1]Materials and tools[/SIZE]
Materials used:
[*]One "standard" piece of stripboard (100 x 160 mm, 2.54 mm pitch). These are available in various qualities. I opted for a higher quality fiberglass board because the cheaper phenolic boards tend to smell quite a bit. The smell can be very annoying as I have learned by using such a board in my IBM M4-1.
[*]One AVR ATMega16 or ATMega32 in DIL-40 package. The bigger ATMega32 is slightly more expensive, but also has more EEPROM capacity, allowing you to store more key maps on your controller. I'll recommend the ATmega32 unless you are extra cheap or have an ATMega16 lying around anyway.
[*]DIL-40 IC socket
[*]6-pin single row jumper header, 2.54 mm pitch
[*]6-pin dual row jumper header, 2.54 mm pitch
[*]resistors: 2 x 68 Ohm, 3 x 470 Ohm, 1 x 2.2 kOhm, 1 x 4.7 kOhm, 1 x 10 kOhm
[*]capacitors: 2 x 22 pF, 1 x 100 nF
[*]2 x 3.6 V Z-diodes
[*]12 MHz crystal oscillator
[*]USB type B receptacle connector, right angle, solder type
[*]3 x FFC connector (flat flexible cable connectors), 2.54 mm pitch, vertical PCB mount type. You'll need one with 8 and one with 16 terminals for connecting the keyboard matrix, and another one with 4 terminals for the LEDs. It might be hard to obtain these--in worst case you could sacrifice your original IBM controller and desolder its connectors.
[*]loads of wires
[*]thick wire and a ring terminal for grounding
[/LIST]
Tools used:
[*]soldering iron, solder, etc.
[*]diagonal pliers
[*]wire stripping pliers
[*]cutter knife
[*]file
[*]multimeter (to check for shorts)
[*]Dremel rotary tool (optional)
[*]3.5 mm and 2 mm drill bits, and a drill
[*]5.5 mm socket wrench to open the keyboard (check out
this thread if you don't have one already)
[/LIST]
(And yes, I am ignoring medieval ways for specifying lengths. This world is metric. Get used to it. ;) )
[SIZE=+1]Build![/SIZE]
So, here are the instructions for building a cheap IBM Model M USB controller... Please read the instructions in full length before attempting to build your own.
The resolution of some of the pictures below may not be high enough to show all the necessary details. Therefore, I have attached larger versions
here and
here.
First, cut the stripboard into pieces as illustrated on the following picture using a Dremel or a cutter knife (which is harder). It is OK for the bigger pieces to be a tad larger than shown on the picture since the size of the USB board is not as critical. The main board should not be smaller than shown on the picture. If done correctly, you'll end up with four pieces that could actually be used to make
two controllers: two bigger pieces with 39x20 holes, and two smaller 19x20 ones.

File down one of the long sides of the main board until it fits easily into the tray where the old controller was (
don't force it in!), right next to the two poles that hold the controller in its place.
Drill the USB board as shown on the next picture. The smaller holes will pick up the USB connector. The bigger holes should fit over the two poles at the gap for the SDL connector so that the board is held in its place just like the old controller was (later, we will attach the USB board to the main board so that they appear as a single board). Make sure to remove enough copper surrounding the big holes so that it cannot eat into or otherwise damage the plastic poles. Again:
don't force anything here and make use of your tools!
Now as the boards are correctly sized and drilled, cut the copper strips in the red-marked areas as shown below. I used a Dremel for the coarse cuts, and a cutter knife to rework some improperly cut strips. Double-check for shorts with a multimeter.


We'll be running wires from underneath the IC socket, so you'll need to make sure that there is enough room to route some wires below the short sides of the socket. (Scroll down a bit and look at one of the pictures with the IC socket soldered in to see what I mean.) My socket had some ridges on both sides standing in the way which I had to remove with a cutter knife like this:

That's it for the mechanical work, you may stow away your Dremel now. Heat up your soldering iron and start soldering some wires onto the stripboard as shown on the next two pictures. There are direct connections between neighboring copper strips in the two green marked areas; these are intended and no mistakes.


What follows is a list of the wire connections seen on the pictures.
Holes are identified using the coordinate system displayed on the pictures; e.g., coordinate 4/9 means row 4, column (or copper strip) 9.
Blue White Red Direct
4/ 9 - 5/12 5/20 - 5/27 17/12 - 17/24 6/28 - 6/29
4/10 - 5/13 6/24 - 6/28 18/10 - 18/23 6/29 - 6/30
4/11 - 5/14 9/15 - 9/29 17/11 - 17/12
4/12 - 5/15 9/17 - 9/30 (9/27 - 9/28)
4/13 - 5/16 9/27 - 9/28 [2]
4/14 - 5/17 13/23 - 13/37
4/15 - 5/18 14/ 2 - 14/13 [3]
4/16 - 5/19 14/ 4 - 14/12 [3]
10/18 - 10/39 [1]
10/19 - 11/38 [1]
10/20 - 11/36 [1]
[1] End points are not connected in these pictures yet. See below.
[2] Can be replaced by a "green" direct connection, but I didn't think of this at the time...
[3] Bend wires, do not make a straight connection. See below.
I kept the three long blue wires rather long and loose on one end because I didn't know how long they should really be at that point. You may just take a look at one of the later pictures to get their lengths right in the first place. :)
The two white wires 14/2-14/13 and 14/4-14/12 need to run around the programming connector that is soldered in later. Hold the 6-pin jumper header at 14/6-14/11 and route the wires around it to get them right; also check out the pictures below. I didn't solder the header in at that point, however, because it would have stood in the way all the time.
Next come 8 wires that you'll need to make long enough to "flow around" the IC socket (look at one of the next pictures to get an idea). Hold the socket into its later place--rows 6 and 12 and starting in column 1--to get the lengths right (I didn't really measure their lengths). I've actually made the four "inner" wires a bit too short for this controller, which is why they are sitting rather tight around the socket...

Connections:
10/1 - 4/23 10/5 - 4/27
10/2 - 4/24 10/6 - 4/28
10/3 - 4/25 10/7 - 4/29
10/4 - 4/26 10/8 - 4/30
This is how your controller should look like after putting in the IC socket, dual row jumper header, and soldering the three loose ends mentioned before:

This is a good time to double-check all connections. Are there any shorts? Do the connections work? Any weak solder joints? This is really important--do yourself a favor and don't skip this step.
We'll carry on by soldering in the components. I've added the 8 resistors and 3 capacitors for the next picture. No new wires here.

Components:
Resistors Capacitors
4/36 - 9/36 (470 Ohm) 13/11 - 13/12 (22 pF)
4/38 - 9/38 (470 Ohm) 16/10 - 16/11 (100 nF)
4/39 - 9/39 (470 Ohm) 16/12 - 16/13 (22 pF)
10/22 - 10/24 (4.7 kOhm)
11/22 - 11/23 (2.2 kOhm)
13/14 - 13/22 (68 Ohm)
14/16 - 14/21 (68 Ohm)
16/ 9 - 16/23 (10 kOhm)
Then, add the 2 Z-diodes, crystal oscillator, programming header, and the FFC connctors for the keyboard matrix. My version of this controller lacks the connector for the LEDs because I didn't have a spare one, so instead I've marked the place in the picture where the 4-pin connector should go. It should face in the same direction as the neighboring 8-pin connector, with the four legs soldered in the green marked area (row 3). Pay attention to the correct orientation of the FFC connectors (all of them!).

Components:
Z-diodes Crystal
12/21 - 12/24 16/2 - 16/4
15/22 - 14/24
16-pin connector : 2/ 1 - 2/16
8-pin connector : 3/23 - 3/30
4-pin connector : 3/36 - 3/39
6-pin jumper header: 14/ 6 - 14/11
The diodes are the only components in this circuit where polarity matters, so take care to solder them in in the correct orientation. The black rings mark the cathodes and go to holes 12/21 and 15/22, respectively.
Note that the 6-pin header for hooking up the AVR programmer is not exactly "the standard way to do it"; commonly, 6- or 10-pin IDC sockets are used for this. The six pins on this design, however, connect straight to pins 6 through 11 on the AVR, which is much more convinient on stripboard. Another reason to go with this solution is space: there is not enough room for an IDC socket in this location when putting the controller into a Mini.
If you are planning to use your controller in a Space Saving keyboard, then you still must
cut the header pins to a shorter length so that they don't make contact with the metal plate of the keyboard assembly! There is really much less vertical space in a Mini than in a full-size Model M. Your best bet is to put the board into the keyboard case and take a good look if the pins are touching the plate when putting in the assembly; cut the pins accordingly while keeping them long enough to make contact with a programming connector. Make sure that the keyboard assembly is really in its place when doing this, i.e., it must be fully inserted and held in its place by the rectangular plastic poles at its top, and not "hang" or be otherwise misaligned.
So, most of your controller is ready by now. Solder the USB connector to the USB board, and add four long wires to the copper strips that run to the pins on the connector. The wires will provide the electrical connection between the smaller USB board and the larger main board. Their names are "GND", "+5V", "D-", and "D+", corresponding to the pins on the USB connector. Again, I didn't really measure the lengths of the wires...
Also add the thick grounding wire now that will go to the keyboard assembly--I forgot it at first, but added it later. Depending on the type of cable that you are using for this, you may need to drill the hole for the grounding wire a bit larger.


Connections:
Blue Red White Direct
16/10 (D+) 16/8 (+5V) 16/7 (GND) 3/7 - 3/ 8
16/ 9 (D-) 3/9 - 3/10
Grounding wire: 10/7
USB connector: pins at 4/8, 4/9, 5/8, and 5/9
We are still missing the mechanical connection between the two boards in order to get "one" controller board. As seen already on the previous picture, I used some junk wire that I've cut off from the resistors to tie them together (do not forget to remove the copper from the area around the holes when using wire!). The connection is flexible and not overly stable, a bit like a hinge, but that's more than we need. Here is a close-up of the two "wire hinges" marked by green circles:

Alright, here is the last step: connect the four wires to the main board. This picture also shows the grounding wire that I have added a bit too late (at hole 10/7):


Connections:
Blue Red White
19/21 (D+) 19/10 (+5V) 19/11 (GND)
19/22 (D-)
Check again all solder joints, at least visually. Take good care that there are no connections between neighboring copper traces where there should be none. Sometimes these accidental connections are hard to spot, so take a good final look.
Well done!
The hardware is ready to be programmed now.

Here is the pinout of the programming header on the controller. Your AVR programmer will likely have a 6-pin or a 10-pin IDC socket, or both. Build an adapter cable according to one of the following pinouts in order to program the AVR on the controller. Do not plug the controller into your computer's USB plug when attaching the programmer to the programming header!
6-pin at | header pin on 10-pin at | header pin on
programmer | controller programmer | controller
------------+--------------- ------------+---------------
1 (MISO) | 2 1 (MOSI) | 1
2 (+5V) | 5 2 (+5V) | 5
3 (SCK) | 3 3 (NC) | -
4 (MOSI) | 1 4 (GND) | 6
5 (nRESET) | 4 5 (nRESET) | 4
6 (GND) | 6 6 (GND) | 6
7 (SCK) | 3
8 (GND) | 6
9 (MISO) | 2
10 (GND) | 6


This is my cable:

A bit rough--I know you can make a nicer one! :)
If you don't want to make an adapter cable, see
here for a "quick how-to guide on making ultra-simple development boards for programming AVR microcontrollers". Really simple, and saves you from building a custom cable.
Note: you should probably add a 12 MHz crystal oscillator and two 22 pF capacitors to the board (in the same places as on the keyboard controller) so that the AVR would still work after programming its fuses to actually make use of an external crystal oscillator...
[SIZE=+1]Jumpers[/SIZE]
There are three jumpers on the controller, in columns 28, 29, and 30. For normal operation, all of these should be left open.

Only one of the jumpers is used by the firmware at the moment, called
KM0 (for
Key
Map
0), located in column 28. Closing
KM0 forces the controller to use its built-in QWERTY key map. Use this in case you have activated a broken key map and cannot switch back to a good one anymore.
[SIZE=+1]Programming the boot loader and firmware[/SIZE]
The AVR needs, to the very least, a boot loader so that the main firmware can be programmed from your computer via USB. Firmware and boot loader images can be downloaded from
http://sourceforge.net/projects/kbupgrade/files/Firmware, sorted by keyboard model and AVR type. Choose the 1391401 version for a 1391401, and the 1392934 version for the Mini; the latter simply lacks LED and numpad support.
There is a file called file_id.diz in the zip archives that documents which values your AVR's fuses must be programmed to for the particular firmware. After programming the low and high fuses, write the boot.hex image to your AVR. You need to do this only once and not again for later updates. Then, program the main.hex image to the AVR, and lock the boot loader by programming the lock fuse to the value given in the file_id.diz file.
Note that for updating the firmware or uploading alternative key maps via USB you'll still need to build the corresponding tools from the sources for now. I do not have pre-compiled binaries of the required tools right now (too much extra work to keep them up-to-date for multiple operating systems and package management systems). Maybe I can build them for you on demand.
If you prefer to build the firmware (and tools) from scratch, you can download source tarballs from
http://sourceforge.net/projects/kbupgrade/files/Source or pull the latest sources from GitHub at
http://github.com/rhomann/kbupgrade. Follow the instructions given in the
INSTALL file.
That's all. Put your new controller into your keyboard and stow away or sell the original controller. :)
Plug in, and it should be recognized as a generic USB keyboard. For more documentation, read the
INSTALL file from the firmware sources (yes, the docs should be split somehow).
Have fun!
[SIZE=+1]But wait! Look at all those wires! I don't wanna mess with stripboards![/SIZE]
If you prefer an etched PCB and are able to produce one by yourself, you may want to take a look at either
Dulcimer or
RUMP. The relevant files are also found in
my source tree.
Both of the designs are compatible with my firmware, but only the Dulcimer design incorporates a connector for the LEDs.
Note that both designs were made with a full-size 1391401 Model M in mind, which has significantly more spare space than a Mini, especially in vertical direction. If you are planning to build a controller for your Mini using one of these designs, then
double-check that it will fit into the keyboard and that no component will touch the metal plate!
Programming works just like with the stripboard version, of course.