techWebsite/content/posts/rmk-ferris-sweep/index.md
2025-03-17 19:49:23 +01:00

4.8 KiB

+++ title = "Rust on the Ferris Sweep" date = 2025-03-10T17:28:15+01:00 draft = true +++ The other day, I stumbled upon RMK, a keyboard firmware written in Rust. Given that my Ferris Sweep has a ferris the crab logo on the silkcreen, it felt only fitting that I flash it with RMK.

However, RMK is a much newer project than QMK. QMK provides premade configurations for almost keyboard out there (or at least, every keyboard that allows flashing your own firmware), allowing you to build someone else's design and get straight to designing a keymap, without having to fuss about matrices or pin mappings. RMK has no such definitions, just documentation of how to write them and a few example projects, making this journey to put it on my Ferris Sweep interesting enough to write about.

I started by installing a few tools via cargo, running

cargo install rmkit flip-link elf2uf2-rs

Then I ran rmkit init and answered a few questions about my keyboard, which generated a template for me to further modify. I modified .cargo/config.toml to use elf2uf2-rs as documented in the templates README, as I cant exactly set up a debug link on an already assembled keyboard. The docs say I need to modify the memory.x file for my microcontroller, but I found the rmkit tool had already set it with the right contents.

Then came the hard work, configuring keyboard.toml. I followed the docs, carefully started porting my Ferris Sweep layout to the keyboard.toml.

First off, for the keyboard metadata, I simply took from QMK's Ferris Sweep info.json.

Then for the tricky part. We have to define our pin mappings using the peripheral names as defined by embassy This is hard because the QMK mappings given in the keyboard.json are for the Aurdino pro-micro pin names, and I wasn't able to figure out what magic QMK does to convert those into the RP2040 Elite-pi equivalents. In the end, I just cloned the Ferris sweep repo and opened the files in kicad, cross referencing the schematic with the elite-pis usage guide One stumbling block is that the Ferris sweep ran out of pins to use full-duplex UART, and therefore only uses half-duplex. To solve this, RMK supports (only on the RP2040) a PIO driver for half duplex, gated behind a crate feature in cargo.toml. With it, we can set our Tx and Rx pins to the same pin. In order to do this, however, I had to set the rmk dependency to a direct link to the Github repo, because as of the time of writing, the rp2040_pio feature had not made it into a release.

After the painstaking process of tracing all the pins and putting them in the matrix, we can define the keymap. My keymap is a bit complex, so it took some time to port. It was mostly tedium rather than anything truly headscratching, however.

Next, and the most complicated step, was creating a vial.json. The json file provided by the via project was wrong, as it layed out the keyboard as a 8x5, rather than a 4x10 that I had done in rmk. So I had to take that file, load it into the keyboard layout editor, and follow vials guide to remake the vial.json in the right layout.

Finally, I could flash my keyboard. I flashed it, and... It didnt work. The left hand side, the one plugged into USB, worked fine, all keys worked. But the right hand side, connected to the main by TRRS, did nothing. A day or 2 of investigation later revealed that the half-duplex serial implementation only used the RP2040s internal pull-up resistors, which for my keyboard and TRRS cable, were insufficient for a baud rate of 115200. This was (temporarily) fixed by setting a lower baud rate, but for the long term, ive made a PR mirroring QMKs solution to this problem.

The final file looked like this