pusch_pc.c 10.5 KB
Newer Older
1 2 3 4 5
/*
 * 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
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * 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
 */

22
/*! \file pusch_pc.c
23
 * \brief Implementation of UE PUSCH Power Control procedures from 36.213 LTE specifications (Section
24 25 26 27 28 29 30 31 32
 * \author R. Knopp
 * \date 2011
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr
 * \note
 * \warning
 */

33
#include "defs.h"
34 35 36 37
#include "PHY/defs.h"
#include "PHY/LTE_TRANSPORT/proto.h"
#include "PHY/extern.h"

38 39
extern uint8_t  nfapi_mode;

40 41
// This is the formula from Section 5.1.1.1 in 36.213 100*10*log10((2^(MPR*Ks)-1)), where MPR is in the range [0,6] and Ks=1.25
int16_t hundred_times_delta_TF[100] = {-32768,-1268,-956,-768,-631,-523,-431,-352,-282,-219,-161,-107,-57,-9,36,79,120,159,197,234,269,304,337,370,402,434,465,495,525,555,583,612,640,668,696,723,750,777,803,829,856,881,907,933,958,983,1008,1033,1058,1083,1108,1132,1157,1181,1205,1229,1254,1278,1302,1325,1349,1373,1397,1421,1444,1468,1491,1515,1538,1562,1585,1609,1632,1655,1679,1702,1725,1748,1772,1795,1818,1841,1864,1887,1910,1933,1956,1980,2003,2026,2049,2072,2095,2118,2141,2164,2186,2209,2232,2255};
42 43
uint16_t hundred_times_log10_NPRB[100] = {0,301,477,602,698,778,845,903,954,1000,1041,1079,1113,1146,1176,1204,1230,1255,1278,1301,1322,1342,1361,1380,1397,1414,1431,1447,1462,1477,1491,1505,1518,1531,1544,1556,1568,1579,1591,1602,1612,1623,1633,1643,1653,1662,1672,1681,1690,1698,1707,1716,1724,1732,1740,1748,1755,1763,1770,1778,1785,1792,1799,1806,1812,1819,1826,1832,1838,1845,1851,1857,1863,1869,1875,1880,1886,1892,1897,1903,1908,1913,1919,1924,1929,1934,1939,1944,1949,1954,1959,1963,1968,1973,1977,1982,1986,1991,1995,2000};

44
int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint8_t UE_id,uint8_t harq_pid, uint8_t bw_factor)
45
{
46

47 48 49
  uint32_t Nre,sumKr,MPR_x100,Kr,r;
  uint16_t beta_offset_pusch;

50 51 52
  DevAssert( UE_id < NUMBER_OF_UE_MAX+1 );
  DevAssert( harq_pid < 8 );

53 54
  Nre = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_initial *
        eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12;
55 56

  sumKr = 0;
57

58 59 60
  for (r=0; r<eNB->ulsch[UE_id]->harq_processes[harq_pid]->C; r++) {
    if (r<eNB->ulsch[UE_id]->harq_processes[harq_pid]->Cminus)
      Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kminus;
61
    else
62
      Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus;
63

64 65
    sumKr += Kr;
  }
66

67 68 69
  if (Nre==0)
    return(0);

70
  MPR_x100 = 100*sumKr/Nre;
71 72 73 74
  // Note: MPR=is the effective spectral efficiency of the PUSCH
  // FK 20140908 sumKr is only set after the ulsch_encoding

  beta_offset_pusch = 8;
75
  //(eNB->ulsch[UE_id]->harq_processes[harq_pid]->control_only == 1) ? eNB->ulsch[UE_id]->beta_offset_cqi_times8:8;
76

77
  DevAssert( UE_id < NUMBER_OF_UE_MAX );
78
//#warning "This condition happens sometimes. Need more investigation" // navid
79
  //DevAssert( MPR_x100/6 < 100 );
80

81
  if (1==1) { //eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled == 1) {
82
    // This is the formula from Section 5.1.1.1 in 36.213 10*log10(deltaIF_PUSCH = (2^(MPR*Ks)-1)*beta_offset_pusch)
83
    if (bw_factor == 1) {
84
      uint8_t nb_rb = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb;
85 86 87 88
      return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3)) + hundred_times_log10_NPRB[nb_rb-1];
    } else
      return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3));
  } else {
89 90 91
    return(0);
  }
}
92

