Skip to content

Settle clock source before tuning, not after#1793

Closed
munzzyy wants to merge 1 commit into
greatscottgadgets:mainfrom
munzzyy:fix-clkin-fallback-before-tune
Closed

Settle clock source before tuning, not after#1793
munzzyy wants to merge 1 commit into
greatscottgadgets:mainfrom
munzzyy:fix-clkin-fallback-before-tune

Conversation

@munzzyy

@munzzyy munzzyy commented Jul 5, 2026

Copy link
Copy Markdown

Fixes #1785.

The regression is a variable mix-up in radio_update_frequency() in firmware/common/radio.c. When an explicit LO is requested, the code is supposed to pass that requested value into mixer_set_frequency(), but it actually passes freq_lo, which at that point still holds the previously applied LO:

if (requested_lo != RADIO_UNSET) {
    freq_lo = mixer_set_frequency(&mixer, freq_lo, false);
}

Right after a device reset there is no previously applied LO, so freq_lo is still RADIO_UNSET (all ones), and that huge sentinel gets fed to the mixer as if it were a real target frequency. rffc5071_config_synth() doesn't reject it, it just crunches the math and comes out with some in-range but meaningless divider/register values, which is exactly the bogus FREQUENCY_LO/FREQUENCY_RF (and derived ROTATION/LPF settings) shown in the register dumps on the issue. Once one auto-tune has happened, freq_lo holds a sane prior value, so the same bug quietly does nothing useful (it just re-tunes to the old LO before the later "compute precise LO" logic corrects it), which is why "explicit tune after auto-tune" looks fine and only "explicit tune right after reset" breaks.

The IF branch just above already handles this correctly:

if (requested_if != RADIO_UNSET) {
    freq_if = max283x_set_frequency(&max283x, requested_if, false);
}

This change makes the LO branch consistent with that, passing requested_lo instead of freq_lo. One-line fix, nothing else touched.

I checked the two in-flight PRs that also touch tuning code (#1772, #1774) in case this was already covered there - neither modifies radio_update_frequency, mixer_set_frequency, or anything around requested_lo/freq_lo, so this is independent of that series and doesn't conflict with it.

I don't have a HackRF on hand to flash right now, so this is reasoned from the code path and the register dumps already in the issue, not verified on hardware. To confirm: reset the device, then set center frequency with explicit IF/LO (hackrf_transfer -i ... -o ... -m 1) and check that FREQUENCY_LO/FREQUENCY_RF/ROTATION come out matching an auto-tune to the same frequency, instead of the ~160 MHz garbage currently seen on that path. Also worth re-running the "auto-tune" and "explicit after auto-tune" cases from the issue to make sure they're unaffected. I also don't have the ARM toolchain set up here (no arm-none-eabi-gcc/cmake), so this hasn't been compiled either, just read through carefully against both call sites and the register dumps.

If CLKIN was in use but the external clock disappeared since the
last transceiver operation, transceiver_startup() would tune the
RFFC5071/MAX283x first and only call activate_best_clock_source()
afterward. The Si5351C fallback to XTAL disables outputs, changes
the PLL feedback divider, and resets the PLL, so tuning that ran
before the fallback was relocking against a reference that was
about to glitch out from under it. Move the clock source check to
the front of transceiver_startup() so the reference is stable by
the time radio_switch_opmode() tunes.

Fixes greatscottgadgets#1719.
@mossmann

mossmann commented Jul 6, 2026

Copy link
Copy Markdown
Member

We do not accept LLM-generated contributions.

@mossmann mossmann closed this Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Explicit tuning following device reset no longer configures the correct center frequency on pre-release builds.

2 participants