comnum_spec/blocks/wireless/mod.rs
1//! Wireless blocks: several antennas, fading channels, OFDM and MIMO detection.
2//!
3//! | Block | Does |
4//! |---|---|
5//! | `mimo_tx` | spreads the symbols over $n_{t}$ antennas: spatial multiplexing (one layer per antenna, power $1/n_{t}$ each) or Alamouti's code |
6//! | `rayleigh` | flat Rayleigh or Rician fading, $n_{r} \times n_{t}$, constant over the trial or over coherence blocks, with exponential antenna correlation |
7//! | `tdl` | a tapped delay line (EPA, EVA, ETU, ITU Pedestrian A and Vehicular A, exponential) with Doppler |
8//! | `cdl` | a clustered delay line of 3GPP TR 38.901 (CDL-A to CDL-E) between uniform linear arrays, with the Doppler of a moving receiver |
9//! | `ofdm_tx` | maps every antenna's symbols on a resource grid with pilots and modulates it |
10//! | `ofdm_rx` | demodulates, estimates the channel (perfect, LS or LMMSE) and detects every resource element |
11//! | `mimo_rx` | detects a single-carrier link over flat fading with the known channel |
12//!
13//! # Scales
14//!
15//! The OFDM modulator gives the samples the power $K/(L N)$ ($K$ active subcarriers,
16//! IFFT of size $L N$), so that a resource element of unit energy spreads over
17//! $L N / K$ samples: `ofdm_tx` sets the samples per symbol to $L N / K$ and the symbol
18//! rate to the rate of the resource elements $K \Delta f$. The noise blocks then set the
19//! SNR per resource element: `awgn` with `snr_db` gives $E_{s}/N_{0}$ on every data
20//! resource element of unit energy, and the noise of every demodulated resource
21//! element has the variance of the noise per sample. Spatial multiplexing divides the
22//! power among the antennas, so that the SNR is the total transmitted energy per
23//! resource element over the noise of one receive antenna.
24//!
25//! # Example
26//!
27//! ```yaml
28//! link:
29//! - {type: source, constellation: 16-QAM, n_symbols: 4800}
30//! - {type: mimo_tx, n_tx: 2}
31//! - {type: ofdm_tx, n_fft: 256, n_subcarriers: 200, n_cp: 18, n_symbols: 14}
32//! - {type: tdl, profile: EPA, doppler_hz: 5, n_rx: 2}
33//! - {type: awgn, snr_db: $snr_db}
34//! - {type: ofdm_rx, estimation: lmmse, detector: mmse}
35//! ```
36//!
37//! # References
38//!
39//! 1. S. M. Alamouti, "A simple transmit diversity technique for wireless
40//! communications," *IEEE J. Sel. Areas Commun.*, 16(8), 1451–1458, 1998.
41//! 2. O. Edfors, M. Sandell, J.-J. van de Beek, S. K. Wilson and P. O. Börjesson, "OFDM
42//! channel estimation by singular value decomposition," *IEEE Trans. Commun.*,
43//! 46(7), 931–939, 1998.
44//! 3. 3GPP TS 36.101, *E-UTRA; User Equipment radio transmission and reception*,
45//! Annex B.2 (EPA, EVA, ETU).
46
47use super::Extension;
48use comnum_channel::multipath::Taps;
49use comnum_math::linalg::CMat;
50
51mod fading;
52mod mimo;
53mod ofdm;
54
55use fading::{CdlBlock, CdlSpec, Rayleigh, RayleighSpec, TdlBlock, TdlSpec};
56use mimo::{Detection, DetectorSpec, MimoRx, MimoTx, MimoTxSpec};
57use ofdm::{OfdmRx, OfdmRxSpec, OfdmTx, OfdmTxSpec};
58
59/// The channel of a trial, as a genie-aided receiver knows it.
60#[derive(Clone, Debug)]
61pub enum Csi {
62 /// Flat fading: one matrix $n_{r} \times n_{t}$ per block of `coherence` samples.
63 Flat {
64 /// The matrices, block after block.
65 h: Vec<CMat>,
66 /// Samples per block.
67 coherence: usize,
68 },
69 /// The taps of a tapped delay line.
70 Taps(Taps),
71}
72
73impl Csi {
74 /// The flat channel at sample `n`.
75 fn flat(&self, n: usize) -> Option<&CMat> {
76 match self {
77 Csi::Flat { h, coherence } => h.get(n / (*coherence).max(1)).or_else(|| h.last()),
78 Csi::Taps(_) => None,
79 }
80 }
81}
82
83pub use comnum_waveform::ofdm::link::OfdmFrame;
84
85/// The blocks of this module: their documentation and their builders.
86pub(super) fn blocks() -> Vec<Extension> {
87 vec![
88 builtin!(
89 "mimo_tx",
90 "Spread the symbols over n_tx antennas: spatial multiplexing (power 1/n_tx per antenna) or Alamouti's code.",
91 MimoTxSpec,
92 needs [Samples],
93 gives [],
94 |q, _, _| Ok(Box::new(MimoTx::new(&q)?)),
95 ),
96 builtin!(
97 "rayleigh",
98 "Flat fading y = H x on every antenna; records the channel for a genie-aided receiver.",
99 RayleighSpec,
100 needs[Samples],
101 gives[Csi],
102 |q, _, _| Ok(Box::new(Rayleigh { p: q })),
103 ),
104 builtin!(
105 "tdl",
106 "Tapped-delay-line multipath fading with Clarke/Jakes Doppler; records the taps for a genie-aided receiver.",
107 TdlSpec,
108 needs[Samples],
109 gives[Csi],
110 |q, _, _| Ok(Box::new(TdlBlock::new(&q)?)),
111 ),
112 builtin!(
113 "cdl",
114 "Clustered delay line of 3GPP TR 38.901 between uniform linear arrays (one tap per cluster, random ray phases and coupling); records the taps for a genie-aided receiver.",
115 CdlSpec,
116 needs[Samples],
117 gives[Csi],
118 |q, _, _| Ok(Box::new(CdlBlock::new(&q)?)),
119 ),
120 builtin!(
121 "ofdm_tx",
122 "Map every antenna's symbols on resource grids with pilots and OFDM-modulate them (power K/(LN) per sample).",
123 OfdmTxSpec,
124 needs[Samples],
125 gives[Ofdm],
126 |q, _, _| Ok(Box::new(OfdmTx::new(&q)?)),
127 ),
128 builtin!(
129 "ofdm_rx",
130 "Demodulate the OFDM grids, estimate the channel and detect every data resource element; output the symbols and their noise variances.",
131 OfdmRxSpec,
132 needs [Samples, Constellation, Ofdm],
133 gives [Noise, Llr],
134 |q, _, _| Ok(Box::new(OfdmRx::new(&q)?)),
135 ),
136 builtin!(
137 "mimo_rx",
138 "Detect a single-carrier link over flat fading with the known channel; output the symbols and their noise variances.",
139 DetectorSpec,
140 needs [Samples, Constellation, Csi],
141 gives [Noise, Llr],
142 |q, _, _| Ok(Box::new(MimoRx(Detection::new(&q)?))),
143 ),
144 ]
145}
146
147#[cfg(test)]
148mod tests;