Skip to content

Iridium: prove + harden the wideband path at 6 MS/s#126

Merged
kevinelliott merged 1 commit into
masterfrom
iridium-wideband-rates
Jun 13, 2026
Merged

Iridium: prove + harden the wideband path at 6 MS/s#126
kevinelliott merged 1 commit into
masterfrom
iridium-wideband-rates

Conversation

@kevinelliott

@kevinelliott kevinelliott commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Triggered by the live Iridium session decoding nothing. Conclusion: the iridium core works correctly at the station's 6 MS/s — the live silence is the antenna/signal (separately confirmed: SAWbird+IR powered and passing the band, but a full-band capture shows zero burst energy; the Maxtena PN100/M1621HCT-EXT1 passive antenna needs clear sky view).

What this PR adds:

  • decodes_real_burst_at_station_rates — the wideband decoder had no test above 2 MS/s, yet the station runs it at 6 MS/s (decim 24); that gap is exactly why 6 MS/s correctness was unknown. The test upsamples the real gr-iridium reference burst to 2 and 6 MS/s at several offsets (including near the band edge) and asserts detect + demod with clean PRBS15. It passes — 6 MS/s is correct.
  • Noise-floor warmup — the per-bin floor was seeded from a single frame, so many bins started near a noise null and read tens of dB "hot" for the EMA's whole settling time: a startup burst-detection storm, worse at the larger FFTs of higher rates (wasted CPU — CRC rejects them, so no false decodes). Now averages the floor over the first 64 frames (~33 ms) before detecting; real-burst detection is unaffected.

Note for future testing: modulate() is the wrong way to synthesize high-rate test signal — its RRC is a fixed 81 taps (~half a symbol at 6 MS/s sps=240), so it produces garbage above ~2 MS/s. Upsample real bursts instead (as this test and the existing 2 MS/s test do).

Bench gates unchanged.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved wideband burst detection accuracy by implementing a noise floor warmup phase that ensures stable threshold comparisons before detection begins.
  • Tests

    • Added comprehensive integration test validating burst detection across multiple sampling rates, frequency offsets, and noise conditions with payload verification.

Investigating why the live Iridium session decoded nothing, I found the
wideband decoder had NO test above 2 MS/s — the station runs it at
6 MS/s (decim 24). Added decodes_real_burst_at_station_rates: it
upsamples the real gr-iridium reference burst to 2 and 6 MS/s at
several offsets (incl. near the band edge) and confirms detect +
demod with clean PRBS15. The 6 MS/s path works correctly — the live
silence is the antenna/signal, not the core.

(A synthetic multi-rate test via modulate() is the WRONG tool: its RRC
is a fixed 81 taps, which under-filters to ~half a symbol at high sps,
so it generates garbage above ~2 MS/s. Upsample real bursts instead.)

Also fixed a real robustness bug found en route: the per-bin noise
floor was seeded from a single frame, so many bins started near a
noise null and read tens of dB 'hot' for the EMA's whole settling
time — a startup storm of false detections, worse at the larger FFTs
of higher rates (wasted CPU; CRC rejects them so no false decodes).
Now warms up a mean over the first 64 frames (~33 ms) before
detecting. Real-burst detection is unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4db2e3e4-4196-4053-a346-061908b71109

📥 Commits

Reviewing files that changed from the base of the PR and between d3d93f8 and c29467b.

📒 Files selected for processing (2)
  • crates/xng-mode-iridium/src/wideband.rs
  • crates/xng-mode-iridium/tests/wideband.rs

📝 Walkthrough

Walkthrough

This PR introduces a noise-floor warmup phase to the wideband FFT burst detector. A new WARMUP_FRAMES constant controls how many initial frames are used to settle the per-bin noise floor via incremental mean before threshold-based detection resumes. The detector tracks warmup progress with floor_frames and suppresses hot-bin detection until warmup completes, then switches to the existing EMA behavior. An integration test validates the behavior with resampled real burst data across multiple station rates and frequency offsets.

Changes

Wideband Burst Detection Warmup Phase

Layer / File(s) Summary
Warmup phase implementation
crates/xng-mode-iridium/src/wideband.rs
Adds WARMUP_FRAMES constant to define the warmup period, introduces floor_frames: u64 field to IridiumWideband to track frames during the settling phase, initializes the field on struct construction, and replaces the original noise-floor initialization and continuous EMA with a two-phase algorithm: frames are accumulated into an incremental mean during warmup (hot bin detection suppressed), then the code switches to symmetric EMA for the normal phase once the floor has stabilized.
Integration test validation
crates/xng-mode-iridium/tests/wideband.rs
Adds decodes_real_burst_at_station_rates test that loads the PRBS15 reference fixture, resamples to multiple station rates with frequency offsets, adds pseudorandom noise, runs the wideband detector over chunked buffers, and asserts decoded bursts match the access preamble and have zero PRBS15 bit violations.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

A rabbit hops through FFT frames with glee,
Warmup's begun, the noise floor to see!
Let the bins settle 'fore hot ones ignite,
Then burst detection shines clear and bright. ✨📡

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding a test and fixing noise-floor warmup to validate the wideband detection path at the 6 MS/s station sampling rate.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch iridium-wideband-rates

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 and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c29467ba03

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +140 to +143
if warming {
// Incremental mean of the frames seen so far.
*f += (m - *f) / self.floor_frames as f32;
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve bursts during the warmup window

When a stream or file begins with an Iridium burst, or a burst starts within the first 64 FFT frames, this branch updates the floor and continues before setting any hot bins, so no ActiveBurst is created. At the current 6 MS/s FFT size this suppresses detection for about 44 ms, long enough to drop shorter bursts entirely or miss the preamble of longer ones, after which process can drain the samples because there is no active burst; this regresses captures that do not have an initial quiet lead-in.

Useful? React with 👍 / 👎.

@kevinelliott
kevinelliott merged commit b4f6077 into master Jun 13, 2026
3 checks passed
@kevinelliott
kevinelliott deleted the iridium-wideband-rates branch June 13, 2026 05:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant