Развертка луча NR SSB

В этом примере показано, как использовать луч, развертывающийся и в передатчике (gNB) и в приемнике (UE) концы 5G система NR. Используя блоки сигнала синхронизации (SSB), этот пример иллюстрирует некоторые процедуры управления луча, используемые во время начального доступа. Чтобы выполнить развертку луча, пример использует несколько компонентов от Phased Array System Toolbox™.

Введение

Поддержка волны миллиметра (mmWave) частоты требует направленных ссылок, которые привели к спецификации процедур управления луча по начальному доступу в NR. Управление лучом является набором (физического) Слоя 1 и Слоя 2 (среднее управление доступом) процедуры, чтобы получить и обеспечить набор ссылок пары луча (луч, используемый в gNB, соединенном с лучом, используемым в UE). Процедуры управления луча применяются и для нисходящей и для восходящей передачи и приема [1], [2]. Эти процедуры включают:

  • Развертка луча

  • Излучите измерение

  • Излучите определение

  • Излучите создание отчетов

  • Излучите восстановление

Этот пример фокусируется на первоначальных процедурах доступа для неактивных пользователей, когда связь устанавливается между оборудованием пользователя (UE) и узлом сети доступа (gNB). На физическом уровне, с помощью блоков сигнала синхронизации (SSB), переданных как пакет в нисходящем направлении (gNB к UE), пример подсвечивает, и передайте/получите точку (TRP) развертка луча и луч UE, развертывающийся, чтобы установить ссылку пары луча. Среди нескольких процедур управления луча TR 38.802 задает эту развертку двойного конца как процедуру p-1 [1].

После того, как соединенный, та же ссылка пары луча может использоваться для последующих передач. При необходимости лучи далее усовершенствованы с помощью CSI-RS (для нисходящего канала) и SRS (для восходящего канала). В случае отказа луча могут быть восстановлены эти парные ссылки. Для примера улучшения пары луча смотрите, что Улучшение Луча Конца Передачи Нисходящего канала NR Использует CSI-RS (5G Toolbox).

Этот пример генерирует пакет сигнала синхронизации NR, beamforms каждый из SSBs в пакете, чтобы развернуться и по азимуту и по направлениям вертикального изменения, передает этот сигнал beamformed по пространственному каналу рассеивания и обрабатывает этот полученный сигнал по нескольким лучам получать-конца. Пример измеряется, мощность приемника опорного сигнала (RSRP) для каждой передачи - получают пары луча (в двойном цикле), и определяет ссылку пары луча с максимальным RSRP. Эта ссылка пары луча таким образом показывает лучшее парное лучом в передаче, и получите концы для симулированного пространственного сценария. Этот рисунок показывает основные шаги обработки с единицами управления лучом, подсвеченными в цвете.

rng(211);                           % Set RNG state for repeatability

Параметры симуляции

Задайте системные параметры для примера. Измените эти параметры, чтобы исследовать их удар на систему.

prm.NCellID = 1;                    % Cell ID
prm.FreqRange = 'FR1';              % Frequency range: 'FR1' or 'FR2'
prm.CenterFreq = 3.5e9;             % Hz
prm.SSBlockPattern = 'Case B';      % Case A/B/C/D/E
prm.SSBTransmitted = [ones(1,8) zeros(1,0)];   % 4/8 or 64 in length

prm.TxArraySize = [8 8];            % Transmit array size, [rows cols]
prm.TxAZlim = [-60 60];             % Transmit azimuthal sweep limits
prm.TxELlim = [-90 0];              % Transmit elevation sweep limits

prm.RxArraySize = [2 2];            % Receive array size, [rows cols]
prm.RxAZlim = [-180 180];           % Receive azimuthal sweep limits
prm.RxELlim = [0 90];               % Receive elevation sweep limits

prm.ElevationSweep = false;         % Enable/disable elevation sweep
prm.SNRdB = 30;                     % SNR, dB
prm.RSRPMode = 'SSSwDMRS';          % {'SSSwDMRS', 'SSSonly'}

