smart_keymap/
lib.rs

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