Rotary encoders
A rotary encoder is a common input device that can be used for volume control, page scrolling, and other functions.
toml configuration
You can define a rotary encoder in your keyboard.toml:
[[input_device.encoder]]
pin_a = "P0_30"
pin_b = "P0_31"
# Whether to use the MCU's internal pull-up resistor, default to false
internal_pullup = false
# Working mode of the encoder
# Available modes:
# - default: resolution = 1
# - resolution: custom resolution, requires specifying resolution and reverse parameters
phase = "resolution"
# `resolution` represents the number of steps generated per detent.
#
# When your encoder datasheet lists:
# - detent = number of mechanical detent positions
# - pulse = number of full quadrature cycles (A/B cycles)
#
# Then the relationship is:
# resolution = (pulse × 4) / detent
# because each full quadrature cycle (pulse) produces 4 edge transitions.
#
# For example — in the ALPS EC11E series (https://tech.alpsalpine.com/cms.media/product_catalog_ec_01_ec11e_en_611f078659.pdf):
# detent = 30, pulse = 15 → resolution = (15 × 4) / 30 = 2
resolution = 2
# Or you can specify detent and pulse to calculate resolution automatically
resolution = { detent = 30, pulse = 15 }
# Whether the direction of the rotary encoder is reversed.
reverse = false
Multiple encoders can be added directly, the encoder index is determined by the order:
# Encoder 0
[[input_device.encoder]]
pin_a = "P0_01"
pin_b = "P0_02"
phase = "default"
# Encoder 1
[[input_device.encoder]]
pin_a = "P0_03"
pin_b = "P0_04"
phase = "default"
Rust configuration
With Rust, you can define a rotary encoder as the following:
use rmk::input_device::rotary_encoder::RotaryEncoder;
use rmk::input_device::rotary_encoder::DefaultPhase;
let pin_a = Input::new(p.P1_06, embassy_nrf::gpio::Pull::None);
let pin_b = Input::new(p.P1_04, embassy_nrf::gpio::Pull::None);
let mut encoder = RotaryEncoder::with_phase(pin_a, pin_b, DefaultPhase, encoder_id);
You can also use the resolution based phase:
use rmk::input_device::rotary_encoder::RotaryEncoder;
let pin_a = Input::new(p.P1_06, embassy_nrf::gpio::Pull::None);
let pin_b = Input::new(p.P1_04, embassy_nrf::gpio::Pull::None);
// Create an encoder with resolution = 2, reversed = false
let mut encoder = RotaryEncoder::with_resolution(pin_a, pin_b, 2, false, encoder_id)
Then add the encoder to the device list of run_device.
join3(
run_devices! (
(matrix, encoder) => EVENT_CHANNEL,
),
keyboard.run(), // Keyboard is special
run_rmk(&keymap, driver, storage, rmk_config, sd),
)
.await;