diff --git a/src/help/05-window.txt b/src/help/05-window.txt new file mode 100644 index 0000000..c1d2d21 --- /dev/null +++ b/src/help/05-window.txt @@ -0,0 +1,30 @@ +Time window + +The window is how much time the plot shows. Every row shares one window: the figure has a +single x link group, so the rows cannot drift apart. The trigger's event span follows it, and +the pre-trigger share is a share of this window. + +How to reach it + +The header bar's window button opens a popover: type a number, pick a unit under it, or step a +decade with the arrows. The button's own label is a reading of the current window in a natural +unit, width-locked so a change of window cannot widen the header bar. + +Worth knowing + +• A window too long to store at the wire rate is decimated, not refused. The shared clock + takes a power-of-two stride, and each group of samples is averaged rather than strided, + so a tone above the stored Nyquist is attenuated instead of aliasing to a false low frequency. +• The stamp stored for a group is the group's mean, which is where the averaging puts the + value. Stamping at the end of a group would shift every trace half a stored sample late. +• Moving the window across a decimation boundary rebuilds the buffer and drops the history. + Walking it inside one decade is free. +• The trigger sees the stored (filtered) signal, not the wire signal, because an edge + found on a sample that is not in the buffer could not be cut out of it. + +Example + +1 MS/s with 200 MB of buffer. A 2 s window stores every sample (time x1). Widen it to +600 s and the stride becomes x16: 625 S/s stored, anti-aliased at 312.5 Hz. A 2 kHz +sine seen through that window reads y=[-0.059, 0.079] — attenuated to about 6%, not +folded down to a full-amplitude 125 Hz one. diff --git a/src/help/06-navigate.txt b/src/help/06-navigate.txt new file mode 100644 index 0000000..f073948 --- /dev/null +++ b/src/help/06-navigate.txt @@ -0,0 +1,34 @@ +Navigating the plot + +The plot pans and zooms with the mouse and with the keyboard. Every gesture acts on the row the +pointer is over, and because the rows share one time axis, an x change moves all of them. + +How to reach it + +Wheel zooms both axes · Shift+wheel zooms x only · Ctrl+wheel zooms y only. +Drag pans · Ctrl+drag is a box zoom on x · Alt+drag a box zoom on y. ++ and - zoom both axes; Ctrl with them restricts to x, Alt to y. +Arrow keys pan, f fits, Escape cancels a gesture in progress. +The full table is in the shortcut overview (Ctrl+/). + +Worth knowing + +• The keyboard zoom's modifiers are not the wheel's, and that is deliberate: on common + layouts + is shift+=, so a bare zoom-in already arrives with Shift + set and Shift could not mean anything. Ctrl/Alt mirror the box-zoom drags instead. +• A pinned view is navigable within its own data but cannot leave it. While an event is + held, a capture is filling, or the view is paused, a zoom in works normally — "not + outside the event" is not "not readable" — but a pan or a zoom out is clamped to the data. +• A live view is clamped to the window you asked for, not to what the ring happens to hold. + That is why a buffer that has only just started filling leaves its left-hand side empty + instead of squeezing the window down to the first few samples. +• Zooming hard into a held capture is exact. The renderer finds the visible samples by binary + search over the real timestamps, never over a nominal sample grid, so a capture whose clock + wandered does not drift away from its axis as you zoom. + +Example + +Pause a live view, then press Ctrl++: x narrows and y does not move. Press +Alt++: y narrows and x does not. Eight doublings into a held 2 s capture, the trace +still reaches both margins — the zoom probe reports gap_px and end_px within +a pixel or two at every step. diff --git a/src/help/07-pause.txt b/src/help/07-pause.txt new file mode 100644 index 0000000..41942f4 --- /dev/null +++ b/src/help/07-pause.txt @@ -0,0 +1,29 @@ +Pause and play + +Pause freezes the display, not the acquisition. The producer keeps filling the ring at +full rate; the view binds an immutable snapshot of the window that was on screen, and the axis +is pinned to it. + +How to reach it + +The pause button in the toolbar, or Space. Press it again to resume, which rebinds the +live ring and puts the window back on the newest data. + +Worth knowing + +• Nothing is lost while paused. Because the producer never stops, resuming shows current data + with no hole in the history behind it. +• The axis is pinned to the snapshot's own stamps, not to the window that was requested. + A window reaching back past the oldest retained sample yields a shorter snapshot, and the + pinned axis is that shorter span — so you see a narrower view rather than an empty margin. +• A paused view is pinned exactly as a held trigger event is: zoom in freely, but a pan or a + zoom out is clamped to the snapshot's data. +• Pausing is the easiest way to measure a layout or read a cursor precisely, because nothing + under the pointer moves between frames. + +Example + +Pause with a 2 s window over a ring holding 1.4 s: the frozen axis reads +[-1.40 .. 0.00] rather than [-2.00 .. 0.00] with 0.6 s of blank. The pause +probe reports ring_produced still growing across the pause and +event_size non-zero exactly while paused. diff --git a/src/help/08-trigger.txt b/src/help/08-trigger.txt new file mode 100644 index 0000000..f4f0ebf --- /dev/null +++ b/src/help/08-trigger.txt @@ -0,0 +1,35 @@ +Trigger + +The trigger watches one signal for an edge through a level and captures a window around it. +The captured window is frozen on screen until you re-arm. + +How to reach it + +The trigger button in the toolbar (t) reveals the trigger panel: the signal, the level, +the edge (rising, falling, either), the mode (Normal or Single) and the pre-trigger share. +Arm starts watching; a arms and disarms from the keyboard. + +Worth knowing + +• Arming enables the signal if it was off, because a trigger on a signal nobody acquires + can never fire. +• The pre-trigger share is a share of the display window, not of the ring. A 2 s window + at 50% captures 1 s before the edge and 1 s after. +• There are four display states, and the status bar names each: armed (watching, + nothing drawn yet), capturing (the edge was accepted and the post window is filling + in view, with the marker at x = 0), event held (the frozen capture) and + disarmed. A held capture is never quietly replaced by live data. +• The first edge after arming is only accepted once the history reaches back a full pre-trigger + window, so a capture may legitimately be shorter than you asked for. The axis is pinned to + what the capture actually got. +• Disarming during a capture publishes what the capture got to, so the picture on screen + at that moment stays on screen. No event fired, so the event count does not move. +• The trigger reads the stored signal — decimated and averaged — not the wire signal. + A spike narrower than one decimation group is filtered away rather than triggering on data + the buffer does not contain. + +Example + +A 1 Hz sine, level 0, rising, 2 s window at 50%, Single. The capture spans +[-1.000 .. 1.000] with n=20001 samples at 10 kS/s — the span times the real +rate, plus one — and the marker sits at x = 0 throughout. diff --git a/src/help/udpscope-help.gresource.xml b/src/help/udpscope-help.gresource.xml index e48cef4..7df6621 100644 --- a/src/help/udpscope-help.gresource.xml +++ b/src/help/udpscope-help.gresource.xml @@ -13,5 +13,9 @@ 02-source.txt 03-signals.txt 04-layout.txt + 05-window.txt + 06-navigate.txt + 07-pause.txt + 08-trigger.txt diff --git a/src/help_window.cpp b/src/help_window.cpp index 70bb9e1..a9153f7 100644 --- a/src/help_window.cpp +++ b/src/help_window.cpp @@ -34,6 +34,10 @@ constexpr HelpPage kPages[] = { {"Getting started", "Choosing a source", "/org/udpscope/help/02-source.txt"}, {"Getting started", "Signals and calibration", "/org/udpscope/help/03-signals.txt"}, {"Getting started", "Rows, layout and drag & drop", "/org/udpscope/help/04-layout.txt"}, + {"Viewing", "Time window", "/org/udpscope/help/05-window.txt"}, + {"Viewing", "Navigating the plot", "/org/udpscope/help/06-navigate.txt"}, + {"Viewing", "Pause and play", "/org/udpscope/help/07-pause.txt"}, + {"Viewing", "Trigger", "/org/udpscope/help/08-trigger.txt"}, }; constexpr int kPageCount = static_cast(sizeof(kPages) / sizeof(kPages[0]));