ONLINE
RAVEN RF · FIELD BUILD
JACOB LUNN · SIGINT / SDR
RAVEN RF // FIELD NOTES 00 01 02 03 04 05 06 07 08
// portable RF platform

raven_rf

Raven RF is a portable platform I built to understand radio frequency (RF) systems from the antenna up: the signals themselves, the processing behind them, and how raw radio activity becomes useful information on a screen.

It started with aircraft tracking. I wanted to understand what was happening beneath the software I was already using, from raw in-phase and quadrature (I/Q) samples to decoded messages and maintained tracks. That question grew into a self-contained Raspberry Pi platform for exploring aircraft, analog radio, satellites, Bluetooth, Wi-Fi, signal classification, and RF fingerprinting through a single interface.

Pi 5HackRF ProRTL-SDR V4 custom aircraft decodingPythonPyTorch

Raven RF is designed for receive-side RF analysis and authorized testing of hardware and signals I am permitted to examine.

00 · Where it started

The attic feeder

My first RF project was an aircraft feeder in the attic: two 9 dBi antennas, one for 1090 MHz and one for 978 MHz, each connected to its own software-defined radio (SDR) and both feeding a Raspberry Pi.

The feeder runs FlightAware's existing PiAware software stack, including dump1090-fa, dump978-fa, and fa-mlat-client. I assembled and configured the station; those tools handle aircraft decoding, the multilateration client, and reporting to FlightAware. Located between DFW International and Alliance, the station receives arrivals and departures from both airports along with high-altitude traffic farther away.

PHOTOThe attic feeder, two SDRs into a Raspberry Pi
The attic feeder, two SDRs into a Raspberry Pi
PHOTOThe two 9 dBi antennas for 1090 and 978 MHz
The two 9 dBi antennas for 1090 and 978 MHz
PHOTOThe ham radio I was learning on, part of getting into RF
The ham radio I was learning on, part of getting into RF
By the numbers · measured August 2026
#525
global FlightAware feeder rank over 30 days
33.4M
Mode S position reports in 30 days
~1.1M
average positions per day
4,119
aircraft observed in a single day
250NM
maximum reception range
100–115K/HR
Mode S messages per hour at the DFW morning peak

Seeing that coverage was exciting, but FlightAware's software was still doing the work of turning radio traffic into aircraft on a screen. I had assembled and configured the feeder, not written the decoding software behind it.

I could read the result, but I could not yet explain the complete path from the signal at the antenna to the bits in a Mode S message, from those bits to a position, and from successive positions to a moving aircraft track.

That became the question behind Raven RF.

From visualization to decoding

I first built a browser-based visualization to connect the antennas' gain and coverage patterns with the reception range I was measuring.

PHOTOThe browser antenna-coverage visualization
The browser antenna-coverage visualization

From there, I started an Unreal Engine 5 project to place those aircraft into a real 3D world while I learned more object-oriented programming. The longer-term idea was that an SDR user could connect a receiver and render their own local airspace.

A middleware application sat between the incoming aircraft data and Unreal Engine 5. It converted the aircraft messages into structured records and forwarded them to the visualization.

PHOTOThe Unreal Engine 5 aircraft visualization
The Unreal Engine 5 aircraft visualization

That pipeline helped me understand how to organize and display the aircraft data, but it made me increasingly interested in how the data was produced in the first place.

01 · From idea to device

From idea to device

While building those aircraft projects, I was also participating in an Aero Cyber Range capture-the-flag competition and working through Hack The Box as part of my OSCP preparation. I was spending more time in Linux and seeing more cyberdeck-style projects built around small, self-contained computers.

I liked devices such as the ClockworkPi uConsole, Flipper Zero, PortaPack H2, and Hak5 WiFi Pineapple, but I wanted to build something around my own interests instead of buying another general-purpose device.

The goal became a portable platform with a heavier RF focus. It needed to be:

  • self-contained
  • battery powered
  • usable without a network
  • equipped with its own display
  • capable of working with several radio and wireless systems through a single interface

Hardware

The resulting stack uses:

  • HackRF Pro, the main SDR, covering 100 kHz to 6 GHz
  • RTL-SDR V4 with a low-noise amplifier (LNA), dedicated to 978 MHz Universal Access Transceiver (UAT) reception
  • nRF52840 radio, Bluetooth Low Energy (BLE)
  • ALFA Wi-Fi adapter, 2.4 and 5 GHz Wi-Fi
  • BU-353N5, GPS receiver
  • Raspberry Pi 5, application computer with a 7-inch touchscreen
  • Geekworm X1202 UPS HAT, battery power from four 18650 cells

I also assembled antennas for the bands I wanted to explore: a 25 to 1300 MHz wideband whip, a VHF/UHF telescopic antenna for air and weather, a tuned 1090 MHz Automatic Dependent Surveillance-Broadcast (ADS-B) antenna, a 900 MHz ISM antenna, and several cellular whips.

PHOTOThe assembled antenna set for the bands I wanted to explore
The assembled antenna set for the bands I wanted to explore

Building the enclosure

Because my access to the 3D printer was limited, I measured the entire hardware stack with calipers before designing the enclosure: the screen, Raspberry Pi, batteries, radios, cooling system, and cable clearances.

I used those dimensions to generate an initial OpenSCAD model with AI, then manually refined the design before exporting it for printing. The first full print was functional enough to become the current enclosure, although I may revisit the design as the hardware evolves.

PHOTOThe enclosure fresh off the 3D printer
The enclosure fresh off the 3D printer

Why Raven?

Before the main interface loads, a boot animation introduces the project's name and visual identity.

BOOT SEQUENCE
tap to run the boot sequence
The boot animation that introduces the Raven identity

The name comes from Huginn and Muninn, the two ravens associated with Odin in Norse mythology. Their names are commonly translated as Thought and Memory. They are sent out into the world and return with what they have seen and heard.

That idea matched what I wanted the device to do. Raven RF uses sensors to observe an environment that is largely invisible, gathers their readings, and brings those observations into a single place where they can be interpreted.

The interface follows the same idea: a dark tactical HUD, Raven-purple accents, monospaced readouts, and a live map used as the common operating picture.

02 · Engineering the platform

Engineering the platform

Building individual RF tools was only one part of the problem. As Raven RF grew, the larger challenge became allowing those tools to share hardware and data without interfering with one another.

One radio, many capabilities

The HackRF is a half-duplex SDR with one RF chain and one antenna port. It can receive or transmit, but not both simultaneously, and it produces only one tuned I/Q stream at a time.

That creates an immediate constraint. Several components can analyze signals contained within the same captured bandwidth, but capabilities such as 1090 MHz Airspace, satellite reception, VHF radio, and sub-GHz analysis cannot independently tune the same HackRF to different frequencies at the same time.

The 978 MHz UAT path avoids that conflict by using the RTL-SDR independently.

Early versions of Raven RF let individual tabs control the HackRF directly. As more capabilities were added, two parts of the application could try to configure the same radio at once, causing hangs. I replaced that arrangement with a central SDR arbitrator. Every subsystem must request ownership before it can configure or start the HackRF. The owner controls settings such as center frequency and sample rate until it releases the radio.

Engineering decision
One physical RF chain → one explicit owner

The limitation did not disappear. Instead, Raven RF's architecture now represents it directly.

Decoupling the software

A second scaling problem appeared as workers, decoders, trackers, classifiers, and views accumulated: every new feature needed direct connections to more existing components. Small changes began to ripple across unrelated parts of the application.

I replaced that point-to-point mesh with a publish/subscribe DataBus. Producers publish named events such as decoded frames, aircraft updates, and signal classifications. Consumers subscribe only to the events they need. Hardware workers no longer update the interface directly, and views do not reach into worker implementations.

Raven RF system architecture Four layers: views, DataBus, workers and decoders, hardware. A cooperative SDR arbitrator grants HackRF receive ownership to one worker at a time and an IQ selector routes the single HackRF stream to that owner. RTL-SDR, nRF52840 and ALFA feed their workers directly. Raven RF system architecture Four layers, one shared HackRF receiver 01 Views 02 DataBus 03 Workers 04 Hardware HUD / base map Airspace Radio intercept Satellite Bluetooth Wi-Fi DataBus, publish / subscribe aircraft_updated gps_position wifi_networks ble_devices Separate process multiprocessing queue ADS-B decoder Radio intercept Satellite Signal AI NRX UAT decoder Bluetooth Wi-Fi IQ ownership IQ selector, one active consumer at a time SDR arbitrator one owner at a time, HackRF receive ownership only the granted owner receives the IQ stream HackRF IQ into the selector HackRF half duplex, one IQ stream RTL-SDR 978 MHz UAT nRF52840 BLE ALFA Wi-Fi Views read only from the DataBus. No view connects to a worker, the arbitrator or the hardware. Only the ADS-B decoder runs in a separate process. Every other worker runs in the main process. The arbitrator governs HackRF receive ownership only. The RTL-SDR, nRF52840 and ALFA paths never touch it. Solid purple: HackRF IQ or data path Solid teal: independent hardware data path Dashed purple: HackRF ownership request or grant Faded purple: available IQ route, not active Dashed gray outline: separate process boundary Solid arrow into the bus: publish Dashed arrow from the bus: subscribe
FIG. Raven RF system architecture: hardware, arbitrator, workers, DataBus, and views

The DataBus reduced coupling, but it did not solve CPU contention. The aircraft decoder and radar renderer originally ran in separate Python threads. Architecturally they were separate, but CPU-bound Python code still had to contend with the global interpreter lock. The decoder could hold the interpreter long enough to starve the radar renderer.

The aircraft decoder now runs in a separate process and returns its results through a multiprocessing queue. Resources tied to a particular thread remain with the worker that created them, while inactive views pause their refresh timers.

GIL STARVATION → PROCESS ISOLATION why the ADS-B decoder moved to its own process BEFORE: TWO THREADS, ONE INTERPRETER LOCK single CPython interpreter · one GIL ADS-B DECODER thread RADAR RENDERER thread holds GIL starved: brief slivers between decoder bursts → dropped frames time concurrency is not parallelism. The GIL lets only one thread run Python bytecode at a time. AFTER: DECODER IN ITS OWN PROCESS decoder process main process ADS-B DECODER own process RADAR RENDERER main process runs continuously · never yields to the UI steady frame cadence · no starvation multiprocessing queue decoded tracks → main process time separate processes run truly in parallel; results cross back through a queue.
FIG. Why the ADS-B decoder moved to a separate process

Together, those boundaries let the application grow without every subsystem directly depending on every other one.

The common operating picture

The home screen is Raven RF's base view rather than another tab. It combines information from across the system into one persistent picture:

  • offline map
  • aircraft tracks
  • Wi-Fi and BLE detections
  • Radio Intercept status
  • GPS position
  • upcoming satellite passes
  • Signal AI results
  • RF fingerprint alerts
  • hardware state
SCREENSHOTThe home screen, the common operating picture
The home screen, the common operating picture

When another capability opens, the map remains underneath it. Closing that view returns directly to the common operating picture.

The Android Team Awareness Kit (ATAK) was the primary design influence: the map acts as the anchor while different sources contribute tracks, icons, layers, status, and context.

A broader version of the same idea appears in the open-source intelligence (OSINT) globe, where external data sources share a geographic view. The next step is to combine more of Raven RF's locally detected activity with that wider context.

Runtime health

The System tab shows Raven RF watching itself while it runs. It displays live CPU, memory, temperature, UPS battery state, SDR state, peripheral state, and active subsystems.

SCREENSHOTThe System tab, live hardware and power state
The System tab, live hardware and power state

Because the platform is battery powered and several hardware devices share one Raspberry Pi, resource health is part of the instrument rather than something hidden behind the interface.

The System tab shows whether Raven RF remains healthy after startup. Preflight, described later, determines whether it was healthy enough to start in the first place.

03 · Airspace: from raw RF to tracks

Airspace

Airspace is the most developed part of Raven RF and the capability that most directly follows the question that started the project. The goal is not simply to display aircraft. It is to follow the processing chain from the radio signal itself to decoded messages, reconstructed positions, maintained tracks, and predicted motion.

Raven RF processes both 1090 MHz Mode S / ADS-B and 978 MHz UAT. The 1090 MHz path uses the HackRF. The 978 MHz path runs independently on the RTL-SDR, allowing Raven RF to process both aircraft bands at the same time instead of continually retuning one receiver.

Building the 1090 MHz decoder

At first, I used existing Mode S decoders while I built the surrounding system. Once that pipeline was working, I replaced that layer with my own decoder so I could understand and control the complete path from raw I/Q samples to aircraft messages. Raven RF's current 1090 MHz receiver begins with raw samples rather than decoded aircraft data. It:

  1. calculates the signal magnitude
  2. detects the fixed Mode S preamble
  3. recovers the pulse-position-modulated bits
  4. verifies the recovered message
  5. parses its fields
Mode S / ADS-B demodulation at 1090 MHz how a received radio burst becomes bits 01 raw IQ magnitude, one received burst preamble data bits amplitude 8 microseconds one bit per microsecond, 56 or 112 of them 02 preamble, a fixed 8 microsecond pattern that marks the start quiet, no pulses 0 1.0 3.5 4.5 microseconds 8 microseconds, always the same shape the receiver locks onto this known shape to find where a message begins. 03 bit periods, pulse position modulation each 1 microsecond slot is split in two; the half holding the pulse sets the bit. 1 microsecond first half second half bits 1 0 0 0 1 adjacent pulses can run together, the fixed slot grid still separates the bits pulse in the first half = 1 pulse in the second half = 0 04 recovered bits assemble into a frame 10001 10001101 01001000 01000000 ... recovered Mode S frame then CRC checked the first five bits, 10001, are downlink format 17, an ADS-B extended squitter
FIG. 1090 MHz Mode S demodulation, from I/Q to decoded frame

Message integrity

Once a frame is recovered, Raven RF calculates its 24-bit cyclic redundancy check (CRC). I also implemented single-bit error correction. A precomputed syndrome table maps a CRC error pattern to a possible corrupted bit. Raven RF flips that candidate bit and calculates the CRC again. The repaired frame is accepted only if it validates afterward. Frames that still fail are discarded.

Mode S single bit CRC correction Raven RF 01 Received frame, one bit flipped in transit. 1 0 0 0 1 1 0 1 0 1 0 0 1 0 1 1 0 0 0 1 1 0 1 0 0 0 1 0 1 1 0 0 32 of 112 bits shown. Marked here for the reader. The receiver does not know which bit yet. 02 CRC-24 check fails. CRC-24 check, polynomial 0xFFF409 Fail The checksum does not match, so the frame is wrong somewhere. 03 Locate and flip. A precomputed syndrome table maps the failure to this single bit. The syndrome is the received parity XOR the parity recomputed over the payload. 1 0 0 0 1 1 0 1 0 1 0 0 1 0 1 1 0 0 0 1 1 0 1 0 0 0 1 0 1 1 0 0 Flip the one suspect bit, 0 becomes 1. 1 0 0 0 1 1 0 1 0 1 0 0 1 0 1 1 0 0 1 1 1 0 1 0 0 0 1 0 1 1 0 0 One bit changed. Every other bit is left untouched. 04 Re-check and decide. CRC-24 re-check, same polynomial passes still fails Accept, frame trusted Discard, frame dropped The repaired frame is only trusted if it passes CRC the second time. Anything else is discarded, not guessed. Single bit correction only. Multi bit corruption is not repaired. ADS-B / DF17
FIG. Mode S single-bit CRC correction, with a mandatory re-check

Field decoding

I also wrote the field decoder directly in Python instead of calling the pyModeS library. Depending on the message type, it extracts the aircraft's 24-bit ICAO address, flight identification or callsign, altitude, velocity, and Compact Position Reporting (CPR) data. As a result, Raven RF's active 1090 MHz path no longer relies on an external aircraft-decoding library.

978 MHz UAT

UAT required a separate implementation because the modulation and framing are different. Where Mode S represents bits through pulse position, UAT uses frequency changes. Raven RF derives those changes from the phase relationship between consecutive I/Q samples, recovers the symbols, and searches for the 36-bit synchronization word that identifies a frame.

The most substantial part of this decoder is its Reed-Solomon forward error correction. Reed-Solomon correction uses redundant symbols in the transmission to reconstruct data damaged in transit. I implemented the decoder from the finite-field arithmetic upward over GF(2^8). The decoding path uses Berlekamp-Massey to derive the error-locator polynomial, Chien search to locate corrupted symbols, and Forney's algorithm to calculate the required corrections. Short UAT frames use RS(30,18) and can repair up to 6 corrupted symbols. Long frames use RS(48,34) and can repair up to 7. A CRC-16 is checked after Reed-Solomon processing.

byte view UAT 978 MHz, RS(30,18) received frame, corrupted symbols in red symbols 0 to 14 of 30 shown 8d a0 4c 3f 69 5a c7 02 91 1b 7d 33 6a 5a 9e ··· Reed-Solomon decode after Reed-Solomon, repaired symbols in teal repaired at 3, 8, 12 8d a0 4c b1 69 5a c7 02 e4 1b 7d 33 c0 5a 9e ··· illustrative bytes, not an over-the-air capture. decode stages 01 Syndromes detect that errors exist 02 Berlekamp-Massey find the error-locator polynomial 03 Chien search locate which symbols are wrong 04 Forney compute the repair values custom implementation over GF(2^8), primitive polynomial 0x11D. RS(30,18) repairs up to 6 corrupted symbols; RS(48,34) up to 7.
FIG. Reed-Solomon repair of a corrupted UAT frame

From messages to positions

Receiving a valid ADS-B frame still does not necessarily provide a directly usable latitude and longitude. ADS-B encodes positions with CPR. Raven RF supports two methods of resolving those positions. A position can be reconstructed locally using the receiver's known location as a reference, or a recent even and odd CPR frame from the same aircraft can be paired to derive a globally unambiguous position. Once resolved, those measurements become input to the tracking system.

From positions to tracks

Plotting every reported coordinate independently would leave the display vulnerable to noise, inconsistent measurements, and abrupt motion. Instead, Raven RF maintains a state estimate for each aircraft with an Interacting Multiple Model (IMM) tracker. Three motion models operate together:

  • constant velocity, steady flight
  • constant acceleration, changes in speed
  • coordinated turn, maneuvering flight

On each update, the tracker compares the newest measurement against the prediction made by each model and changes their weights according to how well each one explains the aircraft's current behavior.

IMM aircraft tracking with three weighted motion models One interacting multiple model track blends constant velocity, constant acceleration, and coordinated turn estimates, reweights them using a new measurement, gates implausible jumps, and predicts sixty seconds ahead. IMM aircraft tracker three models run at once, each with a probability weight Constant velocity (CV) steady flight 20% Constant acceleration (CA) speeding up or slowing down 15% Coordinated turn (CT) banking through a turn 65% one blended IMM state New position measurement compare against every model prediction each update, the models are reweighted by how well they match the newest measurement probabilistic weighting by measurement likelihood, not a hard model switch Gate check implausible jumps are gated, not trusted rejected measurement; prediction-only update Prediction 60 s ahead, 5 s steps, curved when turning CT dominates here, so the blended projection bends one estimate blended continuously from CV + CA + CT, with gating against inconsistent measurements
FIG. IMM tracker: three weighted motion models, gating, and prediction

The tracker also gates measurements that are too inconsistent with the predicted state. Rather than allowing one implausible observation to pull a track across the map, Raven RF performs a prediction-only update and waits for another measurement. After three consecutive rejected measurements, the track reinitializes at the new position instead of continuing to preserve stale state.

From the current estimate, Raven RF projects the aircraft 60 seconds forward in 5-second increments. When the coordinated-turn model carries the strongest weight, the projected path can curve with the maneuver.

One aircraft picture

Local 1090 MHz reports, local 978 MHz UAT reports, and an optional network aircraft source can all contribute to the displayed picture. That network source is the attic feeder from chapter 00. Selecting NET supplements the portable receivers with the feeder's attic antennas, bringing hundreds of additional aircraft into the same picture the handheld builds on its own. Reports are associated using the ICAO address. Raven RF uses a fixed source precedence rather than mixing individual fields from different records. The resulting state feeds several Airspace views, each exposing a different part of the pipeline.

RADAR

RADAR is the tactical view of the complete Airspace system. It displays traffic around the receiver with range rings, aircraft colored by source, smoothed trails, current motion-model state, predicted flight paths, uncertainty information, and conflict overlays.

REC · LIVE
Airspace RADAR, live tracks with range rings

The important difference from a simple aircraft plot is that RADAR displays the maintained estimate produced by the tracking system rather than treating every received position as an isolated point.

ACTIVITY

ACTIVITY presents the same live traffic as a searchable aircraft roster. Aircraft can be inspected and grouped into categories such as military, government, medical, and civilian traffic.

REC · LIVE
Airspace ACTIVITY, the aircraft roster

RADAR answers where the traffic is. ACTIVITY makes the population itself easier to explore.

SIGNALS

SIGNALS exposes the RF and message-processing side of the Airspace pipeline. For a selected aircraft, Raven RF can show captured signal data alongside its decoded Mode S messages. The message table exposes the hexadecimal frame, decoded fields, and integrity state.

REC · LIVE
Airspace SIGNALS, the I/Q and envelope view of a captured burst

The same tab also has a view for messages that arrive without captured I/Q, such as those added from the attic feeder. Instead of the envelope, it presents the decoded fields directly, including message type, aircraft address, category information, position-quality data, and integrity status.

REC · LIVE
Airspace SIGNALS, decoded fields for messages without captured I/Q

This view keeps the intermediate data visible, making it possible to work backward from an aircraft displayed elsewhere in Raven RF toward the radio traffic that produced it.

TRACKS

TRACKS follows one ICAO address over time. It combines altitude, speed, heading, signal strength, position history, and the recent message timeline.

REC · LIVE
Airspace TRACKS, one aircraft over time

Where RADAR shows the whole airspace, TRACKS makes it easier to inspect how the system maintains the state of one aircraft through successive observations.

RAW

RAW is the closest Airspace view to the decoder output. Mode S frames appear as they are received with timestamp, downlink format, ICAO address, type code, raw hexadecimal bytes, and integrity state.

REC · LIVE
Airspace RAW, decoded Mode S frames as received

The higher-level views deliberately turn radio traffic into something easier to understand. RAW does the opposite. It leaves the received messages close to their decoded form so the aircraft picture can be traced back to the live RF traffic beneath it.

04 · Expanding across the spectrum

Expanding across the spectrum

Airspace is the deepest implementation, but Raven RF was designed so additional sensing capabilities can use the same platform and contribute to the same overall picture.

Radio Intercept

Current

Radio Intercept is the analog-voice receiver pipeline I wrote. It covers civilian air traffic control, FM, NOAA weather radio, and the 225 to 400 MHz military UHF aviation band.

The receiver intentionally tunes slightly away from the selected center frequency to avoid the HackRF's central DC artifact. It then isolates the monitored channel from the wider I/Q capture before demodulating the AM or FM audio. The squelch measures power inside that channel rather than across the entire captured bandwidth, so unrelated activity elsewhere in the sample does not open the audio.

REC · LIVE
Radio Intercept, live analog voice receive
Next

Project 25 (P25) is the next major step for monitoring unencrypted public-safety traffic. Railroad radio monitoring is another planned addition because an active freight line runs nearby.

Satellite

The Satellite tab serves two roles.

External context

The OSINT globe is a Cesium-based world view. It continuously pulls live data from external APIs and combines the results geographically. Satellites are plotted from two-line element (TLE) orbital data, and selecting one displays its orbit. The globe also combines external hazard and activity feeds with aircraft and satellite data, making their geographic relationships visible on the same map. A selected point can also display the satellites currently closest to it.

REC · LIVE
The OSINT globe, live external sources on one map

Receiving overhead

The second part of the tab uses Raven RF's own radio hardware. It predicts NOAA weather-satellite passes using SGP4, schedules capture when a satellite is in range, and displays a live waterfall while the downlink is received. The Automatic Picture Transmission (APT) signal is then decoded line by line into a weather image.

REC · LIVE
A NOAA weather-satellite pass decoded into an APT image

This turns a live 137 MHz satellite downlink into a weather image covering the region around the receiver.

Bluetooth

Current

The Bluetooth tab maps nearby BLE activity across the 2.402 to 2.480 GHz portion of the 2.4 GHz ISM band. Bluetooth operates independently of the HackRF. Devices can be discovered through the computer's normal Bluetooth controller or, when connected, through an nRF52840 running Nordic sniffer firmware that captures advertising packets directly over the air.

ILLUSTRATIONHow BLE uses the 2.4 GHz band: advertising channels, data channels, hopping, and Wi-Fi overlap
How BLE uses the 2.4 GHz band: advertising channels, data channels, hopping, and Wi-Fi overlap

I wrote an advertisement parser that converts raw BLE fields into structured device information, including device name, address, address type, advertised services, manufacturer data, and vendor information. The parser uses Bluetooth SIG identifier tables to map known codes to vendor and service names.

Raven RF also identifies resolvable private addresses, or RPAs, which rotate periodically instead of behaving like permanent device addresses. The parser can recognize selected information from common Bluetooth ecosystems and manufacturer-specific advertisements. Because some proprietary formats are undocumented or change across software versions, Raven RF treats those interpretations as best-effort rather than guaranteed protocol definitions.

REC · LIVE
Bluetooth discovery, live BLE device map

Devices can be grouped into categories such as phones, wearables, IoT hardware, and trackers using several pieces of advertisement data rather than the name alone. Recognized tracker-like devices, including AirTag / Find My accessories, Tile devices, and Samsung SmartTags, can be surfaced to the home screen.

Proximity

Raven RF also tracks each device's received signal strength indicator (RSSI) over time. A Kalman filter smooths the signal measurements so short fluctuations do not dominate the trend. The resulting movement state can be reported as approaching, receding, or steady. When a device advertises calibrated transmit power, Raven RF can combine it with RSSI to estimate rough distance. Otherwise it uses a general signal-falloff estimate.

These are proximity estimates, not coordinates. A single antenna provides no direction information, and walls, reflections, people, orientation, and other environmental factors can significantly change RSSI.

Authorized active testing

For devices I own or have explicit permission to test, Raven RF can move from passive observation to controlled interaction. The tab's active assessment layer can enumerate Generic Attribute Profile (GATT) services and characteristics, inspect captured connection and pairing behavior, exercise writable characteristics with controlled fuzzing, and perform lower-level controller testing through the Linux host controller interface (HCI). These functions require an explicitly selected target and are intended for authorized testing of my own hardware.

