diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index cf69f7cd71..31461f68eb 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -197,6 +197,11 @@ In the `MACRLCs` section of the gNB/DU configuration file: beams, depending on hardware switching performance * `beams_per_period` (default 1): set of beams that can be simultaneously allocated in a period (`beam_duration`) +* `pusch_RSSI_Threshold`: Value between -1280 and 0 which maps to range + from -128.0 dBm/dBFS to 0.0 dBm/dBFS. This limits PUSCH TPC commands in + case RSSI reaches the threshold and prevents ADC railing. Unit depends on + RSSI reporting config. +* `pucch_RSSI_Threshold`: Same as above but for PUCCH In the `gNBs` section of the gNB/DU configuration file: some of the parameters affect RRC configuration (CellGroupConfig) of a UE, and are therefore listed diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index b9b62ec39f..a1d860c86c 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -75,6 +75,8 @@ #define CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING "set_analog_beamforming" #define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration" #define CONFIG_STRING_MACRLC_BEAMS_PERIOD "beams_per_period" +#define CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD "pusch_RSSI_Threshold" +#define CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD "pucch_RSSI_Threshold" #define HLP_MACRLC_UL_PRBBLACK "SNR threshold to decide whether a PRB will be blacklisted or not" #define HLP_MACRLC_DL_BLER_UP "Upper threshold of BLER to decrease DL MCS" @@ -91,6 +93,8 @@ #define HLP_MACRLC_AB "Flag to enable analog beamforming" #define HLP_MACRLC_BEAM_DURATION "number of consecutive slots for a given set of beams" #define HLP_MACRLC_BEAMS_PERIOD "set of beams that can be simultaneously allocated in a period" +#define HLP_MACRLC_PUSCH_RSSI_THRESHOLD "Limits PUSCH TPC commands based on RSSI to prevent ADC railing. Value range [-1280, 0], unit 0.1 dBm/dBFS" +#define HLP_MACRLC_PUCCH_RSSI_THRESHOLD "Limits PUCCH TPC commands based on RSSI to prevent ADC railing. Value range [-1280, 0], unit 0.1 dBm/dBFS" /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* MacRLC configuration parameters */ @@ -136,6 +140,10 @@ {CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING, HLP_MACRLC_AB, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_BEAM_DURATION, HLP_MACRLC_BEAM_DURATION, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_BEAMS_PERIOD, HLP_MACRLC_BEAMS_PERIOD, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \ + {CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD, HLP_MACRLC_PUSCH_RSSI_THRESHOLD, \ + 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ + {CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD, HLP_MACRLC_PUCCH_RSSI_THRESHOLD, \ + 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ } // clang-format off @@ -177,6 +185,8 @@ #define MACRLC_ANALOG_BEAMFORMING_IDX 35 #define MACRLC_ANALOG_BEAM_DURATION_IDX 36 #define MACRLC_ANALOG_BEAMS_PERIOD_IDX 37 +#define MACRLC_PUSCH_RSSI_THRES_IDX 38 +#define MACRLC_PUCCH_RSSI_THRES_IDX 39 #define MACRLCPARAMS_CHECK { \ { .s5 = { NULL } }, \ @@ -217,6 +227,8 @@ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ + { .s2 = { config_check_intrange, {-1280, 0}} }, /* PUSCH RSSI threshold range */ \ + { .s2 = { config_check_intrange, {-1280, 0}} }, /* PUCCH RSSI threshold range */ \ } /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 3b8981353d..baeca1aa72 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1417,6 +1417,8 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) for (j = 0; j < RC.nb_nr_macrlc_inst; j++) { RC.nb_nr_mac_CC[j] = *(MacRLC_ParamList.paramarray[j][MACRLC_CC_IDX].iptr); RC.nrmac[j]->pusch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHTARGETSNRX10_IDX].iptr); + RC.nrmac[j]->pusch_rssi_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCH_RSSI_THRES_IDX].iptr); + RC.nrmac[j]->pucch_rssi_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCH_RSSI_THRES_IDX].iptr); RC.nrmac[j]->pucch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHTARGETSNRX10_IDX].iptr); RC.nrmac[j]->ul_prbblack_SNR_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX].iptr); RC.nrmac[j]->pucch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHFAILURETHRES_IDX].iptr); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a84c156a82..708337640c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2693,6 +2693,44 @@ uint8_t nr_get_tpc(int target, uint8_t cqi, int incr, int tx_power) return 1; // no change } +/** + * @brief Limits the power control commands (TPC) in NR by checking the RSSI threshold. + * + * This function evaluates the received signal strength indicator (RSSI) and adjusts the + * transmit power control (TPC) commands accordingly to ensure they remain within acceptable + * limits. It helps in maintaining the signal quality and preventing excessive power usage. + * + * @param rssi The received signal strength indicator value, as defined in FAPI specifications. + * @param tpc The transmit power control command to be limited. + * @param rssi_threshold RSSI threshold in 0.1 dBm/dBFS, range -1280 to 0 + * @return The adjusted TPC command after applying the RSSI threshold check. + */ +uint8_t nr_limit_tpc(int tpc, int rssi, int rssi_threshold) +{ + if (rssi == 0xFFFF) { + // RSSI not available, keep tpc + return tpc; + } + // Convert RSSI threshold to FAPI scale + const int fapi_rssi_0dBm_or_0dBFS = 1280; + int rssi_fapi_threshold = fapi_rssi_0dBm_or_0dBFS + rssi_threshold; + // Further limit TPC if above or near RSSI threshold + int tpc_to_db[] = {-1, 0, 1, 3}; + if (rssi > rssi_fapi_threshold) { + // RSSI above theshold, reduce power + return 0; + } else if (rssi + tpc_to_db[tpc] * 10 > rssi_fapi_threshold) { + // Cannot apply required TPC, check 1 dB increment + if (rssi + 10 > rssi_fapi_threshold) { + // Still cannot apply required TPC, keep power + return 1; + } else { + // Can apply 1dB increment, but 3 was requested + return 2; + } + } + return tpc; +} int get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config, nr_dci_format_t dci_format, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 64def07a9e..378565123b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -761,6 +761,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01) { gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; + int rssi_threshold = nrmac->pucch_rssi_threshold; NR_SCHED_LOCK(&nrmac->sched_lock); NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti); if (!UE) { @@ -796,6 +797,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, sched_ctrl->tpc1 = nr_get_tpc(nrmac->pucch_target_snrx10, uci_01->ul_cqi, 30, 0); } else sched_ctrl->tpc1 = 1; + sched_ctrl->tpc1 = nr_limit_tpc(sched_ctrl->tpc1, uci_01->rssi, rssi_threshold); } // check scheduling request result, confidence_level == 0 is good @@ -817,6 +819,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, { gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; NR_SCHED_LOCK(&nrmac->sched_lock); + int rssi_threshold = nrmac->pucch_rssi_threshold; NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, uci_234->rnti); if (!UE) { @@ -837,6 +840,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, if (uci_234->ul_cqi != 0xff) { sched_ctrl->pucch_snrx10 = uci_234->ul_cqi * 5 - 640; sched_ctrl->tpc1 = nr_get_tpc(nrmac->pucch_target_snrx10, uci_234->ul_cqi, 30, 0); + sched_ctrl->tpc1 = nr_limit_tpc(sched_ctrl->tpc1, uci_234->rssi, rssi_threshold); } // TODO: handle SR diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index f6005a6191..afc8c7e6d9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -708,6 +708,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, const int current_rnti = rntiP; LOG_D(NR_MAC, "rx_sdu for rnti %04x\n", current_rnti); const int target_snrx10 = gNB_mac->pusch_target_snrx10; + const int rssi_threshold = gNB_mac->pusch_rssi_threshold; const int pusch_failure_thres = gNB_mac->pusch_failure_thres; NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti); @@ -749,6 +750,8 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, if (UE_scheduling_control->ph < 0 && UE_scheduling_control->tpc0 > 1) UE_scheduling_control->tpc0 = 1; + UE_scheduling_control->tpc0 = nr_limit_tpc(UE_scheduling_control->tpc0, rssi, rssi_threshold); + if (timing_advance != 0xffff) UE_scheduling_control->ta_update = timing_advance; UE_scheduling_control->raw_rssi = rssi; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 57548cd5ce..d8c876439b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -295,6 +295,7 @@ NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, const int Layers); uint8_t nr_get_tpc(int target, uint8_t cqi, int incr, int tx_power); +uint8_t nr_limit_tpc(int tpc, int rssi, int rssi_threshold); int get_spf(nfapi_nr_config_request_scf_t *cfg); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index df03e59eca..c94f64dfef 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -833,8 +833,12 @@ typedef struct gNB_MAC_INST_s { pthread_t stats_thread; /// Pusch target SNR int pusch_target_snrx10; + /// RSSI threshold for power control. Limits power control commands when RSSI reaches threshold. + int pusch_rssi_threshold; /// Pucch target SNR int pucch_target_snrx10; + /// RSSI threshold for PUCCH power control. Limits power control commands when RSSI reaches threshold. + int pucch_rssi_threshold; /// SNR threshold needed to put or not a PRB in the black list int ul_prbblack_SNR_threshold; /// PUCCH Failure threshold (compared to consecutive PUCCH DTX)