Merge remote-tracking branch 'origin/NR_SSB_SINR' into integration_2025_w16 (!3326)

Enable SSB-SINR based CSI reporting

3GPP 38.331 release 16 specifies that If the field reportQuantity-r16 is present,
UE shall ignore reportQuantity (without suffix). reportQuantity-r16 configures
SSB based SINR as the reporting quantity.

set do_SINR = 1; in gNB params part of the config file to enable SSB based SINR
reporting.
This commit is contained in:
Jaroslava Fiedlerova
2025-04-17 23:01:08 +02:00
18 changed files with 439 additions and 149 deletions
+14
View File
@@ -250,6 +250,8 @@ configuration](../RRC/rrc-usage.md) as well for SIB configuration.
* `do_CSIRS` (default 0): flag whether to use channel-state information
reference signal (CSI-RS)
* `do_SRS` (default 0): flag whether to use sounding reference signal (SRS)
* `do_SINR` (default 0): flag whether to enable CSI reporting of SSB-SINR (introduced in rel16)
Default setting of CSI reporting quantity is SSB-RSRP.
* `min_rxtxtime` (default 2): minimum feedback time for UE to respond to
transmissions (k1 and k2 in 3GPP spec)
* `ul_prbblacklist`: PRBs that should not be used for UL scheduling. Cf with
@@ -272,6 +274,18 @@ configuration](../RRC/rrc-usage.md) as well for SIB configuration.
- `du_sibs` (default `[]`): list of SIBs to transmit in the cell. Currently,
SIB19 (for NTN) is supported.
| DL MIMO |`do_CSIRS`|`do_SINR`| CSI report Quantity |
| ---------------------------- | -------- | ------- | --------------------------------------------------|
| OFF (pdsch_AntennaPorts = 1) | 0 | 0 | SSB-RSRP |
| OFF (pdsch_AntennaPorts = 1) | 0 | 1 | SSB-SINR |
| OFF (pdsch_AntennaPorts = 1) | 1 | 0 | CSI-Reference signal RSRP |
| OFF (pdsch_AntennaPorts = 1) | 1 | 1 | CSI-Reference signal SINR (not supported yet) |
| ON (pdsch_AntennaPorts > 1) | 1 | 0 | cri-RI-PMI-CQI |
DL-MIMO is configured using following parameters:
`pdsch_AntennaPorts_XP` , `pdsch_AntennaPorts_N1` , `pdsch_AntennaPorts_N2`, `maxMIMO_layers`
(see also [`RUNMODEM.md`](../RUNMODEM.md))
## ServingCellConfigCommon parameters
The `gNBs` configuration section has a big structure `servingCellConfigCommon`
@@ -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 {
+3 -1
View File
@@ -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;
@@ -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,
@@ -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
@@ -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);
}
+1
View File
@@ -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];
@@ -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;
+4 -1
View File
@@ -858,6 +858,7 @@ void RCconfig_verify(configmodule_interface_t *cfg, ngran_node_t node_type)
verify_gnb_param_notset(gnbp, GNB_DISABLE_HARQ_IDX, GNB_CONFIG_STRING_DISABLE_HARQ);
verify_gnb_param_notset(gnbp, GNB_NUM_DL_HARQ_IDX, GNB_CONFIG_STRING_NUM_DL_HARQPROCESSES);
verify_gnb_param_notset(gnbp, GNB_NUM_UL_HARQ_IDX, GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES);
verify_gnb_param_notset(gnbp, GNB_DO_SINR_IDX, GNB_CONFIG_STRING_DOSINR);
// check for some general sections
verify_section_notset(cfg, NULL, CONFIG_STRING_L1_LIST);
@@ -1500,6 +1501,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
LOG_I(GNB_APP, "SIB1 TDA %d\n", config.sib1_tda);
config.do_CSIRS = *GNBParamList.paramarray[0][GNB_DO_CSIRS_IDX].iptr;
config.do_SRS = *GNBParamList.paramarray[0][GNB_DO_SRS_IDX].iptr;
config.do_SINR = *GNBParamList.paramarray[0][GNB_DO_SINR_IDX].iptr;
config.force_256qam_off = *GNBParamList.paramarray[0][GNB_FORCE256QAMOFF_IDX].iptr;
config.force_UL256qam_off = *GNBParamList.paramarray[0][GNB_FORCEUL256QAMOFF_IDX].iptr;
config.use_deltaMCS = *GNBParamList.paramarray[0][GNB_USE_DELTA_MCS_IDX].iptr != 0;
@@ -1510,9 +1512,10 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
if (config.disable_harq)
LOG_W(GNB_APP, "\"disable_harq\" is a REL17 feature and is incompatible with REL15 and REL16 UEs!\n");
LOG_I(GNB_APP,
"CSI-RS %d, SRS %d, 256 QAM %s, delta_MCS %s, maxMIMO_Layers %d, HARQ feedback %s, num DLHARQ:%d, num ULHARQ:%d\n",
"CSI-RS %d, SRS %d, SINR:%d, 256 QAM %s, delta_MCS %s, maxMIMO_Layers %d, HARQ feedback %s, num DLHARQ:%d, num ULHARQ:%d\n",
config.do_CSIRS,
config.do_SRS,
config.do_SINR,
config.force_256qam_off ? "force off" : "may be on",
config.use_deltaMCS ? "on" : "off",
config.maxMIMO_layers,
+5
View File
@@ -141,6 +141,7 @@ typedef enum {
#define GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST "uess_agg_levels"
#define GNB_CONFIG_STRING_CU_SIB_LIST "cu_sibs"
#define GNB_CONFIG_STRING_DU_SIB_LIST "du_sibs"
#define GNB_CONFIG_STRING_DOSINR "do_SINR"
#define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n"
#define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support"
@@ -154,6 +155,7 @@ typedef enum {
#define GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST "List of aggregation levels with number of candidates per level. Element 0 - aggregation level 1"
#define GNB_CONFIG_HLP_CU_SIBS "List of CU generated SIBs to be transmitted"
#define GNB_CONFIG_HLP_DU_SIBS "List of DU generated SIBs to be transmitted"
#define GNB_CONFIG_HLP_DOSINR "Enable CSI feedback using SINR measurements on SSB"
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* cell configuration parameters */
@@ -201,6 +203,7 @@ typedef enum {
GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST, 0, .iptr=NULL, .defintarrayval=NULL, TYPE_INTARRAY, 0}, \
{GNB_CONFIG_STRING_CU_SIB_LIST, GNB_CONFIG_HLP_CU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
{GNB_CONFIG_STRING_DU_SIB_LIST, GNB_CONFIG_HLP_DU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
{GNB_CONFIG_STRING_DOSINR, GNB_CONFIG_HLP_DOSINR, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
}
// clang-format on
@@ -244,6 +247,7 @@ typedef enum {
#define GNB_UESS_AGG_LEVEL_LIST_IDX 36
#define GNB_CU_SIBS_IDX 37
#define GNB_DU_SIBS_IDX 38
#define GNB_DO_SINR_IDX 39
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
#define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32}
@@ -289,6 +293,7 @@ typedef enum {
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
+5 -2
View File
@@ -517,7 +517,9 @@ typedef struct {
uint8_t cri_ssbri_bitlen;
uint8_t rsrp_bitlen;
uint8_t diff_rsrp_bitlen;
} L1_RSRP_bitlen_t;
uint8_t sinr_bitlen;
uint8_t diff_sinr_bitlen;
} L1_Meas_bitlen_t;
typedef struct{
uint8_t ri_restriction;
@@ -535,13 +537,14 @@ typedef struct{
typedef struct nr_csi_report {
NR_CSI_ReportConfigId_t reportConfigId;
NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type;
NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR reportQuantity_type_r16;
long periodicity;
uint16_t offset;
long **SSB_Index_list;
long **CSI_Index_list;
// uint8_t nb_of_nzp_csi_report;
uint8_t nb_of_csi_ssb_report;
L1_RSRP_bitlen_t CSI_report_bitlen;
L1_Meas_bitlen_t CSI_report_bitlen;
CSI_Meas_bitlen_t csi_meas_bitlen;
int codebook_mode;
int N1;
+68 -37
View File
@@ -4427,7 +4427,10 @@ static uint8_t number_of_bits_set(uint8_t buf)
return nb_of_bits_set;
}
static void compute_rsrp_bitlen(const NR_CSI_ReportConfig_t *csi_reportconfig, uint8_t nb_resources, nr_csi_report_t *csi_report)
static void compute_rsrp_or_sinr_bitlen(const NR_CSI_ReportConfig_t *csi_reportconfig,
uint8_t nb_resources,
nr_csi_report_t *csi_report,
bool is_RSRP_configured)
{
if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == csi_reportconfig->groupBasedBeamReporting.present) {
if (csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
@@ -4445,13 +4448,20 @@ static void compute_rsrp_bitlen(const NR_CSI_ReportConfig_t *csi_reportconfig, u
csi_report->CSI_report_bitlen.nb_ssbri_cri = 2;
if (nb_resources) {
csi_report->CSI_report_bitlen.cri_ssbri_bitlen =ceil(log2 (nb_resources));
csi_report->CSI_report_bitlen.rsrp_bitlen = 7; // From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
csi_report->CSI_report_bitlen.diff_rsrp_bitlen = 4; // From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
csi_report->CSI_report_bitlen.cri_ssbri_bitlen = ceil(log2 (nb_resources));
if (is_RSRP_configured) {
csi_report->CSI_report_bitlen.rsrp_bitlen = 7; // From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
csi_report->CSI_report_bitlen.diff_rsrp_bitlen = 4; // From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
} else {
csi_report->CSI_report_bitlen.sinr_bitlen = 7; // From spec 38.212 Table 6.3.1.1.2-6A: CRI, SSBRI, and SINR
csi_report->CSI_report_bitlen.diff_sinr_bitlen = 4; // From spec 38.212 Table 6.3.1.1.2-6A: CRI, SSBRI, and SINR
}
} else {
csi_report->CSI_report_bitlen.cri_ssbri_bitlen = 0;
csi_report->CSI_report_bitlen.rsrp_bitlen = 0;
csi_report->CSI_report_bitlen.diff_rsrp_bitlen = 0;
csi_report->CSI_report_bitlen.sinr_bitlen = 0;
csi_report->CSI_report_bitlen.diff_sinr_bitlen = 0;
}
}
@@ -4878,9 +4888,13 @@ void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report
reportQuantity_type = csi_reportconfig->reportQuantity.present;
csi_report->reportQuantity_type = reportQuantity_type;
csi_report->reportConfigId = csi_reportconfig->reportConfigId;
csi_report->reportQuantity_type_r16 = NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_NOTHING;
if (csi_reportconfig->ext2 != NULL && csi_reportconfig->ext2->reportQuantity_r16)
csi_report->reportQuantity_type_r16 = csi_reportconfig->ext2->reportQuantity_r16->present;
// setting the CSI or SSB index list
if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == csi_report->reportQuantity_type) {
if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == csi_report->reportQuantity_type
|| NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16 == csi_report->reportQuantity_type_r16) {
for (int csi_idx = 0; csi_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_idx++) {
if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceSetId ==
*(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){
@@ -4891,8 +4905,7 @@ void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report
break;
}
}
}
else {
} else {
if (resourceType == NR_CSI_ResourceConfig__resourceType_periodic) {
AssertFatal(csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList != NULL,
"Wrong settings! Report quantity requires CSI-RS but csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList is NULL\n");
@@ -4911,33 +4924,46 @@ void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report
}
LOG_D(NR_MAC,"nb_resources %d\n",nb_resources);
// computation of bit length depending on the report type
switch(reportQuantity_type){
case (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP):
compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP):
compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI):
csi_report->csi_meas_bitlen.cri_bitlen = ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI):
csi_report->csi_meas_bitlen.cri_bitlen = ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI):
csi_report->csi_meas_bitlen.cri_bitlen = ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_li_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
default:
AssertFatal(1==0,"Not yet supported CSI report quantity type");
if (csi_report->reportQuantity_type_r16 != NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_NOTHING) {
switch (csi_report->reportQuantity_type_r16) {
case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16:
compute_rsrp_or_sinr_bitlen(csi_reportconfig, nb_resources, csi_report, false);
break;
case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_cri_SINR_r16:
compute_rsrp_or_sinr_bitlen(csi_reportconfig, nb_resources, csi_report, false);
break;
default:
AssertFatal(1 == 0, "Not yet supported CSI report quantity type");
}
} else {
switch (reportQuantity_type) {
case (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP):
compute_rsrp_or_sinr_bitlen(csi_reportconfig, nb_resources, csi_report, true);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP):
compute_rsrp_or_sinr_bitlen(csi_reportconfig, nb_resources, csi_report, true);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI):
csi_report->csi_meas_bitlen.cri_bitlen = ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI):
csi_report->csi_meas_bitlen.cri_bitlen = ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI):
csi_report->csi_meas_bitlen.cri_bitlen = ceil(log2(nb_resources));
csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report);
compute_li_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report);
break;
default:
AssertFatal(1 == 0, "Not yet supported CSI report quantity type");
}
}
}
}
@@ -4946,11 +4972,16 @@ uint16_t nr_get_csi_bitlen(nr_csi_report_t *csi_report)
{
uint16_t csi_bitlen = 0;
uint16_t max_bitlen = 0;
L1_RSRP_bitlen_t *CSI_report_bitlen = NULL;
L1_Meas_bitlen_t *CSI_report_bitlen = NULL;
CSI_Meas_bitlen_t *csi_meas_bitlen = NULL;
if (csi_report->reportQuantity_type == NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP ||
csi_report->reportQuantity_type == NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP) {
if (csi_report->reportQuantity_type_r16 == NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16
|| csi_report->reportQuantity_type_r16 == NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_cri_SINR_r16) {
CSI_report_bitlen = &(csi_report->CSI_report_bitlen); // This might need to be moodif for Aperiodic CSI-RS measurements
csi_bitlen += ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) + CSI_report_bitlen->sinr_bitlen
+ (CSI_report_bitlen->diff_sinr_bitlen * (CSI_report_bitlen->nb_ssbri_cri - 1)));
} else if (csi_report->reportQuantity_type == NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP
|| csi_report->reportQuantity_type == NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP) {
CSI_report_bitlen = &(csi_report->CSI_report_bitlen); // This might need to be moodif for Aperiodic CSI-RS measurements
csi_bitlen += ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) +
CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen *
+1
View File
@@ -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 {
+138 -20
View File
@@ -2643,6 +2643,111 @@ int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCC
return num_csi;
}
// Referred - Table 10.1.16.1-1 in 38.133 V16.7.0.
static uint8_t get_sinr_index(float sinr)
{
int index = sinr * 2 + 47;
if (sinr >= 40)
index = 127;
if (sinr < -23)
index = 0;
return index;
}
// Reffered Table 10.1.16.1-2 in 38.133 V16.7.0. Differential value is reported.
static uint8_t get_sinr_diff_index(float best_sinr, float current_sinr)
{
int diff = best_sinr - current_sinr;
if (diff >= 15)
return 15;
else if (diff <= 0)
return 0;
else
return diff;
}
static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
struct NR_CSI_ReportConfig *csi_reportconfig,
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
NR_CSI_MeasConfig_t *csi_MeasConfig)
{
int nb_ssb = 0; // nb of ssb in the resource
int nb_meas = 0; // nb of ssb to report measurements on
int bits = 0;
uint32_t temp_payload = 0;
for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {
struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx];
if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) {
if (csi_reportconfig->groupBasedBeamReporting.present == NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled) {
if (csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS != NULL)
nb_meas = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + 1;
else
nb_meas = 1;
} else
nb_meas = 2;
struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList SSB_resource;
for (int csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId
== *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) {
SSB_resource = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList;
/// only one SSB resource set from spec 38.331 IE CSI-ResourceConfig
nb_ssb = SSB_resource.list.count;
break;
}
}
AssertFatal(nb_ssb > 0, "No SSB found in the resource set\n");
AssertFatal(nb_meas == 1, "PHY currently reports only the strongest SSB to MAC. Can't report more than 1 RSRP\n");
int ssbri_bits = ceil(log2(nb_ssb));
int ssb_index[nb_meas]; // the array contains index and RSRP of each SSB to be reported (nb_meas highest RSRPs)
float ssb_sinr[nb_meas];
// TODO replace the following 2 lines with a function to order the nb_meas highest SSB RSRPs
for (int i = 0; i < nb_ssb; i++) {
ssb_index[i] = -1;//Invalid index
if (*SSB_resource.list.array[i] == mac->mib_ssb) {
ssb_index[0] = i;
break;
}
}
AssertFatal(ssb_index[0] >= 0, "Couldn't find corresponding SSB in csi_SSB_ResourceList\n");
ssb_sinr[0] = mac->ssb_measurements.ssb_sinr_dB;
uint8_t ssbi;
// TS38.212 v16.5.0: Table 6.3.1.1.2-8A
if (ssbri_bits > 0) {
ssbi = ssb_index[0];
temp_payload = reverse_bits(ssbi, ssbri_bits);
bits += ssbri_bits;
}
uint8_t sinr_idx = get_sinr_index(ssb_sinr[0]);
temp_payload |= (reverse_bits(sinr_idx, 7) << bits);
bits += 7; // 7 bits for highest SINR
// from the second SSB, differential report
for (int i = 1; i < nb_meas; i++) {
ssbi = ssb_index[i];
temp_payload = reverse_bits(ssbi, ssbri_bits);
bits += ssbri_bits;
sinr_idx = get_sinr_diff_index(ssb_sinr[0], ssb_sinr[i]);
temp_payload |= (reverse_bits(sinr_idx, 4) << bits);
bits += 4; // 7 bits for highest SINR
}
break; // resource found
}
}
AssertFatal(bits <= 32, "Not supporting CSI report with more than 32 bits\n");
csi_payload_t csi = {.part1_payload = temp_payload, .p1_bits = bits, csi.p2_bits = 0};
return csi;
}
csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
int csi_report_id,
CSI_mapping_t mapping_type,
@@ -2652,26 +2757,39 @@ csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
csi_payload_t csi = {0};
struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement;
switch(csi_reportconfig->reportQuantity.present) {
case NR_CSI_ReportConfig__reportQuantity_PR_none:
break;
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
csi = get_ssb_rsrp_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
csi = get_csirs_RI_PMI_CQI_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig, mapping_type);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
csi = get_csirs_RSRP_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1:
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI:
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
LOG_E(NR_MAC,"Measurement report %d based on CSI-RS is not available\n", csi_reportconfig->reportQuantity.present);
break;
default:
AssertFatal(1==0,"Invalid CSI report quantity type %d\n",csi_reportconfig->reportQuantity.present);
if (csi_reportconfig->ext2 && csi_reportconfig->ext2->reportQuantity_r16) {
switch (csi_reportconfig->ext2->reportQuantity_r16->present) {
case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16:
csi = get_ssb_sinr_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
break;
case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_cri_SINR_r16:
LOG_E(NR_MAC, "CSI Reporting of CSI-RS based SINR not yet available\n");
break;
default:
AssertFatal(1 == 0, "Invalid CSI report quantity r16 type %d\n", csi_reportconfig->ext2->reportQuantity_r16->present);
}
} else {
switch (csi_reportconfig->reportQuantity.present) {
case NR_CSI_ReportConfig__reportQuantity_PR_none:
break;
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
csi = get_ssb_rsrp_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
csi = get_csirs_RI_PMI_CQI_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig, mapping_type);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
csi = get_csirs_RSRP_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1:
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI:
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
LOG_E(NR_MAC, "Measurement report %d based on CSI-RS is not available\n", csi_reportconfig->reportQuantity.present);
break;
default:
AssertFatal(1 == 0, "Invalid CSI report quantity type %d\n", csi_reportconfig->reportQuantity.present);
}
}
return csi;
}
+146 -66
View File
@@ -429,6 +429,78 @@ static uint8_t pickandreverse_bits(uint8_t *payload, uint16_t bitlen, uint8_t st
return rev_bits;
}
static void evaluate_sinr_report(gNB_MAC_INST *nrmac,
NR_UE_info_t *UE,
NR_UE_sched_ctrl_t *sched_ctrl,
uint8_t csi_report_id,
uint8_t *payload,
int *cumul_bits,
NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR reportQuantity_type_r16)
{
/*! As per the spec 38.212 and table: 6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report
* the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE
* From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set
* From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets
* configured is limited to S=1
*/
/** from 38.214 sec 5.2.1.4.2
- if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE is
not required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in
a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting
- if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE is not
required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in a
single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB
resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with
multiple simultaneous spatial domain receive filter
*/
nr_csi_report_t *csi_report = &UE->csi_report_template[csi_report_id];
RSRP_report_t *sinr_report;
long **index_list;
switch (reportQuantity_type_r16) {
case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16:
sinr_report = &sched_ctrl->CSI_report.ssb_rsrp_report;
index_list = csi_report->SSB_Index_list;
break;
case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_cri_SINR_r16:
sinr_report = &sched_ctrl->CSI_report.csirs_rsrp_report;
index_list = csi_report->CSI_Index_list;
break;
default:
AssertFatal(false, "Invalid RSRP report type\n");
}
sinr_report->nr_reports = csi_report->CSI_report_bitlen.nb_ssbri_cri;
uint16_t curr_payload;
for (int i = 0; i < sinr_report->nr_reports; i++) {
int bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen;
curr_payload = pickandreverse_bits(payload, bitlen, *cumul_bits);
sinr_report->resource_id[i] = *(index_list[bitlen > 0 ? ((curr_payload) & ~(~1U << (bitlen - 1))) : bitlen]);
LOG_D(MAC, "SSB/CSI-RS index = %d\n", sinr_report->resource_id[i]);
*cumul_bits += bitlen;
}
curr_payload = pickandreverse_bits(payload, 7, *cumul_bits);
sinr_report->SINR_index[0] = curr_payload & 0x7f;
*cumul_bits += 7;
csi_report->nb_of_csi_ssb_report++;
if (sinr_report->SINR_index[0] < 0 || sinr_report->SINR_index[0] > 127) {
LOG_E(NR_MAC, "UE %04x: reported SINR index %d invalid\n", UE->rnti, sinr_report->SINR_index[0]);
return;
}
for (int i = 1; i < sinr_report->nr_reports; i++) {
curr_payload = pickandreverse_bits(payload, 4, *cumul_bits);
sinr_report->SINR_index[i] = curr_payload & 0x0f;
*cumul_bits += 4;
}
LOG_D(MAC, "Reported SSB-SINR index = %d\n", sinr_report->SINR_index[0]);
}
static void evaluate_rsrp_report(gNB_MAC_INST *nrmac,
NR_UE_info_t *UE,
NR_UE_sched_ctrl_t *sched_ctrl,
@@ -627,6 +699,8 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
uint8_t *payload = uci_pdu->csi_part1.csi_part1_payload;
uint16_t bitlen = uci_pdu->csi_part1.csi_part1_bit_len;
NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type = NR_CSI_ReportConfig__reportQuantity_PR_NOTHING;
NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR reportQuantity_type_r16 =
NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_NOTHING;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
@@ -650,72 +724,78 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
// verify if report with current id has been scheduled for this frame and slot
if ((n_slots_frame*frame + slot - offset)%period == 0) {
reportQuantity_type = csi_report->reportQuantity_type;
// phy-test has hardcoded allocation, so no use to handle CSI reports except RSRP
if (get_softmodem_params()->phy_test
&& reportQuantity_type != NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP
&& reportQuantity_type != NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP)
continue;
LOG_D(MAC,"SFN/SF:%d/%d reportQuantity type = %d\n",frame,slot,reportQuantity_type);
switch(reportQuantity_type) {
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
evaluate_rsrp_report(nrmac, UE, sched_ctrl, csi_report_id, payload, &cumul_bits, reportQuantity_type);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
evaluate_rsrp_report(nrmac, UE, sched_ctrl, csi_report_id, payload, &cumul_bits, reportQuantity_type);
beam_selection_procedures(nrmac, UE);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report = true;
cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
if(cri_bitlen)
evaluate_cri_report(payload,cri_bitlen,cumul_bits,sched_ctrl);
cumul_bits += cri_bitlen;
ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen;
if(ri_bitlen)
r_index = evaluate_ri_report(payload,ri_bitlen,csi_report->csi_meas_bitlen.ri_restriction,cumul_bits,sched_ctrl);
cumul_bits += ri_bitlen;
if (r_index != -1)
skip_zero_padding(&cumul_bits,csi_report,r_index,bitlen);
evaluate_cqi_report(payload,csi_report,cumul_bits,r_index,UE,cqi_table);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report = true;
cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
if(cri_bitlen)
evaluate_cri_report(payload,cri_bitlen,cumul_bits,sched_ctrl);
cumul_bits += cri_bitlen;
ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen;
if(ri_bitlen)
r_index = evaluate_ri_report(payload,ri_bitlen,csi_report->csi_meas_bitlen.ri_restriction,cumul_bits,sched_ctrl);
cumul_bits += ri_bitlen;
if (r_index != -1)
skip_zero_padding(&cumul_bits,csi_report,r_index,bitlen);
pmi_bitlen = evaluate_pmi_report(payload,csi_report,cumul_bits,r_index,sched_ctrl);
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.csi_report_id = csi_report_id;
cumul_bits += pmi_bitlen;
evaluate_cqi_report(payload,csi_report,cumul_bits,r_index,UE,cqi_table);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report = true;
cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
if(cri_bitlen)
evaluate_cri_report(payload,cri_bitlen,cumul_bits,sched_ctrl);
cumul_bits += cri_bitlen;
ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen;
if(ri_bitlen)
r_index = evaluate_ri_report(payload,ri_bitlen,csi_report->csi_meas_bitlen.ri_restriction,cumul_bits,sched_ctrl);
cumul_bits += ri_bitlen;
li_bitlen = evaluate_li_report(payload,csi_report,cumul_bits,r_index,sched_ctrl);
cumul_bits += li_bitlen;
if (r_index != -1)
skip_zero_padding(&cumul_bits,csi_report,r_index,bitlen);
pmi_bitlen = evaluate_pmi_report(payload,csi_report,cumul_bits,r_index,sched_ctrl);
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.csi_report_id = csi_report_id;
cumul_bits += pmi_bitlen;
evaluate_cqi_report(payload,csi_report,cumul_bits,r_index,UE,cqi_table);
break;
default:
AssertFatal(1==0, "Invalid or not supported CSI measurement report\n");
reportQuantity_type_r16 = csi_report->reportQuantity_type_r16;
LOG_D(MAC, "SFN/SF:%d/%d reportQuantity type = %d, type_r16 = %d\n", frame, slot, reportQuantity_type, reportQuantity_type_r16);
if (reportQuantity_type_r16 == NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_cri_SINR_r16
|| reportQuantity_type_r16 == NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16) {
evaluate_sinr_report(nrmac, UE, sched_ctrl, csi_report_id, payload, &cumul_bits, reportQuantity_type_r16);
} else {
// phy-test has hardcoded allocation, so no use to handle CSI reports except RSRP
if (get_softmodem_params()->phy_test
&& reportQuantity_type != NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP
&& reportQuantity_type != NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP)
continue;
switch (reportQuantity_type) {
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
evaluate_rsrp_report(nrmac, UE, sched_ctrl, csi_report_id, payload, &cumul_bits, reportQuantity_type);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
evaluate_rsrp_report(nrmac, UE, sched_ctrl, csi_report_id, payload, &cumul_bits, reportQuantity_type);
beam_selection_procedures(nrmac, UE);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report = true;
cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
if (cri_bitlen)
evaluate_cri_report(payload, cri_bitlen, cumul_bits, sched_ctrl);
cumul_bits += cri_bitlen;
ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen;
if (ri_bitlen)
r_index = evaluate_ri_report(payload, ri_bitlen, csi_report->csi_meas_bitlen.ri_restriction, cumul_bits, sched_ctrl);
cumul_bits += ri_bitlen;
if (r_index != -1)
skip_zero_padding(&cumul_bits, csi_report, r_index, bitlen);
evaluate_cqi_report(payload, csi_report, cumul_bits, r_index, UE, cqi_table);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report = true;
cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
if (cri_bitlen)
evaluate_cri_report(payload, cri_bitlen, cumul_bits, sched_ctrl);
cumul_bits += cri_bitlen;
ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen;
if (ri_bitlen)
r_index = evaluate_ri_report(payload, ri_bitlen, csi_report->csi_meas_bitlen.ri_restriction, cumul_bits, sched_ctrl);
cumul_bits += ri_bitlen;
if (r_index != -1)
skip_zero_padding(&cumul_bits, csi_report, r_index, bitlen);
pmi_bitlen = evaluate_pmi_report(payload, csi_report, cumul_bits, r_index, sched_ctrl);
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.csi_report_id = csi_report_id;
cumul_bits += pmi_bitlen;
evaluate_cqi_report(payload, csi_report, cumul_bits, r_index, UE, cqi_table);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report = true;
cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
if (cri_bitlen)
evaluate_cri_report(payload, cri_bitlen, cumul_bits, sched_ctrl);
cumul_bits += cri_bitlen;
ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen;
if (ri_bitlen)
r_index = evaluate_ri_report(payload, ri_bitlen, csi_report->csi_meas_bitlen.ri_restriction, cumul_bits, sched_ctrl);
cumul_bits += ri_bitlen;
li_bitlen = evaluate_li_report(payload, csi_report, cumul_bits, r_index, sched_ctrl);
cumul_bits += li_bitlen;
if (r_index != -1)
skip_zero_padding(&cumul_bits, csi_report, r_index, bitlen);
pmi_bitlen = evaluate_pmi_report(payload, csi_report, cumul_bits, r_index, sched_ctrl);
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.csi_report_id = csi_report_id;
cumul_bits += pmi_bitlen;
evaluate_cqi_report(payload, csi_report, cumul_bits, r_index, UE, cqi_table);
break;
default:
AssertFatal(1 == 0, "Invalid or not supported CSI measurement report\n");
}
}
}
}
+3
View File
@@ -179,6 +179,7 @@ typedef struct nr_mac_config_t {
int32_t *bw_list;
int num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];
nr_redcap_config_t *redcap;
bool do_SINR;
} nr_mac_config_t;
typedef struct NR_preamble_ue {
@@ -537,6 +538,8 @@ typedef struct RSRP_report {
uint8_t nr_reports;
uint8_t resource_id[MAX_NR_OF_REPORTED_RS];
int RSRP[MAX_NR_OF_REPORTED_RS];
// SINR index according to tables 10.1.16.1-1, 10.1.16.1-2
int SINR_index[MAX_NR_OF_REPORTED_RS];
} RSRP_report_t;
struct CSI_Report {
+4 -2
View File
@@ -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,
+21 -3
View File
@@ -1934,7 +1934,8 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
int rep_id,
int uid,
int curr_bwp,
int num_antenna_ports)
int num_antenna_ports,
bool do_sinr)
{
int resource_id = -1;
for (int csi_list = 0; csi_list < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_list++) {
@@ -1968,6 +1969,14 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
} else {
csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP;
csirep->reportQuantity.choice.ssb_Index_RSRP = (NULL_t)0;
if (do_sinr) {
csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_none;
csirep->reportQuantity.choice.none = (NULL_t)0;
csirep->ext2 = calloc(1, sizeof(*csirep->ext2));
csirep->ext2->reportQuantity_r16 = calloc(1, sizeof(*csirep->ext2->reportQuantity_r16));
csirep->ext2->reportQuantity_r16->present = NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16;
csirep->ext2->reportQuantity_r16->choice.ssb_Index_SINR_r16 = (NULL_t)0;
}
}
csirep->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled;
csirep->groupBasedBeamReporting.choice.disabled = calloc(1, sizeof(*csirep->groupBasedBeamReporting.choice.disabled));
@@ -3298,7 +3307,15 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp));
pucchrsrp->uplinkBandwidthPartId = bwp_id;
pucchrsrp->pucch_Resource = pucch_Resource;
config_rsrp_meas_report(csi_MeasConfig, scc, pucchrsrp, configuration->do_CSIRS, bwp_id + 10, uid, curr_bwp, pdsch_AntennaPorts);
config_rsrp_meas_report(csi_MeasConfig,
scc,
pucchrsrp,
configuration->do_CSIRS,
bwp_id + 10,
uid,
curr_bwp,
pdsch_AntennaPorts,
configuration->do_SINR);
}
fill_harq_IEs(SpCellConfig->spCellConfigDedicated, configuration->num_dlharq, configuration->num_ulharq);
@@ -3811,7 +3828,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
bwp->bwp_Id + 10,
uid,
curr_bwp,
dl_antenna_ports);
dl_antenna_ports,
configuration->do_SINR);
}
secondaryCellGroup->spCellConfig->spCellConfigDedicated->sCellDeactivationTimer = NULL;
secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig = NULL;