Matlab Detect Capture Usrp
MathWorksOfficialCreated by MathWorks
- Skill
- Tool integration
- Software development
- BSD-2-Clause
- No issues found
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
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/matlab/matlab-detect-capture-usrp/downloadUnzip 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.mdbefore generating any capture code.API reference (required at Step 3):
Read references/api.mdfor 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/plotThresholdstep-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-workflow | What 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:
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.Wrong detection — Pattern returned
status >= 1but the captured data is wrong: noise instead of signal, baseline instead of preamble, saturated waveform (max(abs(data))near1.414), or sanity ratio fails (r < 50for energyDetector,r < 100for preambleDetector).Unstable detection — the user reports, or an earlier run in this session already showed, that the Pattern fires inconsistently (sometimes
status=0, sometimesstatus=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.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.
| Detector | Formula the pattern prints | Real 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 ratio | matched-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 verificationCapture 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 sequencesCalibrate detection thresholds (
plotDetectionSignalsfor energyDetector,plotThresholdfor 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-usrpContinuous streaming (System objects, real-time processing loops) -> use the
matlab-read-documentationskill for "Live Data I/O" (Wireless Testbench)Radio setup or troubleshooting ->
matlab-set-up-usrp-radioClock/time synchronization -> use the
matlab-read-documentationskill for "Radio Management" (Wireless Testbench)FPGA targeting -> use the
matlab-read-documentationskill 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
| Function | Purpose | Toolbox | Available From |
|---|---|---|---|
energyDetector | Arm radio; trigger capture when energy rises above the noise floor | Wireless Testbench | R2023b |
preambleDetector | Arm radio; trigger capture on correlation with a known preamble | Wireless Testbench | R2022a |
capture | Blocking triggered IQ capture (returns on detection or timeout) | Wireless Testbench | with detector object |
capture(..., "NumCaptures", N) | Capture N consecutive triggered signals (Pattern E) | Wireless Testbench | R2024a |
plotDetectionSignals | Calibrate energy threshold — energyDetector only | Wireless Testbench | R2023b |
plotThreshold | Calibrate preamble threshold — preambleDetector only | Wireless Testbench | R2022a |
transmit / stopTransmission | Send / stop a test waveform on the detector object (Pattern F) | Wireless Testbench | with detector object |
zadoffChuSeq | Generate a Zadoff-Chu preamble sequence (Patterns C/D) | Communications Toolbox | R2012b |
wlanLLTF / wlanNonHTConfig | Build the WLAN L-LTF preamble (Pattern G) | WLAN Toolbox | R2015b |
chirp | Generate a test chirp waveform (Pattern F) | Signal Processing Toolbox | before R2006a |
Step 1: Determine Detector Type
Select on an explicit cue, not on the mere absence of a preamble.
| Signal | User says | Detector |
|---|---|---|
| Energy-based | explicit 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 sequence | preambleDetector |
| Ambiguous | only "detect a signal" / "capture when it appears" — no energy/power cue, no preamble, no threshold parameters | Ask first (Guardrails -> Ask First); do not default to energy |
Step 2: Gather Required Inputs
| Parameter | Required | Ask if missing |
|---|---|---|
| Radio name | Yes | Always |
| Center frequency | Yes | Yes |
| Sample rate | Yes | Yes |
| Threshold method | Yes | Yes (adaptive/fixed) |
| Threshold values | Yes | Yes |
| Capture duration | Yes | Yes |
| Timeout | Yes | Default seconds(1) if not specified |
| Preamble sequence | Only for preambleDetector | Yes |
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.
| Pattern | Detector | Threshold | Use case |
|---|---|---|---|
| A | energyDetector | adaptive | Wake-on-signal capture on an energy rise |
| B | energyDetector | fixed | Capture above a fixed power level |
| C | preambleDetector | adaptive | Capture on correlation with a known preamble |
| D | preambleDetector | fixed | Preamble capture / plotThreshold calibration |
| E | energyDetector | adaptive | Multiple consecutive captures with timestamps |
| F | energyDetector | adaptive | Transmit-then-detect (loopback) |
| G | preambleDetector | adaptive | Frequency-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
radioNamevariable 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 anenergyDetectoror apreambleDetectorobject; clearing only one variable name does not release a lease held by the other, which causesvalidateLeaseOwnererrors when patterns are pasted sequentially into the same MATLAB session.Validate threshold ranges before generating code — see
references/api.mdfor exact valid ranges per parameter (key: energyDetectorFixedThreshold[0, 8191], preambleDetectorFixedThreshold[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
%% Verifysection that reports the outcome and prints the sanity ratior(formulas in the table above). Do NOT hard-assertonstatus: 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
NumCapturescaptures and let Pattern G finish every channel in its scan loop. Once%% Verifyreports success (status == 1, orstatus > 0for multi-capture) and the printedrclears 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-openplotDetectionSignals/plotThresholdto 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 inreferences/threshold-calibration.md.Use
transmit()/stopTransmission()on the detector object for transmit-then-detect — do NOT create a separatebasebandTransmitter.Set
ThresholdMethodbefore callingtransmit()— you cannot switch fixed↔adaptive during a continuous transmission (it errors: "stop the ongoing transmission first").MinimumEnergy,EnergyDeltaThreshold, andFixedThresholdcan be tuned live, so sweep those without stopping.Match the calibration plot to the detector class —
plotDetectionSignalsis energyDetector-only;plotThresholdis preambleDetector-only. Never cross them.Normalize any custom or random preamble into [-1, 1] before assigning
pd.Preamble.Preambleelements must lie in [-1, 1] (references/api.md). Zadoff-Chu viaseq / norm(seq, 2)already satisfies this; for a random or protocol-derived sequence, scale it withpreamble = preamble / max(abs(preamble))— rawrandn/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-documentationskill for "Live Data I/O", Wireless Testbench).
Copyright 2026 The MathWorks, Inc.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.1 KiB
- LICENSELicence file added by AutoGineer1.4 KiB
- SKILL.md15.8 KiB
- manifest.yaml699 B
- references/api.md6.3 KiB
- references/overview.md4.1 KiB
- references/patterns.md18.7 KiB
- references/threshold-calibration.md13.8 KiB
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 mode | Symptom | Sub-workflow handles |
|---|---|---|
| No detection | status == 0 (capture timed out, no data) when a signal was expected | Step 1: read plotDetectionSignals or plotThreshold figure to check whether thresholds are above peaks (false negative) or whether the RF path is dead |
| Wrong detection | status >= 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 detection | Same 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 request | User says "calibrate", "tune thresholds", "tune detection", "fix detection", "why didn't it detect", "diagnose", or names plotDetectionSignals / plotThreshold | Whichever 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
| Required | Why |
|---|---|
| Detector object already created and configured | Calibration 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.");
endAdaptive 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:
| Observation | Interpretation |
|---|---|
Integrated Signal Energy curve does not touch Minimum Energy Threshold line | MinE too high -> false negative |
Energy Delta curve never crosses Energy Delta Threshold, but shows clear positive peaks | Delta 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 Energy | Noise 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 peaks | RF 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 letEnergyDeltaThresholdtrigger (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 valueEnergyDeltaThresholdin dB progression:3 -> 1.5 -> 0.5dB until the Delta curve crosses threshold
Step 3 — False-positive recovery
Raise
EnergyDeltaThresholdx2:3 -> 6 -> 12dB until threshold sits well above the noise band's natural jitterRaise
MinimumEnergyone decade if noise leaks through:1e-6 -> 1e-4 -> 1e-2Leave 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);| Ratio | Verdict |
|---|---|
r >= 50 | Real signal — calibration is good |
r < 50 | Likely 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 rawmax/medianratio under-reports —r ≈ 15–20is 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
ralone, 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:
| Observation | Interpretation |
|---|---|
| Correlation peaks visible AND threshold curve sits above peaks | Gain too high -> false negative |
| Correlation peaks visible AND threshold curve sits below noise band | Gain too low -> false positive |
| No correlation peaks at all | RF 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.5Step 3 — False-positive recovery
Raise
AdaptiveThresholdGainx2 progression until the threshold curve clears the noise bandIf margin remains tight, add a small
AdaptiveThresholdOffset(start0.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;| Ratio | Verdict |
|---|---|
r > 100 | Real preamble fire |
50 <= r <= 100 | Marginal — real fire but tight; consider raising Gain |
r < 50 | Likely 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)
| Symptom | Likely cause | First diagnostic | Fix |
|---|---|---|---|
status=0 always (timeout, PD) | Threshold above peak (Gain too high) or RF path dead | plotThreshold | Correlation 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 baseline | Offline peak/baseline ratio after capture | Ratio < 50 -> raise Gain x2 or add small Offset (start 0.1). |
status=1 but max|data| ~= 1.414 | RX saturated (RadioGain too high or TX too strong) | max(abs(data)) check | Reduce RadioGain by 10-20 dB. Loopback ceiling is RadioGain=60 dB at TxGain=50 dB. |
Adaptive Gain=8 always times out over loopback | Quiet baseline -> 8 * ~0 collapses to Offset; peaks are also small | Loopback sweep evidence | Use Gain=0.5, Offset=0 for loopback (working window 0.1-0.9, sharp boundary at 1.0). |
OTA Gain=0.5 constant false positives | Real noise floor lifts moving avg; 0.5 * avg sits below peaks | plotThreshold shows triggers in non-signal regions | Raise 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 dead | plotDetectionSignals(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 noise | Delta too low + tiny MinE -> baseline jitter cleared | Offline 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 boundary | Living on FN edge of EnergyDeltaThreshold | Run capture 5x and count fires; if non-deterministic | Add 6+ dB Delta margin: if observed Delta is 22 dB, set threshold to 12-15 dB. |
Tool Restrictions (from parent skill guardrails)
plotDetectionSignalsis forenergyDetectorONLY — never call on apreambleDetectorplotThresholdis forpreambleDetectorONLY — never call on anenergyDetector
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 == 1and the post-capture check passes: the sanity ratiorclears the threshold (>= 50for ED,> 100for 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/plotThresholdafter 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
EnergyDeltaThresholdby 6 dB; PD: setAdaptiveThresholdOffset = 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.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-detect-capture-usrp.zip