- Introduced new enums for LoRa bandwidth and coding rate to improve clarity. - Updated default values for preamble length, frequency, bandwidth, and coding rate. - Added new structures for modulation and packet parameters, encapsulating related settings. - Refactored functions to utilize the new structures, improving parameter management in the llcc68 component.
360 lines
8.3 KiB
C++
360 lines
8.3 KiB
C++
//
|
||
// Created by Kurosu Chan on 2024/1/26.
|
||
//
|
||
|
||
#ifndef LLCC68_DEFINITIONS_H
|
||
#define LLCC68_DEFINITIONS_H
|
||
#include <cstddef>
|
||
#include <cstdint>
|
||
#include <tuple>
|
||
#include <variant>
|
||
#include "radiolib_definitions.hpp"
|
||
|
||
namespace app::driver::llcc68 {
|
||
using freq_t = float;
|
||
enum LoRaBandwidth : uint8_t {
|
||
BW_10_4 = 0x08,
|
||
BW_15_6 = 0x01,
|
||
BW_20_8 = 0x09,
|
||
BW_31_25 = 0x02,
|
||
BW_41_7 = 0x0A,
|
||
BW_62_5 = 0x03,
|
||
BW_125_0 = 0x04,
|
||
BW_250_0 = 0x05,
|
||
BW_500_0 = 0x06,
|
||
};
|
||
|
||
enum LoRaCodingRate : uint8_t {
|
||
CR_4_5 = 0x01,
|
||
CR_4_6 = 0x02,
|
||
CR_4_7 = 0x03,
|
||
CR_4_8 = 0x04,
|
||
};
|
||
|
||
constexpr uint16_t DEFAULT_PREAMBLE_LEN = 8;
|
||
constexpr uint8_t DEFAULT_SYNC_WORD = RADIOLIB_SX126X_SYNC_WORD_PRIVATE;
|
||
constexpr uint8_t DEFAULT_CRC_TYPE = RADIOLIB_SX126X_LORA_CRC_OFF;
|
||
constexpr uint8_t DEFAULT_HEADER_TYPE = RADIOLIB_SX126X_LORA_HEADER_EXPLICIT;
|
||
constexpr uint8_t DEFAULT_IQ_TYPE = RADIOLIB_SX126X_LORA_IQ_STANDARD;
|
||
|
||
constexpr auto DEFAULT_SF = 7;
|
||
constexpr auto DEFAULT_FREQUENCY = freq_t{433.05};
|
||
constexpr auto DEFAULT_BW = BW_250_0;
|
||
constexpr auto DEFAULT_CR = CR_4_5;
|
||
constexpr auto DEFAULT_LDR_OPTIMIZE = RADIOLIB_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF;
|
||
|
||
|
||
struct modulation_params_t {
|
||
uint8_t bw;
|
||
uint8_t sf;
|
||
uint8_t cr;
|
||
uint8_t ldr_optimize;
|
||
|
||
static modulation_params_t Default() {
|
||
return modulation_params_t{
|
||
.bw = DEFAULT_BW,
|
||
.sf = DEFAULT_SF,
|
||
.cr = DEFAULT_CR,
|
||
.ldr_optimize = DEFAULT_LDR_OPTIMIZE,
|
||
};
|
||
}
|
||
};
|
||
|
||
struct packet_params_t {
|
||
uint16_t preamble_len;
|
||
uint8_t payload_len;
|
||
uint8_t crc_type;
|
||
uint8_t hdr_type;
|
||
|
||
static packet_params_t Default() {
|
||
return packet_params_t{
|
||
.preamble_len = DEFAULT_PREAMBLE_LEN,
|
||
.payload_len = 0xff,
|
||
.crc_type = DEFAULT_CRC_TYPE,
|
||
.hdr_type = DEFAULT_HEADER_TYPE,
|
||
};
|
||
}
|
||
};
|
||
|
||
struct lora_parameters_t {
|
||
modulation_params_t mod_params;
|
||
packet_params_t packet_params;
|
||
freq_t frequency;
|
||
uint8_t sync_word;
|
||
|
||
static lora_parameters_t Default() {
|
||
return lora_parameters_t{
|
||
.mod_params = modulation_params_t::Default(),
|
||
.packet_params = packet_params_t::Default(),
|
||
.frequency = DEFAULT_FREQUENCY,
|
||
.sync_word = DEFAULT_SYNC_WORD,
|
||
};
|
||
}
|
||
};
|
||
|
||
enum class ChipType {
|
||
Unknown,
|
||
LLCC68,
|
||
SX1261,
|
||
SX1262,
|
||
};
|
||
|
||
inline const char *chip_type_str(const ChipType &chip) {
|
||
switch (chip) {
|
||
case ChipType::LLCC68:
|
||
return "LLCC68";
|
||
case ChipType::SX1261:
|
||
return "SX1261";
|
||
case ChipType::SX1262:
|
||
return "SX1262";
|
||
default:
|
||
return "Unknown";
|
||
}
|
||
}
|
||
|
||
|
||
/// @note suitable SX1262/LLCC68
|
||
enum class PaOptimalPresetHigh : uint8_t {
|
||
DBM_14,
|
||
DBM_17,
|
||
DBM_20,
|
||
DBM_22,
|
||
};
|
||
|
||
/// @note suitable SX1261
|
||
enum class PaOptimalPresetLow : uint8_t {
|
||
DBM_10,
|
||
DBM_14,
|
||
DBM_15,
|
||
};
|
||
|
||
using PaOptimalPreset = std::variant<PaOptimalPresetHigh, PaOptimalPresetLow>;
|
||
|
||
struct pa_config_t {
|
||
uint8_t pa_duty_cycle;
|
||
uint8_t hp_max;
|
||
uint8_t device_sel;
|
||
};
|
||
|
||
enum class PacketType : uint8_t {
|
||
FSK = RADIOLIB_SX126X_PACKET_TYPE_GFSK,
|
||
LORA = RADIOLIB_SX126X_PACKET_TYPE_LORA,
|
||
LR_FHSS = RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS,
|
||
};
|
||
|
||
|
||
enum class TcxoVoltage : uint8_t {
|
||
V_1_6 = 0x00,
|
||
V_1_7 = 0x01,
|
||
V_1_8 = 0x02,
|
||
V_2_2 = 0x03,
|
||
V_2_4 = 0x04,
|
||
V_2_7 = 0x05,
|
||
V_3_0 = 0x06,
|
||
V_3_3 = 0x07,
|
||
};
|
||
|
||
enum class CommandStatus : uint8_t {
|
||
RESERVED = 0x00, // 0b000
|
||
RFU = 0x01, // 0b001
|
||
DATA_AVAILABLE = 0x02, // 0b010
|
||
COMMAND_TIMEOUT = 0x03, // 0b011 i.e. TIMEOUT
|
||
COMMAND_PROCESSING_ERROR = 0x04, // 0b100 i.e. INVALID
|
||
FAILURE_TO_EXECUTE_COMMAND = 0x05, // 0b101 i.e. FAILED
|
||
COMMAND_TX_DONE = 0x06, // 0b110
|
||
};
|
||
|
||
enum class ChipMode : uint8_t {
|
||
UNUSED = 0x00, // 0b000
|
||
RFU = 0x01, // 0b001
|
||
STBY_RC = 0x02, // 0b010
|
||
STBY_XOSC = 0x03, // 0b011
|
||
FS = 0x04, // 0b100
|
||
RX = 0x05, // 0b101
|
||
TX = 0x06, // 0b110
|
||
};
|
||
|
||
|
||
struct __attribute__((packed)) status_t {
|
||
uint8_t reserved_1 : 1;
|
||
CommandStatus command_status : 3;
|
||
ChipMode chip_mode : 3;
|
||
uint8_t reserved_2 : 1;
|
||
};
|
||
static_assert(sizeof(status_t) == 1);
|
||
|
||
|
||
struct __attribute__((packed)) lora_packet_status_t {
|
||
// Average over last packet received of RSSI
|
||
// Actual signal power is –RssiPkt/2 (dBm)
|
||
uint8_t rssi_pkt;
|
||
// Estimation of SNR on last packet received in two’s compliment format multiplied by 4.
|
||
// Actual SNR in dB =SnrPkt/4
|
||
uint8_t snr_pkt;
|
||
// Estimation of RSSI of the LoRa® signal (after despreading) on last packet received.
|
||
// Actual Rssi in dB = -SignalRssiPkt/2
|
||
uint8_t signal_rssi_pkt;
|
||
|
||
float rssi_pkt_dbm() const {
|
||
return -rssi_pkt / 2.0f;
|
||
}
|
||
|
||
float snr_pkt_db() const {
|
||
return snr_pkt / 4.0f;
|
||
}
|
||
|
||
float signal_rssi_pkt_dbm() const {
|
||
return -signal_rssi_pkt / 2.0f;
|
||
}
|
||
};
|
||
|
||
struct __attribute__((packed)) fsk_packet_status_t {
|
||
// bit 7: preamble err
|
||
// bit 6: sync err
|
||
// bit 5: adrs err
|
||
// bit 4: crc err
|
||
// bit 3: length err
|
||
// bit 2: abort err
|
||
// bit 1: pkt received
|
||
// bit 0: pkt sent
|
||
uint8_t rx_status;
|
||
// RSSI value latched upon the detection of the sync address.
|
||
// [negated, dBm, fixdt(0,8,1)]
|
||
// Actual signal power is –RssiSync/2 (dBm)
|
||
uint8_t rssi_sync;
|
||
// RSSI average value over the payload of the received packet. Latched upon the pkt_done IRQ.
|
||
// [negated, dBm, fixdt(0,8,1)]
|
||
// Actual signal power is –RssiAvg/2 (dBm)
|
||
uint8_t rssi_avg;
|
||
};
|
||
|
||
union packet_status_t {
|
||
uint8_t raw[3];
|
||
lora_packet_status_t lora;
|
||
fsk_packet_status_t fsk;
|
||
};
|
||
|
||
|
||
struct __attribute__((packed)) op_error_t {
|
||
bool RC64K_CALIB_ERR : 1; // RC64k calibration failed
|
||
bool RC13M_CALIB_ERR : 1; // RC13M calibration failed
|
||
bool PLL_CALIB_ERR : 1; // PLL calibration failed
|
||
bool ADC_CALIB_ERR : 1; // ADC calibration failed
|
||
bool IMG_CALIB_ERR : 1; // IMG calibration failed
|
||
bool XOSC_START_ERR : 1; // XOSC failed to start
|
||
bool PLL_LOCK_ERR : 1; // PLL failed to lock
|
||
uint8_t rfu_1 : 1; // RFU
|
||
bool PA_RAMP_ERR : 1; // PA ramping failed
|
||
uint8_t rfu_2 : 7; // RFU
|
||
};
|
||
|
||
static_assert(sizeof(op_error_t) == 2);
|
||
|
||
constexpr bool in_range(const auto v, const auto min, const auto max) {
|
||
return v >= min && v <= max;
|
||
}
|
||
|
||
constexpr bool valid_cr(const uint8_t cr) {
|
||
switch (cr) {
|
||
case RADIOLIB_SX126X_LORA_CR_4_5:
|
||
case RADIOLIB_SX126X_LORA_CR_4_6:
|
||
case RADIOLIB_SX126X_LORA_CR_4_7:
|
||
case RADIOLIB_SX126X_LORA_CR_4_8:
|
||
return true;
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
constexpr std::tuple<uint8_t, uint8_t>
|
||
cr_to_ratio(const uint8_t cr) {
|
||
switch (cr) {
|
||
case RADIOLIB_SX126X_LORA_CR_4_5:
|
||
return {4, 5};
|
||
case RADIOLIB_SX126X_LORA_CR_4_6:
|
||
return {4, 6};
|
||
case RADIOLIB_SX126X_LORA_CR_4_7:
|
||
return {4, 7};
|
||
case RADIOLIB_SX126X_LORA_CR_4_8:
|
||
return {4, 8};
|
||
default:
|
||
return {0, 1};
|
||
}
|
||
}
|
||
|
||
constexpr bool valid_ldr_optimize(const uint8_t ldr_optimize) {
|
||
if (ldr_optimize > RADIOLIB_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
constexpr bool valid_bw(const uint8_t bw) {
|
||
switch (bw) {
|
||
case RADIOLIB_SX126X_LORA_BW_7_8:
|
||
case RADIOLIB_SX126X_LORA_BW_10_4:
|
||
case RADIOLIB_SX126X_LORA_BW_15_6:
|
||
case RADIOLIB_SX126X_LORA_BW_20_8:
|
||
case RADIOLIB_SX126X_LORA_BW_31_25:
|
||
case RADIOLIB_SX126X_LORA_BW_41_7:
|
||
case RADIOLIB_SX126X_LORA_BW_62_5:
|
||
case RADIOLIB_SX126X_LORA_BW_125_0:
|
||
case RADIOLIB_SX126X_LORA_BW_250_0:
|
||
case RADIOLIB_SX126X_LORA_BW_500_0:
|
||
return true;
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
using bw_t = float;
|
||
constexpr bw_t bw_khz(const uint8_t bw) {
|
||
switch (bw) {
|
||
case RADIOLIB_SX126X_LORA_BW_7_8:
|
||
return bw_t{7.8f};
|
||
case RADIOLIB_SX126X_LORA_BW_10_4:
|
||
return bw_t{10.4f};
|
||
case RADIOLIB_SX126X_LORA_BW_15_6:
|
||
return bw_t{15.6f};
|
||
case RADIOLIB_SX126X_LORA_BW_20_8:
|
||
return bw_t{20.8f};
|
||
case RADIOLIB_SX126X_LORA_BW_31_25:
|
||
return bw_t{31.25f};
|
||
case RADIOLIB_SX126X_LORA_BW_41_7:
|
||
return bw_t{41.7f};
|
||
case RADIOLIB_SX126X_LORA_BW_62_5:
|
||
return bw_t{62.5f};
|
||
case RADIOLIB_SX126X_LORA_BW_125_0:
|
||
return bw_t{125.0f};
|
||
case RADIOLIB_SX126X_LORA_BW_250_0:
|
||
return bw_t{250.0f};
|
||
case RADIOLIB_SX126X_LORA_BW_500_0:
|
||
return bw_t{500.0f};
|
||
default:
|
||
return bw_t{0};
|
||
}
|
||
}
|
||
|
||
constexpr bool valid_sf(const uint8_t bw, const uint8_t sf) {
|
||
if (const bool ok = valid_bw(bw); not ok) {
|
||
return false;
|
||
}
|
||
switch (bw) {
|
||
case RADIOLIB_SX126X_LORA_BW_125_0:
|
||
return in_range(sf, 5, 9);
|
||
case RADIOLIB_SX126X_LORA_BW_250_0:
|
||
return in_range(sf, 5, 10);
|
||
case RADIOLIB_SX126X_LORA_BW_500_0:
|
||
return in_range(sf, 5, 11);
|
||
default:
|
||
return in_range(sf, 5, 12);
|
||
}
|
||
}
|
||
|
||
constexpr bool valid_freq(const freq_t freq) {
|
||
return in_range(freq, freq_t{150.0}, freq_t{960.0});
|
||
}
|
||
}
|
||
|
||
#endif // LLCC68_DEFINITIONS_H
|