Skip to content

feat: RF spectrum scanner for clean frequency selection - #1

Open
wkumik wants to merge 4 commits into
mainfrom
claude/rf-scanner-frequency-hr0ag2
Open

feat: RF spectrum scanner for clean frequency selection#1
wkumik wants to merge 4 commits into
mainfrom
claude/rf-scanner-frequency-hr0ag2

Conversation

@wkumik

@wkumik wkumik commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds "Scan for Clean Channel" menu item to the vehicle radio link settings (WiFi bands only: 2.3/2.4/2.5/5.8 GHz)
  • Opens a full-width spectrum bar chart showing noise floor per channel — shorter bar = less noise = cleaner channel (spectrum-analyser style, Option A as agreed)
  • Colour-coded bars: green (< −88 dBm), yellow (−76 to −88 dBm), red (> −76 dBm)
  • Annotation bubble marks the recommended (cleanest) channel
  • "Use Recommended" button applies the winning frequency via the existing radio link frequency change path

Architecture

Router side (code/r_station/rf_scan.cpp):

  • Triggered by new IPC packet PACKET_TYPE_LOCAL_CONTROLLER_RF_SCAN_START (band flags in vehicle_id_dest)
  • Non-blocking scan state machine runs in router_periodic_loop() — one channel per tick
  • Hops through all band channels at 280 ms/channel via existing radio_links_set_cards_frequencies_for_search()
  • Reads per-channel noise floor via iw dev <iface> survey dump (supported by RTL8812AU, ath9k_htc)
  • Writes live results to /tmp/ruby_rf_scan_results.txt as each channel completes
  • Restores original frequencies on completion; sends PACKET_TYPE_LOCAL_CONTROLLER_RF_SCAN_RESULT back to central with best frequency

UI side (code/r_central/menu/menu_rf_scan.cpp):

  • periodicLoop() reads results file progressively — live graph updates as scan proceeds
  • Blue highlight tracks the channel currently being measured
  • On completion: best channel annotated with bubble + arrow; "Use Recommended: XXXX MHz" button enabled
  • Rescan and Cancel also available

Files changed

File Change
code/radio/local_packets.h +2 IPC packet type constants (231, 232)
code/r_central/menu/menu_objects.h +MENU_ID_RF_SCAN 140
code/r_station/rf_scan.h New — scanner public API
code/r_station/rf_scan.cpp New — scan state machine + iw survey parsing
code/r_station/process_local_packets.cpp Handle RF_SCAN_START message
code/r_station/periodic_loop.cpp Call rf_scan_periodic_loop()
code/r_central/menu/menu_rf_scan.h New — scan menu header
code/r_central/menu/menu_rf_scan.cpp New — spectrum bar chart UI
code/r_central/menu/menu_vehicle_radio_link.h +m_IndexScanFreq member
code/r_central/menu/menu_vehicle_radio_link.cpp +"Scan for Clean Channel" item + onReturnFromChild handler
Makefile Add rf_scan.o and menu_rf_scan.o
.gitignore Exclude .claude/ worktree directory

Test plan

  • Build ruby_rt_station and ruby_central on target hardware
  • Open Vehicle → Radio → Radio Link N → verify "Scan for Clean Channel" appears for 2.4/5.8 GHz links and is absent for SiK links
  • Trigger scan: bars appear progressively, blue highlight tracks current channel
  • Verify colour coding matches noise levels (green/yellow/red)
  • Verify annotation bubble appears on cleanest channel at end of scan
  • "Use Recommended" applies the frequency and closes the menu
  • "Rescan" clears and restarts
  • "Cancel" closes without changing frequency
  • Verify iw dev survey dump populates noise floor for RTL8812AU on 5.8 GHz

🤖 Generated with Claude Code

https://claude.ai/code/session_01JiQhEG8VApL39xVyJLXJ79


Generated by Claude Code

claude and others added 4 commits June 16, 2026 20:58
Adds a new "Scan for Clean Channel" menu item to the vehicle radio link
settings. Opens a full-width spectrum bar chart showing noise floor per
channel (shorter bar = less noise = cleaner, spectrum-analyser style).

Router-side (rf_scan.cpp): hops through all band channels at 280 ms/ch,
reads per-channel noise floor via `iw dev survey dump`, writes live
results to /tmp/ruby_rf_scan_results.txt, signals completion via IPC.

UI-side (menu_rf_scan.cpp): reads results file in periodicLoop, draws
bar chart with colour-coding (green/yellow/red) and an annotation bubble
over the cleanest channel. "Use Recommended" applies the winner via the
existing sendNewRadioLinkFrequency() path.

Only shown for 2.3/2.4/2.5/5.8 GHz links (not SiK/serial).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JiQhEG8VApL39xVyJLXJ79
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JiQhEG8VApL39xVyJLXJ79
Addresses review feedback on the RF spectrum scanner:

1. Safety: do not scan while flying. The scan hops the GS across the whole
   band, dropping video/telemetry/RC to the vehicle for several seconds.
   - Block opening the scan while the vehicle is armed (informational dialog).
   - Stop auto-starting the scan on menu open; require explicit "Start Scan".
   - Warn about the link interruption in the menu item description.

2. No fabricated data: the noise read returned a hard-coded -75 dBm when the
   card reported no survey data, silently recommending channel 0. Now an
   unreadable channel is marked invalid and excluded; if no channel yields
   data, the UI states the card does not support channel survey.

3. Better metric: replace noise floor (near-constant across a band) with the
   channel busy ratio (busy/active time) from `iw survey dump`. Chart now
   plots 0-100% busy; lower = cleaner. Recommendation = lowest busy %.

4. Remove dead RESULT packet path (no central handler existed); the UI reads
   the results file directly. Drops the unused IPC-to-central plumbing.

5. Abort on exit: send RF_SCAN_STOP on Cancel / Back / menu destruction so an
   in-progress scan restores the radio links immediately instead of running
   to completion after the user leaves.

Also fix the apply path: MenuRFScan's id was matched with iChildMenuId/1000
(=> 140==0, never true), so "Use Recommended" never applied the frequency.
Match the full child menu id instead.

GS-only change (local control packets 231/232); no vehicle rebuild needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants