-
Notifications
You must be signed in to change notification settings - Fork 4
Serial Command Reference
Transport: native ESP32-P4 USB Serial/JTAG (COM17 on the reference bench;
the COM number is not a device identity), 8N1, line-terminated (\n). Examples
use 115200 for compatibility; see the native-USB note below.
Firmware: current main at 427c8c6; the authoritative parsers are
main.cpp,
rf_lab.cpp,
and rf_visualizer.cpp.
This is the human/AI-facing control surface for the Tab5 radio — everything needed to tune, scan, monitor telemetry, and pull files off the device without touching the touchscreen. It's the same protocol the physical UI itself drives internally (touch handlers call the same underlying functions these commands do), so anything scriptable here is exactly what the device is already doing live.
Send one command per line. Most commands reply with one or more lines
prefixed by the command's own name (e.g. RTL_TUNE ... replies
RTL_TUNE_OK ... or RTL_TUNE_INVALID ...). A command that doesn't match
anything produces no reply at all — there is no error line for "unknown
command," so typos fail silently. RTL_HELP prints the short on-device list;
this page also includes implemented specialist, transfer, test, and companion
commands that do not fit in that short help response.
Every operator-facing control must expose a matching serial command or record
why it cannot. RTL_SCREEN_STATUS is the read-only render-ownership diagnostic:
it reports the active screen, Settings return target, transitions, rejected
inactive draws, and visible update count.
# One-shot: send a command, print whatever comes back for 2 seconds.
$port = New-Object System.IO.Ports.SerialPort COM17,115200,None,8,One
$port.ReadTimeout = 2000
$port.NewLine = "`n"
$port.Open()
$port.WriteLine("RTL_HELP")
Start-Sleep -Milliseconds 500
while ($true) { try { $port.ReadLine() } catch { break } }
$port.Close()Any serial library in any language works the same way — this is a plain line protocol, nothing OrcSDR-specific about the transport itself.
The Tab5's PC-facing port is the ESP32-P4's native USB Serial/JTAG interface,
not an external USB-to-UART bridge. On the accepted bench unit Windows reports
USB\VID_303A&PID_1001&MI_00. Confirm the current COM assignment instead of
assuming COM17:
Get-PnpDevice -Class Ports |
Format-Table Status, FriendlyName, InstanceId -AutoSize
Get-CimInstance Win32_SerialPort |
Select-Object DeviceID, Name, Description, PNPDeviceIDFor this native USB connection, the 115200 or 921600 value passed to
SerialPort is configuration metadata, not a physical UART bit clock. A host
connection at 921600 was hardware-verified while firmware still used
Serial.begin(115200); it did not provide an 8x transfer-speed increase. Keep
the existing scripts at 115200 unless the hardware path changes to a real UART
bridge. With a real UART bridge, both ends must use the same baud.
Large captures use binary chunks, not ASCII samples or hex text. The current protocol uses 16 KiB host-to-device chunks and 2 KiB device-to-host chunks, then verifies the complete file with SHA-256. Use the repository clients:
# PC -> Tab5
.\tools\copy_to_tab5_sd.ps1 '.\capture.s16' `
'/orcsdr/rds_debug/capture.s16' -Port COM17
# Tab5 -> PC
.\tools\copy_from_tab5_sd.ps1 '/orcsdr/rds_debug/capture.s16' `
-Destination '.\capture.s16' -Port COM17Transfer rules and failure meanings:
- Only one process may own the COM port. Close serial monitors before running
a transfer or upload.
PermissionError(13)/Access is deniedusually means a monitor or an orphaned PlatformIO/esptool process still holds it; identify the exact holder and stop only that process. - Do not run an automatic logger beside a binary transfer. Firmware now blocks
radio auto-start while
SD_GET/SD_PUTis active so radio logs cannot be inserted into file bytes. - Do not accept byte count alone. Completion requires the device and host SHA-256 values to match. The RDS investigation verified two 3,840,000-byte downloads this way.
Classification: native-USB baud behavior is expected device operation (a how-to), port contention is a host-side troubleshooting condition, and the former radio-log interleaving was a firmware bug fixed by the transfer guard.
Do not leave this cable connected for radio or Android TV use. The PC USB
Serial/JTAG link supplies VBUS and keeps the JTAG device enumerated; under
Wi-Fi + RTL-SDR load that path has produced ESP_RST_BROWNOUT on a unit that
is stable with the same firmware when the flash cable is unplugged. Current
firmware turns the P4 brownout reset off (CONFIG_ESP_BROWNOUT_DET=n) so the
sag no longer reboots the chip; glitches are still possible. Flash, close the
COM port, unplug the cable, then use the LAN console.
Two tiers, and the split is not fully consistent across the codebase (some state-changing commands require auth, some don't — documented per-command below rather than papered over):
-
Unauthenticated — works immediately over the physical serial
connection. Covers all status/query commands and several state-changing
ones (
RTL_REC_START,RTL_TOOL,RTL_RDS_STATUS,RTL_FREQquery). -
authenticated— gates the rest (RTL_TUNE,RTL_VOLUME <n>,RTL_CAPTURE/RTL_LISTEN,RTL_STOP,RTL_PRESET_SCAN,RTL_PRESET_TUNE). Requires thePAIR/AUTHHMAC handshake below. This exists for a remote/untrusted-host scenario (e.g. Bluetooth); if you're driving the device over a physically-attached USB cable, that trust boundary is arguably already crossed, but the gate is enforced as written today. Pair once per session:
> PAIR <32-byte-hex-key>
< PAIR_OK (or PAIR_LOCKED if already paired to a different key)
> AUTH <16-byte-hex-nonce> <32-byte-hex-hmac-of("host"+nonce)>
< AUTH_OK <32-byte-hex-hmac-of("device"+nonce)>
The pairing key is stored in NVS after first pair and persists across reboots. There is currently no documented out-of-band way to generate a compliant nonce/proof pair from a plain script without replicating the HMAC-SHA256 handshake — treat the authenticated commands as requiring a proper pairing client, not something to hand-roll casually.
The repository clients already implement this handshake. Use
tools/help_media.py
or one of the PowerShell regression/copy tools instead of printing, copying,
or embedding the pairing key in a command log.
| Command | Auth | What it does / how to use it |
|---|---|---|
RTL_HELP |
no | Prints the concise built-in command list between RTL_HELP_BEGIN and RTL_HELP_END. |
RTL_STATUS |
no | Reports whether the RTL-SDR is enumerated plus VID, PID, USB speed, and serial number. |
RTL_HEALTH |
no | Reports uptime, current/minimum heap, DMA heap and largest block, task count, main-task stack high-water mark, and reset reason. Use it before and during soak tests. |
RTL_RESET |
yes | Prints RTL_RESETTING and performs a software restart. |
RTL_SERIAL VERBOSITY |
no | Reads the persistent serial logging level. |
RTL_SERIAL VERBOSITY <QUIET|NORMAL|DEBUG|TRACE> |
yes | Changes and persists logging. QUIET retains command replies and crash/reset evidence. |
RTL_SCREEN_STATUS |
no | Reports active/return screens, transitions, rejected inactive draws, visible updates, and the last transition time. |
RTL_UI_REGRESSION CHECK |
no | Runs passive UI geometry/ownership checks. |
RTL_UI_REGRESSION RUN |
yes | Exercises a bounded Home-to-dashboard-to-Home transition and reports whether state was restored. |
RTL_DRIVER STATUS |
no | Reports driver version/state/capabilities, gain/AGC/bias shadows, bytes, blocks, effective sample rate, overruns, and consumer drops. |
RTL_DRIVER SELF_CHECK |
no | Verifies the installed driver exposes the minimum capabilities required by OrcSDR. |
RTL_DRIVER GAINMODE <AUTO|MANUAL> |
yes | Selects tuner automatic or manual gain mode. |
RTL_DRIVER GAIN <0..496> |
yes | Sets tuner gain in tenths of a dB; 297 means 29.7 dB. The driver may reject a value unsupported by the tuner. |
RTL_DRIVER RTLAGC <ON|OFF> |
yes | Enables or disables RTL2832 digital AGC. |
RTL_DRIVER BIAS <ON|OFF> |
yes | Controls the RTL-SDR Blog V4 bias tee. Disconnect DC-short loads before enabling it. |
RTL_CAPTURE_STATUS |
no | Reports the state of a legacy one-shot/continuous capture and, when finished, byte statistics, SHA-256, and any error. |
| Command | Auth | Reply | Notes |
|---|---|---|---|
RTL_TUNE <BAND> <HZ> |
yes | RTL_TUNE_OK band=... frequency_hz=... |
BAND = FM|AM|WX|CB|LORA|BROWSE|ADSB|P25. Full retune (stops/restarts the capture path as needed). |
RTL_FREQ |
no | RTL_FREQ_STATUS band=... frequency_hz=... mode=... |
Query only. |
RTL_FREQ <HZ> |
yes | RTL_FREQ_OK band=... frequency_hz=... |
Hot retune within the current band — cheaper than RTL_TUNE, use for stepping/scanning. |
RTL_CAPTURE [KZEL|NOAA|AM|LORA] / RTL_LISTEN <KZEL|FM|NOAA|WX|AM|LORA>
|
yes |
RTL_CAPTURE_QUEUED ... or RTL_CAPTURE_BUSY_OR_UNAVAILABLE
|
Older, band-limited entry point. RTL_LISTEN is continuous; RTL_CAPTURE is one-shot. Prefer RTL_TUNE for new work. |
RTL_STOP |
yes | RTL_STOPPING |
Stops the active capture/stream. |
RTL_TOOL |
no | RTL_TOOL_STATUS tool=RADIO|SCOPE|CAPTURE |
Query the active tool tab. |
RTL_TOOL <RADIO|SCOPE|CAPTURE> |
no | (none) or RTL_TOOL_INVALID
|
Switch tool tab. Case-insensitive value. |
RTL_SOUND |
no | RTL_SOUND_STATUS enabled=0|1 |
Reads the audio/demod pipeline state. |
RTL_SOUND <ON|OFF> |
no | RTL_SOUND_OK enabled=... |
Enables or disables audio and demodulation. |
RTL_AUDIO_TEST STATUS |
no | status line | Reports the audio-test state. |
RTL_AUDIO_TEST TONE |
no | status/result line | Starts the built-in speaker tone test. |
RTL_AUDIO_TEST FM |
no | status/result line | Routes the FM audio test path. |
RTL_AUDIO_TEST STOP |
no | status/result line | Stops the active audio test. |
Band default frequencies (used when a command doesn't specify one, e.g.
RTL_LISTEN WX): FM 96.113 MHz (last-tuned FM freq persists in NVS and
overrides this), AM/WX/CB/LoRa each have their own fixed default — see
rtl_band_default_frequency() in main.cpp for exact values, they're
band-plan specific and not usually worth hardcoding in a client.
| Command | Auth | Reply |
|---|---|---|
RTL_VOLUME |
no | RTL_VOLUME_STATUS volume=<0-32> |
RTL_VOLUME <0-32> |
yes |
RTL_VOLUME_OK volume=... or RTL_VOLUME_INVALID
|
Off by default. Enable from Settings → Companion or the serial commands
below. The page is read-only (GET / and GET /api/status); it does not
tune, change volume, or return passwords or coordinates.
| Command | Auth | Reply |
|---|---|---|
RTL_WEB / RTL_WEB_STATUS
|
no | RTL_WEB_STATUS enabled=0|1 listening=0|1 url=http://…/|offline |
RTL_WEB ON|OFF |
yes | RTL_WEB_OK enabled=… listening=… url=… |
| Command | Auth | Reply |
|---|---|---|
RTL_STATUS |
no |
RTL_SDR_STATUS connected=... vid=... pid=... speed=... serial="..." — is the RTL-SDR dongle itself present/enumerated. |
RTL_SIGNAL |
no |
RTL_SIGNAL_STATUS band=... frequency_hz=... signal_dbfs_tenths=... stereo_locked=0|1 left_dbfs_tenths=... right_dbfs_tenths=... rds_carrier=0|1 rds_signal_tenths=... pilot_env_thou=... filter_hz=... lo_nudge=... — one-shot snapshot of the dashboard and DSP state. Divide *_tenths fields by 10 for dBFS. |
signal_dbfs_tenths is the RF-level meter (matches the SIG bar). left_dbfs_tenths/
right_dbfs_tenths are FM stereo decoder outputs — meaningful only when
stereo_locked=1; when unlocked they mirror mono and both read the same
value. rds_carrier/rds_signal_tenths are RDS Stage 1 (carrier presence only,
see below) — always present on FM band regardless of whether the station
actually broadcasts RDS.
| Command | Auth | Reply | Notes |
|---|---|---|---|
RTL_PRESET_SCAN |
yes |
RTL_PRESET_SCAN_QUEUED or RTL_PRESET_SCAN_INVALID (not on FM) |
Sweeps 87.5–108 MHz, ~800 kHz steps, collects up to 10 stations by signal strength. Takes tens of seconds; poll RTL_PRESET_LIST afterward. |
RTL_PRESET_LIST |
no |
RTL_PRESET_LIST_BEGIN count=N then N × RTL_PRESET <n> frequency_hz=... level=... then RTL_PRESET_LIST_END
|
Persists across reboots (NVS). |
RTL_PRESET_TUNE <n> |
yes |
RTL_PRESET_TUNE_OK index=... frequency_hz=... or RTL_PRESET_TUNE_INVALID
|
1-based index, matching the on-screen list numbering. |
RDS decoding is staged — see phasing.md for the current status. Stage 1
(carrier detection) and Stage 2 (bit/block sync) are hardware-verified against
live 96.1 KZEL and a captured MPX replay. Stage 3 parsing/display of PS, PTY,
and RadioText remains open.
| Command | Auth | Reply |
|---|---|---|
RTL_RDS_STATUS |
no | see below |
RTL_RDS_CAPTURE_START |
no | starts an 8-second, 240 kS/s MPX capture in PSRAM |
RTL_RDS_CAPTURE_STOP / RTL_RDS_CAPTURE_SAVE
|
no | stops and exports .s16 plus .json metadata to SD |
RTL_RDS_CAPTURE_STATUS |
no | capture progress, frequency, SD state, and last path |
RTL_RDS_REPLAY <path.s16> |
no | resets and replays an MPX capture through the same RDS processor; live radio must be stopped |
RDS_STATUS carrier=0|1 carrier_signal=<dB> block_locked=0|1 bler=<%>
good=<n> total=<n> hyp0_streak=<n> hyp1_streak=<n>
timing_chip_rate=<Hz> timing_correction_ppm=<ppm>
nco_freq_off=<rad/sample> i_lpf=<n> q_lpf=<n> mu=<0..1>
A=<hex16> B=<hex16> C=<hex16> D=<hex16>
driver_overruns=<n> driver_drops=<n> effective_sps=<n>
audio_chunks=<n> audio_drops=<n>
-
carrier— Stage 1, whether 57 kHz subcarrier energy is present. -
block_locked/bler/good/total— Stage 2 block-sync status.bler=100%withtotal=0means block sync has never been achieved since tuning to this frequency, not that the signal is bad. -
hyp0_streak/hyp1_streak— best streak for each chip-pair polarity across four fractional timing phases. A streak of 4 correctly-spaced offset-word matches declares lock. -
A/B/C/D— last decoded block content (hex). Not meaningful untilblock_locked=1— treat as noise otherwise, per the current known-issue inphasing.md.
The legacy periodic diagnostic pair is compiled off by default. Use
RTL_RDS_STATUS for on-demand diagnostics without a continuous serial load:
RDS_STAGE2 locked=... bler=... good=... total=... hyp0_locked=... hyp0_streak=...
hyp1_locked=... hyp1_streak=... nco_freq_off=... i_lpf=... q_lpf=...
bp_env=... A=... B=... C=... D=...
RDS_TIMING chip_rate=... mu=... symbols_sec=... correction_ppm=... freq_off=...
i_lpf/q_lpf are the complex 57 kHz baseband before carrier-independent
differential pairing. timing_correction_ppm reports the measured RTL sample
clock calibration (-10 on the accepted fixture); nco_freq_off is retained
for protocol compatibility and currently reports zero. The driver/audio fields
are explicit, on-demand stream-continuity counters. symbols_sec should read
close to 2375 (the RDS biphase chip rate, not the final 1187.5 bit/s information
rate).
Capture stores signed 16-bit little-endian FM multiplex samples at 240 kS/s
under /orcsdr/rds_debug/, with a sibling JSON file containing the sample
rate, tuned frequency, sample count, radians-per-LSB scale, and start uptime.
The raw .s16 file is directly consumable by Redsea:
RTL_RDS_CAPTURE_START
... wait up to 8 seconds ...
RTL_RDS_CAPTURE_STOP
RTL_RDS_CAPTURE_STATUS
After copying the reported .s16 file to a PC:
redsea --input mpx -r 240k < capture.s16For deterministic on-device replay, stop the live radio first and use the SD
path reported by RTL_RDS_CAPTURE_STOP:
RTL_RDS_REPLAY /orcsdr/rds_debug/001_96113000_mpx.s16
RTL_RDS_STATUS
| Command | Auth | What it does / how to use it |
|---|---|---|
RTL_ADSB_START |
no | Starts the 1090 MHz ADS-B receive path and opens its default frequency. |
RTL_ADSB_STOP |
no | Stops reception when ADS-B currently owns the radio. A call made in another band has no reply. |
RTL_ADSB_LOCATION <latitude> <longitude> |
no | Validates decimal coordinates, persists them, and refreshes range/bearing calculations. Latitude must be -90..90 and longitude -180..180. |
RTL_P25_STATUS |
no | Reports the active profile/site, control candidates and levels, frame/NID/TSBK health, identity, BER estimate, grant/follow state, voice counters, queue drops, stack margin, and worst processing times. |
RTL_P25_SCAN |
yes | Opens P25 if needed and starts its configured control-channel survey. Poll RTL_P25_STATUS for progress. |
RTL_P25_CONFIG_RELOAD |
yes | Reloads the SD-backed P25 configuration, cancels an active survey, and retunes/redraws the P25 screen when active. |
| Command | Auth | Reply |
|---|---|---|
RTL_REC_START |
no | (switches to Capture tool, starts recording) |
RTL_REC_STOP |
no | (stops and exports WAV to SD) |
RTL_REC_STATUS |
no | multi-line status (buffered seconds, sample count, last file path — see audio_rec_status_print()) |
RTL_REC_SAVE |
no | re-exports the currently-held PCM buffer, useful after inserting an SD card mid-session |
Capped at kAudioRecMaxSeconds (12s) per recording, 48 kHz mono PCM,
written under /orcsdr/rec_NNN_<BAND>_<HZ>.wav.
Chunked binary protocol (SD_LIST, SD_GET_BEGIN/_CHUNK/_ABORT,
SD_PUT_BEGIN/_CHUNK/_ABORT, SD_REMOVE) with SHA-256 verification and
staged-write rollback on failure. All paths must be under /orcsdr/.
Use copy_to_tab5_sd.ps1
and copy_from_tab5_sd.ps1 rather than
re-implementing the binary framing by hand; they handle chunking and hashing:
.\tools\copy_to_tab5_sd.ps1 <local-file> /orcsdr/<name> -Port COM17
.\tools\copy_from_tab5_sd.ps1 /orcsdr/<name> -Destination <local-file> -Port COM17SD_LIST alone (no chunking needed) returns one SD_LIST_ENTRY bytes=... modified=... pathhex=<hex> line per file, then
SD_LIST_DONE count=N — safe to call directly for a quick directory dump.
| Command | What it does / how to use it |
|---|---|
SD_LIST |
Lists files beneath /orcsdr/; returned paths are hex encoded. |
SD_GET_BEGIN <path_hex> |
Opens an allowed file for download and reports chunk/total sizes. |
SD_GET_CHUNK |
Emits an SD_GET_DATA bytes=N header followed by exactly N binary bytes. Repeat until SD_GET_DONE supplies total bytes and SHA-256. |
SD_GET_ABORT |
Closes an active download, or acknowledges that none is active. |
SD_PUT_BEGIN <bytes> <sha256_hex> <path_hex> |
Creates a staged .part upload and reports the allowed chunk size. |
SD_PUT_CHUNK <bytes> |
Announces the size of the immediately following binary payload. Repeat until the staged upload reaches its declared size and verifies its hash. |
SD_PUT_ABORT |
Aborts the upload and removes its temporary file. |
SD_REMOVE <path_hex> |
Removes an allowed writable file beneath /orcsdr/. |
All SD writes are refused with ..._ERROR radio_busy while a capture/
stream is active — stop the radio (RTL_STOP, needs auth) or wait for it
to be idle first.
These commands invoke the exact same manual Data & Maps actions as the
touchscreen. They never run at boot and they do not create an alternate
download path. Connect Wi-Fi first, then check the signed catalog before
selecting a pack by its returned stable id.
| Command | Auth | Reply / notes |
|---|---|---|
RTL_CATALOG_STATUS / RTL_CATALOG_LIST
|
no |
RTL_CATALOG_STATUS, then one RTL_CATALOG_PACK per pack. Safe state query. |
RTL_CATALOG_CHECK / RTL_CATALOG_FETCH
|
yes | Downloads and verifies the signed release manifest. Requires mounted SD and connected Wi-Fi. The reply uses the selected CHECK or FETCH name. |
RTL_CATALOG_INSTALL <id> |
yes | Streams the selected published pack to SD, validates its hash/schema, then activates it atomically. Run a check first. |
RTL_CATALOG_REMOVE <id> CONFIRM |
yes | Removes only the selected installed pack. The literal CONFIRM is required. |
The currently named pack IDs are faa_aircraft, faa_aviation,
noaa_weather, fcc_broadcast, and lane_county_map. Treat
RTL_CATALOG_STATUS as authoritative because a future signed catalog can
change availability and versions.
Example:
RTL_CATALOG_CHECK
RTL_CATALOG_STATUS
RTL_CATALOG_INSTALL faa_aircraft
RTL_UI gives a serial agent the same semantic action handlers used by the
FM, P25, LoRa, and Settings touch views. It is authenticated because every
action can change device state. Credentials continue to use signed SET_WIFI;
ADS-B coordinates use RTL_ADSB_LOCATION.
RTL_UI STATUS
RTL_UI OPEN ADSB
RTL_UI ACTION SETTINGS RANGE 50
RTL_UI ACTION P25 SURVEY
RTL_UI ACTION LORA VIEW 3
RTL_UI ACTION FM TUNE 101900000
RTL_UI OPEN accepts HOME, FM, P25, ADSB, LORA, RF_LAB,
WIFI_ANALYSIS, or SETTINGS.
RTL_UI ACTION accepts a domain and one of its visible touch actions:
-
FM:TUNE,DOWN,UP,SEEK_DOWN,SEEK_UP,SAVE,STEP,FILTER_DOWN,FILTER_UP,SPAN_DOWN,SPAN_UP,SOUND,VOL_DOWN,VOL_UP,GRAPHICS,RECORD,SCAN,SETTINGS,HOME. -
P25:TUNE,PREV,NEXT,SURVEY,HOLD,HOLD_TG <id>,SKIP,FOLLOW,ENCRYPT_SKIP,RELOAD,SPAN_DOWN,SPAN_UP,SOUND,VOL_DOWN,VOL_UP,SETTINGS,HOME. -
LORA:VIEW <0-5>,NODE <index>,FAVORITE,FILTER,SCAN,IQ,LOG,CLEAR,EXPORT,FOLLOW,CHANNELS,SETTINGS,HOME. -
SETTINGS:WIFI_POWER <0|1>,WIFI_BOOT <0|1>,ANTENNA <0|1>,C6_UPDATE_CONFIRM,SCAN,CONNECT_SAVED <index>,FORGET <index>,MOVE_UP <index>,MOVE_DOWN <index>,RANGE <nm>,BRIGHTNESS <0-255>,ROTATION <1|3>,TIMEOUT <seconds>,VOLUME <0-255>,SOUND <0|1>,AUTO_START <0|1>,GRAPHICS <0|1>,WEB <0|1>,CATALOG_CHECK,CATALOG_INSTALL <index>,CATALOG_REMOVE <index>,CLOSE.
Each succeeds with RTL_UI_ACTION_OK. Inputs are intentionally routed through
the existing dashboard handlers rather than duplicating touch-only state.
RTL_RF24_PAGE <0-4> is an authenticated shortcut for selecting a page on
the active 2.4 GHz analysis dashboard. It returns RTL_RF24_PAGE_OK, rejects
values outside 0-4, and reports dashboard_inactive if that screen is not open.
These commands drive the same test bench described in RF Lab. Only
STATUS, SELF_CHECK, GET, RECIPE LIST, and RECORDS LIST are available
without authentication; every other RTL_LAB command requires it.
| Command | What it does / how to use it |
|---|---|
RTL_LAB OPEN / RTL_LAB CLOSE
|
Opens RF Lab or queues its close action. |
RTL_LAB STATUS |
Reports active page, RF source, frequency, sample rate, PPM, gain mode/value, RTL AGC, bias tee, and keep-settings state. |
RTL_LAB PAGE <LIVE|CONTROLS|MEASUREMENTS|RECORDS> |
Selects a lab page. Names are case-insensitive. |
RTL_LAB SELF_CHECK |
Runs RF Lab's internal bounds, parser, layout, calibration, and analysis checks. |
RTL_LAB GET <id> |
Reads one of frequency_hz, sample_rate_sps, ppm, gain_tenth_db, gain_mode, rtl_agc, or bias_tee. |
RTL_LAB SET <id> <integer> |
Queues a supported receiver change. The same seven IDs are accepted. gain_mode, rtl_agc, and bias_tee use 0/1. Frequency, sample-rate, PPM, gain, and driver capabilities are validated. |
RTL_LAB ACTION bias_ack |
Opens a 30-second safety window required before RTL_LAB SET bias_tee 1. Disconnect DC-short loads first. |
RTL_LAB ACTION calibrate |
Calculates a reference-based dBm offset when the reference and source are stable. |
RTL_LAB REFERENCE STATUS |
Reports the configured signal-generator reference and calibration state. |
RTL_LAB REFERENCE SET <hz> <source_dbm> <path_loss_db> <tolerance_db> [note] |
Defines the external reference used for calibration. Notes reject CSV/JSON-unsafe punctuation. |
RTL_LAB REFERENCE CLEAR |
Clears the reference and invalidates calibration. |
RTL_LAB SNAPSHOT [note] |
Queues a point-in-time RF Lab evidence record on SD. |
RTL_LAB RUN START [seconds] |
Starts a measurement run. Omit seconds for a manual run; timed runs are bounded by the in-memory reading capacity. |
RTL_LAB RUN MARK [note] |
Adds a timestamped marker to an active run. |
RTL_LAB RUN STOP |
Finishes and queues the current run for storage. |
RTL_LAB RECIPE LIST |
Lists the current recipe IDs: identity, transport, rate_passport, gain_quick, gain_full, tuner_auto, rtl_agc, ppm, hf_path, source_reconnect, and bias_off_on_off. |
RTL_LAB RECIPE START <id> |
Starts a recipe. Some recipes are guided/manual and intentionally return an inconclusive status until external measurements are supplied. |
RTL_LAB RECIPE STATUS |
Reports the active recipe and status. |
RTL_LAB RECIPE INPUT <volts> |
Supplies the requested voltage measurement during bias_off_on_off. Follow the reported state; values are accepted only at expected stages. |
RTL_LAB RECIPE CONFIRM_BIAS_SAFE |
Confirms it is safe for the bias recipe to energize the bias tee after the initial off-voltage check. |
RTL_LAB RECIPE CANCEL |
Cancels the recipe/run and forces the bias tee off when applicable. |
RTL_LAB RECORDS LIST |
Reports the recent record count and newest result. |
RTL_LAB RECORDS SHOW <record-id> |
Returns the selected recent record and SD path. |
The visualizer commands are what let a serial client open Phosphor Persistence directly, for example:
RTL_VIS OPEN phosphor
RTL_VIS STATUS
Only STATUS, SELF_CHECK, GET, and PRESET LIST work without
authentication. Other visualizer commands change UI or persisted state and
require an authenticated session.
| Command | What it does / how to use it |
|---|---|
RTL_VIS OPEN [view] |
Opens the visualizer, optionally selecting a view. Valid slugs: spectrum, waterfall, phosphor, spectrum3d, constellation, iqscope, polar, occupancy, peakavg, doppler, channelizer, audiospec. |
RTL_VIS CLOSE |
Queues the visualizer close action. |
RTL_VIS STATUS |
Reports active view, source availability, freeze/HUD/drawer state, presentation and analysis FPS, dropped inputs, and effective quality. |
RTL_VIS NEXT / RTL_VIS PREV
|
Moves to the next or previous view. |
RTL_VIS FREEZE <ON|OFF> |
Freezes or resumes history updates. |
RTL_VIS GET <control-id> |
Reads a control's formatted value and whether it is currently enabled. |
RTL_VIS SET <control-id> <number> |
Sets a numeric, toggle, or choice control. Toggles use 0/1; choices use their zero-based option index. Values are validated and clamped by the shared UI control. |
RTL_VIS ACTION <control-id> |
Runs an action control such as persistence.clear. |
RTL_VIS PRESET LIST |
Lists four preset slots for the current view. |
RTL_VIS PRESET <SAVE|APPLY|RENAME|DELETE> <1-4> [name] |
Manages the current view's persisted presets. Names are limited to 20 characters. |
RTL_VIS SELF_CHECK |
Runs visualizer control, layout, analysis, and buffer-invariant checks. |
Visualizer control IDs
- Common:
rf.center_hz,rf.span_hz,rf.gain_mode,rf.gain_db,display.floor_dbfs,display.ceiling_dbfs,display.auto_levels,display.grid,display.palette,visual.freeze,visual.quality,visual.fps_overlay; actionvisual.reset. - Spectrum:
fft.size,fft.window,fft.overlap,fft.detector,fft.average_mode,fft.average_time_ms,fft.peak_hold_mode,fft.peak_hold_s,fft.peak_decay_db_s,fft.marker_count,fft.marker_threshold_db,fft.trace_thickness,fft.center_cursor; actionfft.clear_peak. - Waterfall:
waterfall.palette,waterfall.direction,waterfall.speed,waterfall.history_s,waterfall.gamma,waterfall.level_mode,waterfall.floor_dbfs,waterfall.ceiling_dbfs,waterfall.bin_mapping,waterfall.time_grid_s,waterfall.frequency_labels; actionwaterfall.clear. - Phosphor:
persistence.half_life_s,persistence.accumulation,persistence.exposure,persistence.decay_curve,persistence.point_size,persistence.blur_px,persistence.palette,persistence.rare_hold_s,persistence.background_reject_db; actionpersistence.clear. - 3D spectrum:
spectrum3d.slices,spectrum3d.history_s,spectrum3d.elevation_deg,spectrum3d.azimuth_deg,spectrum3d.zoom,spectrum3d.depth_scale,spectrum3d.z_gain,spectrum3d.mesh_mode,spectrum3d.color_mode,spectrum3d.line_decimation,spectrum3d.auto_orbit; actionspectrum3d.reset_camera. - Constellation:
constellation.source,constellation.profile,constellation.channel_bw_hz,constellation.points,constellation.persistence_s,constellation.point_size,constellation.normalize,constellation.axis_scale,constellation.dc_remove,constellation.phase_deg,constellation.carrier_recovery,constellation.timing_recovery,constellation.symbol_rate,constellation.show_ideal; actionconstellation.clear. - IQ scope:
iqscope.traces,iqscope.timebase,iqscope.vertical_scale,iqscope.vertical_position,iqscope.coupling,iqscope.trigger_mode,iqscope.trigger_source,iqscope.trigger_level,iqscope.trigger_slope,iqscope.pretrigger_pct,iqscope.decimation,iqscope.interpolation; actioniqscope.arm_single. - Polar:
polar.source,polar.mode,polar.phase_reference,polar.rotation_deg,polar.radial_scale,polar.normalize,polar.persistence_s,polar.magnitude_gate_db,polar.trail_width,polar.angle_labels,polar.show_histogram; actionpolar.clear. - Occupancy:
occupancy.band_plan,occupancy.band_count,occupancy.threshold_mode,occupancy.threshold_offset_db,occupancy.absolute_dbfs,occupancy.minimum_dwell_ms,occupancy.integration,occupancy.time_bin_ms,occupancy.basis,occupancy.alert_enabled,occupancy.alert_pct,occupancy.sort_bars; actionsoccupancy.reset_session,occupancy.save_csv. - Peak/average:
peakavg.show_live,peakavg.show_average,peakavg.show_max,peakavg.average_mode,peakavg.average_time_s,peakavg.live_smoothing,peakavg.max_mode,peakavg.hold_time_s,peakavg.decay_db_s,peakavg.marker_count,peakavg.shared_scale,peakavg.trace_width; actionspeakavg.clear_hold,peakavg.clear_average. - Doppler:
doppler.span_hz,doppler.fft_size,doppler.window,doppler.integration,doppler.history_s,doppler.tracking,doppler.track_window_hz,doppler.threshold_db,doppler.reference,doppler.fixed_reference_hz,doppler.detrend,doppler.units,doppler.show_fit; actionsdoppler.lock_track,doppler.clear,doppler.save_csv. - Channelizer:
channelizer.count,channelizer.layout,channelizer.plan,channelizer.bandwidth,channelizer.demod,channelizer.squelch_dbfs,channelizer.selected_offset_hz,channelizer.guard_pct,channelizer.scale_mode,channelizer.metric,channelizer.threshold_mode,channelizer.threshold_db,channelizer.refresh_hz,channelizer.selected_action,channelizer.tile_labels,channelizer.solo,channelizer.mute; actionschannelizer.edit_channel,channelizer.reset_plan. - Audio spectrogram:
audiospec.source,audiospec.sample_rate,audiospec.fft_size,audiospec.window,audiospec.overlap,audiospec.max_frequency,audiospec.frequency_scale,audiospec.floor_dbfs,audiospec.ceiling_dbfs,audiospec.normalization,audiospec.palette,audiospec.time_span_s,audiospec.preemphasis,audiospec.filter_overlay,audiospec.cursor; actionaudiospec.clear.
Exact ranges and choice ordering are defined in
rf_visualizer_controls.cpp.
Wi-Fi automation uses the same bounded scan snapshot and Settings handlers as the display. SSIDs are returned as hexadecimal bytes so arbitrary SSID text cannot forge serial records. Passwords are never returned.
| Command | Auth | Reply / behavior |
|---|---|---|
RTL_WIFI_STATUS |
no | Station/Hosted state, scan/connect state, profile/AP counts, power, auto-connect, and antenna. |
RTL_WIFI_SCAN |
no | Queues one scan; wait for RTL_WIFI_SCAN_RESULTS count=N and RTL_WIFI_COEX event=scan_complete. |
RTL_WIFI_RESULTS |
no | Bounded RTL_WIFI_AP rows with ssid_hex, BSSID, RSSI, channel, and security flag. |
RTL_WIFI_PROFILES |
no | Priority-ordered SSID-only profile list; never returns passwords. |
RTL_WIFI_CONNECT_SAVED |
no | Compatibility shortcut for saved profile 0. Indexed connection uses RTL_UI ACTION SETTINGS CONNECT_SAVED <index>. |
RTL_WIFI_CONNECT_SAVED PAUSE |
no | Queues connection to profile 0 and explicitly pauses the SDR during association. |
RTL_WIFI_DISCONNECT |
yes | Disconnects Wi-Fi and restores the paused radio/audio path. |
RTL_WIFI_C6_STATUS |
no | Reports host and C6 firmware versions, transport readiness, embedded-update availability, update stage/percent, and version match. |
RTL_WIFI_C6_UPDATE CONFIRM |
yes | Starts the explicit embedded C6 firmware update when ready. This is disruptive; poll RTL_WIFI_C6_STATUS until terminal state. |
RTL_WIFI_COEX_STATUS |
no | Reports the Wi-Fi/SDR coexistence state and counters. |
SET_WIFI <ssid_hex> <pass_hex> <hmac> |
yes + signed payload | Provisions slot 0 and attempts connection without echoing credentials. |
| Command | Auth | What it does / how to use it |
|---|---|---|
RTL_LOCATION STATUS |
no | Reports whether a location lookup is busy/ready, the candidate coordinates in E7 form, and status text. |
RTL_LOCATION IP |
yes | Queues an IP-based location estimate; Wi-Fi must be connected. |
RTL_LOCATION LOOKUP <ZIP-or-address> |
yes | Queues a text lookup. The query must be nonempty and shorter than 64 bytes. |
RTL_LOCATION CONFIRM |
yes | Saves the ready candidate location through the same Settings action used by touch. |
Power, auto-connect, antenna selection, scan, indexed connection, forget, and
priority moves use authenticated RTL_UI ACTION SETTINGS ... commands listed
above. Invalid boolean values and profile indices return
RTL_UI_ACTION_INVALID instead of a false success.
Run the complete non-destructive hardware surface with:
apps/orcsdr-tab5/tools/run-tab5-ui-regression.ps1 -WifiOnly -PairingKeyPath <key-file>Add -RequireWifiConnection when a real saved profile must associate for the
test to pass.
The regression command checks the shared radio-control geometry and screen
ownership self-checks without changing receiver state or NVS. RUN also
exercises an actual screen handoff: Home to the current FM, P25, ADS-B, or
LoRa dashboard and back to Home. It refuses to run over Settings, NAV, keypad,
or documentation overlays.
| Command | Reply | Notes |
|---|---|---|
RTL_UI_REGRESSION CHECK |
RTL_UI_REGRESSION_RESULT ... pass=1 |
Passive checks only. |
RTL_UI_REGRESSION RUN |
RTL_UI_REGRESSION_RESULT ... transitioned=1 restored=1 |
Exercises the bounded handoff and confirms the original UI snapshot returned. |
Use the repeatable runner; it disables DTR/RTS before opening COM17 so it does not reset the Tab5:
.\tools\run-tab5-ui-regression.ps1 -Port COM17
.\tools\run-tab5-ui-regression.ps1 -Port COM17 -Run
.\tools\run-tab5-ui-regression.ps1 -Port COM17 -Soak -Cycles 10 -DwellSeconds 2
.\tools\run-tab5-ui-regression.ps1 -Port COM17 -Profile Smoke
.\tools\run-tab5-ui-regression.ps1 -Port COM17 -Profile Stress -Seed 12345
.\tools\run-tab5-ui-regression.ps1 -Port COM17 -Profile Stress -Cycles 1 -WifiEvery 1
.\tools\run-tab5-ui-regression.ps1 -Port COM17 -Profile Overnight -Cycles 500
.\tools\run-tab5-ui-regression.ps1 -Port COM17 -RadioScan -Cycles 10-RadioScan repeatedly starts FM and P25 scans, transfers tuner ownership to
another dashboard during each scan, rejects stale restoration, and records heap,
DMA, stack, uptime, reset, watchdog, and panic evidence. The first cycle warms
the dashboards before the memory baseline is recorded. The run fails if free
heap falls by more than 4 KiB, DMA-capable heap falls by more than 2 KiB, or the
largest DMA-capable block falls below 20 KiB.
-Soak authenticates with .orclink\ui-doc.key, then drives every radio
dashboard through Home and Settings. Smoke, Stress, and Overnight provide
5, 50, and 500-cycle defaults. Stress and Overnight randomize the radio order
from the recorded seed and cycle Wi-Fi every ten passes. All profiles exercise
mute/unmute, query heap health, require advancing FM audio after every return,
and save a timestamped log under artifacts\ui-soak. The runner fails on panic,
watchdog, brownout, assertion, reboot, timeout, exclusive-screen violation, or
lost audio; after failure it stays attached briefly to capture reset evidence.
It restores the starting dashboard, tuning, sound, and verbosity when possible.
Use -WifiEvery 1 for a focused Wi-Fi cycle on every pass.
| Command | Reply | Notes |
|---|---|---|
RTL_SERIAL VERBOSITY |
RTL_SERIAL_VERBOSITY mode=... |
Query without authentication. |
RTL_SERIAL VERBOSITY QUIET|NORMAL|DEBUG|TRACE |
RTL_SERIAL_VERBOSITY_OK mode=... |
Authenticated, persistent setting. NORMAL is the default. |
RTL_HEALTH |
RTL_HEALTH_STATUS ... |
Heap, internal DMA, task count, uptime, and boot reset reason. |
QUIET retains errors, command replies, panic text, and reset evidence.
NORMAL adds normal lifecycle information. DEBUG enables periodic receiver,
RDS, power, and heartbeat diagnostics. TRACE additionally enables decoded
ADS-B frames, LoRa energy triggers, spectrum timing, and scan samples.
The partition table reserves a 256 KiB flash core-dump partition. With the
matching ELF from build-native-hosted3, inspect a retained panic using
idf.py -B build-native-hosted3 -p COM17 coredump-info.
Run the host-side crash/audio parser check without a device:
.\tools\run-tab5-ui-regression.ps1 -SelfCheckThe authenticated documentation commands stage stable views and save an exact
1280x720 BMP through M5GFX. Use tools/build-help-media.ps1 instead of driving
the commands by hand; it verifies the firmware/catalog, retrieves each BMP
through the hash-checked SD protocol, and always attempts state restoration.
| Command | Reply | Notes |
|---|---|---|
UI_DOC_LIST |
UI_DOC_LIST_BEGIN, one UI_DOC_SCREEN per view, UI_DOC_LIST_DONE
|
Enumerates the firmware-owned screen catalog. |
UI_DOC_SHOW <screen-id> <live|demo> |
UI_DOC_SHOW_DONE |
Enters documentation mode without persisting navigation or demo state. Demo views carry a visible DEMO badge. |
UI_CAPTURE <slug> |
UI_CAPTURE_DONE ... bytes=... width=1280 height=720 firmware=... sha256=... |
Freezes the frame, stops reception if needed, and writes /orcsdr/screenshots/<slug>.bmp. |
UI_DOC_EXIT |
UI_DOC_EXIT_DONE restored=true |
Restores the prior dashboard, view, sound, and reception state. |
All four commands require the normal PAIR/AUTH session. Arbitrary editors
cannot be selected; the only keyboard capture is a sanitized deterministic
example, so saved credentials and private location fields are never exposed.
These commands serve the LoRa energy-trigger and host-decode round trip. See the repository's LoRa developer guide for the binary framing and payload formats.
| Command | Auth | What it does / how to use it |
|---|---|---|
RTL_IQ_START |
no | Starts a bounded raw-IQ capture into PSRAM. |
RTL_IQ_STOP / RTL_IQ_SAVE
|
no | Stops capture and exports it to SD. The two names currently use the same implementation. |
RTL_IQ_STATUS |
no | Reports capture/ready state, bytes, frequency, LoRa SF/BW metadata, detector state/counters, thresholds, and last SD path. |
RTL_IQ_RETRIEVE_BEGIN |
no | Locks a completed PSRAM capture for host retrieval and reports its size and RF metadata. |
RTL_IQ_GET_BEGIN |
no | Starts the binary IQ read protocol after RTL_IQ_RETRIEVE_BEGIN. |
RTL_IQ_GET_CHUNK |
no | Requests the next binary IQ chunk. Use the repository client rather than a line-only terminal. |
RTL_IQ_GET_ABORT |
no | Aborts the active binary read while retaining the completed capture. |
RTL_IQ_RETRIEVE_END |
no | Releases the completed capture and resumes LoRa reception when it was paused for retrieval. |
RTL_LORA_NATIVE_STATUS |
no | Reports decoder readiness/busy state, authorized-key presence, CRC/encryption/failure counters, preamble/header/CRC diagnostics, and CFO. |
RTL_LORA_AUTO <ON|OFF> |
no | Enables or disables the energy-triggered LoRa detector. |
RTL_LORA_TUNE <HZ> |
no | Tunes or starts LoRa reception within the firmware's allowed LoRa range. |
LORA_SD_LOG <ON|OFF> |
no | Enables or disables SD event logging. |
LORA_SD_LOG STATUS |
no | Reports requested/ready/error state, queue depth, drops, and log path. |
LORA_MESSAGE <fields> |
no | Injects a validated host-decoded message into the LoRa UI. Intended for the repository decoder workflow. |
LORA_PACKET <fields> |
no | Injects a validated host-decoded packet/metadata record into the LoRa UI. Intended for the repository decoder workflow. |
LORA_MESSAGE_CLEAR |
no | Clears displayed packets and cached node positions. |
These commands support a paired host, updater, or reliability test. They are implemented serial commands, but most users should call them through the repository tooling because several require signed fields and some intentionally have no reply.
| Command | Auth | What it does / how to use it |
|---|---|---|
PING |
yes | Refreshes the authenticated-session timeout. It intentionally has no reply. |
PREPARE_FLASH <sha256_hex> |
yes | Records host approval for a firmware digest and returns FLASH_READY <digest>. It does not itself write or flash firmware. |
SET_WIFI <ssid_hex> <password_hex> <hmac> |
yes + signed payload | Validates the signature, stores profile 0, and begins connection. Never log the password or key. |
INSTALL_STATUS <revision> <max_runs> <hmac> |
yes + signed payload | Installs a newer bounded workflow configuration and resets its run counter. Stale revisions are rejected. |
ROTATE_KEY <new_key_hex> <hmac> |
yes + signed payload | Replaces the pairing key, ends authentication, and requires the host to reconnect with the new key. |
TEST_PRESSURE |
yes | Adds ten synthetic journal events and reports how many events were dropped. Used to test bounded-journal pressure behavior. |
PRESSURE_ACK |
yes | Clears the journal's dropped-event count. |
ACK <sequence> |
yes | Acknowledges journal events through the supplied sequence. It intentionally has no reply. |
The device also emits unsolicited JSON hello, snapshot, telemetry, and
journal records after authentication. Those records are outputs rather than
commands.
Tune to a specific frequency and check signal:
> RTL_TUNE FM 101900000
< RTL_TUNE_OK band=FM frequency_hz=101900000
> RTL_SIGNAL
< RTL_SIGNAL_STATUS band=FM frequency_hz=101900000 signal_dbfs_tenths=-382 stereo_locked=1 ...
Scan and tune to the strongest preset:
> RTL_PRESET_SCAN
< RTL_PRESET_SCAN_QUEUED
(wait ~30-60s, sweeping the whole FM band)
> RTL_PRESET_LIST
< RTL_PRESET_LIST_BEGIN count=6
< RTL_PRESET 1 frequency_hz=94500000 level=-45.0
< ...
< RTL_PRESET_LIST_END
> RTL_PRESET_TUNE 1
< RTL_PRESET_TUNE_OK index=1 frequency_hz=94500000
Poll RDS decode progress while developing the decoder:
> RTL_TUNE FM 96100000
> RTL_RDS_STATUS
< RDS_STATUS carrier=1 carrier_signal=-6.2 block_locked=0 bler=100.0% ...
(poll RTL_RDS_STATUS; continuous stream diagnostics are disabled by default)
- No JSON output mode — everything is
key=valuespace-separated text. Fine for line-oriented parsing, more work for a strict JSON client. -
RTL_HELP's command list is maintained by hand alongside this doc — if you add a command, update both.