Commit dcd09069 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/srs-tx-power' into integration_2024_w40

parents 5636d77c fecff5f3
......@@ -36,6 +36,79 @@
#include "nr_common.h"
#include <complex.h>
#define C_SRS_NUMBER (64)
#define B_SRS_NUMBER (4)
/* TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration */
static const unsigned short srs_bandwidth_config[C_SRS_NUMBER][B_SRS_NUMBER][2] = {
/* B_SRS = 0 B_SRS = 1 B_SRS = 2 B_SRS = 3 */
/* C SRS m_srs0 N_0 m_srs1 N_1 m_srs2 N_2 m_srs3 N_3 */
/* 0 */ {{4, 1}, {4, 1}, {4, 1}, {4, 1}},
/* 1 */ {{8, 1}, {4, 2}, {4, 1}, {4, 1}},
/* 2 */ {{12, 1}, {4, 3}, {4, 1}, {4, 1}},
/* 3 */ {{16, 1}, {4, 4}, {4, 1}, {4, 1}},
/* 4 */ {{16, 1}, {8, 2}, {4, 2}, {4, 1}},
/* 5 */ {{20, 1}, {4, 5}, {4, 1}, {4, 1}},
/* 6 */ {{24, 1}, {4, 6}, {4, 1}, {4, 1}},
/* 7 */ {{24, 1}, {12, 2}, {4, 3}, {4, 1}},
/* 8 */ {{28, 1}, {4, 7}, {4, 1}, {4, 1}},
/* 9 */ {{32, 1}, {16, 2}, {8, 2}, {4, 2}},
/* 10 */ {{36, 1}, {12, 3}, {4, 3}, {4, 1}},
/* 11 */ {{40, 1}, {20, 2}, {4, 5}, {4, 1}},
/* 12 */ {{48, 1}, {16, 3}, {8, 2}, {4, 2}},
/* 13 */ {{48, 1}, {24, 2}, {12, 2}, {4, 3}},
/* 14 */ {{52, 1}, {4, 13}, {4, 1}, {4, 1}},
/* 15 */ {{56, 1}, {28, 2}, {4, 7}, {4, 1}},
/* 16 */ {{60, 1}, {20, 3}, {4, 5}, {4, 1}},
/* 17 */ {{64, 1}, {32, 2}, {16, 2}, {4, 4}},
/* 18 */ {{72, 1}, {24, 3}, {12, 2}, {4, 3}},
/* 19 */ {{72, 1}, {36, 2}, {12, 3}, {4, 3}},
/* 20 */ {{76, 1}, {4, 19}, {4, 1}, {4, 1}},
/* 21 */ {{80, 1}, {40, 2}, {20, 2}, {4, 5}},
/* 22 */ {{88, 1}, {44, 2}, {4, 11}, {4, 1}},
/* 23 */ {{96, 1}, {32, 3}, {16, 2}, {4, 4}},
/* 24 */ {{96, 1}, {48, 2}, {24, 2}, {4, 6}},
/* 25 */ {{104, 1}, {52, 2}, {4, 13}, {4, 1}},
/* 26 */ {{112, 1}, {56, 2}, {28, 2}, {4, 7}},
/* 27 */ {{120, 1}, {60, 2}, {20, 3}, {4, 5}},
/* 28 */ {{120, 1}, {40, 3}, {8, 5}, {4, 2}},
/* 29 */ {{120, 1}, {24, 5}, {12, 2}, {4, 3}},
/* 30 */ {{128, 1}, {64, 2}, {32, 2}, {4, 8}},
/* 31 */ {{128, 1}, {64, 2}, {16, 4}, {4, 4}},
/* 32 */ {{128, 1}, {16, 8}, {8, 2}, {4, 2}},
/* 33 */ {{132, 1}, {44, 3}, {4, 11}, {4, 1}},
/* 34 */ {{136, 1}, {68, 2}, {4, 17}, {4, 1}},
/* 35 */ {{144, 1}, {72, 2}, {36, 2}, {4, 9}},
/* 36 */ {{144, 1}, {48, 3}, {24, 2}, {12, 2}},
/* 37 */ {{144, 1}, {48, 3}, {16, 3}, {4, 4}},
/* 38 */ {{144, 1}, {16, 9}, {8, 2}, {4, 2}},
/* 39 */ {{152, 1}, {76, 2}, {4, 19}, {4, 1}},
/* 40 */ {{160, 1}, {80, 2}, {40, 2}, {4, 10}},
/* 41 */ {{160, 1}, {80, 2}, {20, 4}, {4, 5}},
/* 42 */ {{160, 1}, {32, 5}, {16, 2}, {4, 4}},
/* 43 */ {{168, 1}, {84, 2}, {28, 3}, {4, 7}},
/* 44 */ {{176, 1}, {88, 2}, {44, 2}, {4, 11}},
/* 45 */ {{184, 1}, {92, 2}, {4, 23}, {4, 1}},
/* 46 */ {{192, 1}, {96, 2}, {48, 2}, {4, 12}},
/* 47 */ {{192, 1}, {96, 2}, {24, 4}, {4, 6}},
/* 48 */ {{192, 1}, {64, 3}, {16, 4}, {4, 4}},
/* 49 */ {{192, 1}, {24, 8}, {8, 3}, {4, 2}},
/* 50 */ {{208, 1}, {104, 2}, {52, 2}, {4, 13}},
/* 51 */ {{216, 1}, {108, 2}, {36, 3}, {4, 9}},
/* 52 */ {{224, 1}, {112, 2}, {56, 2}, {4, 14}},
/* 53 */ {{240, 1}, {120, 2}, {60, 2}, {4, 15}},
/* 54 */ {{240, 1}, {80, 3}, {20, 4}, {4, 5}},
/* 55 */ {{240, 1}, {48, 5}, {16, 3}, {8, 2}},
/* 56 */ {{240, 1}, {24, 10}, {12, 2}, {4, 3}},
/* 57 */ {{256, 1}, {128, 2}, {64, 2}, {4, 16}},
/* 58 */ {{256, 1}, {128, 2}, {32, 4}, {4, 8}},
/* 59 */ {{256, 1}, {16, 16}, {8, 2}, {4, 2}},
/* 60 */ {{264, 1}, {132, 2}, {44, 3}, {4, 11}},
/* 61 */ {{272, 1}, {136, 2}, {68, 2}, {4, 17}},
/* 62 */ {{272, 1}, {68, 4}, {4, 17}, {4, 1}},
/* 63 */ {{272, 1}, {16, 17}, {8, 2}, {4, 2}},
};
const char *duplex_mode[]={"FDD","TDD"};
static const uint8_t bit_reverse_table_256[] = {
......@@ -1212,3 +1285,11 @@ void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t ste
timer->step = step;
nr_timer_stop(timer);
}
unsigned short get_m_srs(int c_srs, int b_srs) {
return srs_bandwidth_config[c_srs][b_srs][0];
}
unsigned short get_N_b_srs(int c_srs, int b_srs) {
return srs_bandwidth_config[c_srs][b_srs][1];
}
......@@ -250,6 +250,8 @@ int get_scan_ssb_first_sc(const double fc,
void check_ssb_raster(uint64_t freq, int band, int scs);
int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_range, int n_rbs);
unsigned short get_m_srs(int c_srs, int b_srs);
unsigned short get_N_b_srs(int c_srs, int b_srs);
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
......
......@@ -391,6 +391,7 @@ typedef struct {
uint16_t t_srs; // SRS-Periodicity in slots [3GPP TS 38.211, Sec 6.4.1.4.4], Value: 1,2,3,4,5,8,10,16,20,32,40,64,80,160,320,640,1280,2560
uint16_t t_offset; // Slot offset value [3GPP TS 38.211, Sec 6.4.1.4.3], Value:0->2559
nfapi_nr_ue_ul_beamforming_t beamforming;
int16_t tx_power;
} fapi_nr_ul_config_srs_pdu;
typedef struct {
......
......@@ -631,7 +631,7 @@ int nr_srs_channel_estimation(
const uint8_t N_ap = 1<<srs_pdu->num_ant_ports;
const uint8_t K_TC = 2<<srs_pdu->comb_size;
const uint16_t m_SRS_b = srs_bandwidth_config[srs_pdu->config_index][srs_pdu->bandwidth_index][0];
const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index);
const uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB/K_TC;
uint8_t fd_cdm = N_ap;
if (N_ap == 4 && ((K_TC == 2 && srs_pdu->cyclic_shift >= 4) || (K_TC == 4 && srs_pdu->cyclic_shift >= 6))) {
......
......@@ -80,7 +80,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
const uint8_t N_ap = 1<<srs_pdu->num_ant_ports;
const uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols;
const uint8_t K_TC = 2 << srs_pdu->comb_size;
const uint16_t M_sc_b_SRS = srs_bandwidth_config[srs_pdu->config_index][srs_pdu->bandwidth_index][0] * NR_NB_SC_PER_RB/K_TC;
const uint16_t M_sc_b_SRS = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index) * NR_NB_SC_PER_RB / K_TC;
int32_t *rx_signal;
bool no_srs_signal = true;
......
......@@ -110,17 +110,17 @@ uint16_t compute_F_b(frame_t frame_number,
uint16_t product_N_b = 1;
for (unsigned int b_prime = b_hop; b_prime < B_SRS; b_prime++) {
if (b_prime != b_hop) {
product_N_b *= srs_bandwidth_config[C_SRS][b_prime][1];
product_N_b *= get_N_b_srs(C_SRS, b_prime);
}
}
uint16_t F_b = 0;
uint8_t N_b = srs_bandwidth_config[C_SRS][b][1];
uint8_t N_b = get_N_b_srs(C_SRS, b);
if (N_b & 1) { // Nb odd
F_b = (N_b/2)*(n_SRS/product_N_b);
} else { // Nb even
uint16_t product_N_b_B_SRS = product_N_b;
product_N_b_B_SRS *= srs_bandwidth_config[C_SRS][B_SRS][1]; /* product for b_hop to b */
product_N_b_B_SRS *= get_N_b_srs(C_SRS, B_SRS); /* product for b_hop to b */
F_b = (N_b/2)*((n_SRS%product_N_b_B_SRS)/product_N_b) + ((n_SRS%product_N_b_B_SRS)/2*product_N_b);
}
......@@ -142,8 +142,8 @@ uint16_t compute_n_b(frame_t frame_number,
uint8_t l_line,
uint8_t b) {
uint8_t N_b = srs_bandwidth_config[C_SRS][b][1];
uint16_t m_SRS_b = srs_bandwidth_config[C_SRS][B_SRS][0];
uint8_t N_b = get_N_b_srs(C_SRS, b);
uint16_t m_SRS_b = get_m_srs(C_SRS, B_SRS);
uint16_t n_b = 0;
if (b_hop >= B_SRS) {
......@@ -211,7 +211,7 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu,
uint8_t N_symb_SRS = 1<<srs_config_pdu->num_symbols; // Number of consecutive OFDM symbols
uint8_t l0 = frame_parms->symbols_per_slot - 1 - l_offset; // Starting symbol position in the time domain
uint8_t n_SRS_cs_max = srs_max_number_cs[srs_config_pdu->comb_size];
uint16_t m_SRS_b = srs_bandwidth_config[C_SRS][B_SRS][0]; // Number of resource blocks
uint16_t m_SRS_b = get_m_srs(C_SRS, B_SRS); // Number of resource blocks
uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB/K_TC; // Length of the SRS sequence
#ifdef SRS_DEBUG
......@@ -273,7 +273,7 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu,
}
uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_config_pdu->bwp_start*NR_NB_SC_PER_RB;
double sqrt_N_ap = sqrt(N_ap);
uint16_t n_b[B_SRS_NUMBER];
uint16_t n_b[B_SRS + 1];
// Find index of table which is for this SRS length
uint16_t M_sc_b_SRS_index = 0;
......
......@@ -35,83 +35,6 @@
#include "PHY/defs_nr_UE.h"
/************** DEFINE ********************************************/
#define C_SRS_NUMBER (64)
#define B_SRS_NUMBER (4)
/************** VARIABLES *****************************************/
/* TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration */
static const unsigned short srs_bandwidth_config[C_SRS_NUMBER][B_SRS_NUMBER][2] = {
/* B_SRS = 0 B_SRS = 1 B_SRS = 2 B_SRS = 3 */
/* C SRS m_srs0 N_0 m_srs1 N_1 m_srs2 N_2 m_srs3 N_3 */
/* 0 */ {{4, 1}, {4, 1}, {4, 1}, {4, 1}},
/* 1 */ {{8, 1}, {4, 2}, {4, 1}, {4, 1}},
/* 2 */ {{12, 1}, {4, 3}, {4, 1}, {4, 1}},
/* 3 */ {{16, 1}, {4, 4}, {4, 1}, {4, 1}},
/* 4 */ {{16, 1}, {8, 2}, {4, 2}, {4, 1}},
/* 5 */ {{20, 1}, {4, 5}, {4, 1}, {4, 1}},
/* 6 */ {{24, 1}, {4, 6}, {4, 1}, {4, 1}},
/* 7 */ {{24, 1}, {12, 2}, {4, 3}, {4, 1}},
/* 8 */ {{28, 1}, {4, 7}, {4, 1}, {4, 1}},
/* 9 */ {{32, 1}, {16, 2}, {8, 2}, {4, 2}},
/* 10 */ {{36, 1}, {12, 3}, {4, 3}, {4, 1}},
/* 11 */ {{40, 1}, {20, 2}, {4, 5}, {4, 1}},
/* 12 */ {{48, 1}, {16, 3}, {8, 2}, {4, 2}},
/* 13 */ {{48, 1}, {24, 2}, {12, 2}, {4, 3}},
/* 14 */ {{52, 1}, {4, 13}, {4, 1}, {4, 1}},
/* 15 */ {{56, 1}, {28, 2}, {4, 7}, {4, 1}},
/* 16 */ {{60, 1}, {20, 3}, {4, 5}, {4, 1}},
/* 17 */ {{64, 1}, {32, 2}, {16, 2}, {4, 4}},
/* 18 */ {{72, 1}, {24, 3}, {12, 2}, {4, 3}},
/* 19 */ {{72, 1}, {36, 2}, {12, 3}, {4, 3}},
/* 20 */ {{76, 1}, {4, 19}, {4, 1}, {4, 1}},
/* 21 */ {{80, 1}, {40, 2}, {20, 2}, {4, 5}},
/* 22 */ {{88, 1}, {44, 2}, {4, 11}, {4, 1}},
/* 23 */ {{96, 1}, {32, 3}, {16, 2}, {4, 4}},
/* 24 */ {{96, 1}, {48, 2}, {24, 2}, {4, 6}},
/* 25 */ {{104, 1}, {52, 2}, {4, 13}, {4, 1}},
/* 26 */ {{112, 1}, {56, 2}, {28, 2}, {4, 7}},
/* 27 */ {{120, 1}, {60, 2}, {20, 3}, {4, 5}},
/* 28 */ {{120, 1}, {40, 3}, {8, 5}, {4, 2}},
/* 29 */ {{120, 1}, {24, 5}, {12, 2}, {4, 3}},
/* 30 */ {{128, 1}, {64, 2}, {32, 2}, {4, 8}},
/* 31 */ {{128, 1}, {64, 2}, {16, 4}, {4, 4}},
/* 32 */ {{128, 1}, {16, 8}, {8, 2}, {4, 2}},
/* 33 */ {{132, 1}, {44, 3}, {4, 11}, {4, 1}},
/* 34 */ {{136, 1}, {68, 2}, {4, 17}, {4, 1}},
/* 35 */ {{144, 1}, {72, 2}, {36, 2}, {4, 9}},
/* 36 */ {{144, 1}, {48, 3}, {24, 2}, {12, 2}},
/* 37 */ {{144, 1}, {48, 3}, {16, 3}, {4, 4}},
/* 38 */ {{144, 1}, {16, 9}, {8, 2}, {4, 2}},
/* 39 */ {{152, 1}, {76, 2}, {4, 19}, {4, 1}},
/* 40 */ {{160, 1}, {80, 2}, {40, 2}, {4, 10}},
/* 41 */ {{160, 1}, {80, 2}, {20, 4}, {4, 5}},
/* 42 */ {{160, 1}, {32, 5}, {16, 2}, {4, 4}},
/* 43 */ {{168, 1}, {84, 2}, {28, 3}, {4, 7}},
/* 44 */ {{176, 1}, {88, 2}, {44, 2}, {4, 11}},
/* 45 */ {{184, 1}, {92, 2}, {4, 23}, {4, 1}},
/* 46 */ {{192, 1}, {96, 2}, {48, 2}, {4, 12}},
/* 47 */ {{192, 1}, {96, 2}, {24, 4}, {4, 6}},
/* 48 */ {{192, 1}, {64, 3}, {16, 4}, {4, 4}},
/* 49 */ {{192, 1}, {24, 8}, {8, 3}, {4, 2}},
/* 50 */ {{208, 1}, {104, 2}, {52, 2}, {4, 13}},
/* 51 */ {{216, 1}, {108, 2}, {36, 3}, {4, 9}},
/* 52 */ {{224, 1}, {112, 2}, {56, 2}, {4, 14}},
/* 53 */ {{240, 1}, {120, 2}, {60, 2}, {4, 15}},
/* 54 */ {{240, 1}, {80, 3}, {20, 4}, {4, 5}},
/* 55 */ {{240, 1}, {48, 5}, {16, 3}, {8, 2}},
/* 56 */ {{240, 1}, {24, 10}, {12, 2}, {4, 3}},
/* 57 */ {{256, 1}, {128, 2}, {64, 2}, {4, 16}},
/* 58 */ {{256, 1}, {128, 2}, {32, 4}, {4, 8}},
/* 59 */ {{256, 1}, {16, 16}, {8, 2}, {4, 2}},
/* 60 */ {{264, 1}, {132, 2}, {44, 3}, {4, 11}},
/* 61 */ {{272, 1}, {136, 2}, {68, 2}, {4, 17}},
/* 62 */ {{272, 1}, {68, 4}, {4, 17}, {4, 1}},
/* 63 */ {{272, 1}, {16, 17}, {8, 2}, {4, 2}},
};
#define SRS_PERIODICITY (17)
static const uint16_t srs_periodicity[SRS_PERIODICITY] = {1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560};
......
......@@ -577,6 +577,9 @@ typedef struct NR_UE_UL_BWP {
int channel_bandwidth;
// Minimum transmission power according to 38.101 6.3.1
float P_CMIN;
// SRS power control adjustment state
int h_b_f_c;
bool srs_power_control_initialized;
} NR_UE_UL_BWP_t;
// non-BWP serving cell configuration
......
......@@ -1280,7 +1280,7 @@ static void handle_aperiodic_srs_type(struct NR_SRS_ResourceSet__resourceType__a
struct NR_SRS_ResourceSet__resourceType__aperiodic__ext1__aperiodicSRS_ResourceTriggerList);
}
static void setup_srsresourceset(NR_SRS_ResourceSet_t *target, NR_SRS_ResourceSet_t *source)
static void setup_srsresourceset(NR_UE_UL_BWP_t *bwp, NR_SRS_ResourceSet_t *target, NR_SRS_ResourceSet_t *source)
{
target->srs_ResourceSetId = source->srs_ResourceSetId;
if (source->srs_ResourceIdList)
......@@ -1311,15 +1311,20 @@ static void setup_srsresourceset(NR_SRS_ResourceSet_t *target, NR_SRS_ResourceSe
}
}
target->usage = source->usage;
if (source->alpha) {
bwp->h_b_f_c = 0;
}
UPDATE_IE(target->alpha, source->alpha, NR_Alpha_t);
if (source->p0)
if (source->p0) {
bwp->h_b_f_c = 0;
UPDATE_IE(target->p0, source->p0, long);
}
if (source->pathlossReferenceRS)
UPDATE_IE(target->pathlossReferenceRS, source->pathlossReferenceRS, struct NR_PathlossReferenceRS_Config);
UPDATE_IE(target->srs_PowerControlAdjustmentStates, source->srs_PowerControlAdjustmentStates, long);
}
static void setup_srsconfig(NR_SRS_Config_t *source, NR_SRS_Config_t *target)
static void setup_srsconfig(NR_UE_UL_BWP_t *bwp, NR_SRS_Config_t *source, NR_SRS_Config_t *target)
{
UPDATE_IE(target->tpc_Accumulation, source->tpc_Accumulation, long);
// SRS-Resource
......@@ -1337,14 +1342,25 @@ static void setup_srsconfig(NR_SRS_Config_t *source, NR_SRS_Config_t *target)
srs_ResourceId);
}
// SRS-ResourceSet
if (source->srs_ResourceSetToAddModList) {
struct NR_SRS_Config__srs_ResourceSetToAddModList *source_srs_list = source->srs_ResourceSetToAddModList;
if (source_srs_list) {
if (!target->srs_ResourceSetToAddModList)
target->srs_ResourceSetToAddModList = calloc(1, sizeof(*target->srs_ResourceSetToAddModList));
ADDMOD_IE_FROMLIST_WFUNCTION(source->srs_ResourceSetToAddModList,
target->srs_ResourceSetToAddModList,
srs_ResourceSetId,
NR_SRS_ResourceSet_t,
setup_srsresourceset);
struct NR_SRS_Config__srs_ResourceSetToAddModList *target_srs_list = target->srs_ResourceSetToAddModList;
for (int i = 0; i < source_srs_list->list.count; i++) {
long srs_resource_id = source_srs_list->list.array[i]->srs_ResourceSetId;
int j;
for (j = 0; j < target_srs_list->list.count; j++) {
if (srs_resource_id == target_srs_list->list.array[j]->srs_ResourceSetId)
break;
}
if (j == target_srs_list->list.count) {
NR_SRS_ResourceSet_t *new = calloc(1, sizeof(*new));
ASN_SEQUENCE_ADD(&target_srs_list->list, new);
}
setup_srsresourceset(bwp, target_srs_list->list.array[j], source_srs_list->list.array[i]);
}
}
if (source->srs_ResourceSetToReleaseList) {
RELEASE_IE_FROMLIST(source->srs_ResourceSetToReleaseList,
......@@ -1459,7 +1475,7 @@ static void configure_dedicated_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP
if (ul_dedicated->srs_Config->present == NR_SetupRelease_SRS_Config_PR_setup) {
if (!bwp->srs_Config)
bwp->srs_Config = calloc(1, sizeof(*bwp->srs_Config));
setup_srsconfig(ul_dedicated->srs_Config->choice.setup, bwp->srs_Config);
setup_srsconfig(bwp, ul_dedicated->srs_Config->choice.setup, bwp->srs_Config);
}
}
AssertFatal(!ul_dedicated->configuredGrantConfig, "configuredGrantConfig not supported\n");
......@@ -1513,6 +1529,7 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up
bwp->channel_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index);
// Minumum transmission power depends on bandwidth, precalculate it here
bwp->P_CMIN = nr_get_Pcmin(bw_index);
bwp->srs_power_control_initialized = false;
if (bwp_id == 0) {
mac->sc_info.initial_ul_BWPSize = bwp->BWPSize;
mac->sc_info.initial_ul_BWPStart = bwp->BWPStart;
......
......@@ -609,6 +609,7 @@ typedef struct NR_UE_MAC_INST_s {
bool pucch_power_control_initialized;
int f_b_f_c;
bool pusch_power_control_initialized;
int delta_msg2;
} NR_UE_MAC_INST_t;
/*@}*/
......
......@@ -240,6 +240,12 @@ int get_pusch_tx_power_ue(
bool is_rar_tx_retx,
bool transform_precoding);
int get_srs_tx_power_ue(NR_UE_MAC_INST_t *mac,
NR_SRS_Resource_t *srs_resource,
NR_SRS_ResourceSet_t *srs_resource_set,
int delta_srs,
bool is_configured_for_pusch_on_current_bwp);
int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
int slot,
frame_t frame,
......
......@@ -578,6 +578,7 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup));
mac->f_b_f_c = DELTA_P_rampup + delta_pusch;
mac->pusch_power_control_initialized = true;
mac->delta_msg2 = delta_pusch;
} else {
if (!((pusch_power_without_f_b_f_c + mac->f_b_f_c >= P_CMAX && delta_pusch > 0) ||
(pusch_power_without_f_b_f_c + mac->f_b_f_c <= P_CMIN && delta_pusch < 0))) {
......@@ -595,3 +596,84 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
f_b_f_c);
return min(P_CMAX, P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF + f_b_f_c);
}
int get_srs_tx_power_ue(NR_UE_MAC_INST_t *mac,
NR_SRS_Resource_t *srs_resource,
NR_SRS_ResourceSet_t *srs_resource_set,
int delta_srs,
bool is_configured_for_pusch_on_current_bwp)
{
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
AssertFatal(current_UL_BWP, "Missing configuration: need UL_BWP to calculate SRS tx power\n");
AssertFatal(srs_resource_set->p0, "P0 mantatory present at configuration\n");
int P_0_SRS = *srs_resource_set->p0;
// alpha is optional, use same default as PUSCH
const float alpha_factor_table[8] = {0.0f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f};
float alpha = srs_resource_set->alpha ? alpha_factor_table[*srs_resource_set->alpha] : 1.0f;
int m_srs_component =
10 * log10(pow(2, current_UL_BWP->scs) * get_m_srs(srs_resource->freqHopping.c_SRS, srs_resource->freqHopping.b_SRS));
// The allowed MPR for SRS, PUCCH formats 0, 1, 3 and 4, and PRACH shall be as specified for QPSK modulated DFTs-OFDM of
// equivalent RB allocation. The allowed MPR for PUCCH format 2 shall be as specified for QPSK modulated CP-OFDM of equivalent RB
// allocation.
int P_CMAX = nr_get_Pcmax(mac->p_Max,
mac->nr_band,
mac->frame_type,
mac->frequency_range,
mac->current_UL_BWP->channel_bandwidth,
2,
false,
mac->current_UL_BWP->scs,
mac->current_UL_BWP->BWPSize,
true,
get_m_srs(srs_resource->freqHopping.c_SRS, srs_resource->freqHopping.b_SRS),
0); // TODO: Determine SRS start RB
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
int srs_power_without_h_b_f_c = P_0_SRS + alpha * pathloss + m_srs_component;
// Power adjustment state
int h_b_f_c = 0;
bool use_pusch_power_adjustment_state = srs_resource_set->srs_PowerControlAdjustmentStates == NULL;
if (is_configured_for_pusch_on_current_bwp && use_pusch_power_adjustment_state) {
// Case 1: Use PUSCH power control adjustment state
h_b_f_c = mac->f_b_f_c;
} else {
// Case 2: Separate power control adjustment state
AssertFatal(srs_resource_set->srs_PowerControlAdjustmentStates == NULL
|| *srs_resource_set->srs_PowerControlAdjustmentStates
!= NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_sameAsFci2,
"Two PUSCH power adjustment states not supported");
bool is_tpc_accumulation_provided = current_UL_BWP->srs_Config != NULL && current_UL_BWP->srs_Config->tpc_Accumulation != NULL;
bool separate_pc_adjustment_state = srs_resource_set->srs_PowerControlAdjustmentStates
&& *srs_resource_set->srs_PowerControlAdjustmentStates
== NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_separateClosedLoop;
if (!is_tpc_accumulation_provided && (!is_configured_for_pusch_on_current_bwp || separate_pc_adjustment_state)) {
if (!current_UL_BWP->srs_power_control_initialized) {
NR_PRACH_RESOURCES_t *prach_resources = &mac->ra.prach_resources;
float DELTA_P_rampup_requested =
(prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP;
float DELTA_P_rampup = P_CMAX - (P_0_SRS + m_srs_component + alpha * pathloss);
DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup));
current_UL_BWP->srs_power_control_initialized = true;
current_UL_BWP->h_b_f_c = DELTA_P_rampup + mac->delta_msg2;
} else {
int P_CMIN = mac->current_UL_BWP->P_CMIN;
if (!((srs_power_without_h_b_f_c + current_UL_BWP->h_b_f_c >= P_CMAX && delta_srs > 0)
|| (srs_power_without_h_b_f_c + current_UL_BWP->h_b_f_c <= P_CMIN && delta_srs < 0))) {
current_UL_BWP->h_b_f_c += delta_srs;
}
}
h_b_f_c = current_UL_BWP->h_b_f_c;
} else {
// Case 3: No accumulation
h_b_f_c = delta_srs;
}
}
return min(P_CMAX, srs_power_without_h_b_f_c + h_b_f_c);
}
......@@ -1058,7 +1058,8 @@ int configure_srs_pdu(NR_UE_MAC_INST_t *mac,
NR_SRS_Resource_t *srs_resource,
fapi_nr_ul_config_srs_pdu *srs_config_pdu,
int period,
int offset)
int offset,
NR_SRS_ResourceSet_t *srs_resource_set)
{
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
......@@ -1100,6 +1101,11 @@ int configure_srs_pdu(NR_UE_MAC_INST_t *mac,
srs_config_pdu->t_offset = offset;
}
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0; // DCI format 2_3 not implemented
srs_config_pdu->tx_power =
get_srs_tx_power_ue(mac, srs_resource, srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
#ifdef SRS_DEBUG
LOG_I(NR_MAC,"Frame = %i, slot = %i\n", frame, slot);
LOG_I(NR_MAC,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti);
......@@ -1142,10 +1148,11 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger
int slot_offset = 0;
NR_SRS_Resource_t *srs_resource = NULL;
NR_SRS_ResourceSet_t *srs_resource_set = NULL;
for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) {
// Find aperiodic resource set
NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
if(srs_resource_set->resourceType.present != NR_SRS_ResourceSet__resourceType_PR_aperiodic)
continue;
// the resource trigger need to match the DCI one
......@@ -1186,7 +1193,7 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, sched_frame, sched_slot, FAPI_NR_UL_CONFIG_TYPE_SRS);
if (!pdu)
return;
int ret = configure_srs_pdu(mac, srs_resource, &pdu->srs_config_pdu, 0, 0);
int ret = configure_srs_pdu(mac, srs_resource, &pdu->srs_config_pdu, 0, 0, srs_resource_set);
if (ret != 0)
remove_ul_config_last_item(pdu);
release_ul_config(pdu, false);
......@@ -1204,9 +1211,10 @@ static bool nr_ue_periodic_srs_scheduling(NR_UE_MAC_INST_t *mac, frame_t frame,
}
bool srs_scheduled = false;
NR_SRS_ResourceSet_t *srs_resource_set = NULL;
for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) {
// Find periodic resource set
NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
if(srs_resource_set->resourceType.present != NR_SRS_ResourceSet__resourceType_PR_periodic) {
continue;
}
......@@ -1237,7 +1245,7 @@ static bool nr_ue_periodic_srs_scheduling(NR_UE_MAC_INST_t *mac, frame_t frame,
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame, slot, FAPI_NR_UL_CONFIG_TYPE_SRS);
if (!pdu)
return false;
int ret = configure_srs_pdu(mac, srs_resource, &pdu->srs_config_pdu, period, offset);
int ret = configure_srs_pdu(mac, srs_resource, &pdu->srs_config_pdu, period, offset, srs_resource_set);
if (ret != 0)
remove_ul_config_last_item(pdu);
else
......
......@@ -594,6 +594,125 @@ TEST(test_pcmax, test_non_obvious_bwp_size)
nr_get_Pcmax(23, nr_band, frame_type, FR1, channel_bandwidth, 2, false, 1, N_RB_UL, false, 6, prb_start));
}
TEST(test_srs_power, use_pusch_power_adjustment_state)
{
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 = &current_UL_BWP;
NR_SRS_Resource_t srs_resource = {0};
NR_SRS_ResourceSet_t srs_resource_set = {0};
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0;
srs_resource_set.srs_PowerControlAdjustmentStates = NULL;
mac.nr_band = 78;
mac.f_b_f_c = 0;
mac.pusch_power_control_initialized = true;
long p0 = 0;
srs_resource_set.p0 = &p0;
int tx_power = get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
mac.f_b_f_c = 4;
int increased_tx_power =
get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
EXPECT_EQ(tx_power + mac.f_b_f_c, increased_tx_power);
}
TEST(test_srs_power, no_support_for_two_pusch_power_adjustment_states)
{
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 = &current_UL_BWP;
NR_SRS_Resource_t srs_resource = {0};
NR_SRS_ResourceSet_t srs_resource_set = {0};
long p0 = 0;
srs_resource_set.p0 = &p0;
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0;
long srs_PowerControlAdjustmentStates = NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_sameAsFci2;
srs_resource_set.srs_PowerControlAdjustmentStates = &srs_PowerControlAdjustmentStates;
mac.nr_band = 78;
mac.f_b_f_c = 0;
mac.pusch_power_control_initialized = true;
EXPECT_DEATH(get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp),
"Two PUSCH power adjustment states not supported");
}
TEST(test_srs_power, no_tpc_accumulation)
{
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 = &current_UL_BWP;
NR_SRS_Resource_t srs_resource = {0};
NR_SRS_ResourceSet_t srs_resource_set = {0};
long p0 = 0;
srs_resource_set.p0 = &p0;
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0;
long srs_PowerControlAdjustmentStates = NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_separateClosedLoop;
srs_resource_set.srs_PowerControlAdjustmentStates = &srs_PowerControlAdjustmentStates;
mac.nr_band = 78;
mac.f_b_f_c = 0;
mac.pusch_power_control_initialized = true;
NR_SRS_Config_t srs_Config = {0};
long tpc_Accumulation = 0;
srs_Config.tpc_Accumulation = &tpc_Accumulation;
current_UL_BWP.srs_Config = &srs_Config;
int tx_power = get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
delta_srs = 4;
int increased_tx_power =
get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
EXPECT_EQ(tx_power + delta_srs, increased_tx_power);
}
TEST(test_srs_power, tpc_accumulation)
{
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 = &current_UL_BWP;
NR_SRS_Resource_t srs_resource = {0};
NR_SRS_ResourceSet_t srs_resource_set = {0};
long p0 = 0;
srs_resource_set.p0 = &p0;
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0;
long srs_PowerControlAdjustmentStates = NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_separateClosedLoop;
srs_resource_set.srs_PowerControlAdjustmentStates = &srs_PowerControlAdjustmentStates;
mac.nr_band = 78;
mac.f_b_f_c = 0;
mac.pusch_power_control_initialized = true;
current_UL_BWP.srs_power_control_initialized = true;
NR_SRS_Config_t srs_Config = {0};
current_UL_BWP.srs_Config = &srs_Config;
int tx_power = get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
delta_srs = 4;
int increased_tx_power =
get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
EXPECT_EQ(tx_power + delta_srs, increased_tx_power);
int more_tx_power =
get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
EXPECT_EQ(tx_power + delta_srs * 2, more_tx_power);
}
int main(int argc, char** argv)
{
logInit();
......
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