Пример использует эти параметры:

  • ID ячейки для сценария отдельной ячейки с одним BS и UE

  • Частотный диапазон, как строка, чтобы определять операцию FR1 или FR2

  • Центральная частота, в Гц, зависящем от частотного диапазона

  • Состав блока сигнала синхронизации как один из Случая A/B/C для FR1 и Случая D/E для FR2. Это также выбирает расстояние между поднесущими.

  • Переданный SSBs в шаблоне, как бинарный вектор из длины 4 или 8 для FR1 и длины 64 для FR2. Количество переданного SSBs определяет номер лучей и в передаче, и получите концы.

  • Передайте размер массивов, как двухэлементный вектор-строка, задающий количество антенных элементов в строках и столбцах массива передачи, соответственно. Универсальный прямоугольный массив (URA) используется, когда оба значения больше того.

  • Передайте азимутальные пределы развертки в градусах, чтобы задать запуск и конечные углы азимута для развертки

  • Передайте пределы развертки вертикального изменения в градусах, чтобы задать запуск и окончание углов возвышения для развертки

  • Получите размер массивов, как двухэлементный вектор-строка, задающий количество антенных элементов в строках и столбцах получить массива, соответственно. Универсальный прямоугольный массив (URA) используется, когда оба значения больше того.

  • Получите азимутальные пределы развертки в градусах, чтобы задать запуск и конечные углы азимута для развертки

  • Получите пределы развертки вертикального изменения в градусах, чтобы задать запуск и окончание углов возвышения для развертки

  • Включите или отключите развертку вертикального изменения и для передачи и получите концы. Включите развертку вертикального изменения для FR2 и/или URAs

  • Отношение сигнал-шум в дБ

  • Режим Measurement для SSB, чтобы задать использование только вторичных сигналов синхронизации ('SSSonly') или использование PBCH DM-RS наряду со вторичными сигналами синхронизации ('SSSwDMRS')

prm = validateParams(prm);

Пакетная настройка сигнала синхронизации

Настройте пакетные параметры сигнала синхронизации при помощи заданных системных параметров. Для начального доступа, набор периодичность SSB к 20 мс.

txBurst.BlockPattern = prm.SSBlockPattern;
txBurst.SSBTransmitted = prm.SSBTransmitted;
txBurst.NCellID = prm.NCellID;
txBurst.SSBPeriodicity = 20;
txBurst.NFrame = 0;
txBurst.Windowing = 0;
txBurst.DisplayBurst = true;

% Assume same subcarrier spacing for carrier as the burst
carrier = nrCarrierConfig('NCellID',prm.NCellID,'NFrame',txBurst.NFrame);
carrier.SubcarrierSpacing = prm.SCS;
carrierInfo = nrOFDMInfo(carrier);
txBurst.SampleRate = carrierInfo.SampleRate;

Обратитесь к учебным Блокам Сигнала Синхронизации и Пакетам (5G Toolbox) для получения дополнительной информации о блоках сигнала синхронизации и пакетах.

Настройка канала

Сконфигурируйте пространственное рассеивание канал MIMO channel. Эта модель канала применяет потери при распространении в свободном пространстве и, опционально, другие атмосферные затухания к входу. Задайте местоположения для BS и UE как [x,y,z] координаты в Декартовой системе. В зависимости от заданных размеров массивов используйте или универсальные линейные матрицы (ULA) или универсальные прямоугольные массивы (URA). Используйте изотропные антенные элементы для массивов.

c = physconst('LightSpeed');   % Propagation speed
lambda = c/prm.CenterFreq;     % Wavelength

prm.posTx = [0;0;0];           % Transmit array position, [x;y;z], meters
prm.posRx = [100;50;0];        % Receive array position, [x;y;z], meters

toRxRange = rangeangle(prm.posTx,prm.posRx);
spLoss = fspl(toRxRange,lambda);    % Free space path loss

% Transmit array
if prm.IsTxURA
    % Uniform rectangular array
    arrayTx = phased.URA(prm.TxArraySize,0.5*lambda, ...
        'Element',phased.IsotropicAntennaElement('BackBaffled',true));
else
    % Uniform linear array
    arrayTx = phased.ULA(prm.NumTx, ...
        'ElementSpacing',0.5*lambda, ...
        'Element',phased.IsotropicAntennaElement('BackBaffled',true));
end

% Receive array
if prm.IsRxURA
    % Uniform rectangular array
    arrayRx = phased.URA(prm.RxArraySize,0.5*lambda, ...
        'Element',phased.IsotropicAntennaElement);
