codex init
This commit is contained in:
68
OpticalChannelTester/Measurement.cpp
Normal file
68
OpticalChannelTester/Measurement.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "Measurement.h"
|
||||
#include "Config.h"
|
||||
#include <string.h>
|
||||
|
||||
bool Measurement::start(float hz, float duty, float tolerance, uint32_t timeMs,
|
||||
uint8_t repeats, uint8_t settleCycles) {
|
||||
if (!hz || !timeMs || !repeats || repeats > 10 || !receiver_.start(static_cast<uint32_t>(hz))) return false;
|
||||
expectedHz_ = hz; expectedDuty_ = duty; tolerance_ = tolerance;
|
||||
timeMs_ = timeMs; repeats_ = repeats; settleLeft_ = settleCycles;
|
||||
stats_.reset(); memset(repeatPeriods_, 0, sizeof(repeatPeriods_));
|
||||
measurementStartTick_ = deadlineTick_ = 0; startedMs_ = millis();
|
||||
measurementStartMs_ = lastPeriodMs_ = 0;
|
||||
state_ = MeasureState::SETTLING; return true;
|
||||
}
|
||||
|
||||
void Measurement::fail(FailReason reason) {
|
||||
if (stats_.reason == FailReason::NONE) stats_.reason = reason;
|
||||
receiver_.stop(); state_ = MeasureState::FAIL;
|
||||
}
|
||||
|
||||
MeasureState Measurement::update() {
|
||||
if (state_ != MeasureState::SETTLING && state_ != MeasureState::RUNNING) return state_;
|
||||
if (receiver_.overflowed()) { fail(FailReason::GLITCH); return state_; }
|
||||
PulsePeriod period;
|
||||
while (receiver_.poll(period)) {
|
||||
if (state_ == MeasureState::SETTLING) {
|
||||
if (settleLeft_) --settleLeft_;
|
||||
if (!settleLeft_) {
|
||||
measurementStartTick_ = period.startTick + period.periodTicks;
|
||||
repeatTicks_ = static_cast<uint64_t>(receiver_.tickHz()) * timeMs_ / 1000ULL;
|
||||
deadlineTick_ = measurementStartTick_ + repeatTicks_ * repeats_;
|
||||
stats_.reset(); measurementStartMs_ = lastPeriodMs_ = millis(); state_ = MeasureState::RUNNING;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const uint64_t endTick = period.startTick + period.periodTicks;
|
||||
if (period.startTick < measurementStartTick_) continue; // leading incomplete period
|
||||
if (endTick > deadlineTick_) break; // trailing incomplete period
|
||||
uint8_t repeat = static_cast<uint8_t>((period.startTick - measurementStartTick_) / repeatTicks_);
|
||||
if (repeat >= repeats_) repeat = repeats_ - 1;
|
||||
++repeatPeriods_[repeat];
|
||||
lastPeriodMs_ = millis();
|
||||
const FailReason r = evaluatePeriod(period, receiver_.tickHz(), expectedHz_, expectedDuty_,
|
||||
tolerance_, repeat + 1, stats_);
|
||||
if (r != FailReason::NONE) { fail(r); return state_; }
|
||||
}
|
||||
const uint64_t expectedPeriodMs = static_cast<uint64_t>(1000.0f / expectedHz_) + 1;
|
||||
const uint64_t settleTimeout = (static_cast<uint64_t>(PWM_SETTLE_CYCLES + NO_SIGNAL_TIMEOUT_PERIODS) *
|
||||
expectedPeriodMs) + 20;
|
||||
if (state_ == MeasureState::SETTLING && millis() - startedMs_ > settleTimeout) fail(FailReason::NO_SIGNAL);
|
||||
if (state_ == MeasureState::RUNNING && measurementStartTick_) {
|
||||
const uint32_t now = millis();
|
||||
const uint32_t totalMs = timeMs_ * repeats_;
|
||||
const uint32_t edgeTimeoutMs = static_cast<uint32_t>(expectedPeriodMs * NO_SIGNAL_TIMEOUT_PERIODS + 2);
|
||||
if (now - measurementStartMs_ < totalMs && now - lastPeriodMs_ > edgeTimeoutMs) {
|
||||
fail(FailReason::LOST_EDGE); return state_;
|
||||
}
|
||||
if (now - measurementStartMs_ > totalMs + expectedPeriodMs + 2) {
|
||||
for (uint8_t i = 0; i < repeats_; ++i) if (!repeatPeriods_[i]) {
|
||||
fail(FailReason::TOO_FEW_PERIODS); return state_;
|
||||
}
|
||||
receiver_.stop(); state_ = MeasureState::PASS;
|
||||
}
|
||||
}
|
||||
return state_;
|
||||
}
|
||||
|
||||
void Measurement::abort() { if (state_ == MeasureState::SETTLING || state_ == MeasureState::RUNNING) fail(FailReason::ABORTED); }
|
||||
Reference in New Issue
Block a user