Harvey Mudd College
No video for this lesson. Lessons 24–38 were drafted in October 2026 with the help of an AI assistant (Claude) in the spirit of the lessons above, and tested on the same RTL-SDR / PlutoSDR / B210 setup. They are less polished than the video lessons; corrections and pull requests are welcome.
(The flowgraph is Jason’s from 2022; only this page is new.)
So far every digital modulation put the bits into the amplitude or phase of the carrier. FSK puts them into the frequency: a 1 is a tone a little above the carrier, a 0 a tone a little below. The transmitter is just the VCO block (voltage-controlled oscillator) from Lesson 8b’s radar: the bit stream, smoothed a little by a low-pass filter and scaled to ±fsk_deviation_hz, is the frequency we ask it to produce.
The receiver is equally simple: the Quadrature Demod block outputs the phase change from one sample to the next, which is the instantaneous frequency. Scale it so the two tones come out as ±1 (samp_rate/(2π·deviation)), low-pass filter, slice at zero, and the bits are back. Notice what is not there: no Costas loop. FSK does not care about the carrier phase, only about frequency, and a frequency error between Pluto and RTL-SDR just shifts the demodulator output up or down (the tuning_freq_kHz slider cancels it; Lesson 25 does this automatically).
The price is bandwidth: two tones 20 kHz apart switching every 100 µs use far more spectrum than the 10 kbit/s deserve. Lesson 25 makes FSK efficient.
lesson24b_4FSK_Pluto_to_RTL.grc sends two bits per symbol by using four tones, at −3, −1, +1 and +3 times the deviation (this is how FLEX pagers and DMR hand-held radios work). The transmitter is the same VCO; the receiver is the same FM demodulator, now followed by a DC Blocker that removes the Pluto/RTL-SDR frequency error automatically, and the demodulated signal has four levels: look at the histogram and the stacked “eyes”. A slicer would need three thresholds instead of one.
fsk_deviation_hz until the demodulator can no longer tell the tones apart. The ratio deviation / bit rate is the modulation index \(h\); here \(h = 2\).multimon-ng program you can decode real ones.Running: 2-FSK from the Pluto, demodulated by the RTL-SDR; the top trace is the sliced bits:
Other flowgraphs for this lesson:
lesson24b_4FSK_Pluto_to_RTL.grc — 4-FSK over the air: four demodulated levels, four histogram peaks, stacked eyes
All GNURadio flowgraphs are at https://github.com/gallicchio/learnSDR