diff --git a/cpu/cc2538/radio/cc2538_rf_getset.c b/cpu/cc2538/radio/cc2538_rf_getset.c index 309275d9b6283cf85fc4fab5748437d20f0d34f3..658e02a092bbd307c0eb8796f1737e9c3a64c13d 100644 --- a/cpu/cc2538/radio/cc2538_rf_getset.c +++ b/cpu/cc2538/radio/cc2538_rf_getset.c @@ -230,6 +230,8 @@ void cc2538_set_state(cc2538_rf_t *dev, netopt_state_t state) RFCORE_WAIT_UNTIL(RFCORE->XREG_FSMSTAT0bits.FSM_FFCTRL_STATE > FSM_STATE_RX_CALIBRATION); dev->state = NETOPT_STATE_IDLE; break; + default: + break; } } diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index 223b435d7d5a8d7774fbd9caba6493b587a16a8f..801ea6bf7b919905f2cd68cd0a0be85a20d19372 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -201,6 +201,13 @@ ifneq (,$(filter srf08,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter sx127%,$(USEMODULE))) + FEATURES_REQUIRED += periph_gpio + FEATURES_REQUIRED += periph_spi + USEMODULE += xtimer + USEMODULE += sx127x +endif + ifneq (,$(filter veml6070,$(USEMODULE))) FEATURES_REQUIRED += periph_i2c endif diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 5490aa45ebc4aeee36af13b01addbe9882119cf8..5529cf87575326bcec54dca476a10b81cab89bd1 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -130,3 +130,6 @@ endif ifneq (,$(filter adcxx1c,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/adcxx1c/include endif +ifneq (,$(filter sx127%,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/sx127x/include +endif diff --git a/drivers/include/net/netdev.h b/drivers/include/net/netdev.h index 38bfb092e4c5be914facd5e59da3bb6d37858e03..2fe9a5716d63381eb6b6e1e4905d7c10778f4edf 100644 --- a/drivers/include/net/netdev.h +++ b/drivers/include/net/netdev.h @@ -212,6 +212,7 @@ enum { NETDEV_TYPE_ETHERNET, NETDEV_TYPE_IEEE802154, NETDEV_TYPE_CC110X, + NETDEV_TYPE_LORA, NETDEV_TYPE_NRFMIN }; @@ -230,6 +231,11 @@ typedef enum { NETDEV_EVENT_TX_MEDIUM_BUSY, /**< couldn't transfer packet */ NETDEV_EVENT_LINK_UP, /**< link established */ NETDEV_EVENT_LINK_DOWN, /**< link gone */ + NETDEV_EVENT_TX_TIMEOUT, /**< timeout when sending */ + NETDEV_EVENT_RX_TIMEOUT, /**< timeout when receiving */ + NETDEV_EVENT_CRC_ERROR, /**< wrong CRC */ + NETDEV_EVENT_FHSS_CHANGE_CHANNEL, /**< channel changed */ + NETDEV_EVENT_CAD_DONE, /**< channel activity detection done */ /* expand this list if needed */ } netdev_event_t; diff --git a/drivers/include/sx127x.h b/drivers/include/sx127x.h new file mode 100644 index 0000000000000000000000000000000000000000..f6f6f3fcb49796cf503923943d4d23a0ea3f6ba7 --- /dev/null +++ b/drivers/include/sx127x.h @@ -0,0 +1,711 @@ +/* + * Copyright (C) 2016 Unwired Devices <info@unwds.com> + * 2017 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. + */ + +/** + * @defgroup drivers_sx127x SX127X + * @ingroup drivers_netdev + * @brief Semtech SX127X driver (SX1272 and SX1276) + * + * This module contains the driver for radio devices of the Semtech SX127x + * series (SX1272 and SX1276). + * Only LoRa long range modem is supported at the moment. + * + * SX127x modules are designed to be used in the ISM RF band. This RF band + * depends on different regional regulatory worldwide. + * Be careful to configure the device to use a RF frequency allowed in your + * region. + * sHere is the list of allowed frequencies for your region (see + * [LoRaWAN regional parameters document available online] + * (https://www.lora-alliance.org/Contact/RequestSpecificationForm.aspx)) + * - Europe has 2 allowed bands (ETSI): + * - EU863-870 + * - EU433 (from 433.175MHZ to 434.665MHZ exactly) + * - US is US902-928 + * - China has 2 allowed bands: + * - CN779-787 (from 779.5MHz to 786.5MHz exactly) + * - CN470-510 (from 470.3MHz to 509.7MHz exactly) + * - Australia is AU915-928 + * - South asia, AS923: + * - Bruneï [923-925 MHz] + * - Cambodia [923-925 MHz] + * - Hong Kong [920-925 MHz] + * - Indonesia [923-925 MHz] + * - Japan [920-928 MHz] + * - Laos [923-925 MHz] + * - New Zealand [915-928 MHz] + * - Singapore [920-925 MHz] + * - Taiwan [922-928 MHz] + * - Thailand [920-925 MHz] + * - Vietnam [920-925 MHz] + * - South Korea: KR920-923 (from 920.9MHz to 923.3MHz exactly) + * + * For more information on Semtech SX1272 and SX1276 modules see: + * - [SX1272/73 datasheet](http://www.semtech.com/images/datasheet/sx1272.pdf) + * - [SX1276/77/78/79 datasheet](http://www.semtech.com/images/datasheet/sx1276_77_78_79.pdf) + * + * @{ + * + * @file + * @brief Public interface for SX127X driver + * @author Eugene P. <ep@unwds.com> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> + */ + +#ifndef SX127X_H +#define SX127X_H + +#include "xtimer.h" +#include "net/netdev.h" +#include "periph/gpio.h" +#include "periph/spi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name SX127X device default configuration + * @{ + */ +#define SX127X_MODEM_DEFAULT (SX127X_MODEM_LORA) /**< Use LoRa as default modem */ +#define SX127X_CHANNEL_DEFAULT (868300000UL) /**< Default channel frequency, 868.3MHz (Europe) */ +#define SX127X_HF_CHANNEL_DEFAULT (868000000UL) /**< Use to calibrate RX chain for LF and HF bands */ +#define SX127X_RF_MID_BAND_THRESH (525000000UL) /**< Mid-band threshold */ +#define SX127X_FREQUENCY_RESOLUTION (61.03515625) /**< Frequency resolution in Hz */ +#define SX127X_XTAL_FREQ (32000000UL) /**< Internal oscillator frequency, 32MHz */ +#define SX127X_RADIO_WAKEUP_TIME (1000U) /**< In microseconds [us] */ + +#define SX127X_PREAMBLE_LENGTH (8U) /**< Preamble length, same for Tx and Rx */ +#define SX127X_SYMBOL_TIMEOUT (10U) /**< Symbols timeout (s) */ + +#define SX127X_BW_DEFAULT (SX127X_BW_125_KHZ) /**< Set default bandwidth to 125kHz */ +#define SX127X_SF_DEFAULT (SX127X_SF12) /**< Set default spreading factor to 12 */ +#define SX127X_CR_DEFAULT (SX127X_CR_4_8) /**< Set default coding rate to 8 */ +#define SX127X_FIX_LENGTH_PAYLOAD_ON (false) /**< Set fixed payload length on */ +#define SX127X_IQ_INVERSION (false) /**< Set inverted IQ on */ +#define SX127X_FREQUENCY_HOPPING (false) /**< Frequency hopping on */ +#define SX127X_FREQUENCY_HOPPING_PERIOD (0U) /**< Frequency hopping period */ +#define SX127X_FIXED_HEADER_LEN_MODE (false) /**< Set fixed header length mode (implicit header) */ +#define SX127X_PAYLOAD_CRC_ON (true) /**< Enable payload CRC, optional */ +#define SX127X_PAYLOAD_LENGTH (0U) /**< Set payload length, unused with implicit header */ + +#define SX127X_TX_TIMEOUT_DEFAULT (1000U * 1000U * 30UL) /**< TX timeout, 30s */ +#define SX127X_RX_SINGLE (false) /**< Single byte receive mode => continuous by default */ +#define SX127X_RX_BUFFER_SIZE (256) /**< RX buffer size */ + +#define SX127X_RADIO_TX_POWER (14U) /**< Radio power in dBm */ + +#ifndef SX1272_DEFAULT_PASELECT +/** @brief Default PA selection config (1: RFO, 0: PABOOST) + * + * This depends on the module configuration. + */ +#define SX1272_DEFAULT_PASELECT (1U) +#endif + +#define SX127X_EVENT_HANDLER_STACK_SIZE (2048U) /**< Stack size event handler */ +#define SX127X_IRQ_DIO0 (1<<0) /**< DIO0 IRQ */ +#define SX127X_IRQ_DIO1 (1<<1) /**< DIO1 IRQ */ +#define SX127X_IRQ_DIO2 (1<<2) /**< DIO2 IRQ */ +#define SX127X_IRQ_DIO3 (1<<3) /**< DIO3 IRQ */ +#define SX127X_IRQ_DIO4 (1<<4) /**< DIO4 IRQ */ +#define SX127X_IRQ_DIO5 (1<<5) /**< DIO5 IRQ */ +/** @} */ + +/** + * @brief SX127X initialization result. + */ +enum { + SX127X_INIT_OK = 0, /**< Initialization was successful */ + SX127X_ERR_SPI, /**< Failed to initialize SPI bus or CS line */ + SX127X_ERR_TEST_FAILED, /**< SX127X testing failed during initialization (check chip) */ + SX127X_ERR_THREAD /**< Unable to create DIO handling thread (check amount of free memory) */ +}; + +/** + * @brief Radio driver supported modems. + */ +enum { + SX127X_MODEM_FSK = 0, /**< FSK modem driver */ + SX127X_MODEM_LORA, /**< LoRa modem driver */ +}; + +/** + * @brief LoRa signal bandwidth. + */ +enum { + SX127X_BW_125_KHZ = 0, /**< 125 kHz bandwidth */ + SX127X_BW_250_KHZ, /**< 250 kHz bandwidth */ + SX127X_BW_500_KHZ /**< 500 kHz bandwidth */ +}; + +/** + * @brief LoRa spreading factor rate + */ +enum { + SX127X_SF6 = 6, /**< spreading factor 6 */ + SX127X_SF7, /**< spreading factor 7 */ + SX127X_SF8, /**< spreading factor 8 */ + SX127X_SF9, /**< spreading factor 9 */ + SX127X_SF10, /**< spreading factor 10 */ + SX127X_SF11, /**< spreading factor 11 */ + SX127X_SF12 /**< spreading factor 12 */ +}; + +/** + * @brief LoRa error coding rate. + */ +enum { + SX127X_CR_4_5 = 1, /**< coding rate 4/5 */ + SX127X_CR_4_6, /**< coding rate 4/6 */ + SX127X_CR_4_7, /**< coding rate 4/7 */ + SX127X_CR_4_8 /**< coding rate 4/8 */ +}; + +/** + * @brief Radio driver internal state machine states definition. + */ +enum { + SX127X_RF_IDLE = 0, /**< Idle state */ + SX127X_RF_RX_RUNNING, /**< Sending state */ + SX127X_RF_TX_RUNNING, /**< Receiving state */ + SX127X_RF_CAD, /**< Channel activity detection state */ +}; + +/** + * @brief Event types. + */ +enum { + SX127X_RX_DONE = 0, /**< Receiving complete */ + SX127X_TX_DONE, /**< Sending complete*/ + SX127X_RX_TIMEOUT, /**< Receiving timeout */ + SX127X_TX_TIMEOUT, /**< Sending timeout */ + SX127X_RX_ERROR_CRC, /**< Receiving CRC error */ + SX127X_FHSS_CHANGE_CHANNEL, /**< Channel change */ + SX127X_CAD_DONE, /**< Channel activity detection complete */ +}; + +/** + * @name SX127X device descriptor boolean flags + * @{ + */ +#define SX127X_LOW_DATARATE_OPTIMIZE_FLAG (1 << 0) +#define SX127X_ENABLE_FIXED_HEADER_LENGTH_FLAG (1 << 1) +#define SX127X_ENABLE_CRC_FLAG (1 << 2) +#define SX127X_CHANNEL_HOPPING_FLAG (1 << 3) +#define SX127X_IQ_INVERTED_FLAG (1 << 4) +#define SX127X_RX_CONTINUOUS_FLAG (1 << 5) +/** @} */ + +/** + * @brief LoRa configuration structure. + */ +typedef struct { + uint16_t preamble_len; /**< Length of preamble header */ + uint8_t power; /**< Signal power */ + uint8_t bandwidth; /**< Signal bandwidth */ + uint8_t datarate; /**< Spreading factor rate, e.g datarate */ + uint8_t coderate; /**< Error coding rate */ + uint8_t freq_hop_period; /**< Frequency hop period */ + uint8_t flags; /**< Boolean flags */ + uint32_t rx_timeout; /**< RX timeout in symbols */ + uint32_t tx_timeout; /**< TX timeout in symbols */ +} sx127x_lora_settings_t; + +/** + * @brief Radio settings. + */ +typedef struct { + uint32_t channel; /**< Radio channel */ + uint32_t window_timeout; /**< Timeout window */ + uint8_t state; /**< Radio state */ + uint8_t modem; /**< Driver model (FSK or LoRa) */ + sx127x_lora_settings_t lora; /**< LoRa settings */ +} sx127x_radio_settings_t; + +/** + * @brief SX127X internal data. + */ +typedef struct { + /* Data that will be passed to events handler in application */ + xtimer_t tx_timeout_timer; /**< TX operation timeout timer */ + xtimer_t rx_timeout_timer; /**< RX operation timeout timer */ + uint32_t last_channel; /**< Last channel in frequency hopping sequence */ + bool is_last_cad_success; /**< Sign of success of last CAD operation (activity detected) */ +} sx127x_internal_t; + +/** + * @brief SX127X hardware and global parameters. + */ +typedef struct { + spi_t spi; /**< SPI device */ + gpio_t nss_pin; /**< SPI NSS pin */ + gpio_t reset_pin; /**< Reset pin */ + gpio_t dio0_pin; /**< Interrupt line DIO0 (Tx done) */ + gpio_t dio1_pin; /**< Interrupt line DIO1 (Rx timeout) */ + gpio_t dio2_pin; /**< Interrupt line DIO2 (FHSS channel change) */ + gpio_t dio3_pin; /**< Interrupt line DIO3 (CAD done) */ + gpio_t dio4_pin; /**< Interrupt line DIO4 (not used) */ + gpio_t dio5_pin; /**< Interrupt line DIO5 (not used) */ +} sx127x_params_t; + +/** + * @brief SX127X IRQ flags. + */ +typedef uint8_t sx127x_flags_t; + +/** + * @brief SX127X device. + * @extends netdev_t + */ +typedef struct sx127x_s { + netdev_t netdev; /**< Netdev parent struct */ + sx127x_radio_settings_t settings; /**< Radio settings */ + sx127x_params_t params; /**< Device driver parameters */ + sx127x_internal_t _internal; /**< Internal sx127x data used within the driver */ + sx127x_flags_t irq; /**< Device IRQ flags */ +} sx127x_t; + +/** + * @brief Hardware IO IRQ callback function definition. + */ +typedef void (sx127x_dio_irq_handler_t)(sx127x_t *dev); + +/** + * @brief Setup the SX127X + * + * @param[in] dev Device descriptor + * @param[in] params Parameters for device initialization + */ +void sx127x_setup(sx127x_t *dev, const sx127x_params_t *params); + +/** + * @brief Resets the SX127X + * + * @param[in] dev The sx127x device descriptor + */ +void sx127x_reset(const sx127x_t *dev); + +/** + * @brief Initializes the transceiver. + * + * @param[in] dev The sx127x device descriptor + * + * @return result of initialization + */ +int sx127x_init(sx127x_t *dev); + +/** + * @brief Initialize radio settings with default values + * + * @param[in] dev The sx127x device pointer + */ +void sx127x_init_radio_settings(sx127x_t *dev); + +/** + * @brief Generates 32 bits random value based on the RSSI readings + * + * @attention This function sets the radio in LoRa mode and disables all + * interrupts from it. After calling this function either + * sx127x_set_rx_config or sx127x_set_tx_config functions must + * be called. + * + * @param[in] dev The sx127x device structure pointer + * + * @return random 32 bits value + */ +uint32_t sx127x_random(sx127x_t *dev); + +/** + * @brief sx127x DIO0 IRQ handler. + * + * @param[in] arg An sx127x device instance + */ +void sx127x_on_dio0(void *arg); + +/** + * @brief sx127x DIO1 IRQ handler. + * + * @param[in] arg An sx127x device instance + */ +void sx127x_on_dio1(void *arg); + +/** + * @brief sx127x DIO2 IRQ handler. + * + * @param[in] arg An sx127x device instance + */ +void sx127x_on_dio2(void *arg); + +/** + * @brief sx127x DIO3 IRQ handler. + * + * @param[in] arg An sx127x device instance + */ +void sx127x_on_dio3(void *arg); + +/** + * @brief Start a channel activity detection. + * + * @param[in] dev The sx127x device descriptor + */ +void sx127x_start_cad(sx127x_t *dev); + +/** + * @brief Gets current state of transceiver. + * + * @param[in] dev The sx127x device descriptor + * + * @return radio state [RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] + */ +uint8_t sx127x_get_state(const sx127x_t *dev); + +/** + * @brief Sets current state of transceiver. + * + * @param[in] dev The sx127x device descriptor + * @param[in] state The new radio state + * + * @return radio state [RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] + */ +void sx127x_set_state(sx127x_t *dev, uint8_t state); + +/** + * @brief Configures the radio with the given modem. + * + * @param[in] dev The sx127x device descriptor + * @param[in] modem Modem to be used [0: FSK, 1: LoRa] + */ +void sx127x_set_modem(sx127x_t *dev, uint8_t modem); + +/** + * @brief Gets the synchronization word. + * + * @param[in] dev The sx127x device descriptor + * + * @return The synchronization word + */ +uint8_t sx127x_get_syncword(const sx127x_t *dev); + +/** + * @brief Sets the synchronization word. + * + * @param[in] dev The sx127x device descriptor + * @param[in] syncword The synchronization word + */ +void sx127x_set_syncword(sx127x_t *dev, uint8_t syncword); + +/** + * @brief Gets the channel RF frequency. + * + * @param[in] dev The sx127x device descriptor + * + * @return The channel frequency + */ +uint32_t sx127x_get_channel(const sx127x_t *dev); + +/** + * @brief Sets the channel RF frequency. + * + * @param[in] dev The sx127x device descriptor + * @param[in] freq Channel RF frequency + */ +void sx127x_set_channel(sx127x_t *dev, uint32_t freq); + +/** + * @brief Computes the packet time on air in milliseconds. + * + * @pre Can only be called once sx127x_init_radio_settings have already + * been called. + * + * @param[in] dev The sx127x device descriptor + * @param[in] pkt_len The received packet payload length + * + * @return computed air time (ms) for the given packet payload length + */ +uint32_t sx127x_get_time_on_air(const sx127x_t *dev, uint8_t pkt_len); + +/** + * @brief Sets the radio in sleep mode + * + * @param[in] dev The sx127x device descriptor + */ +void sx127x_set_sleep(sx127x_t *dev); + +/** + * @brief Sets the radio in stand-by mode + * + * @param[in] dev The sx127x device descriptor + */ +void sx127x_set_standby(sx127x_t *dev); + +/** + * @brief Sets the radio in reception mode. + * + * @param[in] dev The sx127x device descriptor + */ +void sx127x_set_rx(sx127x_t *dev); + +/** + * @brief Sets the radio in transmission mode. + * + * @param[in] dev The sx127x device descriptor + */ +void sx127x_set_tx(sx127x_t *dev); + +/** + * @brief Gets the maximum payload length. + * + * @param[in] dev The sx127x device descriptor + * + * @return The maximum payload length + */ +uint8_t sx127x_get_max_payload_len(const sx127x_t *dev); + +/** + * @brief Sets the maximum payload length. + * + * @param[in] dev The sx127x device descriptor + * @param[in] maxlen Maximum payload length in bytes + */ +void sx127x_set_max_payload_len(const sx127x_t *dev, uint8_t maxlen); + +/** + * @brief Gets the SX127X operating mode + * + * @param[in] dev The sx127x device descriptor + * + * @return The actual operating mode + */ +uint8_t sx127x_get_op_mode(const sx127x_t *dev); + +/** + * @brief Sets the SX127X operating mode + * + * @param[in] dev The sx127x device descriptor + * @param[in] op_mode The new operating mode + */ +void sx127x_set_op_mode(const sx127x_t *dev, uint8_t op_mode); + +/** + * @brief Gets the SX127X bandwidth + * + * @param[in] dev The sx127x device descriptor + * + * @return the bandwidth + */ +uint8_t sx127x_get_bandwidth(const sx127x_t *dev); + +/** + * @brief Sets the SX127X bandwidth + * + * @param[in] dev The sx127x device descriptor + * @param[in] bandwidth The new bandwidth + */ +void sx127x_set_bandwidth(sx127x_t *dev, uint8_t bandwidth); + +/** + * @brief Gets the SX127X LoRa spreading factor + * + * @param[in] dev The sx127x device descriptor + * + * @return the spreading factor + */ +uint8_t sx127x_get_spreading_factor(const sx127x_t *dev); + +/** + * @brief Sets the SX127X LoRa spreading factor + * + * @param[in] dev The sx127x device descriptor + * @param[in] sf The spreading factor + */ +void sx127x_set_spreading_factor(sx127x_t *dev, uint8_t sf); + +/** + * @brief Gets the SX127X LoRa coding rate + * + * @param[in] dev The sx127x device descriptor + * + * @return the current LoRa coding rate + */ +uint8_t sx127x_get_coding_rate(const sx127x_t *dev); + +/** + * @brief Sets the SX127X LoRa coding rate + * + * @param[in] dev The sx127x device descriptor + * @param[in] coderate The LoRa coding rate + */ +void sx127x_set_coding_rate(sx127x_t *dev, uint8_t coderate); + +/** + * @brief Checks if the SX127X LoRa RX single mode is enabled/disabled + * + * @param[in] dev The sx127x device descriptor + * + * @return the LoRa single mode + */ +bool sx127x_get_rx_single(const sx127x_t *dev); + +/** + * @brief Enable/disable the SX127X LoRa RX single mode + * + * @param[in] dev The sx127x device descriptor + * @param[in] single The LoRa RX single mode + */ +void sx127x_set_rx_single(sx127x_t *dev, bool single); + +/** + * @brief Checks if the SX127X CRC verification mode is enabled + * + * @param[in] dev The sx127x device descriptor + * + * @return the LoRa single mode + */ +bool sx127x_get_crc(const sx127x_t *dev); + +/** + * @brief Enable/Disable the SX127X CRC verification mode + * + * @param[in] dev The sx127x device descriptor + * @param[in] crc The CRC check mode + */ +void sx127x_set_crc(sx127x_t *dev, bool crc); + +/** + * @brief Gets the SX127X frequency hopping period + * + * @param[in] dev The sx127x device descriptor + * + * @return the frequency hopping period + */ +uint8_t sx127x_get_hop_period(const sx127x_t *dev); + +/** + * @brief Sets the SX127X frequency hopping period + * + * @param[in] dev The sx127x device descriptor + * @param[in] hop_period The frequency hopping period + */ +void sx127x_set_hop_period(sx127x_t *dev, uint8_t hop_period); + +/** + * @brief Gets the SX127X LoRa fixed header length mode + * + * @param[in] dev The sx127x device descriptor + * + * @return the LoRa implicit mode + */ +bool sx127x_get_fixed_header_len_mode(const sx127x_t *dev); + +/** + * @brief Sets the SX127X to fixed header length mode (explicit mode) + * + * @param[in] dev The sx127x device descriptor + * @param[in] mode The header mode + */ +void sx127x_set_fixed_header_len_mode(sx127x_t *dev, bool mode); + +/** + * @brief Gets the SX127X payload length + * + * @param[in] dev The sx127x device descriptor + * + * @return the payload length + */ +uint8_t sx127x_get_payload_length(const sx127x_t *dev); + +/** + * @brief Sets the SX127X payload length + * + * @param[in] dev The sx127x device descriptor + * @param[in] len The payload len + */ +void sx127x_set_payload_length(sx127x_t *dev, uint8_t len); + +/** + * @brief Gets the SX127X TX radio power + * + * @param[in] dev The sx127x device descriptor + * + * @return the radio power + */ +uint8_t sx127x_get_tx_power(const sx127x_t *dev); + +/** + * @brief Sets the SX127X transmission power + * + * @param[in] dev The sx127x device descriptor + * @param[in] power The TX power + */ +void sx127x_set_tx_power(sx127x_t *dev, uint8_t power); + +/** + * @brief Gets the SX127X preamble length + * + * @param[in] dev The sx127x device descriptor + * + * @return the preamble length + */ +uint16_t sx127x_get_preamble_length(const sx127x_t *dev); + +/** + * @brief Sets the SX127X LoRa preamble length + * + * @param[in] dev The sx127x device descriptor + * @param[in] preamble The LoRa preamble length + */ +void sx127x_set_preamble_length(sx127x_t *dev, uint16_t preamble); + +/** + * @brief Sets the SX127X LoRa symbol timeout + * + * @param[in] dev The sx127x device descriptor + * @param[in] timeout The LoRa symbol timeout + */ +void sx127x_set_symbol_timeout(sx127x_t *dev, uint16_t timeout); + +/** + * @brief Sets the SX127X RX timeout + * + * @param[in] dev The sx127x device descriptor + * @param[in] timeout The RX timeout + */ +void sx127x_set_rx_timeout(sx127x_t *dev, uint32_t timeout); + +/** + * @brief Sets the SX127X TX timeout + * + * @param[in] dev The sx127x device descriptor + * @param[in] timeout The TX timeout + */ +void sx127x_set_tx_timeout(sx127x_t *dev, uint32_t timeout); + +/** + * @brief Sets the SX127X LoRa IQ inverted mode + * + * @param[in] dev The sx127x device descriptor + * @param[in] iq_invert The LoRa IQ inverted mode + */ +void sx127x_set_iq_invert(sx127x_t *dev, bool iq_invert); + +/** + * @brief Sets the SX127X LoRa frequency hopping mode + * + * @param[in] dev The sx127x device descriptor + * @param[in] freq_hop_on The LoRa frequency hopping mode + */ +void sx127x_set_freq_hop(sx127x_t *dev, bool freq_hop_on); + +#ifdef __cplusplus +} +#endif + +#endif /* SX127X_H */ +/** @} */ diff --git a/drivers/sx127x/Makefile b/drivers/sx127x/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..48422e909a47d7cd428d10fa73825060ccc8d8c2 --- /dev/null +++ b/drivers/sx127x/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/sx127x/include/sx127x_internal.h b/drivers/sx127x/include/sx127x_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..72cdd347e3de848a748c321383fb7c70d5c8c9b3 --- /dev/null +++ b/drivers/sx127x/include/sx127x_internal.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2016 Unwired Devices <info@unwds.com> + * 2017 Inria Chile + * 2017 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 drivers_sx127x + * @{ + * @file + * @brief Semtech SX127X internal functions + * + * @author Eugene P. <ep@unwds.com> + * @author José Ignacio Alamos <jose.alamos@inria.cl> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> + */ + +#ifndef SX127X_INTERNAL_H +#define SX127X_INTERNAL_H + +#include <inttypes.h> +#include "sx127x.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Constant values used to compute RSSI + * @{ + */ +#if defined(MODULE_SX1272) +#define SX127X_RSSI_OFFSET (-139) +#else /* MODULE_SX1276 */ +#define SX127X_RSSI_OFFSET_LF (-164) +#define SX127X_RSSI_OFFSET_HF (-157) +#endif +/** @} */ + +/** + * @brief Tests the transceiver version type. + * + * @param[in] dev The sx127x device descriptor + * @return true if test passed, false otherwise + */ +bool sx127x_test(const sx127x_t *dev); + +/** + * @brief Writes the radio register at specified address. + * + * @param[in] dev The sx127x device structure pointer + * @param[in] addr Register address + * @param[in] data New register value + */ +void sx127x_reg_write(const sx127x_t *dev, uint8_t addr, uint8_t data); + +/** + * @brief Reads the radio register at specified address. + * + * @param[in] dev The sx127x device structure pointer + * @param[in] addr Register address + * + * @return Register value + */ +uint8_t sx127x_reg_read(const sx127x_t *dev, uint8_t addr); + +/** + * @brief Writes multiple radio registers starting at address (burst-mode). + * + * @param[in] dev The sx127x device structure pointer + * @param[in] addr First radio register address + * @param[in] buffer Buffer containing the new register's values + * @param[in] size Number of registers to be written + */ +void sx127x_reg_write_burst(const sx127x_t *dev, uint8_t addr, uint8_t *buffer, + uint8_t size); + +/** + * @brief Reads multiple radio registers starting at address. + * + * @param[in] dev The sx127x device structure pointer + * @param[in] addr First radio register address + * @param[in] size Number of registers to be read + * @param[out] buffer Buffer where to copy registers data + */ +void sx127x_reg_read_burst(const sx127x_t *dev, uint8_t addr, uint8_t *buffer, + uint8_t size); + +/** + * @brief Writes the buffer contents to the SX1276 FIFO + * + * @param[in] dev The sx127x device structure pointer + * @param[in] buffer Buffer Buffer containing data to be put on the FIFO. + * @param[in] size Size Number of bytes to be written to the FIFO + */ +void sx127x_write_fifo(const sx127x_t *dev, uint8_t *buffer, uint8_t size); + +/** + * @brief Reads the contents of the SX1276 FIFO + * + * @param[in] dev The sx127x device structure pointer + * @param[in] size Size Number of bytes to be read from the FIFO + * @param[out] buffer Buffer Buffer where to copy the FIFO read data. + */ +void sx127x_read_fifo(const sx127x_t *dev, uint8_t *buffer, uint8_t size); + +/** + * @brief Performs the Rx chain calibration for LF and HF bands + * + * Must be called just after the reset so all registers are at their + * default values + * + * @param[in] dev The sx127x device structure pointer + */ +void sx127x_rx_chain_calibration(sx127x_t *dev); + +/** + * @brief Reads the current RSSI value. + * + * @param[in] dev The sx127x device descriptor + * + * @return current value of RSSI in [dBm] + */ +int16_t sx127x_read_rssi(const sx127x_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* SX127X_INTERNAL_H */ diff --git a/drivers/sx127x/include/sx127x_netdev.h b/drivers/sx127x/include/sx127x_netdev.h new file mode 100644 index 0000000000000000000000000000000000000000..ca924501cd906f8f11006f5409f71c1fb126051d --- /dev/null +++ b/drivers/sx127x/include/sx127x_netdev.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 Inria + * 2017 Inria Chile + * + * 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_sx127x + * @{ + * @file + * @brief Netdev driver definitions for SX127X driver + * + * @author José Ignacio Alamos <jose.alamos@inria.cl> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> + */ + +#ifndef SX127X_NETDEV_H +#define SX127X_NETDEV_H + +#include "net/netdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Reference to the netdev device driver struct + */ +extern const netdev_driver_t sx127x_driver; + +/** + * @brief Received LoRa packet status information + */ +typedef struct netdev_radio_lora_packet_info { + uint8_t rssi; /**< RSSI of a received packet */ + uint8_t lqi; /**< LQI of a received packet */ + int8_t snr; /**< S/N ratio */ + uint32_t time_on_air; /**< Time on air of a received packet (ms) */ +} netdev_sx127x_lora_packet_info_t; + +#ifdef __cplusplus +} +#endif + +#endif /* SX127X_NETDEV_H */ diff --git a/drivers/sx127x/include/sx127x_params.h b/drivers/sx127x/include/sx127x_params.h new file mode 100644 index 0000000000000000000000000000000000000000..c9bf4e477f8810ff7ee1fc4b59feecf631c003a5 --- /dev/null +++ b/drivers/sx127x/include/sx127x_params.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2017 Inria + * 2017 Inria Chile + * + * 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_sx127x + * @{ + * @file + * @brief Default configuration for SX127X driver + * + * @author José Ignacio Alamos <jose.alamos@inria.cl> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> + */ + +#ifndef SX127X_PARAMS_H +#define SX127X_PARAMS_H + +#include "board.h" +#include "sx127x.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Set default configuration parameters for the SX127X driver + * Pins are adapted to ST Nucleo boards. + * @{ + */ +#ifndef SX127X_PARAM_SPI +#define SX127X_PARAM_SPI (SPI_DEV(0)) +#endif + +#ifndef SX127X_PARAM_SPI_SPEED +#define SX127X_PARAM_SPI_SPEED (SPI_CLK_1MHZ) +#endif + +#ifndef SX127X_PARAM_SPI_MODE +#define SX127X_PARAM_SPI_MODE (SPI_MODE_0) +#endif + +#ifndef SX127X_PARAM_SPI_NSS +#define SX127X_PARAM_SPI_NSS GPIO_PIN(1, 6) /* D10 */ +#endif + +#ifndef SX127X_PARAM_RESET +#define SX127X_PARAM_RESET GPIO_PIN(0, 0) /* A0 */ +#endif + +#ifndef SX127X_PARAM_DIO0 +#define SX127X_PARAM_DIO0 GPIO_PIN(0, 10) /* D2 */ +#endif + +#ifndef SX127X_PARAM_DIO1 +#define SX127X_PARAM_DIO1 GPIO_PIN(1, 3) /* D3 */ +#endif + +#ifndef SX127X_PARAM_DIO2 +#define SX127X_PARAM_DIO2 GPIO_PIN(1, 5) /* D4 */ +#endif + +#ifndef SX127X_PARAM_DIO3 +#define SX127X_PARAM_DIO3 GPIO_PIN(1, 4) /* D5 */ +#endif + +#define SX127X_PARAMS_DEFAULT { .spi = SX127X_PARAM_SPI, \ + .nss_pin = SX127X_PARAM_SPI_NSS, \ + .reset_pin = SX127X_PARAM_RESET, \ + .dio0_pin = SX127X_PARAM_DIO0, \ + .dio1_pin = SX127X_PARAM_DIO1, \ + .dio2_pin = SX127X_PARAM_DIO2, \ + .dio3_pin = SX127X_PARAM_DIO3 } +/**@}*/ + +/** + * @brief SX127X configuration + */ +static const sx127x_params_t sx127x_params[] = +{ +#ifdef SX127X_PARAMS_BOARD + SX127X_PARAMS_BOARD, +#else + SX127X_PARAMS_DEFAULT, +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* SX127X_PARAMS_H */ +/** @} */ diff --git a/drivers/sx127x/include/sx127x_registers.h b/drivers/sx127x/include/sx127x_registers.h new file mode 100644 index 0000000000000000000000000000000000000000..3aea5de66c7fa9fa65c43de37588862053f593f9 --- /dev/null +++ b/drivers/sx127x/include/sx127x_registers.h @@ -0,0 +1,1426 @@ +/* + * Copyright (C) 2016 Unwired Devices <info@unwds.com> + * 2016 Inria Chile + * 2017 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 drivers_sx127x + * @{ + * + * @file + * @brief SX127X registers + * + * @author Eugene P. <ep@unwds.com> + * @author José Ignacio Alamos <jose.alamos@inria.cl> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> + * + */ + +#ifndef SX127X_REGISTERS_H +#define SX127X_REGISTERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name SX127X LoRa modem internal registers addresses + * @{ + */ + +/* Common settings */ +#define SX127X_REG_LR_OPMODE (0x01) +#define SX127X_REG_LR_FRFMSB (0x06) +#define SX127X_REG_LR_FRFMID (0x07) +#define SX127X_REG_LR_FRFLSB (0x08) + +/* Tx settings */ +#define SX127X_REG_LR_PACONFIG (0x09) +#define SX127X_REG_LR_PARAMP (0x0A) +#define SX127X_REG_LR_OCP (0x0B) + +/* Rx settings */ +#define SX127X_REG_LR_LNA (0x0C) + +/* LoRa registers */ +#define SX127X_REG_LR_FIFOADDRPTR (0x0D) +#define SX127X_REG_LR_FIFOTXBASEADDR (0x0E) +#define SX127X_REG_LR_FIFORXBASEADDR (0x0F) +#define SX127X_REG_LR_FIFORXCURRENTADDR (0x10) +#define SX127X_REG_LR_IRQFLAGSMASK (0x11) +#define SX127X_REG_LR_IRQFLAGS (0x12) +#define SX127X_REG_LR_RXNBBYTES (0x13) +#define SX127X_REG_LR_RXHEADERCNTVALUEMSB (0x14) +#define SX127X_REG_LR_RXHEADERCNTVALUELSB (0x15) +#define SX127X_REG_LR_RXPACKETCNTVALUEMSB (0x16) +#define SX127X_REG_LR_RXPACKETCNTVALUELSB (0x17) +#define SX127X_REG_LR_MODEMSTAT (0x18) +#define SX127X_REG_LR_PKTSNRVALUE (0x19) +#define SX127X_REG_LR_PKTRSSIVALUE (0x1A) +#define SX127X_REG_LR_RSSIVALUE (0x1B) +#define SX127X_REG_LR_HOPCHANNEL (0x1C) +#define SX127X_REG_LR_MODEMCONFIG1 (0x1D) +#define SX127X_REG_LR_MODEMCONFIG2 (0x1E) +#define SX127X_REG_LR_SYMBTIMEOUTLSB (0x1F) +#define SX127X_REG_LR_PREAMBLEMSB (0x20) +#define SX127X_REG_LR_PREAMBLELSB (0x21) +#define SX127X_REG_LR_PAYLOADLENGTH (0x22) +#define SX127X_REG_LR_PAYLOADMAXLENGTH (0x23) +#define SX127X_REG_LR_HOPPERIOD (0x24) +#define SX127X_REG_LR_FIFORXBYTEADDR (0x25) +#define SX127X_REG_LR_MODEMCONFIG3 (0x26) +#define SX127X_REG_LR_FEIMSB (0x28) +#define SX127X_REG_LR_FEIMID (0x29) +#define SX127X_REG_LR_FEILSB (0x2A) +#define SX127X_REG_LR_RSSIWIDEBAND (0x2C) +#define SX127X_REG_LR_TEST2F (0x2F) +#define SX127X_REG_LR_TEST30 (0x30) +#define SX127X_REG_LR_DETECTOPTIMIZE (0x31) +#define SX127X_REG_LR_INVERTIQ (0x33) +#define SX127X_REG_LR_TEST36 (0x36) +#define SX127X_REG_LR_DETECTIONTHRESHOLD (0x37) +#define SX127X_REG_LR_SYNCWORD (0x39) +#define SX127X_REG_LR_TEST3A (0x3A) +#define SX127X_REG_LR_INVERTIQ2 (0x3B) + +/* I/O settings */ +#define SX127X_REG_LR_DIOMAPPING1 (0x40) +#define SX127X_REG_LR_DIOMAPPING2 (0x41) + +/* Version */ +#define SX127X_REG_LR_VERSION (0x42) + +/* Additional settings */ +#define SX127X_REG_LR_PLLHOP (0x44) +#define SX127X_REG_LR_TCXO (0x4B) +#define SX127X_REG_LR_PADAC (0x4D) +#define SX127X_REG_LR_FORMERTEMP (0x5B) +#define SX127X_REG_LR_BITRATEFRAC (0x5D) +#define SX127X_REG_LR_AGCREF (0x61) +#define SX127X_REG_LR_AGCTHRESH1 (0x62) +#define SX127X_REG_LR_AGCTHRESH2 (0x63) +#define SX127X_REG_LR_AGCTHRESH3 (0x64) +#define SX127X_REG_LR_PLL (0x70) +/** @} */ + +/** + * @name Modem settings for random number generator + * @{ + */ +#define SX127X_RNG_REG_MODEM_CONFIG1 (0x0A) +#define SX127X_RNG_REG_MODEM_CONFIG2 (0x70) +/** @} */ + +/** + * @name SX127X LoRa bits control definition + * @{ + */ + +/* RegFifo */ +#define SX127X_REG_LR_FIFO (0x00) + +/* RegOpMode */ +#define SX127X_RF_LORA_OPMODE_LONGRANGEMODE_MASK (0x7F) +#define SX127X_RF_LORA_OPMODE_LONGRANGEMODE_OFF (0x00) /* Default */ +#define SX127X_RF_LORA_OPMODE_LONGRANGEMODE_ON (0x80) + +#define SX127X_RF_LORA_OPMODE_ACCESSSHAREDSX127X_REG_MASK (0xBF) +#define SX127X_RF_LORA_OPMODE_ACCESSSHAREDSX127X_REG_ENABLE (0x40) +#define SX127X_RF_LORA_OPMODE_ACCESSSHAREDSX127X_REG_DISABLE (0x00) /* Default */ + +#define SX127X_RF_LORA_OPMODE_FREQMODE_ACCESS_MASK (0xF7) +#define SX127X_RF_LORA_OPMODE_FREQMODE_ACCESS_LF (0x08) /* Default */ +#define SX127X_RF_LORA_OPMODE_FREQMODE_ACCESS_HF (0x00) + +#define SX127X_RF_LORA_OPMODE_MASK (0xF8) +#define SX127X_RF_LORA_OPMODE_SLEEP (0x00) +#define SX127X_RF_LORA_OPMODE_STANDBY (0x01) /* Default */ +#define SX127X_RF_LORA_OPMODE_SYNTHESIZER_TX (0x02) +#define SX127X_RF_LORA_OPMODE_TRANSMITTER (0x03) +#define SX127X_RF_LORA_OPMODE_SYNTHESIZER_RX (0x04) +#define SX127X_RF_LORA_OPMODE_RECEIVER (0x05) + +/* LoRa specific modes */ +#define SX127X_RF_LORA_OPMODE_RECEIVER_SINGLE (0x06) +#define SX127X_RF_LORA_OPMODE_CAD (0x07) + +/* RegFrf (MHz) */ +#define SX127X_RF_LORA_FRFMSB_434_MHZ (0x6C) /* Default */ +#define SX127X_RF_LORA_FRFMID_434_MHZ (0x80) /* Default */ +#define SX127X_RF_LORA_FRFLSB_434_MHZ (0x00) /* Default */ + +/* RegPaConfig */ +#define SX127X_RF_LORA_PACONFIG_PASELECT_MASK (0x7F) +#define SX127X_RF_LORA_PACONFIG_PASELECT_PABOOST (0x80) +#define SX127X_RF_LORA_PACONFIG_PASELECT_RFO (0x00) /* Default */ + +#define SX127X_RF_LORA_PACONFIG_MAX_POWER_MASK (0x8F) + +#define SX127X_RF_LORA_PACONFIG_OUTPUTPOWER_MASK (0xF0) + +/* RegPaRamp */ +#define SX127X_RF_LORA_PARAMP_TXBANDFORCE_MASK (0xEF) +#define SX127X_RF_LORA_PARAMP_TXBANDFORCE_BAND_SEL (0x10) +#define SX127X_RF_LORA_PARAMP_TXBANDFORCE_AUTO (0x00) /* Default */ + +#define SX127X_RF_LORA_PARAMP_MASK (0xF0) +#define SX127X_RF_LORA_PARAMP_3400_US (0x00) +#define SX127X_RF_LORA_PARAMP_2000_US (0x01) +#define SX127X_RF_LORA_PARAMP_1000_US (0x02) +#define SX127X_RF_LORA_PARAMP_0500_US (0x03) +#define SX127X_RF_LORA_PARAMP_0250_US (0x04) +#define SX127X_RF_LORA_PARAMP_0125_US (0x05) +#define SX127X_RF_LORA_PARAMP_0100_US (0x06) +#define SX127X_RF_LORA_PARAMP_0062_US (0x07) +#define SX127X_RF_LORA_PARAMP_0050_US (0x08) +#define SX127X_RF_LORA_PARAMP_0040_US (0x09) /* Default */ +#define SX127X_RF_LORA_PARAMP_0031_US (0x0A) +#define SX127X_RF_LORA_PARAMP_0025_US (0x0B) +#define SX127X_RF_LORA_PARAMP_0020_US (0x0C) +#define SX127X_RF_LORA_PARAMP_0015_US (0x0D) +#define SX127X_RF_LORA_PARAMP_0012_US (0x0E) +#define SX127X_RF_LORA_PARAMP_0010_US (0x0F) + +/* RegOcp */ +#define SX127X_RF_LORA_OCP_MASK (0xDF) +#define SX127X_RF_LORA_OCP_ON (0x20) /* Default */ +#define SX127X_RF_LORA_OCP_OFF (0x00) + +#define SX127X_RF_LORA_OCP_TRIM_MASK (0xE0) +#define SX127X_RF_LORA_OCP_TRIM_045_MA (0x00) +#define SX127X_RF_LORA_OCP_TRIM_050_MA (0x01) +#define SX127X_RF_LORA_OCP_TRIM_055_MA (0x02) +#define SX127X_RF_LORA_OCP_TRIM_060_MA (0x03) +#define SX127X_RF_LORA_OCP_TRIM_065_MA (0x04) +#define SX127X_RF_LORA_OCP_TRIM_070_MA (0x05) +#define SX127X_RF_LORA_OCP_TRIM_075_MA (0x06) +#define SX127X_RF_LORA_OCP_TRIM_080_MA (0x07) +#define SX127X_RF_LORA_OCP_TRIM_085_MA (0x08) +#define SX127X_RF_LORA_OCP_TRIM_090_MA (0x09) +#define SX127X_RF_LORA_OCP_TRIM_095_MA (0x0A) +#define SX127X_RF_LORA_OCP_TRIM_100_MA (0x0B) /* Default */ +#define SX127X_RF_LORA_OCP_TRIM_105_MA (0x0C) +#define SX127X_RF_LORA_OCP_TRIM_110_MA (0x0D) +#define SX127X_RF_LORA_OCP_TRIM_115_MA (0x0E) +#define SX127X_RF_LORA_OCP_TRIM_120_MA (0x0F) +#define SX127X_RF_LORA_OCP_TRIM_130_MA (0x10) +#define SX127X_RF_LORA_OCP_TRIM_140_MA (0x11) +#define SX127X_RF_LORA_OCP_TRIM_150_MA (0x12) +#define SX127X_RF_LORA_OCP_TRIM_160_MA (0x13) +#define SX127X_RF_LORA_OCP_TRIM_170_MA (0x14) +#define SX127X_RF_LORA_OCP_TRIM_180_MA (0x15) +#define SX127X_RF_LORA_OCP_TRIM_190_MA (0x16) +#define SX127X_RF_LORA_OCP_TRIM_200_MA (0x17) +#define SX127X_RF_LORA_OCP_TRIM_210_MA (0x18) +#define SX127X_RF_LORA_OCP_TRIM_220_MA (0x19) +#define SX127X_RF_LORA_OCP_TRIM_230_MA (0x1A) +#define SX127X_RF_LORA_OCP_TRIM_240_MA (0x1B) + +/* RegLna */ +#define SX127X_RF_LORA_LNA_GAIN_MASK (0x1F) +#define SX127X_RF_LORA_LNA_GAIN_G1 (0x20) /* Default */ +#define SX127X_RF_LORA_LNA_GAIN_G2 (0x40) +#define SX127X_RF_LORA_LNA_GAIN_G3 (0x60) +#define SX127X_RF_LORA_LNA_GAIN_G4 (0x80) +#define SX127X_RF_LORA_LNA_GAIN_G5 (0xA0) +#define SX127X_RF_LORA_LNA_GAIN_G6 (0xC0) + +#define SX127X_RF_LORA_LNA_BOOST_LF_MASK (0xE7) +#define SX127X_RF_LORA_LNA_BOOST_LF_DEFAULT (0x00) /* Default */ + +#define SX127X_RF_LORA_LNA_BOOST_HF_MASK (0xFC) +#define SX127X_RF_LORA_LNA_BOOST_HF_OFF (0x00) /* Default */ +#define SX127X_RF_LORA_LNA_BOOST_HF_ON (0x03) + +/* RegFifoAddrPtr */ +#define SX127X_RF_LORA_FIFOADDRPTR (0x00) /* Default */ + +/* RegFifoTxBaseAddr */ +#define SX127X_RF_LORA_FIFOTXBASEADDR (0x80) /* Default */ + +/* RegFifoTxBaseAddr */ +#define SX127X_RF_LORA_FIFORXBASEADDR (0x00) /* Default */ + +/* RegIrqFlagsMask */ +#define SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT_MASK (0x80) +#define SX127X_RF_LORA_IRQFLAGS_RXDONE_MASK (0x40) +#define SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR_MASK (0x20) +#define SX127X_RF_LORA_IRQFLAGS_VALIDHEADER_MASK (0x10) +#define SX127X_RF_LORA_IRQFLAGS_TXDONE_MASK (0x08) +#define SX127X_RF_LORA_IRQFLAGS_CADDONE_MASK (0x04) +#define SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL_MASK (0x02) +#define SX127X_RF_LORA_IRQFLAGS_CADDETECTED_MASK (0x01) + +/* RegIrqFlags */ +#define SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT (0x80) +#define SX127X_RF_LORA_IRQFLAGS_RXDONE (0x40) +#define SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR (0x20) +#define SX127X_RF_LORA_IRQFLAGS_VALIDHEADER (0x10) +#define SX127X_RF_LORA_IRQFLAGS_TXDONE (0x08) +#define SX127X_RF_LORA_IRQFLAGS_CADDONE (0x04) +#define SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL (0x02) +#define SX127X_RF_LORA_IRQFLAGS_CADDETECTED (0x01) + +/* RegModemStat (Read Only) */ +#define SX127X_RF_LORA_MODEMSTAT_RX_CR_MASK (0x1F) +#define SX127X_RF_LORA_MODEMSTAT_MODEM_STATUS_MASK (0xE0) + +/* RegHopChannel (Read Only) */ +#define SX127X_RF_LORA_HOPCHANNEL_PLL_LOCK_TIMEOUT_MASK (0x7F) +#define SX127X_RF_LORA_HOPCHANNEL_PLL_LOCK_FAIL (0x80) +#define SX127X_RF_LORA_HOPCHANNEL_PLL_LOCK_SUCCEED (0x00) /* Default */ + +#define SX127X_RF_LORA_HOPCHANNEL_CRCONPAYLOAD_MASK (0xBF) +#define SX127X_RF_LORA_HOPCHANNEL_CRCONPAYLOAD_ON (0x40) +#define SX127X_RF_LORA_HOPCHANNEL_CRCONPAYLOAD_OFF (0x00) /* Default */ + +#define SX127X_RF_LORA_HOPCHANNEL_CHANNEL_MASK (0x3F) + +/* RegModemConfig1 */ +#define SX1272_RF_LORA_MODEMCONFIG1_BW_MASK (0x3F) +#define SX1272_RF_LORA_MODEMCONFIG1_BW_125_KHZ (0x00) /* Default */ +#define SX1272_RF_LORA_MODEMCONFIG1_BW_250_KHZ (0x40) +#define SX1272_RF_LORA_MODEMCONFIG1_BW_500_KHZ (0x80) + +#define SX1276_RF_LORA_MODEMCONFIG1_BW_MASK (0x0F) +#define SX1276_RF_LORA_MODEMCONFIG1_BW_7_81_KHZ (0x00) +#define SX1276_RF_LORA_MODEMCONFIG1_BW_10_41_KHZ (0x10) +#define SX1276_RF_LORA_MODEMCONFIG1_BW_15_62_KHZ (0x20) +#define SX1276_RF_LORA_MODEMCONFIG1_BW_20_83_KHZ (0x30) +#define SX1276_RF_LORA_MODEMCONFIG1_BW_31_25_KHZ (0x40) +#define SX1276_RF_LORA_MODEMCONFIG1_BW_41_66_KHZ (0x50) +#define SX1276_RF_LORA_MODEMCONFIG1_BW_62_50_KHZ (0x60) +#define SX1276_RF_LORA_MODEMCONFIG1_BW_125_KHZ (0x70) /* Default */ +#define SX1276_RF_LORA_MODEMCONFIG1_BW_250_KHZ (0x80) +#define SX1276_RF_LORA_MODEMCONFIG1_BW_500_KHZ (0x90) + +#define SX1272_RF_LORA_MODEMCONFIG1_CODINGRATE_MASK (0xC7) +#define SX1272_RF_LORA_MODEMCONFIG1_CODINGRATE_4_5 (0x08) +#define SX1272_RF_LORA_MODEMCONFIG1_CODINGRATE_4_6 (0x10) /* Default */ +#define SX1272_RF_LORA_MODEMCONFIG1_CODINGRATE_4_7 (0x18) +#define SX1272_RF_LORA_MODEMCONFIG1_CODINGRATE_4_8 (0x20) + +#define SX1276_RF_LORA_MODEMCONFIG1_CODINGRATE_MASK (0xF1) +#define SX1276_RF_LORA_MODEMCONFIG1_CODINGRATE_4_5 (0x02) +#define SX1276_RF_LORA_MODEMCONFIG1_CODINGRATE_4_6 (0x04) /* Default */ +#define SX1276_RF_LORA_MODEMCONFIG1_CODINGRATE_4_7 (0x06) +#define SX1276_RF_LORA_MODEMCONFIG1_CODINGRATE_4_8 (0x08) + +#define SX1272_RF_LORA_MODEMCONFIG1_IMPLICITHEADER_MASK (0xFB) +#define SX1276_RF_LORA_MODEMCONFIG1_IMPLICITHEADER_MASK (0xFE) +#define SX127X_RF_LORA_MODEMCONFIG1_IMPLICITHEADER_ON (0x01) +#define SX127X_RF_LORA_MODEMCONFIG1_IMPLICITHEADER_OFF (0x00) /* Default */ + +#define SX1272_RF_LORA_MODEMCONFIG1_RXPAYLOADCRC_MASK (0xFD) +#define SX1272_RF_LORA_MODEMCONFIG1_RXPAYLOADCRC_ON (0x02) +#define SX1272_RF_LORA_MODEMCONFIG1_RXPAYLOADCRC_OFF (0x00) /* Default */ + +#define SX127X_RF_LORA_MODEMCONFIG1_LOWDATARATEOPTIMIZE_MASK (0xFE) + +/* RegModemConfig2 */ +#define SX127X_RF_LORA_MODEMCONFIG2_SF_MASK (0x0F) +#define SX127X_RF_LORA_MODEMCONFIG2_SF_6 (0x60) +#define SX127X_RF_LORA_MODEMCONFIG2_SF_7 (0x70) /* Default */ +#define SX127X_RF_LORA_MODEMCONFIG2_SF_8 (0x80) +#define SX127X_RF_LORA_MODEMCONFIG2_SF_9 (0x90) +#define SX127X_RF_LORA_MODEMCONFIG2_SF_10 (0xA0) +#define SX127X_RF_LORA_MODEMCONFIG2_SF_11 (0xB0) +#define SX127X_RF_LORA_MODEMCONFIG2_SF_12 (0xC0) + +#define SX127X_RF_LORA_MODEMCONFIG2_TXCONTINUOUSMODE_MASK (0xF7) +#define SX127X_RF_LORA_MODEMCONFIG2_TXCONTINUOUSMODE_ON (0x08) +#define SX127X_RF_LORA_MODEMCONFIG2_TXCONTINUOUSMODE_OFF (0x00) + +#define SX1276_RF_LORA_MODEMCONFIG2_RXPAYLOADCRC_MASK (0xFB) +#define SX1276_RF_LORA_MODEMCONFIG2_RXPAYLOADCRC_ON (0x04) +#define SX1276_RF_LORA_MODEMCONFIG2_RXPAYLOADCRC_OFF (0x00) /* Default */ + +#define SX127X_RF_LORA_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK (0xFC) +#define SX127X_RF_LORA_MODEMCONFIG2_SYMBTIMEOUTMSB (0x00) /* Default */ + +/* RegSymbTimeoutLsb */ +#define SX127X_RF_LORA_SYMBTIMEOUTLSB_SYMBTIMEOUT (0x64) /* Default */ + +/* RegPreambleLengthMsb */ +#define SX127X_RF_LORA_PREAMBLELENGTHMSB (0x00) /* Default */ + +/* RegPreambleLengthLsb */ +#define SX127X_RF_LORA_PREAMBLELENGTHLSB (0x08) /* Default */ + +/* RegPayloadLength */ +#define SX127X_RF_LORA_PAYLOADLENGTH (0x0E) /* Default */ + +/* RegPayloadMaxLength */ +#define SX127X_RF_LORA_PAYLOADMAXLENGTH (0xFF) /* Default */ + +/* RegHopPeriod */ +#define SX127X_RF_LORA_HOPPERIOD_FREQFOPPINGPERIOD (0x00) /* Default */ + +/* RegModemConfig3 */ +#define SX127X_RF_LORA_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK (0xF7) +#define SX127X_RF_LORA_MODEMCONFIG3_LOWDATARATEOPTIMIZE_ON (0x08) +#define SX127X_RF_LORA_MODEMCONFIG3_LOWDATARATEOPTIMIZE_OFF (0x00) /* Default */ + +#define SX127X_RF_LORA_MODEMCONFIG3_AGCAUTO_MASK (0xFB) +#define SX127X_RF_LORA_MODEMCONFIG3_AGCAUTO_ON (0x04) /* Default */ +#define SX127X_RF_LORA_MODEMCONFIG3_AGCAUTO_OFF (0x00) + +/* RegDetectOptimize */ +#define SX127X_RF_LORA_DETECTIONOPTIMIZE_MASK (0xF8) +#define SX127X_RF_LORA_DETECTIONOPTIMIZE_SF7_TO_SF12 (0x03) /* Default */ +#define SX127X_RF_LORA_DETECTIONOPTIMIZE_SF6 (0x05) + +/* RegInvertIQ */ +#define SX127X_RF_LORA_INVERTIQ_RX_MASK (0xBF) +#define SX127X_RF_LORA_INVERTIQ_RX_OFF (0x00) +#define SX127X_RF_LORA_INVERTIQ_RX_ON (0x40) +#define SX127X_RF_LORA_INVERTIQ_TX_MASK (0xFE) +#define SX127X_RF_LORA_INVERTIQ_TX_OFF (0x01) +#define SX127X_RF_LORA_INVERTIQ_TX_ON (0x00) + +/* RegDetectionThreshold */ +#define SX127X_RF_LORA_DETECTIONTHRESH_SF7_TO_SF12 (0x0A) /* Default */ +#define SX127X_RF_LORA_DETECTIONTHRESH_SF6 (0x0C) + +/* RegInvertIQ2 */ +#define SX127X_RF_LORA_INVERTIQ2_ON (0x19) +#define SX127X_RF_LORA_INVERTIQ2_OFF (0x1D) + +/* RegDioMapping1 */ +#define SX127X_RF_LORA_DIOMAPPING1_DIO0_MASK (0x3F) +#define SX127X_RF_LORA_DIOMAPPING1_DIO0_00 (0x00) /* Default */ +#define SX127X_RF_LORA_DIOMAPPING1_DIO0_01 (0x40) +#define SX127X_RF_LORA_DIOMAPPING1_DIO0_10 (0x80) +#define SX127X_RF_LORA_DIOMAPPING1_DIO0_11 (0xC0) + +#define SX127X_RF_LORA_DIOMAPPING1_DIO1_MASK (0xCF) +#define SX127X_RF_LORA_DIOMAPPING1_DIO1_00 (0x00) /* Default */ +#define SX127X_RF_LORA_DIOMAPPING1_DIO1_01 (0x10) +#define SX127X_RF_LORA_DIOMAPPING1_DIO1_10 (0x20) +#define SX127X_RF_LORA_DIOMAPPING1_DIO1_11 (0x30) + +#define SX127X_RF_LORA_DIOMAPPING1_DIO2_MASK (0xF3) +#define SX127X_RF_LORA_DIOMAPPING1_DIO2_00 (0x00) /* Default */ +#define SX127X_RF_LORA_DIOMAPPING1_DIO2_01 (0x04) +#define SX127X_RF_LORA_DIOMAPPING1_DIO2_10 (0x08) +#define SX127X_RF_LORA_DIOMAPPING1_DIO2_11 (0x0C) + +#define SX127X_RF_LORA_DIOMAPPING1_DIO3_MASK (0xFC) +#define SX127X_RF_LORA_DIOMAPPING1_DIO3_00 (0x00) /* Default */ +#define SX127X_RF_LORA_DIOMAPPING1_DIO3_01 (0x01) +#define SX127X_RF_LORA_DIOMAPPING1_DIO3_10 (0x02) +#define SX127X_RF_LORA_DIOMAPPING1_DIO3_11 (0x03) + +/* RegDioMapping2 */ +#define SX127X_RF_LORA_DIOMAPPING2_DIO4_MASK (0x3F) +#define SX127X_RF_LORA_DIOMAPPING2_DIO4_00 (0x00) /* Default */ +#define SX127X_RF_LORA_DIOMAPPING2_DIO4_01 (0x40) +#define SX127X_RF_LORA_DIOMAPPING2_DIO4_10 (0x80) +#define SX127X_RF_LORA_DIOMAPPING2_DIO4_11 (0xC0) + +#define SX127X_RF_LORA_DIOMAPPING2_DIO5_MASK (0xCF) +#define SX127X_RF_LORA_DIOMAPPING2_DIO5_00 (0x00) /* Default */ +#define SX127X_RF_LORA_DIOMAPPING2_DIO5_01 (0x10) +#define SX127X_RF_LORA_DIOMAPPING2_DIO5_10 (0x20) +#define SX127X_RF_LORA_DIOMAPPING2_DIO5_11 (0x30) + +#define SX127X_RF_LORA_DIOMAPPING2_MAP_MASK (0xFE) +#define SX127X_RF_LORA_DIOMAPPING2_MAP_PREAMBLEDETECT (0x01) +#define SX127X_RF_LORA_DIOMAPPING2_MAP_RSSI (0x00) /* Default */ + +/* RegPllHop */ +#define SX127X_RF_LORA_PLLHOP_FASTHOP_MASK (0x7F) +#define SX127X_RF_LORA_PLLHOP_FASTHOP_ON (0x80) +#define SX127X_RF_LORA_PLLHOP_FASTHOP_OFF (0x00) /* Default */ + +/* RegTcxo */ +#define SX127X_RF_LORA_TCXO_TCXOINPUT_MASK (0xEF) +#define SX127X_RF_LORA_TCXO_TCXOINPUT_ON (0x10) +#define SX127X_RF_LORA_TCXO_TCXOINPUT_OFF (0x00) /* Default */ + +/* RegPaDac */ +#define SX127X_RF_LORA_PADAC_20DBM_MASK (0xF8) +#define SX127X_RF_LORA_PADAC_20DBM_ON (0x07) +#define SX127X_RF_LORA_PADAC_20DBM_OFF (0x04) /* Default */ + +/* RegBitrateFrac */ +#define RF_BITRATEFRAC_MASK (0xF0) + +/* RegPll */ +#define RF_PLL_BANDWIDTH_MASK (0x3F) +#define RF_PLL_BANDWIDTH_75 (0x00) +#define RF_PLL_BANDWIDTH_150 (0x40) +#define RF_PLL_BANDWIDTH_225 (0x80) +#define RF_PLL_BANDWIDTH_300 (0xC0) /* Default */ +/** @} */ + + +/* FSK modem definitions */ + +/** + * @name SX127X FSK modem internal registers address + * @{ + */ +#define SX127X_REG_FIFO (0x00) + +/* Common settings */ +#define SX127X_REG_OPMODE (0x01) +#define SX127X_REG_BITRATEMSB (0x02) +#define SX127X_REG_BITRATELSB (0x03) +#define SX127X_REG_FDEVMSB (0x04) +#define SX127X_REG_FDEVLSB (0x05) +#define SX127X_REG_FRFMSB (0x06) +#define SX127X_REG_FRFMID (0x07) +#define SX127X_REG_FRFLSB (0x08) + +/* Tx settings */ +#define SX127X_REG_PACONFIG (0x09) +#define SX127X_REG_PARAMP (0x0A) +#define SX127X_REG_OCP (0x0B) + +/* Rx settings */ +#define SX127X_REG_LNA (0x0C) +#define SX127X_REG_RXCONFIG (0x0D) +#define SX127X_REG_RSSICONFIG (0x0E) +#define SX127X_REG_RSSICOLLISION (0x0F) +#define SX127X_REG_RSSITHRESH (0x10) +#define SX127X_REG_RSSIVALUE (0x11) +#define SX127X_REG_RXBW (0x12) +#define SX127X_REG_AFCBW (0x13) +#define SX127X_REG_OOKPEAK (0x14) +#define SX127X_REG_OOKFIX (0x15) +#define SX127X_REG_OOKAVG (0x16) +#define SX127X_REG_RES17 (0x17) +#define SX127X_REG_RES18 (0x18) +#define SX127X_REG_RES19 (0x19) +#define SX127X_REG_AFCFEI (0x1A) +#define SX127X_REG_AFCMSB (0x1B) +#define SX127X_REG_AFCLSB (0x1C) +#define SX127X_REG_FEIMSB (0x1D) +#define SX127X_REG_FEILSB (0x1E) +#define SX127X_REG_PREAMBLEDETECT (0x1F) +#define SX127X_REG_RXTIMEOUT1 (0x20) +#define SX127X_REG_RXTIMEOUT2 (0x21) +#define SX127X_REG_RXTIMEOUT3 (0x22) +#define SX127X_REG_RXDELAY (0x23) + +/* Oscillator settings */ +#define SX127X_REG_OSC (0x24) + +/* Packet handler settings */ +#define SX127X_REG_PREAMBLEMSB (0x25) +#define SX127X_REG_PREAMBLELSB (0x26) +#define SX127X_REG_SYNCCONFIG (0x27) +#define SX127X_REG_SYNCVALUE1 (0x28) +#define SX127X_REG_SYNCVALUE2 (0x29) +#define SX127X_REG_SYNCVALUE3 (0x2A) +#define SX127X_REG_SYNCVALUE4 (0x2B) +#define SX127X_REG_SYNCVALUE5 (0x2C) +#define SX127X_REG_SYNCVALUE6 (0x2D) +#define SX127X_REG_SYNCVALUE7 (0x2E) +#define SX127X_REG_SYNCVALUE8 (0x2F) +#define SX127X_REG_PACKETCONFIG1 (0x30) +#define SX127X_REG_PACKETCONFIG2 (0x31) +#define SX127X_REG_PAYLOADLENGTH (0x32) +#define SX127X_REG_NODEADRS (0x33) +#define SX127X_REG_BROADCASTADRS (0x34) +#define SX127X_REG_FIFOTHRESH (0x35) + +/* SM settings */ +#define SX127X_REG_SEQCONFIG1 (0x36) +#define SX127X_REG_SEQCONFIG2 (0x37) +#define SX127X_REG_TIMERRESOL (0x38) +#define SX127X_REG_TIMER1COEF (0x39) +#define SX127X_REG_TIMER2COEF (0x3A) + +/* Service settings */ +#define SX127X_REG_IMAGECAL (0x3B) +#define SX127X_REG_TEMP (0x3C) +#define SX127X_REG_LOWBAT (0x3D) + +/* Status */ +#define SX127X_REG_IRQFLAGS1 (0x3E) +#define SX127X_REG_IRQFLAGS2 (0x3F) + +/* I/O settings */ +#define SX127X_REG_DIOMAPPING1 (0x40) +#define SX127X_REG_DIOMAPPING2 (0x41) + +/* Version */ +#define SX127X_REG_VERSION (0x42) +#define VERSION_SX1276 (0x12) +#define VERSION_SX1272 (0x22) + +/* Additional settings */ +#define SX127X_REG_PLLHOP (0x44) +#define SX127X_REG_TCXO (0x4B) +#define SX1276_REG_PADAC (0x4D) +#define SX1272_REG_PADAC (0x5A) +#define SX127X_REG_FORMERTEMP (0x5B) +#define SX127X_REG_BITRATEFRAC (0x5D) +#define SX127X_REG_AGCREF (0x61) +#define SX127X_REG_AGCTHRESH1 (0x62) +#define SX127X_REG_AGCTHRESH2 (0x63) +#define SX127X_REG_AGCTHRESH3 (0x64) +#define SX127X_REG_PLL (0x70) +/** @} */ + +/** + * @name SX127X FSK bits control definition + * @{ + */ + +/* RegOpMode */ +#define SX127X_RF_OPMODE_LONGRANGEMODE_MASK (0x7F) +#define SX127X_RF_OPMODE_LONGRANGEMODE_OFF (0x00) +#define SX127X_RF_OPMODE_LONGRANGEMODE_ON (0x80) + +#define SX127X_RF_OPMODE_MODULATIONTYPE_MASK (0x9F) +#define SX127X_RF_OPMODE_MODULATIONTYPE_FSK (0x00) /* Default */ +#define SX127X_RF_OPMODE_MODULATIONTYPE_OOK (0x20) + +#define SX127X_RF_OPMODE_MODULATIONSHAPING_MASK (0xE7) +#define SX127X_RF_OPMODE_MODULATIONSHAPING_00 (0x00) /* Default */ +#define SX127X_RF_OPMODE_MODULATIONSHAPING_01 (0x08) +#define SX127X_RF_OPMODE_MODULATIONSHAPING_10 (0x10) +#define SX127X_RF_OPMODE_MODULATIONSHAPING_11 (0x18) + +#define SX127X_RF_OPMODE_MASK (0xF8) +#define SX127X_RF_OPMODE_SLEEP (0x00) +#define SX127X_RF_OPMODE_STANDBY (0x01) /* Default */ +#define SX127X_RF_OPMODE_SYNTHESIZER_TX (0x02) +#define SX127X_RF_OPMODE_TRANSMITTER (0x03) +#define SX127X_RF_OPMODE_SYNTHESIZER_RX (0x04) +#define SX127X_RF_OPMODE_RECEIVER (0x05) + +/* RegBitRate (bits/sec) */ +#define SX127X_RF_BITRATEMSB_1200_BPS (0x68) +#define SX127X_RF_BITRATELSB_1200_BPS (0x2B) +#define SX127X_RF_BITRATEMSB_2400_BPS (0x34) +#define SX127X_RF_BITRATELSB_2400_BPS (0x15) +#define SX127X_RF_BITRATEMSB_4800_BPS (0x1A) /* Default */ +#define SX127X_RF_BITRATELSB_4800_BPS (0x0B) /* Default */ +#define SX127X_RF_BITRATEMSB_9600_BPS (0x0D) +#define SX127X_RF_BITRATELSB_9600_BPS (0x05) +#define SX127X_RF_BITRATEMSB_15000_BPS (0x08) +#define SX127X_RF_BITRATELSB_15000_BPS (0x55) +#define SX127X_RF_BITRATEMSB_19200_BPS (0x06) +#define SX127X_RF_BITRATELSB_19200_BPS (0x83) +#define SX127X_RF_BITRATEMSB_38400_BPS (0x03) +#define SX127X_RF_BITRATELSB_38400_BPS (0x41) +#define SX127X_RF_BITRATEMSB_76800_BPS (0x01) +#define SX127X_RF_BITRATELSB_76800_BPS (0xA1) +#define SX127X_RF_BITRATEMSB_153600_BPS (0x00) +#define SX127X_RF_BITRATELSB_153600_BPS (0xD0) +#define SX127X_RF_BITRATEMSB_57600_BPS (0x02) +#define SX127X_RF_BITRATELSB_57600_BPS (0x2C) +#define SX127X_RF_BITRATEMSB_115200_BPS (0x01) +#define SX127X_RF_BITRATELSB_115200_BPS (0x16) +#define SX127X_RF_BITRATEMSB_12500_BPS (0x0A) +#define SX127X_RF_BITRATELSB_12500_BPS (0x00) +#define SX127X_RF_BITRATEMSB_25000_BPS (0x05) +#define SX127X_RF_BITRATELSB_25000_BPS (0x00) +#define SX127X_RF_BITRATEMSB_50000_BPS (0x02) +#define SX127X_RF_BITRATELSB_50000_BPS (0x80) +#define SX127X_RF_BITRATEMSB_100000_BPS (0x01) +#define SX127X_RF_BITRATELSB_100000_BPS (0x40) +#define SX127X_RF_BITRATEMSB_150000_BPS (0x00) +#define SX127X_RF_BITRATELSB_150000_BPS (0xD5) +#define SX127X_RF_BITRATEMSB_200000_BPS (0x00) +#define SX127X_RF_BITRATELSB_200000_BPS (0xA0) +#define SX127X_RF_BITRATEMSB_250000_BPS (0x00) +#define SX127X_RF_BITRATELSB_250000_BPS (0x80) +#define SX127X_RF_BITRATEMSB_32768_BPS (0x03) +#define SX127X_RF_BITRATELSB_32768_BPS (0xD1) + +/* RegFdev (Hz) */ +#define SX127X_RF_FDEVMSB_2000_HZ (0x00) +#define SX127X_RF_FDEVLSB_2000_HZ (0x21) +#define SX127X_RF_FDEVMSB_5000_HZ (0x00) /* Default */ +#define SX127X_RF_FDEVLSB_5000_HZ (0x52) /* Default */ +#define SX127X_RF_FDEVMSB_10000_HZ (0x00) +#define SX127X_RF_FDEVLSB_10000_HZ (0xA4) +#define SX127X_RF_FDEVMSB_15000_HZ (0x00) +#define SX127X_RF_FDEVLSB_15000_HZ (0xF6) +#define SX127X_RF_FDEVMSB_20000_HZ (0x01) +#define SX127X_RF_FDEVLSB_20000_HZ (0x48) +#define SX127X_RF_FDEVMSB_25000_HZ (0x01) +#define SX127X_RF_FDEVLSB_25000_HZ (0x9A) +#define SX127X_RF_FDEVMSB_30000_HZ (0x01) +#define SX127X_RF_FDEVLSB_30000_HZ (0xEC) +#define SX127X_RF_FDEVMSB_35000_HZ (0x02) +#define SX127X_RF_FDEVLSB_35000_HZ (0x3D) +#define SX127X_RF_FDEVMSB_40000_HZ (0x02) +#define SX127X_RF_FDEVLSB_40000_HZ (0x8F) +#define SX127X_RF_FDEVMSB_45000_HZ (0x02) +#define SX127X_RF_FDEVLSB_45000_HZ (0xE1) +#define SX127X_RF_FDEVMSB_50000_HZ (0x03) +#define SX127X_RF_FDEVLSB_50000_HZ (0x33) +#define SX127X_RF_FDEVMSB_55000_HZ (0x03) +#define SX127X_RF_FDEVLSB_55000_HZ (0x85) +#define SX127X_RF_FDEVMSB_60000_HZ (0x03) +#define SX127X_RF_FDEVLSB_60000_HZ (0xD7) +#define SX127X_RF_FDEVMSB_65000_HZ (0x04) +#define SX127X_RF_FDEVLSB_65000_HZ (0x29) +#define SX127X_RF_FDEVMSB_70000_HZ (0x04) +#define SX127X_RF_FDEVLSB_70000_HZ (0x7B) +#define SX127X_RF_FDEVMSB_75000_HZ (0x04) +#define SX127X_RF_FDEVLSB_75000_HZ (0xCD) +#define SX127X_RF_FDEVMSB_80000_HZ (0x05) +#define SX127X_RF_FDEVLSB_80000_HZ (0x1F) +#define SX127X_RF_FDEVMSB_85000_HZ (0x05) +#define SX127X_RF_FDEVLSB_85000_HZ (0x71) +#define SX127X_RF_FDEVMSB_90000_HZ (0x05) +#define SX127X_RF_FDEVLSB_90000_HZ (0xC3) +#define SX127X_RF_FDEVMSB_95000_HZ (0x06) +#define SX127X_RF_FDEVLSB_95000_HZ (0x14) +#define SX127X_RF_FDEVMSB_100000_HZ (0x06) +#define SX127X_RF_FDEVLSB_100000_HZ (0x66) +#define SX127X_RF_FDEVMSB_110000_HZ (0x07) +#define SX127X_RF_FDEVLSB_110000_HZ (0x0A) +#define SX127X_RF_FDEVMSB_120000_HZ (0x07) +#define SX127X_RF_FDEVLSB_120000_HZ (0xAE) +#define SX127X_RF_FDEVMSB_130000_HZ (0x08) +#define SX127X_RF_FDEVLSB_130000_HZ (0x52) +#define SX127X_RF_FDEVMSB_140000_HZ (0x08) +#define SX127X_RF_FDEVLSB_140000_HZ (0xF6) +#define SX127X_RF_FDEVMSB_150000_HZ (0x09) +#define SX127X_RF_FDEVLSB_150000_HZ (0x9A) +#define SX127X_RF_FDEVMSB_160000_HZ (0x0A) +#define SX127X_RF_FDEVLSB_160000_HZ (0x3D) +#define SX127X_RF_FDEVMSB_170000_HZ (0x0A) +#define SX127X_RF_FDEVLSB_170000_HZ (0xE1) +#define SX127X_RF_FDEVMSB_180000_HZ (0x0B) +#define SX127X_RF_FDEVLSB_180000_HZ (0x85) +#define SX127X_RF_FDEVMSB_190000_HZ (0x0C) +#define SX127X_RF_FDEVLSB_190000_HZ (0x29) +#define SX127X_RF_FDEVMSB_200000_HZ (0x0C) +#define SX127X_RF_FDEVLSB_200000_HZ (0xCD) + +/* RegFrf (MHz) */ +#define SX127X_RF_FRFMSB_863_MHZ (0xD7) +#define SX127X_RF_FRFMID_863_MHZ (0xC0) +#define SX127X_RF_FRFLSB_863_MHZ (0x00) +#define SX127X_RF_FRFMSB_864_MHZ (0xD8) +#define SX127X_RF_FRFMID_864_MHZ (0x00) +#define SX127X_RF_FRFLSB_864_MHZ (0x00) +#define SX127X_RF_FRFMSB_865_MHZ (0xD8) +#define SX127X_RF_FRFMID_865_MHZ (0x40) +#define SX127X_RF_FRFLSB_865_MHZ (0x00) +#define SX127X_RF_FRFMSB_866_MHZ (0xD8) +#define SX127X_RF_FRFMID_866_MHZ (0x80) +#define SX127X_RF_FRFLSB_866_MHZ (0x00) +#define SX127X_RF_FRFMSB_867_MHZ (0xD8) +#define SX127X_RF_FRFMID_867_MHZ (0xC0) +#define SX127X_RF_FRFLSB_867_MHZ (0x00) +#define SX127X_RF_FRFMSB_868_MHZ (0xD9) +#define SX127X_RF_FRFMID_868_MHZ (0x00) +#define SX127X_RF_FRFLSB_868_MHZ (0x00) +#define SX127X_RF_FRFMSB_869_MHZ (0xD9) +#define SX127X_RF_FRFMID_869_MHZ (0x40) +#define SX127X_RF_FRFLSB_869_MHZ (0x00) +#define SX127X_RF_FRFMSB_870_MHZ (0xD9) +#define SX127X_RF_FRFMID_870_MHZ (0x80) +#define SX127X_RF_FRFLSB_870_MHZ (0x00) + +#define SX127X_RF_FRFMSB_902_MHZ (0xE1) +#define SX127X_RF_FRFMID_902_MHZ (0x80) +#define SX127X_RF_FRFLSB_902_MHZ (0x00) +#define SX127X_RF_FRFMSB_903_MHZ (0xE1) +#define SX127X_RF_FRFMID_903_MHZ (0xC0) +#define SX127X_RF_FRFLSB_903_MHZ (0x00) +#define SX127X_RF_FRFMSB_904_MHZ (0xE2) +#define SX127X_RF_FRFMID_904_MHZ (0x00) +#define SX127X_RF_FRFLSB_904_MHZ (0x00) +#define SX127X_RF_FRFMSB_905_MHZ (0xE2) +#define SX127X_RF_FRFMID_905_MHZ (0x40) +#define SX127X_RF_FRFLSB_905_MHZ (0x00) +#define SX127X_RF_FRFMSB_906_MHZ (0xE2) +#define SX127X_RF_FRFMID_906_MHZ (0x80) +#define SX127X_RF_FRFLSB_906_MHZ (0x00) +#define SX127X_RF_FRFMSB_907_MHZ (0xE2) +#define SX127X_RF_FRFMID_907_MHZ (0xC0) +#define SX127X_RF_FRFLSB_907_MHZ (0x00) +#define SX127X_RF_FRFMSB_908_MHZ (0xE3) +#define SX127X_RF_FRFMID_908_MHZ (0x00) +#define SX127X_RF_FRFLSB_908_MHZ (0x00) +#define SX127X_RF_FRFMSB_909_MHZ (0xE3) +#define SX127X_RF_FRFMID_909_MHZ (0x40) +#define SX127X_RF_FRFLSB_909_MHZ (0x00) +#define SX127X_RF_FRFMSB_910_MHZ (0xE3) +#define SX127X_RF_FRFMID_910_MHZ (0x80) +#define SX127X_RF_FRFLSB_910_MHZ (0x00) +#define SX127X_RF_FRFMSB_911_MHZ (0xE3) +#define SX127X_RF_FRFMID_911_MHZ (0xC0) +#define SX127X_RF_FRFLSB_911_MHZ (0x00) +#define SX127X_RF_FRFMSB_912_MHZ (0xE4) +#define SX127X_RF_FRFMID_912_MHZ (0x00) +#define SX127X_RF_FRFLSB_912_MHZ (0x00) +#define SX127X_RF_FRFMSB_913_MHZ (0xE4) +#define SX127X_RF_FRFMID_913_MHZ (0x40) +#define SX127X_RF_FRFLSB_913_MHZ (0x00) +#define SX127X_RF_FRFMSB_914_MHZ (0xE4) +#define SX127X_RF_FRFMID_914_MHZ (0x80) +#define SX127X_RF_FRFLSB_914_MHZ (0x00) +#define SX127X_RF_FRFMSB_915_MHZ (0xE4) /* Default */ +#define SX127X_RF_FRFMID_915_MHZ (0xC0) /* Default */ +#define SX127X_RF_FRFLSB_915_MHZ (0x00) /* Default */ +#define SX127X_RF_FRFMSB_916_MHZ (0xE5) +#define SX127X_RF_FRFMID_916_MHZ (0x00) +#define SX127X_RF_FRFLSB_916_MHZ (0x00) +#define SX127X_RF_FRFMSB_917_MHZ (0xE5) +#define SX127X_RF_FRFMID_917_MHZ (0x40) +#define SX127X_RF_FRFLSB_917_MHZ (0x00) +#define SX127X_RF_FRFMSB_918_MHZ (0xE5) +#define SX127X_RF_FRFMID_918_MHZ (0x80) +#define SX127X_RF_FRFLSB_918_MHZ (0x00) +#define SX127X_RF_FRFMSB_919_MHZ (0xE5) +#define SX127X_RF_FRFMID_919_MHZ (0xC0) +#define SX127X_RF_FRFLSB_919_MHZ (0x00) +#define SX127X_RF_FRFMSB_920_MHZ (0xE6) +#define SX127X_RF_FRFMID_920_MHZ (0x00) +#define SX127X_RF_FRFLSB_920_MHZ (0x00) +#define SX127X_RF_FRFMSB_921_MHZ (0xE6) +#define SX127X_RF_FRFMID_921_MHZ (0x40) +#define SX127X_RF_FRFLSB_921_MHZ (0x00) +#define SX127X_RF_FRFMSB_922_MHZ (0xE6) +#define SX127X_RF_FRFMID_922_MHZ (0x80) +#define SX127X_RF_FRFLSB_922_MHZ (0x00) +#define SX127X_RF_FRFMSB_923_MHZ (0xE6) +#define SX127X_RF_FRFMID_923_MHZ (0xC0) +#define SX127X_RF_FRFLSB_923_MHZ (0x00) +#define SX127X_RF_FRFMSB_924_MHZ (0xE7) +#define SX127X_RF_FRFMID_924_MHZ (0x00) +#define SX127X_RF_FRFLSB_924_MHZ (0x00) +#define SX127X_RF_FRFMSB_925_MHZ (0xE7) +#define SX127X_RF_FRFMID_925_MHZ (0x40) +#define SX127X_RF_FRFLSB_925_MHZ (0x00) +#define SX127X_RF_FRFMSB_926_MHZ (0xE7) +#define SX127X_RF_FRFMID_926_MHZ (0x80) +#define SX127X_RF_FRFLSB_926_MHZ (0x00) +#define SX127X_RF_FRFMSB_927_MHZ (0xE7) +#define SX127X_RF_FRFMID_927_MHZ (0xC0) +#define SX127X_RF_FRFLSB_927_MHZ (0x00) +#define SX127X_RF_FRFMSB_928_MHZ (0xE8) +#define SX127X_RF_FRFMID_928_MHZ (0x00) +#define SX127X_RF_FRFLSB_928_MHZ (0x00) + +/* RegPaConfig */ +#define SX127X_RF_PACONFIG_PASELECT_MASK (0x7F) +#define SX127X_RF_PACONFIG_PASELECT_PABOOST (0x80) +#define SX127X_RF_PACONFIG_PASELECT_RFO (0x00) /* Default */ + +#define SX127X_RF_PACONFIG_MAX_POWER_MASK (0x8F) + +#define SX127X_RF_PACONFIG_OUTPUTPOWER_MASK (0xF0) + +/* RegPaRamp */ +#define SX127X_RF_PARAMP_LOWPNTXPLL_MASK (0xE0) +#define SX127X_RF_PARAMP_LOWPNTXPLL_OFF (0x10) /* Default */ +#define SX127X_RF_PARAMP_LOWPNTXPLL_ON (0x00) + +#define SX127X_RF_PARAMP_MASK (0xF0) +#define SX127X_RF_PARAMP_3400_US (0x00) +#define SX127X_RF_PARAMP_2000_US (0x01) +#define SX127X_RF_PARAMP_1000_US (0x02) +#define SX127X_RF_PARAMP_0500_US (0x03) +#define SX127X_RF_PARAMP_0250_US (0x04) +#define SX127X_RF_PARAMP_0125_US (0x05) +#define SX127X_RF_PARAMP_0100_US (0x06) +#define SX127X_RF_PARAMP_0062_US (0x07) +#define SX127X_RF_PARAMP_0050_US (0x08) +#define SX127X_RF_PARAMP_0040_US (0x09) /* Default */ +#define SX127X_RF_PARAMP_0031_US (0x0A) +#define SX127X_RF_PARAMP_0025_US (0x0B) +#define SX127X_RF_PARAMP_0020_US (0x0C) +#define SX127X_RF_PARAMP_0015_US (0x0D) +#define SX127X_RF_PARAMP_0012_US (0x0E) +#define SX127X_RF_PARAMP_0010_US (0x0F) + +/* RegOcp */ +#define SX127X_RF_OCP_MASK (0xDF) +#define SX127X_RF_OCP_ON (0x20) /* Default */ +#define SX127X_RF_OCP_OFF (0x00) + +#define SX127X_RF_OCP_TRIM_MASK (0xE0) +#define SX127X_RF_OCP_TRIM_045_MA (0x00) +#define SX127X_RF_OCP_TRIM_050_MA (0x01) +#define SX127X_RF_OCP_TRIM_055_MA (0x02) +#define SX127X_RF_OCP_TRIM_060_MA (0x03) +#define SX127X_RF_OCP_TRIM_065_MA (0x04) +#define SX127X_RF_OCP_TRIM_070_MA (0x05) +#define SX127X_RF_OCP_TRIM_075_MA (0x06) +#define SX127X_RF_OCP_TRIM_080_MA (0x07) +#define SX127X_RF_OCP_TRIM_085_MA (0x08) +#define SX127X_RF_OCP_TRIM_090_MA (0x09) +#define SX127X_RF_OCP_TRIM_095_MA (0x0A) +#define SX127X_RF_OCP_TRIM_100_MA (0x0B) /* Default */ +#define SX127X_RF_OCP_TRIM_105_MA (0x0C) +#define SX127X_RF_OCP_TRIM_110_MA (0x0D) +#define SX127X_RF_OCP_TRIM_115_MA (0x0E) +#define SX127X_RF_OCP_TRIM_120_MA (0x0F) +#define SX127X_RF_OCP_TRIM_130_MA (0x10) +#define SX127X_RF_OCP_TRIM_140_MA (0x11) +#define SX127X_RF_OCP_TRIM_150_MA (0x12) +#define SX127X_RF_OCP_TRIM_160_MA (0x13) +#define SX127X_RF_OCP_TRIM_170_MA (0x14) +#define SX127X_RF_OCP_TRIM_180_MA (0x15) +#define SX127X_RF_OCP_TRIM_190_MA (0x16) +#define SX127X_RF_OCP_TRIM_200_MA (0x17) +#define SX127X_RF_OCP_TRIM_210_MA (0x18) +#define SX127X_RF_OCP_TRIM_220_MA (0x19) +#define SX127X_RF_OCP_TRIM_230_MA (0x1A) +#define SX127X_RF_OCP_TRIM_240_MA (0x1B) + +/* RegLna */ +#define SX127X_RF_LNA_GAIN_MASK (0x1F) +#define SX127X_RF_LNA_GAIN_G1 (0x20) /* Default */ +#define SX127X_RF_LNA_GAIN_G2 (0x40) +#define SX127X_RF_LNA_GAIN_G3 (0x60) +#define SX127X_RF_LNA_GAIN_G4 (0x80) +#define SX127X_RF_LNA_GAIN_G5 (0xA0) +#define SX127X_RF_LNA_GAIN_G6 (0xC0) + +#define SX127X_RF_LNA_BOOST_MASK (0xFC) +#define SX127X_RF_LNA_BOOST_OFF (0x00) /* Default */ +#define SX127X_RF_LNA_BOOST_ON (0x03) + +/* RegRxConfig */ +#define SX127X_RF_RXCONFIG_RESTARTRXONCOLLISION_MASK (0x7F) +#define SX127X_RF_RXCONFIG_RESTARTRXONCOLLISION_ON (0x80) +#define SX127X_RF_RXCONFIG_RESTARTRXONCOLLISION_OFF (0x00) /* Default */ + +#define SX127X_RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK (0x40) /* Write only */ + +#define SX127X_RF_RXCONFIG_RESTARTRXWITHPLLLOCK (0x20) /* Write only */ + +#define SX127X_RF_RXCONFIG_AFCAUTO_MASK (0xEF) +#define SX127X_RF_RXCONFIG_AFCAUTO_ON (0x10) +#define SX127X_RF_RXCONFIG_AFCAUTO_OFF (0x00) /* Default */ + +#define SX127X_RF_RXCONFIG_AGCAUTO_MASK (0xF7) +#define SX127X_RF_RXCONFIG_AGCAUTO_ON (0x08) /* Default */ +#define SX127X_RF_RXCONFIG_AGCAUTO_OFF (0x00) + +#define SX127X_RF_RXCONFIG_RXTRIGER_MASK (0xF8) +#define SX127X_RF_RXCONFIG_RXTRIGER_OFF (0x00) +#define SX127X_RF_RXCONFIG_RXTRIGER_RSSI (0x01) +#define SX127X_RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT (0x06) /* Default */ +#define SX127X_RF_RXCONFIG_RXTRIGER_RSSI_PREAMBLEDETECT (0x07) + +/* RegRssiConfig */ +#define SX127X_RF_RSSICONFIG_OFFSET_MASK (0x07) +#define SX127X_RF_RSSICONFIG_OFFSET_P_00_DB (0x00) /* Default */ +#define SX127X_RF_RSSICONFIG_OFFSET_P_01_DB (0x08) +#define SX127X_RF_RSSICONFIG_OFFSET_P_02_DB (0x10) +#define SX127X_RF_RSSICONFIG_OFFSET_P_03_DB (0x18) +#define SX127X_RF_RSSICONFIG_OFFSET_P_04_DB (0x20) +#define SX127X_RF_RSSICONFIG_OFFSET_P_05_DB (0x28) +#define SX127X_RF_RSSICONFIG_OFFSET_P_06_DB (0x30) +#define SX127X_RF_RSSICONFIG_OFFSET_P_07_DB (0x38) +#define SX127X_RF_RSSICONFIG_OFFSET_P_08_DB (0x40) +#define SX127X_RF_RSSICONFIG_OFFSET_P_09_DB (0x48) +#define SX127X_RF_RSSICONFIG_OFFSET_P_10_DB (0x50) +#define SX127X_RF_RSSICONFIG_OFFSET_P_11_DB (0x58) +#define SX127X_RF_RSSICONFIG_OFFSET_P_12_DB (0x60) +#define SX127X_RF_RSSICONFIG_OFFSET_P_13_DB (0x68) +#define SX127X_RF_RSSICONFIG_OFFSET_P_14_DB (0x70) +#define SX127X_RF_RSSICONFIG_OFFSET_P_15_DB (0x78) +#define SX127X_RF_RSSICONFIG_OFFSET_M_16_DB (0x80) +#define SX127X_RF_RSSICONFIG_OFFSET_M_15_DB (0x88) +#define SX127X_RF_RSSICONFIG_OFFSET_M_14_DB (0x90) +#define SX127X_RF_RSSICONFIG_OFFSET_M_13_DB (0x98) +#define SX127X_RF_RSSICONFIG_OFFSET_M_12_DB (0xA0) +#define SX127X_RF_RSSICONFIG_OFFSET_M_11_DB (0xA8) +#define SX127X_RF_RSSICONFIG_OFFSET_M_10_DB (0xB0) +#define SX127X_RF_RSSICONFIG_OFFSET_M_09_DB (0xB8) +#define SX127X_RF_RSSICONFIG_OFFSET_M_08_DB (0xC0) +#define SX127X_RF_RSSICONFIG_OFFSET_M_07_DB (0xC8) +#define SX127X_RF_RSSICONFIG_OFFSET_M_06_DB (0xD0) +#define SX127X_RF_RSSICONFIG_OFFSET_M_05_DB (0xD8) +#define SX127X_RF_RSSICONFIG_OFFSET_M_04_DB (0xE0) +#define SX127X_RF_RSSICONFIG_OFFSET_M_03_DB (0xE8) +#define SX127X_RF_RSSICONFIG_OFFSET_M_02_DB (0xF0) +#define SX127X_RF_RSSICONFIG_OFFSET_M_01_DB (0xF8) + +#define SX127X_RF_RSSICONFIG_SMOOTHING_MASK (0xF8) +#define SX127X_RF_RSSICONFIG_SMOOTHING_2 (0x00) +#define SX127X_RF_RSSICONFIG_SMOOTHING_4 (0x01) +#define SX127X_RF_RSSICONFIG_SMOOTHING_8 (0x02) /* Default */ +#define SX127X_RF_RSSICONFIG_SMOOTHING_16 (0x03) +#define SX127X_RF_RSSICONFIG_SMOOTHING_32 (0x04) +#define SX127X_RF_RSSICONFIG_SMOOTHING_64 (0x05) +#define SX127X_RF_RSSICONFIG_SMOOTHING_128 (0x06) +#define SX127X_RF_RSSICONFIG_SMOOTHING_256 (0x07) + +/* RegRssiCollision */ +#define SX127X_RF_RSSICOLISION_THRESHOLD (0x0A) /* Default */ + +/* RegRssiThresh */ +#define SX127X_RF_RSSITHRESH_THRESHOLD (0xFF) /* Default */ + +/* RegRxBw */ +#define SX127X_RF_RXBW_MANT_MASK (0xE7) +#define SX127X_RF_RXBW_MANT_16 (0x00) +#define SX127X_RF_RXBW_MANT_20 (0x08) +#define SX127X_RF_RXBW_MANT_24 (0x10) /* Default */ + +#define SX127X_RF_RXBW_EXP_MASK (0xF8) +#define SX127X_RF_RXBW_EXP_0 (0x00) +#define SX127X_RF_RXBW_EXP_1 (0x01) +#define SX127X_RF_RXBW_EXP_2 (0x02) +#define SX127X_RF_RXBW_EXP_3 (0x03) +#define SX127X_RF_RXBW_EXP_4 (0x04) +#define SX127X_RF_RXBW_EXP_5 (0x05) /* Default */ +#define SX127X_RF_RXBW_EXP_6 (0x06) +#define SX127X_RF_RXBW_EXP_7 (0x07) + +/* RegAfcBw */ +#define SX127X_RF_AFCBW_MANTAFC_MASK (0xE7) +#define SX127X_RF_AFCBW_MANTAFC_16 (0x00) +#define SX127X_RF_AFCBW_MANTAFC_20 (0x08) /* Default */ +#define SX127X_RF_AFCBW_MANTAFC_24 (0x10) + +#define SX127X_RF_AFCBW_EXPAFC_MASK (0xF8) +#define SX127X_RF_AFCBW_EXPAFC_0 (0x00) +#define SX127X_RF_AFCBW_EXPAFC_1 (0x01) +#define SX127X_RF_AFCBW_EXPAFC_2 (0x02) +#define SX127X_RF_AFCBW_EXPAFC_3 (0x03) /* Default */ +#define SX127X_RF_AFCBW_EXPAFC_4 (0x04) +#define SX127X_RF_AFCBW_EXPAFC_5 (0x05) +#define SX127X_RF_AFCBW_EXPAFC_6 (0x06) +#define SX127X_RF_AFCBW_EXPAFC_7 (0x07) + +/* RegOokPeak */ +#define SX127X_RF_OOKPEAK_BITSYNC_MASK (0xDF) /* Default */ +#define SX127X_RF_OOKPEAK_BITSYNC_ON (0x20) /* Default */ +#define SX127X_RF_OOKPEAK_BITSYNC_OFF (0x00) + +#define SX127X_RF_OOKPEAK_OOKTHRESHTYPE_MASK (0xE7) +#define SX127X_RF_OOKPEAK_OOKTHRESHTYPE_FIXED (0x00) +#define SX127X_RF_OOKPEAK_OOKTHRESHTYPE_PEAK (0x08) /* Default */ +#define SX127X_RF_OOKPEAK_OOKTHRESHTYPE_AVERAGE (0x10) + +#define SX127X_RF_OOKPEAK_OOKPEAKTHRESHSTEP_MASK (0xF8) +#define SX127X_RF_OOKPEAK_OOKPEAKTHRESHSTEP_0_5_DB (0x00) /* Default */ +#define SX127X_RF_OOKPEAK_OOKPEAKTHRESHSTEP_1_0_DB (0x01) +#define SX127X_RF_OOKPEAK_OOKPEAKTHRESHSTEP_1_5_DB (0x02) +#define SX127X_RF_OOKPEAK_OOKPEAKTHRESHSTEP_2_0_DB (0x03) +#define SX127X_RF_OOKPEAK_OOKPEAKTHRESHSTEP_3_0_DB (0x04) +#define SX127X_RF_OOKPEAK_OOKPEAKTHRESHSTEP_4_0_DB (0x05) +#define SX127X_RF_OOKPEAK_OOKPEAKTHRESHSTEP_5_0_DB (0x06) +#define SX127X_RF_OOKPEAK_OOKPEAKTHRESHSTEP_6_0_DB (0x07) + +/* RegOokFix */ +#define SX127X_RF_OOKFIX_OOKFIXEDTHRESHOLD (0x0C) /* Default */ + +/* RegOokAvg */ +#define SX127X_RF_OOKAVG_OOKPEAKTHRESHDEC_MASK (0x1F) +#define SX127X_RF_OOKAVG_OOKPEAKTHRESHDEC_000 (0x00) /* Default */ +#define SX127X_RF_OOKAVG_OOKPEAKTHRESHDEC_001 (0x20) +#define SX127X_RF_OOKAVG_OOKPEAKTHRESHDEC_010 (0x40) +#define SX127X_RF_OOKAVG_OOKPEAKTHRESHDEC_011 (0x60) +#define SX127X_RF_OOKAVG_OOKPEAKTHRESHDEC_100 (0x80) +#define SX127X_RF_OOKAVG_OOKPEAKTHRESHDEC_101 (0xA0) +#define SX127X_RF_OOKAVG_OOKPEAKTHRESHDEC_110 (0xC0) +#define SX127X_RF_OOKAVG_OOKPEAKTHRESHDEC_111 (0xE0) + +#define SX127X_RF_OOKAVG_AVERAGEOFFSET_MASK (0xF3) +#define SX127X_RF_OOKAVG_AVERAGEOFFSET_0_DB (0x00) /* Default */ +#define SX127X_RF_OOKAVG_AVERAGEOFFSET_2_DB (0x04) +#define SX127X_RF_OOKAVG_AVERAGEOFFSET_4_DB (0x08) +#define SX127X_RF_OOKAVG_AVERAGEOFFSET_6_DB (0x0C) + +#define SX127X_RF_OOKAVG_OOKAVERAGETHRESHFILT_MASK (0xFC) +#define SX127X_RF_OOKAVG_OOKAVERAGETHRESHFILT_00 (0x00) +#define SX127X_RF_OOKAVG_OOKAVERAGETHRESHFILT_01 (0x01) +#define SX127X_RF_OOKAVG_OOKAVERAGETHRESHFILT_10 (0x02) /* Default */ +#define SX127X_RF_OOKAVG_OOKAVERAGETHRESHFILT_11 (0x03) + +/* RegAfcFei */ +#define SX127X_RF_AFCFEI_AGCSTART (0x10) + +#define SX127X_RF_AFCFEI_AFCCLEAR (0x02) + +#define SX127X_RF_AFCFEI_AFCAUTOCLEAR_MASK (0xFE) +#define SX127X_RF_AFCFEI_AFCAUTOCLEAR_ON (0x01) +#define SX127X_RF_AFCFEI_AFCAUTOCLEAR_OFF (0x00) /* Default */ + +/* RegPreambleDetect */ +#define SX127X_RF_PREAMBLEDETECT_DETECTOR_MASK (0x7F) +#define SX127X_RF_PREAMBLEDETECT_DETECTOR_ON (0x80) /* Default */ +#define SX127X_RF_PREAMBLEDETECT_DETECTOR_OFF (0x00) + +#define SX127X_RF_PREAMBLEDETECT_DETECTORSIZE_MASK (0x9F) +#define SX127X_RF_PREAMBLEDETECT_DETECTORSIZE_1 (0x00) +#define SX127X_RF_PREAMBLEDETECT_DETECTORSIZE_2 (0x20) /* Default */ +#define SX127X_RF_PREAMBLEDETECT_DETECTORSIZE_3 (0x40) +#define SX127X_RF_PREAMBLEDETECT_DETECTORSIZE_4 (0x60) + +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_MASK (0xE0) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_0 (0x00) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_1 (0x01) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_2 (0x02) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_3 (0x03) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_4 (0x04) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_5 (0x05) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_6 (0x06) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_7 (0x07) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_8 (0x08) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_9 (0x09) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_10 (0x0A) /* Default */ +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_11 (0x0B) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_12 (0x0C) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_13 (0x0D) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_14 (0x0E) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_15 (0x0F) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_16 (0x10) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_17 (0x11) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_18 (0x12) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_19 (0x13) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_20 (0x14) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_21 (0x15) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_22 (0x16) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_23 (0x17) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_24 (0x18) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_25 (0x19) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_26 (0x1A) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_27 (0x1B) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_28 (0x1C) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_29 (0x1D) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_30 (0x1E) +#define SX127X_RF_PREAMBLEDETECT_DETECTORTOL_31 (0x1F) + +/* RegRxTimeout1 */ +#define SX127X_RF_RXTIMEOUT1_TIMEOUTRXRSSI (0x00) /* Default */ + +/* RegRxTimeout2 */ +#define SX127X_RF_RXTIMEOUT2_TIMEOUTRXPREAMBLE (0x00) /* Default */ + +/* RegRxTimeout3 */ +#define SX127X_RF_RXTIMEOUT3_TIMEOUTSIGNALSYNC (0x00) /* Default */ + +/* RegRxDelay */ +#define SX127X_RF_RXDELAY_INTERPACKETRXDELAY (0x00) /* Default */ + +/* RegOsc */ +#define SX127X_RF_OSC_RCCALSTART (0x08) + +#define SX127X_RF_OSC_CLKOUT_MASK (0xF8) +#define SX127X_RF_OSC_CLKOUT_32_MHZ (0x00) +#define SX127X_RF_OSC_CLKOUT_16_MHZ (0x01) +#define SX127X_RF_OSC_CLKOUT_8_MHZ (0x02) +#define SX127X_RF_OSC_CLKOUT_4_MHZ (0x03) +#define SX127X_RF_OSC_CLKOUT_2_MHZ (0x04) +#define SX127X_RF_OSC_CLKOUT_1_MHZ (0x05) /* Default */ +#define SX127X_RF_OSC_CLKOUT_RC (0x06) +#define SX127X_RF_OSC_CLKOUT_OFF (0x07) + +/* RegPreambleMsb/RegPreambleLsb */ +#define SX127X_RF_PREAMBLEMSB_SIZE (0x00) /* Default */ +#define SX127X_RF_PREAMBLELSB_SIZE (0x03) /* Default */ + +/* RegSyncConfig */ +#define SX127X_RF_SYNCCONFIG_AUTORESTARTRXMODE_MASK (0x3F) +#define SX127X_RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_ON (0x80) /* Default */ +#define SX127X_RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_OFF (0x40) +#define SX127X_RF_SYNCCONFIG_AUTORESTARTRXMODE_OFF (0x00) + +#define SX127X_RF_SYNCCONFIG_PREAMBLEPOLARITY_MASK (0xDF) +#define SX127X_RF_SYNCCONFIG_PREAMBLEPOLARITY_55 (0x20) +#define SX127X_RF_SYNCCONFIG_PREAMBLEPOLARITY_AA (0x00) /* Default */ + +#define SX127X_RF_SYNCCONFIG_SYNC_MASK (0xEF) +#define SX127X_RF_SYNCCONFIG_SYNC_ON (0x10) /* Default */ +#define SX127X_RF_SYNCCONFIG_SYNC_OFF (0x00) + +#define SX127X_RF_SYNCCONFIG_SYNCSIZE_MASK (0xF8) +#define SX127X_RF_SYNCCONFIG_SYNCSIZE_1 (0x00) +#define SX127X_RF_SYNCCONFIG_SYNCSIZE_2 (0x01) +#define SX127X_RF_SYNCCONFIG_SYNCSIZE_3 (0x02) +#define SX127X_RF_SYNCCONFIG_SYNCSIZE_4 (0x03) /* Default */ +#define SX127X_RF_SYNCCONFIG_SYNCSIZE_5 (0x04) +#define SX127X_RF_SYNCCONFIG_SYNCSIZE_6 (0x05) +#define SX127X_RF_SYNCCONFIG_SYNCSIZE_7 (0x06) +#define SX127X_RF_SYNCCONFIG_SYNCSIZE_8 (0x07) + +/* RegSyncValue1-8 */ +#define SX127X_RF_SYNCVALUE1_SYNCVALUE (0x01) /* Default */ +#define SX127X_RF_SYNCVALUE2_SYNCVALUE (0x01) /* Default */ +#define SX127X_RF_SYNCVALUE3_SYNCVALUE (0x01) /* Default */ +#define SX127X_RF_SYNCVALUE4_SYNCVALUE (0x01) /* Default */ +#define SX127X_RF_SYNCVALUE5_SYNCVALUE (0x01) /* Default */ +#define SX127X_RF_SYNCVALUE6_SYNCVALUE (0x01) /* Default */ +#define SX127X_RF_SYNCVALUE7_SYNCVALUE (0x01) /* Default */ +#define SX127X_RF_SYNCVALUE8_SYNCVALUE (0x01) /* Default */ + +/* RegPacketConfig1 */ +#define SX127X_RF_PACKETCONFIG1_PACKETFORMAT_MASK (0x7F) +#define SX127X_RF_PACKETCONFIG1_PACKETFORMAT_FIXED (0x00) +#define SX127X_RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE (0x80) /* Default */ + +#define SX127X_RF_PACKETCONFIG1_DCFREE_MASK (0x9F) +#define SX127X_RF_PACKETCONFIG1_DCFREE_OFF (0x00) /* Default */ +#define SX127X_RF_PACKETCONFIG1_DCFREE_MANCHESTER (0x20) +#define SX127X_RF_PACKETCONFIG1_DCFREE_WHITENING (0x40) + +#define SX127X_RF_PACKETCONFIG1_CRC_MASK (0xEF) +#define SX127X_RF_PACKETCONFIG1_CRC_ON (0x10) /* Default */ +#define SX127X_RF_PACKETCONFIG1_CRC_OFF (0x00) + +#define SX127X_RF_PACKETCONFIG1_CRCAUTOCLEAR_MASK (0xF7) +#define SX127X_RF_PACKETCONFIG1_CRCAUTOCLEAR_ON (0x00) /* Default */ +#define SX127X_RF_PACKETCONFIG1_CRCAUTOCLEAR_OFF (0x08) + +#define SX127X_RF_PACKETCONFIG1_ADDRSFILTERING_MASK (0xF9) +#define SX127X_RF_PACKETCONFIG1_ADDRSFILTERING_OFF (0x00) /* Default */ +#define SX127X_RF_PACKETCONFIG1_ADDRSFILTERING_NODE (0x02) +#define SX127X_RF_PACKETCONFIG1_ADDRSFILTERING_NODEBROADCAST (0x04) + +#define SX127X_RF_PACKETCONFIG1_CRCWHITENINGTYPE_MASK (0xFE) +#define SX127X_RF_PACKETCONFIG1_CRCWHITENINGTYPE_CCITT (0x00) /* Default */ +#define SX127X_RF_PACKETCONFIG1_CRCWHITENINGTYPE_IBM (0x01) + +/* RegPacketConfig2 */ +#define SX127X_RF_PACKETCONFIG2_WMBUS_CRC_ENABLE_MASK (0x7F) +#define SX127X_RF_PACKETCONFIG2_WMBUS_CRC_ENABLE (0x80) +#define SX127X_RF_PACKETCONFIG2_WMBUS_CRC_DISABLE (0x00) /* Default */ + +#define SX127X_RF_PACKETCONFIG2_DATAMODE_MASK (0xBF) +#define SX127X_RF_PACKETCONFIG2_DATAMODE_CONTINUOUS (0x00) +#define SX127X_RF_PACKETCONFIG2_DATAMODE_PACKET (0x40) /* Default */ + +#define SX127X_RF_PACKETCONFIG2_IOHOME_MASK (0xDF) +#define SX127X_RF_PACKETCONFIG2_IOHOME_ON (0x20) +#define SX127X_RF_PACKETCONFIG2_IOHOME_OFF (0x00) /* Default */ + +#define SX127X_RF_PACKETCONFIG2_BEACON_MASK (0xF7) +#define SX127X_RF_PACKETCONFIG2_BEACON_ON (0x08) +#define SX127X_RF_PACKETCONFIG2_BEACON_OFF (0x00) /* Default */ + +#define SX127X_RF_PACKETCONFIG2_PAYLOADLENGTH_MSB_MASK (0xF8) + +/* RegPayloadLength */ +#define SX127X_RF_PAYLOADLENGTH_LENGTH (0x40) /* Default */ + +/* RegNodeAdrs */ +#define SX127X_RF_NODEADDRESS_ADDRESS (0x00) + +/* RegBroadcastAdrs */ +#define SX127X_RF_BROADCASTADDRESS_ADDRESS (0x00) + +/* RegFifoThresh */ +#define SX127X_RF_FIFOTHRESH_TXSTARTCONDITION_MASK (0x7F) +#define SX127X_RF_FIFOTHRESH_TXSTARTCONDITION_FIFOTHRESH (0x00) /* Default */ +#define SX127X_RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY (0x80) + +#define SX127X_RF_FIFOTHRESH_FIFOTHRESHOLD_MASK (0xC0) +#define SX127X_RF_FIFOTHRESH_FIFOTHRESHOLD_THRESHOLD (0x0F) /* Default */ + +/* RegSeqConfig1 */ +#define SX127X_RF_SEQCONFIG1_SEQUENCER_START (0x80) + +#define SX127X_RF_SEQCONFIG1_SEQUENCER_STOP (0x40) + +#define SX127X_RF_SEQCONFIG1_IDLEMODE_MASK (0xDF) +#define SX127X_RF_SEQCONFIG1_IDLEMODE_SLEEP (0x20) +#define SX127X_RF_SEQCONFIG1_IDLEMODE_STANDBY (0x00) /* Default */ + +#define SX127X_RF_SEQCONFIG1_FROMSTART_MASK (0xE7) +#define SX127X_RF_SEQCONFIG1_FROMSTART_TOLPS (0x00) /* Default */ +#define SX127X_RF_SEQCONFIG1_FROMSTART_TORX (0x08) +#define SX127X_RF_SEQCONFIG1_FROMSTART_TOTX (0x10) +#define SX127X_RF_SEQCONFIG1_FROMSTART_TOTX_ONFIFOLEVEL (0x18) + +#define SX127X_RF_SEQCONFIG1_LPS_MASK (0xFB) +#define SX127X_RF_SEQCONFIG1_LPS_SEQUENCER_OFF (0x00) /* Default */ +#define SX127X_RF_SEQCONFIG1_LPS_IDLE (0x04) + +#define SX127X_RF_SEQCONFIG1_FROMIDLE_MASK (0xFD) +#define SX127X_RF_SEQCONFIG1_FROMIDLE_TOTX (0x00) /* Default */ +#define SX127X_RF_SEQCONFIG1_FROMIDLE_TORX (0x02) + +#define SX127X_RF_SEQCONFIG1_FROMTX_MASK (0xFE) +#define SX127X_RF_SEQCONFIG1_FROMTX_TOLPS (0x00) /* Default */ +#define SX127X_RF_SEQCONFIG1_FROMTX_TORX (0x01) + +/* RegSeqConfig2 */ +#define SX127X_RF_SEQCONFIG2_FROMRX_MASK (0x1F) +#define SX127X_RF_SEQCONFIG2_FROMRX_TOUNUSED_000 (0x00) /* Default */ +#define SX127X_RF_SEQCONFIG2_FROMRX_TORXPKT_ONPLDRDY (0x20) +#define SX127X_RF_SEQCONFIG2_FROMRX_TOLPS_ONPLDRDY (0x40) +#define SX127X_RF_SEQCONFIG2_FROMRX_TORXPKT_ONCRCOK (0x60) +#define SX127X_RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONRSSI (0x80) +#define SX127X_RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONSYNC (0xA0) +#define SX127X_RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONPREAMBLE (0xC0) +#define SX127X_RF_SEQCONFIG2_FROMRX_TOUNUSED_111 (0xE0) + +#define SX127X_RF_SEQCONFIG2_FROMRXTIMEOUT_MASK (0xE7) +#define SX127X_RF_SEQCONFIG2_FROMRXTIMEOUT_TORXRESTART (0x00) /* Default */ +#define SX127X_RF_SEQCONFIG2_FROMRXTIMEOUT_TOTX (0x08) +#define SX127X_RF_SEQCONFIG2_FROMRXTIMEOUT_TOLPS (0x10) +#define SX127X_RF_SEQCONFIG2_FROMRXTIMEOUT_TOSEQUENCEROFF (0x18) + +#define SX127X_RF_SEQCONFIG2_FROMRXPKT_MASK (0xF8) +#define SX127X_RF_SEQCONFIG2_FROMRXPKT_TOSEQUENCEROFF (0x00) /* Default */ +#define SX127X_RF_SEQCONFIG2_FROMRXPKT_TOTX_ONFIFOEMPTY (0x01) +#define SX127X_RF_SEQCONFIG2_FROMRXPKT_TOLPS (0x02) +#define SX127X_RF_SEQCONFIG2_FROMRXPKT_TOSYNTHESIZERRX (0x03) +#define SX127X_RF_SEQCONFIG2_FROMRXPKT_TORX (0x04) + +/* RegTimerResol */ +#define SX127X_RF_TIMERRESOL_TIMER1RESOL_MASK (0xF3) +#define SX127X_RF_TIMERRESOL_TIMER1RESOL_OFF (0x00) /* Default */ +#define SX127X_RF_TIMERRESOL_TIMER1RESOL_000064_US (0x04) +#define SX127X_RF_TIMERRESOL_TIMER1RESOL_004100_US (0x08) +#define SX127X_RF_TIMERRESOL_TIMER1RESOL_262000_US (0x0C) + +#define SX127X_RF_TIMERRESOL_TIMER2RESOL_MASK (0xFC) +#define SX127X_RF_TIMERRESOL_TIMER2RESOL_OFF (0x00) /* Default */ +#define SX127X_RF_TIMERRESOL_TIMER2RESOL_000064_US (0x01) +#define SX127X_RF_TIMERRESOL_TIMER2RESOL_004100_US (0x02) +#define SX127X_RF_TIMERRESOL_TIMER2RESOL_262000_US (0x03) + +/* RegTimer1Coef */ +#define SX127X_RF_TIMER1COEF_TIMER1COEFFICIENT (0xF5) /* Default */ + +/* RegTimer2Coef */ +#define SX127X_RF_TIMER2COEF_TIMER2COEFFICIENT (0x20) /* Default */ + +/* RegImageCal */ +#define SX127X_RF_IMAGECAL_AUTOIMAGECAL_MASK (0x7F) +#define SX127X_RF_IMAGECAL_AUTOIMAGECAL_ON (0x80) +#define SX127X_RF_IMAGECAL_AUTOIMAGECAL_OFF (0x00) /* Default */ + +#define SX127X_RF_IMAGECAL_IMAGECAL_MASK (0xBF) +#define SX127X_RF_IMAGECAL_IMAGECAL_START (0x40) + +#define SX127X_RF_IMAGECAL_IMAGECAL_RUNNING (0x20) +#define SX127X_RF_IMAGECAL_IMAGECAL_DONE (0x00) /* Default */ + +#define SX127X_RF_IMAGECAL_TEMPCHANGE_HIGHER (0x08) +#define SX127X_RF_IMAGECAL_TEMPCHANGE_LOWER (0x00) + +#define SX127X_RF_IMAGECAL_TEMPTHRESHOLD_MASK (0xF9) +#define SX127X_RF_IMAGECAL_TEMPTHRESHOLD_05 (0x00) +#define SX127X_RF_IMAGECAL_TEMPTHRESHOLD_10 (0x02) /* Default */ +#define SX127X_RF_IMAGECAL_TEMPTHRESHOLD_15 (0x04) +#define SX127X_RF_IMAGECAL_TEMPTHRESHOLD_20 (0x06) + +#define SX127X_RF_IMAGECAL_TEMPMONITOR_MASK (0xFE) +#define SX127X_RF_IMAGECAL_TEMPMONITOR_ON (0x00) /* Default */ +#define SX127X_RF_IMAGECAL_TEMPMONITOR_OFF (0x01) + +/* RegLowBat */ +#define SX127X_RF_LOWBAT_MASK (0xF7) +#define SX127X_RF_LOWBAT_ON (0x08) +#define SX127X_RF_LOWBAT_OFF (0x00) /* Default */ + +#define SX127X_RF_LOWBAT_TRIM_MASK (0xF8) +#define SX127X_RF_LOWBAT_TRIM_1695 (0x00) +#define SX127X_RF_LOWBAT_TRIM_1764 (0x01) +#define SX127X_RF_LOWBAT_TRIM_1835 (0x02) /* Default */ +#define SX127X_RF_LOWBAT_TRIM_1905 (0x03) +#define SX127X_RF_LOWBAT_TRIM_1976 (0x04) +#define SX127X_RF_LOWBAT_TRIM_2045 (0x05) +#define SX127X_RF_LOWBAT_TRIM_2116 (0x06) +#define SX127X_RF_LOWBAT_TRIM_2185 (0x07) + +/* RegIrqFlags1 */ +#define SX127X_RF_IRQFLAGS1_MODEREADY (0x80) +#define SX127X_RF_IRQFLAGS1_RXREADY (0x40) +#define SX127X_RF_IRQFLAGS1_TXREADY (0x20) +#define SX127X_RF_IRQFLAGS1_PLLLOCK (0x10) +#define SX127X_RF_IRQFLAGS1_RSSI (0x08) +#define SX127X_RF_IRQFLAGS1_TIMEOUT (0x04) +#define SX127X_RF_IRQFLAGS1_PREAMBLEDETECT (0x02) +#define SX127X_RF_IRQFLAGS1_SYNCADDRESSMATCH (0x01) + +/* RegIrqFlags2 */ +#define SX127X_RF_IRQFLAGS2_FIFOFULL (0x80) +#define SX127X_RF_IRQFLAGS2_FIFOEMPTY (0x40) +#define SX127X_RF_IRQFLAGS2_FIFOLEVEL (0x20) +#define SX127X_RF_IRQFLAGS2_FIFOOVERRUN (0x10) +#define SX127X_RF_IRQFLAGS2_PACKETSENT (0x08) +#define SX127X_RF_IRQFLAGS2_PAYLOADREADY (0x04) +#define SX127X_RF_IRQFLAGS2_CRCOK (0x02) +#define SX127X_RF_IRQFLAGS2_LOWBAT (0x01) + +/* RegDioMapping1 */ +#define SX127X_RF_DIOMAPPING1_DIO0_MASK (0x3F) +#define SX127X_RF_DIOMAPPING1_DIO0_00 (0x00) /* Default */ +#define SX127X_RF_DIOMAPPING1_DIO0_01 (0x40) +#define SX127X_RF_DIOMAPPING1_DIO0_10 (0x80) +#define SX127X_RF_DIOMAPPING1_DIO0_11 (0xC0) + +#define SX127X_RF_DIOMAPPING1_DIO1_MASK (0xCF) +#define SX127X_RF_DIOMAPPING1_DIO1_00 (0x00) /* Default */ +#define SX127X_RF_DIOMAPPING1_DIO1_01 (0x10) +#define SX127X_RF_DIOMAPPING1_DIO1_10 (0x20) +#define SX127X_RF_DIOMAPPING1_DIO1_11 (0x30) + +#define SX127X_RF_DIOMAPPING1_DIO2_MASK (0xF3) +#define SX127X_RF_DIOMAPPING1_DIO2_00 (0x00) /* Default */ +#define SX127X_RF_DIOMAPPING1_DIO2_01 (0x04) +#define SX127X_RF_DIOMAPPING1_DIO2_10 (0x08) +#define SX127X_RF_DIOMAPPING1_DIO2_11 (0x0C) + +#define SX127X_RF_DIOMAPPING1_DIO3_MASK (0xFC) +#define SX127X_RF_DIOMAPPING1_DIO3_00 (0x00) /* Default */ +#define SX127X_RF_DIOMAPPING1_DIO3_01 (0x01) +#define SX127X_RF_DIOMAPPING1_DIO3_10 (0x02) +#define SX127X_RF_DIOMAPPING1_DIO3_11 (0x03) + +/* RegDioMapping2 */ +#define SX127X_RF_DIOMAPPING2_DIO4_MASK (0x3F) +#define SX127X_RF_DIOMAPPING2_DIO4_00 (0x00) /* Default */ +#define SX127X_RF_DIOMAPPING2_DIO4_01 (0x40) +#define SX127X_RF_DIOMAPPING2_DIO4_10 (0x80) +#define SX127X_RF_DIOMAPPING2_DIO4_11 (0xC0) + +#define SX127X_RF_DIOMAPPING2_DIO5_MASK (0xCF) +#define SX127X_RF_DIOMAPPING2_DIO5_00 (0x00) /* Default */ +#define SX127X_RF_DIOMAPPING2_DIO5_01 (0x10) +#define SX127X_RF_DIOMAPPING2_DIO5_10 (0x20) +#define SX127X_RF_DIOMAPPING2_DIO5_11 (0x30) + +#define SX127X_RF_DIOMAPPING2_MAP_MASK (0xFE) +#define SX127X_RF_DIOMAPPING2_MAP_PREAMBLEDETECT (0x01) +#define SX127X_RF_DIOMAPPING2_MAP_RSSI (0x00) /* Default */ + +/* RegPllHop */ +#define SX127X_RF_PLLHOP_FASTHOP_MASK (0x7F) +#define SX127X_RF_PLLHOP_FASTHOP_ON (0x80) +#define SX127X_RF_PLLHOP_FASTHOP_OFF (0x00) /* Default */ + +/* RegTcxo */ +#define SX127X_RF_TCXO_TCXOINPUT_MASK (0xEF) +#define SX127X_RF_TCXO_TCXOINPUT_ON (0x10) +#define SX127X_RF_TCXO_TCXOINPUT_OFF (0x00) /* Default */ + +/* RegPaDac */ +#define SX127X_RF_PADAC_20DBM_MASK (0xF8) +#define SX127X_RF_PADAC_20DBM_ON (0x07) +#define SX127X_RF_PADAC_20DBM_OFF (0x04) /* Default */ + +/* RegBitrateFrac */ +#define SX127X_RF_BITRATEFRAC_MASK (0xF0) + +/* RegPll */ +#define SX127X_RF_PLL_BANDWIDTH_MASK (0x3F) +#define SX127X_RF_PLL_BANDWIDTH_75 (0x00) +#define SX127X_RF_PLL_BANDWIDTH_150 (0x40) +#define SX127X_RF_PLL_BANDWIDTH_225 (0x80) +#define SX127X_RF_PLL_BANDWIDTH_300 (0xC0) /* Default */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* SX127X_REGISTERS_H */ diff --git a/drivers/sx127x/sx127x.c b/drivers/sx127x/sx127x.c new file mode 100644 index 0000000000000000000000000000000000000000..362acc1c24b924d3fd1ac99757b7a74521e84341 --- /dev/null +++ b/drivers/sx127x/sx127x.c @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2016 Unwired Devices <info@unwds.com> + * 2017 Inria Chile + * 2017 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 drivers_sx127x + * @{ + * @file + * @brief Basic functionality of sx127x driver + * + * @author Eugene P. <ep@unwds.com> + * @author José Ignacio Alamos <jose.alamos@inria.cl> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> + * @} + */ +#include <stdbool.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> + +#include "xtimer.h" +#include "thread.h" + +#include "periph/gpio.h" +#include "periph/spi.h" + +#include "sx127x.h" +#include "sx127x_internal.h" +#include "sx127x_registers.h" +#include "sx127x_netdev.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/* Internal functions */ +static void _init_isrs(sx127x_t *dev); +static void _init_timers(sx127x_t *dev); +static int _init_peripherals(sx127x_t *dev); +static void _on_tx_timeout(void *arg); +static void _on_rx_timeout(void *arg); + +/* SX127X DIO interrupt handlers initialization */ +static void sx127x_on_dio0_isr(void *arg); +static void sx127x_on_dio1_isr(void *arg); +static void sx127x_on_dio2_isr(void *arg); +static void sx127x_on_dio3_isr(void *arg); + + +void sx127x_setup(sx127x_t *dev, const sx127x_params_t *params) +{ + netdev_t *netdev = (netdev_t*) dev; + netdev->driver = &sx127x_driver; + memcpy(&dev->params, params, sizeof(sx127x_params_t)); +} + +void sx127x_reset(const sx127x_t *dev) +{ + /* + * This reset scheme complies with 7.2 chapter of the SX1272/1276 datasheet + * See http://www.semtech.com/images/datasheet/sx1276.pdf for SX1276 + * See http://www.semtech.com/images/datasheet/sx1272.pdf for SX1272 + * + * 1. Set NReset pin to LOW for at least 100 us + * 2. Set NReset in Hi-Z state + * 3. Wait at least 5 milliseconds + */ + gpio_init(dev->params.reset_pin, GPIO_OUT); + + /* Set reset pin to 0 */ + gpio_clear(dev->params.reset_pin); + + /* Wait 1 ms */ + xtimer_usleep(1000); + + /* Put reset pin in High-Z */ + gpio_init(dev->params.reset_pin, GPIO_IN); + + /* Wait 10 ms */ + xtimer_usleep(1000 * 10); +} + +int sx127x_init(sx127x_t *dev) +{ + /* Do internal initialization routines */ + if (!_init_peripherals(dev)) { + return -SX127X_ERR_SPI; + } + + /* Check presence of SX127X */ + if (!sx127x_test(dev)) { + DEBUG("[Error] init : sx127x test failed\n"); + return -SX127X_ERR_TEST_FAILED; + } + + _init_timers(dev); + xtimer_usleep(1000); /* wait 1 millisecond */ + + sx127x_reset(dev); + + sx127x_rx_chain_calibration(dev); + sx127x_set_op_mode(dev, SX127X_RF_OPMODE_SLEEP); + + _init_isrs(dev); + + return SX127X_INIT_OK; +} + +void sx127x_init_radio_settings(sx127x_t *dev) +{ + sx127x_set_freq_hop(dev, SX127X_FREQUENCY_HOPPING); + sx127x_set_iq_invert(dev, SX127X_IQ_INVERSION); + sx127x_set_rx_single(dev, SX127X_RX_SINGLE); + sx127x_set_tx_timeout(dev, SX127X_TX_TIMEOUT_DEFAULT); + sx127x_set_modem(dev, SX127X_MODEM_DEFAULT); + sx127x_set_channel(dev, SX127X_CHANNEL_DEFAULT); + sx127x_set_bandwidth(dev, SX127X_BW_DEFAULT); + sx127x_set_spreading_factor(dev, SX127X_SF_DEFAULT); + sx127x_set_coding_rate(dev, SX127X_CR_DEFAULT); + + sx127x_set_fixed_header_len_mode(dev, SX127X_FIXED_HEADER_LEN_MODE); + sx127x_set_crc(dev, SX127X_PAYLOAD_CRC_ON); + sx127x_set_symbol_timeout(dev, SX127X_SYMBOL_TIMEOUT); + sx127x_set_preamble_length(dev, SX127X_PREAMBLE_LENGTH); + sx127x_set_payload_length(dev, SX127X_PAYLOAD_LENGTH); + sx127x_set_hop_period(dev, SX127X_FREQUENCY_HOPPING_PERIOD); + + sx127x_set_tx_power(dev, SX127X_RADIO_TX_POWER); +} + +uint32_t sx127x_random(sx127x_t *dev) +{ + uint32_t rnd = 0; + + sx127x_set_modem(dev, SX127X_MODEM_LORA); /* Set LoRa modem ON */ + + /* Disable LoRa modem interrupts */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGSMASK, SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT | + SX127X_RF_LORA_IRQFLAGS_RXDONE | + SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR | + SX127X_RF_LORA_IRQFLAGS_VALIDHEADER | + SX127X_RF_LORA_IRQFLAGS_TXDONE | + SX127X_RF_LORA_IRQFLAGS_CADDONE | + SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL | + SX127X_RF_LORA_IRQFLAGS_CADDETECTED); + + /* Set radio in continuous reception */ + sx127x_set_op_mode(dev, SX127X_RF_OPMODE_RECEIVER); + + for (unsigned i = 0; i < 32; i++) { + xtimer_usleep(1000); /* wait for the chaos */ + + /* Non-filtered RSSI value reading. Only takes the LSB value */ + rnd |= ((uint32_t) sx127x_reg_read(dev, SX127X_REG_LR_RSSIWIDEBAND) & 0x01) << i; + } + + sx127x_set_sleep(dev); + + return rnd; +} + +/** + * IRQ handlers + */ +void sx127x_isr(netdev_t *dev) +{ + if (dev->event_callback) { + dev->event_callback(dev, NETDEV_EVENT_ISR); + } +} + +static void sx127x_on_dio_isr(sx127x_t *dev, sx127x_flags_t flag) +{ + dev->irq |= flag; + sx127x_isr((netdev_t *)dev); +} + +static void sx127x_on_dio0_isr(void *arg) +{ + sx127x_on_dio_isr((sx127x_t*) arg, SX127X_IRQ_DIO0); +} + +static void sx127x_on_dio1_isr(void *arg) +{ + sx127x_on_dio_isr((sx127x_t*) arg, SX127X_IRQ_DIO1); +} + +static void sx127x_on_dio2_isr(void *arg) +{ + sx127x_on_dio_isr((sx127x_t*) arg, SX127X_IRQ_DIO2); +} + +static void sx127x_on_dio3_isr(void *arg) +{ + sx127x_on_dio_isr((sx127x_t*) arg, SX127X_IRQ_DIO3); +} + +/* Internal event handlers */ +void sx127x_on_dio0(void *arg) +{ + sx127x_t *dev = (sx127x_t *) arg; + netdev_t *netdev = (netdev_t*) &dev->netdev; + + switch (dev->settings.state) { + case SX127X_RF_RX_RUNNING: + netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE); + break; + case SX127X_RF_TX_RUNNING: + xtimer_remove(&dev->_internal.tx_timeout_timer); + switch (dev->settings.modem) { + case SX127X_MODEM_LORA: + /* Clear IRQ */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGS, + SX127X_RF_LORA_IRQFLAGS_TXDONE); + /* Intentional fall-through */ + case SX127X_MODEM_FSK: + default: + sx127x_set_state(dev, SX127X_RF_IDLE); + netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE); + break; + } + break; + case SX127X_RF_IDLE: + printf("sx127x_on_dio0: IDLE state\n"); + break; + default: + printf("sx127x_on_dio0: Unknown state [%d]\n", dev->settings.state); + break; + } +} + +void sx127x_on_dio1(void *arg) +{ + /* Get interrupt context */ + sx127x_t *dev = (sx127x_t *) arg; + netdev_t *netdev = (netdev_t*) &dev->netdev; + + switch (dev->settings.state) { + case SX127X_RF_RX_RUNNING: + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + /* todo */ + break; + case SX127X_MODEM_LORA: + xtimer_remove(&dev->_internal.rx_timeout_timer); + /* Clear Irq */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGS, SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT); + sx127x_set_state(dev, SX127X_RF_IDLE); + netdev->event_callback(netdev, NETDEV_EVENT_RX_TIMEOUT); + break; + default: + break; + } + break; + case SX127X_RF_TX_RUNNING: + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + /* todo */ + break; + case SX127X_MODEM_LORA: + break; + default: + break; + } + break; + default: + puts("sx127x_on_dio1: Unknown state"); + break; + } +} + +void sx127x_on_dio2(void *arg) +{ + /* Get interrupt context */ + sx127x_t *dev = (sx127x_t *) arg; + netdev_t *netdev = (netdev_t*) dev; + + switch (dev->settings.state) { + case SX127X_RF_RX_RUNNING: + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + /* todo */ + break; + case SX127X_MODEM_LORA: + if (dev->settings.lora.flags & SX127X_CHANNEL_HOPPING_FLAG) { + /* Clear IRQ */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGS, + SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL); + + dev->_internal.last_channel = (sx127x_reg_read(dev, SX127X_REG_LR_HOPCHANNEL) & + SX127X_RF_LORA_HOPCHANNEL_CHANNEL_MASK); + netdev->event_callback(netdev, NETDEV_EVENT_FHSS_CHANGE_CHANNEL); + } + + break; + default: + break; + } + break; + case SX127X_RF_TX_RUNNING: + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + break; + case SX127X_MODEM_LORA: + if (dev->settings.lora.flags & SX127X_CHANNEL_HOPPING_FLAG) { + /* Clear IRQ */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGS, + SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL); + + dev->_internal.last_channel = (sx127x_reg_read(dev, SX127X_REG_LR_HOPCHANNEL) & + SX127X_RF_LORA_HOPCHANNEL_CHANNEL_MASK); + netdev->event_callback(netdev, NETDEV_EVENT_FHSS_CHANGE_CHANNEL); + } + break; + default: + break; + } + break; + default: + puts("sx127x_on_dio2: Unknown state"); + break; + } +} + +void sx127x_on_dio3(void *arg) +{ + /* Get interrupt context */ + sx127x_t *dev = (sx127x_t *) arg; + netdev_t *netdev = (netdev_t *) dev; + + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + break; + case SX127X_MODEM_LORA: + /* Clear IRQ */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGS, + SX127X_RF_LORA_IRQFLAGS_CADDETECTED | + SX127X_RF_LORA_IRQFLAGS_CADDONE); + + /* Send event message */ + dev->_internal.is_last_cad_success = (sx127x_reg_read(dev, SX127X_REG_LR_IRQFLAGS) & + SX127X_RF_LORA_IRQFLAGS_CADDETECTED) == SX127X_RF_LORA_IRQFLAGS_CADDETECTED; + netdev->event_callback(netdev, NETDEV_EVENT_CAD_DONE); + break; + default: + puts("sx127x_on_dio3: Unknown modem"); + break; + } +} + +static void _init_isrs(sx127x_t *dev) +{ + if (gpio_init_int(dev->params.dio0_pin, GPIO_IN, GPIO_RISING, sx127x_on_dio0_isr, dev) < 0) { + DEBUG("Error: cannot initialize DIO0 pin\n"); + } + + if (gpio_init_int(dev->params.dio1_pin, GPIO_IN, GPIO_RISING, sx127x_on_dio1_isr, dev) < 0) { + DEBUG("Error: cannot initialize DIO1 pin\n"); + } + + if (gpio_init_int(dev->params.dio2_pin, GPIO_IN, GPIO_RISING, sx127x_on_dio2_isr, dev) < 0) { + DEBUG("Error: cannot initialize DIO2 pin\n"); + } + + if (gpio_init_int(dev->params.dio3_pin, GPIO_IN, GPIO_RISING, sx127x_on_dio3_isr, dev) < 0) { + DEBUG("Error: cannot initialize DIO3 pin\n"); + } +} + +static void _on_tx_timeout(void *arg) +{ + netdev_t *dev = (netdev_t *) arg; + + dev->event_callback(dev, NETDEV_EVENT_TX_TIMEOUT); +} + +static void _on_rx_timeout(void *arg) +{ + netdev_t *dev = (netdev_t *) arg; + + dev->event_callback(dev, NETDEV_EVENT_RX_TIMEOUT); +} + +static void _init_timers(sx127x_t *dev) +{ + dev->_internal.tx_timeout_timer.arg = dev; + dev->_internal.tx_timeout_timer.callback = _on_tx_timeout; + + dev->_internal.rx_timeout_timer.arg = dev; + dev->_internal.rx_timeout_timer.callback = _on_rx_timeout; +} + +static int _init_peripherals(sx127x_t *dev) +{ + int res; + + /* Setup SPI for SX127X */ + res = spi_init_cs(dev->params.spi, dev->params.nss_pin); + + if (res != SPI_OK) { + DEBUG("sx127x: error initializing SPI_%i device (code %i)\n", + dev->params.spi, res); + return 0; + } + + res = gpio_init(dev->params.nss_pin, GPIO_OUT); + if (res < 0) { + DEBUG("sx127x: error initializing GPIO_%ld as CS line (code %i)\n", + (long)dev->params.nss_pin, res); + return 0; + } + + gpio_set(dev->params.nss_pin); + + DEBUG("sx127x: peripherals initialized with success\n"); + return 1; +} diff --git a/drivers/sx127x/sx127x_getset.c b/drivers/sx127x/sx127x_getset.c new file mode 100644 index 0000000000000000000000000000000000000000..1da4e987cd53c17f3402d3a9c534cc271332a21c --- /dev/null +++ b/drivers/sx127x/sx127x_getset.c @@ -0,0 +1,850 @@ +/* + * Copyright (C) 2016 Unwired Devices <info@unwds.com> + * 2017 Inria Chile + * 2017 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 drivers_sx127x + * @{ + * @file + * @brief Implementation of get and set functions for SX127X + * + * @author Eugene P. <ep@unwds.com> + * @author José Ignacio Alamos <jose.alamos@inria.cl> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> + * @} + */ + +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <inttypes.h> + +#include "sx127x.h" +#include "sx127x_registers.h" +#include "sx127x_internal.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + + +uint8_t sx127x_get_state(const sx127x_t *dev) +{ + return dev->settings.state; +} + +void sx127x_set_state(sx127x_t *dev, uint8_t state) +{ +#if ENABLE_DEBUG + switch (state) { + case SX127X_RF_IDLE: + DEBUG("[DEBUG] Change state: IDLE\n"); + break; + case SX127X_RF_RX_RUNNING: + DEBUG("[DEBUG] Change state: RX\n"); + break; + case SX127X_RF_TX_RUNNING: + DEBUG("[DEBUG] Change state: TX\n"); + break; + default: + DEBUG("[DEBUG] Change state: UNKNOWN\n"); + break; + } +#endif + + dev->settings.state = state; +} + +void sx127x_set_modem(sx127x_t *dev, uint8_t modem) +{ + DEBUG("[DEBUG] set modem: %d\n", modem); + + dev->settings.modem = modem; + + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + /* Todo */ + break; + case SX127X_MODEM_LORA: + sx127x_set_op_mode(dev, SX127X_RF_OPMODE_SLEEP); + sx127x_reg_write(dev, SX127X_REG_OPMODE, + (sx127x_reg_read(dev, SX127X_REG_OPMODE) & + SX127X_RF_LORA_OPMODE_LONGRANGEMODE_MASK) | + SX127X_RF_LORA_OPMODE_LONGRANGEMODE_ON); + + sx127x_reg_write(dev, SX127X_REG_DIOMAPPING1, 0x00); + sx127x_reg_write(dev, SX127X_REG_DIOMAPPING2, 0x00); + break; + default: + break; + } +} + +uint8_t sx127x_get_syncword(const sx127x_t *dev) +{ + return sx127x_reg_read(dev, SX127X_REG_LR_SYNCWORD); +} + +void sx127x_set_syncword(sx127x_t *dev, uint8_t syncword) +{ + DEBUG("[DEBUG] Set syncword: %d\n", syncword); + + sx127x_reg_write(dev, SX127X_REG_LR_SYNCWORD, syncword); +} + +uint32_t sx127x_get_channel(const sx127x_t *dev) +{ + return (((uint32_t)sx127x_reg_read(dev, SX127X_REG_FRFMSB) << 16) | + (sx127x_reg_read(dev, SX127X_REG_FRFMID) << 8) | + (sx127x_reg_read(dev, SX127X_REG_FRFLSB))) * SX127X_FREQUENCY_RESOLUTION; +} + +void sx127x_set_channel(sx127x_t *dev, uint32_t channel) +{ + DEBUG("[DEBUG] Set channel: %lu\n", channel); + + /* Save current operating mode */ + dev->settings.channel = channel; + + channel = (uint32_t)((double) channel / (double) SX127X_FREQUENCY_RESOLUTION); + + /* Write frequency settings into chip */ + sx127x_reg_write(dev, SX127X_REG_FRFMSB, (uint8_t)((channel >> 16) & 0xFF)); + sx127x_reg_write(dev, SX127X_REG_FRFMID, (uint8_t)((channel >> 8) & 0xFF)); + sx127x_reg_write(dev, SX127X_REG_FRFLSB, (uint8_t)(channel & 0xFF)); +} + +uint32_t sx127x_get_time_on_air(const sx127x_t *dev, uint8_t pkt_len) +{ + uint32_t air_time = 0; + + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + /* todo */ + break; + case SX127X_MODEM_LORA: + { + double bw = 0.0; + + /* Note: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported. */ + switch (dev->settings.lora.bandwidth) { + case SX127X_BW_125_KHZ: + bw = 125e3; + break; + case SX127X_BW_250_KHZ: + bw = 250e3; + break; + case SX127X_BW_500_KHZ: + bw = 500e3; + break; + default: + DEBUG("Invalid bandwith: %d\n", dev->settings.lora.bandwidth); + break; + } + + /* Symbol rate : time for one symbol [secs] */ + double rs = bw / (1 << dev->settings.lora.datarate); + double ts = 1 / rs; + + /* time of preamble */ + double t_preamble = (dev->settings.lora.preamble_len + 4.25) * ts; + + /* Symbol length of payload and time */ + double tmp = + ceil( + (8 * pkt_len - 4 * dev->settings.lora.datarate + 28 + + 16 * (dev->settings.lora.flags & SX127X_ENABLE_CRC_FLAG) + - (!(dev->settings.lora.flags & SX127X_ENABLE_FIXED_HEADER_LENGTH_FLAG) ? 20 : 0)) + / (double) (4 * dev->settings.lora.datarate + - (((dev->settings.lora.flags & SX127X_LOW_DATARATE_OPTIMIZE_FLAG) + > 0) ? 2 : 0))) + * (dev->settings.lora.coderate + 4); + double n_payload = 8 + ((tmp > 0) ? tmp : 0); + double t_payload = n_payload * ts; + + /* Time on air */ + double t_on_air = t_preamble + t_payload; + + /* return milli seconds */ + air_time = floor(t_on_air * 1e3 + 0.999); + } + break; + } + + return air_time; +} + +void sx127x_set_sleep(sx127x_t *dev) +{ + DEBUG("[DEBUG] Set sleep\n"); + + /* Disable running timers */ + xtimer_remove(&dev->_internal.tx_timeout_timer); + xtimer_remove(&dev->_internal.rx_timeout_timer); + + /* Put chip into sleep */ + sx127x_set_op_mode(dev, SX127X_RF_OPMODE_SLEEP); + sx127x_set_state(dev, SX127X_RF_IDLE); +} + +void sx127x_set_standby(sx127x_t *dev) +{ + DEBUG("[DEBUG] Set standby\n"); + + /* Disable running timers */ + xtimer_remove(&dev->_internal.tx_timeout_timer); + xtimer_remove(&dev->_internal.rx_timeout_timer); + + sx127x_set_op_mode(dev, SX127X_RF_OPMODE_STANDBY); + sx127x_set_state(dev, SX127X_RF_IDLE); +} + +void sx127x_set_rx(sx127x_t *dev) +{ + DEBUG("[DEBUG] Set RX\n"); + + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + /* todo */ + break; + case SX127X_MODEM_LORA: + { + sx127x_reg_write(dev, SX127X_REG_LR_INVERTIQ2, + ((dev->settings.lora.flags & SX127X_IQ_INVERTED_FLAG) ? SX127X_RF_LORA_INVERTIQ2_ON : SX127X_RF_LORA_INVERTIQ2_OFF)); + +#if defined(MODULE_SX1276) + /* ERRATA 2.3 - Receiver Spurious Reception of a LoRa Signal */ + if (dev->settings.lora.bandwidth < 9) { + sx127x_reg_write(dev, SX127X_REG_LR_DETECTOPTIMIZE, + sx127x_reg_read(dev, SX127X_REG_LR_DETECTOPTIMIZE) & 0x7F); + sx127x_reg_write(dev, SX127X_REG_LR_TEST30, 0x00); + switch (dev->settings.lora.bandwidth) { + case SX127X_BW_125_KHZ: /* 125 kHz */ + sx127x_reg_write(dev, SX127X_REG_LR_TEST2F, 0x40); + break; + case SX127X_BW_250_KHZ: /* 250 kHz */ + sx127x_reg_write(dev, SX127X_REG_LR_TEST2F, 0x40); + break; + + default: + break; + } + } + else { + sx127x_reg_write(dev, SX127X_REG_LR_DETECTOPTIMIZE, + sx127x_reg_read(dev, SX127X_REG_LR_DETECTOPTIMIZE) | 0x80); + } +#endif + + /* Setup interrupts */ + if (dev->settings.lora.flags & SX127X_CHANNEL_HOPPING_FLAG) { + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGSMASK, + /* SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT | + SX127X_RF_LORA_IRQFLAGS_RXDONE | + SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR | */ + SX127X_RF_LORA_IRQFLAGS_VALIDHEADER | + SX127X_RF_LORA_IRQFLAGS_TXDONE | + SX127X_RF_LORA_IRQFLAGS_CADDONE | + /* SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL | */ + SX127X_RF_LORA_IRQFLAGS_CADDETECTED); + + /* DIO0=RxDone, DIO2=FhssChangeChannel */ + sx127x_reg_write(dev, SX127X_REG_DIOMAPPING1, + (sx127x_reg_read(dev, SX127X_REG_DIOMAPPING1) & + SX127X_RF_LORA_DIOMAPPING1_DIO0_MASK & + SX127X_RF_LORA_DIOMAPPING1_DIO2_MASK) | + SX127X_RF_LORA_DIOMAPPING1_DIO0_00 | + SX127X_RF_LORA_DIOMAPPING1_DIO2_00); + } + else { + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGSMASK, + /* SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT | + SX127X_RF_LORA_IRQFLAGS_RXDONE | + SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR | */ + SX127X_RF_LORA_IRQFLAGS_VALIDHEADER | + SX127X_RF_LORA_IRQFLAGS_TXDONE | + SX127X_RF_LORA_IRQFLAGS_CADDONE | + SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL | + SX127X_RF_LORA_IRQFLAGS_CADDETECTED); + + /* DIO0=RxDone */ + sx127x_reg_write(dev, SX127X_REG_DIOMAPPING1, + (sx127x_reg_read(dev, SX127X_REG_DIOMAPPING1) & + SX127X_RF_LORA_DIOMAPPING1_DIO0_MASK) | + SX127X_RF_LORA_DIOMAPPING1_DIO0_00); + } + + sx127x_reg_write(dev, SX127X_REG_LR_FIFORXBASEADDR, 0); + sx127x_reg_write(dev, SX127X_REG_LR_FIFOADDRPTR, 0); + } + break; + } + + sx127x_set_state(dev, SX127X_RF_RX_RUNNING); + if (dev->settings.window_timeout != 0) { + xtimer_set(&(dev->_internal.rx_timeout_timer), + dev->settings.window_timeout); + } + + if (dev->settings.lora.flags & SX127X_RX_CONTINUOUS_FLAG) { + sx127x_set_op_mode(dev, SX127X_RF_LORA_OPMODE_RECEIVER); + } + else { + sx127x_set_op_mode(dev, SX127X_RF_LORA_OPMODE_RECEIVER_SINGLE); + } +} + +void sx127x_set_tx(sx127x_t *dev) +{ + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + /* todo */ + break; + case SX127X_MODEM_LORA: + { + if (dev->settings.lora.flags & SX127X_CHANNEL_HOPPING_FLAG) { + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGSMASK, + SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT | + SX127X_RF_LORA_IRQFLAGS_RXDONE | + SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR | + SX127X_RF_LORA_IRQFLAGS_VALIDHEADER | + /* RFLR_IRQFLAGS_TXDONE | */ + SX127X_RF_LORA_IRQFLAGS_CADDONE | + /* RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | */ + SX127X_RF_LORA_IRQFLAGS_CADDETECTED); + + /* DIO0=TxDone, DIO2=FhssChangeChannel */ + sx127x_reg_write(dev, SX127X_REG_DIOMAPPING1, + (sx127x_reg_read(dev, SX127X_REG_DIOMAPPING1 ) & + SX127X_RF_LORA_DIOMAPPING1_DIO0_MASK & + SX127X_RF_LORA_DIOMAPPING1_DIO2_MASK) | + SX127X_RF_LORA_DIOMAPPING1_DIO0_01 | + SX127X_RF_LORA_DIOMAPPING1_DIO2_00); + } + else + { + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGSMASK, + SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT | + SX127X_RF_LORA_IRQFLAGS_RXDONE | + SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR | + SX127X_RF_LORA_IRQFLAGS_VALIDHEADER | + /* RFLR_IRQFLAGS_TXDONE | */ + SX127X_RF_LORA_IRQFLAGS_CADDONE | + SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL | + SX127X_RF_LORA_IRQFLAGS_CADDETECTED); + + /* DIO0=TxDone */ + sx127x_reg_write(dev, SX127X_REG_DIOMAPPING1, + (sx127x_reg_read(dev, SX127X_REG_DIOMAPPING1) & + SX127X_RF_LORA_DIOMAPPING1_DIO0_MASK) | + SX127X_RF_LORA_DIOMAPPING1_DIO0_01); + } + } + break; + } + + sx127x_set_state(dev, SX127X_RF_RX_RUNNING); + if (dev->settings.window_timeout != 0) { + xtimer_set(&(dev->_internal.tx_timeout_timer), + dev->settings.window_timeout); + } + sx127x_set_op_mode(dev, SX127X_RF_OPMODE_TRANSMITTER ); +} + +uint8_t sx127x_get_max_payload_len(const sx127x_t *dev) +{ + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + return sx127x_reg_read(dev, SX127X_REG_PAYLOADLENGTH); + + case SX127X_MODEM_LORA: + return sx127x_reg_read(dev, SX127X_REG_LR_PAYLOADMAXLENGTH); + } + + /* should never be reached */ + return 0; +} + +void sx127x_set_max_payload_len(const sx127x_t *dev, uint8_t maxlen) +{ + DEBUG("[DEBUG] Set max payload len: %d\n", maxlen); + + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + sx127x_reg_write(dev, SX127X_REG_PAYLOADLENGTH, maxlen); + break; + + case SX127X_MODEM_LORA: + sx127x_reg_write(dev, SX127X_REG_LR_PAYLOADMAXLENGTH, maxlen); + break; + } +} + +uint8_t sx127x_get_op_mode(const sx127x_t *dev) +{ + return sx127x_reg_read(dev, SX127X_REG_OPMODE) & ~SX127X_RF_OPMODE_MASK; +} + +void sx127x_set_op_mode(const sx127x_t *dev, uint8_t op_mode) +{ +#if ENABLE_DEBUG + switch(op_mode) { + case SX127X_RF_OPMODE_SLEEP: + DEBUG("[DEBUG] Set op mode: SLEEP\n"); + break; + case SX127X_RF_OPMODE_STANDBY: + DEBUG("[DEBUG] Set op mode: STANDBY\n"); + break; + case SX127X_RF_OPMODE_RECEIVER: + DEBUG("[DEBUG] Set op mode: RECEIVER\n"); + break; + case SX127X_RF_OPMODE_TRANSMITTER: + DEBUG("[DEBUG] Set op mode: TRANSMITTER\n"); + break; + default: + DEBUG("[DEBUG] Set op mode: UNKNOWN\n"); + break; + } +#endif + + /* Replace previous mode value and setup new mode value */ + sx127x_reg_write(dev, SX127X_REG_OPMODE, + (sx127x_reg_read(dev, SX127X_REG_OPMODE) & SX127X_RF_OPMODE_MASK) | op_mode); +} + +uint8_t sx127x_get_bandwidth(const sx127x_t *dev) +{ + return dev->settings.lora.bandwidth; +} + +inline void _low_datarate_optimize(sx127x_t *dev) +{ + if ( ((dev->settings.lora.bandwidth == SX127X_BW_125_KHZ) && + ((dev->settings.lora.datarate == SX127X_SF11) || + (dev->settings.lora.datarate == SX127X_SF12))) || + ((dev->settings.lora.bandwidth == SX127X_BW_250_KHZ) && + (dev->settings.lora.datarate == SX127X_SF12))) { + dev->settings.lora.flags |= SX127X_LOW_DATARATE_OPTIMIZE_FLAG; + } else { + dev->settings.lora.flags &= ~SX127X_LOW_DATARATE_OPTIMIZE_FLAG; + } + +#if defined(MODULE_SX1272) + sx127x_reg_write(dev, SX127X_REG_LR_MODEMCONFIG1, + (sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG1) & + SX127X_RF_LORA_MODEMCONFIG1_LOWDATARATEOPTIMIZE_MASK) | + ((dev->settings.lora.flags & SX127X_LOW_DATARATE_OPTIMIZE_FLAG))); +#else /* MODULE_SX1276 */ + sx127x_reg_write(dev, SX127X_REG_LR_MODEMCONFIG3, + (sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG3) & + SX127X_RF_LORA_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK) | + ((dev->settings.lora.flags & SX127X_LOW_DATARATE_OPTIMIZE_FLAG) << 3)); +#endif +} + +inline void _update_bandwidth(const sx127x_t *dev) +{ + uint8_t config1_reg = sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG1); +#if defined(MODULE_SX1272) + config1_reg &= SX1272_RF_LORA_MODEMCONFIG1_BW_MASK; + switch (dev->settings.lora.bandwidth) { + case SX127X_BW_125_KHZ: + config1_reg |= SX1272_RF_LORA_MODEMCONFIG1_BW_125_KHZ; + break; + case SX127X_BW_250_KHZ: + config1_reg |= SX1272_RF_LORA_MODEMCONFIG1_BW_250_KHZ; + break; + case SX127X_BW_500_KHZ: + config1_reg |= SX1272_RF_LORA_MODEMCONFIG1_BW_500_KHZ; + break; + default: + DEBUG("Unsupported bandwidth, %d", dev->settings.lora.bandwidth); + break; + } +#else /* MODULE_SX1276 */ + config1_reg &= SX1276_RF_LORA_MODEMCONFIG1_BW_MASK; + switch (dev->settings.lora.bandwidth) { + case SX127X_BW_125_KHZ: + config1_reg |= SX1276_RF_LORA_MODEMCONFIG1_BW_125_KHZ; + break; + case SX127X_BW_250_KHZ: + config1_reg |= SX1276_RF_LORA_MODEMCONFIG1_BW_250_KHZ; + break; + case SX127X_BW_500_KHZ: + config1_reg |= SX1276_RF_LORA_MODEMCONFIG1_BW_500_KHZ; + break; + default: + DEBUG("Unsupported bandwidth, %d", dev->settings.lora.bandwidth); + break; + } +#endif + sx127x_reg_write(dev, SX127X_REG_LR_MODEMCONFIG1, config1_reg); +} + +void sx127x_set_bandwidth(sx127x_t *dev, uint8_t bandwidth) +{ + DEBUG("[DEBUG] Set bandwidth: %d\n", bandwidth); + + dev->settings.lora.bandwidth = bandwidth; + + _update_bandwidth((const sx127x_t *)dev); + + _low_datarate_optimize(dev); + + /* ERRATA sensitivity tweaks */ + if ((dev->settings.lora.bandwidth == SX127X_BW_500_KHZ) && + (dev->settings.channel > SX127X_RF_MID_BAND_THRESH)) { + /* ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth */ + sx127x_reg_write(dev, SX127X_REG_LR_TEST36, 0x02); + sx127x_reg_write(dev, SX127X_REG_LR_TEST3A, 0x64); + } + else if (dev->settings.lora.bandwidth == SX127X_BW_500_KHZ) { + /* ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth */ + sx127x_reg_write(dev, SX127X_REG_LR_TEST36, 0x02); + sx127x_reg_write(dev, SX127X_REG_LR_TEST3A, 0x7F); + } + else { + /* ERRATA 2.1 - Sensitivity Optimization with another Bandwidth */ + sx127x_reg_write(dev, SX127X_REG_LR_TEST36, 0x03); + } +} + +uint8_t sx127x_get_spreading_factor(const sx127x_t *dev) +{ + return dev->settings.lora.datarate; +} + +void sx127x_set_spreading_factor(sx127x_t *dev, uint8_t datarate) +{ + DEBUG("[DEBUG] Set spreading factor: %d\n", datarate); + + if (datarate == SX127X_SF6 && + !(dev->settings.lora.flags & SX127X_ENABLE_FIXED_HEADER_LENGTH_FLAG)) { + /* SF 6 is only valid when using explicit header mode */ + DEBUG("Spreading Factor 6 can only be used when explicit header " + "mode is set, this mode is not supported by this driver." + "Ignoring.\n"); + return; + } + + dev->settings.lora.datarate = datarate; + + uint8_t config2_reg = sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG2); + config2_reg &= SX127X_RF_LORA_MODEMCONFIG2_SF_MASK; + config2_reg |= datarate << 4; + sx127x_reg_write(dev, SX127X_REG_LR_MODEMCONFIG2, config2_reg); + + _low_datarate_optimize(dev); + + switch(dev->settings.lora.datarate) { + case SX127X_SF6: + sx127x_reg_write(dev, SX127X_REG_LR_DETECTOPTIMIZE, + SX127X_RF_LORA_DETECTIONOPTIMIZE_SF6); + sx127x_reg_write(dev, SX127X_REG_LR_DETECTIONTHRESHOLD, + SX127X_RF_LORA_DETECTIONTHRESH_SF6); + break; + default: + sx127x_reg_write(dev, SX127X_REG_LR_DETECTOPTIMIZE, + SX127X_RF_LORA_DETECTIONOPTIMIZE_SF7_TO_SF12); + sx127x_reg_write(dev, SX127X_REG_LR_DETECTIONTHRESHOLD, + SX127X_RF_LORA_DETECTIONTHRESH_SF7_TO_SF12); + break; + } +} + +uint8_t sx127x_get_coding_rate(const sx127x_t *dev) +{ + return dev->settings.lora.coderate; +} + +void sx127x_set_coding_rate(sx127x_t *dev, uint8_t coderate) +{ + DEBUG("[DEBUG] Set coding rate: %d\n", coderate); + + dev->settings.lora.coderate = coderate; + uint8_t config1_reg = sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG1); + +#if defined(MODULE_SX1272) + config1_reg &= SX1272_RF_LORA_MODEMCONFIG1_CODINGRATE_MASK; + config1_reg |= coderate << 3; +#else /* MODULE_SX1276 */ + config1_reg &= SX1276_RF_LORA_MODEMCONFIG1_CODINGRATE_MASK; + config1_reg |= coderate << 1; +#endif + + sx127x_reg_write(dev, SX127X_REG_LR_MODEMCONFIG1, config1_reg); +} + +static inline void _set_flag(sx127x_t *dev, uint8_t flag, bool value) +{ + if (value) { + dev->settings.lora.flags |= flag; + } + else { + dev->settings.lora.flags &= ~flag; + } +} + +bool sx127x_get_rx_single(const sx127x_t *dev) +{ + return !(dev->settings.lora.flags & SX127X_RX_CONTINUOUS_FLAG); +} + +void sx127x_set_rx_single(sx127x_t *dev, bool single) +{ + DEBUG("[DEBUG] Set RX single: %d\n", single); + _set_flag(dev, SX127X_RX_CONTINUOUS_FLAG, !single); +} + +bool sx127x_get_crc(const sx127x_t *dev) +{ +#if defined(MODULE_SX1272) + return (sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG1) & + SX1272_RF_LORA_MODEMCONFIG1_RXPAYLOADCRC_MASK); +#else /* MODULE_SX1276 */ + return (sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG2) & + SX1276_RF_LORA_MODEMCONFIG2_RXPAYLOADCRC_MASK); +#endif +} + +void sx127x_set_crc(sx127x_t *dev, bool crc) +{ + DEBUG("[DEBUG] Set CRC: %d\n", crc); + _set_flag(dev, SX127X_ENABLE_CRC_FLAG, crc); + +#if defined(MODULE_SX1272) + uint8_t config2_reg = sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG1); + config2_reg &= SX1272_RF_LORA_MODEMCONFIG1_RXPAYLOADCRC_MASK; + config2_reg |= crc << 1; + sx127x_reg_write(dev, SX127X_REG_LR_MODEMCONFIG1, config2_reg); +#else /* MODULE_SX1276 */ + uint8_t config2_reg = sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG2); + config2_reg &= SX1276_RF_LORA_MODEMCONFIG2_RXPAYLOADCRC_MASK; + config2_reg |= crc << 2; + sx127x_reg_write(dev, SX127X_REG_LR_MODEMCONFIG2, config2_reg); +#endif +} + +uint8_t sx127x_get_hop_period(const sx127x_t *dev) +{ + return sx127x_reg_read(dev, SX127X_REG_LR_HOPPERIOD); +} + +void sx127x_set_hop_period(sx127x_t *dev, uint8_t hop_period) +{ + DEBUG("[DEBUG] Set Hop period: %d\n", hop_period); + + dev->settings.lora.freq_hop_period = hop_period; + + uint8_t tmp = sx127x_reg_read(dev, SX127X_REG_LR_PLLHOP); + if (dev->settings.lora.flags & SX127X_CHANNEL_HOPPING_FLAG) { + tmp |= SX127X_RF_LORA_PLLHOP_FASTHOP_ON; + sx127x_reg_write(dev, SX127X_REG_LR_PLLHOP, tmp); + sx127x_reg_write(dev, SX127X_REG_LR_HOPPERIOD, hop_period); + } +} + +bool sx127x_get_fixed_header_len_mode(const sx127x_t *dev) +{ + return dev->settings.lora.flags & SX127X_ENABLE_FIXED_HEADER_LENGTH_FLAG; +} + +void sx127x_set_fixed_header_len_mode(sx127x_t *dev, bool fixed_len) +{ + DEBUG("[DEBUG] Set fixed header length: %d\n", fixed_len); + + _set_flag(dev, SX127X_ENABLE_FIXED_HEADER_LENGTH_FLAG, fixed_len); + + uint8_t config1_reg = sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG1); +#if defined(MODULE_SX1272) + config1_reg &= SX1272_RF_LORA_MODEMCONFIG1_IMPLICITHEADER_MASK; + config1_reg |= fixed_len << 2; +#else /* MODULE_SX1276 */ + config1_reg &= SX1276_RF_LORA_MODEMCONFIG1_IMPLICITHEADER_MASK; + config1_reg |= fixed_len; +#endif + sx127x_reg_write(dev, SX127X_REG_LR_MODEMCONFIG1, config1_reg); +} + +uint8_t sx127x_get_payload_length(const sx127x_t *dev) +{ + return sx127x_reg_read(dev, SX127X_REG_LR_PAYLOADLENGTH);; +} + +void sx127x_set_payload_length(sx127x_t *dev, uint8_t len) +{ + DEBUG("[DEBUG] Set payload len: %d\n", len); + + sx127x_reg_write(dev, SX127X_REG_LR_PAYLOADLENGTH, len); +} + +static inline uint8_t sx127x_get_pa_select(uint32_t channel) +{ +#if defined(MODULE_SX1272) + (void) channel; +#if SX1272_DEFAULT_PASELECT + return SX127X_RF_PACONFIG_PASELECT_RFO; +#else + return SX127X_RF_PACONFIG_PASELECT_PABOOST; +#endif +#else /* MODULE_SX1276 */ + if (channel < SX127X_RF_MID_BAND_THRESH) { + return SX127X_RF_PACONFIG_PASELECT_PABOOST; + } + else { + return SX127X_RF_PACONFIG_PASELECT_RFO; + } +#endif +} + +uint8_t sx127x_get_tx_power(const sx127x_t *dev) +{ + return dev->settings.lora.power; +} + +void sx127x_set_tx_power(sx127x_t *dev, uint8_t power) +{ + DEBUG("[DEBUG] Set power: %d\n", power); + + dev->settings.lora.power = power; + + uint8_t pa_config = sx127x_reg_read(dev, SX127X_REG_PACONFIG); +#if defined(MODULE_SX1272) + uint8_t pa_dac = sx127x_reg_read(dev, SX1272_REG_PADAC); +#else /* MODULE_SX1276 */ + uint8_t pa_dac = sx127x_reg_read(dev, SX1276_REG_PADAC); +#endif + + pa_config = ((pa_config & SX127X_RF_PACONFIG_PASELECT_MASK) | + sx127x_get_pa_select(dev->settings.channel)); + +#if defined(MODULE_SX1276) + /* max power is 14dBm */ + pa_config = (pa_config & SX127X_RF_PACONFIG_MAX_POWER_MASK) | 0x70; +#endif + + sx127x_reg_write(dev, SX127X_REG_PARAMP, SX127X_RF_PARAMP_0050_US); + + if ((pa_config & SX127X_RF_PACONFIG_PASELECT_PABOOST) + == SX127X_RF_PACONFIG_PASELECT_PABOOST) { + if (power > 17) { + pa_dac = ((pa_dac & SX127X_RF_PADAC_20DBM_MASK) | + SX127X_RF_PADAC_20DBM_ON); + } else { + pa_dac = ((pa_dac & SX127X_RF_PADAC_20DBM_MASK) | + SX127X_RF_PADAC_20DBM_OFF); + } + if ((pa_dac & SX127X_RF_PADAC_20DBM_ON) == SX127X_RF_PADAC_20DBM_ON) { + if (power < 5) { + power = 5; + } + if (power > 20) { + power = 20; + } + + pa_config = ((pa_config & SX127X_RF_PACONFIG_OUTPUTPOWER_MASK) | + (uint8_t)((uint16_t)(power - 5) & 0x0F)); + } else { + if (power < 2) { + power = 2; + } + if (power > 17) { + power = 17; + } + + pa_config = ((pa_config & SX127X_RF_PACONFIG_OUTPUTPOWER_MASK) | + (uint8_t)((uint16_t)(power - 2) & 0x0F)); + } + } else { + if (power < -1) { + power = -1; + } + if (power > 14) { + power = 14; + } + + pa_config = ((pa_config & SX127X_RF_PACONFIG_OUTPUTPOWER_MASK) | + (uint8_t)((uint16_t)(power + 1) & 0x0F)); + } + + sx127x_reg_write(dev, SX127X_REG_PACONFIG, pa_config); +#if defined(MODULE_SX1272) + sx127x_reg_write(dev, SX1272_REG_PADAC, pa_dac); +#else /* MODULE_SX1276 */ + sx127x_reg_write(dev, SX1276_REG_PADAC, pa_dac); +#endif +} + +uint16_t sx127x_get_preamble_length(const sx127x_t *dev) +{ + return dev->settings.lora.preamble_len; +} + +void sx127x_set_preamble_length(sx127x_t *dev, uint16_t preamble) +{ + DEBUG("[DEBUG] Set preamble length: %d\n", preamble); + + dev->settings.lora.preamble_len = preamble; + + sx127x_reg_write(dev, SX127X_REG_LR_PREAMBLEMSB, + (preamble >> 8) & 0xFF); + sx127x_reg_write(dev, SX127X_REG_LR_PREAMBLELSB, + preamble & 0xFF); +} + +void sx127x_set_rx_timeout(sx127x_t *dev, uint32_t timeout) +{ + DEBUG("[DEBUG] Set RX timeout: %lu\n", timeout); + + dev->settings.lora.rx_timeout = timeout; +} + +void sx127x_set_tx_timeout(sx127x_t *dev, uint32_t timeout) +{ + DEBUG("[DEBUG] Set TX timeout: %lu\n", timeout); + + dev->settings.lora.tx_timeout = timeout; +} + +void sx127x_set_symbol_timeout(sx127x_t *dev, uint16_t timeout) +{ + DEBUG("[DEBUG] Set symbol timeout: %d\n", timeout); + + dev->settings.lora.rx_timeout = timeout; + + uint8_t config2_reg = sx127x_reg_read(dev, SX127X_REG_LR_MODEMCONFIG2); + config2_reg &= SX127X_RF_LORA_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK; + config2_reg |= (timeout >> 8) & ~SX127X_RF_LORA_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK; + sx127x_reg_write(dev, SX127X_REG_LR_MODEMCONFIG2, config2_reg); + sx127x_reg_write(dev, SX127X_REG_LR_SYMBTIMEOUTLSB,timeout & 0xFF); +} + +void sx127x_set_iq_invert(sx127x_t *dev, bool iq_invert) +{ + DEBUG("[DEBUG] Set IQ invert: %d\n", iq_invert); + + _set_flag(dev, SX127X_IQ_INVERTED_FLAG, iq_invert); + + sx127x_reg_write(dev, SX127X_REG_LR_INVERTIQ, + (sx127x_reg_read(dev, SX127X_REG_LR_INVERTIQ) & + SX127X_RF_LORA_INVERTIQ_RX_MASK & + SX127X_RF_LORA_INVERTIQ_TX_MASK) | + SX127X_RF_LORA_INVERTIQ_RX_OFF | + (iq_invert ? SX127X_RF_LORA_INVERTIQ_TX_ON : SX127X_RF_LORA_INVERTIQ_TX_OFF)); + + sx127x_reg_write(dev, SX127X_REG_LR_INVERTIQ2, + (iq_invert ? SX127X_RF_LORA_INVERTIQ2_ON : SX127X_RF_LORA_INVERTIQ2_OFF)); +} + +void sx127x_set_freq_hop(sx127x_t *dev, bool freq_hop_on) +{ + DEBUG("[DEBUG] Set freq hop: %d\n", freq_hop_on); + + _set_flag(dev, SX127X_CHANNEL_HOPPING_FLAG, freq_hop_on); +} diff --git a/drivers/sx127x/sx127x_internal.c b/drivers/sx127x/sx127x_internal.c new file mode 100644 index 0000000000000000000000000000000000000000..a70a094df0777bf96b60b45fc8c9234f92f9f0ad --- /dev/null +++ b/drivers/sx127x/sx127x_internal.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016 Unwired Devices <info@unwds.com> + * 2017 Inria Chile + * 2017 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 drivers_sx127x + * @{ + * @file + * @brief implementation of internal functions for sx127x + * + * @author Eugene P. <ep@unwds.com> + * @author José Ignacio Alamos <jose.alamos@inria.cl> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> + * @} + */ +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <inttypes.h> + +#include "irq.h" + +#include "sx127x.h" +#include "sx127x_registers.h" +#include "sx127x_internal.h" +#include "sx127x_params.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + + +bool sx127x_test(const sx127x_t *dev) +{ + /* Read version number and compare with sx127x assigned revision */ + uint8_t version = sx127x_reg_read(dev, SX127X_REG_VERSION); + +#if defined(MODULE_SX1272) + if (version != VERSION_SX1272) { + DEBUG("[Error] sx1272 test failed, invalid version number: %d\n", + version); + return false; + } + DEBUG("SX1272 transceiver detected.\n"); +#else /* MODULE_SX1276) */ + if (version != VERSION_SX1276) { + DEBUG("[Error] sx1276 test failed, invalid version number: %d\n", + version); + return false; + } + DEBUG("SX1276 transceiver detected.\n"); +#endif + + return true; +} + +void sx127x_reg_write(const sx127x_t *dev, uint8_t addr, uint8_t data) +{ + sx127x_reg_write_burst(dev, addr, &data, 1); +} + +uint8_t sx127x_reg_read(const sx127x_t *dev, uint8_t addr) +{ + uint8_t data; + + sx127x_reg_read_burst(dev, addr, &data, 1); + + return data; +} + +void sx127x_reg_write_burst(const sx127x_t *dev, uint8_t addr, uint8_t *buffer, + uint8_t size) +{ + unsigned int cpsr; + + spi_acquire(dev->params.spi, SPI_CS_UNDEF, SX127X_PARAM_SPI_MODE, SX127X_PARAM_SPI_SPEED); + cpsr = irq_disable(); + + gpio_clear(dev->params.nss_pin); + spi_transfer_regs(dev->params.spi, SPI_CS_UNDEF, addr | 0x80, (char *) buffer, NULL, size); + gpio_set(dev->params.nss_pin); + + irq_restore(cpsr); + spi_release(dev->params.spi); +} + +void sx127x_reg_read_burst(const sx127x_t *dev, uint8_t addr, uint8_t *buffer, + uint8_t size) +{ + unsigned int cpsr; + + cpsr = irq_disable(); + + spi_acquire(dev->params.spi, SPI_CS_UNDEF, SX127X_PARAM_SPI_MODE, SX127X_PARAM_SPI_SPEED); + + gpio_clear(dev->params.nss_pin); + spi_transfer_regs(dev->params.spi, SPI_CS_UNDEF, addr & 0x7F, NULL, (char *) buffer, size); + gpio_set(dev->params.nss_pin); + + spi_release(dev->params.spi); + + irq_restore(cpsr); +} + +void sx127x_write_fifo(const sx127x_t *dev, uint8_t *buffer, uint8_t size) +{ + sx127x_reg_write_burst(dev, 0, buffer, size); +} + +void sx127x_read_fifo(const sx127x_t *dev, uint8_t *buffer, uint8_t size) +{ + sx127x_reg_read_burst(dev, 0, buffer, size); +} + +void sx127x_rx_chain_calibration(sx127x_t *dev) +{ + uint8_t reg_pa_config_init_val; + uint32_t initial_freq; + + /* Save context */ + reg_pa_config_init_val = sx127x_reg_read(dev, SX127X_REG_PACONFIG); + initial_freq = (double) (((uint32_t) sx127x_reg_read(dev, SX127X_REG_FRFMSB) << 16) + | ((uint32_t) sx127x_reg_read(dev, SX127X_REG_FRFMID) << 8) + | ((uint32_t) sx127x_reg_read(dev, SX127X_REG_FRFLSB))) * (double) SX127X_FREQUENCY_RESOLUTION; + + /* Cut the PA just in case, RFO output, power = -1 dBm */ + sx127x_reg_write(dev, SX127X_REG_PACONFIG, 0x00); + + /* Launch Rx chain calibration for LF band */ + sx127x_reg_write(dev, + SX127X_REG_IMAGECAL, + (sx127x_reg_read(dev, SX127X_REG_IMAGECAL) & SX127X_RF_IMAGECAL_IMAGECAL_MASK) + | SX127X_RF_IMAGECAL_IMAGECAL_START); + + while ((sx127x_reg_read(dev, SX127X_REG_IMAGECAL) & SX127X_RF_IMAGECAL_IMAGECAL_RUNNING) + == SX127X_RF_IMAGECAL_IMAGECAL_RUNNING) { + } + + /* Set a frequency in HF band */ + sx127x_set_channel(dev, SX127X_HF_CHANNEL_DEFAULT); + + /* Launch Rx chain calibration for HF band */ + sx127x_reg_write(dev, + SX127X_REG_IMAGECAL, + (sx127x_reg_read(dev, SX127X_REG_IMAGECAL) & SX127X_RF_IMAGECAL_IMAGECAL_MASK) + | SX127X_RF_IMAGECAL_IMAGECAL_START); + while ((sx127x_reg_read(dev, SX127X_REG_IMAGECAL) & SX127X_RF_IMAGECAL_IMAGECAL_RUNNING) + == SX127X_RF_IMAGECAL_IMAGECAL_RUNNING) { + } + + /* Restore context */ + sx127x_reg_write(dev, SX127X_REG_PACONFIG, reg_pa_config_init_val); + sx127x_set_channel(dev, initial_freq); +} + +int16_t sx127x_read_rssi(const sx127x_t *dev) +{ + int16_t rssi = 0; + + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + rssi = -(sx127x_reg_read(dev, SX127X_REG_RSSIVALUE) >> 1); + break; + case SX127X_MODEM_LORA: +#if defined(MODULE_SX1272) + rssi = SX127X_RSSI_OFFSET + sx127x_reg_read(dev, SX127X_REG_LR_RSSIVALUE); +#else /* MODULE_SX1276 */ + if (dev->settings.channel > SX127X_RF_MID_BAND_THRESH) { + rssi = SX127X_RSSI_OFFSET_HF + sx127x_reg_read(dev, SX127X_REG_LR_RSSIVALUE); + } + else { + rssi = SX127X_RSSI_OFFSET_LF + sx127x_reg_read(dev, SX127X_REG_LR_RSSIVALUE); + } +#endif + break; + default: + rssi = -1; + break; + } + + return rssi; +} + +void sx127x_start_cad(sx127x_t *dev) +{ + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + break; + case SX127X_MODEM_LORA: + /* Disable all interrupts except CAD-related */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGSMASK, + SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT | + SX127X_RF_LORA_IRQFLAGS_RXDONE | + SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR | + SX127X_RF_LORA_IRQFLAGS_VALIDHEADER | + SX127X_RF_LORA_IRQFLAGS_TXDONE | + /*SX127X_RF_LORA_IRQFLAGS_CADDONE |*/ + SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL + /* | SX127X_RF_LORA_IRQFLAGS_CADDETECTED*/ + ); + + /* DIO3 = CADDone */ + sx127x_reg_write(dev, SX127X_REG_DIOMAPPING1, + (sx127x_reg_read(dev, SX127X_REG_DIOMAPPING1) & + SX127X_RF_LORA_DIOMAPPING1_DIO3_MASK) | + SX127X_RF_LORA_DIOMAPPING1_DIO3_00); + + sx127x_set_state(dev, SX127X_RF_CAD); + sx127x_set_op_mode(dev, SX127X_RF_LORA_OPMODE_CAD); + break; + default: + break; + } +} diff --git a/drivers/sx127x/sx127x_netdev.c b/drivers/sx127x/sx127x_netdev.c new file mode 100644 index 0000000000000000000000000000000000000000..8ed22160875456eaafd1dc67d678e6c751583c5a --- /dev/null +++ b/drivers/sx127x/sx127x_netdev.c @@ -0,0 +1,540 @@ +/* + * Copyright (C) 2016 Fundación Inria Chile + * + * 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_sx127x + * @{ + * @file + * @brief Netdev adaptation for the sx127x driver + * + * @author Eugene P. <ep@unwds.com> + * @author José Ignacio Alamos <jose.alamos@inria.cl> + * @} + */ + +#include <stddef.h> +#include <string.h> +#include <errno.h> + +#include "net/netopt.h" +#include "net/netdev.h" +#include "sx127x_registers.h" +#include "sx127x_internal.h" +#include "sx127x_netdev.h" +#include "sx127x.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/* Internal helper functions */ +static uint8_t _get_tx_len(const struct iovec *vector, unsigned count); +static int _set_state(sx127x_t *dev, netopt_state_t state); +static int _get_state(sx127x_t *dev, void *val); + +/* Netdev driver api functions */ +static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count); +static int _recv(netdev_t *netdev, void *buf, size_t len, void *info); +static int _init(netdev_t *netdev); +static void _isr(netdev_t *netdev); +static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len); +static int _set(netdev_t *netdev, netopt_t opt, void *val, size_t len); + +const netdev_driver_t sx127x_driver = { + .send = _send, + .recv = _recv, + .init = _init, + .isr = _isr, + .get = _get, + .set = _set, +}; + +static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count) +{ + sx127x_t *dev = (sx127x_t*) netdev; + + if (sx127x_get_state(dev) == SX127X_RF_TX_RUNNING) { + DEBUG("[WARNING] Cannot send packet: radio alredy in transmitting " + "state.\n"); + return -ENOTSUP; + } + + uint8_t size; + size = _get_tx_len(vector, count); + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + /* todo */ + break; + case SX127X_MODEM_LORA: + /* Initializes the payload size */ + sx127x_set_payload_length(dev, size); + + /* Full buffer used for Tx */ + sx127x_reg_write(dev, SX127X_REG_LR_FIFOTXBASEADDR, 0x00); + sx127x_reg_write(dev, SX127X_REG_LR_FIFOADDRPTR, 0x00); + + /* FIFO operations can not take place in Sleep mode + * So wake up the chip */ + if (sx127x_get_op_mode(dev) == SX127X_RF_OPMODE_SLEEP) { + sx127x_set_standby(dev); + xtimer_usleep(SX127X_RADIO_WAKEUP_TIME); /* wait for chip wake up */ + } + + /* Write payload buffer */ + for (size_t i = 0;i < count ; i++) { + sx127x_write_fifo(dev, vector[i].iov_base, vector[i].iov_len); + } + break; + default: + puts("sx127x_netdev, Unsupported modem"); + break; + } + + /* Enable TXDONE interrupt */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGSMASK, + SX127X_RF_LORA_IRQFLAGS_RXTIMEOUT | + SX127X_RF_LORA_IRQFLAGS_RXDONE | + SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR | + SX127X_RF_LORA_IRQFLAGS_VALIDHEADER | + /* SX127X_RF_LORA_IRQFLAGS_TXDONE | */ + SX127X_RF_LORA_IRQFLAGS_CADDONE | + SX127X_RF_LORA_IRQFLAGS_FHSSCHANGEDCHANNEL | + SX127X_RF_LORA_IRQFLAGS_CADDETECTED); + + /* Set TXDONE interrupt to the DIO0 line */ + sx127x_reg_write(dev, SX127X_REG_DIOMAPPING1, + (sx127x_reg_read(dev, SX127X_REG_DIOMAPPING1) & + SX127X_RF_LORA_DIOMAPPING1_DIO0_MASK) | + SX127X_RF_LORA_DIOMAPPING1_DIO0_01); + + /* Start TX timeout timer */ + xtimer_set(&dev->_internal.tx_timeout_timer, dev->settings.lora.tx_timeout); + + /* Put chip into transfer mode */ + sx127x_set_state(dev, SX127X_RF_TX_RUNNING); + sx127x_set_op_mode(dev, SX127X_RF_OPMODE_TRANSMITTER); + + return 0; +} + +static int _recv(netdev_t *netdev, void *buf, size_t len, void *info) +{ + sx127x_t *dev = (sx127x_t*) netdev; + volatile uint8_t irq_flags = 0; + uint8_t size = 0; + switch (dev->settings.modem) { + case SX127X_MODEM_FSK: + /* todo */ + break; + case SX127X_MODEM_LORA: + /* Clear IRQ */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGS, SX127X_RF_LORA_IRQFLAGS_RXDONE); + + irq_flags = sx127x_reg_read(dev, SX127X_REG_LR_IRQFLAGS); + if ( (irq_flags & SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR_MASK) == + SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR) { + /* Clear IRQ */ + sx127x_reg_write(dev, SX127X_REG_LR_IRQFLAGS, + SX127X_RF_LORA_IRQFLAGS_PAYLOADCRCERROR); + + if (!(dev->settings.lora.flags & SX127X_RX_CONTINUOUS_FLAG)) { + sx127x_set_state(dev, SX127X_RF_IDLE); + } + + xtimer_remove(&dev->_internal.rx_timeout_timer); + netdev->event_callback(netdev, NETDEV_EVENT_CRC_ERROR); + return -EBADMSG; + } + + netdev_sx127x_lora_packet_info_t *packet_info = info; + if (packet_info) { + /* there is no LQI for LoRa */ + packet_info->lqi = 0; + uint8_t snr_value = sx127x_reg_read(dev, SX127X_REG_LR_PKTSNRVALUE); + if (snr_value & 0x80) { /* The SNR is negative */ + /* Invert and divide by 4 */ + packet_info->snr = -1 * ((~snr_value + 1) & 0xFF) >> 2; + } + else { + /* Divide by 4 */ + packet_info->snr = (snr_value & 0xFF) >> 2; + } + + int16_t rssi = sx127x_reg_read(dev, SX127X_REG_LR_PKTRSSIVALUE); + + if (packet_info->snr < 0) { +#if defined(MODULE_SX1272) + packet_info->rssi = SX127X_RSSI_OFFSET + rssi + (rssi >> 4) + packet_info->snr; +#else /* MODULE_SX1276 */ + if (dev->settings.channel > SX127X_RF_MID_BAND_THRESH) { + packet_info->rssi = SX127X_RSSI_OFFSET_HF + rssi + (rssi >> 4) + packet_info->snr; + } + else { + packet_info->rssi = SX127X_RSSI_OFFSET_LF + rssi + (rssi >> 4) + packet_info->snr; + } +#endif + } + else { +#if defined(MODULE_SX1272) + packet_info->rssi = SX127X_RSSI_OFFSET + rssi + (rssi >> 4); +#else /* MODULE_SX1276 */ + if (dev->settings.channel > SX127X_RF_MID_BAND_THRESH) { + packet_info->rssi = SX127X_RSSI_OFFSET_HF + rssi + (rssi >> 4); + } + else { + packet_info->rssi = SX127X_RSSI_OFFSET_LF + rssi + (rssi >> 4); + } +#endif + } + packet_info->time_on_air = sx127x_get_time_on_air(dev, len); + } + + size = sx127x_reg_read(dev, SX127X_REG_LR_RXNBBYTES); + if (buf == NULL) { + return size; + } + + if (size > len) { + return -ENOBUFS; + } + + if (!(dev->settings.lora.flags & SX127X_RX_CONTINUOUS_FLAG)) { + sx127x_set_state(dev, SX127X_RF_IDLE); + } + + xtimer_remove(&dev->_internal.rx_timeout_timer); + + /* Read the last packet from FIFO */ + uint8_t last_rx_addr = sx127x_reg_read(dev, SX127X_REG_LR_FIFORXCURRENTADDR); + sx127x_reg_write(dev, SX127X_REG_LR_FIFOADDRPTR, last_rx_addr); + sx127x_read_fifo(dev, (uint8_t*)buf, size); + break; + default: + break; + } + + return size; +} + +static int _init(netdev_t *netdev) +{ + sx127x_t *sx127x = (sx127x_t*) netdev; + + sx127x->irq = 0; + sx127x_radio_settings_t settings; + settings.channel = SX127X_CHANNEL_DEFAULT; + settings.modem = SX127X_MODEM_DEFAULT; + settings.state = SX127X_RF_IDLE; + + sx127x->settings = settings; + + /* Launch initialization of driver and device */ + DEBUG("init_radio: initializing driver...\n"); + sx127x_init(sx127x); + + sx127x_init_radio_settings(sx127x); + /* Put chip into sleep */ + sx127x_set_sleep(sx127x); + + DEBUG("init_radio: sx127x initialization done\n"); + + return 0; +} + +static void _isr(netdev_t *netdev) +{ + sx127x_t *dev = (sx127x_t *) netdev; + + uint8_t irq = dev->irq; + dev->irq = 0; + + switch (irq) { + case SX127X_IRQ_DIO0: + sx127x_on_dio0(dev); + break; + + case SX127X_IRQ_DIO1: + sx127x_on_dio1(dev); + break; + + case SX127X_IRQ_DIO2: + sx127x_on_dio2(dev); + break; + + case SX127X_IRQ_DIO3: + sx127x_on_dio3(dev); + break; + + default: + break; + } +} + +static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len) +{ + sx127x_t *dev = (sx127x_t*) netdev; + + if (dev == NULL) { + return -ENODEV; + } + + switch(opt) { + case NETOPT_STATE: + assert(max_len >= sizeof(netopt_state_t)); + return _get_state(dev, val); + + case NETOPT_DEVICE_MODE: + assert(max_len >= sizeof(uint8_t)); + *((uint8_t*) val) = dev->settings.modem; + return sizeof(uint8_t); + + case NETOPT_CHANNEL: + assert(max_len >= sizeof(uint32_t)); + *((uint32_t*) val) = sx127x_get_channel(dev); + return sizeof(uint32_t); + + case NETOPT_BANDWIDTH: + assert(max_len >= sizeof(uint8_t)); + *((uint8_t*) val) = sx127x_get_bandwidth(dev); + return sizeof(uint8_t); + + case NETOPT_SPREADING_FACTOR: + assert(max_len >= sizeof(uint8_t)); + *((uint8_t*) val) = sx127x_get_spreading_factor(dev); + return sizeof(uint8_t); + + case NETOPT_CODING_RATE: + assert(max_len >= sizeof(uint8_t)); + *((uint8_t*) val) = sx127x_get_coding_rate(dev); + return sizeof(uint8_t); + + case NETOPT_MAX_PACKET_SIZE: + assert(max_len >= sizeof(uint8_t)); + *((uint8_t*) val) = sx127x_get_max_payload_len(dev); + return sizeof(uint8_t); + + case NETOPT_INTEGRITY_CHECK: + assert(max_len >= sizeof(netopt_enable_t)); + *((netopt_enable_t*) val) = sx127x_get_crc(dev) ? NETOPT_ENABLE : NETOPT_DISABLE; + break; + + case NETOPT_CHANNEL_HOP: + assert(max_len >= sizeof(netopt_enable_t)); + *((netopt_enable_t*) val) = (dev->settings.lora.flags & SX127X_CHANNEL_HOPPING_FLAG) ? NETOPT_ENABLE : NETOPT_DISABLE; + break; + + case NETOPT_CHANNEL_HOP_PERIOD: + assert(max_len >= sizeof(uint8_t)); + *((uint8_t*) val) = sx127x_get_hop_period(dev); + return sizeof(uint8_t); + + case NETOPT_SINGLE_RECEIVE: + assert(max_len >= sizeof(uint8_t)); + *((netopt_enable_t*) val) = sx127x_get_rx_single(dev) ? NETOPT_ENABLE : NETOPT_DISABLE; + break; + + default: + break; + } + + return 0; +} + +static int _set(netdev_t *netdev, netopt_t opt, void *val, size_t len) +{ + sx127x_t *dev = (sx127x_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, *((netopt_state_t*) val)); + + case NETOPT_DEVICE_MODE: + assert(len <= sizeof(uint8_t)); + sx127x_set_modem(dev, *((uint8_t*) val)); + return sizeof(netopt_enable_t); + + case NETOPT_CHANNEL: + assert(len <= sizeof(uint32_t)); + sx127x_set_channel(dev, *((uint32_t*) val)); + return sizeof(uint32_t); + + case NETOPT_BANDWIDTH: + assert(len <= sizeof(uint8_t)); + uint8_t bw = *((uint8_t *)val); + if (bw < SX127X_BW_125_KHZ || + bw > SX127X_BW_500_KHZ) { + res = -EINVAL; + break; + } + sx127x_set_bandwidth(dev, bw); + return sizeof(uint8_t); + + case NETOPT_SPREADING_FACTOR: + assert(len <= sizeof(uint8_t)); + uint8_t sf = *((uint8_t *)val); + if (sf < SX127X_SF6 || + sf > SX127X_SF12) { + res = -EINVAL; + break; + } + sx127x_set_spreading_factor(dev, sf); + return sizeof(uint8_t); + + case NETOPT_CODING_RATE: + assert(len <= sizeof(uint8_t)); + uint8_t cr = *((uint8_t *)val); + if (cr < SX127X_CR_4_5 || + cr > SX127X_CR_4_8) { + res = -EINVAL; + break; + } + sx127x_set_coding_rate(dev, cr); + return sizeof(uint8_t); + + case NETOPT_MAX_PACKET_SIZE: + assert(len <= sizeof(uint8_t)); + sx127x_set_max_payload_len(dev, *((uint8_t*) val)); + return sizeof(uint8_t); + + case NETOPT_INTEGRITY_CHECK: + assert(len <= sizeof(netopt_enable_t)); + sx127x_set_crc(dev, *((netopt_enable_t*) val) ? true : false); + return sizeof(netopt_enable_t); + + case NETOPT_CHANNEL_HOP: + assert(len <= sizeof(netopt_enable_t)); + sx127x_set_freq_hop(dev, *((netopt_enable_t*) val) ? true : false); + return sizeof(netopt_enable_t); + + case NETOPT_CHANNEL_HOP_PERIOD: + assert(len <= sizeof(uint8_t)); + sx127x_set_hop_period(dev, *((uint8_t*) val)); + return sizeof(uint8_t); + + case NETOPT_SINGLE_RECEIVE: + assert(len <= sizeof(uint8_t)); + sx127x_set_rx_single(dev, *((netopt_enable_t*) val) ? true : false); + return sizeof(netopt_enable_t); + + case NETOPT_RX_TIMEOUT: + assert(len <= sizeof(uint32_t)); + sx127x_set_rx_timeout(dev, *((uint32_t*) val)); + return sizeof(uint32_t); + + case NETOPT_TX_TIMEOUT: + assert(len <= sizeof(uint32_t)); + sx127x_set_tx_timeout(dev, *((uint32_t*) val)); + return sizeof(uint32_t); + + case NETOPT_TX_POWER: + assert(len <= sizeof(uint8_t)); + sx127x_set_tx_power(dev, *((uint8_t*) val)); + return sizeof(uint16_t); + + case NETOPT_FIXED_HEADER: + assert(len <= sizeof(netopt_enable_t)); + sx127x_set_fixed_header_len_mode(dev, *((netopt_enable_t*) val) ? true : false); + return sizeof(netopt_enable_t); + + case NETOPT_PREAMBLE_LENGTH: + assert(len <= sizeof(uint16_t)); + sx127x_set_preamble_length(dev, *((uint16_t*) val)); + return sizeof(uint16_t); + + case NETOPT_IQ_INVERT: + assert(len <= sizeof(netopt_enable_t)); + sx127x_set_iq_invert(dev, *((netopt_enable_t*) val) ? true : false); + return sizeof(bool); + + default: + break; + } + + return res; +} + +static uint8_t _get_tx_len(const struct iovec *vector, unsigned count) +{ + uint8_t len = 0; + + for (int i=0 ; i < count ; i++) { + len += vector[i].iov_len; + } + + return len; +} + +static int _set_state(sx127x_t *dev, netopt_state_t state) +{ + switch (state) { + case NETOPT_STATE_SLEEP: + sx127x_set_sleep(dev); + break; + + case NETOPT_STATE_STANDBY: + sx127x_set_standby(dev); + break; + + case NETOPT_STATE_IDLE: + dev->settings.window_timeout = 0; + /* set permanent listening */ + sx127x_set_rx(dev); + break; + + case NETOPT_STATE_RX: + sx127x_set_rx(dev); + break; + + case NETOPT_STATE_TX: + sx127x_set_tx(dev); + break; + + case NETOPT_STATE_RESET: + sx127x_reset(dev); + break; + + default: + return -ENOTSUP; + } + return sizeof(netopt_state_t); +} + +static int _get_state(sx127x_t *dev, void *val) +{ + uint8_t op_mode; + op_mode = sx127x_get_op_mode(dev); + netopt_state_t state; + switch(op_mode) { + case SX127X_RF_OPMODE_SLEEP: + state = NETOPT_STATE_SLEEP; + break; + + case SX127X_RF_OPMODE_STANDBY: + state = NETOPT_STATE_STANDBY; + break; + + case SX127X_RF_OPMODE_TRANSMITTER: + state = NETOPT_STATE_TX; + break; + + case SX127X_RF_OPMODE_RECEIVER: + case SX127X_RF_LORA_OPMODE_RECEIVER_SINGLE: + state = NETOPT_STATE_IDLE; + break; + + default: + break; + } + memcpy(val, &state, sizeof(netopt_state_t)); + return sizeof(netopt_state_t); +} diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 3a738ad65ebbb40bd009b34671da3afe18433063..dfd2f6fef434fbdf9d5e2e7aeef3544264a1c0b0 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -76,5 +76,9 @@ PSEUDOMODULES += adc081c PSEUDOMODULES += adc101c PSEUDOMODULES += adc121c +# include variants of SX127X drivers as pseudo modules +PSEUDOMODULES += sx1272 +PSEUDOMODULES += sx1276 + # add all pseudo random number generator variants as pseudomodules PSEUDOMODULES += prng_% diff --git a/sys/include/net/netopt.h b/sys/include/net/netopt.h index 16d2a6975f8c9eb128eca506ceaca6b5da4bc3a3..810051762bcefeb52225725bef5c181d6751bc68 100644 --- a/sys/include/net/netopt.h +++ b/sys/include/net/netopt.h @@ -269,10 +269,81 @@ typedef enum { */ NETOPT_LAST_ED_LEVEL, + /** + * @brief Get/Set preamble length as uint16_t in host byte order. + */ + NETOPT_PREAMBLE_LENGTH, + + /** + * @brief Enable/disable integrity check (e.g CRC). + */ + NETOPT_INTEGRITY_CHECK, + + /** + * @brief Enable/disable channel hopping. + */ + NETOPT_CHANNEL_HOP, + + /** + * @brief Get/Set channel hopping period as uint8_t. + */ + NETOPT_CHANNEL_HOP_PERIOD, + + /** + * @brief Enable/disable single packet reception. + * + * If enabled, RX is turned off upon reception of a packet + */ + NETOPT_SINGLE_RECEIVE, + + /** + * @brief Get/Set the reception timeout of a packet. + * + * Values are retrieved/passed as uint32_t in host byte order. + */ + NETOPT_RX_TIMEOUT, + + /** + * @brief Get/Set the transmission timeout of a packet. + * + * Values are retrieved/passed as uint32_t in host byte order. + */ + NETOPT_TX_TIMEOUT, + + /** + * @brief Get/Set the radio modem type as uint8_t. + */ + NETOPT_DEVICE_MODE, + + /** + * @brief Get/Set the radio modulation bandwidth as uint8_t. + */ + NETOPT_BANDWIDTH, + + /** + * @brief Get/Set the radio spreading factor as uint8_t. + */ + NETOPT_SPREADING_FACTOR, + + /** + * @brief Get/Set the radio coding rate as uint8_t. + */ + NETOPT_CODING_RATE, + + /** + * @brief Enable/disable fixed header mode. + */ + NETOPT_FIXED_HEADER, + + /** + * @brief Enable/disable IQ inverted. + */ + NETOPT_IQ_INVERT, + /* add more options if needed */ /** - * @brief maximum number of options defined here + * @brief maximum number of options defined here. * * @note Interfaces are not meant to respond to that. */ @@ -306,6 +377,8 @@ typedef enum { * transmitting a packet */ NETOPT_STATE_RESET, /**< triggers a hardware reset. The resulting * state of the network device is @ref NETOPT_STATE_IDLE */ + NETOPT_STATE_STANDBY, /**< standby mode. The devices is awake but + * not listening to packets. */ /* add other states if needed */ } netopt_state_t; diff --git a/sys/net/crosslayer/netopt/netopt.c b/sys/net/crosslayer/netopt/netopt.c index 63d89f0279ddce36c591087cb22d8972244f52f4..b4842a5895c03aaebfefc7328a7d8e40c5a8cc22 100644 --- a/sys/net/crosslayer/netopt/netopt.c +++ b/sys/net/crosslayer/netopt/netopt.c @@ -24,44 +24,57 @@ extern "C" { #endif static const char *_netopt_strmap[] = { - [NETOPT_CHANNEL] = "NETOPT_CHANNEL", - [NETOPT_IS_CHANNEL_CLR] = "NETOPT_IS_CHANNEL_CLR", - [NETOPT_ADDRESS] = "NETOPT_ADDRESS", - [NETOPT_ADDRESS_LONG] = "NETOPT_ADDRESS_LONG", - [NETOPT_ADDR_LEN] = "NETOPT_ADDR_LEN", - [NETOPT_SRC_LEN] = "NETOPT_SRC_LEN", - [NETOPT_NID] = "NETOPT_NID", - [NETOPT_IPV6_IID] = "NETOPT_IPV6_IID", - [NETOPT_TX_POWER] = "NETOPT_TX_POWER", - [NETOPT_MAX_PACKET_SIZE] = "NETOPT_MAX_PACKET_SIZE", - [NETOPT_PRELOADING] = "NETOPT_PRELOADING", - [NETOPT_PROMISCUOUSMODE] = "NETOPT_PROMISCUOUSMODE", - [NETOPT_AUTOACK] = "NETOPT_AUTOACK", - [NETOPT_ACK_REQ] = "NETOPT_ACK_REQ", - [NETOPT_RETRANS] = "NETOPT_RETRANS", - [NETOPT_PROTO] = "NETOPT_PROTO", - [NETOPT_STATE] = "NETOPT_STATE", - [NETOPT_RAWMODE] = "NETOPT_RAWMODE", - [NETOPT_RX_START_IRQ] = "NETOPT_RX_START_IRQ", - [NETOPT_RX_END_IRQ] = "NETOPT_RX_END_IRQ", - [NETOPT_TX_START_IRQ] = "NETOPT_TX_START_IRQ", - [NETOPT_TX_END_IRQ] = "NETOPT_TX_END_IRQ", - [NETOPT_AUTOCCA] = "NETOPT_AUTOCCA", - [NETOPT_CSMA] = "NETOPT_CSMA", - [NETOPT_CSMA_RETRIES] = "NETOPT_CSMA_RETRIES", - [NETOPT_IS_WIRED] = "NETOPT_IS_WIRED", - [NETOPT_DEVICE_TYPE] = "NETOPT_DEVICE_TYPE", - [NETOPT_CHANNEL_PAGE] = "NETOPT_CHANNEL_PAGE", - [NETOPT_CCA_THRESHOLD] = "NETOPT_CCA_THRESHOLD", - [NETOPT_CCA_MODE] = "NETOPT_CCA_MODE", - [NETOPT_STATS] = "NETOPT_STATS", - [NETOPT_ENCRYPTION] = "NETOPT_ENCRYPTION", - [NETOPT_ENCRYPTION_KEY] = "NETOPT_ENCRYPTION_KEY", - [NETOPT_RF_TESTMODE] = "NETOPT_RF_TESTMODE", - [NETOPT_L2FILTER] = "NETOPT_L2FILTER", - [NETOPT_L2FILTER_RM] = "NETOPT_L2FILTER_RM", - [NETOPT_LAST_ED_LEVEL] = "NETOPT_LAST_ED_LEVEL", - [NETOPT_NUMOF] = "NETOPT_NUMOF", + [NETOPT_CHANNEL] = "NETOPT_CHANNEL", + [NETOPT_IS_CHANNEL_CLR] = "NETOPT_IS_CHANNEL_CLR", + [NETOPT_ADDRESS] = "NETOPT_ADDRESS", + [NETOPT_ADDRESS_LONG] = "NETOPT_ADDRESS_LONG", + [NETOPT_ADDR_LEN] = "NETOPT_ADDR_LEN", + [NETOPT_SRC_LEN] = "NETOPT_SRC_LEN", + [NETOPT_NID] = "NETOPT_NID", + [NETOPT_IPV6_IID] = "NETOPT_IPV6_IID", + [NETOPT_TX_POWER] = "NETOPT_TX_POWER", + [NETOPT_MAX_PACKET_SIZE] = "NETOPT_MAX_PACKET_SIZE", + [NETOPT_PRELOADING] = "NETOPT_PRELOADING", + [NETOPT_PROMISCUOUSMODE] = "NETOPT_PROMISCUOUSMODE", + [NETOPT_AUTOACK] = "NETOPT_AUTOACK", + [NETOPT_ACK_REQ] = "NETOPT_ACK_REQ", + [NETOPT_RETRANS] = "NETOPT_RETRANS", + [NETOPT_PROTO] = "NETOPT_PROTO", + [NETOPT_STATE] = "NETOPT_STATE", + [NETOPT_RAWMODE] = "NETOPT_RAWMODE", + [NETOPT_RX_START_IRQ] = "NETOPT_RX_START_IRQ", + [NETOPT_RX_END_IRQ] = "NETOPT_RX_END_IRQ", + [NETOPT_TX_START_IRQ] = "NETOPT_TX_START_IRQ", + [NETOPT_TX_END_IRQ] = "NETOPT_TX_END_IRQ", + [NETOPT_AUTOCCA] = "NETOPT_AUTOCCA", + [NETOPT_CSMA] = "NETOPT_CSMA", + [NETOPT_CSMA_RETRIES] = "NETOPT_CSMA_RETRIES", + [NETOPT_IS_WIRED] = "NETOPT_IS_WIRED", + [NETOPT_DEVICE_TYPE] = "NETOPT_DEVICE_TYPE", + [NETOPT_CHANNEL_PAGE] = "NETOPT_CHANNEL_PAGE", + [NETOPT_CCA_THRESHOLD] = "NETOPT_CCA_THRESHOLD", + [NETOPT_CCA_MODE] = "NETOPT_CCA_MODE", + [NETOPT_STATS] = "NETOPT_STATS", + [NETOPT_ENCRYPTION] = "NETOPT_ENCRYPTION", + [NETOPT_ENCRYPTION_KEY] = "NETOPT_ENCRYPTION_KEY", + [NETOPT_RF_TESTMODE] = "NETOPT_RF_TESTMODE", + [NETOPT_L2FILTER] = "NETOPT_L2FILTER", + [NETOPT_L2FILTER_RM] = "NETOPT_L2FILTER_RM", + [NETOPT_LAST_ED_LEVEL] = "NETOPT_LAST_ED_LEVEL", + [NETOPT_DEVICE_MODE] = "NETOPT_DEVICE_MODE", + [NETOPT_BANDWIDTH] = "NETOPT_BANDWIDTH", + [NETOPT_SPREADING_FACTOR] = "NETOPT_SPREADING_FACTOR", + [NETOPT_CODING_RATE] = "NETOPT_CODING_RATE", + [NETOPT_SINGLE_RECEIVE] = "NETOPT_SINGLE_RECEIVE", + [NETOPT_RX_TIMEOUT] = "NETOPT_RX_TIMEOUT", + [NETOPT_TX_TIMEOUT] = "NETOPT_TX_TIMEOUT", + [NETOPT_PREAMBLE_LENGTH] = "NETOPT_PREAMBLE_LENGTH", + [NETOPT_INTEGRITY_CHECK] = "NETOPT_INTEGRITY_CHECK", + [NETOPT_CHANNEL_HOP] = "NETOPT_CHANNEL_HOP", + [NETOPT_CHANNEL_HOP_PERIOD] = "NETOPT_CHANNEL_HOP_PERIOD", + [NETOPT_FIXED_HEADER] = "NETOPT_FIXED_HEADER", + [NETOPT_IQ_INVERT] = "NETOPT_IQ_INVERT", + [NETOPT_NUMOF] = "NETOPT_NUMOF", }; const char *netopt2str(netopt_t opt) diff --git a/tests/driver_sx127x/Makefile b/tests/driver_sx127x/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..73f0261ad7b8e8d093ec160e9e266b58e4ead846 --- /dev/null +++ b/tests/driver_sx127x/Makefile @@ -0,0 +1,24 @@ +APPLICATION = driver_sx127x +include ../Makefile.tests_common + +BOARD_INSUFFICIENT_MEMORY := nucleo32-f031 + +BOARD ?= nucleo-l1 + +USEMODULE += od +USEMODULE += shell +USEMODULE += shell_commands +USEMODULE += ps +USEMODULE += xtimer + +DRIVER ?= sx1276 + +# use SX1276 by default +USEMODULE += ${DRIVER} + +FEATURES_REQUIRED ?= periph_spi +FEATURES_REQUIRED ?= periph_gpio + +CFLAGS += -DDEVELHELP + +include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_sx127x/README.md b/tests/driver_sx127x/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7465b4cd81ff18fd3406b072f0dfa8c96617f5f8 --- /dev/null +++ b/tests/driver_sx127x/README.md @@ -0,0 +1,134 @@ +## About + +This is a manual test application for the SX127X radio driver. + +This test application uses the default pin configuration provided by the +driver implementation and that matches the ST Nucleo 64 pins layout. +It is best to use [SX1272](https://developer.mbed.org/components/SX1272MB2xAS/) +or [SX1276](https://developer.mbed.org/components/SX1276MB1xAS/) mbed modules +with nucleo boards or the all-in-one +[ST P-NUCLEO-LRWAN1 LoRa kit](http://www.st.com/en/evaluation-tools/p-nucleo-lrwan1.html). + +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/sx127x/include/sx127x_params.h` file to your application directory. + +By default the application builds the SX1276 version of the driver. If you +want to use this application with a SX1272 module, set the variable `DRIVER` in +the application [Makefile](Makefile): +``` +DRIVER = sx1272 +``` +instead of +``` +DRIVER = sx1276 +``` +You can also pass `DRIVER` when building the application: +``` +$ make BOARD=nucleo-l073 DRIVER=sx1272 -C tests/drivers_sx127x flash term +``` + +## Usage + +This test application provides low level shell commands to interact with the +SX1272/SX1276 modules. + +Once the board is flashed and you are connected via serial to the shell, use the `help` +command to display the available commands: +``` +> help +help +Command Description +--------------------------------------- +setup Initialize LoRa modulation settings +random Get random number from sx127x +channel Get/Set channel frequency (in Hz) +register Get/Set value(s) of registers of sx127x +send Send raw payload string +listen Start raw payload listener +reboot Reboot the node +ps Prints information about running threads. +``` + +Once the board is booted, use `setup` to configure the basic LoRa settings: +* Bandwidth: 125kHz, 250kHz or 500kHz +* Spreading factor: between 7 and 12 +* Code rate: between 5 and 8 + +Example: +``` +> setup 125 12 5 +setup: setting 125KHz bandwidth +[Info] setup: configuration set with success +``` + +All values are supported by both SX1272 and SX1276. + +The `random ` command use the Semtech to generate a random integer value. + +Example: +``` +> random +random: number from sx127x: 2339536315 +> random +random: number from sx127x: 863363442 +``` + +The `channel` command allows to change/query the RF frequency channel. +The default is 868MHz for Europe, change to 915MHz for America. The frequency +is given/returned in Hz. + +Example: +``` +> channel set 868000000 +New channel set +> channel get +Channel: 868000000 +``` + +The `register` command allows to get/set the content of the module registers. +Example: +``` +> register get all +- listing all registers - +Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F +0x00 00 80 1A 0B 00 52 D9 00 00 0F 08 2B 00 4D 80 00 +0x10 00 FF 00 00 00 00 00 00 00 00 00 00 00 72 C4 0A +0x20 00 08 01 FF 00 00 08 00 00 00 00 00 00 50 14 40 +0x30 00 03 05 67 1C 0A 00 0A 42 12 64 19 01 A1 00 00 +0x40 00 10 22 13 0E 5B DB 24 0E 81 3A 2E 00 03 00 00 +0x50 00 00 04 23 01 24 3F B0 09 05 84 0B D0 0B D0 32 +0x60 2B 14 00 00 10 00 00 00 0F E0 00 0C F6 10 1D 07 +0x70 00 5C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +- done - +``` + +Use the `send` and `receive` commands in order to exchange messages between several modules. +You need first to ensure that all modules are configured the same: use `setup` and +`channel` commands to configure them correctly. + +Assuming you have 2 modules, one listening and one sending messages, do the following: +* On listening module: +``` +> setup 125 12 5 +setup: setting 125KHz bandwidth +[Info] setup: configuration set with success +> channel set 868000000 +New channel set +> listen +Listen mode set +``` +* On sending module: +``` +> setup 125 12 5 +setup: setting 125KHz bandwidth +[Info] setup: configuration set with success +> channel set 868000000 +New channel set +> send This\ is\ RIOT! +``` + +On the listening module, the message is captured: +``` +{Payload: "This is RIOT!" (13 bytes), RSSI: 103, SNR: 240} +``` diff --git a/tests/driver_sx127x/main.c b/tests/driver_sx127x/main.c new file mode 100644 index 0000000000000000000000000000000000000000..cf7dae6e2c07a99abd569f1a81360d9de8c017b6 --- /dev/null +++ b/tests/driver_sx127x/main.c @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2016 Unwired Devices <info@unwds.com> + * 2017 Inria Chile + * 2017 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 tests + * @{ + * @file + * @brief Test application for SX127X modem driver + * + * @author Eugene P. <ep@unwds.com> + * @author José Ignacio Alamos <jose.alamos@inria.cl> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> + * @} + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "thread.h" +#include "xtimer.h" +#include "shell.h" +#include "shell_commands.h" + +#include "net/gnrc/netdev.h" +#include "net/netdev.h" + +#include "board.h" +#include "periph/rtc.h" + +#include "sx127x_internal.h" +#include "sx127x_params.h" +#include "sx127x_netdev.h" + +#define SX127X_LORA_MSG_QUEUE (16U) +#define SX127X_STACKSIZE (THREAD_STACKSIZE_DEFAULT) + +#define MSG_TYPE_ISR (0x3456) + +static char stack[SX127X_STACKSIZE]; +static kernel_pid_t _recv_pid; + +static char message[32]; +static sx127x_t sx127x; +static netdev_t *netdev; + +int lora_setup_cmd(int argc, char **argv) { + + if (argc < 4) { + puts("usage: setup " + "<bandwidth (125, 250, 500)> " + "<spreading factor (7..12)> " + "<code rate (5..8)>"); + return -1; + } + + /* Check bandwidth value */ + int bw = atoi(argv[1]); + uint8_t lora_bw; + switch (bw) { + case 125: + puts("setup: setting 125KHz bandwidth"); + lora_bw = SX127X_BW_125_KHZ; + break; + + case 250: + puts("setup: setting 250KHz bandwidth"); + lora_bw = SX127X_BW_250_KHZ; + break; + + case 500: + puts("setup: setting 500KHz bandwidth"); + lora_bw = SX127X_BW_500_KHZ; + break; + + default: + puts("[Error] setup: invalid bandwidth value given, " + "only 125, 250 or 500 allowed."); + return -1; + } + + /* Check spreading factor value */ + uint8_t lora_sf = atoi(argv[2]); + if (lora_sf < 7 || lora_sf > 12) { + puts("[Error] setup: invalid spreading factor value given"); + return -1; + } + + /* Check coding rate value */ + int cr = atoi(argv[3]);; + if (cr < 5 || cr > 8) { + puts("[Error ]setup: invalid coding rate value given"); + return -1; + } + uint8_t lora_cr = (uint8_t)(cr - 4); + + /* Configure radio device */ + netdev_t *netdev = (netdev_t*) &sx127x; + netdev->driver->set(netdev, NETOPT_BANDWIDTH, + &lora_bw, sizeof(uint8_t)); + netdev->driver->set(netdev, NETOPT_SPREADING_FACTOR, + &lora_sf, 1); + netdev->driver->set(netdev, NETOPT_CODING_RATE, + &lora_cr, sizeof(uint8_t)); + + puts("[Info] setup: configuration set with success"); + + return 0; +} + +int random_cmd(int argc, char **argv) +{ + printf("random: number from sx127x: %u\n", + (unsigned int) sx127x_random((sx127x_t*) netdev)); + + /* reinit the transceiver to default values */ + sx127x_init_radio_settings((sx127x_t*) netdev); + + return 0; +} + +int register_cmd(int argc, char **argv) +{ + if (argc < 2) { + puts("usage: register <get | set>"); + return -1; + } + + if (strstr(argv[1], "get") != NULL) { + if (argc < 3) { + puts("usage: register get <all | allinline | regnum>"); + return -1; + } + if (strcmp(argv[2], "all") == 0) { + puts("- listing all registers -"); + uint8_t reg = 0, data = 0; + /* Listing registers map */ + puts("Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F"); + for (unsigned i = 0; i <= 7; i++) { + printf("0x%02X ", i << 4); + + for (unsigned j = 0; j <= 15; j++, reg++) { + data = sx127x_reg_read(&sx127x, reg); + printf("%02X ", data); + } + puts(""); + } + puts("-done-"); + return 0; + } else if (strcmp(argv[2], "allinline") == 0) { + puts("- listing all registers in one line -"); + /* Listing registers map */ + for (uint16_t reg = 0; reg < 256; reg++) { + printf("%02X ", sx127x_reg_read(&sx127x, (uint8_t) reg)); + } + puts("- done -"); + return 0; + } else { + long int num = 0; + /* Register number in hex */ + if (strstr(argv[2], "0x") != NULL) { + num = strtol(argv[2], NULL, 16); + } else { + num = atoi(argv[2]); + } + if (num >= 0 && num <= 255) { + printf("[regs] 0x%02X = 0x%02X\n", + (uint8_t) num, + sx127x_reg_read(&sx127x, (uint8_t) num)); + } else { + puts("regs: invalid register number specified"); + return -1; + } + } + } else if (strstr(argv[1], "set") != NULL) { + if (argc < 4) { + puts("usage: register set <regnum> <value>"); + return -1; + } + + long num, val; + + /* Register number in hex */ + if (strstr(argv[2], "0x") != NULL) { + num = strtol(argv[2], NULL, 16); + } else { + num = atoi(argv[2]); + } + + /* Register value in hex */ + if (strstr(argv[3], "0x") != NULL) { + val = strtol(argv[3], NULL, 16); + } else { + val = atoi(argv[3]); + } + + sx127x_reg_write(&sx127x, (uint8_t) num, (uint8_t) val); + } + else { + puts("usage: register get <all | allinline | regnum>"); + return -1; + } + + return 0; +} + +int send_cmd(int argc, char **argv) +{ + if (argc <= 1) { + puts("usage: send <payload>"); + return -1; + } + + printf("sending \"%s\" payload (%d bytes)\n", + argv[1], strlen(argv[1]) + 1); + + struct iovec vec[1]; + vec[0].iov_base = argv[1]; + vec[0].iov_len = strlen(argv[1]) + 1; + if (netdev->driver->send(netdev, vec, 1) == -ENOTSUP) { + puts("Cannot send: radio is still transmitting"); + } + + return 0; +} + +int listen_cmd(int argc, char **argv) +{ + /* Switch to continuous listen mode */ + netdev->driver->set(netdev, NETOPT_SINGLE_RECEIVE, false, sizeof(uint8_t)); + sx127x_set_rx(&sx127x); + + printf("Listen mode set\n"); + + return 0; +} + +int channel_cmd(int argc, char **argv) +{ + if(argc < 2) { + puts("usage: channel <get|set>"); + return -1; + } + + uint32_t chan; + if (strstr(argv[1], "get") != NULL) { + netdev->driver->get(netdev, NETOPT_CHANNEL, &chan, sizeof(uint32_t)); + printf("Channel: %i\n", (int) chan); + return 0; + } + + if (strstr(argv[1], "set") != NULL) { + if(argc < 3) { + puts("usage: channel set <channel>"); + return -1; + } + chan = atoi(argv[2]); + netdev->driver->set(netdev, NETOPT_CHANNEL, &chan, sizeof(uint32_t)); + printf("New channel set\n"); + } + else { + puts("usage: channel <get|set>"); + return -1; + } + + return 0; +} + +static const shell_command_t shell_commands[] = { + { "setup", "Initialize LoRa modulation settings", lora_setup_cmd}, + { "random", "Get random number from sx127x", random_cmd }, + { "channel", "Get/Set channel frequency (in Hz)", channel_cmd }, + { "register", "Get/Set value(s) of registers of sx127x", register_cmd }, + { "send", "Send raw payload string", send_cmd }, + { "listen", "Start raw payload listener", listen_cmd }, + { NULL, NULL, NULL } +}; + +static void _event_cb(netdev_t *dev, netdev_event_t event) +{ + if (event == NETDEV_EVENT_ISR) { + msg_t msg; + + msg.type = MSG_TYPE_ISR; + msg.content.ptr = dev; + + if (msg_send(&msg, _recv_pid) <= 0) { + puts("gnrc_netdev: possibly lost interrupt."); + } + } + else { + size_t len; + netdev_sx127x_lora_packet_info_t packet_info; + switch (event) { + case NETDEV_EVENT_RX_COMPLETE: + len = dev->driver->recv(dev, NULL, 0, 0); + dev->driver->recv(dev, message, len, &packet_info); + printf("{Payload: \"%s\" (%d bytes), RSSI: %i, SNR: %i, TOA: %i}\n", + message, (int)len, + packet_info.rssi, (int)packet_info.snr, + (int)packet_info.time_on_air); + break; + case NETDEV_EVENT_TX_COMPLETE: + puts("Transmission completed"); + break; + case NETDEV_EVENT_CAD_DONE: + break; + case NETDEV_EVENT_TX_TIMEOUT: + break; + default: + printf("Unexpected netdev event received: %d\n", event); + break; + } + } +} + +void *_recv_thread(void *arg) +{ + static msg_t _msg_q[SX127X_LORA_MSG_QUEUE]; + msg_init_queue(_msg_q, SX127X_LORA_MSG_QUEUE); + + while (1) { + msg_t msg; + msg_receive(&msg); + if (msg.type == MSG_TYPE_ISR) { + netdev_t *dev = msg.content.ptr; + dev->driver->isr(dev); + } + else { + puts("Unexpected msg type"); + } + } +} + +int main(void) +{ + memcpy(&sx127x.params, sx127x_params, sizeof(sx127x_params)); + netdev = (netdev_t*) &sx127x; + netdev->driver = &sx127x_driver; + netdev->driver->init(netdev); + netdev->event_callback = _event_cb; + + _recv_pid = thread_create(stack, sizeof(stack), THREAD_PRIORITY_MAIN - 1, + THREAD_CREATE_STACKTEST, _recv_thread, NULL, + "recv_thread"); + + if (_recv_pid <= KERNEL_PID_UNDEF) { + puts("Creation of receiver thread failed"); + return 1; + } + + /* start the shell */ + puts("Initialization successful - starting the shell now"); + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + + return 0; +}