Bluetooth LE transmitter code in MATLAB

26 views (last 30 days)
I am trying to use the Bluetooth LE in https://www.mathworks.com/help/comm/ug/bluetooth-low-energy-receiver.html. When I try to decode the data I saved in a .bb file created from the transmitter, I get an incorrect operation.
The code seems to run fine until I get to the part that calls:
[cfgLLAdv,pktCnt,crcCnt,remStartIdx] = helperBLEPhyBitRecover(rcvFilt,...
prbIdx,pktCnt,crcCnt,bleParam);
In the function, There is a function that determines the PDU length.
PDULenInBytes = comm.internal.utilities.bi2deRightMSB(PDULenField',2);
I am getting an incorrect value for PDULenInBytes. The value is way higher than the PDU's actual length. Once this happens the next lines of the code also fail because the size of the dewhitenedBits is less than the PDU size.
I have attached the output response waveform and the code for both transmitter and receiver.
%Transmitter Code:
%Transmission Frequency: 2.402 -
%RF Channels: 40
%Symbol Rate: 1Msym/s
%Modulation: GFSK
%Transmission Mode: LE1M i.e. Uncoded PHY with data rate of 1Mbps
%Preamble: 01010101 or 10101010 dependent on the first value of access
%address
%Access address: 32 bit field
%Payload maximum size is 2080 (includes every part of packet)
%%BLE Transmitter
clc;
phyMode = 'LE1M';
commSupportPackageCheck('BLUETOOTH'); %Check that MATLAB bluetooth is on system
symbolRate = 1e6;
channelBW = 2e6;
%Configure the advertising channel PDU
cfgLLAdv = bleLLAdvertisingChannelPDUConfig;
cfgLLAdv.PDUType = 'Advertising indication';
cfgLLAdv.AdvertisingData = '0123456789ABCDEF';
cfgLLAdv.AdvertiserAddress = '1234567890AB';
%Generate the message, pack into message bits
messageBits = bleLLAdvertisingChannelPDU(cfgLLAdv);
[status, value] = bleLLAdvertisingChannelPDUDecode(messageBits); %Loop exists here to go through octets of data entry
%For visualization purposes
numIter = 1;
sps = 8; % Samples per symbol
accessAddLen = 32;% Length of access address
accessAddHex = '8E89BED6'; % Access address value in hexadecimal
accessAddBin = de2bi(hex2dec(accessAddHex),accessAddLen)'; % Access address in binary
%Setting up visualization
% Create a spectrum analyzer object
specAn = dsp.SpectrumAnalyzer('SpectrumType','Power density');
specAn.SampleRate = symbolRate*sps;
% Create a time scope object
timeScope = timescope('SampleRate', symbolRate*sps,'TimeSpanSource','Auto',...
'ShowLegend',true);
rng default; %controlled repetiton
for numIdx = 1:numIter
channelIdx = randi([37 39],1,1);
%channelIdx = 37; % Channel index value in the range [0,39]
%Generate the waveform
txWaveform = bleWaveformGenerator(messageBits,...
'Mode', phyMode,...
'SamplesPerSymbol',sps,...
'ChannelIndex', channelIdx,...
'AccessAddress', accessAddBin);
% txWaveform = awgn(txWaveform,20,'measured');
% Initialize the parameters required for signal source
if channelIdx == 37
txCenterFrequency = 2.402e9;
elseif channelIdx == 38
txCenterFrequency = 2.426e9;
else
txCenterFrequency = 2.480e9;
end
txFrameLength = length(txWaveform);
txNumberOfFrames = 1; %1e4
txFrontEndSampleRate = symbolRate*sps;
% specAn.FrequencyOffset = channelBW*channelIdx;
specAn.Title = ['Spectrum of ',phyMode,' Waveform for Channel Index = ', num2str(channelIdx)];
channelIdx;
tic
while toc < 0.5 % To hold the spectrum for 0.5 seconds
specAn(txWaveform);
end
% Plot the generated waveform
timeScope.Title = ['BLE ',phyMode,' Waveform for Channel Index = ', num2str(channelIdx)];
timeScope(txWaveform);
end
sigSink = comm.BasebandFileWriter('CenterFrequency',txCenterFrequency,...
'Filename','bleCaptures.bb',...
'SampleRate',txFrontEndSampleRate);
sigSink(txWaveform); % Writing to a baseband file 'bleCaptures.bb'
%So basically it is a .bb because I can save the data
release(sigSink)
constDiagram = comm.ConstellationDiagram('SamplesPerSymbol',sps, ...
'SymbolsToDisplaySource','Property','SymbolsToDisplay',100);
constDiagram(txWaveform)
%% End
%Receive Code:
%%BLE Receiver
load 'Port ECG 1 [shielded 2020 10cm]-2020.09.30.17.01.31.716.MAT'
clc;
phyMode = 'LE1M';
bleParam = helperBLEReceiverConfig(phyMode);
bbFileName = 'bleCaptures.bb';
sigSrc = comm.BasebandFileReader(bbFileName);
sigSrcInfo = info(sigSrc);
sigSrc.SamplesPerFrame = sigSrcInfo.NumSamplesInData;
bbSampleRate = sigSrc.SampleRate;
bleParam.SamplesPerSymbol = bbSampleRate/bleParam.SymbolRate;
%View the received signal
spectrumScope = dsp.SpectrumAnalyzer( ...
'SampleRate', bbSampleRate,...
'SpectrumType', 'Power density', ...
'SpectralAverages', 10, ...
'YLimits', [-130 -10], ...
'Title', 'Received Baseband BLE Signal Spectrum', ...
'YLabel', 'Power spectral density');
dataCaptures = sigSrc();
% Show power spectral density of the received waveform
spectrumScope(dataCaptures);
agc = comm.AGC('MaxPowerGain',20,'DesiredOutputPower',2);
freqCompensator = comm.CoarseFrequencyCompensator('Modulation','OQPSK', ...
'SampleRate',bbSampleRate,...
'SamplesPerSymbol',2*bleParam.SamplesPerSymbol,...
'FrequencyResolution',100);
prbDet = comm.PreambleDetector(bleParam.RefSeq,'Detections','First');
length(dataCaptures)
bleParam.MinimumPacketLen;
pktCnt = 0;
crcCnt = 0;
displayFlag = true;%false; % true if the received data is to be printed
%while length(dataCaptures) > bleParam.MinimumPacketLen
% Consider two frames from the captured signal for each iteration
startIndex = 1;
endIndex = min(length(dataCaptures),2*bleParam.FrameLength);
rcvSig = dataCaptures(startIndex:endIndex);
rcvAGC = agc(rcvSig); % Perform AGC
rcvDCFree = rcvAGC - mean(rcvAGC); % Remove the DC offset
rcvFreqComp = freqCompensator(rcvDCFree); % Estimate and compensate for the carrier frequency offset
rcvFilt = conv(rcvFreqComp,bleParam.h,'same'); % Perform gaussian matched filtering
% Perform frame timing synchronization
[~, dtMt] = prbDet(rcvFilt);
release(prbDet)
prbDet.Threshold = max(dtMt);
prbIdx = prbDet(rcvFilt);
prbIdx;
% Extract message information
[cfgLLAdv,pktCnt,crcCnt,remStartIdx] = helperBLEPhyBitRecover(rcvFilt,...
prbIdx,pktCnt,crcCnt,bleParam);
% Remaining signal in the burst captures
dataCaptures = dataCaptures(1+remStartIdx:end);
% Display the decoded information
if displayFlag && ~isempty(cfgLLAdv)
disp('we are here')
fprintf('Advertising PDU Type: %s\n',cfgLLAdv.PDUType);
fprintf('Advertising Address: %s\n',cfgLLAdv.AdvertiserAddress);
end
% Release System objects
release(freqCompensator)
release(prbDet)
%end
% Release the signal source
release(sigSrc)
%%
  1 Comment
Akpabio Ekpewoh
Akpabio Ekpewoh on 6 Jul 2021
%Create a bluetooth LE transmitter
%RF Channels: 40
%Symbol Rate: 1Msym/s
%Modulation: GFSK
%Transmission Mode: LE1M i.e. Uncoded PHY with data rate of 1Mbps
%Preamble: 01010101 or 10101010 dependent on the first value of access
%address
%Access address: 32 bit field
%Payload maximum size is 2080 (includes every part of packet)
%%BLE Transmitter
clc;
phyMode = 'LE1M';
commSupportPackageCheck('BLUETOOTH'); %Check that MATLAB bluetooth is on system
symbolRate = 1e6;
channelBW = 2e6;
%Configure the advertising channel PDU
cfgLLAdv = bleLLAdvertisingChannelPDUConfig;
cfgLLAdv.PDUType = 'Advertising indication';
cfgLLAdv.AdvertisingData = '0123456789ABCDEF';
cfgLLAdv.AdvertiserAddress = '1234567890AB';
%Generate the message, pack into message bits
messageBits = bleLLAdvertisingChannelPDU(cfgLLAdv);
[status, value] = bleLLAdvertisingChannelPDUDecode(messageBits); %Loop exists here to go through octets of data entry
%For visualization purposes
numIter = 1;
sps = 8; % Samples per symbol
accessAddLen = 32;% Length of access address
accessAddHex = '8E89BED6'; % Access address value in hexadecimal
accessAddBin = de2bi(hex2dec(accessAddHex),accessAddLen)'; % Access address in binary
%Setting up visualization
% Create a spectrum analyzer object
specAn = dsp.SpectrumAnalyzer('SpectrumType','Power density');
specAn.SampleRate = symbolRate*sps;
% Create a time scope object
timeScope = timescope('SampleRate', symbolRate*sps,'TimeSpanSource','Auto',...
'ShowLegend',true);
rng default; %controlled repetiton
for numIdx = 1:numIter
channelIdx = randi([37 39],1,1);
%channelIdx = 37; % Channel index value in the range [0,39]
%Generate the waveform
txWaveform = bleWaveformGenerator(messageBits,...
'Mode', phyMode,...
'SamplesPerSymbol',sps,...
'ChannelIndex', channelIdx,...
'AccessAddress', accessAddBin);
% txWaveform = awgn(txWaveform,20,'measured');
% Initialize the parameters required for signal source
if channelIdx == 37
txCenterFrequency = 2.402e9;
elseif channelIdx == 38
txCenterFrequency = 2.426e9;
else
txCenterFrequency = 2.480e9;
end
txFrameLength = length(txWaveform);
txNumberOfFrames = 1; %1e4
txFrontEndSampleRate = symbolRate*sps;
% specAn.FrequencyOffset = channelBW*channelIdx;
specAn.Title = ['Spectrum of ',phyMode,' Waveform for Channel Index = ', num2str(channelIdx)];
channelIdx;
tic
while toc < 0.5 % To hold the spectrum for 0.5 seconds
specAn(txWaveform);
end
% Plot the generated waveform
timeScope.Title = ['BLE ',phyMode,' Waveform for Channel Index = ', num2str(channelIdx)];
timeScope(txWaveform);
end
sigSink = comm.BasebandFileWriter('CenterFrequency',txCenterFrequency,...
'Filename','bleCaptures.bb',...
'SampleRate',txFrontEndSampleRate);
sigSink(txWaveform); % Writing to a baseband file 'bleCaptures.bb'
%So basically it is a .bb because I can save the data
release(sigSink)
constDiagram = comm.ConstellationDiagram('SamplesPerSymbol',sps, ...
'SymbolsToDisplaySource','Property','SymbolsToDisplay',100);
constDiagram(txWaveform)
%% End
%Receiver
%%BLE Receiver
load 'Port ECG 1 [shielded 2020 10cm]-2020.09.30.17.01.31.716.MAT'
clc;
phyMode = 'LE1M';
bleParam = helperBLEReceiverConfig(phyMode);
bbFileName = 'bleCaptures.bb';
sigSrc = comm.BasebandFileReader(bbFileName);
sigSrcInfo = info(sigSrc);
sigSrc.SamplesPerFrame = sigSrcInfo.NumSamplesInData;
bbSampleRate = sigSrc.SampleRate;
bleParam.SamplesPerSymbol = bbSampleRate/bleParam.SymbolRate;
%View the received signal
spectrumScope = dsp.SpectrumAnalyzer( ...
'SampleRate', bbSampleRate,...
'SpectrumType', 'Power density', ...
'SpectralAverages', 10, ...
'YLimits', [-130 -10], ...
'Title', 'Received Baseband BLE Signal Spectrum', ...
'YLabel', 'Power spectral density');
dataCaptures = sigSrc();
% Show power spectral density of the received waveform
spectrumScope(dataCaptures);
agc = comm.AGC('MaxPowerGain',20,'DesiredOutputPower',2);
freqCompensator = comm.CoarseFrequencyCompensator('Modulation','OQPSK', ...
'SampleRate',bbSampleRate,...
'SamplesPerSymbol',2*bleParam.SamplesPerSymbol,...
'FrequencyResolution',100);
prbDet = comm.PreambleDetector(bleParam.RefSeq,'Detections','First');
length(dataCaptures)
bleParam.MinimumPacketLen;
pktCnt = 0;
crcCnt = 0;
displayFlag = true;%false; % true if the received data is to be printed
%while length(dataCaptures) > bleParam.MinimumPacketLen
% Consider two frames from the captured signal for each iteration
startIndex = 1;
endIndex = min(length(dataCaptures),2*bleParam.FrameLength);
rcvSig = dataCaptures(startIndex:endIndex);
rcvAGC = agc(rcvSig); % Perform AGC
rcvDCFree = rcvAGC - mean(rcvAGC); % Remove the DC offset
rcvFreqComp = freqCompensator(rcvDCFree); % Estimate and compensate for the carrier frequency offset
rcvFilt = conv(rcvFreqComp,bleParam.h,'same'); % Perform gaussian matched filtering
% Perform frame timing synchronization
[~, dtMt] = prbDet(rcvFilt);
release(prbDet)
prbDet.Threshold = max(dtMt);
prbIdx = prbDet(rcvFilt);
prbIdx;
% Extract message information
[cfgLLAdv,pktCnt,crcCnt,remStartIdx] = helperBLEPhyBitRecover(rcvFilt,...
prbIdx,pktCnt,crcCnt,bleParam);
% Remaining signal in the burst captures
dataCaptures = dataCaptures(1+remStartIdx:end);
% Display the decoded information
if displayFlag && ~isempty(cfgLLAdv)
disp('we are here')
fprintf('Advertising PDU Type: %s\n',cfgLLAdv.PDUType);
fprintf('Advertising Address: %s\n',cfgLLAdv.AdvertiserAddress);
end
% Release System objects
release(freqCompensator)
release(prbDet)
%end
% Release the signal source
release(sigSrc)
%%

Sign in to comment.

Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!