1use crate::gpio::gpioa::{PA0, PA1, PA6, PA7};
3use crate::gpio::gpiob::{PB6, PB7};
4use crate::gpio::{AltMode, Floating, Input};
5use crate::hal::{self, Direction};
6use crate::rcc::Rcc;
7use crate::stm32::{TIM2, TIM3, TIM4, TIM5};
8use core::u16;
9
10pub trait Pins<TIM> {
11 fn setup(&self);
12}
13
14impl Pins<TIM2> for (PA0<Input<Floating>>, PA1<Input<Floating>>) {
15 fn setup(&self) {
16 self.0.set_alt_mode(AltMode::TIM2);
17 self.1.set_alt_mode(AltMode::TIM2);
18 }
19}
20
21impl Pins<TIM3> for (PA6<Input<Floating>>, PA7<Input<Floating>>) {
22 fn setup(&self) {
23 self.0.set_alt_mode(AltMode::TIM3_5);
24 self.1.set_alt_mode(AltMode::TIM3_5);
25 }
26}
27
28impl Pins<TIM4> for (PB6<Input<Floating>>, PB7<Input<Floating>>) {
29 fn setup(&self) {
30 self.0.set_alt_mode(AltMode::TIM3_5);
31 self.1.set_alt_mode(AltMode::TIM3_5);
32 }
33}
34
35impl Pins<TIM5> for (PA0<Input<Floating>>, PA1<Input<Floating>>) {
36 fn setup(&self) {
37 self.0.set_alt_mode(AltMode::TIM3_5);
38 self.1.set_alt_mode(AltMode::TIM3_5);
39 }
40}
41
42pub struct Qei<TIM, PINS> {
43 tim: TIM,
44 pins: PINS,
45}
46
47pub trait QeiExt<TIM, PINS>
48where
49 PINS: Pins<TIM>,
50{
51 fn qei(self, pins: PINS, rcc: &mut Rcc) -> Qei<TIM, PINS>;
52}
53
54macro_rules! hal {
55 ($($TIMX:ident: ($timX:ident, $timXen:ident, $timXrst:ident),)+) => {
56 $(
57 impl<PINS> Qei<$TIMX, PINS> where PINS: Pins<$TIMX> {
58 fn $timX(tim: $TIMX, pins: PINS, rcc: &mut Rcc) -> Self {
59 pins.setup();
60 rcc.rb.apb1enr.modify(|_, w| w.$timXen().set_bit());
62 rcc.rb.apb1rstr.modify(|_, w| w.$timXrst().set_bit());
63 rcc.rb.apb1rstr.modify(|_, w| w.$timXrst().clear_bit());
64
65 tim.ccmr1_output.write(|w| unsafe {
67 w.cc1s().bits(0b01).cc2s().set_bit()
68 });
69
70 tim.ccer.write(|w| {
72 w.cc1e()
73 .set_bit()
74 .cc2e()
75 .set_bit()
76 .cc1p()
77 .clear_bit()
78 .cc2p()
79 .clear_bit()
80 .cc1np()
81 .clear_bit()
82 .cc2np()
83 .clear_bit()
84 });
85
86 tim.smcr.write(|w| unsafe { w.sms().bits(0b011) });
88
89 tim.arr.write(|w| w.arr().bits(u16::MAX));
90 tim.cr1.write(|w| w.cen().enabled());
91
92 Qei { tim, pins }
93 }
94
95 pub fn release(self) -> ($TIMX, PINS) {
96 (self.tim, self.pins)
97 }
98 }
99
100 impl<PINS> hal::Qei for Qei<$TIMX, PINS> {
101 type Count = u16;
102
103 fn count(&self) -> u16 {
104 self.tim.cnt.read().cnt().bits()
105 }
106
107 fn direction(&self) -> Direction {
108 if self.tim.cr1.read().dir().bit_is_clear() {
109 hal::Direction::Upcounting
110 } else {
111 hal::Direction::Downcounting
112 }
113 }
114 }
115
116 impl<PINS> QeiExt<$TIMX, PINS> for $TIMX where PINS: Pins<$TIMX> {
117 fn qei(self, pins: PINS, rcc: &mut Rcc) -> Qei<$TIMX, PINS> {
118 Qei::$timX(self, pins, rcc)
119 }
120 }
121 )+
122 }
123}
124
125hal! {
126 TIM2: (tim2, tim2en, tim2rst),
127 TIM3: (tim3, tim3en, tim3rst),
128 TIM4: (tim4, tim4en, tim4rst),
129 TIM5: (tim5, tim5en, tim5rst),
130}