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

    function [bits, failCRC, eqDataSym, varargout] = wlanVHTSIGARecover( ...
    rxVHTSIGA, chanEst, noiseVarEst, chanBW, varargin)
%WLANVHTSIGARECOVER Recover information bits in VHT-SIG-A field
% 
%   [BITS, FAILCRC] = wlanVHTSIGARecover(RXVHTSIGA, CHANEST, NOISEVAREST,
%   CHANBW) recovers the information bits in the VHT-SIG-A field and
%   performs CRC check.
% 
%   BITS is an int8 column vector of length 48 containing the recovered
%   information bits.
%
%   FAILCRC is true if BITS fails the CRC check. It is a logical scalar.
%
%   RXVHTSIGA is the received time-domain VHT-SIG-A 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 VHT-SIG-A field and Nr represents
%   the number of receive antennas. Ns can be greater than the VHT-SIG-A
%   field length; in this case additional samples at the end of RXVHTSIGA
%   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 double precision,
%   real, nonnegative scalar.
%
%   CHANBW is a string describing the channel bandwidth and must be one of
%   the following: 'CBW20','CBW40','CBW80','CBW160'.
% 
%   [BITS, FAILCRC] = wlanVHTSIGARecover(..., 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] = wlanVHTSIGARecover(...) also returns the
%   equalized subcarriers and common phase error.
%
%   EQDATASYM is a 48-by-2 complex matrix containing the equalized symbols
%   at data subcarriers. There are 48 data subcarriers in each of the 2
%   OFDM symbols which constitute the VHT-SIG-A field.
% 
%   CPE is a column vector of length 2 containing the common phase error
%   between each of the 2 received and expected OFDM symbols.
%
%   Example: 
%   %  Recover the information bits in VHT-SIG-A field via channel 
%   %  estimation on L-LTF over a 1 x 2 quasi-static fading channel
%
%     % Configure a VHT configuration object 
%     chanBW = 'CBW80';
%     cfgVHT = wlanVHTConfig('ChannelBandwidth', chanBW);
%  
%     % Generate L-LTF and VHT-SIG-A field signals
%     txLLTF    = wlanLLTF(cfgVHT); 
%     txVHTSIGA = wlanVHTSIGA(cfgVHT);
% 
%     % Pass through a 1 x 2 quasi-static fading channel with AWGN 
%     H = 1/sqrt(2)*complex(randn(1, 2), randn(1, 2));
%     rxLLTF    = awgn(txLLTF    * H, 10);
%     rxVHTSIGA = awgn(txVHTSIGA * H, 10);
% 
%     % Perform channel estimation based on L-LTF
%     demodLLTF = wlanLLTFDemodulate(rxLLTF, chanBW, 1);
%     chanEst = wlanLLTFChannelEstimate(demodLLTF, chanBW);
% 
%     % Recover information bits in VHT-SIG-A
%     [recVHTSIGABits, failCRC] = wlanVHTSIGARecover(rxVHTSIGA, ...
%         chanEst, 0.1, chanBW);
%
%     % Check CRC validation
%     failCRC
% 
%   See also wlanRecoveryConfig, wlanVHTSIGA, 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, ...
    {'CBW20','CBW40','CBW80','CBW160'})), ...
    'wlan:wlanVHTSIGARecover:InvalidChanBW');

[cfgOFDM,dataInd,pilotInd] = wlan.internal.wlanGetOFDMConfig(chanBW, 'Long', 'Legacy');

% Validate VHT-SIG-A field signal input
validateattributes(rxVHTSIGA, {'double'}, {'2d','finite', ...
    'nrows',cfgOFDM.FFTLength*5/2}, 'rxVHTSIGA', 'VHT-SIG-A field signal'); 
numRx = size(rxVHTSIGA, 2);

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

% Cross validate inputs
numST = numel([dataInd; pilotInd]); % Total number of occupied subcarriers
coder.internal.errorIf(size(chanEst, 1) ~= numST, ...
    'wlan:wlanVHTSIGARecover:InvalidChanEst1D', numST);
coder.internal.errorIf(size(chanEst, 2) ~= 1, ...
    'wlan:wlanVHTSIGARecover:InvalidChanEst2D');
coder.internal.errorIf(size(chanEst, 3) ~= numRx, ...
    'wlan:wlanVHTSIGARecover: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

% OFDM demodulation 
[ofdmOutData, ofdmOutPilots] = ... % data is [48*num20, 2, numRx]
    wlan.internal.wlanOFDMDemodulate(rxVHTSIGA, cfgOFDM, symOffset); 

% Pilot phase tracking
if calculateCPE==true || strcmp(pilotPhaseTracking, 'PreEQ')
    % Get reference pilots, from Eqn 22-28, IEEE Std 802.11ac-2013
    z = 1; % Offset by 1 to account for L-SIG pilot symbol
    refPilots = wlan.internal.nonHTPilots(2, 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
    varargout{1} = cpe.'; % Permute to Nsym-by-1
end

% Merge num20 channel estimates and demodulated symbols together for the
% repeated subcarriers
num20MHz = cfgOFDM.FFTLength/64; % Number of 20 MHz subchannels
[ofdmOutDataOne20MHz, chanEstDataOne20MHz] = wlan.internal.mergeSubchannels( ...
    ofdmOutData, chanEstData, num20MHz);

% Perform equalization
[eqDataSym, csiData] = wlan.internal.wlanEqualize(ofdmOutDataOne20MHz, ...
    chanEstDataOne20MHz, eqMethod, noiseVarEst); % [48, 2]

% Constellation demapping
demodOut = wlan.internal.wlanConstellationDemodulate(bsxfun(@times, eqDataSym,[1 -1i]), ...
                                       1, noiseVarEst); % [48, 2]
demodOut = demodOut .* repmat(csiData, 1, 2); % [48, 2]

% Deinterleaving
deintlvrOut = zeros(size(demodOut)); % [48, 2]
deintlvrOut(:, 1) = wlan.internal.wlanBCCDeinterleave(demodOut(:, 1), 'NON_HT', 48, 1);
deintlvrOut(:, 2) = wlan.internal.wlanBCCDeinterleave(demodOut(:, 2), 'NON_HT', 48, 1);

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

% CRC detection
[~, failCRC] = wlan.internal.wlanCRCDetect(bits(1:42));

end

% [EOF]