1use crate::peripherals::Timer;
18use crate::soc::ws63::TIMER_CLOCK_HZ;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum TimerMode {
23 OneShot = 0,
25 Periodic = 1,
27}
28
29pub struct TimerDriver<'d> {
31 _timer: Timer<'d>,
32}
33
34impl<'d> TimerDriver<'d> {
35 pub fn new(timer: Timer<'d>) -> Self {
37 Self { _timer: timer }
38 }
39
40 fn regs(&self) -> &'static ws63_pac::timer::RegisterBlock {
41 unsafe { &*Timer::ptr() }
43 }
44
45 pub fn configure(&self, n: usize, mode: TimerMode, load_value: u32) {
47 let r = self.regs();
48 match n {
49 0 => r.timer0_load_count(0).write(|w| unsafe { w.bits(load_value) }),
50 1 => r.timer0_load_count(1).write(|w| unsafe { w.bits(load_value) }),
51 2 => r.timer0_load_count(2).write(|w| unsafe { w.bits(load_value) }),
52 _ => unreachable!(),
53 };
54 let ctl = ((mode as u32) & 0x3) << 1;
55 match n {
56 0 => r.timer0_control(0).write(|w| unsafe { w.bits(ctl) }),
57 1 => r.timer0_control(1).write(|w| unsafe { w.bits(ctl) }),
58 2 => r.timer0_control(2).write(|w| unsafe { w.bits(ctl) }),
59 _ => unreachable!(),
60 };
61 }
62
63 pub fn enable(&self, n: usize) {
65 let r = self.regs();
66 let prev = match n {
67 0 => r.timer0_control(0).read().bits(),
68 1 => r.timer0_control(1).read().bits(),
69 2 => r.timer0_control(2).read().bits(),
70 _ => unreachable!(),
71 };
72 match n {
73 0 => r.timer0_control(0).write(|w| unsafe { w.bits(prev | 1) }),
74 1 => r.timer0_control(1).write(|w| unsafe { w.bits(prev | 1) }),
75 2 => r.timer0_control(2).write(|w| unsafe { w.bits(prev | 1) }),
76 _ => unreachable!(),
77 };
78 }
79
80 pub fn disable(&self, n: usize) {
82 let r = self.regs();
83 let prev = match n {
84 0 => r.timer0_control(0).read().bits(),
85 1 => r.timer0_control(1).read().bits(),
86 2 => r.timer0_control(2).read().bits(),
87 _ => unreachable!(),
88 };
89 match n {
90 0 => r.timer0_control(0).write(|w| unsafe { w.bits(prev & !1) }),
91 1 => r.timer0_control(1).write(|w| unsafe { w.bits(prev & !1) }),
92 2 => r.timer0_control(2).write(|w| unsafe { w.bits(prev & !1) }),
93 _ => unreachable!(),
94 };
95 }
96
97 pub fn current_value(&self, n: usize) -> u32 {
99 let r = self.regs();
100 match n {
101 0 => r.timer0_current_value(0).read().bits(),
102 1 => r.timer0_current_value(1).read().bits(),
103 2 => r.timer0_current_value(2).read().bits(),
104 _ => unreachable!(),
105 }
106 }
107
108 pub fn interrupt_pending(&self, n: usize) -> bool {
110 let r = self.regs();
111 match n {
112 0 => r.timer0_raw_intr(0).read().bits() & 1 != 0,
113 1 => r.timer0_raw_intr(1).read().bits() & 1 != 0,
114 2 => r.timer0_raw_intr(2).read().bits() & 1 != 0,
115 _ => unreachable!(),
116 }
117 }
118
119 pub fn clear_interrupt(&self, n: usize) {
121 let r = self.regs();
122 match n {
123 0 => {
124 let _ = r.timer0_eoi(0).read().bits();
125 }
126 1 => {
127 let _ = r.timer0_eoi(1).read().bits();
128 }
129 2 => {
130 let _ = r.timer0_eoi(2).read().bits();
131 }
132 _ => unreachable!(),
133 }
134 }
135
136 pub fn oneshot(&self, channel: usize) -> OneShotTimer<'_> {
138 OneShotTimer { driver: self, channel }
139 }
140
141 pub fn periodic(&self, channel: usize) -> PeriodicTimer<'_> {
143 PeriodicTimer { driver: self, channel }
144 }
145}
146
147pub struct OneShotTimer<'a> {
153 driver: &'a TimerDriver<'a>,
154 channel: usize,
155}
156
157impl OneShotTimer<'_> {
158 pub fn start(&mut self, count: u32) {
162 self.driver.configure(self.channel, TimerMode::OneShot, count);
163 self.driver.enable(self.channel);
164 }
165
166 pub fn start_micros(&mut self, us: u32) {
171 let ticks64 = TIMER_CLOCK_HZ as u64 * us as u64 / 1_000_000;
172 let ticks = if ticks64 > u32::MAX as u64 { u32::MAX } else { ticks64 as u32 };
174 self.start(ticks);
175 }
176
177 pub fn start_millis(&mut self, ms: u32) {
182 let ticks64 = TIMER_CLOCK_HZ as u64 * ms as u64 / 1_000;
183 let ticks = if ticks64 > u32::MAX as u64 { u32::MAX } else { ticks64 as u32 };
184 self.start(ticks);
185 }
186
187 pub fn expired(&self) -> bool {
189 self.driver.interrupt_pending(self.channel)
190 }
191
192 pub fn wait(&self) {
194 while !self.expired() {}
195 self.driver.clear_interrupt(self.channel);
196 }
197
198 pub fn current(&self) -> u32 {
200 self.driver.current_value(self.channel)
201 }
202
203 pub fn stop(&self) {
205 self.driver.disable(self.channel);
206 }
207
208 pub fn clear(&self) {
210 self.driver.clear_interrupt(self.channel);
211 }
212}
213
214impl embedded_hal::delay::DelayNs for OneShotTimer<'_> {
215 fn delay_ns(&mut self, ns: u32) {
216 let ticks64 = (TIMER_CLOCK_HZ as u64 * ns as u64) / 1_000_000_000;
217 let ticks = if ticks64 > u32::MAX as u64 { u32::MAX } else { ticks64 as u32 };
218 if ticks > 0 {
219 self.start(ticks);
220 self.wait();
221 }
222 }
223
224 fn delay_us(&mut self, us: u32) {
225 self.start_micros(us);
226 self.wait();
227 }
228
229 fn delay_ms(&mut self, ms: u32) {
230 self.start_millis(ms);
231 self.wait();
232 }
233}
234
235pub struct PeriodicTimer<'a> {
241 driver: &'a TimerDriver<'a>,
242 channel: usize,
243}
244
245impl PeriodicTimer<'_> {
246 pub fn start(&mut self, period: u32) {
248 self.driver.configure(self.channel, TimerMode::Periodic, period);
249 self.driver.enable(self.channel);
250 }
251
252 pub fn start_micros(&mut self, us: u32) {
254 let ticks64 = TIMER_CLOCK_HZ as u64 * us as u64 / 1_000_000;
255 let ticks = if ticks64 > u32::MAX as u64 { u32::MAX } else { ticks64 as u32 };
256 self.start(ticks);
257 }
258
259 pub fn tick_elapsed(&self) -> bool {
261 self.driver.interrupt_pending(self.channel)
262 }
263
264 pub fn wait_tick(&self) {
266 while !self.tick_elapsed() {}
267 self.driver.clear_interrupt(self.channel);
268 }
269
270 pub fn stop(&self) {
272 self.driver.disable(self.channel);
273 }
274
275 pub fn current(&self) -> u32 {
277 self.driver.current_value(self.channel)
278 }
279
280 pub fn clear_tick(&self) {
282 self.driver.clear_interrupt(self.channel);
283 }
284}
285
286#[cfg(test)]
289mod tests {
290 use crate::soc::ws63::TIMER_CLOCK_HZ;
291
292 const TICKS_PER_US: u64 = TIMER_CLOCK_HZ as u64 / 1_000_000;
296 const MAX_SAFE_US: u64 = u32::MAX as u64 / TICKS_PER_US;
297
298 fn ticks_for_us(us: u64) -> u32 {
299 let t = TIMER_CLOCK_HZ as u64 * us / 1_000_000;
300 if t > u32::MAX as u64 { u32::MAX } else { t as u32 }
301 }
302
303 #[test]
304 fn oneshot_overflow_clamps() {
305 assert_eq!(ticks_for_us(MAX_SAFE_US + 1_000_000), u32::MAX);
307 }
308
309 #[test]
310 fn small_value_does_not_clamp() {
311 assert_eq!(ticks_for_us(100), (100 * TICKS_PER_US) as u32);
313 }
314
315 #[test]
316 fn max_safe_value_not_clamped() {
317 let ticks64 = TIMER_CLOCK_HZ as u64 * MAX_SAFE_US / 1_000_000;
318 assert!(ticks64 <= u32::MAX as u64);
319 assert_eq!(ticks_for_us(MAX_SAFE_US), ticks64 as u32);
320 }
321}
322
323#[cfg(test)]
326mod proptests {
327 use crate::soc::ws63::TIMER_CLOCK_HZ;
328 use proptest::prelude::*;
329
330 const MAX_SAFE_US: u64 = u32::MAX as u64 / (TIMER_CLOCK_HZ as u64 / 1_000_000);
331
332 fn ticks64(us: u64) -> u64 {
333 TIMER_CLOCK_HZ as u64 * us / 1_000_000
334 }
335
336 proptest! {
337 #[test]
339 fn ticks_never_panics(us in any::<u32>()) {
340 let t = ticks64(us as u64);
341 let _ = if t > u32::MAX as u64 { u32::MAX } else { t as u32 };
342 }
343
344 #[test]
346 fn safe_range_not_clamped(us in 0u64..=MAX_SAFE_US) {
347 prop_assert!(ticks64(us) <= u32::MAX as u64, "safe us={} -> ticks64={}", us, ticks64(us));
348 }
349
350 #[test]
352 fn overflow_always_clamps(us in (MAX_SAFE_US + 1)..=u32::MAX as u64) {
353 prop_assert!(ticks64(us) > u32::MAX as u64);
354 }
355 }
356}
357
358#[cfg(feature = "async")]
360mod asynch_impl {
361 use super::{TIMER_CLOCK_HZ, Timer, TimerDriver, TimerMode};
362 use crate::asynch::IrqSignal;
363 use crate::interrupt::{self, Interrupt};
364 use core::future::Future;
365 use core::pin::Pin;
366 use core::task::{Context, Poll};
367
368 static TIMER_SIGNAL: [IrqSignal; 3] = [IrqSignal::new(), IrqSignal::new(), IrqSignal::new()];
369
370 fn ch_irq(ch: usize) -> Interrupt {
371 match ch {
372 0 => Interrupt::TIMER_INT0,
373 1 => Interrupt::TIMER_INT1,
374 _ => Interrupt::TIMER_INT2,
375 }
376 }
377
378 pub fn on_interrupt(ch: usize) {
383 let r = unsafe { &*Timer::ptr() };
386 match ch {
387 0 => {
388 let prev = r.timer0_control(0).read().bits();
389 r.timer0_control(0).write(|w| unsafe { w.bits(prev & !1) }); let _ = r.timer0_eoi(0).read().bits(); }
392 1 => {
393 let prev = r.timer0_control(1).read().bits();
394 r.timer0_control(1).write(|w| unsafe { w.bits(prev & !1) });
395 let _ = r.timer0_eoi(1).read().bits();
396 }
397 _ => {
398 let prev = r.timer0_control(2).read().bits();
399 r.timer0_control(2).write(|w| unsafe { w.bits(prev & !1) });
400 let _ = r.timer0_eoi(2).read().bits();
401 }
402 }
403 TIMER_SIGNAL[ch].signal();
404 }
405
406 pub struct AsyncDelay<'d> {
413 driver: TimerDriver<'d>,
414 channel: usize,
415 }
416
417 impl<'d> AsyncDelay<'d> {
418 pub fn new(timer: Timer<'d>, channel: usize) -> Self {
420 Self { driver: TimerDriver::new(timer), channel }
421 }
422
423 async fn delay_ticks(&mut self, ticks: u32) {
424 let ch = self.channel;
425 TIMER_SIGNAL[ch].reset();
426 self.driver.clear_interrupt(ch);
427 self.driver.configure(ch, TimerMode::OneShot, ticks.max(1));
428 unsafe { interrupt::enable(ch_irq(ch)) };
430 self.driver.enable(ch);
431 DelayFuture { ch }.await;
432 }
433 }
434
435 struct DelayFuture {
436 ch: usize,
437 }
438
439 impl Future for DelayFuture {
440 type Output = ();
441 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
442 if TIMER_SIGNAL[self.ch].take_fired() {
443 Poll::Ready(())
444 } else {
445 TIMER_SIGNAL[self.ch].register(cx.waker());
446 Poll::Pending
447 }
448 }
449 }
450
451 impl embedded_hal_async::delay::DelayNs for AsyncDelay<'_> {
452 async fn delay_ns(&mut self, ns: u32) {
453 let ticks = (TIMER_CLOCK_HZ as u64 * ns as u64 / 1_000_000_000) as u32;
454 self.delay_ticks(ticks).await;
455 }
456 }
457}
458
459#[cfg(feature = "async")]
460pub use asynch_impl::{AsyncDelay, on_interrupt};