%% Decode Multiuser HE-Data Field
% Decode the HE-Data field for each user in an OFDMA transmission.
%% Waveform Generation
% Create a multiuser HE object and packet configuration.

allocationIndex = 96; % Two 106-tone RUs, two users, 20 MHz
cfg = wlanHEMUConfig(allocationIndex);
cfg.User{1}.MCS = 4;
cfg.User{2}.APEPLength = 1e3;
cfg.User{2}.MCS = 7;

% Generate random data based on the specific PSDU length per user.

numUsers = numel(cfg.User);
psduLength = getPSDULength(cfg);
txBits = cell(1,numUsers);
for i = 1:numUsers
   txBits{i} = randi([0 1],psduLength(i)*8,1);
end

% Generate an OFDMA waveform signal and add AWGN to the signal.

txWaveform = wlanWaveformGenerator(txBits,cfg);
snr = 25;
rxWaveform = awgn(txWaveform,snr);

%% Receiver Processing per User
% Using the PPDU field indices structure, extract the HE-Data field for each user.

ind = wlanFieldIndices(cfg)
rxData = rxWaveform(ind.HEData(1):ind.HEData(2),:);       

% For each user, OFDM demodulate and extract data-carrying subcarriers assuming 20-MHz channel bandwidth, and 3.2-microsecond guard interval for the appropriate resource unit (RU).

for userIdx = 1:numUsers
   Nfft = 256; % FFT length (20 MHz)
   Ncp = 64;  % Cyclic prefix length (3.2 us at 20 MHz)
   pilotSC = [-116; -90; -48; -22; 22; 48; 90; 116]; % Pilot indices
   if userIdx==1
      ruSC = (-122:-17).'; % Active subcarrier indices RU #1
   else
      ruSC = (17:122).'; % Active subcarrier indices RU #2
   end
   nullIdx = setdiff((-Nfft/2:(Nfft/2-1)).',ruSC)+Nfft/2+1;
   pilotIdx = pilotSC(ismember(pilotSC,ruSC))+Nfft/2+1;
   sf = (1/sqrt(2*numel(ruSC)))*Nfft; % Scaling factor
   rxSym = ofdmdemod(rxData,Nfft,Ncp,Ncp,nullIdx,pilotIdx)/sf;        
  
   % Recover data bits and compare with transmitted
   csi = ones(length(rxSym),1); % Assume CSI estimate of all ones
   nVar = 10^(-snr/10); % Noise variance
   rxBits = wlanHEDataBitRecover(rxSym,nVar,csi,cfg,userIdx);
   disp(isequal(rxBits,txBits{userIdx}))
end

% Copyright 2018 The MathWorks, Inc.