I did this conversion quite a while ago, but since this was a fun process, the keyboard is pretty interesting and because this could potentially be of interest to others, I still decided to write about it.
I found this keyboard on a local flea market, it was love at first sight. When I got it it looked like this:
Maybe a little bit yellowed, but overall in good condition, nothing a good old retr0bright can't fix. But before that I wanted to get that keyboard up and running, so the first thing I did was to disassemble the unit to get a glimpse at the PCB:
You can easily spot the Hall Effect sensors, which are arranged in a matrix of 13 columns and 8 rows. Other than that there isn't much going on here, the big IC in the middle is an Intel 8048 compatible microcontroller. 4 of its pins are connected to a demultiplexer located to its right which is used to strobe the columns of the switch matrix. The demultiplexer expects the column index through a binary encoding from its 4 input pins. This means that the microcontroller can strobe all columns with only 4 of its pins being used! For sensing the 8 rows of the matrix are directly connected to the microcontroller.
A nice side-effect from this design is the fact, that this board supports inherent N-Key Rollover. This is nothing I really need, but it's cool to see and for a Hall Effect keyboard I think such a feature is quite rare. Another useless but nevertheless really cool feature is the solenoid located on the lower right of the board.
In order to record my findings and to make working with this keyboard easier, I created a schematic of the circuit:
My first idea to get the keyboard working was to build a converter that can be plugged into the original cable. The original cable used a Micro D-Sub connector, something which I have never seen before, look how tiny it is compared to a regular D-Sub connector!
Since (at the time) I didn't have any advanced measuring equipment, which I could have used to reverse-engineer the protocol, I decided to desolder the microcontroller and read its ROM directly to figure out how everything works. Thankfully the MCS-48 line of microcontrollers has extensive documentation, so building a circuit with an Arduino to read it was straightforward.
After that I used a disassembler to convert the binary into a readable format. Up to this point everything went pretty well but unfortunately understanding the firmware was much harder than expected. I figured out, that I could use one of the pins of the connector to get the microcontroller to jump to the interrupt routine were it looked like some kind of IO could happen but from there on the code was much harder to understand because one instruction used an indirect jump. After some time I gave up on that approach and decided to do the conversion internally.
I decided to utilize a Teensy 2.0, because it has so many IO ports, that I only had to reroute a handful of signals and could leave most of the traces untouched. I also repurposed the connector on the board for a custom USB cable. Software-wise I decided to use the TMK Keyboard Firmware Core Library, which made everything pretty easy, especially when compared to reading antiquated 1970s assembler code. In the end the board looked like this:
After that the only thing left to do was retr0brighting and putting everything back together. Here is a picture of the keyboard after everything was done:
Chyrosran22 already did a fantastic job reviewing the unit so I'll leave a link to his video here. I agree with him that the switches are incredibly smooth, but unfortunately a little bit too heavy for me for daily use. The solenoid was a bit surprising, though. It not only is loud as hell when activated, but it also makes the whole keyboard slightly vibrate which makes the switches feel almost clicky. Overall this was a very fun and instructive undertaking and if there's someone else on this planet who owns this keyboard and is looking to convert it I hope this is a helpful resource. For the interested reader, I created a GitHub Repository for the code I wrote along with more detailed install instructions.
ITT Courier 110169 Hall Effect Keyboard USB Conversion
- JP!
- Location: United States
- Main keyboard: Currently a Model M
- Main mouse: Steel Series Sensei
- Favorite switch: Beam Spring
- DT Pro Member: 0194
- Contact:
Stunning work. I definitely found this informative.
-
- DT Pro Member: -
I'm trying to do a quite similar situation job except my board is with sw switches, and I think I understand most of your thoughts.
What confused me is: which pins of the sensor do the columns and rows of the matrix connect on respectively? Noticed your back pcb shows 4pins for every sensor but only 3 of them has connecting trace. I guess they should be VCC,GND and output, right? According to your code, the D7, D6, B5, B4 played the driver rows through a demultiplexer so the rows should be set to zero iterablly( I havn't checked the datasheet of the demultiplexer for specific detail, but anyway the rows should be set zero?), should they be connecting to the output pin of the sensors?
Im really messed about the hall effect switches mechanism, but you have done a really cool job. Thanks for sharing that.
What confused me is: which pins of the sensor do the columns and rows of the matrix connect on respectively? Noticed your back pcb shows 4pins for every sensor but only 3 of them has connecting trace. I guess they should be VCC,GND and output, right? According to your code, the D7, D6, B5, B4 played the driver rows through a demultiplexer so the rows should be set to zero iterablly( I havn't checked the datasheet of the demultiplexer for specific detail, but anyway the rows should be set zero?), should they be connecting to the output pin of the sensors?
Im really messed about the hall effect switches mechanism, but you have done a really cool job. Thanks for sharing that.
- DrCracket
- Location: Germany
- Main keyboard: IBM Model F AT
- Favorite switch: Capacitive Buckling Spring
You are right in that the output pins of the demultiplexer are set to low depending on the input signal, however they are not connected to the output pins of the sensors. On this board all 4 pins of each sensor are used. The signals are VCC, GND, input & output respectively. The demultiplexer output pins are connected to the input pins of the sensors. When the input signal of a sensor is high, the output signal is also always high. When the input signal is low, the output reflects the state of the switch. If the switch is pressed the output is low and this is what the microcontroller senses. For reference here is the datasheet for these 4-terminal (and also 3-terminal) sensors.John Doe wrote: ↑27 Nov 2020, 10:13What confused me is: which pins of the sensor do the columns and rows of the matrix connect on respectively? Noticed your back pcb shows 4pins for every sensor but only 3 of them has connecting trace. I guess they should be VCC,GND and output, right? According to your code, the D7, D6, B5, B4 played the driver rows through a demultiplexer so the rows should be set to zero iterablly( I havn't checked the datasheet of the demultiplexer for specific detail, but anyway the rows should be set zero?), should they be connecting to the output pin of the sensors?
I hope this helps, glad you like this project
-
- DT Pro Member: -
Thanks, DrCracket. Your link helped correct my misunderstanding of my 3-terminal sensors kb, now it could register but I still need to find out the matrix to remap the keys. I have to say it's abit counterintuitive compared with other normal keyboard scan modules, I have a new level concept about the halleffect kbds.DrCracket wrote: ↑27 Nov 2020, 16:37You are right in that the output pins of the demultiplexer are set to low depending on the input signal, however they are not connected to the output pins of the sensors. On this board all 4 pins of each sensor are used. The signals are VCC, GND, input & output respectively. The demultiplexer output pins are connected to the input pins of the sensors. When the input signal of a sensor is high, the output signal is also always high. When the input signal is low, the output reflects the state of the switch. If the switch is pressed the output is low and this is what the microcontroller senses. For reference here is the datasheet for these 4-terminal (and also 3-terminal) sensors.John Doe wrote: ↑27 Nov 2020, 10:13What confused me is: which pins of the sensor do the columns and rows of the matrix connect on respectively? Noticed your back pcb shows 4pins for every sensor but only 3 of them has connecting trace. I guess they should be VCC,GND and output, right? According to your code, the D7, D6, B5, B4 played the driver rows through a demultiplexer so the rows should be set to zero iterablly( I havn't checked the datasheet of the demultiplexer for specific detail, but anyway the rows should be set zero?), should they be connecting to the output pin of the sensors?
I hope this helps, glad you like this project
Thanks again.
-
- Location: Norway
- Main keyboard: Unicomp 122
- Favorite switch: Beamspring
I have the same type of switches (broadly speaking), 4B3S, so logic scan switches. I also have the same type of controller with the same type of multiplexer. Very similar set up. The chips around are a bit different, but most are redundant when converted to USB in my case as well as far as i can see.
Is IC1 used for anything in your board? I do not have a chip like that in my board as far as i can see. If i have not misunderstood my circuit, strobing of the multiplexer are driven from a 74121 as a "clock" circuit. Are the G1 and G2 inputs of your multiplexer driven by the teensy?
The matrix is 16x8 in my case. Do i have to modify your code to get all the columns working? I guess i have to do some modifying anyway as the layout is vastly different, but i would be happy just getting an output for starters. The rows have pull up resistors in my case, is it necessary to remove these or should i keep them? I cant see any on your board.
Some help would be very appreciated, i am a bit green yet on this.
Is IC1 used for anything in your board? I do not have a chip like that in my board as far as i can see. If i have not misunderstood my circuit, strobing of the multiplexer are driven from a 74121 as a "clock" circuit. Are the G1 and G2 inputs of your multiplexer driven by the teensy?
The matrix is 16x8 in my case. Do i have to modify your code to get all the columns working? I guess i have to do some modifying anyway as the layout is vastly different, but i would be happy just getting an output for starters. The rows have pull up resistors in my case, is it necessary to remove these or should i keep them? I cant see any on your board.
Some help would be very appreciated, i am a bit green yet on this.
- Attachments
-
- Untitled.jpg (1.49 MiB) Viewed 3974 times
-
- 188433521_217240586624008_157136297309217957_n.jpg (909.97 KiB) Viewed 3974 times
-
- 187119518_801466890511520_85760336132813495_n.jpg (1.5 MiB) Viewed 3974 times
- DrCracket
- Location: Germany
- Main keyboard: IBM Model F AT
- Favorite switch: Capacitive Buckling Spring
Hi, if I remember correctly I only use IC1 to drive the solenoid, so don't worry if your board doesn't have it. If your board works like mine you can probably leave the resistors in place. Also I THINK G1 and G2 are connected to ground on my board, but don't trust me on this. But anyway, just make sure they are low when you read the matrix.thor435 wrote: ↑24 May 2021, 16:39I have the same type of switches (broadly speaking), 4B3S, so logic scan switches. I also have the same type of controller with the same type of multiplexer. Very similar set up. The chips around are a bit different, but most are redundant when converted to USB in my case as well as far as i can see.
Is IC1 used for anything in your board? I do not have a chip like that in my board as far as i can see. If i have not misunderstood my circuit, strobing of the multiplexer are driven from a 74121 as a "clock" circuit. Are the G1 and G2 inputs of your multiplexer driven by the teensy?
The matrix is 16x8 in my case. Do i have to modify your code to get all the columns working? I guess i have to do some modifying anyway as the layout is vastly different, but i would be happy just getting an output for starters. The rows have pull up resistors in my case, is it necessary to remove these or should i keep them? I cant see any on your board.
Some help would be very appreciated, i am a bit green yet on this.
If you want to use my code as a base, you first have to change the MATRIX_ROWS macro in config.h. The code to actually drive the matrix is in matrix.c. Since my wiring also theoretically supports a maximum of 16 rows you shouldn't have to change much (if you use the same pins). You definitely need to change select_row though. There I skip rows 11 and 13 since they are not connected on my board, I think you should remove that. Maybe also try to understand the rest of the function, since I'm not sure anymore if it's specific to my board or not After that update the KEYMAP macro in keymap_common.h, which is a mapping from the keyboard keys to the position in the matrix. Then you're all set to define your own keymap in keymap_plain.c, like I did.
BTW, very nice board you procured there, I wish you luck with your conversion