exponenta event banner

Подметание луча NR SSB

Этот пример показывает, как использовать подметание луча как на конце передатчика (gNB), так и на конце приемника (UE) системы 5G NR. Используя блоки сигналов синхронизации (SSB), этот пример иллюстрирует некоторые процедуры управления лучом, используемые во время начального доступа. Для выполнения протягивания балки в примере используется несколько компонентов из 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, каждый из SSB формируется в пределах пакета для развертки по направлениям как азимута, так и высоты, передается этот сформированный по лучу сигнал по каналу пространственного рассеяния и обрабатывает этот принятый сигнал по множеству лучей приемного конца. Пример измеряет принимаемую мощность опорного сигнала (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'}

В примере используются следующие параметры:

  • Идентификатор соты для сценария с одной сотой с одной BS и UE

  • Диапазон частот, как строка для обозначения FR1 или FR2 операции

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

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

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

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

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

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

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

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

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

  • Включение или отключение сдвига уровня для передающих и приемных концов. Включение сдвига отметок для FR2 и/или URA

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

  • Режим измерения для 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 функция помощника. Сформированный сигнал еще не сформирован.

% 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 необходимо сформировать каждый из блоков SS в сформированной пачке с использованием аналогового формирования луча. На основе количества блоков SS в пачке и заданных диапазонов сдвига определите направления азимута и отметки для различных пучков. Затем формируют луч отдельных блоков внутри пакета в каждом из этих направлений.

% 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

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

Протягивание и измерение луча приемного конца

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

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

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

Обработка приема передаваемого пакета включает в себя

  • Применение пространственно-осведомленного канала замирания

  • Усиление приема для компенсации вызванных потерь в тракте и AWGN

  • Формирование диаграммы направленности на стороне приема

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

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

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

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

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

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

Для измерения в режиме ожидания SS-RSRP в дополнение к SSS используйте только вторичные сигналы синхронизации (SSS) или опорные сигналы демодуляции физического широковещательного канала (PBCH) (DM-RS) (раздел 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 occurence 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
prmScene = struct();
prmScene.txArraySize = prm.TxArraySize;
prmScene.rxArraySize = prm.RxArraySize;
prmScene.txElemPos = getElementPosition(arrayTx); % meters
prmScene.rxElemPos = getElementPosition(arrayRx); % meters
prmScene.txArrayPos = prm.posTx;
prmScene.rxArrayPos = prm.posRx;
prmScene.txAzAngles = -90:90;
prmScene.rxAzAngles = [90:180 -179:-90];
prmScene.scatPos = prm.ScatPos;
prmScene.lambda = lambda;
prmScene.arrayScaling = 1;
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 с использованием блоков сигнала синхронизации для управления лучом на передающем и приемном концах. Измеряя мощность принимаемого опорного сигнала для SSB, можно определить наилучшую линию связи пар лучей для выбранной пространственной среды.

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

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

Ссылки

  1. 3GPP ТР 38.802. «Исследование аспектов физического уровня новой технологии радиодоступа». Техническая спецификация на сеть радиодоступа группы.

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

  3. 3GPP ТС 38.211. "НР; Физические каналы и модуляция. "Проект партнерства 3-го поколения; Техническая спецификация на сеть радиодоступа группы.

  4. 3GPP TS 38.215. "НР; измерение физического уровня. "Проект партнерства 3-го поколения; Техническая спецификация на сеть радиодоступа группы.

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

  6. Онггосануси, Э., С. Мд. Рахман и др. «Модульный и канал с высоким разрешением указывает информацию и управление лучом для 5G НОМЕР». IEEE Comm. Mag., март 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