function [packetDuration,maxSlotDuration] = helperBluetoothPacketDuration(packetType,phyMode,payloadLength)
%helperBluetoothPacketDuration Duration of a Bluetooth packet
%   [PACKETDURATION,MAXSLOTDURATION] =
%   helperBluetoothPacketDuration(PACKETTYPE,PHYMODE,PAYLOADLENGTH) returns
%   the duration of a packet, PACKETDURATION, based on packet type, mode
%   and payload length.
%
%   PACKETDURATION denotes the duration of a Bluetooth packet corresponding
%   to the number of packet symbols.
%
%   MAXSLOTDURATION denotes the maximum slot duration of a packet.
%
%   PACKETTYPE is a character vector or string scalar specifying the type
%   of packet. It must be one of {'ID','NULL','POLL','FHS','DM1','HV1'
%   ,'HV2','HV3','DV','EV3','EV4','EV5','DH1','AUX1','DM3','DH3','DM5',
%   'DH5','2-EV3','3-EV3','2-EV5','3-EV5','2-DH1','3-DH1','2-DH3','3-DH3',
%   '2-DH5','3-DH5'}.
%
%   PHYMODE is a character vector or string scalar specifying the physical
%   layer transmission mode. It must be one of 'BR'|'EDR2M'|'EDR3M'.
%
%   PAYLOADLENGTH is an integer that denotes the payload body length in
%   bytes.
%
%   Reference - Bluetooth Core Specification, version 5.1, volume 2,
%   part B, section 6.0.

%   Copyright 2019 The MathWorks, Inc.

% Remove prefix for EDR packet types
if any(strcmp(packetType,{'2-EV3','3-EV3','2-EV5','3-EV5','2-DH1','3-DH1','2-DH3','3-DH3','2-DH5','3-DH5'}))
    packetType = packetType(3:end);
end

% Maximum slot duration in microseconds
maxSlotDuration = 625*((1*(any(strcmp(packetType,{'ID','NULL','POLL','FHS','HV1','HV2','HV3','DV','EV3','DM1','DH1','AUX1'}))))...
    +(3 * any(strcmp(packetType,{'EV4','EV5','DM3','DH3'})))+ (5*any(strcmp(packetType,{'DM5','DH5'}))));

% Payload header length in bits
payloadHeaderLength = 8*(any(strcmp(packetType,{'DM1','AUX1'})) || (strcmp(packetType,'DH1') && strcmp(phyMode,'BR')) || strcmp(packetType,'DV'))...
                +16*(any(strcmp(packetType,{'DM3','DH3','DM5','DH5'}))||(strcmp(packetType,'DH1') && ~strcmp(phyMode,'BR')));

% CRC length
crcLength = 16*any(strcmp(packetType,{'FHS','DM1','DH1','DM3','DH3','DM5','DH5','EV3','EV4','EV5','DV'}));

% Complete payload length
dataLength = payloadHeaderLength + payloadLength*8 + crcLength;

% Length after performing FEC on payload
if any(strcmp(packetType,{'DM1','HV2','DM3','DM5','EV4','FHS','DV'}))
    % If the length of input bits is not an integer multiple of 10,
    % then tail bits with value zero shall be appended to the input bits.
    payloadPaddedLength = dataLength + (rem(dataLength,10)~=0)*(10-rem(dataLength,10));

    % Perform (15,10) shortened Hamming code
    if ~strcmp(packetType,'DV')
        fecLength = (15/10)*payloadPaddedLength;
    else % Perform FEC only on the data field of DV packet
        dataFieldLen = payloadPaddedLength - 80;
        fecLength = 80 + dataFieldLen*(15/10) ;
    end
elseif  strcmp(packetType,'HV1')
    % Perform 1/3 rate FEC on HV1 packet
    fecLength = dataLength*3;
else % No FEC for the other packets
    fecLength = dataLength;
end

% Access code and header length
accessCodeLength = 68 + 4*(~strcmp(packetType,'ID'));
headerLength = 54*(~strcmp(packetType,'ID'));
ahLength = accessCodeLength + headerLength;

% Packet duration in microseconds
if strcmp(phyMode,'BR')
    packetDuration = ahLength + fecLength;
else % For EDR2M and EDR3M modes
    if ~any(strcmp(packetType,{'ID','NULL','POLL'}))
        guardTime = 5; % Guard time
        syncSequenceLength = 11; % Synchronization sequence length
        trailerLength = 2; % Trailer length
        M = 4*(strcmp(phyMode,'EDR3M')+1); % Modulation order for EDR modes
        k = log2(M);
        edrPacketLength = syncSequenceLength*k+fecLength+trailerLength*k;
        % If the length of EDR packet is not an integer multiple of
        % log2(ModulationOrder), the last symbol of the sequence can be
        % formed by appending data zeros to the appropriate length.
        edrPacketPaddedLength = edrPacketLength+(rem(edrPacketLength,k)~=0)*(k-rem(edrPacketLength,k));
        edrSymLength = edrPacketPaddedLength/k; % Number of symbols in DPSK portion of the EDR packet
        packetDuration = ahLength + guardTime + edrSymLength; % EDR packet duration
    else % No payload for ID, NULL and POLL packets
        packetDuration = ahLength;
    end
end
end