Files
roro9stack/lib/lora/src/sweep_view.cpp
T
twislaandClaude Opus 5.5 b1de0f8804 M3 step 5: Sweep, the band's signal strength as bars and a waterfall
Tab in the LoRa Scanner sweeps 863-870 MHz in 100 kHz steps (the
strongest of three RSSI readings at each, at 125 kHz), shown as bars with
peak hold over a waterfall, the Sniffer's frequency marked (Q98). The
Sweep pauses the Sniffer and keeps its packets; Tab resumes it (Q99).
Status Bar: SW. The floor, top and peaks are host-tested; `lora sweep
on|off|dump` prints them on the console.

At the desk: about 607 ms a pass, a flat floor at -100 to -102 dBm
(15 dB above the chip's own) and a steady carrier at 863.2 MHz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-05 20:28:46 +02:00

49 lines
1.8 KiB
C++

#include "sweep_view.h"
#include <algorithm>
namespace roro::lora {
namespace {
constexpr int kPeakAboveFloorDb = 10;
constexpr size_t kMaxPeaks = 3;
} // namespace
SweepStats summarize(const int8_t* dbm, size_t steps, uint32_t fromHz, uint32_t stepHz) {
SweepStats s;
if (!steps) return s;
std::vector<int8_t> sorted(dbm, dbm + steps);
std::nth_element(sorted.begin(), sorted.begin() + steps / 2, sorted.end());
s.floor = sorted[steps / 2];
s.top = *std::max_element(dbm, dbm + steps);
for (size_t i = 0; i < steps; ++i) {
int v = dbm[i];
bool localMax = (i == 0 || v >= dbm[i - 1]) && (i + 1 == steps || v > dbm[i + 1]);
if (localMax && v >= s.floor + kPeakAboveFloorDb) s.peaks.push_back({fromHz + static_cast<uint32_t>(i) * stepHz, v});
}
std::stable_sort(s.peaks.begin(), s.peaks.end(), [](const SweepPeak& a, const SweepPeak& b) { return a.dbm > b.dbm; });
if (s.peaks.size() > kMaxPeaks) s.peaks.resize(kMaxPeaks);
return s;
}
uint8_t heatLevel(int dbm, int low, int high) {
if (dbm <= low) return 0;
if (dbm >= high) return 255;
return static_cast<uint8_t>((dbm - low) * 255 / (high - low) + ((dbm - low) * 255 % (high - low) ? 1 : 0));
}
uint16_t heatColor(uint8_t level) {
// Five segments of 51 steps each.
auto rgb = [](int r, int g, int b) { return static_cast<uint16_t>((r >> 3) << 11 | (g >> 2) << 5 | (b >> 3)); };
int seg = std::min(level / 51, 4), t = (level - seg * 51) * 255 / 51;
switch (seg) {
case 0: return rgb(0, 0, t); // black to blue
case 1: return rgb(0, t, 255); // blue to cyan
case 2: return rgb(0, 255, 255 - t); // cyan to green
case 3: return rgb(t, 255, 0); // green to yellow
default: return rgb(255, 255 - t, 0); // yellow to red
}
}
} // namespace roro::lora