Main Content

NR 셀 탐색 및 MIB와 SIB1 복원

이 예제에서는 5G Toolbox™를 사용하여 라이브 gNodeB 신호를 동기화, 복조, 디코딩하는 방법을 보여줍니다. 이 예제는 MIB와 시스템 정보 블록 중 첫 번째 블록(SIB1)을 디코딩합니다. MIB와 SIB1을 디코딩하려면 대부분의 다운링크 채널 및 신호를 복조하고 디코딩할 수 있는 포괄적인 수신기가 필요합니다.

소개

UE(사용자 단말)는 네트워크와 통신하기 전에 셀 탐색과 선택 절차를 수행하고 초기 시스템 정보를 얻어 내야 합니다. 그 과정의 첫 단계에서는 프레임 동기화를 달성하고, 셀 ID를 파악하고, MIB와 SIB1을 디코딩합니다. 이 예제에서는 5G Toolbox를 사용하여 이러한 단계를 수행하는 방법을 보여줍니다.

이 예제를 I/Q 샘플의 캡처된 파형에 사용하거나, nrWaveformGenerator를 사용하여 SS(동기화 신호) 버스트와 SIB1이 포함된 국소 파형을 생성할 수 있습니다. 국소적으로 생성된 파형에 대해 예제는 다음 단계를 수행합니다.

  • 파형 생성: 5G Toolbox의 다운링크 파형 생성기를 사용하여 MIB, CORESET 0, PDCCH, PDSCH를 전달하는 동기 신호 버스트를 구성하고 생성합니다. 또한, 여기서 PDSCH는 SIB1을 전달합니다. 송신기는 SS 블록 하나의 SNR을 개선할 수 있으나 빔포밍은 수행하지 않습니다. SSB 빔포밍에 대한 자세한 내용을 보려면 NR SSB Beam Sweeping 항목을 참조하십시오.

  • AWGN: 가산성 백색 가우스 잡음(AWGN)을 파형에 적용합니다.

  • 수신기: 수신된 파형에 다양한 동기화 및 복조 과정을 적용하여 시스템 프레임 번호, 셀 ID, SSB를 설정하고 MIB를 디코딩합니다. 이 과정은 PDCCH에서 DCI(다운링크 제어 정보)의 블라인드 디코딩에 필요한 정보를 제공합니다. 수신기는 DCI를 사용하여 PDSCH 복조기를 구성하고, DL-SCH를 디코딩하고, 마지막으로 SIB1을 복원합니다.

다음 그림은 수신기 내부의 처리 단계를 보여줍니다.

수신기 구성

수신된 파형을 동기화하고 복조하려면 다음 정보가 필요합니다.

  • 수신된 파형을 복조하기 위한 파형 샘플 레이트.

  • 수신된 파형에 심볼 위상 보상을 적용하기 위한 반송파 중심 주파수.

  • CORESET 0 주파수 리소스를 결정하기 위한 최소 채널 대역폭. TS 38.101-1 Table 5.3.5-1[ 1 ]은 각 NR 대역의 채널 대역폭을 설명합니다.

  • SS/PBCH 블록의 부반송파 간격을 결정하기 위한 SS 블록 패턴(Case A...E). UE는 NR 동작 대역을 기반으로 SS 블록 패턴을 탐색합니다. 자세한 내용은 TS 38.104 Table 5.4.3.3-1과 5.4.3.3-2[ 2 ]를 참조하십시오.

  • PBCH DM-RS 시퀀스와 PBCH 디스크램블링의 파라미터를 계산하기 위한 버스트 내 SS/PBCH 블록의 수($L_{max}$). 이러한 파라미터는 TS 38.211 Section 7.3.3.1과 7.4.1.4.1[3 ]에 설명된 대로 SS/PBCH 블록 인덱스에 따라 달라집니다. TS 38.213 Section 4.1[ 5 ]은 각 사례(Case)의 버스트 내 SS/PBCH 블록 세트를 설명합니다. UE는 SS 블록 패턴과 NR 동작 대역을 기반으로 한 $L_{max}$의 값을 알고 있습니다.

loadFromFile = 0; % Set to 1 to load a captured waveform

if loadFromFile
    % Load captured waveform
    rx = load('capturedWaveformSIB1.mat');
    rxWaveform = rx.waveform;

    % Configure receiver sample rate (samples/second)
    sampleRate = rx.sampleRate;

    % Symbol phase compensation frequency. Specify the carrier center
    % frequency or set to 0 to disable symbol phase compensation
    fPhaseComp = rx.fPhaseComp; % Carrier center frequency (Hz)

    % Set the minimum channel bandwidth for the NR band required to
    % configure CORESET 0 in FR1 (See TS 38.101-1 Table 5.3.5-1)
    minChannelBW = rx.minChannelBW; % 5, 10, 40 MHz

    % Configure necessary burst parameters at the receiver. The SSB pattern
    % can be 'Case A','Case B','Case C' for FR1 or 'Case D','Case E' for
    % FR2. The maximum number of blocks L_max can be 4 or 8 for FR1 and 64
    % for FR2.
    refBurst.BlockPattern = rx.ssbBlockPattern;
    refBurst.L_max = rx.L_max;
else
    % Generate waveform containing SS burst and SIB1
    % Configure the cell identity
    config = struct();
    config.NCellID = 102;

    % Configure an SS burst
    config.BlockPattern = 'Case B';         % FR1: 'Case A','Case B','Case C'. FR2: 'Case D','Case E'
    config.TransmittedBlocks = ones(1,8);   % Bitmap of SS blocks transmitted
    config.SubcarrierSpacingCommon = 15;    % SIB1 subcarrier spacing in kHz (15 or 30 for FR1. 60 or 120 for FR2)
    config.EnableSIB1 = 1;                  % Set to 0 to disable SIB1

    % Set the minimum channel bandwidth for the NR band required to
    % configure CORESET 0 in FR1 (See TS 38.101-1 Table 5.3.5-1)
    config.MinChannelBW = 5; % 5, 10, 40 MHz

    % Introduce a beamforming gain by boosting the power (and therefore
    % SNR) of one SSB and associated SIB1 PDCCH and PDSCH
    boost = 6; % SNR boost in dB
    config.Power = zeros(size(config.TransmittedBlocks));
    config.Power(1) = boost; % boost the first SSB

    % Configure and generate a waveform containing an SS burst and SIB1
    wavegenConfig = hSIB1WaveformConfiguration(config);
    [txWaveform,waveInfo] = nrWaveformGenerator(wavegenConfig);
    txOfdmInfo = waveInfo.ResourceGrids(1).Info;

    % Add white Gaussian noise to the waveform. Note that the SNR only
    % applies to the boosted SSB / SIB1
    rng('default'); % Reset the random number generator
    SNRdB = 20; % SNR for AWGN
    rxWaveform = awgn(txWaveform,SNRdB-boost,-10*log10(double(txOfdmInfo.Nfft)));

    % Configure receiver
    % Sample rate
    sampleRate = txOfdmInfo.SampleRate;

    % Symbol phase compensation frequency (Hz). The function
    % nrWaveformGenerator does not apply symbol phase compensation to the
    % generated waveform.
    fPhaseComp = 0; % Carrier center frequency (Hz)

    % Minimum channel bandwidth (MHz)
    minChannelBW = config.MinChannelBW;

    % Configure necessary burst parameters at the receiver
    refBurst.BlockPattern = config.BlockPattern;
    refBurst.L_max = numel(config.TransmittedBlocks);
end

% Get OFDM information from configured burst and receiver parameters
nrbSSB = 20;
scsSSB = hSSBurstSubcarrierSpacing(refBurst.BlockPattern);
rxOfdmInfo = nrOFDMInfo(nrbSSB,scsSSB,'SampleRate',sampleRate);

% Display spectrogram of received waveform
figure;
nfft = rxOfdmInfo.Nfft;
spectrogram(rxWaveform(:,1),ones(nfft,1),0,nfft,'centered',sampleRate,'yaxis','MinThreshold',-130);
title('Spectrogram of the Received Waveform')

PSS 탐색 및 주파수 오프셋 정정

수신기는 다음 단계에 따라 PSS 탐색과 성긴 주파수 오프셋 추정을 수행합니다.

  • 후보 주파수 오프셋 하나를 사용해, 수신된 파형에 주파수 편이를 적용합니다. 후보 오프셋들은 부반송파 절반 간격만큼 떨어져 있습니다. 주파수 오프셋 탐색 대역폭을 제어하려면 searchBW를 사용하십시오.

  • 이렇게 주파수 편이를 적용한 수신 파형을 3개의 가능한 각 PSS 시퀀스(NID2)와 상관시키고 가장 강한 상관 피크를 추출합니다. 기준 PSS 시퀀스는 주파수 중심에 있습니다. 따라서 가장 강한 상관 피크는 반송파의 중심 주파수를 기준으로 성긴 주파수 오프셋의 측정값을 제공합니다. 피크는 수신된 파형에서 3개의 PSS(NID2) 중 어느 것이 검출되었는지와 가장 양호한 채널 조건의 시점도 나타냅니다.

  • SSB의 각 OFDM 심볼의 순환 전치와 이에 대응하는 OFDM 심볼의 유용한 부분을 상관시켜 부반송파 절반 아래의 주파수 오프셋을 추정합니다. 이 상관의 위상은 파형의 주파수 오프셋에 비례합니다.

disp(' -- Frequency correction and timing estimation --')

% Specify the frequency offset search bandwidth in kHz
searchBW = 6*scsSSB;
[rxWaveform,freqOffset,NID2] = hSSBurstFrequencyCorrect(rxWaveform,refBurst.BlockPattern,sampleRate,searchBW);
disp([' Frequency offset: ' num2str(freqOffset,'%.0f') ' Hz'])
 -- Frequency correction and timing estimation --
 Frequency offset: -14 Hz

시간 동기화 및 OFDM 복조

수신기는 주파수 탐색 과정에서 검출된 기준 PSS 시퀀스를 사용하여 가장 강한 SS 블록에 대한 타이밍 오프셋을 추정합니다. 주파수 오프셋 정정 후, 수신기는 기준 PSS와 수신된 파형의 중심 주파수가 정렬된 것으로 가정합니다. 마지막으로 수신기 OFDM은 동기화된 파형을 복조하고 SS 블록을 추출합니다.

% Create a reference grid for timing estimation using detected PSS. The PSS
% is placed in the second OFDM symbol of the reference grid to avoid the
% special CP length of the first OFDM symbol.
refGrid = zeros([nrbSSB*12 2]);
refGrid(nrPSSIndices,2) = nrPSS(NID2); % Second OFDM symbol for correct CP length

% Timing estimation. This is the timing offset to the OFDM symbol prior to
% the detected SSB due to the content of the reference grid
nSlot = 0;
timingOffset = nrTimingEstimate(rxWaveform,nrbSSB,scsSSB,nSlot,refGrid,'SampleRate',sampleRate);

% Synchronization, OFDM demodulation, and extraction of strongest SS block
rxGrid = nrOFDMDemodulate(rxWaveform(1+timingOffset:end,:),nrbSSB,scsSSB,nSlot,'SampleRate',sampleRate);
rxGrid = rxGrid(:,2:5,:);

% Display the timing offset in samples. As the symbol lengths are measured
% in FFT samples, scale the symbol lengths to account for the receiver
% sample rate.
srRatio = sampleRate/(scsSSB*1e3*rxOfdmInfo.Nfft);
firstSymbolLength = rxOfdmInfo.SymbolLengths(1)*srRatio;
str = sprintf(' Time offset to synchronization block: %%.0f samples (%%.%.0ff ms) \n',floor(log10(sampleRate))-3);
fprintf(str,timingOffset+firstSymbolLength,(timingOffset+firstSymbolLength)/sampleRate*1e3);
 Time offset to synchronization block: 2200 samples (0.1432 ms) 

SSS 탐색

수신기는 SSS와 연결된 리소스 요소를 수신된 그리드로부터 추출하여 국소적으로 생성된 가능한 각각의 SSS 시퀀스와 상관시킵니다. 가장 강한 PSS 시퀀스와 SSS 시퀀스의 인덱스가 결합되어 PBCH DM-RS와 PBCH의 처리에 필요한 물리 계층 셀 ID를 제공합니다.

% Extract the received SSS symbols from the SS/PBCH block
sssIndices = nrSSSIndices;
sssRx = nrExtractResources(sssIndices,rxGrid);

% Correlate received SSS symbols with each possible SSS sequence
sssEst = zeros(1,336);
for NID1 = 0:335

    ncellid = (3*NID1) + NID2;
    sssRef = nrSSS(ncellid);
    sssEst(NID1+1) = sum(abs(mean(sssRx .* conj(sssRef),1)).^2);

end

% Plot SSS correlations
figure;
stem(0:335,sssEst,'o');
title('SSS Correlations (Frequency Domain)');
xlabel('$N_{ID}^{(1)}$','Interpreter','latex');
ylabel('Magnitude');
axis([-1 336 0 max(sssEst)*1.1]);

% Determine NID1 by finding the strongest correlation
NID1 = find(sssEst==max(sssEst)) - 1;

% Plot selected NID1
hold on;
plot(NID1,max(sssEst),'kx','LineWidth',2,'MarkerSize',8);
legend(["correlations" "$N_{ID}^{(1)}$ = " + num2str(NID1)],'Interpreter','latex');

% Form overall cell identity from estimated NID1 and NID2
ncellid = (3*NID1) + NID2;

disp([' Cell identity: ' num2str(ncellid)])
 Cell identity: 102

PBCH DM-RS 탐색

SSS 탐색과 유사한 과정을 통해 수신기는 가능한 각 PBCH DM-RS 시퀀스를 구성하고 채널 추정과 잡음 추정을 수행합니다. SNR이 가장 양호한 PBCH DM-RS의 인덱스가 PBCH 스크램블링 초기화에 필요한 SS/PBCH 블록 인덱스의 LSB를 결정합니다.

% Calculate PBCH DM-RS indices
dmrsIndices = nrPBCHDMRSIndices(ncellid);

