mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-15 06:19:55 +00:00
lower sf fixes
This commit is contained in:
@@ -940,32 +940,40 @@ uint32_t LoRaRadioBase::getEstAirtimeFor(int len_bytes)
|
||||
* drifts with it — reported RX airtime, the TX airtime and duty-cycle
|
||||
* budget that now derive from it, and outbound_expiry. Upstream cannot
|
||||
* drift this way because it asks the radio (getTimeOnAir()); these
|
||||
* accessors are our equivalent. bw is read directly rather than via
|
||||
* getActiveBandwidthKHzX10(), whose fixed-point rounding would cost
|
||||
* precision at 31.25 kHz. */
|
||||
* accessors are our equivalent. Resolve bandwidth through the same
|
||||
* enum as buildModemConfig(): a saved 62 or 62.5 both program 62.5 kHz,
|
||||
* and a rounded setting must not change the airtime calculation. */
|
||||
uint8_t sf = getActiveSpreadingFactor();
|
||||
float bw = _has_radio_override ? _override_bw
|
||||
: (_prefs ? _prefs->bw : (float)LoRaConfig::BANDWIDTH);
|
||||
uint8_t cr_val = getActiveCodingRate();
|
||||
|
||||
if (sf < 6) sf = 6;
|
||||
uint8_t min_sf = _loramac_node ? 6 : 5;
|
||||
if (sf < min_sf) sf = min_sf;
|
||||
if (sf > 12) sf = 12;
|
||||
if (bw < 7.0f) bw = 125.0f;
|
||||
bw = bandwidth_to_hz(bw_khz_to_enum((uint16_t)bw)) / 1000.0f;
|
||||
if (cr_val < 5) cr_val = 5;
|
||||
if (cr_val > 8) cr_val = 8;
|
||||
|
||||
float t_sym = (float)(1 << sf) / (bw * 1000.0f);
|
||||
float t_preamble = (preambleLengthForSF(sf) + 4.25f) * t_sym;
|
||||
/* SX126x/LR11xx/LR20xx add two synchronization symbols at SF5/6
|
||||
* and carry eight more header bits there. SX127x uses the older
|
||||
* format. See Semtech's lr11xx_radio_get_lora_time_on_air_numerator.
|
||||
* Treating SF5 as SF6 charged 397 ms for a 126-byte SF5/BW62.5 CR4/8
|
||||
* packet whose Semtech airtime is 237 ms (confirmed by TX timing). */
|
||||
float fine_sync = (!_loramac_node && sf <= 6) ? 1.0f : 0.0f;
|
||||
float t_preamble = (preambleLengthForSF(sf) + 4.25f + 2.0f * fine_sync) * t_sym;
|
||||
|
||||
/* LDRO threshold must track the SX126x driver's should_enable_ldro()
|
||||
* exactly (symbol time > 16.38 ms) so this estimate's DE matches the
|
||||
* hardware's DE on every SF/BW pair. The old `sf >= 11` was only
|
||||
* correct at BW 125 kHz and diverged on every other bandwidth. */
|
||||
float de = (t_sym > 0.01638f) ? 1.0f : 0.0f;
|
||||
float num = 8.0f * len_bytes - 4.0f * sf + 28.0f + 16.0f;
|
||||
float num = 8.0f * len_bytes - 4.0f * sf + 28.0f + 16.0f - 8.0f * fine_sync;
|
||||
float den = 4.0f * (sf - 2.0f * de);
|
||||
if (den < 1.0f) den = 4.0f;
|
||||
float n_payload = 8.0f + fmaxf(ceilf(num / den) * (cr_val - 4 + 4), 0.0f);
|
||||
float n_payload = 8.0f + fmaxf(ceilf(num / den) * cr_val, 0.0f);
|
||||
|
||||
float t_payload = n_payload * t_sym;
|
||||
return (uint32_t)((t_preamble + t_payload) * 1000.0f);
|
||||
|
||||
@@ -283,19 +283,7 @@ static lr11xx_system_tcxo_supply_voltage_t get_tcxo_voltage(uint16_t mv)
|
||||
/* Get kHz value from Zephyr BW enum — needed for duty cycle timing */
|
||||
static float bw_enum_to_khz(enum lora_signal_bandwidth bw)
|
||||
{
|
||||
switch (bw) {
|
||||
case BW_7_KHZ: return 7.81f;
|
||||
case BW_10_KHZ: return 10.42f;
|
||||
case BW_15_KHZ: return 15.63f;
|
||||
case BW_20_KHZ: return 20.83f;
|
||||
case BW_31_KHZ: return 31.25f;
|
||||
case BW_41_KHZ: return 41.67f;
|
||||
case BW_62_KHZ: return 62.5f;
|
||||
case BW_125_KHZ: return 125.0f;
|
||||
case BW_250_KHZ: return 250.0f;
|
||||
case BW_500_KHZ: return 500.0f;
|
||||
default: return 125.0f;
|
||||
}
|
||||
return lr11xx_radio_get_lora_bw_in_hz(bw_enum_to_lr11xx(bw)) / 1000.0f;
|
||||
}
|
||||
|
||||
/* ── Hardware reset (BUSY stuck recovery) ───────────────────────────── */
|
||||
@@ -352,6 +340,14 @@ static void lr11xx_hardware_reset(struct lr11xx_data *data,
|
||||
|
||||
/* ── Apply modem configuration ──────────────────────────────────────── */
|
||||
|
||||
/* Share the LDRO decision between the hardware and its airtime estimate. */
|
||||
static uint8_t lr11xx_ldro(const struct lora_modem_config *mc)
|
||||
{
|
||||
uint32_t bw_hz = lr11xx_radio_get_lora_bw_in_hz(bw_enum_to_lr11xx(mc->bandwidth));
|
||||
uint32_t symbol_time_us = ((1U << (uint8_t)mc->datarate) * 1000000U) / bw_hz;
|
||||
return symbol_time_us > 16380;
|
||||
}
|
||||
|
||||
static void lr11xx_apply_modem_config(struct lr11xx_data *data,
|
||||
const struct lr11xx_config *cfg,
|
||||
bool tx_mode)
|
||||
@@ -361,16 +357,11 @@ static void lr11xx_apply_modem_config(struct lr11xx_data *data,
|
||||
|
||||
lr11xx_radio_set_rf_freq(ctx, mc->frequency);
|
||||
|
||||
/* LDRO must be enabled when symbol time > 16.38ms (SF11+/BW125 etc) */
|
||||
uint32_t bw_hz = (uint32_t)(bw_enum_to_khz(mc->bandwidth) * 1000.0f);
|
||||
uint32_t symbol_time_us = ((1U << (uint8_t)mc->datarate) * 1000000U) / bw_hz;
|
||||
uint8_t ldro = (symbol_time_us > 16380) ? 1 : 0;
|
||||
|
||||
lr11xx_radio_mod_params_lora_t mod = {
|
||||
.sf = (lr11xx_radio_lora_sf_t)mc->datarate,
|
||||
.bw = bw_enum_to_lr11xx(mc->bandwidth),
|
||||
.cr = cr_enum_to_lr11xx(mc->coding_rate),
|
||||
.ldro = ldro,
|
||||
.ldro = lr11xx_ldro(mc),
|
||||
};
|
||||
lr11xx_radio_set_lora_mod_params(ctx, &mod);
|
||||
|
||||
@@ -1088,20 +1079,24 @@ static uint32_t lr11xx_lora_airtime(const struct device *dev,
|
||||
struct lr11xx_data *data = dev->data;
|
||||
struct lora_modem_config *mc = &data->modem_cfg;
|
||||
|
||||
uint8_t sf = (uint8_t)mc->datarate;
|
||||
float bw = bw_enum_to_khz(mc->bandwidth) * 1000.0f;
|
||||
uint8_t cr = (uint8_t)mc->coding_rate + 4;
|
||||
|
||||
float ts = (float)(1 << sf) / bw;
|
||||
int de = (sf >= 11 && bw <= 125000.0f) ? 1 : 0;
|
||||
float n_payload = 8.0f + fmaxf(
|
||||
ceilf((8.0f * data_len - 4.0f * sf + 28.0f + 16.0f) /
|
||||
(4.0f * (sf - 2.0f * de))) * cr,
|
||||
0.0f);
|
||||
float t_preamble = (mc->preamble_len + 4.25f) * ts;
|
||||
float t_payload = n_payload * ts;
|
||||
|
||||
return (uint32_t)((t_preamble + t_payload) * 1000.0f);
|
||||
/* Use Semtech's calculation, including SF5/6 synchronization and the
|
||||
* actual LDRO/CRC configuration. The old SF>=11 && BW<=125 shortcut
|
||||
* underestimated SF10/BW62.5 and SF12/BW250, including the TX watchdog
|
||||
* budgets derived from this API. */
|
||||
lr11xx_radio_mod_params_lora_t mod = {
|
||||
.sf = (lr11xx_radio_lora_sf_t)mc->datarate,
|
||||
.bw = bw_enum_to_lr11xx(mc->bandwidth),
|
||||
.cr = cr_enum_to_lr11xx(mc->coding_rate),
|
||||
.ldro = lr11xx_ldro(mc),
|
||||
};
|
||||
lr11xx_radio_pkt_params_lora_t pkt = {
|
||||
.preamble_len_in_symb = mc->preamble_len,
|
||||
.header_type = LR11XX_RADIO_LORA_PKT_EXPLICIT,
|
||||
.pld_len_in_bytes = (uint8_t)data_len,
|
||||
.crc = mc->packet_crc_disable ? LR11XX_RADIO_LORA_CRC_OFF
|
||||
: LR11XX_RADIO_LORA_CRC_ON,
|
||||
};
|
||||
return lr11xx_radio_get_lora_time_on_air_in_ms(&pkt, &mod);
|
||||
}
|
||||
|
||||
/* Forward declaration — needed by LBT in send_async */
|
||||
|
||||
Reference in New Issue
Block a user