Добавлено тестировние платы в меню:

- Тест Tx Оптики
- Тест Rx Оптики
- Тест АЦП
This commit is contained in:
2026-08-22 20:03:12 +03:00
parent 49332aa028
commit 3907cbcf77
9 changed files with 357 additions and 115 deletions

View File

@@ -17,7 +17,7 @@ namespace {
const char *uiFailName(FailReason reason);
const char *appStateName(AppState state) {
static const char *names[] = {"IDLE", "MENU", "SOLO_MEASURE", "SOLO_DRIVER", "MASTER_DISCOVER",
static const char *names[] = {"IDLE", "MENU", "BOARD_TEST", "SOLO_MEASURE", "SOLO_DRIVER", "MASTER_DISCOVER",
"MASTER_WAIT_READY", "MASTER_WAIT_RESULT", "MASTER_FINALIZE", "SLAVE_READY", "SLAVE_WAIT_START",
"SLAVE_MEASURE", "SLAVE_WAIT_ACK", "FINISHED"};
const uint8_t index = static_cast<uint8_t>(state);
@@ -145,6 +145,30 @@ const char *uiTestName(TestKind kind) {
? UiText::TEST_NAMES[index] : "?";
}
const char *uiTestGroupName(TestGroup group) {
const uint8_t index = static_cast<uint8_t>(group);
return index < sizeof(UiText::TEST_GROUP_NAMES) / sizeof(UiText::TEST_GROUP_NAMES[0])
? UiText::TEST_GROUP_NAMES[index] : "?";
}
const char *uiBoardTestName(BoardTest test) {
const uint8_t index = static_cast<uint8_t>(test);
return index < sizeof(UiText::BOARD_TEST_NAMES) / sizeof(UiText::BOARD_TEST_NAMES[0])
? UiText::BOARD_TEST_NAMES[index] : "?";
}
bool boardTestAvailable(BoardTest test) {
if (test == BoardTest::PWM_OUTPUT) return true;
if (test == BoardTest::ADC) return BOARD_RX_USES_ADC && BOARD_ADC_AVAILABLE;
if (test == BoardTest::RX_INPUT) return !BOARD_RX_USES_ADC;
return false;
}
BoardTest defaultBoardTest() {
return BOARD_RX_USES_ADC && BOARD_ADC_AVAILABLE
? BoardTest::ADC : BoardTest::RX_INPUT;
}
uint8_t lastValidMaxPulseIndex(uint32_t frequencyHz) {
uint8_t last = static_cast<uint8_t>(countOf(MAX_PULSE_OPTIONS_NS) - 1U);
while (last && static_cast<uint64_t>(MAX_PULSE_OPTIONS_NS[last]) * frequencyHz >= 1000000000ULL)
@@ -290,7 +314,8 @@ void App::finishInitialization(bool factoryReset) {
lastUserActivityMs_ = millis();
setActivePerformance(false);
printConfiguration();
if (static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::OPTICS &&
static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
else showIdle();
}
@@ -313,7 +338,15 @@ void App::update() {
else if (now - bootCheckStartedMs_ >= FACTORY_RESET_HOLD_MS) finishInitialization(true);
return;
}
serviceRxPinStateLog();
if (state_ == AppState::BOARD_TEST) {
if (startEvent == ButtonEvent::LONG) stopBoardTest();
else {
if (modeEvent != ButtonEvent::NONE)
Log::event("ACTION", "MODE ignored while board test is active");
updateBoardTest(now);
}
return;
}
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 &&
@@ -323,12 +356,16 @@ void App::update() {
if (modeEvent == ButtonEvent::SHORT) {
cycleRunMode(); sanitizeRange(); const bool saved = store_.save(settings_);
params_ = store_.params(settings_);
if (static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::OPTICS &&
static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
else showIdle();
Log::printf("ACTION", "mode changed to %s/%s, NVS=%s",
roleName(static_cast<Role>(settings_.role)),
testKindName(static_cast<TestKind>(settings_.testKind)),
saved ? "OK" : "FAILED");
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD)
Log::printf("ACTION", "board test changed to %s, NVS=%s",
boardTestName(static_cast<BoardTest>(settings_.boardTest)), saved ? "OK" : "FAILED");
else
Log::printf("ACTION", "mode changed to %s/%s, NVS=%s",
roleName(static_cast<Role>(settings_.role)),
testKindName(static_cast<TestKind>(settings_.testKind)), saved ? "OK" : "FAILED");
} else if (modeEvent == ButtonEvent::LONG) {
state_ = AppState::MENU; menuItem_ = 0; Log::event("ACTION", "settings menu entered"); showMenu();
} else if (startEvent == ButtonEvent::SHORT) { Log::event("ACTION", "test start requested"); startTest(); }
@@ -351,13 +388,15 @@ void App::update() {
}
if (state_ == AppState::MENU) {
if (modeEvent == ButtonEvent::SHORT) {
menuItem_ = (menuItem_ + 1U) % 6U; Log::printf("ACTION", "menu item selected index=%u", menuItem_); showMenu();
const uint8_t menuCount = static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD ? 1U : 7U;
menuItem_ = (menuItem_ + 1U) % menuCount; 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_);
Log::printf("ACTION", "settings menu saved and closed, NVS=%s", saved ? "OK" : "FAILED");
state_ = AppState::IDLE; printConfiguration();
if (static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::OPTICS &&
static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
else showIdle();
} else if (startEvent == ButtonEvent::SHORT) changeMenu(+1);
else if (startEvent == ButtonEvent::LONG || startEvent == ButtonEvent::REPEAT) changeMenu(-1);
@@ -429,10 +468,17 @@ void App::showIdle() {
setActivePerformance(false);
setStandbyOpticalOutput();
lastUserActivityMs_ = millis();
char one[64]; snprintf(one, sizeof(one), "%s: %s",
uiRoleName(static_cast<Role>(settings_.role)),
uiTestName(static_cast<TestKind>(settings_.testKind)));
display_.show(one, UiText::START_RUN);
char one[64];
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD) {
snprintf(one, sizeof(one), "%s: %s", uiTestGroupName(TestGroup::BOARD),
uiBoardTestName(static_cast<BoardTest>(settings_.boardTest)));
display_.show(one, UiText::BOARD_READY);
} else {
snprintf(one, sizeof(one), "%s: %s",
uiRoleName(static_cast<Role>(settings_.role)),
uiTestName(static_cast<TestKind>(settings_.testKind)));
display_.show(one, UiText::START_RUN);
}
}
void App::serviceSerialConsole() {
@@ -464,6 +510,8 @@ void App::serviceSerialConsole() {
void App::printSerialHelp() {
Serial.println("COMMANDS (send with newline):");
Serial.println(" help | status | start | stop | defaults");
Serial.println(" set group optics|board");
Serial.println(" set boardtest adc|pwm|rx");
Serial.println(" set role solo|master|slave");
Serial.println(" set test optical|driver");
Serial.println(" set frequency 500|1000|2000|5000|10000|25000");
@@ -480,8 +528,9 @@ void App::printSerialStatus() {
return;
}
params_ = store_.params(settings_);
Serial.printf("STATUS state=%s role=%s test=%s frequency=%luHz max=%luns min=%luns accuracy=%.2f%% time=%lums light=%s usb=%s\n",
appStateName(state_), roleName(static_cast<Role>(settings_.role)),
Serial.printf("STATUS state=%s group=%s boardtest=%s role=%s test=%s frequency=%luHz max=%luns min=%luns accuracy=%.2f%% time=%lums light=%s usb=%s\n",
appStateName(state_), testGroupName(static_cast<TestGroup>(settings_.testGroup)),
boardTestName(static_cast<BoardTest>(settings_.boardTest)), roleName(static_cast<Role>(settings_.role)),
testKindName(static_cast<TestKind>(settings_.testKind)), params_.frequencyHz,
params_.maxPulseNs, params_.minPulseNs, params_.accuracyPct, params_.testTimeMs,
configuredLevelName(settings_),
@@ -501,7 +550,8 @@ void App::finishSerialSettingsChange() {
pwm_.configureActiveLight(configuredTxPulseLightOn(settings_));
const bool saved = store_.save(settings_);
Serial.printf("OK settings saved=%s\n", saved ? "yes" : "no");
if (static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::OPTICS &&
static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
else showIdle();
printSerialStatus();
}
@@ -535,7 +585,10 @@ void App::handleSerialCommand(char *line) {
if ((!strcmp(command, "stop") || !strcmp(command, "abort")) && !name) {
if (!initialized_) Serial.println("ERR still initializing");
else if (state_ == AppState::IDLE || state_ == AppState::FINISHED) Serial.println("OK already stopped");
else if (state_ == AppState::MENU) {
else if (state_ == AppState::BOARD_TEST) {
Serial.println("OK board test stopped");
stopBoardTest();
} else if (state_ == AppState::MENU) {
state_ = AppState::IDLE; showIdle(); Serial.println("OK menu closed");
} else if (state_ == AppState::SLAVE_READY) Serial.println("OK slave is armed; no test is running");
else {
@@ -564,7 +617,22 @@ void App::handleSerialCommand(char *line) {
bool accepted = false;
uint32_t numeric = 0;
if (!strcmp(name, "role")) {
if (!strcmp(name, "group")) {
if (!strcmp(value, "optics") || !strcmp(value, "optical")) {
settings_.testGroup = static_cast<uint8_t>(TestGroup::OPTICS); accepted = true;
} else if (!strcmp(value, "board")) {
settings_.testGroup = static_cast<uint8_t>(TestGroup::BOARD); accepted = true;
}
} else if (!strcmp(name, "boardtest") || !strcmp(name, "board")) {
BoardTest selected = static_cast<BoardTest>(UINT8_MAX);
if (!strcmp(value, "adc")) selected = BoardTest::ADC;
else if (!strcmp(value, "pwm")) selected = BoardTest::PWM_OUTPUT;
else if (!strcmp(value, "rx")) selected = BoardTest::RX_INPUT;
if (boardTestAvailable(selected)) {
settings_.boardTest = static_cast<uint8_t>(selected);
accepted = true;
}
} else if (!strcmp(name, "role")) {
if (!strcmp(value, "solo")) { settings_.role = static_cast<uint8_t>(Role::SOLO); accepted = true; }
else if (!strcmp(value, "master")) { settings_.role = static_cast<uint8_t>(Role::MASTER); accepted = true; }
else if (!strcmp(value, "slave")) { settings_.role = static_cast<uint8_t>(Role::SLAVE); accepted = true; }
@@ -608,6 +676,13 @@ void App::handleSerialCommand(char *line) {
}
void App::cycleRunMode() {
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD) {
do {
settings_.boardTest = (settings_.boardTest + 1U) %
(static_cast<uint8_t>(BoardTest::RX_INPUT) + 1U);
} while (!boardTestAvailable(static_cast<BoardTest>(settings_.boardTest)));
return;
}
const Role role = static_cast<Role>(settings_.role);
const TestKind kind = static_cast<TestKind>(settings_.testKind);
if (role == Role::SOLO && kind == TestKind::OPTICAL && !TARGET_IS_C3) {
@@ -625,6 +700,11 @@ void App::cycleRunMode() {
}
void App::sanitizeRange() {
if (settings_.testGroup > static_cast<uint8_t>(TestGroup::BOARD))
settings_.testGroup = static_cast<uint8_t>(TestGroup::OPTICS);
if (settings_.boardTest > static_cast<uint8_t>(BoardTest::RX_INPUT) ||
!boardTestAvailable(static_cast<BoardTest>(settings_.boardTest)))
settings_.boardTest = static_cast<uint8_t>(defaultBoardTest());
if (settings_.role > static_cast<uint8_t>(Role::SLAVE))
settings_.role = static_cast<uint8_t>(Role::SOLO);
if (settings_.testKind > static_cast<uint8_t>(TestKind::DRIVER))
@@ -654,29 +734,19 @@ void App::sanitizeRange() {
}
}
void App::serviceRxPinStateLog() {
#ifdef RX_PIN_CHANGE_TEST
const bool level = digitalRead(GPIO_RX) == HIGH;
const bool outsideTest = state_ == AppState::IDLE || state_ == AppState::MENU ||
state_ == AppState::SLAVE_READY || state_ == AppState::FINISHED;
if (rxPinStateKnown_ && level != rxPinState_ && outsideTest)
Log::printf("RX TEST", "GPIO=%u state=%s (%u)", GPIO_RX,
level ? "HIGH" : "LOW", level ? 1U : 0U);
rxPinState_ = level;
rxPinStateKnown_ = true;
#endif
}
void App::changeMenu(int d) {
sanitizeRange();
if (menuItem_ == 1) {
if (menuItem_ == 0) {
settings_.testGroup = cycleIndex(settings_.testGroup, 0,
static_cast<uint8_t>(TestGroup::BOARD), d);
} else if (menuItem_ == 2) {
const uint8_t last = lastValidMaxPulseIndex(
PWM_FREQUENCY_OPTIONS_HZ[settings_.frequencyIndex]);
const uint8_t first = firstMaxPulseIndexAtLeast(
MIN_PULSE_OPTIONS_NS[settings_.minPulseIndex], last);
settings_.maxPulseIndex = cycleIndex(settings_.maxPulseIndex,
first, last, d);
} else if (menuItem_ == 2) {
} else if (menuItem_ == 3) {
const uint8_t last = lastMinPulseIndexAtMost(
MAX_PULSE_OPTIONS_NS[settings_.maxPulseIndex]);
const uint8_t first = static_cast<TestKind>(settings_.testKind) == TestKind::DRIVER
@@ -685,10 +755,10 @@ void App::changeMenu(int d) {
} else {
uint8_t *value = nullptr; size_t count = 0;
switch (menuItem_) {
case 0: value = &settings_.frequencyIndex; count = countOf(PWM_FREQUENCY_OPTIONS_HZ); break;
case 3: value = &settings_.accuracyIndex; count = countOf(ACCURACY_OPTIONS_PCT); break;
case 4: value = &settings_.timeIndex; count = countOf(TEST_TIME_OPTIONS_MS); break;
case 5:
case 1: value = &settings_.frequencyIndex; count = countOf(PWM_FREQUENCY_OPTIONS_HZ); break;
case 4: value = &settings_.accuracyIndex; count = countOf(ACCURACY_OPTIONS_PCT); break;
case 5: value = &settings_.timeIndex; count = countOf(TEST_TIME_OPTIONS_MS); break;
case 6:
if (static_cast<TestKind>(settings_.testKind) != TestKind::DRIVER) {
showMenu();
return;
@@ -713,26 +783,31 @@ void App::showMenu() {
Display::formatDuration(actualNominalTotalUs(), all, sizeof(all));
switch (menuItem_) {
case 0:
snprintf(value, sizeof(value), "%s",
uiTestGroupName(static_cast<TestGroup>(settings_.testGroup)));
label = UiText::MENU_TEST_GROUP;
break;
case 1:
Display::formatPwmFrequency(params_.frequencyHz, value, sizeof(value));
label = UiText::MENU_FREQUENCY;
break;
case 1:
case 2:
Display::formatPulse(params_.maxPulseNs, value, sizeof(value));
label = UiText::MENU_MAX_PULSE;
break;
case 2:
case 3:
Display::formatPulse(params_.minPulseNs, value, sizeof(value));
label = UiText::MENU_MIN_PULSE;
break;
case 3:
case 4:
snprintf(value, sizeof(value), "+/-%g%%", params_.accuracyPct);
label = UiText::MENU_ACCURACY;
break;
case 4:
case 5:
snprintf(value, sizeof(value), "%.1fs", params_.testTimeMs / 1000.0f);
label = UiText::MENU_TEST_TIME;
break;
case 5: {
case 6: {
if (static_cast<TestKind>(settings_.testKind) != TestKind::DRIVER) {
snprintf(value, sizeof(value), "%s", UiText::LIGHT_AUTO);
label = UiText::MENU_LIGHT_CODE;
@@ -751,7 +826,10 @@ void App::showMenu() {
default: return;
}
formatMenuLine(label, value, one, sizeof(one));
formatMenuLine(UiText::MENU_TOTAL_TIME, all, total, sizeof(total));
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD)
snprintf(total, sizeof(total), "%s", UiText::BOARD_READY);
else
formatMenuLine(UiText::MENU_TOTAL_TIME, all, total, sizeof(total));
display_.show(one, total);
}
@@ -760,6 +838,10 @@ void App::startTest() {
pwm_.stop();
setActivePerformance(true);
sanitizeRange();
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD) {
startBoardTest();
return;
}
params_ = store_.params(settings_); stageCount_ = pulseWidthPointCount(params_.maxPulseNs, params_.minPulseNs);
stageIndex_ = 0; requestedHz_ = params_.frequencyHz; requestedPulseNs_ = 0; pendingReason_ = FailReason::NONE;
havePeer_ = false; lastHeartbeatMs_ = 0; lastPeerSeenMs_ = 0;
@@ -787,6 +869,98 @@ void App::startTest() {
else { state_ = AppState::SLAVE_READY; Log::event("TEST", "Slave armed and waiting for Master"); display_.show(UiText::SLAVE_READY, UiText::WAIT_MASTER); }
}
void App::startBoardTest() {
const BoardTest test = static_cast<BoardTest>(settings_.boardTest);
state_ = AppState::BOARD_TEST;
boardTestUpdatedMs_ = boardDisplayUpdatedMs_ = 0;
boardPwmLightOn_ = false;
rxPinStateKnown_ = false;
Log::printf("BOARD", "starting test=%s", boardTestName(test));
// ADC and RX checks need the optical transmitter continuously illuminated.
// The PWM-output check drives the same pin itself and therefore replaces
// the constant active level with its test waveform.
if (test != BoardTest::PWM_OUTPUT) {
pwm_.lightOn();
Log::printf("BOARD", "optical output active GPIO=%u level=%s", GPIO_PWM,
TX_LIGHT_ON_GPIO_LEVEL == HIGH ? "HIGH" : "LOW");
}
if (test == BoardTest::ADC) {
if (!BOARD_ADC_AVAILABLE) {
Serial.println("BOARD ADC: unavailable in MAKETKA profile");
display_.show(UiText::ADC_UNAVAILABLE, UiText::BOARD_STOP);
return;
}
pinMode(GPIO_ANALOG_RX, INPUT);
pinMode(GPIO_VBAT, INPUT);
display_.show(UiText::BOARD_TEST_NAMES[static_cast<uint8_t>(BoardTest::ADC)],
UiText::BOARD_STOP);
} else if (test == BoardTest::PWM_OUTPUT) {
boardPwmLightOn_ = true;
boardTestUpdatedMs_ = millis();
pwm_.lightOn();
Serial.printf("BOARD PWM: GPIO=%u frequency=%luHz duty=50%% light=ON\n",
GPIO_PWM, BOARD_PWM_TEST_FREQUENCY_HZ);
display_.show(UiText::BOARD_TEST_NAMES[static_cast<uint8_t>(test)], UiText::BOARD_STOP);
} else {
pinMode(GPIO_RX, INPUT);
display_.show(UiText::BOARD_TEST_NAMES[static_cast<uint8_t>(test)], UiText::BOARD_STOP);
}
}
void App::updateBoardTest(uint32_t now) {
const BoardTest test = static_cast<BoardTest>(settings_.boardTest);
if (test == BoardTest::ADC) {
if (!BOARD_ADC_AVAILABLE || now - boardTestUpdatedMs_ < BOARD_ADC_PRINT_INTERVAL_MS) return;
boardTestUpdatedMs_ = now;
const uint16_t analogRx = analogRead(GPIO_ANALOG_RX);
const uint16_t vbat = analogRead(GPIO_VBAT);
Serial.printf("ADC analog_rx=%u vbat=%u\n", analogRx, vbat);
if (now - boardDisplayUpdatedMs_ >= BOARD_TEST_DISPLAY_INTERVAL_MS) {
boardDisplayUpdatedMs_ = now;
char one[32], two[32];
snprintf(one, sizeof(one), "ADC RX: %u", analogRx);
snprintf(two, sizeof(two), "ADC VBAT: %u", vbat);
display_.show(one, two);
}
return;
}
if (test == BoardTest::PWM_OUTPUT) {
if (now - boardTestUpdatedMs_ < BOARD_PWM_TEST_HALF_PERIOD_MS) return;
boardTestUpdatedMs_ = now;
boardPwmLightOn_ = !boardPwmLightOn_;
if (boardPwmLightOn_) pwm_.lightOn();
else pwm_.stop();
Serial.printf("BOARD PWM: light=%s\n", boardPwmLightOn_ ? "ON" : "OFF");
char two[32];
snprintf(two, sizeof(two), "%luHz 50%%: %s", BOARD_PWM_TEST_FREQUENCY_HZ,
boardPwmLightOn_ ? "ON" : "OFF");
display_.show(UiText::BOARD_TEST_NAMES[static_cast<uint8_t>(test)], two);
return;
}
const bool level = digitalRead(GPIO_RX) == HIGH;
if (!rxPinStateKnown_ || level != rxPinState_) {
rxPinState_ = level;
rxPinStateKnown_ = true;
Serial.printf("RX GPIO=%u state=%s (%u)\n", GPIO_RX,
level ? "HIGH" : "LOW", level ? 1U : 0U);
char two[32];
snprintf(two, sizeof(two), "GPIO %u: %s", GPIO_RX, level ? "HIGH" : "LOW");
display_.show(UiText::BOARD_TEST_NAMES[static_cast<uint8_t>(test)], two);
}
}
void App::stopBoardTest() {
Log::printf("BOARD", "stopping test=%s", boardTestName(static_cast<BoardTest>(settings_.boardTest)));
pwm_.stop();
state_ = AppState::IDLE;
setActivePerformance(false);
showIdle();
}
bool App::armSlave(bool preserveDisplay) {
setActivePerformance(false);
pwm_.stop();
@@ -1291,13 +1465,15 @@ bool App::usbHostPresent() const {
void App::setStandbyOpticalOutput() {
// A gate driver must never be held enabled while the tester is idle or
// showing a result. DRIVER is SOLO-only, so force real light OFF here.
if (static_cast<Role>(settings_.role) == Role::SLAVE ||
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD ||
static_cast<Role>(settings_.role) == Role::SLAVE ||
static_cast<TestKind>(settings_.testKind) == TestKind::DRIVER) pwm_.stop();
else pwm_.active();
}
void App::setActivePerformance(bool active) {
const bool driverMode = initialized_ &&
static_cast<TestGroup>(settings_.testGroup) == TestGroup::OPTICS &&
static_cast<TestKind>(settings_.testKind) == TestKind::DRIVER;
const uint32_t targetMhz = active ? (driverMode ? 240U : 160U) : 80U;
if (getCpuFrequencyMhz() != targetMhz && !setCpuFrequencyMhz(targetMhz))
@@ -1406,7 +1582,15 @@ 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/%s | light=%s\n", board,
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD) {
Serial.printf("\nOptical Channel Tester | %s | group=BOARD | test=%s\n", board,
boardTestName(static_cast<BoardTest>(settings_.boardTest)));
Serial.printf("GPIO PWM=%u RX=%u ANALOG_RX=%u VBAT=%u START=%u MODE=%u SDA=%u SCL=%u\n",
GPIO_PWM, GPIO_RX, GPIO_ANALOG_RX, GPIO_VBAT, GPIO_BUTTON_START,
GPIO_BUTTON_MODE, GPIO_SDA, GPIO_SCL);
return;
}
Serial.printf("\nOptical Channel Tester | %s | group=OPTICS | mode=%s/%s | light=%s\n", board,
roleName(static_cast<Role>(settings_.role)),
testKindName(static_cast<TestKind>(settings_.testKind)),
configuredLevelName(settings_));