feat: a pulse whose width is wrong can be the trigger's event, so a glitch can be caught

This commit is contained in:
Martino Ferrari committed 2026-10-07 17:32:11 +02:00
1 parent b3fd9ae00f
commit d147678b1c
3 files changed
+245 -1

No files matched your search

+52
View File
@@ -14,6 +14,9 @@ void EventDetector::configure(const EventCondition& c) noexcept {
void EventDetector::reset() noexcept {
have_prev_ = false;
prev_ = 0.0;
in_pulse_ = false;
pulse_up_ = false;
pulse_start_s_ = 0.0;
}
double EventDetector::feed(double value, double t) noexcept {
@@ -28,6 +31,8 @@ double EventDetector::feed(double value, double t) noexcept {
event = feed_edge(value, t);
break;
case TriggerType::PulseWidth:
event = feed_pulse(value, t);
break;
case TriggerType::Window:
case TriggerType::Dropout:
break; // implemented in the tasks that add their panel rows
@@ -46,4 +51,51 @@ double EventDetector::feed_edge(double value, double t) noexcept {
return fired ? t : kNoEvent;
}
bool EventDetector::qualifies(double width_s) const noexcept {
const double a = cond_.width_s < cond_.width2_s ? cond_.width_s : cond_.width2_s;
const double b = cond_.width_s < cond_.width2_s ? cond_.width2_s : cond_.width_s;
switch (cond_.cmp) {
case WidthCmp::Less:
return width_s < cond_.width_s;
case WidthCmp::Greater:
return width_s > cond_.width_s;
case WidthCmp::Within:
return width_s >= a && width_s <= b;
case WidthCmp::Outside:
return width_s < a || width_s > b;
}
return false;
}
double EventDetector::feed_pulse(double value, double t) noexcept {
const bool up = crossed_up(value);
const bool down = crossed_down(value);
if (!in_pulse_) {
// Which crossing opens a pulse is what `edge` selects: Rising measures the time spent
// above the level, Falling the time below, Both every excursion either way.
const bool opens = (cond_.edge == TriggerEdge::Rising && up) ||
(cond_.edge == TriggerEdge::Falling && down) ||
(cond_.edge == TriggerEdge::Both && (up || down));
if (opens) {
in_pulse_ = true;
pulse_up_ = up;
pulse_start_s_ = t;
}
return kNoEvent;
}
const bool closes = pulse_up_ ? down : up;
if (!closes) return kNoEvent;
const double width = t - pulse_start_s_;
if (cond_.edge == TriggerEdge::Both) {
// The closing edge of one excursion is the opening edge of the next, so a square wave
// measures *every* half-period. Dropping the state here instead would measure every
// other one, and the hits would come out half as dense as the waveform.
pulse_up_ = !pulse_up_;
pulse_start_s_ = t;
} else {
in_pulse_ = false;
}
return qualifies(width) ? t : kNoEvent;
}
} // namespace udpscope