Skip to content

airtime_model_check.py: CR 4/7 is computed as 4/8, overstating ToA by ~14% #6

Description

@ACETyr

Summary

reference/airtime_model_check.py — our reference port of SX126x::calculateTimeOnAir(), and the
project's stated authority for airtime — silently maps coding rate 4/7 to 4/8. Every ToA computed
at CR 4/7 is overstated by a factor 8/7 (~14%).

Host-side analysis script, kept in the project folder rather than in this repo; filed here because
this is the project tracker (cf. #5).

Location

reference/airtime_model_check.py:55

cr = cr_wire + 4 if cr_wire < 5 else (cr_wire + 1 if cr_wire == 7 else cr_wire)

The cr_wire == 7 branch adds 1. For cr_wire in {5, 6, 8} the value passes through unchanged, so
the special case is asymmetric and unexplained by the surrounding comment, which states that "a
stored 5..8 is used as-is".

Evidence it is wrong

RadioLib applies the coding-rate denominator directly, with no special case:

.pio/libdeps/Heltec_v3_repeater/RadioLib/src/modules/SX126x/SX126x.cpp:767

uint32_t nSymbol_x4 = (pc.lora.preambleLength + 8) * 4 + sfCoeff1_x4 + nPreCodedSymbols * dr.lora.codingRate * 4;

The symptom is visible directly in the model's own output — the CR7 column is byte-identical to CR8:

 bytes       CR5       CR6       CR7       CR8
    64     529.4     599.0     738.3     738.3
   184    1143.8    1336.3    1721.3    1721.3

Correct values (SF8 / BW 62.5 kHz / preamble 32 / CRC on):

bytes 4/5 4/7 (correct) 4/7 (current, wrong)
16 283.6 ms 324.6 ms 345.1 ms
64 529.4 ms 668.7 ms 738.3 ms
184 1143.8 ms 1528.8 ms 1721.3 ms

Why the selftest did not catch it

--selftest passes 15/15 because every vector uses CR 5. A selftest pinned to a single coding
rate cannot detect a per-CR mapping error by construction. Any fix should add vectors at 4/6, 4/7
and 4/8.

Impact

Low until now, because everything measured so far assumed the AT/EU-narrow preset (CR 4/5), which is
unaffected. It became relevant on 2026-08-22: get radio showed AT-PL-Hofstetten01 running CR 4/7
while KK and the bench companion run 4/5, and the first airtime comparison for that node used the
inflated figures. This is the second CR-related defect in this file after the coefficient fix of
2026-08-17, so the area deserves the extra vectors rather than another point fix.

Suggested fix

Drop the special case, use the denominator as stored, and extend --selftest to cover 4/6, 4/7, 4/8
with hand-computed reference points.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions