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]