Улучшения

- улушчено отображение на OLED
- убраны настройки шага частоты и количества повторов
- сделан перебор только реализуемых частот
- увеличена точность, на 1МГц 1.25%, в остальных до 1%
- точное измерение TOTAL TIME
This commit is contained in:
2026-08-08 10:18:50 +03:00
parent a8099bf2b8
commit 21f8fe8e13
12 changed files with 293 additions and 151 deletions

View File

@@ -1,4 +1,5 @@
#include "Core.h"
#include "Config.h"
#include <math.h>
#include <string.h>
@@ -30,28 +31,52 @@ uint32_t settingsChecksum(const Settings &s) {
return hash;
}
uint32_t frequencyPointCount(uint32_t startHz, uint32_t endHz, uint32_t stepHz) {
if (!startHz || !stepHz || endHz <= startHz) return 0;
const uint64_t span = static_cast<uint64_t>(endHz) - startHz;
return static_cast<uint32_t>(span / stepHz + 1U + ((span % stepHz) ? 1U : 0U));
uint32_t frequencyPointCount(uint32_t startHz, uint32_t endHz) {
if (!startHz || endHz <= startHz) return 0;
uint32_t count = 0;
for (size_t i = 0; i < countOf(TEST_FREQUENCIES_HZ); ++i)
if (TEST_FREQUENCIES_HZ[i] >= startHz && TEST_FREQUENCIES_HZ[i] <= endHz) ++count;
return count;
}
uint32_t frequencyAt(uint32_t startHz, uint32_t endHz, uint32_t stepHz, uint32_t index) {
const uint32_t count = frequencyPointCount(startHz, endHz, stepHz);
if (!count || index >= count) return 0;
if (index == count - 1) return endHz;
const uint64_t v = static_cast<uint64_t>(startHz) + static_cast<uint64_t>(stepHz) * index;
return v < endHz ? static_cast<uint32_t>(v) : endHz;
uint32_t frequencyAt(uint32_t startHz, uint32_t endHz, uint32_t index) {
for (size_t i = 0; i < countOf(TEST_FREQUENCIES_HZ); ++i) {
const uint32_t frequency = TEST_FREQUENCIES_HZ[i];
if (frequency < startHz || frequency > endHz) continue;
if (!index--) return frequency;
}
return 0;
}
uint64_t nominalStageUs(uint32_t frequencyHz, uint32_t sampleTimeMs, uint32_t settleCycles) {
if (!frequencyHz || !sampleTimeMs) return 0;
const uint64_t sampleUs = static_cast<uint64_t>(sampleTimeMs) * 1000ULL;
// At high frequency the CPU needs longer than the requested sample window
// to validate every captured period. Use the measured sustained C3 rate.
const uint64_t processingUs =
(static_cast<uint64_t>(frequencyHz) * sampleTimeMs * 1000ULL +
RX_PROCESSING_PERIODS_PER_SECOND - 1U) / RX_PROCESSING_PERIODS_PER_SECOND;
const uint64_t samplingWallUs = processingUs > sampleUs ? processingUs : sampleUs;
uint64_t chunkSymbols =
(static_cast<uint64_t>(frequencyHz) * RMT_TARGET_CHUNK_US + 999999ULL) / 1000000ULL;
if (chunkSymbols < RMT_MIN_RECEIVE_SYMBOLS) chunkSymbols = RMT_MIN_RECEIVE_SYMBOLS;
if (chunkSymbols > RMT_MAX_RECEIVE_SYMBOLS) chunkSymbols = RMT_MAX_RECEIVE_SYMBOLS;
const uint64_t batchWaitUs =
((chunkSymbols * 1000000ULL + frequencyHz - 1U) / frequencyHz) * MEASUREMENT_PROGRESS_STEPS;
const uint64_t settleUs =
(1000000ULL * settleCycles * MEASUREMENT_PROGRESS_STEPS + frequencyHz - 1U) / frequencyHz;
// Initial stage screen, nine intermediate screens and the final result.
const uint64_t displayUs = static_cast<uint64_t>(OLED_PROGRESS_UPDATE_MS) * 1000ULL *
(MEASUREMENT_PROGRESS_STEPS + 1U);
return samplingWallUs + batchWaitUs + settleUs + displayUs;
}
uint64_t nominalTotalUs(const TestParams &p, uint32_t settleCycles) {
uint64_t total = 0;
const uint32_t count = frequencyPointCount(p.startHz, p.endHz, p.stepHz);
for (uint32_t i = 0; i < count; ++i) {
const uint32_t f = frequencyAt(p.startHz, p.endHz, p.stepHz, i);
total += (1000000ULL * settleCycles + f - 1) / f;
total += static_cast<uint64_t>(p.testTimeMs) * 1000ULL * p.repeats;
}
const uint32_t count = frequencyPointCount(p.startHz, p.endHz);
for (uint32_t i = 0; i < count; ++i)
total += nominalStageUs(frequencyAt(p.startHz, p.endHz, i), p.testTimeMs, settleCycles);
return total;
}
@@ -63,6 +88,10 @@ bool dutyWithin(float measured, float expected, float tolerance) {
return fabsf(measured - expected) <= tolerance + 0.0001f;
}
float effectiveTolerancePct(float configured) {
return configured > 0.0f && configured <= 1.0001f ? 1.25f : configured;
}
uint8_t choosePwmResolution(uint32_t frequencyHz, uint32_t sourceClockHz,
uint8_t maxBits) {
if (!frequencyHz || !sourceClockHz || !maxBits) return 0;
@@ -148,7 +177,8 @@ FailReason validateResolution(uint32_t frequencyHz, float dutyPct, float accurac
// Measurement uses the duty actually programmed into LEDC. A coarse PWM
// step is not itself an error when the requested value (e.g. 50%) is exactly
// representable; only the selected value's actual quantization matters.
return (timerPeriodError > accuracyPct || timerDutyError > accuracyPct)
const float effectiveAccuracy = effectiveTolerancePct(accuracyPct);
return (timerPeriodError > effectiveAccuracy || timerDutyError > effectiveAccuracy)
? FailReason::RESOLUTION : FailReason::NONE;
}