function [refBER,refPER,refEbNo,linkMargin] = helperBLEReferenceResults(phyMode,dataLen)
%helperBLEReferenceResults generates reference BER, PER and Eb/No values
%
%   [REFBER,REFPER,REFEbNo,LINKMARGIN] =
%   helperBLEReferenceResults(PHYMODE,DATALEN) generates the reference
%   BER, PER, Eb/No and LINKMARGIN values for each PHY mode, PHYMODE based
%   on DATALEN.
%
%   See also bleWaveformGenerator, bleIdealReceiver.

%   Copyright 2018-2019 The MathWorks, Inc.

% Thermal noise floor
BW = 2e6;       % Channel bandwidth (Hz)
NF = 6;         % Noise figure (dB)
T = 290;        % Ambient temperature (K)
k = 1.3806e-23; % Boltzmann constant (J/K)
noiseFloor = 10*log10(k*T*BW) + NF; % dB

% Free space path loss (FSPL)
carrierFreq = 2.4e9;   % Carrier frequency (Hz)
c = 3e8;        % Speed of light (m/s)
d = 100;        % Distance (m)
Lamda = c/carrierFreq;
lossesdB = fspl(d,Lamda); % dB

% Calculate received power from the transmitted power
gains = 0;      % Antenna gain (dBi)
transmittedPower = 10;     % dBm, as per Bluetooth specification
receivedPower = transmittedPower+gains-lossesdB; % dBm

% Get receiver sensitivity level value in dBm based on PHY mode
if any(strcmp(phyMode,{'LE1M','LE2M'}))     % For LE1M or LE2M
    codeRate = 1;
    rxSensitivity = -70;
elseif(strcmp(phyMode,'LE500K'))            % For LE500K
    codeRate = 1/2;
    rxSensitivity = -75;
else                                        % For LE125K
    rxSensitivity = -82;
    codeRate = 1/2;
end
linkMargin = receivedPower-rxSensitivity; % dB
dBm2dBWFactor = 30;
refSNR = (receivedPower - dBm2dBWFactor) - noiseFloor;
refEbNo = refSNR + 10*log10(codeRate);

% Reference BER and PER
berTable = [0.1 0.064 0.034 0.017]*0.01;
if(dataLen <= 37)
    refBER = berTable(1);
elseif(dataLen <= 63)
    refBER = berTable(2);
elseif(dataLen <= 127)
    refBER = berTable(3);
else
    refBER = berTable(4);
end
accessAddLen = 4; % Access address length in bytes
crcLengthBytes = 3; % CRC length in bytes
pduHeaderLen = 2; % Header length in bytes
refPER = 1-(1-refBER)^((dataLen+accessAddLen+pduHeaderLen+crcLengthBytes)*8);
end