All posts tagged keyboards

Just a quick update here. No hardware changes since last time, but I finally got around to putting in rudimentary ghost key rejection. What I tried was laughably simple: if there are more than two new keys being detected in a single scanning pass, ignore them both and send no updates, until the next change occurs. It doesn’t even check to see if they are in positions to cause ghosting — it just relies on the fact that ghost keypresses will always appear instantaneously with the last key, and for normal keypresses that’s very unlikely. Since making that change, it’s just perfect. No ghost keypresses, and no lost keys from what I’ve noticed.

One unfortunate effect from the current decoder/diode arrangement is that I can’t really set things up for this to go to sleep and be awaked by an interrupt when any key gets pressed. So I don’t have a great way for this to go into a very low-power mode, but I can at least try to optimize the regular power usage a little. Throughout all of the previous iterations, I had a 1ms delay following each scanning pass, but the passes were now happening much faster without the IO expanders. I tried doubling the loop delay to 2ms, and noticed no change in responsiveness, but greatly increased battery life. At some point I’ll probably put something in to increase that a lot (like 25ms or so) if there haven’t been any keys pressed in an hour or so, and that’ll presumably make another huge difference. But for right now everything’s great.

Oh, I should also put in some kind of support for volume/media control. That would be useful.

Now that I’m partly back in my office, I had to have two functioning keyboards again. I dusted off the two latest-version modified NMB keyboards, and tweaked the debounce timing on them slightly, and they’re working fine as my daily drivers. The current debounce logic is very rudimentary; between each loop through scanning the keyboard matrix, the firmware delays by 1ms. If there was a change in key state, this is sent over bluetooth, and the firmware delays by DEBOUNCE_DELAY (currently 20ms) before scanning again. If I were super picky, I’d just ignore bounces in the most recently-changed key, but for real-world typing this seems fine. Any time I get spurious key repeats, I can either clean the switch contacts or increase the delay value.

I do need to implement some kind of anti-ghosting mechanism, since the old keyboards have no NKRO diodes or anything; if I’m sloppy while typing, I’ll easily start getting ghost keypresses. My plan for a rudimentary solution for that is that if there’s ever a key-scanning update that results in two keypresses being added in the same millisecond, then ignore that update until the state changes again. Most of the cases where I’m getting ghost keypresses are when I’m pressing three keys in sequence but I’m late in releasing the earlier keys, so I get events for key1, key2, and then key3+ghost_key. (This happens when two of the keys being pressed share a row, and two of the keys being pressed share a column, and the end result basically shorts out another intersection on the key matrix. So if the keys being pressed are at A1, B1, and A2, when the third key is pressed it will also appear that B2 is pressed, because row 2 and column B are connected through the other three keyswitches.) Anyway, since I don’t know which of the two simultaneous keys being detected is real, I can just ignore both of them, and once one of the first two keys is released the situation should be resolved and the next update can go through.

One of the keyboards is the large Windows-key-equipped version, with everything mounted internally. The other one is one of the smaller 101-key models, and the bluetooth board is mounted on top, in a socket, too tall to fit inside the case. I finally got tired of using it with the top part of the case removed, so I just cut a hole out of the top to accommodate it. Much nicer.

I’m picky about my keyboards. I like them wireless, I like a full layout, and I like good mechanical switches. This is a hard combination to find for sale, as most mechanical keyboards nowadays are marketed towards gamers, and they don’t like the potential latency of wireless keyboards. Even the hobbyist DIY keyboard resources typically revolve around minimalist layouts.

So fine, I’ll make something. This is probably for the best anyway, since my favorite keyswitches are no longer being made. My favorites were the original Apple Extended Keyboard (using undamped ALPS switches), and the lesser-known line of keyboards using the NMB “space invaders” switches. My college roommate had one of those NMB keyboards with his 80286 PC, and I kept that keyboard to this day; a few years ago I hardwired a PS2-to-USB adapter inside it.

I wanted wireless, though, and there were a few different ways of achieving this. The first pass was very hacky. I picked up a cheap $20 logitech wireless keyboard that had a full layout, and mapped out the matrix that its keys used. (Keyboards work by having a grid of rows and columns, and every time you press a key it connects that row and that column. A microcontroller scans across them, looking for connections. The layout of rows/columns to keys varies widely across models, based on PCB layout and other factors.) At this point I could have designed a new PCB for a keyboard that used the same matrix, and attached it to the controller board from the logitech keyboard, but PCB manufacturers charge by the square inch, and these keyboards are large.

Instead, I took my test Apple keyboard, and removed its PCB entirely, and hand-wired connections between keys to match the Logitech matrix. Lest things get too crowded between keys, I used thin magnet wire to connect them. It was not pretty on the back. At this point the only thing holding the keys in was the fact that some (especially early) mechanical keyboards have the keys mounted through a metal plate before being connected to the PCB.

I’m not proud of this, but it worked.

Well, it worked, but the metal plate didn’t provide enough stability; I had to pop a keycap off to fix a flaky keyswitch, and it ended up pulling the whole keyswitch out of the plate, ripping the thin magnet wires out of the back in the process.

If I were to try this approach again, I’d grab a bunch of the enabler boards and connect them with hookup wire or something. But I wasn’t going to try this approach again; for subsequent versions, I wanted to replace the original keyboard’s microcontroller with something that would interface with a modern bluetooth-enabled microcontroller. I had all the information I needed about the Apple keyboard from this site, but those are more expensive for tinkering, so I focused on the NMB models. (Quick note, though: if you like the “clacky” feel of the first Apple Extended Keyboard as opposed to the softened sound and feel of the AEK2, you can take the AEK2, open up each keyswitch, and remove a couple of rubber dampers from each one, and reassemble.)