Initial commit
This commit is contained in:
commit
8059b90de7
29 files changed
+7893
No files matched your search
+107
@@ -0,0 +1,107 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// SPDX-FileCopyrightText: 2026 Martino Ferrari
|
||||
|
||||
#include "trigger.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace udpscope {
|
||||
|
||||
double TriggerConfig::post_span_s(double buffer_span_s) const {
|
||||
const double pre = std::clamp(pretrigger_pct, 0.0, 100.0) / 100.0;
|
||||
return buffer_span_s * (1.0 - pre);
|
||||
}
|
||||
|
||||
void TriggerEngine::configure(const TriggerConfig& cfg, double post_seconds,
|
||||
double pre_seconds, double oldest_s) {
|
||||
const bool channel_changed = cfg.channel != cfg_.channel;
|
||||
cfg_ = cfg;
|
||||
post_seconds_ = post_seconds > 0.0 ? post_seconds : 0.0;
|
||||
pre_seconds_ = pre_seconds > 0.0 ? pre_seconds : 0.0;
|
||||
oldest_s_ = oldest_s;
|
||||
if (channel_changed) {
|
||||
have_prev_ = false;
|
||||
pending_ = false;
|
||||
post_accum_count_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerEngine::arm(double now_s) noexcept {
|
||||
armed_ = true;
|
||||
pending_ = false;
|
||||
post_accum_count_ = 0.0;
|
||||
holdoff_until_s_ = now_s;
|
||||
have_prev_ = false;
|
||||
}
|
||||
|
||||
bool TriggerEngine::process(double value, double now_s) noexcept {
|
||||
if (!cfg_.enabled || !armed_ || cfg_.channel < 0) return false;
|
||||
|
||||
// Hold-off: settled, waiting for the next edge.
|
||||
if (!pending_ && now_s < holdoff_until_s_) {
|
||||
prev_ = value;
|
||||
have_prev_ = true;
|
||||
last_t_s_ = now_s;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!have_prev_) {
|
||||
prev_ = value;
|
||||
have_prev_ = true;
|
||||
last_t_s_ = now_s;
|
||||
return false;
|
||||
}
|
||||
|
||||
last_t_s_ = now_s;
|
||||
|
||||
if (pending_) {
|
||||
// Accumulate the post-trigger window; latch once the stream clock has advanced
|
||||
// past it. Time, not a sample count: `now_s` is the same clock the x axis reads,
|
||||
// so the capture covers exactly the requested span whatever the cadence is.
|
||||
++post_accum_count_;
|
||||
prev_ = value;
|
||||
if (now_s - pending_start_s_ >= post_seconds_) {
|
||||
pending_ = false;
|
||||
post_accum_count_ = 0;
|
||||
if (cfg_.mode == TriggerMode::Single) {
|
||||
armed_ = false;
|
||||
} else {
|
||||
holdoff_until_s_ = now_s + std::max(0.0, cfg_.holdoff_s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Edge detection against the level.
|
||||
const bool crossed_up = prev_ < cfg_.level && value >= cfg_.level;
|
||||
const bool crossed_down = prev_ > cfg_.level && value <= cfg_.level;
|
||||
const bool fired = (cfg_.edge == TriggerEdge::Rising && crossed_up) ||
|
||||
(cfg_.edge == TriggerEdge::Falling && crossed_down) ||
|
||||
(cfg_.edge == TriggerEdge::Both && (crossed_up || crossed_down));
|
||||
prev_ = value;
|
||||
if (!fired) return false;
|
||||
|
||||
// The pre-trigger window has to already be behind this edge, or the capture opens
|
||||
// on a half-filled pre window and the event is short on its left side -- the plot
|
||||
// then shows a window that is correctly sized but only partly drawn. The buffer
|
||||
// fills whether or not the trigger is armed, so this normally passes on the first
|
||||
// edge; it only bites just after a rebuild (a CONFIG, or enabling the signal),
|
||||
// when the history genuinely is not there yet.
|
||||
if (now_s - oldest_s_ < pre_seconds_) return false;
|
||||
|
||||
// The edge's own time, which is what a trigger marker marks: the latch itself
|
||||
// may happen a post-window later.
|
||||
last_trigger_s_ = now_s;
|
||||
|
||||
// The edge always opens a capture; there is no "latch on the edge itself" case.
|
||||
// A zero-length post window latches on the very next sample, which is the least a
|
||||
// capture can hold, and every longer window is just more samples -- no conversion
|
||||
// from seconds to a sample count, so no conversion to get wrong.
|
||||
pending_ = true;
|
||||
pending_start_s_ = now_s;
|
||||
post_accum_count_ = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace udpscope
|
||||
Reference in new issue
Block a user