stm32g0xx_hal/timer/
opm.rs

1//! # One-pulse Mode
2use crate::rcc::*;
3use crate::stm32::*;
4use crate::time::{Hertz, MicroSecond};
5use crate::timer::pins::TimerPin;
6use crate::timer::*;
7use core::marker::PhantomData;
8use fugit::RateExtU32;
9
10pub trait OpmExt: Sized {
11    fn opm(self, period: MicroSecond, rcc: &mut Rcc) -> Opm<Self>;
12}
13
14pub struct OpmPin<TIM, CH> {
15    tim: PhantomData<TIM>,
16    channel: PhantomData<CH>,
17    delay: u32,
18}
19
20pub struct Opm<TIM> {
21    tim: PhantomData<TIM>,
22    clk: Hertz,
23}
24
25impl<TIM> Opm<TIM> {
26    pub fn bind_pin<PIN>(&self, pin: PIN) -> OpmPin<TIM, PIN::Channel>
27    where
28        PIN: TimerPin<TIM>,
29    {
30        pin.setup();
31        OpmPin {
32            tim: PhantomData,
33            channel: PhantomData,
34            delay: 1,
35        }
36    }
37}
38
39macro_rules! opm {
40    ($($TIMX:ident: ($timX:ident, $arr:ident $(,$arr_h:ident)*),)+) => {
41        $(
42            impl OpmExt for $TIMX {
43                fn opm(self, pulse: MicroSecond, rcc: &mut Rcc) -> Opm<Self> {
44                    $timX(self, pulse, rcc)
45                }
46            }
47
48            fn $timX(_tim: $TIMX, pulse: MicroSecond, rcc: &mut Rcc) -> Opm<$TIMX> {
49                $TIMX::enable(rcc);
50                $TIMX::reset(rcc);
51
52                let mut opm = Opm::<$TIMX> {
53                    clk: rcc.clocks.apb_tim_clk,
54                    tim: PhantomData,
55                };
56                opm.set_pulse(pulse);
57                opm
58            }
59
60            impl Opm<$TIMX> {
61                pub fn set_pulse(&mut self, pulse: MicroSecond) {
62                    let pulsehz: Hertz = pulse.into_rate();
63                    let cycles_per_period = self.clk / pulsehz;
64                    let psc = (cycles_per_period - 1) / 0xffff;
65                    let freq = (self.clk.raw() / (psc + 1)).Hz();
66                    let reload = crate::time::cycles(pulse, freq);
67                    unsafe {
68                        let tim = &*$TIMX::ptr();
69                        tim.psc.write(|w| w.psc().bits(psc as u16));
70                        tim.arr.write(|w| w.$arr().bits(reload as u16));
71                        $(
72                            tim.arr.modify(|_, w| w.$arr_h().bits((reload >> 16) as u16));
73                        )*
74                    }
75                }
76
77                pub fn generate(&mut self) {
78                    let tim =  unsafe {&*$TIMX::ptr()};
79                    tim.cr1.write(|w| w.opm().set_bit().cen().set_bit());
80                }
81            }
82        )+
83    }
84}
85
86macro_rules! opm_hal {
87    ($($TIMX:ident:
88        ($CH:ty, $ccxe:ident, $ccmrx_output:ident, $ocxm:ident, $ocxfe:ident, $ccrx:ident),)+
89    ) => {
90        $(
91            impl OpmPin<$TIMX, $CH> {
92                pub fn enable(&mut self) {
93                    let tim =  unsafe {&*$TIMX::ptr()};
94                    tim.ccer.modify(|_, w| w.$ccxe().set_bit());
95                    self.setup();
96                }
97
98                pub fn disable(&mut self) {
99                    let tim =  unsafe {&*$TIMX::ptr()};
100                    tim.ccer.modify(|_, w| w.$ccxe().clear_bit());
101                }
102
103                pub fn get_max_delay(&mut self) -> u32 {
104                    unsafe { (*$TIMX::ptr()).arr.read().bits() }
105                }
106
107                pub fn set_delay(&mut self, delay: u32) {
108                    self.delay = delay;
109                    self.setup();
110                }
111
112                fn setup(&mut self) {
113                    unsafe {
114                        let tim = &*$TIMX::ptr();
115                        tim.$ccrx.write(|w| w.bits(self.delay));
116                        tim.$ccmrx_output().modify(|_, w| w.$ocxm().bits(7).$ocxfe().set_bit());
117                    }
118                }
119            }
120        )+
121    };
122}
123
124opm_hal! {
125    TIM1: (Channel1, cc1e, ccmr1_output, oc1m, oc1fe, ccr1),
126    TIM1: (Channel2, cc2e, ccmr1_output, oc2m, oc2fe, ccr2),
127    TIM1: (Channel3, cc3e, ccmr2_output, oc3m, oc3fe, ccr3),
128    TIM1: (Channel4, cc4e, ccmr2_output, oc4m, oc4fe, ccr4),
129    TIM3: (Channel1, cc1e, ccmr1_output, oc1m, oc1fe, ccr1),
130    TIM3: (Channel2, cc2e, ccmr1_output, oc2m, oc2fe, ccr2),
131    TIM3: (Channel3, cc3e, ccmr2_output, oc3m, oc3fe, ccr3),
132    TIM3: (Channel4, cc4e, ccmr2_output, oc4m, oc4fe, ccr4),
133    TIM14: (Channel1, cc1e, ccmr1_output, oc1m, oc1fe, ccr1),
134    TIM16: (Channel1, cc1e, ccmr1_output, oc1m, oc1fe, ccr1),
135    TIM17: (Channel1, cc1e, ccmr1_output, oc1m, oc1fe, ccr1),
136}
137
138#[cfg(feature = "stm32g0x1")]
139opm_hal! {
140    TIM2: (Channel1, cc1e, ccmr1_output, oc1m, oc1fe, ccr1),
141    TIM2: (Channel2, cc2e, ccmr1_output, oc2m, oc2fe, ccr2),
142    TIM2: (Channel3, cc3e, ccmr2_output, oc3m, oc3fe, ccr3),
143    TIM2: (Channel4, cc4e, ccmr2_output, oc4m, oc4fe, ccr4),
144}
145
146opm! {
147    TIM1: (tim1, arr),
148    TIM3: (tim3, arr_l, arr_h),
149    TIM14: (tim14, arr),
150    TIM16: (tim16, arr),
151    TIM17: (tim17, arr),
152}
153
154#[cfg(feature = "stm32g0x1")]
155opm! {
156    TIM2: (tim2, arr_l, arr_h),
157}
158
159#[cfg(any(feature = "stm32g070", feature = "stm32g071", feature = "stm32g081"))]
160opm! {
161    TIM15: (tim15, arr),
162}