Commit 6d4de820 authored by Raghavendra Dinavahi's avatar Raghavendra Dinavahi Committed by Marwan Hammouda

PUSCH power control on UE side.UE commandline argument --ulpc to enable feature.

	- Reference values added and modified nr_get_Tx_amp

	- argument --ulpc
		- enables scaling factor calculation based on PUSCH/PUCCH transmit power
		- by default scaling factor for PUSCH/PUCCH is 512
parent 26c0b0e1
......@@ -136,6 +136,7 @@
#define CONFIG_HLP_TI_Scaling "set scaling I for TO"
#define CONFIG_HLP_TO_Iinit "Init the I part of the PI controller for timing offset compensation"
#define CONFIG_HLP_AGC "Enable Receive Automatic Gain control"
#define CONFIG_HLP_ULPC "Enable NR Uplink power control for PUSCH and PUCCH"
/*--------------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters for LOG utility */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
......
......@@ -646,10 +646,26 @@ nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc)
(proc->rx_slot_type == NR_MIXED_SLOT) &&
(proc->frame_rx % UPDATE_RX_GAIN == 0) &&
(proc->nr_slot_rx < 9)) {
/* reset averaging */
UE->init_averaging = 1;
/* Reset the rx gain update flag */
UE->measurements.rx_gain_update = 0;
/* Call the USRP API ina separate thread */
UE->rfdevice.trx_set_gains_func(&UE->rfdevice,&UE->rfdevice.openair0_cfg[0],1);
}
/* UPDATE TX GAIN */
/* USRP API Call for changing TX gain in a thread in slot 0*/
if ((UE->measurements.tx_gain_update == 1) &&
// To Ensure TX gain update done after RX gain update.
(proc->frame_rx % UPDATE_TX_GAIN == 1) &&
(proc->nr_slot_rx == 0)) {
/* Reset the rx gain update flag */
UE->measurements.tx_gain_update = 0;
/* Call the USRP API ina separate thread */
UE->rfdevice.trx_set_gains_func(&UE->rfdevice,&UE->rfdevice.openair0_cfg[0],1);
}
......
......@@ -294,11 +294,14 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
UE->no_timing_correction = nrUE_params.no_timing_correction;
UE->timing_advance = nrUE_params.timing_advance;
UE->enable_agc = nrUE_params.enable_agc;
UE->enable_ulpc = nrUE_params.enable_ulpc;
LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n",
UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time);
LOG_I(PHY,"dl AGC setting %d\n", UE->enable_agc);
LOG_I(PHY,"ul powercontrol setting %d\n", UE->enable_ulpc);
// Set FP variables
if (tddflag){
......
......@@ -79,7 +79,8 @@
{"TOP" , CONFIG_HLP_TP_Scaling, 0, .dblptr=&TO_PScaling, .defdblval=1.0, TYPE_DOUBLE, 0}, \
{"TOI" , CONFIG_HLP_TI_Scaling, 0, .dblptr=&TO_IScaling, .defdblval=0.1, TYPE_DOUBLE, 0}, \
{"TOII", CONFIG_HLP_TO_Iinit, 0, .iptr=&TO_IScalingInit, .defintval=0, TYPE_INT, 0}, \
{"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.enable_agc), .defintval=0, TYPE_INT, 0}}
{"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.enable_agc), .defintval=0, TYPE_INT, 0},\
{"ulpc", CONFIG_HLP_ULPC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.enable_ulpc), .defintval=0, TYPE_INT, 0}}
// clang-format on
typedef struct {
......@@ -101,6 +102,7 @@ typedef struct {
int N_RB_DL;
int ssb_start_subcarrier;
int enable_agc;
int enable_ulpc;
} nrUE_params_t;
extern uint64_t get_nrUE_optmask(void);
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
......
......@@ -360,7 +360,15 @@ typedef struct
//beamforming
nfapi_nr_ue_ul_beamforming_t beamforming;
//OAI specific
// PUSCH power related parameters
int8_t absolute_delta_PUSCH;
int16_t P0_PUSCH; //P0_NOMINAL_PUSCH + P0_UE_PUSCH
int16_t pathloss_compensation; //db which has alpha*pathloss
uint16_t deltaMCS;//0 if not enabled, 1 if enabled
uint16_t beta_offset;//1 if PUSCHData is ulsch data
uint16_t tpc_accumulation_enabled; //0-DISABLED. 1-ENABLED
uint16_t is_rar_grant;
int16_t power_rampup_requested;
} nfapi_nr_ue_pusch_pdu_t;
typedef struct {
......
......@@ -386,6 +386,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
ue->DopplerEst = 0;
ue->DopplerEstTot = (float)commonDoppler;
ue->f_pusch = 0;
return 0;
}
......
......@@ -316,12 +316,13 @@ void nr_layer_mapping(int16_t **mod_symbs,
void nr_ue_layer_mapping(int16_t *mod_symbs,
uint8_t n_layers,
uint32_t n_symbs,
int16_t **tx_layers) {
int16_t **tx_layers,
int tx_amp) {
for (int i=0; i<n_symbs/n_layers; i++) {
for (int l=0; l<n_layers; l++) {
tx_layers[l][i<<1] = (mod_symbs[(n_layers*i+l)<<1]*AMP)>>15;
tx_layers[l][(i<<1)+1] = (mod_symbs[((n_layers*i+l)<<1)+1]*AMP)>>15;
tx_layers[l][i<<1] = (mod_symbs[(n_layers*i+l)<<1]*tx_amp)>>15;
tx_layers[l][(i<<1)+1] = (mod_symbs[((n_layers*i+l)<<1)+1]*tx_amp)>>15;
}
}
}
......
......@@ -64,12 +64,14 @@ void nr_layer_mapping(int16_t **mod_symbs,
@param[in] n_layers, number of layers
@param[in] n_symbs, number of modulated symbols
@param[out] tx_layers, modulated symbols for each layer
@param[out] tx_amp, digital scaling factor for data
*/
void nr_ue_layer_mapping(int16_t *mod_symbs,
uint8_t n_layers,
uint32_t n_symbs,
int16_t **tx_layers);
int16_t **tx_layers,
int tx_amp);
/*!
......
......@@ -55,3 +55,28 @@ void phy_adjust_gain_nr(PHY_VARS_NR_UE *ue) {
ue->measurements.rx_gain_update, n0_dB,
ue->rfdevice.app_rx_gain[0], ue->rfdevice.openair0_cfg[0].rx_gain[0]);
}
/* Adjust the TX Gain based upon gain calculated from power control */
void phy_adjust_txgain_nr(PHY_VARS_NR_UE *ue, int16_t gain) {
int16_t app_tx_gain = ue->rfdevice.app_tx_gain[0];
/* Margin to be used for decision is 3 dB */
const int margin = 3;
/* If Gain change needed is more than margin then update the USRP TX gain */
if ((app_tx_gain - gain) > margin) {
ue->measurements.tx_gain_update = 1;
int16_t tx_gain = 0;
tx_gain = ue->rfdevice.openair0_cfg[0].tx_gain[0] - gain;
if (tx_gain > ue->rfdevice.max_tx_gain[0])
tx_gain = ue->rfdevice.max_tx_gain[0];
else if (tx_gain < ue->rfdevice.min_tx_gain[0])
tx_gain = ue->rfdevice.min_tx_gain[0];
ue->rfdevice.openair0_cfg[0].tx_gain[0] = tx_gain;
}
LOG_I(PHY,
"TX Gain Control: Flag %d, Margin:%d gain change needed:%d ,applied Tx Gain: %3.2f (dB) New Tx Gain ATT value %3.2f, Max:%3.2f\n",
ue->measurements.tx_gain_update, margin, gain, ue->rfdevice.app_tx_gain[0], ue->rfdevice.openair0_cfg[0].tx_gain[0],
ue->rfdevice.max_tx_gain[0]);
}
\ No newline at end of file
......@@ -123,6 +123,7 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
void phy_adjust_gain_nr(PHY_VARS_NR_UE *ue);
void phy_adjust_txgain_nr(PHY_VARS_NR_UE *ue, int16_t gain);
void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
int nbRx,
......
......@@ -159,10 +159,13 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue,
for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) {
ue->measurements.rx_power_avg_dB[gNB_id] = dB_fixed( ue->measurements.rx_power_avg[gNB_id]);
ue->measurements.wideband_cqi_tot[gNB_id] = ue->measurements.rx_power_tot_dB[gNB_id] - ue->measurements.n0_power_tot_dB;
ue->measurements.wideband_cqi_avg[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] - dB_fixed(ue->measurements.n0_power_avg);
ue->measurements.rx_rssi_dBm[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] + 30 - 10*log10(pow(2, 30)) - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size);
ue->measurements.rx_rssi_fixed_point_dB[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0])- dB_fixed(ue->frame_parms.ofdm_symbol_size);
ue->measurements.wideband_cqi_tot[gNB_id] = dB_fixed2(ue->measurements.rx_power_tot[gNB_id], ue->measurements.n0_power_tot);
ue->measurements.wideband_cqi_avg[gNB_id] = dB_fixed2(ue->measurements.rx_power_avg[gNB_id], ue->measurements.n0_power_avg);
//ue->measurements.rx_rssi_dBm[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] + 30 - 10*log10(pow(2, 30)) - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size);
ue->measurements.rx_rssi_dBm[gNB_id] = (ue->measurements.rx_power_avg_dB[gNB_id] - (int)ue->rfdevice.app_rx_gain[0]) - (int)openair0_cfg[0].rx_gain_offset[0];
//ue->measurements.rx_rssi_fixed_point_dB[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0])- dB_fixed(ue->frame_parms.ofdm_symbol_size);
ue->measurements.rx_rssi_fixed_point_dB[gNB_id] = (ue->measurements.rx_power_avg_dB[gNB_id] - (int)ue->rfdevice.app_rx_gain[0]) - (int)openair0_cfg[0].rx_gain_offset[0] - dB_fixed(ue->frame_parms.ofdm_symbol_size);
LOG_D(PHY,
"[gNB %d] Slot %d, RSSI %d dB (%d dBm/RE), WBandCQI %d dB, rxPwrAvg "
"%d, n0PwrAvg %d, Instant CQI %d (dB), RSSI Fixed Point (dB) %d\n",
......@@ -234,7 +237,9 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) -
dB_fixed(ue->frame_parms.ofdm_symbol_size);
LOG_D(PHY, "In %s: [UE %d] ssb %d SS-RSRP: %d dBm/RE (%d)\n",
ue->measurements.ssb_rsrp_dBm[ssb_index] = (10*log10(rsrp) - (int)ue->rfdevice.app_rx_gain[0]) - (int)openair0_cfg[0].rx_gain_offset[0];
LOG_D(PHY, "In %s: [UE %d] slot %d SS-RSRP: %d dBm/RE (%d)\n",
__FUNCTION__,
ue->Mod_id,
ssb_index,
......@@ -474,7 +479,7 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
const uint8_t k_length = 8;
uint8_t l_sss = (ue->symbol_offset + 2) % ue->frame_parms.symbols_per_slot;
unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier;
double rx_gain = openair0_cfg[0].rx_gain[0];
double rx_gain = (int)ue->rfdevice.app_rx_gain[0];
double rx_gain_offset = openair0_cfg[0].rx_gain_offset[0];
ue->measurements.n0_power_tot = 0;
......@@ -534,10 +539,12 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
((int)rx_gain - (int)rx_gain_offset) -
dB_fixed(ue->frame_parms.ofdm_symbol_size);
/* Noise Power spectral density calculations in dBm/RE */
ue->measurements.noise_psd = ue->measurements.n0_power_tot_dB + 30 -
10 * log10(pow(2, 30)) -
dB_fixed(ue->frame_parms.ofdm_symbol_size) -
((int)rx_gain - (int)rx_gain_offset);
/*ue->measurements.noise_psd = ue->measurements.n0_power_tot_dB + 30 -
10 * log10(pow(2, 30)) -
dB_fixed(ue->frame_parms.ofdm_symbol_size) -
((int)rx_gain - (int)rx_gain_offset);*/
ue->measurements.noise_psd = (ue->measurements.n0_power_tot_dB - (int)rx_gain) - (int)rx_gain_offset;
LOG_D(PHY,
"In [%s][slot:%d] Noise Level %d Noise Level %d (dB), Noise PSD %d (dBm/RE), NF USRP %d (dB) Noise Floor %d (dB/RE) \n",
__FUNCTION__, slot, ue->measurements.n0_power_tot,
......
......@@ -104,6 +104,16 @@ typedef struct {
uint8_t rnti_type;
/// Cell ID
int Nid_cell;
/// f_PUSCH parameter for PUSCH power control
int16_t f_pusch;
/// Po_PUSCH - target output power for PUSCH
int16_t pusch_tx_power;
/// PHR - current power headroom (based on last PUSCH transmission)
int16_t PHR;
/// Po_SRS - target output power for SRS
int16_t Po_SRS;
/// num active cba group
uint8_t num_active_cba_groups;
/// bit mask of PT-RS ofdm symbol indicies
uint16_t ptrs_symbols;
} NR_UE_ULSCH_t;
......
......@@ -48,6 +48,7 @@
#include "executables/softmodem-common.h"
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#include <openair2/UTIL/OPT/opt.h>
//#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
//#define DEBUG_PUSCH_MAPPING
//#define DEBUG_MAC_PDU
......@@ -55,6 +56,73 @@
//extern int32_t uplink_counter;
int16_t nr_get_pusch_tx_power(PHY_VARS_NR_UE *UE,
int scs,
nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
uint16_t N_RE,
uint16_t harq_pid){
//NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
//fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
//UE->tx_power_max_dBm = 10; //nr_get_Pcmax(mac, pusch_pdu->qam_mod_order, false, scs, cfg->carrier_config.dl_grid_size[scs], pusch_pdu->transform_precoding, pusch_pdu->rb_size, pusch_pdu->bwp_start);
/////////////////////////////////////////// delta_TF //////////////////////////////////////////////
float_t BPRE = 0;
uint8_t Nl = pusch_pdu->nrOfLayers;
uint16_t Kr = UE->ul_harq_processes[harq_pid].K;
uint16_t C = UE->ul_harq_processes[harq_pid].C;
int delta_TF = 0;
//if deltaMCS is configured, Ks = 1.25; else Ks = 0
// delta_TF is 0 if more than 1 layer
if (Nl == 1 || pusch_pdu->deltaMCS) { //deltaMCS configured or Nl = 1
if (pusch_pdu->beta_offset == 1)
BPRE = (float) C*Kr / N_RE;
else
BPRE = (pusch_pdu->qam_mod_order * (pusch_pdu->target_code_rate/10240.0))/pusch_pdu->beta_offset;
delta_TF = 10 * log10((pow(2, BPRE*1.25)-1) * pusch_pdu->beta_offset);
}
LOG_I(PHY, "Nl:%d, Qm:%d, coderate:%d Kr:%d, C:%d, N_RE:%d, BPRE:%f \n",
Nl, pusch_pdu->qam_mod_order, pusch_pdu->target_code_rate, Kr, C, N_RE, BPRE);
LOG_I(PHY, "deltaMCS:%d, betaoffset:%d, deltaTF:%d dB \n", pusch_pdu->deltaMCS, pusch_pdu->beta_offset, delta_TF);
///////////////////////////////////////////// delta_TF END ///////////////////////////////////////////////
LOG_I(PHY, "scs:%d, M_RB_PUSCH:%d, deltapusch:%d dB, tpc_accumulation_enabled:%d \n",
scs, pusch_pdu->rb_size, pusch_pdu->absolute_delta_PUSCH, pusch_pdu->tpc_accumulation_enabled);
/// Final PUSCH target power
int16_t pusch_power = 0;
int M_pusch_component = (10 * log10((double)(1<<scs * pusch_pdu->rb_size)));
int16_t f_pusch = 0;
// TbD: extend delta_PUSCH to the sum of TPC command values as per clause 7.1.1 of TS 38.213 version 16.3.0 Release 16
// now is taking into account only the last received TPC command from DCI
if (pusch_pdu->is_rar_grant){ // UE receives a PUSCH from RAR grant
pusch_power = pusch_pdu->P0_PUSCH + M_pusch_component + pusch_pdu->pathloss_compensation + delta_TF + pusch_pdu->absolute_delta_PUSCH;
int delta_P_rampup = min( max(0, (UE->tx_power_max_dBm - pusch_power)), pusch_pdu->power_rampup_requested);
UE->f_pusch = delta_P_rampup + pusch_pdu->absolute_delta_PUSCH;
} else {
f_pusch = (pusch_pdu->tpc_accumulation_enabled) ? (UE->f_pusch + pusch_pdu->absolute_delta_PUSCH) : pusch_pdu->absolute_delta_PUSCH;
pusch_power = pusch_pdu->P0_PUSCH + M_pusch_component + pusch_pdu->pathloss_compensation + delta_TF + f_pusch;
}
LOG_I(PHY, "PUSCH(Tx power: %d dBm) (P0_offset: %d dB) (bw gain: %d dB) (gain because of pathloss: %d dB) (delta_TF: %d dB) (TPC adjustment: %d dB) \n",
pusch_power, pusch_pdu->P0_PUSCH, M_pusch_component, pusch_pdu->pathloss_compensation, delta_TF, f_pusch);
///////////////////////////////////////////// f_pusch END ///////////////////////////////////////////////
if (pusch_power <= UE->tx_power_max_dBm)
UE->f_pusch = f_pusch;
else
pusch_power = UE->tx_power_max_dBm;
return (pusch_power);
}
void nr_pusch_codeword_scrambling_uci(uint8_t *in,
uint32_t size,
uint32_t Nid,
......@@ -253,7 +321,38 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
}
///////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////PUSCH TX POWER to be calculated///////////////////////////////////////
int tx_amp = AMP;
if (UE->enable_ulpc) {
uint16_t max_dmrs_re = nb_dmrs_re_per_rb * nb_rb * number_dmrs_symbols;
uint16_t max_ptrs_re = 0; //
uint16_t N_RE = number_of_symbols*nb_rb*NR_NB_SC_PER_RB - max_dmrs_re - max_ptrs_re;
ulsch_ue->pusch_tx_power = nr_get_pusch_tx_power(UE, frame_parms->numerology_index,
pusch_pdu,
N_RE,
harq_pid);
//Power headroom - remaining power - pusch tx power
ulsch_ue->PHR = UE->tx_power_max_dBm - ulsch_ue->pusch_tx_power;
/* set tx power */
UE->tx_power_dBm[slot] = ulsch_ue->pusch_tx_power;
UE->tx_total_RE[slot] = pusch_pdu->rb_size*N_SC_RB;
tx_amp = nr_get_tx_amp(UE, ulsch_ue->pusch_tx_power ,
UE->tx_power_max_dBm,
UE->frame_parms.N_RB_UL,
pusch_pdu->rb_size);
LOG_I(PHY,"ULPC ENABLED: max tx power:%d, PUSCH tx power:%d PHR:%d dB , PUSCH scaling factor:%d\n",
UE->tx_power_max_dBm, UE->tx_power_dBm[slot], ulsch_ue->PHR, tx_amp);
} else {
LOG_I(PHY,"ULPC DISABLED: PUSCH scaling factor:%d\n", tx_amp);
}
/////////////////////////ULSCH layer mapping/////////////////////////
///////////
......@@ -265,7 +364,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
nr_ue_layer_mapping((int16_t *)d_mod,
Nl,
available_bits/mod_order,
tx_layers);
tx_layers, tx_amp);
///////////
////////////////////////////////////////////////////////////////////////
......@@ -426,11 +525,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
if (is_dmrs == 1) {
// if transform precoding is enabled
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[2*dmrs_idx]) >> 15;
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[(2*dmrs_idx) + 1]) >> 15;
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*tx_amp*dmrs_seq[2*dmrs_idx]) >> 15;
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*tx_amp*dmrs_seq[(2*dmrs_idx) + 1]) >> 15;
} else {
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[dmrs_idx<<1]) >> 15;
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*tx_amp*mod_dmrs[dmrs_idx<<1]) >> 15;
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*tx_amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
}
#ifdef DEBUG_PUSCH_MAPPING
......@@ -445,8 +544,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
n+=(k_prime)?0:1;
} else if (is_ptrs == 1) {
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = (beta_ptrs*AMP*mod_ptrs[ptrs_idx<<1]) >> 15;
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (beta_ptrs*AMP*mod_ptrs[(ptrs_idx<<1) + 1]) >> 15;
((int16_t*)tx_precoding[nl])[(sample_offsetF)<<1] = (beta_ptrs*tx_amp*mod_ptrs[ptrs_idx<<1]) >> 15;
((int16_t*)tx_precoding[nl])[((sample_offsetF)<<1) + 1] = (beta_ptrs*tx_amp*mod_ptrs[(ptrs_idx<<1) + 1]) >> 15;
ptrs_idx++;
} else if (!is_dmrs_sym || allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) {
if (pusch_pdu->transform_precoding == transformPrecoder_disabled) {
......
......@@ -247,6 +247,7 @@ typedef struct {
bool meas_running;
// update the flag to update rx gain value
short rx_gain_update;
short tx_gain_update;
} PHY_NR_MEASUREMENTS;
typedef struct {
......@@ -697,6 +698,11 @@ typedef struct {
// Enables Automatic gain control. controlled by --agc flag
int enable_agc;
int f_pusch;
// Enables Power control for PUSCH/PUCCH transmission. controlled by --ulpc flag
//Scaling factor will be calculated based on tranmit power of the channel.
// by default scaling factor is 512
int enable_ulpc;
} PHY_VARS_NR_UE;
typedef struct nr_phy_data_tx_s {
......
......@@ -185,8 +185,11 @@
//#define MIN_RF_GAIN 96
#define MAX_RF_GAIN 200
#define MIN_RF_GAIN 80
// update rx after 20 frames for usrp
#define UPDATE_RX_GAIN 20
// update rx after 16 frames for usrp
#define UPDATE_RX_GAIN 16
// update tx gain after 16 frames for usrp
#define UPDATE_TX_GAIN 16
#define PHY_SYNCH_OFFSET ((OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)-1) // OFFSET of BEACON SYNCH
#define PHY_SYNCH_MIN_POWER 1000
......
......@@ -128,7 +128,7 @@ int8_t nr_find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB);
*/
void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx);
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb);
unsigned int nr_get_tx_amp(PHY_VARS_NR_UE *UE, int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb);
void set_tx_harq_id(NR_UE_ULSCH_t *ulsch, int harq_pid, int slot_tx);
int get_tx_harq_id(NR_UE_ULSCH_t *ulsch, int slot_tx);
......
......@@ -52,6 +52,7 @@
#include "executables/nr-uesoftmodem.h"
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
//#define DEBUG_PHY_PROC
//#define NR_PDCCH_SCHED_DEBUG
......@@ -286,6 +287,15 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
for (uint8_t harq_pid = 0; harq_pid < NR_MAX_ULSCH_HARQ_PROCESSES; harq_pid++) {
if (ue->ul_harq_processes[harq_pid].status == ACTIVE) {
if(ue->enable_ulpc)
{
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
NR_UE_MAC_INST_t *mac = get_mac_inst(ue->Mod_id);
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
NR_UE_ULSCH_t *ulsch_ue = &phy_data->ulsch;
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch_ue->pusch_pdu;
ue->tx_power_max_dBm = nr_get_Pcmax(mac, pusch_pdu->qam_mod_order, false, frame_parms->subcarrier_spacing, cfg->carrier_config.dl_grid_size[frame_parms->numerology_index], pusch_pdu->transform_precoding, pusch_pdu->rb_size, pusch_pdu->bwp_start);
}
nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, gNB_id, phy_data, (c16_t **)&txdataF);
}
}
......@@ -398,21 +408,66 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
return ret;
}
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb)
unsigned int nr_get_tx_amp(PHY_VARS_NR_UE *UE, int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb)
{
int gain_dB = power_dBm - power_max_dBm;
#define MAX_INCREASE_IN_GAIN_FROM_SCALING_FACTOR 6
#define MIN_DECREASE_IN_GAIN_FROM_SCALING_FACTOR -12
AssertFatal(((nb_rb >0) && (nb_rb <= N_RB_UL)), "Illegal nb_rb/N_RB_UL combination (%d/%d)\n",nb_rb,N_RB_UL);
int16_t gain_db = 0, digital_gain_per_re = 0, tx_gain_adjust_dB = 0;
const int16_t reference_scaling_gain = 51; //51db for every RE .10log362 using scaling factor AMP (512)
const int16_t max_possible_bw_gain = round(10*log10(N_RB_UL));
const int16_t allocated_bw_gain = round(10*log10(nb_rb));
// Increase from 512->1024 is change in power by 6dB
// Decrease from 512->128 is change in power by -12dB
//Possible digital scaling = 6db + bw gain possible
const int16_t max_digital_scaling_gain = MAX_INCREASE_IN_GAIN_FROM_SCALING_FACTOR + (max_possible_bw_gain - allocated_bw_gain);
const int16_t min_digital_scaling_gain = MIN_DECREASE_IN_GAIN_FROM_SCALING_FACTOR; //-12db
unsigned int scaling_factor = 0;
double gain_lin;
gain_lin = pow(10,.1*gain_dB);
if ((nb_rb >0) && (nb_rb <= N_RB_UL)) {
return((int)(AMP*sqrt(gain_lin*N_RB_UL/(double)nb_rb)));
}
else {
LOG_E(PHY,"Illegal nb_rb/N_RB_UL combination (%d/%d)\n",nb_rb,N_RB_UL);
//mac_xface->macphy_exit("");
gain_db = power_dBm + UE->rfdevice.openair0_cfg->tx_gain_offset[0];
LOG_I(PHY, "Expected power:%d dbm, Max power:%d dbm, tx_dbm_to_db_offset:%d dB, Applied TX gain:%d\n",
power_dBm, power_max_dBm, (int)UE->rfdevice.openair0_cfg->tx_gain_offset[0], (int)UE->rfdevice.app_tx_gain[0]);
LOG_D(PHY, "gain_db:%d db, max_possible_bw_gain:%d db, bw gain:%d, MAX RBs:%d, Allocated RBs:%d \n",
gain_db, max_possible_bw_gain, allocated_bw_gain, N_RB_UL, nb_rb);
// Remove the applied TX GAIN from to be achieved power gain
gain_db = gain_db - (int)UE->rfdevice.app_tx_gain[0];
digital_gain_per_re = gain_db - allocated_bw_gain; // Remove gain achieved because of Bw
digital_gain_per_re = digital_gain_per_re - reference_scaling_gain;
LOG_I(PHY, "gain_db:%d db, Max possible Digital scaling Gain:%d db/RE, Min Digital scaling Gain:%d db/RE, digital gain per RE:%d db/RE\n",
gain_db, max_digital_scaling_gain, min_digital_scaling_gain, digital_gain_per_re);
if (digital_gain_per_re < min_digital_scaling_gain) {
tx_gain_adjust_dB = digital_gain_per_re - min_digital_scaling_gain;
digital_gain_per_re = min_digital_scaling_gain;
} else if (digital_gain_per_re > max_digital_scaling_gain) {
tx_gain_adjust_dB = digital_gain_per_re - max_digital_scaling_gain;
digital_gain_per_re = max_digital_scaling_gain;
}
return(0);
gain_lin = pow(10,.1*digital_gain_per_re);
// Set USRP txgain such that the tx gain increases by tx_gain_adjust
// Can USRP tx_gain be set during execution?
// Need to check the consequences of apply tx_gain to USRP in run mode . TBD.....
phy_adjust_txgain_nr(UE, tx_gain_adjust_dB);
LOG_I(PHY, "USRP TX gain should be adjusted by %d dB to achieve the expected transmit power. New tx_gain value:%3.2f\n",
tx_gain_adjust_dB, UE->rfdevice.openair0_cfg->tx_gain[0]);
scaling_factor = (int)(AMP*sqrt(gain_lin));
LOG_I(PHY,"Scaling factor:%d, Digital gain from scaling factor:%d dB/RE \n",scaling_factor, digital_gain_per_re);
return scaling_factor;
}
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
......
......@@ -210,17 +210,18 @@ void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
ue->tx_power_dBm[nr_slot_tx] = pucch_tx_power;
ue->tx_total_RE[nr_slot_tx] = nb_of_prbs*N_SC_RB;
int tx_amp;
int tx_amp = AMP;
if (ue->enable_ulpc) {
/*
tx_amp = nr_get_tx_amp(pucch_tx_power,
tx_amp = nr_get_tx_amp(ue, pucch_tx_power,
ue->tx_power_max_dBm,
ue->frame_parms.N_RB_UL,
nb_of_prbs);
if (tx_amp == 0)*/
// FIXME temporarly using fixed amplitude before pucch power control implementation revised
tx_amp = AMP;
LOG_D(PHY,"ULPC ENABLED: pucch_tx_power:%d , maxpower:%d, PUCCH scaling factor:%d\n",
pucch_tx_power, ue->tx_power_max_dBm, tx_amp);
} else {
LOG_D(PHY,"ULPC DISABLED: PUCCH scaling factor:%d\n", tx_amp);
}
LOG_D(PHY,"Generation of PUCCH format %d at frame.slot %d.%d\n",pucch_pdu->format_type,proc->frame_tx,nr_slot_tx);
......
......@@ -595,6 +595,7 @@ typedef struct NR_UE_UL_BWP {
NR_CSI_MeasConfig_t *csi_MeasConfig;
NR_SRS_Config_t *srs_Config;
long *msg3_DeltaPreamble;
long *p0_NominalWithGrant;
long transform_precoding;
uint8_t mcs_table;
nr_dci_format_t dci_format;
......
......@@ -582,6 +582,7 @@ void configure_current_BWP(NR_UE_MAC_INST_t *mac,
if (mac->bwp_ulcommon->pusch_ConfigCommon) {
UL_BWP->tdaList_Common = mac->bwp_ulcommon->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
UL_BWP->msg3_DeltaPreamble = mac->bwp_ulcommon->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble;
UL_BWP->p0_NominalWithGrant = mac->bwp_ulcommon->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant;
}
if (mac->bwp_ulcommon->pucch_ConfigCommon)
UL_BWP->pucch_ConfigCommon = mac->bwp_ulcommon->pucch_ConfigCommon->choice.setup;
......@@ -639,6 +640,7 @@ void configure_current_BWP(NR_UE_MAC_INST_t *mac,
}
UL_BWP->msg3_DeltaPreamble = mac->bwp_ulcommon->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble;
UL_BWP->p0_NominalWithGrant = mac->bwp_ulcommon->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant;
NR_BWP_Uplink_t *bwp_uplink = NULL;
const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList;
......
......@@ -534,5 +534,15 @@ typedef struct {
} NR_UE_MAC_INST_t;
typedef enum e_pusch_grant_type {
PUSCH_GRANT_TYPE_MIN,
PUSCH_GRANT_TYPE_RAR,
PUSCH_GRANT_TYPE_MSGA,
PUSCH_GRANT_TYPE_CONFIGURED,
PUSCH_GRANT_TYPE_DCI
} e_pusch_grant_type_t;
/*@}*/
#endif /*__LAYER2_MAC_DEFS_H__ */
......@@ -291,6 +291,12 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
fapi_nr_ul_config_pucch_pdu *pucch_pdu);
int nr_get_Pcmax(NR_UE_MAC_INST_t *mac, int Qm, bool powerBoostPi2BPSK, int scs, int N_RB_UL, bool is_transform_precoding, int n_prbs, int start_prb);
void nr_get_pusch_tx_power_ue_parameters(NR_UE_MAC_INST_t *mac,
NR_PUSCH_Config_t *pusch_Config,
NR_PUSCH_ConfigCommon_t *pusch_ConfigCommon,
nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
e_pusch_grant_type_t grant_type);
/* Random Access */
......
......@@ -530,6 +530,11 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->pusch_data.num_cb = 0;
pusch_config_pdu->tbslbrm = 0;
pusch_config_pdu->absolute_delta_PUSCH = mac->ra.Msg3_TPC;
nr_get_pusch_tx_power_ue_parameters(mac,pusch_Config, NULL, pusch_config_pdu, PUSCH_GRANT_TYPE_RAR);
} else if (dci) {
pusch_config_pdu->bwp_start = current_UL_BWP->BWPStart;
pusch_config_pdu->bwp_size = current_UL_BWP->BWPSize;
......@@ -640,17 +645,32 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->pusch_data.harq_process_id = dci->harq_pid;
/* TPC_PUSCH */
// according to TS 38.213 Table Table 7.1.1-1
if (dci->tpc == 0) {
pusch_config_pdu->absolute_delta_PUSCH = -4;
}
if (dci->tpc == 1) {
pusch_config_pdu->absolute_delta_PUSCH = -1;
}
if (dci->tpc == 2) {
pusch_config_pdu->absolute_delta_PUSCH = 1;
}
if (dci->tpc == 3) {
pusch_config_pdu->absolute_delta_PUSCH = 4;
if (pusch_Config->pusch_PowerControl->tpc_Accumulation != NULL) { // TPC ACCUMULATION DISABLED if IE present
if (dci->tpc == 0) {
pusch_config_pdu->absolute_delta_PUSCH = -4;
}
if (dci->tpc == 1) {
pusch_config_pdu->absolute_delta_PUSCH = -1;
}
if (dci->tpc == 2) {
pusch_config_pdu->absolute_delta_PUSCH = 1;
}
if (dci->tpc == 3) {
pusch_config_pdu->absolute_delta_PUSCH = 4;
}
} else { // TPC ACCULUMULATION ENABLED
if (dci->tpc == 0) {
pusch_config_pdu->absolute_delta_PUSCH = -1;
}
if (dci->tpc == 1) {
pusch_config_pdu->absolute_delta_PUSCH = 0;
}
if (dci->tpc == 2) {
pusch_config_pdu->absolute_delta_PUSCH = 1;
}
if (dci->tpc == 3) {
pusch_config_pdu->absolute_delta_PUSCH = 3;
}
}
if (NR_DMRS_ulconfig != NULL)
......@@ -701,6 +721,8 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
LOG_D(NR_MAC, "UL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", pusch_config_pdu->pusch_ptrs.ptrs_time_density, pusch_config_pdu->pusch_ptrs.ptrs_freq_density);
}
}
nr_get_pusch_tx_power_ue_parameters(mac,pusch_Config, NULL, pusch_config_pdu, PUSCH_GRANT_TYPE_DCI);
}
LOG_D(NR_MAC, "In %s: received UL grant (rb_start %d, rb_size %d, start_symbol_index %d, nr_of_symbols %d) for RNTI type %s \n",
......
......@@ -1086,6 +1086,9 @@ static struct NR_SetupRelease_PUSCH_Config *config_pusch(NR_PUSCH_Config_t *pusc
if (!pusch_Config->pusch_PowerControl->msg3_Alpha)
pusch_Config->pusch_PowerControl->msg3_Alpha = calloc(1, sizeof(*pusch_Config->pusch_PowerControl->msg3_Alpha));
*pusch_Config->pusch_PowerControl->msg3_Alpha = NR_Alpha_alpha1;
//Set tpc accumulation to disabled
pusch_Config->pusch_PowerControl->tpc_Accumulation = calloc(1, sizeof(*pusch_Config->pusch_PowerControl->tpc_Accumulation));
*pusch_Config->pusch_PowerControl->tpc_Accumulation = 0;
pusch_Config->pusch_PowerControl->p0_NominalWithoutGrant = NULL;
pusch_Config->pusch_PowerControl->p0_AlphaSets = calloc(1, sizeof(*pusch_Config->pusch_PowerControl->p0_AlphaSets));
NR_P0_PUSCH_AlphaSet_t *aset = calloc(1, sizeof(*aset));
......
......@@ -128,10 +128,9 @@ typedef enum {
MAX_HOST_TYPE
} host_type_t;
/*! \brief RF Gain clibration */
/*! \brief RF Gain calibration */
typedef struct {
//! Frequency for which RX chain was calibrated
//! Frequency for which TX,RX chain was calibrated
double freq;
//! Offset to be applied to RX gain
double offset;
......@@ -177,6 +176,15 @@ typedef enum {
RU_GPIO_CONTROL_GENERIC,
RU_GPIO_CONTROL_INTERDIGITAL,
} gpio_control_t;
/*! \brief RF REFERENCE measurements against a calibrated device in Downlink and uplink*/
typedef struct {
//! Band on which reference measurements were done
//uint16_t band;
//! Offset to be applied on received digital power in db to covert to dbm
int16_t rx_db_to_dbm_offset;
//!Offset to be applied on uplink power to convert to digital power in db
int16_t tx_dbm_to_db_offset;
} reference_meas_t;
/*! \brief RF frontend parameters set by application */
typedef struct {
......@@ -222,6 +230,8 @@ typedef struct {
//! \brief memory
//! \brief Pointer to Calibration table for RX gains
rx_gain_calib_table_t *rx_gain_calib_table;
//! \brief Pointer to Calibration table for TX gains
rx_gain_calib_table_t *tx_gain_calib_table;
//! mode for rxgain (ExpressMIMO2)
rx_gain_t rxg_mode[4];
//! \brief Gain for RX in dB.
......@@ -232,6 +242,9 @@ typedef struct {
double rx_gain_offset[4];
//! gain for TX in dB
double tx_gain[4];
//! \brief TX Gain offset (for calibration) in dB
//! index: [0..tx_num_channels]
double tx_gain_offset[4];
//! RX bandwidth in Hz
double rx_bw;
//! TX bandwidth in Hz
......@@ -281,6 +294,9 @@ typedef struct {
int txfh_cores[4];
//! select the GPIO control method
gpio_control_t gpio_controller;
//!reference measurements done on this device
//reference_meas_t *reference_meas;
} openair0_config_t;
/*! \brief RF mapping */
......@@ -394,10 +410,14 @@ struct openair0_device_t {
/* !brief Store the value of max gain limit for the RX 4*4 MIMO */
double max_rx_gain[4];
/* !brief Store the value of max gain limit for the RX 4*4 MIMO */
double min_rx_gain[4];
/* !brief Store the value of applied gain for the RX 4*4 MIMO */
double app_rx_gain[4];
/* !brief Store the value of max gain limit for the TX 4*4 MIMO */
double max_tx_gain[4];
/* !brief Store the value of max gain limit for the TX 4*4 MIMO */
double min_tx_gain[4];
/* !brief Store the value of applied gain for the TX 4*4 MIMO */
double app_tx_gain[4];
......
This diff is collapsed.
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