Этот пример показывает обработку передачи и приема для 802.11ac™ многопользовательской передачи по нисходящей линии связи по каналу замирания. В примере используются методы линейного предварительного кодирования, основанные на сингулярном разложении (SVD) канала.
802.11ac поддерживает нисходящие (точка доступа к станции) многопользовательские передачи для четырех пользователей и до восьми передающих антенн для увеличения совокупной пропускной способности линии [1]. На основании запланированного времени передачи для пользователя планировщик ищет другие пакеты меньшего размера, готовые для передачи другим пользователям. Если доступно, он планирует этих пользователей в течение одного и того же интервала, что уменьшает общее время, затрачиваемое на несколько передач.
Эта одновременная передача имеет более высокую сложность, поскольку успешный прием полезной нагрузки отдельного пользователя требует предварительного кодирования, также известного как формирование луча на передающей стороне. Предварительное кодирование предполагает, что информация о состоянии канала (CSI) известна в передатчике. Зондирующий пакет, как описано в примере формирования луча передачи 802.11ac, используется для определения CSI для каждого пользователя в многопользовательской передаче. Каждый из пользователей передает свой индивидуальный CSI в формирователь луча. Формирователь луча использует CSI от всех пользователей для установки матрицы предварительного кодирования (пространственного отображения) для последующей передачи данных.
В этом примере используется метод инверсии канала для трехпользовательской передачи с различным количеством пространственных потоков, выделенных на пользователя, и различными параметрами скорости на пользователя. Система может быть охарактеризована на рисунке ниже.

