Skip to content

IC-7600: stale IC-7200 leftovers in the .rig file (fix confirmed working) + three related memory save/recall bugs #108

Closed

Description

@karlskontorp

Sorry for another long one — this repo has clearly had a lot of careful work put into it, and I want to be upfront that some of this is source-reading rather than exhaustive hardware testing, so please treat all of it as "here's what we think we're seeing," not a demand. Happy to be told any part of this is wrong or already known.

Part 1: MemFormat / VFO A-B frequency tracking — fix already applied locally, confirmed working

While digging into why VFO A and VFO B always showed the same frequency, and separately why saved memory channels came back with blank names, we think we found that rigs/IC-7600.rig has a few fields that look copy-pasted from rigs/IC-7200.rig and never updated for the IC-7600's actual, richer command set:

  • MemFormat (line 25) was byte-for-byte identical to IC-7200.rig's — missing the memory-name and tone/TSQL fields the IC-7600 actually has (per the official IC-7600 CI-V manual, memory content command 1A 00, page 177 in our copy).
  • Commands\58 (Memory Contents)'s Max was 201, also copied from IC-7200, rather than matching this file's own correctly-set Memories=101.
  • Commands\72/73 (what would become Selected Freq/Unselected Freq, CI-V 0x25) were present but disabled with a comment saying SET isn't implemented on this rig — we think the disabled version may have been shaped like IC-7610's single-command 0x25 (no explicit 00/01 sub-byte), rather than the explicit-subcommand form IC-7300.rig already uses successfully. We can't be sure that's the actual reason SET was disabled, but it seemed worth mentioning.

We compared this against the official IC-7600 CI-V reference (main manual + the firmware V2.00 addendum) and against IC-7300.rig/IC-7610.rig's equivalent, working fields, and applied this locally:

MemFormat=%1.2b %3.1c %4.5f %9.1g %10.1h %11.1k %12.3n %15.3o %18.10z

Commands\58\Max=101 (was 201)

Commands\72\Type=Selected Freq
Commands\72\String=\x25\x00
Commands\72\GetCommand=true
Commands\72\SetCommand=false

Commands\73\Type=Unselected Freq
Commands\73\String=\x25\x01
Commands\73\GetCommand=true
Commands\73\SetCommand=false

Commands\76\Type=Selected Mode
Commands\76\String=\x26\x00
Commands\76\GetCommand=true
Commands\76\SetCommand=false

Commands\77\Type=Unselected Mode
Commands\77\String=\x26\x01
Commands\77\GetCommand=true
Commands\77\SetCommand=false

(plus matching Periodic entries for the new Selected/Unselected Freq+Mode commands, replacing the old plain Freq Get/Mode Get polls)

We've since tested this on a real IC-7600 and can confirm: VFO A and VFO B now track independently and correctly, and saving different frequencies to different memory channels now works (previously the write silently failed due to the truncated MemFormat payload). We deliberately left SetCommand=false on 0x25/0x26 since the manual says "send/read" but we don't have independent confirmation the SET direction is safe/correct on this rig — GetCommand is the part we're confident about.

We know real hardware CI-V behavior is something only you can fully verify against Icom's engineering notes, so please treat the above as a starting point rather than a finished patch.

Part 2: Three further bugs found while testing memory recall (not related to Part 1)

With Part 1's fix in place, memory save/recall became usable enough to notice these — all three seem to be pre-existing, general wfweb behavior, not specific to our local .rig changes. We think they compound each other, which made the symptoms hard to pin down at first ("sometimes it saves, sometimes it doesn't, no clear pattern").

2a. Entering MEM mode appears to mislabel the recalled memory's frequency as "VFO A"

As best we can tell from reading src/webserver.cpp and src/cachingqueue.cpp:

  • Entering MEM mode (selectVFO('MEM') in the UI) sends a bare CI-V 08 (no channel number) — which is genuine, expected radio behavior: the rig switches to whatever memory channel it last had selected internally and displays that frequency.
  • getVfoCommand() picks funcSelectedFreq (0x25 0x00) only while rigState.vfoMode == vfoModeVfo. Once the rig reports it's in memory mode, it looks like the code falls back to a generic "current displayed frequency" query instead.
  • receiveCache()'s generic frequency-reply handler then appears to write that value into vfoAFrequency unconditionally, with no check on rigState.vfoMode — so the recalled memory channel's frequency gets sent to the browser labeled as VFO A's frequency.
  • We think this same path is also what writeMemory() uses to source the frequency for a save — so if a save happens shortly after entering MEM mode, it may capture the memory-preview frequency rather than whatever was actually last dialed into VFO A, depending on poll timing.

