embedded_controls/
encoder.rs1use crate::{Control, DebouncedInput, DebouncedInputConfig, DebouncedInputEvent};
2
3use core::ops::AddAssign;
4use num_integer::Integer;
5use num_traits::{One, Signed, Zero};
6use switch_hal::InputSwitch;
7
8pub trait EncoderConfig: DebouncedInputConfig {
10 type Counts: AddAssign + Integer + Signed + Copy;
12
13 const COUNTS_DIV: Self::Counts;
15}
16
17pub struct Encoder<SwitchA: InputSwitch, SwitchB: InputSwitch, Config: EncoderConfig> {
50 debounced_input_a: DebouncedInput<SwitchA, Config>,
51 debounced_input_b: DebouncedInput<SwitchB, Config>,
52 counts: Config::Counts,
53}
54
55#[derive(Debug, Clone, Copy, PartialEq)]
57pub enum EncoderEvent {
58 NoTurn,
60 ClockwiseTurn,
62 CounterClockwiseTurn,
64}
65
66impl<SwitchA: InputSwitch, SwitchB: InputSwitch, Config: EncoderConfig>
67 Encoder<SwitchA, SwitchB, Config>
68{
69 pub fn new(input_switch_a: SwitchA, input_switch_b: SwitchB) -> Self {
71 Encoder {
72 debounced_input_a: DebouncedInput::new(input_switch_a),
73 debounced_input_b: DebouncedInput::new(input_switch_b),
74 counts: Zero::zero(),
75 }
76 }
77
78 pub fn release_input_switches(self) -> (SwitchA, SwitchB) {
80 (
81 self.debounced_input_a.release_input_switch(),
82 self.debounced_input_b.release_input_switch(),
83 )
84 }
85}
86
87impl<SwitchA: InputSwitch, SwitchB: InputSwitch, Config: EncoderConfig> Control
88 for Encoder<SwitchA, SwitchB, Config>
89where
90 <DebouncedInput<SwitchA, Config> as Control>::Error:
91 From<<DebouncedInput<SwitchB, Config> as Control>::Error>,
92{
93 type Event = EncoderEvent;
94 type Error = <DebouncedInput<SwitchA, Config> as Control>::Error;
95
96 fn update(&mut self) -> Result<Self::Event, Self::Error> {
97 let a_event = self.debounced_input_a.update()?;
98 let b_event = self.debounced_input_b.update()?;
99
100 fn check_event<Counts: Signed>(
101 event: DebouncedInputEvent,
102 antogonist_state: bool,
103 direct: Counts,
104 ) -> Counts {
105 match event {
106 DebouncedInputEvent::Rise if antogonist_state => -direct,
107 DebouncedInputEvent::Rise => direct,
108 DebouncedInputEvent::Fall if antogonist_state => direct,
109 DebouncedInputEvent::Fall => -direct,
110 _ => Zero::zero(),
111 }
112 }
113
114 let direct = One::one();
115
116 self.counts += check_event(a_event, self.debounced_input_b.is_high(), direct);
117 self.counts += check_event(b_event, self.debounced_input_a.is_high(), -direct);
118
119 let result_event = if !self.counts.is_zero() && (self.counts % Config::COUNTS_DIV).is_zero()
120 {
121 let counts = self.counts;
122 self.counts = Zero::zero();
123
124 match counts.is_positive() {
125 true => EncoderEvent::ClockwiseTurn,
126 false => EncoderEvent::CounterClockwiseTurn,
127 }
128 } else {
129 EncoderEvent::NoTurn
130 };
131
132 Ok(result_event)
133 }
134}