#![no_implicit_prelude]
extern crate core;
extern crate cortex_m;
use core::clone::Clone;
use core::marker::Copy;
use cortex_m::interrupt::free;
use crate::int::Acknowledge;
use crate::pac::TIMER;
use crate::{Board, write_reg};
#[repr(u8)]
pub enum AlarmID {
Alarm0 = 1u8,
Alarm1 = 2u8,
Alarm2 = 4u8,
Alarm3 = 8u8,
}
pub struct Alarm {
i: AlarmID,
dev: TIMER,
}
impl Alarm {
#[inline]
pub fn new(p: &Board, a: AlarmID) -> Alarm {
p.enable_ticks(); Alarm {
i: a,
dev: unsafe { TIMER::steal() },
}
}
#[inline]
pub fn cancel(&mut self) {
let i = self.i as u32;
unsafe { self.dev.armed().write_with_zero(|r| r.bits(i)) };
write_reg(self.dev.intf().as_ptr(), i, true)
}
#[inline]
pub fn done(&self) -> bool {
self.dev.armed().read().bits() & (self.i as u32) == 0
}
#[inline]
pub fn id(&self) -> &AlarmID {
&self.i
}
#[inline]
pub fn interrupt_clear(&mut self) {
write_reg(self.dev.intf().as_ptr(), self.i as u32, true);
match &self.i {
AlarmID::Alarm0 => unsafe { self.dev.intr().write_with_zero(|r| r.alarm_0().clear_bit_by_one()) },
AlarmID::Alarm1 => unsafe { self.dev.intr().write_with_zero(|r| r.alarm_1().clear_bit_by_one()) },
AlarmID::Alarm2 => unsafe { self.dev.intr().write_with_zero(|r| r.alarm_2().clear_bit_by_one()) },
AlarmID::Alarm3 => unsafe { self.dev.intr().write_with_zero(|r| r.alarm_3().clear_bit_by_one()) },
}
}
pub fn current_tick(&self) -> u64 {
let mut v = self.dev.timerawh().read().bits();
loop {
let (l, h) = (
self.dev.timerawl().read().bits(),
self.dev.timerawh().read().bits(),
);
if v == h {
return unsafe { (h as u64).unchecked_shl(32) | l as u64 };
}
v = h;
}
}
#[inline]
pub fn schedule(&mut self, ms: u32) {
self.schedule_us(ms * 1_000);
}
pub fn schedule_us(&mut self, us: u32) {
let v = self.current_tick() + us as u64;
let l = (v & 0xFFFFFFFF) as u32;
free(|_| {
match &self.i {
AlarmID::Alarm0 => unsafe { self.dev.alarm0().write(|r| r.bits(l)) },
AlarmID::Alarm1 => unsafe { self.dev.alarm1().write(|r| r.bits(l)) },
AlarmID::Alarm2 => unsafe { self.dev.alarm2().write(|r| r.bits(l)) },
AlarmID::Alarm3 => unsafe { self.dev.alarm3().write(|r| r.bits(l)) },
}
let (n, i) = (self.current_tick(), self.i as u32);
if n <= v || self.dev.armed().read().bits() & i == 0 {
return;
}
unsafe { self.dev.armed().write_with_zero(|r| r.bits(i)) };
write_reg(self.dev.intf().as_ptr(), i, false);
})
}
#[inline]
pub fn interrupt_set(&mut self, en: bool) {
write_reg(self.dev.inte().as_ptr(), self.i as u32, !en)
}
}
impl Copy for AlarmID {}
impl Clone for AlarmID {
#[inline]
fn clone(&self) -> AlarmID {
*self
}
}
impl Acknowledge for Alarm {
#[inline]
fn ack_interrupt(&mut self) -> bool {
let r = self.done();
self.interrupt_clear();
r
}
}