Main Content

NR SSB Beam Sweeping

This example shows how to employ beam sweeping at both the transmitter (gNB) and receiver (UE) ends of a 5G NR system. Using synchronization signal blocks (SSB), this example illustrates some of the beam management procedures used during initial access. To accomplish beam sweeping, the example uses several components from Phased Array System Toolbox™.

Introduction

The support of millimeter wave (mmWave) frequencies requires directional links, which led to the specification of beam management procedures for initial access in NR. Beam management is a set of Layer 1 (physical) and Layer 2 (medium access control) procedures to acquire and maintain a set of beam pair links (a beam used at gNB paired with a beam used at UE). Beam management procedures are applied for both downlink and uplink transmission and reception [ 1 ], [ 2 ]. These procedures include:

  • Beam sweeping

  • Beam measurement

  • Beam determination

  • Beam reporting

  • Beam recovery

This example focuses on initial access procedures for idle users when a connection is established between the user equipment (UE) and access network node (gNB). At the physical layer, using synchronization signal blocks (SSB) transmitted as a burst in the downlink direction (gNB to UE), the example highlights both transmit/receive point (TRP) beam sweeping and UE beam sweeping to establish a beam pair link. Amongst the multiple beam management procedures, TR 38.802 defines this dual-end sweep as procedure P-1 [ 1 ].

Once connected, the same beam pair link can be used for subsequent transmissions. If necessary, the beams are further refined using CSI-RS (for downlink) and SRS (for uplink). In case of beam failure, these pair links can be reestablished. For an example of beam pair refinement, see NR Downlink Transmit-End Beam Refinement Using CSI-RS.

This example generates an NR synchronization signal burst, beamforms each of the SSBs within the burst to sweep over both azimuth and elevation directions, transmits this beamformed signal over a spatial scattering channel, and processes this received signal over the multiple receive-end beams. The example measures the reference signal received power (RSRP) for each of the transmit-receive beam pairs (in a dual loop) and determines the beam pair link with the maximum RSRP. This beam pair link thus signifies the best beam-pair at transmit and receive ends for the simulated spatial scenario. This figure shows the main processing steps with the beam management ones highlighted in color.

rng(211);                           % Set RNG state for repeatability

Simulation Parameters

Define system parameters for the example. Modify these parameters to explore their impact on the system.

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'}

The example uses these parameters:

  • Cell ID for a single-cell scenario with a single BS and UE

  • Frequency range, as a string to designate FR1 or FR2 operation

  • Center frequency, in Hz, dependent on the frequency range

  • Synchronization signal block pattern as one of Case A/B/C for FR1 and Case D/E for FR2. This also selects the subcarrier spacing.

  • Transmitted SSBs in the pattern, as a binary vector of length 4 or 8 for FR1 and length 64 for FR2. The number of SSBs transmitted sets the number of beams at both transmit and receive ends.

  • Transmit array size, as a two-element row vector specifying the number of antenna elements in the rows and columns of the transmit array, respectively. A uniform rectangular array (URA) is used when both values are greater than one.

  • Transmit azimuthal sweep limits in degrees to specify the starting and ending azimuth angles for the sweep

  • Transmit elevation sweep limits in degrees to specify the starting and ending elevation angles for the sweep

  • Receive array size, as a two-element row vector specifying the number of antenna elements in the rows and columns of the receive array, respectively. A uniform rectangular array (URA) is used when both values are greater than one.

  • Receive azimuthal sweep limits in degrees to specify the starting and ending azimuth angles for the sweep

  • Receive elevation sweep limits in degrees to specify the starting and ending elevation angles for the sweep

  • Enable or disable elevation sweep for both transmit and receive ends. Enable elevation sweep for FR2 and/or URAs

  • Signal-to-noise ratio in dB

  • Measurement mode for SSB to specify the use of only secondary synchronization signals ('SSSonly') or use of PBCH DM-RS along with secondary synchronization signals ('SSSwDMRS')

prm = validateParams(prm);

Synchronization Signal Burst Configuration

Set up the synchronization signal burst parameters by using the specified system parameters. For initial access, set the SSB periodicity to 20 ms.

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;

Refer to the tutorial Synchronization Signal Blocks and Bursts for more details on synchronization signal blocks and bursts.

Channel Configuration

Configure a spatial scattering MIMO channel channel. Specify the locations for the BS and UE as [x,y,z] coordinates in a cartesian system. Depending on the array sizes specified, employ either uniform linear arrays (ULA) or uniform rectangular arrays (URA). Use isotropic antenna elements for the arrays.

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);

Burst Generation

Create the SS burst waveform [ 3 ] by calling the hSSBurst helper function. The generated waveform is not yet 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

Transmit-End Beam Sweeping

