In late July, I had tickets for the NorCal’22 Keyboard meetup. It was my first such experience in the mechanical keyboard community and I had a great time. After seeing enough of the DIY keyboards on display, I was itching to design something of my own. At home, I had a gorgeous looking ortho keycap set, Drop+MT3 Cyber lying around and it was a shame to not have it adorned on a board. So, I knew the design would be centered around 1u keycaps. However, unlike the usual ortholinear layouts that such keycaps are usually intended for, I preferred the row staggered layout. This was also around the time that I came across an article for the Seeed XIAO Mechanical Keyboard contest on KBD.news, so I thought I should throw my hat in the ring. And, so I designed the Purple Owl, the board with which this article was written!
The layout is inspired by the works of Ziptyze with their Zlant (4x12) and ZlantXL (5x12). It is almost like a staggered 5-row Preonic but with more columns and a narrow bottom row to offer the visual aesthetic of four dominant rows like a Plank. Each row has a 0.25u stagger unlike a traditional row-stagger. There are 14 columns to accommodate the outer symbols (-=[]\). The right shift can be traded in for an arrow cluster. The ctrl, shift and other mods are designed to be under the thumbs with a symmetric bottom row that has a 2u surrounded by two 1u on each side. Since the board runs on KMK firmware, the keys can be freely mapped.
The electronics were designed to be powered by a cute and tiny Seeed XIAO RP2040. The real constraint was the limited GPIO to interface with the 61 switches of the Purple Owl layout. So, instead of a traditional diode matrix, the Purple Owl implements a scan chain to poll the state of its switches using only 3 logic pins. KMK supports a scan chain scanner by default. The PCB is compatible with any CircuitPython compatible board with the pinouts shown below should snap into Purple Owl. There is a solder jumper to select between two popular layouts - the Pro Micro variant and the Seeed XIAO variant. The Purple Owl design needs two power pins (3V3 and GND) and three logic pins (CLK, DATA, LATCH).
With the scan chain polling the switches, there were enough GPIO left for some bells and whistles. I threw in 16 RGB LEDs in the design to emit an underglow which I knew would look stunning in a laser cut case.
The design uses eight 74HC165 (TSSOP-16 package) to form the scan chain. Each 74HC165 can scan upto 8 switches. 7 of these poll the top 4 rows across 14 columns and the last one polls the bottom row. The scan chain for the first 6 columns is shown below.
I've also added 16 underglow LEDs (WS2812B-V5). The PCB design has a clean board edge tightly fitting the switches and the uC goes underneath. The uC is socketed to the board with through-hole headers. Out of the 14 pins of the Seeed XIAO RP2040, 11 are physically connected (though not all are functionally used).
There are jumpers to select the 3V3 source depending on the attached uC. And jumpers to select the power source (3.3V or 5V) for the LEDs. Though off-spec, The LEDs work fine on 3.3V, albeit slightly less bright than if powered by 5V. There wasn't enough space (while staying close to the board edge) to allow a through hole header for the 5V, so the design offers a jumper/through-hole that needs to be wired between the board and the jumper site if 5V is desired.
JP1: Join 1-2 or 2-3 depending on where the 3V3 pin on the uC is. For the Seeed XIAO RP2040 variants short the 1-2. And, for Pro Micro variants, short 2-3.
- JP1: Join 1-2 or 2-3 depending on where the 3V3 pin on the uC is. For the Seeed XIAO RP2040 variants short the 1-2. And, for Pro Micro variants, short 2-3.
- JP2: Join 1-2 to select the 3.3V source selected by JP1, or connect the 5V to 3 from the uC over a wire and join 2-3.
For assembly, Seeed is sponsoring two fully assembled boards 🎉
This project was my first experience with CircuitPython, let alone KMK. I am stunned how easy it was to work with. Never did I think it would take just a few lines of python to establish a fully functional keyboard with layers and underglow LEDs.
I initially confirmed that the electronics were working as intended using the base CircuitPython digitialio (bringup.py). The scan chain for 61 keys worked as intended, and I observed that it took about 1ms to scan all of them using native digitalio alone.
The setup for KMK firmware was fairly straightforward (main.py). I included three basic layers to start with (I really need the tilde/grave in my line of work). The physical layout (scan chain) of the switches were mapped to the layout with the coord_mapping setup. The firmware uses the KMK ShiftRegisterKeys() as scanner. KMK offers a neat RGB extension to support the underglow LEDs. The underglow RGB controls are added on a layer. Looking at the sheer simplicity of the RGB extension I might consider writing a fancy underglow mode or two.
Since this was a proper build, the boot.py was updated with a "dev mode" which hides CircuitPython enumerations (serial, midi and storage) except for the USB HID keyboard. So, the keyboard now normally only enumerates as a HID device and the CircuitPython drives are hidden, unless you attach the keyboard in while pressing the top-left key (usually, ESC).
Laser cut caseFor the case, I had envisioned a laser cut case with 1/8" acrylic layers. With the top layers as dark and the bottom layer as translucent to diffuse the underglow. This was the first time I used Fusion360 as well. Lots of firsts for me in this project. Thankfully, there are a ton of youtube videos to learn from, and I only need the basics of sketching in 2D to set up the layers for the laser cut case.
Using plate.keeb.io I obtained the cut outs for the switches and stabilizer to form the top switch plate. Then, I designed the middle layers to be spaced around the PCB by importing the PCB edge-cuts layer into the design and offset it. All the layers except for the top switch plate have cut outs for the Seeed XIAO RP2040 that is on the underside of the PCB. All the holes are cut out for M2 hardware. I also added holes for some feet that I found on Flashquark.
Files for the case are here. I used p95 matte black acrylic sourced from a local TAP plastics for the top three layers (1xtop, 2xmiddle), and a satinice acrylic for the bottom layer.
Credits- Seeed DIY XIAO Mechanical Keyboard Contest, Link.
- Layout inspired by Ziptyze's Zlant and ZlantXL.
- Electronics inspired by Zhihui's HanWen and Tzarc's Ghoul which use shift registers to scan the matrix.
- Dovenyi and Keyboard Builder's Digest.
- Photography by Wife 😘.
Comments