aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer
diff options
context:
space:
mode:
authorBrian Schwind <[email protected]>2025-09-29 22:05:27 +0900
committerBrian Schwind <[email protected]>2025-09-29 22:05:27 +0900
commit165fa1debd7f8aa6131c467825477a25e1862539 (patch)
tree439c7c221cc44da6a8d6c27dfe6fa6267a37138d /embassy-stm32/src/timer
parenta791e9f1fc17eda2b05df97a72b94264ee6a4c12 (diff)
Add a Config struct for the Qei peripheral
Diffstat (limited to 'embassy-stm32/src/timer')
-rw-r--r--embassy-stm32/src/timer/qei.rs65
1 files changed, 60 insertions, 5 deletions
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 25e8c3705..2e438bc74 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -1,6 +1,6 @@
1//! Quadrature decoder using a timer. 1//! Quadrature decoder using a timer.
2 2
3use stm32_metapac::timer::vals; 3use stm32_metapac::timer::vals::{self, Sms};
4 4
5use super::low_level::Timer; 5use super::low_level::Timer;
6pub use super::{Ch1, Ch2}; 6pub use super::{Ch1, Ch2};
@@ -9,6 +9,51 @@ use crate::gpio::{AfType, AnyPin, Pull};
9use crate::timer::TimerChannel; 9use crate::timer::TimerChannel;
10use crate::Peri; 10use crate::Peri;
11 11
12/// Qei driver config.
13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14#[derive(Clone, Copy)]
15pub struct Config {
16 /// Configures the internal pull up/down resistor for Qei's channel 1 pin.
17 pub ch1_pull: Pull,
18 /// Configures the internal pull up/down resistor for Qei's channel 2 pin.
19 pub ch2_pull: Pull,
20 /// Specifies the encoder mode to use for the Qei peripheral.
21 pub mode: QeiMode,
22}
23
24impl Default for Config {
25 /// Arbitrary defaults to preserve backwards compatibility
26 fn default() -> Self {
27 Self {
28 ch1_pull: Pull::None,
29 ch2_pull: Pull::None,
30 mode: QeiMode::Mode3,
31 }
32 }
33}
34
35/// See STMicro AN4013 for ยง2.3 for more information
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37#[derive(Clone, Copy)]
38pub enum QeiMode {
39 /// Direct alias for [`Sms::ENCODER_MODE_1`]
40 Mode1,
41 /// Direct alias for [`Sms::ENCODER_MODE_2`]
42 Mode2,
43 /// Direct alias for [`Sms::ENCODER_MODE_3`]
44 Mode3,
45}
46
47impl From<QeiMode> for Sms {
48 fn from(mode: QeiMode) -> Self {
49 match mode {
50 QeiMode::Mode1 => Sms::ENCODER_MODE_1,
51 QeiMode::Mode2 => Sms::ENCODER_MODE_2,
52 QeiMode::Mode3 => Sms::ENCODER_MODE_3,
53 }
54 }
55}
56
12/// Counting direction 57/// Counting direction
13pub enum Direction { 58pub enum Direction {
14 /// Counting up. 59 /// Counting up.
@@ -37,20 +82,30 @@ pub struct Qei<'d, T: GeneralInstance4Channel> {
37} 82}
38 83
39impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { 84impl<'d, T: GeneralInstance4Channel> Qei<'d, T> {
40 /// Create a new quadrature decoder driver. 85 /// Create a new quadrature decoder driver, with a given [`Config`].
41 #[allow(unused)] 86 #[allow(unused)]
42 pub fn new<CH1: QeiChannel, CH2: QeiChannel, #[cfg(afio)] A>( 87 pub fn new<CH1: QeiChannel, CH2: QeiChannel, #[cfg(afio)] A>(
43 tim: Peri<'d, T>, 88 tim: Peri<'d, T>,
44 ch1: Peri<'d, if_afio!(impl TimerPin<T, CH1, A>)>, 89 ch1: Peri<'d, if_afio!(impl TimerPin<T, CH1, A>)>,
45 ch2: Peri<'d, if_afio!(impl TimerPin<T, CH2, A>)>, 90 ch2: Peri<'d, if_afio!(impl TimerPin<T, CH2, A>)>,
46 ) -> Self { 91 ) -> Self {
92 Self::new_with_config(tim, ch1, ch2, Default::default())
93 }
94 /// Create a new quadrature decoder driver, with a given [`Config`].
95 #[allow(unused)]
96 pub fn new_with_config<CH1: QeiChannel, CH2: QeiChannel, #[cfg(afio)] A>(
97 tim: Peri<'d, T>,
98 ch1: Peri<'d, if_afio!(impl TimerPin<T, CH1, A>)>,
99 ch2: Peri<'d, if_afio!(impl TimerPin<T, CH2, A>)>,
100 config: Config,
101 ) -> Self {
47 // Configure the pins to be used for the QEI peripheral. 102 // Configure the pins to be used for the QEI peripheral.
48 critical_section::with(|_| { 103 critical_section::with(|_| {
49 ch1.set_low(); 104 ch1.set_low();
50 set_as_af!(ch1, AfType::input(Pull::None)); 105 set_as_af!(ch1, AfType::input(config.ch1_pull));
51 106
52 ch2.set_low(); 107 ch2.set_low();
53 set_as_af!(ch2, AfType::input(Pull::None)); 108 set_as_af!(ch2, AfType::input(config.ch2_pull));
54 }); 109 });
55 110
56 let inner = Timer::new(tim); 111 let inner = Timer::new(tim);
@@ -72,7 +127,7 @@ impl<'d, T: GeneralInstance4Channel> Qei<'d, T> {
72 }); 127 });
73 128
74 r.smcr().modify(|w| { 129 r.smcr().modify(|w| {
75 w.set_sms(vals::Sms::ENCODER_MODE_3); 130 w.set_sms(config.mode.into());
76 }); 131 });
77 132
78 r.arr().modify(|w| w.set_arr(u16::MAX)); 133 r.arr().modify(|w| w.set_arr(u16::MAX));