From 3c9b5df3b502c020eff1fc6da19df5320fbbe155 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Mon, 16 Dec 2024 17:21:56 +0800 Subject: [PATCH 01/21] wip: input device Signed-off-by: Haobo Gu --- rmk/src/input_device/mod.rs | 1 + rmk/src/lib.rs | 1 + 2 files changed, 2 insertions(+) create mode 100644 rmk/src/input_device/mod.rs diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs new file mode 100644 index 00000000..8273c14b --- /dev/null +++ b/rmk/src/input_device/mod.rs @@ -0,0 +1 @@ +//! Input device for RMK \ No newline at end of file diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index 69218137..aa376ff1 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -65,6 +65,7 @@ mod debounce; pub mod direct_pin; mod flash; mod hid; +mod input_device; mod keyboard; mod keyboard_macro; pub mod keycode; From 29a8972863d011defa60305ac805a8df7e7fe2b5 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 24 Dec 2024 15:22:37 +0800 Subject: [PATCH 02/21] wip(input_device): POC impl for input device trait Signed-off-by: Haobo Gu --- examples/use_rust/nrf52840_ble/src/main.rs | 21 ++++++++ rmk/src/input_device/mod.rs | 59 +++++++++++++++++++++- rmk/src/input_device/rotary_encoder.rs | 18 +++++++ rmk/src/lib.rs | 2 +- 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 rmk/src/input_device/rotary_encoder.rs diff --git a/examples/use_rust/nrf52840_ble/src/main.rs b/examples/use_rust/nrf52840_ble/src/main.rs index a2692a41..7acb88b8 100644 --- a/examples/use_rust/nrf52840_ble/src/main.rs +++ b/examples/use_rust/nrf52840_ble/src/main.rs @@ -21,6 +21,11 @@ use panic_probe as _; use rmk::{ ble::SOFTWARE_VBUS, config::{BleBatteryConfig, KeyboardUsbConfig, RmkConfig, StorageConfig, VialConfig}, + impl_input_device, + input_device::{ + rotary_encoder::{rotary_encoder_task, RotaryEncoder}, + InputDevice, + }, run_rmk, }; @@ -106,6 +111,11 @@ async fn main(spawner: Spawner) { ..Default::default() }; + let encoder = RotaryEncoder {}; + spawner.spawn(rotary_encoder_task(encoder)).unwrap(); + let my_device = MyDevice {}; + spawner.spawn(my_device_task(my_device)).unwrap(); + run_rmk( input_pins, output_pins, @@ -116,3 +126,14 @@ async fn main(spawner: Spawner) { ) .await; } + +struct MyDevice {} +impl InputDevice for MyDevice { + async fn run(&mut self) { + loop { + info!("Hi my device"); + embassy_time::Timer::after_secs(1).await; + } + } +} +impl_input_device!(MyDevice, my_device_task); diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs index 8273c14b..8aede0ee 100644 --- a/rmk/src/input_device/mod.rs +++ b/rmk/src/input_device/mod.rs @@ -1 +1,58 @@ -//! Input device for RMK \ No newline at end of file +//! Input device for RMK +//! + +use core::future::Future; + +pub mod rotary_encoder; + +/// The trait for input devices. +/// +/// This trait MUST be used with `impl_input_device` macro, which will automatically create a static embassy task for the input device. +/// The following is an example for the usage of this trait: +/// ```rust +/// use core::futures::Future; +/// struct MyInputDevice; +/// impl InputDevice for MyInputDevice { +/// fn run(&mut self) -> impl Future { +/// // Implementation +/// } +/// } +/// impl_input_device!(MyInputDevice, my_input_device_task); +/// ``` +/// The expanded code will be: +/// ```rust +/// use core::futures::Future; +/// struct MyInputDevice; +/// impl InputDevice for MyInputDevice { +/// fn run(&mut self) -> impl Future { +/// // Implementation +/// } +/// } +/// #[embassy_executor::task] +/// async fn my_input_device_task(device: MyInputDevice) -> ! { +/// device.run().await +/// } +/// ``` +/// Then, you can spawn `my_input_device_task` as an embassy task: +/// ```rust +/// let input_device = MyInputDevice{}; +/// spawner.spawn(my_input_device_task(input_device)); +/// ``` +pub trait InputDevice { + fn run(&mut self) -> impl Future; +} + +#[macro_export] +macro_rules! impl_input_device { + ($device:ty, $task_name:ident) => { + #[::embassy_executor::task] + pub async fn $task_name(mut device: $device) -> ! { + device.run().await; + loop { + // If the device.run() completes, we enter an infinite loop to satisfy + // the `-> !` return type requirement for embassy tasks + ::embassy_time::Timer::after_secs(1).await; + } + } + }; +} diff --git a/rmk/src/input_device/rotary_encoder.rs b/rmk/src/input_device/rotary_encoder.rs new file mode 100644 index 00000000..10b898d8 --- /dev/null +++ b/rmk/src/input_device/rotary_encoder.rs @@ -0,0 +1,18 @@ +use defmt::info; + +use crate::impl_input_device; + +use super::InputDevice; + +pub struct RotaryEncoder {} + +impl InputDevice for RotaryEncoder{ + async fn run(&mut self) { + loop { + embassy_time::Timer::after_secs(1).await; + info!("hello device") + } + } +} + +impl_input_device!(RotaryEncoder, rotary_encoder_task); \ No newline at end of file diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index 5b642f3c..946d0f97 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -65,7 +65,7 @@ mod debounce; pub mod direct_pin; mod flash; mod hid; -mod input_device; +pub mod input_device; mod keyboard; mod keyboard_macro; pub mod keycode; From 4c7a48fcda572b8dde363448baa39ec7af0c1da0 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 24 Dec 2024 17:40:39 +0800 Subject: [PATCH 03/21] feat(input_device): add first POC impl of input device, add rotary encoder as the example Signed-off-by: Haobo Gu --- rmk/src/input_device/mod.rs | 95 +++++++++------ rmk/src/input_device/rotary_encoder.rs | 157 +++++++++++++++++++++++-- 2 files changed, 206 insertions(+), 46 deletions(-) diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs index 8aede0ee..4c1e7070 100644 --- a/rmk/src/input_device/mod.rs +++ b/rmk/src/input_device/mod.rs @@ -1,5 +1,9 @@ -//! Input device for RMK +//! Input device module for RMK //! +//! This module defines the `InputDevice` trait and the `run_devices` macro, enabling the simultaneous execution of multiple input devices. +//! The `InputDevice` trait provides the interface for individual input devices, and the `run_devices` macro facilitates their concurrent execution. +//! +//! Note: The `InputDevice` trait must be used in conjunction with the `run_devices` macro to ensure correct execution of all input devices. use core::future::Future; @@ -7,52 +11,67 @@ pub mod rotary_encoder; /// The trait for input devices. /// -/// This trait MUST be used with `impl_input_device` macro, which will automatically create a static embassy task for the input device. -/// The following is an example for the usage of this trait: -/// ```rust -/// use core::futures::Future; -/// struct MyInputDevice; -/// impl InputDevice for MyInputDevice { -/// fn run(&mut self) -> impl Future { -/// // Implementation -/// } -/// } -/// impl_input_device!(MyInputDevice, my_input_device_task); -/// ``` -/// The expanded code will be: +/// This trait defines the interface for input devices in RMK. +/// The `run_devices` macro is required to run tasks associated with input devices concurrently. +/// +/// # Example /// ```rust -/// use core::futures::Future; +/// // Define an input device /// struct MyInputDevice; +/// /// impl InputDevice for MyInputDevice { -/// fn run(&mut self) -> impl Future { -/// // Implementation +/// async fn run(&mut self) { +/// // Input device implementation /// } /// } -/// #[embassy_executor::task] -/// async fn my_input_device_task(device: MyInputDevice) -> ! { -/// device.run().await -/// } -/// ``` -/// Then, you can spawn `my_input_device_task` as an embassy task: -/// ```rust -/// let input_device = MyInputDevice{}; -/// spawner.spawn(my_input_device_task(input_device)); +/// +/// // Use the input device +/// let d1 = MyInputDevice{}; +/// let d2 = MyInputDevice{}; +/// +/// // Run all devices simultaneously with RMK +/// embassy_futures::join::join( +/// run_devices!(d1, d2), +/// run_rmk( +/// // .. arguments +/// ), +/// ) +/// .await; /// ``` pub trait InputDevice { + /// Starts the input device task. + /// + /// This asynchronous method should contain the main logic for the input device. + /// It will be executed concurrently with other input devices using the `run_devices` macro. fn run(&mut self) -> impl Future; } +/// Macro to run multiple input devices concurrently. +/// +/// The `run_devices` macro is specifically designed to work with the `InputDevice` trait. It takes one or more instances of +/// input devices and combines their `run` methods into a single future. All futures are executed concurrently, enabling +/// efficient multitasking for multiple input devices. +/// +/// # Note +/// This macro must be used with input devices that implement the `InputDevice` trait. +/// +/// # Example +/// ```rust +/// // `MyInputDevice` should implement `InputDevice` trait +/// let d1 = MyInputDevice{}; +/// let d2 = MyInputDevice{}; +/// +/// // Run all input devices concurrently +/// run_devices!(d1, d2).await; +/// ``` #[macro_export] -macro_rules! impl_input_device { - ($device:ty, $task_name:ident) => { - #[::embassy_executor::task] - pub async fn $task_name(mut device: $device) -> ! { - device.run().await; - loop { - // If the device.run() completes, we enter an infinite loop to satisfy - // the `-> !` return type requirement for embassy tasks - ::embassy_time::Timer::after_secs(1).await; - } - } +macro_rules! run_devices { + // Single device case + ($single:expr) => { + $single.run() }; -} + // Multiple devices case + ($first:expr, $second:expr $(, $rest:expr)*) => { + ::embassy_futures::join::join($first.run(), run_devices!($second $(, $rest)*)) + }; +} \ No newline at end of file diff --git a/rmk/src/input_device/rotary_encoder.rs b/rmk/src/input_device/rotary_encoder.rs index 10b898d8..03d32e33 100644 --- a/rmk/src/input_device/rotary_encoder.rs +++ b/rmk/src/input_device/rotary_encoder.rs @@ -1,18 +1,159 @@ -use defmt::info; +//! The rotary encoder implementation is from: https://github.com/leshow/rotary-encoder-hal/blob/master/src/lib.rs +//! -use crate::impl_input_device; +use defmt::info; +use embedded_hal::digital::InputPin; +#[cfg(feature = "async_matrix")] +use embedded_hal_async::digital::Wait; use super::InputDevice; -pub struct RotaryEncoder {} +/// Holds current/old state and both [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html) +#[derive(Clone, Debug, Eq, PartialEq)] +// #[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct RotaryEncoder { + pin_a: A, + pin_b: B, + state: u8, + phase: P, +} + +/// The encoder direction is either `Clockwise`, `CounterClockwise`, or `None` +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +// #[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Direction { + /// A clockwise turn + Clockwise, + /// A counterclockwise turn + CounterClockwise, + /// No change + None, +} + +/// Allows customizing which Quadrature Phases should be considered movements +/// and in which direction or ignored. +pub trait Phase { + /// Given the current state `s`, return the direction. + fn direction(&mut self, s: u8) -> Direction; +} + +/// Default implementation of `Phase`. +pub struct DefaultPhase; + +/// The useful values of `s` are: +/// - 0b0001 | 0b0111 | 0b1000 | 0b1110 +/// - 0b0010 | 0b0100 | 0b1011 | 0b1101 +impl Phase for DefaultPhase { + fn direction(&mut self, s: u8) -> Direction { + match s { + 0b0001 | 0b0111 | 0b1000 | 0b1110 => Direction::Clockwise, + 0b0010 | 0b0100 | 0b1011 | 0b1101 => Direction::CounterClockwise, + _ => Direction::None, + } + } +} + +impl RotaryEncoder +where + A: InputPin, + B: InputPin, +{ + /// Accepts two [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html)s, these will be read on every `update()` + pub fn new(pin_a: A, pin_b: B) -> Self { + Self { + pin_a, + pin_b, + state: 0u8, + phase: DefaultPhase, + } + } +} + +impl RotaryEncoder { + /// Accepts two [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html)s, these will be read on every `update()`, while using `phase` to determine the direction. + pub fn with_phase(pin_a: A, pin_b: B, phase: P) -> Self { + Self { + pin_a, + pin_b, + state: 0u8, + phase, + } + } + + /// Call `update` to evaluate the next state of the encoder, propagates errors from `InputPin` read + pub fn update(&mut self) -> Direction { + // use mask to get previous state value + let mut s = self.state & 0b11; + + let (a_is_low, b_is_low) = (self.pin_a.is_low(), self.pin_b.is_low()); + + // move in the new state + match a_is_low { + Ok(true) => s |= 0b0100, + Ok(false) => {} + Err(_) => return Direction::None, + } + match b_is_low { + Ok(true) => s |= 0b1000, + Ok(false) => {} + Err(_) => return Direction::None, + } + + // move new state in + self.state = s >> 2; + self.phase.direction(s) + } + + /// Returns a reference to the first pin. Can be used to clear interrupt. + pub fn pin_a(&mut self) -> &mut A { + &mut self.pin_a + } + + /// Returns a reference to the second pin. Can be used to clear interrupt. + pub fn pin_b(&mut self) -> &mut B { + &mut self.pin_b + } + + /// Returns a reference to both pins. Can be used to clear interrupt. + pub fn pins(&mut self) -> (&mut A, &mut B) { + (&mut self.pin_a, &mut self.pin_b) + } -impl InputDevice for RotaryEncoder{ + /// Consumes this `Rotary`, returning the underlying pins `A` and `B`. + pub fn into_inner(self) -> (A, B) { + (self.pin_a, self.pin_b) + } +} + +impl< + #[cfg(feature = "async_matrix")] A: InputPin + Wait, + #[cfg(not(feature = "async_matrix"))] A: InputPin, + #[cfg(feature = "async_matrix")] B: InputPin + Wait, + #[cfg(not(feature = "async_matrix"))] B: InputPin, + P: Phase, + > InputDevice for RotaryEncoder +{ async fn run(&mut self) { loop { - embassy_time::Timer::after_secs(1).await; - info!("hello device") + #[cfg(feature = "async_matrix")] + { + let (pin_a, pin_b) = self.pins(); + embassy_futures::select::select( + pin_a.wait_for_any_edge(), + pin_b.wait_for_any_edge(), + ) + .await; + } + // If not using async_matrix feature, scanning the encoder pins with 50HZ frequency + #[cfg(not(feature = "async_matrix"))] + embassy_time::Timer::after_millis(20).await; + let direction = self.update(); + // TODO: Process directions + match direction { + Direction::Clockwise => info!("Clockwise"), + Direction::CounterClockwise => info!("CounterClockwise"), + Direction::None => {} + } } } } - -impl_input_device!(RotaryEncoder, rotary_encoder_task); \ No newline at end of file From 32236eef17fe77a2ad70ab7eb66ce23ca5b861c1 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Wed, 25 Dec 2024 18:26:05 +0800 Subject: [PATCH 04/21] chore: update input device example Signed-off-by: Haobo Gu --- examples/use_rust/nrf52840_ble/Cargo.toml | 2 ++ examples/use_rust/nrf52840_ble/src/main.rs | 34 ++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/use_rust/nrf52840_ble/Cargo.toml b/examples/use_rust/nrf52840_ble/Cargo.toml index 6a9796e5..18159a06 100644 --- a/examples/use_rust/nrf52840_ble/Cargo.toml +++ b/examples/use_rust/nrf52840_ble/Cargo.toml @@ -34,6 +34,8 @@ embassy-executor = { version = "0.6", features = [ "executor-thread", "integrated-timers", ] } +embassy-futures = { version = "0.1", features = ["defmt"] } + defmt = "0.3" defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } diff --git a/examples/use_rust/nrf52840_ble/src/main.rs b/examples/use_rust/nrf52840_ble/src/main.rs index 7acb88b8..a59a2c6f 100644 --- a/examples/use_rust/nrf52840_ble/src/main.rs +++ b/examples/use_rust/nrf52840_ble/src/main.rs @@ -21,12 +21,8 @@ use panic_probe as _; use rmk::{ ble::SOFTWARE_VBUS, config::{BleBatteryConfig, KeyboardUsbConfig, RmkConfig, StorageConfig, VialConfig}, - impl_input_device, - input_device::{ - rotary_encoder::{rotary_encoder_task, RotaryEncoder}, - InputDevice, - }, - run_rmk, + input_device::{rotary_encoder::RotaryEncoder, InputDevice}, + run_devices, run_rmk, }; use vial::{VIAL_KEYBOARD_DEF, VIAL_KEYBOARD_ID}; @@ -111,18 +107,21 @@ async fn main(spawner: Spawner) { ..Default::default() }; - let encoder = RotaryEncoder {}; - spawner.spawn(rotary_encoder_task(encoder)).unwrap(); - let my_device = MyDevice {}; - spawner.spawn(my_device_task(my_device)).unwrap(); + let mut my_device = MyDevice {}; + let pin_a = Input::new(AnyPin::from(p.P0_06), embassy_nrf::gpio::Pull::Up); + let pin_b = Input::new(AnyPin::from(p.P0_11), embassy_nrf::gpio::Pull::Up); + let mut encoder = RotaryEncoder::new(pin_a, pin_b); - run_rmk( - input_pins, - output_pins, - driver, - &mut keymap::get_default_keymap(), - keyboard_config, - spawner, + embassy_futures::join::join( + run_rmk( + input_pins, + output_pins, + driver, + &mut keymap::get_default_keymap(), + keyboard_config, + spawner, + ), + run_devices!(my_device, encoder), ) .await; } @@ -136,4 +135,3 @@ impl InputDevice for MyDevice { } } } -impl_input_device!(MyDevice, my_device_task); From ae465ff5077e5810397ce0895814592350b439f8 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Thu, 26 Dec 2024 15:17:07 +0800 Subject: [PATCH 05/21] feat(input_device): send event from the rotary encoder Signed-off-by: Haobo Gu --- examples/use_rust/nrf52840_ble/src/main.rs | 2 +- rmk/src/input_device/mod.rs | 16 +++--- rmk/src/input_device/rotary_encoder.rs | 67 ++++++++++++++++++---- 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/examples/use_rust/nrf52840_ble/src/main.rs b/examples/use_rust/nrf52840_ble/src/main.rs index a59a2c6f..c8c459c2 100644 --- a/examples/use_rust/nrf52840_ble/src/main.rs +++ b/examples/use_rust/nrf52840_ble/src/main.rs @@ -110,7 +110,7 @@ async fn main(spawner: Spawner) { let mut my_device = MyDevice {}; let pin_a = Input::new(AnyPin::from(p.P0_06), embassy_nrf::gpio::Pull::Up); let pin_b = Input::new(AnyPin::from(p.P0_11), embassy_nrf::gpio::Pull::Up); - let mut encoder = RotaryEncoder::new(pin_a, pin_b); + let mut encoder = RotaryEncoder::new(pin_a, pin_b, (0, 0), (0, 1)); embassy_futures::join::join( run_rmk( diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs index 4c1e7070..6b0c086e 100644 --- a/rmk/src/input_device/mod.rs +++ b/rmk/src/input_device/mod.rs @@ -3,32 +3,34 @@ //! This module defines the `InputDevice` trait and the `run_devices` macro, enabling the simultaneous execution of multiple input devices. //! The `InputDevice` trait provides the interface for individual input devices, and the `run_devices` macro facilitates their concurrent execution. //! -//! Note: The `InputDevice` trait must be used in conjunction with the `run_devices` macro to ensure correct execution of all input devices. +//! Note: The `InputDevice` trait must be used in conjunction with the `run_devices` macro to ensure correct execution of all input devices. use core::future::Future; +use crate::keyboard::key_event_channel; + pub mod rotary_encoder; /// The trait for input devices. /// /// This trait defines the interface for input devices in RMK. /// The `run_devices` macro is required to run tasks associated with input devices concurrently. -/// +/// /// # Example /// ```rust /// // Define an input device /// struct MyInputDevice; -/// +/// /// impl InputDevice for MyInputDevice { /// async fn run(&mut self) { /// // Input device implementation /// } /// } -/// +/// /// // Use the input device /// let d1 = MyInputDevice{}; /// let d2 = MyInputDevice{}; -/// +/// /// // Run all devices simultaneously with RMK /// embassy_futures::join::join( /// run_devices!(d1, d2), @@ -60,7 +62,7 @@ pub trait InputDevice { /// // `MyInputDevice` should implement `InputDevice` trait /// let d1 = MyInputDevice{}; /// let d2 = MyInputDevice{}; -/// +/// /// // Run all input devices concurrently /// run_devices!(d1, d2).await; /// ``` @@ -74,4 +76,4 @@ macro_rules! run_devices { ($first:expr, $second:expr $(, $rest:expr)*) => { ::embassy_futures::join::join($first.run(), run_devices!($second $(, $rest)*)) }; -} \ No newline at end of file +} diff --git a/rmk/src/input_device/rotary_encoder.rs b/rmk/src/input_device/rotary_encoder.rs index 03d32e33..44d16151 100644 --- a/rmk/src/input_device/rotary_encoder.rs +++ b/rmk/src/input_device/rotary_encoder.rs @@ -1,21 +1,26 @@ //! The rotary encoder implementation is from: https://github.com/leshow/rotary-encoder-hal/blob/master/src/lib.rs //! -use defmt::info; use embedded_hal::digital::InputPin; #[cfg(feature = "async_matrix")] use embedded_hal_async::digital::Wait; -use super::InputDevice; +use crate::keyboard::KeyEvent; + +use super::{key_event_channel, InputDevice}; /// Holds current/old state and both [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html) -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug)] // #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RotaryEncoder { pin_a: A, pin_b: B, state: u8, phase: P, + /// (row, col) position in the keymap + clockwise_pos: (u8, u8), + /// (row, col) position in the keymap + counter_clockwise_pos: (u8, u8), } /// The encoder direction is either `Clockwise`, `CounterClockwise`, or `None` @@ -58,25 +63,44 @@ where A: InputPin, B: InputPin, { - /// Accepts two [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html)s, these will be read on every `update()` - pub fn new(pin_a: A, pin_b: B) -> Self { + /// Accepts two [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html)s, these will be read on every `update()`. + /// + /// `clockwise_pos` and `counter_clockwise_pos` are the (row, col) positions in the keymap. + pub fn new( + pin_a: A, + pin_b: B, + clockwise_pos: (u8, u8), + counter_clockwise_pos: (u8, u8), + ) -> Self { Self { pin_a, pin_b, state: 0u8, phase: DefaultPhase, + clockwise_pos, + counter_clockwise_pos, } } } impl RotaryEncoder { /// Accepts two [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html)s, these will be read on every `update()`, while using `phase` to determine the direction. - pub fn with_phase(pin_a: A, pin_b: B, phase: P) -> Self { + /// + /// `clockwise_pos` and `counter_clockwise_pos` are the (row, col) positions in the keymap. + pub fn with_phase( + pin_a: A, + pin_b: B, + phase: P, + clockwise_pos: (u8, u8), + counter_clockwise_pos: (u8, u8), + ) -> Self { Self { pin_a, pin_b, state: 0u8, phase, + clockwise_pos, + counter_clockwise_pos, } } @@ -148,12 +172,31 @@ impl< #[cfg(not(feature = "async_matrix"))] embassy_time::Timer::after_millis(20).await; let direction = self.update(); - // TODO: Process directions - match direction { - Direction::Clockwise => info!("Clockwise"), - Direction::CounterClockwise => info!("CounterClockwise"), - Direction::None => {} - } + // TODO: Resolution + let (row, col) = match direction { + Direction::Clockwise => (self.clockwise_pos.0, self.clockwise_pos.1), + Direction::CounterClockwise => { + (self.counter_clockwise_pos.0, self.counter_clockwise_pos.1) + } + Direction::None => continue, + }; + + // Send the key event, process it like a tap + key_event_channel + .send(KeyEvent { + row, + col, + pressed: true, + }) + .await; + embassy_time::Timer::after_millis(10).await; + key_event_channel + .send(KeyEvent { + row, + col, + pressed: false, + }) + .await; } } } From 2a186c71bd38084d425b9242da928e0f19c0a3e4 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Thu, 26 Dec 2024 15:23:05 +0800 Subject: [PATCH 06/21] feat(input_device): expose key event channel Signed-off-by: Haobo Gu --- docs/po/zh_CN.po | 4 ++-- docs/src/how_to_contribute.md | 4 ++-- rmk/src/ble/esp/mod.rs | 6 ++--- rmk/src/ble/nrf/mod.rs | 6 ++--- rmk/src/direct_pin.rs | 4 ++-- rmk/src/input_device/mod.rs | 2 -- rmk/src/input_device/rotary_encoder.rs | 8 +++---- rmk/src/keyboard.rs | 33 +++++++++++++------------- rmk/src/lib.rs | 8 +++---- rmk/src/matrix.rs | 4 ++-- rmk/src/split/central.rs | 10 ++++---- rmk/src/split/driver.rs | 6 ++--- rmk/src/split/peripheral.rs | 4 ++-- 13 files changed, 49 insertions(+), 50 deletions(-) diff --git a/docs/po/zh_CN.po b/docs/po/zh_CN.po index 157b11d6..940ecef4 100644 --- a/docs/po/zh_CN.po +++ b/docs/po/zh_CN.po @@ -2538,7 +2538,7 @@ msgstr "" #: src\how_to_contribute.md:41 msgid "" -"`key_event_channel`: a multi-sender, single-receiver channel. The sender can " +"`KEY_EVENT_CHANNEL`: a multi-sender, single-receiver channel. The sender can " "be a matrix task which scans the key matrix or a split peripheral monitor " "which receives key event from split peripheral. The receiver, i.e. keyboard " "task, receives the key event and processes the key" @@ -2546,7 +2546,7 @@ msgstr "" #: src\how_to_contribute.md:42 msgid "" -"`keyboard_report_channel`: a single-sender, single-receiver channel, " +"`KEYBOARD_REPORT_CHANNEL`: a single-sender, single-receiver channel, " "keyboard task sends keyboard report to channel after the key event is " "processed, and USB/BLE task receives the keyboard report and sends the key " "to the host." diff --git a/docs/src/how_to_contribute.md b/docs/src/how_to_contribute.md index 849e7de5..a43a6d32 100644 --- a/docs/src/how_to_contribute.md +++ b/docs/src/how_to_contribute.md @@ -33,8 +33,8 @@ So, if you want to contribute new features of RMK, just look into `rmk` core cra Generally, there are 4-5 running tasks in the meanwhile, according to the user's config. Communication between tasks is done by channels.There are several built-in channels: - `FLASH_CHANNEL`: a multi-sender, single-receiver channel. There are many tasks send the `FlashOperationMessage`, such as BLE task(which saves bond info), vial task(which saves key), etc. -- `key_event_channel`: a multi-sender, single-receiver channel. The sender can be a matrix task which scans the key matrix or a split peripheral monitor which receives key event from split peripheral. The receiver, i.e. keyboard task, receives the key event and processes the key -- `keyboard_report_channel`: a single-sender, single-receiver channel, keyboard task sends keyboard report to channel after the key event is processed, and USB/BLE task receives the keyboard report and sends the key to the host. +- `KEY_EVENT_CHANNEL`: a multi-sender, single-receiver channel. The sender can be a matrix task which scans the key matrix or a split peripheral monitor which receives key event from split peripheral. The receiver, i.e. keyboard task, receives the key event and processes the key +- `KEYBOARD_REPORT_CHANNEL`: a single-sender, single-receiver channel, keyboard task sends keyboard report to channel after the key event is processed, and USB/BLE task receives the keyboard report and sends the key to the host. ### Matrix scanning & key processing diff --git a/rmk/src/ble/esp/mod.rs b/rmk/src/ble/esp/mod.rs index 95f71d62..5869871c 100644 --- a/rmk/src/ble/esp/mod.rs +++ b/rmk/src/ble/esp/mod.rs @@ -2,7 +2,7 @@ pub(crate) mod server; use self::server::{BleServer, VialReaderWriter}; use crate::config::StorageConfig; -use crate::keyboard::keyboard_report_channel; +use crate::keyboard::KEYBOARD_REPORT_CHANNEL; use crate::matrix::MatrixTrait; use crate::storage::nor_flash::esp_partition::{Partition, PartitionType}; use crate::storage::Storage; @@ -61,8 +61,8 @@ pub(crate) async fn initialize_esp_ble_keyboard_with_config_and_run< let keymap = RefCell::new(KeyMap::new_from_storage(default_keymap, Some(&mut storage)).await); - let keyboard_report_sender = keyboard_report_channel.sender(); - let keyboard_report_receiver = keyboard_report_channel.receiver(); + let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); + let keyboard_report_receiver = KEYBOARD_REPORT_CHANNEL.receiver(); let mut keyboard = Keyboard::new( &keymap, diff --git a/rmk/src/ble/nrf/mod.rs b/rmk/src/ble/nrf/mod.rs index 63a379da..4fce1dbf 100644 --- a/rmk/src/ble/nrf/mod.rs +++ b/rmk/src/ble/nrf/mod.rs @@ -10,7 +10,7 @@ mod vial_service; use self::server::BleServer; use crate::config::BleBatteryConfig; -use crate::keyboard::{keyboard_report_channel, REPORT_CHANNEL_SIZE}; +use crate::keyboard::{KEYBOARD_REPORT_CHANNEL, REPORT_CHANNEL_SIZE}; use crate::matrix::MatrixTrait; use crate::storage::StorageKeys; use crate::{ @@ -295,8 +295,8 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< let ble_server = unwrap!(BleServer::new(sd, keyboard_config.usb_config, bonder)); - let keyboard_report_sender = keyboard_report_channel.sender(); - let keyboard_report_receiver = keyboard_report_channel.receiver(); + let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); + let keyboard_report_receiver = KEYBOARD_REPORT_CHANNEL.receiver(); // Keyboard services let mut keyboard = Keyboard::new( diff --git a/rmk/src/direct_pin.rs b/rmk/src/direct_pin.rs index f0a56c67..3bd0df32 100644 --- a/rmk/src/direct_pin.rs +++ b/rmk/src/direct_pin.rs @@ -5,7 +5,7 @@ use crate::debounce::default_bouncer::DefaultDebouncer; use crate::debounce::fast_debouncer::RapidDebouncer; use crate::debounce::DebounceState; use crate::debounce::DebouncerTrait; -use crate::keyboard::key_event_channel; +use crate::keyboard::KEY_EVENT_CHANNEL; use crate::keyboard::KeyEvent; use crate::matrix::KeyState; use crate::MatrixTrait; @@ -330,7 +330,7 @@ impl< self.key_states[row_idx][col_idx].toggle_pressed(); let key_state = self.key_states[row_idx][col_idx]; - key_event_channel + KEY_EVENT_CHANNEL .send(KeyEvent { row: row_idx as u8, col: col_idx as u8, diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs index 6b0c086e..8d6ea4cc 100644 --- a/rmk/src/input_device/mod.rs +++ b/rmk/src/input_device/mod.rs @@ -7,8 +7,6 @@ use core::future::Future; -use crate::keyboard::key_event_channel; - pub mod rotary_encoder; /// The trait for input devices. diff --git a/rmk/src/input_device/rotary_encoder.rs b/rmk/src/input_device/rotary_encoder.rs index 44d16151..89a2aa07 100644 --- a/rmk/src/input_device/rotary_encoder.rs +++ b/rmk/src/input_device/rotary_encoder.rs @@ -5,9 +5,9 @@ use embedded_hal::digital::InputPin; #[cfg(feature = "async_matrix")] use embedded_hal_async::digital::Wait; -use crate::keyboard::KeyEvent; +use crate::keyboard::{KeyEvent, KEY_EVENT_CHANNEL}; -use super::{key_event_channel, InputDevice}; +use super::InputDevice; /// Holds current/old state and both [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html) #[derive(Clone, Debug)] @@ -182,7 +182,7 @@ impl< }; // Send the key event, process it like a tap - key_event_channel + KEY_EVENT_CHANNEL .send(KeyEvent { row, col, @@ -190,7 +190,7 @@ impl< }) .await; embassy_time::Timer::after_millis(10).await; - key_event_channel + KEY_EVENT_CHANNEL .send(KeyEvent { row, col, diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index ef59811d..bd227da9 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -22,21 +22,22 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; use usbd_hid::descriptor::KeyboardReport; + #[derive(Serialize, Deserialize, Clone, Copy, Debug, Format, MaxSize)] -pub(crate) struct KeyEvent { - pub(crate) row: u8, - pub(crate) col: u8, - pub(crate) pressed: bool, +pub struct KeyEvent { + pub row: u8, + pub col: u8, + pub pressed: bool, } pub(crate) const EVENT_CHANNEL_SIZE: usize = 32; -pub(crate) const REPORT_CHANNEL_SIZE: usize = 32; - -pub(crate) static key_event_channel: Channel< +pub static KEY_EVENT_CHANNEL: Channel< CriticalSectionRawMutex, KeyEvent, EVENT_CHANNEL_SIZE, > = Channel::new(); -pub(crate) static keyboard_report_channel: Channel< + +pub(crate) const REPORT_CHANNEL_SIZE: usize = 32; +pub(crate) static KEYBOARD_REPORT_CHANNEL: Channel< CriticalSectionRawMutex, KeyboardReportMessage, REPORT_CHANNEL_SIZE, @@ -260,11 +261,11 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> } /// Main keyboard task, it receives input devices result, processes keys. - /// The report is sent to communication task via keyboard_report_channel, and finally sent to the host + /// The report is sent to communication task via `KEYBOARD_REPORT_CHANNEL`, and finally sent to the host pub(crate) async fn run(&mut self) { KEYBOARD_STATE.store(true, core::sync::atomic::Ordering::Release); loop { - let key_event = key_event_channel.receive().await; + let key_event = KEY_EVENT_CHANNEL.receive().await; // Process the key change self.process_key_change(key_event).await; @@ -528,7 +529,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> let hold_timeout = embassy_time::Timer::after_millis(self.behavior.tap_hold.hold_timeout.as_millis()); - match select(hold_timeout, key_event_channel.receive()).await { + match select(hold_timeout, KEY_EVENT_CHANNEL.receive()).await { embassy_futures::select::Either::First(_) => { // Timeout, trigger hold debug!("Hold timeout, got HOLD: {}, {}", hold_action, key_event); @@ -557,7 +558,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> // Wait for key release, record all pressed keys during this loop { - let next_key_event = key_event_channel.receive().await; + let next_key_event = KEY_EVENT_CHANNEL.receive().await; self.unprocessed_events.push(next_key_event).ok(); if !next_key_event.pressed { break; @@ -595,7 +596,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> ); let wait_release = async { loop { - let next_key_event = key_event_channel.receive().await; + let next_key_event = KEY_EVENT_CHANNEL.receive().await; if !next_key_event.pressed { self.unprocessed_events.push(next_key_event).ok(); } else { @@ -660,7 +661,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> self.osm_state = OneShotState::Single(m); let timeout = embassy_time::Timer::after(self.behavior.one_shot.timeout); - match select(timeout, key_event_channel.receive()).await { + match select(timeout, KEY_EVENT_CHANNEL.receive()).await { embassy_futures::select::Either::First(_) => { // Timeout, release modifier self.process_key_action_normal(Action::Modifier(modifier), key_event) @@ -711,7 +712,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> self.osl_state = OneShotState::Single(l); let timeout = embassy_time::Timer::after(self.behavior.one_shot.timeout); - match select(timeout, key_event_channel.receive()).await { + match select(timeout, KEY_EVENT_CHANNEL.receive()).await { embassy_futures::select::Either::First(_) => { // Timeout, deactivate layer self.keymap.borrow_mut().deactivate_layer(layer_num); @@ -924,7 +925,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> // So now we just block for 20ms for mouse keys. // In the future, we're going to use esp-hal once it have good support for BLE embassy_time::Timer::after_millis(20).await; - key_event_channel.try_send(key_event).ok(); + KEY_EVENT_CHANNEL.try_send(key_event).ok(); } } } diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index 946d0f97..cdf446f5 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -46,7 +46,7 @@ use embedded_storage::nor_flash::NorFlash; pub use flash::EmptyFlashWrapper; use futures::pin_mut; use keyboard::{ - communication_task, keyboard_report_channel, Keyboard, KeyboardReportMessage, + communication_task, Keyboard, KeyboardReportMessage, KEYBOARD_REPORT_CHANNEL, REPORT_CHANNEL_SIZE, }; use keymap::KeyMap; @@ -66,7 +66,7 @@ pub mod direct_pin; mod flash; mod hid; pub mod input_device; -mod keyboard; +pub mod keyboard; mod keyboard_macro; pub mod keycode; mod keymap; @@ -250,8 +250,8 @@ pub(crate) async fn initialize_usb_keyboard_and_run< #[cfg(all(not(feature = "_nrf_ble"), feature = "_no_external_storage"))] let keymap = RefCell::new(KeyMap::::new(default_keymap).await); - let keyboard_report_sender = keyboard_report_channel.sender(); - let keyboard_report_receiver = keyboard_report_channel.receiver(); + let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); + let keyboard_report_receiver = KEYBOARD_REPORT_CHANNEL.receiver(); // Create keyboard services and devices let (mut keyboard, mut usb_device, mut vial_service, mut light_service) = ( diff --git a/rmk/src/matrix.rs b/rmk/src/matrix.rs index fa08719a..bdf28c1b 100644 --- a/rmk/src/matrix.rs +++ b/rmk/src/matrix.rs @@ -1,6 +1,6 @@ use crate::{ debounce::{DebounceState, DebouncerTrait}, - keyboard::{key_event_channel, KeyEvent}, + keyboard::{KEY_EVENT_CHANNEL, KeyEvent}, CONNECTION_STATE, }; use defmt::{info, Format}; @@ -216,7 +216,7 @@ impl< let (row, col, key_state) = (out_idx, in_idx, self.key_states[out_idx][in_idx]); - key_event_channel + KEY_EVENT_CHANNEL .send(KeyEvent { row: row as u8, col: col as u8, diff --git a/rmk/src/split/central.rs b/rmk/src/split/central.rs index bea8718d..1dfe9dab 100644 --- a/rmk/src/split/central.rs +++ b/rmk/src/split/central.rs @@ -17,7 +17,7 @@ use crate::debounce::default_bouncer::DefaultDebouncer; #[cfg(feature = "rapid_debouncer")] use crate::debounce::fast_debouncer::RapidDebouncer; use crate::debounce::{DebounceState, DebouncerTrait}; -use crate::keyboard::{key_event_channel, keyboard_report_channel, KeyEvent, Keyboard}; +use crate::keyboard::{KEY_EVENT_CHANNEL, KEYBOARD_REPORT_CHANNEL, KeyEvent, Keyboard}; use crate::keymap::KeyMap; use crate::light::LightService; use crate::matrix::{KeyState, MatrixTrait}; @@ -269,8 +269,8 @@ pub(crate) async fn initialize_usb_split_central_and_run< #[cfg(all(not(feature = "_nrf_ble"), feature = "_no_external_storage"))] let keymap = RefCell::new(KeyMap::::new(default_keymap).await); - let keyboard_report_sender = keyboard_report_channel.sender(); - let keyboard_report_receiver = keyboard_report_channel.receiver(); + let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); + let keyboard_report_receiver = KEYBOARD_REPORT_CHANNEL.receiver(); // Create keyboard services and devices let (mut keyboard, mut usb_device, mut vial_service, mut light_service) = ( @@ -378,7 +378,7 @@ impl< self.key_states[out_idx][in_idx], ); - key_event_channel + KEY_EVENT_CHANNEL .send(KeyEvent { row, col, @@ -609,7 +609,7 @@ impl< self.key_states[row_idx][col_idx], ); - key_event_channel + KEY_EVENT_CHANNEL .send(KeyEvent { row, col, diff --git a/rmk/src/split/driver.rs b/rmk/src/split/driver.rs index 44a531cf..e3556c0f 100644 --- a/rmk/src/split/driver.rs +++ b/rmk/src/split/driver.rs @@ -3,7 +3,7 @@ use core::sync::atomic::Ordering; ///! The abstracted driver layer of the split keyboard. ///! use super::SplitMessage; -use crate::keyboard::{key_event_channel, KeyEvent}; +use crate::keyboard::{KEY_EVENT_CHANNEL, KeyEvent}; use crate::CONNECTION_STATE; use defmt::{debug, error, warn}; use embassy_futures::select::select; @@ -62,7 +62,7 @@ impl< /// Run the monitor. /// - /// The monitor receives from the peripheral and forward the message to key_event_channel. + /// The monitor receives from the peripheral and forward the message to `KEY_EVENT_CHANNEL`. pub(crate) async fn run(mut self) -> ! { let mut conn_state = CONNECTION_STATE.load(Ordering::Acquire); // Send once on start @@ -87,7 +87,7 @@ impl< if CONNECTION_STATE.load(core::sync::atomic::Ordering::Acquire) { // Only when the connection is established, send the key event. - key_event_channel + KEY_EVENT_CHANNEL .send(KeyEvent { row: e.row + ROW_OFFSET as u8, col: e.col + COL_OFFSET as u8, diff --git a/rmk/src/split/peripheral.rs b/rmk/src/split/peripheral.rs index 1a1efa00..619d971e 100644 --- a/rmk/src/split/peripheral.rs +++ b/rmk/src/split/peripheral.rs @@ -6,7 +6,7 @@ use crate::debounce::default_bouncer::DefaultDebouncer; use crate::debounce::fast_debouncer::RapidDebouncer; use crate::debounce::DebouncerTrait; use crate::direct_pin::DirectPinMatrix; -use crate::keyboard::key_event_channel; +use crate::keyboard::KEY_EVENT_CHANNEL; use crate::matrix::Matrix; use crate::CONNECTION_STATE; use defmt::{error, info}; @@ -145,7 +145,7 @@ impl SplitPeripheral { /// If also receives split messages from the central through `SplitReader`. pub(crate) async fn run(&mut self) -> ! { loop { - match select(self.split_driver.read(), key_event_channel.receive()).await { + match select(self.split_driver.read(), KEY_EVENT_CHANNEL.receive()).await { embassy_futures::select::Either::First(m) => match m { // Currently only handle the central state message Ok(split_message) => match split_message { From 5a91d3a7ff36bd751a174e25e89f1cc3fd4443a2 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Thu, 26 Dec 2024 20:40:11 +0800 Subject: [PATCH 07/21] feat(macro): add input device toml config Signed-off-by: Haobo Gu --- rmk-macro/src/config/mod.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/rmk-macro/src/config/mod.rs b/rmk-macro/src/config/mod.rs index 4be0dc62..861f642f 100644 --- a/rmk-macro/src/config/mod.rs +++ b/rmk-macro/src/config/mod.rs @@ -23,6 +23,8 @@ pub struct KeyboardTomlConfig { pub dependency: Option, /// Split config pub split: Option, + /// Input device config + pub input_device: Option, } /// Configurations for keyboard info @@ -185,7 +187,10 @@ pub struct SplitBoardConfig { pub ble_addr: Option<[u8; 6]>, /// Serial config, the vector length should be 1 for peripheral pub serial: Option>, + /// Matrix config for the split pub matrix: MatrixConfig, + /// Input device config for the split + pub input_device: InputDeviceConfig, } /// Serial port config @@ -220,3 +225,21 @@ fn parse_duration_millis<'de, D: de::Deserializer<'de>>(deserializer: D) -> Resu other => Err(de::Error::custom(format!("Invalid unit \"{other}\" in [one_shot.timeout]: unit part must be either \"s\" or \"ms\""))), } } + +/// Configurations for input devices +/// +#[derive(Clone, Debug, Default, Deserialize)] +pub struct InputDeviceConfig { + pub encoder: Option>, +} + +#[derive(Clone, Debug, Default, Deserialize)] +pub struct EncoderConfig { + pub pin_a: String, + pub pin_b: String, + pub pin_btn: Option, + pub resolution: Option, + pub clockwise_pos: (u8, u8), + pub counter_clockwise_pos: (u8, u8), + pub press_pos: Option<(u8, u8)>, +} From 4a3597ca44495a127d34f84f0766fe360d44003e Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Thu, 26 Dec 2024 21:42:51 +0800 Subject: [PATCH 08/21] feat(core): add mouse event Signed-off-by: Haobo Gu --- rmk/src/direct_pin.rs | 2 +- rmk/src/event.rs | 20 ++++++++++++++++++++ rmk/src/input_device/rotary_encoder.rs | 3 ++- rmk/src/keyboard.rs | 19 ++++--------------- rmk/src/keymap.rs | 2 +- rmk/src/lib.rs | 1 + rmk/src/matrix.rs | 4 +--- rmk/src/split/central.rs | 3 ++- rmk/src/split/driver.rs | 2 +- rmk/src/split/mod.rs | 2 +- 10 files changed, 34 insertions(+), 24 deletions(-) create mode 100644 rmk/src/event.rs diff --git a/rmk/src/direct_pin.rs b/rmk/src/direct_pin.rs index 3bd0df32..04423785 100644 --- a/rmk/src/direct_pin.rs +++ b/rmk/src/direct_pin.rs @@ -6,7 +6,7 @@ use crate::debounce::fast_debouncer::RapidDebouncer; use crate::debounce::DebounceState; use crate::debounce::DebouncerTrait; use crate::keyboard::KEY_EVENT_CHANNEL; -use crate::keyboard::KeyEvent; +use crate::event::KeyEvent; use crate::matrix::KeyState; use crate::MatrixTrait; use crate::RmkConfig; diff --git a/rmk/src/event.rs b/rmk/src/event.rs new file mode 100644 index 00000000..857602cc --- /dev/null +++ b/rmk/src/event.rs @@ -0,0 +1,20 @@ +use defmt::Format; +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Clone, Copy, Debug, Format, MaxSize)] +pub struct KeyEvent { + pub row: u8, + pub col: u8, + pub pressed: bool, +} + + +#[derive(Serialize, Deserialize, Clone, Copy, Debug, Format, MaxSize)] +pub struct MouseEvent { + pub buttons: u8, + pub x: i8, + pub y: i8, + pub wheel: i8, // Scroll down (negative) or up (positive) this many units + pub pan: i8, // Scroll left (negative) or right (positive) this many units +} diff --git a/rmk/src/input_device/rotary_encoder.rs b/rmk/src/input_device/rotary_encoder.rs index 89a2aa07..d5cd5490 100644 --- a/rmk/src/input_device/rotary_encoder.rs +++ b/rmk/src/input_device/rotary_encoder.rs @@ -5,7 +5,8 @@ use embedded_hal::digital::InputPin; #[cfg(feature = "async_matrix")] use embedded_hal_async::digital::Wait; -use crate::keyboard::{KeyEvent, KEY_EVENT_CHANNEL}; +use crate::event::KeyEvent; +use crate::keyboard::KEY_EVENT_CHANNEL; use super::InputDevice; diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index bd227da9..c50fa2a0 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -1,4 +1,5 @@ use crate::config::BehaviorConfig; +use crate::event::KeyEvent; use crate::CONNECTION_STATE; use crate::{ action::{Action, KeyAction}, @@ -10,7 +11,7 @@ use crate::{ KEYBOARD_STATE, }; use core::cell::RefCell; -use defmt::{debug, error, info, warn, Format}; +use defmt::{debug, error, info, warn}; use embassy_futures::{select::select, yield_now}; use embassy_sync::{ blocking_mutex::raw::CriticalSectionRawMutex, @@ -18,23 +19,11 @@ use embassy_sync::{ }; use embassy_time::{Instant, Timer}; use heapless::{FnvIndexMap, Vec}; -use postcard::experimental::max_size::MaxSize; -use serde::{Deserialize, Serialize}; use usbd_hid::descriptor::KeyboardReport; - -#[derive(Serialize, Deserialize, Clone, Copy, Debug, Format, MaxSize)] -pub struct KeyEvent { - pub row: u8, - pub col: u8, - pub pressed: bool, -} pub(crate) const EVENT_CHANNEL_SIZE: usize = 32; -pub static KEY_EVENT_CHANNEL: Channel< - CriticalSectionRawMutex, - KeyEvent, - EVENT_CHANNEL_SIZE, -> = Channel::new(); +pub static KEY_EVENT_CHANNEL: Channel = + Channel::new(); pub(crate) const REPORT_CHANNEL_SIZE: usize = 32; pub(crate) static KEYBOARD_REPORT_CHANNEL: Channel< diff --git a/rmk/src/keymap.rs b/rmk/src/keymap.rs index b4674eb8..c5bcf84c 100644 --- a/rmk/src/keymap.rs +++ b/rmk/src/keymap.rs @@ -1,6 +1,6 @@ use crate::{ action::KeyAction, - keyboard::KeyEvent, + event::KeyEvent, keyboard_macro::{MacroOperation, MACRO_SPACE_SIZE}, keycode::KeyCode, reboot_keyboard, diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index cdf446f5..2198c638 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -63,6 +63,7 @@ pub mod ble; pub mod config; mod debounce; pub mod direct_pin; +pub mod event; mod flash; mod hid; pub mod input_device; diff --git a/rmk/src/matrix.rs b/rmk/src/matrix.rs index bdf28c1b..0df62da7 100644 --- a/rmk/src/matrix.rs +++ b/rmk/src/matrix.rs @@ -1,7 +1,5 @@ use crate::{ - debounce::{DebounceState, DebouncerTrait}, - keyboard::{KEY_EVENT_CHANNEL, KeyEvent}, - CONNECTION_STATE, + debounce::{DebounceState, DebouncerTrait}, event::KeyEvent, keyboard::KEY_EVENT_CHANNEL, CONNECTION_STATE }; use defmt::{info, Format}; use embassy_time::{Instant, Timer}; diff --git a/rmk/src/split/central.rs b/rmk/src/split/central.rs index 1dfe9dab..17eb53f5 100644 --- a/rmk/src/split/central.rs +++ b/rmk/src/split/central.rs @@ -17,7 +17,8 @@ use crate::debounce::default_bouncer::DefaultDebouncer; #[cfg(feature = "rapid_debouncer")] use crate::debounce::fast_debouncer::RapidDebouncer; use crate::debounce::{DebounceState, DebouncerTrait}; -use crate::keyboard::{KEY_EVENT_CHANNEL, KEYBOARD_REPORT_CHANNEL, KeyEvent, Keyboard}; +use crate::event::KeyEvent; +use crate::keyboard::{Keyboard, KEYBOARD_REPORT_CHANNEL, KEY_EVENT_CHANNEL}; use crate::keymap::KeyMap; use crate::light::LightService; use crate::matrix::{KeyState, MatrixTrait}; diff --git a/rmk/src/split/driver.rs b/rmk/src/split/driver.rs index e3556c0f..a47652c8 100644 --- a/rmk/src/split/driver.rs +++ b/rmk/src/split/driver.rs @@ -3,7 +3,7 @@ use core::sync::atomic::Ordering; ///! The abstracted driver layer of the split keyboard. ///! use super::SplitMessage; -use crate::keyboard::{KEY_EVENT_CHANNEL, KeyEvent}; +use crate::{event::KeyEvent, keyboard::KEY_EVENT_CHANNEL}; use crate::CONNECTION_STATE; use defmt::{debug, error, warn}; use embassy_futures::select::select; diff --git a/rmk/src/split/mod.rs b/rmk/src/split/mod.rs index 0396807a..c758200f 100644 --- a/rmk/src/split/mod.rs +++ b/rmk/src/split/mod.rs @@ -1,7 +1,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::keyboard::KeyEvent; +use crate::event::KeyEvent; pub mod central; /// Common abstraction layer of split driver From ff8aa3a7a0e4940abce68b6e25b5f91dea16359e Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Fri, 27 Dec 2024 18:17:47 +0800 Subject: [PATCH 09/21] feat(input_device): add event definition Signed-off-by: Haobo Gu --- rmk/src/event.rs | 64 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/rmk/src/event.rs b/rmk/src/event.rs index 857602cc..9623b634 100644 --- a/rmk/src/event.rs +++ b/rmk/src/event.rs @@ -2,19 +2,63 @@ use defmt::Format; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; +/// Raw events from input devices and keyboards +/// +/// This should be as close to the raw output of the devices as possible. +/// The input processors receives it, processes it, +/// and then converts it to the final keyboard/mouse report. +#[non_exhaustive] +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum Event { + /// Keyboard event + Key(KeyEvent), + /// Multi-touch touchpad + Touchpad(TouchpadEvent), + /// Joystick, suppose we have x,y,z axes for this joystick + Joystick([AxisEvent; 3]), +} + +/// Event for multi-touch touchpad +#[derive(Serialize, Deserialize, Clone, Debug, Format, MaxSize)] +pub struct TouchpadEvent { + /// Finger slot + pub finger: u8, + /// X, Y, Z axes for touchpad + pub axis: [AxisEvent; 3], +} + +#[derive(Serialize, Deserialize, Clone, Debug, Copy, Format, MaxSize)] +pub struct AxisEvent { + /// The axis event value type, relative or absolute + pub typ: AxisValType, + /// The axis name + pub axis: Axis, + /// Value of the axis event + pub value: i8, +} + +#[derive(Serialize, Deserialize, Clone, Debug, Copy, Format, MaxSize)] +pub enum AxisValType { + /// The axis value is relative + Rel, + /// The axis value is absolute + Abs, +} + +#[derive(Serialize, Deserialize, Clone, Copy, Debug, Format, MaxSize)] +#[non_exhaustive] +pub enum Axis { + X, + Y, + Z, + H, + V, + // .. More is allowed +} + #[derive(Serialize, Deserialize, Clone, Copy, Debug, Format, MaxSize)] pub struct KeyEvent { pub row: u8, pub col: u8, pub pressed: bool, } - - -#[derive(Serialize, Deserialize, Clone, Copy, Debug, Format, MaxSize)] -pub struct MouseEvent { - pub buttons: u8, - pub x: i8, - pub y: i8, - pub wheel: i8, // Scroll down (negative) or up (positive) this many units - pub pan: i8, // Scroll left (negative) or right (positive) this many units -} From d3b1964311c21509904aad359fb8b85996ed9703 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Mon, 30 Dec 2024 15:26:15 +0800 Subject: [PATCH 10/21] feat(input_device): add `InputProcessor` trait Signed-off-by: Haobo Gu --- rmk/src/event.rs | 8 ++++++- rmk/src/input_device/mod.rs | 44 +++++++++++++++++++++++++++++++++++++ rmk/src/keyboard.rs | 5 ++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/rmk/src/event.rs b/rmk/src/event.rs index 9623b634..49828d4e 100644 --- a/rmk/src/event.rs +++ b/rmk/src/event.rs @@ -16,6 +16,12 @@ pub enum Event { Touchpad(TouchpadEvent), /// Joystick, suppose we have x,y,z axes for this joystick Joystick([AxisEvent; 3]), + /// An AxisEvent in a stream of events. The receiver should keep receiving events until it receives [`Eos`] event. + AxisEventStream(AxisEvent), + /// End of the event sequence + /// + /// This is used with [`AxisEventStream`] to indicate the end of the event sequence. + Eos, } /// Event for multi-touch touchpad @@ -34,7 +40,7 @@ pub struct AxisEvent { /// The axis name pub axis: Axis, /// Value of the axis event - pub value: i8, + pub value: i16, } #[derive(Serialize, Deserialize, Clone, Debug, Copy, Format, MaxSize)] diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs index 8d6ea4cc..42edfb39 100644 --- a/rmk/src/input_device/mod.rs +++ b/rmk/src/input_device/mod.rs @@ -7,6 +7,13 @@ use core::future::Future; +use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel}; + +use crate::{ + event::Event, + keyboard::{EVENT_CHANNEL, EVENT_CHANNEL_SIZE}, +}; + pub mod rotary_encoder; /// The trait for input devices. @@ -46,6 +53,43 @@ pub trait InputDevice { fn run(&mut self) -> impl Future; } +/// The trait for input processors. +/// +/// The input processor processes the [`Event`] from the input devices and converts it to the final HID report. +/// Take the normal keyboard as the example: +/// +/// The [`Matrix`] is actually an input device and the [`Keyboard`] is actually an input processor. +pub trait InputProcessor { + /// Process the incoming events, convert them to HID report [`KeyboardReportMessage`], + /// then send the report to the USB/BLE. + /// + /// Note there might be mulitple HID reports are generated for one event, + /// so the "sending report" operation should be done in the `process` method. + /// The input processor implementor should be aware of this. + fn process(&mut self, event: Event) -> impl Future; + + /// Get the input event channel for the input processor. + /// + /// The input processor receives events from this channel, processes the event, + /// then sends to the report channel. + fn get_event_channel(&self) -> &Channel { + &EVENT_CHANNEL + } + + /// Default implementation of the input processor. It wait for a new event from the event channel, + /// then process the event. + /// + /// The report is sent to the USB/BLE in the `process` method. + fn run(&mut self) -> impl Future { + async { + loop { + let event = self.get_event_channel().receive().await; + self.process(event).await; + } + } + } +} + /// Macro to run multiple input devices concurrently. /// /// The `run_devices` macro is specifically designed to work with the `InputDevice` trait. It takes one or more instances of diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index c50fa2a0..4b5b10e1 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -1,5 +1,5 @@ use crate::config::BehaviorConfig; -use crate::event::KeyEvent; +use crate::event::{Event, KeyEvent}; use crate::CONNECTION_STATE; use crate::{ action::{Action, KeyAction}, @@ -25,6 +25,9 @@ pub(crate) const EVENT_CHANNEL_SIZE: usize = 32; pub static KEY_EVENT_CHANNEL: Channel = Channel::new(); +pub static EVENT_CHANNEL: Channel = + Channel::new(); + pub(crate) const REPORT_CHANNEL_SIZE: usize = 32; pub(crate) static KEYBOARD_REPORT_CHANNEL: Channel< CriticalSectionRawMutex, From e622ea6040f5cefe614384f346adda20bcf9fb69 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Mon, 30 Dec 2024 16:22:08 +0800 Subject: [PATCH 11/21] feat(input_device): add rotary encoder event Signed-off-by: Haobo Gu --- README.md | 2 +- examples/use_rust/nrf52840_ble/src/main.rs | 2 +- rmk/src/event.rs | 13 ++++ rmk/src/input_device/rotary_encoder.rs | 83 +++++++--------------- 4 files changed, 40 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index bd38d9ef..19f2a9f0 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ - **Real-time keymap editing**: RMK has built-in [Vial](https://get.vial.today) support, the keymap can be changed on-the-fly. You can even use Vial to edit keymap over BLE directly - **Advanced keyboard features**: Many advanced keyboard features are available by default in RMK, such as layer switch, media control, system control, mouse control, etc - **Wireless**: BLE wireless support with auto-reconnection/multiple devices feature for nRF52 and esp32 microcontrollers, tested on nRF52840, esp32c3 and esp32s3 -- **Easy configuration**: RMK provides a simple way to build your keyboard: a `keyboard.toml` is all you need! For experienced Rust user, you can still customize your firmware easily using RMK +- **Easy configuration**: RMK provides a simple way to build your keyboard: a `keyboard.toml` is all you need! For experienced Rust user, you can still customize your firmware easily using Rust code - **Low latency and low-power ready**: RMK has a typical 2 ms latency in wired mode and 10 ms latency in wireless mode. By enabling `async_matrix` feature, RMK has very low power consumption, with a 2000mah battery, RMK can provide several months battery life ## [User Documentation](https://haobogu.github.io/rmk/user_guide/1_guide_overview.html) | [API Reference](https://docs.rs/rmk/latest/rmk/) | [FAQs](https://haobogu.github.io/rmk/faq.html) | [Changelog](https://github.com/HaoboGu/rmk/blob/main/rmk/CHANGELOG.md) diff --git a/examples/use_rust/nrf52840_ble/src/main.rs b/examples/use_rust/nrf52840_ble/src/main.rs index c8c459c2..92441ad9 100644 --- a/examples/use_rust/nrf52840_ble/src/main.rs +++ b/examples/use_rust/nrf52840_ble/src/main.rs @@ -110,7 +110,7 @@ async fn main(spawner: Spawner) { let mut my_device = MyDevice {}; let pin_a = Input::new(AnyPin::from(p.P0_06), embassy_nrf::gpio::Pull::Up); let pin_b = Input::new(AnyPin::from(p.P0_11), embassy_nrf::gpio::Pull::Up); - let mut encoder = RotaryEncoder::new(pin_a, pin_b, (0, 0), (0, 1)); + let mut encoder = RotaryEncoder::new(pin_a, pin_b, 0); embassy_futures::join::join( run_rmk( diff --git a/rmk/src/event.rs b/rmk/src/event.rs index 49828d4e..1dce54d5 100644 --- a/rmk/src/event.rs +++ b/rmk/src/event.rs @@ -2,6 +2,8 @@ use defmt::Format; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; +use crate::input_device::rotary_encoder::Direction; + /// Raw events from input devices and keyboards /// /// This should be as close to the raw output of the devices as possible. @@ -12,6 +14,8 @@ use serde::{Deserialize, Serialize}; pub enum Event { /// Keyboard event Key(KeyEvent), + /// Rotary encoder, ec11 compatible models + RotaryEncoder(RotaryEncoderEvent), /// Multi-touch touchpad Touchpad(TouchpadEvent), /// Joystick, suppose we have x,y,z axes for this joystick @@ -24,6 +28,15 @@ pub enum Event { Eos, } +/// Event for rotary encoder +#[derive(Serialize, Deserialize, Clone, Debug, Format, MaxSize)] +pub struct RotaryEncoderEvent { + /// The id of the rotary encoder + pub id: u8, + /// The direction of the rotary encoder + pub direction: Direction, +} + /// Event for multi-touch touchpad #[derive(Serialize, Deserialize, Clone, Debug, Format, MaxSize)] pub struct TouchpadEvent { diff --git a/rmk/src/input_device/rotary_encoder.rs b/rmk/src/input_device/rotary_encoder.rs index d5cd5490..8a59a5ef 100644 --- a/rmk/src/input_device/rotary_encoder.rs +++ b/rmk/src/input_device/rotary_encoder.rs @@ -1,12 +1,14 @@ -//! The rotary encoder implementation is from: https://github.com/leshow/rotary-encoder-hal/blob/master/src/lib.rs -//! +//! The rotary encoder implementation is adapted from: https://github.com/leshow/rotary-encoder-hal/blob/master/src/lib.rs +use defmt::Format; use embedded_hal::digital::InputPin; #[cfg(feature = "async_matrix")] use embedded_hal_async::digital::Wait; +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; -use crate::event::KeyEvent; -use crate::keyboard::KEY_EVENT_CHANNEL; +use crate::event::{Event, RotaryEncoderEvent}; +use crate::keyboard::EVENT_CHANNEL; use super::InputDevice; @@ -18,15 +20,12 @@ pub struct RotaryEncoder { pin_b: B, state: u8, phase: P, - /// (row, col) position in the keymap - clockwise_pos: (u8, u8), - /// (row, col) position in the keymap - counter_clockwise_pos: (u8, u8), + /// The index of the rotary encoder + id: u8, } /// The encoder direction is either `Clockwise`, `CounterClockwise`, or `None` -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -// #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Serialize, Deserialize, Clone, Debug, Format, MaxSize)] pub enum Direction { /// A clockwise turn Clockwise, @@ -65,43 +64,26 @@ where B: InputPin, { /// Accepts two [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html)s, these will be read on every `update()`. - /// - /// `clockwise_pos` and `counter_clockwise_pos` are the (row, col) positions in the keymap. - pub fn new( - pin_a: A, - pin_b: B, - clockwise_pos: (u8, u8), - counter_clockwise_pos: (u8, u8), - ) -> Self { + pub fn new(pin_a: A, pin_b: B, id: u8) -> Self { Self { pin_a, pin_b, state: 0u8, phase: DefaultPhase, - clockwise_pos, - counter_clockwise_pos, + id, } } } impl RotaryEncoder { /// Accepts two [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html)s, these will be read on every `update()`, while using `phase` to determine the direction. - /// - /// `clockwise_pos` and `counter_clockwise_pos` are the (row, col) positions in the keymap. - pub fn with_phase( - pin_a: A, - pin_b: B, - phase: P, - clockwise_pos: (u8, u8), - counter_clockwise_pos: (u8, u8), - ) -> Self { + pub fn with_phase(pin_a: A, pin_b: B, phase: P, id: u8) -> Self { Self { pin_a, pin_b, state: 0u8, phase, - clockwise_pos, - counter_clockwise_pos, + id, } } @@ -160,6 +142,10 @@ impl< { async fn run(&mut self) { loop { + // If not using async_matrix feature, scanning the encoder pins with 50HZ frequency + #[cfg(not(feature = "async_matrix"))] + embassy_time::Timer::after_millis(20).await; + #[cfg(feature = "async_matrix")] { let (pin_a, pin_b) = self.pins(); @@ -169,34 +155,15 @@ impl< ) .await; } - // If not using async_matrix feature, scanning the encoder pins with 50HZ frequency - #[cfg(not(feature = "async_matrix"))] - embassy_time::Timer::after_millis(20).await; + let direction = self.update(); - // TODO: Resolution - let (row, col) = match direction { - Direction::Clockwise => (self.clockwise_pos.0, self.clockwise_pos.1), - Direction::CounterClockwise => { - (self.counter_clockwise_pos.0, self.counter_clockwise_pos.1) - } - Direction::None => continue, - }; - - // Send the key event, process it like a tap - KEY_EVENT_CHANNEL - .send(KeyEvent { - row, - col, - pressed: true, - }) - .await; - embassy_time::Timer::after_millis(10).await; - KEY_EVENT_CHANNEL - .send(KeyEvent { - row, - col, - pressed: false, - }) + + // TODO: Channel customization + EVENT_CHANNEL + .send(Event::RotaryEncoder(RotaryEncoderEvent { + id: self.id, + direction, + })) .await; } } From 77920c3934adafef66f0bd9f56fbd5f64541a8a5 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Mon, 30 Dec 2024 19:53:33 +0800 Subject: [PATCH 12/21] feat(input_device): add event type to input device trait Signed-off-by: Haobo Gu --- rmk/src/input_device/mod.rs | 9 +++++++++ rmk/src/input_device/rotary_encoder.rs | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs index 42edfb39..8923b7c3 100644 --- a/rmk/src/input_device/mod.rs +++ b/rmk/src/input_device/mod.rs @@ -46,11 +46,20 @@ pub mod rotary_encoder; /// .await; /// ``` pub trait InputDevice { + /// Event type that input device will send + type EventType; + + /// The number of required channel size + const EVENT_CHANNEL_SIZE: usize = 32; + /// Starts the input device task. /// /// This asynchronous method should contain the main logic for the input device. /// It will be executed concurrently with other input devices using the `run_devices` macro. fn run(&mut self) -> impl Future; + + /// Get the event channel for the input device. All events should be send by this channel. + fn get_channel(&self) -> &Channel; } /// The trait for input processors. diff --git a/rmk/src/input_device/rotary_encoder.rs b/rmk/src/input_device/rotary_encoder.rs index 8a59a5ef..78f2b9f7 100644 --- a/rmk/src/input_device/rotary_encoder.rs +++ b/rmk/src/input_device/rotary_encoder.rs @@ -1,6 +1,8 @@ //! The rotary encoder implementation is adapted from: https://github.com/leshow/rotary-encoder-hal/blob/master/src/lib.rs use defmt::Format; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::channel::Channel; use embedded_hal::digital::InputPin; #[cfg(feature = "async_matrix")] use embedded_hal_async::digital::Wait; @@ -10,7 +12,7 @@ use serde::{Deserialize, Serialize}; use crate::event::{Event, RotaryEncoderEvent}; use crate::keyboard::EVENT_CHANNEL; -use super::InputDevice; +use super::{InputDevice, EVENT_CHANNEL_SIZE}; /// Holds current/old state and both [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html) #[derive(Clone, Debug)] @@ -140,6 +142,8 @@ impl< P: Phase, > InputDevice for RotaryEncoder { + type EventType = Event; + async fn run(&mut self) { loop { // If not using async_matrix feature, scanning the encoder pins with 50HZ frequency @@ -158,8 +162,7 @@ impl< let direction = self.update(); - // TODO: Channel customization - EVENT_CHANNEL + self.get_channel() .send(Event::RotaryEncoder(RotaryEncoderEvent { id: self.id, direction, @@ -167,4 +170,10 @@ impl< .await; } } + + fn get_channel( + &self, + ) -> &Channel { + &EVENT_CHANNEL + } } From 779ce2f6eedd81653c72eef0e1275bb19b97181a Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 31 Dec 2024 18:23:04 +0800 Subject: [PATCH 13/21] feat(input_device): add `EventType` to `InputProcessor` trait, add docs Signed-off-by: Haobo Gu --- docs/src/design_doc/input_device.md | 135 ++++++++++++++++++ docs/src/images/input_device_framework.drawio | 88 ++++++++++++ docs/src/images/input_device_framework.svg | 1 + rmk/src/input_device/mod.rs | 37 +++-- rmk/src/keyboard.rs | 2 +- rmk/src/usb/descriptor.rs | 4 +- 6 files changed, 254 insertions(+), 13 deletions(-) create mode 100644 docs/src/design_doc/input_device.md create mode 100644 docs/src/images/input_device_framework.drawio create mode 100644 docs/src/images/input_device_framework.svg diff --git a/docs/src/design_doc/input_device.md b/docs/src/design_doc/input_device.md new file mode 100644 index 00000000..c115472e --- /dev/null +++ b/docs/src/design_doc/input_device.md @@ -0,0 +1,135 @@ +# Input devices + +The definition of input devices varies, but for RMK, we focus on two categories: keys and sensors. + +- Keys are straightforward—they are essentially switches with two states. +- Sensors, on the other hand, are more complex. Devices such as joysticks, mice, trackpads, and trackballs are all sensors. They produce different data and speak different protocols. + +RMK’s input device framework is designed to provide a simple yet extensible way to handle both keys and sensors. Below is an overview of the framework: + +![input_device_framework](../images/input_device_framework.svg) + +Looks simple, great. In this documentation we'll only cover the left half of the pic, aka `InputDevice`s and `InputProcessors`. Actually, there're lots of detail/complexity underlying, for example: + +At first glance, the framework looks simple. However, as we delve into the implementation, intricacies emerge. In this documentation, we will focus on the left half of the diagram: `InputDevices` and `InputProcessors`. Key areas of complexity include: + +This design document outlines the current implementation, which aims to make RMK’s input device system clear, easy to use, and extensible. + +## Input device trait + +The input devices can be key matrix or sensors, which read the physical devices, send raw events to the input processors. All input devices in RMK should implement the `InputDevice` trait: + +```rust +pub trait InputDevice { + /// Event type that input device will send + type EventType; + + /// Starts the input device task. + /// + /// This asynchronous method should contain the main logic for the input device. + /// It will be executed concurrently with other input devices using the `run_devices` macro. + fn run(&mut self) -> impl Future; + + /// Get the event channel for the input device. All events should be send by this channel. + fn get_channel(&self) -> &Channel; +} +``` + +This trait should be used with the `run_devices!` macro: + +```rust +// Suppose that the d1 & d2 both implement `InputDevice`. `run()` will be called in `run_devices!` +run_devices!(d1, d2).await; +``` + +> Why `run_devices!`? +> +> Currently, embassy-rs does not support generic tasks. So the only option is to join all tasks(aka `run` function in `InputDevice`) together. That's what `run_devices!` does. + + +Another thing that need to be mentioned is that every input device defines its own `EventType`. RMK provides a default Event enum, which is compatible with built-in InputProcessors. This design balances convenience and flexibility: + +- For common devices, developers can use the built-in `Event` and `InputProcessor` implementations to when implementing new `InputDevice` +- For advanced use cases, developers can define custom events and processors to fully control the input logic. + +## Event + +The event is the output of input devices. It's defined as a non-exhaustive enum: + +```rust +#[non_exhaustive] +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum Event { + /// Keyboard event + Key(KeyEvent), + /// Rotary encoder, ec11 compatible models + RotaryEncoder(RotaryEncoderEvent), + /// Multi-touch touchpad + Touchpad(TouchpadEvent), + /// Joystick, suppose we have x,y,z axes for this joystick + Joystick([AxisEvent; 3]), + /// An AxisEvent in a stream of events. The receiver should keep receiving events until it receives [`Eos`] event. + AxisEventStream(AxisEvent), + /// End of the event sequence + /// + /// This is used with [`AxisEventStream`] to indicate the end of the event sequence. + Eos, +} +``` + +The `Event` aims to include raw outputs of all commonly used input devices, such as mice, trackpads, joysticks, etc. It also provides a stream-like axis event representation `AxisEventStream`, which can be used for a multiple-axis device where the number of axes is not known. Note that when using this, the `Eos` should be sent the indicate the end of the event sequence, otherwise the `InputProcessor` would wait for the next event forever. + +## Input processor trait + +The input processors receive the event from input devices, process them and convert results to HID reports for USB/BLE transmission. All input processors should implement the `InputProcessor` trait: + +```rust +pub trait InputProcessor { + /// Event type that the input processor receives. + type EventType; + + /// Process the incoming events, convert them to HID report [`KeyboardReportMessage`], + /// then send the report to the USB/BLE. + /// + /// Note there might be mulitple HID reports are generated for one event, + /// so the "sending report" operation should be done in the `process` method. + /// The input processor implementor should be aware of this. + fn process(&mut self, event: Self::EventType) -> impl Future; + + /// Get the input event channel for the input processor. + /// + /// The input processor receives events from this channel, processes the event, + /// then sends to the report channel. + fn get_event_channel( + &self, + ) -> &Channel; + + /// Get the output report channel for the input processor. + /// + /// The input processor sends keyboard reports to this channel. + fn get_report_channel( + &self, + ) -> &Channel { + &KEYBOARD_REPORT_CHANNEL + } + + /// Default implementation of the input processor. It wait for a new event from the event channel, + /// then process the event. + /// + /// The report is sent to the USB/BLE in the `process` method. + fn run(&mut self) -> impl Future { + async { + loop { + let event = self.get_event_channel().receive().await; + self.process(event).await; + } + } + } +} +``` + +The `process` method is responsible for processing input events and sending HID report to the report channel, which is available by `get_report_channel`. + +## TODO + +- Sometimes, we need different `InputProcessor`s for SAME `Event` from different `InputDevice`s. How to realize it? diff --git a/docs/src/images/input_device_framework.drawio b/docs/src/images/input_device_framework.drawio new file mode 100644 index 00000000..b476cebc --- /dev/null +++ b/docs/src/images/input_device_framework.drawio @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/src/images/input_device_framework.svg b/docs/src/images/input_device_framework.svg new file mode 100644 index 00000000..0d7613a3 --- /dev/null +++ b/docs/src/images/input_device_framework.svg @@ -0,0 +1 @@ +
key matrix
key matrix
encoders
encoders
mice
mice
trackpads
trackpads
Input devices
Input devices
key processor
key processor
encoder processor
encoder process...
mice processor
mice processor
axis processor
axis processor
Input processor
Input processor
Event
Event
USB
USB
BLE
BLE
Reporter
Reporter
host
host
Report
Report
Text is not SVG - cannot display
\ No newline at end of file diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs index 8923b7c3..49350459 100644 --- a/rmk/src/input_device/mod.rs +++ b/rmk/src/input_device/mod.rs @@ -9,9 +9,8 @@ use core::future::Future; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel}; -use crate::{ - event::Event, - keyboard::{EVENT_CHANNEL, EVENT_CHANNEL_SIZE}, +use crate::keyboard::{ + KeyboardReportMessage, EVENT_CHANNEL_SIZE, KEYBOARD_REPORT_CHANNEL, REPORT_CHANNEL_SIZE, }; pub mod rotary_encoder; @@ -46,11 +45,17 @@ pub mod rotary_encoder; /// .await; /// ``` pub trait InputDevice { - /// Event type that input device will send + /// Event type that input device will send type EventType; /// The number of required channel size - const EVENT_CHANNEL_SIZE: usize = 32; + // FIXME: it's not possible in stable to define an associated const and use it as the channel size: + // `fn get_channel(..) -> &Channel;` + // + // It requires #[feature(generic_const_exprs)] and adding `{}` to the const: + // `fn get_channel(..) -> &Channel;` + // + // const EVENT_CHANNEL_SIZE: usize = 32; /// Starts the input device task. /// @@ -59,7 +64,8 @@ pub trait InputDevice { fn run(&mut self) -> impl Future; /// Get the event channel for the input device. All events should be send by this channel. - fn get_channel(&self) -> &Channel; + fn get_channel(&self) + -> &Channel; } /// The trait for input processors. @@ -69,25 +75,36 @@ pub trait InputDevice { /// /// The [`Matrix`] is actually an input device and the [`Keyboard`] is actually an input processor. pub trait InputProcessor { + type EventType; + /// Process the incoming events, convert them to HID report [`KeyboardReportMessage`], /// then send the report to the USB/BLE. /// /// Note there might be mulitple HID reports are generated for one event, /// so the "sending report" operation should be done in the `process` method. /// The input processor implementor should be aware of this. - fn process(&mut self, event: Event) -> impl Future; + fn process(&mut self, event: Self::EventType) -> impl Future; /// Get the input event channel for the input processor. /// /// The input processor receives events from this channel, processes the event, /// then sends to the report channel. - fn get_event_channel(&self) -> &Channel { - &EVENT_CHANNEL + fn get_event_channel( + &self, + ) -> &Channel; + + /// Get the output report channel for the input processor. + /// + /// The input processor sends keyboard reports to this channel. + fn get_report_channel( + &self, + ) -> &Channel { + &KEYBOARD_REPORT_CHANNEL } /// Default implementation of the input processor. It wait for a new event from the event channel, /// then process the event. - /// + /// /// The report is sent to the USB/BLE in the `process` method. fn run(&mut self) -> impl Future { async { diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index 4b5b10e1..3ae93c03 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -60,7 +60,7 @@ impl OneShotState { } /// Matrix scanning task sends this [KeyboardReportMessage] to communication task. -pub(crate) enum KeyboardReportMessage { +pub enum KeyboardReportMessage { /// Normal keyboard hid report KeyboardReport(KeyboardReport), /// Other types of keyboard reports: mouse + media(consumer) + system control diff --git a/rmk/src/usb/descriptor.rs b/rmk/src/usb/descriptor.rs index 98eb6f70..79592bc5 100644 --- a/rmk/src/usb/descriptor.rs +++ b/rmk/src/usb/descriptor.rs @@ -51,7 +51,7 @@ pub(crate) struct ViaReport { #[repr(u8)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub(crate) enum CompositeReportType { +pub enum CompositeReportType { None = 0x00, Mouse = 0x01, Media = 0x02, @@ -113,7 +113,7 @@ impl CompositeReportType { } )] #[derive(Default)] -pub(crate) struct CompositeReport { +pub struct CompositeReport { pub(crate) buttons: u8, pub(crate) x: i8, pub(crate) y: i8, From a6bc24fb6b1feeac80eb7bd3638fc44ee8f2b167 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 31 Dec 2024 22:33:49 +0800 Subject: [PATCH 14/21] doc: improve doc Signed-off-by: Haobo Gu --- docs/src/design_doc/input_device.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/src/design_doc/input_device.md b/docs/src/design_doc/input_device.md index c115472e..1d09d1c4 100644 --- a/docs/src/design_doc/input_device.md +++ b/docs/src/design_doc/input_device.md @@ -9,8 +9,6 @@ RMK’s input device framework is designed to provide a simple yet extensible wa ![input_device_framework](../images/input_device_framework.svg) -Looks simple, great. In this documentation we'll only cover the left half of the pic, aka `InputDevice`s and `InputProcessors`. Actually, there're lots of detail/complexity underlying, for example: - At first glance, the framework looks simple. However, as we delve into the implementation, intricacies emerge. In this documentation, we will focus on the left half of the diagram: `InputDevices` and `InputProcessors`. Key areas of complexity include: This design document outlines the current implementation, which aims to make RMK’s input device system clear, easy to use, and extensible. From 50ad5fa156d9a95c35c4905ae91af91c6ce7332f Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Thu, 2 Jan 2025 11:07:54 +0800 Subject: [PATCH 15/21] feat: expose channels Signed-off-by: Haobo Gu --- examples/use_rust/nrf52840_ble/src/main.rs | 11 ++++++++++- rmk/src/input_device/mod.rs | 12 ++++++------ rmk/src/keyboard.rs | 4 ++-- rmk/src/lib.rs | 11 ++++++----- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/examples/use_rust/nrf52840_ble/src/main.rs b/examples/use_rust/nrf52840_ble/src/main.rs index 92441ad9..a043f55c 100644 --- a/examples/use_rust/nrf52840_ble/src/main.rs +++ b/examples/use_rust/nrf52840_ble/src/main.rs @@ -21,8 +21,9 @@ use panic_probe as _; use rmk::{ ble::SOFTWARE_VBUS, config::{BleBatteryConfig, KeyboardUsbConfig, RmkConfig, StorageConfig, VialConfig}, + event::Event, input_device::{rotary_encoder::RotaryEncoder, InputDevice}, - run_devices, run_rmk, + run_devices, run_rmk, Channel, CriticalSectionRawMutex, EVENT_CHANNEL, EVENT_CHANNEL_SIZE, }; use vial::{VIAL_KEYBOARD_DEF, VIAL_KEYBOARD_ID}; @@ -134,4 +135,12 @@ impl InputDevice for MyDevice { embassy_time::Timer::after_secs(1).await; } } + + type EventType = Event; + + fn get_channel( + &self, + ) -> &Channel { + &EVENT_CHANNEL + } } diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs index 49350459..0cf68f4a 100644 --- a/rmk/src/input_device/mod.rs +++ b/rmk/src/input_device/mod.rs @@ -9,9 +9,7 @@ use core::future::Future; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel}; -use crate::keyboard::{ - KeyboardReportMessage, EVENT_CHANNEL_SIZE, KEYBOARD_REPORT_CHANNEL, REPORT_CHANNEL_SIZE, -}; +use crate::keyboard::{EVENT_CHANNEL_SIZE, REPORT_CHANNEL_SIZE}; pub mod rotary_encoder; @@ -75,8 +73,12 @@ pub trait InputDevice { /// /// The [`Matrix`] is actually an input device and the [`Keyboard`] is actually an input processor. pub trait InputProcessor { + /// The event type that the input processor receives. type EventType; + /// The report type that the input processor sends. + type ReportType; + /// Process the incoming events, convert them to HID report [`KeyboardReportMessage`], /// then send the report to the USB/BLE. /// @@ -98,9 +100,7 @@ pub trait InputProcessor { /// The input processor sends keyboard reports to this channel. fn get_report_channel( &self, - ) -> &Channel { - &KEYBOARD_REPORT_CHANNEL - } + ) -> &Channel; /// Default implementation of the input processor. It wait for a new event from the event channel, /// then process the event. diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index 3ae93c03..1cf61e34 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -21,14 +21,14 @@ use embassy_time::{Instant, Timer}; use heapless::{FnvIndexMap, Vec}; use usbd_hid::descriptor::KeyboardReport; -pub(crate) const EVENT_CHANNEL_SIZE: usize = 32; +pub const EVENT_CHANNEL_SIZE: usize = 32; pub static KEY_EVENT_CHANNEL: Channel = Channel::new(); pub static EVENT_CHANNEL: Channel = Channel::new(); -pub(crate) const REPORT_CHANNEL_SIZE: usize = 32; +pub const REPORT_CHANNEL_SIZE: usize = 32; pub(crate) static KEYBOARD_REPORT_CHANNEL: Channel< CriticalSectionRawMutex, KeyboardReportMessage, diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index 2198c638..ed4e41e4 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -34,7 +34,10 @@ use defmt::{error, warn}; #[cfg(not(feature = "_esp_ble"))] use embassy_executor::Spawner; use embassy_futures::select::{select, select4, Either4}; -use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Receiver}; +pub use embassy_sync::{ + blocking_mutex::raw::CriticalSectionRawMutex, + channel::{Channel, Receiver}, +}; use embassy_time::Timer; use embassy_usb::driver::Driver; pub use embedded_hal; @@ -45,10 +48,8 @@ use embedded_hal_async::digital::Wait; use embedded_storage::nor_flash::NorFlash; pub use flash::EmptyFlashWrapper; use futures::pin_mut; -use keyboard::{ - communication_task, Keyboard, KeyboardReportMessage, KEYBOARD_REPORT_CHANNEL, - REPORT_CHANNEL_SIZE, -}; +use keyboard::{communication_task, Keyboard, KeyboardReportMessage, KEYBOARD_REPORT_CHANNEL}; +pub use keyboard::{EVENT_CHANNEL_SIZE, REPORT_CHANNEL_SIZE, EVENT_CHANNEL}; use keymap::KeyMap; use matrix::{Matrix, MatrixTrait}; pub use rmk_macro as macros; From 54bf7c17c089e076c4424dc0e861711ba99c6372 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Thu, 2 Jan 2025 11:15:41 +0800 Subject: [PATCH 16/21] feat(macro): add input device definition in toml Signed-off-by: Haobo Gu --- rmk-macro/src/config/mod.rs | 52 ++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/rmk-macro/src/config/mod.rs b/rmk-macro/src/config/mod.rs index 8dfbdbe1..e4b9ea86 100644 --- a/rmk-macro/src/config/mod.rs +++ b/rmk-macro/src/config/mod.rs @@ -58,7 +58,6 @@ pub enum MatrixType { direct_pin, } -#[allow(unused)] #[derive(Clone, Debug, Default, Deserialize)] pub struct MatrixConfig { #[serde(default)] @@ -176,6 +175,7 @@ pub struct SplitConfig { /// Configurations for each split board /// /// Either ble_addr or serial must be set, but not both. +#[allow(unused)] #[derive(Clone, Debug, Default, Deserialize)] pub struct SplitBoardConfig { /// Row number of the split board @@ -193,7 +193,7 @@ pub struct SplitBoardConfig { /// Matrix config for the split pub matrix: MatrixConfig, /// Input device config for the split - pub input_device: InputDeviceConfig, + pub input_device: Option, } /// Serial port config @@ -238,17 +238,61 @@ fn parse_duration_millis<'de, D: de::Deserializer<'de>>(deserializer: D) -> Resu /// Configurations for input devices /// #[derive(Clone, Debug, Default, Deserialize)] +#[allow(unused)] pub struct InputDeviceConfig { pub encoder: Option>, + pub pointing: Option>, } #[derive(Clone, Debug, Default, Deserialize)] +#[allow(unused)] pub struct EncoderConfig { + // Pin a of the encoder pub pin_a: String, + // Pin b of the encoder pub pin_b: String, - pub pin_btn: Option, + // Press button position in the keyboard matrix + // TODO: direct pin support? + pub btn_pos: Option<(u8, u8)>, + // Resolution pub resolution: Option, pub clockwise_pos: (u8, u8), pub counter_clockwise_pos: (u8, u8), - pub press_pos: Option<(u8, u8)>, } + + +/// Pointing device config +#[derive(Clone, Debug, Default, Deserialize)] +#[allow(unused)] +pub struct PointingDeviceConfig { + pub interface: Option, +} + +#[derive(Clone, Debug, Deserialize)] +#[allow(unused)] +pub enum CommunicationProtocol { + I2C(I2cConfig), + SPI(SpiConfig), +} + +/// SPI config +#[derive(Clone, Debug, Default, Deserialize)] +#[allow(unused)] +pub struct SpiConfig { + pub instance: String, + pub sck: String, + pub mosi: String, + pub miso: String, + pub cs: Option, + pub cpi: Option, +} + +/// I2C config +#[derive(Clone, Debug, Default, Deserialize)] +#[allow(unused)] +pub struct I2cConfig { + pub instance: String, + pub sda: String, + pub scl: String, + pub address: u8, +} \ No newline at end of file From 0734ae0924f3fe5209e54b0ead57137817b132cf Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Fri, 3 Jan 2025 11:47:14 +0800 Subject: [PATCH 17/21] feat(input_device): update input device traits, add encoder map to API Signed-off-by: Haobo Gu --- docs/src/design_doc/input_device.md | 4 -- examples/use_rust/nrf52840_ble/src/keymap.rs | 38 ++++++++++++ examples/use_rust/nrf52840_ble/src/main.rs | 9 ++- examples/use_rust/nrf52840_ble/vial.json | 9 ++- rmk-macro/src/config/mod.rs | 6 +- rmk-macro/src/layout.rs | 7 +-- rmk/src/ble/nrf/mod.rs | 5 +- rmk/src/direct_pin.rs | 10 +++- rmk/src/input_device/mod.rs | 49 +++++++++++++--- rmk/src/input_device/rotary_encoder.rs | 48 ++++++++++++--- rmk/src/keyboard.rs | 1 + rmk/src/keymap.rs | 11 +++- rmk/src/lib.rs | 16 +++-- rmk/src/matrix.rs | 5 +- rmk/src/split/central.rs | 6 ++ rmk/src/split/driver.rs | 2 +- rmk/src/via/process.rs | 10 +++- rmk/src/via/vial.rs | 61 ++++++++++++++++++-- 18 files changed, 244 insertions(+), 53 deletions(-) diff --git a/docs/src/design_doc/input_device.md b/docs/src/design_doc/input_device.md index 1d09d1c4..e32068cb 100644 --- a/docs/src/design_doc/input_device.md +++ b/docs/src/design_doc/input_device.md @@ -127,7 +127,3 @@ pub trait InputProcessor { ``` The `process` method is responsible for processing input events and sending HID report to the report channel, which is available by `get_report_channel`. - -## TODO - -- Sometimes, we need different `InputProcessor`s for SAME `Event` from different `InputDevice`s. How to realize it? diff --git a/examples/use_rust/nrf52840_ble/src/keymap.rs b/examples/use_rust/nrf52840_ble/src/keymap.rs index 7ff0151d..917baacf 100644 --- a/examples/use_rust/nrf52840_ble/src/keymap.rs +++ b/examples/use_rust/nrf52840_ble/src/keymap.rs @@ -3,6 +3,7 @@ use rmk::{a, k, layer, mo}; pub(crate) const COL: usize = 14; pub(crate) const ROW: usize = 5; pub(crate) const NUM_LAYER: usize = 8; +pub(crate) const NUM_ENCODER: usize = 2; #[rustfmt::skip] pub fn get_default_keymap() -> [[[KeyAction; COL]; ROW]; NUM_LAYER] { @@ -65,3 +66,40 @@ pub fn get_default_keymap() -> [[[KeyAction; COL]; ROW]; NUM_LAYER] { ]), ] } + +pub fn get_default_encoder_map() -> [[(KeyAction, KeyAction); NUM_ENCODER]; NUM_LAYER] { + [ + [ + (k!(KbVolumeUp), k!(KbVolumeDown)), + (k!(KbVolumeUp), k!(KbVolumeDown)), + ], + [ + (k!(KbVolumeUp), k!(KbVolumeDown)), + (k!(KbVolumeUp), k!(KbVolumeDown)), + ], + [ + (k!(KbVolumeUp), k!(KbVolumeDown)), + (k!(KbVolumeUp), k!(KbVolumeDown)), + ], + [ + (k!(KbVolumeUp), k!(KbVolumeDown)), + (k!(KbVolumeUp), k!(KbVolumeDown)), + ], + [ + (k!(KbVolumeUp), k!(KbVolumeDown)), + (k!(KbVolumeUp), k!(KbVolumeDown)), + ], + [ + (k!(KbVolumeUp), k!(KbVolumeDown)), + (k!(KbVolumeUp), k!(KbVolumeDown)), + ], + [ + (k!(KbVolumeUp), k!(KbVolumeDown)), + (k!(KbVolumeUp), k!(KbVolumeDown)), + ], + [ + (k!(KbVolumeUp), k!(KbVolumeDown)), + (k!(KbVolumeUp), k!(KbVolumeDown)), + ], + ] +} diff --git a/examples/use_rust/nrf52840_ble/src/main.rs b/examples/use_rust/nrf52840_ble/src/main.rs index a043f55c..16c0efc1 100644 --- a/examples/use_rust/nrf52840_ble/src/main.rs +++ b/examples/use_rust/nrf52840_ble/src/main.rs @@ -23,7 +23,7 @@ use rmk::{ config::{BleBatteryConfig, KeyboardUsbConfig, RmkConfig, StorageConfig, VialConfig}, event::Event, input_device::{rotary_encoder::RotaryEncoder, InputDevice}, - run_devices, run_rmk, Channel, CriticalSectionRawMutex, EVENT_CHANNEL, EVENT_CHANNEL_SIZE, + run_devices, run_rmk, CriticalSectionRawMutex, Sender, EVENT_CHANNEL, EVENT_CHANNEL_SIZE, }; use vial::{VIAL_KEYBOARD_DEF, VIAL_KEYBOARD_ID}; @@ -119,6 +119,7 @@ async fn main(spawner: Spawner) { output_pins, driver, &mut keymap::get_default_keymap(), + Some(&mut keymap::get_default_encoder_map()), keyboard_config, spawner, ), @@ -138,9 +139,7 @@ impl InputDevice for MyDevice { type EventType = Event; - fn get_channel( - &self, - ) -> &Channel { - &EVENT_CHANNEL + fn get_channel(&self) -> Sender { + EVENT_CHANNEL.sender() } } diff --git a/examples/use_rust/nrf52840_ble/vial.json b/examples/use_rust/nrf52840_ble/vial.json index 13f994ab..e1e82c61 100644 --- a/examples/use_rust/nrf52840_ble/vial.json +++ b/examples/use_rust/nrf52840_ble/vial.json @@ -88,7 +88,10 @@ { "w": 2 }, - "0,13" + "0,13", + {"x":0.25}, + "0,0\n\n\n\n\n\n\n\n\ne", + "0,1\n\n\n\n\n\n\n\n\ne" ], [ { @@ -131,7 +134,9 @@ { "w": 2.25 }, - "2,13" + "2,13", + {"x":0.75}, + "2,12" ], [ { diff --git a/rmk-macro/src/config/mod.rs b/rmk-macro/src/config/mod.rs index e4b9ea86..bbfb8f6e 100644 --- a/rmk-macro/src/config/mod.rs +++ b/rmk-macro/src/config/mod.rs @@ -3,6 +3,7 @@ use serde_derive::Deserialize; /// Configurations for RMK keyboard. #[derive(Clone, Debug, Deserialize)] +#[allow(unused)] pub struct KeyboardTomlConfig { /// Basic keyboard info pub keyboard: KeyboardInfo, @@ -251,7 +252,7 @@ pub struct EncoderConfig { pub pin_a: String, // Pin b of the encoder pub pin_b: String, - // Press button position in the keyboard matrix + // Press button position in the keyboard matrix // TODO: direct pin support? pub btn_pos: Option<(u8, u8)>, // Resolution @@ -260,7 +261,6 @@ pub struct EncoderConfig { pub counter_clockwise_pos: (u8, u8), } - /// Pointing device config #[derive(Clone, Debug, Default, Deserialize)] #[allow(unused)] @@ -295,4 +295,4 @@ pub struct I2cConfig { pub sda: String, pub scl: String, pub address: u8, -} \ No newline at end of file +} diff --git a/rmk-macro/src/layout.rs b/rmk-macro/src/layout.rs index 68c157e5..37d7936c 100644 --- a/rmk-macro/src/layout.rs +++ b/rmk-macro/src/layout.rs @@ -62,10 +62,10 @@ impl ModifierCombinationMacro { impl quote::ToTokens for ModifierCombinationMacro { fn to_tokens(&self, tokens: &mut TokenStream2) { let right = self.right; - let gui = self.gui; - let alt = self.alt; + let gui = self.gui; + let alt = self.alt; let shift = self.shift; - let ctrl = self.ctrl; + let ctrl = self.ctrl; tokens.extend(quote! { ::rmk::keycode::ModifierCombination::new_from(#right, #gui, #alt, #shift, #ctrl) @@ -303,7 +303,6 @@ fn parse_key(key: String) -> TokenStream2 { compile_error!("keyboard.toml: TH(key_tap, key_hold) invalid, please check the documentation: https://haobogu.github.io/rmk/keyboard_configuration.html"); }; } - } _ => { let ident = format_ident!("{}", key); diff --git a/rmk/src/ble/nrf/mod.rs b/rmk/src/ble/nrf/mod.rs index 4fce1dbf..330f35bd 100644 --- a/rmk/src/ble/nrf/mod.rs +++ b/rmk/src/ble/nrf/mod.rs @@ -226,6 +226,7 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< mut matrix: M, #[cfg(not(feature = "_no_usb"))] usb_driver: D, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, mut keyboard_config: RmkConfig<'static, Out>, ble_addr: Option<[u8; 6]>, spawner: Spawner, @@ -250,7 +251,9 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< // Flash and keymap configuration let flash = Flash::take(sd); let mut storage = Storage::new(flash, default_keymap, keyboard_config.storage_config).await; - let keymap = RefCell::new(KeyMap::new_from_storage(default_keymap, Some(&mut storage)).await); + let keymap = RefCell::new( + KeyMap::new_from_storage(default_keymap, encoder_map, Some(&mut storage)).await, + ); let mut buf: [u8; 128] = [0; 128]; diff --git a/rmk/src/direct_pin.rs b/rmk/src/direct_pin.rs index 04423785..5422a02f 100644 --- a/rmk/src/direct_pin.rs +++ b/rmk/src/direct_pin.rs @@ -5,8 +5,8 @@ use crate::debounce::default_bouncer::DefaultDebouncer; use crate::debounce::fast_debouncer::RapidDebouncer; use crate::debounce::DebounceState; use crate::debounce::DebouncerTrait; -use crate::keyboard::KEY_EVENT_CHANNEL; use crate::event::KeyEvent; +use crate::keyboard::KEY_EVENT_CHANNEL; use crate::matrix::KeyState; use crate::MatrixTrait; use crate::RmkConfig; @@ -66,6 +66,7 @@ pub async fn run_rmk_direct_pin< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, low_active: bool, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, @@ -79,6 +80,7 @@ pub async fn run_rmk_direct_pin< run_rmk_direct_pin_with_async_flash::<_, _, ROW, COL, SIZE, NUM_LAYER>( direct_pins, default_keymap, + encoder_map, keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -93,6 +95,7 @@ pub async fn run_rmk_direct_pin< direct_pins, usb_driver, default_keymap, + encoder_map, keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -107,6 +110,7 @@ pub async fn run_rmk_direct_pin< direct_pins, async_flash, default_keymap, + encoder_map, keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -122,6 +126,7 @@ pub async fn run_rmk_direct_pin< usb_driver, async_flash, default_keymap, + encoder_map, keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -159,6 +164,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, low_active: bool, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, @@ -179,6 +185,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver, default_keymap, + encoder_map, keyboard_config, None, spawner, @@ -198,6 +205,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< #[cfg(not(feature = "_no_external_storage"))] flash, default_keymap, + encoder_map, keyboard_config, ) .await; diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs index 0cf68f4a..0bd35cba 100644 --- a/rmk/src/input_device/mod.rs +++ b/rmk/src/input_device/mod.rs @@ -7,7 +7,10 @@ use core::future::Future; -use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel}; +use embassy_sync::{ + blocking_mutex::raw::CriticalSectionRawMutex, + channel::{Receiver, Sender}, +}; use crate::keyboard::{EVENT_CHANNEL_SIZE, REPORT_CHANNEL_SIZE}; @@ -47,12 +50,11 @@ pub trait InputDevice { type EventType; /// The number of required channel size - // FIXME: it's not possible in stable to define an associated const and use it as the channel size: - // `fn get_channel(..) -> &Channel;` + // FIXME: it's not possible in stable to define an associated const and use it as the channel size in stable Rust. + // It requires #[feature(generic_const_exprs)]: // - // It requires #[feature(generic_const_exprs)] and adding `{}` to the const: // `fn get_channel(..) -> &Channel;` - // + // So this size is commented out // const EVENT_CHANNEL_SIZE: usize = 32; /// Starts the input device task. @@ -62,8 +64,7 @@ pub trait InputDevice { fn run(&mut self) -> impl Future; /// Get the event channel for the input device. All events should be send by this channel. - fn get_channel(&self) - -> &Channel; + fn get_channel(&self) -> Sender; } /// The trait for input processors. @@ -93,14 +94,14 @@ pub trait InputProcessor { /// then sends to the report channel. fn get_event_channel( &self, - ) -> &Channel; + ) -> Receiver; /// Get the output report channel for the input processor. /// /// The input processor sends keyboard reports to this channel. fn get_report_channel( &self, - ) -> &Channel; + ) -> Sender; /// Default implementation of the input processor. It wait for a new event from the event channel, /// then process the event. @@ -145,3 +146,33 @@ macro_rules! run_devices { ::embassy_futures::join::join($first.run(), run_devices!($second $(, $rest)*)) }; } + +/// Macro to run multiple input processors concurrently. +/// +/// The `run_processors` macro is specifically designed to work with the `InputProcessor` trait. It takes one or more instances of +/// input processors and combines their `run` methods into a single future. All futures are executed concurrently, enabling +/// efficient multitasking for multiple input processors. +/// +/// # Note +/// This macro must be used with input processors that implement the `InputProcessor` trait. +/// +/// # Example +/// ```rust +/// // `RotaryEncoderProcessor` and `TouchpadProcessor` should implement `InputProcessor` trait +/// let d1 = RotaryEncoderProcessor{}; +/// let d2 = TouchpadProcessor{}; +/// +/// // Run all input devices concurrently +/// run_processors!(d1, d2).await; +/// ``` +#[macro_export] +macro_rules! run_processors { + // Single device case + ($single:expr) => { + $single.run() + }; + // Multiple devices case + ($first:expr, $second:expr $(, $rest:expr)*) => { + ::embassy_futures::join::join($first.run(), run_processors!($second $(, $rest)*)) + }; +} diff --git a/rmk/src/input_device/rotary_encoder.rs b/rmk/src/input_device/rotary_encoder.rs index 78f2b9f7..7953d45c 100644 --- a/rmk/src/input_device/rotary_encoder.rs +++ b/rmk/src/input_device/rotary_encoder.rs @@ -1,8 +1,8 @@ //! The rotary encoder implementation is adapted from: https://github.com/leshow/rotary-encoder-hal/blob/master/src/lib.rs -use defmt::Format; +use defmt::{debug, Format}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::channel::Channel; +use embassy_sync::channel::{Receiver, Sender}; use embedded_hal::digital::InputPin; #[cfg(feature = "async_matrix")] use embedded_hal_async::digital::Wait; @@ -10,9 +10,10 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; use crate::event::{Event, RotaryEncoderEvent}; -use crate::keyboard::EVENT_CHANNEL; +use crate::keyboard::{KeyboardReportMessage, EVENT_CHANNEL, KEYBOARD_REPORT_CHANNEL}; +use crate::REPORT_CHANNEL_SIZE; -use super::{InputDevice, EVENT_CHANNEL_SIZE}; +use super::{InputDevice, InputProcessor, EVENT_CHANNEL_SIZE}; /// Holds current/old state and both [`InputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.InputPin.html) #[derive(Clone, Debug)] @@ -171,9 +172,42 @@ impl< } } - fn get_channel( + fn get_channel(&self) -> Sender { + EVENT_CHANNEL.sender() + } +} + +pub struct RotaryEncoderProcessor {} + +impl InputProcessor for RotaryEncoderProcessor { + type EventType = Event; + + type ReportType = KeyboardReportMessage; + + async fn process(&mut self, event: Self::EventType) { + match event { + Event::RotaryEncoder(RotaryEncoderEvent { id, direction }) => match direction { + Direction::Clockwise => { + debug!("Encoder {} - Clockwise", id); + } + Direction::CounterClockwise => { + debug!("Encoder {} - CounterClockwise", id); + } + Direction::None => (), + }, + _ => {} + } + } + + fn get_event_channel( + &self, + ) -> Receiver { + EVENT_CHANNEL.receiver() + } + + fn get_report_channel( &self, - ) -> &Channel { - &EVENT_CHANNEL + ) -> Sender { + KEYBOARD_REPORT_CHANNEL.sender() } } diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index 1cf61e34..9d64d516 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -254,6 +254,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> /// Main keyboard task, it receives input devices result, processes keys. /// The report is sent to communication task via `KEYBOARD_REPORT_CHANNEL`, and finally sent to the host + /// TODO: make keyboard an `InputProcessor` pub(crate) async fn run(&mut self) { KEYBOARD_STATE.store(true, core::sync::atomic::Ordering::Release); loop { diff --git a/rmk/src/keymap.rs b/rmk/src/keymap.rs index c5bcf84c..1284b741 100644 --- a/rmk/src/keymap.rs +++ b/rmk/src/keymap.rs @@ -19,6 +19,9 @@ use num_enum::FromPrimitive; pub(crate) struct KeyMap<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> { /// Layers pub(crate) layers: &'a mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + // Rotary encoders, each rotary encoder is represented as (Clockwise, CounterClockwise) + // TODO: support customization of number of encoders + pub(crate) encoders: Option<&'a mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, /// Current state of each layer layer_state: [bool; NUM_LAYER], /// Default layer number, max: 32 @@ -32,9 +35,13 @@ pub(crate) struct KeyMap<'a, const ROW: usize, const COL: usize, const NUM_LAYER impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> KeyMap<'a, ROW, COL, NUM_LAYER> { - pub(crate) async fn new(action_map: &'a mut [[[KeyAction; COL]; ROW]; NUM_LAYER]) -> Self { + pub(crate) async fn new( + action_map: &'a mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + encoder_map: Option<&'a mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + ) -> Self { KeyMap { layers: action_map, + encoders: encoder_map, layer_state: [false; NUM_LAYER], default_layer: 0, layer_cache: [[0; COL]; ROW], @@ -44,6 +51,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> pub(crate) async fn new_from_storage( action_map: &'a mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + encoder_map: Option<&'a mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, storage: Option<&mut Storage>, ) -> Self { // If the storage is initialized, read keymap from storage @@ -76,6 +84,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> KeyMap { layers: action_map, + encoders: encoder_map, layer_state: [false; NUM_LAYER], default_layer: 0, layer_cache: [[0; COL]; ROW], diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index ed4e41e4..7695bdc4 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -34,10 +34,7 @@ use defmt::{error, warn}; #[cfg(not(feature = "_esp_ble"))] use embassy_executor::Spawner; use embassy_futures::select::{select, select4, Either4}; -pub use embassy_sync::{ - blocking_mutex::raw::CriticalSectionRawMutex, - channel::{Channel, Receiver}, -}; +pub use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::*}; use embassy_time::Timer; use embassy_usb::driver::Driver; pub use embedded_hal; @@ -49,7 +46,7 @@ use embedded_storage::nor_flash::NorFlash; pub use flash::EmptyFlashWrapper; use futures::pin_mut; use keyboard::{communication_task, Keyboard, KeyboardReportMessage, KEYBOARD_REPORT_CHANNEL}; -pub use keyboard::{EVENT_CHANNEL_SIZE, REPORT_CHANNEL_SIZE, EVENT_CHANNEL}; +pub use keyboard::{EVENT_CHANNEL, EVENT_CHANNEL_SIZE, REPORT_CHANNEL_SIZE}; use keymap::KeyMap; use matrix::{Matrix, MatrixTrait}; pub use rmk_macro as macros; @@ -120,6 +117,7 @@ pub async fn run_rmk< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, ) -> ! { @@ -135,6 +133,7 @@ pub async fn run_rmk< #[cfg(not(feature = "_no_external_storage"))] async_flash, default_keymap, + encoder_map, keyboard_config, #[cfg(not(feature = "_esp_ble"))] spawner, @@ -172,6 +171,7 @@ pub async fn run_rmk_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, ) -> ! { @@ -198,6 +198,7 @@ pub async fn run_rmk_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver, default_keymap, + encoder_map, keyboard_config, None, spawner, @@ -217,6 +218,7 @@ pub async fn run_rmk_with_async_flash< #[cfg(not(feature = "_no_external_storage"))] flash, default_keymap, + encoder_map, keyboard_config, ) .await; @@ -239,6 +241,7 @@ pub(crate) async fn initialize_usb_keyboard_and_run< usb_driver: D, #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, ) -> ! { // Initialize storage and keymap @@ -246,7 +249,8 @@ pub(crate) async fn initialize_usb_keyboard_and_run< #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] let (mut storage, keymap) = { let mut s = Storage::new(flash, default_keymap, keyboard_config.storage_config).await; - let keymap = RefCell::new(KeyMap::new_from_storage(default_keymap, Some(&mut s)).await); + let keymap = + RefCell::new(KeyMap::new_from_storage(default_keymap, encoder_map, Some(&mut s)).await); (s, keymap) }; #[cfg(all(not(feature = "_nrf_ble"), feature = "_no_external_storage"))] diff --git a/rmk/src/matrix.rs b/rmk/src/matrix.rs index 0df62da7..d54a62db 100644 --- a/rmk/src/matrix.rs +++ b/rmk/src/matrix.rs @@ -1,5 +1,8 @@ use crate::{ - debounce::{DebounceState, DebouncerTrait}, event::KeyEvent, keyboard::KEY_EVENT_CHANNEL, CONNECTION_STATE + debounce::{DebounceState, DebouncerTrait}, + event::KeyEvent, + keyboard::KEY_EVENT_CHANNEL, + CONNECTION_STATE, }; use defmt::{info, Format}; use embassy_time::{Instant, Timer}; diff --git a/rmk/src/split/central.rs b/rmk/src/split/central.rs index 17eb53f5..ee5e32ed 100644 --- a/rmk/src/split/central.rs +++ b/rmk/src/split/central.rs @@ -66,6 +66,7 @@ pub async fn run_rmk_split_central< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; TOTAL_COL]; TOTAL_ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, #[cfg(feature = "_nrf_ble")] central_addr: [u8; 6], #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, @@ -107,6 +108,7 @@ pub async fn run_rmk_split_central< matrix, usb_driver, default_keymap, + encoder_map, keyboard_config, Some(central_addr), spawner, @@ -159,6 +161,7 @@ pub async fn run_rmk_split_central_direct_pin< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; TOTAL_COL]; TOTAL_ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, low_active: bool, #[cfg(feature = "_nrf_ble")] central_addr: [u8; 6], @@ -187,6 +190,7 @@ pub async fn run_rmk_split_central_direct_pin< matrix, usb_driver, default_keymap, + encoder_map, keyboard_config, Some(central_addr), spawner, @@ -250,6 +254,7 @@ pub(crate) async fn initialize_usb_split_central_and_run< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] flash: F, default_keymap: &mut [[[KeyAction; TOTAL_COL]; TOTAL_ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, ) -> ! { // Initialize storage and keymap @@ -260,6 +265,7 @@ pub(crate) async fn initialize_usb_split_central_and_run< let keymap = RefCell::new( KeyMap::::new_from_storage( default_keymap, + encoder_map, Some(&mut s), ) .await, diff --git a/rmk/src/split/driver.rs b/rmk/src/split/driver.rs index a47652c8..eb5e2604 100644 --- a/rmk/src/split/driver.rs +++ b/rmk/src/split/driver.rs @@ -3,8 +3,8 @@ use core::sync::atomic::Ordering; ///! The abstracted driver layer of the split keyboard. ///! use super::SplitMessage; -use crate::{event::KeyEvent, keyboard::KEY_EVENT_CHANNEL}; use crate::CONNECTION_STATE; +use crate::{event::KeyEvent, keyboard::KEY_EVENT_CHANNEL}; use defmt::{debug, error, warn}; use embassy_futures::select::select; diff --git a/rmk/src/via/process.rs b/rmk/src/via/process.rs index e6018421..cf448ffd 100644 --- a/rmk/src/via/process.rs +++ b/rmk/src/via/process.rs @@ -253,7 +253,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> let offset = BigEndian::read_u16(&report.output_data[1..3]); // size <= 28 let size = report.output_data[3]; - info!("Getting keymap buffer, offset: {}, size: {}", offset, size); + debug!("Getting keymap buffer, offset: {}, size: {}", offset, size); let mut idx = 4; keymap .borrow() @@ -311,14 +311,18 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> warn!("Keymap get encoder -- not supported"); } ViaCommand::DynamicKeymapSetEncoder => { - warn!("Keymap get encoder -- not supported"); + warn!("Keymap set encoder -- not supported"); } ViaCommand::Vial => process_vial( report, self.vial_config.vial_keyboard_id, self.vial_config.vial_keyboard_def, + keymap, ), - ViaCommand::Unhandled => report.input_data[0] = ViaCommand::Unhandled as u8, + ViaCommand::Unhandled => { + info!("Unknown cmd: {}", report.output_data); + report.input_data[0] = ViaCommand::Unhandled as u8 + } } } } diff --git a/rmk/src/via/vial.rs b/rmk/src/via/vial.rs index 42d07128..ab3a96a4 100644 --- a/rmk/src/via/vial.rs +++ b/rmk/src/via/vial.rs @@ -1,10 +1,16 @@ -use byteorder::{ByteOrder, LittleEndian}; -use defmt::debug; +use core::cell::RefCell; + +use byteorder::{BigEndian, ByteOrder, LittleEndian}; +use defmt::{debug, info}; use num_enum::FromPrimitive; -use crate::usb::descriptor::ViaReport; +use crate::{ + keymap::KeyMap, + usb::descriptor::ViaReport, + via::keycode_convert::{from_via_keycode, to_via_keycode}, +}; -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive)] +#[derive(Debug, Copy, Clone, defmt::Format, PartialEq, Eq, PartialOrd, Ord, FromPrimitive)] #[repr(u8)] enum VialCommand { GetKeyboardId = 0x00, @@ -29,13 +35,15 @@ const VIAL_PROTOCOL_VERSION: u32 = 6; const VIAL_EP_SIZE: usize = 32; /// /// Note: vial uses litte endian, while via uses big endian -pub(crate) fn process_vial( +pub(crate) fn process_vial<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize>( report: &mut ViaReport, vial_keyboard_Id: &[u8], vial_keyboard_def: &[u8], + keymap: &RefCell>, ) { // report.output_data[0] == 0xFE -> vial commands let vial_command = VialCommand::from_primitive(report.output_data[1]); + info!("Received vial command: {}", vial_command); match vial_command { VialCommand::GetKeyboardId => { debug!("Received Vial - GetKeyboardId"); @@ -84,6 +92,49 @@ pub(crate) fn process_vial( VialCommand::DynamicEntryOp => { report.input_data.fill(0x00); } + VialCommand::GetEncoder => { + let layer = report.output_data[2]; + let index = report.output_data[3]; + debug!("Received Vial - GetEncoder, data: {}", report.output_data); + // Get encoder value + if let Some(encoders) = &keymap.borrow().encoders { + if let Some(encoder_layer) = encoders.get(layer as usize) { + if let Some(encoder) = encoder_layer.get(index as usize) { + let clockwise = to_via_keycode(encoder.0); + BigEndian::write_u16(&mut report.input_data[0..2], clockwise); + let counter_clockwise = to_via_keycode(encoder.1); + BigEndian::write_u16(&mut report.input_data[2..4], counter_clockwise); + return; + } + } + } + + // Clear returned value, aka `KeyAction::No` + report.input_data.fill(0x0); + } + VialCommand::SetEncoder => { + let layer = report.output_data[2]; + let index = report.output_data[3]; + let clockwise = report.output_data[4]; + if let Some(&mut mut encoders) = keymap.borrow_mut().encoders { + if let Some(&mut mut encoder_layer) = encoders.get_mut(layer as usize) { + if let Some(&mut mut encoder) = encoder_layer.get_mut(index as usize) { + if clockwise == 1 { + let keycode = BigEndian::read_u16(&report.output_data[5..7]); + let action = from_via_keycode(keycode); + info!("Setting clockwise action: {}", action); + encoder.0 = action + } else { + let keycode = BigEndian::read_u16(&report.output_data[5..7]); + let action = from_via_keycode(keycode); + info!("Setting counter-clockwise action: {}", action); + encoder.1 = action + } + } + } + } + debug!("Received Vial - SetEncoder, data: {}", report.output_data); + } _ => (), } } From aeea0d348b70654f0be68df3bee018435f037768 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Fri, 3 Jan 2025 14:58:31 +0800 Subject: [PATCH 18/21] feat(input_device): add encoder map to entry API Signed-off-by: Haobo Gu --- examples/use_config/stm32h7/src/main.rs | 1 + examples/use_rust/ch32v307/src/main.rs | 1 + examples/use_rust/esp32c3_ble/src/main.rs | 1 + examples/use_rust/esp32c6_ble/src/main.rs | 1 + examples/use_rust/esp32s3_ble/src/main.rs | 1 + examples/use_rust/hpm5300/src/main.rs | 1 + examples/use_rust/nrf52832_ble/src/main.rs | 1 + examples/use_rust/nrf52840/src/main.rs | 1 + examples/use_rust/nrf52840_ble_split/src/central.rs | 1 + examples/use_rust/py32f07x/src/main.rs | 1 + examples/use_rust/rp2040/src/main.rs | 1 + examples/use_rust/rp2040_direct_pin/src/main.rs | 1 + examples/use_rust/rp2040_split/src/central.rs | 1 + examples/use_rust/stm32f1/src/main.rs | 1 + examples/use_rust/stm32f4/src/main.rs | 1 + examples/use_rust/stm32h7/src/main.rs | 1 + examples/use_rust/stm32h7_async/src/main.rs | 1 + rmk-macro/src/entry.rs | 12 ++++++++++++ rmk-macro/src/split/central.rs | 12 ++++++------ rmk/src/ble/esp/mod.rs | 5 ++++- rmk/src/direct_pin.rs | 2 +- rmk/src/lib.rs | 5 +++-- rmk/src/split/central.rs | 2 ++ 23 files changed, 45 insertions(+), 10 deletions(-) diff --git a/examples/use_config/stm32h7/src/main.rs b/examples/use_config/stm32h7/src/main.rs index 37762fbb..90d60f32 100644 --- a/examples/use_config/stm32h7/src/main.rs +++ b/examples/use_config/stm32h7/src/main.rs @@ -83,6 +83,7 @@ mod my_keyboard { driver, f, &mut get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/ch32v307/src/main.rs b/examples/use_rust/ch32v307/src/main.rs index d9915e58..9465aa10 100644 --- a/examples/use_rust/ch32v307/src/main.rs +++ b/examples/use_rust/ch32v307/src/main.rs @@ -96,6 +96,7 @@ async fn main(spawner: Spawner) -> ! { driver, // rmk::EmptyFlashWrapper::new(), &mut default_keymap, + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/esp32c3_ble/src/main.rs b/examples/use_rust/esp32c3_ble/src/main.rs index 2b34e36d..4a2380de 100644 --- a/examples/use_rust/esp32c3_ble/src/main.rs +++ b/examples/use_rust/esp32c3_ble/src/main.rs @@ -40,6 +40,7 @@ fn main() { input_pins, output_pins, &mut keymap::get_default_keymap(), + None, keyboard_config, )); } diff --git a/examples/use_rust/esp32c6_ble/src/main.rs b/examples/use_rust/esp32c6_ble/src/main.rs index 2b34e36d..4a2380de 100644 --- a/examples/use_rust/esp32c6_ble/src/main.rs +++ b/examples/use_rust/esp32c6_ble/src/main.rs @@ -40,6 +40,7 @@ fn main() { input_pins, output_pins, &mut keymap::get_default_keymap(), + None, keyboard_config, )); } diff --git a/examples/use_rust/esp32s3_ble/src/main.rs b/examples/use_rust/esp32s3_ble/src/main.rs index 3ebedf66..be03fe7d 100644 --- a/examples/use_rust/esp32s3_ble/src/main.rs +++ b/examples/use_rust/esp32s3_ble/src/main.rs @@ -40,6 +40,7 @@ fn main() { input_pins, output_pins, &mut keymap::get_default_keymap(), + None, keyboard_config, )); } diff --git a/examples/use_rust/hpm5300/src/main.rs b/examples/use_rust/hpm5300/src/main.rs index abccf535..ccbd1d18 100644 --- a/examples/use_rust/hpm5300/src/main.rs +++ b/examples/use_rust/hpm5300/src/main.rs @@ -63,6 +63,7 @@ async fn main(spawner: Spawner) { usb_driver, flash, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/nrf52832_ble/src/main.rs b/examples/use_rust/nrf52832_ble/src/main.rs index c0ad7c2a..e958456a 100644 --- a/examples/use_rust/nrf52832_ble/src/main.rs +++ b/examples/use_rust/nrf52832_ble/src/main.rs @@ -60,6 +60,7 @@ async fn main(spawner: Spawner) { input_pins, output_pins, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/nrf52840/src/main.rs b/examples/use_rust/nrf52840/src/main.rs index 6c9bdd35..f6217516 100644 --- a/examples/use_rust/nrf52840/src/main.rs +++ b/examples/use_rust/nrf52840/src/main.rs @@ -65,6 +65,7 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/nrf52840_ble_split/src/central.rs b/examples/use_rust/nrf52840_ble_split/src/central.rs index c7cf9805..d2922e37 100644 --- a/examples/use_rust/nrf52840_ble_split/src/central.rs +++ b/examples/use_rust/nrf52840_ble_split/src/central.rs @@ -131,6 +131,7 @@ async fn main(spawner: Spawner) { output_pins, driver, &mut keymap::get_default_keymap(), + None, keyboard_config, central_addr, spawner, diff --git a/examples/use_rust/py32f07x/src/main.rs b/examples/use_rust/py32f07x/src/main.rs index be0bad0a..da6df6db 100644 --- a/examples/use_rust/py32f07x/src/main.rs +++ b/examples/use_rust/py32f07x/src/main.rs @@ -72,6 +72,7 @@ async fn main(spawner: Spawner) { driver, // flash, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/rp2040/src/main.rs b/examples/use_rust/rp2040/src/main.rs index 1ff20ac4..8d204a13 100644 --- a/examples/use_rust/rp2040/src/main.rs +++ b/examples/use_rust/rp2040/src/main.rs @@ -72,6 +72,7 @@ async fn main(spawner: Spawner) { driver, flash, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/rp2040_direct_pin/src/main.rs b/examples/use_rust/rp2040_direct_pin/src/main.rs index 735cdf95..fa5a060c 100644 --- a/examples/use_rust/rp2040_direct_pin/src/main.rs +++ b/examples/use_rust/rp2040_direct_pin/src/main.rs @@ -81,6 +81,7 @@ async fn main(spawner: Spawner) { driver, flash, &mut keymap::get_default_keymap(), + None, keyboard_config, true, spawner, diff --git a/examples/use_rust/rp2040_split/src/central.rs b/examples/use_rust/rp2040_split/src/central.rs index f2871f91..65f13e91 100644 --- a/examples/use_rust/rp2040_split/src/central.rs +++ b/examples/use_rust/rp2040_split/src/central.rs @@ -107,6 +107,7 @@ async fn main(spawner: Spawner) { driver, flash, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ), diff --git a/examples/use_rust/stm32f1/src/main.rs b/examples/use_rust/stm32f1/src/main.rs index 30a122b4..2d5de419 100644 --- a/examples/use_rust/stm32f1/src/main.rs +++ b/examples/use_rust/stm32f1/src/main.rs @@ -68,6 +68,7 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/stm32f4/src/main.rs b/examples/use_rust/stm32f4/src/main.rs index 3c869fa3..74e15036 100644 --- a/examples/use_rust/stm32f4/src/main.rs +++ b/examples/use_rust/stm32f4/src/main.rs @@ -70,6 +70,7 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/stm32h7/src/main.rs b/examples/use_rust/stm32h7/src/main.rs index 1e2bb4fb..11b6b231 100644 --- a/examples/use_rust/stm32h7/src/main.rs +++ b/examples/use_rust/stm32h7/src/main.rs @@ -103,6 +103,7 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/examples/use_rust/stm32h7_async/src/main.rs b/examples/use_rust/stm32h7_async/src/main.rs index 7e01a13f..46f3cd5f 100644 --- a/examples/use_rust/stm32h7_async/src/main.rs +++ b/examples/use_rust/stm32h7_async/src/main.rs @@ -110,6 +110,7 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), + None, keyboard_config, spawner, ) diff --git a/rmk-macro/src/entry.rs b/rmk-macro/src/entry.rs index 0e30b6b8..c8dc93d3 100644 --- a/rmk-macro/src/entry.rs +++ b/rmk-macro/src/entry.rs @@ -62,6 +62,7 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr driver, f, &mut get_default_keymap(), + None, keyboard_config, low_active, spawner, @@ -77,6 +78,7 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr driver, f, &mut get_default_keymap(), + None, keyboard_config, low_active, spawner @@ -89,6 +91,7 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr direct_pins, driver, &mut get_default_keymap(), + None, keyboard_config, low_active, spawner, @@ -99,6 +102,7 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr ::rmk::direct_pin::run_rmk_direct_pin::<_, ::embassy_nrf::gpio::Output, ROW, COL, SIZE, NUM_LAYER>( direct_pins, &mut get_default_keymap(), + None, keyboard_config, low_active, spawner, @@ -113,6 +117,7 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr driver, flash, &mut get_default_keymap(), + None, keyboard_config, low_active, spawner, @@ -123,6 +128,7 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr ::esp_idf_svc::hal::task::block_on(::rmk::direct_pin::run_rmk_direct_pin::<_, ::esp_idf_svc::hal::gpio::Output, ROW, COL, SIZE, NUM_LAYER>( direct_pins, &mut get_default_keymap(), + None, keyboard_config, low_active, )); @@ -140,6 +146,7 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream driver, f, &mut get_default_keymap(), + None, keyboard_config, spawner, ) @@ -155,6 +162,7 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream driver, f, &mut get_default_keymap(), + None, keyboard_config, spawner ) @@ -167,6 +175,7 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream output_pins, driver, &mut get_default_keymap(), + None, keyboard_config, spawner, ) @@ -177,6 +186,7 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream input_pins, output_pins, &mut get_default_keymap(), + None, keyboard_config, spawner, ) @@ -191,6 +201,7 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream driver, flash, &mut get_default_keymap(), + None, keyboard_config, spawner, ) @@ -201,6 +212,7 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream input_pins, output_pins, &mut get_default_keymap(), + None, keyboard_config, )); }, diff --git a/rmk-macro/src/split/central.rs b/rmk-macro/src/split/central.rs index 0032b7e5..0d10bd9b 100644 --- a/rmk-macro/src/split/central.rs +++ b/rmk-macro/src/split/central.rs @@ -226,7 +226,7 @@ fn expand_split_central_entry( #central_row_offset, #central_col_offset, NUM_LAYER, - >(input_pins, output_pins, driver, flash, &mut get_default_keymap(), keyboard_config, , spawner) + >(input_pins, output_pins, driver, flash, &mut get_default_keymap(), None, keyboard_config, , spawner) }, MatrixType::direct_pin => quote! { ::rmk::split::central::run_rmk_split_central_direct_pin::< @@ -242,7 +242,7 @@ fn expand_split_central_entry( #central_col_offset, NUM_LAYER, SIZE, - >(direct_pins, driver, flash, &mut get_default_keymap(), keyboard_config, #low_active, spawner) + >(direct_pins, driver, flash, &mut get_default_keymap(), None, keyboard_config, #low_active, spawner) }, }; let mut tasks = vec![central_task]; @@ -291,7 +291,7 @@ fn expand_split_central_entry( #central_row_offset, #central_col_offset, NUM_LAYER, - >(input_pins, output_pins, driver, &mut get_default_keymap(), keyboard_config, [#(#central_addr), *], spawner) + >(input_pins, output_pins, driver, &mut get_default_keymap(), None, keyboard_config, [#(#central_addr), *], spawner) }, MatrixType::direct_pin => quote! { ::rmk::split::central::run_rmk_split_central_direct_pin::< @@ -306,7 +306,7 @@ fn expand_split_central_entry( #central_col_offset, NUM_LAYER, SIZE, - >(direct_pins, driver, &mut get_default_keymap(), keyboard_config, #low_active, [#(#central_addr), *], spawner) + >(direct_pins, driver, &mut get_default_keymap(), None, keyboard_config, #low_active, [#(#central_addr), *], spawner) }, }; let mut tasks = vec![central_task]; @@ -342,7 +342,7 @@ fn expand_split_central_entry( #central_row_offset, #central_col_offset, NUM_LAYER, - >(input_pins, output_pins, driver, flash, &mut get_default_keymap(), keyboard_config, spawner) + >(input_pins, output_pins, driver, flash, &mut get_default_keymap(), None, keyboard_config, spawner) }, MatrixType::direct_pin => quote! { ::rmk::split::central::run_rmk_split_central_direct_pin::< @@ -358,7 +358,7 @@ fn expand_split_central_entry( #central_col_offset, NUM_LAYER, SIZE, - >(direct_pins, driver, flash, &mut get_default_keymap(), keyboard_config, #low_active, spawner) + >(direct_pins, driver, flash, &mut get_default_keymap(), None, keyboard_config, #low_active, spawner) }, }; let mut tasks = vec![central_task]; diff --git a/rmk/src/ble/esp/mod.rs b/rmk/src/ble/esp/mod.rs index 5869871c..837ede9e 100644 --- a/rmk/src/ble/esp/mod.rs +++ b/rmk/src/ble/esp/mod.rs @@ -44,6 +44,7 @@ pub(crate) async fn initialize_esp_ble_keyboard_with_config_and_run< >( mut matrix: M, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], + encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, ) -> ! { let f = Partition::new(PartitionType::Custom, Some(c"rmk")); @@ -59,7 +60,9 @@ pub(crate) async fn initialize_esp_ble_keyboard_with_config_and_run< ) .await; - let keymap = RefCell::new(KeyMap::new_from_storage(default_keymap, Some(&mut storage)).await); + let keymap = RefCell::new( + KeyMap::new_from_storage(default_keymap, encoder_map, Some(&mut storage)).await, + ); let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); let keyboard_report_receiver = KEYBOARD_REPORT_CHANNEL.receiver(); diff --git a/rmk/src/direct_pin.rs b/rmk/src/direct_pin.rs index 5422a02f..09ea30b1 100644 --- a/rmk/src/direct_pin.rs +++ b/rmk/src/direct_pin.rs @@ -193,7 +193,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< .await; #[cfg(feature = "_esp_ble")] - initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, keyboard_config).await; + initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, encoder_map, keyboard_config).await; #[cfg(all( not(feature = "_no_usb"), diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index 7695bdc4..c7d471f7 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -206,7 +206,7 @@ pub async fn run_rmk_with_async_flash< .await; #[cfg(feature = "_esp_ble")] - initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, keyboard_config).await; + initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, encoder_map, keyboard_config).await; #[cfg(all( not(feature = "_no_usb"), @@ -254,7 +254,8 @@ pub(crate) async fn initialize_usb_keyboard_and_run< (s, keymap) }; #[cfg(all(not(feature = "_nrf_ble"), feature = "_no_external_storage"))] - let keymap = RefCell::new(KeyMap::::new(default_keymap).await); + let keymap = + RefCell::new(KeyMap::::new(default_keymap, encoder_map).await); let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); let keyboard_report_receiver = KEYBOARD_REPORT_CHANNEL.receiver(); diff --git a/rmk/src/split/central.rs b/rmk/src/split/central.rs index ee5e32ed..f5100dba 100644 --- a/rmk/src/split/central.rs +++ b/rmk/src/split/central.rs @@ -121,6 +121,7 @@ pub async fn run_rmk_split_central< usb_driver, flash, default_keymap, + encoder_map, keyboard_config, ) .await; @@ -203,6 +204,7 @@ pub async fn run_rmk_split_central_direct_pin< usb_driver, flash, default_keymap, + encoder_map, keyboard_config, ) .await; From 017ab7d72ac95d6e3ccf5fc8b3371a855d66c086 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Fri, 3 Jan 2025 16:03:16 +0800 Subject: [PATCH 19/21] revert!: remove encoders API Signed-off-by: Haobo Gu --- examples/use_config/stm32h7/src/main.rs | 1 - examples/use_rust/ch32v307/src/main.rs | 1 - examples/use_rust/esp32c3_ble/src/main.rs | 1 - examples/use_rust/esp32c6_ble/src/main.rs | 1 - examples/use_rust/esp32s3_ble/src/main.rs | 1 - examples/use_rust/hpm5300/src/main.rs | 1 - examples/use_rust/nrf52832_ble/src/main.rs | 1 - examples/use_rust/nrf52840/src/main.rs | 1 - examples/use_rust/nrf52840_ble/src/main.rs | 1 - .../nrf52840_ble_split/src/central.rs | 1 - examples/use_rust/py32f07x/src/main.rs | 1 - examples/use_rust/rp2040/src/main.rs | 1 - .../use_rust/rp2040_direct_pin/src/main.rs | 1 - examples/use_rust/rp2040_split/src/central.rs | 1 - examples/use_rust/stm32f1/src/main.rs | 1 - examples/use_rust/stm32f4/src/main.rs | 1 - examples/use_rust/stm32h7/src/main.rs | 1 - examples/use_rust/stm32h7_async/src/main.rs | 1 - rmk-macro/src/entry.rs | 12 ---- rmk-macro/src/split/central.rs | 12 ++-- rmk/src/ble/esp/mod.rs | 4 +- rmk/src/ble/nrf/mod.rs | 4 +- rmk/src/direct_pin.rs | 17 +++-- rmk/src/keymap.rs | 9 +-- rmk/src/lib.rs | 18 ++--- rmk/src/split/central.rs | 16 ++--- rmk/src/via/vial.rs | 66 +++++++++---------- 27 files changed, 70 insertions(+), 106 deletions(-) diff --git a/examples/use_config/stm32h7/src/main.rs b/examples/use_config/stm32h7/src/main.rs index 90d60f32..37762fbb 100644 --- a/examples/use_config/stm32h7/src/main.rs +++ b/examples/use_config/stm32h7/src/main.rs @@ -83,7 +83,6 @@ mod my_keyboard { driver, f, &mut get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/ch32v307/src/main.rs b/examples/use_rust/ch32v307/src/main.rs index 9465aa10..d9915e58 100644 --- a/examples/use_rust/ch32v307/src/main.rs +++ b/examples/use_rust/ch32v307/src/main.rs @@ -96,7 +96,6 @@ async fn main(spawner: Spawner) -> ! { driver, // rmk::EmptyFlashWrapper::new(), &mut default_keymap, - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/esp32c3_ble/src/main.rs b/examples/use_rust/esp32c3_ble/src/main.rs index 4a2380de..2b34e36d 100644 --- a/examples/use_rust/esp32c3_ble/src/main.rs +++ b/examples/use_rust/esp32c3_ble/src/main.rs @@ -40,7 +40,6 @@ fn main() { input_pins, output_pins, &mut keymap::get_default_keymap(), - None, keyboard_config, )); } diff --git a/examples/use_rust/esp32c6_ble/src/main.rs b/examples/use_rust/esp32c6_ble/src/main.rs index 4a2380de..2b34e36d 100644 --- a/examples/use_rust/esp32c6_ble/src/main.rs +++ b/examples/use_rust/esp32c6_ble/src/main.rs @@ -40,7 +40,6 @@ fn main() { input_pins, output_pins, &mut keymap::get_default_keymap(), - None, keyboard_config, )); } diff --git a/examples/use_rust/esp32s3_ble/src/main.rs b/examples/use_rust/esp32s3_ble/src/main.rs index be03fe7d..3ebedf66 100644 --- a/examples/use_rust/esp32s3_ble/src/main.rs +++ b/examples/use_rust/esp32s3_ble/src/main.rs @@ -40,7 +40,6 @@ fn main() { input_pins, output_pins, &mut keymap::get_default_keymap(), - None, keyboard_config, )); } diff --git a/examples/use_rust/hpm5300/src/main.rs b/examples/use_rust/hpm5300/src/main.rs index ccbd1d18..abccf535 100644 --- a/examples/use_rust/hpm5300/src/main.rs +++ b/examples/use_rust/hpm5300/src/main.rs @@ -63,7 +63,6 @@ async fn main(spawner: Spawner) { usb_driver, flash, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/nrf52832_ble/src/main.rs b/examples/use_rust/nrf52832_ble/src/main.rs index e958456a..c0ad7c2a 100644 --- a/examples/use_rust/nrf52832_ble/src/main.rs +++ b/examples/use_rust/nrf52832_ble/src/main.rs @@ -60,7 +60,6 @@ async fn main(spawner: Spawner) { input_pins, output_pins, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/nrf52840/src/main.rs b/examples/use_rust/nrf52840/src/main.rs index f6217516..6c9bdd35 100644 --- a/examples/use_rust/nrf52840/src/main.rs +++ b/examples/use_rust/nrf52840/src/main.rs @@ -65,7 +65,6 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/nrf52840_ble/src/main.rs b/examples/use_rust/nrf52840_ble/src/main.rs index 16c0efc1..b427f29b 100644 --- a/examples/use_rust/nrf52840_ble/src/main.rs +++ b/examples/use_rust/nrf52840_ble/src/main.rs @@ -119,7 +119,6 @@ async fn main(spawner: Spawner) { output_pins, driver, &mut keymap::get_default_keymap(), - Some(&mut keymap::get_default_encoder_map()), keyboard_config, spawner, ), diff --git a/examples/use_rust/nrf52840_ble_split/src/central.rs b/examples/use_rust/nrf52840_ble_split/src/central.rs index d2922e37..c7cf9805 100644 --- a/examples/use_rust/nrf52840_ble_split/src/central.rs +++ b/examples/use_rust/nrf52840_ble_split/src/central.rs @@ -131,7 +131,6 @@ async fn main(spawner: Spawner) { output_pins, driver, &mut keymap::get_default_keymap(), - None, keyboard_config, central_addr, spawner, diff --git a/examples/use_rust/py32f07x/src/main.rs b/examples/use_rust/py32f07x/src/main.rs index da6df6db..be0bad0a 100644 --- a/examples/use_rust/py32f07x/src/main.rs +++ b/examples/use_rust/py32f07x/src/main.rs @@ -72,7 +72,6 @@ async fn main(spawner: Spawner) { driver, // flash, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/rp2040/src/main.rs b/examples/use_rust/rp2040/src/main.rs index 8d204a13..1ff20ac4 100644 --- a/examples/use_rust/rp2040/src/main.rs +++ b/examples/use_rust/rp2040/src/main.rs @@ -72,7 +72,6 @@ async fn main(spawner: Spawner) { driver, flash, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/rp2040_direct_pin/src/main.rs b/examples/use_rust/rp2040_direct_pin/src/main.rs index fa5a060c..735cdf95 100644 --- a/examples/use_rust/rp2040_direct_pin/src/main.rs +++ b/examples/use_rust/rp2040_direct_pin/src/main.rs @@ -81,7 +81,6 @@ async fn main(spawner: Spawner) { driver, flash, &mut keymap::get_default_keymap(), - None, keyboard_config, true, spawner, diff --git a/examples/use_rust/rp2040_split/src/central.rs b/examples/use_rust/rp2040_split/src/central.rs index 65f13e91..f2871f91 100644 --- a/examples/use_rust/rp2040_split/src/central.rs +++ b/examples/use_rust/rp2040_split/src/central.rs @@ -107,7 +107,6 @@ async fn main(spawner: Spawner) { driver, flash, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ), diff --git a/examples/use_rust/stm32f1/src/main.rs b/examples/use_rust/stm32f1/src/main.rs index 2d5de419..30a122b4 100644 --- a/examples/use_rust/stm32f1/src/main.rs +++ b/examples/use_rust/stm32f1/src/main.rs @@ -68,7 +68,6 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/stm32f4/src/main.rs b/examples/use_rust/stm32f4/src/main.rs index 74e15036..3c869fa3 100644 --- a/examples/use_rust/stm32f4/src/main.rs +++ b/examples/use_rust/stm32f4/src/main.rs @@ -70,7 +70,6 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/stm32h7/src/main.rs b/examples/use_rust/stm32h7/src/main.rs index 11b6b231..1e2bb4fb 100644 --- a/examples/use_rust/stm32h7/src/main.rs +++ b/examples/use_rust/stm32h7/src/main.rs @@ -103,7 +103,6 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/examples/use_rust/stm32h7_async/src/main.rs b/examples/use_rust/stm32h7_async/src/main.rs index 46f3cd5f..7e01a13f 100644 --- a/examples/use_rust/stm32h7_async/src/main.rs +++ b/examples/use_rust/stm32h7_async/src/main.rs @@ -110,7 +110,6 @@ async fn main(spawner: Spawner) { driver, f, &mut keymap::get_default_keymap(), - None, keyboard_config, spawner, ) diff --git a/rmk-macro/src/entry.rs b/rmk-macro/src/entry.rs index c8dc93d3..0e30b6b8 100644 --- a/rmk-macro/src/entry.rs +++ b/rmk-macro/src/entry.rs @@ -62,7 +62,6 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr driver, f, &mut get_default_keymap(), - None, keyboard_config, low_active, spawner, @@ -78,7 +77,6 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr driver, f, &mut get_default_keymap(), - None, keyboard_config, low_active, spawner @@ -91,7 +89,6 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr direct_pins, driver, &mut get_default_keymap(), - None, keyboard_config, low_active, spawner, @@ -102,7 +99,6 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr ::rmk::direct_pin::run_rmk_direct_pin::<_, ::embassy_nrf::gpio::Output, ROW, COL, SIZE, NUM_LAYER>( direct_pins, &mut get_default_keymap(), - None, keyboard_config, low_active, spawner, @@ -117,7 +113,6 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr driver, flash, &mut get_default_keymap(), - None, keyboard_config, low_active, spawner, @@ -128,7 +123,6 @@ pub(crate) fn rmk_entry_direct_pin(keyboard_config: &KeyboardConfig) -> TokenStr ::esp_idf_svc::hal::task::block_on(::rmk::direct_pin::run_rmk_direct_pin::<_, ::esp_idf_svc::hal::gpio::Output, ROW, COL, SIZE, NUM_LAYER>( direct_pins, &mut get_default_keymap(), - None, keyboard_config, low_active, )); @@ -146,7 +140,6 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream driver, f, &mut get_default_keymap(), - None, keyboard_config, spawner, ) @@ -162,7 +155,6 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream driver, f, &mut get_default_keymap(), - None, keyboard_config, spawner ) @@ -175,7 +167,6 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream output_pins, driver, &mut get_default_keymap(), - None, keyboard_config, spawner, ) @@ -186,7 +177,6 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream input_pins, output_pins, &mut get_default_keymap(), - None, keyboard_config, spawner, ) @@ -201,7 +191,6 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream driver, flash, &mut get_default_keymap(), - None, keyboard_config, spawner, ) @@ -212,7 +201,6 @@ pub(crate) fn rmk_entry_default(keyboard_config: &KeyboardConfig) -> TokenStream input_pins, output_pins, &mut get_default_keymap(), - None, keyboard_config, )); }, diff --git a/rmk-macro/src/split/central.rs b/rmk-macro/src/split/central.rs index 0d10bd9b..0032b7e5 100644 --- a/rmk-macro/src/split/central.rs +++ b/rmk-macro/src/split/central.rs @@ -226,7 +226,7 @@ fn expand_split_central_entry( #central_row_offset, #central_col_offset, NUM_LAYER, - >(input_pins, output_pins, driver, flash, &mut get_default_keymap(), None, keyboard_config, , spawner) + >(input_pins, output_pins, driver, flash, &mut get_default_keymap(), keyboard_config, , spawner) }, MatrixType::direct_pin => quote! { ::rmk::split::central::run_rmk_split_central_direct_pin::< @@ -242,7 +242,7 @@ fn expand_split_central_entry( #central_col_offset, NUM_LAYER, SIZE, - >(direct_pins, driver, flash, &mut get_default_keymap(), None, keyboard_config, #low_active, spawner) + >(direct_pins, driver, flash, &mut get_default_keymap(), keyboard_config, #low_active, spawner) }, }; let mut tasks = vec![central_task]; @@ -291,7 +291,7 @@ fn expand_split_central_entry( #central_row_offset, #central_col_offset, NUM_LAYER, - >(input_pins, output_pins, driver, &mut get_default_keymap(), None, keyboard_config, [#(#central_addr), *], spawner) + >(input_pins, output_pins, driver, &mut get_default_keymap(), keyboard_config, [#(#central_addr), *], spawner) }, MatrixType::direct_pin => quote! { ::rmk::split::central::run_rmk_split_central_direct_pin::< @@ -306,7 +306,7 @@ fn expand_split_central_entry( #central_col_offset, NUM_LAYER, SIZE, - >(direct_pins, driver, &mut get_default_keymap(), None, keyboard_config, #low_active, [#(#central_addr), *], spawner) + >(direct_pins, driver, &mut get_default_keymap(), keyboard_config, #low_active, [#(#central_addr), *], spawner) }, }; let mut tasks = vec![central_task]; @@ -342,7 +342,7 @@ fn expand_split_central_entry( #central_row_offset, #central_col_offset, NUM_LAYER, - >(input_pins, output_pins, driver, flash, &mut get_default_keymap(), None, keyboard_config, spawner) + >(input_pins, output_pins, driver, flash, &mut get_default_keymap(), keyboard_config, spawner) }, MatrixType::direct_pin => quote! { ::rmk::split::central::run_rmk_split_central_direct_pin::< @@ -358,7 +358,7 @@ fn expand_split_central_entry( #central_col_offset, NUM_LAYER, SIZE, - >(direct_pins, driver, flash, &mut get_default_keymap(), None, keyboard_config, #low_active, spawner) + >(direct_pins, driver, flash, &mut get_default_keymap(), keyboard_config, #low_active, spawner) }, }; let mut tasks = vec![central_task]; diff --git a/rmk/src/ble/esp/mod.rs b/rmk/src/ble/esp/mod.rs index 837ede9e..4b40080e 100644 --- a/rmk/src/ble/esp/mod.rs +++ b/rmk/src/ble/esp/mod.rs @@ -44,7 +44,7 @@ pub(crate) async fn initialize_esp_ble_keyboard_with_config_and_run< >( mut matrix: M, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + keyboard_config: RmkConfig<'static, Out>, ) -> ! { let f = Partition::new(PartitionType::Custom, Some(c"rmk")); @@ -61,7 +61,7 @@ pub(crate) async fn initialize_esp_ble_keyboard_with_config_and_run< .await; let keymap = RefCell::new( - KeyMap::new_from_storage(default_keymap, encoder_map, Some(&mut storage)).await, + KeyMap::new_from_storage(default_keymap, Some(&mut storage)).await, ); let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); diff --git a/rmk/src/ble/nrf/mod.rs b/rmk/src/ble/nrf/mod.rs index 330f35bd..f7bd438f 100644 --- a/rmk/src/ble/nrf/mod.rs +++ b/rmk/src/ble/nrf/mod.rs @@ -226,7 +226,7 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< mut matrix: M, #[cfg(not(feature = "_no_usb"))] usb_driver: D, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + mut keyboard_config: RmkConfig<'static, Out>, ble_addr: Option<[u8; 6]>, spawner: Spawner, @@ -252,7 +252,7 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< let flash = Flash::take(sd); let mut storage = Storage::new(flash, default_keymap, keyboard_config.storage_config).await; let keymap = RefCell::new( - KeyMap::new_from_storage(default_keymap, encoder_map, Some(&mut storage)).await, + KeyMap::new_from_storage(default_keymap, Some(&mut storage)).await, ); let mut buf: [u8; 128] = [0; 128]; diff --git a/rmk/src/direct_pin.rs b/rmk/src/direct_pin.rs index 09ea30b1..6bcf1680 100644 --- a/rmk/src/direct_pin.rs +++ b/rmk/src/direct_pin.rs @@ -66,7 +66,6 @@ pub async fn run_rmk_direct_pin< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, keyboard_config: RmkConfig<'static, Out>, low_active: bool, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, @@ -80,7 +79,7 @@ pub async fn run_rmk_direct_pin< run_rmk_direct_pin_with_async_flash::<_, _, ROW, COL, SIZE, NUM_LAYER>( direct_pins, default_keymap, - encoder_map, + keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -95,7 +94,7 @@ pub async fn run_rmk_direct_pin< direct_pins, usb_driver, default_keymap, - encoder_map, + keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -110,7 +109,7 @@ pub async fn run_rmk_direct_pin< direct_pins, async_flash, default_keymap, - encoder_map, + keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -126,7 +125,7 @@ pub async fn run_rmk_direct_pin< usb_driver, async_flash, default_keymap, - encoder_map, + keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -164,7 +163,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + keyboard_config: RmkConfig<'static, Out>, low_active: bool, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, @@ -185,7 +184,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver, default_keymap, - encoder_map, + keyboard_config, None, spawner, @@ -193,7 +192,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< .await; #[cfg(feature = "_esp_ble")] - initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, encoder_map, keyboard_config).await; + initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, keyboard_config).await; #[cfg(all( not(feature = "_no_usb"), @@ -205,7 +204,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< #[cfg(not(feature = "_no_external_storage"))] flash, default_keymap, - encoder_map, + keyboard_config, ) .await; diff --git a/rmk/src/keymap.rs b/rmk/src/keymap.rs index 1284b741..2fa44b17 100644 --- a/rmk/src/keymap.rs +++ b/rmk/src/keymap.rs @@ -19,9 +19,8 @@ use num_enum::FromPrimitive; pub(crate) struct KeyMap<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> { /// Layers pub(crate) layers: &'a mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - // Rotary encoders, each rotary encoder is represented as (Clockwise, CounterClockwise) - // TODO: support customization of number of encoders - pub(crate) encoders: Option<&'a mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + // TODO: Rotary encoders, each rotary encoder is represented as (Clockwise, CounterClockwise) + // pub(crate) encoders: Option<&'a mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, /// Current state of each layer layer_state: [bool; NUM_LAYER], /// Default layer number, max: 32 @@ -37,11 +36,9 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> { pub(crate) async fn new( action_map: &'a mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - encoder_map: Option<&'a mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, ) -> Self { KeyMap { layers: action_map, - encoders: encoder_map, layer_state: [false; NUM_LAYER], default_layer: 0, layer_cache: [[0; COL]; ROW], @@ -51,7 +48,6 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> pub(crate) async fn new_from_storage( action_map: &'a mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - encoder_map: Option<&'a mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, storage: Option<&mut Storage>, ) -> Self { // If the storage is initialized, read keymap from storage @@ -84,7 +80,6 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> KeyMap { layers: action_map, - encoders: encoder_map, layer_state: [false; NUM_LAYER], default_layer: 0, layer_cache: [[0; COL]; ROW], diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index c7d471f7..37f5f6c1 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -117,7 +117,7 @@ pub async fn run_rmk< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + keyboard_config: RmkConfig<'static, Out>, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, ) -> ! { @@ -133,7 +133,7 @@ pub async fn run_rmk< #[cfg(not(feature = "_no_external_storage"))] async_flash, default_keymap, - encoder_map, + keyboard_config, #[cfg(not(feature = "_esp_ble"))] spawner, @@ -171,7 +171,7 @@ pub async fn run_rmk_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + keyboard_config: RmkConfig<'static, Out>, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, ) -> ! { @@ -198,7 +198,7 @@ pub async fn run_rmk_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver, default_keymap, - encoder_map, + keyboard_config, None, spawner, @@ -206,7 +206,7 @@ pub async fn run_rmk_with_async_flash< .await; #[cfg(feature = "_esp_ble")] - initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, encoder_map, keyboard_config).await; + initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, keyboard_config).await; #[cfg(all( not(feature = "_no_usb"), @@ -218,7 +218,7 @@ pub async fn run_rmk_with_async_flash< #[cfg(not(feature = "_no_external_storage"))] flash, default_keymap, - encoder_map, + keyboard_config, ) .await; @@ -241,7 +241,7 @@ pub(crate) async fn initialize_usb_keyboard_and_run< usb_driver: D, #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + keyboard_config: RmkConfig<'static, Out>, ) -> ! { // Initialize storage and keymap @@ -250,12 +250,12 @@ pub(crate) async fn initialize_usb_keyboard_and_run< let (mut storage, keymap) = { let mut s = Storage::new(flash, default_keymap, keyboard_config.storage_config).await; let keymap = - RefCell::new(KeyMap::new_from_storage(default_keymap, encoder_map, Some(&mut s)).await); + RefCell::new(KeyMap::new_from_storage(default_keymap, Some(&mut s)).await); (s, keymap) }; #[cfg(all(not(feature = "_nrf_ble"), feature = "_no_external_storage"))] let keymap = - RefCell::new(KeyMap::::new(default_keymap, encoder_map).await); + RefCell::new(KeyMap::::new(default_keymap).await); let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); let keyboard_report_receiver = KEYBOARD_REPORT_CHANNEL.receiver(); diff --git a/rmk/src/split/central.rs b/rmk/src/split/central.rs index f5100dba..b01609b2 100644 --- a/rmk/src/split/central.rs +++ b/rmk/src/split/central.rs @@ -66,7 +66,7 @@ pub async fn run_rmk_split_central< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; TOTAL_COL]; TOTAL_ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + keyboard_config: RmkConfig<'static, Out>, #[cfg(feature = "_nrf_ble")] central_addr: [u8; 6], #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, @@ -108,7 +108,7 @@ pub async fn run_rmk_split_central< matrix, usb_driver, default_keymap, - encoder_map, + keyboard_config, Some(central_addr), spawner, @@ -121,7 +121,7 @@ pub async fn run_rmk_split_central< usb_driver, flash, default_keymap, - encoder_map, + keyboard_config, ) .await; @@ -162,7 +162,7 @@ pub async fn run_rmk_split_central_direct_pin< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; TOTAL_COL]; TOTAL_ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + keyboard_config: RmkConfig<'static, Out>, low_active: bool, #[cfg(feature = "_nrf_ble")] central_addr: [u8; 6], @@ -191,7 +191,7 @@ pub async fn run_rmk_split_central_direct_pin< matrix, usb_driver, default_keymap, - encoder_map, + keyboard_config, Some(central_addr), spawner, @@ -204,7 +204,7 @@ pub async fn run_rmk_split_central_direct_pin< usb_driver, flash, default_keymap, - encoder_map, + keyboard_config, ) .await; @@ -256,7 +256,7 @@ pub(crate) async fn initialize_usb_split_central_and_run< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] flash: F, default_keymap: &mut [[[KeyAction; TOTAL_COL]; TOTAL_ROW]; NUM_LAYER], - encoder_map: Option<&mut [[(KeyAction, KeyAction); 2]; NUM_LAYER]>, + keyboard_config: RmkConfig<'static, Out>, ) -> ! { // Initialize storage and keymap @@ -267,7 +267,7 @@ pub(crate) async fn initialize_usb_split_central_and_run< let keymap = RefCell::new( KeyMap::::new_from_storage( default_keymap, - encoder_map, + Some(&mut s), ) .await, diff --git a/rmk/src/via/vial.rs b/rmk/src/via/vial.rs index ab3a96a4..381bca74 100644 --- a/rmk/src/via/vial.rs +++ b/rmk/src/via/vial.rs @@ -1,13 +1,12 @@ use core::cell::RefCell; -use byteorder::{BigEndian, ByteOrder, LittleEndian}; +use byteorder::{ByteOrder, LittleEndian}; use defmt::{debug, info}; use num_enum::FromPrimitive; use crate::{ keymap::KeyMap, usb::descriptor::ViaReport, - via::keycode_convert::{from_via_keycode, to_via_keycode}, }; #[derive(Debug, Copy, Clone, defmt::Format, PartialEq, Eq, PartialOrd, Ord, FromPrimitive)] @@ -33,13 +32,13 @@ enum VialCommand { const VIAL_PROTOCOL_VERSION: u32 = 6; const VIAL_EP_SIZE: usize = 32; -/// + /// Note: vial uses litte endian, while via uses big endian pub(crate) fn process_vial<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize>( report: &mut ViaReport, vial_keyboard_Id: &[u8], vial_keyboard_def: &[u8], - keymap: &RefCell>, + _keymap: &RefCell>, ) { // report.output_data[0] == 0xFE -> vial commands let vial_command = VialCommand::from_primitive(report.output_data[1]); @@ -95,19 +94,19 @@ pub(crate) fn process_vial<'a, const ROW: usize, const COL: usize, const NUM_LAY VialCommand::GetEncoder => { let layer = report.output_data[2]; let index = report.output_data[3]; - debug!("Received Vial - GetEncoder, data: {}", report.output_data); + debug!("Received Vial - GetEncoder, encoder idx: {} at layer: {}", index, layer); // Get encoder value - if let Some(encoders) = &keymap.borrow().encoders { - if let Some(encoder_layer) = encoders.get(layer as usize) { - if let Some(encoder) = encoder_layer.get(index as usize) { - let clockwise = to_via_keycode(encoder.0); - BigEndian::write_u16(&mut report.input_data[0..2], clockwise); - let counter_clockwise = to_via_keycode(encoder.1); - BigEndian::write_u16(&mut report.input_data[2..4], counter_clockwise); - return; - } - } - } + // if let Some(encoders) = &keymap.borrow().encoders { + // if let Some(encoder_layer) = encoders.get(layer as usize) { + // if let Some(encoder) = encoder_layer.get(index as usize) { + // let clockwise = to_via_keycode(encoder.0); + // BigEndian::write_u16(&mut report.input_data[0..2], clockwise); + // let counter_clockwise = to_via_keycode(encoder.1); + // BigEndian::write_u16(&mut report.input_data[2..4], counter_clockwise); + // return; + // } + // } + // } // Clear returned value, aka `KeyAction::No` report.input_data.fill(0x0); @@ -116,23 +115,24 @@ pub(crate) fn process_vial<'a, const ROW: usize, const COL: usize, const NUM_LAY let layer = report.output_data[2]; let index = report.output_data[3]; let clockwise = report.output_data[4]; - if let Some(&mut mut encoders) = keymap.borrow_mut().encoders { - if let Some(&mut mut encoder_layer) = encoders.get_mut(layer as usize) { - if let Some(&mut mut encoder) = encoder_layer.get_mut(index as usize) { - if clockwise == 1 { - let keycode = BigEndian::read_u16(&report.output_data[5..7]); - let action = from_via_keycode(keycode); - info!("Setting clockwise action: {}", action); - encoder.0 = action - } else { - let keycode = BigEndian::read_u16(&report.output_data[5..7]); - let action = from_via_keycode(keycode); - info!("Setting counter-clockwise action: {}", action); - encoder.1 = action - } - } - } - } + debug!("Received Vial - SetEncoder, encoder idx: {} clockwise: {} at layer: {}", index, clockwise, layer); + // if let Some(&mut mut encoders) = keymap.borrow_mut().encoders { + // if let Some(&mut mut encoder_layer) = encoders.get_mut(layer as usize) { + // if let Some(&mut mut encoder) = encoder_layer.get_mut(index as usize) { + // if clockwise == 1 { + // let keycode = BigEndian::read_u16(&report.output_data[5..7]); + // let action = from_via_keycode(keycode); + // info!("Setting clockwise action: {}", action); + // encoder.0 = action + // } else { + // let keycode = BigEndian::read_u16(&report.output_data[5..7]); + // let action = from_via_keycode(keycode); + // info!("Setting counter-clockwise action: {}", action); + // encoder.1 = action + // } + // } + // } + // } debug!("Received Vial - SetEncoder, data: {}", report.output_data); } _ => (), From f667479fd03d95ffc4a6f8f68bc0dc7609b33179 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Fri, 3 Jan 2025 16:26:54 +0800 Subject: [PATCH 20/21] refactor: format code Signed-off-by: Haobo Gu --- rmk/src/ble/esp/mod.rs | 6 ++---- rmk/src/ble/nrf/mod.rs | 6 ++---- rmk/src/direct_pin.rs | 10 ++-------- rmk/src/keymap.rs | 4 +--- rmk/src/lib.rs | 17 ++++++----------- rmk/src/split/central.rs | 11 +++-------- rmk/src/via/vial.rs | 15 +++++++++------ 7 files changed, 25 insertions(+), 44 deletions(-) diff --git a/rmk/src/ble/esp/mod.rs b/rmk/src/ble/esp/mod.rs index 4b40080e..b0dae68d 100644 --- a/rmk/src/ble/esp/mod.rs +++ b/rmk/src/ble/esp/mod.rs @@ -44,7 +44,7 @@ pub(crate) async fn initialize_esp_ble_keyboard_with_config_and_run< >( mut matrix: M, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - + keyboard_config: RmkConfig<'static, Out>, ) -> ! { let f = Partition::new(PartitionType::Custom, Some(c"rmk")); @@ -60,9 +60,7 @@ pub(crate) async fn initialize_esp_ble_keyboard_with_config_and_run< ) .await; - let keymap = RefCell::new( - KeyMap::new_from_storage(default_keymap, Some(&mut storage)).await, - ); + let keymap = RefCell::new(KeyMap::new_from_storage(default_keymap, Some(&mut storage)).await); let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); let keyboard_report_receiver = KEYBOARD_REPORT_CHANNEL.receiver(); diff --git a/rmk/src/ble/nrf/mod.rs b/rmk/src/ble/nrf/mod.rs index f7bd438f..06a5e284 100644 --- a/rmk/src/ble/nrf/mod.rs +++ b/rmk/src/ble/nrf/mod.rs @@ -226,7 +226,7 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< mut matrix: M, #[cfg(not(feature = "_no_usb"))] usb_driver: D, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - + mut keyboard_config: RmkConfig<'static, Out>, ble_addr: Option<[u8; 6]>, spawner: Spawner, @@ -251,9 +251,7 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< // Flash and keymap configuration let flash = Flash::take(sd); let mut storage = Storage::new(flash, default_keymap, keyboard_config.storage_config).await; - let keymap = RefCell::new( - KeyMap::new_from_storage(default_keymap, Some(&mut storage)).await, - ); + let keymap = RefCell::new(KeyMap::new_from_storage(default_keymap, Some(&mut storage)).await); let mut buf: [u8; 128] = [0; 128]; diff --git a/rmk/src/direct_pin.rs b/rmk/src/direct_pin.rs index 6bcf1680..6b0fdf3e 100644 --- a/rmk/src/direct_pin.rs +++ b/rmk/src/direct_pin.rs @@ -79,7 +79,6 @@ pub async fn run_rmk_direct_pin< run_rmk_direct_pin_with_async_flash::<_, _, ROW, COL, SIZE, NUM_LAYER>( direct_pins, default_keymap, - keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -94,7 +93,6 @@ pub async fn run_rmk_direct_pin< direct_pins, usb_driver, default_keymap, - keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -109,7 +107,6 @@ pub async fn run_rmk_direct_pin< direct_pins, async_flash, default_keymap, - keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -125,7 +122,6 @@ pub async fn run_rmk_direct_pin< usb_driver, async_flash, default_keymap, - keyboard_config, low_active, #[cfg(not(feature = "_esp_ble"))] @@ -163,7 +159,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - + keyboard_config: RmkConfig<'static, Out>, low_active: bool, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, @@ -184,7 +180,6 @@ pub async fn run_rmk_direct_pin_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver, default_keymap, - keyboard_config, None, spawner, @@ -192,7 +187,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< .await; #[cfg(feature = "_esp_ble")] - initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, keyboard_config).await; + initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, keyboard_config).await; #[cfg(all( not(feature = "_no_usb"), @@ -204,7 +199,6 @@ pub async fn run_rmk_direct_pin_with_async_flash< #[cfg(not(feature = "_no_external_storage"))] flash, default_keymap, - keyboard_config, ) .await; diff --git a/rmk/src/keymap.rs b/rmk/src/keymap.rs index 2fa44b17..7fc5482b 100644 --- a/rmk/src/keymap.rs +++ b/rmk/src/keymap.rs @@ -34,9 +34,7 @@ pub(crate) struct KeyMap<'a, const ROW: usize, const COL: usize, const NUM_LAYER impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> KeyMap<'a, ROW, COL, NUM_LAYER> { - pub(crate) async fn new( - action_map: &'a mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - ) -> Self { + pub(crate) async fn new(action_map: &'a mut [[[KeyAction; COL]; ROW]; NUM_LAYER]) -> Self { KeyMap { layers: action_map, layer_state: [false; NUM_LAYER], diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index 37f5f6c1..5646fe05 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -117,7 +117,7 @@ pub async fn run_rmk< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - + keyboard_config: RmkConfig<'static, Out>, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, ) -> ! { @@ -133,7 +133,6 @@ pub async fn run_rmk< #[cfg(not(feature = "_no_external_storage"))] async_flash, default_keymap, - keyboard_config, #[cfg(not(feature = "_esp_ble"))] spawner, @@ -171,7 +170,7 @@ pub async fn run_rmk_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - + keyboard_config: RmkConfig<'static, Out>, #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, ) -> ! { @@ -198,7 +197,6 @@ pub async fn run_rmk_with_async_flash< #[cfg(not(feature = "_no_usb"))] usb_driver, default_keymap, - keyboard_config, None, spawner, @@ -206,7 +204,7 @@ pub async fn run_rmk_with_async_flash< .await; #[cfg(feature = "_esp_ble")] - initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, keyboard_config).await; + initialize_esp_ble_keyboard_with_config_and_run(matrix, default_keymap, keyboard_config).await; #[cfg(all( not(feature = "_no_usb"), @@ -218,7 +216,6 @@ pub async fn run_rmk_with_async_flash< #[cfg(not(feature = "_no_external_storage"))] flash, default_keymap, - keyboard_config, ) .await; @@ -241,7 +238,7 @@ pub(crate) async fn initialize_usb_keyboard_and_run< usb_driver: D, #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] flash: F, default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER], - + keyboard_config: RmkConfig<'static, Out>, ) -> ! { // Initialize storage and keymap @@ -249,13 +246,11 @@ pub(crate) async fn initialize_usb_keyboard_and_run< #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] let (mut storage, keymap) = { let mut s = Storage::new(flash, default_keymap, keyboard_config.storage_config).await; - let keymap = - RefCell::new(KeyMap::new_from_storage(default_keymap, Some(&mut s)).await); + let keymap = RefCell::new(KeyMap::new_from_storage(default_keymap, Some(&mut s)).await); (s, keymap) }; #[cfg(all(not(feature = "_nrf_ble"), feature = "_no_external_storage"))] - let keymap = - RefCell::new(KeyMap::::new(default_keymap).await); + let keymap = RefCell::new(KeyMap::::new(default_keymap).await); let keyboard_report_sender = KEYBOARD_REPORT_CHANNEL.sender(); let keyboard_report_receiver = KEYBOARD_REPORT_CHANNEL.receiver(); diff --git a/rmk/src/split/central.rs b/rmk/src/split/central.rs index b01609b2..497cc935 100644 --- a/rmk/src/split/central.rs +++ b/rmk/src/split/central.rs @@ -66,7 +66,7 @@ pub async fn run_rmk_split_central< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; TOTAL_COL]; TOTAL_ROW]; NUM_LAYER], - + keyboard_config: RmkConfig<'static, Out>, #[cfg(feature = "_nrf_ble")] central_addr: [u8; 6], #[cfg(not(feature = "_esp_ble"))] spawner: Spawner, @@ -108,7 +108,6 @@ pub async fn run_rmk_split_central< matrix, usb_driver, default_keymap, - keyboard_config, Some(central_addr), spawner, @@ -121,7 +120,6 @@ pub async fn run_rmk_split_central< usb_driver, flash, default_keymap, - keyboard_config, ) .await; @@ -162,7 +160,7 @@ pub async fn run_rmk_split_central_direct_pin< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(not(feature = "_no_external_storage"))] flash: F, default_keymap: &mut [[[KeyAction; TOTAL_COL]; TOTAL_ROW]; NUM_LAYER], - + keyboard_config: RmkConfig<'static, Out>, low_active: bool, #[cfg(feature = "_nrf_ble")] central_addr: [u8; 6], @@ -191,7 +189,6 @@ pub async fn run_rmk_split_central_direct_pin< matrix, usb_driver, default_keymap, - keyboard_config, Some(central_addr), spawner, @@ -204,7 +201,6 @@ pub async fn run_rmk_split_central_direct_pin< usb_driver, flash, default_keymap, - keyboard_config, ) .await; @@ -256,7 +252,7 @@ pub(crate) async fn initialize_usb_split_central_and_run< #[cfg(not(feature = "_no_usb"))] usb_driver: D, #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] flash: F, default_keymap: &mut [[[KeyAction; TOTAL_COL]; TOTAL_ROW]; NUM_LAYER], - + keyboard_config: RmkConfig<'static, Out>, ) -> ! { // Initialize storage and keymap @@ -267,7 +263,6 @@ pub(crate) async fn initialize_usb_split_central_and_run< let keymap = RefCell::new( KeyMap::::new_from_storage( default_keymap, - Some(&mut s), ) .await, diff --git a/rmk/src/via/vial.rs b/rmk/src/via/vial.rs index 381bca74..3fedf40f 100644 --- a/rmk/src/via/vial.rs +++ b/rmk/src/via/vial.rs @@ -4,10 +4,7 @@ use byteorder::{ByteOrder, LittleEndian}; use defmt::{debug, info}; use num_enum::FromPrimitive; -use crate::{ - keymap::KeyMap, - usb::descriptor::ViaReport, -}; +use crate::{keymap::KeyMap, usb::descriptor::ViaReport}; #[derive(Debug, Copy, Clone, defmt::Format, PartialEq, Eq, PartialOrd, Ord, FromPrimitive)] #[repr(u8)] @@ -94,7 +91,10 @@ pub(crate) fn process_vial<'a, const ROW: usize, const COL: usize, const NUM_LAY VialCommand::GetEncoder => { let layer = report.output_data[2]; let index = report.output_data[3]; - debug!("Received Vial - GetEncoder, encoder idx: {} at layer: {}", index, layer); + debug!( + "Received Vial - GetEncoder, encoder idx: {} at layer: {}", + index, layer + ); // Get encoder value // if let Some(encoders) = &keymap.borrow().encoders { // if let Some(encoder_layer) = encoders.get(layer as usize) { @@ -115,7 +115,10 @@ pub(crate) fn process_vial<'a, const ROW: usize, const COL: usize, const NUM_LAY let layer = report.output_data[2]; let index = report.output_data[3]; let clockwise = report.output_data[4]; - debug!("Received Vial - SetEncoder, encoder idx: {} clockwise: {} at layer: {}", index, clockwise, layer); + debug!( + "Received Vial - SetEncoder, encoder idx: {} clockwise: {} at layer: {}", + index, clockwise, layer + ); // if let Some(&mut mut encoders) = keymap.borrow_mut().encoders { // if let Some(&mut mut encoder_layer) = encoders.get_mut(layer as usize) { // if let Some(&mut mut encoder) = encoder_layer.get_mut(index as usize) { From e01373e0f82e0249ae55afa5ae89a2ea6da45e0d Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Fri, 3 Jan 2025 16:44:04 +0800 Subject: [PATCH 21/21] fix(matrix): fix async public trait Signed-off-by: Haobo Gu --- rmk/src/matrix.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/rmk/src/matrix.rs b/rmk/src/matrix.rs index 7de921d7..667ee609 100644 --- a/rmk/src/matrix.rs +++ b/rmk/src/matrix.rs @@ -4,6 +4,7 @@ use crate::{ keyboard::KEY_EVENT_CHANNEL, CONNECTION_STATE, }; +use core::future::Future; use defmt::{info, Format}; use embassy_time::{Instant, Timer}; use embedded_hal::digital::{InputPin, OutputPin}; @@ -20,24 +21,28 @@ pub trait MatrixTrait { const COL: usize; // Wait for USB or BLE really connected - async fn wait_for_connected(&self) { - while !CONNECTION_STATE.load(core::sync::atomic::Ordering::Acquire) { - embassy_time::Timer::after_millis(100).await; + fn wait_for_connected(&self) -> impl Future { + async { + while !CONNECTION_STATE.load(core::sync::atomic::Ordering::Acquire) { + embassy_time::Timer::after_millis(100).await; + } + info!("Connected, start scanning matrix"); } - info!("Connected, start scanning matrix"); } // Run the matrix - async fn run(&mut self) { - // We don't check disconnected state because disconnection means the task will be dropped - loop { - self.wait_for_connected().await; - self.scan().await; + fn run(&mut self) -> impl Future { + async { + // We don't check disconnected state because disconnection means the task will be dropped + loop { + self.wait_for_connected().await; + self.scan().await; + } } } // Do matrix scanning, save the result in matrix's key_state field. - async fn scan(&mut self); + fn scan(&mut self) -> impl Future; // Read key state at position (row, col) fn get_key_state(&mut self, row: usize, col: usize) -> KeyState; @@ -56,7 +61,7 @@ pub trait MatrixTrait { } #[cfg(feature = "async_matrix")] - async fn wait_for_key(&mut self); + fn wait_for_key(&mut self) -> impl Future; } /// KeyState represents the state of a key.