embedded_simple_ui/
switch.rs1use core::marker::PhantomData;
2use embedded_hal::digital::InputPin;
3use embedded_time::duration::Milliseconds;
4use embedded_time::{Clock, Instant};
5
6pub trait Switch<C: Clock> {
16 fn reset(&mut self);
18
19 fn poll(&mut self, now: Instant<C>);
25
26 fn has_changed(&self) -> bool;
28
29 fn is_pressed(&self) -> bool;
31
32 fn is_released(&self) -> bool;
34
35 fn pressed_for(&self) -> Option<Milliseconds<C::T>>;
43
44 fn released_for(&self) -> Option<Milliseconds<C::T>>;
52
53 fn prev_state_lasted_for(&self) -> Milliseconds<C::T>;
55
56 fn current_state(&self, now: Instant<C>) -> Milliseconds<C::T>;
60
61 fn wait(&mut self, clock: &C);
67}
68
69pub mod switch_state {
70 use embedded_hal::digital::InputPin;
71
72 pub trait PressedState {
77 fn get_pressed_state<P: InputPin>(pin: &mut P) -> bool;
78 }
79
80 pub struct PressedOnHigh {}
82
83 pub struct PressedOnLow {}
85
86 impl PressedState for PressedOnHigh {
87 fn get_pressed_state<P: InputPin>(pin: &mut P) -> bool {
88 pin.is_high().unwrap()
89 }
90 }
91 impl PressedState for PressedOnLow {
92 fn get_pressed_state<P: InputPin>(pin: &mut P) -> bool {
93 pin.is_low().unwrap()
94 }
95 }
96}
97
98pub struct PinSwitch<P: InputPin, S: switch_state::PressedState, C: Clock> {
102 pin: P,
103 is_pressed: bool,
104 has_changed: bool,
105 last_change_at: Instant<C>,
106 prev_state_lasted: Milliseconds<C::T>,
107 pressed_state: PhantomData<S>,
108}
109
110impl<P: InputPin, S: switch_state::PressedState, C: Clock> PinSwitch<P, S, C> {
111 pub fn new(pin: P) -> Self {
113 Self {
114 pin,
115 is_pressed: false,
116 has_changed: false,
117 last_change_at: Instant::<C>::new(C::T::from(0)),
118 prev_state_lasted: Milliseconds::<C::T>::new(C::T::from(0)),
119 pressed_state: Default::default(),
120 }
121 }
122}
123
124impl<P: InputPin, S: switch_state::PressedState, C: Clock> Switch<C> for PinSwitch<P, S, C> {
125 fn poll(&mut self, now: Instant<C>) {
126 let new_state = S::get_pressed_state(&mut self.pin);
127
128 if new_state == self.is_pressed {
129 self.has_changed = false;
130 return;
131 }
132
133 self.is_pressed = new_state;
134 self.has_changed = true;
135 self.prev_state_lasted = self.current_state(now);
136 self.last_change_at = now;
137 }
138
139 fn has_changed(&self) -> bool {
140 self.has_changed
141 }
142
143 fn is_pressed(&self) -> bool {
144 self.is_pressed
145 }
146
147 fn is_released(&self) -> bool {
148 !self.is_pressed
149 }
150
151 fn pressed_for(&self) -> Option<Milliseconds<C::T>> {
152 if !self.is_pressed {
153 return Some(self.prev_state_lasted);
154 }
155 None
156 }
157
158 fn released_for(&self) -> Option<Milliseconds<C::T>> {
159 if self.is_pressed {
160 return Some(self.prev_state_lasted);
161 }
162 None
163 }
164
165 fn wait(&mut self, clock: &C) {
166 loop {
167 self.poll(clock.try_now().unwrap());
168 if self.has_changed {
169 break;
170 }
171 }
172 }
173
174 fn reset(&mut self) {
175 self.last_change_at = Instant::<C>::new(C::T::from(0));
176 self.prev_state_lasted = Milliseconds::<C::T>::new(C::T::from(0));
177 self.has_changed = false;
178 self.is_pressed = false;
179 }
180
181 fn prev_state_lasted_for(&self) -> Milliseconds<<C as Clock>::T> {
182 self.prev_state_lasted
183 }
184
185 fn current_state(&self, now: Instant<C>) -> Milliseconds<<C as Clock>::T> {
186 now
187 .checked_duration_since(&self.last_change_at)
188 .unwrap()
189 .try_into()
190 .unwrap()
191 }
192}