gusucode.com > wlan工具箱matlab源码程序 > wlan/wlan/+wlan/+internal/wlanSTBCCombine.m
function [y, CSI] = wlanSTBCCombine(x, chanEst, numSS, eqMethod, varargin) %wlanSTBCCombine Perform space-time block code (STBC) combining % % Note: This is an internal undocumented function and its API and/or % functionality may change in subsequent releases. % % [Y, CSI] = wlanSTBCCombine(X, CHANEST, NUMSS, 'ZF') performs STBC % combining using the signal input X and the channel estimates input % CHANEST, according to the STBC scheme for HT and VHT formats. % Zero-forcing (ZF) equalization is performed for the combining. % % Y is a complex array of size Nsd-by-Nsym-by-Nss containing the estimate % of the transmitted signal. Nsd represents the number of data % subcarriers (frequency domain), Nsym represents the number of OFDM % symbols (time domain) and must be even, and Nss represents the number % of spatial streams (spatial domain), also given by NUMSS. Y is complex % when either X or CHANEST is complex and is real otherwise. % % CSI is a real matrix of size Nsd-by-Nss representing the soft channel % state information. % % X is complex 3D array of size Nsd-by-Nsym-by-Nr representing the % frequency domain input signal, where Nr represents the number of % receive antennas. % % CHANEST is a complex 3D array of size Nsd-by-Nsts-by-Nr, where Nsts % represents the number of space-time streams. Nsts must be either twice % more than Nss or equal to Nss+1 when Nss = 2 or 3. % % NUMSS is a double precision, real, positive integer scalar, which % represents the number of spatial streams. % % [Y, CSI] = wlanSTBCCombine(X, CHANEST, NUMSS, 'MMSE', NOISEVAR) % performs the STBC combining using the minimum-mean-square-error (MMSE) % equalization method. The noise variance input NOISEVAR is a double % precision, real, nonnegative scalar. % % See also wlanSTBCEncode. % Copyright 2015-2016 The MathWorks, Inc. %#codegen %#ok<*EMCA> % Input validation narginchk(4, 5); validateattributes(x, {'double'}, {'3d','finite','nonempty'}, ... 'wlanSTBCCombine:InSignal', 'signal input'); coder.internal.errorIf(mod(size(x, 2), 2) ~= 0, ... 'wlan:wlanSTBCCombine:InvalidNumSym'); validateattributes(numSS, {'double'}, {'real','scalar','positive','finite'}, ... 'wlanSTBCCombine:NumSS', 'number of spatial streams'); validateattributes(chanEst, {'double'}, {'3d','finite','nonempty'}, ... 'wlanSTBCCombine:ChanEst', 'channel estimation input'); coder.internal.errorIf(~strcmp(eqMethod, 'ZF') && ~strcmp(eqMethod, 'MMSE'), ... 'wlan:wlanSTBCCombine:InvalidEqMethod'); coder.internal.errorIf(size(x, 1) ~= size(chanEst, 1), ... 'wlan:wlanSTBCCombine:UnequalFreqCarriers'); coder.internal.errorIf(size(x, 3) ~= size(chanEst, 3), ... 'wlan:wlanSTBCCombine:UnequalNumRx'); numSTS = size(chanEst, 2); coder.internal.errorIf((numSTS ~= 2*numSS) && ... ~((numSTS == numSS + 1) && (numSS == 2 || numSS == 3)), ... 'wlan:wlanSTBCCombine:InvalidSSAndSTSComb'); if strcmp(eqMethod, 'MMSE') narginchk(5,5); validateattributes(varargin{1}, {'double'}, {'real','scalar','nonnegative','finite','nonempty'}, ... 'wlanSTBCCombine:noiseVarEst', 'noise variance estimation input'); noiseVarEst = varargin{1}; else noiseVarEst = 0; end % Perform combining numSD = size(x, 1); numSym = size(x, 2); numRx = size(chanEst, 3); % Expand channel matrix to size [numSD 2*numSS numRx] by inserting zero links if (numSS == 2) && (numSTS == 3) modifiedH = cat(2, chanEst, zeros(numSD, 1, numRx)); elseif (numSS == 3) && (numSTS == 4) modifiedH = cat(2, chanEst(:,1:3,:), zeros(numSD, 1, numRx), ... chanEst(:,4,:), zeros(numSD, 1, numRx)); else % numSTS == 2*numSS modifiedH = chanEst; end num2SS = size(modifiedH, 2); % = 2*numSS % Derive equivalent channel matrix eqH = complex(zeros(numSD, num2SS, 2*numRx)); eqH(:, 1:2:end, 1:2:end) = conj(modifiedH(:, 1:2:end, :)); eqH(:, 2:2:end, 1:2:end) = -conj(modifiedH(:, 2:2:end, :)); eqH(:, :, 2:2:end) = reshape(flip(reshape(modifiedH, numSD, 2, []), 2), ... numSD, num2SS, numRx); % Derive equivalent receiver matrix x(:, 1:2:end, :) = conj(x(:, 1:2:end, :)); eqR = reshape(permute(reshape(x, numSD, 2, [], numRx), [1 3 2 4]), ... numSD, [], 2*numRx); % [numSD numSym/2 2*numRx] % Perform equalization CSI = zeros(numSD, numSS); if (numSS == 1) && (numSTS == 2) % Take advantage of orthogonal channel matrix chanEst2D = reshape(chanEst, numSD, []); CSI(:,1) = real(sum(chanEst2D.*conj(chanEst2D), 2)) + noiseVarEst; % [numSD numSS] eqOut = complex(zeros(numSD, numSym/2, numSTS)); % [numSD numSym/2 2*numSS] for idx = 1:numSD eqOut(idx, :, :) = reshape(eqR(idx,:,:), [], 2*numRx) * ... reshape(eqH(idx,:,:), 2, 2*numRx)' / CSI(idx); end else % Regular equalization % Instead of calling equalization function directly, we can exploit % block matrix inversion algorithm for faster performance. [eqOut, eqCSI] = wlan.internal.wlanEqualize(eqR, eqH, eqMethod, ... noiseVarEst); % [numSD numSym/2 2*numSS] CSI(:) = eqCSI(:, 1:2:end); % [numSD numSS] end % Organize output eqOut(:,:,1:2:end) = conj(eqOut(:,:,1:2:end)); y = reshape(permute(reshape(eqOut, numSD, [], 2, numSS), [1 3 2 4]), ... numSD, [], numSS); % [numSD numSym numSS] end % [EOF]