1#[cfg(esp32)]
15use super::HighSpeed;
16use super::{LowSpeed, Speed};
17use crate::{clock::Clocks, pac, time::Rate};
18
19const LEDC_TIMER_DIV_NUM_MAX: u64 = 0x3FFFF;
20
21#[derive(Debug, Clone, Copy, PartialEq)]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24pub enum Error {
25 Divisor,
27}
28
29#[cfg(esp32)]
30#[derive(PartialEq, Eq, Copy, Clone, Debug)]
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
33pub enum HSClockSource {
34 APBClk,
36 }
38
39#[derive(PartialEq, Eq, Copy, Clone, Debug)]
41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42pub enum LSClockSource {
43 APBClk,
45 }
47
48#[derive(PartialEq, Eq, Copy, Clone, Debug)]
50#[cfg_attr(feature = "defmt", derive(defmt::Format))]
51pub enum Number {
52 Timer0 = 0,
54 Timer1 = 1,
56 Timer2 = 2,
58 Timer3 = 3,
60}
61
62pub mod config {
64 use crate::time::Rate;
65
66 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
68 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
69 #[allow(clippy::enum_variant_names)] pub enum Duty {
71 Duty1Bit = 1,
73 Duty2Bit,
75 Duty3Bit,
77 Duty4Bit,
79 Duty5Bit,
81 Duty6Bit,
83 Duty7Bit,
85 Duty8Bit,
87 Duty9Bit,
89 Duty10Bit,
91 Duty11Bit,
93 Duty12Bit,
95 Duty13Bit,
97 Duty14Bit,
99 #[cfg(esp32)]
100 Duty15Bit,
102 #[cfg(esp32)]
103 Duty16Bit,
105 #[cfg(esp32)]
106 Duty17Bit,
108 #[cfg(esp32)]
109 Duty18Bit,
111 #[cfg(esp32)]
112 Duty19Bit,
114 #[cfg(esp32)]
115 Duty20Bit,
117 }
118
119 impl TryFrom<u32> for Duty {
120 type Error = ();
121
122 fn try_from(value: u32) -> Result<Self, Self::Error> {
123 Ok(match value {
124 1 => Self::Duty1Bit,
125 2 => Self::Duty2Bit,
126 3 => Self::Duty3Bit,
127 4 => Self::Duty4Bit,
128 5 => Self::Duty5Bit,
129 6 => Self::Duty6Bit,
130 7 => Self::Duty7Bit,
131 8 => Self::Duty8Bit,
132 9 => Self::Duty9Bit,
133 10 => Self::Duty10Bit,
134 11 => Self::Duty11Bit,
135 12 => Self::Duty12Bit,
136 13 => Self::Duty13Bit,
137 14 => Self::Duty14Bit,
138 #[cfg(esp32)]
139 15 => Self::Duty15Bit,
140 #[cfg(esp32)]
141 16 => Self::Duty16Bit,
142 #[cfg(esp32)]
143 17 => Self::Duty17Bit,
144 #[cfg(esp32)]
145 18 => Self::Duty18Bit,
146 #[cfg(esp32)]
147 19 => Self::Duty19Bit,
148 #[cfg(esp32)]
149 20 => Self::Duty20Bit,
150 _ => Err(())?,
151 })
152 }
153 }
154
155 #[derive(Copy, Clone)]
157 pub struct Config<CS> {
158 pub duty: Duty,
160 pub clock_source: CS,
162 pub frequency: Rate,
164 }
165}
166
167pub trait TimerSpeed: Speed {
169 type ClockSourceType;
171}
172
173impl TimerSpeed for LowSpeed {
175 type ClockSourceType = LSClockSource;
177}
178
179#[cfg(esp32)]
180impl TimerSpeed for HighSpeed {
182 type ClockSourceType = HSClockSource;
184}
185
186pub trait TimerIFace<S: TimerSpeed> {
188 fn freq(&self) -> Option<Rate>;
190
191 fn configure(&mut self, config: config::Config<S::ClockSourceType>) -> Result<(), Error>;
193
194 fn is_configured(&self) -> bool;
196
197 fn duty(&self) -> Option<config::Duty>;
199
200 fn number(&self) -> Number;
202
203 fn frequency(&self) -> u32;
205}
206
207pub trait TimerHW<S: TimerSpeed> {
209 fn freq_hw(&self) -> Option<Rate>;
211
212 fn configure_hw(&self, divisor: u32);
214
215 fn update_hw(&self);
217}
218
219pub struct Timer<'a, S: TimerSpeed> {
221 ledc: &'a pac::ledc::RegisterBlock,
222 number: Number,
223 duty: Option<config::Duty>,
224 frequency: u32,
225 configured: bool,
226 use_ref_tick: bool,
227 clock_source: Option<S::ClockSourceType>,
228}
229
230impl<'a, S: TimerSpeed> TimerIFace<S> for Timer<'a, S>
231where
232 Timer<'a, S>: TimerHW<S>,
233{
234 fn freq(&self) -> Option<Rate> {
236 self.freq_hw()
237 }
238
239 fn configure(&mut self, config: config::Config<S::ClockSourceType>) -> Result<(), Error> {
241 self.duty = Some(config.duty);
242 self.clock_source = Some(config.clock_source);
243
244 let src_freq: u32 = self.freq().unwrap().as_hz();
246 let precision = 1 << config.duty as u32;
247 let frequency: u32 = config.frequency.as_hz();
248 self.frequency = frequency;
249
250 let mut divisor = ((src_freq as u64) << 8) / frequency as u64 / precision as u64;
251
252 if divisor > LEDC_TIMER_DIV_NUM_MAX {
253 self.use_ref_tick = true;
256 divisor = (1_000_000u64 << 8) / frequency as u64 / precision as u64;
257 }
258
259 if !(256..LEDC_TIMER_DIV_NUM_MAX).contains(&divisor) {
260 return Err(Error::Divisor);
261 }
262
263 self.configure_hw(divisor as u32);
264 self.update_hw();
265
266 self.configured = true;
267
268 Ok(())
269 }
270
271 fn is_configured(&self) -> bool {
273 self.configured
274 }
275
276 fn duty(&self) -> Option<config::Duty> {
278 self.duty
279 }
280
281 fn number(&self) -> Number {
283 self.number
284 }
285
286 fn frequency(&self) -> u32 {
288 self.frequency
289 }
290}
291
292impl<'a, S: TimerSpeed> Timer<'a, S> {
293 pub fn new(ledc: &'a pac::ledc::RegisterBlock, number: Number) -> Self {
295 Timer {
296 ledc,
297 number,
298 duty: None,
299 frequency: 0u32,
300 configured: false,
301 use_ref_tick: false,
302 clock_source: None,
303 }
304 }
305}
306
307impl TimerHW<LowSpeed> for Timer<'_, LowSpeed> {
309 fn freq_hw(&self) -> Option<Rate> {
311 self.clock_source.map(|source| match source {
312 LSClockSource::APBClk => {
313 let clocks = Clocks::get();
314 clocks.apb_clock
315 }
316 })
317 }
318
319 #[cfg(esp32)]
320 fn configure_hw(&self, divisor: u32) {
322 let duty = unwrap!(self.duty) as u8;
323 let use_apb = !self.use_ref_tick;
324
325 self.ledc
326 .lstimer(self.number as usize)
327 .conf()
328 .modify(|_, w| unsafe {
329 w.tick_sel().bit(use_apb);
330 w.rst().clear_bit();
331 w.pause().clear_bit();
332 w.div_num().bits(divisor);
333 w.duty_res().bits(duty)
334 });
335 }
336
337 #[cfg(not(esp32))]
338 fn configure_hw(&self, divisor: u32) {
340 let duty = unwrap!(self.duty) as u8;
341 let use_ref_tick = self.use_ref_tick;
342
343 self.ledc
344 .timer(self.number as usize)
345 .conf()
346 .modify(|_, w| unsafe {
347 w.tick_sel().bit(use_ref_tick);
348 w.rst().clear_bit();
349 w.pause().clear_bit();
350 w.clk_div().bits(divisor);
351 w.duty_res().bits(duty)
352 });
353 }
354
355 fn update_hw(&self) {
357 cfg_if::cfg_if! {
358 if #[cfg(esp32)] {
359 let tmr = self.ledc.lstimer(self.number as usize);
360 } else {
361 let tmr = self.ledc.timer(self.number as usize);
362 }
363 }
364
365 tmr.conf().modify(|_, w| w.para_up().set_bit());
366 }
367}
368
369#[cfg(esp32)]
370impl TimerHW<HighSpeed> for Timer<'_, HighSpeed> {
372 fn freq_hw(&self) -> Option<Rate> {
374 self.clock_source.map(|source| match source {
375 HSClockSource::APBClk => {
376 let clocks = Clocks::get();
377 clocks.apb_clock
378 }
379 })
380 }
381
382 fn configure_hw(&self, divisor: u32) {
384 let duty = unwrap!(self.duty) as u8;
385 let sel_hstimer = self.clock_source == Some(HSClockSource::APBClk);
386
387 self.ledc
388 .hstimer(self.number as usize)
389 .conf()
390 .modify(|_, w| unsafe {
391 w.tick_sel().bit(sel_hstimer);
392 w.rst().clear_bit();
393 w.pause().clear_bit();
394 w.div_num().bits(divisor);
395 w.duty_res().bits(duty)
396 });
397 }
398
399 fn update_hw(&self) {
401 }
403}