Unplugged-cable behavior fixed end to end: heat grid rolls on the slot boundary (view computes the newest slot from the draw clock; history sampled every frame so slots color within a frame; noise phase displayed as commanded straight from the shared clock — radiating and the per-slot vote deleted), SNR ghost panic disambiguated via the PMA 1.1 latch (link dropped mid-read discards the batch, ghost on a proven-up link still dies), measure skips the 25s relink wait when the ECD verdict says faulted and the header says MEASURING instead of GOOD while a diag runs, RollBall mailbox deadline resized to 10s from bench measurement (<25ms linked, ~220ms no-link, >3s during a live plug's training; docs/modules/wiitek updated)

This commit is contained in:
flamingcow
2026-08-17 21:29:02 -07:00
parent 916c0150ef
commit be2bf56fa7
7 changed files with 81 additions and 40 deletions
+13 -16
View File
@@ -5,10 +5,11 @@ import (
"time"
)
// The panel's recent-history ring: 18 slots of 5 seconds, sampled once a
// second from the same figures the console row prints. Slots are wall-time
// and survive a reset — recently is recently, whatever the counters were
// re-based to — while the since-reset aggregates and fault ages clear.
// The panel's recent-history ring: 18 slots of 5 seconds, sampled every drawn
// frame from the same figures the panel paints, so a slot has data within one
// frame of being born. Slots are wall-time and survive a reset — recently is
// recently, whatever the counters were re-based to — while the since-reset
// aggregates and fault ages clear.
const (
histSlots = 18
histSlotSpan = 5 * time.Second
@@ -39,15 +40,12 @@ type histSlot struct {
rateLow bool
haveSNR bool
snrMin float64
noiseOn int
noiseN int
}
type history struct {
mu sync.Mutex
start time.Time
slots [histSlots]histSlot
seq int64
prevValid bool
prevSince errs
@@ -80,13 +78,12 @@ func delta(now, prev uint64) uint64 {
return now - prev
}
func (h *history) sample(now time.Time, v view, phy phyDisplay, nv noiseView,
func (h *history) sample(now time.Time, v view, phy phyDisplay,
measuring bool, target float64) {
h.mu.Lock()
defer h.mu.Unlock()
h.seq = int64(now.Sub(h.start) / histSlotSpan)
s := h.slot(h.seq)
s := h.slot(int64(now.Sub(h.start) / histSlotSpan))
if h.prevValid {
for i, c := range faultClasses {
@@ -118,10 +115,6 @@ func (h *history) sample(now time.Time, v view, phy phyDisplay, nv noiseView,
}
}
}
s.noiseN++
if nv.on {
s.noiseOn++
}
}
// The wall-time slots stay: recently is recently. Everything judged against
@@ -146,12 +139,16 @@ type histView struct {
sinceSNRMin float64
}
func (h *history) view() histView {
// The window's newest column is the slot containing now, taken from the draw
// clock rather than the last sample: the grid then rolls on the slot boundary
// itself — the same instant the noise cycle flips.
func (h *history) view(now time.Time) histView {
h.mu.Lock()
defer h.mu.Unlock()
newest := int64(now.Sub(h.start) / histSlotSpan)
var out histView
for k := 0; k < histSlots; k++ {
seq := h.seq - int64(histSlots-1-k)
seq := newest - int64(histSlots-1-k)
if seq < 0 {
continue
}