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
use embedded_hal::timer::{Cancel, CountDown, Periodic};
use esp8266::TIMER;
use void::Void;

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

pub trait TimerExt {
    fn timers(self, frequency: u32) -> (Timer1, Timer2);
}

impl TimerExt for TIMER {
    fn timers(self, frequency: u32) -> (Timer1, Timer2) {
        (Timer1::new(frequency), Timer2::new(frequency))
    }
}

macro_rules! impl_timer {
    ($TIMER:ident: ($ctrl:ident, $load:ident, $alarm:ident, $int:ident, $clr_mask:ident, $load_value:ident)) => {
        pub struct $TIMER {
            ticks_per_ms: u32,
        }

        impl $TIMER {
            fn new(frequency: u32) -> Self {
                let timer = unsafe { (&*TIMER::ptr()) };
                timer.$ctrl.write(|w| {
                    w.rollover()
                        .set_bit()
                        .interrupt_type()
                        .level()
                        .prescale_divider()
                        .devided_by_256()
                });
                timer.$alarm.write(|w| unsafe { w.bits(0) });

                $TIMER {
                    ticks_per_ms: (1_000_000_000 / (frequency / 256)),
                }
            }
        }

        impl CountDown for $TIMER {
            type Time = Nanoseconds;

            fn start<T>(&mut self, timeout: T)
            where
                T: Into<Nanoseconds>,
            {
                let timer = unsafe { (&*TIMER::ptr()) };
                let timeout: Nanoseconds = timeout.into();

                let ticks = timeout.0 / self.ticks_per_ms;
                timer.$ctrl.modify(|_, w| w.timer_enable().set_bit());
                timer.$load.write(|w| unsafe { w.bits($load_value(ticks)) });
            }

            fn wait(&mut self) -> nb::Result<(), Void> {
                let timer = unsafe { (&*TIMER::ptr()) };
                if timer.$ctrl.read().$int().bit_is_clear() {
                    Err(nb::Error::WouldBlock)
                } else {
                    timer.$int.modify(|_, w| w.$clr_mask().set_bit());
                    Ok(())
                }
            }
        }

        impl Periodic for $TIMER {}

        impl Cancel for $TIMER {
            type Error = Void;

            fn cancel(&mut self) -> Result<(), Self::Error> {
                let timer = unsafe { (&*TIMER::ptr()) };
                timer.$ctrl.modify(|_, w| w.timer_enable().clear_bit());
                Ok(())
            }
        }
    };
}

fn timer1_load_value(ticks: u32) -> u32 {
    ticks
}

fn timer2_load_value(ticks: u32) -> u32 {
    // timer2 counts up
    u32::max_value() - ticks
}

impl_timer!(
    Timer1:
        (
            frc1_ctrl,
            frc1_load,
            frc1_load,
            frc1_int,
            frc1_int_clr_mask,
            timer1_load_value
        )
);
impl_timer!(
    Timer2:
        (
            frc2_ctrl,
            frc2_load,
            frc2_alarm,
            frc2_int,
            frc2_int_clr_mask,
            timer2_load_value
        )
);