Skip to content

Experimental IC-7610 and IC-7760 dual-receiver Ethernet support #6910

Open

Description

@jensenpat

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:

IC-7760 device reports and support evidence:

Related Icom bring-up, control and receiver-presentation context:

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 00 supplies 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 rr addressing, 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.

Experimental CI-V model choices

IC-7760 in the new connection dialog

IC-7610 experimental tab strip — offline fixture

IC-7760 experimental tab strip — offline fixture

Activity

  1. self-assigned this
    on Oct 31, 2026
  2. added
    claude-activeAetherClaude is actively working on this issue
    audioAudio engine and streaming
    external devicesFlexControl, MIDI, serial port, USB peripherals
    maintainer-reviewRequires maintainer review before any action is taken
    protocolSmartSDR protocol
    spectrumPanadapter and waterfall
    on Oct 31, 2026
  3. aethersdr-agent commented on Oct 31, 2026

    @aethersdr-agent
    Contributor

    Triage: maintainer-review

    This is a contribution proposal, not a defect report, so triage here is about (a) which of the claims are verifiable against main today, (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 #6871

    The scope geometry is model-driven at the amplitude step and hardcoded at the bin-count step. Two separate things:

    • IcomCivBackend.cpp:2478-2481 builds a per-model ScopeGeometry from m_model->scopePoints / scopeMaxAmplitude — but only hands it to toDbm().
    • The decoder that actually sizes the sweep is ScopeDecoder m_scope (IcomCivBackend.h:409), default-constructed. ScopeGeometry::points defaults to kScopePointsIc705 = 475 (IcomScope.h:27,31), ScopeDecoder takes 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() at IcomCivBackend.cpp:1050 clears partial-sweep state, not geometry.
    • So IcomScope.cpp:121 and :145 run m_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 from m_model once 19 00 resolves the model (and re-seed on model change), in IcomCivBackend. 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

    • 0xB2 is absent from kModels (IcomModels.cpp:22-120, 7 rows), so unknownModel() applies — hasScope = false, hasTransmit = false. ConnectionPanel.cpp:2360-2366 says so in a comment: the combo is generated from knownModels(), "which is the point, given the table is where the IC-7760 row is missing."
    • [bug]%20Unknown%20Icom%20v26.9.2 Icom IC-7760 #5585's log is the live proof: 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 at 0xB2 on a real radio.
    • Information regarding implementing the Icom 7760 spectrum scope. #5280 supplies measured geometry for the 7760: 704-byte LAN payload − 15-byte header = 689 points, division 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). 200 is an inference from the 7610/785x rows. The new row should carry verified = false on the amplitude range specifically, as Information regarding implementing the Icom 7760 spectrum scope. #5280 itself asks.
    • The IC-7610 row already exists (0x98, 689/200/15) but resolves to kTunerOnlyProfile (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-412 fixes 20 ms / s16 / mono / 48 kHz with a static_assert on the derived 1920-byte frame, and IcomSession.cpp:479-484 clamps any other requested rate with a warning rather than negotiating. Two candidate mechanisms for #6872's "nothing below ~3 kHz" both survive that evidence:

    1. a rate mismatch (radio streaming 24 kHz, played at 48 → everything an octave up, which reads as "only the high frequencies"), or
    2. the IC-7610's LAN output being set to IF rather than AF, which the proposal's AF/IF inspection targets.

    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 before Lpcm2ch16 can be negotiated for receive only.

    Capability and design-contract changes the maintainer should rule on

    Today IcomCivBackend.cpp:371-375 publishes maxSlices = m.receivers (so the 7610 row already claims 2) but maxPanadapters = 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

    1. Stacked on unmerged work. Radio connection workspace with Locations, operator profiles and SmartLink accounts #6885 and Radio tab actions, saved ordering, and connection handoff #6889 are both still open PRs. The connection-dialog, saved-CI-V, Locations, scoped-credential and EXPERIMENTAL-badge claims in this issue cannot land before them, and three PRs from the same author now contend over the same dialog. Landing order should be Radio connection workspace with Locations, operator profiles and SmartLink accounts #6885 → Radio tab actions, saved ordering, and connection handoff #6889 → this.
    2. RFC gate — maintainer's call. GOVERNANCE.md lists "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?
    3. This is not a new backend, so the Add native ADALM-Pluto and Pluto+ multi-channel RX/TX support #5474 "no new backends until aetherd is complete" hold does not apply — it extends the existing Icom family. But the aetherd IRadioBackend migration (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.
    4. Evidence tier. The issue is admirably explicit that the profiles record official-guide evidence, not live-hardware qualification, and that the tab strips are offline fixtures. The item I'd most want live proof on before the EXPERIMENTAL badge ever comes off is the TX route: split → MAIN/SUB selection, the 1C 03 actual-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; the 0xB2 row 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: seed ScopeDecoder's geometry from the resolved model (small, separable, authorize-now candidate); then the 0xB2 row 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/AetherSDR at origin/main.

    Unresolved citations (12)
    Citation Reason
    ConnectionPanel.cpp:2360-2366 file not found in workspace
    IcomCivBackend.cpp:1050 file not found in workspace
    IcomCivBackend.cpp:2478-2481 file not found in workspace
    IcomCivBackend.cpp:371-375 file not found in workspace
    IcomCivBackend.h:409 file not found in workspace
    IcomModels.cpp:22-120 file not found in workspace
    IcomModels.cpp:665-676 file not found in workspace
    IcomProtocol.h:408-412 file not found in workspace
    IcomScope.cpp:121 file not found in workspace
    IcomScope.h:144-157 file not found in workspace
    IcomScope.h:27 file not found in workspace
    IcomSession.cpp:479-484 file not found in workspace
  4. added
    awaiting-responseWaiting for reporter to provide additional information
    and removed
    claude-activeAetherClaude is actively working on this issue
    awaiting-responseWaiting for reporter to provide additional information
    on Oct 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

New FeatureNew feature requestaudioAudio engine and streamingexternal devicesFlexControl, MIDI, serial port, USB peripheralsmaintainer-reviewRequires maintainer review before any action is takenprotocolSmartSDR protocolspectrumPanadapter and waterfall

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions