pub struct Ofdm {
pub n_fft: usize,
pub n_active: usize,
pub oversampling: usize,
pub n_cp: usize,
pub dc_null: bool,
pub dft_spread: bool,
pub sample_rate: Hertz,
}Expand description
An OFDM (or DFT-spread OFDM) modulator and demodulator.
Fields§
§n_fft: usizeSize $N$ of the subcarrier grid.
n_active: usizeNumber $K$ of active (modulated) subcarriers, centred on the carrier.
oversampling: usizeOversampling factor $L$ (IFFT of size $L N$).
n_cp: usizeCyclic prefix, in Nyquist-rate samples ($L N_{\mathrm{cp}}$ samples).
dc_null: boolLeave the DC subcarrier empty (the active subcarriers skip $k = 0$).
dft_spread: boolDFT spreading of the data (localised SC-FDMA).
sample_rate: HertzThe rate of the modulated samples, $L N \Delta f$ ($\Delta f$ the subcarrier
spacing): the rate of the Signal of Modulate, and the rate Demodulate
expects; 1 Hz by default (time in samples).
Implementations§
Source§impl Ofdm
impl Ofdm
Sourcepub fn new(n_fft: usize, n_active: usize) -> Result<Ofdm>
pub fn new(n_fft: usize, n_active: usize) -> Result<Ofdm>
$K$ active subcarriers out of $N$, oversampling 4, no prefix, at the sample rate 1 Hz.
§Errors
comnum_core::Error::Config unless $1 \le K \le N$.
Sourcepub fn check(&self) -> Result<()>
pub fn check(&self) -> Result<()>
Validate the configuration.
§Errors
comnum_core::Error::Config for an empty or overfull grid, a zero oversampling or a
sample rate that is not positive and finite.
Sourcepub fn block_len(&self) -> usize
pub fn block_len(&self) -> usize
Samples per block, prefix included, $L (N + N_{\mathrm{cp}})$.
Sourcepub fn subcarrier(&self, i: usize) -> isize
pub fn subcarrier(&self, i: usize) -> isize
Subcarrier index $k$ of the active subcarrier i.
Sourcepub fn bin(&self, i: usize) -> usize
pub fn bin(&self, i: usize) -> usize
FFT bin of the active subcarrier i (fft::centred_bin, one bin further from
the subcarrier 0 on with dc_null).
Sourcepub fn pulse(&self, i: usize, n: usize) -> (usize, Vec<C64>)
pub fn pulse(&self, i: usize, n: usize) -> (usize, Vec<C64>)
The transmit pulse of the active subcarrier i of symbol n, prefix included, on
its support: (first sample, values), $\frac{1}{\sqrt{LN}} e^{j 2\pi k (t -
L N_{\mathrm{cp}})/(LN)}$ for $t = 0, \dots, L(N + N_{\mathrm{cp}}) - 1$ (energy
$(N + N_{\mathrm{cp}})/N$); a column of the matrix $\mathbf{G}$ of Nissel, Schwarz &
Rupp 2017, eq. (20).
Sourcepub fn window(&self, i: usize, n: usize) -> (usize, Vec<C64>)
pub fn window(&self, i: usize, n: usize) -> (usize, Vec<C64>)
The receive pulse (the window of the demodulator) of the active subcarrier i of
symbol n: the Ofdm::pulse without its prefix, of unit energy, on its support
(first sample, values).
Sourcepub fn is_active_bin(&self, bin: usize) -> bool
pub fn is_active_bin(&self, bin: usize) -> bool
Whether an FFT bin carries an active subcarrier.
Sourcepub fn spread(&self, data: &[C64]) -> Vec<C64> ⓘ
pub fn spread(&self, data: &[C64]) -> Vec<C64> ⓘ
The values of the active subcarriers of data (the identity, or the unitary DFT
of size $K$ with dft_spread).
Sourcepub fn to_time(&self, active: &[C64]) -> Result<Vec<C64>>
pub fn to_time(&self, active: &[C64]) -> Result<Vec<C64>>
The time block (without prefix, $L N$ samples) of the values of the active subcarriers.
§Errors
comnum_core::Error::Shape if active does not have $K$ values.
Sourcepub fn to_active(&self, block: &[C64]) -> Result<Vec<C64>>
pub fn to_active(&self, block: &[C64]) -> Result<Vec<C64>>
The values of the active subcarriers of a time block (without prefix).
§Errors
comnum_core::Error::Shape if block does not have $L N$ samples.
Sourcepub fn filter(&self, block: &[C64]) -> Result<Vec<C64>>
pub fn filter(&self, block: &[C64]) -> Result<Vec<C64>>
Keep only the active subcarriers of a time block (an ideal band-pass filter).
§Errors
As Ofdm::to_active.
Sourcepub fn with_prefix(&self, block: &[C64]) -> Result<Vec<C64>>
pub fn with_prefix(&self, block: &[C64]) -> Result<Vec<C64>>
Prepend the cyclic prefix to a time block.
§Errors
comnum_core::Error::Shape if the prefix is longer than the block.
Sourcepub fn windowed(&self, samples: &[C64], ramp: usize) -> Result<Vec<C64>>
pub fn windowed(&self, samples: &[C64], ramp: usize) -> Result<Vec<C64>>
The raised-cosine window of whole blocks of Ofdm::block_len samples (prefix
included): the first ramp samples of every prefix rise as
$$ w[n] = \frac{1}{2}\left(1 - \cos\frac{\pi (n + 1/2)}{R}\right), \qquad n = 0 \dots R - 1, $$
a cyclic postfix of $R$ samples of the block falls as $1 - w$ and overlaps the
ramp of the next block (the postfix of the last block wraps onto the first: the
stream stays periodic), so the output has the length of the input and the FFT
part of every block is untouched. The pulse of a block then lasts
$L(N + N_{\mathrm{cp}}) + R$ samples with $(1 - \cos)$ edges: the raised-cosine
impulse shape of windowed OFDM (Saul, Proc. IEEE VTC2004-Fall, 2004, eq. (1):
a guard interval and a roll-off of 11.1 %), whose out-of-band sidelobes fall as
$f^{-3}$ instead of the $f^{-1}$ of the rectangular pulse. ramp = 0 returns the
samples unchanged.
§Errors
comnum_core::Error::Config if ramp exceeds the prefix $L N_{\mathrm{cp}}$,
comnum_core::Error::Shape for a partial block.
§Examples
use comnum_waveform::ofdm::Ofdm;
use comnum_math::C64;
let ofdm = Ofdm { n_cp: 4, oversampling: 1, ..Ofdm::new(16, 16).unwrap() };
let data: Vec<C64> = (0..32).map(|k| C64::new(if k % 3 == 0 { 1.0 } else { -1.0 }, 0.0)).collect();
let x = ofdm.modulate(&data).unwrap();
let y = ofdm.windowed(&x, 4).unwrap();
assert_eq!(y.len(), x.len());
// the FFT part of every block is untouched
assert!(y[4..20].iter().zip(&x[4..20]).all(|(a, b)| (a - b).norm() < 1e-12));Sourcepub fn modulate(&self, data: &[C64]) -> Result<Vec<C64>>
pub fn modulate(&self, data: &[C64]) -> Result<Vec<C64>>
Modulate data symbols (a multiple of $K$): $L (N + N_{\mathrm{cp}})$ samples per block.
§Errors
comnum_core::Error::Shape if the number of symbols is not a multiple of $K$, and the
errors of Ofdm::check.
Sourcepub fn demodulate(&self, samples: &[C64]) -> Result<Vec<C64>>
pub fn demodulate(&self, samples: &[C64]) -> Result<Vec<C64>>
Demodulate whole blocks into data symbols.
§Errors
comnum_core::Error::Shape if the number of samples is not a multiple of the block length.
Sourcepub fn papr_db_per_block(&self, samples: &[C64]) -> Vec<f64>
pub fn papr_db_per_block(&self, samples: &[C64]) -> Vec<f64>
The PAPR (dB) of every whole block of samples, the cyclic prefix excluded
(comnum_math::papr_db of the useful part).
Sourcepub fn modulate_with(
&self,
data: &[C64],
reduction: &dyn PaprReduction,
) -> Result<(Vec<C64>, Vec<usize>)>
pub fn modulate_with( &self, data: &[C64], reduction: &dyn PaprReduction, ) -> Result<(Vec<C64>, Vec<usize>)>
Modulate with a PAPR reduction technique: the samples and the side information of every block (the selected candidate of SLM or PTS, 0 otherwise).
§Errors
As Ofdm::modulate, with the number of data symbols per block of the technique,
and the errors of the technique.
Sourcepub fn demodulate_with(
&self,
samples: &[C64],
reduction: &dyn PaprReduction,
side: &[usize],
) -> Result<Vec<C64>>
pub fn demodulate_with( &self, samples: &[C64], reduction: &dyn PaprReduction, side: &[usize], ) -> Result<Vec<C64>>
Demodulate blocks transmitted with a PAPR reduction technique and its side information.
§Errors
comnum_core::Error::Shape for a partial block or a side information of another length.
Trait Implementations§
Source§impl Demodulate for Ofdm
OFDM as a Demodulate block: one stream of samples at Ofdm::sample_rate.
impl Demodulate for Ofdm
OFDM as a Demodulate block: one stream of samples at Ofdm::sample_rate.
Source§fn demodulate_into(&mut self, y: &Signal, out: &mut Symbols) -> Result<()>
fn demodulate_into(&mut self, y: &Signal, out: &mut Symbols) -> Result<()>
§Errors
comnum_core::Error::Config for several streams or a signal at another sample rate,
and the errors of Ofdm::demodulate.
Source§impl Modulate for Ofdm
OFDM as a Modulate block: one stream of data symbols into one stream of samples
at Ofdm::sample_rate.
impl Modulate for Ofdm
OFDM as a Modulate block: one stream of data symbols into one stream of samples
at Ofdm::sample_rate.