Skip to content

Add idfxx_lora and idfxx_sx126x components for LoRa radio#56

Open
cleishm wants to merge 2 commits into
mainfrom
lora/add-components
Open

Add idfxx_lora and idfxx_sx126x components for LoRa radio#56
cleishm wants to merge 2 commits into
mainfrom
lora/add-components

Conversation

@cleishm

@cleishm cleishm commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

Adds LoRa radio support as two new components:

idfxx_lora — chip-agnostic LoRa radio abstraction:

  • Abstract lora::radio base class using the non-virtual-interface pattern: public non-virtual try_*/throwing method pairs with protected do_* hooks that drivers override privately. Chip-agnostic validation (payload length, positive duty-cycle periods) lives in the base.
  • Three data-path styles: blocking calls (transmit/receive/scan_channel, composed in the base over the async hooks), future-based one-shot operations (start_transmit, single-shot start_receive into a caller buffer, and start_channel_scan return idfxx::future and need no event loop), and event streams for continuous/duty-cycled receive, with typed events (tx_done, rx_done, crc_error, cad_done, preamble_detected) posted on an idfxx::event_loop.
  • Semantic modulation/packet types (spreading factor, bandwidth, coding rate, ramp time) that drivers map to chip register encodings.
  • constexpr helpers that need no hardware: time_on_air() implementing the Semtech air-time equation, and rx_duty_cycle_for() computing listen/sleep windows for duty-cycled receive that cannot miss a packet.

idfxx_sx126x — driver for the Semtech SX126x family (SX1261/SX1262/SX1268) over idfxx_spi:

  • Per-variant PA configuration with full output-power range validation, including the SX1261's +15 dBm case (high-duty-cycle PA row with a +14 SetTxParams byte, per DS table 13-21).
  • Datasheet errata workarounds: BW500 TX modulation quality (§15.1), antenna-mismatch TX clamp (§15.2), boosted-RX gain refresh across duty-cycle sleep windows; software-managed timeouts avoid the chip's RTC timeout errata.
  • Optional TCXO via DIO3 (with full recalibration), DIO2-as-RF-switch or external rxen/txen switch GPIOs, LDO/DC-DC regulator selection, and warm/cold sleep and RC/XOSC standby refinements as typed-enum overloads of the base interface.
  • DIO1 ISR feeding a worker task that drains chip IRQs, completes per-operation futures, and posts events. Each async operation completes through its own heap-allocated latch, so outstanding futures stay valid across cancellation (standby/sleep) and driver teardown.
  • Image calibration per frequency band, a low-level opcode/register escape hatch, and four standalone examples (transmit_beacon, receive_log, ping_pong, duty_cycle_listener).

Both components ship Unity tests with compile-time verification of register encodings, PA/power tables, and air-time and duty-cycle window calculations against datasheet reference values, and are listed in the top-level README component table.

idfxx_core 1.1.1 — fixes the flags<E> bitwise operators (|, &, ^, -, ~), which failed to compile for enums with an underlying type smaller than int: integer promotion made the braced construction of the result a narrowing error. The SX126x driver's 16-bit irq_flag bitfield is the first such use. New static_asserts in the flags tests cover each operator with a uint16_t-based enum.

cleishm added 2 commits June 11, 2026 17:03
The flags<E> bitwise operators (|, &, ^, -, ~) constructed their result
with braced initialization from an expression whose operands undergo
integer promotion. For enums with an underlying type smaller than int
(e.g. uint16_t), the promoted int result made the braced init a
narrowing error, so combining such flags failed to compile. Cast the
result back to the underlying type before construction.

Adds a uint16_t-based enum to the flags tests with static_asserts
covering each operator, and bumps idfxx_core to 1.1.1.
idfxx_lora provides a chip-agnostic LoRa radio abstraction:

- An abstract lora::radio base class using the non-virtual-interface
  pattern: public non-virtual try_*/throwing method pairs with
  protected do_* hooks that drivers override privately. Chip-agnostic
  validation (payload length, positive duty-cycle periods) lives in
  the base.
- Three data-path styles: blocking calls (transmit/receive/
  scan_channel, composed in the base over the async hooks),
  future-based one-shot operations (start_transmit, single-shot
  start_receive into a caller buffer, and start_channel_scan return
  idfxx::future and need no event loop), and event streams for
  continuous/duty-cycled receive, with typed events (tx_done, rx_done,
  crc_error, cad_done, preamble_detected) posted on an
  idfxx::event_loop.
- Semantic modulation/packet types (spreading factor, bandwidth,
  coding rate, ramp time) that drivers map to chip register encodings.
- constexpr helpers that need no hardware: time_on_air() implementing
  the Semtech air-time equation, and rx_duty_cycle_for() computing
  listen/sleep windows for duty-cycled receive that cannot miss a
  packet.

idfxx_sx126x implements the interface for the Semtech SX126x family
(SX1261/SX1262/SX1268) over idfxx_spi:

- Per-variant PA configuration with full output-power range validation,
  including the SX1261's +15 dBm case (high-duty-cycle PA row with a
  +14 SetTxParams byte, per DS table 13-21).
- Datasheet errata workarounds: BW500 TX modulation quality (15.1),
  antenna-mismatch TX clamp (15.2), boosted-RX gain refresh across
  duty-cycle sleep windows.
- Optional TCXO via DIO3 (with full recalibration), DIO2-as-RF-switch
  or external rxen/txen switch GPIOs, LDO/DC-DC regulator selection,
  and warm/cold sleep and RC/XOSC standby refinements as typed-enum
  overloads of the base interface.
- A DIO1 ISR feeding a worker task that drains chip IRQs, completes
  per-operation futures, and posts events; software-managed timeouts
  avoid the chip's RTC timeout errata. Each async operation completes
  through its own heap-allocated latch, so outstanding futures stay
  valid across cancellation (standby/sleep) and driver teardown.
- Image calibration per frequency band, a low-level opcode/register
  escape hatch, and four standalone examples (transmit_beacon,
  receive_log, ping_pong, duty_cycle_listener).

Both components ship Unity tests with compile-time verification of
register encodings, PA/power tables, and air-time and duty-cycle
window calculations against datasheet reference values.
@cleishm cleishm force-pushed the lora/add-components branch from 8561595 to 43fcfca Compare June 12, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant