fix: read the FIRST digit of the Yaesu VFO reply — I inverted it yesterday
Reported both ways round, which is what settles it. With RX and TX on SUB
everything worked; with them on MAIN the frequency froze and a spot click tuned
the sub VFO. The log shows the rig answering FR01 in the MAIN case.
So on an FTDX101 the state is the FIRST digit — 0 = main — and the second is a
separate parameter. Yesterday I changed this to the LAST digit, which read FR01
as SUB and inverted the whole thing. The fault that change was meant to fix ("SUB
shows MAIN") came from reading VS instead of FR, and probing FR had already fixed
it on its own; the digit change was an unnecessary guess layered on a real fix.
Nothing else needed changing for the operator's two questions: the display and
SetFrequency already follow curVFO, so a spot now tunes whichever VFO holds RX
and TX, and the main frequency is read when on main. A test states that in those
terms — active VFO and which command a spot writes — rather than only as a byte,
because the byte is what I got wrong while believing the logic was right.
This commit is contained in:
+56
-13
@@ -225,11 +225,14 @@ func TestYaesuReceiveVFOAndSplit(t *testing.T) {
|
||||
|
||||
// The state digit of a reply, when the parameter is not one character.
|
||||
//
|
||||
// An FTDX101 answers "FR01;" where an FTDX10 answers "FR0;". Reading the FIRST
|
||||
// digit took the 0 of "01" as the answer, so a rig on SUB reported MAIN: OpsLog
|
||||
// showed the main frequency, and — since split is "TX VFO differs from RX VFO" —
|
||||
// the split flag flipped between consecutive polls, swapping freq and rx in the
|
||||
// log (F4NBZ, 2026-07-29). The last digit is the state on both rigs.
|
||||
// An FTDX101 answers "FR01;" where an FTDX10 answers "FR0;". The state is the
|
||||
// FIRST digit on both — the second is a separate parameter.
|
||||
//
|
||||
// This test asserted the opposite for one evening. Reading the LAST digit turned
|
||||
// "FR01" into SUB, so an operator with RX and TX on MAIN saw the main frequency
|
||||
// freeze and a spot click tune VFO B (F4NBZ, 2026-07-29). The fault it was meant
|
||||
// to fix — "SUB shows MAIN" — came from reading VS, not from this digit, and the
|
||||
// FR probe alone had already fixed it.
|
||||
func TestYaesuStateDigit(t *testing.T) {
|
||||
cases := []struct {
|
||||
reply, cmd string
|
||||
@@ -237,8 +240,8 @@ func TestYaesuStateDigit(t *testing.T) {
|
||||
}{
|
||||
{"FR0;", "FR", '0'}, // FTDX10 form
|
||||
{"FR1;", "FR", '1'},
|
||||
{"FR01;", "FR", '1'}, // FTDX101 form — the bug: this read as '0'
|
||||
{"FR00;", "FR", '0'},
|
||||
{"FR01;", "FR", '0'}, // FTDX101 form: MAIN — the reported bug read this as SUB
|
||||
{"FR11;", "FR", '1'}, // …and this is SUB
|
||||
{"ST1;", "ST", '1'},
|
||||
{"FT0;", "FT", '0'},
|
||||
{"VS1;", "VS", '1'},
|
||||
@@ -255,12 +258,52 @@ func TestYaesuStateDigit(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// End to end: the FTDX101 two-digit form must place the operator on SUB.
|
||||
if d := yaesuStateDigit("FR01;", "FR"); d != '1' {
|
||||
t.Fatalf("FR01 read as %q — the operator is on SUB and must be seen there", d)
|
||||
// End to end, both directions of the reported fault:
|
||||
if d := yaesuStateDigit("FR01;", "FR"); d != '0' {
|
||||
t.Fatalf("FR01 read as %q — the operator is on MAIN and must be seen there", d)
|
||||
}
|
||||
// And with the receive VFO right, both-on-sub is correctly NOT split.
|
||||
if yaesuSplitFromReply("FT01;", "FT", "B") {
|
||||
t.Error("RX and TX both on sub reported as split")
|
||||
if d := yaesuStateDigit("FR11;", "FR"); d != '1' {
|
||||
t.Fatalf("FR11 read as %q — the operator is on SUB", d)
|
||||
}
|
||||
}
|
||||
|
||||
// A spot click tunes the VFO the operator is ON, and the display reads that same
|
||||
// VFO. Both follow from the receive-VFO digit, which is why it is pinned here in
|
||||
// the operator's terms rather than only as a byte.
|
||||
//
|
||||
// Reported both ways round on an FTDX101 (F4NBZ, 2026-07-29): with RX and TX on
|
||||
// SUB everything worked, and with them on MAIN the frequency froze and a spot
|
||||
// clicked tuned the sub VFO.
|
||||
func TestYaesuActiveVFOFollowsReceiveVFO(t *testing.T) {
|
||||
// Mirrors ReadState's choice of VFO and SetFrequency's choice of command.
|
||||
activeVFO := func(frReply string) string {
|
||||
if yaesuStateDigit(frReply, "FR") == '1' {
|
||||
return "B"
|
||||
}
|
||||
return "A"
|
||||
}
|
||||
tuneCmd := func(vfo string) string {
|
||||
if vfo == "B" {
|
||||
return "FB" // sub
|
||||
}
|
||||
return "FA" // main
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name, fr, wantVFO, wantCmd string
|
||||
}{
|
||||
{"RX and TX on MAIN (FTDX101 two-digit reply)", "FR01;", "A", "FA"},
|
||||
{"RX and TX on SUB (FTDX101)", "FR11;", "B", "FB"},
|
||||
{"MAIN on a one-digit rig", "FR0;", "A", "FA"},
|
||||
{"SUB on a one-digit rig", "FR1;", "B", "FB"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
vfo := activeVFO(c.fr)
|
||||
if vfo != c.wantVFO {
|
||||
t.Errorf("%s: active VFO = %s, want %s", c.name, vfo, c.wantVFO)
|
||||
}
|
||||
if cmd := tuneCmd(vfo); cmd != c.wantCmd {
|
||||
t.Errorf("%s: a spot click would write %s, want %s", c.name, cmd, c.wantCmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user