diff --git a/app.go b/app.go
index ed7350f..10d1e6c 100644
--- a/app.go
+++ b/app.go
@@ -10667,6 +10667,16 @@ func (a *App) AudioStartMonitor() error {
if strings.TrimSpace(cfg.FromRadio) == "" {
return fmt.Errorf(`no "From radio" capture device set — pick the rig's USB Audio CODEC in Settings → Audio`)
}
+ // When the rig's audio arrives over the NETWORK (Icom 50003), the monitor
+ // must be render-only: this button used to start a USB capture from the
+ // "From radio" device as well, and that second producer — often another
+ // radio's DAX — interleaved its chunks with the network stream's pushes.
+ // The result was audio chopped to pieces the moment the operator toggled
+ // Listening off and on while connected to a network Icom.
+ if cs, err := a.GetCATSettings(); err == nil && cs.Enabled && cs.Backend == "icom-net" && cs.IcomNetAudio {
+ applog.Printf("audio: RX monitor start (network sink only → listen=%q)", cfg.ListeningDevice)
+ return a.audioMgr.StartMonitorSink(cfg.ListeningDevice)
+ }
applog.Printf("audio: RX monitor start (from=%q → listen=%q)", cfg.FromRadio, cfg.ListeningDevice)
a.audioMgr.SetMonitorGain(cfg.FromGain)
return a.audioMgr.StartMonitor(cfg.FromRadio, cfg.ListeningDevice)
diff --git a/changelog.json b/changelog.json
index ef7f65b..e172041 100644
--- a/changelog.json
+++ b/changelog.json
@@ -11,7 +11,9 @@
"Icom: switching back from a data mode (USB-D1) to plain USB now sticks — if the rig ignores the data-flag command, it is repeated with the modern one-frame form (0x26). Seen on the IC-7760.",
"Icom console: a DATA mode button (USB-D, what FT8 wants), the PSK button drives the rigs that have a native PSK mode, and the power meter reads in real watts on the IC-7760’s 250 W scale.",
"Icom network audio: the right codec is requested (16-bit mono LPCM), settled by experiment on a real IC-7760.",
- "CAT settings: reopening the panel now shows the radio that is actually selected — it always showed the first one, with the fields (MY_RIG included) silently editing the wrong entry."
+ "CAT settings: reopening the panel now shows the radio that is actually selected — it always showed the first one, with the fields (MY_RIG included) silently editing the wrong entry.",
+ "IC-7760: the power meter is calibrated against the radio (100 W reads 100 W on the 250 W face) and the RF power setting reads in watts, not a percentage.",
+ "Icom network audio: toggling Listening off and on no longer chops the sound — the monitor restarts as network-fed instead of also opening a USB capture."
],
"fr": [
"Console Elecraft : le S-mètre est calibré sur un vrai K3 — S9 et les +dB correspondent désormais à l’affichage de la radio (il lisait environ deux points S trop bas).",
@@ -22,7 +24,9 @@
"Icom : revenir d’un mode data (USB-D1) au USB simple tient désormais — si la radio ignore la commande du drapeau data, elle est répétée sous la forme moderne en une trame (0x26). Constaté sur l’IC-7760.",
"Console Icom : un bouton de mode DATA (USB-D, celui de FT8), le bouton PSK pilote les radios qui ont un vrai mode PSK, et le wattmètre lit en watts réels sur l’échelle 250 W de l’IC-7760.",
"Audio réseau Icom : le bon codec est demandé (LPCM mono 16 bits), déterminé par l’expérience sur un vrai IC-7760.",
- "Réglages CAT : rouvrir le panneau montre désormais la radio réellement sélectionnée — il montrait toujours la première, et les champs (MY_RIG compris) modifiaient silencieusement la mauvaise entrée."
+ "Réglages CAT : rouvrir le panneau montre désormais la radio réellement sélectionnée — il montrait toujours la première, et les champs (MY_RIG compris) modifiaient silencieusement la mauvaise entrée.",
+ "IC-7760 : le wattmètre est calibré sur la radio (100 W affiche 100 W sur l’échelle 250 W) et le réglage RF power se lit en watts, plus en pourcentage.",
+ "Audio réseau Icom : couper puis relancer Listening ne hache plus le son — le moniteur redémarre alimenté par le réseau au lieu d’ouvrir en plus une capture USB."
]
},
{
diff --git a/frontend/src/components/IcomPanel.tsx b/frontend/src/components/IcomPanel.tsx
index 583fadc..0d6cd1d 100644
--- a/frontend/src/components/IcomPanel.tsx
+++ b/frontend/src/components/IcomPanel.tsx
@@ -129,6 +129,19 @@ function fmtVFO(hz?: number): string {
}
// modeMatches marks a mode button active, folding the rig's USB/LSB into SSB.
+// icomWatts turns the backend's 0-100 meter percentage back into watts on the
+// IC-7760's own meter face. The backend value is linear in the RAW meter byte
+// (0-255 → 0-100), but Icom's calibration is not: raw 143 is half deflection
+// and raw 213 is full scale. On a real 7760 a measured 100 W sits at half
+// deflection of the 250 W face — the linear ×2.5 first tried showed 140 W for
+// it. Below half scale watts run 0→100, above it 100→250.
+function icomWatts(pct: number): { w: number; defl: number } {
+ const raw = Math.max(0, pct * 2.55);
+ const defl = raw <= 143 ? (raw / 143) * 50 : Math.min(100, 50 + ((raw - 143) / 70) * 50);
+ const w = raw <= 143 ? (raw / 143) * 100 : Math.min(250, 100 + ((raw - 143) / 70) * 150);
+ return { w: Math.round(w), defl };
+}
+
function modeMatches(btn: string, cur?: string): boolean {
if (!cur) return false;
if (btn === 'SSB') return cur === 'SSB' || cur === 'USB' || cur === 'LSB';
@@ -743,11 +756,13 @@ export function IcomPanel({ onReportRST, isNetwork = false }: { onReportRST?: (r
title={onReportRST ? t('rst.clickToFill') : undefined}
onClick={onReportRST ? () => onReportRST(sMeterRST(sp.s, sp.over, st.mode)) : undefined} />
); })()}
- {/* The meter reads 0-100% of the rig's own scale. On a 100 W rig the
- percentage IS the watts; the IC-7760's meter runs to 250 W (the rig
- makes 200), so its percentage is worth 2.5 W a point — same face as
- the radio's. */}
-
+ {(() => {
+ if ((st.model ?? '').includes('7760')) {
+ const { w, defl } = icomWatts(st.power_meter);
+ return ;
+ }
+ return ;
+ })()}
0 ? `${(1 + st.swr_meter / 33.3).toFixed(1)}` : '1.0'} />
@@ -793,7 +808,11 @@ export function IcomPanel({ onReportRST, isNetwork = false }: { onReportRST?: (r
set({ rf_power: v }, () => IcomSetRFPower(v))} />
- {st.rf_power}
+ {/* PC is a percentage of the rig's rated power; on a 200 W rig the
+ operator thinks in watts, so say it in watts there. */}
+
+ {(st.model ?? '').includes('7760') ? `${st.rf_power * 2} W` : st.rf_power}
+
{isPhone && (