Skip to main content

keyberon_smart_keyboard/input/
smart_keymap.rs

1use core::fmt::Debug;
2use core::ops::Index;
3
4use smart_keymap::input;
5use smart_keymap::key;
6use smart_keymap::keymap::{self, Keymap, KeymapOutput, SetKeymapContext};
7
8/// Callbacks for the keymap.
9pub struct KeymapCallbacks {
10    /// Callback for resetting keyboard state.
11    pub reset: Option<fn() -> ()>,
12    /// Callback for entering the bootloader.
13    pub reset_to_bootloader: Option<fn() -> ()>,
14}
15
16/// The keyboard "backend", manages the keyboard from the events received
17/// (presses/releases of coordinates on a keyboard layout).
18/// through to listing HID scancodes to report using HIDs.
19///
20/// Type parameters match [Keymap].
21#[derive(Debug)]
22pub struct KeyboardBackend<
23    I: Index<usize, Output = R> = [smart_keymap::init::Ref; smart_keymap::init::KEY_COUNT],
24    R = smart_keymap::init::Ref,
25    Ctx = smart_keymap::init::Context,
26    Ev: Debug = smart_keymap::init::Event,
27    PKS = smart_keymap::init::PendingKeyState,
28    KS = smart_keymap::init::KeyState,
29    S = smart_keymap::init::System,
30> {
31    keymap: Keymap<I, R, Ctx, Ev, PKS, KS, S>,
32    keymap_output: KeymapOutput,
33}
34
35impl Default for KeyboardBackend {
36    fn default() -> Self {
37        Self::new()
38    }
39}
40
41impl KeyboardBackend {
42    /// Constructs a new keyboard backend using the board keymap
43    ///  ([smart_keymap::new_keymap]).
44    pub fn new() -> Self {
45        Self::new_with_keymap(smart_keymap::new_keymap())
46    }
47}
48
49impl<I, R, Ctx, Ev, PKS, KS, S> KeyboardBackend<I, R, Ctx, Ev, PKS, KS, S>
50where
51    I: Index<usize, Output = R>,
52    Ev: Debug,
53{
54    /// Constructs a new keyboard backend with the given keymap.
55    pub fn new_with_keymap(keymap: Keymap<I, R, Ctx, Ev, PKS, KS, S>) -> Self {
56        Self {
57            keymap,
58            keymap_output: KeymapOutput::default(),
59        }
60    }
61}
62
63impl<I, R, Ctx, Ev, PKS, KS, S> KeyboardBackend<I, R, Ctx, Ev, PKS, KS, S>
64where
65    I: Debug + Index<usize, Output = R>,
66    R: Copy + Debug,
67    Ctx: Debug + key::Context<Event = Ev> + SetKeymapContext,
68    Ev: Copy + Debug,
69    PKS: Debug,
70    KS: Copy + Debug + From<key::NoOpKeyState>,
71    S: key::System<R, Ref = R, Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS>,
72{
73    /// Set the keymap callbacks.
74    pub fn set_callbacks(&mut self, callbacks: KeymapCallbacks) {
75        use keymap::KeymapCallback;
76        if let Some(callback_fn) = callbacks.reset {
77            self.keymap.set_callback(KeymapCallback::Reset, callback_fn);
78        }
79        if let Some(callback_fn) = callbacks.reset_to_bootloader {
80            self.keymap
81                .set_callback(KeymapCallback::ResetToBootloader, callback_fn);
82        }
83    }
84
85    /// Register a key event.
86    pub fn event(&mut self, event: input::Event) {
87        self.keymap.handle_input(event);
88    }
89
90    /// A time event.
91    ///
92    /// This method must be called regularly, typically every millisecond.
93    ///
94    /// Returns true if the pressed_key_codes have changed.
95    pub fn tick(&mut self) -> bool {
96        self.keymap.tick();
97
98        let keymap_output = self.keymap.report_output();
99
100        let old_keymap_output = core::mem::replace(&mut self.keymap_output, keymap_output);
101
102        old_keymap_output != self.keymap_output
103    }
104
105    /// Returns the current keymap output.
106    pub fn keymap_output(&self) -> &KeymapOutput {
107        &self.keymap_output
108    }
109}
110
111/// Constructs a [input::Event] from a [keyberon::layout::Event],
112///  using a map from row, column to (maybe) keymap index.
113pub fn keymap_index_of<const COLS: usize, const ROWS: usize>(
114    indices: &[[Option<u16>; COLS]; ROWS],
115    ev: keyberon::layout::Event,
116) -> Option<input::Event> {
117    match ev {
118        keyberon::layout::Event::Press(r, c) => {
119            indices[r as usize][c as usize].map(|keymap_index| input::Event::Press { keymap_index })
120        }
121        keyberon::layout::Event::Release(r, c) => indices[r as usize][c as usize]
122            .map(|keymap_index| input::Event::Release { keymap_index }),
123    }
124}