mcpField
M
matlab-generate-ble-waveform

matlab-generate-ble-waveform

github.com/matlabその他1.2k62 回インストール1 日前に更新
リポジトリ

matlab-generate-ble-waveform について

Bluetooth Low EnergyのPHY波形を生成、シミュレーション、解析するMATLABスキルです。BLEの物理層を扱うユーザー向けに、PHYモードの選択から方向検出、適合性試験、受信機シミュレーション、共存解析、送信測定まで案内します。

主な機能

  1. 014種類のBLE PHYモード波形を生成
  2. 02マルチパケットバーストとPDU波形を構成
  3. 03CTEと方向検出の手順に対応
  4. 04BERと劣化受信機のシミュレーションを案内
  5. 05RF-PHY試験と送信測定を扱う

活用シーン

  1. 01BLE PHYモードの比較
  2. 02CTEによる角度推定の試験
  3. 03帯域幅、PAPR、信号電力の測定
  4. 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.yaml
references/
cte-direction-finding.md
data-whitening.md
direction-finding.md
functionalAPI.md
phy-modes-and-timing.md
practical-receiver-simulation.md
rfphy-compliance-testing.md
rssi-localization.md
transmitter-measurements.md
wlan-coexistence.md

詳細

BLE 波形生成

ルーティング

インテント手がかりパターン
基本的な生成「生成」、「波形」単一モード
モードの比較「比較」、「すべてのモード」全モード
方向検出「CTE」、「AoA」、「AoD」CTE
RF-PHY 適合性「適合性」、「RF-PHY」RF-PHY テスト
共存「WLAN」、「干渉」WLAN 共存
TX 測定「PAPR」、「OBW」、「電力」TX 測定
位置特定「RSSI」、「ビーコン」、「距離」RSSI 位置特定
BER/受信機「BER」、「ノイズ」、「感度」BER シミュレーション
複数パケット「バースト」、「IFS」複数パケット
スペクトラム「スペクトラム」、「スペクトルマスク」スペクトル解析
ホワイトニング「ホワイトニング」、「スクランブル」ホワイトニング比較
劣化要因「CFO」、「実用的」、「現実的」エンドツーエンド

デフォルト(曖昧なリクエストの場合):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"1e61 Mbpsなし約336 us
"LE2M"2e62 Mbpsなし約172 us
"LE500K"1e6500 kbpsFEC S=2約974 us
"LE125K"1e6125 kbpsFEC S=8約2768 us

参考資料

このファイルの内容を超える詳細なガイダンスについては、以下を参照してください。

パラメーター(bleWaveformGenerator)

パラメーターデフォルト範囲
Mode"LE1M"LE1M、LE2M、LE500K、LE125K
ChannelIndex370-39
SamplesPerSymbol8>=1(プロットには >=4 を使用)
WhitenStatus"On"On、Off
DFPacketType"Disabled"Disabled、ConnectionCTE、ConnectionlessCTE
AccessAddress広告用のデフォルト値32 ビットのバイナリ列ベクトル
ModulationIndex0.5[0.45, 0.55]
PulseLength1[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 文字の 16 進数文字列(コロンなし)。AdvertisingData:16 進数文字列(長さ・タイプ・値の 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 ではありません)。ペイロード:16 進数文字列、数値ベクトル [0,255]、または n×2 の char 配列。

エンドツーエンド(実用的な受信機)

helperBLEPracticalReceiver(AGC + CFO + タイミングリカバリー)を使用します。次が必要です:openExample('bluetooth/BLEPracticalReceiverExample')。符号化モードの SNR 変換:SNR = EbNo + 10*log10(codeRate) - 10*log10(sps)。

CTE の互換性

モードConnectionCTEConnectionlessCTE
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 を返します。
  • 「スロット」(1 スロット、3 スロット、5 スロット): BR/EDR の概念のみです。BLE にはスロットベースのパケットはありません。
  • ISO ストリーム: BN × IRC × Sub_Interval <= ISO_Interval を検証してください。計算結果が上限を超える場合は、要求を拒否してください。
無効な組み合わせ(これらの要求は拒否してください)
要求無効な理由
LE2M + FEC 符号化FEC はコーデッド PHY(LE500K/LE125K)でのみ使用されます
Ch 37/38/39 での LE2Mプライマリアドバタイジングは LE1M または Coded のみです
CTE + LE500K/LE125KBLE 5.1 仕様により、CTE は LE1M/LE2M に制限されています
ConnectionlessCTE + LE2MConnectionlessCTE は LE1M のみです
「3 スロット」または「5 スロット」の BLEスロットベースなのは BR/EDR です。BLE では単一パケットを使用します
Ch 37/38/39 での CTECTE はデータチャネル(0-36)のみです
BN×IRC×Sub_Int > ISO_Interval となる ISO パラメーターサブイベントがインターバルを超えるため、スケジューリングできません

規約

  • 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...) を直接使用してください
BLE に対する bluetoothWaveformGeneratorBR/EDR のみ。bleWaveformGenerator を使用してください
comm.BLEReceiver存在しません。bleIdealReceiver を使用してください
LE2M に対する symbolRate=1e6LE2M = 2e6
パラメーター名としての 'PHYMode''Mode' を使用してください
モードとしての 'LECODED'"LE500K" または "LE125K" を使用してください
第 1 引数としての設定オブジェクトバイナリ列ベクトル randi([0 1],N,1) でなければなりません
空の [] ビット最小 1 バイト
IFS に対する実数の zeros()complex(zeros(N,1)) を使用してください
CTE + コーディングモードCTE は LE1M/LE2M のみ
ConnectionlessCTE + LE2MLE1M のみ
チャネル 37/38/39 での LE2M仕様違反。LE1M または Coded を使用してください
NV 引数としての CTELength/CTEType有効ではありません。DFPacketType を使用してください
bleAngleEstimate(wf, NV...)bleAngleEstimate(iqSamples, bleAngleEstimateConfig) を使用してください
RF-PHY に対する bleWaveformGeneratorbluetoothTestWaveformConfig + bluetoothTestWaveform を使用してください
オーバーサンプリング補正なしの AWGNconvertSNR(EbNo,"ebno","snr",SamplesPerSymbol=sps) を使用してください。awgn に明示的な電力を渡してください("measured" は決して使用しないでください)
劣化を伴う bleIdealReceiverhelperBLEPracticalReceiver を使用してください
符号化レートなしのコーディングモードに対する Eb/NoSNR = EbNo + 10*log10(codeRate) - 10*log10(sps)
警告なしの SPS=1SPS=1 はナイキスト限界です — ユーザーに警告してください: スペクトル解析なし、デコード性能は限界的
resample なしのタイミング ppm オフセットresample(wf, 1e6+ppm, 1e6) または分数遅延フィルターを介してクロックドリフトを適用してください
PRBS9 なしの適合性 Df1/Df2TP/TRM/CA/BV-05-C には comm.PNSequence(z^9+z^5+1)を使用してください。安定ビット(Df1)と交互ビット(Df2)パターンを分離してください
BLE スペクトルに対する periodogram/pwelch手動の fftshift(fft(wf)) を使用してください — スキルの慣例
プロパティ名としての SNbleLLDataChannelPDUConfig の SequenceNumber を使用してください
コロン付きアドレス "A1:B2:..."コロンなしの 12 文字の 16 進文字列を使用してください: "A1B2C3D4E5F6"
PDUType="ADV_IND"完全な文字列を使用してください: "Advertising indication"
AdvertisingData としてのバイナリベクトル16 進文字列を使用してください: "0201060709..."(長さ-タイプ-値)

Copyright 2026 The MathWorks, Inc.

コメント