To achieve TRP beam sweeping, beamform each of the SS blocks in the generated burst using analog beamforming. Based on the number of SS blocks in the burst and the sweep ranges specified, determine both the azimuth and elevation directions for the different beams. Then beamform the individual blocks within the burst to each of these directions.

% 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

The beamformed burst waveform is then transmitted over the spatially-aware scattering channel.

Receive-End Beam Sweeping and Measurement

For receive-end beam sweeping, the transmitted beamformed burst waveform is received successively over each receive beam. For N transmit beams and M receive beams in procedure P-1, each of the N beams is transmitted M times from gNB so that each transmit beam is received over the M receive beams.

The example assumes both N and M to be equal to the number of SSBs in the burst. For simplicity, the example generates only one burst, but to mimic the burst reception over the air M times, the receiver processes this single burst M times.

This figure shows a beam-based diagram for the sweeps at both gNB and UE for N = M = 4, in the azimuthal plane. The diagram shows the time taken for the dual sweep, where each interval at gNB corresponds to an SSB and each interval at the UE corresponds to the SS burst. For the depicted scenario, beams S3 and U2 are highlighted as the selected beam-pair link notionally. The example implements the dual-sweep over a time duration of N*M time instants.

The receive processing of the transmitted burst includes

  • Application of the fading channel and AWGN

  • Receive-end beamforming

  • Timing correction

  • OFDM demodulation

  • Extracting the known SSB grid

  • Measuring the RSRP based on the specified measurement mode

The processing repeats these steps for each of the receive beams, then selects the best beam-pair based on the complete set of measurements made.

To highlight beam sweeping, the example assumes known SSB information at the receiver. For more details on recovery processing see NR Cell Search and MIB and SIB1 Recovery.

For the idle mode SS-RSRP measurement, use either only the secondary synchronization signals (SSS) or the physical broadcast channel (PBCH) demodulation reference signals (DM-RS) in addition to the SSS (Section 5.1.1. of [ 4 ]). Specify this by the RSRPMode parameter of the example. For FR2, the RSRP measurement is based on the combined signal from antenna elements, while the measurement is per antenna element for 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.

% 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
    txWave = [strTxWaveform; zeros(maxChDelay,size(strTxWaveform,2))];
    fadWave = channel(txWave);

    % AWGN, after accounting for path loss
    noise = N0*complex(randn(size(fadWave)),randn(size(fadWave)));
    rxWaveform = fadWave*(10^(spLoss/20)) + 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

Beam Determination

After the dual-end sweep and measurements are complete, determine the best beam-pair link based on the RSRP measurement.

[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.1564 dBm  Transmit #8 (Azimuth: 60, Elevation: 0)  Receive #6 (Azimuth: 90, Elevation: 0)

These plots highlight the transmit directivity pattern, receive directivity pattern, and the spatial scene, respectively. The results are dependent on the individual beam directions used for the sweeps. The spatial scene offers a combined view of the transmit and receive arrays and the respective determined beams, along with the scatterers.

Summary and Further Exploration

This example highlights the P-1 beam management procedure by using synchronization signal blocks for transmit-end and receive-end beam sweeping. By measuring the reference signal received power for SSBs, you can identify the best beam pair link for a selected spatial environment.

The example allows variation on frequency range, SSB block pattern, number of SSBs, transmit and receive array sizes, transmit and receive sweep ranges, and the measuring mode. To see the impact of parameters on the beam selection, experiment with different values.

For an example of the P-2 procedures of transmit-end beam sweeping using CSI-RS signals for the downlink, see NR Downlink Transmit-End Beam Refinement Using CSI-RS. You can use these procedures for beam refinement and adjustment in the connected mode, once the initial beam pair links are established [ 5 ], [ 6 ].

References

  1. 3GPP TR 38.802. "Study on New Radio access technology physical layer aspects." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

  2. Giordani, M., M. Polese, A. Roy, D. Castor, and M. Zorzi. "A tutorial on beam management for 3GPP NR at mmWave frequencies." IEEE Comm. Surveys & Tutorials, vol. 21, No. 1, Q1 2019.

  3. 3GPP TS 38.211. "NR; Physical channels and modulation." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

  4. 3GPP TS 38.215. "NR; Physical layer measurements." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

  5. Giordani, M., M. Polese, A. Roy, D. Castor, and M. Zorzi. "Standalone and non-standalone beam management for 3GPP NR at mmWaves." IEEE Comm. Mag., April 2019, pp. 123-129.

  6. Onggosanusi, E., S. Md. Rahman, et al. "Modular and high-resolution channel state information and beam management for 5G NR." IEEE Comm. Mag., March 2018, pp. 48-55.

Local Functions

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
           rsrp = max(rsrpSSS+rsrpDMRS)/2; % max over receive elements
    end
end

See Also

Objects

Related Topics