Merge remote-tracking branch 'origin/develop-SRS-feedback' into integration_2022_wk40
This commit is contained in:
@@ -540,5 +540,29 @@ typedef struct nr_csi_report {
|
||||
int N2;
|
||||
} nr_csi_report_t;
|
||||
|
||||
typedef enum {
|
||||
NR_SRS_SRI_0 = 0,
|
||||
NR_SRS_SRI_1,
|
||||
NR_SRS_SRI_2,
|
||||
NR_SRS_SRI_3,
|
||||
NR_SRS_SRI_0_1,
|
||||
NR_SRS_SRI_0_2,
|
||||
NR_SRS_SRI_0_3,
|
||||
NR_SRS_SRI_1_2,
|
||||
NR_SRS_SRI_1_3,
|
||||
NR_SRS_SRI_2_3,
|
||||
NR_SRS_SRI_0_1_2,
|
||||
NR_SRS_SRI_0_1_3,
|
||||
NR_SRS_SRI_0_2_3,
|
||||
NR_SRS_SRI_1_2_3,
|
||||
NR_SRS_SRI_0_1_2_3
|
||||
} nr_srs_sri_t;
|
||||
|
||||
typedef struct nr_srs_feedback {
|
||||
uint8_t sri;
|
||||
uint8_t ul_ri;
|
||||
uint8_t tpmi;
|
||||
} nr_srs_feedback_t;
|
||||
|
||||
#endif /*__LAYER2_MAC_H__ */
|
||||
|
||||
|
||||
@@ -312,6 +312,80 @@ const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[16][4]={
|
||||
{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
|
||||
};
|
||||
|
||||
void get_info_from_tda_tables(int default_abc,
|
||||
int tda,
|
||||
int dmrs_TypeA_Position,
|
||||
@@ -1956,6 +2030,46 @@ int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l [12][8] = {
|
||||
{0, 3072, -1, -1, 3, 1539, -1, -1}, //14 // (DMRS l' position)
|
||||
};
|
||||
|
||||
// TS 38.212
|
||||
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};
|
||||
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};
|
||||
uint16_t table_7_3_1_1_2_2_3layers[7] = {10, 28, 29, 56, 57, 58, 59};
|
||||
uint16_t table_7_3_1_1_2_2_4layers[5] = {11, 30, 31, 60, 61};
|
||||
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};
|
||||
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};
|
||||
uint16_t table_7_3_1_1_2_2B_3layers[3] = {10, 14, 33};
|
||||
uint16_t table_7_3_1_1_2_2B_4layers[3] = {11, 34, 35};
|
||||
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};
|
||||
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};
|
||||
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};
|
||||
uint16_t table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[6] = {0, 1, 3, 4, 5, 6};
|
||||
uint16_t table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[3] = {2, 7, 8};
|
||||
uint16_t table_7_3_1_1_2_4A_1layer[3] = {0, 1, 3};
|
||||
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},
|
||||
};
|
||||
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},
|
||||
};
|
||||
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},
|
||||
};
|
||||
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},
|
||||
};
|
||||
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 get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs){
|
||||
|
||||
@@ -2599,13 +2713,18 @@ uint8_t get_pusch_nb_antenna_ports(NR_PUSCH_Config_t *pusch_Config,
|
||||
n_antenna_port = *pusch_Config->maxRank;
|
||||
}
|
||||
else {
|
||||
if(srs_config != NULL && srs_resource_indicator.nbits > 0) {
|
||||
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];
|
||||
if(srs_resource_set->usage == NR_SRS_ResourceSet__usage_codebook) {
|
||||
NR_SRS_Resource_t *srs_resource = srs_config->srs_ResourceToAddModList->list.array[srs_resource_indicator.val];
|
||||
AssertFatal(srs_resource != NULL,"SRS resource indicated by DCI does not exist\n");
|
||||
n_antenna_port = 1<<srs_resource->nrofSRS_Ports;
|
||||
// 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 != NULL, "SRS resource indicated by DCI does not exist\n");
|
||||
n_antenna_port = 1 << srs_resource->nrofSRS_Ports;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2613,6 +2732,372 @@ uint8_t get_pusch_nb_antenna_ports(NR_PUSCH_Config_t *pusch_Config,
|
||||
return n_antenna_port;
|
||||
}
|
||||
|
||||
// #define DEBUG_SRS_RESOURCE_IND
|
||||
uint8_t compute_srs_resource_indicator(NR_PUSCH_ServingCellConfig_t *pusch_servingcellconfig,
|
||||
NR_PUSCH_Config_t *pusch_Config,
|
||||
NR_SRS_Config_t *srs_config,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
uint16_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 && nbits > 0) {
|
||||
*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 (pusch_servingcellconfig != NULL) {
|
||||
if (pusch_servingcellconfig->ext1->maxMIMO_Layers != NULL) {
|
||||
Lmax = *pusch_servingcellconfig->ext1->maxMIMO_Layers;
|
||||
} else {
|
||||
AssertFatal(1 == 0, "MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n");
|
||||
}
|
||||
} 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,
|
||||
uint16_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;
|
||||
}
|
||||
|
||||
uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
const NR_BWP_UplinkCommon_t *initialUplinkBWP,
|
||||
const NR_CellGroupConfig_t *cg,
|
||||
@@ -2629,6 +3114,11 @@ uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
long rbg_size_config;
|
||||
int num_entries = 0;
|
||||
|
||||
NR_UplinkConfig_t *uplinkConfig = NULL;
|
||||
if (cg && cg->spCellConfig && cg->spCellConfig->spCellConfigDedicated) {
|
||||
uplinkConfig = cg->spCellConfig->spCellConfigDedicated->uplinkConfig;
|
||||
}
|
||||
|
||||
const NR_BWP_DownlinkDedicated_t *bwpd = NULL;
|
||||
const NR_BWP_UplinkDedicated_t *ubwpd = NULL;
|
||||
const NR_BWP_DownlinkCommon_t *bwpc = NULL;
|
||||
@@ -2640,23 +3130,21 @@ uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
NR_SRS_Config_t *srs_config = NULL;
|
||||
if(bwp_id > 0) {
|
||||
AssertFatal(cg!=NULL,"Cellgroup is null and bwp_id!=0");
|
||||
bwpd=cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated;
|
||||
bwpc=cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common;
|
||||
ubwpd=cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated;
|
||||
ubwpc=cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common;
|
||||
bwpd = cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated;
|
||||
bwpc = cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common;
|
||||
ubwpd = uplinkConfig ? uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated : NULL;
|
||||
ubwpc = uplinkConfig ? uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common : NULL;
|
||||
pdsch_Config = (bwpd->pdsch_Config) ? bwpd->pdsch_Config->choice.setup : NULL;
|
||||
pdcch_Config = (bwpd->pdcch_Config) ? bwpd->pdcch_Config->choice.setup : NULL;
|
||||
pucch_Config = (ubwpd->pucch_Config) ? ubwpd->pucch_Config->choice.setup : NULL;
|
||||
pusch_Config = (ubwpd->pusch_Config) ? ubwpd->pusch_Config->choice.setup : NULL;
|
||||
srs_config = (ubwpd->srs_Config) ? ubwpd->srs_Config->choice.setup : NULL;
|
||||
}
|
||||
else if (cg){
|
||||
} else if (cg) {
|
||||
bwpc = initialDownlinkBWP;
|
||||
ubwpc = initialUplinkBWP;
|
||||
bwpd = cg->spCellConfig && cg->spCellConfig->spCellConfigDedicated ?
|
||||
cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP : NULL;
|
||||
ubwpd = cg->spCellConfig && cg->spCellConfig->spCellConfigDedicated && cg->spCellConfig->spCellConfigDedicated->uplinkConfig ?
|
||||
cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP : NULL;
|
||||
ubwpd = uplinkConfig ? uplinkConfig->initialUplinkBWP : NULL;
|
||||
pdsch_Config = (bwpd && bwpd->pdsch_Config) ? bwpd->pdsch_Config->choice.setup : NULL;
|
||||
pdcch_Config = (bwpd && bwpd->pdcch_Config) ? bwpd->pdcch_Config->choice.setup : NULL;
|
||||
pucch_Config = (ubwpd && ubwpd->pucch_Config) ? ubwpd->pucch_Config->choice.setup : NULL;
|
||||
@@ -2739,101 +3227,35 @@ uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP,
|
||||
size += 1;
|
||||
}
|
||||
// 1st DAI
|
||||
if (cg->physicalCellGroupConfig &&
|
||||
cg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook==NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic)
|
||||
if (cg->physicalCellGroupConfig && cg->physicalCellGroupConfig->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);
|
||||
LOG_D(NR_MAC, "DAI1 nbits %d\n", dci_pdu->dai[0].nbits);
|
||||
// 2nd DAI
|
||||
if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig &&
|
||||
cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup &&
|
||||
cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { //TODO not sure about that
|
||||
if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig && cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup
|
||||
&& cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { // TODO not sure about that
|
||||
dci_pdu->dai[1].nbits = 2;
|
||||
size += dci_pdu->dai[1].nbits;
|
||||
}
|
||||
// SRS resource indicator
|
||||
if (srs_config &&
|
||||
pusch_Config &&
|
||||
pusch_Config->txConfig != NULL){
|
||||
int count=0;
|
||||
if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){
|
||||
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>1) {
|
||||
dci_pdu->srs_resource_indicator.nbits = 1;
|
||||
size += dci_pdu->srs_resource_indicator.nbits;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int lmin,Lmax = 0;
|
||||
int lsum = 0;
|
||||
if ( cg->spCellConfig->spCellConfigDedicated->uplinkConfig &&
|
||||
cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig != NULL) {
|
||||
if ( cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers != NULL)
|
||||
Lmax = *cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers;
|
||||
else
|
||||
AssertFatal(1==0,"MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n");
|
||||
}
|
||||
else
|
||||
AssertFatal(1==0,"MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n");
|
||||
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++;
|
||||
if (count < Lmax) lmin = count;
|
||||
else lmin = Lmax;
|
||||
for (int k=1;k<=lmin;k++) {
|
||||
lsum += binomial(count,k);
|
||||
}
|
||||
}
|
||||
dci_pdu->srs_resource_indicator.nbits = (int)ceil(log2(lsum));
|
||||
size += dci_pdu->srs_resource_indicator.nbits;
|
||||
}
|
||||
} else dci_pdu->srs_resource_indicator.nbits = 0;
|
||||
LOG_D(NR_MAC,"dci_pdu->srs_resource_indicator.nbits %d\n",dci_pdu->srs_resource_indicator.nbits);
|
||||
NR_PUSCH_ServingCellConfig_t *pusch_servingcellconfig = uplinkConfig && uplinkConfig->pusch_ServingCellConfig ? uplinkConfig->pusch_ServingCellConfig->choice.setup : NULL;
|
||||
dci_pdu->srs_resource_indicator.nbits = compute_srs_resource_indicator(pusch_servingcellconfig, 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
|
||||
long transformPrecoder = get_transformPrecoding(initialUplinkBWP, pusch_Config, ubwpd, (uint8_t*)&format, rnti_type, 0);
|
||||
|
||||
uint8_t pusch_antenna_ports = get_pusch_nb_antenna_ports(pusch_Config, srs_config, dci_pdu->srs_resource_indicator);
|
||||
|
||||
dci_pdu->precoding_information.nbits=0;
|
||||
if (pusch_Config &&
|
||||
pusch_Config->txConfig != NULL){
|
||||
if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){
|
||||
if (pusch_antenna_ports > 1) {
|
||||
if (pusch_antenna_ports == 4) {
|
||||
if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank>1))
|
||||
dci_pdu->precoding_information.nbits = 6-(*pusch_Config->codebookSubset);
|
||||
else {
|
||||
if(*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent)
|
||||
dci_pdu->precoding_information.nbits = 2;
|
||||
else
|
||||
dci_pdu->precoding_information.nbits = 5-(*pusch_Config->codebookSubset);
|
||||
}
|
||||
}
|
||||
else {
|
||||
AssertFatal(pusch_antenna_ports==2,"Not valid number of antenna ports");
|
||||
if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank==2))
|
||||
dci_pdu->precoding_information.nbits = 4-(*pusch_Config->codebookSubset);
|
||||
else
|
||||
dci_pdu->precoding_information.nbits = 3-(*pusch_Config->codebookSubset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
LOG_D(NR_MAC, "dci_pdu->precoding_informaiton.nbits=%d\n", dci_pdu->precoding_information.nbits);
|
||||
// Antenna ports
|
||||
long transformPrecoder = get_transformPrecoding(initialUplinkBWP, pusch_Config, ubwpd, (uint8_t *)&format, rnti_type, 0);
|
||||
NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = NULL;
|
||||
int xa=0;
|
||||
int xb=0;
|
||||
if(pusch_Config &&
|
||||
pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != 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);
|
||||
xa = ul_ant_bits(NR_DMRS_UplinkConfig, transformPrecoder);
|
||||
}
|
||||
if(pusch_Config &&
|
||||
pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL){
|
||||
|
||||
@@ -64,6 +64,19 @@ int is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,slo
|
||||
|
||||
int is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slotP, frame_type_t frame_type);
|
||||
|
||||
uint8_t compute_srs_resource_indicator(NR_PUSCH_ServingCellConfig_t *pusch_servingcellconfig,
|
||||
NR_PUSCH_Config_t *pusch_Config,
|
||||
NR_SRS_Config_t *srs_config,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
uint16_t *val);
|
||||
|
||||
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,
|
||||
uint16_t *val);
|
||||
|
||||
uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDLBWP,
|
||||
const NR_BWP_UplinkCommon_t *initialULBWP,
|
||||
const NR_CellGroupConfig_t *cg,
|
||||
|
||||
@@ -143,4 +143,7 @@ extern const float table_38213_13_12_c3[16];
|
||||
|
||||
extern const int32_t table_38213_10_1_1_c2[5];
|
||||
|
||||
extern const char table_38211_6_3_1_5_1[6][2][1];
|
||||
extern const char table_38211_6_3_1_5_2[28][4][1];
|
||||
extern const char table_38211_6_3_1_5_3[28][4][1];
|
||||
#endif //DEF_H
|
||||
|
||||
@@ -830,6 +830,7 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t
|
||||
scc,
|
||||
pusch_pdu,
|
||||
&uldci_payload,
|
||||
NULL,
|
||||
ra->Msg3_tda_id,
|
||||
ra->msg3_TPC,
|
||||
&ra->UL_BWP);
|
||||
|
||||
@@ -882,6 +882,7 @@ void config_uldci(const NR_SIB1_t *sib1,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
int time_domain_assignment,
|
||||
uint8_t tpc,
|
||||
NR_UE_UL_BWP_t *ul_bwp) {
|
||||
@@ -916,13 +917,14 @@ void config_uldci(const NR_SIB1_t *sib1,
|
||||
pusch_Config->txConfig != NULL) {
|
||||
AssertFatal(*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook,
|
||||
"Non Codebook configuration non supported\n");
|
||||
dci_pdu_rel15->srs_resource_indicator.val = 0; // taking resource 0 for SRS
|
||||
compute_srs_resource_indicator(ul_bwp->pusch_servingcellconfig, pusch_Config, ul_bwp->srs_Config, srs_feedback, &dci_pdu_rel15->srs_resource_indicator.val);
|
||||
}
|
||||
dci_pdu_rel15->precoding_information.val= 0;
|
||||
if (pusch_pdu->nrOfLayers == 2)
|
||||
dci_pdu_rel15->precoding_information.val = 4;
|
||||
else if (pusch_pdu->nrOfLayers == 4)
|
||||
dci_pdu_rel15->precoding_information.val = 11;
|
||||
compute_precoding_information(pusch_Config,
|
||||
ul_bwp->srs_Config,
|
||||
dci_pdu_rel15->srs_resource_indicator,
|
||||
srs_feedback,
|
||||
&pusch_pdu->nrOfLayers,
|
||||
&dci_pdu_rel15->precoding_information.val);
|
||||
|
||||
// antenna_ports.val = 0 for transform precoder is disabled, dmrs-Type=1, maxLength=1, Rank=1/2/3/4
|
||||
// Antenna Ports
|
||||
@@ -1018,7 +1020,7 @@ int nr_get_pucch_resource(NR_ControlResourceSet_t *coreset,
|
||||
// This function configures pucch pdu fapi structure
|
||||
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
NR_UE_info_t* UE,
|
||||
NR_UE_info_t *UE,
|
||||
uint8_t pucch_resource,
|
||||
uint16_t O_csi,
|
||||
uint16_t O_ack,
|
||||
@@ -2456,6 +2458,12 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
false);
|
||||
}
|
||||
|
||||
void reset_srs_stats(NR_UE_info_t *UE) {
|
||||
if (UE) {
|
||||
UE->mac_stats.srs_stats[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup)
|
||||
{
|
||||
@@ -2522,6 +2530,8 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
|
||||
create_nr_list(&sched_ctrl->feedback_ul_harq, 16);
|
||||
create_nr_list(&sched_ctrl->retrans_ul_harq, 16);
|
||||
|
||||
reset_srs_stats(UE);
|
||||
|
||||
pthread_mutex_lock(&UE_info->mutex);
|
||||
int i;
|
||||
for(i=0; i<MAX_MOBILES_PER_GNB; i++) {
|
||||
@@ -2929,6 +2939,8 @@ void nr_mac_update_timers(module_id_t module_id,
|
||||
if (sched_ctrl->rrc_processing_timer == 0) {
|
||||
LOG_I(NR_MAC, "(%d.%d) De-activating RRC processing timer for UE %04x\n", frame, slot, UE->rnti);
|
||||
|
||||
reset_srs_stats(UE);
|
||||
|
||||
NR_CellGroupConfig_t *cg = NULL;
|
||||
uper_decode(NULL,
|
||||
&asn_DEF_NR_CellGroupConfig, //might be added prefix later
|
||||
|
||||
@@ -35,7 +35,12 @@
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id,NR_UE_info_t* UE, NR_SRS_Resource_t *srs_resource) {
|
||||
const uint16_t m_SRS[64] = { 4, 8, 12, 16, 16, 20, 24, 24, 28, 32, 36, 40, 48, 48, 52, 56, 60, 64, 72, 72, 76, 80, 88,
|
||||
96, 96, 104, 112, 120, 120, 120, 128, 128, 128, 132, 136, 144, 144, 144, 144, 152, 160,
|
||||
160, 160, 168, 176, 184, 192, 192, 192, 192, 208, 216, 224, 240, 240, 240, 240, 256, 256,
|
||||
256, 264, 272, 272, 272 };
|
||||
|
||||
void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id,NR_UE_info_t* UE, NR_SRS_ResourceSet_t *srs_resource_set, NR_SRS_Resource_t *srs_resource) {
|
||||
|
||||
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
|
||||
|
||||
@@ -74,9 +79,22 @@ void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id,NR_U
|
||||
srs_pdu->resource_type = srs_resource->resourceType.present - 1;
|
||||
srs_pdu->t_srs = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
|
||||
srs_pdu->t_offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
|
||||
|
||||
// TODO: This should be completed
|
||||
srs_pdu->srs_parameters_v4.srs_bandwidth_size = m_SRS[srs_pdu->config_index];
|
||||
srs_pdu->srs_parameters_v4.usage = 1<<srs_resource_set->usage;
|
||||
srs_pdu->srs_parameters_v4.report_type[0] = 1;
|
||||
srs_pdu->srs_parameters_v4.iq_representation = 1;
|
||||
srs_pdu->srs_parameters_v4.prg_size = 1;
|
||||
srs_pdu->srs_parameters_v4.num_total_ue_antennas = 1<<srs_pdu->num_ant_ports;
|
||||
if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_beamManagement) {
|
||||
srs_pdu->beamforming.trp_scheme = 0;
|
||||
srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index];
|
||||
srs_pdu->beamforming.prg_size = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_fill_nfapi_srs(int module_id, int CC_id, NR_UE_info_t* UE, sub_frame_t slot, NR_SRS_Resource_t *srs_resource) {
|
||||
void nr_fill_nfapi_srs(int module_id, int CC_id, NR_UE_info_t* UE, sub_frame_t slot, NR_SRS_ResourceSet_t *srs_resource_set, NR_SRS_Resource_t *srs_resource) {
|
||||
|
||||
nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_id]->UL_tti_req_ahead[0][slot];
|
||||
AssertFatal(future_ul_tti_req->n_pdus <
|
||||
@@ -88,7 +106,7 @@ void nr_fill_nfapi_srs(int module_id, int CC_id, NR_UE_info_t* UE, sub_frame_t s
|
||||
memset(srs_pdu, 0, sizeof(nfapi_nr_srs_pdu_t));
|
||||
future_ul_tti_req->n_pdus += 1;
|
||||
|
||||
nr_configure_srs(srs_pdu, module_id, CC_id, UE, srs_resource);
|
||||
nr_configure_srs(srs_pdu, module_id, CC_id, UE, srs_resource_set, srs_resource);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -158,7 +176,7 @@ void nr_schedule_srs(int module_id, frame_t frame) {
|
||||
// Check if UE will transmit the SRS in this frame
|
||||
if ( ((frame - offset/n_slots_frame)*n_slots_frame)%period == 0) {
|
||||
LOG_D(NR_MAC,"Scheduling SRS reception for %d.%d\n", frame, offset%n_slots_frame);
|
||||
nr_fill_nfapi_srs(module_id, CC_id, UE, offset%n_slots_frame, srs_resource);
|
||||
nr_fill_nfapi_srs(module_id, CC_id, UE, offset%n_slots_frame, srs_resource_set, srs_resource);
|
||||
sched_ctrl->sched_srs.frame = frame;
|
||||
sched_ctrl->sched_srs.slot = offset%n_slots_frame;
|
||||
sched_ctrl->sched_srs.srs_scheduled = true;
|
||||
|
||||
@@ -786,60 +786,460 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t calc_power_complex(const int16_t *x, const int16_t *y, const uint32_t size) {
|
||||
|
||||
// Real part value
|
||||
int64_t sum_x = 0;
|
||||
int64_t sum_x2 = 0;
|
||||
for(int k = 0; k<size; k++) {
|
||||
sum_x = sum_x + x[k];
|
||||
sum_x2 = sum_x2 + x[k]*x[k];
|
||||
}
|
||||
uint32_t power_re = sum_x2/size - (sum_x/size)*(sum_x/size);
|
||||
|
||||
// Imaginary part power
|
||||
int64_t sum_y = 0;
|
||||
int64_t sum_y2 = 0;
|
||||
for(int k = 0; k<size; k++) {
|
||||
sum_y = sum_y + y[k];
|
||||
sum_y2 = sum_y2 + y[k]*y[k];
|
||||
}
|
||||
uint32_t power_im = sum_y2/size - (sum_y/size)*(sum_y/size);
|
||||
|
||||
return power_re+power_im;
|
||||
}
|
||||
|
||||
c16_t nr_h_times_w(c16_t h, char w) {
|
||||
c16_t output;
|
||||
switch (w) {
|
||||
case '0': // 0
|
||||
output.r = 0;
|
||||
output.i = 0;
|
||||
break;
|
||||
case '1': // 1
|
||||
output.r = h.r;
|
||||
output.i = h.i;
|
||||
break;
|
||||
case 'n': // -1
|
||||
output.r = -h.r;
|
||||
output.i = -h.i;
|
||||
break;
|
||||
case 'j': // j
|
||||
output.r = -h.i;
|
||||
output.i = h.r;
|
||||
break;
|
||||
case 'o': // -j
|
||||
output.r = h.i;
|
||||
output.i = -h.r;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid precoder value %c\n", w);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
uint8_t get_max_tpmi(const NR_PUSCH_Config_t *pusch_Config,
|
||||
const uint16_t num_ue_srs_ports,
|
||||
const uint8_t *nrOfLayers,
|
||||
int *additional_max_tpmi) {
|
||||
|
||||
uint8_t max_tpmi = 0;
|
||||
|
||||
if ((pusch_Config && pusch_Config->txConfig != NULL && *pusch_Config->txConfig == NR_PUSCH_Config__txConfig_nonCodebook) ||
|
||||
num_ue_srs_ports == 1) {
|
||||
return max_tpmi;
|
||||
}
|
||||
|
||||
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 (num_ue_srs_ports == 2) {
|
||||
|
||||
if (max_rank == 1) {
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
max_tpmi = 2;
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
max_tpmi = 1;
|
||||
} else {
|
||||
max_tpmi = 5;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
max_tpmi = *nrOfLayers == 1 ? 2 : 0;
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
max_tpmi = *nrOfLayers == 1 ? 1 : 0;
|
||||
} else {
|
||||
max_tpmi = *nrOfLayers == 1 ? 5 : 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (num_ue_srs_ports == 4) {
|
||||
|
||||
if (max_rank == 1) {
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
max_tpmi = 3;
|
||||
*additional_max_tpmi = 13;
|
||||
} else {
|
||||
max_tpmi = 15;
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
max_tpmi = 3;
|
||||
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
|
||||
max_tpmi = 11;
|
||||
} else {
|
||||
max_tpmi = 27;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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) {
|
||||
max_tpmi = *nrOfLayers == 1 ? 3 : 6;
|
||||
if (*nrOfLayers == 1) {
|
||||
*additional_max_tpmi = 13;
|
||||
}
|
||||
} else {
|
||||
max_tpmi = *nrOfLayers == 1 ? 15 : 13;
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 3;
|
||||
*additional_max_tpmi = 13;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 6;
|
||||
break;
|
||||
case 3:
|
||||
max_tpmi = 1;
|
||||
break;
|
||||
case 4:
|
||||
max_tpmi = 0;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
} else {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 15;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 13;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
max_tpmi = 2;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 3;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 5;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
max_tpmi = 0;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 11;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 13;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
max_tpmi = 2;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
} else {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
max_tpmi = 28;
|
||||
break;
|
||||
case 2:
|
||||
max_tpmi = 22;
|
||||
break;
|
||||
case 3:
|
||||
max_tpmi = 7;
|
||||
break;
|
||||
case 4:
|
||||
max_tpmi = 5;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return max_tpmi;
|
||||
}
|
||||
|
||||
void get_precoder_matrix_coef(char *w,
|
||||
const uint8_t ul_ri,
|
||||
const uint16_t num_ue_srs_ports,
|
||||
const uint8_t transform_precoding,
|
||||
const uint8_t tpmi,
|
||||
const uint8_t uI) {
|
||||
if (ul_ri == 0) {
|
||||
if (num_ue_srs_ports == 2) {
|
||||
*w = *table_38211_6_3_1_5_1[tpmi][uI];
|
||||
} else {
|
||||
if (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) {
|
||||
*w = *table_38211_6_3_1_5_2[tpmi][uI];
|
||||
} else {
|
||||
*w = *table_38211_6_3_1_5_3[tpmi][uI];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AssertFatal(1==0,"Function get_precoder_matrix_coef() does not support %i layers yet!\n", ul_ri+1);
|
||||
}
|
||||
}
|
||||
|
||||
int nr_srs_tpmi_estimation(const NR_PUSCH_Config_t *pusch_Config,
|
||||
const uint8_t transform_precoding,
|
||||
const uint8_t *channel_matrix,
|
||||
const uint8_t normalized_iq_representation,
|
||||
const uint16_t num_gnb_antenna_elements,
|
||||
const uint16_t num_ue_srs_ports,
|
||||
const uint16_t prg_size,
|
||||
const uint16_t num_prgs,
|
||||
const uint8_t ul_ri) {
|
||||
|
||||
uint8_t tpmi_sel = 0;
|
||||
int16_t precoded_channel_matrix_re[num_prgs*num_gnb_antenna_elements];
|
||||
int16_t precoded_channel_matrix_im[num_prgs*num_gnb_antenna_elements];
|
||||
c16_t *channel_matrix16 = (c16_t*)channel_matrix;
|
||||
uint32_t max_precoded_signal_power = 0;
|
||||
int additional_max_tpmi = -1;
|
||||
char w;
|
||||
|
||||
uint8_t max_tpmi = get_max_tpmi(pusch_Config,
|
||||
num_ue_srs_ports,
|
||||
&ul_ri,
|
||||
&additional_max_tpmi);
|
||||
|
||||
uint8_t end_tpmi_loop = additional_max_tpmi > max_tpmi ? additional_max_tpmi : max_tpmi;
|
||||
|
||||
// channel_matrix x precoder_matrix
|
||||
// [ (gI=0,uI=0) (gI=0,uI=1) ... (gI=0,uI=num_ue_srs_ports-1) ] x [uI=0]
|
||||
// [ (gI=1,uI=0) (gI=1,uI=1) ... (gI=1,uI=num_ue_srs_ports-1) ] [uI=1]
|
||||
// [ (gI=2,uI=0) (gI=2,uI=1) ... (gI=2,uI=num_ue_srs_ports-1) ] [uI=2]
|
||||
// ... ...
|
||||
|
||||
for(uint8_t tpmi = 0; tpmi<=end_tpmi_loop; tpmi++) {
|
||||
|
||||
if (tpmi > max_tpmi) {
|
||||
tpmi = end_tpmi_loop;
|
||||
}
|
||||
|
||||
for(int pI = 0; pI <num_prgs; pI++) {
|
||||
for(int gI = 0; gI < num_gnb_antenna_elements; gI++) {
|
||||
|
||||
uint16_t index_gI_pI = gI*num_prgs + pI;
|
||||
precoded_channel_matrix_re[index_gI_pI] = 0;
|
||||
precoded_channel_matrix_im[index_gI_pI] = 0;
|
||||
|
||||
for(int uI = 0; uI < num_ue_srs_ports; uI++) {
|
||||
|
||||
uint16_t index = uI*num_gnb_antenna_elements*num_prgs + index_gI_pI;
|
||||
get_precoder_matrix_coef(&w, ul_ri, num_ue_srs_ports, transform_precoding, tpmi, uI);
|
||||
c16_t h_times_w = nr_h_times_w(channel_matrix16[index], w);
|
||||
|
||||
precoded_channel_matrix_re[index_gI_pI] += h_times_w.r;
|
||||
precoded_channel_matrix_im[index_gI_pI] += h_times_w.i;
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n",
|
||||
uI, gI, pI, channel_matrix16[index].r, channel_matrix16[index].i);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "(gI %i, pI %i) precoded_channel_coef --> real %i, imag %i\n",
|
||||
gI, pI, precoded_channel_matrix_re[index_gI_pI], precoded_channel_matrix_im[index_gI_pI]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t precoded_signal_power = calc_power_complex(precoded_channel_matrix_re,
|
||||
precoded_channel_matrix_im,
|
||||
num_prgs*num_gnb_antenna_elements);
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "(tpmi %i) precoded_signal_power = %i\n", tpmi, precoded_signal_power);
|
||||
#endif
|
||||
|
||||
if (precoded_signal_power > max_precoded_signal_power) {
|
||||
max_precoded_signal_power = precoded_signal_power;
|
||||
tpmi_sel = tpmi;
|
||||
}
|
||||
}
|
||||
|
||||
return tpmi_sel;
|
||||
}
|
||||
|
||||
void handle_nr_srs_measurements(const module_id_t module_id,
|
||||
const frame_t frame,
|
||||
const sub_frame_t slot,
|
||||
const rnti_t rnti,
|
||||
const uint16_t timing_advance,
|
||||
const uint8_t num_symbols,
|
||||
const uint8_t wide_band_snr,
|
||||
const uint8_t num_reported_symbols,
|
||||
nfapi_nr_srs_indication_reported_symbol_t *reported_symbol_list)
|
||||
const nfapi_nr_srs_indication_pdu_t *srs_ind)
|
||||
{
|
||||
LOG_D(NR_MAC, "(%d.%d) Received SRS indication for rnti: 0x%04x\n", frame, slot, rnti);
|
||||
LOG_D(NR_MAC, "(%d.%d) Received SRS indication for UE %04x\n", frame, slot, srs_ind->rnti);
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "frame = %i\n", frame);
|
||||
LOG_I(NR_MAC, "slot = %i\n", slot);
|
||||
LOG_I(NR_MAC, "rnti = 0x%04x\n", rnti);
|
||||
LOG_I(NR_MAC, "timing_advance = %i\n", timing_advance);
|
||||
LOG_I(NR_MAC, "num_symbols = %i\n", num_symbols);
|
||||
LOG_I(NR_MAC, "wide_band_snr = %i (%i dB)\n", wide_band_snr, (wide_band_snr >> 1) - 64);
|
||||
LOG_I(NR_MAC, "num_reported_symbols = %i\n", num_reported_symbols);
|
||||
LOG_I(NR_MAC, "reported_symbol_list[0].num_rbs = %i\n", reported_symbol_list[0].num_rbs);
|
||||
for (int rb = 0; rb < reported_symbol_list[0].num_rbs; rb++) {
|
||||
LOG_I(NR_MAC, "reported_symbol_list[0].rb_list[%3i].rb_snr = %i (%i dB)\n", rb, reported_symbol_list[0].rb_list[rb].rb_snr, (reported_symbol_list[0].rb_list[rb].rb_snr >> 1) - 64);
|
||||
}
|
||||
LOG_I(NR_MAC, "srs_ind->rnti = %04x\n", srs_ind->rnti);
|
||||
LOG_I(NR_MAC, "srs_ind->timing_advance_offset = %i\n", srs_ind->timing_advance_offset);
|
||||
LOG_I(NR_MAC, "srs_ind->timing_advance_offset_nsec = %i\n", srs_ind->timing_advance_offset_nsec);
|
||||
LOG_I(NR_MAC, "srs_ind->srs_usage = %i\n", srs_ind->srs_usage);
|
||||
LOG_I(NR_MAC, "srs_ind->report_type = %i\n", srs_ind->report_type);
|
||||
#endif
|
||||
|
||||
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, rnti);
|
||||
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, srs_ind->rnti);
|
||||
if (!UE) {
|
||||
LOG_E(NR_MAC, "Could not find UE for RNTI %04x\n", rnti);
|
||||
LOG_W(NR_MAC, "Could not find UE for RNTI %04x\n", srs_ind->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wide_band_snr == 0xFF) {
|
||||
LOG_W(NR_MAC, "Invalid wide_band_snr for RNTI %04x\n", rnti);
|
||||
if (srs_ind->timing_advance_offset == 0xFFFF) {
|
||||
LOG_W(NR_MAC, "Invalid timing advance offset for RNTI %04x\n", srs_ind->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
int wide_band_snr_dB = (wide_band_snr >> 1) - 64;
|
||||
|
||||
gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
|
||||
NR_mac_stats_t *stats = &UE->mac_stats;
|
||||
stats->srs_wide_band_snr = wide_band_snr_dB;
|
||||
|
||||
const int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold;
|
||||
uint16_t *ulprbbl = nr_mac->ulprbbl;
|
||||
switch (srs_ind->srs_usage) {
|
||||
case NR_SRS_ResourceSet__usage_beamManagement: {
|
||||
nfapi_nr_srs_beamforming_report_t nr_srs_beamforming_report;
|
||||
unpack_nr_srs_beamforming_report(srs_ind->report_tlv->value,
|
||||
srs_ind->report_tlv->length,
|
||||
&nr_srs_beamforming_report,
|
||||
sizeof(nfapi_nr_srs_beamforming_report_t));
|
||||
|
||||
memset(ulprbbl, 0, reported_symbol_list[0].num_rbs * sizeof(uint16_t));
|
||||
if (nr_srs_beamforming_report.wide_band_snr == 0xFF) {
|
||||
LOG_W(NR_MAC, "Invalid wide_band_snr for RNTI %04x\n", srs_ind->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int rb = 0; rb < reported_symbol_list[0].num_rbs; rb++) {
|
||||
int snr = (reported_symbol_list[0].rb_list[rb].rb_snr >> 1) - 64;
|
||||
if (snr < wide_band_snr_dB - ul_prbblack_SNR_threshold) {
|
||||
ulprbbl[rb] = 0x3FFF; // all symbols taken
|
||||
int wide_band_snr_dB = (nr_srs_beamforming_report.wide_band_snr >> 1) - 64;
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.prg_size = %i\n", nr_srs_beamforming_report.prg_size);
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.num_symbols = %i\n", nr_srs_beamforming_report.num_symbols);
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.wide_band_snr = %i (%i dB)\n", nr_srs_beamforming_report.wide_band_snr, wide_band_snr_dB);
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.num_reported_symbols = %i\n", nr_srs_beamforming_report.num_reported_symbols);
|
||||
LOG_I(NR_MAC, "nr_srs_beamforming_report.prgs[0].num_prgs = %i\n", nr_srs_beamforming_report.prgs[0].num_prgs);
|
||||
for (int prg_idx = 0; prg_idx < nr_srs_beamforming_report.prgs[0].num_prgs; prg_idx++) {
|
||||
LOG_I(NR_MAC,
|
||||
"nr_srs_beamforming_report.prgs[0].prg_list[%3i].rb_snr = %i (%i dB)\n",
|
||||
prg_idx,
|
||||
nr_srs_beamforming_report.prgs[0].prg_list[prg_idx].rb_snr,
|
||||
(nr_srs_beamforming_report.prgs[0].prg_list[prg_idx].rb_snr >> 1) - 64);
|
||||
}
|
||||
#endif
|
||||
|
||||
sprintf(stats->srs_stats, "UL-SNR %i dB", wide_band_snr_dB);
|
||||
|
||||
const int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold;
|
||||
uint16_t *ulprbbl = nr_mac->ulprbbl;
|
||||
|
||||
uint8_t num_rbs = nr_srs_beamforming_report.prg_size * nr_srs_beamforming_report.prgs[0].num_prgs;
|
||||
memset(ulprbbl, 0, num_rbs * sizeof(uint16_t));
|
||||
for (int rb = 0; rb < num_rbs; rb++) {
|
||||
int snr = (nr_srs_beamforming_report.prgs[0].prg_list[rb / nr_srs_beamforming_report.prg_size].rb_snr >> 1) - 64;
|
||||
if (snr < wide_band_snr_dB - ul_prbblack_SNR_threshold) {
|
||||
ulprbbl[rb] = 0x3FFF; // all symbols taken
|
||||
}
|
||||
LOG_D(NR_MAC, "ulprbbl[%3i] = 0x%x\n", rb, ulprbbl[rb]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
LOG_D(NR_MAC, "ulprbbl[%3i] = 0x%x\n", rb, ulprbbl[rb]);
|
||||
|
||||
case NR_SRS_ResourceSet__usage_codebook: {
|
||||
nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_normalized_channel_iq_matrix;
|
||||
unpack_nr_srs_normalized_channel_iq_matrix(srs_ind->report_tlv->value,
|
||||
srs_ind->report_tlv->length,
|
||||
&nr_srs_normalized_channel_iq_matrix,
|
||||
sizeof(nfapi_nr_srs_normalized_channel_iq_matrix_t));
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.normalized_iq_representation = %i\n", nr_srs_normalized_channel_iq_matrix.normalized_iq_representation);
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements = %i\n", nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements);
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports = %i\n", nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports);
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.prg_size = %i\n", nr_srs_normalized_channel_iq_matrix.prg_size);
|
||||
LOG_I(NR_MAC, "nr_srs_normalized_channel_iq_matrix.num_prgs = %i\n", nr_srs_normalized_channel_iq_matrix.num_prgs);
|
||||
c16_t *channel_matrix16 = (c16_t *)nr_srs_normalized_channel_iq_matrix.channel_matrix;
|
||||
c8_t *channel_matrix8 = (c8_t *)nr_srs_normalized_channel_iq_matrix.channel_matrix;
|
||||
for (int uI = 0; uI < nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports; uI++) {
|
||||
for (int gI = 0; gI < nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements; gI++) {
|
||||
for (int pI = 0; pI < nr_srs_normalized_channel_iq_matrix.num_prgs; pI++) {
|
||||
uint16_t index = uI * nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_normalized_channel_iq_matrix.num_prgs + gI * nr_srs_normalized_channel_iq_matrix.num_prgs + pI;
|
||||
LOG_I(NR_MAC,
|
||||
"(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n",
|
||||
uI,
|
||||
gI,
|
||||
pI,
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].r : channel_matrix16[index].r,
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].i : channel_matrix16[index].i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: This should be improved
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
|
||||
sched_ctrl->srs_feedback.sri = NR_SRS_SRI_0;
|
||||
sched_ctrl->srs_feedback.ul_ri = 0; // TODO: Compute this
|
||||
sched_ctrl->srs_feedback.tpmi = nr_srs_tpmi_estimation(current_BWP->pusch_Config,
|
||||
current_BWP->transform_precoding,
|
||||
nr_srs_normalized_channel_iq_matrix.channel_matrix,
|
||||
nr_srs_normalized_channel_iq_matrix.normalized_iq_representation,
|
||||
nr_srs_normalized_channel_iq_matrix.num_gnb_antenna_elements,
|
||||
nr_srs_normalized_channel_iq_matrix.num_ue_srs_ports,
|
||||
nr_srs_normalized_channel_iq_matrix.prg_size,
|
||||
nr_srs_normalized_channel_iq_matrix.num_prgs,
|
||||
sched_ctrl->srs_feedback.ul_ri);
|
||||
sprintf(stats->srs_stats, "UL-RI %d, TPMI %d", sched_ctrl->srs_feedback.ul_ri + 1, sched_ctrl->srs_feedback.tpmi);
|
||||
break;
|
||||
}
|
||||
|
||||
case NR_SRS_ResourceSet__usage_nonCodebook:
|
||||
case NR_SRS_ResourceSet__usage_antennaSwitching:
|
||||
LOG_W(NR_MAC, "MAC procedures for this SRS usage are not implemented yet!\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid SRS usage\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1851,9 +2251,11 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
|
||||
scc,
|
||||
pusch_pdu,
|
||||
&uldci_payload,
|
||||
&sched_ctrl->srs_feedback,
|
||||
sched_pusch->time_domain_allocation,
|
||||
UE->UE_sched_ctrl.tpc0,
|
||||
current_BWP);
|
||||
|
||||
fill_dci_pdu_rel15(scc,
|
||||
cg,
|
||||
&UE->current_DL_BWP,
|
||||
|
||||
@@ -189,6 +189,7 @@ void config_uldci(const NR_SIB1_t *sib1,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
int time_domain_assignment,
|
||||
uint8_t tpc,
|
||||
NR_UE_UL_BWP_t *ul_bwp);
|
||||
@@ -441,12 +442,7 @@ void handle_nr_ul_harq(const int CC_idP,
|
||||
void handle_nr_srs_measurements(const module_id_t module_id,
|
||||
const frame_t frame,
|
||||
const sub_frame_t slot,
|
||||
const rnti_t rnti,
|
||||
const uint16_t timing_advance,
|
||||
const uint8_t num_symbols,
|
||||
const uint8_t wide_band_snr,
|
||||
const uint8_t num_reported_symbols,
|
||||
nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list);
|
||||
const nfapi_nr_srs_indication_pdu_t *srs_ind);
|
||||
|
||||
int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
frame_t frameP,
|
||||
|
||||
@@ -93,14 +93,14 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE RNTI %04x (%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas), UL-SNR %d dB\n",
|
||||
"UE RNTI %04x (%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas)\n",
|
||||
UE->rnti,
|
||||
num++,
|
||||
sched_ctrl->ph,
|
||||
sched_ctrl->pcmax,
|
||||
avg_rsrp,
|
||||
stats->num_rsrp_meas,
|
||||
stats->srs_wide_band_snr);
|
||||
stats->num_rsrp_meas);
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: CQI %d, RI %d, PMI (%d,%d)\n",
|
||||
@@ -110,6 +110,10 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x1,
|
||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2);
|
||||
|
||||
if (stats->srs_stats[0] != '\0') {
|
||||
output += snprintf(output, end - output, "UE %04x: %s\n", UE->rnti, stats->srs_stats);
|
||||
}
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: dlsch_rounds ", UE->rnti);
|
||||
|
||||
@@ -634,7 +634,7 @@ typedef struct {
|
||||
NR_list_t feedback_ul_harq;
|
||||
/// UL HARQ processes that await retransmission
|
||||
NR_list_t retrans_ul_harq;
|
||||
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information
|
||||
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl; // MAC CE related information
|
||||
/// number of active DL LCs
|
||||
uint8_t dl_lc_num;
|
||||
/// order in which DLSCH scheduler should allocate LCs
|
||||
@@ -642,6 +642,9 @@ typedef struct {
|
||||
|
||||
/// Timer for RRC processing procedures
|
||||
uint32_t rrc_processing_timer;
|
||||
|
||||
/// sri, ul_ri and tpmi based on SRS
|
||||
nr_srs_feedback_t srs_feedback;
|
||||
} NR_UE_sched_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -668,7 +671,7 @@ typedef struct NR_mac_stats {
|
||||
uint32_t pucch0_DTX;
|
||||
int cumul_rsrp;
|
||||
uint8_t num_rsrp_meas;
|
||||
int8_t srs_wide_band_snr;
|
||||
char srs_stats[50]; // Statistics may differ depending on SRS usage
|
||||
} NR_mac_stats_t;
|
||||
|
||||
typedef struct NR_bler_options {
|
||||
|
||||
Reference in New Issue
Block a user