76 lines
2.2 KiB
Go
76 lines
2.2 KiB
Go
package wshub
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
)
|
|
|
|
// A short window at a high sample rate fits in a ring's initial capacity, so the
|
|
// retune sweep used to leave it there — and a ring holding exactly the window has
|
|
// already rolled past the front of a capture by the time that capture is read,
|
|
// which happens a post-window plus captureMarginSec after the trigger fires.
|
|
//
|
|
// 1 MSps over a 200 ms window: 200 k points fit in the 250 k initial ring, and
|
|
// every shot came back missing its first 123 ms.
|
|
func TestCaptureWholeAtHighRateShortWindow(t *testing.T) {
|
|
const (
|
|
key = "s1:Ch1"
|
|
rate = 1e6
|
|
window = 0.2
|
|
prePct = 20.0
|
|
batchSec = 1.0 / 30.0
|
|
simSec = 6.0
|
|
)
|
|
|
|
h := NewHub()
|
|
h.SetRingBudget(defaultRingPts)
|
|
h.rings[key] = newSigRing(ringCapInitial)
|
|
h.trigger.SetConfig(trigConfig{signalKey: key, edge: "rising", threshold: 0,
|
|
windowSec: window, prePercent: prePct, mode: "normal", holdoffSec: 0.2})
|
|
|
|
rateHz := float64(rate)
|
|
nBatch := int(rateHz * batchSec)
|
|
ts := make([]float64, nBatch)
|
|
vs := make([]float64, nBatch)
|
|
|
|
armed, shots := false, 0
|
|
for now := 0.0; now < simSec; now += batchSec {
|
|
for i := range ts {
|
|
ts[i] = now + float64(i)/rateHz
|
|
vs[i] = math.Sin(2 * math.Pi * 5 * ts[i]) // a rising crossing every 200 ms
|
|
}
|
|
h.ingest(key, 1, ts, vs)
|
|
h.retuneRings(now)
|
|
h.refreshTriggerFill()
|
|
|
|
if !armed && now > 2 {
|
|
h.trigger.Arm()
|
|
armed = true
|
|
}
|
|
trigTime, pre, post, ok := h.trigger.dueCapture(now + batchSec)
|
|
if !ok {
|
|
if h.trigger.dueRearm(now + batchSec) {
|
|
h.trigger.Arm()
|
|
}
|
|
continue
|
|
}
|
|
t0 := trigTime - pre
|
|
buf := h.buildTriggerCapture(trigTime, pre, post)
|
|
if buf == nil {
|
|
t.Fatalf("shot at t=%.4f produced no frame at all", trigTime)
|
|
}
|
|
first, last, n := decodeCaptureSpan(t, buf, key)
|
|
shots++
|
|
if lost := first - t0; lost > shortCaptureTol*window {
|
|
_, span := h.rings[key].stats()
|
|
t.Errorf("shot at t=%.4f is missing %.0f ms at the front of its %.0f ms window "+
|
|
"(got [%.4f,%.4f], %d pts; ring holds %.4f s in %d points)",
|
|
trigTime, 1e3*lost, 1e3*window, first, last, n, span, h.rings[key].capacity())
|
|
}
|
|
h.trigger.markTriggered(now + batchSec)
|
|
}
|
|
if shots < 3 {
|
|
t.Fatalf("only %d shots in %.0f s", shots, simSec)
|
|
}
|
|
}
|