1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
//! Time APIs for obtaining the current time and calculating with points in time and durations.
//!
//! These APIs are made for the BLE stack and are not meant to be general-purpose. The APIs here
//! have microsecond resolution and use 32-bit arithmetic wherever possible.

use core::fmt;
use core::ops::{Add, AddAssign, Sub, SubAssign};

/// A duration with microsecond resolution.
///
/// This can represent a maximum duration of about 1 hour. Overflows will result in a panic, but
/// shouldn't happen since the BLE stack doesn't deal with durations that large.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Duration(u32);

impl Duration {
    /// The duration of the interframe spacing between BLE packets.
    pub const T_IFS: Self = Duration(150);

    /// Creates a `Duration` from a number of microseconds.
    pub fn from_micros(micros: u32) -> Self {
        Duration(micros)
    }

    /// Creates a `Duration` representing the given number of milliseconds.
    pub fn from_millis(millis: u16) -> Self {
        Duration(u32::from(millis) * 1_000)
    }

    /// Creates a `Duration` representing a number of seconds.
    pub fn from_secs(secs: u16) -> Self {
        Duration(u32::from(secs) * 1_000_000)
    }

    /// Returns the number of whole seconds that fit in `self`.
    pub fn whole_secs(&self) -> u32 {
        self.0 / 1_000_000
    }

    /// Returns the number of whole milliseconds that fit in `self`.
    pub fn whole_millis(&self) -> u32 {
        self.0 / 1_000
    }

    /// Returns the number of microseconds represented by `self`.
    pub fn as_micros(&self) -> u32 {
        self.0
    }

    /// Returns the fractional part of microseconds in `self`.
    pub fn subsec_micros(&self) -> u32 {
        self.0 % 1_000_000
    }
}

impl Add for Duration {
    type Output = Self;

    fn add(self, rhs: Self) -> Self {
        Duration(self.0.checked_add(rhs.0).expect("duration overflow"))
    }
}

impl Add<&'_ Self> for Duration {
    type Output = Duration;

    fn add(self, rhs: &'_ Self) -> Self {
        self + *rhs
    }
}

impl AddAssign for Duration {
    fn add_assign(&mut self, rhs: Self) {
        *self = *self + rhs;
    }
}

impl Sub for Duration {
    type Output = Self;

    fn sub(self, rhs: Self) -> Self {
        Duration(self.0.checked_sub(rhs.0).expect("duration underflow"))
    }
}

impl Sub<&'_ Self> for Duration {
    type Output = Self;

    fn sub(self, rhs: &'_ Self) -> Self {
        self - *rhs
    }
}

impl SubAssign for Duration {
    fn sub_assign(&mut self, rhs: Self) {
        *self = *self - rhs;
    }
}

impl fmt::Display for Duration {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self.0 >= 1_000_000 {
            // s
            let (secs, subsec_micros) = (self.whole_secs(), self.subsec_micros());
            if subsec_micros == 0 {
                write!(f, "{}s", secs)
            } else {
                write!(f, "{}.{:06}s", secs, subsec_micros)
            }
        } else if self.0 >= 1000 {
            // ms
            let (millis, submilli_micros) = (self.whole_millis(), self.0 % 1000);
            if submilli_micros == 0 {
                write!(f, "{}ms", millis)
            } else {
                write!(f, "{}.{:03}ms", millis, submilli_micros)
            }
        } else {
            // µs
            write!(f, "{}µs", self.0)
        }
    }
}

impl fmt::Debug for Duration {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        <Self as fmt::Display>::fmt(self, f)
    }
}

/// A point in time, relative to an unspecfied epoch.
///
/// This has microsecond resolution and may wrap around after >1 hour. Apart from the wraparound, it
/// is monotonic.
///
/// `Instant`s are obtained from an implementation of [`Timer`]. `Instant`s created from different
/// [`Timer`] instances (even when using the same implementation) are not compatible, and mixing
/// them in operations causes unspecified results. [`Duration`]s are independent of the [`Timer`]
/// implementation and thus can be mixed freely.
///
/// [`Duration`]: struct.Duration.html
/// [`Timer`]: trait.Timer.html
#[derive(Copy, Clone)]
pub struct Instant(u32);

