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}