1use crate::peripherals::Tcxo;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
11pub struct Instant(u64);
12
13impl Instant {
14 pub fn now() -> Self {
16 let tcxo = unsafe { &*Tcxo::ptr() };
18 let status = tcxo.tcxo_status().read().bits();
20 unsafe {
21 tcxo.tcxo_status().write(|w| w.bits(status | 0x01));
22 }
23 while tcxo.tcxo_status().read().bits() & 0x10 == 0 {}
24 let c0 = tcxo.tcxo_count0().read().bits() as u64;
26 let c1 = tcxo.tcxo_count1().read().bits() as u64;
27 let c2 = tcxo.tcxo_count2().read().bits() as u64;
28 let c3 = tcxo.tcxo_count3().read().bits() as u64;
29 Instant((c3 << 48) | (c2 << 32) | (c1 << 16) | c0)
30 }
31
32 pub fn elapsed(&self) -> Duration {
34 Instant::now().checked_duration_since(*self).unwrap_or(Duration::from_micros(0))
35 }
36
37 pub fn duration_since(&self, earlier: Instant) -> Duration {
39 self.checked_duration_since(earlier).unwrap_or(Duration::from_micros(0))
40 }
41
42 pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
44 if self.0 >= earlier.0 { Some(Duration::from_micros(self.0 - earlier.0)) } else { None }
45 }
46
47 pub fn raw(&self) -> u64 {
49 self.0
50 }
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
55pub struct Duration(u64); impl Duration {
58 pub const fn from_micros(micros: u64) -> Self {
60 Duration(micros)
61 }
62
63 pub const fn from_millis(millis: u64) -> Self {
65 Duration(millis * 1_000)
66 }
67
68 pub const fn from_secs(secs: u64) -> Self {
70 Duration(secs * 1_000_000)
71 }
72
73 pub const fn as_micros(&self) -> u64 {
75 self.0
76 }
77
78 pub const fn as_millis(&self) -> u64 {
80 self.0 / 1_000
81 }
82
83 pub const fn as_secs(&self) -> u64 {
85 self.0 / 1_000_000
86 }
87}
88
89impl core::ops::Add for Duration {
90 type Output = Self;
91 fn add(self, rhs: Self) -> Self {
92 Duration(self.0 + rhs.0)
93 }
94}
95
96impl core::ops::AddAssign for Duration {
97 fn add_assign(&mut self, rhs: Self) {
98 self.0 += rhs.0;
99 }
100}
101
102impl core::ops::Sub for Duration {
103 type Output = Self;
104 fn sub(self, rhs: Self) -> Self {
105 Duration(self.0.saturating_sub(rhs.0))
106 }
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub struct Rate(u32);
112
113impl Rate {
114 pub const fn from_hz(hz: u32) -> Self {
115 Rate(hz)
116 }
117 pub const fn from_khz(khz: u32) -> Self {
118 Rate(khz * 1_000)
119 }
120 pub const fn from_mhz(mhz: u32) -> Self {
121 Rate(mhz * 1_000_000)
122 }
123 pub const fn to_hz(&self) -> u32 {
124 self.0
125 }
126 pub const fn to_khz(&self) -> u32 {
127 self.0 / 1_000
128 }
129}
130
131#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_duration_constructors() {
139 assert_eq!(Duration::from_micros(500).as_micros(), 500);
140 assert_eq!(Duration::from_millis(1).as_micros(), 1000);
141 assert_eq!(Duration::from_secs(1).as_micros(), 1_000_000);
142 assert_eq!(Duration::from_micros(1500).as_millis(), 1);
143 }
144
145 #[test]
146 fn test_duration_add_sub() {
147 let a = Duration::from_micros(100);
148 let b = Duration::from_micros(50);
149 assert_eq!((a + b).as_micros(), 150);
150 assert_eq!((a - b).as_micros(), 50);
151 assert_eq!((b - a).as_micros(), 0);
153 }
154
155 #[test]
156 fn test_duration_default() {
157 assert_eq!(Duration::default().as_micros(), 0);
158 }
159
160 #[test]
161 fn test_rate_constructors() {
162 assert_eq!(Rate::from_hz(1000).to_hz(), 1000);
163 assert_eq!(Rate::from_khz(1).to_hz(), 1000);
164 assert_eq!(Rate::from_mhz(1).to_hz(), 1_000_000);
165 assert_eq!(Rate::from_mhz(240).to_khz(), 240_000);
166 }
167
168 #[test]
169 fn test_instant_checked_duration() {
170 let early = Instant(100);
171 let late = Instant(200);
172 assert_eq!(late.checked_duration_since(early).unwrap().as_micros(), 100);
173 assert!(early.checked_duration_since(late).is_none());
174 }
175}