diff --git a/docs/claude/probe-readings.md b/docs/claude/probe-readings.md index ce037e8..2da6d81 100644 --- a/docs/claude/probe-readings.md +++ b/docs/claude/probe-readings.md @@ -1484,6 +1484,31 @@ which must be untouched: [enable-all-probe] switched 'sine' off: traces_left=0 (want 0) math_off=[math x2,math3] math_on=[math lp] notice=''sine' is off: 1 trace left the plots; math off: math x2 and 1 more' ``` +## `trig engine:` — the producer's per-second engine line + +``` +[udpscope] trig engine: ch=1 armed=1 pending=0 elapsed=0.0000/0.1000 s accum=0 history=0.0000/0.4000 s pre_pct=80 v=1 now_t=2.520 holdoff_until=2.520 ring=[2.5200..2.5200] n=567000 +``` + +Printed by the producer once a second while a trigger is configured, so a run with no trigger at all shows +none. `elapsed/post_want` is the capture's progress in stream seconds, `accum` how many samples that window +holds, `history/pre` how much pre-trigger history the engine has, and `now_t` the stamp of the last sample +the **engine** was fed (`engine.last_t()`), not the stream's time. + +**`ring=[oldest..newest] n=` is the store's own retained span and sample count, and it is the pair that says +which of two failures a stalled display is.** `n` counts every stored sample, so it climbs at the stream's +rate whenever data arrives at all: + +- **`ring` standing still while `n` climbs** is the *clock*: samples are stored but every one carries the + same stamp, so the axis cannot advance and the trigger's `history` never fills. Measured after going live + from an event view: `ring=[2.5200..2.5200] n=567000 → n=1131000 → n=1689000`, one second apart, with + `now_t` and `holdoff_until` both pinned at `2.520` — the file view's last stamp. The producer's clock was + frozen, not lagging, and the display stayed blank until something re-planned the store. +- **`ring` advancing while `now_t` does not** is the *feed*: the store is moving and the engine is not being + handed the samples, which is a trigger-path question and not a clock one. + +Neither can be read off the engine's own fields, which is why the store's pair is here. + ## `[udpscope] buffer allocated:` ``` diff --git a/src/acquisition.cpp b/src/acquisition.cpp index d0c7b8f..162776f 100644 --- a/src/acquisition.cpp +++ b/src/acquisition.cpp @@ -917,12 +917,20 @@ void Acquisition::on_data(const udps_frame_t* frame) { std::fprintf(stderr, "[udpscope] trig engine: ch=%d armed=%d pending=%d elapsed=%.4f/%.4f s " "accum=%llu history=%.4f/%.4f s pre_pct=%.0f v=%.4g now_t=%.3f " - "holdoff_until=%.3f\n", + "holdoff_until=%.3f ring=[%.4f..%.4f] n=%zu\n", trig_channel, int(engine.armed()), int(engine.pending()), engine.post_elapsed(), engine.post_seconds(), static_cast(engine.post_accum()), engine.history(), engine.pre_seconds(), tc.pretrigger_pct, engine.last_value(), - engine.last_t(), engine.holdoff_until()); + engine.last_t(), engine.holdoff_until(), + // The store's own retained span, beside the engine's view of the clock. Going live + // restarts the client, and the question a stalled display raises is whether the *time + // ring* is moving at all: `n` climbing while `ring` stands still is a clock problem, and + // `ring` moving while `now_t` does not is a feed problem. Neither can be told from the + // engine's own fields. + store.time().size() > 0 ? double(store.time()[0]) : 0.0, + store.time().size() > 0 ? double(store.time()[store.time().size() - 1]) : 0.0, + store.time().size()); std::fflush(stderr); } }