function MPDUs = zigbeeAddProtocolHeaders(payloadsWithInfo)
%ZIGBEEADDPROTOCOLSTACK Add lower layer headers (MAC, NET, APS, ZCL) of zigbee protocol stack
%   MPDUs = zigbeeAddProtocolStack(PAYLOADSWITHINFO) generates MAC frames
%   for the given ZCL payloads by adding lower layer headers (MAC, NET,
%   APS, ZCL). The input is a struct vector containing the following fields
%   for each payload: (i) Payload, which is the actual payload in bits,
%   (ii) ProfileID, (iii) ClusterID,, and (iv) CommandID. The output is a
%   cell array containing the MAC frames as bit streams.

% Copyright 2017 The MathWorks, Inc.

MPDUs = cell(1, numel(payloadsWithInfo));

for i=1:numel(payloadsWithInfo)
   
  if payloadsWithInfo(i).ClusterSpecific
    frameType = 'Cluster-specific';
  else
    frameType = 'Library-wide';
  end
  
  if isfield(payloadsWithInfo, 'Direction')
    direction = payloadsWithInfo(i).Direction;
  else
    direction = 'Uplink';
  end

  % ZCL frame configuration object
  zclConfig = zigbee.ZCLFrameConfig('FrameType',      frameType, ...
                                    'CommandType',    payloadsWithInfo(i).CommandType, ...
                                    'SequenceNumber', i, ...
                                    'Direction',      direction);
  % ZCL frame generation (APS Payload)
  zclFrame = zigbee.ZCLFrameGenerator(zclConfig, payloadsWithInfo(i).Payload);

  % APS frame configuration object
  apsConfig = zigbee.APSFrameConfig('FrameType',              'Data', ...
                                    'ClusterID', payloadsWithInfo(i).ClusterID, ...
                                    'APSCounter',             i, ...
                                    'SourceEndpoint',         '01', ...
                                    'DestinationEndpoint',    '02', ...
                                    'ProfileID', payloadsWithInfo(i).ProfileID, ...
                                    'AcknowledgmentRequest', true);
  % APS frame generation (NET Payload)
  apsFrame = zigbee.APSFrameGenerator(apsConfig, zclFrame);

  % NET frame configuration object
  netConfig = zigbee.NETFrameConfig('FrameType', 'Data', ...
                                    'SequenceNumber', i);
  % NET frame generation (MAC Payload)
  netFrame = zigbee.NETFrameGenerator(netConfig, apsFrame);

  % MAC frame configuration object
  macConfig = lrwpan.MACFrameConfig('FrameType',                'Data', ...
                                    'SequenceNumber',           i, ...
                                    'SourceAddressing',         'Short address', ...
                                    'SourceAddress',            'FFFE', ...
                                    'SourcePANIdentifier',      '5678', ...
                                    'DestinationAddressing',    'Short address', ...
                                    'DestinationAddress',       'FFFA', ...
                                    'DestinationPANIdentifier', 'CCDD');
  % MAC frame generation
  macFrame = lrwpan.MACFrameGenerator(macConfig, netFrame);

  % Storing MAC payloads to generate PCAP file
  MPDUs{i} = macFrame;
end

end
