pub struct Cpm { /* private fields */ }Expand description
A CPM modulator and its detectors (see the module documentation).
Implementations§
Source§impl Cpm
impl Cpm
Sourcepub const MAX_DIFFERENCE_SEQUENCES: usize
pub const MAX_DIFFERENCE_SEQUENCES: usize
The largest number of difference sequences Cpm::min_distance2 visits.
Sourcepub fn ml_detect(&self, r: &[C64]) -> Result<Vec<usize>>
pub fn ml_detect(&self, r: &[C64]) -> Result<Vec<usize>>
The coherent maximum-likelihood sequence detector (Viterbi algorithm over the phase trellis): the symbol indices of the most likely sequence, starting from the initial state of the modulator and ending in any state.
§Errors
comnum_core::Error::Shape unless r holds a positive whole number of symbols.
§Examples
use comnum_waveform::cpm::{CpmConfig, FrequencyPulse};
let cpm = CpmConfig { order: 4, h_num: 1, h_den: 4, pulse: FrequencyPulse::RaisedCosine, length: 2, sps: 4 }.build()?;
let a = vec![0, 3, 1, 2, 2, 0, 1, 3, 3, 0];
assert_eq!(cpm.ml_detect(&cpm.modulate(&a)?)?, a);Sourcepub fn ml_detect_path(&self, r: &[C64]) -> Result<MlPath>
pub fn ml_detect_path(&self, r: &[C64]) -> Result<MlPath>
The maximum-likelihood sequence with its terminal phase states (see MlPath).
§Errors
As Cpm::ml_detect.
Sourcepub fn msk_detect(&self, r: &[C64]) -> Result<Vec<u8>>
pub fn msk_detect(&self, r: &[C64]) -> Result<Vec<u8>>
The quadrature detector of MSK: the boundary bits $d_{n}$, $n = 1 \dots N$ ($d_{n} = +1$ is the bit 1), decided from $\operatorname{Re}\left[(-j)^{n} \int_{(n-1)T}^{(n+1)T} r(t) \cos \frac{\pi (t - nT)}{2T} \, dt\right]$ (the last window is truncated to the signal). Over AWGN, each decision has the error probability $Q(\sqrt{2 E_{b}/N_{0}})$ of antipodal signalling.
§Errors
comnum_core::Error::Config unless the signal is MSK, comnum_core::Error::Shape
unless it holds a whole number of symbols.
Sourcepub fn differential_detect(
&self,
r: &[C64],
rx_bt: Option<f64>,
) -> Result<Vec<usize>>
pub fn differential_detect( &self, r: &[C64], rx_bt: Option<f64>, ) -> Result<Vec<usize>>
The one-symbol differential phase detector of binary CPM: after an optional
low-pass predetection filter of normalised 3 dB bandwidth rx_bt (None for no
filter; the band-pass bandwidth $B_{i}$ of Simon & Wang, 1984, is twice this
value, and about $0.5/T$ is the best choice for MSK), the
signal is sampled every symbol at $t_{n} = (n + (L + 1)/2) T$, where the phase
increment $\varphi(t_{n}) - \varphi(t_{n-1})$ depends most on $a_{n}$ (for an even
$L$ and an odd sps the instant is rounded down to a sample), and
$\hat{a}{n} = \operatorname{sign} \operatorname{Im} (r{n} r_{n-1}^{\ast})$. A
symbol whose instant falls after the end of the signal uses its last sample.
For MSK without filter the increment is exactly $\pi a_{n}/2$; the partial response of GMSK closes the eye, so the detector degrades with $BT$.
§Errors
comnum_core::Error::Config unless the signal is binary or if rx_bt is not
positive, comnum_core::Error::Shape unless it holds a whole number of symbols.
Sourcepub fn min_distance2(&self, max_len: usize) -> Result<f64>
pub fn min_distance2(&self, max_len: usize) -> Result<f64>
The normalised minimum squared Euclidean distance over the pairs of sequences
that diverge at $t = 0$ and merge again within max_len symbols (the upper bound
$d_{B}^{2}$ of Anderson, Aulin & Sundberg, ch. 3, which is the true $d_{\min}^{2}$
when the shortest merge is the closest one, as for MSK):
$$ d^{2} = \frac{\log_{2} M}{T} \int_{0}^{(N + L - 1) T} \left[1 - \cos \Delta \varphi(t)\right] dt, \qquad \Delta \varphi(t) = 2 \pi h \sum_{k=0}^{N-1} \gamma_{k} \, q(t - kT), $$
over the difference sequences $\gamma_{k} = a_{k} - a_{k}^{\prime} \in \{0, \pm 2,
\dots, \pm 2(M-1)\}$ with $\gamma_{0} \ne 0$ and $\pi h \sum_{k} \gamma_{k}
\equiv 0 \pmod{2 \pi}$ (the merge). The integral is evaluated by Simpson’s rule
with 256 intervals per symbol (within $10^{-9}$ of the closed form $2(1 -
\operatorname{sinc} 2h)$ of binary CPFSK); it is infinite if no sequence merges
within max_len symbols. With this normalisation antipodal signalling has
$d^{2} = 2$. The search visits $(2M - 1)^{N}$ difference sequences for max_len
$= N$, at most Cpm::MAX_DIFFERENCE_SEQUENCES; with max_len $= 0$ it visits
none and returns infinity.
§Errors
Error::Config if $(2M - 1)^{N}$ exceeds Cpm::MAX_DIFFERENCE_SEQUENCES (at
max_len = 20, binary CPM would visit $3.5 \cdot 10^{9}$ sequences).
§Examples
use comnum_waveform::cpm::CpmConfig;
let msk = CpmConfig::msk(4).build()?;
assert!((msk.min_distance2(3)? - 2.0).abs() < 1e-3);
assert!(msk.min_distance2(20).is_err());Source§impl Cpm
impl Cpm
Sourcepub fn config(&self) -> &CpmConfig
pub fn config(&self) -> &CpmConfig
The validated parameters (the modulation index in lowest terms).
Sourcepub fn with_sample_rate(self, sample_rate: Hertz) -> Result<Cpm>
pub fn with_sample_rate(self, sample_rate: Hertz) -> Result<Cpm>
The same modulator at the sample rate sample_rate (sps samples per symbol) of
the verb traits.
§Errors
comnum_core::Error::Config for a sample rate that is not positive and finite.
§Examples
use comnum_core::prelude::*;
use comnum_waveform::cpm::CpmConfig;
let mut msk = CpmConfig::msk(8).build()?.with_sample_rate(Hertz(8e3))?;
let a = Labels::from_stream(vec![1, 0, 0, 1, 1])?;
let s = Modulate::modulate(&msk, &a)?;
assert_eq!((s.len(), s.sample_rate()), (40, Hertz(8e3)));
assert_eq!(Demodulate::<Labels>::demodulate(&mut msk, &s)?, a);Sourcepub fn sample_rate(&self) -> Hertz
pub fn sample_rate(&self) -> Hertz
The sample rate of the signal of the verb traits (1 Hz unless set by
Cpm::with_sample_rate).
Sourcepub fn n_phase_states(&self) -> usize
pub fn n_phase_states(&self) -> usize
The number of terminal phases, $2q$ (the trellis visits $q$ of them when $p$ is even).
Sourcepub fn symbol_value(&self, index: usize) -> f64
pub fn symbol_value(&self, index: usize) -> f64
The symbol value $a = 2i - (M - 1)$ of the index i.
Sourcepub fn phase_response(&self) -> &[f64]
pub fn phase_response(&self) -> &[f64]
The tabulated phase response, $q(k T / \mathrm{sps})$ for $k < L \cdot \mathrm{sps}$.
Trait Implementations§
Source§impl Demodulate<Labels> for Cpm
CPM as a Demodulate block: the coherent maximum-likelihood sequence detector
Cpm::ml_detect on one stream of samples at Cpm::sample_rate.
impl Demodulate<Labels> for Cpm
CPM as a Demodulate block: the coherent maximum-likelihood sequence detector
Cpm::ml_detect on one stream of samples at Cpm::sample_rate.
Source§fn demodulate_into(&mut self, y: &Signal, out: &mut Labels) -> Result<()>
fn demodulate_into(&mut self, y: &Signal, out: &mut Labels) -> Result<()>
§Errors
comnum_core::Error::Config for several streams or a signal at another sample rate,
and the errors of Cpm::ml_detect.
Source§impl Modulate<Labels> for Cpm
CPM as a Modulate block: one stream of symbol indices into one stream of samples
at Cpm::sample_rate, by Cpm::modulate.
impl Modulate<Labels> for Cpm
CPM as a Modulate block: one stream of symbol indices into one stream of samples
at Cpm::sample_rate, by Cpm::modulate.
Source§fn modulate_into(&self, x: &Labels, out: &mut Signal) -> Result<()>
fn modulate_into(&self, x: &Labels, out: &mut Signal) -> Result<()>
§Errors
comnum_core::Error::Config for several streams, and the errors of
Cpm::modulate.