feat: add option to disable radio calibration and update status error handling

This commit is contained in:
2025-08-07 14:51:57 +08:00
parent c4a61d2708
commit 72299b62ce
6 changed files with 57 additions and 25 deletions

View File

@ -10,7 +10,12 @@ idf_component_register(
) )
# This option would make LLCC68 ignore `SPI_CMD_INVALID` error. # This option would make LLCC68 ignore `SPI_CMD_INVALID` error.
option(APP_SPI_DISABLE_INVALID_STATUS_CHECK "Disable invalid status check" ON) option(APP_SPI_DISABLE_INVALID_STATUS_CHECK "Disable invalid status check" OFF)
if (APP_SPI_DISABLE_INVALID_STATUS_CHECK) if (APP_SPI_DISABLE_INVALID_STATUS_CHECK)
target_compile_definitions(${COMPONENT_LIB} PUBLIC APP_SPI_DISABLE_INVALID_STATUS_CHECK) target_compile_definitions(${COMPONENT_LIB} PUBLIC APP_SPI_DISABLE_INVALID_STATUS_CHECK)
endif() endif()
option(APP_RADIO_DISABLE_CALIBRATION "Disable radio calibration" ON)
if (APP_RADIO_DISABLE_CALIBRATION)
target_compile_definitions(${COMPONENT_LIB} PUBLIC APP_RADIO_DISABLE_CALIBRATION)
endif()

View File

