function [bleWaveform, pcapPacket] = helperBLETransmitData(attPDU)
%helperBLETransmitData Transmit application data by generating BLE waveform
%   BLEWAVEFORM = helperBLETransmitData(ATTPDU) Transmits the application
%   data, ATTPDU, to the receiver in the form of BLE waveform, BLEWAVEFORM
%   and also returns the PCAPPACKET to generate PCAP (packet capture) file
%   with the transmitted PDU.
%
%   BLEWAVEFORM is a complex valued column vector of size Ns-by-1, where Ns
%   represents the number of time-domain samples.
%
%   PCAPPACKET is the generated link layer packet prepended with
%   access address, returned as a binary column vector.
%
%   ATTPDU represents the input ATT PDU, given as a character array where
%   each row is the hexadecimal representation of an octet.
%
%   See also helperBLEDecodeData.

%   Copyright 2018 The MathWorks, Inc.

%% L2CAP
% Add L2CAP header to the BLE ATT PDU
attChannelIdentifier = '0004'; % Channel identifier for Attribute Protocol

% Configuration object for adding L2CAP header
l2capCfg = bleL2CAPFrameConfig('ChannelIdentifier', attChannelIdentifier);

% Generate L2CAP frame
l2capFrame = bleL2CAPFrame(l2capCfg, attPDU);

%% Link Layer
% Add Link Layer header to the generated BLE L2CAP frame
defaultAccessAddress = '01234567';  % Default access address
defaultCRCInit       = '012345';    % Default CRC initialization

% Configuring LLID with 'Data (start fragment/complete)'
llCfg = bleLLDataChannelPDUConfig();
llCfg.LLID = 'Data (start fragment/complete)';
llCfg.CRCInitialization = defaultCRCInit;

% Generate Link Layer data PDU
llPacket = bleLLDataChannelPDU(llCfg, l2capFrame);

%% PCAP packet
% The PCAP format expects Link Layer packet to be prepended with the access
% address.

% Prepend access address to the link layer packet
pcapPacket = helperBLEPrependAccessAddress(llPacket, defaultAccessAddress);

%% PHY
% Generate waveform the Link Layer packet

accessAddressBinary = de2bi(hex2dec(defaultAccessAddress), 32)';

bleWaveform = bleWaveformGenerator(llPacket, 'AccessAddress', accessAddressBinary);

end