else
    % Uniform linear array
    arrayRx = phased.ULA(prm.NumRx, ...
        'ElementSpacing',0.5*lambda, ...
        'Element',phased.IsotropicAntennaElement);
end

% Scatterer locations
prm.FixedScatMode = true;
if prm.FixedScatMode
    % Fixed single scatterer location
    prm.ScatPos = [50; 80; 0];
else
    % Generate scatterers at random positions
    Nscat = 10;        % Number of scatterers
    azRange = -180:180;
    elRange = -90:90;
    randAzOrder = randperm(length(azRange));
    randElOrder = randperm(length(elRange));
    azAngInSph = azRange(randAzOrder(1:Nscat));
    elAngInSph = elRange(randElOrder(1:Nscat));
    r = 20;            % radius
    [x,y,z] = sph2cart(deg2rad(azAngInSph),deg2rad(elAngInSph),r);
    prm.ScatPos = [x;y;z] + (prm.posTx + prm.posRx)/2;
end

% Configure channel
channel = phased.ScatteringMIMOChannel;
channel.PropagationSpeed = c;
channel.CarrierFrequency = prm.CenterFreq;
channel.SampleRate = txBurst.SampleRate;
channel.SimulateDirectPath = false;
channel.ChannelResponseOutputPort = true;
channel.Polarization = 'None';
channel.TransmitArray = arrayTx;
channel.TransmitArrayPosition = prm.posTx;
channel.ReceiveArray = arrayRx;
channel.ReceiveArrayPosition = prm.posRx;
channel.ScattererSpecificationSource = 'Property';
channel.ScattererPosition = prm.ScatPos;
channel.ScattererCoefficient = ones(1,size(prm.ScatPos,2));

% Get maximum channel delay
[~,~,tau] = channel(complex(randn(txBurst.SampleRate*1e-3,prm.NumTx), ...
    randn(txBurst.SampleRate*1e-3,prm.NumTx)));
maxChDelay = ceil(max(tau)*txBurst.SampleRate);

Разорвите генерацию

Создайте пакетную форму волны SS [3] путем вызова hSSBurst функция помощника. Сгенерированная форма волны еще не beamformed.

% Create and display burst information
txBurstInfo = hSSBurstInfo(txBurst);
disp(txBurstInfo);

% Generate burst waveform and grid
[burstWaveform,txBurstGrid] = hSSBurst(txBurst);
      SubcarrierSpacing: 30
               NCRB_SSB: -20
                  k_SSB: 0
     FrequencyOffsetSSB: 0
                    MIB: [24x1 double]
                      L: 8
               SSBIndex: [0 1 2 3 4 5 6 7]
                  i_SSB: [0 1 2 3 4 5 6 7]
               ibar_SSB: [0 1 2 3 4 5 6 7]
             SampleRate: 30720000
                   Nfft: 1024
                    NRB: 72
           CyclicPrefix: 'Normal'
    OccupiedSubcarriers: [240x1 double]
        OccupiedSymbols: [8x4 double]
              Windowing: 0

Развертка луча конца передачи

Чтобы достигнуть развертки луча TRP, beamform, каждый из SS блокируется в сгенерированном пакете с помощью аналога beamforming. На основе количества блоков SS в пакете и указанных диапазонах развертки, определите и азимут и направления вертикального изменения для различных лучей. Затем beamform индивидуум блокируется в пакете к каждому из этих направлений.

% Number of beams at both transmit and receive ends
numBeams = sum(txBurst.SSBTransmitted);

% Transmit beam angles in azimuth and elevation, equi-spaced
azBW = beamwidth(arrayTx,prm.CenterFreq,'Cut','Azimuth');
elBW = beamwidth(arrayTx,prm.CenterFreq,'Cut','Elevation');
txBeamAng = hGetBeamSweepAngles(numBeams,prm.TxAZlim,prm.TxELlim, ...
    azBW,elBW,prm.ElevationSweep);

% For evaluating transmit-side steering weights
SteerVecTx = phased.SteeringVector('SensorArray',arrayTx, ...
    'PropagationSpeed',c);

% Apply steering per OFDM symbol for each SSB
carrier.NSizeGrid = txBurstInfo.NRB;
ofdmInfo = nrOFDMInfo(carrier);
gridSymLengths = repmat(ofdmInfo.SymbolLengths,1, ...
    size(txBurstGrid,2)/length(ofdmInfo.SymbolLengths));