Пример генерирует многопользовательский сигнал передачи, пропускает его через канал на пользователя и декодирует принятый сигнал для каждого пользователя, чтобы вычислить ошибочные биты. Перед передачей данных пример использует передачу нулевого пакета данных (NDP) для звучания различных каналов и определяет матрицу предварительного кодирования в предположении совершенной обратной связи.
Для 802.11ac допускается максимум восемь пространственных потоков. В этом примере используется конфигурация 6x6 MIMO для трех пользователей, где первый пользователь имеет три потока, второй - один, а третий - два выделенных ему потока. В качестве векторных параметров указываются различные параметры скорости и размеры полезной нагрузки для четырех пользователей. Они соответствующим образом индексируются в конфигурации передачи на основе количества активных пользователей.
s = rng(21); % Set RNG seed for repeatability % Transmission parameters chanBW = 'CBW80'; % Channel bandwidth numUsers = 3; % Number of active users numSTSAll = [3 1 2 2]; % Number of streams for 4 users userPos = [0 1 2 3]; % User positions for maximum 4 users mcsVec = [4 6 2 2]; % MCS for maximum 4 users apepVec = [15120 8192 5400 6000]; % Payload, in bytes, for 4 users chCodingVec = {'BCC', 'LDPC', 'LDPC', 'BCC'}; % Channel coding for 4 users % Channel and receiver parameters chanMdl = 'Model-A'; % TGac fading channel model precodingType = 'ZF'; % Precoding type; ZF or MMSE snr = 38; % SNR in dB eqMethod = 'ZF'; % Equalization method % Create the multi-user VHT format configuration object, appropriately % indexing into the vector values for the active users if (numUsers==1) groupID = 0; else groupID = 2; end numSTSVec = numSTSAll(1:numUsers); numTx = sum(numSTSVec); cfgVHTMU = wlanVHTConfig('ChannelBandwidth', chanBW,... 'NumUsers', numUsers, ... 'NumTransmitAntennas', numTx, ... 'GroupID', groupID, ... 'NumSpaceTimeStreams', numSTSVec,... 'UserPositions', userPos(1:numUsers), ... 'MCS', mcsVec(1:numUsers), ... 'APEPLength', apepVec(1:numUsers), ... 'ChannelCoding', chCodingVec(1:numUsers));
Количество передающих антенн устанавливается равным сумме всех используемых пространственно-временных потоков. Это подразумевает, что для передачи не используется пространственно-временное блочное кодирование (STBC) или пространственное расширение.
Для предварительного кодирования сначала используется канальное зондирование для определения канала, с которым сталкиваются пользователи (приемники). Эта информация о состоянии канала посылается обратно в передатчик для ее использования для последующей передачи данных. Предполагается, что канал медленно изменяется в течение двух передач. Для многопользовательских передач один и тот же NDP (нулевой пакет данных) передается каждому из запланированных пользователей [2].
% VHT sounding (NDP) configuration, for same number of streams cfgVHTNDP = wlanVHTConfig('ChannelBandwidth', chanBW,... 'NumUsers', 1, ... 'NumTransmitAntennas', numTx, ... 'GroupID', 0, ... 'NumSpaceTimeStreams', sum(numSTSVec),... 'MCS', 0, ... 'APEPLength', 0);
Указанное количество потоков является суммой всех используемых пространственно-временных потоков. Это позволяет звучать всему каналу.
% Generate the null data packet, with no data
txNDPSig = wlanWaveformGenerator([], cfgVHTNDP);
Многопользовательский канал TGac состоит из независимых однопользовательских каналов MIMO между точкой доступа и пространственно разделенными станциями [4]. В этом примере один и тот же канал Model-A профиля задержки применяется для каждого из пользователей, даже если отдельные пользователи могут испытывать различные условия. Канал с плоским замиранием обеспечивает более простой приемник без внешней синхронизации. Также предполагается, что количество приемных антенн каждого пользователя равно количеству выделенных им пространственно-временных потоков.
В данном примере массивы ячеек используются для хранения элементов для каждого пользователя, которые обеспечивают гибкое количество пользователей. Здесь, в качестве примера, каждый экземпляр канала TGac на пользователя сохраняется как элемент массива ячеек.
% Create three independent channels TGAC = cell(numUsers, 1); chanSeeds = [1111 2222 3333 4444]; % chosen for a maximum of 4 users uIndex = [10 5 2 1]; % chosen for a maximum of 4 users chanDelay = zeros(numUsers, 1); for uIdx = 1:numUsers TGAC{uIdx} = wlanTGacChannel(... 'ChannelBandwidth', cfgVHTMU.ChannelBandwidth,... 'DelayProfile', chanMdl, ... 'UserIndex', uIndex(uIdx), ... 'NumTransmitAntennas', numTx, ... 'NumReceiveAntennas', numSTSVec(uIdx), ... 'RandomStream', 'mt19937ar with seed', ... 'Seed', chanSeeds(uIdx),... 'SampleRate', wlanSampleRate(cfgVHTMU), ... 'TransmitReceiveDistance',5); chanInfo = info(TGAC{uIdx}); chanDelay(uIdx) = chanInfo.ChannelFilterDelay; end
Каналы для каждого отдельного пользователя используют различные начальные значения для генерации случайных чисел. Для применения случайных смещений углов к углам прихода (AoA) и отправления (AoD) для кластеров задается другой индекс пользователя. Задержка фильтрации канала сохраняется для обеспечения возможности ее компенсации в приемнике. На практике будет использоваться оценка синхронизации символа.
% Append zeroes to allow for channel filter delay txNDPSig = [txNDPSig; zeros(10, numTx)]; % Sound the independent channels per user for all transmit streams rxNDPSig = cell(numUsers, 1); for uIdx = 1:numUsers rxNDPChan = TGAC{uIdx}(txNDPSig); % Add WGN per receiver rxNDPSig{uIdx} = awgn(rxNDPChan, snr); end
Каждый пользователь оценивает свой собственный канал, используя принятый сигнал NDP, и вычисляет информацию о состоянии канала, которую он может отправить обратно в передатчик. В этом примере используется разложение сингулярного значения канала, видимого каждому пользователю, для вычисления обратной связи CSI.
mat = cell(numUsers,1); for uIdx = 1:numUsers % Compute the feedback matrix based on received signal per user mat{uIdx} = vhtCSIFeedback(rxNDPSig{uIdx}(chanDelay(uIdx)+1:end,:), ... cfgVHTNDP, uIdx, numSTSVec); end
Предполагая совершенную обратную связь без потерь сжатия или квантования CSI, передатчик вычисляет управляющую матрицу для передачи данных с использованием методов предварительного кодирования, основанных либо на нулевом форсировании, либо на минимальном среднем квадрате (MMSE). Оба способа пытаются отменить интерференцию внутри потока для интересующего пользователя и интерференцию для других пользователей. Подход, основанный на MMSE, позволяет избежать усиления шума, присущего технике нулевого форсирования. В результате он работает лучше при низких ОСШ.
% Pack the per user CSI into a matrix numST = length(mat{1}); % Number of subcarriers steeringMatrix = zeros(numST, sum(numSTSVec), sum(numSTSVec)); % Nst-by-Nt-by-Nsts for uIdx = 1:numUsers stsIdx = sum(numSTSVec(1:uIdx-1))+(1:numSTSVec(uIdx)); steeringMatrix(:,:,stsIdx) = mat{uIdx}; % 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 % Set the spatial mapping based on the steering matrix cfgVHTMU.SpatialMapping = 'Custom'; cfgVHTMU.SpatialMappingMatrix = permute(steeringMatrix,[1 3 2]);
Случайные биты используются в качестве полезной нагрузки для отдельных пользователей. Массив ячеек используется для хранения битов данных для каждого пользователя. txDataBits. Для многопользовательской передачи полезные нагрузки отдельных пользователей дополняются таким образом, что продолжительность передачи одинакова для всех пользователей. Этот процесс заполнения описан в разделе 9.12.6 из [1]. В этом примере для простоты полезная нагрузка дополняется нулями для создания PSDU для каждого пользователя.
% Create data sequences, one for each user txDataBits = cell(numUsers, 1); psduDataBits = cell(numUsers, 1); for uIdx = 1:numUsers % Generate payload for each user txDataBits{uIdx} = randi([0 1], cfgVHTMU.APEPLength(uIdx)*8, 1, 'int8'); % Pad payload with zeros to form a PSDU psduDataBits{uIdx} = [txDataBits{uIdx}; ... zeros((cfgVHTMU.PSDULength(uIdx)-cfgVHTMU.APEPLength(uIdx))*8, 1, 'int8')]; end
Используя конфигурацию формата, cfgVHTMUс матрицей управления данные передаются по каналу замирания.
% Generate the multi-user VHT waveform txSig = wlanWaveformGenerator(psduDataBits, cfgVHTMU); % Transmit through per-user fading channel rxSig = cell(numUsers, 1); for uIdx = 1:numUsers % Append zeroes to allow for channel filter delay rxSig{uIdx} = TGAC{uIdx}([txSig; zeros(10, numTx)]); end
Сигналы приема для каждого пользователя обрабатываются индивидуально. В примере предполагается, что отсутствуют внешние нарушения и что конфигурация передачи известна приемнику для простоты.
Номер пользователя определяет пользователя, представляющего интерес, который декодируется для передачи. Это также используется для индексирования в векторные свойства объекта конфигурации, специфичные для пользователя.
% Get field indices from configuration, assumed known at receiver ind = wlanFieldIndices(cfgVHTMU); % Single-user receivers recover payload bits rxDataBits = cell(numUsers, 1); scaler = zeros(numUsers, 1); spAxes = gobjects(sum(numSTSVec), 1); hfig = figure('Name','Per-stream equalized symbol constellation'); for uIdx = 1:numUsers % Add WGN per receiver rxNSig = awgn(rxSig{uIdx}, snr); rxNSig = rxNSig(chanDelay(uIdx)+1:end, :); % User space-time streams stsU = numSTSVec(uIdx); % Perform channel estimation based on VHT-LTF rxVHTLTF = rxNSig(ind.VHTLTF(1):ind.VHTLTF(2),:); demodVHTLTF = wlanVHTLTFDemodulate(rxVHTLTF, chanBW, numSTSVec); chanEst = wlanVHTLTFChannelEstimate(demodVHTLTF, chanBW, numSTSVec); % Get single stream channel estimate chanEstSSPilots = vhtSingleStreamChannelEstimate(demodVHTLTF,cfgVHTMU); % Extract VHT Data samples from the waveform rxVHTData = rxNSig(ind.VHTData(1):ind.VHTData(2),:); % Estimate the noise power in VHT data field nVar = vhtNoiseEstimate(rxVHTData,chanEstSSPilots,cfgVHTMU); % Recover information bits in VHT Data field [rxDataBits{uIdx}, ~, eqsym] = wlanVHTDataRecover(rxVHTData, ... chanEst, nVar, cfgVHTMU, uIdx, 'EqualizationMethod', eqMethod, ... 'PilotPhaseTracking', 'None', 'LDPCDecodingMethod', 'layered-bp'); % Plot equalized symbols for all streams per user scaler(uIdx) = ceil(max(abs([real(eqsym(:)); imag(eqsym(:))]))); for i = 1:stsU subplot(numUsers, max(numSTSVec), (uIdx-1)*max(numSTSVec)+i); plot(reshape(eqsym(:,:,i), [], 1), '.'); axis square spAxes(sum([0 numSTSVec(1:(uIdx-1))])+i) = gca; % Store axes handle title(['User ' num2str(uIdx) ', Stream ' num2str(i)]); grid on; end end % Scale axes for all subplots and scale figure for i = 1:numel(spAxes) xlim(spAxes(i),[-max(scaler) max(scaler)]); ylim(spAxes(i),[-max(scaler) max(scaler)]); end pos = get(hfig, 'Position'); set(hfig, 'Position', [pos(1)*0.7 pos(2)*0.7 1.3*pos(3) 1.3*pos(4)]);

