{
  "attachments": [],
  "title": "Building a USB controller for an IBM Model M",
  "tags": [
    "modelm",
    "diy",
    "keyboards",
    "hardware",
    "teensy",
    "microcontrollers",
    "electronics"
  ],
  "year": "2016",
  "month": "02",
  "day": "21",
  "isDir": false,
  "slug": "modelm-controller",
  "type": "entry",
  "date": "2016-02-21T19:00:00.000Z",
  "postName": "2016-02-21-modelm-controller",
  "html": "<p><strong>TL;DR</strong>: I wired up a Teensy 2.0++ to an IBM Model M keyboard,\nwhich gave it a USB interface and custom firmware that can remap keys and do\nother interesting things.</p>\n<!--more-->\n\n\n\n<nav role=\"navigation\" class=\"table-of-contents\"></nav>\n\n<p>In my <a href=\"http://blog.lmorchard.com/2016/02/06/keyboard-hacking/\">previous post</a>, I wrote about my initial forays into\nkeyboard hacking. I got my hands on a few IBM Model M keyboards, and built a\nPS/2-to-USB converter with a <a href=\"https://www.pjrc.com/store/teensy.html\">Teensy 2.0</a> so I could use it with my\nMacBook Pro after remapping some keys via the <a href=\"https://geekhack.org/index.php?topic=41989.0\">TMK keyboard firmware</a>.</p>\n<p>That was a pretty rewarding little hack. But, then, I found <a href=\"https://github.com/antonizoon/archivis.me/wiki/IBM-Model-M-USB-Controller\">Lawrence Wu's\nnotes</a> on replacing the original controller inside the IBM\nModel M.  In a nutshell, it turns out you can find ribbon connectors that work\nwith the Model M membrane layers and fit on a breadboard. That makes it easy\nto build - and reversible if I decide to return the keyboard to its original\nstate.</p>\n<h2 id=\"initial-prototype\">Initial Prototype</h2>\n<p>So, I ordered a few of the <a href=\"http://www.mouser.com/ProductDetail/TE-Connectivity/6-520315-6/?qs=sGAEpiMZZMvYKGyZxp8jxkA16bSpREuh\">16-pin ribbon connectors from Mouser</a>\nand a <a href=\"https://www.pjrc.com/store/teensypp.html\">Teensy 2.0++</a>. My first stab at wiring things up was\npretty simple:</p>\n<p><a data-flickr-embed=\"true\" data-footer=\"true\" href=\"https://www.flickr.com/photos/deusx/24987051026/in/photolist-E52aJA-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz-Dzg18k\" title=\"Original prototype for replacement IBM Model M keyboard controller\"><img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/24987051026_0d0b1ac2a9_z.jpg\" alt=\"Original prototype for replacement IBM Model M keyboard controller\" width=\"\" height=\"\"></a></p>\n<p>The <a href=\"https://www.pjrc.com/store/teensypp.html\">Teensy 2.0++</a> has 20 pins per side, and I needed 16 for the\nfirst ribbon. So, it was convenient to just plonk both onto the breadboard and\ntake advantage of the built-in conductors. That's also why I upgraded from a\n<a href=\"https://www.pjrc.com/store/teensy.html\">Teensy 2.0</a>: I needed more pins. The second ribbon needed\n8 pins, so I cut some lengths of <a href=\"http://amzn.to/1oCuCJ1\">hook-up wire</a> to keep things neat\nand ran the connections over.</p>\n<p><a data-flickr-embed=\"true\" data-footer=\"true\" href=\"https://www.flickr.com/photos/deusx/24684318539/in/photolist-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz/\" title=\"5.5mm nut driver needed for opening IBM Model M keyboards\"><img class=\"inset wide right\" src=\"/uploads/2016/modelm-controller/24684318539_4dde739235_n.jpg\" alt=\"5.5mm nut driver needed for opening IBM Model M keyboards\" width=\"\" height=\"\"></a></p>\n<h2 id=\"driving-me-nuts\">Driving Me Nuts</h2>\n<p>Then, I wanted to get inside the keyboard to start tinkering. As it turns out,\nopening up an IBM Model M is annoying: None of the tools I had on hand could\ndo it. </p>\n<p>The case is assembled using screws with 5.5mm nut heads, rather than\nsomething like a Phillips-head screw. And, the screws are down in deep wells\ntoo narrow to fit any of the socket wrench heads I had on hand.</p>\n<p>So, I had to order <a href=\"http://amzn.to/1RgjN8k\">a 5.5mm nut driver</a> with a very slim head.\nReading <a href=\"http://www.amazon.com/Dynamite-2803-Nut-Driver-5-5mm/product-reviews/B000BQ4XP6/ref=cm_cr_dp_see_all_summary?ie=UTF8&amp;showViewpoints=1&amp;sortBy=helpful\">the reviews</a>, I can see I'm not alone in this.</p>\n<p>While that made its way to my house, I'd read that <a href=\"https://deskthority.net/workshop-f7/model-m-disassembly-t1960.html#p34013\">some folks used a lighter\nand a pen</a> to form a makeshift nut driver. That was a terrible\nidea, but it worked. In hindsight, I really should have just waited for the\ndriver to show up. But, I was determined to get the thing open while I had\ntime to play with it.</p>\n<h2 id=\"the-original-controller\">The Original Controller</h2>\n<p>And, once open, this is the board I found inside:</p>\n<p><a data-flickr-embed=\"true\" data-footer=\"true\" href=\"https://www.flickr.com/photos/deusx/25046846995/in/photolist-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz/\" title=\"IBM Model M original controller board\"><img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/25046846995_c8dab2484c_z.jpg\" alt=\"IBM Model M original controller board\" width=\"\" height=\"\"></a></p>\n<p>I should have taken a picture of it in place, but oh well. The board has a\ngrounding strap that was screwed down to the steel plate under the keys.\nBeyond that, it just fit into plastic brackets in the case and wasn't\notherwise fastened down. And, in a weird coincidence, the board was almost the\nexact same dimensions as my breadboard. Maybe these things are standard sizes?</p>\n<h2 id=\"mapping-the-membranes\">Mapping the Membranes</h2>\n<p>With the keyboard membrane ribbons free from the original board, I hooked them up to\nmy prototype. From there, I wanted to start making the keys send the right\nsignals. There are three parts to this:</p>\n<ol>\n<li>Mapping Teensy pins to a 16 x 8 switch matrix</li>\n<li>Mapping the 16 x 8 switch matrix to physical key locations</li>\n<li>Mapping physical key locations to USB key codes</li>\n</ol>\n<p>To accomplish <a href=\"/tag/1\">#1</a>, <a href=\"https://github.com/lmorchard/tmk_keyboard/blob/bdde5f9413ce5c3ea627f201b04f04fe371806ce/keyboard/modelm/matrix.c#L163\">I set up pins in the firmware</a>. The way this works is\nthat the rows are set to input and the columns are set to output. By pulsing a\ncurrent for each column in turn and reading the rows, you can build up a\nmatrix of switch state where the circuit is completed. This is called\n<a href=\"https://www.massdrop.com/article/introduction-to-keyboard-programming\">scanning the keyboard</a>. There are problems in this process - <a href=\"http://blog.komar.be/how-to-make-a-keyboard-the-matrix/\">like\nghosting</a> - but I'll skip describing them for now.</p>\n<p>To double check that I had my matrix working, I threw together an initial\nkeymap and set every key to emit \"1\".  I tapped each key and saw a \"1\" in my\nnotepad. Hooray, it worked! At least, electrically speaking.</p>\n<p>For step <a href=\"/tag/2\">#2</a>, I started googling for IBM Model M membrane matrix maps. Surely\nsomeone had done this before! Well, <a href=\"https://deskthority.net/workshop-f7/universal-model-m-controller-t9820.html#p207736\">it turns out someone had</a>.\nDeskthority user <a href=\"https://deskthority.net/idollar-u6930/\">idollar</a> had traced all the wires and annotated the\nmembranes with row &amp; column numbers in marker:</p>\n<img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/DSC_9298.jpg\" width=\"\" height=\"\">\n<img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/DSC_9300.jpg\" width=\"\" height=\"\">\n\n<p>Just to be clear: These two are not my photos. I stand on the shoulders of\n<a href=\"https://deskthority.net/idollar-u6930/\">forum giants</a>. But, after awhile, I couldn't really read the\nhandwriting and started making mistakes. </p>\n<p>That's when I remembered <a href=\"https://github.com/tmk/tmk_keyboard#magic-commands\">the matrix debug mode in TMK</a>: After\nconfiguring just enough keys to enable it, I could just watch the debug\noutput to tell me the rows &amp; columns as I hit other keys.</p>\n<p>Thus equipped, I spent a Sunday morning over coffee mapping the keyboard:\nMethodically pressing keys, noting rows &amp; columns, and building up <a href=\"https://github.com/lmorchard/tmk_keyboard/blob/bdde5f9413ce5c3ea627f201b04f04fe371806ce/keyboard/modelm/keymap.c#L34\">the KEYMAP\nmacro</a> that converts symbols for physical keys to logical matrix\npositions. Along the way, I also built up <a href=\"https://github.com/lmorchard/tmk_keyboard/blob/bdde5f9413ce5c3ea627f201b04f04fe371806ce/keyboard/modelm/keymap.c#L54\">the initial\nkeymap</a> using that macro to assign keycodes to the physical\nkeys.</p>\n<h2 id=\"fitting-the-prototype\">Fitting the Prototype</h2>\n<p>After that, I had an initial stab at steps <a href=\"/tag/2\">#2</a> &amp; <a href=\"/tag/3\">#3</a> - the keyboard was pretty\nmuch working and I could start typing practically with it. But, because I was\nhacking on this from the couch, it was all super-awkward holding things\ntogether in my lap.</p>\n<p>I should mention that these ribbon connectors have short, fragile leads.\nThey're really meant for soldering into a PCB. They snap into the breadboard,\nbut just barely. They spring free at the slightest pressure - you know, like\nhooking up ribbons and moving the keyboard around. And, whenever I reinsert\nthem, invariably one pin or another gets bent up and then snaps off after the\n4th or 5th realignment. I'm really glad I bought extras, because I'm down to\nmy last two that still work.</p>\n<p>So, I got tired of things falling apart and started positioning my breadboard\ninto the case. Everything fit physically, but the parts were all in the wrong\nplace. With a sigh, I pulled everything out of the board, rewired it, and\nreassigned all the pins:</p>\n<p><a data-flickr-embed=\"true\" data-footer=\"true\" href=\"https://www.flickr.com/photos/deusx/24742861610/in/dateposted-public/\" title=\"Teensy 2.0++ USB replacement controller for IBM Model M keyboard\"><img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/24742861610_8c3c931768_z.jpg\" alt=\"Teensy 2.0++ USB replacement controller for IBM Model M keyboard\" width=\"\" height=\"\"></a></p>\n<p>That put the ribbon connectors in the right spots for the keyboard membranes\nto connect, as well as room for a USB connector I bought to loop around without\ntoo much bend. Oh, and I slightly rewired things again, because I discovered\nI'd connected all the LEDs backward:</p>\n<p><a data-flickr-embed=\"true\" data-footer=\"true\" href=\"https://www.flickr.com/photos/deusx/24945773791/in/photolist-E52aJA-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz-Dzg18k/\" title=\"Teensy 2.0++ USB replacement controller for IBM Model M keyboard\"><img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/24945773791_b208614dd7_z.jpg\" alt=\"Teensy 2.0++ USB replacement controller for IBM Model M keyboard\" width=\"\" height=\"\"></a></p>\n<h2 id=\"my-keyboard-is-haunted\">My Keyboard is Haunted</h2>\n<p>After all the rewiring and reassigned pins, I fired things up again. This\ntime, I started getting mysterious spontaneous keystrokes. I thought it might\nbe a grounding issue with static electricity, because I could usually make it\nhappen by waving my hands over the keyboard. While a <a href=\"https://en.wikipedia.org/wiki/Theremin\">theremin</a>\nkeyboard might be fun, that's not actually what I was going for here.</p>\n<p>So, I ran a wire from the steel plate to the GND pin on the Teensy. That\ndidn't fix it.</p>\n<p>Finally, I realized that one of my new pins in use was D6 - and\nD6 is hardwired to an LED on the Teensy board. And, it so happens that LEDs\ncan do weird things when hooked up as an input - <a href=\"http://www.analog.com/library/analogdialogue/archives/48-08/raq_108.html\">such as detecting\nlight</a>. You know, maybe like the changing light from waving my\nhands over the keyboard.</p>\n<p>Thus, I was able to exorcise my keyboard ghost by bending up the pin at D6 to\ndisconnect it from the breadboard. Then, I ran a jumper over to D1 and\n<a href=\"https://github.com/lmorchard/tmk_keyboard/commit/f5b31e9d320d494a4d3fc75db614883b7225d332\">switched the pin assignments in the firmware</a>. No more spontaneous\nkeypresses.</p>\n<h2 id=\"secrets-of-2kro-matrices\">Secrets of 2KRO Matrices</h2>\n<p>After typing a bit, I realized I couldn't get certain key combinations to work -\nShift-T, for example.</p>\n<p>Now, I know that the IBM Model M isn't <a href=\"https://deskthority.net/wiki/Rollover,_blocking_and_ghosting\">an NKRO keyboard</a>. That is, you\ncannot press any arbitrary combination of keys together. But, of course, a\nkeyboard is useless if you can't press at least <em>some</em> keys together - like, say,\nShift and T. In fact, I've read that the IBM Model M is described as 2KRO -\ni.e. two-key rollover.</p>\n<p>So, I knew that the original controller supported Shift-T. Looking in the\nmatrix debug output, I noticed that I couldn't press any 2 keys in the same\nrow together - that included Left Shift and T.</p>\n<p>Scratching my head, I noticed that the membrane matrix had some interesting\nproperties: Pretty much all the modifier keys were in different columns than\nthe other keys I wanted to press along with them. So, my problem might be\nsolved by rotating the matrix - that is, <a href=\"https://github.com/lmorchard/tmk_keyboard/commit/afc4d0f23be23e8c69bc1dfbe127898a7fe82db7\">turning rows into columns and columns\ninto rows</a>.</p>\n<p>I don't entirely have my head wrapped around the design of the Model M\nmembrane layout, but I think this is part of it: After I rotated the matrix,\nthere are 8 columns per row. As far as I can tell, only one key can be pressed\nper row - so that means any given key has 7 others that cannot be pressed at\nthe same time. Practical key rollover, then, is implemented by putting keys\nyou're likely to press together in different rows.</p>\n<p>For example, modifiers like Left Shift and Right Shift share a row, and so\ncannot be pressed together. But, Left Shift &amp; T are found in different rows\nand can work together. However, some of the letters in the QWER &amp; ASDF cluster\nshare rows, so that can be trouble for gaming - directional keypresses and\nsuchlike might cancel each other out in the heat of the keymashing moment.\nBut, since this keyboard harkens to an era where keys were more for typing\nwords than for controlling games, the tradeoff makes sense.</p>\n<h2 id=\"the-result\">The Result</h2>\n<p><a data-flickr-embed=\"true\" data-header=\"false\" data-footer=\"true\" href=\"https://www.flickr.com/photos/deusx/24422592514/in/photolist-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz\" title=\"IBM Model M keyboard with USB controller\"><img class=\"inset wide right\" id=\"thumbnail\" src=\"/uploads/2016/modelm-controller/24422592514_d79da1882a_z.jpg\" alt=\"IBM Model M keyboard with USB controller\" width=\"\" height=\"\"></a></p>\n<p>So, after all the above and a few more random adventures in C programming,\nthis IBM Model M keyboard is now sitting on my desk with a USB cable plugged\ninto it.</p>\n<p>I ordered <a href=\"http://www.pckeyboard.com/page/category/Buttons\">some custom replacement keycaps from Unicomp</a> to reflect\nsome of the remapped keys I implemented - i.e. media control, Command (⌘),\nCaps Lock replaced by Ctrl. </p>\n<p>I've been having some clicky-clacky fun with this thing, and it's been easy to\nreconfigure &amp; reflash along the way as needed. Experience with <a href=\"https://geekhack.org/index.php?topic=41989.0\">TMK</a> to\nconfigure my previous project really came in handy.</p>\n<p><a data-flickr-embed=\"true\" data-footer=\"true\" href=\"https://www.flickr.com/photos/deusx/24959916191/in/photolist-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz/\" title=\"IBM Model M with USB controller upgrade\"><img class=\"inset wide left\" src=\"/uploads/2016/modelm-controller/24959916191_bfe3246ded_z.jpg\" alt=\"IBM Model M with USB controller upgrade\" width=\"\" height=\"\"></a></p>\n<p>The one part that could be considered irreversible with this project is that I\nended up drilling two small holes in the back to secure the USB port. I'm just\nslightly sad about that. But, I guess if I ever sell this thing on eBay, I'll\ntry talking up the benefits of the new USB controller.</p>\n<p>But, otherwise, if I wanted to undo all this work, I could just open it back\nup and plonk the original controller back in. I've currently got that board\nsitting in an anti-static bag in a drawer, taking a rest after decades of\nservice.\n<br style=\"clear: both\"></p>\n<h2 id=\"next-steps\">Next Steps</h2>\n<h3 id=\"breadboard-to-pcb\">Breadboard to PCB</h3>\n<p>Like I mentioned before, those ribbon connectors are fragile and meant to be\nsoldered to a PCB. I'd also like to learn how to design PCBs, so this seems\nlike a super easy project to start with. The only things needed are places to\nsolder the connectors, a socket for a Teensy, and traces connecting everything\nproperly. I wouldn't even need to learn SMD soldering yet!</p>\n<h3 id=\"bluetooth\">Bluetooth</h3>\n<p>I saw <a href=\"https://learn.adafruit.com/convert-your-model-m-keyboard-to-bluetooth-with-bluefruit-ez-key-hid/overview\">a project on Adafruit to add Bluetooth support to an IBM Model\nM</a>. But, that was using the original controller board and\nconverting from PS/2. With my controller, I could hook a Bluetooth module\ndirectly up to Teensy pins and talk to it from <a href=\"https://geekhack.org/index.php?topic=41989.0\">TMK</a>. That should be\ninteresting.</p>\n<h3 id=\"alphanumeric-display\">Alphanumeric Display</h3>\n<p>I noticed that a backlit alphanumeric LCD display is pretty much the exact\ndimensions of the Num Lock / Scroll Lock / Caps Lock LED area on the keyboard\ncase. It would definitely be a destructive change, but it might be kind of\ncool to replace that section with a text readout. I'm not really sure what it\nwould display, but it could be a fun little project like a retro-DIY version\nof <a href=\"http://amzn.to/1TuflVD\">a Logitech G15 keyboard</a>.</p>\n<h3 id=\"reset-button\">Reset button</h3>\n<p>Flashing the Teensy firmware usually requires pushing a button on the board.\nThere are also a couple of pins on the board that do the same when shorted, so\nI threaded some wires out of the case to do that. It's ugly.</p>\n<p>The <a href=\"https://geekhack.org/index.php?topic=41989.0\">TMK</a> firmware also supports a key combination that does the same thing,\nwhich would let me just toss the wires. But, after once or twice where I\nlocked the firmware and had to reopen the case, I don't think I can totally go\nwithout a reset button.</p>\n<p>So, I'm considering where and how to mount an external reset / programming\nbutton that doesn't require any more holes to be drilled or anything else\ndestructive.</p>\n<h3 id=\"60-model-m\">60% Model M</h3>\n<p>On the topic of destructive changes: <a href=\"https://geekhack.org/index.php?action=profile;u=3412\">hasu</a>, the author of the <a href=\"https://geekhack.org/index.php?topic=41989.0\">TMK</a>\nfirmware, <a href=\"https://geekhack.org/index.php?action=profile;u=3412\">literally carved up</a> an IBM Model M keyboard and <a href=\"https://geekhack.org/index.php?topic=29483.0\">reduced it\nto a 60% layout</a> more comparable to a Happy Hacking Keyboard.</p>\n<img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/yROEN.jpg\" width=\"\" height=\"\">\n\n<p>That project took a bit of work reconstituting the membrane using copper tape\nand conductive ink, as well as work to join the plastic bits back together.\nBut, the electronics end up being simpler after discarding piles of keys.\nI know it would be a certain kind of sacriledge to Model M lovers, but I might\nattempt it once I get tired of just how huge this keyboard is on my desk.</p>\n<h2 id=\"conclusion\">Conclusion</h2>\n<p>This was a pretty fun project, and a bit of a step up from the PS/2 converter\nI just built. I learned a bit about the innards of this keyboard, and I've got\nsome decent next steps to pursue in the future. All of this feels like it's\ngiving me some good foundational know-how for when I finally get all the parts\ntogether to try building my own DIY keyboard from the ground up.</p>\n<!-- vim: set wrap wm=5 syntax=markdown textwidth=78: -->\n",
  "body": "**TL;DR**: I wired up a Teensy 2.0++ to an IBM Model M keyboard,\nwhich gave it a USB interface and custom firmware that can remap keys and do\nother interesting things.\n\n<!--more-->\n\n<nav role=\"navigation\" class=\"table-of-contents\"></nav>\n\nIn my [previous post][keyboard-hacking], I wrote about my initial forays into\nkeyboard hacking. I got my hands on a few IBM Model M keyboards, and built a\nPS/2-to-USB converter with a [Teensy 2.0][teensy] so I could use it with my\nMacBook Pro after remapping some keys via the [TMK keyboard firmware][tmk].\n\nThat was a pretty rewarding little hack. But, then, I found [Lawrence Wu's\nnotes][original-notes] on replacing the original controller inside the IBM\nModel M.  In a nutshell, it turns out you can find ribbon connectors that work\nwith the Model M membrane layers and fit on a breadboard. That makes it easy\nto build - and reversible if I decide to return the keyboard to its original\nstate.\n\n## Initial Prototype\n\nSo, I ordered a few of the [16-pin ribbon connectors from Mouser][connector]\nand a [Teensy 2.0++][teensy-plus]. My first stab at wiring things up was\npretty simple:\n\n[connector]: http://www.mouser.com/ProductDetail/TE-Connectivity/6-520315-6/?qs=sGAEpiMZZMvYKGyZxp8jxkA16bSpREuh\n\n<a data-flickr-embed=\"true\" data-footer=\"true\"  href=\"https://www.flickr.com/photos/deusx/24987051026/in/photolist-E52aJA-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz-Dzg18k\" title=\"Original prototype for replacement IBM Model M keyboard controller\"><img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/24987051026_0d0b1ac2a9_z.jpg\" alt=\"Original prototype for replacement IBM Model M keyboard controller\"></a>\n\nThe [Teensy 2.0++][teensy-plus] has 20 pins per side, and I needed 16 for the\nfirst ribbon. So, it was convenient to just plonk both onto the breadboard and\ntake advantage of the built-in conductors. That's also why I upgraded from a\n[Teensy 2.0][teensy]: I needed more pins. The second ribbon needed\n8 pins, so I cut some lengths of [hook-up wire][hookup] to keep things neat\nand ran the connections over.\n\n[tmk]: https://geekhack.org/index.php?topic=41989.0\n[hookup]: http://amzn.to/1oCuCJ1\n\n<a data-flickr-embed=\"true\" data-footer=\"true\"  href=\"https://www.flickr.com/photos/deusx/24684318539/in/photolist-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz/\" title=\"5.5mm nut driver needed for opening IBM Model M keyboards\"><img class=\"inset wide right\" src=\"/uploads/2016/modelm-controller/24684318539_4dde739235_n.jpg\" alt=\"5.5mm nut driver needed for opening IBM Model M keyboards\"></a>\n\n## Driving Me Nuts\n\nThen, I wanted to get inside the keyboard to start tinkering. As it turns out,\nopening up an IBM Model M is annoying: None of the tools I had on hand could\ndo it. \n  \nThe case is assembled using screws with 5.5mm nut heads, rather than\nsomething like a Phillips-head screw. And, the screws are down in deep wells\ntoo narrow to fit any of the socket wrench heads I had on hand.\n\nSo, I had to order [a 5.5mm nut driver][nut-driver] with a very slim head.\nReading [the reviews][reviews], I can see I'm not alone in this.\n\nWhile that made its way to my house, I'd read that [some folks used a lighter\nand a pen][driver-hack] to form a makeshift nut driver. That was a terrible\nidea, but it worked. In hindsight, I really should have just waited for the\ndriver to show up. But, I was determined to get the thing open while I had\ntime to play with it.\n\n[reviews]: http://www.amazon.com/Dynamite-2803-Nut-Driver-5-5mm/product-reviews/B000BQ4XP6/ref=cm_cr_dp_see_all_summary?ie=UTF8&showViewpoints=1&sortBy=helpful\n[driver-hack]: https://deskthority.net/workshop-f7/model-m-disassembly-t1960.html#p34013\n\n## The Original Controller\n\nAnd, once open, this is the board I found inside:\n\n<a data-flickr-embed=\"true\" data-footer=\"true\"  href=\"https://www.flickr.com/photos/deusx/25046846995/in/photolist-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz/\" title=\"IBM Model M original controller board\"><img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/25046846995_c8dab2484c_z.jpg\" alt=\"IBM Model M original controller board\"></a>\n\nI should have taken a picture of it in place, but oh well. The board has a\ngrounding strap that was screwed down to the steel plate under the keys.\nBeyond that, it just fit into plastic brackets in the case and wasn't\notherwise fastened down. And, in a weird coincidence, the board was almost the\nexact same dimensions as my breadboard. Maybe these things are standard sizes?\n\n## Mapping the Membranes\n\nWith the keyboard membrane ribbons free from the original board, I hooked them up to\nmy prototype. From there, I wanted to start making the keys send the right\nsignals. There are three parts to this:\n\n1. Mapping Teensy pins to a 16 x 8 switch matrix\n2. Mapping the 16 x 8 switch matrix to physical key locations\n3. Mapping physical key locations to USB key codes\n\nTo accomplish #1, [I set up pins in the firmware][pins]. The way this works is\nthat the rows are set to input and the columns are set to output. By pulsing a\ncurrent for each column in turn and reading the rows, you can build up a\nmatrix of switch state where the circuit is completed. This is called\n[scanning the keyboard][scanning]. There are problems in this process - [like\nghosting][ghosting] - but I'll skip describing them for now.\n\n[scanning]: https://www.massdrop.com/article/introduction-to-keyboard-programming\n[ghosting]: http://blog.komar.be/how-to-make-a-keyboard-the-matrix/\n\nTo double check that I had my matrix working, I threw together an initial\nkeymap and set every key to emit \"1\".  I tapped each key and saw a \"1\" in my\nnotepad. Hooray, it worked! At least, electrically speaking.\n\n[pins]: https://github.com/lmorchard/tmk_keyboard/blob/bdde5f9413ce5c3ea627f201b04f04fe371806ce/keyboard/modelm/matrix.c#L163\n\nFor step #2, I started googling for IBM Model M membrane matrix maps. Surely\nsomeone had done this before! Well, [it turns out someone had][matrix-map].\nDeskthority user [idollar][] had traced all the wires and annotated the\nmembranes with row & column numbers in marker:\n\n[idollar]: https://deskthority.net/idollar-u6930/\n[matrix-map]: https://deskthority.net/workshop-f7/universal-model-m-controller-t9820.html#p207736\n\n<img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/DSC_9298.jpg\">\n<img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/DSC_9300.jpg\">\n\nJust to be clear: These two are not my photos. I stand on the shoulders of\n[forum giants][idollar]. But, after awhile, I couldn't really read the\nhandwriting and started making mistakes. \n\nThat's when I remembered [the matrix debug mode in TMK][matrix-debug]: After\nconfiguring just enough keys to enable it, I could just watch the debug\noutput to tell me the rows & columns as I hit other keys.\n\n[matrix-debug]: https://github.com/tmk/tmk_keyboard#magic-commands\n\nThus equipped, I spent a Sunday morning over coffee mapping the keyboard:\nMethodically pressing keys, noting rows & columns, and building up [the KEYMAP\nmacro][keymap-macro] that converts symbols for physical keys to logical matrix\npositions. Along the way, I also built up [the initial\nkeymap][keymap-plain] using that macro to assign keycodes to the physical\nkeys.\n\n[keymap-macro]: https://github.com/lmorchard/tmk_keyboard/blob/bdde5f9413ce5c3ea627f201b04f04fe371806ce/keyboard/modelm/keymap.c#L34\n[keymap-plain]: https://github.com/lmorchard/tmk_keyboard/blob/bdde5f9413ce5c3ea627f201b04f04fe371806ce/keyboard/modelm/keymap.c#L54\n\n## Fitting the Prototype\n\nAfter that, I had an initial stab at steps #2 & #3 - the keyboard was pretty\nmuch working and I could start typing practically with it. But, because I was\nhacking on this from the couch, it was all super-awkward holding things\ntogether in my lap.\n\nI should mention that these ribbon connectors have short, fragile leads.\nThey're really meant for soldering into a PCB. They snap into the breadboard,\nbut just barely. They spring free at the slightest pressure - you know, like\nhooking up ribbons and moving the keyboard around. And, whenever I reinsert\nthem, invariably one pin or another gets bent up and then snaps off after the\n4th or 5th realignment. I'm really glad I bought extras, because I'm down to\nmy last two that still work.\n\nSo, I got tired of things falling apart and started positioning my breadboard\ninto the case. Everything fit physically, but the parts were all in the wrong\nplace. With a sigh, I pulled everything out of the board, rewired it, and\nreassigned all the pins:\n\n<a data-flickr-embed=\"true\" data-footer=\"true\"  href=\"https://www.flickr.com/photos/deusx/24742861610/in/dateposted-public/\" title=\"Teensy 2.0++ USB replacement controller for IBM Model M keyboard\"><img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/24742861610_8c3c931768_z.jpg\" alt=\"Teensy 2.0++ USB replacement controller for IBM Model M keyboard\"></a>\n\nThat put the ribbon connectors in the right spots for the keyboard membranes\nto connect, as well as room for a USB connector I bought to loop around without\ntoo much bend. Oh, and I slightly rewired things again, because I discovered\nI'd connected all the LEDs backward:\n\n<a data-flickr-embed=\"true\" data-footer=\"true\"  href=\"https://www.flickr.com/photos/deusx/24945773791/in/photolist-E52aJA-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz-Dzg18k/\" title=\"Teensy 2.0++ USB replacement controller for IBM Model M keyboard\"><img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/24945773791_b208614dd7_z.jpg\" alt=\"Teensy 2.0++ USB replacement controller for IBM Model M keyboard\"></a>\n\n## My Keyboard is Haunted\n\nAfter all the rewiring and reassigned pins, I fired things up again. This\ntime, I started getting mysterious spontaneous keystrokes. I thought it might\nbe a grounding issue with static electricity, because I could usually make it\nhappen by waving my hands over the keyboard. While a [theremin][]\nkeyboard might be fun, that's not actually what I was going for here.\n\n[theremin]: https://en.wikipedia.org/wiki/Theremin\n\nSo, I ran a wire from the steel plate to the GND pin on the Teensy. That\ndidn't fix it.\n\nFinally, I realized that one of my new pins in use was D6 - and\nD6 is hardwired to an LED on the Teensy board. And, it so happens that LEDs\ncan do weird things when hooked up as an input - [such as detecting\nlight][photodiode]. You know, maybe like the changing light from waving my\nhands over the keyboard.\n\nThus, I was able to exorcise my keyboard ghost by bending up the pin at D6 to\ndisconnect it from the breadboard. Then, I ran a jumper over to D1 and\n[switched the pin assignments in the firmware][d0-pin]. No more spontaneous\nkeypresses.\n\n[photodiode]: http://www.analog.com/library/analogdialogue/archives/48-08/raq_108.html\n[d0-pin]: https://github.com/lmorchard/tmk_keyboard/commit/f5b31e9d320d494a4d3fc75db614883b7225d332\n\n## Secrets of 2KRO Matrices\n\nAfter typing a bit, I realized I couldn't get certain key combinations to work -\nShift-T, for example.\n\nNow, I know that the IBM Model M isn't [an NKRO keyboard][nkro]. That is, you\ncannot press any arbitrary combination of keys together. But, of course, a\nkeyboard is useless if you can't press at least *some* keys together - like, say,\nShift and T. In fact, I've read that the IBM Model M is described as 2KRO -\ni.e. two-key rollover.\n\nSo, I knew that the original controller supported Shift-T. Looking in the\nmatrix debug output, I noticed that I couldn't press any 2 keys in the same\nrow together - that included Left Shift and T.\n\nScratching my head, I noticed that the membrane matrix had some interesting\nproperties: Pretty much all the modifier keys were in different columns than\nthe other keys I wanted to press along with them. So, my problem might be\nsolved by rotating the matrix - that is, [turning rows into columns and columns\ninto rows][matrix-swap].\n\nI don't entirely have my head wrapped around the design of the Model M\nmembrane layout, but I think this is part of it: After I rotated the matrix,\nthere are 8 columns per row. As far as I can tell, only one key can be pressed\nper row - so that means any given key has 7 others that cannot be pressed at\nthe same time. Practical key rollover, then, is implemented by putting keys\nyou're likely to press together in different rows.\n\nFor example, modifiers like Left Shift and Right Shift share a row, and so\ncannot be pressed together. But, Left Shift & T are found in different rows\nand can work together. However, some of the letters in the QWER & ASDF cluster\nshare rows, so that can be trouble for gaming - directional keypresses and\nsuchlike might cancel each other out in the heat of the keymashing moment.\nBut, since this keyboard harkens to an era where keys were more for typing\nwords than for controlling games, the tradeoff makes sense.\n\n[nkro]: https://deskthority.net/wiki/Rollover,_blocking_and_ghosting\n[matrix-swap]: https://github.com/lmorchard/tmk_keyboard/commit/afc4d0f23be23e8c69bc1dfbe127898a7fe82db7\n\n## The Result\n\n<a data-flickr-embed=\"true\" data-header=\"false\" data-footer=\"true\"  href=\"https://www.flickr.com/photos/deusx/24422592514/in/photolist-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz\" title=\"IBM Model M keyboard with USB controller\"><img class=\"inset wide right\" id=\"thumbnail\" src=\"/uploads/2016/modelm-controller/24422592514_d79da1882a_z.jpg\" alt=\"IBM Model M keyboard with USB controller\"></a>\n\nSo, after all the above and a few more random adventures in C programming,\nthis IBM Model M keyboard is now sitting on my desk with a USB cable plugged\ninto it.\n\nI ordered [some custom replacement keycaps from Unicomp][unicomp] to reflect\nsome of the remapped keys I implemented - i.e. media control, Command (⌘),\nCaps Lock replaced by Ctrl. \n\nI've been having some clicky-clacky fun with this thing, and it's been easy to\nreconfigure & reflash along the way as needed. Experience with [TMK][] to\nconfigure my previous project really came in handy.\n\n[unicomp]: http://www.pckeyboard.com/page/category/Buttons\n\n<a data-flickr-embed=\"true\" data-footer=\"true\"  href=\"https://www.flickr.com/photos/deusx/24959916191/in/photolist-E1nBs8-DGrCJf-Dd9aTh-E2C6uB-DBgzUX-E7Yy31-EaiCZz/\" title=\"IBM Model M with USB controller upgrade\"><img class=\"inset wide left\" src=\"/uploads/2016/modelm-controller/24959916191_bfe3246ded_z.jpg\" alt=\"IBM Model M with USB controller upgrade\"></a>\n\nThe one part that could be considered irreversible with this project is that I\nended up drilling two small holes in the back to secure the USB port. I'm just\nslightly sad about that. But, I guess if I ever sell this thing on eBay, I'll\ntry talking up the benefits of the new USB controller.\n\nBut, otherwise, if I wanted to undo all this work, I could just open it back\nup and plonk the original controller back in. I've currently got that board\nsitting in an anti-static bag in a drawer, taking a rest after decades of\nservice.\n<br style=\"clear: both\">\n\n[teensy]: https://www.pjrc.com/store/teensy.html\n[teensy-plus]: https://www.pjrc.com/store/teensypp.html\n[nut-driver]: http://amzn.to/1RgjN8k\n[keyboard-hacking]: http://blog.lmorchard.com/2016/02/06/keyboard-hacking/\n[original-notes]: https://github.com/antonizoon/archivis.me/wiki/IBM-Model-M-USB-Controller\n[photo-tag]: https://www.flickr.com/photos/tags/modelmcontroller\n\n## Next Steps\n\n### Breadboard to PCB\n\nLike I mentioned before, those ribbon connectors are fragile and meant to be\nsoldered to a PCB. I'd also like to learn how to design PCBs, so this seems\nlike a super easy project to start with. The only things needed are places to\nsolder the connectors, a socket for a Teensy, and traces connecting everything\nproperly. I wouldn't even need to learn SMD soldering yet!\n\n### Bluetooth\n\nI saw [a project on Adafruit to add Bluetooth support to an IBM Model\nM][Adafruit-Bluetooth]. But, that was using the original controller board and\nconverting from PS/2. With my controller, I could hook a Bluetooth module\ndirectly up to Teensy pins and talk to it from [TMK][]. That should be\ninteresting.\n\n[adafruit-bluetooth]: https://learn.adafruit.com/convert-your-model-m-keyboard-to-bluetooth-with-bluefruit-ez-key-hid/overview\n\n### Alphanumeric Display\n\nI noticed that a backlit alphanumeric LCD display is pretty much the exact\ndimensions of the Num Lock / Scroll Lock / Caps Lock LED area on the keyboard\ncase. It would definitely be a destructive change, but it might be kind of\ncool to replace that section with a text readout. I'm not really sure what it\nwould display, but it could be a fun little project like a retro-DIY version\nof [a Logitech G15 keyboard][g15].\n\n[g15]: http://amzn.to/1TuflVD\n\n### Reset button\n\nFlashing the Teensy firmware usually requires pushing a button on the board.\nThere are also a couple of pins on the board that do the same when shorted, so\nI threaded some wires out of the case to do that. It's ugly.\n\nThe [TMK][] firmware also supports a key combination that does the same thing,\nwhich would let me just toss the wires. But, after once or twice where I\nlocked the firmware and had to reopen the case, I don't think I can totally go\nwithout a reset button.\n\nSo, I'm considering where and how to mount an external reset / programming\nbutton that doesn't require any more holes to be drilled or anything else\ndestructive.\n\n### 60% Model M\n\nOn the topic of destructive changes: [hasu][], the author of the [TMK][]\nfirmware, [literally carved up][hbkb2] an IBM Model M keyboard and [reduced it\nto a 60% layout][hbkb] more comparable to a Happy Hacking Keyboard.\n\n<img class=\"fullwidth\" src=\"/uploads/2016/modelm-controller/yROEN.jpg\">\n\n[hasu]: https://geekhack.org/index.php?action=profile;u=3412\n[hbkb]: https://geekhack.org/index.php?topic=29483.0\n[hbkb2]: https://geekhack.org/index.php?action=profile;u=3412\n\nThat project took a bit of work reconstituting the membrane using copper tape\nand conductive ink, as well as work to join the plastic bits back together.\nBut, the electronics end up being simpler after discarding piles of keys.\nI know it would be a certain kind of sacriledge to Model M lovers, but I might\nattempt it once I get tired of just how huge this keyboard is on my desk.\n\n## Conclusion\n\nThis was a pretty fun project, and a bit of a step up from the PS/2 converter\nI just built. I learned a bit about the innards of this keyboard, and I've got\nsome decent next steps to pursue in the future. All of this feels like it's\ngiving me some good foundational know-how for when I finally get all the parts\ntogether to try building my own DIY keyboard from the ground up.\n\n<!-- vim: set wrap wm=5 syntax=markdown textwidth=78: -->\n",
  "parentPath": "./content/posts/archives/2016",
  "path": "2016/02/21/modelm-controller",
  "thumbnail": "/uploads/2016/modelm-controller/24422592514_d79da1882a_z.jpg",
  "summary": "TL;DR: I wired up a Teensy 2.0++ to an IBM Model M keyboard,\nwhich gave it a USB interface and custom firmware that can remap keys and do\nother interesting things.",
  "needsBuild": true,
  "prevPostPath": "2016/02/06/keyboard-hacking",
  "prevPostTitle": "Keyboard hacking seems like fun",
  "nextPostPath": "2016/04/17/spreadsheets-in-space",
  "nextPostTitle": "How I learned to love spreadsheets in space"
}