Files
openairinterface5g/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
T

5361 lines
259 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file nr_mac_common.c
* \brief Common MAC/PHY functions for NR UE and gNB
* \author Florian Kaltenberger and Raymond Knopp
* \date 2019
* \version 0.1
* \company Eurecom, NTUST
* \email: florian.kalteberger@eurecom.fr, raymond.knopp@eurecom.fr
* @ingroup _mac
*/
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "common/utils/nr/nr_common.h"
#include <limits.h>
#include <executables/softmodem-common.h>
#define reserved 0xffff
//38.321 Table 6.1.3.1-1
const uint32_t NR_SHORT_BSR_TABLE[NR_SHORT_BSR_TABLE_SIZE] = {
0, 10, 14, 20, 28, 38, 53, 74,
102, 142, 198, 276, 384, 535, 745, 1038,
1446, 2014, 2806, 3909, 5446, 7587, 10570, 14726,
20516, 28581, 39818, 55474, 77284, 107669, 150000, 300000
};
//38.321 Table 6.1.3.1-2
const uint32_t NR_LONG_BSR_TABLE[NR_LONG_BSR_TABLE_SIZE] ={
0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26,
28, 30, 32, 34, 36, 38, 40, 43, 46, 49, 52, 55, 59, 62, 66, 71,
75, 80, 85, 91, 97, 103, 110, 117, 124, 132, 141, 150, 160, 170, 181, 193,
205, 218, 233, 248, 264, 281, 299, 318, 339, 361, 384, 409, 436, 464, 494, 526,
560, 597, 635, 677, 720, 767, 817, 870, 926, 987, 1051, 1119, 1191, 1269, 1351, 1439,
1532, 1631, 1737, 1850, 1970, 2098, 2234, 2379, 2533, 2698, 2873, 3059, 3258, 3469, 3694, 3934,
4189, 4461, 4751, 5059, 5387, 5737, 6109, 6506, 6928, 7378, 7857, 8367, 8910, 9488, 10104, 10760,
11458, 12202, 12994, 13838, 14736, 15692, 16711, 17795, 18951, 20181, 21491, 22885, 24371, 25953, 27638, 29431,
31342, 33376, 35543, 37850, 40307, 42923, 45709, 48676, 51836, 55200, 58784, 62599, 66663, 70990, 75598, 80505,
85730, 91295, 97221, 103532, 110252, 117409, 125030, 133146, 141789, 150992, 160793, 171231, 182345, 194182, 206786, 220209,
234503, 249725, 265935, 283197, 301579, 321155, 342002, 364202, 387842, 413018, 439827, 468377, 498780, 531156, 565634, 602350,
641449, 683087, 727427, 774645, 824928, 878475, 935498, 996222, 1060888, 1129752, 1203085, 1281179, 1364342, 1452903, 1547213, 1647644,
1754595, 1868488, 1989774, 2118933, 2256475, 2402946, 2558924, 2725027, 2901912, 3090279, 3290873, 3504487, 3731968, 3974215, 4232186, 4506902,
4799451, 5110989, 5442750, 5796046, 6172275, 6572925, 6999582, 7453933, 7937777, 8453028, 9001725, 9586039, 10208280, 10870913, 11576557, 12328006,
13128233, 13980403, 14887889, 15854280, 16883401, 17979324, 19146385, 20389201, 21712690, 23122088, 24622972, 26221280, 27923336, 29735875, 31666069, 33721553,
35910462, 38241455, 40723756, 43367187, 46182206, 49179951, 52372284, 55771835, 59392055, 63247269, 67352729, 71724679, 76380419, 81338368, 162676736, 4294967295
};
// start symbols for SSB types A,B,C,D,E
static const uint16_t symbol_ssb_AC[8] = {2, 8, 16, 22, 30, 36, 44, 50};
static const uint16_t symbol_ssb_BD[64] = {4, 8, 16, 20, 32, 36, 44, 48, 60, 64, 72, 76, 88, 92, 100, 104,
144, 148, 156, 160, 172, 176, 184, 188, 200, 204, 212, 216, 228, 232, 240, 244,
284, 288, 296, 300, 312, 316, 324, 328, 340, 344, 352, 356, 368, 372, 380, 384,
424, 428, 436, 440, 452, 456, 464, 468, 480, 484, 492, 496, 508, 512, 520, 524};
static const uint16_t symbol_ssb_E[64] = {8, 12, 16, 20, 32, 36, 40, 44, 64, 68, 72, 76, 88, 92, 96, 100,
120, 124, 128, 132, 144, 148, 152, 156, 176, 180, 184, 188, 200, 204, 208, 212,
288, 292, 296, 300, 312, 316, 320, 324, 344, 348, 352, 356, 368, 372, 376, 380,
400, 404, 408, 412, 424, 428, 432, 436, 456, 460, 464, 468, 480, 484, 488, 492};
const uint8_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160};
// Table 6.3.3.1-5 (38.211) NCS for preamble formats with delta_f_RA = 1.25 KHz
static const uint16_t NCS_unrestricted_delta_f_RA_125[16] = {0, 13, 15, 18, 22, 26, 32, 38, 46, 59, 76, 93, 119, 167, 279, 419};
static const uint16_t NCS_restricted_TypeA_delta_f_RA_125[15] =
{15, 18, 22, 26, 32, 38, 46, 55, 68, 82, 100, 128, 158, 202, 237}; // high-speed case set Type A
static const uint16_t NCS_restricted_TypeB_delta_f_RA_125[13] =
{15, 18, 22, 26, 32, 38, 46, 55, 68, 82, 100, 118, 137}; // high-speed case set Type B
// Table 6.3.3.1-6 (38.211) NCS for preamble formats with delta_f_RA = 5 KHz
static const uint16_t NCS_unrestricted_delta_f_RA_5[16] = {0, 13, 26, 33, 38, 41, 49, 55, 64, 76, 93, 119, 139, 209, 279, 419};
static const uint16_t NCS_restricted_TypeA_delta_f_RA_5[16] =
{36, 57, 72, 81, 89, 94, 103, 112, 121, 132, 137, 152, 173, 195, 216, 237}; // high-speed case set Type A
static const uint16_t NCS_restricted_TypeB_delta_f_RA_5[14] =
{36, 57, 60, 63, 65, 68, 71, 77, 81, 85, 97, 109, 122, 137}; // high-speed case set Type B
// Table 6.3.3.1-7 (38.211) NCS for preamble formats with delta_f_RA = 15 * 2mu KHz where mu = {0,1,2,3}
static const uint16_t NCS_unrestricted_delta_f_RA_15[16] = {0, 2, 4, 6, 8, 10, 12, 13, 15, 17, 19, 23, 27, 34, 46, 69};
// specification mapping talbe, table_38$x_$y_$z_c$a
// - $x: specification
// - $y: subclause-major
// - $z: subclause-minor
// - $a: ($a)th of column in table, start from zero
const int32_t table_38213_13_1_c1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, reserved}; // index 15 reserved
const int32_t table_38213_13_1_c2[16] = {24, 24, 24, 24, 24, 24, 48, 48, 48, 48, 48, 48, 96, 96, 96, reserved}; // index 15 reserved
const int32_t table_38213_13_1_c3[16] = { 2, 2, 2, 3, 3, 3, 1, 1, 2, 2, 3, 3, 1, 2, 3, reserved}; // index 15 reserved
const int32_t table_38213_13_1_c4[16] = { 0, 2, 4, 0, 2, 4, 12, 16, 12, 16, 12, 16, 38, 38, 38, reserved}; // index 15 reserved
const int32_t table_38213_13_2_c1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, reserved, reserved}; // index 14-15 reserved
const int32_t table_38213_13_2_c2[16] = {24, 24, 24, 24, 24, 24, 24, 24, 48, 48, 48, 48, 48, 48, reserved, reserved}; // index 14-15 reserved
const int32_t table_38213_13_2_c3[16] = { 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 2, 2, 3, 3, reserved, reserved}; // index 14-15 reserved
const int32_t table_38213_13_2_c4[16] = { 5, 6, 7, 8, 5, 6, 7, 8, 18, 20, 18, 20, 18, 20, reserved, reserved}; // index 14-15 reserved
const int32_t table_38213_13_3_c1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved
const int32_t table_38213_13_3_c2[16] = {48, 48, 48, 48, 48, 48, 96, 96, 96, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved
const int32_t table_38213_13_3_c3[16] = { 1, 1, 2, 2, 3, 3, 1, 2, 3, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved
const int32_t table_38213_13_3_c4[16] = { 2, 6, 2, 6, 2, 6, 28, 28, 28, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved
const int32_t table_38213_13_4_c1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
const int32_t table_38213_13_4_c2[16] = {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 48, 48, 48, 48, 48, 48};
const int32_t table_38213_13_4_c3[16] = { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 1, 1, 1, 2, 2, 2};
const int32_t table_38213_13_4_c4[16] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 12, 14, 16, 12, 14, 16};
const int32_t table_38213_13_5_c1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved
const int32_t table_38213_13_5_c2[16] = {48, 48, 48, 96, 96, 96, 96, 96, 96, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved
const int32_t table_38213_13_5_c3[16] = { 1, 2, 3, 1, 1, 2, 2, 3, 3, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved
const int32_t table_38213_13_5_c4[16] = { 4, 4, 4, 0, 56, 0, 56, 0, 56, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved
const int32_t table_38213_13_6_c1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, reserved, reserved, reserved, reserved, reserved, reserved}; // index 10-15 reserved
const int32_t table_38213_13_6_c2[16] = {24, 24, 24, 24, 48, 48, 48, 48, 48, 48, reserved, reserved, reserved, reserved, reserved, reserved}; // index 10-15 reserved
const int32_t table_38213_13_6_c3[16] = { 2, 2, 3, 3, 1, 1, 2, 2, 3, 3, reserved, reserved, reserved, reserved, reserved, reserved}; // index 10-15 reserved
const int32_t table_38213_13_6_c4[16] = { 0, 4, 0, 4, 0, 28, 0, 28, 0, 28, reserved, reserved, reserved, reserved, reserved, reserved}; // index 10-15 reserved
const int32_t table_38213_13_7_c1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, reserved, reserved, reserved, reserved}; // index 12-15 reserved
const int32_t table_38213_13_7_c2[16] = {48, 48, 48, 48, 48, 48, 96, 96, 48, 48, 96, 96, reserved, reserved, reserved, reserved}; // index 12-15 reserved
const int32_t table_38213_13_7_c3[16] = { 1, 1, 2, 2, 3, 3, 1, 2, 1, 1, 1, 1, reserved, reserved, reserved, reserved}; // index 12-15 reserved
const int32_t table_38213_13_7_c4[16] = { 0, 8, 0, 8, 0, 8, 28, 28,-41, 49,-41, 97, reserved, reserved, reserved, reserved}; // index 12-15 reserved, condition A as default
const int32_t table_38213_13_8_c1[16] = { 1, 1, 1, 1, 3, 3, 3, 3, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 15 reserved
const int32_t table_38213_13_8_c2[16] = {24, 24, 48, 48, 24, 24, 48, 48, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 15 reserved
const int32_t table_38213_13_8_c3[16] = { 2, 2, 1, 2, 2, 2, 2, 2, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 15 reserved
const int32_t table_38213_13_8_c4[16] = { 0, 4, 14, 14,-20, 24,-20, 48, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 15 reserved, condition A as default
const int32_t table_38213_13_9_c1[16] = {1, 1, 1, 1, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 04-15 reserved
const int32_t table_38213_13_9_c2[16] = {96, 96, 96, 96, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 04-15 reserved
const int32_t table_38213_13_9_c3[16] = { 1, 1, 2, 2, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 04-15 reserved
const int32_t table_38213_13_9_c4[16] = { 0, 16, 0, 16, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 04-15 reserved
const int32_t table_38213_13_10_c1[16] = {1, 1, 1, 1, 2, 2, 2, 2, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 08-15 reserved
const int32_t table_38213_13_10_c2[16] = {48, 48, 48, 48, 24, 24, 48, 48, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 08-15 reserved
const int32_t table_38213_13_10_c3[16] = { 1, 1, 2, 2, 1, 1, 1, 1, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 08-15 reserved
const int32_t table_38213_13_10_c4[16] = { 0, 8, 0, 8,-41, 25,-41, 49, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 08-15 reserved, condition A as default
const float table_38213_13_11_c1[16] = { 0, 0, 2, 2, 5, 5, 7, 7, 0, 5, 0, 0, 2, 2, 5, 5}; // O
const int32_t table_38213_13_11_c2[16] = { 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1};
const float table_38213_13_11_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 1, 0.5f, 2, 2, 1, 1, 1, 1, 1, 1}; // M
const int32_t table_38213_13_11_c4[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2}; // i is even as default
const float table_38213_13_12_c1[16] = { 0, 0, 2.5f, 2.5f, 5, 5, 0, 2.5f, 5, 7.5f, 7.5f, 7.5f, 0, 5, reserved, reserved}; // O, index 14-15 reserved
const int32_t table_38213_13_12_c2[16] = { 1, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, reserved, reserved}; // index 14-15 reserved
const float table_38213_13_12_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 0.5f, 0.5f, 0.5f, 1, 0.5f, 0.5f, 2, 2, reserved, reserved}; // M, index 14-15 reserved
const int32_t table_38213_10_1_1_c2[5] = { 0, 0, 4, 2, 1 };
// for PDSCH from TS 38.214 subclause 5.1.2.1.1
const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[16][4]={
{1,0,2,12}, // row index 1
{1,0,2,10}, // row index 2
{1,0,2,9}, // row index 3
{1,0,2,7}, // row index 4
{1,0,2,5}, // row index 5
{0,0,9,4}, // row index 6
{0,0,4,4}, // row index 7
{0,0,5,7}, // row index 8
{0,0,5,2}, // row index 9
{0,0,9,2}, // row index 10
{0,0,12,2}, // row index 11
{1,0,1,13}, // row index 12
{1,0,1,6}, // row index 13
{1,0,2,4}, // row index 14
{0,0,4,7}, // row index 15
{0,0,8,4} // row index 16
};
const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[16][4]={
{1,0,3,11}, // row index 1
{1,0,3,9}, // row index 2
{1,0,3,8}, // row index 3
{1,0,3,6}, // row index 4
{1,0,3,4}, // row index 5
{0,0,10,4}, // row index 6
{0,0,6,4}, // row index 7
{0,0,5,7}, // row index 8
{0,0,5,2}, // row index 9
{0,0,9,2}, // row index 10
{0,0,12,2}, // row index 11
{1,0,1,13}, // row index 12
{1,0,1,6}, // row index 13
{1,0,2,4}, // row index 14
{0,0,4,7}, // row index 15
{0,0,8,4} // row index 16
};
const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[16][4]={
{1,0,2,6}, // row index 1
{1,0,2,10}, // row index 2
{1,0,2,9}, // row index 3
{1,0,2,7}, // row index 4
{1,0,2,5}, // row index 5
{0,0,6,4}, // row index 6
{0,0,4,4}, // row index 7
{0,0,5,6}, // row index 8
{0,0,5,2}, // row index 9
{0,0,9,2}, // row index 10
{0,0,10,2}, // row index 11
{1,0,1,11}, // row index 12
{1,0,1,6}, // row index 13
{1,0,2,4}, // row index 14
{0,0,4,6}, // row index 15
{0,0,8,4} // row index 16
};
const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[16][4]={
{1,0,3,5}, // row index 1
{1,0,3,9}, // row index 2
{1,0,3,8}, // row index 3
{1,0,3,6}, // row index 4
{1,0,3,4}, // row index 5
{0,0,8,2}, // row index 6
{0,0,6,4}, // row index 7
{0,0,5,6}, // row index 8
{0,0,5,2}, // row index 9
{0,0,9,2}, // row index 10
{0,0,10,2}, // row index 11
{1,0,1,11}, // row index 12
{1,0,1,6}, // row index 13
{1,0,2,4}, // row index 14
{0,0,4,6}, // row index 15
{0,0,8,4} // row index 16
};
const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[16][4]={
{0,0,2,2}, // row index 1
{0,0,4,2}, // row index 2
{0,0,6,2}, // row index 3
{0,0,8,2}, // row index 4
{0,0,10,2}, // row index 5
{0,1,2,2}, // row index 6
{0,1,4,2}, // row index 7
{0,0,2,4}, // row index 8
{0,0,4,4}, // row index 9
{0,0,6,4}, // row index 10
{0,0,8,4}, // row index 11
{0,0,10,4}, // row index 12
{0,0,2,7}, // row index 13
{1,0,2,12}, // row index 14
{0,1,2,4}, // row index 15
{0,0,0,0} // row index 16
};
const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[16][4]={
{0,0,2,2}, // row index 1
{0,0,4,2}, // row index 2
{0,0,6,2}, // row index 3
{0,0,8,2}, // row index 4
{0,0,10,2}, // row index 5
{0,1,2,2}, // row index 6
{0,1,4,2}, // row index 7
{0,0,2,4}, // row index 8
{0,0,4,4}, // row index 9
{0,0,6,4}, // row index 10
{0,0,8,4}, // row index 11
{0,0,10,4}, // row index 12
{0,0,2,7}, // row index 13
{1,0,3,11}, // row index 14
{0,1,2,4}, // row index 15
{0,0,0,0} // row index 16
};
const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[16][4]={
{0,0,2,2}, // row index 1
{0,0,4,2}, // row index 2
{0,0,6,2}, // row index 3
{0,0,8,2}, // row index 4
{0,0,10,2}, // row index 5
{0,0,0,0}, // row index 6
{0,0,0,0}, // row index 7
{0,0,2,4}, // row index 8
{0,0,4,4}, // row index 9
{0,0,6,4}, // row index 10
{0,0,8,4}, // row index 11
{0,0,10,4}, // row index 12
{0,0,2,7}, // row index 13
{1,0,2,12}, // row index 14
{1,0,0,6}, // row index 15
{1,0,2,6} // row index 16
};
const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[16][4]={
{0,0,2,2}, // row index 1
{0,0,4,2}, // row index 2
{0,0,6,2}, // row index 3
{0,0,8,2}, // row index 4
{0,0,10,2}, // row index 5
{0,0,0,0}, // row index 6
{0,0,0,0}, // row index 7
{0,0,2,4}, // row index 8
{0,0,4,4}, // row index 9
{0,0,6,4}, // row index 10
{0,0,8,4}, // row index 11
{0,0,10,4}, // row index 12
{0,0,2,7}, // row index 13
{1,0,3,11}, // row index 14
{1,0,0,6}, // row index 15
{1,0,2,6} // row index 16
};
// TS 38.211 - Table 6.3.1.5-1: Precoding matrix W for single-layer transmission using two antenna ports, 'n' = -1 and 'o' = -j
const char table_38211_6_3_1_5_1[6][2][1] = {
{{'1'}, {'0'}}, // tpmi 0
{{'0'}, {'1'}}, // tpmi 1
{{'1'}, {'1'}}, // tpmi 2
{{'1'}, {'n'}}, // tpmi 3
{{'1'}, {'j'}}, // tpmi 4
{{'1'}, {'o'}} // tpmi 5
};
// TS 38.211 - Table 6.3.1.5-2: Precoding matrix W for single-layer transmission using four antenna ports with transform precoding enabled, 'n' = -1 and 'o' = -j
const char table_38211_6_3_1_5_2[28][4][1] = {
{{'1'}, {'0'}, {'0'}, {'0'}}, // tpmi 0
{{'0'}, {'1'}, {'0'}, {'0'}}, // tpmi 1
{{'0'}, {'0'}, {'1'}, {'0'}}, // tpmi 2
{{'0'}, {'0'}, {'0'}, {'1'}}, // tpmi 3
{{'1'}, {'0'}, {'1'}, {'0'}}, // tpmi 4
{{'1'}, {'0'}, {'n'}, {'0'}}, // tpmi 5
{{'1'}, {'0'}, {'j'}, {'0'}}, // tpmi 6
{{'1'}, {'0'}, {'o'}, {'0'}}, // tpmi 7
{{'0'}, {'1'}, {'0'}, {'1'}}, // tpmi 8
{{'0'}, {'1'}, {'0'}, {'n'}}, // tpmi 9
{{'0'}, {'1'}, {'0'}, {'j'}}, // tpmi 10
{{'0'}, {'1'}, {'0'}, {'o'}}, // tpmi 11
{{'1'}, {'1'}, {'1'}, {'n'}}, // tpmi 12
{{'1'}, {'1'}, {'j'}, {'j'}}, // tpmi 13
{{'1'}, {'1'}, {'n'}, {'1'}}, // tpmi 14
{{'1'}, {'1'}, {'o'}, {'o'}}, // tpmi 15
{{'1'}, {'j'}, {'1'}, {'j'}}, // tpmi 16
{{'1'}, {'j'}, {'j'}, {'1'}}, // tpmi 17
{{'1'}, {'j'}, {'n'}, {'o'}}, // tpmi 18
{{'1'}, {'j'}, {'o'}, {'n'}}, // tpmi 19
{{'1'}, {'n'}, {'1'}, {'1'}}, // tpmi 20
{{'1'}, {'n'}, {'j'}, {'o'}}, // tpmi 21
{{'1'}, {'n'}, {'n'}, {'n'}}, // tpmi 22
{{'1'}, {'n'}, {'o'}, {'j'}}, // tpmi 23
{{'1'}, {'o'}, {'1'}, {'o'}}, // tpmi 24
{{'1'}, {'o'}, {'j'}, {'n'}}, // tpmi 25
{{'1'}, {'o'}, {'n'}, {'j'}}, // tpmi 26
{{'1'}, {'o'}, {'o'}, {'1'}} // tpmi 27
};
// TS 38.211 - Table 6.3.1.5-3: Precoding matrix W for single-layer transmission using four antenna ports with transform precoding disabled, 'n' = -1 and 'o' = -j
const char table_38211_6_3_1_5_3[28][4][1] = {
{{'1'}, {'0'}, {'0'}, {'0'}}, // tpmi 0
{{'0'}, {'1'}, {'0'}, {'0'}}, // tpmi 1
{{'0'}, {'0'}, {'1'}, {'0'}}, // tpmi 2
{{'0'}, {'0'}, {'0'}, {'1'}}, // tpmi 3
{{'1'}, {'0'}, {'1'}, {'0'}}, // tpmi 4
{{'1'}, {'0'}, {'n'}, {'0'}}, // tpmi 5
{{'1'}, {'0'}, {'j'}, {'0'}}, // tpmi 6
{{'1'}, {'0'}, {'o'}, {'0'}}, // tpmi 7
{{'0'}, {'1'}, {'0'}, {'1'}}, // tpmi 8
{{'0'}, {'1'}, {'0'}, {'n'}}, // tpmi 9
{{'0'}, {'1'}, {'0'}, {'j'}}, // tpmi 10
{{'0'}, {'1'}, {'0'}, {'o'}}, // tpmi 11
{{'1'}, {'1'}, {'1'}, {'1'}}, // tpmi 12
{{'1'}, {'1'}, {'j'}, {'j'}}, // tpmi 13
{{'1'}, {'1'}, {'n'}, {'n'}}, // tpmi 14
{{'1'}, {'1'}, {'o'}, {'o'}}, // tpmi 15
{{'1'}, {'j'}, {'1'}, {'j'}}, // tpmi 16
{{'1'}, {'j'}, {'j'}, {'n'}}, // tpmi 17
{{'1'}, {'j'}, {'n'}, {'o'}}, // tpmi 18
{{'1'}, {'j'}, {'o'}, {'1'}}, // tpmi 19
{{'1'}, {'n'}, {'1'}, {'n'}}, // tpmi 20
{{'1'}, {'n'}, {'j'}, {'o'}}, // tpmi 21
{{'1'}, {'n'}, {'n'}, {'1'}}, // tpmi 22
{{'1'}, {'n'}, {'o'}, {'j'}}, // tpmi 23
{{'1'}, {'o'}, {'1'}, {'o'}}, // tpmi 24
{{'1'}, {'o'}, {'j'}, {'1'}}, // tpmi 25
{{'1'}, {'o'}, {'n'}, {'j'}}, // tpmi 26
{{'1'}, {'o'}, {'o'}, {'n'}} // tpmi 27
};
// TS 38.211 - Table 6.3.1.5-4: Precoding matrix W for two-layer transmission using two antenna ports, 'n' = -1 and 'o' = -j
const char table_38211_6_3_1_5_4[3][2][2] = {
{{'1', '0'}, {'0', '1'}}, // tpmi 0
{{'1', '1'}, {'1', 'n'}}, // tpmi 1
{{'1', '1'}, {'j', 'o'}} // tpmi 2
};
// TS 38.211 - Table 6.3.1.5-5: Precoding matrix W for two-layer transmission using four antenna ports, 'n' = -1 and 'o' = -j
const char table_38211_6_3_1_5_5[22][4][2] = {
{{'1', '0'}, {'0', '1'}, {'0', '0'}, {'0', '0'}}, // tpmi 0
{{'1', '0'}, {'0', '0'}, {'0', '1'}, {'0', '0'}}, // tpmi 1
{{'1', '0'}, {'0', '0'}, {'0', '0'}, {'0', '1'}}, // tpmi 2
{{'0', '0'}, {'1', '0'}, {'0', '1'}, {'0', '0'}}, // tpmi 3
{{'0', '0'}, {'1', '0'}, {'0', '0'}, {'0', '1'}}, // tpmi 4
{{'0', '0'}, {'0', '0'}, {'1', '0'}, {'0', '1'}}, // tpmi 5
{{'1', '0'}, {'0', '1'}, {'1', '0'}, {'0', 'o'}}, // tpmi 6
{{'1', '0'}, {'0', '1'}, {'1', '0'}, {'0', 'j'}}, // tpmi 7
{{'1', '0'}, {'0', '1'}, {'o', '0'}, {'0', '1'}}, // tpmi 8
{{'1', '0'}, {'0', '1'}, {'o', '0'}, {'0', 'n'}}, // tpmi 9
{{'1', '0'}, {'0', '1'}, {'n', '0'}, {'0', 'o'}}, // tpmi 10
{{'1', '0'}, {'0', '1'}, {'n', '0'}, {'0', 'j'}}, // tpmi 11
{{'1', '0'}, {'0', '1'}, {'j', '0'}, {'0', '1'}}, // tpmi 12
{{'1', '0'}, {'0', '1'}, {'j', '0'}, {'0', 'n'}}, // tpmi 13
{{'1', '1'}, {'1', '1'}, {'1', 'n'}, {'1', 'n'}}, // tpmi 14
{{'1', '1'}, {'1', '1'}, {'j', 'o'}, {'j', 'o'}}, // tpmi 15
{{'1', '1'}, {'j', 'j'}, {'1', 'n'}, {'j', 'o'}}, // tpmi 16
{{'1', '1'}, {'j', 'j'}, {'j', 'o'}, {'n', '1'}}, // tpmi 17
{{'1', '1'}, {'n', 'n'}, {'1', 'n'}, {'n', '1'}}, // tpmi 18
{{'1', '1'}, {'n', 'n'}, {'j', 'o'}, {'o', 'j'}}, // tpmi 19
{{'1', '1'}, {'o', 'o'}, {'1', 'n'}, {'o', 'j'}}, // tpmi 20
{{'1', '1'}, {'o', 'o'}, {'j', 'o'}, {'1', 'n'}} // tpmi 21
};
// Default PUSCH time domain resource allocation tables from 38.214
const uint8_t table_6_1_2_1_1_2[16][4] = {
{0, 0, 0, 14}, // row index 1
{0, 0, 0, 12}, // row index 2
{0, 0, 0, 10}, // row index 3
{1, 0, 2, 10}, // row index 4
{1, 0, 4, 10}, // row index 5
{1, 0, 4, 8}, // row index 6
{1, 0, 4, 6}, // row index 7
{0, 1, 0, 14}, // row index 8
{0, 1, 0, 12}, // row index 9
{0, 1, 0, 10}, // row index 10
{0, 2, 0, 14}, // row index 11
{0, 2, 0, 12}, // row index 12
{0, 2, 0, 10}, // row index 13
{1, 0, 8, 6}, // row index 14
{0, 3, 0, 14}, // row index 15
{0, 3, 0, 10} // row index 16
};
const uint8_t table_6_1_2_1_1_3[16][4] = {
{0, 0, 0, 8}, // row index 1
{0, 0, 0, 12}, // row index 2
{0, 0, 0, 10}, // row index 3
{1, 0, 2, 10}, // row index 4
{1, 0, 4, 4}, // row index 5
{1, 0, 4, 8}, // row index 6
{1, 0, 4, 6}, // row index 7
{0, 1, 0, 8}, // row index 8
{0, 1, 0, 12}, // row index 9
{0, 1, 0, 10}, // row index 10
{0, 2, 0, 6}, // row index 11
{0, 2, 0, 12}, // row index 12
{0, 2, 0, 10}, // row index 13
{1, 0, 8, 4}, // row index 14
{0, 3, 0, 8}, // row index 15
{0, 3, 0, 10} // row index 16
};
NR_tda_info_t get_ul_tda_info(const NR_UE_UL_BWP_t *ul_bwp,
int controlResourceSetId,
int ss_type,
nr_rnti_type_t rnti_type,
int tda_index)
{
NR_tda_info_t tda_info = {0};
NR_PUSCH_TimeDomainResourceAllocationList_t *tdalist = get_ul_tdalist(ul_bwp, controlResourceSetId, ss_type, rnti_type);
// Definition of value j in Table 6.1.2.1.1-4 of 38.214
int scs = ul_bwp->scs;
AssertFatal(scs >= 0 && scs < 5, "Subcarrier spacing indicatior %d invalid value\n", scs);
int j = scs == 0 ? 1 : scs;
if (tdalist) {
tda_info.valid_tda = tda_index < tdalist->list.count;
if (!tda_info.valid_tda) {
LOG_E(NR_MAC, "TDA index from DCI %d exceeds TDA list array size %d\n", tda_index, tdalist->list.count);
return tda_info;
}
NR_PUSCH_TimeDomainResourceAllocation_t *tda = tdalist->list.array[tda_index];
tda_info.mapping_type = tda->mappingType;
// As described in 38.331, when the field is absent the UE applies the value 1 when PUSCH SCS is 15/30KHz
// 2 when PUSCH SCS is 60KHz and 3 when PUSCH SCS is 120KHz. This equates to the parameter j.
tda_info.k2 = tda->k2 ? *tda->k2 : j;
int S, L;
SLIV2SL(tda->startSymbolAndLength, &S, &L);
tda_info.startSymbolIndex = S;
tda_info.nrOfSymbols = L;
} else {
bool normal_CP = ul_bwp->cyclicprefix ? false : true;
tda_info.valid_tda = tda_index < 16;
if (!tda_info.valid_tda) {
LOG_E(NR_MAC, "TDA index from DCI %d exceeds default TDA list array size %d\n", tda_index, 16);
return tda_info;
}
if (normal_CP) {
tda_info.mapping_type = table_6_1_2_1_1_2[tda_index][0];
tda_info.k2 = table_6_1_2_1_1_2[tda_index][1] + j;
tda_info.startSymbolIndex = table_6_1_2_1_1_2[tda_index][2];
tda_info.nrOfSymbols = table_6_1_2_1_1_2[tda_index][3];
} else {
tda_info.mapping_type = table_6_1_2_1_1_3[tda_index][0];
tda_info.k2 = table_6_1_2_1_1_3[tda_index][1] + j;
tda_info.startSymbolIndex = table_6_1_2_1_1_3[tda_index][2];
tda_info.nrOfSymbols = table_6_1_2_1_1_3[tda_index][3];
}
}
return tda_info;
}
NR_tda_info_t get_info_from_tda_tables(default_table_type_t table_type,
int tda,
int dmrs_TypeA_Position,
int normal_CP)
{
NR_tda_info_t tda_info = {0};
tda_info.valid_tda = tda < 16;
if (!tda_info.valid_tda) {
LOG_E(NR_MAC, "TDA index from DCI %d exceeds default TDA list array size %d\n", tda, 16);
return tda_info;
}
bool is_mapping_typeA;
int k0 = 0;
switch(table_type){
case defaultA:
if (normal_CP){
if (dmrs_TypeA_Position){
is_mapping_typeA = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][0];
k0 = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][1];
tda_info.startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][2];
tda_info.nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][3];
}
else{
is_mapping_typeA = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][0];
k0 = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][1];
tda_info.startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][2];
tda_info.nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][3];
}
}
else{
if (dmrs_TypeA_Position){
is_mapping_typeA = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][0];
k0 = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][1];
tda_info.startSymbolIndex = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][2];
tda_info.nrOfSymbols = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][3];
}
else{
is_mapping_typeA = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][0];
k0 = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][1];
tda_info.startSymbolIndex = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][2];
tda_info.nrOfSymbols = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][3];
}
}
break;
case defaultB:
if (dmrs_TypeA_Position){
is_mapping_typeA = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][0];
k0 = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][1];
tda_info.startSymbolIndex = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][2];
tda_info.nrOfSymbols = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][3];
}
else{
is_mapping_typeA = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][0];
k0 = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][1];
tda_info.startSymbolIndex = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][2];
tda_info.nrOfSymbols = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][3];
}
break;
case defaultC:
if (dmrs_TypeA_Position){
is_mapping_typeA = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][0];
k0 = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][1];
tda_info.startSymbolIndex = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][2];
tda_info.nrOfSymbols = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][3];
}
else{
is_mapping_typeA = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][0];
k0 = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][1];
tda_info.startSymbolIndex = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][2];
tda_info.nrOfSymbols = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][3];
}
break;
default:
AssertFatal(1 == 0, "Invalid default time domaing allocation type\n");
}
AssertFatal(k0 == 0, "Only k0 = 0 is supported\n");
tda_info.mapping_type = is_mapping_typeA ? typeA : typeB;
return tda_info;
}
default_table_type_t get_default_table_type(int mux_pattern)
{
switch (mux_pattern) {
case 1:
return defaultA;
case 2:
return defaultB;
case 3:
return defaultC;
default :
AssertFatal(1 == 0, "Invalid multiplexing type %d\n", mux_pattern);
}
}
NR_tda_info_t set_tda_info_from_list(NR_PDSCH_TimeDomainResourceAllocationList_t *tdalist, int tda_index)
{
NR_tda_info_t tda_info = {0};
tda_info.valid_tda = tda_index < tdalist->list.count;
if (!tda_info.valid_tda) {
LOG_E(NR_MAC, "TDA index from DCI %d exceeds TDA list array size %d\n", tda_index, tdalist->list.count);
return tda_info;
}
NR_PDSCH_TimeDomainResourceAllocation_t *tda = tdalist->list.array[tda_index];
tda_info.mapping_type = tda->mappingType;
int S, L;
SLIV2SL(tda->startSymbolAndLength, &S, &L);
tda_info.startSymbolIndex = S;
tda_info.nrOfSymbols = L;
return tda_info;
}
NR_tda_info_t get_dl_tda_info(const NR_UE_DL_BWP_t *dl_BWP,
int ss_type,
int tda_index,
int dmrs_typeA_pos,
int mux_pattern,
nr_rnti_type_t rnti_type,
int coresetid,
bool sib1)
{
NR_tda_info_t tda_info;
bool normal_CP = true;
if (dl_BWP && dl_BWP->cyclicprefix)
normal_CP = false;
// implements Table 5.1.2.1.1-1 of 38.214
NR_PDSCH_TimeDomainResourceAllocationList_t *tdalist = get_dl_tdalist(dl_BWP, coresetid, ss_type, rnti_type);
switch (rnti_type) {
case TYPE_SI_RNTI_:
if(sib1) {
default_table_type_t table_type = get_default_table_type(mux_pattern);
tda_info = get_info_from_tda_tables(table_type, tda_index, dmrs_typeA_pos, normal_CP);
}
else {
if(tdalist)
tda_info = set_tda_info_from_list(tdalist, tda_index);
else {
default_table_type_t table_type = get_default_table_type(mux_pattern);
tda_info = get_info_from_tda_tables(table_type, tda_index, dmrs_typeA_pos, normal_CP);
}
}
break;
case TYPE_P_RNTI_:
if(tdalist)
tda_info = set_tda_info_from_list(tdalist, tda_index);
else {
default_table_type_t table_type = get_default_table_type(mux_pattern);
tda_info = get_info_from_tda_tables(table_type, tda_index, dmrs_typeA_pos, normal_CP);
}
break;
case TYPE_C_RNTI_:
case TYPE_CS_RNTI_:
case TYPE_MCS_C_RNTI_:
case TYPE_RA_RNTI_:
case TYPE_MSGB_RNTI_:
case TYPE_TC_RNTI_:
if(tdalist)
tda_info = set_tda_info_from_list(tdalist, tda_index);
else
tda_info = get_info_from_tda_tables(defaultA, tda_index, dmrs_typeA_pos, normal_CP);
break;
default :
AssertFatal(1 == 0, "Invalid RNTI type\n");
}
return tda_info;
}
uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config) {
LOG_D(MAC,"get_NCS: indx %d,format0 %d, restriced_set_config %d\n",
index,format0,restricted_set_config);
if (format0 < 3) {
switch(restricted_set_config){
case 0:
return(NCS_unrestricted_delta_f_RA_125[index]);
case 1:
return(NCS_restricted_TypeA_delta_f_RA_125[index]);
case 2:
return(NCS_restricted_TypeB_delta_f_RA_125[index]);
default:
AssertFatal(1==0,"Invalid restricted set config value %d",restricted_set_config);
}
}
else {
if (format0 == 3) {
switch(restricted_set_config){
case 0:
return(NCS_unrestricted_delta_f_RA_5[index]);
case 1:
return(NCS_restricted_TypeA_delta_f_RA_5[index]);
case 2:
return(NCS_restricted_TypeB_delta_f_RA_5[index]);
default:
AssertFatal(1==0,"Invalid restricted set config value %d",restricted_set_config);
}
}
else
return(NCS_unrestricted_delta_f_RA_15[index]);
}
}
//from 38.211 Table 6.3.3.2-1
static const int16_t N_RA_RB[16] = {6, 3, 2, 24, 12, 6, 12, 6, 3, 24, 12, 6, 12, 6, 24, 12};
/* Function to get number of RBs required for prach occasion based on
* 38.211 Table 6.3.3.2-1 */
int16_t get_N_RA_RB (int delta_f_RA_PRACH, int delta_f_PUSCH)
{
int8_t index = 0;
switch(delta_f_RA_PRACH) {
case 0 :
index = 6;
if (delta_f_PUSCH == 0)
index += 0;
else if(delta_f_PUSCH == 1)
index += 1;
else
index += 2;
break;
case 1 :
index = 9;
if (delta_f_PUSCH == 0)
index += 0;
else if(delta_f_PUSCH == 1)
index += 1;
else
index += 2;
break;
case 2 :
index = 11;
if (delta_f_PUSCH == 2)
index += 0;
else
index += 1;
break;
case 3:
index = 13;
if (delta_f_PUSCH == 2)
index += 0;
else
index += 1;
break;
default : index = 10;/*30khz prach scs and 30khz pusch scs*/
}
return N_RA_RB[index];
}
// Table 6.3.3.2-2: Random access configurations for FR1 and paired spectrum/supplementary uplink
// the column 5, (SFN_nbr is a bitmap where we set bit to '1' in the position of the subframe where the RACH can be sent.
// E.g. in row 4, and column 5 we have set value 512 ('1000000000') which means RACH can be sent at subframe 9.
// E.g. in row 20 and column 5 we have set value 66 ('0001000010') which means RACH can be sent at subframe 1 or 6
static const int64_t table_6_3_3_2_2_prachConfig_Index[256][9] = {
// format, format, x, y, SFN_nbr, star_symb, slots_sfn, occ_slot, duration
{0, -1, 16, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{0, -1, 16, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{0, -1, 16, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{0, -1, 16, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{0, -1, 8, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{0, -1, 8, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{0, -1, 8, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{0, -1, 8, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{0, -1, 4, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{0, -1, 4, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{0, -1, 4, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{0, -1, 4, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{0, -1, 2, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{0, -1, 2, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{0, -1, 2, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{0, -1, 2, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{0, -1, 1, 0, 2, 0, 1, 1, 0}, // (subframe number) 1
{0, -1, 1, 0, 16, 0, 1, 1, 0}, // (subframe number) 4
{0, -1, 1, 0, 128, 0, 1, 1, 0}, // (subframe number) 7
{0, -1, 1, 0, 66, 0, 1, 1, 0}, // (subframe number) 1,6
{0, -1, 1, 0, 132, 0, 1, 1, 0}, // (subframe number) 2,7
{0, -1, 1, 0, 264, 0, 1, 1, 0}, // (subframe number) 3,8
{0, -1, 1, 0, 146, 0, 1, 1, 0}, // (subframe number) 1,4,7
{0, -1, 1, 0, 292, 0, 1, 1, 0}, // (subframe number) 2,5,8
{0, -1, 1, 0, 584, 0, 1, 1, 0}, // (subframe number) 3, 6, 9
{0, -1, 1, 0, 341, 0, 1, 1, 0}, // (subframe number) 0,2,4,6,8
{0, -1, 1, 0, 682, 0, 1, 1, 0}, // (subframe number) 1,3,5,7,9
{0, -1, 1, 0, 1023, 0, 1, 1, 0}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{1, -1, 16, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{1, -1, 16, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{1, -1, 16, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{1, -1, 16, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{1, -1, 8, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{1, -1, 8, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{1, -1, 8, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{1, -1, 8, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{1, -1, 4, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{1, -1, 4, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{1, -1, 4, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{1, -1, 4, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{1, -1, 2, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{1, -1, 2, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{1, -1, 2, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{1, -1, 2, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{1, -1, 1, 0, 2, 0, 1, 1, 0}, // (subframe number) 1
{1, -1, 1, 0, 16, 0, 1, 1, 0}, // (subframe number) 4
{1, -1, 1, 0, 128, 0, 1, 1, 0}, // (subframe number) 7
{1, -1, 1, 0, 66, 0, 1, 1, 0}, // (subframe number) 1,6
{1, -1, 1, 0, 132, 0, 1, 1, 0}, // (subframe number) 2,7
{1, -1, 1, 0, 264, 0, 1, 1, 0}, // (subframe number) 3,8
{1, -1, 1, 0, 146, 0, 1, 1, 0}, // (subframe number) 1,4,7
{1, -1, 1, 0, 292, 0, 1, 1, 0}, // (subframe number) 2,5,8
{1, -1, 1, 0, 584, 0, 1, 1, 0}, // (subframe number) 3,6,9
{2, -1, 16, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{2, -1, 8, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{2, -1, 4, 0, 2, 0, 1, 1, 0}, // (subframe number) 1
{2, -1, 2, 0, 2, 0, 1, 1, 0}, // (subframe number) 1
{2, -1, 2, 0, 32, 0, 1, 1, 0}, // (subframe number) 5
{2, -1, 1, 0, 2, 0, 1, 1, 0}, // (subframe number) 1
{2, -1, 1, 0, 32, 0, 1, 1, 0}, // (subframe number) 5
{3, -1, 16, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{3, -1, 16, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{3, -1, 16, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{3, -1, 16, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{3, -1, 8, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{3, -1, 8, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{3, -1, 8, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{3, -1, 4, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{3, -1, 4, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{3, -1, 4, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{3, -1, 4, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{3, -1, 2, 1, 2, 0, 1, 1, 0}, // (subframe number) 1
{3, -1, 2, 1, 16, 0, 1, 1, 0}, // (subframe number) 4
{3, -1, 2, 1, 128, 0, 1, 1, 0}, // (subframe number) 7
{3, -1, 2, 1, 512, 0, 1, 1, 0}, // (subframe number) 9
{3, -1, 1, 0, 2, 0, 1, 1, 0}, // (subframe number) 1
{3, -1, 1, 0, 16, 0, 1, 1, 0}, // (subframe number) 4
{3, -1, 1, 0, 128, 0, 1, 1, 0}, // (subframe number) 7
{3, -1, 1, 0, 66, 0, 1, 1, 0}, // (subframe number) 1,6
{3, -1, 1, 0, 132, 0, 1, 1, 0}, // (subframe number) 2,7
{3, -1, 1, 0, 264, 0, 1, 1, 0}, // (subframe number) 3,8
{3, -1, 1, 0, 146, 0, 1, 1, 0}, // (subframe number) 1,4,7
{3, -1, 1, 0, 292, 0, 1, 1, 0}, // (subframe number) 2,5,8
{3, -1, 1, 0, 584, 0, 1, 1, 0}, // (subframe number) 3, 6, 9
{3, -1, 1, 0, 341, 0, 1, 1, 0}, // (subframe number) 0,2,4,6,8
{3, -1, 1, 0, 682, 0, 1, 1, 0}, // (subframe number) 1,3,5,7,9
{3, -1, 1, 0, 1023, 0, 1, 1, 0}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xa1, -1, 16, 0, 528, 0, 1, 6, 2}, // (subframe number) 4,9
{0xa1, -1, 16, 1, 16, 0, 2, 6, 2}, // (subframe number) 4
{0xa1, -1, 8, 0, 528, 0, 1, 6, 2}, // (subframe number) 4,9
{0xa1, -1, 8, 1, 16, 0, 2, 6, 2}, // (subframe number) 4
{0xa1, -1, 4, 0, 528, 0, 1, 6, 2}, // (subframe number) 4,9
{0xa1, -1, 4, 1, 528, 0, 1, 6, 2}, // (subframe number) 4,9
{0xa1, -1, 4, 0, 16, 0, 2, 6, 2}, // (subframe number) 4
{0xa1, -1, 2, 0, 528, 0, 1, 6, 2}, // (subframe number) 4,9
{0xa1, -1, 2, 0, 2, 0, 2, 6, 2}, // (subframe number) 1
{0xa1, -1, 2, 0, 16, 0, 2, 6, 2}, // (subframe number) 4
{0xa1, -1, 2, 0, 128, 0, 2, 6, 2}, // (subframe number) 7
{0xa1, -1, 1, 0, 16, 0, 1, 6, 2}, // (subframe number) 4
{0xa1, -1, 1, 0, 66, 0, 1, 6, 2}, // (subframe number) 1,6
{0xa1, -1, 1, 0, 528, 0, 1, 6, 2}, // (subframe number) 4,9
{0xa1, -1, 1, 0, 2, 0, 2, 6, 2}, // (subframe number) 1
{0xa1, -1, 1, 0, 128, 0, 2, 6, 2}, // (subframe number) 7
{0xa1, -1, 1, 0, 132, 0, 2, 6, 2}, // (subframe number) 2,7
{0xa1, -1, 1, 0, 146, 0, 2, 6, 2}, // (subframe number) 1,4,7
{0xa1, -1, 1, 0, 341, 0, 2, 6, 2}, // (subframe number) 0,2,4,6,8
{0xa1, -1, 1, 0, 1023, 0, 2, 6, 2}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xa1, -1, 1, 0, 682, 0, 2, 6, 2}, // (subframe number) 1,3,5,7,9
{0xa1, 0xb1, 2, 0, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xa1, 0xb1, 2, 0, 16, 0, 2, 7, 2}, // (subframe number) 4
{0xa1, 0xb1, 1, 0, 16, 0, 1, 7, 2}, // (subframe number) 4
{0xa1, 0xb1, 1, 0, 66, 0, 1, 7, 2}, // (subframe number) 1,6
{0xa1, 0xb1, 1, 0, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xa1, 0xb1, 1, 0, 2, 0, 2, 7, 2}, // (subframe number) 1
{0xa1, 0xb1, 1, 0, 128, 0, 2, 7, 2}, // (subframe number) 7
{0xa1, 0xb1, 1, 0, 146, 0, 2, 7, 2}, // (subframe number) 1,4,7
{0xa1, 0xb1, 1, 0, 341, 0, 2, 7, 2}, // (subframe number) 0,2,4,6,8
{0xa2, -1, 16, 1, 580, 0, 1, 3, 4}, // (subframe number) 2,6,9
{0xa2, -1, 16, 1, 16, 0, 2, 3, 4}, // (subframe number) 4
{0xa2, -1, 8, 1, 580, 0, 1, 3, 4}, // (subframe number) 2,6,9
{0xa2, -1, 8, 1, 16, 0, 2, 3, 4}, // (subframe number) 4
{0xa2, -1, 4, 0, 580, 0, 1, 3, 4}, // (subframe number) 2,6,9
{0xa2, -1, 4, 0, 16, 0, 2, 3, 4}, // (subframe number) 4
{0xa2, -1, 2, 1, 580, 0, 1, 3, 4}, // (subframe number) 2,6,9
{0xa2, -1, 2, 0, 2, 0, 2, 3, 4}, // (subframe number) 1
{0xa2, -1, 2, 0, 16, 0, 2, 3, 4}, // (subframe number) 4
{0xa2, -1, 2, 0, 128, 0, 2, 3, 4}, // (subframe number) 7
{0xa2, -1, 1, 0, 16, 0, 1, 3, 4}, // (subframe number) 4
{0xa2, -1, 1, 0, 66, 0, 1, 3, 4}, // (subframe number) 1,6
{0xa2, -1, 1, 0, 528, 0, 1, 3, 4}, // (subframe number) 4,9
{0xa2, -1, 1, 0, 2, 0, 2, 3, 4}, // (subframe number) 1
{0xa2, -1, 1, 0, 128, 0, 2, 3, 4}, // (subframe number) 7
{0xa2, -1, 1, 0, 132, 0, 2, 3, 4}, // (subframe number) 2,7
{0xa2, -1, 1, 0, 146, 0, 2, 3, 4}, // (subframe number) 1,4,7
{0xa2, -1, 1, 0, 341, 0, 2, 3, 4}, // (subframe number) 0,2,4,6,8
{0xa2, -1, 1, 0, 1023, 0, 2, 3, 4}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xa2, -1, 1, 0, 682, 0, 2, 3, 4}, // (subframe number) 1,3,5,7,9
{0xa2, 0xb2, 2, 1, 580, 0, 1, 3, 4}, // (subframe number) 2,6,9
{0xa2, 0xb2, 2, 0, 16, 0, 2, 3, 4}, // (subframe number) 4
{0xa2, 0xb2, 1, 0, 16, 0, 1, 3, 4}, // (subframe number) 4
{0xa2, 0xb2, 1, 0, 66, 0, 1, 3, 4}, // (subframe number) 1,6
{0xa2, 0xb2, 1, 0, 528, 0, 1, 3, 4}, // (subframe number) 4,9
{0xa2, 0xb2, 1, 0, 2, 0, 2, 3, 4}, // (subframe number) 1
{0xa2, 0xb2, 1, 0, 128, 0, 2, 3, 4}, // (subframe number) 7
{0xa2, 0xb2, 1, 0, 146, 0, 2, 3, 4}, // (subframe number) 1,4,7
{0xa2, 0xb2, 1, 0, 341, 0, 2, 3, 4}, // (subframe number) 0,2,4,6,8
{0xa2, 0xb2, 1, 0, 1023, 0, 2, 3, 4}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xa3, -1, 16, 1, 528, 0, 1, 2, 6}, // (subframe number) 4,9
{0xa3, -1, 16, 1, 16, 0, 2, 2, 6}, // (subframe number) 4
{0xa3, -1, 8, 1, 528, 0, 1, 2, 6}, // (subframe number) 4,9
{0xa3, -1, 8, 1, 16, 0, 2, 2, 6}, // (subframe number) 4
{0xa3, -1, 4, 0, 528, 0, 1, 2, 6}, // (subframe number) 4,9
{0xa3, -1, 4, 0, 16, 0, 2, 2, 6}, // (subframe number) 4
{0xa3, -1, 2, 1, 580, 0, 2, 2, 6}, // (subframe number) 2,6,9
{0xa3, -1, 2, 0, 2, 0, 2, 2, 6}, // (subframe number) 1
{0xa3, -1, 2, 0, 16, 0, 2, 2, 6}, // (subframe number) 4
{0xa3, -1, 2, 0, 128, 0, 2, 2, 6}, // (subframe number) 7
{0xa3, -1, 1, 0, 16, 0, 1, 2, 6}, // (subframe number) 4
{0xa3, -1, 1, 0, 66, 0, 1, 2, 6}, // (subframe number) 1,6
{0xa3, -1, 1, 0, 528, 0, 1, 2, 6}, // (subframe number) 4,9
{0xa3, -1, 1, 0, 2, 0, 2, 2, 6}, // (subframe number) 1
{0xa3, -1, 1, 0, 128, 0, 2, 2, 6}, // (subframe number) 7
{0xa3, -1, 1, 0, 132, 0, 2, 2, 6}, // (subframe number) 2,7
{0xa3, -1, 1, 0, 146, 0, 2, 2, 6}, // (subframe number) 1,4,7
{0xa3, -1, 1, 0, 341, 0, 2, 2, 6}, // (subframe number) 0,2,4,6,8
{0xa3, -1, 1, 0, 1023, 0, 2, 2, 6}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xa3, -1, 1, 0, 682, 0, 2, 2, 6}, // (subframe number) 1,3,5,7,9
{0xa3, 0xb3, 2, 1, 580, 0, 2, 2, 6}, // (subframe number) 2,6,9
{0xa3, 0xb3, 2, 0, 16, 0, 2, 2, 6}, // (subframe number) 4
{0xa3, 0xb3, 1, 0, 16, 0, 1, 2, 6}, // (subframe number) 4
{0xa3, 0xb3, 1, 0, 66, 0, 1, 2, 6}, // (subframe number) 1,6
{0xa3, 0xb3, 1, 0, 528, 0, 1, 2, 6}, // (subframe number) 4,9
{0xa3, 0xb3, 1, 0, 2, 0, 2, 2, 6}, // (subframe number) 1
{0xa3, 0xb3, 1, 0, 128, 0, 2, 2, 6}, // (subframe number) 7
{0xa3, 0xb3, 1, 0, 146, 0, 2, 2, 6}, // (subframe number) 1,4,7
{0xa3, 0xb3, 1, 0, 341, 0, 2, 2, 6}, // (subframe number) 0,2,4,6,8
{0xa3, 0xb3, 1, 0, 1023, 0, 2, 2, 6}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xb1, -1, 16, 0, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xb1, -1, 16, 1, 16, 0, 2, 7, 2}, // (subframe number) 4
{0xb1, -1, 8, 0, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xb1, -1, 8, 1, 16, 0, 2, 7, 2}, // (subframe number) 4
{0xb1, -1, 4, 0, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xb1, -1, 4, 1, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xb1, -1, 4, 0, 16, 0, 2, 7, 2}, // (subframe number) 4
{0xb1, -1, 2, 0, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xb1, -1, 2, 0, 2, 0, 2, 7, 2}, // (subframe number) 1
{0xb1, -1, 2, 0, 16, 0, 2, 7, 2}, // (subframe number) 4
{0xb1, -1, 2, 0, 128, 0, 2, 7, 2}, // (subframe number) 7
{0xb1, -1, 1, 0, 16, 0, 1, 7, 2}, // (subframe number) 4
{0xb1, -1, 1, 0, 66, 0, 1, 7, 2}, // (subframe number) 1,6
{0xb1, -1, 1, 0, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xb1, -1, 1, 0, 2, 0, 2, 7, 2}, // (subframe number) 1
{0xb1, -1, 1, 0, 128, 0, 2, 7, 2}, // (subframe number) 7
{0xb1, -1, 1, 0, 132, 0, 2, 7, 2}, // (subframe number) 2,7
{0xb1, -1, 1, 0, 146, 0, 2, 7, 2}, // (subframe number) 1,4,7
{0xb1, -1, 1, 0, 341, 0, 2, 7, 2}, // (subframe number) 0,2,4,6,8
{0xb1, -1, 1, 0, 1023, 0, 2, 7, 2}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xb1, -1, 1, 0, 682, 0, 2, 7, 2}, // (subframe number) 1,3,5,7,9
{0xb4, -1, 16, 0, 528, 0, 2, 1, 12}, // (subframe number) 4,9
{0xb4, -1, 16, 1, 16, 0, 2, 1, 12}, // (subframe number) 4
{0xb4, -1, 8, 0, 528, 0, 2, 1, 12}, // (subframe number) 4,9
{0xb4, -1, 8, 1, 16, 0, 2, 1, 12}, // (subframe number) 4
{0xb4, -1, 4, 0, 528, 0, 2, 1, 12}, // (subframe number) 4,9
{0xb4, -1, 4, 0, 16, 0, 2, 1, 12}, // (subframe number) 4
{0xb4, -1, 4, 1, 528, 0, 2, 1, 12}, // (subframe number) 4,9
{0xb4, -1, 2, 0, 528, 0, 2, 1, 12}, // (subframe number) 4,9
{0xb4, -1, 2, 0, 2, 0, 2, 1, 12}, // (subframe number) 1
{0xb4, -1, 2, 0, 16, 0, 2, 1, 12}, // (subframe number) 4
{0xb4, -1, 2, 0, 128, 0, 2, 1, 12}, // (subframe number) 7
{0xb4, -1, 1, 0, 2, 0, 2, 1, 12}, // (subframe number) 1
{0xb4, -1, 1, 0, 16, 0, 2, 1, 12}, // (subframe number) 4
{0xb4, -1, 1, 0, 128, 0, 2, 1, 12}, // (subframe number) 7
{0xb4, -1, 1, 0, 66, 0, 2, 1, 12}, // (subframe number) 1,6
{0xb4, -1, 1, 0, 132, 0, 2, 1, 12}, // (subframe number) 2,7
{0xb4, -1, 1, 0, 528, 0, 2, 1, 12}, // (subframe number) 4,9
{0xb4, -1, 1, 0, 146, 0, 2, 1, 12}, // (subframe number) 1,4,7
{0xb4, -1, 1, 0, 341, 0, 2, 1, 12}, // (subframe number) 0,2,4,6,8
{0xb4, -1, 1, 0, 1023, 0, 2, 1, 12}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xb4, -1, 1, 0, 682, 0, 2, 1, 12}, // (subframe number) 1,3,5,7,9
{0xc0, -1, 8, 1, 16, 0, 2, 7, 2}, // (subframe number) 4
{0xc0, -1, 4, 1, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xc0, -1, 4, 0, 16, 0, 2, 7, 2}, // (subframe number) 4
{0xc0, -1, 2, 0, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xc0, -1, 2, 0, 2, 0, 2, 7, 2}, // (subframe number) 1
{0xc0, -1, 2, 0, 16, 0, 2, 7, 2}, // (subframe number) 4
{0xc0, -1, 2, 0, 128, 0, 2, 7, 2}, // (subframe number) 7
{0xc0, -1, 1, 0, 16, 0, 1, 7, 2}, // (subframe number) 4
{0xc0, -1, 1, 0, 66, 0, 1, 7, 2}, // (subframe number) 1,6
{0xc0, -1, 1, 0, 528, 0, 1, 7, 2}, // (subframe number) 4,9
{0xc0, -1, 1, 0, 2, 0, 2, 7, 2}, // (subframe number) 1
{0xc0, -1, 1, 0, 128, 0, 2, 7, 2}, // (subframe number) 7
{0xc0, -1, 1, 0, 132, 0, 2, 7, 2}, // (subframe number) 2,7
{0xc0, -1, 1, 0, 146, 0, 2, 7, 2}, // (subframe number) 1,4,7
{0xc0, -1, 1, 0, 341, 0, 2, 7, 2}, // (subframe number) 0,2,4,6,8
{0xc0, -1, 1, 0, 1023, 0, 2, 7, 2}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xc0, -1, 1, 0, 682, 0, 2, 7, 2}, // (subframe number) 1,3,5,7,9
{0xc2, -1, 16, 1, 528, 0, 1, 2, 6}, // (subframe number) 4,9
{0xc2, -1, 16, 1, 16, 0, 2, 2, 6}, // (subframe number) 4
{0xc2, -1, 8, 1, 528, 0, 1, 2, 6}, // (subframe number) 4,9
{0xc2, -1, 8, 1, 16, 0, 2, 2, 6}, // (subframe number) 4
{0xc2, -1, 4, 0, 528, 0, 1, 2, 6}, // (subframe number) 4,9
{0xc2, -1, 4, 0, 16, 0, 2, 2, 6}, // (subframe number) 4
{0xc2, -1, 2, 1, 580, 0, 2, 2, 6}, // (subframe number) 2,6,9
{0xc2, -1, 2, 0, 2, 0, 2, 2, 6}, // (subframe number) 1
{0xc2, -1, 2, 0, 16, 0, 2, 2, 6}, // (subframe number) 4
{0xc2, -1, 2, 0, 128, 0, 2, 2, 6}, // (subframe number) 7
{0xc2, -1, 1, 0, 16, 0, 1, 2, 6}, // (subframe number) 4
{0xc2, -1, 1, 0, 66, 0, 1, 2, 6}, // (subframe number) 1,6
{0xc2, -1, 1, 0, 528, 0, 1, 2, 6}, // (subframe number) 4,9
{0xc2, -1, 1, 0, 2, 0, 2, 2, 6}, // (subframe number) 1
{0xc2, -1, 1, 0, 128, 0, 2, 2, 6}, // (subframe number) 7
{0xc2, -1, 1, 0, 132, 0, 2, 2, 6}, // (subframe number) 2,7
{0xc2, -1, 1, 0, 146, 0, 2, 2, 6}, // (subframe number) 1,4,7
{0xc2, -1, 1, 0, 341, 0, 2, 2, 6}, // (subframe number) 0,2,4,6,8
{0xc2, -1, 1, 0, 1023, 0, 2, 2, 6}, // (subframe number) 0,1,2,3,4,5,6,7,8,9
{0xc2, -1, 1, 0, 682, 0, 2, 2, 6} // (subframe number) 1,3,5,7,9
};
// Table 6.3.3.2-3: Random access configurations for FR1 and unpaired spectrum
static const int64_t table_6_3_3_2_3_prachConfig_Index[256][9] = {
// format, format, x, y, SFN_nbr, star_symb, slots_sfn, occ_slot, duration
{0, -1, 16, 1, 512, 0, 1, 1, 0}, // (subrame number 9)
{0, -1, 8, 1, 512, 0, 1, 1, 0}, // (subrame number 9)
{0, -1, 4, 1, 512, 0, 1, 1, 0}, // (subrame number 9)
{0, -1, 2, 0, 512, 0, 1, 1, 0}, // (subrame number 9)
{0, -1, 2, 1, 512, 0, 1, 1, 0}, // (subrame number 9)
{0, -1, 2, 0, 16, 0, 1, 1, 0}, // (subrame number 4)
{0, -1, 2, 1, 16, 0, 1, 1, 0}, // (subrame number 4)
{0, -1, 1, 0, 512, 0, 1, 1, 0}, // (subrame number 9)
{0, -1, 1, 0, 256, 0, 1, 1, 0}, // (subrame number 8)
{0, -1, 1, 0, 128, 0, 1, 1, 0}, // (subrame number 7)
{0, -1, 1, 0, 64, 0, 1, 1, 0}, // (subrame number 6)
{0, -1, 1, 0, 32, 0, 1, 1, 0}, // (subrame number 5)
{0, -1, 1, 0, 16, 0, 1, 1, 0}, // (subrame number 4)
{0, -1, 1, 0, 8, 0, 1, 1, 0}, // (subrame number 3)
{0, -1, 1, 0, 4, 0, 1, 1, 0}, // (subrame number 2)
{0, -1, 1, 0, 66, 0, 1, 1, 0}, // (subrame number 1,6)
{0, -1, 1, 0, 66, 7, 1, 1, 0}, // (subrame number 1,6)
{0, -1, 1, 0, 528, 0, 1, 1, 0}, // (subrame number 4,9)
{0, -1, 1, 0, 264, 0, 1, 1, 0}, // (subrame number 3,8)
{0, -1, 1, 0, 132, 0, 1, 1, 0}, // (subrame number 2,7)
{0, -1, 1, 0, 768, 0, 1, 1, 0}, // (subrame number 8,9)
{0, -1, 1, 0, 784, 0, 1, 1, 0}, // (subrame number 4,8,9)
{0, -1, 1, 0, 536, 0, 1, 1, 0}, // (subrame number 3,4,9)
{0, -1, 1, 0, 896, 0, 1, 1, 0}, // (subrame number 7,8,9)
{0, -1, 1, 0, 792, 0, 1, 1, 0}, // (subrame number 3,4,8,9)
{0, -1, 1, 0, 960, 0, 1, 1, 0}, // (subrame number 6,7,8,9)
{0, -1, 1, 0, 594, 0, 1, 1, 0}, // (subrame number 1,4,6,9)
{0, -1, 1, 0, 682, 0, 1, 1, 0}, // (subrame number 1,3,5,7,9)
{1, -1, 16, 1, 128, 0, 1, 1, 0}, // (subrame number 7)
{1, -1, 8, 1, 128, 0, 1, 1, 0}, // (subrame number 7)
{1, -1, 4, 1, 128, 0, 1, 1, 0}, // (subrame number 7)
{1, -1, 2, 0, 128, 0, 1, 1, 0}, // (subrame number 7)
{1, -1, 2, 1, 128, 0, 1, 1, 0}, // (subrame number 7)
{1, -1, 1, 0, 128, 0, 1, 1, 0}, // (subrame number 7)
{2, -1, 16, 1, 64, 0, 1, 1, 0}, // (subrame number 6)
{2, -1, 8, 1, 64, 0, 1, 1, 0}, // (subrame number 6)
{2, -1, 4, 1, 64, 0, 1, 1, 0}, // (subrame number 6)
{2, -1, 2, 0, 64, 7, 1, 1, 0}, // (subrame number 6)
{2, -1, 2, 1, 64, 7, 1, 1, 0}, // (subrame number 6)
{2, -1, 1, 0, 64, 7, 1, 1, 0}, // (subrame number 6)
{3, -1, 16, 1, 512, 0, 1, 1, 0}, // (subrame number 9)
{3, -1, 8, 1, 512, 0, 1, 1, 0}, // (subrame number 9)
{3, -1, 4, 1, 512, 0, 1, 1, 0}, // (subrame number 9)
{3, -1, 2, 0, 512, 0, 1, 1, 0}, // (subrame number 9)
{3, -1, 2, 1, 512, 0, 1, 1, 0}, // (subrame number 9)
{3, -1, 2, 0, 16, 0, 1, 1, 0}, // (subrame number 4)
{3, -1, 2, 1, 16, 0, 1, 1, 0}, // (subrame number 4)
{3, -1, 1, 0, 512, 0, 1, 1, 0}, // (subrame number 9)
{3, -1, 1, 0, 256, 0, 1, 1, 0}, // (subrame number 8)
{3, -1, 1, 0, 128, 0, 1, 1, 0}, // (subrame number 7)
{3, -1, 1, 0, 64, 0, 1, 1, 0}, // (subrame number 6)
{3, -1, 1, 0, 32, 0, 1, 1, 0}, // (subrame number 5)
{3, -1, 1, 0, 16, 0, 1, 1, 0}, // (subrame number 4)
{3, -1, 1, 0, 8, 0, 1, 1, 0}, // (subrame number 3)
{3, -1, 1, 0, 4, 0, 1, 1, 0}, // (subrame number 2)
{3, -1, 1, 0, 66, 0, 1, 1, 0}, // (subrame number 1,6)
{3, -1, 1, 0, 66, 7, 1, 1, 0}, // (subrame number 1,6)
{3, -1, 1, 0, 528, 0, 1, 1, 0}, // (subrame number 4,9)
{3, -1, 1, 0, 264, 0, 1, 1, 0}, // (subrame number 3,8)
{3, -1, 1, 0, 132, 0, 1, 1, 0}, // (subrame number 2,7)
{3, -1, 1, 0, 768, 0, 1, 1, 0}, // (subrame number 8,9)
{3, -1, 1, 0, 784, 0, 1, 1, 0}, // (subrame number 4,8,9)
{3, -1, 1, 0, 536, 0, 1, 1, 0}, // (subrame number 3,4,9)
{3, -1, 1, 0, 896, 0, 1, 1, 0}, // (subrame number 7,8,9)
{3, -1, 1, 0, 792, 0, 1, 1, 0}, // (subrame number 3,4,8,9)
{3, -1, 1, 0, 594, 0, 1, 1, 0}, // (subrame number 1,4,6,9)
{3, -1, 1, 0, 682, 0, 1, 1, 0}, // (subrame number 1,3,5,7,9)
{0xa1, -1, 16, 1, 512, 0, 2, 6, 2}, // (subrame number 9)
{0xa1, -1, 8, 1, 512, 0, 2, 6, 2}, // (subrame number 9)
{0xa1, -1, 4, 1, 512, 0, 1, 6, 2}, // (subrame number 9)
{0xa1, -1, 2, 1, 512, 0, 1, 6, 2}, // (subrame number 9)
{0xa1, -1, 2, 1, 528, 7, 1, 3, 2}, // (subrame number 4,9)
{0xa1, -1, 2, 1, 640, 7, 1, 3, 2}, // (subrame number 7,9)
{0xa1, -1, 2, 1, 640, 0, 1, 6, 2}, // (subrame number 7,9)
{0xa1, -1, 2, 1, 768, 0, 2, 6, 2}, // (subrame number 8,9)
{0xa1, -1, 2, 1, 528, 0, 2, 6, 2}, // (subrame number 4,9)
{0xa1, -1, 2, 1, 924, 0, 1, 6, 2}, // (subrame number 2,3,4,7,8,9)
{0xa1, -1, 1, 0, 512, 0, 2, 6, 2}, // (subrame number 9)
{0xa1, -1, 1, 0, 512, 7, 1, 3, 2}, // (subrame number 9)
{0xa1, -1, 1, 0, 512, 0, 1, 6, 2}, // (subrame number 9)
{0xa1, -1, 1, 0, 768, 0, 2, 6, 2}, // (subrame number 8,9)
{0xa1, -1, 1, 0, 528, 0, 1, 6, 2}, // (subrame number 4,9)
{0xa1, -1, 1, 0, 640, 7, 1, 3, 2}, // (subrame number 7,9)
{0xa1, -1, 1, 0, 792, 0, 1, 6, 2}, // (subrame number 3,4,8,9)
{0xa1, -1, 1, 0, 792, 0, 2, 6, 2}, // (subrame number 3,4,8,9)
{0xa1, -1, 1, 0, 682, 0, 1, 6, 2}, // (subrame number 1,3,5,7,9)
{0xa1, -1, 1, 0, 1023, 7, 1, 3, 2}, // (subrame number 0,1,2,3,4,5,6,7,8,9)
{0xa2, -1, 16, 1, 512, 0, 2, 3, 4}, // (subrame number 9)
{0xa2, -1, 8, 1, 512, 0, 2, 3, 4}, // (subrame number 9)
{0xa2, -1, 4, 1, 512, 0, 1, 3, 4}, // (subrame number 9)
{0xa2, -1, 2, 1, 640, 0, 1, 3, 4}, // (subrame number 7,9)
{0xa2, -1, 2, 1, 768, 0, 2, 3, 4}, // (subrame number 8,9)
{0xa2, -1, 2, 1, 640, 9, 1, 1, 4}, // (subrame number 7,9)
{0xa2, -1, 2, 1, 528, 9, 1, 1, 4}, // (subrame number 4,9)
{0xa2, -1, 2, 1, 528, 0, 2, 3, 4}, // (subrame number 4,9)
{0xa2, -1, 16, 1, 924, 0, 1, 3, 4}, // (subrame number 2,3,4,7,8,9)
{0xa2, -1, 1, 0, 4, 0, 1, 3, 4}, // (subrame number 2)
{0xa2, -1, 1, 0, 128, 0, 1, 3, 4}, // (subrame number 7)
{0xa2, -1, 2, 1, 512, 0, 1, 3, 4}, // (subrame number 9)
{0xa2, -1, 1, 0, 512, 0, 2, 3, 4}, // (subrame number 9)
{0xa2, -1, 1, 0, 512, 9, 1, 1, 4}, // (subrame number 9)
{0xa2, -1, 1, 0, 512, 0, 1, 3, 4}, // (subrame number 9)
{0xa2, -1, 1, 0, 132, 0, 1, 3, 4}, // (subrame number 2,7)
{0xa2, -1, 1, 0, 768, 0, 2, 3, 4}, // (subrame number 8,9)
{0xa2, -1, 1, 0, 528, 0, 1, 3, 4}, // (subrame number 4,9)
{0xa2, -1, 1, 0, 640, 9, 1, 1, 4}, // (subrame number 7,9)
{0xa2, -1, 1, 0, 792, 0, 1, 3, 4}, // (subrame number 3,4,8,9)
{0xa2, -1, 1, 0, 792, 0, 2, 3, 4}, // (subrame number 3,4,8,9)
{0xa2, -1, 1, 0, 682, 0, 1, 3, 4}, // (subrame number 1,3,5,7,9)
{0xa2, -1, 1, 0, 1023, 9, 1, 1, 4}, // (subrame number 0,1,2,3,4,5,6,7,8,9)
{0xa3, -1, 16, 1, 512, 0, 2, 2, 6}, // (subrame number 9)
{0xa3, -1, 8, 1, 512, 0, 2, 2, 6}, // (subrame number 9)
{0xa3, -1, 4, 1, 512, 0, 1, 2, 6}, // (subrame number 9)
{0xa3, -1, 2, 1, 528, 7, 1, 1, 6}, // (subrame number 4,9)
{0xa3, -1, 2, 1, 640, 7, 1, 1, 6}, // (subrame number 7,9)
{0xa3, -1, 2, 1, 640, 0, 1, 2, 6}, // (subrame number 7,9)
{0xa3, -1, 2, 1, 528, 0, 2, 2, 6}, // (subrame number 4,9)
{0xa3, -1, 2, 1, 768, 0, 2, 2, 6}, // (subrame number 8,9)
{0xa3, -1, 2, 1, 924, 0, 1, 2, 6}, // (subrame number 2,3,4,7,8,9)
{0xa3, -1, 1, 0, 4, 0, 1, 2, 6}, // (subrame number 2)
{0xa3, -1, 1, 0, 128, 0, 1, 2, 6}, // (subrame number 7)
{0xa3, -1, 2, 1, 512, 0, 1, 2, 6}, // (subrame number 9)
{0xa3, -1, 1, 0, 512, 0, 2, 2, 6}, // (subrame number 9)
{0xa3, -1, 1, 0, 512, 7, 1, 1, 6}, // (subrame number 9)
{0xa3, -1, 1, 0, 512, 0, 1, 2, 6}, // (subrame number 9)
{0xa3, -1, 1, 0, 132, 0, 1, 2, 6}, // (subrame number 2,7)
{0xa3, -1, 1, 0, 768, 0, 2, 2, 6}, // (subrame number 8,9)
{0xa3, -1, 1, 0, 528, 0, 1, 2, 6}, // (subrame number 4,9)
{0xa3, -1, 1, 0, 640, 7, 1, 1, 6}, // (subrame number 7,9)
{0xa3, -1, 1, 0, 792, 0, 1, 2, 6}, // (subrame number 3,4,8,9)
{0xa3, -1, 1, 0, 792, 0, 2, 2, 6}, // (subrame number 3,4,8,9)
{0xa3, -1, 1, 0, 682, 0, 1, 2, 6}, // (subrame number 1,3,5,7,9)
{0xa3, -1, 1, 0, 1023, 7, 1, 1, 6}, // (subrame number 0,1,2,3,4,5,6,7,8,9)
{0xb1, -1, 4, 1, 512, 2, 1, 6, 2}, // (subrame number 9)
{0xb1, -1, 2, 1, 512, 2, 1, 6, 2}, // (subrame number 9)
{0xb1, -1, 2, 1, 640, 2, 1, 6, 2}, // (subrame number 7,9)
{0xb1, -1, 2, 1, 528, 8, 1, 3, 2}, // (subrame number 4,9)
{0xb1, -1, 2, 1, 528, 2, 2, 6, 2}, // (subrame number 4,9)
{0xb1, -1, 1, 0, 512, 2, 2, 6, 2}, // (subrame number 9)
{0xb1, -1, 1, 0, 512, 8, 1, 3, 2}, // (subrame number 9)
{0xb1, -1, 1, 0, 512, 2, 1, 6, 2}, // (subrame number 9)
{0xb1, -1, 1, 0, 768, 2, 2, 6, 2}, // (subrame number 8,9)
{0xb1, -1, 1, 0, 528, 2, 1, 6, 2}, // (subrame number 4,9)
{0xb1, -1, 1, 0, 640, 8, 1, 3, 2}, // (subrame number 7,9)
{0xb1, -1, 1, 0, 682, 2, 1, 6, 2}, // (subrame number 1,3,5,7,9)
{0xb4, -1, 16, 1, 512, 0, 2, 1, 12}, // (subrame number 9)
{0xb4, -1, 8, 1, 512, 0, 2, 1, 12}, // (subrame number 9)
{0xb4, -1, 4, 1, 512, 2, 1, 1, 12}, // (subrame number 9)
{0xb4, -1, 2, 1, 512, 0, 1, 1, 12}, // (subrame number 9)
{0xb4, -1, 2, 1, 512, 2, 1, 1, 12}, // (subrame number 9)
{0xb4, -1, 2, 1, 640, 2, 1, 1, 12}, // (subrame number 7,9)
{0xb4, -1, 2, 1, 528, 2, 1, 1, 12}, // (subrame number 4,9)
{0xb4, -1, 2, 1, 528, 0, 2, 1, 12}, // (subrame number 4,9)
{0xb4, -1, 2, 1, 768, 0, 2, 1, 12}, // (subrame number 8,9)
{0xb4, -1, 2, 1, 924, 0, 1, 1, 12}, // (subrame number 2,3,4,7,8,9)
{0xb4, -1, 1, 0, 2, 0, 1, 1, 12}, // (subrame number 1)
{0xb4, -1, 1, 0, 4, 0, 1, 1, 12}, // (subrame number 2)
{0xb4, -1, 1, 0, 16, 0, 1, 1, 12}, // (subrame number 4)
{0xb4, -1, 1, 0, 128, 0, 1, 1, 12}, // (subrame number 7)
{0xb4, -1, 1, 0, 512, 0, 1, 1, 12}, // (subrame number 9)
{0xb4, -1, 1, 0, 512, 2, 1, 1, 12}, // (subrame number 9)
{0xb4, -1, 1, 0, 512, 0, 2, 1, 12}, // (subrame number 9)
{0xb4, -1, 1, 0, 528, 2, 1, 1, 12}, // (subrame number 4,9)
{0xb4, -1, 1, 0, 640, 2, 1, 1, 12}, // (subrame number 7,9)
{0xb4, -1, 1, 0, 768, 0, 2, 1, 12}, // (subrame number 8,9)
{0xb4, -1, 1, 0, 792, 2, 1, 1, 12}, // (subrame number 3,4,8,9)
{0xb4, -1, 1, 0, 682, 2, 1, 1, 12}, // (subrame number 1,3,5,7,9)
{0xb4, -1, 1, 0, 1023, 0, 2, 1, 12}, // (subrame number 0,1,2,3,4,5,6,7,8,9)
{0xb4, -1, 1, 0, 1023, 2, 1, 1, 12}, // (subrame number 0,1,2,3,4,5,6,7,8,9)
{0xc0, -1, 16, 1, 512, 2, 2, 6, 2}, // (subrame number 9)
{0xc0, -1, 8, 1, 512, 2, 2, 6, 2}, // (subrame number 9)
{0xc0, -1, 4, 1, 512, 2, 1, 6, 2}, // (subrame number 9)
{0xc0, -1, 2, 1, 512, 2, 1, 6, 2}, // (subrame number 9)
{0xc0, -1, 2, 1, 768, 2, 2, 6, 2}, // (subrame number 8,9)
{0xc0, -1, 2, 1, 640, 2, 1, 6, 2}, // (subrame number 7,9)
{0xc0, -1, 2, 1, 640, 8, 1, 3, 2}, // (subrame number 7,9)
{0xc0, -1, 2, 1, 528, 8, 1, 3, 2}, // (subrame number 4,9)
{0xc0, -1, 2, 1, 528, 2, 2, 6, 2}, // (subrame number 4,9)
{0xc0, -1, 2, 1, 924, 2, 1, 6, 2}, // (subrame number 2,3,4,7,8,9)
{0xc0, -1, 1, 0, 512, 2, 2, 6, 2}, // (subrame number 9)
{0xc0, -1, 1, 0, 512, 8, 1, 3, 2}, // (subrame number 9)
{0xc0, -1, 1, 0, 512, 2, 1, 6, 2}, // (subrame number 9)
{0xc0, -1, 1, 0, 768, 2, 2, 6, 2}, // (subrame number 8,9)
{0xc0, -1, 1, 0, 528, 2, 1, 6, 2}, // (subrame number 4,9)
{0xc0, -1, 1, 0, 640, 8, 1, 3, 2}, // (subrame number 7,9)
{0xc0, -1, 1, 0, 792, 2, 1, 6, 2}, // (subrame number 3,4,8,9)
{0xc0, -1, 1, 0, 792, 2, 2, 6, 2}, // (subrame number 3,4,8,9)
{0xc0, -1, 1, 0, 682, 2, 1, 6, 2}, // (subrame number 1,3,5,7,9)
{0xc0, -1, 1, 0, 1023, 8, 1, 3, 2}, // (subrame number 0,1,2,3,4,5,6,7,8,9)
{0xc2, -1, 16, 1, 512, 2, 2, 2, 6}, // (subrame number 9)
{0xc2, -1, 8, 1, 512, 2, 2, 2, 6}, // (subrame number 9)
{0xc2, -1, 4, 1, 512, 2, 1, 2, 6}, // (subrame number 9)
{0xc2, -1, 2, 1, 512, 2, 1, 2, 6}, // (subrame number 9)
{0xc2, -1, 2, 1, 768, 2, 2, 2, 6}, // (subrame number 8,9)
{0xc2, -1, 2, 1, 640, 2, 1, 2, 6}, // (subrame number 7,9)
{0xc2, -1, 2, 1, 640, 8, 1, 1, 6}, // (subrame number 7,9)
{0xc2, -1, 2, 1, 528, 8, 1, 1, 6}, // (subrame number 4,9)
{0xc2, -1, 2, 1, 528, 2, 2, 2, 6}, // (subrame number 4,9)
{0xc2, -1, 2, 1, 924, 2, 1, 2, 6}, // (subrame number 2,3,4,7,8,9)
{0xc2, -1, 8, 1, 512, 8, 2, 1, 6}, // (subrame number 9)
{0xc2, -1, 4, 1, 512, 8, 1, 1, 6}, // (subrame number 9)
{0xc2, -1, 1, 0, 512, 2, 2, 2, 6}, // (subrame number 9)
{0xc2, -1, 1, 0, 512, 8, 1, 1, 6}, // (subrame number 9)
{0xc2, -1, 1, 0, 512, 2, 1, 2, 6}, // (subrame number 9)
{0xc2, -1, 1, 0, 768, 2, 2, 2, 6}, // (subrame number 8,9)
{0xc2, -1, 1, 0, 528, 2, 1, 2, 6}, // (subrame number 4,9)
{0xc2, -1, 1, 0, 640, 8, 1, 1, 6}, // (subrame number 7,9)
{0xc2, -1, 1, 0, 792, 2, 1, 2, 6}, // (subrame number 3,4,8,9)
{0xc2, -1, 1, 0, 792, 2, 2, 2, 6}, // (subrame number 3,4,8,9)
{0xc2, -1, 1, 0, 682, 2, 1, 2, 6}, // (subrame number 1,3,5,7,9)
{0xc2, -1, 1, 0, 1023, 8, 1, 1, 6}, // (subrame number 0,1,2,3,4,5,6,7,8,9)
{0xa1, 0xb1, 2, 1, 512, 2, 1, 6, 2}, // (subrame number 9)
{0xa1, 0xb1, 2, 1, 528, 8, 1, 3, 2}, // (subrame number 4,9)
{0xa1, 0xb1, 2, 1, 640, 8, 1, 3, 2}, // (subrame number 7,9)
{0xa1, 0xb1, 2, 1, 640, 2, 1, 6, 2}, // (subrame number 7,9)
{0xa1, 0xb1, 2, 1, 528, 2, 2, 6, 2}, // (subrame number 4,9)
{0xa1, 0xb1, 2, 1, 768, 2, 2, 6, 2}, // (subrame number 8,9)
{0xa1, 0xb1, 1, 0, 512, 2, 2, 6, 2}, // (subrame number 9)
{0xa1, 0xb1, 1, 0, 512, 8, 1, 3, 2}, // (subrame number 9)
{0xa1, 0xb1, 1, 0, 512, 2, 1, 6, 2}, // (subrame number 9)
{0xa1, 0xb1, 1, 0, 768, 2, 2, 6, 2}, // (subrame number 8,9)
{0xa1, 0xb1, 1, 0, 528, 2, 1, 6, 2}, // (subrame number 4,9)
{0xa1, 0xb1, 1, 0, 640, 8, 1, 3, 2}, // (subrame number 7,9)
{0xa1, 0xb1, 1, 0, 792, 2, 2, 6, 2}, // (subrame number 3,4,8,9)
{0xa1, 0xb1, 1, 0, 682, 2, 1, 6, 2}, // (subrame number 1,3,5,7,9)
{0xa1, 0xb1, 1, 0, 1023, 8, 1, 3, 2}, // (subrame number 0,1,2,3,4,5,6,7,8,9)
{0xa2, 0xb2, 2, 1, 512, 0, 1, 3, 4}, // (subrame number 9)
{0xa2, 0xb2, 2, 1, 528, 6, 1, 2, 4}, // (subrame number 4,9)
{0xa2, 0xb2, 2, 1, 640, 6, 1, 2, 4}, // (subrame number 7,9)
{0xa2, 0xb2, 2, 1, 528, 0, 2, 3, 4}, // (subrame number 4,9)
{0xa2, 0xb2, 2, 1, 768, 0, 2, 3, 4}, // (subrame number 8,9)
{0xa2, 0xb2, 1, 0, 512, 0, 2, 3, 4}, // (subrame number 9)
{0xa2, 0xb2, 1, 0, 512, 6, 1, 2, 4}, // (subrame number 9)
{0xa2, 0xb2, 1, 0, 512, 0, 1, 3, 4}, // (subrame number 9)
{0xa2, 0xb2, 1, 0, 768, 0, 2, 3, 4}, // (subrame number 8,9)
{0xa2, 0xb2, 1, 0, 528, 0, 1, 3, 4}, // (subrame number 4,9)
{0xa2, 0xb2, 1, 0, 640, 6, 1, 2, 4}, // (subrame number 7,9)
{0xa2, 0xb2, 1, 0, 792, 0, 1, 3, 4}, // (subrame number 3,4,8,9)
{0xa2, 0xb2, 1, 0, 792, 0, 2, 3, 4}, // (subrame number 3,4,8,9)
{0xa2, 0xb2, 1, 0, 682, 0, 1, 3, 4}, // (subrame number 1,3,5,7,9)
{0xa2, 0xb2, 1, 0, 1023, 6, 1, 2, 4}, // (subrame number 0,1,2,3,4,5,6,7,8,9)
{0xa3, 0xb3, 2, 1, 512, 0, 1, 2, 6}, // (subrame number 9)
{0xa3, 0xb3, 2, 1, 528, 2, 1, 2, 6}, // (subrame number 4,9)
{0xa3, 0xb3, 2, 1, 640, 0, 1, 2, 6}, // (subrame number 7,9)
{0xa3, 0xb3, 2, 1, 640, 2, 1, 2, 6}, // (subrame number 7,9)
{0xa3, 0xb3, 2, 1, 528, 0, 2, 2, 6}, // (subrame number 4,9)
{0xa3, 0xb3, 2, 1, 768, 0, 2, 2, 6}, // (subrame number 8,9)
{0xa3, 0xb3, 1, 0, 512, 0, 2, 2, 6}, // (subrame number 9)
{0xa3, 0xb3, 1, 0, 512, 2, 1, 2, 6}, // (subrame number 9)
{0xa3, 0xb3, 1, 0, 512, 0, 1, 2, 6}, // (subrame number 9)
{0xa3, 0xb3, 1, 0, 768, 0, 2, 2, 6}, // (subrame number 8,9)
{0xa3, 0xb3, 1, 0, 528, 0, 1, 2, 6}, // (subrame number 4,9)
{0xa3, 0xb3, 1, 0, 640, 2, 1, 2, 6}, // (subrame number 7,9)
{0xa3, 0xb3, 1, 0, 792, 0, 2, 2, 6}, // (subrame number 3,4,8,9)
{0xa3, 0xb3, 1, 0, 682, 0, 1, 2, 6}, // (subrame number 1,3,5,7,9)
{0xa3, 0xb3, 1, 0, 1023, 2, 1, 2, 6} // (subrame number 0,1,2,3,4,5,6,7,8,9)
};
// Table 6.3.3.2-4: Random access configurations for FR2 and unpaired spectrum
static const int64_t table_6_3_3_2_4_prachConfig_Index[256][10] = {
// format, format, x, y, y, SFN_nbr, star_symb, slots_sfn, occ_slot,
// duration
{0xa1, -1, 16, 1, -1, 567489872400, 0, 2, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, -1, 16, 1, -1, 586406201480, 0, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, -1, 8, 1, 2, 550293209600, 0, 2, 6, 2}, // (subframe number :9,19,29,39)
{0xa1, -1, 8, 1, -1, 567489872400, 0, 2, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, -1, 8, 1, -1, 586406201480, 0, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, -1, 4, 1, -1, 567489872400, 0, 1, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, -1, 4, 1, -1, 567489872400, 0, 2, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, -1, 4, 1, -1, 586406201480, 0, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, -1, 2, 1, -1, 551911719040, 0, 2, 6, 2}, // (subframe number :7,15,23,31,39)
{0xa1, -1, 2, 1, -1, 567489872400, 0, 1, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, -1, 2, 1, -1, 567489872400, 0, 2, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, -1, 2, 1, -1, 586406201480, 0, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, -1, 1, 0, -1, 549756338176, 7, 1, 3, 2}, // (subframe number :19,39)
{0xa1, -1, 1, 0, -1, 168, 0, 1, 6, 2}, // (subframe number :3,5,7)
{0xa1, -1, 1, 0, -1, 567489331200, 7, 1, 3, 2}, // (subframe number :24,29,34,39)
{0xa1, -1, 1, 0, -1, 550293209600, 7, 2, 3, 2}, // (subframe number :9,19,29,39)
{0xa1, -1, 1, 0, -1, 687195422720, 0, 1, 6, 2}, // (subframe number :17,19,37,39)
{0xa1, -1, 1, 0, -1, 550293209600, 0, 2, 6, 2}, // (subframe number :9,19,29,39)
{0xa1, -1, 1, 0, -1, 567489872400, 0, 1, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, -1, 1, 0, -1, 567489872400, 7, 1, 3, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, -1, 1, 0, -1, 10920, 7, 1, 3, 2}, // (subframe number :3,5,7,9,11,13)
{0xa1, -1, 1, 0, -1, 586405642240, 7, 1, 3, 2}, // (subframe number :23,27,31,35,39)
{0xa1, -1, 1, 0, -1, 551911719040, 0, 1, 6, 2}, // (subframe number :7,15,23,31,39)
{0xa1, -1, 1, 0, -1, 586405642240, 0, 1, 6, 2}, // (subframe number :23,27,31,35,39)
{0xa1, -1, 1, 0, -1, 965830828032, 7, 2, 3, 2}, // (subframe number :13,14,15, 29,30,31,37,38,39)
{0xa1, -1, 1, 0, -1, 586406201480, 7, 1, 3, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, -1, 1, 0, -1, 586406201480, 0, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, -1, 1, 0, -1, 733007751850, 0, 1, 6, 2}, // (subframe number :1,3,5,7,…,37,39)
{0xa1, -1, 1, 0, -1, 1099511627775, 7, 1, 3, 2}, // (subframe number :0,1,2,…,39)
{0xa2, -1, 16, 1, -1, 567489872400, 0, 2, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, -1, 16, 1, -1, 586406201480, 0, 1, 3, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, -1, 8, 1, -1, 567489872400, 0, 2, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, -1, 8, 1, -1, 586406201480, 0, 1, 3, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, -1, 8, 1, 2, 550293209600, 0, 2, 3, 4}, // (subframe number :9,19,29,39)
{0xa2, -1, 4, 1, -1, 567489872400, 0, 1, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, -1, 4, 1, -1, 567489872400, 0, 2, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, -1, 4, 1, -1, 586406201480, 0, 1, 3, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, -1, 2, 1, -1, 551911719040, 0, 2, 3, 4}, // (subframe number :7,15,23,31,39)
{0xa2, -1, 2, 1, -1, 567489872400, 0, 1, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, -1, 2, 1, -1, 567489872400, 0, 2, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, -1, 2, 1, -1, 586406201480, 0, 1, 3, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, -1, 1, 0, -1, 549756338176, 5, 1, 2, 4}, // (subframe number :19,39)
{0xa2, -1, 1, 0, -1, 168, 0, 1, 3, 4}, // (subframe number :3,5,7)
{0xa2, -1, 1, 0, -1, 567489331200, 5, 1, 2, 4}, // (subframe number :24,29,34,39)
{0xa2, -1, 1, 0, -1, 550293209600, 5, 2, 2, 4}, // (subframe number :9,19,29,39)
{0xa2, -1, 1, 0, -1, 687195422720, 0, 1, 3, 4}, // (subframe number :17,19,37,39)
{0xa2, -1, 1, 0, -1, 550293209600, 0, 2, 3, 4}, // (subframe number :9, 19, 29, 39)
{0xa2, -1, 1, 0, -1, 551911719040, 0, 1, 3, 4}, // (subframe number :7,15,23,31,39)
{0xa2, -1, 1, 0, -1, 586405642240, 5, 1, 2, 4}, // (subframe number :23,27,31,35,39)
{0xa2, -1, 1, 0, -1, 586405642240, 0, 1, 3, 4}, // (subframe number :23,27,31,35,39)
{0xa2, -1, 1, 0, -1, 10920, 5, 1, 2, 4}, // (subframe number :3,5,7,9,11,13)
{0xa2, -1, 1, 0, -1, 10920, 0, 1, 3, 4}, // (subframe number :3,5,7,9,11,13)
{0xa2, -1, 1, 0, -1, 567489872400, 5, 1, 2, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, -1, 1, 0, -1, 567489872400, 0, 1, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, -1, 1, 0, -1, 965830828032, 5, 2, 2, 4}, // (subframe number :13,14,15, 29,30,31,37,38,39)
{0xa2, -1, 1, 0, -1, 586406201480, 5, 1, 2, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, -1, 1, 0, -1, 586406201480, 0, 1, 3, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, -1, 1, 0, -1, 733007751850, 0, 1, 3, 4}, // (subframe number :1,3,5,7,…,37,39)
{0xa2, -1, 1, 0, -1, 1099511627775, 5, 1, 2, 4}, // (subframe number :0,1,2,…,39)
{0xa3, -1, 16, 1, -1, 567489872400, 0, 2, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, -1, 16, 1, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, -1, 8, 1, -1, 567489872400, 0, 2, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, -1, 8, 1, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, -1, 8, 1, 2, 550293209600, 0, 2, 2, 6}, // (subframe number :9,19,29,39)
{0xa3, -1, 4, 1, -1, 567489872400, 0, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, -1, 4, 1, -1, 567489872400, 0, 2, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, -1, 4, 1, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, -1, 2, 1, -1, 567489872400, 0, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, -1, 2, 1, -1, 567489872400, 0, 2, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, -1, 2, 1, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, -1, 1, 0, -1, 549756338176, 7, 1, 1, 6}, // (subframe number :19,39)
{0xa3, -1, 1, 0, -1, 168, 0, 1, 2, 6}, // (subframe number :3,5,7)
{0xa3, -1, 1, 0, -1, 10752, 2, 1, 2, 6}, // (subframe number :9,11,13)
{0xa3, -1, 1, 0, -1, 567489331200, 7, 1, 1, 6}, // (subframe number :24,29,34,39)
{0xa3, -1, 1, 0, -1, 550293209600, 7, 2, 1, 6}, // (subframe number :9,19,29,39)
{0xa3, -1, 1, 0, -1, 687195422720, 0, 1, 2, 6}, // (subframe number :17,19,37,39)
{0xa3, -1, 1, 0, -1, 550293209600, 0, 2, 2, 6}, // (subframe number :9,19,29,39)
{0xa3, -1, 1, 0, -1, 551911719040, 0, 1, 2, 6}, // (subframe number :7,15,23,31,39)
{0xa3, -1, 1, 0, -1, 586405642240, 7, 1, 1, 6}, // (subframe number :23,27,31,35,39)
{0xa3, -1, 1, 0, -1, 586405642240, 0, 1, 2, 6}, // (subframe number :23,27,31,35,39)
{0xa3, -1, 1, 0, -1, 10920, 0, 1, 2, 6}, // (subframe number :3,5,7,9,11,13)
{0xa3, -1, 1, 0, -1, 10920, 7, 1, 1, 6}, // (subframe number :3,5,7,9,11,13)
{0xa3, -1, 1, 0, -1, 567489872400, 0, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, -1, 1, 0, -1, 567489872400, 7, 1, 1, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, -1, 1, 0, -1, 965830828032, 7, 2, 1, 6}, // (subframe number :13,14,15, 29,30,31,37,38,39)
{0xa3, -1, 1, 0, -1, 586406201480, 7, 1, 1, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, -1, 1, 0, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, -1, 1, 0, -1, 733007751850, 0, 1, 2, 6}, // (subframe number :1,3,5,7,…,37,39)
{0xa3, -1, 1, 0, -1, 1099511627775, 7, 1, 1, 6}, // (subframe number :0,1,2,…,39)
{0xb1, -1, 16, 1, -1, 567489872400, 2, 2, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb1, -1, 8, 1, -1, 567489872400, 2, 2, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb1, -1, 8, 1, 2, 550293209600, 2, 2, 6, 2}, // (subframe number :9,19,29,39)
{0xb1, -1, 4, 1, -1, 567489872400, 2, 2, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb1, -1, 2, 1, -1, 567489872400, 2, 2, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb1, -1, 2, 1, -1, 586406201480, 2, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xb1, -1, 1, 0, -1, 549756338176, 8, 1, 3, 2}, // (subframe number :19,39)
{0xb1, -1, 1, 0, -1, 168, 2, 1, 6, 2}, // (subframe number :3,5,7)
{0xb1, -1, 1, 0, -1, 567489331200, 8, 1, 3, 2}, // (subframe number :24,29,34,39)
{0xb1, -1, 1, 0, -1, 550293209600, 8, 2, 3, 2}, // (subframe number :9,19,29,39)
{0xb1, -1, 1, 0, -1, 687195422720, 2, 1, 6, 2}, // (subframe number :17,19,37,39)
{0xb1, -1, 1, 0, -1, 550293209600, 2, 2, 6, 2}, // (subframe number :9,19,29,39)
{0xb1, -1, 1, 0, -1, 551911719040, 2, 1, 6, 2}, // (subframe number :7,15,23,31,39)
{0xb1, -1, 1, 0, -1, 586405642240, 8, 1, 3, 2}, // (subframe number :23,27,31,35,39)
{0xb1, -1, 1, 0, -1, 586405642240, 2, 1, 6, 2}, // (subframe number :23,27,31,35,39)
{0xb1, -1, 1, 0, -1, 10920, 8, 1, 3, 2}, // (subframe number :3,5,7,9,11,13)
{0xb1, -1, 1, 0, -1, 567489872400, 8, 1, 3, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb1, -1, 1, 0, -1, 567489872400, 2, 1, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb1, -1, 1, 0, -1, 586406201480, 8, 1, 3, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xb1, -1, 1, 0, -1, 965830828032, 8, 2, 3, 2}, // (subframe number :13,14,15, 29,30,31,37,38,39)
{0xb1, -1, 1, 0, -1, 586406201480, 2, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xb1, -1, 1, 0, -1, 733007751850, 2, 1, 6, 2}, // (subframe number :1,3,5,7,…,37,39)
{0xb1, -1, 1, 0, -1, 1099511627775, 8, 1, 3, 2}, // (subframe number :0,1,2,…,39)
{0xb4, -1, 16, 1, 2, 567489872400, 0, 2, 1, 12}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb4, -1, 16, 1, 2, 586406201480, 0, 1, 1, 12}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xb4, -1, 8, 1, 2, 567489872400, 0, 2, 1, 12}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb4, -1, 8, 1, 2, 586406201480, 0, 1, 1, 12}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xb4, -1, 8, 1, 2, 550293209600, 0, 2, 1, 12}, // (subframe number :9,19,29,39)
{0xb4, -1, 4, 1, -1, 567489872400, 0, 1, 1, 12}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb4, -1, 4, 1, -1, 567489872400, 0, 2, 1, 12}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb4, -1, 4, 1, 2, 586406201480, 0, 1, 1, 12}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xb4, -1, 2, 1, -1, 551911719040, 2, 2, 1, 12}, // (subframe number :7,15,23,31,39)
{0xb4, -1, 2, 1, -1, 567489872400, 0, 1, 1, 12}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb4, -1, 2, 1, -1, 567489872400, 0, 2, 1, 12}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb4, -1, 2, 1, -1, 586406201480, 0, 1, 1, 12}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xb4, -1, 1, 0, -1, 549756338176, 2, 2, 1, 12}, // (subframe number :19, 39)
{0xb4, -1, 1, 0, -1, 687195422720, 0, 1, 1, 12}, // (subframe number :17, 19, 37, 39)
{0xb4, -1, 1, 0, -1, 567489331200, 2, 1, 1, 12}, // (subframe number :24,29,34,39)
{0xb4, -1, 1, 0, -1, 550293209600, 2, 2, 1, 12}, // (subframe number :9,19,29,39)
{0xb4, -1, 1, 0, -1, 550293209600, 0, 2, 1, 12}, // (subframe number :9,19,29,39)
{0xb4, -1, 1, 0, -1, 551911719040, 0, 1, 1, 12}, // (subframe number :7,15,23,31,39)
{0xb4, -1, 1, 0, -1, 551911719040, 0, 2, 1, 12}, // (subframe number :7,15,23,31,39)
{0xb4, -1, 1, 0, -1, 586405642240, 0, 1, 1, 12}, // (subframe number :23,27,31,35,39)
{0xb4, -1, 1, 0, -1, 586405642240, 2, 2, 1, 12}, // (subframe number :23,27,31,35,39)
{0xb4, -1, 1, 0, -1, 698880, 0, 1, 1, 12}, // (subframe number :9,11,13,15,17,19)
{0xb4, -1, 1, 0, -1, 10920, 2, 1, 1, 12}, // (subframe number :3,5,7,9,11,13)
{0xb4, -1, 1, 0, -1, 567489872400, 0, 1, 1, 12}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb4, -1, 1, 0, -1, 567489872400, 2, 2, 1, 12}, // (subframe number :4,9,14,19,24,29,34,39)
{0xb4, -1, 1, 0, -1, 965830828032, 2, 2, 1, 12}, // (subframe number :13,14,15, 29,30,31,37,38,39)
{0xb4, -1, 1, 0, -1, 586406201480, 0, 1, 1, 12}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xb4, -1, 1, 0, -1, 586406201480, 2, 1, 1, 12}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xb4, -1, 1, 0, -1, 44739240, 2, 1, 1, 12}, // (subframe number :3, 5, 7, …, 23,25)
{0xb4, -1, 1, 0, -1, 44739240, 0, 2, 1, 12}, // (subframe number :3, 5, 7, …, 23,25)
{0xb4, -1, 1, 0, -1, 733007751850, 0, 1, 1, 12}, // (subframe number :1,3,5,7,…,37,39)
{0xb4, -1, 1, 0, -1, 1099511627775, 2, 1, 1, 12}, // (subframe number :0, 1, 2,…, 39)
{0xc0, -1, 16, 1, -1, 567489872400, 0, 2, 7, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc0, -1, 16, 1, -1, 586406201480, 0, 1, 7, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc0, -1, 8, 1, -1, 567489872400, 0, 1, 7, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc0, -1, 8, 1, -1, 586406201480, 0, 1, 7, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc0, -1, 8, 1, 2, 550293209600, 0, 2, 7, 2}, // (subframe number :9,19,29,39)
{0xc0, -1, 4, 1, -1, 567489872400, 0, 1, 7, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc0, -1, 4, 1, -1, 567489872400, 0, 2, 7, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc0, -1, 4, 1, -1, 586406201480, 0, 1, 7, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc0, -1, 2, 1, -1, 551911719040, 0, 2, 7, 2}, // (subframe number :7,15,23,31,39)
{0xc0, -1, 2, 1, -1, 567489872400, 0, 1, 7, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc0, -1, 2, 1, -1, 567489872400, 0, 2, 7, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc0, -1, 2, 1, -1, 586406201480, 0, 1, 7, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc0, -1, 1, 0, -1, 549756338176, 8, 1, 3, 2}, // (subframe number :19,39)
{0xc0, -1, 1, 0, -1, 168, 0, 1, 7, 2}, // (subframe number :3,5,7)
{0xc0, -1, 1, 0, -1, 567489331200, 8, 1, 3, 2}, // (subframe number :24,29,34,39)
{0xc0, -1, 1, 0, -1, 550293209600, 8, 2, 3, 2}, // (subframe number :9,19,29,39)
{0xc0, -1, 1, 0, -1, 687195422720, 0, 1, 7, 2}, // (subframe number :17,19,37,39)
{0xc0, -1, 1, 0, -1, 550293209600, 0, 2, 7, 2}, // (subframe number :9,19,29,39)
{0xc0, -1, 1, 0, -1, 586405642240, 8, 1, 3, 2}, // (subframe number :23,27,31,35,39)
{0xc0, -1, 1, 0, -1, 551911719040, 0, 1, 7, 2}, // (subframe number :7,15,23,31,39)
{0xc0, -1, 1, 0, -1, 586405642240, 0, 1, 7, 2}, // (subframe number :23,27,31,35,39)
{0xc0, -1, 1, 0, -1, 10920, 8, 1, 3, 2}, // (subframe number :3,5,7,9,11,13)
{0xc0, -1, 1, 0, -1, 567489872400, 8, 1, 3, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc0, -1, 1, 0, -1, 567489872400, 0, 1, 7, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc0, -1, 1, 0, -1, 965830828032, 8, 2, 3, 2}, // (subframe number :13,14,15, 29,30,31,37,38,39)
{0xc0, -1, 1, 0, -1, 586406201480, 8, 1, 3, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc0, -1, 1, 0, -1, 586406201480, 0, 1, 7, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc0, -1, 1, 0, -1, 733007751850, 0, 1, 7, 2}, // (subframe number :1,3,5,7,…,37,39)
{0xc0, -1, 1, 0, -1, 1099511627775, 8, 1, 3, 2}, // (subframe number :0,1,2,…,39)
{0xc2, -1, 16, 1, -1, 567489872400, 0, 2, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc2, -1, 16, 1, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc2, -1, 8, 1, -1, 567489872400, 0, 2, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc2, -1, 8, 1, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc2, -1, 8, 1, 2, 550293209600, 0, 2, 2, 6}, // (subframe number :9,19,29,39)
{0xc2, -1, 4, 1, -1, 567489872400, 0, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc2, -1, 4, 1, -1, 567489872400, 0, 2, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc2, -1, 4, 1, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc2, -1, 2, 1, -1, 551911719040, 2, 2, 2, 6}, // (subframe number :7,15,23,31,39)
{0xc2, -1, 2, 1, -1, 567489872400, 0, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc2, -1, 2, 1, -1, 567489872400, 0, 2, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc2, -1, 2, 1, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc2, -1, 1, 0, -1, 549756338176, 2, 1, 2, 6}, // (subframe number :19,39)
{0xc2, -1, 1, 0, -1, 168, 0, 1, 2, 6}, // (subframe number :3,5,7)
{0xc2, -1, 1, 0, -1, 567489331200, 7, 1, 1, 6}, // (subframe number :24,29,34,39)
{0xc2, -1, 1, 0, -1, 550293209600, 7, 2, 1, 6}, // (subframe number :9,19,29,39)
{0xc2, -1, 1, 0, -1, 687195422720, 0, 1, 2, 6}, // (subframe number :17,19,37,39)
{0xc2, -1, 1, 0, -1, 550293209600, 2, 2, 2, 6}, // (subframe number :9,19,29,39)
{0xc2, -1, 1, 0, -1, 551911719040, 2, 1, 2, 6}, // (subframe number :7,15,23,31,39)
{0xc2, -1, 1, 0, -1, 10920, 7, 1, 1, 6}, // (subframe number :3,5,7,9,11,13)
{0xc2, -1, 1, 0, -1, 586405642240, 7, 2, 1, 6}, // (subframe number :23,27,31,35,39)
{0xc2, -1, 1, 0, -1, 586405642240, 0, 1, 2, 6}, // (subframe number :23,27,31,35,39)
{0xc2, -1, 1, 0, -1, 567489872400, 7, 2, 1, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc2, -1, 1, 0, -1, 567489872400, 2, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xc2, -1, 1, 0, -1, 965830828032, 7, 2, 1, 6}, // (subframe number :13,14,15, 29,30,31,37,38,39)
{0xc2, -1, 1, 0, -1, 586406201480, 7, 1, 1, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc2, -1, 1, 0, -1, 586406201480, 0, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xc2, -1, 1, 0, -1, 733007751850, 0, 1, 2, 6}, // (subframe number :1,3,5,7,…,37,39)
{0xc2, -1, 1, 0, -1, 1099511627775, 7, 1, 1, 6}, // (subframe number :0,1,2,…,39)
{0xa1, 0xb1, 16, 1, -1, 567489872400, 2, 1, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, 0xb1, 16, 1, -1, 586406201480, 2, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, 0xb1, 8, 1, -1, 567489872400, 2, 1, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, 0xb1, 8, 1, -1, 586406201480, 2, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, 0xb1, 4, 1, -1, 567489872400, 2, 1, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, 0xb1, 4, 1, -1, 586406201480, 2, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, 0xb1, 2, 1, -1, 567489872400, 2, 1, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, 0xb1, 1, 0, -1, 549756338176, 8, 1, 3, 2}, // (subframe number :19,39)
{0xa1, 0xb1, 1, 0, -1, 550293209600, 8, 1, 3, 2}, // (subframe number :9,19,29,39)
{0xa1, 0xb1, 1, 0, -1, 687195422720, 2, 1, 6, 2}, // (subframe number :17,19,37,39)
{0xa1, 0xb1, 1, 0, -1, 550293209600, 2, 2, 6, 2}, // (subframe number :9,19,29,39)
{0xa1, 0xb1, 1, 0, -1, 586405642240, 8, 1, 3, 2}, // (subframe number :23,27,31,35,39)
{0xa1, 0xb1, 1, 0, -1, 551911719040, 2, 1, 6, 2}, // (subframe number :7,15,23,31,39)
{0xa1, 0xb1, 1, 0, -1, 586405642240, 2, 1, 6, 2}, // (subframe number :23,27,31,35,39)
{0xa1, 0xb1, 1, 0, -1, 567489872400, 8, 1, 3, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, 0xb1, 1, 0, -1, 567489872400, 2, 1, 6, 2}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa1, 0xb1, 1, 0, -1, 586406201480, 2, 1, 6, 2}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa1, 0xb1, 1, 0, -1, 733007751850, 2, 1, 6, 2}, // (subframe number :1,3,5,7,…,37,39)
{0xa2, 0xb2, 16, 1, -1, 567489872400, 2, 1, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, 0xb2, 16, 1, -1, 586406201480, 2, 1, 3, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, 0xb2, 8, 1, -1, 567489872400, 2, 1, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, 0xb2, 8, 1, -1, 586406201480, 2, 1, 3, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, 0xb2, 4, 1, -1, 567489872400, 2, 1, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, 0xb2, 4, 1, -1, 586406201480, 2, 1, 3, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, 0xb2, 2, 1, -1, 567489872400, 2, 1, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, 0xb2, 1, 0, -1, 549756338176, 6, 1, 2, 4}, // (subframe number :19,39)
{0xa2, 0xb2, 1, 0, -1, 550293209600, 6, 1, 2, 4}, // (subframe number :9,19,29,39)
{0xa2, 0xb2, 1, 0, -1, 687195422720, 2, 1, 3, 4}, // (subframe number :17,19,37,39)
{0xa2, 0xb2, 1, 0, -1, 550293209600, 2, 2, 3, 4}, // (subframe number :9,19,29,39)
{0xa2, 0xb2, 1, 0, -1, 586405642240, 6, 1, 2, 4}, // (subframe number :23,27,31,35,39)
{0xa2, 0xb2, 1, 0, -1, 551911719040, 2, 1, 3, 4}, // (subframe number :7,15,23,31,39)
{0xa2, 0xb2, 1, 0, -1, 586405642240, 2, 1, 3, 4}, // (subframe number :23,27,31,35,39)
{0xa2, 0xb2, 1, 0, -1, 567489872400, 6, 1, 2, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, 0xb2, 1, 0, -1, 567489872400, 2, 1, 3, 4}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa2, 0xb2, 1, 0, -1, 586406201480, 2, 1, 3, 4}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa2, 0xb2, 1, 0, -1, 733007751850, 2, 1, 3, 4}, // (subframe number :1,3,5,7,…,37,39)
{0xa3, 0xb3, 16, 1, -1, 567489872400, 2, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, 0xb3, 16, 1, -1, 586406201480, 2, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, 0xb3, 8, 1, -1, 567489872400, 2, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, 0xb3, 8, 1, -1, 586406201480, 2, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, 0xb3, 4, 1, -1, 567489872400, 2, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, 0xb3, 4, 1, -1, 586406201480, 2, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, 0xb3, 2, 1, -1, 567489872400, 2, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, 0xb3, 1, 0, -1, 549756338176, 2, 1, 2, 6}, // (subframe number :19,39)
{0xa3, 0xb3, 1, 0, -1, 550293209600, 2, 1, 2, 6}, // (subframe number :9,19,29,39)
{0xa3, 0xb3, 1, 0, -1, 687195422720, 2, 1, 2, 6}, // (subframe number :17,19,37,39)
{0xa3, 0xb3, 1, 0, -1, 550293209600, 2, 2, 2, 6}, // (subframe number :9,19,29,39)
{0xa3, 0xb3, 1, 0, -1, 551911719040, 2, 1, 2, 6}, // (subframe number :7,15,23,31,39)
{0xa3, 0xb3, 1, 0, -1, 586405642240, 2, 1, 2, 6}, // (subframe number :23,27,31,35,39)
{0xa3, 0xb3, 1, 0, -1, 586405642240, 2, 2, 2, 6}, // (subframe number :23,27,31,35,39)
{0xa3, 0xb3, 1, 0, -1, 567489872400, 2, 1, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, 0xb3, 1, 0, -1, 567489872400, 2, 2, 2, 6}, // (subframe number :4,9,14,19,24,29,34,39)
{0xa3, 0xb3, 1, 0, -1, 586406201480, 2, 1, 2, 6}, // (subframe number :3,7,11,15,19,23,27,31,35,39)
{0xa3, 0xb3, 1, 0, -1, 733007751850, 2, 1, 2, 6} // (subframe number :1,3,5,7,…,37,39)
};
int get_format0(uint8_t index,
uint8_t unpaired,
frequency_range_t frequency_range){
uint16_t format=0;
if (unpaired) {
if (frequency_range==FR1)
format = table_6_3_3_2_3_prachConfig_Index[index][0];
else
format = table_6_3_3_2_4_prachConfig_Index[index][0];
}
else {
if (frequency_range==FR1)
format = table_6_3_3_2_2_prachConfig_Index[index][0];
else
AssertFatal(0==1,"no paired spectrum for FR2\n");
}
return format;
}
const int64_t *get_prach_config_info(frequency_range_t freq_range, uint8_t index, uint8_t unpaired)
{
const int64_t *prach_config_info_p;
if (freq_range == FR2) { //FR2
prach_config_info_p = table_6_3_3_2_4_prachConfig_Index[index];
}
else { // FR1
if (unpaired)
prach_config_info_p = table_6_3_3_2_3_prachConfig_Index[index];
else
prach_config_info_p = table_6_3_3_2_2_prachConfig_Index[index];
} // FR2 / FR1
return prach_config_info_p;
}
void find_aggregation_candidates(uint8_t *aggregation_level,
uint8_t *nr_of_candidates,
const NR_SearchSpace_t *ss,
int L)
{
AssertFatal(L>=1 && L<=16,"L %d not ok\n", L);
*nr_of_candidates = 0;
switch(L) {
case 1:
if (ss->nrofCandidates->aggregationLevel1 != NR_SearchSpace__nrofCandidates__aggregationLevel1_n0) {
*aggregation_level = 1;
*nr_of_candidates = ss->nrofCandidates->aggregationLevel1;
}
break;
case 2:
if (ss->nrofCandidates->aggregationLevel2 != NR_SearchSpace__nrofCandidates__aggregationLevel2_n0) {
*aggregation_level = 2;
*nr_of_candidates = ss->nrofCandidates->aggregationLevel2;
}
break;
case 4:
if (ss->nrofCandidates->aggregationLevel4 != NR_SearchSpace__nrofCandidates__aggregationLevel4_n0) {
*aggregation_level = 4;
*nr_of_candidates = ss->nrofCandidates->aggregationLevel4;
}
break;
case 8:
if (ss->nrofCandidates->aggregationLevel8 != NR_SearchSpace__nrofCandidates__aggregationLevel8_n0) {
*aggregation_level = 8;
*nr_of_candidates = ss->nrofCandidates->aggregationLevel8;
}
break;
case 16:
if (ss->nrofCandidates->aggregationLevel16 != NR_SearchSpace__nrofCandidates__aggregationLevel16_n0) {
*aggregation_level = 16;
*nr_of_candidates = ss->nrofCandidates->aggregationLevel16;
}
break;
}
}
void set_monitoring_periodicity_offset(NR_SearchSpace_t *ss,
uint16_t period,
uint16_t offset) {
switch(period) {
case 1:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1;
break;
case 2:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2;
ss->monitoringSlotPeriodicityAndOffset->choice.sl2 = offset;
break;
case 4:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4;
ss->monitoringSlotPeriodicityAndOffset->choice.sl4 = offset;
break;
case 5:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5;
ss->monitoringSlotPeriodicityAndOffset->choice.sl5 = offset;
break;
case 8:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8;
ss->monitoringSlotPeriodicityAndOffset->choice.sl8 = offset;
break;
case 10:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10;
ss->monitoringSlotPeriodicityAndOffset->choice.sl10 = offset;
break;
case 16:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16;
ss->monitoringSlotPeriodicityAndOffset->choice.sl16 = offset;
break;
case 20:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20;
ss->monitoringSlotPeriodicityAndOffset->choice.sl20 = offset;
break;
case 40:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40;
ss->monitoringSlotPeriodicityAndOffset->choice.sl40 = offset;
break;
case 80:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80;
ss->monitoringSlotPeriodicityAndOffset->choice.sl80 = offset;
break;
case 160:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160;
ss->monitoringSlotPeriodicityAndOffset->choice.sl160 = offset;
break;
case 320:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320;
ss->monitoringSlotPeriodicityAndOffset->choice.sl320 = offset;
break;
case 640:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640;
ss->monitoringSlotPeriodicityAndOffset->choice.sl640 = offset;
break;
case 1280:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280;
ss->monitoringSlotPeriodicityAndOffset->choice.sl1280 = offset;
break;
case 2560:
ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560;
ss->monitoringSlotPeriodicityAndOffset->choice.sl2560 = offset; break;
default:
AssertFatal(1==0,"Invalid monitoring slot periodicity value\n");
break;
}
}
int get_nr_prach_occasion_info_from_index(uint8_t index,
uint32_t pointa,
uint8_t mu,
uint8_t unpaired,
uint16_t *format,
uint8_t *start_symbol,
uint8_t *N_t_slot,
uint8_t *N_dur,
uint8_t *N_RA_slot,
uint16_t *N_RA_sfn,
uint8_t *max_association_period)
{
int x;
uint64_t s_map;
uint8_t format2 = 0xff;
if (pointa > 2016666) { //FR2
x = table_6_3_3_2_4_prachConfig_Index[index][2];
s_map = table_6_3_3_2_4_prachConfig_Index[index][5];
*N_RA_sfn += count_bits64(s_map);
*N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe
*max_association_period = 160/(x * 10);
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
*start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];//multiple prach occasions in diff slot
*N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8];
*N_dur = table_6_3_3_2_4_prachConfig_Index[index][9];
if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1)
format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1];
*format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8);
LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n",
index,
pointa,
mu,
unpaired,
*start_symbol,
*N_t_slot,
*N_dur,
*N_RA_sfn);
}
return 1;
}
else {
if (unpaired) {
x = table_6_3_3_2_3_prachConfig_Index[index][2];
s_map = table_6_3_3_2_3_prachConfig_Index[index][4];
*N_RA_sfn += count_bits64(s_map);
*N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
*max_association_period = 160/(x * 10);
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
*start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5];
*N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7];
*N_dur = table_6_3_3_2_3_prachConfig_Index[index][8];
if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1)
format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1];
*format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8);
LOG_D(NR_MAC,"Getting Total PRACH info from index %d (col %lu ) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n",
index, table_6_3_3_2_3_prachConfig_Index[index][6],
pointa,
mu,
unpaired,
*start_symbol,
*N_t_slot,
*N_dur,
*N_RA_sfn);
}
return 1;
}
else { // FDD
x = table_6_3_3_2_2_prachConfig_Index[index][2];
s_map = table_6_3_3_2_2_prachConfig_Index[index][4];
*N_RA_sfn += count_bits64(s_map);
*N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6];
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
*start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
*N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7];
*N_dur = table_6_3_3_2_2_prachConfig_Index[index][8];
if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1)
format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1];
*format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8);
LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n",
index,
pointa,
mu,
unpaired,
*start_symbol,
*N_t_slot,
*N_dur);
}
return 1;
}
}
}
int get_nr_prach_info_from_index(uint8_t index,
int frame,
int slot,
uint32_t pointa,
uint8_t mu,
uint8_t unpaired,
uint16_t *format,
uint8_t *start_symbol,
uint8_t *N_t_slot,
uint8_t *N_dur,
uint16_t *RA_sfn_index,
uint8_t *N_RA_slot,
uint8_t *config_period)
{
int x,y;
int64_t s_map;
uint8_t format2 = 0xff;
if (pointa > 2016666) { //FR2
int y2;
uint8_t slot_60khz;
x = table_6_3_3_2_4_prachConfig_Index[index][2];
y = table_6_3_3_2_4_prachConfig_Index[index][3];
y2 = table_6_3_3_2_4_prachConfig_Index[index][4];
// checking n_sfn mod x = y
if ((frame % x) == y || (frame % x) == y2) {
slot_60khz = slot >> (mu - 2); // in table slots are numbered wrt 60kHz
s_map = table_6_3_3_2_4_prachConfig_Index[index][5];
if ((s_map >> slot_60khz) & 0x01) {
for(int i = 0; i <= slot_60khz ;i++) {
if ((s_map >> i) & 0x01) {
(*RA_sfn_index)++;
}
}
}
if (((s_map >> slot_60khz) & 0x01)) {
*N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe
if (mu == 3) {
if ((*N_RA_slot == 1) && (slot % 2 == 0) )
return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot
}
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
*config_period = x;
*start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];
*N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8];
*N_dur = table_6_3_3_2_4_prachConfig_Index[index][9];
if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1)
format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1];
*format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8);
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u\n",
frame,
slot,
index,
pointa,
mu,
unpaired,
*start_symbol,
*N_t_slot,
*N_dur,
*N_RA_slot,
*RA_sfn_index);
}
return 1;
}
else
return 0; // no prach in current slot
}
else
return 0; // no prach in current frame
}
else {
uint8_t subframe;
if (unpaired) {
x = table_6_3_3_2_3_prachConfig_Index[index][2];
y = table_6_3_3_2_3_prachConfig_Index[index][3];
if ((frame % x) == y) {
subframe = slot >> mu;
s_map = table_6_3_3_2_3_prachConfig_Index[index][4];
if ((s_map >> subframe) & 0x01) {
for(int i = 0; i <= subframe ;i++) {
if ((s_map >> i) & 0x01) {
(*RA_sfn_index)++;
}
}
}
if ((s_map >> subframe) & 0x01 ) {
*N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
if (mu == 1 && index >= 67) {
if ((*N_RA_slot <= 1) && (slot % 2 == 0))
return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
}
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL) {
*config_period = x;
*start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5];
*N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7];
*N_dur = table_6_3_3_2_3_prachConfig_Index[index][8];
if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1)
format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1];
*format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8);
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n",
frame,
slot,
index,
table_6_3_3_2_3_prachConfig_Index[index][6],
pointa,
mu,
unpaired,
*start_symbol,
*N_t_slot,
*N_dur,
*N_RA_slot,
*RA_sfn_index);
}
return 1;
}
else
return 0; // no prach in current slot
}
else
return 0; // no prach in current frame
}
else { // FDD
x = table_6_3_3_2_2_prachConfig_Index[index][2];
y = table_6_3_3_2_2_prachConfig_Index[index][3];
if ((frame % x) == y) {
subframe = slot >> mu;
s_map = table_6_3_3_2_2_prachConfig_Index[index][4];
if ((s_map>>subframe) & 0x01) {
*N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
if (mu == 1) {
if ((*N_RA_slot <= 1) && (slot % 2 == 0)){
return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
}
}
for(int i = 0; i <= subframe ; i++) {
if ((s_map >> i) & 0x01) {
(*RA_sfn_index)++;
}
}
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
*start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
*config_period = x;
*N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7];
*N_dur = table_6_3_3_2_2_prachConfig_Index[index][8];
if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1)
format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1];
*format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8);
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n",
frame,
slot,
index,
pointa,
mu,
unpaired,
*start_symbol,
*N_t_slot,
*N_dur);
}
return 1;
}
else
return 0; // no prach in current slot
}
else
return 0; // no prach in current frame
}
}
}
//Table 6.3.3.1-3: Mapping from logical index i to sequence number u for preamble formats with L_RA = 839
static const uint16_t table_63313[838] = {
129, 710, 140, 699, 120, 719, 210, 629, 168, 671, 84, 755, 105, 734, 93, 746, 70, 769, 60, 779, 2, 837, 1, 838, 56,
783, 112, 727, 148, 691, 80, 759, 42, 797, 40, 799, 35, 804, 73, 766, 146, 693, 31, 808, 28, 811, 30, 809, 27, 812,
29, 810, 24, 815, 48, 791, 68, 771, 74, 765, 178, 661, 136, 703, 86, 753, 78, 761, 43, 796, 39, 800, 20, 819, 21,
818, 95, 744, 202, 637, 190, 649, 181, 658, 137, 702, 125, 714, 151, 688, 217, 622, 128, 711, 142, 697, 122, 717, 203, 636,
118, 721, 110, 729, 89, 750, 103, 736, 61, 778, 55, 784, 15, 824, 14, 825, 12, 827, 23, 816, 34, 805, 37, 802, 46,
793, 207, 632, 179, 660, 145, 694, 130, 709, 223, 616, 228, 611, 227, 612, 132, 707, 133, 706, 143, 696, 135, 704, 161, 678,
201, 638, 173, 666, 106, 733, 83, 756, 91, 748, 66, 773, 53, 786, 10, 829, 9, 830, 7, 832, 8, 831, 16, 823, 47,
792, 64, 775, 57, 782, 104, 735, 101, 738, 108, 731, 208, 631, 184, 655, 197, 642, 191, 648, 121, 718, 141, 698, 149, 690,
216, 623, 218, 621, 152, 687, 144, 695, 134, 705, 138, 701, 199, 640, 162, 677, 176, 663, 119, 720, 158, 681, 164, 675, 174,
665, 171, 668, 170, 669, 87, 752, 169, 670, 88, 751, 107, 732, 81, 758, 82, 757, 100, 739, 98, 741, 71, 768, 59, 780,
65, 774, 50, 789, 49, 790, 26, 813, 17, 822, 13, 826, 6, 833, 5, 834, 33, 806, 51, 788, 75, 764, 99, 740, 96,
743, 97, 742, 166, 673, 172, 667, 175, 664, 187, 652, 163, 676, 185, 654, 200, 639, 114, 725, 189, 650, 115, 724, 194, 645,
195, 644, 192, 647, 182, 657, 157, 682, 156, 683, 211, 628, 154, 685, 123, 716, 139, 700, 212, 627, 153, 686, 213, 626, 215,
624, 150, 689, 225, 614, 224, 615, 221, 618, 220, 619, 127, 712, 147, 692, 124, 715, 193, 646, 205, 634, 206, 633, 116, 723,
160, 679, 186, 653, 167, 672, 79, 760, 85, 754, 77, 762, 92, 747, 58, 781, 62, 777, 69, 770, 54, 785, 36, 803, 32,
807, 25, 814, 18, 821, 11, 828, 4, 835, 3, 836, 19, 820, 22, 817, 41, 798, 38, 801, 44, 795, 52, 787, 45, 794,
63, 776, 67, 772, 72, 767, 76, 763, 94, 745, 102, 737, 90, 749, 109, 730, 165, 674, 111, 728, 209, 630, 204, 635, 117,
722, 188, 651, 159, 680, 198, 641, 113, 726, 183, 656, 180, 659, 177, 662, 196, 643, 155, 684, 214, 625, 126, 713, 131, 708,
219, 620, 222, 617, 226, 613, 230, 609, 232, 607, 262, 577, 252, 587, 418, 421, 416, 423, 413, 426, 411, 428, 376, 463, 395,
444, 283, 556, 285, 554, 379, 460, 390, 449, 363, 476, 384, 455, 388, 451, 386, 453, 361, 478, 387, 452, 360, 479, 310, 529,
354, 485, 328, 511, 315, 524, 337, 502, 349, 490, 335, 504, 324, 515, 323, 516, 320, 519, 334, 505, 359, 480, 295, 544, 385,
454, 292, 547, 291, 548, 381, 458, 399, 440, 380, 459, 397, 442, 369, 470, 377, 462, 410, 429, 407, 432, 281, 558, 414, 425,
247, 592, 277, 562, 271, 568, 272, 567, 264, 575, 259, 580, 237, 602, 239, 600, 244, 595, 243, 596, 275, 564, 278, 561, 250,
589, 246, 593, 417, 422, 248, 591, 394, 445, 393, 446, 370, 469, 365, 474, 300, 539, 299, 540, 364, 475, 362, 477, 298, 541,
312, 527, 313, 526, 314, 525, 353, 486, 352, 487, 343, 496, 327, 512, 350, 489, 326, 513, 319, 520, 332, 507, 333, 506, 348,
491, 347, 492, 322, 517, 330, 509, 338, 501, 341, 498, 340, 499, 342, 497, 301, 538, 366, 473, 401, 438, 371, 468, 408, 431,
375, 464, 249, 590, 269, 570, 238, 601, 234, 605, 257, 582, 273, 566, 255, 584, 254, 585, 245, 594, 251, 588, 412, 427, 372,
467, 282, 557, 403, 436, 396, 443, 392, 447, 391, 448, 382, 457, 389, 450, 294, 545, 297, 542, 311, 528, 344, 495, 345, 494,
318, 521, 331, 508, 325, 514, 321, 518, 346, 493, 339, 500, 351, 488, 306, 533, 289, 550, 400, 439, 378, 461, 374, 465, 415,
424, 270, 569, 241, 598, 231, 608, 260, 579, 268, 571, 276, 563, 409, 430, 398, 441, 290, 549, 304, 535, 308, 531, 358, 481,
316, 523, 293, 546, 288, 551, 284, 555, 368, 471, 253, 586, 256, 583, 263, 576, 242, 597, 274, 565, 402, 437, 383, 456, 357,
482, 329, 510, 317, 522, 307, 532, 286, 553, 287, 552, 266, 573, 261, 578, 236, 603, 303, 536, 356, 483, 355, 484, 405, 434,
404, 435, 406, 433, 235, 604, 267, 572, 302, 537, 309, 530, 265, 574, 233, 606, 367, 472, 296, 543, 336, 503, 305, 534, 373,
466, 280, 559, 279, 560, 419, 420, 240, 599, 258, 581, 229, 610};
uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config,
uint8_t nb_preambles,
uint8_t unpaired,
frequency_range_t frequency_range) {
uint8_t config_index = rach_config->rach_ConfigGeneric.prach_ConfigurationIndex;
uint8_t ncs_index = rach_config->rach_ConfigGeneric.zeroCorrelationZoneConfig;
uint16_t format0 = get_format0(config_index, unpaired, frequency_range);
uint16_t NCS = get_NCS(ncs_index, format0, rach_config->restrictedSetConfig);
uint16_t L_ra = (rach_config->prach_RootSequenceIndex.present==NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139) ? 139 : 839;
uint16_t r,u,index,q,d_u,n_shift_ra,n_shift_ra_bar,d_start;
uint32_t w;
uint8_t found_preambles = 0;
uint8_t found_sequences = 0;
if (rach_config->restrictedSetConfig == 0) {
if (NCS == 0) return nb_preambles;
else {
r = L_ra/NCS;
AssertFatal(r > 0, "bad r: L_ra %d, NCS %d\n", L_ra, NCS);
found_sequences = (nb_preambles/r) + (nb_preambles%r!=0); //ceil(nb_preambles/r)
LOG_D(MAC, "Computing NR root sequences: found %u sequences\n", found_sequences);
return (found_sequences);
}
}
else{
index = rach_config->prach_RootSequenceIndex.choice.l839;
while (found_preambles < nb_preambles) {
u = table_63313[index%(L_ra-1)];
q = 0;
while (((q*u)%L_ra) != 1) q++;
if (q < 420) d_u = q;
else d_u = L_ra - q;
uint16_t n_group_ra = 0;
if (rach_config->restrictedSetConfig == 1) {
if ( (d_u<280) && (d_u>=NCS) ) {
n_shift_ra = d_u/NCS;
d_start = (d_u<<1) + (n_shift_ra * NCS);
n_group_ra = L_ra/d_start;
n_shift_ra_bar = max(0,(L_ra-(d_u<<1)-(n_group_ra*d_start))/L_ra);
} else if ( (d_u>=280) && (d_u<=((L_ra - NCS)>>1)) ) {
n_shift_ra = (L_ra - (d_u<<1))/NCS;
d_start = L_ra - (d_u<<1) + (n_shift_ra * NCS);
n_group_ra = d_u/d_start;
n_shift_ra_bar = min(n_shift_ra,max(0,(d_u- (n_group_ra*d_start))/NCS));
} else {
n_shift_ra = 0;
n_shift_ra_bar = 0;
}
w = n_shift_ra*n_group_ra + n_shift_ra_bar;
found_preambles += w;
found_sequences++;
}
else {
AssertFatal(1==0,"Procedure to find nb of sequences for restricted type B not implemented yet");
}
}
LOG_D(MAC, "Computing NR root sequences: found %u sequences\n", found_sequences);
return found_sequences;
}
}
// TS 38.211 Table 7.4.1.1.2-3: PDSCH DMRS positions l' within a slot for single-symbol DMRS and intra-slot frequency hopping disabled.
// The first 4 colomns are PDSCH mapping type A and the last 4 colomns are PDSCH mapping type B.
// When l' = l0, it is represented by 1
// E.g. when symbol duration is 12 in colomn 7, value 1057 ('10000100001') which means l' = l0, 5, 10.
static const int32_t table_7_4_1_1_2_3_pdsch_dmrs_positions_l[13][8] = {
// Duration in symbols
{-1, -1, -1, -1, 1, 1, 1, 1}, // 2 // (DMRS l' position)
{0, 0, 0, 0, 1, 1, 1, 1}, // 3 // (DMRS l' position)
{0, 0, 0, 0, 1, 1, 1, 1}, // 4 // (DMRS l' position)
{0, 0, 0, 0, 1, 17, 17, 17}, // 5 // (DMRS l' position)
{0, 0, 0, 0, 1, 17, 17, 17}, // 6 // (DMRS l' position)
{0, 0, 0, 0, 1, 17, 17, 17}, // 7 // (DMRS l' position)
{0, 128, 128, 128, 1, 65, 73, 73}, // 8 // (DMRS l' position)
{0, 128, 128, 128, 1, 129, 145, 145}, // 9 // (DMRS l' position)
{0, 512, 576, 576, 1, 129, 145, 145}, // 10 // (DMRS l' position)
{0, 512, 576, 576, 1, 257, 273, 585}, // 11 // (DMRS l' position)
{0, 512, 576, 2336, 1, 513, 545, 585}, // 12 // (DMRS l' position)
{0, 2048, 2176, 2336, 1, 513, 545, 585}, // 13 // (DMRS l' position)
{0, 2048, 2176, 2336, -1, -1, -1, -1}, // 14 // (DMRS l' position)
};
// TS 38.211 Table 7.4.1.1.2-4: PDSCH DMRS positions l' within a slot for double-symbol DMRS and intra-slot frequency hopping disabled.
// The first 4 colomns are PDSCH mapping type A and the last 4 colomns are PDSCH mapping type B.
// When l' = l0, it is represented by 1
static const int32_t table_7_4_1_1_2_4_pdsch_dmrs_positions_l[12][8] = {
// Duration in symbols
{-1, -1, -1, -1, -1, -1, -1, -1}, //<4 // (DMRS l' position)
{0, 0, -1, -1, -1, -1, -1, -1}, // 4 // (DMRS l' position)
{0, 0, -1, -1, 3, 3, -1, -1}, // 5 // (DMRS l' position)
{0, 0, -1, -1, 3, 3, -1, -1}, // 6 // (DMRS l' position)
{0, 0, -1, -1, 3, 3, -1, -1}, // 7 // (DMRS l' position)
{0, 0, -1, -1, 3, 99, -1, -1}, // 8 // (DMRS l' position)
{0, 0, -1, -1, 3, 99, -1, -1}, // 9 // (DMRS l' position)
{0, 768, -1, -1, 3, 387, -1, -1}, // 10 // (DMRS l' position)
{0, 768, -1, -1, 3, 387, -1, -1}, // 11 // (DMRS l' position)
{0, 768, -1, -1, 3, 771, -1, -1}, // 12 // (DMRS l' position)
{0, 3072, -1, -1, 3, 771, -1, -1}, // 13 // (DMRS l' position)
{0, 3072, -1, -1, -1, -1, -1, -1}, // 14 // (DMRS l' position)
};
// TS 38.211 Table 6.4.1.1.3-3: PUSCH DMRS positions l' within a slot for single-symbol DMRS and intra-slot frequency hopping disabled.
// The first 4 colomns are PUSCH mapping type A and the last 4 colomns are PUSCH mapping type B.
// When l' = l0, it is represented by 1
// E.g. when symbol duration is 12 in colomn 7, value 1057 ('10000100001') which means l' = l0, 5, 10.
static const int32_t table_6_4_1_1_3_3_pusch_dmrs_positions_l[12][8] = {
// Duration in symbols
{-1, -1, -1, -1, 1, 1, 1, 1}, //<4 // (DMRS l' position)
{0, 0, 0, 0, 1, 1, 1, 1}, // 4 // (DMRS l' position)
{0, 0, 0, 0, 1, 17, 17, 17}, // 5 // (DMRS l' position)
{0, 0, 0, 0, 1, 17, 17, 17}, // 6 // (DMRS l' position)
{0, 0, 0, 0, 1, 17, 17, 17}, // 7 // (DMRS l' position)
{0, 128, 128, 128, 1, 65, 73, 73}, // 8 // (DMRS l' position)
{0, 128, 128, 128, 1, 65, 73, 73}, // 9 // (DMRS l' position)
{0, 512, 576, 576, 1, 257, 273, 585}, // 10 // (DMRS l' position)
{0, 512, 576, 576, 1, 257, 273, 585}, // 11 // (DMRS l' position)
{0, 512, 576, 2336, 1, 1025, 1057, 585}, // 12 // (DMRS l' position)
{0, 2048, 2176, 2336, 1, 1025, 1057, 585}, // 13 // (DMRS l' position)
{0, 2048, 2176, 2336, 1, 1025, 1057, 585}, // 14 // (DMRS l' position)
};
// TS 38.211 Table 6.4.1.1.3-4: PUSCH DMRS positions l' within a slot for double-symbol DMRS and intra-slot frequency hopping disabled.
// The first 4 colomns are PUSCH mapping type A and the last 4 colomns are PUSCH mapping type B.
// When l' = l0, it is represented by 1
static const int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l[12][8] = {
// Duration in symbols
{-1, -1, -1, -1, -1, -1, -1, -1}, //<4 // (DMRS l' position)
{0, 0, -1, -1, -1, -1, -1, -1}, // 4 // (DMRS l' position)
{0, 0, -1, -1, 3, 3, -1, -1}, // 5 // (DMRS l' position)
{0, 0, -1, -1, 3, 3, -1, -1}, // 6 // (DMRS l' position)
{0, 0, -1, -1, 3, 3, -1, -1}, // 7 // (DMRS l' position)
{0, 0, -1, -1, 3, 99, -1, -1}, // 8 // (DMRS l' position)
{0, 0, -1, -1, 3, 99, -1, -1}, // 9 // (DMRS l' position)
{0, 768, -1, -1, 3, 387, -1, -1}, // 10 // (DMRS l' position)
{0, 768, -1, -1, 3, 387, -1, -1}, // 11 // (DMRS l' position)
{0, 768, -1, -1, 3, 1539, -1, -1}, // 12 // (DMRS l' position)
{0, 3072, -1, -1, 3, 1539, -1, -1}, // 13 // (DMRS l' position)
{0, 3072, -1, -1, 3, 1539, -1, -1}, // 14 // (DMRS l' position)
};
// TS 38.212
static const uint16_t table_7_3_1_1_2_2_1layer[28] = {0, 1, 2, 3, 12, 13, 14, 15, 16, 17, 18, 19, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
static const uint16_t table_7_3_1_1_2_2_2layers[22] = {4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24,
25, 26, 27, 48, 49, 50, 51, 52, 53, 54, 55};
static const uint16_t table_7_3_1_1_2_2_3layers[7] = {10, 28, 29, 56, 57, 58, 59};
static const uint16_t table_7_3_1_1_2_2_4layers[5] = {11, 30, 31, 60, 61};
static const uint16_t table_7_3_1_1_2_2B_1layer[16] = {0, 1, 2, 3, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 24, 25};
static const uint16_t table_7_3_1_1_2_2B_2layers[14] = {4, 5, 6, 7, 8, 9, 13, 26, 27, 28, 29, 30, 31, 32};
static const uint16_t table_7_3_1_1_2_2B_3layers[3] = {10, 14, 33};
static const uint16_t table_7_3_1_1_2_2B_4layers[3] = {11, 34, 35};
static const uint16_t table_7_3_1_1_2_2A_1layer[16] = {0, 1, 2, 3, 12, 13, 14, 15, 16, 17, 18, 19, 20, 10, 21, 22};
static const uint16_t table_7_3_1_1_2_2A_2layers[14] = {4, 5, 6, 7, 8, 9, 11, 23, 24, 25, 26, 27, 28, 29};
static const uint16_t table_7_3_1_1_2_3A[16] = {0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 14, 15};
static const uint16_t table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[6] = {0, 1, 3, 4, 5, 6};
static const uint16_t table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[3] = {2, 7, 8};
static const uint16_t table_7_3_1_1_2_4A_1layer[3] = {0, 1, 3};
static const uint16_t table_7_3_1_1_2_28[3][15] = {
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
static const uint16_t table_7_3_1_1_2_29[3][15] = {
{0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0},
};
static const uint16_t table_7_3_1_1_2_30[3][15] = {
{0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 6, 0, 0, 0, 0},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0},
};
static const uint16_t table_7_3_1_1_2_31[3][15] = {
{0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 6, 0, 0, 0, 0},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
};
static const uint16_t table_7_3_1_1_2_32[3][15] = {
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
int x_overhead,
uint8_t numdmrscdmgroupnodata,
uint8_t tb_scaling) {
LOG_D(MAC, "TBS calculation\n");
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_rel15 = &pdsch_pdu->pdsch_pdu_rel15;
uint16_t N_PRB_oh = x_overhead;
uint8_t N_PRB_DMRS;
if (pdsch_rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) {
// if no data in dmrs cdm group is 1 only even REs have no data
// if no data in dmrs cdm group is 2 both odd and even REs have no data
N_PRB_DMRS = numdmrscdmgroupnodata*6;
}
else {
N_PRB_DMRS = numdmrscdmgroupnodata*4;
}
uint8_t N_sh_symb = pdsch_rel15->NrOfSymbols;
uint8_t Imcs = pdsch_rel15->mcsIndex[0];
uint16_t dmrs_length = get_num_dmrs(pdsch_rel15->dlDmrsSymbPos);
uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS*dmrs_length - N_PRB_oh;
LOG_D(MAC, "N_RE_prime %d for %d symbols %d DMRS per PRB and %d overhead\n", N_RE_prime, N_sh_symb, N_PRB_DMRS, N_PRB_oh);
uint32_t TBS=0;
/*uint8_t mcs_table = config.pdsch_config.mcs_table.value;
uint8_t ss_type = params_rel15.search_space_type;
uint8_t dci_format = params_rel15.dci_format;
get_table_idx(mcs_table, dci_format, rnti_type, ss_type);*/
uint8_t table_idx = 0;
uint16_t R = nr_get_code_rate_dl(Imcs, table_idx);
uint8_t Qm = nr_get_Qm_dl(Imcs, table_idx);
TBS = nr_compute_tbs(Qm,
R,
pdsch_rel15->rbSize,
N_sh_symb,
N_PRB_DMRS*dmrs_length,
N_PRB_oh,
tb_scaling,
pdsch_rel15->nrOfLayers)>>3;
pdsch_rel15->targetCodeRate[0] = R;
pdsch_rel15->qamModOrder[0] = Qm;
pdsch_rel15->TBSize[0] = TBS;
// pdsch_rel15->nb_mod_symbols = N_RE_prime*pdsch_rel15->n_prb*pdsch_rel15->nb_codewords;
pdsch_rel15->mcsTable[0] = table_idx;
LOG_D(MAC, "TBS %d bytes: N_PRB_DMRS %d N_sh_symb %d N_PRB_oh %d R %d Qm %d table %d nb_symbols %d\n",
TBS, N_PRB_DMRS, N_sh_symb, N_PRB_oh, R, Qm, table_idx,N_RE_prime*pdsch_rel15->rbSize*pdsch_rel15->NrOfCodewords );
}
// the following tables contain 10 times the value reported in 214 (in line with SCF specification and to avoid fractional values)
//Table 5.1.3.1-1 of 38.214
static const uint16_t Table_51311[32][2] = {{2, 1200}, {2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260},
{2, 6020}, {2, 6790}, {4, 3400}, {4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160},
{4, 6580}, {6, 4380}, {6, 4660}, {6, 5170}, {6, 5670}, {6, 6160}, {6, 6660}, {6, 7190},
{6, 7720}, {6, 8220}, {6, 8730}, {6, 9100}, {6, 9480}, {2, 0}, {4, 0}, {6, 0}};
//Table 5.1.3.1-2 of 38.214
// Imcs values 20 and 26 have been multiplied by 2 to avoid the floating point
static const uint16_t Table_51312[32][2] = {{2, 1200}, {2, 1930}, {2, 3080}, {2, 4490}, {2, 6020}, {4, 3780}, {4, 4340},
{4, 4900}, {4, 5530}, {4, 6160}, {4, 6580}, {6, 4660}, {6, 5170}, {6, 5670},
{6, 6160}, {6, 6660}, {6, 7190}, {6, 7720}, {6, 8220}, {6, 8730}, {8, 6825},
{8, 7110}, {8, 7540}, {8, 7970}, {8, 8410}, {8, 8850}, {8, 9165}, {8, 9480},
{2, 0}, {4, 0}, {6, 0}, {8, 0}};
//Table 5.1.3.1-3 of 38.214
static const uint16_t Table_51313[32][2] = {{2, 300}, {2, 400}, {2, 500}, {2, 640}, {2, 780}, {2, 990}, {2, 1200}, {2, 1570},
{2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260}, {2, 6020}, {4, 3400},
{4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160}, {6, 4380}, {6, 4660}, {6, 5170},
{6, 5670}, {6, 6160}, {6, 6660}, {6, 7190}, {6, 7720}, {2, 0}, {4, 0}, {6, 0}};
static const uint16_t Table_61411[32][2] = {{2, 1200}, {2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490},
{2, 5260}, {2, 6020}, {2, 6790}, {4, 3400}, {4, 3780}, {4, 4340}, {4, 4900},
{4, 5530}, {4, 6160}, {4, 6580}, {6, 4660}, {6, 5170}, {6, 5670}, {6, 6160},
{6, 6660}, {6, 7190}, {6, 7720}, {6, 8220}, {6, 8730}, {6, 9100}, {6, 9480},
{2, 0}, {2, 0}, {4, 0}, {6, 0}};
static const uint16_t Table_61412[32][2] = {{2, 300}, {2, 400}, {2, 500}, {2, 640}, {2, 780}, {2, 990}, {2, 1200},
{2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260},
{2, 6020}, {2, 6790}, {4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160},
{4, 6580}, {4, 6990}, {4, 7720}, {6, 5670}, {6, 6160}, {6, 6660}, {6, 7720},
{2, 0}, {2, 0}, {4, 0}, {6, 0}};
uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][0]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][0]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][0]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx);
return 0;
}
}
uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][1]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][1]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][1]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx);
return 0;
}
}
uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][0]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][0]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][0]);
break;
case 3:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61411[Imcs][0]);
break;
case 4:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61412[Imcs][0]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx);
return 0;
}
}
uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 0:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51311[Imcs][1]);
break;
case 1:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51312[Imcs][1]);
break;
case 2:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_51313[Imcs][1]);
break;
case 3:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61411[Imcs][1]);
break;
case 4:
if (Imcs > 31) {
LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,31])\n", Imcs);
return 0;
}
return (Table_61412[Imcs][1]);
break;
default:
LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx);
return 0;
}
}
// Table 5.1.2.2.1-1 38.214
uint8_t getRBGSize(uint16_t bwp_size, long rbg_size_config)
{
AssertFatal(bwp_size < 276, "Invalid BWP Size %d\n", bwp_size);
if (bwp_size < 37)
return (rbg_size_config ? 4 : 2);
if (bwp_size < 73)
return (rbg_size_config ? 8 : 4);
if (bwp_size < 145)
return (rbg_size_config ? 16 : 8);
else
return 16;
}
uint8_t getNRBG(uint16_t bwp_size, uint16_t bwp_start, long rbg_size_config)
{
uint8_t rbg_size = getRBGSize(bwp_size, rbg_size_config);
return (uint8_t)ceil((float)(bwp_size + (bwp_start % rbg_size)) / (float)rbg_size);
}
uint8_t getAntPortBitWidth(NR_SetupRelease_DMRS_DownlinkConfig_t *typeA, NR_SetupRelease_DMRS_DownlinkConfig_t *typeB) {
uint8_t nbitsA = 0;
uint8_t nbitsB = 0;
uint8_t type,length,nbits;
if (typeA != NULL) {
type = (typeA->choice.setup->dmrs_Type==NULL) ? 1:2;
length = (typeA->choice.setup->maxLength==NULL) ? 1:2;
nbitsA = type + length + 2;
if (typeB == NULL) return nbitsA;
}
if (typeB != NULL) {
type = (typeB->choice.setup->dmrs_Type==NULL) ? 1:2;
length = (typeB->choice.setup->maxLength==NULL) ? 1:2;
nbitsB = type + length + 2;
if (typeA == NULL) return nbitsB;
}
nbits = (nbitsA > nbitsB) ? nbitsA : nbitsB;
return nbits;
}
/*******************************************************************
*
* NAME : get_l0_ul
*
* PARAMETERS : mapping_type : PUSCH mapping type
* dmrs_typeA_position : higher layer parameter
*
* RETURN : demodulation reference signal for PUSCH
*
* DESCRIPTION : see TS 38.211 V15.4.0 Demodulation reference signals for PUSCH
*
*********************************************************************/
uint8_t get_l0_ul(uint8_t mapping_type, uint8_t dmrs_typeA_position)
{
return ((mapping_type==typeA)?dmrs_typeA_position:0);
}
int32_t get_l_prime(uint8_t duration_in_symbols,
uint8_t mapping_type,
pusch_dmrs_AdditionalPosition_t additional_pos,
pusch_maxLength_t pusch_maxLength,
uint8_t start_symbol,
uint8_t dmrs_typeA_position)
{
LOG_D(NR_MAC,
"PUSCH NrofSymbols:%d, startSymbol:%d, mappingtype:%d, dmrs_TypeA_Position:%d additional_pos:%d, pusch_maxLength:%d\n",
duration_in_symbols,
start_symbol,
mapping_type,
dmrs_typeA_position,
additional_pos,
pusch_maxLength);
// Section 6.4.1.1.3 in Spec 38.211
// For PDSCH Mapping TypeA, ld is duration between first OFDM of the slot and last OFDM symbol of the scheduled PUSCH resources
// For TypeB, ld is the duration of the scheduled PUSCH resources
uint8_t ld = (mapping_type == typeA) ? (duration_in_symbols + start_symbol) : duration_in_symbols;
uint8_t l0 = (dmrs_typeA_position == NR_MIB__dmrs_TypeA_Position_pos2) ? 2 : 3 ;
uint8_t colomn = additional_pos;
if (mapping_type == typeB)
colomn += 4;
uint8_t row;
if (ld < 4)
row = 0;
else
row = ld - 3;
uint32_t l_prime;
if (pusch_maxLength == pusch_len1) {
l_prime = table_6_4_1_1_3_3_pusch_dmrs_positions_l[row][colomn];
l0 = 1 << l0;
}
else {
l_prime = table_6_4_1_1_3_4_pusch_dmrs_positions_l[row][colomn];
l0 = 1<<l0 | 1<<(l0+1);
}
LOG_D(NR_MAC, "PUSCH - l0:%d, ld:%d,row:%d, column:%d, addpos:%d, maxlen:%d\n", l0, ld, row, colomn, additional_pos, pusch_maxLength);
AssertFatal(l_prime>=0,"invalid l_prime < 0\n");
l_prime = (mapping_type == typeA) ? (l_prime | l0) : (l_prime << start_symbol);
LOG_D(MAC, " PUSCH DMRS MASK in HEX:%x\n", l_prime);
return l_prime;
}
/*******************************************************************
*
* NAME : get_L_ptrs
*
* PARAMETERS : mcs(i) higher layer parameter in PTRS-UplinkConfig
* I_mcs MCS index used for PUSCH
* mcs_table 0 for table 5.1.3.1-1, 1 for table 5.1.3.1-1
*
* RETURN : the parameter L_ptrs
*
* DESCRIPTION : 3GPP TS 38.214 section 6.2.3.1
*
*********************************************************************/
uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint8_t mcs_table) {
uint8_t mcs4;
if(mcs_table == 0)
mcs4 = 29;
else
mcs4 = 28;
if (I_mcs < mcs1) {
LOG_D(PHY, "PUSH PT-RS is not present.\n");
return -1;
} else if (I_mcs >= mcs1 && I_mcs < mcs2)
return 2;
else if (I_mcs >= mcs2 && I_mcs < mcs3)
return 1;
else if (I_mcs >= mcs3 && I_mcs < mcs4)
return 0;
else {
LOG_D(NR_MAC, "PT-RS time-density determination is obtained from the DCI for the same transport block in the initial transmission\n");
return -1;
}
}
/*******************************************************************
*
* NAME : get_K_ptrs
*
* PARAMETERS : nrb0, nrb1 PTRS uplink configuration
* N_RB number of RBs scheduled for PUSCH
*
* RETURN : the parameter K_ptrs
*
* DESCRIPTION : 3GPP TS 38.214 6.2.3 Table 6.2.3.1-2
*
*********************************************************************/
uint8_t get_K_ptrs(uint32_t nrb0, uint32_t nrb1, uint32_t N_RB)
{
if (N_RB < nrb0) {
LOG_D(PHY,"PUSH PT-RS is not present.\n");
return -1;
} else if (N_RB >= nrb0 && N_RB < nrb1)
return 2;
else
return 4;
}
/*******************************************************************
*
* NAME : get_nr_srs_offset
*
* PARAMETERS : periodicityAndOffset for SRS
*
* RETURN : the offset parameter for SRS
*
*********************************************************************/
uint16_t get_nr_srs_offset(NR_SRS_PeriodicityAndOffset_t periodicityAndOffset) {
switch(periodicityAndOffset.present) {
case NR_SRS_PeriodicityAndOffset_PR_sl1:
return periodicityAndOffset.choice.sl1;
case NR_SRS_PeriodicityAndOffset_PR_sl2:
return periodicityAndOffset.choice.sl2;
case NR_SRS_PeriodicityAndOffset_PR_sl4:
return periodicityAndOffset.choice.sl4;
case NR_SRS_PeriodicityAndOffset_PR_sl5:
return periodicityAndOffset.choice.sl5;
case NR_SRS_PeriodicityAndOffset_PR_sl8:
return periodicityAndOffset.choice.sl8;
case NR_SRS_PeriodicityAndOffset_PR_sl10:
return periodicityAndOffset.choice.sl10;
case NR_SRS_PeriodicityAndOffset_PR_sl16:
return periodicityAndOffset.choice.sl16;
case NR_SRS_PeriodicityAndOffset_PR_sl20:
return periodicityAndOffset.choice.sl20;
case NR_SRS_PeriodicityAndOffset_PR_sl32:
return periodicityAndOffset.choice.sl32;
case NR_SRS_PeriodicityAndOffset_PR_sl40:
return periodicityAndOffset.choice.sl40;
case NR_SRS_PeriodicityAndOffset_PR_sl64:
return periodicityAndOffset.choice.sl64;
case NR_SRS_PeriodicityAndOffset_PR_sl80:
return periodicityAndOffset.choice.sl80;
case NR_SRS_PeriodicityAndOffset_PR_sl160:
return periodicityAndOffset.choice.sl160;
case NR_SRS_PeriodicityAndOffset_PR_sl320:
return periodicityAndOffset.choice.sl320;
case NR_SRS_PeriodicityAndOffset_PR_sl640:
return periodicityAndOffset.choice.sl640;
case NR_SRS_PeriodicityAndOffset_PR_sl1280:
return periodicityAndOffset.choice.sl1280;
case NR_SRS_PeriodicityAndOffset_PR_sl2560:
return periodicityAndOffset.choice.sl2560;
case NR_SRS_PeriodicityAndOffset_PR_NOTHING:
LOG_W(NR_MAC,"NR_SRS_PeriodicityAndOffset_PR_NOTHING\n");
return 0;
default:
return 0;
}
}
// Set the transform precoding status according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16:
// - "UE procedure for applying transform precoding on PUSCH"
long get_transformPrecoding(const NR_UE_UL_BWP_t *current_UL_BWP, nr_dci_format_t dci_format, uint8_t configuredGrant)
{
if (configuredGrant
&& current_UL_BWP
&& current_UL_BWP->configuredGrantConfig
&& current_UL_BWP->configuredGrantConfig->transformPrecoder)
return *current_UL_BWP->configuredGrantConfig->transformPrecoder;
if (dci_format == NR_UL_DCI_FORMAT_0_1
&& current_UL_BWP
&& current_UL_BWP->pusch_Config
&& current_UL_BWP->pusch_Config->transformPrecoder)
return *current_UL_BWP->pusch_Config->transformPrecoder;
if (current_UL_BWP && current_UL_BWP->rach_ConfigCommon && current_UL_BWP->rach_ConfigCommon->msg3_transformPrecoder)
return NR_PUSCH_Config__transformPrecoder_enabled;
return NR_PUSCH_Config__transformPrecoder_disabled;
}
uint8_t get_pusch_nb_antenna_ports(NR_PUSCH_Config_t *pusch_Config,
NR_SRS_Config_t *srs_config,
dci_field_t srs_resource_indicator)
{
uint8_t n_antenna_port = 1;
if (get_softmodem_params()->phy_test == 1) {
// temporary hack to allow UL-MIMO in phy-test mode without SRS
n_antenna_port = *pusch_Config->maxRank;
}
else {
uint8_t sri = srs_resource_indicator.nbits > 0 ? srs_resource_indicator.val : 0;
if(srs_config != NULL) {
for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) {
NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
// When multiple SRS resources are configured by SRS-ResourceSet with usage set to 'codebook',
// the UE shall expect that higher layer parameters nrofSRS-Ports in SRS-Resource in SRS-ResourceSet
// shall be configured with the same value for all these SRS resources.
if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_codebook) {
NR_SRS_Resource_t *srs_resource = srs_config->srs_ResourceToAddModList->list.array[sri];
AssertFatal(srs_resource, "SRS resource indicated by DCI does not exist\n");
n_antenna_port = 1 << srs_resource->nrofSRS_Ports;
break;
}
}
}
}
return n_antenna_port;
}
// #define DEBUG_SRS_RESOURCE_IND
uint8_t compute_srs_resource_indicator(long *maxMIMO_Layers,
NR_PUSCH_Config_t *pusch_Config,
NR_SRS_Config_t *srs_config,
nr_srs_feedback_t *srs_feedback,
uint32_t *val)
{
uint8_t nbits = 0;
// SRI occupies a number of bits which is dependent upon the uplink transmission scheme, and it is used to determine
// the antenna ports and uplink transmission beam to use for PUSCH transmission. In the case of codebook based
// transmission, the SRI is used to select between SRS Resources belonging to different antenna panels
// (kind of directional antenna). There can be up to 2 SRS Resources (2 antenna panels). In the case of non-codebook
// based transmission, the SRI is used to select one or more SRS Resources from a set of N_SRS resources. The number
// of SRS Resources selected corresponds to the number of layers (rank) to be transmitted.
if (val) {
*val = 0;
}
if (srs_config && pusch_Config && pusch_Config->txConfig != NULL) {
if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook) {
#ifdef DEBUG_SRS_RESOURCE_IND
LOG_I(NR_MAC, "*pusch_Config->txConfig = NR_PUSCH_Config__txConfig_codebook\n");
#endif
// TS 38.212 - Section 7.3.1.1.2: SRS resource indicator has ceil(log2(N_SRS)) bits according to
// Tables 7.3.1.1.2-32, 7.3.1.1.2-32A and 7.3.1.1.2-32B if the higher layer parameter txConfig = codebook,
// where N_SRS is the number of configured SRS resources in the SRS resource set configured by higher layer
// parameter srs-ResourceSetToAddModList, and associated with the higher layer parameter usage of value codeBook.
int count = 0;
for (int i=0; i<srs_config->srs_ResourceSetToAddModList->list.count; i++) {
if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_codebook) {
count++;
}
}
if (count>0) {
nbits = ceil(log2(count));
if (val && srs_feedback && count > 1) {
*val = table_7_3_1_1_2_32[count-2][srs_feedback->sri];
}
}
#ifdef DEBUG_SRS_RESOURCE_IND
LOG_I(NR_MAC, "srs_config->srs_ResourceSetToAddModList->list.count = %i\n", srs_config->srs_ResourceSetToAddModList->list.count);
LOG_I(NR_MAC, "count = %i\n", count);
#endif
} else {
#ifdef DEBUG_SRS_RESOURCE_IND
LOG_I(NR_MAC, "*pusch_Config->txConfig = NR_PUSCH_Config__txConfig_nonCodebook\n");
#endif
// TS 38.212 - Section 7.3.1.1.2: SRS resource indicator has ceil(log2(sum(k = 1 until min(Lmax,N_SRS) of binomial(N_SRS,k))))
// bits according to Tables 7.3.1.1.2-28/29/30/31 if the higher layer parameter txConfig = nonCodebook, where
// N_SRS is the number of configured SRS resources in the SRS resource set configured by higher layer parameter
// srs-ResourceSetToAddModList, and associated with the higher layer parameter usage of value nonCodeBook and:
//
// - if UE supports operation with maxMIMO-Layers and the higher layer parameter maxMIMO-Layers of
// PUSCH-ServingCellConfig of the serving cell is configured, Lmax is given by that parameter;
//
// - otherwise, Lmax is given by the maximum number of layers for PUSCH supported by the UE for the serving cell
// for non-codebook based operation.
int Lmax = 0;
if (maxMIMO_Layers != NULL)
Lmax = *maxMIMO_Layers;
else
AssertFatal(1 == 0, "MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n");
int lmin = 0;
int lsum = 0;
int count = 0;
for (int i = 0; i < srs_config->srs_ResourceSetToAddModList->list.count; i++) {
if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_nonCodebook) {
count++;
}
}
lmin = count < Lmax ? count : Lmax;
for (int k=1;k<=lmin;k++) {
lsum += binomial(count,k);
}
if (lsum>0) {
nbits = ceil(log2(lsum));
if (val && srs_feedback && nbits > 0) {
switch(Lmax) {
case 1:
*val = table_7_3_1_1_2_28[count-2][srs_feedback->sri];
break;
case 2:
*val = table_7_3_1_1_2_29[count-2][srs_feedback->sri];
break;
case 3:
*val = table_7_3_1_1_2_30[count-2][srs_feedback->sri];
break;
case 4:
*val = table_7_3_1_1_2_31[count-2][srs_feedback->sri];
break;
default:
LOG_E(NR_MAC, "%s (%d) - Invalid Lmax %d\n", __FUNCTION__, __LINE__, Lmax);
}
}
}
#ifdef DEBUG_SRS_RESOURCE_IND
LOG_I(NR_MAC, "srs_config->srs_ResourceSetToAddModList->list.count = %i\n", srs_config->srs_ResourceSetToAddModList->list.count);
LOG_I(NR_MAC, "count = %i\n", count);
LOG_I(NR_MAC, "Lmax = %i\n", Lmax);
LOG_I(NR_MAC, "lsum = %i\n", lsum);
#endif
}
}
return nbits;
}
uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
NR_SRS_Config_t *srs_config,
dci_field_t srs_resource_indicator,
nr_srs_feedback_t *srs_feedback,
const uint8_t *nrOfLayers,
uint32_t *val)
{
// It is only applicable to codebook based transmission. This field occupies 0 bits for non-codebook based
// transmission. It also occupies 0 bits for codebook based transmission using a single antenna port.
uint8_t nbits = 0;
if (val) {
*val = 0;
}
uint8_t pusch_antenna_ports = get_pusch_nb_antenna_ports(pusch_Config, srs_config, srs_resource_indicator);
if (!pusch_Config
|| (pusch_Config->txConfig != NULL && *pusch_Config->txConfig == NR_PUSCH_Config__txConfig_nonCodebook)
|| pusch_antenna_ports == 1) {
return nbits;
}
long max_rank = *pusch_Config->maxRank;
long *ul_FullPowerTransmission = pusch_Config->ext1 ? pusch_Config->ext1->ul_FullPowerTransmission_r16 : NULL;
long *codebookSubset = pusch_Config->codebookSubset;
if (pusch_antenna_ports == 2) {
if (max_rank == 1) {
// - 1 or 3 bits according to Table 7.3.1.1.2-5 for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission
// is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform
// precoder is enabled or disabled, and the values of higher layer parameters maxRank and codebookSubset;
// - 2 bits according to Table 7.3.1.1.2-5A for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
// fullpowerMode1, maxRank=1, and according to whether transform precoder is enabled or disabled, and the values
// of higher layer parameter codebookSubset;
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
nbits = 2;
if (val && srs_feedback) {
AssertFatal(srs_feedback->tpmi <= 2,"TPMI %d is invalid!\n", srs_feedback->tpmi);
*val = srs_feedback->tpmi;
}
} else {
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
nbits = 1;
if (val && srs_feedback) {
AssertFatal(srs_feedback->tpmi <= 1,"TPMI %d is invalid!\n", srs_feedback->tpmi);
*val = srs_feedback->tpmi;
}
} else {
nbits = 3;
if (val && srs_feedback) {
AssertFatal(srs_feedback->tpmi <= 5,"TPMI %d is invalid!\n", srs_feedback->tpmi);
*val = srs_feedback->tpmi;
}
}
}
} else {
// - 2 or 4 bits according to Table 7.3.1.1.2-4 for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission
// is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform
// precoder is enabled or disabled, and the values of higher layer parameters maxRank and codebookSubset;
// - 2 bits according to Table 7.3.1.1.2-4A for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
// fullpowerMode1, transform precoder is disabled, maxRank=2, and codebookSubset=nonCoherent;
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
nbits = 2;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 2) || (*nrOfLayers==2 && srs_feedback->tpmi == 0),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
*val = *nrOfLayers==1 ? table_7_3_1_1_2_4A_1layer[srs_feedback->tpmi] : 2;
}
} else {
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
nbits = 2;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 1) || (*nrOfLayers==2 && srs_feedback->tpmi == 0),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
*val = *nrOfLayers==1 ? srs_feedback->tpmi : 2;
}
} else {
nbits = 4;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 5) || (*nrOfLayers==2 && srs_feedback->tpmi <= 2),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
*val = *nrOfLayers==1 ? table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[srs_feedback->tpmi] :
table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[srs_feedback->tpmi];
}
}
}
}
} else if (pusch_antenna_ports == 4) {
if (max_rank == 1) {
// - 2, 4, or 5 bits according to Table 7.3.1.1.2-3 for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission
// is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform
// precoder is enabled or disabled, and the values of higher layer parameters maxRank, and codebookSubset;
// - 3 or 4 bits according to Table 7.3.1.1.2-3A for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
// fullpowerMode1, maxRank=1, and according to whether transform precoder is enabled or disabled, and the values
// of higher layer parameter codebookSubset;
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
nbits = 3;
if (val && srs_feedback) {
AssertFatal(srs_feedback->tpmi <= 3 || srs_feedback->tpmi == 13, "TPMI %d is invalid!\n", srs_feedback->tpmi);
}
} else {
nbits = 4;
if (val && srs_feedback) {
AssertFatal(srs_feedback->tpmi <= 15, "TPMI %d is invalid!\n", srs_feedback->tpmi);
}
}
if (val && srs_feedback) {
*val = table_7_3_1_1_2_3A[srs_feedback->tpmi];
}
} else {
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
nbits = 2;
if (val && srs_feedback) {
AssertFatal(srs_feedback->tpmi <= 3, "TPMI %d is invalid!\n", srs_feedback->tpmi);
}
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
nbits = 4;
if (val && srs_feedback) {
AssertFatal(srs_feedback->tpmi <= 11, "TPMI %d is invalid!\n", srs_feedback->tpmi);
}
} else {
nbits = 5;
if (val && srs_feedback) {
AssertFatal(srs_feedback->tpmi <= 27, "TPMI %d is invalid!\n", srs_feedback->tpmi);
}
}
if (val && srs_feedback) {
*val = srs_feedback->tpmi;
}
}
} else {
// - 4, 5, or 6 bits according to Table 7.3.1.1.2-2 for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission
// is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform
// precoder is enabled or disabled, and the values of higher layer parameters maxRank, and codebookSubset;
// - 4 or 5 bits according to Table 7.3.1.1.2-2A for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
// fullpowerMode1, maxRank=2, transform precoder is disabled, and according to the values of higher layer parameter
// codebookSubset;
// - 4 or 6 bits according to Table 7.3.1.1.2-2B for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission =
// fullpowerMode1, maxRank=3 or 4, transform precoder is disabled, and according to the values of higher layer
// parameter codebookSubset;
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
if (max_rank == 2) {
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
nbits = 4;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && (srs_feedback->tpmi <= 3 || srs_feedback->tpmi==13)) || (*nrOfLayers==2 && srs_feedback->tpmi <= 6),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
}
} else {
nbits = 5;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 15) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
}
}
if (val && srs_feedback) {
*val = *nrOfLayers==1 ? table_7_3_1_1_2_2A_1layer[srs_feedback->tpmi] : table_7_3_1_1_2_2A_2layers[srs_feedback->tpmi];
}
} else {
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
nbits = 4;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && (srs_feedback->tpmi <= 3 || srs_feedback->tpmi == 13)) || (*nrOfLayers==2 && srs_feedback->tpmi <= 6) ||
(*nrOfLayers==3 && srs_feedback->tpmi <= 1) || (*nrOfLayers==4 && srs_feedback->tpmi == 0),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
}
} else {
nbits = 6;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 15) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13) ||
(*nrOfLayers==3 && srs_feedback->tpmi <= 2) || (*nrOfLayers==4 && srs_feedback->tpmi <= 2),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
}
}
if (val && srs_feedback) {
switch (*nrOfLayers) {
case 1:
*val = table_7_3_1_1_2_2B_1layer[srs_feedback->tpmi];
break;
case 2:
*val = table_7_3_1_1_2_2B_2layers[srs_feedback->tpmi];
break;
case 3:
*val = table_7_3_1_1_2_2B_3layers[srs_feedback->tpmi];
break;
case 4:
*val = table_7_3_1_1_2_2B_4layers[srs_feedback->tpmi];
break;
default:
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
}
}
}
} else {
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
nbits = 4;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 3) || (*nrOfLayers==2 && srs_feedback->tpmi <= 5) ||
(*nrOfLayers==3 && srs_feedback->tpmi == 0) || (*nrOfLayers==4 && srs_feedback->tpmi == 0),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
}
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
nbits = 5;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 11) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13) ||
(*nrOfLayers==3 && srs_feedback->tpmi <= 2) || (*nrOfLayers==4 && srs_feedback->tpmi <= 2),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
}
} else {
nbits = 6;
if (val && srs_feedback) {
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 28) || (*nrOfLayers==2 && srs_feedback->tpmi <= 22) ||
(*nrOfLayers==3 && srs_feedback->tpmi <= 7) || (*nrOfLayers==4 && srs_feedback->tpmi <= 5),
"TPMI %d is invalid!\n", srs_feedback->tpmi);
}
}
if (val && srs_feedback) {
switch (*nrOfLayers) {
case 1:
*val = table_7_3_1_1_2_2_1layer[srs_feedback->tpmi];
break;
case 2:
*val = table_7_3_1_1_2_2_2layers[srs_feedback->tpmi];
break;
case 3:
*val = table_7_3_1_1_2_2_3layers[srs_feedback->tpmi];
break;
case 4:
*val = table_7_3_1_1_2_2_4layers[srs_feedback->tpmi];
break;
default:
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
}
}
}
}
}
return nbits;
}
NR_PDSCH_TimeDomainResourceAllocationList_t *get_dl_tdalist(const NR_UE_DL_BWP_t *DL_BWP,
int controlResourceSetId,
int ss_type,
nr_rnti_type_t rnti_type)
{
if (!DL_BWP)
return NULL;
// see table 5.1.2.1.1-1 in 38.214
if ((rnti_type == TYPE_CS_RNTI_ || rnti_type == TYPE_C_RNTI_ || rnti_type == TYPE_MCS_C_RNTI_)
&& !(ss_type == NR_SearchSpace__searchSpaceType_PR_common && controlResourceSetId == 0)
&& (DL_BWP->pdsch_Config && DL_BWP->pdsch_Config->pdsch_TimeDomainAllocationList))
return DL_BWP->pdsch_Config->pdsch_TimeDomainAllocationList->choice.setup;
else
return DL_BWP->tdaList_Common;
}
NR_PUSCH_TimeDomainResourceAllocationList_t *get_ul_tdalist(const NR_UE_UL_BWP_t *UL_BWP,
int controlResourceSetId,
int ss_type,
nr_rnti_type_t rnti_type)
{
if ((rnti_type == TYPE_CS_RNTI_ || rnti_type == TYPE_C_RNTI_ || rnti_type == TYPE_MCS_C_RNTI_)
&& !(ss_type == NR_SearchSpace__searchSpaceType_PR_common && controlResourceSetId == 0)
&& (UL_BWP->pusch_Config && UL_BWP->pusch_Config->pusch_TimeDomainAllocationList))
return UL_BWP->pusch_Config->pusch_TimeDomainAllocationList->choice.setup;
else
return UL_BWP->tdaList_Common;
}
uint16_t get_rb_bwp_dci(nr_dci_format_t format,
int ss_type,
uint16_t cset0_bwp_size,
uint16_t ul_bwp_size,
uint16_t dl_bwp_size,
uint16_t initial_ul_bwp_size,
uint16_t initial_dl_bwp_size)
{
uint16_t N_RB;
if (format == NR_UL_DCI_FORMAT_0_0 || format == NR_UL_DCI_FORMAT_0_1) {
if(format == NR_UL_DCI_FORMAT_0_0 && ss_type == NR_SearchSpace__searchSpaceType_PR_common)
N_RB = initial_ul_bwp_size;
else
N_RB = ul_bwp_size;
}
else {
if(format == NR_DL_DCI_FORMAT_1_0 && ss_type == NR_SearchSpace__searchSpaceType_PR_common) {
N_RB = cset0_bwp_size ? cset0_bwp_size : initial_dl_bwp_size;
}
else
N_RB = dl_bwp_size;
}
return N_RB;
}
// 32 HARQ processes supported in rel17, default is 8
int get_nrofHARQ_ProcessesForPDSCH(const NR_UE_ServingCell_Info_t *sc_info)
{
if (sc_info && sc_info->nrofHARQ_ProcessesForPDSCH_v1700)
return 32;
if (!sc_info || !sc_info->nrofHARQ_ProcessesForPDSCH)
return 8;
int IEvalues[] = {2, 4, 6, 10, 12, 16};
return IEvalues[*sc_info->nrofHARQ_ProcessesForPDSCH];
}
// 32 HARQ processes supported in rel17, default is 16
int get_nrofHARQ_ProcessesForPUSCH(const NR_UE_ServingCell_Info_t *sc_info)
{
if (sc_info && sc_info->nrofHARQ_ProcessesForPUSCH_r17)
return 32;
return 16;
}
static int get_nrofHARQ_bits_PDSCH(int dci_format, int num_dl_harq, NR_PDSCH_Config_t *dl_cfg)
{
// IF DCI Format 1_0 - then use 4 bits. Refer to Spec 38.212 section 7.3.1.2.1
int harqbits = 4;
if (dl_cfg && dl_cfg->ext3) {
// 5 bits if higher layer parameter harq-ProcessNumberSizeDCI-1-1 is configured, otherwise 4 bits
// Refer to Spec 38.212 section 7.3.1.2.2
if (dci_format == NR_DL_DCI_FORMAT_1_1 && dl_cfg->ext3->harq_ProcessNumberSizeDCI_1_1_r17) {
harqbits = 5;
AssertFatal(num_dl_harq == 32, "Incorrect configuration of DL HARQ processes %d\n",num_dl_harq);
}
}
return harqbits;
}
static int get_nrofHARQ_bits_PUSCH(int dci_format, int num_ul_harq, NR_PUSCH_Config_t *ul_cfg)
{
// IF DCI Format 0_0 - then use 4 bits. Refer to Spec 38.212 section 7.3.1.1.1
int harqbits = 4;
if (ul_cfg && ul_cfg->ext2) {
// 5 bits if higher layer parameter harq-ProcessNumberSizeDCI-0-1 is configured, otherwise 4 bits
// Refer to Spec 38.212 section 7.3.1.1.2
if (dci_format == NR_UL_DCI_FORMAT_0_1 && ul_cfg->ext2->harq_ProcessNumberSizeDCI_0_1_r17) {
harqbits = 5;
AssertFatal(num_ul_harq == 32, "Incorrect configuration of UL HARQ processes %d\n",num_ul_harq);
}
}
return harqbits;
}
uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP,
const NR_UE_UL_BWP_t *UL_BWP,
const NR_UE_ServingCell_Info_t *sc_info,
long pdsch_HARQ_ACK_Codebook,
dci_pdu_rel15_t *dci_pdu,
nr_dci_format_t format,
nr_rnti_type_t rnti_type,
NR_ControlResourceSet_t *coreset,
int bwp_id,
int ss_type,
uint16_t cset0_bwp_size,
uint16_t alt_size)
{
uint16_t size = 0;
uint16_t numRBG = 0;
long rbg_size_config;
int num_entries = 0;
NR_PDSCH_Config_t *pdsch_Config = DL_BWP ? DL_BWP->pdsch_Config : NULL;
NR_PUSCH_Config_t *pusch_Config = UL_BWP ? UL_BWP->pusch_Config : NULL;
NR_PUCCH_Config_t *pucch_Config = UL_BWP ? UL_BWP->pucch_Config : NULL;
NR_SRS_Config_t *srs_config = UL_BWP ? UL_BWP->srs_Config : NULL;
uint16_t N_RB = cset0_bwp_size;
if (DL_BWP)
N_RB = get_rb_bwp_dci(format,
ss_type,
cset0_bwp_size,
UL_BWP->BWPSize,
DL_BWP->BWPSize,
sc_info->initial_ul_BWPSize,
sc_info->initial_dl_BWPSize);
const int num_dl_harq = get_nrofHARQ_ProcessesForPDSCH(sc_info);
const int num_ul_harq = get_nrofHARQ_ProcessesForPUSCH(sc_info);
const int num_dlharqbits = get_nrofHARQ_bits_PDSCH(format, num_dl_harq, pdsch_Config);
const int num_ulharqbits = get_nrofHARQ_bits_PUSCH(format, num_ul_harq, pusch_Config);
switch(format) {
case NR_UL_DCI_FORMAT_0_0:
/// fixed: Format identifier 1, Hop flag 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2 Time Domain assgnmt 4 --20
size += 20;
// HARQ pid - 4bits , Spec 38.212 section 7.3.1.1.1
dci_pdu->harq_pid.nbits = 4;
dci_pdu->frequency_domain_assignment.nbits = (uint8_t)ceil(log2((N_RB * (N_RB + 1)) >>1)); // Freq domain assignment -- hopping scenario to be updated
size += dci_pdu->frequency_domain_assignment.nbits;
if(alt_size >= size)
size += alt_size - size; // Padding to match 1_0 size
else if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) {
dci_pdu->frequency_domain_assignment.nbits -= (size - alt_size);
size = alt_size;
}
// UL/SUL indicator assumed to be 0
break;
case NR_UL_DCI_FORMAT_0_1:
if (!UL_BWP) {
LOG_E(NR_MAC, "Error! Not possible to configure DCI format 01 without UL BWP.\n");
return 0;
}
/// fixed: Format identifier 1, MCS 5, NDI 1, RV 2, PUSCH TPC 2, ULSCH indicator 1 --12
size += 12;
// HARQ PID - 4/5 bits Spec 38.212 section 7.3.1.1.2
// 5 bits if higher layer parameter harq-ProcessNumberSizeDCI-0-1 is configured;otherwise 4 bits
dci_pdu->harq_pid.nbits = num_ulharqbits;
size += dci_pdu->harq_pid.nbits;
// Carrier indicator
if (sc_info->crossCarrierSchedulingConfig) {
dci_pdu->carrier_indicator.nbits = 3;
size += dci_pdu->carrier_indicator.nbits;
}
// UL/SUL indicator
if (sc_info->supplementaryUplink) {
dci_pdu->carrier_indicator.nbits = 1;
size += dci_pdu->ul_sul_indicator.nbits;
}
// BWP Indicator
if (sc_info->n_ul_bwp < 2)
dci_pdu->bwp_indicator.nbits = sc_info->n_ul_bwp;
else
dci_pdu->bwp_indicator.nbits = 2;
LOG_D(NR_MAC, "BWP indicator nbits %d, num UL BWPs %d\n", dci_pdu->bwp_indicator.nbits, sc_info->n_ul_bwp);
size += dci_pdu->bwp_indicator.nbits;
// Freq domain assignment
if (pusch_Config) {
if (pusch_Config->rbg_Size != NULL)
rbg_size_config = 1;
else
rbg_size_config = 0;
numRBG = getNRBG(UL_BWP->BWPSize, UL_BWP->BWPStart, rbg_size_config);
if (pusch_Config->resourceAllocation == 0)
dci_pdu->frequency_domain_assignment.nbits = numRBG;
else if (pusch_Config->resourceAllocation == 1)
dci_pdu->frequency_domain_assignment.nbits = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
else
dci_pdu->frequency_domain_assignment.nbits = ((int)ceil(log2((N_RB * (N_RB + 1)) >> 1)) > numRBG) ? (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)) + 1 : numRBG + 1;
}
else
dci_pdu->frequency_domain_assignment.nbits = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
LOG_D(NR_MAC, "PUSCH Frequency Domain Assignment nbits %d, N_RB %d\n", dci_pdu->frequency_domain_assignment.nbits, N_RB);
size += dci_pdu->frequency_domain_assignment.nbits;
// Time domain assignment
NR_PUSCH_TimeDomainResourceAllocationList_t *tdalistul = get_ul_tdalist(UL_BWP, coreset->controlResourceSetId, ss_type, rnti_type);
num_entries = tdalistul ? tdalistul->list.count : 16; // 16 in default table
dci_pdu->time_domain_assignment.nbits = (int)ceil(log2(num_entries));
LOG_D(NR_MAC, "PUSCH Time Domain Allocation nbits %d, pusch_Config %p\n", dci_pdu->time_domain_assignment.nbits, pusch_Config);
size += dci_pdu->time_domain_assignment.nbits;
// Frequency Hopping flag
if (pusch_Config &&
pusch_Config->frequencyHopping!=NULL &&
pusch_Config->resourceAllocation != NR_PUSCH_Config__resourceAllocation_resourceAllocationType0) {
dci_pdu->frequency_hopping_flag.nbits = 1;
size += 1;
}
// 1st DAI
if (pdsch_HARQ_ACK_Codebook == NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic)
dci_pdu->dai[0].nbits = 2;
else
dci_pdu->dai[0].nbits = 1;
size += dci_pdu->dai[0].nbits;
LOG_D(NR_MAC, "DAI1 nbits %d\n", dci_pdu->dai[0].nbits);
// 2nd DAI
if (sc_info->pdsch_CGB_Transmission) {
dci_pdu->dai[1].nbits = 2;
size += dci_pdu->dai[1].nbits;
}
// SRS resource indicator
dci_pdu->srs_resource_indicator.nbits =
compute_srs_resource_indicator(sc_info->maxMIMO_Layers_PUSCH, pusch_Config, srs_config, NULL, NULL);
size += dci_pdu->srs_resource_indicator.nbits;
LOG_D(NR_MAC, "dci_pdu->srs_resource_indicator.nbits %d\n", dci_pdu->srs_resource_indicator.nbits);
// Precoding info and number of layers
dci_pdu->precoding_information.nbits = compute_precoding_information(pusch_Config, srs_config, dci_pdu->srs_resource_indicator, NULL, NULL, NULL);
size += dci_pdu->precoding_information.nbits;
LOG_D(NR_MAC, "dci_pdu->precoding_informaiton.nbits=%d\n", dci_pdu->precoding_information.nbits);
// Antenna ports
long transformPrecoder = get_transformPrecoding(UL_BWP, format, 0);
NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = NULL;
int xa = 0;
int xb = 0;
if (pusch_Config && pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) {
NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup;
xa = ul_ant_bits(NR_DMRS_UplinkConfig, transformPrecoder);
}
if(pusch_Config &&
pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL){
NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup;
xb = ul_ant_bits(NR_DMRS_UplinkConfig, transformPrecoder);
}
if (xa>xb)
dci_pdu->antenna_ports.nbits = xa;
else
dci_pdu->antenna_ports.nbits = xb;
size += dci_pdu->antenna_ports.nbits;
LOG_D(NR_MAC,"dci_pdu->antenna_ports.nbits = %d\n",dci_pdu->antenna_ports.nbits);
// SRS request
if (sc_info->supplementaryUplink == NULL)
dci_pdu->srs_request.nbits = 2;
else
dci_pdu->srs_request.nbits = 3;
size += dci_pdu->srs_request.nbits;
// CSI request
if (sc_info->csi_MeasConfig != NULL) {
if (sc_info->csi_MeasConfig->reportTriggerSize != NULL) {
dci_pdu->csi_request.nbits = *sc_info->csi_MeasConfig->reportTriggerSize;
size += dci_pdu->csi_request.nbits;
}
}
// CBGTI
if (sc_info->pusch_CGB_Transmission) {
int num = sc_info->pusch_CGB_Transmission->maxCodeBlockGroupsPerTransportBlock;
dci_pdu->cbgti.nbits = 2 + (num<<1);
size += dci_pdu->cbgti.nbits;
}
// PTRS - DMRS association
if ( (NR_DMRS_UplinkConfig &&
NR_DMRS_UplinkConfig->phaseTrackingRS == NULL &&
transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) ||
transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled ||
(pusch_Config && pusch_Config->maxRank &&
*pusch_Config->maxRank==1) )
dci_pdu->ptrs_dmrs_association.nbits = 0;
else
dci_pdu->ptrs_dmrs_association.nbits = 2;
size += dci_pdu->ptrs_dmrs_association.nbits;
// beta offset indicator
if (pusch_Config &&
pusch_Config->uci_OnPUSCH!=NULL){
if (pusch_Config->uci_OnPUSCH->choice.setup->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_dynamic) {
dci_pdu->beta_offset_indicator.nbits = 2;
size += dci_pdu->beta_offset_indicator.nbits;
}
}
// DMRS sequence init
if (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) {
dci_pdu->dmrs_sequence_initialization.nbits = 1;
size += dci_pdu->dmrs_sequence_initialization.nbits;
}
break;
case NR_DL_DCI_FORMAT_1_0:
/// fixed: Format identifier 1, VRB2PRB 1, MCS 5, NDI 1, RV 2, HARQ PID 4, DAI 2, PUCCH TPC 2, PUCCH RInd 3, PDSCH to HARQ TInd 3 Time Domain assgnmt 4 -- 28
// 3GPP TS 38.212 Section 7.3.1.0: DCI size alignment
// Size of DCI format 1_0 is given by the size of CORESET 0 if CORESET 0 is configured for the cell and the size
// of initial DL bandwidth part if CORESET 0 is not configured for the cell
size = 28;
// HARQ pid - 4 bits. Spec 38.212 section 7.3.1.2.1
dci_pdu->harq_pid.nbits = 4;
dci_pdu->frequency_domain_assignment.nbits = (uint8_t)ceil(log2((N_RB * (N_RB + 1)) >> 1)); // Freq domain assignment
size += dci_pdu->frequency_domain_assignment.nbits;
if(ss_type == NR_SearchSpace__searchSpaceType_PR_ue_Specific && alt_size >= size)
size += alt_size - size; // Padding to match 0_0 size
dci_pdu->time_domain_assignment.nbits = 4;
dci_pdu->vrb_to_prb_mapping.nbits = 1;
break;
case NR_DL_DCI_FORMAT_1_1:
LOG_D(NR_MAC, "DCI_FORMAT 1_1 : pdsch_Config %p, pucch_Config %p\n", pdsch_Config, pucch_Config);
if (!DL_BWP) {
LOG_E(NR_MAC, "Error! Not possible to configure DCI format 11 without DL BWP.\n");
return 0;
}
// General note: 0 bits condition is ignored as default nbits is 0.
// Format identifier
size = 1;
// Carrier indicator
if (sc_info->crossCarrierSchedulingConfig) {
dci_pdu->carrier_indicator.nbits = 3;
size += dci_pdu->carrier_indicator.nbits;
}
// BWP Indicator
if (sc_info->n_dl_bwp < 2)
dci_pdu->bwp_indicator.nbits = sc_info->n_dl_bwp;
else
dci_pdu->bwp_indicator.nbits = 2;
size += dci_pdu->bwp_indicator.nbits;
// Freq domain assignment
if (pdsch_Config) rbg_size_config = pdsch_Config->rbg_Size;
else rbg_size_config = 0;
numRBG = getNRBG(DL_BWP->BWPSize, DL_BWP->BWPStart, rbg_size_config);
if (pdsch_Config && pdsch_Config->resourceAllocation == 0)
dci_pdu->frequency_domain_assignment.nbits = numRBG;
else if (pdsch_Config == NULL || pdsch_Config->resourceAllocation == 1)
dci_pdu->frequency_domain_assignment.nbits = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
else
dci_pdu->frequency_domain_assignment.nbits = ((int)ceil(log2((N_RB * (N_RB + 1)) >> 1)) > numRBG) ? (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)) + 1 : numRBG + 1;
size += dci_pdu->frequency_domain_assignment.nbits;
LOG_D(NR_MAC,"dci_pdu->frequency_domain_assignment.nbits %d (N_RB %d)\n",dci_pdu->frequency_domain_assignment.nbits,N_RB);
NR_PDSCH_TimeDomainResourceAllocationList_t *tdalist = get_dl_tdalist(DL_BWP, coreset->controlResourceSetId, ss_type, rnti_type);
num_entries = tdalist ? tdalist->list.count : 16; // 16 in default table
dci_pdu->time_domain_assignment.nbits = (int)ceil(log2(num_entries));
LOG_D(NR_MAC,"pdsch tda.nbits= %d\n",dci_pdu->time_domain_assignment.nbits);
size += dci_pdu->time_domain_assignment.nbits;
// VRB to PRB mapping
if (pdsch_Config &&
pdsch_Config->resourceAllocation == 1 &&
pdsch_Config->vrb_ToPRB_Interleaver != NULL) {
dci_pdu->vrb_to_prb_mapping.nbits = 1;
size += dci_pdu->vrb_to_prb_mapping.nbits;
}
// PRB bundling size indicator
if (pdsch_Config &&
pdsch_Config->prb_BundlingType.present == NR_PDSCH_Config__prb_BundlingType_PR_dynamicBundling) {
dci_pdu->prb_bundling_size_indicator.nbits = 1;
size += dci_pdu->prb_bundling_size_indicator.nbits;
}
// Rate matching indicator
NR_RateMatchPatternGroup_t *group1 = pdsch_Config ? pdsch_Config->rateMatchPatternGroup1 : NULL;
NR_RateMatchPatternGroup_t *group2 = pdsch_Config ? pdsch_Config->rateMatchPatternGroup2 : NULL;
if ((group1 != NULL) && (group2 != NULL))
dci_pdu->rate_matching_indicator.nbits = 2;
if ((group1 != NULL) != (group2 != NULL))
dci_pdu->rate_matching_indicator.nbits = 1;
size += dci_pdu->rate_matching_indicator.nbits;
// ZP CSI-RS trigger
if (pdsch_Config &&
pdsch_Config->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList != NULL) {
uint8_t nZP = pdsch_Config->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList->list.count;
dci_pdu->zp_csi_rs_trigger.nbits = (int)ceil(log2(nZP+1));
}
size += dci_pdu->zp_csi_rs_trigger.nbits;
// TB1- MCS 5, NDI 1, RV 2
size += 8;
// TB2
long *maxCWperDCI = pdsch_Config ? pdsch_Config->maxNrofCodeWordsScheduledByDCI : NULL;
if ((maxCWperDCI != NULL) && (*maxCWperDCI == 2)) {
size += 8;
}
// HARQ process number – 5 bits if higher layer parameter harq-ProcessNumberSizeDCI-1-1 is configured;
// otherwise 4 bits. Spec 38.212 Section 7.3.1.2.2
dci_pdu->harq_pid.nbits = num_dlharqbits;
size += dci_pdu->harq_pid.nbits;
// DAI
if (pdsch_HARQ_ACK_Codebook == NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic) { // FIXME in case of more than one serving cell
dci_pdu->dai[0].nbits = 2;
size += dci_pdu->dai[0].nbits;
}
LOG_D(NR_MAC,"dci_pdu->dai[0].nbits %d\n",dci_pdu->dai[0].nbits);
// TPC PUCCH
size += 2;
// PUCCH resource indicator
size += 3;
// PDSCH to HARQ timing indicator
uint8_t I = (pucch_Config && pucch_Config->dl_DataToUL_ACK) ? pucch_Config->dl_DataToUL_ACK->list.count : 8;
dci_pdu->pdsch_to_harq_feedback_timing_indicator.nbits = (int)ceil(log2(I));
size += dci_pdu->pdsch_to_harq_feedback_timing_indicator.nbits;
LOG_D(NR_MAC,"dci_pdu->pdsch_to_harq_feedback_timing_indicator.nbits %d\n",dci_pdu->pdsch_to_harq_feedback_timing_indicator.nbits);
// Antenna ports
NR_SetupRelease_DMRS_DownlinkConfig_t *typeA = pdsch_Config ? pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA : NULL;
NR_SetupRelease_DMRS_DownlinkConfig_t *typeB = pdsch_Config ? pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB : NULL;
AssertFatal(typeA!=NULL || typeB!=NULL, "either dmrs_typeA or typeB must be configured\n");
dci_pdu->antenna_ports.nbits = getAntPortBitWidth(typeA,typeB);
size += dci_pdu->antenna_ports.nbits;
LOG_D(NR_MAC,"dci_pdu->antenna_ports.nbits %d\n",dci_pdu->antenna_ports.nbits);
// Tx Config Indication
if (coreset->tci_PresentInDCI != NULL) {
dci_pdu->transmission_configuration_indication.nbits = 3;
size += dci_pdu->transmission_configuration_indication.nbits;
}
// SRS request
if (sc_info->supplementaryUplink == NULL)
dci_pdu->srs_request.nbits = 2;
else
dci_pdu->srs_request.nbits = 3;
size += dci_pdu->srs_request.nbits;
// CBGTI
if (sc_info->pdsch_CGB_Transmission) {
uint8_t maxCBGperTB = (sc_info->pdsch_CGB_Transmission->maxCodeBlockGroupsPerTransportBlock + 1) * 2;
long *maxCWperDCI_rrc = pdsch_Config->maxNrofCodeWordsScheduledByDCI;
uint8_t maxCW = (maxCWperDCI_rrc == NULL) ? 1 : *maxCWperDCI_rrc;
dci_pdu->cbgti.nbits = maxCBGperTB * maxCW;
size += dci_pdu->cbgti.nbits;
// CBGFI
if (sc_info->pdsch_CGB_Transmission->codeBlockGroupFlushIndicator) {
dci_pdu->cbgfi.nbits = 1;
size += dci_pdu->cbgfi.nbits;
}
}
// DMRS sequence init
size += 1;
break;
case NR_DL_DCI_FORMAT_2_0:
break;
case NR_DL_DCI_FORMAT_2_1:
break;
case NR_DL_DCI_FORMAT_2_2:
break;
case NR_DL_DCI_FORMAT_2_3:
break;
default:
AssertFatal(1==0, "Invalid NR DCI format %d\n", format);
}
LOG_D(NR_MAC, "DCI size: %d\n", size);
return size;
}
int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrecoder) {
uint8_t type,maxl;
if(NR_DMRS_UplinkConfig->dmrs_Type == NULL)
type = 1;
else
type = 2;
if(NR_DMRS_UplinkConfig->maxLength == NULL)
maxl = 1;
else
maxl = 2;
if (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled)
return( maxl+type+1);
else {
if (type==1)
return (maxl<<1);
else
AssertFatal(1==0,"DMRS type not valid for this choice");
}
}
static const int tdd_period_to_num[8] = {500, 625, 1000, 1250, 2000, 2500, 5000, 10000};
bool is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slot)
{
if (tdd_UL_DL_ConfigurationCommon == NULL)
return true;
int period1, period2 = 0;
if (tdd_UL_DL_ConfigurationCommon->pattern1.ext1 &&
tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530)
period1 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530;
else
period1 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity];
if (tdd_UL_DL_ConfigurationCommon->pattern2) {
if (tdd_UL_DL_ConfigurationCommon->pattern2->ext1 &&
tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530)
period2 = 3000 + *tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530;
else
period2 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity];
}
int period = period1+period2;
int scs = tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing;
int slots = period * (1 << scs) / 1000;
int slots1 = period1 * (1 << scs) / 1000;
int slot_in_period = slot % slots;
if (slot_in_period < slots1)
return slot_in_period <= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
else
return slot_in_period <= slots1 + tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots;
}
bool is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slot, frame_type_t frame_type)
{
// Note: condition on frame_type
// goal: the UL scheduler assumes mode is TDD therefore this hack is needed to make FDD work
if (frame_type == FDD)
return true;
if (tdd_UL_DL_ConfigurationCommon == NULL)
// before receiving TDD information all slots should be considered to be DL
return false;
int period1, period2 = 0;
if (tdd_UL_DL_ConfigurationCommon->pattern1.ext1 &&
tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530)
period1 = 3000 + *tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530;
else
period1 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity];
if (tdd_UL_DL_ConfigurationCommon->pattern2) {
if (tdd_UL_DL_ConfigurationCommon->pattern2->ext1 &&
tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530)
period2 = 3000 + *tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530;
else
period2 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity];
}
int period = period1+period2;
int scs = tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing;
int slots = period * (1 << scs) / 1000;
int slots1 = period1 * (1 << scs) / 1000;
int slot_in_period = slot % slots;
if (slot_in_period < slots1)
return slot_in_period >= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
else
return slot_in_period >= slots1+tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots;
}
int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,
int dci_format,
int dmrs_TypeA_Position,
int NrOfSymbols,
int startSymbol,
mappingType_t mappingtype,
int length)
{
int dmrs_AdditionalPosition = 0;
NR_DMRS_DownlinkConfig_t *dmrs_config = NULL;
LOG_D(MAC, "NrofSymbols:%d, startSymbol:%d, mappingtype:%d, dmrs_TypeA_Position:%d\n", NrOfSymbols, startSymbol, mappingtype, dmrs_TypeA_Position);
int l0 = 0; // type B
if (mappingtype == typeA) {
if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2) l0 = 2;
else if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3) l0 = 3;
else AssertFatal(1==0,"Illegal dmrs_TypeA_Position %d\n",(int)dmrs_TypeA_Position);
}
// in case of DCI FORMAT 1_0 or dedicated pdsch config not received additionposition = pos2, len1 should be used
// referred to section 5.1.6.2 in 38.214
dmrs_AdditionalPosition = 2;
if (pdsch_Config != NULL) {
if (mappingtype == typeA) { // Type A
if (dci_format != NR_DL_DCI_FORMAT_1_0 &&
pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup)
dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup;
} else if (mappingtype == typeB) {
if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup)
dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup;
} else {
AssertFatal(1==0,"Incorrect Mappingtype\n");
}
// default values of additionalposition is pos2
if (dmrs_config && dmrs_config->dmrs_AdditionalPosition != NULL)
dmrs_AdditionalPosition = *dmrs_config->dmrs_AdditionalPosition;
}
uint8_t ld, row, column;
int32_t l_prime = -1;
// columns 0-3 for TypeA, 4-7 for TypeB
column = (mappingtype == typeA) ? dmrs_AdditionalPosition : (dmrs_AdditionalPosition + 4);
// Section 7.4.1.1.2 in Spec 38.211
// For PDSCH Mapping TypeA, ld is duration between first OFDM of the slot and last OFDM symbol of the scheduled PDSCH resources
// For TypeB, ld is the duration of the scheduled PDSCH resources
ld = (mappingtype == typeA) ? (NrOfSymbols + startSymbol) : NrOfSymbols;
AssertFatal(ld > 2 && ld < 15,"Illegal NrOfSymbols according to Table 5.1.2.1-1 Spec 38.214 %d\n",ld);
AssertFatal((NrOfSymbols + startSymbol) < 15,"Illegal S+L according to Table 5.1.2.1-1 Spec 38.214 S:%d L:%d\n",startSymbol, NrOfSymbols);
if (mappingtype == typeA) {
// Section 7.4.1.1.2 in Spec 38.211
AssertFatal((l0 == 2) || (l0 == 3 && dmrs_AdditionalPosition != 3),"Wrong config, If dmrs_TypeA_Position POS3, ADD POS cannot be POS3 \n");
// Table 5.1.2.1-1 in Spec 38.214
AssertFatal(startSymbol <= l0, "Wrong config, Start symbol %d cannot be later than dmrs_TypeA_Position %d \n", startSymbol, l0);
// Section 7.4.1.1.2 in Spec 38.211
AssertFatal(l0 == 2 || (l0 == 3 && (ld != 3 && ld != 4)), "ld 3 or 4 symbols only possible with dmrs_TypeA_Position POS2 \n");
}
// number of front loaded symbols
if (length == 1) {
row = ld - 2;
l_prime = table_7_4_1_1_2_3_pdsch_dmrs_positions_l[row][column];
l0 = 1 << l0;
}
else {
row = (ld < 4) ? 0 : (ld - 3);
l_prime = table_7_4_1_1_2_4_pdsch_dmrs_positions_l[row][column];
l0 = 1<<l0 | 1<<(l0+1);
}
LOG_D(MAC, "l0:%d, ld:%d,row:%d, column:%d, addpos:%d, maxlen:%d\n", l0, ld, row, column, dmrs_AdditionalPosition, length);
AssertFatal(l_prime>=0,"ERROR in configuration.Check Time Domain allocation of this Grant. l_prime < 1. row:%d, column:%d\n", row, column);
l_prime = (mappingtype == typeA) ? (l_prime | l0) : (l_prime << startSymbol);
LOG_D(MAC, " PDSCH DMRS MASK in HEX:%x\n", l_prime);
return l_prime;
}
uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type)
{
// Set downlink MCS table (Semi-persistent scheduling ignored for now)
uint8_t mcsTableIdx = 0; // default value
if (mcs_Table && *mcs_Table == NR_PDSCH_Config__mcs_Table_qam256 && dci_format == NR_DL_DCI_FORMAT_1_1 && rnti_type == TYPE_C_RNTI_)
mcsTableIdx = 1;
else if (rnti_type != TYPE_MCS_C_RNTI_ && mcs_Table && *mcs_Table == NR_PDSCH_Config__mcs_Table_qam64LowSE
&& ss_type == NR_SearchSpace__searchSpaceType_PR_ue_Specific)
mcsTableIdx = 2;
else if (rnti_type == TYPE_MCS_C_RNTI_)
mcsTableIdx = 2;
LOG_D(NR_MAC,"DL MCS Table Index: %d\n", mcsTableIdx);
return mcsTableIdx;
}
uint8_t get_pusch_mcs_table(long *mcs_Table,
int is_tp,
int dci_format,
int rnti_type,
int target_ss,
bool config_grant)
{
// implementing 6.1.4.1 in 38.214
if (mcs_Table != NULL) {
if (config_grant || (rnti_type == TYPE_CS_RNTI_)) {
if (*mcs_Table == NR_PUSCH_Config__mcs_Table_qam256)
return 1;
else
return (2 + (is_tp << 1));
} else {
if ((*mcs_Table == NR_PUSCH_Config__mcs_Table_qam256) && (dci_format == NR_UL_DCI_FORMAT_0_1)
&& ((rnti_type == TYPE_C_RNTI_) || (rnti_type == TYPE_SP_CSI_RNTI_)))
return 1;
// TODO take into account UE configuration
if ((*mcs_Table == NR_PUSCH_Config__mcs_Table_qam64LowSE) && (target_ss == NR_SearchSpace__searchSpaceType_PR_ue_Specific)
&& ((rnti_type == TYPE_C_RNTI_) || (rnti_type == TYPE_SP_CSI_RNTI_)))
return (2 + (is_tp << 1));
if (rnti_type == TYPE_MCS_C_RNTI_)
return (2 + (is_tp << 1));
}
}
return (0 + (is_tp * 3));
}
int binomial(int n, int k) {
int c = 1, i;
if (k > n-k)
k = n-k;
for (i = 1; i <= k; i++, n--) {
if (c/i > UINT_MAX/n) // return 0 on overflow
return 0;
c = c / i * n + c % i * n / i;
}
return c;
}
/* extract PTRS values from RC and validate it based upon 38.214 5.1.6.3 */
bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config,
uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable,
uint8_t *K_ptrs, uint8_t *L_ptrs,
uint8_t *portIndex,uint8_t *nERatio, uint8_t *reOffset,
uint8_t NrOfSymbols)
{
bool valid = true;
/* as defined in T 38.214 5.1.6.3 */
if(rbSize < 3) {
valid = false;
return valid;
}
/* Check for Frequency Density values */
if(ptrs_config->frequencyDensity->list.count < 2) {
/* Default value for K_PTRS = 2 as defined in T 38.214 5.1.6.3 */
*K_ptrs = 2;
}
else {
*K_ptrs = get_K_ptrs(*ptrs_config->frequencyDensity->list.array[0],
*ptrs_config->frequencyDensity->list.array[1],
rbSize);
}
/* Check for time Density values */
if(ptrs_config->timeDensity->list.count < 3) {
/* Default value for L_PTRS = 1 as defined in T 38.214 5.1.6.3 */
*L_ptrs = 1;
}
else {
*L_ptrs = get_L_ptrs(*ptrs_config->timeDensity->list.array[0],
*ptrs_config->timeDensity->list.array[1],
*ptrs_config->timeDensity->list.array[2],
mcsIndex,
mcsTable);
}
*portIndex =*ptrs_config->epre_Ratio;
*nERatio = *ptrs_config->resourceElementOffset;
*reOffset = 0;
/* If either or both of the parameters PT-RS time density (LPT-RS) and PT-RS frequency density (KPT-RS), shown in Table
* 5.1.6.3-1 and Table 5.1.6.3-2, indicates that 'PT-RS not present', the UE shall assume that PT-RS is not present
*/
if(*K_ptrs ==2 || *K_ptrs ==4 ) {
valid = true;
}
else {
valid = false;
return valid;
}
if(*L_ptrs ==0 || *L_ptrs ==1 || *L_ptrs ==2 ) {
valid = true;
}
else {
valid = false;
return valid;
}
/* PTRS is not present also :
* When the UE is receiving a PDSCH with allocation duration of 4 symbols and if LPT-RS is set to 4, the UE shall assume
* PT-RS is not transmitted
* When the UE is receiving a PDSCH with allocation duration of 2 symbols as defined in Clause 7.4.1.1.2 of [4, TS
* 38.211] and if LPT-RS is set to 2 or 4, the UE shall assume PT-RS is not transmitted.
*/
if((NrOfSymbols == 4 && *L_ptrs ==2) || ((NrOfSymbols == 2 && *L_ptrs > 0))) {
valid = false;
return valid;
}
/* Moved below check from scheduler function to here */
if (*L_ptrs >= NrOfSymbols) {
valid = false;
return valid;
}
return valid;
}
uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i_ssb) {
switch (scs) {
case NR_SubcarrierSpacing_kHz15:
return symbol_ssb_AC[i_ssb]; //type A
case NR_SubcarrierSpacing_kHz30:
if (band == 5 || band == 66)
return symbol_ssb_BD[i_ssb]; //type B
else
return symbol_ssb_AC[i_ssb]; //type C
case NR_SubcarrierSpacing_kHz120:
return symbol_ssb_BD[i_ssb]; //type D
case NR_SubcarrierSpacing_kHz240:
return symbol_ssb_E[i_ssb];
default:
AssertFatal(1 == 0, "SCS %ld not allowed for SSB \n",scs);
}
}
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
int *period, int *offset) {
if(periodicityAndOffset != NULL) {
NR_CSI_ResourcePeriodicityAndOffset_PR p_and_o = periodicityAndOffset->present;
switch(p_and_o){
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots4:
*period = 4;
*offset = periodicityAndOffset->choice.slots4;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots5:
*period = 5;
*offset = periodicityAndOffset->choice.slots5;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots8:
*period = 8;
*offset = periodicityAndOffset->choice.slots8;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots10:
*period = 10;
*offset = periodicityAndOffset->choice.slots10;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots16:
*period = 16;
*offset = periodicityAndOffset->choice.slots16;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots20:
*period = 20;
*offset = periodicityAndOffset->choice.slots20;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots32:
*period = 32;
*offset = periodicityAndOffset->choice.slots32;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots40:
*period = 40;
*offset = periodicityAndOffset->choice.slots40;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots64:
*period = 64;
*offset = periodicityAndOffset->choice.slots64;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots80:
*period = 80;
*offset = periodicityAndOffset->choice.slots80;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots160:
*period = 160;
*offset = periodicityAndOffset->choice.slots160;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots320:
*period = 320;
*offset = periodicityAndOffset->choice.slots320;
break;
case NR_CSI_ResourcePeriodicityAndOffset_PR_slots640:
*period = 640;
*offset = periodicityAndOffset->choice.slots640;
break;
default:
AssertFatal(1==0,"No periodicity and offset found in CSI resource");
}
}
if(csirep != NULL) {
NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present;
switch(p_and_o){
case NR_CSI_ReportPeriodicityAndOffset_PR_slots4:
*period = 4;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots5:
*period = 5;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots8:
*period = 8;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots10:
*period = 10;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots16:
*period = 16;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots20:
*period = 20;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots40:
*period = 40;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots80:
*period = 80;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots160:
*period = 160;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots320:
*period = 320;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320;
break;
default:
AssertFatal(1==0,"No periodicity and offset resource found in CSI report");
}
}
}
uint8_t get_BG(uint32_t A, uint16_t R)
{
float code_rate = (float) R / 10240.0f;
if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (code_rate <= 0.6667)) || code_rate <= 0.25)
return 2;
else
return 1;
}
uint32_t get_Y(const NR_SearchSpace_t *ss, int slot, rnti_t rnti) {
if(ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common)
return 0;
const int cid = *ss->controlResourceSetId % 3;
const uint32_t A[3] = {39827, 39829, 39839};
const uint32_t D = 65537;
uint32_t Y;
Y = (A[cid] * rnti) % D;
for (int s = 0; s < slot; s++)
Y = (A[cid] * Y) % D;
return Y;
}
void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
frame_t frameP,
const NR_MIB_t *mib,
uint8_t num_slot_per_frame,
uint8_t ssb_subcarrier_offset,
uint16_t ssb_start_symbol,
NR_SubcarrierSpacing_t scs_ssb,
frequency_range_t frequency_range,
int nr_band,
uint32_t ssb_index,
uint32_t ssb_period,
uint32_t ssb_offset_point_a)
{
NR_SubcarrierSpacing_t scs_pdcch;
channel_bandwidth_t min_channel_bw;
// according to Table 5.3.5-1 in 38.104
// band 79 is the only one which minimum is 40
// for all the other channels it is either 10 or 5
// and there is no difference between the two for this implementation so it is set it to 10
if (nr_band == 79)
min_channel_bw = bw_40MHz;
else
min_channel_bw = bw_10MHz;
if (frequency_range == FR2) {
if(mib->subCarrierSpacingCommon == NR_MIB__subCarrierSpacingCommon_scs15or60)
scs_pdcch = NR_SubcarrierSpacing_kHz60;
else
scs_pdcch = NR_SubcarrierSpacing_kHz120;
}
else {
frequency_range = FR1;
if(mib->subCarrierSpacingCommon == NR_MIB__subCarrierSpacingCommon_scs15or60)
scs_pdcch = NR_SubcarrierSpacing_kHz15;
else
scs_pdcch = NR_SubcarrierSpacing_kHz30;
}
type0_PDCCH_CSS_config->scs_pdcch = scs_pdcch;
type0_PDCCH_CSS_config->ssb_index = ssb_index;
type0_PDCCH_CSS_config->frame = frameP;
uint8_t ssb_slot = ssb_start_symbol/14;
uint32_t is_condition_A = (ssb_subcarrier_offset == 0); // 38.213 ch.13
uint32_t index_4msb = (mib->pdcch_ConfigSIB1.controlResourceSetZero);
uint32_t index_4lsb = (mib->pdcch_ConfigSIB1.searchSpaceZero);
type0_PDCCH_CSS_config->num_rbs = -1;
type0_PDCCH_CSS_config->num_symbols = -1;
type0_PDCCH_CSS_config->rb_offset = -1;
LOG_D(NR_MAC,"NR_SubcarrierSpacing_kHz30 %d, scs_ssb %d, scs_pdcch %d, min_chan_bw %d\n",(int)NR_SubcarrierSpacing_kHz30,(int)scs_ssb,(int)scs_pdcch,min_channel_bw);
// type0-pdcch coreset
switch( ((int)scs_ssb << 3) | (int)scs_pdcch ){
case (NR_SubcarrierSpacing_kHz15 << 3) | NR_SubcarrierSpacing_kHz15:
AssertFatal(index_4msb < 15, "38.213 Table 13-1 4 MSB out of range\n");
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
type0_PDCCH_CSS_config->num_rbs = table_38213_13_1_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_1_c3[index_4msb];
type0_PDCCH_CSS_config->rb_offset = table_38213_13_1_c4[index_4msb];
break;
case (NR_SubcarrierSpacing_kHz15 << 3) | NR_SubcarrierSpacing_kHz30:
AssertFatal(index_4msb < 14, "38.213 Table 13-2 4 MSB out of range\n");
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
type0_PDCCH_CSS_config->num_rbs = table_38213_13_2_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_2_c3[index_4msb];
type0_PDCCH_CSS_config->rb_offset = table_38213_13_2_c4[index_4msb];
break;
case (NR_SubcarrierSpacing_kHz30 << 3) | NR_SubcarrierSpacing_kHz15:
if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)){
AssertFatal(index_4msb < 9, "38.213 Table 13-3 4 MSB out of range\n");
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
type0_PDCCH_CSS_config->num_rbs = table_38213_13_3_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_3_c3[index_4msb];
type0_PDCCH_CSS_config->rb_offset = table_38213_13_3_c4[index_4msb];
}else if(min_channel_bw & bw_40MHz){
AssertFatal(index_4msb < 9, "38.213 Table 13-5 4 MSB out of range\n");
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
type0_PDCCH_CSS_config->num_rbs = table_38213_13_5_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_5_c3[index_4msb];
type0_PDCCH_CSS_config->rb_offset = table_38213_13_5_c4[index_4msb];
}else{ ; }
break;
case (NR_SubcarrierSpacing_kHz30 << 3) | NR_SubcarrierSpacing_kHz30:
if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)){
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
type0_PDCCH_CSS_config->num_rbs = table_38213_13_4_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_4_c3[index_4msb];
type0_PDCCH_CSS_config->rb_offset = table_38213_13_4_c4[index_4msb];
}else if(min_channel_bw & bw_40MHz){
AssertFatal(index_4msb < 10, "38.213 Table 13-6 4 MSB out of range\n");
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
type0_PDCCH_CSS_config->num_rbs = table_38213_13_6_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_6_c3[index_4msb];
type0_PDCCH_CSS_config->rb_offset = table_38213_13_6_c4[index_4msb];
}else{ ; }
break;
case (NR_SubcarrierSpacing_kHz120 << 3) | NR_SubcarrierSpacing_kHz60:
AssertFatal(index_4msb < 12, "38.213 Table 13-7 4 MSB out of range\n");
if (index_4msb < 8) {
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
} else if (index_4msb < 12) {
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 2;
}
type0_PDCCH_CSS_config->num_rbs = table_38213_13_7_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_7_c3[index_4msb];
if(!is_condition_A && (index_4msb == 8 || index_4msb == 10)){
type0_PDCCH_CSS_config->rb_offset = table_38213_13_7_c4[index_4msb] - 1;
}else{
type0_PDCCH_CSS_config->rb_offset = table_38213_13_7_c4[index_4msb];
}
break;
case (NR_SubcarrierSpacing_kHz120 << 3) | NR_SubcarrierSpacing_kHz120:
AssertFatal(index_4msb < 8, "38.213 Table 13-8 4 MSB out of range\n");
if (index_4msb < 4) {
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
} else if (index_4msb < 8) {
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 3;
}
type0_PDCCH_CSS_config->num_rbs = table_38213_13_8_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_8_c3[index_4msb];
if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)){
type0_PDCCH_CSS_config->rb_offset = table_38213_13_8_c4[index_4msb] - 1;
}else{
type0_PDCCH_CSS_config->rb_offset = table_38213_13_8_c4[index_4msb];
}
break;
case (NR_SubcarrierSpacing_kHz240 << 3) | NR_SubcarrierSpacing_kHz60:
AssertFatal(index_4msb < 4, "38.213 Table 13-9 4 MSB out of range\n");
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
type0_PDCCH_CSS_config->num_rbs = table_38213_13_9_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_9_c3[index_4msb];
type0_PDCCH_CSS_config->rb_offset = table_38213_13_9_c4[index_4msb];
break;
case (NR_SubcarrierSpacing_kHz240 << 3) | NR_SubcarrierSpacing_kHz120:
AssertFatal(index_4msb < 8, "38.213 Table 13-10 4 MSB out of range\n");
if (index_4msb < 4) {
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1;
} else if (index_4msb < 8) {
type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 2;
}
type0_PDCCH_CSS_config->num_rbs = table_38213_13_10_c2[index_4msb];
type0_PDCCH_CSS_config->num_symbols = table_38213_13_10_c3[index_4msb];
if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)){
type0_PDCCH_CSS_config->rb_offset = table_38213_13_10_c4[index_4msb]-1;
}else{
type0_PDCCH_CSS_config->rb_offset = table_38213_13_10_c4[index_4msb];
}
break;
default:
LOG_E(NR_MAC,"NR_SubcarrierSpacing_kHz30 %d, scs_ssb %d, scs_pdcch %d, min_chan_bw %d\n",NR_SubcarrierSpacing_kHz30,(int)scs_ssb,(int)scs_pdcch,min_channel_bw);
break;
}
LOG_D(NR_MAC,"Coreset0: index_4msb=%d, num_rbs=%d, num_symb=%d, rb_offset=%d\n",
index_4msb,type0_PDCCH_CSS_config->num_rbs,type0_PDCCH_CSS_config->num_symbols,type0_PDCCH_CSS_config->rb_offset );
AssertFatal(type0_PDCCH_CSS_config->num_rbs != -1, "Type0 PDCCH coreset num_rbs undefined, index_4msb=%d, min_channel_bw %d, scs_ssb %d, scs_pdcch %d\n",index_4msb,min_channel_bw,(int)scs_ssb,(int)scs_pdcch);
AssertFatal(type0_PDCCH_CSS_config->num_symbols != -1, "Type0 PDCCH coreset num_symbols undefined");
AssertFatal(type0_PDCCH_CSS_config->rb_offset != -1, "Type0 PDCCH coreset rb_offset undefined");
// type0-pdcch search space
float big_o = 0.0f;
float big_m = 0.0f;
type0_PDCCH_CSS_config->sfn_c = -1; // only valid for mux=1
type0_PDCCH_CSS_config->n_c = UINT_MAX;
type0_PDCCH_CSS_config->first_symbol_index = UINT_MAX;
type0_PDCCH_CSS_config->search_space_duration = 0; // element of search space
// 38.213 table 10.1-1
/// MUX PATTERN 1
if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR1){
big_o = table_38213_13_11_c1[index_4lsb];
big_m = table_38213_13_11_c3[index_4lsb];
uint32_t temp = (uint32_t)(big_o*(1<<scs_pdcch)) + (uint32_t)(type0_PDCCH_CSS_config->ssb_index*big_m);
type0_PDCCH_CSS_config->n_c = temp / num_slot_per_frame;
type0_PDCCH_CSS_config->sfn_c = type0_PDCCH_CSS_config->n_c % 2;
if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (type0_PDCCH_CSS_config->ssb_index&1)){
type0_PDCCH_CSS_config->first_symbol_index = type0_PDCCH_CSS_config->num_symbols;
}else{
type0_PDCCH_CSS_config->first_symbol_index = table_38213_13_11_c4[index_4lsb];
}
// 38.213 chapter 13: over two consecutive slots
type0_PDCCH_CSS_config->search_space_duration = 2;
// two frames
type0_PDCCH_CSS_config->search_space_frame_period = nr_slots_per_frame[scs_ssb]<<1;
}
if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){
big_o = table_38213_13_12_c1[index_4lsb];
big_m = table_38213_13_12_c3[index_4lsb];
uint32_t temp = (uint32_t)(big_o*(1<<scs_pdcch)) + (uint32_t)(type0_PDCCH_CSS_config->ssb_index*big_m);
type0_PDCCH_CSS_config->n_c = temp / num_slot_per_frame;
type0_PDCCH_CSS_config->sfn_c = type0_PDCCH_CSS_config->n_c % 2;
if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (type0_PDCCH_CSS_config->ssb_index&1)){
type0_PDCCH_CSS_config->first_symbol_index = 7;
}else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (type0_PDCCH_CSS_config->ssb_index&1)){
type0_PDCCH_CSS_config->first_symbol_index = type0_PDCCH_CSS_config->num_symbols;
}else{
type0_PDCCH_CSS_config->first_symbol_index = 0;
}
// 38.213 chapter 13: over two consecutive slots
type0_PDCCH_CSS_config->search_space_duration = 2;
// two frames
type0_PDCCH_CSS_config->search_space_frame_period = nr_slots_per_frame[scs_ssb]<<1;
}
/// MUX PATTERN 2
if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 2){
if((scs_ssb == NR_SubcarrierSpacing_kHz120) && (scs_pdcch == NR_SubcarrierSpacing_kHz60)){
// 38.213 Table 13-13
AssertFatal(index_4lsb == 0, "38.213 Table 13-13 4 LSB out of range\n");
// PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot
// sfn_c = SFN_C_EQ_SFN_SSB;
type0_PDCCH_CSS_config->n_c = ssb_slot;
switch(type0_PDCCH_CSS_config->ssb_index & 0x3){ // ssb_index(i) mod 4
case 0:
type0_PDCCH_CSS_config->first_symbol_index = 0;
break;
case 1:
type0_PDCCH_CSS_config->first_symbol_index = 1;
break;
case 2:
type0_PDCCH_CSS_config->first_symbol_index = 6;
break;
case 3:
type0_PDCCH_CSS_config->first_symbol_index = 7;
break;
default: break;
}
}else if((scs_ssb == NR_SubcarrierSpacing_kHz240) && (scs_pdcch == NR_SubcarrierSpacing_kHz120)){
// 38.213 Table 13-14
AssertFatal(index_4lsb == 0, "38.213 Table 13-14 4 LSB out of range\n");
// PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot
// sfn_c = SFN_C_EQ_SFN_SSB;
type0_PDCCH_CSS_config->n_c = ssb_slot;
switch(type0_PDCCH_CSS_config->ssb_index & 0x7){ // ssb_index(i) mod 8
case 0:
type0_PDCCH_CSS_config->first_symbol_index = 0;
break;
case 1:
type0_PDCCH_CSS_config->first_symbol_index = 1;
break;
case 2:
type0_PDCCH_CSS_config->first_symbol_index = 2;
break;
case 3:
type0_PDCCH_CSS_config->first_symbol_index = 3;
break;
case 4:
type0_PDCCH_CSS_config->first_symbol_index = 12;
type0_PDCCH_CSS_config->n_c = ssb_slot - 1;
break;
case 5:
type0_PDCCH_CSS_config->first_symbol_index = 13;
type0_PDCCH_CSS_config->n_c = ssb_slot - 1;
break;
case 6:
type0_PDCCH_CSS_config->first_symbol_index = 0;
break;
case 7:
type0_PDCCH_CSS_config->first_symbol_index = 1;
break;
default: break;
}
}else{ ; }
// 38.213 chapter 13: over one slot
type0_PDCCH_CSS_config->search_space_duration = 1;
// SSB periodicity in slots
type0_PDCCH_CSS_config->search_space_frame_period = ssb_period*nr_slots_per_frame[scs_ssb];
}
/// MUX PATTERN 3
if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 3){
if((scs_ssb == NR_SubcarrierSpacing_kHz120) && (scs_pdcch == NR_SubcarrierSpacing_kHz120)){
// 38.213 Table 13-15
AssertFatal(index_4lsb == 0, "38.213 Table 13-15 4 LSB out of range\n");
// PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot
// sfn_c = SFN_C_EQ_SFN_SSB;
type0_PDCCH_CSS_config->n_c = ssb_slot;
switch(type0_PDCCH_CSS_config->ssb_index & 0x3){ // ssb_index(i) mod 4
case 0:
type0_PDCCH_CSS_config->first_symbol_index = 4;
break;
case 1:
type0_PDCCH_CSS_config->first_symbol_index = 8;
break;
case 2:
type0_PDCCH_CSS_config->first_symbol_index = 2;
break;
case 3:
type0_PDCCH_CSS_config->first_symbol_index = 6;
break;
default: break;
}
}else{ ; }
// 38.213 chapter 13: over one slot
type0_PDCCH_CSS_config->search_space_duration = 1;
// SSB periodicity in slots
type0_PDCCH_CSS_config->search_space_frame_period = ssb_period*nr_slots_per_frame[scs_ssb];
}
AssertFatal(type0_PDCCH_CSS_config->sfn_c >= 0, "");
AssertFatal(type0_PDCCH_CSS_config->n_c != UINT_MAX, "");
type0_PDCCH_CSS_config->n_0 = ((uint32_t)(big_o*(1<<scs_pdcch)) + (uint32_t)(type0_PDCCH_CSS_config->ssb_index*big_m))%num_slot_per_frame;
type0_PDCCH_CSS_config->cset_start_rb = ssb_offset_point_a - type0_PDCCH_CSS_config->rb_offset;
AssertFatal(type0_PDCCH_CSS_config->cset_start_rb >= 0, "Invalid CSET0 start PRB %d SSB offset point A %d RB offset %d\n",
type0_PDCCH_CSS_config->cset_start_rb, ssb_offset_point_a, type0_PDCCH_CSS_config->rb_offset);
}
void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config)
{
AssertFatal(type0_PDCCH_CSS_config, "No type0 CSS configuration\n");
AssertFatal(coreset0, "Coreset0 should have been allocated outside of this function\n");
coreset0->controlResourceSetId = 0;
int duration = type0_PDCCH_CSS_config->num_symbols;
if(coreset0->frequencyDomainResources.buf == NULL)
coreset0->frequencyDomainResources.buf = calloc(1,6);
switch(type0_PDCCH_CSS_config->num_rbs){
case 24:
coreset0->frequencyDomainResources.buf[0] = 0xf0;
coreset0->frequencyDomainResources.buf[1] = 0;
break;
case 48:
coreset0->frequencyDomainResources.buf[0] = 0xff;
coreset0->frequencyDomainResources.buf[1] = 0;
break;
case 96:
coreset0->frequencyDomainResources.buf[0] = 0xff;
coreset0->frequencyDomainResources.buf[1] = 0xff;
break;
default:
AssertFatal(1==0,"Invalid number of PRBs %d for Coreset0\n",type0_PDCCH_CSS_config->num_rbs);
}
coreset0->frequencyDomainResources.buf[2] = 0;
coreset0->frequencyDomainResources.buf[3] = 0;
coreset0->frequencyDomainResources.buf[4] = 0;
coreset0->frequencyDomainResources.buf[5] = 0;
coreset0->frequencyDomainResources.size = 6;
coreset0->frequencyDomainResources.bits_unused = 3;
coreset0->duration = duration;
coreset0->cce_REG_MappingType.present = NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved;
if (!coreset0->cce_REG_MappingType.choice.interleaved)
coreset0->cce_REG_MappingType.choice.interleaved = calloc(1,sizeof(*coreset0->cce_REG_MappingType.choice.interleaved));
coreset0->cce_REG_MappingType.choice.interleaved->reg_BundleSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6;
coreset0->cce_REG_MappingType.choice.interleaved->interleaverSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n2;
coreset0->cce_REG_MappingType.choice.interleaved->shiftIndex = NULL; // -> use cell_id
coreset0->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle;
coreset0->tci_StatesPDCCH_ToAddList = NULL;
coreset0->tci_StatesPDCCH_ToReleaseList = NULL;
coreset0->tci_PresentInDCI = NULL;
coreset0->pdcch_DMRS_ScramblingID = NULL;
}
void fill_searchSpaceZero(NR_SearchSpace_t *ss0,
int slots_per_frame,
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config)
{
AssertFatal(ss0, "SearchSpace0 should have been allocated outside of this function\n");
if(ss0->controlResourceSetId == NULL)
ss0->controlResourceSetId = calloc(1, sizeof(*ss0->controlResourceSetId));
if(ss0->monitoringSymbolsWithinSlot == NULL)
ss0->monitoringSymbolsWithinSlot = calloc(1, sizeof(*ss0->monitoringSymbolsWithinSlot));
if(ss0->monitoringSymbolsWithinSlot->buf == NULL)
ss0->monitoringSymbolsWithinSlot->buf = calloc(1, 2);
if(ss0->nrofCandidates == NULL)
ss0->nrofCandidates = calloc(1, sizeof(*ss0->nrofCandidates));
if(ss0->searchSpaceType == NULL)
ss0->searchSpaceType = calloc(1, sizeof(*ss0->searchSpaceType));
if(ss0->searchSpaceType->choice.common == NULL)
ss0->searchSpaceType->choice.common = calloc(1, sizeof(*ss0->searchSpaceType->choice.common));
if(ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 == NULL)
ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1, sizeof(*ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0));
AssertFatal(type0_PDCCH_CSS_config!=NULL,"No type0 CSS configuration\n");
const uint32_t periodicity = type0_PDCCH_CSS_config->search_space_frame_period;
const uint32_t offset = type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 ?
type0_PDCCH_CSS_config->n_0 + (slots_per_frame * type0_PDCCH_CSS_config->sfn_c) :
type0_PDCCH_CSS_config->n_c;
ss0->searchSpaceId = 0;
*ss0->controlResourceSetId = 0;
if(ss0->monitoringSlotPeriodicityAndOffset == NULL)
ss0->monitoringSlotPeriodicityAndOffset = calloc(1, sizeof(*ss0->monitoringSlotPeriodicityAndOffset));
set_monitoring_periodicity_offset(ss0,periodicity,offset);
const uint32_t duration = type0_PDCCH_CSS_config->search_space_duration;
if (duration==1)
ss0->duration = NULL;
else{
if (!ss0->duration)
ss0->duration = calloc(1, sizeof(*ss0->duration));
*ss0->duration = duration;
}
const uint16_t symbols = SL_to_bitmap(type0_PDCCH_CSS_config->first_symbol_index, type0_PDCCH_CSS_config->num_symbols);
ss0->monitoringSymbolsWithinSlot->size = 2;
ss0->monitoringSymbolsWithinSlot->bits_unused = 2;
ss0->monitoringSymbolsWithinSlot->buf[1] = 0;
ss0->monitoringSymbolsWithinSlot->buf[0] = 0;
for (int i=0; i<8; i++) {
ss0->monitoringSymbolsWithinSlot->buf[1] |= ((symbols>>(i+8))&0x01)<<(7-i);
ss0->monitoringSymbolsWithinSlot->buf[0] |= ((symbols>>i)&0x01)<<(7-i);
}
// max values are set according to TS38.213 Section 10.1 Table 10.1-1
ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0;
ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0;
ss0->nrofCandidates->aggregationLevel4 = 4;
ss0->nrofCandidates->aggregationLevel8 = 2;
ss0->nrofCandidates->aggregationLevel16 = 1;
ss0->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common;
}
void find_period_offset_SR(const NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset) {
NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR P_O = SchedulingReqRec->periodicityAndOffset->present;
switch (P_O){
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl1:
*period = 1;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl1;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl2:
*period = 2;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl2;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl4:
*period = 4;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl4;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl5:
*period = 5;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl5;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl8:
*period = 8;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl8;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10:
*period = 10;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl10;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl16:
*period = 16;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl16;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20:
*period = 20;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl20;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40:
*period = 40;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl40;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80:
*period = 80;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl80;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160:
*period = 160;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl160;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320:
*period = 320;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl320;
break;
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640:
*period = 640;
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl640;
break;
default:
AssertFatal(1==0,"No periodicityAndOffset resources found in schedulingrequestresourceconfig");
}
}
int compute_pucch_crc_size(int O_uci)
{
if (O_uci < 12)
return 0;
else{
if (O_uci < 20)
return 6;
else {
if (O_uci < 360)
return 11;
else
AssertFatal(1==0,"Case for segmented PUCCH not yet implemented");
}
}
}
float get_max_code_rate(NR_PUCCH_MaxCodeRate_t *maxCodeRate)
{
int rtimes100;
switch(*maxCodeRate){
case NR_PUCCH_MaxCodeRate_zeroDot08 :
rtimes100 = 8;
break;
case NR_PUCCH_MaxCodeRate_zeroDot15 :
rtimes100 = 15;
break;
case NR_PUCCH_MaxCodeRate_zeroDot25 :
rtimes100 = 25;
break;
case NR_PUCCH_MaxCodeRate_zeroDot35 :
rtimes100 = 35;
break;
case NR_PUCCH_MaxCodeRate_zeroDot45 :
rtimes100 = 45;
break;
case NR_PUCCH_MaxCodeRate_zeroDot60 :
rtimes100 = 60;
break;
case NR_PUCCH_MaxCodeRate_zeroDot80 :
rtimes100 = 80;
break;
default :
AssertFatal(1==0,"Invalid MaxCodeRate");
}
float r = (float)rtimes100 / 100;
return r;
}
int get_f3_dmrs_symbols(NR_PUCCH_Resource_t *pucchres, NR_PUCCH_Config_t *pucch_Config)
{
int f3_dmrs_symbols;
int add_dmrs_flag;
if (pucch_Config->format3 == NULL)
add_dmrs_flag = 0;
else
add_dmrs_flag = pucch_Config->format3->choice.setup->additionalDMRS ? 1 : 0;
if (pucchres->format.choice.format3->nrofSymbols == 4)
f3_dmrs_symbols = 1 << (pucchres->intraSlotFrequencyHopping ? 1 : 0);
else {
if (pucchres->format.choice.format3->nrofSymbols < 10)
f3_dmrs_symbols = 2;
else
f3_dmrs_symbols = 2 << add_dmrs_flag;
}
return f3_dmrs_symbols;
}
uint16_t compute_pucch_prb_size(uint8_t format,
uint8_t nr_prbs,
uint16_t O_uci,
NR_PUCCH_MaxCodeRate_t *maxCodeRate,
uint8_t Qm,
uint8_t n_symb,
uint8_t n_re_ctrl)
{
int O_crc = compute_pucch_crc_size(O_uci);
int O_tot = O_uci + O_crc;
float r = get_max_code_rate(maxCodeRate);
AssertFatal(O_tot <= (nr_prbs * n_re_ctrl * n_symb * Qm * r),
"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs",
r,
O_uci,
O_crc,
nr_prbs);
if (format==2){
// TODO fix this for multiple CSI reports
for (int i = nr_prbs; i > 0; i--) {
// compute code rate factor for next prb value
int next_prb_factor = (i - 1) * n_symb * Qm * n_re_ctrl * r;
// if it does not sa
if (O_tot > next_prb_factor)
return i;
}
}
else{
AssertFatal(1==0,"Not yet implemented");
}
return 0;
}
/* extract UL PTRS values from RRC and validate it based upon 38.214 6.2.3 */
bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config,
uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable,
uint8_t *K_ptrs, uint8_t *L_ptrs,
uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower,
uint8_t NrOfSymbols)
{
bool valid = true;
/* as defined in T 38.214 6.2.3 */
if(rbSize < 3) {
valid = false;
return valid;
}
/* Check for Frequency Density values */
if(ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.count < 2) {
/* Default value for K_PTRS = 2 as defined in T 38.214 6.2.3 */
*K_ptrs = 2;
}
else {
*K_ptrs = get_K_ptrs(*ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[0],
*ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[1],
rbSize);
}
/* Check for time Density values */
if(ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.count < 3) {
*L_ptrs = 0;
}
else {
*L_ptrs = get_L_ptrs(*ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[0],
*ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[1],
*ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[2],
mcsIndex,
mcsTable);
}
*reOffset = *ul_ptrs_config->transformPrecoderDisabled->resourceElementOffset;
*maxNumPorts = ul_ptrs_config->transformPrecoderDisabled->maxNrofPorts;
*ulPower = ul_ptrs_config->transformPrecoderDisabled->ptrs_Power;
/* If either or both of the parameters PT-RS time density (LPT-RS) and PT-RS frequency density (KPT-RS), shown in Table
* 6.2.3.1-1 and Table 6.2.3.1-2, indicates that 'PT-RS not present', the UE shall assume that PT-RS is not present
*/
if(*K_ptrs ==2 || *K_ptrs ==4 ) {
valid = true;
}
else {
valid = false;
return valid;
}
if(*L_ptrs ==0 || *L_ptrs ==1 || *L_ptrs ==2 ) {
valid = true;
}
else {
valid = false;
return valid;
}
/* PTRS is not present also :
* When the UE is receiving a PUSCH with allocation duration of 4 symbols and if LPT-RS is set to 4, the UE shall assume
* PT-RS is not transmitted
* When the UE is receiving a PUSCH with allocation duration of 2 symbols as defined in Clause 6.4.1.2.2 of [4, TS
* 38.211] and if LPT-RS is set to 2 or 4, the UE shall assume PT-RS is not transmitted.
*/
if((NrOfSymbols == 4 && *L_ptrs ==2) || ((NrOfSymbols == 2 && *L_ptrs > 0))) {
valid = false;
return valid;
}
/* Moved below check from nr_ue_scheduler function to here */
if (*L_ptrs >= NrOfSymbols) {
valid = false;
return valid;
}
return valid;
}
//! Calculating number of bits set
uint8_t number_of_bits_set(uint8_t buf) {
uint8_t nb_of_bits_set = 0;
uint8_t mask = 0xff;
uint8_t index = 0;
for (index=7; (buf & mask) && (index>=0) ; index--){
if (buf & (1<<index))
nb_of_bits_set++;
mask>>=1;
}
return nb_of_bits_set;
}
void compute_rsrp_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
uint8_t nb_resources,
nr_csi_report_t *csi_report) {
if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == csi_reportconfig->groupBasedBeamReporting.present) {
if (NULL != csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
csi_report->CSI_report_bitlen.nb_ssbri_cri = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
else
/*! From Spec 38.331
* nrofReportedRS
* The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE
* capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report.
* When the field is absent the UE applies the value 1
*/
csi_report->CSI_report_bitlen.nb_ssbri_cri= 1;
} else
csi_report->CSI_report_bitlen.nb_ssbri_cri= 2;
if (nb_resources) {
csi_report->CSI_report_bitlen.cri_ssbri_bitlen =ceil(log2 (nb_resources));
csi_report->CSI_report_bitlen.rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
csi_report->CSI_report_bitlen.diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
} else {
csi_report->CSI_report_bitlen.cri_ssbri_bitlen =0;
csi_report->CSI_report_bitlen.rsrp_bitlen = 0;
csi_report->CSI_report_bitlen.diff_rsrp_bitlen =0;
}
}
uint8_t compute_ri_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
nr_csi_report_t *csi_report)
{
struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig;
uint8_t nb_allowed_ri, ri_bitlen;
uint8_t ri_restriction = 0;
if (codebookConfig == NULL) {
csi_report->csi_meas_bitlen.ri_bitlen = 0;
return ri_restriction;
}
// codebook type1 single panel
if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel == codebookConfig->codebookType.choice.type1->subType.present) {
struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel;
if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two) {
ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0];
nb_allowed_ri = number_of_bits_set(ri_restriction);
ri_bitlen = ceil(log2(nb_allowed_ri));
ri_bitlen = ri_bitlen < 1 ? ri_bitlen : 1; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel
csi_report->csi_meas_bitlen.ri_bitlen = ri_bitlen;
}
if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo){
if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present ==
NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) {
// 4 ports
ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0];
nb_allowed_ri = number_of_bits_set(ri_restriction);
ri_bitlen = ceil(log2(nb_allowed_ri));
ri_bitlen = ri_bitlen < 2 ? ri_bitlen : 2; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel
csi_report->csi_meas_bitlen.ri_bitlen = ri_bitlen;
}
else {
// more than 4 ports
ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0];
nb_allowed_ri = number_of_bits_set(ri_restriction);
ri_bitlen = ceil(log2(nb_allowed_ri));
csi_report->csi_meas_bitlen.ri_bitlen = ri_bitlen;
}
}
return ri_restriction;
}
else
AssertFatal(1==0,"Other configurations not yet implemented\n");
return -1;
}
void compute_li_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
uint8_t ri_restriction,
nr_csi_report_t *csi_report) {
struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig;
for(int i=0; i<8; i++) {
if (codebookConfig == NULL || ((ri_restriction>>i)&0x01) == 0)
csi_report->csi_meas_bitlen.li_bitlen[i]=0;
else {
// codebook type1 single panel
if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==codebookConfig->codebookType.choice.type1->subType.present)
csi_report->csi_meas_bitlen.li_bitlen[i]=ceil(log2(i+1))<2?ceil(log2(i+1)):2;
else
AssertFatal(1==0,"Other configurations not yet implemented\n");
}
}
}
void get_n1n2_o1o2_singlepanel(int *n1, int *n2, int *o1, int *o2,
struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo *morethantwo) {
// Table 5.2.2.2.1-2 in 38.214 for supported configurations
switch(morethantwo->n1_n2.present){
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction):
*n1 = 2;
*n2 = 1;
*o1 = 4;
*o2 = 1;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_two_TypeI_SinglePanel_Restriction):
*n1 = 2;
*n2 = 2;
*o1 = 4;
*o2 = 4;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_one_TypeI_SinglePanel_Restriction):
*n1 = 4;
*n2 = 1;
*o1 = 4;
*o2 = 1;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_three_two_TypeI_SinglePanel_Restriction):
*n1 = 3;
*n2 = 2;
*o1 = 4;
*o2 = 4;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_six_one_TypeI_SinglePanel_Restriction):
*n1 = 6;
*n2 = 1;
*o1 = 4;
*o2 = 1;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_two_TypeI_SinglePanel_Restriction):
*n1 = 4;
*n2 = 2;
*o1 = 4;
*o2 = 4;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_eight_one_TypeI_SinglePanel_Restriction):
*n1 = 8;
*n2 = 1;
*o1 = 4;
*o2 = 1;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_three_TypeI_SinglePanel_Restriction):
*n1 = 4;
*n2 = 3;
*o1 = 4;
*o2 = 4;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_six_two_TypeI_SinglePanel_Restriction):
*n1 = 4;
*n2 = 2;
*o1 = 4;
*o2 = 4;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_twelve_one_TypeI_SinglePanel_Restriction):
*n1 = 12;
*n2 = 1;
*o1 = 4;
*o2 = 1;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_four_TypeI_SinglePanel_Restriction):
*n1 = 4;
*n2 = 4;
*o1 = 4;
*o2 = 4;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_eight_two_TypeI_SinglePanel_Restriction):
*n1 = 8;
*n2 = 2;
*o1 = 4;
*o2 = 4;
break;
case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_sixteen_one_TypeI_SinglePanel_Restriction):
*n1 = 16;
*n2 = 1;
*o1 = 4;
*o2 = 1;
break;
default:
AssertFatal(1==0,"Not supported configuration for n1_n2 in codebook configuration");
}
}
static void set_bitlen_size_singlepanel(CSI_Meas_bitlen_t *csi_bitlen, int n1, int n2, int o1, int o2, int rank, int codebook_mode)
{
int i = rank - 1;
// Table 6.3.1.1.2-1 in 38.212
switch(rank){
case 1:
if(n2 > 1) {
if (codebook_mode == 1) {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_x2_bitlen[i] = 2;
}
else {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1 / 2));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2 / 2));
csi_bitlen->pmi_x2_bitlen[i] = 4;
}
}
else{
if (codebook_mode == 1) {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_x2_bitlen[i] = 2;
}
else {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1 / 2));
csi_bitlen->pmi_i12_bitlen[i] = 0;
csi_bitlen->pmi_x2_bitlen[i] = 4;
}
}
csi_bitlen->pmi_i13_bitlen[i] = 0;
break;
case 2:
if(n1 * n2 == 2) {
if (codebook_mode == 1) {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_x2_bitlen[i] = 1;
}
else {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1 / 2));
csi_bitlen->pmi_i12_bitlen[i] = 0;
csi_bitlen->pmi_x2_bitlen[i] = 3;
}
csi_bitlen->pmi_i13_bitlen[i] = 1;
}
else {
if(n2 > 1) {
if (codebook_mode == 1) {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_x2_bitlen[i] = 1;
}
else {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1 / 2));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2 / 2));
csi_bitlen->pmi_x2_bitlen[i] = 3;
}
}
else{
if (codebook_mode == 1) {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_x2_bitlen[i] = 1;
}
else {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1 / 2));
csi_bitlen->pmi_i12_bitlen[i] = 0;
csi_bitlen->pmi_x2_bitlen[i] = 3;
}
}
csi_bitlen->pmi_i13_bitlen[i] = 2;
}
break;
case 3:
case 4:
if(n1*n2 == 2) {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_i13_bitlen[i] = 0;
csi_bitlen->pmi_x2_bitlen[i] = 1;
}
else {
if(n1*n2 >= 8) {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1 / 2));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_i13_bitlen[i] = 2;
csi_bitlen->pmi_x2_bitlen[i] = 1;
}
else {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_i13_bitlen[i] = 2;
csi_bitlen->pmi_x2_bitlen[i] = 1;
}
}
break;
case 5:
case 6:
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_i13_bitlen[i] = 0;
csi_bitlen->pmi_x2_bitlen[i] = 1;
break;
case 7:
case 8:
if(n1 == 4 && n2 == 1) {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2 / 2));
csi_bitlen->pmi_i13_bitlen[i] = 0;
csi_bitlen->pmi_x2_bitlen[i] = 1;
}
else {
if(n1 > 2 && n2 == 2) {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2 / 2));
csi_bitlen->pmi_i13_bitlen[i] = 0;
csi_bitlen->pmi_x2_bitlen[i] = 1;
}
else {
csi_bitlen->pmi_i11_bitlen[i] = ceil(log2(n1 * o1));
csi_bitlen->pmi_i12_bitlen[i] = ceil(log2(n2 * o2));
csi_bitlen->pmi_i13_bitlen[i] = 0;
csi_bitlen->pmi_x2_bitlen[i] = 1;
}
}
break;
default:
AssertFatal(1==0,"Invalid rank in x1 x2 bit length computation\n");
}
csi_bitlen->pmi_x1_bitlen[i] = csi_bitlen->pmi_i11_bitlen[i] + csi_bitlen->pmi_i12_bitlen[i] + csi_bitlen->pmi_i13_bitlen[i];
}
void compute_pmi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
uint8_t ri_restriction,
nr_csi_report_t *csi_report)
{
NR_CodebookConfig_t *codebookConfig = csi_reportconfig->codebookConfig;
for(int i = 0; i < 8; i++) {
csi_report->csi_meas_bitlen.pmi_x1_bitlen[i] = 0;
csi_report->csi_meas_bitlen.pmi_x2_bitlen[i] = 0;
if (codebookConfig == NULL || ((ri_restriction >> i) & 0x01) == 0)
return;
else {
if(codebookConfig->codebookType.present == NR_CodebookConfig__codebookType_PR_type1) {
struct NR_CodebookConfig__codebookType__type1 *type1 = codebookConfig->codebookType.choice.type1;
if(type1->subType.present == NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel) {
struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *sp = type1->subType.choice.typeI_SinglePanel;
if(sp->nrOfAntennaPorts.present ==
NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two) {
csi_report->N1 = 1;
csi_report->N2 = 1;
if (i == 0)
csi_report->csi_meas_bitlen.pmi_x2_bitlen[i] = 2;
if (i == 1)
csi_report->csi_meas_bitlen.pmi_x2_bitlen[i] = 1;
}
else { // more than two
int n1, n2, o1, o2;
get_n1n2_o1o2_singlepanel(&n1, &n2, &o1, &o2, sp->nrOfAntennaPorts.choice.moreThanTwo);
set_bitlen_size_singlepanel(&csi_report->csi_meas_bitlen, n1, n2, o1, o2, i + 1, type1->codebookMode);
csi_report->N1 = n1;
csi_report->N2 = n2;
csi_report->codebook_mode = type1->codebookMode;
}
}
else
AssertFatal(1==0,"Type1 Multi-panel Codebook Config not yet implemented\n");
}
else
AssertFatal(1==0,"Type2 Codebook Config not yet implemented\n");
}
}
}
void compute_cqi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
uint8_t ri_restriction,
nr_csi_report_t *csi_report) {
struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig;
struct NR_CSI_ReportConfig__reportFreqConfiguration *freq_config = csi_reportconfig->reportFreqConfiguration;
if (*freq_config->cqi_FormatIndicator == NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI) {
for(int i=0; i<8; i++) {
if ((ri_restriction>>i)&0x01) {
csi_report->csi_meas_bitlen.cqi_bitlen[i] = 4;
if(codebookConfig != NULL) {
if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel == codebookConfig->codebookType.choice.type1->subType.present){
struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel;
if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo) {
if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present >
NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) {
// more than 4 antenna ports
if (i > 4)
csi_report->csi_meas_bitlen.cqi_bitlen[i] += 4; // CQI for second TB
}
}
}
}
}
else
csi_report->csi_meas_bitlen.cqi_bitlen[i] = 0;
}
}
else
AssertFatal(1==0,"Sub-band CQI reporting not yet supported");
}
//!TODO : same function can be written to handle csi_resources
void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report_t *csi_report_template)
{
uint8_t csi_report_id = 0;
uint8_t nb_resources = 0;
NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type;
NR_CSI_ResourceConfigId_t csi_ResourceConfigId;
struct NR_CSI_ResourceConfig *csi_resourceconfig;
// for each CSI measurement report configuration (list of CSI-ReportConfig)
LOG_D(NR_MAC,"Searching %d csi_reports\n",csi_MeasConfig->csi_ReportConfigToAddModList->list.count);
for (csi_report_id = 0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++) {
struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
// MAC structure for CSI measurement reports (per UE and per report)
nr_csi_report_t *csi_report = &csi_report_template[csi_report_id];
// csi-ResourceConfigId of a CSI-ResourceConfig included in the configuration
// (either CSI-RS or SSB)
csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement;
// looking for CSI-ResourceConfig
int found_resource = 0;
int csi_resourceidx = 0;
while (found_resource == 0 && csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count) {
csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx];
if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId)
found_resource = 1;
csi_resourceidx++;
}
AssertFatal(found_resource==1,"Not able to found any CSI-ResourceConfig with csi-ResourceConfigId %ld\n",
csi_ResourceConfigId);
long resourceType = csi_resourceconfig->resourceType;
reportQuantity_type = csi_reportconfig->reportQuantity.present;
csi_report->reportQuantity_type = reportQuantity_type;
csi_report->reportConfigId = csi_reportconfig->reportConfigId;
// setting the CSI or SSB index list
if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == csi_report->reportQuantity_type) {
for (int csi_idx = 0; csi_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_idx++) {
if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceSetId ==
*(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){
//We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig
nb_resources = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.count;
csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.array;
csi_report->CSI_Index_list = NULL;
break;
}
}
}
else {
if (resourceType == NR_CSI_ResourceConfig__resourceType_periodic) {
AssertFatal(csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList != NULL,
"Wrong settings! Report quantity requires CSI-RS but csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList is NULL\n");
for (int csi_idx = 0; csi_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_idx++) {
if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_ResourceSetId ==
*(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) {
//For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212
nb_resources = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.count;
csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.array;
csi_report->SSB_Index_list = NULL;
break;
}
}
}
else AssertFatal(1==0,"Only periodic resource configuration currently supported\n");
}
LOG_D(NR_MAC,"nb_resources %d\n",nb_resources);
// computation of bit length depending on the report type
switch(reportQuantity_type){
case (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP):
compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP):
compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI):
csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI):
csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI):
csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_li_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
default:
AssertFatal(1==0,"Not yet supported CSI report quantity type");
}
}
}
uint16_t nr_get_csi_bitlen(nr_csi_report_t *csi_report)
{
uint16_t csi_bitlen = 0;
uint16_t max_bitlen = 0;
L1_RSRP_bitlen_t *CSI_report_bitlen = NULL;
CSI_Meas_bitlen_t *csi_meas_bitlen = NULL;
if (csi_report->reportQuantity_type == NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP ||
csi_report->reportQuantity_type == NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP) {
CSI_report_bitlen = &(csi_report->CSI_report_bitlen); // This might need to be moodif for Aperiodic CSI-RS measurements
csi_bitlen += ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) +
CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen *
(CSI_report_bitlen->nb_ssbri_cri -1 )));
} else {
csi_meas_bitlen = &(csi_report->csi_meas_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements
uint16_t temp_bitlen;
for (int i = 0; i < 8; i++) {
temp_bitlen = (csi_meas_bitlen->cri_bitlen+
csi_meas_bitlen->ri_bitlen+
csi_meas_bitlen->li_bitlen[i]+
csi_meas_bitlen->cqi_bitlen[i]+
csi_meas_bitlen->pmi_x1_bitlen[i]+
csi_meas_bitlen->pmi_x2_bitlen[i]);
if(temp_bitlen > max_bitlen)
max_bitlen = temp_bitlen;
}
csi_bitlen += max_bitlen;
}
return csi_bitlen;
}
bool supported_bw_comparison(int bw_mhz, NR_SupportedBandwidth_t *supported_BW, long *support_90mhz)
{
if (bw_mhz == 90)
return support_90mhz ? true : false;
switch (supported_BW->present) {
case NR_SupportedBandwidth_PR_fr1 :
switch (supported_BW->choice.fr1) {
case NR_SupportedBandwidth__fr1_mhz5 :
return bw_mhz == 5;
case NR_SupportedBandwidth__fr1_mhz10 :
return bw_mhz == 10;
case NR_SupportedBandwidth__fr1_mhz15 :
return bw_mhz == 15;
case NR_SupportedBandwidth__fr1_mhz20 :
return bw_mhz == 20;
case NR_SupportedBandwidth__fr1_mhz25 :
return bw_mhz == 25;
case NR_SupportedBandwidth__fr1_mhz30 :
return bw_mhz == 30;
case NR_SupportedBandwidth__fr1_mhz40 :
return bw_mhz == 40;
case NR_SupportedBandwidth__fr1_mhz50 :
return bw_mhz == 50;
case NR_SupportedBandwidth__fr1_mhz60 :
return bw_mhz == 60;
case NR_SupportedBandwidth__fr1_mhz80 :
return bw_mhz == 80;
case NR_SupportedBandwidth__fr1_mhz100 :
return bw_mhz == 100;
default :
AssertFatal(false, "Invalid FR1 supported band\n");
}
break;
case NR_SupportedBandwidth_PR_fr2 :
switch (supported_BW->choice.fr2) {
case NR_SupportedBandwidth__fr2_mhz50 :
return bw_mhz == 50;
case NR_SupportedBandwidth__fr2_mhz100 :
return bw_mhz == 100;
case NR_SupportedBandwidth__fr2_mhz200 :
return bw_mhz == 200;
case NR_SupportedBandwidth__fr2_mhz400 :
return bw_mhz == 400;
default :
AssertFatal(false, "Invalid FR2 supported band\n");
}
break;
default :
AssertFatal(false, "Invalid BW type\n");
}
return false;
}
uint32_t compute_PDU_length(uint32_t num_TLV, uint32_t total_length)
{
uint32_t pdu_length = 8; // 2 bytes PDU_Length + 2 bytes PDU_Index + 4 bytes num_TLV
// For each TLV, add 2 bytes tag + 2 bytes length + value size without padding
pdu_length += (num_TLV * 4) + total_length;
return pdu_length;
}
// RA-RNTI computation (associated to PRACH occasion in which the RA Preamble is transmitted)
// - this does not apply to contention-free RA Preamble for beam failure recovery request
// - getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario)
// - s_id is starting symbol of the PRACH occasion [0...14]
// - t_id is the first slot of the PRACH occasion in a system frame [0...80]
// - f_id: index of the PRACH occasion in the frequency domain
// - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier
rnti_t nr_get_ra_rnti(uint8_t s_id, uint8_t t_id, uint8_t f_id, uint8_t ul_carrier_id)
{
// 3GPP TS 38.321 Section 5.1.3
rnti_t ra_rnti = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id;
LOG_D(MAC, "f_id %d t_id %d s_id %d ul_carrier_id %d Computed RA_RNTI is 0x%04X\n", f_id, t_id, s_id, ul_carrier_id, ra_rnti);
return ra_rnti;
}
rnti_t nr_get_MsgB_rnti(uint8_t s_id, uint8_t t_id, uint8_t f_id, uint8_t ul_carrier_id)
{
// 3GPP TS 38.321 Section 5.1.3a
rnti_t MsgB_rnti = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id + 17920;
LOG_D(MAC, "f_id %d t_id %d s_id %d ul_carrier_id %d Computed MsgB_RNTI is 0x%04X\n", f_id, t_id, s_id, ul_carrier_id, MsgB_rnti);
return MsgB_rnti;
}
int get_FeedbackDisabled(NR_DownlinkHARQ_FeedbackDisabled_r17_t *downlinkHARQ_FeedbackDisabled_r17, int harq_pid)
{
if (downlinkHARQ_FeedbackDisabled_r17 == NULL)
return 0;
const int byte_index = harq_pid / 8;
const int bit_index = harq_pid % 8;
return (downlinkHARQ_FeedbackDisabled_r17->buf[byte_index] >> (7 - bit_index)) & 1;
}
int nr_get_mu(const NR_UplinkConfigCommon_t *uplinkConfigCommon)
{
int mu;
NR_BWP_UplinkCommon_t *initialUplinkBWP = uplinkConfigCommon->initialUplinkBWP;
// if 2-Step configuration file exists
if (initialUplinkBWP->ext1 && initialUplinkBWP->ext1->msgA_ConfigCommon_r16) {
if (initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16) {
// Choose Subcarrier Spacing of configuration file of 2-Step
const NR_MsgA_ConfigCommon_r16_t *msgacc = initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup;
mu = *msgacc->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16;
} else {
// Choose Subcarrier Spacing of configuration file of 4-Step
mu = uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
}
} else {
if (initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) {
mu = *initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
} else {
mu = uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
}
}
return mu;
}