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

    function [bits, eqDataSym, varargout] = wlanNonHTDataRecover( ...
    rxNonHTData, chanEst, noiseVarEst, cfgNonHT, varargin)
%wlanNonHTDataRecover Recover information bits from Non-HT Data field signal
%
%   BITS = wlanNonHTDataRecover(RXNONHTDATA, CHANEST, NOISEVAREST,
%   CFGNONHT) recovers the information bits in the Non-HT Data field for a
%   Non-HT OFDM format transmission.
%
%   BITS is an int8 column vector of length 8*CFGNONHT.PSDULength
%   containing the recovered information bits.
%
%   RXNONHTDATA is the received time-domain NonHT-Data field signal. It is
%   a Ns-by-Nr matrix of real or complex values, where Ns represents the
%   number of time-domain samples in the NonHT-Data field and Nr represents
%   the number of receive antennas. Ns can be greater than the NonHT-Data
%   field length; in this case redundant samples at the end of RXNONHTDATA
%   are not used.
%
%   CHANEST is the estimated channel at data and pilot subcarriers based on
%   the L-LTF. It is a real or complex array of size Nst-by-1-by-Nr, where
%   Nst represents the total number of occupied subcarriers. The singleton
%   dimension corresponds to the single transmitted stream in the L-LTF
%   which includes the combined cyclic shifts if multiple transmit antennas
%   are used.
%
%   NOISEVAREST is the noise variance estimate. It is a real, nonnegative
%   scalar.
%
%   CFGNONHT is the format configuration object of type <a href="matlab:help('wlanNonHTConfig')">wlanNonHTConfig</a> 
%   that specifies the Non-HT format parameters. Only OFDM modulation is
%   supported.
% 
%   BITS = wlanNonHTDataRecover(..., CFGREC) allows different algorithm
%   options for data recovery via the input CFGREC, which is a
%   <a href="matlab:help('wlanRecoveryConfig')">wlanRecoveryConfig</a> configuration object. When the CFGREC input is not 
%   specified, the default property values of the  <a href="matlab:help('wlanRecoveryConfig')">wlanRecoveryConfig</a> object
%   are adopted in the recovery.
%
%   [..., EQDATASYM, CPE] = wlanNonHTDataRecover(...) also returns the
%   equalized subcarriers and common phase error.
%
%   EQDATASYM is a complex 48-by-Nsym matrix containing the equalized
%   symbols at data carrying subcarriers. There are 48 data carrying
%   subcarriers in the Non-HT Data field. Nsym represents the number of
%   OFDM symbols in the NonHT-Data field.
%
%   CPE is a column vector of length Nsym containing the common phase error
%   between each received and expected OFDM symbol.
%   
%   Example: 
%   %  Recover a NONHT-Data field signal through a SISO AWGN channel
%   %  using ZF equalization.
%  
%     cfgNonHT = wlanNonHTConfig('PSDULength', 1024);  % NonHT OFDM 
%     txBits = randi([0 1], 8*cfgNonHT.PSDULength, 1); % PSDU bits
%     tx = wlanNonHTData(txBits, cfgNonHT);       % NonHT-Data field signal
% 
%     % Add AWGN, with noise variance of 1
%     rx = awgn(tx, 1, 1);
%
%     % Configure recovery object
%     cfgRec = wlanRecoveryConfig('EqualizationMethod', 'ZF'); 
%     % Recover PSDU bits 
%     rxBits = wlanNonHTDataRecover(rx, ones(52,1), 1, cfgNonHT, cfgRec);
%   
%     [numerr, ber] = biterr(rxBits, txBits); % Compare bits
%     disp(ber)
%     
%   See also wlanNonHTConfig, wlanRecoveryConfig, wlanLLTFChannelEstimate, 
%       wlanNonHTData. 

%   Copyright 2015-2016 The MathWorks, Inc.

%#codegen

narginchk(4,5);
nargoutchk(0,3);

% Calculate CPE if requested
if nargout>2
    calculateCPE = true;
else
    calculateCPE = false;
end

% NonHT configuration input self-validation
validateattributes(cfgNonHT, {'wlanNonHTConfig'}, ...
    {'scalar'}, mfilename, 'format configuration object');
% Only applicable for OFDM and DUP-OFDM modulations
coder.internal.errorIf( ~strcmp(cfgNonHT.Modulation, 'OFDM'), ...
                        'wlan:wlanNonHTDataRecover:InvalidModulation');
s = validateConfig(cfgNonHT);

% Validate rxNonHTData
validateattributes(rxNonHTData, {'double'}, {'2d','finite'}, ...
    'rxHTData', 'Non-HT OFDM Data field signal'); 
% Validate chanEst
validateattributes(chanEst, {'double'}, {'3d','finite'}, ...
    'chanEst', 'channel estimates'); 
% Validate noiseVarEst
validateattributes(noiseVarEst, {'double'}, ...
    {'real','scalar','nonnegative','finite'}, ...
    'noiseVarEst', 'noise variance estimate'); 

