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