Generated banner for Matlab Generate Ble Waveform
Generated logo for Matlab Generate Ble Waveform

Matlab Generate Ble Waveform

MathWorksOfficialCreated by MathWorks

  • Skill
  • Tool integration
  • Science and research
  • BSD-2-Clause
  • No issues found

From the author

Generate Bluetooth Low Energy (BLE) PHY waveforms. Read BEFORE writing any BLE waveform code to avoid hallucinating API patterns. Covers bleWaveformGenerator, bleIdealReceiver, bleCTEIQSample, bleAngleEstimate, bluetoothTestWaveform for LE1M/LE2M/LE500K/LE125K. Bluetooth Toolbox R2022a+.
— the description by MathWorks

AutoGineer summary

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

This skill provides a structured approach to generating, simulating, and analyzing Bluetooth Low Energy (BLE) physical layer waveforms. It covers the use of core MATLAB functions such as bleWaveformGenerator, bleIdealReceiver, and bleAngleEstimate to support tasks ranging from basic waveform creation to complex direction-finding (CTE) pipelines, RF-PHY compliance testing, and BER simulations. The skill emphasizes correct configuration for LE1M, LE2M, and Coded PHY modes while adhering to Bluetooth 5.1+ specifications.

What it does

  • Generates BLE PHY waveforms for LE1M, LE2M, LE500K, and LE125K modes.
  • Simulates direction-finding pipelines using Constant Tone Extension (CTE) for AoA/AoD.
  • Performs RF-PHY compliance testing and transmitter measurements like PAPR and OBW.
  • Models receiver performance through BER simulations and WLAN coexistence scenarios.
  • Configures advertising and data channel PDUs with custom access addresses and whitening.
  • Provides visualization patterns for IQ samples and spectral analysis.

When to use it

  • When generating BLE PHY waveforms for simulation or testing.
  • When implementing direction-finding (AoA/AoD) using CTE.
  • When performing RF-PHY compliance or transmitter performance measurements.
  • When simulating receiver sensitivity and BER under noise or interference.
  • When comparing different BLE PHY modes or analyzing spectral characteristics.

Advantages

  • Ensures adherence to BLE specification constraints regarding PHY modes and channels.
  • Provides standardized patterns for complex tasks like CTE pipelines and multi-packet bursts.
  • Prevents common API hallucinations by enforcing correct parameter usage.
  • Includes robust conventions for spectral analysis and visualization.
  • Facilitates accurate simulation of practical receiver impairments.

Usage examples

“Generate an LE2M BLE waveform for channel 15 with a random payload.”
The agent provides a script using bleWaveformGenerator with Mode set to 'LE2M' and ChannelIndex set to 15, ensuring the symbol rate is correctly calculated as 2 Msym/s.
“How do I simulate a CTE connection-oriented packet for direction finding?”
The agent provides a code snippet using bleWaveformGenerator with DFPacketType set to 'ConnectionCTE', followed by the appropriate IQ sampling and angle estimation workflow.
“Show me how to calculate the Bit Error Rate for an LE1M signal.”
The agent generates a loop-based script that iterates through SNR values, applies AWGN to the generated waveform, and uses bleIdealReceiver to calculate the error rate.
“Can I use LE2M for advertising on channel 37?”
The agent correctly identifies this as a specification violation and refuses the request, explaining that advertising channels (37-39) are restricted to LE1M or Coded PHYs.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/matlab/matlab-generate-ble-waveform/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip matlab-generate-ble-waveform.zip -d .agents/skills

Documentation by MathWorks

BLE Waveform Generation

Routing

IntentCuesPattern
Basic generation"generate", "waveform"Single-Mode
Compare modes"compare", "all modes"All-Mode
Direction finding"CTE", "AoA", "AoD"CTE
RF-PHY compliance"compliance", "RF-PHY"RF-PHY Test
Coexistence"WLAN", "interference"WLAN Coexistence
TX measurements"PAPR", "OBW", "power"TX Measurements
Localization"RSSI", "beacon", "distance"RSSI Localization
BER/receiver"BER", "noise", "sensitivity"BER Simulation
Multi-packet"burst", "IFS"Multi-Packet
Spectrum"spectrum", "spectral mask"Spectral Analysis
Whitening"whitening", "scrambling"Whitening Comparison
Impairments"CFO", "practical", "realistic"End-to-End

Default (ambiguous request): LE1M, 37-byte payload, channel 37.

When To Use

Use this skill when the user asks to generate, simulate, or analyze BLE PHY-layer waveforms — including mode comparisons, CTE/direction finding, RF-PHY compliance testing, BER simulations, TX measurements, WLAN coexistence, or RSSI localization. Applies to any task involving bleWaveformGenerator, bleIdealReceiver, bleCTEIQSample, bleAngleEstimate, or bluetoothTestWaveform.

When Not To Use

  • BR/EDR (Classic Bluetooth) → use bluetoothWaveformGenerator (covered by a separate BR/EDR skill)

  • Channel Sounding (CS) → use bleCSWaveform(bleCSConfig) (R2024b+); CS has its own ranging/distance-measurement pipeline and is not part of PHY waveform generation

  • Network-level simulation → use bluetoothLENode for link-layer/network modeling

  • Path loss modeling → use bluetoothPathLoss for propagation/channel modeling

