1use crate::pac::{self, DBGMCU as DBG};
7
8use crate::afio::{RInto, Rmp, TimC};
9use crate::rcc::Rcc;
10use crate::time::Hertz;
11use crate::timer::{General, Timer};
12
13use embedded_hal_02 as hal;
14pub use hal::Direction;
15
16pub trait Instance: General + TimC<0> + TimC<1> {}
17
18#[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity"))]
19impl Instance for pac::TIM1 {}
20impl Instance for pac::TIM2 {}
21impl Instance for pac::TIM3 {}
22#[cfg(feature = "medium")]
23impl Instance for pac::TIM4 {}
24
25#[allow(unused)]
27pub struct PwmInput<TIM: Instance> {
28 timer: TIM,
29 pins: (<TIM as TimC<0>>::In, <TIM as TimC<1>>::In),
30}
31
32pub enum ReadMode {
34 Instant,
36 WaitForNextCapture,
39}
40
41#[derive(Debug)]
43pub enum Error {
44 FrequencyTooLow,
46}
47
48pub enum Configuration {
50 Frequency(Hertz),
58
59 DutyCycle(Hertz),
65
66 RawFrequency(Hertz),
70
71 RawValues { arr: u16, presc: u16 },
73}
74
75#[derive(Copy, Clone, Debug)]
77pub enum SlaveMode {
78 EncoderMode1 = 0b001,
80 EncoderMode2 = 0b010,
82 EncoderMode3 = 0b011,
85 ResetMode = 0b100,
88 TriggerMode = 0b110,
91 ExternalClockMode1 = 0b111,
93}
94
95#[derive(Copy, Clone, Debug)]
100pub struct QeiOptions {
101 pub slave_mode: SlaveMode,
103
104 pub auto_reload_value: u16,
109}
110
111impl Default for QeiOptions {
112 fn default() -> Self {
113 Self {
114 slave_mode: SlaveMode::EncoderMode3,
115 auto_reload_value: u16::MAX,
116 }
117 }
118}
119
120pub struct Qei<TIM: Instance> {
122 tim: TIM,
123 pins: (<TIM as TimC<0>>::In, <TIM as TimC<1>>::In),
124}
125
126pub trait PwmInputExt: Sized + Instance {
127 fn pwm_input(
128 self,
129 pins: (
130 impl RInto<<Self as TimC<0>>::In, 0>,
131 impl RInto<<Self as TimC<1>>::In, 0>,
132 ),
133 dbg: &mut DBG,
134 mode: Configuration,
135 rcc: &mut Rcc,
136 ) -> PwmInput<Self>;
137}
138
139pub trait QeiExt: Sized + Instance {
140 fn qei(
141 self,
142 pins: (
143 impl RInto<<Self as TimC<0>>::In, 0>,
144 impl RInto<<Self as TimC<1>>::In, 0>,
145 ),
146 options: QeiOptions,
147 rcc: &mut Rcc,
148 ) -> Qei<Self>;
149}
150
151fn compute_arr_presc(freq: u32, clock: u32) -> (u16, u16) {
153 if freq == 0 {
154 return (u16::MAX, u16::MAX);
155 }
156 let presc = clock / freq.saturating_mul(u16::MAX as u32 + 1);
157 let arr = clock / freq.saturating_mul(presc + 1);
158 (core::cmp::max(1, arr as u16), presc as u16)
159}
160macro_rules! hal {
161 ($TIM:ty: $timX:ident, $qeix:ident) => {
162 impl Timer<$TIM> {
163 pub fn pwm_input(
164 mut self,
165 pins: (
166 impl RInto<<$TIM as TimC<0>>::In, 0>,
167 impl RInto<<$TIM as TimC<1>>::In, 0>,
168 ),
169 dbg: &mut DBG,
170 mode: Configuration,
171 ) -> PwmInput<$TIM> {
172 self.stop_in_debug(dbg, false);
173 let Self { tim, clk } = self;
174 $timX(tim, pins, clk, mode)
175 }
176 pub fn qei(
177 self,
178 pins: (
179 impl RInto<<$TIM as TimC<0>>::In, 0>,
180 impl RInto<<$TIM as TimC<1>>::In, 0>,
181 ),
182 options: QeiOptions,
183 ) -> Qei<$TIM> {
184 let Self { tim, clk: _ } = self;
185 $qeix(tim, pins, options)
186 }
187 }
188 impl PwmInputExt for $TIM {
189 fn pwm_input(
190 self,
191 pins: (
192 impl RInto<<Self as TimC<0>>::In, 0>,
193 impl RInto<<Self as TimC<1>>::In, 0>,
194 ),
195 dbg: &mut DBG,
196 mode: Configuration,
197 rcc: &mut Rcc,
198 ) -> PwmInput<Self> {
199 Timer::new(self, rcc).pwm_input(pins, dbg, mode)
200 }
201 }
202 impl QeiExt for $TIM {
203 fn qei(
204 self,
205 pins: (
206 impl RInto<<Self as TimC<0>>::In, 0>,
207 impl RInto<<Self as TimC<1>>::In, 0>,
208 ),
209 options: QeiOptions,
210 rcc: &mut Rcc,
211 ) -> Qei<Self> {
212 Timer::new(self, rcc).qei(pins, options)
213 }
214 }
215
216 impl<const R: u8> Rmp<$TIM, R> {
217 pub fn pwm_input(
218 self,
219 pins: (
220 impl RInto<<$TIM as TimC<0>>::In, R>,
221 impl RInto<<$TIM as TimC<1>>::In, R>,
222 ),
223 dbg: &mut DBG,
224 mode: Configuration,
225 rcc: &mut Rcc,
226 ) -> PwmInput<$TIM> {
227 let mut tim = Timer::new(self.0, rcc);
228 tim.stop_in_debug(dbg, false);
229 let Timer { tim, clk } = tim;
230 $timX(tim, pins, clk, mode)
231 }
232 pub fn qei(
233 self,
234 pins: (
235 impl RInto<<$TIM as TimC<0>>::In, R>,
236 impl RInto<<$TIM as TimC<1>>::In, R>,
237 ),
238 options: QeiOptions,
239 rcc: &mut Rcc,
240 ) -> Qei<$TIM> {
241 let Timer { tim, clk: _ } = Timer::new(self.0, rcc);
242 $qeix(tim, pins, options)
243 }
244 }
245
246 fn $timX<const R: u8>(
247 tim: $TIM,
248 pins: (
249 impl RInto<<$TIM as TimC<0>>::In, R>,
250 impl RInto<<$TIM as TimC<1>>::In, R>,
251 ),
252 clk: Hertz,
253 mode: Configuration,
254 ) -> PwmInput<$TIM> {
255 let pins = (pins.0.rinto(), pins.1.rinto());
256
257 use Configuration::*;
258 tim.ccer().modify(|_, w| {
261 w.cc1e().clear_bit();
262 w.cc2e().clear_bit();
263 w.cc1p().clear_bit();
264 w.cc2p().set_bit()
265 });
266
267 tim.ccmr1_input().modify(|_, w| w.cc1s().ti1().cc2s().ti1());
270
271 tim.dier().write(|w| w.cc1ie().set_bit());
272
273 tim.smcr()
281 .modify(|_, w| unsafe { w.ts().bits(0b101).sms().bits(0b100) });
282
283 match mode {
284 Frequency(f) => {
285 let freq = f.raw();
286 let max_freq = if freq > 5 { freq / 5 } else { 1 };
287 let (arr, presc) = compute_arr_presc(max_freq, clk.raw());
288 tim.arr().write(|w| w.arr().set(arr));
289 tim.psc().write(|w| w.psc().set(presc));
290 }
291 DutyCycle(f) => {
292 let freq = f.raw();
293 let max_freq = if freq > 2 {
294 freq / 2 + freq / 4 + freq / 8
295 } else {
296 1
297 };
298 let (arr, presc) = compute_arr_presc(max_freq, clk.raw());
299 tim.arr().write(|w| w.arr().set(arr));
300 tim.psc().write(|w| w.psc().set(presc));
301 }
302 RawFrequency(f) => {
303 let freq = f.raw();
304 let (arr, presc) = compute_arr_presc(freq, clk.raw());
305 tim.arr().write(|w| w.arr().set(arr));
306 tim.psc().write(|w| w.psc().set(presc));
307 }
308 RawValues { arr, presc } => {
309 tim.arr().write(|w| w.arr().set(arr));
310 tim.psc().write(|w| w.psc().set(presc));
311 }
312 }
313
314 tim.ccer()
316 .modify(|_, w| w.cc1e().set_bit().cc2e().set_bit());
317
318 tim.cr1().modify(|_, w| w.cen().set_bit());
319 PwmInput { timer: tim, pins }
320 }
321
322 impl PwmInput<$TIM> {
323 pub fn read_frequency(&self, mode: ReadMode, clk: Hertz) -> Result<Hertz, Error> {
325 if let ReadMode::WaitForNextCapture = mode {
326 self.wait_for_capture();
327 }
328
329 let presc = unsafe { (*<$TIM>::ptr()).psc().read().bits() as u16 };
330 let ccr1 = unsafe { (*<$TIM>::ptr()).ccr1().read().bits() as u16 };
331
332 if ccr1 == 0 {
347 Err(Error::FrequencyTooLow)
348 } else {
349 Ok(clk / ((presc + 1) as u32 * (ccr1 + 1) as u32))
350 }
351 }
352
353 pub fn read_duty(&self, mode: ReadMode) -> Result<(u16, u16), Error> {
355 if let ReadMode::WaitForNextCapture = mode {
356 self.wait_for_capture();
357 }
358
359 let ccr1 = unsafe { (*<$TIM>::ptr()).ccr1().read().bits() as u16 };
362 let ccr2 = unsafe { (*<$TIM>::ptr()).ccr2().read().bits() as u16 };
363 if ccr1 == 0 {
364 Err(Error::FrequencyTooLow)
365 } else {
366 Ok((ccr2, ccr1))
367 }
368 }
369
370 fn wait_for_capture(&self) {
372 unsafe { &(*<$TIM>::ptr()) }.sr().write(|w| {
373 w.uif().clear_bit();
374 w.cc1if().clear_bit();
375 w.cc1of().clear_bit()
376 });
377 while unsafe { (*<$TIM>::ptr()).sr().read().cc1if().bit_is_clear() } {}
378 }
379
380 pub fn release(self) -> ($TIM, (<$TIM as TimC<0>>::In, <$TIM as TimC<1>>::In)) {
381 (self.timer, self.pins)
382 }
383 }
384
385 fn $qeix<const R: u8>(
386 tim: $TIM,
387 pins: (
388 impl RInto<<$TIM as TimC<0>>::In, R>,
389 impl RInto<<$TIM as TimC<1>>::In, R>,
390 ),
391 options: QeiOptions,
392 ) -> Qei<$TIM> {
393 let pins = (pins.0.rinto(), pins.1.rinto());
394 tim.ccmr1_input().write(|w| w.cc1s().ti1().cc2s().ti2());
396
397 tim.ccer().write(|w| {
399 w.cc1e().set_bit();
400 w.cc1p().clear_bit();
401 w.cc2e().set_bit();
402 w.cc2p().clear_bit()
403 });
404
405 tim.smcr().write(|w| w.sms().set(options.slave_mode as u8));
407
408 tim.arr().write(|w| w.arr().set(options.auto_reload_value));
409 tim.cr1().write(|w| w.cen().set_bit());
410
411 Qei { tim, pins }
412 }
413
414 impl Qei<$TIM> {
415 pub fn release(self) -> ($TIM, (<$TIM as TimC<0>>::In, <$TIM as TimC<1>>::In)) {
416 (self.tim, self.pins)
417 }
418 }
419
420 impl hal::Qei for Qei<$TIM> {
421 type Count = u16;
422
423 fn count(&self) -> u16 {
424 self.tim.cnt().read().cnt().bits()
425 }
426
427 fn direction(&self) -> Direction {
428 if self.tim.cr1().read().dir().bit_is_clear() {
429 Direction::Upcounting
430 } else {
431 Direction::Downcounting
432 }
433 }
434 }
435 };
436}
437
438#[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity"))]
439hal!(pac::TIM1: tim1, qei1);
440
441hal!(pac::TIM2: tim2, qei2);
442hal!(pac::TIM3: tim3, qei3);
443
444#[cfg(feature = "medium")]
445hal!(pac::TIM4: tim4, qei4);