stm32f7x7_hal/
qei.rs

1//! # Quadrature Encoder Interface
2use crate::hal::{self, Direction};
3use crate::stm32::RCC;
4
5use crate::gpio::gpioa::*;
6use crate::gpio::gpiob::*;
7use crate::gpio::gpioc::*;
8use crate::gpio::gpiod::*;
9use crate::gpio::gpioe::*;
10use crate::gpio::gpiof::*;
11use crate::gpio::gpioh::*;
12use crate::gpio::gpioi::*;
13use crate::gpio::{Alternate, AF1, AF2, AF3};
14
15use crate::stm32::{TIM1, TIM5, TIM2, TIM3, TIM4, TIM8};
16
17pub trait Pins<TIM> {}
18pub trait PinC1<TIM> {}
19pub trait PinC2<TIM> {}
20
21impl<TIM, PC1, PC2> Pins<TIM> for (PC1, PC2)
22where
23    PC1: PinC1<TIM>,
24    PC2: PinC2<TIM>,
25{
26}
27
28impl PinC1<TIM1> for PA8<Alternate<AF1>> {}
29impl PinC2<TIM1> for PA9<Alternate<AF1>> {}
30impl PinC1<TIM1> for PE9<Alternate<AF1>> {}
31impl PinC2<TIM1> for PE11<Alternate<AF1>> {}
32impl PinC1<TIM2> for PA0<Alternate<AF1>> {}
33impl PinC1<TIM2> for PA5<Alternate<AF1>> {}
34impl PinC1<TIM2> for PA15<Alternate<AF1>> {}
35impl PinC2<TIM2> for PA1<Alternate<AF1>> {}
36impl PinC2<TIM2> for PB3<Alternate<AF1>> {}
37impl PinC1<TIM2> for PB8<Alternate<AF1>> {}
38impl PinC2<TIM2> for PB9<Alternate<AF1>> {}
39impl PinC1<TIM3> for PA6<Alternate<AF2>> {}
40impl PinC2<TIM3> for PA7<Alternate<AF2>> {}
41impl PinC1<TIM3> for PB4<Alternate<AF2>> {}
42impl PinC2<TIM3> for PB5<Alternate<AF2>> {}
43impl PinC1<TIM3> for PC6<Alternate<AF2>> {}
44impl PinC2<TIM3> for PC7<Alternate<AF2>> {}
45impl PinC1<TIM4> for PB6<Alternate<AF2>> {}
46impl PinC2<TIM4> for PB7<Alternate<AF2>> {}
47impl PinC1<TIM4> for PD12<Alternate<AF2>> {}
48impl PinC2<TIM4> for PD13<Alternate<AF2>> {}
49impl PinC1<TIM5> for PA0<Alternate<AF2>> {}
50impl PinC2<TIM5> for PA1<Alternate<AF2>> {}
51impl PinC1<TIM5> for PB12<Alternate<AF2>> {}
52impl PinC1<TIM5> for PF3<Alternate<AF2>> {}
53impl PinC2<TIM5> for PF4<Alternate<AF2>> {}
54impl PinC1<TIM5> for PH10<Alternate<AF2>> {}
55impl PinC2<TIM5> for PH11<Alternate<AF2>> {}
56impl PinC1<TIM8> for PC6<Alternate<AF3>> {}
57impl PinC2<TIM8> for PC7<Alternate<AF3>> {}
58impl PinC1<TIM8> for PI5<Alternate<AF3>> {}
59impl PinC2<TIM8> for PI6<Alternate<AF3>> {}
60
61/// Hardware quadrature encoder interface peripheral
62pub struct Qei<TIM, PINS> {
63    tim: TIM,
64    pins: PINS,
65}
66
67macro_rules! hal {
68    ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident, $bits:ident),)+) => {
69        $(
70            impl<PINS> Qei<$TIM, PINS> {
71                /// Configures a TIM peripheral as a quadrature encoder interface input
72                pub fn $tim(tim: $TIM, pins: PINS) -> Self
73                where
74                    PINS: Pins<$TIM>
75                {
76                    let rcc = unsafe { &(*RCC::ptr()) };
77                    // enable and reset peripheral to a clean slate state
78                    rcc.$apbenr.modify(|_, w| w.$timXen().set_bit());
79                    rcc.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
80                    rcc.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
81
82                    // Configure TxC1 and TxC2 as captures
83                    tim.ccmr1_output
84                        .write(|w| unsafe { w.cc1s().bits(0b01).cc2s().bits(0b01) });
85
86                    // enable and configure to capture on rising edge
87                    tim.ccer.write(|w| {
88                        w.cc1e()
89                            .set_bit()
90                            .cc1p()
91                            .clear_bit()
92                            .cc2e()
93                            .set_bit()
94                            .cc2p()
95                            .clear_bit()
96                    });
97
98                    // configure as quadrature encoder
99                    // some chip variants declare `.bits()` as unsafe, some don't
100                    #[allow(unused_unsafe)]
101                    tim.smcr.write(|w| unsafe { w.sms().bits(3) });
102
103                    tim.arr.write(|w| unsafe { w.bits(core::u32::MAX) });
104                    tim.cr1.write(|w| w.cen().set_bit());
105
106                    Qei { tim, pins }
107                }
108
109                /// Releases the TIM peripheral and QEI pins
110                pub fn release(self) -> ($TIM, PINS) {
111                    (self.tim, self.pins)
112                }
113            }
114
115            impl<PINS> hal::Qei for Qei<$TIM, PINS> {
116                type Count = $bits;
117
118                fn count(&self) -> $bits {
119                    self.tim.cnt.read().bits() as $bits
120                }
121
122                fn direction(&self) -> Direction {
123                    if self.tim.cr1.read().dir().bit_is_clear() {
124                        hal::Direction::Upcounting
125                    } else {
126                        hal::Direction::Downcounting
127                    }
128                }
129            }
130
131        )+
132    }
133}
134
135hal! {
136    TIM1: (tim1, tim1en, tim1rst, apb2enr, apb2rstr, u16),
137    TIM5: (tim5, tim5en, tim5rst, apb1enr, apb1rstr, u32),
138    TIM2: (tim2, tim2en, tim2rst, apb1enr, apb1rstr, u32),
139    TIM3: (tim3, tim3en, tim3rst, apb1enr, apb1rstr, u16),
140    TIM4: (tim4, tim4en, tim4rst, apb1enr, apb1rstr, u16),
141    TIM8: (tim8, tim8en, tim8rst, apb2enr, apb2rstr, u16),
142}