Merge remote-tracking branch 'origin/meas-report-A2' into integration_2025_w38 (!3596)

L3 measurements and measReport A2

- Implementation of L3 measurements for active cell
- UE sends the measurement report for event A2
This commit is contained in:
Robert Schmidt
2025-09-18 09:38:39 +02:00
22 changed files with 494 additions and 68 deletions
+13
View File
@@ -88,6 +88,8 @@ static inline const char *rnti_types(nr_rnti_type_t rr)
#define NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP 12 #define NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP 12
#define NR_MAX_NB_LAYERS 4 // 8 #define NR_MAX_NB_LAYERS 4 // 8
#define BOUNDED_EVAL(a, b, c) (min(c, max(a, b)))
// Since the IQ samples are represented by SQ15 R+I (see https://en.wikipedia.org/wiki/Q_(number_format)) we need to compensate when // Since the IQ samples are represented by SQ15 R+I (see https://en.wikipedia.org/wiki/Q_(number_format)) we need to compensate when
// calcualting signal energy. Instead of shifting each sample right by 15, we can normalize the result in dB scale once its // calcualting signal energy. Instead of shifting each sample right by 15, we can normalize the result in dB scale once its
// calcualted. Signal energy is calculated using RMS^2, where each sample is squared before taking the average of the sum, therefore // calcualted. Signal energy is calculated using RMS^2, where each sample is squared before taking the average of the sum, therefore
@@ -175,6 +177,17 @@ typedef struct {
uint32_t step; uint32_t step;
} NR_timer_t; } NR_timer_t;
typedef struct val_init {
int val;
bool init;
} val_init_t;
typedef struct meas_s {
uint16_t Nid_cell;
val_init_t ss_rsrp_dBm;
val_init_t csi_rsrp_dBm;
} meas_t;
/** /**
* @brief To start a timer * @brief To start a timer
* @param timer Timer to be started * @param timer Timer to be started
@@ -20,7 +20,7 @@
#define FAPI_NR_RX_PDU_TYPE_DLSCH 0x03 #define FAPI_NR_RX_PDU_TYPE_DLSCH 0x03
#define FAPI_NR_DCI_IND 0x04 #define FAPI_NR_DCI_IND 0x04
#define FAPI_NR_RX_PDU_TYPE_RAR 0x05 #define FAPI_NR_RX_PDU_TYPE_RAR 0x05
#define FAPI_NR_CSIRS_IND 0x06 #define FAPI_NR_MEAS_IND 0x06
#define FAPI_NR_SIBS_MASK_SIB1 0x1 #define FAPI_NR_SIBS_MASK_SIB1 0x1
@@ -49,16 +49,23 @@ typedef enum {
NFAPI_NR_FORMAT_0_1_AND_1_1, NFAPI_NR_FORMAT_0_1_AND_1_1,
} nfapi_nr_dci_formats_e; } nfapi_nr_dci_formats_e;
typedef enum {
NFAPI_NR_CSI_MEAS,
NFAPI_NR_SS_MEAS
} nfapi_nr_meas_type_e;
typedef struct { typedef struct {
uint32_t rsrp; uint32_t gNB_index;
int rsrp_dBm; uint16_t Nid_cell;
nfapi_nr_meas_type_e meas_type;
bool is_neighboring_cell;
uint8_t rsrp_dBm;
uint8_t rank_indicator; uint8_t rank_indicator;
uint16_t i1; uint16_t i1;
uint8_t i2; uint8_t i2;
uint8_t cqi; uint8_t cqi;
rlm_t radiolink_monitoring; rlm_t radiolink_monitoring;
} fapi_nr_csirs_measurements_t; } fapi_nr_l1_measurements_t;
typedef struct { typedef struct {
/// frequency_domain_resource; /// frequency_domain_resource;
@@ -145,7 +152,7 @@ typedef struct {
fapi_nr_pdsch_pdu_t pdsch_pdu; fapi_nr_pdsch_pdu_t pdsch_pdu;
fapi_nr_ssb_pdu_t ssb_pdu; fapi_nr_ssb_pdu_t ssb_pdu;
fapi_nr_sib_pdu_t sib_pdu; fapi_nr_sib_pdu_t sib_pdu;
fapi_nr_csirs_measurements_t csirs_measurements; fapi_nr_l1_measurements_t l1_measurements;
}; };
} fapi_nr_rx_indication_body_t; } fapi_nr_rx_indication_body_t;
@@ -37,6 +37,7 @@
#include "PHY/phy_extern_nr_ue.h" #include "PHY/phy_extern_nr_ue.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "PHY/sse_intrin.h" #include "PHY/sse_intrin.h"
#include "SCHED_NR_UE/defs.h"
#define K1 ((long long int) 512) #define K1 ((long long int) 512)
#define K2 ((long long int) (1024-K1)) #define K2 ((long long int) (1024-K1))
@@ -254,6 +255,24 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
ue->measurements.ssb_rsrp_dBm[ssb_index], ue->measurements.ssb_rsrp_dBm[ssb_index],
rsrp_db_per_re, rsrp_db_per_re,
ue->measurements.ssb_sinr_dB[ssb_index]); ue->measurements.ssb_sinr_dB[ssb_index]);
// Send SS measurements to MAC
if (!ue->if_inst || !ue->if_inst->dl_indication)
return;
fapi_nr_l1_measurements_t l1_measurements = {
.gNB_index = proc->gNB_id,
.meas_type = NFAPI_NR_SS_MEAS,
.Nid_cell = ue->frame_parms.Nid_cell,
.is_neighboring_cell = false,
};
int ssb_rsrp_dBm = ue->measurements.ssb_rsrp_dBm[ssb_index];
l1_measurements.rsrp_dBm = BOUNDED_EVAL(16, ssb_rsrp_dBm + 157, 113); // TS 38.133 - Table 10.1.6.1-1
nr_downlink_indication_t dl_indication = {0};
fapi_nr_rx_indication_t rx_ind = {0};
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, &l1_measurements, NULL);
ue->if_inst->dl_indication(&dl_indication);
} }
// This function computes the received noise power // This function computes the received noise power
+17 -11
View File
@@ -979,18 +979,24 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
} }
// Send CSI measurements to MAC // Send CSI measurements to MAC
fapi_nr_csirs_measurements_t csirs_measurements; if (!ue->if_inst || !ue->if_inst->dl_indication)
csirs_measurements.rsrp = rsrp; return;
csirs_measurements.rsrp_dBm = rsrp_dBm;
csirs_measurements.rank_indicator = rank_indicator; fapi_nr_l1_measurements_t l1_measurements = {
csirs_measurements.i1 = *i1; .gNB_index = proc->gNB_id,
csirs_measurements.i2 = *i2; .meas_type = NFAPI_NR_CSI_MEAS,
csirs_measurements.cqi = cqi; .Nid_cell = frame_parms->Nid_cell,
csirs_measurements.radiolink_monitoring = RLM_no_monitoring; // TODO do be activated in case of RLM based on CSI-RS .is_neighboring_cell = false,
.rsrp_dBm = BOUNDED_EVAL(16, rsrp_dBm + 157, 113), // TS 38.133 - Table 10.1.6.1-1
.rank_indicator = rank_indicator,
.i1 = *i1,
.i2 = *i2,
.cqi = cqi,
.radiolink_monitoring = RLM_no_monitoring, // TODO do be activated in case of RLM based on CSI-RS
};
nr_downlink_indication_t dl_indication; nr_downlink_indication_t dl_indication;
fapi_nr_rx_indication_t rx_ind = {0}; fapi_nr_rx_indication_t rx_ind = {0};
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_CSIRS_IND, ue, NULL, NULL, 1, proc, (void *)&csirs_measurements, NULL); nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, (void *)&l1_measurements, NULL);
if (ue->if_inst && ue->if_inst->dl_indication) ue->if_inst->dl_indication(&dl_indication);
ue->if_inst->dl_indication(&dl_indication);
} }
+2 -2
View File
@@ -186,8 +186,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
rx->ssb_pdu.decoded_pdu = false; rx->ssb_pdu.decoded_pdu = false;
} }
} break; } break;
case FAPI_NR_CSIRS_IND: case FAPI_NR_MEAS_IND:
memcpy(&rx->csirs_measurements, typeSpecific, sizeof(fapi_nr_csirs_measurements_t)); memcpy(&rx->l1_measurements, typeSpecific, sizeof(fapi_nr_l1_measurements_t));
break; break;
default: default:
break; break;
@@ -178,3 +178,12 @@ void *rrc_nrue(void *notUsed)
{ {
return NULL; return NULL;
} }
void nr_mac_rrc_meas_ind_ue(module_id_t module_id,
uint32_t gNB_index,
uint16_t Nid_cell,
bool csi_meas,
bool is_neighboring_cell,
uint8_t rsrp_dBm)
{
}
+4
View File
@@ -62,3 +62,7 @@ MESSAGE_DEF(NR_RRC_MAC_SBCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSBc
// Message to GNB_APP to update SIB19 satellite position information // Message to GNB_APP to update SIB19 satellite position information
MESSAGE_DEF(GNB_SAT_POSITION_UPDATE, MESSAGE_PRIORITY_MED, gnb_sat_position_update_t, gnb_sat_position_update) MESSAGE_DEF(GNB_SAT_POSITION_UPDATE, MESSAGE_PRIORITY_MED, gnb_sat_position_update_t, gnb_sat_position_update)
// nrUE
MESSAGE_DEF(NR_RRC_MAC_MEAS_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacMeasDataInd, nr_rrc_mac_meas_data_ind)
+10
View File
@@ -44,6 +44,8 @@
#define NR_RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_bcch_data_ind #define NR_RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_bcch_data_ind
#define NR_RRC_MAC_SBCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_sbcch_data_ind #define NR_RRC_MAC_SBCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_sbcch_data_ind
#define NR_RRC_MAC_MEAS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_meas_data_ind
#define RRC_MAC_BCCH_MBMS_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_req #define RRC_MAC_BCCH_MBMS_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_req
#define RRC_MAC_BCCH_MBMS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_ind #define RRC_MAC_BCCH_MBMS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_ind
@@ -142,6 +144,14 @@ typedef struct NRRrcMacSBcchDataInd_s {
uint8_t rsrp; uint8_t rsrp;
} NRRrcMacSBcchDataInd; } NRRrcMacSBcchDataInd;
typedef struct NRRrcMacMeasDataInd_s {
uint8_t gnb_index;
uint8_t rsrp_dBm;
uint16_t Nid_cell;
bool is_csi_meas;
bool is_neighboring_cell;
} NRRrcMacMeasDataInd;
typedef struct RrcMacBcchMbmsDataReq_s { typedef struct RrcMacBcchMbmsDataReq_s {
uint32_t frame; uint32_t frame;
uint32_t sdu_size; uint32_t sdu_size;
+2 -2
View File
@@ -594,8 +594,8 @@ typedef struct NR_UE_MAC_INST_s {
nr_csi_report_t csi_report_template[MAX_CSI_REPORTCONFIG]; nr_csi_report_t csi_report_template[MAX_CSI_REPORTCONFIG];
/// measurements from CSI-RS /// measurements from SS or CSI-RS
fapi_nr_csirs_measurements_t csirs_measurements; fapi_nr_l1_measurements_t l1_measurements;
//// FAPI-like interface message //// FAPI-like interface message
fapi_nr_ul_config_request_t *ul_config_request; fapi_nr_ul_config_request_t *ul_config_request;
+2 -4
View File
@@ -117,10 +117,8 @@ csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t c
nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci);
int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac, void nr_ue_process_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_l1_measurements_t *l1_measurements);
frame_t frame,
int slot,
fapi_nr_csirs_measurements_t *csirs_measurements);
void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger, int frame, int slot); void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger, int frame, int slot);
bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac,
+1 -1
View File
@@ -302,7 +302,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca
release_ul_BWP(mac, i); release_ul_BWP(mac, i);
memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
memset(&mac->csirs_measurements, 0, sizeof(mac->csirs_measurements)); memset(&mac->l1_measurements, 0, sizeof(mac->l1_measurements));
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
for (int i = mac->TAG_list.count; i > 0 ; i--) for (int i = mac->TAG_list.count; i > 0 ; i--)
asn_sequence_del(&mac->TAG_list, i - 1, 1); asn_sequence_del(&mac->TAG_list, i - 1, 1);
+26 -32
View File
@@ -1504,13 +1504,17 @@ nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t
return format; return format;
} }
int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac, void nr_ue_process_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_l1_measurements_t *l1_measurements)
frame_t frame, {
int slot, LOG_D(NR_MAC, "(%d.%d) Received CSI-RS measurements\n", frame, slot);
fapi_nr_csirs_measurements_t *csirs_measurements) { memcpy(&mac->l1_measurements, l1_measurements, sizeof(*l1_measurements));
LOG_D(NR_MAC,"(%d.%d) Received CSI-RS measurements\n", frame, slot); bool csi_meas = l1_measurements->meas_type == NFAPI_NR_CSI_MEAS;
memcpy(&mac->csirs_measurements, csirs_measurements, sizeof(*csirs_measurements)); nr_mac_rrc_meas_ind_ue(mac->ue_id,
return 0; l1_measurements->gNB_index,
l1_measurements->Nid_cell,
csi_meas,
l1_measurements->is_neighboring_cell,
l1_measurements->rsrp_dBm);
} }
static void set_harq_status(NR_UE_MAC_INST_t *mac, static void set_harq_status(NR_UE_MAC_INST_t *mac,
@@ -2993,9 +2997,9 @@ static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
AssertFatal(csi_report, "Couldn't find CSI report with ID %ld\n", csi_reportconfig->reportConfigId); AssertFatal(csi_report, "Couldn't find CSI report with ID %ld\n", csi_reportconfig->reportConfigId);
int cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen; int cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
int ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen; int ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen;
int pmi_x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[mac->csirs_measurements.rank_indicator]; int pmi_x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[mac->l1_measurements.rank_indicator];
int pmi_x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[mac->csirs_measurements.rank_indicator]; int pmi_x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[mac->l1_measurements.rank_indicator];
int cqi_bitlen = csi_report->csi_meas_bitlen.cqi_bitlen[mac->csirs_measurements.rank_indicator]; int cqi_bitlen = csi_report->csi_meas_bitlen.cqi_bitlen[mac->l1_measurements.rank_indicator];
if (get_softmodem_params()->emulate_l1) { if (get_softmodem_params()->emulate_l1) {
static const uint8_t mcs_to_cqi[] = {0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, static const uint8_t mcs_to_cqi[] = {0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
@@ -3003,9 +3007,9 @@ static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
CHECK_INDEX(nr_bler_data, NR_NUM_MCS - 1); CHECK_INDEX(nr_bler_data, NR_NUM_MCS - 1);
int mcs = get_mcs_from_sinr(nr_bler_data, (mac->nr_ue_emul_l1.cqi - 640) * 0.1); int mcs = get_mcs_from_sinr(nr_bler_data, (mac->nr_ue_emul_l1.cqi - 640) * 0.1);
CHECK_INDEX(mcs_to_cqi, mcs); CHECK_INDEX(mcs_to_cqi, mcs);
mac->csirs_measurements.rank_indicator = mac->nr_ue_emul_l1.ri; mac->l1_measurements.rank_indicator = mac->nr_ue_emul_l1.ri;
mac->csirs_measurements.i1 = mac->nr_ue_emul_l1.pmi; mac->l1_measurements.i1 = mac->nr_ue_emul_l1.pmi;
mac->csirs_measurements.cqi = mcs_to_cqi[mcs]; mac->l1_measurements.cqi = mcs_to_cqi[mcs];
} }
int padding_bitlen = 0; int padding_bitlen = 0;
@@ -3014,19 +3018,19 @@ static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
p1_bits = cri_bitlen + ri_bitlen + cqi_bitlen; p1_bits = cri_bitlen + ri_bitlen + cqi_bitlen;
p2_bits = pmi_x1_bitlen + pmi_x2_bitlen; p2_bits = pmi_x1_bitlen + pmi_x2_bitlen;
temp_payload_1 = (0/*mac->csi_measurements.cri*/ << (cqi_bitlen + ri_bitlen)) | temp_payload_1 = (0/*mac->csi_measurements.cri*/ << (cqi_bitlen + ri_bitlen)) |
(mac->csirs_measurements.rank_indicator << cqi_bitlen) | (mac->l1_measurements.rank_indicator << cqi_bitlen) |
(mac->csirs_measurements.cqi); (mac->l1_measurements.cqi);
temp_payload_2 = (mac->csirs_measurements.i1 << pmi_x2_bitlen) | temp_payload_2 = (mac->l1_measurements.i1 << pmi_x2_bitlen) |
mac->csirs_measurements.i2; mac->l1_measurements.i2;
} }
else { else {
p1_bits = nr_get_csi_bitlen(csi_report); p1_bits = nr_get_csi_bitlen(csi_report);
padding_bitlen = p1_bits - (cri_bitlen + ri_bitlen + pmi_x1_bitlen + pmi_x2_bitlen + cqi_bitlen); padding_bitlen = p1_bits - (cri_bitlen + ri_bitlen + pmi_x1_bitlen + pmi_x2_bitlen + cqi_bitlen);
temp_payload_1 = (0/*mac->csi_measurements.cri*/ << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen + ri_bitlen)) | temp_payload_1 = (0/*mac->csi_measurements.cri*/ << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen + ri_bitlen)) |
(mac->csirs_measurements.rank_indicator << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen)) | (mac->l1_measurements.rank_indicator << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen)) |
(mac->csirs_measurements.i1 << (cqi_bitlen + pmi_x2_bitlen)) | (mac->l1_measurements.i1 << (cqi_bitlen + pmi_x2_bitlen)) |
(mac->csirs_measurements.i2 << (cqi_bitlen)) | (mac->l1_measurements.i2 << (cqi_bitlen)) |
(mac->csirs_measurements.cqi); (mac->l1_measurements.cqi);
} }
temp_payload_1 = reverse_bits(temp_payload_1, p1_bits); temp_payload_1 = reverse_bits(temp_payload_1, p1_bits);
@@ -3085,17 +3089,7 @@ static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac,
} }
// TODO: Improvements will be needed to cri_ssbri_bitlen>0 // TODO: Improvements will be needed to cri_ssbri_bitlen>0
// TS 38.133 - Table 10.1.6.1-1 temp_payload = reverse_bits(mac->l1_measurements.rsrp_dBm, n_bits); // rsrp_dBm as in TS 38.133 - Table 10.1.6.1-1
int rsrp_dBm = mac->csirs_measurements.rsrp_dBm;
if (rsrp_dBm < -140) {
temp_payload = 16;
} else if (rsrp_dBm > -44) {
temp_payload = 113;
} else {
temp_payload = mac->csirs_measurements.rsrp_dBm + 157;
}
temp_payload = reverse_bits(temp_payload, n_bits);
LOG_D(NR_MAC, "cri_ssbri_bitlen = %d\n", cri_ssbri_bitlen); LOG_D(NR_MAC, "cri_ssbri_bitlen = %d\n", cri_ssbri_bitlen);
LOG_D(NR_MAC, "rsrp_bitlen = %d\n", rsrp_bitlen); LOG_D(NR_MAC, "rsrp_bitlen = %d\n", rsrp_bitlen);
+9 -11
View File
@@ -1174,13 +1174,11 @@ static void handle_rlm(rlm_t rlm_result, int frame, NR_UE_MAC_INST_t *mac)
nr_mac_rrc_sync_ind(mac->ue_id, frame, is_sync); nr_mac_rrc_sync_ind(mac->ue_id, frame, is_sync);
} }
static int8_t handle_csirs_measurements(NR_UE_MAC_INST_t *mac, static int8_t handle_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_l1_measurements_t *l1_measurements)
frame_t frame,
int slot,
fapi_nr_csirs_measurements_t *csirs_measurements)
{ {
handle_rlm(csirs_measurements->radiolink_monitoring, frame, mac); handle_rlm(l1_measurements->radiolink_monitoring, frame, mac);
return nr_ue_process_csirs_measurements(mac, frame, slot, csirs_measurements); nr_ue_process_l1_measurements(mac, frame, slot, l1_measurements);
return 0;
} }
void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack) void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack)
@@ -1316,11 +1314,11 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio
} }
ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR; ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR;
break; break;
case FAPI_NR_CSIRS_IND: case FAPI_NR_MEAS_IND:
ret_mask |= (handle_csirs_measurements(mac, ret_mask |= (handle_l1_measurements(mac,
dl_info->frame, dl_info->frame,
dl_info->slot, dl_info->slot,
&rx_indication_body.csirs_measurements)) << FAPI_NR_CSIRS_IND; &rx_indication_body.l1_measurements)) << FAPI_NR_MEAS_IND;
break; break;
default: default:
break; break;
+57
View File
@@ -785,6 +785,63 @@ int do_RRCSetupComplete(uint8_t *buffer,
return((enc_rval.encoded+7)/8); return((enc_rval.encoded+7)/8);
} }
// TODO: This function is only implemented for event A2
int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport,
long trigger_to_measid,
long trigger_quantity,
long rs_type,
uint16_t Nid_cell,
int rsrp_dBm,
uint8_t *buffer,
size_t buffer_size)
{
asn_enc_rval_t enc_rval;
NR_UL_DCCH_Message_t ul_dcch_msg;
memset((void *)&ul_dcch_msg, 0, sizeof(NR_UL_DCCH_Message_t));
ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1;
ul_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_DCCH_MessageType__c1));
ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_measurementReport;
memset(measurementReport, 0, sizeof(struct NR_MeasurementReport));
ul_dcch_msg.message.choice.c1->choice.measurementReport = measurementReport;
measurementReport->criticalExtensions.present = NR_MeasurementReport__criticalExtensions_PR_measurementReport;
NR_MeasurementReport_IEs_t *measurementReport_ie = CALLOC(1, sizeof(struct NR_MeasurementReport_IEs));
measurementReport->criticalExtensions.choice.measurementReport = measurementReport_ie;
measurementReport_ie->measResults.measId = trigger_to_measid;
NR_MeasResultServMO_t *measResultServMo = CALLOC(1, sizeof(struct NR_MeasResultServMO));
NR_MeasResultNR_t *measResultServingCell = &measResultServMo->measResultServingCell;
measResultServingCell->physCellId = CALLOC(1, sizeof(NR_PhysCellId_t));
*measResultServingCell->physCellId = Nid_cell;
struct NR_MeasQuantityResults *active_mq_res = CALLOC(1, sizeof(struct NR_MeasQuantityResults));
if (trigger_quantity == NR_MeasTriggerQuantityOffset_PR_rsrp) {
active_mq_res->rsrp = CALLOC(1, sizeof(NR_RSRP_Range_t));
*active_mq_res->rsrp = rsrp_dBm + 157;
if (rs_type == NR_NR_RS_Type_ssb)
measResultServingCell->measResult.cellResults.resultsSSB_Cell = active_mq_res;
else
measResultServingCell->measResult.cellResults.resultsCSI_RS_Cell = active_mq_res;
}
ASN_SEQUENCE_ADD(&measurementReport_ie->measResults.measResultServingMOList.list, measResultServMo);
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, buffer_size);
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg);
}
LOG_I(NR_RRC, "MeasurementReport Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded + 7) / 8);
return ((enc_rval.encoded + 7) / 8);
}
int do_NR_DLInformationTransfer(uint8_t *buffer, int do_NR_DLInformationTransfer(uint8_t *buffer,
size_t buffer_len, size_t buffer_len,
uint8_t transaction_id, uint8_t transaction_id,
+11
View File
@@ -50,11 +50,13 @@
#include "NR_ReestablishmentCause.h" #include "NR_ReestablishmentCause.h"
#include "NR_SRB-ToAddModList.h" #include "NR_SRB-ToAddModList.h"
#include "NR_SecurityConfig.h" #include "NR_SecurityConfig.h"
#include "NR_MeasurementReport.h"
#include "NR_MeasurementTimingConfiguration.h" #include "NR_MeasurementTimingConfiguration.h"
#include "ds/seq_arr.h" #include "ds/seq_arr.h"
#include "ds/byte_array.h" #include "ds/byte_array.h"
#include "rrc_messages_types.h" #include "rrc_messages_types.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
#include "common/utils/nr/nr_common.h"
struct asn_TYPE_descriptor_s; struct asn_TYPE_descriptor_s;
typedef struct { typedef struct {
@@ -127,6 +129,15 @@ int do_NR_MeasurementTimingConfiguration(const NR_MeasurementTimingConfiguration
int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI_part1); int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI_part1);
int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport,
long trigger_to_measid,
long trigger_quantity,
long rs_type,
uint16_t Nid_cell,
int rsrp_dBm,
uint8_t *buffer,
size_t buffer_size);
int do_NR_RRCReconfigurationComplete_for_nsa(uint8_t *buffer, size_t buffer_size, NR_RRC_TransactionIdentifier_t Transaction_id); int do_NR_RRCReconfigurationComplete_for_nsa(uint8_t *buffer, size_t buffer_size, NR_RRC_TransactionIdentifier_t Transaction_id);
int do_NR_RRCReconfigurationComplete(uint8_t *buffer, size_t buffer_size, const uint8_t Transaction_id); int do_NR_RRCReconfigurationComplete(uint8_t *buffer, size_t buffer_size, const uint8_t Transaction_id);
+11
View File
@@ -37,6 +37,17 @@
typedef uint32_t channel_t; typedef uint32_t channel_t;
void nr_mac_rrc_meas_ind_ue(module_id_t module_id, uint32_t gNB_index, uint16_t Nid_cell, bool csi_meas, bool is_neighboring_cell, uint8_t rsrp_dBm)
{
MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_MEAS_DATA_IND);
NR_RRC_MAC_MEAS_DATA_IND(message_p).gnb_index = gNB_index;
NR_RRC_MAC_MEAS_DATA_IND(message_p).Nid_cell = Nid_cell;
NR_RRC_MAC_MEAS_DATA_IND(message_p).is_csi_meas = csi_meas;
NR_RRC_MAC_MEAS_DATA_IND(message_p).is_neighboring_cell = is_neighboring_cell;
NR_RRC_MAC_MEAS_DATA_IND(message_p).rsrp_dBm = rsrp_dBm;
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p);
}
void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const bool in_sync) void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const bool in_sync)
{ {
MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_SYNC_IND); MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_SYNC_IND);
+6
View File
@@ -37,6 +37,12 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const channel_t channel, const channel_t channel,
const uint8_t* pduP, const uint8_t* pduP,
const sdu_size_t pdu_len); const sdu_size_t pdu_len);
void nr_mac_rrc_meas_ind_ue(module_id_t module_id,
uint32_t gNB_index,
uint16_t Nid_cell,
bool csi_meas,
bool is_neighboring_cell,
uint8_t rsrp_dBm);
void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id); void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id);
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload); void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload);
void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id); void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id);
+193
View File
@@ -807,6 +807,9 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int instance_id, int num_ant_
for (int i = 0; i < NB_CNX_UE; i++) { for (int i = 0; i < NB_CNX_UE; i++) {
rrcPerNB_t *ptr = &rrc->perNB[i]; rrcPerNB_t *ptr = &rrc->perNB[i];
ptr->SInfo = (NR_UE_RRC_SI_INFO){0}; ptr->SInfo = (NR_UE_RRC_SI_INFO){0};
ptr->l3_measurements = (l3_measurements_t){0};
ptr->l3_measurements.ssb_filter_coeff_rsrp = 1.0f;
ptr->l3_measurements.csi_RS_filter_coeff_rsrp = 1.0f;
init_SI_timers(&ptr->SInfo); init_SI_timers(&ptr->SInfo);
} }
@@ -1663,6 +1666,14 @@ static void handle_meas_reporting_remove(rrcPerNB_t *rrc, int id, NR_UE_Timers_C
// TODO stop the periodical reporting timer or timer T321, whichever is running, // TODO stop the periodical reporting timer or timer T321, whichever is running,
// and reset the associated information (e.g. timeToTrigger) for this measId // and reset the associated information (e.g. timeToTrigger) for this measId
nr_timer_stop(&timers->T321); nr_timer_stop(&timers->T321);
l3_measurements_t *l3_measurements = &rrc->l3_measurements;
nr_timer_stop(&l3_measurements->TA2);
nr_timer_stop(&l3_measurements->periodic_report_timer);
l3_measurements->reports_sent = 0;
l3_measurements->max_reports = 0;
l3_measurements->report_interval_ms = 0;
} }
static void handle_measobj_remove(rrcPerNB_t *rrc, struct NR_MeasObjectToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers) static void handle_measobj_remove(rrcPerNB_t *rrc, struct NR_MeasObjectToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers)
@@ -1814,6 +1825,14 @@ static void handle_quantityconfig(rrcPerNB_t *rrc, NR_QuantityConfig_t *quantity
if (!rrc->QuantityConfig[i]) if (!rrc->QuantityConfig[i])
rrc->QuantityConfig[i] = calloc(1, sizeof(*rrc->QuantityConfig[i])); rrc->QuantityConfig[i] = calloc(1, sizeof(*rrc->QuantityConfig[i]));
rrc->QuantityConfig[i]->quantityConfigCell = quantityNR->quantityConfigCell; rrc->QuantityConfig[i]->quantityConfigCell = quantityNR->quantityConfigCell;
// TODO: It remains to compute ssb_filter_coeff_rsrp and csi_RS_filter_coeff_rsrp for multiple quantityConfig
// TS 38.331 - 5.5.3.2 Layer 3 filtering
NR_QuantityConfigRS_t *qcc = &quantityNR->quantityConfigCell;
l3_measurements_t *l3_measurements = &rrc->l3_measurements;
if (qcc->ssb_FilterConfig.filterCoefficientRSRP)
l3_measurements->ssb_filter_coeff_rsrp = 1. / pow(2, (*qcc->ssb_FilterConfig.filterCoefficientRSRP) / 4);
if (qcc->csi_RS_FilterConfig.filterCoefficientRSRP)
l3_measurements->csi_RS_filter_coeff_rsrp = 1. / pow(2, (*qcc->csi_RS_FilterConfig.filterCoefficientRSRP) / 4);
if (quantityNR->quantityConfigRS_Index) if (quantityNR->quantityConfigRS_Index)
UPDATE_IE(rrc->QuantityConfig[i]->quantityConfigRS_Index, quantityNR->quantityConfigRS_Index, struct NR_QuantityConfigRS); UPDATE_IE(rrc->QuantityConfig[i]->quantityConfigRS_Index, quantityNR->quantityConfigRS_Index, struct NR_QuantityConfigRS);
} }
@@ -2238,6 +2257,146 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
return 0; return 0;
} }
static void apply_ema(val_init_t *vi_rsrp_dBm, float filter_coeff_rsrp, int rsrp_dBm)
{
int *quant = &vi_rsrp_dBm->val;
bool *meas_init = &vi_rsrp_dBm->init;
float coef = *meas_init ? filter_coeff_rsrp : 1.0f; // if not init, first measurement gets full weight
*quant = (1.0f - coef) * (*quant) + coef * rsrp_dBm;
*meas_init = true;
}
void nr_ue_meas_filtering(rrcPerNB_t *rrc, bool is_neighboring_cell, uint16_t Nid_cell, bool csi_meas, int rsrp_dBm)
{
if (is_neighboring_cell)
return;
l3_measurements_t *l3_measurements = &rrc->l3_measurements;
meas_t *meas_cell = &l3_measurements->serving_cell;
if (meas_cell->Nid_cell != Nid_cell) {
meas_cell->ss_rsrp_dBm.init = false;
meas_cell->csi_rsrp_dBm.init = false;
}
meas_cell->Nid_cell = Nid_cell;
if (csi_meas)
apply_ema(&meas_cell->csi_rsrp_dBm, l3_measurements->csi_RS_filter_coeff_rsrp, rsrp_dBm);
else
apply_ema(&meas_cell->ss_rsrp_dBm, l3_measurements->ssb_filter_coeff_rsrp, rsrp_dBm);
}
static long get_measurement_report_interval_ms(NR_ReportInterval_t interval)
{
switch (interval) {
case NR_ReportInterval_ms120:
return 120;
case NR_ReportInterval_ms240:
return 240;
case NR_ReportInterval_ms480:
return 480;
case NR_ReportInterval_ms640:
return 640;
case NR_ReportInterval_ms1024:
return 1024;
case NR_ReportInterval_ms2048:
return 2048;
case NR_ReportInterval_ms5120:
return 5120;
case NR_ReportInterval_ms10240:
return 10240;
case NR_ReportInterval_min1:
return 60000;
case NR_ReportInterval_min6:
return 360000;
case NR_ReportInterval_min12:
return 720000;
case NR_ReportInterval_min30:
return 1800000;
default:
return 1024;
}
}
static void nr_ue_check_meas_report(NR_UE_RRC_INST_t *rrc, const uint8_t gnb_index)
{
rrcPerNB_t *rrcNB = rrc->perNB + gnb_index;
l3_measurements_t *l3_measurements = &rrcNB->l3_measurements;
for (int i = 0; i < MAX_MEAS_CONFIG; i++) {
NR_ReportConfigToAddMod_t *report_config = rrcNB->ReportConfig[i];
if (report_config == NULL)
continue;
if (report_config->reportConfig.present != NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR)
continue;
NR_ReportConfigNR_t *report_config_nr = report_config->reportConfig.choice.reportConfigNR;
if (report_config_nr->reportType.present != NR_ReportConfigNR__reportType_PR_eventTriggered)
continue;
NR_EventTriggerConfig_t *event_trigger_config = report_config_nr->reportType.choice.eventTriggered;
if (event_trigger_config->eventId.present != NR_EventTriggerConfig__eventId_PR_eventA2)
continue;
struct NR_EventTriggerConfig__eventId__eventA2 *event_A2 = event_trigger_config->eventId.choice.eventA2;
if (event_A2->a2_Threshold.present != NR_MeasTriggerQuantity_PR_rsrp)
continue;
meas_t *serving_cell = &l3_measurements->serving_cell;
int serving_cell_rsrp = INT_MAX;
if (serving_cell->ss_rsrp_dBm.init == true) {
serving_cell_rsrp = serving_cell->ss_rsrp_dBm.val;
} else if (serving_cell->csi_rsrp_dBm.init == true) {
serving_cell_rsrp = serving_cell->csi_rsrp_dBm.val;
} else {
LOG_E(NR_RRC, "There are no RSRP measurements taken for the active cell\n");
}
// TS 38.133 - Table 10.1.6.1-1: SS-RSRP and CSI-RSRP measurement report mapping
int rsrp_threshold = event_A2->a2_Threshold.choice.rsrp - 157;
int rsrp_hysteresis = event_A2->hysteresis >> 1;
// TS 38.331 - 5.5.4.3 Event A2 (Serving becomes worse than threshold)
if (serving_cell_rsrp + rsrp_hysteresis < rsrp_threshold) {
if (!nr_timer_is_active(&l3_measurements->TA2) && (l3_measurements->reports_sent == 0)) {
nr_timer_setup(&l3_measurements->TA2, get_A2_event_time_to_trigger(event_A2->timeToTrigger), 10);
nr_timer_start(&l3_measurements->TA2);
int report_config_id = report_config->reportConfigId;
int meas_id = -1;
for (int j = 0; j < MAX_MEAS_ID; j++) {
NR_MeasIdToAddMod_t *meas_id_toAddMod = rrcNB->MeasId[j];
if (meas_id_toAddMod == NULL) {
continue;
}
if (meas_id_toAddMod->reportConfigId == report_config_id) {
meas_id = meas_id_toAddMod->measId;
}
}
AssertFatal(meas_id > 0, "meas_id did not found for report_config_id %i\n", report_config_id);
l3_measurements->trigger_to_measid = meas_id;
l3_measurements->trigger_quantity = event_A2->a2_Threshold.present;
l3_measurements->rs_type = event_trigger_config->rsType;
l3_measurements->reports_sent = 0;
l3_measurements->max_reports = (event_trigger_config->reportAmount == NR_EventTriggerConfig__reportAmount_infinity)
? INT_MAX
: (1 << event_trigger_config->reportAmount);
l3_measurements->report_interval_ms = get_measurement_report_interval_ms(event_trigger_config->reportInterval);
LOG_W(NR_RRC,
"(active_cell_rsrp) %i + (rsrp_hysteresis) %i < (rsrp_threshold) %i\n",
serving_cell_rsrp,
rsrp_hysteresis,
rsrp_threshold);
}
} else if (nr_timer_is_active(&l3_measurements->TA2) && (serving_cell_rsrp - rsrp_hysteresis > rsrp_threshold)) {
nr_timer_stop(&l3_measurements->TA2);
nr_timer_stop(&l3_measurements->periodic_report_timer);
l3_measurements->reports_sent = 0;
}
}
}
void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded) void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded)
{ {
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
@@ -2354,6 +2513,21 @@ void *rrc_nrue(void *notUsed)
nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(rrc, sbcch->gnb_index,sbcch->frame, sbcch->slot, sbcch->sdu, nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(rrc, sbcch->gnb_index,sbcch->frame, sbcch->slot, sbcch->sdu,
sbcch->sdu_size, sbcch->rx_slss_id); sbcch->sdu_size, sbcch->rx_slss_id);
case NR_RRC_MAC_MEAS_DATA_IND:
LOG_D(NR_RRC, "[%s][Nid_cell %i] Received %s measurements: RSRP = %i (dBm)\n",
NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_neighboring_cell? "Neighboring cell" : "Active cell",
NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell,
NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_csi_meas ? "CSI meas" : "SSB meas",
NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm - 157);
rrcPerNB_t *rrcNB = rrc->perNB + NR_RRC_MAC_MEAS_DATA_IND(msg_p).gnb_index;
nr_ue_meas_filtering(rrcNB,
NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_neighboring_cell,
NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell,
NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_csi_meas,
NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm - 157);
nr_ue_check_meas_report(rrc, NR_RRC_MAC_MEAS_DATA_IND(msg_p).gnb_index);
break; break;
case NR_RRC_MAC_CCCH_DATA_IND: { case NR_RRC_MAC_CCCH_DATA_IND: {
@@ -2992,3 +3166,22 @@ void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf)
NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance); NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance);
rrc->mac_input_nf = mac_input_nf; rrc->mac_input_nf = mac_input_nf;
} }
void rrc_ue_generate_measurementReport(rrcPerNB_t *rrc, instance_t ue_id)
{
uint8_t buffer[NR_RRC_BUF_SIZE];
NR_MeasurementReport_t measurementReport = {0};
l3_measurements_t *l3m = &rrc->l3_measurements;
int rsrp_dBm = l3m->rs_type == NR_NR_RS_Type_ssb ? l3m->serving_cell.ss_rsrp_dBm.val : l3m->serving_cell.csi_rsrp_dBm.val;
uint8_t size = do_nrMeasurementReport_SA(&measurementReport,
l3m->trigger_to_measid,
l3m->trigger_quantity,
l3m->rs_type,
l3m->serving_cell.Nid_cell,
rsrp_dBm,
buffer,
sizeof(buffer));
int srb_id = 1; // possibly TODO in SRB3 in some cases
nr_pdcp_data_req_srb(ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
}
+15
View File
@@ -192,6 +192,20 @@ typedef enum {
typedef enum { RB_NOT_PRESENT, RB_ESTABLISHED, RB_SUSPENDED } NR_RB_status_t; typedef enum { RB_NOT_PRESENT, RB_ESTABLISHED, RB_SUSPENDED } NR_RB_status_t;
typedef struct l3_measurements_s {
float ssb_filter_coeff_rsrp;
float csi_RS_filter_coeff_rsrp;
meas_t serving_cell;
long trigger_to_measid;
long trigger_quantity;
long rs_type;
int reports_sent;
int max_reports;
long report_interval_ms;
NR_timer_t TA2;
NR_timer_t periodic_report_timer;
} l3_measurements_t;
typedef struct rrcPerNB { typedef struct rrcPerNB {
NR_MeasObjectToAddMod_t *MeasObj[MAX_MEAS_OBJ]; NR_MeasObjectToAddMod_t *MeasObj[MAX_MEAS_OBJ];
NR_ReportConfigToAddMod_t *ReportConfig[MAX_MEAS_CONFIG]; NR_ReportConfigToAddMod_t *ReportConfig[MAX_MEAS_CONFIG];
@@ -201,6 +215,7 @@ typedef struct rrcPerNB {
NR_MeasGapConfig_t *measGapConfig; NR_MeasGapConfig_t *measGapConfig;
NR_UE_RRC_SI_INFO SInfo; NR_UE_RRC_SI_INFO SInfo;
NR_RSRP_Range_t s_measure; NR_RSRP_Range_t s_measure;
l3_measurements_t l3_measurements;
} rrcPerNB_t; } rrcPerNB_t;
typedef struct NR_UE_RRC_INST_s { typedef struct NR_UE_RRC_INST_s {
+3
View File
@@ -55,6 +55,8 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
void handle_RRCRelease(NR_UE_RRC_INST_t *rrc); void handle_RRCRelease(NR_UE_RRC_INST_t *rrc);
void rrc_ue_generate_measurementReport(rrcPerNB_t *rrc, instance_t ue_id);
void set_rlf_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_UE_TimersAndConstants_t *ue_TimersAndConstants); void set_rlf_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_UE_TimersAndConstants_t *ue_TimersAndConstants);
/**\brief RRC UE task. /**\brief RRC UE task.
@@ -83,6 +85,7 @@ void nr_ue_rrc_timer_trigger(int module_id, int frame, int gnb_id);
void handle_t300_expiry(NR_UE_RRC_INST_t *rrc); void handle_t300_expiry(NR_UE_RRC_INST_t *rrc);
void handle_t430_expiry(NR_UE_RRC_INST_t *rrc); void handle_t430_expiry(NR_UE_RRC_INST_t *rrc);
int get_A2_event_time_to_trigger(long time_to_trigger);
void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac); void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac);
void set_default_timers_and_constants(NR_UE_Timers_Constants_t *tac); void set_default_timers_and_constants(NR_UE_Timers_Constants_t *tac);
void nr_rrc_set_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_SIB1_t *sib1); void nr_rrc_set_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_SIB1_t *sib1);
@@ -122,6 +122,36 @@ void nr_rrc_SI_timers(NR_UE_RRC_SI_INFO *SInfo)
} }
} }
void handle_meas_timers(NR_UE_RRC_INST_t *rrc)
{
for (int i = 0; i < NB_CNX_UE; i++) {
rrcPerNB_t *nb = &rrc->perNB[i];
l3_measurements_t *l3_measurements = &nb->l3_measurements;
bool ta2_expired = nr_timer_tick(&l3_measurements->TA2);
if (ta2_expired && l3_measurements->trigger_quantity > 0) {
rrc_ue_generate_measurementReport(nb, rrc->ue_id);
l3_measurements->reports_sent = 1;
if (l3_measurements->reports_sent < l3_measurements->max_reports) {
nr_timer_setup(&l3_measurements->periodic_report_timer, l3_measurements->report_interval_ms, 10);
nr_timer_start(&l3_measurements->periodic_report_timer);
}
}
bool periodic_expired = nr_timer_tick(&l3_measurements->periodic_report_timer);
if (periodic_expired && l3_measurements->reports_sent < l3_measurements->max_reports) {
rrc_ue_generate_measurementReport(nb, rrc->ue_id);
l3_measurements->reports_sent++;
if (l3_measurements->reports_sent < l3_measurements->max_reports) {
nr_timer_setup(&l3_measurements->periodic_report_timer, l3_measurements->report_interval_ms, 10);
nr_timer_start(&l3_measurements->periodic_report_timer);
}
}
}
}
void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc)
{ {
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
@@ -185,6 +215,8 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc)
// Spec 38.331 Section 5.2.2.6 // Spec 38.331 Section 5.2.2.6
handle_t430_expiry(rrc); handle_t430_expiry(rrc);
} }
handle_meas_timers(rrc);
} }
int nr_rrc_get_T304(long t304) int nr_rrc_get_T304(long t304)
@@ -630,3 +662,43 @@ void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac)
tac->N310_cnt = 0; tac->N310_cnt = 0;
tac->N311_cnt = 0; tac->N311_cnt = 0;
} }
int get_A2_event_time_to_trigger(long time_to_trigger)
{
switch (time_to_trigger) {
case NR_TimeToTrigger_ms0:
return 0;
case NR_TimeToTrigger_ms40:
return 40;
case NR_TimeToTrigger_ms64:
return 64;
case NR_TimeToTrigger_ms80:
return 80;
case NR_TimeToTrigger_ms100:
return 100;
case NR_TimeToTrigger_ms128:
return 128;
case NR_TimeToTrigger_ms160:
return 160;
case NR_TimeToTrigger_ms256:
return 256;
case NR_TimeToTrigger_ms320:
return 320;
case NR_TimeToTrigger_ms480:
return 480;
case NR_TimeToTrigger_ms512:
return 512;
case NR_TimeToTrigger_ms640:
return 640;
case NR_TimeToTrigger_ms1024:
return 1024;
case NR_TimeToTrigger_ms1280:
return 1280;
case NR_TimeToTrigger_ms2560:
return 2560;
case NR_TimeToTrigger_ms5120:
return 5120;
default:
AssertFatal(false, "Invalid TimeToTrigger %ld\n", time_to_trigger);
}
}