Performance
The perf/ directory contains AWGN SNR-sweep scripts that measure the
receiver end-to-end and produce PER (packet-error-rate) curves. All of
them generate a clean LoRa packet with the gr-lora_sdr GNU Radio TX chain,
then decode the same noisy draws with the receiver, so the only thing being
measured is the sync + decode path.
awgn_testbench_xhonneux.py — SF 7–12 PER sweep
The main testbench:10,000 point Monte Carlo simulation over AWGN channel to measure PER across SF 7 to 12.
Setup
- BW=125 kHz, fs=250 kHz, CR=1 (4/5, uncoded), CRC on, explicit header, 19-byte payload, 8-upchirp preamble, sync word 0x12, up to 10000 packets per SNR point.
- PER is the fraction of trials whose decoded payload bytes differ from
the transmitted payload. Covering sync failure, header failure,
wrong length and payload bit errors.
p_detectseparates sync failures from post-sync decode errors.
|
|:---:|
| *Combined PER panels from `perf/plot_xhonneux.py` — one sub-plot per spreading factor; each SF step gains roughly 4 dB.* |
|
|:---:|
| *All SF curves overlaid: the SF7–12 waterfall in one figure.* |
awgn_compare_sf7.py — receiver vs GNU Radio vs theory
An uncoded SF7 comparison (no Hamming FEC, implicit header, no CRC, 20-byte payload) that decodes the same noisy draws with both sync algorithms:
xhonneux— the Xhonneux et al. paper sync (default)gr-lora-sdr— the gr-lora_sdrframe_syncport
and reports SER (payload-symbol errors vs the TX ground truth) and PER, compared against the theoretical AWGN limit for perfect sync (the non-coherent M-ary orthogonal symbol error probability).
|
|:---:|
| *Uncoded SF7 SER/PER: the two sync front-ends vs the theoretical AWGN limit for perfect sync.* |
awgn_chase_vs_hard.py — Chase coding gain
Runs an AWGN PER sweep for the Chase soft-decision decoder
(DecoderSettings(decode_mode='chase')) on the same config of hard-decoder, and compares the two PER curves
point-for-point on the stored SNR grid. Reports the SNR needed for
PER = 1e-2 and 1e-1 for both decoders and the Chase coding gain in dB.
python3 perf/awgn_chase_vs_hard.py # uses stored hard data
python3 perf/awgn_chase_vs_hard.py --paired --snr=-13,-12,-11,-10,-9
--pairedre-runs the hard decoder on the same noisy draws as Chase (a per-trial "Chase recovered N packets hard missed" count).- Chase is roughly 6× slower than hard decoding (~0.1 s/pkt at SF7/250 kHz),
so narrow the run with
--snr/--packets. - Results →
perf/data/awgn_chase_sf7_results.json, plot →perf/plots/awgn_chase_vs_hard_sf7.png.
|
|:---:|
| *Chase vs hard-decision PER at SF7 — the horizontal gap between the two curves is the Chase coding gain.* |
Interpreting the curves
- PER — where the curve climbs is the sensitivity floor; each SF step adds roughly 4 dB of processing gain (SF10 floors around −18 dB).
- SER / PER vs theory — validates the sync against the ideal AWGN limit.
- Chase vs hard — the horizontal gap between the two PER curves is the Chase coding gain at marginal SNR.
Synthetic packets
The test suite ships tests/tx_helpers.py, a pure-Python LoRa TX encoder
(whiten, Hamming encode, interleave, Gray-code, chirp modulation) used to
build known packets for round-trip tests at any spreading factor.