You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
639 lines
16 KiB
639 lines
16 KiB
/* |
|
* Copyright (c) 2019 Manivannan Sadhasivam |
|
* Copyright (c) 2020 Grinn |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#include <zephyr/drivers/gpio.h> |
|
#include <zephyr/drivers/lora.h> |
|
#include <zephyr/drivers/spi.h> |
|
#include <zephyr/kernel.h> |
|
|
|
#include "sx12xx_common.h" |
|
|
|
#include <zephyr/logging/log.h> |
|
LOG_MODULE_REGISTER(sx127x, CONFIG_LORA_LOG_LEVEL); |
|
|
|
#if DT_HAS_COMPAT_STATUS_OKAY(semtech_sx1272) |
|
|
|
#include <sx1272/sx1272.h> |
|
|
|
#define DT_DRV_COMPAT semtech_sx1272 |
|
|
|
#define SX127xCheckRfFrequency SX1272CheckRfFrequency |
|
#define SX127xGetBoardTcxoWakeupTime SX1272GetBoardTcxoWakeupTime |
|
#define SX127xSetAntSwLowPower SX1272SetAntSwLowPower |
|
#define SX127xSetBoardTcxo SX1272SetBoardTcxo |
|
#define SX127xSetAntSw SX1272SetAntSw |
|
#define SX127xReset SX1272Reset |
|
#define SX127xIoIrqInit SX1272IoIrqInit |
|
#define SX127xWriteBuffer SX1272WriteBuffer |
|
#define SX127xReadBuffer SX1272ReadBuffer |
|
#define SX127xSetRfTxPower SX1272SetRfTxPower |
|
#define SX127xGetDio1PinState SX1272GetDio1PinState |
|
#define SX127xInit SX1272Init |
|
#define SX127xGetStatus SX1272GetStatus |
|
#define SX127xSetModem SX1272SetModem |
|
#define SX127xSetChannel SX1272SetChannel |
|
#define SX127xIsChannelFree SX1272IsChannelFree |
|
#define SX127xRandom SX1272Random |
|
#define SX127xSetRxConfig SX1272SetRxConfig |
|
#define SX127xSetTxConfig SX1272SetTxConfig |
|
#define SX127xGetTimeOnAir SX1272GetTimeOnAir |
|
#define SX127xSend SX1272Send |
|
#define SX127xSetSleep SX1272SetSleep |
|
#define SX127xSetStby SX1272SetStby |
|
#define SX127xSetRx SX1272SetRx |
|
#define SX127xWrite SX1272Write |
|
#define SX127xRead SX1272Read |
|
#define SX127xSetMaxPayloadLength SX1272SetMaxPayloadLength |
|
#define SX127xSetPublicNetwork SX1272SetPublicNetwork |
|
#define SX127xGetWakeupTime SX1272GetWakeupTime |
|
#define SX127xSetTxContinuousWave SX1272SetTxContinuousWave |
|
|
|
#elif DT_HAS_COMPAT_STATUS_OKAY(semtech_sx1276) |
|
|
|
#include <sx1276/sx1276.h> |
|
|
|
#define DT_DRV_COMPAT semtech_sx1276 |
|
|
|
#define SX127xCheckRfFrequency SX1276CheckRfFrequency |
|
#define SX127xGetBoardTcxoWakeupTime SX1276GetBoardTcxoWakeupTime |
|
#define SX127xSetAntSwLowPower SX1276SetAntSwLowPower |
|
#define SX127xSetBoardTcxo SX1276SetBoardTcxo |
|
#define SX127xSetAntSw SX1276SetAntSw |
|
#define SX127xReset SX1276Reset |
|
#define SX127xIoIrqInit SX1276IoIrqInit |
|
#define SX127xWriteBuffer SX1276WriteBuffer |
|
#define SX127xReadBuffer SX1276ReadBuffer |
|
#define SX127xSetRfTxPower SX1276SetRfTxPower |
|
#define SX127xGetDio1PinState SX1276GetDio1PinState |
|
#define SX127xInit SX1276Init |
|
#define SX127xGetStatus SX1276GetStatus |
|
#define SX127xSetModem SX1276SetModem |
|
#define SX127xSetChannel SX1276SetChannel |
|
#define SX127xIsChannelFree SX1276IsChannelFree |
|
#define SX127xRandom SX1276Random |
|
#define SX127xSetRxConfig SX1276SetRxConfig |
|
#define SX127xSetTxConfig SX1276SetTxConfig |
|
#define SX127xGetTimeOnAir SX1276GetTimeOnAir |
|
#define SX127xSend SX1276Send |
|
#define SX127xSetSleep SX1276SetSleep |
|
#define SX127xSetStby SX1276SetStby |
|
#define SX127xSetRx SX1276SetRx |
|
#define SX127xWrite SX1276Write |
|
#define SX127xRead SX1276Read |
|
#define SX127xSetMaxPayloadLength SX1276SetMaxPayloadLength |
|
#define SX127xSetPublicNetwork SX1276SetPublicNetwork |
|
#define SX127xGetWakeupTime SX1276GetWakeupTime |
|
#define SX127xSetTxContinuousWave SX1276SetTxContinuousWave |
|
|
|
#else |
|
#error No SX127x instance in device tree. |
|
#endif |
|
|
|
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(semtech_sx1272) + |
|
DT_NUM_INST_STATUS_OKAY(semtech_sx1276) <= 1, |
|
"Multiple SX127x instances in DT"); |
|
|
|
#if DT_INST_NODE_HAS_PROP(0, tcxo_power_startup_delay_ms) |
|
#define TCXO_POWER_STARTUP_DELAY_MS \ |
|
DT_INST_PROP(0, tcxo_power_startup_delay_ms) |
|
#else |
|
#define TCXO_POWER_STARTUP_DELAY_MS 0 |
|
#endif |
|
|
|
/* |
|
* Those macros must be in sync with 'power-amplifier-output' dts property. |
|
*/ |
|
#define SX127X_PA_RFO 0 |
|
#define SX127X_PA_BOOST 1 |
|
|
|
#if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) && \ |
|
DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios) |
|
#define SX127X_PA_OUTPUT(power) \ |
|
((power) > 14 ? SX127X_PA_BOOST : SX127X_PA_RFO) |
|
#elif DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) |
|
#define SX127X_PA_OUTPUT(power) SX127X_PA_RFO |
|
#elif DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios) |
|
#define SX127X_PA_OUTPUT(power) SX127X_PA_BOOST |
|
#elif DT_INST_NODE_HAS_PROP(0, power_amplifier_output) |
|
#define SX127X_PA_OUTPUT(power) \ |
|
DT_INST_ENUM_IDX(0, power_amplifier_output) |
|
#else |
|
BUILD_ASSERT(0, "None of rfo-enable-gpios, pa-boost-enable-gpios and " |
|
"power-amplifier-output has been specified. " |
|
"Look at semtech,sx127x-base.yaml to fix that."); |
|
#endif |
|
|
|
#define SX127X_PADAC_20DBM_ON (RF_PADAC_20DBM_ON) |
|
#define SX127X_PADAC_20DBM_OFF (RF_PADAC_20DBM_OFF) |
|
#define SX127X_PADAC_20DBM_MASK (~RF_PADAC_20DBM_MASK) |
|
|
|
#define SX127X_PACONFIG_PASELECT_PABOOST (RF_PACONFIG_PASELECT_PABOOST) |
|
#define SX127X_PACONFIG_OUTPUTPOWER_MASK (~RF_PACONFIG_OUTPUTPOWER_MASK) |
|
|
|
#ifdef RF_PACONFIG_MAX_POWER_MASK |
|
#define SX127X_PACONFIG_MAX_POWER_SHIFT 4 |
|
#endif |
|
|
|
extern DioIrqHandler *DioIrq[]; |
|
|
|
/* Helper macro that UTIL_LISTIFY can use and produces an element with comma */ |
|
#define SX127X_DIO_GPIO_LEN(inst) \ |
|
DT_INST_PROP_LEN(inst, dio_gpios) |
|
|
|
#define SX127X_DIO_GPIO_ELEM(idx, inst) \ |
|
GPIO_DT_SPEC_INST_GET_BY_IDX(inst, dio_gpios, idx) |
|
|
|
#define SX127X_DIO_GPIO_INIT(n) \ |
|
LISTIFY(SX127X_DIO_GPIO_LEN(n), SX127X_DIO_GPIO_ELEM, (,), n) |
|
|
|
static const struct gpio_dt_spec sx127x_dios[] = { SX127X_DIO_GPIO_INIT(0) }; |
|
|
|
#define SX127X_MAX_DIO ARRAY_SIZE(sx127x_dios) |
|
|
|
struct sx127x_config { |
|
struct spi_dt_spec bus; |
|
struct gpio_dt_spec reset; |
|
#if DT_INST_NODE_HAS_PROP(0, antenna_enable_gpios) |
|
struct gpio_dt_spec antenna_enable; |
|
#endif |
|
#if DT_INST_NODE_HAS_PROP(0, rfi_enable_gpios) |
|
struct gpio_dt_spec rfi_enable; |
|
#endif |
|
#if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) |
|
struct gpio_dt_spec rfo_enable; |
|
#endif |
|
#if DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios) |
|
struct gpio_dt_spec pa_boost_enable; |
|
#endif |
|
#if DT_INST_NODE_HAS_PROP(0, tcxo_power_gpios) |
|
struct gpio_dt_spec tcxo_power; |
|
#endif |
|
}; |
|
|
|
static const struct sx127x_config dev_config = { |
|
.bus = SPI_DT_SPEC_INST_GET(0, SPI_WORD_SET(8) | SPI_TRANSFER_MSB, 0), |
|
.reset = GPIO_DT_SPEC_INST_GET(0, reset_gpios), |
|
#if DT_INST_NODE_HAS_PROP(0, antenna_enable_gpios) |
|
.antenna_enable = GPIO_DT_SPEC_INST_GET(0, antenna_enable_gpios), |
|
#endif |
|
#if DT_INST_NODE_HAS_PROP(0, rfi_enable_gpios) |
|
.rfi_enable = GPIO_DT_SPEC_INST_GET(0, rfi_enable_gpios), |
|
#endif |
|
#if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) |
|
.rfo_enable = GPIO_DT_SPEC_INST_GET(0, rfo_enable_gpios), |
|
#endif |
|
#if DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios) |
|
.pa_boost_enable = GPIO_DT_SPEC_INST_GET(0, pa_boost_enable_gpios), |
|
#endif |
|
#if DT_INST_NODE_HAS_PROP(0, tcxo_power_gpios) |
|
.tcxo_power = GPIO_DT_SPEC_INST_GET(0, tcxo_power_gpios), |
|
#endif |
|
}; |
|
|
|
static struct sx127x_data { |
|
#if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) && \ |
|
DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios) |
|
uint8_t tx_power; |
|
#endif |
|
#if DT_INST_NODE_HAS_PROP(0, tcxo_power_gpios) |
|
bool tcxo_power_enabled; |
|
#endif |
|
struct k_work dio_work[SX127X_MAX_DIO]; |
|
} dev_data; |
|
|
|
static int8_t clamp_int8(int8_t x, int8_t min, int8_t max) |
|
{ |
|
if (x < min) { |
|
return min; |
|
} else if (x > max) { |
|
return max; |
|
} else { |
|
return x; |
|
} |
|
} |
|
|
|
bool SX127xCheckRfFrequency(uint32_t frequency) |
|
{ |
|
/* TODO */ |
|
return true; |
|
} |
|
|
|
uint32_t SX127xGetBoardTcxoWakeupTime(void) |
|
{ |
|
return TCXO_POWER_STARTUP_DELAY_MS; |
|
} |
|
|
|
static inline void sx127x_antenna_enable(int val) |
|
{ |
|
#if DT_INST_NODE_HAS_PROP(0, antenna_enable_gpios) |
|
gpio_pin_set_dt(&dev_config.antenna_enable, val); |
|
#endif |
|
} |
|
|
|
static inline void sx127x_rfi_enable(int val) |
|
{ |
|
#if DT_INST_NODE_HAS_PROP(0, rfi_enable_gpios) |
|
gpio_pin_set_dt(&dev_config.rfi_enable, val); |
|
#endif |
|
} |
|
|
|
static inline void sx127x_rfo_enable(int val) |
|
{ |
|
#if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) |
|
gpio_pin_set_dt(&dev_config.rfo_enable, val); |
|
#endif |
|
} |
|
|
|
static inline void sx127x_pa_boost_enable(int val) |
|
{ |
|
#if DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios) |
|
gpio_pin_set_dt(&dev_config.pa_boost_enable, val); |
|
#endif |
|
} |
|
|
|
void SX127xSetAntSwLowPower(bool low_power) |
|
{ |
|
if (low_power) { |
|
/* force inactive (low power) state of all antenna paths */ |
|
sx127x_rfi_enable(0); |
|
sx127x_rfo_enable(0); |
|
sx127x_pa_boost_enable(0); |
|
|
|
sx127x_antenna_enable(0); |
|
} else { |
|
sx127x_antenna_enable(1); |
|
|
|
/* rely on SX127xSetAntSw() to configure proper antenna path */ |
|
} |
|
} |
|
|
|
void SX127xSetBoardTcxo(uint8_t state) |
|
{ |
|
#if DT_INST_NODE_HAS_PROP(0, tcxo_power_gpios) |
|
bool enable = state; |
|
|
|
if (enable == dev_data.tcxo_power_enabled) { |
|
return; |
|
} |
|
|
|
if (enable) { |
|
gpio_pin_set_dt(&dev_config.tcxo_power, 1); |
|
|
|
if (TCXO_POWER_STARTUP_DELAY_MS > 0) { |
|
k_sleep(K_MSEC(TCXO_POWER_STARTUP_DELAY_MS)); |
|
} |
|
} else { |
|
gpio_pin_set_dt(&dev_config.tcxo_power, 0); |
|
} |
|
|
|
dev_data.tcxo_power_enabled = enable; |
|
#endif |
|
} |
|
|
|
void SX127xSetAntSw(uint8_t opMode) |
|
{ |
|
switch (opMode) { |
|
case RFLR_OPMODE_TRANSMITTER: |
|
sx127x_rfi_enable(0); |
|
|
|
if (SX127X_PA_OUTPUT(dev_data.tx_power) == SX127X_PA_BOOST) { |
|
sx127x_rfo_enable(0); |
|
sx127x_pa_boost_enable(1); |
|
} else { |
|
sx127x_pa_boost_enable(0); |
|
sx127x_rfo_enable(1); |
|
} |
|
break; |
|
default: |
|
sx127x_rfo_enable(0); |
|
sx127x_pa_boost_enable(0); |
|
sx127x_rfi_enable(1); |
|
break; |
|
} |
|
} |
|
|
|
void SX127xReset(void) |
|
{ |
|
SX127xSetBoardTcxo(true); |
|
|
|
gpio_pin_set_dt(&dev_config.reset, 1); |
|
|
|
k_sleep(K_MSEC(1)); |
|
|
|
gpio_pin_set_dt(&dev_config.reset, 0); |
|
|
|
k_sleep(K_MSEC(6)); |
|
} |
|
|
|
static void sx127x_dio_work_handle(struct k_work *work) |
|
{ |
|
int dio = work - dev_data.dio_work; |
|
|
|
(*DioIrq[dio])(NULL); |
|
} |
|
|
|
static void sx127x_irq_callback(const struct device *dev, |
|
struct gpio_callback *cb, uint32_t pins) |
|
{ |
|
unsigned int i, pin; |
|
|
|
pin = find_lsb_set(pins) - 1; |
|
|
|
for (i = 0; i < SX127X_MAX_DIO; i++) { |
|
if (dev == sx127x_dios[i].port && |
|
pin == sx127x_dios[i].pin) { |
|
k_work_submit(&dev_data.dio_work[i]); |
|
} |
|
} |
|
} |
|
|
|
void SX127xIoIrqInit(DioIrqHandler **irqHandlers) |
|
{ |
|
unsigned int i; |
|
static struct gpio_callback callbacks[SX127X_MAX_DIO]; |
|
|
|
/* Setup DIO gpios */ |
|
for (i = 0; i < SX127X_MAX_DIO; i++) { |
|
if (!irqHandlers[i]) { |
|
continue; |
|
} |
|
|
|
if (!gpio_is_ready_dt(&sx127x_dios[i])) { |
|
LOG_ERR("GPIO port %s not ready", |
|
sx127x_dios[i].port->name); |
|
return; |
|
} |
|
|
|
k_work_init(&dev_data.dio_work[i], sx127x_dio_work_handle); |
|
|
|
gpio_pin_configure_dt(&sx127x_dios[i], GPIO_INPUT); |
|
|
|
gpio_init_callback(&callbacks[i], |
|
sx127x_irq_callback, |
|
BIT(sx127x_dios[i].pin)); |
|
|
|
if (gpio_add_callback(sx127x_dios[i].port, &callbacks[i]) < 0) { |
|
LOG_ERR("Could not set gpio callback."); |
|
return; |
|
} |
|
gpio_pin_interrupt_configure_dt(&sx127x_dios[i], |
|
GPIO_INT_EDGE_TO_ACTIVE); |
|
} |
|
|
|
} |
|
|
|
static int sx127x_transceive(uint8_t reg, bool write, void *data, size_t length) |
|
{ |
|
const struct spi_buf buf[2] = { |
|
{ |
|
.buf = ®, |
|
.len = sizeof(reg) |
|
}, |
|
{ |
|
.buf = data, |
|
.len = length |
|
} |
|
}; |
|
|
|
struct spi_buf_set tx = { |
|
.buffers = buf, |
|
.count = ARRAY_SIZE(buf), |
|
}; |
|
|
|
if (!write) { |
|
const struct spi_buf_set rx = { |
|
.buffers = buf, |
|
.count = ARRAY_SIZE(buf) |
|
}; |
|
|
|
return spi_transceive_dt(&dev_config.bus, &tx, &rx); |
|
} |
|
|
|
return spi_write_dt(&dev_config.bus, &tx); |
|
} |
|
|
|
int sx127x_read(uint8_t reg_addr, uint8_t *data, uint8_t len) |
|
{ |
|
return sx127x_transceive(reg_addr, false, data, len); |
|
} |
|
|
|
int sx127x_write(uint8_t reg_addr, uint8_t *data, uint8_t len) |
|
{ |
|
return sx127x_transceive(reg_addr | BIT(7), true, data, len); |
|
} |
|
|
|
void SX127xWriteBuffer(uint32_t addr, uint8_t *buffer, uint8_t size) |
|
{ |
|
int ret; |
|
|
|
ret = sx127x_write(addr, buffer, size); |
|
if (ret < 0) { |
|
LOG_ERR("Unable to write address: 0x%x", addr); |
|
} |
|
} |
|
|
|
void SX127xReadBuffer(uint32_t addr, uint8_t *buffer, uint8_t size) |
|
{ |
|
int ret; |
|
|
|
ret = sx127x_read(addr, buffer, size); |
|
if (ret < 0) { |
|
LOG_ERR("Unable to read address: 0x%x", addr); |
|
} |
|
} |
|
|
|
void SX127xSetRfTxPower(int8_t power) |
|
{ |
|
int ret; |
|
uint8_t pa_config = 0; |
|
uint8_t pa_dac = 0; |
|
|
|
ret = sx127x_read(REG_PADAC, &pa_dac, 1); |
|
if (ret < 0) { |
|
LOG_ERR("Unable to read PA dac"); |
|
return; |
|
} |
|
|
|
pa_dac &= ~SX127X_PADAC_20DBM_MASK; |
|
|
|
if (SX127X_PA_OUTPUT(power) == SX127X_PA_BOOST) { |
|
power = clamp_int8(power, 2, 20); |
|
|
|
pa_config |= SX127X_PACONFIG_PASELECT_PABOOST; |
|
if (power > 17) { |
|
pa_dac |= SX127X_PADAC_20DBM_ON; |
|
pa_config |= (power - 5) & SX127X_PACONFIG_OUTPUTPOWER_MASK; |
|
} else { |
|
pa_dac |= SX127X_PADAC_20DBM_OFF; |
|
pa_config |= (power - 2) & SX127X_PACONFIG_OUTPUTPOWER_MASK; |
|
} |
|
} else { |
|
#ifdef SX127X_PACONFIG_MAX_POWER_SHIFT |
|
power = clamp_int8(power, -4, 15); |
|
|
|
pa_dac |= SX127X_PADAC_20DBM_OFF; |
|
if (power > 0) { |
|
/* Set the power range to 0 -- 10.8+0.6*7 dBm */ |
|
pa_config |= 7 << SX127X_PACONFIG_MAX_POWER_SHIFT; |
|
pa_config |= power & SX127X_PACONFIG_OUTPUTPOWER_MASK; |
|
} else { |
|
/* Set the power range to -4.2 -- 10.8+0.6*0 dBm */ |
|
pa_config |= (power + 4) & SX127X_PACONFIG_OUTPUTPOWER_MASK; |
|
} |
|
#else |
|
power = clamp_int8(power, -1, 14); |
|
|
|
pa_dac |= SX127X_PADAC_20DBM_OFF; |
|
pa_config |= (power + 1) & SX127X_PACONFIG_OUTPUTPOWER_MASK; |
|
#endif |
|
} |
|
|
|
#if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) && \ |
|
DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios) |
|
dev_data.tx_power = power; |
|
#endif |
|
|
|
ret = sx127x_write(REG_PACONFIG, &pa_config, 1); |
|
if (ret < 0) { |
|
LOG_ERR("Unable to write PA config"); |
|
return; |
|
} |
|
|
|
ret = sx127x_write(REG_PADAC, &pa_dac, 1); |
|
if (ret < 0) { |
|
LOG_ERR("Unable to write PA dac"); |
|
return; |
|
} |
|
} |
|
|
|
uint32_t SX127xGetDio1PinState(void) |
|
{ |
|
#if SX127X_DIO_GPIO_LEN(0) >= 2 |
|
if (gpio_pin_get_dt(&sx127x_dios[1]) > 0) { |
|
return 1U; |
|
} |
|
#endif |
|
|
|
return 0U; |
|
} |
|
|
|
/* Initialize Radio driver callbacks */ |
|
const struct Radio_s Radio = { |
|
.Init = SX127xInit, |
|
.GetStatus = SX127xGetStatus, |
|
.SetModem = SX127xSetModem, |
|
.SetChannel = SX127xSetChannel, |
|
.IsChannelFree = SX127xIsChannelFree, |
|
.Random = SX127xRandom, |
|
.SetRxConfig = SX127xSetRxConfig, |
|
.SetTxConfig = SX127xSetTxConfig, |
|
.CheckRfFrequency = SX127xCheckRfFrequency, |
|
.TimeOnAir = SX127xGetTimeOnAir, |
|
.Send = SX127xSend, |
|
.Sleep = SX127xSetSleep, |
|
.Standby = SX127xSetStby, |
|
.Rx = SX127xSetRx, |
|
.Write = SX127xWrite, |
|
.Read = SX127xRead, |
|
.WriteBuffer = SX127xWriteBuffer, |
|
.ReadBuffer = SX127xReadBuffer, |
|
.SetMaxPayloadLength = SX127xSetMaxPayloadLength, |
|
.SetPublicNetwork = SX127xSetPublicNetwork, |
|
.GetWakeupTime = SX127xGetWakeupTime, |
|
.IrqProcess = NULL, |
|
.RxBoosted = NULL, |
|
.SetRxDutyCycle = NULL, |
|
.SetTxContinuousWave = SX127xSetTxContinuousWave, |
|
}; |
|
|
|
static int sx127x_antenna_configure(void) |
|
{ |
|
int ret; |
|
|
|
ret = sx12xx_configure_pin(antenna_enable, GPIO_OUTPUT_INACTIVE); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
ret = sx12xx_configure_pin(rfi_enable, GPIO_OUTPUT_INACTIVE); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
ret = sx12xx_configure_pin(rfo_enable, GPIO_OUTPUT_INACTIVE); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
ret = sx12xx_configure_pin(pa_boost_enable, GPIO_OUTPUT_INACTIVE); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static int sx127x_lora_init(const struct device *dev) |
|
{ |
|
int ret; |
|
uint8_t regval; |
|
|
|
if (!spi_is_ready_dt(&dev_config.bus)) { |
|
LOG_ERR("SPI device not ready"); |
|
return -ENODEV; |
|
} |
|
|
|
ret = sx12xx_configure_pin(tcxo_power, GPIO_OUTPUT_INACTIVE); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
/* Setup Reset gpio and perform soft reset */ |
|
ret = sx12xx_configure_pin(reset, GPIO_OUTPUT_ACTIVE); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
k_sleep(K_MSEC(100)); |
|
gpio_pin_set_dt(&dev_config.reset, 0); |
|
k_sleep(K_MSEC(100)); |
|
|
|
ret = sx127x_read(REG_VERSION, ®val, 1); |
|
if (ret < 0) { |
|
LOG_ERR("Unable to read version info"); |
|
return -EIO; |
|
} |
|
|
|
LOG_INF("SX127x version 0x%02x found", regval); |
|
|
|
ret = sx127x_antenna_configure(); |
|
if (ret < 0) { |
|
LOG_ERR("Unable to configure antenna"); |
|
return -EIO; |
|
} |
|
|
|
ret = sx12xx_init(dev); |
|
if (ret < 0) { |
|
LOG_ERR("Failed to initialize SX12xx common"); |
|
return ret; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static DEVICE_API(lora, sx127x_lora_api) = { |
|
.config = sx12xx_lora_config, |
|
.send = sx12xx_lora_send, |
|
.send_async = sx12xx_lora_send_async, |
|
.recv = sx12xx_lora_recv, |
|
.recv_async = sx12xx_lora_recv_async, |
|
.test_cw = sx12xx_lora_test_cw, |
|
}; |
|
|
|
DEVICE_DT_INST_DEFINE(0, &sx127x_lora_init, NULL, NULL, |
|
NULL, POST_KERNEL, CONFIG_LORA_INIT_PRIORITY, |
|
&sx127x_lora_api);
|
|
|