function [] = DataDecoding(rx) %% HE-Data Decoding % The updated % object for each user can then be used to recover the PSDU bits for each % user in the HE-Data field. cfgDataRec = trackingRecoveryConfig; cfgDataRec.PilotTracking = pilotTracking; fprintf('Decoding HE-Data...\n'); for iu = 1:numUsers % Get recovery configuration object for each user user = cfgUsers{iu}; if strcmp(pktFormat,'HE-MU') fprintf(' Decoding User:%d, STAID:%d, RUSize:%d\n',iu,user.STAID,user.RUSize); else fprintf(' Decoding RUSize:%d\n',user.RUSize); end heInfo = wlanHEOFDMInfo('HE-Data',chanBW,user.GuardInterval,[user.RUSize user.RUIndex]); % HE-LTF demodulation and channel estimation rxHELTF = rx(pktOffset+(ind.HELTF(1):ind.HELTF(2)),:); heltfDemod = wlanHEDemodulate(rxHELTF,'HE-LTF',chanBW,user.GuardInterval, ... user.HELTFType,[user.RUSize user.RUIndex]); [chanEst,pilotEst] = heLTFChannelEstimate(heltfDemod,user); % Number of expected data OFDM symbols symLen = heInfo.FFTLength+heInfo.CPLength; numOFDMSym = (ind.HEData(2)-ind.HEData(1)+1)/symLen; % HE-Data demodulation with pilot phase and timing tracking % Account for extra samples when extracting data field from the packet % for sample rate offset tracking. Extra samples may be required if the % receiver clock is significantly faster than the transmitter. maxSRO = 120; % Parts per million Ne = ceil(numRxSamples*maxSRO*1e-6); % Number of extra samples Ne = min(Ne,rxWaveLen-numRxSamples); % Limited to length of waveform numRxSamplesProcess = numRxSamples+Ne; rxData = rx(pktOffset+(ind.HEData(1):numRxSamplesProcess),:); if user.RUSize==26 % Force CPE only tracking for 26-tone RU as algorithm susceptible % to noise cfgDataRec.PilotTracking = 'CPE'; else cfgDataRec.PilotTracking = pilotTracking; end [demodSym,cpe,peg] = heTrackingOFDMDemodulate(rxData,chanEst,numOFDMSym,user,cfgDataRec); % Estimate noise power in HE fields demodPilotSym = demodSym(heInfo.PilotIndices,:,:); nVarEst = heNoiseEstimate(demodPilotSym,pilotEst,user); % Equalize [eqSym,csi] = heEqualizeCombine(demodSym,chanEst,nVarEst,user); % Discard pilot subcarriers eqSymUser = eqSym(heInfo.DataIndices,:,:); csiData = csi(heInfo.DataIndices,:); % Demap and decode bits rxPSDU = wlanHEDataBitRecover(eqSymUser,nVarEst,csiData,user,'LDPCDecodingMethod','layered-bp'); % Deaggregate the A-MPDU [mpduList,~,status] = wlanAMPDUDeaggregate(rxPSDU,wlanHESUConfig); if strcmp(status,'Success') fprintf(' A-MPDU deaggregation successful \n'); else fprintf(' A-MPDU deaggregation unsuccessful \n'); end % Decode the list of MPDUs and check the FCS for each MPDU for i = 1:numel(mpduList) [~,~,status] = wlanMPDUDecode(mpduList{i},wlanHESUConfig,'DataFormat','octets'); if strcmp(status,'Success') fprintf(' FCS pass for MPDU:%d\n',i); else fprintf(' FCS fail for MPDU:%d\n',i); end end % Plot equalized constellation of the recovered HE data symbols for all % spatial streams per user hePlotEQConstellation(eqSymUser,user,ConstellationDiagram,iu,numUsers); % Measure EVM of HE-Data symbols release(EVM); EVM.ReferenceConstellation = wlanReferenceSymbols(user); rmsEVM = EVM(eqSymUser(:)); fprintf(' HE-Data EVM:%2.2fdB\n\n',20*log10(rmsEVM/100)); % Plot EVM per symbol of the recovered HE data symbols hePlotEVMPerSymbol(eqSymUser,user,EVMPerSymbol,iu,numUsers); % Plot EVM per subcarrier of the recovered HE data symbols hePlotEVMPerSubcarrier(eqSymUser,user,EVMPerSubcarrier,iu,numUsers); end end