Skip to content

Compression gauge broken on multi-slice sessions — m_compPeakIdx/m_afterEqIdx use last-match-wins scan, always resolve to the highest-numbered slice's TX waveform block #2040

@rnash2

Description

@rnash2

Report preparation

  • I used the AI-assisted bug report tool (Help → Support → File an Issue)
  • I have attached a support bundle or log file

What happened?

What happened?

The FLEX-6600 firmware builds the meter manifest dynamically based on the number of slices present at connection time. The manifest contains exactly 10 + (N × 22) slots, where N is the active slice count. Each slice contributes a block of 10 RX meters (src=SLC, num=slice_index) and 12 TX waveform pipeline meters (src=TX-, num=8+slice_index), appended in ascending slice order:

Slices active | Total slots | SC_MIC / COMPPEAK manifest IDs -- | -- | -- 1 | 32 | 22 / 23 2 | 54 | 22 / 23, 44 / 45 3 | 76 | 22 / 23, 44 / 45, 66 / 67 4 | 98 | 22 / 23, 44 / 45, 66 / 67, 88 / 89

SC_MIC and COMPPEAK each appear once per slice in the manifest. MeterModel resolves m_afterEqIdx (SC_MIC on FLEX-6000, AFTEREQ on FLEX-8000) and m_compPeakIdx (COMPPEAK) by scanning the manifest for a matching name, assigning on each hit with the last match winning. Because the manifest is ordered lowest-slice-first, the final values always correspond to the highest-numbered slice's TX waveform block, regardless of which slice is the active TX slice.

On a two-slice session with slice 0 as the active TX slice:

