Asking the fleet what it is doing…
monad-knowledge Wi-Fi sensing lab · FIIT STU

From OFDM to CSI: how sampling the channel frequency response on subcarriers turns H into the matrix the NIC hands you

Where We Are

Last week we learned that radio does not travel in one straight line. It bounces off walls, floor, and furniture and arrives by many paths at once. That mixing leaves a pattern across frequencies — the channel's fingerprint. We also saw that a person entering a room changes that fingerprint, because a human body (mostly water) blocks and re-routes the reflections. The question we left open was the obvious next one: how does a Wi-Fi card actually read that fingerprint?

Written tidily, Week 1's fingerprint was the sum over all the bouncing paths:

H(f) = \sum_{l=1}^{L} \alpha_l \, e^{-j2\pi f \tau_l}

Here each path l arrives with a strength α (how much energy it carries) and a delay τ (how long it took), and the big Σ just means "add up all L paths." The Rician K-factor, the path-loss-per-wall numbers from the lab's blockage measurements, and the coherence-bandwidth idea all came out of this single expression. This week we answer the read-out question: how a card samples this fingerprint, why it hands you a table of numbers instead of a clean waveform, what its own hardware does to that table, and how those numbers turn into a real occupancy measurement.

A few terms recur throughout, so it is worth fixing them in plain language up front. A subcarrier is one of many narrow tones a Wi-Fi card transmits side by side. OFDM is the trick of splitting one wide channel into those many narrow tones. The CFR (Channel Frequency Response) is the fingerprint seen across frequency; the CIR (Channel Impulse Response) is the same channel seen as time-spaced echoes. CSI (Channel State Information) is the table of fingerprint values the card reports. The NIC is the Wi-Fi chip itself. Bandwidth is how wide a slice of radio you use. And MIMO means several antennas at each end, giving several fingerprints per packet. Each of these is defined again, in context, the first time it does real work below.

0. Why CSI and Not RSSI?

One question deserves an answer before we go to the trouble of reading a whole row of tones: every Wi-Fi chip already reports a far simpler number — RSSI, the received signal strength — so why not just use that? The answer, drawn from the Tsinghua "Understanding CSI" tutorial, is the whole reason this course works in CSI.

RSSI is the total received power, the single scalar you get by squaring the coherent sum of every multipath component with its phase already baked in:

\text{RSSI} = 10\log_{10}\lVert V\rVert^2, \qquad V = \sum_{n} \lVert V_n\rVert\, e^{-j\phi_n}.

Crushing the channel down to one number costs two things. First, it is not injective: two completely different channels with the same total power give the same RSSI, so it cannot distinguish room states that CSI tells apart at a glance. Second, it fluctuates even on a static link — tiny, sub-wavelength changes (a door down the corridor, thermal drift) re-phase the paths, so the coherent sum V swings by several decibels while nothing of interest has moved. CSI instead keeps the full per-subcarrier complex vector H[k] = \lVert H[k]\rVert\,e^{j\angle H[k]}, so the geometry written into the ripple — Week 1's ray-tracing fingerprint — survives intact. That richness is exactly what the rest of this week sets out to capture.

Workbook §2.0 makes both failures visible: it plots two different channels normalised to the same power (same RSSI, plainly different CSI) and a static-link RSSI trace that wanders several dB from path re-phasing alone.

Why CSI, not RSSI. Left: two genuinely different channels (A, B) scaled to identical total power — their RSSI is the same dashed line, yet their per-subcarrier CSI shapes differ completely. Right: RSSI on a "static" link still swings several dB over time as sub-wavelength drift re-phases the paths. One scalar throws the channel's structure away. Reproduce in Workbook §2.0.

1. OFDM: Reading the Fingerprint at a Row of Tones

Start with an analogy. You cannot hear every pitch a guitar string can make all at once, so you check it at a few fixed frets — evenly-spaced steps up the neck. OFDM does the same thing to a wide radio channel: instead of measuring the fingerprint everywhere, it measures it at a row of evenly-spaced frequencies.

The reason for splitting the channel up is practical. A wide channel is frequency-selective — different frequencies of the same transmitted symbol come out with different strength and delay. Correcting for that across a wiggly curve is hard. OFDM sidesteps the problem by dividing the total bandwidth B into N narrow tones, called subcarriers, each of width Δf = B/N. If each tone is much narrower than the range over which the channel changes, the channel looks essentially flat across that one tone — so the receiver only has to apply one simple correction per tone, rather than untangle a curve.

