фиксы до работы с перемычкой вместо оптики
This commit is contained in:
@@ -1,31 +1,52 @@
|
||||
#include "App.h"
|
||||
#include "Config.h"
|
||||
#include "Log.h"
|
||||
#include <WiFi.h>
|
||||
#include <esp_mac.h>
|
||||
#include <esp_system.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace {
|
||||
const char *appStateName(AppState state) {
|
||||
static const char *names[] = {"IDLE", "MENU", "SOLO_MEASURE", "MASTER_DISCOVER",
|
||||
"MASTER_WAIT_READY", "MASTER_WAIT_RESULT", "SLAVE_READY", "SLAVE_WAIT_START",
|
||||
"SLAVE_MEASURE", "SLAVE_WAIT_ACK", "FINISHED"};
|
||||
const uint8_t index = static_cast<uint8_t>(state);
|
||||
return index < sizeof(names) / sizeof(names[0]) ? names[index] : "UNKNOWN";
|
||||
}
|
||||
|
||||
const char *buttonEventName(ButtonEvent event) {
|
||||
static const char *names[] = {"NONE", "SHORT", "LONG", "REPEAT"};
|
||||
const uint8_t index = static_cast<uint8_t>(event);
|
||||
return index < sizeof(names) / sizeof(names[0]) ? names[index] : "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
App::App() : startButton_(GPIO_BUTTON_START), modeButton_(GPIO_BUTTON_MODE), measurement_(receiver_) {}
|
||||
|
||||
void App::begin() {
|
||||
Serial.begin(SERIAL_BAUD);
|
||||
Log::printf("BOOT", "firmware start, Serial=%lu baud", SERIAL_BAUD);
|
||||
startButton_.begin(); modeButton_.begin(); pwm_.begin();
|
||||
bootCheckStartedMs_ = millis();
|
||||
bootResetCandidate_ = startButton_.pressed() && modeButton_.pressed();
|
||||
Log::printf("BOOT", "buttons initialized, factory-reset candidate=%s", bootResetCandidate_ ? "YES" : "NO");
|
||||
if (!bootResetCandidate_) finishInitialization(false);
|
||||
}
|
||||
|
||||
void App::finishInitialization(bool factoryReset) {
|
||||
if (initialized_) return;
|
||||
Log::printf("BOOT", "initialization continues, factory-reset=%s", factoryReset ? "YES" : "NO");
|
||||
if (factoryReset) {
|
||||
store_.defaults(settings_); store_.save(settings_); Serial.println("FACTORY DEFAULTS RESTORED");
|
||||
store_.defaults(settings_); store_.save(settings_); Log::event("BOOT", "FACTORY DEFAULTS RESTORED");
|
||||
} else if (!store_.load(settings_)) {
|
||||
store_.save(settings_); Serial.println("NVS invalid/missing: defaults loaded");
|
||||
store_.save(settings_); Log::event("BOOT", "NVS invalid/missing: defaults loaded");
|
||||
}
|
||||
params_ = store_.params(settings_);
|
||||
if (!display_.begin()) Serial.println("OLED unavailable; continuing through Serial");
|
||||
if (!display_.begin()) Log::event("BOOT", "OLED unavailable; Serial UI remains fully operational");
|
||||
initialized_ = true;
|
||||
if (!receiver_.begin()) { Serial.println("FATAL: capture peripheral init failed"); finish(false, FailReason::UNSUPPORTED); return; }
|
||||
if (!receiver_.begin()) { Log::event("BOOT", "FATAL: capture peripheral init failed"); finish(false, FailReason::UNSUPPORTED); return; }
|
||||
Log::printf("BOOT", "capture initialized: %s", receiver_.highRateBackend() ? "RMT DMA" : "RMT ping-pong");
|
||||
printConfiguration(); showIdle();
|
||||
}
|
||||
|
||||
@@ -33,6 +54,10 @@ void App::update() {
|
||||
const uint32_t now = millis();
|
||||
const ButtonEvent startEvent = startButton_.update(now);
|
||||
const ButtonEvent modeEvent = modeButton_.update(now);
|
||||
if (startEvent != ButtonEvent::NONE)
|
||||
Log::printf("INPUT", "START %s state=%s", buttonEventName(startEvent), appStateName(state_));
|
||||
if (modeEvent != ButtonEvent::NONE)
|
||||
Log::printf("INPUT", "MODE %s state=%s", buttonEventName(modeEvent), appStateName(state_));
|
||||
if (!initialized_) {
|
||||
if (!startButton_.pressed() || !modeButton_.pressed()) finishInitialization(false);
|
||||
else if (now - bootCheckStartedMs_ >= FACTORY_RESET_HOLD_MS) finishInitialization(true);
|
||||
@@ -40,20 +65,26 @@ void App::update() {
|
||||
}
|
||||
if (state_ != AppState::IDLE && state_ != AppState::MENU && state_ != AppState::FINISHED &&
|
||||
startEvent == ButtonEvent::LONG) { abortTest(); return; }
|
||||
if (state_ != AppState::IDLE && state_ != AppState::MENU && state_ != AppState::FINISHED &&
|
||||
modeEvent != ButtonEvent::NONE) Log::event("ACTION", "MODE ignored while test is active");
|
||||
|
||||
if (state_ == AppState::IDLE || state_ == AppState::FINISHED) {
|
||||
if (modeEvent == ButtonEvent::SHORT) {
|
||||
settings_.role = (settings_.role + 1U) % 3U; store_.save(settings_); params_ = store_.params(settings_); showIdle();
|
||||
Serial.printf("MODE: %s\n", roleName(static_cast<Role>(settings_.role)));
|
||||
settings_.role = (settings_.role + 1U) % 3U; const bool saved = store_.save(settings_);
|
||||
params_ = store_.params(settings_); showIdle();
|
||||
Log::printf("ACTION", "role changed to %s, NVS=%s", roleName(static_cast<Role>(settings_.role)), saved ? "OK" : "FAILED");
|
||||
} else if (modeEvent == ButtonEvent::LONG) {
|
||||
state_ = AppState::MENU; menuItem_ = 0; showMenu();
|
||||
} else if (startEvent == ButtonEvent::SHORT) startTest();
|
||||
state_ = AppState::MENU; menuItem_ = 0; Log::event("ACTION", "settings menu entered"); showMenu();
|
||||
} else if (startEvent == ButtonEvent::SHORT) { Log::event("ACTION", "test start requested"); startTest(); }
|
||||
return;
|
||||
}
|
||||
if (state_ == AppState::MENU) {
|
||||
if (modeEvent == ButtonEvent::SHORT) { menuItem_ = (menuItem_ + 1U) % 7U; showMenu(); }
|
||||
if (modeEvent == ButtonEvent::SHORT) {
|
||||
menuItem_ = (menuItem_ + 1U) % 7U; Log::printf("ACTION", "menu item selected index=%u", menuItem_); showMenu();
|
||||
}
|
||||
else if (modeEvent == ButtonEvent::LONG) {
|
||||
sanitizeRange(); store_.save(settings_); params_ = store_.params(settings_);
|
||||
sanitizeRange(); const bool saved = store_.save(settings_); params_ = store_.params(settings_);
|
||||
Log::printf("ACTION", "settings menu saved and closed, NVS=%s", saved ? "OK" : "FAILED");
|
||||
state_ = AppState::IDLE; printConfiguration(); showIdle();
|
||||
} else if (startEvent == ButtonEvent::SHORT) changeMenu(+1);
|
||||
else if (startEvent == ButtonEvent::LONG || startEvent == ButtonEvent::REPEAT) changeMenu(-1);
|
||||
@@ -97,7 +128,9 @@ void App::changeMenu(int d) {
|
||||
case 5: value = &settings_.repeatIndex; count = countOf(REPEAT_OPTIONS); break;
|
||||
default: value = &settings_.dutyIndex; count = countOf(DUTY_OPTIONS_PCT); break;
|
||||
}
|
||||
*value = static_cast<uint8_t>((*value + count + d) % count); sanitizeRange(); params_ = store_.params(settings_); showMenu();
|
||||
*value = static_cast<uint8_t>((*value + count + d) % count);
|
||||
Log::printf("ACTION", "menu item=%u changed direction=%+d new-index=%u", menuItem_, d, *value);
|
||||
sanitizeRange(); params_ = store_.params(settings_); showMenu();
|
||||
}
|
||||
|
||||
void App::showMenu() {
|
||||
@@ -119,6 +152,11 @@ void App::startTest() {
|
||||
params_ = store_.params(settings_); stageCount_ = frequencyPointCount(params_.startHz, params_.endHz, params_.stepHz);
|
||||
stageIndex_ = 0; pendingReason_ = FailReason::NONE;
|
||||
if (!stageCount_) { finish(false, FailReason::UNSUPPORTED); return; }
|
||||
Log::printf("TEST", "starting role=%s stages=%lu", roleName(static_cast<Role>(settings_.role)), stageCount_);
|
||||
if (SERIAL_MINIMAL_LOG)
|
||||
Log::printf("CONFIG", "mode=%s range=%lu..%luHz step=%luHz accuracy=%.2f%% time=%lums repeats=%u duty=%u%% stages=%lu",
|
||||
roleName(static_cast<Role>(settings_.role)), params_.startHz, params_.endHz, params_.stepHz,
|
||||
params_.accuracyPct, params_.testTimeMs, params_.repeats, params_.dutyPct, stageCount_);
|
||||
printConfiguration();
|
||||
const Role role = static_cast<Role>(settings_.role);
|
||||
if (role == Role::SOLO) {
|
||||
@@ -126,7 +164,7 @@ void App::startTest() {
|
||||
state_ = AppState::SOLO_MEASURE;
|
||||
} else if (!radio_.begin()) finish(false, FailReason::LINK_LOST);
|
||||
else if (role == Role::MASTER) startMasterDiscovery();
|
||||
else { state_ = AppState::SLAVE_READY; display_.show("SLAVE READY", "WAIT MASTER"); Serial.println("SLAVE READY"); }
|
||||
else { state_ = AppState::SLAVE_READY; Log::event("TEST", "Slave armed and waiting for Master"); display_.show("SLAVE READY", "WAIT MASTER"); }
|
||||
}
|
||||
|
||||
bool App::prepareStage() {
|
||||
@@ -134,11 +172,20 @@ bool App::prepareStage() {
|
||||
const uint32_t maxHz = TARGET_IS_C3 ? C3_STRICT_MAX_HZ :
|
||||
(receiver_.highRateBackend() ? S3_STRICT_MAX_HZ : C3_STRICT_MAX_HZ);
|
||||
if (requestedHz_ > maxHz) { finish(false, FailReason::UNSUPPORTED); return false; }
|
||||
if (!pwm_.start(requestedHz_, params_.dutyPct, actual_)) { finish(false, FailReason::RESOLUTION); return false; }
|
||||
Log::printf("PWM", "starting GPIO=%u requested=%luHz duty=%u%%", GPIO_PWM, requestedHz_, params_.dutyPct);
|
||||
if (!pwm_.start(requestedHz_, params_.dutyPct, actual_)) {
|
||||
Log::printf("PWM", "START FAILED GPIO=%u requested=%luHz; LEDC attach/write/read failed",
|
||||
GPIO_PWM, requestedHz_);
|
||||
finish(false, FailReason::RESOLUTION); return false;
|
||||
}
|
||||
const FailReason resolution = validateResolution(actual_.actualHz, actual_.actualDutyPct, params_.accuracyPct,
|
||||
receiver_.tickHz(), actual_.bits);
|
||||
if (resolution != FailReason::NONE) { finish(false, resolution); return false; }
|
||||
Serial.printf("STAGE %lu/%lu requested=%luHz actual=%luHz duty=%.2f%% bits=%u\n",
|
||||
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, receiver_.tickHz(), params_.accuracyPct);
|
||||
finish(false, resolution); return false;
|
||||
}
|
||||
Log::printf("PWM", "stage=%lu/%lu requested=%luHz actual=%luHz duty=%.2f%% bits=%u STARTED",
|
||||
stageIndex_ + 1, stageCount_, requestedHz_, actual_.actualHz, actual_.actualDutyPct, actual_.bits);
|
||||
char f[12], one[24], two[24]; Display::formatFrequency(actual_.actualHz, f, sizeof(f));
|
||||
snprintf(one, sizeof(one), "F %s D %.1f%%", f, actual_.actualDutyPct);
|
||||
@@ -150,10 +197,16 @@ bool App::prepareStage() {
|
||||
}
|
||||
|
||||
bool App::startLocalMeasurement(float hz, float duty) {
|
||||
return measurement_.start(hz, duty, params_.accuracyPct, params_.testTimeMs, params_.repeats, PWM_SETTLE_CYCLES);
|
||||
Log::printf("MEASURE", "arming expected=%.3fHz duty=%.3f%% tolerance=%.3f%% settle=%u cycles window=%lums x%u; per-pulse logging suspended",
|
||||
hz, duty, params_.accuracyPct, PWM_SETTLE_CYCLES, params_.testTimeMs, params_.repeats);
|
||||
const bool ok = measurement_.start(hz, duty, params_.accuracyPct, params_.testTimeMs, params_.repeats, PWM_SETTLE_CYCLES);
|
||||
Log::printf("MEASURE", "receiver start %s, RMT chunk=%u symbols", ok ? "OK" : "FAILED",
|
||||
receiver_.receiveChunkSymbols());
|
||||
return ok;
|
||||
}
|
||||
|
||||
void App::stagePassed() {
|
||||
Log::printf("TEST", "stage %lu/%lu PASS; PWM stopping", stageIndex_ + 1, stageCount_);
|
||||
pwm_.stop();
|
||||
if (++stageIndex_ >= stageCount_) { finish(true, FailReason::NONE); return; }
|
||||
if (static_cast<Role>(settings_.role) == Role::SOLO) { if (prepareStage()) state_ = AppState::SOLO_MEASURE; }
|
||||
@@ -168,7 +221,8 @@ void App::startMasterDiscovery() {
|
||||
session_ = esp_random(); if (!session_) session_ = 1; sequence_ = 1; havePeer_ = false; radio_.flush();
|
||||
pendingPacket_ = makePacket(MessageType::DISCOVER); radio_.sendBroadcast(pendingPacket_);
|
||||
lastSendMs_ = millis(); deadlineMs_ = millis() + LINK_DISCOVERY_TIMEOUT_MS; retries_ = 0;
|
||||
state_ = AppState::MASTER_DISCOVER; display_.show("MASTER SEARCH", "WAIT SLAVE"); Serial.println("ESP-NOW DISCOVER");
|
||||
state_ = AppState::MASTER_DISCOVER; Log::printf("ESP-NOW", "discovery started session=%08lX", session_);
|
||||
display_.show("MASTER SEARCH", "WAIT SLAVE");
|
||||
}
|
||||
|
||||
ProtocolPacket App::makePacket(MessageType type) const {
|
||||
@@ -182,7 +236,9 @@ ProtocolPacket App::makePacket(MessageType type) const {
|
||||
}
|
||||
|
||||
void App::sendCurrent(MessageType type) {
|
||||
++sequence_; pendingPacket_ = makePacket(type); radio_.sendTo(peer_, pendingPacket_); lastSendMs_ = millis();
|
||||
++sequence_; pendingPacket_ = makePacket(type);
|
||||
const bool ok = radio_.sendTo(peer_, pendingPacket_); lastSendMs_ = millis();
|
||||
if (!ok) Log::printf("ESP-NOW", "sendCurrent %s FAILED", messageName(type));
|
||||
}
|
||||
|
||||
bool App::packetForCurrent(const ProtocolPacket &p) const {
|
||||
@@ -194,7 +250,8 @@ void App::handleRadio() {
|
||||
while (radio_.receive(r)) {
|
||||
const MessageType type = static_cast<MessageType>(r.packet.type);
|
||||
if (state_ != AppState::SLAVE_MEASURE)
|
||||
Serial.printf("ESP-NOW RX type=%u session=%08lX stage=%u seq=%u\n", r.packet.type, r.packet.session, r.packet.stage, r.packet.sequence);
|
||||
Log::printf("ESP-NOW", "RX %s session=%08lX stage=%u seq=%u",
|
||||
messageName(type), r.packet.session, r.packet.stage, r.packet.sequence);
|
||||
if (state_ == AppState::SLAVE_READY && type == MessageType::DISCOVER) {
|
||||
memcpy(peer_, r.mac, 6); havePeer_ = true; session_ = r.packet.session; stageIndex_ = 0; sequence_ = r.packet.sequence;
|
||||
ProtocolPacket ack = makePacket(MessageType::DISCOVER_ACK); ack.sequence = r.packet.sequence; radio_.sendTo(peer_, ack);
|
||||
@@ -203,7 +260,7 @@ void App::handleRadio() {
|
||||
if (state_ == AppState::MASTER_DISCOVER && type == MessageType::DISCOVER_ACK && r.packet.session == session_) {
|
||||
memcpy(peer_, r.mac, 6); havePeer_ = true; requestedHz_ = frequencyAt(params_.startHz, params_.endHz, params_.stepHz, stageIndex_);
|
||||
sendCurrent(MessageType::PREPARE); state_ = AppState::MASTER_WAIT_READY; retries_ = 0; deadlineMs_ = millis() + LINK_REPLY_TIMEOUT_MS;
|
||||
char mac[20]; Radio::macText(peer_, mac, sizeof(mac)); Serial.printf("SLAVE SELECTED %s\n", mac); continue;
|
||||
char mac[20]; Radio::macText(peer_, mac, sizeof(mac)); Log::printf("ESP-NOW", "Slave selected %s", mac); continue;
|
||||
}
|
||||
if (state_ == AppState::SLAVE_WAIT_START && type == MessageType::DISCOVER &&
|
||||
r.packet.session == session_ && !memcmp(peer_, r.mac, 6)) {
|
||||
@@ -244,11 +301,15 @@ void App::updateMaster() {
|
||||
const uint32_t now = millis();
|
||||
if (state_ == AppState::MASTER_DISCOVER) {
|
||||
if (now >= deadlineMs_) { finish(false, FailReason::LINK_LOST); return; }
|
||||
if (now - lastSendMs_ >= LINK_RETRY_INTERVAL_MS) { radio_.sendBroadcast(pendingPacket_); lastSendMs_ = now; }
|
||||
if (now - lastSendMs_ >= LINK_RETRY_INTERVAL_MS) {
|
||||
Log::printf("ESP-NOW", "DISCOVER retry=%u", retries_ + 1); radio_.sendBroadcast(pendingPacket_);
|
||||
lastSendMs_ = now; ++retries_;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (now < deadlineMs_) return;
|
||||
if (retries_ >= LINK_PACKET_RETRIES) { finish(false, FailReason::LINK_LOST); return; }
|
||||
Log::printf("ESP-NOW", "%s retry=%u", messageName(static_cast<MessageType>(pendingPacket_.type)), retries_ + 1);
|
||||
radio_.sendTo(peer_, pendingPacket_); ++retries_;
|
||||
deadlineMs_ = now + (state_ == AppState::MASTER_WAIT_RESULT ?
|
||||
params_.testTimeMs * params_.repeats + LINK_REPLY_TIMEOUT_MS : LINK_REPLY_TIMEOUT_MS);
|
||||
@@ -263,28 +324,34 @@ void App::updateSlave() {
|
||||
pendingPacket_.reason = static_cast<uint8_t>(measurement_.reason()); pendingPacket_.periods = measurement_.stats().periods;
|
||||
pendingPacket_.minPeriodTicks = measurement_.stats().minPeriod; pendingPacket_.maxPeriodTicks = measurement_.stats().maxPeriod;
|
||||
pendingPacket_.sequence = ++sequence_; radio_.sendTo(peer_, pendingPacket_);
|
||||
Log::printf("TEST", "Slave result prepared: %s reason=%s periods=%lu",
|
||||
pendingPacket_.passed ? "PASS" : "FAIL", failName(static_cast<FailReason>(pendingPacket_.reason)), pendingPacket_.periods);
|
||||
state_ = AppState::SLAVE_WAIT_ACK; retries_ = 0; deadlineMs_ = millis() + LINK_REPLY_TIMEOUT_MS;
|
||||
} else if (state_ == AppState::SLAVE_WAIT_ACK && millis() >= deadlineMs_) {
|
||||
if (retries_++ >= LINK_PACKET_RETRIES) finish(false, FailReason::LINK_LOST);
|
||||
else { radio_.sendTo(peer_, pendingPacket_); deadlineMs_ = millis() + LINK_REPLY_TIMEOUT_MS; }
|
||||
else { Log::printf("ESP-NOW", "RESULT retry=%u", retries_); radio_.sendTo(peer_, pendingPacket_); deadlineMs_ = millis() + LINK_REPLY_TIMEOUT_MS; }
|
||||
}
|
||||
}
|
||||
|
||||
void App::sendAbort() { if (havePeer_) sendCurrent(MessageType::ABORT); }
|
||||
|
||||
void App::abortTest() { sendAbort(); measurement_.abort(); finish(false, FailReason::ABORTED); }
|
||||
void App::abortTest() {
|
||||
Log::event("ACTION", "abort requested: sending ABORT, stopping receiver and PWM");
|
||||
sendAbort(); measurement_.abort(); finish(false, FailReason::ABORTED);
|
||||
}
|
||||
|
||||
void App::finish(bool pass, FailReason reason) {
|
||||
Log::printf("TEST", "finishing result=%s reason=%s", pass ? "PASS" : "FAIL", failName(reason));
|
||||
pwm_.stop(); receiver_.stop();
|
||||
if (state_ != AppState::IDLE && state_ != AppState::MENU) radio_.end();
|
||||
state_ = AppState::FINISHED; pendingReason_ = reason;
|
||||
char one[24];
|
||||
if (pass) { snprintf(one, sizeof(one), "PASS %luHz-%lu", params_.startHz, params_.endHz); display_.show(one, "START=REPEAT"); }
|
||||
else { snprintf(one, sizeof(one), "FAIL AT %lu", requestedHz_); display_.show(one, failName(reason)); }
|
||||
Serial.printf("TEST %s: %s\n", pass ? "PASS" : "FAIL", failName(reason));
|
||||
}
|
||||
|
||||
void App::printConfiguration() {
|
||||
if (SERIAL_MINIMAL_LOG) return;
|
||||
const char *board = TARGET_IS_C3 ? "ESP32-C3" : "ESP32-S3";
|
||||
uint8_t mac[6] = {}; esp_read_mac(mac, ESP_MAC_WIFI_STA);
|
||||
Serial.printf("\nOptical Channel Tester | %s | mode=%s\n", board, roleName(static_cast<Role>(settings_.role)));
|
||||
@@ -300,23 +367,17 @@ void App::printConfiguration() {
|
||||
}
|
||||
|
||||
uint64_t App::actualNominalTotalUs() {
|
||||
uint64_t total = 0;
|
||||
const uint32_t count = frequencyPointCount(params_.startHz, params_.endHz, params_.stepHz);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
ActualPwm preview = {};
|
||||
const uint32_t requested = frequencyAt(params_.startHz, params_.endHz, params_.stepHz, i);
|
||||
const uint32_t actualHz = pwm_.preview(requested, params_.dutyPct, preview) ? preview.actualHz : requested;
|
||||
total += (1000000ULL * PWM_SETTLE_CYCLES + actualHz - 1) / actualHz;
|
||||
total += static_cast<uint64_t>(params_.testTimeMs) * 1000ULL * params_.repeats;
|
||||
}
|
||||
return total;
|
||||
// ALL is only an estimate. Do not attach/detach LEDC for every frequency:
|
||||
// large sweeps can perform hundreds of unnecessary driver reconfigurations
|
||||
// immediately before the real test and leave no observable PWM on failure.
|
||||
return nominalTotalUs(params_, PWM_SETTLE_CYCLES);
|
||||
}
|
||||
|
||||
void App::printStageStats(const StageStats &s, uint32_t hz) {
|
||||
if (!s.periods) return;
|
||||
Serial.printf("STATS %luHz periods=%lu period ticks min/avg/max=%lu/%llu/%lu active=%lu/%llu/%lu\n",
|
||||
hz, s.periods, s.minPeriod, s.periodSum / s.periods, s.maxPeriod,
|
||||
s.minActive, s.activeSum / s.periods, s.maxActive);
|
||||
if (s.reason != FailReason::NONE) Serial.printf("FIRST BAD repeat=%u period=%lu f=%.3f duty=%.3f reason=%s\n",
|
||||
s.firstBadRepeat, s.firstBadPeriod, s.badFrequency, s.badDuty, failName(s.reason));
|
||||
const float measuredHz = static_cast<float>(receiver_.tickHz()) * s.periods / s.periodSum;
|
||||
const float measuredDuty = 100.0f * s.activeSum / s.periodSum;
|
||||
Log::printf("RESULT", "%luHz %s periods=%lu measured=%.2fHz duty=%.2f%%%s%s",
|
||||
hz, s.reason == FailReason::NONE ? "PASS" : "FAIL", s.periods, measuredHz, measuredDuty,
|
||||
s.reason == FailReason::NONE ? "" : " reason=", s.reason == FailReason::NONE ? "" : failName(s.reason));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user