Struct idsp::PLL

source ·
pub struct PLL { /* private fields */ }
Expand description

Type-II, sampled phase, discrete time PLL

This PLL tracks the frequency and phase of an input signal with respect to the sampling clock. The open loop transfer function is I^2,I from input phase to output phase and P,I from input phase to output frequency.

The transfer functions (for phase and frequency) contain an additional zero at Nyquist.

The PLL locks to any frequency (i.e. it locks to the alias in the first Nyquist zone) and is stable for any gain (1 <= shift <= 30). It has a single parameter that determines the loop bandwidth in octave steps. The gain can be changed freely between updates.

The frequency and phase settling time constants for a frequency/phase jump are 1 << shift update cycles. The loop bandwidth is 1/(2*pi*(1 << shift)) in units of the sample rate. While the phase is being settled after settling the frequency, there is a typically very small frequency overshoot.

All math is naturally wrapping 32 bit integer. Phase and frequency are understood modulo that overflow in the first Nyquist zone. Expressing the IIR equations in other ways (e.g. single (T)-DF-{I,II} biquad/IIR) would break on overflow (i.e. every cycle).

There are no floating point rounding errors here. But there is integer quantization/truncation error of the shift lowest bits leading to a phase offset for very low gains. Truncation bias is applied. Rounding is “half up”. The phase truncation error can be removed very efficiently by dithering.

This PLL does not unwrap phase slips accumulated during (frequency) lock acquisition. This can and should be implemented elsewhere by unwrapping and scaling the input phase and un-scaling and wrapping output phase and frequency. This then affects dynamic range, gain, and noise accordingly.

The extension to I^3,I^2,I behavior to track chirps phase-accurately or to i64 data to increase resolution for extremely narrowband applications is obvious.

This PLL implements first order noise shaping to reduce quantization errors.

Implementations§

source§

impl PLL

source

pub fn update(&mut self, x: Option<i32>, k: i32)

Update the PLL with a new phase sample. This needs to be called (sampled) periodically. The signal’s phase/frequency is reconstructed relative to the sampling period.

Args:

  • x: New input phase sample or None if a sample has been missed.
  • k: Feedback gain.

Returns: A tuple of instantaneous phase and frequency estimates.

source

pub fn phase(&self) -> i32

Return the current phase estimate

source

pub fn frequency(&self) -> i32

Return the current frequency estimate

Trait Implementations§

source§

impl Clone for PLL

source§

fn clone(&self) -> PLL

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for PLL

source§

fn default() -> PLL

Returns the “default value” for a type. Read more
source§

impl<'de> Deserialize<'de> for PLL

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for PLL

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl Copy for PLL

Auto Trait Implementations§

§

impl RefUnwindSafe for PLL

§

impl Send for PLL

§

impl Sync for PLL

§

impl Unpin for PLL

§

impl UnwindSafe for PLL

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,