93 94
int16_t get_hundred_times_delta_IF_mac(module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t harq_pid)
{
95 96 97 98 99 100 101 102

  int8_t UE_id;

  if ((RC.eNB == NULL) || (module_idP > RC.nb_inst) || (CC_id > RC.nb_CC[module_idP])) {
    LOG_E(PHY,"get_UE_stats: No eNB found (or not allocated) for Mod_id %d,CC_id %d\n",module_idP,CC_id);
    return -1;
  }

103
  UE_id = find_ulsch( rnti, RC.eNB[module_idP][CC_id],SEARCH_EXIST);
104

105
  if (UE_id == -1) {
106 107
    // not found
    return 0;
108
  }
109

110
  return get_hundred_times_delta_IF_eNB( RC.eNB[module_idP][CC_id], UE_id, harq_pid, 0 );
111
}
112

113
int16_t get_hundred_times_delta_IF(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t harq_pid)
114 115
{

Bilel's avatar
Bilel committed
116
  uint32_t Nre = 2*ue->ulsch[eNB_id]->harq_processes[harq_pid]->Nsymb_initial *
117
                 ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb*12;
118 119 120 121

  if (Nre==0)
    return(0);

Bilel's avatar
Bilel committed
122
  uint32_t MPR_x100 = 100*ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/Nre;
123 124
  // Note: MPR=is the effective spectral efficiency of the PUSCH
  // FK 20140908 sumKr is only set after the ulsch_encoding
125

126 127
  uint16_t beta_offset_pusch = (ue->ulsch[eNB_id]->harq_processes[harq_pid]->control_only == 1) ?
    ue->ulsch[eNB_id]->beta_offset_cqi_times8:8;
128

129
  if (ue->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled == 1) {
130 131
    // This is the formula from Section 5.1.1.1 in 36.213 10*log10(deltaIF_PUSCH = (2^(MPR*Ks)-1)*beta_offset_pusch)
    return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3));
132
  } else {
133 134 135 136 137
    return(0);
  }
}


138

139
uint8_t alpha_lut[8] = {0,40,50,60,70,80,90,100};
140

141
void pusch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag)
142 143
{

144

145
  uint8_t harq_pid = subframe2harq_pid(&ue->frame_parms,
146 147
                                       proc->frame_tx,
                                       proc->subframe_tx);
148

149
  uint8_t nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb;
150
  int16_t PL;
151 152


153
  // P_pusch = 10*log10(nb_rb + P_opusch(j)+ alpha(u)*PL + delta_TF(i) + f(i))
154
  //
155 156 157
  // P_opusch(0) = P_oPTR + deltaP_Msg3 if PUSCH is transporting Msg3
  // else
  // P_opusch(0) = PO_NOMINAL_PUSCH(j) + P_O_UE_PUSCH(j)
158
  PL = get_PL(ue->Mod_id,ue->CC_id,eNB_id);
159

160 161 162
  ue->ulsch[eNB_id]->Po_PUSCH = (hundred_times_log10_NPRB[nb_rb-1]+
				 get_hundred_times_delta_IF(ue,eNB_id,harq_pid) +
				 100*ue->ulsch[eNB_id]->f_pusch)/100;
163

164
  if(ue->ulsch_Msg3_active[eNB_id] == 1) {  // Msg3 PUSCH
165

166
    ue->ulsch[eNB_id]->Po_PUSCH += (get_Po_NOMINAL_PUSCH(ue->Mod_id,0) + PL);
167 168


169
    LOG_I(PHY,"[UE  %d][RAPROC] frame %d, subframe %d: Msg3 Po_PUSCH %d dBm (%d,%d,100*PL=%d,%d,%d)\n",
170
          ue->Mod_id,proc->frame_tx,proc->subframe_tx,ue->ulsch[eNB_id]->Po_PUSCH,
171
          100*get_Po_NOMINAL_PUSCH(ue->Mod_id,0),
172 173
          hundred_times_log10_NPRB[nb_rb-1],
          100*PL,
174 175
          get_hundred_times_delta_IF(ue,eNB_id,harq_pid),
          100*ue->ulsch[eNB_id]->f_pusch);
176 177 178
  } else if (j==0) { // SPS PUSCH
  } else if (j==1) { // Normal PUSCH

179 180 181
    ue->ulsch[eNB_id]->Po_PUSCH +=  ((alpha_lut[ue->frame_parms.ul_power_control_config_common.alpha]*PL)/100);
    ue->ulsch[eNB_id]->Po_PUSCH +=  ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
    ue->ulsch[eNB_id]->PHR       =  ue->tx_power_max_dBm-ue->ulsch[eNB_id]->Po_PUSCH;  
182

183 184 185 186
    if (ue->ulsch[eNB_id]->PHR < -23)
      ue->ulsch[eNB_id]->PHR = -23;
    else if (ue->ulsch[eNB_id]->PHR > 40)
      ue->ulsch[eNB_id]->PHR = 40;
187

Bilel's avatar
Bilel committed
188 189
    LOG_D(PHY,"[UE  %d][PUSCH %d] AbsSubframe %d.%d: nb_rb: %d, Po_PUSCH %d dBm : tx power %d, Po_NOMINAL_PUSCH %d,log10(NPRB) %f,PHR %d, PL %d, alpha*PL %f,delta_IF %f,f_pusch %d\n",
          ue->Mod_id,harq_pid,proc->frame_tx,proc->subframe_tx,nb_rb,
190 191 192
          ue->ulsch[eNB_id]->Po_PUSCH,
          ue->tx_power_max_dBm,
          ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH,
193
          hundred_times_log10_NPRB[nb_rb-1]/100.0,
194
          ue->ulsch[eNB_id]->PHR,
195
          PL,
196 197 198
          alpha_lut[ue->frame_parms.ul_power_control_config_common.alpha]*PL/100.0,
          get_hundred_times_delta_IF(ue,eNB_id,harq_pid)/100.0,
          ue->ulsch[eNB_id]->f_pusch);
199
  }
200

201 202
}

