Public Access
There is no Debug Build any more (ADR 0010, issue #68, Q188 to Q195). The console and the test commands are compiled into every firmware. It listens only while Settings > Debug Console is on, which isn't the default; off, neither its task nor its 4 KB ring exists. The token is made by the device and shown on that page; a client proves it knows it by answering a challenge with an HMAC, so it never crosses the network, and five wrong answers close the console for a minute. DBG in the Status Bar while it listens. Over USB serial only: debug on, debug token <value>, debug token new. scripts/flash.sh --debug uses them to set a device up with the developer's token. scripts/rdbg.py takes the token from -t, $RORO_DEBUG_TOKEN or the file, answers the challenge, and fetches a release's ELF to decode a crash. Gone: the cardputer-adv-debug environment, RORO_DEBUG, the +debug version, scripts/debug_flags.py, update install ... force, and the rule that a Debug Build doesn't install releases. Old clients and old firmwares don't talk to each other. Against the builds it replaces: 30 KB more flash and 88 bytes more static RAM than the release, 4 KB less RAM than the Debug Build. 468 host tests. Checked on the device: off by default, login, the pause after wrong tokens, Safe Mode with the console, the setting surviving an update, debug off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
109 lines
3.5 KiB
C++
109 lines
3.5 KiB
C++
|
|
#include "services/noise_test.h"
|
|
|
|
#include <Arduino.h>
|
|
|
|
#include <algorithm>
|
|
#include <cstdio>
|
|
|
|
#include "platform/console.h"
|
|
#include "sweep_view.h"
|
|
|
|
namespace roro {
|
|
|
|
void NoiseTest::start(std::vector<Condition> conditions, int passes) {
|
|
if (running()) return;
|
|
conditions_ = std::move(conditions);
|
|
results_.clear();
|
|
report_.clear();
|
|
passes_ = passes;
|
|
index_ = 0;
|
|
console.printf("noise test: %u conditions, %d passes each\n", (unsigned)conditions_.size(), passes_);
|
|
begin(millis());
|
|
}
|
|
|
|
void NoiseTest::begin(uint32_t nowMs) {
|
|
const Condition& c = conditions_[index_];
|
|
if (c.apply) c.apply();
|
|
radio_.sweep(true); // sets the radio up again, with whatever the condition changed
|
|
std::fill(std::begin(lowest_), std::end(lowest_), 0);
|
|
std::fill(std::begin(counts_), std::end(counts_), 0);
|
|
seen_ = 0;
|
|
phase_ = Phase::Settle;
|
|
phaseMs_ = nowMs;
|
|
}
|
|
|
|
void NoiseTest::step(uint32_t nowMs) {
|
|
if (phase_ == Phase::Idle) return;
|
|
const Condition& c = conditions_[index_];
|
|
if (phase_ == Phase::Settle) {
|
|
if (nowMs - phaseMs_ < c.settleMs) return;
|
|
lastSeq_ = radio_.sweeps();
|
|
phase_ = Phase::Sweep;
|
|
phaseMs_ = nowMs;
|
|
return;
|
|
}
|
|
SweepFrame f;
|
|
if (radio_.sweeps() != lastSeq_ && radio_.sweepFrame(f)) {
|
|
lastSeq_ = f.seq;
|
|
fromHz_ = f.fromHz, stepHz_ = f.stepHz, steps_ = f.steps;
|
|
for (uint16_t i = 0; i < f.steps; i++) {
|
|
lowest_[i] = seen_ ? std::min(lowest_[i], f.dbm[i]) : f.dbm[i];
|
|
counts_[std::clamp<int>(-f.dbm[i], 0, 127)]++;
|
|
}
|
|
seen_++;
|
|
}
|
|
bool stuck = nowMs - phaseMs_ > 20000; // the radio never swept: don't hang the test
|
|
if (seen_ < passes_ && !stuck) return;
|
|
|
|
Result r;
|
|
r.name = c.name;
|
|
if (seen_) {
|
|
// The floor: the median of every reading. The top and the peaks: from the lowest reading
|
|
// at each step, so a burst in one pass doesn't count and a steady carrier does.
|
|
uint32_t total = 0, half = static_cast<uint32_t>(seen_) * steps_ / 2;
|
|
for (int level = 127; level >= 0; level--) {
|
|
total += counts_[level];
|
|
if (total > half) {
|
|
r.floor = -level;
|
|
break;
|
|
}
|
|
}
|
|
lora::SweepStats st = lora::summarize(lowest_, steps_, fromHz_, stepHz_);
|
|
r.top = st.top;
|
|
char p[32];
|
|
for (auto& peak : st.peaks) {
|
|
std::snprintf(p, sizeof p, "%s%.1f %d", r.peaks.empty() ? "" : ", ", peak.hz / 1e6, peak.dbm);
|
|
r.peaks += p;
|
|
}
|
|
} else {
|
|
r.name += " (no sweep)";
|
|
}
|
|
results_.push_back(r);
|
|
radio_.sweep(false);
|
|
if (c.restore) c.restore();
|
|
if (++index_ < conditions_.size()) begin(nowMs);
|
|
else finish();
|
|
}
|
|
|
|
void NoiseTest::finish() {
|
|
phase_ = Phase::Idle;
|
|
char line[160];
|
|
report_.push_back("noise test: floor = median of every reading; top and peaks = steady (lowest of the passes), dBm at 125 kHz");
|
|
for (auto& r : results_) {
|
|
std::snprintf(line, sizeof line, "noise test: %-26s floor %4d top %4d %s", r.name.c_str(), r.floor, r.top,
|
|
r.peaks.empty() ? "no steady peak" : r.peaks.c_str());
|
|
report_.push_back(line);
|
|
}
|
|
report_.push_back("noise test: done");
|
|
printReport(console);
|
|
}
|
|
|
|
void NoiseTest::printReport(Print& out) const {
|
|
if (report_.empty()) return (void)out.println(running() ? "noise test: still running" : "noise test: none run yet");
|
|
for (auto& l : report_) out.println(l.c_str());
|
|
}
|
|
|
|
} // namespace roro
|
|
|