% Optional recovery configuration input validation
if nargin == 5
    validateattributes(varargin{1}, {'wlanRecoveryConfig'}, ...
    {'scalar'}, mfilename, 'recovery configuration object');

    symOffset = varargin{1}.OFDMSymbolOffset;
    eqMethod  = varargin{1}.EqualizationMethod; 
    pilotPhaseTracking = varargin{1}.PilotPhaseTracking;
else % use defaults
    symOffset = 0.75;
    eqMethod  = 'MMSE'; 
    pilotPhaseTracking = 'PreEQ';
end

numRx = size(rxNonHTData, 2);

mcsTable = wlan.internal.getRateTable(cfgNonHT);
pNcbpssi = mcsTable.NCBPS;

numOFDMSym = s.NumDataSymbols;

% Get OFDM configuration
[cfgOFDM,dataInd,pilotInd] = wlan.internal.wlanGetOFDMConfig( ...
    cfgNonHT.ChannelBandwidth, 'Long', 'Legacy');

% Cross validate inputs
numST = numel([dataInd; pilotInd]); % Total number of occupied subcarriers
coder.internal.errorIf(size(chanEst, 1) ~= numST, ...
    'wlan:wlanNonHTDataRecover:InvalidNHTChanEst1D', numST);
coder.internal.errorIf(size(chanEst, 2) ~= 1, ...
    'wlan:wlanNonHTDataRecover:InvalidNHTChanEst2D');
coder.internal.errorIf(size(chanEst, 3) ~= numRx, ...
    'wlan:wlanNonHTDataRecover:InvalidNHTChanEst3D');

% Extract data and pilot subcarriers from channel estimate
chanEstData = chanEst(dataInd,:,:);
chanEstPilots = chanEst(pilotInd,:,:);

% Cross-validation between inputs
minInputLen = numOFDMSym*(cfgOFDM.FFTLength+cfgOFDM.CyclicPrefixLength);
coder.internal.errorIf(size(rxNonHTData, 1) < minInputLen, ...
    'wlan:wlanNonHTDataRecover:ShortNHTDataInput', minInputLen);

% Processing 
% OFDM Demodulation 
[ofdmDemodData,ofdmDemodPilots] = wlan.internal.wlanOFDMDemodulate( ...
    rxNonHTData(1:minInputLen, :), cfgOFDM, symOffset);

% Pilot phase tracking
if calculateCPE==true || strcmp(pilotPhaseTracking, 'PreEQ')
    % Get reference pilots, from IEEE Std 802.11-2012, Eqn 18-22
    z = 1; % Offset by 1 to account for L-SIG pilot symbol
    refPilots = wlan.internal.nonHTPilots(numOFDMSym, z);
    
    % Estimate CPE and phase correct symbols
    cpe = wlan.internal.commonPhaseErrorEstimate(ofdmDemodPilots, ...
        chanEstPilots, refPilots);
    if strcmp(pilotPhaseTracking, 'PreEQ')
        ofdmDemodData = wlan.internal.commonPhaseErrorCorrect(ofdmDemodData, cpe);
    end
    if calculateCPE==true
        varargout{1} = cpe.'; % Permute to Nsym-by-1
    end
end

% Equalization
[eqDataSym, csiData] = wlan.internal.wlanEqualize(ofdmDemodData, ...
    chanEstData, eqMethod, noiseVarEst);

% LLR Demodulation
qamDemodOut = wlan.internal.wlanConstellationDemodulate(eqDataSym, ...
    mcsTable.NBPSCS, noiseVarEst);
% Apply bit-wise CSI
qamDemodOut = bsxfun(@times, ...
              reshape(qamDemodOut, mcsTable.NBPSCS, [], numOFDMSym), ...
              reshape(csiData, 1, [])); % [Nbpscs Nsd Nsym]

% Deinterleave per OFDM symbol
deintlvrOut = zeros(pNcbpssi*numOFDMSym, 1);
for symIdx = 1:numOFDMSym 
    deintlvrOut((symIdx-1)*pNcbpssi+(1:pNcbpssi), 1) = ...
        wlan.internal.wlanBCCDeinterleave(reshape( ...
          qamDemodOut(:,:,symIdx), [], 1), 'NON_HT', pNcbpssi, mcsTable.NBPSCS);        
end

% Channel decoding
nhtDecBits = wlan.internal.wlanBCCDecode(deintlvrOut, mcsTable.Rate);

% Combine bits and Descramble with derived initial State
iniY = nhtDecBits(1:7,1); % Take the first 7 bits for scrambler init
scramInit = [iniY(3)+iniY(7) iniY(2)+iniY(6) iniY(1)+iniY(5) ...
    iniY(4)+iniY(3)+iniY(7) iniY(3)+iniY(2)+iniY(6) ...
    iniY(2)+iniY(1)+iniY(5) iniY(1)+iniY(4)+iniY(3)+iniY(7)];
scramInit = mod(scramInit, 2);

% Remove the padded and tail bits to output only the data bits
descramDataOut = wlan.internal.wlanScramble( ...
    nhtDecBits(1:(16+8*cfgNonHT.PSDULength),:), scramInit);

%   Remove the 16 service bits
bits = descramDataOut(17:end);   

end