m_afterEqIdx  = 44   (TX- num=9 → slice 1's SC_MIC)
m_compPeakIdx = 45   (TX- num=9 → slice 1's COMPPEAK)

Since v0.8.19 (#1682), the compression gauge displays COMPPEAK - AFTEREQ (gain reduction in dB). The radio's VITA-49 PCC 0x8002 stream sends both meter values under the manifest IDs of the active TX slice's waveform block — IDs 22 and 23 when slice 0 is TX. These arrive at MeterModel::updateValues(), find no match against 44/45, and are silently discarded. The compression gauge displays nothing.

Verified: creating four slices and making slice 3 (the last) the active TX slice causes the compression gauge to work correctly, because m_compPeakIdx = 89 and m_afterEqIdx = 88 accidentally match the meter IDs the radio is streaming under slice 3's TX chain. Any other TX slice → silent mismatch → dead gauge.

The VITA-49 dispatch, unit conversion, gain-reduction subtraction, and gauge rendering are all confirmed correct. The fault is entirely in index resolution.

Note: Changes to meterModel.cpp were made on main last night targeting v0.9.0. Please verify whether those changes partially or fully address this before applying the fix below.

What did you expect?

The compression gauge should display real-time gain-reduction activity for whichever slice is the active TX slice, regardless of how many slices exist or what position that slice occupies in the manifest. m_compPeakIdx and m_afterEqIdx should resolve to the manifest IDs belonging to the active TX slice and should update dynamically if TX assignment changes at runtime.

Developer Notes
Root cause — confirmed, scope fully bounded
The bug is entirely in MeterModel's index resolution for m_compPeakIdx and m_afterEqIdx. The v0.8.19 gain-reduction fix (#1682) correctly computes COMPPEAK - AFTEREQ but both operands are looked up via the same last-match-wins scan, so on any multi-slice session both operands are sourced from the wrong slice's TX chain. The subtraction produces zero (or a near-zero garbage value) rather than the actual gain reduction.
Radio family meter name differences
The pre-compression input meter name differs by radio family and must be detected from the manifest — do not branch on radio model:
Radio familyManifest name for pre-compression inputFLEX-6000 series (e.g. 6600)SC_MICFLEX-8000 series (e.g. 8600)AFTEREQ
Populating m_afterEqIdxBySlice on whichever name appears handles both families and any future firmware rename without additional conditional logic.
num field semantics — confirmed from full 98-slot manifest
srcnum valueMeaningSLC0, 1, 2, 3Slice index directlyTX- waveform chain8, 9, 10, 11Waveform pipeline slot; slice_index = num - 8 on FLEX-6600TX- hardware (FWDPWR, REFPWR, SWR, PATEMP, HWALC)1–5Hardware meters; not slice-specificRADvariousRadio-global; not slice-specific
The waveform base offset of 8 must be derived from the manifest (the minimum num seen among TX- waveform chain meters, distinguished from hardware meters by num >= 8) rather than hardcoded, so the fix remains correct on FLEX-8000 series hardware if the offset differs.
Required fix

  1. Replace scalar indexes with per-slice maps in meterModel.h:
    cpp// Remove:
    int m_compPeakIdx = -1;
    int m_afterEqIdx = -1;

// Add:
QMap<int, int> m_compPeakIdxBySlice; // slice index → manifest slot ID
QMap<int, int> m_afterEqIdxBySlice; // slice index → manifest slot ID
int m_txWaveformSlotBase = -1; // lowest TX- waveform num seen (8 on FLEX-6600)
2. Populate at manifest parse time in defineMeter():
cpp// TX- waveform chain meters have num >= 8.
// Hardware TX- meters (FWDPWR, REFPWR, SWR, PATEMP, HWALC) use num 1–5.
if (src == "TX-" && num >= 8) {
if (m_txWaveformSlotBase < 0) m_txWaveformSlotBase = num;
int sliceIdx = num - m_txWaveformSlotBase;
if (nam == "COMPPEAK")
m_compPeakIdxBySlice[sliceIdx] = manifestSlotId;
if (nam == "SC_MIC" || nam == "AFTEREQ")
m_afterEqIdxBySlice[sliceIdx] = manifestSlotId;
}
3. Resolve at dispatch time against the active TX slice:
cppint txSlice = m_radioModel->activeTxSliceNum();
int compIdx = m_compPeakIdxBySlice.value(txSlice, -1);
int afterIdx = m_afterEqIdxBySlice.value(txSlice, -1);
// Both -1 guard must be checked before computing gain reduction:
// gainReduction = compValue - afterEqValue (existing #1682 logic)
4. Handle runtime TX reassignment:
When SliceModel::applyStatus() processes a tx=1 status change, RadioModel should emit activeTxSliceChanged(int sliceIdx). Since the fix resolves via activeTxSliceNum() at dispatch time, the gauge automatically tracks the correct slice after TX moves without requiring a reconnect, as long as activeTxSliceNum() is kept current.
5. Clear maps on disconnect:
clearMeters() must reset m_compPeakIdxBySlice, m_afterEqIdxBySlice, and m_txWaveformSlotBase alongside the rest of the registry so a reconnect with a different slice count or radio model produces a clean map.
Files to inspect
FileChange neededsrc/models/meterModel.hReplace m_compPeakIdx, m_afterEqIdx scalar int declarations with QMap<int,int> per-slice maps; add m_txWaveformSlotBasesrc/models/meterModel.cppdefineMeter() — replace last-match-wins assignment with per-slice map inserts for COMPPEAK, SC_MIC, AFTEREQ; add compPeakIdxForSlice(int) / afterEqIdxForSlice(int) accessors; clearMeters() — reset maps and base offsetsrc/models/radioModel.cppAdd or verify activeTxSliceNum() returning the index of the slice with tx=1src/models/sliceModel.cppConfirm tx= field in applyStatus() emits a change signal so activeTxSliceNum() is always currentsrc/gui/PhoneCwApplet.cppupdateMeters() — replace scalar index reads with compPeakIdxForSlice(activeTxSliceNum()) and afterEqIdxForSlice(activeTxSliceNum()); guard against -1 on both before computing gain reduction
Logging to enable
Enable Meters in Help → Support. After the fix, the log should show per-slice map entries populated for each TX waveform slot in the manifest, with compPeakIdxForSlice(0) resolving to 23 on a session where slice 0 is the active TX slice.

meters.txt

Steps to reproduce

Steps to Reproduce

Connect AetherSDR 0.8.21 to a FLEX-6600 running firmware 4.1.5.39794.
Create two or more slices. Leave slice 0 as the active TX slice (default).
Enable the Meters log category in Help → Support and reconnect.
Confirm the log shows Discovery: Assigned m_compPeakIdx with a value greater than 23 (e.g. 45 on a two-slice session).
Key the radio in USB mode with PROC/compander enabled and drive the microphone.
Observe the compression gauge in the P/CW applet — no movement.
To confirm root cause: move TX assignment to the highest-numbered slice without reconnecting. The compression gauge immediately begins working — the VITA-49 stream now sends meter IDs that match m_compPeakIdx and m_afterEqIdx.
To confirm single-slice is unaffected: disconnect, remove all but one slice, reconnect. m_compPeakIdx = 23, compression gauge works correctly.

AetherSDR version

0.9.0

Radio model & firmware

Radio: FLEX-6600 Firmware: 4.1.5.39794

Operating system

Windows

OS version and hardware

Windows 11-Pro 25H2, Qt: 6.7.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclaude-activeAetherClaude is actively working on this issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions