-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhDLPMISelect.m
1975 lines (1898 loc) · 113 KB
/
hDLPMISelect.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
function [PMISet,info] = hDLPMISelect(carrier,csirs,reportConfig,nLayers,H,varargin)
%hDLPMISelect PDSCH precoding matrix indicator calculation
% [PMISET,INFO] = hDLPMISelect(CARRIER,CSIRS,REPORTCONFIG,NLAYERS,H)
% returns the precoding matrix indicator (PMI) values, as defined in
% TS 38.214 Section 5.2.2.2, for the specified carrier configuration
% CARRIER, CSI-RS configuration CSIRS, channel state information (CSI)
% reporting configuration REPORTCONFIG, number of transmission layers
% NLAYERS, and estimated channel information H.
%
% CARRIER is a carrier specific configuration object, as described in
% <a href="matlab:help('nrCarrierConfig')">nrCarrierConfig</a>. Only these object properties are relevant for this
% function:
%
% SubcarrierSpacing - Subcarrier spacing in kHz
% CyclicPrefix - Cyclic prefix type
% NSizeGrid - Number of resource blocks (RBs) in
% carrier resource grid
% NStartGrid - Start of carrier resource grid relative to common
% resource block 0 (CRB 0)
% NSlot - Slot number
% NFrame - System frame number
%
% CSIRS is a CSI-RS specific configuration object to specify one or more
% CSI-RS resources, as described in <a href="matlab:help('nrCSIRSConfig')">nrCSIRSConfig</a>. Only these object
% properties are relevant for this function:
%
% CSIRSType - Type of a CSI-RS resource {'ZP', 'NZP'}
% CSIRSPeriod - CSI-RS slot periodicity and offset
% RowNumber - Row number corresponding to a CSI-RS resource, as
% defined in TS 38.211 Table 7.4.1.5.3-1
% Density - CSI-RS resource frequency density
% SymbolLocations - Time-domain locations of a CSI-RS resource
% SubcarrierLocations - Frequency-domain locations of a CSI-RS resource
% NumRB - Number of RBs allocated for a CSI-RS resource
% RBOffset - Starting RB index of CSI-RS allocation relative
% to carrier resource grid
% For better results, it is recommended to use the same CSI-RS
% resource(s) that are used for channel estimate, because the resource
% elements (REs) that does not contain the CSI-RS may have the
% interpolated channel estimates. Note that the CDM lengths and the
% number of ports configured for all the CSI-RS resources must be same.
%
% REPORTCONFIG is a CSI reporting configuration structure with these
% fields:
% NSizeBWP - Size of the bandwidth part (BWP) in terms of number
% of physical resource blocks (PRBs). It must be a
% scalar and the value must be in the range 1...275.
% Empty ([]) is also supported and it implies that the
% value of NSizeBWP is equal to the size of carrier
% resource grid
% NStartBWP - Starting PRB index of BWP relative to common resource
% block 0 (CRB 0). It must be a scalar and the value
% must be in the range 0...2473. Empty ([]) is also
% supported and it implies that the value of NStartBWP
% is equal to the start of carrier resource grid
% CodebookType - Optional. The type of codebooks according to which
% the CSI parameters must be computed. It must be a
% character array or a string scalar. It must be one of
% {'Type1SinglePanel', 'Type1MultiPanel'}. In case of
% 'Type1SinglePanel', the PMI computation is performed
% using TS 38.214 Tables 5.2.2.2.1-1 to 5.2.2.2.1-12.
% In case of 'Type1MultiPanel', the PMI computation is
% performed using TS 38.214 Tables 5.2.2.2.2-1 to
% 5.2.2.2.2-6. The default value is 'Type1SinglePanel'
% PanelDimensions - Antenna panel configuration.
% - When CodebookType field is specified as
% 'Type1SinglePanel', this field is a two-element
% vector in the form of [N1 N2]. N1 represents the
% number of antenna elements in horizontal
% direction and N2 represents the number of
% antenna elements in vertical direction. Valid
% combinations of [N1 N2] are defined in TS 38.214
% Table 5.2.2.2.1-2. This field is not applicable
% when the number of CSI-RS ports is less than or
% equal to 2
% - When CodebookType field is specified as
% 'Type1MultiPanel', this field is a three element
% vector in the form of [Ng N1 N2], where Ng
% represents the number of antenna panels. Valid
% combinations of [Ng N1 N2] are defined in TS
% 38.214 Table 5.2.2.2.2-1
% PMIMode - Optional. It represents the mode of PMI reporting. It
% must be a character array or a string scalar. It must
% be one of {'Subband', 'Wideband'}. The default value
% is 'Wideband'
% SubbandSize - Subband size for PMI reporting, provided by the
% higher-layer parameter NSBPRB. It must be a positive
% scalar and must be one of two possible subband sizes,
% as defined in TS 38.214 Table 5.2.1.4-2. It is
% applicable only when the PMIMode is provided as
% 'Subband' and the size of BWP is greater than or
% equal to 24 PRBs
% PRGSize - Optional. Precoding resource block group (PRG) size
% for CQI calculation, provided by the higher-layer
% parameter pdsch-BundleSizeForCSI. This field is
% applicable when the PMI reporting is needed for the
% CSI report quantity cri-RI-i1-CQI, as defined in
% TS 38.214 Section 5.2.1.4.2. This report quantity
% expects only the i1 set of PMI to be reported as part
% of CSI parameters and PMI mode is expected to be
% 'Wideband'. But, for the computation of the CQI in
% this report quantity, PMI i2 values are needed for
% each PRG. Hence, the PMI output, when this field is
% configured, is given as a set of i2 values, one for
% each PRG of the specified size. It must be a scalar
% and it must be one of {2, 4}. Empty ([]) is also
% supported to represent that this field is not
% configured by higher layers. If it is present and not
% configured as empty, irrespective of the PMIMode,
% PRGSize is considered for the number of subbands
% calculation instead of SubbandSize and the function
% reports PMI for each PRG. This field is applicable
% only when the CodebookType is specified as
% 'Type1SinglePanel'. The default value is []
% CodebookMode - Optional. It represents the codebook mode and it must
% be a scalar. The value must be one of {1, 2}.
% - When CodebookType is specified as
% 'Type1SinglePanel', this field is applicable
% only if the number of transmission layers is 1
% or 2 and number of CSI-RS ports is greater than
% 2.
% - When CodebookType is specified as
% 'Type1MultiPanel', this field is applicable for
% all the number of transmission layers and the
% CodebookMode value 2 is applicable only for the
% panel configurations with Ng value 2.
% The default value is 1
% CodebookSubsetRestriction
% - Optional. It is a binary vector which represents the
% codebook subset restriction. When the number of
% CSI-RS ports is greater than 2, the length of the
% input vector must be N1*N2*O1*O2, where N1 and N2 are
% panel configurations obtained from PanelDimensions
% field and O1 and O2 are the respective discrete
% Fourier transform (DFT) oversampling factors obtained
% from TS.38.214 Table 5.2.2.2.1-2 for
% 'Type1SinglePanel' codebook type or TS.38.214 Table
% 5.2.2.2.2-1 for 'Type1MultiPanel' codebook type.
% When the number of CSI-RS ports is 2, the applicable
% codebook type is 'Type1SinglePanel' and the length of
% the input vector must be 6, as defined in TS 38.214
% Section 5.2.2.2.1. The default value is empty ([]),
% which means there is no codebook subset restriction
% i2Restriction - Optional. It is a binary vector which represents the
% restricted i2 values in a codebook. Length of the
% input vector must be 16. First element of the input
% binary vector corresponds to i2 as 0, second element
% corresponds to i2 as 1, and so on. Binary value 1
% indicates that the precoding matrix associated with
% the respective i2 is unrestricted and 0 indicates
% that the precoding matrix associated with the
% respective i2 is restricted. For a precoding matrices
% codebook, if the number of possible i2 values are
% less than 16, then only the required binary elements
% are considered and the trailing extra elements in the
% input vector are ignored. This field is applicable
% only when the number of CSI-RS ports is greater than
% 2 and the CodebookType field is specified as
% 'Type1SinglePanel'. The default value is empty ([]),
% which means there is no i2 restriction.
%
% For the CodebookSubsetRestriction,
% - The element N2*O2*l+m+1 (1-based) is associated with the precoding
% matrices based on vlm (l = 0...N1*O1-1, m = N2*O2-1). If the associated
% binary value is zero, then all the precoding matrices based on vlm are
% restricted.
% - When CodebookType field is specified as 'Type1SinglePanel', only if
% the number of transmission layers is one of {3, 4} and the number of
% CSI-RS ports is greater than or equal to 16, the elements
% {mod(N2*O2*(2*l-1)+m,N1*O1*N2*O2)+1, N2*O2*(2*l)+m+1,
% N2*O2*(2*l+1)+m+1} (1-based) are each associated with all the precoding
% matrices based on vbarlm (l = 0....(N1*O1/2)-1, m = 0....N2*O2), as
% defined in TS 38.214 Section 5.2.2.2.1. If one or more of the
% associated binary values is zero, then all the precoding matrices based
% on vbarlm are restricted.
%
% NLAYERS is a scalar representing the number of transmission layers.
% When CodebookType is specified as 'Type1SinglePanel', its value must be
% in the range of 1...8. When CodebookType is specified as
% 'Type1MultiPanel', its value must be in the range of 1...4.
%
% H is the channel estimation matrix. It is of size
% K-by-L-by-nRxAnts-by-Pcsirs, where K is the number of subcarriers in
% the carrier resource grid, L is the number of orthogonal frequency
% division multiplexing (OFDM) symbols spanning one slot, nRxAnts is the
% number of receive antennas, and Pcsirs is the number of CSI-RS antenna
% ports. Note that the number of transmission layers provided must be
% less than or equal to min(nRxAnts,Pcsirs).
%
% PMISET is an output structure with these fields:
% i1 - Indicates wideband PMI (1-based).
% - It is a three-element vector in the form of [i11 i12 i13],
% when CodebookType is specified as 'Type1SinglePanel'. Note
% that i13 is not applicable when the number of transmission
% layers is one of {1, 5, 6, 7, 8}. In that case, function
% returns the value of i13 as 1
% - It is a six-element vector in the form of
% [i11 i12 i13 i141 i142 i143] when CodebookType is specified
% as 'Type1MultiPanel'. Note that when CodebookMode is 1 and
% number of antenna panels is 2, i142 and i143 are not
% applicable and when CodebookMode is 2, i143 is not
% applicable. In both the codebook modes, i13 value is not
% applicable when the number of transmission layers is 1. In
% these cases, the function returns the respective values as 1
% i2 - Indicates subband PMI (1-based).
% - For 'Type1SinglePanel' codebook type
% - When PMIMode is specified as 'wideband', it is a scalar
% representing one i2 indication for the entire band
% - When PMIMode is specified as 'subband' or when PRGSize
% is configured as other than empty ([]), one subband
% indication i2 is reported for each subband or PRG,
% respectively. Length of the i2 vector in the latter case
% equals to the number of subbands or PRGs
% - For 'Type1MultiPanel' codebook type
% - When PMIMode is specified as 'wideband', it is a
% three-element column vector in the form of
% [i20; i21; i22] representing one i2 set for the entire
% band
% - When PMIMode is configured as 'subband', it is a matrix
% of size 3-by-numSubbands, where numSubbands represents
% the number of subbands. In subband PMIMode, each column
% represents an indices set [i20; i21; i22] for each
% subband and each row consists of an array of elements of
% length numSubbands. Note that when CodebookMode is
% specified as 1, i21 and i22 are not applicable. In that
% case i2 is considered as i20 (first row), and i21 and
% i22 are given as ones
% Note that when the number of CSI-RS ports is 2, the applicable codebook
% type is 'Type1SinglePanel'. In this case, the precoding matrix is
% obtained by a single index (i2 field here) based on TS 38.214 Table
% 5.2.2.2.1-1. The function returns the i1 as [1 1 1] to support same
% indexing for all INFO fields according to 'Type1SinglePanel' codebook
% type. When the number of CSI-RS ports is 1, all the values of i1 and
% i2 fields are returned as ones, considering the dimensions of type 1
% single panel codebook index set.
%
% INFO is an output structure with these fields:
% SINRPerRE - It represents the linear signal to noise plus
% interference ratio (SINR) values in each RE within the
% BWP for all the layers and all the precoding matrices.
% When CodebookType is specified as 'Type1SinglePanel',
% it is a multidimensional array of size
% - N-by-L-by-nLayers-by-i2Length-by-i11Length-by-i12Length-by-i13Length
% when the number of CSI-RS ports is greater than 2
% - N-by-L-by-nLayers-by-i2Length when the number of
% CSI-RS ports is 2
% - N-by-L when the number of CSI-RS ports is 1
% N is the number of subcarriers in the BWP resource
% grid, i2Length is the maximum number of possible i2
% values and i11Length, i12Length, i13Length are the
% maximum number of possible i11, i12, and i13 values
% for the given report configuration respectively.
% When CodebookType is specified as 'Type1MultiPanel',
% it is a multidimensional array of size
% N-by-L-by-nLayers-by-i20Length-by-i21Length-by-i22Length-by-i11Length-by-i12Length-by-i13Length-by-i141Length-by-i142Length-by-i143Length
% i20Length, i21Length, i22Length, i141Length,
% i142Length and i143Length are the maximum number of
% possible i20, i21, i22, i141, i142, and i143 values
% for the given configuration respectively
% SINRPerSubband - It represents the linear SINR values in each subband
% for all the layers. SINR value in each subband is
% formed by averaging SINRPerRE estimates across each
% subband (i.e. in the appropriate region of the N
% dimension and across the L dimension).
% When CodebookType is specified as 'Type1SinglePanel',
% it is a multidimensional array of size
% - numSubbands-by-nLayers-by-i2Length-by-i11Length-by-i12Length-by-i13Length
% when the number of CSI-RS ports is greater than 2
% - numSubbands-by-nLayers-by-i2Length when the
% number of CSI-RS ports is 2
% - numSubbands-by-1 when the number of CSI-RS ports
% is 1
% When CodebookType is specified as 'Type1MultiPanel',
% it is a multidimensional array of size
% - numSubbands-by-nLayers-by-i20Length-by-i21Length-by-i22Length-by-i11Length-by-i12Length-by-i13Length-by-i141Length-by-i142Length-by-i143Length
% W - Multidimensional array containing precoding matrices
% based on the CSI reporting configuration.
% When CodebookType is specified as 'Type1SinglePanel',
% it is a multidimensional array of size
% - Pcsirs-by-nLayers-by-i2Length-by-i11Length-by-i12Length-by-i13Length
% when the number of CSI-RS ports is greater than 2
% - 2-by-nLayers-by-i2Length when the number of
% CSI-RS ports is 2
% - 1-by-1 with the value 1 when the number of CSI-RS
% ports is 1
% When CodebookType is specified as 'Type1MultiPanel',
% it is a multidimensional array of size
% - Pcsirs-by-nLayers-by-i20Length-by-i21Length-by-i22Length-by-i11Length-by-i12Length-by-i13Length-by-i141Length-by-i142Length-by-i143Length
% Note that the restricted precoding matrices as per the
% report configuration are returned as all zeros
%
% [PMISET,INFO] = hDLPMISelect(...,NVAR) specifies the estimated noise
% variance at the receiver NVAR as a nonnegative scalar. By default, the
% value of nVar is considered as 1e-10, if it is not given as input.
%
% Note that i1 and i2 fields of PMISET and SINRPerRE and SINRPerSubband
% fields of INFO are returned as array of NaNs for these cases:
% - When CSI-RS is not present in the operating slot or in the BWP
% - When all the precoding matrices in a codebook are restricted
% Also note that the PMI i2 index (or indices set) is reported as NaNs in
% the subbands where CSI-RS is not present.
%
% Note that the function only supports PMI reporting with type 1 single
% panel and type 1 multipanel codebooks.
%
% % Example:
% % This example demonstrates how to calculate PMI.
%
% % Carrier configuration
% carrier = nrCarrierConfig;
%
% % CSI-RS configuration
% csirs = nrCSIRSConfig;
% csirs.CSIRSType = {'nzp','nzp'};
% csirs.RowNumber = [4 4];
% csirs.Density = {'one','one'};
% csirs.SubcarrierLocations = {0 0};
% csirs.SymbolLocations = {0,5};
% csirs.NumRB = 52;
% csirs.RBOffset = 0;
% csirs.CSIRSPeriod = [4 0];
%
% % Configure the number of transmit and receive antennas
% nTxAnts = max(csirs.NumCSIRSPorts);
% nRxAnts = nTxAnts;
%
% % Configure the number of transmission layers
% numLayers = 1;
%
% % Generate CSI-RS indices and symbols
% csirsInd = nrCSIRSIndices(carrier,csirs);
% csirsSym = nrCSIRS(carrier,csirs);
%
% % Resource element mapping
% txGrid = nrResourceGrid(carrier,nTxAnts);
% txGrid(csirsInd) = csirsSym;
%
% % Get OFDM modulation related information
% OFDMInfo = nrOFDMInfo(carrier);
%
% % Perform OFDM modulation
% txWaveform = nrOFDMModulate(carrier,txGrid);
%
% % Configure the channel parameters.
% channel = nrTDLChannel;
% channel.NumTransmitAntennas = nTxAnts;
% channel.NumReceiveAntennas = nRxAnts;
% channel.SampleRate = OFDMInfo.SampleRate;
% channel.DelayProfile = 'TDL-C';
% channel.DelaySpread = 300e-9;
% channel.MaximumDopplerShift = 5;
% chInfo = info(channel);
%
% % Calculate the maximum channel delay
% maxChDelay = ceil(max(chInfo.PathDelays*OFDMInfo.SampleRate)) + chInfo.ChannelFilterDelay;
%
% % Pass the time-domain waveform through the channel
% rxWaveform = channel([txWaveform; zeros(maxChDelay,nTxAnts)]);
%
% % Calculate the timing offset
% offset = nrTimingEstimate(carrier,rxWaveform,csirsInd,csirsSym);
%
% % Perform timing synchronization
% rxWaveform = rxWaveform(1+offset:end,:);
%
% % Add AWGN
% SNRdB = 20; % in dB
% SNR = 10^(SNRdB/20); % Linear value
% N0 = 1/(sqrt(2.0*channel.NumReceiveAntennas*double(OFDMInfo.Nfft))*SNR); % Noise standard deviation
% rng('default');
% noise = N0*complex(randn(size(rxWaveform)),randn(size(rxWaveform)));
% rxWaveform = rxWaveform + noise;
% rxGrid = nrOFDMDemodulate(carrier,rxWaveform);
%
% % Perform the channel estimate
% [H,nVar] = nrChannelEstimate(rxGrid,csirsInd,csirsSym,'CDMLengths',[2 1]);
%
% % Configure the parameters related to CSI reporting
% reportConfig.NStartBWP = 0;
% reportConfig.NSizeBWP = 52;
% reportConfig.PanelDimensions = [2 1];
% reportConfig.PMIMode = 'Subband';
% reportConfig.SubbandSize = 4;
% reportConfig.PRGSize = [];
% reportConfig.CodebookMode = 2;
% reportConfig.CodebookSubsetRestriction = [];
% reportConfig.i2Restriction = [];
%
% % Calculate the PMI values
% [PMISet,PMIInfo] = hDLPMISelect(carrier,csirs,reportConfig,numLayers,H,nVar)
% Copyright 2020-2021 The MathWorks, Inc.
narginchk(5,6);
if (nargin == 6)
nVar = varargin{1};
else
% Consider a small noise variance value by default, if the noise
% variance is not given
nVar = 1e-10;
end
[reportConfig,csirsIndSubs,nVar] = validateInputs(carrier,csirs,reportConfig,nLayers,H,nVar);
% Get the PMI subband related information
subbandInfo = getDownlinkPMISubbandInfo(reportConfig);
numCSIRSPorts = csirs.NumCSIRSPorts(1);
% Set isType1SinglePanel flag to true if the codebook type is
% 'Type1SinglePanel'
isType1SinglePanel = strcmpi(reportConfig.CodebookType,'Type1SinglePanel');
if isType1SinglePanel
if numCSIRSPorts == 1
% W is a scalar with the value 1, when the number of CSI-RS
% ports is 1
W = 1;
else
% W is a multidimensional matrix of size
% Pcsirs-by-nLayers-by-i2Length-by-i11Length-by-i12Length-by-i13Length
% or Pcsirs-by-nLayers-by-i2Length based on the number of
% CSI-RS ports
W = getPMIType1SinglePanelCodebook(reportConfig,nLayers);
end
% Get the size of W
[~,~,i2Length,i11Length,i12Length,i13Length] = size(W);
% Store the sizes of the indices in a variable
indexSetSizes = [i2Length,i11Length,i12Length,i13Length];
else
% W is a multidimensional matrix of size
% Pcsirs-by-nLayers-by-i20Length-by-i21Length-by-i22Length-by-i11Length-by-i12Length-by-i13Length-by-i141Length-by-i142Length-by-i143Length
W = getPMIType1MultiPanelCodebook(reportConfig,nLayers);
[~,~,i20Length,i21Length,i22Length,i11Length,i12Length,i13Length,i141Length,i142Length,i143Length] = size(W);
% Store the sizes of the indices in a variable
indexSetSizes = [i20Length,i21Length,i22Length,i11Length,i12Length,i13Length,i141Length,i142Length,i143Length];
end
% Calculate the start of BWP relative to the carrier
bwpStart = reportConfig.NStartBWP - carrier.NStartGrid;
% Consider only the RE indices corresponding to the first CSI-RS port
csirsIndSubs_k = csirsIndSubs(:,1);
csirsIndSubs_l = csirsIndSubs(:,2);
% Extract the CSI-RS indices which are present in the BWP
csirsIndSubs_k = csirsIndSubs_k((csirsIndSubs_k >= bwpStart*12 + 1) & csirsIndSubs_k <= (bwpStart + reportConfig.NSizeBWP)*12);
csirsIndSubs_l = csirsIndSubs_l((csirsIndSubs_k >= bwpStart*12 + 1) & csirsIndSubs_k <= (bwpStart + reportConfig.NSizeBWP)*12);
% Make the CSI-RS subscripts relative to BWP
csirsIndSubs_k = csirsIndSubs_k - bwpStart*12;
if isempty(csirsIndSubs_k) || ~any(W(:))
% Report the outputs as all NaNs, if there are no CSI-RS resources
% present in the BWP or all the precoding matrices of the codebook
% are restricted
if isType1SinglePanel
PMISet.i1 = NaN(1,3);
PMISet.i2 = NaN*ones(1,subbandInfo.NumSubbands);
else
PMISet.i1 = NaN(1,6);
PMISet.i2 = NaN*ones(3,subbandInfo.NumSubbands);
end
info.SINRPerRE = NaN([reportConfig.NSizeBWP*12,carrier.SymbolsPerSlot,nLayers,indexSetSizes]);
info.SINRPerSubband = NaN([subbandInfo.NumSubbands,nLayers,indexSetSizes]);
info.W = W;
else
% Rearrange the channel matrix dimensions from
% K-by-L-by-nRxAnts-by-Pcsirs to nRxAnts-by-Pcsirs-by-K-by-L
H = permute(H,[3,4,1,2]);
SINRPerRE = NaN([reportConfig.NSizeBWP*12,carrier.SymbolsPerSlot,nLayers,indexSetSizes]);
for reIdx = 1:numel(csirsIndSubs_k)
% Calculate the linear SINR values in all CSI-RS REs for all
% the layers by considering all unrestricted precoding matrices
k = csirsIndSubs_k(reIdx);
l = csirsIndSubs_l(reIdx);
Htemp = H(:,:,k,l);
for i11 = 1:i11Length
for i12 = 1:i12Length
for i13 = 1:i13Length
if ~isType1SinglePanel
for i141 = 1:i141Length
for i142 = 1:i142Length
for i143 = 1:i143Length
for i20 = 1:i20Length
for i21 = 1:i21Length
for i22 = 1:i22Length
currentW = W(:,:,i20,i21,i22,i11,i12,i13,i141,i142,i143);
if any(currentW)
% Calculate the linear SINR value for the
% current RE and for the current precoding
% matrix
SINRPerRE(k,l,:,i20,i21,i22,i11,i12,i13,i141,i142,i143) = getPrecodedSINR(Htemp,nVar,currentW);
end
end
end
end
end
end
end
else % Type 1 single panel codebooks
for i2 = 1:i2Length
currentW = W(:,:,i2,i11,i12,i13);
if any(currentW)
% Calculate the linear SINR value for
% the current RE and for the current
% precoding matrix
SINRPerRE(k,l,:,i2,i11,i12,i13) = getPrecodedSINR(Htemp,nVar,currentW);
end
end
end
end
end
end
end
% Calculate the total SINR value for the entire grid corresponding
% to each index to check which index gives the maximum wideband SINR
% value
% If the SINRPerRE values result as all NaNs, report the
% PMISet as NaNs
if all(isnan(SINRPerRE(:)))
if isType1SinglePanel
PMISet.i1 = NaN(1,3);
PMISet.i2 = NaN;
else
PMISet.i1 = NaN(1,6);
PMISet.i2 = NaN(3,1);
end
else
totalSINR = squeeze(sum(SINRPerRE,[1 2 3],'omitnan')); % Sum of SINRs across the BWP for all layers for each PMI index
% Round the total SINR value to four decimals, to avoid the
% fluctuations in the PMI output because of the minute
% variations among the SINR values corresponding to different
% PMI indices
totalSINR = round(reshape(totalSINR,indexSetSizes),4,'decimal');
% Find the set of indices that correspond to the precoding
% matrix with maximum SINR
if isType1SinglePanel
[i2,i11,i12,i13] = ind2sub(size(totalSINR),find(totalSINR == max(totalSINR,[],'all'),1));
PMISet.i1 = [i11 i12 i13];
PMISet.i2 = i2;
else
[i20,i21,i22,i11,i12,i13,i141,i142,i143] = ind2sub(size(totalSINR),find(totalSINR == max(totalSINR,[],'all'),1));
PMISet.i1 = [i11 i12 i13 i141 i142 i143];
PMISet.i2 = [i20; i21; i22];
end
end
% Consider the starting position of the first subband as 0, which
% is the start of BWP
subbandStart = 0;
SubbandSINRs = NaN([subbandInfo.NumSubbands,nLayers,indexSetSizes]);
% Initialise with maximum number of possible i1 values for PMISet
pmi = ones(1,6);
pmi(1:numel(PMISet.i1)) = PMISet.i1;
% Loop over all the subbands
for SubbandIdx = 1:subbandInfo.NumSubbands
% Extract the SINR values in the subband
sinrValuesPerSubband = SINRPerRE((subbandStart*12 + 1):(subbandStart+ subbandInfo.SubbandSizes(SubbandIdx))*12,:,:,:,:,:,:,:,:,:);
if all(isnan(sinrValuesPerSubband(:))) % CSI-RS is absent in the subband
% Report i2 as NaN for the current subband as CSI-RS is not
% present
PMISet.i2(:,SubbandIdx) = NaN;
else % CSI-RS is present in the subband
% Average the SINR per RE values across the subband for all
% the PMI indices
SubbandSINRs(SubbandIdx,:,:,:,:,:,:,:,:) = squeeze(mean(mean(sinrValuesPerSubband,'omitnan'),'omitnan'));
% Add the subband SINR values across all the layers for
% each PMI i2 index set.
if ~isType1SinglePanel
tempSubbandSINR = round(sum(SubbandSINRs(SubbandIdx,:,:,:,:,pmi(1),pmi(2),pmi(3),pmi(4),pmi(5),pmi(6)),2,'omitnan'),4,'decimal');
% Report i2 indices set [i20; i21; i22] corresponding
% to the maximum SINR for current subband
[i20,i21,i22] = ind2sub(size(squeeze(tempSubbandSINR)),find(tempSubbandSINR == max(tempSubbandSINR,[],'all'),1));
PMISet.i2(:,SubbandIdx) = [i20;i21;i22];
else
tempSubbandSINR = round(sum(SubbandSINRs(SubbandIdx,:,:,pmi(1),pmi(2),pmi(3),pmi(4),pmi(5),pmi(6)),2,'omitnan'),4,'decimal');
% Report i2 index corresponding to the maximum SINR for
% current subband
[~,PMISet.i2(SubbandIdx)] = max(tempSubbandSINR);
end
end
% Compute the starting position of next subband
subbandStart = subbandStart + subbandInfo.SubbandSizes(SubbandIdx);
end
SubbandSINRs = reshape(SubbandSINRs,[subbandInfo.NumSubbands,nLayers,indexSetSizes]);
% Form the output structure
info.SINRPerRE = SINRPerRE; % SINR value per RE for all the layers for all PMI indices
info.SINRPerSubband = SubbandSINRs; % SINR value per subband for all the layers for all PMI indices
info.W = W; % PMI codebook containing the precoding matrices corresponding to all PMI indices
end
end
function [reportConfigOut,csirsInd,nVar] = validateInputs(carrier,csirs,reportConfig,nLayers,H,nVar)
% [REPORTCONFIGOUT,CSIRSIND] = validateInputs(CARRIER,CSIRS,REPORTCONFIG,NLAYERS,H,NVAR)
% validates the inputs arguments and returns the validated CSI report
% configuration structure REPORTCONFIGOUT along with the NZP-CSI-RS
% indices CSIRSIND.
fcnName = 'hDLPMISelect';
validateattributes(carrier,{'nrCarrierConfig'},{'scalar'},fcnName,'CARRIER');
% Validate 'csirs'
validateattributes(csirs,{'nrCSIRSConfig'},{'scalar'},fcnName,'CSIRS');
if ~isscalar(unique(csirs.NumCSIRSPorts))
error('nr5g:hDLPMISelect:InvalidCSIRSPorts',...
'All the CSI-RS resources must be configured to have the same number of CSI-RS ports.');
end
if iscell(csirs.CDMType)
cdmType = csirs.CDMType;
else
cdmType = {csirs.CDMType};
end
if ~all(strcmpi(cdmType,cdmType{1}))
error('nr5g:hDLPMISelect:InvalidCSIRSCDMTypes',...
'All the CSI-RS resources must be configured to have the same CDM lengths.');
end
% Validate 'reportConfig'
% Validate 'NSizeBWP'
if ~isfield(reportConfig,'NSizeBWP')
error('nr5g:hDLPMISelect:NSizeBWPMissing','NSizeBWP field is mandatory.');
end
nSizeBWP = reportConfig.NSizeBWP;
if ~(isnumeric(nSizeBWP) && isempty(nSizeBWP))
validateattributes(nSizeBWP,{'double','single'},{'scalar','integer','positive','<=',275},fcnName,'the size of BWP');
else
nSizeBWP = carrier.NSizeGrid;
end
% Validate 'NStartBWP'
if ~isfield(reportConfig,'NStartBWP')
error('nr5g:hDLPMISelect:NStartBWPMissing','NStartBWP field is mandatory.');
end
nStartBWP = reportConfig.NStartBWP;
if ~(isnumeric(nStartBWP) && isempty(nStartBWP))
validateattributes(nStartBWP,{'double','single'},{'scalar','integer','nonnegative','<=',2473},fcnName,'the start of BWP');
else
nStartBWP = carrier.NStartGrid;
end
if nStartBWP < carrier.NStartGrid
error('nr5g:hDLPMISelect:InvalidNStartBWP',...
['The starting resource block of BWP ('...
num2str(nStartBWP) ') must be greater than '...
'or equal to the starting resource block of carrier ('...
num2str(carrier.NStartGrid) ').']);
end
% Check whether BWP is located within the limits of carrier or not
if (nSizeBWP + nStartBWP)>(carrier.NStartGrid + carrier.NSizeGrid)
error('nr5g:hDLPMISelect:InvalidBWPLimits',['The sum of starting resource '...
'block of BWP (' num2str(nStartBWP) ') and the size of BWP ('...
num2str(nSizeBWP) ') must be less than or equal to '...
'the sum of starting resource block of carrier ('...
num2str(carrier.NStartGrid) ') and size of the carrier ('...
num2str(carrier.NSizeGrid) ').']);
end
reportConfigOut.NStartBWP = nStartBWP;
reportConfigOut.NSizeBWP = nSizeBWP;
% Check for the presence of 'CodebookType' field
if isfield(reportConfig,'CodebookType')
reportConfigOut.CodebookType = validatestring(reportConfig.CodebookType,{'Type1SinglePanel','Type1MultiPanel'},fcnName,'CodebookType field');
else
reportConfigOut.CodebookType = 'Type1SinglePanel';
end
% Set isType1SinglePanel flag to true if the codebook type is
% 'Type1SinglePanel'
isType1SinglePanel = strcmpi(reportConfigOut.CodebookType,'Type1SinglePanel');
% Validate 'CodebookMode'
if isfield(reportConfig,'CodebookMode')
validateattributes(reportConfig.CodebookMode,{'numeric'},...
{'scalar','integer','positive','<=',2},fcnName,'CodebookMode field');
reportConfigOut.CodebookMode = reportConfig.CodebookMode;
else
reportConfigOut.CodebookMode = 1;
end
% Validate 'PanelDimensions'
N1 = 1;
N2 = 1;
O1 = 1;
O2 = 1;
NumCSIRSPorts = csirs.NumCSIRSPorts(1);
if isType1SinglePanel
if NumCSIRSPorts > 2
if ~isfield(reportConfig,'PanelDimensions')
error('nr5g:hDLPMISelect:PanelDimensionsMissing',...
'PanelDimensions field is mandatory.');
end
validateattributes(reportConfig.PanelDimensions,...
{'double','single'},{'vector','numel',2},fcnName,'PanelDimensions field for type 1 single panel codebooks');
N1 = reportConfig.PanelDimensions(1);
N2 = reportConfig.PanelDimensions(2);
Pcsirs = 2*prod(reportConfig.PanelDimensions);
if Pcsirs ~= NumCSIRSPorts
error('nr5g:hDLPMISelect:InvalidPanelDimensions',...
['For the configured number of CSI-RS ports (' num2str(NumCSIRSPorts)...
'), the given panel configuration [' num2str(N1) ' ' num2str(N2)...
'] is not valid. Note that, two times the product of panel dimensions ('...
num2str(Pcsirs) ') must be equal to the number of CSI-RS ports (' num2str(NumCSIRSPorts) ').']);
end
% Supported panel configurations and oversampling factors for
% type 1 single panel codebooks, as defined in
% TS 38.214 Table 5.2.2.2.1-2
panelConfigs = [2 2 4 3 6 4 8 4 6 12 4 8 16 % N1
1 2 1 2 1 2 1 3 2 1 4 2 1 % N2
4 4 4 4 4 4 4 4 4 4 4 4 4 % O1
1 4 1 4 1 4 1 4 4 1 4 4 1]; % O2
configIdx = find(panelConfigs(1,:) == N1 & panelConfigs(2,:) == N2,1);
if isempty(configIdx)
error('nr5g:hDLPMISelect:InvalidPanelConfiguration',['The given panel configuration ['...
num2str(reportConfig.PanelDimensions(1)) ' ' num2str(reportConfig.PanelDimensions(2)) '] ' ...
'is not valid for the given CSI-RS configuration. '...
'For a number of CSI-RS ports, the panel configuration should ' ...
'be one of the possibilities from TS 38.214 Table 5.2.2.2.1-2.']);
end
% Extract the oversampling factors
O1 = panelConfigs(3,configIdx);
O2 = panelConfigs(4,configIdx);
end
reportConfigOut.PanelDimensions = [N1 N2];
else
if ~any(NumCSIRSPorts == [8 16 32])
error('nr5g:hDLPMISelect:InvalidNumCSIRSPortsForMultiPanel',['For' ...
' multipanel codebook type, the number of CSI-RS ports must be 8, 16, or 32.']);
end
if ~isfield(reportConfig,'PanelDimensions')
error('nr5g:hDLPMISelect:PanelDimensionsMissing',...
'PanelDimensions field is mandatory.');
end
validateattributes(reportConfig.PanelDimensions,...
{'double','single'},{'vector','numel',3},fcnName,'PanelDimensions field for type 1 multipanel codebooks');
N1 = reportConfig.PanelDimensions(2);
N2 = reportConfig.PanelDimensions(3);
Pcsirs = 2*prod(reportConfig.PanelDimensions);
Ng = reportConfig.PanelDimensions(1);
if Pcsirs ~= NumCSIRSPorts
error('nr5g:hDLPMISelect:InvalidMultiPanelDimensions',...
['For the configured number of CSI-RS ports (' num2str(NumCSIRSPorts)...
'), the given panel configuration [' num2str(Ng) ' ' num2str(N1) ' ' num2str(N2)...
'] is not valid. Note that, two times the product of panel dimensions ('...
num2str(Pcsirs) ') must be equal to the number of CSI-RS ports (' num2str(NumCSIRSPorts) ').']);
end
% Supported panel configurations and oversampling factors for
% type 1 multipanel codebooks, as defined in
% TS 38.214 Table 5.2.2.2.2-1
panelConfigs = [2 2 2 4 2 2 4 4 % Ng
2 2 4 2 8 4 4 2 % N1
1 2 1 1 1 2 1 2 % N2
4 4 4 4 4 4 4 4 % O1
1 4 1 1 1 4 1 4 ]; % O2
configIdx = find(panelConfigs(1,:) == Ng & panelConfigs(2,:) == N1 & panelConfigs(3,:) == N2,1);
if isempty(configIdx)
error('nr5g:hDLPMISelect:InvalidMultiPanelConfiguration',['The given panel configuration ['...
num2str(Ng) ' ' num2str(N1) ' ' num2str(N2) ...
'] is not valid for the given CSI-RS configuration. '...
'For a number of CSI-RS ports, the panel configuration should ' ...
'be one of the possibilities from TS 38.214 Table 5.2.2.2.2-1.']);
end
if reportConfigOut.CodebookMode == 2 && Ng ~= 2
error('nr5g:hDLPMISelect:InvalidNumPanelsforGivenCodebookMode',['For' ...
' codebook mode 2, number of panels Ng (' num2str(Ng) ') must be 2.' ...
' Choose appropriate PanelDimensions.']);
end
% Extract the oversampling factors
O1 = panelConfigs(4,configIdx);
O2 = panelConfigs(5,configIdx);
reportConfigOut.PanelDimensions = [Ng N1 N2];
end
reportConfigOut.OverSamplingFactors = [O1 O2];
% Validate 'PMIMode'
if isfield(reportConfig,'PMIMode')
reportConfigOut.PMIMode = validatestring(reportConfig.PMIMode,{'Wideband','Subband'},fcnName,'PMIMode field');
else
reportConfigOut.PMIMode = 'Wideband';
end
% Validate 'PRGSize'
if isfield(reportConfig,'PRGSize') && isType1SinglePanel
if ~(isnumeric(reportConfig.PRGSize) && isempty(reportConfig.PRGSize))
validateattributes(reportConfig.PRGSize,{'double','single'},...
{'real','scalar'},fcnName,'PRGSize field');
end
if ~(isempty(reportConfig.PRGSize) || any(reportConfig.PRGSize == [2 4]))
error('nr5g:hDLPMISelect:InvalidPRGSize',...
['PRGSize value (' num2str(reportConfig.PRGSize) ') must be [], 2, or 4.']);
end
reportConfigOut.PRGSize = reportConfig.PRGSize;
else
reportConfigOut.PRGSize = [];
end
% Validate 'SubbandSize'
NSBPRB = [];
if strcmpi(reportConfigOut.PMIMode,'Subband') && isempty(reportConfigOut.PRGSize)
if nSizeBWP >= 24
if ~isfield(reportConfig,'SubbandSize')
error('nr5g:hDLPMISelect:SubbandSizeMissing',...
['For the subband mode, SubbandSize field is '...
'mandatory when the size of BWP is more than 24 PRBs.']);
end
validateattributes(reportConfig.SubbandSize,{'double','single'},...
{'real','scalar'},fcnName,'SubbandSize field');
NSBPRB = reportConfig.SubbandSize;
end
end
reportConfigOut.SubbandSize = NSBPRB;
if strcmpi(reportConfigOut.PMIMode,'Subband') && isempty(reportConfigOut.PRGSize)
if nSizeBWP >= 24
% Validate the subband size, based on the size of BWP
% BWP size ranges
nSizeBWPRange = [24 72;
73 144;
145 275];
% Possible values of subband size
nSBPRBValues = [4 8;
8 16;
16 32];
bwpRangeCheck = (nSizeBWP >= nSizeBWPRange(:,1)) & (nSizeBWP <= nSizeBWPRange(:,2));
validNSBPRBValues = nSBPRBValues(bwpRangeCheck,:);
if ~any(NSBPRB == validNSBPRBValues)
error('nr5g:hDLPMISelect:InvalidSubbandSize',['For the configured BWP size (' num2str(nSizeBWP) ...
'), subband size (' num2str(NSBPRB) ') must be ' num2str(validNSBPRBValues(1)) ...
' or ' num2str(validNSBPRBValues(2)) '.']);
end
end
end
% Validate 'CodebookSubsetRestriction'
if NumCSIRSPorts > 2
codebookLength = N1*O1*N2*O2;
codebookSubsetRestriction = ones(1,codebookLength);
if isfield(reportConfig,'CodebookSubsetRestriction') &&...
~isempty(reportConfig.CodebookSubsetRestriction)
codebookSubsetRestriction = reportConfig.CodebookSubsetRestriction;
validateattributes(codebookSubsetRestriction,...
{'numeric'},{'vector','binary','numel',codebookLength},fcnName,'CodebookSubsetRestriction field');
end
elseif NumCSIRSPorts == 2
codebookSubsetRestriction = ones(1,6);
if isfield(reportConfig,'CodebookSubsetRestriction') &&...
~isempty(reportConfig.CodebookSubsetRestriction)
codebookSubsetRestriction = reportConfig.CodebookSubsetRestriction;
validateattributes(codebookSubsetRestriction,{'numeric'},{'vector','binary','numel',6},fcnName,'CodebookSubsetRestriction field');
end
else
codebookSubsetRestriction = 1;
end
reportConfigOut.CodebookSubsetRestriction = codebookSubsetRestriction;
% Validate 'i2Restriction'
i2Restriction = ones(1,16);
if NumCSIRSPorts > 2 && isType1SinglePanel
if isfield(reportConfig,'i2Restriction') && ~isempty(reportConfig.i2Restriction)
validateattributes(reportConfig.i2Restriction,...
{'numeric'},{'vector','binary','numel',16},fcnName,'i2Restriction field');
i2Restriction = reportConfig.i2Restriction;
end
end
reportConfigOut.i2Restriction = i2Restriction;
% Validate 'nLayers'
if isType1SinglePanel
validateattributes(nLayers,{'numeric'},{'scalar','integer','positive','<=',8},fcnName,['NLAYERS(' num2str(nLayers) ') when codebook type is "Type1SinglePanel"']);
else
validateattributes(nLayers,{'numeric'},{'scalar','integer','positive','<=',4},fcnName,['NLAYERS(' num2str(nLayers) ') when codebook type is "Type1MultiPanel"']);
end
% Validate 'H'
validateattributes(H,{'double','single'},{},fcnName,'H');
validateattributes(numel(size(H)),{'double'},{'>=',2,'<=',4},fcnName,'number of dimensions of H');
% Ignore zero-power (ZP) CSI-RS resources, as they are not used for CSI
% estimation
if ~iscell(csirs.CSIRSType)
csirs.CSIRSType = {csirs.CSIRSType};
end
numZPCSIRSRes = sum(strcmpi(csirs.CSIRSType,'zp'));
tempInd = nrCSIRSIndices(carrier,csirs,"IndexStyle","subscript","OutputResourceFormat","cell");
tempInd = tempInd(numZPCSIRSRes+1:end)'; % NZP-CSI-RS indices
% Extract the NZP-CSI-RS indices corresponding to first port
for nzpResIdx = 1:numel(tempInd)
nzpInd = tempInd{nzpResIdx};
tempInd{nzpResIdx} = nzpInd(nzpInd(:,3) == 1,:);
end
% Extract the indices corresponding to the lowest RE of each CSI-RS CDM
% group
if ~strcmpi(cdmType{1},'noCDM')
for resIdx = 1:numel(tempInd)
totIndices = size(tempInd{resIdx},1);
if strcmpi(cdmType{1},'FD-CDM2')
indicesPerSym = totIndices;
elseif strcmpi(cdmType{1},'CDM4')
indicesPerSym = totIndices/2;
elseif strcmpi(cdmType{1},'CDM8')
indicesPerSym = totIndices/4;
end
tempIndInOneSymbol = tempInd{resIdx}(1:indicesPerSym,:);
tempInd{resIdx} = tempIndInOneSymbol(1:2:end,:);
end
end
csirsInd = zeros(0,3);
if ~isempty(tempInd)
csirsInd = cell2mat(tempInd);
end
if ~isempty(csirsInd)
K = carrier.NSizeGrid*12;
L = carrier.SymbolsPerSlot;
validateattributes(H,{class(H)},{'size',[K L NaN NumCSIRSPorts]},fcnName,'H');
% Validate 'nLayers'
nRxAnts = size(H,3);
maxNLayers = min(nRxAnts,NumCSIRSPorts);
if nLayers > maxNLayers
error('nr5g:hDLPMISelect:InvalidNumLayers',...
['The given antenna configuration (' ...
num2str(NumCSIRSPorts) 'x' num2str(nRxAnts)...
') supports only up to (' num2str(maxNLayers) ') layers.']);
end
end
% Validate 'nVar'
validateattributes(nVar,{'double','single'},{'scalar','real','nonnegative','finite'},fcnName,'NVAR');
% Clip nVar to a small noise variance to avoid +/-Inf outputs
if nVar < 1e-10
nVar = 1e-10;
end
end
function W = getPMIType1SinglePanelCodebook(reportConfig,nLayers)
% W = getPMIType1SinglePanelCodebook(REPORTCONFIG,NLAYERS) returns type 1
% single panel precoding matrices W, as defined in TS 38.214 Tables
% 5.2.2.2.1-1 to 5.2.2.2.1-12 by considering these inputs:
%
% REPORTCONFIG is a CSI reporting configuration structure with these
% fields:
% PanelDimensions - Antenna panel configuration as a
% two-element vector ([N1 N2]). It is
% not applicable for CSI-RS ports less
% than or equal to 2
% OverSamplingFactors - DFT oversampling factors corresponding to
% the panel configuration
% CodebookMode - Codebook mode. Applicable only when the
% number of MIMO layers is 1 or 2 and
% number of CSI-RS ports is greater than 2
% CodebookSubsetRestriction - Binary vector for vlm or vbarlm restriction
% i2Restriction - Binary vector for i2 restriction
%
% NLAYERS - Number of transmission layers
%
% W - Multidimensional array containing unrestricted type 1
% single panel precoding matrices. It is of size
% Pcsirs-by-nLayers-by-i2Length-by-i11Length-by-i12Length-by-i13Length
%
% Note that the restricted precoding matrices are returned as all zeros.
panelDimensions = reportConfig.PanelDimensions;
codebookMode = reportConfig.CodebookMode;
codebookSubsetRestriction = reportConfig.CodebookSubsetRestriction;
i2Restriction = reportConfig.i2Restriction;
% Create a function handle to compute the co-phasing factor value
% according to TS 38.214 Section 5.2.2.2.1, considering the co-phasing
% factor index
phi = @(x)exp(1i*pi*x/2);
% Get the number of CSI-RS ports using the panel dimensions
Pcsirs = 2*panelDimensions(1)*panelDimensions(2);
if Pcsirs == 2
% Codebooks for 1-layer and 2-layer CSI reporting using antenna
% ports 3000 to 3001, as defined in TS 38.214 Table 5.2.2.2.1-1
if nLayers == 1
W(:,:,1) = 1/sqrt(2).*[1; 1];
W(:,:,2) = 1/sqrt(2).*[1; 1i];
W(:,:,3) = 1/sqrt(2).*[1; -1];
W(:,:,4) = 1/sqrt(2).*[1; -1i];
restrictedIndices = find(~codebookSubsetRestriction);
restrictedIndices = restrictedIndices(restrictedIndices <= 4);
if ~isempty(restrictedIndices)
restrictedSet = logical(sum(restrictedIndices == [1;2;3;4],2));
W(:,:,restrictedSet) = 0;
end
elseif nLayers == 2
W(:,:,1) = 1/2*[1 1;1 -1];
W(:,:,2) = 1/2*[1 1; 1i -1i];
restrictedIndices = find(~codebookSubsetRestriction);
restrictedIndices = restrictedIndices(restrictedIndices > 4);
if ~isempty(restrictedIndices)
restrictedSet = logical(sum(restrictedIndices == [5;6],2));
W(:,:,restrictedSet) = 0;