mono_clock/
lib.rs

1#![cfg_attr(not(test), no_std)]
2///! Embedded time wrapper for RTIC's `monotonics::now()`
3///!
4///! # Design
5///!  `Clock` is implemented using the RTIC `app::monotonics::now()` which is backed
6///!   by a monotonic `Monotonic`.
7use core::hash::Hash;
8pub use embedded_time;
9use embedded_time::{clock::Error, fraction::Fraction, Clock, Instant, TimeInt};
10
11#[derive(Copy, Clone, Debug)]
12pub struct MonoClock<T, const HZ: u32>(fn() -> T);
13
14impl<T, const HZ: u32> MonoClock<T, HZ> {
15    ///! Create a new `MonoClock` using e.g. RTIC's `monotonics::now()`.
16    ///!
17    ///! Args:
18    ///! * now: a closure that returns the current ticks
19    ///!
20    ///! ```
21    ///! // In your `app` `init()`, set up a `Monotonic` as usual, e.g.:
22    ///! use mono_clock::MonoClock, systick_monotonic::Systick;
23    ///! const HZ: u32 = 1_000;
24    ///! let sysclk = 400_000_000u32;
25    ///! let mono = Systick::<HZ>::new(c.core.SYST, sysclk);
26    ///! // Then build a `Clock` that is `Copy` and can be passed
27    ///! // around by value or reference:
28    ///! let clock = MonoClock::<u32, HZ>::new(|| monotonics::now());
29    ///! ```
30    pub fn new(now: fn() -> T) -> Self {
31        Self(now)
32    }
33}
34
35impl<T: Copy + TimeInt + Hash, const HZ: u32> Clock for MonoClock<T, HZ> {
36    type T = T;
37
38    // The duration of each tick in seconds.
39    const SCALING_FACTOR: Fraction = Fraction::new(1, HZ);
40
41    fn try_now(&self) -> Result<Instant<Self>, Error> {
42        Ok(Instant::new((self.0)() as T))
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn it_works() {
52        let c = MonoClock::<u32, 1_000>::new(|| 42);
53        assert_eq!(c.try_now(), Ok(Instant::<MonoClock<_, 1_000>>::new(42)));
54    }
55}