Skip to content

Lr1121 tcxo optional tries xtal first, and get all my yamls in a row - #11215

Merged
caveman99 merged 11 commits into
meshtastic:developfrom
NomDeTom:LR1121_TCXO_optional
Aug 5, 2026
Merged

Lr1121 tcxo optional tries xtal first, and get all my yamls in a row#11215
caveman99 merged 11 commits into
meshtastic:developfrom
NomDeTom:LR1121_TCXO_optional

Conversation

@NomDeTom

@NomDeTom NomDeTom commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

On a board where a TCXO may or may not be fitted (DIY / socketed LR1121 modules), configuring a
DIO3 TCXO reference that isn't physically present makes RadioLib hang forever during
LR11x0::config(). The oscillator never locks, BUSY stays asserted, and the calibration wait is
an unbounded while(digitalRead(busy)). It happens in setup() before any watchdog is running,
so the board needs a physical reset. This defeats the existing TCXO_OPTIONAL fallback, which
can only work if begin() returns.

Upstream bug: jgromes/RadioLib#1844.

This PR bounds tries xtal first, then tcxo, which works without any other fix.

More stuff

  • Added WIO LR1121 pins to promicro with build flag
  • Corrected LR1121 yamls for femtofox

Testing

Built for nrf52_promicro_diy_tcxo. Hang reproduced and traced on a bare (no-TCXO) GNiceRF
LR1121 on an nRF52840 Pro Micro; behaviour confirmed independent of the LR1121's own on-die
firmware version (retested after updating 0x01010x0104).

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3
    • LilyGo T-Deck
    • LilyGo T-Beam
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card
    • Other (please specify below)

nRF52840 Pro Micro DIY (nrf52_promicro_diy_tcxo) with LR1121, both bare/no-TCXO and
TCXO-equipped modules.

Summary by CodeRabbit

Summary by CodeRabbit

  • Bug Fixes

    • Improved LoRa radio bring-up for optional XTAL/TCXO setups with clearer attempt logging and safer fallback behavior.
    • Added a BUSY-signal watchdog to prevent potential hangs when BUSY stays asserted.
    • Receive now starts only after successful initialization (including RX gain setup).
    • Enhanced diagnostics for oscillator/DIO3 IRQ usability.
  • Documentation

    • Updated FEMTOFOX LR1121 configuration naming/formatting, module labeling, and RF switch tables for E80 and Wio-LR1121.
    • Refreshed nRF52840 DIY Promicro TCXO docs with correct build-flag guidance and Wio-LR1121 truth table.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

LR11x0 initialization now derives TCXO voltage from board and compile-time settings, probes XTAL before optional TCXO fallback, retries SPI command failures with delay, and starts receive only after successful initialization. LR1121 configurations now support E80 and Wio wiring through build-time module selection.

Changes

LR11x0 initialization

Layer / File(s) Summary
Oscillator selection and diagnostics
src/mesh/LR11x0Interface.cpp
TCXO voltage defaults and precedence, DIO3 IRQ logging, optional-TCXO diagnostics, and the LR1120 power default are updated.
Startup retry flow
src/mesh/LR11x0Interface.cpp
Initialization uses timestamped XTAL-first attempts, conditional TCXO fallback, delayed SPI_CMD_FAILED retries, and success-gated RX setup.

LR1121 module configuration

