Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 65 additions & 4 deletions drivers/lora/loramac_node/sx126x.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,15 @@ static const struct sx126x_config dev_config = {
#if HAVE_GPIO_RX_ENABLE
.rx_enable = GPIO_DT_SPEC_INST_GET(0, rx_enable_gpios),
#endif
#if HAVE_GPIO_FE_CTRL
.fe_ctrl1_enable = GPIO_DT_SPEC_INST_GET(0, fe_ctrl1_enable_gpios),
.fe_ctrl2_enable = GPIO_DT_SPEC_INST_GET(0, fe_ctrl2_enable_gpios),
.fe_ctrl3_enable = GPIO_DT_SPEC_INST_GET(0, fe_ctrl3_enable_gpios),
#endif

};


static struct sx126x_data dev_data;

void SX126xWaitOnBusy(void);
Expand Down Expand Up @@ -253,29 +260,57 @@ void SX126xAntSwOff(void)
#endif
}

#if HAVE_GPIO_TX_ENABLE
static void sx126x_set_tx_enable(int value)
{
#if HAVE_GPIO_TX_ENABLE
gpio_pin_set_dt(&dev_config.tx_enable, value);
#endif
}
#endif

#if HAVE_GPIO_RX_ENABLE
static void sx126x_set_rx_enable(int value)
{
#if HAVE_GPIO_RX_ENABLE
gpio_pin_set_dt(&dev_config.rx_enable, value);
}
#endif


static void sx126x_set_fe_ctrl(int ctrl1, int ctrl2, int ctrl3)
{
#if HAVE_GPIO_FE_CTRL
gpio_pin_set_dt(&dev_config.fe_ctrl1_enable, ctrl1);
gpio_pin_set_dt(&dev_config.fe_ctrl2_enable, ctrl2);
gpio_pin_set_dt(&dev_config.fe_ctrl3_enable, ctrl3);
#endif
}


RadioOperatingModes_t SX126xGetOperatingMode(void)
{
return dev_data.mode;
}

#if HAVE_GPIO_FE_CTRL
static const enum {
RFO_LP,
RFO_HP,
} pa_output = DT_INST_STRING_UPPER_TOKEN(0, power_amplifier_output);
#endif

#define LORA_NODE DT_NODELABEL(lora)


void SX126xSetOperatingMode(RadioOperatingModes_t mode)
{
LOG_DBG("SetOperatingMode: %s (%i)", sx126x_mode_name(mode), mode);

#if HAVE_GPIO_FE_CTRL
const int off_fe_ctrl_lines[] = DT_PROP(LORA_NODE, off_fe_ctrl_lines);
const int rx_fe_ctrl_lines[] = DT_PROP(LORA_NODE, rx_fe_ctrl_lines);
const int txhp_fe_ctrl_lines[] = DT_PROP(LORA_NODE, txhp_fe_ctrl_lines);
const int txlp_fe_ctrl_lines[] = DT_PROP(LORA_NODE, txlp_fe_ctrl_lines);
#endif

dev_data.mode = mode;

/* To avoid inadvertently putting the RF switch in an
Expand All @@ -284,24 +319,43 @@ void SX126xSetOperatingMode(RadioOperatingModes_t mode)
*/
switch (mode) {
case MODE_TX:
#if HAVE_GPIO_TX_ENABLE
sx126x_set_rx_enable(0);
sx126x_set_tx_enable(1);
#endif
#if HAVE_GPIO_FE_CTRL
if (pa_output == RFO_LP) {
sx126x_set_fe_ctrl(txlp_fe_ctrl_lines[0], txlp_fe_ctrl_lines[1], txlp_fe_ctrl_lines[2]);
} else {
sx126x_set_fe_ctrl(txhp_fe_ctrl_lines[0], txhp_fe_ctrl_lines[1], txhp_fe_ctrl_lines[2]);
}
#endif
break;

case MODE_RX:
case MODE_RX_DC:
case MODE_CAD:
#if HAVE_GPIO_TX_ENABLE
sx126x_set_tx_enable(0);
sx126x_set_rx_enable(1);
#endif
#if HAVE_GPIO_FE_CTRL
sx126x_set_fe_ctrl(rx_fe_ctrl_lines[0], rx_fe_ctrl_lines[1], rx_fe_ctrl_lines[2]);
#endif
break;

case MODE_SLEEP:
/* Additionally disable the DIO1 interrupt to save power */
sx126x_dio1_irq_disable(&dev_data);
__fallthrough;
default:
#if HAVE_GPIO_TX_ENABLE
sx126x_set_rx_enable(0);
sx126x_set_tx_enable(0);
#endif
#if HAVE_GPIO_FE_CTRL
sx126x_set_fe_ctrl(off_fe_ctrl_lines[0], off_fe_ctrl_lines[1], off_fe_ctrl_lines[2]);
#endif
break;
}
}
Expand Down Expand Up @@ -437,7 +491,14 @@ static int sx126x_lora_init(const struct device *dev)