% Perform channel estimation using DM-RS symbols for each possible DM-RS
% sequence and estimate the SNR
dmrsEst = zeros(1,8);
for ibar_SSB = 0:7

    refGrid = zeros([240 4]);
    refGrid(dmrsIndices) = nrPBCHDMRS(ncellid,ibar_SSB);
    [hest,nest] = nrChannelEstimate(rxGrid,refGrid,'AveragingWindow',[0 1]);
    dmrsEst(ibar_SSB+1) = 10*log10(mean(abs(hest(:).^2)) / nest);

end

% Plot PBCH DM-RS SNRs
figure;
stem(0:7,dmrsEst,'o');
title('PBCH DM-RS SNR Estimates');
xlabel('$\overline{i}_{SSB}$','Interpreter','latex');
xticks(0:7);
ylabel('Estimated SNR (dB)');
axis([-1 8 min(dmrsEst)-1 max(dmrsEst)+1]);

% Record ibar_SSB for the highest SNR
ibar_SSB = find(dmrsEst==max(dmrsEst)) - 1;

% Plot selected ibar_SSB
hold on;
plot(ibar_SSB,max(dmrsEst),'kx','LineWidth',2,'MarkerSize',8);
legend(["SNRs" "$\overline{i}_{SSB}$ = " + num2str(ibar_SSB)],'Interpreter','latex');

PBCH DM-RS와 SSS를 사용한 채널 추정

수신기는 이전 단계에서 검출된 SSS와 PBCH DM-RS를 사용하여 전체 SS/PBCH 블록에 대한 채널을 추정합니다. PBCH DM-RS/SSS에 대한 가산성 잡음 추정도 수행됩니다.

refGrid = zeros([nrbSSB*12 4]);
refGrid(dmrsIndices) = nrPBCHDMRS(ncellid,ibar_SSB);
refGrid(sssIndices) = nrSSS(ncellid);
[hest,nest,hestInfo] = nrChannelEstimate(rxGrid,refGrid,'AveragingWindow',[0 1]);

PBCH 복조

수신기는 셀 ID를 사용하여 PBCH와 연결된 리소스 요소를 결정하고 수신된 그리드로부터 이를 추출합니다. 또한, 수신기는 채널 추정값과 잡음 추정값을 사용하여 MMSE 이퀄라이제이션을 수행합니다. 그런 다음, 이퀄라이징된 PBCH 심볼은 복조되고 디스크램블링되어 코딩된 BCH 블록에 대한 비트 추정값을 제공합니다.

disp(' -- PBCH demodulation and BCH decoding -- ')

% Extract the received PBCH symbols from the SS/PBCH block
[pbchIndices,pbchIndicesInfo] = nrPBCHIndices(ncellid);
pbchRx = nrExtractResources(pbchIndices,rxGrid);

% Configure 'v' for PBCH scrambling according to TS 38.211 Section 7.3.3.1
% 'v' is also the 2 LSBs of the SS/PBCH block index for L_max=4, or the 3
% LSBs for L_max=8 or 64.
if refBurst.L_max == 4
    v = mod(ibar_SSB,4);
else
    v = ibar_SSB;
end
ssbIndex = v;

