%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)
%%