The cyclic prefix is a short copy of the end of each OFDM symbol pasted onto its front. It absorbs the lingering echoes from the previous symbol so they do not smear into the next one, which is what lets the receiver process each symbol cleanly with an FFT.

In the IEEE 802.11n 20 MHz channel the card uses N = 64 tones, so the spacing between neighbouring tones is

\Delta f = \frac{20 \text{ MHz}}{64} = 312.5 \text{ kHz}.

Of those 64 tones, 56 carry energy; four of them are pilot tones — reference tones with known values that the receiver uses to track small timing and frequency errors — and the rest are data. Tone index 0, the centre tone, is switched off in every 802.11 standard (Section 4 explains why), and the remaining eight tones are guard space at the edges of the band. Widening to 40 MHz simply doubles the tone count to 128 (114 of them active); the spacing stays 312.5 kHz. The key point: bandwidth grows by packing in more tones, not by spreading them apart.

You will see this grid in Workbook §2.1, which samples a continuous H(f) onto the OFDM tone grid and marks the switched-off centre tone and the 30 tones an Intel 5300 keeps.

Sampling the continuous CFR H(f) onto the OFDM subcarrier grid: the grey curve is the channel the world produces, the red dots are the 30 subcarriers the Intel 5300 keeps, and the dotted line is the nulled DC subcarrier. Reproduce in Workbook §2.1.

2. From the Continuous Fingerprint to One Number per Tone

Reading the fingerprint at a tone is just substitution — no approximation is involved. The k-th tone sits at frequency

f_k = f_c + k \cdot \Delta f, \quad k = 0, 1, \ldots, N-1,

where f_c is the channel's centre frequency and k counts the tones. Putting f = f_k into Week 1's fingerprint gives

H(k) = H(f_c + k\,\Delta f) = \sum_{l=1}^{L} \alpha_l \, e^{-j2\pi (f_c + k\,\Delta f)\, \tau_l}.

The part that depends only on the centre frequency, e^{−j2πf_c τ_l}, is a fixed rotation for each path — it does not change from tone to tone — so we fold it into each path's strength α_l. What is left is the clean per-tone form:

H(k) = \sum_{l=1}^{L} \alpha_l \, e^{-j2\pi k \Delta f \tau_l}.

This is exactly Week 1's multipath sum, now read at N discrete frequencies. Each H(k) is a single complex number: a size (how much the channel weakens that tone) and an angle (how much it delays it). The exponent −j2π·k·Δf·τ_l is the part that writes time-of-flight into the frequency pattern — each path becomes a ripple across the tones whose wiggle rate is set by its delay. CSI is precisely this row of complex numbers, nothing more. Every sensing method in this course ultimately manipulates this object.

MIMO means several antennas at each end. With N_t transmit and N_r receive antennas, the channel at time t is a small stack of fingerprints:

\mathbf{H}(t) \in \mathbb{C}^{N_r \times N_t \times N_{\text{sub}}},

with one complex number for every antenna-pair-and-tone combination. Each packet adds one time-slice to that stack, and a trace is just these slices in time order. Sensing is the task of reading physical-world state from how the stack changes.

Workbook §2.2 builds a synthetic H(k) from a four-path model. Delay one path by just 1 ns and the whole ripple pattern across the 30 reported tones shifts — a first demonstration that the geometry of the room is written into the pattern of tone sizes, not into any single tone.

A four-path H(k) and the same channel with the wall reflection delayed by +1 ns. The ripple pattern shifts across all 30 reported subcarriers, showing that sub-nanosecond geometry is written into the pattern of |H(k)|, not into any single bin. Reproduce in Workbook §2.2.

3. Two Views of One Channel: CFR, CIR, and the IFFT

Here is the analogy that makes the next step intuitive. A prism splits white light into a rainbow of colours. Run the prism backwards — feed the rainbow back in — and you collapse it into a single beam. The IFFT does exactly that to our tones: it takes the fingerprint spread across frequency and turns it back into a few sharp echoes spread across time.

