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)
37 where
38 T: Into<NanosDurationU32>,
39 {
40 let params = TimerParams::new_ns(timeout.into(), self.freq);
41 self.start_timer(params.divider, params.check_cycles_u16());
42 }
43
44 fn wait(&mut self) -> nb::Result<(), Infallible> {
45 let count = self.tc.count_16();
46 if count.intflag().read().ovf().bit_is_set() {
47 count.intflag().modify(|_, w| w.ovf().set_bit());
49 Ok(())
50 } else {
51 Err(nb::Error::WouldBlock)
52 }
53 }
54
55 fn disable_interrupt(&mut self) {
60 self.tc.count_16().intenclr().write(|w| w.ovf().set_bit());
61 }
62}
63
64impl<TC> Periodic for TimerCounter<TC> {}
65impl<TC> CountDown for TimerCounter<TC>
66where
67 TC: Count16,
68{
69 type Time = Nanoseconds;
70
71 fn start<T>(&mut self, timeout: T)
72 where
73 T: Into<Self::Time>,
74 {
75 <Self as InterruptDrivenTimer>::start(self, timeout);
76 }
77
78 fn wait(&mut self) -> nb::Result<(), void::Void> {
79 nb::block! {
80 <Self as InterruptDrivenTimer>::wait(self)
81 }
82 .unwrap(); Ok(())
84 }
85}
86
87impl<TC> DelayNs for TimerCounter<TC>
88where
89 TC: Count16,
90{
91 fn delay_ns(&mut self, ns: u32) {
92 let ticks: u32 = (ns as u64 * self.freq.to_Hz() as u64 / 1_000_000_000_u64) as u32;
93 let params = TimerParams::new_from_ticks(ticks);
94
95 let mut cycles = params.cycles;
97 if cycles > u16::MAX as u32 {
98 self.start_timer(params.divider, u16::MAX);
99 while cycles > u16::MAX as u32 {
100 let _ = nb::block!(InterruptDrivenTimer::wait(self));
101 cycles -= u16::MAX as u32;
102 }
103 }
104
105 if cycles > 0 {
107 self.start_timer(params.divider, cycles as u16);
108 let _ = nb::block!(InterruptDrivenTimer::wait(self));
109 }
110
111 self.disable();
112 }
113}