Layer / File(s) Summary
FemtoFox wiring and switch configuration
bin/config.d/femtofox/*LR1121*
LR1121 configuration naming, nesting, switch tables, pin topology, and Ebyte/Wio wiring comments are updated.
Module selection and switch matrices
variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h, variants/nrf52840/diy/nrf52_promicro_diy_tcxo/variant.h
Mutually exclusive E80 and Wio build flags select the corresponding LR1121 RF switch mappings.
Module selection documentation
variants/nrf52840/diy/nrf52_promicro_diy_tcxo/readme.md
Build-flag selection, Wio switch behavior, truth tables, and configuration examples are documented.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BuildConfig
  participant rfswitch_h
  participant LR1121Module
  BuildConfig->>rfswitch_h: define LR1121_MODULE_E80 or LR1121_MODULE_WIO
  rfswitch_h->>LR1121Module: select pin mapping and switch table
  LR1121Module-->>BuildConfig: compile selected LR1121 configuration
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title covers the LR1121 TCXO/XTAL behavior change, though the trailing YAML remark is noisy.
Description check ✅ Passed The description covers the bug, change summary, testing, and attestations required by the template.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@NomDeTom NomDeTom added the cleanup Code cleanup or refactor label Jul 25, 2026
@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

⚡ Try this PR in the Web Flasher

Flash this PR in the Web Flasher

firmware commit boards expires

Warning

This is an automated, unreviewed CI test build. Back up your device configuration
before flashing, and only flash devices you are able to recover.

Supported boards built by this PR (14)
Device Board Platform
Heltec HT62 heltec-ht62-esp32c3-sx1262 esp32-c3
Heltec Mesh Node T114 heltec-mesh-node-t114 nrf52840
Heltec V3 heltec-v3 esp32-s3
Raspberry Pi Pico W picow rp2040
RAK WisMesh Pocket V3 rak_wismesh_pocket nrf52840
RAK WisMesh Repeater Mini V2 rak_wismesh_repeater_mini nrf52840
RAK WisBlock 4631 rak4631 nrf52840
Seeed SenseCAP Mesh-Tracker-X1 seeed_mesh_tracker_X1 nrf52840
Seeed Wio Tracker L1 seeed_wio_tracker_L1 nrf52840
Seeed SenseCAP Indicator seeed-sensecap-indicator-tft esp32-s3
LILYGO T-Deck t-deck-tft esp32-s3
LILYGO T-Echo Plus t-echo-plus nrf52840
LilyGo T3-C6 tlora-c6 esp32-c6
Seeed SenseCAP T1000-E tracker-t1000-e nrf52840

Build artifacts expire on 2026-08-30. Updated for 3f017e7.

@NomDeTom
NomDeTom marked this pull request as ready for review July 25, 2026 19:24
@NomDeTom NomDeTom added the bugfix Pull request that fixes bugs label Jul 25, 2026
@NomDeTom

Copy link
Copy Markdown
Collaborator Author

I will test this properly tonight, but it worked in a brief check

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/mesh/LR11x0Interface.cpp`:
- Around line 58-64: Update the tcxoVoltage initialization in the ARCH_PORTDUINO
branch of LR11x0Interface so it tracks whether YAML configured a DIO3 voltage;
use the configured value when present, otherwise apply the existing
TCXO_OPTIONAL 1.6 V default. Preserve the later fallback behavior that depends
on tcxoVoltage > 0.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ff25708-0e59-47a9-92cb-4ff123f041ff

📥 Commits

Reviewing files that changed from the base of the PR and between b9a5443 and 7cd8726.

📒 Files selected for processing (1)
  • src/mesh/LR11x0Interface.cpp

Comment thread src/mesh/LR11x0Interface.cpp Outdated
@NomDeTom
NomDeTom force-pushed the LR1121_TCXO_optional branch from e8301a5 to 2f4a846 Compare July 26, 2026 01:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@bin/config.d/femtofox/femtofox_E80-900M2213S.yaml`:
- Line 3: Update the hardware model comment at the top of the
femtofox_E80-900M2213S configuration to use the complete identifier
E80-900M2213S, matching the file name and LR1121 module.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5f0a93e7-272f-4124-9ae1-06e19766ea87

📥 Commits

Reviewing files that changed from the base of the PR and between 2f4a846 and 482f592.

📒 Files selected for processing (3)
  • bin/config.d/femtofox/femtofox_E80-900M2213S.yaml
  • bin/config.d/femtofox/femtofox_LR1121 generic.yaml
  • bin/config.d/femtofox/femtofox_WIO-LR1121.yaml

Comment thread bin/config.d/femtofox/femtofox_E80-900M2213S.yaml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h (1)

51-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reduce duplicated header commentary to the two-line limit. Keep detailed module wiring and truth-table explanations in readme.md; retain only concise selection/mapping rationale here.

  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h#L51-L62: replace the twelve-line Wio topology explanation with at most two lines.
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h#L9-L14: shorten the module-selection explanation to at most two lines.

As per coding guidelines, “Keep code comments minimal—one or two lines maximum.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h` around lines 51 -
62, The comments in variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h at
lines 51-62 and 9-14 exceed the two-line comment limit. Shorten both
module-selection/topology explanations to at most two lines each, retaining only
concise selection or mapping rationale; keep the detailed wiring and truth-table
information in readme.md.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h`:
- Around line 51-62: The comments in
variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h at lines 51-62 and 9-14
exceed the two-line comment limit. Shorten both module-selection/topology
explanations to at most two lines each, retaining only concise selection or
mapping rationale; keep the detailed wiring and truth-table information in
readme.md.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a4af66d6-60a7-45d3-ba6c-98df6248667a

📥 Commits

Reviewing files that changed from the base of the PR and between 482f592 and 6c1d020.

📒 Files selected for processing (4)
  • bin/config.d/femtofox/femtofox_WIO-LR1121.yaml
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/readme.md
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/variant.h

@NomDeTom
NomDeTom force-pushed the LR1121_TCXO_optional branch from df10d90 to 1c354c4 Compare July 26, 2026 18:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/mesh/RadioLibInterface.cpp (1)

51-72: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use Throttle for the elapsed-time check instead of raw millis() arithmetic.

Line 66's now - busyHighSince < busyWatchTimeoutMs is an elapsed-time check; the repo's own Throttle::isWithinTimespanMs() helper already exists for exactly this and should be used per guideline for src/**/*.cpp files.

