#pragma once #include #include #include #include #include #include namespace adc_sweep { struct SweepMeta { uint32_t sweep_idx = 0; int32_t ch_primary = 0; uint32_t ch_mask = 0; float n_valid = 0.0f; float min = 0.0f; float max = 0.0f; float mean = 0.0f; float std = 0.0f; float dt_ms = 0.0f; uint64_t ts_mono_ns = 0; }; struct SweepResult { std::vector sweep; SweepMeta meta; }; int32_t u32_to_i32(uint32_t v); class SweepFinalizer { public: SweepFinalizer(uint32_t sweep_width, float invert_threshold, bool fancy_fill); std::optional finalize( const std::vector& xs, const std::vector& ys, uint32_t ch_mask, int32_t ch_primary); private: uint32_t sweep_width_; float invert_threshold_; bool fancy_fill_; uint32_t max_width_seen_ = 0; uint32_t sweep_idx_ = 0; std::optional last_sweep_ts_; std::deque> n_valid_hist_; }; class BinarySweepParser { public: using SweepCallback = std::function&, const std::vector&, uint32_t, int32_t)>; void feed(const uint8_t* data, size_t size, const SweepCallback& on_sweep); void flush(const SweepCallback& on_sweep); private: void emit_current(const SweepCallback& on_sweep); std::vector xs_; std::vector ys_; bool has_cur_channel_ = false; int32_t cur_channel_ = 0; uint32_t ch_mask_ = 0; std::deque words_; std::optional odd_byte_; }; } // namespace adc_sweep