Skip to content

DAX channel and IQ channel per-slice settings are not persisted #1221

Description

@k0otc

### 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

  1. Launch AetherSDR 0.8.10 and connect to the FLEX-8600.
  2. Create or activate one or more slices.
  3. In the slice controls, set a non-default DAX channel (e.g., DAX ch = 2) and IQ Ch for that slice.
  4. (Optional) Load or save a Global Profile via the profile UI.
  5. Close AetherSDR completely.
  6. Re-launch AetherSDR and reconnect to the same radio.
  7. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    aetherclaude-eligibleIssue approved for AetherClaude automated agentaudioAudio engine and streamingbugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions