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 ブロックの数 ()。これらのパラメーターは、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 動作帯域に基づいて、 の値を認識します。
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 mcsTables = nrPDSCHMCSTables; qam64Table = mcsTables.QAM64Table; % TS 38.214 Table 5.1.3.1-1 tcr = qam64Table.TargetCodeRate(qam64Table.MCSIndex==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.
参考文献
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.
3GPP TS 38.104. "NR; Base Station (BS) radio transmission and reception." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.
3GPP TS 38.211. "NR; Physical channels and modulation." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.
3GPP TS 38.212. "NR; Multiplexing and channel coding." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.
3GPP TS 38.213. "NR; Physical layer procedures for control." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.
3GPP TS 38.214. "NR; Physical layer procedures for data." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.
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