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
//! Timer traits

/// Marker trait that indicates that a timer is periodic
pub trait Periodic {}

/// Non-blocking timer traits
pub mod nb {

    /// A count down timer
    ///
    /// # Contract
    ///
    /// - `self.start(count); block!(self.wait());` MUST block for AT LEAST the time specified by
    /// `count`.
    ///
    /// *Note* that the implementer doesn't necessarily have to be a *downcounting* timer; it could also
    /// be an *upcounting* timer as long as the above contract is upheld.
    ///
    /// # Examples
    ///
    /// You can use this timer to create delays
    ///
    /// ```
    /// extern crate embedded_hal as hal;
    /// #[macro_use(block)]
    /// extern crate nb;
    ///
    /// use hal::timer::nb::CountDown;
    ///
    /// fn main() {
    ///     let mut led: Led = {
    ///         // ..
    /// #       Led
    ///     };
    ///     let mut timer: Timer6 = {
    ///         // ..
    /// #       Timer6
    ///     };
    ///
    ///     Led.on();
    ///     timer.start(1.s()).unwrap();
    ///     block!(timer.wait()); // blocks for 1 second
    ///     Led.off();
    /// }
    ///
    /// # use core::convert::Infallible;
    /// # struct Seconds(u32);
    /// # trait U32Ext { fn s(self) -> Seconds; }
    /// # impl U32Ext for u32 { fn s(self) -> Seconds { Seconds(self) } }
    /// # struct Led;
    /// # impl Led {
    /// #     pub fn off(&mut self) {}
    /// #     pub fn on(&mut self) {}
    /// # }
    /// # struct Timer6;
    /// # impl hal::timer::nb::CountDown for Timer6 {
    /// #     type Error = Infallible;
    /// #     type Time = Seconds;
    /// #     fn start<T>(&mut self, _: T) -> Result<(), Self::Error> where T: Into<Seconds> { Ok(()) }
    /// #     fn wait(&mut self) -> ::nb::Result<(), Infallible> { Ok(()) }
    /// # }
    /// ```
    pub trait CountDown {
        /// An enumeration of `CountDown` errors.
        ///
        /// For infallible implementations, will be `Infallible`
        type Error: core::fmt::Debug;

        /// The unit of time used by this timer
        type Time;

        /// Starts a new count down
        fn start<T>(&mut self, count: T) -> Result<(), Self::Error>
        where
            T: Into<Self::Time>;

        /// Non-blockingly "waits" until the count down finishes
        ///
        /// # Contract
        ///
        /// - If `Self: Periodic`, the timer will start a new count down right after the last one
        /// finishes.
        /// - Otherwise the behavior of calling `wait` after the last call returned `Ok` is UNSPECIFIED.
        /// Implementers are suggested to panic on this scenario to signal a programmer error.
        fn wait(&mut self) -> nb::Result<(), Self::Error>;
    }

    impl<T: CountDown> CountDown for &mut T {
        type Error = T::Error;

        type Time = T::Time;

        fn start<TIME>(&mut self, count: TIME) -> Result<(), Self::Error>
        where
            TIME: Into<Self::Time>,
        {
            T::start(self, count)
        }

        fn wait(&mut self) -> nb::Result<(), Self::Error> {
            T::wait(self)
        }
    }

    /// Trait for cancelable countdowns.
    pub trait Cancel: CountDown {
        /// Tries to cancel this countdown.
        ///
        /// # Errors
        ///
        /// An error will be returned if the countdown has already been canceled or was never started.
        /// An error is also returned if the countdown is not `Periodic` and has already expired.
        fn cancel(&mut self) -> Result<(), Self::Error>;
    }

    impl<T: Cancel> Cancel for &mut T {
        fn cancel(&mut self) -> Result<(), Self::Error> {
            T::cancel(self)
        }
    }
}