impl Instant {
    /// The maximum time between two `Instant`s that can be handled by `Instant::duration_since`.
    ///
    /// This is defined to be a value of a few minutes, intended to be sufficient for the BLE stack.
    pub const MAX_TIME_BETWEEN: Duration = Duration(1_000_000 * 60 * 5); // 5 minutes

    /// Creates an `Instant` from raw microseconds since an arbitrary implementation-defined
    /// reference point.
    ///
    /// This should only be called from a [`Timer`] implementation.
    ///
    /// [`Timer`]: trait.Timer.html
    pub fn from_raw_micros(micros: u32) -> Self {
        Instant(micros)
    }

    /// Returns the raw value from which this `Instant` was created.
    ///
    /// This should only be called from a [`Timer`] implementation.
    ///
    /// [`Timer`]: trait.Timer.html
    pub fn raw_micros(&self) -> u32 {
        self.0
    }

    /// Calculates the duration of time that has passed between `earlier` and `self`.
    ///
    /// The maximum duration that can be calculated by this method is defined as `MAX_TIME_BETWEEN`.
    /// Calling this method when the `Instant`s are further apart is an error and may panic. This is
    /// done as a safeguard, since `Instant`s can wrap around, which can cause the result of this
    /// function to be incorrect. It does not prevent that from happening, but makes unexpected
    /// durations show up much earlier.
    ///
    /// Both `self` and `earlier` must have been created by the same [`Timer`], or the result of
    /// this function will be unspecified.
    ///
    /// [`Timer`]: trait.Timer.html
    pub fn duration_since(&self, earlier: Instant) -> Duration {
        let micros_passed = self.0.wrapping_sub(earlier.0);
        debug_assert!(
            micros_passed <= Self::MAX_TIME_BETWEEN.0,
            "{}µs between instants {} and {}",
            micros_passed,
            earlier,
            self
        );

        Duration(micros_passed)
    }
}

/// `Instant`s can be subtracted, which computes the `Duration` between the rhs and lhs using
/// [`Instant::duration_since`].
///
/// [`Instant::duration_since`]: struct.Instant.html#method.duration_since
impl Sub<Instant> for Instant {
    type Output = Duration;

    fn sub(self, rhs: Self) -> Duration {
        self.duration_since(rhs)
    }
}

/// A `Duration` can be added to an `Instant`, moving the `Instant` forwards in time.
impl Add<Duration> for Instant {
    type Output = Self;

    fn add(self, d: Duration) -> Self {
        Instant(self.0.wrapping_add(d.as_micros()))
    }
}

impl AddAssign<Duration> for Instant {
    fn add_assign(&mut self, d: Duration) {
        *self = *self + d;
    }
}

/// A `Duration` can be subtracted from an `Instant`, moving the `Instant` backwards in time.
impl Sub<Duration> for Instant {
    type Output = Self;

    fn sub(self, d: Duration) -> Self {
        Instant(self.0.wrapping_sub(d.as_micros()))
    }
}

/// Subtracts a `Duration` from `self`.
impl SubAssign<Duration> for Instant {
    fn sub_assign(&mut self, d: Duration) {
        *self = *self - d;
    }
}

impl fmt::Display for Instant {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self.0 >= 1_000_000 {
            // s
            let (secs, subsec_micros) = (self.0 / 1_000_000, self.0 % 1_000_000);
            if subsec_micros == 0 {
                write!(f, "{}s", secs)
            } else {
                write!(f, "{}.{:06}s", secs, subsec_micros)
            }
        } else if self.0 >= 1000 {
            // ms
            let (millis, submilli_micros) = (self.0 / 1000, self.0 % 1000);
            if submilli_micros == 0 {
                write!(f, "{}ms", millis)
            } else {
                write!(f, "{}.{:03}ms", millis, submilli_micros)
            }
        } else {
            // µs
            write!(f, "{}µs", self.0)
        }
    }
}

impl fmt::Debug for Instant {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        <Self as fmt::Display>::fmt(self, f)
    }
}

/// Trait for time providers.
///
/// The hardware interface has to provide an implementation of `Timer` to the stack. The
/// implementation must have microsecond accuracy.
///
/// This trait can also be implemented by a mock timer for testing.
pub trait Timer {
    /// Obtain the current time as an `Instant`.
    ///
    /// The `Instant`s returned by this function must never move backwards in time, except when the
    /// underlying value wraps around.
    fn now(&self) -> Instant;
}