%% Bluetooth Full Duplex Data and Voice Transmission in MATLAB
% This example shows how to model a full duplex communication in a Bluetooth® piconet having WLAN interference and supporting the adaptive frequency hopping (AFH) functionality using the Communications Toolbox™ Library for the Bluetooth Protocol and the WLAN Toolbox™. The Bluetooth nodes operating with basic rate (BR) physical layer (PHY) communicate with each other simultaneously by transmitting data packets (over an asynchronous connection-oriented (ACL) logical transport) and voice packets (over a synchronous connection-oriented (SCO) logical transport) as random bits. The supported data and voice packets are:
% Data packet types: DM1, DH1, DM3, DH3, DM5, and DH5
% Voice packet types: HV1, HV2, and HV3
% This example enables AFH by classifying channels as good or bad based on the packet error rate (PER) of each channel. The simulation results show a plot of the bit error rate (BER) for each Bluetooth node. The power spectral density of Bluetooth waveforms with WLAN interference is visualized using the spectrum analyzer.
%
%% Bluetooth Specifications
% Bluetooth technology operates in 2.4 GHz industrial, scientific, and medical (ISM) band and shares it with other wireless technologies like ZigBee and WLAN. The Bluetooth Core Specification [1] defined by the Special Interest Group (SIG) specifies two PHY modes: the mandatory BR and the optional enhanced data rate (EDR). The Bluetooth BR/EDR radio implements a 1600 hops/s frequency hopping spread spectrum (FHSS) technique. The radio hops in a pseudo-random way on 79 designated Bluetooth channels. Each Bluetooth channel has a bandwidth of 1 MHz. Each channel is centered at (2402 + k) MHz, where k = 0, 1, ... 78. The modulation technique on the payload for BR and EDR mode is Gaussian frequency shift-keying (GFSK) and differential phase shift-keying (DPSK), respectively. The baud rate is 1 MSymbols/s. The Bluetooth BR/EDR radio uses a time-division duplex (TDD) scheme in which data transmission occurs in one direction at one time. The transmission alternates in two directions, one after the other.
% Bluetooth and WLAN radios often operate in the same physical scenario and in the same device. Therefore, Bluetooth and WLAN transmissions can interfere with each other, thus impacting the performance and reliability of both the networks. To mitigate this interference, the IEEE 802.15.2 Task Group [2] recommends using the AFH technique. To study AFH and the coexistence of Bluetooth with WLAN, see Bluetooth-WLAN Coexistence.
% For more information about the Bluetooth BR/EDR radio and the protocol stack, see Bluetooth Protocol Stack. For more information about Bluetooth BR/EDR packet structures, see Bluetooth Packet Format.
%
%% Logical Transports
% The Bluetooth system supports point-to-point or point-to-multipoint connections called as piconets. Each piconet consists of a node in the role of Master, with other nodes in the Slave role. The Master and Slave exchange data over multiple logical transports. These logical transports are:
% SCO: The Master and Slave exchange SCO packets at regular intervals in the reserved slots. The Bluetooth nodes use SCO logical transport to exchange periodic data such as audio streaming. This logical transport does not support retransmissions.
% Extended synchronous connection-oriented (eSCO): The Bluetooth nodes use eSCO to exchange periodic data such as audio streaming. This logical transport supports retransmissions.
% ACL: The Bluetooth nodes use ACL to exchange asynchronous data such as a file transfer protocol (FTP). During each poll interval, the Master polls the ACL logical transport of a Slave at least once.
% Active slave broadcast (ASB): The Bluetooth nodes use ASB logical transport to send messages from the Master to all of the Slaves in a piconet. This logical transport supports unidirectional traffic with no acknowledgments.
% Connectionless slave broadcast (CSB): The Master node uses a CSB logical transport to send profile broadcast data to multiple Slaves. This logical transport supports unidirectional traffic with no acknowledgments.
% This example supports ACL and SCO logical transports between a Master and Slaves by considering data as random bits of 0s and 1s. This figure shows the communication between a Master and three Slaves in a piconet over ACL and SCO logical transports.
%
% Bluetooth uses reserved time slots for communication between the nodes. The duration of each slot is 625 microseconds. The Master node initiates the transmission in even slots and extends the transmission to odd slots when transmitting a multislot packet. The Slave node initiates the transmission in odd slots and extends the transmission to even slots when transmitting a multislot packet.
%% Check for Support Package Installation

% Check if the 'Communications Toolbox Library for the Bluetooth Protocol'
% support package is installed.
commSupportPackageCheck('BLUETOOTH');

