%% BLE Link Layer Packet Generation and Decoding
%
% This example shows how to generate and decode Bluetooth(R) Low Energy
% (BLE) link layer packets using the Communications Toolbox(TM) Library
% for the Bluetooth(R) Protocol.

% Copyright 2018 The MathWorks, Inc. 

%% Background
%
% The Bluetooth Core Specification [ <#36 1> ] includes a Low Energy
% version for low-rate wireless personal area networks, that is referred to
% as Bluetooth Low Energy (BLE) or Bluetooth Smart. The BLE stack consists
% of: Generic Attribute Profile (GATT), Attribute Protocol (ATT), Security
% Manager Protocol (SMP), Logical Link Control and Adaptation Protocol
% (L2CAP), link layer (LL) and physical layer. BLE was added to the
% standard for low energy devices generating small amounts of data, such as
% notification alerts used in such applications as home automation,
% health-care, fitness, and Internet of Things (IoT).
%
% <<../BLEProtocolStack.png>>

%% Packet Formats
%
% Bluetooth core specification [ <#36 1> ] defines two kinds of PHYs for
% BLE. Each PHY has its own packet format.
%
% (i) Uncoded PHYs (1 Mbps and 2 Mbps)
%
% (ii) Coded PHYs (125 Kbps and 500 Kbps)
%
% Coded PHYs use Forward Error Correction (FEC) encoding (with coding
% scheme S = 8 or S = 2) for the packets. The figures show the uncoded and
% coded PHY packet formats.
%
% *Format of LE Air Interface Packet for Uncoded PHY*
%
% <<../BLELLAirInterfacePktUncodedFormat.png>>
%
% *Format of LE Air Interface Packet for Coded PHY*
%
% <<../BLELLAirInterfacePktCodedFormat.png>>
%
% The Communications Toolbox(TM) Library for the Bluetooth Protocol
% generates LL packets that consist of Protocol Data Unit (PDU) and the
% Cyclic Redundancy Check (CRC) shown in the PHY packet.
%
% BLE classifies 40 RF channels into three advertising channels (Channel
% indices: 37, 38, 39) and thirty-seven data channels (Channel indices: 0
% to 36). BLE link layer defines two categories of PDUs, advertising
% channel PDUs and data channel PDUs. There are different PDU types within
% these two categories of PDUs. The access address field in the air
% interface packet format differentiates between a data channel PDU and an
% advertising channel PDU. Each category of PDU has its own format.

%% Advertising Channel PDUs
%
% The advertising channel PDUs (see Section 2.3, Part-B, Vol-6 in [ <#36 1>
% ]) are used before a LL connection is created. These PDUs are transmitted
% only on the advertising channels and used in establishing the LL
% connection. The advertising channel PDU has a 16-bit header and a
% variable size payload.
%
% The advertising channel PDU has the following packet format:
%
% <<../BLELLAdvChanPDUFormat.png>>
%
% This example illustrates generation and decoding of advertising
% indication PDU. For a list of other advertising channel PDUs supported,
% see the <matlab:help('bleLLAdvertisingChannelPDUConfig.PDUType') PDUType>
% property.
%
% _Advertising indication_: The advertising indication PDU is used when a
% device wants to advertise itself. This PDU contains the advertising data
% related to the application profile of the device.

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

%% Advertising Channel PDUs Generation
%
% You can use the <docid:comm_ref#mw_fccd1d53-97fd-42f0-bc75-3dcc8a93ca5e bleLLAdvertisingChannelPDU>
% function to generate an advertising
% channel PDU. This function accepts a configuration object
% <docid:comm_ref#obj_bleLLAdvertisingChannelPDUConfig bleLLAdvertisingChannelPDUConfig>.
% This object configures the fields
% required for generating an advertising channel PDU.
%
% *Advertising Indication Generation*

%%
% To generate an 'Advertising indication' PDU, create a
% <docid:comm_ref#obj_bleLLAdvertisingChannelPDUConfig bleLLAdvertisingChannelPDUConfig> object with |PDUType| set to
% |'Advertising indication'|.

cfgLLAdv = bleLLAdvertisingChannelPDUConfig('PDUType', ...
    'Advertising indication');

%%
% Configure the fields:

% Advertiser address
cfgLLAdv.AdvertiserAddress = '012345ABCDEF';
% Advertising data
cfgLLAdv.AdvertisingData = '0201060D09426174746572792056312E30'

%%
% Generate an 'Advertising indication' PDU.

llAdvPDU = bleLLAdvertisingChannelPDU(cfgLLAdv);

%% Decoding Advertising Channel PDUs
%
% You can use the <docid:comm_ref#mw_0309e66e-dc52-4189-872e-2523a76669de bleLLAdvertisingChannelPDUDecode> function to decode an advertising
% channel PDU. This function outputs the following information:
%
% # |status|: An enumeration of type <matlab:help('blePacketDecodeStatus')
% blePacketDecodeStatus>, which indicates whether the LL decoding was
% successful.
% # |cfgLLAdv|: A LL advertising channel PDU configuration object of type
% <docid:comm_ref#obj_bleLLAdvertisingChannelPDUConfig bleLLAdvertisingChannelPDUConfig>, which contains the decoded LL
% properties.
%
% Provide the advertising channel PDU and an optional name-value pair
% specifying the format of the input data PDU to the
% bleLLAdvertisingChannelPDUDecode function. Default input format is
% 'bits'.

%%
% *Decoding Advertising Indication*

[llAdvDecodeStatus, cfgLLAdv] = bleLLAdvertisingChannelPDUDecode(llAdvPDU);

% Observe the outputs

% Decoding is successful
if strcmp(llAdvDecodeStatus, 'Success')
    fprintf('Link layer decoding status is: %s\n\n', llAdvDecodeStatus);
    fprintf('Received Advertising channel PDU configuration is:\n');
    cfgLLAdv
% Decoding failed
else
    fprintf('Link layer decoding status is: %s\n', llAdvDecodeStatus);
end

%% Data Channel PDUs
%
% The data channel PDUs (see Section 2.4, Part-B, Vol-6 in [ <#36 1> ]) are
% used after a LL connection is created. The data channel PDUs consist of
% two sub-categories: *LL data PDUs* and *LL control PDUs*. The LL control
% PDUs are used for managing the LL connection and the LL data PDUs are
% used to carry the upper-layer data. The data channel PDU has a 16-bit
% header and a variable size payload.
%
% The data channel PDUs have the following packet format:
%
% <<../BLELLDataChanPDUFormat.png>>
%
% This example illustrates generation and decoding of the following PDUs.
% For a list of other control PDU types and data PDU types supported see
% <matlab:help('bleLLControlPDUConfig.Opcode') Opcode> and
% <matlab:help('bleLLDataChannelPDUConfig.LLID') LLID> properties
% respectively.
%
% # _Channel map indication_: This LL control PDU is used to update the
% channel map at the peer device. This PDU contains the updated channel map
% indicating good and bad channels.
%
% # _Data (start fragment/complete)_: This LL data PDU is used to carry
% L2CAP data to the peer device.

%% Data Channel PDUs Generation
%
% You can use the <docid:comm_ref#mw_161d6aa9-0483-4c84-9635-deaff3f09b70 bleLLDataChannelPDU> function to generate a data channel PDU.
% This function accepts a configuration object
% <docid:comm_ref#obj_bleLLDataChannelPDUConfig bleLLDataChannelPDUConfig>,
% which configures the fields required for generating a data channel PDU.
% The <docid:comm_ref#obj_bleLLControlPDUConfig bleLLControlPDUConfig> is a
% sub-configuration object within <docid:comm_ref#obj_bleLLDataChannelPDUConfig bleLLDataChannelPDUConfig>, control PDU payload fields are populated
% using the settings of this configuration object.

%%
% Data channel PDUs use the CRC initialization value obtained in the
% 'Connection indication' packet. The CRC initialization value used in the
% generation and decoding of packets.

% CRC initialization value
crcInit = 'ED321C';

%%
% *LL Data PDU Generation*

%%
% To generate a data PDU, create a
% <docid:comm_ref#obj_bleLLDataChannelPDUConfig bleLLDataChannelPDUConfig>
% object with |LLID| set to |'Data (start fragment/complete)'|.

cfgLLData = bleLLDataChannelPDUConfig('LLID', ...
    'Data (start fragment/complete)');

%%
% Configure the fields:

% CRC initialization value
cfgLLData.CRCInitialization = crcInit;
% Sequence number
cfgLLData.SequenceNumber = 0;
% Next expected sequence number
cfgLLData.NESN = 1

%%
% A data PDU is used to transmit a payload from upper-layer. A 18-byte
% payload is used in this example.

% Payload
payload = '0E00050014010A001F004000170017000000';

%%
% Generate a data PDU using payload and configuration.

llDataPDU = bleLLDataChannelPDU(cfgLLData, payload);

%%
% *LL Control PDU Generation*

%%
% To generate a control PDU, create a
% <docid:comm_ref#obj_bleLLDataChannelPDUConfig bleLLDataChannelPDUConfig>
% object with |LLID| set to |'Control'|.

cfgLLData = bleLLDataChannelPDUConfig('LLID', 'Control');

%%
% Configure the fields:

% CRC initialization value
cfgLLData.CRCInitialization = crcInit

%%
% You can configure the contents of an LL control PDU using
% <docid:comm_ref#obj_bleLLControlPDUConfig bleLLControlPDUConfig>.

%%
% Create a control PDU configuration object with |Opcode| set to |'Channel
% map indication'|.

cfgControl = bleLLControlPDUConfig('Opcode', 'Channel map indication');

%%
% Configure the fields:

% Used channels
cfgControl.UsedChannels = [9, 10, 12, 24, 28, 32];
% Connection event instant
cfgControl.Instant = 245

%%
% Assign the updated control PDU configuration object to the
% |ControlConfig| property in the data channel PDU configuration object.

% Update the data channel PDU configuration
cfgLLData.ControlConfig = cfgControl;

%%
% Generate a control PDU with the updated configuration.

llControlPDU = bleLLDataChannelPDU(cfgLLData);

%% Decoding Data Channel PDUs
%
% You can use the <docid:comm_ref#mw_b8b55044-0492-4daa-9ce6-dfe4f355c30f bleLLDataChannelPDUDecode> function to decode a data channel PDU. This
% function outputs the following information:
%
% # |status|: An enumeration of type <matlab:help('blePacketDecodeStatus')
% blePacketDecodeStatus>, which indicates whether the LL decoding was
% successful.
% # |cfgLLData|: An LL data channel PDU configuration object of type
% <docid:comm_ref#obj_bleLLDataChannelPDUConfig bleLLDataChannelPDUConfig>,
% which contains the decoded LL properties.
% # |payload|: An n-by-2 character array representing the upper-layer
% payload carried by LL data PDUs.
%
% Provide the data channel PDU, CRC initialization value and an optional
% name-value pair specifying the format of the input data PDU to the
% <docid:comm_ref#mw_b8b55044-0492-4daa-9ce6-dfe4f355c30f bleLLDataChannelPDUDecode> function. Default input format is 'bits'.

%%
% *Decoding LL Data PDU*

[llDataDecodeStatus, cfgLLData, payload] = ...
    bleLLDataChannelPDUDecode(llDataPDU, crcInit);

% Observe the outputs

% Decoding is successful
if strcmp(llDataDecodeStatus, 'Success') 
    fprintf('Link layer decoding status is: %s\n\n', llDataDecodeStatus);
    fprintf('Received Data channel PDU configuration is:\n');
    cfgLLData
    fprintf('Size of the received upper-layer payload is: %d\n', ...
        numel(payload)/2);
% Decoding failed
else
    fprintf('Link layer decoding status is: %s\n', llDataDecodeStatus);
end

%%
% *Decoding LL Control PDU*

[llControlDecodeStatus, cfgLLData] = ...
    bleLLDataChannelPDUDecode(llControlPDU, crcInit);

% Observe the outputs

% Decoding is successful
if strcmp(llControlDecodeStatus, 'Success')
    fprintf('Link layer decoding status is: %s\n\n', llControlDecodeStatus);
    fprintf('Received Data channel PDU configuration is:\n');
    cfgLLData
    fprintf('Received control PDU configuration is:\n');
    cfgControl = cfgLLData.ControlConfig
% Decoding failed
else
    fprintf('Link layer decoding status is: %s\n', llControlDecodeStatus);
end

%% Exporting to a PCAP File
%
% The generated PDUs are exported to a PCAP file, which can be analyzed and
% visualized with a third party packet analyzer such as Wireshark [ <#36 2>
% ]. The helper function <matlab:edit('helperBLEExportToPCAP')
% helperBLEExportToPCAP> generates a PCAP file containing the BLE Link
% Layer packets.
%
% The following commands generate a PCAP file that can be opened in a
% packet analyzer. The PCAP file contains all the LL packets generated in
% this example.

%%
% *Prepend access address*
%
% The PCAP format expects access address to be prepended to the LL packet.
% The helper function <matlab:edit('helperBLEPrependAccessAddress')
% helperBLEPrependAccessAddress> prepends access address to the generated
% LL packet.

% Advertising channel PDUs use the default access address
advAccessAddress = '8E89BED6';
% Data channel PDUs use the access address obtained from 'Connection
% indication' packet. A random access address is used for this example
connAccessAddress = 'E213BC42';
% Prepend access address
llPkts{1} = helperBLEPrependAccessAddress(llAdvPDU, advAccessAddress);
llPkts{2} = helperBLEPrependAccessAddress(llDataPDU, connAccessAddress);
llPkts{3} = helperBLEPrependAccessAddress(llControlPDU, connAccessAddress);

%%
% *Export to a PCAP file*

% Export the generated LL packets (llPkts) to a PCAP file
helperBLEExportToPCAP(llPkts, 'bleLLPackets.pcap');

%% Visualization of the Generated Link Layer Packets
%
% You can open the PCAP file containing the generated LL packets in a
% packet analyzer. The packets decoded by the packet analyzer match the
% standard compliant LL packets generated by the Communications Toolbox(TM)
% Library for the Bluetooth Protocol. The captured analysis of the packets
% is shown below.
%
% * *Advertising indication*
%
% <<../BLELLAdvertisingPCAP.png>>
%
% * *LL data PDU (carrying L2CAP payload)*
%
% <<../BLELLDataPCAP.png>>
%
% * *LL control PDU (channel map indication)*
%
% <<../BLELLControlPCAP.png>>

%% Conclusion
%
% This example demonstrated generation and decoding of LL packets specified
% in the Bluetooth standard [ <#36 1> ]. You can use a packet analyzer to
% view the generated LL packets.

%% Appendix
%
% This example uses the following helper functions:
%
% * <matlab:edit('helperBLEPrependAccessAddress')
% helperBLEPrependAccessAddress>
% * <matlab:edit('helperBLEExportToPCAP') helperBLEExportToPCAP>

%% Selected Bibliography
%
% # Bluetooth SIG, Bluetooth core specification v5.0:
% https://www.bluetooth.com/
% # Wireshark software: https://www.wireshark.org/
