1 | use core::fmt; |
2 | use core::ops::{Add, AddAssign, Sub, SubAssign}; |
3 | |
4 | use super::{Duration, GCD_1K, GCD_1M, TICK_HZ}; |
5 | |
6 | #[derive (Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] |
7 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
8 | /// An Instant in time, based on the MCU's clock ticks since startup. |
9 | pub struct Instant { |
10 | ticks: u64, |
11 | } |
12 | |
13 | impl Instant { |
14 | /// The smallest (earliest) value that can be represented by the `Instant` type. |
15 | pub const MIN: Instant = Instant { ticks: u64::MIN }; |
16 | /// The largest (latest) value that can be represented by the `Instant` type. |
17 | pub const MAX: Instant = Instant { ticks: u64::MAX }; |
18 | |
19 | /// Returns an Instant representing the current time. |
20 | pub fn now() -> Instant { |
21 | Instant { |
22 | ticks: embassy_time_driver::now(), |
23 | } |
24 | } |
25 | |
26 | /// Create an Instant from a tick count since system boot. |
27 | pub const fn from_ticks(ticks: u64) -> Self { |
28 | Self { ticks } |
29 | } |
30 | |
31 | /// Create an Instant from a microsecond count since system boot. |
32 | pub const fn from_micros(micros: u64) -> Self { |
33 | Self { |
34 | ticks: micros * (TICK_HZ / GCD_1M) / (1_000_000 / GCD_1M), |
35 | } |
36 | } |
37 | |
38 | /// Create an Instant from a millisecond count since system boot. |
39 | pub const fn from_millis(millis: u64) -> Self { |
40 | Self { |
41 | ticks: millis * (TICK_HZ / GCD_1K) / (1000 / GCD_1K), |
42 | } |
43 | } |
44 | |
45 | /// Create an Instant from a second count since system boot. |
46 | pub const fn from_secs(seconds: u64) -> Self { |
47 | Self { |
48 | ticks: seconds * TICK_HZ, |
49 | } |
50 | } |
51 | |
52 | /// Tick count since system boot. |
53 | pub const fn as_ticks(&self) -> u64 { |
54 | self.ticks |
55 | } |
56 | |
57 | /// Seconds since system boot. |
58 | pub const fn as_secs(&self) -> u64 { |
59 | self.ticks / TICK_HZ |
60 | } |
61 | |
62 | /// Milliseconds since system boot. |
63 | pub const fn as_millis(&self) -> u64 { |
64 | self.ticks * (1000 / GCD_1K) / (TICK_HZ / GCD_1K) |
65 | } |
66 | |
67 | /// Microseconds since system boot. |
68 | pub const fn as_micros(&self) -> u64 { |
69 | self.ticks * (1_000_000 / GCD_1M) / (TICK_HZ / GCD_1M) |
70 | } |
71 | |
72 | /// Duration between this Instant and another Instant |
73 | /// Panics on over/underflow. |
74 | pub fn duration_since(&self, earlier: Instant) -> Duration { |
75 | Duration { |
76 | ticks: unwrap!(self.ticks.checked_sub(earlier.ticks)), |
77 | } |
78 | } |
79 | |
80 | /// Duration between this Instant and another Instant |
81 | pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> { |
82 | if self.ticks < earlier.ticks { |
83 | None |
84 | } else { |
85 | Some(Duration { |
86 | ticks: self.ticks - earlier.ticks, |
87 | }) |
88 | } |
89 | } |
90 | |
91 | /// Returns the duration since the "earlier" Instant. |
92 | /// If the "earlier" instant is in the future, the duration is set to zero. |
93 | pub fn saturating_duration_since(&self, earlier: Instant) -> Duration { |
94 | Duration { |
95 | ticks: if self.ticks < earlier.ticks { |
96 | 0 |
97 | } else { |
98 | self.ticks - earlier.ticks |
99 | }, |
100 | } |
101 | } |
102 | |
103 | /// Duration elapsed since this Instant. |
104 | pub fn elapsed(&self) -> Duration { |
105 | Instant::now() - *self |
106 | } |
107 | |
108 | /// Adds one Duration to self, returning a new `Instant` or None in the event of an overflow. |
109 | pub fn checked_add(&self, duration: Duration) -> Option<Instant> { |
110 | self.ticks.checked_add(duration.ticks).map(|ticks| Instant { ticks }) |
111 | } |
112 | |
113 | /// Subtracts one Duration to self, returning a new `Instant` or None in the event of an overflow. |
114 | pub fn checked_sub(&self, duration: Duration) -> Option<Instant> { |
115 | self.ticks.checked_sub(duration.ticks).map(|ticks| Instant { ticks }) |
116 | } |
117 | } |
118 | |
119 | impl Add<Duration> for Instant { |
120 | type Output = Instant; |
121 | |
122 | fn add(self, other: Duration) -> Instant { |
123 | self.checked_add(other) |
124 | .expect(msg:"overflow when adding duration to instant" ) |
125 | } |
126 | } |
127 | |
128 | impl AddAssign<Duration> for Instant { |
129 | fn add_assign(&mut self, other: Duration) { |
130 | *self = *self + other; |
131 | } |
132 | } |
133 | |
134 | impl Sub<Duration> for Instant { |
135 | type Output = Instant; |
136 | |
137 | fn sub(self, other: Duration) -> Instant { |
138 | self.checked_sub(other) |
139 | .expect(msg:"overflow when subtracting duration from instant" ) |
140 | } |
141 | } |
142 | |
143 | impl SubAssign<Duration> for Instant { |
144 | fn sub_assign(&mut self, other: Duration) { |
145 | *self = *self - other; |
146 | } |
147 | } |
148 | |
149 | impl Sub<Instant> for Instant { |
150 | type Output = Duration; |
151 | |
152 | fn sub(self, other: Instant) -> Duration { |
153 | self.duration_since(earlier:other) |
154 | } |
155 | } |
156 | |
157 | impl<'a> fmt::Display for Instant { |
158 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
159 | write!(f, " {} ticks" , self.ticks) |
160 | } |
161 | } |
162 | |