@ -3,7 +3,8 @@
#include <array> #include <array>
#include <tuple> #include <tuple>
#define APP_ERR_TBL_IT(err) {err, #err} #define APP_ERR_TBL_IT(err) \
{ err, #err }
namespace app::driver::hal::error { namespace app::driver::hal::error {
using t = int; using t = int;
@ -41,6 +42,7 @@ constexpr t SPI_CMD_INVALID = SPI_ERR_BASE + 3;
// The command was successfully processed, however the chip could not execute the command; // The command was successfully processed, however the chip could not execute the command;
// for instance it was unable to enter the specified device mode or send the requested data // for instance it was unable to enter the specified device mode or send the requested data
constexpr t SPI_CMD_FAILED = SPI_ERR_BASE + 4; constexpr t SPI_CMD_FAILED = SPI_ERR_BASE + 4;
constexpr t SPI_INVALID_RADIO_STATE = SPI_ERR_BASE + 5; /*!< Radio is in an invalid state for the requested operation */
constexpr t RADIO_ERR_BASE = 0x1'3000; constexpr t RADIO_ERR_BASE = 0x1'3000;
constexpr t RADIO_CHIP_NOT_FOUND = RADIO_ERR_BASE + 1; constexpr t RADIO_CHIP_NOT_FOUND = RADIO_ERR_BASE + 1;
@ -76,6 +78,7 @@ constexpr auto error_table = std::to_array<std::tuple<t, const char *>>(
APP_ERR_TBL_IT(SPI_TIMEOUT), APP_ERR_TBL_IT(SPI_TIMEOUT),
APP_ERR_TBL_IT(SPI_CMD_INVALID), APP_ERR_TBL_IT(SPI_CMD_INVALID),
APP_ERR_TBL_IT(SPI_CMD_FAILED), APP_ERR_TBL_IT(SPI_CMD_FAILED),
APP_ERR_TBL_IT(SPI_INVALID_RADIO_STATE),
APP_ERR_TBL_IT(RADIO_CHIP_NOT_FOUND), APP_ERR_TBL_IT(RADIO_CHIP_NOT_FOUND),
APP_ERR_TBL_IT(RADIO_INVALID_TCXO_VOLTAGE), APP_ERR_TBL_IT(RADIO_INVALID_TCXO_VOLTAGE),

View File

@ -48,7 +48,8 @@ void init(spi_config_t config = {SPI2_HOST, 4'000'000});
inline error_t status_to_err(const uint8_t status) { inline error_t status_to_err(const uint8_t status) {
const auto st = *reinterpret_cast<const llcc68::status_t *>(&status); const auto st = *reinterpret_cast<const llcc68::status_t *>(&status);
switch (st.command_status) { error_t status_ok = [](llcc68::CommandStatus st) {
switch (st) {
case llcc68::CommandStatus::COMMAND_TIMEOUT: case llcc68::CommandStatus::COMMAND_TIMEOUT:
return error::SPI_TIMEOUT; return error::SPI_TIMEOUT;
case llcc68::CommandStatus::FAILURE_TO_EXECUTE_COMMAND: case llcc68::CommandStatus::FAILURE_TO_EXECUTE_COMMAND:
@ -62,6 +63,21 @@ inline error_t status_to_err(const uint8_t status) {
default: default:
return error::OK; return error::OK;
} }
}(st.command_status);
if (status_ok != error::OK) {
return status_ok;
}
error_t chip_mode_usual = [](llcc68::ChipMode mode) {
switch (mode) {
case llcc68::ChipMode::TX:
case llcc68::ChipMode::RX:
case llcc68::ChipMode::STBY_RC:
return error::OK;
default:
return error::SPI_INVALID_RADIO_STATE;
}
}(st.chip_mode);
return chip_mode_usual;
} }
/*! /*!

View File

@ -494,16 +494,17 @@ inline Result<Unit, error_t> config_packet_type(uint8_t sf) {
res = set_dio_irq_params(irq_params); res = set_dio_irq_params(irq_params);
APP_RADIO_RETURN_ERR(res); APP_RADIO_RETURN_ERR(res);
#ifndef APP_RADIO_DISABLE_CALIBRATION
data[0] = RADIOLIB_SX126X_CALIBRATE_ALL; data[0] = RADIOLIB_SX126X_CALIBRATE_ALL;
res = spi::write_stream(RADIOLIB_SX126X_CMD_CALIBRATE, std::span<const uint8_t>{data, 1}); res = spi::write_stream(RADIOLIB_SX126X_CMD_CALIBRATE, std::span<const uint8_t>{data, 1});
APP_RADIO_RETURN_ERR(res); APP_RADIO_RETURN_ERR(res);
// The total calibration time if all blocks are calibrated is 3.5 ms. The // The total calibration time if all blocks are calibrated is 3.5 ms. The
// calibration must be launched in STDBY_RC mode and the BUSY pins will be // calibration must be launched in STDBY_RC mode and the BUSY pins will be
// high during the calibration process. A falling edge of BUSY indicates the // high during the calibration process. A falling edge of BUSY indicates the
// end of the procedure. // end of the procedure.
delay_ms(5); delay_ms(5);
while (gpio::digital_read(BUSY_PIN) == gpio::HIGH) {} while (gpio::digital_read(BUSY_PIN) == gpio::HIGH) {}
#endif /** APP_RADIO_DISABLE_CALIBRATION */
return {}; return {};
} }
@ -1130,19 +1131,19 @@ async_transmit(const std::span<const uint8_t> data,
Result<Unit, error_t> res; Result<Unit, error_t> res;
res = standby(); res = standby();
APP_RADIO_RETURN_ERR_CTX(res, "failed to standby"); APP_RADIO_RETURN_ERR_CTX(res, "standby");
res = set_packet_params(packet_params.preamble_len, data.size(), packet_params.crc_type, packet_params.hdr_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"); APP_RADIO_RETURN_ERR_CTX(res, "set packet params");
res = set_buffer_base_address(); res = set_buffer_base_address();
APP_RADIO_RETURN_ERR_CTX(res, "failed to set buffer base address"); APP_RADIO_RETURN_ERR_CTX(res, "set buffer base address");
res = write_buffer(data); res = write_buffer(data);
APP_RADIO_RETURN_ERR_CTX(res, "failed to write buffer"); APP_RADIO_RETURN_ERR_CTX(res, "write buffer");
res = fix_sensitivity(mod_params.bw); res = fix_sensitivity(mod_params.bw);
APP_RADIO_RETURN_ERR_CTX(res, "failed to fix sensitivity"); APP_RADIO_RETURN_ERR_CTX(res, "fix sensitivity");
constexpr auto irq_mask = RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT; constexpr auto irq_mask = RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT;
constexpr auto irq_params = irq_params_t{ constexpr auto irq_params = irq_params_t{
@ -1152,12 +1153,12 @@ async_transmit(const std::span<const uint8_t> data,
DIO3_PIN == NC_PIN ? RADIOLIB_SX126X_IRQ_NONE : irq_mask, DIO3_PIN == NC_PIN ? RADIOLIB_SX126X_IRQ_NONE : irq_mask,
}; };
res = set_dio_irq_params(irq_params); res = set_dio_irq_params(irq_params);
APP_RADIO_RETURN_ERR_CTX(res, "failed to set dio irq params"); APP_RADIO_RETURN_ERR_CTX(res, "set dio irq params");
clear_irq_status(irq_mask); clear_irq_status(irq_mask);
APP_RADIO_RETURN_ERR_CTX(res, "failed to clear irq status"); APP_RADIO_RETURN_ERR_CTX(res, "clear irq status");
res = tx(); res = tx();
APP_RADIO_RETURN_ERR_CTX(res, "failed to transmit"); APP_RADIO_RETURN_ERR_CTX(res, "tx");
constexpr auto TIMEOUT_FACTOR = 11u / 10u; constexpr auto TIMEOUT_FACTOR = 11u / 10u;
const auto timeout_us = calc_time_on_air(data.size(), const auto timeout_us = calc_time_on_air(data.size(),
@ -1310,7 +1311,12 @@ static constexpr auto begin = [](const lora_parameters_t &params) -> Result<Unit
res = set_dio2_as_rf_switch(false); res = set_dio2_as_rf_switch(false);
APP_RADIO_RETURN_ERR_CTX(res, "set dio2 as rf switch"); APP_RADIO_RETURN_ERR_CTX(res, "set dio2 as rf switch");
res = set_frequency(params.frequency); #ifdef APP_RADIO_DISABLE_CALIBRATION
res = set_frequency(params.frequency, false);
#else
res = set_frequency(params.frequency, true);
#endif /* APP_RADIO_DISABLE_CALIBRATION */
APP_RADIO_RETURN_ERR_CTX(res, "set frequency"); APP_RADIO_RETURN_ERR_CTX(res, "set frequency");
// SetPacketParams // SetPacketParams

View File

@ -284,10 +284,12 @@ inline const char *to_str(const ChipMode &mode) {
struct __attribute__((packed)) status_t { struct __attribute__((packed)) status_t {
// LSB
uint8_t reserved_1 : 1; uint8_t reserved_1 : 1;
CommandStatus command_status : 3; CommandStatus command_status : 3;
ChipMode chip_mode : 3; ChipMode chip_mode : 3;
uint8_t reserved_2 : 1; uint8_t reserved_2 : 1;
// MSB
}; };
static_assert(sizeof(status_t) == 1); static_assert(sizeof(status_t) == 1);

View File

@ -43,7 +43,7 @@ static constexpr auto verify_statuses = [](std::span<const uint8_t> statuses) {
uint8_t i = 0; uint8_t i = 0;
for (const auto st : statuses) { for (const auto st : statuses) {
if (const auto err = status_to_err(st); err != error::OK) { if (const auto err = status_to_err(st); err != error::OK) {
ESP_LOGE(TAG, "failed to verify status 0x%02x at byte %u", st, i); ESP_LOGE(TAG, "bad status 0x%02x at byte %u", st, i);
return err; return err;
} }
i += 1; i += 1;