Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial migration from const-generics to typenum #189

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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