enabled transmission of up to 4 RSRP measurement reports from UE to gNB
This commit is contained in:
committed by
francescomani
parent
b462fa45e8
commit
5903806d2e
@@ -965,31 +965,38 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_
|
|||||||
nr_ue_ssb_rsrp_measurements(ue, ssb_index, proc, rxdataF);
|
nr_ue_ssb_rsrp_measurements(ue, ssb_index, proc, rxdataF);
|
||||||
|
|
||||||
// resetting ssb index for PBCH detection if there is a stronger SSB index
|
// resetting ssb index for PBCH detection if there is a stronger SSB index
|
||||||
if(ue->measurements.ssb_rsrp_dBm[ssb_index] > ue->measurements.ssb_rsrp_dBm[fp->ssb_index])
|
if(ue->measurements.ssb_rsrp_dBm[ssb_index] > ue->measurements.ssb_rsrp_dBm[fp->ssb_index]) {
|
||||||
fp->ssb_index = ssb_index;
|
fp->ssb_index = ssb_index;
|
||||||
|
LOG_D(PHY, "New best SSB: index %d RSRP %d\n", ssb_index, ue->measurements.ssb_rsrp_dBm[ssb_index]);
|
||||||
if(ssb_index == fp->ssb_index) {
|
|
||||||
|
|
||||||
LOG_D(PHY," ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx);
|
|
||||||
const int pbchSuccess = nr_ue_pbch_procedures(ue, proc, estimateSz, dl_ch_estimates, rxdataF);
|
|
||||||
|
|
||||||
if (ue->no_timing_correction==0 && pbchSuccess == 0) {
|
|
||||||
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
|
|
||||||
sampleShift =
|
|
||||||
nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_nrUE_params()->cont_fo_comp && pbchSuccess == 0) {
|
|
||||||
double freq_offset = nr_ue_pbch_freq_offset(fp, estimateSz, dl_ch_estimates);
|
|
||||||
LOG_D(PHY,"compensated frequency offset = %.3f Hz, detected residual frequency offset = %.3f Hz, accumulated frequency offset = %.3f Hz\n", ue->freq_offset, freq_offset, ue->freq_off_acc);
|
|
||||||
|
|
||||||
// PI controller
|
|
||||||
const double PID_P = get_nrUE_params()->freq_sync_P;
|
|
||||||
const double PID_I = get_nrUE_params()->freq_sync_I;
|
|
||||||
ue->freq_offset += freq_offset * PID_P + ue->freq_off_acc * PID_I;
|
|
||||||
ue->freq_off_acc += freq_offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ssb_index != fp->ssb_index)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LOG_D(PHY, " ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx % 1024, nr_slot_rx);
|
||||||
|
const int pbchSuccess = nr_ue_pbch_procedures(ue, proc, estimateSz, dl_ch_estimates, rxdataF);
|
||||||
|
|
||||||
|
if (ue->no_timing_correction == 0 && pbchSuccess == 0) {
|
||||||
|
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
|
||||||
|
sampleShift =
|
||||||
|
nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_nrUE_params()->cont_fo_comp && pbchSuccess == 0) {
|
||||||
|
double freq_offset = nr_ue_pbch_freq_offset(fp, estimateSz, dl_ch_estimates);
|
||||||
|
LOG_D(PHY,
|
||||||
|
"compensated freq offset = %.3f Hz, detected residual freq offset = %.3f Hz, accumulated freq offset = %.3f Hz\n",
|
||||||
|
ue->freq_offset,
|
||||||
|
freq_offset,
|
||||||
|
ue->freq_off_acc);
|
||||||
|
|
||||||
|
// PI controller
|
||||||
|
const double PID_P = get_nrUE_params()->freq_sync_P;
|
||||||
|
const double PID_I = get_nrUE_params()->freq_sync_I;
|
||||||
|
ue->freq_offset += freq_offset * PID_P + ue->freq_off_acc * PID_I;
|
||||||
|
ue->freq_off_acc += freq_offset;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
|
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
|
||||||
nr_ue_rrc_measurements(ue, proc, rxdataF);
|
nr_ue_rrc_measurements(ue, proc, rxdataF);
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_OUT);
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_OUT);
|
||||||
|
|||||||
@@ -407,8 +407,8 @@ typedef struct {
|
|||||||
NR_PUCCH_Resource_t *pucch_resource;
|
NR_PUCCH_Resource_t *pucch_resource;
|
||||||
uint32_t ack_payload;
|
uint32_t ack_payload;
|
||||||
uint8_t sr_payload;
|
uint8_t sr_payload;
|
||||||
uint32_t csi_part1_payload;
|
uint64_t csi_part1_payload;
|
||||||
uint32_t csi_part2_payload;
|
uint64_t csi_part2_payload;
|
||||||
int n_sr;
|
int n_sr;
|
||||||
int n_csi;
|
int n_csi;
|
||||||
int n_harq;
|
int n_harq;
|
||||||
@@ -418,9 +418,8 @@ typedef struct {
|
|||||||
} PUCCH_sched_t;
|
} PUCCH_sched_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t ssb_index;
|
|
||||||
/// SSB RSRP in dBm
|
/// SSB RSRP in dBm
|
||||||
short ssb_rsrp_dBm;
|
int ssb_rsrp_dBm;
|
||||||
float_t ssb_sinr_dB;
|
float_t ssb_sinr_dB;
|
||||||
} NR_SSB_meas_t;
|
} NR_SSB_meas_t;
|
||||||
|
|
||||||
@@ -473,8 +472,8 @@ typedef struct {
|
|||||||
} NR_BWP_PDCCH_t;
|
} NR_BWP_PDCCH_t;
|
||||||
|
|
||||||
typedef struct csi_payload {
|
typedef struct csi_payload {
|
||||||
uint32_t part1_payload;
|
uint64_t part1_payload;
|
||||||
uint32_t part2_payload;
|
uint64_t part2_payload;
|
||||||
int p1_bits;
|
int p1_bits;
|
||||||
int p2_bits;
|
int p2_bits;
|
||||||
} csi_payload_t;
|
} csi_payload_t;
|
||||||
@@ -625,7 +624,7 @@ typedef struct NR_UE_MAC_INST_s {
|
|||||||
uint8_t ssb_subcarrier_offset;
|
uint8_t ssb_subcarrier_offset;
|
||||||
int ssb_start_subcarrier;
|
int ssb_start_subcarrier;
|
||||||
|
|
||||||
NR_SSB_meas_t ssb_measurements;
|
NR_SSB_meas_t ssb_measurements[MAX_NB_SSB];
|
||||||
|
|
||||||
dci_pdu_rel15_t def_dci_pdu_rel15[NR_MAX_SLOTS_PER_FRAME][8];
|
dci_pdu_rel15_t def_dci_pdu_rel15[NR_MAX_SLOTS_PER_FRAME][8];
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu);
|
|||||||
fapi_nr_ul_config_request_pdu_t *fapiLockIterator(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx);
|
fapi_nr_ul_config_request_pdu_t *fapiLockIterator(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx);
|
||||||
|
|
||||||
void release_ul_config(fapi_nr_ul_config_request_pdu_t *pdu, bool clearIt);
|
void release_ul_config(fapi_nr_ul_config_request_pdu_t *pdu, bool clearIt);
|
||||||
int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm);
|
int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac);
|
||||||
|
|
||||||
// PUSCH scheduler:
|
// PUSCH scheduler:
|
||||||
// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2,
|
// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2,
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
|
|||||||
nr_timer_stop(&mac->scheduling_info.sr_DelayTimer);
|
nr_timer_stop(&mac->scheduling_info.sr_DelayTimer);
|
||||||
|
|
||||||
memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
|
memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
|
||||||
|
for (int i = 0; i < MAX_NB_SSB; i++) {
|
||||||
|
mac->ssb_measurements[i].ssb_rsrp_dBm = INT_MIN;
|
||||||
|
mac->ssb_measurements[i].ssb_sinr_dB = INT_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
|
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
|
||||||
memset(&mac->ssb_list, 0, sizeof(mac->ssb_list));
|
memset(&mac->ssb_list, 0, sizeof(mac->ssb_list));
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac)
|
int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac)
|
||||||
{
|
{
|
||||||
RA_config_t *ra = &mac->ra;
|
RA_config_t *ra = &mac->ra;
|
||||||
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
|
int16_t pathloss = compute_nr_SSB_PL(mac);
|
||||||
int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_preamble_rx_target_power + pathloss);
|
int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_preamble_rx_target_power + pathloss);
|
||||||
return min(ra->prach_resources.Pc_max, ra_preamble_rx_power);
|
return min(ra->prach_resources.Pc_max, ra_preamble_rx_power);
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ static void select_preamble_group(NR_UE_MAC_INST_t *mac)
|
|||||||
// – preambleReceivedTargetPower – msg3-DeltaPreamble – messagePowerOffsetGroupB
|
// – preambleReceivedTargetPower – msg3-DeltaPreamble – messagePowerOffsetGroupB
|
||||||
int groupB_pow_offset = get_messagePowerOffsetGroupB(groupB->messagePowerOffsetGroupB);
|
int groupB_pow_offset = get_messagePowerOffsetGroupB(groupB->messagePowerOffsetGroupB);
|
||||||
int PLThreshold = ra->prach_resources.Pc_max - ra->preambleRxTargetPower - ra->msg3_deltaPreamble - groupB_pow_offset;
|
int PLThreshold = ra->prach_resources.Pc_max - ra->preambleRxTargetPower - ra->msg3_deltaPreamble - groupB_pow_offset;
|
||||||
int pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
|
int pathloss = compute_nr_SSB_PL(mac);
|
||||||
// TODO if the Random Access procedure was initiated for the CCCH logical channel and the CCCH SDU size
|
// TODO if the Random Access procedure was initiated for the CCCH logical channel and the CCCH SDU size
|
||||||
// plus MAC subheader is greater than ra-Msg3SizeGroupA
|
// plus MAC subheader is greater than ra-Msg3SizeGroupA
|
||||||
if (ra->Msg3_size > get_Msg3SizeGroupA(groupB->ra_Msg3SizeGroupA) && pathloss < PLThreshold)
|
if (ra->Msg3_size > get_Msg3SizeGroupA(groupB->ra_Msg3SizeGroupA) && pathloss < PLThreshold)
|
||||||
@@ -971,7 +971,7 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame)
|
|||||||
"msgA_RSRP_Threshold_r16 is mandatory present if both 2-step and 4-step random access types are configured\n");
|
"msgA_RSRP_Threshold_r16 is mandatory present if both 2-step and 4-step random access types are configured\n");
|
||||||
// For thresholds the RSRP value is (IE value – 156) dBm except for the IE 127 in which case the actual value is infinity
|
// For thresholds the RSRP value is (IE value – 156) dBm except for the IE 127 in which case the actual value is infinity
|
||||||
int rsrp_msga_thr = *twostep_conf->msgA_RSRP_Threshold_r16 - 156;
|
int rsrp_msga_thr = *twostep_conf->msgA_RSRP_Threshold_r16 - 156;
|
||||||
if (*twostep_conf->msgA_RSRP_Threshold_r16 != 127 && mac->ssb_measurements.ssb_rsrp_dBm > rsrp_msga_thr)
|
if (*twostep_conf->msgA_RSRP_Threshold_r16 != 127 && mac->ssb_measurements[mac->mib_ssb].ssb_rsrp_dBm > rsrp_msga_thr)
|
||||||
twostep = true;
|
twostep = true;
|
||||||
} else {
|
} else {
|
||||||
// if the BWP selected for Random Access procedure is only configured with 2-step RA type Random Access
|
// if the BWP selected for Random Access procedure is only configured with 2-step RA type Random Access
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
|
|||||||
1,
|
1,
|
||||||
start_prb);
|
start_prb);
|
||||||
float P_CMIN = current_UL_BWP->P_CMIN;
|
float P_CMIN = current_UL_BWP->P_CMIN;
|
||||||
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
|
int16_t pathloss = compute_nr_SSB_PL(mac);
|
||||||
|
|
||||||
if (power_config->twoPUCCH_PC_AdjustmentStates && *power_config->twoPUCCH_PC_AdjustmentStates > 1) {
|
if (power_config->twoPUCCH_PC_AdjustmentStates && *power_config->twoPUCCH_PC_AdjustmentStates > 1) {
|
||||||
LOG_E(MAC,"PUCCH power control adjustment states with 2 states not yet implemented\n");
|
LOG_E(MAC,"PUCCH power control adjustment states with 2 states not yet implemented\n");
|
||||||
@@ -427,20 +427,23 @@ static int get_deltatf(uint16_t nb_of_prbs,
|
|||||||
// - PRACH transmission from a UE is not in response to a detection of a PDCCH order by the UE
|
// - PRACH transmission from a UE is not in response to a detection of a PDCCH order by the UE
|
||||||
// Measurement units:
|
// Measurement units:
|
||||||
// - referenceSignalPower: dBm/RE (average EPRE of the resources elements that carry secondary synchronization signals in dBm)
|
// - referenceSignalPower: dBm/RE (average EPRE of the resources elements that carry secondary synchronization signals in dBm)
|
||||||
int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm)
|
int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac)
|
||||||
{
|
{
|
||||||
|
// getting the maximum SSB RSRP from the SSB measurements
|
||||||
|
int max_ssb_rsrp_dBm = mac->ssb_measurements[mac->mib_ssb].ssb_rsrp_dBm;
|
||||||
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
||||||
int referenceSignalPower = cfg->ssb_config.ss_pbch_power;
|
int referenceSignalPower = cfg->ssb_config.ss_pbch_power;
|
||||||
|
|
||||||
//TODO improve PL measurements. Probably not correct as it is.
|
//TODO improve PL measurements. Probably not correct as it is.
|
||||||
|
|
||||||
int16_t pathloss = (int16_t)(referenceSignalPower - ssb_rsrp_dBm);
|
int16_t pathloss = (int16_t)(referenceSignalPower - max_ssb_rsrp_dBm);
|
||||||
|
|
||||||
LOG_D(NR_MAC, "pathloss %d dB, referenceSignalPower %d dBm/RE (%f mW), RSRP %d dBm (%f mW)\n",
|
LOG_D(NR_MAC, "pathloss %d dB, referenceSignalPower %d dBm/RE (%f mW), RSRP %d dBm (%f mW)\n",
|
||||||
pathloss,
|
pathloss,
|
||||||
referenceSignalPower,
|
referenceSignalPower,
|
||||||
pow(10, referenceSignalPower/10),
|
pow(10, referenceSignalPower/10),
|
||||||
ssb_rsrp_dBm,
|
max_ssb_rsrp_dBm,
|
||||||
pow(10, ssb_rsrp_dBm/10));
|
pow(10, max_ssb_rsrp_dBm/10));
|
||||||
|
|
||||||
return pathloss;
|
return pathloss;
|
||||||
}
|
}
|
||||||
@@ -557,8 +560,8 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
|
|||||||
DELTA_TF = 10 * log10(pow(2, BPRE * 1.25f) * beta_offset);
|
DELTA_TF = 10 * log10(pow(2, BPRE * 1.25f) * beta_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: compute pathoss using correct reference
|
// TODO: compute pathloss using correct reference
|
||||||
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
|
int16_t pathloss = compute_nr_SSB_PL(mac);
|
||||||
int P_CMIN = mac->current_UL_BWP->P_CMIN;
|
int P_CMIN = mac->current_UL_BWP->P_CMIN;
|
||||||
|
|
||||||
float pusch_power_without_f_b_f_c = P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF;
|
float pusch_power_without_f_b_f_c = P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF;
|
||||||
@@ -626,7 +629,7 @@ int get_srs_tx_power_ue(NR_UE_MAC_INST_t *mac,
|
|||||||
get_m_srs(srs_resource->freqHopping.c_SRS, srs_resource->freqHopping.b_SRS),
|
get_m_srs(srs_resource->freqHopping.c_SRS, srs_resource->freqHopping.b_SRS),
|
||||||
0); // TODO: Determine SRS start RB
|
0); // TODO: Determine SRS start RB
|
||||||
|
|
||||||
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
|
int16_t pathloss = compute_nr_SSB_PL(mac);
|
||||||
|
|
||||||
int srs_power_without_h_b_f_c = P_0_SRS + alpha * pathloss + m_srs_component;
|
int srs_power_without_h_b_f_c = P_0_SRS + alpha * pathloss + m_srs_component;
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,12 @@ const uint16_t table_7_2_1[16] = {
|
|||||||
1920, // row index 13
|
1920, // row index 13
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t ssb_index;
|
||||||
|
short ssb_rsrp_dBm;
|
||||||
|
float_t ssb_sinr_dB;
|
||||||
|
} NR_RSRP_meas_t;
|
||||||
|
|
||||||
/* TS 36.213 Table 9.2.3-3: Mapping of values for one HARQ-ACK bit to sequences */
|
/* TS 36.213 Table 9.2.3-3: Mapping of values for one HARQ-ACK bit to sequences */
|
||||||
static const int sequence_cyclic_shift_1_harq_ack_bit[2]
|
static const int sequence_cyclic_shift_1_harq_ack_bit[2]
|
||||||
/* HARQ-ACK Value 0 1 */
|
/* HARQ-ACK Value 0 1 */
|
||||||
@@ -1510,9 +1516,9 @@ void nr_ue_process_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slo
|
|||||||
memcpy(&mac->l1_measurements, l1_measurements, sizeof(*l1_measurements));
|
memcpy(&mac->l1_measurements, l1_measurements, sizeof(*l1_measurements));
|
||||||
bool csi_meas = l1_measurements->meas_type == NFAPI_NR_CSI_MEAS;
|
bool csi_meas = l1_measurements->meas_type == NFAPI_NR_CSI_MEAS;
|
||||||
if (!csi_meas && !l1_measurements->is_neighboring_cell) {
|
if (!csi_meas && !l1_measurements->is_neighboring_cell) {
|
||||||
mac->ssb_measurements.ssb_index = l1_measurements->ssb_index;
|
int ssb_index = l1_measurements->ssb_index;
|
||||||
mac->ssb_measurements.ssb_rsrp_dBm = l1_measurements->rsrp_dBm;
|
mac->ssb_measurements[ssb_index].ssb_rsrp_dBm = l1_measurements->rsrp_dBm;
|
||||||
mac->ssb_measurements.ssb_sinr_dB = l1_measurements->sinr_dB;
|
mac->ssb_measurements[ssb_index].ssb_sinr_dB = l1_measurements->sinr_dB;
|
||||||
}
|
}
|
||||||
nr_mac_rrc_meas_ind_ue(mac->ue_id,
|
nr_mac_rrc_meas_ind_ue(mac->ue_id,
|
||||||
l1_measurements->gNB_index,
|
l1_measurements->gNB_index,
|
||||||
@@ -2764,6 +2770,14 @@ static uint8_t get_sinr_diff_index(float best_sinr, float current_sinr)
|
|||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Comparison function for sorting SSB SINR measurements in descending order
|
||||||
|
static int compare_ssb_sinr(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const NR_RSRP_meas_t *ma = (const NR_RSRP_meas_t *)a;
|
||||||
|
const NR_RSRP_meas_t *mb = (const NR_RSRP_meas_t *)b;
|
||||||
|
return mb->ssb_sinr_dB - ma->ssb_sinr_dB;
|
||||||
|
}
|
||||||
|
|
||||||
static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
|
static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
|
||||||
struct NR_CSI_ReportConfig *csi_reportconfig,
|
struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||||
@@ -2772,7 +2786,7 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
|
|||||||
int nb_ssb = 0; // nb of ssb in the resource
|
int nb_ssb = 0; // nb of ssb in the resource
|
||||||
int nb_meas = 0; // nb of ssb to report measurements on
|
int nb_meas = 0; // nb of ssb to report measurements on
|
||||||
int bits = 0;
|
int bits = 0;
|
||||||
uint32_t temp_payload = 0;
|
uint64_t temp_payload = 0;
|
||||||
|
|
||||||
for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {
|
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];
|
struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx];
|
||||||
@@ -2797,51 +2811,55 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
|
|||||||
}
|
}
|
||||||
|
|
||||||
AssertFatal(nb_ssb > 0, "No SSB found in the resource set\n");
|
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");
|
AssertFatal(nb_meas <= 4,"Can't report more than 4 RSRPs\n");
|
||||||
int ssbri_bits = ceil(log2(nb_ssb));
|
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)
|
// map SSB index to SSB resource table index, copy measurements, sort in descending order
|
||||||
float ssb_sinr[nb_meas];
|
NR_RSRP_meas_t sorted_sinr_measurements[nb_ssb];
|
||||||
|
int sorted_idx = 0;
|
||||||
// TODO replace the following 2 lines with a function to order the nb_meas highest SSB RSRPs
|
for (int measured_ssb_idx = 0; measured_ssb_idx < MAX_NB_SSB; measured_ssb_idx++) {
|
||||||
for (int i = 0; i < nb_ssb; i++) {
|
// searching for the SSB index in the SSB resource table
|
||||||
ssb_index[i] = -1;//Invalid index
|
for (int ssb_resource = 0; ssb_resource < nb_ssb; ssb_resource++) {
|
||||||
if (*SSB_resource.list.array[i] == mac->mib_ssb) {
|
if (*SSB_resource.list.array[ssb_resource] == measured_ssb_idx) {
|
||||||
ssb_index[0] = i;
|
sorted_sinr_measurements[sorted_idx].ssb_index = ssb_resource;
|
||||||
break;
|
sorted_sinr_measurements[sorted_idx].ssb_rsrp_dBm = mac->ssb_measurements[measured_ssb_idx].ssb_rsrp_dBm;
|
||||||
|
sorted_sinr_measurements[sorted_idx].ssb_sinr_dB = mac->ssb_measurements[measured_ssb_idx].ssb_sinr_dB;
|
||||||
|
sorted_idx++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssertFatal(ssb_index[0] >= 0, "Couldn't find corresponding SSB in csi_SSB_ResourceList\n");
|
qsort(sorted_sinr_measurements, nb_ssb, sizeof(NR_RSRP_meas_t), compare_ssb_sinr);
|
||||||
ssb_sinr[0] = mac->ssb_measurements.ssb_sinr_dB;
|
|
||||||
|
|
||||||
uint8_t ssbi;
|
uint8_t ssbi;
|
||||||
|
|
||||||
// TS38.212 v16.5.0: Table 6.3.1.1.2-8A
|
// TS38.212 v16.5.0: Table 6.3.1.1.2-8A
|
||||||
if (ssbri_bits > 0) {
|
if (ssbri_bits > 0) {
|
||||||
ssbi = ssb_index[0];
|
ssbi = sorted_sinr_measurements[0].ssb_index;
|
||||||
temp_payload = reverse_bits(ssbi, ssbri_bits);
|
temp_payload = reverse_bits(ssbi, ssbri_bits);
|
||||||
bits += ssbri_bits;
|
bits += ssbri_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t sinr_idx = get_sinr_index(ssb_sinr[0]);
|
uint8_t sinr_idx = get_sinr_index(sorted_sinr_measurements[0].ssb_sinr_dB);
|
||||||
temp_payload |= (reverse_bits(sinr_idx, 7) << bits);
|
temp_payload |= (reverse_bits(sinr_idx, 7) << bits);
|
||||||
bits += 7; // 7 bits for highest SINR
|
bits += 7; // 7 bits for highest SINR
|
||||||
|
|
||||||
// from the second SSB, differential report
|
// from the second SSB, differential report
|
||||||
for (int i = 1; i < nb_meas; i++) {
|
for (int i = 1; i < nb_meas; i++) {
|
||||||
ssbi = ssb_index[i];
|
ssbi = sorted_sinr_measurements[i].ssb_index;
|
||||||
temp_payload = reverse_bits(ssbi, ssbri_bits);
|
temp_payload = reverse_bits(ssbi, ssbri_bits);
|
||||||
bits += ssbri_bits;
|
bits += ssbri_bits;
|
||||||
|
|
||||||
sinr_idx = get_sinr_diff_index(ssb_sinr[0], ssb_sinr[i]);
|
sinr_idx = get_sinr_diff_index(sorted_sinr_measurements[0].ssb_sinr_dB, sorted_sinr_measurements[i].ssb_sinr_dB);
|
||||||
temp_payload |= (reverse_bits(sinr_idx, 4) << bits);
|
temp_payload |= (reverse_bits(sinr_idx, 4) << bits);
|
||||||
bits += 4; // 7 bits for highest SINR
|
bits += 4; // 4 bits for differential SINR
|
||||||
}
|
}
|
||||||
break; // resource found
|
break; // resource found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssertFatal(bits <= 32, "Not supporting CSI report with more than 32 bits\n");
|
int max_bits = sizeof(((csi_payload_t *)0)->part1_payload) * 8;
|
||||||
csi_payload_t csi = {.part1_payload = temp_payload, .p1_bits = bits, csi.p2_bits = 0};
|
AssertFatal(bits <= max_bits, "Not supporting CSI report with more than %d bits (payload: %d bits)\n", max_bits, bits);
|
||||||
|
csi_payload_t csi = {.part1_payload = temp_payload, .part2_payload = 0, .p1_bits = bits, csi.p2_bits = 0};
|
||||||
return csi;
|
return csi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2891,6 +2909,14 @@ csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
|
|||||||
return csi;
|
return csi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Comparison function for sorting SSB RSRP measurements in descending order
|
||||||
|
static int compare_ssb_rsrp(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const NR_RSRP_meas_t *ma = (const NR_RSRP_meas_t *)a;
|
||||||
|
const NR_RSRP_meas_t *mb = (const NR_RSRP_meas_t *)b;
|
||||||
|
return mb->ssb_rsrp_dBm - ma->ssb_rsrp_dBm;
|
||||||
|
}
|
||||||
|
|
||||||
static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
||||||
struct NR_CSI_ReportConfig *csi_reportconfig,
|
struct NR_CSI_ReportConfig *csi_reportconfig,
|
||||||
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
|
||||||
@@ -2899,7 +2925,7 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
|||||||
int nb_ssb = 0; // nb of ssb in the resource
|
int nb_ssb = 0; // nb of ssb in the resource
|
||||||
int nb_meas = 0; // nb of ssb to report measurements on
|
int nb_meas = 0; // nb of ssb to report measurements on
|
||||||
int bits = 0;
|
int bits = 0;
|
||||||
uint32_t temp_payload = 0;
|
uint64_t temp_payload = 0;
|
||||||
|
|
||||||
for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {
|
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];
|
struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx];
|
||||||
@@ -2907,7 +2933,7 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
|||||||
|
|
||||||
if (csi_reportconfig->groupBasedBeamReporting.present == NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled) {
|
if (csi_reportconfig->groupBasedBeamReporting.present == NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled) {
|
||||||
if (csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS != NULL)
|
if (csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS != NULL)
|
||||||
nb_meas = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
|
nb_meas = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + 1;
|
||||||
else
|
else
|
||||||
nb_meas = 1;
|
nb_meas = 1;
|
||||||
} else
|
} else
|
||||||
@@ -2924,50 +2950,56 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AssertFatal(nb_ssb>0,"No SSB found in the resource set\n");
|
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");
|
AssertFatal(nb_meas <= 4,"Can't report more than 4 RSRPs\n");
|
||||||
int ssbri_bits = ceil(log2(nb_ssb));
|
int ssbri_bits = ceil(log2(nb_ssb));
|
||||||
|
|
||||||
int ssb_rsrp[2][nb_meas]; // the array contains index and RSRP of each SSB to be reported (nb_meas highest RSRPs)
|
// map SSB index to SSB resource table index, copy measurements, sort in descending order
|
||||||
memset(ssb_rsrp, 0, sizeof(ssb_rsrp));
|
NR_RSRP_meas_t sorted_rsrp_measurements[nb_ssb];
|
||||||
|
int sorted_idx = 0;
|
||||||
//TODO replace the following 2 lines with a function to order the nb_meas highest SSB RSRPs
|
for (int measured_ssb_idx = 0; measured_ssb_idx < MAX_NB_SSB; measured_ssb_idx++) {
|
||||||
for (int i=0; i<nb_ssb; i++) {
|
// searching for the SSB index in the SSB resource table
|
||||||
if(*SSB_resource.list.array[i] == mac->mib_ssb) {
|
for (int ssb_resource = 0; ssb_resource < nb_ssb; ssb_resource++) {
|
||||||
ssb_rsrp[0][0] = i;
|
if (*SSB_resource.list.array[ssb_resource] == measured_ssb_idx) {
|
||||||
break;
|
sorted_rsrp_measurements[sorted_idx].ssb_index = ssb_resource;
|
||||||
|
sorted_rsrp_measurements[sorted_idx].ssb_rsrp_dBm = mac->ssb_measurements[measured_ssb_idx].ssb_rsrp_dBm;
|
||||||
|
sorted_rsrp_measurements[sorted_idx].ssb_sinr_dB = mac->ssb_measurements[measured_ssb_idx].ssb_sinr_dB;
|
||||||
|
sorted_idx++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssertFatal(*SSB_resource.list.array[ssb_rsrp[0][0]] == mac->mib_ssb, "Couldn't find corresponding SSB in csi_SSB_ResourceList\n");
|
qsort(sorted_rsrp_measurements, nb_ssb, sizeof(NR_RSRP_meas_t), compare_ssb_rsrp);
|
||||||
ssb_rsrp[1][0] = mac->ssb_measurements.ssb_rsrp_dBm;
|
|
||||||
|
|
||||||
uint8_t ssbi;
|
uint32_t ssbi;
|
||||||
|
|
||||||
if (ssbri_bits > 0) {
|
if (ssbri_bits > 0) {
|
||||||
ssbi = ssb_rsrp[0][0];
|
ssbi = sorted_rsrp_measurements[0].ssb_index;
|
||||||
temp_payload = reverse_bits(ssbi, ssbri_bits);
|
temp_payload = reverse_bits(ssbi, ssbri_bits);
|
||||||
bits += ssbri_bits;
|
bits += ssbri_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t rsrp_idx = get_rsrp_index(ssb_rsrp[1][0]);
|
uint8_t rsrp_idx = get_rsrp_index(sorted_rsrp_measurements[0].ssb_rsrp_dBm);
|
||||||
temp_payload |= (reverse_bits(rsrp_idx, 7) << bits);
|
temp_payload |= (reverse_bits(rsrp_idx, 7) << bits);
|
||||||
bits += 7; // 7 bits for highest RSRP
|
bits += 7; // 7 bits for highest RSRP
|
||||||
|
|
||||||
// from the second SSB, differential report
|
// from the second SSB, differential report
|
||||||
for (int i=1; i<nb_meas; i++){
|
for (int i = 1; i < nb_meas; i++) {
|
||||||
ssbi = ssb_rsrp[0][i];
|
ssbi = sorted_rsrp_measurements[i].ssb_index;
|
||||||
temp_payload = reverse_bits(ssbi, ssbri_bits);
|
temp_payload |= (reverse_bits(ssbi, ssbri_bits) << bits);
|
||||||
bits += ssbri_bits;
|
bits += ssbri_bits;
|
||||||
|
|
||||||
rsrp_idx = get_rsrp_diff_index(ssb_rsrp[1][0],ssb_rsrp[1][i]);
|
rsrp_idx = get_rsrp_diff_index(sorted_rsrp_measurements[0].ssb_rsrp_dBm,sorted_rsrp_measurements[i].ssb_rsrp_dBm);
|
||||||
temp_payload |= (reverse_bits(rsrp_idx, 4) << bits);
|
temp_payload |= (reverse_bits(rsrp_idx, 4) << bits);
|
||||||
bits += 4; // 7 bits for highest RSRP
|
bits += 4; // 4 bits for subsequent RSRP
|
||||||
}
|
}
|
||||||
break; // resorce found
|
break; // resorce found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssertFatal(bits <= 32, "Not supporting CSI report with more than 32 bits\n");
|
int max_bits = sizeof(((csi_payload_t *)0)->part1_payload) * 8;
|
||||||
csi_payload_t csi = {.part1_payload = temp_payload, .p1_bits = bits, csi.p2_bits = 0};
|
AssertFatal(bits <= max_bits, "Not supporting CSI report with more than %d bits (payload: %d bits)\n", max_bits, bits);
|
||||||
|
|
||||||
|
csi_payload_t csi = {.part1_payload = temp_payload, .part2_payload = 0, .p1_bits = bits, .p2_bits = 0};
|
||||||
return csi;
|
return csi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ void update_mac_ul_timers(NR_UE_MAC_INST_t *mac)
|
|||||||
if (phr_info->is_configured) {
|
if (phr_info->is_configured) {
|
||||||
bool prohibit_expired = nr_timer_tick(&phr_info->prohibitPHR_Timer);
|
bool prohibit_expired = nr_timer_tick(&phr_info->prohibitPHR_Timer);
|
||||||
if (prohibit_expired) {
|
if (prohibit_expired) {
|
||||||
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
|
int16_t pathloss = compute_nr_SSB_PL(mac);
|
||||||
if (abs(pathloss - phr_info->PathlossLastValue) > phr_info->PathlossChange_db) {
|
if (abs(pathloss - phr_info->PathlossLastValue) > phr_info->PathlossChange_db) {
|
||||||
phr_info->phr_reporting |= (1 << phr_cause_prohibit_timer);
|
phr_info->phr_reporting |= (1 << phr_cause_prohibit_timer);
|
||||||
}
|
}
|
||||||
@@ -2905,7 +2905,7 @@ static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac,
|
|||||||
headroom,
|
headroom,
|
||||||
tx_power);
|
tx_power);
|
||||||
|
|
||||||
phr_info->PathlossLastValue = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
|
phr_info->PathlossLastValue = compute_nr_SSB_PL(mac);
|
||||||
// Restart both timers according to 38.321
|
// Restart both timers according to 38.321
|
||||||
nr_timer_start(&phr_info->periodicPHR_Timer);
|
nr_timer_start(&phr_info->periodicPHR_Timer);
|
||||||
nr_timer_start(&phr_info->prohibitPHR_Timer);
|
nr_timer_start(&phr_info->prohibitPHR_Timer);
|
||||||
|
|||||||
Reference in New Issue
Block a user