Next

Two planned directions are to move proximity state onto the main HUD map and to use captured BLE signal data as real input for NRF-ID fingerprinting experiments.

Wi-Fi

Current

The Wi-Fi tab maps nearby 802.11 networks across the 2.4 and 5 GHz bands. It uses a dedicated external ALFA Wi-Fi adapter through Linux wireless tools, so Wi-Fi scanning operates independently of the HackRF. A background scanner records SSID, BSSID, channel, signal strength, and security type. Networks age out after they are no longer observed. The same data drives a channel display showing where identified networks are operating and how strongly they are received.

REC · LIVE
Wi-Fi discovery, networks mapped by channel and signal strength

That visualization is intentionally different from a spectrum analyzer. A fast Fourier transform (FFT) displays the frequency content of raw samples regardless of whether Raven RF understands the signal. The Wi-Fi view displays only networks the scanner has identified and places them on their corresponding channels. It is therefore a view of the Wi-Fi environment rather than the complete RF energy in the band.

Next

This is an area I want to develop much further. The next step is to study 802.11 at a lower level by capturing and inspecting packets, examining management and authentication frames, following device-association behavior, and working more directly with Linux networking tools.

05 · Experimental intelligence

Experimental intelligence

Two parts of Raven RF explore whether the system can extract information about a transmission beyond decoding a known protocol. They approach that question from different directions.

Signal AI asks: what kind of signal is this?
NRF-ID asks: does this physical transmitter resemble one I have seen before?

Neither result should be treated as proof on its own.

Signal AI

Current experiment

Signal AI takes short windows of raw I/Q samples and attempts to classify the signal's modulation. The current PyTorch model combines a convolutional encoder with a small Transformer. The model classifies signals across 13 modulation types while also estimating properties such as signal-to-noise ratio and frequency offset.

Inference runs locally on the Raspberry Pi. The current model reaches approximately 46% accuracy across 13 classes on synthetic test data, compared with roughly 8% for random guessing. That result is limited to the current synthetic evaluation and is not presented as equivalent performance on real RF captures.

Signal AI and NRF-ID layered architecture One IQ capture feeds two independent analysis layers, Signal AI and NRF-ID. Their outputs may later be fused into a combined qualitative description, shown as planned future work. one IQ capture raw samples from a receiver Signal AI what kind of signal is this? outputs modulation type SNR frequency offset maturity neural model, trained NRF-ID which device sent this? outputs hardware fingerprint consistent / different / unknown closest enrolled device maturity feature matching, model planned planned fusion, not yet wired together combined description of the emission signal type and likely source, together each result is evidence, not proof; the two together describe more than either alone.
FIG. Signal AI and NRF-ID: two questions about the same transmission
Next

The architecture I am working toward keeps the Raspberry Pi focused on RF capture and deployed inference while moving training and retraining to a connected RTX 3090 workstation. The next major step is to train under more realistic RF conditions, incorporate labeled over-the-air captures, and measure how well a model trained on synthetic data transfers to real signals.

NRF-ID

Current experiment

NRF-ID is Raven RF's RF-fingerprinting workspace. It looks for small, repeatable differences associated with transmitter hardware using I/Q samples already captured by Raven RF's receive paths. Current measurements include characteristics such as carrier-frequency offset, I/Q imbalance, turn-on behavior, and nonlinear distortion.

Multiple captures can be enrolled into a persistent reference profile. Future transmissions can then be compared with that profile and reported as consistent with the reference profile, inconsistent with it, or unknown.

next capture 01 Capture I/Q a burst from an existing receive path 02 Extract features carrier-frequency offset, I/Q imbalance, turn-on transient, nonlinear distortion 03 Enroll or compare enroll Reference profile stored between sessions compare within tolerance? consistent different unknown Statistical feature-matching, not a trained model. Meaningful only across repeated captures over different days and conditions.
FIG. NRF-ID fingerprinting cycle: enroll, build a profile, compare

The central challenge is separating the transmitter's characteristics from the environment and receiver. Signal strength, multipath, receiver gain, temperature, orientation, and the receiving hardware itself can all affect the measurements. A fingerprint from one recording is therefore not enough. The experiment becomes more meaningful only if the same transmitter remains distinguishable across different captures, days, and RF conditions.

Next

