1use core::fmt::{Debug, Display, Formatter, Result as FmtResult};
8
9#[cfg(esp32)]
10use crate::peripherals::TIMG0;
11
12type InnerRate = fugit::Rate<u32, 1, 1>;
13type InnerInstant = fugit::Instant<u64, 1, 1_000_000>;
14type InnerDuration = fugit::Duration<u64, 1, 1_000_000>;
15
16#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
18pub struct Rate(InnerRate);
19
20impl core::hash::Hash for Rate {
21 #[inline]
22 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
23 self.as_hz().hash(state);
24 }
25}
26
27impl Display for Rate {
28 #[inline]
29 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
30 write!(f, "{} Hz", self.as_hz())
31 }
32}
33
34impl Debug for Rate {
35 #[inline]
36 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
37 write!(f, "Rate({} Hz)", self.as_hz())
38 }
39}
40
41#[cfg(feature = "defmt")]
42impl defmt::Format for Rate {
43 #[inline]
44 fn format(&self, f: defmt::Formatter<'_>) {
45 defmt::write!(f, "{=u32} Hz", self.as_hz())
46 }
47}
48
49impl Rate {
50 #[inline]
52 pub const fn from_hz(val: u32) -> Self {
53 Self(InnerRate::Hz(val))
54 }
55
56 #[inline]
58 pub const fn from_khz(val: u32) -> Self {
59 Self(InnerRate::kHz(val))
60 }
61
62 #[inline]
64 pub const fn from_mhz(val: u32) -> Self {
65 Self(InnerRate::MHz(val))
66 }
67
68 #[inline]
70 pub const fn as_hz(&self) -> u32 {
71 self.0.to_Hz()
72 }
73
74 #[inline]
76 pub const fn as_khz(&self) -> u32 {
77 self.0.to_kHz()
78 }
79
80 #[inline]
82 pub const fn as_mhz(&self) -> u32 {
83 self.0.to_MHz()
84 }
85
86 #[inline]
88 pub const fn as_duration(&self) -> Duration {
89 Duration::from_micros(1_000_000 / self.as_hz() as u64)
90 }
91}
92
93impl core::ops::Div for Rate {
94 type Output = u32;
95
96 #[inline]
97 fn div(self, rhs: Self) -> Self::Output {
98 self.0 / rhs.0
99 }
100}
101
102impl core::ops::Mul<u32> for Rate {
103 type Output = Rate;
104
105 #[inline]
106 fn mul(self, rhs: u32) -> Self::Output {
107 Rate(self.0 * rhs)
108 }
109}
110
111impl core::ops::Div<u32> for Rate {
112 type Output = Rate;
113
114 #[inline]
115 fn div(self, rhs: u32) -> Self::Output {
116 Rate(self.0 / rhs)
117 }
118}
119
120#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
122pub struct Instant(InnerInstant);
123
124impl Debug for Instant {
125 #[inline]
126 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
127 write!(
128 f,
129 "Instant({} µs since epoch)",
130 self.duration_since_epoch().as_micros()
131 )
132 }
133}
134
135impl Display for Instant {
136 #[inline]
137 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
138 write!(
139 f,
140 "{} µs since epoch",
141 self.duration_since_epoch().as_micros()
142 )
143 }
144}
145
146#[cfg(feature = "defmt")]
147impl defmt::Format for Instant {
148 #[inline]
149 fn format(&self, f: defmt::Formatter<'_>) {
150 defmt::write!(
151 f,
152 "{=u64} µs since epoch",
153 self.duration_since_epoch().as_micros()
154 )
155 }
156}
157
158impl Instant {
159 pub const EPOCH: Instant = Instant(InnerInstant::from_ticks(0));
161
162 #[cfg_attr(esp32, doc = "36_558 years")]
168 #[cfg_attr(esp32s2, doc = "7_311 years")]
169 #[cfg_attr(not(any(esp32, esp32s2)), doc = "more than 7 years")]
170 #[inline]
171 pub fn now() -> Self {
172 now()
173 }
174
175 #[inline]
176 pub(crate) fn from_ticks(ticks: u64) -> Self {
177 Instant(InnerInstant::from_ticks(ticks))
178 }
179
180 #[inline]
182 pub fn duration_since_epoch(&self) -> Duration {
183 Self::EPOCH.elapsed()
184 }
185
186 #[inline]
188 pub fn elapsed(&self) -> Duration {
189 Self::now() - *self
190 }
191}
192
193impl core::ops::Add<Duration> for Instant {
194 type Output = Self;
195
196 #[inline]
197 fn add(self, rhs: Duration) -> Self::Output {
198 Instant(self.0 + rhs.0)
199 }
200}
201
202impl core::ops::AddAssign<Duration> for Instant {
203 #[inline]
204 fn add_assign(&mut self, rhs: Duration) {
205 self.0 += rhs.0;
206 }
207}
208
209impl core::ops::Sub for Instant {
210 type Output = Duration;
211
212 #[inline]
213 fn sub(self, rhs: Self) -> Self::Output {
214 Duration(self.0 - rhs.0)
215 }
216}
217
218impl core::ops::Sub<Duration> for Instant {
219 type Output = Self;
220
221 #[inline]
222 fn sub(self, rhs: Duration) -> Self::Output {
223 Instant(self.0 - rhs.0)
224 }
225}
226
227impl core::ops::SubAssign<Duration> for Instant {
228 #[inline]
229 fn sub_assign(&mut self, rhs: Duration) {
230 self.0 -= rhs.0;
231 }
232}
233
234#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
236pub struct Duration(InnerDuration);
237
238impl Debug for Duration {
239 #[inline]
240 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
241 write!(f, "Duration({} µs)", self.as_micros())
242 }
243}
244
245impl Display for Duration {
246 #[inline]
247 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
248 write!(f, "{} µs", self.as_micros())
249 }
250}
251
252#[cfg(feature = "defmt")]
253impl defmt::Format for Duration {
254 #[inline]
255 fn format(&self, f: defmt::Formatter<'_>) {
256 defmt::write!(f, "{=u64} µs", self.as_micros())
257 }
258}
259
260impl Duration {
261 pub const ZERO: Self = Self(InnerDuration::from_ticks(0));
263
264 pub const MAX: Self = Self(InnerDuration::from_ticks(u64::MAX));
266
267 #[inline]
269 pub const fn from_micros(val: u64) -> Self {
270 Self(InnerDuration::micros(val))
271 }
272
273 #[inline]
275 pub const fn from_millis(val: u64) -> Self {
276 Self(InnerDuration::millis(val))
277 }
278
279 #[inline]
281 pub const fn from_secs(val: u64) -> Self {
282 Self(InnerDuration::secs(val))
283 }
284
285 #[inline]
287 pub const fn from_minutes(val: u64) -> Self {
288 Self(InnerDuration::minutes(val))
289 }
290
291 #[inline]
293 pub const fn from_hours(val: u64) -> Self {
294 Self(InnerDuration::hours(val))
295 }
296
297 delegate::delegate! {
298 #[inline]
299 to self.0 {
300 #[call(to_micros)]
302 pub const fn as_micros(&self) -> u64;
303
304 #[call(to_millis)]
306 pub const fn as_millis(&self) -> u64;
307
308 #[call(to_secs)]
310 pub const fn as_secs(&self) -> u64;
311
312 #[call(to_minutes)]
314 pub const fn as_minutes(&self) -> u64;
315
316 #[call(to_hours)]
318 pub const fn as_hours(&self) -> u64;
319 }
320 }
321
322 #[inline]
324 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
325 if let Some(val) = self.0.checked_add(rhs.0) {
326 Some(Duration(val))
327 } else {
328 None
329 }
330 }
331
332 #[inline]
334 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
335 if let Some(val) = self.0.checked_sub(rhs.0) {
336 Some(Duration(val))
337 } else {
338 None
339 }
340 }
341
342 #[inline]
344 pub const fn saturating_add(self, rhs: Self) -> Self {
345 if let Some(val) = self.checked_add(rhs) {
346 val
347 } else {
348 Self::MAX
349 }
350 }
351
352 #[inline]
355 pub const fn saturating_sub(self, rhs: Self) -> Self {
356 if let Some(val) = self.checked_sub(rhs) {
357 val
358 } else {
359 Self::ZERO
360 }
361 }
362}
363
364impl core::ops::Add for Duration {
365 type Output = Self;
366
367 #[inline]
368 fn add(self, rhs: Self) -> Self::Output {
369 Duration(self.0 + rhs.0)
370 }
371}
372
373impl core::ops::AddAssign for Duration {
374 #[inline]
375 fn add_assign(&mut self, rhs: Self) {
376 self.0 += rhs.0;
377 }
378}
379
380impl core::ops::Sub for Duration {
381 type Output = Self;
382
383 #[inline]
384 fn sub(self, rhs: Self) -> Self::Output {
385 Duration(self.0 - rhs.0)
386 }
387}
388
389impl core::ops::SubAssign for Duration {
390 #[inline]
391 fn sub_assign(&mut self, rhs: Self) {
392 self.0 -= rhs.0;
393 }
394}
395
396impl core::ops::Mul<u32> for Duration {
397 type Output = Self;
398
399 #[inline]
400 fn mul(self, rhs: u32) -> Self::Output {
401 Duration(self.0 * rhs)
402 }
403}
404
405impl core::ops::Div<u32> for Duration {
406 type Output = Self;
407
408 #[inline]
409 fn div(self, rhs: u32) -> Self::Output {
410 Duration(self.0 / rhs)
411 }
412}
413
414impl core::ops::Div<Duration> for Duration {
415 type Output = u64;
416
417 #[inline]
418 fn div(self, rhs: Duration) -> Self::Output {
419 self.0 / rhs.0
420 }
421}
422
423#[inline]
424fn now() -> Instant {
425 #[cfg(esp32)]
426 let (ticks, div) = {
427 let tg0 = TIMG0::regs();
429 tg0.lactupdate().write(|w| unsafe { w.update().bits(1) });
430
431 let lo_initial = tg0.lactlo().read().bits();
435 let mut div = tg0.lactconfig().read().divider().bits();
436 let lo = loop {
437 let lo = tg0.lactlo().read().bits();
438 if lo != lo_initial || div == 0 {
439 break lo;
440 }
441 div -= 1;
442 };
443 let hi = tg0.lacthi().read().bits();
444
445 let ticks = ((hi as u64) << 32u64) | lo as u64;
446 (ticks, 16)
447 };
448
449 #[cfg(not(esp32))]
450 let (ticks, div) = {
451 use crate::timer::systimer::{SystemTimer, Unit};
452 let ticks = SystemTimer::unit_value(Unit::Unit0);
454 (ticks, (SystemTimer::ticks_per_second() / 1_000_000))
455 };
456
457 Instant::from_ticks(ticks / div)
458}
459
460#[cfg(esp32)]
461pub(crate) fn time_init() {
462 let apb = crate::Clocks::get().apb_clock.as_hz();
463 assert_eq!(apb, 80_000_000u32);
466
467 let tg0 = TIMG0::regs();
468
469 tg0.lactconfig().write(|w| unsafe { w.bits(0) });
470 tg0.lactalarmhi().write(|w| unsafe { w.bits(u32::MAX) });
471 tg0.lactalarmlo().write(|w| unsafe { w.bits(u32::MAX) });
472 tg0.lactload().write(|w| unsafe { w.load().bits(1) });
473
474 tg0.lactconfig()
476 .modify(|_, w| unsafe { w.divider().bits((apb / 16_000_000u32) as u16) });
477 tg0.lactconfig().modify(|_, w| {
478 w.increase().bit(true);
479 w.autoreload().bit(true);
480 w.en().bit(true)
481 });
482}