All lab entries

Lab note

LOG-004SDR

Television here is still analog, and an SDR can watch it

I set out to receive digital TV with a HackRF and spent two days proving that three of the four options were impossible, unavailable, or wider than my radio. What was left is the one everybody assumes is dead.

9 min read
  • SDR
  • HackRF
  • GNU Radio
  • Video
  • PAL
  • DSP

I wanted to watch television with a HackRF. Not decode a beacon, not plot a spectrum — actually see a picture that somebody is broadcasting right now.

The first thing that happened was two days of research that killed almost every version of the idea.

Everything that does not work

Digital terrestrial television is the obvious target, and in Türkiye it is a series of closed doors:

Left: chart of samples per video line at different SDR sample rates, PAL landing on whole numbers and NTSC on fractions. Right: four boxes rating analog PAL as watchable and DVB-T, DVB-T2 and Türksat as unreachable.
Left: why the decoder is pinned to 8 Msps. Right: what a 20 MHz SDR can and cannot pull out of the sky over Türkiye, as of July 2026.

DVB-T was never commercially broadcast here, so there is nothing to receive. DVB-T2 exists only as test transmissions — Çamlıca on UHF channel 50 around 706 MHz is confirmed, with Ankara, İzmir and Adana testing — and there is no open-source real-time DVB-T2 receiver at all. gr-dtv's T2 support is transmit-only, the SDRangel request is closed as wontfix, and gr-dvbs2rx does satellite DVB-S2 instead. Türksat is worse in a way that no amount of code fixes: a 27.5 MSym/s transponder occupies roughly 33–37 MHz, and a HackRF tops out at 20 MHz. You cannot see the whole signal, so you cannot demodulate it.

What survived is the option I had assumed was long dead. Analog PAL-B/G is still on the air in Türkiye, with no announced shutdown date. Most homes moved to satellite years ago and simply stopped looking at the terrestrial band, but the transmitters never went off.

Why the decoder is pinned to 8 Msps

Analog video is refreshingly dumb: amplitude over time, one line after another, with sync pulses telling you where the lines and frames begin. Demodulate, slice the stream into lines, stack the lines into a frame. The entire question is how many samples one line is worth.

PAL runs 625 lines at 25 frames per second — exactly 15,625 lines per second. At 8 Msps that is exactly 512 samples per line, and 512 × 625 gives you a frame with nothing left over. A power of two, no rounding, no accumulating drift.

NTSC's line rate is 15,734.27 Hz, and at the same 8 Msps it lands on 508.44 samples. It only divides evenly at 18 Msps; everywhere else it has to be resampled before you can cut a raster from it.

The sync problem, which is the whole problem

Finding line boundaries is easy in principle: the horizontal sync pulse is the darkest part of the line, so the darkest column is where the line starts. The longest run of dark rows is the vertical blanking interval, so that is where the frame starts.

Doing that independently on every frame is also what makes the picture shake. Noise moves the estimate by a pixel or two, the whole image jumps, and it looks far worse than a static offset would.

So the aligner became a tracking loop instead of a per-frame guess: a smoothed offset, a deadband of 2.5 pixels, and a cap of 5% movement per frame to reject single-frame outliers. Inside the deadband it simply stops moving. The unit test tells the story — raw per-frame argmin gave a standard deviation of 1.52 pixels; the tracked version gives 0.0. Locked means locked. It still follows a slow drift if the line length is slightly wrong, it just refuses to chase noise.

Finding something to point it at

Preset channel lists assume the transmitter is where the list says it is. For cameras and FPV links it usually isn't, so each band got a sweep: step across the whole range, take FFT peaks, and report where signals actually are.

The sweep driver also needed rebuilding once. The first version stepped on a fixed 600 ms timer while a retune takes about 1600 ms to settle, so it blindly skipped the first two or three centres of every band — the beginning of each band was never scanned at all. The fix was to stop trusting the clock and start matching each FFT frame's own centre-frequency header against the requested centre, only advancing after four valid frames have arrived.

Where this honestly stands

The full path — demodulation, rastering, sync tracking, the clarity chain — is verified end to end on the loopback test pattern at 512 × 625, and verified on a real HackRF tuned to an off-air signal at 615.251172 MHz, where it produced 25 frames while I narrowed the bandwidth from 6 MHz to 3 MHz live.

And then a picture came out of it — which is not the same thing as a good one.

A grainy monochrome frame received off the air: the same picture appears twice, stacked, with a bright vertical bar down the right side and small white boxes that read as a station logo and a caption.
Straight off the air, no cleanup.

The bright bar down the right is the blanking interval sitting inside the visible raster; the picture appears twice because the frame boundary is landing in the wrong place. Both of those are alignment, not demodulation.

It is grey, it is noisy, and it is not locked. But it is a broadcast: there is a station logo in the top-left corner and a caption box lower down, and both are legible. The chain is genuinely pulling a picture out of the air — what it is missing is the last mile, which is holding the frame still.

So what I have not done is sit down and watch a clean, locked broadcast picture. That is the honest state of it.

Decode rate
8 Msps
PAL raster
512 x 625
Sync jitter
1.52 → 0.0 px
Picture
grey, silent

And even when it does lock, it will be grey and silent. Proper analog TV needs a vestigial-sideband filter, a real sync separator, interlace handling, the colour subcarrier, and the 5.5 MHz audio subcarrier — none of which this has. Every one of them is a known, bounded piece of work rather than a mystery, which is a comfortable place for a project to sit.

The part I did not expect to enjoy was the research. I set out to write a demodulator and spent the first two days establishing that three of the four things I might have demodulated were impossible, unavailable, or physically larger than my radio. Knowing which door is the only open one is worth more than kicking at the locked ones faster.