I Kept the Engineering Decisions Human
I chose the architecture, the physical connections, the 222–225 MHz working boundary, the safety rules, the question for each experiment, and the one variable allowed to change. Those choices determine what an RF result means. They cannot be recovered later from a directory of captures.
I gave the repeatable mechanics to the orchestration. It edited the nominated parameter, ran Yosys and nextpnr, checked timing, started direct telemetry, waited for the RTL-SDR ready handshake, loaded volatile CRAM, verified CDONE, commanded one finite burst, captured the off/on/off interval, recovered the packet or audio, and returned the output to its idle state. Ordinary sweep segmentation, gain sweeps, and unchanged repeats remained predetermined instrument work.
Three branches chose their next setting from the physical response: Run 14 through Run 17, Run 33 through Run 36, and the later PLL-delay branch. Everywhere else, automation executed the experiment I had already defined. This kept physical authority narrow while still letting the receiver answer quickly enough to guide the next build.
One Question Crossed the Whole Machine
- Choose one physical question. I named the measurement, the allowed band, the safety condition, and one variable to change.
- Build the exact digital change. The tools synthesized, placed, and routed it. A timing or topology failure stopped the branch before the board was touched.
- Start the observers first. Direct FPGA telemetry began, then the RTL-SDR armed and acknowledged that samples were already flowing.
- Load volatile CRAM. The orchestration programmed the image through FTDI/D2XX and checked CDONE. Nothing was written to persistent configuration memory.
- Transmit one bounded event. The receiver was already recording when the burst began, so one capture held RF-off guard time, the burst, and the return to quiet.
- Read both sides of the boundary. Direct telemetry identified what the FPGA applied; independent IQ samples showed what crossed N16, the tank, the pad, cable, tuner, and receiver.
- Recover the information. Spectral separation was useful, but packet length, CRC, symbols, bits, EVM, and timing decided whether the change remained a radio.
- Keep, reject, or restore. A successful discriminator became the starting point for the next single change. A failure caused the last accepted image to be reloaded.
- Check the idle state. Postflight telemetry had to show N16 high-impedance and the transmit LED off before the loop could advance.
From 11:13 PDT on July 25 through 20:43 PDT on July 26, the work spanned 33 hours, 30 minutes. Inside that interval I made 171 RTL-SDR acquisitions, 87 configured NanoVNA sweeps, saved 133 raw IQ captures, and performed 70 volatile FPGA loads across 42 digital configurations. These are bounded instrument and programming operations, not equivalent experiments and not continuous RF transmission. Receiver acquisitions include their RF-off guard intervals.
July 25: I Taught the Bench to Answer Clean Questions
The first day was about removing ambiguity from the physical path. I corrected the antenna, coupler, LNA, attenuation, and 50-ohm terminations; separated passive NanoVNA work from active SDR work; and stopped using an early H8 configuration when its tuner did not lock as intended. The NanoVNA was powered down before transmitter captures.
- 11:13 PDT
- The session began with the physical connections and safe operating boundary, not with an RF optimization target.
- 12:22–13:44
- Receiver and fixture baselines exposed the topology mistakes and fixed the antenna, coupler, LNA, attenuator, and termination arrangement.
- 14:59–15:37
- Wide views, gain checks, finite on/off behavior, and the high-impedance idle state bounded what later narrow measurements could mean.
- 16:06–17:58
- Q-sign reversal, tone, amplitude, sawtooth, and phase-ramp experiments made the one-pin boundary answer elementary causal questions.
- 18:49–20:22
- Two-axis audio and system-identification experiments tested whether richer structure survived the physical path.
- 20:42 onward
- The loop moved into QPSK and FM. The first saved volatile programming operation followed at 00:36 PDT on July 26.
Five complex sweeps of the passive tank put the median S21 maximum at 220.782991 MHz. The half-power crossings were 217.439055 and 223.718667 MHz, a 6.280417 MHz loaded bandwidth and a loaded Q of 35.1575. That result mattered later: the final 223.5625 MHz QPSK lane sat only 156.167 kHz inside the upper half-power crossing.
Then I changed only the sign of Q. The received component moved from 997.925 Hz below the measured midpoint to 997.925 Hz above it, a 1.995850 kHz crossing. The digital quadrature choice was controlling which side of the physical carrier received energy, giving the later packet work a directional control it could change deliberately.
July 26: The Receiver Chose Two Follow-Up Experiments
At 02:38 PDT, Run 14 recovered all 1,800 transmitted bits and passed CRC while giving 7.661408 dB of separation from the unwanted comparison window. The physical response did not justify a full correction, so the loop selected a half-sized frequency warp for the follow-up. At 03:02, Run 17 preserved the exact 1,800-bit recovery and raised that separation to 10.435617 dB, an improvement of 2.774209 dB. It also worsened separation from the central LO by 1.011560 dB. The receiver had found an improvement and exposed its cost in the same event.
The sharper sequence began at 04:40. Run 33 passed its packet check with 8.865934 dB of raw separation between opposite windows. The pattern pointed to Q entering the first IF mixer with the wrong adjacent phase. In that RTL snapshot, the Johnson counter served specifically as the quadrature IF oscillator; I changed only the Q input tap from phase 1 to phase 0.
Run 35 at 05:09 raised the separation to 20.583482 dB, an 11.717548 dB improvement, while the frame length and CRC still passed. Run 36 at 05:23 looked even better in the spectral window: 23.744552 dB. But its recovered length was wrong, CRC failed, decision-referenced EVM reached 96.152%, and angular jitter reached 93.617 degrees. Three minutes later the orchestration restored Run 35.
That reversal is the central reason I built the loop. A spectrum analyzer can reward a change that destroys the communication system. Closing the path through recovered information prevented the nicest-looking failure from becoming the next design.
One PLL Tap Improved the Image and Worsened the Carrier
Later that afternoon, I considered swapping the sideband. The predicted dominant output would have moved outside my 222–225 MHz boundary, so I stopped that branch before transmission. I instead allowed one nominal delay tap on PLL port A and held the rest of the transmitter constant.
Physical 24 through Physical 26, acquired from 16:09 to 16:21 PDT, separated three questions into fixed receiver views. In the 25 kHz integration windows used for the main comparison, wanted-to-image separation moved from 24.7769 to 30.0123 dB. Wanted-to-carrier separation moved the other way, from 8.1091 to 7.3466 dB. The tap bought image separation by spending carrier separation; neither number alone could choose the design.
Physical 27 Closed the Loop Through Recovered Bits
I built the accepted Physical 27 image at 16:48 PDT. It used 2,127 of 7,680 logic cells, one PLL, no block RAM, three global networks, and seven package I/O sites. Its routed maxima were 84.78, 115.81, 108.67, and 244.20 MHz for the four declared domains, including the 216.03 MHz RF-phase domain.
At 16:56, the orchestration started telemetry, waited for the SDR, programmed volatile CRAM, verified CDONE, issued one three-second burst, and left the receiver running long enough to observe quiet on both sides. Direct telemetry associated the actual PRBS16 QPSK state with the independent IQ stream rather than inferring the transmitted state from the receiver alone.
The QPSK source ran at 3,295.8984375 symbols per second, or 6,591.796875 gross bits per second. After acquisition, 4,296 directly observed held-out symbols produced 8,592 checked bits with no observed errors. Carrier-tracked RMS EVM was 2.0696% and normalized correlation was 0.999584. The receiver used known symbols only for initial acquisition; phase tracking over the held-out region did not use the transmitted bit decisions.
The nominal held-out span contained 5,623 epochs. Direct telemetry reached 4,296 of them; the other 1,327 remained holes. Across the complete run I found 7,555 directly observed epochs and 2,332 holes, and I did not interpolate those holes into successes. After the burst, 22,528 idle telemetry frames reported no burst request, no RF-enable state, and no transmit LED activity.
Physical 28 Moved Only the Receiver
At 17:50 PDT, Physical 28 changed one thing outside the FPGA: the RTL-SDR tuned from 223.4875 MHz to 208.3625 MHz to look at the conjugate image. The FPGA image, transmitter profile, SDR gain, sample rate, cable path, and receiver stayed otherwise unchanged.
The sequential complete-path comparison gave 29.4439 dB of wanted-to-image separation in fixed 25 kHz windows. That value belongs to this complete physical path. It includes the tank, pad, cable, tuner, and RTL-SDR frequency response; it is not an intrinsic cancellation number isolated from the apparatus.
The Chamber Bounded the Bursts
I used my RF chamber as the physical safety boundary and operated finite one-shot bursts, not a continuously transmitting board. Physical 27 and Physical 28 both ended with telemetry showing N16 high-impedance and the transmit LED off. The orchestration would not begin another branch until that postflight condition was visible.
I did not retain a chamber photograph or an exterior calibrated field-strength sweep from this session. I therefore do not present these experiments as measured containment, outdoor legality, or regulatory compliance. The next chamber pass needs distance, antenna factor, orientation, detector and bandwidth settings, ambient baseline, and uncertainty recorded together.
What I Will Make the Loop Do Next
The next work is a better measurement plane. I want a complete tank schematic and measured BOM, fixture geometry, loading, cables, and named reference planes. I will tie a raw TDS3034C waveform at the intended RF output plane to the exact FPGA image, carrier setting, load, and scope configuration. Traceable amplitude calibration and conducted power with uncertainty will replace relative receiver units where absolute quantities matter.
I also want a common trigger or clock between FPGA telemetry and RF acquisition, repeated bursts across supply and temperature, drift tracking, and BER versus controlled condition. A simultaneous target/image receiver would remove the sequential frequency-response ambiguity in Physical 28. Wider calibrated chamber sweeps and final-profile harmonic work need instruments and fixtures chosen for those frequency ranges.
Once that foundation is in place, the same loop can control multiple active lanes, choose discriminators that separate image, carrier, flatness, timing, and message recovery, and expose safe predetermined experiments through a browser. The important part will remain unchanged: every digital idea must cross the physical machine and return as an intelligible consequence before it earns the next experiment.