if (sx12xx_configure_pin(antenna_enable, GPIO_OUTPUT_INACTIVE) ||
sx12xx_configure_pin(rx_enable, GPIO_OUTPUT_INACTIVE) ||
sx12xx_configure_pin(tx_enable, GPIO_OUTPUT_INACTIVE)) {
sx12xx_configure_pin(tx_enable, GPIO_OUTPUT_INACTIVE)
#if HAVE_GPIO_FE_CTRL
|| sx12xx_configure_pin(fe_ctrl1_enable, GPIO_OUTPUT_INACTIVE)
|| sx12xx_configure_pin(fe_ctrl2_enable, GPIO_OUTPUT_INACTIVE)
|| sx12xx_configure_pin(fe_ctrl3_enable, GPIO_OUTPUT_INACTIVE)
#endif
)
{
return -EIO;
}

Expand Down
7 changes: 7 additions & 0 deletions drivers/lora/loramac_node/sx126x_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
DT_INST_NODE_HAS_PROP(0, antenna_enable_gpios)
#define HAVE_GPIO_TX_ENABLE DT_INST_NODE_HAS_PROP(0, tx_enable_gpios)
#define HAVE_GPIO_RX_ENABLE DT_INST_NODE_HAS_PROP(0, rx_enable_gpios)
#define HAVE_GPIO_FE_CTRL (DT_INST_NODE_HAS_PROP(0, fe_ctrl1_enable_gpios) && !DT_INST_NODE_HAS_PROP(0, tx_enable_gpios))

