Generated banner for Matlab Detect Capture Usrp
Generated logo for Matlab Detect Capture Usrp

Matlab Detect Capture Usrp

MathWorksOfficialCreated by MathWorks

  • Skill
  • Tool integration
  • Software development
  • BSD-2-Clause
  • No issues found

From the author

Smart triggered RF capture on NI USRP radios with Wireless Testbench — record only when a signal of interest appears, not continuously (triggered spectrum sensing). Use energy detection to capture when signal power rises above the noise floor, or preamble detection to cross-correlate against a known sequence (WLAN L-LTF, 5G NR PSS/SSS, LTE PSS, Zadoff-Chu, custom protocols) and capture only when that protocol's preamble is detected. Use when implementing triggered (wake-on-signal) capture or spectrum sensing, capturing protocol-based signals via cross-correlation, calibrating detection thresholds (plotDetectionSignals / plotThreshold), scanning frequency bands for activity, or building transmit-then-detect workflows.
— the description by MathWorks

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured workflow for implementing triggered RF capture on NI USRP radios using the MATLAB Wireless Testbench. It enables users to move beyond continuous streaming by configuring detectors that record data only when specific conditions are met, such as signal energy rising above a noise floor or the detection of a known protocol preamble. The skill includes support for adaptive and fixed thresholding, multi-capture sequences, and transmit-then-detect loopback testing, while providing a systematic approach to calibrating detection thresholds when performance is inconsistent.

What it does

  • Configures energy-based triggers for wake-on-signal recording.
  • Implements preamble-based triggers using cross-correlation for protocols like 5G NR, LTE, and WLAN.
  • Supports transmit-then-detect workflows for hardware loopback verification.
  • Provides diagnostic sub-workflows for calibrating detection thresholds.
  • Enables multi-capture sequences with sample-clock timestamps.
  • Facilitates frequency-scanning loops for spectrum activity monitoring.

When to use it

  • When you need to capture specific RF events rather than continuous IQ data.
  • When you have a known preamble sequence to trigger on.
  • When you need to verify signal detection thresholds using visual calibration tools.
  • When performing transmit-then-detect testing on a single radio.
  • When scanning multiple frequency bands for signal activity.

Advantages

  • Reduces data storage requirements by avoiding continuous recording.
  • Improves signal capture reliability through adaptive thresholding.
  • Simplifies hardware testing with integrated transmit-and-detect capabilities.
  • Provides clear diagnostic paths for tuning detection parameters.
  • Ensures consistent radio resource management through proper object lifecycle handling.

Usage examples

“I need to capture a signal on my USRP radio 'usrp1' when the energy rises above the noise floor. Use an adaptive threshold.”
The agent generates a MATLAB script using energyDetector with adaptive thresholding, configured for the specified radio, and includes a verification block to report the detection status.
“My preamble detection is failing to trigger on my 5G NR signal. How can I fix it?”
The agent guides you through the threshold calibration sub-workflow, using plotThreshold to visualize the correlation output and adjust the adaptive gain or offset.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/matlab/matlab-detect-capture-usrp/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip matlab-detect-capture-usrp.zip -d .agents/skills

Documentation by MathWorks

Detect and Capture RF Signals on NI USRP Radios

Reference Loading

  • Code patterns (required at Step 4): for the seven copy-ready capture patterns (A–G) and the loopback table, Read references/patterns.md before generating any capture code.

  • API reference (required at Step 3): Read references/api.md for signatures, property ranges, and threshold constraints. Every generation validates parameters against it before emitting code — see the Always rule below. This read is not optional.

  • On demand: references/overview.md — conceptual architecture and detector behavior.

  • On demand, after a failure only: references/threshold-calibration.md — the calibration sub-workflow (plotDetectionSignals / plotThreshold step-by-step). Do not load it during first-time code generation.

Sub-Workflows

This skill exposes one sub-workflow that is loaded on demand from references/:

Sub-workflowWhat it provides
Threshold Calibration (references/threshold-calibration.md)Step-by-step plot -> diagnose -> tune procedure for both energyDetector and preambleDetector, plus combined symptom -> cause -> fix table
Trigger: when to route into Threshold Calibration

