Some time ago I started implementing “classic” packet radio into PacketRF. Not the fancy NPR stuff, not high-speed links, but the old and simple AX.25. The one that runs at 1200 baud over a narrow FM channel and somehow still works over surprisingly long distances. And as soon as I decided to support 1200 baud packet radio (often called PR1200) in PacketRF, I ran into a problem that many people before me had already solved, but I had never really thought about in detail: how do you efficiently decode Bell 202 AFSK on a small embedded system without wasting half your CPU on it? This post is a write-up of what I learned. Part refresher, part rediscovery, part “wait, why does this even work?”. I ended up making a bunch of small visualizations along the way, mostly out of curiosity, and at some point I realized this is actually a very nice way to look at DFT and Goertzel that I personally had never seen presented this way. So this is not a textbook explanation. This is more like: I needed this for PacketRF, I looked into it, and this is what finally made it understandable for me. And I also wanted to share my fancy animated GIFs :) What are we trying to decode? Let’s start from the beginning. Packet radio is one of those things that “everyone knows”, but if you ask three people what PR actually is, you will probably get three slightly different answers. Classic packet radio (on VHF/UHF) is basically a stack of very simple building blocks layered on top of each other: AX.25 on the link layer (HDLC-like framing) NRZI encoding of bits AFSK modulation at the physical layer And specifically for 1200 baud, this is Bell 202, which uses two tones: 1200 Hz → mark (logical 1) 2200 Hz → space (logical 0) So the whole chain looks like this: TX: HDLC frames → NRZI → bits → AFSK (1200/2200 Hz) → audio → radio RX: radio → audio → detect tones → bits → NRZI decode → HDLC frames The part we care about in this article is just one small piece of that chain: detect tones and turn them into...
First seen: 2026-05-24 14:53
Last seen: 2026-05-25 13:16