- Initialize 2 identical large buffer at initialization (default 200MB each, configurable as cli argument) to use as sample buffer for the rest of the application - Uses `deps/plotter` for plotting - Uses `deps/udpsclient/udps_client.h` to connect to one stream source - the application should be composed of: 1. main toolbar that contain: - time window selection - plot layout selection - pause/resume button - enable/disable trigger mode - show/hide and reset cursors [horizontal and or vertical] 2. when in trigger mode a collapsable right panel to configure trigger logic: - select signal to use as trigger - select edge detection type (rising, falling, both) - select trigger level - select pre trigger window size (in %) - select trigger hold off time (default 10ms) - select trigger mode [normal], [single] - arm/disarm trigger button 3. a collapsable signal panel: - list with all available signals - enable/disable signal to acquire - calibrate signal: popup to select offset and gain for signal - drag and drop signal on plot to start plotting it - button to show signal info in a popup (unit, range, rate, type, quantisation etc) 4. main view with plot: - multiples plots depending from selected layout - each plot have it x-axis sync - each plot can have y-axis with [right click menu]: 1. auto scale (default) 2. fixed range (user definable) - each plot can show one or more signals - signal acqusition: - the memory buffer should be split in N+1 (where N is the number of enabled signals) and +1 is for the shared time base - only if the time window \* signal sample rate is greater than size of signal buffer decimate input signal - the buffer should be used as circular buffer - the time should be computed from the time associated with the signal (not from the client but from the streamed data) - in trigger mode data visualisation should not be refreshed till next event, that's why 2 identical buffer, one is the currently viewed event, the other used to acquire live data for next event ## Deviations from the spec The following were built differently from what the spec states, for documented reasons in `README.md`: - **`todo.md` item 2 — relative timing.** Implemented as `--relative-time`. The retained history in this mode is **41.943 s** against the default **83.886 s** (measured at 100 kS/s, 4 channels, `--buffer-mb 200`): exactly half, because a second f64 ring for absolute time raises a tick's cost from 24 to 32 bytes — a third more — and `Partition::time_capacity` is floored to a power of two, so a third more weight costs a full halving. The spec and the original plan both quoted ~22%, which is wrong; the per-byte figure of 75% is also wrong for the same reason. Absolute stream time is preserved in a separate ring and used for the export's `abs_seconds` column, exactly as `todo.md` requires.