1use crate::TimeDuration;
2use crate::config::Config;
3use crate::event::Event;
4use crate::service_timing::ServiceTiming;
5use crate::state_machine::{Edge, StateMachine};
6use crate::time::TimeInstant;
7
8#[derive(Debug, Clone, Copy)]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11pub struct UpdateResult<D: TimeDuration> {
12 pub event: Option<Event<D>>,
14 pub next_service: ServiceTiming<D>,
16}
17
18pub struct ButtHead<I: TimeInstant> {
23 prev_input: bool,
24 state_machine: StateMachine<I>,
25 config: &'static Config<I::Duration>,
26}
27
28impl<I: TimeInstant> ButtHead<I> {
29 pub fn new(config: &'static Config<I::Duration>) -> Self {
31 Self {
32 prev_input: false,
33 state_machine: StateMachine::new(config),
34 config,
35 }
36 }
37
38 pub fn is_pressed(&self) -> bool {
40 self.prev_input
41 }
42
43 pub fn pressed_duration(&self, now: I) -> Option<I::Duration> {
46 self.state_machine
47 .pressed_at()
48 .map(|at| now.duration_since(at))
49 }
50
51 pub fn update(&mut self, is_pressed: bool, now: I) -> UpdateResult<I::Duration> {
57 let input = if self.config.active_low {
58 !is_pressed
59 } else {
60 is_pressed
61 };
62
63 let edge = if input != self.prev_input {
64 self.prev_input = input;
65 Some(if input { Edge::Press } else { Edge::Release })
66 } else {
67 None
68 };
69
70 let (event, next_service) = self.state_machine.update(edge, now);
71
72 UpdateResult {
73 event,
74 next_service,
75 }
76 }
77}