fix(icom): power in watts on the 7760, and Listening restarts clean
The power meter applies Icom's own meter calibration (raw 143 = half deflection, 213 = full scale) anchored against the real radio: a measured 100 W sits at half deflection of the 7760's 250 W face — the linear guess showed it as 140. The RF power slider says watts on a 200 W rig instead of a percentage the operator has to convert. And the Listening button, pressed while a network Icom is connected, restarts the monitor render-only: it used to open a USB capture from the From-radio device as well, and that second producer interleaved with the network pushes chopped the audio to pieces.
This commit is contained in:
@@ -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)
|
||||
|
||||
+6
-2
@@ -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."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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. */}
|
||||
<Meter label="Po" value={st.power_meter} accent="#ef4444" scale={`${Math.round(st.power_meter * (((st.model ?? '').includes('7760')) ? 2.5 : 1))} W`} />
|
||||
{(() => {
|
||||
if ((st.model ?? '').includes('7760')) {
|
||||
const { w, defl } = icomWatts(st.power_meter);
|
||||
return <Meter label="Po" value={defl} accent="#ef4444" scale={`${w} W`} />;
|
||||
}
|
||||
return <Meter label="Po" value={st.power_meter} accent="#ef4444" scale={`${st.power_meter} W`} />;
|
||||
})()}
|
||||
<Meter label="SWR" value={st.swr_meter} accent="#f59e0b" scale={st.swr_meter > 0 ? `${(1 + st.swr_meter / 33.3).toFixed(1)}` : '1.0'} />
|
||||
</div>
|
||||
|
||||
@@ -793,7 +808,11 @@ export function IcomPanel({ onReportRST, isNetwork = false }: { onReportRST?: (r
|
||||
<Card icon={Mic} title={t('icmp.transmit')} accent="#ef4444">
|
||||
<Row label={t('icmp.power')}>
|
||||
<Slider value={st.rf_power} accent="#ef4444" onChange={(v) => set({ rf_power: v }, () => IcomSetRFPower(v))} />
|
||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.rf_power}</span>
|
||||
{/* 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. */}
|
||||
<span className="w-12 text-right text-xs font-mono tabular-nums text-muted-foreground">
|
||||
{(st.model ?? '').includes('7760') ? `${st.rf_power * 2} W` : st.rf_power}
|
||||
</span>
|
||||
</Row>
|
||||
{isPhone && (
|
||||
<Row label={t('icmp.mic')}>
|
||||
|
||||
Reference in New Issue
Block a user