1use core::mem::ManuallyDrop;
10
11use embassy_hal_internal::Peri;
12pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource};
14
15use super::*;
16use crate::pac::timer::vals;
17use crate::rcc;
18use crate::time::Hertz;
19
20#[derive(Clone, Copy)]
22pub enum InputCaptureMode {
23 Rising,
25 Falling,
27 BothEdges,
29}
30
31#[derive(Clone, Copy)]
33pub enum InputTISelection {
34 Normal,
36 Alternate,
38 TRC,
40}
41
42impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs {
43 fn from(tisel: InputTISelection) -> Self {
44 match tisel {
45 InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4,
46 InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3,
47 InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC,
48 }
49 }
50}
51
52#[repr(u8)]
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
55pub enum CountingMode {
56 #[default]
57 EdgeAlignedUp,
59 EdgeAlignedDown,
61 CenterAlignedDownInterrupts,
66 CenterAlignedUpInterrupts,
71 CenterAlignedBothInterrupts,
76}
77
78impl CountingMode {
79 pub fn is_edge_aligned(&self) -> bool {
81 matches!(self, CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown)
82 }
83
84 pub fn is_center_aligned(&self) -> bool {
86 matches!(
87 self,
88 CountingMode::CenterAlignedDownInterrupts
89 | CountingMode::CenterAlignedUpInterrupts
90 | CountingMode::CenterAlignedBothInterrupts
91 )
92 }
93}
94
95impl From<CountingMode> for (vals::Cms, vals::Dir) {
96 fn from(value: CountingMode) -> Self {
97 match value {
98 CountingMode::EdgeAlignedUp => (vals::Cms::EDGE_ALIGNED, vals::Dir::UP),
99 CountingMode::EdgeAlignedDown => (vals::Cms::EDGE_ALIGNED, vals::Dir::DOWN),
100 CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTER_ALIGNED1, vals::Dir::UP),
101 CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTER_ALIGNED2, vals::Dir::UP),
102 CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTER_ALIGNED3, vals::Dir::UP),
103 }
104 }
105}
106
107impl From<(vals::Cms, vals::Dir)> for CountingMode {
108 fn from(value: (vals::Cms, vals::Dir)) -> Self {
109 match value {
110 (vals::Cms::EDGE_ALIGNED, vals::Dir::UP) => CountingMode::EdgeAlignedUp,
111 (vals::Cms::EDGE_ALIGNED, vals::Dir::DOWN) => CountingMode::EdgeAlignedDown,
112 (vals::Cms::CENTER_ALIGNED1, _) => CountingMode::CenterAlignedDownInterrupts,
113 (vals::Cms::CENTER_ALIGNED2, _) => CountingMode::CenterAlignedUpInterrupts,
114 (vals::Cms::CENTER_ALIGNED3, _) => CountingMode::CenterAlignedBothInterrupts,
115 }
116 }
117}
118
119#[derive(Clone, Copy)]
121pub enum OutputCompareMode {
122 Frozen,
126 ActiveOnMatch,
129 InactiveOnMatch,
132 Toggle,
134 ForceInactive,
136 ForceActive,
138 PwmMode1,
142 PwmMode2,
146 }
148
149impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
150 fn from(mode: OutputCompareMode) -> Self {
151 match mode {
152 OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN,
153 OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVE_ON_MATCH,
154 OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVE_ON_MATCH,
155 OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE,
156 OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCE_INACTIVE,
157 OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCE_ACTIVE,
158 OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWM_MODE1,
159 OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWM_MODE2,
160 }
161 }
162}
163
164#[derive(Clone, Copy)]
166pub enum OutputPolarity {
167 ActiveHigh,
169 ActiveLow,
171}
172
173impl From<OutputPolarity> for bool {
174 fn from(mode: OutputPolarity) -> Self {
175 match mode {
176 OutputPolarity::ActiveHigh => false,
177 OutputPolarity::ActiveLow => true,
178 }
179 }
180}
181
182pub struct Timer<'d, T: CoreInstance> {
184 tim: Peri<'d, T>,
185}
186
187impl<'d, T: CoreInstance> Drop for Timer<'d, T> {
188 fn drop(&mut self) {
189 rcc::disable::<T>();
190 }
191}
192
193impl<'d, T: CoreInstance> Timer<'d, T> {
194 pub fn new(tim: Peri<'d, T>) -> Self {
196 rcc::enable_and_reset::<T>();
197
198 Self { tim }
199 }
200
201 pub(crate) unsafe fn clone_unchecked(&self) -> ManuallyDrop<Self> {
202 let tim = unsafe { self.tim.clone_unchecked() };
203 ManuallyDrop::new(Self { tim })
204 }
205
206 pub fn regs_core(&self) -> crate::pac::timer::TimCore {
213 unsafe { crate::pac::timer::TimCore::from_ptr(T::regs()) }
214 }
215
216 #[cfg(not(stm32l0))]
217 fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp32 {
218 unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) }
219 }
220
221 pub fn start(&self) {
223 self.regs_core().cr1().modify(|r| r.set_cen(true));
224 }
225
226 pub fn stop(&self) {
228 self.regs_core().cr1().modify(|r| r.set_cen(false));
229 }
230
231 pub fn reset(&self) {
233 self.regs_core().cnt().write(|r| r.set_cnt(0));
234 }
235
236 pub fn bits(&self) -> TimerBits {
238 T::BITS
239 }
240
241 pub fn set_frequency(&self, frequency: Hertz) {
248 match T::BITS {
249 TimerBits::Bits16 => {
250 self.set_frequency_internal(frequency, 16);
251 }
252 #[cfg(not(stm32l0))]
253 TimerBits::Bits32 => {
254 self.set_frequency_internal(frequency, 32);
255 }
256 }
257 }
258
259 pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: u8) {
260 let f = frequency.0;
261 assert!(f > 0);
262 let timer_f = T::frequency().0;
263
264 let pclk_ticks_per_timer_period = (timer_f / f) as u64;
265 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << max_divide_by_bits)).try_into());
266 let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1);
267
268 match T::BITS {
269 TimerBits::Bits16 => {
270 let arr = unwrap!(u16::try_from(divide_by - 1));
272
273 let regs = self.regs_core();
274 regs.psc().write_value(psc);
275 regs.arr().write(|r| r.set_arr(arr));
276
277 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
278 regs.egr().write(|r| r.set_ug(true));
279 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
280 }
281 #[cfg(not(stm32l0))]
282 TimerBits::Bits32 => {
283 let arr: u32 = unwrap!(u32::try_from(divide_by - 1));
285
286 let regs = self.regs_gp32_unchecked();
287 regs.psc().write_value(psc);
288 regs.arr().write_value(arr);
289
290 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
291 regs.egr().write(|r| r.set_ug(true));
292 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
293 }
294 }
295 }
296
297 pub fn set_tick_freq(&mut self, freq: Hertz) {
299 let f = freq;
300 assert!(f.0 > 0);
301 let timer_f = self.get_clock_frequency();
302
303 let pclk_ticks_per_timer_period = timer_f / f;
304 let psc: u16 = unwrap!((pclk_ticks_per_timer_period - 1).try_into());
305
306 let regs = self.regs_core();
307 regs.psc().write_value(psc);
308
309 regs.egr().write(|r| r.set_ug(true));
311 }
312
313 pub fn clear_update_interrupt(&self) -> bool {
317 let regs = self.regs_core();
318 let sr = regs.sr().read();
319 if sr.uif() {
320 regs.sr().modify(|r| {
321 r.set_uif(false);
322 });
323 true
324 } else {
325 false
326 }
327 }
328
329 pub fn enable_update_interrupt(&self, enable: bool) {
331 self.regs_core().dier().modify(|r| r.set_uie(enable));
332 }
333
334 pub fn set_autoreload_preload(&self, enable: bool) {
336 self.regs_core().cr1().modify(|r| r.set_arpe(enable));
337 }
338
339 pub fn get_frequency(&self) -> Hertz {
341 let timer_f = T::frequency();
342
343 match T::BITS {
344 TimerBits::Bits16 => {
345 let regs = self.regs_core();
346 let arr = regs.arr().read().arr();
347 let psc = regs.psc().read();
348
349 timer_f / arr / (psc + 1)
350 }
351 #[cfg(not(stm32l0))]
352 TimerBits::Bits32 => {
353 let regs = self.regs_gp32_unchecked();
354 let arr = regs.arr().read();
355 let psc = regs.psc().read();
356
357 timer_f / arr / (psc + 1)
358 }
359 }
360 }
361
362 pub fn get_clock_frequency(&self) -> Hertz {
364 T::frequency()
365 }
366}
367
368impl<'d, T: BasicNoCr2Instance> Timer<'d, T> {
369 pub fn regs_basic_no_cr2(&self) -> crate::pac::timer::TimBasicNoCr2 {
376 unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(T::regs()) }
377 }
378
379 pub fn enable_update_dma(&self, enable: bool) {
381 self.regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable));
382 }
383
384 pub fn get_update_dma_state(&self) -> bool {
386 self.regs_basic_no_cr2().dier().read().ude()
387 }
388}
389
390impl<'d, T: BasicInstance> Timer<'d, T> {
391 pub fn regs_basic(&self) -> crate::pac::timer::TimBasic {
398 unsafe { crate::pac::timer::TimBasic::from_ptr(T::regs()) }
399 }
400}
401
402impl<'d, T: GeneralInstance1Channel> Timer<'d, T> {
403 pub fn regs_1ch(&self) -> crate::pac::timer::Tim1ch {
410 unsafe { crate::pac::timer::Tim1ch::from_ptr(T::regs()) }
411 }
412
413 pub fn set_clock_division(&self, ckd: vals::Ckd) {
415 self.regs_1ch().cr1().modify(|r| r.set_ckd(ckd));
416 }
417
418 pub fn get_max_compare_value(&self) -> u32 {
420 match T::BITS {
421 TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32,
422 #[cfg(not(stm32l0))]
423 TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(),
424 }
425 }
426
427 pub fn set_max_compare_value(&self, ticks: u32) {
432 match T::BITS {
433 TimerBits::Bits16 => {
434 let arr = unwrap!(u16::try_from(ticks));
435
436 let regs = self.regs_1ch();
437 regs.arr().write(|r| r.set_arr(arr));
438
439 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
440 regs.egr().write(|r| r.set_ug(true));
441 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
442 }
443 #[cfg(not(stm32l0))]
444 TimerBits::Bits32 => {
445 let arr = ticks;
446
447 let regs = self.regs_gp32_unchecked();
448 regs.arr().write_value(arr);
449
450 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
451 regs.egr().write(|r| r.set_ug(true));
452 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
453 }
454 }
455 }
456}
457
458impl<'d, T: GeneralInstance2Channel> Timer<'d, T> {
459 pub fn regs_2ch(&self) -> crate::pac::timer::Tim2ch {
466 unsafe { crate::pac::timer::Tim2ch::from_ptr(T::regs()) }
467 }
468}
469
470impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
471 pub fn regs_gp16(&self) -> crate::pac::timer::TimGp16 {
478 unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) }
479 }
480
481 pub fn enable_outputs(&self) {
483 self.tim.enable_outputs()
484 }
485
486 pub fn set_counting_mode(&self, mode: CountingMode) {
488 let (cms, dir) = mode.into();
489
490 let timer_enabled = self.regs_core().cr1().read().cen();
491 assert!(!timer_enabled);
494
495 self.regs_gp16().cr1().modify(|r| r.set_dir(dir));
496 self.regs_gp16().cr1().modify(|r| r.set_cms(cms))
497 }
498
499 pub fn get_counting_mode(&self) -> CountingMode {
501 let cr1 = self.regs_gp16().cr1().read();
502 (cr1.cms(), cr1.dir()).into()
503 }
504
505 pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) {
507 let raw_channel = channel.index();
508 self.regs_gp16()
509 .ccmr_input(raw_channel / 2)
510 .modify(|r| r.set_icf(raw_channel % 2, icf));
511 }
512
513 pub fn clear_input_interrupt(&self, channel: Channel) {
515 self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
516 }
517
518 pub fn get_input_interrupt(&self, channel: Channel) -> bool {
520 self.regs_gp16().sr().read().ccif(channel.index())
521 }
522
523 pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) {
525 self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
526 }
527
528 pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) {
530 let raw_channel = channel.index();
531 self.regs_gp16()
532 .ccmr_input(raw_channel / 2)
533 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
534 }
535
536 pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) {
538 let raw_channel = channel.index();
539 self.regs_gp16()
540 .ccmr_input(raw_channel / 2)
541 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
542 }
543
544 pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) {
546 self.regs_gp16().ccer().modify(|r| match mode {
547 InputCaptureMode::Rising => {
548 r.set_ccnp(channel.index(), false);
549 r.set_ccp(channel.index(), false);
550 }
551 InputCaptureMode::Falling => {
552 r.set_ccnp(channel.index(), false);
553 r.set_ccp(channel.index(), true);
554 }
555 InputCaptureMode::BothEdges => {
556 r.set_ccnp(channel.index(), true);
557 r.set_ccp(channel.index(), true);
558 }
559 });
560 }
561
562 pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) {
564 let raw_channel: usize = channel.index();
565 self.regs_gp16()
566 .ccmr_output(raw_channel / 2)
567 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
568 }
569
570 pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
572 self.regs_gp16()
573 .ccer()
574 .modify(|w| w.set_ccp(channel.index(), polarity.into()));
575 }
576
577 pub fn enable_channel(&self, channel: Channel, enable: bool) {
579 self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
580 }
581
582 pub fn get_channel_enable_state(&self, channel: Channel) -> bool {
584 self.regs_gp16().ccer().read().cce(channel.index())
585 }
586
587 pub fn set_compare_value(&self, channel: Channel, value: u32) {
589 match T::BITS {
590 TimerBits::Bits16 => {
591 let value = unwrap!(u16::try_from(value));
592 self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value));
593 }
594 #[cfg(not(stm32l0))]
595 TimerBits::Bits32 => {
596 self.regs_gp32_unchecked().ccr(channel.index()).write_value(value);
597 }
598 }
599 }
600
601 pub fn get_compare_value(&self, channel: Channel) -> u32 {
603 match T::BITS {
604 TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32,
605 #[cfg(not(stm32l0))]
606 TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(),
607 }
608 }
609
610 pub fn get_capture_value(&self, channel: Channel) -> u32 {
612 self.get_compare_value(channel)
613 }
614
615 pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) {
617 let channel_index = channel.index();
618 self.regs_gp16()
619 .ccmr_output(channel_index / 2)
620 .modify(|w| w.set_ocpe(channel_index % 2, preload));
621 }
622
623 pub fn get_cc_dma_selection(&self) -> vals::Ccds {
625 self.regs_gp16().cr2().read().ccds()
626 }
627
628 pub fn set_cc_dma_selection(&self, ccds: vals::Ccds) {
630 self.regs_gp16().cr2().modify(|w| w.set_ccds(ccds))
631 }
632
633 pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
635 self.regs_gp16().dier().read().ccde(channel.index())
636 }
637
638 pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) {
640 self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
641 }
642
643 pub fn set_slave_mode(&self, sms: SlaveMode) {
645 self.regs_gp16().smcr().modify(|r| r.set_sms(sms));
646 }
647
648 pub fn set_trigger_source(&self, ts: TriggerSource) {
650 self.regs_gp16().smcr().modify(|r| r.set_ts(ts));
651 }
652}
653
654#[cfg(not(stm32l0))]
655impl<'d, T: GeneralInstance32bit4Channel> Timer<'d, T> {
656 pub fn regs_gp32(&self) -> crate::pac::timer::TimGp32 {
663 unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) }
664 }
665}
666
667#[cfg(not(stm32l0))]
668impl<'d, T: AdvancedInstance1Channel> Timer<'d, T> {
669 pub fn regs_1ch_cmp(&self) -> crate::pac::timer::Tim1chCmp {
676 unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) }
677 }
678
679 pub fn set_dead_time_clock_division(&self, value: vals::Ckd) {
681 self.regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value));
682 }
683
684 pub fn set_dead_time_value(&self, value: u8) {
686 self.regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value));
687 }
688
689 pub fn set_ossi(&self, val: vals::Ossi) {
691 self.regs_1ch_cmp().bdtr().modify(|w| w.set_ossi(val));
692 }
693
694 pub fn get_ossi(&self) -> vals::Ossi {
696 self.regs_1ch_cmp().bdtr().read().ossi()
697 }
698
699 pub fn set_ossr(&self, val: vals::Ossr) {
701 self.regs_1ch_cmp().bdtr().modify(|w| w.set_ossr(val));
702 }
703
704 pub fn get_ossr(&self) -> vals::Ossr {
706 self.regs_1ch_cmp().bdtr().read().ossr()
707 }
708
709 pub fn set_moe(&self, enable: bool) {
711 self.regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable));
712 }
713
714 pub fn get_moe(&self) -> bool {
716 self.regs_1ch_cmp().bdtr().read().moe()
717 }
718}
719
720#[cfg(not(stm32l0))]
721impl<'d, T: AdvancedInstance2Channel> Timer<'d, T> {
722 pub fn regs_2ch_cmp(&self) -> crate::pac::timer::Tim2chCmp {
729 unsafe { crate::pac::timer::Tim2chCmp::from_ptr(T::regs()) }
730 }
731}
732
733#[cfg(not(stm32l0))]
734impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> {
735 pub fn regs_advanced(&self) -> crate::pac::timer::TimAdv {
737 unsafe { crate::pac::timer::TimAdv::from_ptr(T::regs()) }
738 }
739
740 pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
742 self.regs_advanced()
743 .ccer()
744 .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
745 }
746
747 pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) {
749 self.regs_advanced()
750 .ccer()
751 .modify(|w| w.set_ccne(channel.index(), enable));
752 }
753
754 pub fn set_ois(&self, channel: Channel, val: bool) {
756 self.regs_advanced().cr2().modify(|w| w.set_ois(channel.index(), val));
757 }
758 pub fn set_oisn(&self, channel: Channel, val: bool) {
760 self.regs_advanced().cr2().modify(|w| w.set_oisn(channel.index(), val));
761 }
762
763 pub fn trigger_software_break(&self, n: usize) {
766 self.regs_advanced().egr().write(|r| r.set_bg(n, true));
767 }
768}