comnum.CeOfdm#
- class comnum.CeOfdm(n_subcarriers, h, *, oversampling=4, n_cp=0)#
A constant-envelope OFDM (CE-OFDM) modulator and phase demodulator (Thompson et al. 2008).
After Thompson, Ahmed, Proakis, Zeidler & Geile, “Constant envelope OFDM,” IEEE Trans. Commun. 56(8), 2008.
A block carries
Kdata symbolsd(unit mean energy) on the subcarriers1..Kof a DFT of sizeN = 2J(K+1),Jthe oversampling factor; the real OFDM signalx = (F d + F* d*)/√(2K)has a unit variance and the samples ares_n = exp(j2πh x_n), so that the phase has the standard deviation2πh,hbeing the modulation index (Sec. II). An optional cyclic prefix ofN_cpsamples is prepended. The receiver (Sec. III, Fig. 1) takes the phase of the samples, unwrapped along the stream or not, removes the prefix and projects it on the data bins:d̂ = G ψ/(2πh).SNR convention.
E_s/N_0is per data symbol: a block of energyN + N_cpcarriesKsymbols, so the noise variance per sample isσ² = (N + N_cp)/(K E_s/N_0)(noise_variance();sps = (N + N_cp)/Ksamples per data symbol). Above the threshold of the phase demodulator (a carrier-to-noise ratio near 10 dB, Sec. III-B), every data subcarrier sees the SNR(2πh)² E_s/N_0 N/(N + N_cp)(snr()), and the error rates are those of the constellation over AWGN at that SNR (ser_esn0(),ber_esn0()). ForM-PAM on every real subcarrier this is eq. (15) of the paper,BER = 2(M-1)/(M log₂M) Q(2πh √(6 log₂M E_b/N_0 / (M²-1))), the nearest-neighbour term of the Gray BER;ber_esn0()uses the exact Gray BER of the square QAM of orderM²whose real and imaginary parts are the two PAM symbols (within 1 % of eq. (15) once the BER is under 1e-2).- Parameters:
- Raises:
ValueError – for an invalid parameter (the message names it).
Examples
>>> import comnum, numpy as np >>> ce = comnum.CeOfdm(16, h=0.1, oversampling=2) >>> c = comnum.Constellation("qam", 16).normalized() >>> _, d = comnum.symbols(c, 64, comnum.Rng(1)) >>> s = ce.modulate(d) >>> s.size == 4 * ce.n_fft and np.allclose(np.abs(s), 1.0) True >>> np.allclose(ce.demodulate(s), d) True
- ber_esn0(m, esn0_db, kind='qam')#
The BER of the linear regime, Gray mapping: the exact Gray BER of a square QAM (eq. (15) of Thompson et al. with its further neighbours), else
theory_ber().- Parameters:
- Returns:
the BER.
- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
- ber_receiver(m, esn0_db, kind='qam', *, receiver='arctangent')#
The BER of a Gray-mapped constellation with the receiver, averaged over the subcarriers of
subcarrier_snr().- Parameters:
- Returns:
the BER.
- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
- cycle_slip_response(start)#
The change of the estimates of the arctangent receiver caused by a cycle slip of
+2πfrom samplestart(after the prefix) to the end of the block (Ahmed et al. 2012, eqs. (11)–(14)).- Parameters:
start (int) – first sample of the slip,
0 ≤ start < N.- Returns:
Kcomplex changes.- Return type:
- Raises:
ValueError – for an invalid parameter (the message names it).
- demodulate(samples, *, unwrap='none', receiver='arctangent')#
The symbol estimates of every block.
- Parameters:
samples (array_like) – a multiple of
N + N_cpreceived samples.unwrap (str) – for the arctangent receiver,
"none"(the principal phase, wraps are errors) or"stream"(the phase unwrapped along the stream, the phase unwrapper of the paper).receiver (str) –
"arctangent"(d̂ = G ψ/(2πh), Thompson et al. 2008),"linear"(Im r) or"enhanced"(Im r (2 - Re r)), the low-complexity receivers of Ahmed and Zeidler (2015), divided by their Bussgang gain.
- Returns:
Kcomplex estimates per block.- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
- gamp(samples, noise_var, constellation, *, iterations=50, damping=0.5, points=64)#
The posterior means of the symbols of every block by the GAMP receiver of López Morales, Dinis and García Armada (2022), near the optimum where the phase leaves
(-π, π].- Parameters:
samples (array_like) – a multiple of
N + N_cpreceived samples.noise_var (float) –
σ²per sample (noise_variance()).constellation (Constellation) – the symbols as transmitted (square QAM, PAM or BPSK).
iterations (int) – iterations per block.
damping (float) – damping factor in
(0, 1].points (int) – points of the quadrature of the output step.
- Returns:
Kcomplex estimates per block.- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
- modulate(symbols)#
The transmitted samples
exp(j2πh x)with the cyclic prefix of every block.- Parameters:
symbols (array_like) – a multiple of
Kdata symbols.- Returns:
N + N_cpunit-envelope samples per block.- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
- noise_variance(esn0_db)#
The noise variance per sample for an
E_s/N_0per data symbol and a unit envelope,σ² = (N + N_cp)/(K E_s/N_0).- Parameters:
esn0_db (float | array_like) –
E_s/N_0(dB) per data symbol.- Returns:
σ²(forRng.complex_noise).- Return type:
- Raises:
ValueError – for values that are not real numbers.
- ofdm_signal(symbols)#
The real OFDM signal
x = (F d + F* d*)/√(2K)of every block (no prefix).- Parameters:
symbols (array_like) – a multiple of
Kdata symbols.- Returns:
Nreal samples per block.- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
- psd()#
The expected periodogram
E|S_k|²/Nof a transmitted block under the Gaussian model (Guerreiro et al. 2015): the bins average to 1, bin 0 holds the carrier line.- Returns:
Nvalues, in the order of the DFT.- Return type:
- Raises:
ValueError – for an invalid parameter (the message names it).
- received_phase(samples, *, unwrap='none')#
The phase of the receiver before the DFT, prefix included.
- Parameters:
samples (array_like) – received samples.
unwrap (str) –
"none"or"stream", asdemodulate().
- Returns:
one phase (rad) per sample.
- Return type:
- Raises:
ValueError – for an input that is not an array of numbers of the expected shape.
- ser_esn0(m, esn0_db, kind='qam')#
The SER of the linear regime: that of a constellation of
mpoints over AWGN atsnr()(theory_ser()).- Parameters:
- Returns:
the SER.
- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
- snr(esn0_db)#
The SNR of every data subcarrier in the linear regime (linear scale),
(2πh)² E_s/N_0 N/(N + N_cp).- Parameters:
esn0_db (float | array_like) –
E_s/N_0(dB) per data symbol.- Returns:
the SNR (linear).
- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
- subcarrier_snr(esn0_db, *, receiver='arctangent')#
The SNR of every data subcarrier with the receiver: flat for the arctangent receiver above its threshold, Bussgang’s analysis for the linear receivers.
- Parameters:
- Returns:
KSNRs (linear).- Return type:
- Raises:
ValueError – for an invalid parameter (the message names it).