|
Home IO Control
ESPHome add-on for IO-Homecontrol devices
|
LR1121 radio driver for IO-Homecontrol. More...
Go to the source code of this file.
Classes | |
| class | esphome::home_io_control::RadioLR1121 |
| LR1121 implementation of RadioDriver. More... | |
Namespaces | |
| namespace | esphome |
| namespace | esphome::home_io_control |
Functions | |
| constexpr bool | esphome::home_io_control::lr1121_firmware_is_outdated (uint8_t fw_major, uint8_t fw_minor) |
| Pure comparison against the known-latest constants above — no I/O, host-testable. | |
Variables | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_GET_STATUS = 0x0100 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_GET_VERSION = 0x0101 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_GET_ERRORS = 0x010D |
| cross-checked (2-byte response) | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_CLEAR_ERRORS |
| hardware-verified (called on every init/RX cycle, never rejected — see log_command_status_()) | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_WRITE_BUFFER = 0x0109 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_READ_BUFFER = 0x010A |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_WRITE_REG_MEM_MASK32 |
| cross-checked (Semtech SWDR001 lr11xx_radio.c / RadioLib LR11x0_commands.h) | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_CALIBRATE = 0x010F |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_CALIBRATE_IMAGE = 0x0111 |
| cross-checked (RadioLib calibrateImageRejection) | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_DIO_AS_RF_SWITCH = 0x0112 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_DIO_IRQ_PARAMS = 0x0113 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_CLEAR_IRQ = 0x0114 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_TCXO_MODE = 0x0117 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_STANDBY = 0x011C |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_GET_RX_BUFFER_STATUS = 0x0203 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_GET_PKT_STATUS |
| cross-checked (Semtech SWDR001 lr11xx_radio.c :: lr11xx_radio_get_gfsk_pkt_status — 0 request params, 4-byte GFSK response: [rssi_sync, rssi_avg, rx_len, status_flags], rssi_sync/avg both decode via -(raw>>1) dBm, same formula as LR1121_CMD_GET_RSSI_INST) | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_GET_RSSI_INST = 0x0205 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_GFSK_SYNC_WORD = 0x0206 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_RX = 0x0209 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_TX = 0x020A |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_RF_FREQUENCY = 0x020B |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_PACKET_TYPE = 0x020E |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_MODULATION_PARAMS = 0x020F |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_PACKET_PARAMS = 0x0210 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_TX_PARAMS = 0x0211 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_RX_TX_FALLBACK_MODE = 0x0213 |
| cross-checked | |
| static constexpr uint16_t | esphome::home_io_control::LR1121_CMD_SET_PA_CONFIG = 0x0215 |
| cross-checked | |
| static constexpr uint32_t | esphome::home_io_control::LR1121_IRQ_TX_DONE = 1UL << 2 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_IRQ_RX_DONE = 1UL << 3 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_IRQ_PREAMBLE_DETECTED = 1UL << 4 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_IRQ_SYNC_WORD_VALID = 1UL << 5 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_IRQ_CRC_ERR = 1UL << 7 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_IRQ_TIMEOUT = 1UL << 10 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_IRQ_ACTIVITY_MASK |
| IRQ bits that represent a terminal radio event — a frame finished decoding, an outbound frame completed, or the chip gave up on its own. | |
| static constexpr uint32_t | esphome::home_io_control::LR1121_IRQ_DIO_ENABLE_MASK |
| DIO-routed IRQ enable mask: TxDone|RxDone|PreambleDetected|SyncWordValid|Timeout (design implementation §Step 2, item 2 — deliberately excludes CrcErr from the DIO-routed set, unlike SX1262; CrcErr is still visible in the raw status word for capture diagnostics). | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_DEVICE_TYPE = 0x03 |
| cross-checked (design §1.2 "Identity" row) | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_KNOWN_LATEST_FW_MAJOR = 0x01 |
| Newest LR1121 transceiver firmware known at the time this file was last updated, per the version-numbered filenames and CHANGELOG.md at https://github.com/Lora-net/radio_firmware_images/tree/master/lr1121/transceiver — the same two bytes GetVersion reports as fw_major/fw_minor (e.g. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_KNOWN_LATEST_FW_MINOR = 0x04 |
| static constexpr uint8_t | esphome::home_io_control::LR1121_PACKET_TYPE_GFSK = 0x01 |
| cross-checked (design §3.2 step 5) | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_GFSK_CRC_OFF = 0x01 |
| cross-checked (same encoding as SX126x) | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_GFSK_PACKET_FIXED_LENGTH = 0x00 |
| cross-checked (same encoding as SX126x) | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_PREAMBLE_DETECTOR_16_BIT = 0x05 |
| Preamble detector length selector: 16 bits. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_SYNC_WORD_PARAM_24_BITS = 0x18 |
| Sync word length: 24 bits, encoded as a literal bit count — cross-checked, identical encoding to SX1262's SX1262_SYNC_WORD_PARAM_24_BITS. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_CALIBRATE_ALL_BLOCKS = 0x3F |
| Calibrate "all blocks" bitmask. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_FALLBACK_STDBY_XOSC = 0x02 |
| SetRxTxFallbackMode value for STDBY_XOSC. | |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_HIGH_ACP_WORKAROUND_ADDR = 0x00F30054 |
| High-ACP (adjacent channel power) TX-quality erratum: clear bit 30 of this register before every SetRx/SetTx. | |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_HIGH_ACP_WORKAROUND_MASK = 1UL << 30 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_HIGH_ACP_WORKAROUND_VALUE = 0x00000000 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_1_ADDR = 0x00F20344 |
| GFSK modulation workaround register trio, standard (non-0.6/1.2kbps) values for our 38.4kbps config — applied after every modulation-params write, mirroring RadioLib's workaroundGFSK() ("always the first step, even when resetting" per its own comment on the first write). | |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_1_MASK = 0x00000030 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_1_VALUE = 0x00000010 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_2_ADDR = 0x00F20348 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_2_MASK = 0x00000005 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_2_VALUE = 0x00000001 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_3_ADDR = 0x00F20244 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_3_MASK = 0x0001FF03 |
| static constexpr uint32_t | esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_3_VALUE = 0x00000A01 |
| static constexpr uint8_t | esphome::home_io_control::LR1121_IMAGE_CAL_FREQ1 = 0xD7 |
| Banded image calibration for 868.25-869.85MHz +/-4MHz (~860-876MHz), matching RadioLib's setFrequency() margin. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_IMAGE_CAL_FREQ2 = 0xDB |
| static constexpr uint8_t | esphome::home_io_control::LR1121_RFSWITCH_ENABLE_DIO5_DIO6 = 0x03 |
| DIO5 + DIO6 are switch pins. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_RFSWITCH_STANDBY = 0x00 |
| Both low. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_RFSWITCH_RX = 0x01 |
| DIO5 high. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_RFSWITCH_TX = 0x02 |
| DIO6 high (both LP and HP PA). | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_RFSWITCH_TX_HP = 0x02 |
| Same as TX (LP PA only used today). | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_RFSWITCH_TX_HF = 0x00 |
| 2.4GHz path unused; both low. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_RFSWITCH_GNSS = 0x00 |
| Unused; both low. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_RFSWITCH_WIFI = 0x00 |
| Unused; both low. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_TCXO_STARTUP_DELAY_TICKS_MSB = 0x00 |
| LR1121 TCXO voltage on the T3-S3 board — 3.0V, confirmed on real hardware. | |
| static constexpr uint8_t | esphome::home_io_control::LR1121_TCXO_STARTUP_DELAY_TICKS_MID = 0x01 |
| static constexpr uint8_t | esphome::home_io_control::LR1121_TCXO_STARTUP_DELAY_TICKS_LSB = 0x40 |
| 0x140 ticks at 30.52us/tick (32.768kHz RTC) is ~9.8ms, not the ~5ms the SX1262-derived comment used to claim (that chip's tick base differs) — harmless either way (longer startup is safe). | |
| static constexpr int32_t | esphome::home_io_control::LR1121_EXCHANGE_RESPONSE_WAIT_SLICE_MS = 600 |
| LR1121-specific per-channel dwell while waiting for authenticated exchange responses. | |
LR1121 radio driver for IO-Homecontrol.
Implements the RadioDriver interface for the Semtech LR1121 transceiver on the LilyGo T3-S3 board. Like the SX1262, the LR1121 has no hardware equivalent of the SX1276's IoHomeOn framing, so this driver reuses the shared software PHY (radio_soft_phy.h) wholesale: software UART bit-encoding on TX, a UART-decode probe with CRC-CCITT validation on RX, fixed-length GFSK packets, software CRC. This is a re-plumbed RadioSX1262 with a different SPI command set, not a new bring-up from first principles (design doc §1.2). The IRQ-driven RX/TX orchestration this driver shares with RadioSX1262 lives in SoftPhyDriverBase (see radio_soft_phy_driver_base.h).
The chip-level difference from the SX1262 that actually changes the driver's shape is the SPI transport: the LR1121 uses 16-bit opcodes and a two-transaction command/response protocol (write opcode+params, wait BUSY, then a second transaction clocks out a status byte + response), instead of the SX1262's single-transaction opcode+NOP-then-data pattern.
Hardware bring-up (2026-08) confirmed this driver end-to-end against a real Somfy Sunea IO awning motor: authenticated open/close/stop exchanges complete reliably, with correct position/state feedback decoded from the device's real responses. Every constant below is therefore hardware-verified unless its own comment says otherwise.
Definition in file radio_lr1121.h.