|
Home IO Control
ESPHome add-on for IO-Homecontrol devices
|
Abstract radio driver for IO-Homecontrol. More...
#include <radio_interface.h>
Public Member Functions | |
| RadioDriver (InternalGPIOPin *rst_pin=nullptr) | |
| virtual | ~RadioDriver ()=default |
| virtual bool | init ()=0 |
| Initialize the radio hardware. Returns true on success. | |
| virtual bool | send_packet (const uint8_t *data, uint8_t len, const RadioTxConfig &tx_config)=0 |
| Send a packet using the specified carrier frequency and preamble settings. | |
| virtual bool | wait_for_packet (RadioRxPacket &packet, uint32_t timeout_ms)=0 |
| Wait (blocking) for a packet with timeout. | |
| virtual bool | check_for_packet (RadioRxPacket &packet)=0 |
| Non-blocking check for a received packet. | |
| virtual int16_t | read_rssi ()=0 |
| Read instantaneous RSSI (in dBm) while in RX mode. | |
| virtual bool | is_sync_detected ()=0 |
| Check if sync word has been detected (while in RX). | |
| virtual bool | is_preamble_detected ()=0 |
| Check if preamble has been detected (while in RX). | |
| virtual uint16_t | response_preamble () const |
| Return the preamble length for response/continuation frames. | |
| virtual void | apply_tuning (const TuningConfig &tuning) |
| Apply runtime tuning parameters to the driver. | |
| virtual uint16_t | hop_dwell_ms (const TuningConfig &tuning) const =0 |
| Per-channel dwell for a rotating listen that does not name its own dwell. | |
| virtual bool | has_fast_tx_rx_turnaround () const =0 |
| Whether the chip re-enters RX fast enough after a TX to catch an immediate reply through the standard exchange wait. | |
| virtual void | change_frequency (uint32_t freq_hz)=0 |
| Change the carrier frequency using fast hop (no standby transition needed). | |
| virtual void | set_mode_rx ()=0 |
| Switch to continuous receive mode. | |
| virtual void | set_mode_standby ()=0 |
| Switch to standby mode. | |
| virtual bool | is_failed () const =0 |
| Returns true if the radio failed to initialize or encountered a fatal error. | |
| virtual const char * | chip_name () const =0 |
| Get a human‑readable chip name. | |
| virtual void | dump_debug () |
| Optional chip-specific diagnostics emitted from dump_config. | |
| 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 | 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. | |
Protected Attributes | |
| 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} |
Abstract radio driver for IO-Homecontrol.
Encapsulates all chip-specific operations: initialization, packet TX/RX, frequency control, and mode switching. Concrete implementations (RadioSX1276, RadioSX1262, RadioLR1121) handle the register-level details for each chip.
Definition at line 112 of file radio_interface.h.
|
inlineexplicit |
Definition at line 114 of file radio_interface.h.
|
virtualdefault |
|
inlinevirtual |
Apply runtime tuning parameters to the driver.
Each driver consumes only the fields it understands; the default is a no-op for chips with no runtime-tunable radio parameters. This keeps the hub free of chip-specific tuning knowledge — it hands over the whole config and lets the driver pick what it needs.
| tuning | Current tuning configuration. |
Reimplemented in esphome::home_io_control::RadioLR1121, esphome::home_io_control::RadioSX1262, and esphome::home_io_control::RadioSX1276.
Definition at line 175 of file radio_interface.h.
|
pure virtual |
Change the carrier frequency using fast hop (no standby transition needed).
Implemented in esphome::home_io_control::RadioSX1276, and esphome::home_io_control::SoftPhyDriverBase.
|
pure virtual |
Non-blocking check for a received packet.
Called from loop(). Returns true if a packet was read into packet. Contract:
Implemented in esphome::home_io_control::RadioSX1276, and esphome::home_io_control::SoftPhyDriverBase.
|
nodiscardpure virtual |
Get a human‑readable chip name.
Implemented in esphome::home_io_control::RadioLR1121, esphome::home_io_control::RadioSX1262, and esphome::home_io_control::RadioSX1276.
|
inline |
Definition at line 274 of file radio_interface.h.
|
inline |
Reset the diagnostic capture buffer.
Public because ExchangeEngine blanks it at the start of every exchange: the radio only clears this buffer when it actually begins a listen, so without an explicit reset a fully-silent exchange's failure report would inherit the previous exchange's capture (frame length, RSSI, IRQ bits) and claim "we heard something" when nothing was on air.
Definition at line 237 of file radio_interface.h.
|
inlineprotected |
Drop the holdoff: the reception ended, was delivered, or was torn down deliberately.
Definition at line 316 of file radio_interface.h.
|
inlinevirtual |
Optional chip-specific diagnostics emitted from dump_config.
Reimplemented in esphome::home_io_control::RadioLR1121, esphome::home_io_control::RadioSX1262, and esphome::home_io_control::RadioSX1276.
Definition at line 222 of file radio_interface.h.
|
inlinenodiscard |
Get the current RF frequency.
Definition at line 226 of file radio_interface.h.
|
inlinenodiscard |
Get the most recent radio capture info.
Definition at line 229 of file radio_interface.h.
|
nodiscardpure virtual |
Whether the chip re-enters RX fast enough after a TX to catch an immediate reply through the standard exchange wait.
Some chips need a standby/settle cycle between TX and RX, so a device's immediate response (e.g. the pairing key-confirm 0x33) can arrive while the receiver is still settling and be lost. Callers choose between the standard exchange wait and a dedicated wait-and-retrigger strategy based on this. There is no safe generic default — each driver must declare it.
Implemented in esphome::home_io_control::RadioLR1121, esphome::home_io_control::RadioSX1262, and esphome::home_io_control::RadioSX1276.
|
nodiscardpure virtual |
Per-channel dwell for a rotating listen that does not name its own dwell.
Every ListenPolicy::ROTATE_ALL_CHANNELS or ListenPolicy::ROTATE_SKIPPING_REQUEST listen falls back to this when ListenSpec::dwell_ms is left at 0 — which is every call site today: pairing discovery and the broadcast roll-call both rotate, and neither has a measured reason to dwell differently from the other. The right dwell is inherently chip-specific — it depends on how fast the chip can retune (fast hop vs. a standby→retune→RX cycle) — so there is no generic default: each driver must return its value, normally from its user-facing tuning field. This answers a chip question ("how long must this radio sit on a channel before it can hear anything at all"), never a protocol one — a loop with a measured reason to dwell differently sets ListenSpec::dwell_ms instead of asking for a second driver virtual.
| tuning | Current tuning configuration. |
Implemented in esphome::home_io_control::RadioLR1121, esphome::home_io_control::RadioSX1262, and esphome::home_io_control::RadioSX1276.
|
pure virtual |
Initialize the radio hardware. Returns true on success.
Implemented in esphome::home_io_control::RadioLR1121, esphome::home_io_control::RadioSX1262, and esphome::home_io_control::RadioSX1276.
|
inlinenodiscard |
Set by the ISR when DIO fires.
Using access helpers instead of touching the flag directly keeps the ISR/main-loop handoff explicit and lets ESP32 builds use atomic storage.
Definition at line 266 of file radio_interface.h.
|
nodiscardpure virtual |
Returns true if the radio failed to initialize or encountered a fatal error.
Implemented in esphome::home_io_control::RadioSX1276, and esphome::home_io_control::SoftPhyDriverBase.
|
pure virtual |
Check if preamble has been detected (while in RX).
Used together with sync detection to gate frequency hopping.
Implemented in esphome::home_io_control::RadioSX1276, and esphome::home_io_control::SoftPhyDriverBase.
|
pure virtual |
Check if sync word has been detected (while in RX).
Used to gate frequency hopping — prevents hopping away mid-frame.
Implemented in esphome::home_io_control::RadioSX1276, and esphome::home_io_control::SoftPhyDriverBase.
|
inline |
Definition at line 284 of file radio_interface.h.
|
inlineprotected |
Record that a frame is arriving right now.
Re-arming refreshes the deadline, so a driver may call this on every poll that still sees the reception.
Definition at line 311 of file radio_interface.h.
|
inlineprotected |
Populate the common fields of RadioCaptureInfo from raw telemetry.
Chip‑specific fields (rx_done, crc_error, irq_flags*, irq_status, packet_status, etc.) must be set by the derived driver after calling this helper.
| blocking_wait | if this was a blocking receive. |
| freq_hz | RF frequency of the capture. |
| rssi_dbm | Received signal strength. |
| raw | Pointer to raw bytes (may be nullptr). |
| raw_len | Length of raw buffer. |
| frame | Pointer to parsed frame bytes (may be nullptr). |
| frame_len | Length of parsed frame. |
Definition at line 332 of file radio_interface.h.
|
inlineprotected |
Common preamble for blocking receive: clear diagnostics and output packet.
| packet | Output packet buffer to zero and prepare. |
Definition at line 296 of file radio_interface.h.
|
inlineprotected |
Common preamble for non‑blocking receive: clear diagnostics, output packet, and DIO latch.
| packet | Output packet buffer to zero and prepare. |
Definition at line 303 of file radio_interface.h.
|
pure virtual |
Read instantaneous RSSI (in dBm) while in RX mode.
Used for listen-before-talk (LBT) carrier sense before transmitting.
Implemented in esphome::home_io_control::RadioSX1276, and esphome::home_io_control::SoftPhyDriverBase.
|
inlinenodiscardvirtual |
True while a frame is arriving on the current channel and retuning would destroy it.
Consulted by ExchangeEngine::maybe_hop() — the idle-path hop — which is purely time-gated and otherwise fires on essentially every loop() pass (issue #81). Not consulted by hop_frequency() itself: the blocking listen() loop does its own, differently-shaped gating through preamble_or_sync_incoming(), and a caller that asked for a hop explicitly must get one.
The default implementation is the recorded-state one: a driver reports a reception by calling note_reception_in_progress_() from wherever it can actually observe one, and the holdoff expires by itself after RX_HOP_HOLDOFF_US. That default is correct for any driver whose RX path passes through check_for_packet() while the frame is still arriving, and it is what both software-PHY drivers use. A driver that cannot observe a reception from check_for_packet() overrides this and reads the chip at hop time instead — see RadioSX1276.
Non-const because it expires its own latch, and because an override may do SPI.
Reimplemented in esphome::home_io_control::RadioSX1276.
Definition at line 254 of file radio_interface.h.
|
protected |
Shared hardware reset sequence for chips with an active-low RST pin.
Drives RST pin low → 10 ms → high → 10 ms. Called from derived driver init().
Definition at line 18 of file radio_interface.cpp.
|
inlinenodiscardvirtual |
Return the preamble length for response/continuation frames.
Callers use this instead of hardcoding SHORT_PREAMBLE for any frame sent as an immediate reply within an exchange (challenge responses, key transfers, and any future non-START continuation frames — i.e. tight RX→TX turnaround).
The default is the protocol's standard SHORT_PREAMBLE. Drivers whose TX waveform gives the peer device less synchronization margin override this with a longer preamble (see the concrete drivers for the chip-specific rationale).
Reimplemented in esphome::home_io_control::RadioSX1276, and esphome::home_io_control::SoftPhyDriverBase.
Definition at line 166 of file radio_interface.h.
|
pure virtual |
Send a packet using the specified carrier frequency and preamble settings.
The driver is responsible for appending the protocol CRC on the air (in hardware or software, depending on the chip).
Implemented in esphome::home_io_control::RadioSX1276, and esphome::home_io_control::SoftPhyDriverBase.
|
pure virtual |
Switch to continuous receive mode.
Implemented in esphome::home_io_control::RadioLR1121, esphome::home_io_control::RadioSX1262, and esphome::home_io_control::RadioSX1276.
|
pure virtual |
Switch to standby mode.
Implemented in esphome::home_io_control::RadioLR1121, esphome::home_io_control::RadioSX1262, and esphome::home_io_control::RadioSX1276.
|
pure virtual |
Wait (blocking) for a packet with timeout.
Returns true if a packet was received. Contract:
Implemented in esphome::home_io_control::RadioSX1276, and esphome::home_io_control::SoftPhyDriverBase.
|
protected |
Definition at line 350 of file radio_interface.h.
|
protected |
Definition at line 360 of file radio_interface.h.
|
protected |
Definition at line 351 of file radio_interface.h.
|
protected |
Definition at line 352 of file radio_interface.h.
|
protected |
Idle-hop holdoff latch — see reception_in_progress().
Definition at line 354 of file radio_interface.h.
|
protected |
micros() timestamp the holdoff was last (re-)armed at.
Definition at line 355 of file radio_interface.h.