From d6404dbdc695798711ad4e77e686e33bf045a455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20H=C3=BC=C3=9Fler?= Date: Fri, 26 Sep 2025 13:09:21 +0200 Subject: [PATCH 1/2] drivers/sx126x: split out _set_state and _get_state --- drivers/sx126x/include/sx126x_internal.h | 17 +++++++++++++ drivers/sx126x/sx126x.c | 32 ++++++++++++++++++++++++ drivers/sx126x/sx126x_netdev.c | 29 +++++++-------------- 3 files changed, 58 insertions(+), 20 deletions(-) diff --git a/drivers/sx126x/include/sx126x_internal.h b/drivers/sx126x/include/sx126x_internal.h index 400edea42a..ce27f31aa8 100644 --- a/drivers/sx126x/include/sx126x_internal.h +++ b/drivers/sx126x/include/sx126x_internal.h @@ -122,6 +122,23 @@ static inline bool sx126x_is_stm32wl(sx126x_t *dev) } } +/** + * @brief Get the current chip state + * + * @param[in] dev Device descriptor of the driver + * + * @return Chip state + */ +sx126x_chip_modes_t sx126x_get_state(const sx126x_t *dev); + +/** + * @brief Set the internal chip state + * + * @param[in] dev Device descriptor of the driver + * @param[in] state State to set + */ +void sx126x_set_state(sx126x_t *dev, sx126x_chip_modes_t state); + #ifdef __cplusplus } #endif diff --git a/drivers/sx126x/sx126x.c b/drivers/sx126x/sx126x.c index b442ed16e1..c7b71d2d18 100644 --- a/drivers/sx126x/sx126x.c +++ b/drivers/sx126x/sx126x.c @@ -427,6 +427,38 @@ int sx126x_init(sx126x_t *dev) return res; } +sx126x_chip_modes_t sx126x_get_state(const sx126x_t *dev) +{ + sx126x_chip_status_t radio_status; + sx126x_get_status(dev, &radio_status); + return radio_status.chip_mode; +} + +void sx126x_set_state(sx126x_t *dev, sx126x_chip_modes_t state) +{ + switch (state) { + case SX126X_CHIP_MODE_TX: + sx126x_set_tx(dev, 0); /* no TX frame timeout */ + break; + case SX126X_CHIP_MODE_RX: { + int timeout = (sx126x_symbol_to_msec(dev, dev->rx_timeout)); + sx126x_set_rx_tx_fallback_mode(dev, SX126X_FALLBACK_STDBY_XOSC); + if (timeout > 0) { + sx126x_set_rx(dev, timeout); + } + else { + sx126x_set_rx(dev, SX126X_RX_SINGLE_MODE); + } + } break; + case SX126X_CHIP_MODE_STBY_RC: + case SX126X_CHIP_MODE_STBY_XOSC: + sx126x_set_standby(dev, state); + break; + default: + break; + } +} + uint32_t sx126x_get_channel(const sx126x_t *dev) { DEBUG("[sx126x]: sx126x_get_radio_status \n"); diff --git a/drivers/sx126x/sx126x_netdev.c b/drivers/sx126x/sx126x_netdev.c index 6719a80060..a7b1ba7f08 100644 --- a/drivers/sx126x/sx126x_netdev.c +++ b/drivers/sx126x/sx126x_netdev.c @@ -206,16 +206,11 @@ static void _isr(netdev_t *netdev) static int _get_state(sx126x_t *dev, void *val) { - sx126x_chip_status_t radio_status; - - sx126x_get_status(dev, &radio_status); - netopt_state_t state = NETOPT_STATE_OFF; - - switch (radio_status.chip_mode) { - case SX126X_CHIP_MODE_RFU: - case SX126X_CHIP_MODE_STBY_RC: - case SX126X_CHIP_MODE_STBY_XOSC: - state = NETOPT_STATE_STANDBY; + netopt_state_t state; + sx126x_chip_modes_t mode = sx126x_get_state(dev); + switch (mode) { + case SX126X_CHIP_MODE_FS: + state = NETOPT_STATE_IDLE; break; case SX126X_CHIP_MODE_TX: @@ -227,6 +222,7 @@ static int _get_state(sx126x_t *dev, void *val) break; default: + state = NETOPT_STATE_STANDBY; break; } memcpy(val, &state, sizeof(netopt_state_t)); @@ -312,7 +308,7 @@ static int _set_state(sx126x_t *dev, netopt_state_t state) switch (state) { case NETOPT_STATE_STANDBY: DEBUG("[sx126x] netdev: set NETOPT_STATE_STANDBY state\n"); - sx126x_set_standby(dev, SX126X_CHIP_MODE_STBY_XOSC); + sx126x_set_state(dev, SX126X_CHIP_MODE_STBY_XOSC); break; case NETOPT_STATE_IDLE: @@ -324,14 +320,7 @@ static int _set_state(sx126x_t *dev, netopt_state_t state) dev->params->set_rf_mode(dev, SX126X_RF_MODE_RX); } #endif - sx126x_cfg_rx_boosted(dev, true); - int _timeout = (sx126x_symbol_to_msec(dev, dev->rx_timeout)); - if (_timeout != 0) { - sx126x_set_rx(dev, _timeout); - } - else { - sx126x_set_rx(dev, SX126X_RX_SINGLE_MODE); - } + sx126x_set_state(dev, SX126X_CHIP_MODE_RX); break; case NETOPT_STATE_TX: @@ -341,7 +330,7 @@ static int _set_state(sx126x_t *dev, netopt_state_t state) dev->params->set_rf_mode(dev, dev->params->tx_pa_mode); } #endif - sx126x_set_tx(dev, 0); + sx126x_set_state(dev, SX126X_CHIP_MODE_TX); break; case NETOPT_STATE_RESET: From 0c624bad1f6ea693dfad622f649768ff40e09ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20H=C3=BC=C3=9Fler?= Date: Mon, 5 May 2025 17:52:37 +0200 Subject: [PATCH 2/2] drivers/sx126x: image calibration after frequency Also changes standby configuration after image calibratin, else TCXO switches off afterwards --- drivers/sx126x/sx126x.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/sx126x/sx126x.c b/drivers/sx126x/sx126x.c index c7b71d2d18..baeee8d6e3 100644 --- a/drivers/sx126x/sx126x.c +++ b/drivers/sx126x/sx126x.c @@ -22,6 +22,7 @@ #include "sx126x_netdev.h" +#include "macros/units.h" #include "net/lora.h" #include "periph/spi.h" @@ -465,11 +466,46 @@ uint32_t sx126x_get_channel(const sx126x_t *dev) return dev->channel; } +/* 9.2.1 Image Calibration for Specific Frequency Bands */ +static void _cal_img(sx126x_t *dev, uint32_t freq) +{ + sx126x_chip_modes_t state = sx126x_get_state(dev); + /* don't know what to do with frequencies that don't fit in the intervals from the datasheet */ + if (freq >= MHZ(902) && freq <= MHZ(928)) { + /* 902 - 928 MHz band and anything upper */ + sx126x_cal_img_in_mhz(dev, 902, 928); + } + else if (freq >= MHZ(863) && freq <= MHZ(870)) { + /* 863 - 870 MHz band */ + sx126x_cal_img_in_mhz(dev, 863, 870); + } + else if (freq >= MHZ(779) && freq <= MHZ(787)) { + /* 779 - 787 MHz band */ + sx126x_cal_img_in_mhz(dev, 779, 787); + } + else if (freq >= MHZ(470) && freq <= MHZ(510)) { + /* 470 - 510 MHz band */ + sx126x_cal_img_in_mhz(dev, 470, 510); + } + else if (freq >= MHZ(430) && freq <= MHZ(440)) { + /* 430 - 440 MHz band and anything lower */ + sx126x_cal_img_in_mhz(dev, 430, 440); + } + else { + /* Contact your Semtech representative for the other optimal calibration settings + outside of the given frequency bands. */ + } + /* Image calibration sets the chip mode back to STBY_RC */ + /* When using DIO3, TCXO switches off. */ + sx126x_set_state(dev, state); +} + void sx126x_set_channel(sx126x_t *dev, uint32_t freq) { DEBUG("[sx126x]: sx126x_set_channel %" PRIu32 "Hz \n", freq); dev->channel = freq; sx126x_set_rf_freq(dev, dev->channel); + _cal_img(dev, freq); } uint8_t sx126x_get_bandwidth(const sx126x_t *dev)