PUSCH power control without PUSCH power control state
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -434,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
|
||||
|
||||
@@ -164,15 +164,169 @@ 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++) {
|
||||
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 = ¤t_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 = ¤t_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();
|
||||
|
||||
Reference in New Issue
Block a user