feat: add shared LLCC68 Zephyr module

This commit is contained in:
2026-05-19 10:30:34 +08:00
commit 8d19312631
11 changed files with 3450 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
if(CONFIG_LLCC68)
zephyr_library_named(app_driver_llcc68)
zephyr_library_sources(src/llcc68.cpp drivers/llcc68/llcc68_raw.c)
zephyr_library_include_directories(include src)
set_target_properties(app_driver_llcc68 PROPERTIES CXX_STANDARD 23 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS ON)
target_compile_options(app_driver_llcc68 PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-std=gnu++23>)
target_include_directories(app_driver_llcc68 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(app_driver_llcc68 PUBLIC zephyr_interface)
add_dependencies(app_driver_llcc68 offsets_h)
endif()
+1
View File
@@ -0,0 +1 @@
rsource "drivers/llcc68/Kconfig"
+27
View File
@@ -0,0 +1,27 @@
DT_COMPAT_SEMTECH_LLCC68 := "semtech,llcc68"
config LLCC68
bool "Semtech LLCC68 LoRa Radio Driver"
depends on SPI && GPIO
default $(dt_compat_enabled,$(DT_COMPAT_SEMTECH_LLCC68))
help
Enable the Semtech LLCC68 LoRa Radio Driver.
config LLCC68_INIT_PRIORITY
int "LLCC68 Initialization Priority"
default 90
help
The priority of the LLCC68 initialization. Lower numbers indicate
higher priority.
config LLCC68_ALWAYS_USE_SX1262_HIGH_PA
bool "LLCC68 Always Use SX1262 High Power Amplifier"
default y
help
When enabled, the LLCC68/SX1262/SX1261 driver always chooses high
power amplifier settings instead of selecting them from chip version.
module = LLCC68
module-str = llcc68
source "subsys/logging/Kconfig.template.log_config"
+69
View File
@@ -0,0 +1,69 @@
#include "llcc68_raw.h"
#include <errno.h>
#include <zephyr/sys/util.h>
#define DT_DRV_COMPAT semtech_llcc68
static void dio1_irq_trampoline(const struct device *port, struct gpio_callback *cb, uint32_t pins) {
ARG_UNUSED(port);
struct llcc68_data *data = CONTAINER_OF(cb, struct llcc68_data, dio1_irq_callback);
const struct llcc68_config *config = data->self->config;
if ((pins & BIT(config->dio1_gpio.pin)) != 0U && data->dio1_user_handler != NULL) {
data->dio1_user_handler(data->self, data->dio1_user_data);
}
}
int llcc68_init(const struct device *dev) {
const struct llcc68_config *config = dev->config;
struct llcc68_data *data = dev->data;
if (config->tx_enable_gpio.port != NULL) {
gpio_pin_configure_dt(&config->tx_enable_gpio, GPIO_OUTPUT_INACTIVE);
}
if (config->rx_enable_gpio.port != NULL) {
gpio_pin_configure_dt(&config->rx_enable_gpio, GPIO_OUTPUT_INACTIVE);
}
gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&config->busy_gpio, GPIO_INPUT);
gpio_pin_configure_dt(&config->dio1_gpio, GPIO_INPUT);
data->self = dev;
gpio_init_callback(&data->dio1_irq_callback, dio1_irq_trampoline, BIT(config->dio1_gpio.pin));
if (gpio_add_callback(config->dio1_gpio.port, &data->dio1_irq_callback) < 0) {
return -EIO;
}
gpio_pin_interrupt_configure_dt(&config->dio1_gpio, GPIO_INT_DISABLE);
return 0;
}
#define LLCC68_DEFINE(inst) \
static struct llcc68_data llcc68_data_##inst; \
static const struct llcc68_config llcc68_config_##inst = \
{ \
.spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) | SPI_TRANSFER_MSB, 100), \
.reset_gpio = GPIO_DT_SPEC_INST_GET(inst, reset_gpios), \
.busy_gpio = GPIO_DT_SPEC_INST_GET(inst, busy_gpios), \
.dio1_gpio = GPIO_DT_SPEC_INST_GET(inst, dio1_gpios), \
.tx_enable_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, tx_enable_gpios, {.port = NULL}), \
.rx_enable_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, rx_enable_gpios, {.port = NULL}), \
}; \
DEVICE_DT_INST_DEFINE(inst, \
llcc68_init, \
NULL, \
&llcc68_data_##inst, \
&llcc68_config_##inst, \
POST_KERNEL, \
CONFIG_LLCC68_INIT_PRIORITY, \
NULL)
BUILD_ASSERT(DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT),
"No status=okay nodes for DT_DRV_COMPAT; check compatible/status");
DT_INST_FOREACH_STATUS_OKAY(LLCC68_DEFINE)
+46
View File
@@ -0,0 +1,46 @@
# Copyright (c) 2019 Manivannan Sadhasivam
# Copyright (c) 2020 Andreas Sandberg
# SPDX-License-Identifier: Apache-2.0
description: |
Semtech LLCC68 LoRa transceiver
compatible: "semtech,llcc68"
include: spi-device.yaml
properties:
reset-gpios:
type: phandle-array
required: true
description: |
GPIO connected to the modem's NRESET signal.
This signal is open-drain, active-low as interpreted by the
modem.
busy-gpios:
type: phandle-array
required: true
description: |
GPIO connected to the modem's BUSY signal.
dio1-gpios:
type: phandle-array
required: true
description: |
GPIO connected to DIO1. This GPIO will be used as a generic
IRQ line from the chip.
tx-enable-gpios:
type: phandle-array
description: |
Antenna switch TX enable GPIO. If set, the driver tracks the
state of the radio and controls the RF switch.
rx-enable-gpios:
type: phandle-array
description: |
Antenna switch RX enable GPIO. If set, the driver tracks the
state of the radio and controls the RF switch.
+295
View File
@@ -0,0 +1,295 @@
#ifndef AA1F69D0_32E3_44B6_BFD7_2013E1E86A6B
#define AA1F69D0_32E3_44B6_BFD7_2013E1E86A6B
#include "llcc68_definitions.hpp"
#include "llcc68_raw.h"
#include <cstdint>
#include <expected>
#include <optional>
#include <span>
#include <variant>
#include <zephyr/drivers/gpio.h>
namespace app::driver::llcc68 {
constexpr size_t MAX_BUFFER_PAYLOAD = 128;
constexpr uint32_t TIMEOUT_NONE = 0;
constexpr uint32_t TIMEOUT_INF = 0xffffffff;
constexpr auto DEFAULT_TX_BUFFER_ADDRESS = 0x00;
constexpr auto DEFAULT_RX_BUFFER_ADDRESS = 0x80;
using user_dio1_handler_t = void (*)(const struct device *dev, void *user_data);
} // namespace app::driver::llcc68
namespace app::driver::llcc68 {
template <typename T, typename E>
using expected = std::expected<T, E>;
template <typename E>
using unexpected = std::unexpected<E>;
using unit = std::monostate;
constexpr auto DEFAULT_BUSY_TIMEOUT_MS = 100;
/**
* @brief calculate time-on-air for a LoRa packet
*
* @param len Payload length in bytes
* @param sf Spreading factor (7-12)
* @param bw Bandwidth (125, 250, 500 kHz)
* @param cr Coding rate (4/5, 4/6, 4/7, 4/8)
* @param preamble_length Preamble length in symbols
* @param header_type Header type (implicit or explicit).
* @param crc_type CRC type (none or 16-bit)
*/
constexpr airtime_t calc_time_on_air(uint8_t len, uint8_t sf, LoRaBandwidth bw,
LoRaCodingRate cr,
uint16_t preamble_length,
LoRaHeaderType header_type,
LoRaCrcType crc_type);
struct LLCC68 {
/** trivial getter */
[[nodiscard]]
const struct llcc68_config &config() const;
struct llcc68_data &data();
[[nodiscard]]
std::optional<gpio_dt_spec> tx_enable_gpio() const;
[[nodiscard]]
std::optional<gpio_dt_spec> rx_enable_gpio() const;
using timeout_ms_t = uint16_t;
/** SPI operation API */
expected<unit, error_code>
read_stream(uint8_t cmd, std::span<uint8_t> data_to_host,
timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
expected<unit, error_code>
write_stream(uint8_t cmd, std::span<const uint8_t> data_from_host,
timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
expected<unit, error_code>
read_register(uint16_t reg, std::span<uint8_t> data_to_host,
timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
expected<unit, error_code>
write_register(uint16_t reg, std::span<const uint8_t> data_from_host,
timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
/** READ BUFFER */
/**
* @brief read buffer of any offset and length, copying to user buffer
* @param[in] offset offset in the LLCC68 buffer to read from
* @param[out] data_to_host buffer to copy data into, the read length is
* determined by the size of this span
* @returns number of bytes read
*/
expected<uint8_t, error_code>
read_buffer_copy(uint8_t offset, std::span<uint8_t> data_to_host,
timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
/**
* @brief read buffer of any offset and length
* @returns span referencing internal buffer
*/
expected<std::span<const uint8_t>, error_code>
read_buffer_ref(uint8_t offset, uint8_t n,
timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
/**
* @brief read the RX buffer (whose offset would be DEFAULT_RX_BUFFER_ADDRESS)
* with all its current available data
* @returns span referencing internal buffer
*/
expected<std::span<const uint8_t>, error_code>
read_rx_buffer_ref(timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
/** WRITE BUFFER */
expected<unit, error_code>
write_tx_buffer(std::span<const uint8_t> data_from_host);
expected<unit, error_code>
flush_tx_buffer(timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
expected<unit, error_code> write_buffer_immediate_mode(
uint8_t offset, std::span<const uint8_t> data_from_host,
timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
void tx_rx_en_pin_set(TxRxPinState state);
/** LLCC68 DataSheet Function */
expected<status_t, error_code> get_status();
expected<packet_status_t, error_code> get_packet_status();
expected<unit, error_code> reset();
expected<unit, error_code> set_standby();
expected<ChipType, error_code> hal_get_chip_type();
expected<unit, error_code> set_dio_irq_params(irq_params_t params);
expected<irq_status_t, error_code> get_irq_status();
expected<unit, error_code>
clear_irq_status(irq_status_t irq = irq_status_t::all());
expected<unit, error_code> set_packet_type_lora();
expected<unit, error_code> set_packet_type_gfsk();
expected<unit, error_code>
set_modulation_params(modulation_params_t mod_params);
expected<unit, error_code> set_modulation_params(uint8_t sf, uint8_t bw,
uint8_t cr, uint8_t ldro);
expected<unit, error_code>
set_gfsk_modulation_params(gfsk_modulation_params_t mod_params);
/*!
\brief Sets LoRa sync word.
\param sync_word LoRa sync word to be set.
\note Differentiate the LoRa signal for Public or Private Network
Set to 0x3444 for Public Network
Set to 0x1424 for Private Network
*/
expected<unit, error_code> set_lora_sync_word(uint16_t sync_word);
expected<unit, error_code> set_dio2_as_rf_switch(bool en);
expected<unit, error_code> set_rf_frequency(freq_t freq_mhz);
expected<unit, error_code> set_rf_frequency(uint32_t freq_raw);
expected<unit, error_code>
set_packet_params(uint16_t preamble_length, uint8_t payload_length,
uint8_t crc_type, uint8_t hdr_type, uint8_t iq_type);
expected<unit, error_code>
set_gfsk_packet_params(gfsk_packet_params_t packet_params);
expected<unit, error_code>
set_gfsk_sync_word(std::span<const uint8_t> sync_word);
expected<unit, error_code>
set_gfsk_address_filtering(uint8_t node_address, uint8_t broadcast_address);
expected<unit, error_code> set_gfsk_crc_seed(uint16_t seed);
expected<unit, error_code> set_gfsk_crc_polynomial(uint16_t polynomial);
expected<unit, error_code> set_gfsk_whitening_seed(uint16_t seed);
expected<unit, error_code> set_tx_params(tx_params_t params);
expected<unit, error_code> set_tx_params(int8_t pwr,
LoRaTxRampTime ramp_time);
expected<unit, error_code> set_pa_config(pa_setting_t settings);
/**
* @brief fixes overly eager PA clamping
*
* fixes overly eager PA clamping
* see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.2 for
* details
*
* The LLCC68 platform embeds a Power Amplifier (PA) clamping mechanism,
* backing-off the power when over-voltage conditions are detected internally.
* This method is put in place to protect the internal devices and ensure
* long-term reliability of the chip. Considering a high-power operation of
* the LLCC68 (supporting +22dBm on-chip), these "clamping" devices are overly
* protective, causing the chip to back-down its output power when even a
* reasonable mismatch is detected at the PA output. The observation is
* typically 5 to 6 dB less output power than the expected.
*
* @param enable
* @return Result<Unit, error_code>
*/
expected<unit, error_code> fix_pa_clamping(bool enable = true);
/**
* \brief fixes inverted IQ on SX1262 rev. B
* \param iq_config RADIOLIB_SX126X_LORA_IQ_STANDARD or
* RADIOLIB_SX126X_LORA_IQ_INVERTED
* \see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.4
* for details
*/
expected<unit, error_code> fix_inverted_iq(uint8_t iq_config);
/**
* \brief Some sensitivity degradation may be observed on any LoRa device,
when receiving signals transmitted by the LLCC68 with a LoRa BW of 500 kHz.
* \note should be used before each packet transmission, to properly configure
the chip
* \param bw the bandwidth
* \sa SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.1 for
details
*/
expected<unit, error_code> fix_sensitivity(LoRaBandwidth bw);
expected<unit, error_code> fix_gfsk_tx_modulation();
expected<unit, error_code> fix_gfsk_low_bitrate(uint32_t bitrate_bps);
/**
* \brief Channel Activity Detection (CAD) params
*/
expected<unit, error_code> set_cad_params(cad_params_t params);
/**
* \brief Set the CAD mode
*
* The command SetCAD() can be used only in LoRa packet type. The Channel
* Activity Detection is a LoRa specific mode of operation where the device
* searches for the presence of a LoRa preamble signal. After the search has
* completed, the device returns in STDBY_RC mode. The length of the search is
* configured via the command SetCadParams(...). At the end of the search
* period, the device triggers the IRQ CAD DONE if it has been enabled. If a
* valid signal has been detected it also generates the IRQ CAD DETECTED.
*
* The time taken for the channel activity detection is dependent upon the
* LoRa® modulation settings used. For a given configuration (SF/BW) the
* typical CAD detection time can be selected to be either 1, 2, 4, 8 or 16
* symbols. Once the duration of the selected number of symbols has been done,
* the radio will remains for around half a symbol in Rx to post-process the
* measurement.
*/
expected<unit, error_code> set_cad();
expected<unit, error_code> set_tx(uint32_t timeout = TIMEOUT_NONE);
expected<unit, error_code> set_rx(uint32_t timeout = TIMEOUT_INF);
expected<unit, error_code> set_sleep(sleep_config_t config);
expected<unit, error_code> set_tx_continuous_wave();
expected<unit, error_code> set_tx_infinite_preamble();
expected<unit, error_code>
set_buffer_base_address(uint8_t tx_base_addr = DEFAULT_TX_BUFFER_ADDRESS,
uint8_t rx_base_addr = DEFAULT_RX_BUFFER_ADDRESS);
struct rx_buffer_status_t {
uint8_t payload_length;
uint8_t start_address;
};
expected<rx_buffer_status_t, error_code>
get_rx_buffer_status(timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS);
/**
* @brief Random Number Generator (RNG)
*/
expected<uint32_t, error_code> random_number_gen();
/** DIO1 IRQ registration helpers (like sx126x) */
expected<unit, error_code> dio1_irq_enable();
void dio1_irq_disable();
void set_dio1_irq_handler(user_dio1_handler_t handler, void *user_data);
/** high level API that wraps the raw function call */
expected<unit, error_code> hal_modem_init(lora_parameters_t params);
expected<unit, error_code> hal_gfsk_modem_init(gfsk_parameters_t params);
expected<transmit_result, error_code>
hal_async_transmit(std::span<const uint8_t> data, lora_parameters_t params);
expected<transmit_result, error_code>
hal_async_flush(lora_parameters_t params);
expected<unit, error_code> hal_async_rx(lora_parameters_t params);
expected<transmit_result, error_code>
hal_gfsk_async_transmit(std::span<const uint8_t> data,
gfsk_parameters_t params);
expected<transmit_result, error_code>
hal_gfsk_async_flush(gfsk_parameters_t params);
expected<unit, error_code> hal_gfsk_async_rx(gfsk_parameters_t params);
expected<unit, error_code> hal_set_output_power(ChipType chip,
tx_params_t params);
error_code init();
/** properties */
const struct device *dev;
};
} // namespace app::driver::llcc68
namespace app::radio {
namespace llcc68 = app::driver::llcc68;
}
#endif /* AA1F69D0_32E3_44B6_BFD7_2013E1E86A6B */
File diff suppressed because it is too large Load Diff
+42
View File
@@ -0,0 +1,42 @@
#ifndef BD6F9621_EF52_430C_86CB_3BC688233342
#define BD6F9621_EF52_430C_86CB_3BC688233342
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/types.h>
#include <stddef.h>
#define LLCC68_MAX_BUFFER_PAYLOAD 128
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*llcc68_user_dio1_handler_t)(const struct device *dev, void *user_data);
struct llcc68_config {
struct spi_dt_spec spi;
struct gpio_dt_spec reset_gpio;
struct gpio_dt_spec busy_gpio;
struct gpio_dt_spec dio1_gpio;
struct gpio_dt_spec tx_enable_gpio;
struct gpio_dt_spec rx_enable_gpio;
};
struct llcc68_data {
struct gpio_callback dio1_irq_callback;
const struct device *self;
uint8_t tx_buffer[LLCC68_MAX_BUFFER_PAYLOAD + 4];
uint8_t rx_buffer[LLCC68_MAX_BUFFER_PAYLOAD + 4];
size_t tx_xfer_size;
llcc68_user_dio1_handler_t dio1_user_handler;
void *dio1_user_data;
};
int llcc68_init(const struct device *dev);
#ifdef __cplusplus
}
#endif
#endif /* BD6F9621_EF52_430C_86CB_3BC688233342 */
+1499
View File
File diff suppressed because it is too large Load Diff
+445
View File
@@ -0,0 +1,445 @@
/**
* @file priv_radiolib_definitions.hpp
* @brief private definitions from the radiolib library;
* @note should only be included in the llcc68 driver implementation files
*/
#ifndef ADC87656_291B_49BB_A611_52533D666023
#define ADC87656_291B_49BB_A611_52533D666023
#include <cstdint>
// SX126X physical layer properties
constexpr auto RADIOLIB_SX126X_FREQUENCY_STEP_SIZE = 0.9536743164;
constexpr auto RADIOLIB_SX126X_MAX_PACKET_LENGTH = 255;
constexpr auto RADIOLIB_SX126X_CRYSTAL_FREQ = 32.0;
constexpr auto RADIOLIB_SX126X_DIV_EXPONENT = 25;
// SX126X SPI commands
// operational modes commands
constexpr uint8_t RADIOLIB_SX126X_CMD_NOP = 0x00;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_SLEEP = 0x84;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_STANDBY = 0x80;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_FS = 0xC1;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_TX = 0x83;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_RX = 0x82;
constexpr uint8_t RADIOLIB_SX126X_CMD_STOP_TIMER_ON_PREAMBLE = 0x9F;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_RX_DUTY_CYCLE = 0x94;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_CAD = 0xC5;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_TX_CONTINUOUS_WAVE = 0xD1;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_TX_INFINITE_PREAMBLE = 0xD2;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_REGULATOR_MODE = 0x96;
constexpr uint8_t RADIOLIB_SX126X_CMD_CALIBRATE = 0x89;
constexpr uint8_t RADIOLIB_SX126X_CMD_CALIBRATE_IMAGE = 0x98;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_PA_CONFIG = 0x95;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_RX_TX_FALLBACK_MODE = 0x93;
// register and buffer access commands
constexpr uint8_t RADIOLIB_SX126X_CMD_WRITE_REGISTER = 0x0D;
constexpr uint8_t RADIOLIB_SX126X_CMD_READ_REGISTER = 0x1D;
constexpr uint8_t RADIOLIB_SX126X_CMD_WRITE_BUFFER = 0x0E;
constexpr uint8_t RADIOLIB_SX126X_CMD_READ_BUFFER = 0x1E;
// DIO and IRQ control
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_DIO_IRQ_PARAMS = 0x08;
constexpr uint8_t RADIOLIB_SX126X_CMD_GET_IRQ_STATUS = 0x12;
constexpr uint8_t RADIOLIB_SX126X_CMD_CLEAR_IRQ_STATUS = 0x02;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL = 0x9D;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_DIO3_AS_TCXO_CTRL = 0x97;
// RF, modulation and packet commands
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_RF_FREQUENCY = 0x86;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_PACKET_TYPE = 0x8A;
constexpr uint8_t RADIOLIB_SX126X_CMD_GET_PACKET_TYPE = 0x11;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_TX_PARAMS = 0x8E;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_MODULATION_PARAMS = 0x8B;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_PACKET_PARAMS = 0x8C;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_CAD_PARAMS = 0x88;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_BUFFER_BASE_ADDRESS = 0x8F;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT = 0x0A;
// status commands
constexpr uint8_t RADIOLIB_SX126X_CMD_GET_STATUS = 0xC0;
constexpr uint8_t RADIOLIB_SX126X_CMD_GET_RSSI_INST = 0x15;
constexpr uint8_t RADIOLIB_SX126X_CMD_GET_RX_BUFFER_STATUS = 0x13;
constexpr uint8_t RADIOLIB_SX126X_CMD_GET_PACKET_STATUS = 0x14;
constexpr uint8_t RADIOLIB_SX126X_CMD_GET_DEVICE_ERRORS = 0x17;
constexpr uint8_t RADIOLIB_SX126X_CMD_CLEAR_DEVICE_ERRORS = 0x07;
constexpr uint8_t RADIOLIB_SX126X_CMD_GET_STATS = 0x10;
constexpr uint8_t RADIOLIB_SX126X_CMD_RESET_STATS = 0x00;
constexpr uint8_t RADIOLIB_SX126X_CMD_PRAM_UPDATE = 0xD9;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_LBT_SCAN_PARAMS = 0x9A;
constexpr uint8_t RADIOLIB_SX126X_CMD_SET_SPECTR_SCAN_PARAMS = 0x9B;
#define RADIOLIB_SX126X_REG_LR_FHSS_NUM_SYMBOLS_FREQX_MSB(X) (0x0388 + (X) * 6)
#define RADIOLIB_SX126X_REG_LR_FHSS_NUM_SYMBOLS_FREQX_LSB(X) (0x0389 + (X) * 6)
#define RADIOLIB_SX126X_REG_LR_FHSS_FREQX_0(X) (0x038A + (X) * 6)
#define RADIOLIB_SX126X_REG_LR_FHSS_FREQX_1(X) (0x038B + (X) * 6)
#define RADIOLIB_SX126X_REG_LR_FHSS_FREQX_2(X) (0x038C + (X) * 6)
#define RADIOLIB_SX126X_REG_LR_FHSS_FREQX_3(X) (0x038D + (X) * 6)
// SX126X register map
constexpr uint16_t RADIOLIB_SX126X_REG_RX_GAIN_RETENTION_0 = 0x029F; // SX1268 datasheet v1.1, section 9.6
constexpr uint16_t RADIOLIB_SX126X_REG_RX_GAIN_RETENTION_1 = 0x02A0; // SX1268 datasheet v1.1, section 9.6
constexpr uint16_t RADIOLIB_SX126X_REG_RX_GAIN_RETENTION_2 = 0x02A1; // SX1268 datasheet v1.1, section 9.6
constexpr uint16_t RADIOLIB_SX126X_REG_VERSION_STRING = 0x0320;
constexpr uint16_t RADIOLIB_SX126X_REG_HOPPING_ENABLE = 0x0385;
constexpr uint16_t RADIOLIB_SX126X_REG_LR_FHSS_PACKET_LENGTH = 0x0386;
constexpr uint16_t RADIOLIB_SX126X_REG_LR_FHSS_NUM_HOPPING_BLOCKS = 0x0387;
constexpr uint16_t RADIOLIB_SX126X_REG_SPECTRAL_SCAN_RESULT = 0x0401;
constexpr uint16_t RADIOLIB_SX126X_REG_DIOX_OUT_ENABLE = 0x0580;
constexpr uint16_t RADIOLIB_SX126X_REG_DIOX_DRIVE_STRENGTH = 0x0582;
constexpr uint16_t RADIOLIB_SX126X_REG_DIOX_IN_ENABLE = 0x0583;
constexpr uint16_t RADIOLIB_SX126X_REG_DIOX_PULL_UP_CTRL = 0x0584;
constexpr uint16_t RADIOLIB_SX126X_REG_DIOX_PULL_DOWN_CTRL = 0x0585;
constexpr uint16_t RADIOLIB_SX126X_REG_TX_BITBANG_ENABLE_0 = 0x0587;
constexpr uint16_t RADIOLIB_SX126X_REG_PATCH_UPDATE_ENABLE = 0x0610;
constexpr uint16_t RADIOLIB_SX126X_REG_TX_BITBANG_ENABLE_1 = 0x0680;
constexpr uint16_t RADIOLIB_SX126X_REG_GFSK_LOW_DATA_RATE_CONFIG = 0x06AC;
constexpr uint16_t RADIOLIB_SX126X_REG_WHITENING_INITIAL_MSB = 0x06B8;
constexpr uint16_t RADIOLIB_SX126X_REG_WHITENING_INITIAL_LSB = 0x06B9;
constexpr uint16_t RADIOLIB_SX126X_REG_RX_TX_PLD_LEN = 0x06BB;
constexpr uint16_t RADIOLIB_SX126X_REG_CRC_INITIAL_MSB = 0x06BC;
constexpr uint16_t RADIOLIB_SX126X_REG_CRC_INITIAL_LSB = 0x06BD;
constexpr uint16_t RADIOLIB_SX126X_REG_CRC_POLYNOMIAL_MSB = 0x06BE;
constexpr uint16_t RADIOLIB_SX126X_REG_CRC_POLYNOMIAL_LSB = 0x06BF;
// GFSK used
constexpr uint16_t RADIOLIB_SX126X_REG_SYNC_WORD_0 = 0x06C0;
constexpr uint16_t RADIOLIB_SX126X_REG_SYNC_WORD_1 = 0x06C1;
constexpr uint16_t RADIOLIB_SX126X_REG_SYNC_WORD_2 = 0x06C2;
constexpr uint16_t RADIOLIB_SX126X_REG_SYNC_WORD_3 = 0x06C3;
constexpr uint16_t RADIOLIB_SX126X_REG_SYNC_WORD_4 = 0x06C4;
constexpr uint16_t RADIOLIB_SX126X_REG_SYNC_WORD_5 = 0x06C5;
constexpr uint16_t RADIOLIB_SX126X_REG_SYNC_WORD_6 = 0x06C6;
constexpr uint16_t RADIOLIB_SX126X_REG_SYNC_WORD_7 = 0x06C7;
constexpr uint16_t RADIOLIB_SX126X_REG_NODE_ADDRESS = 0x06CD;
constexpr uint16_t RADIOLIB_SX126X_REG_BROADCAST_ADDRESS = 0x06CE;
constexpr uint16_t RADIOLIB_SX126X_REG_GFSK_BITRATE_CONFIG = 0x06D1;
constexpr uint16_t RADIOLIB_SX126X_REG_PAYLOAD_LENGTH = 0x0702;
constexpr uint16_t RADIOLIB_SX126X_REG_PACKET_PARAMS = 0x0704;
constexpr uint16_t RADIOLIB_SX126X_REG_LORA_SYNC_TIMEOUT = 0x0706;
constexpr uint16_t RADIOLIB_SX126X_REG_IQ_CONFIG = 0x0736;
constexpr uint16_t RADIOLIB_SX126X_REG_LORA_SYNC_WORD_MSB = 0x0740;
constexpr uint16_t RADIOLIB_SX126X_REG_LORA_SYNC_WORD_LSB = 0x0741;
constexpr uint16_t RADIOLIB_SX126X_REG_FREQ_ERROR = 0x076B;
constexpr uint16_t RADIOLIB_SX126X_REG_SPECTRAL_SCAN_STATUS = 0x07CD;
constexpr uint16_t RADIOLIB_SX126X_REG_RX_ADDR_PTR = 0x0803;
constexpr uint16_t RADIOLIB_SX126X_REG_RANDOM_NUMBER_0 = 0x0819;
constexpr uint16_t RADIOLIB_SX126X_REG_RANDOM_NUMBER_1 = 0x081A;
constexpr uint16_t RADIOLIB_SX126X_REG_RANDOM_NUMBER_2 = 0x081B;
constexpr uint16_t RADIOLIB_SX126X_REG_RANDOM_NUMBER_3 = 0x081C;
constexpr uint16_t RADIOLIB_SX126X_REG_SENSITIVITY_CONFIG = 0x0889; // SX1268 datasheet v1.1, section 15.1
constexpr uint16_t RADIOLIB_SX126X_REG_RF_FREQUENCY_0 = 0x088B;
constexpr uint16_t RADIOLIB_SX126X_REG_RF_FREQUENCY_1 = 0x088C;
constexpr uint16_t RADIOLIB_SX126X_REG_RF_FREQUENCY_2 = 0x088D;
constexpr uint16_t RADIOLIB_SX126X_REG_RF_FREQUENCY_3 = 0x088E;
constexpr uint16_t RADIOLIB_SX126X_REG_RSSI_AVG_WINDOW = 0x089B;
constexpr uint16_t RADIOLIB_SX126X_REG_GFSK_SYNC_CONFIG = 0x08B8;
constexpr uint16_t RADIOLIB_SX126X_REG_RX_GAIN = 0x08AC;
constexpr uint16_t RADIOLIB_SX126X_REG_TX_CLAMP_CONFIG = 0x08D8;
constexpr uint16_t RADIOLIB_SX126X_REG_ANA_LNA = 0x08E2;
constexpr uint16_t RADIOLIB_SX126X_REG_LNA_CAP_TUNE_N = 0x08E3;
constexpr uint16_t RADIOLIB_SX126X_REG_LNA_CAP_TUNE_P = 0x08E4;
constexpr uint16_t RADIOLIB_SX126X_REG_ANA_MIXER = 0x08E5;
constexpr uint16_t RADIOLIB_SX126X_REG_OCP_CONFIGURATION = 0x08E7;
constexpr uint16_t RADIOLIB_SX126X_REG_RTC_CTRL = 0x0902;
constexpr uint16_t RADIOLIB_SX126X_REG_XTA_TRIM = 0x0911;
constexpr uint16_t RADIOLIB_SX126X_REG_XTB_TRIM = 0x0912;
constexpr uint16_t RADIOLIB_SX126X_REG_DIO3_OUT_VOLTAGE_CTRL = 0x0920;
constexpr uint16_t RADIOLIB_SX126X_REG_EVENT_MASK = 0x0944;
constexpr uint16_t RADIOLIB_SX126X_REG_PATCH_MEMORY_BASE = 0x8000;
// SX126X SPI command variables
// RADIOLIB_SX126X_CMD_SET_SLEEP MSB LSB DESCRIPTION
constexpr uint8_t RADIOLIB_SX126X_SLEEP_START_COLD = 0b00000000; // 2 2 sleep mode: cold start, configuration is lost (default)
constexpr uint8_t RADIOLIB_SX126X_SLEEP_START_WARM = 0b00000100; // 2 2 warm start, configuration is retained
constexpr uint8_t RADIOLIB_SX126X_SLEEP_RTC_OFF = 0b00000000; // 0 0 wake on RTC timeout: disabled
constexpr uint8_t RADIOLIB_SX126X_SLEEP_RTC_ON = 0b00000001; // 0 0 enabled
// RADIOLIB_SX126X_CMD_SET_STANDBY
constexpr uint8_t RADIOLIB_SX126X_STANDBY_RC = 0x00; // 7 0 standby mode: 13 MHz RC oscillator
constexpr uint8_t RADIOLIB_SX126X_STANDBY_XOSC = 0x01; // 7 0 32 MHz crystal oscillator
// RADIOLIB_SX126X_CMD_SET_RX
constexpr uint32_t RADIOLIB_SX126X_RX_TIMEOUT_NONE = 0x000000; // 23 0 Rx timeout duration: no timeout (Rx single mode)
constexpr uint32_t RADIOLIB_SX126X_RX_TIMEOUT_INF = 0xFFFFFF; // 23 0 infinite (Rx continuous mode)
// RADIOLIB_SX126X_CMD_SET_TX
constexpr uint32_t RADIOLIB_SX126X_TX_TIMEOUT_NONE = 0x000000; // 23 0 Tx timeout duration: no timeout (Tx single mode)
// RADIOLIB_SX126X_CMD_STOP_TIMER_ON_PREAMBLE
constexpr uint8_t RADIOLIB_SX126X_STOP_ON_PREAMBLE_OFF = 0x00; // 7 0 stop timer on: sync word or header (default)
constexpr uint8_t RADIOLIB_SX126X_STOP_ON_PREAMBLE_ON = 0x01; // 7 0 preamble detection
// RADIOLIB_SX126X_CMD_SET_REGULATOR_MODE
constexpr uint8_t RADIOLIB_SX126X_REGULATOR_LDO = 0x00; // 7 0 set regulator mode: LDO (default)
constexpr uint8_t RADIOLIB_SX126X_REGULATOR_DC_DC = 0x01; // 7 0 DC-DC
// RADIOLIB_SX126X_CMD_CALIBRATE
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_IMAGE_OFF = 0b00000000; // 6 6 image calibration: disabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_IMAGE_ON = 0b01000000; // 6 6 enabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_ADC_BULK_P_OFF = 0b00000000; // 5 5 ADC bulk P calibration: disabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_ADC_BULK_P_ON = 0b00100000; // 5 5 enabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_ADC_BULK_N_OFF = 0b00000000; // 4 4 ADC bulk N calibration: disabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_ADC_BULK_N_ON = 0b00010000; // 4 4 enabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_ADC_PULSE_OFF = 0b00000000; // 3 3 ADC pulse calibration: disabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_ADC_PULSE_ON = 0b00001000; // 3 3 enabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_PLL_OFF = 0b00000000; // 2 2 PLL calibration: disabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_PLL_ON = 0b00000100; // 2 2 enabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_RC13M_OFF = 0b00000000; // 1 1 13 MHz RC osc. calibration: disabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_RC13M_ON = 0b00000010; // 1 1 enabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_RC64K_OFF = 0b00000000; // 0 0 64 kHz RC osc. calibration: disabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_RC64K_ON = 0b00000001; // 0 0 enabled
constexpr uint8_t RADIOLIB_SX126X_CALIBRATE_ALL = 0b01111111; // 6 0 calibrate all blocks
// RADIOLIB_SX126X_CMD_CALIBRATE_IMAGE
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_430_MHZ_1 = 0x6B;
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_430_MHZ_2 = 0x6F;
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_470_MHZ_1 = 0x75;
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_470_MHZ_2 = 0x81;
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_779_MHZ_1 = 0xC1;
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_779_MHZ_2 = 0xC5;
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_863_MHZ_1 = 0xD7;
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_863_MHZ_2 = 0xDB;
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_902_MHZ_1 = 0xE1;
constexpr uint8_t RADIOLIB_SX126X_CAL_IMG_902_MHZ_2 = 0xE9;
// RADIOLIB_SX126X_CMD_SET_PA_CONFIG
constexpr uint8_t RADIOLIB_SX126X_PA_CONFIG_HP_MAX = 0x07;
constexpr uint8_t RADIOLIB_SX126X_PA_CONFIG_PA_LUT = 0x01;
constexpr uint8_t RADIOLIB_SX126X_PA_CONFIG_SX1262_8 = 0x00;
// RADIOLIB_SX126X_CMD_SET_RX_TX_FALLBACK_MODE
constexpr uint8_t RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_FS = 0x40; // 7 0 after Rx/Tx go to: FS mode
constexpr uint8_t RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC = 0x30; // 7 0 standby with crystal oscillator
constexpr uint8_t RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_STDBY_RC = 0x20; // 7 0 standby with RC oscillator (default)
// RADIOLIB_SX126X_CMD_SET_DIO_IRQ_PARAMS
#define RADIOLIB_SX126X_IRQ_LR_FHSS_HOP 0b0100000000000000 // 14 14 PA ramped up during LR-FHSS hop
#define RADIOLIB_SX126X_IRQ_TIMEOUT 0b0000001000000000 // 9 9 Rx or Tx timeout
#define RADIOLIB_SX126X_IRQ_CAD_DETECTED 0b0000000100000000 // 8 8 channel activity detected
#define RADIOLIB_SX126X_IRQ_CAD_DONE 0b0000000010000000 // 7 7 channel activity detection finished
#define RADIOLIB_SX126X_IRQ_CRC_ERR 0b0000000001000000 // 6 6 wrong CRC received
#define RADIOLIB_SX126X_IRQ_HEADER_ERR 0b0000000000100000 // 5 5 LoRa header CRC error
#define RADIOLIB_SX126X_IRQ_HEADER_VALID 0b0000000000010000 // 4 4 valid LoRa header received
#define RADIOLIB_SX126X_IRQ_SYNC_WORD_VALID 0b0000000000001000 // 3 3 valid sync word detected
#define RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED 0b0000000000000100 // 2 2 preamble detected
#define RADIOLIB_SX126X_IRQ_RX_DONE 0b0000000000000010 // 1 1 packet received
#define RADIOLIB_SX126X_IRQ_TX_DONE 0b0000000000000001 // 0 0 packet transmission completed
#define RADIOLIB_SX126X_IRQ_RX_DEFAULT 0b0000001001100010 // 14 0 default for Rx (RX_DONE, TIMEOUT, CRC_ERR and HEADER_ERR)
#define RADIOLIB_SX126X_IRQ_ALL 0b0100001111111111 // 14 0 all interrupts
#define RADIOLIB_SX126X_IRQ_NONE 0b0000000000000000 // 14 0 no interrupts
// RADIOLIB_SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL
#define RADIOLIB_SX126X_DIO2_AS_IRQ 0x00 // 7 0 DIO2 configuration: IRQ
#define RADIOLIB_SX126X_DIO2_AS_RF_SWITCH 0x01 // 7 0 RF switch control
// RADIOLIB_SX126X_CMD_SET_DIO3_AS_TCXO_CTRL
#define RADIOLIB_SX126X_DIO3_OUTPUT_1_6 0x00 // 7 0 DIO3 voltage output for TCXO: 1.6 V
#define RADIOLIB_SX126X_DIO3_OUTPUT_1_7 0x01 // 7 0 1.7 V
#define RADIOLIB_SX126X_DIO3_OUTPUT_1_8 0x02 // 7 0 1.8 V
#define RADIOLIB_SX126X_DIO3_OUTPUT_2_2 0x03 // 7 0 2.2 V
#define RADIOLIB_SX126X_DIO3_OUTPUT_2_4 0x04 // 7 0 2.4 V
#define RADIOLIB_SX126X_DIO3_OUTPUT_2_7 0x05 // 7 0 2.7 V
#define RADIOLIB_SX126X_DIO3_OUTPUT_3_0 0x06 // 7 0 3.0 V
#define RADIOLIB_SX126X_DIO3_OUTPUT_3_3 0x07 // 7 0 3.3 V
// RADIOLIB_SX126X_CMD_SET_PACKET_TYPE
constexpr uint8_t RADIOLIB_SX126X_PACKET_TYPE_GFSK = 0x00; // 7 0 packet type: GFSK
constexpr uint8_t RADIOLIB_SX126X_PACKET_TYPE_LORA = 0x01; // 7 0 LoRa
constexpr uint8_t RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS = 0x03; // 7 0 LR-FHSS
// RADIOLIB_SX126X_CMD_SET_TX_PARAMS
#define RADIOLIB_SX126X_PA_RAMP_10U 0x00 // 7 0 ramp time: 10 us
#define RADIOLIB_SX126X_PA_RAMP_20U 0x01 // 7 0 20 us
#define RADIOLIB_SX126X_PA_RAMP_40U 0x02 // 7 0 40 us
#define RADIOLIB_SX126X_PA_RAMP_80U 0x03 // 7 0 80 us
#define RADIOLIB_SX126X_PA_RAMP_200U 0x04 // 7 0 200 us
#define RADIOLIB_SX126X_PA_RAMP_800U 0x05 // 7 0 800 us
#define RADIOLIB_SX126X_PA_RAMP_1700U 0x06 // 7 0 1700 us
#define RADIOLIB_SX126X_PA_RAMP_3400U 0x07 // 7 0 3400 us
// RADIOLIB_SX126X_CMD_SET_MODULATION_PARAMS
constexpr uint8_t RADIOLIB_SX126X_GFSK_FILTER_NONE = 0x00; // 7 0 GFSK filter: none
constexpr uint8_t RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_3 = 0x08; // 7 0 Gaussian, BT = 0.3
constexpr uint8_t RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_5 = 0x09; // 7 0 Gaussian, BT = 0.5
constexpr uint8_t RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_7 = 0x0A; // 7 0 Gaussian, BT = 0.7
constexpr uint8_t RADIOLIB_SX126X_GFSK_FILTER_GAUSS_1 = 0x0B; // 7 0 Gaussian, BT = 1
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_4_8 = 0x1F; // 7 0 GFSK Rx bandwidth: 4.8 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_5_8 = 0x17; // 7 0 5.8 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_7_3 = 0x0F; // 7 0 7.3 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_9_7 = 0x1E; // 7 0 9.7 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_11_7 = 0x16; // 7 0 11.7 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_14_6 = 0x0E; // 7 0 14.6 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_19_5 = 0x1D; // 7 0 19.5 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_23_4 = 0x15; // 7 0 23.4 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_29_3 = 0x0D; // 7 0 29.3 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_39_0 = 0x1C; // 7 0 39.0 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_46_9 = 0x14; // 7 0 46.9 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_58_6 = 0x0C; // 7 0 58.6 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_78_2 = 0x1B; // 7 0 78.2 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_93_8 = 0x13; // 7 0 93.8 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_117_3 = 0x0B; // 7 0 117.3 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_156_2 = 0x1A; // 7 0 156.2 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_187_2 = 0x12; // 7 0 187.2 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_234_3 = 0x0A; // 7 0 234.3 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_312_0 = 0x19; // 7 0 312.0 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_373_6 = 0x11; // 7 0 373.6 kHz
constexpr uint8_t RADIOLIB_SX126X_GFSK_RX_BW_467_0 = 0x09; // 7 0 467.0 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_7_8 = 0x00; // 7 0 LoRa bandwidth: 7.8 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_10_4 = 0x08; // 7 0 10.4 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_15_6 = 0x01; // 7 0 15.6 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_20_8 = 0x09; // 7 0 20.8 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_31_25 = 0x02; // 7 0 31.25 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_41_7 = 0x0A; // 7 0 41.7 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_62_5 = 0x03; // 7 0 62.5 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_125_0 = 0x04; // 7 0 125.0 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_250_0 = 0x05; // 7 0 250.0 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_BW_500_0 = 0x06; // 7 0 500.0 kHz
constexpr uint8_t RADIOLIB_SX126X_LORA_CR_4_5 = 0x01; // 7 0 LoRa coding rate: 4/5
constexpr uint8_t RADIOLIB_SX126X_LORA_CR_4_6 = 0x02; // 7 0 4/6
constexpr uint8_t RADIOLIB_SX126X_LORA_CR_4_7 = 0x03; // 7 0 4/7
constexpr uint8_t RADIOLIB_SX126X_LORA_CR_4_8 = 0x04; // 7 0 4/8
constexpr uint8_t RADIOLIB_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF = 0x00; // 7 0 LoRa low data rate optimization: disabled
constexpr uint8_t RADIOLIB_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON = 0x01; // 7 0 enabled
// RADIOLIB_SX126X_CMD_SET_PACKET_PARAMS
constexpr uint8_t RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_OFF = 0x00; // 7 0 GFSK minimum preamble length before reception starts: detector disabled
constexpr uint8_t RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_8 = 0x04; // 7 0 8 bits
constexpr uint8_t RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_16 = 0x05; // 7 0 16 bits
constexpr uint8_t RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_24 = 0x06; // 7 0 24 bits
constexpr uint8_t RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_32 = 0x07; // 7 0 32 bits
constexpr uint8_t RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF = 0x00; // 7 0 GFSK address filtering: disabled
constexpr uint8_t RADIOLIB_SX126X_GFSK_ADDRESS_FILT_NODE = 0x01; // 7 0 node only
constexpr uint8_t RADIOLIB_SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST = 0x02; // 7 0 node and broadcast
constexpr uint8_t RADIOLIB_SX126X_GFSK_PACKET_FIXED = 0x00; // 7 0 GFSK packet type: fixed (payload length known in advance to both sides)
constexpr uint8_t RADIOLIB_SX126X_GFSK_PACKET_VARIABLE = 0x01; // 7 0 variable (payload length added to packet)
constexpr uint8_t RADIOLIB_SX126X_GFSK_CRC_OFF = 0x01; // 7 0 GFSK packet CRC: disabled
constexpr uint8_t RADIOLIB_SX126X_GFSK_CRC_1_BYTE = 0x00; // 7 0 1 byte
constexpr uint8_t RADIOLIB_SX126X_GFSK_CRC_2_BYTE = 0x02; // 7 0 2 byte
constexpr uint8_t RADIOLIB_SX126X_GFSK_CRC_1_BYTE_INV = 0x04; // 7 0 1 byte, inverted
constexpr uint8_t RADIOLIB_SX126X_GFSK_CRC_2_BYTE_INV = 0x06; // 7 0 2 byte, inverted
constexpr uint8_t RADIOLIB_SX126X_GFSK_WHITENING_OFF = 0x00; // 7 0 GFSK data whitening: disabled
constexpr uint8_t RADIOLIB_SX126X_GFSK_WHITENING_ON = 0x01; // 7 0 enabled
constexpr uint8_t RADIOLIB_SX126X_LORA_HEADER_EXPLICIT = 0x00; // 7 0 LoRa header mode: explicit
constexpr uint8_t RADIOLIB_SX126X_LORA_HEADER_IMPLICIT = 0x01; // 7 0 implicit
constexpr uint8_t RADIOLIB_SX126X_LORA_CRC_OFF = 0x00; // 7 0 LoRa CRC mode: disabled
constexpr uint8_t RADIOLIB_SX126X_LORA_CRC_ON = 0x01; // 7 0 enabled
constexpr uint8_t RADIOLIB_SX126X_LORA_IQ_STANDARD = 0x00; // 7 0 LoRa IQ setup: standard
constexpr uint8_t RADIOLIB_SX126X_LORA_IQ_INVERTED = 0x01; // 7 0 inverted
// RADIOLIB_SX126X_CMD_SET_CAD_PARAMS
#define RADIOLIB_SX126X_CAD_ON_1_SYMB 0x00 // 7 0 number of symbols used for CAD: 1
#define RADIOLIB_SX126X_CAD_ON_2_SYMB 0x01 // 7 0 2
#define RADIOLIB_SX126X_CAD_ON_4_SYMB 0x02 // 7 0 4
#define RADIOLIB_SX126X_CAD_ON_8_SYMB 0x03 // 7 0 8
#define RADIOLIB_SX126X_CAD_ON_16_SYMB 0x04 // 7 0 16
#define RADIOLIB_SX126X_CAD_GOTO_STDBY 0x00 // 7 0 after CAD is done, always go to STDBY_RC mode
#define RADIOLIB_SX126X_CAD_GOTO_RX 0x01 // 7 0 after CAD is done, go to Rx mode if activity is detected
#define RADIOLIB_SX126X_CAD_PARAM_DEFAULT 0xFF // 7 0 used by the CAD methods to specify default parameter value
#define RADIOLIB_SX126X_CAD_PARAM_DET_MIN 10 // 7 0 default detMin CAD parameter
// RADIOLIB_SX126X_CMD_GET_STATUS
#define RADIOLIB_SX126X_STATUS_MODE_STDBY_RC 0b00100000 // 6 4 current chip mode: STDBY_RC
#define RADIOLIB_SX126X_STATUS_MODE_STDBY_XOSC 0b00110000 // 6 4 STDBY_XOSC
#define RADIOLIB_SX126X_STATUS_MODE_FS 0b01000000 // 6 4 FS
#define RADIOLIB_SX126X_STATUS_MODE_RX 0b01010000 // 6 4 RX
#define RADIOLIB_SX126X_STATUS_MODE_TX 0b01100000 // 6 4 TX
#define RADIOLIB_SX126X_STATUS_DATA_AVAILABLE 0b00000100 // 3 1 command status: packet received and data can be retrieved
#define RADIOLIB_SX126X_STATUS_CMD_TIMEOUT 0b00000110 // 3 1 SPI command timed out
#define RADIOLIB_SX126X_STATUS_CMD_INVALID 0b00001000 // 3 1 invalid SPI command
#define RADIOLIB_SX126X_STATUS_CMD_FAILED 0b00001010 // 3 1 SPI command failed to execute
#define RADIOLIB_SX126X_STATUS_TX_DONE 0b00001100 // 3 1 packet transmission done
#define RADIOLIB_SX126X_STATUS_SPI_FAILED 0b11111111 // 7 0 SPI transaction failed
// RADIOLIB_SX126X_CMD_GET_PACKET_STATUS
#define RADIOLIB_SX126X_GFSK_RX_STATUS_PREAMBLE_ERR 0b10000000 // 7 7 GFSK Rx status: preamble error
#define RADIOLIB_SX126X_GFSK_RX_STATUS_SYNC_ERR 0b01000000 // 6 6 sync word error
#define RADIOLIB_SX126X_GFSK_RX_STATUS_ADRS_ERR 0b00100000 // 5 5 address error
#define RADIOLIB_SX126X_GFSK_RX_STATUS_CRC_ERR 0b00010000 // 4 4 CRC error
#define RADIOLIB_SX126X_GFSK_RX_STATUS_LENGTH_ERR 0b00001000 // 3 3 length error
#define RADIOLIB_SX126X_GFSK_RX_STATUS_ABORT_ERR 0b00000100 // 2 2 abort error
#define RADIOLIB_SX126X_GFSK_RX_STATUS_PACKET_RECEIVED 0b00000010 // 2 2 packet received
#define RADIOLIB_SX126X_GFSK_RX_STATUS_PACKET_SENT 0b00000001 // 2 2 packet sent
// RADIOLIB_SX126X_CMD_GET_DEVICE_ERRORS
#define RADIOLIB_SX126X_PA_RAMP_ERR 0b100000000 // 8 8 device errors: PA ramping failed
#define RADIOLIB_SX126X_PLL_LOCK_ERR 0b001000000 // 6 6 PLL failed to lock
#define RADIOLIB_SX126X_XOSC_START_ERR 0b000100000 // 5 5 crystal oscillator failed to start
#define RADIOLIB_SX126X_IMG_CALIB_ERR 0b000010000 // 4 4 image calibration failed
#define RADIOLIB_SX126X_ADC_CALIB_ERR 0b000001000 // 3 3 ADC calibration failed
#define RADIOLIB_SX126X_PLL_CALIB_ERR 0b000000100 // 2 2 PLL calibration failed
#define RADIOLIB_SX126X_RC13M_CALIB_ERR 0b000000010 // 1 1 RC13M calibration failed
#define RADIOLIB_SX126X_RC64K_CALIB_ERR 0b000000001 // 0 0 RC64K calibration failed
// RADIOLIB_SX126X_CMD_SET_LBT_SCAN_PARAMS + RADIOLIB_SX126X_CMD_SET_SPECTR_SCAN_PARAMS
#define RADIOLIB_SX126X_SCAN_INTERVAL_7_68_US 10 // 7 0 RSSI reading interval: 7.68 us
#define RADIOLIB_SX126X_SCAN_INTERVAL_8_20_US 11 // 7 0 8.20 us
#define RADIOLIB_SX126X_SCAN_INTERVAL_8_68_US 12 // 7 0 8.68 us
// SX126X SPI register variables
// RADIOLIB_SX126X_REG_HOPPING_ENABLE
#define RADIOLIB_SX126X_HOPPING_ENABLED 0b00000001 // 0 0 intra-packet hopping for LR-FHSS: enabled
#define RADIOLIB_SX126X_HOPPING_DISABLED 0b00000000 // 0 0 (disabled)
// RADIOLIB_SX126X_REG_LORA_SYNC_WORD_MSB + LSB
constexpr uint8_t RADIOLIB_SX126X_SYNC_WORD_PUBLIC = 0x34; // actually 0x3444 NOTE: The low nibbles in each byte (0x_4_4) are masked out since apparently, they're reserved.
constexpr uint8_t RADIOLIB_SX126X_SYNC_WORD_PRIVATE = 0x12; // actually 0x1424 You couldn't make this up if you tried.
// RADIOLIB_SX126X_REG_TX_BITBANG_ENABLE_1
#define RADIOLIB_SX126X_TX_BITBANG_1_DISABLED 0b00000000 // 6 4 Tx bitbang: disabled (default)
#define RADIOLIB_SX126X_TX_BITBANG_1_ENABLED 0b00010000 // 6 4 enabled
// RADIOLIB_SX126X_REG_TX_BITBANG_ENABLE_0
#define RADIOLIB_SX126X_TX_BITBANG_0_DISABLED 0b00000000 // 3 0 Tx bitbang: disabled (default)
#define RADIOLIB_SX126X_TX_BITBANG_0_ENABLED 0b00001100 // 3 0 enabled
// RADIOLIB_SX126X_REG_DIOX_OUT_ENABLE
#define RADIOLIB_SX126X_DIO1_OUT_DISABLED 0b00000010 // 1 1 DIO1 output: disabled
#define RADIOLIB_SX126X_DIO1_OUT_ENABLED 0b00000000 // 1 1 enabled
#define RADIOLIB_SX126X_DIO2_OUT_DISABLED 0b00000100 // 2 2 DIO2 output: disabled
#define RADIOLIB_SX126X_DIO2_OUT_ENABLED 0b00000000 // 2 2 enabled
#define RADIOLIB_SX126X_DIO3_OUT_DISABLED 0b00001000 // 3 3 DIO3 output: disabled
#define RADIOLIB_SX126X_DIO3_OUT_ENABLED 0b00000000 // 3 3 enabled
// RADIOLIB_SX126X_REG_DIOX_IN_ENABLE
#define RADIOLIB_SX126X_DIO1_IN_DISABLED 0b00000000 // 1 1 DIO1 input: disabled
#define RADIOLIB_SX126X_DIO1_IN_ENABLED 0b00000010 // 1 1 enabled
#define RADIOLIB_SX126X_DIO2_IN_DISABLED 0b00000000 // 2 2 DIO2 input: disabled
#define RADIOLIB_SX126X_DIO2_IN_ENABLED 0b00000100 // 2 2 enabled
#define RADIOLIB_SX126X_DIO3_IN_DISABLED 0b00000000 // 3 3 DIO3 input: disabled
#define RADIOLIB_SX126X_DIO3_IN_ENABLED 0b00001000 // 3 3 enabled
// RADIOLIB_SX126X_REG_RX_GAIN
#define RADIOLIB_SX126X_RX_GAIN_BOOSTED 0x96 // 7 0 Rx gain: boosted
#define RADIOLIB_SX126X_RX_GAIN_POWER_SAVING 0x94 // 7 0 power saving
#define RADIOLIB_SX126X_RX_GAIN_SPECTRAL_SCAN 0xCB // 7 0 spectral scan
// RADIOLIB_SX126X_REG_PATCH_UPDATE_ENABLE
#define RADIOLIB_SX126X_PATCH_UPDATE_DISABLED 0b00000000 // 4 4 patch update: disabled
#define RADIOLIB_SX126X_PATCH_UPDATE_ENABLED 0b00010000 // 4 4 enabled
// RADIOLIB_SX126X_REG_SPECTRAL_SCAN_STATUS
#define RADIOLIB_SX126X_SPECTRAL_SCAN_NONE 0x00 // 7 0 spectral scan status: none
#define RADIOLIB_SX126X_SPECTRAL_SCAN_ONGOING 0x0F // 7 0 ongoing
#define RADIOLIB_SX126X_SPECTRAL_SCAN_ABORTED 0xF0 // 7 0 aborted
#define RADIOLIB_SX126X_SPECTRAL_SCAN_COMPLETED 0xFF // 7 0 completed
// RADIOLIB_SX126X_REG_RSSI_AVG_WINDOW
#define RADIOLIB_SX126X_SPECTRAL_SCAN_WINDOW_DEFAULT (0x05 << 2) // 7 0 default RSSI average window
// RADIOLIB_SX126X_REG_ANA_LNA
#define RADIOLIB_SX126X_LNA_RNG_DISABLED 0b00000001 // 0 0 random number: disabled
#define RADIOLIB_SX126X_LNA_RNG_ENABLED 0b00000000 // 0 0 enabled
// RADIOLIB_SX126X_REG_ANA_MIXER
#define RADIOLIB_SX126X_MIXER_RNG_DISABLED 0b00000001 // 7 7 random number: disabled
#define RADIOLIB_SX126X_MIXER_RNG_ENABLED 0b00000000 // 7 7 enabled
// size of the spectral scan result
#define RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE (33)
// RADIOLIB_SX126X_CMD_SET_PA_CONFIG
#define RADIOLIB_SX126X_PA_CONFIG_SX1262 0x00
#endif /* ADC87656_291B_49BB_A611_52533D666023 */
+6
View File
@@ -0,0 +1,6 @@
name: zephyr_llcc68_driver
build:
cmake: .
kconfig: Kconfig
settings:
dts_root: .