async_debounce/
lib.rs

1#![no_std]
2
3use embassy_time::{Duration, Timer};
4use embedded_hal::digital::{ErrorType, InputPin};
5use embedded_hal_async::digital::Wait;
6
7pub struct Debouncer<T> {
8    input: T,
9    debounce_high_time: Duration,
10    debounce_low_time: Duration,
11}
12
13impl<T> Debouncer<T> {
14    pub fn new(input: T, debounce_time: Duration) -> Self {
15        Self {
16            input,
17            debounce_high_time: debounce_time,
18            debounce_low_time: debounce_time,
19        }
20    }
21
22    pub fn new_asymmetric(
23        input: T,
24        debounce_high_time: Duration,
25        debounce_low_time: Duration,
26    ) -> Self {
27        Self {
28            input,
29            debounce_high_time,
30            debounce_low_time,
31        }
32    }
33}
34
35impl<T: InputPin> ErrorType for Debouncer<T> {
36    type Error = T::Error;
37}
38
39impl<T: Wait + InputPin> Wait for Debouncer<T> {
40    async fn wait_for_high(&mut self) -> Result<(), T::Error> {
41        if self.input.is_low()? {
42            loop {
43                self.input.wait_for_rising_edge().await?;
44
45                Timer::after(self.debounce_high_time).await;
46
47                if self.input.is_high()? {
48                    break;
49                }
50            }
51        }
52        Ok(())
53    }
54
55    async fn wait_for_low(&mut self) -> Result<(), T::Error> {
56        if self.input.is_high()? {
57            loop {
58                self.input.wait_for_falling_edge().await?;
59
60                Timer::after(self.debounce_low_time).await;
61
62                if self.input.is_low()? {
63                    break;
64                }
65            }
66        }
67        Ok(())
68    }
69
70    async fn wait_for_rising_edge(&mut self) -> Result<(), T::Error> {
71        loop {
72            self.input.wait_for_rising_edge().await?;
73
74            Timer::after(self.debounce_high_time).await;
75
76            if self.input.is_high()? {
77                break Ok(());
78            }
79        }
80    }
81
82    async fn wait_for_falling_edge(&mut self) -> Result<(), T::Error> {
83        loop {
84            self.input.wait_for_falling_edge().await?;
85
86            Timer::after(self.debounce_low_time).await;
87
88            if self.input.is_low()? {
89                break Ok(());
90            }
91        }
92    }
93
94    async fn wait_for_any_edge(&mut self) -> Result<(), T::Error> {
95        if self.input.is_low()? {
96            self.wait_for_rising_edge().await
97        } else {
98            self.wait_for_falling_edge().await
99        }
100    }
101}
102
103impl<T: InputPin> InputPin for Debouncer<T> {
104    #[inline]
105    fn is_high(&mut self) -> Result<bool, Self::Error> {
106        self.input.is_high()
107    }
108
109    #[inline]
110    fn is_low(&mut self) -> Result<bool, Self::Error> {
111        self.input.is_low()
112    }
113}