Skip to main content

smart_keymap/
lib.rs

1#![warn(missing_docs)]
2#![warn(clippy::unwrap_used)]
3#![warn(clippy::expect_used)]
4
5//! Smart Keymap library.
6//!
7//! A "smart keyboard" is a keyboard where the keys can perform
8//!  multiple actions, depending on the context.
9//! Features such as layering, tap-hold, and tap-dance are
10//!  examples of smart keyboard functionality.
11//!
12//! The smart keymap library provides an interface for the "smart keymap"
13//!  part of smart keyboard firmware.
14//! i.e. the part that takes key presses and releases as input,
15//!  and outputs HID keyboard reports (or other smart keyboard outputs).
16//!
17//! This crate can be used directly with Rust, or built as a C library.
18//!
19//! # Usage as a C library
20//!
21//! ## Custom Keymap
22//!
23//! When used as a C library, the library should be built by setting
24//!  the environment variable `SMART_KEYMAP_CUSTOM_KEYMAP` to the path
25//!  of a custom keymap file.
26//!
27//! `SMART_KEYMAP_CUSTOM_KEYMAP` can be set either to a `.ncl` file,
28//!  or to a `.rs` file (generated using the scripts under `ncl/`).
29//!
30//! ## Keyboard Firmware Implementation
31//!
32//! When used as a C library, the firmware should call to
33//!  `keymap_init`, `keymap_register_input_keypress`, `keymap_register_input_keyrelease`,
34//!  and `keymap_tick` functions.
35//! The `keymap_tick` function should be called every ms, and should copy the
36//!  HID keyboard report to the given buffer.
37//!
38//! # Implementation Overview
39//!
40//! The heart of the library is the [key] module,
41//! and its [key::System] trait.
42//!
43//! Implementors are then aggregated by [key::composite],
44//! which is used by the [keymap] module.
45
46#![cfg_attr(not(feature = "std"), no_std)]
47
48/// Structs for input to the keymap.
49pub mod input;
50/// Smart key interface and implementations.
51///
52/// The core interface for the smart keymap library is [key::System],
53///  and its associated [key::Context], `PendingKeyState`, and [key::KeyState] types.
54/// Together, these are used to define smart key behaviour.
55pub mod key;
56/// Keymap implementation.
57pub mod keymap;
58
59/// Split keyboard support.
60pub mod split;
61
62/// A helper value type for Copy-able slices.
63pub mod slice;
64
65/// Types and initial data used for constructing a [keymap::Keymap].
66/// cbindgen:ignore
67#[cfg(not(custom_keymap))]
68pub mod init {
69    use crate as smart_keymap;
70
71    use smart_keymap::key::composite;
72    use smart_keymap::key::keyboard;
73    use smart_keymap::keymap;
74
75    use composite as key_system;
76
77    /// Number of instructions used by the [crate::key::automation] implementation.
78    pub const AUTOMATION_INSTRUCTION_COUNT: usize = 1024;
79
80    /// Number of layers supported by the [crate::key::layered] implementation.
81    pub const LAYERED_LAYER_COUNT: usize = 8;
82
83    /// The maximum number of keys in a chord.
84    pub const CHORDED_MAX_CHORD_SIZE: usize = 16;
85
86    /// The maximum number of chords.
87    pub const CHORDED_MAX_CHORDS: usize = 4;
88
89    /// The maximum number of overlapping chords for a chorded key.
90    pub const CHORDED_MAX_OVERLAPPING_CHORD_SIZE: usize = 16;
91
92    /// The tap-dance definitions.
93    pub const TAP_DANCE_MAX_DEFINITIONS: usize = 3;
94
95    pub use key_system::Ref;
96
97    pub use key_system::Context;
98
99    pub use key_system::Event;
100
101    pub use key_system::PendingKeyState;
102
103    pub use key_system::KeyState;
104
105    /// Max number of data entries for each system.
106    pub const DATA_LEN: usize = 0;
107
108    /// Alias for the System type
109    pub type System = key_system::System<
110        key_system::KeyArrays<
111            DATA_LEN,
112            DATA_LEN,
113            DATA_LEN,
114            DATA_LEN,
115            DATA_LEN,
116            DATA_LEN,
117            DATA_LEN,
118            DATA_LEN,
119            DATA_LEN,
120            DATA_LEN,
121        >,
122    >;
123
124    /// The number of keys in the keymap.
125    pub const KEY_COUNT: usize = 1;
126
127    /// A tuples KeysN value with keys. Without a custom keymap, just the letter 'A'.
128    pub const KEY_REFS: [Ref; KEY_COUNT] = [Ref::Keyboard(keyboard::Ref::KeyCode(0x04))];
129
130    /// Config used to construct initial context.
131    pub const CONFIG: key_system::Config = key_system::Config::new();
132
133    /// Initial [Context] value.
134    pub const CONTEXT: Context = key_system::Context::from_config(CONFIG);
135
136    /// Initial [Context] value.
137    pub const SYSTEM: System = System::array_based(
138        smart_keymap::key::automation::System::new([]),
139        smart_keymap::key::callback::System::new([]),
140        smart_keymap::key::chorded::System::new([], []),
141        smart_keymap::key::keyboard::System::new([]),
142        smart_keymap::key::layered::System::new([], []),
143        smart_keymap::key::sticky::System::new([]),
144        smart_keymap::key::tap_dance::System::new([]),
145        smart_keymap::key::tap_hold::System::new([]),
146    );
147
148    /// Alias for the [keymap::Keymap] type.
149    pub type Keymap =
150        keymap::Keymap<[Ref; KEY_COUNT], Ref, Context, Event, PendingKeyState, KeyState, System>;
151}
152
153#[cfg(custom_keymap)]
154include!(concat!(env!("OUT_DIR"), "/keymap.rs"));
155
156pub use init::{Keymap, CONTEXT, KEY_REFS, SYSTEM};
157
158/// Constructs a new keymap;
159pub const fn new_keymap() -> Keymap {
160    Keymap::new(KEY_REFS, CONTEXT, SYSTEM)
161}