docs: record the three noise-rejection controls and their invariants

README gains the three controls where each lives -- the trigger's `band`/`reject`, the
measurement's `noise`/`hf`, and the math channel's `de-noise` node -- each with its unit, what
"off" is, and what it costs, plus the two deliberate deviations from the design spec next to the
features they belong to: the band applies to `edge` and `window` only (a pulse's width is measured
from a crossing to its return, so a band there changes the measured width rather than rejecting
noise; a dropout is an absence with no level to compare), and the band is verified through
`BufferSearch` hit counts rather than `[condition-probe]` latch times, because probe-readings.md
states that a `t0` is not an assertion.

The invariant docs gain the rules a later change must not break: `EventCondition`'s two new fields
and the once-per-packet `configure(dt)` that must not reset; the crossing rule that a change is
between two *decided* sides; the measurement path's exception to "a readout quotes a stored
sample", why the band moves the edge decision only, why `measure_accumulate` loops samples outer,
and why a filtered window disables both bucket fast paths; that `MathOp` is append-only (the index
*is* the serialisation), that the median window is pooled in the runtime rather than held per node,
why the pole reuses `b0`/`z1`, and that median-then-pole is the design; the session's named
`noise`/`hf` keys and its thirteen-field node string that still reads twelve; and the two GTK
traps -- positionally brace-initialised dialogs, and a control that cannot apply being hidden
rather than disabled.
This commit is contained in:
Martino Ferrari committed 2026-10-13 16:05:28 +02:00
1 parent c38630643d
commit 749b34a2cb
7 files changed
+114 -1

No files matched your search

@@ -32,6 +32,15 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
`crosshair_interpolated_mode_blends_the_two_samples` and
`the_crosshair_mark_is_bigger_than_a_sample_dot`, plus `[cursors-probe]`'s `first mark at x=..
y=..` agreeing with the pane's first value.
- **A measurement with a non-zero `hf_fc` is the one exception**, and it is inherent rather than a rounding
error. Its `min`, `max`, `peak to peak`, `average`, `top` and `bottom` are computed from a one-pole-filtered
copy of the window, so the quoted value need not equal any stored sample -- and with `show_on_plot` its
ruler sits at a level the drawn trace, which is raw, never reaches. This is what filtering *is*; it must
not be "fixed" by snapping the readout to the nearest sample. Every measurement with `hf_fc == 0`, which is
the default, still quotes a stored sample exactly as the rule above says. The filter is seeded with the
window's **first sample** and never from history before the window, so a measurement never depends on data
outside the window it reports on: the left-edge step transient is removed by the seeding, not by priming
from earlier samples.
- **`format_measure()` is the one formatter for both panes, and its SI prefix does not depend on
there being a unit.** The cursors pane's values and the measurements pane's `text=` go through
it, so a change reaches both. The prefix ladder used to be inside `if (!unit.empty())`, which