feat: CI-V byte trace, for a fault the command table cannot explain
Reported on an IC-9100: the MOX button does not transmit, it sets split. The source sends the PTT command (0x1C 0x00) and nowhere sends the split one (0x0F), so the discrepancy is between what OpsLog sends and what the rig acts on — and that link has already been shown, in the same operator's log, to lose frame sync. Rather than guess from the command table, this adds what settled the WinKeyer bug in one line: the actual bytes. Settings → CAT → Log the CI-V protocol writes every frame in both directions as hex. RX is traced BEFORE framing, since the bytes as they arrived are what reveals a lost boundary — a decoded view would hide exactly the fault being hunted. Session-only, like the keyer trace: it is a diagnostic, and a log full of hex helps nobody who forgot it was on. I am not claiming a cause yet. The last time I inferred one from a protocol document rather than from evidence, I inverted a digit and broke the case that worked.
This commit is contained in:
@@ -14428,6 +14428,17 @@ func (a *App) SetWinkeyerTrace(on bool) {
|
||||
winkeyer.SetTrace(on)
|
||||
}
|
||||
|
||||
// SetCIVTrace turns the byte-level CI-V trace on or off.
|
||||
//
|
||||
// Same reasoning as the WinKeyer trace, and prompted by the same shape of
|
||||
// report: an IC-9100 whose MOX button sets split instead of transmitting, while
|
||||
// the source demonstrably sends the PTT command (0x1C 0x00) and not the split
|
||||
// one (0x0F). Something between the two is not what it appears, and on a link
|
||||
// already shown to lose frame sync, the bytes are the only witness.
|
||||
func (a *App) SetCIVTrace(on bool) {
|
||||
cat.SetCIVTrace(on)
|
||||
}
|
||||
|
||||
// WinkeyerConnect opens the serial link using the saved config.
|
||||
func (a *App) WinkeyerConnect() error {
|
||||
if a.winkeyer == nil {
|
||||
|
||||
+4
-2
@@ -8,7 +8,8 @@
|
||||
"Yaesu: the mode follows the VFO you are on. A spot clicked while working the SUB receiver tuned the sub VFO but set the mode on MAIN, leaving the VFO in use on its old mode; the console read main mode too.",
|
||||
"Rotator control now covers any GS-232A controller, ERC (Easy Rotor Control) included: the serial speed is selectable and the entry is named after the protocol rather than one device. Set the ERC to GS-232 emulation, not Hy-Gain DCU-1.",
|
||||
"Native Kenwood CAT: a sixth backend talks straight to a TS-590, TS-890, TS-990 or TS-2000 over its serial port — frequency, mode, VFO, split and PTT — with no OmniRig in between. Elecraft K3/K4 speak the same dialect. Pick \"Kenwood (native)\" in Settings → CAT.",
|
||||
"Icom and Xiegu: a CI-V frame read at the wrong offset no longer turns into a frequency. Values such as 16445550000 Hz appeared in the status bar while the rig sat on 145.550 MHz — the decoder treated non-decimal bytes as digits. Such frames are now refused and the last good reading stands."
|
||||
"Icom and Xiegu: a CI-V frame read at the wrong offset no longer turns into a frequency. Values such as 16445550000 Hz appeared in the status bar while the rig sat on 145.550 MHz — the decoder treated non-decimal bytes as digits. Such frames are now refused and the last good reading stands.",
|
||||
"Settings → CAT can log the CI-V protocol: every frame to and from an Icom or Xiegu, as hex. For reporting a radio that answers oddly — a button that does the wrong thing, a frequency that jumps — where a description alone leaves the cause to guesswork."
|
||||
],
|
||||
"fr": [
|
||||
"Les entrées de réglages Antenna Genius et Tuner Genius portent une petite marque 4O3A : les panneaux pilotant ce matériel se repèrent d'un coup d'œil dans le menu.",
|
||||
@@ -16,7 +17,8 @@
|
||||
"Yaesu : le mode suit le VFO utilisé. Un spot cliqué en travaillant sur le récepteur SUB accordait bien le VFO secondaire mais réglait le mode sur le MAIN, laissant le VFO en service sur son ancien mode ; la console lisait également le mode du principal.",
|
||||
"Le contrôle de rotator couvre désormais tout contrôleur GS-232A, ERC (Easy Rotor Control) compris : la vitesse du port série est sélectionnable et l'entrée porte le nom du protocole plutôt que celui d'un seul appareil. Réglez l'ERC sur l'émulation GS-232, pas Hy-Gain DCU-1.",
|
||||
"CAT Kenwood natif : un sixième backend parle directement à un TS-590, TS-890, TS-990 ou TS-2000 par son port série — fréquence, mode, VFO, split et PTT — sans OmniRig. Les Elecraft K3/K4 parlent le même dialecte. À choisir sous « Kenwood (natif) » dans Réglages → CAT.",
|
||||
"Icom et Xiegu : une trame CI-V lue au mauvais décalage ne se transforme plus en fréquence. Des valeurs comme 16445550000 Hz apparaissaient dans la barre d'état alors que la radio était sur 145,550 MHz — le décodeur prenait des octets non décimaux pour des chiffres. Ces trames sont désormais refusées et la dernière lecture valable est conservée."
|
||||
"Icom et Xiegu : une trame CI-V lue au mauvais décalage ne se transforme plus en fréquence. Des valeurs comme 16445550000 Hz apparaissaient dans la barre d'état alors que la radio était sur 145,550 MHz — le décodeur prenait des octets non décimaux pour des chiffres. Ces trames sont désormais refusées et la dernière lecture valable est conservée.",
|
||||
"Réglages → CAT permet de journaliser le protocole CI-V : chaque trame échangée avec un Icom ou un Xiegu, en hexadécimal. Pour signaler une radio qui répond de travers — un bouton qui fait autre chose, une fréquence qui saute — là où une description seule laisse la cause à la devinette."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
GetTelemetryEnabled, SetTelemetryEnabled,
|
||||
GetQSLDefaults, SaveQSLDefaults,
|
||||
SetWinkeyerTrace,
|
||||
SetCIVTrace,
|
||||
GetExternalServices, SaveExternalServices, TestQRZUpload, TestClublogUpload, TestHRDLogUpload, TestEQSLUpload, TestCloudlogUpload,
|
||||
GetPOTAToken, SavePOTAToken,
|
||||
TestLoTWUpload, ListTQSLStationLocations,
|
||||
@@ -1136,6 +1137,7 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
const [wkPorts, setWkPorts] = useState<string[]>([]);
|
||||
// Session-only: the byte trace is a diagnostic, never a saved preference.
|
||||
const [wkTrace, setWkTrace] = useState(false);
|
||||
const [civTrace, setCivTrace] = useState(false);
|
||||
const setWkField = (patch: Partial<WKSettings>) => setWk((s) => ({ ...s, ...patch }));
|
||||
|
||||
// ── Audio (DVK + QSO recorder) ──
|
||||
@@ -2514,6 +2516,15 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{(catCfg.backend === 'icom' || catCfg.backend === 'xiegu') && (
|
||||
<div className="border-t border-border/60 pt-3">
|
||||
<label className="flex items-center gap-2 text-sm cursor-pointer">
|
||||
<Checkbox checked={civTrace} onCheckedChange={(c) => { setCivTrace(!!c); SetCIVTrace(!!c); }} />
|
||||
{t('cat.civTrace')}
|
||||
</label>
|
||||
<p className="text-[10px] text-muted-foreground mt-1">{t('cat.civTraceHint')}</p>
|
||||
</div>
|
||||
)}
|
||||
{catCfg.backend === 'kenwood' && (
|
||||
<>
|
||||
<div className="space-y-1">
|
||||
|
||||
@@ -277,7 +277,7 @@ const en: Dict = {
|
||||
'extsvc.hint': 'Upload logged QSOs to online logbooks. Each service uploads automatically on a new QSO when enabled; timing is per-service (immediate, or a 1–2 min delay so a mis-logged QSO can still be fixed first).',
|
||||
'hw.motorTxInhibit': 'Inhibit transmission while the antenna is moving', 'hw.motorTxInhibitHint': 'Blocks the FlexRadio from transmitting while the elements move (needs FlexRadio in API mode + this antenna enabled). No effect with other radios.', 'hw.motorAntenna': 'Ultrabeam / Steppir', 'hw.motorEnable': 'Enable antenna control', 'hw.motorType': 'Antenna type', 'hw.motorTransport': 'Connection', 'hw.motorTcp': 'Network (TCP)', 'hw.motorSerial': 'Serial (COM)', 'hw.motorCom': 'Serial port', 'hw.motorBaud': 'Baud', 'hw.steppirHint': 'SteppIR controllers are RS-232 serial (the DATA OUT DB9 port). Serial = a USB↔RS-232 (FTDI) adapter, shown as a COM port. Network = a serial-to-Ethernet bridge (as for the Ultrabeam).', 'hw.steppirRange': 'Tunable range', 'hw.steppirRangeHint': "The SteppIR's frequency coverage. On a band outside this range (e.g. 30 m on a 20 m–6 m SteppIR) OpsLog won't try to tune the antenna and won't inhibit transmission. Default 13–54 MHz (20 m–6 m); widen the low edge (e.g. 6) for a 40 m-equipped SteppIR.", 'hw.ultrabeam': 'Antenna (Ultrabeam)', 'hw.audioVoice': 'Audio devices & voice keyer',
|
||||
// CAT panel body
|
||||
'cat.enable': 'Enable CAT', 'cat.backend': 'Backend', 'cat.optOmnirig': 'OmniRig (any rig, Windows COM)', 'cat.optFlex': 'FlexRadio / SmartSDR (native)', 'cat.share': 'Share CAT with other programs', 'cat.shareHint': 'A native CAT backend owns the radio serial port, so no other program can reach it. This lets WSJT-X, JTDX, MSHV or Log4OM talk to the rig THROUGH OpsLog: in the other program pick the rig model "Hamlib NET rigctl" and enter 127.0.0.1:4532. Works with every backend, not only the native ones.', 'cat.sharePort': 'Sharing port', 'cat.optXiegu': 'Xiegu (native CI-V)', 'cat.xieguPort': 'Xiegu CAT port', 'cat.xieguBaudHint': 'Must match the radio menu (G90 default: 19200).', 'cat.xieguAddrHint': 'Factory CI-V address of the G90/X6100 family: 0x70.', 'cat.optYaesu': 'Yaesu (native CAT)', 'cat.optKenwood': 'Kenwood (native)', 'cat.kenwoodPort': 'Kenwood COM port', 'cat.kenwoodPortHint': 'The rig\u2019s CAT/USB serial port (TS-590, TS-890, TS-990, TS-2000, and Elecraft K3/K4 which speak the same dialect).', 'cat.kenwoodBaudHint': 'Must match MENU on the radio: a TS-590 leaves the factory at 9600, a TS-890 at 115200.', 'cat.yaesuPort': 'Yaesu CAT port', 'cat.yaesuPortHint': 'The rig CAT port — on an FTDX10/FTDX101 over USB this is the ENHANCED COM port, not the standard one.', 'cat.yaesuBaudHint': 'Must match the radio menu (FTDX10/FTDX101 default: 38400).', 'cat.optIcom': 'Icom CI-V (USB serial)', 'cat.optIcomNet': 'Icom CI-V (network / remote)', 'cat.optTci': 'TCI (Expert Electronics / SunSDR)',
|
||||
'cat.enable': 'Enable CAT', 'cat.backend': 'Backend', 'cat.optOmnirig': 'OmniRig (any rig, Windows COM)', 'cat.optFlex': 'FlexRadio / SmartSDR (native)', 'cat.share': 'Share CAT with other programs', 'cat.shareHint': 'A native CAT backend owns the radio serial port, so no other program can reach it. This lets WSJT-X, JTDX, MSHV or Log4OM talk to the rig THROUGH OpsLog: in the other program pick the rig model "Hamlib NET rigctl" and enter 127.0.0.1:4532. Works with every backend, not only the native ones.', 'cat.sharePort': 'Sharing port', 'cat.optXiegu': 'Xiegu (native CI-V)', 'cat.xieguPort': 'Xiegu CAT port', 'cat.xieguBaudHint': 'Must match the radio menu (G90 default: 19200).', 'cat.xieguAddrHint': 'Factory CI-V address of the G90/X6100 family: 0x70.', 'cat.optYaesu': 'Yaesu (native CAT)', 'cat.optKenwood': 'Kenwood (native)', 'cat.civTrace': 'Log the CI-V protocol', 'cat.civTraceHint': 'Writes every CI-V frame to and from the radio into the log, as hex. For reporting a rig that answers oddly \u2014 a button that does the wrong thing, a frequency that jumps. Session only: it is a diagnostic, and it makes the log large.', 'cat.kenwoodPort': 'Kenwood COM port', 'cat.kenwoodPortHint': 'The rig\u2019s CAT/USB serial port (TS-590, TS-890, TS-990, TS-2000, and Elecraft K3/K4 which speak the same dialect).', 'cat.kenwoodBaudHint': 'Must match MENU on the radio: a TS-590 leaves the factory at 9600, a TS-890 at 115200.', 'cat.yaesuPort': 'Yaesu CAT port', 'cat.yaesuPortHint': 'The rig CAT port — on an FTDX10/FTDX101 over USB this is the ENHANCED COM port, not the standard one.', 'cat.yaesuBaudHint': 'Must match the radio menu (FTDX10/FTDX101 default: 38400).', 'cat.optIcom': 'Icom CI-V (USB serial)', 'cat.optIcomNet': 'Icom CI-V (network / remote)', 'cat.optTci': 'TCI (Expert Electronics / SunSDR)',
|
||||
'cat.icomNetHost': 'Rig IP / hostname', 'cat.icomNetUser': 'Network user (ID)', 'cat.icomNetPass': 'Network password',
|
||||
'cat.icomNetHint': "Connects to the rig's built-in LAN server directly — no RS-BA1 or Remote Utility needed (close them first). Use the Network User1 ID/Password set in the rig's Network menu. A rig in standby is powered on automatically.",
|
||||
'cat.icomNetAudio': 'Stream RX audio over the network (experimental)',
|
||||
@@ -678,7 +678,7 @@ const fr: Dict = {
|
||||
'rot.enable': 'Activer le contrôle du rotator', 'rot.testOkRG': 'Connecté — le Rotator Genius a accepté la commande (rotation vers 0°).', 'rot.type': 'Type de rotator', 'rot.rotatorNum': 'Rotator n°', 'rot.rgHint': 'Parle directement à un Rotator Genius 4O3A en TCP (port 9006 par défaut) — sans PstRotator. Le n° choisit lequel des deux rotators du boîtier piloter.', 'rot.arcoHint': "Parle directement à tout contrôleur réglé sur Yaesu GS-232A — sans PstRotator. microHAM ARCO : régler Config → LAN → CONTROL PROTOCOL (ou USB CONTROL PROTOCOL) sur « Yaesu GS-232A » ; en USB la vitesse est sans importance. ERC (Easy Rotor Control, ERC Mini compris) : son émulation DOIT être réglée sur GS-232 — un ERC laissé en Hy-Gain DCU-1 parle un autre jeu de commandes et ne répondra pas — puis choisir son port COM et la même vitesse que dans la configuration de l'ERC.", 'rot.hint': "OpsLog envoie des commandes UDP à PstRotator. Active l'écouteur UDP de PstRotator (Setup → Communication → UDP) avant de tester.",
|
||||
'extsvc.hint': "Envoie les QSO enregistrés vers des carnets en ligne. Chaque service upload automatiquement à chaque nouveau QSO si activé ; le délai est propre à chaque service (immédiat, ou 1–2 min pour corriger un QSO mal saisi avant).",
|
||||
'hw.motorTxInhibit': "Inhiber la transmission pendant que l'antenne bouge", 'hw.motorTxInhibitHint': "Empêche le FlexRadio d'émettre pendant que les éléments bougent (nécessite le FlexRadio en API + cette antenne activée). Sans effet avec les autres radios.", 'hw.motorAntenna': 'Antenne motorisée', 'hw.motorEnable': "Activer le contrôle de l'antenne", 'hw.motorType': "Type d'antenne", 'hw.motorTransport': 'Connexion', 'hw.motorTcp': 'Réseau (TCP)', 'hw.motorSerial': 'Série (COM)', 'hw.motorCom': 'Port série', 'hw.motorBaud': 'Débit', 'hw.steppirHint': "Les contrôleurs SteppIR sont en RS-232 série (port DB9 « DATA OUT »). Série = un adaptateur USB↔RS-232 (FTDI), vu comme un port COM. Réseau = un pont série-Ethernet (comme pour l'Ultrabeam).", 'hw.steppirRange': 'Plage accordable', 'hw.steppirRangeHint': "La couverture en fréquence de la SteppIR. Sur une bande hors de cette plage (p. ex. 30 m avec une SteppIR 20 m-6 m), OpsLog n'essaie pas d'accorder l'antenne et n'inhibe pas l'émission. Défaut 13-54 MHz (20 m-6 m) ; abaisse la borne basse (p. ex. 6) pour une SteppIR équipée 40 m.", 'hw.ultrabeam': 'Antenne (Ultrabeam)', 'hw.audioVoice': 'Périphériques audio & manipulateur vocal',
|
||||
'cat.enable': 'Activer le CAT', 'cat.backend': 'Backend', 'cat.optOmnirig': 'OmniRig (tout poste, COM Windows)', 'cat.optFlex': 'FlexRadio / SmartSDR (natif)', 'cat.share': 'Partager le CAT avec les autres logiciels', 'cat.shareHint': "Un backend CAT natif occupe le port série de la radio, aucun autre logiciel ne peut donc y accéder. Ceci permet à WSJT-X, JTDX, MSHV ou Log4OM de dialoguer avec la radio À TRAVERS OpsLog : dans l'autre logiciel, choisissez le modèle « Hamlib NET rigctl » et saisissez 127.0.0.1:4532. Fonctionne avec tous les backends, pas seulement les natifs.", 'cat.sharePort': 'Port de partage', 'cat.optXiegu': 'Xiegu (CI-V natif)', 'cat.xieguPort': 'Port CAT Xiegu', 'cat.xieguBaudHint': 'Doit correspondre au menu de la radio (G90 par défaut : 19200).', 'cat.xieguAddrHint': "Adresse CI-V d'usine de la famille G90/X6100 : 0x70.", 'cat.optYaesu': 'Yaesu (CAT natif)', 'cat.optKenwood': 'Kenwood (natif)', 'cat.kenwoodPort': 'Port COM Kenwood', 'cat.kenwoodPortHint': 'Le port s\u00e9rie CAT/USB de la radio (TS-590, TS-890, TS-990, TS-2000, ainsi que les Elecraft K3/K4 qui parlent le m\u00eame dialecte).', 'cat.kenwoodBaudHint': 'Doit correspondre au MENU de la radio : un TS-590 sort d\u2019usine \u00e0 9600, un TS-890 \u00e0 115200.', 'cat.yaesuPort': 'Port CAT Yaesu', 'cat.yaesuPortHint': "Le port CAT de la radio — sur un FTDX10/FTDX101 en USB c'est le port COM ENHANCED, pas le standard.", 'cat.yaesuBaudHint': 'Doit correspondre au menu de la radio (FTDX10/FTDX101 par défaut : 38400).', 'cat.optIcom': 'Icom CI-V (USB série)', 'cat.optIcomNet': 'Icom CI-V (réseau / remote)', 'cat.optTci': 'TCI (Expert Electronics / SunSDR)',
|
||||
'cat.enable': 'Activer le CAT', 'cat.backend': 'Backend', 'cat.optOmnirig': 'OmniRig (tout poste, COM Windows)', 'cat.optFlex': 'FlexRadio / SmartSDR (natif)', 'cat.share': 'Partager le CAT avec les autres logiciels', 'cat.shareHint': "Un backend CAT natif occupe le port série de la radio, aucun autre logiciel ne peut donc y accéder. Ceci permet à WSJT-X, JTDX, MSHV ou Log4OM de dialoguer avec la radio À TRAVERS OpsLog : dans l'autre logiciel, choisissez le modèle « Hamlib NET rigctl » et saisissez 127.0.0.1:4532. Fonctionne avec tous les backends, pas seulement les natifs.", 'cat.sharePort': 'Port de partage', 'cat.optXiegu': 'Xiegu (CI-V natif)', 'cat.xieguPort': 'Port CAT Xiegu', 'cat.xieguBaudHint': 'Doit correspondre au menu de la radio (G90 par défaut : 19200).', 'cat.xieguAddrHint': "Adresse CI-V d'usine de la famille G90/X6100 : 0x70.", 'cat.optYaesu': 'Yaesu (CAT natif)', 'cat.optKenwood': 'Kenwood (natif)', 'cat.civTrace': 'Journaliser le protocole CI-V', 'cat.civTraceHint': '\u00c9crit dans le journal chaque trame CI-V \u00e9chang\u00e9e avec la radio, en hexad\u00e9cimal. Pour signaler une radio qui r\u00e9pond de travers \u2014 un bouton qui fait autre chose, une fr\u00e9quence qui saute. Valable pour la session seulement : c\u2019est un diagnostic, et le journal grossit vite.', 'cat.kenwoodPort': 'Port COM Kenwood', 'cat.kenwoodPortHint': 'Le port s\u00e9rie CAT/USB de la radio (TS-590, TS-890, TS-990, TS-2000, ainsi que les Elecraft K3/K4 qui parlent le m\u00eame dialecte).', 'cat.kenwoodBaudHint': 'Doit correspondre au MENU de la radio : un TS-590 sort d\u2019usine \u00e0 9600, un TS-890 \u00e0 115200.', 'cat.yaesuPort': 'Port CAT Yaesu', 'cat.yaesuPortHint': "Le port CAT de la radio — sur un FTDX10/FTDX101 en USB c'est le port COM ENHANCED, pas le standard.", 'cat.yaesuBaudHint': 'Doit correspondre au menu de la radio (FTDX10/FTDX101 par défaut : 38400).', 'cat.optIcom': 'Icom CI-V (USB série)', 'cat.optIcomNet': 'Icom CI-V (réseau / remote)', 'cat.optTci': 'TCI (Expert Electronics / SunSDR)',
|
||||
'cat.icomNetHost': 'IP / nom d\'hôte du poste', 'cat.icomNetUser': 'Utilisateur réseau (ID)', 'cat.icomNetPass': 'Mot de passe réseau',
|
||||
'cat.icomNetHint': "Se connecte directement au serveur LAN intégré du poste — sans RS-BA1 ni Remote Utility (ferme-les d'abord). Utilise l'ID/mot de passe Network User1 configurés dans le menu Network du poste. Un poste en veille est allumé automatiquement.",
|
||||
'cat.icomNetAudio': 'Diffuser l’audio RX par le réseau (expérimental)',
|
||||
|
||||
Vendored
+2
@@ -891,6 +891,8 @@ export function SetCATFrequency(arg1:number):Promise<void>;
|
||||
|
||||
export function SetCATMode(arg1:string):Promise<void>;
|
||||
|
||||
export function SetCIVTrace(arg1:boolean):Promise<void>;
|
||||
|
||||
export function SetCWDecoderPitch(arg1:number):Promise<void>;
|
||||
|
||||
export function SetClublogCtyEnabled(arg1:boolean):Promise<void>;
|
||||
|
||||
@@ -1730,6 +1730,10 @@ export function SetCATMode(arg1) {
|
||||
return window['go']['main']['App']['SetCATMode'](arg1);
|
||||
}
|
||||
|
||||
export function SetCIVTrace(arg1) {
|
||||
return window['go']['main']['App']['SetCIVTrace'](arg1);
|
||||
}
|
||||
|
||||
export function SetCWDecoderPitch(arg1) {
|
||||
return window['go']['main']['App']['SetCWDecoderPitch'](arg1);
|
||||
}
|
||||
|
||||
@@ -557,7 +557,9 @@ func (b *IcomSerial) write(payload ...byte) error {
|
||||
// recv() only sees the reply to THIS request (avoids a previous command's ack
|
||||
// or an unsolicited dial-turn update being mistaken for our response).
|
||||
b.drainResp()
|
||||
_, err := b.port.Write(civ.Frame(b.rigAddr, civ.AddrController, payload...))
|
||||
frame := civ.Frame(b.rigAddr, civ.AddrController, payload...)
|
||||
traceCIV("TX", frame)
|
||||
_, err := b.port.Write(frame)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -603,6 +605,9 @@ func (b *IcomSerial) reader(port civTransport, done chan struct{}) {
|
||||
continue // read timeout with no data
|
||||
}
|
||||
rx = append(rx, tmp[:n]...)
|
||||
// Traced BEFORE framing: the bytes as they arrived are what shows a lost
|
||||
// frame boundary, which a decoded view would hide.
|
||||
traceCIV("RX", tmp[:n])
|
||||
frames, consumed := civ.Scan(rx)
|
||||
if consumed > 0 {
|
||||
rx = append(rx[:0], rx[consumed:]...)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// LogSink, when set by the host app at startup, receives every CAT debug
|
||||
@@ -73,3 +74,38 @@ func DebugLogPath() string {
|
||||
}
|
||||
return filepath.Join(base, "OpsLog", "cat.log")
|
||||
}
|
||||
|
||||
// ── CI-V byte trace ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Opt-in, off by default. Turning it on logs every CI-V frame sent and received
|
||||
// as hex, exactly like the WinKeyer protocol trace.
|
||||
//
|
||||
// That trace exists because a fault nobody could reason about — "the keyer sends
|
||||
// one element then stalls" — was settled in one line the moment the actual bytes
|
||||
// were visible. The CI-V link has now produced the same class of report: a MOX
|
||||
// button that sets split instead of transmitting, on a rig whose PTT command is
|
||||
// demonstrably correct in the source. Guessing at that from the command table
|
||||
// has already cost this project a wrong fix; the bytes will say what the rig was
|
||||
// really asked.
|
||||
var civTrace atomic.Bool
|
||||
|
||||
// SetCIVTrace turns the CI-V byte trace on or off.
|
||||
func SetCIVTrace(on bool) {
|
||||
civTrace.Store(on)
|
||||
if on {
|
||||
debugLog.Printf("civ trace ON — every CI-V frame to and from the rig is logged")
|
||||
} else {
|
||||
debugLog.Printf("civ trace OFF")
|
||||
}
|
||||
}
|
||||
|
||||
// CIVTraceEnabled reports whether the trace is running (for the settings UI).
|
||||
func CIVTraceEnabled() bool { return civTrace.Load() }
|
||||
|
||||
// traceCIV logs one frame. dir is "TX" (to the rig) or "RX" (from it).
|
||||
func traceCIV(dir string, b []byte) {
|
||||
if !civTrace.Load() || len(b) == 0 {
|
||||
return
|
||||
}
|
||||
debugLog.Printf("civ %s % X", dir, b)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user