mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-09-25 18:33:37 +00:00
Skip redundant modulation writes during owned fast RX retunes when the last acknowledged SF/BW/CR/LDRO tuple matches. Invalidate that cache after ordinary setters, failed writes, and lifecycle changes. Include the remaining scan, preamble, settling, and memory-soak experiments, their collectors, validation notes, and original capture records. Preserve capture bytes across checkouts and keep private soak credentials local. Run lab collector and compiled contract tests in CI. Update the expectation, profile mapping, and result-buffer tests for the extended lab tools, and make the private WiFi override header optional for ordinary soak diagnostics. Validation: 145 host tests passed from the staged source snapshot. Clean heltec_v4_repeater and Xiao_S3_WIO_companion_radio_usb builds passed their RAM/flash gates. All 229 staged capture files retain their original bytes; all 75 local documentation links resolve in the clean snapshot.
461 lines
26 KiB
Markdown
461 lines
26 KiB
Markdown
# SX1262 profile-switch validation
|
|
|
|
Measured locally on 2026-09-13 using an XIAO ESP32-S3 with WIO SX1262.
|
|
Later tests also use the SenseCAP Indicator ESP32-S3 LoRa processor. The
|
|
[V8 integration](#production-integration-and-usb-recovery-v8) is the current
|
|
implementation; V1-V7 sections/captures document the development history.
|
|
|
|
## Initial result (V1)
|
|
|
|
The production retune path averaged **1.434 ms with XOSC held**, versus
|
|
**3.166 ms with RC standby**. Holding the oscillator saved **1.732 ms per
|
|
retune (54.7%)**. Warm-mode maximum was **1.467 ms** across 6,000 measured
|
|
retunes. The 6 ms switch allowance and 4 ms loop allowance are unchanged.
|
|
|
|
Each row combines both directions and two reversed-order trials, with 2,000
|
|
measured retunes per standby policy. Times run from production `tuneProfile`
|
|
entry until BUSY is observed low. GetStatus confirmed RX after every timed hop.
|
|
|
|
| Secondary profile | RC mean / maximum | XOSC mean / maximum |
|
|
| --- | --- | --- |
|
|
| SF7 / 500 kHz | 3.161 / 3.199 ms | 1.434 / 1.467 ms |
|
|
| SF8 / 500 kHz | 3.166 / 3.209 ms | 1.435 / 1.464 ms |
|
|
| SF9 / 500 kHz | 3.171 / 3.193 ms | 1.433 / 1.437 ms |
|
|
|
|
- Primary: 909.5 MHz, SF7 / 62.5 kHz, CR 4/5.
|
|
- Secondary: 910.5 MHz, CR 4/5, automatic production preamble calculation.
|
|
- TCXO configuration remained 1.8 V and 1,600 us startup delay.
|
|
- 12,000 measured retunes; zero retune failures, BUSY timeouts, or RX-mode errors.
|
|
- 109 packet/busy deferrals were excluded from hop timings (57 RC, 52 XOSC).
|
|
Deferral preserves the existing packet and radio ownership checks.
|
|
- The first eight successful hops of every trial were excluded from
|
|
steady-state statistics, including the initial oscillator transition.
|
|
- All 12 trials returned to RC standby after disabling the second profile.
|
|
|
|
## Scope and reproducibility
|
|
|
|
The [timing harness](../tools/hil/profile_switch_README.md) compiles the actual
|
|
production wrapper, not the earlier fast/minimal RX benchmark. RC and XOSC
|
|
use the same executable: the baseline changes only the standby policy after
|
|
entering dual-profile mode. No TCXO supply or initial startup delay is disabled.
|
|
The normal guard checks and frequency/SF/BW/CR/preamble setters remain active.
|
|
|
|
This isolates radio switching from UI, Wi-Fi, BLE, mesh dispatch, and scan-loop
|
|
scheduling. BUSY polling/timer overhead is included; the RX status query is
|
|
outside the timing. This is not a packet-delivery test, first-startup timing,
|
|
power measurement, wide-frequency image-recalibration test, or proof of analog
|
|
RF settling beyond BUSY/RX status. Indicator I/O-expander latency and nRF52
|
|
timing still need their own measurements before reducing common budgets.
|
|
|
|
Raw results: [profile_switch_results.json](../tools/hil/profile_switch_results.json).
|
|
The collector requires all requested samples, zero failure/timeout/mode-error
|
|
counts, and successful RC restoration before accepting a trial.
|
|
|
|
Build provenance:
|
|
|
|
- Base commit: `c329cf1fc1e7f2e8c8733ab0d000094730458fe3`, with the local warm-standby patch.
|
|
- Environment: `profile_switch_xiao`; Espressif32 6.11.0 / Arduino 2.0.17.
|
|
- RadioLib: pinned `187ef24791c3d844939b2be13a68bd890bd04e4c` (7.7.1).
|
|
- Test `firmware.bin` SHA-256:
|
|
`629d39bba80ad97c434fbaab61bc7c3c302b5ac8180cb2cb12806508b2d111e0`.
|
|
- Existing unrelated Companion/repeater/Wi-Fi soak changes were not included
|
|
in this minimal timing executable.
|
|
|
|
Host regression checks also passed: profile scan/CLI (3 tests), receive contract
|
|
(2 tests), and SX126x RX-status decoding (1 test). A normal
|
|
`heltec_v4_companion_radio_usb` build and the XIAO timing build succeeded.
|
|
|
|
The XIAO's original 8 MiB flash snapshot was verified against the device while
|
|
held in the bootloader before the timing firmware was uploaded. Raw flash
|
|
backups stay in the current user's private backup directory, outside Git.
|
|
After testing, the entire original snapshot was restored and verified again
|
|
against the device before reboot. The live USB CLI then confirmed `Xiao S3 WIO`
|
|
running `v1.17.1-soak-xiao-B` (11-Sep-2026). Its soak logger was left stopped;
|
|
existing logs were preserved. The Indicator and RAK Tag were not flashed.
|
|
|
|
## Follow-up: batched modulation
|
|
|
|
On the same date, a second 12,000-retune experiment held XOSC warm in both
|
|
cases and compared the old three-setter sequence with one combined LoRa
|
|
modulation update. Both paths ran in the same V2 executable, with the second
|
|
round reversing their order. Each mode completed 6,000 timed hops.
|
|
|
|
| Secondary profile | Separate setters: mean / maximum | Batched: mean / maximum |
|
|
| --- | --- | --- |
|
|
| SF7 / 500 kHz | 1.442 / 1.473 ms | 1.159 / 1.198 ms |
|
|
| SF8 / 500 kHz | 1.444 / 1.480 ms | 1.158 / 1.192 ms |
|
|
| SF9 / 500 kHz | 1.446 / 1.478 ms | 1.156 / 1.163 ms |
|
|
|
|
Overall: **1.444 ms to 1.158 ms**, saving **0.286 ms (19.8%)** per retune.
|
|
Use this matched V2 baseline for the batching comparison; the earlier V1
|
|
warm-standby numbers came from a different executable layout.
|
|
|
|
There were zero retune failures, BUSY timeouts, RX-mode errors, or SF/BW/CR
|
|
cache mismatches. All 12 trials restored RC standby after disabling profile 2.
|
|
84 packet/busy deferrals were excluded (54 separate-setter, 30 batched).
|
|
First eight successful hops per trial were excluded as before.
|
|
|
|
The batching removes two repeated modem checks and two modulation writes.
|
|
The helper validates a complete MeshCore bandwidth/SF/CR tuple, updates
|
|
RadioLib's cached SF/BW/CR before its automatic LDRO calculation, and restores
|
|
the old cache if the command fails. The wrapper's existing physical rollback
|
|
and safe-transition paths are retained. **Frequency changes, preamble updates,
|
|
standby, IRQ/buffer setup, packet parameters, and RX restart remain unchanged.**
|
|
This does not qualify eliminating those other repeated operations.
|
|
|
|
Raw results: [profile_switch_batch_results.json](../tools/hil/profile_switch_batch_results.json).
|
|
V2 test firmware SHA-256:
|
|
`b4403f6f5eb0a2b0a31c2d79859122225f247296699a578ad2596ef17eaed0fd`.
|
|
Toolchain and RadioLib pin match the first experiment. The normal
|
|
`heltec_v4_companion_radio_usb` build also succeeded with batching enabled.
|
|
|
|
The two new host tests execute the production method over 1,200 valid
|
|
bandwidth/SF/CR/LDRO combinations, invalid inputs and wrong modem, command
|
|
failures with cache rollback/retry, and the wrapper's failure short-circuit.
|
|
All eight relevant host tests passed. RF packet delivery and application/UI
|
|
scheduling remain outside this timing experiment; shared budgets are unchanged.
|
|
|
|
## Expanded screening: redundant RX setup and SPI (V5)
|
|
|
|
Corrected V5 measurements on 2026-09-13 cover **28,800 timed retunes in 300
|
|
trials** across XIAO S3/WIO SX1262 and the Indicator ESP32/SX1262. Each sweep
|
|
uses SF7/8/9 at 500 kHz paired with SF7/62.5 kHz, both directions, reversed
|
|
case order in round two, and eight excluded initial hops per trial.
|
|
All 300 trials completed their sample count and restored RC standby on exit.
|
|
There were **zero timed switch failures, BUSY timeouts, RX-mode errors or
|
|
SF/BW/CR cache mismatches**. The normal packet guards deferred 175 attempted
|
|
hops; these were not counted as timed retunes.
|
|
|
|
Twenty-one distinct cases were screened: seven individual redundant-operation
|
|
changes, a full manual RX control, combinations, 2/4/8 MHz SPI and whole-buffer
|
|
ESP32 SPI transfers. Shared controls appear in both groups. All new shortcuts
|
|
are **HIL-only**, not included in normal targets.
|
|
|
|
### Individual and combined RX changes
|
|
|
|
Means in milliseconds, with warm oscillator and batched modulation throughout.
|
|
Each XIAO row has 768 timed hops; each Indicator row has 384.
|
|
|
|
| RX/SPI case | XIAO mean | Indicator mean |
|
|
| --- | ---: | ---: |
|
|
| Production batching, 2 MHz SPI | 1.182 | 15.190 |
|
|
| Manual RX sequence, no omissions | 1.181 | 15.135 |
|
|
| Skip second standby | 1.124 | 14.195 |
|
|
| Skip repeated IRQ setup | 1.096 | 14.399 |
|
|
| Skip repeated buffer-base setup | 1.146 | 14.437 |
|
|
| Skip repeated packet-parameter setup | 0.991 | 12.364 |
|
|
| Skip RX modem query | 1.145 | 14.427 |
|
|
| Defer preamble to the one RX packet-parameter write | 0.956 | 11.659 |
|
|
| Skip wake NOP when already awake | 1.146 | 14.576 |
|
|
| Combined omissions, early preamble write | 0.771 | 9.096 |
|
|
| Combined omissions, deferred preamble | 0.732 | 8.384 |
|
|
| 4 MHz SPI only | 0.985 | 14.996 |
|
|
| 8 MHz SPI only | 0.889 | 14.889 |
|
|
| Combined/deferred, 4 MHz SPI | 0.627 | 8.280 |
|
|
| Combined/deferred, 8 MHz SPI | 0.579 | 8.224 |
|
|
|
|
The largest individual saving is programming preamble/packet parameters once.
|
|
Compare individual omissions with the manual full control when attributing
|
|
their isolated costs: replacing RadioLib's staging dispatch also has overhead.
|
|
Individual savings are not additive; some remove overlapping work.
|
|
|
|
### Whole-buffer SPI follow-up (same V5 binaries)
|
|
|
|
| Case | XIAO mean / maximum | Indicator mean / maximum |
|
|
| --- | --- | --- |
|
|
| Production batching, byte loop, 2 MHz | 1.184 / 1.221 ms | 15.185 / 15.785 ms |
|
|
| Bulk transfer only, 2 MHz | 1.070 / 1.073 ms | 15.092 / 15.134 ms |
|
|
| Bulk transfer only, 4 MHz | 0.890 / 0.903 ms | 14.924 / 14.983 ms |
|
|
| Bulk transfer only, 8 MHz | 0.797 / 0.806 ms | 14.836 / 14.908 ms |
|
|
| Combined/deferred, byte loop, 8 MHz | 0.579 / 0.588 ms | 8.222 / 8.843 ms |
|
|
| Combined/deferred + bulk, 2 MHz | 0.671 / 0.700 ms | 8.369 / 9.027 ms |
|
|
| Combined/deferred + bulk, 4 MHz | 0.582 / 0.595 ms | 8.252 / 8.315 ms |
|
|
| Combined/deferred + bulk, 8 MHz | **0.535 / 0.545 ms** | **8.203 / 8.233 ms** |
|
|
|
|
The fastest XIAO candidate saves **0.649 ms (54.8%)** versus that sweep's
|
|
already-warm, already-batched production control. At 8 MHz, bulk transfers
|
|
alone add about 0.043 ms of benefit to the combined RX shortcut. The Indicator
|
|
remains dominated by I2C-mediated chip-select/BUSY/DIO access; the final bulk
|
|
step improves its combined mean by only 0.019 ms. Small HAL effects varied
|
|
between executable layouts in preliminary screens; do not generalize them.
|
|
|
|
**The Indicator exceeds the generic 6 ms switch allowance even in its fastest
|
|
experimental path.** These are board measurements, not a justification for
|
|
reducing the shared 6 ms switch / 4 ms loop constants. Indicator scheduling
|
|
and effective preambles need board-specific treatment before a production
|
|
rollout. Application/display/network scheduling is still excluded here.
|
|
|
|
Raw accepted sweeps:
|
|
|
|
- [XIAO RX cases](../tools/hil/profile_switch_v5_rx_xiao_complete.json)
|
|
- [Indicator RX cases](../tools/hil/profile_switch_v5_rx_indicator.json)
|
|
- [XIAO bulk SPI](../tools/hil/profile_switch_v5_bulk_xiao.json)
|
|
- [Indicator bulk SPI](../tools/hil/profile_switch_v5_bulk_indicator.json)
|
|
|
|
### Test corrections and provenance
|
|
|
|
V3/V4 broad screening accidentally called `SX1262::startReceive()` instead of
|
|
`CustomSX1262::startReceive()` in the fallback, omitting MeshCore's extra
|
|
preamble-detection IRQ flag. Their raw files are marked superseded and are
|
|
not included in the counts or conclusions above. The V4 packet sweep was
|
|
stopped on discovery. V5 preserves that flag in both normal and manual RX
|
|
paths; a host regression test checks the Custom fallback and mapped flags.
|
|
The earlier V1/V2 warm/batching experiments did not use that experimental
|
|
subclass and are unaffected.
|
|
|
|
An initial V5 XIAO capture stopped on a partial serial JSON line during guarded
|
|
mode exit. It is retained as incomplete, not counted above. The host now
|
|
accumulates reads until newline, with regression coverage. Initial setup
|
|
rejections are retried only for the explicit pre-measurement packet-guard
|
|
reply, bounded to three seconds and counted; packet losses and timed failures
|
|
are never retried away.
|
|
|
|
Final V5 firmware SHA-256:
|
|
|
|
- XIAO: `5506a40ffa8240201aca519e8e24db3647f897e7a1290bba22be6e4986d8f02f`
|
|
- Indicator: `dd595b2e7fa8c1ccb14fac9223f1a57277cd6a602864ee9bf090672f494fa2f6`
|
|
|
|
Base commit/toolchain/RadioLib pin match the earlier experiments. Thirteen unique
|
|
host tests passed (eight production regressions, two HIL boundary/buffer tests,
|
|
three serial-reader/setup-guard tests). The HIL tests cover all 255 nonzero omission masks,
|
|
normal-path fallbacks, preserved IRQ clear/SetRx, error short-circuit and
|
|
full-duplex buffer lengths 1..260. They are not full driver lifecycle tests.
|
|
An additional normal `t1000e_companion_radio_usb` nRF52 build passed with the
|
|
production warm/batching changes: 591,484-byte app, runtime RAM guard passed.
|
|
It was not flashed to the RAK or any nRF52 board.
|
|
|
|
### Qualification boundary
|
|
|
|
No BUSY wait, command status validation, stale-IRQ clear, RX command or wrapper
|
|
packet-ownership guard is removed. The fastest path relies on a known
|
|
RX-to-RX window and established RX setup. Correct invalidation after TX, CAD,
|
|
sleep, reset, failed commands, and recovery must be designed and tested before
|
|
promoting these shortcuts. The per-byte/bulk HAL experiment is ESP32-specific.
|
|
Sensitivity/PER, oscillator power draw, large-frequency image recalibration,
|
|
and application-driven continuous scanning remain unqualified.
|
|
|
|
### Actual packet checks and limitations
|
|
|
|
Final forward matrix: Indicator transmitter to XIAO receiver, -9 dBm,
|
|
21 cases x SF7/8/9 x both profiles x 16/64/255-byte payloads = **378 probes**.
|
|
**359 sequence/length/payload/profile checks succeeded**, 13 receiver-declared
|
|
wait timeouts occurred, and six receiver USB replies did not arrive before
|
|
the host deadline. Transmitter replies returned success. Successfully read
|
|
packets had RSSI -42 to -39 dBm and SNR 10.2 to 14.2 dB. Timeout diagnostics
|
|
reported RX mode and no device errors; some retained a preamble IRQ. These
|
|
observations do not establish why packets were missed.
|
|
|
|
The production-batched baseline delivered 17/18 in that matrix; the fastest
|
|
combined/bulk/8 MHz candidate delivered 18/18. An earlier reversed-order
|
|
smoke test of the fastest candidate had one receiver timeout, so the clean
|
|
18-packet batch is **not** a reliability qualification. Earlier 0 dBm checks
|
|
also had baseline and candidate misses. Reducing power did not eliminate them.
|
|
|
|
Reverse direction: XIAO transmitter to Indicator receiver, -9 dBm, baseline,
|
|
combined/8 MHz and combined/bulk/8 MHz, with the same SF/profile/length matrix.
|
|
**All 54 payloads arrived intact**, 18/18 per case. However, one XIAO USB TX
|
|
acknowledgement was delayed past the host deadline, after which 32 later
|
|
records picked up the previous command's acknowledgement. Thus the raw file
|
|
has only 21 fully matched transactions despite 54 correctly received payloads.
|
|
This is sequence-correlated evidence of a host acknowledgement problem, not
|
|
33 RF losses. Subsequent collector code rejects/stores stale sequence replies
|
|
instead of associating them with a new command, and now asserts DTR on Windows
|
|
to match the existing `s3_memory_soak.py` HWCDC session policy. The captures
|
|
above used DTR deasserted; a causal DTR A/B test was not performed. Sequence
|
|
handling has host regression coverage, but these last host changes were not
|
|
rerun on HIL firmware after the boards were restored.
|
|
|
|
USB acknowledgements and actual receiver payload validity are recorded
|
|
separately. Missing acknowledgements never trigger an automatic retransmit.
|
|
The host drains the receiver concurrently with the transmitter's command and
|
|
records timeouts without hiding them. These tests establish some real packet
|
|
functionality, not a controlled packet-error-rate comparison. Fix/qualify the
|
|
test transport, repeat with a stable RF reference, then test TX/CAD/reset/RXPS
|
|
and continuous application scanning before promoting the shortcuts.
|
|
|
|
- [Forward matrix, all 21 cases](../tools/hil/profile_switch_v5_packets_complete.json)
|
|
- [Reverse matrix, three cases](../tools/hil/profile_switch_v5_packets_reverse_complete.json)
|
|
- [0 dBm smoke](../tools/hil/profile_switch_v5_packet_smoke.json)
|
|
- [-9 dBm reversed-order smoke](../tools/hil/profile_switch_v5_packet_minus9_smoke.json)
|
|
|
|
Earlier incomplete packet captures and superseded screens are retained for
|
|
audit, not counted in the 378/54 final matrices. No identity or channel secrets
|
|
were transmitted: probes used synthetic sequence-tagged bytes.
|
|
|
|
## Production integration and USB recovery (V8)
|
|
|
|
Normal XIAO S3 WIO and Indicator LoRa variants now opt in to buffered 8 MHz
|
|
SPI and a guarded fast RX-to-RX path. Other SX1262 variants retain default
|
|
SPI/full RX setup; modulation batching and warm standby remain shared.
|
|
|
|
The fast path keeps the TCXO warm, applies one SF/BW/CR tuple and one packet
|
|
tuple, clears stale IRQs and starts RX with the original BUSY handling. It
|
|
reuses an established LoRa IRQ map and buffer bases only within an owned
|
|
continuous-RX retune. Ordinary standby, staging/TX, CAD, sleep, reset/init,
|
|
RX duty cycling and command failures invalidate that reuse. RX startup failure
|
|
now fails the whole profile transaction and restores the old profile/caches
|
|
with full setup; failed recovery keeps the profile marked for refresh.
|
|
|
|
### Sleep recovery discovered during integration
|
|
|
|
Initial lifecycle captures found `XOSC_START_ERR` (0x20) after retained sleep,
|
|
despite successful RX status. RC-policy controls reproduced the same flag:
|
|
this was not established as a regression caused by the fast path. Simply
|
|
waking in RC and entering standby before sleep did not clear it. Reapplying
|
|
the already configured TCXO voltage and 1,600 us delay resolved it.
|
|
|
|
The production sleep override now enters standby first, wakes in RC, and
|
|
restores TCXO configuration on wake. It refuses to clear unrelated device
|
|
faults. The warm policy resumes after full RX setup. This follows the standby
|
|
entry requirement in section 13.1.1 of the
|
|
[Semtech SX1261/2 datasheet](https://files.waveshare.com/wiki/SX1262-XXXM-LoRaWAN-GNSS-HAT/DS_SX1261-2_V1.2.pdf).
|
|
Section 13.3.6 describes TCXO control and the XOSC error flag; it does not by
|
|
itself prove the cause of this retained-sleep observation.
|
|
|
|
Diagnostic files `profile_switch_v6_recovery_xiao.json`,
|
|
`profile_switch_v7_recovery_xiao.json`,
|
|
`profile_switch_v7_recovery_xiao_complete.json` (despite its filename, its
|
|
`complete` field is false), and `profile_switch_v7_sleep_diagnostic_xiao.json`
|
|
retain these failures. They are not counted as passing lifecycle tests.
|
|
|
|
### USB fix and scope
|
|
|
|
The HIL host distinguishes Espressif native CDC (DTR asserted) from CH340
|
|
bridges (DTR/RTS deasserted). Replies are newline-assembled and sequence-matched.
|
|
Firmware caches completed packet **and timing** reports before emitting and
|
|
flushing them. A timeout or malformed report triggers a sequence-scoped result
|
|
query, never a repeated TX or timing run. Randomized session sequence starts
|
|
avoid a cached result from an earlier host session.
|
|
|
|
V7 had successfully fixed/retested packet result replay but a long native-USB
|
|
timing sweep still lost one response. V8 adds whole-report timing buffering and
|
|
replay. The incomplete V7 XIAO timing capture is retained, not silently completed.
|
|
The public MeshCore Companion USB protocol is unchanged; these USB fixes are
|
|
for the radio-lab transport. The previous broad Windows-DTR policy described
|
|
in the V5 history above has been replaced by native-device identification.
|
|
|
|
Both boards passed **20 reopen cycles**, deliberate lost timing replies,
|
|
deliberate lost TX replies, stale TX reply isolation, and **18 lifecycle cases**
|
|
each. The cases cover TX, CAD, sleep, reset/init, RC-policy sleep and explicit
|
|
TCXO-restoration controls, repeated three times. Fast counters prove one full
|
|
RX fallback after invalidation and reuse only on the following retune.
|
|
All command results, RX-mode checks and device-error checks passed.
|
|
|
|
- [XIAO recovery](../tools/hil/profile_switch_v8_recovery_xiao.json)
|
|
- [Indicator recovery](../tools/hil/profile_switch_v8_recovery_indicator.json)
|
|
|
|
V8 test firmware SHA-256 (same pinned RadioLib/toolchain as above):
|
|
|
|
- XIAO: `e1806bbf4af5a88b31423131806a682713221082235507ff95e5beb9ef3ac067`
|
|
- Indicator: `bab4009078a4fff68dfb7aa73a5afc83e84f5c47589354d8aeb8e5b8d8798442`
|
|
|
|
Normal USB Companion builds passed for `Xiao_S3_WIO_companion_radio_usb`
|
|
(813,901 app bytes / 63,012 static RAM),
|
|
`SenseCapIndicator-LoRa_comp_radio_usb` (879,809 / 62,960), and
|
|
`t1000e_companion_radio_usb` (591,980 / 179,868). Runtime RAM budgets passed
|
|
on all three. These normal application images were compiled, not substituted
|
|
for the user's configured soak firmware during the HIL tests.
|
|
|
|
Host/native regression coverage includes production modulation caches/LDRO,
|
|
standby failure short-circuit, RX-start rollback failure, ownership guards,
|
|
fast-state invalidation, TCXO wake fault preservation, buffered SPI semantics,
|
|
USB result overflow/replay, partial reads and stale-sequence handling.
|
|
|
|
### Final steady-state timing
|
|
|
|
V8 ran 256 timed retunes per trial, four production configurations, SF7/8/9
|
|
at 500 kHz paired with SF7/62.5 kHz, and two reversed-order rounds on each
|
|
board: **12,288 measured retunes / 48 trials**. The first eight hops per trial
|
|
are excluded. There were zero retune failures, BUSY timeouts, RX-mode errors
|
|
or modulation-cache errors. All 48 trials restored RC policy on exit. The
|
|
normal packet guards deferred 21 XIAO and 59 Indicator hops; no setup retries
|
|
or naturally missing/replayed USB reports occurred in these final sweeps.
|
|
|
|
| Production configuration | XIAO mean / maximum | Indicator mean / maximum |
|
|
| --- | --- | --- |
|
|
| Warm + batching, per-byte SPI 2 MHz | 1.193 / 1.227 ms | 15.174 / 15.836 ms |
|
|
| Fast RX, per-byte SPI 2 MHz | 0.744 / 0.770 ms | 8.426 / 8.471 ms |
|
|
| Full RX, buffered SPI 8 MHz | 0.828 / 0.840 ms | 14.816 / 15.386 ms |
|
|
| Fast RX + buffered SPI 8 MHz | **0.549 / 0.556 ms** | **8.263 / 8.879 ms** |
|
|
|
|
The combined production path saves **54.0% on XIAO** and **45.5% on Indicator**
|
|
relative to each same-image warm/batched control. Small differences from V5-V7
|
|
reflect different binaries/code layout; only within-image A/Bs are compared.
|
|
Both fast configurations must increment the production success counter; full
|
|
RX controls must not. Mode/cache verification happens after the timed region.
|
|
|
|
- [XIAO V8 timing](../tools/hil/profile_switch_v8_production_xiao.json)
|
|
- [Indicator V8 timing](../tools/hil/profile_switch_v8_production_indicator.json)
|
|
|
|
The common 6 ms switch and 4 ms loop allowances are unchanged, not delays
|
|
inserted by the driver. Indicator still exceeds 6 ms. These measurements do
|
|
not qualify continuous application scheduling, scan-overlap reception,
|
|
sensitivity/PER, power use, temperature extremes, or image recalibration on
|
|
frequency changes larger than this 1 MHz pair. Do not shorten common transmit
|
|
preambles or advertise the XIAO number for other boards.
|
|
|
|
### Final over-air packet matrix
|
|
|
|
**288/288 payloads and command transactions passed**: 144 Indicator-to-XIAO
|
|
and 144 XIAO-to-Indicator. Each direction covers all four production cases,
|
|
SF7/8/9 secondary profiles, both target profiles, 16/64/255-byte synthetic
|
|
payloads and two reversed-order rounds. TX used buffered 8 MHz SPI at -9 dBm.
|
|
Fast receiver readiness reports had to show actual production fast resumes.
|
|
|
|
There were **zero RX errors, receiver timeouts, missing replies, stale replies,
|
|
or natural transport-recovery queries** in these matrices. Deliberately lost
|
|
and stale replies were separately exercised by the recovery tests above.
|
|
RSSI ranged -43 to -39 dBm and SNR 10.2 to 14.5 dB. This clean short-range
|
|
matrix addresses the failures seen in the earlier V5 harness; it does not
|
|
identify which single change caused each historical miss or establish a
|
|
field packet-error rate.
|
|
|
|
- [Indicator TX / XIAO RX](../tools/hil/profile_switch_v8_packets_forward.json)
|
|
- [XIAO TX / Indicator RX](../tools/hil/profile_switch_v8_packets_reverse.json)
|
|
|
|
All **18 host/native regression tests** passed. The HIL builds do not include
|
|
the unrelated pre-existing Companion/repeater/Wi-Fi soak edits; the normal
|
|
application compile checks include the current working tree and preserve them.
|
|
|
|
A subsequent requested [SF6/125 kHz multi-channel test](sf6_channel_scan_validation.md)
|
|
used 32-symbol preambles and 4.8-symbol visits. It stopped on the third packet
|
|
at the initial four channels (two received, one timeout); no higher count was
|
|
tried. That continuous scan experiment is separate from the 288/288
|
|
stationary-after-retune matrix above.
|
|
|
|
## Unchanged modulation tuple follow-up
|
|
|
|
The initial software-only checks below were followed by
|
|
[same-image hardware timing and separated-radio tests](separated_radio_modulation_cache_validation.md).
|
|
Frequency-only means improved from 548.880 to 451.897 us on XIAO and from
|
|
8,263.438 to 7,601.193 us on Indicator. Four-channel SF6 reception was not
|
|
loss-free. The following paragraph records the initial implementation stage,
|
|
not the current hardware-test status.
|
|
|
|
Implemented 2026-09-14 after commit `0e5955f8`, without restarting hardware
|
|
tests. On opted-in fast RX-to-RX hops, `setLoRaModulationParams()` now compares
|
|
the requested SF, encoded bandwidth, encoded CR and effective LDRO against
|
|
the last successfully acknowledged modulation write. An exact match within
|
|
a valid owned standby window omits only `SetModulationParams` (0x8B).
|
|
Frequency programming, the modem query, preamble/packet parameters, IRQ clears,
|
|
RF-switch control and BUSY waits remain unchanged.
|
|
|
|
The acknowledgement is separate from RadioLib's mutable software fields.
|
|
Auto/manual LDRO compares the resulting command byte, with the pinned
|
|
RadioLib >=16 ms symbol rule. A failed write revokes the whole fast context
|
|
before rollback. Ordinary SF/BW/CR/forced-LDRO setters invalidate the saved
|
|
tuple even on failure. Existing full-RX staging, ordinary standby, TX/CAD
|
|
staging, reset/init, sleep, duty cycling and failed RX/standby operations also
|
|
invalidate it. The first hop after lost context therefore writes again;
|
|
frequency-only hops that retain the context can skip subsequent writes.
|
|
|
|
All **30 selected host/native tests passed**, including repeat-write counts
|
|
for all supported bandwidth/SF/CR combinations and auto/forced LDRO modes,
|
|
each independently changed field, LDRO policy transitions, failed-write retry,
|
|
modem-query failure, ownership gates, ordinary setters and lifecycle invalidation.
|
|
Both `profile_switch_xiao` and `profile_switch_indicator` compiled successfully
|
|
against the pinned RadioLib. No firmware was uploaded, no radio command was
|
|
issued, and no new RF result was collected. The temporary build overlay was
|
|
removed. The earlier ~0.549 ms XIAO and ~8.263 ms Indicator timings do **not**
|
|
measure this added optimization; its time saving and RF behavior await testing.
|