From a75393b5c69f7714c392b4b50bfdc231d475c8fd Mon Sep 17 00:00:00 2001
From: Gabe Venberg <gabevenberg@gmail.com>
Date: Tue, 25 Mar 2025 10:55:52 +0100
Subject: [PATCH] rewrote lare parts of the RMK on ferris sweep article.

---
 content/posts/rmk-ferris-sweep/index.md | 106 +++++++++++++++---------
 1 file changed, 69 insertions(+), 37 deletions(-)

diff --git a/content/posts/rmk-ferris-sweep/index.md b/content/posts/rmk-ferris-sweep/index.md
index acbdd62..31cb160 100644
--- a/content/posts/rmk-ferris-sweep/index.md
+++ b/content/posts/rmk-ferris-sweep/index.md
@@ -1,6 +1,6 @@
 +++
 title = "Rust on the Ferris Sweep"
-date = 2025-03-10T17:28:15+01:00
+date = 2025-03-25T17:28:15+01:00
 draft = true
 [cover]
 image = "keyboard-with-rust"
@@ -28,67 +28,99 @@ which made the journey to put it on my Ferris Sweep interesting enough to write
 
 ## Configuring the firmware
 
-Unlike QMK, you don't clone the entire RMK repo, rather you make your own repo,
-which uses Rusts package manager, `cargo`, to depend on RMK.
-Setup of this repo is aided by the `rmkit` command line tool.
-
-I started by installing a few tools via cargo, running
+Now, the setup between RMK and QMK is a bit different.
+In QMK, you clone the entire QMK repo, make any keymap modifications you want,
+and compile.
+RMK, being written in a language with a decent package manager,
+just has you make a repo from a small template that depends on the RMK crate.
+RMK provides a tool, `rmkit`, to help you setup this repo.
 
+I started by installing `rmkit` and a few embedded tools via cargo, running:
 ```
 cargo install rmkit flip-link elf2uf2-rs probe-rs-tools
 ```
 
-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 I ran `rmkit init` and answered a few questions about my keyboard,
+which generated my initial template.
+From there, I modified `.cargo/config.toml` to use `elf2uf2-rs`,
+as my keyboard does not have an exposed debug header, which would be needed for `probe-rs`.
+The docs mentioned I may have to modify a file called `memory.x`,
+which defines the microcontrollers memory map,
+but I found the template already had the correct memory map for the RP2040.
 
-Then came the hard work, configuring `keyboard.toml`.
-I followed [the docs](https://haobogu.github.io/rmk/keyboard_configuration.html),
-carefully started porting my [Ferris Sweep layout](https://github.com/gabevenberg/qmk_firmware/blob/personal/keyboards/ferris/keymaps/almost_default/keymap.json) to the `keyboard.toml`.
+### `keyboard.toml`
 
-First off, for the keyboard metadata, I simply took from [QMK's Ferris Sweep info.json](https://github.com/gabevenberg/qmk_firmware/blob/personal/keyboards/ferris/sweep/info.json).
+That was the easy part done.
+The next step was to configure a file called `keyboard.toml`.
+This file is used by RMK to configure everything from the type of microcontroller we use,
+to defining which pins on the microcontroller correspond to which keys,
+and even configuring the initial keymap,
+all at compile time.
+Similar to QMK, RMK does provide you with the option to configure your keyboard using Rust code directly,
+but I wasn't doing anything fancy enough to justify that.
 
-Then for the tricky part. We have to define our pin mappings using the peripheral names as [defined by embassy](https://docs.embassy.dev/embassy-rp/git/rp2040/struct.Peripherals.html)
-This is hard because the QMK mappings given in the [keyboard.json](https://github.com/qmk/qmk_firmware/blob/master/keyboards/ferris/sweep/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](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) equivalents.
-In the end, I just cloned the Ferris sweep [repo](https://github.com/davidphilipbarr/Sweep) and opened the files in Kicad,
-cross referencing the schematic with the elite-pis [usage guide](https://docs.keeb.io/elite-pi-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.
+The first part of the `keyboard.toml` contains some basic metadata about your keyboard,
+like its name, USB ID, and what microcontroller it uses.
+I lifted all this info from [QMK's Ferris Sweep info.json](https://github.com/gabevenberg/qmk_firmware/blob/personal/keyboards/ferris/sweep/info.json) for consistencies sake.
 
-After the painstaking process of tracing all the pins and putting them in the matrix, we can define the keymap.
-My [keymap](https://github.com/gabevenberg/qmk_firmware/blob/personal/keyboards/ferris/keymaps/almost_default/keymap.json)
-is a bit complex, so it took some time to port.
-It was mostly tedium rather than anything truly head scratching, however.
+Then I had to configure the pin mappings, defining which pin correspond to each key (in the Ferris Sweeps case, as it is a direct wire, where each pin corresponds to exactly 1 key),
+or defining which pins correspond to rows and columns of the keyboard matrix (in the case of most larger keyboards.)
+This proved more difficult than expected,
+as I planned to take the pin mappings from QMKs pin mapping configuration file,
+the [`keyboard.json`](https://github.com/gabevenberg/qmk_firmware/blob/personal/keyboards/ferris/sweep/info.json).
+However, it was unusable, as the `keyboard.json` gives pin mappings for a different microcontroller,
+the ATmega32U4, specifically for the Aurdino Pro-Micro board.
+QMK does some black magic at compile time in order to rewrite these pin mappings to their RP2040 equivalents,
+but I was not able to figure out said magic in order to do the same by hand.
+In the end, I cloned the [repo](https://github.com/davidphilipbarr/Sweep) for the Ferris Sweep itself and looked at the PCB design in Kicad,
+Tracing where each pin went and cross referencing with the elite-pi (my specific RP2040 board) [usage guide](https://docs.keeb.io/elite-pi-guide) to get the pin number.
 
-## `vial.json`
+Another thing I had to do was define how the 2 microcontrollers in each half of the keyboard communicate with each other,
+and define the pins that are used in that communication.
+Due to being a 'direct wire' design,
+the Ferris Sweep only has one IO pin on each micro that's not dedicated to a key.
+This means it has to use whats called 'half-duplex' UART,
+where a single wire is used for 2 way communication.
+Luckily, RMK supports this mode of communication through the RP2040's [PIO](https://www.raspberrypi.com/news/what-is-pio/) feature.
+Unfortunately, this ability to use half-duplex over PIO is only on RMK's master branch,
+and has not made it into a stable release as of this writing.
+This simply means I had to do some fiddling in the `Cargo.toml` file to instruct cargo to fetch the latest commit from git, rather than getting the latest published version of the package.
 
-Next, and the most complicated step, was creating a `vial.json`.
+After the *painful* process of tracing each pin and defining the pin mappings,
+we can define the keymap.
+My [keymap](https://github.com/gabevenberg/qmk_firmware/blob/personal/keyboards/ferris/keymaps/almost_default/keymap.json) is not especially fancy,
+other than its extensive use of layers and tap-hold Keybinds.
+(keybinds that do a different thing on being held down than they do on tapping them)
+All the features I use are [well documented](https://haobogu.github.io/rmk/keyboard_configuration.html#layout) by RMK,
+so while porting the keymap was tedious, it was not especially difficult or noteworthly.
+
+### `vial.json`
+
+The next and most complicated step, was creating a `vial.json`.
+This file is used by the [VIAL](https://get.vial.today/) software to allow you to remap your keyboard without re-flashing the microcontrollers,
+and for 'reasons', the keyboard will fail to boot if your `vial.json` does not match your keymap.
 The JSON file [provided by the via project](https://github.com/the-via/keyboards/blob/master/src/ferris/sweep/sweep.json) was wrong,
 as it laid 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](https://www.keyboard-layout-editor.com/),
 and follow [vials guide](https://get.vial.today/docs/porting-to-via.html) to remake the `vial.json` in the right layout.
+Ill be honest, I still don't fully understand what I was doing, I just messed around until it worked.
 
-## Flashing and troubleshooting
+## Flashing and debugging
 
 Finally, I could flash my keyboard.
 I flashed it, and... It didn't 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 RP2040's 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, I've made a PR mirroring [QMKs solution](https://github.com/qmk/qmk_firmware/blob/6d0e5728aa61b442885d48caf49d29e5c60e8197/platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c#L133) to this problem. (Ill update this article when it gets merged.)
+only used the RP2040's 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 in the RMK source code,
+but for the long term, I've made a [PR](https://github.com/HaoboGu/rmk/pull/291) mirroring [QMKs solution](https://github.com/qmk/qmk_firmware/blob/6d0e5728aa61b442885d48caf49d29e5c60e8197/platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c#L133) to this problem.
 
 But, after all that, I had a Ferris Sweep running Rust,
 just as the silkscreen demands.
 Granted, until the PR gets merged and a new release is cut,
-its running a modified version of RMK from my own repo, but Rust is Rust.
+its running a modified version of RMK from my own fork, but its still Rust.
 
 The final firmware repo is [here](https://github.com/gabevenberg/ferris-sweep-rmk),
 if you want to use it for your own RP2040, wired Ferris Sweep,
@@ -98,7 +130,7 @@ or just want an example to help you along.
 
 I then proceeded to use RMK for a few tasks, including writing this article.
 It did not feel the exact same as QMK,
-I think some of the timings on tap-hold and debouncing might be different,
+I think some of the timings on tap-hold and key debouncing might be different,
 but, apart from a few repeated keys (which should be fixed once configurable debouncing [lands](https://github.com/HaoboGu/rmk/issues/289),
 it was a very serviceable keyboard firmware.
 Obviously, being a much newer project than QMK,