The band buttons in Station Control tuned to a fixed mid-band frequency baked into the frontend. An operator who lives in the CW segment, or in the FT8 window, got the antenna resonant somewhere he never operates and had to nudge it every time. The SteppIR's own controller has a Frequency (KHz) column per band for exactly this; this is that column. Stored sparsely: a band with no entry uses its default, so nothing migrates and an operator sets only the bands he cares about. Left empty the Settings box shows the default as its placeholder, which makes clearing it the obvious way back. The value is checked against the band plan before it is kept, because it goes to the antenna as a tune command — a lost digit (1450 for 20 m) or kHz typed as MHz would send the elements travelling to a length wrong for the band the operator is on, and on a SteppIR that journey inhibits transmit the whole way. A rejected entry is logged and the band falls back to its default. Resolution happens in the backend and rides on the existing status poll, so the widget no longer decides where a band button goes and cannot drift from what Settings shows. Its own table stays only as a floor for the first poll.
79 lines
2.7 KiB
Go
79 lines
2.7 KiB
Go
package main
|
|
|
|
import "testing"
|
|
|
|
// A per-band tune frequency goes straight to the antenna as a command, so a
|
|
// value that is not actually in that band has to be refused rather than obeyed.
|
|
// One wrong digit sends the elements travelling to a length that is wrong for
|
|
// the band the operator is on — and on a SteppIR that journey inhibits transmit
|
|
// the whole way.
|
|
func TestNormMotorBandFreqsRefusesOutOfBand(t *testing.T) {
|
|
in := map[string]int{
|
|
"20m": 14050, // fine, CW end
|
|
"40m": 7005, // fine
|
|
"6m": 50313, // fine, FT8
|
|
"15m": 1450, // a digit lost — lands in the broadcast band
|
|
"10m": 28400000, // Hz typed where kHz was asked
|
|
"17m": 14100, // right number, wrong band
|
|
"30m": 0, // not set
|
|
"80m": 3750, // not a band this antenna covers at all
|
|
"bogus": 14100, // not a band
|
|
}
|
|
got := normMotorBandFreqs(in)
|
|
want := map[string]int{"40m": 7005, "20m": 14050, "6m": 50313}
|
|
if len(got) != len(want) {
|
|
t.Fatalf("kept %v, want %v", got, want)
|
|
}
|
|
for k, v := range want {
|
|
if got[k] != v {
|
|
t.Errorf("%s = %d, want %d", k, got[k], v)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The stored form round-trips, in canonical band order rather than map order so
|
|
// the settings row does not churn between saves.
|
|
func TestMotorBandFreqsRoundTrip(t *testing.T) {
|
|
m := map[string]int{"20m": 14050, "40m": 7005, "6m": 50313}
|
|
enc := encodeMotorBandFreqs(m)
|
|
if enc != "40m=7005,20m=14050,6m=50313" {
|
|
t.Errorf("encoded %q — want canonical low→high order", enc)
|
|
}
|
|
back := decodeMotorBandFreqs(enc)
|
|
for k, v := range m {
|
|
if back[k] != v {
|
|
t.Errorf("round trip lost %s: %d → %d", k, v, back[k])
|
|
}
|
|
}
|
|
// Garbage in one entry must cost only that entry.
|
|
part := decodeMotorBandFreqs("40m=7005,20m=oops,6m=50313")
|
|
if part["40m"] != 7005 || part["6m"] != 50313 {
|
|
t.Errorf("one bad entry took the others down: %v", part)
|
|
}
|
|
if _, ok := part["20m"]; ok {
|
|
t.Errorf("kept an unparseable entry: %v", part)
|
|
}
|
|
}
|
|
|
|
// An unset band falls back to its default, which is what makes the Settings box
|
|
// safe to leave empty.
|
|
func TestMotorTuneKHzForBandFallsBack(t *testing.T) {
|
|
m := map[string]int{"20m": 14050}
|
|
if got := motorTuneKHzForBand(m, "20m"); got != 14050 {
|
|
t.Errorf("chosen frequency ignored: %d", got)
|
|
}
|
|
if got := motorTuneKHzForBand(m, "15m"); got != 21150 {
|
|
t.Errorf("15m = %d, want the 21150 default", got)
|
|
}
|
|
if got := motorTuneKHzForBand(m, "80m"); got != 0 {
|
|
t.Errorf("80m = %d, want 0 — not a motor band", got)
|
|
}
|
|
// Every default must itself be in its band, or the fallback ships the very
|
|
// fault normMotorBandFreqs exists to catch.
|
|
for _, b := range motorBands {
|
|
if got := bandForHz(int64(b.defKHz) * 1000); got != b.name {
|
|
t.Errorf("default %d kHz for %s reads as %q", b.defKHz, b.name, got)
|
|
}
|
|
}
|
|
}
|