function y = ehtSTF(cfgEHT,varargin)
%ehtSTF EHT Short Training Field (EHT-STF)
%
%   Y = ehtSTF(CFGHE) generates the EHT Short Training Field (EHT-STF)
%   time-domain signal for the EHT transmission format.
%
%   Y is the time-domain EHT-STF signal. It is a complex matrix of size
%   Ns-by-Nt where Ns represents the number of time-domain samples and Nt
%   represents the number of transmit antennas.
%
%   CFGEHT is the format configuration object of type <a
%   href="matlab:help('ehtMUConfig')">ehtMUConfig</a>.
%
%   Y = ehtSTF(CFGEHT,OSF) generates a signal oversampled by the
%   oversampling factor OSF. When not specified, 1 is assumed.
%
%   % Example: Generate an EHT-STF field for a 320 MHz, EHT MU PPDU
%   % format.
%
%     cfgEHT = ehtMUConfig('CBW320');
%     y = ehtSTF(cfgEHT);
%     plot(abs(y));
%
%   See also ehtMUConfig, ehtLTF.

%   Copyright 2020-2021 The MathWorks, Inc.

osf = 1;
if nargin>1
    osf = varargin{1};
end

% M Sequence, IEEE P802.11ax/D4.1, Equation 27-21
M = [-1; -1; -1; 1; 1; 1; -1; 1; 1; 1; -1; 1; 1; -1; 1];

chanBW = wlan.internal.cbwStr2Num(cfgEHT.ChannelBandwidth);
allocationInfo = ruInfo(cfgEHT);
numTx = cfgEHT.NumTransmitAntennas;

if chanBW==20
    HESIndex = (-112:16:112).';
    HESSequence = M*(1+1i)/sqrt(2); % IEEE P802.11ax/D4.1, Equation 27-22
    HESSequence(8) = 0; % Set HES 0 = 0; 
elseif chanBW==40
    HESIndex = (-240:16:240).';
    HESSequence = [M; 0; -M]*(1+1i)/sqrt(2); % IEEE P802.11ax/D4.1, Equation 27-23
elseif chanBW==80
    HESIndex = (-496:16:496).'; % IEEE P802.11ax/D4.1, Equation 27-24
    HESSequence = [M; 1; -M; 0; -M; 1; -M]*(1+1i)/sqrt(2);
elseif chanBW==160
    HESIndex = (-1008:16:1008).'; % IEEE P802.11ax/D4.1, Equation 27-25
    HESSequence = [M; 1; -M; 0; -M; 1; -M; 0; -M; -1; M; 0; -M; 1; -M]*(1+1i)/sqrt(2);
else % 320 MHz
    HESIndex = (-2032:16:2032).'; % IEEE P802.11be/D01.0, Equation 36-29
    HESSequence = [M; 1; -M; 0; -M; 1; -M; 0; M; 1; -M; 0; -M; 1; -M; 0; ...
                  -M; -1; M; 0; M; -1; M; 0; -M; -1; M; 0; M; -1; M]*(1+1i)/sqrt(2);
end
periodicity = 4*chanBW*osf; % IEEE P802.11be/D1.0, Section 36.3.12.9

startSpaceTimeStream = 1;
RU = cfgEHT.RU;
% OFDM parameters
Nfft = 256*osf*chanBW/20;
cpLen = 0;
numKru = zeros(1,allocationInfo.NumRUs);
numKhestf = zeros(1,allocationInfo.NumRUs);
ofdmGrid = complex(zeros(Nfft,1,numTx));
for i = 1:allocationInfo.NumRUs
    % Get the index of the RU object containing the active RU properties
    iru = allocationInfo.RUNumbers(i);

    % Determine the number of STS in this RU, and the indices of the
    % space-time streams. The indices may not always start at 1 due to the
    % trigger-based format.
    ruNumSTS = allocationInfo.NumSpaceTimeStreamsPerRU(i);
    stsIdx = startSpaceTimeStream-1+(1:ruNumSTS).';

    % Extract the RU of interest from the full-bandwidth EHT-STF
    kRU = ehtRUSubcarrierIndices(chanBW,RU{iru}.Size,RU{iru}.Index);

    [ruIdx,seqIdx] = wlan.internal.intersectRUIndices(kRU,HESIndex);

    ruGrid = complex(zeros(numel(kRU),1,ruNumSTS)); % NST(per RU)-by-NSYM-by-NSTS

    % The same sequence is used on all space-time streams
    ruGrid(ruIdx,:,:) = repmat(HESSequence(seqIdx),1,1,ruNumSTS);

    % Cyclic shift
    ruGrid = wlan.internal.heCyclicShift(ruGrid,chanBW,kRU,stsIdx);

    % Spatial mapping
    txRUGrid = wlan.internal.spatialMap(ruGrid,RU{iru}.SpatialMapping,numTx,RU{iru}.SpatialMappingMatrix);

    numKru(i) = numel(kRU);
    numKhestf(i) = numel(ruIdx);

    % Calculate per RU scaling. IEEE P802.11be/D1.0, Equations 36-35
    BetarRU = sqrt(numKru(i)./numKhestf(i));
    ruScalingFactor = (allocationInfo.PowerBoostFactorPerRU(i)*BetarRU)/sqrt(allocationInfo.NumSpaceTimeStreamsPerRU(i));

    % Map subcarriers to full FFT grid and scale
    ruFFTInd = kRU+Nfft/2+1;
    ofdmGrid(ruFFTInd,:,:) = txRUGrid*ruScalingFactor;
end

% Common scaling
BetarCommon = 1/sqrt(sum(allocationInfo.PowerBoostFactorPerRU.^2.*numKru));

% OFDM modulate, scale, and extract required periodicity
ofdmModulated = wlan.internal.wlanOFDMModulate(ofdmGrid,cpLen);
y = ofdmModulated(1:periodicity,:)*Nfft*BetarCommon;

end