The ADS-B Framer (adsb_framer) is the first block in the gr-adsb pipeline. It consumes a magnitude-squared power signal, searches for the 8-symbol ADS-B preamble pattern, and annotates the stream with "burst" stream tags at each detected preamble position. Downstream blocks use these tags to locate and demodulate individual ADS-B frames.
Block info
| Property | Value |
|---|
| GRC block ID | adsb_framer |
| GRC label | ADS-B Framer |
| GRC category | [ADS-B] |
| Python class | adsb.framer |
| Constructor | adsb.framer(fs, threshold) |
| Block type | sync block |
Parameters
Sample rate in samples per second. The block computes sps = int(fs // 1e6) to determine the number of samples per symbol. The sample rate must be an integer multiple of 1 MHz (fs % 1e6 == 0); the block raises an AssertionError otherwise. The minimum usable sample rate is 2 Msps (2 samples per symbol at the 1 Msym/s ADS-B symbol rate).
Detection threshold applied to the magnitude-squared input signal. Any sample at or above this value is treated as a high pulse; samples below it are treated as low. Lower values increase sensitivity but also increase false-positive preamble detections. This parameter can be updated at runtime by calling set_threshold(threshold).
Ports
| Label | Domain | Data type | Vector length |
|---|
in | stream | float32 | 1 |
The input must be the instantaneous power of the received signal: |I|² + |Q|². Use a blocks.complex_to_mag_squared block upstream to compute this from a complex IQ source.
Outputs
| Label | Domain | Data type | Vector length |
|---|
out | stream | float32 | 1 |
The output is a pass-through of the input signal with no modification to the sample values. The burst stream tags described below are attached to this output stream.
When a valid preamble is detected, the Framer emits a stream tag on output port 0:
| Field | Value |
|---|
| Key | "burst" |
| Value | ("SOB", snr) — a tuple of the string "SOB" (Start of Burst) and the SNR in dB |
| Source | "framer" |
The tag is placed at the sample index corresponding to the centre of the first preamble pulse. The SNR is computed as:
SNR (dB) = 10 * log10(pulse_amplitude / median_noise) + 1.6
The 1.6 dB correction accounts for the fact that the median of a Rayleigh-distributed noise variable is 1.6 dB below its mean power.
Preamble detection
ADS-B uses Pulse Position Modulation (PPM) at 1 Msym/s. The 8-symbol preamble produces the following half-symbol pulse pattern (sampled at 2× the symbol rate):
[1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
The Framer converts the input to a binary pulse vector by thresholding, then checks each detected rising edge to see if the subsequent 16 half-symbol samples match the pattern above. A preamble is confirmed only when all 16 half-symbol samples match.
History buffer
The Framer sets a history buffer of N_hist = NUM_PREAMBLE_BITS * sps samples (8 × sps). This history allows the work() function to detect preambles whose first pulse falls at the very end of the previous work() call’s input buffer. At 2 Msps, N_hist is 8 samples; at higher sample rates it scales proportionally.
Runtime callback
The detection threshold can be changed while the flowgraph is running:
framer.set_threshold(0.005)
This updates the internal self.threshold value. The next work() call will use the new threshold.
End-of-burst guard
After confirming a preamble, the Framer records the estimated end-of-burst index (prev_eob_idx) based on the shorter 56-bit (Short Squitter) packet length. Subsequent rising edges that fall before this index are skipped, avoiding spurious preamble detections on data pulses within the same packet.
Instantiation example
import gnuradio.adsb as adsb
framer = adsb.framer(fs=2e6, threshold=0.01)
In GNU Radio Companion, set the Sample Rate and Detection Threshold parameters in the block properties dialog. The block ID is adsb_framer.