Share radio profile validation and simplify bounded airtime arithmetic

This commit is contained in:
mikecarper committed 2026-10-19 21:20:57 -07:00
1 parent 44ba5b4f18
commit 1fd993ecf5
2 files changed
+18 -19

No files matched your search

+10 -7
View File
@@ -146,15 +146,18 @@ class RadioProfiles {
const RadioProfileParams& params(uint8_t profile) const {
return profile == 1 ? secondary.params : primary;
}
static bool valid(const RadioProfileParams& p) {
if (!isfinite(p.freq) || !isfinite(p.bw) || p.freq < 137 || p.freq > 2500
static bool valid(const RadioProfileParams& p, bool extended_bandwidths = true) {
if (!(p.freq >= 137 && p.freq <= 2500)
|| p.sf < 5 || p.sf > 12 || p.cr < 5 || p.cr > 8
|| (p.protocol != RadioProfileProtocol::MeshCore && p.protocol != RadioProfileProtocol::Meshtext
&& p.protocol != RadioProfileProtocol::Ethernet)
|| (p.preamble != 0 && (p.preamble < 8 || p.preamble > MaxPreamble))) return false;
static constexpr float bandwidths[] = {7.8f, 10.4f, 15.6f, 20.8f, 31.25f, 41.67f, 41.7f,
62.5f, 83.34f, 101.56f, 125, 203.125f, 250, 406.25f, 500, 812.5f, 1000, 1625};
for (float bw : bandwidths) if (fabsf(p.bw - bw) < 0.01f) return true;
// The first ten entries are the shared SX126x/SX127x bandwidth subset.
static constexpr float bandwidths[] = {7.8f, 10.4f, 15.6f, 20.8f, 31.25f, 41.7f,
62.5f, 125, 250, 500, 41.67f, 83.34f, 101.56f, 203.125f,
406.25f, 812.5f, 1000, 1625};
const size_t count = extended_bandwidths ? sizeof(bandwidths) / sizeof(bandwidths[0]) : 10;
for (size_t i = 0; i < count; ++i) if (fabsf(p.bw - bandwidths[i]) < 0.01f) return true;
return false;
}
static double symbolUs(const RadioProfileParams& p) {
@@ -168,13 +171,13 @@ class RadioProfiles {
const double symbol = symbolUs(p);
if (symbol <= 0) return false;
const int de = symbol >= 16000 ? 1 : 0;
const int denominator = 4 * (p.sf - 2 * de);
const int denominator = p.sf - 2 * de;
// The payload expression is integral apart from this small rational
// ceiling. Preserve even invalid-SF behavior: a zero denominator was
// infinite (and failed the limit), while signed division rounds a
// negative quotient toward zero, exactly its mathematical ceiling.
if (!denominator) return false;
const int numerator = 8 * 255 - 4 * p.sf + (p.sf <= 6 ? 20 : 28) + 16;
const int numerator = 2 * 255 - p.sf + (p.sf <= 6 ? 9 : 11);
const double payload = 8 + (denominator > 0
? (numerator + denominator - 1) / denominator : numerator / denominator) * 8;
// RadioLib's microsecond airtime calculation multiplies by four before
+8 -12
View File
@@ -491,19 +491,17 @@ mesh::RadioParamApplyResult RadioLibWrapper::trySetParams(float freq, float bw,
}
bool RadioLibWrapper::validateProfile(const mesh::RadioProfileParams& p) const {
#if MESH_RADIO_PROFILE_CHIP != 1110 && MESH_RADIO_PROFILE_CHIP != 1121 && MESH_RADIO_PROFILE_CHIP != 2021 && MESH_RADIO_PROFILE_CHIP != 68 && MESH_RADIO_PROFILE_CHIP != 1272
if (!mesh::RadioProfiles::valid(p, false)) return false;
#else
if (!mesh::RadioProfiles::valid(p)) return false;
#endif
if (p.protocol == mesh::RadioProfileProtocol::Meshtext && !supportsMeshtext()) return false;
#if MESH_ENABLE_ETHERNET_WIRE
if (p.protocol == mesh::RadioProfileProtocol::Ethernet && !supportsEthernetTunnel()) return false;
#else
if (p.protocol == mesh::RadioProfileProtocol::Ethernet) return false;
#endif
#if MESH_RADIO_PROFILE_CHIP != 1110 && MESH_RADIO_PROFILE_CHIP != 1121 && MESH_RADIO_PROFILE_CHIP != 2021 && MESH_RADIO_PROFILE_CHIP != 68 && MESH_RADIO_PROFILE_CHIP != 1272
static constexpr float bandwidths[] = {7.8f, 10.4f, 15.6f, 20.8f, 31.25f, 41.7f, 62.5f, 125, 250, 500};
bool supported = false;
for (float bw : bandwidths) if (fabsf(p.bw - bw) < 0.01f) supported = true;
if (!supported) return false;
#endif
#if MESH_RADIO_PROFILE_CHIP == 1276
return p.freq >= 137 && p.freq <= 1020 && p.sf >= 7 && p.bw <= 500;
#elif MESH_RADIO_PROFILE_CHIP == 1272
@@ -675,9 +673,8 @@ uint32_t RadioLibWrapper::getBeaconAirtime(const mesh::RadioProfileParams& p, in
#endif
? 1 : 0;
// Round the small integer bit/block ratio without floating-point division.
const int numerator = 8 * length - 4 * p.sf + (p.sf <= 6 ? 20 : 28) + 16;
const int denominator = 4 * (p.sf - 2 * de);
const int coded = numerator > 0 ? (numerator + denominator - 1) / denominator : 0;
const int denominator = p.sf - 2 * de;
const int coded = (2 * length + (p.sf <= 6 ? 8 : 10) - 2 * de) / denominator;
const double payload = 8 + coded * p.cr;
return static_cast<uint32_t>(ceil((preamble + (p.sf <= 6 ? 6.25 : 4.25) + payload)
* symbol / 1000.0));
@@ -1016,9 +1013,8 @@ uint32_t RadioLibWrapper::getProfileAirtime(uint8_t profile, int len, uint8_t cr
#endif
? 1 : 0;
// Round the small integer bit/block ratio without floating-point division.
const int numerator = 8 * len - 4 * p.sf + (p.sf <= 6 ? 20 : 28) + 16;
const int denominator = 4 * (p.sf - 2 * de);
const int coded = numerator > 0 ? (numerator + denominator - 1) / denominator : 0;
const int denominator = p.sf - 2 * de;
const int coded = (2 * len + (p.sf <= 6 ? 8 : 10) - 2 * de) / denominator;
const double payload_symbols = 8 + coded * cr;
const double suffix = p.sf <= 6 ? 6.25 : 4.25;
const double airtime = ceil((profilePreamble(profile) + suffix + payload_symbols) * symbol / 1000.0);