HackRF One · Volume 6

HackRF One Volume 6 — GNU Radio Companion 3.10+ Workflows

From source/sink block to a working AM/FM/SSB/FSK demodulator and an OOT module

Contents

SectionTopic
1About this Volume
2Installing GNU Radio 3.10+ with HackRF Support
· 2.1Linux
· 2.2macOS
· 2.3Windows
· 2.4Verify
3The osmocom Source/Sink for HackRF
4Worked Example — Live FM Broadcast Receiver
5Worked Example — FSK Decode
6Sample-Rate-vs-Bandwidth Trade-offs
7OOT Modules — When to Build Your Own
8Authoring an OOT Module Yourself
9Performance Tuning
10Cheatsheet Updates from this Volume
11Resources

1. About this Volume

GNU Radio is the canonical signal-flow DSP environment for the open-source SDR community. Where Universal Radio Hacker (Vol 7) is a pre-built protocol-analysis toolkit, GNU Radio is a construction set — you assemble a flowgraph from primitives (sources, sinks, filters, demodulators, framers) and the runtime executes it as a streaming graph at sample rate.

This volume covers GNU Radio Companion (the GUI flowgraph editor) version 3.10+, the version family used since 2022. Earlier 3.7/3.8 documentation is everywhere on the web; treat it as historical and translate the block names if you encounter it (most 3.7 examples have 3.10 equivalents with renamed/refactored blocks).

The four chapters of this volume cover: install, the source/sink for HackRF, a worked AM/FM example, a worked FSK example, and a quick OOT-module overview.

2. Installing GNU Radio 3.10+ with HackRF Support

2.1 Linux

sudo apt install gnuradio gnuradio-dev gr-osmosdr
gnuradio-companion &

gnuradio ships GNU Radio Companion (GRC), the runtime, and the standard block library. gnuradio-dev adds headers for OOT module development. gr-osmosdr is the osmocom block that provides SoapySDR-mediated source/sink for HackRF, RTL-SDR, USRP, BladeRF, LimeSDR, and more — you’ll use osmocom Source and osmocom Sink for HackRF flowgraphs.

For Kali users, the same packages are pre-installed in recent Kali releases.

2.2 macOS

brew install gnuradio gr-osmosdr
gnuradio-companion &

2.3 Windows

Use WSL2 (as in Vol 5 §2.3) — GRC’s GTK GUI launches over WSLg’s display server. Native Windows GNU Radio exists (gnuradio.org Windows installer) but the OOT-module ecosystem is sparse on Windows.

2.4 Verify

In GRC, drag an osmocom Source from the right-hand pane into the flowgraph. Set its parameters: device arguments hackrf=0, sample rate 2e6, centre freq 100e6. Drag a Frequency Sink (QT GUI), connect them, hit Run (▶). You should see live spectrum.

If osmocom Source is missing, gr-osmosdr is not installed. If the device fails to open, see Vol 5 §2.1 (udev rules).

3. The osmocom Source/Sink for HackRF

The osmocom block has roughly 30 parameters; the ones that matter for HackRF:

GRC parameterHackRF mappingTypical value
Device ArgumentsSelects the HackRF instancehackrf=0 or hackrf=<serial>
Sample Ratesample rate in samples/s2e6 to 20e6
Ch0: Frequencycentre frequency in Hze.g. 433.92e6
Ch0: RF GainRF amp on/off (0=off, 14=on)0 or 14
Ch0: IF GainLNA gain, 0–40 in 8 dB steps16
Ch0: BB GainVGA gain, 0–62 in 2 dB steps24
Ch0: BandwidthMAX2837 IF filter (auto if 0)0 (auto)
Ch0: Antennabias-T enable: empty = off, “TX/RX” = onempty

osmocom Source outputs complex float32 samples — the standard GNU Radio sample type. No format conversion needed for downstream blocks. (Compare to hackrf_transfer which writes int8; Vol 5 §4.)

4. Worked Example — Live FM Broadcast Receiver

A classic first GNU Radio flowgraph:

osmocom Source ──► Low-Pass Filter ──► WBFM Receive ──► Audio Sink
   (98e6 ctr)      (cutoff 100k)        (quad rate          (44.1 kHz)
   2e6 sr                                = 2e6,
                                         audio = 44.1k)

Block parameters:

BlockParameterValue
osmocom Sourcesample rate2e6
Ch0 Frequency98000000 (or your favourite FM station)
Ch0 RF/IF/BB Gain0/16/16
Low Pass Filtercutoff freq100e3
transition width50e3
sample rate2e6
WBFM Receivequadrature rate2e6 (input rate)
audio decimation5 (2e6 / 5 = 400k → 44.1k via Audio Sink rate change)
Audio Sinksample rate44.1e3

Connect them in order, run. Adjust BB gain for clear audio without clipping.

The flowgraph is saved as .grc (XML) and generates a .py file when you Run. The generated .py is the actual program; GRC is just the editor.

5. Worked Example — FSK Decode

For a sub-GHz FSK protocol (typical of 433 MHz remotes), the flowgraph adds a few more stages:

osmocom Source ──► Low-Pass Filter ──► Quadrature Demod ──► Binary Slicer ──► Throttle ──► File Sink
                                       (gain = sample_rate /  (slice level     (rate cap)    (write bits)
                                       (2π × freq_dev))        from histogram)

The Quadrature Demod block does the FSK demodulation by computing the angle change between successive samples — the result is a real-valued signal whose sign tracks the FSK symbol. Binary Slicer thresholds it to bits. File Sink writes the bit stream for offline analysis.

