fix: Flex with multiple slices opened was always showing slice A s-meter.
This commit is contained in:
@@ -815,6 +815,12 @@ func (a *App) startup(ctx context.Context) {
|
||||
// CAT manager: emit pushes state to the frontend via Wails events, and
|
||||
// forwards frequency/mode to any outbound UDP emitters (PstRotator, N1MM).
|
||||
a.cat = cat.NewManager(func(s cat.RigState) {
|
||||
// DIAGNOSTIC: the manager only fires this on a USER-relevant change, so a
|
||||
// burst of these lines = the frontend is being re-rendered rapidly (the
|
||||
// "screen flickers" symptom). Shows WHAT is churning — connection flap,
|
||||
// or freq/split/mode oscillating between slices during FT8.
|
||||
applog.Printf("cat:state → connected=%v freq=%d rx=%d split=%v mode=%s band=%s",
|
||||
s.Connected, s.FreqHz, s.RxFreqHz, s.Split, s.Mode, s.Band)
|
||||
if a.ctx != nil {
|
||||
wruntime.EventsEmit(a.ctx, "cat:state", s)
|
||||
}
|
||||
@@ -7870,6 +7876,12 @@ func (a *App) consumeUDPEvents() {
|
||||
if a.udp == nil {
|
||||
return
|
||||
}
|
||||
// Rate-limit decode spots: an FT8 opening decodes the SAME stations every
|
||||
// cycle, so spot each call at most once per window (well within its display
|
||||
// lifetime) instead of blasting the radio with a burst of adds+removes every
|
||||
// 15 s. Single-goroutine loop → the map needs no lock.
|
||||
const decodeSpotWindow = 20 * time.Second
|
||||
lastDecodeSpot := map[string]time.Time{}
|
||||
for ev := range a.udp.Events() {
|
||||
if a.ctx == nil {
|
||||
continue
|
||||
@@ -7880,6 +7892,14 @@ func (a *App) consumeUDPEvents() {
|
||||
// panadapter when the option is on; green + SNR comment, auto-expiring
|
||||
// after the configured duration. De-duped per call in the Flex backend.
|
||||
if a.catFlexDecodeSpots && a.cat != nil {
|
||||
now := time.Now()
|
||||
if t, seen := lastDecodeSpot[ev.DecodeCall]; seen && now.Sub(t) < decodeSpotWindow {
|
||||
continue // spotted this call very recently — don't re-hammer the radio
|
||||
}
|
||||
if len(lastDecodeSpot) > 4000 {
|
||||
lastDecodeSpot = map[string]time.Time{} // bound memory on long sessions
|
||||
}
|
||||
lastDecodeSpot[ev.DecodeCall] = now
|
||||
secs := a.catFlexDecodeSecs
|
||||
if secs <= 0 {
|
||||
secs = 120
|
||||
@@ -8203,6 +8223,7 @@ func (a *App) SetCATFrequency(hz int64) error {
|
||||
if a.cat == nil {
|
||||
return fmt.Errorf("cat not initialized")
|
||||
}
|
||||
applog.Printf("cat: SetCATFrequency %.3f MHz — deliberate frontend set (spot click / band / memory / entry)", float64(hz)/1e6)
|
||||
err := a.cat.SetFrequency(hz)
|
||||
if err != nil {
|
||||
applog.Printf("cat: SetFrequency(%d Hz) dispatch error: %v", hz, err)
|
||||
@@ -8226,6 +8247,7 @@ func (a *App) ultrabeamFollowNow(freqHz int64) {
|
||||
if err != nil || !s.Enabled || !s.Follow {
|
||||
return
|
||||
}
|
||||
applog.Printf("ultrabeam: followNow — deliberate CAT set to %.3f MHz", float64(freqHz)/1e6)
|
||||
step := s.StepKHz
|
||||
if step <= 0 {
|
||||
step = 50
|
||||
@@ -8241,17 +8263,22 @@ func (a *App) ultrabeamFollowNow(freqHz int64) {
|
||||
}
|
||||
}
|
||||
khz := int(freqHz / 1000)
|
||||
diff := khz - st.Frequency
|
||||
ref := st.Frequency
|
||||
if ref <= 0 {
|
||||
ref = c.LastSetKHz()
|
||||
}
|
||||
diff := khz - ref
|
||||
if diff < 0 {
|
||||
diff = -diff
|
||||
}
|
||||
if st.Frequency > 0 && diff < step {
|
||||
if ref > 0 && diff < step {
|
||||
applog.Printf("ultrabeam: followNow within deadband (%d kHz vs ref %d, step %d) — no move", khz, ref, step)
|
||||
return // within the deadband — don't chase a tiny QSY
|
||||
}
|
||||
if err := c.SetFrequency(khz, st.Direction); err != nil {
|
||||
applog.Printf("ultrabeam: immediate re-tune to %d kHz failed: %v", khz, err)
|
||||
} else {
|
||||
applog.Printf("ultrabeam: re-tuned on freq set → %d kHz (dir %d)", khz, st.Direction)
|
||||
applog.Printf("ultrabeam: re-tuned on freq set → %d kHz (dir %d, was ref %d kHz)", khz, st.Direction, ref)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9594,6 +9621,7 @@ func (a *App) ultrabeamFollowLoop(c *ultrabeam.Client, stepKHz int, stop <-chan
|
||||
}
|
||||
ticker := time.NewTicker(1500 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
lastRigKHz := 0 // only log when the followed rig frequency actually changes
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
@@ -9611,6 +9639,15 @@ func (a *App) ultrabeamFollowLoop(c *ultrabeam.Client, stepKHz int, stop <-chan
|
||||
continue
|
||||
}
|
||||
rigKHz := int(rs.FreqHz / 1000)
|
||||
// Log the moment the poll sees a NEW rig frequency — this is what the
|
||||
// follow loop chases. If the antenna QSYs unexpectedly, this shows the
|
||||
// CAT backend started reporting that frequency (e.g. WSJT-X moved the
|
||||
// dial, or the active slice changed) even though you didn't touch the VFO.
|
||||
if rigKHz != lastRigKHz {
|
||||
applog.Printf("ultrabeam: follow loop reads rig freq %.3f MHz (mode %s) — antenna at %d kHz, step %d kHz",
|
||||
float64(rs.FreqHz)/1e6, rs.Mode, st.Frequency, stepKHz)
|
||||
lastRigKHz = rigKHz
|
||||
}
|
||||
// Skip frequencies outside the antenna's tunable range (other band).
|
||||
if st.FreqMin > 0 && st.FreqMax > 0 {
|
||||
rigMHz := rs.FreqHz / 1_000_000
|
||||
@@ -9618,17 +9655,24 @@ func (a *App) ultrabeamFollowLoop(c *ultrabeam.Client, stepKHz int, stop <-chan
|
||||
continue
|
||||
}
|
||||
}
|
||||
diff := rigKHz - st.Frequency
|
||||
// Deadband reference = the antenna's reported freq, or (when it hasn't
|
||||
// reported one yet) the last freq we commanded — so a 0/blank status
|
||||
// doesn't bypass the deadband and re-tune on every small QSY.
|
||||
ref := st.Frequency
|
||||
if ref <= 0 {
|
||||
ref = c.LastSetKHz()
|
||||
}
|
||||
diff := rigKHz - ref
|
||||
if diff < 0 {
|
||||
diff = -diff
|
||||
}
|
||||
if st.Frequency > 0 && diff < stepKHz {
|
||||
if ref > 0 && diff < stepKHz {
|
||||
continue // within the deadband — leave the motors alone
|
||||
}
|
||||
if err := c.SetFrequency(rigKHz, st.Direction); err != nil {
|
||||
applog.Printf("ultrabeam: follow re-tune to %d kHz failed: %v", rigKHz, err)
|
||||
} else {
|
||||
applog.Printf("ultrabeam: followed rig → %d kHz (dir %d)", rigKHz, st.Direction)
|
||||
applog.Printf("ultrabeam: followed rig → %d kHz (dir %d, was ref %d kHz, step %d)", rigKHz, st.Direction, ref, stepKHz)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user