1use 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}