Графики выровненной комбинации символов для каждого потока проверяют параметры моделирования и передают эффективность метода. Обратите внимание на различимые совокупности 16QAM, 64QAM и QPSK для каждого пользователя, как указано на передающем конце. Также наблюдайте ухудшение EVM над различными потоками для отдельного пользователя. Это характерная характеристика метода инверсии каналов.
Восстановленные биты данных сравниваются с переданными битами полезной нагрузки для определения частоты битовых ошибок.
% Compare recovered bits against per-user APEPLength information bits ber = inf(1, numUsers); for uIdx = 1:numUsers idx = (1:cfgVHTMU.APEPLength(uIdx)*8).'; [~, ber(uIdx)] = biterr(txDataBits{uIdx}(idx), rxDataBits{uIdx}(idx)); disp(['Bit Error Rate for User ' num2str(uIdx) ': ' num2str(ber(uIdx))]); end rng(s); % Restore RNG state
Bit Error Rate for User 1: 0.00013228 Bit Error Rate for User 2: 0 Bit Error Rate for User 3: 0
Небольшое количество битовых ошибок в пределах дисперсии шума указывает на успешное декодирование данных для всех потоков для каждого пользователя, несмотря на изменение EVM, наблюдаемое в отдельных потоках.
Пример показывает конфигурацию многопользовательской передачи, независимое моделирование канала для каждого пользователя и обработку индивидуального приема с использованием методов предварительного кодирования инверсии канала.
Дальнейшее исследование включает в себя модификации параметров передачи и канала, альтернативные способы предварительного кодирования, более реалистичные приемники и механизм обратной связи, включающий в себя задержки и квантование.
В этом примере используются следующие вспомогательные функции:
Стандарт IEEE Std 802.11ac™-2013 IEEE для информационных технологий - Связь и обмен информацией между системами - Локальные и городские сети - Особые требования - Часть 11: Спецификации управления доступом к среде беспроводной локальной сети (MAC) и физического уровня (PHY) - Поправка 4: Улучшения для очень высокой пропускной способности для работы в диапазонах ниже 6 GY
Perahia, E., R. Stacey, «Следующее поколение беспроводных LANS: 802.11n и 802.11ac», Cambridge University Press, 2013.
Стандарт IEEE Std 802.11™-2012 IEEE для информационных технологий - Телекоммуникации и обмен информацией между системами - Локальные и городские сети - Особые требования - Часть 11: Спецификации управления доступом к среде беспроводной локальной сети (MAC) и физического уровня (PHY).
Breit, G., H. Sampath, S. Vermani и др., «Добавление к модели канала TGac», версия 12. IEEE 802.11-09/0308r12, март 2010 г.