The IFFT (Inverse Fast Fourier Transform; the fast way to compute the IDFT, Inverse Discrete Fourier Transform) is the mathematical operation that converts frequency-domain values back into time-domain echoes.

So the row of tones, H(k), is the CFR — the channel seen across frequency. Run it through the IFFT and you recover the CIR, h[n] — the same channel seen across time, as one spike (a "tap") per echo:

h[n] = \text{IDFT}\{H(k)\} = \frac{1}{N} \sum_{k=0}^{N-1} H(k) \, e^{j 2\pi k n / N}, \quad n = 0, \ldots, N-1.

The CFR and CIR carry identical information; they are just two arrangements of it. Tap n sits at a delay τ_n = n/(NΔf) = n/B. Two echoes can only be told apart if their delays differ by more than one tap — this is the delay resolution:

\Delta\tau_{\min} = \frac{1}{B}.

To see why bandwidth matters, picture a ruler. A ruler with only centimetre marks cannot separate two scratches a millimetre apart — they look like one. More marks (wider bandwidth) let you separate things that sit very close together. Turning the time gap into a distance, the shortest path-length difference you can resolve is

\Delta d = c \cdot \Delta\tau_{\min} = \frac{c}{B}.

At 20 MHz this is 50 ns, or about 15 m of path-length difference. At 40 MHz it halves to 7.5 m; at 80 MHz to 3.75 m. In a typical 10 m × 8 m classroom, many echoes arrive within 15 m of each other, so a 20 MHz card blurs them into a single broad tap. The CIR from a 20 MHz trace is therefore a coarse picture of the room's geometry — useful for bulk fading statistics, but not for pinning down range to the metre.

The averaging penalty. Some cards make this worse. The Intel 5300 reports only 30 averaged tones rather than the full 56. Feeding 30 tones to the IFFT is like using a narrower ruler: it treats the missing tones as zero, which spreads each echo into side-lobes and merges close ones. The effective bandwidth drops to roughly 30 × 312.5 kHz ≈ 9.4 MHz, so the time resolution is coarser still than the 15 m figure above.

Workbook §2.3 makes this quantitative: it runs the IFFT on (a) the full 56-tone fingerprint and (b) the 30-tone averaged version, and overlays the recovered echoes. The averaging-induced side-lobes are plainly visible in the grouped trace.

CFR-to-CIR by IFFT for a four-path channel. The full 56-bin CFR (left) places sharp taps near each true path delay (green lines); the 30-bin Intel-5300 version (right) spreads energy into side-lobes and merges closely-spaced echoes — the coarse, aliased time resolution discussed in the text. Reproduce in Workbook §2.3.

4. What the Card Actually Reports: The Estimated CSI Table

4.1 Measuring Each Number

Think of each number the card reports as a compass reading with a length: a size (how strong the channel is on that tone) and an angle (how much it delays it). Together they are one complex number written in "size-and-angle" form, a·e^{jθ}, where a is the amplitude and θ is the phase.

Neither end knows the channel in advance, so the card measures it from each packet.

The LTF (Long Training Field) is a known pattern at the start of every packet. Both ends agree on it ahead of time, so the receiver can compare what it expected against what arrived.

On tone k the receiver sends a known value X_k in the LTF and observes

Y_k = H(k) \cdot X_k + N_k,

where N_k is a little noise. Dividing out the known part recovers the channel on that tone:

\hat{H}(k) = \frac{Y_k}{X_k}.

Received divided by known-sent equals the channel's effect on that tone. The card does this during the preamble, before any data is decoded; CSI extraction tools simply log this table before the card discards it. Each reported element is the complex number

\hat{H}_{r,t,k} = a_{r,t,k} \cdot e^{j\theta_{r,t,k}},

where the size a reflects the combined weakening from path loss, multipath, and the card's own front-end, and the angle θ encodes delay — but, as the next section shows, also picks up hardware offsets that mean nothing physical.

A concrete sense of scale: a 3 × 3 antenna setup over 56 active tones is 504 complex numbers per packet, and cards send 100 to 1000 packets per second.

4.2 Why Real Traces Are Never Flat — Even on a Wired Channel

A cheap microphone has its own character: it trims the very lowest and highest notes, has a dead spot, and its volume knob drifts. Even recording perfect silence, the result is not flat. The card's radio front-end does the same to the channel. If you connected transmitter and receiver with a plain cable — no room, no echoes — the fingerprint would still come back bumpy. Four hardware effects are responsible, and none of them is real multipath.