♻️ Proposed refactor
+#include "mesh/Throttle.h"
+
 uint32_t LockingArduinoHal::digitalRead(uint32_t pin)
 {
     uint32_t value = ArduinoHal::digitalRead(pin);

     // Not watching, or BUSY is behaving: restart the window
     if (!busyWatchArmed || pin != busyWatchPin || value == GpioLevelLow) {
         busyHighSince = 0;
         return value;
     }

     uint32_t now = millis();
     if (busyHighSince == 0) {
         busyHighSince = now;
         return value;
     }
-    if (now - busyHighSince < busyWatchTimeoutMs)
+    if (Throttle::isWithinTimespanMs(busyHighSince, busyWatchTimeoutMs))
         return value;

As per coding guidelines, "Use Throttle from src/mesh/Throttle.h for time-based rate limiting and elapsed-time checks; do not use raw millis() arithmetic such as millis() > lastMs + N, because it is rollover-unsafe."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mesh/RadioLibInterface.cpp` around lines 51 - 72, Update
LockingArduinoHal::digitalRead to use Throttle::isWithinTimespanMs() for the
busyHighSince elapsed-time check instead of raw millis() arithmetic. Include the
Throttle header and preserve the existing timeout behavior, one-shot reset,
logging, and returned GPIO levels.

Source: Coding guidelines

src/mesh/RadioLibInterface.h (1)

41-69: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Trim the BUSY-watchdog comments to comply with the 1–2 line comment guideline.

Both sites explain the same watchdog rationale in multi-paragraph blocks, which the repo's coding guideline explicitly disallows ("Keep code comments minimal—one or two lines maximum ... do not restate straightforward code or add multi-paragraph explanatory blocks"). Condense each to 1–2 lines, keeping only the essential "why" and a link to the upstream issue for anyone who needs the full rationale.

  • src/mesh/RadioLibInterface.h#L41-L69: shorten the 20-line Doxygen block on armBusyWatchdog/digitalRead to 1–2 lines plus the jgromes/RadioLib#1844 reference.
  • src/mesh/LR11x0Interface.cpp#L47-L52: shorten the 6-line LR11X0_BUSY_WATCHDOG_MS comment to 1–2 lines.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mesh/RadioLibInterface.h` around lines 41 - 69, Shorten the BUSY-watchdog
comments at src/mesh/RadioLibInterface.h lines 41-69 and
src/mesh/LR11x0Interface.cpp lines 47-52 to 1–2 lines each. Retain only the
essential reason for the watchdog and the upstream RadioLib issue reference; do
not change armBusyWatchdog, disarmBusyWatchdog, or LR11X0_BUSY_WATCHDOG_MS
behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/mesh/LR11x0Interface.cpp`:
- Around line 148-160: Update the LR11x0 initialization retry and final failure
checks around tryBegin and radioLibResult to also handle
RADIOLIB_ERR_SPI_CMD_TIMEOUT alongside RADIOLIB_ERR_SPI_CMD_FAILED. Preserve the
existing delay/retry behavior and ensure either SPI error causes init() to
return false before subsequent setup calls.

---

Nitpick comments:
In `@src/mesh/RadioLibInterface.cpp`:
- Around line 51-72: Update LockingArduinoHal::digitalRead to use
Throttle::isWithinTimespanMs() for the busyHighSince elapsed-time check instead
of raw millis() arithmetic. Include the Throttle header and preserve the
existing timeout behavior, one-shot reset, logging, and returned GPIO levels.

In `@src/mesh/RadioLibInterface.h`:
- Around line 41-69: Shorten the BUSY-watchdog comments at
src/mesh/RadioLibInterface.h lines 41-69 and src/mesh/LR11x0Interface.cpp lines
47-52 to 1–2 lines each. Retain only the essential reason for the watchdog and
the upstream RadioLib issue reference; do not change armBusyWatchdog,
disarmBusyWatchdog, or LR11X0_BUSY_WATCHDOG_MS behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7bec1f73-1e2c-4177-b290-5afb89071608

📥 Commits

Reviewing files that changed from the base of the PR and between 6c1d020 and 1c354c4.

📒 Files selected for processing (10)
  • bin/config.d/femtofox/femtofox_E80-900M2213S.yaml
  • bin/config.d/femtofox/femtofox_LR1121 generic.yaml
  • bin/config.d/femtofox/femtofox_WIO-LR1121.yaml
  • src/mesh/LR11x0Interface.cpp
  • src/mesh/RadioLibInterface.cpp
  • src/mesh/RadioLibInterface.h
  • src/platform/esp32/MCP23017LockingArduinoHal.cpp
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/readme.md
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/variant.h
🚧 Files skipped from review as they are similar to previous changes (5)
  • bin/config.d/femtofox/femtofox_LR1121 generic.yaml
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/variant.h
  • bin/config.d/femtofox/femtofox_E80-900M2213S.yaml
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/readme.md
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h

Comment thread src/mesh/LR11x0Interface.cpp Outdated
Comment thread src/mesh/LR11x0Interface.cpp Outdated
Comment thread src/mesh/RadioLibInterface.cpp Outdated
@NomDeTom
NomDeTom force-pushed the LR1121_TCXO_optional branch from e9f1bf6 to f2cce5b Compare July 27, 2026 17:13
@NomDeTom
NomDeTom requested a review from caveman99 July 27, 2026 17:21
@NomDeTom NomDeTom changed the title Lr1121 tcxo optional Lr1121 tcxo optional tries xtal first, plus all yamls in a row Jul 27, 2026
@NomDeTom NomDeTom changed the title Lr1121 tcxo optional tries xtal first, plus all yamls in a row Lr1121 tcxo optional tries xtal first, and get all my yamls in a row Jul 27, 2026
@NomDeTom

Copy link
Copy Markdown
Collaborator Author

@caveman99 are we confident that a TCXO LR1121 started with DIO3=0V will definitely fail rather than starting in a degraded mode?

@caveman99

Copy link
Copy Markdown
Member

@caveman99 are we confident that a TCXO LR1121 started with DIO3=0V will definitely fail rather than starting in a degraded mode?

I was testing with LR2021 a lot and if the previous generation is anything like it (either runs on xtal or tcxo) the startup in the wrong mode will raise a -707 error

@NomDeTom

Copy link
Copy Markdown
Collaborator Author

I was testing with LR2021 a lot and if the previous generation is anything like it (either runs on xtal or tcxo) the startup in the wrong mode will raise a -707 error

In this case, it does not / is no longer doing that, and instead is going into a perma-busy state. LR2021 with XTAL fails correctly, but LR1121 does not for some reason.

@NomDeTom

Copy link
Copy Markdown
Collaborator Author

@caveman99 are you happy for this one to go when the checks are finished?

@NomDeTom
NomDeTom force-pushed the LR1121_TCXO_optional branch from 8e7f565 to 3f017e7 Compare July 31, 2026 01:10
NomDeTom and others added 8 commits August 2, 2026 12:39
On boards with TCXO_OPTIONAL, a TCXO-first attempt either hangs RadioLib's
calibration wait forever on a bare/non-TCXO module (unpatched upstream), or
costs a slow failed attempt before falling back even once that's fixed with
a timeout. Measured on hardware: XTAL succeeds immediately on a bare module
(~350ms) and fails fast and cleanly on a genuine TCXO module (~300ms,
RADIOLIB_ERR_SPI_CMD_FAILED), so trying XTAL first is a strict improvement
for hang-avoidance regardless of which oscillator is actually present.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The BUSY watchdog breaks RadioLib's wait, so the next bounded transfer
returns SPI_CMD_TIMEOUT rather than SPI_CMD_FAILED. Only the latter was
checked, so a watchdog-triggered failure fell through to getVersionInfo(),
setRfSwitchTable() and startReceive() against an unresponsive chip.

Also use Throttle::isWithinTimespanMs() for the watchdog's elapsed-time
check instead of raw millis() arithmetic.
The watchdog bounded RadioLib's unbounded BUSY wait in LR11x0::config() by
having LockingArduinoHal::digitalRead() report a stuck pin low exactly once.
That let a TCXO-first attempt fail cleanly rather than hang, but it meant
lying to RadioLib about a GPIO from a HAL shared by every radio driver.

Ordering the attempts XTAL-first avoids the hang outright instead: attempt 1
configures no DIO3 Vref, so there is no calibration wait to get stuck in, and
the TCXO fallback is only reached on a module that answered and refused XTAL.

Attempts are now XTAL, then TCXO, then a settling retry on whichever
oscillator was settled on - after a fallback that is a second TCXO attempt.
Only TCXO_OPTIONAL builds probe XTAL; a variant that declares a Vref
unconditionally still goes straight to it and never probes XTAL at all.

SPI_CMD_TIMEOUT stays a failure alongside SPI_CMD_FAILED: a bounded
per-command BUSY wait in Module::SPItransferStream() reports it in its own
right, independently of the removed watchdog.
trunk fmt: prettier flags the whitespace-only line inside the <summary>
block, which was the only failing check on the PR.
@NomDeTom

NomDeTom commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator Author

@vidplace7 can you take a look at this? Blast radius is low, but I'd prefer another pair of eyes before I merge t.

@joshbowyer

Copy link
Copy Markdown

My weigh-in as I have been somewhat brought in to help with a HAT design for the Luckfox Lyra Zero and an LR1121 radio:

Core fix (LR11x0Interface.cpp): lr11x0SpiFailed() cleanly unifies SPI_CMD_FAILED/SPI_CMD_TIMEOUT handling, which matches the earlier BUSY-watchdog iteration in the commit history correctly surfacing either error depending on where RadioLib gave up. The attempt ordering (XTAL first when TCXO_OPTIONAL, TCXO fallback only if the chip actually answered and refused XTAL, then one settling retry) directly matches the hang described in the PR body and jgromes/RadioLib#1844.

Low blast radius is structurally true, not just asserted: when TCXO_OPTIONAL isn't defined, attemptVoltage is just the pre-existing configured tcxoVoltage, so every already-shipped board (Heltec, T-Deck, T-Beam, RAK, T-1000E - the unchecked regression boxes) hits the exact same single-attempt path as before, just wrapped in the new tryBegin lambda for logging. That's a real reason to be comfortable merging without re-testing every listed board, since the change is a no-op for that code path.

One open question: the femtofox YAML changes correctly move rfswitch_table to be nested under Lora: instead of a top-level sibling key. If that was actually being silently ignored at runtime before (rather than just a style/indentation preference), it'd be worth knowing whether existing femtofox LR1121 users were running with no RF switch control this whole time.

Otherwise this looks mergeable to me.


This comment was drafted with the assistance of an LLM, but manually posted by myself

@NomDeTom

NomDeTom commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator Author

it'd be worth knowing whether existing femtofox LR1121 users were running with no RF switch control this whole time.

I'm almost certain noone has had it working with an lr radio

@caveman99
caveman99 enabled auto-merge August 5, 2026 08:11
@caveman99
caveman99 added this pull request to the merge queue Aug 5, 2026
Merged via the queue into meshtastic:develop with commit e78b121 Aug 5, 2026
61 checks passed
@NomDeTom
NomDeTom deleted the LR1121_TCXO_optional branch August 5, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Pull request that fixes bugs cleanup Code cleanup or refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants