stay in full RX after TX for 3 seconds

agc reset on every lora_recv_duty_cycle entry
This commit is contained in:
liquidraver
2026-05-01 20:46:12 +02:00
parent 624fc3306c
commit 9282ac8c9c
3 changed files with 968 additions and 797 deletions
File diff suppressed because it is too large Load Diff
+31
View File
@@ -123,6 +123,17 @@ protected:
void configureTx();
void startReceive();
/* Continuous (non-duty-cycle) RX entry, used for the post-TX hot
* window so a quick reply (within ~3 s) is caught before we drop
* back to duty cycle. Caller must check _rx_duty_cycle_enabled
* — only meaningful when duty cycle would otherwise be active. */
void startReceiveHot();
/* Decides between startReceiveHot() and startReceive() based on
* whether duty cycle is currently enabled. Used by the TX wait
* thread on every TX completion path. */
void restartReceiveAfterTx();
void startTxThread(k_thread_stack_t *stack, size_t stack_size);
const struct device *_dev;
@@ -191,6 +202,26 @@ private:
struct k_sem _tx_start_sem;
bool _tx_thread_running;
/* Post-TX hot-RX window: after every TX, run continuous RX for
* POST_TX_HOT_RX_MS so a fast reply (e.g. our repeater echoing
* our flood) can't fall into a duty-cycle sleep gap. After the
* timer expires, _hot_rx_expire_work cancels async RX and re-enters
* via duty cycle (which now does Calibrate(ALL) on entry).
* Hot window is gated by _rx_duty_cycle_enabled — if duty cycle
* is disabled globally there's nothing to "hot up" relative to. */
/* Wrapper makes the work item standard-layout so CONTAINER_OF can
* recover the owning radio without tripping the C++ -Winvalid-offsetof
* warning that fires on the (non-standard-layout) LoRaRadioBase. */
struct HotRxWork {
struct k_work work;
LoRaRadioBase *self;
};
struct k_timer _hot_rx_timer;
HotRxWork _hot_rx_expire_work;
atomic_t _hot_rx_active;
static void hotRxTimerHandler(struct k_timer *timer);
static void hotRxExpireWorkFn(struct k_work *work);
/* Packet statistics */
atomic_t _packets_recv;
atomic_t _packets_sent;
@@ -634,7 +634,7 @@ index 30243ba5dc7..c5e346da139 100644
k_mutex_unlock(&data->lock);
return 0;
}
@@ -1083,14 +1408,469 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency,
@@ -1083,14 +1408,500 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency,
return 0;
}
@@ -982,6 +982,37 @@ index 30243ba5dc7..c5e346da139 100644
+ return ret;
+ }
+
+ /* AGC reset on every entry: Calibrate(ALL) re-initialises the analog
+ * frontend (ADC/PLL/RC) so the receiver starts with a clean AGC state.
+ * Without this, an AGC lock-up from a strong adjacent-channel signal
+ * persists across the cycle (the hardware-driven duty cycle never
+ * fires an IRQ to trigger sx126x_restart_rx's calibration path), and
+ * post-TX entry inherits whatever state the chip was in before TX.
+ * Cost: ~5 ms — paid once per entry, not per internal duty-cycle wake. */
+ {
+ const struct sx126x_hal_config *hal_cfg = dev->config;
+
+ sx126x_calibrate(dev, SX126X_CALIBRATE_ALL);
+ k_busy_wait(5000);
+ ret = sx126x_hal_wait_busy(dev, 50);
+ if (ret < 0) {
+ k_mutex_unlock(&data->lock);
+ atomic_set(&data->state, SX126X_REST_STATE);
+ return ret;
+ }
+
+ /* Re-issue CalibrateImage for the operating frequency:
+ * Calibrate(ALL) reverts image cal to the chip default
+ * (902-928 MHz band) which kills RX sensitivity on
+ * EU868 / 433 / 779 MHz operation. */
+ sx126x_calibrate_image(dev, data->config.frequency);
+
+ /* Re-apply DIO2 as RF switch — Calibrate resets it. */
+ if (hal_cfg->dio2_tx_enable) {
+ sx126x_set_dio2_as_rf_switch(dev, true);
+ }
+ }
+
+ data->rx_cb = cb;
+ data->rx_cb_user_data = user_data;
+ atomic_inc(&data->rx_cb_gen);
@@ -1111,7 +1142,7 @@ index 30243ba5dc7..c5e346da139 100644
};
#ifdef CONFIG_PM_DEVICE
@@ -1112,6 +1892,7 @@ static int sx126x_pm_action(const struct device *dev,
@@ -1112,6 +1923,7 @@ static int sx126x_pm_action(const struct device *dev,
static int sx126x_init(const struct device *dev)
{
struct sx126x_data *data = dev->data;
@@ -1119,7 +1150,7 @@ index 30243ba5dc7..c5e346da139 100644
int ret;
/* Initialize data structures */
@@ -1121,9 +1902,25 @@ static int sx126x_init(const struct device *dev)
@@ -1121,9 +1933,25 @@ static int sx126x_init(const struct device *dev)
k_msgq_init(&data->rx_msgq, (char *)&data->rx_result,
sizeof(struct sx126x_rx_result), 1);
k_work_init(&data->irq_work, sx126x_irq_work_handler);