adsb_demod) is the second block in the gr-adsb pipeline. It reads the tagged float stream produced by the Framer, demodulates each ADS-B burst using Pulse Position Modulation (PPM) detection, and publishes a PMT PDU containing the raw demodulated bits and burst metadata on the demodulated message port.
Block info
| Property | Value |
|---|---|
| GRC block ID | adsb_demod |
| GRC label | ADS-B Demod |
| GRC category | [ADS-B] |
| Python class | adsb.demod |
| Constructor | adsb.demod(fs) |
| Block type | sync block |
Parameters
Sample rate in samples per second. Must be an integer multiple of 1 MHz (
fs % 1e6 == 0). The block computes sps = int(fs // 1e6) to determine the number of samples per symbol, and uses sps // 2 as the half-symbol offset for PPM sampling.Ports
Stream ports
| Label | Direction | Domain | Data type | Vector length |
|---|---|---|---|---|
in | input | stream | float32 | 1 |
out | output | stream | float32 | 1 |
Message ports
| Label | Direction | Description |
|---|---|---|
demodulated | output | PMT PDU containing raw bits and burst metadata |
PPM demodulation
ADS-B encodes each bit as a pair of half-symbol intervals. A1 bit has a high pulse in the first half and a low pulse in the second half; a 0 bit has the reverse.
For each of the 112 bits in a maximum-length ADS-B frame, the Demod block samples the input stream at two positions relative to the start of the burst:
bit1_idx:sob_idx + bit_number * sps— first half of the symbol (expected high for a1)bit0_idx:sob_idx + bit_number * sps + sps // 2— second half of the symbol (expected high for a0)
1 if the amplitude at bit1_idx exceeds the amplitude at bit0_idx, and 0 otherwise.
The block also computes a confidence metric for each bit:
1; negative values indicate higher confidence of a 0; values near zero are ambiguous.
Demodulated PDU structure
Each detected burst produces one PMT PDU published on thedemodulated port. The PDU is a PMT cons cell: (metadata_dict . data_vector).
Metadata dict
UTC Unix timestamp (seconds since 1970-01-01 00:00:00 UTC) of the burst, derived from the block’s startup time plus the burst sample offset divided by
fs.Signal-to-noise ratio in dB, as estimated by the Framer and propagated via the burst stream tag.
Data vector
Anumpy array of uint8, always 112 elements long. Each element is 0 or 1 representing one demodulated PPM bit. Bits are in transmission order: the first 5 bits encode the Downlink Format (DF), followed by the message payload and 24-bit CRC.
Extracting bits in a custom block
Straddled-packet handling
If the end of a burst falls beyond the currentwork() call’s input buffer, the block sets an internal straddled_packet flag and skips demodulation for that burst. The flag is cleared at the start of the next work() call. Straddled packets are not recovered; they are silently dropped.
Instantiation example
out stream port to the Demod’s in stream port, then connect the Demod’s demodulated message port to the Decoder’s demodulated message port.