%
%% Configure Simulation Parameters
% This section shows how to configure the simulation parameters for the Bluetooth piconet, the wireless channel, and WLAN interference.
%% Configure Bluetooth Piconet
% The numSlaves parameter specifies the number of Slaves in the Bluetooth piconet. The linkTraffic parameter specifies the type of traffic over Bluetooth logical transports between a Master and the respective Slave. This table maps linkTraffic to different logical transports.
%
% If the Master communicates with multiple Slaves, linkTraffic must be a vector.
% The sequenceType parameter specifies the type of frequency hopping algorithm that the Bluetooth node uses. When you set sequenceType to 'Connection adaptive', the Bluetooth channels are classified as good or bad periodically based on the PER of each Bluetooth channel. To classify the Bluetooth channels, you can use the classifyChannels object function.

% Configure the number of Slaves in the piconet.
numSlaves = 1;

% Configure the logical links between the Master and Slaves.

% Each element represents the logical link between the Master and the
% respective Slave. If the Master is connected to multiple Slaves, this
% value must be a vector.
linkTraffic = 1;

% Configure the frequency hopping sequence as 'Connection basic' or
% 'Connection adaptive'.
sequenceType = 'Connection adaptive';

% To enable an ACL logical transport, set linkTraffic to 1 or 3. Specify
% the ACL packet type as 'DM1', 'DH1', 'DM3', 'DH3', 'DM5', or 'DH5'.
aclPacketType = 'DM1';

% To enable a SCO logical transport, set linkTraffic to 2 or 3. Specify the
% SCO packet type as 'HV1', 'HV2', or 'HV3' for the respective Slave that
% has SCO link traffic. Here, 1 represents the Slave number, and 'HV3'
% represents the corresponding SCO packet type used by Slave 1.
scoPacketType = {1, 'HV3'};

%% Configure Wireless Channel and WLAN Interference
% Configure the wireless channel by using the helperBluetoothChannel helper object. You can set the EbNo value for the AWGN channel. To generate the WLAN signal interference, use the helperBluetoothGenerateWLANWaveform helper function. Specify the sources of WLAN interference by using the wlanInterference parameter. Use one of these options to specify the source of the WLAN interference.
% 'Generated': To add a WLAN toolbox™ signal, select this option.
% 'BasebandFile': To add a WLAN signal from a baseband file (.bb), select this option. You can specify the file name using the wlanBBFilename input argument. If you do not specify the .bb file, the example uses the default .bb file, 'WLANNonHTDSSS.bb', to add the WLAN signal.
% The 'None' option implies that no WLAN signal is added. AWGN is present throughout the simulation.

% Configure wireless channel parameters.
EbNo = 22; % Ratio of energy per bit (Eb) to spectral noise density (No) in dB.

% Configure the WLAN interference.

% Specify the WLAN interference as 'Generated', 'BasebandFile', or 'None'.
% To use the 'wlanBBFilename' option, set wlanInterference to
% 'BasebandFile'.
wlanInterference = 'BasebandFile';
wlanBBFilename =  'WLANNonHTDSSS.bb';

% Signal to interference ratio in dB.
SIR = -15;

%% Create Bluetooth Piconet
% Specify the total number of Bluetooth nodes in the piconet. Set the role of the nodes as Master or Slave. To create a Bluetooth piconet from the configured parameters, use the helperBluetoothCreatePiconet helper function.

% Reset the random number generator.
rng('default');

% Set the total number of nodes in the piconet (one Master and multiple
% Slaves).
numNodes = numSlaves + 1;

% Initialize the cell array to store the Bluetooth nodes.
btNodes = cell(1, numNodes);

% Specify the distance (in meters) between two Bluetooth nodes.
interNodeDistance = 10;

% Configure the nodes as Master or Slave.
for nodeIdx = 1:numNodes
    if nodeIdx == 1
        % Create a baseband Master instance.
        basebandInstance = helperBluetoothBaseband('Role','Master');
    else
        % Create a baseband Slave instance.
        basebandInstance = helperBluetoothBaseband('Role','Slave');
    end
    % Configure the node position.
    nodePosition = [nodeIdx*interNodeDistance 0 0];
    
    % Create and configure the channel of the node.
    channelInstance = helperBluetoothChannel('EbNo',EbNo, ...
                                             'SIR',SIR, ...
                                             'NodePosition',nodePosition, ...
                                             'RxRange',numNodes*interNodeDistance);
    if ~strcmpi(wlanInterference, 'None')
        % Generate the WLAN waveform.
        wlanWaveform = helperBluetoothGenerateWLANWaveform(wlanInterference, wlanBBFilename);
        % Add the WLAN interference to Bluetooth channel.
        addWLANWaveform(channelInstance, wlanWaveform);
    end
    
    % Create and configure the node with a baseband layer and channel.
    node = helperBluetoothFullDuplexNode('Baseband',basebandInstance, ...
                                         'Channel',channelInstance);
    % Update the node ID.
    node.NodeID = nodeIdx;
    
    % Update the node position.
    node.NodePosition = nodePosition;
    
    % Add Bluetooth nodes in the cell array.
    btNodes{nodeIdx} = node;
