package cat import "testing" // Every known rig's OmniRig behaviour, pinned. These rules genuinely contradict // each other between models, so a change that fixes one rig must be shown not to // break another — that is what this table is for. func TestResolveOmniRigVFOs(t *testing.T) { const ( a14200 = 14200000 b14205 = 14205000 b21000 = 21000000 ) cases := []struct { name string rig string main, fa, fb int64 vfo string split int64 sticky bool wantTX, wantRX int64 wantSplit bool }{ // The reported failure: FTDX101D, SUB VFO pressed. OmniRig names VFO B and // reports it as the generic Freq; freqA still holds the main VFO. Preferring // freqA meant the display never followed the operator to B. {"FTDX101D on SUB VFO", "FTDX101D", b14205, a14200, b14205, "B", pmSplitOff, false, b14205, 0, false}, {"FTDX101D on MAIN VFO", "FTDX101D", a14200, a14200, b14205, "A", pmSplitOff, false, a14200, 0, false}, // Yaesu fallback for a rig file that names NO VFO at all (the stock FTDX10 // one, confirmed 2026-07-26): the generic Freq matching FreqB is then the // only sign that the operator is on SUB. It applies ONLY when the enum is // silent — when the enum names a VFO, the enum wins (pair cases below). {"FTDX10, no enum, generic Freq is B", "FTDX10", b14205, a14200, b14205, "", pmSplitOff, false, b14205, 0, false}, // Same alternating ini: one poll says OFF while the rig IS in split. The // latched ON flag has to survive the contradicting sample. {"FTDX101D split, contradicting OFF sample", "FTDX101D", a14200, a14200, b14205, "AB", pmSplitOff, true, b14205, a14200, true}, // The latch must not manufacture a split out of a stale cross-band VFO B. {"FTDX101D latch, VFOs on different bands", "FTDX101D", a14200, a14200, b21000, "AB", pmSplitOff, true, a14200, 0, false}, // Pair enums: first letter is the VFO being listened on. Reported by the // whole Yaesu family; ignoring them pinned the display to VFO A (F4NBZ, // 2026-07-26 — Log4OM follows SUB on the same rig through OmniRig). {"pair enum BA, simplex → listening on B", "", b14205, a14200, b14205, "BA", pmSplitOff, false, b14205, 0, false}, {"pair enum BB, simplex → listening on B", "", b14205, a14200, b14205, "BB", pmSplitOff, false, b14205, 0, false}, {"pair enum AB, simplex → listening on A", "", a14200, a14200, b14205, "AB", pmSplitOff, false, a14200, 0, false}, {"pair enum AA, simplex → listening on A", "", a14200, a14200, b14205, "AA", pmSplitOff, false, a14200, 0, false}, // Non-regression: a rig that does not report the VFO enum keeps the old // order — freqA, then the generic Freq, then freqB. {"no VFO enum, freqA populated (Yaesu/Kenwood)", "FT-891", a14200, a14200, 0, "", pmSplitOff, false, a14200, 0, false}, {"no VFO enum, only generic Freq (IC-9100)", "IC-9100", a14200, 0, 0, "", pmSplitOff, false, a14200, 0, false}, {"IC-7610: generic Freq reports B, enum says A", "IC-7610", b14205, a14200, b14205, "A", pmSplitOff, false, a14200, 0, false}, // Split: PM_SPLITON must be read as a BIT. An exact == 0x8000 reported "no // split" for any rig that sets the flag alongside another bit. {"split, ON flag alone", "", a14200, a14200, b14205, "AB", pmSplitOn, false, b14205, a14200, true}, {"split, ON flag with extra bits set", "", a14200, a14200, b14205, "AB", pmSplitOn | 0x40, false, b14205, a14200, true}, {"listening on B → TX on A", "", b14205, a14200, b14205, "BA", pmSplitOn, false, a14200, b14205, true}, // Split must NOT be inferred when the rig says OFF, nor from a stale VFO B // left on another band (the FT-710 / TS-570 false positive). {"OFF flag, two distinct VFOs", "", a14200, a14200, b14205, "A", pmSplitOff, false, a14200, 0, false}, {"ON flag but VFOs on different bands", "", a14200, a14200, b21000, "AB", pmSplitOn, false, a14200, 0, false}, {"ON flag but both VFOs identical", "", a14200, a14200, a14200, "AB", pmSplitOn, false, a14200, 0, false}, {"ON and OFF both set — ambiguous, treat as no split", "", a14200, a14200, b14205, "A", pmSplitOn | pmSplitOff, false, a14200, 0, false}, } for _, c := range cases { tx, rx, split := resolveOmniRigVFOs(c.rig, c.main, c.fa, c.fb, c.vfo, c.split, c.sticky) if tx != c.wantTX || rx != c.wantRX || split != c.wantSplit { t.Errorf("%s:\n got TX=%d RX=%d split=%v\n want TX=%d RX=%d split=%v", c.name, tx, rx, split, c.wantTX, c.wantRX, c.wantSplit) } } }