diff --git a/src/RadioProfiles.h b/src/RadioProfiles.h index 7842d140c..578308750 100644 --- a/src/RadioProfiles.h +++ b/src/RadioProfiles.h @@ -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 diff --git a/src/helpers/radiolib/RadioLibWrappers.cpp b/src/helpers/radiolib/RadioLibWrappers.cpp index fdd575cb2..360df43e9 100644 --- a/src/helpers/radiolib/RadioLibWrappers.cpp +++ b/src/helpers/radiolib/RadioLibWrappers.cpp @@ -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(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);