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

    function [bits, eqDataSym, varargout] = wlanVHTSIGBRecover(rxVHTSIGB, ...
    chanEst, noiseVarEst, chanBW, varargin)
%WLANVHTSIGBRECOVER Recover information bits in VHT-SIG-B field
% 
%   BITS = wlanVHTSIGBRecover(RXVHTSIGB, CHANEST, NOISEVAREST, CHANBW)
%   recovers the information bits in the VHT-SIG-B field for a single-user
%   transmission.
%
%   BITS is an int8 column vector containing the recovered information
%   bits.
%
%   RXVHTSIGB is the received time-domain VHT-SIG-B field signal specified
%   as an Ns-by-Nr matrix of real or complex values. Ns represents the
%   number of time-domain samples in the VHT-SIG-B field and Nr represents
%   the number of receive antennas. Ns can be greater than the VHT-SIG-B
%   field length; in this case, additional samples at the end of RXVHTSIGB
%   are not used.
% 
%   CHANEST is the estimated channel at data and pilot subcarriers based on
%   the VHT-LTF. It is a real or complex array of size Nst-by-Nsts-by-Nr,
%   where Nst represents the total number of occupied subcarriers and Nsts
%   is the total number of space-time streams used for the transmission.
% 
%   NOISEVAREST is the noise variance estimate, specified as a nonnegative
%   scalar.
%  
%   CHANBW is the channel bandwidth, specified as one of 'CBW20', 'CBW40',
%   'CBW80', or 'CBW160'.
% 
%   BITS = wlanVHTSIGBRecover(RXVHTSIGB, CHANEST, NOISEVAREST, CHANBW, ...
%   USERNUMBER, NUMSTS) recovers the information bits in the VHT-SIG-B
%   field of a VHT format multiuser transmission for an individual user of
%   interest.
%
%   USERNUMBER is the user of interest, specified as an integer between 1
%   and NumUsers, where NumUsers is the number of users in the
%   transmission.
%
%   NUMSTS is the number of space-time streams, specified as a
%   1-by-NumUsers vector. Element values specify the number of space-time
%   streams per user.
%
%   BITS = wlanVHTSIGBRecover(..., 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] = wlanVHTSIGBRecover(...) also returns the
%   equalized subcarriers and common phase error.
%
%   EQDATASYM is a complex column vector of length Nsd containing the
%   equalized symbols at data subcarriers. Nsd represents the number of
%   data subcarriers.
%
%   CPE is a scalar containing the common phase error between the received
%   and expected OFDM symbol.
% 
%   Example: 
%   %  Recover the information bits in VHT-SIG-B field via channel 
%   %  estimation on VHT-LTF over a 4 x 2 quasi-static fading channel
%
%     % Configure a VHT configuration object 
%     chanBW = 'CBW80';
%     cfgVHT = wlanVHTConfig( 'ChannelBandwidth',    chanBW, ...
%         'NumTransmitAntennas', 4, 'NumSpaceTimeStreams', 4); 
%  
%     % Generate VHT-LTF and VHT-SIG-B field signals
%     txVHTLTF = wlanVHTLTF(cfgVHT); 
%     [txVHTSIGB, VHTSIGBBits] = wlanVHTSIGB(cfgVHT);
% 
%     % Pass through a 4 x 2 quasi-static fading channel with AWGN 
%     H = 1/sqrt(2)*complex(randn(4, 2), randn(4, 2));
%     rxVHTLTF  = awgn(txVHTLTF  * H, 10);
%     rxVHTSIGB = awgn(txVHTSIGB * H, 10);
% 
%     % Perform channel estimation based on VHT-LTF
%     demodVHTLTF = wlanVHTLTFDemodulate(rxVHTLTF, cfgVHT, 1);
%     chanEst = wlanVHTLTFChannelEstimate(demodVHTLTF, cfgVHT);
% 
%     % Recover information bits in VHT-SIG-B
%     recVHTSIGBBits = wlanVHTSIGBRecover(rxVHTSIGB, chanEst, 0.1, chanBW);
%
%     % Compare against original information bits
%     disp(isequal(VHTSIGBBits, recVHTSIGBBits));
% 
%   See also wlanRecoveryConfig, wlanVHTSIGB, wlanVHTLTF,
%   wlanVHTLTFDemodulate, wlanVHTLTFChannelEstimate.

%   Copyright 2015-2016 The MathWorks, Inc.

%#codegen

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

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

% Parse optional inputs  - with cfgREc at the end
if nargin == 7  % (..., userNum, numSTSVec, cfgRec)
    cfgRecSpec = true;
    cfgRec = varargin{3};

    muSpec = true;
    userNum = varargin{1};
    numSTSVec = varargin{2};
elseif nargin == 6 % (..., userNum, numSTSVec)
    muSpec = true;
    userNum = varargin{1};
    numSTSVec = varargin{2};

    cfgRecSpec = false;
elseif nargin == 5 % (..., cfgRec)
    cfgRecSpec = true;
    cfgRec = varargin{1};

    muSpec = false;
else % 4 (...)
    cfgRecSpec = false;
    muSpec = false;
end

% Validate optional inputs
if muSpec
    validateattributes(userNum, {'numeric'}, ...
        {'real','integer','scalar','>=',1,'<=',4}, mfilename, 'USERNUMBER');

    wlan.internal.validateParam('NUMSTS', numSTSVec, mfilename);

    % If userNum>1, NUMSTS must be a vector
    coder.internal.errorIf(userNum > length(numSTSVec), ...
        'wlan:wlanVHTSIGBRecover:InvalidUserNum', length(numSTSVec));

