aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-08-29 20:06:53 -0500
committerxoviat <[email protected]>2023-08-29 20:06:53 -0500
commit416ecc73d8211e348bf51a5cfe84075673b18963 (patch)
tree722771ef54d896fae8739948279db8d667ead3d6 /embassy-stm32
parentfdb2c4946aeef968704c358fb52d5fea69e80dcc (diff)
add qei draft
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/timer/qei.rs142
1 files changed, 142 insertions, 0 deletions
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
new file mode 100644
index 000000000..fa8814722
--- /dev/null
+++ b/embassy-stm32/src/timer/qei.rs
@@ -0,0 +1,142 @@
1//! # Quadrature Encoder Interface
2use crate::{
3 gpio::PushPull,
4 pac, rcc,
5 timer::{CPin, General},
6};
7
8pub trait QeiExt: Sized + Instance {
9 fn qei(
10 self,
11 pins: (
12 impl Into<<Self as CPin<0>>::Ch<PushPull>>,
13 impl Into<<Self as CPin<1>>::Ch<PushPull>>,
14 ),
15 ) -> Qei<Self>;
16}
17
18impl<TIM: Instance> QeiExt for TIM {
19 fn qei(
20 self,
21 pins: (
22 impl Into<<Self as CPin<0>>::Ch<PushPull>>,
23 impl Into<<Self as CPin<1>>::Ch<PushPull>>,
24 ),
25 ) -> Qei<Self> {
26 Qei::new(self, pins)
27 }
28}
29
30/// Hardware quadrature encoder interface peripheral
31pub struct Qei<TIM: Instance> {
32 tim: TIM,
33 pins: (
34 <TIM as CPin<0>>::Ch<PushPull>,
35 <TIM as CPin<1>>::Ch<PushPull>,
36 ),
37}
38
39impl<TIM: Instance> Qei<TIM> {
40 /// Configures a TIM peripheral as a quadrature encoder interface input
41 pub fn new(
42 mut tim: TIM,
43 pins: (
44 impl Into<<TIM as CPin<0>>::Ch<PushPull>>,
45 impl Into<<TIM as CPin<1>>::Ch<PushPull>>,
46 ),
47 ) -> Self {
48 // Enable and reset clock.
49 unsafe {
50 TIM::enable_unchecked();
51 TIM::reset_unchecked();
52 }
53
54 let pins = (pins.0.into(), pins.1.into());
55 tim.setup_qei();
56
57 Qei { tim, pins }
58 }
59
60 /// Releases the TIM peripheral and QEI pins
61 #[allow(clippy::type_complexity)]
62 pub fn release(
63 self,
64 ) -> (
65 TIM,
66 (
67 <TIM as CPin<0>>::Ch<PushPull>,
68 <TIM as CPin<1>>::Ch<PushPull>,
69 ),
70 ) {
71 (self.tim, self.pins)
72 }
73
74 /// Set current count number
75 pub fn set_count(&mut self, value: TIM::Width) -> &mut Self {
76 self.tim.write_count(value);
77 self
78 }
79}
80
81impl<TIM: Instance> embedded_hal::Qei for Qei<TIM> {
82 type Count = TIM::Width;
83
84 fn count(&self) -> Self::Count {
85 self.tim.read_count()
86 }
87
88 fn direction(&self) -> embedded_hal::Direction {
89 if self.tim.read_direction() {
90 embedded_hal::Direction::Upcounting
91 } else {
92 embedded_hal::Direction::Downcounting
93 }
94 }
95}
96
97pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + General + CPin<0> + CPin<1> {
98 fn setup_qei(&mut self);
99
100 fn read_direction(&self) -> bool;
101}
102
103macro_rules! hal {
104 ($TIM:ty) => {
105 impl Instance for $TIM {
106 fn setup_qei(&mut self) {
107 // Configure TxC1 and TxC2 as captures
108 #[cfg(not(feature = "gpio-f410"))]
109 self.ccmr1_input().write(|w| w.cc1s().ti1().cc2s().ti2());
110 #[cfg(feature = "gpio-f410")]
111 self.ccmr1_input()
112 .write(|w| unsafe { w.cc1s().bits(0b01).cc2s().bits(0b01) });
113 // enable and configure to capture on rising edge
114 self.ccer.write(|w| {
115 w.cc1e().set_bit().cc1p().clear_bit();
116 w.cc2e().set_bit().cc2p().clear_bit()
117 });
118 self.smcr.write(|w| w.sms().encoder_mode_3());
119 self.set_auto_reload(<$TIM as General>::Width::MAX as u32)
120 .unwrap();
121 self.cr1.write(|w| w.cen().set_bit());
122 }
123
124 fn read_direction(&self) -> bool {
125 self.cr1.read().dir().bit_is_clear()
126 }
127 }
128 };
129}
130
131#[cfg(feature = "tim1")]
132hal! { pac::TIM1 }
133#[cfg(feature = "tim2")]
134hal! { pac::TIM2 }
135#[cfg(feature = "tim3")]
136hal! { pac::TIM3 }
137#[cfg(feature = "tim4")]
138hal! { pac::TIM4 }
139#[cfg(feature = "tim5")]
140hal! { pac::TIM5 }
141#[cfg(feature = "tim8")]
142hal! { pac::TIM8 }