atsamd_hal/peripherals/timer/
common.rs1use core::convert::Infallible;
3use fugit::NanosDurationU32;
4
5use crate::ehal::delay::DelayNs;
6use crate::ehal_02::timer::{CountDown, Periodic};
7use crate::time::Nanoseconds;
8use crate::timer_params::TimerParams;
9use crate::timer_traits::InterruptDrivenTimer;
10
11use super::{Count16Reg, TimerCounter};
12
13pub trait Count16 {
17 fn count_16(&self) -> &Count16Reg;
18}
19
20impl<TC> InterruptDrivenTimer for TimerCounter<TC>
21where
22 TC: Count16,
23{
24 fn enable_interrupt(&mut self) {
29 self.tc.count_16().intenset().write(|w| w.ovf().set_bit());
30 }
31
32 fn start<T>(&mut self, timeout: T)
33 where
34 T: Into<NanosDurationU32>,
35 {
36 let params = TimerParams::new_ns(timeout.into(), self.freq);
37 self.start_timer(params.divider, params.check_cycles_u16());
38 }
39
40 fn wait(&mut self) -> nb::Result<(), Infallible> {
41 let count = self.tc.count_16();
42 if count.intflag().read().ovf().bit_is_set() {
43 count.intflag().modify(|_, w| w.ovf().set_bit());
45 Ok(())
46 } else {
47 Err(nb::Error::WouldBlock)
48 }
49 }
50
51 fn disable_interrupt(&mut self) {
56 self.tc.count_16().intenclr().write(|w| w.ovf().set_bit());
57 }
58}
59
60impl<TC> Periodic for TimerCounter<TC> {}
61impl<TC> CountDown for TimerCounter<TC>
62where
63 TC: Count16,
64{
65 type Time = Nanoseconds;
66
67 fn start<T>(&mut self, timeout: T)
68 where
69 T: Into<Self::Time>,
70 {
71 <Self as InterruptDrivenTimer>::start(self, timeout);
72 }
73
74 fn wait(&mut self) -> nb::Result<(), void::Void> {
75 nb::block! {
76 <Self as InterruptDrivenTimer>::wait(self)
77 }
78 .unwrap(); Ok(())
80 }
81}
82
83impl<TC> DelayNs for TimerCounter<TC>
84where
85 TC: Count16,
86{
87 fn delay_ns(&mut self, ns: u32) {
88 let ticks: u32 = (ns as u64 * self.freq.to_Hz() as u64 / 1_000_000_000_u64) as u32;
89 let params = TimerParams::new_from_ticks(ticks);
90
91 let mut cycles = params.cycles;
93 if cycles > u16::MAX as u32 {
94 self.start_timer(params.divider, u16::MAX);
95 while cycles > u16::MAX as u32 {
96 let _ = nb::block!(InterruptDrivenTimer::wait(self));
97 cycles -= u16::MAX as u32;
98 }
99 }
100
101 if cycles > 0 {
103 self.start_timer(params.divider, cycles as u16);
104 let _ = nb::block!(InterruptDrivenTimer::wait(self));
105 }
106
107 self.disable();
108 }
109}