1use core::marker::PhantomData;
4
5use num_traits::{One, SaturatingAdd, WrappingNeg, Zero};
6use quadrature_decoder::{Change, FullStep, IncrementalDecoder, StepMode};
7
8#[allow(unused_imports)]
9use crate::{
10 mode::{Async, Blocking, Movement, OperationMode, PollMode},
11 traits::*,
12 Error, InputPinError, Linear, Rotary,
13};
14
15pub type RotaryEncoder<Clk, Dt, Steps = FullStep, T = i32, PM = Blocking> =
17 IncrementalEncoder<Rotary, Clk, Dt, Steps, T, PM>;
18pub type LinearEncoder<Clk, Dt, Steps = FullStep, T = i32, PM = Blocking> =
20 IncrementalEncoder<Linear, Clk, Dt, Steps, T, PM>;
21
22#[derive(Debug)]
24pub struct IncrementalEncoder<Mode, Clk, Dt, Steps = FullStep, T = i32, PM = Blocking> {
25 decoder: IncrementalDecoder<Steps, T>,
26 pin_clk: Clk,
27 pin_dt: Dt,
28 pin_clk_state: bool,
29 pin_dt_state: bool,
30 is_reversed: bool,
31 _mode: PhantomData<Mode>,
32 _poll_mode: PhantomData<PM>,
33}
34
35impl<Mode, Clk, Dt, Steps, T, PM> IncrementalEncoder<Mode, Clk, Dt, Steps, T, PM>
36where
37 Mode: OperationMode,
38 Clk: InputPin,
39 Dt: InputPin,
40 Steps: StepMode,
41 T: Zero,
42 PM: PollMode,
43{
44 pub fn new(mut pin_clk: Clk, mut pin_dt: Dt) -> Self
46 where
47 IncrementalDecoder<Steps, T>: Default,
48 Clk: InputPin,
49 Dt: InputPin,
50 {
51 let pin_clk_state = pin_clk.is_high().unwrap_or(false);
53 let pin_dt_state = pin_dt.is_high().unwrap_or(false);
54
55 Self {
56 decoder: Default::default(),
57 pin_clk,
58 pin_dt,
59 pin_clk_state,
60 pin_dt_state,
61 is_reversed: false,
62 _mode: PhantomData,
63 _poll_mode: PhantomData,
64 }
65 }
66}
67
68impl<Mode, Clk, Dt, Steps, T, PM> IncrementalEncoder<Mode, Clk, Dt, Steps, T, PM>
69where
70 Mode: OperationMode,
71 Clk: InputPin,
72 Dt: InputPin,
73 Steps: StepMode,
74 T: Copy + Zero + One + SaturatingAdd + WrappingNeg + From<i8>,
75 PM: PollMode,
76{
77 pub fn reversed(mut self) -> Self {
79 self.is_reversed = true;
80 self
81 }
82
83 pub fn is_reversed(&self) -> bool {
85 self.is_reversed
86 }
87
88 pub fn pins_mut(&mut self) -> (&mut Clk, &mut Dt) {
90 (&mut self.pin_clk, &mut self.pin_dt)
91 }
92
93 pub fn release(self) -> (Clk, Dt) {
95 (self.pin_clk, self.pin_dt)
96 }
97
98 fn update(&mut self) -> Result<Option<Mode::Movement>, Error> {
101 let change: Option<Change> = self
102 .decoder
103 .update(self.pin_clk_state, self.pin_dt_state)
104 .map_err(Error::Quadrature)?;
105 let movement: Option<Mode::Movement> = change.map(From::from);
106
107 Ok(movement.map(|movement| {
108 if self.is_reversed() {
109 movement.flipped()
110 } else {
111 movement
112 }
113 }))
114 }
115
116 pub fn reset(&mut self) {
118 self.decoder.reset();
119 }
120
121 pub fn position(&self) -> T {
123 match self.is_reversed {
124 true => self.decoder.counter().wrapping_neg(),
125 false => self.decoder.counter(),
126 }
127 }
128
129 pub fn set_position(&mut self, position: T) {
131 match self.is_reversed {
132 true => self.decoder.set_counter(position.wrapping_neg()),
133 false => self.decoder.set_counter(position),
134 }
135 }
136}
137
138impl<Mode, Clk, Dt, Steps, T> IncrementalEncoder<Mode, Clk, Dt, Steps, T, Blocking>
139where
140 Mode: OperationMode,
141 Clk: InputPin,
142 Dt: InputPin,
143 Steps: StepMode,
144 T: Copy + Zero + One + SaturatingAdd + WrappingNeg + From<i8>,
145{
146 pub fn poll(&mut self) -> Result<Option<Mode::Movement>, Error> {
155 self.pin_clk_state = self
156 .pin_clk
157 .is_high()
158 .map_err(|_| Error::InputPin(InputPinError::PinClk))?;
159 self.pin_dt_state = self
160 .pin_dt
161 .is_high()
162 .map_err(|_| Error::InputPin(InputPinError::PinDt))?;
163 self.update()
164 }
165}
166
167#[cfg(feature = "async")]
169impl<Mode, Clk, Dt, Steps, T> IncrementalEncoder<Mode, Clk, Dt, Steps, T, Blocking>
170where
171 Mode: OperationMode,
172 Clk: InputPin + Wait,
173 Dt: InputPin + Wait,
174 Steps: StepMode,
175 T: Copy + Zero + One + SaturatingAdd + WrappingNeg + From<i8>,
176{
177 pub fn into_async(self) -> IncrementalEncoder<Mode, Clk, Dt, Steps, T, Async>
179 where
180 IncrementalDecoder<Steps, T>: Default,
181 {
182 IncrementalEncoder::<Mode, Clk, Dt, Steps, T, Async> {
183 decoder: self.decoder,
184 pin_clk: self.pin_clk,
185 pin_dt: self.pin_dt,
186 pin_clk_state: self.pin_clk_state,
187 pin_dt_state: self.pin_dt_state,
188 is_reversed: self.is_reversed,
189 _mode: PhantomData,
190 _poll_mode: PhantomData,
191 }
192 }
193}
194
195#[cfg(feature = "async")]
196impl<Mode, Clk, Dt, Steps, T> IncrementalEncoder<Mode, Clk, Dt, Steps, T, Async>
197where
198 Mode: OperationMode,
199 Clk: InputPin + Wait,
200 Dt: InputPin + Wait,
201 Steps: StepMode,
202 T: Copy + Zero + One + SaturatingAdd + WrappingNeg + From<i8>,
203{
204 pub async fn poll(&mut self) -> Result<Option<Mode::Movement>, Error> {
215 let clk_fut = match self.pin_clk_state {
216 true => self.pin_clk.wait_for_low().left_future(),
217 false => self.pin_clk.wait_for_high().right_future(),
218 };
219
220 let dt_fut = match self.pin_dt_state {
221 true => self.pin_dt.wait_for_low().left_future(),
222 false => self.pin_dt.wait_for_high().right_future(),
223 };
224
225 match select(clk_fut, dt_fut).await {
229 Either::First(_) => {
230 self.pin_clk_state = !self.pin_clk_state;
231 }
232 Either::Second(_) => {
233 self.pin_dt_state = !self.pin_dt_state;
234 }
235 };
236
237 self.update()
238 }
239
240 pub fn into_blocking(self) -> IncrementalEncoder<Mode, Clk, Dt, Steps, T, Blocking>
242 where
243 IncrementalDecoder<Steps, T>: Default,
244 {
245 IncrementalEncoder::<Mode, Clk, Dt, Steps, T, Blocking> {
246 decoder: self.decoder,
247 pin_clk: self.pin_clk,
248 pin_dt: self.pin_dt,
249 pin_clk_state: self.pin_clk_state,
250 pin_dt_state: self.pin_dt_state,
251 is_reversed: self.is_reversed,
252 _mode: PhantomData,
253 _poll_mode: PhantomData,
254 }
255 }
256}