Route into references/threshold-calibration.md whenever any of these conditions hold:

  1. No detection — generated Pattern returned status == 0 (capture timed out, no data captured) and the user expected a signal to fire it. This is the primary trigger.

  2. Wrong detection — Pattern returned status >= 1 but the captured data is wrong: noise instead of signal, baseline instead of preamble, saturated waveform (max(abs(data)) near 1.414), or sanity ratio fails (r < 50 for energyDetector, r < 100 for preambleDetector).

  3. Unstable detection — the user reports, or an earlier run in this session already showed, that the Pattern fires inconsistently (sometimes status=0, sometimes status=1); thresholds are sitting on a jittery boundary. Do not run extra captures hunting for this — the Always rule below caps a clean run at one.

  4. User explicitly asks to "calibrate", "tune thresholds", "tune detection", "fix detection", "why didn't it detect", "diagnose", or names plotDetectionSignals / plotThreshold.

Sanity ratio r — where it comes from. Every Pattern's %% Verify block computes and prints r, so triggers 2 and 3 are read straight off the pattern's own output. No extra run is needed.

DetectorFormula the pattern printsReal signal
energyDetector (A/B/E/F)r = max(abs(data).^2) / median(abs(data).^2)r >= 50
preambleDetector (C/D/G)same ratio on the matched-filter output, filter(conj(flipud(pd.Preamble)), 1, data)r > 100
Wideband chirp / OFDM (F)raw r under-reports — 15-20 is normal; the pattern also prints a matched-filter ratiomatched-filter ratio >> 100

Do not route into the sub-workflow for first-time code generation — generate the Pattern from this SKILL.md, run it, and only route into calibration on a failure outcome. The sub-workflow assumes a detector object is already configured and a TX or external signal is present.

If the failure mode is RF-path (no peaks at all on the figure, wrong frequency, broken cable, wrong antenna name), the sub-workflow exits early back to this skill — calibration cannot fix RF problems.

Generate working MATLAB code to detect and capture RF signals using energy detection or preamble detection triggers on NI USRP radios with Wireless Testbench.

Prerequisites

Before this skill applies, the user must have:

  • MATLAB R2022a+ (preambleDetector) or R2023b+ (energyDetector)

  • Wireless Testbench toolbox installed

  • Wireless Testbench Support Package for NI USRP Radios installed

  • Radio previously configured using the Radio Setup wizard

  • Physical NI USRP radio connected and validated

When to Use

Trigger this skill when the user wants smart/triggered capture — record only when something interesting appears on the air, not continuously:

  • Capture only when signal energy rises above the noise floor (energyDetector, Patterns A/B/E/F) — wake-on-signal recording, opportunistic capture, transmit-then-detect verification

  • Capture only when a known protocol preamble is cross-correlated and matched (preambleDetector, Patterns C/D/G) — WLAN L-LTF, 5G NR PSS/SSS, LTE PSS, Zadoff-Chu, custom sync sequences

  • Calibrate detection thresholds (plotDetectionSignals for energyDetector, plotThreshold for preambleDetector)

  • Scan multiple frequencies / channels for activity (e.g., WLAN channel scan across 2.4 GHz band)

  • Transmit a test waveform from the same radio and capture it back upon detection (loopback verification)

  • Capture multiple consecutive triggered signals with sample-clock timestamps

When NOT to Use

Route to another skill if the user's goal is:

  • Untriggered capture (immediate IQ capture without detection) -> matlab-transmit-capture-usrp

  • Continuous streaming (System objects, real-time processing loops) -> use the matlab-read-documentation skill for "Live Data I/O" (Wireless Testbench)

  • Radio setup or troubleshooting -> matlab-set-up-usrp-radio

  • Clock/time synchronization -> use the matlab-read-documentation skill for "Radio Management" (Wireless Testbench)

  • FPGA targeting -> use the matlab-read-documentation skill for "Target NI USRP Radios" (Wireless Testbench)

Decision Tree