end

% Create a Bluetooth piconet.
helperBluetoothCreatePiconet(btNodes, numSlaves, linkTraffic, ...
    sequenceType, scoPacketType);

% To visualize the Bluetooth waveforms, create the dsp.SpectrumAnalyzer System™ object.

% View the Bluetooth waveforms using the spectrum analyzer.
spectrumAnalyzer = dsp.SpectrumAnalyzer(...
    'Name','Bluetooth Full Duplex Communication', ...
    'ViewType','Spectrum and spectrogram', ...
    'SpectrumType','Power density', ...
    'TimeResolutionSource','Property', ...
    'TimeResolution',0.0005, ...
    'SampleRate',btNodes{1}.PHY.SamplesPerSymbol*1e6, ...
    'TimeSpanSource','Property', ...
    'TimeSpan',0.05, ...
    'FrequencyResolutionMethod','WindowLength', ...
    'WindowLength',512, ...
    'AxesLayout','Horizontal');

%
%% Simulation
% Simulate the Bluetooth piconet using the configured parameters. Visualize the plot of the BER of each Bluetooth node in the piconet. Visualize the power spectral density of the Bluetooth waveforms by using the dsp.SpectrumAnalyzer System object. You can also calculate the baseband layer statistics (total transmitted packets, total received packets, and total dropped packets) and channel classification statistics at each Bluetooth node. When the sequence type is set to 'Connection adaptive', the Bluetooth node updates the channel classification statistics.

% Set the simulation time in seconds.
simulationTime = 2;

% Convert the simulation time into microseconds.
simulationTimeInUS = simulationTime*1e6;

% Enable or disable the visualization in the example.
enableVisualization = true;

% Current simulation time in microseconds.
curTime = 0;

% Elapsed time in microseconds.
elapsedTime = 0;

% Next invoke times of all of the nodes in microseconds.
nextInvokeTimes = zeros(1, numNodes);

% Transmission flag to specify that the channel is free.
txFlag = false;

% Buffer to store the transmitted waveforms.
txBuffer = cell(1, numNodes);

if enableVisualization
    % Plot the BER.
    berFigure = figure("Name","BER of Each Bluetooth Node",'Tag','BluetoothBERPlot');
    berAxes = axes(berFigure);
    % Add annotations to the figure.
    ylim(berAxes, [0 0.3]);
    xlabel(berAxes, 'Simulation Time (in Microseconds)');
    ylabel(berAxes, 'BER');
    title(berAxes, 'BER of Each Bluetooth Node');
    % Plot the BER line for each Bluetooth node.
    [berPlots, legendStr] = deal(cell(1, numNodes));
    for plotIdx = 1:numNodes
        hold on
        berPlots{plotIdx} = plot(berAxes, curTime, 0);
        if plotIdx == 1
            legendStr{1} = ['\color[rgb]{' num2str(berPlots{plotIdx}.Color) '} Master'];
        else
            legendStr{plotIdx} = ['\color[rgb]{' num2str(berPlots{plotIdx}.Color) '} Slave-' num2str(plotIdx-1)];
        end
    end
    % Add a legend to the figure.
    legend(berAxes, legendStr,'Location','northeastoutside','Box','on');
end

