28 June 2021

Apple Keyboard II Revival

For those that might remember, I originally tried to revive the Apple Keyboard II with a Teensy 2.0 (link), but it ultimately failed. I did kinda poke around with it again recently, but still couldn't get it to work. Anyway, with my CircuitPython/MCU "craze", I decided the next best way is to just make my own controller board for it.

The first thing to do was to figure out the array of the membrane keyboard, which was annoying to do but still doable. What was interesting to find was that the modifier keys (control, shift, option, command, caps lock) had their own rows but all had ground as the column. Another interesting thing I found was that the right and left shift keys were tied together, so pressing left shift is no different than pressing right shift — they were both on the same row. I used a spreadsheet later on to clean up the array map and to map the positions of the membrane to the MCU pins.

Another thing I had to do was to get some of the board dimensions and such, but it was a little tough to get reference points because the board's size from the tolerance that Apple put in. I figured out to use the centre of the tactile switch as a reference point because there's a boss in the case underneath the board where the centre of the tactile is (or rather, supposed to be because the boss' circle and the tactile switch's circles are not concentric). I had to go back a lot to get dimensions that I didn't think about and it was a bit annoying having to get the keyboard out and open it multiple times.

I was thinking to use the original FPC connector and desoldered it before measuring the via spacing on the board for it, and came up with some weird numbers, but kinda went with it. I had also looked to see if I could find something that was close or would work, and I think I had found a part, but it was obosolete or non-stocked. Later on, I thought to check the entirety of the spacing or to take the spacing and divide it accordingly, and with measuring centre to centre of the first and last vias, I found that the spacing I originally had wouldn't've worked; I think I also confirmed the issue with the spacing on the keyboard's FPC cable. With this, I realised that the connector was metric and searched for a part using metric dimensions (1.25mm pitch instead of 1.27mm) and found a compatible part that's active and in stock. Looking at its datasheet, I decided to go with it because it was narrower or shorter (I don't remember which) than the original part, which would give me a bit more board space.

One of the things I wanted to keep was the ability to plug the keyboard in from either side, but this was a little easier said than done because I wanted to keep the board cost as low as possible and also trying to avoid running long traces for the D+ and D- USB signals. I decided having remote boards would probably be the best option, but I would need to connect them. For the right side, I decided to use an internal USB cable because of the ~20cm distance, and for the left, I decided on an FPC cable. Because of the internal connections, I wanted to have a way to be able to check if the cables were connected (well one of them would have to be connected for the MCU to get power to do so), so instead of having just 4 connections for each USB signal, I needed 5. The FPC was easy, but the internal USB connection gave me trouble. I wanted to use USB-C because of its size and such, but it seems like the spec says to connect shield to ground because of all the USB-C cables that I have, shield is always tied to ground. What I needed was a shield to shield connection so that I can use it to carry the high signal from the MCU over to the remote board where it would connect to ground (getting the far-side connection status is more useful than the near-side connection status). I had also thought about using USB micro-B, but it was hard to tell if the shield-shield connection was there in the datasheet, and there wasn't any connectors that were easy to hand solder fully (there's usually a couple pads underneath the shell that requires solder paste and reflowing to fully secure the connector to the board). I settled on using USB mini-B on both sides and using a short USB mini-B cable (USB A male to mini-B male) and a short USB mini-B adapter cable (USB A female to mini-B male) for the connection between the boards, and confirmed the shield-shield connections in both items. For the USB connection between the keyboard and the computer, I went with USB B because it's the only option to fill out the ADB port (really, a 4-pin mini-DIN) cutout.

With two USB outputs to the computer, I needed to keep them separate for minimal weirdness, so I opted for a signal relay to do this. I connected a diode between the 5 volts of the USB and the 3.3-volt voltage regulator to keep the two 5-volt lines separate, and behind the diode, I have a small trace running to an inverting level shifter so that the MCU would know which side the power's coming from and adjust the latching relay accordingly. The main problems were that I had the FPC connector for the keyboard in the middle of the board, I wanted to keep the USB traces on the board as short as possible, and that the relay and USB mini-B connector take up quite a bit of space. I also wanted the MCU on the top side of the board to kinda show it off (well, whenever the keyboard was opened up), but I eventually opted to put it on the bottom of the board because I didn't have any other choice. I was going to use a latching signal relay that I had used before (probably one of the soundcard switching ones) which takes up a small area while being kinda tall, but I had to switch to one that took up more area for a reduced height. Originally, I wanted the relay in the top-right corner of the board because of the amount of space that's above the board, but to keep the USB traces sane, I moved it to below the keyboard FPC connector. I also wanted the mini-B connector in the top right, but again, sensible trace routing made me move it to below the FPC connector.

