function y = ehtStreamParse(x,numSS,numCBPS,numBPSCS)
%ehtStreamParse Stream parser
%
%   Y = ehtStreamParse(X,NUMSS,NUMCBPS,NUMBPSCS) parses the encoded
%   bits in X into spatial streams as defined in IEEE 802.11-2016 Sections
%   19.3.11.8.2 and 21.3.10.6, and IEEE P802.11ax/D4.1 Section 27.3.11.6.
%
%   Y is a matrix of size (Ncbpss*Nsym)-by-NUMSS containing stream parsed
%   data, where Ncbpss is the number of coded bits per OFDM symbol per
%   spatial stream, Nsym is the number of OFDM symbols, and NUMSS is the
%   number of spatial streams.
%
%   X is a matrix of size (Ncbps*Nsym/Nes)-by-Nes containing the encoded
%   bits, where Nes is the number of encoded streams.
%
%   NUMSS is a scalar between 1 and 8 representing the number of spatial
%   streams.
%
%   NUMCBPS is a scalar specifying the number of coded bits per OFDM
%   symbol. NUMCBPS must be equal to NUMBPSCS*NUMSS*Nsd, where Nsd is one
%   of 12, 24, 48, 51, 52, 102, 108, 117, 234, 468, 490, 980, 1960, or
%   3920.
%
%   NUMBPSCS is a scalar specifying the number of coded bits per subcarrier
%   per spatial stream. It must be equal to 1, 2, 4, 6, 8, 10, or 12.
%
%   Example 1:
%   % Stream parse 3 OFDM symbols with 2 encoded streams into 5 spatial  
%   % streams.
%
%       % Input parameters
%       numCBPS = 235200;
%       numBPSCS = 12;
%       numES = 1;
%       numSS = 5;
%       numSym = 3;
%
%       % Create input bits
%       bits = randi([0 1],numCBPS*numSym/numES,numES,'int8');
%
%       % Stream parser
%       parsedData = ehtStreamParse(bits,numSS,numCBPS,numBPSCS);
%
%   See also ehtStreamDeparse.

%   Copyright 2020-2021 The MathWorks, Inc.

% Return an empty matrix if x is empty
if isempty(x)
    y = zeros(0,numSS,'like',x);
    return;
end

% Validate numBPSCS
if (~isnumeric(numBPSCS) || ~isscalar(numBPSCS) || ~any(numBPSCS==[1 2 4 6 8 10 12]))
    error('numBPSCS must be equal to 1, 2, 4, 6, 8, 10, or 12.');
end

% Validate numSS
validateattributes(numSS,{'numeric'},{'scalar','>=',1,'<=',8},mfilename,'numSS');

% Validate numCBPS
validateattributes(numCBPS,{'numeric'},{'scalar'},mfilename,'numCBPS');
if ~any(numCBPS/(numBPSCS*numSS)==[24 36 48 63 72 102 126 234 468 702 980 1448 1682 1960 2428 2940 3408 3920])
    error('numCBPS must be equal to numBPSCS*numSS*Nsd, where Nsd is one of 24, 36, 48, 63, 72, 102, 126, 234, 468, 702, 980, 1448, 1682, 1960, 2428, 2940, 3408, ór 3920'); 
end

if size(x,2)>1
   error('The number of columns of the input x must be equal to a one, i.e. number of encoded streams');
end

if numSS==1 % 1 spatial stream
    y = x;
else
    coder.internal.errorIf(mod(numel(x),numCBPS)~=0,'wlan:wlanStreamParse:InvalidInputSizeNUMCBPS'); % Integer number of OFDM symbols

    % IEEE Std 802.11-2016, Sections 19.3.11.8.2 and 21.3.10.6
    numES = 1; % 1 for 802.11be
    blkSize = max(1,numBPSCS/2); % IEEE Std 802.11-2016, Equation 21-68
    sumS = numSS*blkSize;
    numBlock = floor(numCBPS/(numES*sumS)); % IEEE Std 802.11-2016, Equation 21-69

    % Cross-validation between inputs and numES
    coder.internal.errorIf(~(numCBPS==numBlock*numES*sumS || numES==numSS),'wlan:wlanStreamParse:InvalidInputRelation');

    % No tail in IEEE P802.11ax/D4.1, Section 27.3.11.6.
    tempX = reshape(x,blkSize,numSS,[],numES); % [blkSize,numSS,numBlock*numSym,numES]
    tempX = permute(tempX,[1 4 3 2]); % [blkSize,numES,numBlock*numSym,numSS]
    y = reshape(tempX,[],numSS); % [numCBPSS*numSym,numSS]
end