The switched-off centre tone. Like a speaker that hums at one exact pitch, the radio leaks junk right at its centre frequency. (This leakage comes from the local oscillator — the chip's internal reference tone — bleeding into the signal.) Rather than fight the hum, the 802.11 standard simply leaves the centre tone unused. The card reports zero or a placeholder there, and any later algorithm must treat that tone as missing data, never as a genuine weak reading.

Quieter band edges. Like the treble knob on a stereo turned down a touch, the card's band-pass filter trims the very highest and lowest tones in its band. Real filters have soft edges, so tones near the band edges come back quieter than centre tones. This taper is fixed hardware, identical packet to packet, and has nothing to do with the room.

The per-packet volume knob. Before the signal is digitised, the card adjusts its gain to keep the signal within the converter's range. This AGC (Automatic Gain Control) is set per packet and can differ from one packet to the next, so it multiplies all tones by the same scalar at once. The consequence: absolute sizes are not comparable across packets. Features built from ratios between tones within the same packet survive AGC; features that track absolute level across packets do not.

Tone averaging. Like a thumbnail that blurs fine detail, the Intel 5300 firmware averages neighbouring tones to save space, reporting 30 smoothed values instead of 56 (roughly two tones per group at 20 MHz). A sharp notch in the fingerprint, caused by destructive interference, can be partly cancelled inside a group. A per-tone card such as the Atheros or Nexmon does not do this, so algorithms tuned on per-tone data must account for the smoothing when applied to Intel 5300 traces.

The angle (phase) has its own set of offsets — a constant shift across all tones (Carrier Frequency Offset), a slope across tones (Sampling Frequency Offset), and a random per-packet jump (packet-boundary delay) — which push the raw angle far from the true channel phase. Removing them is the subject of Week 3 and Week 4; the workbook here stays on the sizes only.

Workbook §2.4 renders a 3 × 3 MIMO CSI table with these size artefacts baked in — the centre-tone hole, the quieter band edges, and the per-antenna-pair AGC offset are each annotated on the heatmap. Connecting each visible feature to its cause is the cell's core task. An optional, guarded cell shows how to fetch the real clean-control data file if you want to repeat the exercise on measured data.

A 3×3 MIMO CSI tensor |H_{r,t,k}| over 56 active subcarriers, rendered as a heatmap. The dark vertical stripe at k=0 is the DC null; the dimmer band edges are analogue filter roll-off; each antenna-pair row sits at a different overall level from the per-packet AGC offset. None of these is physical multipath. Reproduce in Workbook §2.4.

5. Which Card Sees What

The number of tones a card reports, how finely it rounds each number, and whether it averages tones together all set the ceiling on what every later sensing method can resolve. Three families dominate the literature.

Intel 5300 — Linux 802.11n CSI Tool

Released in 2011, this is the most-cited extraction tool in the field. It reports 30 averaged tone-groups across the 56 active tones of a 20 MHz channel (or 114 in 40 MHz), with each value rounded to 8 bits — that is, 256 possible levels per component. Its maximum bandwidth is 40 MHz; 802.11ac (80 MHz) is not supported. The chipset is no longer manufactured, but its traces make up the bulk of public CSI datasets, so understanding its averaging and coarse rounding matters in practice.

Atheros CSI Tool — ath9k

Built on the open-source ath9k driver for Qualcomm Atheros 802.11n chips, this tool reports CSI per tone, with no averaging: 56 values at 20 MHz, 114 at 40 MHz. Each value is rounded to 10 bits — finer than the Intel tool — and the ungrouped output preserves narrow notches that the Intel averaging would smear. It tops out at 40 MHz.

Nexmon CSI — Broadcom 802.11ac

The Nexmon framework reverse-engineered the Broadcom chipset to expose its CSI tables, and runs on widely-available hardware including the Raspberry Pi 4 and many routers. It supports up to 80 MHz, where 256 tones are available. The spacing is still 312.5 kHz, but the wider 80 MHz band drops the delay-resolution floor to 12.5 ns — about 3.75 m of path-length uncertainty, four times finer than the 20 MHz Intel case. The hardware used for the public 80 MHz dataset encodes each tone as a 4-byte floating-point value (12-bit mantissa), far finer than the Intel 8-bit rounding. The trade-off is that Nexmon traces tend to be noisier, partly from the aggressive firmware patching and partly from the broader noise floor at wider bandwidth.

The table below compares the three along the axes that matter for downstream resolution. ("8-bit / 10-bit / float" is just how finely each card rounds the numbers — more bits means finer steps.)

Tool Standard Max BW Tones (20 MHz) Tones (80 MHz) Number precision Averaging
Intel 5300 802.11n 40 MHz 30 (grouped) 8-bit signed ~2:1 at 20 MHz
Atheros ath9k 802.11n 40 MHz 56 (per-tone) 10-bit signed None
Nexmon 802.11ac 80 MHz 64 256 float (12-bit mantissa) None

The choice of card depends on the task. Locating someone (Week 8) needs the fine grid — Nexmon resolves to about ±3.75 m where the Intel 5300 manages only ±15 m. Counting people and recognising activity (Weeks 6–7) lean on amplitude statistics gathered over all tones, so they tolerate the coarse Intel grid well.

Workbook §2.5 renders this comparison and prints the delay-resolution arithmetic Δτ = 1/B for each card: 50 ns / 15 m at 20 MHz, down to 12.5 ns / 3.75 m at 80 MHz. The numbers in the figure match this table cell for cell.

CSI extraction tool comparison rendered as a table figure: Intel 5300 (30 grouped subcarriers, 8-bit signed, up to 40 MHz), Atheros ath9k (56/114 per-subcarrier, 10-bit, up to 40 MHz), and Nexmon (up to 256 subcarriers / 80 MHz, 4-byte float). The delay-resolution column is Δτ_min = 1/B. Reproduce in Workbook §2.5.

6. From the Table to a Real Measurement: The Clean-Channel Occupancy Signature

The sections above built H(k) as a mathematical object. This section connects it to real measured quantities from the lab's simulation platform, so that every later sensing week stands on measured ground rather than idealised models.

First, a term we have referred to since Week 1 but not yet defined plainly. Imagine one clear shout in an arena versus the crowd's background murmur.

The Rician K-factor is the ratio of power in the strong direct path to power in the scattered echoes. A high K means the direct "shout" dominates (a clear line of sight); a low K means the scattered "murmur" takes over (lots of bouncing).

Formally, with v² the direct-path power and 2σ² the scattered power,

K = \frac{v^2}{2\sigma^2}.

Both quantities come from the tone sizes |H(k)| alone — no angle is needed. Occupancy changes K because people add scattered echoes (more murmur), shifting the balance; whether K goes up or down depends on the geometry, which is exactly what the lab measured.

The lab ran its static-channel simulator across a grid of impairments plus a clean control case — no added hardware noise, full numerical precision. With six simulated occupants across many placements, two scalar features were computed from the tone sizes |H(k)|.

Mean blockage attenuation — how much one person in the link weakens the average tone size, in decibels:

\Delta_{dB} = 20\log_{10}\frac{\overline{|H_k^{\text{empty}}|}}{\overline{|H_k^{\text{occ}}|}}.

Averaged over all tones and placements, the clean control gives 27.5 dB per person. Every occupied tone contributes a sample to this average — including tones in deep fade, which weigh the same as bright ones, a choice the impairment discussion revisits later.

Rician-K-vs-occupancy slope — the straight-line fit of K-factor against the number of people. The clean control gives +10.12 per person. A positive slope may seem odd at first: adding people might be expected to disrupt the direct path and lower K. But in this simulator's geometry the occupants sit in scattering positions without blocking the direct line of sight, so each one adds scattered energy while the direct path is only mildly weakened — and here the balance tips the slope positive.

Both numbers come from the tone sizes alone; nothing here uses the angle. The fragility, however, is striking. Adding even mild noise — at a signal-to-noise ratio of 30 dB — halves the blockage signal to 12.3 dB per person and flips the K-slope to −2.40. Occupancy lives in the small-size tail of |H(k)|, so once noise lifts the floor, it is the first thing to be swamped. This is why the finer-precision cards from Section 5 matter: a card with more numerical headroom crosses this fragility boundary later than the Intel 5300's coarse 8-bit rounding.

The clearest way to see the fragility is to plot the Rician K-factor against occupancy for both cases. The clean control rises steeply with each person; mild noise not only flattens it but sends it in the opposite direction — the sign-flip from +10.12 to −2.40 is the punchline.

Workbook §2.6 reproduces the 27.5 dB/person and +10.12 slope from an illustrative model anchored to those exact numbers, and contrasts the clean control against the noisy (SNR = 30 dB) case where the attenuation halves and the K-slope sign-flips. The clean-control data fetch is an optional, guarded cell that no-ops cleanly offline, so the notebook runs without cloud access; the executed output prints 27.50 dB/person and +10.12/agent.

Clean-channel occupancy signature. Left: mean |H(k)| in dB falls at 27.5 dB/person (clean) and 12.3 dB/person under mild added noise. Right: the Rician K-factor rises with occupancy at +10.12/agent in the clean control and sign-flips to −2.40 under noise. Reproduce in Workbook §2.6.

Key Results and Where to Reproduce Them

Result Value Workbook cell
802.11n subcarrier spacing 312.5 kHz §2.1
20 MHz delay resolution 50 ns / 15 m path uncertainty §2.3
Intel 5300: 30 grouped tones, 8-bit §2.5
Atheros ath9k: 56 tones, 10-bit, no grouping §2.5
Nexmon 80 MHz: 256 tones, float §2.5
Clean-channel blockage attenuation 27.5 dB/person §2.6
Clean-channel Rician-K-vs-occupancy slope +10.12 per person §2.6
Same signature under mild noise (SNR = 30 dB) 12.3 dB/person; K-slope −2.40 §2.6

Bridge to Week 3

This week derived the object the card hands you and named the hardware factors — the switched-off centre tone, quieter band edges, the per-packet AGC, tone averaging, and the angle offsets — that stop the raw table from faithfully reproducing the true channel. Week 3 takes the extraction toolchains as its subject: how the firmware modifications behind FeitCSI, Nexmon, and PicoScenes pull the CSI tables off commodity hardware, what file format each emits, and the practical gotchas (tone indexing, byte order, dropped packets) you meet before any sensing algorithm runs. The size artefacts catalogued here are exactly the signals Week 4's preprocessing lab will clean up, so the channel-table understanding built this week is the foundation for both.

Further Reading

  • Halperin et al. 2011, Tool Release: Gathering 802.11n Traces with Channel State Information — the original Intel 5300 CSI tool release; the canonical primary source for the 30-group / 8-bit format. halperin2011_2cbc
  • Gringoli et al. 2019, Free Your CSI — introduces the Nexmon CSI extractor and gives the first systematic side-by-side characterisation of Intel, Atheros, and Nexmon capabilities. gringoli2019_68e7
  • Bocus et al. 2022, OPERAnet — a multi-sensor activity-recognition dataset collected with the Intel 5300; defines the CFR↔CIR (IFFT) relationship in the data-collection context. bocus2022_ce7f
  • Ali et al. 2015, Keystroke Recognition Using WiFi Signals — per-subcarrier amplitude calibration and edge roll-off modelling. ali2015_d284
  • Xie et al. 2015, Precise Power Delay Profiling with Commodity WiFi — derives the delay-resolution formula Δτ = 1/B and quantifies the 15 m / 7.5 m path-length figures for 20/40 MHz channels. xie2015_0389
  • Meneghello et al. 2023, A CSI Dataset for Wireless Human Sensing on 80 MHz Wi-Fi Channels — the 80 MHz Nexmon dataset; Section III reports the hardware specifications cited in Section 5. meneghello2023_0a93
  • Ma et al. 2020, WiFi Sensing with Channel State Information — surveys phase-offset removal (CFO, SFO) with pseudocode for the linear-fit sanitisation algorithm. ma2020_4782
  • Zhang et al. 2022, Practical Issues and Challenges in CSI-based Integrated Sensing and Communication — enumerates the AGC, CFO, and unsynchronised-transceiver problems that make raw CSI non-flat, with a clear receiver-chain diagram. zhang2022_5822
  • Guarino et al. 2026, A survey on CSI-based Wi-Fi sensing datasets and models with a focus on reproducibility — the most comprehensive recent comparison of extraction tools, including PicoScenes, FeitCSI, and AX-CSI for 802.11ax. guarino2026_e72c