% Run the simulation.
while(curTime < simulationTimeInUS)
    if txFlag
        % When the channel is busy, update the elapsed time as 0.
        elapsedTime = 0;
    else
        % When the channel is free, update the elapsed time as a minimum of
        % all of the next invoke times.
        elapsedTime = min(nextInvokeTimes(nextInvokeTimes ~= -1));
    end
    
    % Simulate the Bluetooth nodes.
    for nodeIdx = 1:numNodes
        % Push the data into the node.
        pushData(btNodes{nodeIdx}, aclPacketType, scoPacketType);
        
        % Run the Bluetooth node instance.
        nextInvokeTimes(nodeIdx) = runNode(btNodes{nodeIdx}, elapsedTime);
        
        if enableVisualization
            if ~isempty(findobj('Tag', 'BluetoothBERPlot'))
                % Update and plot the BER.
                berPlots{nodeIdx}.XData = [berPlots{nodeIdx}.XData curTime];
                if isempty(btNodes{nodeIdx}.PHY.BER)
                    ber = 0;
                else
                    ber = btNodes{nodeIdx}.PHY.BER;
                end
                berPlots{nodeIdx}.YData = [berPlots{nodeIdx}.YData ber];
            end
           if btNodes{nodeIdx}.VisualizeSpectrum
                % Plot the Bluetooth waveform.
                spectrumAnalyzer(btNodes{nodeIdx}.ChannelWaveform);
            end
        end
    end
    
    % Reset the transmission buffer index.
    txBufIdx = 0;
    
    % Reset the transmission flag to specify that the channel is free.
    txFlag = false;

    % Get the data from all of the nodes to be transmitted.
    for nodeIdx = 1:numNodes
        if (btNodes{nodeIdx}.TxBuffer.NumSamples > 0)
            txBufIdx = txBufIdx + 1;
            txBuffer{txBufIdx} = btNodes{nodeIdx}.TxBuffer;
        end
    end
    
    % Pass the transmitted data to the receiving buffers of all of the
    % nodes.
    if txBufIdx > 0
        for nodeIdx = 1:numNodes
            btNodes{nodeIdx}.RxBuffer(1:txBufIdx) = txBuffer(1:txBufIdx);
            btNodes{nodeIdx}.RxBufferIdx = txBufIdx;
        end
        % Set the transmission flag to specify the channel is busy (at
        % least one node is transmitting the waveform).
        txFlag = true;
    end
    
    % Update the current simulation time.
    curTime = curTime + elapsedTime;
end

% The preceding spectrum analyzer plot shows the spectrum of the Bluetooth waveform distorted with WLAN interference (in the frequency domain) and passed through the AWGN channel. The right-side plot shows the overlapping of Bluetooth packets with the interfering WLAN signal.
% The plot "BER of Each Bluetooth Node" shows the BER of each node in the Bluetooth piconet with respect to the simulation time.
% To see the baseband layer statistics for each Bluetooth node, inspect the statisticsAtEachNode variable. To see the channel classification statistics for each Master-Slave pair, inspect the classificationStats variable. The channel classification statistics are valid when sequenceType is set to 'Connection adaptive'. Get the baseband layer and channel classification statistics of each Bluetooth node in the piconet.

% Get the baseband layer and channel classification statistics of each Bluetooth node in the piconet
[statisticsAtEachNode, classificationStats] = helperBluetoothFullDuplexStatistics(btNodes)

% This example enables you to configure and simulate a full duplex data and voice communication in a Bluetooth piconet with WLAN interference. The example uses AFH to mitigate WLAN interference by classifying channels as good or bad based on the PER value. The performance of full duplex communication is analyzed by visualizing the impact of WLAN interference on each Bluetooth node.
%% Appendix
%  The example uses this object:
% bluetoothFrequencyHop: Selects Bluetooth BR/EDR channel index for frequency hopping
% The example uses these helpers:
% helperBluetoothFullDuplexNode: Configures and simulates Bluetooth node
% helperBluetoothBaseband: Configures and simulates Bluetooth baseband layer
% helperBluetoothLogicalTransports: Configures logical transports between Bluetooth nodes
% helperBluetoothSlotTimer: Manages Bluetooth clock and the timing of slots
% helperBluetoothPHY: Configures and simulates Bluetooth PHY layer
% helperBluetoothChannel: Configures and simulates Bluetooth wireless channel
% helperBluetoothGenerateWLANWaveform: Generates WLAN waveform to be added as an interference to Bluetooth waveforms
% helperBluetoothCreatePiconet: Creates Bluetooth piconet using the Bluetooth nodes
% helperBluetoothFullDuplexStatistics: Returns statistics of each Bluetooth node in the Bluetooth piconet
% helperBluetoothQueue: Create an object for Bluetooth queue functionality
%% Selected Bibliography
% Bluetooth Special Interest Group (SIG). "Bluetooth Core Specification." Version 5.2. https://www.bluetooth.com.
% IEEE® Standard 802.15.2™. "Coexistence of Wireless Personal Area Networks with Other Wireless Devices Operating in Unlicensed Frequency Bands." IEEE Recommended Practice for Information technology - Telecommunications and information exchange between systems - Local and metropolitan area networks - Specific requirements; IEEE Computer Society.
% Copyright 2020 The MathWorks, Inc.