PHY Modes

ModesymbolRateData RateCodingDuration (37 B)
"LE1M"1e61 MbpsNone~336 us
"LE2M"2e62 MbpsNone~172 us
"LE500K"1e6500 kbpsFEC S=2~974 us
"LE125K"1e6125 kbpsFEC S=8~2768 us

References

For detailed guidance beyond what's in this file, see:

Parameters (bleWaveformGenerator)

ParamDefaultRange
Mode"LE1M"LE1M, LE2M, LE500K, LE125K
ChannelIndex370-39
SamplesPerSymbol8>=1 (use >=4 for plots)
WhitenStatus"On"On, Off
DFPacketType"Disabled"Disabled, ConnectionCTE, ConnectionlessCTE
AccessAddressadv default32-bit binary col vector
ModulationIndex0.5[0.45, 0.55]
PulseLength1[1, 4]

Core Recipe

messageBits = randi([0 1], payloadLenBytes*8, 1);
waveform = bleWaveformGenerator(messageBits, ...
    Mode=phyMode, SamplesPerSymbol=sps, ...
    ChannelIndex=ch, WhitenStatus="On");
symbolRate = 1e6 + 1e6*(phyMode=="LE2M");
fs = symbolRate * sps;

Patterns

All-Mode Comparison
phyModes = ["LE1M","LE2M","LE500K","LE125K"];
sps = 8;
messageBits = randi([0 1], 37*8, 1);
figure; tl = tiledlayout(4,2,TileSpacing="compact",Padding="compact");
title(tl,"BLE - All PHY Modes")
for idx = 1:4
    wf = bleWaveformGenerator(messageBits, ...
        Mode=phyModes(idx), SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
    sr = 1e6 + 1e6*(phyModes(idx)=="LE2M");
    fs = sr*sps; t = (0:length(wf)-1)/fs*1e6;
    nexttile; plot(t,real(wf),t,imag(wf))
    xlabel("Time (\mus)"); ylabel("Amplitude"); title(phyModes(idx)+" - IQ")
    legend("I","Q"); grid on; xlim([0 min(80,t(end))])
    nexttile; N=length(wf); f=(-N/2:N/2-1)*(fs/N)/1e6;
    plot(f, 20*log10(abs(fftshift(fft(wf)))/N+eps))
    xlabel("Frequency (MHz)"); ylabel("dB"); title(phyModes(idx)+" - Spectrum")
    grid on; xlim([-3 3]); ylim([-80 0])
end
Multi-Packet Burst (T_IFS = 150 us)
sps = 8; fs = 1e6*sps;
messageBits = randi([0 1], 37*8, 1);
ifsGap = complex(zeros(round(150e-6*fs), 1));
burst = complex(zeros(0,1));
for pkt = 1:3
    wf = bleWaveformGenerator(messageBits, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37);
    burst = [burst; wf; ifsGap]; %#ok<AGROW>
end
Round-Trip Decode
messageBits = randi([0 1], 37*8, 1); sps = 8;
wf = bleWaveformGenerator(messageBits, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
rxBits = bleIdealReceiver(wf, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
assert(isequal(rxBits, messageBits))
Data Channel + Custom Access Address
accessAddr = randi([0 1], 32, 1);
wf = bleWaveformGenerator(randi([0 1],27*8,1), ...
    Mode="LE2M", SamplesPerSymbol=8, ChannelIndex=9, ...
    AccessAddress=accessAddr, WhitenStatus="On");
fs = 2e6 * 8;
CTE Generation
messageBits = randi([0 1], 20*8, 1); sps = 8; fs = 1e6*sps;
wf_noCTE = bleWaveformGenerator(messageBits, Mode="LE1M", ...
    SamplesPerSymbol=sps, ChannelIndex=10, WhitenStatus="On");
wf_conn = bleWaveformGenerator(messageBits, Mode="LE1M", ...
    SamplesPerSymbol=sps, ChannelIndex=10, WhitenStatus="On", DFPacketType="ConnectionCTE");
wf_cless = bleWaveformGenerator(messageBits, Mode="LE1M", ...
    SamplesPerSymbol=sps, ChannelIndex=10, WhitenStatus="On", DFPacketType="ConnectionlessCTE");

% CTE appends unmodulated constant tone for antenna switching (typ. 72-216 us)
cteDelta_conn_us = (length(wf_conn) - length(wf_noCTE)) / fs * 1e6;
cteDelta_cless_us = (length(wf_cless) - length(wf_noCTE)) / fs * 1e6;
CTE Full Pipeline (Tx → Rx → Angle)
pduHex = '02049B03270102030405';  % 10-byte PDU (>=6 bytes needed for >=11 IQ samples)
pdu = int2bit(hex2dec(reshape(pduHex, 2, [])'), 8, false);
pdu = pdu(:);
cfgCRC = crcConfig(Polynomial="z^24+z^10+z^9+z^6+z^4+z^3+z+1", ...
    InitialConditions=int2bit(hex2dec('555551'),24), DirectMethod=true);
pduCRC = crcGenerate(pdu, cfgCRC);
txWf = bleWaveformGenerator(pduCRC, ChannelIndex=36, DFPacketType="ConnectionlessCTE");
[~, ~, iqSamples] = bleIdealReceiver(txWf, ChannelIndex=36, ...
    DFPacketType="ConnectionlessCTE", SlotDuration=2);
cfgAngle = bleAngleEstimateConfig;
cfgAngle.ArraySize = 4; cfgAngle.SlotDuration = 2; cfgAngle.SwitchingPattern = [1 2 3 4];
angle = bleAngleEstimate(iqSamples, cfgAngle);

Alternative (R2022a+): iqSamples = bleCTEIQSample(cteSamples, Mode="LE1M", SlotDuration=2);

BER Simulation
messageBits = randi([0 1], 100*8, 1); sps = 8; phyMode = "LE1M";
snrValues = 0:4:20; berResults = zeros(size(snrValues));
for idx = 1:length(snrValues)
    wf = bleWaveformGenerator(messageBits, Mode=phyMode, SamplesPerSymbol=sps, ChannelIndex=5, WhitenStatus="On");
    sigPower = mean(abs(wf).^2);
    rxWf = awgn(wf, snrValues(idx), 10*log10(sigPower));
    rxBits = bleIdealReceiver(rxWf, Mode=phyMode, SamplesPerSymbol=sps, ChannelIndex=5, WhitenStatus="On");
    n = min(length(messageBits), length(rxBits));
    berResults(idx) = sum(messageBits(1:n) ~= double(rxBits(1:n))) / n;
end
semilogy(snrValues, berResults, "-o"); xlabel("SNR (dB)"); ylabel("BER"); grid on

bleIdealReceiver returns int8 — cast with double(). For Eb/No conversion: snr = convertSNR(EbNo,"ebno","snr",SamplesPerSymbol=sps).

RF-PHY Test Waveform
cfg = bluetoothTestWaveformConfig;
cfg.Mode = "LE1M"; cfg.PayloadLength = 37;
cfg.PacketType = "Disabled"; cfg.ModulationIndex = 0.5;
testWf = bluetoothTestWaveform(cfg);

rfCfg = bluetoothRFPHYTestConfig;
rfCfg.Test = "Output power"; rfCfg.Mode = "LE1M";
rfCfg.PayloadLength = 37; rfCfg.OutputPower = 0; rfCfg.CenterFrequency = "Mid";
WLAN Coexistence
sps = 8; fs = 1e6*sps;
bleWf = bleWaveformGenerator(randi([0 1],37*8,1), Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
t = (0:length(bleWf)-1)'/fs;
wlanInterferer = 0.1*complex(randn(length(bleWf),1),randn(length(bleWf),1)) .* exp(1j*2*pi*3e6*t);
combined = bleWf + wlanInterferer;
CIR_dB = 10*log10(mean(abs(bleWf).^2) / mean(abs(wlanInterferer).^2));
TX Measurements (Power, OBW, PAPR)
sps = 8; wf = bleWaveformGenerator(randi([0 1],255*8,1), Mode="LE1M", ...
    SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On", ModulationIndex=0.5);
fs = 1e6*sps; N = length(wf);
avgPower_dBm = 10*log10(mean(abs(wf).^2)) + 30;
spec = abs(fftshift(fft(wf))).^2; cumP = cumsum(spec)/sum(spec);
f = (-N/2:N/2-1)*(fs/N);
occBW_MHz = (f(find(cumP>=0.995,1)) - f(find(cumP>=0.005,1))) / 1e6;
papr_dB = 10*log10(max(abs(wf).^2) / mean(abs(wf).^2));
Whitening Comparison
bits = randi([0 1], 37*8, 1); sps = 8;
wfOn  = bleWaveformGenerator(bits, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
wfOff = bleWaveformGenerator(bits, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="Off");
Advertising PDU (ADV_IND)
cfgAdv = bleLLAdvertisingChannelPDUConfig;
cfgAdv.PDUType = "Advertising indication";
cfgAdv.AdvertiserAddress = "A1B2C3D4E5F6";
cfgAdv.AdvertiserAddressType = "Random";
cfgAdv.AdvertisingData = "0201060709546573744245020A00";
pduBits = bleLLAdvertisingChannelPDU(cfgAdv);
wf = bleWaveformGenerator(pduBits, Mode="LE1M", SamplesPerSymbol=8, ChannelIndex=37);

PDUType values: "Advertising indication", "Scan request", "Scan response", "Connection indication", "Advertising direct indication", "Advertising non connectable indication". Addresses: 12-char hex string (no colons). AdvertisingData: hex string (length-type-value AD structs).

Data Channel PDU
cfgData = bleLLDataChannelPDUConfig;
cfgData.LLID = "Data (start fragment/complete)";
cfgData.SequenceNumber = 1;
cfgData.NESN = 0;
cfgData.MoreData = false;
payload = dec2hex(randi([0 255], 50, 1))';  % 50-byte hex payload
payload = reshape(payload', 1, []);
pduBits = bleLLDataChannelPDU(cfgData, payload);
wf = bleWaveformGenerator(pduBits, Mode="LE2M", SamplesPerSymbol=8, ChannelIndex=15);

LLID values: "Data (continuation fragment/empty)", "Data (start fragment/complete)", "Control". SequenceNumber (not SN). Payload: hex string, numeric vector [0,255], or n×2 char array.

End-to-End (Practical Receiver)

Uses helperBLEPracticalReceiver (AGC + CFO + timing recovery). Requires: openExample('bluetooth/BLEPracticalReceiverExample'). SNR conversion for coded modes: SNR = EbNo + 10*log10(codeRate) - 10*log10(sps).

CTE Compatibility

ModeConnectionCTEConnectionlessCTE
LE1MYesYes
LE2MYesNo
LE500KNoNo
LE125KNoNo

CTE requires data channels (0-36). Never use ChannelIndex 37/38/39 with DFPacketType≠"Disabled". CTE is a data-channel-only feature.

Spec Constraints

  • Ch 37/38/39 (advertising): LE1M or LE Coded only. NOT LE2M.

  • CTE: LE1M/LE2M on data channels (0-36) only. Never coded PHY.

  • Access address: Advertising = '8E89BED6' (fixed); data = random.

  • Whitening init: Auto from ChannelIndex. Not settable.

  • T_IFS: 150 us. TX power: max +20 dBm. Mod index: 0.45-0.55.

  • bleIdealReceiver: Hard-decision only, returns int8.

  • "Slots" (1-slot, 3-slot, 5-slot): BR/EDR concept only. BLE has no slot-based packets.

  • ISO streams: Verify BN × IRC × Sub_Interval <= ISO_Interval. If math exceeds, REFUSE.

Invalid Combos (REFUSE these requests)
RequestWhy Invalid
LE2M + FEC codingFEC only exists in coded PHY (LE500K/LE125K)
LE2M on ch 37/38/39Primary advertising = LE1M or Coded only
CTE + LE500K/LE125KCTE restricted to LE1M/LE2M per BLE 5.1 spec
ConnectionlessCTE + LE2MConnectionlessCTE = LE1M only
"3-slot" or "5-slot" BLESlot-based = BR/EDR; BLE uses single packets
CTE on ch 37/38/39CTE = data channels (0-36) only
ISO params where BN×IRC×Sub_Int > ISO_IntervalSub-events exceed interval = impossible scheduling

Conventions

  • fs = (1e6 + 1e6*(mode=="LE2M")) * sps — never hardcode

  • Axes: us (time), MHz (freq), dB (power)

  • tiledlayout/nexttile (not subplot)

  • Spectrum: always 20*log10(abs(fftshift(fft(wf)))/N + eps) — do NOT use periodogram, pspectrum, or pwelch for BLE spectral plots

  • xlim([0 min(80,t(end))]) for coded modes

  • Plot both I and Q: plot(t, real(wf), t, imag(wf))

  • IFS gap: complex(zeros(N,1)) (output is complex)

  • SamplesPerSymbol>=4 for spectrum plots; SPS=1 is valid for generation but insufficient for visualization or accurate spectral analysis (at Nyquist limit)

Code Style

Generated scripts must follow MathWorks example conventions. Use %% section headers, softcode all parameters, and comment non-obvious logic.

Structure & Softcoding

Divide scripts with %% headers: Configuration → Waveform Generation → Processing → Analysis → Visualization. All user-configurable values as named variables at the top; no magic numbers in processing logic.

%% Configuration
% Specify BLE waveform generation parameters.

phyMode = "LE1M";                               % PHY transmission mode
payloadLength = 37;                             % Payload length in bytes
sps = 8;                                        % Samples per symbol
channelIndex = 37;                              % BLE channel index (0-39)

% Derived parameters
symbolRate = 1e6 + 1e6*(phyMode=="LE2M");       % 2 Msym/s for LE2M, 1 Msym/s otherwise
fs = sps * symbolRate;                          % Sample rate in Hz
numBits = payloadLength * 8;                    % Payload length in bits

%% Waveform Generation
% Generate BLE waveform from random payload bits.

messageBits = randi([0 1], numBits, 1);
waveform = bleWaveformGenerator(messageBits, ...
    Mode=phyMode, SamplesPerSymbol=sps, ChannelIndex=channelIndex);
Comments
  • Inline (right-aligned): units, range, or brief purpose — % Eb/No in dB

  • Block (above 2-5 lines): intent or why — % IFS gap must be complex (bleWaveformGenerator output is complex)

  • Constraints: spec reference — % LE2M uses 2 Msym/s (only mode with 2x symbol rate)

  • Do NOT comment self-evident lines, every line mechanically, or closing end statements

Naming
  • camelCase: messageBits, txWaveform, symbolRate, channelIndex

  • Descriptive loop counters: countMode, pktIdx (not i, j)

  • Named constants: bitsPerByte = 8, tIFS = 150e-6

  • Multi-init: [numErrors, perCount] = deal(0, 0)

Gotchas

MistakeFix
bleWaveformConfig(...)Does not exist. Use bleWaveformGenerator(bits, NV...) directly
bluetoothWaveformGenerator for BLEBR/EDR only. Use bleWaveformGenerator
comm.BLEReceiverDoes not exist. Use bleIdealReceiver
symbolRate=1e6 for LE2MLE2M = 2e6
'PHYMode' as param nameUse 'Mode'
'LECODED' as modeUse "LE500K" or "LE125K"
Config object as 1st argMust be binary col vector randi([0 1],N,1)
Empty [] bitsMinimum 1 byte
Real zeros() for IFSUse complex(zeros(N,1))
CTE + coded modesCTE only on LE1M/LE2M
ConnectionlessCTE + LE2MLE1M only
LE2M on ch 37/38/39Spec violation. Use LE1M or Coded
CTELength/CTEType as NV argsNot valid. Use DFPacketType
bleAngleEstimate(wf, NV...)Use bleAngleEstimate(iqSamples, bleAngleEstimateConfig)
bleWaveformGenerator for RF-PHYUse bluetoothTestWaveformConfig + bluetoothTestWaveform
AWGN without oversampling correctionUse convertSNR(EbNo,"ebno","snr",SamplesPerSymbol=sps); pass explicit power to awgn (never use "measured")
bleIdealReceiver with impairmentsUse helperBLEPracticalReceiver
Eb/No for coded modes without code rateSNR = EbNo + 10*log10(codeRate) - 10*log10(sps)
SPS=1 without warningSPS=1 is at Nyquist limit — warn user: no spectral analysis, marginal decode performance
Timing ppm offset without resampleApply clock drift via resample(wf, 1e6+ppm, 1e6) or fractional delay filter
Conformance Df1/Df2 without PRBS9Use comm.PNSequence (z^9+z^5+1) for TP/TRM/CA/BV-05-C; separate stable-bit (Df1) from alternating-bit (Df2) patterns
periodogram/pwelch for BLE spectrumUse manual fftshift(fft(wf)) — skill convention
SN as property nameUse SequenceNumber on bleLLDataChannelPDUConfig
Address with colons "A1:B2:..."Use 12-char hex string without colons: "A1B2C3D4E5F6"
PDUType="ADV_IND"Use full string: "Advertising indication"
Binary vector as AdvertisingDataUse hex string: "0201060709..." (length-type-value)

Copyright 2026 The MathWorks, Inc.

Files

references/functionalAPI.md

Bluetooth Toolbox — Functional API Reference

Verified against official MathWorks documentation (2026-05-21). Use this file to avoid re-fetching web docs for Bluetooth Toolbox functions.


1. bleWaveformGenerator (R2022a)

Purpose: Generate BLE PHY waveform from message bits.

Syntax
waveform = bleWaveformGenerator(message)
waveform = bleWaveformGenerator(message, Name=Value)
Input: message
  • Binary-valued column vector (PDU + CRC data)

  • Maximum length: 2088 bits

  • Data types: double | single | int8 | logical

Name-Value Arguments
ParameterDefaultValid ValuesNotes
Mode"LE1M""LE1M", "LE2M", "LE500K", "LE125K"PHY mode
ChannelIndex370-39Used by whitening block
SamplesPerSymbol8Positive integerGFSK modulation
WhitenStatus"On""On", "Off"Data whitening
DFPacketType"Disabled""Disabled", "ConnectionlessCTE", "ConnectionCTE"CTE enable
AccessAddressAdvertising default32-bit column vectorOverride access addr
ModulationIndex0.5[0.45, 0.55]GFSK mod index
PulseLength1[1, 4] symbol intervalsFrequency pulse shape
OutputDataType(inferred)"single", "double"Output precision
Output: waveform
  • Complex column vector (Ns-by-1)

  • LE1M/LE2M: includes 40 extra bits (access address + preamble)

  • Data types: double | single

Critical Notes
  • No config object. bleWaveformConfig does NOT exist.

  • CTE is NOT configured via CTELength/CTEType NV args. CTE parameters are encoded in the PDU bits. Only DFPacketType enables CTE processing.

  • First arg must be binary column vector, not struct/object.

  • Symbol rate: LE2M = 2 MHz, all others = 1 MHz.


2. bleIdealReceiver (R2022a)

Purpose: Decode BLE PHY waveform. Returns bits, access address, and optionally CTE IQ samples.

Syntax
[bits, accessAddr] = bleIdealReceiver(waveform)
[bits, accessAddr] = bleIdealReceiver(waveform, Name=Value)
[bits, accessAddr, IQsamples] = bleIdealReceiver(___)
Input: waveform
  • Complex column vector (Ns-by-1)

  • Minimum Ns by mode:

ModeMin NsMust be multiple of
LE1M40×spssps
LE2M48×spssps
LE500K376×sps2×sps
LE125K376×sps8×sps
Name-Value Arguments
ParameterDefaultValid ValuesNotes
Mode"LE1M""LE1M", "LE2M", "LE500K", "LE125K"Must match generator
ChannelIndex370-39Must match generator
SamplesPerSymbol8Positive integerMust match generator
WhitenStatus"On""On", "Off"Must match generator
DFPacketType"Disabled""Disabled", "ConnectionlessCTE", "ConnectionCTE"Enables IQ output
SlotDuration21, 2 (microseconds)CTE slot duration
ModulationIndex0.5[0.45, 0.55]GFSK trellis params
PulseLength1[1, 4]Frequency pulse shape
NoiseVariance1Positive scalar (linear)Input noise variance
Outputs
OutputDescriptionType
bitsRecovered payload bits (max 260 bytes)int8 column vector
accessAddr32-bit access addressint8 column vector
IQsamplesCTE IQ samples (only when DFPacketType != "Disabled")Complex column vector
Critical Notes
  • 3rd output (IQsamples) only returned when DFPacketType is set to CTE mode.

  • All NV args (Mode, ChannelIndex, SamplesPerSymbol, WhitenStatus) must match the generator settings.

  • Performs ideal (noiseless reference) demodulation — no receiver impairments modeled.


3. bleCTEIQSample (R2022a)

Purpose: Extract IQ samples from CTE portion of a BLE waveform by performing IQ sampling at reference period and each sample slot.

Syntax
iqSamples = bleCTEIQSample(cteSamples)
iqSamples = bleCTEIQSample(cteSamples, Name=Value)
Input: cteSamples
  • Complex column vector (CTE portion only, not full waveform)

  • Size constraints:

ModeNs rangeMust be multiple of
LE1M[16×sps, 160×sps]8×sps
LE2M[32×sps, 320×sps]16×sps
Name-Value Arguments
ParameterDefaultValid ValuesNotes
Mode"LE1M""LE1M", "LE2M"Only uncoded modes
SamplesPerSymbol8Positive integer—
SlotDuration21, 2 (microseconds)Switch/sample slot
SampleOffset4Depends on mode (see below)Sampling point offset

SampleOffset range:

ModeRange
LE1M[sps/8, 7×(sps/8)]
LE2M[sps/4, 7×(sps/4)]
Output: iqSamples
  • Complex column vector

  • Corresponds to 8 us reference period and SlotDuration

Critical Notes
  • Input is the CTE portion only — not the full BLE waveform.

  • Only LE1M and LE2M (no coded modes).

  • Alternative to using bleIdealReceiver 3rd output.


4. bleAngleEstimate (R2020b)

Purpose: Estimate AoA or AoD from IQ samples.

Syntax
angle = bleAngleEstimate(IQsamples, cfgAngle)

No name-value arguments. Only two positional inputs.

Input: IQsamples
  • Complex column vector

  • Corresponds to 8 us reference period and slot duration

  • Obtained from bleIdealReceiver (3rd output) or bleCTEIQSample

Input: cfgAngle
  • bleAngleEstimateConfig object (see below)

Output: angle
  • Scalar (azimuth only, when elevation = 0) OR

  • Two-element row vector [azimuth, elevation] (when custom array enabled)

Critical Notes
  • Does NOT take name-value args. Does NOT take a waveform directly.

  • Input must be pre-extracted IQ samples, not raw waveform.

  • Since R2020b (not R2021a).


5. bleAngleEstimateConfig (R2020b)

Purpose: Configuration object for bleAngleEstimate.

Syntax
cfgAngle = bleAngleEstimateConfig
cfgAngle = bleAngleEstimateConfig(Name=Value)
Properties
PropertyDefaultValid ValuesDescription
ArraySize—Integer >=2 (ULA) or [M,N] (URA)Antenna array size
ElementSpacing0.5Positive scalar <=0.5Normalized spacing (wavelengths)
SlotDuration21, 2Switch/sample slot (us)
SwitchingPattern—Integer vectorAntenna switching order
EnableCustomArrayfalsetrue/falseUse custom element positions
ElementPosition—3×N matrixNormalized positions (custom only)

6. bluetoothWhiten (System Object, R2022b)

Purpose: Whiten or dewhiten data bits using LFSR (x⁷+x⁴+1).

Creation
whiten = bluetoothWhiten
whiten = bluetoothWhiten(Name=Value)
Properties
PropertyDefaultValid ValuesTunable
InitialConditionsSource"Property""Property", "Input port"No
InitialConditions[1;1;1;1;1;1;1]7-bit binary column vector (>=1 nonzero)No
Calling
y = whiten(x)                    % uses InitialConditions property
y = whiten(x, initCondition)     % uses input port (requires InitialConditionsSource="Input port")
Notes
  • Same operation whitens and dewhitens (apply twice = original)

  • Channel-index-based init: initCond = [1; int2bit(channelIndex, 6)]

  • bleWaveformGenerator handles whitening internally when WhitenStatus="On"


7. bluetoothRFPHYTestConfig (R2022a)

Purpose: Configure BLE RF-PHY transmitter/receiver test parameters per RF-PHY.TS.p15.

Syntax
cfgRFPHYTest = bluetoothRFPHYTestConfig
cfgRFPHYTest = bluetoothRFPHYTestConfig(Name=Value)
Key Properties
PropertyDefaultValid Values
Test"Output Power"13 test types (see below)
Mode"LE1M""LE1M", "LE2M", "LE125K", "LE500K"
PayloadLength37[31, 255] bytes
PacketType"Disabled""Disabled", "ConnectionCTE"
CTELength2[2, 20] (×8 us)
CTEType[0;0][0;0]=AoA, [0;1]=AoD 2us, [1;0]=AoD 1us
SamplesPerSymbol8Positive integer
ArraySize4Integer >=2
ElementSpacing0.5<=0.5
ModulationIndex0.5[0.45, 0.55]
NumPackets1Positive integer

Test types: "Output Power", "Inband emissions", "Modulation characteristics", "Carrier frequency offset and drift", "Tx power stability", "C/I", "Blocking", "Intermodulation", "Receiver sensitivity", "Maximum input signal level", "PER report integrity", "IQ samples coherency", "IQ samples dynamic range"

Notes
  • This config goes to bluetoothTestWaveform (generation) and bluetoothTestWaveformValidate (validation).

  • CTELength/CTEType properties only available when PacketType="ConnectionCTE" and Mode is LE1M/LE2M.


8. bluetoothTestWaveformConfig (R2022a)

Purpose: Configure bluetoothTestWaveform for generating BR/EDR or LE test waveforms.

Syntax
cfgTestWaveform = bluetoothTestWaveformConfig
cfgTestWaveform = bluetoothTestWaveformConfig(Name=Value)
Key Properties
PropertyDefaultValid ValuesNotes
Mode"LE1M""LE1M", "LE2M", "LE125K", "LE500K", "BR", "EDR2M", "EDR3M"All BLE + BR/EDR
PayloadType0[0, 7]Test payload pattern
PayloadLength255[0, 255] bytesLE modes only
PacketType"Disabled"Mode-dependent (see below)Test packet type
SamplesPerSymbol8Positive integer—
WhitenStatus"On""On", "Off"—
WhitenInitialization[1;1;1;1;1;1;1]7-bit binary vectorWhen WhitenStatus="On"
ModulationIndex0.5[0.45,0.55] LE, [0.28,0.35] BR/EDR—
PulseLength1[1, 4]LE modes only (R2023a+)
CTELength2[2, 20]LE1M/LE2M + ConnectionCTE
CTEType[0;0][0;0], [0;1], [1;0]LE1M/LE2M + ConnectionCTE

PacketType by Mode:

  • LE1M/LE2M: "ConnectionCTE", "Disabled"

  • LE125K/LE500K: "Disabled" only

  • BR: "DH1", "DH3", "DH5", "DM1", "DM3", "DM5"

  • EDR2M: "2-DH1", "2-DH3", "2-DH5", "2-EV3", "2-EV5"

  • EDR3M: "3-DH1", "3-DH3", "3-DH5", "3-EV3", "3-EV5"


9. bluetoothTestWaveformValidate (R2024a)

Purpose: Validate BLE RF-PHY test waveform against test procedures.

Syntax (multiple forms based on test type)
crcError = bluetoothTestWaveformValidate(waveform, cfgRFPHYTest)
[waveformOut, avgFreqDev, avgCenterFreq, maxFreqDev] = bluetoothTestWaveformValidate(...)
[waveformOut, initFreqOffset, carrierFreqDrift] = bluetoothTestWaveformValidate(...)
[relativePhase, sumRelativePhase, angleRelativePhase, ...] = bluetoothTestWaveformValidate(...)
[meanAmpRefAntennas, meanAmpNonRefAntennas] = bluetoothTestWaveformValidate(...)
Inputs
ArgumentTypeDescription
waveformComplex Ns-by-NpTest waveform
cfgRFPHYTestbluetoothRFPHYTestConfigTest configuration
Minimum Ns by Mode
ModeMin NsMultiple of
LE1M248×spssps
LE2M256×spssps
LE500K1054×sps2×sps
LE125K3088×sps8×sps
Notes
  • Output structure depends on which test is configured in cfgRFPHYTest.

  • Validates: blocking, C/I, carrier freq offset/drift, intermod, IQ coherency, IQ dynamic range, modulation characteristics, PER integrity.


10. bluetoothPathLoss (R2022b)

Purpose: Estimate path loss between Bluetooth BR/EDR or LE devices.

Syntax
pathLoss = bluetoothPathLoss(distance, cfgPathLoss)
Inputs
ArgumentTypeDescription
distanceNonneg scalar or row vector (meters)Device separation
cfgPathLossbluetoothPathLossConfig objectPath loss config
Output
ArgumentTypeDescription
pathLossScalar or row vector (dB)Estimated loss

11. bluetoothPathLossConfig (R2022b)

Purpose: Configure path loss model for bluetoothPathLoss.

Syntax
cfgPathLoss = bluetoothPathLossConfig
cfgPathLoss = bluetoothPathLossConfig(Name=Value)
Properties
PropertyDefaultValid ValuesNotes
Environment"Outdoor""Home", "Industrial", "Office", "Outdoor"Selects model
TransmitterAntennaGain0[-10, 10] dBi—
ReceiverAntennaGain0[-10, 10] dBi—
TransmitterCableLoss0Nonneg (dB)—
ReceiverCableLoss0Nonneg (dB)—
TransmitterAntennaHeight1Positive (meters)Outdoor only
ReceiverAntennaHeight1Positive (meters)Outdoor only
PathLossExponent2.2Positive scalarIndustrial only
StandardDeviation2.667Nonneg (dB)Industrial/Outdoor
RandomStream"Global stream""Global stream", "mt19937ar with seed"—
Seed73Nonneg scalarWhen mt19937ar

PathLossModel (read-only, derived from Environment):

  • Outdoor → TwoRayGroundReflection

  • Industrial → LogNormalShadowing

  • Home/Office → NISTPAP02Task6


12. bleCSWaveform (R2024b)

Purpose: Generate BLE Channel Sounding PHY waveform.

Syntax
csPHYWaveform = bleCSWaveform(cfgChannelSounding)
[csPHYWaveform, accessAddress] = bleCSWaveform(cfgChannelSounding)
Input: cfgChannelSounding

A bleCSConfig object with properties:

  • Mode: "LE1M", "LE2M", "LE2M 2BT" (2BT since R2026a)

  • SamplesPerSymbol: positive integer

  • DeviceRole: "Initiator", "Reflector"

  • StepMode: 0, 1, 2, 3

  • ToneDuration: 80 (StepMode 0) or 10/20/40 (StepMode 2,3) microseconds

  • SequenceType: "Sounding Sequence", "Random Sequence"

  • SequenceLength: 32/96 (sounding) or 32/64/96/128 (random) bits

Outputs
OutputTypeDescription
csPHYWaveformComplex column vectorCS waveform
accessAddressint8 32-bit vectorCS DRBG access address
Notes
  • Completely separate from bleWaveformGenerator — different API, different config.

  • Guard duration fixed at 10 us.

  • LE2M uses 2x multiplicative factor for sample counts.


Function Availability Timeline

ReleaseFunctions Added
R2022ableWaveformGenerator, bleIdealReceiver
R2020bbleAngleEstimate, bleAngleEstimateConfig
R2022ableCTEIQSample, bluetoothRFPHYTestConfig, bluetoothTestWaveformConfig, bluetoothTestWaveform
R2022bbluetoothWhiten, bluetoothPathLoss, bluetoothPathLossConfig
R2024abluetoothTestWaveformValidate
R2024bbleCSWaveform, bleCSConfig
R2026ableCSConfig adds "LE2M 2BT" mode

CTE Workflow Summary (Verified)

1. Build PDU bits with CTE info encoded in header
2. Append CRC: crcGenerate(pdu, cfgCRC)
3. Generate: bleWaveformGenerator(pduCRC, DFPacketType="ConnectionlessCTE", ChannelIndex=N)
4. Extract IQ:
   Option A: [bits, addr, iq] = bleIdealReceiver(waveform, DFPacketType="ConnectionlessCTE", SlotDuration=2)
   Option B: iq = bleCTEIQSample(cteSamples, Mode="LE1M", SlotDuration=2)
5. Estimate: angle = bleAngleEstimate(iq, bleAngleEstimateConfig(...))

NOT valid:

  • bleWaveformGenerator(..., CTELength=16, CTEType="AoA") — these are NOT NV args

  • bleAngleEstimate(waveform, Mode=..., CTELength=...) — takes (iqSamples, configObj)


Practical Receiver Helpers (Example-Based, R2022a)

These are NOT built-in functions — they ship as example helpers. Access via:

openExample('bluetooth/BLEPHYWithRFImpairmentsAndCorrectionsExample')
helperBLEImpairmentsInit

Purpose: Initialize RF impairment parameters struct.

initImp = helperBLEImpairmentsInit(phyMode, sps)

Output struct fields:

  • pfo — Phase/frequency offset object (set .FrequencyOffset, .PhaseOffset)

  • vdelay — Variable delay vector (timing drift)

  • dc — DC offset percentage

helperBLEImpairmentsAddition

Purpose: Apply all RF impairments to a BLE waveform.

txImpairedWfm = helperBLEImpairmentsAddition(txWaveform, initImp)

Applies: frequency offset → phase offset → timing drift → DC offset.

helperBLEPracticalReceiver

Purpose: Full practical receiver with impairment corrections.

[rxBits, accessAddress] = helperBLEPracticalReceiver(rxWaveform, rxCfg)

rxCfg struct fields:

FieldValue
ModePHY mode string
SamplesPerSymbolsps
DFPacketType"Disabled"
ChannelIndex0-39
AccessAddress32-bit binary vector
CoarseFreqCompensatorcomm.CoarseFrequencyCompensator object
PreambleDetectorcomm.PreambleDetector object

RX pipeline: AGC → DC removal → coarse CFO → matched filter → preamble detection → timing correction → demod → de-whiten.

helperBLEReferenceResults

Purpose: Compute Bluetooth spec reference BER/PER values.

[refBER, refPER, refEbNo] = helperBLEReferenceResults(phyMode, payloadLen)
Eb/No to SNR Conversion
% Uncoded (LE1M, LE2M):
snr = EbNo - 10*log10(sps);

% Coded (LE500K, rate=1/2):
snr = EbNo + 10*log10(1/2) - 10*log10(sps);

% Coded (LE125K, rate=1/8):
snr = EbNo + 10*log10(1/8) - 10*log10(sps);

Copyright 2026 The MathWorks, Inc. Last verified: 2026-05-22 from in.mathworks.com/help/bluetooth/ref/

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.

The author says: >=R2022a

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-generate-ble-waveform · 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-generate-ble-waveform.zip