Repository navigation
Experimental IC-7610 and IC-7760 dual-receiver Ethernet support #6910
Description
Adds an initial Ethernet/RS-BA1 bring-up path for the IC-7610 and IC-7760: two fixed MAIN/SUB receive slices and panadapters, native scope geometry, separate receive audio feeds plus a monitor mix, and one shared PTT/mono transmit-audio path. Both models are marked experimental.
Integrates the connection-dialog changes from #6885 and #6889.
Related issues
IC-7610 device reports:
- Icom 7610 - Spectrum display not on radio frequency #6871 — spectrum does not align with the receiver frequency.
- Icom 7610 - No computer sound output #6872 — missing or filtered computer receive audio.
- [bug]%20IC-7610%20v26.9.3%20%E2%80%94%20 #5714 — spectrum/waterfall displacement varies with the selected span.
- IC-7610 RX ERROR IN WATERFAL #5341 — waterfall displayed about 52 kHz above the received frequency.
- IC-7610: Waterfall has a shift of approx 38kHz #5154 — waterfall displayed about 38 kHz above the received frequency.
- [bug] IC-7610 - Watefall the signal shows on wrong freq. #5096 — spectrum/waterfall displayed about 23 kHz above the received frequency.
- Aether panafall show signal 10 khz higher than on radio ...radio is iocm7610 , runnuing mcos 26.2.2 aether 26.8.3 #5084 — panadapter/waterfall displayed about 10 kHz above the received frequency.
IC-7760 device reports and support evidence:
- [bug]%20Unknown%20Icom%20v26.9.2 Icom IC-7760 #5585 — unrecognized B2 identity and blank spectrum/waterfall.
- Information regarding implementing the Icom 7760 spectrum scope. #5280 — IC-7760 support information and measured 704-byte / 689-bin LAN scope frames.
Related Icom bring-up, control and receiver-presentation context:
- AetherSDR doesn't send CI-V Power ON (18 01) after connecting to Icom radios in standby #5349 — remote power-on from standby, including IC-7610 reports.
- Icom: data modes (DIGU/DIGL/DFM) never send the DATA setting — DIGU and USB are byte-identical on the wire, so FT8 TX stays on the microphone #4931 — DATA-mode selection and transmit modulation-input routing.
- RadioModel::maxPanadapters() turns a non-Flex backend's reported 0 into the Flex default of 2 — Add Pan offered on a scope-less Icom #6056 — panadapter capacity while an Icom model has no recognized scope profile.
- Icom: VOX, speech processor, CW speed and break-in raise a false "dropping transmit set" notice #6086 — false dropped-command notices for Icom transmit controls.
- Per-slice RIT/XIT through the seam: RadioModel drops the slice id, the backend holds one radio-wide value #6105 — receiver ownership of RIT/XIT at the backend seam.
- Icom: CW speed, break-in and pitch do nothing on radios without a CW text keyer (IC-9700, IC-7610, IC-785x, IC-7300, IC-905) #6110 — physical CW controls gated by the text-keyer capability, including IC-7610.
- [RFC] Radio-native VFO flag layout — carry a second receiver where a second panadapter cannot go #5348 — radio-native MAIN/SUB receiver and VFO presentation.
The links include historical reports and shared Icom context.
What changes
- Recognize IC-7760 model ID B2 and provide model-specific IC-7610/7760 profiles. CI-V
19 00supplies the canonical model independently of the configurable bus address and network nickname. That identity reaches the status-bar model label through the existing RadioModel information update. - Keep MAIN and SUB as fixed receiver resources with separate state and pans. Use absolute
25 rr/26 rraddressing, retain DATA OFF/D1/D2/D3 and FIL1/FIL2/FIL3, and qualify command-29 controls by the exact model guides. Global TX controls remain unwrapped. Editing SUB does not change the radio's TX route. - Install the actual scope geometry before decoding. The old 475-bin decoder truncated 689-bin sweeps, shifting native bin positions on the rendered frequency axis. Each new receiver now preserves 689 bins and its own metadata. Center uses centre ± half-span; Fixed/scroll use reported edges. Spectrum and waterfall consume identical ordered amplitudes and edges. No IQ conjugation or FFT rotation is applied to these cooked display traces.
- Negotiate stereo PCM16 receive audio independently of mono PCM16 transmit audio. Preserve stereo frame alignment across packets, use independent receiver resamplers/decoder feeds, and mix monitor audio with per-slice gain, mute and balance. LAN AF/IF is inspected; IF is withheld from AF playback with guidance rather than silently rewriting the radio's menu.
- Keep one global PTT/readback path and TX coordinator. Split determines MAIN/SUB TX; actual TX frequency is read through
1C 03. Key-on waits for receiver mode/frequency and split readbacks. The active TX receiver's DATA variant chooses the appropriate model-specific modulation register. - Mark the model choices experimental using the same policy as the radio-tab strip. Both receive the EXPERIMENTAL badge; IC-7300MK2 retains its supported treatment. Preserve the new dialog's saved CI-V values, Locations, paths and scoped credentials.
Protocol authority: the operator's Icom oracle §§13.2–13.6/13.13 and the official IC-7610 A7380-7EX-4 and IC-7760 A7788-8EX-2 CI-V guides. Profiles record official-guide evidence, not live-hardware qualification. The IC-9700 retains its existing single selectable scope.
Validation
- macOS app configured and built with 8-way compilation.
- 16 focused CTest targets passed: Icom dual receiver, scope, audio, family, pan capacity, identity, backend seam, session lease, scheduler, PTT authority, scoped credentials, connection workspace, source selection, dialog sizing, startup lockout and unified title bar.
- Socket-free production-backend injection covers both model identities at a custom address; distinct pans/slices; full bin positions; shared spectrum/waterfall rows and axes; malformed, foreign and stale frames; reordered receiver replies; D2/D3; split/focus; global PTT/unkey; independent codec negotiation; monitor mixing; and decoder audio surviving monitor mute.
- Captured production uplink packets for both models verify 20 ms mono PCM framing/downmix level, 24→48 kHz conversion after acoustic filter delay, rejection without keying/audio authority, and queued-audio cancellation on unkey. The updated dual-receiver, audio and PTT-authority tests passed together.
- Mutation check: replacing the native geometry with 475 bins causes the new receiver/render assertions to fail. Restoring the production geometry returns the suite to green.
- Automation bridge on an isolated, disconnected app, with autoconnect off and TX automation disabled: exercised the Radio connection workspace with Locations, operator profiles and SmartLink accounts #6885/Radio tab actions, saved ordering, and connection handoff #6889 Add radio by IP flow, selected Icom, inspected both experimental model entries and selected IC-7760. Captured the dialog/list below. No physical radio was connected or keyed.
- User documentation build and engine-boundary, command-plane, capability-record, touchpoint and test-registration checks passed.
Screenshots
The dialog/list are live automation-bridge captures from the integrated offline app. The tab strips are explicitly offline TitleBar fixtures; they are not hardware evidence.




