mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-02 08:43:43 +00:00
promicro LR2021 first shot
This commit is contained in:
+13
-1
@@ -210,7 +210,7 @@ set(ZEPHCORE_COMMON_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/zephcore_com
|
||||
# Detect platform from board name and add platform-specific common config
|
||||
# For boards with qualifiers like "wio_tracker_l1/nrf52840", check both the full BOARD
|
||||
# string and the BOARD_QUALIFIERS which contains just the qualifier (e.g., "nrf52840")
|
||||
if(BOARD MATCHES ".*nrf52.*" OR BOARD MATCHES "rak4631" OR BOARD MATCHES "rak_wismesh_tag" OR BOARD MATCHES "wio_tracker" OR BOARD MATCHES "ikoka_nano" OR BOARD MATCHES "t1000_e" OR BOARD MATCHES "thinknode_m1" OR BOARD MATCHES "thinknode_m3" OR BOARD MATCHES "thinknode_m6")
|
||||
if(BOARD MATCHES ".*nrf52.*" OR BOARD MATCHES "rak4631" OR BOARD MATCHES "rak_wismesh_tag" OR BOARD MATCHES "wio_tracker" OR BOARD MATCHES "ikoka_nano" OR BOARD MATCHES "t1000_e" OR BOARD MATCHES "thinknode_m1" OR BOARD MATCHES "thinknode_m3" OR BOARD MATCHES "thinknode_m6" OR BOARD MATCHES "promicro_lr2021")
|
||||
set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf52_common.conf")
|
||||
elseif(DEFINED BOARD_QUALIFIERS AND BOARD_QUALIFIERS MATCHES ".*nrf52.*")
|
||||
set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf52_common.conf")
|
||||
@@ -395,6 +395,18 @@ if(CONFIG_ZEPHCORE_RADIO_LR1110)
|
||||
target_include_directories(app PRIVATE
|
||||
${ZEPHYR_DIR}/drivers/lora/lr11xx
|
||||
)
|
||||
elseif(CONFIG_ZEPHCORE_RADIO_LR2021)
|
||||
message(STATUS "ZephCore Radio: LR2021 (Zephyr LoRa driver)")
|
||||
target_sources(app PRIVATE
|
||||
adapters/radio/LR2021Radio.cpp
|
||||
)
|
||||
target_include_directories(app PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/adapters/radio/lr20xx
|
||||
)
|
||||
get_filename_component(ZEPHYR_DIR_LR20 ${CMAKE_CURRENT_SOURCE_DIR}/../zephyr ABSOLUTE)
|
||||
target_include_directories(app PRIVATE
|
||||
${ZEPHYR_DIR_LR20}/drivers/lora/lr20xx
|
||||
)
|
||||
else()
|
||||
# Default: SX126x via native Zephyr LoRa driver
|
||||
message(STATUS "ZephCore Radio: SX126x (native Zephyr driver)")
|
||||
|
||||
@@ -241,6 +241,15 @@ config ZEPHCORE_RADIO_LR1110
|
||||
TCXO, RF switch, and PA config are in the device tree.
|
||||
For any board with an LR1110, LR1120, or LR1121 radio.
|
||||
|
||||
config ZEPHCORE_RADIO_LR2021
|
||||
bool "LR2021 (custom driver)"
|
||||
select LORA
|
||||
select SPI
|
||||
help
|
||||
Semtech LR2021 (LoRa Plus, 4th-gen) via custom ZephCore driver.
|
||||
Supports sub-GHz + 2.4 GHz ISM + NTN/SATCOM.
|
||||
TCXO, RF switch, and PA config are in the device tree.
|
||||
|
||||
endchoice
|
||||
|
||||
config ZEPHCORE_DEFAULT_TX_POWER_DBM
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* LR2021 hardware hooks for LoRaRadioBase.
|
||||
*/
|
||||
|
||||
#include "LR2021Radio.h"
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
/* LR20xx driver extension API */
|
||||
extern "C" {
|
||||
#include "lr20xx_lora.h"
|
||||
}
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(lr2021_radio, CONFIG_ZEPHCORE_LORA_LOG_LEVEL);
|
||||
|
||||
namespace mesh {
|
||||
|
||||
K_THREAD_STACK_DEFINE(lr20xx_tx_wait_stack, TX_WAIT_THREAD_STACK_SIZE);
|
||||
|
||||
LR2021Radio::LR2021Radio(const struct device *lora_dev, MainBoard &board,
|
||||
NodePrefs *prefs)
|
||||
: LoRaRadioBase(lora_dev, board, prefs)
|
||||
{
|
||||
}
|
||||
|
||||
void LR2021Radio::begin()
|
||||
{
|
||||
startTxThread(lr20xx_tx_wait_stack,
|
||||
K_THREAD_STACK_SIZEOF(lr20xx_tx_wait_stack));
|
||||
LoRaRadioBase::begin();
|
||||
}
|
||||
|
||||
/* ── Hardware primitives ──────────────────────────────────────────────── */
|
||||
|
||||
void LR2021Radio::hwConfigure(const struct lora_modem_config &cfg)
|
||||
{
|
||||
int ret = lora_config(_dev, const_cast<struct lora_modem_config *>(&cfg));
|
||||
if (ret < 0) {
|
||||
LOG_ERR("lora_config failed: %d", ret);
|
||||
}
|
||||
}
|
||||
|
||||
void LR2021Radio::hwStartReceive()
|
||||
{
|
||||
int ret = lora_recv_async(_dev, rxCallbackStatic, this);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("lora_recv_async failed: %d", ret);
|
||||
atomic_set(&_in_recv_mode, 0);
|
||||
return;
|
||||
}
|
||||
atomic_set(&_in_recv_mode, 1);
|
||||
|
||||
if (_rx_duty_cycle_enabled) {
|
||||
lr20xx_set_rx_duty_cycle(_dev, true);
|
||||
}
|
||||
}
|
||||
|
||||
void LR2021Radio::hwCancelReceive()
|
||||
{
|
||||
lora_recv_async(_dev, NULL, NULL);
|
||||
}
|
||||
|
||||
int LR2021Radio::hwSendAsync(uint8_t *buf, uint32_t len,
|
||||
struct k_poll_signal *sig)
|
||||
{
|
||||
return lora_send_async(_dev, buf, len, sig);
|
||||
}
|
||||
|
||||
int16_t LR2021Radio::hwGetCurrentRSSI()
|
||||
{
|
||||
return lr20xx_get_rssi_inst(_dev);
|
||||
}
|
||||
|
||||
bool LR2021Radio::hwIsPreambleDetected()
|
||||
{
|
||||
return lr20xx_is_receiving(_dev);
|
||||
}
|
||||
|
||||
void LR2021Radio::hwSetRxBoost(bool enable)
|
||||
{
|
||||
lr20xx_set_rx_boost(_dev, enable);
|
||||
}
|
||||
|
||||
void LR2021Radio::hwSetRxDutyCycle(bool enable)
|
||||
{
|
||||
lr20xx_set_rx_duty_cycle(_dev, enable);
|
||||
}
|
||||
|
||||
void LR2021Radio::hwResetAGC()
|
||||
{
|
||||
lr20xx_reset_agc(_dev);
|
||||
}
|
||||
|
||||
} /* namespace mesh */
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* ZephCore Radio adapter for LR2021 using Zephyr LoRa driver
|
||||
*
|
||||
* Thin wrapper around LoRaRadioBase — only hardware-specific hooks.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LoRaRadioBase.h"
|
||||
|
||||
namespace mesh {
|
||||
|
||||
class LR2021Radio : public LoRaRadioBase {
|
||||
public:
|
||||
LR2021Radio(const struct device *lora_dev, MainBoard &board,
|
||||
NodePrefs *prefs = nullptr);
|
||||
|
||||
void begin() override;
|
||||
|
||||
protected:
|
||||
/* Hardware primitives */
|
||||
void hwConfigure(const struct lora_modem_config &cfg) override;
|
||||
void hwStartReceive() override;
|
||||
void hwCancelReceive() override;
|
||||
int hwSendAsync(uint8_t *buf, uint32_t len,
|
||||
struct k_poll_signal *sig) override;
|
||||
int16_t hwGetCurrentRSSI() override;
|
||||
bool hwIsPreambleDetected() override;
|
||||
void hwSetRxBoost(bool enable) override;
|
||||
void hwSetRxDutyCycle(bool enable) override;
|
||||
void hwResetAGC() override;
|
||||
};
|
||||
|
||||
} /* namespace mesh */
|
||||
@@ -0,0 +1,82 @@
|
||||
/*!
|
||||
* @file lr20xx_driver_version.c
|
||||
*
|
||||
* @brief Placeholder to keep the version of LR20XX driver.
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2024. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "lr20xx_driver_version.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE MACROS-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE CONSTANTS -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE TYPES -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE VARIABLES -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DECLARATION -------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS DEFINITION ---------------------------------------------
|
||||
*/
|
||||
|
||||
const char* lr20xx_driver_version_get_version_string( void )
|
||||
{
|
||||
return ( const char* ) LR20XX_DRIVER_VERSION;
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DEFINITION --------------------------------------------
|
||||
*/
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,85 @@
|
||||
/*!
|
||||
* @file lr20xx_driver_version.h
|
||||
*
|
||||
* @brief Placeholder to keep the version of LR20XX driver.
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2024. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_DRIVER_VERSION_H
|
||||
#define LR20XX_DRIVER_VERSION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Value of driver version string
|
||||
*/
|
||||
#define LR20XX_DRIVER_VERSION "v1.3.4"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get version of driver as string
|
||||
*
|
||||
* @return String describing driver version
|
||||
*/
|
||||
const char* lr20xx_driver_version_get_version_string( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_DRIVER_VERSION_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,179 @@
|
||||
/*!
|
||||
* @file lr20xx_hal.h
|
||||
*
|
||||
* @brief Hardware Abstraction Layer (HAL) interface for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_HAL_H
|
||||
#define LR20XX_HAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief LR20XX HAL status
|
||||
*/
|
||||
typedef enum lr20xx_hal_status_e
|
||||
{
|
||||
LR20XX_HAL_STATUS_OK = 0,
|
||||
LR20XX_HAL_STATUS_ERROR = 3,
|
||||
} lr20xx_hal_status_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Reset the radio
|
||||
*
|
||||
* @param [in] context Radio implementation parameters
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_hal_status_t lr20xx_hal_reset( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Wake the radio up.
|
||||
*
|
||||
* @param [in] context Radio implementation parameters
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_hal_status_t lr20xx_hal_wakeup( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Radio data transfer - write
|
||||
*
|
||||
* @param [in] context Radio implementation parameters
|
||||
* @param [in] command Pointer to the buffer to be transmitted
|
||||
* @param [in] command_length Buffer size to be transmitted
|
||||
* @param [in] data Pointer to the buffer to be transmitted
|
||||
* @param [in] data_length Buffer size to be transmitted
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_hal_status_t lr20xx_hal_write( const void* context, const uint8_t* command, const uint16_t command_length,
|
||||
const uint8_t* data, const uint16_t data_length );
|
||||
|
||||
/*!
|
||||
* @brief Radio data transfer - read
|
||||
*
|
||||
* @remark This is a two-step radio read operation. It consists of writing the command, releasing then re-asserting the
|
||||
* NSS line, then reading a discarded dummy byte followed by data_length bytes of response data from the transceiver.
|
||||
* While reading the dummy bytes and the response data, the implementation of this function must ensure that only zero
|
||||
* bytes (NOP) are written to the SPI bus.
|
||||
*
|
||||
* @param [in] context Radio implementation parameters
|
||||
* @param [in] command Pointer to the buffer to be transmitted
|
||||
* @param [in] command_length Buffer size to be transmitted
|
||||
* @param [out] data Pointer to the buffer to be received
|
||||
* @param [in] data_length Buffer size to be received
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @remark Some hardware SPI implementations write arbitrary values on the MOSI line while reading. If this is done on
|
||||
* the LR20XX, non-zero values may be interpreted as commands. This driver does not exploit this functionality, and
|
||||
* expects that zeros be sent on the MOSI line when this command is reading the command response data.
|
||||
*/
|
||||
lr20xx_hal_status_t lr20xx_hal_read( const void* context, const uint8_t* command, const uint16_t command_length,
|
||||
uint8_t* data, const uint16_t data_length );
|
||||
|
||||
/*!
|
||||
* @brief Direct read from the SPI bus
|
||||
*
|
||||
* @remark Unlike @ref lr20xx_hal_read, this is a simple direct SPI bus SS/read/nSS operation. While reading the
|
||||
* response data, the implementation of this function must ensure that only zero bytes (NOP) are written to the SPI bus.
|
||||
*
|
||||
* @remark Formerly, that function depended on a lr20xx_hal_write_read API function, which required bidirectional SPI
|
||||
* communication. Given that all other radio functionality can be implemented with unidirectional SPI, it has been
|
||||
* decided to make this HAL API change to simplify implementation requirements.
|
||||
*
|
||||
* @remark Only required by the @ref lr20xx_system_get_status
|
||||
*
|
||||
* @param [in] context Radio implementation parameters
|
||||
* @param [out] data Pointer to the buffer to be received
|
||||
* @param [in] data_length Buffer size to be received
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_hal_status_t lr20xx_hal_direct_read( const void* context, uint8_t* data, const uint16_t data_length );
|
||||
|
||||
/*!
|
||||
* @brief Radio data transfer - read
|
||||
*
|
||||
* @remark This is a one-step radio read operation. It consists of writing the command then reading data_length bytes of
|
||||
* response data from the transceiver.
|
||||
*
|
||||
* @param [in] context Radio implementation parameters
|
||||
* @param [in] command Pointer to the buffer to be transmitted
|
||||
* @param [in] command_length Buffer size to be transmitted
|
||||
* @param [out] data Pointer to the buffer to be received
|
||||
* @param [in] data_length Buffer size to be received
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @remark Some hardware SPI implementations write arbitrary values on the MOSI line while reading. If this is done on
|
||||
* the LR20XX, non-zero values may be interpreted as commands. This driver does not exploit this functionality, and
|
||||
* expects that zeros be sent on the MOSI line when this command is reading the command response data.
|
||||
*/
|
||||
lr20xx_hal_status_t lr20xx_hal_direct_read_fifo( const void* context, const uint8_t* command,
|
||||
const uint16_t command_length, uint8_t* data,
|
||||
const uint16_t data_length );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_HAL_H
|
||||
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* LR20xx HAL implementation for Zephyr - ZephCore
|
||||
*
|
||||
* Based on Semtech SWDR001 lr20xx_driver and the ZephCore lr11xx HAL.
|
||||
*/
|
||||
|
||||
#include "lr20xx_hal_zephyr.h"
|
||||
#include "lr20xx_hal.h"
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(lr20xx_hal, CONFIG_LORA_LOG_LEVEL);
|
||||
|
||||
/* Timeout for busy wait in milliseconds.
|
||||
* LR2021 should respond within a few ms after most commands.
|
||||
* After reset, firmware boot can take up to ~300ms.
|
||||
* Use 3000ms to be safe. */
|
||||
#define LR20XX_BUSY_TIMEOUT_MS 3000
|
||||
|
||||
/* Static state for DIO1 interrupt handling */
|
||||
static struct gpio_callback dio1_gpio_cb;
|
||||
static lr20xx_dio1_callback_t dio1_user_cb = NULL;
|
||||
static void *dio1_user_data = NULL;
|
||||
|
||||
/* BUSY pin interrupt — wakes wait_on_busy() via semaphore instead of polling */
|
||||
static struct gpio_callback busy_gpio_cb;
|
||||
static K_SEM_DEFINE(busy_sem, 0, 1);
|
||||
|
||||
static void busy_isr_callback(const struct device *dev, struct gpio_callback *cb,
|
||||
uint32_t pins)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(cb);
|
||||
ARG_UNUSED(pins);
|
||||
k_sem_give(&busy_sem);
|
||||
}
|
||||
|
||||
/* Track the last SPI opcode for debugging BUSY stuck */
|
||||
static uint16_t last_opcode;
|
||||
static int64_t last_cmd_time;
|
||||
|
||||
/**
|
||||
* @brief Wait until BUSY pin goes low or timeout.
|
||||
*
|
||||
* Uses GPIO interrupt + semaphore instead of polling. The CPU sleeps
|
||||
* while waiting, saving power during long BUSY periods (reset, firmware
|
||||
* commands). Fast-path returns immediately when already ready.
|
||||
*/
|
||||
static lr20xx_hal_status_t wait_on_busy(struct lr20xx_hal_context *ctx)
|
||||
{
|
||||
/* Fast path: already ready */
|
||||
if (!gpio_pin_get_dt(&ctx->busy)) {
|
||||
return LR20XX_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
k_sem_reset(&busy_sem);
|
||||
gpio_pin_interrupt_configure_dt(&ctx->busy, GPIO_INT_EDGE_TO_INACTIVE);
|
||||
|
||||
/* Re-check after enabling interrupt to close the race window where
|
||||
* BUSY dropped between our first check and the interrupt enable. */
|
||||
if (!gpio_pin_get_dt(&ctx->busy)) {
|
||||
gpio_pin_interrupt_configure_dt(&ctx->busy, GPIO_INT_DISABLE);
|
||||
return LR20XX_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
int ret = k_sem_take(&busy_sem, K_MSEC(LR20XX_BUSY_TIMEOUT_MS));
|
||||
gpio_pin_interrupt_configure_dt(&ctx->busy, GPIO_INT_DISABLE);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
LOG_ERR("BUSY timeout! last_op=0x%04x sent_at=%lld (%lld ms ago) DIO1=%d",
|
||||
last_opcode, last_cmd_time,
|
||||
k_uptime_get() - last_cmd_time,
|
||||
gpio_pin_get_dt(&ctx->dio1));
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return LR20XX_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check device ready, wake from sleep if needed.
|
||||
*/
|
||||
static lr20xx_hal_status_t check_device_ready(struct lr20xx_hal_context *ctx)
|
||||
{
|
||||
if (!ctx->radio_is_sleeping) {
|
||||
return wait_on_busy(ctx);
|
||||
}
|
||||
|
||||
/* Radio is sleeping — wake with NSS pulse.
|
||||
* NSS is ACTIVE_LOW: logical 1 = physical LOW = asserted. */
|
||||
gpio_pin_set_dt(&ctx->nss, 1); /* Assert NSS (pull LOW) */
|
||||
k_busy_wait(10);
|
||||
gpio_pin_set_dt(&ctx->nss, 0); /* Deassert NSS (release HIGH) */
|
||||
|
||||
ctx->radio_is_sleeping = false;
|
||||
return wait_on_busy(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DIO1 GPIO interrupt callback (ISR context)
|
||||
*/
|
||||
static void dio1_isr_callback(const struct device *dev, struct gpio_callback *cb,
|
||||
uint32_t pins)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(cb);
|
||||
ARG_UNUSED(pins);
|
||||
|
||||
if (dio1_user_cb) {
|
||||
dio1_user_cb(dio1_user_data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Public HAL API - called by Semtech driver */
|
||||
|
||||
int lr20xx_hal_init(struct lr20xx_hal_context *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ctx->radio_is_sleeping = false;
|
||||
|
||||
/* Configure NSS as output, inactive (deselected).
|
||||
* GPIO_OUTPUT_INACTIVE with GPIO_ACTIVE_LOW:
|
||||
* inactive = logical 0 = physical HIGH = chip deselected. */
|
||||
ret = gpio_pin_configure_dt(&ctx->nss, GPIO_OUTPUT_INACTIVE);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to configure NSS: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure RESET as output, inactive (not in reset).
|
||||
* GPIO_OUTPUT_INACTIVE with GPIO_ACTIVE_LOW:
|
||||
* inactive = logical 0 = physical HIGH = reset released. */
|
||||
ret = gpio_pin_configure_dt(&ctx->reset, GPIO_OUTPUT_INACTIVE);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to configure RESET: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure BUSY as input */
|
||||
ret = gpio_pin_configure_dt(&ctx->busy, GPIO_INPUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to configure BUSY: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set up BUSY interrupt callback (interrupt enabled on-demand by wait_on_busy) */
|
||||
gpio_init_callback(&busy_gpio_cb, busy_isr_callback, BIT(ctx->busy.pin));
|
||||
ret = gpio_add_callback(ctx->busy.port, &busy_gpio_cb);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to add BUSY callback: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure DIO1 as input */
|
||||
ret = gpio_pin_configure_dt(&ctx->dio1, GPIO_INPUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to configure DIO1: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set up DIO1 interrupt callback */
|
||||
gpio_init_callback(&dio1_gpio_cb, dio1_isr_callback, BIT(ctx->dio1.pin));
|
||||
ret = gpio_add_callback(ctx->dio1.port, &dio1_gpio_cb);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to add DIO1 callback: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LOG_INF("LR20xx HAL initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lr20xx_hal_set_dio1_callback(struct lr20xx_hal_context *ctx,
|
||||
lr20xx_dio1_callback_t cb, void *user_data)
|
||||
{
|
||||
ARG_UNUSED(ctx);
|
||||
dio1_user_cb = cb;
|
||||
dio1_user_data = user_data;
|
||||
}
|
||||
|
||||
void lr20xx_hal_enable_dio1_irq(struct lr20xx_hal_context *ctx)
|
||||
{
|
||||
gpio_pin_interrupt_configure_dt(&ctx->dio1, GPIO_INT_EDGE_RISING);
|
||||
}
|
||||
|
||||
void lr20xx_hal_disable_dio1_irq(struct lr20xx_hal_context *ctx)
|
||||
{
|
||||
gpio_pin_interrupt_configure_dt(&ctx->dio1, GPIO_INT_DISABLE);
|
||||
}
|
||||
|
||||
/* Semtech HAL interface implementation */
|
||||
|
||||
lr20xx_hal_status_t lr20xx_hal_write(const void *context, const uint8_t *command,
|
||||
const uint16_t command_length,
|
||||
const uint8_t *data, const uint16_t data_length)
|
||||
{
|
||||
struct lr20xx_hal_context *ctx = (struct lr20xx_hal_context *)context;
|
||||
int ret;
|
||||
|
||||
/* Track opcode for BUSY timeout diagnostics */
|
||||
if (command_length >= 2) {
|
||||
last_opcode = ((uint16_t)command[0] << 8) | command[1];
|
||||
}
|
||||
last_cmd_time = k_uptime_get();
|
||||
|
||||
if (check_device_ready(ctx) != LR20XX_HAL_STATUS_OK) {
|
||||
LOG_ERR("hal_write: device not ready, op=0x%04x", last_opcode);
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
const struct spi_buf tx_bufs[] = {
|
||||
{ .buf = (uint8_t *)command, .len = command_length },
|
||||
{ .buf = (uint8_t *)data, .len = data_length },
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_bufs,
|
||||
.count = (data_length > 0) ? 2 : 1,
|
||||
};
|
||||
|
||||
/* Assert NSS (active LOW: logical 1 = physical LOW = chip selected) */
|
||||
gpio_pin_set_dt(&ctx->nss, 1);
|
||||
ret = spi_write(ctx->spi_dev, &ctx->spi_cfg, &tx);
|
||||
/* Deassert NSS (logical 0 = physical HIGH = chip deselected) */
|
||||
gpio_pin_set_dt(&ctx->nss, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_ERR("SPI write failed: %d", ret);
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Check for sleep command: opcode 0x0127 (LR2021 SetSleep) */
|
||||
if (command_length >= 2 && command[0] == 0x01 && command[1] == 0x27) {
|
||||
ctx->radio_is_sleeping = true;
|
||||
k_busy_wait(1000); /* 1ms for sleep transition */
|
||||
return LR20XX_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
return wait_on_busy(ctx);
|
||||
}
|
||||
|
||||
lr20xx_hal_status_t lr20xx_hal_read(const void *context, const uint8_t *command,
|
||||
const uint16_t command_length,
|
||||
uint8_t *data, const uint16_t data_length)
|
||||
{
|
||||
struct lr20xx_hal_context *ctx = (struct lr20xx_hal_context *)context;
|
||||
int ret;
|
||||
|
||||
/* Track opcode for BUSY timeout diagnostics */
|
||||
if (command_length >= 2) {
|
||||
last_opcode = ((uint16_t)command[0] << 8) | command[1];
|
||||
}
|
||||
last_cmd_time = k_uptime_get();
|
||||
|
||||
if (check_device_ready(ctx) != LR20XX_HAL_STATUS_OK) {
|
||||
LOG_ERR("hal_read: device not ready, op=0x%04x", last_opcode);
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Step 1: Write command */
|
||||
const struct spi_buf tx_buf = { .buf = (uint8_t *)command, .len = command_length };
|
||||
const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 };
|
||||
|
||||
gpio_pin_set_dt(&ctx->nss, 1);
|
||||
ret = spi_write(ctx->spi_dev, &ctx->spi_cfg, &tx);
|
||||
gpio_pin_set_dt(&ctx->nss, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_ERR("SPI write (cmd) failed: %d", ret);
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (data_length == 0) {
|
||||
return wait_on_busy(ctx);
|
||||
}
|
||||
|
||||
/* Step 2: Wait for device ready, then read response */
|
||||
if (check_device_ready(ctx) != LR20XX_HAL_STATUS_OK) {
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* LR20xx returns 1 dummy byte + data */
|
||||
uint8_t dummy;
|
||||
const struct spi_buf rx_bufs[] = {
|
||||
{ .buf = &dummy, .len = 1 },
|
||||
{ .buf = data, .len = data_length },
|
||||
};
|
||||
const struct spi_buf_set rx = { .buffers = rx_bufs, .count = 2 };
|
||||
|
||||
gpio_pin_set_dt(&ctx->nss, 1);
|
||||
ret = spi_read(ctx->spi_dev, &ctx->spi_cfg, &rx);
|
||||
gpio_pin_set_dt(&ctx->nss, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_ERR("SPI read failed: %d", ret);
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return LR20XX_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
lr20xx_hal_status_t lr20xx_hal_direct_read(const void *context, uint8_t *data,
|
||||
const uint16_t data_length)
|
||||
{
|
||||
struct lr20xx_hal_context *ctx = (struct lr20xx_hal_context *)context;
|
||||
int ret;
|
||||
|
||||
if (check_device_ready(ctx) != LR20XX_HAL_STATUS_OK) {
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
const struct spi_buf rx_buf = { .buf = data, .len = data_length };
|
||||
const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1 };
|
||||
|
||||
gpio_pin_set_dt(&ctx->nss, 1);
|
||||
ret = spi_read(ctx->spi_dev, &ctx->spi_cfg, &rx);
|
||||
gpio_pin_set_dt(&ctx->nss, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_ERR("SPI direct read failed: %d", ret);
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return LR20XX_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
lr20xx_hal_status_t lr20xx_hal_direct_read_fifo(const void *context,
|
||||
const uint8_t *command,
|
||||
const uint16_t command_length,
|
||||
uint8_t *data,
|
||||
const uint16_t data_length)
|
||||
{
|
||||
struct lr20xx_hal_context *ctx = (struct lr20xx_hal_context *)context;
|
||||
int ret;
|
||||
|
||||
if (check_device_ready(ctx) != LR20XX_HAL_STATUS_OK) {
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* One-step FIFO read: write command + receive data in a single NSS
|
||||
* assertion. MOSI carries the command during the first phase, then
|
||||
* zeros (NULL buf) during the data phase. MISO is discarded (NULL)
|
||||
* during the command phase, then captured into data during the data
|
||||
* phase. The nRF SPIM sends 0x00 bytes when TX buf is NULL. */
|
||||
const struct spi_buf tx_bufs[] = {
|
||||
{ .buf = (uint8_t *)command, .len = command_length },
|
||||
{ .buf = NULL, .len = data_length },
|
||||
};
|
||||
const struct spi_buf rx_bufs[] = {
|
||||
{ .buf = NULL, .len = command_length },
|
||||
{ .buf = data, .len = data_length },
|
||||
};
|
||||
const struct spi_buf_set tx_set = { .buffers = tx_bufs, .count = 2 };
|
||||
const struct spi_buf_set rx_set = { .buffers = rx_bufs, .count = 2 };
|
||||
|
||||
gpio_pin_set_dt(&ctx->nss, 1);
|
||||
ret = spi_transceive(ctx->spi_dev, &ctx->spi_cfg, &tx_set, &rx_set);
|
||||
gpio_pin_set_dt(&ctx->nss, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_ERR("SPI FIFO read failed: %d", ret);
|
||||
return LR20XX_HAL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return LR20XX_HAL_STATUS_OK;
|
||||
}
|
||||
|
||||
lr20xx_hal_status_t lr20xx_hal_reset(const void *context)
|
||||
{
|
||||
struct lr20xx_hal_context *ctx = (struct lr20xx_hal_context *)context;
|
||||
|
||||
LOG_INF("LR20xx reset: assert reset, hold 10ms");
|
||||
|
||||
/* Reset pin is ACTIVE_LOW in DTS:
|
||||
* gpio_pin_set_dt(..., 1) = logical assert = physical LOW = reset active
|
||||
* gpio_pin_set_dt(..., 0) = logical deassert = physical HIGH = reset released */
|
||||
gpio_pin_set_dt(&ctx->reset, 1); /* Assert reset */
|
||||
k_msleep(10);
|
||||
|
||||
gpio_pin_set_dt(&ctx->reset, 0); /* Deassert reset */
|
||||
|
||||
/* Wait 300ms for internal LR20xx firmware boot */
|
||||
k_msleep(300);
|
||||
|
||||
LOG_INF("LR20xx reset complete, BUSY=%d", gpio_pin_get_dt(&ctx->busy));
|
||||
|
||||
ctx->radio_is_sleeping = false;
|
||||
|
||||
return wait_on_busy(ctx);
|
||||
}
|
||||
|
||||
lr20xx_hal_status_t lr20xx_hal_wakeup(const void *context)
|
||||
{
|
||||
struct lr20xx_hal_context *ctx = (struct lr20xx_hal_context *)context;
|
||||
return check_device_ready(ctx);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* LR20xx HAL implementation for Zephyr - ZephCore
|
||||
*
|
||||
* Zephyr hardware context for the Semtech lr20xx_driver HAL interface.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_HAL_ZEPHYR_H
|
||||
#define LR20XX_HAL_ZEPHYR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
|
||||
#include "lr20xx_hal.h"
|
||||
|
||||
/**
|
||||
* @brief LR20xx HAL context for Zephyr
|
||||
*
|
||||
* Passed as the 'context' pointer to all lr20xx_hal_* functions.
|
||||
* Contains all hardware configuration needed to communicate with the radio.
|
||||
*
|
||||
* CRITICAL: All SPI operations must be protected by the driver's spi_mutex.
|
||||
* The LR2021 radio is accessed from two threads (main event loop + DIO1 work
|
||||
* queue). Without the mutex, concurrent SPI access corrupts the command/response
|
||||
* protocol and the BUSY pin gets stuck HIGH permanently.
|
||||
*/
|
||||
struct lr20xx_hal_context {
|
||||
/* SPI device */
|
||||
const struct device *spi_dev;
|
||||
struct spi_config spi_cfg;
|
||||
|
||||
/* GPIO pins */
|
||||
struct gpio_dt_spec nss; /* Chip select (direct GPIO, not SPI peripheral CS) */
|
||||
struct gpio_dt_spec reset; /* Reset pin (active-low) */
|
||||
struct gpio_dt_spec busy; /* Busy pin (high = busy) */
|
||||
struct gpio_dt_spec dio1; /* DIO1 interrupt pin */
|
||||
|
||||
/* State tracking */
|
||||
volatile bool radio_is_sleeping;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize HAL context GPIOs
|
||||
*
|
||||
* Must be called before any other HAL functions.
|
||||
*
|
||||
* @param ctx HAL context with gpio specs already filled in
|
||||
* @return 0 on success, negative errno on failure
|
||||
*/
|
||||
int lr20xx_hal_init(struct lr20xx_hal_context *ctx);
|
||||
|
||||
/**
|
||||
* @brief GPIO callback type for DIO1 interrupt
|
||||
*/
|
||||
typedef void (*lr20xx_dio1_callback_t)(void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Set DIO1 interrupt callback
|
||||
*
|
||||
* @param ctx HAL context
|
||||
* @param cb Callback (called directly from GPIO ISR — must be ISR-safe)
|
||||
* @param user_data User data passed to callback
|
||||
*/
|
||||
void lr20xx_hal_set_dio1_callback(struct lr20xx_hal_context *ctx,
|
||||
lr20xx_dio1_callback_t cb, void *user_data);
|
||||
|
||||
/** @brief Enable DIO1 edge interrupt */
|
||||
void lr20xx_hal_enable_dio1_irq(struct lr20xx_hal_context *ctx);
|
||||
|
||||
/** @brief Disable DIO1 interrupt */
|
||||
void lr20xx_hal_disable_dio1_irq(struct lr20xx_hal_context *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LR20XX_HAL_ZEPHYR_H */
|
||||
@@ -0,0 +1,798 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_common.c
|
||||
*
|
||||
* @brief Radio common driver implementation for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "lr20xx_radio_common.h"
|
||||
#include "lr20xx_regmem.h"
|
||||
#include "lr20xx_workarounds.h"
|
||||
#include "lr20xx_hal.h"
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE MACROS-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Internal RTC frequency
|
||||
*/
|
||||
#define LR20XX_RTC_FREQ_IN_HZ ( 32768UL )
|
||||
|
||||
/*!
|
||||
* @brief Frequency step in Hz used to compute the front end calibration parameter
|
||||
*
|
||||
* @see lr20xx_radio_common_calibrate_front_end_helper
|
||||
*/
|
||||
#define LR20XX_RADIO_COMMON_FRONT_END_CALIBRATION_STEP_IN_HZ ( 4000000u )
|
||||
|
||||
/**
|
||||
* Register address holding the LQI value
|
||||
*/
|
||||
#define LR20XX_RADIO_COMMON_REGISTER_LQI ( 0xF30C38 )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE CONSTANTS -------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LR20XX_RADIO_COMMON_CALIBRATE_FRONT_END_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_COMMON_SET_RF_FREQ_CMD_LENGTH ( 2 + 4 )
|
||||
#define LR20XX_RADIO_COMMON_SET_RX_PATH_CMD_LENGTH ( 2 + 2 )
|
||||
#define LR20XX_RADIO_COMMON_SET_PA_CFG_CMD_LENGTH ( 2 + 3 )
|
||||
#define LR20XX_RADIO_COMMON_SET_TX_PARAMS_CMD_LENGTH ( 2 + 2 )
|
||||
#define LR20XX_RADIO_COMMON_SET_RSSI_CALIBRATION_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_COMMON_SET_RX_TX_FALLBACK_MODE_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_COMMON_SET_PKT_TYPE_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_COMMON_GET_PKT_TYPE_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_COMMON_SET_RX_TIMEOUT_STOP_EVENT_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_COMMON_RESET_RX_STATS_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_COMMON_GET_RX_STATS_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_COMMON_GET_RSSI_INST_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_COMMON_SET_RX_CMD_LENGTH ( 2 + 3 )
|
||||
#define LR20XX_RADIO_COMMON_SET_RX_WITH_DEFAULT_TIMEOUT_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_COMMON_SET_TX_CMD_LENGTH ( 2 + 3 )
|
||||
#define LR20XX_RADIO_COMMON_SET_TX_WITH_DEFAULT_TIMEOUT_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_COMMON_SET_TX_TEST_MODE_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_COMMON_SEL_PA_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_COMMON_SET_RX_DUTY_CYCLE_CMD_LENGTH ( 2 + 7 )
|
||||
#define LR20XX_RADIO_COMMON_CONFIGURE_AUTO_TX_RX_CMD_LENGTH ( 2 + 8 )
|
||||
#define LR20XX_RADIO_COMMON_GET_RX_PACKET_LENGTH_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_COMMON_SET_DEFAULT_RX_TX_TIMEOUT_CMD_LENGTH ( 2 + 6 )
|
||||
#define LR20XX_RADIO_COMMON_SET_TIMESTAMP_SOURCE_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_COMMON_GET_TIMESTAMP_VALUE_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_COMMON_SET_CCA_CMD_LENGTH ( 2 + 3 )
|
||||
#define LR20XX_RADIO_COMMON_GET_CCA_RESULT_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_COMMON_SET_AGC_GAIN_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_COMMON_SET_CAD_PARAMS_CMD_LENGTH ( 2 + 8 )
|
||||
#define LR20XX_RADIO_COMMON_SET_CAD_CMD_LENGTH ( 2 )
|
||||
|
||||
#define LR20XX_RADIO_COMMON_RSSI_CALIBRATION_SINGLE_LENGTH ( 81u )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE TYPES -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Operating codes for radio related operations
|
||||
*/
|
||||
enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_CALIBRATE_FRONT_END_OC = 0x0123,
|
||||
LR20XX_RADIO_COMMON_SET_RF_FREQ_OC = 0x0200,
|
||||
LR20XX_RADIO_COMMON_SET_RX_PATH_OC = 0x0201,
|
||||
LR20XX_RADIO_COMMON_SET_PA_CFG_OC = 0x0202,
|
||||
LR20XX_RADIO_COMMON_SET_TX_PARAMS_OC = 0x0203,
|
||||
LR20XX_RADIO_COMMON_SET_RSSI_CALIBRATION_OC = 0x0205,
|
||||
LR20XX_RADIO_COMMON_SET_RX_TX_FALLBACK_MODE_OC = 0x0206,
|
||||
LR20XX_RADIO_COMMON_SET_PKT_TYPE_OC = 0x0207,
|
||||
LR20XX_RADIO_COMMON_GET_PKT_TYPE_OC = 0x0208,
|
||||
LR20XX_RADIO_COMMON_SET_RX_TIMEOUT_STOP_EVENT_OC = 0x0209,
|
||||
LR20XX_RADIO_COMMON_RESET_RX_STATS_OC = 0x020A,
|
||||
LR20XX_RADIO_COMMON_GET_RSSI_INST_OC = 0x020B,
|
||||
LR20XX_RADIO_COMMON_SET_RX_OC = 0x020C,
|
||||
LR20XX_RADIO_COMMON_SET_TX_OC = 0x020D,
|
||||
LR20XX_RADIO_COMMON_SET_TX_TEST_MODE_OC = 0x020E,
|
||||
LR20XX_RADIO_COMMON_SEL_PA_OC = 0x020F,
|
||||
LR20XX_RADIO_COMMON_SET_RX_DUTY_CYCLE_OC = 0x0210,
|
||||
LR20XX_RADIO_COMMON_CONFIGURE_AUTO_TX_RX = 0x0211,
|
||||
LR20XX_RADIO_COMMON_GET_RX_PACKET_LENGTH_OC = 0x0212,
|
||||
LR20XX_RADIO_COMMON_SET_DEFAULT_RX_TX_TIMEOUT_OC = 0x0215,
|
||||
LR20XX_RADIO_COMMON_SET_TIMESTAMP_SOURCE_OC = 0x0216,
|
||||
LR20XX_RADIO_COMMON_GET_TIMESTAMP_VALUE_OC = 0x0217,
|
||||
LR20XX_RADIO_COMMON_SET_CCA_OC = 0x0218,
|
||||
LR20XX_RADIO_COMMON_GET_CCA_RESULT_OC = 0x0219,
|
||||
LR20XX_RADIO_COMMON_SET_AGC_GAIN_OC = 0x021A,
|
||||
LR20XX_RADIO_COMMON_SET_CAD_PARAMETERS_OC = 0x021B,
|
||||
LR20XX_RADIO_COMMON_SET_CAD_OC = 0x021C,
|
||||
};
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE VARIABLES -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DECLARATION -------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Serialize an RSSI calibration item into an array
|
||||
*
|
||||
* @param array Pointer to the array to write to. It is up to the caller to ensure the array is long enough to store the
|
||||
* serialized item
|
||||
* @param rssi_calibration_item Pointer to the RSSI calibration item to serialize. It is up to the caller to ensure it
|
||||
* points to an actual item.
|
||||
* @return uint8_t* Pointer to the next memory slot to write
|
||||
*/
|
||||
uint8_t* lr20xx_radio_common_serialize_rssi_calibration_item(
|
||||
uint8_t* array, const lr20xx_radio_common_rssi_calibration_gain_item_t* rssi_calibration_item );
|
||||
|
||||
/**
|
||||
* @brief Serialize an RSSI calibration table into an array
|
||||
*
|
||||
* @param array Pointer to the array to write to. It is up to the caller to ensure the array is long enough to store the
|
||||
* serialized table
|
||||
* @param rssi_calibration_table Pointer to the calibration table to serialize. Can be NULL, in which case nothing is
|
||||
* written to the array
|
||||
* @return uint8_t* Pointer to the next memory slot to write
|
||||
*/
|
||||
uint8_t* lr20xx_radio_common_serialize_rssi_calibration_table(
|
||||
uint8_t* array, const lr20xx_radio_common_rssi_calibration_gain_table_t* rssi_calibration_table );
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS DEFINITION ---------------------------------------------
|
||||
*/
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_calibrate_front_end(
|
||||
const void* context, const lr20xx_radio_common_raw_front_end_calibration_value_t* front_end_calibration_values,
|
||||
uint8_t n_front_end_calibration_values )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_CALIBRATE_FRONT_END_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_CALIBRATE_FRONT_END_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_CALIBRATE_FRONT_END_OC >> 0 )
|
||||
};
|
||||
|
||||
uint8_t raw_front_end_calibration_values[6] = { 0 };
|
||||
for( uint8_t rx_path_frequency_index = 0; rx_path_frequency_index < n_front_end_calibration_values;
|
||||
rx_path_frequency_index++ )
|
||||
{
|
||||
raw_front_end_calibration_values[rx_path_frequency_index * 2] =
|
||||
( uint8_t ) ( ( uint16_t )( front_end_calibration_values[rx_path_frequency_index] ) >> 8 );
|
||||
raw_front_end_calibration_values[rx_path_frequency_index * 2 + 1] =
|
||||
( uint8_t ) ( ( uint16_t )( front_end_calibration_values[rx_path_frequency_index] ) );
|
||||
}
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_CALIBRATE_FRONT_END_CMD_LENGTH,
|
||||
raw_front_end_calibration_values,
|
||||
( uint16_t )( n_front_end_calibration_values * 2 ) );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_calibrate_front_end_helper(
|
||||
const void* context, const lr20xx_radio_common_front_end_calibration_value_t* front_end_calibration_structures,
|
||||
uint8_t n_front_end_calibration_structures )
|
||||
{
|
||||
lr20xx_radio_common_raw_front_end_calibration_value_t raw_calibration_values[3] = { 0 };
|
||||
|
||||
for( uint8_t front_end_calibration_value_index = 0;
|
||||
front_end_calibration_value_index < n_front_end_calibration_structures; front_end_calibration_value_index++ )
|
||||
{
|
||||
const uint32_t freq_hz = front_end_calibration_structures[front_end_calibration_value_index].frequency_in_hertz;
|
||||
const lr20xx_radio_common_rx_path_t rx_path =
|
||||
front_end_calibration_structures[front_end_calibration_value_index].rx_path;
|
||||
// Perform a ceil() to get a value for freq_4mhz corresponding to a frequency higher than or equal to freq_hz
|
||||
const uint16_t freq_4mhz =
|
||||
( uint16_t ) ( ( freq_hz + LR20XX_RADIO_COMMON_FRONT_END_CALIBRATION_STEP_IN_HZ - 1u ) /
|
||||
LR20XX_RADIO_COMMON_FRONT_END_CALIBRATION_STEP_IN_HZ );
|
||||
raw_calibration_values[front_end_calibration_value_index] =
|
||||
( uint16_t ) ( ( ( rx_path == LR20XX_RADIO_COMMON_RX_PATH_HF ) ? 0x8000u : 0x0000u ) | freq_4mhz );
|
||||
}
|
||||
|
||||
return lr20xx_radio_common_calibrate_front_end( context, raw_calibration_values,
|
||||
n_front_end_calibration_structures );
|
||||
}
|
||||
|
||||
uint32_t lr20xx_radio_common_convert_time_in_ms_to_rtc_step( uint32_t time_in_ms )
|
||||
{
|
||||
return ( uint32_t ) ( time_in_ms * LR20XX_RTC_FREQ_IN_HZ / 1000 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rf_freq( const void* context, uint32_t freq_in_hz )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_RF_FREQ_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RF_FREQ_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RF_FREQ_OC >> 0 ),
|
||||
( uint8_t ) ( freq_in_hz >> 24 ),
|
||||
( uint8_t ) ( freq_in_hz >> 16 ),
|
||||
( uint8_t ) ( freq_in_hz >> 8 ),
|
||||
( uint8_t ) ( freq_in_hz >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_RF_FREQ_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_path( const void* context, lr20xx_radio_common_rx_path_t rx_path,
|
||||
lr20xx_radio_common_rx_path_boost_mode_t boost_mode )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_RX_PATH_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_PATH_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_PATH_OC >> 0 ),
|
||||
( uint8_t ) rx_path,
|
||||
( uint8_t ) boost_mode,
|
||||
};
|
||||
|
||||
const lr20xx_status_t write_status =
|
||||
( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_RX_PATH_CMD_LENGTH, 0, 0 );
|
||||
|
||||
if( write_status != LR20XX_STATUS_OK )
|
||||
{
|
||||
return write_status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LR20XX_WORKAROUNDS_CONDITIONAL_APPLY_AUTOMATIC_DCDC_CONFIGURE( context );
|
||||
}
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_pa_cfg( const void* context, const lr20xx_radio_common_pa_cfg_t* pa_cfg )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_PA_CFG_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_PA_CFG_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_PA_CFG_OC >> 0 ),
|
||||
( uint8_t ) ( ( ( uint8_t ) pa_cfg->pa_sel << 7 ) + ( uint8_t ) pa_cfg->pa_lf_mode ),
|
||||
( uint8_t ) ( ( pa_cfg->pa_lf_duty_cycle << 4 ) + pa_cfg->pa_lf_slices ),
|
||||
pa_cfg->pa_hf_duty_cycle,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_PA_CFG_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx_params( const void* context, const int8_t power_half_dbm,
|
||||
const lr20xx_radio_common_ramp_time_t ramp_time )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_TX_PARAMS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TX_PARAMS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TX_PARAMS_OC >> 0 ),
|
||||
( uint8_t ) power_half_dbm,
|
||||
( uint8_t ) ramp_time,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_TX_PARAMS_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rssi_calibration(
|
||||
const void* context, const lr20xx_radio_common_rssi_calibration_gain_table_t* rssi_cal_table_lf,
|
||||
const lr20xx_radio_common_rssi_calibration_gain_table_t* rssi_cal_table_hf )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_RSSI_CALIBRATION_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RSSI_CALIBRATION_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RSSI_CALIBRATION_OC >> 0 ),
|
||||
( uint8_t ) ( ( ( rssi_cal_table_lf == NULL ) ? 0x00 : 0x01 ) | ( ( rssi_cal_table_hf == NULL ) ? 0x00 : 0x02 ) )
|
||||
};
|
||||
|
||||
uint8_t raw_rssi_table[LR20XX_RADIO_COMMON_RSSI_CALIBRATION_SINGLE_LENGTH * 2] = { 0 };
|
||||
uint8_t* raw_rssi_table_pointer = raw_rssi_table;
|
||||
uint16_t raw_rssi_table_length = 0;
|
||||
|
||||
if( rssi_cal_table_lf != NULL )
|
||||
{
|
||||
raw_rssi_table_pointer =
|
||||
lr20xx_radio_common_serialize_rssi_calibration_table( raw_rssi_table_pointer, rssi_cal_table_lf );
|
||||
raw_rssi_table_length =
|
||||
( uint16_t )( raw_rssi_table_length + LR20XX_RADIO_COMMON_RSSI_CALIBRATION_SINGLE_LENGTH );
|
||||
}
|
||||
if( rssi_cal_table_hf != NULL )
|
||||
{
|
||||
raw_rssi_table_pointer =
|
||||
lr20xx_radio_common_serialize_rssi_calibration_table( raw_rssi_table_pointer, rssi_cal_table_hf );
|
||||
raw_rssi_table_length =
|
||||
( uint16_t )( raw_rssi_table_length + LR20XX_RADIO_COMMON_RSSI_CALIBRATION_SINGLE_LENGTH );
|
||||
}
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_RSSI_CALIBRATION_CMD_LENGTH,
|
||||
raw_rssi_table, raw_rssi_table_length );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_tx_fallback_mode( const void* context,
|
||||
const lr20xx_radio_common_fallback_modes_t fallback_mode )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_RX_TX_FALLBACK_MODE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_TX_FALLBACK_MODE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_TX_FALLBACK_MODE_OC >> 0 ),
|
||||
( uint8_t ) fallback_mode,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer,
|
||||
LR20XX_RADIO_COMMON_SET_RX_TX_FALLBACK_MODE_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_pkt_type( const void* context, lr20xx_radio_common_pkt_type_t pkt_type )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_PKT_TYPE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_PKT_TYPE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_PKT_TYPE_OC >> 0 ),
|
||||
( uint8_t ) pkt_type,
|
||||
};
|
||||
|
||||
const lr20xx_status_t write_status =
|
||||
( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_PKT_TYPE_CMD_LENGTH, 0, 0 );
|
||||
|
||||
if( write_status != LR20XX_STATUS_OK )
|
||||
{
|
||||
return write_status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LR20XX_WORKAROUNDS_CONDITIONAL_APPLY_AUTOMATIC_DCDC_RESET( context );
|
||||
}
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_get_pkt_type( const void* context, lr20xx_radio_common_pkt_type_t* pkt_type )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_GET_PKT_TYPE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_PKT_TYPE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_PKT_TYPE_OC >> 0 ),
|
||||
};
|
||||
|
||||
uint8_t pkt_type_raw = 0;
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_RADIO_COMMON_GET_PKT_TYPE_CMD_LENGTH, &pkt_type_raw, 1 );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*pkt_type = ( lr20xx_radio_common_pkt_type_t ) pkt_type_raw;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_timeout_stop_event( const void* context,
|
||||
const bool is_stopped_on_preamble_detection )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_RX_TIMEOUT_STOP_EVENT_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_TIMEOUT_STOP_EVENT_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_TIMEOUT_STOP_EVENT_OC >> 0 ),
|
||||
( is_stopped_on_preamble_detection == true ) ? 0x01 : 0x00,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer,
|
||||
LR20XX_RADIO_COMMON_SET_RX_TIMEOUT_STOP_EVENT_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_reset_rx_stats( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_RESET_RX_STATS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_RESET_RX_STATS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_RESET_RX_STATS_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_RESET_RX_STATS_CMD_LENGTH, 0,
|
||||
0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_get_rssi_inst( const void* context, int16_t* rssi_in_dbm, uint8_t* half_dbm_count )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_GET_RSSI_INST_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_RSSI_INST_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_RSSI_INST_OC >> 0 ),
|
||||
};
|
||||
uint8_t rssi_raw[2] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_RADIO_COMMON_GET_RSSI_INST_CMD_LENGTH, rssi_raw, 2 );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*rssi_in_dbm = ( int16_t )( -( ( int16_t )( rssi_raw[0] ) ) );
|
||||
if( half_dbm_count != NULL )
|
||||
{
|
||||
*half_dbm_count = rssi_raw[1] & 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx( const void* context, const uint32_t timeout_in_ms )
|
||||
{
|
||||
return lr20xx_radio_common_set_rx_with_timeout_in_rtc_step(
|
||||
context, lr20xx_radio_common_convert_time_in_ms_to_rtc_step( timeout_in_ms ) );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_with_timeout_in_rtc_step( const void* context,
|
||||
const uint32_t timeout_in_rtc_step )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_RX_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_OC >> 8 ), ( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_OC >> 0 ),
|
||||
( uint8_t ) ( timeout_in_rtc_step >> 16 ), ( uint8_t ) ( timeout_in_rtc_step >> 8 ),
|
||||
( uint8_t ) ( timeout_in_rtc_step >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_RX_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_with_default_timeout( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_RX_WITH_DEFAULT_TIMEOUT_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer,
|
||||
LR20XX_RADIO_COMMON_SET_RX_WITH_DEFAULT_TIMEOUT_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx( const void* context, const uint32_t timeout_in_ms )
|
||||
{
|
||||
return lr20xx_radio_common_set_tx_with_timeout_in_rtc_step(
|
||||
context, lr20xx_radio_common_convert_time_in_ms_to_rtc_step( timeout_in_ms ) );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx_with_timeout_in_rtc_step( const void* context,
|
||||
const uint32_t timeout_in_rtc_step )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_TX_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TX_OC >> 8 ), ( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TX_OC >> 0 ),
|
||||
( uint8_t ) ( timeout_in_rtc_step >> 16 ), ( uint8_t ) ( timeout_in_rtc_step >> 8 ),
|
||||
( uint8_t ) ( timeout_in_rtc_step >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_TX_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx_with_default_timeout( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_TX_WITH_DEFAULT_TIMEOUT_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TX_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TX_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer,
|
||||
LR20XX_RADIO_COMMON_SET_TX_WITH_DEFAULT_TIMEOUT_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx_test_mode( const void* context, lr20xx_radio_common_tx_test_mode_t mode )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_TX_TEST_MODE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TX_TEST_MODE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TX_TEST_MODE_OC >> 0 ),
|
||||
( uint8_t ) mode,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_TX_TEST_MODE_CMD_LENGTH, 0,
|
||||
0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_select_pa( const void* context, lr20xx_radio_common_pa_selection_t sel )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SEL_PA_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SEL_PA_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SEL_PA_OC >> 0 ),
|
||||
( uint8_t ) sel,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SEL_PA_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_duty_cycle( const void* context, const uint32_t rx_period_in_ms,
|
||||
const uint32_t sleep_period_in_ms,
|
||||
const lr20xx_radio_common_rx_duty_cycle_mode_t mode )
|
||||
{
|
||||
return lr20xx_radio_common_set_rx_duty_cycle_with_timing_in_rtc_step(
|
||||
context, lr20xx_radio_common_convert_time_in_ms_to_rtc_step( rx_period_in_ms ),
|
||||
lr20xx_radio_common_convert_time_in_ms_to_rtc_step( sleep_period_in_ms ), mode );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_duty_cycle_with_timing_in_rtc_step(
|
||||
const void* context, const uint32_t rx_period_in_rtc_step, const uint32_t sleep_period_in_rtc_step,
|
||||
const lr20xx_radio_common_rx_duty_cycle_mode_t mode )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_RX_DUTY_CYCLE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_DUTY_CYCLE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_RX_DUTY_CYCLE_OC >> 0 ),
|
||||
( uint8_t ) ( rx_period_in_rtc_step >> 16 ),
|
||||
( uint8_t ) ( rx_period_in_rtc_step >> 8 ),
|
||||
( uint8_t ) ( rx_period_in_rtc_step >> 0 ),
|
||||
( uint8_t ) ( sleep_period_in_rtc_step >> 16 ),
|
||||
( uint8_t ) ( sleep_period_in_rtc_step >> 8 ),
|
||||
( uint8_t ) ( sleep_period_in_rtc_step >> 0 ),
|
||||
( uint8_t ) ( mode << 4 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_RX_DUTY_CYCLE_CMD_LENGTH, 0,
|
||||
0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_configure_auto_tx_rx(
|
||||
const void* context, const lr20xx_radio_common_auto_tx_rx_configuration_t* configuration )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_CONFIGURE_AUTO_TX_RX_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_COMMON_CONFIGURE_AUTO_TX_RX >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_COMMON_CONFIGURE_AUTO_TX_RX >> 0 ),
|
||||
( uint8_t )( ( ( uint8_t ) configuration->condition ) |
|
||||
( ( configuration->disable_on_failure == true ) ? 0x80 : 0x00 ) ),
|
||||
( uint8_t )( configuration->tx_rx_timeout_in_rtc_step >> 16 ),
|
||||
( uint8_t )( configuration->tx_rx_timeout_in_rtc_step >> 8 ),
|
||||
( uint8_t )( configuration->tx_rx_timeout_in_rtc_step >> 0 ),
|
||||
( uint8_t )( configuration->delay_in_tick >> 24 ),
|
||||
( uint8_t )( configuration->delay_in_tick >> 16 ),
|
||||
( uint8_t )( configuration->delay_in_tick >> 8 ),
|
||||
( uint8_t )( configuration->delay_in_tick >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_CONFIGURE_AUTO_TX_RX_CMD_LENGTH,
|
||||
0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_get_rx_packet_length( const void* context, uint16_t* pkt_len )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_GET_RX_PACKET_LENGTH_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_RX_PACKET_LENGTH_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_RX_PACKET_LENGTH_OC >> 0 ),
|
||||
};
|
||||
|
||||
uint8_t pkt_len_loc[2] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_RADIO_COMMON_GET_RX_PACKET_LENGTH_CMD_LENGTH, pkt_len_loc, 2 );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*pkt_len = ( uint16_t ) ( ( ( ( uint16_t ) pkt_len_loc[0] ) << 8 ) + ( uint16_t ) pkt_len_loc[1] );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_default_rx_tx_timeout( const void* context, uint32_t rx_timeout_in_ms,
|
||||
uint32_t tx_timeout_in_ms )
|
||||
{
|
||||
return lr20xx_radio_common_set_default_rx_tx_timeout_in_rtc_step(
|
||||
context, lr20xx_radio_common_convert_time_in_ms_to_rtc_step( rx_timeout_in_ms ),
|
||||
lr20xx_radio_common_convert_time_in_ms_to_rtc_step( tx_timeout_in_ms ) );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_default_rx_tx_timeout_in_rtc_step( const void* context,
|
||||
uint32_t rx_timeout_in_rtc_step,
|
||||
uint32_t tx_timeout_in_rtc_step )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_DEFAULT_RX_TX_TIMEOUT_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_DEFAULT_RX_TX_TIMEOUT_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_DEFAULT_RX_TX_TIMEOUT_OC >> 0 ),
|
||||
( uint8_t ) ( rx_timeout_in_rtc_step >> 16 ),
|
||||
( uint8_t ) ( rx_timeout_in_rtc_step >> 8 ),
|
||||
( uint8_t ) ( rx_timeout_in_rtc_step >> 0 ),
|
||||
( uint8_t ) ( tx_timeout_in_rtc_step >> 16 ),
|
||||
( uint8_t ) ( tx_timeout_in_rtc_step >> 8 ),
|
||||
( uint8_t ) ( tx_timeout_in_rtc_step >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer,
|
||||
LR20XX_RADIO_COMMON_SET_DEFAULT_RX_TX_TIMEOUT_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_timestamp_source( const void* context,
|
||||
lr20xx_radio_common_timestamp_cfg_slot_t cfg_slot,
|
||||
lr20xx_radio_common_timestamp_source_t source )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_TIMESTAMP_SOURCE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TIMESTAMP_SOURCE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_TIMESTAMP_SOURCE_OC >> 0 ),
|
||||
( uint8_t ) ( ( ( uint8_t ) cfg_slot << 4 ) + ( uint8_t ) source ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_TIMESTAMP_SOURCE_CMD_LENGTH,
|
||||
0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_get_elapsed_time_in_tick( const void* context,
|
||||
lr20xx_radio_common_timestamp_cfg_slot_t cfg_slot,
|
||||
uint32_t* elapsed_time_in_tick )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_GET_TIMESTAMP_VALUE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_TIMESTAMP_VALUE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_TIMESTAMP_VALUE_OC >> 0 ),
|
||||
( uint8_t ) cfg_slot,
|
||||
};
|
||||
|
||||
uint8_t elapsed_time_raw[4] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_RADIO_COMMON_GET_TIMESTAMP_VALUE_CMD_LENGTH, elapsed_time_raw, 4 );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*elapsed_time_in_tick = ( ( uint32_t ) elapsed_time_raw[0] << 24 ) +
|
||||
( ( uint32_t ) elapsed_time_raw[1] << 16 ) + ( ( uint32_t ) elapsed_time_raw[2] << 8 ) +
|
||||
( ( uint32_t ) elapsed_time_raw[3] << 0 );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_cca( const void* context, const uint32_t duration )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_CCA_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_CCA_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_CCA_OC >> 0 ),
|
||||
( uint8_t ) ( duration >> 16 ),
|
||||
( uint8_t ) ( duration >> 8 ),
|
||||
( uint8_t ) ( duration >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_CCA_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_get_cca_result( const void* context, lr20xx_radio_common_cca_res_t* cca_res )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_GET_CCA_RESULT_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_CCA_RESULT_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_GET_CCA_RESULT_OC >> 0 ),
|
||||
};
|
||||
|
||||
uint8_t cca_res_raw[4] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_RADIO_COMMON_GET_RX_PACKET_LENGTH_CMD_LENGTH, cca_res_raw, 4 );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
cca_res->min = ( int16_t )( -( ( int16_t ) cca_res_raw[0] ) );
|
||||
cca_res->max = ( int16_t )( -( ( int16_t ) cca_res_raw[1] ) );
|
||||
cca_res->avg = ( int16_t )( -( ( int16_t ) cca_res_raw[2] ) );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_agc_gain( const void* context, lr20xx_radio_common_gain_step_t gain )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_AGC_GAIN_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_AGC_GAIN_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_AGC_GAIN_OC >> 0 ),
|
||||
( uint8_t ) gain,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_AGC_GAIN_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_cad_params( const void* context,
|
||||
const lr20xx_radio_common_cad_params_t* params )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_CAD_PARAMS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_CAD_PARAMETERS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_CAD_PARAMETERS_OC >> 0 ),
|
||||
( uint8_t ) ( params->timeout >> 16 ),
|
||||
( uint8_t ) ( params->timeout >> 8 ),
|
||||
( uint8_t ) ( params->timeout >> 0 ),
|
||||
params->threshold,
|
||||
( uint8_t ) params->exit_mode,
|
||||
( uint8_t ) ( params->tx_rx_timeout >> 16 ),
|
||||
( uint8_t ) ( params->tx_rx_timeout >> 8 ),
|
||||
( uint8_t ) ( params->tx_rx_timeout >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_CAD_PARAMS_CMD_LENGTH, 0,
|
||||
0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_set_cad( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_COMMON_SET_CAD_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_CAD_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_COMMON_SET_CAD_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_COMMON_SET_CAD_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_common_get_lqi( const void* context, lr20xx_radio_common_lqi_value_t* lqi )
|
||||
{
|
||||
uint32_t raw_register_value = 0;
|
||||
const lr20xx_status_t read_register_status =
|
||||
lr20xx_regmem_read_regmem32( context, LR20XX_RADIO_COMMON_REGISTER_LQI, &raw_register_value, 1 );
|
||||
if( read_register_status == LR20XX_STATUS_OK )
|
||||
{
|
||||
// The LQI is on the 8 LSBits of the register value
|
||||
const uint8_t raw_lqi_value = ( uint8_t ) raw_register_value;
|
||||
|
||||
// The raw LQI is given as counter of 1/4 dB. So divide by 4 to get the integer part, and the 2 LSBits give the
|
||||
// number of 1/4 counts
|
||||
lqi->lqi_db = ( raw_lqi_value / 4 );
|
||||
lqi->lqi_quarter_db_counter = ( raw_lqi_value & 0x03 );
|
||||
}
|
||||
return read_register_status;
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DEFINITION --------------------------------------------
|
||||
*/
|
||||
|
||||
uint8_t* lr20xx_radio_common_serialize_rssi_calibration_item(
|
||||
uint8_t* array, const lr20xx_radio_common_rssi_calibration_gain_item_t* rssi_calibration_item )
|
||||
{
|
||||
array[0] = ( uint8_t ) ( rssi_calibration_item->gain_value >> 8 );
|
||||
array[1] = ( uint8_t ) rssi_calibration_item->gain_value;
|
||||
array[2] = rssi_calibration_item->noise_figure;
|
||||
return array + 3;
|
||||
}
|
||||
|
||||
uint8_t* lr20xx_radio_common_serialize_rssi_calibration_table(
|
||||
uint8_t* array, const lr20xx_radio_common_rssi_calibration_gain_table_t* rssi_calibration_table )
|
||||
{
|
||||
if( rssi_calibration_table != NULL )
|
||||
{
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g1 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g2 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g3 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g4 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g5 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g6 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g7 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g8 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g9 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g10 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g11 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g12_boost0 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g12_boost1 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g12_boost2 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g12_boost3 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g12_boost4 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g12_boost5 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g12_boost6 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g12_boost7 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g13_boost0 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g13_boost1 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g13_boost2 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g13_boost3 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g13_boost4 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g13_boost5 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g13_boost6 );
|
||||
array = lr20xx_radio_common_serialize_rssi_calibration_item( array, &rssi_calibration_table->g13_boost7 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do nothing on purpose
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,655 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_common.h
|
||||
*
|
||||
* @brief Radio common driver definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_RADIO_COMMON_H
|
||||
#define LR20XX_RADIO_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "lr20xx_status.h"
|
||||
#include "lr20xx_radio_common_types.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Executes front end calibration procedure on given raw frequencies and Rx path
|
||||
*
|
||||
* The front end calibration calibrates:
|
||||
* - the ADC offset
|
||||
* - the poly-phase filter
|
||||
* - the image
|
||||
* This function can be called only if the chip is neither in Rx nor Tx states.
|
||||
*
|
||||
* Upon completion, the chip will return to the same mode it was before calling this command.
|
||||
* Potential calibration issues can be read out with lr20xx_system_get_errors command.
|
||||
*
|
||||
* Up to three calibration configuration values can be given.
|
||||
* Only the provided and non-zero frequencies are calibrated.
|
||||
*
|
||||
* It is advised to configure calibration so that RF frequencies used during RF operations are at most 50MHz away from
|
||||
* a calibrated RF frequency.
|
||||
*
|
||||
* If no calibration configuration is given, then one front end calibration is executed on the next 4MHz multiple of the
|
||||
* currently configured RF frequency.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] front_end_calibration_values Array of front end calibration configuration. It is up to the caller to
|
||||
* ensure that it has at least n_rx_path_frequency elements.
|
||||
* @param [in] n_front_end_calibration_values Number of front end calibration values to consider. Valid values are [0:3]
|
||||
* included.
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_get_errors, lr20xx_radio_common_calibrate_front_end_helper
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_calibrate_front_end(
|
||||
const void* context, const lr20xx_radio_common_raw_front_end_calibration_value_t* front_end_calibration_values,
|
||||
uint8_t n_front_end_calibration_values );
|
||||
|
||||
/*!
|
||||
* @brief Helper function to execute front end calibration procedure
|
||||
*
|
||||
* This function really is a helper function that converts the front end calibration structures in argument to the
|
||||
* corresponding raw values, and calls @ref lr20xx_radio_common_calibrate_front_end.
|
||||
* For each given front end calibration frequency, the actual calibration frequency used is the next frequency multiple
|
||||
* of 4MHz following the given frequency.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] front_end_calibration_structures Array of front end calibration configuration structures. It is up to the
|
||||
* user that it contains at least n_rx_path_frequency items.
|
||||
* @param [in] n_front_end_calibration_structures Number of front end calibration structures to consider. Valid values
|
||||
* are [0:3] included.
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_radio_common_calibrate_front_end
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_calibrate_front_end_helper(
|
||||
const void* context, const lr20xx_radio_common_front_end_calibration_value_t* front_end_calibration_structures,
|
||||
uint8_t n_front_end_calibration_structures );
|
||||
|
||||
/**
|
||||
* @brief Helper function that computes the number of RTC steps from a given time in millisecond
|
||||
*
|
||||
* @param [in] time_in_ms Time in millisecond
|
||||
*
|
||||
* @returns Number of RTC steps
|
||||
*/
|
||||
uint32_t lr20xx_radio_common_convert_time_in_ms_to_rtc_step( uint32_t time_in_ms );
|
||||
|
||||
/*!
|
||||
* @brief Set the RF frequency to be used
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] freq_in_hz RF frequency in Hertz
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rf_freq( const void* context, uint32_t freq_in_hz );
|
||||
|
||||
/*!
|
||||
* @brief Select the Rx path and set the boost mode
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] rx_path Rx path to be used
|
||||
* @param [in] boost_mode Boost mode applied to selected Rx path
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_path( const void* context, lr20xx_radio_common_rx_path_t rx_path,
|
||||
lr20xx_radio_common_rx_path_boost_mode_t boost_mode );
|
||||
|
||||
/*!
|
||||
* @brief Set the Power Amplifier configuration
|
||||
*
|
||||
* It must be called prior using @ref lr20xx_radio_common_set_tx_params.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] pa_cfg The structure for PA configuration
|
||||
*
|
||||
* @see lr20xx_radio_common_set_tx_params
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_pa_cfg( const void* context, const lr20xx_radio_common_pa_cfg_t* pa_cfg );
|
||||
|
||||
/*!
|
||||
* @brief Set the parameters for TX power and power amplifier ramp time
|
||||
*
|
||||
* @ref lr20xx_radio_common_set_pa_cfg must be called prior calling lr20xx_radio_common_set_tx_params.
|
||||
*
|
||||
* The range of possible TX output power values depends on PA selected with @ref
|
||||
* lr20xx_radio_common_set_pa_cfg :
|
||||
* - for @ref LR20XX_RADIO_COMMON_PA_SEL_LF : power value goes from -9.5dBm to +22dBm
|
||||
* (ie. @p power_half_dbm from 0xED to 0x2C)
|
||||
* - for @ref LR20XX_RADIO_COMMON_PA_SEL_HF : power value goes from -19.5dBm to +12dBm
|
||||
* (ie. @p power_half_dbm from 0xD9 to 0x18)
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] power_half_dbm TX output power raw value, as 0.5dBm steps (so twice the value in dBm)
|
||||
* @param [in] ramp_time Ramping time configuration
|
||||
*
|
||||
* @see lr20xx_radio_common_set_pa_cfg
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx_params( const void* context, const int8_t power_half_dbm,
|
||||
const lr20xx_radio_common_ramp_time_t ramp_time );
|
||||
|
||||
/*!
|
||||
* @brief Set RSSI calibration table(s)
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] rssi_cal_table_lf Pointer to RSSI calibration table for low frequency path. Can be NULL, in which case
|
||||
* this path is not configured
|
||||
* @param [in] rssi_cal_table_hf Pointer to RSSI calibration table for high frequency path. Can be NULL, in which case
|
||||
* this path is not configured
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rssi_calibration(
|
||||
const void* context, const lr20xx_radio_common_rssi_calibration_gain_table_t* rssi_cal_table_lf,
|
||||
const lr20xx_radio_common_rssi_calibration_gain_table_t* rssi_cal_table_hf );
|
||||
|
||||
/*!
|
||||
* @brief Configure the chip mode shall be in after transmission or reception operation
|
||||
*
|
||||
* @remark The configured fallback mode is applied as soon as the chip leaves Tx / Rx mode:
|
||||
* - after a successful transmission
|
||||
* - after a successful reception if not set in continuous mode
|
||||
* - after a successful reception in duty cycle mode
|
||||
* - after a CAD operation (depending on configured exit mode)
|
||||
* - when a timeout occurs
|
||||
* - during automatic Tx/Rx (see @ref lr20xx_radio_common_configure_auto_tx_rx), both after the first Rx/Tx and the
|
||||
* second Tx/Rx
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] fallback_mode Chip mode to enter after transmission or reception operation
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_tx_fallback_mode( const void* context,
|
||||
const lr20xx_radio_common_fallback_modes_t fallback_mode );
|
||||
|
||||
/*!
|
||||
* @brief Set the packet type to be used
|
||||
*
|
||||
* @remark This command has to be sent prior to any modulation related configuration command
|
||||
*
|
||||
* @note This function automatically applies the workaround @ref lr20xx_workarounds_dcdc_reset unless the macro @p
|
||||
* LR20XX_WORKAROUNDS_DISABLE_AUTOMATIC_DCDC_RESET is defined at compile time.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] pkt_type Packet type to be configured
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_pkt_type( const void* context, lr20xx_radio_common_pkt_type_t pkt_type );
|
||||
|
||||
/*!
|
||||
* @brief Get the packet type currently in use
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] pkt_type Packet type currently in use
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_get_pkt_type( const void* context, lr20xx_radio_common_pkt_type_t* pkt_type );
|
||||
|
||||
/*!
|
||||
* @brief Set the event on which the Rx timeout is stopped
|
||||
*
|
||||
* Depending on the configuration, Rx timeout is stopped either on the detection of the following events:
|
||||
* - LoRa header detection (or Rx done in implicit mode) / GFSK syncword detection
|
||||
* - Preamble detection
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] is_stopped_on_preamble_detection If true, the timer stops on preamble detection
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_timeout_stop_event( const void* context,
|
||||
const bool is_stopped_on_preamble_detection );
|
||||
|
||||
/*!
|
||||
* @brief Reset internal Rx stats
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_reset_rx_stats( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Get the instantaneous RSSI while the transceiver is in reception mode
|
||||
*
|
||||
* This command can be used during reception of a packet
|
||||
*
|
||||
* The instantaneous RSSI can be obtained with 0.5 dBm accuracy thanks to the output argument half_dbm_count, which is
|
||||
* either 0 or 1, using the following formula:
|
||||
*
|
||||
* RSSI = rssi_in_dbm - ( half_dbm_count * 0.5 )
|
||||
*
|
||||
* The pointer half_dbm_count can be NULL, in which case the value is not returned.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] rssi_in_dbm Instantaneous RSSI.
|
||||
* @param [out] half_dbm_count Count of 0.5 dBm to subtract to value in dBm. Can be NULL.
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_get_rssi_inst( const void* context, int16_t* rssi_in_dbm, uint8_t* half_dbm_count );
|
||||
|
||||
/*!
|
||||
* @brief Start RX operations with a timeout in millisecond
|
||||
*
|
||||
* @remark To set the radio in Rx continuous mode, refer to @ref lr20xx_radio_common_set_rx_with_timeout_in_rtc_step
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] timeout_in_ms Timeout configuration in millisecond for RX operation
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx( const void* context, const uint32_t timeout_in_ms );
|
||||
|
||||
/*!
|
||||
* @brief Start RX operations with a timeout in RTC step
|
||||
*
|
||||
* The timeout duration is obtained by:
|
||||
* \f$ timeout\_duration\_ms = timeout\_in\_rtc\_step \times \frac{1}{32.768} \f$
|
||||
*
|
||||
* Maximal timeout value is 0xFFFFFE, which gives a maximal timeout of 511 seconds.
|
||||
*
|
||||
* The timeout argument can also have the following special values:
|
||||
* <table>
|
||||
* <tr><th> Special values </th><th> Meaning </th>
|
||||
* <tr><td> 0x000000 </td><td> RX single - transceiver stays in RX mode until a packet is received </td>
|
||||
* <tr><td> 0xFFFFFF </td><td> RX continuous - transceiver stays in RX mode even after reception of a packet </td>
|
||||
* </table>
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] timeout_in_rtc_step Timeout configuration in RTC step for RX operation
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_with_timeout_in_rtc_step( const void* context,
|
||||
const uint32_t timeout_in_rtc_step );
|
||||
|
||||
/*!
|
||||
* @brief Start RX operations with a pre-configured default timeout
|
||||
*
|
||||
* @remark The timeout has to be configured by calling either @ref lr20xx_radio_common_set_default_rx_tx_timeout or @ref
|
||||
* lr20xx_radio_common_set_default_rx_tx_timeout_in_rtc_step
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_with_default_timeout( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Start transmission operation with a timeout in millisecond
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] timeout_in_ms Timeout configuration in millisecond for RX operation
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx( const void* context, const uint32_t timeout_in_ms );
|
||||
|
||||
/*!
|
||||
* @brief Start transmission operation with a timeout in RTC step
|
||||
*
|
||||
* The timeout duration is obtained by:
|
||||
* \f$ timeout\_duration\_ms = timeout_in_rtc_step \times \frac{1}{32.768} \f$
|
||||
*
|
||||
* Maximal timeout value is 0xFFFFFF, which gives a maximal timeout of 511 seconds.
|
||||
*
|
||||
* If \p timeout_in_rtc_step is set to 0, then no timeout is used.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] timeout_in_rtc_step Timeout configuration in RTC step for TX operation
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx_with_timeout_in_rtc_step( const void* context,
|
||||
const uint32_t timeout_in_rtc_step );
|
||||
|
||||
/*!
|
||||
* @brief Start TX operations with a pre-configured default timeout
|
||||
*
|
||||
* @remark The timeout has to be configured by calling either @ref lr20xx_radio_common_set_default_rx_tx_timeout or @ref
|
||||
* lr20xx_radio_common_set_default_rx_tx_timeout_in_rtc_step
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx_with_default_timeout( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Set the transceiver into a Tx test mode.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] mode Test mode
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_tx_test_mode( const void* context, lr20xx_radio_common_tx_test_mode_t mode );
|
||||
|
||||
/*!
|
||||
* @brief Select the Power Amplifier to use
|
||||
*
|
||||
* @remark Configuration has to be applied first by calling @ref lr20xx_radio_common_set_pa_cfg
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] sel Power amplifier selection
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_select_pa( const void* context, lr20xx_radio_common_pa_selection_t sel );
|
||||
|
||||
/*!
|
||||
* @brief Configure and start a Rx Duty Cycle operation with timings in millisecond
|
||||
*
|
||||
* @remark This function computes timings in RTC step from values given in millisecond and then calls @ref
|
||||
* lr20xx_radio_common_set_rx_duty_cycle_with_timing_in_rtc_step
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] rx_period_in_ms Rx period in millisecond
|
||||
* @param [in] sleep_period_in_ms Sleep period in millisecond
|
||||
* @param [in] mode Operation mode used during Rx phase
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_duty_cycle( const void* context, const uint32_t rx_period_in_ms,
|
||||
const uint32_t sleep_period_in_ms,
|
||||
const lr20xx_radio_common_rx_duty_cycle_mode_t mode );
|
||||
|
||||
/*!
|
||||
* @brief Configure and start a Rx Duty Cycle operation with timings in RTC step
|
||||
*
|
||||
* It executes the following steps:
|
||||
* 1. Reception - enters reception state for duration defined by @p rx_period_in_rtc_step:
|
||||
* - @p mode = LR20XX_RADIO_COMMON_RX_DUTY_CYCLE_MODE_RX: regular Rx mode
|
||||
* - @p mode = LR20XX_RADIO_COMMON_RX_DUTY_CYCLE_MODE_CAD (LoRa only) : CAD mode
|
||||
* 2. Depending on the over-the-air activity detection (either preamble detection or valid CAD):
|
||||
* - In case of positive over-the-air detection, the Rx period timeout is restarted with the value
|
||||
* \f$2 \times rx_period_in_rtc_step + sleep_period_in_rtc_step\f$
|
||||
* - else, the transceiver goes into sleep mode with retention for a duration defined by @p
|
||||
* sleep_period_in_rtc_step
|
||||
* 3. On wake-up, the transceiver restarts the process to step 1
|
||||
*
|
||||
* The loop described above is terminated in the following cases:
|
||||
* - a packet is received during a Rx window - the chip goes back to fallback mode configured with @ref
|
||||
* lr20xx_radio_common_set_rx_tx_fallback_mode
|
||||
* - a call to @ref lr20xx_system_set_standby_mode is done during a Rx window
|
||||
* - a call to @ref lr20xx_system_wakeup is done during a sleep phase - to prevent a possible race condition from
|
||||
* happening when the call is performed during the boot phase, it is recommended to call @ref
|
||||
* lr20xx_system_set_standby_mode when BUSY is going low
|
||||
*
|
||||
* @remark If @p mode is set to @ref LR20XX_RADIO_COMMON_RX_DUTY_CYCLE_MODE_CAD, CAD parameters have to be defined
|
||||
* before calling this function
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] rx_period_in_rtc_step Rx period in RTC step
|
||||
* @param [in] sleep_period_in_rtc_step Sleep period in RTC step
|
||||
* @param [in] mode Operation mode used during Rx phase
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_rx_duty_cycle_with_timing_in_rtc_step(
|
||||
const void* context, const uint32_t rx_period_in_rtc_step, const uint32_t sleep_period_in_rtc_step,
|
||||
const lr20xx_radio_common_rx_duty_cycle_mode_t mode );
|
||||
|
||||
/**
|
||||
* @brief Configure the automatic Tx operation after Rx, or automatic Rx operation after Tx
|
||||
*
|
||||
* This feature allows the chip to automatically execute a Tx operation after an Rx one; or to automatically execute an
|
||||
* Rx operation after a Tx one.
|
||||
*
|
||||
* The order of operation depends on the mode manually requested after issuing this command:
|
||||
* - If the radio is set to Tx mode, then an automatic Rx will be executed;
|
||||
* - If the radio is set to Rx mode, then an automatic Tx will be executed.
|
||||
*
|
||||
* This feature is similar to a call to @ref lr20xx_radio_common_set_tx_with_timeout_in_rtc_step (or @ref
|
||||
* lr20xx_radio_common_set_rx_with_timeout_in_rtc_step) after the given delay_in_tick. Therefore to fine tune the
|
||||
* instant of first bit automatically sent over-the-air (or reception window opening) other delays have to be taken into
|
||||
* account when determining the delay_in_tick value. For instance, but not limited to:
|
||||
* - PA ramp-up
|
||||
* - TCXO start time (if applicable)
|
||||
* - Configured fallback mode
|
||||
* - Radio state switching time
|
||||
*
|
||||
* When the automatic Tx/Rx is enabled, the chip is in the state configured by @ref
|
||||
* lr20xx_radio_common_set_rx_tx_fallback_mode between the end of Rx (or Tx) operation and the start of the next
|
||||
* automatic Tx (or Rx) operation.
|
||||
*
|
||||
* Calling @ref lr20xx_radio_common_configure_auto_tx_rx with condition being @ref LR20XX_RADIO_COMMON_AUTO_TX_RX_OFF
|
||||
* disables the automatic Tx or Rx behavior. Doing so after end of Rx (or Tx) operation and start of automatic Tx (or
|
||||
* Rx) also cancels the automatic Tx or Rx operation.
|
||||
*
|
||||
* Once the automatic operation triggers, the feature is automatically disabled. So that to engage again an automatic
|
||||
* operation after a manual one, the @ref lr20xx_radio_common_configure_auto_tx_rx must be called to enable it again.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param configuration The configuration of the automatic Tx/Rx
|
||||
*
|
||||
* @see lr20xx_radio_common_set_tx_with_timeout_in_rtc_step, lr20xx_radio_common_set_rx_with_timeout_in_rtc_step,
|
||||
* lr20xx_radio_common_set_rx_tx_fallback_mode
|
||||
*
|
||||
* @return lr20xx_status_t
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_configure_auto_tx_rx(
|
||||
const void* context, const lr20xx_radio_common_auto_tx_rx_configuration_t* configuration );
|
||||
|
||||
/*!
|
||||
* @brief Get the length in byte of the last received packet
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] pkt_len Length in byte of the last received packet
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_get_rx_packet_length( const void* context, uint16_t* pkt_len );
|
||||
|
||||
/*!
|
||||
* @brief Set default timeout values for RX and TX operations
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] rx_timeout_in_ms Timeout configuration in millisecond for RX operation
|
||||
* @param [in] tx_timeout_in_ms Timeout configuration in millisecond for TX operation
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_default_rx_tx_timeout( const void* context, uint32_t rx_timeout_in_ms,
|
||||
uint32_t tx_timeout_in_ms );
|
||||
|
||||
/*!
|
||||
* @brief Set default timeout values for RX and TX operations
|
||||
*
|
||||
* @remark Special values defined for @ref lr20xx_radio_common_set_rx_with_timeout_in_rtc_step and @ref
|
||||
* lr20xx_radio_common_set_tx_with_timeout_in_rtc_step are also applicable here
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] rx_timeout_in_rtc_step Timeout configuration in RTC step for RX operation
|
||||
* @param [in] tx_timeout_in_rtc_step Timeout configuration in RTC step for TX operation
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_default_rx_tx_timeout_in_rtc_step( const void* context,
|
||||
uint32_t rx_timeout_in_rtc_step,
|
||||
uint32_t tx_timeout_in_rtc_step );
|
||||
|
||||
/*!
|
||||
* @brief Set a timestamp source for a given configuration slot
|
||||
*
|
||||
* @remark This command configure a source linked to a radio event that will then be used by @ref
|
||||
* lr20xx_radio_common_get_elapsed_time_in_tick to compute the elapsed time
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] cfg_slot Configuration slot
|
||||
* @param [in] source Timestamp source
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_timestamp_source( const void* context,
|
||||
lr20xx_radio_common_timestamp_cfg_slot_t cfg_slot,
|
||||
lr20xx_radio_common_timestamp_source_t source );
|
||||
|
||||
/*!
|
||||
* @brief Get the elapsed time since radio event registered at given configuration slot
|
||||
*
|
||||
* @remark This is the time elapsed between the event configured with @ref lr20xx_radio_common_set_timestamp_source and
|
||||
* the NSS falling edge of this request
|
||||
*
|
||||
* @remark That radio must not be put in sleep mode between the configured event and the call to this function
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] cfg_slot Configuration slot
|
||||
* @param [out] elapsed_time_in_tick Elapsed time in 32MHz tick
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_get_elapsed_time_in_tick( const void* context,
|
||||
lr20xx_radio_common_timestamp_cfg_slot_t cfg_slot,
|
||||
uint32_t* elapsed_time_in_tick );
|
||||
|
||||
/*!
|
||||
* @brief Launch a CCA (Clear Channel Assessment) operation
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] duration CCA duration in 32MHz step
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_cca( const void* context, const uint32_t duration );
|
||||
|
||||
/*!
|
||||
* @brief Get the CCA values once the operation is over
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] cca_res Structure holding CCA result
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_get_cca_result( const void* context, lr20xx_radio_common_cca_res_t* cca_res );
|
||||
|
||||
/*!
|
||||
* @brief Set the gain to be used by the AGC (Automatic Gain Control)
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] gain Gain
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_agc_gain( const void* context, lr20xx_radio_common_gain_step_t gain );
|
||||
|
||||
/*!
|
||||
* @brief Set non-LoRa CAD parameters
|
||||
*
|
||||
* @remark This command is not applicable if the packet type is set to LoRa
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] params CAD parameters
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_cad_params( const void* context,
|
||||
const lr20xx_radio_common_cad_params_t* params );
|
||||
|
||||
/*!
|
||||
* @brief Set the chip in non-LoRa CAD mode
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_set_cad( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Get the Link Quality Indicator (LQI) of latest detected packet
|
||||
*
|
||||
* This function is only valid if the latest received packet is an FSK based modulation:
|
||||
* - FSK
|
||||
* - Bluetooth_LE
|
||||
* - OQPSK 15.4
|
||||
* - Wi-SUN
|
||||
* - Wireless M-Bus
|
||||
* - Z-Wave
|
||||
*
|
||||
* The value returned corresponds to the latest detected packet. It is valid from the packet detection (corresponding to
|
||||
* @ref LR20XX_SYSTEM_IRQ_PREAMBLE_DETECTED raised if enabled) until next Rx attempt (through call to @ref
|
||||
* lr20xx_radio_common_set_rx or @ref lr20xx_radio_common_set_rx_with_timeout_in_rtc_step for instance).
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[out] lqi The LQI value
|
||||
* @return lr20xx_status_t Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_common_get_lqi( const void* context, lr20xx_radio_common_lqi_value_t* lqi );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_RADIO_COMMON_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,404 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_common_types.h
|
||||
*
|
||||
* @brief Radio common driver types for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_RADIO_COMMON_TYPES_H
|
||||
#define LR20XX_RADIO_COMMON_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Rx path values
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_RX_PATH_LF = 0x00, //!< Low-frequency Rx path
|
||||
LR20XX_RADIO_COMMON_RX_PATH_HF = 0x01, //!< High-frequency Rx path
|
||||
} lr20xx_radio_common_rx_path_t;
|
||||
|
||||
/**
|
||||
* @brief Raw front end calibration value
|
||||
*
|
||||
* MSBit is the Rx path selection:
|
||||
* - 0: LF path
|
||||
* - 1: HF path
|
||||
*
|
||||
* The remaining 15 LSbits are the frequency expressed as 4MHz steps.
|
||||
*
|
||||
* For instance:
|
||||
* - 0x80E1 means 900MHz on HF path
|
||||
* - 0x00E1 means 900MHz on LF path
|
||||
*
|
||||
*/
|
||||
typedef uint16_t lr20xx_radio_common_raw_front_end_calibration_value_t;
|
||||
|
||||
/**
|
||||
* @brief Helper structure for front end calibration value
|
||||
*
|
||||
* @see lr20xx_radio_common_raw_front_end_calibration_value_t
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
lr20xx_radio_common_rx_path_t rx_path; //!< The RX path to calibrate
|
||||
uint32_t frequency_in_hertz; //!< The frequency to calibrate
|
||||
} lr20xx_radio_common_front_end_calibration_value_t;
|
||||
|
||||
/*!
|
||||
* @brief Rx path boost configuration values
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_NONE = 0x00, //!< Boost deactivated
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_1 = 0x01, //!< Boost mode 1
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_2 = 0x02, //!< Boost mode 2
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_3 = 0x03, //!< Boost mode 3
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_4 = 0x04, //!< Boost mode 4
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_5 = 0x05, //!< Boost mode 5
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_6 = 0x06, //!< Boost mode 6
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_7 = 0x07, //!< Boost mode 7
|
||||
} lr20xx_radio_common_rx_path_boost_mode_t;
|
||||
|
||||
/*!
|
||||
* @brief Power Amplifier Selection values
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_PA_SEL_LF = 0x00, //!< Low-frequency Power Amplifier
|
||||
LR20XX_RADIO_COMMON_PA_SEL_HF = 0x01, //!< High-frequency Power Amplifier
|
||||
} lr20xx_radio_common_pa_selection_t;
|
||||
|
||||
/*!
|
||||
* @brief Power Amplifier Low-Frequency mode
|
||||
*/
|
||||
typedef enum lr20xx_radio_common_pa_lf_mode_e
|
||||
{
|
||||
LR20XX_RADIO_COMMON_PA_LF_MODE_FSM = 0x00, //!< Full Single-ended Mode
|
||||
} lr20xx_radio_common_pa_lf_mode_t;
|
||||
|
||||
/*!
|
||||
* @brief Ramping time for PA
|
||||
*
|
||||
* This parameter is the ramping time of the PA. A high value improves spectral quality.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_RAMP_2_US = 0x00, //!< 2 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_4_US = 0x01, //!< 4 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_8_US = 0x02, //!< 8 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_16_US = 0x03, //!< 16 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_32_US = 0x04, //!< 32 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_48_US = 0x05, //!< 48 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_64_US = 0x06, //!< 64 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_80_US = 0x07, //!< 80 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_96_US = 0x08, //!< 96 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_112_US = 0x09, //!< 112 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_128_US = 0x0A, //!< 128 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_144_US = 0x0B, //!< 144 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_160_US = 0x0C, //!< 160 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_176_US = 0x0D, //!< 176 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_192_US = 0x0E, //!< 192 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_208_US = 0x0F, //!< 208 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_240_US = 0x10, //!< 240 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_272_US = 0x11, //!< 272 us Ramp Time
|
||||
LR20XX_RADIO_COMMON_RAMP_304_US = 0x12, //!< 304 us Ramp Time
|
||||
} lr20xx_radio_common_ramp_time_t;
|
||||
|
||||
/*!
|
||||
* @brief Chip mode after leaving transmission or reception mode
|
||||
*/
|
||||
typedef enum lr20xx_radio_common_fallback_modes_e
|
||||
{
|
||||
LR20XX_RADIO_FALLBACK_STDBY_RC = 0x01, //!< Standby RC (Default)
|
||||
LR20XX_RADIO_FALLBACK_STDBY_XOSC = 0x02, //!< Standby XOSC
|
||||
LR20XX_RADIO_FALLBACK_FS = 0x03 //!< FS
|
||||
} lr20xx_radio_common_fallback_modes_t;
|
||||
|
||||
/*!
|
||||
* @brief Packet type values
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_LORA = 0x00, //!< LoRa packet engine (default)
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_FSK = 0x02, //!< FSK packet engine - configuration compatible with
|
||||
//!< existing transceivers (SX127x / SX126x / SX128x / LR11xx)
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_BLUETOOTH_LE = 0x03, //!< Bluetooth_LE packet engine
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_RTTOF = 0x04, //!< RTToF packet engine
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_FLRC = 0x05, //!< FLRC packet engine
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_BPSK = 0x06, //!< BPSK packet engine
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_LRFHSS = 0x07, //!< LR-FHSS packet engine
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_WM_BUS = 0x08, //!< Wireless M-Bus packet engine
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_WI_SUN = 0x09, //!< Wi-SUN packet engine
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_OOK = 0x0A, //!< OOK packet engine
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_Z_WAVE = 0x0C, //!< Z-Wave packet engine
|
||||
LR20XX_RADIO_COMMON_PKT_TYPE_OQPSK_15_4 = 0x0D, //!< OQPSK 15.4 packet engine
|
||||
} lr20xx_radio_common_pkt_type_t;
|
||||
|
||||
/*!
|
||||
* @brief RX Duty Cycle Modes
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_RX_DUTY_CYCLE_MODE_RX = 0x00, //!< LoRa/GFSK: Uses Rx for listening to packets
|
||||
LR20XX_RADIO_COMMON_RX_DUTY_CYCLE_MODE_CAD = 0x01, //!< LoRa only: Uses CAD to listen for over-the-air activity
|
||||
} lr20xx_radio_common_rx_duty_cycle_mode_t;
|
||||
|
||||
/*!
|
||||
* @brief Timestamp configuration slot
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_TIMESTAMP_CFG_SLOT_0 = 0x00, //!< Timestamp source configuration slot 0
|
||||
LR20XX_RADIO_COMMON_TIMESTAMP_CFG_SLOT_1 = 0x01, //!< Timestamp source configuration slot 1
|
||||
LR20XX_RADIO_COMMON_TIMESTAMP_CFG_SLOT_2 = 0x02, //!< Timestamp source configuration slot 2
|
||||
} lr20xx_radio_common_timestamp_cfg_slot_t;
|
||||
|
||||
/*!
|
||||
* @brief Timestamp source
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_TIMESTAMP_SOURCE_NONE = 0x00, //!< Timestamp deactivated
|
||||
LR20XX_RADIO_COMMON_TIMESTAMP_SOURCE_TX_DONE = 0x01, //!< Timestamp triggered on last payload bit/symbol sent
|
||||
LR20XX_RADIO_COMMON_TIMESTAMP_SOURCE_RX_DONE = 0x02, //!< Timestamp triggered on last payload bit/symbol received
|
||||
LR20XX_RADIO_COMMON_TIMESTAMP_SOURCE_SYNC = 0x03, //!< Timestamp triggered on last syncword bit/symbol received
|
||||
LR20XX_RADIO_COMMON_TIMESTAMP_SOURCE_HEADER =
|
||||
0x04, //!< Timestamp triggered on last header bit/symbol received (LoRa only)
|
||||
} lr20xx_radio_common_timestamp_source_t;
|
||||
|
||||
/*!
|
||||
* @brief Tx test modes
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_TX_TEST_MODE_NORMAL =
|
||||
0x00, //!< Equivalent to lr20xx_radio_common_set_tx_with_timeout_in_rtc_step with @p timeout_in_ms set to 0
|
||||
LR20XX_RADIO_COMMON_TX_TEST_MODE_INFINITE_PREAMBLE =
|
||||
0x01, //!< Generate an infinite preamble (not available with LR-FHSS)
|
||||
LR20XX_RADIO_COMMON_TX_TEST_MODE_CONTINUOUS_WAVE = 0x02, //!< Generate continuous wave (not available with LR-FHSS)
|
||||
LR20XX_RADIO_COMMON_TX_TEST_MODE_PRBS9 =
|
||||
0x03, //!< Generate a PseudoRandom Binary Sequence (not available with LoRa nor LR-FHSS)
|
||||
} lr20xx_radio_common_tx_test_mode_t;
|
||||
|
||||
/*!
|
||||
* @brief Structure to define RSSI calibration gain item
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t gain_value; //!< Gain value expressed on 10 bits fix point decimal format 8.2
|
||||
uint8_t noise_figure; //!< Noise figure value expressed on 8 bits unsigned fix point decimal format 6.2
|
||||
} lr20xx_radio_common_rssi_calibration_gain_item_t;
|
||||
|
||||
/*!
|
||||
* @brief Structure to define RSSI calibration gain table for one RF path
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g1;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g2;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g3;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g4;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g5;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g6;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g7;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g8;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g9;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g10;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g11;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g12_boost0;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g12_boost1;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g12_boost2;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g12_boost3;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g12_boost4;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g12_boost5;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g12_boost6;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g12_boost7;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g13_boost0;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g13_boost1;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g13_boost2;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g13_boost3;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g13_boost4;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g13_boost5;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g13_boost6;
|
||||
lr20xx_radio_common_rssi_calibration_gain_item_t g13_boost7;
|
||||
} lr20xx_radio_common_rssi_calibration_gain_table_t;
|
||||
|
||||
/*!
|
||||
* @brief Gain step
|
||||
*/
|
||||
typedef enum lr20xx_radio_common_gain_step_e
|
||||
{
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_AUTO = 0x00, //!< Enable Automatic gain control (AGC)
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G1 = 0x01, //!< Gain set to G1
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G2 = 0x02, //!< Gain set to G2
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G3 = 0x03, //!< Gain set to G3
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G4 = 0x04, //!< Gain set to G4
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G5 = 0x05, //!< Gain set to G5
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G6 = 0x06, //!< Gain set to G6
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G7 = 0x07, //!< Gain set to G7
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G8 = 0x08, //!< Gain set to G8
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G9 = 0x09, //!< Gain set to G9
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G10 = 0x0A, //!< Gain set to G10
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G11 = 0x0B, //!< Gain set to G11
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G12 = 0x0C, //!< Gain set to G12
|
||||
LR20XX_RADIO_COMMON_GAIN_STEP_G13 = 0x0D, //!< Gain set to G13
|
||||
} lr20xx_radio_common_gain_step_t;
|
||||
|
||||
/**
|
||||
* @brief Exit mode of LoRa Channel Activity Detection (CAD) operation
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_CAD_EXIT_MODE_FALLBACK = 0x00, //!< The chip goes to the configured fallback mode after CAD
|
||||
//!< operation, no matter what the CAD result is
|
||||
LR20XX_RADIO_COMMON_CAD_EXIT_MODE_TX =
|
||||
0x01, //!< If the CAD operation does not detect an activity, the chip enters in TX mode
|
||||
LR20XX_RADIO_COMMON_CAD_EXIT_MODE_RX =
|
||||
0x02, //!< If the CAD operation detects an activity, the chip enters in RX mode
|
||||
} lr20xx_radio_common_cad_exit_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Condition that triggers automatic Tx (or Rx) after Rx (or Tx) operation
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_COMMON_AUTO_TX_RX_OFF = 0x00, //!< Disable Auto Tx (or Rx) after Rx (or Tx) operation
|
||||
LR20XX_RADIO_COMMON_AUTO_TX_RX_ALWAYS = 0x01, //!< Always trigger Tx (or Rx) operation after Rx (or Tx) operation
|
||||
LR20XX_RADIO_COMMON_AUTO_TX_RX_RX_DONE_ONLY =
|
||||
0x02, //!< Trigger Tx operation only if Rx operation terminates with CRC Ok. Similar to @ref
|
||||
//!< LR20XX_RADIO_COMMON_AUTO_TX_RX_ALWAYS when used for automatic Rx after Tx situation
|
||||
} lr20xx_radio_common_auto_tx_rx_conditions_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration of automatic Tx/Rx feature
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
lr20xx_radio_common_auto_tx_rx_conditions_t
|
||||
condition; //!< The condition for executing the automatic Tx (or Rx) operation after Rx (or Tx)
|
||||
bool disable_on_failure; //!< Set to @p true to disable the automatic Tx (or Rx) on Timeout, or on invalid packet
|
||||
//!< received with @p condition sets to @ref LR20XX_RADIO_COMMON_AUTO_TX_RX_RX_DONE_ONLY
|
||||
uint32_t delay_in_tick; //!< The delay between the Rx (or Tx) termination, and the trig of the automatic Tx (or Rx)
|
||||
//!< operation. Expressed in ticks of 32MHz clock.
|
||||
uint32_t tx_rx_timeout_in_rtc_step; //!< The timeout to apply on the automatic Tx (or Rx) operation. Expressed
|
||||
//!< in 32.768kHz RTC step. Possible values are the same as documented for
|
||||
//!< lr20xx_radio_common_set_tx_with_timeout_in_rtc_step or
|
||||
//!< lr20xx_radio_common_set_rx_with_timeout_in_rtc_step
|
||||
} lr20xx_radio_common_auto_tx_rx_configuration_t;
|
||||
|
||||
/*!
|
||||
* @brief Configuration of Power Amplifier
|
||||
*/
|
||||
typedef struct lr20xx_radio_common_pa_cfg_s
|
||||
{
|
||||
lr20xx_radio_common_pa_selection_t pa_sel; //!< Power Amplifier selection
|
||||
lr20xx_radio_common_pa_lf_mode_t pa_lf_mode; //!< Power Amplifier Low-Frequency mode. If pa_sel is unused set to @p
|
||||
//!< LR20XX_RADIO_COMMON_PA_LF_MODE_FSM
|
||||
uint8_t pa_lf_duty_cycle; //!< Power Amplifier - Low-frequency duty cycle. If pa_sel is unused set to 6
|
||||
uint8_t pa_lf_slices; //!< Power Amplifier - Low-frequency number of slices. If pa_sel is unused set to 7
|
||||
uint8_t pa_hf_duty_cycle; //!< Power Amplifier - High-frequency duty cycle. If pa_sel is unused set to 16
|
||||
} lr20xx_radio_common_pa_cfg_t;
|
||||
|
||||
/*!
|
||||
* @brief Clear Channel Assessment results
|
||||
*/
|
||||
typedef struct lr20xx_radio_common_cca_res_s
|
||||
{
|
||||
int16_t min; //!< CCA min - in dBm
|
||||
int16_t max; //!< CCA max - in dBm
|
||||
int16_t avg; //!< CCA average - in dBm
|
||||
} lr20xx_radio_common_cca_res_t;
|
||||
|
||||
/*!
|
||||
* @brief CAD parameters
|
||||
*/
|
||||
typedef struct lr20xx_radio_common_cad_params_s
|
||||
{
|
||||
uint32_t timeout; //!< Timeout in 32MHz step
|
||||
uint8_t threshold; //!< RSSI threshold in -dBm
|
||||
lr20xx_radio_common_cad_exit_mode_t exit_mode; //!< Exit mode
|
||||
uint32_t tx_rx_timeout; //!< Tx / Rx timeout in 32kHz step
|
||||
} lr20xx_radio_common_cad_params_t;
|
||||
|
||||
/**
|
||||
* @brief Link Quality Indicator (LQI) value
|
||||
*
|
||||
* The LQI value is a positive value that is defined as the margin between detection sensitivity threshold and detection
|
||||
* peak that trigger the detection of a signal.
|
||||
*
|
||||
* Here it is given as an integer part (in dB), and a decimal part (in 1/4dB). The actual decimal value can then be
|
||||
* obtained with: \f$LQI_{dB} = lqi\_db + 0.25 \times lqi\_quarter\_db\_counter \f$.
|
||||
*/
|
||||
typedef struct lr20xx_radio_common_lqi_value_s
|
||||
{
|
||||
uint8_t lqi_db; //!< The integer part of LQI (in dB)
|
||||
uint8_t lqi_quarter_db_counter; //!< The decimal part of LQI (in 1/4dB)
|
||||
} lr20xx_radio_common_lqi_value_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_RADIO_COMMON_TYPES_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,265 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_fifo.c
|
||||
*
|
||||
* @brief Radio FiFo driver definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "lr20xx_radio_fifo.h"
|
||||
#include "lr20xx_hal.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE MACROS-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE CONSTANTS -------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LR20XX_RADIO_FIFO_READ_RX_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_FIFO_WRITE_TX_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_FIFO_CLEAR_IRQ_FLAGS_CMD_LENGTH ( 2 + 2 )
|
||||
#define LR20XX_RADIO_FIFO_CFG_IRQ_CMD_LENGTH ( 2 + 10 )
|
||||
#define LR20XX_RADIO_FIFO_GET_IRQ_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_FIFO_GET_RX_LEVEL_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_FIFO_GET_TX_LEVEL_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_FIFO_CLEAR_RX_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_FIFO_CLEAR_TX_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_FIFO_GET_AND_CLEAR_IRQ_FLAGS_CMD_LENGTH ( 2 )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE TYPES -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Operating codes for register and memory related operations
|
||||
*/
|
||||
enum
|
||||
{
|
||||
LR20XX_RADIO_FIFO_READ_RX_OC = 0x0001,
|
||||
LR20XX_RADIO_FIFO_WRITE_TX_OC = 0x0002,
|
||||
LR20XX_RADIO_FIFO_CLEAR_FIFO_IRQ_FLAGS_OC = 0x0114,
|
||||
LR20XX_RADIO_FIFO_CFG_IRQ_OC = 0x011A,
|
||||
LR20XX_RADIO_FIFO_GET_IRQ_OC = 0x011B,
|
||||
LR20XX_RADIO_FIFO_GET_RX_LEVEL_OC = 0x011C,
|
||||
LR20XX_RADIO_FIFO_GET_TX_LEVEL_OC = 0x011D,
|
||||
LR20XX_RADIO_FIFO_CLEAR_RX_OC = 0x011E,
|
||||
LR20XX_RADIO_FIFO_GET_AND_CLEAR_IRQ_FLAGS_OC = 0x012E,
|
||||
LR20XX_RADIO_FIFO_CLEAR_TX_OC = 0x011F,
|
||||
};
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE VARIABLES -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DECLARATION -------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS DEFINITION ---------------------------------------------
|
||||
*/
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_read_rx( const void* context, uint8_t* buffer, const uint16_t length )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_READ_RX_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_READ_RX_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_READ_RX_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_direct_read_fifo( context, cbuffer, LR20XX_RADIO_FIFO_READ_RX_CMD_LENGTH,
|
||||
buffer, length );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_write_tx( const void* context, const uint8_t* buffer, const uint16_t length )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_WRITE_TX_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_WRITE_TX_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_WRITE_TX_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_FIFO_WRITE_TX_CMD_LENGTH, buffer,
|
||||
length );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_clear_rx( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_CLEAR_RX_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_CLEAR_RX_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_CLEAR_RX_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_FIFO_CLEAR_RX_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_clear_tx( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_CLEAR_TX_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_CLEAR_TX_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_CLEAR_TX_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_FIFO_CLEAR_TX_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_get_rx_level( const void* context, uint16_t* fifo_level )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_GET_RX_LEVEL_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_GET_RX_LEVEL_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_GET_RX_LEVEL_OC >> 0 ),
|
||||
};
|
||||
uint8_t fifo_level_uint8[2] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_RADIO_FIFO_GET_RX_LEVEL_CMD_LENGTH, fifo_level_uint8, 2 );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*fifo_level = ( uint16_t )( ( ( uint16_t ) fifo_level_uint8[0] << 8 ) + fifo_level_uint8[1] );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_get_tx_level( const void* context, uint16_t* fifo_level )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_GET_TX_LEVEL_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_GET_TX_LEVEL_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_GET_TX_LEVEL_OC >> 0 ),
|
||||
};
|
||||
uint8_t fifo_level_uint8[2] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_RADIO_FIFO_GET_TX_LEVEL_CMD_LENGTH, fifo_level_uint8, 2 );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*fifo_level = ( uint16_t )( ( ( uint16_t ) fifo_level_uint8[0] << 8 ) + fifo_level_uint8[1] );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_cfg_irq( const void* context, lr20xx_radio_fifo_flag_t rx_fifo_irq_enable,
|
||||
lr20xx_radio_fifo_flag_t tx_fifo_irq_enable, uint16_t rx_fifo_high_threshold,
|
||||
uint16_t tx_fifo_low_threshold, uint16_t rx_fifo_low_threshold,
|
||||
uint16_t tx_fifo_high_threshold )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_CFG_IRQ_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_CFG_IRQ_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_CFG_IRQ_OC >> 0 ),
|
||||
rx_fifo_irq_enable,
|
||||
tx_fifo_irq_enable,
|
||||
( uint8_t )( rx_fifo_high_threshold >> 8 ),
|
||||
( uint8_t )( rx_fifo_high_threshold >> 0 ),
|
||||
( uint8_t )( tx_fifo_low_threshold >> 8 ),
|
||||
( uint8_t )( tx_fifo_low_threshold >> 0 ),
|
||||
( uint8_t )( rx_fifo_low_threshold >> 8 ),
|
||||
( uint8_t )( rx_fifo_low_threshold >> 0 ),
|
||||
( uint8_t )( tx_fifo_high_threshold >> 8 ),
|
||||
( uint8_t )( tx_fifo_high_threshold >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_FIFO_CFG_IRQ_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_clear_irq_flags( const void* context, lr20xx_radio_fifo_flag_t rx_fifo_flags_to_clear,
|
||||
lr20xx_radio_fifo_flag_t tx_fifo_flags_to_clear )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_CLEAR_IRQ_FLAGS_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_CLEAR_FIFO_IRQ_FLAGS_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_CLEAR_FIFO_IRQ_FLAGS_OC >> 0 ),
|
||||
rx_fifo_flags_to_clear,
|
||||
tx_fifo_flags_to_clear,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_FIFO_CLEAR_IRQ_FLAGS_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_get_irq( const void* context, lr20xx_radio_fifo_flag_t* rx_fifo_flags,
|
||||
lr20xx_radio_fifo_flag_t* tx_fifo_flags )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_GET_IRQ_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_GET_IRQ_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_GET_IRQ_OC >> 0 ),
|
||||
};
|
||||
|
||||
uint8_t rbuffer[2] = { 0 };
|
||||
|
||||
const lr20xx_status_t status =
|
||||
( lr20xx_status_t ) lr20xx_hal_read( context, cbuffer, LR20XX_RADIO_FIFO_GET_IRQ_CMD_LENGTH, rbuffer, 2 );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*rx_fifo_flags = rbuffer[0];
|
||||
*tx_fifo_flags = rbuffer[1];
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_fifo_get_and_clear_irq_flags( const void* context, lr20xx_radio_fifo_flag_t* rx_fifo_flags,
|
||||
lr20xx_radio_fifo_flag_t* tx_fifo_flags )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_FIFO_GET_AND_CLEAR_IRQ_FLAGS_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_GET_AND_CLEAR_IRQ_FLAGS_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_FIFO_GET_AND_CLEAR_IRQ_FLAGS_OC >> 0 ),
|
||||
};
|
||||
uint8_t flags[2] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_RADIO_FIFO_GET_AND_CLEAR_IRQ_FLAGS_CMD_LENGTH, flags, 2 );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*rx_fifo_flags = flags[0];
|
||||
*tx_fifo_flags = flags[1];
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DEFINITION --------------------------------------------
|
||||
*/
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,209 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_fifo.h
|
||||
*
|
||||
* @brief Radio FiFo driver definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_RADIO_FIFO_H
|
||||
#define LR20XX_RADIO_FIFO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lr20xx_status.h"
|
||||
#include "lr20xx_radio_fifo_types.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Read data from RX First in First out (FiFo) radio memory
|
||||
*
|
||||
* The RX FiFo radio memory contains packet received or being received.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] buffer The buffer to be filled with data read from RX FiFo. It is up to the caller to ensure it is at
|
||||
* least @p length bytes long.
|
||||
* @param [in] length The number of bytes to read from RX FiFo
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_radio_fifo_write_tx
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_read_rx( const void* context, uint8_t* buffer, const uint16_t length );
|
||||
|
||||
/*!
|
||||
* @brief Write data to TX First in First out (FiFo) radio memory
|
||||
*
|
||||
* The TX FiFo radio memory contains packet to send.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] buffer The buffer to be written to TX FiFo. It is up to the caller to ensure it is at least
|
||||
* @p length bytes long.
|
||||
* @param [in] length The number of bytes to write to TX FiFo
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_radio_fifo_read_rx
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_write_tx( const void* context, const uint8_t* buffer, const uint16_t length );
|
||||
|
||||
/*!
|
||||
* @brief Clear Rx FIFO
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_clear_rx( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Clear Tx FIFO
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_clear_tx( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Get Rx FIFO level
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] fifo_level Rx FIFO level in byte
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_get_rx_level( const void* context, uint16_t* fifo_level );
|
||||
|
||||
/*!
|
||||
* @brief Get Tx FIFO level
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] fifo_level Tx FIFO level in byte
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_get_tx_level( const void* context, uint16_t* fifo_level );
|
||||
|
||||
/*!
|
||||
* @brief Configure FIFO events and threshold levels triggering a FIFO interrupt in Rx and Tx
|
||||
*
|
||||
* @remark When configured, the FIFO interrupts are triggered if the FIFO level crosses the threshold in the correct
|
||||
* direction. Therefore if a threshold related IRQ is cleared, it will be raised again only if the FIFO level crosses
|
||||
* the threshold on the correct direction.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] rx_fifo_irq_enable FIFO events triggering an interrupt in Rx
|
||||
* @param [in] tx_fifo_irq_enable FIFO events triggering an interrupt in Tx
|
||||
* @param [in] rx_fifo_high_threshold Rx FIFO threshold above which an interrupt (if
|
||||
* LR20XX_RADIO_FIFO_FLAG_THRESHOLD_HIGH is enabled) is triggered
|
||||
* @param [in] tx_fifo_low_threshold Tx FIFO threshold below which an interrupt (if
|
||||
* LR20XX_RADIO_FIFO_FLAG_THRESHOLD_LOW is enabled) is triggered
|
||||
* @param [in] rx_fifo_low_threshold Rx FIFO threshold below which an interrupt (if
|
||||
* LR20XX_RADIO_FIFO_FLAG_THRESHOLD_LOW is enabled) is triggered
|
||||
* @param [in] tx_fifo_high_threshold Tx FIFO threshold above which an interrupt (if
|
||||
* LR20XX_RADIO_FIFO_FLAG_THRESHOLD_HIGH is enabled) is triggered
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_cfg_irq( const void* context, lr20xx_radio_fifo_flag_t rx_fifo_irq_enable,
|
||||
lr20xx_radio_fifo_flag_t tx_fifo_irq_enable, uint16_t rx_fifo_high_threshold,
|
||||
uint16_t tx_fifo_low_threshold, uint16_t rx_fifo_low_threshold,
|
||||
uint16_t tx_fifo_high_threshold );
|
||||
|
||||
/*!
|
||||
* @brief Clear specific IRQ flags for both Rx and Tx FIFO
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] rx_fifo_flags_to_clear Rx FIFO IRQ flags to clear
|
||||
* @param [in] tx_fifo_flags_to_clear Tx FIFO IRQ flags to clear
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_clear_irq_flags( const void* context, lr20xx_radio_fifo_flag_t rx_fifo_flags_to_clear,
|
||||
lr20xx_radio_fifo_flag_t tx_fifo_flags_to_clear );
|
||||
|
||||
/*!
|
||||
* @brief Get FIFO events triggering a FIFO interrupt in Rx and Tx
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] rx_fifo_flags FIFO events triggering an interrupt in Rx
|
||||
* @param [out] tx_fifo_flags FIFO events triggering an interrupt in Tx
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_get_irq( const void* context, lr20xx_radio_fifo_flag_t* rx_fifo_flags,
|
||||
lr20xx_radio_fifo_flag_t* tx_fifo_flags );
|
||||
|
||||
/*!
|
||||
* @brief Clear and return FiFo IRQ flags
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] rx_fifo_flags Rx FiFo flags
|
||||
* @param [out] tx_fifo_flags Tx FiFo flags
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_fifo_get_and_clear_irq_flags( const void* context, lr20xx_radio_fifo_flag_t* rx_fifo_flags,
|
||||
lr20xx_radio_fifo_flag_t* tx_fifo_flags );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_RADIO_FIFO_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,96 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_fifo_types.h
|
||||
*
|
||||
* @brief Radio FIFO driver types for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2024. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_RADIO_FIFO_TYPES_H
|
||||
#define LR20XX_RADIO_FIFO_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief FIFO flags
|
||||
*/
|
||||
enum lr20xx_radio_fifo_flag_e
|
||||
{
|
||||
LR20XX_RADIO_FIFO_FLAG_NONE = ( 0 << 0 ),
|
||||
LR20XX_RADIO_FIFO_FLAG_EMPTY = ( 1 << 0 ),
|
||||
LR20XX_RADIO_FIFO_FLAG_THRESHOLD_LOW = ( 1 << 1 ),
|
||||
LR20XX_RADIO_FIFO_FLAG_THRESHOLD_HIGH = ( 1 << 2 ),
|
||||
LR20XX_RADIO_FIFO_FLAG_FULL = ( 1 << 3 ),
|
||||
LR20XX_RADIO_FIFO_FLAG_OVERFLOW = ( 1 << 4 ),
|
||||
LR20XX_RADIO_FIFO_FLAG_UNDERFLOW = ( 1 << 5 ),
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief FIFO flag type re-definition
|
||||
*
|
||||
* @see lr20xx_radio_fifo_flag_e
|
||||
*/
|
||||
typedef uint8_t lr20xx_radio_fifo_flag_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_RADIO_FIFO_TYPES_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,206 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_flrc.h
|
||||
*
|
||||
* @brief Radio FLRC driver definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_RADIO_FLRC_H
|
||||
#define LR20XX_RADIO_FLRC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lr20xx_status.h"
|
||||
#include "lr20xx_radio_flrc_types.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set the modulation parameters for FLRC packets
|
||||
*
|
||||
* The workaround @ref lr20xx_workarounds_dcdc_configure must be called for Rx sub-GHz operations with regulator @ref
|
||||
* LR20XX_SYSTEM_REG_MODE_DCDC after this function to avoid possible RF sensitivity degradation.
|
||||
*
|
||||
* @note This function automatically applies the workaround @ref lr20xx_workarounds_dcdc_configure unless the macro @p
|
||||
* LR20XX_WORKAROUNDS_DISABLE_AUTOMATIC_DCDC_CONFIGURE is defined at compile time.
|
||||
*
|
||||
* @note This command is not available to LR2022
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] params Structure of FLRC modulation configuration
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_workarounds_dcdc_configure
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_flrc_set_modulation_params( const void* context,
|
||||
const lr20xx_radio_flrc_mod_params_t* params );
|
||||
|
||||
/**
|
||||
* @brief Set the packet parameters for FLRC packets
|
||||
*
|
||||
* @note This command is not available to LR2022
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] params Structure of FLRC packet configuration
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_flrc_set_pkt_params( const void* context, const lr20xx_radio_flrc_pkt_params_t* params );
|
||||
|
||||
/**
|
||||
* @brief Get the internal statistics of received FLRC packets
|
||||
*
|
||||
* The internal statistics are reset on:
|
||||
* - Power On Reset (POR)
|
||||
* - sleep without memory retention
|
||||
* - call to lr20xx_radio_common_reset_rx_stats
|
||||
*
|
||||
* @note This command is not available to LR2022
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[out] statistics FLRC received packet statistics
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_radio_common_reset_rx_stats
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_flrc_get_rx_stats( const void* context, lr20xx_radio_flrc_rx_stats_t* statistics );
|
||||
|
||||
/**
|
||||
* @brief Get the status of the last FLRC received packet
|
||||
*
|
||||
* Availability of the packet status fields depend on the IRQ as follows:
|
||||
* - Available from LR20XX_SYSTEM_IRQ_SYNC_WORD_HEADER_VALID:
|
||||
* - lr20xx_radio_flrc_pkt_status_t.rssi_sync_in_dbm
|
||||
* - lr20xx_radio_flrc_pkt_status_t.rssi_sync_half_dbm_count
|
||||
* - lr20xx_radio_flrc_pkt_status_t.syncword_index
|
||||
* - Available from LR20XX_SYSTEM_IRQ_RX_DONE:
|
||||
* - lr20xx_radio_flrc_pkt_status_t.rssi_avg_in_dbm
|
||||
* - lr20xx_radio_flrc_pkt_status_t.rssi_avg_half_dbm_count
|
||||
*
|
||||
* @note This command is not available to LR2022
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[out] pkt_status FLRC packet status structure
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_flrc_get_pkt_status( const void* context, lr20xx_radio_flrc_pkt_status_t* pkt_status );
|
||||
|
||||
/**
|
||||
* @brief Set a short syncword for FLRC packet
|
||||
*
|
||||
* A short syncword is a 2-bytes long syncword.
|
||||
*
|
||||
* Status is available only after the end of a packet reception.
|
||||
*
|
||||
* @note This command is not available to LR2022
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] syncword_index Syncword index to be configured
|
||||
* @param[in] short_syncword Syncword value to be configured. It is up to the caller to ensure @p short_syncword is at
|
||||
* least @ref LR20XX_RADIO_FLRC_SHORT_SYNCWORD_LENGTH bytes long
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_radio_flrc_set_syncword
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_flrc_set_short_syncword(
|
||||
const void* context, uint8_t syncword_index,
|
||||
const uint8_t short_syncword[LR20XX_RADIO_FLRC_SHORT_SYNCWORD_LENGTH] );
|
||||
|
||||
/**
|
||||
* @brief Set the syncword for FLRC packet
|
||||
*
|
||||
* Status is available only after the end of a packet reception.
|
||||
*
|
||||
* @note This command is not available to LR2022
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] syncword_index Syncword index to be configured
|
||||
* @param[in] syncword Syncword value to be configured. It is up to the caller to ensure @p short_syncword is at least
|
||||
* @ref LR20XX_RADIO_FLRC_SYNCWORD_LENGTH bytes long
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_radio_flrc_set_short_syncword
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_flrc_set_syncword( const void* context, uint8_t syncword_index,
|
||||
const uint8_t syncword[LR20XX_RADIO_FLRC_SYNCWORD_LENGTH] );
|
||||
|
||||
/**
|
||||
* @brief Helper function to get the time-on-air of FLRC packet, in microseconds
|
||||
*
|
||||
* @note This command is not available to LR2022
|
||||
*
|
||||
* @param pkt_params The packet parameter configuration
|
||||
* @param mod_params The modulation parameter configuration
|
||||
*
|
||||
* @return Time-on-air of the packet in microsecond
|
||||
*
|
||||
* @see lr20xx_radio_flrc_set_modulation_params, lr20xx_radio_flrc_set_pkt_params
|
||||
*/
|
||||
uint32_t lr20xx_get_flrc_time_on_air_in_us( const lr20xx_radio_flrc_pkt_params_t* pkt_params,
|
||||
const lr20xx_radio_flrc_mod_params_t* mod_params );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_RADIO_FLRC_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,250 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_flrc_types.h
|
||||
*
|
||||
* @brief FLRC radio types driver definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_RADIO_FLRC_TYPES_H
|
||||
#define LR20XX_RADIO_FLRC_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Length in bytes of the FLRC short syncword
|
||||
*
|
||||
*/
|
||||
#define LR20XX_RADIO_FLRC_SHORT_SYNCWORD_LENGTH ( 2 )
|
||||
|
||||
/**
|
||||
* @brief Length in bytes of the FLRC syncword
|
||||
*
|
||||
*/
|
||||
#define LR20XX_RADIO_FLRC_SYNCWORD_LENGTH ( 4 )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Combinations of bitrate and bandwidth for FLRC packet type
|
||||
*
|
||||
* @remark The bitrate is in Mb/s and the bandwidth in MHz (DSB)
|
||||
*/
|
||||
typedef enum lr20xx_radio_flrc_br_bw_e
|
||||
{
|
||||
LR20XX_RADIO_FLRC_BR_2_600_BW_2_666 = 0x00, //!< 2.600 Mb/s, 2.666 MHz
|
||||
LR20XX_RADIO_FLRC_BR_2_080_BW_2_222 = 0x01, //!< 2.080 Mb/s, 2.222 MHz
|
||||
LR20XX_RADIO_FLRC_BR_1_300_BW_1_333 = 0x02, //!< 1.300 Mb/s, 1.333 MHz
|
||||
LR20XX_RADIO_FLRC_BR_1_040_BW_1_333 = 0x03, //!< 1.040 Mb/s, 1.333 MHz
|
||||
LR20XX_RADIO_FLRC_BR_0_650_BW_0_740 = 0x04, //!< 0.650 Mb/s, 0.740 MHz
|
||||
LR20XX_RADIO_FLRC_BR_0_520_BW_0_571 = 0x05, //!< 0.520 Mb/s, 0.571 MHz
|
||||
LR20XX_RADIO_FLRC_BR_0_325_BW_0_357 = 0x06, //!< 0.325 Mb/s, 0.357 MHz
|
||||
LR20XX_RADIO_FLRC_BR_0_260_BW_0_307 = 0x07, //!< 0.260 Mb/s, 0.307 MHz
|
||||
} lr20xx_radio_flrc_br_bw_t;
|
||||
|
||||
/**
|
||||
* @brief Coding rates for FLRC packet type
|
||||
*/
|
||||
typedef enum lr20xx_radio_flrc_cr_e
|
||||
{
|
||||
LR20XX_RADIO_FLRC_CR_1_2 = 0x00, //!< Coding rate 1/2
|
||||
LR20XX_RADIO_FLRC_CR_3_4 = 0x01, //!< Coding rate 3/4
|
||||
LR20XX_RADIO_FLRC_CR_NONE = 0x02, //!< Coding rate 1 (no FEC)
|
||||
LR20XX_RADIO_FLRC_CR_2_3 = 0x03, //!< Coding rate 2/3
|
||||
} lr20xx_radio_flrc_cr_t;
|
||||
|
||||
/**
|
||||
* @brief Modulation shaping values for FLRC packet type
|
||||
*/
|
||||
typedef enum lr20xx_radio_flrc_pulse_shape_e
|
||||
{
|
||||
LR20XX_RADIO_FLRC_PULSE_SHAPE_OFF = 0x00,
|
||||
LR20XX_RADIO_FLRC_PULSE_SHAPE_BT_05 = 0x05,
|
||||
LR20XX_RADIO_FLRC_PULSE_SHAPE_BT_1 = 0x07,
|
||||
} lr20xx_radio_flrc_pulse_shape_t;
|
||||
|
||||
/**
|
||||
* @brief Preamble lengths for FLRC packet type
|
||||
*/
|
||||
typedef enum lr20xx_radio_flrc_preamble_len_e
|
||||
{
|
||||
LR20XX_RADIO_FLRC_PREAMBLE_LEN_04_BITS = 0x00,
|
||||
LR20XX_RADIO_FLRC_PREAMBLE_LEN_08_BITS = 0x01,
|
||||
LR20XX_RADIO_FLRC_PREAMBLE_LEN_12_BITS = 0x02,
|
||||
LR20XX_RADIO_FLRC_PREAMBLE_LEN_16_BITS = 0x03,
|
||||
LR20XX_RADIO_FLRC_PREAMBLE_LEN_20_BITS = 0x04,
|
||||
LR20XX_RADIO_FLRC_PREAMBLE_LEN_24_BITS = 0x05,
|
||||
LR20XX_RADIO_FLRC_PREAMBLE_LEN_28_BITS = 0x06,
|
||||
LR20XX_RADIO_FLRC_PREAMBLE_LEN_32_BITS = 0x07,
|
||||
} lr20xx_radio_flrc_preamble_len_t;
|
||||
|
||||
/**
|
||||
* @brief Combinations of SyncWord correlators activated for FLRC packet types
|
||||
*
|
||||
* @remark Each syncword (1,2 or 3) is configured thanks to @ref lr20xx_radio_flrc_set_syncword
|
||||
*/
|
||||
typedef enum lr20xx_radio_flrc_rx_match_sync_word_e
|
||||
{
|
||||
LR20XX_RADIO_FLRC_RX_MATCH_SYNCWORD_OFF = 0x00, //!< No syncword match
|
||||
LR20XX_RADIO_FLRC_RX_MATCH_SYNCWORD_1 = 0x01, //!< Match syncword #1
|
||||
LR20XX_RADIO_FLRC_RX_MATCH_SYNCWORD_2 = 0x02, //!< Match syncword #2
|
||||
LR20XX_RADIO_FLRC_RX_MATCH_SYNCWORD_1_OR_2 = 0x03, //!< Match syncword #1 or #2
|
||||
LR20XX_RADIO_FLRC_RX_MATCH_SYNCWORD_3 = 0x04, //!< Match syncword #3
|
||||
LR20XX_RADIO_FLRC_RX_MATCH_SYNCWORD_1_OR_3 = 0x05, //!< Match syncword #1 or #3
|
||||
LR20XX_RADIO_FLRC_RX_MATCH_SYNCWORD_2_OR_3 = 0x06, //!< Match syncword #2 or #3
|
||||
LR20XX_RADIO_FLRC_RX_MATCH_SYNCWORD_1_OR_2_OR_3 = 0x07, //!< Match syncword #1 or #2 or #3
|
||||
} lr20xx_radio_flrc_rx_match_sync_word_t;
|
||||
|
||||
/**
|
||||
* @brief Syncword lengths for FLRC packet type
|
||||
*/
|
||||
typedef enum lr20xx_radio_flrc_sync_word_len_e
|
||||
{
|
||||
LR20XX_RADIO_FLRC_SYNCWORD_LENGTH_OFF = 0x00,
|
||||
LR20XX_RADIO_FLRC_SYNCWORD_LENGTH_2_BYTES = 0x01,
|
||||
LR20XX_RADIO_FLRC_SYNCWORD_LENGTH_4_BYTES = 0x02,
|
||||
} lr20xx_radio_flrc_sync_word_len_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration of syncwords for Tx operations
|
||||
*
|
||||
*/
|
||||
typedef enum lr20xx_radio_flrc_tx_syncword_e
|
||||
{
|
||||
LR20XX_RADIO_FLRC_TX_SYNCWORD_NONE = 0x00, //!< Do not use syncword for Tx operation
|
||||
LR20XX_RADIO_FLRC_TX_SYNCWORD_1 = 0x01, //!< Use syncword 1
|
||||
LR20XX_RADIO_FLRC_TX_SYNCWORD_2 = 0x02, //!< Use syncword 2
|
||||
LR20XX_RADIO_FLRC_TX_SYNCWORD_3 = 0x03, //!< Use syncword 3
|
||||
} lr20xx_radio_flrc_tx_syncword_t;
|
||||
|
||||
/**
|
||||
* @brief Packet length mode for FLRC packet type
|
||||
*/
|
||||
typedef enum lr20xx_radio_flrc_pkt_len_modes_e
|
||||
{
|
||||
LR20XX_RADIO_FLRC_PKT_VAR_LEN = 0x00,
|
||||
LR20XX_RADIO_FLRC_PKT_FIX_LEN = 0x01,
|
||||
} lr20xx_radio_flrc_pkt_len_modes_t;
|
||||
|
||||
/**
|
||||
* @brief CRC lengths for FLRC packet type
|
||||
*/
|
||||
typedef enum lr20xx_radio_flrc_crc_types_e
|
||||
{
|
||||
LR20XX_RADIO_FLRC_CRC_OFF = 0x00,
|
||||
LR20XX_RADIO_FLRC_CRC_2_BYTES = 0x01,
|
||||
LR20XX_RADIO_FLRC_CRC_3_BYTES = 0x02,
|
||||
LR20XX_RADIO_FLRC_CRC_4_BYTES = 0x03,
|
||||
} lr20xx_radio_flrc_crc_types_t;
|
||||
|
||||
/**
|
||||
* @brief Modulation configuration for LoRa packet
|
||||
*
|
||||
*/
|
||||
typedef struct lr20xx_radio_flrc_mod_params_s
|
||||
{
|
||||
lr20xx_radio_flrc_br_bw_t br_bw; //!< Bitrate & bandwidth
|
||||
lr20xx_radio_flrc_cr_t cr; //!< Coding rate
|
||||
lr20xx_radio_flrc_pulse_shape_t shape; //!< Shaping
|
||||
} lr20xx_radio_flrc_mod_params_t;
|
||||
|
||||
/**
|
||||
* @brief Packet parameters for FLRC packet type
|
||||
*/
|
||||
typedef struct lr20xx_radio_flrc_pkt_params_s
|
||||
{
|
||||
lr20xx_radio_flrc_preamble_len_t preamble_len; //!< FLRC preamble length
|
||||
lr20xx_radio_flrc_sync_word_len_t sync_word_len; //!< FLRC syncword length
|
||||
lr20xx_radio_flrc_tx_syncword_t tx_syncword; //!< FLRC syncword to use for Tx operation
|
||||
lr20xx_radio_flrc_rx_match_sync_word_t match_sync_word; //!< FLRC syncword matcher
|
||||
lr20xx_radio_flrc_pkt_len_modes_t header_type; //!< FLRC header type
|
||||
uint16_t pld_len_in_bytes; //!< FLRC payload length in byte - in [6:511] (note that for SX1280 compatibility, range
|
||||
//!< is [6:127]). If a length error is detected while
|
||||
//!< lr20xx_radio_flrc_pkt_params_t.header_type == LR20XX_RADIO_FLRC_PKT_VAR_LEN, the
|
||||
//!< IRQ LR20XX_SYSTEM_IRQ_LEN_ERROR is raised, but the device remains in Rx mode.
|
||||
lr20xx_radio_flrc_crc_types_t crc_type; //!< FLRC CRC type configuration
|
||||
} lr20xx_radio_flrc_pkt_params_t;
|
||||
|
||||
/**
|
||||
* @brief FLRC statistics of received packets
|
||||
*/
|
||||
typedef struct lr20xx_radio_flrc_rx_stats_s
|
||||
{
|
||||
uint16_t received_packets; //!< Number of received packets
|
||||
uint16_t crc_errors; //!< Number of received packets with CRC error
|
||||
uint16_t length_errors; //!< Number of received packets with length error
|
||||
} lr20xx_radio_flrc_rx_stats_t;
|
||||
|
||||
/**
|
||||
* @brief Packet status parameters for FLRC packet types
|
||||
*/
|
||||
typedef struct lr20xx_radio_flrc_pkt_status_s
|
||||
{
|
||||
uint16_t packet_length_bytes; //!< Length of last received packet in bytes
|
||||
uint8_t syncword_index; //!< Syncword index of the last received packet - in [1, 2, 3]
|
||||
int16_t rssi_avg_in_dbm; //!< RSSI in dBm - averaged over the last received packet
|
||||
uint8_t rssi_avg_half_dbm_count; //!< Count of 0.5 dBm to subtract to rssi_avg_in_dbm value in dBm
|
||||
int16_t rssi_sync_in_dbm; //!< RSSI in dBm - averaged over the last received packet
|
||||
uint8_t rssi_sync_half_dbm_count; //!< Count of 0.5 dBm to subtract to rssi_sync_in_dbm value in dBm
|
||||
} lr20xx_radio_flrc_pkt_status_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_RADIO_FLRC_TYPES_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,172 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_fsk_common_types.h
|
||||
*
|
||||
* @brief Radio FSK common driver types for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_RADIO_FSK_COMMON_TYPES_H
|
||||
#define LR20XX_RADIO_FSK_COMMON_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reception Double Side Bandwidth (DSB) value for FSK modulation
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_3_500_HZ = 0xE7, //!< RX Bandwidth 3.5 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_4_200_HZ = 0xA7, //!< RX Bandwidth 4.2 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_4_300_HZ = 0xDF, //!< RX Bandwidth 4.3 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_4_500_HZ = 0x67, //!< RX Bandwidth 4.5 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_4_800_HZ = 0x27, //!< RX Bandwidth 4.8 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_5_200_HZ = 0x9F, //!< RX Bandwidth 5.2 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_5_600_HZ = 0x5F, //!< RX Bandwidth 5.6 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_5_800_HZ = 0xD7, //!< RX Bandwidth 5.8 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_6_000_HZ = 0x1F, //!< RX Bandwidth 6 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_6_900_HZ = 0xE6, //!< RX Bandwidth 6.9 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_7_400_HZ = 0x57, //!< RX Bandwidth 7.4 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_8_000_HZ = 0x17, //!< RX Bandwidth 8 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_8_300_HZ = 0xA6, //!< RX Bandwidth 8.3 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_8_700_HZ = 0xDE, //!< RX Bandwidth 8.7 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_8_900_HZ = 0x66, //!< RX Bandwidth 8.9 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_9_600_HZ = 0x26, //!< RX Bandwidth 9.6 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_10_000_HZ = 0x9E, //!< RX Bandwidth 10 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_11_000_HZ = 0x5E, //!< RX Bandwidth 11 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_12_000_HZ = 0x1E, //!< RX Bandwidth 12 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_13_000_HZ = 0xE5, //!< RX Bandwidth 13 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_14_000_HZ = 0x56, //!< RX Bandwidth 14 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_16_000_HZ = 0xA5, //!< RX Bandwidth 16 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_17_000_HZ = 0x65, //!< RX Bandwidth 17 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_19_000_HZ = 0x25, //!< RX Bandwidth 19 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_20_000_HZ = 0x9D, //!< RX Bandwidth 20 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_22_000_HZ = 0x5D, //!< RX Bandwidth 22 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_23_000_HZ = 0xD5, //!< RX Bandwidth 23 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_24_000_HZ = 0x1D, //!< RX Bandwidth 24 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_27_000_HZ = 0xE4, //!< RX Bandwidth 27 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_29_000_HZ = 0x55, //!< RX Bandwidth 29 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_32_000_HZ = 0x15, //!< RX Bandwidth 32 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_33_000_HZ = 0xA4, //!< RX Bandwidth 33 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_34_000_HZ = 0xDC, //!< RX Bandwidth 34 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_35_000_HZ = 0x64, //!< RX Bandwidth 35 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_38_000_HZ = 0x24, //!< RX Bandwidth 38 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_41_000_HZ = 0x9C, //!< RX Bandwidth 41 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_44_000_HZ = 0x5C, //!< RX Bandwidth 44 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_46_000_HZ = 0xD4, //!< RX Bandwidth 46 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_48_000_HZ = 0x1C, //!< RX Bandwidth 48 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_55_000_HZ = 0xE3, //!< RX Bandwidth 55 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_59_000_HZ = 0x54, //!< RX Bandwidth 59 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_64_000_HZ = 0x14, //!< RX Bandwidth 64 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_66_000_HZ = 0xA3, //!< RX Bandwidth 66 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_69_000_HZ = 0xDB, //!< RX Bandwidth 69 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_71_000_HZ = 0x63, //!< RX Bandwidth 71 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_76_000_HZ = 0x23, //!< RX Bandwidth 76 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_83_000_HZ = 0x9B, //!< RX Bandwidth 83 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_89_000_HZ = 0x5B, //!< RX Bandwidth 89 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_92_000_HZ = 0xD3, //!< RX Bandwidth 92 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_96_000_HZ = 0x1B, //!< RX Bandwidth 96 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_111_000_HZ = 0xE2, //!< RX Bandwidth 111 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_119_000_HZ = 0x53, //!< RX Bandwidth 119 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_128_000_HZ = 0x13, //!< RX Bandwidth 128 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_133_000_HZ = 0xA2, //!< RX Bandwidth 133 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_138_000_HZ = 0xDA, //!< RX Bandwidth 138 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_142_000_HZ = 0x62, //!< RX Bandwidth 142 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_153_000_HZ = 0x22, //!< RX Bandwidth 153 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_166_000_HZ = 0x9A, //!< RX Bandwidth 166 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_178_000_HZ = 0x5A, //!< RX Bandwidth 178 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_185_000_HZ = 0xD2, //!< RX Bandwidth 185 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_192_000_HZ = 0x1A, //!< RX Bandwidth 192 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_222_000_HZ = 0xE1, //!< RX Bandwidth 222 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_238_000_HZ = 0x52, //!< RX Bandwidth 238 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_256_000_HZ = 0x12, //!< RX Bandwidth 256 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_266_000_HZ = 0xA1, //!< RX Bandwidth 266 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_277_000_HZ = 0xD9, //!< RX Bandwidth 277 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_285_000_HZ = 0x61, //!< RX Bandwidth 285 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_307_000_HZ = 0x21, //!< RX Bandwidth 307 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_333_000_HZ = 0x99, //!< RX Bandwidth 333 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_357_000_HZ = 0x59, //!< RX Bandwidth 357 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_370_000_HZ = 0xD1, //!< RX Bandwidth 370 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_384_000_HZ = 0x19, //!< RX Bandwidth 384 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_444_000_HZ = 0xE0, //!< RX Bandwidth 444 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_476_000_HZ = 0x51, //!< RX Bandwidth 476 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_512_000_HZ = 0x11, //!< RX Bandwidth 512 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_533_000_HZ = 0xA0, //!< RX Bandwidth 533 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_555_000_HZ = 0xD8, //!< RX Bandwidth 555 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_571_000_HZ = 0x60, //!< RX Bandwidth 571 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_615_000_HZ = 0x20, //!< RX Bandwidth 615 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_666_000_HZ = 0x98, //!< RX Bandwidth 666 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_714_000_HZ = 0x58, //!< RX Bandwidth 714 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_740_000_HZ = 0xD0, //!< RX Bandwidth 740 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_769_000_HZ = 0x18, //!< RX Bandwidth 769 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_888_000_HZ = 0x90, //!< RX Bandwidth 888 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_1_111_000_HZ = 0xC8, //!< RX Bandwidth 1111 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_1_333_000_HZ = 0x88, //!< RX Bandwidth 1333 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_2_222_000_HZ = 0xC0, //!< RX Bandwidth 2222 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_2_666_000_HZ = 0x80, //!< RX Bandwidth 2666 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_2_857_000_HZ = 0x40, //!< RX Bandwidth 2857 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_3_076_000_HZ = 0x00, //!< RX Bandwidth 3076 kHz
|
||||
LR20XX_RADIO_FSK_COMMON_RX_BW_AUTO =
|
||||
0xFF, //!< RX Bandwidth automatic choice - limited to Wi-SUN, Wireless M-BUS, Wi-SUN, and Z-Wave
|
||||
} lr20xx_radio_fsk_common_bw_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_RADIO_FSK_COMMON_TYPES_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,648 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_lora.c
|
||||
*
|
||||
* @brief Radio LoRa driver implementation for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "lr20xx_radio_lora.h"
|
||||
#include "lr20xx_hal.h"
|
||||
#include "lr20xx_workarounds.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE MACROS-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Length in byte of one side detector CAD configuration
|
||||
*/
|
||||
#define LR20XX_RADIO_LORA_CAD_SIDE_DETECTOR_CONFIGURATION_LENGTH ( 2u )
|
||||
|
||||
#define LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_CONFIGURE_CAD_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_LORA_SET_MODULATION_PARAMS_CMD_LENGTH ( 2 + 2 )
|
||||
#define LR20XX_RADIO_LORA_SET_PACKET_PARAMS_CMD_LENGTH ( 2 + 4 )
|
||||
#define LR20XX_RADIO_LORA_SET_LORA_SEARCH_SYMBOLS_CMD_LENGTH ( 2 + 2 )
|
||||
#define LR20XX_RADIO_LORA_SET_SYNCWORD_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_LORA_CONFIGURE_SIDE_DETECTORS_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_SYNCWORD_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_LORA_CONFIGURE_CAD_PARAMS_CMD_LENGTH ( 2 + 7 )
|
||||
#define LR20XX_RADIO_LORA_SET_CAD_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_LORA_GET_RX_STATISTICS_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_LORA_GET_PACKET_STATUS_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_RADIO_LORA_SET_ADDRESS_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_RADIO_LORA_SET_FREQ_HOP_CMD_LENGTH ( 2 + 2 )
|
||||
|
||||
#define LR20XX_RADIO_LORA_CONFIGURE_SIDE_DETECTOR_CAD_TEMP_LENGTH \
|
||||
( 3 * LR20XX_RADIO_LORA_CAD_SIDE_DETECTOR_CONFIGURATION_LENGTH )
|
||||
|
||||
#define LR20XX_RADIO_LORA_GET_RX_STATISTICS_RBUFFER_LENGTH ( 8 )
|
||||
#define LR20XX_RADIO_LORA_GET_PACKET_STATUS_RBUFFER_LENGTH ( 6 )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE CONSTANTS -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE TYPES -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Operating codes for radio related operations
|
||||
*/
|
||||
enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_CONFIGURE_CAD_OC = 0x021E,
|
||||
LR20XX_RADIO_LORA_SET_MODULATION_PARAMS_OC = 0x0220,
|
||||
LR20XX_RADIO_LORA_SET_PACKET_PARAMS_OC = 0x0221,
|
||||
LR20XX_RADIO_LORA_SET_LORA_SEARCH_SYMBOLS_OC = 0x0222,
|
||||
LR20XX_RADIO_LORA_SET_SYNCWORD_OC = 0x0223,
|
||||
LR20XX_RADIO_LORA_CONFIGURE_SIDE_DETECTORS_OC = 0x0224,
|
||||
LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_SYNCWORD_OC = 0x0225,
|
||||
LR20XX_RADIO_LORA_CONFIGURE_CAD_PARAMS_OC = 0x0227,
|
||||
LR20XX_RADIO_LORA_SET_CAD_OC = 0x0228,
|
||||
LR20XX_RADIO_LORA_GET_RX_STATISTICS_OC = 0x0229,
|
||||
LR20XX_RADIO_LORA_GET_PACKET_STATUS_OC = 0x022A,
|
||||
LR20XX_RADIO_LORA_SET_ADDRESS_OC = 0x022B,
|
||||
LR20XX_RADIO_LORA_SET_FREQ_HOP_OC = 0x022C,
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SEARCH_SYMBOL_FORMAT_NUMBER = 0x00,
|
||||
SEARCH_SYMBOL_FORMAT_MANTISSA = 0x01,
|
||||
} search_symbol_format_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE VARIABLES -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DECLARATION -------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Helper function that abstract the call for lr20xx_radio_lora_set_lora_search_symbols_by_number and
|
||||
* lr20xx_radio_lora_set_lora_search_symbols_by_mantissa
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] n_symbols A byte representing the number of symbol. Meaning depends on format
|
||||
* @param[in] format The format that defines the meaning of n_symbols
|
||||
* @return lr20xx_status_t
|
||||
*/
|
||||
static lr20xx_status_t abstract_search_symbols( const void* context, uint8_t n_symbols, search_symbol_format_t format );
|
||||
|
||||
/**
|
||||
* @brief Read two bytes from buffer and convert it in 16 bits value MSB first
|
||||
*
|
||||
* @param buffer Pointer to location where to read 2 bytes. It is up to the caller to ensure there are at least two
|
||||
* bytes to read
|
||||
*
|
||||
* @return The MSB first value corresponding to the consecutive bytes read
|
||||
*/
|
||||
static uint16_t read_2_bytes_msbf( const uint8_t* buffer );
|
||||
|
||||
/**
|
||||
* @brief Compute the byte representation of LoRa side detector configuration
|
||||
*
|
||||
* @param side_detector_cfg The LoRa side detector configuration
|
||||
*
|
||||
* @return uint8_t The byte representing the LoRa side detector configuration
|
||||
*/
|
||||
static uint8_t radio_lora_side_detector_cfg_to_byte( const lr20xx_radio_lora_side_detector_cfg_t* side_detector_cfg );
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS DEFINITION ---------------------------------------------
|
||||
*/
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_side_detector_cad(
|
||||
const void* context, const lr20xx_radio_lora_side_detector_cad_configuration_t* side_detector_cad_configurations,
|
||||
uint8_t n_side_detector_cad_configurations )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_CONFIGURE_CAD_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_CONFIGURE_CAD_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_CONFIGURE_CAD_OC >> 0 ),
|
||||
};
|
||||
|
||||
uint8_t side_detect_temp[LR20XX_RADIO_LORA_CONFIGURE_SIDE_DETECTOR_CAD_TEMP_LENGTH] = { 0 };
|
||||
for( uint8_t index_side_detector = 0; index_side_detector < n_side_detector_cad_configurations;
|
||||
index_side_detector++ )
|
||||
{
|
||||
const unsigned int local_side_detect_temp_index =
|
||||
index_side_detector * LR20XX_RADIO_LORA_CAD_SIDE_DETECTOR_CONFIGURATION_LENGTH;
|
||||
const lr20xx_radio_lora_side_detector_cad_configuration_t local_cad_side_detector_configuration =
|
||||
side_detector_cad_configurations[index_side_detector];
|
||||
side_detect_temp[local_side_detect_temp_index] = local_cad_side_detector_configuration.pnr_delta;
|
||||
side_detect_temp[local_side_detect_temp_index + 1] = local_cad_side_detector_configuration.det_peak;
|
||||
}
|
||||
|
||||
const uint16_t n_side_detect_temp =
|
||||
( uint16_t )( n_side_detector_cad_configurations * LR20XX_RADIO_LORA_CAD_SIDE_DETECTOR_CONFIGURATION_LENGTH );
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer,
|
||||
LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_CONFIGURE_CAD_CMD_LENGTH,
|
||||
side_detect_temp, n_side_detect_temp );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_set_modulation_params( const void* context,
|
||||
const lr20xx_radio_lora_mod_params_t* mod_params )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_SET_MODULATION_PARAMS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_MODULATION_PARAMS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_MODULATION_PARAMS_OC >> 0 ),
|
||||
( uint8_t ) ( ( mod_params->sf << 4 ) + mod_params->bw ),
|
||||
( uint8_t ) ( ( mod_params->cr << 4 ) + mod_params->ppm ),
|
||||
};
|
||||
|
||||
const lr20xx_status_t write_status = ( lr20xx_status_t ) lr20xx_hal_write(
|
||||
context, cbuffer, LR20XX_RADIO_LORA_SET_MODULATION_PARAMS_CMD_LENGTH, 0, 0 );
|
||||
|
||||
if( write_status != LR20XX_STATUS_OK )
|
||||
{
|
||||
return write_status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LR20XX_WORKAROUNDS_CONDITIONAL_APPLY_AUTOMATIC_DCDC_CONFIGURE( context );
|
||||
}
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_set_packet_params( const void* context,
|
||||
const lr20xx_radio_lora_pkt_params_t* pkt_params )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_SET_PACKET_PARAMS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_PACKET_PARAMS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_PACKET_PARAMS_OC >> 0 ),
|
||||
( uint8_t ) ( pkt_params->preamble_len_in_symb >> 8 ),
|
||||
( uint8_t ) ( pkt_params->preamble_len_in_symb >> 0 ),
|
||||
pkt_params->pld_len_in_bytes,
|
||||
( uint8_t ) ( ( pkt_params->pkt_mode << 2 ) + ( pkt_params->crc << 1 ) + ( pkt_params->iq << 0 ) ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_LORA_SET_PACKET_PARAMS_CMD_LENGTH, 0,
|
||||
0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_timeout_by_number_of_symbols( const void* context, uint16_t n_symbols )
|
||||
{
|
||||
if( n_symbols <= 255 )
|
||||
{
|
||||
return abstract_search_symbols( context, ( uint8_t ) n_symbols, SEARCH_SYMBOL_FORMAT_NUMBER );
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t exp = 0;
|
||||
uint8_t mant = 0;
|
||||
|
||||
lr20xx_radio_convert_nb_symb_to_mant_exp( n_symbols, &mant, &exp );
|
||||
|
||||
return lr20xx_radio_lora_configure_timeout_by_mantissa_exponent_symbols( context, mant, exp );
|
||||
}
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_timeout_by_mantissa_exponent_symbols( const void* context, uint8_t mantissa,
|
||||
uint8_t exponent )
|
||||
{
|
||||
const uint8_t n_symbols_mantissa_format = ( uint8_t ) ( ( mantissa << 3 ) + exponent );
|
||||
return abstract_search_symbols( context, n_symbols_mantissa_format, SEARCH_SYMBOL_FORMAT_MANTISSA );
|
||||
}
|
||||
|
||||
uint16_t lr20xx_radio_convert_nb_symb_to_mant_exp( const uint16_t nb_symbol, uint8_t* mant, uint8_t* exp )
|
||||
{
|
||||
uint8_t exp_loc = 0;
|
||||
uint16_t mant_loc = ( uint16_t ) ( ( nb_symbol + 1 ) >> 1 );
|
||||
|
||||
while( mant_loc > 31 )
|
||||
{
|
||||
mant_loc = ( uint16_t ) ( ( mant_loc + 3 ) >> 2 );
|
||||
exp_loc++;
|
||||
}
|
||||
|
||||
*mant = ( uint8_t ) mant_loc;
|
||||
*exp = exp_loc;
|
||||
|
||||
return ( uint16_t ) ( mant_loc << ( 2 * exp_loc + 1 ) );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_set_syncword( const void* context, uint8_t syncword )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_SET_SYNCWORD_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_SYNCWORD_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_SYNCWORD_OC >> 0 ),
|
||||
syncword,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_LORA_SET_SYNCWORD_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_side_detectors(
|
||||
const void* context, const lr20xx_radio_lora_side_detector_cfg_t* side_detector_cfgs, uint8_t n_side_detector_cfgs )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_CONFIGURE_SIDE_DETECTORS_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_LORA_CONFIGURE_SIDE_DETECTORS_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_LORA_CONFIGURE_SIDE_DETECTORS_OC >> 0 ),
|
||||
};
|
||||
|
||||
uint8_t dbuffer[3];
|
||||
|
||||
for( uint8_t i = 0; i < n_side_detector_cfgs; i++ )
|
||||
{
|
||||
const lr20xx_radio_lora_side_detector_cfg_t local_side_detector = side_detector_cfgs[i];
|
||||
dbuffer[i] = radio_lora_side_detector_cfg_to_byte( &local_side_detector );
|
||||
}
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write(
|
||||
context, cbuffer, LR20XX_RADIO_LORA_CONFIGURE_SIDE_DETECTORS_CMD_LENGTH, dbuffer, n_side_detector_cfgs );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_set_side_detector_syncwords( const void* context, const uint8_t* syncword,
|
||||
uint8_t n_syncword )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_SYNCWORD_CMD_LENGTH] = {
|
||||
( uint8_t )( LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_SYNCWORD_OC >> 8 ),
|
||||
( uint8_t )( LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_SYNCWORD_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write(
|
||||
context, cbuffer, LR20XX_RADIO_LORA_SET_SIDE_DETECTOR_SYNCWORD_CMD_LENGTH, syncword, n_syncword );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_cad_params( const void* context,
|
||||
const lr20xx_radio_lora_cad_params_t* cad_params )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_CONFIGURE_CAD_PARAMS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_CONFIGURE_CAD_PARAMS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_CONFIGURE_CAD_PARAMS_OC >> 0 ),
|
||||
cad_params->cad_symb_nb,
|
||||
( uint8_t ) cad_params->pnr_delta,
|
||||
( uint8_t ) cad_params->cad_exit_mode,
|
||||
( uint8_t ) ( cad_params->cad_timeout_in_pll_step >> 16 ),
|
||||
( uint8_t ) ( cad_params->cad_timeout_in_pll_step >> 8 ),
|
||||
( uint8_t ) ( cad_params->cad_timeout_in_pll_step >> 0 ),
|
||||
cad_params->cad_detect_peak,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_LORA_CONFIGURE_CAD_PARAMS_CMD_LENGTH, 0,
|
||||
0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_set_cad( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_SET_CAD_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_CAD_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_CAD_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_LORA_SET_CAD_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_get_rx_statistics( const void* context,
|
||||
lr20xx_radio_lora_rx_statistics_t* statistics )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_GET_RX_STATISTICS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_GET_RX_STATISTICS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_GET_RX_STATISTICS_OC >> 0 ),
|
||||
};
|
||||
|
||||
uint8_t rbuffer[LR20XX_RADIO_LORA_GET_RX_STATISTICS_RBUFFER_LENGTH] = { 0 };
|
||||
|
||||
const lr20xx_status_t status =
|
||||
( lr20xx_status_t ) lr20xx_hal_read( context, cbuffer, LR20XX_RADIO_LORA_GET_RX_STATISTICS_CMD_LENGTH, rbuffer,
|
||||
LR20XX_RADIO_LORA_GET_RX_STATISTICS_RBUFFER_LENGTH );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
statistics->n_received_packets = read_2_bytes_msbf( rbuffer + 0 );
|
||||
statistics->n_crc_errors = read_2_bytes_msbf( rbuffer + 2 );
|
||||
statistics->n_header_errors = read_2_bytes_msbf( rbuffer + 4 );
|
||||
statistics->n_false_synchronisation = read_2_bytes_msbf( rbuffer + 6 );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_get_packet_status( const void* context,
|
||||
lr20xx_radio_lora_packet_status_t* pkt_status )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_GET_PACKET_STATUS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_GET_PACKET_STATUS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_GET_PACKET_STATUS_OC >> 0 ),
|
||||
};
|
||||
|
||||
uint8_t rbuffer[LR20XX_RADIO_LORA_GET_PACKET_STATUS_RBUFFER_LENGTH] = { 0 };
|
||||
|
||||
const lr20xx_status_t status =
|
||||
( lr20xx_status_t ) lr20xx_hal_read( context, cbuffer, LR20XX_RADIO_LORA_GET_PACKET_STATUS_CMD_LENGTH, rbuffer,
|
||||
LR20XX_RADIO_LORA_GET_PACKET_STATUS_RBUFFER_LENGTH );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
pkt_status->crc = ( lr20xx_radio_lora_crc_t ) ( ( rbuffer[0] >> 4 ) & 0x01 );
|
||||
pkt_status->cr = ( lr20xx_radio_lora_cr_t ) ( rbuffer[0] & 0x0F );
|
||||
pkt_status->packet_length_bytes = rbuffer[1];
|
||||
pkt_status->snr_pkt_raw = ( int8_t ) rbuffer[2];
|
||||
pkt_status->rssi_pkt_in_dbm = ( int16_t ) ( -( ( int16_t ) rbuffer[3] ) );
|
||||
pkt_status->rssi_signal_pkt_in_dbm = ( int16_t ) ( -( ( int16_t ) rbuffer[4] ) );
|
||||
pkt_status->detector = ( rbuffer[5] >> 2 ) & 0x0F;
|
||||
pkt_status->rssi_pkt_half_dbm_count = ( rbuffer[5] >> 1 ) & 0x01;
|
||||
pkt_status->rssi_signal_pkt_half_dbm_count = ( rbuffer[5] >> 0 ) & 0x01;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_set_address( const void* context, uint8_t address_offset, uint8_t address_length,
|
||||
const uint8_t* address )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_SET_ADDRESS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_ADDRESS_OC >> 8 ), ( uint8_t ) ( LR20XX_RADIO_LORA_SET_ADDRESS_OC >> 0 ),
|
||||
( uint8_t ) ( ( address_length << 4 ) + address_offset )
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_LORA_SET_ADDRESS_CMD_LENGTH, address,
|
||||
address_length );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_radio_lora_set_freq_hop( const void* context, const lr20xx_radio_lora_hopping_cfg_t* cfg )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_SET_FREQ_HOP_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_FREQ_HOP_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_FREQ_HOP_OC >> 0 ),
|
||||
( uint8_t ) ( ( cfg->hop_ctrl << 6 ) + ( uint8_t ) ( cfg->hop_period >> 8 ) ),
|
||||
( uint8_t ) ( cfg->hop_period >> 0 ),
|
||||
};
|
||||
|
||||
uint8_t freq_hop_table[160];
|
||||
|
||||
for( uint8_t i = 0; i < cfg->nb_freq_hop; i++ )
|
||||
{
|
||||
freq_hop_table[4 * i + 0] = ( uint8_t ) ( cfg->freq_hop[i] >> 24 );
|
||||
freq_hop_table[4 * i + 1] = ( uint8_t ) ( cfg->freq_hop[i] >> 16 );
|
||||
freq_hop_table[4 * i + 2] = ( uint8_t ) ( cfg->freq_hop[i] >> 8 );
|
||||
freq_hop_table[4 * i + 3] = ( uint8_t ) ( cfg->freq_hop[i] >> 0 );
|
||||
}
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_LORA_SET_FREQ_HOP_CMD_LENGTH,
|
||||
freq_hop_table, ( uint16_t )( cfg->nb_freq_hop * 4u ) );
|
||||
}
|
||||
|
||||
uint32_t lr20xx_radio_lora_get_time_on_air_numerator( const lr20xx_radio_lora_pkt_params_t* pkt_p,
|
||||
const lr20xx_radio_lora_mod_params_t* mod_p )
|
||||
{
|
||||
const int32_t pld_len_in_bytes = pkt_p->pld_len_in_bytes;
|
||||
const int32_t sf = mod_p->sf;
|
||||
const bool pld_is_fix = pkt_p->pkt_mode == LR20XX_RADIO_LORA_PKT_IMPLICIT;
|
||||
|
||||
int32_t fine_synch = ( sf <= 6 ) ? 1 : 0;
|
||||
bool long_interleaving = ( mod_p->cr > 4 );
|
||||
|
||||
int32_t total_bytes_nb = pld_len_in_bytes + ( ( pkt_p->crc == LR20XX_RADIO_LORA_CRC_ENABLED ) ? 2 : 0 );
|
||||
int32_t tx_bits_symbol = sf - 2 * ( mod_p->ppm != 0 ? 1 : 0 );
|
||||
|
||||
int32_t ceil_numerator;
|
||||
int32_t ceil_denominator;
|
||||
|
||||
int32_t symbols_nb_data;
|
||||
int32_t tx_infobits_header;
|
||||
int32_t tx_infobits_payload;
|
||||
|
||||
if( long_interleaving )
|
||||
{
|
||||
const int32_t fec_rate_numerator = 4;
|
||||
const int32_t fec_rate_denominator = ( mod_p->cr + ( mod_p->cr == 7 ? 1 : 0 ) );
|
||||
|
||||
if( pld_is_fix )
|
||||
{
|
||||
int32_t tx_bits_symbol_start = sf - 2 + 2 * fine_synch;
|
||||
if( 8 * total_bytes_nb * fec_rate_denominator <= 7 * fec_rate_numerator * tx_bits_symbol_start )
|
||||
{
|
||||
ceil_numerator = 8 * total_bytes_nb * fec_rate_denominator;
|
||||
ceil_denominator = fec_rate_numerator * tx_bits_symbol_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t tx_codedbits_header = tx_bits_symbol_start * 8;
|
||||
ceil_numerator = 8 * fec_rate_numerator * tx_bits_symbol + 8 * total_bytes_nb * fec_rate_denominator -
|
||||
fec_rate_numerator * tx_codedbits_header;
|
||||
ceil_denominator = fec_rate_numerator * tx_bits_symbol;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_infobits_header = ( sf * 4 + fine_synch * 8 - 28 ) & ~0x07;
|
||||
if( tx_infobits_header < 8 * total_bytes_nb )
|
||||
{
|
||||
if( tx_infobits_header > 8 * pld_len_in_bytes )
|
||||
{
|
||||
tx_infobits_header = 8 * pld_len_in_bytes;
|
||||
}
|
||||
}
|
||||
tx_infobits_payload = 8 * total_bytes_nb - tx_infobits_header;
|
||||
if( tx_infobits_payload < 0 )
|
||||
{
|
||||
tx_infobits_payload = 0;
|
||||
}
|
||||
|
||||
ceil_numerator = tx_infobits_payload * fec_rate_denominator + 8 * fec_rate_numerator * tx_bits_symbol;
|
||||
ceil_denominator = fec_rate_numerator * tx_bits_symbol;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_infobits_header = sf * 4 + fine_synch * 8 - 8;
|
||||
|
||||
if( !pld_is_fix )
|
||||
{
|
||||
tx_infobits_header -= 20;
|
||||
}
|
||||
|
||||
tx_infobits_payload = 8 * total_bytes_nb - tx_infobits_header;
|
||||
|
||||
if( tx_infobits_payload < 0 ) tx_infobits_payload = 0;
|
||||
|
||||
ceil_numerator = tx_infobits_payload;
|
||||
ceil_denominator = 4 * tx_bits_symbol;
|
||||
}
|
||||
|
||||
symbols_nb_data = ( ( ceil_numerator + ceil_denominator - 1 ) / ceil_denominator );
|
||||
if( !long_interleaving )
|
||||
{
|
||||
symbols_nb_data = symbols_nb_data * ( mod_p->cr + 4 ) + 8;
|
||||
}
|
||||
const int32_t intermed = pkt_p->preamble_len_in_symb + 4 + 2 * fine_synch + symbols_nb_data;
|
||||
|
||||
return ( uint32_t ) ( ( 4 * intermed + 1 ) * ( 1 << ( sf - 2 ) ) ) - 1;
|
||||
}
|
||||
|
||||
uint32_t lr20xx_radio_lora_get_bw_in_hz( lr20xx_radio_lora_bw_t bw )
|
||||
{
|
||||
uint32_t bw_in_hz = 0;
|
||||
|
||||
switch( bw )
|
||||
{
|
||||
case LR20XX_RADIO_LORA_BW_31:
|
||||
bw_in_hz = 31250UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_41:
|
||||
bw_in_hz = 41667UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_62:
|
||||
bw_in_hz = 62500UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_83:
|
||||
bw_in_hz = 83340UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_101:
|
||||
bw_in_hz = 101563UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_125:
|
||||
bw_in_hz = 125000UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_250:
|
||||
bw_in_hz = 250000UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_500:
|
||||
bw_in_hz = 500000UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_203:
|
||||
bw_in_hz = 203000UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_406:
|
||||
bw_in_hz = 406000UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_812:
|
||||
bw_in_hz = 812000UL;
|
||||
break;
|
||||
case LR20XX_RADIO_LORA_BW_1000:
|
||||
bw_in_hz = 1000000UL;
|
||||
break;
|
||||
}
|
||||
|
||||
return bw_in_hz;
|
||||
}
|
||||
|
||||
uint32_t lr20xx_radio_lora_get_time_on_air_in_ms( const lr20xx_radio_lora_pkt_params_t* pkt_p,
|
||||
const lr20xx_radio_lora_mod_params_t* mod_p )
|
||||
{
|
||||
uint32_t numerator = 1000U * lr20xx_radio_lora_get_time_on_air_numerator( pkt_p, mod_p );
|
||||
uint32_t denominator = lr20xx_radio_lora_get_bw_in_hz( mod_p->bw );
|
||||
// Perform integral ceil()
|
||||
return ( numerator + denominator - 1 ) / denominator;
|
||||
}
|
||||
|
||||
lr20xx_radio_lora_ppm_t lr20xx_radio_lora_get_recommended_ppm_offset( lr20xx_radio_lora_sf_t sf,
|
||||
lr20xx_radio_lora_bw_t bw )
|
||||
{
|
||||
// PPM offset is LR20XX_RADIO_LORA_PPM_1_4, except for the cases that follow
|
||||
lr20xx_radio_lora_ppm_t ppm_offset = LR20XX_RADIO_LORA_PPM_1_4;
|
||||
|
||||
if( ( sf != LR20XX_RADIO_LORA_SF11 ) && ( sf != LR20XX_RADIO_LORA_SF12 ) )
|
||||
{
|
||||
// 1. If sf is not SF11 nor SF12: no ppm offset
|
||||
ppm_offset = LR20XX_RADIO_LORA_NO_PPM;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2. Else it depends on the bandwidth
|
||||
switch( bw )
|
||||
{
|
||||
case LR20XX_RADIO_LORA_BW_1000:
|
||||
case LR20XX_RADIO_LORA_BW_500:
|
||||
{
|
||||
ppm_offset = LR20XX_RADIO_LORA_NO_PPM;
|
||||
break;
|
||||
}
|
||||
case LR20XX_RADIO_LORA_BW_250:
|
||||
{
|
||||
if( sf == LR20XX_RADIO_LORA_SF11 )
|
||||
{
|
||||
ppm_offset = LR20XX_RADIO_LORA_NO_PPM;
|
||||
}
|
||||
else if( sf == LR20XX_RADIO_LORA_SF12 )
|
||||
{
|
||||
ppm_offset = LR20XX_RADIO_LORA_PPM_1_4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LR20XX_RADIO_LORA_BW_812:
|
||||
case LR20XX_RADIO_LORA_BW_406:
|
||||
case LR20XX_RADIO_LORA_BW_203:
|
||||
{
|
||||
ppm_offset = LR20XX_RADIO_LORA_PPM_1_4;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// Empty on purpose
|
||||
}
|
||||
}
|
||||
}
|
||||
return ppm_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DEFINITION --------------------------------------------
|
||||
*/
|
||||
|
||||
lr20xx_status_t abstract_search_symbols( const void* context, uint8_t n_symbols, search_symbol_format_t format )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_RADIO_LORA_SET_LORA_SEARCH_SYMBOLS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_LORA_SEARCH_SYMBOLS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_RADIO_LORA_SET_LORA_SEARCH_SYMBOLS_OC >> 0 ),
|
||||
n_symbols,
|
||||
( uint8_t ) format,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_RADIO_LORA_SET_LORA_SEARCH_SYMBOLS_CMD_LENGTH,
|
||||
0, 0 );
|
||||
}
|
||||
|
||||
uint16_t read_2_bytes_msbf( const uint8_t* buffer )
|
||||
{
|
||||
return ( uint16_t ) ( ( ( ( uint16_t ) buffer[0] ) << 8 ) + ( ( ( uint16_t ) buffer[1] ) << 0 ) );
|
||||
}
|
||||
|
||||
uint8_t radio_lora_side_detector_cfg_to_byte( const lr20xx_radio_lora_side_detector_cfg_t* side_detector_cfg )
|
||||
{
|
||||
return ( uint8_t ) ( ( side_detector_cfg->sf << 4 ) + ( side_detector_cfg->ppm << 2 ) + side_detector_cfg->iq );
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,483 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_lora.h
|
||||
*
|
||||
* @brief Radio LoRa driver definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_RADIO_LORA_H
|
||||
#define LR20XX_RADIO_LORA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lr20xx_status.h"
|
||||
#include "lr20xx_radio_lora_types.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set the modulation parameters for LoRa packets
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] mod_params Structure of LoRa modulation configuration
|
||||
*
|
||||
* The workaround @ref lr20xx_workarounds_dcdc_configure must be called for Rx sub-GHz operations with regulator
|
||||
* @ref LR20XX_SYSTEM_REG_MODE_DCDC after this function to avoid possible RF sensitivity degradation.
|
||||
*
|
||||
* @note This function automatically applies the workaround @ref lr20xx_workarounds_dcdc_configure unless the macro @p
|
||||
* LR20XX_WORKAROUNDS_DISABLE_AUTOMATIC_DCDC_CONFIGURE is defined at compile time.
|
||||
*
|
||||
* @note For RTToF operations with fractional bandwidth, the workaround @ref lr20xx_workarounds_rttof_results_deviation
|
||||
* shall be applied. Refer to its documentation for details.
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_radio_lora_get_recommended_ppm_offset, lr20xx_workarounds_dcdc_configure,
|
||||
* lr20xx_workarounds_rttof_results_deviation
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_set_modulation_params( const void* context,
|
||||
const lr20xx_radio_lora_mod_params_t* mod_params );
|
||||
|
||||
/**
|
||||
* @brief Set the packet parameters for LoRa packets
|
||||
*
|
||||
* The meaning of field pkt_params->pld_len_in_bytes depends on the packet mode selected:
|
||||
* - If LR20XX_RADIO_LORA_PKT_EXPLICIT:
|
||||
* - pld_len_in_bytes = 0 means that packets of all payload length will be accepted
|
||||
* - pld_len_in_bytes > 0 means that packet with payload length in range [1:pld_len_in_bytes] will be accepted.
|
||||
* Packet of payload length equals to 0 or strictly superior to pld_len_in_bytes will be rejected with IRQ
|
||||
* LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] pkt_params Structure of LoRa packet configuration
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_set_packet_params( const void* context,
|
||||
const lr20xx_radio_lora_pkt_params_t* pkt_params );
|
||||
|
||||
/**
|
||||
* @brief Configure a timeout given in number of LoRa symbols before stopping reception if no LoRa preamble symbols are
|
||||
* detected
|
||||
*
|
||||
* A timeout interrupt is triggered if no LoRa preamble symbol is detected during the given period.
|
||||
*
|
||||
* Setting @p n_symbols to 0 disables the mechanism.
|
||||
*
|
||||
* If @p n_symbols is higher than 255, this function automatically propagate call to @ref
|
||||
* lr20xx_radio_lora_configure_timeout_by_mantissa_exponent_symbols function, using @ref
|
||||
* lr20xx_radio_convert_nb_symb_to_mant_exp to compute mantissa, exponent components.
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] n_symbols The number of symbols to search for.
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_radio_lora_configure_timeout_by_mantissa_exponent_symbols, lr20xx_radio_convert_nb_symb_to_mant_exp
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_timeout_by_number_of_symbols( const void* context, uint16_t n_symbols );
|
||||
|
||||
/**
|
||||
* @brief Configure a timeout given in number of LoRa symbols before stopping reception if no LoRa preamble symbols are
|
||||
* detected
|
||||
*
|
||||
* A timeout interrupt is triggered if no LoRa preamble symbol is detected during the given period.
|
||||
*
|
||||
* The number of symbol is computed as \f$ N_{symbols} = mantissa ^ {2 \times exponent + 1} \f$
|
||||
*
|
||||
* Setting @p mantissa and @p exponent to get a number of symbol equal to 0 disables the mechanism.
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] mantissa Mantissa - from 0 to 31 - to compute the number of symbols
|
||||
* @param[in] exponent Exponent - from 0 to 7 - to compute the number of symbols
|
||||
*
|
||||
* @return lr20xx_status_t
|
||||
*
|
||||
* @see lr20xx_radio_lora_configure_timeout_by_number_of_symbols, lr20xx_radio_convert_nb_symb_to_mant_exp
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_timeout_by_mantissa_exponent_symbols( const void* context, uint8_t mantissa,
|
||||
uint8_t exponent );
|
||||
|
||||
/**
|
||||
* @brief Helper function to get the mantissa and exponent for a given number of symbol
|
||||
*
|
||||
* @remark This function computes the [mantissa, exponent] duple which corresponds to \f$ nb\_of\_symb \f$ : the
|
||||
* smallest value verifying both following conditions:
|
||||
* - \f$ nb\_of\_symb >= nb\_symbol \f$; and
|
||||
* - \f$ nb\_of\_symb = mant * 2 ^ { 2 * exp + 1 } \f$
|
||||
*
|
||||
* @param [in] nb_symbol Number of symbols
|
||||
* @param [out] mant Mantissa computed from @p nb_symbol
|
||||
* @param [out] exp Exponent computed from @p nb_symbol
|
||||
*
|
||||
* @returns Number of symbols corresponding to the [mantissa, exponent] duple computed with the following formula:
|
||||
* \f$ nb\_of\_symb = mant * 2 ^ { 2 * exp + 1 } \f$
|
||||
*
|
||||
* @see lr20xx_radio_lora_configure_timeout_by_mantissa_exponent_symbols,
|
||||
* lr20xx_radio_lora_configure_timeout_by_number_of_symbols
|
||||
*/
|
||||
uint16_t lr20xx_radio_convert_nb_symb_to_mant_exp( const uint16_t nb_symbol, uint8_t* mant, uint8_t* exp );
|
||||
|
||||
/**
|
||||
* @brief Configure the LoRa syncword.
|
||||
*
|
||||
* Default value is 0x12.
|
||||
* Example of typical values:
|
||||
* - LoRaWAN public network: 0x34
|
||||
* - LoRaWAN private network: 0x12
|
||||
*
|
||||
* The syncword here should be understood as the concatenation of two 4 bits blocks as follows:
|
||||
* @code{.c}
|
||||
* uint8_t sync_block_1 = BLOCK_1;
|
||||
* uint8_t sync_block_2 = BLOCK_2;
|
||||
* uint8_t syncword = ((sync_block_1 & 0x0F) << 4) | (sync_block_2 & 0x0F);
|
||||
* @endcode
|
||||
*
|
||||
* Here are some recommendations for syncword selection:
|
||||
* - @p sync_block_1 must not be 0. So that syncword 0x0x must not be used;
|
||||
* - avoid reusing a block value from another network
|
||||
*
|
||||
* Note that using different syncwords does not guarantee packet rejection. Receiver is just less likely to accept frame
|
||||
* of different syncword.
|
||||
*
|
||||
* The following table indicates the compatible block values with other chips. Note that the block values are to be
|
||||
* compared as signed integer when evaluating compatibility.
|
||||
* A line indicates a set of values that are compatible together depending on other chips.
|
||||
* Column <tt>SX126x/LR11xx/LR20xx syncword</tt> indicates block values used
|
||||
* with @ref lr20xx_radio_lora_set_syncword function and SX1276 LoRa compatibility disabled (@ref
|
||||
* lr20xx_workarounds_lora_disable_sx1276_compatibility_mode); the column <tt>LR20xx syncword SX127x compatibility</tt>
|
||||
* indicates block values used with @ref lr20xx_radio_lora_set_syncword and with SX1276 LoRa compatibility enabled
|
||||
* (@ref lr20xx_workarounds_lora_enable_sx1276_compatibility_mode).
|
||||
*
|
||||
* | SX126x/LR11xx/LR20xx syncword | LR20xx syncword SX127x compatibility | SX127x |
|
||||
* | ----------------------------- | ------------------------------------ | --------------- |
|
||||
* | 4 bits signed | 4 bits unsigned | 4 bits unsigned |
|
||||
* | -8 | | |
|
||||
* | -7 | | |
|
||||
* | -6 | | |
|
||||
* | -5 | | |
|
||||
* | -4 | | |
|
||||
* | -3 | | |
|
||||
* | -2 | | |
|
||||
* | -1 | | |
|
||||
* | 0 | 0 | 0 |
|
||||
* | 1 | 1 | 1 |
|
||||
* | 2 | 2 | 2 |
|
||||
* | 3 | 3 | 3 |
|
||||
* | 4 | 4 | 4 |
|
||||
* | 5 | 5 | 5 |
|
||||
* | 6 | 6 | 6 |
|
||||
* | 7 | 7 | 7 |
|
||||
* | | 8 | 8 |
|
||||
* | | 9 | 9 |
|
||||
* | | 10 | 10 |
|
||||
* | | 11 | 11 |
|
||||
* | | 12 | 12 |
|
||||
* | | 13 | 13 |
|
||||
* | | 14 | 14 |
|
||||
* | | 15 | 15 |
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] syncword The syncword to configure
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see LR20XX_RADIO_LORA_SYNCWORD_LORAWAN_PUBLIC_NETWORK,
|
||||
* LR20XX_RADIO_LORA_SYNCWORD_LORAWAN_PRIVATE_NETWORK
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_set_syncword( const void* context, uint8_t syncword );
|
||||
|
||||
/**
|
||||
* @brief Configure the Channel Activity Detection (CAD) operation
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] cad_params Structure of CAD parameter configuration
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_radio_lora_set_cad
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_cad_params( const void* context,
|
||||
const lr20xx_radio_lora_cad_params_t* cad_params );
|
||||
|
||||
/**
|
||||
* @brief Start Channel Activity Detection (CAD) operation
|
||||
*
|
||||
* The CAD operation is a special mode of operation where the chip is looking for the presence of LoRa preamble symbols
|
||||
* or for any Lora signal, depending on the setting in the @ref lr20xx_radio_lora_configure_cad_params command.
|
||||
*
|
||||
* At the end of the CAD operation a LR20XX_SYSTEM_IRQ_CAD_DONE is generated. If the CAD operation detects a signal, it
|
||||
* also generates a LR20XX_SYSTEM_IRQ_CAD_DETECTED.
|
||||
*
|
||||
* Depending on the CAD configuration, the chip may either go back to the configured fallback mode, or enter the
|
||||
* configured exit mode.
|
||||
*
|
||||
* If the exit mode is a radio operation the corresponding IRQ the CAD related IRQ(s) comes at the end CAD operation,
|
||||
* and radio operations IRQ(s) of exit modes comes at the end of this radio operation.
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_radio_lora_configure_cad_params
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_set_cad( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Get the internal statistics of received packets
|
||||
*
|
||||
* The internal statistics are reset on:
|
||||
* - Power On Reset (POR)
|
||||
* - sleep without memory retention
|
||||
* - call to lr20xx_radio_common_reset_rx_stats
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[out] statistics Pointer to a structure of statistic to populate with internal statistics
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_radio_common_reset_rx_stats
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_get_rx_statistics( const void* context,
|
||||
lr20xx_radio_lora_rx_statistics_t* statistics );
|
||||
|
||||
/**
|
||||
* @brief Get the status of the last received LoRa packet
|
||||
*
|
||||
* Status is valid only after the end of a packet reception or CAD done and until the next LoRa packet configuration.
|
||||
*
|
||||
* CRC and coding rate source depends on the packet mode configured on the receiver:
|
||||
* - If LR20XX_RADIO_LORA_PKT_EXPLICIT: it is obtained from the received payload
|
||||
* - If LR20XX_RADIO_LORA_PKT_IMPLICIT: it is obtained from the receiver configuration
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[out] pkt_status Pointer to a structure of packet status to populate
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_get_packet_status( const void* context,
|
||||
lr20xx_radio_lora_packet_status_t* pkt_status );
|
||||
|
||||
/**
|
||||
* @brief Set the address for filtering in reception
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] address_offset Offset in byte of the address field in the payload (header not counted)
|
||||
* @param[in] address_length Address length in byte - in [0:8], 0 disables LoRa address filtering
|
||||
* @param[in] address Address
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_set_address( const void* context, uint8_t address_offset, uint8_t address_length,
|
||||
const uint8_t* address );
|
||||
|
||||
/**
|
||||
* @brief Configure LoRa intra-packet frequency hopping
|
||||
*
|
||||
* If the intra-packet frequency hopping must be compatible with SX1276, then the workaround @ref
|
||||
* lr20xx_workarounds_lora_freq_hop_enable_sx1276_compatibility_mode must be called after calling @ref
|
||||
* lr20xx_radio_lora_set_freq_hop.
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] cfg Frequency hopping configuration
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*
|
||||
* @see lr20xx_workarounds_lora_freq_hop_enable_sx1276_compatibility_mode
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_set_freq_hop( const void* context, const lr20xx_radio_lora_hopping_cfg_t* cfg );
|
||||
|
||||
/**
|
||||
* @brief Configure the LoRa Channel Activity Detection (CAD) side detectors
|
||||
*
|
||||
* Up to three CAD side detectors can be configured.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param side_detector_cad_configurations Array of side detector CAD configurations
|
||||
* @param n_side_detector_cad_configurations Number of CAD side detector configurations in @p
|
||||
* side_detector_cad_configurations. It is up to the caller to ensure that @p side_detector_cad_configurations contains
|
||||
* at least @p n_side_detector_cad_configurations elements
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_side_detector_cad(
|
||||
const void* context, const lr20xx_radio_lora_side_detector_cad_configuration_t* side_detector_cad_configurations,
|
||||
uint8_t n_side_detector_cad_configurations );
|
||||
|
||||
/**
|
||||
* @brief Configure LoRa side detectors
|
||||
*
|
||||
* The side detectors allow to receive on multiple spreading factors, but on the same bandwidth as main detector. Up to
|
||||
* three side detectors can be configured.
|
||||
*
|
||||
* To disable all side detectors, there are 2 options:
|
||||
* - call this command with @p n_side_detector_cfgs set to 0.
|
||||
* - call @ref lr20xx_radio_lora_set_modulation_params
|
||||
*
|
||||
* Once a packet is received, it is possible to know which SF has been demodulated thanks to @ref
|
||||
* lr20xx_radio_lora_get_packet_status.
|
||||
*
|
||||
* Specificities related to the side detector configuration:
|
||||
* - For normal Rx operations, the SF configured with @ref lr20xx_radio_lora_set_modulation_params must be lower than
|
||||
* the SF of the side detectors
|
||||
* - For CAD operations, the SF configured with @ref lr20xx_radio_lora_set_modulation_params must be higher than the
|
||||
* SF of the side detectors
|
||||
* - With BW set to @ref LR20XX_RADIO_LORA_BW_500 or higher, maximum 2 side detectors are allowed except if the SF
|
||||
* configured with @ref lr20xx_radio_lora_set_modulation_params is @ref LR20XX_RADIO_LORA_SF10 or higher where only 1
|
||||
* side detector is allowed
|
||||
* - All SF must be different
|
||||
* - Difference between the highest and the lowest SF must be less than or equal to 4
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] side_detector_cfgs Array of side detector configuration to set. It is up to the caller to ensure
|
||||
* there are at least @p n_side_detector_cfgs
|
||||
* @param[in] n_side_detector_cfgs Number of side detector to configure. Un-configured side detectors are
|
||||
* disabled. Value must be in range [0:3] included.
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_configure_side_detectors(
|
||||
const void* context, const lr20xx_radio_lora_side_detector_cfg_t* side_detector_cfgs,
|
||||
uint8_t n_side_detector_cfgs );
|
||||
|
||||
/**
|
||||
* @brief Configure the LoRa syncwords for side detectors
|
||||
*
|
||||
* @param[in] context Chip implementation context
|
||||
* @param[in] syncword Array of side detector syncword to set. It is up to the caller to ensure there are at least @p
|
||||
* n_syncword
|
||||
* @param[in] n_syncword Number of side detector syncword configure. Un-configured syncword are set to a default value.
|
||||
* Value must be in range [0:3] included.
|
||||
*
|
||||
* @return lr20xx_status_t Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_radio_lora_set_side_detector_syncwords( const void* context, const uint8_t* syncword,
|
||||
uint8_t n_syncword );
|
||||
|
||||
/**
|
||||
* @brief Compute the numerator for LoRa time-on-air computation.
|
||||
*
|
||||
* @remark To get the actual time-on-air in seconds, this value has to be divided by the LoRa bandwidth in Hertz.
|
||||
*
|
||||
* @param [in] pkt_p Pointer to the structure holding the LoRa packet parameters
|
||||
* @param [in] mod_p Pointer to the structure holding the LoRa modulation parameters
|
||||
*
|
||||
* @returns LoRa time-on-air numerator
|
||||
*/
|
||||
uint32_t lr20xx_radio_lora_get_time_on_air_numerator( const lr20xx_radio_lora_pkt_params_t* pkt_p,
|
||||
const lr20xx_radio_lora_mod_params_t* mod_p );
|
||||
|
||||
/**
|
||||
* @brief Get the actual value in Hertz of a given LoRa bandwidth
|
||||
*
|
||||
* @param [in] bw LoRa bandwidth parameter
|
||||
*
|
||||
* @returns Actual LoRa bandwidth in Hertz
|
||||
*/
|
||||
uint32_t lr20xx_radio_lora_get_bw_in_hz( lr20xx_radio_lora_bw_t bw );
|
||||
|
||||
/*!
|
||||
* @brief Get the time on air in ms for LoRa transmission
|
||||
*
|
||||
* @param [in] pkt_p Pointer to a structure holding the LoRa packet parameters
|
||||
* @param [in] mod_p Pointer to a structure holding the LoRa modulation parameters
|
||||
*
|
||||
* @returns Time-on-air value in ms for LoRa transmission
|
||||
*/
|
||||
uint32_t lr20xx_radio_lora_get_time_on_air_in_ms( const lr20xx_radio_lora_pkt_params_t* pkt_p,
|
||||
const lr20xx_radio_lora_mod_params_t* mod_p );
|
||||
|
||||
/**
|
||||
* @brief Helper function to compute recommended ppm offset value from SF and BW
|
||||
*
|
||||
* This helper function provides recommended PPM offset configuration based on the following rules
|
||||
* - @ref LR20XX_RADIO_LORA_NO_PPM for all spreading factors, except for @ref LR20XX_RADIO_LORA_SF11 and @ref
|
||||
* LR20XX_RADIO_LORA_SF12
|
||||
* - @ref LR20XX_RADIO_LORA_PPM_1_4 for bandwidths @ref LR20XX_RADIO_LORA_BW_812, @ref LR20XX_RADIO_LORA_BW_406 and
|
||||
* @ref LR20XX_RADIO_LORA_BW_203 to ensure SX128x compatibility
|
||||
* - @ref LR20XX_RADIO_LORA_NO_PPM for bandwidths @ref LR20XX_RADIO_LORA_BW_1000 and @ref LR20XX_RADIO_LORA_BW_500
|
||||
* - @ref LR20XX_RADIO_LORA_NO_PPM for bandwidth @ref LR20XX_RADIO_LORA_BW_250 and spreading factor @ref
|
||||
* LR20XX_RADIO_LORA_SF11
|
||||
* - @ref LR20XX_RADIO_LORA_PPM_1_4 for bandwidth @ref LR20XX_RADIO_LORA_BW_250 and spreading factor @ref
|
||||
* LR20XX_RADIO_LORA_SF12
|
||||
* - @ref LR20XX_RADIO_LORA_PPM_1_4 otherwise
|
||||
*
|
||||
* | Bandwidths | @ref LR20XX_RADIO_LORA_SF12 | @ref LR20XX_RADIO_LORA_SF11 | other spreading factors |
|
||||
* | -- | -- | -- | -- |
|
||||
* | @ref LR20XX_RADIO_LORA_BW_1000 | @ref LR20XX_RADIO_LORA_NO_PPM |||
|
||||
* | @ref LR20XX_RADIO_LORA_BW_500 | @ref LR20XX_RADIO_LORA_NO_PPM |||
|
||||
* | @ref LR20XX_RADIO_LORA_BW_250 | @ref LR20XX_RADIO_LORA_PPM_1_4 | @ref LR20XX_RADIO_LORA_NO_PPM ||
|
||||
* | @ref LR20XX_RADIO_LORA_BW_812 | @ref LR20XX_RADIO_LORA_PPM_1_4 || @ref LR20XX_RADIO_LORA_NO_PPM |
|
||||
* | @ref LR20XX_RADIO_LORA_BW_406 | @ref LR20XX_RADIO_LORA_PPM_1_4 || @ref LR20XX_RADIO_LORA_NO_PPM |
|
||||
* | @ref LR20XX_RADIO_LORA_BW_203 | @ref LR20XX_RADIO_LORA_PPM_1_4 || @ref LR20XX_RADIO_LORA_NO_PPM |
|
||||
* | other bandwidths | @ref LR20XX_RADIO_LORA_PPM_1_4 || @ref LR20XX_RADIO_LORA_NO_PPM |
|
||||
*
|
||||
* @param sf Spreading factor
|
||||
* @param bw Bandwidth
|
||||
*
|
||||
* @return The recommended PPM offset configuration for the given spreading factor and bandwidth
|
||||
*
|
||||
* @see lr20xx_radio_lora_set_modulation_params
|
||||
*/
|
||||
lr20xx_radio_lora_ppm_t lr20xx_radio_lora_get_recommended_ppm_offset( lr20xx_radio_lora_sf_t sf,
|
||||
lr20xx_radio_lora_bw_t bw );
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_RADIO_LORA_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,335 @@
|
||||
/*!
|
||||
* @file lr20xx_radio_lora_types.h
|
||||
*
|
||||
* @brief LoRa radio types driver definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_RADIO_LORA_TYPES_H
|
||||
#define LR20XX_RADIO_LORA_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief LoRa syncword value for LoRaWAN public networks
|
||||
*/
|
||||
#define LR20XX_RADIO_LORA_SYNCWORD_LORAWAN_PUBLIC_NETWORK ( 0x34 )
|
||||
|
||||
/**
|
||||
* @brief LoRa syncword value for LoRaWAN private networks
|
||||
*/
|
||||
#define LR20XX_RADIO_LORA_SYNCWORD_LORAWAN_PRIVATE_NETWORK ( 0x12 )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief LoRa Spreading Factor
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_SF5 = 0x05, //!< Spreading factor 5
|
||||
LR20XX_RADIO_LORA_SF6 = 0x06, //!< Spreading factor 6
|
||||
LR20XX_RADIO_LORA_SF7 = 0x07, //!< Spreading factor 7
|
||||
LR20XX_RADIO_LORA_SF8 = 0x08, //!< Spreading factor 8
|
||||
LR20XX_RADIO_LORA_SF9 = 0x09, //!< Spreading factor 9
|
||||
LR20XX_RADIO_LORA_SF10 = 0x0A, //!< Spreading factor 10
|
||||
LR20XX_RADIO_LORA_SF11 = 0x0B, //!< Spreading factor 11
|
||||
LR20XX_RADIO_LORA_SF12 = 0x0C, //!< Spreading factor 12
|
||||
} lr20xx_radio_lora_sf_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa Bandwidth
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_BW_31 = 0x02, //!< Bandwidth 31.25 kHz
|
||||
LR20XX_RADIO_LORA_BW_41 = 0x0A, //!< Bandwidth 41.67 kHz
|
||||
LR20XX_RADIO_LORA_BW_83 = 0x0B, //!< Bandwidth 83.34 kHz
|
||||
LR20XX_RADIO_LORA_BW_62 = 0x03, //!< Bandwidth 62.50 kHz
|
||||
LR20XX_RADIO_LORA_BW_101 = 0x0C, //!< Bandwidth 101.5625 kHz
|
||||
LR20XX_RADIO_LORA_BW_125 = 0x04, //!< Bandwidth 125 kHz
|
||||
LR20XX_RADIO_LORA_BW_203 = 0x0D, //!< Bandwidth 203 kHz
|
||||
LR20XX_RADIO_LORA_BW_250 = 0x05, //!< Bandwidth 250 kHz
|
||||
LR20XX_RADIO_LORA_BW_406 = 0x0E, //!< Bandwidth 406 kHz
|
||||
LR20XX_RADIO_LORA_BW_500 = 0x06, //!< Bandwidth 500 kHz
|
||||
LR20XX_RADIO_LORA_BW_812 = 0x0F, //!< Bandwidth 812 kHz
|
||||
LR20XX_RADIO_LORA_BW_1000 = 0x07, //!< Bandwidth 1000 kHz
|
||||
} lr20xx_radio_lora_bw_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa Coding Rate
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_NO_CR = 0x00, //!< No Coding Rate
|
||||
LR20XX_RADIO_LORA_CR_4_5 = 0x01, //!< Short Interleaver Parity code
|
||||
LR20XX_RADIO_LORA_CR_4_6 = 0x02, //!< Short Interleaver Hamming code 2/3
|
||||
LR20XX_RADIO_LORA_CR_4_7 = 0x03, //!< Short Interleaver Hamming code 7/5
|
||||
LR20XX_RADIO_LORA_CR_4_8 = 0x04, //!< Short Interleaver Hamming code 1/2
|
||||
LR20XX_RADIO_LORA_CR_LI_4_5 = 0x05, //!< Long Interleaver Parity code
|
||||
LR20XX_RADIO_LORA_CR_LI_4_6 = 0x06, //!< Long Interleaver Hamming code 2/3
|
||||
LR20XX_RADIO_LORA_CR_LI_4_8 = 0x07, //!< Long Interleaver Hamming code 1/2
|
||||
LR20XX_RADIO_LORA_CR_LI_CONVOLUTIONAL_4_6 = 0x08, //!< Long Interleaver Convolutional code 2/3
|
||||
LR20XX_RADIO_LORA_CR_LI_CONVOLUTIONAL_4_8 = 0x09, //!< Long Interleaver Convolutional code 1/2
|
||||
} lr20xx_radio_lora_cr_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa PPM Offset
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_NO_PPM = 0x00, //!< No PPM offset: use full range of modulation
|
||||
LR20XX_RADIO_LORA_PPM_1_4 = 0x01, //!< 1 bin every 4
|
||||
} lr20xx_radio_lora_ppm_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa header packet configuration
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_PKT_EXPLICIT = 0x00, //!< (aka. variable length packet) The packet is sent with a header
|
||||
//!< containing payload length so the receiver adapts to the payload length
|
||||
LR20XX_RADIO_LORA_PKT_IMPLICIT =
|
||||
0x01, //!< (aka. fixed length packet) The packet is sent without header so the receiver must be configured to
|
||||
//!< receive the same payload length as the transmitted one
|
||||
} lr20xx_radio_lora_pkt_mode_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa Cyclic Redundancy Check packet configuration
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_CRC_DISABLED = 0x00, //!< CRC is not appended to the packet sent over the air
|
||||
LR20XX_RADIO_LORA_CRC_ENABLED =
|
||||
0x01, //!< CRC is appended to the packet sent over the air, and checked upon reception
|
||||
} lr20xx_radio_lora_crc_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa IQ packet configuration
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_IQ_STANDARD = 0x00, //!< IQ standard
|
||||
LR20XX_RADIO_LORA_IQ_INVERTED = 0x01, //!< IQ inverted
|
||||
} lr20xx_radio_lora_iq_t;
|
||||
|
||||
/**
|
||||
* @brief Exit mode of LoRa Channel Activity Detection (CAD) operation
|
||||
*
|
||||
* Refer to @ref lr20xx_radio_common_set_rx_tx_fallback_mode for details regarding configuration of fallback mode.
|
||||
*
|
||||
* @see lr20xx_radio_common_set_rx_tx_fallback_mode
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_CAD_EXIT_MODE_STANDBYRC =
|
||||
0x00, //!< The chip goes to fallback mode after CAD operation, no matter what the result of CAD is
|
||||
LR20XX_RADIO_LORA_CAD_EXIT_MODE_RX = 0x01, //!< If the CAD operation detects an activity, the chip enters in RX
|
||||
//!< mode. Otherwise it enters in fallback mode
|
||||
LR20XX_RADIO_LORA_CAD_EXIT_MODE_TX = 0x10, //!< If the CAD operation does not detect an activity, the chip enters
|
||||
//!< in TX mode. Otherwise it enters in fallback mode
|
||||
} lr20xx_radio_lora_cad_exit_mode_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa intra-packet frequency hopping control
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_RADIO_LORA_HOPPING_CTRL_DISABLED = 0x00, //!< LoRa intra-packet frequency hopping disabled
|
||||
LR20XX_RADIO_LORA_HOPPING_CTRL_ENABLED = 0x01, //!< LoRa intra-packet frequency hopping enabled
|
||||
} lr20xx_radio_lora_hopping_ctrl_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa Channel Activity Detection (CAD) parameters
|
||||
*
|
||||
* Parameter @ref lr20xx_radio_lora_cad_params_s.cad_detect_peak is used to tune the sensitivity of Channel Activity
|
||||
* Detection. It depends on Spreading Factor and @ref lr20xx_radio_lora_cad_params_s.cad_symb_nb.
|
||||
* Increasing value of lr20xx_radio_lora_cad_params_s.cad_detect_peak decreases CAD sensitivity.
|
||||
* Decreasing value of lr20xx_radio_lora_cad_params_s.cad_detect_peak increases CAD sensitivity, but increase the false
|
||||
* detections.
|
||||
*
|
||||
* Recommended values for @ref lr20xx_radio_lora_cad_params_s.cad_detect_peak, depending on @ref
|
||||
* lr20xx_radio_lora_cad_params_s.cad_symb_nb and the configured Spreading Factor are:
|
||||
*
|
||||
* | Spreading factor | 1 symbol | 2 symbols | 3 symbols | 4 symbols |
|
||||
* | --------------------------- | -------- | --------- | --------- | --------- |
|
||||
* | @ref LR20XX_RADIO_LORA_SF5 | 60 | 56 | 51 | 51 |
|
||||
* | @ref LR20XX_RADIO_LORA_SF6 | 60 | 56 | 51 | 51 |
|
||||
* | @ref LR20XX_RADIO_LORA_SF7 | 60 | 56 | 52 | 51 |
|
||||
* | @ref LR20XX_RADIO_LORA_SF8 | 64 | 58 | 54 | 54 |
|
||||
* | @ref LR20XX_RADIO_LORA_SF9 | 64 | 58 | 56 | 56 |
|
||||
* | @ref LR20XX_RADIO_LORA_SF10 | 66 | 60 | 60 | 60 |
|
||||
* | @ref LR20XX_RADIO_LORA_SF11 | 70 | 64 | 60 | 60 |
|
||||
* | @ref LR20XX_RADIO_LORA_SF12 | 74 | 68 | 65 | 64 |
|
||||
*
|
||||
* The CAD can be configured in best-effort CAD operation to allow early CAD operation to stop if a clear non-detection
|
||||
* is obtained. The best-effort CAD is enabled by setting @ref lr20xx_radio_lora_cad_params_s.pnr_delta to a non-zero
|
||||
* value. The recommended @ref lr20xx_radio_lora_cad_params_s.pnr_delta value to use for best-effort CAD is 8, and 0 to
|
||||
* disable the best-effort CAD.
|
||||
*
|
||||
* @ref lr20xx_radio_lora_cad_params_s.cad_timeout_in_pll_step is given in PPL step of 31.25us.
|
||||
*/
|
||||
typedef struct lr20xx_radio_lora_cad_params_s
|
||||
{
|
||||
uint8_t cad_symb_nb; //!< Number of symbols to search for CAD operation
|
||||
uint8_t pnr_delta; //!< Peak to Noise Ratio. Possible values are:
|
||||
//!< - 0: then the exact number of requested symbols @p cad_symb_nb is used to determine the
|
||||
//!< activity detection;
|
||||
//!< - 8: best-effort CAD is activated.
|
||||
lr20xx_radio_lora_cad_exit_mode_t cad_exit_mode; //!< Action taken automatically at the end of CAD operation
|
||||
uint32_t cad_timeout_in_pll_step; //!< Timeout in PLL steps used while in exit mode, if applicable. Max value is
|
||||
//!< 0x00FFFFFF PLL steps
|
||||
uint8_t cad_detect_peak; //!< Ratio for CAD between correlator peak and average to identify a peak as a detection
|
||||
//!< (default: 0x32)
|
||||
} lr20xx_radio_lora_cad_params_t;
|
||||
|
||||
/**
|
||||
* @brief Packet parameters for LoRa packet
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t preamble_len_in_symb; //!< LoRa Preamble length [symbols]
|
||||
lr20xx_radio_lora_pkt_mode_t pkt_mode; //!< LoRa packet mode configuration
|
||||
uint8_t pld_len_in_bytes; //!< LoRa Payload length [bytes]
|
||||
lr20xx_radio_lora_crc_t crc; //!< LoRa CRC configuration
|
||||
lr20xx_radio_lora_iq_t iq; //!< LoRa IQ configuration
|
||||
} lr20xx_radio_lora_pkt_params_t;
|
||||
|
||||
/**
|
||||
* @brief Modulation configuration for LoRa packet
|
||||
*
|
||||
* Refer to @ref lr20xx_radio_lora_get_recommended_ppm_offset for recommended values concerning @p ppm field.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
lr20xx_radio_lora_sf_t sf; //!< Spreading factor
|
||||
lr20xx_radio_lora_bw_t bw; //!< Bandwidth
|
||||
lr20xx_radio_lora_cr_t cr; //!< Coding rate
|
||||
lr20xx_radio_lora_ppm_t ppm; //!< PPM offset
|
||||
} lr20xx_radio_lora_mod_params_t;
|
||||
|
||||
/**
|
||||
* @brief Reception statistics for LoRa packet
|
||||
*/
|
||||
typedef struct lr20xx_radio_lora_rx_statistics_s
|
||||
{
|
||||
uint16_t n_received_packets; //!< Number of received packets
|
||||
uint16_t n_crc_errors; //!< Number of received packets with CRC error
|
||||
uint16_t n_header_errors; //!< Number of received packets with header error (Rx configured in
|
||||
//!< LR20XX_RADIO_LORA_PKT_EXPLICIT and header CRC check failed)
|
||||
uint16_t n_false_synchronisation; //!< Number of false synchronisation (preamble detected but syncword not
|
||||
//!< detected, probably preamble detected on noise)
|
||||
} lr20xx_radio_lora_rx_statistics_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa packet status fields
|
||||
*/
|
||||
typedef struct lr20xx_radio_lora_packet_status_s
|
||||
{
|
||||
uint8_t packet_length_bytes; //!< Length of last received packet in bytes
|
||||
lr20xx_radio_lora_crc_t crc; //!< CRC presence of the received packet
|
||||
lr20xx_radio_lora_cr_t cr; //!< Coding rate of the received packet
|
||||
uint8_t detector; //!< Identifier of detectors that received / detected the packet
|
||||
int16_t rssi_pkt_in_dbm; //!< Average energy in dBm at the input of the chip over the last packet received
|
||||
uint8_t rssi_pkt_half_dbm_count; //!< Count of 0.5 dBm to subtract to rssi_pkt_in_dbm value in dBm
|
||||
int8_t snr_pkt_raw; //!< Estimation of the SNR on last packet received expressed in 0.25dB
|
||||
int16_t
|
||||
rssi_signal_pkt_in_dbm; //!< Estimation of the mean energy of the LoRa signal over the last packet received.
|
||||
//!< Equivalent to rssi_pkt_in_dbm if snr_pkt_raw is positive, to rssi_pkt_in_dbm
|
||||
//!< + (snr_pkt_raw/4) if snr_pkt_raw is negative
|
||||
uint8_t rssi_signal_pkt_half_dbm_count; //!< Count of 0.5 dBm to subtract to rssi_signal_pkt_in_dbm value in dBm
|
||||
} lr20xx_radio_lora_packet_status_t;
|
||||
|
||||
/**
|
||||
* @brief LoRa intra-packet hopping configuration
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
lr20xx_radio_lora_hopping_ctrl_t hop_ctrl; //!< LoRa intra-packet frequency hopping control
|
||||
uint16_t hop_period; //!< Number of LoRa symbols between two RF frequency changes (valid values in [0:16383])
|
||||
uint32_t* freq_hop; //!< List of frequencies. It is up to the caller to ensure that the array pointed to contains
|
||||
//!< at least nb_freq_hop items
|
||||
uint8_t nb_freq_hop; //!< Number of frequencies in @ref freq_hop. Possible value in [0:40] included
|
||||
} lr20xx_radio_lora_hopping_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration structure of Channel Activity Detection (CAD) for side detectors
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pnr_delta;
|
||||
uint8_t det_peak;
|
||||
} lr20xx_radio_lora_side_detector_cad_configuration_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration of LoRa side detector
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
lr20xx_radio_lora_sf_t sf; //!< Spreading factor
|
||||
lr20xx_radio_lora_ppm_t ppm; //!< PPM offset
|
||||
lr20xx_radio_lora_iq_t iq; //!< LoRa IQ configuration
|
||||
} lr20xx_radio_lora_side_detector_cfg_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_RADIO_LORA_TYPES_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,257 @@
|
||||
/*!
|
||||
* @file lr20xx_regmem.c
|
||||
*
|
||||
* @brief Register/memory driver implementation for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "lr20xx_regmem.h"
|
||||
#include "lr20xx_hal.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE MACROS-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE CONSTANTS -------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LR20XX_REGMEM_WRITE_REGMEM32_CMD_LENGTH ( 2 + 3 )
|
||||
#define LR20XX_REGMEM_WRITE_REGMEM32_MASK_CMD_LENGTH ( 2 + 3 + 4 + 4 )
|
||||
#define LR20XX_REGMEM_READ_REGMEM32_CMD_LENGTH ( 2 + 3 + 1 )
|
||||
|
||||
#define LR20XX_REGMEM_BUFFER_SIZE_MAX ( 256 )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE TYPES -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Operating codes for register and memory related operations
|
||||
*/
|
||||
enum
|
||||
{
|
||||
LR20XX_REGMEM_WRITE_REGMEM32_OC = 0x0104,
|
||||
LR20XX_REGMEM_WRITE_REGMEM32_MASK_OC = 0x0105,
|
||||
LR20XX_REGMEM_READ_REGMEM32_OC = 0x0106,
|
||||
};
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE VARIABLES -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DECLARATION -------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Helper function that fill both cbuffer with opcode and memory address
|
||||
*
|
||||
* It is typically used in read/write regmem32 functions.
|
||||
*
|
||||
* @warning It is up to the caller to ensure cbuffer is big enough to contain opcode and address!
|
||||
*/
|
||||
static void lr20xx_regmem_fill_cbuffer_opcode_address( uint8_t* cbuffer, uint16_t opcode, uint32_t address );
|
||||
|
||||
/*!
|
||||
* @brief Helper function that fill both cbuffer with opcode memory address, and data length to read
|
||||
*
|
||||
* It is typically used in read functions.
|
||||
*
|
||||
* @warning It is up to the caller to ensure cbuffer is big enough to contain opcode and address!
|
||||
*/
|
||||
static void lr20xx_regmem_fill_cbuffer_opcode_address_length( uint8_t* cbuffer, uint16_t opcode, uint32_t address,
|
||||
uint8_t length );
|
||||
|
||||
/*!
|
||||
* @brief Helper function that fill both cbuffer with data
|
||||
*
|
||||
* It is typically used in write write regmem32 functions.
|
||||
*
|
||||
* @warning It is up to the caller to ensure cdata is big enough to contain all data!
|
||||
*/
|
||||
static void lr20xx_regmem_fill_cdata( uint8_t* cdata, const uint32_t* data, uint8_t data_length );
|
||||
|
||||
/*!
|
||||
* @brief Helper function that fill both cbuffer and cdata buffers with opcode, memory address and data
|
||||
*
|
||||
* It is typically used to factorize and write regmem32 operations. Behind the scene it calls the other helpers
|
||||
* lr20xx_regmem_fill_cbuffer_opcode_address and lr20xx_regmem_fill_cdata.
|
||||
*
|
||||
* @warning It is up to the caller to ensure cbuffer and cdata are big enough to contain their respective information!
|
||||
*/
|
||||
static void lr20xx_regmem_fill_cbuffer_cdata_opcode_address_data( uint8_t* cbuffer, uint8_t* cdata, uint16_t opcode,
|
||||
uint32_t address, const uint32_t* data,
|
||||
uint8_t data_length );
|
||||
|
||||
/*!
|
||||
* @brief Helper function that convert an array of uint8_t into an array of uint32_t
|
||||
*
|
||||
* Typically used in the read function returning uint32_t array.
|
||||
*
|
||||
* @warning It is up to the caller to ensure the raw_buffer is of length at least "out_buffer_length *
|
||||
* sizeof(uint32_t)"!
|
||||
*/
|
||||
static void lr20xx_regmem_fill_out_buffer_from_raw_buffer( uint32_t* out_buffer, const uint8_t* raw_buffer,
|
||||
uint8_t out_buffer_length );
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS DEFINITION ---------------------------------------------
|
||||
*/
|
||||
|
||||
lr20xx_status_t lr20xx_regmem_write_regmem32( const void* context, const uint32_t address, const uint32_t* buffer,
|
||||
const uint8_t length )
|
||||
{
|
||||
uint8_t cbuffer[LR20XX_REGMEM_WRITE_REGMEM32_CMD_LENGTH];
|
||||
uint8_t cdata[LR20XX_REGMEM_BUFFER_SIZE_MAX];
|
||||
|
||||
if( length > LR20XX_REGMEM_MAX_WRITE_READ_WORDS )
|
||||
{
|
||||
return LR20XX_STATUS_ERROR;
|
||||
}
|
||||
|
||||
lr20xx_regmem_fill_cbuffer_cdata_opcode_address_data( cbuffer, cdata, LR20XX_REGMEM_WRITE_REGMEM32_OC, address,
|
||||
buffer, length );
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_REGMEM_WRITE_REGMEM32_CMD_LENGTH, cdata,
|
||||
( uint16_t )( length * sizeof( uint32_t ) ) );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_regmem_write_regmem32_mask( const void* context, const uint32_t address, const uint32_t mask,
|
||||
const uint32_t data )
|
||||
{
|
||||
uint8_t cbuffer[LR20XX_REGMEM_WRITE_REGMEM32_MASK_CMD_LENGTH];
|
||||
|
||||
lr20xx_regmem_fill_cbuffer_opcode_address( cbuffer, LR20XX_REGMEM_WRITE_REGMEM32_MASK_OC, address );
|
||||
|
||||
cbuffer[5] = ( uint8_t ) ( mask >> 24 );
|
||||
cbuffer[6] = ( uint8_t ) ( mask >> 16 );
|
||||
cbuffer[7] = ( uint8_t ) ( mask >> 8 );
|
||||
cbuffer[8] = ( uint8_t ) ( mask >> 0 );
|
||||
|
||||
cbuffer[9] = ( uint8_t ) ( data >> 24 );
|
||||
cbuffer[10] = ( uint8_t ) ( data >> 16 );
|
||||
cbuffer[11] = ( uint8_t ) ( data >> 8 );
|
||||
cbuffer[12] = ( uint8_t ) ( data >> 0 );
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_REGMEM_WRITE_REGMEM32_MASK_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_regmem_read_regmem32( const void* context, const uint32_t address, uint32_t* buffer,
|
||||
const uint8_t length )
|
||||
{
|
||||
uint8_t cbuffer[LR20XX_REGMEM_READ_REGMEM32_CMD_LENGTH];
|
||||
|
||||
if( length > LR20XX_REGMEM_MAX_WRITE_READ_WORDS )
|
||||
{
|
||||
return LR20XX_STATUS_ERROR;
|
||||
}
|
||||
|
||||
lr20xx_regmem_fill_cbuffer_opcode_address_length( cbuffer, LR20XX_REGMEM_READ_REGMEM32_OC, address, length );
|
||||
|
||||
lr20xx_status_t status =
|
||||
( lr20xx_status_t ) lr20xx_hal_read( context, cbuffer, LR20XX_REGMEM_READ_REGMEM32_CMD_LENGTH,
|
||||
( uint8_t* ) buffer, ( uint16_t )( length * sizeof( uint32_t ) ) );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
lr20xx_regmem_fill_out_buffer_from_raw_buffer( buffer, ( const uint8_t* ) buffer, length );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DEFINITION --------------------------------------------
|
||||
*/
|
||||
|
||||
void lr20xx_regmem_fill_cbuffer_opcode_address( uint8_t* cbuffer, uint16_t opcode, uint32_t address )
|
||||
{
|
||||
cbuffer[0] = ( uint8_t ) ( opcode >> 8 );
|
||||
cbuffer[1] = ( uint8_t ) ( opcode >> 0 );
|
||||
|
||||
cbuffer[2] = ( uint8_t ) ( address >> 16 );
|
||||
cbuffer[3] = ( uint8_t ) ( address >> 8 );
|
||||
cbuffer[4] = ( uint8_t ) ( address >> 0 );
|
||||
}
|
||||
|
||||
void lr20xx_regmem_fill_cbuffer_opcode_address_length( uint8_t* cbuffer, uint16_t opcode, uint32_t address,
|
||||
uint8_t length )
|
||||
{
|
||||
lr20xx_regmem_fill_cbuffer_opcode_address( cbuffer, opcode, address );
|
||||
cbuffer[5] = length;
|
||||
}
|
||||
|
||||
void lr20xx_regmem_fill_cdata( uint8_t* cdata, const uint32_t* data, uint8_t data_length )
|
||||
{
|
||||
for( uint16_t index = 0; index < data_length; index++ )
|
||||
{
|
||||
uint8_t* cdata_local = &cdata[index * sizeof( uint32_t )];
|
||||
|
||||
cdata_local[0] = ( uint8_t ) ( data[index] >> 24 );
|
||||
cdata_local[1] = ( uint8_t ) ( data[index] >> 16 );
|
||||
cdata_local[2] = ( uint8_t ) ( data[index] >> 8 );
|
||||
cdata_local[3] = ( uint8_t ) ( data[index] >> 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void lr20xx_regmem_fill_cbuffer_cdata_opcode_address_data( uint8_t* cbuffer, uint8_t* cdata, uint16_t opcode,
|
||||
uint32_t address, const uint32_t* data, uint8_t data_length )
|
||||
{
|
||||
lr20xx_regmem_fill_cbuffer_opcode_address( cbuffer, opcode, address );
|
||||
lr20xx_regmem_fill_cdata( cdata, data, data_length );
|
||||
}
|
||||
|
||||
void lr20xx_regmem_fill_out_buffer_from_raw_buffer( uint32_t* out_buffer, const uint8_t* raw_buffer,
|
||||
uint8_t out_buffer_length )
|
||||
{
|
||||
for( uint8_t out_index = 0; out_index < out_buffer_length; out_index++ )
|
||||
{
|
||||
const uint8_t* raw_buffer_local = &raw_buffer[out_index * 4];
|
||||
|
||||
out_buffer[out_index] = ( ( uint32_t ) raw_buffer_local[0] << 24 ) +
|
||||
( ( uint32_t ) raw_buffer_local[1] << 16 ) + ( ( uint32_t ) raw_buffer_local[2] << 8 ) +
|
||||
( ( uint32_t ) raw_buffer_local[3] << 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,131 @@
|
||||
/*!
|
||||
* @file lr20xx_regmem.h
|
||||
*
|
||||
* @brief Register/memory driver definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_REGMEM_H
|
||||
#define LR20XX_REGMEM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lr20xx_status.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Maximum number of words that can be written to / read from a LR20XX chip with regmem32 commands
|
||||
*/
|
||||
#define LR20XX_REGMEM_MAX_WRITE_READ_WORDS 32
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Write up to 32 words into register memory space of the transceiver.
|
||||
*
|
||||
* A word is 32-bit long. The writing operations write contiguously in register memory, starting at the address
|
||||
* provided.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] address The register memory address to start writing operation (only the 3 bytes LSB are relevant)
|
||||
* @param [in] buffer The buffer of words to write into memory. Its size must be enough to contain length words.
|
||||
* @param [in] length Number of words to write into memory
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_regmem_read_regmem32
|
||||
*/
|
||||
lr20xx_status_t lr20xx_regmem_write_regmem32( const void* context, const uint32_t address, const uint32_t* buffer,
|
||||
const uint8_t length );
|
||||
|
||||
/*!
|
||||
* @brief Read-modify-write data at given register/memory address
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] address The register memory address to be modified (only the 3 bytes LSB are relevant)
|
||||
* @param [in] mask The mask to be applied on read data
|
||||
* @param [in] data The data to be written
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_regmem_write_regmem32_mask( const void* context, const uint32_t address, const uint32_t mask,
|
||||
const uint32_t data );
|
||||
|
||||
/*!
|
||||
* @brief Read up to 32 words into register memory space of the transceiver.
|
||||
*
|
||||
* A word is 32-bit long. The reading operations read contiguously from register memory, starting at the address
|
||||
* provided.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] address The register memory address to start reading operation (only the 3 bytes LSB are relevant)
|
||||
* @param [in] length Number of words to read from memory
|
||||
* @param [out] buffer Pointer to a words array to be filled with content from memory. Its size must be enough to
|
||||
* contain at least length words.
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_regmem_write_regmem32
|
||||
*/
|
||||
lr20xx_status_t lr20xx_regmem_read_regmem32( const void* context, const uint32_t address, uint32_t* buffer,
|
||||
const uint8_t length );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_REGMEM_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,88 @@
|
||||
/*!
|
||||
* @file lr20xx_status.h
|
||||
*
|
||||
* @brief Status type definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_STATUS_H
|
||||
#define LR20XX_STATUS_H
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Helper macro that execute return call if status is not @ref LR20XX_STATUS_OK
|
||||
*
|
||||
*/
|
||||
#define RETURN_STATUS_ON_NOT_OK( call ) \
|
||||
do \
|
||||
{ \
|
||||
const lr20xx_status_t status = call; \
|
||||
if( status != LR20XX_STATUS_OK ) \
|
||||
{ \
|
||||
return status; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief LR20XX status
|
||||
*/
|
||||
typedef enum lr20xx_status_e
|
||||
{
|
||||
LR20XX_STATUS_OK = 0,
|
||||
LR20XX_STATUS_ERROR = 3,
|
||||
} lr20xx_status_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
#endif // LR20XX_STATUS_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,629 @@
|
||||
/*!
|
||||
* @file lr20xx_system.c
|
||||
*
|
||||
* @brief System driver implementation for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "lr20xx_system.h"
|
||||
#include "lr20xx_hal.h"
|
||||
#include "lr20xx_workarounds.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE MACROS-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE CONSTANTS -------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LR20XX_SYSTEM_GET_STATUS_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_SYSTEM_GET_VERSION_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_SYSTEM_GET_ERRORS_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_SYSTEM_CLEAR_ERRORS_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_SYSTEM_SET_DIO_FUNC_CMD_LENGTH ( 2 + 2 )
|
||||
#define LR20XX_SYSTEM_SET_DIO_RF_SWITCH_CFG_CMD_LENGTH ( 2 + 2 )
|
||||
#define LR20XX_SYSTEM_SET_DIO_IRQ_CFG_CMD_LENGTH ( 2 + 5 )
|
||||
#define LR20XX_SYSTEM_CLEAR_IRQ_STATUS_CMD_LENGTH ( 2 + 4 )
|
||||
#define LR20XX_SYSTEM_GET_AND_CLEAR_IRQ_STATUS_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_SYSTEM_CFG_LF_CLK_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_SYSTEM_CFG_CLK_OUTPUT_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_SYSTEM_SET_TCXO_MODE_CMD_LENGTH ( 2 + 5 )
|
||||
#define LR20XX_SYSTEM_SET_REG_MODE_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_SYSTEM_CALIBRATE_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_SYSTEM_GET_VBAT_CMD_LENGTH ( 3 )
|
||||
#define LR20XX_SYSTEM_GET_TEMP_CMD_LENGTH ( 3 )
|
||||
#define LR20XX_SYSTEM_GET_RANDOM_NUMBER_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_SYSTEM_SET_SLEEP_MODE_CMD_LENGTH ( 2 + 5 )
|
||||
#define LR20XX_SYSTEM_SET_STANDBY_MODE_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_SYSTEM_SET_FS_MODE_CMD_LENGTH ( 2 )
|
||||
#define LR20XX_SYSTEM_ADD_REGISTER_TO_RETENTION_MEM_CMD_LENGTH ( 2 + 4 )
|
||||
#define LR20XX_SYSTEM_CONFIGURE_XOSC_CMD_LENGTH ( 2 + 3 )
|
||||
#define LR20XX_SYSTEM_SET_EOL_CFG_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_SYSTEM_SET_TEMP_COMP_CFG_CMD_LENGTH ( 2 + 1 )
|
||||
#define LR20XX_SYSTEM_SET_NTC_PARAMS_CMD_LENGTH ( 2 + 5 )
|
||||
|
||||
/*!
|
||||
* @brief Length in byte of the status returned by the transceiver
|
||||
*/
|
||||
#define LR20XX_SYSTEM_GET_STATUS_DIRECT_READ_LENGTH ( 6 )
|
||||
|
||||
/*!
|
||||
* @brief Length in byte of the version returned by the transceiver
|
||||
*/
|
||||
#define LR20XX_SYSTEM_VERSION_LENGTH ( 2 )
|
||||
|
||||
/*!
|
||||
* @brief Length in byte of the error list returned by the transceiver
|
||||
*/
|
||||
#define LR20XX_SYSTEM_ERRORS_LENGTH ( 2 )
|
||||
|
||||
/*!
|
||||
* @brief Length in byte of the random number returned by the transceiver
|
||||
*/
|
||||
#define LR20XX_SYSTEM_RANDOM_NUMBER_LENGTH ( 4 )
|
||||
|
||||
/*!
|
||||
* @brief Length in byte of the measure (temperature or voltage) returned by the transceiver
|
||||
*/
|
||||
#define LR20XX_SYSTEM_MEASURE_LENGTH ( 2 )
|
||||
|
||||
/*!
|
||||
* @brief Length in byte of the interrupt flags returned by the transceiver
|
||||
*/
|
||||
#define LR20XX_SYSTEM_INTERRUPTS_LENGTH ( 4 )
|
||||
|
||||
static const lr20xx_system_dio_t dio_list[] = {
|
||||
LR20XX_SYSTEM_DIO_5, LR20XX_SYSTEM_DIO_6, LR20XX_SYSTEM_DIO_7, LR20XX_SYSTEM_DIO_8,
|
||||
LR20XX_SYSTEM_DIO_9, LR20XX_SYSTEM_DIO_10, LR20XX_SYSTEM_DIO_11,
|
||||
};
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE TYPES -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Operating codes for system related operations
|
||||
*/
|
||||
enum
|
||||
{
|
||||
LR20XX_SYSTEM_GET_STATUS_OC = 0x0100,
|
||||
LR20XX_SYSTEM_GET_VERSION_OC = 0x0101,
|
||||
LR20XX_SYSTEM_GET_ERRORS_OC = 0x0110,
|
||||
LR20XX_SYSTEM_CLEAR_ERRORS_OC = 0x0111,
|
||||
LR20XX_SYSTEM_SET_DIO_FUNC_OC = 0x0112,
|
||||
LR20XX_SYSTEM_SET_DIO_RF_SWITCH_CFG_OC = 0x0113,
|
||||
LR20XX_SYSTEM_SET_DIO_IRQ_CFG_OC = 0x0115,
|
||||
LR20XX_SYSTEM_CLEAR_IRQ_STATUS_OC = 0x0116,
|
||||
LR20XX_SYSTEM_GET_AND_CLEAR_IRQ_STATUS_OC = 0x0117,
|
||||
LR20XX_SYSTEM_CFG_LF_CLK_OC = 0x0118,
|
||||
LR20XX_SYSTEM_CFG_CLK_OUTPUT_OC = 0x0119,
|
||||
LR20XX_SYSTEM_SET_TCXO_MODE_OC = 0x0120,
|
||||
LR20XX_SYSTEM_SET_REG_MODE_OC = 0x0121,
|
||||
LR20XX_SYSTEM_CALIBRATE_OC = 0x0122,
|
||||
LR20XX_SYSTEM_GET_VBAT_OC = 0x0124,
|
||||
LR20XX_SYSTEM_GET_TEMP_OC = 0x0125,
|
||||
LR20XX_SYSTEM_GET_RANDOM_NUMBER_OC = 0x0126,
|
||||
LR20XX_SYSTEM_SET_SLEEP_MODE_OC = 0x0127,
|
||||
LR20XX_SYSTEM_SET_STANDBY_MODE_OC = 0x0128,
|
||||
LR20XX_SYSTEM_SET_FS_MODE_OC = 0x0129,
|
||||
LR20XX_SYSTEM_ADD_REGISTER_TO_RETENTION_MEM_OC = 0x012A,
|
||||
LR20XX_SYSTEM_SET_EOL_CFG_OC = 0x0130,
|
||||
LR20XX_SYSTEM_CONFIGURE_XOSC_OC = 0x0131,
|
||||
LR20XX_SYSTEM_SET_TEMP_COMP_CFG_OC = 0x0132,
|
||||
LR20XX_SYSTEM_SET_NTC_PARAMS_OC = 0x0133,
|
||||
};
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE VARIABLES -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DECLARATION -------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Fill stat1 structure with data from stat1_byte
|
||||
*
|
||||
* @remark If \p stat1 is NULL, the function does not perform any operation
|
||||
*
|
||||
* @param [in] stat1_byte stat1 byte
|
||||
* @param [out] stat1 stat1 structure
|
||||
*/
|
||||
static void lr20xx_system_convert_stat1_byte_to_enum( uint8_t stat1_byte, lr20xx_system_stat1_t* stat1 );
|
||||
|
||||
/*!
|
||||
* @brief Fill stat2 structure with data from stat2_byte
|
||||
*
|
||||
* @remark If \p stat2 is NULL, the function does not perform any operation
|
||||
*
|
||||
* @param [in] stat2_byte stat2 byte
|
||||
* @param [out] stat2 stat2 structure
|
||||
*/
|
||||
static void lr20xx_system_convert_stat2_byte_to_enum( uint8_t stat2_byte, lr20xx_system_stat2_t* stat2 );
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS DEFINITION ---------------------------------------------
|
||||
*/
|
||||
|
||||
lr20xx_status_t lr20xx_system_reset( const void* context )
|
||||
{
|
||||
return ( lr20xx_status_t ) lr20xx_hal_reset( context );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_wakeup( const void* context )
|
||||
{
|
||||
return ( lr20xx_status_t ) lr20xx_hal_wakeup( context );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_get_status( const void* context, lr20xx_system_stat1_t* stat1,
|
||||
lr20xx_system_stat2_t* stat2, lr20xx_system_irq_mask_t* irq_status )
|
||||
{
|
||||
uint8_t data[LR20XX_SYSTEM_GET_STATUS_DIRECT_READ_LENGTH] = { 0 };
|
||||
const lr20xx_status_t status =
|
||||
( lr20xx_status_t ) lr20xx_hal_direct_read( context, data, LR20XX_SYSTEM_GET_STATUS_DIRECT_READ_LENGTH );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
lr20xx_system_convert_stat1_byte_to_enum( data[0], stat1 );
|
||||
lr20xx_system_convert_stat2_byte_to_enum( data[1], stat2 );
|
||||
if( irq_status != NULL )
|
||||
{
|
||||
*irq_status = ( ( lr20xx_system_irq_mask_t ) data[2] << 24 ) +
|
||||
( ( lr20xx_system_irq_mask_t ) data[3] << 16 ) +
|
||||
( ( lr20xx_system_irq_mask_t ) data[4] << 8 ) + ( ( lr20xx_system_irq_mask_t ) data[5] << 0 );
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_clear_reset_status_info( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_GET_STATUS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_STATUS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_STATUS_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_GET_STATUS_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_get_version( const void* context, lr20xx_system_version_t* version )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_GET_VERSION_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_VERSION_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_VERSION_OC >> 0 ),
|
||||
};
|
||||
uint8_t rbuffer[LR20XX_SYSTEM_VERSION_LENGTH] = { 0x00 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_SYSTEM_GET_VERSION_CMD_LENGTH, rbuffer, LR20XX_SYSTEM_VERSION_LENGTH );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
version->major = rbuffer[0];
|
||||
version->minor = rbuffer[1];
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_get_errors( const void* context, lr20xx_system_errors_t* errors )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_GET_ERRORS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_ERRORS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_ERRORS_OC >> 0 ),
|
||||
};
|
||||
uint8_t rbuffer[LR20XX_SYSTEM_ERRORS_LENGTH] = { 0x00 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_SYSTEM_GET_ERRORS_CMD_LENGTH, rbuffer, LR20XX_SYSTEM_ERRORS_LENGTH );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*errors = ( uint16_t ) ( ( ( uint16_t ) rbuffer[0] << 8 ) + ( uint16_t ) rbuffer[1] );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_clear_errors( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_CLEAR_ERRORS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CLEAR_ERRORS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CLEAR_ERRORS_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_CLEAR_ERRORS_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
uint8_t lr20xx_system_dio_get_count( void )
|
||||
{
|
||||
return sizeof( dio_list ) / sizeof( dio_list[0] );
|
||||
}
|
||||
|
||||
bool lr20xx_system_dio_get_nth( uint8_t nth, lr20xx_system_dio_t* dio )
|
||||
{
|
||||
if( nth < lr20xx_system_dio_get_count( ) )
|
||||
{
|
||||
*dio = dio_list[nth];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_dio_function( const void* context, lr20xx_system_dio_t dio,
|
||||
lr20xx_system_dio_func_t func, lr20xx_system_dio_drive_t drive )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_DIO_FUNC_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_DIO_FUNC_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_DIO_FUNC_OC >> 0 ),
|
||||
( uint8_t ) ( dio ),
|
||||
( uint8_t ) ( ( ( uint8_t ) func << 4 ) + ( ( uint8_t ) drive << 0 ) ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_DIO_FUNC_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_dio_rf_switch_cfg( const void* context, lr20xx_system_dio_t dio,
|
||||
const lr20xx_system_dio_rf_switch_cfg_t rf_switch_cfg )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_DIO_RF_SWITCH_CFG_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_DIO_RF_SWITCH_CFG_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_DIO_RF_SWITCH_CFG_OC >> 0 ),
|
||||
( uint8_t ) ( dio ),
|
||||
( uint8_t ) ( rf_switch_cfg ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_DIO_RF_SWITCH_CFG_CMD_LENGTH, 0,
|
||||
0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_dio_irq_cfg( const void* context, lr20xx_system_dio_t dio,
|
||||
const lr20xx_system_irq_mask_t irq_cfg )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_DIO_IRQ_CFG_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_DIO_IRQ_CFG_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_DIO_IRQ_CFG_OC >> 0 ),
|
||||
( uint8_t ) ( dio ),
|
||||
( uint8_t ) ( irq_cfg >> 24 ),
|
||||
( uint8_t ) ( irq_cfg >> 16 ),
|
||||
( uint8_t ) ( irq_cfg >> 8 ),
|
||||
( uint8_t ) ( irq_cfg >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_DIO_IRQ_CFG_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_clear_irq_status( const void* context, const lr20xx_system_irq_mask_t irqs_to_clear )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_CLEAR_IRQ_STATUS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CLEAR_IRQ_STATUS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CLEAR_IRQ_STATUS_OC >> 0 ),
|
||||
( uint8_t ) ( irqs_to_clear >> 24 ),
|
||||
( uint8_t ) ( irqs_to_clear >> 16 ),
|
||||
( uint8_t ) ( irqs_to_clear >> 8 ),
|
||||
( uint8_t ) ( irqs_to_clear >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_CLEAR_IRQ_STATUS_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_get_and_clear_irq_status( const void* context, lr20xx_system_irq_mask_t* irqs )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_GET_AND_CLEAR_IRQ_STATUS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_AND_CLEAR_IRQ_STATUS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_AND_CLEAR_IRQ_STATUS_OC >> 0 ),
|
||||
};
|
||||
uint8_t rbuffer[LR20XX_SYSTEM_INTERRUPTS_LENGTH] = { 0x00 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_SYSTEM_GET_AND_CLEAR_IRQ_STATUS_CMD_LENGTH, rbuffer, LR20XX_SYSTEM_INTERRUPTS_LENGTH );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*irqs = ( ( uint32_t ) rbuffer[0] << 24 ) + ( ( uint32_t ) rbuffer[1] << 16 ) +
|
||||
( ( uint32_t ) rbuffer[2] << 8 ) + ( ( uint32_t ) rbuffer[3] << 0 );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_cfg_lfclk( const void* context, const lr20xx_system_lfclk_cfg_t lfclock_cfg )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_CFG_LF_CLK_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CFG_LF_CLK_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CFG_LF_CLK_OC >> 0 ),
|
||||
( uint8_t ) lfclock_cfg,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_CFG_LF_CLK_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_cfg_clk_output( const void* context, lr20xx_system_hf_clk_scaling_t hf_clk_scaling )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_CFG_CLK_OUTPUT_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CFG_CLK_OUTPUT_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CFG_CLK_OUTPUT_OC >> 0 ),
|
||||
( uint8_t ) hf_clk_scaling,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_CFG_CLK_OUTPUT_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_tcxo_mode( const void* context, const lr20xx_system_tcxo_supply_voltage_t tune,
|
||||
const uint32_t start_delay_in_rtc_step )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_TCXO_MODE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_TCXO_MODE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_TCXO_MODE_OC >> 0 ),
|
||||
( uint8_t ) tune,
|
||||
( uint8_t ) ( start_delay_in_rtc_step >> 24 ),
|
||||
( uint8_t ) ( start_delay_in_rtc_step >> 16 ),
|
||||
( uint8_t ) ( start_delay_in_rtc_step >> 8 ),
|
||||
( uint8_t ) ( start_delay_in_rtc_step >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_TCXO_MODE_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_reg_mode( const void* context, const lr20xx_system_reg_mode_t reg_mode )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_REG_MODE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_REG_MODE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_REG_MODE_OC >> 0 ),
|
||||
( uint8_t ) reg_mode,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_REG_MODE_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_calibrate( const void* context,
|
||||
const lr20xx_system_calibration_mask_t blocks_to_calibrate )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_CALIBRATE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CALIBRATE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CALIBRATE_OC >> 0 ),
|
||||
( uint8_t ) blocks_to_calibrate,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_CALIBRATE_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_get_vbat( const void* context, lr20xx_system_value_format_t format,
|
||||
lr20xx_system_meas_res_t res, uint16_t* vbat )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_GET_VBAT_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_VBAT_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_VBAT_OC >> 0 ),
|
||||
( uint8_t ) ( ( ( uint8_t ) format << 3 ) + ( uint8_t ) res ),
|
||||
};
|
||||
uint8_t rbuffer[LR20XX_SYSTEM_MEASURE_LENGTH] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_SYSTEM_GET_VBAT_CMD_LENGTH, rbuffer, LR20XX_SYSTEM_MEASURE_LENGTH );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*vbat = ( uint16_t ) ( ( ( uint16_t ) rbuffer[0] << 8 ) + ( uint16_t ) rbuffer[1] );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_get_temp( const void* context, lr20xx_system_value_format_t format,
|
||||
lr20xx_system_meas_res_t res, lr20xx_system_temp_src_t src, uint16_t* temp )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_GET_TEMP_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_TEMP_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_TEMP_OC >> 0 ),
|
||||
( uint8_t ) ( ( ( uint8_t ) src << 4 ) + ( ( uint8_t ) format << 3 ) + ( uint8_t ) res ),
|
||||
};
|
||||
uint8_t rbuffer[LR20XX_SYSTEM_MEASURE_LENGTH] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_SYSTEM_GET_TEMP_CMD_LENGTH, rbuffer, LR20XX_SYSTEM_MEASURE_LENGTH );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*temp = ( uint16_t ) ( ( ( ( uint16_t ) rbuffer[0] << 8 ) + ( uint16_t ) rbuffer[1] ) >> 3 );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_get_random_number( const void* context,
|
||||
lr20xx_system_random_entropy_source_bitmask_t source,
|
||||
uint32_t* random_number )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_GET_RANDOM_NUMBER_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_RANDOM_NUMBER_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_GET_RANDOM_NUMBER_OC >> 0 ),
|
||||
( uint8_t ) source,
|
||||
};
|
||||
|
||||
uint8_t buffer[LR20XX_SYSTEM_RANDOM_NUMBER_LENGTH] = { 0 };
|
||||
|
||||
const lr20xx_status_t status = ( lr20xx_status_t ) lr20xx_hal_read(
|
||||
context, cbuffer, LR20XX_SYSTEM_GET_RANDOM_NUMBER_CMD_LENGTH, buffer, LR20XX_SYSTEM_RANDOM_NUMBER_LENGTH );
|
||||
|
||||
if( status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*random_number = ( ( uint32_t ) buffer[0] << 24 ) + ( ( uint32_t ) buffer[1] << 16 ) +
|
||||
( ( uint32_t ) buffer[2] << 8 ) + ( ( uint32_t ) buffer[3] << 0 );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_sleep_mode( const void* context, const lr20xx_system_sleep_cfg_t* sleep_cfg,
|
||||
const uint32_t sleep_time )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_SLEEP_MODE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_SLEEP_MODE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_SLEEP_MODE_OC >> 0 ),
|
||||
( uint8_t ) ( ( ( sleep_cfg->is_ram_retention_enabled == true ) ? 0x02 : 0x00 ) +
|
||||
( ( sleep_cfg->is_clk_32k_enabled == true ) ? 0x01 : 0x00 ) ),
|
||||
( uint8_t ) ( sleep_time >> 24 ),
|
||||
( uint8_t ) ( sleep_time >> 16 ),
|
||||
( uint8_t ) ( sleep_time >> 8 ),
|
||||
( uint8_t ) ( sleep_time >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_SLEEP_MODE_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_standby_mode( const void* context, const lr20xx_system_standby_mode_t standby_mode )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_STANDBY_MODE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_STANDBY_MODE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_STANDBY_MODE_OC >> 0 ),
|
||||
( uint8_t ) standby_mode,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_STANDBY_MODE_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_fs_mode( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_FS_MODE_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_FS_MODE_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_FS_MODE_OC >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_FS_MODE_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_add_register_to_retention_mem( const void* context, uint8_t slot, uint32_t address )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_ADD_REGISTER_TO_RETENTION_MEM_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_ADD_REGISTER_TO_RETENTION_MEM_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_ADD_REGISTER_TO_RETENTION_MEM_OC >> 0 ),
|
||||
slot,
|
||||
( uint8_t ) ( address >> 16 ),
|
||||
( uint8_t ) ( address >> 8 ),
|
||||
( uint8_t ) ( address >> 0 ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer,
|
||||
LR20XX_SYSTEM_ADD_REGISTER_TO_RETENTION_MEM_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_lbd_cfg( const void* context, bool is_enabled, lr20xx_system_lbd_trim_t trim )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_EOL_CFG_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_EOL_CFG_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_EOL_CFG_OC >> 0 ),
|
||||
( uint8_t ) ( ( ( uint8_t ) trim << 1 ) | ( ( is_enabled == true ) ? 1 : 0 ) ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_EOL_CFG_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_configure_xosc( const void* context, uint8_t xta, uint8_t xtb, uint8_t wait_time_us )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_CONFIGURE_XOSC_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CONFIGURE_XOSC_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_CONFIGURE_XOSC_OC >> 0 ),
|
||||
xta,
|
||||
xtb,
|
||||
wait_time_us,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_CONFIGURE_XOSC_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_temp_comp_cfg( const void* context, lr20xx_system_temp_comp_mode_t mode,
|
||||
bool is_ntc_en )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_TEMP_COMP_CFG_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_TEMP_COMP_CFG_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_TEMP_COMP_CFG_OC >> 0 ),
|
||||
( uint8_t ) ( ( ( ( is_ntc_en == false ) ? 0 : 1 ) << 2 ) + ( uint8_t ) mode ),
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_TEMP_COMP_CFG_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_system_set_ntc_params( const void* context, uint16_t ntc_r_ratio, uint16_t ntc_beta,
|
||||
uint8_t delay )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_SYSTEM_SET_NTC_PARAMS_CMD_LENGTH] = {
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_NTC_PARAMS_OC >> 8 ),
|
||||
( uint8_t ) ( LR20XX_SYSTEM_SET_NTC_PARAMS_OC >> 0 ),
|
||||
( uint8_t ) ( ntc_r_ratio >> 8 ),
|
||||
( uint8_t ) ( ntc_r_ratio >> 0 ),
|
||||
( uint8_t ) ( ntc_beta >> 8 ),
|
||||
( uint8_t ) ( ntc_beta >> 0 ),
|
||||
delay,
|
||||
};
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_SYSTEM_SET_NTC_PARAMS_CMD_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DEFINITION --------------------------------------------
|
||||
*/
|
||||
|
||||
static void lr20xx_system_convert_stat1_byte_to_enum( uint8_t stat1_byte, lr20xx_system_stat1_t* stat1 )
|
||||
{
|
||||
if( stat1 != NULL )
|
||||
{
|
||||
stat1->is_interrupt_active = ( ( stat1_byte & 0x01 ) == 1 ) ? true : false;
|
||||
stat1->command_status = ( lr20xx_system_command_status_t ) ( stat1_byte >> 1 );
|
||||
}
|
||||
}
|
||||
|
||||
static void lr20xx_system_convert_stat2_byte_to_enum( uint8_t stat2_byte, lr20xx_system_stat2_t* stat2 )
|
||||
{
|
||||
if( stat2 != NULL )
|
||||
{
|
||||
stat2->chip_mode = ( lr20xx_system_chip_modes_t ) ( stat2_byte & 0x07 );
|
||||
stat2->reset_status = ( lr20xx_system_reset_status_t ) ( ( stat2_byte & 0xF0 ) >> 4 );
|
||||
}
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,545 @@
|
||||
/*!
|
||||
* @file lr20xx_system.h
|
||||
*
|
||||
* @brief System driver definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_SYSTEM_H
|
||||
#define LR20XX_SYSTEM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lr20xx_system_types.h"
|
||||
#include "lr20xx_status.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Reset the radio
|
||||
*
|
||||
* @param [in] context Chip implementation context.
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_reset( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Wake the radio up from sleep mode.
|
||||
*
|
||||
* @param [in] context Chip implementation context.
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_wakeup( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Return stat1, stat2, and irq_status
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] stat1 Pointer to a variable for holding stat1. Can be NULL.
|
||||
* @param [out] stat2 Pointer to a variable for holding stat2. Can be NULL.
|
||||
* @param [out] irq_status Pointer to a variable for holding irq_status. Can be NULL.
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @remark To simplify system integration, this function does not actually execute the GetStatus command, which would
|
||||
* require bidirectional SPI communication. It obtains the stat1, stat2, and irq_status values by performing an ordinary
|
||||
* SPI read (which is required to send null/NOP bytes on the MOSI line). This is possible since the LR20XX returns these
|
||||
* values automatically whenever a read that does not directly follow a response-carrying command is performed.
|
||||
* Unlike with the GetStatus command, however, the reset status information is NOT cleared by this command. The function
|
||||
* @ref lr20xx_system_clear_reset_status_info may be used for this purpose when necessary.
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_get_status( const void* context, lr20xx_system_stat1_t* stat1,
|
||||
lr20xx_system_stat2_t* stat2, lr20xx_system_irq_mask_t* irq_status );
|
||||
|
||||
/*!
|
||||
* @brief Clear the reset status information stored in stat2
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_clear_reset_status_info( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Return the version of the system
|
||||
*
|
||||
* The following table provides expected version per LR20xx derivatives:
|
||||
*
|
||||
* | Derivative | Version major | Version minor |
|
||||
* | ---------- | ------------- | ------------- |
|
||||
* | LR2021 | 0x01 | 0x18 |
|
||||
* | LR2022 | 0x02 | 0x00 |
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] version Pointer to the structure holding the system version
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_get_version( const void* context, lr20xx_system_version_t* version );
|
||||
|
||||
/*!
|
||||
* @brief Return the system errors
|
||||
*
|
||||
* Errors may be fixed following:
|
||||
* - calibration error can be fixed by attempting another RC calibration;
|
||||
* - XOsc related errors may be due to hardware problems, can be fixed by reset;
|
||||
* - PLL lock related errors can be due to not-locked PLL, or by attempting to use an out-of-band frequency, can be
|
||||
* fixed by executing a PLL calibration, or by using other frequencies.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [out] errors Pointer to a value holding error flags
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_calibrate, lr20xx_radio_common_calibrate_front_end, lr20xx_system_clear_errors
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_get_errors( const void* context, lr20xx_system_errors_t* errors );
|
||||
|
||||
/*!
|
||||
* @brief Clear all error flags pending.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_get_errors
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_clear_errors( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Returns the number of available DIOs
|
||||
*
|
||||
* @remark Also is the valid range for lr20xx_system_dio_get_nth.
|
||||
*
|
||||
* @return uint8_t the number of valid DIOs.
|
||||
*
|
||||
* @see lr20xx_system_dio_get_nth
|
||||
*/
|
||||
uint8_t lr20xx_system_dio_get_count( void );
|
||||
|
||||
/**
|
||||
* @brief Returns the nth value from the enum lr20xx_system_dio_t
|
||||
*
|
||||
* @param [in] nth from 0 to lr20xx_system_dio_get_count() - 1
|
||||
* @param [out] dio Pointer to a value holding the corresponding DIO enum
|
||||
* @return true if nth is a valid number, false otherwise
|
||||
*
|
||||
* @see lr20xx_system_dio_get_count, lr20xx_system_dio_t
|
||||
*/
|
||||
bool lr20xx_system_dio_get_nth( uint8_t nth, lr20xx_system_dio_t* dio );
|
||||
|
||||
/*!
|
||||
* @brief Configure the function and the drive mode of a given DIO
|
||||
*
|
||||
* @remark @p drive is applied when entering sleep mode if @p func is not @ref LR20XX_SYSTEM_DIO_FUNC_NONE.
|
||||
* When leaving sleep mode without retention, @p drive is reset to @ref LR20XX_SYSTEM_DIO_DRIVE_NONE (except for @p dio
|
||||
* LR20XX_SYSTEM_DIO_5 and LR20XX_SYSTEM_DIO_6 where @p drive is reset to LR20XX_SYSTEM_DIO_DRIVE_PULL_UP).
|
||||
*
|
||||
* @remark The state of @p dio is reevaluated when sending this command
|
||||
*
|
||||
* @remark When @p func is set to either LR20XX_SYSTEM_DIO_FUNC_TX_TRIGGER or LR20XX_SYSTEM_DIO_FUNC_RX_TRIGGER, default
|
||||
* timeout set through @ref lr20xx_radio_common_set_default_rx_tx_timeout or @ref
|
||||
* lr20xx_radio_common_set_default_rx_tx_timeout_in_rtc_step is used when radio operation is triggered
|
||||
*
|
||||
* @remark On @ref LR20XX_SYSTEM_DIO_5, only @ref LR20XX_SYSTEM_DIO_DRIVE_PULL_UP for @p drive
|
||||
*
|
||||
* @remark Function @ref LR20XX_SYSTEM_DIO_FUNC_LF_CLK_OUT can only be used if @p dio is one of:
|
||||
* - LR20XX_SYSTEM_DIO_7
|
||||
* - LR20XX_SYSTEM_DIO_8
|
||||
* - LR20XX_SYSTEM_DIO_9
|
||||
* - LR20XX_SYSTEM_DIO_10
|
||||
* - LR20XX_SYSTEM_DIO_11
|
||||
*
|
||||
* @ref LR20XX_SYSTEM_DIO_5 and @ref LR20XX_SYSTEM_DIO_6 must be configured explicitly to function @ref
|
||||
* LR20XX_SYSTEM_DIO_FUNC_NONE if they are connected to an external component that could toggle their state between a
|
||||
* cold start or a start without retention and the configuration of a function.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] dio DIO pin
|
||||
* @param [in] func DIO pin function
|
||||
* @param [in] drive DIO pin drive
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_dio_function( const void* context, lr20xx_system_dio_t dio,
|
||||
lr20xx_system_dio_func_t func, lr20xx_system_dio_drive_t drive );
|
||||
|
||||
/*!
|
||||
* @brief Set the RF switch configurations for a given DIO
|
||||
*
|
||||
* @remark The state of @p dio is reevaluated when sending this command
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] dio DIO pin
|
||||
* @param [in] rf_switch_cfg Pointer to a structure that holds the RF switch configuration for @p dio
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_dio_rf_switch_cfg( const void* context, lr20xx_system_dio_t dio,
|
||||
const lr20xx_system_dio_rf_switch_cfg_t rf_switch_cfg );
|
||||
|
||||
/*!
|
||||
* @brief Set the interrupt configurations for a given DIO
|
||||
*
|
||||
* It is not possible to set the same IRQ on multiple DIOs. Only the last mapping for each IRQ is take into account.
|
||||
*
|
||||
* @remark The state of \p dio is reevaluated when sending this command
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] dio DIO pin
|
||||
* @param [in] irq_cfg Interrupt mask for \p dio
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_dio_irq_cfg( const void* context, lr20xx_system_dio_t dio,
|
||||
const lr20xx_system_irq_mask_t irq_cfg );
|
||||
|
||||
/*!
|
||||
* @brief Clear requested bits in the internal pending interrupt register
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] irqs_to_clear Variable that holds the interrupts to be cleared
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_get_and_clear_irq_status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_clear_irq_status( const void* context, const lr20xx_system_irq_mask_t irqs_to_clear );
|
||||
|
||||
/**
|
||||
* @brief This helper function clears any radio irq status flags that are set and returns the flags that were cleared.
|
||||
*
|
||||
* @param [in] context Chip implementation context.
|
||||
* @param [out] irq Pointer to a variable for holding the system interrupt status.
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_clear_irq_status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_get_and_clear_irq_status( const void* context, lr20xx_system_irq_mask_t* irq );
|
||||
|
||||
/*!
|
||||
* @brief Configure the source of the Low Frequency Clock (LF_CLK)
|
||||
*
|
||||
* When switching LF CLK to external source (@ref LR20XX_SYSTEM_LFCLK_EXT), the external clock source must be already
|
||||
* running, and shall keep running afterwards.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] lfclock_cfg Low frequency clock configuration
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_calibrate, lr20xx_radio_common_calibrate_front_end, lr20xx_system_set_dio_function
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_cfg_lfclk( const void* context, const lr20xx_system_lfclk_cfg_t lfclock_cfg );
|
||||
|
||||
/*!
|
||||
* @brief Configure the High Frequency clock scaling on the output
|
||||
*
|
||||
* This command sets the HF clock scaling on the DIO configured with functionality
|
||||
* LR20XX_SYSTEM_DIO_FUNC_HF_CLK_OUT through lr20xx_system_set_dio_function
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] hf_clk_scaling High frequency output scaling
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_set_dio_function
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_cfg_clk_output( const void* context, lr20xx_system_hf_clk_scaling_t hf_clk_scaling );
|
||||
|
||||
/*!
|
||||
* @brief Enable the usage of a TCXO as HF clock and configure supply voltage & start delay
|
||||
*
|
||||
* \p start_delay_in_32mhz_step is the time the firmware waits before going into RF mode, expressed in number of 32MHz
|
||||
* clock ticks.
|
||||
* The timeout duration is given by: \f$ start\_delay\_in\_ns = start\_delay\_in\_32mhz\_step \times 31.25 \f$
|
||||
*
|
||||
* The TCXO mode can be disabled by setting \p start_delay_in_32mhz_step to 0.
|
||||
*
|
||||
* In the situation where the TCXO has not started within \p start_delay_in_32mhz_step then the error bit
|
||||
* LR20XX_SYSTEM_ERRORS_HF_XOSC_START_MASK will be set. It can be checked with a call to \p lr20xx_system_get_errors.
|
||||
*
|
||||
* It must be noted that the TCXO start time duration can last twice the duration of \p start_delay_in_32mhz_step
|
||||
* lr20xx_system_calibrate if the internal 32MHz RC clock source is not calibrated. Refer to \p lr20xx_system_calibrate
|
||||
* for details.
|
||||
*
|
||||
* The maximum value for \p start_delay_in_32mhz_step is 0xFFFFFFFF.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] supply_voltage Supply voltage value
|
||||
* @param [in] start_delay_in_32mhz_step Gating time before which the radio starts its RF operation
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_calibrate, lr20xx_radio_common_calibrate_front_end, lr20xx_system_get_errors
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_tcxo_mode( const void* context,
|
||||
const lr20xx_system_tcxo_supply_voltage_t supply_voltage,
|
||||
const uint32_t start_delay_in_32mhz_step );
|
||||
|
||||
/*!
|
||||
* @brief Configure the regulator mode to be used in specific modes
|
||||
*
|
||||
* \p reg_mode defines if the DC-DC converter is switched on in the following modes: STANDBY XOSC, FS, RX, TX.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] reg_mode Regulator mode configuration
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_reg_mode( const void* context, const lr20xx_system_reg_mode_t reg_mode );
|
||||
|
||||
/*!
|
||||
* @brief Calibrate the requested blocks
|
||||
*
|
||||
* This function can be called in any mode of the chip.
|
||||
*
|
||||
* The chip will return to standby RC mode on exit. Potential calibration issues can be read out with
|
||||
* lr20xx_system_get_errors command.
|
||||
*
|
||||
* The calibration should be executed at boot. The calibration can then be executed again:
|
||||
* - @ref lr20xx_system_calibration_e::LR20XX_SYSTEM_CALIB_AAF_MASK : should be calibrated again for a temperature
|
||||
* change superior to 20 degree Celsius
|
||||
* - @ref lr20xx_system_calibration_e::LR20XX_SYSTEM_CALIB_MU_MASK : initial calibration is enough
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] blocks_to_calibrate Blocks to be calibrated - bitfield built with lr20xx_system_calibration_e
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_get_errors
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_calibrate( const void* context,
|
||||
const lr20xx_system_calibration_mask_t blocks_to_calibrate );
|
||||
|
||||
/*!
|
||||
* @brief Get the value of the power supply voltage
|
||||
*
|
||||
* If @p format is set to LR20XX_SYSTEM_VALUE_FORMAT_RAW, Vbat value (in [V]) is a function of Vana (typ. 1.35V) and can
|
||||
* be obtained using the following formula: \f$ Vbat_{V} = (\frac{vbat}{8192} \times 5 - 1) \times Vana \f$ where vbat
|
||||
* is a 13-bit long value
|
||||
*
|
||||
* If @p format is set to LR20XX_SYSTEM_VALUE_FORMAT_UNIT, the power supply voltage is given in [mV]
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] format Format of the returned value of @p vbat
|
||||
* @param [in] res Resolution of the measure of @p vbat
|
||||
* @param [out] vbat A pointer to the @p vbat value
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_get_vbat( const void* context, lr20xx_system_value_format_t format,
|
||||
lr20xx_system_meas_res_t res, uint16_t* vbat );
|
||||
|
||||
/*!
|
||||
* @brief Get the value of the internal junction temperature
|
||||
*
|
||||
* If @p format is set to LR20XX_SYSTEM_VALUE_FORMAT_RAW, the temperature (in [°C]) is a function of Vana (typ. 1.35V),
|
||||
* Vbe25 (Vbe voltage @ 25°C, typ. 0.7295V) and VbeSlope (typ. -1.7mV/°C) using the following formula:
|
||||
* \f$ Temperature_{°C} = (\frac{temp(12:0)}{8192} \times Vana - Vbe25) \times \frac{1000}{VbeSlope} + 25 \f$ where
|
||||
* temp{12:0} is the value corresponding to the 12 LSBs of the output argument of @ref lr20xx_system_get_temp
|
||||
*
|
||||
* If @p format is set to LR20XX_SYSTEM_VALUE_FORMAT_UNIT, the temperature is given in [°C] in 13.5sb format, the first
|
||||
* byte returned contains the integer part, the second the fractional part.
|
||||
*
|
||||
* @remark If a TCXO is used, make sure to configure it with @ref lr20xx_system_set_tcxo_mode before calling this
|
||||
* function
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] format Format of the returned value of @p temp
|
||||
* @param [in] res Resolution of the measure
|
||||
* @param [in] src Temperature source
|
||||
* @param [out] temp A pointer to the @p temp value
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_get_temp( const void* context, lr20xx_system_value_format_t format,
|
||||
lr20xx_system_meas_res_t res, lr20xx_system_temp_src_t src, uint16_t* temp );
|
||||
|
||||
/*!
|
||||
* @brief Read and return a 32-bit random number
|
||||
*
|
||||
* This random number generator is not suitable for cryptographic operations.
|
||||
* It can be called during any mode without perturbation on ongoing Rx or Tx operation.
|
||||
*
|
||||
* @remark Radio operating mode must be set into standby.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] source Select source of entropy for random number generator
|
||||
* @param [out] random_number 32-bit random number
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_get_random_number( const void* context,
|
||||
lr20xx_system_random_entropy_source_bitmask_t source,
|
||||
uint32_t* random_number );
|
||||
|
||||
/*!
|
||||
* @brief Switch the transceiver into sleep mode with the request configuration
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] sleep_cfg Sleep configuration
|
||||
* @param [in] sleep_time Sleep time in LF clock steps
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_sleep_mode( const void* context, const lr20xx_system_sleep_cfg_t* sleep_cfg,
|
||||
const uint32_t sleep_time );
|
||||
|
||||
/*!
|
||||
* @brief Switch the transceiver into the requested stand-by mode
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] standby_mode Requested stand-by mode
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_standby_mode( const void* context, const lr20xx_system_standby_mode_t standby_mode );
|
||||
|
||||
/*!
|
||||
* @brief Switch the transceiver into the Frequency Synthesis (FS) mode
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_fs_mode( const void* context );
|
||||
|
||||
/*!
|
||||
* @brief Add a register to be saved in retention memory
|
||||
*
|
||||
* @remark This command is used when a register is not added by default to the retention memory. It gives the
|
||||
* possibility to store up to 32 additional registers when entering sleep mode.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] slot Index in the storage list. Allowed values [0:31]
|
||||
* @param [in] address Address of the register to be added to the list. Only the 3 LSBs are significant. Address must be
|
||||
* word-aligned
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_system_set_sleep_mode
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_add_register_to_retention_mem( const void* context, uint8_t slot, uint32_t address );
|
||||
|
||||
/*!
|
||||
* @brief Configure the low battery detector
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] is_enabled Low battery detector activation
|
||||
* @param [in] trim Trimming value defining the threshold used to trigger a low battery interrupt
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_lbd_cfg( const void* context, bool is_enabled, lr20xx_system_lbd_trim_t trim );
|
||||
|
||||
/*!
|
||||
* @brief Configure the internal trimming capacitor values and XTAL start time
|
||||
*
|
||||
* @remark The device is fitted with internal programmable capacitors connected independently to the pins XTA and XTB of
|
||||
* the device. Each capacitor can be controlled independently in steps of 0.47 pF added to the minimal value of 11.3pF
|
||||
* for XTA and 10.1pF for XTB.
|
||||
*
|
||||
* The maximal capacitor value corresponds to 47 LSB steps added to the corresponding minimal value, so it is 33.39pF
|
||||
* for XTA and 32.19pF for XTB.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] xta Value for the trimming capacitor connected to XTA pin
|
||||
* @param [in] xtb Value for the trimming capacitor connected to XTB pin
|
||||
* @param [in] wait_time_us Additional wait time after XTAL readiness in microsecond
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_configure_xosc( const void* context, uint8_t xta, uint8_t xtb, uint8_t wait_time_us );
|
||||
|
||||
/*!
|
||||
* @brief Set the temperature compensation configuration
|
||||
*
|
||||
* This command configures the heating compensation during Tx operations when XTAL 32MHz is used.
|
||||
* This command will fail if a TCXO is configured.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] mode Temperature compensation mode
|
||||
* @param [in] is_ntc_en Indicate if an external temperature sensor is available
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_temp_comp_cfg( const void* context, lr20xx_system_temp_comp_mode_t mode,
|
||||
bool is_ntc_en );
|
||||
|
||||
/*!
|
||||
* @brief Set Negative Temperature Coefficient parameters
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] ntc_r_ratio Resistance bias ratio (10.9b) - ratio between resistance bias and NTC resistance at 25°C
|
||||
* @param [in] ntc_beta Beta coefficient (unit is 2 Kelvin)
|
||||
* @param [in] delay First order time delay coefficient
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_system_set_ntc_params( const void* context, uint16_t ntc_r_ratio, uint16_t ntc_beta,
|
||||
uint8_t delay );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_SYSTEM_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,486 @@
|
||||
/*!
|
||||
* @file lr20xx_system_types.h
|
||||
*
|
||||
* @brief System driver types for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2022. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_SYSTEM_TYPES_H
|
||||
#define LR20XX_SYSTEM_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Command status
|
||||
*/
|
||||
typedef enum lr20xx_system_command_status_e
|
||||
{
|
||||
LR20XX_SYSTEM_CMD_STATUS_FAIL = 0x00, //!< Last command could not be executed
|
||||
LR20XX_SYSTEM_CMD_STATUS_PERR = 0x01, //!< Last command could not be processed (wrong opcode, wrong argument)
|
||||
LR20XX_SYSTEM_CMD_STATUS_OK = 0x02, //!< Last command processed successfully
|
||||
LR20XX_SYSTEM_CMD_STATUS_DATA = 0x03, //!< Last command was a successfully processed read, and data is currently
|
||||
//!< transmitted instead of IRQ status
|
||||
} lr20xx_system_command_status_t;
|
||||
|
||||
/**
|
||||
* @brief Reset status
|
||||
*/
|
||||
typedef enum lr20xx_system_reset_status_e
|
||||
{
|
||||
LR20XX_SYSTEM_RESET_STATUS_CLEARED = 0x00, //!< Reset status has been cleared
|
||||
LR20XX_SYSTEM_RESET_STATUS_PWR_ON_BROWN_OUT = 0x01, //!< Reset triggered by power-on or brown-out
|
||||
LR20XX_SYSTEM_RESET_STATUS_RESET_PIN = 0x02, //!< Reset triggered by reset pin
|
||||
LR20XX_SYSTEM_RESET_STATUS_NSS_WAKEUP = 0x05, //!< Reset triggered by leaving sleep mode with NSS toggling
|
||||
LR20XX_SYSTEM_RESET_STATUS_RTC_WAKEUP = 0x06, //!< Reset triggered by leaving sleep mode with RTC timeout
|
||||
} lr20xx_system_reset_status_t;
|
||||
|
||||
/**
|
||||
* @brief Chip modes
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_SYSTEM_CHIP_MODE_SLEEP = 0x00,
|
||||
LR20XX_SYSTEM_CHIP_MODE_STBY_RC = 0x01,
|
||||
LR20XX_SYSTEM_CHIP_MODE_STBY_XOSC = 0x02,
|
||||
LR20XX_SYSTEM_CHIP_MODE_FS = 0x03,
|
||||
LR20XX_SYSTEM_CHIP_MODE_RX = 0x04,
|
||||
LR20XX_SYSTEM_CHIP_MODE_TX = 0x05,
|
||||
} lr20xx_system_chip_modes_t;
|
||||
|
||||
/**
|
||||
* @brief Status register 1 structure definition
|
||||
*/
|
||||
typedef struct lr20xx_system_stat1_s
|
||||
{
|
||||
lr20xx_system_command_status_t command_status; //!< Command status
|
||||
bool is_interrupt_active; //!< Indication of a still active interrupt
|
||||
} lr20xx_system_stat1_t;
|
||||
|
||||
/**
|
||||
* @brief Status register 2 structure definition
|
||||
*/
|
||||
typedef struct lr20xx_system_stat2_s
|
||||
{
|
||||
lr20xx_system_reset_status_t reset_status; //!< Source of the last reset
|
||||
lr20xx_system_chip_modes_t chip_mode; //!< Current chip mode
|
||||
} lr20xx_system_stat2_t;
|
||||
|
||||
/**
|
||||
* @brief Version structure definition
|
||||
*/
|
||||
typedef struct lr20xx_system_version_s
|
||||
{
|
||||
uint8_t major; //!< Version major field
|
||||
uint8_t minor; //!< Version minor field
|
||||
} lr20xx_system_version_t;
|
||||
|
||||
/**
|
||||
* @brief Version structure definition
|
||||
*/
|
||||
typedef struct lr20xx_system_sleep_cfg_s
|
||||
{
|
||||
bool is_clk_32k_enabled; //!< 32kHz clock state when entering sleep mode
|
||||
bool is_ram_retention_enabled; //!< RAM retention state when entering sleep mode
|
||||
} lr20xx_system_sleep_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Error flags
|
||||
*/
|
||||
enum lr20xx_system_errors_e
|
||||
{
|
||||
LR20XX_SYSTEM_ERRORS_HF_XOSC_START_MASK = ( 1 << 0 ), //!< HF XOSC did not start correctly
|
||||
LR20XX_SYSTEM_ERRORS_LF_XOSC_START_MASK = ( 1 << 1 ), //!< LF XOSC did not start correctly
|
||||
LR20XX_SYSTEM_ERRORS_PLL_LOCK_MASK = ( 1 << 2 ), //!< PLL did not lock
|
||||
LR20XX_SYSTEM_ERRORS_LF_RC_CALIB_MASK = ( 1 << 3 ), //!< Calibration of the LF RC clock failed
|
||||
LR20XX_SYSTEM_ERRORS_HF_RC_CALIB_MASK = ( 1 << 4 ), //!< Calibration of the HF RC clock failed
|
||||
LR20XX_SYSTEM_ERRORS_PLL_CALIB_MASK = ( 1 << 5 ), //!< Calibration of the min / max RF frequencies failed
|
||||
LR20XX_SYSTEM_ERRORS_AAF_CALIB_MASK = ( 1 << 6 ), //!< Calibration of the anti-aliasing filter (AAF) failed
|
||||
LR20XX_SYSTEM_ERRORS_IMG_CALIB_MASK = ( 1 << 7 ), //!< Calibration of the image rejection failed
|
||||
LR20XX_SYSTEM_ERRORS_CHIP_BUSY_MASK =
|
||||
( 1 << 8 ), //!< DIO Tx or Rx trigger cannot be executed because chip was changing mode
|
||||
LR20XX_SYSTEM_ERRORS_RXFREQ_NO_FRONT_END_CALIB_MASK =
|
||||
( 1 << 9 ), //!< Front end calibration not available (image rejection, Poly-Phase filter, ADC offset) for the
|
||||
//!< configured RF frequency
|
||||
LR20XX_SYSTEM_ERRORS_MEAS_UNIT_ADC_CALIB_MASK = ( 1 << 10 ), //!< Error during calibration of the measure unit ADC
|
||||
LR20XX_SYSTEM_ERRORS_PA_OFFSET_CALIB_MASK =
|
||||
( 1 << 11 ), //!< Error during calibration of the Power Amplifier offset
|
||||
LR20XX_SYSTEM_ERRORS_PPF_CALIB_MASK = ( 1 << 12 ), //!< Error during calibration of the Poly-Phase Filter (PPF)
|
||||
LR20XX_SYSTEM_ERRORS_SRC_CALIB_MASK =
|
||||
( 1 << 13 ), //!< Error during calibration of the Self Reception Cancellation (SRC)
|
||||
LR20XX_SYSTEM_ERRORS_SRC_SATURATION_CALIB_MASK =
|
||||
( 1 << 14 ), //!< RSSI saturation detected during SRC calibration. It may comes from an interferer.
|
||||
LR20XX_SYSTEM_ERRORS_SRC_TOLERANCE_CALIB_MASK = ( 1 << 15 ), //!< SRC calibration values are out of tolerance
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interrupt flags
|
||||
*/
|
||||
enum lr20xx_system_irq_e
|
||||
{
|
||||
LR20XX_SYSTEM_IRQ_NONE = ( 0 << 0 ), //!< No interrupt
|
||||
LR20XX_SYSTEM_IRQ_FIFO_RX = ( int ) ( 1u << 0 ), //!< RX FIFO threshold reached
|
||||
LR20XX_SYSTEM_IRQ_FIFO_TX = ( int ) ( 1u << 1 ), //!< TX FIFO threshold reached
|
||||
LR20XX_SYSTEM_IRQ_RTTOF_RESPONDER_REQUEST_VALID =
|
||||
( int ) ( 1u << 2 ), //!< Responder received a valid RTToF request
|
||||
LR20XX_SYSTEM_IRQ_TX_TIMESTAMP = ( int ) ( 1u << 3 ), //!< Last bit sent timestamp
|
||||
LR20XX_SYSTEM_IRQ_RX_TIMESTAMP = ( int ) ( 1u << 4 ), //!< Last bit received timestamp
|
||||
LR20XX_SYSTEM_IRQ_PREAMBLE_DETECTED = ( int ) ( 1u << 5 ), //!< Preamble detected
|
||||
LR20XX_SYSTEM_IRQ_SYNC_WORD_HEADER_VALID =
|
||||
( int ) ( 1u << 6 ), //!< Valid LoRa header received / Sync word received
|
||||
LR20XX_SYSTEM_IRQ_CAD_DETECTED = ( int ) ( 1u << 7 ), //!< Activity detected during CAD operation
|
||||
LR20XX_SYSTEM_IRQ_LORA_RX_HEADER_TIMESTAMP =
|
||||
( int ) ( 1u << 8 ), //!< Last bit of LoRa header received in explicit mode,
|
||||
//!< asserted after 8 symbols of payload in implicit mode
|
||||
LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR = ( int ) ( 1u << 9 ), //!< Erroneous LoRa header received
|
||||
LR20XX_SYSTEM_IRQ_LOW_BATTERY = ( int ) ( 1u << 10 ), //!< Power supply level dropped below the threshold
|
||||
LR20XX_SYSTEM_IRQ_PA_OVP_OCP = ( int ) ( 1u << 11 ), //!< Power amplifier over-current protection has triggered
|
||||
LR20XX_SYSTEM_IRQ_ERROR =
|
||||
( int ) ( 1u << 16 ), //!< Error other than a command error occurred - call lr20xx_system_get_errors
|
||||
LR20XX_SYSTEM_IRQ_CMD_ERROR = ( int ) ( 1u << 17 ), //!< Host command fail/error occurred
|
||||
LR20XX_SYSTEM_IRQ_RX_DONE = ( int ) ( 1u << 18 ), //!< Packet received
|
||||
LR20XX_SYSTEM_IRQ_TX_DONE = ( int ) ( 1u << 19 ), //!< Packet sent
|
||||
LR20XX_SYSTEM_IRQ_CAD_DONE = ( int ) ( 1u << 20 ), //!< CAD operation done
|
||||
LR20XX_SYSTEM_IRQ_TIMEOUT = ( int ) ( 1u << 21 ), //!< Timeout occurred during Rx or Tx operation
|
||||
LR20XX_SYSTEM_IRQ_CRC_ERROR = ( int ) ( 1u << 22 ), //!< Packet received with wrong CRC
|
||||
LR20XX_SYSTEM_IRQ_LEN_ERROR = ( int ) ( 1u << 23 ), //!< Length of the received packet higher than expected
|
||||
LR20XX_SYSTEM_IRQ_ADDR_ERROR = ( int ) ( 1u << 24 ), //!< Received packet discarded - no address match
|
||||
LR20XX_SYSTEM_IRQ_LR_FHSS_INTRA_PKT_HOP = ( int ) ( 1u << 25 ), //!< LR-FHSS intra-packet hopping occurred
|
||||
LR20XX_SYSTEM_IRQ_LR_FHSS_RDY_FOR_NEW_FREQ_TABLE =
|
||||
( int ) ( 1u << 26 ), //!< A new LR-FHSS frequency table can be loaded
|
||||
LR20XX_SYSTEM_IRQ_LR_FHSS_RDY_FOR_NEW_PAYLOAD = ( int ) ( 1u << 27 ), //!< A new LR-FHSS payload can be loaded
|
||||
LR20XX_SYSTEM_IRQ_RTTOF_RESPONDER_RESPONSE_DONE = ( int ) ( 1u << 28 ), //!< Responder sent an RTToF response
|
||||
LR20XX_SYSTEM_IRQ_RTTOF_RESPONDER_REQUEST_DISCARDED =
|
||||
( int ) ( 1u << 29 ), //!< Responder discarded the RTToF request - no address match
|
||||
LR20XX_SYSTEM_IRQ_RTTOF_INITIATOR_EXCHANGE_VALID =
|
||||
( int ) ( 1u << 30 ), //!< Initiator received a valid RTToF response from a responder
|
||||
LR20XX_SYSTEM_IRQ_RTTOF_INITIATOR_TIMEOUT =
|
||||
( int ) ( 1u << 31 ), //!< Initiator did not receive an RTToF response from a responder
|
||||
LR20XX_SYSTEM_IRQ_ALL_MASK =
|
||||
LR20XX_SYSTEM_IRQ_FIFO_RX | LR20XX_SYSTEM_IRQ_FIFO_TX | LR20XX_SYSTEM_IRQ_RTTOF_RESPONDER_REQUEST_VALID |
|
||||
LR20XX_SYSTEM_IRQ_TX_TIMESTAMP | LR20XX_SYSTEM_IRQ_RX_TIMESTAMP | LR20XX_SYSTEM_IRQ_PREAMBLE_DETECTED |
|
||||
LR20XX_SYSTEM_IRQ_SYNC_WORD_HEADER_VALID | LR20XX_SYSTEM_IRQ_CAD_DETECTED |
|
||||
LR20XX_SYSTEM_IRQ_LORA_RX_HEADER_TIMESTAMP | LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR |
|
||||
LR20XX_SYSTEM_IRQ_LOW_BATTERY | LR20XX_SYSTEM_IRQ_ERROR | LR20XX_SYSTEM_IRQ_CMD_ERROR |
|
||||
LR20XX_SYSTEM_IRQ_RX_DONE | LR20XX_SYSTEM_IRQ_TX_DONE | LR20XX_SYSTEM_IRQ_CAD_DONE | LR20XX_SYSTEM_IRQ_TIMEOUT |
|
||||
LR20XX_SYSTEM_IRQ_CRC_ERROR | LR20XX_SYSTEM_IRQ_LEN_ERROR | LR20XX_SYSTEM_IRQ_ADDR_ERROR |
|
||||
LR20XX_SYSTEM_IRQ_LR_FHSS_INTRA_PKT_HOP | LR20XX_SYSTEM_IRQ_LR_FHSS_RDY_FOR_NEW_FREQ_TABLE |
|
||||
LR20XX_SYSTEM_IRQ_LR_FHSS_RDY_FOR_NEW_PAYLOAD | LR20XX_SYSTEM_IRQ_RTTOF_RESPONDER_RESPONSE_DONE |
|
||||
LR20XX_SYSTEM_IRQ_RTTOF_RESPONDER_REQUEST_DISCARDED | LR20XX_SYSTEM_IRQ_RTTOF_INITIATOR_EXCHANGE_VALID |
|
||||
LR20XX_SYSTEM_IRQ_RTTOF_INITIATOR_TIMEOUT,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interrupt type re-definition
|
||||
*
|
||||
* @see lr20xx_system_irq_e
|
||||
*/
|
||||
typedef uint32_t lr20xx_system_irq_mask_t;
|
||||
|
||||
/**
|
||||
* @brief Calibration mask type re-definition
|
||||
*
|
||||
* The values are from @ref lr20xx_system_calibration_e
|
||||
*/
|
||||
typedef uint8_t lr20xx_system_calibration_mask_t;
|
||||
|
||||
/**
|
||||
* @brief Error type re-definition
|
||||
*
|
||||
* @see lr20xx_system_errors_e
|
||||
*/
|
||||
typedef uint16_t lr20xx_system_errors_t;
|
||||
|
||||
/**
|
||||
* @brief Configurable DIO pins
|
||||
*/
|
||||
typedef enum lr20xx_system_dio_e
|
||||
{
|
||||
LR20XX_SYSTEM_DIO_5 = 0x05, //!< DIO5
|
||||
LR20XX_SYSTEM_DIO_6 = 0x06, //!< DIO6
|
||||
LR20XX_SYSTEM_DIO_7 = 0x07, //!< DIO7
|
||||
LR20XX_SYSTEM_DIO_8 = 0x08, //!< DIO8
|
||||
LR20XX_SYSTEM_DIO_9 = 0x09, //!< DIO9
|
||||
LR20XX_SYSTEM_DIO_10 = 0x0A, //!< DIO10
|
||||
LR20XX_SYSTEM_DIO_11 = 0x0B, //!< DIO11
|
||||
} lr20xx_system_dio_t;
|
||||
|
||||
/**
|
||||
* @brief DIO pin functions
|
||||
*/
|
||||
typedef enum lr20xx_system_dio_func_e
|
||||
{
|
||||
LR20XX_SYSTEM_DIO_FUNC_NONE = 0x00, //!< No DIO function
|
||||
LR20XX_SYSTEM_DIO_FUNC_IRQ = 0x01, //!< Interrupt request function
|
||||
LR20XX_SYSTEM_DIO_FUNC_RF_SWITCH = 0x02, //!< RF switch control function
|
||||
LR20XX_SYSTEM_DIO_FUNC_GPIO_LOW = 0x05, //!< Set DIO state to low
|
||||
LR20XX_SYSTEM_DIO_FUNC_GPIO_HIGH = 0x06, //!< Set DIO state to high
|
||||
LR20XX_SYSTEM_DIO_FUNC_HF_CLK_OUT = 0x07, //!< High frequency clock output function
|
||||
LR20XX_SYSTEM_DIO_FUNC_LF_CLK_OUT = 0x08, //!< Low frequency clock output function
|
||||
LR20XX_SYSTEM_DIO_FUNC_TX_TRIGGER = 0x09, //!< TX trigger function
|
||||
LR20XX_SYSTEM_DIO_FUNC_RX_TRIGGER = 0x0A, //!< RX trigger function
|
||||
} lr20xx_system_dio_func_t;
|
||||
|
||||
/**
|
||||
* @brief DIO pin drive modes
|
||||
*/
|
||||
typedef enum lr20xx_system_dio_drive_e
|
||||
{
|
||||
LR20XX_SYSTEM_DIO_DRIVE_NONE = 0x00, //!< No pull
|
||||
LR20XX_SYSTEM_DIO_DRIVE_PULL_DOWN = 0x01, //!< Pull down
|
||||
LR20XX_SYSTEM_DIO_DRIVE_PULL_UP = 0x02, //!< Pull up
|
||||
LR20XX_SYSTEM_DIO_DRIVE_AUTO =
|
||||
0x03, //!< If the DIO value in standby mode was ‘1’, it will be pulled-up, if it was ‘0’ it will be pulled-down
|
||||
} lr20xx_system_dio_drive_t;
|
||||
|
||||
/**
|
||||
* @brief DIO RF switch states
|
||||
*/
|
||||
typedef enum lr20xx_system_dio_rf_switch_cfg_state_e
|
||||
{
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_CFG_STATE_LOW = 0x00,
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_CFG_STATE_HIGH = 0x01,
|
||||
} lr20xx_system_dio_rf_switch_cfg_state_t;
|
||||
|
||||
/**
|
||||
* @brief RF switch configuration bitmask definition
|
||||
*/
|
||||
enum lr20xx_system_dio_rf_switch_cfg_e
|
||||
{
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_STANDBY = ( 1 << 0 ),
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_LF = ( 1 << 1 ),
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_TX_LF = ( 1 << 2 ),
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_HF = ( 1 << 3 ),
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_TX_HF = ( 1 << 4 ),
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_ALL_MASK =
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_STANDBY | LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_LF |
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_TX_LF | LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_HF |
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_TX_HF,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief RF switch configuration type
|
||||
*
|
||||
* @see lr20xx_system_dio_rf_switch_cfg_e
|
||||
*/
|
||||
typedef uint8_t lr20xx_system_dio_rf_switch_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Low-frequency clock modes
|
||||
*/
|
||||
typedef enum lr20xx_system_lfclk_cfg_e
|
||||
{
|
||||
LR20XX_SYSTEM_LFCLK_RC = 0x00, //!< Use internal RC 32kHz (Default)
|
||||
LR20XX_SYSTEM_LFCLK_EXT = 0x02, //!< Use externally provided 32kHz signal on DIO11
|
||||
} lr20xx_system_lfclk_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief TCXO supply voltage values
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_SYSTEM_TCXO_CTRL_1_6V = 0x00, //!< Supply voltage = 1.6v
|
||||
LR20XX_SYSTEM_TCXO_CTRL_1_7V = 0x01, //!< Supply voltage = 1.7v
|
||||
LR20XX_SYSTEM_TCXO_CTRL_1_8V = 0x02, //!< Supply voltage = 1.8v
|
||||
LR20XX_SYSTEM_TCXO_CTRL_2_2V = 0x03, //!< Supply voltage = 2.2v
|
||||
LR20XX_SYSTEM_TCXO_CTRL_2_4V = 0x04, //!< Supply voltage = 2.4v
|
||||
LR20XX_SYSTEM_TCXO_CTRL_2_7V = 0x05, //!< Supply voltage = 2.7v
|
||||
LR20XX_SYSTEM_TCXO_CTRL_3_0V = 0x06, //!< Supply voltage = 3.0v
|
||||
LR20XX_SYSTEM_TCXO_CTRL_3_3V = 0x07, //!< Supply voltage = 3.3v
|
||||
} lr20xx_system_tcxo_supply_voltage_t;
|
||||
|
||||
/**
|
||||
* @brief Regulator modes
|
||||
*/
|
||||
typedef enum lr20xx_system_reg_mode_e
|
||||
{
|
||||
LR20XX_SYSTEM_REG_MODE_LDO = 0x00, //!< (Default) Only use the Low-Dropout Regulator
|
||||
LR20XX_SYSTEM_REG_MODE_DCDC = 0x02, //!< Switch on the DC-to-DC regulator in applicable chip modes
|
||||
} lr20xx_system_reg_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Calibration flags
|
||||
*/
|
||||
enum lr20xx_system_calibration_e
|
||||
{
|
||||
LR20XX_SYSTEM_CALIB_LF_RC_MASK = ( 1 << 0 ), //!< Low Frequency clock RC
|
||||
LR20XX_SYSTEM_CALIB_HF_RC_MASK = ( 1 << 1 ), //!< High Frequency clock RC
|
||||
LR20XX_SYSTEM_CALIB_PLL_MASK = ( 1 << 2 ), //!< PLL
|
||||
LR20XX_SYSTEM_CALIB_AAF_MASK = ( 1 << 3 ), //!< Anti aliasing filter bandwidth
|
||||
LR20XX_SYSTEM_CALIB_MU_MASK = ( 1 << 5 ), //!< Measure unit ADC gain
|
||||
LR20XX_SYSTEM_CALIB_PA_OFF_MASK = ( 1 << 6 ), //!< Power amplifier offset
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Value formats
|
||||
*/
|
||||
typedef enum lr20xx_system_value_format_e
|
||||
{
|
||||
LR20XX_SYSTEM_VALUE_FORMAT_RAW = 0x00,
|
||||
LR20XX_SYSTEM_VALUE_FORMAT_UNIT = 0x01,
|
||||
} lr20xx_system_value_format_t;
|
||||
|
||||
/**
|
||||
* @brief Measurement resolution
|
||||
*/
|
||||
typedef enum lr20xx_system_meas_res_e
|
||||
{
|
||||
LR20XX_SYSTEM_MEAS_RES_8_BITS = 0x00,
|
||||
LR20XX_SYSTEM_MEAS_RES_9_BITS = 0x01,
|
||||
LR20XX_SYSTEM_MEAS_RES_10_BITS = 0x02,
|
||||
LR20XX_SYSTEM_MEAS_RES_11_BITS = 0x03,
|
||||
LR20XX_SYSTEM_MEAS_RES_12_BITS = 0x04,
|
||||
LR20XX_SYSTEM_MEAS_RES_13_BITS = 0x05,
|
||||
} lr20xx_system_meas_res_t;
|
||||
|
||||
/**
|
||||
* @brief Source of the measured temperature
|
||||
*/
|
||||
typedef enum lr20xx_system_temp_src_e
|
||||
{
|
||||
LR20XX_SYSTEM_TEMP_SRC_VBE = 0x00,
|
||||
LR20XX_SYSTEM_TEMP_SRC_XOSC = 0x01,
|
||||
LR20XX_SYSTEM_TEMP_SRC_NTC = 0x02,
|
||||
} lr20xx_system_temp_src_t;
|
||||
|
||||
/**
|
||||
* @brief Select the entropy source to enable for random number generator
|
||||
*
|
||||
* It is advised to enable both PLL and ADC entropy sources.
|
||||
* By default PLL and ADC are used as entropy sources.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_SYSTEM_RANDOM_ENTROPY_SOURCE_PLL = 0x01, //!< PLL is used as entropy source. The chip automatically goes to
|
||||
//!< FS mode when needed, and goes back to original mode afterward.
|
||||
LR20XX_SYSTEM_RANDOM_ENTROPY_SOURCE_ADC = 0x02, //!< ADC is used as entropy source. The chip automatically goes to
|
||||
//!< FS mode when needed, and goes back to original mode afterward.
|
||||
} lr20xx_system_random_entropy_source_t;
|
||||
|
||||
/**
|
||||
* @brief Bit mask of entropy source to enable.
|
||||
*
|
||||
* The values are from @ref lr20xx_system_random_entropy_source_t.
|
||||
*/
|
||||
typedef uint8_t lr20xx_system_random_entropy_source_bitmask_t;
|
||||
|
||||
/**
|
||||
* @brief Stand-by modes
|
||||
*/
|
||||
typedef enum lr20xx_system_standby_mode_e
|
||||
{
|
||||
LR20XX_SYSTEM_STANDBY_MODE_RC = 0x00,
|
||||
LR20XX_SYSTEM_STANDBY_MODE_XOSC = 0x01,
|
||||
} lr20xx_system_standby_mode_t;
|
||||
|
||||
/**
|
||||
* @brief High Frequency Clock scaling values
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_32_MHZ = 0x00, //!< Division by 1 - 32 MHz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_16_MHZ = 0x01, //!< Division by 2 - 16 MHz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_8_MHZ = 0x02, //!< Division by 4 - 8 MHz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_4_MHZ = 0x03, //!< Division by 8 - 4 MHz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_2_MHZ = 0x04, //!< Division by 16 - 2 MHz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_1_MHZ = 0x05, //!< Division by 32 - 1 MHz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_500_KHZ = 0x06, //!< Division by 64 - 500 kHz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_250_KHZ = 0x07, //!< Division by 128 - 250 kHz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_125_KHZ = 0x08, //!< Division by 256 - 125 kHz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_62500_HZ = 0x09, //!< Division by 512 - 62500 Hz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_31250_HZ = 0x0A, //!< Division by 1024 - 31250 Hz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_15625_HZ = 0x0B, //!< Division by 2048 - 15625 Hz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_7813_HZ = 0x0C, //!< Division by 4096 - 7812.5 Hz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_3906_HZ = 0x0D, //!< Division by 8192 - 3906.25 Hz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_1953_HZ = 0x0E, //!< Division by 16384 - 1953.125 Hz
|
||||
LR20XX_SYSTEM_HF_CLK_SCALING_977_HZ = 0x0F, //!< Division by 32768 - 976.5625 Hz
|
||||
} lr20xx_system_hf_clk_scaling_t;
|
||||
|
||||
/**
|
||||
* @brief Temperature compensation modes
|
||||
*/
|
||||
typedef enum lr20xx_system_temp_comp_mode_e
|
||||
{
|
||||
LR20XX_SYSTEM_TEMP_COMP_MODE_DISABLED = 0x00,
|
||||
LR20XX_SYSTEM_TEMP_COMP_MODE_RELATIVE = 0x01,
|
||||
LR20XX_SYSTEM_TEMP_COMP_MODE_ABSOLUTE = 0x02,
|
||||
} lr20xx_system_temp_comp_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Low battery detector trimming used to configure threshold triggering a battery low interrupt
|
||||
*/
|
||||
typedef enum lr20xx_system_lbd_trim_e
|
||||
{
|
||||
LR20XX_SYSTEM_LBD_TRIM_1_60_V = 0x00, //!< EoL threshold set to 1.60V
|
||||
LR20XX_SYSTEM_LBD_TRIM_1_67_V = 0x01, //!< EoL threshold set to 1.67V
|
||||
LR20XX_SYSTEM_LBD_TRIM_1_74_V = 0x02, //!< EoL threshold set to 1.74V
|
||||
LR20XX_SYSTEM_LBD_TRIM_1_80_V = 0x03, //!< EoL threshold set to 1.80V
|
||||
LR20XX_SYSTEM_LBD_TRIM_1_88_V = 0x04, //!< EoL threshold set to 1.88V - default value
|
||||
LR20XX_SYSTEM_LBD_TRIM_1_95_V = 0x05, //!< EoL threshold set to 1.98V
|
||||
LR20XX_SYSTEM_LBD_TRIM_2_00_V = 0x06, //!< EoL threshold set to 2.00V
|
||||
LR20XX_SYSTEM_LBD_TRIM_2_10_V = 0x07, //!< EoL threshold set to 2.10V
|
||||
} lr20xx_system_lbd_trim_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_SYSTEM_TYPES_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,690 @@
|
||||
/*!
|
||||
* @file lr20xx_workarounds.c
|
||||
*
|
||||
* @brief System driver workaround implementation for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2025. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "lr20xx_workarounds.h"
|
||||
#include "lr20xx_hal.h"
|
||||
#include "lr20xx_regmem.h"
|
||||
#include "lr20xx_radio_fsk_common_types.h"
|
||||
#include "lr20xx_system.h"
|
||||
#include "lr20xx_radio_ook.h"
|
||||
#include "lr20xx_radio_common.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE MACROS-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_SYNCWORDS ( 7 )
|
||||
#define LR20XX_WORKAROUND_BLUETOOTH_LE_2MBPS_PREAMBLE_LENGTH_BUFFER_LENGTH ( 7 )
|
||||
|
||||
#define LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_FREQUENCY_DRIFT_REGISTER_ADDRESS ( 0x00F30C28 )
|
||||
#define LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_FREQUENCY_DRIFT_REGISTER_MASK ( 0x1F << 5 )
|
||||
#define LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_FREQUENCY_DRIFT_VALUE ( 30 << 5 )
|
||||
|
||||
#define LR20XX_WORKAROUND_LORA_SX1276_COMPATIBILITY_REGISTER_ADDRESS ( 0x00F30A14 )
|
||||
#define LR20XX_WORKAROUND_LORA_SX1276_COMPATIBILITY_REGISTER_MASK ( 3 << 18 )
|
||||
|
||||
#define LR20XX_WORKAROUND_LORA_FREQ_HOP_SX1276_COMPATIBILITY_REGISTER_ADDRESS ( 0x00F30A24 )
|
||||
#define LR20XX_WORKAROUND_LORA_FREQ_HOP_SX1276_COMPATIBILITY_REGISTER_MASK ( 1 << 18 )
|
||||
|
||||
#define LR20XX_WORKAROUND_OOK_DETECTION_THRESHOLD_REGISTER_ADDRESS ( 0x00F30E14 )
|
||||
#define LR20XX_WORKAROUND_OOK_DETECTION_THRESHOLD_REGISTER_MASK ( 0x7F << 20 )
|
||||
|
||||
#define LR20XX_WORKAROUND_RTTOF_RF_FREQ_ADDRESS ( 0x00F40144 )
|
||||
#define LR20XX_WORKAROUND_RTTOF_RF_FREQ_MASK ( 0x7F )
|
||||
|
||||
#define LR20XX_WORKAROUND_RTTOF_RSSI_MAX_GAIN_REGISTER_ADDRESS ( 0x00F301A4 )
|
||||
#define LR20XX_WORKAROUND_RTTOF_RSSI_POWER_OFFSET_REGISTER_ADDRESS ( 0x00F30128 )
|
||||
|
||||
#define LR20XX_WORKAROUND_DCDC_ADC_CTRL_REGISTER_ADDRESS ( 0x00F40200 )
|
||||
#define LR20XX_WORKAROUND_DCDC_RX_PATH_REGISTER_ADDRESS ( 0x00F40430 )
|
||||
#define LR20XX_WORKAROUND_DCDC_SWITCHER_REGISTER_ADDRESS ( 0x00F20024 )
|
||||
#define LR20XX_WORKAROUND_DCDC_SWITCHER_RISE_REGISTER_MASK ( 0xF << 20 )
|
||||
#define LR20XX_WORKAROUND_DCDC_SWITCHER_FALL_REGISTER_MASK ( 0xF << 16 )
|
||||
#define LR20XX_WORKAROUND_DCDC_FREQ_LF_REGISTER_ADDRESS ( 0x80004C )
|
||||
#define LR20XX_WORKAROUND_DCDC_RF_FREQ_ADDRESS ( LR20XX_WORKAROUND_RTTOF_RF_FREQ_ADDRESS )
|
||||
|
||||
#define LR20XX_WORKAROUND_RESULT_DEVIATION_CHANNEL_FILTER_ADDRESS ( 0xF3013C )
|
||||
#define LR20XX_WORKAROUND_RESULT_DEVIATION_CHANNEL_FILTER_MASK ( 0x38 )
|
||||
#define LR20XX_WORKAROUND_RESULT_DEVIATION_CHANNEL_FILTER_VALUE ( 0x30 )
|
||||
|
||||
#define LR20XX_WORKAROUND_RESULT_DEVIATION_DCC_ADDRESS ( 0xF30134 )
|
||||
#define LR20XX_WORKAROUND_RESULT_DEVIATION_DCC_MASK ( 0x1B )
|
||||
#define LR20XX_WORKAROUND_RESULT_DEVIATION_DCC_MANAGER_VALUE ( 0x08 )
|
||||
#define LR20XX_WORKAROUND_RESULT_DEVIATION_DCC_SUBORDINATE_VALUE ( 0x0A )
|
||||
|
||||
#define LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_ADDRESS ( 0x00F30B50 )
|
||||
#define LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_MASK ( 0x7 << 24 )
|
||||
#define LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_SET_VALUE ( 0x0 << 24 )
|
||||
#define LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_RESET_VALUE ( 0x1 << 24 )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE CONSTANTS -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE TYPES -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE VARIABLES -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DECLARATION -------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Helper function to write the appropriate field to store LoRa SX1276 compatibility parameter
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param value True to enable the compatibility mode, false to disable it
|
||||
* @return Operation status
|
||||
*/
|
||||
static lr20xx_status_t lr20xx_workaround_lora_sx1276_compatibility_write_value( const void* context, bool value );
|
||||
|
||||
/**
|
||||
* @brief Helper function to write the appropriate field to store LoRa frequency hopping SX1276 compatibility parameter
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param value True to enable the compatibility mode, false to disable it
|
||||
* @return Operation status
|
||||
*/
|
||||
static lr20xx_status_t lr20xx_workaround_lora_frequency_hopping_sx1276_compatibility_write_value( const void* context,
|
||||
bool value );
|
||||
|
||||
/**
|
||||
* @brief Read the configured SF value configured
|
||||
*
|
||||
* This command is to be used only when disabling the SX1276 LoRa compatibility mode.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param [out] sf The configure SF
|
||||
*
|
||||
* @return Operation status
|
||||
*/
|
||||
static lr20xx_status_t lr20xx_workaround_lora_sx1276_compatibility_read_sf_value( const void* context, uint8_t* sf );
|
||||
|
||||
/**
|
||||
* @brief Read RTToF max gain and power offset from the LR20xx register
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param [out] max_gain Max gain read from register
|
||||
* @param [out] power_offset Power offset read from register
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_workarounds_rttof_rssi_computation_apply_correction, lr20xx_workarounds_rttof_rssi_computation
|
||||
*/
|
||||
static lr20xx_status_t lr20xx_workarounds_rttof_rssi_computation_get_gain_power( const void* context,
|
||||
uint16_t* max_gain,
|
||||
int16_t* power_offset );
|
||||
|
||||
/**
|
||||
* @brief Compute RTToF RSSI correction from max gain, power offset, and raw RSSI value
|
||||
*
|
||||
* @param max_gain The max gain obtained from reading the LR20xx register
|
||||
* @param power_offset The power offset obtained from reading the LR20xx register
|
||||
* @param raw_rssi The raw RSSI value typically obtained from SPI response to @ref lr20xx_rttof_get_results, before
|
||||
* converting value to dB
|
||||
*
|
||||
* @return uint8_t The corrected RSSI value
|
||||
*
|
||||
* @see lr20xx_workarounds_rttof_rssi_computation_get_gain_power, lr20xx_workarounds_rttof_rssi_computation
|
||||
*/
|
||||
static uint8_t lr20xx_workarounds_rttof_rssi_computation_apply_correction( uint16_t max_gain, int16_t power_offset,
|
||||
uint8_t raw_rssi );
|
||||
|
||||
/**
|
||||
* @brief Set the DCDC regulator frequency
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param frequency [in] The frequency to set, expressed in Hz
|
||||
*
|
||||
* @return Operation status
|
||||
*/
|
||||
static lr20xx_status_t lr20xx_workaround_dcdc_set_frequency( const void* context, uint32_t frequency );
|
||||
|
||||
/**
|
||||
* @brief Get the RF frequency configured
|
||||
*
|
||||
* This function must be used only in the context of DCDC workaround.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param [out] frequency The RF frequency, in Hz
|
||||
*
|
||||
* @return Operation status
|
||||
*/
|
||||
static lr20xx_status_t lr20xx_workaround_dcdc_get_rf_frequency( const void* context, uint32_t* frequency );
|
||||
|
||||
static uint32_t pll_step_to_hz( uint32_t pll_steps );
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS DEFINITION ---------------------------------------------
|
||||
*/
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_bluetooth_le_phy_coded_syncwords( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_SYNCWORDS] = { 0x02, 0x30, 0x01, 0x20,
|
||||
0x00, 0x09, 0x00 };
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write( context, cbuffer, LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_SYNCWORDS,
|
||||
0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_bluetooth_le_phy_coded_frequency_drift( const void* context )
|
||||
{
|
||||
return lr20xx_regmem_write_regmem32_mask( context,
|
||||
LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_FREQUENCY_DRIFT_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_FREQUENCY_DRIFT_REGISTER_MASK,
|
||||
LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_FREQUENCY_DRIFT_VALUE );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_bluetooth_le_phy_coded_frequency_drift_store_retention_mem( const void* context,
|
||||
uint8_t slot )
|
||||
{
|
||||
return lr20xx_system_add_register_to_retention_mem(
|
||||
context, slot, LR20XX_WORKAROUND_BLUETOOTH_LE_PHY_CODED_FREQUENCY_DRIFT_REGISTER_ADDRESS );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_bluetooth_le_2mbps_preamble_length( const void* context )
|
||||
{
|
||||
const uint8_t cbuffer[LR20XX_WORKAROUND_BLUETOOTH_LE_2MBPS_PREAMBLE_LENGTH_BUFFER_LENGTH] = { 0x02, 0x30, 0x01,
|
||||
0x21, 0x00, 0x07,
|
||||
0x00 };
|
||||
|
||||
return ( lr20xx_status_t ) lr20xx_hal_write(
|
||||
context, cbuffer, LR20XX_WORKAROUND_BLUETOOTH_LE_2MBPS_PREAMBLE_LENGTH_BUFFER_LENGTH, 0, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_lora_enable_sx1276_compatibility_mode( const void* context )
|
||||
{
|
||||
return lr20xx_workaround_lora_sx1276_compatibility_write_value( context, true );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_lora_disable_sx1276_compatibility_mode( const void* context )
|
||||
{
|
||||
// 1. Get the currently configured SF value
|
||||
uint8_t sf = 0;
|
||||
const lr20xx_status_t get_sf_status = lr20xx_workaround_lora_sx1276_compatibility_read_sf_value( context, &sf );
|
||||
|
||||
// 2. Modify the compatibility mode value depending on currently configured SF
|
||||
if( get_sf_status == LR20XX_STATUS_OK )
|
||||
{
|
||||
return lr20xx_workaround_lora_sx1276_compatibility_write_value( context, ( ( sf <= 6 ) ? true : false ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_sf_status;
|
||||
}
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_lora_sx1276_compatibility_mode_store_retention_mem( const void* context,
|
||||
uint8_t slot )
|
||||
{
|
||||
return lr20xx_system_add_register_to_retention_mem( context, slot,
|
||||
LR20XX_WORKAROUND_LORA_SX1276_COMPATIBILITY_REGISTER_ADDRESS );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_lora_freq_hop_enable_sx1276_compatibility_mode( const void* context )
|
||||
{
|
||||
return lr20xx_workaround_lora_frequency_hopping_sx1276_compatibility_write_value( context, true );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_lora_freq_hop_disable_sx1276_compatibility_mode( const void* context )
|
||||
{
|
||||
return lr20xx_workaround_lora_frequency_hopping_sx1276_compatibility_write_value( context, false );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_lora_freq_hop_sx1276_compatibility_mode_store_retention_mem( const void* context,
|
||||
uint8_t slot )
|
||||
{
|
||||
return lr20xx_system_add_register_to_retention_mem(
|
||||
context, slot, LR20XX_WORKAROUND_LORA_FREQ_HOP_SX1276_COMPATIBILITY_REGISTER_ADDRESS );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_ook_set_detection_threshold_level( const void* context, int16_t threshold_level_db )
|
||||
{
|
||||
const int threshold_db = threshold_level_db + 10 + 64;
|
||||
return lr20xx_regmem_write_regmem32_mask(
|
||||
context, LR20XX_WORKAROUND_OOK_DETECTION_THRESHOLD_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_OOK_DETECTION_THRESHOLD_REGISTER_MASK,
|
||||
( ( ( uint32_t ) threshold_db ) << 20u ) & LR20XX_WORKAROUND_OOK_DETECTION_THRESHOLD_REGISTER_MASK );
|
||||
}
|
||||
|
||||
int16_t lr20xx_workarounds_ook_get_default_detection_threshold_level( lr20xx_radio_fsk_common_bw_t bw )
|
||||
{
|
||||
switch( bw )
|
||||
{
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_3_500_HZ:
|
||||
{
|
||||
return -135;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_4_200_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_4_300_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_4_500_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_4_800_HZ:
|
||||
{
|
||||
return -134;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_5_200_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_5_600_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_5_800_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_6_000_HZ:
|
||||
{
|
||||
return -133;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_6_900_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_7_400_HZ:
|
||||
{
|
||||
return -132;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_8_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_8_300_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_8_700_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_8_900_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_9_600_HZ:
|
||||
{
|
||||
return -131;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_10_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_11_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_12_000_HZ:
|
||||
{
|
||||
return -130;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_13_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_14_000_HZ:
|
||||
{
|
||||
return -129;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_16_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_17_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_19_000_HZ:
|
||||
{
|
||||
return -128;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_20_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_22_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_23_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_24_000_HZ:
|
||||
{
|
||||
return -127;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_27_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_29_000_HZ:
|
||||
{
|
||||
return -126;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_32_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_33_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_34_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_35_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_38_000_HZ:
|
||||
{
|
||||
return -125;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_41_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_44_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_46_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_48_000_HZ:
|
||||
{
|
||||
return -124;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_55_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_59_000_HZ:
|
||||
{
|
||||
return -123;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_64_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_66_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_69_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_71_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_76_000_HZ:
|
||||
{
|
||||
return -122;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_83_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_89_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_92_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_96_000_HZ:
|
||||
{
|
||||
return -121;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_111_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_119_000_HZ:
|
||||
{
|
||||
return -120;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_128_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_133_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_138_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_142_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_153_000_HZ:
|
||||
{
|
||||
return -119;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_166_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_178_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_185_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_192_000_HZ:
|
||||
{
|
||||
return -118;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_222_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_238_000_HZ:
|
||||
{
|
||||
return -117;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_256_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_266_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_277_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_285_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_307_000_HZ:
|
||||
{
|
||||
return -116;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_333_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_357_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_370_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_384_000_HZ:
|
||||
{
|
||||
return -115;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_444_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_476_000_HZ:
|
||||
{
|
||||
return -114;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_512_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_533_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_555_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_571_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_615_000_HZ:
|
||||
{
|
||||
return -113;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_666_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_714_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_740_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_769_000_HZ:
|
||||
{
|
||||
return -112;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_888_000_HZ:
|
||||
{
|
||||
return -111;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_1_111_000_HZ:
|
||||
{
|
||||
return -110;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_1_333_000_HZ:
|
||||
{
|
||||
return -109;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_2_222_000_HZ:
|
||||
{
|
||||
return -107;
|
||||
}
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_2_666_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_2_857_000_HZ:
|
||||
case LR20XX_RADIO_FSK_COMMON_RX_BW_3_076_000_HZ:
|
||||
{
|
||||
return -106;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_truncate_pll_freq_step( const void* context )
|
||||
{
|
||||
return lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_RTTOF_RF_FREQ_ADDRESS,
|
||||
LR20XX_WORKAROUND_RTTOF_RF_FREQ_MASK, 0 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_rssi_computation( const void* context, uint8_t rssi1_raw_value,
|
||||
uint8_t rssi2_raw_value, uint8_t* rssi1_raw_fixed,
|
||||
uint8_t* rssi2_raw_fixed )
|
||||
{
|
||||
uint16_t max_gain = 0;
|
||||
int16_t power_offset = 0;
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_workarounds_rttof_rssi_computation_get_gain_power( context, &max_gain, &power_offset ) );
|
||||
( *rssi1_raw_fixed ) =
|
||||
lr20xx_workarounds_rttof_rssi_computation_apply_correction( max_gain, power_offset, rssi1_raw_value );
|
||||
if( rssi2_raw_fixed != 0 )
|
||||
{
|
||||
( *rssi2_raw_fixed ) =
|
||||
lr20xx_workarounds_rttof_rssi_computation_apply_correction( max_gain, power_offset, rssi2_raw_value );
|
||||
}
|
||||
|
||||
// OK is returned here, as an error would have returned on previous RETURN_STATUS_ON_NOT_OK
|
||||
return LR20XX_STATUS_OK;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_dcdc_reset( const void* context )
|
||||
{
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_DCDC_SWITCHER_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_DCDC_SWITCHER_RISE_REGISTER_MASK, 15 << 20 ) );
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_DCDC_SWITCHER_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_DCDC_SWITCHER_FALL_REGISTER_MASK, 15 << 16 ) );
|
||||
return lr20xx_workaround_dcdc_set_frequency( context, 2800000 );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_dcdc_configure( const void* context )
|
||||
{
|
||||
uint32_t adc_ctrl_raw = 0;
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_read_regmem32( context, LR20XX_WORKAROUND_DCDC_ADC_CTRL_REGISTER_ADDRESS, &adc_ctrl_raw, 1 ) );
|
||||
const uint32_t ana_dec = ( adc_ctrl_raw >> 8 ) & 0x7;
|
||||
|
||||
uint32_t rx_path_raw = 0;
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_read_regmem32( context, LR20XX_WORKAROUND_DCDC_RX_PATH_REGISTER_ADDRESS, &rx_path_raw, 1 ) );
|
||||
const bool is_rx_hf = ( ( rx_path_raw & 0x3 ) == 1 );
|
||||
|
||||
if( ( is_rx_hf == false ) && ( ( ana_dec == 1 ) || ( ana_dec == 2 ) ) )
|
||||
{
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_DCDC_SWITCHER_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_DCDC_SWITCHER_RISE_REGISTER_MASK, 11 << 20 ) );
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_DCDC_SWITCHER_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_DCDC_SWITCHER_FALL_REGISTER_MASK, 13 << 16 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_DCDC_SWITCHER_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_DCDC_SWITCHER_RISE_REGISTER_MASK, 15 << 20 ) );
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_DCDC_SWITCHER_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_DCDC_SWITCHER_FALL_REGISTER_MASK, 15 << 16 ) );
|
||||
}
|
||||
|
||||
if( ana_dec == 1 )
|
||||
{
|
||||
return lr20xx_workaround_dcdc_set_frequency( context, 4300000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return lr20xx_workaround_dcdc_set_frequency( context, 2800000 );
|
||||
}
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_dcdc_store_retention_mem( const void* context, uint8_t slot )
|
||||
{
|
||||
return lr20xx_system_add_register_to_retention_mem( context, slot,
|
||||
LR20XX_WORKAROUND_DCDC_SWITCHER_REGISTER_ADDRESS );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_results_deviation( const void* context, bool is_manager )
|
||||
{
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_RESULT_DEVIATION_CHANNEL_FILTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_RESULT_DEVIATION_CHANNEL_FILTER_MASK,
|
||||
LR20XX_WORKAROUND_RESULT_DEVIATION_CHANNEL_FILTER_VALUE ) );
|
||||
return lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_RESULT_DEVIATION_DCC_ADDRESS,
|
||||
LR20XX_WORKAROUND_RESULT_DEVIATION_DCC_MASK,
|
||||
is_manager ? LR20XX_WORKAROUND_RESULT_DEVIATION_DCC_MANAGER_VALUE
|
||||
: LR20XX_WORKAROUND_RESULT_DEVIATION_DCC_SUBORDINATE_VALUE );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_results_deviation_store_retention_mem( const void* context, uint8_t slot_1,
|
||||
uint8_t slot_2 )
|
||||
{
|
||||
RETURN_STATUS_ON_NOT_OK( lr20xx_system_add_register_to_retention_mem(
|
||||
context, slot_1, LR20XX_WORKAROUND_RESULT_DEVIATION_CHANNEL_FILTER_ADDRESS ) );
|
||||
return lr20xx_system_add_register_to_retention_mem( context, slot_2,
|
||||
LR20XX_WORKAROUND_RESULT_DEVIATION_DCC_ADDRESS );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_extended_stuck_second_request_enable( const void* context )
|
||||
{
|
||||
return lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_ADDRESS,
|
||||
LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_MASK,
|
||||
LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_SET_VALUE );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_extended_stuck_second_request_disable( const void* context )
|
||||
{
|
||||
return lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_ADDRESS,
|
||||
LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_MASK,
|
||||
LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_RESET_VALUE );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_extended_stuck_second_request_store_retention_mem( const void* context,
|
||||
uint8_t slot )
|
||||
{
|
||||
return lr20xx_system_add_register_to_retention_mem( context, slot, LR20XX_WORKAROUND_RTTOF_EXTENDED_STUCK_ADDRESS );
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DEFINITION --------------------------------------------
|
||||
*/
|
||||
|
||||
lr20xx_status_t lr20xx_workaround_lora_sx1276_compatibility_write_value( const void* context, bool value )
|
||||
{
|
||||
return lr20xx_regmem_write_regmem32_mask( context, LR20XX_WORKAROUND_LORA_SX1276_COMPATIBILITY_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_LORA_SX1276_COMPATIBILITY_REGISTER_MASK,
|
||||
( value ? ( 1 << 19 ) : 0 ) );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workaround_lora_frequency_hopping_sx1276_compatibility_write_value( const void* context,
|
||||
bool value )
|
||||
{
|
||||
return lr20xx_regmem_write_regmem32_mask(
|
||||
context, LR20XX_WORKAROUND_LORA_FREQ_HOP_SX1276_COMPATIBILITY_REGISTER_ADDRESS,
|
||||
LR20XX_WORKAROUND_LORA_FREQ_HOP_SX1276_COMPATIBILITY_REGISTER_MASK, ( value ? ( 1 << 18 ) : 0 ) );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workaround_lora_sx1276_compatibility_read_sf_value( const void* context, uint8_t* sf )
|
||||
{
|
||||
uint32_t raw_register_value = 0;
|
||||
const lr20xx_status_t read_status = lr20xx_regmem_read_regmem32(
|
||||
context, LR20XX_WORKAROUND_LORA_SX1276_COMPATIBILITY_REGISTER_ADDRESS, &raw_register_value, 1 );
|
||||
if( read_status == LR20XX_STATUS_OK )
|
||||
{
|
||||
*sf = raw_register_value & 0x0f;
|
||||
}
|
||||
return read_status;
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_rssi_computation_get_gain_power( const void* context, uint16_t* max_gain,
|
||||
int16_t* power_offset )
|
||||
{
|
||||
uint32_t max_gain_raw = 0;
|
||||
RETURN_STATUS_ON_NOT_OK( lr20xx_regmem_read_regmem32(
|
||||
context, LR20XX_WORKAROUND_RTTOF_RSSI_MAX_GAIN_REGISTER_ADDRESS, &max_gain_raw, 1 ) );
|
||||
( *max_gain ) = ( uint16_t ) ( max_gain_raw & 0x03FF );
|
||||
|
||||
uint32_t power_offset_raw = 0;
|
||||
RETURN_STATUS_ON_NOT_OK( lr20xx_regmem_read_regmem32(
|
||||
context, LR20XX_WORKAROUND_RTTOF_RSSI_POWER_OFFSET_REGISTER_ADDRESS, &power_offset_raw, 1 ) );
|
||||
const int16_t power_offset_raw_value = ( power_offset_raw >> 6 ) & 0x3F;
|
||||
( *power_offset ) = ( int16_t ) ( ( ( power_offset_raw_value ) > 32 ) ? ( power_offset_raw_value - ( int16_t ) 64 )
|
||||
: power_offset_raw_value );
|
||||
return LR20XX_STATUS_OK;
|
||||
}
|
||||
|
||||
uint8_t lr20xx_workarounds_rttof_rssi_computation_apply_correction( uint16_t max_gain, int16_t power_offset,
|
||||
uint8_t raw_rssi )
|
||||
{
|
||||
return ( uint8_t ) ( 208 + ( max_gain >> 1 ) + power_offset - ( raw_rssi << 1 ) );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workaround_dcdc_set_frequency( const void* context, uint32_t frequency )
|
||||
{
|
||||
const uint32_t freq_lf = ( uint32_t ) ( ( float ) frequency * 1.048576f );
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_write_regmem32( context, LR20XX_WORKAROUND_DCDC_FREQ_LF_REGISTER_ADDRESS, &freq_lf, 1 ) );
|
||||
uint32_t rf_frequency = 0;
|
||||
RETURN_STATUS_ON_NOT_OK( lr20xx_workaround_dcdc_get_rf_frequency( context, &rf_frequency ) );
|
||||
return lr20xx_radio_common_set_rf_freq( context, rf_frequency );
|
||||
}
|
||||
|
||||
lr20xx_status_t lr20xx_workaround_dcdc_get_rf_frequency( const void* context, uint32_t* frequency )
|
||||
{
|
||||
uint32_t raw_rf_freq = 0;
|
||||
RETURN_STATUS_ON_NOT_OK(
|
||||
lr20xx_regmem_read_regmem32( context, LR20XX_WORKAROUND_DCDC_RF_FREQ_ADDRESS, &raw_rf_freq, 1 ) );
|
||||
*frequency = pll_step_to_hz( raw_rf_freq );
|
||||
return LR20XX_STATUS_OK;
|
||||
}
|
||||
|
||||
uint32_t pll_step_to_hz( uint32_t pll_steps )
|
||||
{
|
||||
const uint_least64_t numerator = ( ( uint_least64_t ) pll_steps * ( uint_least64_t ) 15625ULL );
|
||||
const uint_least64_t denominator = ( ( uint_least64_t ) ( 1 << 14 ) ); // 1<<14 is 2**14
|
||||
return ( uint32_t ) ( ( numerator + denominator - 1 ) / denominator );
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,491 @@
|
||||
/*!
|
||||
* @file lr20xx_workarounds.h
|
||||
*
|
||||
* @brief System driver workarounds definition for LR20XX
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2025. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_WORKAROUNDS_H
|
||||
#define LR20XX_WORKAROUNDS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "lr20xx_status.h"
|
||||
#include "lr20xx_radio_fsk_common_types.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_WORKAROUNDS_DISABLE_AUTOMATIC_DCDC_RESET
|
||||
#define LR20XX_WORKAROUNDS_CONDITIONAL_APPLY_AUTOMATIC_DCDC_RESET( cont ) lr20xx_workarounds_dcdc_reset( cont )
|
||||
#else
|
||||
#define LR20XX_WORKAROUNDS_CONDITIONAL_APPLY_AUTOMATIC_DCDC_RESET( cont ) LR20XX_STATUS_OK
|
||||
#endif // LR20XX_WORKAROUNDS_DISABLE_AUTOMATIC_DCDC_RESET
|
||||
|
||||
#ifndef LR20XX_WORKAROUNDS_DISABLE_AUTOMATIC_DCDC_CONFIGURE
|
||||
#define LR20XX_WORKAROUNDS_CONDITIONAL_APPLY_AUTOMATIC_DCDC_CONFIGURE( cont ) lr20xx_workarounds_dcdc_configure( cont )
|
||||
#else
|
||||
#define LR20XX_WORKAROUNDS_CONDITIONAL_APPLY_AUTOMATIC_DCDC_CONFIGURE( cont ) LR20XX_STATUS_OK
|
||||
#endif // LR20XX_WORKAROUNDS_DISABLE_AUTOMATIC_DCDC_CONFIGURE
|
||||
|
||||
#ifndef LR20XX_WORKAROUND_DISABLE_AUTOMATIC_BLE_2MBPS_PREAMBLE_LENGTH
|
||||
#define LR20XX_WORKAROUND_CONDITIONAL_APPLY_BLE_2MBPS_PREAMBLE_LENGTH( cont ) \
|
||||
lr20xx_workarounds_bluetooth_le_2mbps_preamble_length( cont )
|
||||
#else
|
||||
#define LR20XX_WORKAROUND_CONDITIONAL_APPLY_BLE_2MBPS_PREAMBLE_LENGTH( cont ) LR20XX_STATUS_OK
|
||||
#endif // LR20XX_WORKAROUND_DISABLE_AUTOMATIC_BLE_2MBPS_PREAMBLE_LENGTH
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Apply workaround for syncwords usage with BLE LE coded PHY
|
||||
*
|
||||
* This workaround is to be applied after configuring Bluetooth LE modulation and packet, if phy @ref
|
||||
* LR20XX_RADIO_BLUETOOTH_LE_PHY_LE_CODED_125KB or @ref LR20XX_RADIO_BLUETOOTH_LE_PHY_LE_CODED_500KB are configured.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_radio_bluetooth_le_set_modulation_params, lr20xx_radio_bluetooth_le_set_pkt_params,
|
||||
* lr20xx_workarounds_bluetooth_le_phy_coded_frequency_drift
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_bluetooth_le_phy_coded_syncwords( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Apply workaround to support frequency drift with BLE LE coded PHY
|
||||
*
|
||||
* This workaround is to be applied after configuring Bluetooth LE modulation and packet, if phy @ref
|
||||
* LR20XX_RADIO_BLUETOOTH_LE_PHY_LE_CODED_125KB or @ref LR20XX_RADIO_BLUETOOTH_LE_PHY_LE_CODED_500KB are configured.
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
*
|
||||
* @returns Operation status
|
||||
*
|
||||
* @see lr20xx_radio_bluetooth_le_set_modulation_params, lr20xx_radio_bluetooth_le_set_pkt_params,
|
||||
* lr20xx_workarounds_bluetooth_le_phy_coded_syncwords
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_bluetooth_le_phy_coded_frequency_drift( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Store the Bluetooth LE PHY coded frequency drift workaround in retention memory
|
||||
*
|
||||
* Calling this function allows to store the Bluetooth LE PHY coded frequency drift workaround state during sleep mode.
|
||||
* This helper function internally calls @ref lr20xx_system_add_register_to_retention_mem with the appropriate register
|
||||
* address.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param slot Index in the storage list. Allowed values [0:31]
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_system_add_register_to_retention_mem, lr20xx_workarounds_bluetooth_le_phy_coded_frequency_drift
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_bluetooth_le_phy_coded_frequency_drift_store_retention_mem( const void* context,
|
||||
uint8_t slot );
|
||||
|
||||
/**
|
||||
* @brief Fix preamble length for Bluetooth LE 2Mbps
|
||||
*
|
||||
* The preamble length is by default incorrect for 2Mbps datarate. This workaround fixes the preamble length.
|
||||
* It must be called right after @ref lr20xx_radio_bluetooth_le_set_modulation_params if the mode is @ref
|
||||
* LR20XX_RADIO_BLUETOOTH_LE_PHY_LE_2M.
|
||||
*
|
||||
* Note that by default this workaround is automatically applied by @ref
|
||||
* lr20xx_radio_bluetooth_le_set_modulation_params, unless the macro @ref
|
||||
* LR20XX_WORKAROUND_DISABLE_AUTOMATIC_BLE_2MBPS_PREAMBLE_LENGTH is defined.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @return Operation status
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_bluetooth_le_2mbps_preamble_length( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Enable LoRa compatibility mode with SX1276
|
||||
*
|
||||
* If the SX1276 LoRa compatibility is required, this workaround must be called after calling @ref
|
||||
* lr20xx_radio_lora_set_modulation_params.
|
||||
*
|
||||
* SX1276 LoRa compatibility mode allows:
|
||||
* - transmission to, and reception from, SX1276 LoRa packets at SF6 only in implicit mode (@ref
|
||||
* LR20XX_RADIO_LORA_PKT_IMPLICIT); and
|
||||
* - syncword nibbles greater than 7 for all SF.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_workarounds_lora_disable_sx1276_compatibility_mode,
|
||||
* lr20xx_workarounds_lora_sx1276_compatibility_mode_store_retention_mem
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_lora_enable_sx1276_compatibility_mode( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Disable the LoRa compatibility mode with SX1276
|
||||
*
|
||||
* To disable the SX1276 LoRa compatibility mode, this workaround can be call either before or after @ref
|
||||
* lr20xx_radio_lora_set_modulation_params.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_workarounds_lora_enable_sx1276_compatibility_mode,
|
||||
* lr20xx_workarounds_lora_sx1276_compatibility_mode_store_retention_mem
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_lora_disable_sx1276_compatibility_mode( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Store the LoRa SX1276 compatibility mode in retention memory
|
||||
*
|
||||
* Calling this function allows to store the SX1276 LoRa compatible state during sleep mode.
|
||||
* This helper function internally calls @ref lr20xx_system_add_register_to_retention_mem with the appropriate register
|
||||
* address.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param slot Index in the storage list. Allowed values [0:31]
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_system_add_register_to_retention_mem, lr20xx_workarounds_lora_enable_sx1276_compatibility_mode,
|
||||
* lr20xx_workarounds_lora_disable_sx1276_compatibility_mode
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_lora_sx1276_compatibility_mode_store_retention_mem( const void* context,
|
||||
uint8_t slot );
|
||||
|
||||
/**
|
||||
* @brief Enable the SX1276 compatibility mode for LoRa intra-packet frequency hopping
|
||||
*
|
||||
* If the LoRa intra-packet frequency hopping compatible with SX1276 is required, this function must be called after
|
||||
* @ref lr20xx_radio_lora_set_freq_hop.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_radio_lora_set_freq_hop, lr20xx_workarounds_lora_freq_hop_disable_sx1276_compatibility_mode,
|
||||
* lr20xx_workarounds_lora_freq_hop_sx1276_compatibility_mode_store_retention_mem
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_lora_freq_hop_enable_sx1276_compatibility_mode( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Disable the SX1276 compatibility mode for LoRa intra-packet frequency hopping
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_radio_lora_set_freq_hop, lr20xx_workarounds_lora_freq_hop_enable_sx1276_compatibility_mode,
|
||||
* lr20xx_workarounds_lora_freq_hop_sx1276_compatibility_mode_store_retention_mem
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_lora_freq_hop_disable_sx1276_compatibility_mode( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Store the SX1276 compatibility mode for LoRa intra-packet frequency hopping in retention memory
|
||||
*
|
||||
* Calling this function allows to store the SX1276 LoRa intra-packet frequency hopping compatible state during sleep
|
||||
* mode. This helper function internally calls @ref lr20xx_system_add_register_to_retention_mem with the appropriate
|
||||
* register address.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param slot Index in the storage list. Allowed values [0:31]
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_system_add_register_to_retention_mem, lr20xx_workarounds_lora_freq_hop_enable_sx1276_compatibility_mode,
|
||||
* lr20xx_workarounds_lora_freq_hop_disable_sx1276_compatibility_mode
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_lora_freq_hop_sx1276_compatibility_mode_store_retention_mem( const void* context,
|
||||
uint8_t slot );
|
||||
|
||||
/**
|
||||
* @brief Override the OOK detection threshold level
|
||||
*
|
||||
* The OOK detection threshold level is automatically computed by the LR20xx depending on the modulation parameters.
|
||||
* However the computed value may be too conservative which increase the packet error rate.
|
||||
* The detection threshold level can be therefore modified with this function. The threshold to provide is typically the
|
||||
* noise level returned by @ref lr20xx_radio_common_get_rssi_inst using the same modulation parameters, if it is higher
|
||||
* than the LR20xx default computed value.
|
||||
*
|
||||
* Refer to @ref lr20xx_workarounds_ook_get_default_detection_threshold_level to obtain the default computed values
|
||||
* depending on modulation bandwidth.
|
||||
*
|
||||
* This function should be called after @ref lr20xx_radio_ook_set_modulation_params.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param threshold_level_db The threshold level to set, in dB
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_radio_ook_set_modulation_params, lr20xx_radio_common_get_rssi_inst,
|
||||
* lr20xx_workarounds_ook_get_default_detection_threshold_level
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_ook_set_detection_threshold_level( const void* context, int16_t threshold_level_db );
|
||||
|
||||
/**
|
||||
* @brief Helper function that returns default OOK detection threshold level
|
||||
*
|
||||
* This helper function helps to determine if the workaround @ref lr20xx_workarounds_ook_set_detection_threshold_level
|
||||
* is to be applied.
|
||||
*
|
||||
* @param bw The bandwidth for which the detection threshold is to be computed
|
||||
*
|
||||
* @return The default OOK detection threshold level, or 0 if the bandwidth @p bw is unknown
|
||||
*
|
||||
* @see lr20xx_workarounds_ook_set_detection_threshold_level
|
||||
*
|
||||
*/
|
||||
int16_t lr20xx_workarounds_ook_get_default_detection_threshold_level( lr20xx_radio_fsk_common_bw_t bw );
|
||||
|
||||
/**
|
||||
* @brief Apply workaround to truncate internal PLL frequency step for RTToF operation
|
||||
*
|
||||
* Unexpected RTToF results may be obtained if the RF frequency is not set to a value multiple of 122Hz.
|
||||
* This workaround ensures internal RF frequency is configured to a multiple of 122Hz.
|
||||
*
|
||||
* This workaround must be applied after configuring the RF frequency of RTToF ranging operations with @ref
|
||||
* lr20xx_radio_common_set_rf_freq.
|
||||
* After applying the workaround, the RF frequency is therefore modified by a quantity inferior or equal to 122Hz
|
||||
* compared to the value set by last call to @ref lr20xx_radio_common_set_rf_freq.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_radio_common_set_rf_freq
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_truncate_pll_freq_step( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Fix RTToF RSSI raw values
|
||||
*
|
||||
* This workaround fixes raw values of RTToF RSSIs by gathering information from the chip.
|
||||
* This function can be used either for:
|
||||
* - normal result (with only one RSSI value), setting @p rssi2_raw_fixed to null pointer; and
|
||||
* - extended result (with two RSSI values).
|
||||
*
|
||||
* This workaround handles the raw RSSI values, which are available only in the internal of the driver, and not exposed
|
||||
* by the API. It is however possible to retrieve approximation of raw RSSI value from exposed one in dB (and the other
|
||||
* way around) thanks to the following pseudo-code:
|
||||
* @code{.c}
|
||||
* // Convert from RSSI in dB to raw value
|
||||
* uint8_t raw_rssi_value = -(rssi_db * 2);
|
||||
*
|
||||
* // Convert from raw RSSI value to dB value
|
||||
* uint8_t rssi_db = -(raw_rssi_value / 2);
|
||||
* @endcode
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param [in] rssi1_raw_value Raw value of RSSI1
|
||||
* @param [in] rssi2_raw_value Raw value of RSSI2
|
||||
* @param [out] rssi1_raw_fixed Pointer to store fixed raw value for RSSI1
|
||||
* @param [out] rssi2_raw_fixed Pointer to store fixed raw value for RSSI2, can be null.
|
||||
* @return lr20xx_status_t
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_rssi_computation( const void* context, uint8_t rssi1_raw_value,
|
||||
uint8_t rssi2_raw_value, uint8_t* rssi1_raw_fixed,
|
||||
uint8_t* rssi2_raw_fixed );
|
||||
|
||||
/**
|
||||
* @brief Reset DCDC regulator internal value to appropriate configuration
|
||||
*
|
||||
* This workaround must be called after each @ref lr20xx_radio_common_set_pkt_type if all the following is true:
|
||||
* - Rx operations are intended
|
||||
* - @ref LR20XX_SYSTEM_REG_MODE_DCDC is used
|
||||
* - sub GHz operations are intended
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_radio_common_set_pkt_type, lr20xx_workarounds_dcdc_configure,
|
||||
* lr20xx_workarounds_lora_sx1276_compatibility_mode_store_retention_mem
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_dcdc_reset( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Configure DCDC regulator internal value for specific operations
|
||||
*
|
||||
* This workaround must be called if all the following is true:
|
||||
* - Rx operations are intended
|
||||
* - @ref LR20XX_SYSTEM_REG_MODE_DCDC is used
|
||||
* - sub GHz operations are intended
|
||||
*
|
||||
* This workaround must be called after each of the following commands:
|
||||
* - @ref lr20xx_radio_fsk_set_modulation_params
|
||||
* - @ref lr20xx_radio_flrc_set_modulation_params
|
||||
* - @ref lr20xx_radio_ook_set_modulation_params
|
||||
* - @ref lr20xx_radio_lora_set_modulation_params
|
||||
* - @ref lr20xx_radio_z_wave_set_params
|
||||
* - @ref lr20xx_radio_common_set_rx_path
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_workarounds_dcdc_reset, lr20xx_radio_fsk_set_modulation_params, lr20xx_radio_flrc_set_modulation_params,
|
||||
* lr20xx_radio_ook_set_modulation_params, lr20xx_radio_lora_set_modulation_params, lr20xx_radio_z_wave_set_params,
|
||||
* lr20xx_radio_common_set_rx_path, lr20xx_workarounds_lora_sx1276_compatibility_mode_store_retention_mem
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_dcdc_configure( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Store the LoRa DCDC configuration in retention memory
|
||||
*
|
||||
* Calling this function allows to store the DCDC new reset value or configuration during sleep mode.
|
||||
* This helper function internally calls @ref lr20xx_system_add_register_to_retention_mem with the appropriate register
|
||||
* address.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param slot Index in the storage list. Allowed values [0:31]
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_system_add_register_to_retention_mem, lr20xx_workarounds_dcdc_reset, lr20xx_workarounds_dcdc_configure
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_dcdc_store_retention_mem( const void* context, uint8_t slot );
|
||||
|
||||
/**
|
||||
* @brief Apply workaround to reduce standard deviation of RTToF results with fractional bandwidths
|
||||
*
|
||||
* This workaround reduces the standard deviation of observed RTToF result on the following bandwiths:
|
||||
* - @ref LR20XX_RADIO_LORA_BW_812
|
||||
* - @ref LR20XX_RADIO_LORA_BW_406
|
||||
* - @ref LR20XX_RADIO_LORA_BW_203
|
||||
* - @ref LR20XX_RADIO_LORA_BW_101
|
||||
* The workaround must be called only on these bandwidths, after calling @ref lr20xx_radio_lora_set_modulation_params.
|
||||
*
|
||||
* Note that a call to @ref lr20xx_radio_lora_set_modulation_params reset the changes executed by this workaround.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param is_manager True if the device operate as manager, false if it operates as subordinate
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_radio_lora_set_modulation_params
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_results_deviation( const void* context, bool is_manager );
|
||||
|
||||
/**
|
||||
* @brief Store the registers for RTToF results deviation workaround in retention memory
|
||||
*
|
||||
* Calling this function allows to store the RTToF results deviation workaround registers during sleep mode. This helper
|
||||
* function internally calls @ref lr20xx_system_add_register_to_retention_mem with the appropriate register address.
|
||||
*
|
||||
* The @ref lr20xx_workarounds_rttof_results_deviation workaround addresses two registers, hence the two configurable
|
||||
* slots.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param slot_1 Index in the storage list. Allowed values [0:31]
|
||||
* @param slot_2 Index in the storage list. Allowed values [0:31]
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_system_add_register_to_retention_mem, lr20xx_workarounds_rttof_results_deviation
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_results_deviation_store_retention_mem( const void* context, uint8_t slot_1,
|
||||
uint8_t slot_2 );
|
||||
|
||||
/**
|
||||
* @brief Enable the workaround for RTToF Extention mode
|
||||
*
|
||||
* This workaround must be called when attempting RTToF operations with @ref
|
||||
* lr20xx_rttof_mode_e:LR20XX_RTTOF_MODE_EXTENDED
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_rttof_set_params, lr20xx_workarounds_rttof_extended_stuck_second_request_disable,
|
||||
* lr20xx_workarounds_rttof_extended_stuck_second_request_store_retention_mem
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_extended_stuck_second_request_enable( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Disable the RTToF workaround for Extention mode
|
||||
*
|
||||
* If @ref lr20xx_workarounds_rttof_extended_stuck_second_request_enable has previously been called and @ref
|
||||
* lr20xx_rttof_mode_e:LR20XX_RTTOF_MODE_NORMAL are attempted, the workaround must be disabled calling this function.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_rttof_set_params, lr20xx_workarounds_rttof_extended_stuck_second_request_enable,
|
||||
* lr20xx_workarounds_rttof_extended_stuck_second_request_store_retention_mem
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_extended_stuck_second_request_disable( const void* context );
|
||||
|
||||
/**
|
||||
* @brief Store the registers for RTToF extended stuck workaround in retention memory
|
||||
*
|
||||
* Calling this function allows to store the workaround register during sleep mode. This helper function internally
|
||||
* calls @ref lr20xx_system_add_register_to_retention_mem with the appropriate register address.
|
||||
*
|
||||
* @param context Chip implementation context
|
||||
* @param slot Index in the storage list. Allowed values [0:31]
|
||||
*
|
||||
* @return Operation status
|
||||
*
|
||||
* @see lr20xx_system_add_register_to_retention_mem, lr20xx_workarounds_rttof_extended_stuck_second_request_enable,
|
||||
* lr20xx_workarounds_rttof_extended_stuck_second_request_disable
|
||||
*/
|
||||
lr20xx_status_t lr20xx_workarounds_rttof_extended_stuck_second_request_store_retention_mem( const void* context,
|
||||
uint8_t slot );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR20XX_WORKAROUNDS_H
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
@@ -0,0 +1,6 @@
|
||||
# ProMicro LR2021 board configuration
|
||||
# Copyright (c) 2025 ZephCore
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config BOARD_PROMICRO_LR2021
|
||||
select SOC_NRF52840_QIAA
|
||||
@@ -0,0 +1,10 @@
|
||||
# ProMicro LR2021 — nRF52840 SuperMini + LR2021
|
||||
# SoftDevice v6 (S140 v6) — NiceNano/SuperMini bootloader uses S140 6.1.1
|
||||
# 0x00B6 = S140 v6 firmware ID; app partition starts at 0x26000
|
||||
|
||||
CONFIG_ZEPHCORE_BOARD_NAME="ProMicro LR2021"
|
||||
CONFIG_BT_DIS_MODEL_NUMBER_STR="ProMicro LR2021 nRF52840-LR2021"
|
||||
CONFIG_ZEPHCORE_SD_FWID=0x00B6
|
||||
|
||||
# LR2021 radio driver
|
||||
CONFIG_ZEPHCORE_RADIO_LR2021=y
|
||||
@@ -0,0 +1,8 @@
|
||||
# Copyright (c) 2025 ZephCore
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
board:
|
||||
name: promicro_lr2021
|
||||
full_name: ProMicro LR2021 (nRF52840 SuperMini + LR2021)
|
||||
vendor: zephcore
|
||||
socs:
|
||||
- name: nrf52840
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* ProMicro LR2021 pin control definitions
|
||||
* Copyright (c) 2025 ZephCore
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* SPI2 (LR2021): SCK=P1.11, MOSI=P1.15, MISO=P0.02
|
||||
* I2C0 (sensors): SDA=P1.04, SCL=P0.11
|
||||
* UART0 (GPS): TX=P0.20→GPS RX, RX=P0.22←GPS TX
|
||||
*/
|
||||
|
||||
&pinctrl {
|
||||
spi2_default: spi2_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 1, 11)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 1, 15)>,
|
||||
<NRF_PSEL(SPIM_MISO, 0, 2)>;
|
||||
};
|
||||
};
|
||||
spi2_sleep: spi2_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 1, 11)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 1, 15)>,
|
||||
<NRF_PSEL(SPIM_MISO, 0, 2)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
i2c0_default: i2c0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(TWIM_SDA, 1, 4)>,
|
||||
<NRF_PSEL(TWIM_SCL, 0, 11)>;
|
||||
};
|
||||
};
|
||||
i2c0_sleep: i2c0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(TWIM_SDA, 1, 4)>,
|
||||
<NRF_PSEL(TWIM_SCL, 0, 11)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 20)>;
|
||||
};
|
||||
group2 {
|
||||
psels = <NRF_PSEL(UART_RX, 0, 22)>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
uart0_sleep: uart0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 20)>,
|
||||
<NRF_PSEL(UART_RX, 0, 22)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* ProMicro LR2021 — nRF52840 SuperMini + LR2021
|
||||
* Copyright (c) 2025 ZephCore
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Hardware:
|
||||
* - nRF52840 (SuperMini/ProMicro form factor) with BLE 5
|
||||
* - Semtech LR2021 LoRa Plus radio (DIO5 as IRQ, DIO3 as TCXO supply)
|
||||
* - GPS module on UART0 (9600 baud, P0.22 RX, P0.20 TX)
|
||||
* - Battery ADC on AIN7 (P0.31), 150K+150K divider (2:1)
|
||||
* - User button on P1.00, LED on P0.15
|
||||
* - 3V3 enable on P0.13 (must be HIGH for LR2021 to function)
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <nordic/nrf52840_qiaa.dtsi>
|
||||
#include "promicro_lr2021-pinctrl.dtsi"
|
||||
#include <zephyr/dt-bindings/adc/nrf-saadc.h>
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
/ {
|
||||
model = "ProMicro LR2021";
|
||||
compatible = "zephcore,promicro-lr2021";
|
||||
|
||||
chosen {
|
||||
zephyr,sram = &sram0;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,code-partition = &code_partition;
|
||||
zephyr,console = &cdc_acm_uart;
|
||||
zephyr,shell-uart = &cdc_acm_uart;
|
||||
};
|
||||
|
||||
aliases {
|
||||
lora0 = &lora;
|
||||
led0 = &led0;
|
||||
sw0 = &user_button;
|
||||
watchdog0 = &wdt0;
|
||||
gps-enable = &gps_enable_pin;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led0: led_0 {
|
||||
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
|
||||
label = "LED";
|
||||
};
|
||||
};
|
||||
|
||||
buttons: buttons {
|
||||
compatible = "gpio-keys";
|
||||
user_button: button_0 {
|
||||
gpios = <&gpio1 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
zephyr,code = <INPUT_KEY_ENTER>;
|
||||
label = "User Button";
|
||||
};
|
||||
};
|
||||
|
||||
/* 3V3 enable — must be HIGH to power LR2021 module */
|
||||
vcc3v3_enable: vcc3v3-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc3v3-enable";
|
||||
enable-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
|
||||
regulator-boot-on;
|
||||
startup-delay-us = <5000>;
|
||||
};
|
||||
|
||||
/* GPS power control */
|
||||
gps_en: gps-enable {
|
||||
compatible = "gpio-leds";
|
||||
gps_enable_pin: gps_enable {
|
||||
gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
|
||||
label = "GPS Enable";
|
||||
};
|
||||
};
|
||||
|
||||
/* Battery ADC: P0.31 (AIN7), 150K+150K voltage divider (2:1) */
|
||||
zephyr,user {
|
||||
io-channels = <&adc 7>;
|
||||
vbat-mv-multiplier = <7200>;
|
||||
};
|
||||
};
|
||||
|
||||
®0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
®1 {
|
||||
regulator-initial-mode = <NRF5X_REG_MODE_DCDC>;
|
||||
};
|
||||
|
||||
&uicr {
|
||||
nfct-pins-as-gpios;
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* Battery voltage on P0.31 (AIN7) */
|
||||
channel@7 {
|
||||
reg = <7>;
|
||||
zephyr,gain = "ADC_GAIN_1_6";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10)>;
|
||||
zephyr,input-positive = <NRF_SAADC_AIN7>;
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- SPI2 for LR2021 ---- */
|
||||
&spi2 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
pinctrl-0 = <&spi2_default>;
|
||||
pinctrl-1 = <&spi2_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
cs-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; /* P1.13 LR2021_CS */
|
||||
|
||||
lora: lora@0 {
|
||||
compatible = "semtech,lr2021";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <8000000>;
|
||||
|
||||
reset-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
|
||||
busy-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
|
||||
dio1-gpios = <&gpio0 10 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
||||
|
||||
tcxo-voltage-mv = <1800>;
|
||||
tcxo-startup-delay-ms = <5>;
|
||||
rx-boosted;
|
||||
|
||||
/* RF switch via LR2021 internal DIOs (DIO5=bit0..DIO8=bit3)
|
||||
* Standard Semtech reference design RF switch config:
|
||||
* DIO5: ANT_SW (high in all active modes)
|
||||
* DIO6: TX_SW (high in TX)
|
||||
* DIO7: unused
|
||||
* DIO8: RX_SW (high in RX)
|
||||
* rfswitch-rx=0x09 → DIO5+DIO8 HIGH in RX
|
||||
* rfswitch-tx=0x03 → DIO5+DIO6 HIGH in LF TX
|
||||
* rfswitch-tx-hp=0x03 → DIO5+DIO6 HIGH in HF TX */
|
||||
rfswitch-enable = <0x0F>;
|
||||
rfswitch-standby = <0x00>;
|
||||
rfswitch-rx = <0x09>;
|
||||
rfswitch-tx = <0x03>;
|
||||
rfswitch-tx-hp = <0x03>;
|
||||
|
||||
pa-hp-sel = <7>;
|
||||
pa-duty-cycle = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- I2C0 for optional sensors ---- */
|
||||
&i2c0 {
|
||||
compatible = "nordic,nrf-twim";
|
||||
status = "okay";
|
||||
clock-frequency = <I2C_BITRATE_FAST>;
|
||||
pinctrl-0 = <&i2c0_default>;
|
||||
pinctrl-1 = <&i2c0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
/* All supported environment & power sensors — auto-detected at runtime */
|
||||
#include "../../common/sensors-i2c.dtsi"
|
||||
};
|
||||
|
||||
/* ---- GPS on UART0 (9600 baud) ---- */
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
status = "okay";
|
||||
current-speed = <9600>;
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-1 = <&uart0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
gnss: gnss {
|
||||
compatible = "luatos,air530z";
|
||||
on-off-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- USB CDC for console/CLI ---- */
|
||||
zephyr_udc0: &usbd {
|
||||
compatible = "nordic,nrf-usbd";
|
||||
status = "okay";
|
||||
|
||||
cdc_acm_uart: cdc_acm_uart {
|
||||
compatible = "zephyr,cdc-acm-uart";
|
||||
};
|
||||
};
|
||||
|
||||
/* ---- Flash partitions (SoftDevice v6, app@0x26000) ---- */
|
||||
#include "../../common/nrf52_partitions_sdv6.dtsi"
|
||||
@@ -0,0 +1,14 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
CONFIG_ARM_MPU=y
|
||||
CONFIG_HW_STACK_PROTECTION=y
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_UART_LINE_CTRL=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_NVS=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_ADC=y
|
||||
@@ -0,0 +1,20 @@
|
||||
# Copyright (c) 2025 ZephCore
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
zephyr_library_compile_definitions(LR20XX_DISABLE_WARNINGS)
|
||||
|
||||
zephyr_library_sources(lr20xx_lora.c)
|
||||
|
||||
set(LR20XX_SDK_DIR ${APPLICATION_SOURCE_DIR}/adapters/radio/lr20xx)
|
||||
zephyr_library_sources(${LR20XX_SDK_DIR}/lr20xx_hal_zephyr.c)
|
||||
zephyr_library_sources(${LR20XX_SDK_DIR}/lr20xx_radio_common.c)
|
||||
zephyr_library_sources(${LR20XX_SDK_DIR}/lr20xx_radio_lora.c)
|
||||
zephyr_library_sources(${LR20XX_SDK_DIR}/lr20xx_radio_fifo.c)
|
||||
zephyr_library_sources(${LR20XX_SDK_DIR}/lr20xx_system.c)
|
||||
zephyr_library_sources(${LR20XX_SDK_DIR}/lr20xx_regmem.c)
|
||||
zephyr_library_sources(${LR20XX_SDK_DIR}/lr20xx_workarounds.c)
|
||||
zephyr_library_sources(${LR20XX_SDK_DIR}/lr20xx_driver_version.c)
|
||||
|
||||
zephyr_library_include_directories(${LR20XX_SDK_DIR})
|
||||
zephyr_library_add_dependencies(offsets_h)
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2025 ZephCore
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config LORA_LR20XX
|
||||
bool "Semtech LR20xx LoRa transceiver driver"
|
||||
default y
|
||||
depends on DT_HAS_SEMTECH_LR2021_ENABLED
|
||||
select SPI
|
||||
select GPIO
|
||||
help
|
||||
Enable driver for Semtech LR2021 (LoRa Plus, 4th-gen) transceivers.
|
||||
Uses native Semtech lr20xx_driver SDK with Zephyr LoRa driver API.
|
||||
Supports sub-GHz + 2.4 GHz ISM + NTN/SATCOM.
|
||||
@@ -0,0 +1,984 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* LR20xx Zephyr LoRa driver
|
||||
*
|
||||
* Implements the standard Zephyr lora_driver_api using the Semtech lr20xx_driver
|
||||
* SDK. All SPI access, DIO1 IRQ handling, and radio state management is internal.
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT semtech_lr2021
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#include <zephyr/drivers/lora.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "lr20xx_lora.h"
|
||||
#include "lr20xx_hal_zephyr.h"
|
||||
#include "lr20xx_radio_common.h"
|
||||
#include "lr20xx_radio_common_types.h"
|
||||
#include "lr20xx_radio_lora.h"
|
||||
#include "lr20xx_radio_lora_types.h"
|
||||
#include "lr20xx_radio_fifo.h"
|
||||
#include "lr20xx_system.h"
|
||||
#include "lr20xx_system_types.h"
|
||||
|
||||
LOG_MODULE_REGISTER(lr20xx_lora, CONFIG_LORA_LOG_LEVEL);
|
||||
|
||||
/* Dedicated DIO1 work queue — keeps LoRa interrupt processing off the
|
||||
* system work queue so USB/BLE/timer work items cannot delay packet RX. */
|
||||
#define LR20XX_DIO1_WQ_STACK_SIZE 2560
|
||||
K_THREAD_STACK_DEFINE(lr20xx_dio1_wq_stack, LR20XX_DIO1_WQ_STACK_SIZE);
|
||||
|
||||
/* ── Driver data structures ─────────────────────────────────────────── */
|
||||
|
||||
struct lr20xx_config {
|
||||
struct spi_dt_spec bus;
|
||||
struct gpio_dt_spec reset;
|
||||
struct gpio_dt_spec busy;
|
||||
struct gpio_dt_spec dio1;
|
||||
uint16_t tcxo_voltage_mv;
|
||||
uint32_t tcxo_startup_delay_ms;
|
||||
bool rx_boosted;
|
||||
/* RF switch DIO bitmasks (bit 0 = DIO5, bit 1 = DIO6, ...) */
|
||||
uint8_t rfswitch_enable;
|
||||
uint8_t rfswitch_standby;
|
||||
uint8_t rfswitch_rx;
|
||||
uint8_t rfswitch_tx;
|
||||
uint8_t rfswitch_tx_hp;
|
||||
/* PA config */
|
||||
uint8_t pa_hp_sel; /* maps to pa_lf_slices in LR20xx */
|
||||
uint8_t pa_duty_cycle; /* maps to pa_lf_duty_cycle in LR20xx */
|
||||
};
|
||||
|
||||
struct lr20xx_data {
|
||||
const struct device *dev;
|
||||
struct lr20xx_hal_context hal_ctx;
|
||||
struct k_mutex spi_mutex;
|
||||
|
||||
/* Cached modem config from lora_config() */
|
||||
struct lora_modem_config modem_cfg;
|
||||
bool configured;
|
||||
|
||||
/* Async RX state */
|
||||
lora_recv_cb async_rx_cb;
|
||||
void *async_rx_user_data;
|
||||
|
||||
/* Async TX state */
|
||||
struct k_poll_signal *tx_signal;
|
||||
|
||||
/* DIO1 work — runs on dedicated queue, not system work queue */
|
||||
struct k_work dio1_work;
|
||||
struct k_work_q dio1_wq;
|
||||
|
||||
/* Radio state */
|
||||
volatile bool tx_active;
|
||||
volatile bool in_rx_mode;
|
||||
|
||||
/* Extension features */
|
||||
bool rx_duty_cycle_enabled;
|
||||
bool rx_boost_enabled;
|
||||
bool rx_boost_applied;
|
||||
|
||||
/* Deferred hardware init */
|
||||
bool hw_initialized;
|
||||
|
||||
/* DIO1 stuck-HIGH detection */
|
||||
int dio1_stuck_count;
|
||||
|
||||
/* RX data buffer */
|
||||
uint8_t rx_buf[256];
|
||||
};
|
||||
|
||||
/* ── Helpers ────────────────────────────────────────────────────────── */
|
||||
|
||||
static lr20xx_radio_lora_bw_t bw_enum_to_lr20xx(enum lora_signal_bandwidth bw)
|
||||
{
|
||||
switch (bw) {
|
||||
case BW_31_KHZ: return LR20XX_RADIO_LORA_BW_31;
|
||||
case BW_41_KHZ: return LR20XX_RADIO_LORA_BW_41;
|
||||
case BW_62_KHZ: return LR20XX_RADIO_LORA_BW_62;
|
||||
case BW_125_KHZ: return LR20XX_RADIO_LORA_BW_125;
|
||||
case BW_250_KHZ: return LR20XX_RADIO_LORA_BW_250;
|
||||
case BW_500_KHZ: return LR20XX_RADIO_LORA_BW_500;
|
||||
default: return LR20XX_RADIO_LORA_BW_125;
|
||||
}
|
||||
}
|
||||
|
||||
static lr20xx_radio_lora_cr_t cr_enum_to_lr20xx(enum lora_coding_rate cr)
|
||||
{
|
||||
switch (cr) {
|
||||
case CR_4_5: return LR20XX_RADIO_LORA_CR_4_5;
|
||||
case CR_4_6: return LR20XX_RADIO_LORA_CR_4_6;
|
||||
case CR_4_7: return LR20XX_RADIO_LORA_CR_4_7;
|
||||
case CR_4_8: return LR20XX_RADIO_LORA_CR_4_8;
|
||||
default: return LR20XX_RADIO_LORA_CR_4_8;
|
||||
}
|
||||
}
|
||||
|
||||
static lr20xx_system_tcxo_supply_voltage_t get_tcxo_voltage(uint16_t mv)
|
||||
{
|
||||
if (mv >= 3300) return LR20XX_SYSTEM_TCXO_CTRL_3_3V;
|
||||
if (mv >= 3000) return LR20XX_SYSTEM_TCXO_CTRL_3_0V;
|
||||
if (mv >= 2700) return LR20XX_SYSTEM_TCXO_CTRL_2_7V;
|
||||
if (mv >= 2400) return LR20XX_SYSTEM_TCXO_CTRL_2_4V;
|
||||
if (mv >= 2200) return LR20XX_SYSTEM_TCXO_CTRL_2_2V;
|
||||
if (mv >= 1800) return LR20XX_SYSTEM_TCXO_CTRL_1_8V;
|
||||
return LR20XX_SYSTEM_TCXO_CTRL_1_6V;
|
||||
}
|
||||
|
||||
/* Get kHz value from Zephyr BW enum — used for LDRO/PPM calculation */
|
||||
static float bw_enum_to_khz(enum lora_signal_bandwidth bw)
|
||||
{
|
||||
switch (bw) {
|
||||
case BW_7_KHZ: return 7.81f;
|
||||
case BW_10_KHZ: return 10.42f;
|
||||
case BW_15_KHZ: return 15.63f;
|
||||
case BW_20_KHZ: return 20.83f;
|
||||
case BW_31_KHZ: return 31.25f;
|
||||
case BW_41_KHZ: return 41.67f;
|
||||
case BW_62_KHZ: return 62.5f;
|
||||
case BW_125_KHZ: return 125.0f;
|
||||
case BW_250_KHZ: return 250.0f;
|
||||
case BW_500_KHZ: return 500.0f;
|
||||
default: return 125.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Configure RF switch DIOs ───────────────────────────────────────── */
|
||||
|
||||
static void lr20xx_configure_rfswitch(void *ctx, const struct lr20xx_config *cfg)
|
||||
{
|
||||
/* LR20xx RF switch uses per-DIO configuration.
|
||||
* DIO5..DIO8 map to enable bitmask bits 0..3.
|
||||
* For each enabled DIO, compute which operational modes
|
||||
* should drive it HIGH by looking at the per-mode bitmasks. */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!(cfg->rfswitch_enable & BIT(i))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lr20xx_system_dio_t dio = (lr20xx_system_dio_t)(LR20XX_SYSTEM_DIO_5 + i);
|
||||
|
||||
/* Set this DIO function to RF switch control */
|
||||
lr20xx_system_set_dio_function(ctx, dio,
|
||||
LR20XX_SYSTEM_DIO_FUNC_RF_SWITCH);
|
||||
|
||||
/* Build the per-DIO mode bitmask:
|
||||
* which operational modes drive this DIO HIGH */
|
||||
lr20xx_system_dio_rf_switch_cfg_t sw_cfg = 0;
|
||||
|
||||
if (cfg->rfswitch_standby & BIT(i)) {
|
||||
sw_cfg |= LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_STANDBY;
|
||||
}
|
||||
if (cfg->rfswitch_rx & BIT(i)) {
|
||||
sw_cfg |= LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_LF |
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_HF;
|
||||
}
|
||||
if (cfg->rfswitch_tx & BIT(i)) {
|
||||
sw_cfg |= LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_TX_LF;
|
||||
}
|
||||
if (cfg->rfswitch_tx_hp & BIT(i)) {
|
||||
sw_cfg |= LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_TX_HF;
|
||||
}
|
||||
|
||||
lr20xx_system_set_dio_rf_switch_cfg(ctx, dio, sw_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Hardware reset (BUSY stuck recovery) ───────────────────────────── */
|
||||
|
||||
static void lr20xx_hardware_reset(struct lr20xx_data *data,
|
||||
const struct lr20xx_config *cfg)
|
||||
{
|
||||
void *ctx = &data->hal_ctx;
|
||||
|
||||
LOG_WRN("LR2021 hardware reset (BUSY stuck recovery)");
|
||||
|
||||
lr20xx_hal_reset(ctx);
|
||||
|
||||
if (cfg->tcxo_voltage_mv > 0) {
|
||||
lr20xx_system_set_tcxo_mode(ctx,
|
||||
get_tcxo_voltage(cfg->tcxo_voltage_mv),
|
||||
(cfg->tcxo_startup_delay_ms * 1000) / 31);
|
||||
}
|
||||
|
||||
lr20xx_system_set_reg_mode(ctx, LR20XX_SYSTEM_REG_MODE_DCDC);
|
||||
|
||||
lr20xx_configure_rfswitch(ctx, cfg);
|
||||
|
||||
lr20xx_system_calibrate(ctx, 0x6F);
|
||||
|
||||
lr20xx_radio_common_set_rx_tx_fallback_mode(ctx,
|
||||
LR20XX_RADIO_FALLBACK_STDBY_RC);
|
||||
|
||||
lr20xx_radio_common_set_pkt_type(ctx, LR20XX_RADIO_COMMON_PKT_TYPE_LORA);
|
||||
|
||||
lr20xx_system_clear_errors(ctx);
|
||||
lr20xx_system_clear_irq_status(ctx, LR20XX_SYSTEM_IRQ_ALL_MASK);
|
||||
|
||||
data->rx_boost_applied = false;
|
||||
|
||||
lr20xx_hal_enable_dio1_irq(&data->hal_ctx);
|
||||
|
||||
LOG_WRN("LR2021 recovered from hardware reset");
|
||||
}
|
||||
|
||||
/* ── Apply modem configuration ──────────────────────────────────────── */
|
||||
|
||||
static void lr20xx_apply_modem_config(struct lr20xx_data *data,
|
||||
const struct lr20xx_config *cfg,
|
||||
bool tx_mode)
|
||||
{
|
||||
void *ctx = &data->hal_ctx;
|
||||
struct lora_modem_config *mc = &data->modem_cfg;
|
||||
|
||||
lr20xx_radio_common_set_rf_freq(ctx, mc->frequency);
|
||||
|
||||
/* LR20xx uses PPM offset instead of explicit LDRO.
|
||||
* PPM_1_4 (1 bin every 4) is equivalent to LDRO for high-SF
|
||||
* wide-time-on-air configurations. Use recommended value. */
|
||||
lr20xx_radio_lora_mod_params_t mod = {
|
||||
.sf = (lr20xx_radio_lora_sf_t)mc->datarate,
|
||||
.bw = bw_enum_to_lr20xx(mc->bandwidth),
|
||||
.cr = cr_enum_to_lr20xx(mc->coding_rate),
|
||||
.ppm = lr20xx_radio_lora_get_recommended_ppm_offset(
|
||||
(lr20xx_radio_lora_sf_t)mc->datarate,
|
||||
bw_enum_to_lr20xx(mc->bandwidth)),
|
||||
};
|
||||
lr20xx_radio_lora_set_modulation_params(ctx, &mod);
|
||||
|
||||
lr20xx_radio_lora_pkt_params_t pkt = {
|
||||
.preamble_len_in_symb = mc->preamble_len,
|
||||
.pkt_mode = LR20XX_RADIO_LORA_PKT_EXPLICIT,
|
||||
.pld_len_in_bytes = 255,
|
||||
.crc = mc->packet_crc_disable ? LR20XX_RADIO_LORA_CRC_DISABLED
|
||||
: LR20XX_RADIO_LORA_CRC_ENABLED,
|
||||
.iq = mc->iq_inverted ? LR20XX_RADIO_LORA_IQ_INVERTED
|
||||
: LR20XX_RADIO_LORA_IQ_STANDARD,
|
||||
};
|
||||
lr20xx_radio_lora_set_packet_params(ctx, &pkt);
|
||||
|
||||
lr20xx_radio_lora_set_syncword(ctx,
|
||||
mc->public_network ? 0x34 : 0x12);
|
||||
|
||||
if (tx_mode) {
|
||||
/* LR20xx set_tx_params uses half-dBm (multiply by 2) */
|
||||
lr20xx_radio_common_set_tx_params(ctx,
|
||||
(int8_t)(mc->tx_power * 2),
|
||||
LR20XX_RADIO_COMMON_RAMP_48_US);
|
||||
|
||||
lr20xx_radio_common_select_pa(ctx, LR20XX_RADIO_COMMON_PA_SEL_LF);
|
||||
|
||||
lr20xx_radio_common_pa_cfg_t pa = {
|
||||
.pa_sel = LR20XX_RADIO_COMMON_PA_SEL_LF,
|
||||
.pa_lf_mode = LR20XX_RADIO_COMMON_PA_LF_MODE_FSM,
|
||||
.pa_lf_duty_cycle = cfg->pa_duty_cycle,
|
||||
.pa_lf_slices = cfg->pa_hp_sel,
|
||||
.pa_hf_duty_cycle = 16, /* unused for LF, default */
|
||||
};
|
||||
lr20xx_radio_common_set_pa_cfg(ctx, &pa);
|
||||
}
|
||||
|
||||
/* Route IRQ events to DIO5 (physical DIO1 pin on the board) */
|
||||
lr20xx_system_set_dio_irq_cfg(ctx, LR20XX_SYSTEM_DIO_5,
|
||||
LR20XX_SYSTEM_IRQ_RX_DONE | LR20XX_SYSTEM_IRQ_TX_DONE |
|
||||
LR20XX_SYSTEM_IRQ_TIMEOUT | LR20XX_SYSTEM_IRQ_CRC_ERROR |
|
||||
LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR);
|
||||
}
|
||||
|
||||
/* ── Start RX (internal) ────────────────────────────────────────────── */
|
||||
|
||||
static void lr20xx_start_rx(struct lr20xx_data *data,
|
||||
const struct lr20xx_config *cfg)
|
||||
{
|
||||
void *ctx = &data->hal_ctx;
|
||||
|
||||
LOG_DBG("start_rx: t=%lld", k_uptime_get());
|
||||
|
||||
/* Standby first — wake from any sleep state */
|
||||
data->hal_ctx.radio_is_sleeping = true;
|
||||
lr20xx_status_t rc = lr20xx_system_set_standby_mode(ctx,
|
||||
LR20XX_SYSTEM_STANDBY_MODE_RC);
|
||||
if (rc != LR20XX_STATUS_OK) {
|
||||
LOG_ERR("standby failed (rc=%d) — triggering HW reset", rc);
|
||||
lr20xx_hardware_reset(data, cfg);
|
||||
}
|
||||
|
||||
lr20xx_system_clear_irq_status(ctx, LR20XX_SYSTEM_IRQ_ALL_MASK);
|
||||
|
||||
lr20xx_apply_modem_config(data, cfg, false);
|
||||
|
||||
/* Apply RX boost if needed */
|
||||
if (data->rx_boost_enabled && !data->rx_boost_applied) {
|
||||
lr20xx_radio_common_set_rx_path(
|
||||
ctx, LR20XX_RADIO_COMMON_RX_PATH_LF,
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_4);
|
||||
data->rx_boost_applied = true;
|
||||
}
|
||||
|
||||
/* Start continuous RX using RTC-step API (0xFFFFFF = continuous) */
|
||||
lr20xx_radio_common_set_rx_with_timeout_in_rtc_step(ctx, 0xFFFFFF);
|
||||
|
||||
/* Clear any IRQ flags set during modem configuration */
|
||||
lr20xx_system_clear_irq_status(ctx, LR20XX_SYSTEM_IRQ_ALL_MASK);
|
||||
|
||||
data->in_rx_mode = true;
|
||||
data->tx_active = false;
|
||||
}
|
||||
|
||||
/* ── Lightweight RX restart (no modem reconfig) ─────────────────────── */
|
||||
|
||||
static void lr20xx_restart_rx(struct lr20xx_data *data)
|
||||
{
|
||||
void *ctx = &data->hal_ctx;
|
||||
|
||||
lr20xx_system_clear_irq_status(ctx, LR20XX_SYSTEM_IRQ_ALL_MASK);
|
||||
lr20xx_radio_common_set_rx_with_timeout_in_rtc_step(ctx, 0xFFFFFF);
|
||||
|
||||
data->in_rx_mode = true;
|
||||
}
|
||||
|
||||
/* ── DIO1 IRQ handler (work queue, thread context) ──────────────────── */
|
||||
|
||||
static void lr20xx_dio1_callback(void *user_data);
|
||||
|
||||
static void lr20xx_dio1_work_handler(struct k_work *work)
|
||||
{
|
||||
struct lr20xx_data *data = CONTAINER_OF(work, struct lr20xx_data,
|
||||
dio1_work);
|
||||
const struct lr20xx_config *cfg = data->dev->config;
|
||||
void *ctx = &data->hal_ctx;
|
||||
bool rx_restarted = false;
|
||||
|
||||
k_mutex_lock(&data->spi_mutex, K_FOREVER);
|
||||
|
||||
/* Combined get + clear IRQ status */
|
||||
lr20xx_system_irq_mask_t irq = 0;
|
||||
lr20xx_status_t rc = lr20xx_system_get_and_clear_irq_status(ctx, &irq);
|
||||
|
||||
if (rc != LR20XX_STATUS_OK) {
|
||||
LOG_ERR("Failed to read IRQ status (rc=%d)", rc);
|
||||
goto safety_check;
|
||||
}
|
||||
|
||||
LOG_DBG("DIO1 IRQ: 0x%08x tx=%d t=%lld", irq, data->tx_active,
|
||||
k_uptime_get());
|
||||
|
||||
if (irq & LR20XX_SYSTEM_IRQ_ERROR) {
|
||||
LOG_WRN("IRQ hardware ERROR: 0x%08x", irq);
|
||||
}
|
||||
|
||||
if (irq != 0) {
|
||||
data->dio1_stuck_count = 0;
|
||||
}
|
||||
|
||||
/* ── RX done ── */
|
||||
if (irq & LR20XX_SYSTEM_IRQ_RX_DONE) {
|
||||
uint16_t pkt_len = 0;
|
||||
lr20xx_radio_common_get_rx_packet_length(ctx, &pkt_len);
|
||||
|
||||
if (pkt_len > 0 && pkt_len <= 255) {
|
||||
lr20xx_radio_lora_packet_status_t pkt_stat;
|
||||
lr20xx_radio_lora_get_packet_status(ctx, &pkt_stat);
|
||||
|
||||
lr20xx_radio_fifo_read_rx(ctx, data->rx_buf,
|
||||
(uint16_t)pkt_len);
|
||||
|
||||
/* Restart RX before firing callback */
|
||||
lr20xx_restart_rx(data);
|
||||
rx_restarted = true;
|
||||
|
||||
/* When SNR < 0, use signal RSSI for a more
|
||||
* accurate reading on weak links. */
|
||||
int16_t rssi = pkt_stat.rssi_pkt_in_dbm;
|
||||
int8_t snr = pkt_stat.snr_pkt_raw / 4;
|
||||
|
||||
if (snr < 0 &&
|
||||
pkt_stat.rssi_signal_pkt_in_dbm > rssi) {
|
||||
rssi = pkt_stat.rssi_signal_pkt_in_dbm;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
|
||||
if (data->async_rx_cb) {
|
||||
data->async_rx_cb(data->dev, data->rx_buf,
|
||||
(uint8_t)pkt_len,
|
||||
rssi, snr,
|
||||
data->async_rx_user_data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_WRN("RX: invalid len %d", pkt_len);
|
||||
lr20xx_restart_rx(data);
|
||||
rx_restarted = true;
|
||||
}
|
||||
|
||||
/* ── TX done ── */
|
||||
if (irq & LR20XX_SYSTEM_IRQ_TX_DONE) {
|
||||
LOG_DBG("TX done");
|
||||
data->tx_active = false;
|
||||
|
||||
lr20xx_start_rx(data, cfg);
|
||||
rx_restarted = true;
|
||||
|
||||
if (data->tx_signal) {
|
||||
k_poll_signal_raise(data->tx_signal, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Timeout ── */
|
||||
if (irq & LR20XX_SYSTEM_IRQ_TIMEOUT) {
|
||||
LOG_DBG("Timeout IRQ — restarting RX");
|
||||
if (!data->tx_active) {
|
||||
lr20xx_restart_rx(data);
|
||||
rx_restarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── CRC / Header error ── */
|
||||
if (irq & LR20XX_SYSTEM_IRQ_CRC_ERROR ||
|
||||
((irq & LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR) &&
|
||||
!(irq & LR20XX_SYSTEM_IRQ_SYNC_WORD_HEADER_VALID))) {
|
||||
LOG_WRN("RX error: CRC=%d HDR=%d",
|
||||
(irq & LR20XX_SYSTEM_IRQ_CRC_ERROR) ? 1 : 0,
|
||||
(irq & LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR) ? 1 : 0);
|
||||
|
||||
if (!data->tx_active) {
|
||||
lr20xx_restart_rx(data);
|
||||
rx_restarted = true;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
|
||||
if (data->async_rx_cb) {
|
||||
data->async_rx_cb(data->dev, NULL, 0, 0, 0,
|
||||
data->async_rx_user_data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
safety_check:
|
||||
if (!rx_restarted && data->in_rx_mode && !data->tx_active) {
|
||||
LOG_WRN("DIO1 safety: no IRQ handled (0x%08x rc=%d), "
|
||||
"restarting RX", irq, rc);
|
||||
lr20xx_restart_rx(data);
|
||||
}
|
||||
|
||||
/* Edge-triggered DIO1: if still HIGH, re-submit for pending flags.
|
||||
* Guard against stuck DIO1: after 5 empty cycles, hardware reset. */
|
||||
if (gpio_pin_get_dt(&data->hal_ctx.dio1)) {
|
||||
data->dio1_stuck_count++;
|
||||
if (data->dio1_stuck_count >= 5) {
|
||||
LOG_ERR("DIO1 stuck HIGH for %d cycles — "
|
||||
"hardware reset", data->dio1_stuck_count);
|
||||
data->dio1_stuck_count = 0;
|
||||
lr20xx_hardware_reset(data, cfg);
|
||||
lr20xx_start_rx(data, cfg);
|
||||
} else {
|
||||
k_work_submit_to_queue(&data->dio1_wq,
|
||||
&data->dio1_work);
|
||||
}
|
||||
} else {
|
||||
data->dio1_stuck_count = 0;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
}
|
||||
|
||||
static void lr20xx_dio1_callback(void *user_data)
|
||||
{
|
||||
struct lr20xx_data *data = (struct lr20xx_data *)user_data;
|
||||
k_work_submit_to_queue(&data->dio1_wq, &data->dio1_work);
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static int lr20xx_hw_init(struct lr20xx_data *data,
|
||||
const struct lr20xx_config *cfg);
|
||||
|
||||
/* ── Driver API: config ─────────────────────────────────────────────── */
|
||||
|
||||
static int lr20xx_lora_config(const struct device *dev,
|
||||
struct lora_modem_config *config)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
|
||||
if (!data->hw_initialized) {
|
||||
int ret = lr20xx_hw_init(data, dev->config);
|
||||
if (ret != 0) {
|
||||
LOG_ERR("Hardware init failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&data->modem_cfg, config, sizeof(*config));
|
||||
data->configured = true;
|
||||
|
||||
/* Image calibration at operating frequency */
|
||||
k_mutex_lock(&data->spi_mutex, K_FOREVER);
|
||||
lr20xx_radio_common_front_end_calibration_value_t cal = {
|
||||
.rx_path = LR20XX_RADIO_COMMON_RX_PATH_LF,
|
||||
.frequency_in_hertz = config->frequency,
|
||||
};
|
||||
lr20xx_radio_common_calibrate_front_end_helper(&data->hal_ctx,
|
||||
&cal, 1);
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
|
||||
LOG_INF("config: %uHz SF%d BW%d CR%d pwr=%d tx=%d",
|
||||
config->frequency, config->datarate, config->bandwidth,
|
||||
config->coding_rate, config->tx_power, config->tx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── Driver API: airtime ────────────────────────────────────────────── */
|
||||
|
||||
static uint32_t lr20xx_lora_airtime(const struct device *dev,
|
||||
uint32_t data_len)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
struct lora_modem_config *mc = &data->modem_cfg;
|
||||
|
||||
uint8_t sf = (uint8_t)mc->datarate;
|
||||
float bw = bw_enum_to_khz(mc->bandwidth) * 1000.0f;
|
||||
uint8_t cr = (uint8_t)mc->coding_rate + 4;
|
||||
|
||||
float ts = (float)(1 << sf) / bw;
|
||||
int de = (sf >= 11 && bw <= 125000.0f) ? 1 : 0;
|
||||
float n_payload = 8.0f + fmaxf(
|
||||
ceilf((8.0f * data_len - 4.0f * sf + 28.0f + 16.0f) /
|
||||
(4.0f * (sf - 2.0f * de))) * cr,
|
||||
0.0f);
|
||||
float t_preamble = (mc->preamble_len + 4.25f) * ts;
|
||||
float t_payload = n_payload * ts;
|
||||
|
||||
return (uint32_t)((t_preamble + t_payload) * 1000.0f);
|
||||
}
|
||||
|
||||
/* ── Driver API: send_async ─────────────────────────────────────────── */
|
||||
|
||||
static int lr20xx_lora_send_async(const struct device *dev,
|
||||
uint8_t *buf, uint32_t data_len,
|
||||
struct k_poll_signal *async)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
const struct lr20xx_config *cfg = dev->config;
|
||||
void *ctx = &data->hal_ctx;
|
||||
|
||||
if (!data->configured) return -EINVAL;
|
||||
if (data->tx_active) return -EBUSY;
|
||||
if (data_len > 255 || data_len == 0) return -EINVAL;
|
||||
|
||||
k_mutex_lock(&data->spi_mutex, K_FOREVER);
|
||||
|
||||
data->async_rx_cb = NULL;
|
||||
data->in_rx_mode = false;
|
||||
|
||||
lr20xx_hal_disable_dio1_irq(&data->hal_ctx);
|
||||
|
||||
/* Standby — wake from sleep if needed */
|
||||
data->hal_ctx.radio_is_sleeping = true;
|
||||
lr20xx_status_t rc = lr20xx_system_set_standby_mode(ctx,
|
||||
LR20XX_SYSTEM_STANDBY_MODE_RC);
|
||||
if (rc != LR20XX_STATUS_OK) {
|
||||
LOG_ERR("TX standby failed — HW reset");
|
||||
lr20xx_hardware_reset(data, cfg);
|
||||
}
|
||||
|
||||
lr20xx_apply_modem_config(data, cfg, true);
|
||||
|
||||
/* Set TX-specific packet length */
|
||||
lr20xx_radio_lora_pkt_params_t pkt = {
|
||||
.preamble_len_in_symb = data->modem_cfg.preamble_len,
|
||||
.pkt_mode = LR20XX_RADIO_LORA_PKT_EXPLICIT,
|
||||
.pld_len_in_bytes = (uint8_t)data_len,
|
||||
.crc = data->modem_cfg.packet_crc_disable
|
||||
? LR20XX_RADIO_LORA_CRC_DISABLED
|
||||
: LR20XX_RADIO_LORA_CRC_ENABLED,
|
||||
.iq = data->modem_cfg.iq_inverted
|
||||
? LR20XX_RADIO_LORA_IQ_INVERTED
|
||||
: LR20XX_RADIO_LORA_IQ_STANDARD,
|
||||
};
|
||||
lr20xx_radio_lora_set_packet_params(ctx, &pkt);
|
||||
|
||||
/* Write to TX FIFO */
|
||||
lr20xx_radio_fifo_write_tx(ctx, buf, (uint16_t)data_len);
|
||||
|
||||
lr20xx_system_clear_irq_status(ctx, LR20XX_SYSTEM_IRQ_ALL_MASK);
|
||||
lr20xx_hal_enable_dio1_irq(&data->hal_ctx);
|
||||
|
||||
data->tx_signal = async;
|
||||
data->tx_active = true;
|
||||
lr20xx_radio_common_set_tx(ctx, 5000);
|
||||
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
|
||||
LOG_DBG("TX started: len=%u", data_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── Driver API: send (sync) ────────────────────────────────────────── */
|
||||
|
||||
static int lr20xx_lora_send(const struct device *dev,
|
||||
uint8_t *buf, uint32_t data_len)
|
||||
{
|
||||
struct k_poll_signal done = K_POLL_SIGNAL_INITIALIZER(done);
|
||||
struct k_poll_event evt = K_POLL_EVENT_INITIALIZER(
|
||||
K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &done);
|
||||
|
||||
int ret = lr20xx_lora_send_async(dev, buf, data_len, &done);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
uint32_t air_time = lr20xx_lora_airtime(dev, data_len);
|
||||
ret = k_poll(&evt, 1, K_MSEC(2 * air_time + 1000));
|
||||
if (ret < 0) {
|
||||
LOG_ERR("TX sync timeout");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── Driver API: recv_async ─────────────────────────────────────────── */
|
||||
|
||||
static int lr20xx_lora_recv_async(const struct device *dev,
|
||||
lora_recv_cb cb, void *user_data)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
const struct lr20xx_config *cfg = dev->config;
|
||||
|
||||
if (cb == NULL) {
|
||||
k_mutex_lock(&data->spi_mutex, K_FOREVER);
|
||||
data->async_rx_cb = NULL;
|
||||
data->async_rx_user_data = NULL;
|
||||
data->in_rx_mode = false;
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!data->configured) return -EINVAL;
|
||||
|
||||
k_mutex_lock(&data->spi_mutex, K_FOREVER);
|
||||
|
||||
data->async_rx_cb = cb;
|
||||
data->async_rx_user_data = user_data;
|
||||
|
||||
lr20xx_start_rx(data, cfg);
|
||||
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
|
||||
LOG_INF("recv_async started (continuous RX%s)",
|
||||
data->rx_boost_enabled ? ", boosted" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── Driver API: recv (sync) ────────────────────────────────────────── */
|
||||
|
||||
static int lr20xx_lora_recv(const struct device *dev, uint8_t *buf,
|
||||
uint8_t size, k_timeout_t timeout,
|
||||
int16_t *rssi, int8_t *snr)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(buf);
|
||||
ARG_UNUSED(size);
|
||||
ARG_UNUSED(timeout);
|
||||
ARG_UNUSED(rssi);
|
||||
ARG_UNUSED(snr);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* ── LR20xx extension API ───────────────────────────────────────────── */
|
||||
|
||||
int16_t lr20xx_get_rssi_inst(const struct device *dev)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
int16_t rssi = 0;
|
||||
uint8_t half_dbm = 0;
|
||||
|
||||
k_mutex_lock(&data->spi_mutex, K_FOREVER);
|
||||
lr20xx_radio_common_get_rssi_inst(&data->hal_ctx, &rssi, &half_dbm);
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
|
||||
return rssi;
|
||||
}
|
||||
|
||||
bool lr20xx_is_receiving(const struct device *dev)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
|
||||
/* LR20xx has no non-destructive IRQ read (only get_and_clear).
|
||||
* Consuming bits here races with the DIO1 work handler — RX_DONE
|
||||
* could be cleared before the handler delivers the packet.
|
||||
* Use radio state flags as proxy: radio is "receiving" if in
|
||||
* continuous RX, not in TX, and DIO1 is not asserted (asserted
|
||||
* means a completion event is pending, not a mid-preamble state). */
|
||||
if (!data->in_rx_mode || data->tx_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !gpio_pin_get_dt(&data->hal_ctx.dio1);
|
||||
}
|
||||
|
||||
void lr20xx_set_rx_duty_cycle(const struct device *dev, bool enable)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
|
||||
data->rx_duty_cycle_enabled = enable;
|
||||
LOG_INF("RX duty cycle %s", enable ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
void lr20xx_set_rx_boost(const struct device *dev, bool enable)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
|
||||
if (data->rx_boost_enabled == enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
data->rx_boost_enabled = enable;
|
||||
LOG_INF("RX boost %s", enable ? "enabled" : "disabled");
|
||||
|
||||
if (data->in_rx_mode && data->configured) {
|
||||
k_mutex_lock(&data->spi_mutex, K_FOREVER);
|
||||
lr20xx_radio_common_set_rx_path(
|
||||
&data->hal_ctx, LR20XX_RADIO_COMMON_RX_PATH_LF,
|
||||
enable ? LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_4
|
||||
: LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_NONE);
|
||||
data->rx_boost_applied = enable;
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
} else {
|
||||
data->rx_boost_applied = false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lr20xx_get_random(const struct device *dev)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
uint32_t random = 0;
|
||||
|
||||
k_mutex_lock(&data->spi_mutex, K_FOREVER);
|
||||
lr20xx_system_get_random_number(
|
||||
&data->hal_ctx,
|
||||
LR20XX_SYSTEM_RANDOM_ENTROPY_SOURCE_PLL |
|
||||
LR20XX_SYSTEM_RANDOM_ENTROPY_SOURCE_ADC,
|
||||
&random);
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
|
||||
return random;
|
||||
}
|
||||
|
||||
void lr20xx_reset_agc(const struct device *dev)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
void *ctx = &data->hal_ctx;
|
||||
|
||||
k_mutex_lock(&data->spi_mutex, K_FOREVER);
|
||||
|
||||
/* Warm sleep — powers down analog frontend (resets AGC gain state).
|
||||
* is_ram_retention_enabled=true = warm sleep (equivalent to LR11xx warm_start). */
|
||||
lr20xx_system_sleep_cfg_t sleep_cfg = {
|
||||
.is_clk_32k_enabled = false,
|
||||
.is_ram_retention_enabled = true,
|
||||
};
|
||||
lr20xx_system_set_sleep_mode(ctx, &sleep_cfg, 0);
|
||||
k_sleep(K_USEC(500));
|
||||
|
||||
lr20xx_system_set_standby_mode(ctx, LR20XX_SYSTEM_STANDBY_MODE_RC);
|
||||
|
||||
lr20xx_system_calibrate(ctx, 0x6F);
|
||||
|
||||
if (data->configured) {
|
||||
lr20xx_radio_common_front_end_calibration_value_t cal = {
|
||||
.rx_path = LR20XX_RADIO_COMMON_RX_PATH_LF,
|
||||
.frequency_in_hertz = data->modem_cfg.frequency,
|
||||
};
|
||||
lr20xx_radio_common_calibrate_front_end_helper(ctx, &cal, 1);
|
||||
}
|
||||
|
||||
if (data->rx_boost_enabled) {
|
||||
lr20xx_radio_common_set_rx_path(
|
||||
ctx, LR20XX_RADIO_COMMON_RX_PATH_LF,
|
||||
LR20XX_RADIO_COMMON_RX_PATH_BOOST_MODE_4);
|
||||
data->rx_boost_applied = true;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&data->spi_mutex);
|
||||
}
|
||||
|
||||
/* ── Deferred hardware init ─────────────────────────────────────────── */
|
||||
|
||||
static int lr20xx_hw_init(struct lr20xx_data *data,
|
||||
const struct lr20xx_config *cfg)
|
||||
{
|
||||
void *ctx = &data->hal_ctx;
|
||||
|
||||
LOG_INF("LR20xx hardware init starting");
|
||||
|
||||
lr20xx_system_version_t ver;
|
||||
bool found = false;
|
||||
|
||||
for (int attempt = 0; attempt < 3; attempt++) {
|
||||
lr20xx_hal_status_t hal_rc = lr20xx_hal_reset(ctx);
|
||||
if (hal_rc != LR20XX_HAL_STATUS_OK) {
|
||||
LOG_WRN("LR20xx reset failed (attempt %d)", attempt);
|
||||
k_msleep(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
lr20xx_status_t st = lr20xx_system_get_version(ctx, &ver);
|
||||
if (st == LR20XX_STATUS_OK) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_WRN("LR20xx get_version failed (attempt %d)", attempt);
|
||||
k_msleep(10);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LOG_ERR("LR20xx not found after 3 attempts");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
LOG_INF("LR20xx HW:0x%02X FW:0x%04X", ver.hw, ver.fw);
|
||||
|
||||
if (cfg->tcxo_voltage_mv > 0) {
|
||||
/* Convert ms to RTC steps (31.25 us per step) */
|
||||
uint32_t rtc_steps = (cfg->tcxo_startup_delay_ms * 1000) / 31;
|
||||
lr20xx_system_set_tcxo_mode(ctx,
|
||||
get_tcxo_voltage(cfg->tcxo_voltage_mv),
|
||||
rtc_steps);
|
||||
LOG_DBG("TCXO: %dmV", cfg->tcxo_voltage_mv);
|
||||
}
|
||||
|
||||
lr20xx_system_set_reg_mode(ctx, LR20XX_SYSTEM_REG_MODE_DCDC);
|
||||
|
||||
lr20xx_configure_rfswitch(ctx, cfg);
|
||||
|
||||
LOG_INF("RF switch: en=0x%02x rx=0x%02x tx=0x%02x txhp=0x%02x",
|
||||
cfg->rfswitch_enable, cfg->rfswitch_rx,
|
||||
cfg->rfswitch_tx, cfg->rfswitch_tx_hp);
|
||||
|
||||
/* Calibrate all 7 blocks (LF_RC=1, HF_RC=2, PLL=4, AAF=8, MU=32, PA_OFF=64) */
|
||||
lr20xx_system_calibrate(ctx, 0x6F);
|
||||
LOG_INF("Calibration OK");
|
||||
|
||||
lr20xx_radio_common_set_rx_tx_fallback_mode(ctx,
|
||||
LR20XX_RADIO_FALLBACK_STDBY_RC);
|
||||
|
||||
lr20xx_radio_common_set_pkt_type(ctx, LR20XX_RADIO_COMMON_PKT_TYPE_LORA);
|
||||
|
||||
lr20xx_system_errors_t sys_errors = 0;
|
||||
lr20xx_system_get_errors(ctx, &sys_errors);
|
||||
if (sys_errors) {
|
||||
LOG_WRN("System errors at init: 0x%04x — clearing", sys_errors);
|
||||
}
|
||||
lr20xx_system_clear_errors(ctx);
|
||||
lr20xx_system_clear_irq_status(ctx, LR20XX_SYSTEM_IRQ_ALL_MASK);
|
||||
|
||||
lr20xx_hal_enable_dio1_irq(&data->hal_ctx);
|
||||
|
||||
data->rx_boost_enabled = cfg->rx_boosted;
|
||||
data->rx_boost_applied = false;
|
||||
|
||||
data->hw_initialized = true;
|
||||
LOG_INF("LR20xx driver ready");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── Driver init (lightweight — runs at POST_KERNEL) ────────────────── */
|
||||
|
||||
static int lr20xx_lora_init(const struct device *dev)
|
||||
{
|
||||
struct lr20xx_data *data = dev->data;
|
||||
const struct lr20xx_config *cfg = dev->config;
|
||||
int ret;
|
||||
|
||||
data->dev = dev;
|
||||
data->hw_initialized = false;
|
||||
|
||||
k_mutex_init(&data->spi_mutex);
|
||||
k_work_init(&data->dio1_work, lr20xx_dio1_work_handler);
|
||||
|
||||
k_work_queue_start(&data->dio1_wq, lr20xx_dio1_wq_stack,
|
||||
K_THREAD_STACK_SIZEOF(lr20xx_dio1_wq_stack),
|
||||
K_PRIO_COOP(7), NULL);
|
||||
k_thread_name_set(&data->dio1_wq.thread, "lr20xx_dio1");
|
||||
|
||||
if (!spi_is_ready_dt(&cfg->bus)) {
|
||||
LOG_ERR("SPI bus not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
memset(&data->hal_ctx, 0, sizeof(data->hal_ctx));
|
||||
data->hal_ctx.spi_dev = cfg->bus.bus;
|
||||
data->hal_ctx.spi_cfg = cfg->bus.config;
|
||||
/* Manual NSS control — disable SPI peripheral CS */
|
||||
data->hal_ctx.spi_cfg.cs.cs_is_gpio = false;
|
||||
data->hal_ctx.spi_cfg.cs.gpio.port = NULL;
|
||||
data->hal_ctx.nss.port = cfg->bus.config.cs.gpio.port;
|
||||
data->hal_ctx.nss.pin = cfg->bus.config.cs.gpio.pin;
|
||||
data->hal_ctx.nss.dt_flags = cfg->bus.config.cs.gpio.dt_flags;
|
||||
data->hal_ctx.reset = cfg->reset;
|
||||
data->hal_ctx.busy = cfg->busy;
|
||||
data->hal_ctx.dio1 = cfg->dio1;
|
||||
data->hal_ctx.radio_is_sleeping = false;
|
||||
|
||||
ret = lr20xx_hal_init(&data->hal_ctx);
|
||||
if (ret != 0) {
|
||||
LOG_ERR("HAL init failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
lr20xx_hal_set_dio1_callback(&data->hal_ctx, lr20xx_dio1_callback,
|
||||
data);
|
||||
|
||||
LOG_INF("LR20xx driver registered (hw init deferred to first config)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── Device instantiation ───────────────────────────────────────────── */
|
||||
|
||||
static DEVICE_API(lora, lr20xx_lora_api) = {
|
||||
.config = lr20xx_lora_config,
|
||||
.airtime = lr20xx_lora_airtime,
|
||||
.send = lr20xx_lora_send,
|
||||
.send_async = lr20xx_lora_send_async,
|
||||
.recv = lr20xx_lora_recv,
|
||||
.recv_async = lr20xx_lora_recv_async,
|
||||
};
|
||||
|
||||
#define LR20XX_INIT(n) \
|
||||
static const struct lr20xx_config lr20xx_config_##n = { \
|
||||
.bus = SPI_DT_SPEC_INST_GET(n, \
|
||||
SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | \
|
||||
SPI_TRANSFER_MSB), \
|
||||
.reset = GPIO_DT_SPEC_INST_GET(n, reset_gpios), \
|
||||
.busy = GPIO_DT_SPEC_INST_GET(n, busy_gpios), \
|
||||
.dio1 = GPIO_DT_SPEC_INST_GET(n, dio1_gpios), \
|
||||
.tcxo_voltage_mv = \
|
||||
DT_INST_PROP_OR(n, tcxo_voltage_mv, 0), \
|
||||
.tcxo_startup_delay_ms = \
|
||||
DT_INST_PROP_OR(n, tcxo_startup_delay_ms, 5), \
|
||||
.rx_boosted = DT_INST_PROP(n, rx_boosted), \
|
||||
.rfswitch_enable = DT_INST_PROP_OR(n, rfswitch_enable, 0), \
|
||||
.rfswitch_standby = DT_INST_PROP_OR(n, rfswitch_standby, 0),\
|
||||
.rfswitch_rx = DT_INST_PROP_OR(n, rfswitch_rx, 0), \
|
||||
.rfswitch_tx = DT_INST_PROP_OR(n, rfswitch_tx, 0), \
|
||||
.rfswitch_tx_hp = DT_INST_PROP_OR(n, rfswitch_tx_hp, 0), \
|
||||
.pa_hp_sel = DT_INST_PROP_OR(n, pa_hp_sel, 7), \
|
||||
.pa_duty_cycle = DT_INST_PROP_OR(n, pa_duty_cycle, 4), \
|
||||
}; \
|
||||
static struct lr20xx_data lr20xx_data_##n; \
|
||||
DEVICE_DT_INST_DEFINE(n, lr20xx_lora_init, NULL, \
|
||||
&lr20xx_data_##n, &lr20xx_config_##n, \
|
||||
POST_KERNEL, CONFIG_LORA_INIT_PRIORITY, \
|
||||
&lr20xx_lora_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(LR20XX_INIT)
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* LR20xx Zephyr LoRa driver — extension API
|
||||
*
|
||||
* Functions extending the standard Zephyr lora_driver_api with
|
||||
* LR20xx-specific features (RX boost, RSSI readout, preamble detection,
|
||||
* duty cycle, AGC reset).
|
||||
*/
|
||||
|
||||
#ifndef LR20XX_LORA_H
|
||||
#define LR20XX_LORA_H
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get instantaneous RSSI (for noise floor calibration)
|
||||
*
|
||||
* @param dev LoRa device
|
||||
* @return RSSI in dBm, or -128 on error
|
||||
*/
|
||||
int16_t lr20xx_get_rssi_inst(const struct device *dev);
|
||||
|
||||
/**
|
||||
* @brief Check if radio is actively receiving a packet
|
||||
*
|
||||
* Checks IRQ status for preamble/sync word detection.
|
||||
* Uses non-blocking mutex — returns false if SPI is busy.
|
||||
*
|
||||
* @param dev LoRa device
|
||||
* @return true if preamble or sync word detected
|
||||
*/
|
||||
bool lr20xx_is_receiving(const struct device *dev);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable RX duty cycle mode
|
||||
*
|
||||
* When enabled, radio alternates between RX and sleep.
|
||||
* Takes effect on the next RX start.
|
||||
*
|
||||
* @param dev LoRa device
|
||||
* @param enable true to enable, false for continuous RX
|
||||
*/
|
||||
void lr20xx_set_rx_duty_cycle(const struct device *dev, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable RX boosted mode
|
||||
*
|
||||
* @param dev LoRa device
|
||||
* @param enable true to enable boost
|
||||
*/
|
||||
void lr20xx_set_rx_boost(const struct device *dev, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Get a random number from the radio hardware RNG
|
||||
*
|
||||
* @param dev LoRa device
|
||||
* @return Random 32-bit value
|
||||
*/
|
||||
uint32_t lr20xx_get_random(const struct device *dev);
|
||||
|
||||
/**
|
||||
* @brief Reset AGC by performing warm sleep + full recalibration
|
||||
*
|
||||
* @param dev LoRa device
|
||||
*/
|
||||
void lr20xx_reset_agc(const struct device *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LR20XX_LORA_H */
|
||||
@@ -0,0 +1,92 @@
|
||||
# Copyright (c) 2025 ZephCore
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Semtech LR2021 LoRa Plus transceiver (4th-gen LoRa IP).
|
||||
Uses native Semtech lr20xx_driver SDK with Zephyr LoRa driver API.
|
||||
Supports sub-GHz + 2.4 GHz ISM + NTN/SATCOM.
|
||||
|
||||
compatible: "semtech,lr2021"
|
||||
|
||||
include: spi-device.yaml
|
||||
|
||||
properties:
|
||||
reset-gpios:
|
||||
type: phandle-array
|
||||
required: true
|
||||
description: GPIO connected to NRESET (active-low).
|
||||
|
||||
busy-gpios:
|
||||
type: phandle-array
|
||||
required: true
|
||||
description: GPIO connected to BUSY (high = busy).
|
||||
|
||||
dio1-gpios:
|
||||
type: phandle-array
|
||||
required: true
|
||||
description: GPIO connected to DIO5/IRQ line (active-high, pull-down).
|
||||
|
||||
tcxo-voltage-mv:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
TCXO supply voltage in millivolts (provided by LR2021 DIO3).
|
||||
0 = no TCXO (use XTAL). Common: 1800 (1.8V), 3300 (3.3V).
|
||||
|
||||
tcxo-startup-delay-ms:
|
||||
type: int
|
||||
default: 5
|
||||
description: TCXO startup stabilization time in milliseconds.
|
||||
|
||||
rx-boosted:
|
||||
type: boolean
|
||||
description: Enable RX boosted mode for better sensitivity (+~3dB, +~2mA).
|
||||
|
||||
rfswitch-enable:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
RF switch DIO enable bitmask (bit 0 = DIO5, bit 1 = DIO6, ...).
|
||||
Set a bit to include that DIO in RF switch control.
|
||||
|
||||
rfswitch-standby:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Bitmask of RF switch DIOs that are HIGH in standby mode.
|
||||
Bit mapping matches rfswitch-enable.
|
||||
|
||||
rfswitch-rx:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Bitmask of RF switch DIOs that are HIGH in RX mode (both LF and HF).
|
||||
Bit mapping matches rfswitch-enable.
|
||||
|
||||
rfswitch-tx:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Bitmask of RF switch DIOs that are HIGH in sub-GHz TX mode (LF PA).
|
||||
Bit mapping matches rfswitch-enable.
|
||||
|
||||
rfswitch-tx-hp:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Bitmask of RF switch DIOs that are HIGH in 2.4 GHz / high-power TX mode (HF PA).
|
||||
Bit mapping matches rfswitch-enable.
|
||||
|
||||
pa-hp-sel:
|
||||
type: int
|
||||
default: 7
|
||||
description: |
|
||||
LF PA number of slices (0-7). Maps to pa_lf_slices in the SDK.
|
||||
Higher = more PA output slices active = more power. Default 7 = maximum.
|
||||
|
||||
pa-duty-cycle:
|
||||
type: int
|
||||
default: 4
|
||||
description: |
|
||||
LF PA duty cycle (0-7). Maps to pa_lf_duty_cycle in the SDK.
|
||||
Default 4 is suitable for most sub-GHz applications.
|
||||
@@ -0,0 +1,37 @@
|
||||
diff --git a/drivers/lora/CMakeLists.txt b/drivers/lora/CMakeLists.txt
|
||||
index 9cd035fcf2b..18d04ec099a 100644
|
||||
--- a/drivers/lora/CMakeLists.txt
|
||||
+++ b/drivers/lora/CMakeLists.txt
|
||||
@@ -1,7 +1,11 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
+# ZephCore patch: adds lr11xx driver subdirectory.
|
||||
|
||||
zephyr_sources_ifdef(CONFIG_LORA_SHELL shell.c)
|
||||
|
||||
+add_subdirectory_ifdef(CONFIG_LORA_LR11XX lr11xx)
|
||||
+add_subdirectory_ifdef(CONFIG_LORA_LR20XX lr20xx)
|
||||
+
|
||||
# zephyr-keep-sorted-start
|
||||
add_subdirectory_ifdef(CONFIG_LORA_MODULE_BACKEND_LORAMAC_NODE loramac-node)
|
||||
add_subdirectory_ifdef(CONFIG_LORA_MODULE_BACKEND_LORA_BASICS_MODEM lora-basics-modem)
|
||||
diff --git a/drivers/lora/Kconfig b/drivers/lora/Kconfig
|
||||
index 657bdb9ce28..f8513b37044 100644
|
||||
--- a/drivers/lora/Kconfig
|
||||
+++ b/drivers/lora/Kconfig
|
||||
@@ -5,6 +5,7 @@
|
||||
#
|
||||
|
||||
# Top-level configuration file for LORA drivers.
|
||||
+# ZephCore patch: adds lr11xx driver Kconfig.
|
||||
|
||||
menuconfig LORA
|
||||
bool "LoRa drivers"
|
||||
@@ -60,6 +61,8 @@ config LORA_INIT_PRIORITY
|
||||
|
||||
rsource "Kconfig.sx12xx"
|
||||
rsource "Kconfig.rylrxxx"
|
||||
+rsource "lr11xx/Kconfig"
|
||||
+rsource "lr20xx/Kconfig"
|
||||
rsource "lora-basics-modem/Kconfig"
|
||||
rsource "native/Kconfig"
|
||||
|
||||
Reference in New Issue
Block a user