stm32l1xx_hal/
qei.rs

1//! Quadrature Encoder Interface
2use 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                    // enable and reset peripheral to a clean slate state
61                    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                    // Configure TxC1 and TxC2 as captures
66                    tim.ccmr1_output.write(|w| unsafe {
67                        w.cc1s().bits(0b01).cc2s().set_bit()
68                    });
69
70                    // Enable and configure to capture on rising edge
71                    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                    // Encoder mode, count up/down on both TI1FP1 and TI2FP2
87                    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}