Commit 0f54eb8f authored by General ABS's avatar General ABS Committed by francescomani

L1 and L3 measurements (including A3 event configuration in gNB, L1 and L3...

L1 and L3 measurements (including A3 event configuration in gNB, L1 and L3 measurements for the active and neighboring cells and Implementation of procedures related to MeasurementReport)
parent 1244c9a2
...@@ -20,7 +20,7 @@ ...@@ -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
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define NFAPI_UE_MAX_NUM_CB 8 #define NFAPI_UE_MAX_NUM_CB 8
#define NFAPI_MAX_NUM_UL_PDU 255 #define NFAPI_MAX_NUM_UL_PDU 255
#define NUMBER_OF_NEIGHBORING_CELLs_MAX 1
/* /*
typedef unsigned int uint32_t; typedef unsigned int uint32_t;
...@@ -62,14 +63,17 @@ typedef enum { ...@@ -62,14 +63,17 @@ typedef enum {
typedef struct { typedef struct {
uint32_t rsrp; uint32_t gNB_index;
int rsrp_dBm; uint16_t Nid_cell;
uint8_t meas_type; // (0) SS, (1) CSI
uint8_t is_neighboring_cell; // (0) false, (1) true
uint8_t rsrp_dBm;
uint8_t rank_indicator; uint8_t rank_indicator;
uint8_t i1; uint8_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;
...@@ -154,7 +158,7 @@ typedef struct { ...@@ -154,7 +158,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;
...@@ -686,13 +690,22 @@ typedef struct ...@@ -686,13 +690,22 @@ typedef struct
} fapi_nr_prach_config_t; } fapi_nr_prach_config_t;
typedef struct {
uint16_t Nid_cell;
uint8_t active;
uint8_t perform_validation;
} fapi_nr_neighboring_cell_t;
typedef struct {
fapi_nr_neighboring_cell_t nr_neighboring_cell[NUMBER_OF_NEIGHBORING_CELLs_MAX];
} fapi_nr_meas_config_t;
typedef struct { typedef struct {
int16_t target_Nid_cell; int16_t target_Nid_cell;
} fapi_nr_synch_request_t; } fapi_nr_synch_request_t;
typedef struct { typedef struct {
uint32_t config_mask; uint32_t config_mask;
fapi_nr_ue_carrier_config_t carrier_config; fapi_nr_ue_carrier_config_t carrier_config;
fapi_nr_cell_config_t cell_config; fapi_nr_cell_config_t cell_config;
fapi_nr_ssb_config_t ssb_config; fapi_nr_ssb_config_t ssb_config;
...@@ -700,7 +713,7 @@ typedef struct { ...@@ -700,7 +713,7 @@ typedef struct {
fapi_nr_tdd_table_t tdd_table_1; fapi_nr_tdd_table_t tdd_table_1;
fapi_nr_tdd_table_t *tdd_table_2; fapi_nr_tdd_table_t *tdd_table_2;
fapi_nr_prach_config_t prach_config; fapi_nr_prach_config_t prach_config;
fapi_nr_meas_config_t meas_config;
} fapi_nr_config_request_t; } fapi_nr_config_request_t;
#endif #endif
......
...@@ -61,6 +61,14 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, ...@@ -61,6 +61,14 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int link_type); int link_type);
int nr_slot_fep_meas(PHY_VARS_NR_UE *ue,
int Ns,
unsigned char symbol,
int sample_offset,
uint32_t rxdata_size,
int rxdata[][rxdata_size],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue,
unsigned char l, unsigned char l,
int subframe, int subframe,
......
...@@ -219,6 +219,63 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, ...@@ -219,6 +219,63 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
return 0; return 0;
} }
int nr_slot_fep_meas(PHY_VARS_NR_UE *ue,
int Ns,
unsigned char symbol,
int sample_offset,
uint32_t rxdata_size,
int rxdata[][rxdata_size],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot - 1);
AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame - 1);
unsigned int nb_prefix_samples = frame_parms->nb_prefix_samples;
unsigned int nb_prefix_samples0 = frame_parms->nb_prefix_samples;
unsigned int frame_length_samples = frame_parms->samples_per_frame;
dft_size_idx_t dftsize = get_dft(frame_parms->ofdm_symbol_size);
unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns, frame_parms, 0);
unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol;
unsigned int rx_offset = sample_offset + slot_offset;
for (int idx_symb = Ns * frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) {
rx_offset += (abs_symbol % (0x7 << frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
}
rx_offset += frame_parms->ofdm_symbol_size * symbol;
int32_t tmp_dft_in[8192] __attribute__((aligned(32)));
for (unsigned char aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
int16_t *rxdata_ptr;
rx_offset %= frame_length_samples * 2;
if (rx_offset + frame_parms->ofdm_symbol_size > frame_length_samples * 2) {
memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], (frame_length_samples * 2 - rx_offset) * sizeof(int32_t));
memcpy((void *)&tmp_dft_in[frame_length_samples * 2 - rx_offset], (void *)&rxdata[aa][0], (frame_parms->ofdm_symbol_size - (frame_length_samples * 2 - rx_offset)) * sizeof(int32_t));
rxdata_ptr = (int16_t *)tmp_dft_in;
} else if ((rx_offset & 7) != 0) {
// if input to dft is not 256-bit aligned
memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], frame_parms->ofdm_symbol_size * sizeof(int32_t));
rxdata_ptr = (int16_t *)tmp_dft_in;
} else {
// use dft input from RX buffer directly
rxdata_ptr = (int16_t *)&rxdata[aa][rx_offset];
}
start_meas(&ue->rx_dft_stats);
dft(dftsize, rxdata_ptr, (int16_t *)&rxdataF[aa][frame_parms->ofdm_symbol_size * symbol], 1);
stop_meas(&ue->rx_dft_stats);
int symb_offset = (Ns % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot;
c16_t rot2 = frame_parms->symbol_rotation[0][symbol + symb_offset];
rot2.i = -rot2.i;
c16_t *this_symbol = &rxdataF[aa][frame_parms->ofdm_symbol_size * symbol];
rotate_cpx_vector(this_symbol, &rot2, this_symbol, frame_parms->ofdm_symbol_size, 15);
}
return 0;
}
int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdata, int32_t *rxdata,
......
...@@ -79,6 +79,7 @@ void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue); ...@@ -79,6 +79,7 @@ void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue);
void free_context_synchro_nr(void); void free_context_synchro_nr(void);
int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change); int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change);
int16_t *get_primary_synchro_nr2(const int nid2); int16_t *get_primary_synchro_nr2(const int nid2);
c16_t *get_primary_synchro_time_nr(const int nid2);
#endif /* PSS_NR_H */ #endif /* PSS_NR_H */
......
...@@ -81,5 +81,10 @@ bool rx_sss_nr(PHY_VARS_NR_UE *ue, ...@@ -81,5 +81,10 @@ bool rx_sss_nr(PHY_VARS_NR_UE *ue,
uint8_t *phase_max, uint8_t *phase_max,
int *freq_offset_sss, int *freq_offset_sss,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
const int16_t *get_phase_re_nr();
const int16_t *get_phase_im_nr();
int16_t *get_d_sss(const int nid2, const int nid1);
#endif /* SSS_NR_H */ #endif /* SSS_NR_H */
...@@ -112,6 +112,8 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, ...@@ -112,6 +112,8 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
void *nr_ue_meas_neighboring_cell(void *param);
void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue, void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
......
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
#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 "PHY/NR_REFSIG/sss_nr.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "SCHED_NR_UE/defs.h"
//#define k1 1000 //#define k1 1000
#define k1 ((long long int) 1000) #define k1 ((long long int) 1000)
...@@ -45,6 +48,7 @@ ...@@ -45,6 +48,7 @@
//#define DEBUG_MEAS_RRC //#define DEBUG_MEAS_RRC
//#define DEBUG_MEAS_UE //#define DEBUG_MEAS_UE
//#define DEBUG_RANK_EST //#define DEBUG_RANK_EST
//#define DEBUG_MEAS_NEIGHBORING_CELL
uint32_t get_nr_rx_total_gain_dB (module_id_t Mod_id,uint8_t CC_id) uint32_t get_nr_rx_total_gain_dB (module_id_t Mod_id,uint8_t CC_id)
{ {
...@@ -229,6 +233,220 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, ...@@ -229,6 +233,220 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
ssb_index, ssb_index,
ue->measurements.ssb_rsrp_dBm[ssb_index], ue->measurements.ssb_rsrp_dBm[ssb_index],
rsrp); rsrp);
// Send SS measurements to MAC
fapi_nr_l1_measurements_t l1_measurements;
l1_measurements.gNB_index = proc->gNB_id;
l1_measurements.meas_type = 0;
l1_measurements.Nid_cell = ue->frame_parms.Nid_cell;
l1_measurements.is_neighboring_cell = 0;
if (ue->measurements.ssb_rsrp_dBm[ssb_index] < -140) {
l1_measurements.rsrp_dBm = 16;
} else if (ue->measurements.ssb_rsrp_dBm[ssb_index] > -44) {
l1_measurements.rsrp_dBm = 113;
} else {
l1_measurements.rsrp_dBm = ue->measurements.ssb_rsrp_dBm[ssb_index] + 157; // TS 38.133 - Table 10.1.6.1-1
}
nr_downlink_indication_t dl_indication;
fapi_nr_rx_indication_t *rx_ind = calloc(sizeof(*rx_ind),1);
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, (void *)&l1_measurements, NULL);
if (ue->if_inst && ue->if_inst->dl_indication) {
ue->if_inst->dl_indication(&dl_indication);
} else {
free(rx_ind);
}
}
void *nr_ue_meas_neighboring_cell(void *param)
{
PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)param;
const UE_nr_rxtx_proc_t *proc = ue->measurements.meas_proc;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
// Copy rxdata, because this function is running in a separate thread, and rxdata will be changed in another thread, before this function finishes measuring.
uint32_t rxdata_size = (2 * (frame_parms->samples_per_frame) + frame_parms->ofdm_symbol_size);
int rxdata[frame_parms->nb_antennas_rx][rxdata_size];
for (int i = 0; i < frame_parms->nb_antennas_rx; i++) {
memcpy(rxdata[i], ue->common_vars.rxdata[i], rxdata_size * sizeof(int32_t));
}
const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP;
for (int cell_idx = 0; cell_idx < NUMBER_OF_NEIGHBORING_CELLs_MAX; cell_idx++) {
fapi_nr_neighboring_cell_t *nr_neighboring_cell = &PHY_vars_UE_g[ue->Mod_id][ue->CC_id]->nrUE_config.meas_config.nr_neighboring_cell[cell_idx];
if (nr_neighboring_cell->active == 0) {
continue;
}
ue->measurements.meas_running = true;
__attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
neighboring_cell_info_t *neighboring_cell_info = &ue->measurements.neighboring_cell_info[cell_idx];
// performing the correlation on a frame length plus one symbol for the first of the two frame
// to take into account the possibility of PSS between the two frames
if (neighboring_cell_info->pss_search_length == 0) {
neighboring_cell_info->pss_search_length = frame_parms->samples_per_frame + (2 * frame_parms->ofdm_symbol_size);
}
int length = neighboring_cell_info->pss_search_length;
int start = neighboring_cell_info->pss_search_start;
// Search pss in the received buffer each 8 samples
int pss_index = GET_NID2(nr_neighboring_cell->Nid_cell);
c16_t *pss_time = get_primary_synchro_time_nr(pss_index);
int maxval = 0;
for (int i = 0; i < IQ_SIZE * (frame_parms->ofdm_symbol_size); i++) {
maxval = max(maxval, abs(pss_time[i].r));
maxval = max(maxval, abs(pss_time[i].i));
}
int shift = log2_approx(maxval);
int peak_position = -1;
int64_t peak_value = 0;
int64_t avg = 0;
for (int n = start; n < start + length; n += 8) {
int64_t pss_corr_ue = 0;
for (int ar = 0; ar < frame_parms->nb_antennas_rx; ar++) {
const c32_t result = dot_product(pss_time, (c16_t *)&(rxdata[ar][n]), frame_parms->ofdm_symbol_size, shift);
const c64_t r64 = {.r = result.r, .i = result.i};
pss_corr_ue += squaredMod(r64);
}
avg += pss_corr_ue;
if (pss_corr_ue > peak_value) {
peak_value = pss_corr_ue;
peak_position = n;
}
}
avg /= (length / 4);
int ssb_offset = peak_position - frame_parms->nb_prefix_samples;
LOG_D(NR_PHY,
"PSS Peak found at pos %d (SSB offset %d), val = %llu (%d dB) avg %d dB\n",
peak_position,
ssb_offset,
(unsigned long long)peak_value,
dB_fixed64(peak_value),
dB_fixed64(avg));
if (peak_position == -1) {
continue;
}
// Validation using the SSS correlation
unsigned int k = 0;
uint8_t sss_symbol = SSS_SYMBOL_NB - PSS_SYMBOL_NB;
nr_slot_fep_meas(ue, 0, sss_symbol, ssb_offset, rxdata_size, rxdata, rxdataF);
c16_t *sss_rx = &rxdataF[0][frame_parms->ofdm_symbol_size * sss_symbol];
if (nr_neighboring_cell->perform_validation == 1) {
int sss_index = GET_NID1(nr_neighboring_cell->Nid_cell);
int16_t *sss_seq = get_d_sss(pss_index, sss_index);
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56;
if (k >= frame_parms->ofdm_symbol_size) {
k -= frame_parms->ofdm_symbol_size;
}
int32_t metric = 0;
const int16_t *phase_re_nr = get_phase_re_nr();
const int16_t *phase_im_nr = get_phase_im_nr();
for (uint8_t phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) {
int32_t metric_re = 0;
for (int i = 0; i < LENGTH_SSS_NR; i++) {
metric_re += sss_seq[i] * (((phase_re_nr[phase] * sss_rx[k].r) >> SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase] * sss_rx[k].i) >> SCALING_METRIC_SSS_NR));
k++;
if (k == frame_parms->ofdm_symbol_size) {
k = 0;
}
}
if (metric_re > metric) {
metric = metric_re;
}
}
#ifdef DEBUG_MEAS_NEIGHBORING_CELL
LOG_I(NR_PHY, "SSS metric = %i\n", metric);
#endif
if (metric < 15000) {
continue;
} else {
nr_neighboring_cell->perform_validation = 0;
}
}
neighboring_cell_info->pss_search_start = peak_position - 16;
neighboring_cell_info->pss_search_length = 32;
#ifdef DEBUG_MEAS_NEIGHBORING_CELL
LOG_I(NR_PHY, "Received symbol with PBCH 0...0 SSS 0...0 PBCH:\n");
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
if (k >= frame_parms->ofdm_symbol_size) {
k -= frame_parms->ofdm_symbol_size;
}
for (int i = 0; i < 20 * 12; i++) {
LOG_I(NR_PHY, "SSB[%i][%3i] = (%4i, %4i)\n", sss_symbol, i, sss_rx[k].r, sss_rx[k].i);
k++;
if (k == frame_parms->ofdm_symbol_size) {
k = 0;
}
}
#endif
// RSRP measurements
uint32_t rsrp_sum = 0;
int nb_re = 0;
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56;
if (k >= frame_parms->ofdm_symbol_size) {
k -= frame_parms->ofdm_symbol_size;
}
for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
sss_rx = &rxdataF[aarx][frame_parms->ofdm_symbol_size * sss_symbol];
for (int i = 0; i < LENGTH_SSS_NR; i++) {
rsrp_sum += (((int32_t)sss_rx[k].r * sss_rx[k].r) + ((int32_t)sss_rx[k].i * sss_rx[k].i));
nb_re++;
k++;
if (k == frame_parms->ofdm_symbol_size) {
k = 0;
}
}
}
neighboring_cell_info->ssb_rsrp = rsrp_sum / nb_re;
neighboring_cell_info->ssb_rsrp_dBm = 10 * log10(neighboring_cell_info->ssb_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);
#ifdef DEBUG_MEAS_NEIGHBORING_CELL
LOG_I(NR_PHY, "[Nid_cell %i] SSB RSRP = %u (%i dBm)\n", nr_neighboring_cell->Nid_cell, neighboring_cell_info->ssb_rsrp, neighboring_cell_info->ssb_rsrp_dBm);
#endif
// Send SS measurements to MAC
fapi_nr_l1_measurements_t l1_measurements;
l1_measurements.gNB_index = proc->gNB_id;
l1_measurements.meas_type = 0;
l1_measurements.Nid_cell = nr_neighboring_cell->Nid_cell;
l1_measurements.is_neighboring_cell = 1;
if (neighboring_cell_info->ssb_rsrp_dBm < -140) {
l1_measurements.rsrp_dBm = 16;
} else if (neighboring_cell_info->ssb_rsrp_dBm > -44) {
l1_measurements.rsrp_dBm = 113;
} else {
l1_measurements.rsrp_dBm = neighboring_cell_info->ssb_rsrp_dBm + 157; // TS 38.133 - Table 10.1.6.1-1
}
nr_downlink_indication_t dl_indication;
fapi_nr_rx_indication_t *rx_ind = calloc(sizeof(*rx_ind),1);
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, (void *)&l1_measurements, NULL);
if (ue->if_inst && ue->if_inst->dl_indication) {
ue->if_inst->dl_indication(&dl_indication);
} else {
free(rx_ind);
}
}
ue->measurements.meas_running = false;
pthread_detach(ue->measurements.meas_thread);
return NULL;
} }
// This function computes the received noise power // This function computes the received noise power
......
...@@ -1022,20 +1022,30 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, ...@@ -1022,20 +1022,30 @@ 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; fapi_nr_l1_measurements_t l1_measurements;
csirs_measurements.rsrp = rsrp; l1_measurements.gNB_index = gNB_id;
csirs_measurements.rsrp_dBm = rsrp_dBm; l1_measurements.meas_type = 1;
csirs_measurements.rank_indicator = rank_indicator; l1_measurements.Nid_cell = frame_parms->Nid_cell;
csirs_measurements.i1 = *i1; l1_measurements.is_neighboring_cell = 0;
csirs_measurements.i2 = *i2; if (rsrp_dBm < -140) {
csirs_measurements.cqi = cqi; l1_measurements.rsrp_dBm = 16;
csirs_measurements.radiolink_monitoring = RLM_no_monitoring; // TODO do be activated in case of RLM based on CSI-RS } else if (rsrp_dBm > -44) {
l1_measurements.rsrp_dBm = 113;
} else {
l1_measurements.rsrp_dBm = rsrp_dBm + 157; // TS 38.133 - Table 10.1.6.1-1
}
l1_measurements.rank_indicator = rank_indicator;
l1_measurements.i1 = *i1;
l1_measurements.i2 = *i2;
l1_measurements.cqi = cqi;
l1_measurements.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) if (ue->if_inst && ue->if_inst->dl_indication) {
ue->if_inst->dl_indication(&dl_indication); ue->if_inst->dl_indication(&dl_indication);
}
return; return;
} }
...@@ -59,6 +59,11 @@ int16_t *get_primary_synchro_nr2(const int nid2) ...@@ -59,6 +59,11 @@ int16_t *get_primary_synchro_nr2(const int nid2)
return primary_synchro_nr2[nid2]; return primary_synchro_nr2[nid2];
} }
c16_t *get_primary_synchro_time_nr(const int nid2)
{
return primary_synchro_time_nr[nid2];
}
/******************************************************************* /*******************************************************************
* *
* NAME : generate_pss_nr * NAME : generate_pss_nr
......
...@@ -72,6 +72,21 @@ static const int16_t phase_im_nr[PHASE_HYPOTHESIS_NUMBER] // -pi/3 ---- pi/3 ...@@ -72,6 +72,21 @@ static const int16_t phase_im_nr[PHASE_HYPOTHESIS_NUMBER] // -pi/3 ---- pi/3
static int16_t d_sss[N_ID_2_NUMBER][N_ID_1_NUMBER][LENGTH_SSS_NR]; static int16_t d_sss[N_ID_2_NUMBER][N_ID_1_NUMBER][LENGTH_SSS_NR];
int16_t *get_d_sss(const int nid2, const int nid1)
{
return d_sss[nid2][nid1];
}
const int16_t *get_phase_re_nr()
{
return phase_re_nr;
}
const int16_t *get_phase_im_nr()
{
return phase_im_nr;
}
void init_context_sss_nr(int amp) void init_context_sss_nr(int amp)
{ {
int16_t x0[LENGTH_SSS_NR]; int16_t x0[LENGTH_SSS_NR];
......
...@@ -122,6 +122,31 @@ typedef enum { ...@@ -122,6 +122,31 @@ typedef enum {
#define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg #define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg
#define NUMBER_OF_NEIGHBORING_CELLs_MAX 1
typedef struct {
openair0_timestamp timestamp_tx;
int gNB_id;
/// NR slot index within frame_tx [0 .. slots_per_frame - 1] to act upon for transmission
int nr_slot_tx;
int rx_slot_type;
/// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission
int nr_slot_rx;
int tx_slot_type;
//#endif
/// frame to act upon for transmission
int frame_tx;
/// frame to act upon for reception
int frame_rx;
} UE_nr_rxtx_proc_t;
typedef struct {
int pss_search_start;
int pss_search_length;
uint32_t ssb_rsrp;
int ssb_rsrp_dBm;
} neighboring_cell_info_t;
typedef struct { typedef struct {
// RRC measurements // RRC measurements
...@@ -205,7 +230,11 @@ typedef struct { ...@@ -205,7 +230,11 @@ typedef struct {
unsigned char nb_antennas_rx; unsigned char nb_antennas_rx;
/// DLSCH error counter /// DLSCH error counter
// short dlsch_errors; // short dlsch_errors;
/// Info about neighboring cells to perform the measurements
neighboring_cell_info_t neighboring_cell_info[NUMBER_OF_NEIGHBORING_CELLs_MAX];
const UE_nr_rxtx_proc_t *meas_proc;
pthread_t meas_thread;
bool meas_running;
} PHY_NR_MEASUREMENTS; } PHY_NR_MEASUREMENTS;
typedef struct { typedef struct {
...@@ -593,22 +622,6 @@ typedef struct PHY_VARS_NR_UE_s { ...@@ -593,22 +622,6 @@ typedef struct PHY_VARS_NR_UE_s {
notifiedFIFO_t tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME]; notifiedFIFO_t tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME];
} PHY_VARS_NR_UE; } PHY_VARS_NR_UE;
typedef struct {
openair0_timestamp timestamp_tx;
int gNB_id;
/// NR slot index within frame_tx [0 .. slots_per_frame - 1] to act upon for transmission
int nr_slot_tx;
int rx_slot_type;
/// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission
int nr_slot_rx;
int tx_slot_type;
//#endif
/// frame to act upon for transmission
int frame_tx;
/// frame to act upon for reception
int frame_rx;
} UE_nr_rxtx_proc_t;
typedef struct nr_phy_data_tx_s { typedef struct nr_phy_data_tx_s {
NR_UE_ULSCH_t ulsch; NR_UE_ULSCH_t ulsch;
NR_UE_PUCCH pucch_vars; NR_UE_PUCCH pucch_vars;
......
...@@ -186,10 +186,10 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, ...@@ -186,10 +186,10 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
} }
} }
break; break;
case FAPI_NR_CSIRS_IND: case FAPI_NR_MEAS_IND:
memcpy(&rx_ind->rx_indication_body[n_pdus - 1].csirs_measurements, memcpy(&rx_ind->rx_indication_body[n_pdus - 1].l1_measurements,
(fapi_nr_csirs_measurements_t*)typeSpecific, (fapi_nr_l1_measurements_t*)typeSpecific,
sizeof(*(fapi_nr_csirs_measurements_t*)typeSpecific)); sizeof(*(fapi_nr_l1_measurements_t*)typeSpecific));
break; break;
default: default:
break; break;
...@@ -826,6 +826,26 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, ...@@ -826,6 +826,26 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
return dec; return dec;
} }
bool check_meas_to_perform(PHY_VARS_NR_UE *ue, int nr_slot_rx)
{
if (nr_slot_rx != 0) {
return false;
}
if (ue->measurements.meas_running == true) {
return false;
}
for (int cell_idx = 0; cell_idx < NUMBER_OF_NEIGHBORING_CELLs_MAX; cell_idx++) {
fapi_nr_neighboring_cell_t *nr_neighboring_cell = &PHY_vars_UE_g[ue->Mod_id][ue->CC_id]->nrUE_config.meas_config.nr_neighboring_cell[cell_idx];
if (nr_neighboring_cell->active == 1) {
return true;
}
}
return false;
}
int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
{ {
int frame_rx = proc->frame_rx; int frame_rx = proc->frame_rx;
...@@ -932,6 +952,13 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ ...@@ -932,6 +952,13 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_
} // for rsc_id } // for rsc_id
} // for gNB_id } // for gNB_id
PHY_NR_MEASUREMENTS *measurements = &ue->measurements;
if (check_meas_to_perform(ue, nr_slot_rx) == true) {
measurements->meas_proc = proc;
int ret = pthread_create(&measurements->meas_thread, NULL, nr_ue_meas_neighboring_cell, (void *)ue);
AssertFatal(ret == 0, "%s: Thread for neighboring measurements was not created, errno: %d\n", __FUNCTION__, errno);
}
if ((frame_rx%64 == 0) && (nr_slot_rx==0)) { if ((frame_rx%64 == 0) && (nr_slot_rx==0)) {
LOG_I(NR_PHY,"============================================\n"); LOG_I(NR_PHY,"============================================\n");
// fixed text + 8 HARQs rounds à 10 ("999999999/") + NULL // fixed text + 8 HARQs rounds à 10 ("999999999/") + NULL
......
...@@ -42,6 +42,17 @@ void rrc_data_ind(const protocol_ctxt_t *const ctxt_pP, ...@@ -42,6 +42,17 @@ void rrc_data_ind(const protocol_ctxt_t *const ctxt_pP,
const uint8_t *const buffer_pP) { } const uint8_t *const buffer_pP) { }
typedef uint32_t channel_t; typedef uint32_t channel_t;
int8_t nr_mac_rrc_meas_ind_ue(module_id_t module_id,
uint32_t gNB_index,
uint16_t Nid_cell,
uint8_t meas_type,
uint8_t is_neighboring_cell,
uint8_t rsrp_dBm)
{
return 0;
}
int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const int CC_id, const int CC_id,
const uint8_t gNB_index, const uint8_t gNB_index,
......
...@@ -59,3 +59,6 @@ MESSAGE_DEF(NR_RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacCcch ...@@ -59,3 +59,6 @@ MESSAGE_DEF(NR_RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacCcch
MESSAGE_DEF(NR_RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacBcchDataInd, nr_rrc_mac_bcch_data_ind) MESSAGE_DEF(NR_RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacBcchDataInd, nr_rrc_mac_bcch_data_ind)
MESSAGE_DEF(NR_RRC_MAC_SBCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSBcchDataInd, nr_rrc_mac_sbcch_data_ind) MESSAGE_DEF(NR_RRC_MAC_SBCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSBcchDataInd, nr_rrc_mac_sbcch_data_ind)
// nrUE
MESSAGE_DEF(NR_RRC_MAC_MEAS_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacMeasDataInd, nr_rrc_mac_meas_data_ind)
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,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
...@@ -134,6 +136,14 @@ typedef struct NRRrcMacSBcchDataInd_s { ...@@ -134,6 +136,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;
uint8_t meas_type; // (0) SS, (1) CSI
uint8_t is_neighboring_cell; // (0) false, (1) true
} NRRrcMacMeasDataInd;
typedef struct RrcMacBcchMbmsDataReq_s { typedef struct RrcMacBcchMbmsDataReq_s {
uint32_t frame; uint32_t frame;
uint32_t sdu_size; uint32_t sdu_size;
......
...@@ -242,6 +242,36 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, ...@@ -242,6 +242,36 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac,
} }
void config_measConfig(NR_UE_MAC_INST_t *mac, const NR_MeasConfig_t *measConfig)
{
int Nid_cell = -1;
if (measConfig->measObjectToAddModList) {
NR_MeasObjectToAddModList_t *measObjectToAddModList = measConfig->measObjectToAddModList;
for (int i = 0; i < measObjectToAddModList->list.count; i++) {
NR_MeasObjectToAddMod_t *meas_obj = measObjectToAddModList->list.array[i];
if (meas_obj->measObject.choice.measObjectNR) {
NR_MeasObjectNR_t *measObjectNR = meas_obj->measObject.choice.measObjectNR;
if (measObjectNR->cellsToAddModList) {
NR_CellsToAddModList_t *cellsToAddModList = measObjectNR->cellsToAddModList;
for (int j = 0; j < cellsToAddModList->list.count; j++) {
NR_CellsToAddMod_t *cell = cellsToAddModList->list.array[j];
Nid_cell = cell->physCellId;
}
}
}
}
}
if (Nid_cell == -1) {
return;
}
fapi_nr_neighboring_cell_t *neighboring_cell = &mac->phy_config.config_req.meas_config.nr_neighboring_cell[0];
neighboring_cell->Nid_cell = Nid_cell;
neighboring_cell->active = 1;
neighboring_cell->perform_validation = 1;
}
static void config_common_ue(NR_UE_MAC_INST_t *mac, static void config_common_ue(NR_UE_MAC_INST_t *mac,
NR_ServingCellConfigCommon_t *scc, NR_ServingCellConfigCommon_t *scc,
int cc_idP) int cc_idP)
...@@ -2226,3 +2256,10 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, ...@@ -2226,3 +2256,10 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
if (!mac->dl_config_request || !mac->ul_config_request) if (!mac->dl_config_request || !mac->ul_config_request)
ue_init_config_request(mac, mac->current_DL_BWP->scs); ue_init_config_request(mac, mac->current_DL_BWP->scs);
} }
void nr_rrc_mac_config_req_meas(module_id_t module_id, const NR_MeasConfig_t *measConfig)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
config_measConfig(mac, measConfig);
mac->if_module->phy_config_request(&mac->phy_config);
}
...@@ -517,8 +517,8 @@ typedef struct NR_UE_MAC_INST_s { ...@@ -517,8 +517,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;
......
...@@ -91,6 +91,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, ...@@ -91,6 +91,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
NR_ServingCellConfigCommonSIB_t *scc); NR_ServingCellConfigCommonSIB_t *scc);
void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause); void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause);
void nr_rrc_mac_config_req_meas(module_id_t module_id, const NR_MeasConfig_t *measConfig);
/**\brief initialization NR UE MAC instance(s)*/ /**\brief initialization NR UE MAC instance(s)*/
NR_UE_MAC_INST_t * nr_l2_init_ue(int nb_inst); NR_UE_MAC_INST_t * nr_l2_init_ue(int nb_inst);
...@@ -122,10 +123,8 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP); ...@@ -122,10 +123,8 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP);
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, int8_t 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,
......
...@@ -283,7 +283,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, ...@@ -283,7 +283,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac,
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));
} }
......
...@@ -1274,12 +1274,16 @@ nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t ...@@ -1274,12 +1274,16 @@ 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, int8_t 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); nr_mac_rrc_meas_ind_ue(mac->ue_id,
memcpy(&mac->csirs_measurements, csirs_measurements, sizeof(*csirs_measurements)); l1_measurements->gNB_index,
l1_measurements->Nid_cell,
l1_measurements->meas_type,
l1_measurements->is_neighboring_cell,
l1_measurements->rsrp_dBm);
return 0; return 0;
} }
...@@ -2736,9 +2740,9 @@ uint8_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, ...@@ -2736,9 +2740,9 @@ uint8_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
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];
int padding_bitlen = n_bits - (cri_bitlen + ri_bitlen + pmi_x1_bitlen + pmi_x2_bitlen + cqi_bitlen); int padding_bitlen = n_bits - (cri_bitlen + ri_bitlen + pmi_x1_bitlen + pmi_x2_bitlen + cqi_bitlen);
if (get_softmodem_params()->emulate_l1) { if (get_softmodem_params()->emulate_l1) {
...@@ -2747,16 +2751,16 @@ uint8_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, ...@@ -2747,16 +2751,16 @@ uint8_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];
} }
// TODO: Improvements will be needed to cri_bitlen>0 and pmi_x1_bitlen>0 // TODO: Improvements will be needed to cri_bitlen>0 and pmi_x1_bitlen>0
temp_payload = (mac->csirs_measurements.rank_indicator<<(cri_bitlen+cqi_bitlen+pmi_x2_bitlen+padding_bitlen+pmi_x1_bitlen)) | temp_payload = (mac->l1_measurements.rank_indicator<<(cri_bitlen+cqi_bitlen+pmi_x2_bitlen+padding_bitlen+pmi_x1_bitlen)) |
(mac->csirs_measurements.i1<<(cri_bitlen+cqi_bitlen+pmi_x2_bitlen)) | (mac->l1_measurements.i1<<(cri_bitlen+cqi_bitlen+pmi_x2_bitlen)) |
(mac->csirs_measurements.i2<<(cri_bitlen+cqi_bitlen)) | (mac->l1_measurements.i2<<(cri_bitlen+cqi_bitlen)) |
(mac->csirs_measurements.cqi<<cri_bitlen) | (mac->l1_measurements.cqi<<cri_bitlen) |
0; 0;
reverse_n_bits((uint8_t *)&temp_payload, n_bits); reverse_n_bits((uint8_t *)&temp_payload, n_bits);
...@@ -2811,16 +2815,7 @@ uint8_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, ...@@ -2811,16 +2815,7 @@ uint8_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 = mac->l1_measurements.rsrp_dBm;
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;
}
reverse_n_bits((uint8_t *)&temp_payload, n_bits); reverse_n_bits((uint8_t *)&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);
......
...@@ -1098,13 +1098,10 @@ static void handle_rlm(rlm_t rlm_result, int frame, NR_UE_MAC_INST_t *mac) ...@@ -1098,13 +1098,10 @@ 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); return nr_ue_process_l1_measurements(mac, frame, slot, l1_measurements);
} }
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)
...@@ -1230,11 +1227,11 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info) ...@@ -1230,11 +1227,11 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info)
else else
LOG_I(PHY, "RAR-Msg2 decoded\n"); LOG_I(PHY, "RAR-Msg2 decoded\n");
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;
......
This diff is collapsed.
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <asn_application.h> #include <asn_application.h>
#include "RRC/NR/nr_rrc_config.h" #include "RRC/NR/nr_rrc_config.h"
#include "RRC/NR_UE/rrc_defs.h"
/* /*
* The variant of the above function which dumps the BASIC-XER (XER_F_BASIC) * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC)
...@@ -115,6 +116,11 @@ uint8_t do_RRCSetupComplete(uint8_t *buffer, ...@@ -115,6 +116,11 @@ uint8_t do_RRCSetupComplete(uint8_t *buffer,
int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv); int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv);
uint16_t do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport,
l3_measurements_t *l3_measurements,
uint8_t *buffer,
size_t buffer_size);
uint8_t do_NR_RRCReconfigurationComplete_for_nsa(uint8_t *buffer, size_t buffer_size, NR_RRC_TransactionIdentifier_t Transaction_id); uint8_t do_NR_RRCReconfigurationComplete_for_nsa(uint8_t *buffer, size_t buffer_size, NR_RRC_TransactionIdentifier_t Transaction_id);
uint8_t do_NR_RRCReconfigurationComplete(uint8_t *buffer, size_t buffer_size, const uint8_t Transaction_id); uint8_t do_NR_RRCReconfigurationComplete(uint8_t *buffer, size_t buffer_size, const uint8_t Transaction_id);
......
...@@ -236,7 +236,7 @@ static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int curr_bwp, uin ...@@ -236,7 +236,7 @@ static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int curr_bwp, uin
return coreset; return coreset;
} }
static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc) uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc)
{ {
uint64_t bitmap=0; uint64_t bitmap=0;
switch (scc->ssb_PositionsInBurst->present) { switch (scc->ssb_PositionsInBurst->present) {
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
struct nr_mac_config_t; struct nr_mac_config_t;
typedef struct nr_mac_config_t nr_mac_config_t; typedef struct nr_mac_config_t nr_mac_config_t;
uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc);
void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsch_TimeDomainAllocationList, void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsch_TimeDomainAllocationList,
frame_type_t frame_type, frame_type_t frame_type,
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
......
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
#include "NR_CellGroupConfig.h" #include "NR_CellGroupConfig.h"
#include "NR_ServingCellConfigCommon.h" #include "NR_ServingCellConfigCommon.h"
#include "NR_EstablishmentCause.h" #include "NR_EstablishmentCause.h"
#include "NR_MeasurementReport.h"
//------------------- //-------------------
#include "intertask_interface.h" #include "intertask_interface.h"
......
...@@ -585,6 +585,7 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co ...@@ -585,6 +585,7 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co
* we don't know the DU's SSB ARFCN */ * we don't know the DU's SSB ARFCN */
uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1); uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1);
measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs); measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs);
ue_p->measConfig = measconfig;
} }
NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false);
NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false);
...@@ -1296,24 +1297,125 @@ fallback_rrc_setup: ...@@ -1296,24 +1297,125 @@ fallback_rrc_setup:
return; return;
} }
static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context, NR_MeasurementReport_t *measurementReport) static void rrc_gNB_process_MeasurementReport(const protocol_ctxt_t *ctxt_p, rrc_gNB_ue_context_t *ue_context, NR_MeasurementReport_t *measurementReport)
{ {
LOG_I(NR_RRC, "Process measurementReport\n");
if (LOG_DEBUGFLAG(DEBUG_ASN1)) if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_MeasurementReport, (void *)measurementReport); xer_fprint(stdout, &asn_DEF_NR_MeasurementReport, (void *)measurementReport);
DevAssert(measurementReport->criticalExtensions.present == NR_MeasurementReport__criticalExtensions_PR_measurementReport DevAssert(measurementReport->criticalExtensions.present == NR_MeasurementReport__criticalExtensions_PR_measurementReport
&& measurementReport->criticalExtensions.choice.measurementReport != NULL); && measurementReport->criticalExtensions.choice.measurementReport != NULL);
NR_MeasurementReport_IEs_t *measurementReport_IEs = measurementReport->criticalExtensions.choice.measurementReport;
const NR_MeasId_t id = measurementReport_IEs->measResults.measId;
gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context; gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context;
ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, ue_ctxt->measResults);
ue_ctxt->measResults = NULL;
const NR_MeasId_t id = measurementReport->criticalExtensions.choice.measurementReport->measResults.measId;
AssertFatal(id, "unexpected MeasResult for MeasurementId %ld received\n", id); AssertFatal(id, "unexpected MeasResult for MeasurementId %ld received\n", id);
asn1cCallocOne(ue_ctxt->measResults, measurementReport->criticalExtensions.choice.measurementReport->measResults); asn1cCallocOne(ue_ctxt->measResults, measurementReport_IEs->measResults);
/* we "keep" the measurement report, so set to 0 */ /* we "keep" the measurement report, so set to 0 */
free(measurementReport->criticalExtensions.choice.measurementReport); free(measurementReport->criticalExtensions.choice.measurementReport);
measurementReport->criticalExtensions.choice.measurementReport = NULL; measurementReport->criticalExtensions.choice.measurementReport = NULL;
NR_MeasConfig_t *meas_config = ue_ctxt->measConfig;
if (meas_config == NULL) {
LOG_W(NR_RRC, "%s: %i - meas_config = %p\n", __FUNCTION__, __LINE__, meas_config);
return;
}
NR_MeasResults_t *meas_results = &measurementReport_IEs->measResults;
if (ue_ctxt->measResults != NULL) {
// ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_MeasResults, ue_ctxt->measResults);
free(ue_ctxt->measResults);
}
ue_ctxt->measResults = meas_results;
// Get the meas_id_s structure which contains the measId, measObjectId and reportConfigId
NR_MeasIdToAddMod_t *meas_id_s = NULL;
for (int meas_idx = 0; meas_idx < meas_config->measIdToAddModList->list.count; meas_idx++) {
if (id == meas_config->measIdToAddModList->list.array[meas_idx]->measId) {
meas_id_s = meas_config->measIdToAddModList->list.array[meas_idx];
break;
}
}
// Get the report_config
struct NR_ReportConfigToAddMod__reportConfig *report_config = NULL;
for (int rep_id = 0; rep_id < meas_config->reportConfigToAddModList->list.count; rep_id++) {
if (meas_id_s->reportConfigId == meas_config->reportConfigToAddModList->list.array[rep_id]->reportConfigId) {
report_config = &meas_config->reportConfigToAddModList->list.array[rep_id]->reportConfig;
}
}
NR_EventTriggerConfig_t *event_triggered = report_config->choice.reportConfigNR->reportType.choice.eventTriggered;
bool trigger_ho = false;
switch (event_triggered->eventId.present) {
case NR_EventTriggerConfig__eventId_PR_eventA1:
LOG_I(NR_RRC, "Event A1 (Serving becomes better than threshold)\n");
break;
case NR_EventTriggerConfig__eventId_PR_eventA2:
LOG_I(NR_RRC, "Event A2 (Serving becomes worse than threshold)\n");
break;
case NR_EventTriggerConfig__eventId_PR_eventA3:
LOG_I(NR_RRC, "Event A3 (Neighbour becomes offset better than SpCell)\n");
for (int res_mo_idx = 0; res_mo_idx < meas_results->measResultServingMOList.list.count; res_mo_idx++) {
NR_MeasResultServMO_t *meas_result_serv_MO = meas_results->measResultServingMOList.list.array[res_mo_idx];
struct NR_MeasQuantityResults *active_mq_res = NULL;
if (meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell) {
active_mq_res = meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell;
} else {
active_mq_res = meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsCSI_RS_Cell;
}
AssertFatal(active_mq_res, "No active cell measurement results!\n");
long rsrp_s = (*active_mq_res->rsrp) - 157;
LOG_I(NR_RRC, "[Active gNB %d] UE %04lx (Measurement Id %li): RSRP = %li dBm\n", ctxt_p->module_id, ctxt_p->rntiMaybeUEid, id, rsrp_s);
struct NR_MeasQuantityResults *neighboring_mq_res = NULL;
if (meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell) {
neighboring_mq_res = meas_result_serv_MO->measResultBestNeighCell->measResult.cellResults.resultsSSB_Cell;
} else {
neighboring_mq_res = meas_result_serv_MO->measResultBestNeighCell->measResult.cellResults.resultsCSI_RS_Cell;
}
AssertFatal(neighboring_mq_res, "No neighboring cell measurement results!\n");
long rsrp_t = (*neighboring_mq_res->rsrp) - 157;
LOG_I(NR_RRC, "[BestNeighCell] UE %04lx (Measurement Id %li): RSRP = %li dBm\n", ctxt_p->rntiMaybeUEid, id, rsrp_t);
long rsrp_offset = event_triggered->eventId.choice.eventA3 ? (event_triggered->eventId.choice.eventA3->a3_Offset.choice.rsrp) >> 1 : 0;
if (rsrp_t > (rsrp_s + rsrp_offset)) {
trigger_ho = true;
}
}
break;
case NR_EventTriggerConfig__eventId_PR_eventA4:
LOG_I(NR_RRC, "Event A4 (Neighbour becomes better than threshold)\n");
break;
case NR_EventTriggerConfig__eventId_PR_eventA5:
LOG_I(NR_RRC, "Event A5 (SpCell becomes worse than threshold1 and neighbour becomes better than threshold2)\n");
break;
case NR_EventTriggerConfig__eventId_PR_eventA6:
LOG_I(NR_RRC, "Event A6 (Neighbour becomes offset better than SCell)\n");
break;
default:
LOG_I(NR_RRC, "NR_EventTriggerConfig__eventId_PR_NOTHING or Other event report\n");
break;
}
if (trigger_ho == true && ue_ctxt->StatusRrc != NR_RRC_HO_EXECUTION) {
LOG_D(NR_RRC, "Trigger handover procedures are not implemented yet!\n");
}
} }
static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP, static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP,
...@@ -1671,7 +1773,8 @@ int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP, ...@@ -1671,7 +1773,8 @@ int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP,
&& ul_dcch_msg->message.present == NR_UL_DCCH_MessageType_PR_c1 && ul_dcch_msg->message.present == NR_UL_DCCH_MessageType_PR_c1
&& ul_dcch_msg->message.choice.c1 && ul_dcch_msg->message.choice.c1
&& ul_dcch_msg->message.choice.c1->present == NR_UL_DCCH_MessageType__c1_PR_measurementReport); && ul_dcch_msg->message.choice.c1->present == NR_UL_DCCH_MessageType__c1_PR_measurementReport);
rrc_gNB_process_MeasurementReport(ue_context_p, ul_dcch_msg->message.choice.c1->choice.measurementReport); LOG_A(NR_RRC, "Received measurementReport\n");
rrc_gNB_process_MeasurementReport(ctxt_pP, ue_context_p, ul_dcch_msg->message.choice.c1->choice.measurementReport);
break; break;
case NR_UL_DCCH_MessageType__c1_PR_ulInformationTransfer: case NR_UL_DCCH_MessageType__c1_PR_ulInformationTransfer:
...@@ -2247,10 +2350,19 @@ static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) ...@@ -2247,10 +2350,19 @@ static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults)
fprintf(f, " servingCellId %ld MeasResultNR for phyCellId %ld:\n resultSSB:", measresultservmo->servCellId, *measresultnr->physCellId); fprintf(f, " servingCellId %ld MeasResultNR for phyCellId %ld:\n resultSSB:", measresultservmo->servCellId, *measresultnr->physCellId);
if (mqr != NULL) { if (mqr != NULL) {
const long rrsrp = *mqr->rsrp - 156; if (mqr->rsrp) {
const float rrsrq = (float) (*mqr->rsrq - 87) / 2.0f; const long rrsrp = *mqr->rsrp - 156;
const float rsinr = (float) (*mqr->sinr - 46) / 2.0f; fprintf(f, "RSRP %ld dBm ", rrsrp);
fprintf(f, "RSRP %ld dBm RSRQ %.1f dB SINR %.1f dB\n", rrsrp, rrsrq, rsinr); }
if (mqr->rsrq) {
const float rrsrq = (float)(*mqr->rsrq - 87) / 2.0f;
fprintf(f, "RSRQ %.1f dB ", rrsrq);
}
if (mqr->sinr) {
const float rsinr = (float)(*mqr->sinr - 46) / 2.0f;
fprintf(f, "SINR %.1f dB ", rsinr);
}
fprintf(f, "\n");
} else { } else {
fprintf(f, "NOT PROVIDED\n"); fprintf(f, "NOT PROVIDED\n");
} }
......
...@@ -38,6 +38,18 @@ ...@@ -38,6 +38,18 @@
typedef uint32_t channel_t; typedef uint32_t channel_t;
int8_t nr_mac_rrc_meas_ind_ue(module_id_t module_id, uint32_t gNB_index, uint16_t Nid_cell, uint8_t meas_type, uint8_t 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).meas_type = meas_type;
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);
return 0;
}
void nr_mac_rrc_sync_ind(const module_id_t module_id, void nr_mac_rrc_sync_ind(const module_id_t module_id,
const frame_t frame, const frame_t frame,
const bool in_sync) const bool in_sync)
......
...@@ -231,6 +231,7 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, ...@@ -231,6 +231,7 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc,
if (ie->measConfig != NULL) { if (ie->measConfig != NULL) {
LOG_I(NR_RRC, "Measurement Configuration is present\n"); LOG_I(NR_RRC, "Measurement Configuration is present\n");
nr_rrc_ue_process_measConfig(rrcNB, ie->measConfig, &rrc->timers_and_constants); nr_rrc_ue_process_measConfig(rrcNB, ie->measConfig, &rrc->timers_and_constants);
nr_rrc_mac_config_req_meas(rrc->ue_id, ie->measConfig);
} }
if (ie->lateNonCriticalExtension != NULL) { if (ie->lateNonCriticalExtension != NULL) {
// unuse now // unuse now
...@@ -953,6 +954,23 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, ...@@ -953,6 +954,23 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc,
rrc_ue_generate_RRCSetupComplete(rrc, rrcSetup->rrc_TransactionIdentifier); rrc_ue_generate_RRCSetupComplete(rrc, rrcSetup->rrc_TransactionIdentifier);
} }
void rrc_ue_generate_measurementReport(NR_UE_RRC_INST_t *rrc)
{
uint8_t buffer[100];
if (rrc->measurementReport == NULL) {
rrc->measurementReport = calloc(1, sizeof(struct NR_MeasurementReport));
}
uint8_t size = do_nrMeasurementReport_SA(rrc->measurementReport,
&rrc->l3_measurements,
buffer,
sizeof(buffer));
int srb_id = 1; // possibly TODO in SRB3 in some cases
nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
}
static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc, static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc,
const NRRrcMacCcchDataInd *ind) const NRRrcMacCcchDataInd *ind)
{ {
...@@ -1683,6 +1701,115 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, ...@@ -1683,6 +1701,115 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
return 0; return 0;
} }
void nr_ue_meas_filtering(NR_UE_RRC_INST_t *rrc, uint8_t is_neighboring_cell, uint16_t Nid_cell, uint8_t meas_type, int rsrp_dBm)
{
l3_measurements_t *l3_measurements = &rrc->l3_measurements;
meas_t *meas_cell = NULL;
if (is_neighboring_cell == 0) {
meas_cell = &l3_measurements->active_cell;
} else {
meas_cell = &l3_measurements->neighboring_cell[0];
}
meas_cell->Nid_cell = Nid_cell;
double a = l3_measurements->filter_coeff_rsrp;
if (meas_type == 0) {
if (meas_cell->ss_rsrp_dBm_initialized == true) {
meas_cell->ss_rsrp_dBm = (1.0 - a) * meas_cell->ss_rsrp_dBm + a * rsrp_dBm;
} else {
meas_cell->ss_rsrp_dBm = rsrp_dBm;
meas_cell->ss_rsrp_dBm_initialized = true;
}
} else {
if (meas_cell->csi_rsrp_dBm_initialized == true) {
meas_cell->csi_rsrp_dBm = (1.0 - a) * meas_cell->csi_rsrp_dBm + a * rsrp_dBm;
} else {
meas_cell->csi_rsrp_dBm = rsrp_dBm;
meas_cell->csi_rsrp_dBm_initialized = true;
}
}
}
void nr_ue_ckeck_meas_report(NR_UE_RRC_INST_t *rrc, const uint8_t gnb_index)
{
l3_measurements_t *l3_measurements = &rrc->l3_measurements;
rrcPerNB_t *nb = &rrc->perNB[gnb_index];
for (int i = 0; i < MAX_MEAS_CONFIG; i++) {
NR_ReportConfigToAddMod_t *report_config = nb->ReportConfig[i];
if (report_config == NULL) {
continue;
}
if (report_config->reportConfig.present == NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR) {
NR_ReportConfigNR_t *report_config_nr = report_config->reportConfig.choice.reportConfigNR;
if (report_config_nr->reportType.present == NR_ReportConfigNR__reportType_PR_eventTriggered) {
NR_EventTriggerConfig_t *event_trigger_config = report_config_nr->reportType.choice.eventTriggered;
if (event_trigger_config->eventId.present == NR_EventTriggerConfig__eventId_PR_eventA3) {
struct NR_EventTriggerConfig__eventId__eventA3 *event_A3 = event_trigger_config->eventId.choice.eventA3;
if (event_A3->a3_Offset.present == NR_MeasTriggerQuantityOffset_PR_rsrp) {
meas_t *active_cell = &l3_measurements->active_cell;
meas_t *neighboring_cell = &l3_measurements->neighboring_cell[0];
int active_cell_rsrp = INT_MAX;
if (active_cell->ss_rsrp_dBm_initialized == true) {
active_cell_rsrp = active_cell->ss_rsrp_dBm;
} else if (active_cell->csi_rsrp_dBm_initialized == true) {
active_cell_rsrp = active_cell->csi_rsrp_dBm;
} else {
LOG_E(NR_RRC, "There are no RSRP measurements taken for the active cell\n");
}
int neighboring_cell_rsrp = INT_MIN;
if (neighboring_cell->ss_rsrp_dBm_initialized == true && event_trigger_config->rsType == NR_NR_RS_Type_ssb) {
neighboring_cell_rsrp = neighboring_cell->ss_rsrp_dBm;
}
int rsrp_offset = event_A3->a3_Offset.choice.rsrp >> 1;
int rsrp_hysteresis = event_A3->hysteresis;
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
if (neighboring_cell_rsrp > active_cell_rsrp + rsrp_offset + rsrp_hysteresis) {
if (!is_nr_timer_active(timers->TA3)) {
nr_timer_setup(&timers->TA3, get_time_to_trigger(event_A3->timeToTrigger), 10);
nr_timer_start(&timers->TA3);
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 = nb->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_A3->a3_Offset.present;
l3_measurements->rs_type = event_trigger_config->rsType;
LOG_W(NR_RRC, "(neighboring_cell_rsrp) %i > (active_cell_rsrp %i) + (rsrp_offset) %i + (rsrp_hysteresis) %i\n",
neighboring_cell_rsrp,
active_cell_rsrp,
rsrp_offset,
rsrp_hysteresis);
}
} else {
nr_timer_stop(&timers->TA3);
}
}
}
}
}
}
}
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;
...@@ -1764,6 +1891,21 @@ void *rrc_nrue(void *notUsed) ...@@ -1764,6 +1891,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 == 0 ? "Active cell" : "Neighboring cell",
NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell,
NR_RRC_MAC_MEAS_DATA_IND(msg_p).meas_type == 0 ? "SS" : "CSI",
NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm - 157);
nr_ue_meas_filtering(rrc,
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).meas_type,
NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm - 157);
nr_ue_ckeck_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: {
......
...@@ -160,6 +160,7 @@ typedef struct NR_UE_Timers_Constants_s { ...@@ -160,6 +160,7 @@ typedef struct NR_UE_Timers_Constants_s {
NR_timer_t T321; NR_timer_t T321;
NR_timer_t T325; NR_timer_t T325;
NR_timer_t T390; NR_timer_t T390;
NR_timer_t TA3;
// counters // counters
uint32_t N310_cnt; uint32_t N310_cnt;
uint32_t N311_cnt; uint32_t N311_cnt;
...@@ -168,6 +169,23 @@ typedef struct NR_UE_Timers_Constants_s { ...@@ -168,6 +169,23 @@ typedef struct NR_UE_Timers_Constants_s {
uint32_t N311_k; uint32_t N311_k;
} NR_UE_Timers_Constants_t; } NR_UE_Timers_Constants_t;
typedef struct meas_s {
uint16_t Nid_cell;
int ss_rsrp_dBm;
bool ss_rsrp_dBm_initialized;
int csi_rsrp_dBm;
bool csi_rsrp_dBm_initialized;
} meas_t;
typedef struct l3_measurements_s {
double filter_coeff_rsrp;
meas_t active_cell;
meas_t neighboring_cell[1];
long trigger_to_measid;
long trigger_quantity;
long rs_type;
} l3_measurements_t;
typedef enum { typedef enum {
OUT_OF_SYNC = 0, OUT_OF_SYNC = 0,
IN_SYNC = 1 IN_SYNC = 1
...@@ -189,6 +207,8 @@ typedef struct rrcPerNB { ...@@ -189,6 +207,8 @@ typedef struct rrcPerNB {
typedef struct NR_UE_RRC_INST_s { typedef struct NR_UE_RRC_INST_s {
instance_t ue_id; instance_t ue_id;
rrcPerNB_t perNB[NB_CNX_UE]; rrcPerNB_t perNB[NB_CNX_UE];
NR_MeasurementReport_t *measurementReport;
l3_measurements_t l3_measurements;
rnti_t rnti; rnti_t rnti;
uint32_t phyCellID; uint32_t phyCellID;
......
...@@ -60,6 +60,15 @@ void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, ...@@ -60,6 +60,15 @@ void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type,
void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig); void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig);
/**\brief Send measurements to RRC to perform the L3 measurements
\param module_id module id
\param gNB_index gNB index
\param Nid_cell Nid_cell
\param meas_type (0) SS, (1) CSI
\param is_neighboring_cell (0) false, (1) true
\param rsrp_dBm reference signal received power*/
int8_t nr_mac_rrc_meas_ind_ue(module_id_t module_id, uint32_t gNB_index, uint16_t Nid_cell, uint8_t meas_type, uint8_t is_neighboring_cell, uint8_t rsrp_dBm);
/**\brief interface between MAC and RRC thru SRB0 (RLC TM/no PDCP) /**\brief interface between MAC and RRC thru SRB0 (RLC TM/no PDCP)
\param module_id module id \param module_id module id
\param CC_id component carrier id \param CC_id component carrier id
...@@ -116,6 +125,7 @@ void init_SI_timers(NR_UE_RRC_SI_INFO *SInfo); ...@@ -116,6 +125,7 @@ void init_SI_timers(NR_UE_RRC_SI_INFO *SInfo);
void nr_ue_rrc_timer_trigger(int module_id, int frame, int gnb_id); 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);
int get_time_to_trigger(const 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);
......
...@@ -603,3 +603,44 @@ void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac) ...@@ -603,3 +603,44 @@ 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_time_to_trigger(const 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);
}
}
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