Compare commits

...

3 Commits

Author SHA1 Message Date
crosstyan e6f96ea0e3 fix(llcc68): cache detected chip type
Store the detected chip type after the first successful version-register read so repeated radio operations do not keep querying the chip identity.

This preserves Unknown as uncached so transient read failures or unsupported responses can still be retried on a later call.
2026-06-16 19:36:45 +08:00
crosstyan b125dd33b9 style(llcc68): apply shared clang-format
Add a .clang-format file to the LLCC68 submodule so it can be formatted consistently when edited or checked out independently from the parent repository.

Reformat the tracked C and C++ driver sources with the shared style configuration.
2026-06-16 19:36:45 +08:00
crosstyan d382bdfd1e fix(llcc68): apply full radio profile before tx and rx
Reapply packet type, sync word, RF frequency, modulation, packet, CRC, and whitening settings on async TX/RX entry points.

This lets callers switch between preconfigured profiles immediately before a send or listen operation instead of relying on modem-init state.
2026-06-16 19:35:59 +08:00
5 changed files with 2172 additions and 2075 deletions
+25
View File
@@ -0,0 +1,25 @@
# C++ specific configuration (akin to Google's C++ style)
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#adding-additional-style-options
---
Language: Cpp
BasedOnStyle: LLVM
UseTab: ForContinuationAndIndentation
IndentWidth: 4
TabWidth: 4
AccessModifierOffset: -4
ColumnLimit: 0
NamespaceIndentation: Inner
FixNamespaceComments: false
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AllowShortBlocksOnASingleLine: Empty
IndentCaseLabels: false
SortIncludes: Never
AlignConsecutiveMacros: AcrossEmptyLines
AlignConsecutiveAssignments: Consecutive
BreakStringLiterals: true
LineEnding: LF
MaxEmptyLinesToKeep: 2
BreakBeforeBraces: Attach
InsertBraces: true
BreakAfterAttributes: Always
+1
View File
@@ -303,6 +303,7 @@ struct LLCC68 {
/** properties */
const struct device *dev;
std::optional<ChipType> cached_chip_type{};
};
} // namespace app::driver::llcc68
+2 -1
View File
@@ -1143,7 +1143,8 @@ namespace llcc68 = app::driver::llcc68;
}
namespace std {
template <> struct is_error_code_enum<app::driver::llcc68::Errc> : true_type {};
template <>
struct is_error_code_enum<app::driver::llcc68::Errc> : true_type {};
} // namespace std
#endif /* ECC594CF_EDF0_42B5_8518_0EB3B3583727 */
+84 -14
View File
@@ -186,6 +186,7 @@ expected<unit, error_code> LLCC68::set_rf_switch_state(RfSwitchState state) {
};
switch (config().rf_switch_mode) {
case LLCC68_RF_SWITCH_DIO2_SINGLE:
case LLCC68_RF_SWITCH_NONE:
return unit{};
case LLCC68_RF_SWITCH_GPIO_COMPLEMENTARY: {
@@ -205,10 +206,6 @@ expected<unit, error_code> LLCC68::set_rf_switch_state(RfSwitchState state) {
APP_RADIO_RETURN_ERR(r);
return set_gpio(*rx, state == RfSwitchState::RX ? 1 : 0);
}
case LLCC68_RF_SWITCH_DIO2_SINGLE:
if (auto rx = rx_enable_gpio()) {
return set_gpio(*rx, 1);
}
return unit{};
default:
return ue(-EINVAL);
@@ -677,6 +674,10 @@ expected<unit, error_code> LLCC68::set_standby() {
}
expected<ChipType, error_code> LLCC68::hal_get_chip_type() {
if (cached_chip_type.has_value()) {
return *cached_chip_type;
}
constexpr auto SX1262_CHIP_TYPE = "SX1262";
constexpr auto LLCC68_CHIP_TYPE = "LLCC68";
constexpr auto SX1261_CHIP_TYPE = "SX1261";
@@ -687,23 +688,31 @@ expected<ChipType, error_code> LLCC68::hal_get_chip_type() {
auto r = read_register(RADIOLIB_SX126X_REG_VERSION_STRING, version_buf);
APP_RADIO_RETURN_ERR(r);
LOG_HEXDUMP_DBG(version, sizeof(version), "version dump");
ChipType chip_type = ChipType::Unknown;
if (strncmp(version, LLCC68_CHIP_TYPE, 6) == 0) {
return ChipType::LLCC68;
chip_type = ChipType::LLCC68;
} else if (strncmp(version, SX1261_CHIP_TYPE, 6) == 0) {
chip_type = ChipType::SX1261;
} else if (strncmp(version, SX1262_CHIP_TYPE, 6) == 0) {
chip_type = ChipType::SX1262;
}
if (strncmp(version, SX1261_CHIP_TYPE, 6) == 0) {
return ChipType::SX1261;
if (chip_type != ChipType::Unknown) {
cached_chip_type = chip_type;
}
if (strncmp(version, SX1262_CHIP_TYPE, 6) == 0) {
return ChipType::SX1262;
}
return ChipType::Unknown;
return chip_type;
}
expected<unit, error_code> LLCC68::set_dio_irq_params(irq_params_t params) {
const uint8_t data[8] = {
params.irqMask.msb(), params.irqMask.lsb(), params.dio1Mask.msb(),
params.dio1Mask.lsb(), params.dio2Mask.msb(), params.dio2Mask.lsb(),
params.dio3Mask.msb(), params.dio3Mask.lsb(),
params.irqMask.msb(),
params.irqMask.lsb(),
params.dio1Mask.msb(),
params.dio1Mask.lsb(),
params.dio2Mask.msb(),
params.dio2Mask.lsb(),
params.dio3Mask.msb(),
params.dio3Mask.lsb(),
};
return write_stream(RADIOLIB_SX126X_CMD_SET_DIO_IRQ_PARAMS, data);
}
@@ -1369,6 +1378,11 @@ LLCC68::hal_async_flush(lora_parameters_t params) {
return ue(Errc::InvalidState);
}
APP_RADIO_RETURN_ERR_CTX(set_standby(), "tx::standby");
APP_RADIO_RETURN_ERR_CTX(set_packet_type_lora(), "tx::set_packet_type");
APP_RADIO_RETURN_ERR_CTX(set_lora_sync_word(params.sync_word),
"tx::set_lora_sync_word");
APP_RADIO_RETURN_ERR_CTX(set_rf_frequency(params.frequency_mhz),
"tx::set_rf_frequency");
APP_RADIO_RETURN_ERR_CTX(
set_modulation_params(params.mod_params.sf, params.mod_params.bw,
params.mod_params.cr,
@@ -1430,10 +1444,35 @@ LLCC68::hal_gfsk_async_flush(gfsk_parameters_t params) {
if (data().tx_xfer_size == 0 || data().tx_xfer_size > MAX_BUFFER_PAYLOAD) {
return ue(-EINVAL);
}
if (params.sync_word_length > params.sync_word.size() ||
params.packet_params.sync_length_bits > params.sync_word.size() * 8) {
return ue(-EINVAL);
}
APP_RADIO_RETURN_ERR_CTX(set_standby(), "gfsk_tx::standby");
APP_RADIO_RETURN_ERR_CTX(set_packet_type_gfsk(),
"gfsk_tx::set_packet_type");
APP_RADIO_RETURN_ERR_CTX(set_rf_frequency(params.frequency_mhz),
"gfsk_tx::set_rf_frequency");
APP_RADIO_RETURN_ERR_CTX(set_gfsk_modulation_params(params.mod_params),
"gfsk_tx::set_modulation_params");
APP_RADIO_RETURN_ERR_CTX(
set_gfsk_sync_word(std::span<const uint8_t>{params.sync_word.data(),
params.sync_word_length}),
"gfsk_tx::set_sync_word");
APP_RADIO_RETURN_ERR_CTX(set_gfsk_crc_seed(params.crc_seed),
"gfsk_tx::set_crc_seed");
APP_RADIO_RETURN_ERR_CTX(set_gfsk_crc_polynomial(params.crc_polynomial),
"gfsk_tx::set_crc_polynomial");
APP_RADIO_RETURN_ERR_CTX(set_gfsk_whitening_seed(params.whitening_seed),
"gfsk_tx::set_whitening_seed");
if (params.packet_params.address_filtering !=
GfskAddressFiltering::Disabled) {
APP_RADIO_RETURN_ERR_CTX(
set_gfsk_address_filtering(params.node_address.value_or(0),
params.broadcast_address.value_or(0)),
"gfsk_tx::set_address_filtering");
}
auto packet_params = params.packet_params;
packet_params.payload_length = static_cast<uint8_t>(data().tx_xfer_size);
APP_RADIO_RETURN_ERR_CTX(set_gfsk_packet_params(packet_params),
@@ -1477,6 +1516,11 @@ LLCC68::hal_gfsk_async_transmit(std::span<const uint8_t> data,
expected<unit, error_code> LLCC68::hal_async_rx(lora_parameters_t params) {
APP_RADIO_RETURN_ERR_CTX(set_standby(), "rx::standby");
APP_RADIO_RETURN_ERR_CTX(set_packet_type_lora(), "rx::set_packet_type");
APP_RADIO_RETURN_ERR_CTX(set_lora_sync_word(params.sync_word),
"rx::set_lora_sync_word");
APP_RADIO_RETURN_ERR_CTX(set_rf_frequency(params.frequency_mhz),
"rx::set_rf_frequency");
APP_RADIO_RETURN_ERR_CTX(set_buffer_base_address(),
"rx::set_buffer_base_address");
@@ -1511,11 +1555,37 @@ expected<unit, error_code> LLCC68::hal_async_rx(lora_parameters_t params) {
}
expected<unit, error_code> LLCC68::hal_gfsk_async_rx(gfsk_parameters_t params) {
if (params.sync_word_length > params.sync_word.size() ||
params.packet_params.sync_length_bits > params.sync_word.size() * 8) {
return ue(-EINVAL);
}
APP_RADIO_RETURN_ERR_CTX(set_standby(), "gfsk_rx::standby");
APP_RADIO_RETURN_ERR_CTX(set_packet_type_gfsk(),
"gfsk_rx::set_packet_type");
APP_RADIO_RETURN_ERR_CTX(set_rf_frequency(params.frequency_mhz),
"gfsk_rx::set_rf_frequency");
APP_RADIO_RETURN_ERR_CTX(set_buffer_base_address(),
"gfsk_rx::set_buffer_base_address");
APP_RADIO_RETURN_ERR_CTX(set_gfsk_modulation_params(params.mod_params),
"gfsk_rx::set_modulation_params");
APP_RADIO_RETURN_ERR_CTX(
set_gfsk_sync_word(std::span<const uint8_t>{params.sync_word.data(),
params.sync_word_length}),
"gfsk_rx::set_sync_word");
APP_RADIO_RETURN_ERR_CTX(set_gfsk_crc_seed(params.crc_seed),
"gfsk_rx::set_crc_seed");
APP_RADIO_RETURN_ERR_CTX(set_gfsk_crc_polynomial(params.crc_polynomial),
"gfsk_rx::set_crc_polynomial");
APP_RADIO_RETURN_ERR_CTX(set_gfsk_whitening_seed(params.whitening_seed),
"gfsk_rx::set_whitening_seed");
if (params.packet_params.address_filtering !=
GfskAddressFiltering::Disabled) {
APP_RADIO_RETURN_ERR_CTX(
set_gfsk_address_filtering(params.node_address.value_or(0),
params.broadcast_address.value_or(0)),
"gfsk_rx::set_address_filtering");
}
APP_RADIO_RETURN_ERR_CTX(set_gfsk_packet_params(params.packet_params),
"gfsk_rx::set_packet_params");