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
use nb;
use core::convert::Infallible;

/**
    A countdown timer which nonblockingly waits until the specified countdown
    is completed. The countdown is started by calling `start`.

    This trait is needed because `embedded_hal` currently does not have a standardised
    measure of time.

    The implementation of this trait will depend on your HAL implementation, but
    here is a sample impl for the stm32f1xx_hal


    ```rust
    struct LongTimer<T> {
        timer: Timer<T>,
        milliseconds_remaining: u32,
    }

    impl<T> LongTimer<T>
        where Timer<T>: CountDown<Time = Hertz> + Periodic
    {
        pub fn new(timer: Timer<T>) -> Self {
            Self {
                timer,
                milliseconds_remaining: 0
            }
        }
        fn process_tick(&mut self) -> nb::Result<(), Infallible>{
            match self.milliseconds_remaining {
                0 => Ok(()),
                t @ 0..=1000 => {
                    self.milliseconds_remaining = 0;
                    self.timer.start(((1000. / t as f32) as u32).hz());
                    Err(nb::Error::WouldBlock)
                }
                _ => {
                    self.timer.start(1.hz());
                    self.milliseconds_remaining -= 1000;
                    Err(nb::Error::WouldBlock)
                }
            }
        }
    }

    impl<T> esp01::LongTimer for LongTimer<T>
        where Timer<T>: CountDown<Time = Hertz> + Periodic
    {
        fn wait(&mut self) -> nb::Result<(), Infallible> {
            match self.timer.wait() {
                Ok(_) => self.process_tick(),
                Err(nb::Error::WouldBlock) => Err(nb::Error::WouldBlock),
                Err(_void) => unreachable!() // The void type can not exist
            }
        }
        fn start(&mut self, Millisecond(duration): Millisecond) {
            self.milliseconds_remaining = duration;
            // This will always return nb::WouldBlock (unless duration is 0)
            self.process_tick().ok();
        }

    }
    ```
*/
pub trait LongTimer {
    /**
      Returns Err(WouldBlock) if less time than `delay` has passed since `start_real`
      was called and `Ok(())` if more time has passed.

      If start_real hasn't been called yet, the behaviour is undefined
    */
    fn wait(&mut self) -> nb::Result<(), Infallible>;

    /**
        Start the count down for the specified amount of milliseconds.

        The required accuracy depends on the duration. Above 1 second, the
        requirements are very low.
    */
    fn start(&mut self, duration: Millisecond);
}


#[derive(Clone, Copy)]
pub struct Second(pub u32);
#[derive(Clone, Copy)]
pub struct Millisecond(pub u32);

impl From<Second> for Millisecond {
    fn from(Second(duration): Second) -> Self {
        return Millisecond(duration * 1000);
    }
}