Classroom Glossary Public page

RF-201 Intermediate RF — Setup Guide

760 words

Prerequisites

Complete WIR-101 (Wireless Penetration Testing) and CSA-101 (Computer Systems Architecture) before enrolling. You need:

  • Python 3.11+ with NumPy, SciPy, and Matplotlib
  • GNU Radio 3.10+ (GR3) installed and functional from WIR-101
  • Familiarity with reading and writing .iq / .sigmf capture files
  • Comfort with basic GNU Radio flowgraph construction (WIR-101 Week 9 baseline)

Hardware Kit

Per-Student (required)

Item Purpose Approx. Cost
RTL-SDR Blog V4 dongle + dipole antenna Passive receive; spectrum survey; sub-GHz labs ~$40
Alfa AWUS036ACM 802.11ac USB NIC Monitor mode; 802.11 fuzzing labs ~$35

Minimum per-student outlay (if WIR-101 kit owned): ~$0. Both items carry forward from WIR-101.

Program-Supplied (shared; one per lab cohort)

Item Purpose
ANTSDR E200 (AD9361 + Zynq-7020) Academy canonical full-duplex SDR platform; IQ-sampling labs; LoRa demodulator; URH replay; capstone
LimeSDR Mini Alternate TX/RX platform; alternate for LoRa/BLE labs
HackRF One TX-capable replay; PT cross-cut module
nRF52840 USB dongle Bluetooth Classic + BLE sniffer for Lab 4
Faraday cage enclosure (50x30x30 cm) Contain live transmissions for all TX labs

Remote students use the virtual/recorded-capture path for all transmit-side work (see below).


Software Environment

Option A — Kali Linux 2025.x (recommended)

sudo apt update && sudo apt full-upgrade -y
sudo apt install -y \
  gnuradio gnuradio-dev gr-osmosdr \
  rtl-sdr librtlsdr-dev \
  libiio-utils libiio-dev \
  python3-iio \
  urh \
  inspectrum \
  wireshark tshark \
  libpcap-dev \
  aircrack-ng \
  scapy \
  python3-numpy python3-scipy python3-matplotlib \
  python3-pip \
  bluez bluez-tools bluetooth \
  nrf-sniffer-for-bluetooth-le 2>/dev/null || true
pip3 install sigmf pysdr pyserial

Option B — Ubuntu 24.04 LTS

Same apt commands. Install GNU Radio from PPA if apt version is older than 3.10:

sudo add-apt-repository ppa:gnuradio/gnuradio-releases
sudo apt update
sudo apt install gnuradio

Option C — Windows 11 + WSL2

WSL2 Ubuntu 24.04 works for Python DSP analysis. USB passthrough (usbipd-win) required for SDR hardware. ANTSDR E200 connects via Ethernet to the host at 192.168.1.10; accessible from WSL2 with network passthrough or via the libiio network context ip:192.168.1.10. GNU Radio under WSL2 requires an X server (VcXsrv or WSLg) for the GRC GUI.


ANTSDR E200 Setup

The ANTSDR E200 is the academy's canonical lab platform. It carries an AD9361 RF front-end (identical chip to ADALM-PLUTO / PlutoSDR) on a Xilinx Zynq-7020 FPGA-SoC. Two firmware options are supported; the course uses both at different points.

Connection

Connect the E200 via Ethernet to your lab machine. Default IP: 192.168.1.10. Set your host NIC to the same subnet (192.168.1.x/24).

Verify connectivity:

ping 192.168.1.10

Firmware Option 1: libiio (IIO driver) — Weeks 8-9 + Lab 11

libiio is the recommended firmware for GNU Radio work via gr-iio.

# Install libiio from source (if packaged version < 0.24)
sudo apt install -y libavahi-client-dev libxml2-dev
git clone https://github.com/analogdevicesinc/libiio
cd libiio && mkdir build && cd build
cmake .. -DINSTALL_UDEV_RULE=OFF
make && sudo make install && sudo ldconfig

# Verify: discover the E200 over network
iio_info -u "ip:192.168.1.10"
# Expect: iio:device0 = ad9361-phy; iio:device1 = cf-ad9361-lpc; etc.

Install gr-iio for GNU Radio integration:

sudo apt install gnuradio-dev cmake libboost-all-dev
git clone https://github.com/analogdevicesinc/gr-iio
cd gr-iio && mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
make && sudo make install && sudo ldconfig

Verify in GNU Radio: search for "IIO" in the GRC block search bar. You should see PlutoSDR Source and PlutoSDR Sink blocks — these work with the ANTSDR E200 (same AD9361 chip, same libiio API).

Firmware Option 2: UHD driver — Lab 10 cross-cut

sudo apt install uhd-host libuhd-dev
uhd_find_devices
# Expect: ANTSDR E200 listed as UHD device at 192.168.1.10

ANTSDR E200 GNU Radio flowgraph (libiio path)

Minimum receive flowgraph:

Block Settings
PlutoSDR Source URI: ip:192.168.1.10 / Frequency: 433.92e6 / Sample Rate: 2e6 / RF Bandwidth: 2e6
Throttle Sample Rate: 2e6
QT GUI Frequency Sink Center Freq: 433.92e6 / Bandwidth: 2e6

