use core::marker::PhantomData;
#[cfg(any(
feature = "pic32mx1xxfxxxb",
feature = "pic32mx2xxfxxxb",
feature = "pic32mx37x",
feature = "pic32mx47x",
))]
use crate::pac::{osc::RegisterBlock, OSC};
#[cfg(feature = "pic32mx2x4fxxxb")]
use crate::pac::{cru::RegisterBlock, CRU};
use super::Error;
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[repr(u8)]
pub enum Source {
Sysclock = 0,
Pbclock = 1,
Posc = 2,
Frc = 3,
Lprc = 4,
Sosc = 5,
Usbpll = 6,
Syspll = 7,
Refclki = 8,
}
pub struct Refclock {
pub(super) _private: PhantomData<()>, }
#[cfg(any(
feature = "pic32mx1xxfxxxb",
feature = "pic32mx2xxfxxxb",
feature = "pic32mx37x",
feature = "pic32mx47x",
))]
macro_rules! regs {
() => {
unsafe { &*OSC::ptr() as &RegisterBlock }
};
}
#[cfg(feature = "pic32mx2x4fxxxb")]
macro_rules! regs {
() => {
unsafe { &*CRU::ptr() as &RegisterBlock }
};
}
impl Refclock {
pub fn enable(&self) {
regs!().refoconset.write(|w| w.on().bit(true));
while !regs!().refocon.read().active().bit() {}
}
pub fn disable(&self) {
regs!().refoconclr.write(|w| w.on().bit(true));
while regs!().refocon.read().active().bit() {}
}
pub fn output_enable(&self) {
regs!().refoconset.write(|w| w.oe().bit(true));
}
pub fn output_disable(&self) {
regs!().refoconclr.write(|w| w.oe().bit(true));
}
pub fn select_source(&self, s: Source) -> Result<(), Error> {
if regs!().refocon.read().active().bit() {
return Err(Error::InvalidState);
}
regs!()
.refocon
.write(|w| unsafe { w.rosel().bits(s as u8) });
Ok(())
}
pub fn set_divisor(&self, div_q8: u32) -> Result<(), Error> {
let m = div_q8 & 0x1ff; let n = div_q8 >> 9; if n == 0 || n > 32767 {
return Err(Error::InvalidArgument);
}
if self.set_divisor_ongoing() {
return Err(Error::InvalidState);
}
regs!()
.refotrim
.write(|w| unsafe { w.rotrim().bits(m as u16) });
regs!()
.refocon
.modify(|_, w| unsafe { w.rodiv().bits(n as u16).divswen().bit(true) });
Ok(())
}
pub fn set_divisor_ongoing(&self) -> bool {
regs!().refocon.read().active().bit() && regs!().refocon.read().divswen().bit()
}
}