major: refactor

- 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.
This commit is contained in:
2025-05-30 16:15:41 +08:00
parent 4602468822
commit ee1c1a0497
2 changed files with 124 additions and 165 deletions

View File

@ -444,7 +444,7 @@ set_dio2_as_rf_switch(const bool en) {
/**
* \brief set packet type and do the calibration
*/
inline Result<Unit, error_t> config_packet_type(const parameters_t &params) {
inline Result<Unit, error_t> config_packet_type(uint8_t sf) {
Result<Unit, error_t> res;
constexpr auto mod = RADIOLIB_SX126X_PACKET_TYPE_LORA;
uint8_t data[7];
@ -456,7 +456,7 @@ inline Result<Unit, error_t> config_packet_type(const parameters_t &params) {
APP_RADIO_RETURN_ERR(res);
data[0] = RADIOLIB_SX126X_CAD_ON_8_SYMB;
data[1] = params.sf + 13;
data[1] = sf + 13;
data[2] = RADIOLIB_SX126X_CAD_PARAM_DET_MIN;
data[3] = RADIOLIB_SX126X_CAD_GOTO_STDBY;
data[4] = 0x00;
@ -490,12 +490,16 @@ inline Result<Unit, error_t> config_packet_type(const parameters_t &params) {
\returns Expected time-on-air in microseconds.
*/
constexpr uint32_t
calc_time_on_air(const size_t len, const calc_time_on_air_t params) {
calc_time_on_air(const size_t len,
uint8_t sf,
uint8_t bw,
uint8_t cr,
uint16_t preamble_length,
uint8_t header_type) {
// everything is in microseconds to allow integer arithmetic
// some constants have .25, these are multiplied by 4, and have _x4 postfix to indicate that fact
const auto bw_ = float{bw_khz(params.bw)};
const auto bw_ = float{bw_khz(bw)};
const auto ubw = static_cast<uint32_t>(bw_ * 10);
const auto sf = params.sf;
const uint32_t symbolLength_us = (static_cast<uint32_t>(1000 * 10) << sf) / ubw;
uint8_t sfCoeff1_x4 = 17; // (4.25 * 4)
uint8_t sfCoeff2 = 8;
@ -507,20 +511,20 @@ calc_time_on_air(const size_t len, const calc_time_on_air_t params) {
if (symbolLength_us >= 16000) {
sfDivisor = 4 * (sf - 2);
}
constexpr int8_t bitsPerCrc = 16;
constexpr int8_t N_symbol_header = params.header_type == RADIOLIB_SX126X_LORA_HEADER_EXPLICIT ? 20 : 0;
constexpr int8_t bitsPerCrc = 16;
int8_t N_symbol_header = header_type == RADIOLIB_SX126X_LORA_HEADER_EXPLICIT ? 20 : 0;
// numerator of equation in section 6.1.4 of SX1268 datasheet v1.1 (might not actually be bitcount, but it has len * 8)
int16_t bitCount = static_cast<int16_t>(8) * len + params.crc_type * bitsPerCrc - 4 * sf + sfCoeff2 + N_symbol_header;
int16_t bitCount = static_cast<int16_t>(8) * len + RADIOLIB_SX126X_LORA_CRC_ON * bitsPerCrc - 4 * sf + sfCoeff2 + N_symbol_header;
if (bitCount < 0) {
bitCount = 0;
}
// add (sfDivisor) - 1 to the numerator to give integer CEIL(...)
const uint16_t nPreCodedSymbols = (bitCount + (sfDivisor - 1)) / (sfDivisor);
const auto de = std::get<1>(cr_to_ratio(params.cr));
const auto de = std::get<1>(cr_to_ratio(cr));
// preamble can be 65k, therefore nSymbol_x4 needs to be 32 bit
const uint32_t nSymbol_x4 = (params.preamble_length + 8) * 4 + sfCoeff1_x4 + nPreCodedSymbols * de * 4;
const uint32_t nSymbol_x4 = (preamble_length + 8) * 4 + sfCoeff1_x4 + nPreCodedSymbols * de * 4;
return symbolLength_us * nSymbol_x4 / 4;
}
@ -1017,7 +1021,7 @@ read_data_internal() {
\note The IRQ RxDone means that a packet has been received but the CRC could be wrong: the user must check the CRC before validating the packet.
*/
inline Result<Unit, error_t>
kick_inf_rx() {
kick_inf_rx(const modulation_params_t &mod_params, const packet_params_t &packet_params) {
Result<Unit, error_t> res;
res = standby();
APP_RADIO_RETURN_ERR_CTX(res, "failed to standby");
@ -1032,6 +1036,11 @@ kick_inf_rx() {
DIO3_PIN == NC_PIN ? RADIOLIB_SX126X_IRQ_NONE : irq_mask,
};
res = set_modulation_params(mod_params.sf, mod_params.bw, mod_params.cr, mod_params.ldr_optimize);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set modulation params");
res = set_packet_params(packet_params.preamble_len, packet_params.payload_len, packet_params.crc_type, packet_params.hdr_type);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set packet params");
res = set_dio_irq_params(irq_params);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set dio irq params");
res = clear_irq_status();
@ -1042,27 +1051,6 @@ kick_inf_rx() {
}
enum class AFTER_TX_BEHAVIOR {
STDBY,
RX,
};
/**
* \brief will be called after each `sync_transmit`
* \note Application writer (i.e. myself) should manually enable the receiver after transmission
*/
inline void after_tx(const AFTER_TX_BEHAVIOR behavior = AFTER_TX_BEHAVIOR::RX) {
clear_irq_status();
switch (behavior) {
case AFTER_TX_BEHAVIOR::STDBY:
standby();
break;
case AFTER_TX_BEHAVIOR::RX:
kick_inf_rx();
break;
}
}
/**
After power up (battery insertion or hard reset) the chip runs automatically a calibration procedure and goes to STDBY_RC
mode. This is indicated by a low state on BUSY pin. From this state the steps are:
@ -1082,7 +1070,7 @@ inline void after_tx(const AFTER_TX_BEHAVIOR behavior = AFTER_TX_BEHAVIOR::RX) {
14. Clear the IRQ TxDone flag
*/
inline Result<Unit, error_t>
sync_transmit(const uint8_t *data, const size_t len, const calc_time_on_air_t &params) {
sync_transmit(const std::span<const uint8_t> data, const lora_parameters_t &params) {
// unimplemented
std::unreachable();
return {};
@ -1098,30 +1086,32 @@ sync_transmit(const uint8_t *data, const size_t len, const calc_time_on_air_t &p
* \see poll_tx_state
*/
inline Result<transmit_state_t, error_t>
async_transmit(const uint8_t *data, const size_t len,
const calc_time_on_air_t &params,
async_transmit(const std::span<const uint8_t> data,
const lora_parameters_t &params,
const transmit_state_t &tx_state) {
if (tx_state.is_transmitting) {
return ue_t{error_t{error::RADIO_BUSY_TX}};
}
if (len > RADIOLIB_SX126X_MAX_PACKET_LENGTH) {
if (data.size() > RADIOLIB_SX126X_MAX_PACKET_LENGTH) {
return ue_t{error_t{error::INVALID_SIZE}};
}
const auto &mod_params = params.mod_params;
const auto &packet_params = params.packet_params;
Result<Unit, error_t> res;
res = standby();
APP_RADIO_RETURN_ERR_CTX(res, "failed to standby");
res = set_packet_params(params.preamble_length, len, params.crc_type, params.header_type);
res = set_packet_params(packet_params.preamble_len, data.size(), packet_params.crc_type, packet_params.hdr_type);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set packet params");
res = set_buffer_base_address();
APP_RADIO_RETURN_ERR_CTX(res, "failed to set buffer base address");
res = write_buffer(std::span<const uint8_t>{data, len});
res = write_buffer(data);
APP_RADIO_RETURN_ERR_CTX(res, "failed to write buffer");
res = fix_sensitivity(params.bw);
res = fix_sensitivity(mod_params.bw);
APP_RADIO_RETURN_ERR_CTX(res, "failed to fix sensitivity");
constexpr auto irq_mask = RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT;
@ -1139,7 +1129,14 @@ async_transmit(const uint8_t *data, const size_t len,
res = tx();
APP_RADIO_RETURN_ERR_CTX(res, "failed to transmit");
const auto timeout_us = calc_time_on_air(len, params) * 11u / 10u;
constexpr auto TIMEOUT_FACTOR = 11u / 10u;
const auto timeout_us = calc_time_on_air(data.size(),
mod_params.sf,
mod_params.bw,
mod_params.cr,
packet_params.preamble_len,
packet_params.hdr_type) *
TIMEOUT_FACTOR;
const uint16_t timeout_ms = timeout_us / 1000;
auto instant = Instant<>{};
return transmit_state_t{
@ -1149,13 +1146,6 @@ async_transmit(const uint8_t *data, const size_t len,
};
}
inline Result<transmit_state_t, error_t>
async_transmit(const std::span<const uint8_t> data,
const calc_time_on_air_t &params,
const transmit_state_t &tx_state) {
return async_transmit(data.data(), data.size(), params, tx_state);
}
static constexpr auto init_pins = [](void (*isr)(void *), void *arg) {
if (RST_PIN != GPIO_NUM_NC) {
@ -1183,7 +1173,7 @@ static constexpr auto init_pins = [](void (*isr)(void *), void *arg) {
}
};
static constexpr auto begin = [](const parameters_t &params) -> Result<Unit, error_t> {
static constexpr auto begin = [](const lora_parameters_t &params) -> Result<Unit, error_t> {
/**
* Most of the commands can be sent in any order except for the radio configuration commands which will set the radio in
* the proper operating mode. Indeed, it is mandatory to set the radio protocol using the command SetPacketType(...) as a first
@ -1212,16 +1202,17 @@ static constexpr auto begin = [](const parameters_t &params) -> Result<Unit, err
details::__tcxo_delay__ = *voltage_;
APP_RADIO_RETURN_ERR_CTX(res, "failed to set TCXO");
}
const auto &mod_params = params.mod_params;
const auto &packet_params = params.packet_params;
// SetPacketType
res = config_packet_type(params);
res = config_packet_type(mod_params.sf);
APP_RADIO_RETURN_ERR_CTX(res, "failed to config packet type");
// SetModulationParams
res = set_modulation_params(params.sf,
params.bw,
params.cr,
params.ldr_optimize);
res = set_modulation_params(mod_params.sf,
mod_params.bw,
mod_params.cr,
mod_params.ldr_optimize);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set modulation params");
res = set_sync_word(params.sync_word);
@ -1245,10 +1236,10 @@ static constexpr auto begin = [](const parameters_t &params) -> Result<Unit, err
APP_RADIO_RETURN_ERR_CTX(res, "failed to set frequency");
// SetPacketParams
res = set_packet_params(params.preamble_len,
0x00,
DEFAULT_CRC_TYPE,
DEFAULT_HEADER_TYPE);
res = set_packet_params(packet_params.preamble_len,
packet_params.payload_len,
packet_params.crc_type,
packet_params.hdr_type);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set packet params");
res = set_output_power(chip_type_to_max_tx_power(chip));