Skip to content

Commit

Permalink
Initial migration from const-generics to typenum
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben-PH committed Dec 15, 2024
1 parent 6ea066a commit aad32fd
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 190 deletions.
2 changes: 2 additions & 0 deletions rmk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ esp-idf-svc = { version = "0.49", default-features = false, optional = true }

# Document feature
document-features = "0.2"
typenum = { version = "1.17.0", features = ["no_std"] }
generic-array = "1.1.1"

[package.metadata.docs.rs]
features = ["split"]
Expand Down
15 changes: 10 additions & 5 deletions rmk/src/debounce/default_bouncer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use embassy_time::Instant;
use generic_array::{sequence::GenericSequence, ArrayLength, GenericArray};
use typenum::NonZero;

use crate::matrix::KeyState;

Expand Down Expand Up @@ -28,18 +30,21 @@ impl DebounceCounter {
}

/// Default per-key debouncer. The debouncing algorithm is same as ZMK's [default debouncer](https://github.com/zmkfirmware/zmk/blob/19613128b901723f7b78c136792d72e6ca7cf4fc/app/module/lib/zmk_debounce/debounce.c)
pub(crate) struct DefaultDebouncer<const INPUT_PIN_NUM: usize, const OUTPUT_PIN_NUM: usize> {
pub(crate) struct DefaultDebouncer<
InputPinNum: ArrayLength + NonZero,
OutputPinNum: ArrayLength + NonZero,
> {
last_ms: u32,
counters: [[DebounceCounter; INPUT_PIN_NUM]; OUTPUT_PIN_NUM],
counters: GenericArray<GenericArray<DebounceCounter, InputPinNum>, OutputPinNum>,
}

impl<const INPUT_PIN_NUM: usize, const OUTPUT_PIN_NUM: usize> DebouncerTrait
for DefaultDebouncer<INPUT_PIN_NUM, OUTPUT_PIN_NUM>
impl<InputPinNum: ArrayLength + NonZero, OutputPinNum: ArrayLength + NonZero> DebouncerTrait
for DefaultDebouncer<InputPinNum, OutputPinNum>
{
/// Create a default debouncer
fn new() -> Self {
DefaultDebouncer {
counters: [[DebounceCounter(0); INPUT_PIN_NUM]; OUTPUT_PIN_NUM],
counters: GenericArray::generate(|_| GenericArray::generate(|_| DebounceCounter(0))),
last_ms: 0,
}
}
Expand Down
75 changes: 35 additions & 40 deletions rmk/src/direct_pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ use embedded_hal::digital::{InputPin, OutputPin};
use embedded_storage::nor_flash::NorFlash;
#[cfg(not(feature = "_no_external_storage"))]
use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash;
use generic_array::sequence::GenericSequence;
use generic_array::ArrayLength;
use generic_array::GenericArray;
use typenum::NonZero;
#[cfg(feature = "async_matrix")]
use {embassy_futures::select::select_slice, embedded_hal_async::digital::Wait, heapless::Vec};

Expand All @@ -54,18 +58,14 @@ pub async fn run_rmk_direct_pin<
Out: OutputPin,
#[cfg(not(feature = "_no_usb"))] D: Driver<'static>,
#[cfg(not(feature = "_no_external_storage"))] F: NorFlash,
const ROW: usize,
const COL: usize,
// `let mut futs: Vec<_, {ROW * COL}>` is invalid because of
// generic parameters may not be used in const operations.
// Maybe we can use nightly only feature `generic_const_exprs`
const SIZE: usize,
const NUM_LAYER: usize,
Row: ArrayLength + NonZero,
Col: ArrayLength + NonZero,
NumLayers: ArrayLength + NonZero,
>(
direct_pins: [[Option<In>; COL]; ROW],
direct_pins: GenericArray<GenericArray<Option<In>, Col>, Row>,
#[cfg(not(feature = "_no_usb"))] usb_driver: D,
#[cfg(not(feature = "_no_external_storage"))] flash: F,
default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER],
default_keymap: &mut GenericArray<GenericArray<GenericArray<KeyAction, Col>, Row>, NumLayers>,
keyboard_config: RmkConfig<'static, Out>,
low_active: bool,
#[cfg(not(feature = "_esp_ble"))] spawner: Spawner,
Expand All @@ -76,7 +76,7 @@ pub async fn run_rmk_direct_pin<

#[cfg(all(feature = "_no_usb", feature = "_no_external_storage"))]
{
run_rmk_direct_pin_with_async_flash::<_, _, ROW, COL, SIZE, NUM_LAYER>(
run_rmk_direct_pin_with_async_flash::<_, _, Row, Col, NumLayers>(
direct_pins,
default_keymap,
keyboard_config,
Expand All @@ -89,7 +89,7 @@ pub async fn run_rmk_direct_pin<

#[cfg(all(not(feature = "_no_usb"), feature = "_no_external_storage"))]
{
run_rmk_direct_pin_with_async_flash::<_, _, _, ROW, COL, SIZE, NUM_LAYER>(
run_rmk_direct_pin_with_async_flash::<_, _, _, Row, Col, NumLayers>(
direct_pins,
usb_driver,
default_keymap,
Expand All @@ -103,7 +103,7 @@ pub async fn run_rmk_direct_pin<

#[cfg(all(feature = "_no_usb", not(feature = "_no_external_storage")))]
{
run_rmk_direct_pin_with_async_flash::<_, _, _, ROW, COL, SIZE, NUM_LAYER>(
run_rmk_direct_pin_with_async_flash::<_, _, _, Row, Col, NumLayers>(
direct_pins,
async_flash,
default_keymap,
Expand All @@ -117,7 +117,7 @@ pub async fn run_rmk_direct_pin<

#[cfg(all(not(feature = "_no_usb"), not(feature = "_no_external_storage")))]
{
run_rmk_direct_pin_with_async_flash::<_, _, _, _, ROW, COL, SIZE, NUM_LAYER>(
run_rmk_direct_pin_with_async_flash::<_, _, _, _, Row, Col, NumLayers>(
direct_pins,
usb_driver,
async_flash,
Expand Down Expand Up @@ -150,27 +150,26 @@ pub async fn run_rmk_direct_pin_with_async_flash<
Out: OutputPin,
#[cfg(not(feature = "_no_usb"))] D: Driver<'static>,
#[cfg(not(feature = "_no_external_storage"))] F: AsyncNorFlash,
const ROW: usize,
const COL: usize,
const SIZE: usize,
const NUM_LAYER: usize,
Row: NonZero + ArrayLength,
Col: NonZero + ArrayLength,
NumLayers: NonZero + ArrayLength,
>(
direct_pins: [[Option<In>; COL]; ROW],
direct_pins: GenericArray<GenericArray<Option<In>, Col>, Row>,
#[cfg(not(feature = "_no_usb"))] usb_driver: D,
#[cfg(not(feature = "_no_external_storage"))] flash: F,
default_keymap: &mut [[[KeyAction; COL]; ROW]; NUM_LAYER],
default_keymap: &mut GenericArray<GenericArray<GenericArray<KeyAction, Col>, Row>, NumLayers>,
keyboard_config: RmkConfig<'static, Out>,
low_active: bool,
#[cfg(not(feature = "_esp_ble"))] spawner: Spawner,
) -> ! {
// Create the debouncer
#[cfg(feature = "rapid_debouncer")]
let debouncer = RapidDebouncer::<COL, ROW>::new();
let debouncer = RapidDebouncer::<Col, Row>::new();
#[cfg(not(feature = "rapid_debouncer"))]
let debouncer = DefaultDebouncer::<COL, ROW>::new();
let debouncer = DefaultDebouncer::<Col, Row>::new();

// Keyboard matrix
let matrix = DirectPinMatrix::<_, _, ROW, COL, SIZE>::new(direct_pins, debouncer, low_active);
let matrix = DirectPinMatrix::<_, _, Row, Col>::new(direct_pins, debouncer, low_active);

// Dispatch according to chip and communication type
#[cfg(feature = "_nrf_ble")]
Expand Down Expand Up @@ -211,16 +210,15 @@ pub(crate) struct DirectPinMatrix<
#[cfg(feature = "async_matrix")] In: Wait + InputPin,
#[cfg(not(feature = "async_matrix"))] In: InputPin,
D: DebouncerTrait,
const ROW: usize,
const COL: usize,
const SIZE: usize,
Row: ArrayLength + NonZero,
Col: ArrayLength + NonZero,
> {
/// Input pins of the pcb matrix
direct_pins: [[Option<In>; COL]; ROW],
direct_pins: GenericArray<GenericArray<Option<In>, Col>, Row>,
/// Debouncer
debouncer: D,
/// Key state matrix
key_states: [[KeyState; COL]; ROW],
key_states: GenericArray<GenericArray<KeyState, Col>, Row>,
/// Start scanning
scan_start: Option<Instant>,
/// Pin active level
Expand All @@ -231,21 +229,20 @@ impl<
#[cfg(not(feature = "async_matrix"))] In: InputPin,
#[cfg(feature = "async_matrix")] In: Wait + InputPin,
D: DebouncerTrait,
const ROW: usize,
const COL: usize,
const SIZE: usize,
> DirectPinMatrix<In, D, ROW, COL, SIZE>
Row: ArrayLength + NonZero,
Col: ArrayLength + NonZero,
> DirectPinMatrix<In, D, Row, Col>
{
/// Create a matrix from input and output pins.
pub(crate) fn new(
direct_pins: [[Option<In>; COL]; ROW],
direct_pins: GenericArray<GenericArray<Option<In>, Col>, Row>,
debouncer: D,
low_active: bool,
) -> Self {
DirectPinMatrix {
direct_pins,
debouncer,
key_states: [[KeyState::new(); COL]; ROW],
key_states: GenericArray::generate(|_| GenericArray::generate(|_| KeyState::new())),
scan_start: None,
low_active,
}
Expand All @@ -256,14 +253,12 @@ impl<
#[cfg(not(feature = "async_matrix"))] In: InputPin,
#[cfg(feature = "async_matrix")] In: Wait + InputPin,
D: DebouncerTrait,
const ROW: usize,
const COL: usize,
const SIZE: usize,
> MatrixTrait for DirectPinMatrix<In, D, ROW, COL, SIZE>
Row: ArrayLength + NonZero,
Col: ArrayLength + NonZero,
> MatrixTrait for DirectPinMatrix<In, D, Row, Col>
{
const ROW: usize = ROW;
const COL: usize = COL;

type Row = Row;
type Col = Col;
#[cfg(feature = "async_matrix")]
async fn wait_for_key(&mut self) {
if let Some(start_time) = self.scan_start {
Expand Down
32 changes: 22 additions & 10 deletions rmk/src/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::config::BehaviorConfig;
use crate::{
action::{Action, KeyAction},
hid::{ConnectionType, HidWriterWrapper},
keyboard_macro::{MacroOperation, NUM_MACRO},
keyboard_macro::{MacroOperation, NumMacro},
keycode::{KeyCode, ModifierCombination},
keymap::KeyMap,
usb::descriptor::{CompositeReport, CompositeReportType, ViaReport},
Expand All @@ -16,9 +16,12 @@ use embassy_sync::{
channel::{Channel, Receiver, Sender},
};
use embassy_time::{Instant, Timer};
use generic_array::sequence::GenericSequence;
use generic_array::{ArrayLength, GenericArray};
use heapless::{FnvIndexMap, Vec};
use postcard::experimental::max_size::MaxSize;
use serde::{Deserialize, Serialize};
use typenum::NonZero;
use usbd_hid::descriptor::KeyboardReport;

#[derive(Serialize, Deserialize, Clone, Copy, Debug, Format, MaxSize)]
Expand Down Expand Up @@ -118,9 +121,14 @@ pub(crate) async fn write_other_report_to_host<W: HidWriterWrapper>(
}
}

pub(crate) struct Keyboard<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> {
pub(crate) struct Keyboard<
'a,
Row: NonZero + ArrayLength,
Col: NonZero + ArrayLength,
NumLayers: NonZero + ArrayLength,
> {
/// Keymap
pub(crate) keymap: &'a RefCell<KeyMap<'a, ROW, COL, NUM_LAYER>>,
pub(crate) keymap: &'a RefCell<KeyMap<'a, Row, Col, NumLayers>>,

/// Report Sender
pub(crate) sender:
Expand All @@ -130,7 +138,7 @@ pub(crate) struct Keyboard<'a, const ROW: usize, const COL: usize, const NUM_LAY
unprocessed_events: Vec<KeyEvent, 16>,

/// Timer which records the timestamp of key changes
pub(crate) timer: [[Option<Instant>; ROW]; COL],
pub(crate) timer: GenericArray<GenericArray<Option<Instant>, Row>, Col>,

/// Record the timestamp of last release, (event, is_modifier, timestamp)
last_release: (KeyEvent, bool, Option<Instant>),
Expand Down Expand Up @@ -167,18 +175,22 @@ pub(crate) struct Keyboard<'a, const ROW: usize, const COL: usize, const NUM_LAY
mouse_wheel_move_delta: i8,
}

impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize>
Keyboard<'a, ROW, COL, NUM_LAYER>
impl<
'a,
Row: NonZero + ArrayLength,
Col: NonZero + ArrayLength,
NumLayers: NonZero + ArrayLength,
> Keyboard<'a, Row, Col, NumLayers>
{
pub(crate) fn new(
keymap: &'a RefCell<KeyMap<'a, ROW, COL, NUM_LAYER>>,
keymap: &'a RefCell<KeyMap<'a, Row, Col, NumLayers>>,
sender: &'a Sender<'a, CriticalSectionRawMutex, KeyboardReportMessage, REPORT_CHANNEL_SIZE>,
behavior: BehaviorConfig,
) -> Self {
Keyboard {
keymap,
sender,
timer: [[None; ROW]; COL],
timer: GenericArray::generate(|_| GenericArray::generate(|_| None)),
last_release: (
KeyEvent {
row: 0,
Expand Down Expand Up @@ -397,7 +409,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize>
if key_event.pressed {
// Disable all layers except the default layer
let default_layer = self.keymap.borrow().get_default_layer();
for i in 0..NUM_LAYER as u8 {
for i in 0..NumLayers::U8 {
if i != default_layer {
self.keymap.borrow_mut().deactivate_layer(i);
}
Expand Down Expand Up @@ -936,7 +948,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize>

// Get macro index
if let Some(macro_idx) = key.as_macro_index() {
if macro_idx as usize >= NUM_MACRO {
if macro_idx as usize >= NumMacro {
error!("Macro idx invalid: {}", macro_idx);
return;
}
Expand Down
4 changes: 2 additions & 2 deletions rmk/src/keyboard_macro.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::keycode::KeyCode;

// Default macro space size
pub(crate) const MACRO_SPACE_SIZE: usize = 256;
pub(crate) type MacroSpaceSize = typenum::U256;

// Default number of keyboard macros
pub(crate) const NUM_MACRO: usize = 8;
pub(crate) const NumMacro: usize = 8;

pub(crate) enum MacroOperation {
Press(KeyCode),
Expand Down
Loading

0 comments on commit aad32fd

Please sign in to comment.