Fixed triggering mode change when acquiring
This commit is contained in:
1 parent
3d4085898e
commit
0d741c401b
10 files changed
+504
-106
No files matched your search
+48
-7
@@ -127,6 +127,21 @@ struct StreamStats {
|
||||
std::atomic<bool> have_config{false};
|
||||
};
|
||||
|
||||
/// What the plot is showing, which is one decision made once per frame: the bind, the
|
||||
/// export and the status wording all have to agree, and the producer can latch between
|
||||
/// any two of them.
|
||||
///
|
||||
/// `Capturing` is the live-updating capture: an edge has been accepted (so the pre
|
||||
/// window was full) and the post window is still filling, and the plot follows the live
|
||||
/// ring on an edge-relative axis until the snapshot lands. It is a deliberate departure
|
||||
/// from SPECS:37 ("not refreshed till next event") -- see README.
|
||||
enum class DisplayMode {
|
||||
Live, ///< no trigger: the live ring, stream clock
|
||||
Capturing, ///< an edge was accepted: the live ring, edge-relative clock
|
||||
Held, ///< the frozen snapshot of the last event
|
||||
Waiting, ///< armed, nothing captured yet: blank
|
||||
};
|
||||
|
||||
/// The application's data model: the stream description, the two sample buffers,
|
||||
/// the trigger configuration and the counters. Structural changes (a CONFIG
|
||||
/// update, an enable/disable, a calibration) rebuild the buffers, so all mutating
|
||||
@@ -191,6 +206,11 @@ class ScopeModel {
|
||||
std::shared_ptr<const EventSnapshot> event() const noexcept {
|
||||
return event_.load(std::memory_order_acquire);
|
||||
}
|
||||
/// How many snapshots `publish_event()` has produced. Not interchangeable with
|
||||
/// `trigger_latches()`: a Disarm during a capture publishes what the capture got to
|
||||
/// *without* an event having fired, so this counts "there is a new picture to frame"
|
||||
/// while the latch count keeps answering "how many events fired".
|
||||
std::uint64_t event_seq() const noexcept { return event_seq_.load(std::memory_order_acquire); }
|
||||
|
||||
/// Publishes the live buffer's new samples to its `ChannelBuffer`s.
|
||||
void acquire_all();
|
||||
@@ -211,16 +231,35 @@ class ScopeModel {
|
||||
}
|
||||
void set_trigger_enabled(bool on);
|
||||
|
||||
/// Whether the engine is mid-capture (an edge was seen and the post-trigger
|
||||
/// window is still filling). Purely informational: it drives the status line's
|
||||
/// wording. The plot deliberately does *not* react to it -- in trigger mode the
|
||||
/// picture changes only on a latch (SPECS: "data visualisation should not be
|
||||
/// refreshed till next event").
|
||||
/// Whether the engine is mid-capture (an edge was seen -- so the pre window was
|
||||
/// full -- and the post-trigger window is still filling). This is what puts the
|
||||
/// display in `DisplayMode::Capturing`: the plot follows the live ring, on an axis
|
||||
/// pinned to the coming event's window, until the snapshot replaces it.
|
||||
///
|
||||
/// Release/acquire, not relaxed: `capture_edge()` is written before this is set and
|
||||
/// has to be visible to a consumer that sees the flag.
|
||||
bool trigger_pending() const noexcept {
|
||||
return trigger_pending_.load(std::memory_order_relaxed);
|
||||
return trigger_pending_.load(std::memory_order_acquire);
|
||||
}
|
||||
void set_trigger_pending(bool on) noexcept {
|
||||
trigger_pending_.store(on, std::memory_order_relaxed);
|
||||
trigger_pending_.store(on, std::memory_order_release);
|
||||
}
|
||||
|
||||
/// The stream time of the edge of the capture `trigger_pending()` refers to. Written
|
||||
/// by the producer before it raises the flag, so a consumer that sees the flag sees
|
||||
/// this too; stale once the flag clears.
|
||||
f64 capture_edge() const noexcept { return capture_edge_.load(std::memory_order_relaxed); }
|
||||
void set_capture_edge(f64 e) noexcept {
|
||||
capture_edge_.store(e, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
/// What the plot should bind to this frame. Read it *once* per frame and pass the
|
||||
/// answer around: calling it twice can straddle a latch, and then the bind and the
|
||||
/// axis disagree about which clock they are on.
|
||||
DisplayMode display_mode() const noexcept {
|
||||
if (!trigger_enabled()) return DisplayMode::Live;
|
||||
if (trigger_pending()) return DisplayMode::Capturing;
|
||||
return event() != nullptr ? DisplayMode::Held : DisplayMode::Waiting;
|
||||
}
|
||||
|
||||
/// The x origin the plot uses: 0 for "seconds since the stream started", or minus
|
||||
@@ -283,7 +322,9 @@ class ScopeModel {
|
||||
f64 epoch_ = 0.0;
|
||||
std::atomic<double> event_span_{1.0};
|
||||
std::atomic<bool> trigger_pending_{false};
|
||||
std::atomic<double> capture_edge_{0.0};
|
||||
std::atomic<std::shared_ptr<const EventSnapshot>> event_; ///< the event on screen
|
||||
std::atomic<std::uint64_t> event_seq_{0};
|
||||
std::atomic<double> display_epoch_{0.0};
|
||||
std::atomic<bool> trigger_armed_{false};
|
||||
std::atomic<bool> trigger_enabled_{false};
|
||||
|
||||
Reference in new issue
Block a user