diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index a5d6087856..140ed130a4 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -129,6 +129,8 @@ typedef struct { short rsrp_dBm; long arfcn; rlm_t radiolink_monitoring; // -1 no monitoring, 0 out_of_sync, 1 in_sync + // SINR value times 10 as reporting granularity is 0.5 + float sinr_dB; } fapi_nr_ssb_pdu_t; typedef struct { diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 9f8a463ec7..f4f0f7e50e 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -180,8 +180,10 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) AssertFatal( nb_connected_gNB <= NUMBER_OF_CONNECTED_gNB_MAX, "n_connected_gNB is too large" ); // init phy_vars_ue - for (int i = 0; i < fp->Lmax; i++) + for (int i = 0; i < fp->Lmax; i++) { ue->measurements.ssb_rsrp_dBm[i] = INT_MIN; + ue->measurements.ssb_sinr_dB[i] = INT_MIN; + } for (int i = 0; i < 4; i++) { ue->rx_gain_max[i] = 135; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 835876d4bf..da6fd31eb5 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -111,11 +111,11 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, uint32_t pdsch_est_size, int32_t dl_ch_estimates[][pdsch_est_size]); -int nr_ue_calculate_ssb_rsrp(const NR_DL_FRAME_PARMS *fp, - const UE_nr_rxtx_proc_t *proc, - const c16_t rxdataF[][fp->samples_per_slot_wCP], - int symbol_offset, - int ssb_start_subcarrier); +uint32_t nr_ue_calculate_ssb_rsrp(const NR_DL_FRAME_PARMS *fp, + const UE_nr_rxtx_proc_t *proc, + const c16_t rxdataF[][fp->samples_per_slot_wCP], + int symbol_offset, + int ssb_start_subcarrier); void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, uint8_t gNB_index, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 0fb94f93f3..b6aeba7f76 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -172,11 +172,11 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, // This function calculates: // - SS reference signal received digital power in dB/RE -int nr_ue_calculate_ssb_rsrp(const NR_DL_FRAME_PARMS *fp, - const UE_nr_rxtx_proc_t *proc, - const c16_t rxdataF[][fp->samples_per_slot_wCP], - int symbol_offset, - int ssb_start_subcarrier) +uint32_t nr_ue_calculate_ssb_rsrp(const NR_DL_FRAME_PARMS *fp, + const UE_nr_rxtx_proc_t *proc, + const c16_t rxdataF[][fp->samples_per_slot_wCP], + int symbol_offset, + int ssb_start_subcarrier) { int k_start = 56; int k_end = 183; @@ -209,9 +209,7 @@ int nr_ue_calculate_ssb_rsrp(const NR_DL_FRAME_PARMS *fp, LOG_D(PHY, "In %s: RSRP/nb_re: %d nb_re :%d\n", __FUNCTION__, rsrp, nb_re); - int rsrp_db_per_re = 10 * log10(rsrp); - - return rsrp_db_per_re; + return rsrp; } // This function implements: @@ -234,7 +232,8 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, if (fp->half_frame_bit) symbol_offset += (fp->slots_per_frame >> 1) * fp->symbols_per_slot; - int rsrp_db_per_re = nr_ue_calculate_ssb_rsrp(fp, proc, rxdataF, symbol_offset, fp->ssb_start_subcarrier); + uint32_t rsrp_avg = nr_ue_calculate_ssb_rsrp(fp, proc, rxdataF, symbol_offset, fp->ssb_start_subcarrier); + float rsrp_db_per_re = 10 * log10(rsrp_avg); openair0_config_t *cfg0 = &openair0_cfg[0]; @@ -242,12 +241,18 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, - ((int)cfg0->rx_gain[0] - (int)cfg0->rx_gain_offset[0]) - dB_fixed(fp->ofdm_symbol_size); + // to obtain non-integer dB value with a resoluion of 0.5dB + uint32_t signal_pwr = rsrp_avg > ue->measurements.n0_power_avg ? rsrp_avg - ue->measurements.n0_power_avg : 0; + int SNRtimes10 = dB_fixed_x10(signal_pwr) - dB_fixed_x10(ue->measurements.n0_power_avg); + ue->measurements.ssb_sinr_dB[ssb_index] = SNRtimes10 / 10.0; + LOG_D(PHY, - "[UE %d] ssb %d SS-RSRP: %d dBm/RE (%d dB/RE)\n", + "[UE %d] ssb %d SS-RSRP: %d dBm/RE (%f dB/RE), SS-SINR: %f dB\n", ue->Mod_id, ssb_index, ue->measurements.ssb_rsrp_dBm[ssb_index], - rsrp_db_per_re); + rsrp_db_per_re, + ue->measurements.ssb_sinr_dB[ssb_index]); } // This function computes the received noise power diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index dc634584f6..422e8d6484 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -285,7 +285,8 @@ void nr_scan_ssb(void *arg) &ssbInfo->pbchResult, rxdataF); // start pbch detection at first symbol after pss if (ssbInfo->syncRes.cell_detected) { - int rsrp_db_per_re = nr_ue_calculate_ssb_rsrp(ssbInfo->fp, ssbInfo->proc, rxdataF, 0, ssbInfo->gscnInfo.ssbFirstSC); + uint32_t rsrp_avg = nr_ue_calculate_ssb_rsrp(ssbInfo->fp, ssbInfo->proc, rxdataF, 0, ssbInfo->gscnInfo.ssbFirstSC); + int rsrp_db_per_re = 10 * log10(rsrp_avg); ssbInfo->adjust_rxgain = TARGET_RX_POWER - rsrp_db_per_re; LOG_I(PHY, "pbch rx ok. rsrp:%d dB/RE, adjust_rxgain:%d dB\n", rsrp_db_per_re, ssbInfo->adjust_rxgain); } diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index a617784e64..f724861e2d 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -140,6 +140,7 @@ typedef struct { uint32_t rsrp[7]; short rsrp_dBm[7]; int ssb_rsrp_dBm[64]; + float ssb_sinr_dB[64]; // common measurements //! estimated noise power (linear) unsigned int n0_power[NB_ANTENNAS_RX]; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index d427e9721c..64ee69679a 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -175,6 +175,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, rx->ssb_pdu.cell_id = frame_parms->Nid_cell; rx->ssb_pdu.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; rx->ssb_pdu.rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index]; + rx->ssb_pdu.sinr_dB = ue->measurements.ssb_sinr_dB[frame_parms->ssb_index]; rx->ssb_pdu.arfcn = get_ssb_arfcn(frame_parms); rx->ssb_pdu.radiolink_monitoring = RLM_in_sync; // TODO to be removed from here rx->ssb_pdu.decoded_pdu = true; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 3241235bd3..526e68892c 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -417,6 +417,7 @@ typedef struct { uint32_t ssb_index; /// SSB RSRP in dBm short ssb_rsrp_dBm; + float_t ssb_sinr_dB; } NR_SSB_meas_t; typedef enum ta_type { diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index dfb0a0d942..0d0829181e 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1133,10 +1133,11 @@ static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, return nr_ue_process_dci_indication_pdu(mac, frame, slot, dci); } -static void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm) +static void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm, float_t sinr_dB) { mac->ssb_measurements.ssb_index = ssb_index; mac->ssb_measurements.ssb_rsrp_dBm = rsrp_dbm; + mac->ssb_measurements.ssb_sinr_dB = sinr_dB; } // L2 Abstraction Layer @@ -1272,7 +1273,8 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio if(rx_indication_body.ssb_pdu.decoded_pdu) { handle_ssb_meas(mac, rx_indication_body.ssb_pdu.ssb_index, - rx_indication_body.ssb_pdu.rsrp_dBm); + rx_indication_body.ssb_pdu.rsrp_dBm, + rx_indication_body.ssb_pdu.sinr_dB); ret_mask |= (handle_bcch_bch(mac, dl_info->cc_id, dl_info->gNB_index,