User request
|
|-- Mentions "untriggered capture", "immediate capture", "basebandReceiver"
|     -> REDIRECT to matlab-transmit-capture-usrp
|
|-- Mentions "System object", "streaming loop", "real-time processing"
|     -> REDIRECT: use matlab-read-documentation for "Live Data I/O" (Wireless Testbench streaming)
|
|-- Wants triggered capture (detection-based)
|     |
|     |-- Knows signal structure (preamble sequence available)
|     |     |-- Adaptive threshold -> Pattern C
|     |     |-- Fixed threshold -> Pattern D
|     |     |-- Wants to calibrate threshold -> Pattern D + plotThreshold
|     |     |-- Frequency scanning loop -> Pattern G
|     |
|     |-- Explicit energy/power cue (energy rise, power increase), no preamble
|     |     |-- Adaptive threshold (energy delta + minimum) -> Pattern A
|     |     |-- Fixed threshold -> Pattern B
|     |     |-- Wants to calibrate threshold -> Pattern A/B + plotDetectionSignals
|     |     |-- Multiple captures with timestamps -> Pattern E
|     |     |-- Transmit-then-detect workflow -> Pattern F
|     |
|     |-- Ambiguous: no energy/power cue, no preamble, no parameters given
|           -> ASK FIRST (do not assume energy): "Do you have a known preamble
|              sequence to correlate against, or do you want to trigger on any
|              signal energy increase? Also, what threshold values or detection
|              parameters would you like to use?"

Code Generation Steps

Key Functions
FunctionPurposeToolboxAvailable From
energyDetectorArm radio; trigger capture when energy rises above the noise floorWireless TestbenchR2023b
preambleDetectorArm radio; trigger capture on correlation with a known preambleWireless TestbenchR2022a
captureBlocking triggered IQ capture (returns on detection or timeout)Wireless Testbenchwith detector object
capture(..., "NumCaptures", N)Capture N consecutive triggered signals (Pattern E)Wireless TestbenchR2024a
plotDetectionSignalsCalibrate energy threshold — energyDetector onlyWireless TestbenchR2023b
plotThresholdCalibrate preamble threshold — preambleDetector onlyWireless TestbenchR2022a
transmit / stopTransmissionSend / stop a test waveform on the detector object (Pattern F)Wireless Testbenchwith detector object
zadoffChuSeqGenerate a Zadoff-Chu preamble sequence (Patterns C/D)Communications ToolboxR2012b
wlanLLTF / wlanNonHTConfigBuild the WLAN L-LTF preamble (Pattern G)WLAN ToolboxR2015b
chirpGenerate a test chirp waveform (Pattern F)Signal Processing Toolboxbefore R2006a
Step 1: Determine Detector Type

Select on an explicit cue, not on the mere absence of a preamble.

SignalUser saysDetector
Energy-basedexplicit energy/power cue: "energy", "power increase/rise", "amplitude above the noise floor"energyDetector
Preamble-based"preamble", "Zadoff-Chu", "L-LTF", "PSS/SSS", "correlation", a known sequencepreambleDetector
Ambiguousonly "detect a signal" / "capture when it appears" — no energy/power cue, no preamble, no threshold parametersAsk first (Guardrails -> Ask First); do not default to energy
Step 2: Gather Required Inputs
ParameterRequiredAsk if missing
Radio nameYesAlways
Center frequencyYesYes
Sample rateYesYes
Threshold methodYesYes (adaptive/fixed)
Threshold valuesYesYes
Capture durationYesYes
TimeoutYesDefault seconds(1) if not specified
Preamble sequenceOnly for preambleDetectorYes
Step 3: Validate Constraints

Check parameter values against valid ranges before generating code. See references/api.md for complete constraint tables (WindowLength, FixedThreshold, Preamble length, TriggerOffset, AdaptiveThresholdGain, AdaptiveThresholdOffset).

If a value violates these constraints, inform the user and suggest the valid range. Do NOT generate code with invalid values.

Step 4: Generate Code

The seven copy-ready patterns (A–G) live in references/patterns.md. Read references/patterns.md now, then use the pattern the Decision Tree selected. Each pattern ships with concrete default values — replace the values marked % <- set with the user's radio and signal parameters, and validate them against the references/api.md ranges (Step 3) before running. For loopback bring-up (transmit-then-detect), follow the Local Hardware Testing table in that file.

PatternDetectorThresholdUse case
AenergyDetectoradaptiveWake-on-signal capture on an energy rise
BenergyDetectorfixedCapture above a fixed power level
CpreambleDetectoradaptiveCapture on correlation with a known preamble
DpreambleDetectorfixedPreamble capture / plotThreshold calibration
EenergyDetectoradaptiveMultiple consecutive captures with timestamps
FenergyDetectoradaptiveTransmit-then-detect (loopback)
GpreambleDetectoradaptiveFrequency-scanning loop (WLAN channel scan)

If a generated pattern fires unreliably (timeout despite a real signal, false positives, or captures of noise/baseline), route into the threshold calibration sub-workflow — see the per-pattern calibration notes in references/patterns.md and the procedure in references/threshold-calibration.md.

Guardrails

Organized by when they apply: Always rules fire on every generation, Ask First rules pause for the user, Never rules trigger a refusal and redirect.

Always
  • Use a radioName variable from user input — never hardcode radio names.

  • Begin every pattern with clear ed pd — releases any prior radio lease regardless of detector class. The same physical radio can be held by either an energyDetector or a preambleDetector object; clearing only one variable name does not release a lease held by the other, which causes validateLeaseOwner errors when patterns are pasted sequentially into the same MATLAB session.

  • Validate threshold ranges before generating code — see references/api.md for exact valid ranges per parameter (key: energyDetector FixedThreshold [0, 8191], preambleDetector FixedThreshold [0, 4095]). If a value is out of range, state the valid range and do not emit the code.

  • End every generated code block with a %% Verify section that reports the outcome and prints the sanity ratio r (formulas in the table above). Do NOT hard-assert on status: a timeout (status == 0) is an expected result to handle (warn + route to calibration), not a crash — a hard assert makes a no-signal bench run throw.

  • Run the generated script once — do not re-run it to "confirm." This caps whole-script runs, not the loops inside one run: let Pattern E complete all NumCaptures captures and let Pattern G finish every channel in its scan loop. Once %% Verify reports success (status == 1, or status > 0 for multi-capture) and the printed r clears its threshold — or, for a wideband chirp/OFDM signal, the matched-filter ratio confirms it — the task is done. Do NOT execute the full deliverable again end-to-end or re-open plotDetectionSignals / plotThreshold to double-check — each extra radio round-trip costs real seconds and risks a timeout. Only exception: the user reports earlier inconsistent firing (sub-workflow trigger 3), where a short repeat is allowed — see Exit Criteria in references/threshold-calibration.md.

  • Use transmit() / stopTransmission() on the detector object for transmit-then-detect — do NOT create a separate basebandTransmitter.

  • Set ThresholdMethod before calling transmit() — you cannot switch fixed↔adaptive during a continuous transmission (it errors: "stop the ongoing transmission first"). MinimumEnergy, EnergyDeltaThreshold, and FixedThreshold can be tuned live, so sweep those without stopping.

  • Match the calibration plot to the detector class — plotDetectionSignals is energyDetector-only; plotThreshold is preambleDetector-only. Never cross them.

  • Normalize any custom or random preamble into [-1, 1] before assigning pd.Preamble. Preamble elements must lie in [-1, 1] (references/api.md). Zadoff-Chu via seq / norm(seq, 2) already satisfies this; for a random or protocol-derived sequence, scale it with preamble = preamble / max(abs(preamble)) — raw randn/sample values overflow [-1, 1] and error at assignment.

Ask First
  • When the detection method is unstated, ask before generating — do not default to energy detection. The absence of a preamble in the request is not evidence for energy detection. If the request names no explicit energy/power cue, no preamble/correlation sequence, and no threshold parameters, ask one question covering both the method (energy vs. preamble) and its parameters, then proceed. If the method is clear and only parameters are missing, ask once for those.

Never
  • Never generate untriggered capture — if the user wants immediate capture without detection, redirect to matlab-transmit-capture-usrp.

  • Never generate streaming code — if the user wants continuous real-time processing, redirect to the streaming workflow (use the matlab-read-documentation skill for "Live Data I/O", Wireless Testbench).


Copyright 2026 The MathWorks, Inc.


Files

references/threshold-calibration.md

Threshold Calibration — Sub-Workflow

Calibration sub-procedure for energyDetector (plotDetectionSignals) and preambleDetector (plotThreshold). Load this file when the parent skill (matlab-detect-capture-usrp) routes a calibration request, or when a generated Pattern fires unreliably (timeouts despite a real signal, false positives on noise, captures of pure baseline, or status=1 with garbage data).

When to Apply This Sub-Workflow

Route in when any of these failure modes are observed:

