smart_keymap/key/
automation.rs

1use core::fmt::Debug;
2use core::ops::Index;
3
4use serde::Deserialize;
5
6use crate::input;
7use crate::key;
8
9const EXECUTION_QUEUE_SIZE: usize = 8;
10
11/// Reference for a automation key.
12#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
13pub struct Ref(pub u8);
14
15/// Value describing an automation key execution.
16#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
17pub struct Execution {
18    /// The start index into the instructions array.
19    pub start: u16,
20    /// The number of instructions to execute.
21    pub length: u16,
22}
23
24impl Execution {
25    /// An empty execution.
26    pub const EMPTY: Self = Self {
27        start: 0,
28        length: 0,
29    };
30
31    /// Returns true if the execution is empty (length == 0).
32    pub const fn is_empty(&self) -> bool {
33        self.length == 0
34    }
35
36    /// Increments the execution to the next instruction.
37    pub fn incr(&mut self) {
38        if self.length > 0 {
39            self.start += 1;
40            self.length -= 1;
41        }
42    }
43}
44
45/// Instructions for a automation key.
46#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
47pub struct KeyInstructions {
48    /// The automation instructions to execute when the key is pressed.
49    pub on_press: Execution,
50    /// The automation instructions to execute while the key is pressed.
51    pub while_pressed: Execution,
52    /// The automation instructions to execute when the key is released.
53    pub on_release: Execution,
54}
55
56/// Definition for a automation key.
57#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
58pub struct Key {
59    /// The automation instructions for the key.
60    pub automation_instructions: KeyInstructions,
61}
62
63/// An instruction for a automation key.
64#[derive(Deserialize, Debug, Default, Clone, Copy, PartialEq)]
65pub enum Instruction {
66    /// No operation.
67    #[default]
68    NoOp,
69    /// Press a key.
70    Press(key::KeyOutput),
71    /// Release a key.
72    Release(key::KeyOutput),
73    /// Taps a key.
74    Tap(key::KeyOutput),
75    /// Wait for a number of ticks.
76    Wait(u16),
77}
78
79/// Config for automation keys.
80#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
81pub struct Config<const INSTRUCTION_COUNT: usize> {
82    /// Concatenation of all the automation key instructions.
83    ///
84    /// Automation keys' instructions are defined by start+len into this array.
85    #[serde(deserialize_with = "deserialize_instructions")]
86    pub instructions: [Instruction; INSTRUCTION_COUNT],
87
88    /// Duration (in ticks) of each instruction.
89    #[serde(default = "default_instruction_duration")]
90    pub instruction_duration: u16,
91}
92
93/// Constructs an array of instructions for the given array.
94pub const fn instructions<const N: usize, const INSTRUCTION_COUNT: usize>(
95    instructions: [Instruction; N],
96) -> [Instruction; INSTRUCTION_COUNT] {
97    let mut cfg_instructions: [Instruction; INSTRUCTION_COUNT] =
98        [Instruction::NoOp; INSTRUCTION_COUNT];
99
100    if N > INSTRUCTION_COUNT {
101        panic!("Too many instructions for instructions array");
102    }
103
104    let mut i = 0;
105
106    while i < N {
107        cfg_instructions[i] = instructions[i];
108        i += 1;
109    }
110
111    cfg_instructions
112}
113
114/// Deserialize instructions.
115fn deserialize_instructions<'de, D, const INSTRUCTION_COUNT: usize>(
116    deserializer: D,
117) -> Result<[Instruction; INSTRUCTION_COUNT], D::Error>
118where
119    D: serde::Deserializer<'de>,
120{
121    let instructions_vec: heapless::Vec<Instruction, INSTRUCTION_COUNT> =
122        Deserialize::deserialize(deserializer)?;
123
124    let mut instructions_array: [Instruction; INSTRUCTION_COUNT] =
125        [Instruction::NoOp; INSTRUCTION_COUNT];
126    for (i, instruction) in instructions_vec.iter().enumerate() {
127        instructions_array[i] = *instruction;
128    }
129
130    Ok(instructions_array)
131}
132
133fn default_instruction_duration() -> u16 {
134    DEFAULT_INSTRUCTION_DURATION
135}
136
137/// The default instruction duration.
138pub const DEFAULT_INSTRUCTION_DURATION: u16 = 10;
139
140impl<const INSTRUCTION_COUNT: usize> Config<INSTRUCTION_COUNT> {
141    /// Constructs a new default [Config].
142    pub const fn new() -> Self {
143        Self {
144            instructions: [{ Instruction::NoOp }; INSTRUCTION_COUNT],
145            instruction_duration: DEFAULT_INSTRUCTION_DURATION,
146        }
147    }
148}
149
150impl<const INSTRUCTION_COUNT: usize> Default for Config<INSTRUCTION_COUNT> {
151    fn default() -> Self {
152        Self::new()
153    }
154}
155
156/// Context for automation keys.
157#[derive(Debug, Clone, Copy, PartialEq)]
158pub struct Context<const INSTRUCTION_COUNT: usize> {
159    config: Config<INSTRUCTION_COUNT>,
160    execution_queue: [Execution; EXECUTION_QUEUE_SIZE],
161}
162
163impl<const INSTRUCTION_COUNT: usize> Context<INSTRUCTION_COUNT> {
164    /// Constructs a new [Context] with the given [Config].
165    pub const fn from_config(config: Config<INSTRUCTION_COUNT>) -> Self {
166        let execution_queue = [Execution::EMPTY; EXECUTION_QUEUE_SIZE];
167        Self {
168            config,
169            execution_queue,
170        }
171    }
172
173    /// Enqueues a new execution onto the execution queue.
174    pub fn enqueue(&mut self, new_execution: Execution) -> usize {
175        // Ignore empty executions.
176        if new_execution.is_empty() {
177            return EXECUTION_QUEUE_SIZE;
178        }
179
180        for (i, exec) in self.execution_queue.iter_mut().enumerate() {
181            if exec.is_empty() {
182                *exec = new_execution;
183                return i;
184            }
185        }
186
187        // Queue is full, drop the new execution.
188        EXECUTION_QUEUE_SIZE
189    }
190
191    fn execute_head(&mut self, keymap_index: u16) -> key::KeyEvents<Event> {
192        let mut pke = key_events_for(self.config, keymap_index, self.execution_queue[0]);
193
194        self.execution_queue[0].incr();
195
196        if self.execution_queue[0].is_empty() {
197            self.execution_queue.rotate_left(1);
198            self.execution_queue[EXECUTION_QUEUE_SIZE - 1] = Execution::EMPTY;
199
200            // If there's more to execute, schedule it to execute.
201            if !self.execution_queue[0].is_empty() {
202                pke.add_event(key::ScheduledEvent::after(
203                    self.config.instruction_duration,
204                    key::Event::Key {
205                        keymap_index,
206                        key_event: Event::NextInstruction,
207                    },
208                ));
209            }
210        }
211
212        pke
213    }
214}
215
216impl<const INSTRUCTION_COUNT: usize> key::Context for Context<INSTRUCTION_COUNT> {
217    type Event = Event;
218
219    fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
220        match event {
221            key::Event::Key {
222                key_event: Event::Enqueue(execution),
223                keymap_index,
224            } if !execution.is_empty() => {
225                let exec_immediately = self.execution_queue[0].is_empty();
226
227                self.enqueue(execution);
228
229                if exec_immediately {
230                    self.execute_head(keymap_index)
231                } else {
232                    key::KeyEvents::no_events()
233                }
234            }
235            key::Event::Key {
236                key_event: Event::NextInstruction,
237                keymap_index,
238            } => {
239                if !self.execution_queue[0].is_empty() {
240                    self.execute_head(keymap_index)
241                } else {
242                    key::KeyEvents::no_events()
243                }
244            }
245            _ => key::KeyEvents::no_events(),
246        }
247    }
248}
249
250/// The event type for automation keys.
251#[derive(Debug, Clone, Copy, PartialEq)]
252pub enum Event {
253    /// Enqueues an execution onto the Context's execution queue.
254    Enqueue(Execution),
255    /// Indicates to the context to execute the next instruction.
256    NextInstruction,
257    /// Indicates that the execution has finished.
258    ExecutionFinished,
259}
260
261/// Converts the instruction to a scheduled event, if applicable.
262pub fn key_events_for<const INSTRUCTION_COUNT: usize>(
263    config: Config<INSTRUCTION_COUNT>,
264    keymap_index: u16,
265    Execution { start, length }: Execution,
266) -> key::KeyEvents<Event> {
267    let instruction = config.instructions[start as usize];
268
269    let next_key_ev = if length > 1 {
270        key::Event::Key {
271            keymap_index,
272            key_event: Event::NextInstruction,
273        }
274    } else {
275        key::Event::Key {
276            keymap_index,
277            key_event: Event::ExecutionFinished,
278        }
279    };
280
281    match instruction {
282        Instruction::NoOp => {
283            let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
284            key::KeyEvents::scheduled_event(sch_ev)
285        }
286        Instruction::Press(key_output) => {
287            let sch_ev =
288                key::ScheduledEvent::immediate(key::Event::Input(input::Event::VirtualKeyPress {
289                    key_output,
290                }));
291
292            let mut pke = key::KeyEvents::scheduled_event(sch_ev);
293            let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
294            pke.add_event(sch_ev);
295
296            pke
297        }
298        Instruction::Release(key_output) => {
299            let sch_ev = key::ScheduledEvent::immediate(key::Event::Input(
300                input::Event::VirtualKeyRelease { key_output },
301            ));
302
303            let mut pke = key::KeyEvents::scheduled_event(sch_ev);
304            let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
305            pke.add_event(sch_ev);
306
307            pke
308        }
309        Instruction::Tap(key_output) => {
310            let sch_press_ev =
311                key::ScheduledEvent::immediate(key::Event::Input(input::Event::VirtualKeyPress {
312                    key_output,
313                }));
314            let sch_release_ev = key::ScheduledEvent::after(
315                config.instruction_duration,
316                key::Event::Input(input::Event::VirtualKeyRelease { key_output }),
317            );
318
319            let mut pke = key::KeyEvents::scheduled_event(sch_press_ev);
320            pke.add_event(sch_release_ev);
321            let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
322            pke.add_event(sch_ev);
323
324            pke
325        }
326        Instruction::Wait(ticks) => {
327            let sch_ev = key::ScheduledEvent::after(ticks, next_key_ev);
328            key::KeyEvents::scheduled_event(sch_ev)
329        }
330    }
331}
332
333/// The pending key state type for automation keys. (No pending state).
334#[derive(Debug, Clone, Copy, PartialEq)]
335pub struct PendingKeyState;
336
337/// Key state used by [System].
338#[derive(Debug, Clone, Copy, PartialEq)]
339pub struct KeyState;
340
341/// The [key::System] implementation for automation keys.
342#[derive(Debug, Clone, Copy, PartialEq)]
343pub struct System<R: Debug, Keys: Index<usize, Output = Key>, const INSTRUCTION_COUNT: usize> {
344    keys: Keys,
345    _marker: core::marker::PhantomData<(R, [(); INSTRUCTION_COUNT])>,
346}
347
348impl<R: Debug, Keys: Index<usize, Output = Key>, const INSTRUCTION_COUNT: usize>
349    System<R, Keys, INSTRUCTION_COUNT>
350{
351    /// Constructs a new [System].
352    pub const fn new(keys: Keys) -> Self {
353        Self {
354            keys,
355            _marker: core::marker::PhantomData,
356        }
357    }
358}
359
360impl<R: Copy + Debug, Keys: Debug + Index<usize, Output = Key>, const INSTRUCTION_COUNT: usize>
361    key::System<R> for System<R, Keys, INSTRUCTION_COUNT>
362{
363    type Ref = Ref;
364    type Context = Context<INSTRUCTION_COUNT>;
365    type Event = Event;
366    type PendingKeyState = PendingKeyState;
367    type KeyState = KeyState;
368
369    fn new_pressed_key(
370        &self,
371        keymap_index: u16,
372        _context: &Self::Context,
373        Ref(key_index): Ref,
374    ) -> (
375        key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
376        key::KeyEvents<Self::Event>,
377    ) {
378        let pkr = key::PressedKeyResult::Resolved(KeyState);
379
380        let Key {
381            automation_instructions:
382                KeyInstructions {
383                    on_press: execution,
384                    ..
385                },
386        } = self.keys[key_index as usize];
387        let key_ev = key::Event::Key {
388            keymap_index,
389            key_event: if !execution.is_empty() {
390                Event::Enqueue(execution)
391            } else {
392                // Trigger "while_pressed"
393                Event::ExecutionFinished
394            },
395        };
396        let pke = key::KeyEvents::event(key_ev);
397
398        (pkr, pke)
399    }
400
401    fn update_pending_state(
402        &self,
403        _pending_state: &mut Self::PendingKeyState,
404        _keymap_index: u16,
405        _context: &Self::Context,
406        _key_ref: Ref,
407        _event: key::Event<Self::Event>,
408    ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
409        panic!()
410    }
411
412    fn update_state(
413        &self,
414        _key_state: &mut Self::KeyState,
415        Ref(key_index): &Self::Ref,
416        _context: &Self::Context,
417        keymap_index: u16,
418        event: key::Event<Self::Event>,
419    ) -> key::KeyEvents<Self::Event> {
420        match event {
421            key::Event::Key {
422                key_event: Event::ExecutionFinished,
423                keymap_index: ev_kmi,
424            } if keymap_index == ev_kmi => {
425                // Execution finished while key is pressed;
426                //  enqueue the while_pressed instructions.
427                let Key {
428                    automation_instructions:
429                        KeyInstructions {
430                            while_pressed: execution,
431                            ..
432                        },
433                } = self.keys[*key_index as usize];
434                let key_ev = key::Event::Key {
435                    keymap_index,
436                    key_event: Event::Enqueue(execution),
437                };
438                key::KeyEvents::event(key_ev)
439            }
440            key::Event::Input(input::Event::Release {
441                keymap_index: ev_kmi,
442            }) if keymap_index == ev_kmi => {
443                // Key released.
444                //  enqueue the on_release instructions.
445                let Key {
446                    automation_instructions:
447                        KeyInstructions {
448                            on_release: execution,
449                            ..
450                        },
451                } = self.keys[*key_index as usize];
452                let key_ev = key::Event::Key {
453                    keymap_index,
454                    key_event: Event::Enqueue(execution),
455                };
456                key::KeyEvents::event(key_ev)
457            }
458            _ => key::KeyEvents::no_events(),
459        }
460    }
461
462    fn key_output(
463        &self,
464        _key_ref: &Self::Ref,
465        _key_state: &Self::KeyState,
466    ) -> Option<key::KeyOutput> {
467        None
468    }
469}
470
471#[cfg(test)]
472mod tests {
473    use super::*;
474
475    #[test]
476    fn test_sizeof_ref() {
477        assert_eq!(1, core::mem::size_of::<Ref>());
478    }
479
480    #[test]
481    fn test_sizeof_event() {
482        assert_eq!(6, core::mem::size_of::<Event>());
483    }
484}