fix: the hole reservation now runs after the accumulator re-plan, so value_acc_ is always sized to channels.size() before reserve_hole() writes into it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
e9d259ac7f
commit
d38ab3f9c9
1 file changed
+18
-13
+18
-13
@@ -518,6 +518,19 @@ void Acquisition::on_data(const udps_frame_t* frame) {
|
||||
BufferStore& store = model_.live();
|
||||
const u64 g = part.time_stride;
|
||||
|
||||
// The filter's groups are `g` long, so a re-plan has to start a fresh group rather than
|
||||
// finish the one it was in with the wrong length.
|
||||
if (acc_stride_ != g || acc_channels_ != channels.size()) {
|
||||
acc_stride_ = g;
|
||||
acc_channels_ = channels.size();
|
||||
value_acc_.assign(channels.size(), 0.0);
|
||||
value_acc_n_.assign(channels.size(), 0);
|
||||
math_sample_.assign(channels.size(), std::nanf(""));
|
||||
time_acc_ = 0.0;
|
||||
abs_time_acc_ = 0.0;
|
||||
time_acc_n_ = 0;
|
||||
}
|
||||
|
||||
// The gap the counter reports, reserved as NaN before this frame's own samples are
|
||||
// stamped: the hole belongs *ahead* of the data that revealed it. Running the missing
|
||||
// samples through the same per-sample loop below is the whole trick -- `tick_` advances
|
||||
@@ -528,6 +541,11 @@ void Acquisition::on_data(const udps_frame_t* frame) {
|
||||
// Capped at `kGlitchPackets`: 256 packet spans in one go is an outage, not loss, and
|
||||
// reserving one would push the entire retained history out of the ring to make room for
|
||||
// samples that are not coming.
|
||||
//
|
||||
// This block must follow the re-plan above: reserve_hole() runs the missing samples
|
||||
// through the same decimation accumulators (value_acc_, value_acc_n_, math_sample_),
|
||||
// which must already be sized to the current channel count and stride before any
|
||||
// per-sample write.
|
||||
const std::uint32_t missing = frame->late ? 0u : frame->lost;
|
||||
if (missing > 0 && batch_ > 0 && double(missing) <= kGlitchPackets) {
|
||||
reserve_hole(missing, part, channels, store, g);
|
||||
@@ -542,19 +560,6 @@ void Acquisition::on_data(const udps_frame_t* frame) {
|
||||
std::fflush(stderr);
|
||||
}
|
||||
|
||||
// The filter's groups are `g` long, so a re-plan has to start a fresh group rather than
|
||||
// finish the one it was in with the wrong length.
|
||||
if (acc_stride_ != g || acc_channels_ != channels.size()) {
|
||||
acc_stride_ = g;
|
||||
acc_channels_ = channels.size();
|
||||
value_acc_.assign(channels.size(), 0.0);
|
||||
value_acc_n_.assign(channels.size(), 0);
|
||||
math_sample_.assign(channels.size(), std::nanf(""));
|
||||
time_acc_ = 0.0;
|
||||
abs_time_acc_ = 0.0;
|
||||
time_acc_n_ = 0;
|
||||
}
|
||||
|
||||
// Calibration is read per frame; it only changes under the same lock.
|
||||
TriggerEngine& engine = engine_;
|
||||
const int trig_channel = tc.channel;
|
||||
|
||||
Reference in new issue
Block a user