关于 matlab-generate-ble-waveform
这项 MATLAB 技能用于生成、仿真和分析 Bluetooth Low Energy PHY 波形,面向开展 BLE 物理层工作的用户。它提供 PHY 模式选择指引,并涵盖测向、合规测试、接收机仿真、共存分析和发射机测量流程。
主要功能
- 01生成四种 BLE PHY 模式波形
- 02构建多数据包突发和 PDU 波形
- 03支持 CTE 与测向流程
- 04指导 BER 和受损接收机仿真
- 05涵盖 RF-PHY 测试与发射测量
适用场景
- 01比较 BLE PHY 模式
- 02测试基于 CTE 的角度估计
- 03测量带宽、PAPR 或信号功率
- 04仿真噪声或 WLAN 干扰下的 BER
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill matlab-generate-ble-waveform安装后在 Claude Code 中输入/matlab-generate-ble-waveform确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
manifest.yamlreferences/cte-direction-finding.mddata-whitening.mddirection-finding.mdfunctionalAPI.mdphy-modes-and-timing.mdpractical-receiver-simulation.mdrfphy-compliance-testing.mdrssi-localization.mdtransmitter-measurements.mdwlan-coexistence.md详细介绍
BLE 波形生成
路由
| 意图 | 线索 | 模式 |
|---|---|---|
| 基本生成 | “generate”、“waveform” | 单模式 |
| 比较模式 | “compare”、“all modes” | 全模式 |
| 测向 | “CTE”、“AoA”、“AoD” | CTE |
| RF-PHY 合规性 | “compliance”、“RF-PHY” | RF-PHY 测试 |
| 共存 | “WLAN”、“interference” | WLAN 共存 |
| TX 测量 | “PAPR”、“OBW”、“power” | TX 测量 |
| 定位 | “RSSI”、“beacon”、“distance” | RSSI 定位 |
| BER/接收器 | “BER”、“noise”、“sensitivity” | BER 仿真 |
| 多数据包 | “burst”、“IFS” | 多数据包 |
| 频谱 | “spectrum”、“spectral mask” | 频谱分析 |
| 白化 | “whitening”、“scrambling” | 白化对比 |
| 损伤 | “CFO”、“practical”、“realistic” | 端到端 |
默认值(请求不明确时):LE1M、37 字节载荷、信道 37。
适用场景
当用户要求生成、仿真或分析 BLE PHY 层波形时,请使用此技能——包括模式比较、CTE/测向、RF-PHY 合规性测试、BER 仿真、TX 测量、WLAN 共存或 RSSI 定位。适用于涉及 bleWaveformGenerator、bleIdealReceiver、bleCTEIQSample、bleAngleEstimate 或 bluetoothTestWaveform 的任何任务。
不适用场景
- BR/EDR(经典 Bluetooth)→ 使用
bluetoothWaveformGenerator(由单独的 BR/EDR 技能介绍) - Channel Sounding(CS)→ 使用
bleCSWaveform(bleCSConfig)(R2024b+);CS 有自己的测距/距离测量流程,不属于 PHY 波形生成 - 网络级仿真 → 使用
bluetoothLENode进行链路层/网络建模 - 路径损耗建模 → 使用
bluetoothPathLoss进行传播/信道建模
PHY 模式
| 模式 | symbolRate | 数据速率 | 编码 | 时长(37 B) |
|---|---|---|---|---|
"LE1M" | 1e6 | 1 Mbps | 无 | ~336 us |
"LE2M" | 2e6 | 2 Mbps | 无 | ~172 us |
"LE500K" | 1e6 | 500 kbps | FEC S=2 | ~974 us |
"LE125K" | 1e6 | 125 kbps | FEC S=8 | ~2768 us |
参考资料
如需了解此文件之外的详细指南,请参阅:
- functionalAPI.md — bleWaveformGenerator 名称-值对的完整 API 参考
- phy-modes-and-timing.md — 各 PHY 模式的详细时序计算
- cte-direction-finding.md — CTE 流程:生成、IQ 采样、约束
- direction-finding.md — 使用 bleAngleEstimate 进行 AoA/AoD 角度估计
- rfphy-compliance-testing.md — RF-PHY 测试波形模式和配置
- transmitter-measurements.md — OBW、PAPR、功率测量模式
- practical-receiver-simulation.md — BER 仿真和受损接收器
- wlan-coexistence.md — WLAN 干扰和共存场景
- rssi-localization.md — RSSI 信标和距离估算模式
- data-whitening.md — 白化开启/关闭对比及内部机制
参数(bleWaveformGenerator)
| 参数 | 默认值 | 范围 |
|---|---|---|
Mode | "LE1M" | LE1M、LE2M、LE500K、LE125K |
ChannelIndex | 37 | 0-39 |
SamplesPerSymbol | 8 | >=1(绘图时建议使用 >=4) |
WhitenStatus | "On" | On、Off |
DFPacketType | "Disabled" | Disabled、ConnectionCTE、ConnectionlessCTE |
AccessAddress | adv default | 32 位二进制列向量 |
ModulationIndex | 0.5 | [0.45, 0.55] |
PulseLength | 1 | [1, 4] |
核心示例
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;
模式
全模式对比
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
多数据包突发(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
往返解码
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))
数据信道 + 自定义接入地址
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 生成
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 全流程(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);
替代方式(R2022a+):iqSamples = bleCTEIQSample(cteSamples, Mode="LE1M", SlotDuration=2);
BER 仿真
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 返回 int8,请使用 double() 转换。Eb/No 转换方式:snr = convertSNR(EbNo,"ebno","snr",SamplesPerSymbol=sps)。
RF-PHY 测试波形
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 共存
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 测量(功率、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));
白化比较
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");
广播 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 的值:"Advertising indication"、"Scan request"、"Scan response"、"Connection indication"、"Advertising direct indication"、"Advertising non connectable indication"。
地址:12 个字符的十六进制字符串(不含冒号)。AdvertisingData:十六进制字符串(长度-类型-值 AD 结构)。
数据信道 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 的值:"Data (continuation fragment/empty)"、"Data (start fragment/complete)"、"Control"。
SequenceNumber(不是 SN)。载荷:十六进制字符串、数值向量 [0,255] 或 n×2 字符数组。
端到端(实用接收机)
使用 helperBLEPracticalReceiver(AGC + CFO + 定时恢复)。需要:openExample('bluetooth/BLEPracticalReceiverExample')。编码模式的 SNR 转换:SNR = EbNo + 10*log10(codeRate) - 10*log10(sps)。
CTE 兼容性
| 模式 | ConnectionCTE | ConnectionlessCTE |
|---|---|---|
| LE1M | 是 | 是 |
| LE2M | 是 | 否 |
| LE500K | 否 | 否 |
| LE125K | 否 | 否 |
CTE 需要数据信道(0-36)。 使用 DFPacketType≠"Disabled" 时,切勿使用 ChannelIndex 37/38/39。CTE 仅适用于数据信道。
规范约束
- Ch 37/38/39(广播): 仅限 LE1M 或 LE Coded。不支持 LE2M。
- CTE: 仅限数据信道(0-36)上的 LE1M/LE2M。切勿使用编码 PHY。
- 接入地址: 广播 =
'8E89BED6'(固定);数据 = 随机。 - 白化初始化: 根据 ChannelIndex 自动设置。不可设置。
- T_IFS: 150 us。TX 功率: 最大 +20 dBm。调制指数: 0.45-0.55。
bleIdealReceiver: 仅支持硬判决,返回int8。- “Slots”(1-slot、3-slot、5-slot): 仅适用于 BR/EDR。BLE 没有基于时隙的数据包。
- ISO 流: 验证
BN × IRC × Sub_Interval <= ISO_Interval。如果计算结果超出范围,拒绝请求。
无效组合(拒绝这些请求)
| 请求 | 原因 |
|---|---|
| LE2M + FEC 编码 | FEC 仅存在于编码 PHY(LE500K/LE125K)中 |
| LE2M 用于 ch 37/38/39 | 主广播仅支持 LE1M 或 Coded |
| CTE + LE500K/LE125K | 根据 BLE 5.1 规范,CTE 仅限 LE1M/LE2M |
| ConnectionlessCTE + LE2M | ConnectionlessCTE 仅支持 LE1M |
| BLE 使用“3-slot”或“5-slot” | 基于时隙的模式仅适用于 BR/EDR;BLE 使用单个数据包 |
| CTE 用于 ch 37/38/39 | CTE 仅适用于数据信道(0-36) |
| ISO 参数满足 BN×IRC×Sub_Int > ISO_Interval | 子事件超出间隔,无法进行调度 |
约定
fs = (1e6 + 1e6*(mode=="LE2M")) * sps——切勿硬编码- 坐标轴:us(时间)、MHz(频率)、dB(功率)
- 使用
tiledlayout/nexttile(而非subplot) - 频谱:始终使用
20*log10(abs(fftshift(fft(wf)))/N + eps)——BLE 频谱图不要使用periodogram、pspectrum或pwelch - 编码模式使用
xlim([0 min(80,t(end))]) - 同时绘制 I 和 Q:
plot(t, real(wf), t, imag(wf)) - IFS 间隔:
complex(zeros(N,1))(输出为复数) - 频谱图要求
SamplesPerSymbol>=4;SPS=1 可用于生成,但不足以用于可视化或精确的频谱分析(处于奈奎斯特极限)
代码风格
生成的脚本必须遵循 MathWorks 示例惯例。使用 %% 分节标题,将所有参数软编码,并为不明显的逻辑添加注释。
结构与软编码
使用 %% 标题划分脚本:配置 → 波形生成 → 处理 → 分析 → 可视化。所有用户可配置值都应在顶部定义为具名变量;处理逻辑中不得使用魔法数字。
%% 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);
注释
- 行内(右对齐):单位、范围或简要用途 —
% Eb/No in dB - 块注释(上方 2-5 行):意图或原因 —
% IFS gap must be complex (bleWaveformGenerator output is complex) - 约束:规范引用 —
% LE2M uses 2 Msym/s (only mode with 2x symbol rate) - 不要注释显而易见的行、机械地注释每一行或注释结束的
end语句
命名
- camelCase:
messageBits、txWaveform、symbolRate、channelIndex - 描述性循环计数器:
countMode、pktIdx(而非i、j) - 命名常量:
bitsPerByte = 8、tIFS = 150e-6 - 多重初始化:
[numErrors, perCount] = deal(0, 0)
易错点
| 错误 | 修正 |
|---|---|
bleWaveformConfig(...) | 不存在。直接使用 bleWaveformGenerator(bits, NV...) |
将 bluetoothWaveformGenerator 用于 BLE | 仅适用于 BR/EDR。请使用 bleWaveformGenerator |
comm.BLEReceiver | 不存在。请使用 bleIdealReceiver |
LE2M 使用 symbolRate=1e6 | LE2M = 2e6 |
将 'PHYMode' 用作参数名 | 请使用 'Mode' |
将 'LECODED' 用作模式 | 请使用 "LE500K" 或 "LE125K" |
| 配置对象作为第 1 个参数 | 必须是二进制列向量 randi([0 1],N,1) |
空 [] 比特 | 至少需要 1 字节 |
IFS 使用实数 zeros() | 请使用 complex(zeros(N,1)) |
| CTE + 编码模式 | CTE 仅适用于 LE1M/LE2M |
ConnectionlessCTE + LE2M | 仅适用于 LE1M |
| 在信道 37/38/39 上使用 LE2M | 违反规范。请使用 LE1M 或 Coded |
将 CTELength/CTEType 用作 NV 参数 | 无效。请使用 DFPacketType |
bleAngleEstimate(wf, NV...) | 请使用 bleAngleEstimate(iqSamples, bleAngleEstimateConfig) |
将 bleWaveformGenerator 用于 RF-PHY | 请使用 bluetoothTestWaveformConfig + bluetoothTestWaveform |
| AWGN 未进行过采样校正 | 请使用 convertSNR(EbNo,"ebno","snr",SamplesPerSymbol=sps);向 awgn 传入显式功率(绝不使用 "measured") |
在存在损伤时使用 bleIdealReceiver | 请使用 helperBLEPracticalReceiver |
| 编码模式的 Eb/No 未考虑码率 | SNR = EbNo + 10*log10(codeRate) - 10*log10(sps) |
| 使用 SPS=1 却未警告 | SPS=1 处于奈奎斯特极限——提醒用户:无法进行频谱分析,解码性能可能不稳定 |
定时 ppm 偏移未使用 resample | 通过 resample(wf, 1e6+ppm, 1e6) 或分数延迟滤波器施加时钟漂移 |
| 一致性 Df1/Df2 未使用 PRBS9 | 对 TP/TRM/CA/BV-05-C 使用 comm.PNSequence (z^9+z^5+1);将稳定比特 (Df1) 与交替比特 (Df2) 模式分开 |
使用 periodogram/pwelch 计算 BLE 频谱 | 使用手动 fftshift(fft(wf))——技能规范 |
将 SN 用作属性名 | 在 bleLLDataChannelPDUConfig 上使用 SequenceNumber |
地址使用带冒号的 "A1:B2:..." | 使用不带冒号的 12 字符十六进制字符串:"A1B2C3D4E5F6" |
PDUType="ADV_IND" | 使用完整字符串:"Advertising indication" |
| 将二进制向量用作 AdvertisingData | 使用十六进制字符串:"0201060709..."(长度-类型-值) |
版权所有 2026 The MathWorks, Inc.