diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 2d7e4ce02f..c1ed6c7546 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -105,6 +105,16 @@ int get_supported_band_index(int scs, frequency_range_t freq_range, int n_rbs) return (-1); // not found } +int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_range, int n_rbs) +{ + int scs_index = scs + frequency_range; + for (int i = 0; i < 12; i++) { + if (n_rbs <= tables_5_3_2[scs_index][i]) + return i; + } + return -1; // not found +} + // Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) // Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101) // Notes: @@ -299,64 +309,30 @@ void check_ssb_raster(uint64_t freq, int band, int scs) band); } -int get_supported_bw_mhz(frequency_range_t frequency_range, int scs, int nb_rb) +int get_supported_bw_mhz(frequency_range_t frequency_range, int bw_index) { - int bw_index = get_supported_band_index(scs, frequency_range, nb_rb); if (frequency_range == FR1) { - switch (bw_index) { - case 0 : - return 5; // 5MHz - case 1 : - return 10; - case 2 : - return 15; - case 3 : - return 20; - case 4 : - return 25; - case 5 : - return 30; - case 6 : - return 40; - case 7 : - return 50; - case 8 : - return 60; - case 9 : - return 80; - case 10 : - return 90; - case 11 : - return 100; - default : - AssertFatal(false, "Invalid band index for FR1 %d\n", bw_index); - } - } - else { - switch (bw_index) { - case 0 : - return 50; // 50MHz - case 1 : - return 100; - case 2 : - return 200; - case 3 : - return 400; - default : - AssertFatal(false, "Invalid band index for FR2 %d\n", bw_index); - } + int bandwidth_index_to_mhz[] = {5, 10, 15, 20, 25, 30, 40, 50, 60, 80, 90, 100}; + AssertFatal(bw_index >= 0 && bw_index <= sizeofArray(bandwidth_index_to_mhz), + "Bandwidth index %d is invalid\n", + bw_index); + return bandwidth_index_to_mhz[bw_index]; + } else { + int bandwidth_index_to_mhz[] = {50, 100, 200, 400}; + AssertFatal(bw_index >= 0 && bw_index <= sizeofArray(bandwidth_index_to_mhz), + "Bandwidth index %d is invalid\n", + bw_index); + return bandwidth_index_to_mhz[bw_index]; } } -bool compare_relative_ul_channel_bw(int nr_band, int scs, int nb_ul, frame_type_t frame_type) +bool compare_relative_ul_channel_bw(int nr_band, int scs, int channel_bandwidth, frame_type_t frame_type) { // 38.101-1 section 6.2.2 // Relative channel bandwidth <= 4% for TDD bands and <= 3% for FDD bands int index = get_nr_table_idx(nr_band, scs); - - int band_size_khz = get_supported_bw_mhz(nr_band > 256 ? FR2 : FR1, scs, nb_ul) * 1000; float limit = frame_type == TDD ? 0.04 : 0.03; - float rel_bw = (float) (band_size_khz) / (float) (nr_bandtable[index].ul_max - nr_bandtable[index].ul_min); + float rel_bw = (float) (2 * channel_bandwidth * 1000) / (float) (nr_bandtable[index].ul_max - nr_bandtable[index].ul_min); return rel_bw > limit; } diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 6ed86cb7bd..d65344b27d 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -224,8 +224,8 @@ int get_dmrs_port(int nl, uint16_t dmrs_ports); uint16_t SL_to_bitmap(int startSymbolIndex, int nrOfSymbols); int get_nb_periods_per_frame(uint8_t tdd_period); long rrc_get_max_nr_csrs(const int max_rbs, long b_SRS); -bool compare_relative_ul_channel_bw(int nr_band, int scs, int nb_ul, frame_type_t frame_type); -int get_supported_bw_mhz(frequency_range_t frequency_range, int scs, int nb_rb); +bool compare_relative_ul_channel_bw(int nr_band, int scs, int channel_bandwidth, frame_type_t frame_type); +int get_supported_bw_mhz(frequency_range_t frequency_range, int bw_index); int get_supported_band_index(int scs, frequency_range_t freq_range, int n_rbs); void get_samplerate_and_bw(int mu, int n_rb, @@ -248,6 +248,7 @@ int get_scan_ssb_first_sc(const double fc, nr_gscn_info_t ssbStartSC[MAX_GSCN_BAND]); void check_ssb_raster(uint64_t freq, int band, int scs); +int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_range, int n_rbs); #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index e95451fcd8..a461d46142 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -518,7 +518,9 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, } fp->threequarter_fs = 0; - gNB_config->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, mu, N_RB_DL); + frequency_range_t frequency_range = fp->nr_band > 256 ? FR2 : FR1; + int bw_index = get_supported_band_index(mu, frequency_range, N_RB_DL); + gNB_config->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(frequency_range, bw_index); nr_init_frame_parms(gNB_config, fp); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 63546246f0..f77d9e7e3e 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -161,8 +161,9 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, if (mu>2) fp->nr_band = 257; else fp->nr_band = 78; fp->threequarter_fs= 0; - - gNB_config->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, mu, N_RB_DL); + frequency_range_t frequency_range = fp->nr_band > 256 ? FR2 : FR1; + int bw_index = get_supported_band_index(mu, frequency_range, N_RB_DL); + gNB_config->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(frequency_range, bw_index); fp->ofdm_offset_divisor = UINT_MAX; nr_init_frame_parms(gNB_config, fp); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index d141215846..fa98a7ecac 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -573,6 +573,10 @@ typedef struct NR_UE_UL_BWP { nr_dci_format_t dci_format; int max_fb_time; long *p0_NominalWithGrant; + // UE Channel bandwidth according to 38.101 5.3.2 + int channel_bandwidth; + // Minimum transmission power according to 38.101 6.3.1 + float P_CMIN; } NR_UE_UL_BWP_t; // non-BWP serving cell configuration diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index c6c69311f7..e28f7dce93 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -118,9 +118,11 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_FrequencyInfoDL_SIB_t *frequencyInfoDL = &scc->downlinkConfigCommon.frequencyInfoDL; AssertFatal(frequencyInfoDL->frequencyBandList.list.array[0]->freqBandIndicatorNR, "Field mandatory present for DL in SIB1\n"); mac->nr_band = *frequencyInfoDL->frequencyBandList.list.array[0]->freqBandIndicatorNR; - cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + + int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + mac->frequency_range, + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index); uint64_t dl_bw_khz = (12 * frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth) * (15 << frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing); @@ -139,9 +141,11 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_FrequencyInfoUL_SIB_t *frequencyInfoUL = &scc->uplinkConfigCommon->frequencyInfoUL; mac->p_Max = frequencyInfoUL->p_Max ? *frequencyInfoUL->p_Max : INT_MIN; - cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + + bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + mac->frequency_range, + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index); if (frequencyInfoUL->absoluteFrequencyPointA == NULL) cfg->carrier_config.uplink_frequency = cfg->carrier_config.dl_frequency; @@ -260,9 +264,10 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, mac->frame_type = get_frame_type(mac->nr_band, get_softmodem_params()->numerology); mac->frequency_range = mac->nr_band < 256 ? FR1 : FR2; - cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + mac->frequency_range, + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index); cfg->carrier_config.dl_frequency = from_nrarfcn(mac->nr_band, *scc->ssbSubcarrierSpacing, @@ -284,9 +289,10 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; mac->p_Max = frequencyInfoUL->p_Max ? *frequencyInfoUL->p_Max : INT_MIN; - cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + int bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + mac->frequency_range, + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index); long *UL_pointA = NULL; if (frequencyInfoUL->absoluteFrequencyPointA) @@ -1488,6 +1494,11 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up bwp->cyclicprefix = ul_genericParameters->cyclicPrefix; bwp->BWPSize = NRRIV2BW(ul_genericParameters->locationAndBandwidth, MAX_BWP_SIZE); bwp->BWPStart = NRRIV2PRBOFFSET(ul_genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + // For power calculations assume the UE channel is the smallest channel that can support the BWP + int bw_index = get_smallest_supported_bandwidth_index(bwp->scs, mac->frequency_range, bwp->BWPSize); + bwp->channel_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index); + // Minumum transmission power depends on bandwidth, precalculate it here + bwp->P_CMIN = nr_get_Pcmin(bw_index); if (bwp_id == 0) { mac->sc_info.initial_ul_BWPSize = bwp->BWPSize; mac->sc_info.initial_ul_BWPStart = bwp->BWPStart; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c b/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c index 04cf626a54..babdd96f10 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c @@ -138,7 +138,8 @@ static void sl_prepare_phy_config(int module_id, AssertFatal(carriercfg, "SCS_SpecificCarrier cannot be NULL"); - phycfg->sl_carrier_config.sl_bandwidth = get_supported_bw_mhz(FR1, carriercfg->subcarrierSpacing, carriercfg->carrierBandwidth); + int bw_index = get_supported_band_index(carriercfg->subcarrierSpacing, FR1, carriercfg->carrierBandwidth); + phycfg->sl_carrier_config.sl_bandwidth = get_supported_bw_mhz(FR1, bw_index); phycfg->sl_carrier_config.sl_frequency = from_nrarfcn(sl_band,carriercfg->subcarrierSpacing,pointA_ARFCN); // freq in kHz diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index d4a6bcfb7d..396294fc97 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -248,6 +248,7 @@ float nr_get_Pcmax(int p_Max, uint16_t nr_band, frame_type_t frame_type, frequency_range_t frequency_range, + int channel_bandwidth_index, int Qm, bool powerBoostPi2BPSK, int scs, @@ -256,7 +257,7 @@ float nr_get_Pcmax(int p_Max, int n_prbs, int start_prb); -float nr_get_Pcmin(int scs, int nr_band, int N_RB_UL); +float nr_get_Pcmin(int bandwidth_index); int get_sum_delta_pucch(NR_UE_MAC_INST_t *mac, int slot, frame_t frame); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index dfe1c86e72..9264e4ad16 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -91,6 +91,7 @@ void init_RA(NR_UE_MAC_INST_t *mac, mac->nr_band, mac->frame_type, mac->frequency_range, + mac->current_UL_BWP->channel_bandwidth, 2, false, prach_scs, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c index 01bf59b56f..de16ba3d6a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c @@ -66,16 +66,16 @@ static int get_deltatf(uint16_t nb_of_prbs, int O_UCI); // ∆MPR according to Table 6.2.2-3 38.101-1 -static float get_delta_mpr(uint16_t nr_band, frame_type_t frame_type, int scs, int N_RB_UL, int n_prbs, int start_prb, int power_class) +static float get_delta_mpr(uint16_t nr_band, frame_type_t frame_type, int scs, int channel_bandwidth, int n_prbs, int start_prb, int power_class) { - if (compare_relative_ul_channel_bw(nr_band, scs, N_RB_UL, frame_type)) { + if (compare_relative_ul_channel_bw(nr_band, scs, channel_bandwidth, frame_type)) { if (power_class == 3) { - if ((nr_band == 28 || nr_band == 83) && get_supported_bw_mhz(nr_band > 256 ? FR2 : FR1, scs, N_RB_UL) == 30) { + if ((nr_band == 28 || nr_band == 83) && channel_bandwidth == 30) { return 0.5f; } } if (power_class == 3 || power_class == 2) { - if ((nr_band == 40 || nr_band == 97) && get_supported_bw_mhz(nr_band > 256 ? FR2 : FR1, scs, N_RB_UL) == 100) { + if ((nr_band == 40 || nr_band == 97) && channel_bandwidth == 100) { return 1.0f; } } @@ -168,6 +168,7 @@ float nr_get_Pcmax(int p_Max, uint16_t nr_band, frame_type_t frame_type, frequency_range_t frequency_range, + int channel_bandwidth, int Qm, bool powerBoostPi2BPSK, int scs, @@ -197,7 +198,7 @@ float nr_get_Pcmax(int p_Max, int delta_TC = 0; float MPR = get_mpr(Qm, N_RB_UL, is_transform_precoding, n_prbs, start_prb, power_class); - float delta_MPR = get_delta_mpr(nr_band, frame_type, scs, N_RB_UL, n_prbs, start_prb, power_class); + float delta_MPR = get_delta_mpr(nr_band, frame_type, scs, channel_bandwidth, n_prbs, start_prb, power_class); int A_MPR = 0; // TODO too complicated to implement for now (see 6.2.3 in 38.101-1) int delta_rx_SRS = 0; // TODO for SRS int P_MPR = 0; // to ensure compliance with applicable electromagnetic energy absorption requirements @@ -216,7 +217,13 @@ float nr_get_Pcmax(int p_Max, } // TODO we need a strategy to select a value between minimum and maximum allowed PC_max float pcmax = (pcmax_low + pcmax_high) / 2; - LOG_D(MAC, "Configured maximum output power: %f dBm <= PCMAX %f dBm <= %f dBm \n", pcmax_low, pcmax, pcmax_high); + LOG_D(MAC, + "Configured maximum output power: %f dBm <= PCMAX %f dBm <= %f dBm MPR=%.2f deltaMPR=%.2f\n", + pcmax_low, + pcmax, + pcmax_high, + MPR, + delta_MPR); return pcmax; } else { // FR2 TODO it is even more complex because it is radiated power @@ -224,12 +231,11 @@ float nr_get_Pcmax(int p_Max, } } -float nr_get_Pcmin(int scs, int nr_band, int N_RB_UL) { - int band_index = get_supported_band_index(nr_band > 256 ? FR2 : FR1, scs, N_RB_UL); +float nr_get_Pcmin(int bandwidth_index) { const float table_38101_6_3_1_1[] = { -40, -40, -40, -40, -39, -38.2, -37.5, -37, -36.5, -35.2, -34.6, -34, -33.5, -33 }; - return table_38101_6_3_1_1[band_index]; + return table_38101_6_3_1_1[bandwidth_index]; } // This is not entirely correct. In certain k2/k1/k0 settings we might postpone accumulating delta_PUCCH until next HARQ feedback @@ -341,6 +347,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, mac->nr_band, mac->frame_type, mac->frequency_range, + current_UL_BWP->channel_bandwidth, 2, false, mac->current_UL_BWP->scs, @@ -348,7 +355,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, format_type == 2, 1, start_prb); - int P_CMIN = nr_get_Pcmin(mac->current_UL_BWP->scs, mac->nr_band, mac->current_UL_BWP->BWPSize); + float P_CMIN = current_UL_BWP->P_CMIN; int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); if (power_config->twoPUCCH_PC_AdjustmentStates && *power_config->twoPUCCH_PC_AdjustmentStates > 1) { @@ -522,6 +529,7 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac, mac->nr_band, mac->frame_type, mac->frequency_range, + mac->current_UL_BWP->channel_bandwidth, qm, false, mac->current_UL_BWP->scs, @@ -553,7 +561,7 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac, // TODO: compute pathoss using correct reference int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); - int P_CMIN = nr_get_Pcmin(mac->current_UL_BWP->scs, mac->nr_band, mac->current_UL_BWP->BWPSize); + int P_CMIN = mac->current_UL_BWP->P_CMIN; float pusch_power_without_f_b_f_c = P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF; diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp index a315835df7..c8467241b8 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp @@ -44,24 +44,27 @@ TEST(test_pcmax, test_mpr) int nr_band = 20; float expected_power = 23 - (1.5 / 2); frame_type_t frame_type = TDD; - EXPECT_EQ(expected_power, nr_get_Pcmax(23, nr_band, frame_type, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start)); + int channel_bandwidth = 20; + EXPECT_EQ(expected_power, + nr_get_Pcmax(23, nr_band, frame_type, FR1, channel_bandwidth, 2, false, 1, N_RB_UL, false, 6, prb_start)); // Outer PRB, MPR = 3, no delta MPR prb_start = 0; expected_power = 23 - (3.0 / 2); - EXPECT_EQ(expected_power, nr_get_Pcmax(23, nr_band, frame_type, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start)); + EXPECT_EQ(expected_power, + nr_get_Pcmax(23, nr_band, frame_type, FR1, channel_bandwidth, 2, false, 1, N_RB_UL, false, 6, prb_start)); // Outer PRB on band 28, MPR = 3, delta MPR = 0.5 dB N_RB_UL = 78; nr_band = 28; expected_power = 23 - ((3.0 + 0.5) / 2); - EXPECT_EQ(expected_power, nr_get_Pcmax(23, nr_band, frame_type, FR1, 2, false, 1, N_RB_UL, false, 100, prb_start)); + EXPECT_EQ(expected_power, nr_get_Pcmax(23, nr_band, frame_type, FR1, 30, 2, false, 1, N_RB_UL, false, 100, prb_start)); } TEST(test_pcmax, test_not_implemented) { int N_RB_UL = 51; - EXPECT_DEATH(nr_get_Pcmax(23, 20, TDD, FR1, 1, false, 1, N_RB_UL, false, 6, 0), "MPR for Pi/2 BPSK not implemented yet"); + EXPECT_DEATH(nr_get_Pcmax(23, 20, TDD, FR1, 20, 1, false, 1, N_RB_UL, false, 6, 0), "MPR for Pi/2 BPSK not implemented yet"); } TEST(test_pcmax, test_pucch_max_power) @@ -70,11 +73,12 @@ TEST(test_pcmax, test_pucch_max_power) int prb_start = 0; int N_RB_UL = 51; // 10Mhz float expected_power = 23 - (1.0 / 2); - EXPECT_EQ(expected_power, nr_get_Pcmax(23, 20, TDD, FR1, 2, false, 1, N_RB_UL, true, 1, prb_start)); + int channel_bandwidth = 20; + EXPECT_EQ(expected_power, nr_get_Pcmax(23, 20, TDD, FR1, channel_bandwidth, 2, false, 1, N_RB_UL, true, 1, prb_start)); // Other fromats, no transform precoding, MPR = 3 expected_power = 23 - (3.0 / 2); - EXPECT_EQ(expected_power, nr_get_Pcmax(23, 20, TDD, FR1, 2, false, 1, N_RB_UL, false, 1, prb_start)); + EXPECT_EQ(expected_power, nr_get_Pcmax(23, 20, TDD, FR1, channel_bandwidth, 2, false, 1, N_RB_UL, false, 1, prb_start)); } TEST(test_pucch_power_state, test_accumulated_delta_pucch) @@ -108,6 +112,7 @@ TEST(test_pucch_power_state, test_accumulated_delta_pucch) mac.nr_band, mac.frame_type, FR1, + current_UL_BWP.channel_bandwidth, 2, false, current_UL_BWP.scs, @@ -177,9 +182,9 @@ TEST(test_pucch_power_state, test_accumulated_delta_pucch) TEST(pc_min, check_all_bw_indexes) { - const int NB_RB_UL[] = {11, 24, 38, 51, 65, 78, 106, 133, 162, 217, 245, 273}; - for (auto i = 0U; i < sizeof(NB_RB_UL) / sizeof(NB_RB_UL[0]); i++) { - (void)nr_get_Pcmin(1, 20, NB_RB_UL[i]); + const int bws[] = {5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 100}; + for (auto i = 0U; i < sizeofArray(bws); i++) { + (void)nr_get_Pcmin(i); } } @@ -189,6 +194,7 @@ TEST(pusch_power_control, pusch_power_control_msg3) NR_UE_UL_BWP_t current_UL_BWP = {0}; current_UL_BWP.scs = 1; current_UL_BWP.BWPSize = 106; + current_UL_BWP.channel_bandwidth = 40; mac.current_UL_BWP = ¤t_UL_BWP; NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon; @@ -218,6 +224,7 @@ TEST(pusch_power_control, pusch_power_control_msg3) mac.nr_band, mac.frame_type, FR1, + current_UL_BWP.channel_bandwidth, Qm, false, current_UL_BWP.scs, @@ -286,6 +293,7 @@ TEST(pusch_power_control, pusch_power_data) NR_UE_UL_BWP_t current_UL_BWP = {0}; current_UL_BWP.scs = 1; current_UL_BWP.BWPSize = 106; + current_UL_BWP.channel_bandwidth = 40; mac.current_UL_BWP = ¤t_UL_BWP; NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon; @@ -317,6 +325,7 @@ TEST(pusch_power_control, pusch_power_data) mac.nr_band, mac.frame_type, FR1, + current_UL_BWP.channel_bandwidth, Qm, false, current_UL_BWP.scs, @@ -365,6 +374,7 @@ TEST(pusch_power_control, pusch_power_control_state_initialization) NR_UE_UL_BWP_t current_UL_BWP = {0}; current_UL_BWP.scs = 1; current_UL_BWP.BWPSize = 106; + current_UL_BWP.channel_bandwidth = 40; mac.current_UL_BWP = ¤t_UL_BWP; NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon; @@ -412,6 +422,7 @@ TEST(pusch_power_control, pusch_power_control_state) NR_UE_UL_BWP_t current_UL_BWP = {0}; current_UL_BWP.scs = 1; current_UL_BWP.BWPSize = 106; + current_UL_BWP.channel_bandwidth = 40; mac.current_UL_BWP = ¤t_UL_BWP; NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon; @@ -443,6 +454,7 @@ TEST(pusch_power_control, pusch_power_control_state) mac.nr_band, mac.frame_type, FR1, + current_UL_BWP.channel_bandwidth, Qm, false, current_UL_BWP.scs, @@ -569,9 +581,25 @@ TEST(pusch_power_control, pusch_power_100_rb) EXPECT_GT(power_100_prbs, power); } +TEST(test_pcmax, test_non_obvious_bwp_size) +{ + // Inner PRB, MPR = 1.5, no delta MPR + int prb_start = 4; + int N_RB_UL = 48; + int nr_band = 20; + frame_type_t frame_type = TDD; + int channel_bandwidth = 10; + float expected_power = 23 - 1.5 / 2; + EXPECT_EQ(expected_power, + nr_get_Pcmax(23, nr_band, frame_type, FR1, channel_bandwidth, 2, false, 1, N_RB_UL, false, 6, prb_start)); +} + int main(int argc, char** argv) { logInit(); + uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY); + g_log->log_component[MAC].level = OAILOG_DEBUG; + g_log->log_component[NR_MAC].level = OAILOG_DEBUG; testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 77f794332a..9c0ff76cec 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -280,9 +280,11 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant // Carrier configuration struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; - cfg->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(*frequencyInfoDL->frequencyBandList.list.array[0] > 256 ? FR2 : FR1, - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + frequency_range_t frequency_range = *frequencyInfoDL->frequencyBandList.list.array[0] > 256 ? FR2 : FR1; + int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + frequency_range, + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + cfg->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(frequency_range, bw_index); cfg->carrier_config.dl_bandwidth.tl.tag = NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG; // temporary cfg->num_tlv++; LOG_I(NR_MAC, "DL_Bandwidth:%d\n", cfg->carrier_config.dl_bandwidth.value); @@ -308,9 +310,11 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant } } struct NR_FrequencyInfoUL *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; - cfg->carrier_config.uplink_bandwidth.value = get_supported_bw_mhz(*frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + frequency_range = *frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1; + bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + frequency_range, + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + cfg->carrier_config.uplink_bandwidth.value = get_supported_bw_mhz(frequency_range, bw_index); cfg->carrier_config.uplink_bandwidth.tl.tag = NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG; // temporary cfg->num_tlv++; LOG_I(NR_MAC, "DL_Bandwidth:%d\n", cfg->carrier_config.uplink_bandwidth.value); @@ -343,7 +347,7 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant } uint32_t band = *frequencyInfoDL->frequencyBandList.list.array[0]; - frequency_range_t frequency_range = band < 100 ? FR1 : FR2; + frequency_range = band < 100 ? FR1 : FR2; frame_type_t frame_type = get_frame_type(*frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); nrmac->common_channels[0].frame_type = frame_type; diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index d0b692232f..dd3b3db216 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -529,7 +529,7 @@ void set_dl_maxmimolayers(NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig, NR_FeatureSets_t *fs = uecap ? uecap->featureSets : NULL; if (fs) { - const int bw_mhz = get_supported_bw_mhz(freq_range, scs, bw_size); + const int bw_mhz = get_supported_bw_mhz(freq_range, get_supported_band_index(scs, freq_range, bw_size)); // go through UL feature sets and look for one with current SCS for (int i = 0; i < fs->featureSetsDownlinkPerCC->list.count; i++) { NR_FeatureSetDownlinkPerCC_t *dl_fs = fs->featureSetsDownlinkPerCC->list.array[i];