Waveforms beyond OFDM#
CP-OFDM turns a frequency-selective channel into flat subcarriers at the price of a
prefix, of sidelobes that fall slowly, and of interference between subcarriers when
the channel changes within a symbol. comnum implements the waveforms proposed to
relax each of these limits, with the same conventions as Ofdm:
modulate takes the symbols of whole blocks and returns the samples, demodulate
inverts it, and the round trip is exact without a channel. The gallery page
Filtered multicarrier and OTFS compares their
spectra.
FBMC/OQAM#
Fbmc shapes every subcarrier with the PHYDYAS prototype of overlapping
factor 2, 3 or 4 and drops the prefix. Orthogonality holds in the real sense only, so
each subcarrier carries a real symbol every half symbol: oqam_stagger()
splits complex symbols into them and oqam_destagger() takes the real part
back.
import comnum, numpy as np
fbmc = comnum.Fbmc(64, overlap=4)
c = comnum.Constellation("qam", 16).normalized().map_bits(comnum.bits(4 * 64 * 20, comnum.Rng(1)))
x = fbmc.modulate(comnum.oqam_stagger(c, 64))
c_hat = comnum.oqam_destagger(fbmc.demodulate(x).real, 64)
The prototype spans \(K\) symbols, so a burst is \(K - 1/2\) symbols longer
than its data, and PHYDYAS is orthogonal only nearly: the round trip leaves a residual of
about \(10^{-3}\), far below any noise of interest. In a doubly-selective channel
the residual imaginary interference adds to the noise; validation/tests/multicarrier/nissel2017.rs
compares FBMC with OFDM and CP-OFDM in the Vehicular A channel of Nissel & Rupp (2017).
UFMC#
Ufmc groups the active subcarriers in sub-bands and filters each one
with a Dolph–Chebyshev filter of length \(L\) (chebyshev_window()), as
Schaich & Wild (2014) propose: the filter’s ramps replace the prefix, a symbol is
\(N + L - 1\) samples, and the receiver takes a DFT of \(2N\) points and keeps
the even bins. The filter attenuates the subcarriers at the edges of each sub-band, which
the one-tap equaliser undoes.
OTFS#
Otfs places \(MN\) symbols on a grid of \(M\) delays and
\(N\) Doppler shifts, maps them to time and frequency by the inverse symplectic
Fourier transform and transmits them as OFDM symbols with one prefix per frame. A
channel of paths of whole delays and Doppler bins is a 2-D circular convolution on that
grid: effective_channel() builds it (Raviteja et al. 2019, Theorem 1),
and delay_doppler_paths() draws paths from a power-delay profile with
Jakes’ Doppler.
otfs = comnum.Otfs(32, 16, n_cp=8)
fs = 32 * 15e3
paths = comnum.delay_doppler_paths("eva", 500.0, fs, comnum.Rng(2))
# paths: (gain, delay in samples, Doppler in Hz); with whole bins
# (Doppler multiple of fs / (M N)), H @ x is the demodulated frame
H = otfs.effective_channel([(1.0, 0, 0.0), (0.5, 3, fs / 512)], fs)
Every path then reaches every symbol: a detector on the whole frame (linear MMSE on
H, or message passing) collects the full diversity of the channel, where one-tap
OFDM loses it (validation/tests/multicarrier/raviteja2019.rs).
Chirp spread spectrum#
Css is the modulation of LoRa: \(2^{SF}\) cyclic shifts of an
up-chirp, detected by dechirping and an FFT. theory_css_ser() and
theory_css_ber() give the error rates over AWGN, the css_* functions the
spectrum and the interference between two signals; the gallery page
The LoRa modulation: error rates, spectrum and interference compares them with three papers.