Commit 7264f9e0 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/nr-ue-pusch-power-control' into integration_2024_w26b

parents 5af81bbc 8ea2e77a
......@@ -356,8 +356,8 @@ bool compare_relative_ul_channel_bw(int nr_band, int scs, int nb_ul, frame_type_
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) (2 * band_size_khz) / (float) (nr_bandtable[index].ul_max + nr_bandtable[index].ul_min);
return rel_bw <= limit;
float rel_bw = (float) (band_size_khz) / (float) (nr_bandtable[index].ul_max - nr_bandtable[index].ul_min);
return rel_bw > limit;
}
uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex)
......
......@@ -359,6 +359,7 @@ typedef struct
nfapi_nr_ue_ul_beamforming_t beamforming;
//OAI specific
int8_t absolute_delta_PUSCH;
int16_t tx_power;
fapi_nr_tx_request_body_t tx_request_body;
} nfapi_nr_ue_pusch_pdu_t;
......
......@@ -571,6 +571,7 @@ typedef struct NR_UE_UL_BWP {
uint8_t mcs_table;
nr_dci_format_t dci_format;
int max_fb_time;
long *p0_NominalWithGrant;
} NR_UE_UL_BWP_t;
// non-BWP serving cell configuration
......
......@@ -1409,11 +1409,14 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up
ul_common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList,
NR_PUSCH_TimeDomainResourceAllocationList_t);
UPDATE_IE(bwp->msg3_DeltaPreamble, ul_common->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble, long);
UPDATE_IE(bwp->p0_NominalWithGrant, ul_common->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant, long);
}
if (ul_common->pusch_ConfigCommon->present == NR_SetupRelease_PUSCH_ConfigCommon_PR_release) {
asn1cFreeStruc(asn_DEF_NR_PUSCH_TimeDomainResourceAllocationList, bwp->tdaList_Common);
free(bwp->msg3_DeltaPreamble);
bwp->msg3_DeltaPreamble = NULL;
free(bwp->p0_NominalWithGrant);
bwp->p0_NominalWithGrant = NULL;
}
}
}
......@@ -2130,6 +2133,8 @@ void release_ul_BWP(NR_UE_MAC_INST_t *mac, int index)
asn1cFreeStruc(asn_DEF_NR_SRS_Config, bwp->srs_Config);
free(bwp->msg3_DeltaPreamble);
bwp->msg3_DeltaPreamble = NULL;
free(bwp->p0_NominalWithGrant);
bwp->p0_NominalWithGrant = NULL;
free(bwp);
}
......
......@@ -219,6 +219,20 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
int subframe_number,
int O_uci,
uint16_t start_prb);
int get_pusch_tx_power_ue(
NR_UE_MAC_INST_t *mac,
int num_rb,
int start_prb,
uint16_t nb_symb_sch,
uint16_t nb_dmrs_prb,
uint16_t nb_ptrs_prb,
uint16_t qm,
uint16_t R,
uint16_t beta_offset_csi1,
uint32_t sum_bits_in_codeblocks,
int delta_pusch,
bool is_rar_tx_retx,
bool transform_precoding);
int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
int slot,
......@@ -227,16 +241,18 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
PUCCH_sched_t *pucch,
fapi_nr_ul_config_pucch_pdu *pucch_pdu);
int nr_get_Pcmax(int p_Max,
uint16_t nr_band,
frequency_range_t frequency_range,
int Qm,
bool powerBoostPi2BPSK,
int scs,
int N_RB_UL,
bool is_transform_precoding,
int n_prbs,
int start_prb);
float nr_get_Pcmax(int p_Max,
uint16_t nr_band,
frequency_range_t frequency_range,
int Qm,
bool powerBoostPi2BPSK,
int scs,
int N_RB_UL,
bool is_transform_precoding,
int n_prbs,
int start_prb);
float nr_get_Pcmin(int scs, int nr_band, int N_RB_UL);
int get_sum_delta_pucch(NR_UE_MAC_INST_t *mac, int slot, frame_t frame);
......
......@@ -65,62 +65,34 @@ static int get_deltatf(uint16_t nb_of_prbs,
int N_sc_ctrl_RB,
int O_UCI);
// Implementation of 6.2.4 Configured ransmitted power
// 3GPP TS 38.101-1 version 16.5.0 Release 16
// -
// The UE is allowed to set its configured maximum output power PCMAX,f,c for carrier f of serving cell c in each slot.
// The configured maximum output power PCMAX,f,c is set within the following bounds: PCMAX_L,f,c <= PCMAX,f,c <= PCMAX_H,f,c
// -
// Measurement units:
// - p_max: dBm
// - delta_TC_c: dB
// - P_powerclass: dBm
// - delta_P_powerclass: dB
// - MPR_c: dB
// - delta_MPR_c: dB
// - delta_T_IB_c dB
// - delta_rx_SRS dB
// note:
// - Assuming:
// -- Powerclass 3 capable UE (which is default power class unless otherwise stated)
// -- Maximum power reduction (MPR_c) for power class 3
// -- no additional MPR (A_MPR_c)
int nr_get_Pcmax(int p_Max,
uint16_t nr_band,
frequency_range_t frequency_range,
int Qm,
bool powerBoostPi2BPSK,
int scs,
int N_RB_UL,
bool is_transform_precoding,
int n_prbs,
int start_prb)
// ∆MPR according to Table 6.2.2-3 38.101-1
static float get_delta_mpr(uint16_t nr_band, int scs, int N_RB_UL, int n_prbs, int start_prb, int power_class)
{
if (frequency_range == FR1) {
// TODO configure P-MAX from the upper layers according to 38.331
int p_powerclass = 23; // dBm assuming poweclass 3 UE
int p_emax = p_Max != INT_MIN ? p_Max : p_powerclass;
int delta_P_powerclass = 0; // for powerclass 2 needs to be changed
if (p_Max && Qm == 1 && powerBoostPi2BPSK
&& (nr_band == 40 || nr_band == 41 || nr_band == 77 || nr_band == 78 || nr_band == 79)) {
p_emax += 3;
delta_P_powerclass -= 3;
frame_type_t frame_type = get_frame_type(nr_band, scs);
if (compare_relative_ul_channel_bw(nr_band, scs, N_RB_UL, 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) {
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) {
return 1.0f;
}
}
}
return 0;
}
// TODO to be set for CA and DC
int delta_T_IB = 0;
// TODO in case of band 41 and PRB allocation within 4MHz of the upper or lower limit of the band -> delta_TC = 1.5
if (nr_band == 41)
LOG_E(NR_MAC, "Need to implement delta_TC for band 41\n");
int delta_TC = 0;
float MPR = 0;
frame_type_t frame_type = get_frame_type(nr_band, scs);
if (compare_relative_ul_channel_bw(nr_band, scs, N_RB_UL, frame_type)) {
int rb_low = (n_prbs / 2) > 1 ? (n_prbs / 2) : 1;
int rb_high = N_RB_UL - rb_low - n_prbs;
bool is_inner_rb = start_prb >= rb_low && start_prb <= rb_high && n_prbs <= ((N_RB_UL / 2) + (N_RB_UL & 1));
// MPR according to 38-101 6.2.2
static float get_mpr(int Qm, int N_RB_UL, bool is_transform_precoding, int n_prbs, int start_prb, int power_class)
{
float MPR = 0;
int rb_low = (n_prbs / 2) > 1 ? (n_prbs / 2) : 1;
int rb_high = N_RB_UL - rb_low - n_prbs;
bool is_inner_rb = start_prb >= rb_low && start_prb <= rb_high && n_prbs <= ((N_RB_UL / 2) + (N_RB_UL & 1));
switch (power_class) {
case 3:
// Table 6.2.2-1 in 38.101
switch (Qm) {
case 1:
......@@ -166,16 +138,73 @@ int nr_get_Pcmax(int p_Max,
default:
AssertFatal(false, "Invalid Qm %d\n", Qm);
}
break;
default:
AssertFatal(false, "PowerClass != 3 not implemented\n");
}
return MPR;
}
// Implementation of 6.2.4 Configured ransmitted power
// 3GPP TS 38.101-1 version 16.5.0 Release 16
// -
// The UE is allowed to set its configured maximum output power PCMAX,f,c for carrier f of serving cell c in each slot.
// The configured maximum output power PCMAX,f,c is set within the following bounds: PCMAX_L,f,c <= PCMAX,f,c <= PCMAX_H,f,c
// -
// Measurement units:
// - p_max: dBm
// - delta_TC_c: dB
// - P_powerclass: dBm
// - delta_P_powerclass: dB
// - MPR_c: dB
// - delta_MPR_c: dB
// - delta_T_IB_c dB
// - delta_rx_SRS dB
// note:
// - Assuming:
// -- Powerclass 3 capable UE (which is default power class unless otherwise stated)
// -- Maximum power reduction (MPR_c) for power class 3
// -- no additional MPR (A_MPR_c)
float nr_get_Pcmax(int p_Max,
uint16_t nr_band,
frequency_range_t frequency_range,
int Qm,
bool powerBoostPi2BPSK,
int scs,
int N_RB_UL,
bool is_transform_precoding,
int n_prbs,
int start_prb)
{
const int power_class = 3; // Assume power class 3
if (frequency_range == FR1) {
// TODO configure P-MAX from the upper layers according to 38.331
int p_powerclass = 23; // dBm assuming poweclass 3 UE
int p_emax = p_Max != INT_MIN ? p_Max : p_powerclass;
int delta_P_powerclass = 0; // for powerclass 2 needs to be changed
if (p_Max && Qm == 1 && powerBoostPi2BPSK
&& (nr_band == 40 || nr_band == 41 || nr_band == 77 || nr_band == 78 || nr_band == 79)) {
p_emax += 3;
delta_P_powerclass -= 3;
}
// TODO to be set for CA and DC
int delta_T_IB = 0;
// TODO in case of band 41 and PRB allocation within 4MHz of the upper or lower limit of the band -> delta_TC = 1.5
if (nr_band == 41)
LOG_E(NR_MAC, "Need to implement delta_TC for band 41\n");
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, scs, N_RB_UL, 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
float total_reduction = (MPR > A_MPR ? MPR : A_MPR) + delta_T_IB + delta_TC + delta_rx_SRS;
if (P_MPR > total_reduction)
total_reduction = P_MPR;
int pcmax_high, pcmax_low;
float total_reduction = max(max(MPR + delta_MPR, A_MPR) + delta_T_IB + delta_TC + delta_rx_SRS, P_MPR);
float pcmax_high, pcmax_low;
if (p_Max) {
pcmax_high = p_emax < (p_powerclass - delta_P_powerclass) ? p_emax : (p_powerclass - delta_P_powerclass);
pcmax_low = (p_emax - delta_TC) < (p_powerclass - delta_P_powerclass - total_reduction)
......@@ -186,8 +215,8 @@ int nr_get_Pcmax(int p_Max,
pcmax_low = p_powerclass - delta_P_powerclass - total_reduction;
}
// TODO we need a strategy to select a value between minimum and maximum allowed PC_max
int pcmax = (pcmax_low + pcmax_high) / 2;
LOG_D(MAC, "Configured maximum output power: %d dBm <= PCMAX %d dBm <= %d dBm \n", pcmax_low, pcmax, pcmax_high);
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);
return pcmax;
} else {
// FR2 TODO it is even more complex because it is radiated power
......@@ -195,6 +224,14 @@ int 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);
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];
}
// This is not entirely correct. In certain k2/k1/k0 settings we might postpone accumulating delta_PUCCH until next HARQ feedback
// slot. The correct way to do this would be to calculate the K_PUCCH (delta_PUCCH summation window end) for each PUCCH occasion and
// compare PUCCH transmission symbol with the reception symbol of the DCI containing delta_PUCCH to determine if the delta_PUCCH
......@@ -297,8 +334,9 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
delta_F_PUCCH = *delta_F_PUCCH_config;
}
// PUCCH shall be as specified for QPSK modulated DFT-s-OFDM of equivalent RB allocation (38.101-1)
// TODO: P_CMAX for format 2
// 38.101-1: The allowed MPR for SRS, PUCCH formats 0, 1, 3 and 4, and PRACH shall be as specified for QPSK modulated DFT-
// s-OFDM of equivalent RB allocation. The allowed MPR for PUCCH format 2 shall be as specified for QPSK
// modulated CP-OFDM of equivalent RB allocation.
int P_CMAX = nr_get_Pcmax(mac->p_Max,
mac->nr_band,
mac->frequency_range,
......@@ -306,10 +344,10 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
false,
mac->current_UL_BWP->scs,
mac->current_UL_BWP->BWPSize,
true,
format_type == 2,
1,
start_prb);
int P_CMIN = -40; // TODO: minimum TX power, possibly 38.101-1 6.3.1
int P_CMIN = nr_get_Pcmin(mac->current_UL_BWP->scs, mac->nr_band, mac->current_UL_BWP->BWPSize);
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) {
......@@ -396,3 +434,136 @@ int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm)
return pathloss;
}
// PUSCH transmission power according to 38.213 7.1
int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
int num_rb,
int start_prb,
uint16_t nb_symb_sch,
uint16_t nb_dmrs_prb,
uint16_t nb_ptrs_prb,
uint16_t qm,
uint16_t R,
uint16_t beta_offset_csi1,
uint32_t sum_bits_in_codeblocks,
int delta_pusch,
bool is_rar_tx_retx,
bool transform_precoding)
{
LOG_D(NR_MAC,
"PUSCH tx power determination num_rb=%d start_prb=%d nb_symb_sch=%u nb_dmrs_prb=%u nb_ptrs_prb=%u Qm=%u R= %u "
"beta_offset_cs1=%u sum_bits_in_codeblocks=%u delta_pusch=%d is_rar_tx_retx=%d transform_precoding=%d\n",
num_rb,
start_prb,
nb_symb_sch,
nb_dmrs_prb,
nb_ptrs_prb,
qm,
R,
beta_offset_csi1,
sum_bits_in_codeblocks,
delta_pusch,
is_rar_tx_retx,
transform_precoding);
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
AssertFatal(current_UL_BWP, "Missing configuration: need UL_BWP to calculate PUSCH tx power\n");
NR_PUSCH_Config_t *pusch_Config = current_UL_BWP->pusch_Config;
bool has_pusch_config = pusch_Config != NULL;
bool has_pusch_power_control_config = has_pusch_config && pusch_Config->pusch_PowerControl != NULL;
bool is_provided_alpha_sets = has_pusch_power_control_config && pusch_Config->pusch_PowerControl->p0_AlphaSets != NULL;
AssertFatal(!has_pusch_power_control_config || pusch_Config->pusch_PowerControl->sri_PUSCH_MappingToAddModList == NULL,
"SRI-PUSCH-PowerControl handling not implemented\n");
int P_O_NOMINAL_PUSCH;
float alpha;
const float alpha_factor_table[8] = {0.0f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f};
if (is_rar_tx_retx || !is_provided_alpha_sets || current_UL_BWP->p0_NominalWithGrant == NULL) {
int DELTA_PREAMBLE_MSG3 = 0;
if (current_UL_BWP->msg3_DeltaPreamble) {
DELTA_PREAMBLE_MSG3 = *current_UL_BWP->msg3_DeltaPreamble;
}
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = current_UL_BWP->rach_ConfigCommon;
long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower;
int P_O_PRE = preambleReceivedTargetPower;
P_O_NOMINAL_PUSCH = P_O_PRE + DELTA_PREAMBLE_MSG3;
if (has_pusch_power_control_config && pusch_Config->pusch_PowerControl->msg3_Alpha) {
alpha = alpha_factor_table[*pusch_Config->pusch_PowerControl->msg3_Alpha];
} else {
alpha = 1.0f;
}
} else {
P_O_NOMINAL_PUSCH = *current_UL_BWP->p0_NominalWithGrant;
if (pusch_Config->pusch_PowerControl->p0_AlphaSets->list.array[0]->alpha) {
alpha = alpha_factor_table[*pusch_Config->pusch_PowerControl->p0_AlphaSets->list.array[0]->alpha];
} else {
// Default according to 38.331 P0-PUSCH-AlphaSet field descriptions
alpha = 1.0f;
}
}
int P_O_UE_PUSCH;
if (is_rar_tx_retx || !is_provided_alpha_sets) {
P_O_UE_PUSCH = 0;
} else {
if (pusch_Config->pusch_PowerControl->p0_AlphaSets->list.array[0]->p0) {
P_O_UE_PUSCH = *pusch_Config->pusch_PowerControl->p0_AlphaSets->list.array[0]->p0;
} else {
// Default according to 38.331 P0-PUSCH-AlphaSet field descriptions
P_O_UE_PUSCH = 0;
}
}
int mu = current_UL_BWP->scs;
int M_pusch_component = 10 * log10((pow(2, mu)) * num_rb);
int P_CMAX = nr_get_Pcmax(mac->p_Max,
mac->nr_band,
mac->frequency_range,
2,
false,
mac->current_UL_BWP->scs,
mac->current_UL_BWP->BWPSize,
transform_precoding,
1,
start_prb);
int P_O_PUSCH = P_O_NOMINAL_PUSCH + P_O_UE_PUSCH;
float DELTA_TF = 0;
if (has_pusch_power_control_config && pusch_Config->pusch_PowerControl->deltaMCS) {
float beta_offset = 1;
float BPRE;
if (sum_bits_in_codeblocks == 0) {
float table_38_213_9_3_2[] = {
1.125, 11.250, 21.375, 31.625, 41.750, 52.000, 62.250, 72.500, 82.875, 93.125,
103.500, 114.000, 125.000, 136.250, 148.000, 1510.000, 1612.625, 1715.875, 1820.000,
};
beta_offset = table_38_213_9_3_2[beta_offset_csi1];
BPRE = (qm * R / beta_offset) / 1024;
} else {
const int nb_subcarrier_per_rb = 12;
const uint32_t N_RE = nb_subcarrier_per_rb * nb_symb_sch - nb_dmrs_prb - nb_ptrs_prb;
BPRE = sum_bits_in_codeblocks / (float)(N_RE * num_rb);
}
DELTA_TF = 10 * log10(pow(2, BPRE * 1.25f) * beta_offset);
}
// TODO: compute pathoss using correct reference
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
int f_b_f_c = 0;
if (has_pusch_power_control_config && pusch_Config->pusch_PowerControl->tpc_Accumulation) {
f_b_f_c = delta_pusch;
} else {
// TODO: PUSCH power control state
}
LOG_D(NR_MAC,
"PUSCH tx power components P_O_PUSCH=%d, M_pusch_component=%d, alpha*pathloss=%f, delta_TF=%f, f_b_f_c=%d\n",
P_O_PUSCH,
M_pusch_component,
alpha * pathloss,
DELTA_TF,
f_b_f_c);
return min(P_CMAX, P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF + f_b_f_c);
}
......@@ -913,6 +913,22 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->pusch_data.tb_size = mac->ul_harq_info[pid].TBS;
}
bool is_rar_tx_retx = rnti_type == TYPE_TC_RNTI_;
pusch_config_pdu->tx_power = get_pusch_tx_power_ue(mac,
pusch_config_pdu->rb_size,
pusch_config_pdu->rb_start,
pusch_config_pdu->nr_of_symbols,
nb_dmrs_re_per_rb * number_dmrs_symbols,
0, //TODO: count PTRS per RB
pusch_config_pdu->qam_mod_order,
pusch_config_pdu->target_code_rate,
pusch_config_pdu->pusch_uci.beta_offset_csi1,
pusch_config_pdu->pusch_data.tb_size << 3,
pusch_config_pdu->absolute_delta_PUSCH,
is_rar_tx_retx,
pusch_config_pdu->transform_precoding);
pusch_config_pdu->ldpcBaseGraph = get_BG(pusch_config_pdu->pusch_data.tb_size << 3, pusch_config_pdu->target_code_rate);
//The MAC entity shall restart retxBSR-Timer upon reception of a grant for transmission of new data on any UL-SCH
......
......@@ -19,43 +19,314 @@
* contact@openairinterface.org
*/
#include "gtest/gtest.h"
extern "C" {
#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
#include "executables/softmodem-common.h"
uint64_t get_softmodem_optmask(void) {return 0;}
uint64_t get_softmodem_optmask(void)
{
return 0;
}
static softmodem_params_t softmodem_params;
softmodem_params_t *get_softmodem_params(void) {
softmodem_params_t* get_softmodem_params(void)
{
return &softmodem_params;
}
}
#include <cstdio>
#include "common/utils/LOG/log.h"
TEST(power_procedures_fr1, test_prach_max_tx_power_mpr)
TEST(test_pcmax, test_mpr)
{
// Inner PRB, MPR = 1.5
// Inner PRB, MPR = 1.5, no delta MPR
int prb_start = 4;
int N_RB_UL = 51; // 10Mhz
EXPECT_EQ(22, nr_get_Pcmax(23, 20, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start));
int nr_band = 20;
float expected_power = 23 - (1.5 / 2);
EXPECT_EQ(expected_power, nr_get_Pcmax(23, nr_band, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start));
// Outer PRB, MPR = 3
// Outer PRB, MPR = 3, no delta MPR
prb_start = 0;
EXPECT_EQ(21, nr_get_Pcmax(23, 20, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start));
expected_power = 23 - (3.0 / 2);
EXPECT_EQ(expected_power, nr_get_Pcmax(23, nr_band, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start));
// Channel bandwidth conditon not met, no MPR
N_RB_UL = 106;
EXPECT_EQ(23, nr_get_Pcmax(23, 20, FR1, 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, FR1, 2, false, 1, N_RB_UL, false, 100, prb_start));
}
TEST(power_procedures_fr1, test_not_implemented)
TEST(test_pcmax, test_not_implemented)
{
int N_RB_UL = 51;
EXPECT_DEATH(nr_get_Pcmax(23, 20, FR1, 1, false, 1, N_RB_UL, false, 6, 0), "MPR for Pi/2 BPSK not implemented yet");
}
TEST(test_pcmax, test_pucch_max_power)
{
// Format 2, transform precoding, MPR = 1
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, FR1, 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, FR1, 2, false, 1, N_RB_UL, false, 1, prb_start));
}
TEST(test_pucch_power_state, test_accumulated_delta_pucch)
{
NR_UE_MAC_INST_t mac = {0};
NR_UE_UL_BWP_t current_UL_BWP = {0};
current_UL_BWP.scs = 1;
current_UL_BWP.BWPSize = 106;
NR_PUCCH_ConfigCommon_t pucch_ConfigCommon = {0};
mac.current_UL_BWP = &current_UL_BWP;
mac.current_UL_BWP->pucch_ConfigCommon = &pucch_ConfigCommon;
mac.nr_band = 20;
NR_PUCCH_Config_t pucch_Config = {0};
struct NR_PUCCH_PowerControl power_config;
pucch_Config.pucch_PowerControl = &power_config;
mac.G_b_f_c = 0;
mac.pucch_power_control_initialized = true;
int scs = 1;
int sum_delta_pucch = 3;
uint8_t format_type = 1;
uint16_t nb_of_prbs = 1;
uint8_t freq_hop_flag = 0;
uint8_t add_dmrs_flag = 0;
uint8_t N_symb_PUCCH = 12;
int subframe_number = 0;
int O_uci = 2;
uint16_t start_prb = 0;
int P_CMAX =
nr_get_Pcmax(23, mac.nr_band, FR1, 2, false, current_UL_BWP.scs, current_UL_BWP.BWPSize, false, nb_of_prbs, start_prb);
int pucch_power_prev = get_pucch_tx_power_ue(&mac,
scs,
&pucch_Config,
sum_delta_pucch,
format_type,
nb_of_prbs,
freq_hop_flag,
add_dmrs_flag,
N_symb_PUCCH,
subframe_number,
O_uci,
start_prb);
EXPECT_LT(pucch_power_prev, P_CMAX);
for (int i = 0; i < 10; i++) {
int pucch_power_state = mac.G_b_f_c;
int pucch_power = get_pucch_tx_power_ue(&mac,
scs,
&pucch_Config,
sum_delta_pucch,
format_type,
nb_of_prbs,
freq_hop_flag,
add_dmrs_flag,
N_symb_PUCCH,
subframe_number,
O_uci,
start_prb);
if (pucch_power_prev == P_CMAX) {
EXPECT_EQ(pucch_power_state, mac.G_b_f_c) << "PUCCH power control state increased after reaching max TX power";
}
EXPECT_LE(pucch_power, P_CMAX) << "PUUCH TX power above P_CMAX";
EXPECT_EQ(std::min(P_CMAX, pucch_power_prev + sum_delta_pucch), pucch_power)
<< "PUCCH power expected to change by delta pucch only, between P_CMAX and P_CMIN";
pucch_power_prev = pucch_power;
if (i > 5) {
EXPECT_EQ(pucch_power, P_CMAX) << "Expected to reach MAX PUCCH TX power";
}
}
sum_delta_pucch = -15;
for (int i = 0; i < 10; i++) {
int pucch_power_state = mac.G_b_f_c;
int pucch_power = get_pucch_tx_power_ue(&mac,
scs,
&pucch_Config,
sum_delta_pucch,
format_type,
nb_of_prbs,
freq_hop_flag,
add_dmrs_flag,
N_symb_PUCCH,
subframe_number,
O_uci,
start_prb);
EXPECT_LE(mac.G_b_f_c, pucch_power_state) << "PUCCH power control state increased with negative delta pucch";
pucch_power_prev = pucch_power;
}
}
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]);
}
}
TEST(pusch_power_control, pusch_power_control_msg3)
{
NR_UE_MAC_INST_t mac = {0};
NR_UE_UL_BWP_t current_UL_BWP = {0};
current_UL_BWP.scs = 1;
current_UL_BWP.BWPSize = 106;
mac.current_UL_BWP = &current_UL_BWP;
NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon;
mac.nr_band = 78;
NR_PUSCH_Config_t pusch_Config = {0};
current_UL_BWP.pusch_Config = &pusch_Config;
NR_PUSCH_PowerControl pusch_PowerControl = {0};
pusch_Config.pusch_PowerControl = &pusch_PowerControl;
pusch_PowerControl.tpc_Accumulation = (long*)1;
// msg3 cofiguration as in 5g_rfsimulator testcase
int num_rb = 8;
int start_prb = 0;
uint16_t nb_symb_sch = 3;
uint16_t nb_dmrs_prb = 12;
uint16_t nb_ptrs_prb = 0;
uint16_t Qm = 2;
uint16_t R = 1570;
uint16_t beta_offset_csi1 = 0;
uint32_t sum_bits_in_codeblocks = 56;
int delta_pusch = 0;
bool is_rar_tx_retx = true;
int P_CMAX = nr_get_Pcmax(23, mac.nr_band, FR1, Qm, false, current_UL_BWP.scs, current_UL_BWP.BWPSize, false, num_rb, start_prb);
long preambleReceivedTargetPower = -96;
nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower = preambleReceivedTargetPower;
int power = get_pusch_tx_power_ue(&mac,
num_rb,
start_prb,
nb_symb_sch,
nb_dmrs_prb,
nb_ptrs_prb,
Qm,
R,
beta_offset_csi1,
sum_bits_in_codeblocks,
delta_pusch,
is_rar_tx_retx,
false);
EXPECT_EQ(power, -84);
EXPECT_LT(power, P_CMAX);
nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower -= 2;
int reduced_power = get_pusch_tx_power_ue(&mac,
num_rb,
start_prb,
nb_symb_sch,
nb_dmrs_prb,
nb_ptrs_prb,
Qm,
R,
beta_offset_csi1,
sum_bits_in_codeblocks,
delta_pusch,
is_rar_tx_retx,
false);
EXPECT_EQ(std::min(P_CMAX, power - 2), reduced_power)
<< "Incorrect handling of preambleReceivedTargetPower";
EXPECT_LT(reduced_power, P_CMAX) << "Power above P_CMAX";
delta_pusch = 4;
int increased_power = get_pusch_tx_power_ue(&mac,
num_rb,
start_prb,
nb_symb_sch,
nb_dmrs_prb,
nb_ptrs_prb,
Qm,
R,
beta_offset_csi1,
sum_bits_in_codeblocks,
delta_pusch,
is_rar_tx_retx,
false);
EXPECT_EQ(std::min(P_CMAX, reduced_power + delta_pusch), increased_power)
<< "delta_pusch should increase tx power";
EXPECT_LT(increased_power, P_CMAX) << "Power above P_CMAX";
}
TEST(pusch_power_control, pusch_power_data)
{
NR_UE_MAC_INST_t mac = {0};
NR_UE_UL_BWP_t current_UL_BWP = {0};
current_UL_BWP.scs = 1;
current_UL_BWP.BWPSize = 106;
mac.current_UL_BWP = &current_UL_BWP;
NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon;
mac.nr_band = 78;
bool is_rar_tx_retx = false;
int num_rb = 5;
int start_prb = 0;
uint16_t nb_symb_sch = 3;
uint16_t nb_dmrs_prb = 6;
uint16_t nb_ptrs_prb = 0;
uint16_t Qm = 2;
uint16_t R = 6790;
uint16_t beta_offset_csi1 = 0;
uint32_t sum_bits_in_codeblocks = 192;
int delta_pusch = 4;
bool transform_precoding = false;
NR_PUSCH_Config_t pusch_Config = {0};
current_UL_BWP.pusch_Config = &pusch_Config;
NR_PUSCH_PowerControl pusch_PowerControl = {0};
pusch_Config.pusch_PowerControl = &pusch_PowerControl;
pusch_PowerControl.tpc_Accumulation = (long*)1;
long p0_NominalWithGrant = 0;
current_UL_BWP.p0_NominalWithGrant = &p0_NominalWithGrant;
pusch_PowerControl.deltaMCS = (long*)1;
int P_CMAX = nr_get_Pcmax(23, mac.nr_band, FR1, Qm, false, current_UL_BWP.scs, current_UL_BWP.BWPSize, transform_precoding, num_rb, start_prb);
int power = get_pusch_tx_power_ue(&mac,
num_rb,
start_prb,
nb_symb_sch,
nb_dmrs_prb,
nb_ptrs_prb,
Qm,
R,
beta_offset_csi1,
sum_bits_in_codeblocks,
delta_pusch,
is_rar_tx_retx,
transform_precoding);
EXPECT_LE(power, P_CMAX);
EXPECT_EQ(power, 18);
const int BETA_OFFSET_CSI1_DEFAULT = 13;
sum_bits_in_codeblocks = 0; // CSI-only
power = get_pusch_tx_power_ue(&mac,
num_rb,
start_prb,
nb_symb_sch,
nb_dmrs_prb,
nb_ptrs_prb,
Qm,
R,
BETA_OFFSET_CSI1_DEFAULT,
sum_bits_in_codeblocks,
delta_pusch,
is_rar_tx_retx,
transform_precoding);
EXPECT_EQ(power, P_CMAX) << "Expecting max tx power because of deltaMCS with CSI-only";
}
int main(int argc, char** argv)
{
logInit();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment