Commit c61d0b6c authored by Bo Zhao's avatar Bo Zhao Committed by Thomas Schlichter

Generating SSB based SINR report at UE side

parent c8605190
...@@ -136,6 +136,7 @@ typedef struct { ...@@ -136,6 +136,7 @@ typedef struct {
uint16_t cell_id; uint16_t cell_id;
uint16_t ssb_start_subcarrier; uint16_t ssb_start_subcarrier;
short rsrp_dBm; short rsrp_dBm;
float sinr_dB;
rlm_t radiolink_monitoring; // -1 no monitoring, 0 out_of_sync, 1 in_sync rlm_t radiolink_monitoring; // -1 no monitoring, 0 out_of_sync, 1 in_sync
} fapi_nr_ssb_pdu_t; } fapi_nr_ssb_pdu_t;
......
...@@ -132,6 +132,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, ...@@ -132,6 +132,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue,
} }
ue->measurements.rx_power_tot[gNB_id] /= frame_parms->nb_antennas_rx;
ue->measurements.rx_power_tot_dB[gNB_id] = (unsigned short) dB_fixed(ue->measurements.rx_power_tot[gNB_id]); ue->measurements.rx_power_tot_dB[gNB_id] = (unsigned short) dB_fixed(ue->measurements.rx_power_tot[gNB_id]);
} }
...@@ -232,19 +233,20 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, ...@@ -232,19 +233,20 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
} }
rsrp /= nb_re; rsrp /= nb_re;
ue->measurements.ssb_rsrp_dBm[ssb_index] = 10*log10(rsrp) +
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.ssb_rsrp_dBm[ssb_index] = (10*log10(rsrp) - (int)ue->rfdevice.app_rx_gain[0]) - (int)openair0_cfg[0].rx_gain_offset[0]; 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", // to obtain non-integer dB value with a resoluion of 0.5dB
__FUNCTION__, int SNRtimes10 = dB_fixed_x10(rsrp) - dB_fixed_x10(ue->measurements.n0_power_avg);
ue->Mod_id, ue->measurements.ssb_sinr_dB[ssb_index] = SNRtimes10 / 10.0;
ssb_index,
ue->measurements.ssb_rsrp_dBm[ssb_index], LOG_D(PHY,
rsrp); "In %s: [UE %d] SSB index: %d, SS-RSRP: %d dBm/RE, SS-SINR: %f dB\n",
__FUNCTION__,
ue->Mod_id,
ssb_index,
ue->measurements.ssb_rsrp_dBm[ssb_index],
ue->measurements.ssb_sinr_dB[ssb_index]);
// Send SS measurements to MAC // Send SS measurements to MAC
fapi_nr_l1_measurements_t l1_measurements; fapi_nr_l1_measurements_t l1_measurements;
...@@ -523,6 +525,7 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue, ...@@ -523,6 +525,7 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
} }
ue->measurements.n0_power_tot /= ue->frame_parms.nb_antennas_rx;
ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot); ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot);
LOG_A(PHY, "aarx: %d\n", aarx); LOG_A(PHY, "aarx: %d\n", aarx);
......
...@@ -158,6 +158,7 @@ typedef struct { ...@@ -158,6 +158,7 @@ typedef struct {
uint32_t rsrp[7]; uint32_t rsrp[7];
short rsrp_dBm[7]; short rsrp_dBm[7];
int ssb_rsrp_dBm[64]; int ssb_rsrp_dBm[64];
float ssb_sinr_dB[64];
// common measurements // common measurements
//! estimated noise power (linear) //! estimated noise power (linear)
unsigned int n0_power[NB_ANTENNAS_RX]; unsigned int n0_power[NB_ANTENNAS_RX];
......
...@@ -167,6 +167,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, ...@@ -167,6 +167,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
ssb_pdu->cell_id = frame_parms->Nid_cell; ssb_pdu->cell_id = frame_parms->Nid_cell;
ssb_pdu->ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; ssb_pdu->ssb_start_subcarrier = frame_parms->ssb_start_subcarrier;
ssb_pdu->rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index]; ssb_pdu->rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index];
ssb_pdu->sinr_dB = ue->measurements.ssb_sinr_dB[frame_parms->ssb_index];
ssb_pdu->radiolink_monitoring = RLM_in_sync; // TODO to be removed from here ssb_pdu->radiolink_monitoring = RLM_in_sync; // TODO to be removed from here
ssb_pdu->decoded_pdu = true; ssb_pdu->decoded_pdu = true;
} }
......
...@@ -370,6 +370,8 @@ typedef struct { ...@@ -370,6 +370,8 @@ typedef struct {
uint32_t ssb_index; uint32_t ssb_index;
/// SSB RSRP in dBm /// SSB RSRP in dBm
short ssb_rsrp_dBm; short ssb_rsrp_dBm;
/// measured SSB SINR in dB
float ssb_sinr_dB;
} NR_SSB_meas_t; } NR_SSB_meas_t;
typedef struct NR_UL_TIME_ALIGNMENT { typedef struct NR_UL_TIME_ALIGNMENT {
......
...@@ -186,6 +186,12 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, ...@@ -186,6 +186,12 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac,
int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch); int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch);
uint8_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
PUCCH_sched_t *pucch,
struct NR_CSI_ReportConfig *csi_reportconfig,
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
NR_CSI_MeasConfig_t *csi_MeasConfig);
uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
PUCCH_sched_t *pucch, PUCCH_sched_t *pucch,
struct NR_CSI_ReportConfig *csi_reportconfig, struct NR_CSI_ReportConfig *csi_reportconfig,
...@@ -209,6 +215,8 @@ uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, ...@@ -209,6 +215,8 @@ uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
int csi_report_id, int csi_report_id,
NR_CSI_MeasConfig_t *csi_MeasConfig); NR_CSI_MeasConfig_t *csi_MeasConfig);
uint8_t get_sinr_index(float sinr);
uint8_t get_sinr_diff_index(float best_sinr, float current_sinr);
uint8_t get_rsrp_index(int rsrp); uint8_t get_rsrp_index(int rsrp);
uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp); uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp);
......
...@@ -2544,30 +2544,136 @@ uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, ...@@ -2544,30 +2544,136 @@ uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement; NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement;
switch(csi_reportconfig->reportQuantity.present) { if (csi_reportconfig->ext2 != NULL
case NR_CSI_ReportConfig__reportQuantity_PR_none: && csi_reportconfig->ext2->reportQuantity_r16->present != NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_NOTHING) {
break; switch (csi_reportconfig->ext2->reportQuantity_r16->present) {
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP: case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16:
n_csi_bits = get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); n_csi_bits += get_ssb_sinr_payload(mac, pucch, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
break; break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI: case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_cri_SINR_r16:
n_csi_bits = get_csirs_RI_PMI_CQI_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); LOG_E(NR_MAC,
break; "Measurement report %d based on CSI-RS not availalble\n",
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP: csi_reportconfig->ext2->reportQuantity_r16->present);
n_csi_bits = get_csirs_RSRP_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); break;
break; default:
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1: AssertFatal(1 == 0, "Invalid CSI report quantity r16 type %d\n", csi_reportconfig->ext2->reportQuantity_r16->present);
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI: }
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI: } else {
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI: switch (csi_reportconfig->reportQuantity.present) {
LOG_E(NR_MAC,"Measurement report %d based on CSI-RS is not available\n", csi_reportconfig->reportQuantity.present); case NR_CSI_ReportConfig__reportQuantity_PR_none:
break; break;
default: case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
AssertFatal(1==0,"Invalid CSI report quantity type %d\n",csi_reportconfig->reportQuantity.present); n_csi_bits = get_ssb_rsrp_payload(mac, pucch, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
n_csi_bits = get_csirs_RI_PMI_CQI_payload(mac, pucch, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
n_csi_bits = get_csirs_RSRP_payload(mac, pucch, 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 (n_csi_bits); return (n_csi_bits);
} }
uint8_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
PUCCH_sched_t *pucch,
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) {
/* 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 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 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.
*/
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;
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])) {
/// only one SSB resource set per configuration from spec 38.331 IE CSI-ResourceConfig:
/// maxNrofCSI-SSB-ResourceSetsPerConfig=1
nb_ssb = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count;
break;
}
}
AssertFatal(nb_ssb > 0, "No SSB found in the resource set\n");
int ssbri_bits = ceil(log2(nb_ssb));
// TODO measurement of multiple SSBs at PHY and indication to MAC
if (nb_ssb > 1)
LOG_E(MAC,
"In current implementation only the SSB of synchronization is measured at PHY. This works only for a single SSB "
"scenario\n");
int ssb_sinr[nb_meas]; // the array contains index of each SSB to be reported (nb_meas highest SINRs)
float sinr[nb_meas]; // the array contains SINR of each SSB to be reported (nb_meas highest SINRs)
// TODO replace the following lines with a function to order the nb_meas highest SSB SINRs
for (int i = 0; i < nb_meas; i++) {
ssb_sinr[i] = mac->mib_ssb;
sinr[i] = 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_sinr[0];
reverse_n_bits(&ssbi, ssbri_bits);
temp_payload = ssbi;
bits += ssbri_bits;
}
// from the second SSB, differential report
for (int i = 1; i < nb_meas; i++) {
ssbi = ssb_sinr[i];
reverse_n_bits(&ssbi, ssbri_bits);
temp_payload |= (ssbi << bits);
bits += ssbri_bits;
}
uint8_t sinr_idx = get_sinr_index(sinr[0]);
reverse_n_bits(&sinr_idx, 7);
temp_payload |= (sinr_idx << bits);
bits += 7; // 7 bits for highest SINR
// from the second SSB, differential report
for (int i = 1; i < nb_meas; i++) {
sinr_idx = get_sinr_diff_index(sinr[0], sinr[i]);
reverse_n_bits(&sinr_idx, 4);
temp_payload |= (sinr_idx << bits);
bits += 4; // 4 bits for differential SINR
}
break; // resource found
}
}
pucch->csi_part1_payload = temp_payload;
return bits;
}
uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
PUCCH_sched_t *pucch, PUCCH_sched_t *pucch,
...@@ -2799,6 +2905,32 @@ uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp) { ...@@ -2799,6 +2905,32 @@ uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp) {
} }
// returns index from SINR
// according to Table Table 10.1.16.1-1 in 38.133 V16.7.0
uint8_t get_sinr_index(float sinr)
{
int index = sinr * 2 + 47;
if (sinr >= 40)
index = 127;
if (sinr < -23)
index = 0;
return index;
}
// returns index from differential SINR
// according to Table 10.1.16.1-2 in 38.133 V16.7.0
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;
}
void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, int pdu_id) void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, int pdu_id)
{ {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
......
...@@ -1064,10 +1064,11 @@ int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t ...@@ -1064,10 +1064,11 @@ int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t
} }
void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm) void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm, float sinr_dB)
{ {
mac->ssb_measurements.ssb_index = ssb_index; mac->ssb_measurements.ssb_index = ssb_index;
mac->ssb_measurements.ssb_rsrp_dBm = rsrp_dbm; mac->ssb_measurements.ssb_rsrp_dBm = rsrp_dbm;
mac->ssb_measurements.ssb_sinr_dB = sinr_dB;
} }
// L2 Abstraction Layer // L2 Abstraction Layer
...@@ -1202,7 +1203,8 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info) ...@@ -1202,7 +1203,8 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info)
if(rx_indication_body.ssb_pdu.decoded_pdu) { if(rx_indication_body.ssb_pdu.decoded_pdu) {
handle_ssb_meas(mac, handle_ssb_meas(mac,
rx_indication_body.ssb_pdu.ssb_index, 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(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, dl_info->phy_data, ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, dl_info->phy_data,
rx_indication_body.ssb_pdu.pdu, rx_indication_body.ssb_pdu.pdu,
rx_indication_body.ssb_pdu.additional_bits, rx_indication_body.ssb_pdu.additional_bits,
......
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