gusucode.com > wlan工具箱matlab源码程序 > wlan/wlan/wlanVHTData.m

    function y = wlanVHTData(PSDU,cfgVHT,varargin)
%wlanVHTData VHT Data field processing of the PSDU input
% 
%   Y = wlanVHTData(PSDU,CFGVHT) generates the VHT format Data field
%   time-domain waveform for the input PHY Service Data Unit (PSDU).
%
%   Y is the time-domain VHT Data field 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.
%
%   PSDU is the PHY service data unit input to the PHY. For single-user,
%   PSDU can be a double or int8 typed binary column vector of length
%   CFGVHT.PSDULength*8. Alternatively, PSDU can be a row cell array with
%   length equal to number of users. The ith element in the cell array must
%   be a double or int8 typed binary column vector of length
%   CFGVHT.PSDULength(i)*8.
%
%   CFGVHT is the format configuration object of type <a href="matlab:help('wlanVHTConfig')">wlanVHTConfig</a> which
%   specifies the parameters for the VHT format.
%
%   Y = wlanVHTData(...,SCRAMINIT) optionally allows specification of the
%   scrambler initialization. When not specified, it defaults to a value of
%   93. When specified, it can be a double or int8-typed integer scalar or
%   1-by-Nu row vector between 1 and 127, inclusive, where Nu represents
%   the number of users. Alternatively, SCRAMINIT can be a double or
%   int8-typed binary 7-by-1 column vector or 7-by-Nu matrix, without any
%   all-zero column. If it is a scalar or column vector, it applies to all
%   users. Otherwise, each user can have its own scrambler initialization
%   as indicated by the corresponding column.
% 
%   Example: 
%   %  Generate signal for a 80MHz VHT Data field for single-user single
%   %  transmit antenna configuration.
% 
%      cfgVHT = wlanVHTConfig('ChannelBandwidth', 'CBW80', ...
%                            'NumTransmitAntennas', 1, ...
%                            'NumSpaceTimeStreams', 1, ...
%                            'MCS', 4);
%      inpPSDU = randi([0 1], cfgVHT.PSDULength*8, 1);    % PSDU in bits
%      y = wlanVHTData(inpPSDU,cfgVHT);
%
%   %  Generate signal for a 20MHz VHT Data field for two-user multiple
%   %  transmit antenna configuration.
% 
%      cfgVHT = wlanVHTConfig('ChannelBandwidth', 'CBW20', ...
%                            'NumUsers', 2, ...
%                            'GroupID', 2, ...
%                            'NumTransmitAntennas', 2, ...
%                            'NumSpaceTimeStreams', [1 1], ...
%                            'MCS', [4 8],...
%                            'APEPLength', [1024 2048]);
%      inp1PSDU = randi([0 1], cfgVHT.PSDULength(1)*8, 1); % User 1 PSDU 
%      inp2PSDU = randi([0 1], cfgVHT.PSDULength(2)*8, 1); % User 2 PSDU
%      inpPSDUs = {inp1PSDU, inp2PSDU};               % Concatenate PSDUs
%      y = wlanVHTData(inpPSDUs,cfgVHT);
%    
%   See also wlanVHTConfig, wlanWaveformGenerator, wlanVHTDataRecover.

%   Copyright 2015-2016 The MathWorks, Inc.

%#codegen

narginchk(2,3);
if nargin == 2
    scramInit = 93;     % As per IEEE Std 802.11-2012 Section L.1.5.2.
else
    scramInit = varargin{1};
end

% Validate format configuration input
validateattributes(cfgVHT, {'wlanVHTConfig'}, {'scalar'}, mfilename, ...
    'VHT format configuration object');
cfgInfo = validateConfig(cfgVHT, 'SMappingMCS');
numUsers = cfgVHT.NumUsers;

% Early return for NDP, if invoked by user.
if isscalar(cfgVHT.APEPLength) && (cfgVHT.APEPLength == 0)
    y = complex(zeros(0, cfgVHT.NumTransmitAntennas));
    return;
end

% Validate PSDU input
PSDUMU = wlan.internal.validateVHTPSDUInput(PSDU,cfgVHT.PSDULength,numUsers,mfilename);

% Validate scrambler init input
scramInitBits = wlan.internal.validateVHTScramblerInit(scramInit,numUsers,mfilename);

% Set up implicit parameters
chanBW      = cfgVHT.ChannelBandwidth;
numSTS      = cfgVHT.NumSpaceTimeStreams; % [1 Nu]
numSTSTotal = sum(numSTS);
numOFDMSym  = cfgInfo.NumDataSymbols; % [1 1]
numPadBits  = cfgInfo.NumPadBits;     % [1 Nu]
mcsTable    = wlan.internal.getRateTable(cfgVHT);
numSD       = mcsTable.NSD(1);        % [1 1]
vecAPEPLen  = repmat(cfgVHT.APEPLength, 1, ...
                     numUsers/length(cfgVHT.APEPLength)); % [1 Nu]
