www.gusucode.com > wlan工具箱matlab源码程序 > wlan/wlan/+wlan/+internal/wlanEqualize.m
function [y, CSI] = wlanEqualize(x, chanEst, eqMethod, varargin) %wlanEqualize Perform MIMO channel equalization. % % Note: This is an internal undocumented function and its API and/or % functionality may change in subsequent releases. % % [Y, CSI] = wlanEqualize(X, CHANEST, 'ZF') performs equalization using % the signal input X and the channel estimation input CHANEST, and % returns the estimation of transmitted signal in Y and the soft channel % state information in CSI. The zero-forcing (ZF) method is used. The % inputs X and CHANEST can be double precision 2-D matrices or 3-D arrays % with real or complex values. X is of size Nsd x Nsym x Nr, where Nsd % represents the number of data subcarriers (frequency domain), Nsym % represents the number of OFDM symbols (time domain), and Nr represents % the number of receive antennas (spatial domain). CHANEST is of size Nsd % x Nsts x Nr, where Nsts represents the number of space-time streams. % The double precision output Y is of size Nsd x Nsym x Nsts. Y is % complex when either X or CHANEST is complex and is real otherwise. The % double precision, real output CSI is of size Nsd x Nsts. % % [Y, CSI] = wlanEqualize(X, CHANEST, 'MMSE', NOISEVAR) performs the % equalization using the minimum-mean-square-error (MMSE) method. The % noise variance input NOISEVAR is a double precision, real, nonnegative % scalar. % % See also wlanSTBCCombine. % Copyright 2015-2016 The MathWorks, Inc. %#codegen %#ok<*EMCA> % Input validation narginchk(3, 4); validateattributes(x, {'double'}, {'3d','finite','nonempty'}, ... 'wlanEqualize:InSignal', 'signal input'); validateattributes(chanEst, {'double'}, {'3d','finite','nonempty'}, ... 'wlanEqualize:ChanEst', 'channel estimation input'); coder.internal.errorIf(~strcmp(eqMethod, 'ZF') && ~strcmp(eqMethod, 'MMSE'), ... 'wlan:wlanEqualize:InvalidEqMethod'); coder.internal.errorIf(size(x, 1) ~= size(chanEst, 1), ... 'wlan:wlanEqualize:UnequalFreqCarriers'); coder.internal.errorIf(size(x, 3) ~= size(chanEst, 3), ... 'wlan:wlanEqualize:UnequalNumRx'); if strcmp(eqMethod, 'MMSE') narginchk(4,4); validateattributes(varargin{1}, {'double'}, {'real','scalar','nonnegative','finite','nonempty'}, ... 'wlanEqualizer:noiseVarEst', 'noise variance estimation input'); noiseVarEst = varargin{1}; else % ZF noiseVarEst = 0; end % Perform equalization numTx = size(chanEst, 2); numRx = size(chanEst, 3); CSI = zeros(size(x, 1), numTx); % Pre-allocation here for code generation if (numTx == 1 && numRx == 1) % SISO CSI = real(chanEst.*conj(chanEst)) + noiseVarEst; y = bsxfun(@times, x, conj(chanEst(:))./CSI(:)); % (:) for codegen elseif (numTx == 1 && numRx > 1) % SIMO chanEst2D = reshape(chanEst, size(chanEst, 1), numRx); CSI = real(diag(chanEst2D*chanEst2D')) + noiseVarEst; y = bsxfun(@rdivide, sum(bsxfun(@times, x, conj(chanEst(:,1,:))), 3), CSI(:)); % Indexing for codegen elseif (numTx > 1 && numRx == 1) % MISO chanPower = real(chanEst.*conj(chanEst)); if strcmp(eqMethod, 'ZF') CSI = chanPower; else % Use Schur complement formula CSI = noiseVarEst + noiseVarEst*chanPower./... (bsxfun(@minus, sum(chanPower, 2), chanPower) + noiseVarEst); end chanEstInv = bsxfun(@rdivide, conj(chanEst), sum(chanPower, 2)+noiseVarEst); chanEstInvPermute = permute(chanEstInv, [1 3 2]); y = bsxfun(@times, x(:,:,1), chanEstInvPermute(:,1,:)); % Indexing for codegen elseif (numTx > numRx) && strcmp(eqMethod, 'ZF') % MIMO: singular channel matrix using ZF numSym = size(x, 2); CSI = sum(real(chanEst .* conj(chanEst)), 3); y = complex(zeros(size(x, 1), numSym, numTx)); for idx = 1:size(chanEst, 1) y(idx, :, 1:numTx) = reshape(x(idx, :, :), numSym, numRx) * ... pinv(reshape(chanEst(idx,:,:), numTx, numRx)); end else % MIMO: numTx > numRx using MMSE or numTx <= numRx numSym = size(x, 2); y = complex(zeros(size(x, 1), numSym, numTx)); for idx = 1:size(chanEst, 1) H = reshape((chanEst(idx,:,:)), numTx, numRx); invH = inv(H*H'+noiseVarEst*eye(numTx)); CSI(idx, :) = 1./real(diag(invH)); y(idx, :, 1:numTx) = reshape(x(idx, :, :), numSym, numRx) * H' * invH; %#ok<MINV> end end % [EOF