203 204
int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id,uint8_t eNB_index)
{
205

206 207 208 209
	if(nfapi_mode!=3)
		return PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->PHR;
	else
		return 40; // For nfapi_mode=3 consider ideal conditions
210 211
}

212
// uint8_t eNB_id,uint8_t harq_pid, uint8_t UE_id,
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
int16_t estimate_ue_tx_power(uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs)
{

  /// The payload + CRC size in bits, "B"
  uint32_t B;
  /// Number of code segments
  uint32_t C;
  /// Number of "small" code segments
  uint32_t Cminus;
  /// Number of "large" code segments
  uint32_t Cplus;
  /// Number of bits in "small" code segments (<6144)
  uint32_t Kminus;
  /// Number of bits in "large" code segments (<6144)
  uint32_t Kplus;
228 229
  /// Total number of bits across all segments
  uint32_t sumKr;
230 231
  /// Number of "Filler" bits
  uint32_t F;
232 233 234 235 236
  // num resource elements
  uint32_t num_re=0.0;
  // num symbols
  uint32_t num_symb=0.0;
  /// effective spectral efficiency of the PUSCH
237
  uint32_t MPR_x100=0;
238 239 240 241
  /// beta_offset
  uint16_t beta_offset_pusch_x8=8;
  /// delta mcs
  float delta_mcs=0.0;
242
  /// bandwidth factor
243 244 245 246
  float bw_factor=0.0;

  B= tbs+24;
  lte_segmentation(NULL,
247 248 249 250 251 252 253 254 255 256 257
                   NULL,
                   B,
                   &C,
                   &Cplus,
                   &Cminus,
                   &Kplus,
                   &Kminus,
                   &F);


  sumKr = Cminus*Kminus + Cplus*Kplus;
258 259
  num_symb = 12-(ncp<<1)-(use_srs==0?0:1);
  num_re = num_symb * nb_rb * 12;
260

261 262 263 264
  if (num_re == 0)
    return(0);

  MPR_x100 = 100*sumKr/num_re;
265

266 267
  if (control_only == 1 )
    beta_offset_pusch_x8=8; // fixme
268

269
  //(beta_offset_pusch_x8=ue->ulsch[eNB_id]->harq_processes[harq_pid]->control_only == 1) ? ue->ulsch[eNB_id]->beta_offset_cqi_times8:8;
270 271 272 273 274

  // if deltamcs_enabledm
  delta_mcs = ((hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch_x8)>>3))/100.0);
  bw_factor = (hundred_times_log10_NPRB[nb_rb-1]/100.0);
#ifdef DEBUG_SEGMENTATION
275 276 277
  printf("estimated ue tx power %d (num_re %d, sumKr %d, mpr_x100 %d, delta_mcs %f, bw_factor %f)\n",
         (int16_t)ceil(delta_mcs + bw_factor), num_re, sumKr, MPR_x100, delta_mcs, bw_factor);
#endif
278
  return (int16_t)ceil(delta_mcs + bw_factor);
279

280
}