fix: hold the TX meters through the gaps between words
A quarter-per-poll decay covers the milliseconds between CW elements but not the gaps that matter on the air: between the words of a CQ, in CW as in SSB, the meters genuinely read 0 for most of a second and the bars fell with them. A peak now stands for 1.5 s before it starts to fall, and still rises instantly — a needle goes up fast and comes down slow. The SWR RATIO is not updated at all from a zero reading: showing 1.0 during a word gap is worse than showing a stale figure, because it looks like good news. A test caught a real defect on the way: the proportional decay stalls on integers. With the needle at 13 and the truth at 10, a quarter of the gap rounds to zero and the meter sat three units high for ever. It now always steps down by at least one, so it converges.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
package cat
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// What SPLIT means when the operator presses it.
|
||||
//
|
||||
@@ -76,3 +79,42 @@ func TestSWRFromReflection(t *testing.T) {
|
||||
prev = v
|
||||
}
|
||||
}
|
||||
|
||||
// Needle inertia on the TX meters.
|
||||
//
|
||||
// The gaps are what this is for: milliseconds between CW elements, but most of a
|
||||
// second between the words of a CQ — in CW as in SSB. A meter that decays
|
||||
// immediately reads 0 in every one of those gaps, so the operator sees a bar
|
||||
// flashing instead of the power they are running.
|
||||
func TestMeterPeakHold(t *testing.T) {
|
||||
var m meterPeak
|
||||
t0 := time.Now()
|
||||
|
||||
if got := m.update(80, t0); got != 80 {
|
||||
t.Fatalf("first sample = %d, want 80 — a meter must show a reading at once", got)
|
||||
}
|
||||
// A gap between two words: still inside the hold, so the reading stands.
|
||||
if got := m.update(0, t0.Add(400*time.Millisecond)); got != 80 {
|
||||
t.Errorf("during a word gap = %d, want 80 held", got)
|
||||
}
|
||||
if got := m.update(0, t0.Add(1400*time.Millisecond)); got != 80 {
|
||||
t.Errorf("just before the hold expires = %d, want 80 held", got)
|
||||
}
|
||||
// Past the hold it falls — but gradually, not to zero in one step.
|
||||
after := m.update(0, t0.Add(1600*time.Millisecond))
|
||||
if after >= 80 || after <= 0 {
|
||||
t.Errorf("after the hold = %d, want a value falling between 80 and 0", after)
|
||||
}
|
||||
// A HIGHER reading is taken immediately: a needle rises fast and falls slow.
|
||||
if got := m.update(95, t0.Add(1700*time.Millisecond)); got != 95 {
|
||||
t.Errorf("rising sample = %d, want 95 straight away", got)
|
||||
}
|
||||
// And it does reach the real value eventually, or a power drop would never show.
|
||||
v := 0
|
||||
for i := 0; i < 60; i++ {
|
||||
v = m.update(10, t0.Add(time.Duration(2000+i*250)*time.Millisecond))
|
||||
}
|
||||
if v != 10 {
|
||||
t.Errorf("settled at %d, want 10 — the meter must converge on the truth", v)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user