This would explain "the frequency in memory channel 1 sometimes shows up in VFO A," and why save reliability seemed to depend on exact timing rather than anything about the channel itself.

2b. Command-queue dedup key doesn't appear to include the payload

queueItem::operator== in include/cachingqueue.h looks like it compares only (command, receiver, recurring) — not the actual parameter/value being sent. If that's right, addUnique() calls for funcMemoryContents (used by save, clear, and the per-channel memory-list scan) would all share the same identity regardless of which channel or value they carry, so a save/clear/scan-read landing close together in time could silently evict a still-pending command for a different channel before it's transmitted — with nothing surfaced to the log or the browser.

2c. The memory list's "next free channel" picker may read a cache that's mid-rebuild

refreshMemories() in resources/web/index.html appears to clear the browser's local memoryChannels object synchronously, then repopulate it gradually as the backend scans channels one at a time (roughly one every 500ms based on the timer we found). Since a save also triggers this same rescan on a 500ms delay, clicking "save" again (or delete) before the rescan has finished repopulating the list could mean nextFreeMemoryChannel() is working from an incomplete picture — which might explain the trouble reported when deleting all channels and then re-adding them.

We haven't attempted fixes for 2a/2b/2c ourselves — we wanted to describe what we found and let you decide the right approach, especially since 2b in particular sounds like it could have implications beyond just memory handling if addUnique() is used the same way elsewhere.

Thank you again for your patience with these reports — please let us know if it'd help to get more specific logs/traces from the real IC-7600 for any of this.

