Skip to content

Rig: Send the frequency once more after the mode when tuning to a spot - #1191

Open
oh2gba wants to merge 1 commit into
foldynl:masterfrom
oh2gba:tune-freq-after-mode
Open

oh2gba wants to merge 1 commit into
foldynl:masterfrom
oh2gba:tune-freq-after-mode

Conversation

@oh2gba

@oh2gba oh2gba commented Oct 4, 2026 •

Copy link
Copy Markdown

When QLog tunes the rig to a DX spot it sends the frequency first and the mode second (the order chosen in #453, because a band change makes many rigs recall the mode last used on that band).

Some rigs move the dial together with the mode. The Yaesu FTDX series shifts it by the CW pitch when switching between SSB and CW, as long as the rig's menu item CW FREQ DISPLAY is set to PITCH OFFSET (its default). The result after a click on a CW spot from SSB: the rig sits a few hundred Hz next to the spot instead of on it. @aa5sh saw the same thing in #453 (28.462 became 28.461.620, the CW side tone), and switching the rig menu to DIRECT FREQ was the workaround at that time.

The change

Only the Hamlib driver changes, two files:

  • HamlibRigDrv::setFrequency remembers the frequency QLog asked for, but only when rig_set_freq returned success.
  • HamlibRigDrv::__setMode sends that frequency once more right after a successful mode command, so the sequence on a spot click becomes frequency, mode, frequency. This is what WSJT-X does as well (its commit 35e377d, quoted in Click on PHONE DX Spots sets wrong mode #453).
  • HamlibRigDrv::checkFreqChange forgets the remembered frequency as soon as a poll shows the operator has tuned elsewhere, so a manual mode change later on does not pull the rig back.

tuneDx and the other backends (OmniRig, FLRig, TCI) are not touched; they see exactly the commands they see today.

Reading the frequency back after the mode command instead does not work: Hamlib answers rig_get_freq from its cache for 500 ms after a set command, in the client library and again inside rigctld, so the read returns the frequency just set and not the moved dial.

Cost: one rig_set_freq per mode change that follows a frequency request. Rigs that do not move the dial receive a frequency they are already on.

This differs from the earlier attempt 3e37ec9 from #453, which looped inside setFrequency and re-sent the mode from there. Here the frequency and mode commands stay as they are; the driver only repeats the frequency after the mode.

Verification

  • Builds on Linux (Qt 6.8, Hamlib 4.6.2).
  • Tested on a Yaesu FTDX-101D via rigctld with CW FREQ DISPLAY = PITCH OFFSET: clicks between SSB, CW and FT8 spots on 20 m all end exactly on the spot frequency. The trace shows the sequence set frequency, set mode, set frequency for every click, all accepted by the rig, and the next poll reading exactly the spot frequency.
  • When the mode really changes, the dial is visibly off by the pitch for about 400 ms before the second frequency command corrects it; this is the time QLog pauses after each rig command. Rigs that do not move the dial with the mode are not affected.
  • Not tested: other rig families, Windows, macOS.

@oh2gba
oh2gba force-pushed the tune-freq-after-mode branch from 61c3fff to d79c400 Compare October 4, 2026 13:13
@oh2gba
oh2gba marked this pull request as ready for review October 4, 2026 14:07

@foldynl foldynl left a comment •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Unfortunately, I'm not sure it's safe to accept it like this. See my comments.

Comment thread rig/drivers/HamlibRigDrv.cpp Outdated
{
int status = rig_set_freq(rig, RIG_VFO_CURR, newFreq);
isRigRespOK(status, tr("Set Frequency Error"), false);
dialMovedByMode = false;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this really be set if the rig_set_freq was executed successfully, meaning Hamlib returned success for rig_set_freq ?

Comment thread ui/NewContactWidget.cpp Outdated
// The frequency is therefore sent once more after the mode, so that
// the rig ends up exactly on the spot. The commands are queued, the
// order freq - mode - freq is kept.
rig->setFrequency(MHz2Hz(frequency - RigProfilesManager::instance()->getCurProfile1().ritOffset));

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit risky because you're introducing the setFreq call globally for all drivers. That means setFreq will be sent twice to OmniRig v1/v2, FLRig, and TCI. Are you sure these backends can handle this and will behave the same way after the change?

When QLog tunes the rig to a spot it sends the frequency first and
the mode second. The frequency has to go first, because a band change
makes many rigs recall the mode last used on that band (issue foldynl#453).

Some rigs move the dial together with the mode: the Yaesu FTDX series
shifts it by the CW pitch when switching between SSB and CW, so the
rig ended up a few hundred Hz next to the spot instead of on it.
WSJT-X handles the same behaviour by sending the frequency once more
after the mode.

The Hamlib driver now does the same by itself. It remembers the last
frequency QLog asked for, as long as rig_set_freq accepted it and no
poll has seen the operator tune elsewhere, and sends it once more
right after a successful mode command. Reading the dial back after
the mode command is no alternative, because Hamlib answers from its
cache for a while after a set command, both in the client and in
rigctld. Other rig backends are not touched.
@oh2gba
oh2gba force-pushed the tune-freq-after-mode branch from d79c400 to fac7da4 Compare October 4, 2026 17:40
@oh2gba

oh2gba commented Oct 4, 2026

Copy link
Copy Markdown
Author

Thanks for the review, both points were valid.

I moved the whole thing into the Hamlib driver and force-pushed. tuneDx is back to what master has, so OmniRig, FLRig and TCI see exactly the commands they see today. The driver now remembers the frequency QLog asked for, only when rig_set_freq returned success, and sends it once more right after a successful mode command. A poll that shows the operator has tuned elsewhere forgets it, so a manual mode change later does not pull the rig back.

Retested on the FTDX-101D via rigctld: SSB to CW and back lands on the spot.

Happy testing

@foldynl

foldynl commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Retested on the FTDX-101D via rigctld: SSB to CW and back lands on the spot.

Have you tested it with a direct connection as well? Rigctld sometimes has its own internal "algorithms"

@oh2gba

oh2gba commented Oct 5, 2026

Copy link
Copy Markdown
Author

Yes, tested, and it works for me, which of course is just a sample of one. Now also with a direct USB connection to the FTDX-101D: same result, SSB to CW and back lands on the spot.

Which brings up a question. Is there a beta channel for QLog? As far as I can see there is none, apart from the testing branch, which only people who build from source ever run. Would it be worth letting changes like this one sit in a beta for a while, so that a few more rigs and operators see them before they land in a release and break somebody's QLog? I would happily run such a beta.

73, John

@foldynl

foldynl commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Is there a beta channel for QLog?

Currently, there is no beta channel. That’s what the testing branch is for. I plan to release a beta, but only as an AppImage for Linux (I’m currently working on it, but it won’t be in this version, maybe the next one). Releasing isn’t just about putting out a version; it also means creating documentation and handling translations.

@oh2gba

oh2gba commented Oct 5, 2026 •

Copy link
Copy Markdown
Author

A beta AppImage would be great, count me in as a tester.

On documentation and translations, a few pointers, since that is the part that costs you time, not the release itself. Full disclosure: tokens were spent on this, I let an AI read the wiki against the code last night. The result: 36 pages, about half of them lag the code they describe, the QSO Detail, POTA and Export pages by 70 to 80 commits, the Rig page by 46 although you touched it in June, and three pages have not changed since 2023. Not for lack of effort, a hand-written wiki simply cannot keep up with a release every month or two.

And the readers were never there to begin with. Novick and Ward, Why don't people read the manual? (2006), watched people hit real problems with their software: about 1% were solved by opening the manual, 4% by the online help, the rest by trying things or asking someone. The someone is now an AI, so it makes sense to feed the AI instead of the reader. Two things exist today that could take the load off you: a wiki generated from the code, which DeepWiki does for any public repo, and questions answered straight from the repo and the wiki, which GitHub's own Copilot overview and Copilot Spaces already do. Translations the same way: AI-drafted .ts files for the translators to review instead of write. The manual gets generated at release time, the humans only check it.

Tokens are cheap, TTL is irreplaceable.

73, John

@foldynl

foldynl commented Oct 5, 2026

Copy link
Copy Markdown
Owner

AI tends to generate very extensive documentation. Yes, some parts of the wiki are "old" and some things are not fully described, but I try to keep it as up to date as possible, especially for the main changes.

The purpose of the wiki is not to describe every single button. Its purpose is to explain how things work when something is not immediately clear. I am not saying I always achieve that perfectly because I am not a native speaker , but that is the direction I am trying to follow.

When I look at AI-generated documentation today, I often start losing interest by the second long paragraph. And when there is something important in it, it can easily get buried and go unnoticed. Tokens may be cheap, but generating hundreds of pages of documentation just because it is cheap is not my goal.

As for translations, I already have something in the pipeline. I just have not had enough time to validate it properly yet. QLog is not the only thing that takes up my time.

As for AI, there is also the QLog-MCP server if you want to experiment with it further. Version 0.54 will add even more capabilities because there will be a communication bridge between QLog and QLog-MCP.

Maybe one day we will really reach the point where nothing more than an agent is needed, but we are not there yet.

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.

2 participants