mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #18033 from thingsat/pr/sx1280_v2
drivers/sx1280: add driver for SX1280 transceiver v2
This commit is contained in:
commit
37da85f047
@ -21,5 +21,6 @@ rsource "slipdev/Kconfig"
|
||||
rsource "$(RIOTCPU)/native/socket_zep/Kconfig"
|
||||
rsource "sx126x/Kconfig"
|
||||
rsource "sx127x/Kconfig"
|
||||
rsource "sx1280/Kconfig"
|
||||
rsource "tja1042/Kconfig"
|
||||
endmenu # Network Device Drivers
|
||||
|
@ -320,6 +320,7 @@ typedef enum {
|
||||
NETDEV_NRF24L01P_NG,
|
||||
NETDEV_SOCKET_ZEP,
|
||||
NETDEV_SX126X,
|
||||
NETDEV_SX1280,
|
||||
NETDEV_CC2420,
|
||||
NETDEV_ETHOS,
|
||||
NETDEV_SLIPDEV,
|
||||
|
267
drivers/include/sx1280.h
Normal file
267
drivers/include/sx1280.h
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Inria
|
||||
* Copyright (C) 2020-2022 Université Grenoble Alpes
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_sx1280 LoRa radio driver
|
||||
* @ingroup drivers_netdev
|
||||
* @brief Driver for the sx1280 LoRa radio device
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
* @author Aymeric Brochier <aymeric.brochier@univ-grenoble-alpes.fr>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SX1280_H
|
||||
#define SX1280_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "sx1280_driver/src/sx1280_hal.h"
|
||||
#include "sx1280_driver/src/sx1280.h"
|
||||
#include "smtc_ral/src/ral.h"
|
||||
#include "smtc_ral/src/ral_defs.h"
|
||||
|
||||
#include "net/netdev.h"
|
||||
|
||||
#include "periph/gpio.h"
|
||||
#include "periph/spi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name SX1280 device default configuration
|
||||
* @{
|
||||
*/
|
||||
#define SX1280_CHANNEL_DEFAULT (2403000000UL) /**< Default channel frequency, 2403MHz */
|
||||
#define SX1280_RADIO_TX_POWER (SX1280_PWR_MAX) /**< Radio power in dBm */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* * @note Forward declaration of the sx1280 device descriptor
|
||||
*/
|
||||
typedef struct sx1280 sx1280_t;
|
||||
|
||||
/**
|
||||
* @brief Device initialization parameters
|
||||
*/
|
||||
typedef struct {
|
||||
spi_t spi; /**< SPI device */
|
||||
spi_mode_t spi_mode; /**< SPI mode */
|
||||
spi_clk_t spi_clk; /**< SPI clk */
|
||||
gpio_t nss_pin; /**< SPI NSS pin */
|
||||
gpio_t reset_pin; /**< Reset pin */
|
||||
gpio_t busy_pin; /**< Busy pin */
|
||||
gpio_t dio0_pin; /**< Dio0 pin */
|
||||
gpio_t dio1_pin; /**< Dio1 pin */
|
||||
sx1280_reg_mod_t regulator; /**< Power regulator mode */
|
||||
} sx1280_params_t;
|
||||
|
||||
/**
|
||||
* @brief Device descriptor for the driver
|
||||
*/
|
||||
struct sx1280 {
|
||||
netdev_t netdev; /**< Netdev parent struct */
|
||||
ral_t ral; /**< Radio abstraction */
|
||||
ral_params_lora_t ral_params_lora; /**< LoRa modulation parameters */
|
||||
sx1280_params_t *params; /**< Initialization parameters */
|
||||
sx1280_hal_operating_mode_t mode; /**< Operating Mode */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Setup the radio device
|
||||
*
|
||||
* @param[in] dev Device descriptor
|
||||
* @param[in] params Parameters for device initialization
|
||||
* @param[in] index Index of @p params in a global parameter struct array.
|
||||
* If initialized manually, pass a unique identifier instead.
|
||||
*/
|
||||
void sx1280_setup(sx1280_t *dev, const sx1280_params_t *params, uint8_t index);
|
||||
|
||||
/**
|
||||
* @brief Initialize the given device
|
||||
*
|
||||
* @param[inout] dev Device descriptor of the driver
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int sx1280_init(sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Gets the channel RF frequency.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return The channel frequency
|
||||
*/
|
||||
uint32_t sx1280_get_channel(const sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Gets a random number
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return a random number
|
||||
*/
|
||||
uint32_t sx1280_random(const sx1280_t *dev);
|
||||
/**
|
||||
* @brief Sets the channel RF frequency.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[in] freq Channel RF frequency
|
||||
*/
|
||||
void sx1280_set_channel(sx1280_t *dev, uint32_t freq);
|
||||
|
||||
/**
|
||||
* @brief Gets the LoRa bandwidth
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return the bandwidth
|
||||
*/
|
||||
uint32_t sx1280_get_bandwidth(const sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Sets the LoRa bandwidth
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[in] bandwidth The new bandwidth
|
||||
*/
|
||||
void sx1280_set_bandwidth(sx1280_t *dev, uint16_t bandwidth);
|
||||
|
||||
/**
|
||||
* @brief Gets the LoRa spreading factor
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return the spreading factor
|
||||
*/
|
||||
uint8_t sx1280_get_spreading_factor(const sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Sets the LoRa spreading factor
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[in] sf The spreading factor
|
||||
*/
|
||||
void sx1280_set_spreading_factor(sx1280_t *dev, uint8_t sf);
|
||||
|
||||
/**
|
||||
* @brief Gets the LoRa coding rate
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return the current LoRa coding rate
|
||||
*/
|
||||
uint8_t sx1280_get_coding_rate(const sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Sets the LoRa coding rate
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[in] cr The LoRa coding rate
|
||||
*/
|
||||
void sx1280_set_coding_rate(sx1280_t *dev, uint8_t cr);
|
||||
|
||||
/**
|
||||
* @brief Gets the payload length
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return the payload length
|
||||
*/
|
||||
uint8_t sx1280_get_lora_payload_length(const sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Sets the payload length
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[in] len The payload len
|
||||
*/
|
||||
void sx1280_set_lora_payload_length(sx1280_t *dev, uint8_t len);
|
||||
|
||||
/**
|
||||
* @brief Checks if CRC verification mode is enabled
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return the LoRa single mode
|
||||
*/
|
||||
bool sx1280_get_lora_crc(const sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable CRC verification mode
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[in] crc The CRC check mode
|
||||
*/
|
||||
void sx1280_set_lora_crc(sx1280_t *dev, bool crc);
|
||||
|
||||
/**
|
||||
* @brief Gets the LoRa implicit header mode
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return the LoRa implicit mode
|
||||
*/
|
||||
bool sx1280_get_lora_implicit_header(const sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Sets LoRa implicit header mode
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[in] mode The header mode
|
||||
*/
|
||||
void sx1280_set_lora_implicit_header(sx1280_t *dev, bool mode);
|
||||
|
||||
/**
|
||||
* @brief Gets the LoRa preamble length
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return the preamble length
|
||||
*/
|
||||
uint16_t sx1280_get_lora_preamble_length(const sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Sets the LoRa preamble length
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[in] preamble The LoRa preamble length
|
||||
*/
|
||||
void sx1280_set_lora_preamble_length(sx1280_t *dev, uint16_t preamble);
|
||||
|
||||
/**
|
||||
* @brief Checks if the LoRa inverted IQ mode is enabled/disabled
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
*
|
||||
* @return the LoRa IQ inverted mode
|
||||
*/
|
||||
bool sx1280_get_lora_iq_invert(const sx1280_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable the LoRa IQ inverted mode
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[in] iq_invert The LoRa IQ inverted mode
|
||||
*/
|
||||
void sx1280_set_lora_iq_invert(sx1280_t *dev, bool iq_invert);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SX1280_H */
|
||||
/** @} */
|
17
drivers/sx1280/Kconfig
Normal file
17
drivers/sx1280/Kconfig
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (c) 2022 Inria
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU Lesser
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
config MODULE_SX1280
|
||||
bool "LoRa 2.4Ghz SX1280 Driver" if !(HAVE_SX1280 && MODULE_NETDEV_DEFAULT)
|
||||
default y if (HAVE_SX1280 && MODULE_NETDEV_DEFAULT)
|
||||
depends on TEST_KCONFIG
|
||||
select PACKAGE_LORABASICS
|
||||
select MODULE_LORABASICS_SX1280_DRIVER
|
||||
|
||||
config HAVE_SX1280
|
||||
bool
|
||||
help
|
||||
Indicates that an sx1280 2.4Ghz transceiver is present.
|
1
drivers/sx1280/Makefile
Normal file
1
drivers/sx1280/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
2
drivers/sx1280/Makefile.dep
Normal file
2
drivers/sx1280/Makefile.dep
Normal file
@ -0,0 +1,2 @@
|
||||
USEPKG += lorabasics
|
||||
USEMODULE += lorabasics_sx1280_driver
|
7
drivers/sx1280/Makefile.include
Normal file
7
drivers/sx1280/Makefile.include
Normal file
@ -0,0 +1,7 @@
|
||||
USEMODULE_INCLUDES_sx1280 := $(LAST_MAKEFILEDIR)/include
|
||||
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_sx1280)
|
||||
|
||||
# Overide defaults see See https://lora-developers.semtech.com/documentation/tech-papers-and-guides/physical-layer-proposal-2.4ghz/
|
||||
CFLAGS += -DCONFIG_LORA_BW_DEFAULT_800=1
|
||||
CFLAGS += -DCONFIG_LORA_SF_DEFAULT_SF12=1
|
||||
CFLAGS += -DCONFIG_LORA_CR_DEFAULT_CR_LI_4_8=1
|
75
drivers/sx1280/include/sx1280_constants.h
Normal file
75
drivers/sx1280/include/sx1280_constants.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Inria
|
||||
* Copyright (C) 2020-2022 Université Grenoble Alpes
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_sx1280
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Internal addresses, registers and constants
|
||||
*
|
||||
* @author Aymeric Brochier <aymeric.brochier@univ-grenoble-alpes.fr>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SX1280_CONSTANTS_H
|
||||
#define SX1280_CONSTANTS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SX1280 Single RX mode.
|
||||
*
|
||||
* sx1280_set_rx constant to be in single mode
|
||||
*
|
||||
* There is a known issue about this in some circonstances described in section 16.1 of the datasheet:
|
||||
* https://manualzz.com/doc/55353537/semtech-sx1280-2.4-ghz-transceiver-datasheet
|
||||
*
|
||||
* When subjected to a high co-channel traffic conditions
|
||||
* (for example in BLE mode when the SX1280 receives more than 220 packets per second)
|
||||
* and only when configured in continuous receiver
|
||||
* The SX1280 busy line will remain high and the radio unresponsive.
|
||||
*
|
||||
* If the radio may be subject to high levels of BLE traffic, to allow the radio to remain in operation RX single mode must be used
|
||||
*/
|
||||
#define SX1280_RX_SINGLE_MODE 0x0000
|
||||
|
||||
/**
|
||||
* @brief SX1280 Continuous RX mode.
|
||||
*
|
||||
* @note This addresses a known issue detailed in section 16.1 of the datasheet, see
|
||||
* @ref SX1280_RX_SINGLE_MODE for more details.
|
||||
*
|
||||
* sx1280_set_rx require this constant to be in continuous mode
|
||||
*
|
||||
*/
|
||||
#define SX1280_RX_CONTINUOUS_MODE 0xFFFF
|
||||
|
||||
/**
|
||||
* @brief SX1280 wakeup time in ms
|
||||
* @note From the datasheet wakeup time is usually 1200us but rounded up to 2 to only use the ZTIMER_MSEC
|
||||
*
|
||||
*/
|
||||
#define SX1280_WAKEUP_TIME_MS 2
|
||||
|
||||
/**
|
||||
* @brief SX1280 reset time in ms
|
||||
* hold NRST pin low for 1ms, nothing is specified in the datasheet, 1ms worked fine
|
||||
*
|
||||
*/
|
||||
#define SX1280_RESET_MS 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SX1280_CONSTANTS_H */
|
||||
/** @} */
|
40
drivers/sx1280/include/sx1280_netdev.h
Normal file
40
drivers/sx1280/include/sx1280_netdev.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Inria
|
||||
* Copyright (C) 2020-2022 Université Grenoble Alpes
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_sx1280
|
||||
* @{
|
||||
* @file
|
||||
* @brief Netdev driver definitions for LoRa SX1280 Driver driver
|
||||
*
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
* @author Aymeric Brochier <aymeric.brochier@univ-grenoble-alpes.fr>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SX1280_NETDEV_H
|
||||
#define SX1280_NETDEV_H
|
||||
|
||||
#include "net/netdev.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Reference to the netdev device driver struct
|
||||
*/
|
||||
extern const netdev_driver_t sx1280_driver;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SX1280_NETDEV_H */
|
||||
/** @} */
|
113
drivers/sx1280/include/sx1280_params.h
Normal file
113
drivers/sx1280/include/sx1280_params.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Inria
|
||||
* Copyright (C) 2020-2022 Université Grenoble Alpes
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_sx1280
|
||||
* @{
|
||||
* @file
|
||||
* @brief Default configuration
|
||||
*
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
* @author Aymeric Brochier <aymeric.brochier@univ-grenoble-alpes.fr>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SX1280_PARAMS_H
|
||||
#define SX1280_PARAMS_H
|
||||
|
||||
#include "board.h"
|
||||
#include "sx1280.h"
|
||||
#include "sx1280_constants.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Set default configuration parameters
|
||||
*
|
||||
* Default values are adapted for mbed shield used with to nucleo64 boards
|
||||
* @see https://github.com/donsez/RIOT/blob/pr/sx1280/drivers/sx1280/include/sx1280_hal.h
|
||||
* @see 'board/commun/nucleo64/include/arduino_pinmap.h'
|
||||
*
|
||||
* ARDUINO_PIN_10 -> GPIO_PIN(PORT_B, 6) -> GPIO_PIN(1, 6)
|
||||
* ARDUINO_PIN_7 -> GPIO_PIN(PORT_A, 8) -> GPIO_PIN(0, 8)
|
||||
* ARDUINO_PIN_6 -> GPIO_PIN(PORT_B, 10) -> GPIO_PIN(1, 10)
|
||||
* ARDUINO_PIN_9 -> GPIO_PIN(PORT_C, 7) -> GPIO_PIN(2, 7)
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef USE_RX_CONTINUOUS_MODE
|
||||
#define USE_RX_CONTINUOUS_MODE /**< default RX MODE */
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_CONTINUOUS_MODE
|
||||
#define SX1280_RX_MODE SX1280_RX_CONTINUOUS_MODE /**< continuous RX MODE */
|
||||
#else
|
||||
#define SX1280_RX_MODE SX1280_RX_SINGLE_MODE /**< single RX MODE */
|
||||
#endif
|
||||
|
||||
#ifndef SX1280_PARAM_SPI
|
||||
#define SX1280_PARAM_SPI SPI_DEV(0) /**< default SPI device */
|
||||
#endif
|
||||
|
||||
#ifndef SX1280_PARAM_SPI_CLK
|
||||
#define SX1280_PARAM_SPI_CLK SPI_CLK_5MHZ /**< default SPI speed */
|
||||
#endif
|
||||
|
||||
#ifndef SX1280_PARAM_SPI_MODE
|
||||
#define SX1280_PARAM_SPI_MODE SPI_MODE_0 /**< default SPI mode for sx1280 */
|
||||
#endif
|
||||
|
||||
#ifndef SX1280_PARAM_SPI_NSS
|
||||
#define SX1280_PARAM_SPI_NSS GPIO_PIN(1, 6) /**< SPI NSS pin */
|
||||
#endif
|
||||
|
||||
#ifndef SX1280_PARAM_RESET
|
||||
#define SX1280_PARAM_RESET GPIO_PIN(0, 8) /**< Reset pin */
|
||||
#endif
|
||||
|
||||
#ifndef SX1280_PARAM_DIO0
|
||||
#define SX1280_PARAM_DIO0 GPIO_PIN(1, 10) /**< DIO0 */
|
||||
#endif
|
||||
|
||||
#ifndef SX1280_PARAM_DIO1
|
||||
#define SX1280_PARAM_DIO1 GPIO_PIN(2, 7) /**< DIO1 */
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Default sx1280 parameters
|
||||
*/
|
||||
#define SX1280_PARAMS { .spi = SX1280_PARAM_SPI, \
|
||||
.spi_mode = SX1280_PARAM_SPI_MODE, \
|
||||
.spi_clk = SX1280_PARAM_SPI_CLK, \
|
||||
.nss_pin = SX1280_PARAM_SPI_NSS, \
|
||||
.reset_pin = SX1280_PARAM_RESET, \
|
||||
.dio0_pin = SX1280_PARAM_DIO0, \
|
||||
.dio1_pin = SX1280_PARAM_DIO1, \
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* @brief Configuration struct
|
||||
*/
|
||||
static const sx1280_params_t sx1280_params[] =
|
||||
{
|
||||
SX1280_PARAMS
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SX1280_PARAMS_H */
|
||||
/** @} */
|
406
drivers/sx1280/sx1280.c
Normal file
406
drivers/sx1280/sx1280.c
Normal file
@ -0,0 +1,406 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Inria
|
||||
* Copyright (C) 2020-2022 Université Grenoble Alpes
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_sx1280
|
||||
* @{
|
||||
* @file
|
||||
* @brief Device driver implementation for the LoRa SX1280 Driver
|
||||
*
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
* @author Aymeric Brochier <aymeric.brochier@univ-grenoble-alpes.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "ztimer.h"
|
||||
|
||||
#include "sx1280_driver/src/sx1280.h"
|
||||
#include "sx1280_driver/src/sx1280_regs.h"
|
||||
#include "smtc_ral/src/ral_sx1280.h"
|
||||
|
||||
#include "sx1280.h"
|
||||
#include "sx1280_constants.h"
|
||||
#include "sx1280_params.h"
|
||||
#include "sx1280_netdev.h"
|
||||
|
||||
#include "net/lora.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
static ral_lora_bw_t _lora_bw_to_ral_bw(int bw)
|
||||
{
|
||||
switch (bw) {
|
||||
case LORA_BW_125_KHZ:
|
||||
return RAL_LORA_BW_125_KHZ;
|
||||
case LORA_BW_200_KHZ:
|
||||
return RAL_LORA_BW_200_KHZ;
|
||||
case LORA_BW_250_KHZ:
|
||||
return RAL_LORA_BW_250_KHZ;
|
||||
case LORA_BW_400_KHZ:
|
||||
return RAL_LORA_BW_400_KHZ;
|
||||
case LORA_BW_500_KHZ:
|
||||
return RAL_LORA_BW_500_KHZ;
|
||||
case LORA_BW_800_KHZ:
|
||||
return RAL_LORA_BW_800_KHZ;
|
||||
case LORA_BW_1600_KHZ:
|
||||
return RAL_LORA_BW_1600_KHZ;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static ral_lora_sf_t _lora_sf_to_ral_sf(int sf)
|
||||
{
|
||||
return (ral_lora_sf_t)sf;
|
||||
}
|
||||
|
||||
static ral_lora_cr_t _lora_cr_to_ral_cr(int cr)
|
||||
{
|
||||
switch (cr) {
|
||||
case LORA_CR_4_5:
|
||||
return RAL_LORA_CR_4_5;
|
||||
case LORA_CR_4_6:
|
||||
return RAL_LORA_CR_4_6;
|
||||
case LORA_CR_4_7:
|
||||
return RAL_LORA_CR_4_7;
|
||||
case LORA_CR_4_8:
|
||||
return RAL_LORA_CR_4_8;
|
||||
case LORA_CR_LI_4_5:
|
||||
return RAL_LORA_CR_LI_4_5;
|
||||
case LORA_CR_LI_4_6:
|
||||
return RAL_LORA_CR_LI_4_6;
|
||||
case LORA_CR_LI_4_8:
|
||||
return RAL_LORA_CR_LI_4_8;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int _ral_lora_cr_to_lora_cr(int cr)
|
||||
{
|
||||
switch (cr) {
|
||||
case RAL_LORA_CR_4_5:
|
||||
return LORA_CR_4_5;
|
||||
case RAL_LORA_CR_4_6:
|
||||
return LORA_CR_4_6;
|
||||
case RAL_LORA_CR_4_7:
|
||||
return LORA_CR_4_7;
|
||||
case RAL_LORA_CR_4_8:
|
||||
return LORA_CR_4_8;
|
||||
case RAL_LORA_CR_LI_4_5:
|
||||
return LORA_CR_LI_4_5;
|
||||
case RAL_LORA_CR_LI_4_6:
|
||||
return LORA_CR_LI_4_6;
|
||||
case RAL_LORA_CR_LI_4_8:
|
||||
return LORA_CR_LI_4_8;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t _get_bw(ral_lora_bw_t lora_bw)
|
||||
{
|
||||
switch (lora_bw) {
|
||||
case RAL_LORA_BW_007_KHZ:
|
||||
return (uint32_t)7000;
|
||||
case RAL_LORA_BW_010_KHZ:
|
||||
return (uint32_t)10000;
|
||||
case RAL_LORA_BW_015_KHZ:
|
||||
return (uint32_t)15000;
|
||||
case RAL_LORA_BW_020_KHZ:
|
||||
return (uint32_t)20000;
|
||||
case RAL_LORA_BW_031_KHZ:
|
||||
return (uint32_t)31000;
|
||||
case RAL_LORA_BW_041_KHZ:
|
||||
return (uint32_t)41000;
|
||||
case RAL_LORA_BW_062_KHZ:
|
||||
return (uint32_t)62000;
|
||||
case RAL_LORA_BW_125_KHZ:
|
||||
return (uint32_t)125000;
|
||||
case RAL_LORA_BW_200_KHZ:
|
||||
return (uint32_t)200000;
|
||||
case RAL_LORA_BW_250_KHZ:
|
||||
return (uint32_t)250000;
|
||||
case RAL_LORA_BW_400_KHZ:
|
||||
return (uint32_t)400000;
|
||||
case RAL_LORA_BW_500_KHZ:
|
||||
return (uint32_t)500000;
|
||||
case RAL_LORA_BW_800_KHZ:
|
||||
return (uint32_t)800000;
|
||||
case RAL_LORA_BW_1600_KHZ:
|
||||
return (uint32_t)1600000;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void _dio1_isr(void *arg)
|
||||
{
|
||||
netdev_trigger_event_isr(arg);
|
||||
}
|
||||
|
||||
static int enable_irq(const sx1280_t *dev)
|
||||
{
|
||||
const uint16_t irq_mask = (
|
||||
SX1280_IRQ_TX_DONE |
|
||||
SX1280_IRQ_RX_DONE |
|
||||
SX1280_IRQ_PBL_DET |
|
||||
SX1280_IRQ_HEADER_VALID |
|
||||
SX1280_IRQ_HEADER_ERROR |
|
||||
SX1280_IRQ_CAD_DONE |
|
||||
SX1280_IRQ_CAD_DET |
|
||||
SX1280_IRQ_TIMEOUT
|
||||
);
|
||||
|
||||
int res = sx1280_set_dio_irq_params(dev, irq_mask, irq_mask, SX1280_IRQ_NONE, SX1280_IRQ_NONE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void sx1280_setup(sx1280_t *dev, const sx1280_params_t *params, uint8_t index)
|
||||
{
|
||||
dev->ral.context = dev;
|
||||
dev->ral.radio_type = RAL_RADIO_SX1280;
|
||||
dev->ral.tcxo_cfg.tcxo_ctrl_mode = RAL_TCXO_NONE;
|
||||
|
||||
netdev_t *netdev = &dev->netdev;
|
||||
|
||||
netdev->driver = &sx1280_driver;
|
||||
dev->params = (sx1280_params_t *)params;
|
||||
netdev_register(&dev->netdev, NETDEV_SX1280, index);
|
||||
}
|
||||
|
||||
static uint32_t sx1280_init_default_config(sx1280_t *dev)
|
||||
|
||||
{
|
||||
/* default parameters */
|
||||
const ral_params_lora_t params_default = {
|
||||
.freq_in_hz = SX1280_CHANNEL_DEFAULT,
|
||||
.sf = _lora_sf_to_ral_sf(CONFIG_LORA_SF_DEFAULT),
|
||||
.bw = _lora_bw_to_ral_bw(CONFIG_LORA_BW_DEFAULT),
|
||||
.cr = _lora_cr_to_ral_cr(CONFIG_LORA_CR_DEFAULT),
|
||||
.pbl_len_in_symb = CONFIG_LORA_PREAMBLE_LENGTH_DEFAULT,
|
||||
.sync_word = LORA_SYNCWORD_ISM2400_PUBLIC,
|
||||
.pld_is_fix = false,
|
||||
.crc_is_on = true,
|
||||
.invert_iq_is_on = false,
|
||||
.symb_nb_timeout = 0,
|
||||
.pwr_in_dbm = SX1280_RADIO_TX_POWER,
|
||||
};
|
||||
|
||||
/* set current ral_params */
|
||||
dev->ral_params_lora = params_default;
|
||||
|
||||
ral_status_t res = ral_sx1280_setup_lora(&dev->ral, ¶ms_default);
|
||||
|
||||
if (res != RAL_STATUS_OK) {
|
||||
DEBUG("[sx1280] init: ERROR failed LoRa setup, %d\n", res);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sx1280_init(sx1280_t *dev)
|
||||
{
|
||||
/* Setup SPI for SX1280 */
|
||||
int res = spi_init_cs(dev->params->spi, dev->params->nss_pin);
|
||||
|
||||
if (res != SPI_OK) {
|
||||
DEBUG("[sx1280] error: failed to initialize SPI_%i device (code %i)\n",
|
||||
dev->params->spi, res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG("[sx1280] init: SPI_%i initialized with success\n", dev->params->spi);
|
||||
/* Initialize Reset */
|
||||
if (gpio_init(dev->params->reset_pin, GPIO_OUT) < 0) {
|
||||
DEBUG("[sx1280] error: failed to initialize RESET pin\n");
|
||||
return -EIO;
|
||||
}
|
||||
/* Initialize DIO0s */
|
||||
if (gpio_init(dev->params->dio0_pin, GPIO_IN) < 0) {
|
||||
DEBUG("[sx1280] error: failed to initialize DIO1 pin\n");
|
||||
return -EIO;
|
||||
}
|
||||
/* Initialize DI01s */
|
||||
if (gpio_init_int(dev->params->dio1_pin, GPIO_IN, GPIO_RISING, _dio1_isr, dev)) {
|
||||
DEBUG("[sx1280] error: failed to initialize DIO1 pin\n");
|
||||
return -EIO;
|
||||
}
|
||||
/* sx1280_reset() and sx1280_set_reg_mode() set in ral_sx1280_init */
|
||||
res = ral_sx1280_init(&dev->ral);
|
||||
if (res == RAL_STATUS_OK) {
|
||||
uint16_t fwid;
|
||||
ral_sx1280_read_register(&dev->ral, SX1280_REG_FW_VERSION, (uint8_t *)&fwid, 2);
|
||||
if (fwid == 0x5853) {
|
||||
DEBUG("[sx1280]: firmware version = %x\n", fwid);
|
||||
}
|
||||
else {
|
||||
DEBUG("[sx1280] error: firmware version = %x\n", fwid);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
sx1280_init_default_config(dev);
|
||||
|
||||
res = enable_irq(dev);
|
||||
if (res != SX1280_STATUS_OK) {
|
||||
DEBUG("[sx1280] init: ERROR failed irq setup, %d\n", res);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
sx1280_set_lna_settings(dev, SX1280_LNA_HIGH_SENSITIVITY_MODE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t sx1280_get_channel(const sx1280_t *dev)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_get_channel\n");
|
||||
return dev->ral_params_lora.freq_in_hz;
|
||||
}
|
||||
|
||||
void sx1280_set_channel(sx1280_t *dev, uint32_t freq)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_set_channel %" PRIu32 "Hz\n", freq);
|
||||
dev->ral_params_lora.freq_in_hz = freq;
|
||||
sx1280_set_rf_freq(dev, dev->ral_params_lora.freq_in_hz);
|
||||
}
|
||||
|
||||
uint32_t sx1280_get_bandwidth(const sx1280_t *dev)
|
||||
{
|
||||
return _get_bw(dev->ral_params_lora.bw);
|
||||
}
|
||||
|
||||
void sx1280_set_bandwidth(sx1280_t *dev, uint16_t bandwidth)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_set_bandwidth (KHz)\n");
|
||||
switch (bandwidth) {
|
||||
case 200:
|
||||
puts("setup: setting 200KHz bandwidth");
|
||||
dev->ral_params_lora.bw = RAL_LORA_BW_200_KHZ;
|
||||
break;
|
||||
case 400:
|
||||
puts("setup: setting 400KHz bandwidth");
|
||||
dev->ral_params_lora.bw = RAL_LORA_BW_400_KHZ;
|
||||
break;
|
||||
case 800:
|
||||
puts("setup: setting 800KHz bandwidth");
|
||||
dev->ral_params_lora.bw = RAL_LORA_BW_800_KHZ;
|
||||
break;
|
||||
case 1600:
|
||||
puts("setup: setting 1600KHz bandwidth");
|
||||
dev->ral_params_lora.bw = RAL_LORA_BW_1600_KHZ;
|
||||
break;
|
||||
/* assume caller function check the validity of the value so should never go here */
|
||||
default:
|
||||
puts("[Error] setup: invalid bandwidth value given, "
|
||||
"only 200, 400, 800 or 1600 allowed.");
|
||||
return;
|
||||
}
|
||||
ral_sx1280_setup_lora(&dev->ral, &dev->ral_params_lora);
|
||||
}
|
||||
|
||||
uint8_t sx1280_get_spreading_factor(const sx1280_t *dev)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_get_spreading_factor\n");
|
||||
/* no conversion needed */
|
||||
return dev->ral_params_lora.sf;
|
||||
}
|
||||
|
||||
void sx1280_set_spreading_factor(sx1280_t *dev, uint8_t sf)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_set_spreading_factor\n");
|
||||
dev->ral_params_lora.sf = sf;
|
||||
ral_sx1280_setup_lora(&dev->ral, &dev->ral_params_lora);
|
||||
}
|
||||
|
||||
uint8_t sx1280_get_coding_rate(const sx1280_t *dev)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_get_coding_rate\n");
|
||||
return _ral_lora_cr_to_lora_cr(dev->ral_params_lora.cr);
|
||||
}
|
||||
|
||||
void sx1280_set_coding_rate(sx1280_t *dev, uint8_t cr)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_set_coding_rate\n");
|
||||
dev->ral_params_lora.cr = cr;
|
||||
ral_sx1280_setup_lora(&dev->ral, &dev->ral_params_lora);
|
||||
}
|
||||
|
||||
uint8_t sx1280_get_lora_payload_length(const sx1280_t *dev)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_get_lora_payload_length\n");
|
||||
sx1280_rx_buffer_status_t rx_buffer_status;
|
||||
|
||||
sx1280_get_rx_buffer_status(dev, &rx_buffer_status);
|
||||
return rx_buffer_status.pld_len_in_bytes;
|
||||
}
|
||||
void sx1280_set_lora_payload_length(sx1280_t *dev, uint8_t len)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_set_lora_payload_length\n");
|
||||
dev->ral_params_lora.pld_len_in_bytes = len;
|
||||
ral_sx1280_setup_lora(&dev->ral, &dev->ral_params_lora);
|
||||
}
|
||||
|
||||
bool sx1280_get_lora_crc(const sx1280_t *dev)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_get_lora_crc\n");
|
||||
return dev->ral_params_lora.crc_is_on;
|
||||
}
|
||||
|
||||
void sx1280_set_lora_crc(sx1280_t *dev, bool crc)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_set_lora_crc\n");
|
||||
dev->ral_params_lora.crc_is_on = crc;
|
||||
ral_sx1280_setup_lora(&dev->ral, &dev->ral_params_lora);
|
||||
}
|
||||
|
||||
bool sx1280_get_lora_implicit_header(const sx1280_t *dev)
|
||||
{
|
||||
(void)dev;
|
||||
DEBUG("[sx1280]: sx1280_get_lora_implicit_header not implemented \n");
|
||||
return false;
|
||||
}
|
||||
|
||||
void sx1280_set_lora_implicit_header(sx1280_t *dev, bool mode)
|
||||
{
|
||||
(void)dev;
|
||||
DEBUG("[sx1280]: sx1280_set_lora_implicit_header not implemented %d\n", mode);
|
||||
}
|
||||
|
||||
uint16_t sx1280_get_lora_preamble_length(const sx1280_t *dev)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_get_lora_preamble_length\n");
|
||||
return dev->ral_params_lora.pbl_len_in_symb;
|
||||
}
|
||||
|
||||
void sx1280_set_lora_preamble_length(sx1280_t *dev, uint16_t preamble)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_set_lora_preamble_length\n");
|
||||
dev->ral_params_lora.pbl_len_in_symb = preamble;
|
||||
ral_sx1280_setup_lora(&dev->ral, &dev->ral_params_lora);
|
||||
}
|
||||
|
||||
bool sx1280_get_lora_iq_invert(const sx1280_t *dev)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_get_lora_iq_invert\n");
|
||||
return dev->ral_params_lora.invert_iq_is_on;
|
||||
}
|
||||
|
||||
void sx1280_set_lora_iq_invert(sx1280_t *dev, bool iq_invert)
|
||||
{
|
||||
DEBUG("[sx1280]: sx1280_set_lora_iq_invert\n");
|
||||
dev->ral_params_lora.invert_iq_is_on = iq_invert;
|
||||
ral_sx1280_setup_lora(&dev->ral, &dev->ral_params_lora);
|
||||
}
|
458
drivers/sx1280/sx1280_netdev.c
Normal file
458
drivers/sx1280/sx1280_netdev.c
Normal file
@ -0,0 +1,458 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Inria
|
||||
* Copyright (C) 2020-2022 Université Grenoble Alpes
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_sx1280
|
||||
* @{
|
||||
* @file
|
||||
* @brief Netdev adaptation for the LoRa SX1280 Driver driver
|
||||
*
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
* @author Aymeric Brochier <aymeric.brochier@univ-grenoble-alpes.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "iolist.h"
|
||||
#include "net/netopt.h"
|
||||
#include "net/netdev.h"
|
||||
#include "net/netdev/lora.h"
|
||||
#include "net/lora.h"
|
||||
|
||||
#include "sx1280.h"
|
||||
#include "sx1280_params.h"
|
||||
|
||||
#include "sx1280_netdev.h"
|
||||
#include "sx1280_driver/src/sx1280.h"
|
||||
|
||||
#include "smtc_ral/src/ral_defs.h"
|
||||
#include "smtc_ral/src/ral_sx1280.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
static int _send(netdev_t *netdev, const iolist_t *iolist)
|
||||
{
|
||||
|
||||
sx1280_t *dev = (sx1280_t *)netdev;
|
||||
netopt_state_t state;
|
||||
|
||||
netdev->driver->get(netdev, NETOPT_STATE, &state, sizeof(netopt_state_t));
|
||||
if (state == NETOPT_STATE_TX) {
|
||||
DEBUG("[sx1280] netdev: cannot send packet, radio is already transmitting.\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
else {
|
||||
DEBUG("[sx1280] netdev: can send packet\n");
|
||||
}
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
/* Write payload buffer */
|
||||
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
|
||||
if (iol->iol_len > 0) {
|
||||
/* write data to payload buffer */
|
||||
sx1280_write_buffer(dev, pos, iol->iol_base, iol->iol_len);
|
||||
DEBUG("[sx1280] netdev: send: wrote data to payload buffer.\n");
|
||||
pos += iol->iol_len;
|
||||
}
|
||||
}
|
||||
/* Ignore send if packet size is 0 */
|
||||
if (!pos) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG("[sx1280] netdev: sending packet now (size: %d).\n", pos);
|
||||
sx1280_set_lora_payload_length(dev, pos);
|
||||
|
||||
state = NETOPT_STATE_TX;
|
||||
netdev->driver->set(netdev, NETOPT_STATE, &state, sizeof(state));
|
||||
DEBUG("[sx1280] netdev: send: transmission in progress.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
|
||||
{
|
||||
DEBUG("[sx1280] netdev: read received data.\n");
|
||||
|
||||
sx1280_t *dev = (sx1280_t *)netdev;
|
||||
uint8_t size = 0;
|
||||
|
||||
/* Get received packet info and size here */
|
||||
netdev_lora_rx_info_t *packet_info = info;
|
||||
|
||||
if (packet_info) {
|
||||
sx1280_pkt_status_lora_t pkt_status;
|
||||
sx1280_get_lora_pkt_status(dev, &pkt_status);
|
||||
packet_info->snr = pkt_status.snr;
|
||||
packet_info->rssi = pkt_status.rssi;
|
||||
}
|
||||
|
||||
sx1280_rx_buffer_status_t rx_buffer_status;
|
||||
|
||||
sx1280_get_rx_buffer_status(dev, &rx_buffer_status);
|
||||
|
||||
size = rx_buffer_status.pld_len_in_bytes;
|
||||
|
||||
if (buf == NULL) {
|
||||
return size;
|
||||
}
|
||||
|
||||
if (size > len) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
/* Read the received packet content here and write it to buf */
|
||||
sx1280_read_buffer(dev, rx_buffer_status.buffer_start_pointer, buf, size);
|
||||
|
||||
/* RX SINGLE MODE */
|
||||
if (sx1280_hal_get_operating_mode(&dev) == SX1280_HAL_OP_MODE_RX) {
|
||||
DEBUG("[sx1280] netdev stop RX single mode" );
|
||||
netopt_state_t state = NETOPT_STATE_IDLE;
|
||||
dev->netdev.driver->set(&dev->netdev, NETOPT_STATE, &state, sizeof(state));
|
||||
return 0;
|
||||
/* RX CONTINUOUS MODE */
|
||||
}
|
||||
else if (sx1280_hal_get_operating_mode(&dev) == SX1280_HAL_OP_MODE_RX_C) {
|
||||
DEBUG("[sx1280] netdev keep RX continuous mode" );
|
||||
netopt_state_t state = NETOPT_STATE_RX;
|
||||
dev->netdev.driver->set(&dev->netdev, NETOPT_STATE, &state, sizeof(state));
|
||||
return size;
|
||||
}
|
||||
else {
|
||||
DEBUG("[sx1280] netdev NOT IMPLEMENTED");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int _init(netdev_t *netdev)
|
||||
{
|
||||
sx1280_t *dev = (sx1280_t *)netdev;
|
||||
|
||||
/* Launch initialization of driver and device */
|
||||
DEBUG("[sx1280] netdev: initializing driver...\n");
|
||||
if (sx1280_init(dev) != 0) {
|
||||
DEBUG("[sx1280] netdev: initialization failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG("[sx1280] netdev: initialization successful\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _isr(netdev_t *netdev)
|
||||
{
|
||||
sx1280_t *dev = (sx1280_t *)netdev;
|
||||
sx1280_irq_mask_t irq_mask;
|
||||
|
||||
ral_sx1280_get_and_clear_irq_status(&dev->ral, &irq_mask);
|
||||
|
||||
if (irq_mask & RAL_IRQ_RX_DONE) {
|
||||
if (irq_mask & RAL_IRQ_RX_CRC_ERROR) {
|
||||
DEBUG("[sx1280] netdev: SX1280_IRQ_CRC_ERROR\n");
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_CRC_ERROR);
|
||||
}
|
||||
else {
|
||||
DEBUG("[sx1280] netdev: SX1280_IRQ_RX_DONE\n");
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
|
||||
}
|
||||
}
|
||||
else if (irq_mask & RAL_IRQ_TX_DONE) {
|
||||
DEBUG("[sx1280] netdev: SX1280_IRQ_TX_DONE\n");
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
|
||||
}
|
||||
else if (irq_mask & RAL_IRQ_RX_HDR_OK) {
|
||||
DEBUG("[sx1280] netdev: SX1280_IRQ_HEADER_VALID\n");
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_RX_STARTED);
|
||||
}
|
||||
else if (irq_mask & RAL_IRQ_RX_HDR_ERROR) {
|
||||
DEBUG("[sx1280] netdev: SX1280_IRQ_HEADER_ERROR\n");
|
||||
}
|
||||
else if (irq_mask & RAL_IRQ_RX_TIMEOUT) {
|
||||
DEBUG("[sx1280x] netdev: SX1280_IRQ_RX_TIMEOUT\n");
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_RX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
static int _get_state(sx1280_t *dev, void *val)
|
||||
{
|
||||
(void)dev;
|
||||
netopt_state_t state = NETOPT_STATE_OFF;
|
||||
sx1280_chip_status_t radio_status;
|
||||
|
||||
sx1280_get_status(dev, &radio_status);
|
||||
|
||||
switch (radio_status.chip_mode) {
|
||||
|
||||
case SX1280_CHIP_MODE_STBY_RC:
|
||||
/* Intentional fall-through */
|
||||
case SX1280_CHIP_MODE_STBY_XOSC:
|
||||
state = NETOPT_STATE_STANDBY;
|
||||
DEBUG("NETOPT_STATE_STANDBY ");
|
||||
break;
|
||||
|
||||
case SX1280_CHIP_MODE_RX:
|
||||
state = NETOPT_STATE_RX;
|
||||
DEBUG("NETOPT_STATE_RX ");
|
||||
break;
|
||||
case SX1280_CHIP_MODE_TX:
|
||||
state = NETOPT_STATE_TX;
|
||||
DEBUG("NETOPT_STATE_TX ");
|
||||
break;
|
||||
case SX1280_CHIP_MODE_FS:
|
||||
DEBUG("SX1280_CHIP_MODE_FS");
|
||||
/* Intentional fall-through */
|
||||
default:
|
||||
DEBUG("default");
|
||||
break;
|
||||
}
|
||||
memcpy(val, &state, sizeof(netopt_state_t));
|
||||
return sizeof(netopt_state_t);
|
||||
}
|
||||
|
||||
static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len)
|
||||
{
|
||||
(void)max_len; /* unused when compiled without debug, assert empty */
|
||||
sx1280_t *dev = (sx1280_t *)netdev;
|
||||
|
||||
if (dev == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case NETOPT_DEVICE_TYPE:
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)val) = NETDEV_TYPE_LORA;
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_STATE:
|
||||
assert(max_len >= sizeof(netopt_state_t));
|
||||
return _get_state(dev, val);
|
||||
|
||||
case NETOPT_CHANNEL_FREQUENCY:
|
||||
assert(max_len >= sizeof(uint32_t));
|
||||
*((uint32_t *)val) = sx1280_get_channel(dev);
|
||||
return sizeof(uint32_t);
|
||||
|
||||
case NETOPT_BANDWIDTH:
|
||||
assert(max_len >= sizeof(uint32_t));
|
||||
*((uint32_t *)val) = sx1280_get_bandwidth(dev);
|
||||
return sizeof(uint32_t);
|
||||
|
||||
case NETOPT_SPREADING_FACTOR:
|
||||
assert(max_len >= sizeof(uint8_t));
|
||||
*((uint8_t *)val) = sx1280_get_spreading_factor(dev);
|
||||
return sizeof(uint8_t);
|
||||
|
||||
case NETOPT_CODING_RATE:
|
||||
assert(max_len >= sizeof(uint8_t));
|
||||
*((uint8_t *)val) = sx1280_get_coding_rate(dev);
|
||||
return sizeof(uint8_t);
|
||||
|
||||
case NETOPT_PDU_SIZE:
|
||||
assert(max_len >= sizeof(uint8_t));
|
||||
*((uint8_t *)val) = sx1280_get_lora_payload_length(dev);
|
||||
return sizeof(uint8_t);
|
||||
|
||||
case NETOPT_INTEGRITY_CHECK:
|
||||
assert(max_len >= sizeof(netopt_enable_t));
|
||||
*((netopt_enable_t *)val) = sx1280_get_lora_crc(dev) ? NETOPT_ENABLE : NETOPT_DISABLE;
|
||||
return sizeof(netopt_enable_t);
|
||||
|
||||
case NETOPT_IQ_INVERT:
|
||||
assert(max_len >= sizeof(uint8_t));
|
||||
*((netopt_enable_t *)val) = sx1280_get_lora_iq_invert(dev) ? NETOPT_ENABLE : NETOPT_DISABLE;
|
||||
return sizeof(netopt_enable_t);
|
||||
|
||||
case NETOPT_RSSI:
|
||||
assert(max_len >= sizeof(int16_t));
|
||||
sx1280_get_rssi_inst(dev, ((int16_t *)val));
|
||||
return sizeof(int16_t);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int _set_state(sx1280_t *dev, netopt_state_t state)
|
||||
{
|
||||
(void)dev;
|
||||
switch (state) {
|
||||
case NETOPT_STATE_STANDBY:
|
||||
DEBUG("[sx1280] netdev: set NETOPT_STATE_STANDBY state\n");
|
||||
sx1280_set_standby(dev, SX1280_STANDBY_CFG_RC);
|
||||
break;
|
||||
|
||||
case NETOPT_STATE_IDLE:
|
||||
/* intentional fall-throught */
|
||||
case NETOPT_STATE_RX:
|
||||
DEBUG("[sx1280] netdev: set NETOPT_STATE_RX state\n");
|
||||
sx1280_set_rx(dev->ral.context, SX1280_TICK_SIZE_1000_US, SX1280_RX_MODE );
|
||||
break;
|
||||
|
||||
case NETOPT_STATE_TX:
|
||||
DEBUG("[sx1280] netdev: set NETOPT_STATE_TX state\n");
|
||||
sx1280_set_tx(dev->ral.context, SX1280_TICK_SIZE_1000_US, 0 );
|
||||
break;
|
||||
|
||||
case NETOPT_STATE_RESET:
|
||||
DEBUG("[sx1280] netdev: set NETOPT_STATE_RESET state\n");
|
||||
sx1280_reset(dev);
|
||||
sx1280_init(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
return sizeof(netopt_state_t);
|
||||
}
|
||||
|
||||
static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len)
|
||||
{
|
||||
(void)len; /* unused when compiled without debug, assert empty */
|
||||
sx1280_t *dev = (sx1280_t *)netdev;
|
||||
int res = -ENOTSUP;
|
||||
|
||||
if (dev == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case NETOPT_STATE:
|
||||
assert(len == sizeof(netopt_state_t));
|
||||
return _set_state(dev, *((const netopt_state_t *)val));
|
||||
|
||||
case NETOPT_CHANNEL_FREQUENCY:
|
||||
assert(len <= sizeof(uint32_t));
|
||||
uint32_t params_lora_bw = sx1280_get_bandwidth(dev);
|
||||
|
||||
uint32_t freq = *((const uint32_t *)val);
|
||||
uint32_t min_freq = (uint32_t)LORA_ISM2400_FREQUENCY_LOW + (params_lora_bw / 2);
|
||||
uint32_t max_freq = (uint32_t)LORA_ISM2400_FREQUENCY_HIGH - (params_lora_bw / 2);
|
||||
|
||||
if (freq < min_freq || freq > max_freq) {
|
||||
res = -EINVAL;
|
||||
break;
|
||||
}
|
||||
sx1280_set_channel(dev, *((const uint32_t *)val));
|
||||
return sizeof(uint32_t);
|
||||
|
||||
case NETOPT_BANDWIDTH:
|
||||
assert(len <= sizeof(uint16_t));
|
||||
uint16_t bw = *((const uint16_t *)val);
|
||||
switch (bw) {
|
||||
case 200: /* fall-through */
|
||||
case 400: /* fall-through */
|
||||
case 800: /* fall-through */
|
||||
case 1600:
|
||||
sx1280_set_bandwidth(dev, bw);
|
||||
return sizeof(uint16_t);
|
||||
default:
|
||||
res = -EINVAL;
|
||||
puts("invalid bandwidth, use 200, 400 , 800, 1600");
|
||||
break;
|
||||
}
|
||||
|
||||
break; /* outer switch*/
|
||||
|
||||
case NETOPT_SPREADING_FACTOR:
|
||||
assert(len <= sizeof(uint8_t));
|
||||
uint8_t sf = *((const uint8_t *)val);
|
||||
if ((sf < RAL_LORA_SF5) || (sf > RAL_LORA_SF12)) {
|
||||
res = -EINVAL;
|
||||
break;
|
||||
}
|
||||
sx1280_set_spreading_factor(dev, sf);
|
||||
return sizeof(uint8_t);
|
||||
|
||||
case NETOPT_CODING_RATE:
|
||||
assert(len <= sizeof(uint8_t));
|
||||
uint8_t cr = *((const uint8_t *)val);
|
||||
switch (cr) {
|
||||
case LORA_CR_4_5:
|
||||
cr = RAL_LORA_CR_4_5;
|
||||
break;
|
||||
case LORA_CR_4_6:
|
||||
cr = RAL_LORA_CR_4_6;
|
||||
break;
|
||||
case LORA_CR_4_7:
|
||||
cr = RAL_LORA_CR_4_7;
|
||||
break;
|
||||
case LORA_CR_4_8:
|
||||
cr = RAL_LORA_CR_4_8;
|
||||
break;
|
||||
case LORA_CR_LI_4_5:
|
||||
cr = RAL_LORA_CR_LI_4_5;
|
||||
break;
|
||||
case LORA_CR_LI_4_6:
|
||||
cr = RAL_LORA_CR_LI_4_6;
|
||||
break;
|
||||
case LORA_CR_LI_4_8:
|
||||
cr = RAL_LORA_CR_LI_4_8;
|
||||
break;
|
||||
default:
|
||||
res = -EINVAL;
|
||||
puts(
|
||||
"invalid cr, use\n \
|
||||
LORA_CR_4_5 = 1\n \
|
||||
LORA_CR_4_6 = 2\n \
|
||||
LORA_CR_4_7 = 3\n \
|
||||
LORA_CR_4_8 = 4\n \
|
||||
LORA_CR_LI_4_5 = 5\n \
|
||||
LORA_CR_LI_4_6 = 6\n \
|
||||
LORA_CR_LI_4_8 = 7\n");
|
||||
return res;
|
||||
|
||||
}
|
||||
sx1280_set_coding_rate(dev, cr);
|
||||
return sizeof(uint8_t);
|
||||
|
||||
case NETOPT_PDU_SIZE:
|
||||
assert(len <= sizeof(uint8_t));
|
||||
sx1280_set_lora_payload_length(dev, *((const uint8_t *)val));
|
||||
return sizeof(uint8_t);
|
||||
|
||||
case NETOPT_INTEGRITY_CHECK:
|
||||
assert(len <= sizeof(netopt_enable_t));
|
||||
sx1280_set_lora_crc(dev, *((const netopt_enable_t *)val) ? true : false);
|
||||
return sizeof(netopt_enable_t);
|
||||
|
||||
case NETOPT_PREAMBLE_LENGTH:
|
||||
assert(len <= sizeof(uint16_t));
|
||||
sx1280_set_lora_preamble_length(dev, *((const uint16_t *)val));
|
||||
return sizeof(uint16_t);
|
||||
|
||||
case NETOPT_IQ_INVERT:
|
||||
assert(len <= sizeof(netopt_enable_t));
|
||||
sx1280_set_lora_iq_invert(dev, *((const netopt_enable_t *)val) ? true : false);
|
||||
return sizeof(bool);
|
||||
|
||||
default:
|
||||
DEBUG(" OPT unrecognised (missing case) %i", opt);
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const netdev_driver_t sx1280_driver = {
|
||||
.send = _send,
|
||||
.recv = _recv,
|
||||
.init = _init,
|
||||
.isr = _isr,
|
||||
.get = _get,
|
||||
.set = _set,
|
||||
};
|
@ -38,6 +38,7 @@ rsource "libcose/Kconfig"
|
||||
rsource "libfixmath/Kconfig"
|
||||
rsource "libhydrogen/Kconfig"
|
||||
rsource "littlefs2/Kconfig"
|
||||
rsource "lorabasics/Kconfig"
|
||||
rsource "lora-serialization/Kconfig"
|
||||
rsource "lua/Kconfig"
|
||||
rsource "lv_drivers/Kconfig"
|
||||
|
33
pkg/lorabasics/Kconfig
Normal file
33
pkg/lorabasics/Kconfig
Normal file
@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2022 Inria
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU Lesser
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
config PACKAGE_LORABASICS
|
||||
bool "LoRa Basics"
|
||||
depends on TEST_KCONFIG
|
||||
# depends on HAS_ARCH_32_BIT
|
||||
select MODULE_LORABASICS_SMTC_RAL
|
||||
|
||||
if PACKAGE_LORABASICS
|
||||
|
||||
config MODULE_LORABASICS_SX1280_DRIVER
|
||||
bool "LoRaBasics SX1280 driver code"
|
||||
depends on HAS_PERIPH_SPI
|
||||
depends on HAS_PERIPH_GPIO
|
||||
depends on HAS_PERIPH_GPIO_IRQ
|
||||
select MODULE_PERIPH_SPI
|
||||
select MODULE_PERIPH_GPIO
|
||||
select MODULE_PERIPH_GPIO_IRQ
|
||||
select MODULE_ZTIMER
|
||||
select MODULE_ZTIMER_MSEC
|
||||
select MODULE_LORABASICS_DRIVER_SX1280_HAL
|
||||
|
||||
config MODULE_LORABASICS_DRIVER_SX1280_HAL
|
||||
bool "LoRaBasicsModem SX1280 driver hal"
|
||||
|
||||
config MODULE_LORABASICS_SMTC_RAL
|
||||
bool "LoRaBasicsModem Radio Abstraction Layer (RAL)"
|
||||
|
||||
endif # PACKAGE_LORABASICS
|
23
pkg/lorabasics/Makefile
Normal file
23
pkg/lorabasics/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
PKG_NAME=lorabasicsmodem
|
||||
PKG_URL=https://github.com/lorabasics/lorabasicsmodem.git
|
||||
PKG_VERSION=04e415bcfbdc7f1f4bff918a4867fab53bc8bb8a
|
||||
PKG_LICENSE=BSD
|
||||
|
||||
include $(RIOTBASE)/pkg/pkg.mk
|
||||
|
||||
CFLAGS += -Wno-error=unused-parameter
|
||||
CFLAGS += -Wno-error=unused-function
|
||||
|
||||
IGNORE_MODULES := lorabasics_driver_sx1280_hal
|
||||
#
|
||||
|
||||
LORABASICS_MODULES := $(filter-out $(IGNORE_MODULES),$(filter lorabasics%,$(USEMODULE)))
|
||||
|
||||
all: $(LORABASICS_MODULES)
|
||||
@true
|
||||
|
||||
lorabasics_smtc_ral:
|
||||
$(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR)/smtc_ral/src -f $(RIOTBASE)/Makefile.base MODULE=$@ SRC="ral.c ral_sx1280.c"
|
||||
|
||||
lorabasics_sx1280_driver:
|
||||
$(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR)/sx1280_driver/src -f $(RIOTBASE)/Makefile.base MODULE=$@
|
11
pkg/lorabasics/Makefile.dep
Normal file
11
pkg/lorabasics/Makefile.dep
Normal file
@ -0,0 +1,11 @@
|
||||
ifneq (,$(filter lorabasics_sx1280_driver,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += periph_gpio_irq
|
||||
FEATURES_REQUIRED += periph_spi
|
||||
|
||||
USEMODULE += ztimer_msec
|
||||
|
||||
USEMODULE += lorabasics_driver_sx1280_hal
|
||||
endif
|
||||
# This package has assumptions that only work for 32-bit architectures
|
||||
FEATURES_REQUIRED += arch_32bit
|
||||
USEMODULE += lorabasics_smtc_ral
|
11
pkg/lorabasics/Makefile.include
Normal file
11
pkg/lorabasics/Makefile.include
Normal file
@ -0,0 +1,11 @@
|
||||
INCLUDES += -I$(PKGDIRBASE)/lorabasicsmodem \
|
||||
#
|
||||
|
||||
ifneq (,$(filter lorabasics_driver_sx1280_hal,$(USEMODULE)))
|
||||
DIRS += $(RIOTBASE)/pkg/lorabasics/driver_sx1280_hal
|
||||
|
||||
# In the lorabasics package setting this define includes RAL code for the sx1280 radio
|
||||
CFLAGS += -DSX1280
|
||||
endif
|
||||
|
||||
PSEUDOMODULES += lorabasics
|
13
pkg/lorabasics/doc.txt
Normal file
13
pkg/lorabasics/doc.txt
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @defgroup pkg_lorabasicsmodem LoRa Basics
|
||||
* @ingroup pkg
|
||||
* @brief LoRa Basics Modem
|
||||
*
|
||||
* # HAL implementation for the SX1280 LoRa radio driver and vendor code for SX1280
|
||||
*
|
||||
* # License
|
||||
*
|
||||
* Licensed under BSD.
|
||||
*
|
||||
* @see git@github.com:lorabasics/lorabasicsmodem.git
|
||||
*/
|
3
pkg/lorabasics/driver_sx1280_hal/Makefile
Normal file
3
pkg/lorabasics/driver_sx1280_hal/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = lorabasics_driver_sx1280_hal
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
136
pkg/lorabasics/driver_sx1280_hal/driver_sx1280_hal.c
Normal file
136
pkg/lorabasics/driver_sx1280_hal/driver_sx1280_hal.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Inria
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup pkg_lorabasicsmodem
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief HAL implementation for the SX1280 LoRa radio driver
|
||||
*
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
* @author Nicolas Albarel <nicolas.albarel@univ-grenoble-alpes.fr>
|
||||
* @author Didier Donsez <didier.donsez@univ-grenoble-alpes.fr>
|
||||
* @author Olivier Alphand <olivier.alphand@univ-grenoble-alpes.fr>
|
||||
* @author Aymeric Brochier <aymeric.brochier@univ-grenoble-alpes.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "irq.h"
|
||||
#include "periph/spi.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#include "sx1280.h"
|
||||
#include "sx1280_constants.h"
|
||||
#include "sx1280_driver/src/sx1280_hal.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief Wait until radio busy pin is reset to 0
|
||||
*/
|
||||
static void sx1280_hal_wait_on_busy(const void *context)
|
||||
{
|
||||
sx1280_t *dev = (sx1280_t *)context;
|
||||
|
||||
while (gpio_read(dev->params->dio0_pin)) {}
|
||||
}
|
||||
|
||||
sx1280_hal_status_t sx1280_hal_write(const void *context, const uint8_t *command,
|
||||
const uint16_t command_length,
|
||||
const uint8_t *data, const uint16_t data_length)
|
||||
{
|
||||
sx1280_t *dev = (sx1280_t *)context;
|
||||
|
||||
sx1280_hal_wakeup(context);
|
||||
|
||||
DEBUG("[sx1280_hal_write]: command_length=%d data_length=%d\n", command_length, data_length);
|
||||
|
||||
spi_acquire(dev->params->spi, SPI_CS_UNDEF, dev->params->spi_mode, dev->params->spi_clk);
|
||||
spi_transfer_bytes(dev->params->spi, dev->params->nss_pin, data_length != 0,
|
||||
command, NULL, command_length);
|
||||
if (data_length) {
|
||||
spi_transfer_bytes(dev->params->spi, dev->params->nss_pin, false, data,
|
||||
NULL, data_length);
|
||||
}
|
||||
spi_release(dev->params->spi);
|
||||
|
||||
/* 0x84 - SX1280_SET_SLEEP opcode. In sleep mode the radio dio is stuck
|
||||
to 1 => do not test it */
|
||||
if (command[0] != 0x84) {
|
||||
sx1280_hal_wait_on_busy(context);
|
||||
}
|
||||
return SX1280_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
sx1280_hal_status_t sx1280_hal_read(const void *context, const uint8_t *command,
|
||||
const uint16_t command_length,
|
||||
uint8_t *data, const uint16_t data_length)
|
||||
{
|
||||
sx1280_t *dev = (sx1280_t *)context;
|
||||
|
||||
sx1280_hal_wakeup(context);
|
||||
|
||||
spi_acquire(dev->params->spi, SPI_CS_UNDEF, dev->params->spi_mode, dev->params->spi_clk);
|
||||
spi_transfer_bytes(dev->params->spi, dev->params->nss_pin, true, \
|
||||
command, NULL, command_length);
|
||||
spi_transfer_bytes(dev->params->spi, dev->params->nss_pin, false, \
|
||||
NULL, data, data_length);
|
||||
spi_release(dev->params->spi);
|
||||
|
||||
return SX1280_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
void sx1280_hal_reset( const void *context )
|
||||
{
|
||||
sx1280_t *dev = (sx1280_t *)context;
|
||||
|
||||
gpio_clear(dev->params->reset_pin);
|
||||
ztimer_sleep(ZTIMER_MSEC, SX1280_RESET_MS);
|
||||
gpio_set(dev->params->reset_pin);
|
||||
ztimer_sleep(ZTIMER_MSEC, SX1280_WAKEUP_TIME_MS);
|
||||
}
|
||||
|
||||
sx1280_hal_status_t sx1280_hal_wakeup(const void *context)
|
||||
{
|
||||
sx1280_t *dev = (sx1280_t *)context;
|
||||
|
||||
if (dev->mode == SX1280_HAL_OP_MODE_SLEEP) {
|
||||
/* Busy is HIGH in sleep mode, wake-up the device */
|
||||
gpio_clear(dev->params->nss_pin);
|
||||
sx1280_hal_wait_on_busy(context);
|
||||
gpio_set(dev->params->nss_pin);
|
||||
|
||||
/* Radio is awake in STDBY_RC mode */
|
||||
dev->mode = SX1280_HAL_OP_MODE_STDBY_RC;
|
||||
}
|
||||
else {
|
||||
/* if the radio is awake, just wait until busy pin get low */
|
||||
sx1280_hal_wait_on_busy(context);
|
||||
}
|
||||
|
||||
return SX1280_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
sx1280_hal_operating_mode_t sx1280_hal_get_operating_mode(const void *context)
|
||||
{
|
||||
sx1280_t *dev = (sx1280_t *)context;
|
||||
|
||||
return dev->mode;
|
||||
}
|
||||
|
||||
void sx1280_hal_set_operating_mode(const void *context, const sx1280_hal_operating_mode_t op_mode)
|
||||
{
|
||||
sx1280_t *dev = (sx1280_t *)context;
|
||||
|
||||
dev->mode = op_mode;
|
||||
}
|
Binary file not shown.
BIN
pkg/lorabasics/patches/0002-treewide-fix-include-paths.patch
Normal file
BIN
pkg/lorabasics/patches/0002-treewide-fix-include-paths.patch
Normal file
Binary file not shown.
@ -75,6 +75,14 @@ extern "C" {
|
||||
#define CONFIG_LORA_BW_DEFAULT (LORA_BW_250_KHZ)
|
||||
#elif IS_ACTIVE(CONFIG_LORA_BW_DEFAULT_500)
|
||||
#define CONFIG_LORA_BW_DEFAULT (LORA_BW_500_KHZ)
|
||||
#elif IS_ACTIVE(CONFIG_LORA_BW_DEFAULT_200)
|
||||
#define CONFIG_LORA_BW_DEFAULT (LORA_BW_200_KHZ)
|
||||
#elif IS_ACTIVE(CONFIG_LORA_BW_DEFAULT_400)
|
||||
#define CONFIG_LORA_BW_DEFAULT (LORA_BW_400_KHZ)
|
||||
#elif IS_ACTIVE(CONFIG_LORA_BW_DEFAULT_800)
|
||||
#define CONFIG_LORA_BW_DEFAULT (LORA_BW_800_KHZ)
|
||||
#elif IS_ACTIVE(CONFIG_LORA_BW_DEFAULT_1600)
|
||||
#define CONFIG_LORA_BW_DEFAULT (LORA_BW_1600_KHZ)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_LORA_BW_DEFAULT
|
||||
@ -131,6 +139,12 @@ extern "C" {
|
||||
#define CONFIG_LORA_CR_DEFAULT (LORA_CR_4_7)
|
||||
#elif IS_ACTIVE(CONFIG_LORA_CR_DEFAULT_CR_4_8)
|
||||
#define CONFIG_LORA_CR_DEFAULT (LORA_CR_4_8)
|
||||
#elif IS_ACTIVE(CONFIG_LORA_CR_DEFAULT_CR_LI_4_5)
|
||||
#define CONFIG_LORA_CR_DEFAULT (LORA_CR_LI_4_5)
|
||||
#elif IS_ACTIVE(CONFIG_LORA_CR_DEFAULT_CR_LI_4_6)
|
||||
#define CONFIG_LORA_CR_DEFAULT (LORA_CR_LI_4_6)
|
||||
#elif IS_ACTIVE(CONFIG_LORA_CR_DEFAULT_CR_LI_4_8)
|
||||
#define CONFIG_LORA_CR_DEFAULT (LORA_CR_LI_4_8)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_LORA_CR_DEFAULT
|
||||
@ -201,6 +215,18 @@ extern "C" {
|
||||
*/
|
||||
#define LORA_SYNCWORD_PUBLIC (0x34) /**< Syncword used for public networks */
|
||||
#define LORA_SYNCWORD_PRIVATE (0x12) /**< Syncword used for private networks */
|
||||
/* see https://lora-developers.semtech.com/documentation/tech-papers-and-guides/physical-layer-proposal-2.4ghz */
|
||||
#define LORA_SYNCWORD_ISM2400_PUBLIC (0x21) /**< Syncword used for public networks on ISM2400 */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name LoRa 2.4Ghz band frequency definitions
|
||||
*
|
||||
* See https://lora-developers.semtech.com/documentation/tech-papers-and-guides/physical-layer-proposal-2.4ghz/
|
||||
* @{
|
||||
*/
|
||||
#define LORA_ISM2400_FREQUENCY_LOW 2400000000 /**< lowest frequency ISM24000 band */
|
||||
#define LORA_ISM2400_FREQUENCY_HIGH 2500000000 /**< highest frequency ISM24000 band */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -213,14 +239,19 @@ extern "C" {
|
||||
enum {
|
||||
LORA_BW_125_KHZ = 0, /**< 125 kHz bandwidth */
|
||||
LORA_BW_250_KHZ, /**< 250 kHz bandwidth */
|
||||
LORA_BW_500_KHZ /**< 500 kHz bandwidth */
|
||||
LORA_BW_500_KHZ, /**< 500 kHz bandwidth */
|
||||
LORA_BW_200_KHZ, /**< 200 kHz bandwidth, only 2.4Ghz */
|
||||
LORA_BW_400_KHZ, /**< 400 kHz bandwidth, only 2.4Ghz */
|
||||
LORA_BW_800_KHZ, /**< 800 kHz bandwidth, only 2.4Ghz */
|
||||
LORA_BW_1600_KHZ, /**< 1600 kHz bandwidth, only 2.4Ghz */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief LoRa modulation spreading factor rate
|
||||
*/
|
||||
enum {
|
||||
LORA_SF6 = 6, /**< spreading factor 6 */
|
||||
LORA_SF5 = 5, /**< spreading factor 5, sx126x and sx1280 */
|
||||
LORA_SF6, /**< spreading factor 6 */
|
||||
LORA_SF7, /**< spreading factor 7 */
|
||||
LORA_SF8, /**< spreading factor 8 */
|
||||
LORA_SF9, /**< spreading factor 9 */
|
||||
@ -236,7 +267,10 @@ enum {
|
||||
LORA_CR_4_5 = 1, /**< coding rate 4/5 */
|
||||
LORA_CR_4_6, /**< coding rate 4/6 */
|
||||
LORA_CR_4_7, /**< coding rate 4/7 */
|
||||
LORA_CR_4_8 /**< coding rate 4/8 */
|
||||
LORA_CR_4_8, /**< coding rate 4/8 */
|
||||
LORA_CR_LI_4_5, /**< coding rate long interleaving 4/5 */
|
||||
LORA_CR_LI_4_6, /**< coding rate long interleaving 4/6 */
|
||||
LORA_CR_LI_4_8 /**< coding rate long interleaving 4/8 */
|
||||
};
|
||||
/** @} */
|
||||
|
||||
|
13
tests/driver_sx1280/Makefile
Normal file
13
tests/driver_sx1280/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
BOARD ?= nucleo-f103rb
|
||||
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# required modules
|
||||
USEMODULE += sx1280
|
||||
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
|
||||
USEMODULE += iolist
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
5
tests/driver_sx1280/Makefile.ci
Normal file
5
tests/driver_sx1280/Makefile.ci
Normal file
@ -0,0 +1,5 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
nucleo-l011k4 \
|
||||
stm32f030f4-demo \
|
||||
samd10-xmini \
|
||||
#
|
172
tests/driver_sx1280/README.md
Normal file
172
tests/driver_sx1280/README.md
Normal file
@ -0,0 +1,172 @@
|
||||
## About
|
||||
|
||||
This is a manual test application for the SX1280 radio driver.
|
||||
|
||||
This manual test application was also tested with a custom board (esp32-wroom-32 + lambda80C-24S on Mikrobus_0) :
|
||||
see https://github.com/thingsat/tinygs_2g4station
|
||||
|
||||
If you have other hardware (boards, Semtech based LoRa module), you can adapt
|
||||
the configuration to your needs by copying an adapted version of
|
||||
`drivers/sx1280/include/sx1280_params.h` file to your application directory.
|
||||
|
||||
## Build and Flash
|
||||
|
||||
```shell
|
||||
cd tests/driver_sx1280
|
||||
make flash term
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
This test application provides low level shell commands to interact with the
|
||||
SX1280 module.
|
||||
|
||||
Once the board is flashed and you are connected via serial to the shell, use the `help`
|
||||
command to display the available commands:
|
||||
|
||||
```
|
||||
> help
|
||||
2022-05-09 10:27:13,724 # help
|
||||
2022-05-09 10:27:13,731 # Command Description
|
||||
2022-05-09 10:27:13,731 # ---------------------------------------
|
||||
2022-05-09 10:27:13,735 # sx1280 Control the SX1280 radio
|
||||
2022-05-09 10:27:13,738 # reboot Reboot the node
|
||||
2022-05-09 10:27:13,742 # version Prints current RIOT_VERSION
|
||||
2022-05-09 10:27:13,747 # pm interact with layered PM subsystem
|
||||
```
|
||||
|
||||
### Getter
|
||||
|
||||
```
|
||||
2022-04-28 15:00:32,795 # main(): This is RIOT! (Version: 2021.10-devel-3491-g23b57-pr/sx1280_v2)
|
||||
2022-04-28 15:00:32,806 # Initialization successful - starting the shell now
|
||||
> sx1280
|
||||
2022-04-28 15:00:39,408 # sx1280
|
||||
2022-04-28 15:00:39,409 # Usage: sx1280 <get|set|rx|tx|reset>
|
||||
> sx1280 get
|
||||
2022-04-28 15:00:44,808 # sx1280 get
|
||||
2022-04-28 15:00:44,809 # Usage: sx1280 get <type|freq|bw|sf|cr>
|
||||
> sx1280 get type
|
||||
2022-04-28 15:00:48,064 # sx1280 get type
|
||||
2022-04-28 15:00:48,065 # Device type: lora
|
||||
> sx1280 get freq
|
||||
2022-04-28 15:00:52,639 # sx1280 get freq
|
||||
2022-04-28 15:00:52,639 # Frequency: 2403000000 Hz
|
||||
> sx1280 get bw
|
||||
2022-04-28 15:00:57,130 # sx1280 get bw
|
||||
2022-04-28 15:00:57,131 # Bandwidth: 800 kHz
|
||||
> sx1280 get sf
|
||||
2022-04-28 15:01:01,476 # sx1280 get sf
|
||||
2022-04-28 15:01:01,477 # Spreading factor: 12
|
||||
2022-04-28 15:01:10,159 # sx1280 get cr
|
||||
2022-04-28 15:01:10,165 # Coding rate: 6
|
||||
2022-04-28 15:01:10,165 # Usage: use
|
||||
2022-04-28 15:01:10,166 # LORA_CR_4_5 = 1
|
||||
2022-04-28 15:01:10,166 # LORA_CR_4_6 = 2
|
||||
2022-04-28 15:01:10,167 # LORA_CR_4_7 = 3
|
||||
2022-04-28 15:01:10,167 # LORA_CR_4_8 = 4
|
||||
2022-04-28 15:01:10,169 # LORA_CR_LI_4_5 = 5
|
||||
2022-04-28 15:01:10,170 # LORA_CR_LI_4_6 = 6
|
||||
2022-04-28 15:01:10,171 # LORA_CR_LI_4_8 = 7
|
||||
```
|
||||
|
||||
### Setter
|
||||
|
||||
```
|
||||
2022-04-28 16:30:53,635 # sx1280
|
||||
2022-04-28 16:30:53,642 # Usage: sx1280 <get|set|rx|tx>
|
||||
> sx1280 set
|
||||
2022-04-28 16:30:56,504 # sx1280 set
|
||||
2022-04-28 16:30:56,505 # Usage: sx1280 set <freq|bw|sf|cr|> <value>
|
||||
> sx1280 freq
|
||||
2022-04-28 16:31:02,802 # sx1280 freq
|
||||
> sx1280 set freq
|
||||
2022-04-28 16:31:12,282 # sx1280 set freq
|
||||
2022-04-28 16:31:12,287 # Usage: use freq between 2400000000 + (bw/2) and 2500000000 - (bw/2) (Hz) !
|
||||
2022-04-28 16:31:12,290 # Usage: sx1280 set <freq|bw|sf|cr|> <value>
|
||||
> sx1280 set bw
|
||||
2022-04-28 16:31:18,924 # sx1280 set bw
|
||||
2022-04-28 16:31:18,925 # Usage: use 200, 400, 800, 1600 (kHz)
|
||||
2022-04-28 16:31:18,929 # Usage: sx1280 set <freq|bw|sf|cr|> <value>
|
||||
> sx1280 set sf
|
||||
2022-04-28 16:31:23,232 # sx1280 set sf
|
||||
2022-04-28 16:31:23,233 # Usage: use SF between 5 and 12
|
||||
2022-04-28 16:31:23,236 # Usage: sx1280 set <freq|bw|sf|cr|> <value>
|
||||
> sx1280 set cr
|
||||
2022-04-28 15:01:10,159 # sx1280 set cr
|
||||
2022-04-28 15:01:10,165 # Usage: use
|
||||
2022-04-28 15:01:10,166 # LORA_CR_4_5 = 1
|
||||
2022-04-28 15:01:10,166 # LORA_CR_4_6 = 2
|
||||
2022-04-28 15:01:10,167 # LORA_CR_4_7 = 3
|
||||
2022-04-28 15:01:10,167 # LORA_CR_4_8 = 4
|
||||
2022-04-28 15:01:10,169 # LORA_CR_LI_4_5 = 5
|
||||
2022-04-28 15:01:10,170 # LORA_CR_LI_4_6 = 6
|
||||
2022-04-28 15:01:10,171 # LORA_CR_LI_4_8 = 7
|
||||
> sx1280 set cr 6
|
||||
2022-04-28 15:01:12,359 # sx1280 set cr 6
|
||||
2022-04-28 15:01:12,362 # cr set
|
||||
|
||||
2022-04-28 16:31:27,001 # Usage: sx1280 set <freq|bw|sf|cr|> <value>
|
||||
> sx1280 set freq 2455555555
|
||||
2022-04-28 16:32:20,235 # sx1280 set freq 2455555555
|
||||
2022-04-28 16:32:20,236 # freq set
|
||||
> sx1280 set bw 200
|
||||
2022-04-28 16:32:29,468 # sx1280 set bw 200
|
||||
2022-04-28 16:32:29,468 # setup: setting 200KHz bandwidth
|
||||
2022-04-28 16:32:29,469 # bw set
|
||||
> sx1280 set sf 5
|
||||
2022-04-28 16:32:35,138 # sx1280 set sf 5
|
||||
2022-04-28 16:32:35,141 # sf set
|
||||
> sx1280 set cr 4
|
||||
2022-04-28 16:32:40,970 # sx1280 set cr 4
|
||||
2022-04-28 16:32:40,973 # cr set
|
||||
|
||||
sx1280 reset
|
||||
2022-05-17 13:36:54,836 # sx1280 reset
|
||||
2022-05-17 13:36:54,836 # resetting sx1280...
|
||||
```
|
||||
|
||||
### TX/RX
|
||||
|
||||
Once we have a shell on both card we can use the shell cmd :
|
||||
|
||||
```
|
||||
2022-04-28 16:26:48,034 # main(): This is RIOT! (Version: 2021.10-devel-3491-g23b57-pr/sx1280_v2)
|
||||
2022-04-28 16:26:48,046 # Initialization successful - starting the shell now
|
||||
help
|
||||
2022-04-28 16:27:23,060 # help
|
||||
2022-04-28 16:27:23,061 # Command Description
|
||||
2022-04-28 16:27:23,066 # ---------------------------------------
|
||||
2022-04-28 16:27:23,067 # sx1280 Control the SX1280 radio
|
||||
2022-04-28 16:27:23,072 # reboot Reboot the node
|
||||
2022-04-28 16:27:23,077 # version Prints current RIOT_VERSION
|
||||
2022-04-28 16:27:23,082 # pm interact with layered PM subsystem
|
||||
2022-04-28 16:27:23,085 # ps Prints information about running threads.
|
||||
> sx1280
|
||||
2022-04-28 16:27:27,574 # sx1280
|
||||
2022-04-28 16:27:27,575 # Usage: sx1280 <get|set|rx|tx>
|
||||
> sx1280 tx
|
||||
2022-04-28 16:27:30,710 # sx1280 tx
|
||||
2022-04-28 16:27:30,711 # Usage: sx1280 tx <payload>
|
||||
> sx1280 tx test_default_params
|
||||
2022-04-28 16:28:00,452 # sx1280 tx test_default_params
|
||||
2022-04-28 16:28:00,455 # sending "test_default_params" payload (20 bytes)
|
||||
> 2022-04-28 16:28:00,718 # Transmission completed
|
||||
```
|
||||
|
||||
```
|
||||
2022-04-28 16:26:43,538 # Connect to serial port /dev/tty.usbserial-14620
|
||||
Welcome to pyterm!
|
||||
Type '/exit' to exit.
|
||||
sx1280
|
||||
2022-04-28 16:27:49,686 # sx1280
|
||||
2022-04-28 16:27:49,687 # Usage: sx1280 <get|set|rx|tx>
|
||||
> sx1280 rx
|
||||
2022-04-28 16:27:53,657 # sx1280 rx
|
||||
2022-04-28 16:27:53,657 # Usage: sx1280 rx <start|stop>
|
||||
> sx1280 rx start
|
||||
2022-04-28 16:27:56,596 # sx1280 rx start
|
||||
2022-04-28 16:27:56,600 # Listen mode started
|
||||
> 2022-04-28 16:28:00,562 # Data reception started
|
||||
2022-04-28 16:28:00,726 # Received: "test_default_params" (20 bytes) - [RSSI: -43, SNR: 8]
|
||||
```
|
8
tests/driver_sx1280/app.config.test
Normal file
8
tests/driver_sx1280/app.config.test
Normal file
@ -0,0 +1,8 @@
|
||||
# this file enables modules defined in Kconfig. Do not use this file for
|
||||
# application configuration. This is only needed during migration.
|
||||
CONFIG_MODULE_SX1280=y
|
||||
|
||||
CONFIG_MODULE_IOLIST=y
|
||||
|
||||
CONFIG_MODULE_SHELL=y
|
||||
CONFIG_MODULE_SHELL_COMMANDS=y
|
379
tests/driver_sx1280/main.c
Normal file
379
tests/driver_sx1280/main.c
Normal file
@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Inria
|
||||
* Copyright (C) 2020-2022 Université Grenoble Alpes
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Test Application For SX1280 Driver
|
||||
*
|
||||
* @author Aymeric Brochier <aymeric.brochier@univ-grenoble-alpes.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "msg.h"
|
||||
#include "thread.h"
|
||||
#include "shell.h"
|
||||
|
||||
#include "net/lora.h"
|
||||
#include "net/netdev.h"
|
||||
#include "net/netdev/lora.h"
|
||||
|
||||
#include "sx1280.h"
|
||||
#include "sx1280_params.h"
|
||||
#include "sx1280_netdev.h"
|
||||
|
||||
#define SX1280_MSG_QUEUE (8U)
|
||||
#define SX1280_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
|
||||
#define SX1280_MSG_TYPE_ISR (0x3456)
|
||||
#define SX1280_MAX_PAYLOAD_LEN (128U)
|
||||
|
||||
static char stack[SX1280_STACKSIZE];
|
||||
static kernel_pid_t _recv_pid;
|
||||
|
||||
static char message[SX1280_MAX_PAYLOAD_LEN];
|
||||
|
||||
static sx1280_t sx1280;
|
||||
|
||||
static void _event_cb(netdev_t *dev, netdev_event_t event)
|
||||
{
|
||||
if (event == NETDEV_EVENT_ISR) {
|
||||
msg_t msg;
|
||||
msg.type = SX1280_MSG_TYPE_ISR;
|
||||
if (msg_send(&msg, _recv_pid) <= 0) {
|
||||
puts("sx1280_netdev: possibly lost interrupt.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (event) {
|
||||
case NETDEV_EVENT_RX_STARTED:
|
||||
puts("Data reception started");
|
||||
break;
|
||||
|
||||
case NETDEV_EVENT_RX_COMPLETE:
|
||||
{
|
||||
size_t len = dev->driver->recv(dev, NULL, 0, 0);
|
||||
netdev_lora_rx_info_t packet_info;
|
||||
dev->driver->recv(dev, message, len, &packet_info);
|
||||
printf(
|
||||
"Received: \"%s\" (%d bytes) - [RSSI: %i, SNR: %i]\n",
|
||||
message, (int)len, packet_info.rssi, (int)packet_info.snr);
|
||||
}
|
||||
break;
|
||||
|
||||
case NETDEV_EVENT_TX_COMPLETE:
|
||||
puts("Transmission completed");
|
||||
break;
|
||||
|
||||
case NETDEV_EVENT_TX_TIMEOUT:
|
||||
puts("Transmission timeout");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unexpected netdev event received: %d\n", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *_recv_thread(void *arg)
|
||||
{
|
||||
netdev_t *netdev = arg;
|
||||
|
||||
static msg_t _msg_queue[SX1280_MSG_QUEUE];
|
||||
|
||||
msg_init_queue(_msg_queue, SX1280_MSG_QUEUE);
|
||||
|
||||
while (1) {
|
||||
msg_t msg;
|
||||
msg_receive(&msg);
|
||||
if (msg.type == SX1280_MSG_TYPE_ISR) {
|
||||
netdev->driver->isr(netdev);
|
||||
}
|
||||
else {
|
||||
puts("Unexpected msg type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _get_usage(const char *cmd)
|
||||
{
|
||||
printf("Usage: %s get <type|freq|bw|sf|cr>\n", cmd);
|
||||
}
|
||||
|
||||
|
||||
static void _usage_freq(void)
|
||||
{
|
||||
printf("Usage: use freq between 2400000000 + (bw/2) and 2500000000 - (bw/2) (Hz) !\n");
|
||||
}
|
||||
|
||||
static void _usage_bw(void)
|
||||
{
|
||||
printf("Usage: use 200, 400, 800, 1600 (kHz)\n");
|
||||
}
|
||||
|
||||
static void _usage_sf(void)
|
||||
{
|
||||
printf("Usage: use SF between 5 and 12\n");
|
||||
}
|
||||
|
||||
static void _usage_cr(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: use\n \
|
||||
LORA_CR_4_5 = 1\n \
|
||||
LORA_CR_4_6 = 2\n \
|
||||
LORA_CR_4_7 = 3\n \
|
||||
LORA_CR_4_8 = 4\n \
|
||||
LORA_CR_LI_4_5 = 5\n \
|
||||
LORA_CR_LI_4_6 = 6\n \
|
||||
LORA_CR_LI_4_8 = 7\n");
|
||||
}
|
||||
|
||||
|
||||
static int sx1280_get_cmd(netdev_t *netdev, int argc, char **argv)
|
||||
{
|
||||
if (argc == 2) {
|
||||
_get_usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp("type", argv[2])) {
|
||||
uint16_t type;
|
||||
netdev->driver->get(netdev, NETOPT_DEVICE_TYPE, &type, sizeof(uint16_t));
|
||||
printf("Device type: %s\n", (type == NETDEV_TYPE_LORA) ? "lora" : "fsk");
|
||||
}
|
||||
else if (!strcmp("freq", argv[2])) {
|
||||
uint32_t freq;
|
||||
netdev->driver->get(netdev, NETOPT_CHANNEL_FREQUENCY, &freq, sizeof(uint32_t));
|
||||
printf("Frequency: %" PRIu32 " Hz\n", freq);
|
||||
}
|
||||
else if (!strcmp("bw", argv[2])) {
|
||||
uint32_t bw_val = 0;
|
||||
netdev->driver->get(netdev, NETOPT_BANDWIDTH, &bw_val, sizeof(uint32_t));
|
||||
printf("Bandwidth: %" PRIu32 " kHz\n", bw_val / 1000);
|
||||
}
|
||||
else if (!strcmp("sf", argv[2])) {
|
||||
uint8_t sf;
|
||||
netdev->driver->get(netdev, NETOPT_SPREADING_FACTOR, &sf, sizeof(uint8_t));
|
||||
printf("Spreading factor: %d\n", sf);
|
||||
}
|
||||
else if (!strcmp("cr", argv[2])) {
|
||||
uint8_t cr;
|
||||
netdev->driver->get(netdev, NETOPT_CODING_RATE, &cr, sizeof(uint8_t));
|
||||
printf("Coding rate: %d\n", cr);
|
||||
_usage_cr();
|
||||
}
|
||||
else {
|
||||
_get_usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _set_usage(const char *cmd)
|
||||
{
|
||||
printf("Usage: %s set <freq|bw|sf|cr|> <value>\n", cmd);
|
||||
}
|
||||
|
||||
static int sx1280_set_cmd(netdev_t *netdev, int argc, char **argv)
|
||||
{
|
||||
if (argc == 3) {
|
||||
if (!strcmp("freq", argv[2])) {
|
||||
_usage_freq();
|
||||
}
|
||||
if (!strcmp("bw", argv[2])) {
|
||||
_usage_bw();
|
||||
}
|
||||
if (!strcmp("sf", argv[2])) {
|
||||
_usage_sf();
|
||||
}
|
||||
if (!strcmp("cr", argv[2])) {
|
||||
_usage_cr();
|
||||
}
|
||||
}
|
||||
if (argc != 4) {
|
||||
_set_usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (!strcmp("freq", argv[2])) {
|
||||
uint32_t freq = strtoul(argv[3], NULL, 10);
|
||||
ret = netdev->driver->set(netdev, NETOPT_CHANNEL_FREQUENCY, &freq, sizeof(uint32_t));
|
||||
}
|
||||
else if (!strcmp("bw", argv[2])) {
|
||||
uint16_t bw = atoi(argv[3]);
|
||||
ret = netdev->driver->set(netdev, NETOPT_BANDWIDTH, &bw, sizeof(uint16_t));
|
||||
}
|
||||
else if (!strcmp("sf", argv[2])) {
|
||||
uint8_t sf = atoi(argv[3]);
|
||||
ret = netdev->driver->set(netdev, NETOPT_SPREADING_FACTOR, &sf, sizeof(uint8_t));
|
||||
}
|
||||
else if (!strcmp("cr", argv[2])) {
|
||||
uint8_t cr = atoi(argv[3]);
|
||||
ret = netdev->driver->set(netdev, NETOPT_CODING_RATE, &cr, sizeof(uint8_t));
|
||||
}
|
||||
else {
|
||||
_set_usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
printf("cannot set %s\n", argv[2]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
printf("%s set\n", argv[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _rx_usage(const char *cmd)
|
||||
{
|
||||
printf("Usage: %s rx <start|stop>\n", cmd);
|
||||
}
|
||||
|
||||
static int sx1280_rx_cmd(netdev_t *netdev, int argc, char **argv)
|
||||
{
|
||||
if (argc == 2) {
|
||||
_rx_usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp("start", argv[2])) {
|
||||
/* Switch to RX (IDLE) state */
|
||||
netopt_state_t state = NETOPT_STATE_IDLE;
|
||||
netdev->driver->set(netdev, NETOPT_STATE, &state, sizeof(state));
|
||||
printf("Listen mode started\n");
|
||||
}
|
||||
else if (!strcmp("stop", argv[2])) {
|
||||
/* Switch to STANDBY state */
|
||||
netopt_state_t state = NETOPT_STATE_STANDBY;
|
||||
netdev->driver->set(netdev, NETOPT_STATE, &state, sizeof(state));
|
||||
printf("Listen mode stopped\n");
|
||||
}
|
||||
else {
|
||||
_rx_usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sx1280_tx_cmd(netdev_t *netdev, int argc, char **argv)
|
||||
{
|
||||
if (argc == 2) {
|
||||
printf("Usage: %s tx <payload>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("sending \"%s\" payload (%u bytes)\n",
|
||||
argv[2], (unsigned)strlen(argv[2]) + 1);
|
||||
iolist_t iolist = {
|
||||
.iol_base = argv[2],
|
||||
.iol_len = (strlen(argv[2]) + 1)
|
||||
};
|
||||
|
||||
if (netdev->driver->send(netdev, &iolist) == -ENOTSUP) {
|
||||
puts("Cannot send: radio is still transmitting");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sx1280_reset_cmd(netdev_t *netdev, int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
puts("resetting sx1280...");
|
||||
netopt_state_t state = NETOPT_STATE_RESET;
|
||||
|
||||
netdev->driver->set(netdev, NETOPT_STATE, &state, sizeof(netopt_state_t));
|
||||
return 0;
|
||||
|
||||
}
|
||||
int sx1280_cmd(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <get|set|rx|tx|reset>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
netdev_t *netdev = &sx1280.netdev;
|
||||
|
||||
if (!strcmp("get", argv[1])) {
|
||||
return sx1280_get_cmd(netdev, argc, argv);
|
||||
}
|
||||
else if (!strcmp("set", argv[1])) {
|
||||
return sx1280_set_cmd(netdev, argc, argv);
|
||||
}
|
||||
else if (!strcmp("rx", argv[1])) {
|
||||
return sx1280_rx_cmd(netdev, argc, argv);
|
||||
}
|
||||
else if (!strcmp("tx", argv[1])) {
|
||||
return sx1280_tx_cmd(netdev, argc, argv);
|
||||
}
|
||||
else if (!strcmp("reset", argv[1])) {
|
||||
return sx1280_reset_cmd(netdev, argc, argv);
|
||||
}
|
||||
else {
|
||||
printf("Unknown cmd %s\n", argv[1]);
|
||||
printf("Usage: %s <get|set|rx|tx|reset>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "sx1280", "Control the SX1280 radio", sx1280_cmd },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
sx1280_setup(&sx1280, &sx1280_params[0], 0);
|
||||
|
||||
netdev_t *netdev = &sx1280.netdev;
|
||||
|
||||
netdev->driver = &sx1280_driver;
|
||||
|
||||
if (netdev->driver->init(netdev) < 0) {
|
||||
puts("Failed to initialize SX1280 device, exiting");
|
||||
return 1;
|
||||
}
|
||||
|
||||
netdev->event_callback = _event_cb;
|
||||
|
||||
_recv_pid = thread_create(stack, sizeof(stack), THREAD_PRIORITY_MAIN - 1,
|
||||
THREAD_CREATE_STACKTEST, _recv_thread, netdev,
|
||||
"recv_thread");
|
||||
|
||||
if (_recv_pid <= KERNEL_PID_UNDEF) {
|
||||
puts("Creation of receiver thread failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts("Initialization successful - starting the shell now");
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user