LimeSDR Mini Setup

sudo apt install limesuite gr-limesdr
LimeUtil --find
# Verify device detected

GNU Radio: use LimeSuite Source block.


RTL-SDR v4 Refresher

The RTL-SDR carries forward from WIR-101. Verify still working:

rtl_test -t
# Expect: Found 1 device(s), no errors

If errors appear, re-run the driver blacklist procedure from WIR-101 SETUP.md.


nRF52840 Dongle (Bluetooth sniffer)

sudo apt install nrfutil
# Flash Wireshark Bluetooth sniffer firmware onto nRF52840
# Nordic: https://www.nordicsemi.com/Products/Development-hardware/nRF52840-Dongle
# Firmware: nrf-sniffer-for-bluetooth-le (Nordic Infocenter download)
nrfutil pkg generate --hw-version 52 --sd-req 0x00 \
  --application nrf_sniffer_for_bluetooth_le.hex --application-version 1 pkg.zip
nrfutil dfu usb-serial -pkg pkg.zip -p /dev/ttyACM0

Wireshark integration: Tools > Serial Capture > select the nRF52840 COM port. Real-time BT/BLE frames appear in the capture window.


GNU Radio Custom Blocks (Week 9 prerequisite)

RF-201 Week 9 requires writing custom GNU Radio blocks in Python. Prerequisites:

# Verify GR3 OOT module infrastructure
gnuradio-config-info --prefix
# Expect: /usr

# gr_modtool for OOT module scaffold
gr_modtool newmod myblock
cd gr-myblock
gr_modtool add myblock_ff --block-type sync

Review: GNU Radio wiki "OutOfTreeModules" tutorial before Week 9.


Virtual / Recorded-Capture Path

Remote and hardware-limited students complete physical-SDR labs through pre-captured IQ archives.

Supported IQ formats

import numpy as np

# GNU Radio / HackRF default (complex64 = interleaved float32 I,Q)
samples = np.fromfile("capture.iq", dtype=np.complex64)

# RTL-SDR raw uint8 (unsigned byte pairs: I0,Q0,I1,Q1,...)
raw = np.fromfile("rtlsdr.bin", dtype=np.uint8)
iq = ((raw.astype(np.float32) - 127.5) / 127.5)[0::2] + \
     1j * ((raw.astype(np.float32) - 127.5) / 127.5)[1::2]

# SigMF (preferred; captures metadata alongside samples)
import sigmf
meta = sigmf.SigMFFile(metadata_file="capture.sigmf-meta",
                       data_file="capture.sigmf-data")
samples = meta.read_samples()

GNU Radio virtual path

For each physical-hardware lab, a virtual path exists:

  1. Replace the PlutoSDR Source / osmocom Source block with a File Source block
  2. Set File Source type to complex, file to the provided .iq archive
  3. Add a Throttle block after File Source (prevents CPU runaway in file-mode)
  4. Set Throttle sample rate to match the capture metadata

Each lab section marked Virtual path gives the exact .iq filename and capture metadata.

Lab IQ archive index

Lab Archive file Sample rate Center freq Duration
Lab 1 lab1-modulation-zoo.iq 2 MSPS varies 10 s per mod
Lab 2 lab2-dsss-demo.iq 4 MSPS 915 MHz 30 s
Lab 3 lab3-80211-mgmt.pcapng n/a (PCAP) 2.4 GHz 5 min capture
Lab 4 lab4-ble-pairing.pcapng n/a (BT PCAP) 2.4 GHz full pairing exchange
Lab 5 lab5-lora-868.iq 1 MSPS 868.1 MHz 60 s
Lab 6 lab6-zigbee-mesh.pcapng n/a (802.15.4 PCAP) 2.405 GHz mesh traffic 5 min
Lab 7 lab7-2msps.iq, lab7-8msps.iq, lab7-20msps.iq 2/8/20 MSPS 433.92 MHz 15 s each
Lab 9 lab9-unknown-protocol.iq 250 kSPS 433.92 MHz 45 s
Lab 11 N/A — ANTSDR E200 required for this lab

Lab 11 (ANTSDR E200 advanced IQ) has no virtual path; it requires physical access to the ANTSDR E200. Remote students with cohort access to a lab-server-hosted E200 connect via the IIO network context ip:<server>. Check the course portal for lab-server scheduling.


First-Day Smoke Tests

# 1. ANTSDR E200 network reachable
ping -c 3 192.168.1.10

# 2. libiio discovers E200
iio_info -u "ip:192.168.1.10" | grep "ad9361"
# Expect: device name containing "ad9361"

# 3. GNU Radio with gr-iio installed
gnuradio-companion --version
python3 -c "import gnuradio; from gnuradio import iio; print('gr-iio OK')"

# 4. NumPy IQ pipeline
python3 -c "
import numpy as np
samples = np.zeros(1024, dtype=np.complex64)
print('IQ pipeline OK, dtype:', samples.dtype)
"

# 5. URH launches
urh --version

# 6. Inspectrum launches
inspectrum --version 2>/dev/null || inspectrum &
# Should open GUI without errors

# 7. scapy 802.11 layers
python3 -c "from scapy.layers.dot11 import Dot11; print('scapy 802.11 OK')"

Flag any failures to the instructor before Week 1.