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
//! [`Future`]-based abstractions for timers.

use core::{
    future::Future,
    pin::Pin,
    task::{Context, Poll, Waker},
};
use embedded_hal::timer::CountDown;
use stm32f1xx_hal::{
    pac::{TIM2, TIM3},
    time::U32Ext,
    timer::{CountDownTimer, Event, Timer},
};

/// An asynchronous abstraction over a timer.
///
/// # Examples
///
/// ```
/// let mut timer: AsyncTimer<_> = Timer::tim2(dp.TIM2, &clocks, &mut apb1).into();
/// loop {
///     led.toggle();
///     timer.delay_for(2.hz()).await;
/// }
/// ```
pub struct AsyncTimer<T>(T);

impl<T> AsMut<T> for AsyncTimer<T> {
    fn as_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<T> AsyncTimer<T>
where
    T: CountDown,
{
    /// Creates a [`Future`] that resolves after the given time has been count down.
    pub fn delay_for<C>(&mut self, count: C) -> Delay<'_, T>
    where
        C: Into<T::Time>,
    {
        self.as_mut().start(count);
        Delay(&mut self.0)
    }
}

/// [`Future`] returned by [`delay_for`].
///
/// [`delay_for`]: AsyncTimer::delay_for
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Delay<'a, T>(&'a mut T);

impl<T> AsMut<T> for Delay<'_, T> {
    fn as_mut(&mut self) -> &mut T {
        self.0
    }
}

macro_rules! timer {
    ($(
        $TIMX:ident
    ),+) => {
        $(
            impl AsyncTimer<CountDownTimer<$TIMX>> {
                /// Releases the TIM peripheral
                pub fn release(self) -> $TIMX {
                    self.0.release()
                }
            }

            impl From<Timer<$TIMX>> for AsyncTimer<CountDownTimer<$TIMX>> {
                fn from(timer: Timer<$TIMX>) -> Self {
                    let mut count_down_timer = timer.start_count_down(1.hz());
                    count_down_timer.listen(Event::Update);
                    Self(count_down_timer)
                }
            }

            impl Future for Delay<'_, CountDownTimer<$TIMX>> {
                type Output = ();

                fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
                    use nb::{Error, Result};

                    match self.get_mut().as_mut().wait() {
                        Result::Ok(ok) => Poll::Ready(ok),
                        Result::Err(Error::Other(err)) => void::unreachable(err),
                        Result::Err(Error::WouldBlock) => {
                            waker_interrupt!($TIMX, cx.waker().clone());
                            Poll::Pending
                        }
                    }
                }
            }
        )+
    }
}

timer!(TIM2, TIM3);