%   repeat burst over numTx to prepare for steering
strTxWaveform = repmat(burstWaveform,1,prm.NumTx)./sqrt(prm.NumTx);
for ssb = 1:length(txBurstInfo.SSBIndex)

    % Extract SSB waveform from burst
    blockSymbols = txBurstInfo.OccupiedSymbols(ssb,:);
    startSSBInd = sum(gridSymLengths(1:blockSymbols(1)-1))+1;
    endSSBInd = sum(gridSymLengths(1:blockSymbols(4)));
    ssbWaveform = strTxWaveform(startSSBInd:endSSBInd,1);

    % Generate weights for steered direction
    wT = SteerVecTx(prm.CenterFreq,txBeamAng(:,ssb));

    % Apply weights per transmit element to SSB
    strTxWaveform(startSSBInd:endSSBInd,:) = ssbWaveform.*(wT');

end

beamformed разрываются, форма волны затем передается по пространственно осведомленному каналу рассеивания.

Развертка луча получать-конца и измерение

Для развертки луча получать-конца разрываются переданные beamformed, форма волны получена последовательно по каждому, получают луч. Для N передайте лучи и M получите лучи в процедуре p-1, каждом N лучами является переданный M времена от gNB так, чтобы каждый луч передачи был получен по M получите лучи.

Пример принимает оба N и M быть равным количеству SSBs в пакете. Для простоты пример генерирует только один пакет, но подражать пакетному приему по воздуху M времена, приемник обрабатывает этот один пакет M \times.

Этот рисунок показывает основанную на луче схему для разверток и в gNB и в UE для N = M = 4, в азимутальной плоскости. Схема показывает время, потраченное для двойной развертки, где каждый интервал в gNB соответствует SSB, и каждый интервал в UE соответствует пакету SS. Для изображенного сценария, S3 лучей и U2 подсвечены как выбранная парная лучом ссылка умозрительно. Пример реализует двойную развертку по длительности времени N*M моменты времени.

Получить обработка переданного пакета включает

  • Приложение пространственно осведомленного исчезающего канала

  • Получите усиление, чтобы компенсировать вызванную потерю на пути и AWGN

  • Получать-конец beamforming

  • Синхронизация коррекции

  • Демодуляция OFDM

  • Извлечение известной сетки SSB

  • Измерение RSRP на основе заданного режима измерения

Обработка повторяет эти шаги для каждого из получить лучей, затем выбирает лучшее парное лучом на основе полного набора сделанных измерений.

Чтобы подсветить развертку луча, пример принимает известную информацию SSB в приемнике. Для получения дополнительной информации о восстановлении обработка смотрите Поиск Ячейки NR и MIB и Восстановление SIB1 (5G Toolbox).

Для нерабочего режима измерение SS-RSRP используйте или только вторичные сигналы синхронизации (SSS) или физический канал телевизионного вещания (PBCH) опорные сигналы демодуляции (DM-RS) в дополнение к SSS (Раздел 5.1.1. из [4]). Задайте это RSRPMode параметр примера. Для FR2 измерение RSRP основано на объединенном сигнале от антенных элементов, в то время как измерение на антенный элемент для FR1.

% Receive beam angles in azimuth and elevation, equi-spaced
azBW = beamwidth(arrayRx,prm.CenterFreq,'Cut','Azimuth');
elBW = beamwidth(arrayRx,prm.CenterFreq,'Cut','Elevation');
rxBeamAng = hGetBeamSweepAngles(numBeams,prm.RxAZlim,prm.RxELlim, ...
    azBW,elBW,prm.ElevationSweep);

% For evaluating receive-side steering weights
SteerVecRx = phased.SteeringVector('SensorArray',arrayRx, ...
    'PropagationSpeed',c);

% AWGN level
SNR = 10^(prm.SNRdB/20);                        % Convert to linear gain
N0 = 1/(sqrt(2.0*prm.NumRx*double(ofdmInfo.Nfft))*SNR); % Noise Std. Dev.

% Receive gain in linear terms, to compensate for the path loss
rxGain = 10^(spLoss/20);

% Generate a reference grid for timing correction
%   assumes an SSB in first slot
pssRef = nrPSS(carrier.NCellID);
pssInd = nrPSSIndices;
pbchdmrsRef = nrPBCHDMRS(carrier.NCellID,txBurstInfo.ibar_SSB(1));
pbchDMRSInd = nrPBCHDMRSIndices(carrier.NCellID);
pssGrid = zeros([240 4]);
pssGrid(pssInd) = pssRef;
pssGrid(pbchDMRSInd) = pbchdmrsRef;
refGrid = zeros([12*carrier.NSizeGrid ofdmInfo.SymbolsPerSlot]);
refGrid(txBurstInfo.OccupiedSubcarriers, ...
    txBurstInfo.OccupiedSymbols(1,:)) = pssGrid;

% Loop over all receive beams
rsrp = zeros(numBeams,numBeams);
for rIdx = 1:numBeams

    % Fading channel, with path loss
    txWave = [strTxWaveform; zeros(maxChDelay,size(strTxWaveform,2))];
    fadWave = channel(txWave);

    % Receive gain, to compensate for the path loss
    fadWaveG = fadWave*rxGain;

    % Add WGN
    noise = N0*complex(randn(size(fadWaveG)),randn(size(fadWaveG)));
    rxWaveform = fadWaveG + noise;

    % Generate weights for steered direction
    wR = SteerVecRx(prm.CenterFreq,rxBeamAng(:,rIdx));

    % Apply weights per receive element
    if strcmp(prm.FreqRange, 'FR1')
        strRxWaveform = rxWaveform.*(wR');
    else  % for FR2, combine signal from antenna elements
        strRxWaveform = rxWaveform*conj(wR);
    end

    % Correct timing
    offset = nrTimingEstimate(carrier, ...
        strRxWaveform(1:ofdmInfo.SampleRate*1e-3,:),refGrid*wR(1)');
    if offset > maxChDelay
        offset = 0;
    end
    strRxWaveformS = strRxWaveform(1+offset:end,:);

    % OFDM Demodulate
    rxGrid = nrOFDMDemodulate(carrier,strRxWaveformS);

    % Loop over all SSBs in rxGrid (transmit end)
    for tIdx = 1:numBeams
        % Get each SSB grid
        rxSSBGrid = rxGrid(txBurstInfo.OccupiedSubcarriers, ...
            txBurstInfo.OccupiedSymbols(tIdx,:),:);

        % Make measurements, store per receive, transmit beam
        rsrp(rIdx,tIdx) = measureSSB(rxSSBGrid,prm.RSRPMode,txBurst.NCellID);
    end
end

Излучите определение

После того, как развертка двойного конца и измерения завершены, определяют лучшую парную лучом ссылку на основе измерения RSRP.

[m,i] = max(rsrp,[],'all','linear');    % First occurrence is output
% i is column-down first (for receive), then across columns (for transmit)
[rxBeamID,txBeamID] = ind2sub([numBeams numBeams],i(1));

% Display the selected beam pair
disp(['Selected Beam pair with RSRP: ' num2str(10*log10(rsrp(rxBeamID, ...
    txBeamID))+30) ' dBm', 13 '  Transmit #' num2str(txBeamID) ...
    ' (Azimuth: ' num2str(txBeamAng(1,txBeamID)) ', Elevation: ' ...
    num2str(txBeamAng(2,txBeamID)) ')' 13 '  Receive #' num2str(rxBeamID) ...
    ' (Azimuth: ' num2str(rxBeamAng(1,rxBeamID)) ', Elevation: ' ...
    num2str(rxBeamAng(2,rxBeamID)) ')' ]);

% Display final beam pair patterns
h = figure('Position',figposition([32 55 32 40]),'MenuBar','none');
h.Name = 'Selected Transmit Array Response Pattern';
wT = SteerVecTx(prm.CenterFreq,txBeamAng(:,txBeamID));
pattern(arrayTx,prm.CenterFreq,'PropagationSpeed',c,'Weights',wT);

h = figure('Position',figposition([32 55 32 40]),'MenuBar','none');
h.Name = 'Selected Receive Array Response Pattern';
wR = SteerVecRx(prm.CenterFreq,rxBeamAng(:,rxBeamID));
pattern(arrayRx,prm.CenterFreq,'PropagationSpeed',c,'Weights',wR);

% Plot MIMO scenario with tx, rx, scatterers, and determined beams. Beam
% patterns in this figure resemble the power patterns in linear scale.
prmScene = struct();
prmScene.TxArray = arrayTx;
prmScene.RxArray = arrayRx;
prmScene.TxArrayPos = prm.posTx;
prmScene.RxArrayPos = prm.posRx;
prmScene.ScatterersPos = prm.ScatPos;
prmScene.Lambda = lambda;
prmScene.ArrayScaling = 1;     % To enlarge antenna arrays in the plot
prmScene.MaxTxBeamLength = 45; % Maximum length of transmit beams in the plot
prmScene.MaxRxBeamLength = 25; % Maximum length of receive beam in the plot
hPlotSpatialMIMOScene(prmScene,wT,wR);
if ~prm.ElevationSweep
    view(2);
end
Selected Beam pair with RSRP: 45.1516 dBm  Transmit #8 (Azimuth: 60, Elevation: 0)  Receive #6 (Azimuth: 90, Elevation: 0)

Эти графики подсвечивают шаблон направленности передачи, получают шаблон направленности и пространственную сцену, соответственно. Результаты зависят от отдельных направлений луча, используемых для разверток. Пространственная сцена открывает объединенный вид передачи, и получите массивы и соответствующие решительные лучи, наряду с рассеивателями.

Итоговое и дальнейшее исследование

Этот пример подсвечивает, что P-1 излучают процедуру управления при помощи блоков сигнала синхронизации для конца передачи и развертки луча получать-конца. Путем измерения мощности приемника опорного сигнала для SSBs можно идентифицировать лучшую ссылку пары луча для выбранной пространственной среды.

Пример позволяет изменение на частотном диапазоне, составе блока SSB, количестве SSBs, передачи, и получите размеры массивов, передайте и получите области значений развертки и измеряющийся режим. Чтобы видеть удар параметров на выборе луча, экспериментируйте с различными значениями. Получить обработка упрощена, чтобы подсветить beamforming аспекты для примера.

Для примера P-2 процедур развертки луча конца передачи с помощью сигналов CSI-RS для нисходящего канала смотрите, что Улучшение Луча Конца Передачи Нисходящего канала NR Использует CSI-RS (5G Toolbox). Можно использовать эти процедуры для улучшения луча и корректировки в связанном режиме, когда-то начальные ссылки пары луча устанавливаются [5], [6].

Ссылки

  1. 3GPP TR 38.802. "Исследование Новых Радио-технологических аспектов физического уровня доступа". Проект Партнерства третьего поколения; Сеть радиодоступа Technical Specification Group.

  2. Джордани, M., М. Полезе, А. Рой, Д. Кэстор и М. Зорзи. "Пример на управлении лучом для 3GPP NR на mmWave частотах". Коммуникация IEEE Surveys & Tutorials, издание 21, № 1, 1 квартал 2019.

  3. 3GPP TS 38.211. "NR; Физические каналы и модуляция". Проект Партнерства третьего поколения; Сеть радиодоступа Technical Specification Group.

  4. 3GPP TS 38.215. "NR; измерения Физического уровня". Проект Партнерства третьего поколения; Сеть радиодоступа Technical Specification Group.

  5. Джордани, M., М. Полезе, А. Рой, Д. Кэстор и М. Зорзи. "Автономное и неавтономное управление лучом для 3GPP NR в mmWaves". Коммуникация IEEE Мэг., апрель 2019, стр 123-129.

  6. Onggosanusi, E. S. Md. Рахман, и др. "Модульный и канал с высоким разрешением утверждает информацию и управление лучом для 5G NR". Коммуникация IEEE Мэг., март 2018, стр 48-55.

Локальные функции

function prm = validateParams(prm)
% Validate user specified parameters and return updated parameters
%
% Only cross-dependent checks are made for parameter consistency.

    if strcmpi(prm.FreqRange,'FR1')
        if prm.CenterFreq > 7.125e9 || prm.CenterFreq < 410e6
            error(['Specified center frequency is outside the FR1 ', ...
                   'frequency range (410 MHz - 7.125 GHz).']);
        end
        if strcmpi(prm.SSBlockPattern,'Case D') ||  ...
           strcmpi(prm.SSBlockPattern,'Case E')
            error(['Invalid SSBlockPattern for selected FR1 frequency ' ...
                'range. SSBlockPattern must be one of ''Case A'' or ' ...
                '''Case B'' or ''Case C'' for FR1.']);
        end
        if ~((length(prm.SSBTransmitted)==4) || ...
             (length(prm.SSBTransmitted)==8))
            error(['SSBTransmitted must be a vector of length 4 or 8', ...
                   'for FR1 frequency range.']);
        end
        if (prm.CenterFreq <= 3e9) && (length(prm.SSBTransmitted)~=4)
            error(['SSBTransmitted must be a vector of length 4 for ' ...
                   'center frequency less than or equal to 3GHz.']);
        end
        if (prm.CenterFreq > 3e9) && (length(prm.SSBTransmitted)~=8)
            error(['SSBTransmitted must be a vector of length 8 for ', ...
                   'center frequency greater than 3GHz and less than ', ...
                   'or equal to 7.125GHz.']);
        end
    else % 'FR2'
        if prm.CenterFreq > 52.6e9 || prm.CenterFreq < 24.25e9
            error(['Specified center frequency is outside the FR2 ', ...
                   'frequency range (24.25 GHz - 52.6 GHz).']);
        end
        if ~(strcmpi(prm.SSBlockPattern,'Case D') || ...
                strcmpi(prm.SSBlockPattern,'Case E'))
            error(['Invalid SSBlockPattern for selected FR2 frequency ' ...
                'range. SSBlockPattern must be either ''Case D'' or ' ...
                '''Case E'' for FR2.']);
        end
        if length(prm.SSBTransmitted)~=64
            error(['SSBTransmitted must be a vector of length 64 for ', ...
                   'FR2 frequency range.']);
        end
    end

    prm.NumTx = prod(prm.TxArraySize);
    prm.NumRx = prod(prm.RxArraySize);
    if prm.NumTx==1 || prm.NumRx==1
        error(['Number of transmit or receive antenna elements must be', ...
               ' greater than 1.']);
    end
    prm.IsTxURA = (prm.TxArraySize(1)>1) && (prm.TxArraySize(2)>1);
    prm.IsRxURA = (prm.RxArraySize(1)>1) && (prm.RxArraySize(2)>1);

    if ~( strcmpi(prm.RSRPMode,'SSSonly') || ...
          strcmpi(prm.RSRPMode,'SSSwDMRS') )
        error(['Invalid RSRP measuring mode. Specify either ', ...
               '''SSSonly'' or ''SSSwDMRS'' as the mode.']);
    end

    % Select SCS based on SSBlockPattern
    switch lower(prm.SSBlockPattern)
        case 'case a'
            scs = 15;
        case {'case b', 'case c'}
            scs = 30;
        case 'case d'
            scs = 120;
        case 'case e'
            scs = 240;
    end
    prm.SCS = scs;

end

function rsrp = measureSSB(rxSSBGrid,mode,NCellID)
% Compute the reference signal received power (RSRP) based on SSS, and if
% selected, also PBCH DM-RS.

    sssInd = nrSSSIndices;                       % SSS indices

    numRx = size(rxSSBGrid,3);
    rsrpSSS = zeros(numRx,1);
    for rxIdx = 1:numRx
        % Extract signals per rx element
        rxSSBGridperRx = rxSSBGrid(:,:,rxIdx);
        rxSSS = rxSSBGridperRx(sssInd);

        % Average power contributions over all REs for RS
        rsrpSSS(rxIdx) = mean(rxSSS.*conj(rxSSS));
    end

    if strcmpi(mode,'SSSwDMRS')
        pbchDMRSInd = nrPBCHDMRSIndices(NCellID);    % PBCH DM-RS indices
        rsrpDMRS = zeros(numRx,1);
        for rxIdx = 1:numRx
            % Extract signals per rx element
            rxSSBGridperRx = rxSSBGrid(:,:,rxIdx);
            rxPBCHDMRS = rxSSBGridperRx(pbchDMRSInd);

            % Average power contributions over all REs for RS
            rsrpDMRS(rxIdx) = mean(rxPBCHDMRS.*conj(rxPBCHDMRS));
        end
    end

    switch lower(mode)
        case 'sssonly'  % Only SSS
           rsrp = max(rsrpSSS);     % max over receive elements
        case 'ssswdmrs' % Both SSS and PBCH-DMRS, accounting for REs per RS
           rsrp = max((rsrpSSS*127+rsrpDMRS*144)/271); % max over receive elements
    end
end