Failure modeSymptomSub-workflow handles
No detectionstatus == 0 (capture timed out, no data) when a signal was expectedStep 1: read plotDetectionSignals or plotThreshold figure to check whether thresholds are above peaks (false negative) or whether the RF path is dead
Wrong detectionstatus >= 1 but captured data is noise, baseline, saturated (max(abs(data)) near 1.414), or sanity ratio fails (ED: r < 50; PD: r < 100)Step 4: post-capture sanity check; falls back to Step 3 false-positive recovery
Unstable detectionSame Pattern fires inconsistently across 5 consecutive runs (sometimes status=0, sometimes status=1)Step 3: add ≥6 dB margin to whichever threshold is on the boundary
Explicit calibration requestUser says "calibrate", "tune thresholds", "tune detection", "fix detection", "why didn't it detect", "diagnose", or names plotDetectionSignals / plotThresholdWhichever step matches the symptom they describe

Do NOT apply when:

  • The RF path itself is unverified (no cable / wrong antenna / wrong frequency / wrong gain). Calibration cannot fix RF problems — exit and fix the path first. (Step 1 will detect this when neither curve has any peaks.)

  • The user is only generating new code and has not yet run it. Generate the Pattern, run it, then route in here only on a failure outcome.

Pre-Conditions

RequiredWhy
Detector object already created and configuredCalibration reads back live curves from the radio
TX is running (or a known external signal present)Both plotDetectionSignals and plotThreshold need a signal to plot against
RF path proven (Pattern B fixed-threshold caught at least one signal previously)Distinguishes "threshold problem" from "RF problem"

Sub-Workflow A: energyDetector Calibration (Patterns A / B / E / F)

energyDetector has two thresholds (MinimumEnergy absolute floor + EnergyDeltaThreshold relative dB ratio). Both must clear, so calibration tunes whichever knob the figure shows is blocking.

Step 0 — Measure the real energy scale first

Absolute energy is radio-, gain-, and signal-specific. On an N310 SMA loopback the integrated energy (window 300) measured ≈ 6e-5 at RadioGain 30, ≈ 3e-4 at 45, ≈ 0.01 at 60, ≈ 0.1 at 70 — orders of magnitude below the OTA example values, and it never reaches ~4. RadioGain scales signal and noise together, so it does not improve SNR; TransmitGain does.

So do not hardcode MinimumEnergy / FixedThreshold. Read the real level once, then set from it:

Set ThresholdMethod before transmission starts — switching fixed<->adaptive during a continuous transmission errors ("stop the ongoing transmission first"). If TX is already running, call stopTransmission(ed) first, set the method, then transmit again.

% 1. Set the method BEFORE transmitting (see the SKILL.md Always rule).
ed.ThresholdMethod = "fixed";
ed.FixedThreshold = 1e-9;                          % tiny -> triggers immediately

% 2. Start TX now (Pattern F), or confirm the external signal is on the air.

% 3. Grab one reference capture. Guard it: a timeout returns empty data.
[x, ~, ~, status] = capture(ed, milliseconds(3), seconds(2));
if status >= 1 && ~isempty(x)
    if iscell(x)                                   % NumCaptures > 1 returns a cell array
        x = x{1};
    end
    peakEnergy = max(movsum(abs(double(x)).^2, ed.WindowLength));  % same units as the thresholds
    ed.FixedThreshold = 0.3 * peakEnergy;          % fixed: ~1/4-1/2 of the measured peak
else
    warning("Reference capture timed out - no energy to measure. Check the RF path (Step 1) first.");
end

Adaptive alternative — also set it before transmitting: ed.ThresholdMethod = "adaptive" with ed.MinimumEnergy = 0, and let EnergyDeltaThreshold (dB rise) trigger. That is scale-invariant, so it needs no reference capture at all.

Prefer adaptive over loopback: the dB-rise trigger fires whatever the absolute scale, so you avoid chasing a moving absolute threshold.

Step 1 — Always: Read the curves

With signal present (or TX running for transmit-then-detect):

plotDetectionSignals(ed, milliseconds(2));

Read off the figure:

ObservationInterpretation
Integrated Signal Energy curve does not touch Minimum Energy Threshold lineMinE too high -> false negative
Energy Delta curve never crosses Energy Delta Threshold, but shows clear positive peaksDelta too high -> false negative (real signal, threshold sits above it)
Energy Delta swings roughly symmetrically about 0 (e.g. ±1.4 dB) with flat Integrated Signal EnergyNoise jitter, not a weak signal. Do NOT lower the threshold — you will fire on noise. On a loopback with no transmitter the cable is passive (nothing arrives): switch to transmit-then-detect (Pattern F).
Neither curve has any peaksRF path issue (cable / antenna / gain / frequency, not threshold) — exit this sub-workflow
Step 2 — False-negative recovery

