PMW3610 Optical Mouse Sensor

PMW3610 is a low‑power optical mouse sensor.

NOTE
  • Currently, only implemented for nRF52 and RP2040 with a single-wire (SDIO) half-duplex SPI.
  • Set motion pin for better power efficiency. If omitted, the sensor is polled.
  • By default, report rate is limited to 125 Hz to prevent flooding the event channel, which causes latency issues especially over BLE.

toml configuration

WARNING

spi.mosi and spi.miso must be the same pin, or one of them empty.

[[input_device.pmw3610]]
name = "trackball0"

spi.instance = "bitbang0"
spi.sck = "P0_05"
spi.mosi = "P0_04"
spi.miso = "P0_04"
spi.cs = "P0_09"
# or spi = { instance = "bitbang0", sck = "P0_05", mosi = "P0_04", miso = "P0_04", cs = "P0_09" }

motion = "P0_02" # Optional. If omitted, the sensor is polled.

# Optional: Report rate in Hz
report_hz = 125

force_awake = false
smart_mode = true
cpi = 800
invert_x = true
# invert_y = true
# swap_xy = true

Rust configuration

Define Pmw3610Device and add it to run_devices! macro.

let pmw3610_config = Pmw3610Config {
    res_cpi: 800,
    // force_awake: true,
    smart_mode: true,
    swap_xy: true,
    // invert_x: true,
    // invert_y: true,
    ..Default::default()
};

let pmw3610_sck = Output::new(p.P0_05, Level::High, OutputDrive::Standard);
let pmw3610_sdio = Flex::new(p.P0_04);
let pmw3610_cs = Output::new(p.P0_09, Level::High, OutputDrive::Standard);
let pmw3610_motion = Some(Input::new(p.P0_02, Pull::Up));
// or if you want to omit the motion pin:
// let pmw3610_motion = Option::<Input<'static>>::None;

let pmw3610_spi = BitBangSpiBus::new(pmw3610_sck, pmw3610_sdio);

let mut pmw3610_device = Pmw3610Device::new(
    pmw3610_spi,
    pmw3610_cs,
    pmw3610_motion,
    pmw3610_config,
);

// If you want to customize the report rate (Hz):
// let mut pmw3610_device = Pmw3610Device::with_report_hz(
//     pmw3610_spi,
//     pmw3610_cs,
//     pmw3610_motion,
//     pmw3610_config,
//     125,
// );

run_devices! (
    (matrix, pmw3610_device) => EVENT_CHANNEL,
),

And define a Pmw3610Processor and add it to run_processor_chain! macro to process the events.

WARNING

This should be added to the central if the sensor is on split peripheral.

use rmk::input_device::pmw3610::Pmw3610Processor;

let mut pmw3610_processor = Pmw3610Processor::new(&keymap);

run_processor_chain! {
    EVENT_CHANNEL => [pmw3610_processor],
},