aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormelvdl <[email protected]>2025-06-26 22:55:12 +0200
committermelvdl <[email protected]>2025-06-26 22:55:12 +0200
commit1623d4e639a54f21678381b54fd6d444309dab0a (patch)
tree748af14a6435864f33ba268ff6102a1bf1c285c6
parent3e78f8a108c031f992116808b66c5e6c760c2c9e (diff)
stm32: generify timer::one_pulse and timer::qei pin constructors
-rw-r--r--embassy-stm32/src/timer/one_pulse.rs88
-rw-r--r--embassy-stm32/src/timer/qei.rs42
2 files changed, 86 insertions, 44 deletions
diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs
index 47c1d7f49..e89ad8390 100644
--- a/embassy-stm32/src/timer/one_pulse.rs
+++ b/embassy-stm32/src/timer/one_pulse.rs
@@ -7,7 +7,7 @@ use core::pin::Pin;
7use core::task::{Context, Poll}; 7use core::task::{Context, Poll};
8 8
9use super::low_level::{ 9use super::low_level::{
10 CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource, 10 CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts,
11}; 11};
12use super::{CaptureCompareInterruptHandler, ExternalTriggerPin, GeneralInstance4Channel, TimerChannel, TimerPin}; 12use super::{CaptureCompareInterruptHandler, ExternalTriggerPin, GeneralInstance4Channel, TimerChannel, TimerPin};
13pub use super::{Ch1, Ch2}; 13pub use super::{Ch1, Ch2};
@@ -46,33 +46,71 @@ pub struct TriggerPin<'d, T, C> {
46 phantom: PhantomData<(T, C)>, 46 phantom: PhantomData<(T, C)>,
47} 47}
48 48
49// TODO: Generify trigger inputs 49trait SealedTriggerSource {}
50 50
51impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ch1> { 51/// Marker trait for a trigger source.
52 /// "Create a new Ch1 trigger pin instance. 52#[expect(private_bounds)]
53 pub fn new_ch1(pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull) -> Self { 53pub trait TriggerSource: SealedTriggerSource {}
54 pin.set_as_af(pin.af_num(), AfType::input(pull)); 54
55 TriggerPin { 55impl TriggerSource for Ch1 {}
56 _pin: pin.into(), 56impl TriggerSource for Ch2 {}
57 phantom: PhantomData, 57impl TriggerSource for Ext {}
58 } 58
59impl SealedTriggerSource for Ch1 {}
60impl SealedTriggerSource for Ch2 {}
61impl SealedTriggerSource for Ext {}
62
63trait SealedTimerTriggerPin<T, S>: crate::gpio::Pin {}
64
65/// Marker trait for a trigger pin.
66#[expect(private_bounds)]
67// TODO: find better naming scheme than prefixing all pin traits with "Timer".
68// The trait name cannot conflict with the corresponding type's name.
69// Applies to other timer submodules as well.
70pub trait TimerTriggerPin<T, S>: SealedTimerTriggerPin<T, S> {
71 /// Get the AF number needed to use this pin as a trigger source.
72 fn af_num(&self) -> u8;
73}
74
75impl<T, P, C> TimerTriggerPin<T, C> for P
76where
77 T: GeneralInstance4Channel,
78 P: TimerPin<T, C>,
79 C: super::Channel + TriggerSource,
80{
81 fn af_num(&self) -> u8 {
82 TimerPin::af_num(self)
59 } 83 }
60} 84}
61 85
62impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ch2> { 86impl<T, P> TimerTriggerPin<T, Ext> for P
63 /// "Create a new Ch2 trigger pin instance. 87where
64 pub fn new_ch2(pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull) -> Self { 88 T: GeneralInstance4Channel,
65 pin.set_as_af(pin.af_num(), AfType::input(pull)); 89 P: ExternalTriggerPin<T>,
66 TriggerPin { 90{
67 _pin: pin.into(), 91 fn af_num(&self) -> u8 {
68 phantom: PhantomData, 92 ExternalTriggerPin::af_num(self)
69 }
70 } 93 }
71} 94}
72 95
73impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ext> { 96impl<T, P, C> SealedTimerTriggerPin<T, C> for P
74 /// "Create a new EXT trigger pin instance. 97where
75 pub fn new_ext(pin: Peri<'d, impl ExternalTriggerPin<T>>, pull: Pull) -> Self { 98 T: GeneralInstance4Channel,
99 P: TimerPin<T, C>,
100 C: super::Channel + TriggerSource,
101{
102}
103
104impl<T, P> SealedTimerTriggerPin<T, Ext> for P
105where
106 T: GeneralInstance4Channel,
107 P: ExternalTriggerPin<T>,
108{
109}
110
111impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> {
112 /// "Create a new Ch1 trigger pin instance.
113 pub fn new(pin: Peri<'d, impl TimerTriggerPin<T, C>>, pull: Pull) -> Self {
76 pin.set_as_af(pin.af_num(), AfType::input(pull)); 114 pin.set_as_af(pin.af_num(), AfType::input(pull));
77 TriggerPin { 115 TriggerPin {
78 _pin: pin.into(), 116 _pin: pin.into(),
@@ -103,7 +141,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
103 ) -> Self { 141 ) -> Self {
104 let mut this = Self { inner: Timer::new(tim) }; 142 let mut this = Self { inner: Timer::new(tim) };
105 143
106 this.inner.set_trigger_source(TriggerSource::TI1F_ED); 144 this.inner.set_trigger_source(Ts::TI1F_ED);
107 this.inner 145 this.inner
108 .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); 146 .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal);
109 this.inner 147 this.inner
@@ -128,7 +166,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
128 ) -> Self { 166 ) -> Self {
129 let mut this = Self { inner: Timer::new(tim) }; 167 let mut this = Self { inner: Timer::new(tim) };
130 168
131 this.inner.set_trigger_source(TriggerSource::TI1FP1); 169 this.inner.set_trigger_source(Ts::TI1FP1);
132 this.inner 170 this.inner
133 .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); 171 .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal);
134 this.inner 172 this.inner
@@ -154,7 +192,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
154 ) -> Self { 192 ) -> Self {
155 let mut this = Self { inner: Timer::new(tim) }; 193 let mut this = Self { inner: Timer::new(tim) };
156 194
157 this.inner.set_trigger_source(TriggerSource::TI2FP2); 195 this.inner.set_trigger_source(Ts::TI2FP2);
158 this.inner 196 this.inner
159 .set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal); 197 .set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal);
160 this.inner 198 this.inner
@@ -186,7 +224,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
186 // No filtering 224 // No filtering
187 r.set_etf(FilterValue::NO_FILTER); 225 r.set_etf(FilterValue::NO_FILTER);
188 }); 226 });
189 this.inner.set_trigger_source(TriggerSource::ETRF); 227 this.inner.set_trigger_source(Ts::ETRF);
190 this.new_inner(freq, pulse_end, counting_mode); 228 this.new_inner(freq, pulse_end, counting_mode);
191 229
192 this 230 this
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index bc7e71290..657052cfa 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -8,6 +8,7 @@ use super::low_level::Timer;
8pub use super::{Ch1, Ch2}; 8pub use super::{Ch1, Ch2};
9use super::{GeneralInstance4Channel, TimerPin}; 9use super::{GeneralInstance4Channel, TimerPin};
10use crate::gpio::{AfType, AnyPin, Pull}; 10use crate::gpio::{AfType, AnyPin, Pull};
11use crate::timer::Channel;
11use crate::Peri; 12use crate::Peri;
12 13
13/// Counting direction 14/// Counting direction
@@ -24,28 +25,31 @@ pub struct QeiPin<'d, T, Channel> {
24 phantom: PhantomData<(T, Channel)>, 25 phantom: PhantomData<(T, Channel)>,
25} 26}
26 27
27// TODO: generify QEI channels 28impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> {
28 29 /// Create a new QEI pin instance.
29macro_rules! channel_impl { 30 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>) -> Self {
30 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 31 critical_section::with(|_| {
31 impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> { 32 pin.set_low();
32 #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] 33 pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
33 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T, $channel>>) -> Self { 34 });
34 critical_section::with(|_| { 35 QeiPin {
35 pin.set_low(); 36 _pin: pin.into(),
36 pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); 37 phantom: PhantomData,
37 });
38 QeiPin {
39 _pin: pin.into(),
40 phantom: PhantomData,
41 }
42 }
43 } 38 }
44 }; 39 }
45} 40}
46 41
47channel_impl!(new_ch1, Ch1, TimerPin); 42trait SealedQeiChannel: Channel {}
48channel_impl!(new_ch2, Ch2, TimerPin); 43
44/// Marker trait for a timer channel eligible for use with QEI.
45#[expect(private_bounds)]
46pub trait QeiChannel: SealedQeiChannel {}
47
48impl QeiChannel for Ch1 {}
49impl QeiChannel for Ch2 {}
50
51impl SealedQeiChannel for Ch1 {}
52impl SealedQeiChannel for Ch2 {}
49 53
50/// Quadrature decoder driver. 54/// Quadrature decoder driver.
51pub struct Qei<'d, T: GeneralInstance4Channel> { 55pub struct Qei<'d, T: GeneralInstance4Channel> {