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/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 a2692a41..c8c459c2 100644 --- a/examples/use_rust/nrf52840_ble/src/main.rs +++ b/examples/use_rust/nrf52840_ble/src/main.rs @@ -21,7 +21,8 @@ use panic_probe as _; use rmk::{ ble::SOFTWARE_VBUS, config::{BleBatteryConfig, KeyboardUsbConfig, RmkConfig, StorageConfig, VialConfig}, - run_rmk, + input_device::{rotary_encoder::RotaryEncoder, InputDevice}, + run_devices, run_rmk, }; use vial::{VIAL_KEYBOARD_DEF, VIAL_KEYBOARD_ID}; @@ -106,13 +107,31 @@ async fn main(spawner: Spawner) { ..Default::default() }; - run_rmk( - input_pins, - output_pins, - driver, - &mut keymap::get_default_keymap(), - keyboard_config, - 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)); + + 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; } + +struct MyDevice {} +impl InputDevice for MyDevice { + async fn run(&mut self) { + loop { + info!("Hi my device"); + embassy_time::Timer::after_secs(1).await; + } + } +} 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)>, +} 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..04423785 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::keyboard::KeyEvent; +use crate::keyboard::KEY_EVENT_CHANNEL; +use crate::event::KeyEvent; use crate::matrix::KeyState; use crate::MatrixTrait; use crate::RmkConfig; @@ -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/event.rs b/rmk/src/event.rs new file mode 100644 index 00000000..9623b634 --- /dev/null +++ b/rmk/src/event.rs @@ -0,0 +1,64 @@ +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, +} diff --git a/rmk/src/input_device/mod.rs b/rmk/src/input_device/mod.rs new file mode 100644 index 00000000..8d6ea4cc --- /dev/null +++ b/rmk/src/input_device/mod.rs @@ -0,0 +1,77 @@ +//! 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; + +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), +/// 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! 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)*)) + }; +} diff --git a/rmk/src/input_device/rotary_encoder.rs b/rmk/src/input_device/rotary_encoder.rs new file mode 100644 index 00000000..d5cd5490 --- /dev/null +++ b/rmk/src/input_device/rotary_encoder.rs @@ -0,0 +1,203 @@ +//! The rotary encoder implementation is from: https://github.com/leshow/rotary-encoder-hal/blob/master/src/lib.rs +//! + +use embedded_hal::digital::InputPin; +#[cfg(feature = "async_matrix")] +use embedded_hal_async::digital::Wait; + +use crate::event::KeyEvent; +use crate::keyboard::KEY_EVENT_CHANNEL; + +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)] +// #[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` +#[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()`. + /// + /// `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. + /// + /// `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, + } + } + + /// 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) + } + + /// 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 { + #[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: 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; + } + } +} diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index ef59811d..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,25 +19,14 @@ 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(crate) struct KeyEvent { - pub(crate) row: u8, - pub(crate) col: u8, - pub(crate) pressed: bool, -} pub(crate) const EVENT_CHANNEL_SIZE: usize = 32; -pub(crate) const REPORT_CHANNEL_SIZE: usize = 32; +pub static KEY_EVENT_CHANNEL: Channel = + Channel::new(); -pub(crate) 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 +250,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 +518,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 +547,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 +585,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 +650,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 +701,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 +914,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/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 05ef8fec..2198c638 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; @@ -63,9 +63,11 @@ pub mod ble; pub mod config; mod debounce; pub mod direct_pin; +pub mod event; mod flash; mod hid; -mod keyboard; +pub mod input_device; +pub mod keyboard; mod keyboard_macro; pub mod keycode; mod keymap; @@ -249,8 +251,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..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}; @@ -216,7 +214,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..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}; @@ -269,8 +270,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 +379,7 @@ impl< self.key_states[out_idx][in_idx], ); - key_event_channel + KEY_EVENT_CHANNEL .send(KeyEvent { row, col, @@ -609,7 +610,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..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; @@ -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/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 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 {