Exact placement of the MCU was weird, it had to be above the FPC vias, but had to keep the pads and traces away from the boss under the tactile and the stabilisation boss next to the tactile. I put the pad egdges a millimetre away from the FPC vias, but had to wait until I had the airwires and some traces in before I could figure out its x position. I also had to do some pin swaps and rerun traces to make it a little easier/cleaner and such.

At some point, I decided to add a piezo buzzer for num lock indication originally, but it evolved into also indicating a broken internal connection (assuming the MCU can get power) and indicating that both sides of the board are plugged in (which would probably very difficult to do, but if it did happen, the MCU wouldn't know which way to switch the relay). I think the piezo buzzer was another piece that made laying out parts weird? It went into the top-right corner.

Board retention is another issue, and I decided to have a 3D-printed part that would make it so that I could screw the boards to the part and set the assembly into the bottom case for the boards to be in a stable position and to not have to try to design the boards for friction-fit placement.

The (likely final) mainboard with notes and such.

I wanted to try to make one board for both sides, and there was a lot of back and forth between being able to do so and not, but when I did straighten out the insides of the case, I was able to do one for both sides. I was wanting to use the through-hole USB B connector that I used for the cooling/charging station that I never talked about, but because the nature of through-hole parts and the way the board would be, I decided an SMT version would be better. The problem with the SMT versions is that the pads for the shell were not within the design rule region because of where I had the edge of the board, but eventually I moved the edge of the board a little further away because there wasn't anything else I could do. Placement of the other connectors was weird because I had quite a bit of space for the FPC connector and I didn't have a length for the board yet. I think it was after getting the mounting holes and such that I was able to get the connectors into place. With the FPC connector in place, I was able to get a distance to base the length of the FPC cable on (since pre-made FPC cables come in certain sizes and is cheaper than making my own via OSH Park).

The remote board and such.

The caps lock key is kinda unique in that it is a locking switch, so it clicks into and out of place when you turn it on or off, and because modern keyboard controllers just toggle the caps lock state, this presented a problem. Back when I was fiddling around with the Trinket M0 and keyboard HID library, there was a way to get the lock status with the USB HID library, but it was awkward, but with some update, it was moved to the keyboard HID library and was easier to use. Anyway, the way to solve the problem of properly sending the caps lock toggle with a locking caps lock key is to send the key input whenever the state of the switch is not the same as the caps lock status. For handling the keyboard keys, I used Adafruit's matrix keypad library, which made it a lot easier than having to write the code myself (and I was ready to because I knew how to).

Because Apple's numeric pad section is different than ones for PCs (even still to this day), I was going to move keys around to keep the layout consistent with PCs, but because Apple still uses the same layout, I moved them all back. There is no num lock key, instead it's "clear", but since it's the same key ID, it would be num lock anyway. Because they clear key would be the num lock key, there had to be some sort of indication for num lock status, which I solved with the piezo buzzer. Whenever the num lock turns on, the buzzer sends two ascending notes; the buzzer would send two descending notes when the num lock turns off. I did it this way instead of using LEDs of some sort because I didn't want to modify the case. I also had an idea to use a level shifter to drive the piezo at 5 volts instead of 3.3, and while it is louder, it doesn't seem to fully like it. I also need to test it with a transistor between the piezo and ground to control the volume, so that it might be louder than when at 3.3 volts, but doesn't do the weird thing that it does at 5.

I have the power button set as a funciton key and have a filter set in the code so if there's a set function key, it would strip the corresponding keys out of the pressed keys list before inserting the new key. For example, function and left arrow I have set as home, so in the list of pressed keys, left arrow would be removed and home would be inserted into the list.

Besides the silicon shortage screwing with MCU availability, I still need to get the dimensions I need to CAD the "liner" piece that holds the boards, and I also need to CAD the piece that helps reduce the movement of the USB B connector.