First rule out noise jitter (Step 1: a symmetric Delta swing about 0 is noise, not a weak signal — do not chase it down; over a passive loopback go straight to transmit-then-detect). Then halve whichever knob the figure shows is blocking.

  • MinimumEnergy: set to 0 and let EnergyDeltaThreshold trigger (the absolute energy is tiny and gain-dependent — see Step 0). If a floor is needed to reject noise jitter, measure the signal energy first and set the floor below it — do not hardcode a decade value

  • EnergyDeltaThreshold in dB progression: 3 -> 1.5 -> 0.5 dB until the Delta curve crosses threshold

Step 3 — False-positive recovery
  • Raise EnergyDeltaThreshold x2: 3 -> 6 -> 12 dB until threshold sits well above the noise band's natural jitter

  • Raise MinimumEnergy one decade if noise leaks through: 1e-6 -> 1e-4 -> 1e-2

  • Leave at least 6 dB of Delta margin between observed signal Delta and chosen threshold — the boundary is jittery

Step 4 — Post-capture sanity

After a successful capture:

if iscell(data)          % NumCaptures > 1 returns a cell array - score one capture
    data = data{1};
end
r = max(abs(data).^2) / median(abs(data).^2);
RatioVerdict
r >= 50Real signal — calibration is good
r < 50Likely false positive (caught noise, not signal) — raise Delta or MinE and re-run — unless the signal is wideband, see below

Wideband / chirp exception. A wideband, low-duty-cycle signal (e.g. a chirp) spreads its energy over time, so the raw max/median ratio under-reports — r ≈ 15–20 is normal for a real chirp and is not a false positive. For such signals the authoritative check is a matched filter against one period of the known transmit template:

template = knownPeriod / norm(knownPeriod);   % one period of the TX waveform (e.g. the chirp)
mf = abs(filter(conj(flipud(template)), 1, data));
mfRatio = max(mf).^2 / median(mf).^2;         % real wideband signal: >> 100 (noise: ~1)

Trust the matched-filter ratio for chirps/wideband; do not re-tune the threshold on a low raw r alone, and do not launch a multi-run investigation — one confirming capture plus this matched-filter check is enough.

Sub-Workflow B: preambleDetector Calibration (Patterns C / D / G)

preambleDetector triggers when correlator output power exceeds AdaptiveThresholdGain * avgPower + AdaptiveThresholdOffset (adaptive) or FixedThreshold (fixed).

Step 1 — Always: Read the threshold curve

With TX running (or external signal present):

plotThreshold(pd, milliseconds(1));

Read off the figure:

ObservationInterpretation
Correlation peaks visible AND threshold curve sits above peaksGain too high -> false negative
Correlation peaks visible AND threshold curve sits below noise bandGain too low -> false positive
No correlation peaks at allRF path issue — exit this sub-workflow
Step 2 — False-negative recovery

Halve AdaptiveThresholdGain until the threshold curve drops below the correlation peaks but stays above the noise band:

8 -> 4 -> 2 -> 1 -> 0.5
Step 3 — False-positive recovery
  • Raise AdaptiveThresholdGain x2 progression until the threshold curve clears the noise band

  • If margin remains tight, add a small AdaptiveThresholdOffset (start 0.1)

Step 4 — Post-capture sanity

After a successful capture:

if iscell(data)          % NumCaptures > 1 returns a cell array - score one capture
    data = data{1};
end
matched = filter(conj(flipud(pd.Preamble)), 1, data);
peak = max(abs(matched).^2);
base = median(abs(matched).^2);   % median is base MATLAB - no extra toolbox needed
r = peak / base;
RatioVerdict
r > 100Real preamble fire
50 <= r <= 100Marginal — real fire but tight; consider raising Gain
r < 50Likely false positive (caught noise, not preamble) — raise Gain or add Offset and re-run

Diagnostic rule of thumb: real preamble fires sit peak/baseline > 100; false positives cluster around 17.

Symptom -> Cause -> Fix (combined ED + PD)

