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 4b28a2f8e0..2e26dc4365 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" @@ -434,17 +435,84 @@ 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"); 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) 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: