atsamd_hal/
timer_params.rs1use crate::time::{Hertz, Nanoseconds};
3
4#[derive(Debug, Clone, Copy)]
6pub struct TimerParams {
7 pub divider: u16,
8 pub cycles: u32,
9}
10
11impl TimerParams {
12 pub fn new(timeout: Hertz, src_freq: Hertz) -> Self {
17 let ticks: u32 = src_freq.to_Hz() / timeout.to_Hz().max(1);
18 let ret = Self::new_from_ticks(ticks);
19 ret.check_cycles_u16();
20 ret
21 }
22
23 pub fn new_ns(timeout: Nanoseconds, src_freq: Hertz) -> Self {
28 let ticks: u32 =
29 (timeout.to_nanos() as u64 * src_freq.to_Hz() as u64 / 1_000_000_000_u64) as u32;
30 let ret = Self::new_from_ticks(ticks);
31 ret.check_cycles_u16();
32 ret
33 }
34
35 pub(crate) fn new_from_ticks(ticks: u32) -> Self {
36 let divider = ((ticks >> 16) + 1).next_power_of_two();
37 let divider = match divider {
38 1 | 2 | 4 | 8 | 16 | 64 | 256 | 1024 => divider,
39 32 => 64,
42 128 => 256,
43 512 => 1024,
44 _ => 1024,
47 };
48
49 let cycles: u32 = ticks / divider;
50
51 TimerParams {
52 divider: divider as u16,
53 cycles,
54 }
55 }
56
57 pub(crate) fn check_cycles_u16(&self) -> u16 {
60 match u16::try_from(self.cycles) {
61 Ok(c) => c,
62 Err(_) => panic!(
63 "cycles {} is out of range for a 16 bit counter",
64 self.cycles
65 ),
66 }
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use crate::fugit::{ExtU32, RateExtU32};
73 use crate::timer_params::TimerParams;
74
75 #[test]
76 fn timer_params_hz_and_us_same_1hz() {
77 let tp_from_hz = TimerParams::new(1.Hz(), 48.MHz());
78 let tp_from_us = TimerParams::new_ns(1_000_000.micros(), 48.MHz());
79
80 assert_eq!(tp_from_hz.divider, tp_from_us.divider);
81 assert_eq!(tp_from_hz.cycles, tp_from_us.cycles);
82 }
83
84 #[test]
85 fn timer_params_hz_and_us_same_3hz() {
86 let tp_from_hz = TimerParams::new(3.Hz(), 48.MHz());
87 let tp_from_us = TimerParams::new_ns(333_333.micros(), 48.MHz());
88
89 assert_eq!(tp_from_hz.divider, tp_from_us.divider);
92 assert!((tp_from_hz.cycles as i32 - tp_from_us.cycles as i32).abs() <= 1);
93 }
94}