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 core::hash::Hash for Instant {
159 #[inline]
160 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
161 self.duration_since_epoch().hash(state);
162 }
163}
164
165impl Instant {
166 pub const EPOCH: Instant = Instant(InnerInstant::from_ticks(0));
168
169 #[cfg_attr(esp32, doc = "36_558 years")]
175 #[cfg_attr(esp32s2, doc = "7_311 years")]
176 #[cfg_attr(not(any(esp32, esp32s2)), doc = "more than 7 years")]
177 #[inline]
178 pub fn now() -> Self {
179 now()
180 }
181
182 #[inline]
183 pub(crate) fn from_ticks(ticks: u64) -> Self {
184 Instant(InnerInstant::from_ticks(ticks))
185 }
186
187 #[inline]
189 pub fn duration_since_epoch(&self) -> Duration {
190 *self - Self::EPOCH
191 }
192
193 #[inline]
195 pub fn elapsed(&self) -> Duration {
196 Self::now() - *self
197 }
198}
199
200impl core::ops::Add<Duration> for Instant {
201 type Output = Self;
202
203 #[inline]
204 fn add(self, rhs: Duration) -> Self::Output {
205 Instant(self.0 + rhs.0)
206 }
207}
208
209impl core::ops::AddAssign<Duration> for Instant {
210 #[inline]
211 fn add_assign(&mut self, rhs: Duration) {
212 self.0 += rhs.0;
213 }
214}
215
216impl core::ops::Sub for Instant {
217 type Output = Duration;
218
219 #[inline]
220 fn sub(self, rhs: Self) -> Self::Output {
221 Duration(self.0 - rhs.0)
222 }
223}
224
225impl core::ops::Sub<Duration> for Instant {
226 type Output = Self;
227
228 #[inline]
229 fn sub(self, rhs: Duration) -> Self::Output {
230 Instant(self.0 - rhs.0)
231 }
232}
233
234impl core::ops::SubAssign<Duration> for Instant {
235 #[inline]
236 fn sub_assign(&mut self, rhs: Duration) {
237 self.0 -= rhs.0;
238 }
239}
240
241#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
243pub struct Duration(InnerDuration);
244
245impl Debug for Duration {
246 #[inline]
247 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
248 write!(f, "Duration({} µs)", self.as_micros())
249 }
250}
251
252impl Display for Duration {
253 #[inline]
254 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
255 write!(f, "{} µs", self.as_micros())
256 }
257}
258
259#[cfg(feature = "defmt")]
260impl defmt::Format for Duration {
261 #[inline]
262 fn format(&self, f: defmt::Formatter<'_>) {
263 defmt::write!(f, "{=u64} µs", self.as_micros())
264 }
265}
266
267impl core::hash::Hash for Duration {
268 #[inline]
269 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
270 self.as_micros().hash(state);
271 }
272}
273
274impl Duration {
275 pub const ZERO: Self = Self(InnerDuration::from_ticks(0));
277
278 pub const MAX: Self = Self(InnerDuration::from_ticks(u64::MAX));
280
281 #[inline]
283 pub const fn from_micros(val: u64) -> Self {
284 Self(InnerDuration::micros(val))
285 }
286
287 #[inline]
289 pub const fn from_millis(val: u64) -> Self {
290 Self(InnerDuration::millis(val))
291 }
292
293 #[inline]
295 pub const fn from_secs(val: u64) -> Self {
296 Self(InnerDuration::secs(val))
297 }
298
299 #[inline]
301 pub const fn from_minutes(val: u64) -> Self {
302 Self(InnerDuration::minutes(val))
303 }
304
305 #[inline]
307 pub const fn from_hours(val: u64) -> Self {
308 Self(InnerDuration::hours(val))
309 }
310
311 delegate::delegate! {
312 #[inline]
313 to self.0 {
314 #[call(to_micros)]
316 pub const fn as_micros(&self) -> u64;
317
318 #[call(to_millis)]
320 pub const fn as_millis(&self) -> u64;
321
322 #[call(to_secs)]
324 pub const fn as_secs(&self) -> u64;
325
326 #[call(to_minutes)]
328 pub const fn as_minutes(&self) -> u64;
329
330 #[call(to_hours)]
332 pub const fn as_hours(&self) -> u64;
333 }
334 }
335
336 #[inline]
338 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
339 if let Some(val) = self.0.checked_add(rhs.0) {
340 Some(Duration(val))
341 } else {
342 None
343 }
344 }
345
346 #[inline]
348 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
349 if let Some(val) = self.0.checked_sub(rhs.0) {
350 Some(Duration(val))
351 } else {
352 None
353 }
354 }
355
356 #[inline]
358 pub const fn saturating_add(self, rhs: Self) -> Self {
359 if let Some(val) = self.checked_add(rhs) {
360 val
361 } else {
362 Self::MAX
363 }
364 }
365
366 #[inline]
369 pub const fn saturating_sub(self, rhs: Self) -> Self {
370 if let Some(val) = self.checked_sub(rhs) {
371 val
372 } else {
373 Self::ZERO
374 }
375 }
376}
377
378impl core::ops::Add for Duration {
379 type Output = Self;
380
381 #[inline]
382 fn add(self, rhs: Self) -> Self::Output {
383 Duration(self.0 + rhs.0)
384 }
385}
386
387impl core::ops::AddAssign for Duration {
388 #[inline]
389 fn add_assign(&mut self, rhs: Self) {
390 self.0 += rhs.0;
391 }
392}
393
394impl core::ops::Sub for Duration {
395 type Output = Self;
396
397 #[inline]
398 fn sub(self, rhs: Self) -> Self::Output {
399 Duration(self.0 - rhs.0)
400 }
401}
402
403impl core::ops::SubAssign for Duration {
404 #[inline]
405 fn sub_assign(&mut self, rhs: Self) {
406 self.0 -= rhs.0;
407 }
408}
409
410impl core::ops::Mul<u32> for Duration {
411 type Output = Self;
412
413 #[inline]
414 fn mul(self, rhs: u32) -> Self::Output {
415 Duration(self.0 * rhs)
416 }
417}
418
419impl core::ops::Div<u32> for Duration {
420 type Output = Self;
421
422 #[inline]
423 fn div(self, rhs: u32) -> Self::Output {
424 Duration(self.0 / rhs)
425 }
426}
427
428impl core::ops::Div<Duration> for Duration {
429 type Output = u64;
430
431 #[inline]
432 fn div(self, rhs: Duration) -> Self::Output {
433 self.0 / rhs.0
434 }
435}
436
437#[inline]
438fn now() -> Instant {
439 #[cfg(esp32)]
440 let (ticks, div) = {
441 let tg0 = TIMG0::regs();
443 tg0.lactupdate().write(|w| unsafe { w.update().bits(1) });
444
445 let lo_initial = tg0.lactlo().read().bits();
449 let mut div = tg0.lactconfig().read().divider().bits();
450 let lo = loop {
451 let lo = tg0.lactlo().read().bits();
452 if lo != lo_initial || div == 0 {
453 break lo;
454 }
455 div -= 1;
456 };
457 let hi = tg0.lacthi().read().bits();
458
459 let ticks = ((hi as u64) << 32u64) | lo as u64;
460 (ticks, 16)
461 };
462
463 #[cfg(not(esp32))]
464 let (ticks, div) = {
465 use crate::timer::systimer::{SystemTimer, Unit};
466 let ticks = SystemTimer::unit_value(Unit::Unit0);
468 (ticks, (SystemTimer::ticks_per_second() / 1_000_000))
469 };
470
471 Instant::from_ticks(ticks / div)
472}
473
474#[cfg(esp32)]
475pub(crate) fn time_init() {
476 let apb = crate::Clocks::get().apb_clock.as_hz();
477 assert_eq!(apb, 80_000_000u32);
480
481 let tg0 = TIMG0::regs();
482
483 tg0.lactconfig().write(|w| unsafe { w.bits(0) });
484 tg0.lactalarmhi().write(|w| unsafe { w.bits(u32::MAX) });
485 tg0.lactalarmlo().write(|w| unsafe { w.bits(u32::MAX) });
486 tg0.lactload().write(|w| unsafe { w.load().bits(1) });
487
488 tg0.lactconfig()
490 .modify(|_, w| unsafe { w.divider().bits((apb / 16_000_000u32) as u16) });
491 tg0.lactconfig().modify(|_, w| {
492 w.increase().bit(true);
493 w.autoreload().bit(true);
494 w.en().bit(true)
495 });
496}