Activity
aethersdr-agent commentedon Oct 31, 2026
Triage:
maintainer-reviewThis is a contribution proposal, not a defect report, so triage here is about (a) which of the claims are verifiable against
maintoday, (b) what the landing order has to be, and (c) which gates are the maintainer's to rule on. The branch exists —jensenpat/AetherSDR aether/icom-dual-receiver-bringup@543e8dcd7. I did not review the diff; that belongs to the PR.Verified in
main: the 689-bin claim is a real, currently-shipping bug, and it explains #6871The scope geometry is model-driven at the amplitude step and hardcoded at the bin-count step. Two separate things:
IcomCivBackend.cpp:2478-2481builds a per-modelScopeGeometryfromm_model->scopePoints/scopeMaxAmplitude— but only hands it totoDbm().ScopeDecoder m_scope(IcomCivBackend.h:409), default-constructed.ScopeGeometry::pointsdefaults tokScopePointsIc705 = 475(IcomScope.h:27,31),ScopeDecodertakes geometry only through its constructor, and there is no setter anywhere in the class (IcomScope.h:144-157—geometry()is a const getter).m_scope.reset()atIcomCivBackend.cpp:1050clears partial-sweep state, not geometry.IcomScope.cpp:121and:145runm_partial.raw.resize(475, 0)on every model. An IC-7610 sweep of 689 bins is truncated to its first 475, and those 475 are then stretched across the full pan width.That arithmetic matches the #6871 report quantitatively: the VFO sits at native bin 344 of 689 in Centre mode, which renders at 344/475 ≈ 72% of the width — the reporter's "about 1/2 way between the center and the right side of the display," and it is bandwidth-independent, exactly as reported.
This fix is separable from the rest of the proposal and is the single highest-value piece here: seed
m_scope's geometry fromm_modelonce19 00resolves the model (and re-seed on model change), inIcomCivBackend. One decoder, no new resources, no dialog dependency, no capability-contract change. It would fix #6871 on its own and could be authorized independently of the dual-receiver work.Verified: the IC-7760 identity gap, with hardware evidence already on file
0xB2is absent fromkModels(IcomModels.cpp:22-120, 7 rows), sounknownModel()applies —hasScope = false,hasTransmit = false.ConnectionPanel.cpp:2360-2366says so in a comment: the combo is generated fromknownModels(), "which is the point, given the table is where the IC-7760 row is missing."CI-V identity: model ID b2 at address b2→Unrecognized Icom model ID B2. Model-specific controls and transmit remain disabled.→ blank pan. Both the model ID and the bus address are attested at0xB2on a real radio.01/01, Centre-mode header cross-checked. Note what that report explicitly does not claim: the level range was not observed (all-zero capture; lower bound 0).200is an inference from the 7610/785x rows. The new row should carryverified = falseon the amplitude range specifically, as Information regarding implementing the Icom 7760 spectrum scope. #5280 itself asks.0x98, 689/200/15) but resolves tokTunerOnlyProfile(IcomModels.cpp:665-676), so the model-specific profile work for it is genuine new ground.Not verified — please don't let the proposal's wording settle #6872 by itself
RX audio is hardwired to one format:
IcomProtocol.h:408-412fixes 20 ms / s16 / mono / 48 kHz with astatic_asserton the derived 1920-byte frame, andIcomSession.cpp:479-484clamps any other requested rate with a warning rather than negotiating. Two candidate mechanisms for #6872's "nothing below ~3 kHz" both survive that evidence:Those are discriminated by the radio's own menu state and a log line, not by code reading — that question belongs on #6872, and I'd rather see it answered there before the audio half of this lands. Related structural note: stereo RX negotiation collides with that
static_assert, because the 1920-byte frame constant is shared by the TX packetizer. RX and TX frame/format constants have to split beforeLpcm2ch16can be negotiated for receive only.Capability and design-contract changes the maintainer should rule on
Today
IcomCivBackend.cpp:371-375publishesmaxSlices = m.receivers(so the 7610 row already claims 2) butmaxPanadapters = hasScope ? 1 : 0. Two fixed MAIN/SUB pans changes that contract — and it contradicts the committed design doc, which is the part that makes this a maintainer decision rather than a review nit:docs/architecture/aetherd-icom-civ-backend-design.md:162—createPanadapter→ "false— one receiver, one scope":31— "AetherSDR does not yet independently model MAIN and SUB":97— describes the panadapter as "a cooked 475-bin, 0–160 display array"All three need to move with the code, and the third is wrong for the 7610/785x rows already.
Gates, and the landing order
GOVERNANCE.mdlists "changes to the audio pipeline" and "new feature areas substantially beyond the current scope" among RFC triggers. Independent per-receiver resamplers plus a monitor mix with per-slice gain/mute/balance, and a second panadapter resource on a family documented as single-pan, both plausibly fire. I'm not ruling on it: @ten9876, does this need an[RFC]first, or does the per-model-profile precedent cover it?IRadioBackendmigration (RFC: AetherD — headless engine + UI decoupling (libaethercore, versioned protocol, thin clients) #3849) is still mid-flight, which is precisely why the design-doc alignment above matters rather than being a paperwork item.1C 03actual-TX-frequency read, and the DATA-variant modulation register. A wrong TX-route inference transmits on the wrong VFO. Reporters with the hardware have already volunteered: @Scooter-web (IC-7610, Icom 7610 - Spectrum display not on radio frequency #6871/Icom 7610 - No computer sound output #6872) and @ny4i, who offered in Information regarding implementing the Icom 7760 spectrum scope. #5280 to test against both an IC-7760 and an IC-9700.Handoff summary
Known and verified: the 475-bin decoder truncation is real, is in
main, and quantitatively explains #6871; the0xB2row is missing and both its ID and address are attested by #5585, with 689 bins measured in #5280. Not verified: #6872's mechanism, and every TX-route claim. To fix: seedScopeDecoder's geometry from the resolved model (small, separable, authorize-now candidate); then the0xB2row plus 7610/7760 profiles; then — subject to the RFC ruling and after #6885/#6889 — the dual-receiver resources, split RX/TX audio format constants, and the three design-doc lines above.No implementation in this pass. Happy to take the separable geometry fix for #6871 as its own change if you add
aetherclaude-eligible.🤖 aethersdr-agent · cost: $5.8514 · model: claude-opus-5
📍 Citation health check (Foundry Constitution Principle I): 1 resolved, 12 unresolved against
/Users/aetherclaude/workspace/AetherSDRat origin/main.Unresolved citations (12)
ConnectionPanel.cpp:2360-2366IcomCivBackend.cpp:1050IcomCivBackend.cpp:2478-2481IcomCivBackend.cpp:371-375IcomCivBackend.h:409IcomModels.cpp:22-120IcomModels.cpp:665-676IcomProtocol.h:408-412IcomScope.cpp:121IcomScope.h:144-157IcomScope.h:27IcomSession.cpp:479-484