rewrote lare parts of the RMK on ferris sweep article.
This commit is contained in:
parent
487b164e43
commit
a75393b5c6
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue