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}