| 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 | |