Skip to content

Commit

Permalink
drivers/sx126x: add support for Dio2 and Dio3
Browse files Browse the repository at this point in the history
  • Loading branch information
fabian18 committed Mar 5, 2025
1 parent 4de386e commit 526acc3
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 24 deletions.
54 changes: 54 additions & 0 deletions drivers/include/sx126x.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,33 @@ typedef enum {
SX126X_STATE_CAD,
} sx126x_state_t;

/**
* @brief Dio2 pin purpose
*/
typedef enum {
SX126X_DIO2_UNUSED, /**< Not used */
SX126X_DIO2_IRQ, /**< IRQ pin */
SX126X_DIO2_RF_SWITCH, /**< RF switch control pin */
} sx126x_dio2_mode_t;

/**
* @brief Dio3 pin purpose
*/
typedef enum {
SX126X_DIO3_UNUSED, /**< Not used */
SX126X_DIO3_IRQ, /**< IRQ pin */
SX126X_DIO3_TCX0, /**< TCXO control pin */
} sx126x_dio3_mode_t;

/**
* @brief Mask of all available interrupts
*/
#define SX126X_IRQ_MASK_ALL (SX126X_IRQ_TX_DONE | SX126X_IRQ_RX_DONE | \
SX126X_IRQ_PREAMBLE_DETECTED | SX126X_IRQ_SYNC_WORD_VALID | \
SX126X_IRQ_HEADER_VALID | SX126X_IRQ_HEADER_ERROR | \
SX126X_IRQ_CRC_ERROR | SX126X_IRQ_CAD_DONE | \
SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_TIMEOUT)

/**
* @brief Device initialization parameters
*/
Expand All @@ -101,6 +128,33 @@ typedef struct {
gpio_t reset_pin; /**< Reset pin */
gpio_t busy_pin; /**< Busy pin */
gpio_t dio1_pin; /**< Dio1 pin */
uint16_t dio1_irq_mask; /**< IRQ mask for IRQs to route to Dio1 */
#if IS_USED(MODULE_SX126X_DIO2)
sx126x_dio2_mode_t dio2_mode; /**< Dio2 purpose */
union {
struct {
gpio_t dio2_pin; /**< Dio2 IRQ pin if purpose is SX126X_DIO2_IRQ */
uint16_t dio2_irq_mask; /**< IRQ mask for IRQs to route to Dio3 */
};
struct {
gpio_t rf_switch_pin; /**< RF switch control pin if purpose is SX126X_DIO2_RF_SWITCH */
};
} u_dio2_arg;
#endif
#if IS_USED(MODULE_SX126X_DIO3)
sx126x_dio3_mode_t dio3_mode; /**< Dio3 purpose */
union {
struct {
gpio_t dio3_pin; /**< Dio3 IRQ pin if purpose is SX126X_DIO3_IRQ */
uint16_t dio3_irq_mask; /**< IRQ mask for IRQs to route to Dio3 */
};
struct {
unsigned tcxo_volt :8; /**< TCXO voltage (see sx126x_tcxo_ctrl_voltages_t)*/
unsigned tcx0_timeout :24; /**< TCXO timeout to wait for 32MHz coming from TXC0,
Delay duration = Delay(23:0) * 15.625 μs */
};
} u_dio3_arg;
#endif
sx126x_reg_mod_t regulator; /**< Power regulator mode */
sx126x_type_t type; /**< Variant of sx126x */
#if IS_USED(MODULE_SX126X_RF_SWITCH)
Expand Down
2 changes: 2 additions & 0 deletions drivers/sx126x/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ PSEUDOMODULES += sx126x_stm32wl
# include RF switch implemented in the board for use with sx126x
PSEUDOMODULES += sx126x_rf_switch
PSEUDOMODULES += sx126x_ieee802154
PSEUDOMODULES += sx126x_dio2
PSEUDOMODULES += sx126x_dio3

USEMODULE_INCLUDES_sx126x := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_sx126x)
80 changes: 70 additions & 10 deletions drivers/sx126x/include/sx126x_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ extern "C" {
# define SX126X_PARAM_DIO1 GPIO_PIN(1, 4) /* D5 */
#endif

#ifndef SX126X_PARAM_DIO1_IRQ_MASK
# define SX126X_PARAM_DIO1_IRQ_MASK SX126X_IRQ_MASK_ALL
#endif

#ifndef SX126X_PARAM_REGULATOR
# define SX126X_PARAM_REGULATOR SX126X_REG_MODE_DCDC
#endif
Expand All @@ -77,6 +81,40 @@ extern "C" {
# define SX126X_PARAM_TX_PA_MODE SX126X_RF_MODE_TX_LPA
#endif

#ifndef SX126X_PARAM_DIO2_MODE
# define SX126X_PARAM_DIO2_MODE SX126X_DIO2_IRQ
#endif

#ifndef SX126X_PARAM_DIO2
# define SX126X_PARAM_DIO2 GPIO_UNDEF
#endif

#ifndef SX126X_PARAM_DIO2_IRQ_MASK
# define SX126X_PARAM_DIO2_IRQ_MASK SX126X_IRQ_MASK_ALL
#endif

#ifndef SX126X_PARAM_DIO2_ARG
# define SX126X_PARAM_DIO2_ARG { .dio2_pin = SX126X_PARAM_DIO2, \
.dio2_irq_mask = SX126X_PARAM_DIO2_IRQ_MASK }
#endif

#ifndef SX126X_PARAM_DIO3_MODE
# define SX126X_PARAM_DIO3_MODE SX126X_DIO3_IRQ
#endif

#ifndef SX126X_PARAM_DIO3
# define SX126X_PARAM_DIO3 GPIO_UNDEF
#endif

#ifndef SX126X_PARAM_DIO3_IRQ_MASK
# define SX126X_PARAM_DIO3_IRQ_MASK SX126X_IRQ_MASK_ALL
#endif

#ifndef SX126X_PARAM_DIO3_ARG
# define SX126X_PARAM_DIO3_ARG { .dio3_pin = SX126X_PARAM_DIO3, \
.dio3_irq_mask = SX126X_PARAM_DIO3_IRQ_MASK }
#endif