struct sx126x_config {
struct spi_dt_spec bus;
Expand All @@ -46,6 +47,12 @@ struct sx126x_config {
#if HAVE_GPIO_RX_ENABLE
struct gpio_dt_spec rx_enable;
#endif
#if HAVE_GPIO_FE_CTRL
struct gpio_dt_spec fe_ctrl3_enable;
struct gpio_dt_spec fe_ctrl2_enable;
struct gpio_dt_spec fe_ctrl1_enable;
#endif

};

struct sx126x_data {
Expand Down
3 changes: 3 additions & 0 deletions drivers/lora/loramac_node/sx127x.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/lora.h>
#include <zephyr/drivers/lora_rssi.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/kernel.h>

Expand Down Expand Up @@ -88,6 +89,7 @@ LOG_MODULE_REGISTER(sx127x, CONFIG_LORA_LOG_LEVEL);
#define SX127xSetPublicNetwork SX1276SetPublicNetwork
#define SX127xGetWakeupTime SX1276GetWakeupTime
#define SX127xSetTxContinuousWave SX1276SetTxContinuousWave
#define SX127xReadRssi SX1276ReadRssi

#else
#error No SX127x instance in device tree.
Expand Down Expand Up @@ -548,6 +550,7 @@ const struct Radio_s Radio = {
.RxBoosted = NULL,
.SetRxDutyCycle = NULL,
.SetTxContinuousWave = SX127xSetTxContinuousWave,
.Rssi = SX127xReadRssi,
};

static int sx127x_antenna_configure(void)
Expand Down
78 changes: 78 additions & 0 deletions drivers/lora/loramac_node/sx12xx_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/lora.h>
#include <zephyr/drivers/lora_rssi.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/kernel.h>
Expand Down Expand Up @@ -102,6 +103,12 @@ static void sx12xx_ev_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
{
struct k_poll_signal *sig = dev_data.operation_done;

if (!dev_data.async_rx_cb && !sig) {
LOG_WRN("RxDone event with no registered consumer "
"(modem_usage=%d)",
(int)atomic_get(&dev_data.modem_usage));
}

/* Receiving in asynchronous mode */
if (dev_data.async_rx_cb) {
/* Start receiving again */
Expand Down Expand Up @@ -311,6 +318,7 @@ int sx12xx_lora_recv_async(const struct device *dev, lora_recv_cb cb, void *user
{
/* Cancel ongoing reception */
if (cb == NULL) {
dev_data.async_rx_cb = NULL;
if (!modem_release(&dev_data)) {
/* Not receiving or already being stopped */
return -EINVAL;
Expand Down Expand Up @@ -379,6 +387,76 @@ int sx12xx_lora_test_cw(const struct device *dev, uint32_t frequency,
return 0;
}

/**
* @brief Get RF noise floor measurement
*
* @param dev Device pointer
* @return int16_t Noise floor value in dBm
*/
int16_t sx12xx_lora_get_noise_floor(const struct device *dev)
{
int16_t noise_floor = NOISE_FLOOR_DEFAULT_VALUE;
int32_t noise_floor_sum = 0;
int valid_measurements = 0;

/* Ensure available, released after measurement */
if (!modem_acquire(&dev_data)) {
LOG_ERR("Radio is busy");
return NOISE_FLOOR_DEFAULT_VALUE;
}

LOG_DBG("Starting noise floor measurement using Radio.Rssi()");

/* Configure radio for optimal noise floor measurement */
Radio.SetModem(MODEM_FSK);

/* Set radio to continuous reception */
Radio.Rx(0);

/* Take multiple measurements to get a stable reading */
for (int i = 0; i < 5; i++) {
/* Give radio time to settle before each measurement */
k_sleep(K_MSEC(20));

/* Get noise floor directly from the radio API */
int16_t current_noise_floor = Radio.Rssi(MODEM_FSK);
LOG_DBG("Noise floor measurement %d: %d dBm", i, current_noise_floor);

/* Filter out clearly invalid measurements */
if (current_noise_floor < 0) { /* Only accept negative values as valid */
noise_floor_sum += current_noise_floor;
valid_measurements++;
} else {
LOG_WRN("Ignoring invalid noise floor: %d dBm", current_noise_floor);
}
}

/* Calculate average */
if (valid_measurements > 0) {
noise_floor = noise_floor_sum / valid_measurements;
LOG_DBG("Average noise floor: %d dBm from %d readings", noise_floor, valid_measurements);
} else {
LOG_WRN("No valid noise floor measurements obtained");
}

/* Restore original radio state - no need to sleep before this */
Radio.Sleep();

/* Release modem when done */
modem_release(&dev_data);

return noise_floor;
}

int16_t lora_get_noise_floor(const struct device *dev)
{
if (!dev) {
return NOISE_FLOOR_DEFAULT_VALUE;
}

return sx12xx_lora_get_noise_floor(dev);
}

int sx12xx_init(const struct device *dev)
{
atomic_set(&dev_data.modem_usage, 0);
Expand Down
2 changes: 2 additions & 0 deletions drivers/lora/loramac_node/sx12xx_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ int sx12xx_lora_test_cw(const struct device *dev, uint32_t frequency,
int8_t tx_power,
uint16_t duration);

int16_t sx12xx_lora_get_noise_floor(const struct device *dev);

int sx12xx_init(const struct device *dev);

#endif /* ZEPHYR_DRIVERS_SX12XX_COMMON_H_ */
Loading
Loading