vecMCS      = repmat(cfgVHT.MCS, 1, numUsers/length(cfgVHT.MCS)); % [1 Nu]

% Set channel coding to cell type
coder.varsize('channelCoding',[1,4]);
channelCoding = getChannelCoding(cfgVHT);

% Get data subcarriers for each symbol and space-time stream for all users
data = complex(zeros(numSD, numOFDMSym, numSTSTotal));
mSTBC = (cfgVHT.NumUsers == 1)*(cfgVHT.STBC ~= 0) + 1;
numSymMaxInit = numOFDMSym - cfgInfo.ExtraLDPCSymbol*mSTBC;  % Eq: 22-65

for u = 1:numUsers
    data(:, :, sum(numSTS(1:u-1))+(1:numSTS(u))) = ...        
        getDataSubcarrierPerUser(chanBW, vecAPEPLen(u), vecMCS(u), ...
        numOFDMSym, numPadBits(u), mcsTable, u, PSDUMU{u}, ...
        scramInitBits(u,:), numSTS(u), channelCoding{u}, numSymMaxInit, mSTBC);
end
    
% Get OFDM parameters
cfgOFDM = wlan.internal.wlanGetOFDMConfig(chanBW, cfgVHT.GuardInterval, ...
    'VHT', numSTSTotal);

% Generate pilots for VHT, IEEE Std 802.11ac-2013, Eqn 22-95
n = (0:numOFDMSym-1).';
z = 4; % Offset by 4 to allow for L-SIG, VHT-SIG-A, VHT-SIG-B pilot symbols
pilots = wlan.internal.vhtPilots(n, z, chanBW, numSTSTotal);

% Perform spatial mapping, CSD and OFDM modulation
csh = wlan.internal.getCyclicShiftVal('VHT', numSTSTotal, cfgOFDM.FFTLength/64*20);
y = wlan.internal.vhtDataModulate(data, pilots, cfgOFDM, cfgOFDM.CyclicPrefixLength, ...
    csh,  cfgVHT.NumTransmitAntennas, cfgVHT.SpatialMapping, cfgVHT.SpatialMappingMatrix);

end

function dataPerUser = getDataSubcarrierPerUser(chanBW, APEPLength, MCS, ...
    numOFDMSym, numPadBits, mcsTable, userIdx, PSDU, scramInitBits, numSTS, ...
    channelCoding, numSymMaxInit, mSTBC)
% Only for Data packets, not for Null-Data-Packets

% Determine VHT-SIG-B bits per user, 
%   Section 22.3.8.3.6, IEEE Std 802.11ac-2013
APEPLenOver4 = ceil(APEPLength/4);
if length(mcsTable.Nss) == 1 % SU PPDU allocation
    switch chanBW
      case 'CBW20' % 20
        bitsPerUser = [de2bi(APEPLenOver4, 17) ones(1, 3, 'int8')].';
      case 'CBW40' % 21
        bitsPerUser = [de2bi(APEPLenOver4, 19) ones(1, 2, 'int8')].';
      otherwise    % 23 for {'CBW80', 'CBW80+80', 'CBW160'}
        bitsPerUser = [de2bi(APEPLenOver4, 21) ones(1, 2, 'int8')].';
    end
else % MU PPDU allocation
    switch chanBW
      case 'CBW20' % 20
        bitsPerUser = int8([de2bi(APEPLenOver4, 16), de2bi(MCS, 4)].');
      case 'CBW40' % 21
        bitsPerUser = int8([de2bi(APEPLenOver4, 17), de2bi(MCS, 4)].');
      otherwise    % 23 for {'CBW80', 'CBW80+80', 'CBW160'} 
        bitsPerUser = int8([de2bi(APEPLenOver4, 19), de2bi(MCS, 4)].');
    end
end

% Assemble the service bits,
%   Section 22.3.10.2 and 22.3.10.3, IEEE Std 802.11ac-2013
%   SERVICE = [scrambler init = 0; Reserved = 0; CRC of SIGB bits];
serviceBits = [zeros(7,1); 0; wlan.internal.wlanCRCGenerate(bitsPerUser)];

paddedData = [serviceBits; PSDU; zeros(numPadBits, 1)];

% Encode, parse and map bits to create space-time streams
dataPerUser = wlan.internal.vhtGetSTSPerUser(paddedData, scramInitBits, ...
    mcsTable, chanBW, numOFDMSym, userIdx, numSTS, channelCoding, ...
    numSymMaxInit, mSTBC);

end

% [EOF]