доработки всякие
This commit is contained in:
@@ -166,7 +166,7 @@ void App::update() {
|
||||
}
|
||||
if (state_ == AppState::MENU) {
|
||||
if (modeEvent == ButtonEvent::SHORT) {
|
||||
menuItem_ = (menuItem_ + 1U) % 5U; Log::printf("ACTION", "menu item selected index=%u", menuItem_); showMenu();
|
||||
menuItem_ = (menuItem_ + 1U) % 4U; Log::printf("ACTION", "menu item selected index=%u", menuItem_); showMenu();
|
||||
}
|
||||
else if (modeEvent == ButtonEvent::LONG) {
|
||||
sanitizeRange(); const bool saved = store_.save(settings_); params_ = store_.params(settings_);
|
||||
@@ -237,7 +237,7 @@ void App::changeMenu(int d) {
|
||||
case 1: value = &settings_.endIndex; count = countOf(END_FREQ_OPTIONS_HZ); break;
|
||||
case 2: value = &settings_.accuracyIndex; count = countOf(ACCURACY_OPTIONS_PCT); break;
|
||||
case 3: value = &settings_.timeIndex; count = countOf(TEST_TIME_OPTIONS_MS); break;
|
||||
default: value = &settings_.dutyIndex; count = countOf(DUTY_OPTIONS_PCT); break;
|
||||
default: return;
|
||||
}
|
||||
*value = static_cast<uint8_t>((*value + count + d) % count);
|
||||
Log::printf("ACTION", "menu item=%u changed direction=%+d new-index=%u", menuItem_, d, *value);
|
||||
@@ -263,14 +263,10 @@ void App::showMenu() {
|
||||
snprintf(value, sizeof(value), "+/-%g%%", params_.accuracyPct);
|
||||
label = UiText::MENU_ACCURACY;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
snprintf(value, sizeof(value), "%.1fs", params_.testTimeMs / 1000.0f);
|
||||
label = UiText::MENU_TEST_TIME;
|
||||
break;
|
||||
default:
|
||||
snprintf(value, sizeof(value), "%u%%", params_.dutyPct);
|
||||
label = UiText::MENU_PWM_DUTY;
|
||||
break;
|
||||
}
|
||||
formatMenuLine(label, value, one, sizeof(one));
|
||||
formatMenuLine(UiText::MENU_TOTAL_TIME, all, total, sizeof(total));
|
||||
@@ -340,7 +336,8 @@ bool App::prepareStage(bool showProgress) {
|
||||
}
|
||||
const uint32_t plannedRxHz = receiver_.plannedTickHz(actual_.actualHz, actual_.actualDutyPct);
|
||||
const FailReason resolution = validateResolution(actual_.actualHz, actual_.actualDutyPct, params_.accuracyPct,
|
||||
plannedRxHz, actual_.bits);
|
||||
plannedRxHz, actual_.bits,
|
||||
MEASUREMENT_AVERAGING_PERIODS);
|
||||
if (resolution != FailReason::NONE) {
|
||||
Log::printf("PWM", "resolution rejected: actual=%luHz duty=%.3f%% bits=%u RXclock=%luHz tolerance=%.3f%%",
|
||||
actual_.actualHz, actual_.actualDutyPct, actual_.bits, plannedRxHz,
|
||||
@@ -357,10 +354,11 @@ bool App::prepareStage(bool showProgress) {
|
||||
}
|
||||
|
||||
bool App::startLocalMeasurement(float hz, float duty) {
|
||||
Log::printf("MEASURE", "arming expected=%.3fHz duty=%.3f%% tolerance=%.3f%% RX=%luHz settle=%u cycles window=%lums; per-pulse logging suspended",
|
||||
Log::printf("MEASURE", "arming expected=%.3fHz duty=%.3f%% tolerance=%.3f%% RX=%luHz settle=%u cycles window=%lums average=%u periods; per-pulse logging suspended",
|
||||
hz, duty, effectiveTolerancePct(params_.accuracyPct), receiver_.plannedTickHz(static_cast<uint32_t>(hz + 0.5f), duty),
|
||||
PWM_SETTLE_CYCLES, params_.testTimeMs);
|
||||
const bool ok = measurement_.start(hz, duty, params_.accuracyPct, params_.testTimeMs, PWM_SETTLE_CYCLES);
|
||||
PWM_SETTLE_CYCLES, params_.testTimeMs, MEASUREMENT_AVERAGING_PERIODS);
|
||||
const bool ok = measurement_.start(hz, duty, params_.accuracyPct, params_.testTimeMs,
|
||||
MEASUREMENT_AVERAGING_PERIODS, PWM_SETTLE_CYCLES);
|
||||
Log::printf("MEASURE", "receiver start %s, RMT chunk=%u symbols", ok ? "OK" : "FAILED",
|
||||
receiver_.receiveChunkSymbols());
|
||||
return ok;
|
||||
@@ -686,7 +684,14 @@ void App::finish(bool pass, FailReason reason, bool preserveDisplay) {
|
||||
armSlave(true);
|
||||
return;
|
||||
}
|
||||
if (static_cast<Role>(settings_.role) == Role::SLAVE) slaveRearmAtMs_ = millis() + 2000;
|
||||
// The result has already been acknowledged before a normal measurement
|
||||
// failure reaches here. Re-arm ESP-NOW immediately so a quick retry from
|
||||
// Master is not hidden behind the former two-second delay; preserve the
|
||||
// failure screen while listening.
|
||||
if (static_cast<Role>(settings_.role) == Role::SLAVE) {
|
||||
armSlave(true);
|
||||
return;
|
||||
}
|
||||
if (preserveDisplay) return;
|
||||
char one[64];
|
||||
if (pass) {
|
||||
|
||||
@@ -104,6 +104,12 @@ constexpr uint16_t RMT_MAX_RECEIVE_SYMBOLS = 512;
|
||||
constexpr uint32_t RMT_TARGET_CHUNK_US = 5000;
|
||||
constexpr uint8_t RMT_QUEUE_BLOCKS = 8;
|
||||
constexpr uint16_t PERIOD_BATCH_SIZE = 128;
|
||||
// Frequency and duty are validated only by their averages over this many
|
||||
// complete periods. Individual tick variation is retained for diagnostics but
|
||||
// is not itself a test failure.
|
||||
constexpr uint16_t MEASUREMENT_AVERAGING_PERIODS = 100;
|
||||
static_assert(MEASUREMENT_AVERAGING_PERIODS > 0,
|
||||
"Averaging window must contain at least one period");
|
||||
constexpr uint8_t MEASUREMENT_PROGRESS_STEPS = 10;
|
||||
constexpr uint32_t OLED_PROGRESS_UPDATE_MS = 15;
|
||||
|
||||
@@ -149,6 +155,6 @@ constexpr uint32_t TEST_FREQUENCIES_HZ[] = {
|
||||
};
|
||||
constexpr float ACCURACY_OPTIONS_PCT[] = {1.0f, 2.0f, 5.0f, 10.0f};
|
||||
constexpr uint32_t TEST_TIME_OPTIONS_MS[] = {100, 250, 500, 1000, 2000, 5000};
|
||||
constexpr uint8_t DUTY_OPTIONS_PCT[] = {10, 25, 50, 75, 90};
|
||||
constexpr uint8_t TEST_DUTY_PCT = 50;
|
||||
|
||||
template <typename T, size_t N> constexpr size_t countOf(const T (&)[N]) { return N; }
|
||||
|
||||
@@ -39,7 +39,6 @@ constexpr const char *MENU_START_FREQUENCY = "ЧАСТОТА ОТ:";
|
||||
constexpr const char *MENU_END_FREQUENCY = "ЧАСТОТА ДО:";
|
||||
constexpr const char *MENU_ACCURACY = "ТОЧНОСТЬ:";
|
||||
constexpr const char *MENU_TEST_TIME = "ВРЕМЯ ВЫБОРКИ:";
|
||||
constexpr const char *MENU_PWM_DUTY = "ЗАПОЛНЕНИЕ:";
|
||||
constexpr const char *MENU_TOTAL_TIME = "ОБЩЕЕ ВРЕМЯ:";
|
||||
constexpr const char *FREQUENCY_UNIT = " Гц";
|
||||
|
||||
@@ -89,7 +88,6 @@ constexpr const char *MENU_START_FREQUENCY = "START FREQ:";
|
||||
constexpr const char *MENU_END_FREQUENCY = "END FREQ:";
|
||||
constexpr const char *MENU_ACCURACY = "ACCURACY:";
|
||||
constexpr const char *MENU_TEST_TIME = "TEST TIME:";
|
||||
constexpr const char *MENU_PWM_DUTY = "PWM DUTY:";
|
||||
constexpr const char *MENU_TOTAL_TIME = "TOTAL TIME:";
|
||||
constexpr const char *FREQUENCY_UNIT = " Hz";
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ bool dutyWithin(float measured, float expected, float tolerance) {
|
||||
}
|
||||
|
||||
float effectiveTolerancePct(float configured) {
|
||||
return configured > 0.0f && configured <= 1.0001f ? 1.25f : configured;
|
||||
return configured;
|
||||
}
|
||||
|
||||
uint8_t choosePwmResolution(uint32_t frequencyHz, uint32_t sourceClockHz,
|
||||
@@ -166,14 +166,17 @@ bool chooseIntegerPwmConfig(uint32_t requestedHz, uint32_t sourceClockHz,
|
||||
}
|
||||
|
||||
FailReason validateResolution(uint32_t frequencyHz, float dutyPct, float accuracyPct,
|
||||
uint32_t captureHz, uint8_t pwmBits) {
|
||||
if (!frequencyHz || !captureHz || !pwmBits) return FailReason::RESOLUTION;
|
||||
uint32_t captureHz, uint8_t pwmBits,
|
||||
uint16_t averagingPeriods) {
|
||||
if (!frequencyHz || !captureHz || !pwmBits || !averagingPeriods)
|
||||
return FailReason::RESOLUTION;
|
||||
const float periodTicks = static_cast<float>(captureHz) / frequencyHz;
|
||||
const float activeTicks = periodTicks * dutyPct / 100.0f;
|
||||
const float inactiveTicks = periodTicks - activeTicks;
|
||||
if (periodTicks < 4.0f || activeTicks < 2.0f || inactiveTicks < 2.0f) return FailReason::RESOLUTION;
|
||||
const float timerPeriodError = 100.0f / periodTicks;
|
||||
const float timerDutyError = 100.0f / periodTicks;
|
||||
const float averagedTicks = periodTicks * averagingPeriods;
|
||||
const float timerPeriodError = 100.0f / averagedTicks;
|
||||
const float timerDutyError = 100.0f / averagedTicks;
|
||||
// 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.
|
||||
@@ -256,3 +259,60 @@ FailReason evaluatePeriodFast(const PulsePeriod &p, uint32_t tickHz,
|
||||
}
|
||||
return reason;
|
||||
}
|
||||
|
||||
FailReason evaluatePeriodWindow(uint64_t periodSum, uint64_t activeSum,
|
||||
uint32_t periodCount, uint32_t tickHz,
|
||||
float expectedHz, float expectedDuty,
|
||||
float tolerance,
|
||||
uint32_t minPeriod, uint32_t maxPeriod,
|
||||
uint8_t repeat,
|
||||
StageStats &s) {
|
||||
if (!periodSum || !periodCount || activeSum >= periodSum || !tickHz)
|
||||
return FailReason::EXTRA_EDGE;
|
||||
const float hz = static_cast<float>(
|
||||
static_cast<double>(tickHz) * periodCount / periodSum);
|
||||
const float duty = static_cast<float>(
|
||||
100.0 * static_cast<double>(activeSum) / periodSum);
|
||||
bool frequencyOk = periodWithin(hz, expectedHz, tolerance);
|
||||
if (!frequencyOk && maxPeriod == minPeriod + 1U) {
|
||||
// At a tolerance boundary, alternating adjacent RMT counts prove that the
|
||||
// result is quantization-limited. Accept only when a one-tick correction
|
||||
// toward the expected value returns the averaged frequency into tolerance.
|
||||
// Consecutive periods telescope into one first-to-last edge interval, so
|
||||
// the whole window has a one-tick endpoint uncertainty, not one tick per
|
||||
// period.
|
||||
uint64_t correctedPeriodSum = periodSum;
|
||||
if (hz > expectedHz) ++correctedPeriodSum;
|
||||
else if (periodSum > 1U) --correctedPeriodSum;
|
||||
const float correctedHz = static_cast<float>(
|
||||
static_cast<double>(tickHz) * periodCount / correctedPeriodSum);
|
||||
frequencyOk = periodWithin(correctedHz, expectedHz, tolerance);
|
||||
}
|
||||
|
||||
bool dutyOk = dutyWithin(duty, expectedDuty, tolerance);
|
||||
if (!dutyOk) {
|
||||
// Unlike full periods, active intervals do not telescope: every pulse is
|
||||
// bounded by a different rising/falling edge pair. With slowly drifting
|
||||
// asynchronous clocks an entire short window can therefore quantize to
|
||||
// the same adjacent count (e.g. 41/80 for a true 50% duty). Apply one tick
|
||||
// per active interval even when minActive == maxActive.
|
||||
const bool dutyHigh = duty > expectedDuty;
|
||||
const uint64_t correctedActive = dutyHigh
|
||||
? (activeSum > periodCount ? activeSum - periodCount : 0U)
|
||||
: activeSum + periodCount;
|
||||
const float correctedDuty = static_cast<float>(
|
||||
100.0 * static_cast<double>(correctedActive) / periodSum);
|
||||
dutyOk = dutyWithin(correctedDuty, expectedDuty, tolerance);
|
||||
}
|
||||
|
||||
FailReason reason = !frequencyOk ? FailReason::PERIOD_OUT :
|
||||
(!dutyOk ? FailReason::DUTY_OUT : FailReason::NONE);
|
||||
if (reason != FailReason::NONE && s.reason == FailReason::NONE) {
|
||||
s.reason = reason;
|
||||
s.firstBadPeriod = s.periods >= periodCount ? s.periods - periodCount + 1U : 1U;
|
||||
s.firstBadRepeat = repeat;
|
||||
s.badFrequency = hz;
|
||||
s.badDuty = duty;
|
||||
}
|
||||
return reason;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ struct Settings {
|
||||
uint8_t endIndex;
|
||||
uint8_t accuracyIndex;
|
||||
uint8_t timeIndex;
|
||||
uint8_t dutyIndex;
|
||||
uint8_t reserved;
|
||||
uint32_t checksum;
|
||||
};
|
||||
|
||||
@@ -83,7 +83,8 @@ bool chooseIntegerPwmConfig(uint32_t requestedHz, uint32_t sourceClockHz,
|
||||
uint8_t maxBits, uint8_t dutyPct,
|
||||
IntegerPwmConfig &config);
|
||||
FailReason validateResolution(uint32_t frequencyHz, float dutyPct, float accuracyPct,
|
||||
uint32_t captureResolutionHz, uint8_t pwmBits);
|
||||
uint32_t captureResolutionHz, uint8_t pwmBits,
|
||||
uint16_t averagingPeriods);
|
||||
FailReason evaluatePeriod(const PulsePeriod &period, uint32_t tickHz, float expectedHz,
|
||||
float expectedDuty, float tolerancePct, uint8_t repeat,
|
||||
StageStats &stats);
|
||||
@@ -92,3 +93,10 @@ bool makePeriodLimits(uint32_t expectedHz, float expectedDuty, float tolerancePc
|
||||
FailReason evaluatePeriodFast(const PulsePeriod &period, uint32_t tickHz,
|
||||
const PeriodLimits &limits, uint8_t repeat,
|
||||
StageStats &stats);
|
||||
FailReason evaluatePeriodWindow(uint64_t periodSum, uint64_t activeSum,
|
||||
uint32_t periodCount, uint32_t tickHz,
|
||||
float expectedHz, float expectedDuty,
|
||||
float tolerancePct,
|
||||
uint32_t minPeriod, uint32_t maxPeriod,
|
||||
uint8_t repeat,
|
||||
StageStats &stats);
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
#include <string.h>
|
||||
|
||||
bool Measurement::start(float hz, float duty, float tolerance, uint32_t timeMs,
|
||||
uint8_t settleCycles) {
|
||||
uint16_t averagingPeriods, uint8_t settleCycles) {
|
||||
if (!task_ && xTaskCreate(taskEntry, "optical-rx", 4096, this, 4, &task_) != pdPASS) return false;
|
||||
expectedHz_ = static_cast<uint32_t>(hz + 0.5f);
|
||||
expectedDutyPct_ = duty;
|
||||
tolerance = effectiveTolerancePct(tolerance);
|
||||
if (!expectedHz_ || !timeMs ||
|
||||
if (!expectedHz_ || !timeMs || !averagingPeriods ||
|
||||
!receiver_.start(expectedHz_, expectedDutyPct_)) return false;
|
||||
if (!makePeriodLimits(expectedHz_, duty, tolerance, receiver_.tickHz(), limits_)) {
|
||||
receiver_.stop(); return false;
|
||||
}
|
||||
settleCycles_ = settleCycles; settleLeft_ = settleCycles;
|
||||
tolerancePct_ = tolerance;
|
||||
averagingPeriods_ = averagingPeriods;
|
||||
resetAveragingWindow();
|
||||
stepTimeMs_ = (timeMs + MEASUREMENT_PROGRESS_STEPS - 1U) / MEASUREMENT_PROGRESS_STEPS;
|
||||
stepTicks_ = static_cast<uint64_t>(receiver_.tickHz()) * timeMs /
|
||||
(1000ULL * MEASUREMENT_PROGRESS_STEPS);
|
||||
@@ -30,6 +30,13 @@ bool Measurement::start(float hz, float duty, float tolerance, uint32_t timeMs,
|
||||
return true;
|
||||
}
|
||||
|
||||
void Measurement::resetAveragingWindow() {
|
||||
windowPeriodCount_ = 0;
|
||||
windowPeriodSum_ = windowActiveSum_ = 0;
|
||||
windowMinPeriod_ = UINT32_MAX;
|
||||
windowMaxPeriod_ = 0;
|
||||
}
|
||||
|
||||
void Measurement::taskEntry(void *context) {
|
||||
static_cast<Measurement *>(context)->taskLoop();
|
||||
}
|
||||
@@ -51,6 +58,14 @@ void Measurement::completeMeasurement() {
|
||||
receiver_.stop();
|
||||
stats_.droppedItems += receiver_.takeDroppedItems();
|
||||
if (receiver_.overflowed()) { fail(FailReason::GLITCH); return; }
|
||||
if (windowPeriodCount_) {
|
||||
const FailReason result = evaluatePeriodWindow(
|
||||
windowPeriodSum_, windowActiveSum_, windowPeriodCount_, receiver_.tickHz(),
|
||||
expectedHz_, expectedDutyPct_, tolerancePct_,
|
||||
windowMinPeriod_, windowMaxPeriod_,
|
||||
currentStep_ + 1U, stats_);
|
||||
if (result != FailReason::NONE) { fail(result); return; }
|
||||
}
|
||||
publishStats();
|
||||
if (++currentStep_ < MEASUREMENT_PROGRESS_STEPS) {
|
||||
state_ = MeasureState::STEP_READY;
|
||||
@@ -99,8 +114,32 @@ MeasureState Measurement::processOnce() {
|
||||
const uint64_t endTick = period.startTick + period.periodTicks;
|
||||
if (period.startTick < measurementStartTick_) continue; // leading incomplete period
|
||||
if (endTick > deadlineTick_) { completeMeasurement(); return state_; } // trailing incomplete period
|
||||
const FailReason r = evaluatePeriodFast(period, receiver_.tickHz(), limits_, 1, stats_);
|
||||
if (r != FailReason::NONE) { fail(r); return state_; }
|
||||
if (!period.periodTicks || period.activeTicks >= period.periodTicks) {
|
||||
fail(FailReason::EXTRA_EDGE); return state_;
|
||||
}
|
||||
|
||||
++stats_.periods;
|
||||
stats_.periodSum += period.periodTicks;
|
||||
stats_.activeSum += period.activeTicks;
|
||||
if (period.periodTicks < stats_.minPeriod) stats_.minPeriod = period.periodTicks;
|
||||
if (period.periodTicks > stats_.maxPeriod) stats_.maxPeriod = period.periodTicks;
|
||||
if (period.activeTicks < stats_.minActive) stats_.minActive = period.activeTicks;
|
||||
if (period.activeTicks > stats_.maxActive) stats_.maxActive = period.activeTicks;
|
||||
|
||||
if (period.periodTicks < windowMinPeriod_) windowMinPeriod_ = period.periodTicks;
|
||||
if (period.periodTicks > windowMaxPeriod_) windowMaxPeriod_ = period.periodTicks;
|
||||
++windowPeriodCount_;
|
||||
windowPeriodSum_ += period.periodTicks;
|
||||
windowActiveSum_ += period.activeTicks;
|
||||
if (windowPeriodCount_ >= averagingPeriods_) {
|
||||
const FailReason result = evaluatePeriodWindow(
|
||||
windowPeriodSum_, windowActiveSum_, windowPeriodCount_, receiver_.tickHz(),
|
||||
expectedHz_, expectedDutyPct_, tolerancePct_,
|
||||
windowMinPeriod_, windowMaxPeriod_,
|
||||
currentStep_ + 1U, stats_);
|
||||
resetAveragingWindow();
|
||||
if (result != FailReason::NONE) { fail(result); return state_; }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (receivedPeriod && state_ == MeasureState::RUNNING) lastPeriodMs_ = millis();
|
||||
@@ -136,6 +175,9 @@ bool Measurement::continueAfterDisplay() {
|
||||
fail(FailReason::UNSUPPORTED);
|
||||
return false;
|
||||
}
|
||||
// receiver_.start() starts a new RMT timebase and therefore a new sampling
|
||||
// phase. Start a fresh averaging window for the new continuous capture.
|
||||
resetAveragingWindow();
|
||||
settleLeft_ = settleCycles_;
|
||||
measurementStartTick_ = deadlineTick_ = 0;
|
||||
startedMs_ = millis(); measurementStartMs_ = lastPeriodMs_ = 0;
|
||||
|
||||
@@ -7,7 +7,8 @@ class Measurement {
|
||||
public:
|
||||
explicit Measurement(PulseReceiver &receiver) : receiver_(receiver) {}
|
||||
bool start(float expectedHz, float expectedDuty, float tolerancePct,
|
||||
uint32_t testTimeMs, uint8_t settleCycles);
|
||||
uint32_t testTimeMs, uint16_t averagingPeriods,
|
||||
uint8_t settleCycles);
|
||||
MeasureState update();
|
||||
bool continueAfterDisplay();
|
||||
void abort();
|
||||
@@ -23,15 +24,19 @@ class Measurement {
|
||||
void fail(FailReason reason);
|
||||
void completeMeasurement();
|
||||
void publishStats();
|
||||
void resetAveragingWindow();
|
||||
PulseReceiver &receiver_;
|
||||
volatile MeasureState state_ = MeasureState::IDLE;
|
||||
TaskHandle_t task_ = nullptr;
|
||||
StageStats stats_ = {};
|
||||
StageStats publishedStats_ = {};
|
||||
mutable portMUX_TYPE statsMux_ = portMUX_INITIALIZER_UNLOCKED;
|
||||
PeriodLimits limits_ = {};
|
||||
uint32_t expectedHz_ = 0;
|
||||
float expectedDutyPct_ = 0.0f;
|
||||
float expectedDutyPct_ = 0.0f, tolerancePct_ = 0.0f;
|
||||
uint16_t averagingPeriods_ = 1;
|
||||
uint32_t windowPeriodCount_ = 0;
|
||||
uint64_t windowPeriodSum_ = 0, windowActiveSum_ = 0;
|
||||
uint32_t windowMinPeriod_ = UINT32_MAX, windowMaxPeriod_ = 0;
|
||||
uint8_t settleCycles_ = 0, settleLeft_ = 0;
|
||||
uint64_t measurementStartTick_ = 0, deadlineTick_ = 0, stepTicks_ = 0;
|
||||
uint32_t startedMs_ = 0, measurementStartMs_ = 0, lastPeriodMs_ = 0;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
namespace { constexpr uint16_t SETTINGS_VERSION = 4; constexpr char NAMESPACE[] = "opt-test"; }
|
||||
|
||||
void SettingsStore::defaults(Settings &s) const {
|
||||
s = {SETTINGS_VERSION, static_cast<uint8_t>(Role::SOLO), 0, 4, 2, 3, 2, 0};
|
||||
s = {SETTINGS_VERSION, static_cast<uint8_t>(Role::SOLO), 0, 4, 2, 3, 0, 0};
|
||||
s.checksum = settingsChecksum(s);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ bool SettingsStore::valid(const Settings &s) const {
|
||||
return s.version == SETTINGS_VERSION && s.role <= static_cast<uint8_t>(Role::SLAVE) &&
|
||||
s.startIndex < countOf(START_FREQ_OPTIONS_HZ) && s.endIndex < countOf(END_FREQ_OPTIONS_HZ) &&
|
||||
s.accuracyIndex < countOf(ACCURACY_OPTIONS_PCT) &&
|
||||
s.timeIndex < countOf(TEST_TIME_OPTIONS_MS) && s.dutyIndex < countOf(DUTY_OPTIONS_PCT) &&
|
||||
s.timeIndex < countOf(TEST_TIME_OPTIONS_MS) &&
|
||||
s.checksum == settingsChecksum(s) &&
|
||||
END_FREQ_OPTIONS_HZ[s.endIndex] > START_FREQ_OPTIONS_HZ[s.startIndex];
|
||||
}
|
||||
@@ -41,5 +41,5 @@ bool SettingsStore::save(Settings &s) {
|
||||
TestParams SettingsStore::params(const Settings &s) const {
|
||||
return {START_FREQ_OPTIONS_HZ[s.startIndex], END_FREQ_OPTIONS_HZ[s.endIndex],
|
||||
ACCURACY_OPTIONS_PCT[s.accuracyIndex], TEST_TIME_OPTIONS_MS[s.timeIndex],
|
||||
DUTY_OPTIONS_PCT[s.dutyIndex]};
|
||||
TEST_DUTY_PCT};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user