Улучшения
- улушчено отображение на OLED - убраны настройки шага частоты и количества повторов - сделан перебор только реализуемых частот - увеличена точность, на 1МГц 1.25%, в остальных до 1% - точное измерение TOTAL TIME
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user