1use core::marker::PhantomData;
5use core::mem;
6
7use crate::pac::Dbg;
8use crate::pac::{Timer0, Timer1, Timer2, Timer3, Timer4};
9
10use crate::afio::PCF0;
11use crate::gpio::{self, Input};
12use crate::rcu::{BusTimerClock, Clocks};
13use crate::time::Hertz;
14use crate::timer::Timer;
15
16pub trait Pins<REMAP> {}
17
18use super::pins::{sealed::Remap, CPin};
19
20impl<TIM, REMAP, P1, P2, MODE1, MODE2> Pins<REMAP> for (P1, P2)
21where
22 REMAP: Remap<Periph = TIM>,
23 P1: CPin<REMAP, 0> + gpio::PinExt<Mode = Input<MODE1>>,
24 P2: CPin<REMAP, 1> + gpio::PinExt<Mode = Input<MODE2>>,
25{
26}
27
28pub struct PwmInput<TIM, REMAP, PINS> {
30 _timer: PhantomData<TIM>,
31 _remap: PhantomData<REMAP>,
32 _pins: PhantomData<PINS>,
33}
34
35pub enum ReadMode {
37 Instant,
39 WaitForNextCapture,
42}
43
44#[derive(Debug)]
46pub enum Error {
47 FrequencyTooLow,
49}
50
51pub enum Configuration {
53 Frequency(Hertz),
61
62 DutyCycle(Hertz),
68
69 RawFrequency(Hertz),
73
74 RawValues { arr: u16, presc: u16 },
76}
77impl Timer<Timer0> {
78 pub fn pwm_input<REMAP, PINS>(
79 mut self,
80 pins: PINS,
81 pcf0: &mut PCF0,
82 dbg: &mut Dbg,
83 mode: Configuration,
84 ) -> PwmInput<Timer0, REMAP, PINS>
85 where
86 REMAP: Remap<Periph = Timer0>,
87 PINS: Pins<REMAP>,
88 {
89 REMAP::remap(pcf0);
90 self.stop_in_debug(dbg, false);
91 let Self { tim, clk } = self;
92 tim0(tim, pins, clk, mode)
93 }
94}
95impl Timer<Timer1> {
96 pub fn pwm_input<REMAP, PINS>(
97 mut self,
98 pins: PINS,
99 pcf0: &mut PCF0,
100 dbg: &mut Dbg,
101 mode: Configuration,
102 ) -> PwmInput<Timer1, REMAP, PINS>
103 where
104 REMAP: Remap<Periph = Timer1>,
105 PINS: Pins<REMAP>,
106 {
107 REMAP::remap(pcf0);
108 self.stop_in_debug(dbg, false);
109 let Self { tim, clk } = self;
110 tim1(tim, pins, clk, mode)
111 }
112}
113
114impl Timer<Timer2> {
115 pub fn pwm_input<REMAP, PINS>(
116 mut self,
117 pins: PINS,
118 pcf0: &mut PCF0,
119 dbg: &mut Dbg,
120 mode: Configuration,
121 ) -> PwmInput<Timer2, REMAP, PINS>
122 where
123 REMAP: Remap<Periph = Timer2>,
124 PINS: Pins<REMAP>,
125 {
126 REMAP::remap(pcf0);
127 self.stop_in_debug(dbg, false);
128 let Self { tim, clk } = self;
129 tim2(tim, pins, clk, mode)
130 }
131}
132
133impl Timer<Timer3> {
134 pub fn pwm_input<REMAP, PINS>(
135 mut self,
136 pins: PINS,
137 pcf0: &mut PCF0,
138 dbg: &mut Dbg,
139 mode: Configuration,
140 ) -> PwmInput<Timer3, REMAP, PINS>
141 where
142 REMAP: Remap<Periph = Timer3>,
143 PINS: Pins<REMAP>,
144 {
145 REMAP::remap(pcf0);
146 self.stop_in_debug(dbg, false);
147 let Self { tim, clk } = self;
148 tim3(tim, pins, clk, mode)
149 }
150}
151
152impl Timer<Timer4> {
153 pub fn pwm_input<REMAP, PINS>(
154 mut self,
155 pins: PINS,
156 pcf0: &mut PCF0,
157 dbg: &mut Dbg,
158 mode: Configuration,
159 ) -> PwmInput<Timer4, REMAP, PINS>
160 where
161 REMAP: Remap<Periph = Timer4>,
162 PINS: Pins<REMAP>,
163 {
164 REMAP::remap(pcf0);
165 self.stop_in_debug(dbg, false);
166 let Self { tim, clk } = self;
167 tim4(tim, pins, clk, mode)
168 }
169}
170
171fn compute_arr_presc(freq: u32, clock: u32) -> (u16, u16) {
173 if freq == 0 {
174 return (core::u16::MAX, core::u16::MAX);
175 }
176 let presc = clock / freq.saturating_mul(core::u16::MAX as u32 + 1);
177 let arr = clock / freq.saturating_mul(presc + 1);
178 (core::cmp::max(1, arr as u16), presc as u16)
179}
180macro_rules! hal {
181 ($($TIMX:ident: ($timX:ident),)+) => {
182 $(
183 fn $timX<REMAP, PINS>(
184 tim: $TIMX,
185 _pins: PINS,
186 clk: Hertz,
187 mode : Configuration,
188 ) -> PwmInput<$TIMX, REMAP, PINS>
189 where
190 REMAP: Remap<Periph = $TIMX>,
191 PINS: Pins<REMAP>,
192 {
193 use Configuration::*;
194 tim.chctl2().modify(|_,w| w.ch0en().clear_bit().ch1en().clear_bit()
197 .ch0p().clear_bit().ch1p().set_bit());
198
199 tim.chctl0_input().modify( |_,w| w.ch0ms().ci0().ch1ms().ci0());
202
203 tim.dmainten().write(|w| w.ch0ie().set_bit());
204
205 tim.smcfg().modify( |_,w| unsafe {w.trgs().bits(0b101).smc().bits(0b100)});
213
214 match mode {
215 Frequency(f) => {
216 let freq = f.raw();
217 let max_freq = if freq > 5 {freq/5} else {1};
218 let (arr,presc) = compute_arr_presc(max_freq, clk.raw());
219 tim.car().write(|w| w.car().bits(arr));
220 tim.psc().write(|w| w.psc().bits(presc));
221 },
222 DutyCycle(f) => {
223 let freq = f.raw();
224 let max_freq = if freq > 2 {freq/2 + freq/4 + freq/8} else {1};
225 let (arr,presc) = compute_arr_presc(max_freq, clk.raw());
226 tim.car().write(|w| w.car().bits(arr));
227 tim.psc().write(|w| w.psc().bits(presc));
228 },
229 RawFrequency(f) => {
230 let freq = f.raw();
231 let (arr,presc) = compute_arr_presc(freq, clk.raw());
232 tim.car().write(|w| w.car().bits(arr));
233 tim.psc().write(|w| w.psc().bits(presc));
234 }
235 RawValues{arr, presc} => {
236 tim.car().write(|w| w.car().bits(arr));
237 tim.psc().write(|w| w.psc().bits(presc));
238 }
239 }
240
241 tim.chctl2().modify(|_,w| w.ch0en().set_bit().ch1en().set_bit());
243
244 tim.ctl0().modify(|_,w| w.cen().set_bit());
245 unsafe { mem::MaybeUninit::uninit().assume_init() }
246 }
247
248 impl<REMAP, PINS> PwmInput<$TIMX, REMAP, PINS>
249 where
250 REMAP: Remap<Periph = $TIMX>,
251 PINS: Pins<REMAP>,
252 {
253 pub fn read_frequency(&self, mode : ReadMode, clocks : &Clocks) -> Result<Hertz,Error> {
255 if let ReadMode::WaitForNextCapture = mode {
256 self.wait_for_capture();
257 }
258
259 let presc = unsafe { (*$TIMX::ptr()).psc().read().bits() as u16};
260 let ccr1 = unsafe { (*$TIMX::ptr()).ch0cv().read().bits() as u16};
261
262 if ccr1 == 0 {
277 Err(Error::FrequencyTooLow)
278 } else {
279 let clk = <$TIMX>::timer_clock(&clocks);
280 Ok(clk/((presc+1) as u32*(ccr1 + 1)as u32))
281 }
282 }
283
284 pub fn read_duty(&self, mode : ReadMode) -> Result<(u16,u16),Error> {
286 if let ReadMode::WaitForNextCapture = mode {
287 self.wait_for_capture();
288 }
289
290 let ccr1 = unsafe { (*$TIMX::ptr()).ch0cv().read().bits() as u16};
293 let ccr2 = unsafe { (*$TIMX::ptr()).ch1cv().read().bits() as u16};
294 if ccr1 == 0 {
295 Err(Error::FrequencyTooLow)
296 } else {
297 Ok((ccr2,ccr1))
298 }
299 }
300
301 fn wait_for_capture(&self) {
303 unsafe { (*$TIMX::ptr()).intf().write(|w| w.upif().clear_bit().ch0if().clear_bit().ch0of().clear_bit())};
304 while unsafe { (*$TIMX::ptr()).intf().read().ch0if().bit_is_clear()} {}
305 }
306 }
307 )+
308 }
309}
310hal! {
311 Timer0: (tim0),
312}
313
314hal! {
315 Timer1: (tim1),
316}
317
318hal! {
319 Timer2: (tim2),
320 Timer3: (tim3),
321}
322
323hal! {
324 Timer4: (tim4),
325}