feat(llcc68): add configurable RF switch modes

Add an explicit rf-switch-mode devicetree property for LLCC68 instances, covering no switch handling, TXEN/RXEN complementary GPIO control, and DIO2 single-pin control for PE4259-style RF switches. Preserve the existing default behavior with an auto Kconfig default that only enables complementary GPIO handling when both TXEN and RXEN GPIOs are present.

Resolve the RF switch mode into llcc68_config at build time and validate incompatible devicetree combinations with BUILD_ASSERT checks. Configure optional RXEN GPIO handling for DIO2 single-pin mode and keep DIO2 RF switch control disabled unless that mode is selected.

Replace the old fire-and-forget TX/RX GPIO helper with a result-returning mode-aware RF switch state helper, and apply it across standby, sleep, CAD, TX, RX, continuous wave, infinite preamble, and modem init paths.

Add SetRxDutyCycle support with explicit raw 24-bit LLCC68 period units, plus helpers and a millisecond wrapper for callers that work in time units. Select the RX RF path before issuing the duty-cycle command so RXEN stays valid for duty-cycle listen windows.
This commit is contained in:
2026-06-01 18:05:31 +08:00
parent 4fb41a3211
commit 1c3626d58b
7 changed files with 250 additions and 25 deletions
+16 -1
View File
@@ -120,7 +120,7 @@ struct LLCC68 {
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);
expected<unit, error_code> set_rf_switch_state(RfSwitchState state);
/** LLCC68 DataSheet Function */
@@ -239,6 +239,21 @@ struct LLCC68 {
expected<unit, error_code> set_tx(uint32_t timeout = TIMEOUT_NONE);
expected<unit, error_code> set_rx(uint32_t timeout = TIMEOUT_INF);
/**
* @brief Start LLCC68 RX duty-cycle/listen mode.
*
* rx_period and sleep_period are raw 24-bit LLCC68 RTC periods, not
* milliseconds. Datasheet section 13.1.7 defines one period as 15.625 us:
* RX duration = rx_period * 15.625 us
* sleep duration = sleep_period * 15.625 us
*
* Use rx_duty_cycle_period_from_ms() or set_rx_duty_cycle_ms() when caller
* inputs are in milliseconds.
*/
expected<unit, error_code> set_rx_duty_cycle(uint32_t rx_period,
uint32_t sleep_period);
expected<unit, error_code> set_rx_duty_cycle_ms(uint32_t rx_period_ms,
uint32_t sleep_period_ms);
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();
+38 -1
View File
@@ -17,6 +17,42 @@ struct LLCC68;
using airtime_t = std::chrono::microseconds;
using error_code = std::error_code;
constexpr uint32_t RX_DUTY_CYCLE_PERIOD_MAX = 0x00FFFFFFU;
constexpr uint32_t RX_DUTY_CYCLE_PERIOD_UNIT_US_NUMERATOR = 125U;
constexpr uint32_t RX_DUTY_CYCLE_PERIOD_UNIT_US_DENOMINATOR = 8U;
/**
* @brief Convert microseconds to a raw SetRxDutyCycle period.
*
* LLCC68 datasheet section 13.1.7 defines rxPeriod and sleepPeriod as raw
* 24-bit RTC periods, not milliseconds. One raw period is 15.625 us.
*/
constexpr std::optional<uint32_t> rx_duty_cycle_period_from_us(uint64_t us) {
constexpr uint64_t scale = RX_DUTY_CYCLE_PERIOD_UNIT_US_DENOMINATOR;
constexpr uint64_t divisor = RX_DUTY_CYCLE_PERIOD_UNIT_US_NUMERATOR;
if (us > (UINT64_MAX - (divisor - 1U)) / scale) {
return std::nullopt;
}
const uint64_t raw = ((us * scale) + (divisor - 1U)) / divisor;
if (raw > RX_DUTY_CYCLE_PERIOD_MAX) {
return std::nullopt;
}
return static_cast<uint32_t>(raw);
}
/**
* @brief Convert milliseconds to a raw SetRxDutyCycle period.
*
* Returns std::nullopt if the requested duration does not fit the LLCC68
* 24-bit period field.
*/
constexpr std::optional<uint32_t> rx_duty_cycle_period_from_ms(uint64_t ms) {
if (ms > UINT64_MAX / 1000U) {
return std::nullopt;
}
return rx_duty_cycle_period_from_us(ms * 1000U);
}
enum class Errc : uint8_t {
FailureToExecuteCommand = 1,
CommandTimeout = 2,
@@ -985,7 +1021,8 @@ struct irq_status_bits_t {
// MSB
};
enum class TxRxPinState : uint8_t {
enum class RfSwitchState : uint8_t {
Idle,
TX,
RX,
};
+7
View File
@@ -14,6 +14,12 @@ extern "C" {
typedef void (*llcc68_user_dio1_handler_t)(const struct device *dev, void *user_data);
enum llcc68_rf_switch_mode {
LLCC68_RF_SWITCH_NONE = 0,
LLCC68_RF_SWITCH_GPIO_COMPLEMENTARY = 1,
LLCC68_RF_SWITCH_DIO2_SINGLE = 2,
};
struct llcc68_config {
struct spi_dt_spec spi;
struct gpio_dt_spec reset_gpio;
@@ -21,6 +27,7 @@ struct llcc68_config {
struct gpio_dt_spec dio1_gpio;
struct gpio_dt_spec tx_enable_gpio;
struct gpio_dt_spec rx_enable_gpio;
enum llcc68_rf_switch_mode rf_switch_mode;
};
struct llcc68_data {