1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*
* 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"
#include <openair1/PHY/LTE_ESTIMATION/lte_estimation.h>
#include <openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h>
/**************** 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[proc->thread_id][gNB_id][0]->g_pucch;
LOG_D(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_nr_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 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_slot_tx > proc->nr_slot_rx ? (proc->nr_slot_tx - proc->nr_slot_rx - 1) : ((proc->nr_slot_tx + ue->frame_parms.slots_per_subframe) - proc->nr_slot_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);
}