comnum.Dpsk#
- class comnum.Dpsk(m)#
Differential M-PSK (DBPSK, DQPSK, D8PSK, …) with Gray-labelled phase transitions.
The information is carried by the phase transitions: with
a_kthe differential phase index of symbolkandc_{-1} = 0the reference,c_k = (a_k + c_{k-1}) mod Mandx_k = exp(j 2 pi c_k / M), soninformation symbols are sent asn + 1unit-energy PSK symbols. The bits of a symbol are the Gray label of its transition, so the nearest wrong transitions differ by one bit. The noncoherent detector decides the transition nearest toarg(r_k conj(r_{k-1})), which a constant phase rotation of the received symbols leaves unchanged (Proakis & Salehi, Digital Communications, 5th ed., 2008, Sec. 4.5); its bit error rate over AWGN istheory_ber_dpsk(m, ebn0_db). Coherent decisions on the absolute phase followed by differential decoding spoil two differences per symbol error, hence2p(1 - p)for DBPSK (theory_ber_dpsk(2, ebn0_db, detection="coherent"), Sec. 3.2-2).The methods work at two levels: bits (
modulate,demodulate,demodulate_coherent, andindices/bitsbetween bits and differential indices) and phase indices (encodeanddecodebetween differential and absolute indices,detectanddetect_coherentfrom received symbols to indices).- Parameters:
m (int) – the order, a power of two (2 for DBPSK, 4 for DQPSK).
- Raises:
ValueError – for an invalid parameter (the message names it).
Examples
>>> import comnum, numpy as np >>> dqpsk = comnum.Dpsk(4) >>> bits = np.array([0, 1, 1, 1, 0, 0], dtype=np.uint8) >>> x = dqpsk.map_bits(bits) >>> x.shape (4,) >>> dqpsk.demap_bits(x * np.exp(1j * 1.234)).tolist() [0, 1, 1, 1, 0, 0]
- bits(indices)#
The bits of a sequence of differential phase indices (the inverse of
indices).- Parameters:
indices (array_like) – differential indices, below
M.- Returns:
log2 Mbits per index (uint8).- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
Examples
>>> import comnum >>> comnum.Dpsk(4).bits([0, 1, 2, 3]).tolist() [0, 0, 0, 1, 1, 1, 1, 0]
- decode(coded)#
Differential decoding: the
ndifferencesa_k = (c_k - c_{k-1}) mod Mofn + 1absolute phase indices (the inverse ofencode).- Parameters:
coded (array_like) – the
n + 1absolute phase indices, belowM.- Returns:
the
ndifferential phase indices (int64).- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
Examples
>>> import comnum >>> comnum.Dpsk(4).decode([0, 0, 1, 0, 2, 3]).tolist() [0, 1, 3, 2, 1]
- demap_bits(r)#
Noncoherent demodulation: the transition nearest to
arg(r_k conj(r_{k-1}))(no carrier phase needed), as bits.- Parameters:
r (array_like) – the
n + 1received symbols.- Returns:
the
n log2 Mbits (uint8).- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
Examples
>>> import comnum, numpy as np >>> d = comnum.Dpsk(2) >>> d.demap_bits(d.map_bits([1, 0, 1]) * 1j).tolist() [1, 0, 1]
- demodulate_coherent(r)#
Coherent demodulation with differential decoding: the phase index nearest to every symbol, then the differences, as bits.
- Parameters:
r (array_like) – the
n + 1received symbols (carrier phase recovered).- Returns:
the
n log2 Mbits (uint8).- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
Examples
>>> import comnum >>> d = comnum.Dpsk(4) >>> d.demodulate_coherent(d.map_bits([1, 1, 0, 1])).tolist() [1, 1, 0, 1]
- detect(r)#
Noncoherent detection: the differential phase index nearest to
arg(r_k conj(r_{k-1}))for every pair of consecutive received symbols, invariant to a constant phase rotation (Proakis & Salehi, 5th ed., Sec. 4.5).- Parameters:
r (array_like) – the
n + 1received symbols.- Returns:
the
ndifferential phase indices (int64).- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
Examples
>>> import comnum, numpy as np >>> r = np.exp(1j * (0.3 + np.array([0.0, np.pi / 2, 0.0]))) >>> comnum.Dpsk(4).detect(r).tolist() [1, 3]
- detect_coherent(r)#
Coherent decisions: the absolute phase index nearest to every received symbol (the hard decision of M-PSK);
decodethen removes the differential encoding.- Parameters:
r (array_like) – the received symbols.
- Returns:
one absolute phase index per symbol (int64).
- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
Examples
>>> import comnum, numpy as np >>> comnum.Dpsk(4).detect_coherent(np.exp(1j * np.pi / 2 * np.array([0, 1, 1, 2]))).tolist() [0, 1, 1, 2]
- encode(indices)#
Differential encoding of phase indices: the
n + 1absolute indicesc_{-1} = 0, c_0, …, c_{n-1}withc_k = (a_k + c_{k-1}) mod M.- Parameters:
indices (array_like) – the
ndifferential phase indices, belowM.- Returns:
the
n + 1absolute phase indices (int64).- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
Examples
>>> import comnum >>> comnum.Dpsk(4).encode([0, 1, 3, 2, 1]).tolist() [0, 0, 1, 0, 2, 3]
- indices(bits)#
The differential phase indices of a bit stream (
log2 Mbits per symbol, MSB first, Gray-labelled transitions).- Parameters:
bits (array_like) – the bits, a multiple of
log2 M.- Returns:
one differential index per symbol (int64).
- Return type:
- Raises:
ValueError – if the length is not a multiple of
log2 M.
Examples
>>> import comnum >>> comnum.Dpsk(4).indices([0, 0, 0, 1, 1, 1, 1, 0]).tolist() [0, 1, 2, 3]
- map_bits(bits)#
The unit-energy PSK symbols carrying a bit stream (the reference symbol first).
- Parameters:
bits (array_like) –
nbits, a multiple oflog2 M.- Returns:
the
n / log2 M + 1symbols (complex128).- Return type:
- Raises:
ValueError – for an invalid parameter or input (the message names it).
Examples
>>> import comnum >>> comnum.Dpsk(2).map_bits([1, 0]).real.round(12).tolist() [1.0, -1.0, -1.0]