Доработки по тесту драйвера
This commit is contained in:
@@ -38,6 +38,16 @@ float dutyFromPulse(uint32_t hz, uint32_t pulseNs) {
|
||||
return static_cast<float>(static_cast<double>(hz) * pulseNs / 10000000.0);
|
||||
}
|
||||
|
||||
bool configuredTxPulseLightOn(const Settings &settings) {
|
||||
return static_cast<TestKind>(settings.testKind) == TestKind::DRIVER
|
||||
? txActiveLightOn(settings) : true;
|
||||
}
|
||||
|
||||
const char *configuredLevelName(const Settings &settings) {
|
||||
return static_cast<TestKind>(settings.testKind) == TestKind::DRIVER
|
||||
? lightCodeName(static_cast<LightCode>(settings.lightCode)) : "AUTO";
|
||||
}
|
||||
|
||||
void formatTarget(uint32_t hz, uint32_t pulseNs, char *out, size_t size) {
|
||||
char frequency[16], pulse[12];
|
||||
Display::formatPwmFrequency(hz, frequency, sizeof(frequency));
|
||||
@@ -67,7 +77,7 @@ void formatFailure(FailReason reason, uint32_t hz, uint32_t pulseNs,
|
||||
}
|
||||
|
||||
void formatElapsedNs(uint64_t ns, char *out, size_t size) {
|
||||
// Compact form keeps `T:... D:... P:...` within 21 OLED columns.
|
||||
// Compact form keeps error timing within 21 OLED columns.
|
||||
// Exact nanoseconds remain available in the Serial diagnostic.
|
||||
if (ns < 1000ULL) snprintf(out, size, "%llun", ns);
|
||||
else if (ns < 1000000ULL) snprintf(out, size, "%.1fu", ns / 1000.0);
|
||||
@@ -269,7 +279,7 @@ void App::finishInitialization(bool factoryReset) {
|
||||
}
|
||||
sanitizeRange();
|
||||
params_ = store_.params(settings_);
|
||||
pwm_.configureActiveLight(txActiveLightOn(settings_));
|
||||
pwm_.configureActiveLight(configuredTxPulseLightOn(settings_));
|
||||
if (!display_.begin()) Log::event("BOOT", "OLED unavailable; Serial UI remains fully operational");
|
||||
initialized_ = true;
|
||||
if (!receiver_.begin()) { Log::event("BOOT", "FATAL: capture peripheral init failed"); finish(false, FailReason::UNSUPPORTED); return; }
|
||||
@@ -458,7 +468,7 @@ void App::printSerialHelp() {
|
||||
Serial.println(" set min 250|500|1000|2000|5000|10000|50000");
|
||||
Serial.println(" set accuracy 1|2|5|10");
|
||||
Serial.println(" set time 100|250|500|1000|2000|5000 (ms)");
|
||||
Serial.println(" set light HH|HL|LH|LL");
|
||||
Serial.println(" set light HH|HL|LH|LL (DRIVER only)");
|
||||
}
|
||||
|
||||
void App::printSerialStatus() {
|
||||
@@ -471,7 +481,7 @@ void App::printSerialStatus() {
|
||||
appStateName(state_), roleName(static_cast<Role>(settings_.role)),
|
||||
testKindName(static_cast<TestKind>(settings_.testKind)), params_.frequencyHz,
|
||||
params_.maxPulseNs, params_.minPulseNs, params_.accuracyPct, params_.testTimeMs,
|
||||
lightCodeName(static_cast<LightCode>(settings_.lightCode)),
|
||||
configuredLevelName(settings_),
|
||||
usbHostPresent() ? "connected" : "disconnected");
|
||||
}
|
||||
|
||||
@@ -485,7 +495,7 @@ void App::finishSerialSettingsChange() {
|
||||
state_ = AppState::IDLE;
|
||||
sanitizeRange();
|
||||
params_ = store_.params(settings_);
|
||||
pwm_.configureActiveLight(txActiveLightOn(settings_));
|
||||
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();
|
||||
@@ -577,6 +587,10 @@ void App::handleSerialCommand(char *line) {
|
||||
const int index = optionIndex(TEST_TIME_OPTIONS_MS, numeric);
|
||||
if (index >= 0) { settings_.timeIndex = static_cast<uint8_t>(index); accepted = true; }
|
||||
} else if (!strcmp(name, "light")) {
|
||||
if (static_cast<TestKind>(settings_.testKind) != TestKind::DRIVER) {
|
||||
Serial.println("ERR level setting is available only in DRIVER test");
|
||||
return;
|
||||
}
|
||||
if (!strcmp(value, "hh")) { settings_.lightCode = static_cast<uint8_t>(LightCode::HH); accepted = true; }
|
||||
else if (!strcmp(value, "hl")) { settings_.lightCode = static_cast<uint8_t>(LightCode::HL); accepted = true; }
|
||||
else if (!strcmp(value, "lh")) { settings_.lightCode = static_cast<uint8_t>(LightCode::LH); accepted = true; }
|
||||
@@ -634,7 +648,6 @@ void App::sanitizeRange() {
|
||||
DRIVER_MIN_INPUT_PULSE_NS, driverLastMin);
|
||||
if (settings_.minPulseIndex < firstDriverMin)
|
||||
settings_.minPulseIndex = firstDriverMin;
|
||||
settings_.lightCode = static_cast<uint8_t>(LightCode::HL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,17 +685,22 @@ void App::changeMenu(int d) {
|
||||
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: value = &settings_.lightCode; count = 4; break;
|
||||
case 5:
|
||||
if (static_cast<TestKind>(settings_.testKind) != TestKind::DRIVER) {
|
||||
showMenu();
|
||||
return;
|
||||
}
|
||||
value = &settings_.lightCode; count = 4; break;
|
||||
default: return;
|
||||
}
|
||||
*value = cycleIndex(*value, 0, static_cast<uint8_t>(count - 1U), d);
|
||||
}
|
||||
sanitizeRange(); params_ = store_.params(settings_);
|
||||
pwm_.configureActiveLight(txActiveLightOn(settings_));
|
||||
pwm_.configureActiveLight(configuredTxPulseLightOn(settings_));
|
||||
Log::printf("ACTION", "menu item=%u changed direction=%+d frequency=%u max-pulse=%u min-pulse=%u accuracy=%u time=%u light=%s",
|
||||
menuItem_, d, settings_.frequencyIndex, settings_.maxPulseIndex,
|
||||
settings_.minPulseIndex, settings_.accuracyIndex, settings_.timeIndex,
|
||||
lightCodeName(static_cast<LightCode>(settings_.lightCode)));
|
||||
configuredLevelName(settings_));
|
||||
showMenu();
|
||||
}
|
||||
|
||||
@@ -712,6 +730,13 @@ void App::showMenu() {
|
||||
label = UiText::MENU_TEST_TIME;
|
||||
break;
|
||||
case 5: {
|
||||
if (static_cast<TestKind>(settings_.testKind) != TestKind::DRIVER) {
|
||||
snprintf(value, sizeof(value), "%s", UiText::LIGHT_AUTO);
|
||||
label = UiText::MENU_LIGHT_CODE;
|
||||
formatMenuLine(label, value, one, sizeof(one));
|
||||
display_.show(one, UiText::LIGHT_AUTO_FORMAT);
|
||||
return;
|
||||
}
|
||||
const char *code = lightCodeName(static_cast<LightCode>(settings_.lightCode));
|
||||
snprintf(value, sizeof(value), "%s", code);
|
||||
label = UiText::MENU_LIGHT_CODE;
|
||||
@@ -739,13 +764,13 @@ void App::startTest() {
|
||||
Log::printf("TEST", "starting role=%s test=%s light=%s stages=%lu",
|
||||
roleName(static_cast<Role>(settings_.role)),
|
||||
testKindName(static_cast<TestKind>(settings_.testKind)),
|
||||
lightCodeName(static_cast<LightCode>(settings_.lightCode)), stageCount_);
|
||||
configuredLevelName(settings_), stageCount_);
|
||||
if (SERIAL_MINIMAL_LOG) {
|
||||
Log::printf("CONFIG", "mode=%s/%s frequency=%luHz pulse=%lu..%luns accuracy=%.2f%% time=%lums LIGHT=%s stages=%lu",
|
||||
roleName(static_cast<Role>(settings_.role)),
|
||||
testKindName(static_cast<TestKind>(settings_.testKind)), params_.frequencyHz,
|
||||
params_.maxPulseNs, params_.minPulseNs, params_.accuracyPct, params_.testTimeMs,
|
||||
lightCodeName(static_cast<LightCode>(settings_.lightCode)),
|
||||
configuredLevelName(settings_),
|
||||
stageCount_);
|
||||
}
|
||||
printConfiguration();
|
||||
@@ -836,7 +861,7 @@ bool App::startLocalMeasurement(float hz, float duty) {
|
||||
receiver_.plannedPulseTickHz(static_cast<uint32_t>(hz + 0.5f), duty),
|
||||
PWM_SETTLE_CYCLES, params_.testTimeMs);
|
||||
const bool ok = measurement_.start(hz, duty, params_.accuracyPct, params_.testTimeMs,
|
||||
MEASUREMENT_AVERAGING_PERIODS, PWM_SETTLE_CYCLES, rxActiveLightOn(settings_));
|
||||
MEASUREMENT_AVERAGING_PERIODS, PWM_SETTLE_CYCLES, true);
|
||||
const uint32_t nominalMs = stageWallTimeMs(params_.testTimeMs,
|
||||
static_cast<uint32_t>(hz + 0.5f));
|
||||
const uint64_t watchdogMs = static_cast<uint64_t>(nominalMs) * 2ULL + 2000ULL;
|
||||
@@ -1381,15 +1406,20 @@ void App::printConfiguration() {
|
||||
Serial.printf("\nOptical Channel Tester | %s | mode=%s/%s | light=%s\n", board,
|
||||
roleName(static_cast<Role>(settings_.role)),
|
||||
testKindName(static_cast<TestKind>(settings_.testKind)),
|
||||
lightCodeName(static_cast<LightCode>(settings_.lightCode)));
|
||||
configuredLevelName(settings_));
|
||||
Serial.printf("MAC=%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
Serial.printf("GPIO PWM=%u RX=%u START=%u MODE=%u SDA=%u SCL=%u\n", GPIO_PWM, GPIO_RX,
|
||||
GPIO_BUTTON_START, GPIO_BUTTON_MODE, GPIO_SDA, GPIO_SCL);
|
||||
Serial.printf("Test %lu Hz, pulse %lu..%lu ns, accuracy %.2f%%, %lums, TX light=%c RX active light=%c\n",
|
||||
params_.frequencyHz, params_.maxPulseNs, params_.minPulseNs,
|
||||
params_.accuracyPct, params_.testTimeMs,
|
||||
lightCodeName(static_cast<LightCode>(settings_.lightCode))[0],
|
||||
lightCodeName(static_cast<LightCode>(settings_.lightCode))[1]);
|
||||
if (static_cast<TestKind>(settings_.testKind) == TestKind::DRIVER) {
|
||||
const char *code = lightCodeName(static_cast<LightCode>(settings_.lightCode));
|
||||
Serial.printf("Test %lu Hz, pulse %lu..%lu ns, accuracy %.2f%%, %lums, TX light=%c RX active light=%c\n",
|
||||
params_.frequencyHz, params_.maxPulseNs, params_.minPulseNs,
|
||||
params_.accuracyPct, params_.testTimeMs, code[0], code[1]);
|
||||
} else {
|
||||
Serial.printf("Test %lu Hz, pulse %lu..%lu ns, accuracy %.2f%%, %lums, optical polarity=AUTO\n",
|
||||
params_.frequencyHz, params_.maxPulseNs, params_.minPulseNs,
|
||||
params_.accuracyPct, params_.testTimeMs);
|
||||
}
|
||||
stageCount_ = pulseWidthPointCount(params_.maxPulseNs, params_.minPulseNs);
|
||||
Serial.printf("Pulse widths descending (%lu): ", stageCount_);
|
||||
for (uint32_t i = 0; i < stageCount_; ++i)
|
||||
@@ -1484,27 +1514,23 @@ void App::showDriverResult(const DriverStats &s, bool testPassed) {
|
||||
delay, response);
|
||||
} else if (s.reason != FailReason::NONE) {
|
||||
snprintf(one, sizeof(one), "%s", uiFailName(s.reason));
|
||||
char elapsed[12] = "---", errorDelay[12] = "---", errorPulse[12] = "---";
|
||||
if (s.errorElapsedTicks) {
|
||||
char elapsed[12] = "---", errorPulse[12] = "---";
|
||||
if (s.errorTriggerValid) {
|
||||
const uint64_t elapsedNs =
|
||||
(s.errorElapsedTicks * 1000000000ULL + driverTest_.tickHz() / 2U) /
|
||||
(static_cast<uint64_t>(s.errorTriggerTicks) * 1000000000ULL +
|
||||
driverTest_.tickHz() / 2U) /
|
||||
driverTest_.tickHz();
|
||||
formatElapsedNs(elapsedNs, elapsed, sizeof(elapsed));
|
||||
}
|
||||
if (s.errorDelayValid) {
|
||||
const uint64_t errorDelayNs =
|
||||
(static_cast<uint64_t>(s.errorDelayTicks) * 1000000000ULL +
|
||||
driverTest_.tickHz() / 2U) / driverTest_.tickHz();
|
||||
formatElapsedNs(errorDelayNs, errorDelay, sizeof(errorDelay));
|
||||
}
|
||||
if (s.errorPulseValid) {
|
||||
const uint64_t errorPulseNs =
|
||||
(static_cast<uint64_t>(s.errorPulseTicks) * 1000000000ULL +
|
||||
driverTest_.tickHz() / 2U) / driverTest_.tickHz();
|
||||
formatElapsedNs(errorPulseNs, errorPulse, sizeof(errorPulse));
|
||||
}
|
||||
snprintf(two, sizeof(two), "T:%s D:%s P:%s",
|
||||
elapsed, errorDelay, errorPulse);
|
||||
if (s.errorPulseValid)
|
||||
snprintf(two, sizeof(two), "T:%s P:%s", elapsed, errorPulse);
|
||||
else snprintf(two, sizeof(two), "T:%s", elapsed);
|
||||
} else {
|
||||
formatTestTarget(requestedHz_, requestedPulseNs_, one, sizeof(one));
|
||||
snprintf(two, sizeof(two), UiText::DRIVER_MEASUREMENT_FORMAT,
|
||||
|
||||
Reference in New Issue
Block a user