esp_01/
timing.rs

1use nb;
2use core::convert::Infallible;
3
4/**
5    A countdown timer which nonblockingly waits until the specified countdown
6    is completed. The countdown is started by calling `start`.
7
8    This trait is needed because `embedded_hal` currently does not have a standardised
9    measure of time.
10
11    The implementation of this trait will depend on your HAL implementation, but
12    here is a sample impl for the stm32f1xx_hal
13
14
15    ```rust
16    struct LongTimer<T> {
17        timer: Timer<T>,
18        milliseconds_remaining: u32,
19    }
20
21    impl<T> LongTimer<T>
22        where Timer<T>: CountDown<Time = Hertz> + Periodic
23    {
24        pub fn new(timer: Timer<T>) -> Self {
25            Self {
26                timer,
27                milliseconds_remaining: 0
28            }
29        }
30        fn process_tick(&mut self) -> nb::Result<(), Infallible>{
31            match self.milliseconds_remaining {
32                0 => Ok(()),
33                t @ 0..=1000 => {
34                    self.milliseconds_remaining = 0;
35                    self.timer.start(((1000. / t as f32) as u32).hz());
36                    Err(nb::Error::WouldBlock)
37                }
38                _ => {
39                    self.timer.start(1.hz());
40                    self.milliseconds_remaining -= 1000;
41                    Err(nb::Error::WouldBlock)
42                }
43            }
44        }
45    }
46
47    impl<T> esp01::LongTimer for LongTimer<T>
48        where Timer<T>: CountDown<Time = Hertz> + Periodic
49    {
50        fn wait(&mut self) -> nb::Result<(), Infallible> {
51            match self.timer.wait() {
52                Ok(_) => self.process_tick(),
53                Err(nb::Error::WouldBlock) => Err(nb::Error::WouldBlock),
54                Err(_void) => unreachable!() // The void type can not exist
55            }
56        }
57        fn start(&mut self, Millisecond(duration): Millisecond) {
58            self.milliseconds_remaining = duration;
59            // This will always return nb::WouldBlock (unless duration is 0)
60            self.process_tick().ok();
61        }
62
63    }
64    ```
65*/
66pub trait LongTimer {
67    /**
68      Returns Err(WouldBlock) if less time than `delay` has passed since `start_real`
69      was called and `Ok(())` if more time has passed.
70
71      If start_real hasn't been called yet, the behaviour is undefined
72    */
73    fn wait(&mut self) -> nb::Result<(), Infallible>;
74
75    /**
76        Start the count down for the specified amount of milliseconds.
77
78        The required accuracy depends on the duration. Above 1 second, the
79        requirements are very low.
80    */
81    fn start(&mut self, duration: Millisecond);
82}
83
84
85#[derive(Clone, Copy)]
86pub struct Second(pub u32);
87#[derive(Clone, Copy)]
88pub struct Millisecond(pub u32);
89
90impl From<Second> for Millisecond {
91    fn from(Second(duration): Second) -> Self {
92        return Millisecond(duration * 1000);
93    }
94}
95