feat(icom): the ATU can be taken out of line
TUNE (1C 01 02) started a cycle; nothing sent the 0 that puts the tuner back through. An ATU chip beside SPLIT now toggles it, and the tuner state is read on the slow front-panel beat so the radio's own TUNER button stays in sync.
This commit is contained in:
@@ -14533,6 +14533,14 @@ func (a *App) IcomSetSplit(on bool) error {
|
|||||||
return a.cat.IcomDo(func(ic cat.IcomController) error { return ic.SetIcomSplit(on) })
|
return a.cat.IcomDo(func(ic cat.IcomController) error { return ic.SetIcomSplit(on) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IcomSetATU puts the internal tuner in or out of line.
|
||||||
|
func (a *App) IcomSetATU(on bool) error {
|
||||||
|
if a.cat == nil {
|
||||||
|
return fmt.Errorf("cat not initialized")
|
||||||
|
}
|
||||||
|
return a.cat.IcomDo(func(ic cat.IcomController) error { return ic.SetATU(on) })
|
||||||
|
}
|
||||||
|
|
||||||
// IcomSetSplitOffset turns split on with a chosen TX offset (Hz) — the
|
// IcomSetSplitOffset turns split on with a chosen TX offset (Hz) — the
|
||||||
// console's +1/+5/+10 kHz buttons.
|
// console's +1/+5/+10 kHz buttons.
|
||||||
func (a *App) IcomSetSplitOffset(hz int64) error {
|
func (a *App) IcomSetSplitOffset(hz int64) error {
|
||||||
|
|||||||
+4
-2
@@ -31,7 +31,8 @@
|
|||||||
"Icom network: a radio in standby keeps its session and the console’s ON button — the quiet-CI-V recovery was tearing the session down every 15 s, so a radio that was off when OpsLog started could never be powered on.",
|
"Icom network: a radio in standby keeps its session and the console’s ON button — the quiet-CI-V recovery was tearing the session down every 15 s, so a radio that was off when OpsLog started could never be powered on.",
|
||||||
"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 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 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: 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."
|
||||||
],
|
],
|
||||||
"fr": [
|
"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).",
|
"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).",
|
||||||
@@ -62,7 +63,8 @@
|
|||||||
"Réseau Icom : une radio en veille garde sa session et le bouton ON de la console — la récupération du CI-V muet détruisait la session toutes les 15 s, donc une radio éteinte au lancement d’OpsLog ne pouvait jamais être allumée.",
|
"Réseau Icom : une radio en veille garde sa session et le bouton ON de la console — la récupération du CI-V muet détruisait la session toutes les 15 s, donc une radio éteinte au lancement d’OpsLog ne pouvait jamais être allumée.",
|
||||||
"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 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.",
|
"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."
|
"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."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
IcomSetAFGain, IcomSetRFGain, IcomSetNB, IcomSetNBLevel, IcomSetNR, IcomSetNRLevel,
|
IcomSetAFGain, IcomSetRFGain, IcomSetNB, IcomSetNBLevel, IcomSetNR, IcomSetNRLevel,
|
||||||
IcomSetANF, IcomSetAPF, IcomSetAGC, IcomSetPreamp, IcomSetAtt, IcomSetFilter,
|
IcomSetANF, IcomSetAPF, IcomSetAGC, IcomSetPreamp, IcomSetAtt, IcomSetFilter,
|
||||||
AudioMonitorActive, AudioStartMonitor, AudioStopMonitor,
|
AudioMonitorActive, AudioStartMonitor, AudioStopMonitor,
|
||||||
IcomSetRFPower, IcomSetMicGain, IcomSetSplit, IcomTune, IcomConsolePTT,
|
IcomSetRFPower, IcomSetMicGain, IcomSetSplit, IcomTune, IcomSetATU, IcomConsolePTT,
|
||||||
GetCATState, SetCATFrequency, SetCATMode,
|
GetCATState, SetCATFrequency, SetCATMode,
|
||||||
IcomSetRIT, IcomSetRITOn, IcomSetXITOn,
|
IcomSetRIT, IcomSetRITOn, IcomSetXITOn,
|
||||||
IcomSetAntenna, IcomSetPBTInner, IcomSetPBTOuter, IcomSetManualNotch, IcomSetNotchPos,
|
IcomSetAntenna, IcomSetPBTInner, IcomSetPBTOuter, IcomSetManualNotch, IcomSetNotchPos,
|
||||||
@@ -20,7 +20,7 @@ import { ShiftRow } from '@/components/ShiftRow';
|
|||||||
|
|
||||||
type IcomState = {
|
type IcomState = {
|
||||||
available: boolean; model?: string; mode?: string;
|
available: boolean; model?: string; mode?: string;
|
||||||
transmitting: boolean; split: boolean; sub_hz?: number;
|
transmitting: boolean; split: boolean; sub_hz?: number; atu_on?: boolean;
|
||||||
s_meter: number; power_meter: number; swr_meter: number;
|
s_meter: number; power_meter: number; swr_meter: number;
|
||||||
rf_power: number; mic_gain: number;
|
rf_power: number; mic_gain: number;
|
||||||
af_gain: number; rf_gain: number;
|
af_gain: number; rf_gain: number;
|
||||||
@@ -585,6 +585,9 @@ export function IcomPanel({ onReportRST, isNetwork = false }: { onReportRST?: (r
|
|||||||
{tx ? 'TX ON' : 'MOX'}
|
{tx ? 'TX ON' : 'MOX'}
|
||||||
</button>
|
</button>
|
||||||
<Chip label="SPLIT" on={st.split} onClick={() => set({ split: !st.split }, () => IcomSetSplit(!st.split))} />
|
<Chip label="SPLIT" on={st.split} onClick={() => set({ split: !st.split }, () => IcomSetSplit(!st.split))} />
|
||||||
|
{/* Tuner IN/OUT — TUNE below starts a cycle but could never take the
|
||||||
|
tuner back out of line. */}
|
||||||
|
<Chip label="ATU" on={!!st.atu_on} onClick={() => set({ atu_on: !st.atu_on } as any, () => IcomSetATU(!st.atu_on))} />
|
||||||
<button type="button" onClick={tune} disabled={tuning}
|
<button type="button" onClick={tune} disabled={tuning}
|
||||||
className={cn('w-14 shrink-0 px-2 py-1.5 rounded-md text-[11px] font-bold border transition-colors',
|
className={cn('w-14 shrink-0 px-2 py-1.5 rounded-md text-[11px] font-bold border transition-colors',
|
||||||
tuning ? 'bg-warning border-warning text-warning-foreground animate-pulse' : 'bg-card text-foreground border-border hover:bg-muted')}>
|
tuning ? 'bg-warning border-warning text-warning-foreground animate-pulse' : 'bg-card text-foreground border-border hover:bg-muted')}>
|
||||||
|
|||||||
Vendored
+2
@@ -646,6 +646,8 @@ export function IcomSetANF(arg1:boolean):Promise<void>;
|
|||||||
|
|
||||||
export function IcomSetAPF(arg1:boolean):Promise<void>;
|
export function IcomSetAPF(arg1:boolean):Promise<void>;
|
||||||
|
|
||||||
|
export function IcomSetATU(arg1:boolean):Promise<void>;
|
||||||
|
|
||||||
export function IcomSetAntenna(arg1:number):Promise<void>;
|
export function IcomSetAntenna(arg1:number):Promise<void>;
|
||||||
|
|
||||||
export function IcomSetAntiVOX(arg1:number):Promise<void>;
|
export function IcomSetAntiVOX(arg1:number):Promise<void>;
|
||||||
|
|||||||
@@ -1230,6 +1230,10 @@ export function IcomSetAPF(arg1) {
|
|||||||
return window['go']['main']['App']['IcomSetAPF'](arg1);
|
return window['go']['main']['App']['IcomSetAPF'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function IcomSetATU(arg1) {
|
||||||
|
return window['go']['main']['App']['IcomSetATU'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function IcomSetAntenna(arg1) {
|
export function IcomSetAntenna(arg1) {
|
||||||
return window['go']['main']['App']['IcomSetAntenna'](arg1);
|
return window['go']['main']['App']['IcomSetAntenna'](arg1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1007,6 +1007,7 @@ export namespace cat {
|
|||||||
att: number;
|
att: number;
|
||||||
filter: number;
|
filter: number;
|
||||||
antenna: number;
|
antenna: number;
|
||||||
|
atu_on: boolean;
|
||||||
pbt_inner: number;
|
pbt_inner: number;
|
||||||
pbt_outer: number;
|
pbt_outer: number;
|
||||||
manual_notch: boolean;
|
manual_notch: boolean;
|
||||||
@@ -1055,6 +1056,7 @@ export namespace cat {
|
|||||||
this.att = source["att"];
|
this.att = source["att"];
|
||||||
this.filter = source["filter"];
|
this.filter = source["filter"];
|
||||||
this.antenna = source["antenna"];
|
this.antenna = source["antenna"];
|
||||||
|
this.atu_on = source["atu_on"];
|
||||||
this.pbt_inner = source["pbt_inner"];
|
this.pbt_inner = source["pbt_inner"];
|
||||||
this.pbt_outer = source["pbt_outer"];
|
this.pbt_outer = source["pbt_outer"];
|
||||||
this.manual_notch = source["manual_notch"];
|
this.manual_notch = source["manual_notch"];
|
||||||
|
|||||||
+3
-1
@@ -602,7 +602,8 @@ type IcomTXState struct {
|
|||||||
Att int `json:"att"` // dB attenuation, 0=off
|
Att int `json:"att"` // dB attenuation, 0=off
|
||||||
Filter int `json:"filter"` // 1 | 2 | 3 (FIL1/2/3)
|
Filter int `json:"filter"` // 1 | 2 | 3 (FIL1/2/3)
|
||||||
// Antenna (IC-7610 = ANT1/ANT2).
|
// Antenna (IC-7610 = ANT1/ANT2).
|
||||||
Antenna int `json:"antenna"` // 1 | 2 (0 = unknown)
|
Antenna int `json:"antenna"` // 1 | 2 (0 = unknown)
|
||||||
|
ATUOn bool `json:"atu_on"` // internal tuner engaged
|
||||||
// Filter fine controls: Twin PBT + manual notch (0-100, 50 = centre).
|
// Filter fine controls: Twin PBT + manual notch (0-100, 50 = centre).
|
||||||
PBTInner int `json:"pbt_inner"`
|
PBTInner int `json:"pbt_inner"`
|
||||||
PBTOuter int `json:"pbt_outer"`
|
PBTOuter int `json:"pbt_outer"`
|
||||||
@@ -641,6 +642,7 @@ type IcomController interface {
|
|||||||
SetMicGain(int) error
|
SetMicGain(int) error
|
||||||
SetIcomSplit(bool) error
|
SetIcomSplit(bool) error
|
||||||
SetIcomSplitOffset(bool, int64) error
|
SetIcomSplitOffset(bool, int64) error
|
||||||
|
SetATU(bool) error
|
||||||
TuneATU() error
|
TuneATU() error
|
||||||
SetScope(bool) error // enable/disable the spectrum-scope waveform stream
|
SetScope(bool) error // enable/disable the spectrum-scope waveform stream
|
||||||
SetScopeMode(bool) error // true = fixed span, false = center-on-VFO
|
SetScopeMode(bool) error // true = fixed span, false = center-on-VFO
|
||||||
|
|||||||
@@ -530,6 +530,13 @@ func (b *IcomSerial) refreshFrontPanel() {
|
|||||||
b.dsp.Filter = int(f)
|
b.dsp.Filter = int(f)
|
||||||
b.dspMu.Unlock()
|
b.dspMu.Unlock()
|
||||||
}
|
}
|
||||||
|
case 2:
|
||||||
|
// Tuner in/out — the radio's own TUNER button changes it mid-session.
|
||||||
|
if v, ok := b.readSwitchSub(civ.CmdATU, civ.SubATU); ok {
|
||||||
|
b.dspMu.Lock()
|
||||||
|
b.dsp.ATUOn = v == 1
|
||||||
|
b.dspMu.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2041,6 +2048,17 @@ func (b *IcomSerial) TuneATU() error {
|
|||||||
return b.exec(civ.CmdATU, civ.SubATU, 0x02)
|
return b.exec(civ.CmdATU, civ.SubATU, 0x02)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetATU engages or DISENGAGES the internal tuner (0x1C 0x01: 1 = in line,
|
||||||
|
// 0 = through). Tune existed without this, which meant a tuner once engaged
|
||||||
|
// could not be taken out of line again from the console.
|
||||||
|
func (b *IcomSerial) SetATU(on bool) error {
|
||||||
|
if err := b.exec(civ.CmdATU, civ.SubATU, boolByte(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.setCache(func(s *IcomTXState) { s.ATUOn = on })
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *IcomSerial) setCache(fn func(*IcomTXState)) {
|
func (b *IcomSerial) setCache(fn func(*IcomTXState)) {
|
||||||
b.dspMu.Lock()
|
b.dspMu.Lock()
|
||||||
fn(&b.dsp)
|
fn(&b.dsp)
|
||||||
|
|||||||
Reference in New Issue
Block a user