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}