use crate::pac::INT; use crate::time::Hertz;
use embedded_hal::delay::DelayNs;
use embedded_hal_0_2::blocking::delay::{DelayMs, DelayUs};
use critical_section::Mutex;
pub use mips_mcu::core_timer::read_count;
use mips_mcu::core_timer::{read_compare, write_compare};
use core::cell::Cell;
const fn rounded_div_u32(a: u32, b: u32) -> u32 {
(a + b / 2) / b
}
pub struct Delay {
ticks_per_us: u32,
nanos_per_tick: u32,
}
impl Delay {
pub const fn new(sysclock: Hertz) -> Self {
let ticks_per_us = sysclock.0 / 1_000_000 / 2;
let nanos_per_tick = rounded_div_u32(2 * 1_000_000_000, sysclock.0);
Delay {
ticks_per_us,
nanos_per_tick,
}
}
}
impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, ms: u32) {
DelayUs::delay_us(self, ms * 1_000);
}
}
impl DelayMs<i32> for Delay {
fn delay_ms(&mut self, ms: i32) {
if ms >= 0 {
DelayUs::delay_us(self, (ms as u32) * 1000);
}
}
}
impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
DelayMs::delay_ms(self, ms as u32);
}
}
impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
DelayMs::delay_ms(self, ms as u32);
}
}
impl DelayUs<u32> for Delay {
fn delay_us(&mut self, us: u32) {
let mut total_ticks = us as u64 * self.ticks_per_us as u64;
while total_ticks != 0 {
let current_ticks = if total_ticks <= 0xffff_ffffu64 {
total_ticks as u32
} else {
0xffff_ffffu32
};
let start = read_count();
total_ticks -= current_ticks as u64;
while read_count().wrapping_sub(start) < current_ticks {}
}
}
}
impl DelayUs<u16> for Delay {
fn delay_us(&mut self, us: u16) {
let start = read_count();
let ticks = us as u32 * self.ticks_per_us;
while read_count().wrapping_sub(start) < ticks {}
}
}
impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
DelayUs::delay_us(self, us as u16)
}
}
impl DelayNs for Delay {
fn delay_ns(&mut self, ns: u32) {
let start = read_count();
let ticks = ns / self.nanos_per_tick;
while read_count().wrapping_sub(start) < ticks {}
}
}
pub struct Timer {}
static TIMER: Mutex<Cell<Option<Timer>>> = Mutex::new(Cell::new(Some(Timer {})));
impl Timer {
pub fn take() -> Self {
let timeropt = critical_section::with(|cs| {
let cell = TIMER.borrow(cs);
cell.take()
});
timeropt.unwrap()
}
pub fn free(self) {
critical_section::with(|cs| {
let cell = TIMER.borrow(cs);
cell.replace(Some(self));
});
}
pub fn read_count(&self) -> u32 {
read_count()
}
pub fn read_compare(&self) -> u32 {
read_compare()
}
pub fn write_compare(&self, compare: u32) {
unsafe {
write_compare(compare);
}
}
pub fn enable_interrupts(&self, int: &INT) {
int.iec0set.write(|w| w.ctie().bit(true));
}
pub fn disable_interrupts(&self, int: &INT) -> bool {
let was_enabled = int.iec0.read().ctie().bit();
int.iec0clr.write(|w| w.ctie().bit(true));
was_enabled
}
pub fn set_interrupt_prio(&self, int: &INT, prio: u8, subprio: u8) {
int.ipc0
.modify(|_, w| unsafe { w.ctip().bits(prio).ctis().bits(subprio) });
}
}