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 を搬送する同期信号バースト、および SIB1 を搬送する CORESET 0、PDCCH、PDSCH を構成し、生成します。送信機は 1 つの SS ブロックの SNR を向上させることがありますが、ビームフォーミングを実行するわけではありません。SSB ビームフォーミングの詳細については、NR SSB のビーム スイーピングを参照してください。

  • AWGN: 波形に加法性ホワイト ガウス ノイズ (AWGN) を適用します。

  • 受信機: 受信波形にさまざまな同期処理と復調処理を適用し、システム フレーム番号、セル ID、SSB を確定して、MIB を復号化します。これらによって、PDCCH の downlink control information (DCI) のブラインド復号化に必要な情報が得られます。受信機は DCI を使用して PDSCH 復調器を構成し、DL-SCH を復号化して、最後に SIB1 を復元します。

次の図は、受信機内部の処理手順を示しています。

受信機構成

受信波形を同期して復調するには、次の情報が必要です。

  • 受信波形を復調するための波形のサンプル レート。

  • 受信波形にシンボル位相補償を適用するためのキャリアの中心周波数。

  • CORESET 0 の周波数リソースを決定するための最小チャネル帯域幅。TS 38.101-1 の Table 5.3.5-1 [ 1 ] では、各 NR 帯域のチャネル帯域幅について説明されています。

  • SS/PBCH ブロックのサブキャリア間隔を決定するための SS ブロック パターン (ケース A ~ E)。UE は NR 動作帯域に基づいて SS ブロック パターンを検索します。詳細については、TS 38.104 の Table 5.4.3.3-1 と Table 5.4.3.3-2 [ 2 ] を参照してください。

  • PBCH DM-RS シーケンスと PBCH デスクランブルのパラメーターを計算するためのバースト内 SS/PBCH ブロックの数 ($L_{max}$)。これらのパラメーターは、TS 38.211 の Section 7.3.3.1 と Section 7.4.1.4.1 [ 3 ] で説明されているように、SS/PBCH ブロック インデックスに依存しています。TS 38.213 の Section 4.1 [ 5 ] では、各ケースでのバースト内 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 を使用して制御します。

  • 周波数シフトされた受信波形と各 PSS シーケンス (NID2) の 3 つの候補の相関をとり、最も強い相関ピークを抽出する。基準 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 復号化を構成するものには、レート リカバリ、Polar 復号化、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 の 6 つの MSB と PBCH ペイロード ビットの 4 つの LSB から 10 ビットのシステム フレーム番号 (SFN) NFrame を再構成することが含まれます。また、バーストごとに L_max=4 または L_max=8 の SS/PBCH ブロックについて、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 ] で規定されている帯域幅を介する共通の numerology 内で、CORESET 0 の周波数リソースを決定します。周波数補正処理によって、OFDM リソース グリッドの中心と SS バーストの中心周波数が揃えられます。しかし、その中心と CORESET 0 の中心周波数とが必ずしも一致するわけではありません。次の図は、CORESET 0 の周波数リソース SSB と関連する PDCCH モニタリングとの関係を示しています。

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 ブロックをスケジューリングできる最初のフレームのフレーム原点に対するタイミング オフセットを調整します。フレーム オフセットが負の場合、最初のフレームは不完全です。波形の先頭にゼロを追加し、そのフレームと波形の位置を合わせます。

[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 の復調と Downlink Control Information の復号化

CORESET/SS 内のシステム情報 DCI メッセージをブラインド サーチするため、受信機は以下の手順を実行します。

  • PDCCH モニタリングの判定と、制御情報を含む OFDM リソース グリッドの抽出。

  • CORESET 0、サーチ スペース、PDCCH の各構成。

  • Format 1_0 の DCI メッセージのブラインド サーチ。

受信機は、TS 38.213 の Table 13-11 と Table 13-12 [ 5 ] の説明に従い、スロットおよび検出した SS ブロックの位置からの OFDM シンボルのオフセットによって、PDCCH モニタリングを判定します。受信機は、この波形で利用できる最初のフレームに対する新しい同期時間を考慮し、システム フレーム番号を調整します。

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 から REG へのインターリーブ マッピングのパラメーター (REGBundleSize = 6、InterleaverSize = 2、ShiftIndex = NCellID) は、TS 38.211 の Section 7.3.2.2 [ 3 ] に記載されています。CORESET 0 の場合、BWP は TS 38.212 の Section 7.3.1.0 [ 4 ] に記載されている 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、120 kHz の場合、それぞれ 1920、3840、7680、15360 kHz になります。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

関連するトピック