You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

115 lines
4.1 KiB

function steeringMatBF = heMUCalculateSteeringMatrix(steeringMatFB,cfg,cfgNDP,ruIdx)
%heMUCalculateSteeringMatrix Calculate beamforming steering matrix
%
% Note: This is an internal undocumented function and its API and/or
% functionality may change in subsequent releases.
%
% STEERINGMATBF = heMUCalculateSteeringMatrix(STEERINGMATFB,CFG,CFGNDP,RUIDX)
% returns the steering matrix recommended to beamform an RU in a transmit
% beamforming, or MU-MIMO configuration. ZF precoding is used.
%
% STEERINGMATFB is a cell array containing the steering matrices fed-back
% by each user in the RU to beamform.
%
% CFG is the configuration of the HE-MU transmission and is a format
% configuration object of type
% <a href="matlab:help('wlanHEMUConfig')">wlanHEMUConfig</a>.
%
% CFGNDP is the configuration of the HE-NDP used to gather feedback and
% is a format configuration object of type
% <a href="matlab:help('wlanHESUConfig')">wlanHESUConfig</a>.
%
% RUIDX is the RU index.
% Copyright 2018 The MathWorks, Inc.
allocInfo = ruInfo(cfg);
% Indices of active subcarriers within the RU
ruOFDMInfo = wlanHEOFDMInfo('HE-Data',cfg,ruIdx);
ruInd = ruOFDMInfo.ActiveFrequencyIndices;
% Indices of active subcarriers in the NDP
ndpOFDMInfo = wlanHEOFDMInfo('HE-Data',cfgNDP);
trainingInd = ndpOFDMInfo.ActiveFrequencyIndices;
% Get the indices which overlap - use to extract from NDP
[~,scUseInd] = intersect(trainingInd,ruInd);
% Extract the RU of interest from the full bandwidth grid
numUsers = allocInfo.NumUsersPerRU(ruIdx);
steeringMatUse = cell(numUsers,1);
for i = 1:numUsers
% Only take the RU subcarriers and space-time streams of
% interest for the current RU and user
userIdx = cfg.RU{ruIdx}.UserNumbers(i);
numSTS = cfg.User{userIdx}.NumSpaceTimeStreams;
numRx = size(steeringMatFB{userIdx},2);
if numSTS>numRx
error('The number of space-time streams (%d) exceeds the number of receive antennas (%d) for user %d',numSTS,numRx,userIdx);
end
steeringMatUse{i} = steeringMatFB{userIdx}(scUseInd,1:numSTS,:);
end
% Extract steering matrix for each RU
if numUsers>1
steeringMatBF = muSteeringMatrixFromFeedback(steeringMatUse);
else
steeringMatBF = steeringMatUse{1};
end
end
function steeringMatrix = muSteeringMatrixFromFeedback(mappingMatrix,varargin)
% Q = muSteeringMatrixFromFeedback(QU) calculates the spatial mapping
% matrix for a MU transmission using the ZF algorithm.
%
% Q is an Nst-by-Nsts-by-Nt mapping matrix. Nst is the number of
% subcarriers, Nsts is the total number of space-time streams, and Nt is
% the number of transmit antennas.
%
% QU is a cell array containing the individual mapping matrix for each
% user. Each element of QU is sized Nst-by-Nstsu-by-Nt, where Nstsu is
% the number of space-time streams for the individual user.
%
% Q = muSteeringMatrixFromFeedback(QU,SNR) calculates the spatial mapping
% matrix for a MU transmission using the MMSE algorithm given the SNR.
if nargin>1
precodingType = 'MMSE';
snr = varargin{1};
else
precodingType = 'ZF';
end
numUsers = numel(mappingMatrix);
% Get the number of STS per user
numSTS = zeros(numUsers,1);
for uIdx = 1:numUsers
numSTS(uIdx) = size(mappingMatrix{uIdx},2);
end
numSTSTotal = sum(numSTS);
% Pack the per user CSI into a matrix
[numST,~,numTx] = size(mappingMatrix{1}); % Number of subcarriers
steeringMatrix = zeros(numST,numTx,numSTSTotal); % Nst-by-Nt-by-Nsts
for uIdx = 1:numUsers
stsIdx = sum(numSTS(1:uIdx-1))+(1:numSTS(uIdx));
steeringMatrix(:,:,stsIdx) = permute(mappingMatrix{uIdx},[1 3 2]); % Nst-by-Nt-by-Nsts
end
% Zero-forcing or MMSE precoding solution
if strcmp(precodingType, 'ZF')
delta = 0; % Zero-forcing
else
delta = (numTx/(10^(snr/10))) * eye(numTx); % MMSE
end
for i = 1:numST
% Channel inversion precoding
h = squeeze(steeringMatrix(i,:,:));
steeringMatrix(i,:,:) = h/(h'*h + delta);
end
steeringMatrix = permute(steeringMatrix,[1 3 2]);
end