#ifndef SX126X_PARAM_TYPE
# if IS_USED(MODULE_SX1261)
# define SX126X_PARAM_TYPE SX126X_TYPE_SX1261
Expand All @@ -95,22 +133,44 @@ extern "C" {

#if IS_USED(MODULE_SX126X_RF_SWITCH)
# define SX126X_SET_RF_MODE .set_rf_mode = SX126X_PARAM_SET_RF_MODE_CB,
# define SX126X_TX_PA_MODE .tx_pa_mode = SX126X_PARAM_TX_PA_MODE
# define SX126X_TX_PA_MODE .tx_pa_mode = SX126X_PARAM_TX_PA_MODE,
#else
# define SX126X_SET_RF_MODE
# define SX126X_TX_PA_MODE
#endif

#if IS_USED(MODULE_SX126X_DIO2)
#define SX126X_DIO2_MODE .dio2_mode = SX126X_PARAM_DIO2_MODE,
#define SX126X_DIO2_PIN .u_dio2_arg = SX126X_PARAM_DIO2_ARG,
#else
#define SX126X_DIO2_MODE
#define SX126X_DIO2_PIN
#endif

#if IS_USED(MODULE_SX126X_DIO3)
#define SX126X_DIO3_MODE .dio3_mode = SX126X_PARAM_DIO3_MODE,
#define SX126X_DIO3_PIN .u_dio3_arg = SX126X_PARAM_DIO3_ARG,
#else
#define SX126X_DIO3_MODE
#define SX126X_DIO3_PIN
#endif

#ifndef SX126X_PARAMS
# define SX126X_PARAMS { .spi = SX126X_PARAM_SPI, \
.nss_pin = SX126X_PARAM_SPI_NSS, \
.reset_pin = SX126X_PARAM_RESET, \
.busy_pin = SX126X_PARAM_BUSY, \
.dio1_pin = SX126X_PARAM_DIO1, \
.type = SX126X_PARAM_TYPE, \
.regulator = SX126X_PARAM_REGULATOR, \
SX126X_SET_RF_MODE \
SX126X_TX_PA_MODE}
# define SX126X_PARAMS { .spi = SX126X_PARAM_SPI, \
.nss_pin = SX126X_PARAM_SPI_NSS, \
.reset_pin = SX126X_PARAM_RESET, \
.busy_pin = SX126X_PARAM_BUSY, \
.dio1_pin = SX126X_PARAM_DIO1, \
.dio1_irq_mask = SX126X_PARAM_DIO1_IRQ_MASK, \
.type = SX126X_PARAM_TYPE, \
.regulator = SX126X_PARAM_REGULATOR, \
SX126X_SET_RF_MODE \
SX126X_TX_PA_MODE \
SX126X_DIO2_MODE \
SX126X_DIO2_PIN \
SX126X_DIO3_MODE \
SX126X_DIO3_PIN \
}
#endif

/**@}*/
Expand Down
92 changes: 78 additions & 14 deletions drivers/sx126x/sx126x.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include "sx126x.h"
#include "sx126x_driver.h"
#include "sx126x_driver_regs.h"
#include "sx126x_params.h"
#include "sx126x_internal.h"

Expand Down Expand Up @@ -233,20 +234,83 @@ int sx126x_init(sx126x_t *dev)
sx126x_init_default_config(dev);

/* Configure available IRQs */
const uint16_t irq_mask = (
SX126X_IRQ_TX_DONE |
SX126X_IRQ_RX_DONE |
SX126X_IRQ_PREAMBLE_DETECTED |
SX126X_IRQ_SYNC_WORD_VALID |
SX126X_IRQ_HEADER_VALID |
SX126X_IRQ_HEADER_ERROR |
SX126X_IRQ_CRC_ERROR |
SX126X_IRQ_CAD_DONE |
SX126X_IRQ_CAD_DETECTED |
SX126X_IRQ_TIMEOUT
);

sx126x_set_dio_irq_params(dev, irq_mask, irq_mask, 0, 0);
uint16_t irq_mask_dio1 = dev->params->dio1_irq_mask;
uint16_t irq_mask_dio2 = 0;
uint16_t irq_mask_dio3 = 0;

#if IS_USED(MODULE_SX126X_DIO2)
if (dev->params->dio2_mode == SX126X_DIO2_IRQ) {
if (gpio_is_valid(dev->params->u_dio2_arg.dio2_pin)) {
res = gpio_init_int(dev->params->u_dio2_arg.dio2_pin, GPIO_IN, GPIO_RISING,
dev->event_cb, dev->event_arg);
if (res < 0) {
DEBUG("[sx126x] error: failed to initialize DIO2 pin\n");
return res;
}
irq_mask_dio2 = dev->params->u_dio2_arg.dio2_irq_mask;
}
}
else if (dev->params->dio2_mode == SX126X_DIO2_RF_SWITCH) {
if (gpio_is_valid(dev->params->u_dio2_arg.rf_switch_pin)) {
res = gpio_init(dev->params->u_dio2_arg.rf_switch_pin, GPIO_IN);
if (res < 0) {
DEBUG("[sx126x] error: failed to initialize RF switch pin\n");
return res;
}
}
sx126x_set_dio2_as_rf_sw_ctrl(dev, true);
}
#endif
#if IS_USED(MODULE_SX126X_DIO3)
if (dev->params->dio3_mode == SX126X_DIO3_IRQ) {
if (gpio_is_valid(dev->params->u_dio3_arg.dio3_pin)) {
res = gpio_init_int(dev->params->u_dio3_arg.dio3_pin, GPIO_IN, GPIO_RISING,
dev->event_cb, dev->event_arg);
if (res < 0) {
DEBUG("[sx126x] error: failed to initialize DIO3 pin\n");
return res;
}
irq_mask_dio3 = dev->params->u_dio3_arg.dio3_irq_mask;
}
}
else if (dev->params->dio3_mode == SX126X_DIO3_TCX0) {
sx126x_set_dio3_as_tcxo_ctrl(dev, dev->params->u_dio3_arg.tcxo_volt,
dev->params->u_dio3_arg.tcx0_timeout);

/* Once the command SetDIO3AsTCXOCtrl(...) is sent to the device,
the register controlling the internal cap on XTA will be automatically
changed to 0x2F (33.4 pF) to filter any spurious which could occur
and be propagated to the PLL.- Verify that. */
uint8_t trimming_capacitor_values[2] = { 0 };
sx126x_read_register(dev, SX126X_REG_XTATRIM,
trimming_capacitor_values,
sizeof(trimming_capacitor_values));
/* 11.3 pF + x * 0.47pF = 33.4pF | x = 0x2f*/
if (trimming_capacitor_values[0] != 0x2f) {
DEBUG("[sx126x] warning: failed to set TCXO control: SX126X_REG_XTATRIM=%02x\n",
trimming_capacitor_values[0]);
}
DEBUG("[sx126x] XTA capacitor ~ %upF\n",
(unsigned)(0.5f + (11.3f + trimming_capacitor_values[0] * 0.47f)));
DEBUG("[sx126x] XTB capacitor ~ %upF\n",
(unsigned)(0.5f + (11.3f + trimming_capacitor_values[1] * 0.47f)));

/* When the 32 MHz clock is coming from a TCXO, the calibration will fail
and the user should request a complete calibration after calling the function
SetDIO3AsTcxoCtrl(...). */
sx126x_cal(dev, SX126X_CAL_ALL);
}
#endif
/* The user can specify the use of DC-DC by using the command SetRegulatorMode(...).
This operation must be carried out in STDBY_RC mode only.*/
sx126x_set_reg_mode(dev, dev->params->regulator);

/* Initialize radio with the default parameters */
sx126x_init_default_config(dev);

sx126x_set_standby(dev, SX126X_STANDBY_CFG_XOSC);

sx126x_set_dio_irq_params(dev, SX126X_IRQ_MASK_ALL, irq_mask_dio1, irq_mask_dio2, irq_mask_dio3);

if (IS_ACTIVE(ENABLE_DEBUG)) {
sx126x_pkt_type_t pkt_type;
Expand Down

0 comments on commit 526acc3

Please sign in to comment.