Reported symptom: the dongle connects through the browser fine and then
produces nothing. The driver was a sketch written from memory and marked
HARDWARE PASS REQUIRED, and that caveat never reached the UI.
The decisive bug was not the tuner at all: `demodWrite` had every field of
its control transfer wrong. librtlsdr uses value=(addr<<8)|0x20,
index=0x10|page, big-endian; this used the block in value, page and address
transposed in index, and little-endian. Every demod register write went to
the wrong place. The block constants were wrong too (DEMOD=0 USB=1 SYS=2,
not 0x03/0x02/0x09), as was the I2C repeater control (page 1 reg 0x01,
0x18/0x10 — not reg 0x02, 0x41/0x01).
Then the tuner, as originally suspected: the R820T's full 27-register init
(0x05-0x1f) replaces three pokes, with a shadow array since those registers
are write-only; IF filter calibration; a real r82xx_set_pll with VCO band
scan, nint+SDM into 0x14/0x16/0x17, and a lock poll that names the frequency
that failed instead of streaming silence. Gain defaults to tuner AGC. The
buffer reset is 0x1002 -> 0x0000, not 0xffff.
Two more that would each have been fatal alone: the demod was left in
zero-IF mode though the R820T delivers a 3.57MHz IF, so a locked PLL would
still have been off-centre; and setSampleRate masked with JS's 32-bit `&`
on a ~1.2e14 value, mangling the ratio below ~1.15Msps.
Tuner detected by chip id, throwing "unsupported tuner: <name>" rather than
running R82xx sequences against foreign silicon.
The arithmetic is pure and tested against hand-derived vectors, including
107.9MHz where mix_div drops 32->16 — a boundary the old fixed mixDiv=2
could never have reached. Independently re-derived 88.5MHz (0x26/0x66) and
98MHz (0x6d/0x82) and they match exactly.
HONEST LIMIT: none of this has touched hardware. The arithmetic is proven;
the register pokes and transfer encodings are reasoned, not observed.
Several constants are marked UNCONFIRMED in the file, chiefly the tracking
filter table and the SDM register pair.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>