function testWaveform = helperBLETestWaveform(payloadType,pduLength,sps,phyMode)
%helperBLETestWaveform BLE test packet waveform generation
%   TESTWAVEFORM = helperBLETestWaveform(PAYLOADTYPE,PDULENGTH,SPS,PHYMODE)
%   returns the BLE test waveform, TESTWAVEFORM.
%
%   TESTWAVEFORM is a complex valued column vector of size Ns-by-1, where
%   Ns represents the number of time-domain samples.
%
%   PAYLOADTYPE is an integer in the range [0,7] which describes the type
%   of payload to generate test packets.
%
%   PDULENGTH is an integer in the range [37,255] that determines the
%   payload length in bytes.
%
%   SPS denotes the number of samples per symbol.
%
%   PHYMODE is a character vector or string specifying the PHY transmission
%   mode. It must be one of the following: 'LE1M','LE2M',
%   'LE500K','LE125K'.
%
%   Reference - Volume 6, Part-F, Section 4 of the Bluetooth
%   specifications.

%   Copyright 2019 The MathWorks, Inc.

% Synchronization word for test packet (access address)
syncWord = flip([1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 0 1 1 0 1 1 1 0 1 0 0 0 1 1 1 0].');

% Generate PDU based on the payload type
switch payloadType
    case 0      % PRBS9 sequence
        polynomial = 'z^9+z5+1';
        initialConditions = ones(1,9);
    case 1      % '11110000' sequence
        payloadPattern = [1;1;1;1;0;0;0;0];
    case 2      % '10101010' sequence
        payloadPattern = [1;0;1;0;1;0;1;0];
    case 3      % PRBS15 sequence
        polynomial = 'z^15+z14+1';
        initialConditions = ones(1,15);
    case 4      % '11111111' sequence
        payloadPattern = ones(8,1);
    case 5      % '00000000' sequence
        payloadPattern = zeros(8,1);
    case 6      % '00001111' sequence
        payloadPattern = [0;0;0;0;1;1;1;1];
    case 7      % '01010101' sequence
        payloadPattern = [0;1;0;1;0;1;0;1];
end
if payloadType == 0 || payloadType == 3 % For PRBS9, PRBS15 sequences
    pnSeq = comm.PNSequence('Polynomial',polynomial,...
        'InitialConditions',initialConditions,'SamplesPerFrame',pduLength*8);
    payload = pnSeq();
else
    payload = repmat(payloadPattern,pduLength,1);
end

% Generate test packet PDU
payloadTypeBits = comm.internal.utilities.de2biBase2RightMSB(payloadType,4); % Payload type in bits
pduHeader = [payloadTypeBits.';0;0;0;0]; % PDU header with last four zero bits for test packets
pduLengthBits = comm.internal.utilities.de2biBase2RightMSB(pduLength,8).'; % PDU length value in bits
testPacketPDU = [pduHeader;pduLengthBits;payload];

% Generate and append CRC to PDU
crcPolynomial = 'x^24 + x^10 + x^9 + x^6 + x^4 + x^3 + x + 1';
crcInitValue = '555555';
persistent crcGen
if isempty(crcGen)
    crcGen = comm.CRCGenerator(crcPolynomial, 'InitialConditions', ...
        comm.internal.utilities.de2biBase2LeftMSB(hex2dec(crcInitValue), 24), ...
        'DirectMethod', true);
end
pduCRC = crcGen(testPacketPDU);

% Perform data whitening on PDU and CRC bits in order to remove whitening
% effect performed in 'bleWaveformGenerator' function, because whitening
% must be turned off for the test measurements.
chanIdx = 37;
chanIdxBin = comm.internal.utilities.de2biBase2LeftMSB(chanIdx,6);
initState = [1 chanIdxBin];
whitenedMsg = ble.internal.whiten(pduCRC,initState);

% Generate test BLE waveform
testWaveform = bleWaveformGenerator(whitenedMsg,'AccessAddress',syncWord,'SamplesPerSymbol',sps,...
                    'ChannelIndex',chanIdx,'Mode',phyMode);
end