|
Home IO Control
ESPHome add-on for IO-Homecontrol devices
|
SX1262 implementation of RadioDriver. More...
#include <radio_sx1262.h>
Public Member Functions | |
| RadioSX1262 (SpiAccess *spi, InternalGPIOPin *rst_pin, InternalGPIOPin *dio1_pin, InternalGPIOPin *busy_pin, uint8_t tx_power, uint8_t tcxo_voltage, InternalGPIOPin *fem_en_pin=nullptr, InternalGPIOPin *vfem_pin=nullptr, InternalGPIOPin *fem_pa_pin=nullptr) | |
| bool | init () override |
| Initialize the radio hardware. Returns true on success. | |
| void | apply_tuning (const TuningConfig &tuning) override |
| Apply SX1262 runtime tuning: RX bandwidth, response preamble, post-TX settle delay. | |
| uint16_t | hop_dwell_ms (const TuningConfig &tuning) const override |
| Per-channel dwell for a rotating listen (SX1262). | |
| bool | has_fast_tx_rx_turnaround () const override |
| TX→RX turnaround capability (SX1262): slow. | |
| void | set_mode_rx () override |
| Switch to continuous receive mode. | |
| void | set_mode_standby () override |
| Switch to standby mode. | |
| const char * | chip_name () const override |
| Get a human‑readable chip name. | |
| void | dump_debug () override |
| Dump SX1262‑specific debug info. | |
| Public Member Functions inherited from esphome::home_io_control::SoftPhyDriverBase | |
| SoftPhyDriverBase (InternalGPIOPin *rst_pin, InternalGPIOPin *busy_pin, uint32_t busy_timeout_ms, uint16_t default_response_preamble, uint16_t default_post_tx_settle_us) | |
| bool | send_packet (const uint8_t *data, uint8_t len, const RadioTxConfig &tx_config) override |
| Send a packet using the specified carrier frequency and preamble settings. | |
| bool | wait_for_packet (RadioRxPacket &packet, uint32_t timeout_ms) override |
| Wait (blocking) for a packet with timeout. | |
| bool | check_for_packet (RadioRxPacket &packet) override |
| Non-blocking check for a received packet. | |
| void | change_frequency (uint32_t freq_hz) override |
| Change the carrier frequency using fast hop (no standby transition needed). | |
| int16_t | read_rssi () override |
| Read instantaneous RSSI (in dBm) while in RX mode. | |
| bool | is_sync_detected () override |
| Check if sync word has been detected (while in RX). | |
| bool | is_preamble_detected () override |
| Check if preamble has been detected (while in RX). | |
| uint16_t | response_preamble () const override |
| Preamble for response/continuation frames — shared storage, see the concrete drivers' constructors/tuning defaults for the chip-specific rationale and value. | |
| bool | is_failed () const override |
| Returns true if the radio failed to initialize or encountered a fatal error. | |
| Public Member Functions inherited from esphome::home_io_control::RadioDriver | |
| RadioDriver (InternalGPIOPin *rst_pin=nullptr) | |
| virtual | ~RadioDriver ()=default |
| uint32_t | get_current_freq () const |
| Get the current RF frequency. | |
| const RadioCaptureInfo & | get_last_capture () const |
| Get the most recent radio capture info. | |
| void | clear_last_capture () |
| Reset the diagnostic capture buffer. | |
| virtual bool | reception_in_progress () |
| True while a frame is arriving on the current channel and retuning would destroy it. | |
| bool | is_dio_fired () const |
| Set by the ISR when DIO fires. | |
| void | clear_dio_fired () |
| void | mark_dio_fired_from_isr () |
Protected Member Functions | |
| void | set_rx_bandwidth_ (SX1262RxBandwidth bandwidth) |
| Apply the RX bandwidth selector and rewrite the modulation parameters. | |
| void | write_opcode_ (uint8_t opcode, const uint8_t *params, uint8_t len) |
| Write an opcode with optional parameter bytes. | |
| void | read_opcode_ (uint8_t opcode, uint8_t *data, uint8_t len) |
| Read response from an opcode. | |
| void | write_register_ (uint16_t addr, const uint8_t *data, uint8_t len) |
| Write to a register (SX1262 uses opcodes for register access). | |
| void | read_register_ (uint16_t addr, uint8_t *data, uint8_t len) |
| Read from a register. | |
| void | write_buffer_ (uint8_t offset, const uint8_t *data, uint8_t len) |
| Write into the SX1262 TX/RX buffer at a given offset. | |
| void | read_buffer_ (uint8_t offset, uint8_t *data, uint8_t len) |
| Read from the SX1262 RX buffer. | |
| void | configure_radio_ () |
| Full radio initialization (called from init()). | |
| void | set_frequency_register (uint32_t freq_hz) override |
| Set RF frequency via the chip's own frequency register/opcode encoding, and update current_freq_. | |
| void | set_packet_params_ (uint16_t preamble_len, uint8_t payload_len, uint8_t packet_type, uint8_t crc_type) |
| Configure packet parameters (preamble, payload length, CRC). | |
| void | write_modulation_params_ () |
| Apply the runtime bandwidth setting to the SX1262 modulation parameters. | |
| void | apply_tx_modulation_workaround_ () |
| Apply the Semtech TX modulation-quality erratum workaround (datasheet §15.1). | |
| void | set_rx_packet_params () override |
| Configure RX-specific packet parameters (preamble detector length, fixed probe length). | |
| void | set_tx_packet_params (uint16_t preamble_len, uint8_t payload_len) override |
| Configure TX packet parameters for one outgoing UART-encoded frame. | |
| void | clear_irq_status (uint32_t irq_mask) override |
| Clear IRQ status bits. | |
| uint16_t | get_device_errors_ () |
| Read device error flags (and clear them). | |
| void | clear_device_errors_ () |
| Clear device error flags. | |
| void | configure_buffer_base () override |
| Hook run as part of reset_rx_state_, before re-entering RX. | |
| int16_t | early_rx_read_offset () const override |
| Data-buffer offset an in-flight reception is being written to, or a negative value when this chip must not be read before RX_DONE. | |
| void | fill_capture_info (bool blocking_wait, uint32_t irq_status, uint8_t rx_offset, uint8_t reported_len, const uint8_t *raw, uint8_t raw_len, const uint8_t *frame, uint8_t frame_len) override |
| Populate the RadioCaptureInfo from chip-specific telemetry (RSSI opcode, packet-status byte, and IRQ-word-width narrowing all differ per chip). | |
| uint32_t | read_irq_status_raw () override |
| Read the raw IRQ status word from the radio. | |
| uint32_t | sync_word_valid_bit () const override |
| uint32_t | rx_done_bit () const override |
| uint32_t | tx_done_bit () const override |
| uint32_t | preamble_detected_bit () const override |
| uint32_t | activity_irq_mask () const override |
| IRQ bits that count as "activity" for the internal poll_until_activity_() helper and check_for_packet. | |
| uint8_t | read_rssi_raw_byte () override |
| Read the single raw RSSI byte (chip-specific opcode); formula is shared, see read_rssi. | |
| void | write_tx_buffer (const uint8_t *data, uint8_t len) override |
| Write the UART-encoded TX payload into the chip's TX buffer. | |
| void | get_rx_buffer_status (uint8_t &reported_len, uint8_t &rx_offset) override |
| Read the chip-reported RX length and buffer offset (raw, before any clamping). | |
| void | read_rx_buffer (uint8_t offset, uint8_t *data, uint8_t len) override |
| Read len bytes from the RX buffer starting at offset. | |
| void | start_tx () override |
| Issue the SetTx opcode with the fixed TX timeout — identical 3-byte payload on both chips, differing only in opcode/transport, so this stays a thin chip-specific wrapper. | |
| void | before_tx_arm () override |
| Hook run immediately before every SetTx. | |
| Protected Member Functions inherited from esphome::home_io_control::SoftPhyDriverBase | |
| void | set_response_preamble_ (uint16_t preamble) |
| Set the preamble length used for response/continuation frames within an exchange. | |
| void | set_post_tx_settle_us_ (uint16_t delay_us) |
| Set the delay between TX completion and re-entering RX. | |
| void | wait_busy_ () |
| Wait until busy_pin_ reads low, feeding the watchdog while polling. | |
| virtual bool | read_rx_packet (RadioRxPacket &packet, bool blocking_wait, uint32_t irq_status) |
| Read a received packet from the buffer and return the raw bytes reported by the chip. | |
| void | reset_rx_state_ (bool force_standby=true) |
| Reset RX state machine and buffer. Optionally force standby first. | |
| void | rearm_rx_after_tx_ () |
| Minimal path back into RX immediately after a transmission — see the definition for why this is deliberately not reset_rx_state_. | |
| virtual uint32_t | idle_rx_completion_budget_ms () const |
| Blocking budget for the idle-path length-driven receive, in milliseconds (issue #81). | |
| virtual void | invalidate_stale_rx_content_after_tx () |
| Hook run from rearm_rx_after_tx_, after a transmission and before re-entering RX. | |
| Protected Member Functions inherited from esphome::home_io_control::RadioDriver | |
| void | prepare_blocking_receive_ (RadioRxPacket &packet) |
| Common preamble for blocking receive: clear diagnostics and output packet. | |
| void | prepare_nonblocking_receive_ (RadioRxPacket &packet) |
| Common preamble for non‑blocking receive: clear diagnostics, output packet, and DIO latch. | |
| void | note_reception_in_progress_ () |
| Record that a frame is arriving right now. | |
| void | clear_reception_in_progress_ () |
| Drop the holdoff: the reception ended, was delivered, or was torn down deliberately. | |
| void | reset_hardware_ () |
| Shared hardware reset sequence for chips with an active-low RST pin. | |
| void | populate_capture_base_ (bool blocking_wait, uint32_t freq_hz, int16_t rssi_dbm, const uint8_t *raw, uint8_t raw_len, const uint8_t *frame, uint8_t frame_len) |
| Populate the common fields of RadioCaptureInfo from raw telemetry. | |
Static Protected Member Functions | |
| static void | gpio_intr (RadioSX1262 *arg) |
| DIO1 ISR — sets dio_fired flag. Runs in interrupt context. | |
| Static Protected Member Functions inherited from esphome::home_io_control::SoftPhyDriverBase | |
| static void | build_gfsk_packet_params (const SoftPhyPacketParams &p, uint8_t out[GFSK_PACKET_PARAMS_LEN]) |
| Fill the nine-byte GFSK SetPacketParams payload shared by both chips. | |
Additional Inherited Members | |
| Protected Attributes inherited from esphome::home_io_control::SoftPhyDriverBase | |
| bool | failed_ {false} |
| Set on a BUSY timeout or a chip-identity check failing; see is_failed. | |
| InternalGPIOPin * | busy_pin_ |
| BUSY line, read directly by both concrete drivers' own dump_debug() in addition to wait_busy_, so this stays protected rather than folding entirely into the private wait-loop state below. | |
| Protected Attributes inherited from esphome::home_io_control::RadioDriver | |
| uint32_t | current_freq_ {FREQ_CH2} |
| RadioCaptureInfo | last_capture_ {} |
| InternalGPIOPin * | rst_pin_ {nullptr} |
| bool | rx_hold_armed_ {false} |
| Idle-hop holdoff latch — see reception_in_progress(). | |
| uint32_t | rx_hold_since_us_ {0} |
| micros() timestamp the holdoff was last (re-)armed at. | |
| volatile bool | dio_fired_ {false} |
| Static Protected Attributes inherited from esphome::home_io_control::SoftPhyDriverBase | |
| static constexpr uint8_t | GFSK_PACKET_PARAMS_LEN = 9 |
| Byte count of the GFSK SetPacketParams payload — identical on both software-PHY chips. | |
SX1262 implementation of RadioDriver.
Manages the SX1262 via opcode‑based SPI using the SpiAccess interface. Configures the chip in FSK mode with software CRC‑CCITT to match the IO‑Homecontrol protocol (the SX1262 lacks the SX1276's IoHomeOn mode). The IRQ-driven RX/TX orchestration is inherited from SoftPhyDriverBase; this class supplies the SPI transport and every SX1262-specific register/opcode encoding underneath it.
Definition at line 123 of file radio_sx1262.h.
|
inline |
|
inlinenodiscardoverrideprotectedvirtual |
IRQ bits that count as "activity" for the internal poll_until_activity_() helper and check_for_packet.
Default is "any bit" — safe only for a driver whose SetDioIrqParams-equivalent mask never includes PreambleDetected in the first place, so a preamble-only reading can never reach this check. Neither current driver qualifies: both SX1262 and LR1121 unmask PreambleDetected (each for its own reason) and override this to exclude it — a preamble-only reading means a frame may still be arriving, and treating it as terminal activity would tear down RX mid-reception.
The base class default ("any bit") stopped being safe the moment configure_radio_() unmasked PreambleDetected — see SX1262_IRQ_ACTIVITY_MASK's doc comment.
Reimplemented from esphome::home_io_control::SoftPhyDriverBase.
Definition at line 275 of file radio_sx1262.h.
|
inlineoverridevirtual |
Apply SX1262 runtime tuning: RX bandwidth, response preamble, post-TX settle delay.
Reimplemented from esphome::home_io_control::RadioDriver.
Definition at line 141 of file radio_sx1262.h.
|
protected |
Apply the Semtech TX modulation-quality erratum workaround (datasheet §15.1).
The datasheet requires it "before any packet transmission", so it hangs off before_tx_arm rather than running once at init — same placement rationale as RadioLR1121's high-ACP workaround.
Definition at line 205 of file radio_sx1262.cpp.
|
inlineoverrideprotectedvirtual |
Hook run immediately before every SetTx.
No-op by default; LR1121 overrides this to apply its high-ACP TX-quality workaround, which Semtech's own reference applies unconditionally before every SetRx/SetTx.
TX modulation-quality erratum (SX1262_REG_TX_MODULATION): the datasheet requires bit 2 be set for every (G)FSK transmission, so it is re-asserted before each SetTx rather than assumed to survive from init.
Reimplemented from esphome::home_io_control::SoftPhyDriverBase.
Definition at line 293 of file radio_sx1262.h.
|
inlinenodiscardoverridevirtual |
Get a human‑readable chip name.
Implements esphome::home_io_control::RadioDriver.
Definition at line 166 of file radio_sx1262.h.
|
protected |
Clear device error flags.
Definition at line 167 of file radio_sx1262.cpp.
|
overrideprotectedvirtual |
Clear IRQ status bits.
| irq_mask | Bitmask of IRQs to clear (each driver narrows to its own IRQ word width). |
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 153 of file radio_sx1262.cpp.
|
overrideprotectedvirtual |
Hook run as part of reset_rx_state_, before re-entering RX.
No-op by default; SX1262 overrides this to (re-)write its buffer base address, which LR1121 doesn't need.
SX1262's buffer base addresses (TX=0x00, RX=0x80) are re-asserted on every RX reset — LR1121 has no equivalent register.
Reimplemented from esphome::home_io_control::SoftPhyDriverBase.
Definition at line 172 of file radio_sx1262.cpp.
|
protected |
Full radio initialization (called from init()).
Definition at line 305 of file radio_sx1262.cpp.
|
overridevirtual |
Dump SX1262‑specific debug info.
Reimplemented from esphome::home_io_control::RadioDriver.
Definition at line 259 of file radio_sx1262.cpp.
|
inlinenodiscardoverrideprotectedvirtual |
Data-buffer offset an in-flight reception is being written to, or a negative value when this chip must not be read before RX_DONE.
Neither chip's RX_DONE marks the end of the frame: with no hardware framing, RX runs in fixed-length mode at SOFT_PHY_RX_PROBE_PACKET_LEN, so RX_DONE arrives a fixed ~10 ms after the sync word no matter how short the frame actually was. That delay lands squarely on the protocol's tightest turnaround — the hub's reply to a device's challenge — so a driver that can read its buffer while reception is still running opts in here and the shared flow finishes on the frame's own air time instead (see try_early_completion_).
Default is -1: wait for RX_DONE exactly as before. SX1262 overrides it with the RX base address it programs in configure_buffer_base(), which is where a single in-flight packet always starts. LR1121 also opts in, at the base of its one shared TX/RX buffer — see RadioLR1121::early_rx_read_offset for why a wrong guess there is safe only in combination with invalidate_stale_rx_content_after_tx.
The SX1262 writes demodulated bytes into its data buffer as they arrive, and a single in-flight packet always starts at the RX base address programmed by configure_buffer_base(), so the shared flow can read the frame out on its own air time rather than waiting the fixed ~10 ms for the 48-byte RX_DONE.
Reimplemented from esphome::home_io_control::SoftPhyDriverBase.
Definition at line 250 of file radio_sx1262.h.
|
overrideprotectedvirtual |
Populate the RadioCaptureInfo from chip-specific telemetry (RSSI opcode, packet-status byte, and IRQ-word-width narrowing all differ per chip).
Note: crc_error is set from the CrcErr IRQ bit — unlike the SX1276, this driver sees and reports frames with a bad CRC.
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 177 of file radio_sx1262.cpp.
|
protected |
Read device error flags (and clear them).
Definition at line 161 of file radio_sx1262.cpp.
|
overrideprotectedvirtual |
Read the chip-reported RX length and buffer offset (raw, before any clamping).
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 198 of file radio_sx1262.cpp.
|
staticprotected |
DIO1 ISR — sets dio_fired flag. Runs in interrupt context.
Definition at line 221 of file radio_sx1262.cpp.
|
inlinenodiscardoverridevirtual |
TX→RX turnaround capability (SX1262): slow.
The TX→standby→RX transition plus the post-TX settle delay is too slow to catch a device's immediate reply through the standard exchange wait; in pairing, the key-confirm (0x33) is missed that way. PairingEngine therefore uses its dedicated key-confirm wait with key-init re-trigger on this driver.
Implements esphome::home_io_control::RadioDriver.
Definition at line 161 of file radio_sx1262.h.
|
inlinenodiscardoverridevirtual |
Per-channel dwell for a rotating listen (SX1262).
See SX1262_DISCOVERY_HOP_SLICE_MS for why a short dwell is correct here despite SX1262's slower per-channel retune than the SX1276's FastHop. Governs discovery and the broadcast roll-call alike (see RadioDriver::hop_dwell_ms). The value comes from the user-facing sx1262_discovery_hop_slice_ms tuning field.
Implements esphome::home_io_control::RadioDriver.
Definition at line 152 of file radio_sx1262.h.
|
overridevirtual |
Initialize the radio hardware. Returns true on success.
Implements esphome::home_io_control::RadioDriver.
Definition at line 225 of file radio_sx1262.cpp.
|
inlinenodiscardoverrideprotectedvirtual |
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 270 of file radio_sx1262.h.
|
protected |
Read from the SX1262 RX buffer.
| offset | Buffer offset. |
| data | Output buffer. |
| len | Number of bytes to read. |
Definition at line 91 of file radio_sx1262.cpp.
|
overrideprotectedvirtual |
Read the raw IRQ status word from the radio.
Virtual to allow test doubles (both concrete drivers' tests override this).
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 52 of file radio_sx1262.cpp.
|
protected |
Read response from an opcode.
| opcode | Opcode that was previously written. |
| data | Output buffer. |
| len | Expected number of bytes to read. |
Definition at line 42 of file radio_sx1262.cpp.
|
protected |
Read from a register.
| addr | 16‑bit register address. |
| data | Output buffer. |
| len | Number of bytes to read. |
Definition at line 69 of file radio_sx1262.cpp.
|
overrideprotectedvirtual |
Read the single raw RSSI byte (chip-specific opcode); formula is shared, see read_rssi.
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 192 of file radio_sx1262.cpp.
|
inlineoverrideprotectedvirtual |
Read len bytes from the RX buffer starting at offset.
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 285 of file radio_sx1262.h.
|
inlinenodiscardoverrideprotectedvirtual |
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 266 of file radio_sx1262.h.
|
overrideprotectedvirtual |
Set RF frequency via the chip's own frequency register/opcode encoding, and update current_freq_.
Called from both change_frequency and the shared send_packet().
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 439 of file radio_sx1262.cpp.
|
overridevirtual |
Switch to continuous receive mode.
Implements esphome::home_io_control::RadioDriver.
Definition at line 432 of file radio_sx1262.cpp.
|
overridevirtual |
Switch to standby mode.
Implements esphome::home_io_control::RadioDriver.
Definition at line 427 of file radio_sx1262.cpp.
|
protected |
Configure packet parameters (preamble, payload length, CRC).
| preamble_len | Preamble length in symbols. |
| payload_len | Expected payload length. |
| packet_type | Fixed for GFSK. |
| crc_type | CRC configuration (off or on). |
Definition at line 104 of file radio_sx1262.cpp.
|
protected |
Apply the RX bandwidth selector and rewrite the modulation parameters.
| bandwidth | Bandwidth selector enum. |
Definition at line 451 of file radio_sx1262.cpp.
|
overrideprotectedvirtual |
Configure RX-specific packet parameters (preamble detector length, fixed probe length).
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 120 of file radio_sx1262.cpp.
|
inlineoverrideprotectedvirtual |
Configure TX packet parameters for one outgoing UART-encoded frame.
| preamble_len | Preamble length in symbols, from the caller's RadioTxConfig. |
| payload_len | UART-encoded payload length in bytes. |
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 229 of file radio_sx1262.h.
|
overrideprotectedvirtual |
Issue the SetTx opcode with the fixed TX timeout — identical 3-byte payload on both chips, differing only in opcode/transport, so this stays a thin chip-specific wrapper.
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 213 of file radio_sx1262.cpp.
|
inlinenodiscardoverrideprotectedvirtual |
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 264 of file radio_sx1262.h.
|
inlinenodiscardoverrideprotectedvirtual |
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 268 of file radio_sx1262.h.
|
protected |
Write into the SX1262 TX/RX buffer at a given offset.
| offset | Buffer offset. |
| data | Payload bytes. |
| len | Payload length. |
Definition at line 81 of file radio_sx1262.cpp.
|
protected |
Apply the runtime bandwidth setting to the SX1262 modulation parameters.
Definition at line 129 of file radio_sx1262.cpp.
|
protected |
Write an opcode with optional parameter bytes.
| opcode | SX1262 opcode. |
| params | Pointer to parameter buffer (may be nullptr). |
| len | Parameter length. |
Definition at line 33 of file radio_sx1262.cpp.
|
protected |
Write to a register (SX1262 uses opcodes for register access).
| addr | 16‑bit register address. |
| data | Pointer to data bytes. |
| len | Number of bytes. |
Definition at line 58 of file radio_sx1262.cpp.
|
inlineoverrideprotectedvirtual |
Write the UART-encoded TX payload into the chip's TX buffer.
Implements esphome::home_io_control::SoftPhyDriverBase.
Definition at line 279 of file radio_sx1262.h.