SymptomLikely causeFirst diagnosticFix
status=0 always (timeout, PD)Threshold above peak (Gain too high) or RF path deadplotThresholdCorrelation peaks visible but no trigger markers -> halve Gain (8 -> 4 -> 2 -> 1 -> 0.5). No peaks at all -> check antennas, gains, frequency, cable.
status=1 but data is noise (PD)Gain too low, fired on baselineOffline peak/baseline ratio after captureRatio < 50 -> raise Gain x2 or add small Offset (start 0.1).
status=1 but max|data| ~= 1.414RX saturated (RadioGain too high or TX too strong)max(abs(data)) checkReduce RadioGain by 10-20 dB. Loopback ceiling is RadioGain=60 dB at TxGain=50 dB.
Adaptive Gain=8 always times out over loopbackQuiet baseline -> 8 * ~0 collapses to Offset; peaks are also smallLoopback sweep evidenceUse Gain=0.5, Offset=0 for loopback (working window 0.1-0.9, sharp boundary at 1.0).
OTA Gain=0.5 constant false positivesReal noise floor lifts moving avg; 0.5 * avg sits below peaksplotThreshold shows triggers in non-signal regionsRaise Gain to 4-16 OTA range; add Offset 0.1-0.5 if margin tight.
ED status=0 always (Pattern A/E/F)MinE > integrated energy OR Delta > observed peak ratio OR RF path deadplotDetectionSignals(ed, milliseconds(2))Energy curve doesn't touch MinE line -> halve MinE (decade). Delta curve never crosses Delta threshold -> halve Delta (3 -> 1.5 -> 0.5 dB). Neither curve has peaks -> RF path issue.
ED status=1 but data is noiseDelta too low + tiny MinE -> baseline jitter clearedOffline r = max(abs(data).^2) / median(abs(data).^2)If r < 50, raise Delta x2 (3 -> 6 -> 12 dB) or raise MinE one decade.
ED weak-signal jittery boundaryLiving on FN edge of EnergyDeltaThresholdRun capture 5x and count fires; if non-deterministicAdd 6+ dB Delta margin: if observed Delta is 22 dB, set threshold to 12-15 dB.

Tool Restrictions (from parent skill guardrails)

  • plotDetectionSignals is for energyDetector ONLY — never call on a preambleDetector

  • plotThreshold is for preambleDetector ONLY — never call on an energyDetector

Exit Criteria

Calibrate in a single pass, then STOP. Do not re-run the full sweep chasing a perfect score, and do not re-execute the deliverable to "double-check" — over a quiet loopback the trigger boundary is naturally jittery, and every extra radio round-trip costs real seconds. Chasing a flawless run is the main cause of calibration timeouts.

Calibration is COMPLETE — return to the parent skill with the calibrated values — as soon as, in one pass:

  • The relevant figure shows the threshold curve sitting between the noise band and the signal peaks, AND

  • One test capture returns status == 1 and the post-capture check passes: the sanity ratio r clears the threshold (>= 50 for ED, > 100 for PD), or — for a wideband chirp/OFDM signal — the matched-filter ratio confirms the signal (Step 4). That single confirming capture is enough evidence.

Then STOP. Once that confirming capture has fired:

  • Do not re-run the full deliverable end-to-end again "to confirm" — the calibration capture already proved it fires. The deliverable is the calibrated parameter values, not one more live run.

  • Do not re-open plotDetectionSignals / plotThreshold after success.

  • A determinism check (repeating the capture 3-5 times) is optional — run it only if you actually saw inconsistent firing. If you do, a single boundary miss (e.g. 4/5) over a marginal loopback is acceptable: accept it, or apply one margin step (ED: raise EnergyDeltaThreshold by 6 dB; PD: set AdaptiveThresholdOffset = 0.1) and stop. Do NOT keep re-sweeping toward a perfect 5/5. For a wideband signal the matched-filter check already confirms a real detection — do not also run a determinism sweep.

Return to the parent skill (matlab-detect-capture-usrp) Pattern code with the calibrated parameter values.


Copyright 2026 The MathWorks, Inc.


Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
MathWorks
Publisher
MathWorks (Official)
Source
matlab/matlab-agentic-toolkit · skills-catalog/wireless-communications/matlab-detect-capture-usrp · commit 2a7f215
Licence
BSD 2-Clause License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE.md)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by MathWorks or MathWorks.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-detect-capture-usrp.zip