OmniRig reports the VFO pair (AA/AB/BA/BB) on the whole Yaesu range and never the single-letter form. Only the latter was honoured, so every rig in that family stayed pinned to VFO A: pressing SUB moved the radio but not OpsLog, and a QSO worked on SUB was logged on the main VFO's frequency. The first letter of the pair is the VFO being listened on — Log4OM reads it and gets the right frequency on the same rigs, which is what showed the data was there. The enum now wins over the Yaesu Freq==FreqB inference, which is only a fallback for a rig file that names no VFO at all (the stock FTDX10 one answers neither VS; nor FR; usably — verified on the air). Split: the ON flag is still latched to survive a rig file that flips it on its own, but the latch is now ARMED only after 8 flips in 30 s. A first cut at 3-in-15s was armed by the operator toggling split while testing, imposing the 6 s clearing delay on a radio that did not need it; a misreading file flips a dozen times in that window untouched, so the two cases separate cleanly. Distance (km) column added to Recent QSOs and Worked before (shared catalog). Computed from the QSO's OWN my_grid/my_lat/lon first, falling back to the current profile's locator: a log spans years and portable outings, so the station a QSO was made from is not necessarily today's. Locator: a precise QRZ/HamQTH grid is no longer overwritten by the cty.dat entity centroid. The lookup runs several times per QSO and the provider gets 2 s; a slow second answer fell back to cty.dat and downgraded JN05JG to JN16 while name and QTH survived (they are only written when non-empty). The OmniRig diagnostic line now logs what OpsLog concluded, not just what OmniRig reported. icomnet.go: gofmt alignment only.
78 lines
4.4 KiB
Go
78 lines
4.4 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|