Spectral Scan Support
| Driver | HAL | Supported Hardware | 802.11n support | Debugging |
The AR9280 and later NICs have the ability to report FFT data from the baseband under user-controlled conditions.
Overview
The PHY has the ability to report FFT summary information about the received wireless signal. This is useful for a variety of reasons - visualising the radio spectrum is one obvious benefit; others have used it to build interference classifiers.
The FFT summary includes:
- Absolute magnitude (|i| + |q|) - ie, the ABS() of both I and Q phases of a signal) for each FFT bin - 56 carriers in 20MHz mode, 114 in 40MHz mode
- An index indicating which FFT bin had the highest signal;
- The maximum signal magnitude.
It does not run in parallel with wireless transmission or reception - so either spectral scan FFT reporting can run, OR packet transmission/reception.
Configuration
The spectral scan HAL API allows for a few tweaks:
- ss_count - how many samples to return each time an FFT sample is made.
- ss_short_rpt - whether to only run one FFT sample ('short repeat') or whether to run many FFT samples for each FFT sample period.
- ss_fft_period - when active and triggered, how often to sample FFT results. This is implemented as (fft_period+1)*4uS.
- ss_period - when active, how often to trigger the FFT sample. This is implemented as (period*256*Tclk). Where Tclk is the configured clock rate (eg 44MHz for HT20 operation, 88MHz for HT40 operation; 40/80MHz for 5GHz non-fast-clock operation.)
On the AR9280, an ss_count of 128 is interpreted as "never disable" returning samples. Otherwise, "ss_count" samples are returned, then the spectral scan mode is moved from active to stopped.
The athspectral tool in src/tools/tools/ath/ allows for command line control of the spectral scan code.
- athspectral set and get allows for parameters to be tweaked
- athspectral start and athspectral stop will start and stop a spectral scan, respectively
- athspectral enable_at_reset (1|0) will enable/disable spectral scan during channel change and reset.
The latter (enable_at_reset) is useful for sampling during channel scanning.
For the 11n chips (AR9280 and later), chain 0 is used for spectral scan. So, the RSSI values for chain 0 (primary and extension) should be used. Don't use the combined RSSI value.
The RSSI value may be below 0 for very weak signals, so please keep this in mind. The hardware will return RSSI as a signed value.
Frame format
Spectral scan data is reported as a PHY error.
- 0x5 - RADAR
- 0x24 - RADAR, possible false, out of band or wideband signal
- 0x26 - SPECTRAL payload (AR9287 and later)
HT20:
Byte |
Description |
0 |
bin -28 magnitude[7:0] = (|i| + |q|) >> max_exp |
1 |
bin -27 magnitude[7:0] = (|i| + |q|) >> max_exp |
2 - 53 … |
|
54 |
bin 26 magnitude[7:0] = (|i| + |q|) >> max_exp |
55 |
bin 27 magnitude[7:0] = (|i| + |q|) >> max_exp |
56 |
[7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]} |
57 |
[7:0]: all bins max_magnitude[9:2] |
58 |
[7:0]: all bins {max_index[5:0], max_magnitude[11:10]} |
59 |
[3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) |
HT40:
0 |
bin -64 magnitude[7:0] = (|i| + |q|) >> max_exp |
1 |
bin -63 magnitude[7:0] = (|i| + |q|) >> max_exp |
2 - 125 … |
|
126 |
bin 62 magnitude[7:0] = (|i| + |q|) >> max_exp |
127 |
bin 63 magnitude[7:0] = (|i| + |q|) >> max_exp |
128 |
[7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]} |
129 |
[7:0]: lower bins max_magnitude[9:2] |
130 |
[7:0]: lower bins {max_index[5:0], max_magnitude[11:10]} |
131 |
[7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]} |
132 |
[7:0]: upper bins max_magnitude[9:2] |
133 |
[7:0]: upper bins {max_index[5:0], max_magnitude[11:10]} |
134 |
[3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) |
Calculating a dBm value from the reported magnitudes
The sum of all of the magnitudes in the sample should equal the reported RSSI. So to calculate a dBm value, the rough method is:
Convert RSSI -> dBm by assuming the noise floor is -96dBm (in 20 or 20/40 mode, as RSSI is reported separately for both 20MHz halves) and assume the dBm value is simply "RSSI" above the noise floor;
- .. this isn't as easy as it sounds, mainly because noise and spurs can cause the noise floor samples to rise, which reduces the "RSSI" value;
- .. and there's no easy way to figure out how far above -96dBm the calibrated NF really is;
- Then assume that the magnitude of each sample in a 20MHz bin equals the RSSI
- .. for 40MHz, you'd do this once for PRI with the PRI RSSI, and once in the SEC channel with the secondary channel RSSI;
- .. which means that you need to figure out whether PRI maps to the lower or upper channel;
- And then decompose each magnitude into a dBm value.
So do this programatically for a HT20 channel:
bin_sum = 10*log(sum[i=1..56](b(i)^2)
Where b(i) is the magnitude value in each bin, corrected by max_esp to give a true magnitude value;
Then the dBm value for each bin (i):
power(i) = noise_floor + RSSI + 10*log(b(i)^2) - bin_sum
And for HT40, you would do this over 64 bins for both lower and upper - using the appropriate RSSI from the RX descriptor. For HT40- channels, the extension channel is below the primary channel, so you would use lower=extension RSSI and upper=primary RSSI. For HT40+ channels, the extension channel is above the primary channel, so lower=primary RSSI, upper=extension RSSI.
Known Issues
- Since spectral sample FFT is done before any digital correction of DC carrier leak, the values at DC will be artificially high.
- The MAC sometimes mis-classifies these frames as data rather than PHY error payloads and helpfully "aligns" them for us. This partially corrupts one of the FFT results. Because of this, you must leave short_report enabled else you will get many FFT results in one frame, with no way of knowing whether the first has been corrupted.
- The AR9280 has some issues with traffic throughput whilst spectral scan is enabled. Please keep this in mind if you're doing high traffic whilst trying to do spectral scanning.