запущен тест между есп с перемычкой

This commit is contained in:
2026-08-07 16:04:30 +03:00
parent 4b88ac6a42
commit a8099bf2b8
14 changed files with 449 additions and 121 deletions

View File

@@ -9,8 +9,15 @@ bool Measurement::start(float hz, float duty, float tolerance, uint32_t timeMs,
if (!expectedHz_ || !timeMs || !repeats || repeats > 10 ||
!makePeriodLimits(expectedHz_, duty, tolerance, receiver_.tickHz(), limits_) ||
!receiver_.start(expectedHz_)) return false;
timeMs_ = timeMs; repeats_ = repeats; settleLeft_ = settleCycles;
repeats_ = repeats; settleCycles_ = settleCycles; settleLeft_ = settleCycles;
stepTimeMs_ = (timeMs + MEASUREMENT_PROGRESS_STEPS - 1U) / MEASUREMENT_PROGRESS_STEPS;
stepTicks_ = static_cast<uint64_t>(receiver_.tickHz()) * timeMs /
(1000ULL * MEASUREMENT_PROGRESS_STEPS);
if (!stepTicks_) stepTicks_ = 1;
totalSteps_ = repeats * MEASUREMENT_PROGRESS_STEPS;
currentStep_ = currentRepeat_ = 0;
stats_.reset(); memset(repeatPeriods_, 0, sizeof(repeatPeriods_));
publishStats();
measurementStartTick_ = deadlineTick_ = 0; startedMs_ = millis();
measurementStartMs_ = lastPeriodMs_ = 0;
currentRepeat_ = 0;
@@ -34,19 +41,39 @@ void Measurement::taskLoop() {
void Measurement::fail(FailReason reason) {
if (stats_.reason == FailReason::NONE) stats_.reason = reason;
publishStats();
receiver_.stop(); state_ = MeasureState::FAIL;
}
void Measurement::completeWindow() {
void Measurement::completeStep() {
receiver_.stop();
stats_.droppedItems += receiver_.takeDroppedItems();
if (receiver_.overflowed()) { fail(FailReason::GLITCH); return; }
++currentStep_;
publishStats();
if (currentStep_ < totalSteps_) {
state_ = MeasureState::STEP_READY;
return;
}
for (uint8_t i = 0; i < repeats_; ++i) if (!repeatPeriods_[i]) {
fail(FailReason::TOO_FEW_PERIODS); return;
}
state_ = MeasureState::PASS;
}
void Measurement::publishStats() {
portENTER_CRITICAL(&statsMux_);
publishedStats_ = stats_;
portEXIT_CRITICAL(&statsMux_);
}
bool Measurement::statsSnapshot(StageStats &out) const {
portENTER_CRITICAL(&statsMux_);
out = publishedStats_;
portEXIT_CRITICAL(&statsMux_);
return out.periods && out.periodSum;
}
MeasureState Measurement::processOnce() {
if (state_ != MeasureState::SETTLING && state_ != MeasureState::RUNNING) return state_;
if (receiver_.overflowed()) { fail(FailReason::GLITCH); return state_; }
@@ -63,19 +90,15 @@ MeasureState Measurement::processOnce() {
if (settleLeft_) --settleLeft_;
if (!settleLeft_) {
measurementStartTick_ = period.startTick + period.periodTicks;
repeatTicks_ = static_cast<uint64_t>(receiver_.tickHz()) * timeMs_ / 1000ULL;
deadlineTick_ = measurementStartTick_ + repeatTicks_ * repeats_;
nextRepeatTick_ = measurementStartTick_ + repeatTicks_;
stats_.reset(); measurementStartMs_ = lastPeriodMs_ = millis(); state_ = MeasureState::RUNNING;
deadlineTick_ = measurementStartTick_ + stepTicks_;
currentRepeat_ = currentStep_ / MEASUREMENT_PROGRESS_STEPS;
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_) { completeWindow(); return state_; } // trailing incomplete period
while (currentRepeat_ + 1U < repeats_ && period.startTick >= nextRepeatTick_) {
++currentRepeat_; nextRepeatTick_ += repeatTicks_;
}
if (endTick > deadlineTick_) { completeStep(); return state_; } // trailing incomplete period
++repeatPeriods_[currentRepeat_];
const FailReason r = evaluatePeriodFast(period, receiver_.tickHz(), limits_, currentRepeat_ + 1, stats_);
if (r != FailReason::NONE) { fail(r); return state_; }
@@ -90,16 +113,32 @@ MeasureState Measurement::processOnce() {
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 = expectedPeriodMs_ * NO_SIGNAL_TIMEOUT_PERIODS + 2;
if (now - measurementStartMs_ < totalMs && now - lastPeriodMs_ > edgeTimeoutMs) {
if (now - measurementStartMs_ < stepTimeMs_ && now - lastPeriodMs_ > edgeTimeoutMs) {
fail(FailReason::LOST_EDGE); return state_;
}
if (now - measurementStartMs_ > totalMs + expectedPeriodMs_ + 2) completeWindow();
if (now - measurementStartMs_ > stepTimeMs_ + expectedPeriodMs_ + 2) completeStep();
}
return state_;
}
MeasureState Measurement::update() { return state_; }
void Measurement::abort() { if (state_ == MeasureState::SETTLING || state_ == MeasureState::RUNNING) fail(FailReason::ABORTED); }
bool Measurement::continueAfterDisplay() {
if (state_ != MeasureState::STEP_READY) return false;
if (!receiver_.start(expectedHz_)) {
fail(FailReason::UNSUPPORTED);
return false;
}
settleLeft_ = settleCycles_;
measurementStartTick_ = deadlineTick_ = 0;
startedMs_ = millis(); measurementStartMs_ = lastPeriodMs_ = 0;
state_ = MeasureState::SETTLING;
xTaskNotifyGive(task_);
return true;
}
void Measurement::abort() {
if (state_ == MeasureState::SETTLING || state_ == MeasureState::RUNNING ||
state_ == MeasureState::STEP_READY) fail(FailReason::ABORTED);
}