This is the rough shape of what every “decode a 433 MHz remote” tutorial walks. URH (Vol 7) does this whole pipeline graphically and adds protocol-structure inference; GRC is what you reach for when URH’s heuristic decoder is wrong and you want to author the chain by hand.

6. Sample-Rate-vs-Bandwidth Trade-offs

A key thing to internalise about flowgraph design:

  • Sample rate at the source sets the bandwidth captured. Lower = less data to push through USB and CPU.
  • Decimation in mid-flowgraph trades sample rate for bandwidth. A Decimating FIR at 5:1 reduces the rate by 5× and applies an anti-alias filter to keep what fits.
  • Audio-rate output (44.1 kHz typical) is far below most HackRF sample rates. Get there with progressive decimation: 2 MS/s → 200 kS/s → 50 kS/s → 25 kS/s → 12.5 kS/s, etc.

The general rule: keep the sample rate as low as possible without truncating the signal of interest. Capturing 20 MS/s when you only need 2 MS/s is 10× more CPU and 10× more disk for no benefit.

7. OOT Modules — When to Build Your Own

If the protocol you want to decode is published as a GNU Radio out-of-tree (OOT) module, install it rather than re-implement. Common OOT modules:

ModuleWhat it decodesRepo
gr-air-modesADS-B (1090 MHz aviation transponder)https://github.com/bistromath/gr-air-modes
gr-rdsRDS metadata in FM broadcasthttps://github.com/bastibl/gr-rds
gr-gsmGSM cellular (passive observation)https://github.com/ptrkrysik/gr-gsm
gr-iridiumIridium satellite traffichttps://github.com/muccc/gr-iridium
gr-pagingPOCSAG / FLEX pager protocols(multiple forks)
gr-bluetoothBluetooth Classic + LEhttps://github.com/greatscottgadgets/gr-bluetooth
gr-zigbeeIEEE 802.15.4 / ZigBeehttps://github.com/bkerler/gr-zigbee

OOT modules are built from source against your installed GNU Radio (must match major version). Build pattern:

git clone https://github.com/bistromath/gr-air-modes
cd gr-air-modes
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
sudo ldconfig

After install, the new blocks appear in GRC’s right-hand pane under their module name.

8. Authoring an OOT Module Yourself

When the protocol you care about isn’t in any existing module, the bootstrap is gr_modtool:

gr_modtool newmod my_protocol      # create gr-my_protocol/ directory
cd gr-my_protocol
gr_modtool add -t general my_decoder    # create a new block
# edit lib/my_decoder_impl.cc — implement work() with your DSP
mkdir build && cd build
cmake .. && make -j$(nproc)
sudo make install && sudo ldconfig

A minimal work() for a custom block:

int my_decoder_impl::work(int noutput_items,
                          gr_vector_const_void_star &input_items,
                          gr_vector_void_star &output_items)
{
    const gr_complex *in = (const gr_complex *) input_items[0];
    char *out = (char *) output_items[0];

    for (int i = 0; i < noutput_items; i++) {
        out[i] = (std::abs(in[i]) > threshold_) ? 1 : 0;
    }
    return noutput_items;
}

For a real protocol decoder, the work() is more complex — it implements the demodulator, framer, and sometimes a state machine. The OOT-module-authoring book “GNU Radio for the Practical Engineer” by Tom Rondeau is the best reference, but PySDR^[https://pysdr.org/] covers the basics free.

9. Performance Tuning

GRC flowgraphs run as Python that calls into C++ blocks. CPU is sometimes the bottleneck:

  • Profile with top while running. If the GRC python3 process is at 100% CPU, the flowgraph is CPU-bound.
  • Reduce sample rate at the source if possible — the highest-leverage optimisation.
  • Decimate early — push decimation as close to the source as the math allows.
  • Use Polyphase Arbitrary Resampler rather than chained Decimating FIR filters when the rate-change ratio is non-integer.
  • Disable QT visualisations when running production flowgraphs — Frequency Sink and Waterfall Sink each consume meaningful CPU. Use File Sink for throughput-bound work and inspect output offline.

For multi-flowgraph parallel processing (e.g. simultaneous decoders for several frequencies in different bands), each flowgraph can lock to a CPU core via taskset:

taskset -c 0 python3 fm_decoder.py &
taskset -c 1 python3 ads_b.py &

10. Cheatsheet Updates from this Volume

For Vol 12:

  • osmocom Source device args: hackrf=0 or hackrf=<serial>
  • Standard sample type: complex float32
  • Common flowgraph: source → LPF → demod → sink
  • Audio-rate output: progressive decimation 2e6 → 50e3 → 25e3 → 12.5e3 …
  • OOT modules: build with cmake/make against installed gnuradio version
  • gr_modtool newmod NAME to start a new OOT module
  • Performance: decimate early; disable QT GUIs in production

11. Resources

ResourceURL
GNU Radio main sitehttps://www.gnuradio.org/
GNU Radio wikihttps://wiki.gnuradio.org/
GNU Radio tutorialshttps://wiki.gnuradio.org/index.php/Tutorials
gr-osmosdr (HackRF source/sink)https://osmocom.org/projects/gr-osmosdr
PySDR — Marc Lichtman’s free bookhttps://pysdr.org/
OOT module authoring guidehttps://wiki.gnuradio.org/index.php/OutOfTreeModules
gr-air-modes (ADS-B)https://github.com/bistromath/gr-air-modes
gr-rdshttps://github.com/bastibl/gr-rds
gr-bluetoothhttps://github.com/greatscottgadgets/gr-bluetooth
gr-gsmhttps://github.com/ptrkrysik/gr-gsm