### Title:
DAX channel and IQ channel per-slice settings are not persisted (must be re-entered on every startup)
### What happened?
After setting a DAX channel (audio DAX) and IQ channel for any slice, the values are lost when AetherSDR is closed and restarted. On the next launch and reconnect to the radio, every slice defaults back to DAX ch = 0 (and whatever the default IQ Ch is), requiring manual re-entry of the correct DAX ch and IQ Ch values for each slice every single time the application starts.
This happens even though the rest of the slice state (frequency, mode, filter, etc.) appears to restore correctly via radio status messages or global-profile loading. The settings are successfully sent to the radio while the program is running (slice set <id> dax=…), but they are never written to persistent storage.
### What did you expect?
DAX channel and IQ channel assignments should be treated as part of each slice’s persistent configuration and saved together with the Global Profile (via AppSettings). On application startup, profile load, or slice creation, these values should be automatically restored so that the previous per-slice DAX/IQ routing is immediately active without manual intervention.
### Steps to reproduce
- Launch AetherSDR 0.8.10 and connect to the FLEX-8600.
- Create or activate one or more slices.
- In the slice controls, set a non-default DAX channel (e.g., DAX ch = 2) and IQ Ch for that slice.
- (Optional) Load or save a Global Profile via the profile UI.
- Close AetherSDR completely.
- Re-launch AetherSDR and reconnect to the same radio.
- Observe that every slice has DAX ch = 0 (and default IQ Ch) again; the previously chosen values are gone.
### Radio model & firmware
FLEX-8600 fw 4.1.5.39794
### OS & version
Windows (AetherSDR 0.8.10, Qt 6.7.3)
### Developer Notes
Most likely involved source files & functions (based on codebase review of main branch):
-
src/models/SliceModel.cpp
setDaxChannel(int ch) – clamps value, sends slice set <id> dax=<ch> command, emits daxChannelChanged (no AppSettings write).
applyStatus(...) – parses "dax" key from radio status and updates m_daxChannel (≈ line 150-160).
-
src/models/RadioModel.cpp
loadGlobalProfile(const QString& name) – only sends radio command profile global load "…".
createDefaultSlice() – creates slice with freq/mode/antenna but no dax= or IQ parameters.
handleSliceStatus() – instantiates SliceModel objects and wires signals (no persistence).
troubleshootingSnapshot() JSON builder – does serialize sliceModel->daxChannel() into the debug snapshot (but this is read-only, not used for restore).
-
src/models/DaxIqModel.cpp / src/models/DaxIqModel.h – manages the 4 IQ streams (IqStream struct with panId, channel, active, etc.). No slice linkage or AppSettings persistence visible.
-
src/core/AppSettings.cpp / src/core/AppSettings.h – the only allowed persistence layer (XML ~/.config/AetherSDR/AetherSDR.settings, setValue/stationValue, save()). No keys for per-slice DAX or IQ are ever written or read for slices.
Potential root cause
Slice DAX/IQ settings live only in-memory (SliceModel::m_daxChannel and DaxIqModel::m_streams[]) and are synchronized to the radio via protocol commands and status messages. There is no hook that calls AppSettings::instance().setValue(...) (or setStationValue) when daxChannelChanged / IQ stream state changes, nor any restore logic in RadioModel::loadGlobalProfile, handleSliceStatus, or slice creation paths. Global-profile handling is radio-side only; client-side per-slice overrides (DAX ch + IQ Ch) are never persisted to AppSettings. This matches the “use AppSettings, never QSettings” rule in CLAUDE.md / CONTRIBUTING.md, but the implementation for these specific fields is missing.
Recommended diagnostic logging
In Help → Support, enable the following logging categories (or just “All” for a full bundle):
radio / protocol (to capture slice commands and status)
model / slice (SliceModel / RadioModel state)
settings / persist (AppSettings load/save)
dax / iq (if present; otherwise audio)
Then reproduce the issue and attach the generated support bundle (SupportBundle::create(...) in src/core/SupportBundle.cpp). This should show the missing AppSettings writes for DAX/IQ keys and confirm whether the radio is returning the expected dax= values on reconnect.
support-bundle-20260412-070547.zip
### Title:
DAX channel and IQ channel per-slice settings are not persisted (must be re-entered on every startup)
### What happened?
After setting a DAX channel (audio DAX) and IQ channel for any slice, the values are lost when AetherSDR is closed and restarted. On the next launch and reconnect to the radio, every slice defaults back to DAX ch = 0 (and whatever the default IQ Ch is), requiring manual re-entry of the correct DAX ch and IQ Ch values for each slice every single time the application starts.
This happens even though the rest of the slice state (frequency, mode, filter, etc.) appears to restore correctly via radio status messages or global-profile loading. The settings are successfully sent to the radio while the program is running (
slice set <id> dax=…), but they are never written to persistent storage.### What did you expect?
DAX channel and IQ channel assignments should be treated as part of each slice’s persistent configuration and saved together with the Global Profile (via
AppSettings). On application startup, profile load, or slice creation, these values should be automatically restored so that the previous per-slice DAX/IQ routing is immediately active without manual intervention.### Steps to reproduce
### Radio model & firmware
FLEX-8600 fw 4.1.5.39794
### OS & version
Windows (AetherSDR 0.8.10, Qt 6.7.3)
### Developer Notes
Most likely involved source files & functions (based on codebase review of
mainbranch):src/models/SliceModel.cppsetDaxChannel(int ch)– clamps value, sendsslice set <id> dax=<ch>command, emitsdaxChannelChanged(noAppSettingswrite).applyStatus(...)– parses"dax"key from radio status and updatesm_daxChannel(≈ line 150-160).src/models/RadioModel.cpploadGlobalProfile(const QString& name)– only sends radio commandprofile global load "…".createDefaultSlice()– creates slice with freq/mode/antenna but nodax=or IQ parameters.handleSliceStatus()– instantiatesSliceModelobjects and wires signals (no persistence).troubleshootingSnapshot()JSON builder – does serializesliceModel->daxChannel()into the debug snapshot (but this is read-only, not used for restore).src/models/DaxIqModel.cpp/src/models/DaxIqModel.h– manages the 4 IQ streams (IqStreamstruct withpanId,channel,active, etc.). No slice linkage orAppSettingspersistence visible.src/core/AppSettings.cpp/src/core/AppSettings.h– the only allowed persistence layer (XML~/.config/AetherSDR/AetherSDR.settings,setValue/stationValue,save()). No keys for per-slice DAX or IQ are ever written or read for slices.Potential root cause
Slice DAX/IQ settings live only in-memory (
SliceModel::m_daxChannelandDaxIqModel::m_streams[]) and are synchronized to the radio via protocol commands and status messages. There is no hook that callsAppSettings::instance().setValue(...)(orsetStationValue) whendaxChannelChanged/ IQ stream state changes, nor any restore logic inRadioModel::loadGlobalProfile,handleSliceStatus, or slice creation paths. Global-profile handling is radio-side only; client-side per-slice overrides (DAX ch + IQ Ch) are never persisted toAppSettings. This matches the “useAppSettings, neverQSettings” rule inCLAUDE.md/CONTRIBUTING.md, but the implementation for these specific fields is missing.Recommended diagnostic logging
In Help → Support, enable the following logging categories (or just “All” for a full bundle):
radio/protocol(to capture slice commands and status)model/slice(SliceModel / RadioModel state)settings/persist(AppSettings load/save)dax/iq(if present; otherwiseaudio)Then reproduce the issue and attach the generated support bundle (
SupportBundle::create(...)insrc/core/SupportBundle.cpp). This should show the missingAppSettingswrites for DAX/IQ keys and confirm whether the radio is returning the expecteddax=values on reconnect.support-bundle-20260412-070547.zip