diff --git a/changelog.json b/changelog.json index d7bc2cd..edc8bb6 100644 --- a/changelog.json +++ b/changelog.json @@ -32,7 +32,8 @@ "Icom console: the MOX button carries your microphone on a network station, and engaging split aligns the TX VFO’s mode with the main.", "Icom console: the spectrum scope is removed. Every model streams its waveform differently — and on the IC-7760 enabling it killed the whole CI-V link, audio included. The radio’s own scope does it better.", "Icom: any leftover waveform stream is switched off at connect — the scope flag lives in the radio and survived sessions, and its flood is what was killing the IC-7760’s CI-V link.", - "Icom console: an ATU chip beside SPLIT engages or DISENGAGES the internal tuner — TUNE started a cycle but could never take the tuner back out of line." + "Icom console: an ATU chip beside SPLIT engages or DISENGAGES the internal tuner — TUNE started a cycle but could never take the tuner back out of line.", + "Icom console: the TX meters get needle inertia — power holds its peak instead of flickering to 0 W between syllables, SWR shows the real peak then returns to the live value — and the wattage readout no longer wraps at three digits." ], "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).", @@ -64,7 +65,8 @@ "Console Icom : le bouton MOX emporte votre micro sur une station réseau, et activer le split aligne le mode du VFO TX sur le main.", "Console Icom : le scope spectral est retiré. Chaque modèle streame sa forme d’onde différemment — et sur l’IC-7760 son activation tuait tout le lien CI-V, audio compris. Le scope de la radio fait ça mieux.", "Icom : tout flux waveform résiduel est coupé à la connexion — le drapeau scope vit dans la radio et survivait aux sessions, et son flot est ce qui tuait le lien CI-V de l’IC-7760.", - "Console Icom : une puce ATU à côté de SPLIT engage ou DÉSENGAGE le tuner interne — TUNE lançait un cycle mais ne pouvait jamais remettre le tuner hors ligne." + "Console Icom : une puce ATU à côté de SPLIT engage ou DÉSENGAGE le tuner interne — TUNE lançait un cycle mais ne pouvait jamais remettre le tuner hors ligne.", + "Console Icom : les mètres TX gagnent une inertie d’aiguille — la puissance tient sa crête au lieu de retomber à 0 W entre les syllabes, le ROS montre la vraie crête puis revient à la valeur vive — et l’affichage en watts ne passe plus à la ligne à trois chiffres." ] }, { diff --git a/frontend/src/components/IcomPanel.tsx b/frontend/src/components/IcomPanel.tsx index 11bc9ad..cb6f59c 100644 --- a/frontend/src/components/IcomPanel.tsx +++ b/frontend/src/components/IcomPanel.tsx @@ -270,7 +270,7 @@ function Meter({ label, value, accent, scale, onClick, title }: { label: string;
- {scale ?? v} + {scale ?? v} ); if (onClick) { diff --git a/internal/cat/icomserial.go b/internal/cat/icomserial.go index 884da73..aa6918f 100644 --- a/internal/cat/icomserial.go +++ b/internal/cat/icomserial.go @@ -116,7 +116,13 @@ type IcomSerial struct { // "alive but silent" tolerance below, which used to be // unbounded and left the display frozen for ever silentGrace time.Duration // current width of that tolerance (backs off, see ReadState) - dspLoaded bool // readDSP has run since the rig became responsive (loads all + // Needle inertia for the TX meters — the CI-V meters are point samples, and + // between two SSB syllables a poll lands on 0 W and a perfect SWR. See + // meterPeak (yaesu_panel.go): power decays like a needle, SWR holds then + // snaps back to the live truth. + powerPeak meterPeak + swrPeak meterPeak + dspLoaded bool // readDSP has run since the rig became responsive (loads all // the panel's set-once controls once the rig actually answers) // When the console last asked for the DSP snapshot. The meters and the // front-panel rotation are polled ONLY while something is displaying them: @@ -456,12 +462,16 @@ func (b *IcomSerial) ReadState() (RigState, error) { sm, _ = b.readMeter(civ.SubMeterS) po, swr = 0, 0 if tx { + now := time.Now() if v, ok := b.readMeter(civ.SubMeterPo); ok { - po = v + po = b.powerPeak.update(v, now) } if v, ok := b.readMeter(civ.SubMeterSWR); ok { - swr = v + swr = b.swrPeak.updateSnap(v, now) } + } else { + // Cleared with the carrier, so the next transmission starts fresh. + b.powerPeak, b.swrPeak = meterPeak{}, meterPeak{} } } b.dspMu.Lock()