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

    function [bits, failCheck, eqDataSym, varargout] = wlanLSIGRecover( ...
    rxLSIG, chanEst, noiseVarEst, chanBW, varargin)
%WLANLSIGRECOVER Recover information bits in L-SIG field
% 
%   [BITS, FAILCHECK] = wlanLSIGRecover(RXLSIG, CHANEST, NOISEVAREST,
%   CHANBW) recovers the information bits in the L-SIG field and performs
%   parity and rate checks.
% 
%   BITS is an int8 column vector of length 24 containing the recovered
%   information bits.
% 
%   FAILCHECK is a logical scalar which is true if BITS fails the parity
%   check or its first 4 bits is not one of the eight legitimate rates.
%
%   RXLSIG is the received time-domain L-SIG 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 L-SIG field and Nr represents the number of
%   receive antennas. Ns can be greater than the L-SIG field length; in
%   this case additional samples at the end of RXLSIG 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.
% 
%   CHANBW is a string describing the channel bandwidth and must one of:
%   'CBW5','CBW10','CBW20','CBW40','CBW80','CBW160'.
% 
%   [BITS, FAILCHECK] = wlanLSIGRecover(..., CFGREC) allows different
%   algorithm options for information bit 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] = wlanLSIGRecover(...) also returns the equalized
%   subcarriers and common phase error.
%
%   EQDATASYM is a complex column vector of length 48 containing the
%   equalized symbols at data carrying subcarriers. There are 48 data
%   carrying subcarriers in the L-SIG field.
%
%   CPE is an scalar containing the common phase error between the received
%   and expected OFDM symbol.
%
%   Example: 
%   % Recover the information bits in L-SIG via channel estimation on L-LTF
%   % over a 3 x 2 quasi-static fading channel.
%
%     % Configure a VHT configuration object 
%     chanBW = 'CBW40'; 
%     cfgVHT = wlanVHTConfig( ...
%         'ChannelBandwidth', chanBW, ...
%         'NumTransmitAntennas', 3, ...
%         'NumSpaceTimeStreams', 3); 
%  
%     % Generate L-LTF and L-SIG field signals
%     txLLTF = wlanLLTF(cfgVHT); 
%     [txLSIG, LSIGBits] = wlanLSIG(cfgVHT);
% 
%     % Pass through a 3 x 2 quasi-static fading channel with AWGN 
%     H = 1/sqrt(2)*complex(randn(3, 2), randn(3, 2));
%     rxLLTF = awgn(txLLTF * H, 10);
%     rxLSIG = awgn(txLSIG * H, 10);
% 
%     % Perform channel estimation based on L-LTF
%     demodLLTF = wlanLLTFDemodulate(rxLLTF, chanBW, 1);
%     chanEst = wlanLLTFChannelEstimate(demodLLTF, chanBW);
% 
%     % Recover information bits in L-SIG
%     recLSIGBits = wlanLSIGRecover(rxLSIG, chanEst, 0.1, chanBW);
%
%     % Compare against original information bits
%     disp(isequal(LSIGBits, recLSIGBits));
% 
%   See also wlanRecoveryConfig, wlanLSIG, wlanLLTF, wlanLLTFDemodulate,
%   wlanLLTFChannelEstimate.

%   Copyright 2015-2016 The MathWorks, Inc.

%#codegen

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

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

% Validate channel bandwidth input
coder.internal.errorIf(~ischar(chanBW) || ...
    ~any(strcmp(chanBW, {'CBW5','CBW10','CBW20','CBW40','CBW80','CBW160'})), ...
    'wlan:wlanLSIGRecover:InvalidChBandwidth');

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

% Validate L-SIG field signal input
validateattributes(rxLSIG, {'double'}, {'2d','finite','nrows',FFTLen*5/4}, ...
    'rxLSIG', 'L-SIG field signal'); 
numRx = size(rxLSIG, 2);

% Validate channel estimates
validateattributes(chanEst, {'double'}, {'3d','finite'}, ...
    'chanEst', 'channel estimates'); 

% Cross validate inputs
numST = numel([dataInd; pilotInd]); % Total number of subcarriers
coder.internal.errorIf(size(chanEst, 1) ~= numST, ...
    'wlan:wlanLSIGRecover:InvalidChanEst1D', numST);
coder.internal.errorIf(size(chanEst, 2) ~= 1, ...
    'wlan:wlanLSIGRecover:InvalidChanEst2D');
coder.internal.errorIf(size(chanEst, 3) ~= numRx, ...
    'wlan:wlanLSIGRecover:InvalidChanEst3D');

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

% Validate noise variance estimate input
validateattributes(noiseVarEst, {'double'}, ...
    {'real','scalar','nonnegative','finite'}, ...
    'noiseVarEst', 'noise variance estimate'); 

% Validate optional recovery configuration input
if nargin == 5
    validateattributes(varargin{1}, {'wlanRecoveryConfig'}, {'scalar'}, ...
        'cfgRec', 'recovery configuration object');
    symOffset = varargin{1}.OFDMSymbolOffset;
    eqMethod  = varargin{1}.EqualizationMethod;
    pilotPhaseTracking = varargin{1}.PilotPhaseTracking;
else
    symOffset = 0.75;
    eqMethod  = 'MMSE';
    pilotPhaseTracking = 'PreEQ';
end

% ofdmOutData is [48*num20, 1, numRx]
[ofdmOutData, ofdmOutPilots] = wlan.internal.wlanOFDMDemodulate(rxLSIG, cfgOFDM, symOffset); 

% Pilot phase tracking
if calculateCPE==true || strcmp(pilotPhaseTracking, 'PreEQ')
    % Get reference pilots, from IEEE Std 802.11-2012, Eqn 20-14
    z = 0; % No offset as first symbol with pilots
    refPilots = wlan.internal.nonHTPilots(1, z, chanBW);

    % Estimate CPE and phase correct symbols
    cpe = wlan.internal.commonPhaseErrorEstimate(ofdmOutPilots, chanEstPilots, ...
        refPilots);
    if strcmp(pilotPhaseTracking, 'PreEQ')
        ofdmOutData = wlan.internal.commonPhaseErrorCorrect(ofdmOutData, cpe);
    end
    if calculateCPE==true
        varargout{1} = cpe.'; % Permute to Nsym-by-1
    end
end

% Merge num20 channel estimates and demodulated symbols together for the
% repeated subcarriers for data carrying subcarriers
num20MHz = cfgOFDM.FFTLength/64; % Number of 20 MHz subchannels
[ofdmDataOutOne20MHz, chanEstDataOne20MHz] = wlan.internal.mergeSubchannels( ...
    ofdmOutData, chanEstData, num20MHz);
% Perform equalization
[eqDataSym, csiData] = wlan.internal.wlanEqualize(ofdmDataOutOne20MHz, ...
    chanEstDataOne20MHz, eqMethod, noiseVarEst);

% Constellation demapping
demodOut = wlan.internal.wlanConstellationDemodulate(eqDataSym(:), 1, noiseVarEst); 
% Need the (:) above for codegen
demodOut = demodOut .* csiData;

% Deinterleaving
deintlvrOut = wlan.internal.wlanBCCDeinterleave(demodOut, 'NON_HT', 48, 1);

% BCC decoding
bits = wlan.internal.wlanBCCDecode(deintlvrOut, '1/2', 24);

% Parity check & rate check (the 4th bit must be 1)
failCheck = (mod(sum(bits(1:17)), 2) ~= bits(18)) || (bits(4) ~= 1);

end

% [EOF]