use volatile_register::{RO, RW};
use crate::peripheral::SYST;
#[repr(C)]
pub struct RegisterBlock {
pub csr: RW<u32>,
pub rvr: RW<u32>,
pub cvr: RW<u32>,
pub calib: RO<u32>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SystClkSource {
Core,
External,
}
const SYST_COUNTER_MASK: u32 = 0x00ff_ffff;
const SYST_CSR_ENABLE: u32 = 1 << 0;
const SYST_CSR_TICKINT: u32 = 1 << 1;
const SYST_CSR_CLKSOURCE: u32 = 1 << 2;
const SYST_CSR_COUNTFLAG: u32 = 1 << 16;
const SYST_CALIB_SKEW: u32 = 1 << 30;
const SYST_CALIB_NOREF: u32 = 1 << 31;
impl SYST {
#[inline]
pub fn clear_current(&mut self) {
unsafe { self.cvr.write(0) }
}
#[inline]
pub fn disable_counter(&mut self) {
unsafe { self.csr.modify(|v| v & !SYST_CSR_ENABLE) }
}
#[inline]
pub fn disable_interrupt(&mut self) {
unsafe { self.csr.modify(|v| v & !SYST_CSR_TICKINT) }
}
#[inline]
pub fn enable_counter(&mut self) {
unsafe { self.csr.modify(|v| v | SYST_CSR_ENABLE) }
}
#[inline]
pub fn enable_interrupt(&mut self) {
unsafe { self.csr.modify(|v| v | SYST_CSR_TICKINT) }
}
#[inline]
pub fn get_clock_source(&mut self) -> SystClkSource {
if self.csr.read() & SYST_CSR_CLKSOURCE != 0 {
SystClkSource::Core
} else {
SystClkSource::External
}
}
#[inline]
pub fn get_current() -> u32 {
unsafe { (*Self::PTR).cvr.read() }
}
#[inline]
pub fn get_reload() -> u32 {
unsafe { (*Self::PTR).rvr.read() }
}
#[inline]
pub fn get_ticks_per_10ms() -> u32 {
unsafe { (*Self::PTR).calib.read() & SYST_COUNTER_MASK }
}
#[inline]
pub fn has_reference_clock() -> bool {
unsafe { (*Self::PTR).calib.read() & SYST_CALIB_NOREF == 0 }
}
#[inline]
pub fn has_wrapped(&mut self) -> bool {
self.csr.read() & SYST_CSR_COUNTFLAG != 0
}
#[inline]
pub fn is_counter_enabled(&mut self) -> bool {
self.csr.read() & SYST_CSR_ENABLE != 0
}
#[inline]
pub fn is_interrupt_enabled(&mut self) -> bool {
self.csr.read() & SYST_CSR_TICKINT != 0
}
#[inline]
pub fn is_precise() -> bool {
unsafe { (*Self::PTR).calib.read() & SYST_CALIB_SKEW == 0 }
}
#[inline]
pub fn set_clock_source(&mut self, clk_source: SystClkSource) {
match clk_source {
SystClkSource::External => unsafe { self.csr.modify(|v| v & !SYST_CSR_CLKSOURCE) },
SystClkSource::Core => unsafe { self.csr.modify(|v| v | SYST_CSR_CLKSOURCE) },
}
}
#[inline]
pub fn set_reload(&mut self, value: u32) {
unsafe { self.rvr.write(value) }
}
}