function [PE,snrMeas] = tgaxModelPHYLink (rxWaveform,cfgHE,RxNoisePower,interferPower,txPSDU)
%tgaxModelPHYLink Model a PHY link
%
%   This is an example helper function.

%   Copyright 2019 The MathWorks, Inc.

% Default for packet received in error
snrMeas = nan;
PE = 1;

chanBW = cfgHE.ChannelBandwidth;
fs = wlanSampleRate(cfgHE);

ind = wlanFieldIndices(cfgHE);
% Get occupied subcarrier indices and OFDM parameters
ofdmInfo = wlanHEOFDMInfo('HE-Data',cfgHE);

% Add receiver noise
rx = awgn(rxWaveform,-(RxNoisePower-30),0);

% Packet detect and determine coarse packet offset
coarsePktOffset = wlanPacketDetect(rx,chanBW);
if isempty(coarsePktOffset) % If empty no L-STF detected; packet error
    return; % Go to next loop iteration
end

% Extract L-STF and perform coarse frequency offset correction
lstf = rx(coarsePktOffset+(ind.LSTF(1):ind.LSTF(2)),:);

lstfPower = mean(lstf(:).*conj(lstf(:)));
rx = rx./sqrt(lstfPower); % Scale (AGC)

coarseFreqOff = wlanCoarseCFOEstimate(lstf,chanBW);
rx = helperFrequencyOffset(rx,fs,-coarseFreqOff);

% Extract the non-HT fields and determine fine packet offset
nonhtfields = rx(coarsePktOffset+(ind.LSTF(1):ind.LSIG(2)),:);
finePktOffset = wlanSymbolTimingEstimate(nonhtfields,chanBW);

% Determine final packet offset
pktOffset = coarsePktOffset+finePktOffset;

% If packet detected outwith the range of expected delays from
% the channel modeling; packet error
if pktOffset>50
    return; % Go to next loop iteration
end

% Extract L-LTF and perform fine frequency offset correction
rxLLTF = rx(pktOffset+(ind.LLTF(1):ind.LLTF(2)),:);
fineFreqOff = wlanFineCFOEstimate(rxLLTF,chanBW);
rx = helperFrequencyOffset(rx,fs,-fineFreqOff);

% HE-LTF demodulation and channel estimation
rxHELTF = rx(pktOffset+(ind.HELTF(1):ind.HELTF(2)),:);
heltfDemod = wlanHEDemodulate(rxHELTF,'HE-LTF',cfgHE);
chanEst = heLTFChannelEstimate(heltfDemod,cfgHE);

% Data demodulate
rxData = rx(pktOffset+(ind.HEData(1):ind.HEData(2)),:);
demodSym = wlanHEDemodulate(rxData,'HE-Data',cfgHE);

% Pilot phase tracking
demodSym = heCommonPhaseErrorTracking(demodSym,chanEst,cfgHE);

% Use expected total noise power and signal power from channel estimate
% for equalization and de-mapping
nVarEst = (10.^(0.1*(RxNoisePower-30))+interferPower)/lstfPower;
sigEst = sum(mean(abs(chanEst).^2),'all');
snrMeas = 10*log10(sigEst/nVarEst);

% Extract data subcarriers from demodulated symbols and channel
% estimate
demodDataSym = demodSym(ofdmInfo.DataIndices,:,:);
chanEstData = chanEst(ofdmInfo.DataIndices,:,:);

% Equalization and STBC combining
[eqDataSym,csi] = heEqualizeCombine(demodDataSym,chanEstData,nVarEst,cfgHE);

% Recover data
rxPSDU = wlanHEDataBitRecover(eqDataSym,nVarEst,csi,cfgHE);

% Determine if any bits are in error, i.e. a packet error
packetError = ~isequal(txPSDU,rxPSDU);

PE = packetError;

end