|
|
|
@@ -576,9 +576,39 @@ rebase is deliberately behaviour-preserving ("step A"):
|
|
|
|
|
* The DIO1 work queue is named through k_work_queue_config.name. Main
|
|
|
|
|
deprecates writing k_work_q.thread directly.
|
|
|
|
|
|
|
|
|
|
Step B, still open: shrink this patch toward upstream's own duty-cycle
|
|
|
|
|
structure one piece at a time, with a bench PDR run per piece, until what
|
|
|
|
|
remains is only what upstream does not do. Validated so far, on a Wio Tracker
|
|
|
|
|
Step B (2026-09-19), each piece benched on a Wio L1 <-> T1000-E PDR run
|
|
|
|
|
with duty cycle on, 50 packets each way, all 50/50 (pieces 1-2 at 2 s and
|
|
|
|
|
800 ms gaps, piece 3 at 800 ms):
|
|
|
|
|
|
|
|
|
|
1. Upstream's sx126x_set_stop_timer_on_preamble() and
|
|
|
|
|
sx126x_set_rx_duty_cycle() restored verbatim and used by both of our
|
|
|
|
|
duty-cycle entry points instead of open-coded command writes. Same two
|
|
|
|
|
commands in the same order; at the entry site the RX-gain register write
|
|
|
|
|
now precedes StopTimerOnPreamble (all in STDBY). The duplicate
|
|
|
|
|
SX126X_REG_RETENTION_LIST / SX126X_MAX_RETENTION_REGS defines this patch
|
|
|
|
|
added to sx126x_regs.h were dropped -- upstream defines both.
|
|
|
|
|
2. Our dc_rx_time / dc_sleep_time fields dropped in favour of upstream's
|
|
|
|
|
data->duty_cycle.rx_period / .sleep_period (same 15.625 us units).
|
|
|
|
|
3. Upstream's sx126x_duty_cycle_stop() and its preamble-length explanation
|
|
|
|
|
restored, and used by the duty-cycle entry's cancel branch (identical
|
|
|
|
|
wake-if-BUSY -> STDBY_RC -> sleep sequence).
|
|
|
|
|
|
|
|
|
|
Net: +2509/-364 -> +2478/-287 lines against upstream. Deliberately not
|
|
|
|
|
done: replacing our STATE_RX + rx_duty_cycle_enabled model with upstream's
|
|
|
|
|
SX126X_STATE_RX_DUTY_CYCLE. Upstream's enum value already sits in the base
|
|
|
|
|
file unused, so the switch would shrink nothing, while rewriting the RX->TX
|
|
|
|
|
CAS, busy gate, watchdog and restart paths -- the riskiest code in the
|
|
|
|
|
driver. What this patch still deletes is upstream code ours replaces on
|
|
|
|
|
purpose: its duty-cycle driver (ours re-arms RX before running the
|
|
|
|
|
callback and has the parked-RX watchdog) and its RX-done/timeout handlers.
|
|
|
|
|
|
|
|
|
|
Open follow-up, not a reduction: sx126x_lora_recv_async()'s cancel branch
|
|
|
|
|
(ZephCore's hwCancelReceive()) issues SetStandby without a raw-NSS wake,
|
|
|
|
|
so under duty cycle it can block in wait_busy() until the chip's next RX
|
|
|
|
|
window (bounded by one sleep period). sx126x_duty_cycle_stop() would avoid
|
|
|
|
|
that, but it is a behaviour change on paths a PDR run does not reach
|
|
|
|
|
(reconfigure, CAD-timeout recovery, runtime rxduty toggle), so it waits for
|
|
|
|
|
a bench that exercises them. Validated so far, on a Wio Tracker
|
|
|
|
|
L1 and a T1000-E: 50/50 packet parity with the v4.4 build in both directions,
|
|
|
|
|
with RX duty cycle off (2 s gap) and on (2 s and 800 ms gaps).
|
|
|
|
|
|
|
|
|
@@ -624,7 +654,7 @@ Regenerate with:
|
|
|
|
|
appended to this preamble.
|
|
|
|
|
|
|
|
|
|
diff --git a/drivers/lora/native/sx126x/sx126x.c b/drivers/lora/native/sx126x/sx126x.c
|
|
|
|
|
index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
index c8e682ee8..b5ab10c4e 100644
|
|
|
|
|
--- a/drivers/lora/native/sx126x/sx126x.c
|
|
|
|
|
+++ b/drivers/lora/native/sx126x/sx126x.c
|
|
|
|
|
@@ -6,14 +6,52 @@
|
|
|
|
@@ -787,13 +817,11 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
static bool should_enable_ldro(enum lora_datarate sf, enum lora_signal_bandwidth bw,
|
|
|
|
|
const struct sx126x_hal_config *config)
|
|
|
|
|
{
|
|
|
|
|
@@ -336,46 +474,138 @@ static int sx126x_set_sync_word(const struct device *dev, const struct lora_mode
|
|
|
|
|
@@ -336,10 +474,128 @@ static int sx126x_set_sync_word(const struct device *dev, const struct lora_mode
|
|
|
|
|
return sx126x_hal_write_regs(dev, SX126X_REG_LORA_SYNC_WORD_MSB, buf, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-static int sx126x_set_rx_gain(const struct device *dev, bool boosted)
|
|
|
|
|
-{
|
|
|
|
|
- uint8_t val = boosted ? SX126X_RX_GAIN_BOOSTED : SX126X_RX_GAIN_POWER_SAVING;
|
|
|
|
|
+/* RSSI / AGC band calibration (DS Sec 6.1.6, Table 6-4).
|
|
|
|
|
+ *
|
|
|
|
|
+ * Semtech: "The power seen by the SX1261/2 analog front-end is affected by
|
|
|
|
@@ -823,9 +851,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ uint8_t sensi_adjust; /* 0x08AC, bits 7:2 */
|
|
|
|
|
+ uint8_t gain_tune[SX126X_AGC_GAIN_TUNE_LEN]; /* 0x08F5 .. 0x08FB */
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
|
|
- return sx126x_hal_write_regs(dev, SX126X_REG_RX_GAIN, &val, 1);
|
|
|
|
|
-}
|
|
|
|
|
+
|
|
|
|
|
+static const struct sx126x_agc_band_cal sx126x_agc_cal_high = {
|
|
|
|
|
+ .rssi_meas_cal_h = 0x01,
|
|
|
|
|
+ .rssi_meas_cal_l = 0x53,
|
|
|
|
@@ -833,11 +859,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ .sensi_adjust = SX126X_AGC_SENSI_ADJUST_HIGH_BAND,
|
|
|
|
|
+ .gain_tune = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
|
|
-static int sx126x_set_tx(const struct device *dev, uint32_t timeout_ms)
|
|
|
|
|
-{
|
|
|
|
|
- uint32_t timeout = SX126X_MS_TO_TIMEOUT(timeout_ms);
|
|
|
|
|
- uint8_t buf[3];
|
|
|
|
|
+
|
|
|
|
|
+static const struct sx126x_agc_band_cal sx126x_agc_cal_low = {
|
|
|
|
|
+ .rssi_meas_cal_h = 0x01,
|
|
|
|
|
+ .rssi_meas_cal_l = 0x27,
|
|
|
|
@@ -846,44 +868,30 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ /* GainTune_1_2, _3_4, _5_6, _7_8, _9_10, _11_12, _13 */
|
|
|
|
|
+ .gain_tune = { 0xDE, 0xE2, 0x32, 0x44, 0x33, 0x34, 0x04 },
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
|
|
- sys_put_be24(timeout, buf);
|
|
|
|
|
- return sx126x_hal_write_cmd(dev, SX126X_CMD_SET_TX, buf, 3);
|
|
|
|
|
-}
|
|
|
|
|
+
|
|
|
|
|
+/* Band split. The datasheet only characterises 470-490 and 868-915, so any
|
|
|
|
|
+ * threshold between them is a judgement call; 600 MHz sits clear of both the
|
|
|
|
|
+ * 433/470 group and the 779/868/915 group that sx126x_calibrate_image()
|
|
|
|
|
+ * already distinguishes. */
|
|
|
|
|
+#define SX126X_AGC_LOW_BAND_MAX_HZ 600000000
|
|
|
|
|
|
|
|
|
|
-static int sx126x_set_stop_timer_on_preamble(const struct device *dev,
|
|
|
|
|
- bool enable)
|
|
|
|
|
+
|
|
|
|
|
+static const struct sx126x_agc_band_cal *sx126x_agc_cal_for(uint32_t freq)
|
|
|
|
|
{
|
|
|
|
|
- uint8_t val = enable;
|
|
|
|
|
-
|
|
|
|
|
- return sx126x_hal_write_cmd(dev, SX126X_CMD_STOP_TIMER_ON_PREAMBLE,
|
|
|
|
|
- &val, 1);
|
|
|
|
|
+{
|
|
|
|
|
+ return (freq < SX126X_AGC_LOW_BAND_MAX_HZ) ? &sx126x_agc_cal_low
|
|
|
|
|
+ : &sx126x_agc_cal_high;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-static int sx126x_set_rx_duty_cycle(const struct device *dev,
|
|
|
|
|
- uint32_t rx_period, uint32_t sleep_period)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Apply the band's RSSI/AGC calibration. Caches AgcSensiAdjust for the RX
|
|
|
|
|
+ * gain writes, which share register 0x08AC, but does NOT touch 0x08AC itself
|
|
|
|
|
+ * -- sx126x_set_rx_gain() owns that register and runs later in
|
|
|
|
|
+ * sx126x_config(). */
|
|
|
|
|
+static int sx126x_apply_agc_band_cal(const struct device *dev, uint32_t freq)
|
|
|
|
|
{
|
|
|
|
|
- uint8_t buf[6];
|
|
|
|
|
+{
|
|
|
|
|
+ struct sx126x_data *data = dev->data;
|
|
|
|
|
+ const struct sx126x_agc_band_cal *cal = sx126x_agc_cal_for(freq);
|
|
|
|
|
+ uint8_t val;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
- sys_put_be24(rx_period, &buf[0]);
|
|
|
|
|
- sys_put_be24(sleep_period, &buf[3]);
|
|
|
|
|
+ int ret;
|
|
|
|
|
+
|
|
|
|
|
+ data->agc_sensi_adjust = cal->sensi_adjust;
|
|
|
|
|
+
|
|
|
|
|
+ /* Bits 4:0 only -- preserve the rest of 0x089C. */
|
|
|
|
@@ -902,15 +910,13 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ if (ret < 0) {
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
- ret = sx126x_set_stop_timer_on_preamble(dev, true);
|
|
|
|
|
+
|
|
|
|
|
+ val = cal->gforst_powthr;
|
|
|
|
|
+ ret = sx126x_hal_write_regs(dev, SX126X_REG_AGC_GFORST_POWTHR, &val, 1);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- return sx126x_hal_write_cmd(dev, SX126X_CMD_SET_RX_DUTY_CYCLE, buf, 6);
|
|
|
|
|
+ if (ret < 0) {
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return sx126x_hal_write_regs(dev, SX126X_REG_AGC_GAIN_TUNE_1_2,
|
|
|
|
|
+ cal->gain_tune,
|
|
|
|
|
+ SX126X_AGC_GAIN_TUNE_LEN);
|
|
|
|
@@ -918,12 +924,13 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+
|
|
|
|
|
+/* Byte to write to 0x08AC: band AgcSensiAdjust in bits 7:2, gain mode in 1:0. */
|
|
|
|
|
+static uint8_t sx126x_rx_gain_byte(const struct device *dev, bool boosted)
|
|
|
|
|
+{
|
|
|
|
|
{
|
|
|
|
|
- uint8_t val = boosted ? SX126X_RX_GAIN_BOOSTED : SX126X_RX_GAIN_POWER_SAVING;
|
|
|
|
|
+ struct sx126x_data *data = dev->data;
|
|
|
|
|
+
|
|
|
|
|
+ return SX126X_RX_GAIN_VAL(data->agc_sensi_adjust, boosted);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
+static int sx126x_set_rx_gain(const struct device *dev, bool boosted)
|
|
|
|
|
+{
|
|
|
|
|
+ uint8_t val = sx126x_rx_gain_byte(dev, boosted);
|
|
|
|
@@ -938,20 +945,10 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ * wakes are chip-internal warm starts the host never sees, which is
|
|
|
|
|
+ * why 0x08AC is in the retention list installed by
|
|
|
|
|
+ * sx126x_install_retention_list() at chip init. */
|
|
|
|
|
+ return sx126x_hal_write_regs(dev, SX126X_REG_RX_GAIN, &val, 1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int sx126x_set_tx(const struct device *dev, uint32_t timeout_ms)
|
|
|
|
|
+{
|
|
|
|
|
+ uint32_t timeout = SX126X_MS_TO_TIMEOUT(timeout_ms);
|
|
|
|
|
+ uint8_t buf[3];
|
|
|
|
|
+
|
|
|
|
|
+ sys_put_be24(timeout, buf);
|
|
|
|
|
+ return sx126x_hal_write_cmd(dev, SX126X_CMD_SET_TX, buf, 3);
|
|
|
|
|
return sx126x_hal_write_regs(dev, SX126X_REG_RX_GAIN, &val, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sx126x_set_rx(const struct device *dev, uint32_t timeout_ms)
|
|
|
|
|
@@ -415,7 +645,7 @@ static int sx126x_get_packet_status(const struct device *dev,
|
|
|
|
|
@@ -415,7 +671,7 @@ static int sx126x_get_packet_status(const struct device *dev,
|
|
|
|
|
uint8_t buf[3];
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
@@ -960,7 +957,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
/* RSSI is -value/2 dBm */
|
|
|
|
|
*rssi = -((int16_t)buf[0] >> 1);
|
|
|
|
|
@@ -443,6 +673,12 @@ static int sx126x_add_reg_to_retention(const struct device *dev, uint16_t addr)
|
|
|
|
|
@@ -443,6 +699,12 @@ static int sx126x_add_reg_to_retention(const struct device *dev, uint16_t addr)
|
|
|
|
|
|
|
|
|
|
n = buf[0];
|
|
|
|
|
|
|
|
|
@@ -973,7 +970,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
for (uint8_t i = 0; i < n; i++) {
|
|
|
|
|
if (sys_get_be16(&buf[1 + 2 * i]) == addr) {
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -460,6 +696,92 @@ static int sx126x_add_reg_to_retention(const struct device *dev, uint16_t addr)
|
|
|
|
|
@@ -460,6 +722,92 @@ static int sx126x_add_reg_to_retention(const struct device *dev, uint16_t addr)
|
|
|
|
|
return sx126x_hal_write_regs(dev, SX126X_REG_RETENTION_LIST, buf, sizeof(buf));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1066,7 +1063,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
static int sx126x_chip_init(const struct device *dev)
|
|
|
|
|
{
|
|
|
|
|
const struct sx126x_hal_config *config = dev->config;
|
|
|
|
|
@@ -520,6 +842,26 @@ static int sx126x_chip_init(const struct device *dev)
|
|
|
|
|
@@ -520,6 +868,26 @@ static int sx126x_chip_init(const struct device *dev)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1093,7 +1090,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
/* Set packet type to LoRa */
|
|
|
|
|
ret = sx126x_set_packet_type(dev, SX126X_PACKET_TYPE_LORA);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
@@ -527,10 +869,23 @@ static int sx126x_chip_init(const struct device *dev)
|
|
|
|
|
@@ -527,10 +895,23 @@ static int sx126x_chip_init(const struct device *dev)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1120,7 +1117,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
LOG_ERR("Set IRQ params failed: %d", ret);
|
|
|
|
|
return ret;
|
|
|
|
|
@@ -543,21 +898,9 @@ static int sx126x_chip_init(const struct device *dev)
|
|
|
|
|
@@ -543,21 +924,9 @@ static int sx126x_chip_init(const struct device *dev)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1145,7 +1142,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
|
|
|
|
|
LOG_INF("SX126x initialized");
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -567,15 +910,44 @@ static void sx126x_dio1_callback(const struct device *dev)
|
|
|
|
|
@@ -567,15 +936,44 @@ static void sx126x_dio1_callback(const struct device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct sx126x_data *data = dev->data;
|
|
|
|
|
|
|
|
|
@@ -1192,7 +1189,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
sx126x_hal_set_rf_switch(dev, enable, tx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -595,6 +967,7 @@ static void sx126x_disconnect_rf_gpios(const struct device *dev)
|
|
|
|
|
@@ -595,6 +993,7 @@ static void sx126x_disconnect_rf_gpios(const struct device *dev)
|
|
|
|
|
sx126x_disconnect_gpio(&config->antenna_enable);
|
|
|
|
|
sx126x_disconnect_gpio(&config->tx_enable);
|
|
|
|
|
sx126x_disconnect_gpio(&config->rx_enable);
|
|
|
|
@@ -1200,7 +1197,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sx126x_reconnect_rf_gpios(const struct device *dev)
|
|
|
|
|
@@ -620,10 +993,238 @@ static int sx126x_reconnect_rf_gpios(const struct device *dev)
|
|
|
|
|
@@ -620,10 +1019,232 @@ static int sx126x_reconnect_rf_gpios(const struct device *dev)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1303,10 +1300,6 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ * preamble arriving at the tail of the RX window can get
|
|
|
|
|
+ * cut off when the sleep phase begins. Kept as insurance --
|
|
|
|
|
+ * see the note above. */
|
|
|
|
|
+ uint8_t stop_on_preamble = 1;
|
|
|
|
|
+ sx126x_hal_write_cmd(dev, SX126X_CMD_STOP_TIMER_ON_PREAMBLE,
|
|
|
|
|
+ &stop_on_preamble, 1);
|
|
|
|
|
+
|
|
|
|
|
+ /* No retention-list write here. Keeping boosted RX gain alive
|
|
|
|
|
+ * across the chip-internal sleep->RX wakes is still MANDATORY
|
|
|
|
|
+ * (DS sec 9.6: the Rx gain configuration "is not saved when
|
|
|
|
@@ -1320,12 +1313,10 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ * needs the list at all -- the LR2021 retains the gain
|
|
|
|
|
+ * (DS sec 6.3.8) and the LR11xx documents no caveat either way. */
|
|
|
|
|
+
|
|
|
|
|
+ /* Re-apply duty cycle with stored timing */
|
|
|
|
|
+ uint8_t dc_buf[6];
|
|
|
|
|
+ sys_put_be24(data->dc_rx_time, &dc_buf[0]);
|
|
|
|
|
+ sys_put_be24(data->dc_sleep_time, &dc_buf[3]);
|
|
|
|
|
+ sx126x_hal_write_cmd(dev, SX126X_CMD_SET_RX_DUTY_CYCLE,
|
|
|
|
|
+ dc_buf, 6);
|
|
|
|
|
+ /* Re-apply duty cycle with stored timing. Upstream's helper
|
|
|
|
|
+ * issues StopTimerOnPreamble (see above) and then SetRxDutyCycle. */
|
|
|
|
|
+ (void)sx126x_set_rx_duty_cycle(dev, data->duty_cycle.rx_period,
|
|
|
|
|
+ data->duty_cycle.sleep_period);
|
|
|
|
|
+
|
|
|
|
|
+ sx126x_dc_watchdog_kick(data);
|
|
|
|
|
+ } else {
|
|
|
|
@@ -1439,7 +1430,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
static int sx126x_set_sleep(const struct device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct sx126x_data *data = dev->data;
|
|
|
|
|
@@ -697,94 +1298,214 @@ static void sx126x_handle_irq_tx_done(const struct device *dev)
|
|
|
|
|
@@ -697,94 +1318,214 @@ static void sx126x_handle_irq_tx_done(const struct device *dev)
|
|
|
|
|
k_msgq_put(&data->tx_msgq, &result, K_NO_WAIT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1714,7 +1705,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -827,13 +1548,97 @@ static void sx126x_irq_work_handler(struct k_work *work)
|
|
|
|
|
@@ -827,13 +1568,97 @@ static void sx126x_irq_work_handler(struct k_work *work)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (irq_status & SX126X_IRQ_RX_DONE) {
|
|
|
|
@@ -1812,7 +1803,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
/* Re-enable the DIO1 interrupt for the next event (unless sleeping) */
|
|
|
|
|
if (atomic_get(&data->state) != SX126X_REST_STATE) {
|
|
|
|
|
sx126x_hal_dio1_irq_enable(dev);
|
|
|
|
|
@@ -894,10 +1699,19 @@ static int sx126x_lora_config(const struct device *dev,
|
|
|
|
|
@@ -894,10 +1719,19 @@ static int sx126x_lora_config(const struct device *dev,
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1833,30 +1824,20 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
@@ -915,13 +1729,19 @@ static int sx126x_lora_config(const struct device *dev,
|
|
|
|
|
@@ -915,6 +1749,12 @@ static int sx126x_lora_config(const struct device *dev,
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- /* Set sync word */
|
|
|
|
|
- ret = sx126x_set_sync_word(dev, config);
|
|
|
|
|
+ /* Sec 15.1 TX Modulation workaround (datasheet errata). */
|
|
|
|
|
+ ret = sx126x_apply_tx_modulation_workaround(dev, config->bandwidth);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- /* Set RX gain */
|
|
|
|
|
+ /* Set sync word */
|
|
|
|
|
+ ret = sx126x_set_sync_word(dev, config);
|
|
|
|
|
+ if (ret < 0) {
|
|
|
|
|
+ goto out;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Set RX gain */
|
|
|
|
|
ret = sx126x_set_rx_gain(dev, hal_config->rx_boosted);
|
|
|
|
|
/* Set sync word */
|
|
|
|
|
ret = sx126x_set_sync_word(dev, config);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
goto out;
|
|
|
|
|
@@ -938,6 +1758,10 @@ out:
|
|
|
|
|
@@ -938,6 +1778,10 @@ out:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1867,7 +1848,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
static int sx126x_lora_send_async(const struct device *dev,
|
|
|
|
|
uint8_t *data_buf, uint32_t data_len,
|
|
|
|
|
struct k_poll_signal *async)
|
|
|
|
|
@@ -955,11 +1779,27 @@ static int sx126x_lora_send_async(const struct device *dev,
|
|
|
|
|
@@ -955,11 +1799,27 @@ static int sx126x_lora_send_async(const struct device *dev,
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1897,7 +1878,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
k_mutex_lock(&data->lock, K_FOREVER);
|
|
|
|
|
|
|
|
|
|
ret = sx126x_ensure_ready(dev);
|
|
|
|
|
@@ -969,6 +1809,59 @@ static int sx126x_lora_send_async(const struct device *dev,
|
|
|
|
|
@@ -969,6 +1829,59 @@ static int sx126x_lora_send_async(const struct device *dev,
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1957,7 +1938,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
data->tx_async_signal = async;
|
|
|
|
|
k_msgq_purge(&data->tx_msgq);
|
|
|
|
|
|
|
|
|
|
@@ -999,8 +1892,90 @@ static int sx126x_lora_send_async(const struct device *dev,
|
|
|
|
|
@@ -999,8 +1912,90 @@ static int sx126x_lora_send_async(const struct device *dev,
|
|
|
|
|
/* Enable antenna and set TX path */
|
|
|
|
|
sx126x_set_rf_path(dev, true, true);
|
|
|
|
|
|
|
|
|
@@ -2050,7 +2031,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
goto out_error;
|
|
|
|
|
}
|
|
|
|
|
@@ -1069,6 +2044,8 @@ static int sx126x_lora_recv(const struct device *dev, uint8_t *data_buf,
|
|
|
|
|
@@ -1069,6 +2064,8 @@ static int sx126x_lora_recv(const struct device *dev, uint8_t *data_buf,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data->rx_cb = NULL;
|
|
|
|
@@ -2059,7 +2040,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
k_msgq_purge(&data->rx_msgq);
|
|
|
|
|
|
|
|
|
|
/* Set packet parameters for variable length reception */
|
|
|
|
|
@@ -1140,6 +2117,8 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
@@ -1140,6 +2137,8 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
/* Stop async reception */
|
|
|
|
|
data->rx_cb = NULL;
|
|
|
|
|
data->rx_cb_user_data = NULL;
|
|
|
|
@@ -2068,7 +2049,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
if (atomic_cas(&data->state, SX126X_STATE_RX, SX126X_STATE_IDLE)) {
|
|
|
|
|
sx126x_set_standby(dev, SX126X_STANDBY_RC);
|
|
|
|
|
sx126x_set_sleep(dev);
|
|
|
|
|
@@ -1154,6 +2133,19 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
@@ -1154,6 +2153,19 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -2088,7 +2069,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
if (!atomic_cas(&data->state, SX126X_REST_STATE, SX126X_STATE_RX)) {
|
|
|
|
|
LOG_ERR("Busy");
|
|
|
|
|
k_mutex_unlock(&data->lock);
|
|
|
|
|
@@ -1167,8 +2159,18 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
@@ -1167,8 +2179,18 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -2107,7 +2088,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
|
|
|
|
|
/* Set packet parameters */
|
|
|
|
|
ret = sx126x_set_packet_params(dev,
|
|
|
|
|
@@ -1181,6 +2183,7 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
@@ -1181,6 +2203,7 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
SX126X_LORA_IQ_INVERTED : SX126X_LORA_IQ_STANDARD);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
data->rx_cb = NULL;
|
|
|
|
@@ -2115,7 +2096,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
sx126x_set_sleep(dev);
|
|
|
|
|
k_mutex_unlock(&data->lock);
|
|
|
|
|
return ret;
|
|
|
|
|
@@ -1193,221 +2196,25 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
@@ -1193,11 +2216,21 @@ static int sx126x_lora_recv_async(const struct device *dev,
|
|
|
|
|
ret = sx126x_set_rx(dev, 0);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
data->rx_cb = NULL;
|
|
|
|
@@ -2126,63 +2107,21 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- k_mutex_unlock(&data->lock);
|
|
|
|
|
- return 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/*
|
|
|
|
|
- * Read this if you have trouble making the duty cycle working reliably.
|
|
|
|
|
- * I have wasted many hours on this so I'm passing this along.
|
|
|
|
|
- *
|
|
|
|
|
- * The driver sets StopTimerOnPreamble = true before entering duty
|
|
|
|
|
- * cycle mode. This makes the radio stay in RX once a preamble is
|
|
|
|
|
- * detected, instead of going back to sleep when the RX window
|
|
|
|
|
- * expires. The radio then searches for the sync word within a
|
|
|
|
|
- * window sized by the receiver's preamble_len. This value must
|
|
|
|
|
- * match the sender's: a mismatch causes the demodulator to stop
|
|
|
|
|
- * searching before the sync word arrives.
|
|
|
|
|
- *
|
|
|
|
|
- * Matching preamble_len — OK (works even if RX joins mid-preamble)
|
|
|
|
|
- *
|
|
|
|
|
- * TX |#########< 100 preamble symbols >###########|SW|HDR| payload |
|
|
|
|
|
- * ^ ^
|
|
|
|
|
- * RX ..sleep..|==RX==|<<< stays in RX >>>>>>>>>>>>|
|
|
|
|
|
- * ^ |
|
|
|
|
|
- * preamble detected |
|
|
|
|
|
- * timer stops (StopTimerOnPreamble)|
|
|
|
|
|
- * search window = 100 symbols |
|
|
|
|
|
- * sync word found -----------------+
|
|
|
|
|
- * --> full packet received, RX_DONE
|
|
|
|
|
- *
|
|
|
|
|
- * Mismatched preamble_len (RX = 8, TX = 100) — FAIL
|
|
|
|
|
- *
|
|
|
|
|
- * TX |#########< 100 preamble symbols >###########|SW|HDR| payload |
|
|
|
|
|
- * ^ ^
|
|
|
|
|
- * RX ..sleep..|==RX==|<<< stays in RX |
|
|
|
|
|
- * ^ but gives up here |
|
|
|
|
|
- * | |<-8->| |
|
|
|
|
|
- * preamble detected |
|
|
|
|
|
- * search window = only 8 symbols |
|
|
|
|
|
- * sync word NOT found within window
|
|
|
|
|
- * --> demodulator fails, packet lost
|
|
|
|
|
- *
|
|
|
|
|
- * See samples/drivers/lora/duty_cycle/
|
|
|
|
|
- */
|
|
|
|
|
-static void sx126x_duty_cycle_stop(const struct device *dev)
|
|
|
|
|
-{
|
|
|
|
|
- /*
|
|
|
|
|
- * During duty cycle the BUSY pin stays asserted even in the
|
|
|
|
|
- * sleep phase. Wake the radio via a raw NSS edge (bypasses
|
|
|
|
|
- * BUSY check) so the standby command can go through
|
|
|
|
|
- * immediately.
|
|
|
|
|
- */
|
|
|
|
|
- if (sx126x_hal_is_busy(dev)) {
|
|
|
|
|
- sx126x_hal_wakeup(dev);
|
|
|
|
|
- }
|
|
|
|
|
- sx126x_set_standby(dev, SX126X_STANDBY_RC);
|
|
|
|
|
- sx126x_set_sleep(dev);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
+ /* Re-apply RX gain after SetRx -- register 0x08AC is reset on every
|
|
|
|
|
+ * SetRx without retention, and lora_config sets gain before going to
|
|
|
|
|
+ * sleep, so without this the first packet would be received in
|
|
|
|
|
+ * power-saving gain regardless of DTS rx-boosted. */
|
|
|
|
|
+ uint8_t gain = sx126x_rx_gain_byte(dev, data->rx_boost_enabled);
|
|
|
|
|
+
|
|
|
|
|
+ sx126x_hal_write_regs(dev, SX126X_REG_RX_GAIN, &gain, 1);
|
|
|
|
|
+
|
|
|
|
|
k_mutex_unlock(&data->lock);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -1255,159 +2288,6 @@ static void sx126x_duty_cycle_stop(const struct device *dev)
|
|
|
|
|
sx126x_set_sleep(dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-static int sx126x_duty_cycle_start(const struct device *dev,
|
|
|
|
|
- k_timeout_t rx_period,
|
|
|
|
|
- k_timeout_t sleep_period)
|
|
|
|
@@ -2215,21 +2154,15 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
- if (ret < 0) {
|
|
|
|
|
- goto out_error;
|
|
|
|
|
- }
|
|
|
|
|
+ /* Re-apply RX gain after SetRx -- register 0x08AC is reset on every
|
|
|
|
|
+ * SetRx without retention, and lora_config sets gain before going to
|
|
|
|
|
+ * sleep, so without this the first packet would be received in
|
|
|
|
|
+ * power-saving gain regardless of DTS rx-boosted. */
|
|
|
|
|
+ uint8_t gain = sx126x_rx_gain_byte(dev, data->rx_boost_enabled);
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- k_mutex_unlock(&data->lock);
|
|
|
|
|
- return 0;
|
|
|
|
|
+ sx126x_hal_write_regs(dev, SX126X_REG_RX_GAIN, &gain, 1);
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-out_error:
|
|
|
|
|
- data->rx_cb = NULL;
|
|
|
|
|
- atomic_set(&data->state, SX126X_REST_STATE);
|
|
|
|
|
- sx126x_set_sleep(dev);
|
|
|
|
|
k_mutex_unlock(&data->lock);
|
|
|
|
|
- k_mutex_unlock(&data->lock);
|
|
|
|
|
- return ret;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
@@ -2262,9 +2195,9 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
- data->rx_cb = cb;
|
|
|
|
|
- data->rx_cb_user_data = user_data;
|
|
|
|
|
-
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- return 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static int sx126x_lora_recv_duty_cycle(const struct device *dev,
|
|
|
|
|
- k_timeout_t rx_period,
|
|
|
|
|
- k_timeout_t sleep_period,
|
|
|
|
@@ -2345,7 +2278,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
static uint32_t sx126x_lora_airtime(const struct device *dev, uint32_t data_len)
|
|
|
|
|
{
|
|
|
|
|
struct sx126x_data *data = dev->data;
|
|
|
|
|
@@ -1491,7 +2298,7 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency,
|
|
|
|
|
@@ -1491,7 +2371,7 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency,
|
|
|
|
|
|
|
|
|
|
/* Set PA config and TX power */
|
|
|
|
|
ret = sx126x_hal_configure_tx_params(dev, tx_power, frequency,
|
|
|
|
@@ -2354,7 +2287,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
goto out_sleep;
|
|
|
|
|
}
|
|
|
|
|
@@ -1523,50 +2330,1135 @@ out_unlock:
|
|
|
|
|
@@ -1523,50 +2403,1122 @@ out_unlock:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -3232,16 +3165,10 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ data->rx_duty_cycle_enabled = false;
|
|
|
|
|
+ sx126x_reset_rx_busy_signals(data);
|
|
|
|
|
+ if (atomic_cas(&data->state, SX126X_STATE_RX, SX126X_STATE_IDLE)) {
|
|
|
|
|
+ /* If we're called during the duty-cycle sleep phase the
|
|
|
|
|
+ * chip is actually asleep and BUSY is asserted -- issuing
|
|
|
|
|
+ * SetStandby straight away stalls the HAL in
|
|
|
|
|
+ * wait_busy(). Poke CS via sx126x_hal_wakeup() first so
|
|
|
|
|
+ * BUSY drops before we try to talk to the chip. */
|
|
|
|
|
+ if (sx126x_hal_is_busy(dev)) {
|
|
|
|
|
+ sx126x_hal_wakeup(dev);
|
|
|
|
|
+ }
|
|
|
|
|
+ sx126x_set_standby(dev, SX126X_STANDBY_RC);
|
|
|
|
|
+ sx126x_set_sleep(dev);
|
|
|
|
|
+ /* May be called in the duty-cycle sleep phase with BUSY
|
|
|
|
|
+ * asserted; upstream's stop wakes via a raw NSS edge
|
|
|
|
|
+ * before STDBY_RC + sleep. */
|
|
|
|
|
+ sx126x_duty_cycle_stop(dev);
|
|
|
|
|
+ }
|
|
|
|
|
+ k_mutex_unlock(&data->lock);
|
|
|
|
|
+ return 0;
|
|
|
|
@@ -3293,8 +3220,8 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ * dropped RX window. */
|
|
|
|
|
+ if (atomic_get(&data->state) == SX126X_STATE_RX) {
|
|
|
|
|
+ const bool rearm = !data->rx_duty_cycle_enabled ||
|
|
|
|
|
+ data->dc_rx_time != rx_time ||
|
|
|
|
|
+ data->dc_sleep_time != sleep_time;
|
|
|
|
|
+ data->duty_cycle.rx_period != rx_time ||
|
|
|
|
|
+ data->duty_cycle.sleep_period != sleep_time;
|
|
|
|
|
+
|
|
|
|
|
+ data->rx_cb = cb;
|
|
|
|
|
+ data->rx_cb_user_data = user_data;
|
|
|
|
@@ -3305,8 +3232,8 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ data->dc_rx_time = rx_time;
|
|
|
|
|
+ data->dc_sleep_time = sleep_time;
|
|
|
|
|
+ data->duty_cycle.rx_period = rx_time;
|
|
|
|
|
+ data->duty_cycle.sleep_period = sleep_time;
|
|
|
|
|
+ data->rx_duty_cycle_enabled = true;
|
|
|
|
|
+
|
|
|
|
|
+ /* Mid-cycle the chip may be in its duty-cycle sleep phase with
|
|
|
|
@@ -3417,18 +3344,14 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+
|
|
|
|
|
+ /* Store for restart_rx to re-use (periods validated and converted at
|
|
|
|
|
+ * function entry, before the state was claimed). */
|
|
|
|
|
+ data->dc_rx_time = rx_time;
|
|
|
|
|
+ data->dc_sleep_time = sleep_time;
|
|
|
|
|
+ data->duty_cycle.rx_period = rx_time;
|
|
|
|
|
+ data->duty_cycle.sleep_period = sleep_time;
|
|
|
|
|
+ data->rx_duty_cycle_enabled = true;
|
|
|
|
|
+
|
|
|
|
|
+ /* StopTimerOnPreamble: keep the RX timer from expiring mid-packet
|
|
|
|
|
+ * when a preamble is detected late in the RX window. Without it,
|
|
|
|
|
+ * a packet whose preamble lands near the tail of the RX window
|
|
|
|
|
+ * gets cut off by the sleep transition. */
|
|
|
|
|
+ uint8_t stop_on_preamble = 1;
|
|
|
|
|
+ sx126x_hal_write_cmd(dev, SX126X_CMD_STOP_TIMER_ON_PREAMBLE,
|
|
|
|
|
+ &stop_on_preamble, 1);
|
|
|
|
|
+
|
|
|
|
|
+ /* Apply RX gain. The warm-start retention list that makes the
|
|
|
|
|
+ * chip-internal sleep->RX wakes restore it (DS sec 9.6: mandatory for
|
|
|
|
|
+ * SetRxDutyCycle -- without it every window after the first sleep
|
|
|
|
@@ -3438,11 +3361,8 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
+
|
|
|
|
|
+ sx126x_hal_write_regs(dev, SX126X_REG_RX_GAIN, &gain, 1);
|
|
|
|
|
+
|
|
|
|
|
+ uint8_t buf[6];
|
|
|
|
|
+
|
|
|
|
|
+ sys_put_be24(rx_time, &buf[0]);
|
|
|
|
|
+ sys_put_be24(sleep_time, &buf[3]);
|
|
|
|
|
+ sx126x_hal_write_cmd(dev, SX126X_CMD_SET_RX_DUTY_CYCLE, buf, 6);
|
|
|
|
|
+ /* StopTimerOnPreamble (comment above) + SetRxDutyCycle. */
|
|
|
|
|
+ (void)sx126x_set_rx_duty_cycle(dev, rx_time, sleep_time);
|
|
|
|
|
+
|
|
|
|
|
+ sx126x_dc_watchdog_kick(data);
|
|
|
|
|
+
|
|
|
|
@@ -3526,7 +3446,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
|
|
|
|
|
/* Initialize HAL */
|
|
|
|
|
ret = sx126x_hal_init(dev);
|
|
|
|
|
@@ -1628,6 +3520,8 @@ static int sx126x_init(const struct device *dev)
|
|
|
|
|
@@ -1628,6 +3580,8 @@ static int sx126x_init(const struct device *dev)
|
|
|
|
|
{0}), \
|
|
|
|
|
.rx_enable = GPIO_DT_SPEC_INST_GET_OR(inst, rx_enable_gpios, \
|
|
|
|
|
{0}), \
|
|
|
|
@@ -3535,7 +3455,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
.dio2_tx_enable = DT_INST_PROP(inst, dio2_tx_enable), \
|
|
|
|
|
.dio3_tcxo_enable = DT_INST_NODE_HAS_PROP(inst, dio3_tcxo_voltage), \
|
|
|
|
|
.dio3_tcxo_voltage = DT_INST_PROP_OR(inst, dio3_tcxo_voltage, 0), \
|
|
|
|
|
@@ -1682,6 +3576,8 @@ DT_INST_FOREACH_STATUS_OKAY_VARGS(SX126X_INIT, true)
|
|
|
|
|
@@ -1682,6 +3636,8 @@ DT_INST_FOREACH_STATUS_OKAY_VARGS(SX126X_INIT, true)
|
|
|
|
|
{0}), \
|
|
|
|
|
.rx_enable = GPIO_DT_SPEC_INST_GET_OR(inst, rx_enable_gpios, \
|
|
|
|
|
{0}), \
|
|
|
|
@@ -3545,7 +3465,7 @@ index c8e682ee84c..399b84e8086 100644
|
|
|
|
|
.dio3_tcxo_enable = DT_INST_NODE_HAS_PROP(inst, dio3_tcxo_voltage), \
|
|
|
|
|
.dio3_tcxo_voltage = DT_INST_PROP_OR(inst, dio3_tcxo_voltage, 0), \
|
|
|
|
|
diff --git a/drivers/lora/native/sx126x/sx126x.h b/drivers/lora/native/sx126x/sx126x.h
|
|
|
|
|
index 0122958c32a..bac80103ff7 100644
|
|
|
|
|
index 0122958c3..9d39100a7 100644
|
|
|
|
|
--- a/drivers/lora/native/sx126x/sx126x.h
|
|
|
|
|
+++ b/drivers/lora/native/sx126x/sx126x.h
|
|
|
|
|
@@ -57,6 +57,7 @@ struct sx126x_data {
|
|
|
|
@@ -3556,7 +3476,7 @@ index 0122958c32a..bac80103ff7 100644
|
|
|
|
|
|
|
|
|
|
/* RX duty cycle parameters (in SX126x timeout ticks) */
|
|
|
|
|
struct {
|
|
|
|
|
@@ -69,7 +70,136 @@ struct sx126x_data {
|
|
|
|
|
@@ -69,7 +70,133 @@ struct sx126x_data {
|
|
|
|
|
|
|
|
|
|
/* Deferred work for interrupt handling */
|
|
|
|
|
struct k_work irq_work;
|
|
|
|
@@ -3628,9 +3548,6 @@ index 0122958c32a..bac80103ff7 100644
|
|
|
|
|
+ * Reset together with the other RX-busy signals. */
|
|
|
|
|
+ atomic_t raw_header_seen_at_ms;
|
|
|
|
|
+
|
|
|
|
|
+ uint32_t dc_rx_time; /* stored duty cycle rx period (15.625us steps) */
|
|
|
|
|
+ uint32_t dc_sleep_time; /* stored duty cycle sleep period (15.625us steps) */
|
|
|
|
|
+
|
|
|
|
|
+ /* Parked-RX watchdog. StopTimerOnPreamble=1 means a false preamble
|
|
|
|
|
+ * detect parks the chip in full RX "until the next received frame"
|
|
|
|
|
+ * (AN1200.36 sec 3) with no IRQ fired -- nothing is lost (parked RX
|
|
|
|
@@ -3694,7 +3611,7 @@ index 0122958c32a..bac80103ff7 100644
|
|
|
|
|
|
|
|
|
|
#endif /* ZEPHYR_DRIVERS_LORA_SX126X_SX126X_INTERNAL_H_ */
|
|
|
|
|
diff --git a/drivers/lora/native/sx126x/sx126x_hal.c b/drivers/lora/native/sx126x/sx126x_hal.c
|
|
|
|
|
index 34f7089584f..394578956de 100644
|
|
|
|
|
index 34f708958..394578956 100644
|
|
|
|
|
--- a/drivers/lora/native/sx126x/sx126x_hal.c
|
|
|
|
|
+++ b/drivers/lora/native/sx126x/sx126x_hal.c
|
|
|
|
|
@@ -150,7 +150,13 @@ int sx126x_hal_init(const struct device *dev)
|
|
|
|
@@ -3787,7 +3704,7 @@ index 34f7089584f..394578956de 100644
|
|
|
|
|
|
|
|
|
|
uint8_t buf[2] = { (uint8_t)tx_power, ramp_time };
|
|
|
|
|
diff --git a/drivers/lora/native/sx126x/sx126x_hal.h b/drivers/lora/native/sx126x/sx126x_hal.h
|
|
|
|
|
index e4b26ba60bd..558890ad54c 100644
|
|
|
|
|
index e4b26ba60..558890ad5 100644
|
|
|
|
|
--- a/drivers/lora/native/sx126x/sx126x_hal.h
|
|
|
|
|
+++ b/drivers/lora/native/sx126x/sx126x_hal.h
|
|
|
|
|
@@ -29,6 +29,10 @@ struct sx126x_hal_config {
|
|
|
|
@@ -3802,7 +3719,7 @@ index e4b26ba60bd..558890ad54c 100644
|
|
|
|
|
uint8_t dio3_tcxo_voltage;
|
|
|
|
|
bool dio2_tx_enable;
|
|
|
|
|
diff --git a/drivers/lora/native/sx126x/sx126x_hal_common.c b/drivers/lora/native/sx126x/sx126x_hal_common.c
|
|
|
|
|
index 19c71594193..5f7eece3930 100644
|
|
|
|
|
index 19c715941..5f7eece39 100644
|
|
|
|
|
--- a/drivers/lora/native/sx126x/sx126x_hal_common.c
|
|
|
|
|
+++ b/drivers/lora/native/sx126x/sx126x_hal_common.c
|
|
|
|
|
@@ -41,11 +41,29 @@ static int spi_transfer(const struct spi_dt_spec *spi,
|
|
|
|
@@ -3839,7 +3756,7 @@ index 19c71594193..5f7eece3930 100644
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
diff --git a/drivers/lora/native/sx126x/sx126x_hal_stm32wl.c b/drivers/lora/native/sx126x/sx126x_hal_stm32wl.c
|
|
|
|
|
index b7ffbac7a6e..382acfc50b9 100644
|
|
|
|
|
index b7ffbac7a..382acfc50 100644
|
|
|
|
|
--- a/drivers/lora/native/sx126x/sx126x_hal_stm32wl.c
|
|
|
|
|
+++ b/drivers/lora/native/sx126x/sx126x_hal_stm32wl.c
|
|
|
|
|
@@ -254,6 +254,15 @@ int sx126x_hal_init(const struct device *dev)
|
|
|
|
@@ -3859,10 +3776,10 @@ index b7ffbac7a6e..382acfc50b9 100644
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
diff --git a/drivers/lora/native/sx126x/sx126x_regs.h b/drivers/lora/native/sx126x/sx126x_regs.h
|
|
|
|
|
index 1e6146f751f..5992e99969b 100644
|
|
|
|
|
index 1e6146f75..03e72ff90 100644
|
|
|
|
|
--- a/drivers/lora/native/sx126x/sx126x_regs.h
|
|
|
|
|
+++ b/drivers/lora/native/sx126x/sx126x_regs.h
|
|
|
|
|
@@ -175,10 +175,45 @@
|
|
|
|
|
@@ -175,10 +175,34 @@
|
|
|
|
|
#define SX126X_LORA_SYNC_WORD_PUBLIC 0x3444
|
|
|
|
|
#define SX126X_LORA_SYNC_WORD_PRIVATE 0x1424
|
|
|
|
|
|
|
|
|
@@ -3895,22 +3812,11 @@ index 1e6146f751f..5992e99969b 100644
|
|
|
|
|
+/* AgcSensiAdjust (0x08AC bits 7:2) per band */
|
|
|
|
|
+#define SX126X_AGC_SENSI_ADJUST_HIGH_BAND 0x25 /* 868-915 MHz (default) */
|
|
|
|
|
+#define SX126X_AGC_SENSI_ADJUST_LOW_BAND 0x22 /* 470-490 MHz */
|
|
|
|
|
+
|
|
|
|
|
+/* Register retention list (DS Sec 9.6). Registers listed here are restored
|
|
|
|
|
+ * by the chip on a warm-start wake -- which is what every RxDutyCycle
|
|
|
|
|
+ * sleep->RX transition is. Layout: entry count at 0x029F, then one
|
|
|
|
|
+ * big-endian 16-bit register address per entry, four entries max.
|
|
|
|
|
+ *
|
|
|
|
|
+ * The datasheet scopes the loss to sleep/warm-start. It does NOT say SetRx
|
|
|
|
|
+ * resets the Rx gain: in continuous RX, with no sleep in the loop, 0x08AC
|
|
|
|
|
+ * simply persists. */
|
|
|
|
|
+#define SX126X_REG_RETENTION_LIST 0x029F
|
|
|
|
|
+#define SX126X_MAX_RETENTION_REGS 4
|
|
|
|
|
|
|
|
|
|
/* TX Clamp Config (workaround for SX1262) */
|
|
|
|
|
#define SX126X_REG_TX_CLAMP_CFG 0x08D8
|
|
|
|
|
diff --git a/dts/bindings/lora/semtech,sx126x-base.yaml b/dts/bindings/lora/semtech,sx126x-base.yaml
|
|
|
|
|
index 2d13d758695..04390be84e5 100644
|
|
|
|
|
index 2d13d7586..04390be84 100644
|
|
|
|
|
--- a/dts/bindings/lora/semtech,sx126x-base.yaml
|
|
|
|
|
+++ b/dts/bindings/lora/semtech,sx126x-base.yaml
|
|
|
|
|
@@ -35,6 +35,24 @@ properties:
|
|
|
|
|