1use core::future::Future;
4use core::marker::PhantomData;
5use core::mem::ManuallyDrop;
6use core::pin::Pin;
7use core::task::{Context, Poll};
8
9use super::low_level::{
10 CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts,
11};
12use super::{CaptureCompareInterruptHandler, Channel, ExternalTriggerPin, GeneralInstance4Channel, TimerPin};
13pub use super::{Ch1, Ch2};
14use crate::gpio::{AfType, AnyPin, Pull};
15use crate::interrupt::typelevel::{Binding, Interrupt};
16use crate::pac::timer::vals::Etp;
17use crate::time::Hertz;
18use crate::Peri;
19
20pub enum Ext {}
22
23#[derive(Clone, Copy)]
25pub enum ExternalTriggerPolarity {
26 Rising,
28 Falling,
30}
31
32impl From<ExternalTriggerPolarity> for Etp {
33 fn from(mode: ExternalTriggerPolarity) -> Self {
34 match mode {
35 ExternalTriggerPolarity::Rising => 0.into(),
36 ExternalTriggerPolarity::Falling => 1.into(),
37 }
38 }
39}
40
41pub struct TriggerPin<'d, T, C> {
45 _pin: Peri<'d, AnyPin>,
46 phantom: PhantomData<(T, C)>,
47}
48
49trait SealedTriggerSource {}
50
51#[expect(private_bounds)]
53pub trait TriggerSource: SealedTriggerSource {}
54
55impl TriggerSource for Ch1 {}
56impl TriggerSource for Ch2 {}
57impl TriggerSource for Ext {}
58
59impl SealedTriggerSource for Ch1 {}
60impl SealedTriggerSource for Ch2 {}
61impl SealedTriggerSource for Ext {}
62
63trait SealedTimerTriggerPin<T, S>: crate::gpio::Pin {}
64
65#[expect(private_bounds)]
67pub trait TimerTriggerPin<T, S>: SealedTimerTriggerPin<T, S> {
71 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::TimerChannel + TriggerSource,
80{
81 fn af_num(&self) -> u8 {
82 TimerPin::af_num(self)
83 }
84}
85
86impl<T, P> TimerTriggerPin<T, Ext> for P
87where
88 T: GeneralInstance4Channel,
89 P: ExternalTriggerPin<T>,
90{
91 fn af_num(&self) -> u8 {
92 ExternalTriggerPin::af_num(self)
93 }
94}
95
96impl<T, P, C> SealedTimerTriggerPin<T, C> for P
97where
98 T: GeneralInstance4Channel,
99 P: TimerPin<T, C>,
100 C: super::TimerChannel + 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 pub fn new(pin: Peri<'d, impl TimerTriggerPin<T, C>>, pull: Pull) -> Self {
114 pin.set_as_af(pin.af_num(), AfType::input(pull));
115 TriggerPin {
116 _pin: pin.into(),
117 phantom: PhantomData,
118 }
119 }
120}
121
122pub struct OnePulse<'d, T: GeneralInstance4Channel> {
126 inner: Timer<'d, T>,
127}
128
129impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
130 pub fn new_ch1_edge_detect(
135 tim: Peri<'d, T>,
136 _pin: TriggerPin<'d, T, Ch1>,
137 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
138 freq: Hertz,
139 pulse_end: u32,
140 counting_mode: CountingMode,
141 ) -> Self {
142 let mut this = Self { inner: Timer::new(tim) };
143
144 this.inner.set_trigger_source(Ts::TI1F_ED);
145 this.inner
146 .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
147 this.inner
148 .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER);
149 this.new_inner(freq, pulse_end, counting_mode);
150
151 this
152 }
153
154 pub fn new_ch1(
159 tim: Peri<'d, T>,
160 _pin: TriggerPin<'d, T, Ch1>,
161 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
162 freq: Hertz,
163 pulse_end: u32,
164 counting_mode: CountingMode,
165 capture_mode: InputCaptureMode,
166 ) -> Self {
167 let mut this = Self { inner: Timer::new(tim) };
168
169 this.inner.set_trigger_source(Ts::TI1FP1);
170 this.inner
171 .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
172 this.inner
173 .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER);
174 this.inner.set_input_capture_mode(Channel::Ch1, capture_mode);
175 this.new_inner(freq, pulse_end, counting_mode);
176
177 this
178 }
179
180 pub fn new_ch2(
185 tim: Peri<'d, T>,
186 _pin: TriggerPin<'d, T, Ch2>,
187 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
188 freq: Hertz,
189 pulse_end: u32,
190 counting_mode: CountingMode,
191 capture_mode: InputCaptureMode,
192 ) -> Self {
193 let mut this = Self { inner: Timer::new(tim) };
194
195 this.inner.set_trigger_source(Ts::TI2FP2);
196 this.inner
197 .set_input_ti_selection(Channel::Ch2, InputTISelection::Normal);
198 this.inner
199 .set_input_capture_filter(Channel::Ch2, FilterValue::NO_FILTER);
200 this.inner.set_input_capture_mode(Channel::Ch2, capture_mode);
201 this.new_inner(freq, pulse_end, counting_mode);
202
203 this
204 }
205
206 pub fn new_ext(
210 tim: Peri<'d, T>,
211 _pin: TriggerPin<'d, T, Ext>,
212 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
213 freq: Hertz,
214 pulse_end: u32,
215 counting_mode: CountingMode,
216 polarity: ExternalTriggerPolarity,
217 ) -> Self {
218 let mut this = Self { inner: Timer::new(tim) };
219
220 this.inner.regs_gp16().smcr().modify(|r| {
221 r.set_etp(polarity.into());
222 r.set_etps(0.into());
224 r.set_etf(FilterValue::NO_FILTER);
226 });
227 this.inner.set_trigger_source(Ts::ETRF);
228 this.new_inner(freq, pulse_end, counting_mode);
229
230 this
231 }
232
233 fn new_inner(&mut self, freq: Hertz, pulse_end: u32, counting_mode: CountingMode) {
234 self.inner.set_counting_mode(counting_mode);
235 self.inner.set_tick_freq(freq);
236 self.inner.set_max_compare_value(pulse_end);
237 self.inner.regs_core().cr1().modify(|r| r.set_opm(true));
238 self.inner.enable_outputs();
240 self.inner.set_slave_mode(SlaveMode::TRIGGER_MODE);
241
242 T::CaptureCompareInterrupt::unpend();
243 unsafe { T::CaptureCompareInterrupt::enable() };
244 }
245
246 pub fn pulse_end(&self) -> u32 {
248 let max = self.inner.get_max_compare_value();
249 assert!(max < u32::MAX);
250 max + 1
251 }
252
253 pub fn set_pulse_end(&mut self, ticks: u32) {
255 self.inner.set_max_compare_value(ticks)
256 }
257
258 #[cfg(not(stm32l0))]
260 pub fn set_reset_on_trigger(&mut self, reset: bool) {
261 let slave_mode = if reset {
262 SlaveMode::COMBINED_RESET_TRIGGER
263 } else {
264 SlaveMode::TRIGGER_MODE
265 };
266 self.inner.set_slave_mode(slave_mode);
267 }
268
269 pub fn channel(&mut self, channel: Channel) -> OnePulseChannel<'_, T> {
273 OnePulseChannel {
274 inner: unsafe { self.inner.clone_unchecked() },
275 channel,
276 }
277 }
278
279 pub fn ch1(&mut self) -> OnePulseChannel<'_, T> {
285 self.channel(Channel::Ch1)
286 }
287
288 pub fn ch2(&mut self) -> OnePulseChannel<'_, T> {
294 self.channel(Channel::Ch2)
295 }
296
297 pub fn ch3(&mut self) -> OnePulseChannel<'_, T> {
303 self.channel(Channel::Ch3)
304 }
305
306 pub fn ch4(&mut self) -> OnePulseChannel<'_, T> {
312 self.channel(Channel::Ch4)
313 }
314
315 pub fn split(self) -> OnePulseChannels<'static, T>
318 where
319 'd: 'static,
321 {
322 let timer = ManuallyDrop::new(self.inner);
324
325 let ch = |channel| OnePulseChannel {
326 inner: unsafe { timer.clone_unchecked() },
327 channel,
328 };
329
330 OnePulseChannels {
331 ch1: ch(Channel::Ch1),
332 ch2: ch(Channel::Ch2),
333 ch3: ch(Channel::Ch3),
334 ch4: ch(Channel::Ch4),
335 }
336 }
337}
338
339pub struct OnePulseChannels<'d, T: GeneralInstance4Channel> {
341 pub ch1: OnePulseChannel<'d, T>,
343 pub ch2: OnePulseChannel<'d, T>,
345 pub ch3: OnePulseChannel<'d, T>,
347 pub ch4: OnePulseChannel<'d, T>,
349}
350
351pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> {
357 inner: ManuallyDrop<Timer<'d, T>>,
358 channel: Channel,
359}
360
361impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> {
362 pub fn pulse_end(&self) -> u32 {
364 let max = self.inner.get_max_compare_value();
365 assert!(max < u32::MAX);
366 max + 1
367 }
368
369 pub fn pulse_width(&mut self) -> u32 {
371 self.pulse_end().saturating_sub(self.pulse_delay())
372 }
373
374 pub fn pulse_delay(&mut self) -> u32 {
376 self.inner.get_compare_value(self.channel)
377 }
378
379 pub fn set_pulse_delay(&mut self, delay: u32) {
381 assert!(delay <= self.pulse_end());
382 self.inner.set_compare_value(self.channel, delay);
383 }
384
385 pub fn set_pulse_width(&mut self, width: u32) {
387 assert!(width <= self.pulse_end());
388 self.set_pulse_delay(self.pulse_end() - width);
389 }
390
391 pub async fn wait_for_pulse_start(&mut self) {
393 self.inner.enable_input_interrupt(self.channel, true);
394
395 OnePulseFuture::<T> {
396 channel: self.channel,
397 phantom: PhantomData,
398 }
399 .await
400 }
401}
402
403#[must_use = "futures do nothing unless you `.await` or poll them"]
404struct OnePulseFuture<T: GeneralInstance4Channel> {
405 channel: Channel,
406 phantom: PhantomData<T>,
407}
408
409impl<'d, T: GeneralInstance4Channel> Drop for OnePulseFuture<T> {
410 fn drop(&mut self) {
411 critical_section::with(|_| {
412 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
413
414 regs.dier().modify(|w| w.set_ccie(self.channel.index(), false));
416 });
417 }
418}
419
420impl<'d, T: GeneralInstance4Channel> Future for OnePulseFuture<T> {
421 type Output = ();
422
423 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
424 T::state().cc_waker[self.channel.index()].register(cx.waker());
425
426 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
427
428 let dier = regs.dier().read();
429 if !dier.ccie(self.channel.index()) {
430 Poll::Ready(())
431 } else {
432 Poll::Pending
433 }
434 }
435}