feat: the trigger can ignore a noise band and reject HF before comparing

This commit is contained in:
Martino Ferrari committed 2026-10-13 15:04:52 +02:00
1 parent d5a9b3c5d5
commit d34bff3f03
9 files changed
+99 -16

No files matched your search

+24 -2
View File
@@ -33,11 +33,17 @@ struct EventCondition {
double width_s = 1.0e-3; ///< PulseWidth only.
double width2_s = 2.0e-3; ///< PulseWidth, Within/Outside only.
double timeout_s = 1.0e-3; ///< Dropout only.
/// Half-width of the amplitude band around `level` a sample must leave before
/// a crossing counts. 0 is the bare comparator. In signal units.
double noise_band = 0.0;
/// Corner of a one-pole low pass applied to the sample before any comparison.
/// 0 is off. In Hz.
double hf_fc = 0.0;
bool operator==(const EventCondition& o) const noexcept {
return type == o.type && level == o.level && level2 == o.level2 && edge == o.edge &&
cmp == o.cmp && width_s == o.width_s && width2_s == o.width2_s &&
timeout_s == o.timeout_s;
timeout_s == o.timeout_s && noise_band == o.noise_band && hf_fc == o.hf_fc;
}
bool operator!=(const EventCondition& o) const noexcept { return !(*this == o); }
};
@@ -60,7 +66,10 @@ class EventDetector {
/// Re-applying the same condition is a no-op, deliberately: the producer calls this on
/// every packet, and resetting there would restart the machine before any pulse could
/// close. A genuinely different condition resets, because its state means nothing.
void configure(const EventCondition& c) noexcept;
///
/// `dt` is the stored sample interval (`Partition::slot_dt()`), needed for the
/// HF reject's pole. A no-op unless the condition or the interval changed.
void configure(const EventCondition& c, double dt) noexcept;
void reset() noexcept;
/// One sample, in stream order. Returns the event's own stream time, or `kNoEvent`.
@@ -80,6 +89,10 @@ class EventDetector {
bool crossed_down(double v) const noexcept {
return prev_ > cond_.level && v <= cond_.level;
}
/// The HF reject, applied to every sample before any comparison.
double filter(double v) noexcept;
/// `up`/`down` for the edge condition, through the band if there is one.
void decide(double v, bool& up, bool& down) noexcept;
double feed_edge(double value, double t) noexcept;
double feed_pulse(double value, double t) noexcept;
double feed_window(double value, double t) noexcept;
@@ -98,6 +111,15 @@ class EventDetector {
bool inside_ = false; ///< Window: which side of the band the previous sample was.
double last_cross_s_ = 0.0; ///< Dropout: when the signal was last seen crossing.
bool dropped_ = false; ///< Dropout: the timeout has already been reported.
/// One-pole prefilter. `pole_a_ == 1` passes the input through, so "off"
/// costs no branch. `pole_y_` is the filtered value.
double dt_ = 0.0;
double pole_a_ = 1.0;
double pole_y_ = 0.0;
bool pole_have_ = false;
/// Which side of the band the signal was last *decided* to be on: +1 above,
/// -1 below, 0 undecided. A sample inside the band decides nothing.
int side_ = 0;
};
} // namespace udpscope