% PBCH equalization and CSI calculation
pbchHest = nrExtractResources(pbchIndices,hest);
[pbchEq,csi] = nrEqualizeMMSE(pbchRx,pbchHest,nest);
Qm = pbchIndicesInfo.G / pbchIndicesInfo.Gd;
csi = repmat(csi.',Qm,1);
csi = reshape(csi,[],1);

% Plot received PBCH constellation after equalization
figure;
plot(pbchEq,'o');
xlabel('In-Phase'); ylabel('Quadrature')
title('Equalized PBCH Constellation');
m = max(abs([real(pbchEq(:)); imag(pbchEq(:))])) * 1.1;
axis([-m m -m m]);

% PBCH demodulation
pbchBits = nrPBCHDecode(pbchEq,ncellid,v,nest);

% Calculate RMS PBCH EVM
pbchRef = nrPBCH(pbchBits<0,ncellid,v);
evm = comm.EVM;
pbchEVMrms = evm(pbchRef,pbchEq);

% Display calculated EVM
disp([' PBCH RMS EVM: ' num2str(pbchEVMrms,'%0.3f') '%']);
 -- PBCH demodulation and BCH decoding -- 
 PBCH RMS EVM: 8.831%

BCH 디코딩

수신기는 BCH 비트 추정값에 MMSE 이퀄라이저의 CSI(채널 상태 정보)를 가중치로 부여하고 BCH를 디코딩합니다. BCH 디코딩 과정은 레이트 복원, 극성 디코딩, CRC 디코딩, 디스크램블링, 그리고 8개의 추가적인 타이밍 관련 페이로드 비트로부터 24개의 BCH 전송 블록 비트를 분리하는 것으로 구성됩니다.

% Apply CSI
pbchBits = pbchBits .* csi;

% Perform BCH decoding including rate recovery, polar decoding, and CRC
% decoding. PBCH descrambling and separation of the BCH transport block
% bits 'trblk' from 8 additional payload bits A...A+7 is also performed:
%   A ... A+3: 4 LSBs of system frame number
%         A+4: half frame number
% A+5 ... A+7: for L_max=64, 3 MSBs of the SS/PBCH block index
%              for L_max=4 or 8, A+5 is the MSB of subcarrier offset k_SSB
polarListLength = 8;
[~,crcBCH,trblk,sfn4lsb,nHalfFrame,msbidxoffset] = ...
    nrBCHDecode(pbchBits,polarListLength,refBurst.L_max,ncellid);

% Display the BCH CRC
disp([' BCH CRC: ' num2str(crcBCH)]);

% Stop processing MIB and SIB1 if BCH was received with errors
if crcBCH
    disp(' BCH CRC is not zero.');
    return
end

% Use 'msbidxoffset' value to set bits of 'k_SSB' or 'ssbIndex', depending
% on the number of SS/PBCH blocks in the burst
if (refBurst.L_max==64)
    ssbIndex = ssbIndex + (bit2int(msbidxoffset,3) * 8);
    k_SSB = 0;
else
    k_SSB = msbidxoffset * 16;
end

% Displaying the SSB index
disp([' SSB index: ' num2str(ssbIndex)]);
 BCH CRC: 0
 SSB index: 0

MIB 및 BCH 구문 분석

이 예제에서는 구문 분석을 통해 24개의 디코딩된 BCH 전송 블록 비트를 하나의 MIB 메시지로 만들고 초기 시스템 정보를 사용하여 initialSystemInfo 구조체를 생성합니다. 이 과정은 MIB의 MSB 6개와 PBCH 페이로드 비트의 LSB 4개로부터 10비트 시스템 프레임 번호(SFN) NFrame을 복원하는 작업을 포함합니다. L_max=4 또는 버스트당 SS/PBCH 블록이 8개인 경우 PBCH 페이로드 비트로부터의 부반송파 오프셋 k_SSB의 MSB를 통합하는 작업도 포함합니다.

% Parse the last 23 decoded BCH transport block bits into a MIB message.
% The BCH transport block 'trblk' is the RRC message BCCH-BCH-Message,
% consisting of a leading 0 bit and 23 bits corresponding to the MIB. The
% leading bit signals the message type transmitted (MIB or empty sequence).

mib = fromBits(MIB,trblk(2:end)); % Do not parse leading bit

% Create a structure containing complete initial system information
initialSystemInfo = initSystemInfo(mib,sfn4lsb,k_SSB,refBurst.L_max);

% Display the MIB structure
disp(' BCH/MIB Content:')
disp(initialSystemInfo);

% Check if a CORESET for Type0-PDCCH common search space (CSS) is present,
% according to TS 38.213 Section 4.1
if ~isCORESET0Present(refBurst.BlockPattern,initialSystemInfo.k_SSB)
    fprintf('CORESET 0 is not present (k_SSB > k_SSB_max).\n');
    return
end
 BCH/MIB Content:
                     NFrame: 0
    SubcarrierSpacingCommon: 15
                      k_SSB: 0
          DMRSTypeAPosition: 3
            PDCCHConfigSIB1: [1x1 struct]
                 CellBarred: 0
       IntraFreqReselection: 0

전대역폭에서의 OFDM 복조

MIB가 복원되면 수신기는 공통 부반송파 간격과 CORESET 0을 지원하는 대역폭을 사용하여, 검출된 SS 블록이 포함된 프레임에 대해 OFDM 복조를 수행합니다. 수신기는 검출된 SSB의 위치로부터의 오프셋과 TS 38.213 Section 13 Table 13-1~13-10[ 5 ]에 지정된 대역폭을 통해 공통 뉴머롤로지에서 CORESET 0 주파수 리소스를 결정합니다. 주파수 정정 과정에서 SS 버스트의 중심 주파수에 맞춰 OFDM 리소스 그리드의 중심을 정렬했습니다. 그러나 이러한 중심이 반드시 CORESET 0의 중심 주파수에 맞춰 정렬되지는 않습니다. 다음 그림은 SSB, CORESET 0 주파수 리소스, 관련 PDCCH 모니터링 시점(monitoring occasion) 간의 관계를 보여줍니다.

SS 버스트와 달리, 제어 채널과 데이터 채널은 각각의 CRB(공통 리소스 블록) 래스터에 맞춰 주파수가 정렬되어야 합니다. KSSB의 값은 이 CRB 래스터로부터의 SSB의 주파수 오프셋을 나타냅니다. 주파수 정정 과정에서 SSB를 주파수 중심에 놓았으므로 k_SSB에 의해 결정된 주파수 편이를 적용하여 OFDM 복조 전에 데이터 채널과 제어 채널을 CRB에 맞춰 정렬합니다.

k_SSB = initialSystemInfo.k_SSB;
scsCommon = initialSystemInfo.SubcarrierSpacingCommon;
scsKSSB = kSSBSubcarrierSpacing(scsCommon);
kFreqShift = k_SSB*scsKSSB*1e3;
rxWaveform = rxWaveform.*exp(1i*2*pi*kFreqShift*(0:length(rxWaveform)-1)'/sampleRate);

% Adjust the symbol phase compensation frequency with the frequency shift
% introduced.
fPhaseComp = fPhaseComp - kFreqShift;

SS/PBCH 블록을 스케줄링할 수 있는 첫 번째 프레임의 프레임 원점에 맞춰 타이밍 오프셋을 조정합니다. 프레임 오프셋이 음수이면 첫 번째 프레임은 불완전합니다. 파형에 선행 0을 추가하여 파형을 해당 프레임에 맞춰 정렬합니다.

[frameOffset,nLeadingFrames] = hTimingOffsetToFirstFrame(timingOffset,refBurst,ssbIndex,nHalfFrame,sampleRate);

% Add leading zeros
zeroPadding = zeros(-min(frameOffset,0),size(rxWaveform,2));
rxWaveform = [zeroPadding; rxWaveform(1+max(frameOffset,0):end,:)];

% Determine the number of resource blocks and subcarrier spacing for OFDM
% demodulation of CORESET 0.
nrb = hCORESET0DemodulationBandwidth(initialSystemInfo,scsSSB,minChannelBW);

if sampleRate < nrb*12*scsCommon*1e3
    disp(['SIB1 recovery cannot continue. CORESET 0 resources are beyond '...
          'the frequency limits of the received waveform for the sampling rate configured.']);
    return;
end

% OFDM demodulate received waveform with common subcarrier spacing
nSlot = 0;
rxGrid = nrOFDMDemodulate(rxWaveform, nrb, scsCommon, nSlot,...
                         'SampleRate',sampleRate,'CarrierFrequency',fPhaseComp);

% Display OFDM resource grid and highlight strongest SS block
plotResourceGrid(rxGrid,refBurst,initialSystemInfo,nLeadingFrames,ssbIndex,nHalfFrame)

PDCCH 복조 및 다운링크 제어 정보 디코딩

CORESET/SS에서 시스템 정보 DCI 메시지를 블라인드 방식으로 탐색하기 위해 수신기는 다음 단계를 수행합니다.

  • PDCCH 모니터링 시점(monitoring occasion)을 결정하고, 제어 정보를 포함하고 있는 OFDM 리소스 그리드를 추출.

  • CORESET 0, 탐색 공간, PDCCH를 구성.

  • Format 1_0 DCI 메시지를 블라인드 탐색.

수신기는 TS 38.213 Table 13-11과 13-12[ 5 ]에 설명된 대로 검출된 SS 블록의 위치로부터의 슬롯과 OFDM 심볼 오프셋을 통해 PDCCH 모니터링 시점(monitoring occasion)을 결정합니다. 수신기는 파형에서 사용 가능한 첫 번째 프레임에 대한 새로운 동기화 시간을 고려하기 위해 시스템 프레임 번호를 조정합니다.

initialSystemInfo.NFrame = mod(initialSystemInfo.NFrame - nLeadingFrames,1024);
numRxSym = size(rxGrid,2);
[csetSubcarriers,monSlots,monSlotsSym,ssStartSym] = hPDCCH0MonitoringResources(initialSystemInfo,scsSSB,minChannelBW,ssbIndex,numRxSym);

% Check if search space is beyond end of waveform
if isempty(monSlotsSym)
    disp('Search space slot is beyond end of waveform.');
    return;
end

% Extract slots containing strongest PDCCH from the received grid
rxMonSlotGrid = rxGrid(csetSubcarriers,monSlotsSym,:);

CORESET, 탐색 공간 및 그 밖의 PDCCH 파라미터를 구성합니다. CORESET 리소스와 탐색 공간은 TS 38.213 Section 13 Table 13-1~13-15[ 5 ]에 따라 구성됩니다. CCE-to-REG 인터리빙된 매핑 파라미터(REGBundleSize = 6, InterleaverSize = 2, and ShiftIndex = NCellID)는 TS 38.211 Section 7.3.2.2[ 3 ]에 설명되어 있습니다. CORESET 0의 경우, TS 38.212 Section 7.3.1.0[ 4 ]에 설명된 대로 BWP는 CORESET 크기입니다. PDCCH 스크램블링 파라미터는 TS 38.211 Section 7.3.2.3[ 3 ]에 설명된 대로 nRNTI = 0 및 nID = NCellID입니다.

scsPair = [scsSSB scsCommon];
[pdcch,csetPattern] = hPDCCH0Configuration(ssbIndex,initialSystemInfo,scsPair,ncellid,minChannelBW);

% Configure the carrier to span the BWP (CORESET 0)
carrier = hCarrierConfigSIB1(ncellid,initialSystemInfo,pdcch);

DCI 메시지를 탐색합니다. UE는 올바른 후보(또는 인스턴스)를 식별하기 위해 SI-RNTI를 사용하여 모든 결합 레벨에 대한 모든 PDCCH 후보를 모니터링하여, 수신된 PDCCH 심볼을 블라인드 방식으로 디코딩합니다.

% Specify DCI message with Format 1_0 scrambled with SI-RNTI (TS 38.212
% Section 7.3.1.2.1)
dci = DCIFormat1_0_SIRNTI(pdcch.NSizeBWP);

disp(' -- Downlink control information message search in PDCCH -- ');

symbolsPerSlot = 14;
siRNTI = 65535; % TS 38.321 Table 7.1-1
dciCRC = true;
mSlotIdx = 0;
% Loop over all monitoring slots
while (mSlotIdx < length(monSlots)) && dciCRC

    % Update slot number to next monitoring slot
    carrier.NSlot = monSlots(mSlotIdx+1);

    % Get PDCCH candidates according to TS 38.213 Section 10.1
    [pdcchInd,pdcchDmrsSym,pdcchDmrsInd] = nrPDCCHSpace(carrier,pdcch);

    % Extract resource grid for this monitoring slot and normalize
    rxSlotGrid = rxMonSlotGrid(:,(1:symbolsPerSlot) + symbolsPerSlot*mSlotIdx,:);
    rxSlotGrid = rxSlotGrid/max(abs(rxSlotGrid(:)));

    % Proceed to blind decoding only if the PDCCH REs are not zero.
    notZero = any(cellfun(@(x)any(rxSlotGrid(x),'all'),pdcchInd));

    % Loop over all supported aggregation levels
    aLevIdx = 1;
    while (aLevIdx <= 5) && dciCRC && notZero
        % Loop over all candidates at each aggregation level in SS
        cIdx = 1;
        numCandidatesAL = pdcch.SearchSpace.NumCandidates(aLevIdx);
        while (cIdx <= numCandidatesAL) && dciCRC
            % Channel estimation using PDCCH DM-RS
            [hest,nVar,pdcchHestInfo] = nrChannelEstimate(rxSlotGrid,pdcchDmrsInd{aLevIdx}(:,cIdx),pdcchDmrsSym{aLevIdx}(:,cIdx));

            % Equalization and demodulation of PDCCH symbols
            [pdcchRxSym,pdcchHest] = nrExtractResources(pdcchInd{aLevIdx}(:,cIdx),rxSlotGrid,hest);
            pdcchEqSym = nrEqualizeMMSE(pdcchRxSym,pdcchHest,nVar);
            dcicw = nrPDCCHDecode(pdcchEqSym,pdcch.DMRSScramblingID,pdcch.RNTI,nVar);

            % DCI message decoding
            polarListLength = 8;
            [dcibits,dciCRC] = nrDCIDecode(dcicw,dci.Width,polarListLength,siRNTI);

            if dciCRC == 0
                disp([' Decoded PDCCH candidate #' num2str(cIdx) ' at aggregation level ' num2str(2^(aLevIdx-1))])
            end
            cIdx = cIdx + 1;
        end
        aLevIdx = aLevIdx+1;
    end
    mSlotIdx = mSlotIdx+1;
end
mSlotIdx = mSlotIdx-1;
monSlotsSym = monSlotsSym(mSlotIdx*symbolsPerSlot + (1:symbolsPerSlot));

% Highlight CORESET 0/SS occasions in resource grid
highlightCORESET0SS(csetSubcarriers,monSlots,monSlots(mSlotIdx+1),pdcch,dciCRC)

if dciCRC
    disp(' DCI decoding failed.');
    return
end

% Calculate RMS PDCCH EVM
pdcchRef = nrPDCCH(double(dcicw<0),pdcch.DMRSScramblingID,pdcch.RNTI);
evm = comm.EVM;
pdcchEVMrms = evm(pdcchRef,pdcchEqSym);

% Display calculated EVM
disp([' PDCCH RMS EVM: ' num2str(pdcchEVMrms,'%0.3f') '%']);
disp([' PDCCH CRC: ' num2str(dciCRC)]);

% Plot received PDCCH constellation after equalization
figure;
plot(pdcchEqSym,'o');
xlabel('In-Phase'); ylabel('Quadrature')
title('Equalized PDCCH Constellation');
m = max(abs([real(pdcchEqSym(:)); imag(pdcchEqSym(:))])) * 1.1;
axis([-m m -m m]);
 -- Downlink control information message search in PDCCH -- 
 Decoded PDCCH candidate #1 at aggregation level 8
 PDCCH RMS EVM: 12.339%
 PDCCH CRC: 0

PDSCH 복조, DL-SCH 디코딩 및 SIB1 추출

수신기는 다음 단계를 수행하여 첫 번째 시스템 정보 블록을 복원합니다.

  • 셀 ID, BCH 정보, DCI를 사용하여 PDSCH 구성 결정

  • PDSCH 심볼의 채널 추정, 이퀄라이제이션, 복조

  • DL-SCH 디코딩 및 SIB1 추출

% Build DCI message structure
dci = fromBits(dci,dcibits);

% Get PDSCH configuration from cell ID, BCH information, and DCI
[pdsch,K0] = hSIB1PDSCHConfiguration(dci,pdcch.NSizeBWP,initialSystemInfo.DMRSTypeAPosition,csetPattern);

% For CORESET pattern 2, the gNodeB can allocate PDSCH in the next slot,
% which is indicated by the slot offset K_0 signaled by DCI. For more
% information, see TS 38.214 Table 5.1.2.1.1-4.
carrier.NSlot = carrier.NSlot + K0;
monSlotsSym = monSlotsSym+symbolsPerSlot*K0;

if K0 > 0
    % Display the OFDM grid of the slot containing associated PDSCH
    figure;
    imagesc(abs(rxGrid(csetSubcarriers,monSlotsSym,1))); axis xy
    xlabel('OFDM symbol');
    ylabel('subcarrier');
    title('Slot Containing PDSCH (Slot Offset K_0 = 1)');
end

% PDSCH channel estimation and equalization using PDSCH DM-RS
pdschDmrsIndices = nrPDSCHDMRSIndices(carrier,pdsch);
pdschDmrsSymbols = nrPDSCHDMRS(carrier,pdsch);

심볼 위상 보상과 채널 추정에서의 반송 주파수 불일치의 부정적 영향을 보상하기 위해 수신기 OFDM은 fPhaseComp 주변의 탐색 대역폭에서 반송 주파수 세트를 사용하여 파형을 복조합니다. DL-SCH 디코딩이 성공하거나 마지막 주파수에 도달하면 탐색이 종료됩니다. 동일한 심볼 위상 보상을 생성하는 최소 탐색 대역폭은 공통 부반송파 간격 15, 30, 60, 120kHz에 대해 각각 1920, 3840, 7680, 15360kHz입니다. SIB1 디코딩이 실패하고 이퀄라이징된 PDSCH 심볼이 결과적으로 심하게 왜곡되고 회전된 성상도로 이어질 경우 이러한 값에 이를 때까지 탐색 대역폭을 늘립니다.

disp(' -- PDSCH demodulation and DL-SCH decoding -- ')

mu = log2(scsCommon/15);
bw = 2^mu*100;   % Search bandwidth (kHz)
freqStep = 2^mu; % Frequency step (kHz)
freqSearch = -bw/2:freqStep:bw/2-freqStep;
[~,fSearchIdx] = sort(abs(freqSearch)); % Sort frequencies from center
freqSearch = freqSearch(fSearchIdx);

for fpc = fPhaseComp + 1e3*freqSearch

    % OFDM demodulate received waveform
    nSlot = 0;
    rxGrid = nrOFDMDemodulate(rxWaveform, nrb, scsCommon, nSlot,...
                                'SampleRate',sampleRate,'CarrierFrequency',fpc);

    % Extract monitoring slot from the received grid
    rxSlotGrid = rxGrid(csetSubcarriers,monSlotsSym,:);
    rxSlotGrid = rxSlotGrid/max(abs(rxSlotGrid(:))); % Normalization of received RE magnitude

    % Channel estimation and equalization of PDSCH symbols
    [hest,nVar,pdschHestInfo] = nrChannelEstimate(rxSlotGrid,pdschDmrsIndices,pdschDmrsSymbols);
    [pdschIndices,pdschIndicesInfo] = nrPDSCHIndices(carrier,pdsch);
    [pdschRxSym,pdschHest] = nrExtractResources(pdschIndices,rxSlotGrid,hest);
    pdschEqSym = nrEqualizeMMSE(pdschRxSym,pdschHest,nVar);

    % PDSCH demodulation
    cw = nrPDSCHDecode(carrier,pdsch,pdschEqSym,nVar);

    % Create and configure DL-SCH decoder with target code rate and
    % transport block size
    decodeDLSCH = nrDLSCHDecoder;
    decodeDLSCH.LDPCDecodingAlgorithm = 'Normalized min-sum';
    Xoh_PDSCH = 0; % TS 38.214 Section 5.1.3.2
    tcr = hMCS(dci.ModulationCoding);
    NREPerPRB = pdschIndicesInfo.NREPerPRB;
    tbsLength = nrTBS(pdsch.Modulation,pdsch.NumLayers,length(pdsch.PRBSet),NREPerPRB,tcr,Xoh_PDSCH);
    decodeDLSCH.TransportBlockLength = tbsLength;
    decodeDLSCH.TargetCodeRate = tcr;

    % Decode DL-SCH
    [sib1bits,sib1CRC] = decodeDLSCH(cw,pdsch.Modulation,pdsch.NumLayers,dci.RedundancyVersion);

    if sib1CRC == 0
        break;
    end

end

% Highlight PDSCH and PDSCH DM-RS in resource grid.
pdcch.AggregationLevel = 2^(aLevIdx-2);
pdcch.AllocatedCandidate = cIdx-1;
plotResourceGridSIB1(rxSlotGrid,carrier,pdcch,pdsch,tcr,K0);

% Plot received PDSCH constellation after equalization
figure;
plot(pdschEqSym,'o');
xlabel('In-Phase'); ylabel('Quadrature')
title('Equalized PDSCH Constellation');
m = max(abs([real(pdschEqSym(:)); imag(pdschEqSym(:))])) * 1.1;
axis([-m m -m m]);

% Calculate RMS PDSCH EVM, including normalization of PDSCH symbols for any
% offset between DM-RS and PDSCH power
pdschRef = nrPDSCH(carrier,pdsch,double(cw{1}<0));
evm = comm.EVM;
pdschEVMrms = evm(pdschRef,pdschEqSym/sqrt(var(pdschEqSym)));

% Display PDSCH EVM and DL-SCH CRC
disp([' PDSCH RMS EVM: ' num2str(pdschEVMrms,'%0.3f') '%']);
disp([' PDSCH CRC: ' num2str(sib1CRC)]);

if sib1CRC == 0
    disp(' SIB1 decoding succeeded.');
else
    disp(' SIB1 decoding failed.');
end
 -- PDSCH demodulation and DL-SCH decoding -- 
 PDSCH RMS EVM: 10.276%
 PDSCH CRC: 0
 SIB1 decoding succeeded.

참고 문헌

  1. 3GPP TS 38.101-1. "NR; User Equipment (UE) radio transmission and reception; Part 1: Range 1 Standalone" 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

  2. 3GPP TS 38.104. "NR; Base Station (BS) radio transmission and reception." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

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

  4. 3GPP TS 38.212. "NR; Multiplexing and channel coding." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

  5. 3GPP TS 38.213. "NR; Physical layer procedures for control." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

  6. 3GPP TS 38.214. "NR; Physical layer procedures for data." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

  7. 3GPP TS 38.321. "NR; Medium Access Control (MAC) protocol specification." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

로컬 함수

function present = isCORESET0Present(ssbBlockPattern,kSSB)

    switch ssbBlockPattern
        case {'Case A','Case B','Case C'} % FR1
            kssb_max = 23;
        case {'Case D','Case E'} % FR2
            kssb_max = 11;
    end
    if (kSSB <= kssb_max)
        present = true;
    else
        present = false;
    end

end

function [timingOffset,nLeadingFrames] = hTimingOffsetToFirstFrame(offset,burst,ssbIdx,nHalfFrame,sampleRate)

    % As the symbol lengths are measured in FFT samples, scale the symbol
    % lengths to account for the receiver sample rate. Non-integer delays
    % are approximated at the end of the process.
    scs = hSSBurstSubcarrierSpacing(burst.BlockPattern);
    ofdmInfo = nrOFDMInfo(1,scs,'SampleRate',sampleRate); % smallest FFT size for SCS-SR
    srRatio = sampleRate/(scs*1e3*ofdmInfo.Nfft);
    symbolLengths = ofdmInfo.SymbolLengths*srRatio;

    % Adjust timing offset to the start of the SS block. This step removes
    % the extra offset introduced in the reference grid during PSS search,
    % which contained the PSS in the second OFDM symbol.
    offset = offset + symbolLengths(1);

    % Timing offset is adjusted so that the received grid starts at the
    % frame head i.e. adjust the timing offset for the difference between
    % the first symbol of the strongest SSB, and the start of the frame
    burstStartSymbols = hSSBurstStartSymbols(burst.BlockPattern,burst.L_max); % Start symbols in SSB numerology
    ssbFirstSym = burstStartSymbols(ssbIdx+1); % 0-based

    % Adjust for whole subframes
    symbolsPerSubframe = length(symbolLengths);
    subframeOffset = floor(ssbFirstSym/symbolsPerSubframe);
    samplesPerSubframe = sum(symbolLengths);
    timingOffset = offset - (subframeOffset*samplesPerSubframe);

    % Adjust for remaining OFDM symbols
    symbolOffset = mod(ssbFirstSym,symbolsPerSubframe);
    timingOffset = timingOffset - sum(symbolLengths(1:symbolOffset));

    % The first OFDM symbol of the SSB is defined with respect to the
    % half-frame where it is transmitted. Adjust for half-frame offset
    timingOffset = timingOffset - nHalfFrame*5*samplesPerSubframe;

    % Adjust offset to the first frame in the waveform that is scheduled
    % for SSB transmission.
    repetitions = ceil(timingOffset/(20*samplesPerSubframe));
    timingOffset = round(timingOffset - repetitions*20*samplesPerSubframe);

    % Calculate the number of leading frames before the detected one
    nLeadingFrames = 2*repetitions;

end

function initSystemInfo = initSystemInfo(mib,sfn4lsb,k_SSB,L_max)

    % Create set of subcarrier spacings signaled by the 7th bit of the
    % decoded MIB, the set is different for FR1 (L_max=4 or 8) and FR2
    % (L_max=64)
    if (L_max==64)
        scsCommon = [60 120];
    else
        scsCommon = [15 30];
    end

    initSystemInfo = struct();
    initSystemInfo.NFrame = mib.systemFrameNumber*2^4 + bit2int(sfn4lsb,4);
    initSystemInfo.SubcarrierSpacingCommon = scsCommon(mib.subCarrierSpacingCommon + 1);
    initSystemInfo.k_SSB = k_SSB + mib.ssb_SubcarrierOffset;
    initSystemInfo.DMRSTypeAPosition = 2 + mib.dmrs_TypeA_Position;
    initSystemInfo.PDCCHConfigSIB1 = info(mib.pdcch_ConfigSIB1);
    initSystemInfo.CellBarred = mib.cellBarred;
    initSystemInfo.IntraFreqReselection = mib.intraFreqReselection;

end

function nrb = hCORESET0DemodulationBandwidth(sysInfo,scsSSB,minChannelBW)

    % Determine the OFDM demodulation bandwidth from CORESET 0 bandwidth
    cset0Idx = sysInfo.PDCCHConfigSIB1.controlResourceSetZero;
    scsCommon = sysInfo.SubcarrierSpacingCommon;
    scsPair = [scsSSB scsCommon];
    [csetNRB,~,csetFreqOffset] = hCORESET0Resources(cset0Idx,scsPair,minChannelBW,sysInfo.k_SSB);

    % Calculate a suitable bandwidth in RB that includes CORESET 0 in
    % received waveform.
    c0 = csetFreqOffset + 10*scsSSB/scsCommon;  % CORESET frequency offset from carrier center
    nrb = 2*max(c0,csetNRB-c0)+2;               % Number of RB to cover CORESET 0

end

function [k,slots,slotSymbols,ssStartSym] = hPDCCH0MonitoringResources(systemInfo,scsSSB,minChannelBW,ssbIndex,numRxSym)

    cset0Idx = systemInfo.PDCCHConfigSIB1.controlResourceSetZero;
    scsCommon = systemInfo.SubcarrierSpacingCommon;
    scsPair = [scsSSB scsCommon];
    k_SSB = systemInfo.k_SSB;
    [c0NRB,c0Duration,c0FreqOffset,c0Pattern] = hCORESET0Resources(cset0Idx,scsPair,minChannelBW,k_SSB);

    ssIdx = systemInfo.PDCCHConfigSIB1.searchSpaceZero;
    [ssSlot,ssStartSym,isOccasion] = hPDCCH0MonitoringOccasions(ssIdx,ssbIndex,scsPair,c0Pattern,c0Duration,systemInfo.NFrame);

    % PDCCH monitoring occasions associated to different SS blocks can be
    % in different frames. If there are no monitoring occasions in this
    % frame, there must be one in the next one. Adjust the slots associated
    % to the search space by one frame if needed.
    slotsPerFrame = 10*scsCommon/15;
    ssSlot = ssSlot + (~isOccasion)*slotsPerFrame;

    % For FR1, UE monitors PDCCH in the Type0-PDCCH CSS over two consecutive
    % slots for CORESET pattern 1
    monSlotsPerPeriod = 1 + (c0Pattern==1);

    % Calculate 1-based subscripts of the subcarriers and OFDM symbols for
    % the slots containing the PDCCH0 associated to the detected SS block
    % in this and subsequent 2-frame blocks
    nrb = hCORESET0DemodulationBandwidth(systemInfo,scsSSB,minChannelBW);
    k = 12*(nrb-20*scsSSB/scsCommon)/2 - c0FreqOffset*12 + (1:c0NRB*12);

    symbolsPerSlot = 14;
    numRxSlots = ceil(numRxSym/symbolsPerSlot);
    slots = ssSlot + (0:monSlotsPerPeriod-1)' + (0:2*slotsPerFrame:(numRxSlots-ssSlot-1));
    slots = slots(:)';
    slotSymbols = slots*symbolsPerSlot + (1:symbolsPerSlot)';
    slotSymbols = slotSymbols(:)';

    % Remove monitoring symbols exceeding waveform limits
    slotSymbols(slotSymbols>numRxSym) = [];

    % Calculate the monitoring slots after removing symbols
    slots = (slotSymbols(1:symbolsPerSlot:end)-1)/symbolsPerSlot;

end

function scsKSSB = kSSBSubcarrierSpacing(scsCommon)
% Subcarrier spacing of k_SSB, as defined in TS 38.211 Section 7.4.3.1

    if scsCommon > 30  % FR2
        scsKSSB = scsCommon;
    else
        scsKSSB = 15;
    end

end

function c = hCarrierConfigSIB1(ncellid,initSystemInfo,pdcch)

    c = nrCarrierConfig;
    c.SubcarrierSpacing = initSystemInfo.SubcarrierSpacingCommon;
    c.NStartGrid = pdcch.NStartBWP;
    c.NSizeGrid = pdcch.NSizeBWP;
    c.NSlot = pdcch.SearchSpace.SlotPeriodAndOffset(2);
    c.NFrame = initSystemInfo.NFrame;
    c.NCellID = ncellid;

end

function plotResourceGrid(rxGrid,refBurst,systemInfo,nLeadingFrames,ssbIndex,nHalfFrame)

    % Extract SSB and common SCS from reference SS burst and initial system
    % information
    scsSSB = hSSBurstSubcarrierSpacing(refBurst.BlockPattern);
    scsCommon = systemInfo.SubcarrierSpacingCommon;
    scsRatio = scsSSB/scsCommon;

    % Number of subcarriers, symbols and frames.
    [K,L] = size(rxGrid);
    symbolsPerSubframe = 14*scsCommon/15;
    numFrames = ceil(L/(10*symbolsPerSubframe));

    % Define colors and auxiliary plotting function
    basePlotProps = {'LineStyle','-','LineWidth',1};
    occasionColor = 0.7*[1 1 1];
    detectionColor = [200,0,0]/255;

    frameBoundaryColor = 0.1*[1 1 1];
    boundingBox = @(y,x,h,w,varargin)rectangle('Position',[x+0.5 y-0.5 w h],basePlotProps{:},varargin{:});

    % Create figure and display resource grid
    figure;
    imagesc(abs(rxGrid(:,:,1))); axis xy; hold on;

    % Add vertical frame lines
    x = repmat((0:numFrames-1)*10*symbolsPerSubframe,3,1);
    x(3,:) = NaN;
    y = repmat([0;K;NaN],1,numFrames);
    plot(x(:),y(:),'Color',frameBoundaryColor);

    % Determine frequency origin of the SSB in common numerology
    ssbCenter = K/2;
    halfSSB = 10*12*scsRatio;
    scsKSSB = kSSBSubcarrierSpacing(scsCommon);
    kSSBFreqOff = systemInfo.k_SSB*scsKSSB/scsCommon;
    ssbFreqOrig = ssbCenter - halfSSB + kSSBFreqOff + 1;

    % Determine time origin of the SSB in common numerology
    ssbStartSymbols = hSSBurstStartSymbols(refBurst.BlockPattern,refBurst.L_max);
    ssbStartSymbols = ssbStartSymbols + 5*symbolsPerSubframe*nHalfFrame;
    ssbHeadSymbol = ssbStartSymbols(ssbIndex+1)/scsRatio;
    ssbTailSymbol = floor((ssbStartSymbols(ssbIndex+1)+4)/scsRatio)-1;

    % Draw bounding boxes around all SS/PBCH block occasions
    w = ssbTailSymbol - ssbHeadSymbol + 1;
    for i = 1:ceil(numFrames/2)
        s = ssbHeadSymbol + (i-1)*2*10*symbolsPerSubframe + 5*symbolsPerSubframe*nHalfFrame;
        if s <= (L - w)
            boundingBox(ssbFreqOrig,s,240*scsRatio,w,'EdgeColor',occasionColor);
        end
    end

    % Draw bounding box for detected SS/PBCH block
    s = ssbHeadSymbol + nLeadingFrames*10*symbolsPerSubframe + 5*symbolsPerSubframe*nHalfFrame;
    boundingBox(ssbFreqOrig,s,240*scsRatio,w,basePlotProps{:},'EdgeColor',detectionColor)

    % Add text next to detected SS/PBCH block
    str = sprintf('SSB#%d',ssbIndex);
    text(s+w+1,ssbFreqOrig+24,0,str,'FontSize',10,'Color','w')

    % Create legend. Since rectangles don't show up in legend, create a
    % placeholder for bounding boxes.
    plot(NaN,NaN,basePlotProps{:},'Color',occasionColor);
    plot(NaN,NaN,basePlotProps{:},'Color',detectionColor);
    legend('Frame boundary','Occasion','Detected')
    xlabel('OFDM symbol'); ylabel('Subcarrier');

    % Add title including frame numbers
    firstNFrame = systemInfo.NFrame - nLeadingFrames;
    nframes = mod(firstNFrame + (0:numFrames-1),1024);
    sfns = sprintf('(%d...%d)',nframes(1),nframes(end));
    title(['Received Resource Grid. System Frame Number: ' sfns]);

end

function highlightCORESET0SS(csetSubcarriers,monSlots,detSlot,pdcch,dciCRC)

    ssFirstSym = pdcch.SearchSpace.StartSymbolWithinSlot;
    csetDuration = pdcch.CORESET.Duration;

    % Define colors and plotting function
    basePlotProps = {'LineStyle','-','LineWidth',1};
    occasionColor = 0.7*[1 1 1];
    detectionColor = [200,0,0]/255;
    boundingBox = @(y,x,h,w,varargin)rectangle('Position',[x+0.5 y-0.5 w h],basePlotProps{:},varargin{:});

    % Highlight all CORESET 0/SS occasions related to the detected SSB
    k0 = csetSubcarriers(1);
    K = length(csetSubcarriers);
    ssSym = 14*monSlots + ssFirstSym ;
    for i = 1:length(ssSym)
        boundingBox(k0,ssSym(i),K,csetDuration,'EdgeColor',occasionColor);
    end

    if dciCRC == 0
        % Highlight decoded PDCCH
        ssSym = 14*detSlot + ssFirstSym;
        boundingBox(k0,ssSym,K,csetDuration,'EdgeColor',detectionColor);

        % Add text next to decoded PDCCH
        text(ssSym+csetDuration+1,k0+24,0,'PDCCH','FontSize',10,'Color','w')
    end

end

function plotResourceGridSIB1(slotGrid,carrier,pdcch,pdsch,tcr,K0)

    % Display the OFDM grid of the slot containing decoded PDCCH
    figure;
    imagesc(abs(slotGrid(:,:,1))); axis xy
    xlabel('OFDM symbol');
    ylabel('subcarrier');
    title('Slot Containing Decoded PDCCH');

    aggregationLevelIndex = log2(pdcch.AggregationLevel)+1;
    candidate = pdcch.AllocatedCandidate;

    % Define auxiliary plotting function
    color = [200,0,0]/255;
    boundingBox = @(y,x,h,w,varargin)rectangle('Position',[x+0.5 y-0.5 w h],'EdgeColor',color,varargin{:});

    % Highlight PDCCH in resource grid
    carrier.NSlot = carrier.NSlot - K0; % Substract slot offset K0 for subscripts calculations
    subsPdcch = nrPDCCHSpace(carrier,pdcch,'IndexStyle','Subs');
    subsPdcch = double(subsPdcch{aggregationLevelIndex}(:,:,candidate));
    x = min(subsPdcch(:,2))-1; X = max(subsPdcch(:,2))-x;
    y = min(subsPdcch(:,1)); Y = max(subsPdcch(:,1))-y+1;
    boundingBox(y,x,Y,X);
    str = sprintf('PDCCH \nAggregation Level: %d\nCandidate: %d',2.^(aggregationLevelIndex-1),candidate-1);
    text(x+X+1,y+Y/2,0,str,'FontSize',10,'Color','w')

    % Highlight PDSCH and PDSCH DM-RS in resource grid
    carrier.NSlot = carrier.NSlot + K0; % Add back slot offset K0 for subscripts calculations
    subsPdschSym = double(nrPDSCHIndices(carrier,pdsch,'IndexStyle','subscript'));
    subsPdschDmrs = double(nrPDSCHDMRSIndices(carrier,pdsch,'IndexStyle','subscript'));
    subsPdsch = [subsPdschSym;subsPdschDmrs];
    x = min(subsPdsch(:,2))-1; X = max(subsPdsch(:,2))-x;
    y = min(subsPdsch(:,1)); Y = max(subsPdsch(:,1))-y+1;
    boundingBox(y,x,Y,X);
    str = sprintf('PDSCH (SIB1) \nModulation: %s\nCode rate: %.2f',pdsch.Modulation,tcr);
    text(x+4,y+Y+60,0, str,'FontSize',10,'Color','w')

end

관련 항목