/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /************************************************************************ * * MODULE : PUCCH power control for UE NR * * DESCRIPTION : functions related to PUCCH Transmit power * TS 38.213 7.2.1 UE behaviour * **************************************************************************/ #include "PHY/NR_REFSIG/ss_pbch_nr.h" #include "PHY/defs_nr_UE.h" #include "SCHED_NR_UE/pucch_uci_ue_nr.h" #include "SCHED_NR_UE/pucch_power_control_ue_nr.h" int16_t get_PL(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index); /**************** defines **************************************/ /**************** variables **************************************/ /**************** functions **************************************/ /******************************************************************* * * NAME : get_pucch_tx_power_ue * * PARAMETERS : ue context * gNB_id identity * slots for rx and tx * pucch_format_nr_t pucch format * nb_of_prbs number of prb allocated to pucch * N_sc_ctrl_RB subcarrier control rb related to current pucch format * N_symb_PUCCH number of pucch symbols excluding those reserved for dmrs * O_UCI number of bits for UCI Uplink Control Information * O_SR number of bits for SR scheduling Request * O_UCI number of bits for CSI Channel State Information * O_ACK number of bits for HARQ-ACK * O_CRC number of bits for CRC * n_HARQ_ACK use for obtaining a PUCCH transmission power * * RETURN : pucch power level in dBm * * DESCRIPTION : determines pucch transmission power in dBm * TS 38.213 7.2.1 UE behaviour * *********************************************************************/ int16_t get_pucch_tx_power_ue(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, pucch_format_nr_t pucch_format, int nb_of_prbs, int N_sc_ctrl_RB, int N_symb_PUCCH, int O_UCI, int O_SR, int O_CSI, int O_ACK, int O_CRC, int n_HARQ_ACK) { int16_t P_O_NOMINAL_PUCCH = ue->pucch_config_common_nr[gNB_id].p0_nominal; PUCCH_PowerControl_t *power_config = &ue->pucch_config_dedicated_nr[gNB_id].pucch_PowerControl; int16_t P_O_UE_PUCCH; int16_t G_b_f_c = 0; if (ue->pucch_config_dedicated_nr[gNB_id].spatial_Relation_Info[0] != NULL) { /* FFS TODO NR */ LOG_E(PHY,"PUCCH Spatial relation infos are not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); return (PUCCH_POWER_DEFAULT); } if (power_config->p0_Set[0] != NULL) { P_O_UE_PUCCH = power_config->p0_Set[0]->p0_PUCCH_Value; /* get from index 0 if no spatial relation set */ G_b_f_c = 0; } else { G_b_f_c = ue->dlsch[ue->current_thread_id[proc->subframe_rx]][gNB_id][0]->g_pucch; LOG_W(PHY,"PUCCH Transmit power control command not yet implemented for NR : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); return (PUCCH_POWER_DEFAULT); } int P_O_PUCCH = P_O_NOMINAL_PUCCH + P_O_UE_PUCCH; int16_t PL = get_PL(ue->Mod_id, ue->CC_id, gNB_id); /* LTE function because NR path loss not yet implemented FFS TODO NR */ int16_t delta_F_PUCCH = power_config->deltaF_PUCCH_f[pucch_format]; int DELTA_TF; uint16_t N_ref_PUCCH; /* computing of pucch transmission power adjustment */ switch (pucch_format) { case pucch_format0_nr: { N_ref_PUCCH = 2; DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); break; } case pucch_format1_nr: { N_ref_PUCCH = N_SYMB_SLOT; DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); break; } case pucch_format2_nr: case pucch_format3_nr: case pucch_format4_nr: { float N_RE = nb_of_prbs * N_sc_ctrl_RB * N_symb_PUCCH; float K1 = 6; /* initial phase so no higher layer parameters */ if (ue->UE_mode[gNB_id] != PUSCH) { if (O_ACK == 0) { n_HARQ_ACK = 0; } else { n_HARQ_ACK = 1; } } if (O_UCI < 12) { DELTA_TF = 10 * log10((double)(((K1 * (n_HARQ_ACK + O_SR + O_CSI))/N_RE))); } else { float K2 = 2.4; float BPRE = (O_ACK + O_SR + O_CSI + O_CRC)/N_RE; DELTA_TF = 10 * log10((double)(pow(2,(K2*BPRE)) - 1)); } break; } default: { LOG_E(PHY,"PUCCH unknown pucch format : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); return (0); } } int l = 0; int k2; if (power_config->twoPUCCH_PC_AdjustmentStates > 1) { LOG_E(PHY,"PUCCH power control adjustment states with 2 states not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); return (PUCCH_POWER_DEFAULT); } /* response to a detection by the UE of a DCI format 1_0 or DCI format 1_1 */ int K_PUCCH = 0; if (O_ACK != 0) { /* it assumes that PDCCH is in the first symbol of receive slot FFS TDDO NR */ int slots_gap = (proc->nr_tti_tx > proc->nr_tti_rx ? (proc->nr_tti_tx - proc->nr_tti_rx - 1) : ((proc->nr_tti_tx + ue->frame_parms.ttis_per_subframe) - proc->nr_tti_rx - 1)); K_PUCCH = (slots_gap * (ue->frame_parms.symbols_per_tti)) - 1; } else { /* field k2 is not present - to check k2 of pucch from upper layer FFS TDDO NR */ if (ue->pusch_config.pusch_TimeDomainResourceAllocation[0] == NULL) { if (ue->frame_parms.numerology_index == 0) { k2 = 1; } else { k2 = ue->frame_parms.numerology_index; } } else { /* get minimum value of k2 */ int i = 0; int k2_min = 32; /* max value of k2 */ do { k2 = ue->pusch_config.pusch_TimeDomainResourceAllocation[i]->k2; if (k2 < k2_min) { k2_min = k2; } i++; if (i >= MAX_NR_OF_UL_ALLOCATIONS) { break; } } while(ue->pusch_config.pusch_TimeDomainResourceAllocation[i] != NULL); k2 = k2_min; } K_PUCCH = N_SYMB_SLOT * k2; /* the product of a number of symbols per slot and the minimum of the values provided by higher layer parameter k2 */ } int contributor = (10 * log10((double)(pow(2,(ue->frame_parms.numerology_index)) * nb_of_prbs))); int16_t pucch_power = P_O_PUCCH + contributor + PL + delta_F_PUCCH + DELTA_TF + G_b_f_c; if (pucch_power > ue->tx_power_max_dBm) { pucch_power = ue->tx_power_max_dBm; } NR_TST_PHY_PRINTF("PUCCH ( Tx power : %d dBm ) ( 10Log(...) : %d ) ( from Path Loss : %d ) ( delta_F_PUCCH : %d ) ( DELTA_TF : %d ) ( G_b_f_c : %d ) \n", pucch_power, contributor, PL, delta_F_PUCCH, DELTA_TF, G_b_f_c); return (pucch_power); }