попытки запустится до 1 МГц

This commit is contained in:
2026-08-05 18:54:42 +03:00
parent c4c9167df1
commit 1edc420b77
11 changed files with 182 additions and 63 deletions

View File

@@ -4,12 +4,17 @@
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;
expectedHz_ = static_cast<uint32_t>(hz + 0.5f);
if (!expectedHz_ || !timeMs || !repeats || repeats > 10 ||
!makePeriodLimits(expectedHz_, duty, tolerance, receiver_.tickHz(), limits_) ||
!receiver_.start(expectedHz_)) return false;
timeMs_ = timeMs; repeats_ = repeats; settleLeft_ = settleCycles;
stats_.reset(); memset(repeatPeriods_, 0, sizeof(repeatPeriods_));
measurementStartTick_ = deadlineTick_ = 0; startedMs_ = millis();
measurementStartMs_ = lastPeriodMs_ = 0;
currentRepeat_ = 0;
expectedPeriodMs_ = static_cast<uint32_t>((1000ULL + expectedHz_ - 1U) / expectedHz_);
if (!expectedPeriodMs_) expectedPeriodMs_ = 1;
state_ = MeasureState::SETTLING; return true;
}
@@ -18,53 +23,65 @@ void Measurement::fail(FailReason reason) {
receiver_.stop(); state_ = MeasureState::FAIL;
}
void Measurement::completeWindow() {
receiver_.stop();
stats_.lostItems += receiver_.takeDroppedItems();
if (receiver_.overflowed()) { fail(FailReason::GLITCH); return; }
for (uint8_t i = 0; i < repeats_; ++i) if (!repeatPeriods_[i]) {
fail(FailReason::TOO_FEW_PERIODS); return;
}
if (stats_.lostItems && stats_.reason == FailReason::NONE) stats_.reason = FailReason::DATA_LOST;
state_ = MeasureState::PASS;
}
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;
bool receivedPeriod = false;
for (;;) {
const size_t periodCount = receiver_.readPeriods(periodBatch_, PERIOD_BATCH_SIZE);
stats_.lostItems += receiver_.takeDroppedItems();
if (!periodCount) break;
receivedPeriod = true;
for (size_t periodIndex = 0; periodIndex < periodCount; ++periodIndex) {
const PulsePeriod &period = periodBatch_[periodIndex];
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_;
nextRepeatTick_ = measurementStartTick_ + repeatTicks_;
stats_.reset(); measurementStartMs_ = lastPeriodMs_ = millis(); state_ = MeasureState::RUNNING;
}
continue;
}
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_;
}
++repeatPeriods_[currentRepeat_];
const FailReason r = evaluatePeriodFast(period, receiver_.tickHz(), limits_, currentRepeat_ + 1, stats_);
if (r != FailReason::NONE) { fail(r); return state_; }
}
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_; }
}
uint64_t expectedPeriodMs = static_cast<uint64_t>(ceilf(1000.0f / expectedHz_));
if (!expectedPeriodMs) expectedPeriodMs = 1;
if (receivedPeriod && state_ == MeasureState::RUNNING) lastPeriodMs_ = millis();
const uint64_t edgeBasedTimeout =
static_cast<uint64_t>(PWM_SETTLE_CYCLES + NO_SIGNAL_TIMEOUT_PERIODS) * expectedPeriodMs + 20;
static_cast<uint64_t>(PWM_SETTLE_CYCLES + NO_SIGNAL_TIMEOUT_PERIODS) * expectedPeriodMs_ + 20;
const uint64_t rmtBatchTimeout =
static_cast<uint64_t>(RMT_MIN_RECEIVE_SYMBOLS + NO_SIGNAL_TIMEOUT_PERIODS) * expectedPeriodMs + 20;
static_cast<uint64_t>(RMT_MIN_RECEIVE_SYMBOLS + NO_SIGNAL_TIMEOUT_PERIODS) * expectedPeriodMs_ + 20;
const uint64_t settleTimeout = edgeBasedTimeout > rmtBatchTimeout ? edgeBasedTimeout : rmtBatchTimeout;
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);
const uint32_t edgeTimeoutMs = 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;
}
if (now - measurementStartMs_ > totalMs + expectedPeriodMs_ + 2) completeWindow();
}
return state_;
}