The next step is to train an embedding model directly from captured I/Q bursts so signals from the same device can cluster together in a learned fingerprint space. Longer term, NRF-ID could provide an additional consistency check for systems such as Airspace or Bluetooth. The intended result would not prove that a claimed ICAO address or Bluetooth identity is authentic. It would provide another piece of evidence about whether the physical transmission resembles one Raven RF has previously observed.

06 · Preflight

Preflight

A working interface does not necessarily mean the system behind it is working correctly. Raven RF's Preflight sequence exists for that reason.

Before the main interface opens, Raven RF validates the environment, dependencies, connected hardware, SDR interfaces, and software layers required for startup. Checks report one of three states:

  • PASS: operating as expected
  • WARN: optional capability missing or degraded
  • FAIL: required functionality is broken
REC · LIVE
Preflight running staged PASS / WARN / FAIL checks

The exact number of tests depends on the connected hardware, but a fully configured system runs more than 300 checks. These checks go beyond detecting whether a USB device exists. Preflight exercises the layers Raven RF is actually about to use so that a successful launch represents a functioning system rather than one that simply appears alive.

Preflight also became useful during development. Several difficult problems became easier to isolate once Raven RF could test hardware, interfaces, queues, and subsystem contracts before the UI became involved. In that sense, Preflight serves two purposes:

  • Readiness: can Raven RF start correctly?
  • Diagnosis: if it cannot, where is the failure?

The System tab then continues that idea after startup by monitoring whether the platform remains healthy while it runs.

07 · What fought back

What fought back

Some of the most useful parts of Raven RF came from failures rather than planned features. Three bugs in particular changed how I approached the system.

The radar that could not get time to draw
Symptom
The aircraft decoder and radar renderer were placed on different threads, but the renderer could still be starved.
Cause
Separating the code into threads did not make CPU-bound Python execute in parallel. The decoder could hold the global interpreter lock long enough to keep the radar from receiving enough execution time.
Fix
I moved the aircraft decoding loop into a separate process and returned its output through a multiprocessing queue.
What changed
I made process boundaries an explicit part of the architecture instead of assuming threads would provide sufficient isolation.
The database that looked healthy but stored nothing
Symptom
The application continued running and appeared successful, but expected SQLite writes were not actually being stored.
Cause
A SQLite connection created on one thread was being used from another.
Fix
I changed the database code so each SQLite connection is created and used by the same worker thread.
What changed
A failure that remains hidden can be more difficult than one that crashes visibly. I added more instrumentation and validation so broken internal state would be exposed instead of remaining silent.
The audio chain that processed too much signal
Symptom
The VHF receiver produced mostly static instead of intelligible audio.
Cause
It was operating on the full wideband capture instead of first isolating the voice channel.
Fix
I moved channel filtering and decimation earlier in the receive chain, before demodulation.
What changed
I began treating each intermediate DSP stage as something to inspect and validate rather than treating the entire receive chain as one opaque operation.

The common lesson across all three was the same: a system can appear to be working while an internal subsystem is failing. That is why Raven RF now includes mechanisms such as Preflight, queue counters, intermediate signal checks, and clearer ownership boundaries.

08 · Where it goes next

Where it goes next

The next stage of Raven RF is less about adding more tabs and more about deepening the capabilities already present and connecting them more closely.

Signal AI needs to move beyond synthetic training data toward labeled over-the-air captures, with training and retraining moving to a connected RTX 3090 workstation while the Raspberry Pi remains focused on capture and inference.

NRF-ID needs a much larger dataset collected across different days and RF conditions before I can evaluate whether transmitter fingerprints remain consistent enough for a learned embedding model.

Wi-Fi analysis can expand into packet-level 802.11 inspection, while cellular analysis can eventually provide another view of the surrounding radio environment.

The larger direction is the home screen. I want Raven RF to build a unified live picture from aircraft, satellites, Bluetooth, Wi-Fi, detected signals, RF fingerprints, and outside sources while leaving the individual tabs available for deeper analysis.

Codebase snapshot · measured August 2026
57.2K
source lines of code
198
source files
53.3K
Python code lines
1.6K
Rust code lines
14
live tabs
300+
Preflight checks

Raven RF started with one question: how does a radio signal reaching an antenna become meaningful information on a screen? It has grown into a platform I can keep using to answer that question across RF, signal processing, networking, tracking, software architecture, and machine learning.

AI has helped me move faster across a project this broad, but it does not replace verification or understanding. Every capability still has to pass the same test: I need to be able to verify what it does and explain why it works.

Raven RF is not intended to be finished. The point is to have one platform that can continue growing with my understanding of the wireless environment.