diff --git a/rp2040-hal/src/pll.rs b/rp2040-hal/src/pll.rs index d57b322..598c554 100644 --- a/rp2040-hal/src/pll.rs +++ b/rp2040-hal/src/pll.rs @@ -2,26 +2,14 @@ // See [Chapter 2 Section 18](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) for more details use core::{ - convert::{ - Infallible, - TryFrom, - TryInto - }, + convert::{Infallible, TryFrom, TryInto}, marker::PhantomData, - ops::{ - RangeInclusive, - Range, - Deref - } + ops::{Deref, Range, RangeInclusive}, }; use embedded_time::{ fixed_point::FixedPoint, - rate::{ - Hertz, - Generic, - Rate - } + rate::{Generic, Hertz, Rate}, }; use nb::Error::WouldBlock; @@ -29,14 +17,13 @@ use nb::Error::WouldBlock; /// State of the PLL pub trait State {} - /// PLL is disabled. pub struct Disabled; /// PLL is configured, started and locking into its designated frequency. pub struct Locking { post_div1: u8, - post_div2: u8 + post_div2: u8, } /// PLL is locked : it delivers a steady frequency. @@ -55,28 +42,26 @@ impl PhaseLockedLoopDevice for rp2040_pac::PLL_USB {} /// A PLL. pub struct PhaseLockedLoop { device: D, - state: S + state: S, } impl PhaseLockedLoop { fn transition(self, state: To) -> PhaseLockedLoop { PhaseLockedLoop { device: self.device, - state: state + state: state, } } /// Releases the underlying device. - pub fn free(self) -> D{ + pub fn free(self) -> D { self.device } } - /// Error type for the PLL module. /// See Chapter 2, Section 18 ยง2 for details on constraints triggering these errors. pub enum Error { - /// Proposed VCO frequency is out of range. VCOFreqOutOfRange, @@ -90,13 +75,11 @@ pub enum Error { RefFreqOutOfRange, /// Bad argument : overflows, bad conversion, ... - BadArgument + BadArgument, } - /// Parameters for a PLL. pub struct PLLConfig { - /// Voltage Controlled Oscillator frequency. pub vco_freq: R, @@ -107,7 +90,7 @@ pub struct PLLConfig { pub post_div1: u8, /// Post Divider 2 - pub post_div2: u8 + pub post_div2: u8, } /// Common configs for the two PLLs. Both assume the XOSC is cadenced at 12MHz ! @@ -121,7 +104,7 @@ pub mod common_configs { vco_freq: Megahertz(1500), refdiv: 1, post_div1: 6, - post_div2: 2 + post_div2: 2, }; /// Default, nominal configuration for PLL_USB. @@ -129,12 +112,11 @@ pub mod common_configs { vco_freq: Megahertz(480), refdiv: 1, post_div1: 5, - post_div2: 2 + post_div2: 2, }; } impl PhaseLockedLoop { - /// Instantiates a new Phase-Locked-Loop device. pub fn new(dev: D) -> PhaseLockedLoop { PhaseLockedLoop { @@ -144,8 +126,14 @@ impl PhaseLockedLoop { } /// Configures and starts the PLL : it switches to Locking state. - pub fn initialize(self, xosc_frequency: Generic, config: PLLConfig) -> Result, Error> where R: Into>{ - + pub fn initialize( + self, + xosc_frequency: Generic, + config: PLLConfig, + ) -> Result, Error> + where + R: Into>, + { const VCO_FREQ_RANGE: RangeInclusive> = Hertz(400_000_000)..=Hertz(1600_000_000); const POSTDIV_RANGE: Range = 1..7; const FBDIV_RANGE: Range = 16..320; @@ -157,11 +145,12 @@ impl PhaseLockedLoop { let vco_freq: Hertz = vco_freq.try_into().map_err(|_| Error::BadArgument)?; if !VCO_FREQ_RANGE.contains(&vco_freq) { - return Err(Error::VCOFreqOutOfRange) + return Err(Error::VCOFreqOutOfRange); } - if !POSTDIV_RANGE.contains(&config.post_div1) || !POSTDIV_RANGE.contains(&config.post_div2) { - return Err(Error::PostDivOutOfRage) + if !POSTDIV_RANGE.contains(&config.post_div1) || !POSTDIV_RANGE.contains(&config.post_div2) + { + return Err(Error::PostDivOutOfRage); } let ref_freq_range: Range> = Hertz(5_000_000)..vco_freq.div(16); @@ -170,13 +159,13 @@ impl PhaseLockedLoop { self.device.pwr.reset(); self.device.fbdiv_int.reset(); - let ref_freq_hz = Hertz::::try_from(xosc_frequency). - map_err(|_| Error::BadArgument)?. - checked_div(&(config.refdiv as u32)). - ok_or(Error::BadArgument)?; + let ref_freq_hz = Hertz::::try_from(xosc_frequency) + .map_err(|_| Error::BadArgument)? + .checked_div(&(config.refdiv as u32)) + .ok_or(Error::BadArgument)?; if !ref_freq_range.contains(&ref_freq_hz) { - return Err(Error::RefFreqOutOfRange) + return Err(Error::RefFreqOutOfRange); } self.device.cs.write(|w| unsafe { @@ -184,13 +173,16 @@ impl PhaseLockedLoop { w }); - let fbdiv = vco_freq.checked_div(ref_freq_hz.integer()). - ok_or(Error::BadArgument)?; + let fbdiv = vco_freq + .checked_div(ref_freq_hz.integer()) + .ok_or(Error::BadArgument)?; - let fbdiv: u16 = (*fbdiv.integer()).try_into().map_err(|_| Error::BadArgument)?; + let fbdiv: u16 = (*fbdiv.integer()) + .try_into() + .map_err(|_| Error::BadArgument)?; if !FBDIV_RANGE.contains(&fbdiv) { - return Err(Error::FBDIVOutOfRange) + return Err(Error::FBDIVOutOfRange); } self.device.fbdiv_int.write(|w| unsafe { @@ -199,7 +191,7 @@ impl PhaseLockedLoop { }); // Turn on PLL - self.device.pwr.modify(|_,w| { + self.device.pwr.modify(|_, w| { w.pd().clear_bit(); w.vcopd().clear_bit(); w @@ -209,33 +201,31 @@ impl PhaseLockedLoop { let post_div2 = config.post_div2; Ok(self.transition(Locking { - post_div1, post_div2 + post_div1, + post_div2, })) } } /// A token that's given when the PLL is properly locked, so we can safely transition to the next state. pub struct LockedPLLToken { - _private: PhantomData + _private: PhantomData, } impl PhaseLockedLoop { - /// Awaits locking of the PLL. pub fn await_lock(&self) -> nb::Result, Infallible> { - if self.device.cs.read().lock().bit_is_clear() { return Err(WouldBlock); } Ok(LockedPLLToken { - _private: PhantomData + _private: PhantomData, }) } /// Exchanges a token for a Locked PLL. pub fn get_locked(self, _token: LockedPLLToken) -> PhaseLockedLoop { - // Set up post dividers self.device.prim.write(|w| unsafe { w.postdiv1().bits(self.state.post_div1); @@ -244,12 +234,11 @@ impl PhaseLockedLoop { }); // Turn on post divider - self.device.pwr.modify(|_,w| { + self.device.pwr.modify(|_, w| { w.postdivpd().clear_bit(); w }); self.transition(Locked) } - }