1use crate::drivers::drv8873::{Diag, Drv8873, Fault};
9use crate::hw::{Encoder, SpiBus};
10
11use micromath::F32Ext;
12
13use stm32f7xx_hal::{
14 gpio::{self, Output, PushPull},
15 pac, spi,
16};
17
18#[derive(Copy, Clone, Debug)]
20pub enum Direction {
21 Forward,
22 Reverse,
23 Brake,
24 Coast,
25}
26
27pub struct Fit0185<
29 const CS_P: char,
30 const CS_N: u8,
31 const IN1_P: char,
32 const IN1_N: u8,
33 const IN2_P: char,
34 const IN2_N: u8,
35 const SLP_P: char,
36 const SLP_N: u8,
37 const DIS_P: char,
38 const DIS_N: u8,
39> {
40 drv: Drv8873<CS_P, CS_N>,
41 enc: Encoder<pac::TIM2>,
42 in1: gpio::Pin<IN1_P, IN1_N, Output<PushPull>>,
43 in2: gpio::Pin<IN2_P, IN2_N, Output<PushPull>>,
44 nsleep: gpio::Pin<SLP_P, SLP_N, Output<PushPull>>,
45 disable: gpio::Pin<DIS_P, DIS_N, Output<PushPull>>,
46 counts_per_rev: u32,
47}
48
49impl<
50 const CS_P: char,
51 const CS_N: u8,
52 const IN1_P: char,
53 const IN1_N: u8,
54 const IN2_P: char,
55 const IN2_N: u8,
56 const SLP_P: char,
57 const SLP_N: u8,
58 const DIS_P: char,
59 const DIS_N: u8,
60 > Fit0185<CS_P, CS_N, IN1_P, IN1_N, IN2_P, IN2_N, SLP_P, SLP_N, DIS_P, DIS_N>
61{
62 pub fn new<In1Mode, In2Mode, SlpMode, DisMode>(
66 drv: Drv8873<CS_P, CS_N>,
67 enc: Encoder<pac::TIM2>,
68 in1: gpio::Pin<IN1_P, IN1_N, In1Mode>,
69 in2: gpio::Pin<IN2_P, IN2_N, In2Mode>,
70 nsleep: gpio::Pin<SLP_P, SLP_N, SlpMode>,
71 disable: gpio::Pin<DIS_P, DIS_N, DisMode>,
72 counts_per_rev: u32,
73 ) -> Self {
74 let mut in1 = in1.into_push_pull_output();
75 let mut in2 = in2.into_push_pull_output();
76 let mut nsleep = nsleep.into_push_pull_output();
77 let mut disable = disable.into_push_pull_output();
78
79 in1.set_low();
80 in2.set_low();
81
82 nsleep.set_high();
84 disable.set_high();
85
86 Self {
87 drv,
88 enc,
89 in1,
90 in2,
91 nsleep,
92 disable,
93 counts_per_rev,
94 }
95 }
96
97 pub fn free(
99 self,
100 ) -> (
101 Drv8873<CS_P, CS_N>,
102 Encoder<pac::TIM2>,
103 gpio::Pin<IN1_P, IN1_N, Output<PushPull>>,
104 gpio::Pin<IN2_P, IN2_N, Output<PushPull>>,
105 gpio::Pin<SLP_P, SLP_N, Output<PushPull>>,
106 gpio::Pin<DIS_P, DIS_N, Output<PushPull>>,
107 ) {
108 (
109 self.drv,
110 self.enc,
111 self.in1,
112 self.in2,
113 self.nsleep,
114 self.disable,
115 )
116 }
117
118 pub fn init<I, PINS>(&mut self, spi_bus: &mut SpiBus<I, PINS>) -> Result<(), spi::Error>
120 where
121 I: spi::Instance,
122 PINS: spi::Pins<I>,
123 {
124 let _fault = self.drv.read_fault(spi_bus)?;
125 let _diag = self.drv.read_diag(spi_bus)?;
126
127 Ok(())
128 }
129
130 #[inline]
132 pub fn read_fault<I, PINS>(
133 &mut self,
134 spi_bus: &mut SpiBus<I, PINS>,
135 ) -> Result<Fault, spi::Error>
136 where
137 I: spi::Instance,
138 PINS: spi::Pins<I>,
139 {
140 self.drv.read_fault(spi_bus)
141 }
142
143 #[inline]
145 pub fn read_diag<I, PINS>(&mut self, spi_bus: &mut SpiBus<I, PINS>) -> Result<Diag, spi::Error>
146 where
147 I: spi::Instance,
148 PINS: spi::Pins<I>,
149 {
150 self.drv.read_diag(spi_bus)
151 }
152
153 #[inline]
155 pub fn drv(&mut self) -> &mut Drv8873<CS_P, CS_N> {
156 &mut self.drv
157 }
158
159 #[inline]
163 pub fn sleep(&mut self) {
164 self.nsleep.set_low();
165 }
166
167 #[inline]
169 pub fn wake(&mut self) {
170 self.nsleep.set_high();
171 }
172
173 #[inline]
175 pub fn enable_outputs(&mut self) {
176 self.wake();
177 self.disable.set_low();
178 }
179
180 #[inline]
182 pub fn disable_outputs(&mut self) {
183 self.set_direction_pins(Direction::Coast);
184 self.disable.set_high();
185 }
186
187 fn set_direction_pins(&mut self, dir: Direction) {
189 match dir {
190 Direction::Forward => {
191 self.in1.set_high();
192 self.in2.set_low();
193 }
194 Direction::Reverse => {
195 self.in1.set_low();
196 self.in2.set_high();
197 }
198 Direction::Brake => {
199 self.in1.set_high();
200 self.in2.set_high();
201 }
202 Direction::Coast => {
203 self.in1.set_low();
204 self.in2.set_low();
205 }
206 }
207 }
208
209 #[inline]
211 pub fn forward(&mut self) {
212 self.set_direction_pins(Direction::Forward);
213 }
214
215 #[inline]
217 pub fn reverse(&mut self) {
218 self.set_direction_pins(Direction::Reverse);
219 }
220
221 #[inline]
223 pub fn brake(&mut self) {
224 self.set_direction_pins(Direction::Brake);
225 }
226
227 #[inline]
229 pub fn coast(&mut self) {
230 self.set_direction_pins(Direction::Coast);
231 }
232
233 #[inline]
235 pub fn position_ticks(&self) -> i32 {
236 self.enc.position()
237 }
238
239 #[inline]
241 pub fn position_revs(&self) -> f32 {
242 self.enc.position() as f32 / self.counts_per_rev as f32
243 }
244
245 #[inline]
247 pub fn zero(&mut self) {
248 self.enc.reset();
249 }
250
251 #[inline]
253 pub fn ticks_for_revs(&self, revs: f32) -> i32 {
254 (revs * self.counts_per_rev as f32).round() as i32
255 }
256
257 #[inline]
259 pub fn target_for_delta_ticks(&self, delta_ticks: i32) -> i32 {
260 self.position_ticks().wrapping_add(delta_ticks)
261 }
262
263 #[inline]
265 pub fn target_for_delta_revs(&self, delta_revs: f32) -> i32 {
266 let delta_ticks = self.ticks_for_revs(delta_revs);
267 self.target_for_delta_ticks(delta_ticks)
268 }
269
270 #[inline]
272 pub fn encoder(&self) -> &Encoder<pac::TIM2> {
273 &self.enc
274 }
275
276 #[inline]
278 pub fn encoder_mut(&mut self) -> &mut Encoder<pac::TIM2> {
279 &mut self.enc
280 }
281
282 pub fn apply_pid_output(&mut self, u: f32) {
284 if u > 0.0 {
285 self.forward();
286 } else if u < 0.0 {
287 self.reverse();
288 } else {
289 self.coast();
290 }
291 }
292}