diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 568d946056..e5b7e74169 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -386,6 +386,39 @@ const char table_38211_6_3_1_5_3[28][4][1] = { {{'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 +}; + void get_info_from_tda_tables(int default_abc, int tda, int dmrs_TypeA_Position, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h index 01864f02c5..3648ad2c91 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h @@ -146,4 +146,6 @@ 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]; +extern const char table_38211_6_3_1_5_4[3][2][2]; +extern const char table_38211_6_3_1_5_5[22][4][2]; #endif //DEF_H diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 0318418370..ee8dc69bd3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1033,19 +1033,27 @@ void get_precoder_matrix_coef(char *w, const uint16_t num_ue_srs_ports, const uint8_t transform_precoding, const uint8_t tpmi, - const uint8_t uI) { + const uint8_t uI, + int layer_idx) +{ if (ul_ri == 0) { if (num_ue_srs_ports == 2) { - *w = *table_38211_6_3_1_5_1[tpmi][uI]; + *w = table_38211_6_3_1_5_1[tpmi][uI][layer_idx]; } else { if (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) { - *w = *table_38211_6_3_1_5_2[tpmi][uI]; + *w = table_38211_6_3_1_5_2[tpmi][uI][layer_idx]; } else { - *w = *table_38211_6_3_1_5_3[tpmi][uI]; + *w = table_38211_6_3_1_5_3[tpmi][uI][layer_idx]; } } + } else if (ul_ri == 1) { + if (num_ue_srs_ports == 2) { + *w = table_38211_6_3_1_5_4[tpmi][uI][layer_idx]; + } else { + *w = table_38211_6_3_1_5_5[tpmi][uI][layer_idx]; + } } else { - AssertFatal(1==0,"Function get_precoder_matrix_coef() does not support %i layers yet!\n", ul_ri+1); + AssertFatal(1 == 0, "Function get_precoder_matrix_coef() does not support %i layers yet!\n", ul_ri + 1); } } @@ -1058,20 +1066,21 @@ int nr_srs_tpmi_estimation(const NR_PUSCH_Config_t *pusch_Config, const uint16_t prg_size, const uint16_t num_prgs, const uint8_t ul_ri) { + if (ul_ri > 1) { + LOG_D(NR_MAC, "TPMI computation for ul_ri %i is not implemented yet!\n", ul_ri); + return 0; + } 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; + const uint8_t nrOfLayers = ul_ri + 1; + 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 max_tpmi = get_max_tpmi(pusch_Config, num_ue_srs_ports, &nrOfLayers, &additional_max_tpmi); uint8_t end_tpmi_loop = additional_max_tpmi > max_tpmi ? additional_max_tpmi : max_tpmi; // channel_matrix x precoder_matrix @@ -1080,44 +1089,43 @@ int nr_srs_tpmi_estimation(const NR_PUSCH_Config_t *pusch_Config, // [ (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++) { - + for (uint8_t tpmi = 0; tpmi <= end_tpmi_loop && end_tpmi_loop > 0; tpmi++) { if (tpmi > max_tpmi) { tpmi = end_tpmi_loop; } - for(int pI = 0; pI real %i, imag %i\n", - uI, gI, pI, channel_matrix16[index].r, channel_matrix16[index].i); + LOG_I(NR_MAC, "(pI %i, gI %i, uI %i, layer_idx %i) w = %c, channel_matrix --> real %i, imag %i\n", + pI, gI, uI, layer_idx, w, 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]); + LOG_I(NR_MAC, "(pI %i, gI %i) precoded_channel_coef --> real %i, imag %i\n", + pI, gI, 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); + 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); @@ -1198,7 +1206,7 @@ void handle_nr_srs_measurements(const module_id_t module_id, 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; + uint16_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; @@ -1242,11 +1250,12 @@ void handle_nr_srs_measurements(const module_id_t module_id, } #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 + + nr_srs_ri_computation(&nr_srs_normalized_channel_iq_matrix, current_BWP, &sched_ctrl->srs_feedback.ul_ri); + 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, @@ -1256,7 +1265,9 @@ void handle_nr_srs_measurements(const module_id_t module_id, 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; } @@ -1525,7 +1536,6 @@ static int comparator(const void *p, const void *q) { return ((UEsched_t*)p)->coef < ((UEsched_t*)q)->coef; } - void pf_ul(module_id_t module_id, frame_t frame, sub_frame_t slot, @@ -1690,7 +1700,7 @@ void pf_ul(module_id_t module_id, qsort(UE_sched, sizeof(*UE_sched), sizeofArray(UE_sched), comparator); UEsched_t *iterator=UE_sched; - + /* Loop UE_sched to find max coeff and allocate transmission */ while (remainUEs> 0 && n_rb_sched >= min_rb && iterator->UE != NULL) {