Low Power
RMK supports low-power mode by utilizing the Wait trait in embedded-hal-async.
Usage
By default, RMK uses a busy-loop for matrix scanning, which is not very power efficient. To enable the low-power mode, add the async_matrix feature to your Cargo.toml:
If you're using nRF chips or RP2040, you're all set! Your keyboard is now running in low-power mode. The async_matrix feature enables interrupt-based input detection, and puts your microcontroller into sleep mode when no keys are being pressed.
For STM32, there are some limitations about EXTI (see here):
EXTI is not built into Input itself because it needs to take ownership of the corresponding EXTI channel, which is a limited resource.
Pins PA5, PB5, PC5… all use EXTI channel 5, so you can’t use EXTI on, say, PA5 and PC5 at the same time.
There are a few more things that you need to do:
- Enable the
extifeature for yourembassy-stm32dependency inCargo.toml - Ensure that your input pins don't share the same EXTI channel
- For configuration:
- If you're using
keyboard.toml, you are all set. The#[rmk_keyboard]macro will automatically check yourCargo.tomland handle it for you. - If you're using Rust code, you'll need to use
ExtiInputfor your input pins and bind the EXTI interrupts of those pins. EXTI0 to EXTI4 each have their own interrupt, EXTI5 to EXTI9 shareEXTI9_5, and EXTI10 to EXTI15 shareEXTI15_10:
- If you're using
If your firmware already has a bind_interrupts! block (for example, for USB), add the EXTI lines to that block instead of declaring a second Irqs.
BLE idle sleep
BLE builds also run an idle sleep manager. Set split_central_sleep_timeout_seconds in the [rmk] section of keyboard.toml (default 0, disabled) to put the keyboard to sleep after that many seconds without key or pointing activity. Despite the name, it applies to every BLE keyboard, not only split centrals:
When the keyboard falls asleep, RMK publishes a SleepStateEvent, holds battery level reports, and on a split central switches the peripheral links to slower connection parameters. Any key press wakes the keyboard up. The host's HID suspend and exit-suspend commands also put the keyboard to sleep and wake it.
A sleeping split central keeps its radio idle rather than scanning, so a peripheral link that drops gets a single reconnect attempt. If that attempt fails, the central keeps the peripheral's address: press a key on the central half while the peripheral is still advertising (about five minutes) and the halves relink instead of rediscovering each other. After that the peripheral stops advertising too, so it takes a key press on each half to bring the link back.
Two related behaviors are always on:
- When BLE advertising times out without a connection (after 5 minutes), the keyboard sleeps immediately and waits for a key or pointing event before it advertises again.
NrfAdctakes alight_sleepinterval as its last argument. When the analog inputs have been idle for more than 1.2 seconds, the ADC polls at that interval instead ofpolling_interval. A joystick configured inkeyboard.tomluses 350ms.
Split central sleep using BLE Connection Subrating (tested on nrf52840 only)
Enable the subrating feature in your Cargo.toml to let a sleeping central skip connection events while still switching back to the fast intervals in one step.
The key press that wakes the keyboard costs up to ~232ms (~116ms on average) when it lands on the peripheral half; keys on the central half are never delayed. The link is back on the active parameters right after that, which is cheap enough to shorten the timeout aggressively:
With no host connected the central skips further: the waking peripheral key press costs ~472ms on average and up to ~945ms, and the central draws ~22µA, nearly the same as the peripheral (~21µA).
External VCC
Some boards, such as the nice!nano have an external 3.3V regulator that can be used to power the LEDs. If not used, the regulator can be disabled by pulling P0_13 low to safe power.
In the case of the nice!nano, this can be done by adding the following line to main.rs
or the following snippet to your keyboard.toml: