Reference
Type: MMW_OUTPUT_MSG_RANGE_PROFILE
Length: (Range FFT size) × (sizeof(uint16_t), or 2 bytes)
Value: Dense array of range points at the 0th Doppler bin (stationary objects). Each point is the normalised sum of the log₂ magnitudes across the virtual antenna channels, represented in unsigned Q8 format.
How values are produced
-
A range FFT is performed on the ADC samples from each RX antenna for each chirp (functionally for each virtual antenna channel). This produces the radar cube: a collection of complex values that can be indexed by range bin, chirp number, and virtual antenna channel.
Set be ADC sample from any chirp associated with virtual antenna channel . The range FFT produces:
Here, is the number of ADC samples,
is the range-FFT length (either equal to number of samples or next power of two greater. Strictly speaking, it is actually HALF this value because only half the FFT bins after RangeFFT contain unique information due to real, not complex I/Q, sampling),
is the range fft window, and
is the range-bin index.
Basically, the resulting radar cube is indexed:
-
A Doppler FFT is performed across slow time (i.e. the chirp dimension) for each range bin and virtual antenna channel. Its complex output can be indexed by range bin, Doppler bin, and virtual antenna channel.
is the number of chirps for each virtual antenna channel,
is the DopplerFFT length (either equal to the number of chirps in a CPI or next nearest power of two of that number greater). For TDM, this number should be divided by the number of TX antennas because each TX-RX virtual antenna channel only samples when its corresponding TX antenna is transmitting. For DDM, this DopplerFFT length is not divided by anything as every TX-RX virtual antenna channel is sampling at the same time,
is the Doppler window, and
is the Doppler-bin index.
The resulting complex array is logically indexed as:
In the equations below, is another way of writing . I've omitted implementation-specific FFT scaling factors.
-
The log₂ magnitude is calculated for every Doppler FFT output:
is the complex Doppler FFT output. Taking its magnitude, , removes complex phase. The HWA represents the resulting log₂ magnitude internally as an unsigned Q11-formatted value.
-
A second FFT is performed across the virtual antenna channel dimension. Only zero-frequency bin is retained because that bin is the sum of all its inputs (convince yourself that is a mathematical property of FFTs). FFT scaling normalises this sum by the FFT length .
For virtual antenna FFT bin , the scaled FFT output is:
is the virtual antenna channel FFT length (either equal to the number of virtual antenna channels or next power of two from that number greater. FFT inputs are zero-padded for indices beyond number of virtual antenna channels in the latter case so they don't contribute to sum),
At zero-frequency bin, , complex exponential equals one:
Therefore, the retained output is the normalised sum across all virtual antenna channels:
-
The result is converted from unsigned Q11 format to unsigned Q8 format.
For these equations:
- is the range-bin index.
- is the Doppler-bin index.
- is the virtual-antenna index.
- is the number of virtual antenna channels.
- is the next power-of-two FFT length, as outlined in (4). When is already a power of two, .
The complete relationship from the Doppler FFT output to the raw Q8 integer is:
The approximation accounts for fixed-point quantisation and implementation-specific HWA scaling omitted for clarity. Dividing the raw integer by recovers the decoded log₂ value:
The range-profile TLV contains only Doppler bin zero, so its transmitted values
are rawValueToOutput[r, 0] for each range bin .
Q8 representation
Each range point is stored in a 16-bit unsigned integer (uint16_t). Its bits
are interpreted as an unsigned Q8 fixed-point value, with an implied binary
point between bits 8 and 7.
Bit 15 8 7 0
+----------------------------+----------------------------+
| Integer: 8 bits | Fraction: 8 bits |
+----------------------------+----------------------------+
iiiiiiii . ffffffff
The lower 8 bits are the fractional part, so one count represents
1 / 2^8 = 1 / 256. Decode a received value by dividing it by 256:
decoded value = raw value (uint16_t) / 256
For example, a raw value of 13107 (0x3333) represents:
13107 / 256 = 51.19921875
This unsigned 16-bit representation can express values from 0 to
65535 / 256, or approximately 255.996.
Selecting the output
The CLI config command guiMonitor selects the TLV elements that are sent in
the output packet. This includes the range profile.