else    % set defaults
    userNum = 1;    % Single user or first user
    numSTSVec = size(chanEst, 2);
end

if cfgRecSpec
    validateattributes(cfgRec, {'wlanRecoveryConfig'}, {'scalar'}, ...
        'cfgRec', 'recovery configuration object');
    symOffset = cfgRec.OFDMSymbolOffset;
    eqMethod  = cfgRec.EqualizationMethod; 
    pilotPhaseTracking = cfgRec.PilotPhaseTracking;
else    % set dafaults
    symOffset = 0.75;
    eqMethod  = 'MMSE'; 
    pilotPhaseTracking = 'PreEQ';
end

% Total NumSpaceTimeStreams
numSTSTotal = sum(numSTSVec); 

% Validate channel bandwidth input
wlan.internal.validateParam('CHANBW', chanBW);

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

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

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

% Cross validate inputs
numST = numel([dataInd; pilotInd]); % Total number of occupied subcarriers
if muSpec
    coder.internal.errorIf(size(chanEst, 2) ~= numSTSTotal, ...
        'wlan:wlanVHTSIGBRecover:InvalidChanEst2D', numSTSTotal);
end
coder.internal.errorIf(size(chanEst, 1) ~= numST || ...
    (size(chanEst, 2) > 8) || (size(chanEst, 3) ~= numRx), ...
    'wlan:wlanVHTSIGBRecover:InvalidChanEst', numST, numRx);

% 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'); 

% OFDM demodulation
[ofdmDemodData, ofdmDemodPilots] = ... % data is of size [numSD, 1, numRx]
    wlan.internal.wlanOFDMDemodulate(rxVHTSIGB, cfgOFDM, symOffset); 

% Pull out the space-time streams per user
stsU = numSTSVec(userNum);
stsIdx = sum(numSTSVec(1:(userNum-1)))+(1:stsU); 

% Pilot phase tracking
if calculateCPE==true || strcmp(pilotPhaseTracking, 'PreEQ')
    % Get reference pilots, from Eqn 22-47, IEEE Std 802.11ac-2013
    n = 0; % One OFDM symbol (index 0) in VHT-SIG-B
    z = 3; % Offset by 3 to allow for L-SIG and VHT-SIG-A pilot symbols
    refPilots = wlan.internal.vhtPilots(n, z, chanBW, numSTSTotal);
    
    % Estimate CPE and phase correct symbols
    cpe = wlan.internal.commonPhaseErrorEstimate(ofdmDemodPilots, ...
        chanEstPilots(:,stsIdx,:), ...
        refPilots(:,:,stsIdx));
    if strcmp(pilotPhaseTracking, 'PreEQ')
        ofdmDemodData = wlan.internal.commonPhaseErrorCorrect( ...
            ofdmDemodData, cpe);
    end
    varargout{1} = cpe.'; % Permute to Nsym-by-1
end

% Perform equalization
% Flip the 4th and 8th STS, i.e., P matrix multiplication
if any(numSTSTotal == [4 7 8])
    chanEstData(:,4:4:end,:) = -chanEstData(:,4:4:end,:);
end
% Pull out the streams per user and combine
[eqDataSym, csiData] = wlan.internal.wlanEqualize(ofdmDemodData, ...
    sum(chanEstData(:,stsIdx,:),2), eqMethod, noiseVarEst); % [numSD, 1]

% Constellation demapping: For VHT-SIG-B, avoid calling segment deparser
% which just converts a column vector into 2 columns.
qamDemodOut = wlan.internal.wlanConstellationDemodulate(eqDataSym, ...
    1, noiseVarEst);
qamDemodOut = qamDemodOut .* csiData; % [numSD, 1]

% Deinterleaving & segment parser for CBW160
num20 = cfgOFDM.FFTLength/64;
numSD = length(cfgOFDM.DataIndices);
if strcmp(chanBW, 'CBW160')
    deparserOut = zeros(size(qamDemodOut));
    deparserOut(1:2:end, :) = wlan.internal.wlanBCCDeinterleave( ...
        qamDemodOut(1:end/2,:), 'VHT', numSD/2, 1, 20*num20, 1);
    deparserOut(2:2:end, :) = wlan.internal.wlanBCCDeinterleave( ... 
        qamDemodOut(end/2+1:end,:), 'VHT', numSD/2, 1, 20*num20, 1);
else
    deparserOut = wlan.internal.wlanBCCDeinterleave(qamDemodOut, ...
        'VHT', numSD, 1, 20*num20, 1);
end

% Remove redundant zeros between information bit repetitions
if strcmp(chanBW, 'CBW80')
    infoBitRep = deparserOut(1:end-2, :);
elseif strcmp(chanBW, 'CBW160')
    infoBitRep = deparserOut([1:end/2-2,end/2+1:end-2], :);
else
    infoBitRep = deparserOut;
end

% BCC decoding: length 26 for 'CBW20', 27 for 'CBW40' and 29 for 'CBW80'
% and 'CBW160'
recBitLen = length(infoBitRep)/num20/2;
bits = wlan.internal.wlanBCCDecode(mean(reshape(infoBitRep, [], num20), 2), ...
        '1/2', recBitLen);

end

% [EOF]