Activity

  1. adecarolis commented on Sep 20, 2026

    @adecarolis
    Owner

    Thanks for the careful report and the hardware test. Everything in it checked out, with one correction on the VFO part, and there is a test build ready:

    Development Build (fix/ic7600-mainsub)
    https://github.com/adecarolis/wfweb/releases/tag/dev-fix/ic7600-mainsub

    For your Pi: wfweb_0.9.0-dev-fix-ic7600-mainsub-debian13_arm64.deb. The package version is still 0.9.0, so install with sudo apt install --reinstall ./wfweb_0.9.0-dev-fix-ic7600-mainsub-debian13_arm64.deb. Please also remove any hand-edited IC-7600.rig from ~/.local/share/wfweb/wfweb/rigs/ first, otherwise it wins over the installed file. The log should then show the rig file loading as version 2.07.

    Part 1, MemFormat. Confirmed against the memory-contents layout in both the 2009 and 2015 manuals. Your line is byte for byte what the radio expects, and it was the IC-7200's line before, which is why names came back blank and writes were refused. Merged as you proposed, along with the Max fix.

    Part 1, 0x25/0x26. Here the shape is slightly different. The IC-7600 has no VFO A/B at all: like the IC-7610 it has a MAIN and a SUB band. Command 07 only offers exchange, equalize, dual-watch and main/sub select (D0/D1), and the 25/26 sub-byte is the band (00 = MAIN, 01 = SUB), not "selected/unselected". Your layout labels correctly while MAIN is selected, but after selecting SUB the two readouts swap names. The build models the radio as Main/Sub, the same way wfweb already handles the IC-7610 and the way Hamlib treats the 7600. In the browser the VFO tile now reads MAIN/SUB, switches the band on the radio (it silently did nothing before, since the file had no VFO select at all), and each readout tracks its own band.

    One consequence: 25/26 exist only from firmware 2.00, and this build polls them. A 7600 on older firmware will refuse them and lose frequency polling, so 2.00 is required from here on. You are on 2.00, so nothing to do.

    2a, 2b, 2c. All three confirmed and fixed in this build. 2c is very likely what made saves feel random: every save triggered a full rescan that wiped the list, and a second save during those ten to twenty seconds proposed a channel the scan had not reached yet and overwrote it. The list now stays put during a rescan and "+ Save" waits for the first read of the group. 2b was real but narrow, since only memory commands are addressed by channel; those now bypass the dedup. 2a was cosmetic: in memory mode the channel frequency no longer lands in the VFO slots.

    One question, since it can also produce a "wrong frequency saved": is CI-V Transceive ON in the radio's menu? Without it, a dial change on the front panel reaches wfweb only on the next poll, which can be several seconds later on this radio.

    What I would like confirmed on the real radio: MAIN and SUB readouts independent and the tile switching bands, memory save with a name, recall, rename and clear, and two saves in a row landing on two different channels.

  2. karlskontorp commented on Sep 21, 2026

    @karlskontorp
    Author

    Thanks for the quick turnaround and the clear explanation of MAIN/SUB — that makes sense, and the correction on 0x25/0x26 was helpful.

    Tested the dev build on a real IC-7600 (firmware 2.00, CI-V Transceive ON), Raspberry Pi 3, Debian 13 arm64. The installed IC-7600.rig is Version=2.07 and there is no user override, so everything below ran on the packaged file.

    Works as described

    • MAIN and SUB readouts are independent: each tracks its own band, mode and frequency.
    • The VFO tile switches between MAIN and SUB on the radio, and the small text under the frequency follows correctly.
    • Memory: save with frequency and name works, recall works, rename works, clear works. In the memory panel, choosing "VFO A" or "VFO B" and then clicking a channel recalls the channel into MAIN or SUB respectively.
    • Consecutive saves land in consecutive channels, the "Save to Ch" field advances by itself, and the list grows and gets a scrollbar after about 10 channels. My first impression was that channel 4 overwrote channel 3, but that was most likely me saving while the rescan was still running; I could not reproduce it once I waited for the list to settle.

    One inconsistency when saving while SUB is selected

    Setup: MAIN 14.200 MHz USB, SUB 7.100 MHz LSB.

    • Save while MAIN is selected: the radio's memory list shows 14.200 MHz USB, FIL1, name "14.200 USB". Consistent.
    • Save while SUB is selected: the radio's memory list shows 14.200 MHz USB, FIL1, but the name is "7.100 LSB".

    So the stored frequency and mode come from MAIN, while the auto-generated name comes from the SUB readout that is on screen. As far as I can tell from reading writeMemory, the frequency and mode are taken from the receiver-0 cache, and the name from the frequency currently shown. It took me a while to work out that the text after FIL1 on the radio is the channel name and not a second frequency. On this radio a memory channel only holds one frequency and mode (the MemFormat has a single frequency field), so I assume the intended behavior is that the save follows the selected band. If so, saving from SUB should store 7.100 LSB. If not, the auto-name should at least be built from the values that are actually written.

    Small suggestions, all cosmetic

    1. In the memory panel the buttons are labelled "VFO A" / "VFO B". On the IC-7600 they could read "MAIN" / "SUB", like the VFO tile does.
    2. The channel name is shown as the main line of each row, and for auto-named channels it looks exactly like a frequency ("14.200 USB"). Together with the real frequency in the small line below, this was confusing. A label such as "name" or "free text" on the field, or showing the frequency first and the name as a tag, would make it clear which is which.

    Feature request: a way to reach 60 m (and the GENE key)

    Would it be possible to add a key for 60 m to the band picker? I know the 60 m allocations differ between countries and regions, but WRC-15 gave the amateur service secondary status in 5351.5–5366.5 kHz, and many of us can now use it.

    I saw in the BAND_KEYS comment that 60 m is left out because Icom panels have no dedicated key for it, and that it is reached through F-INP instead. That is true for a 60 m key, but the radio does have a GENE key, and as far as I can tell from using it, it behaves exactly like the other band keys, including the band stacking register. The only difference is that GENE covers all of HF plus 6 m instead of one amateur band. If I set GENE to 60 m, it acts as if there had been a 60 m key. Because it has three stack registers, it can also hold three different frequencies, depending on what I entered the last three times I used it.

    So one option would be a GENE key in the web band picker, working like the other band keys, which would cover 60 m and anything else outside the amateur bands. Another would be a dedicated 60 m key that lands on 5351.5 kHz the first time. The IC-7600 rig file already has a band entry around 5.25–5.45 MHz (Bands\11), so the radio knows that range. Either would be very welcome, though I understand if you would rather keep the picker limited to the amateur bands. Not urgent.

    Minor note, not a bug

    I tried to confirm the rig file version from the journal, but "Found Rig ... version 2.07" is a qDebug line, so it only appears with debug logging on. I checked the file directly instead. You may want it at info level if you ask users to confirm the version from the log.

    Thanks again for all the work on this.

  3. adecarolis commented on Sep 22, 2026

    @adecarolis
    Owner

    Thank you for the thorough hardware test, and for pinning down the save inconsistency so precisely. Your reading of writeMemory was right, and the GENE observation was right too.

    A new build is on the same release, rebuilt from the branch a few minutes ago:

    Development Build (fix/ic7600-mainsub)
    https://github.com/adecarolis/wfweb/releases/tag/dev-fix/ic7600-mainsub

    Same file for your Pi, wfweb_0.9.0-dev-fix-ic7600-mainsub-debian13_arm64.deb, same sudo apt install --reinstall ./<file> since the package version does not change.

    Saving while SUB is selected. Fixed, and it was exactly as you described. The write asked the cache for receiver 0, which on a Main/Sub rig is always MAIN, while everything else picks the receiver from the selected band. That is why recall behaved and save did not. It now takes the receiver from the band you are on, for the repeater tone, shift and offset as well as frequency and mode. The name needed no separate fix: it was only ever disagreeing because the stored values were wrong, so correcting the write makes both agree. Worth noting this was not new, and it affects the IC-7610 the same way. It only became reachable on the IC-7600 once the VFO tile started switching bands instead of silently doing nothing.

    The MAIN/SUB labels. Done. The memory panel's selector now reads MAIN and SUB on this radio, matching the VFO tile and your front panel. Rigs that really do have VFO A and B still say so.

    The name that looks like a frequency. Done, and your diagnosis of why it reads badly was the useful part. The save still writes that label to the radio so its own memory list is not blank, but the browser now recognises a label that merely restates the frequency below it and shows the row in its frequency-only form instead. A name you type is unaffected and still sits above the frequency. The rename field also has a "channel name" placeholder now, so it is clear what you are editing.

    The log level. Done, though not where you might expect. The line you found is part of the scan over the rig directory and fires once per file, so raising it would add about thirty lines to every startup. The version now rides on the line that names the rig actually loaded, which was already at info level. You should see Loading Rig: IC-7600 version 2.07 from ... without debug logging.

    60 m and GENE. I checked the rig file against what you described and it holds up: 60 m has no band stacking register, which is why it has no key, while GENE has one and covers 10 kHz to 60 MHz. I have split that off as its own issue rather than folding it in here, since it is a design question about what belongs in an amateur-band picker rather than a bug.

    One thing I did not change, in case you notice it: the status the browser receives still reports the MAIN frequency while SUB is selected. The main display does not use that field, which is why your readouts looked right, so it is cosmetic rather than something you would see. I would rather fix it separately than widen this build.

    If you have time, the things worth retesting are: saving while SUB is selected, which should now store the SUB frequency, mode and a matching name; the MAIN/SUB buttons; that channel rows no longer show a frequency where the name goes; and the version line in the log. If those all look right I will merge this.

  4. karlskontorp commented on Sep 23, 2026

    @karlskontorp
    Author

    Thanks for the detailed explanation and the quick turnaround — retested all four points on the real IC-7600.

    • Saving while SUB is selected: now stores the SUB frequency, mode and a matching name. Works.
    • MAIN/SUB buttons in the memory panel: correct labels, work as expected.
    • Channel rows no longer show a frequency where the name goes: works. One small observation, not a bug: the "channel name" placeholder only appears once the field is actually empty. Opening rename on a channel that still has text in it (including an old auto-generated frequency-like name) shows that text, not the placeholder, until I delete it first. That's normal placeholder behaviour, just flagging it in case a persistent label rather than a placeholder was the intent.
    • Version line: "Loading Rig: IC-7600 version 2.07" shows in the log without --debug. Works.

    All four look good from here. Thanks again for fixing this so quickly.

  5. adecarolis commented on Sep 25, 2026

    @adecarolis
    Owner

    Thanks for going back to the radio and checking all four. That is now merged, and it will ship in the next release.

    For the record, what this issue produced:

    • IC-7600.rig no longer carries IC-7200 leftovers: your MemFormat, the memory count, and the radio modelled as the MAIN/SUB rig it is, with 0x25/0x26 on firmware 2.00.
    • The memory list survives a rescan, so a save no longer overwrites a channel the scan had not reached yet, and memory mode no longer parks the channel's frequency in a VFO readout.
    • Saving while SUB is selected stores the SUB frequency, mode and name.
    • MAIN/SUB labels in the memory panel, and the auto-generated label no longer shown where a channel name goes.
    • The rig file version is visible in the log without debug logging.

    On the placeholder: you are right that it is ordinary placeholder behaviour, and it was what I intended. The field only ever holds the channel name, so once there is text in it there is nothing to disambiguate. If it turns out to be confusing in practice, say so and I will look at a persistent label.

    Your 60 m request is now #116, with the GENE stacking-register detail you found. It holds up beyond the IC-7600, though not universally: the IC-7610 declares no stacking register for GENE, so any key would have to be gated on each rig's own band table. What remains is the design question of whether a general-coverage key belongs in an otherwise amateur-band picker.

    Closing this one. Thank you for the unusually careful reports throughout, and for testing each build on real hardware. That is what made these fixable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions