use crate::{pac::PMC, HALExt};
use core::marker::PhantomData;
#[repr(u8)]
pub enum Error {
OutofBounds,
}
impl HALExt for PMC {
type T = Pmc<Enabled, _2v6>;
fn split(self) -> Pmc<Enabled, _2v6> {
Pmc {
peripheral: self,
_state: PhantomData,
_range: PhantomData,
lv_reset: LVReset {
_state: PhantomData,
},
lv_warn: LVWarn {
_state: PhantomData,
_range: PhantomData,
},
}
}
}
pub struct Pmc<State, Range> {
peripheral: PMC,
_state: PhantomData<State>,
_range: PhantomData<Range>,
pub lv_reset: LVReset<RunAndStop>,
pub lv_warn: LVWarn<Flag, Range>,
}
pub struct DontCare;
pub struct Enabled;
pub struct Disabled;
pub struct Flag;
pub struct Interrupt;
pub struct RunOnly;
pub struct RunAndStop;
pub struct LVReset<State> {
_state: PhantomData<State>,
}
pub struct LVWarn<State, Range> {
_state: PhantomData<State>,
_range: PhantomData<Range>,
}
pub struct _4v3;
pub struct _2v6;
#[repr(u8)]
pub enum LvwLow {
_2v7 = 0,
_2v8 = 1,
_2v9 = 2,
_3v0 = 3,
}
#[repr(u8)]
pub enum LvwHigh {
_4v4 = 0,
_4v5 = 1,
_4v6 = 2,
_4v7 = 3,
}
impl<Range> Pmc<Enabled, Range> {
pub fn into_disabled(self) -> Pmc<Disabled, Range> {
self.peripheral.spmsc1.modify(|_, w| w.lvde().clear_bit());
Pmc {
peripheral: self.peripheral,
_state: PhantomData,
_range: PhantomData,
lv_reset: self.lv_reset,
lv_warn: self.lv_warn,
}
}
}
impl Pmc<Enabled, _2v6> {
pub fn into_4v3(self) -> Pmc<Enabled, _4v3> {
self.peripheral.spmsc2.modify(|_, w| w.lvdv().set_bit());
Pmc {
peripheral: self.peripheral,
_state: PhantomData,
_range: PhantomData,
lv_reset: self.lv_reset,
lv_warn: self.lv_warn.into_high_range(),
}
}
}
impl Pmc<Enabled, _4v3> {
pub fn into_4v3(self) -> Pmc<Enabled, _2v6> {
self.peripheral.spmsc2.modify(|_, w| w.lvdv().set_bit());
Pmc {
peripheral: self.peripheral,
_state: PhantomData,
_range: PhantomData,
lv_reset: self.lv_reset,
lv_warn: self.lv_warn.into_low_range(),
}
}
}
impl<State, Range> LVWarn<State, Range> {
pub fn into_high_range(self) -> LVWarn<State, _4v3> {
LVWarn {
_state: PhantomData,
_range: PhantomData,
}
}
pub fn into_low_range(self) -> LVWarn<State, _2v6> {
LVWarn {
_state: PhantomData,
_range: PhantomData,
}
}
pub fn warning(&self) -> bool {
let pmc = unsafe { &(*PMC::ptr()) };
pmc.spmsc1.read().lvwf().bit()
}
pub fn clear_warning(&self) {
unsafe { (*PMC::ptr()).spmsc1.modify(|_, w| w.lvwack().bit(true)) };
}
}
impl<Range> LVWarn<Flag, Range> {
pub fn into_interrupt(self) -> LVWarn<Interrupt, Range> {
unsafe { (*PMC::ptr()).spmsc1.modify(|_, w| w.lvwie().set_bit()) };
LVWarn {
_state: PhantomData,
_range: PhantomData,
}
}
}
impl<Range> LVWarn<Interrupt, Range> {
pub fn into_flag(self) -> LVWarn<Flag, Range> {
unsafe { (*PMC::ptr()).spmsc1.modify(|_, w| w.lvwie().clear_bit()) };
LVWarn {
_state: PhantomData,
_range: PhantomData,
}
}
}
impl<State> LVWarn<State, _2v6> {
pub fn set_threshold(&self, threshold: LvwLow) {
let pmc = unsafe { &(*PMC::ptr()) };
pmc.spmsc2.modify(|_, w| w.lvwv().bits(threshold as u8));
}
pub fn threshold(&self) -> Result<LvwLow, Error> {
let pmc = unsafe { &(*PMC::ptr()) };
match pmc.spmsc2.read().lvwv().bits() {
0 => Ok(LvwLow::_2v7),
1 => Ok(LvwLow::_2v8),
2 => Ok(LvwLow::_2v9),
3 => Ok(LvwLow::_3v0),
_ => Err(Error::OutofBounds),
}
}
}
impl<State> LVWarn<State, _4v3> {
pub fn set_threshold(&self, threshold: LvwHigh) {
let pmc = unsafe { &(*PMC::ptr()) };
pmc.spmsc2.modify(|_, w| w.lvwv().bits(threshold as u8));
}
pub fn threshold(&self) -> Result<LvwHigh, Error> {
let pmc = unsafe { &(*PMC::ptr()) };
match pmc.spmsc2.read().lvwv().bits() {
0 => Ok(LvwHigh::_4v4),
1 => Ok(LvwHigh::_4v5),
2 => Ok(LvwHigh::_4v6),
3 => Ok(LvwHigh::_4v7),
_ => Err(Error::OutofBounds),
}
}
}
impl LVReset<RunAndStop> {
pub fn into_run_only(self) -> LVReset<RunOnly> {
let pmc = unsafe { &(*PMC::ptr()) };
pmc.spmsc1.modify(|_, w| w.lvdse().clear_bit());
LVReset {
_state: PhantomData,
}
}
pub fn into_disabled(self) -> LVReset<Disabled> {
let pmc = unsafe { &(*PMC::ptr()) };
pmc.spmsc1.modify(|_, w| w.lvdre().clear_bit());
LVReset {
_state: PhantomData,
}
}
}
impl LVReset<RunOnly> {
pub fn into_run_and_stop(self) -> LVReset<RunAndStop> {
let pmc = unsafe { &(*PMC::ptr()) };
pmc.spmsc1.modify(|_, w| w.lvdse().set_bit());
LVReset {
_state: PhantomData,
}
}
pub fn into_disabled(self) -> LVReset<Disabled> {
let pmc = unsafe { &(*PMC::ptr()) };
pmc.spmsc1.modify(|_, w| w.lvdre().clear_bit());
LVReset {
_state: PhantomData,
}
}
}