diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index d0856b415d3761ad639c377ec816ea18fd9fa445..5db6e44d8d2f788375f05649f033a0de2d95be02 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -440,6 +440,10 @@ The following features are valid for the gNB and the 5G-NR UE. - PTRS support - Support for 1, 2 and 4 RX antennas - Support for up to 2 layers (currently limited to DMRS configuration type 2) +* Measurements based on NR-CSIRS + - RI, PMI and CQI computation + - Support for 1 and 2 RX antennas + - Support for up to 2 layers * NR-PUSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). - PUSCH mapping type A and B - DMRS configuration type 1 and 2 @@ -488,12 +492,15 @@ The following features are valid for the gNB and the 5G-NR UE. * UCI processing - ACK/NACK processing - Triggering periodic SR - - CSI measurement reporting (SSB RSRP only) -* DLSH scheduler + - CSI measurement reporting +* DLSCH scheduler - Configuration of fapi PDU according to DCI - HARQ procedures * ULSCH scheduler - Configuration of fapi PDU according to DCI +* NR-CSIRS scheduler + - Scheduling of NR-CSIRS reception + - Fill UCI for CSI measurement reporting * Scheduler procedures for SRS transmission - Periodic SRS transmission * Bandwidth part (BWP) operation diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h index ba66daa9c08783d287a3c60bac8ba72afc048286..6d40752a9aa5f3299105d96f5ebbad05f6645b9c 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h @@ -20,6 +20,7 @@ #define FAPI_NR_RX_PDU_TYPE_DLSCH 0x03 #define FAPI_NR_DCI_IND 0x04 #define FAPI_NR_RX_PDU_TYPE_RAR 0x05 +#define FAPI_NR_CSIRS_IND 0x06 #define FAPI_NR_SIBS_MASK_SIB1 0x1 diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 10f881bae69055d5ebfb06b5dc8c8c1dc3b58832..a28762d1ff092d9fdb52e36e070172c40643d0ec 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -36,9 +36,6 @@ */ - - - typedef struct { uint8_t uci_format; uint8_t uci_channel; @@ -50,7 +47,14 @@ typedef struct { uint32_t sr; } fapi_nr_uci_pdu_rel15_t; - +typedef struct { + uint32_t rsrp; + int rsrp_dBm; + uint8_t rank_indicator; + uint8_t i1; + uint8_t i2; + uint8_t cqi; +} fapi_nr_csirs_measurements_t; typedef struct { /// frequency_domain_resource; @@ -130,6 +134,7 @@ typedef struct { fapi_nr_pdsch_pdu_t pdsch_pdu; fapi_nr_ssb_pdu_t ssb_pdu; fapi_nr_sib_pdu_t sib_pdu; + fapi_nr_csirs_measurements_t csirs_measurements; }; } fapi_nr_rx_indication_body_t; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 4fe66a5cbffe472ea2a784a4fbec437eaf32b70e..c3baa06da64d3e469e22fafc32611bef59c0beca 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -596,20 +596,20 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, // CSI RS init // ceil((NB_RB*8(max allocation per RB)*2(QPSK))/32) int csi_dmrs_init_length = ((fp->N_RB_DL<<4)>>5)+1; - gNB->nr_csi_rs_info = (nr_csi_rs_info_t *)malloc16_clear(sizeof(nr_csi_rs_info_t)); - gNB->nr_csi_rs_info->nr_gold_csi_rs = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **)); - AssertFatal(gNB->nr_csi_rs_info->nr_gold_csi_rs!=NULL, "NR init: csi reference signal malloc failed\n"); + gNB->nr_csi_info = (nr_csi_info_t *)malloc16_clear(sizeof(nr_csi_info_t)); + gNB->nr_csi_info->nr_gold_csi_rs = (uint32_t ***)malloc16(fp->slots_per_frame * sizeof(uint32_t **)); + AssertFatal(gNB->nr_csi_info->nr_gold_csi_rs != NULL, "NR init: csi reference signal malloc failed\n"); for (int slot=0; slotslots_per_frame; slot++) { - gNB->nr_csi_rs_info->nr_gold_csi_rs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *)); - AssertFatal(gNB->nr_csi_rs_info->nr_gold_csi_rs[slot]!=NULL, "NR init: csi reference signal for slot %d - malloc failed\n", slot); + gNB->nr_csi_info->nr_gold_csi_rs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot * sizeof(uint32_t *)); + AssertFatal(gNB->nr_csi_info->nr_gold_csi_rs[slot] != NULL, "NR init: csi reference signal for slot %d - malloc failed\n", slot); for (int symb=0; symbsymbols_per_slot; symb++) { - gNB->nr_csi_rs_info->nr_gold_csi_rs[slot][symb] = (uint32_t *)malloc16(csi_dmrs_init_length*sizeof(uint32_t)); - AssertFatal(gNB->nr_csi_rs_info->nr_gold_csi_rs[slot][symb]!=NULL, "NR init: csi reference signal for slot %d symbol %d - malloc failed\n", slot, symb); + gNB->nr_csi_info->nr_gold_csi_rs[slot][symb] = (uint32_t *)malloc16(csi_dmrs_init_length * sizeof(uint32_t)); + AssertFatal(gNB->nr_csi_info->nr_gold_csi_rs[slot][symb] != NULL, "NR init: csi reference signal for slot %d symbol %d - malloc failed\n", slot, symb); } } - gNB->nr_csi_rs_info->csi_gold_init = cfg->cell_config.phy_cell_id.value; - nr_init_csi_rs(&gNB->frame_parms, gNB->nr_csi_rs_info->nr_gold_csi_rs, cfg->cell_config.phy_cell_id.value); + gNB->nr_csi_info->csi_gold_init = cfg->cell_config.phy_cell_id.value; + nr_init_csi_rs(&gNB->frame_parms, gNB->nr_csi_info->nr_gold_csi_rs, cfg->cell_config.phy_cell_id.value); for (int id=0; idnr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); @@ -760,14 +760,14 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) } free_and_zero(pusch_dmrs); - uint32_t ***nr_gold_csi_rs = gNB->nr_csi_rs_info->nr_gold_csi_rs; + uint32_t ***nr_gold_csi_rs = gNB->nr_csi_info->nr_gold_csi_rs; for (int slot = 0; slot < fp->slots_per_frame; slot++) { for (int symb = 0; symb < fp->symbols_per_slot; symb++) free_and_zero(nr_gold_csi_rs[slot][symb]); free_and_zero(nr_gold_csi_rs[slot]); } free_and_zero(nr_gold_csi_rs); - free_and_zero(gNB->nr_csi_rs_info); + free_and_zero(gNB->nr_csi_info); for (int id = 0; id < NUMBER_OF_NR_SRS_MAX; id++) { free_and_zero(gNB->nr_srs_info[id]); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index a332c2067cdc11edf5884ac779f0651c67eda5da..dee4ca0608154909a28f4dffafa292d77cb954e1 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -159,7 +159,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) NR_UE_CSI_RS **const csirs_vars = ue->csirs_vars; NR_UE_SRS **const srs_vars = ue->srs_vars; - int i, j, slot, symb, gNB_id, th_id; + int i, slot, symb, gNB_id, th_id; LOG_I(PHY, "Initializing UE vars for gNB TXant %u, UE RXant %u\n", fp->nb_antennas_tx, fp->nb_antennas_rx); @@ -347,33 +347,20 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) // ceil((NB_RB*8(max allocation per RB)*2(QPSK))/32) int csi_dmrs_init_length = ((fp->N_RB_DL<<4)>>5)+1; - ue->nr_csi_rs_info = (nr_csi_rs_info_t *)malloc16_clear(sizeof(nr_csi_rs_info_t)); - ue->nr_csi_rs_info->nr_gold_csi_rs = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **)); - AssertFatal(ue->nr_csi_rs_info->nr_gold_csi_rs!=NULL, "NR init: csi reference signal malloc failed\n"); + ue->nr_csi_info = (nr_csi_info_t *)malloc16_clear(sizeof(nr_csi_info_t)); + ue->nr_csi_info->nr_gold_csi_rs = (uint32_t ***)malloc16(fp->slots_per_frame * sizeof(uint32_t **)); + AssertFatal(ue->nr_csi_info->nr_gold_csi_rs != NULL, "NR init: csi reference signal malloc failed\n"); for (int slot=0; slotslots_per_frame; slot++) { - ue->nr_csi_rs_info->nr_gold_csi_rs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *)); - AssertFatal(ue->nr_csi_rs_info->nr_gold_csi_rs[slot]!=NULL, "NR init: csi reference signal for slot %d - malloc failed\n", slot); + ue->nr_csi_info->nr_gold_csi_rs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot * sizeof(uint32_t *)); + AssertFatal(ue->nr_csi_info->nr_gold_csi_rs[slot] != NULL, "NR init: csi reference signal for slot %d - malloc failed\n", slot); for (int symb=0; symbsymbols_per_slot; symb++) { - ue->nr_csi_rs_info->nr_gold_csi_rs[slot][symb] = (uint32_t *)malloc16(csi_dmrs_init_length*sizeof(uint32_t)); - AssertFatal(ue->nr_csi_rs_info->nr_gold_csi_rs[slot][symb]!=NULL, "NR init: csi reference signal for slot %d symbol %d - malloc failed\n", slot, symb); + ue->nr_csi_info->nr_gold_csi_rs[slot][symb] = (uint32_t *)malloc16(csi_dmrs_init_length * sizeof(uint32_t)); + AssertFatal(ue->nr_csi_info->nr_gold_csi_rs[slot][symb] != NULL, "NR init: csi reference signal for slot %d symbol %d - malloc failed\n", slot, symb); } } - ue->nr_csi_rs_info->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t)); - ue->nr_csi_rs_info->csi_rs_generated_signal = (int32_t **)malloc16(NR_MAX_NB_PORTS * sizeof(int32_t *) ); + ue->nr_csi_info->csi_rs_generated_signal = (int32_t **)malloc16(NR_MAX_NB_PORTS * sizeof(int32_t *) ); for (i=0; inr_csi_rs_info->csi_rs_generated_signal[i] = (int32_t *) malloc16_clear(fp->samples_per_frame_wCP * sizeof(int32_t)); - } - ue->nr_csi_rs_info->csi_rs_received_signal = (int32_t **)malloc16(fp->nb_antennas_rx * sizeof(int32_t *) ); - ue->nr_csi_rs_info->csi_rs_ls_estimated_channel = (int32_t ***)malloc16(fp->nb_antennas_rx * sizeof(int32_t **) ); - ue->nr_csi_rs_info->csi_rs_estimated_channel_freq = (int32_t ***)malloc16(fp->nb_antennas_rx * sizeof(int32_t **) ); - for (i=0; inb_antennas_rx; i++) { - ue->nr_csi_rs_info->csi_rs_received_signal[i] = (int32_t *) malloc16_clear(fp->samples_per_frame_wCP * sizeof(int32_t)); - ue->nr_csi_rs_info->csi_rs_ls_estimated_channel[i] = (int32_t **) malloc16_clear(NR_MAX_NB_PORTS * sizeof(int32_t *)); - ue->nr_csi_rs_info->csi_rs_estimated_channel_freq[i] = (int32_t **) malloc16_clear(NR_MAX_NB_PORTS * sizeof(int32_t *)); - for (j=0; jnr_csi_rs_info->csi_rs_ls_estimated_channel[i][j] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size * sizeof(int32_t)); - ue->nr_csi_rs_info->csi_rs_estimated_channel_freq[i][j] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size * sizeof(int32_t)); - } + ue->nr_csi_info->csi_rs_generated_signal[i] = (int32_t *) malloc16_clear(fp->samples_per_frame_wCP * sizeof(int32_t)); } ue->nr_srs_info = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); @@ -470,39 +457,25 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) free_and_zero(ue->pdsch_vars[th_id][gNB_id]); } } - + for (int gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { for (int th_id = 0; th_id < RX_NB_TH_MAX; th_id++) { - free_and_zero(ue->pdcch_vars[th_id][gNB_id]); } for (int i=0; inr_csi_rs_info->csi_rs_generated_signal[i]); - } - for (int i = 0; i < fp->nb_antennas_rx; i++) { - free_and_zero(ue->nr_csi_rs_info->csi_rs_received_signal[i]); - for (int j=0; jnr_csi_rs_info->csi_rs_ls_estimated_channel[i][j]); - free_and_zero(ue->nr_csi_rs_info->csi_rs_estimated_channel_freq[i][j]); - } - free_and_zero(ue->nr_csi_rs_info->csi_rs_ls_estimated_channel[i]); - free_and_zero(ue->nr_csi_rs_info->csi_rs_estimated_channel_freq[i]); + free_and_zero(ue->nr_csi_info->csi_rs_generated_signal[i]); } + free_and_zero(ue->nr_csi_info->csi_rs_generated_signal); for (int slot=0; slotslots_per_frame; slot++) { for (int symb=0; symbsymbols_per_slot; symb++) { - free_and_zero(ue->nr_csi_rs_info->nr_gold_csi_rs[slot][symb]); + free_and_zero(ue->nr_csi_info->nr_gold_csi_rs[slot][symb]); } - free_and_zero(ue->nr_csi_rs_info->nr_gold_csi_rs[slot]); + free_and_zero(ue->nr_csi_info->nr_gold_csi_rs[slot]); } - free_and_zero(ue->nr_csi_rs_info->noise_power); - free_and_zero(ue->nr_csi_rs_info->nr_gold_csi_rs); - free_and_zero(ue->nr_csi_rs_info->csi_rs_generated_signal); - free_and_zero(ue->nr_csi_rs_info->csi_rs_received_signal); - free_and_zero(ue->nr_csi_rs_info->csi_rs_ls_estimated_channel); - free_and_zero(ue->nr_csi_rs_info->csi_rs_estimated_channel_freq); - free_and_zero(ue->nr_csi_rs_info); + free_and_zero(ue->nr_csi_info->nr_gold_csi_rs); + free_and_zero(ue->nr_csi_info); free_and_zero(ue->nr_srs_info); diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 71e1b0e340b900d30ff6413396e44407e258e825..c527c3fc9df083c115f095d1d655e1c35a81c98f 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -151,9 +151,9 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot, int first_symb,int num_symb NR_gNB_COMMON *common_vars = &gNB->common_vars; PHY_MEASUREMENTS_gNB *measurements = &gNB->measurements; int rb, nb_symb[275]={0}; - + memset(measurements->n0_subband_power, 0, sizeof(measurements->n0_subband_power)); - + for (int s=first_symb;s<(first_symb+num_symb);s++) { for (rb=0; rbN_RB_UL; rb++) { if (s==first_symb /*&& ((gNB->rb_mask_ul[s][rb>>5]&(1<<(rb&31))) == 0)*/) { @@ -168,7 +168,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot, int first_symb,int num_symb int offset = offset0 + (s*frame_parms->ofdm_symbol_size); int32_t *ul_ch = &common_vars->rxdataF[aarx][offset]; int len = 12; - if (((frame_parms->N_RB_UL&1) == 1) && + if (((frame_parms->N_RB_UL&1) == 1) && (rb==(frame_parms->N_RB_UL>>1))) { len=6; } diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index d4d91d7060987bd7438b57dabf92b359a4b86935..110ff321bd992c538e0d88f8bf6a44a59329c151 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -38,7 +38,7 @@ void nr_init_pbch_dmrs(PHY_VARS_gNB* gNB); */ void nr_init_pdcch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid); void nr_init_pdsch_dmrs(PHY_VARS_gNB* gNB, uint8_t nscid, uint32_t Nid); -void nr_init_csi_rs(NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid); +void nr_init_csi_rs(const NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid); void nr_gold_pusch(PHY_VARS_gNB* gNB, int nscid, uint32_t nid); diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index eb5c57336829135ee249785ac36756578d08e19b..a6e57fb29826410ecc09241ca0f9794e14d2c522 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -68,6 +68,6 @@ void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue, uint16_t N_n_scid, uint8_t n_scid); -void nr_init_csi_rs(NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid); +void nr_init_csi_rs(const NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid); #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c index ab8d915d6e6b452079b193fd923816cf9705a7f1..0a1619f3e062a7d075e1af3d0a64c10c4f67f06f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c @@ -27,7 +27,7 @@ //#define NR_CSIRS_DEBUG -void nr_init_csi_rs(NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid) { +void nr_init_csi_rs(const NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid) { uint32_t x1, x2; uint8_t reset; int csi_dmrs_init_length = ((fp->N_RB_DL<<4)>>5)+1; @@ -43,12 +43,20 @@ void nr_init_csi_rs(NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid) { } } -void nr_generate_csi_rs(NR_DL_FRAME_PARMS frame_parms, +void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, int32_t **dataF, - int16_t amp, - nr_csi_rs_info_t *nr_csi_rs_info, - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params, - int slot){ + const int16_t amp, + nr_csi_info_t *nr_csi_info, + const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params, + const int slot, + uint8_t *N_cdm_groups, + uint8_t *CDM_group_size, + uint8_t *k_prime, + uint8_t *l_prime, + uint8_t *N_ports, + uint8_t *j_cdm, + uint8_t *k_overline, + uint8_t *l_overline) { #ifdef NR_CSIRS_DEBUG LOG_I(NR_PHY, "csi_params->subcarrier_spacing = %i\n", csi_params->subcarrier_spacing); @@ -67,11 +75,11 @@ void nr_generate_csi_rs(NR_DL_FRAME_PARMS frame_parms, LOG_I(NR_PHY, "csi_params->power_control_offset_ss = %i\n", csi_params->power_control_offset_ss); #endif - int dataF_offset = slot*frame_parms.samples_per_slot_wCP; - uint32_t **nr_gold_csi_rs = nr_csi_rs_info->nr_gold_csi_rs[slot]; + int dataF_offset = slot*frame_parms->samples_per_slot_wCP; + uint32_t **nr_gold_csi_rs = nr_csi_info->nr_gold_csi_rs[slot]; //*8(max allocation per RB)*2(QPSK)) - int csi_rs_length = frame_parms.N_RB_DL<<4; - int16_t mod_csi[frame_parms.symbols_per_slot][csi_rs_length>>1] __attribute__((aligned(16))); + int csi_rs_length = frame_parms->N_RB_DL<<4; + int16_t mod_csi[frame_parms->symbols_per_slot][csi_rs_length>>1] __attribute__((aligned(16))); uint16_t b = csi_params->freq_domain; uint16_t n, p, k, l, mprime, na, kpn; uint8_t size, ports, kprime, lprime, i, gs; @@ -81,14 +89,14 @@ void nr_generate_csi_rs(NR_DL_FRAME_PARMS frame_parms, uint8_t fi = 0; double rho, alpha; uint32_t beta = amp; - nr_csi_rs_info->csi_rs_generated_signal_bits = log2_approx(amp); + nr_csi_info->csi_rs_generated_signal_bits = log2_approx(amp); AssertFatal(b!=0, "Invalid CSI frequency domain mapping: no bit selected in bitmap\n"); // if the scrambling id is not the one previously used to initialize we need to re-initialize the rs - if (csi_params->scramb_id != nr_csi_rs_info->csi_gold_init) { - nr_csi_rs_info->csi_gold_init = csi_params->scramb_id; - nr_init_csi_rs(&frame_parms, nr_csi_rs_info->nr_gold_csi_rs, csi_params->scramb_id); + if (csi_params->scramb_id != nr_csi_info->csi_gold_init) { + nr_csi_info->csi_gold_init = csi_params->scramb_id; + nr_init_csi_rs(frame_parms, nr_csi_info->nr_gold_csi_rs, csi_params->scramb_id); } switch (csi_params->row) { @@ -584,7 +592,7 @@ void nr_generate_csi_rs(NR_DL_FRAME_PARMS frame_parms, } } - uint16_t start_sc = frame_parms.first_carrier_offset; + uint16_t start_sc = frame_parms->first_carrier_offset; // resource mapping according to 38.211 7.4.1.5.3 for (n=csi_params->start_rb; n<(csi_params->start_rb+csi_params->nr_of_rbs); n++) { @@ -593,7 +601,7 @@ void nr_generate_csi_rs(NR_DL_FRAME_PARMS frame_parms, for (int s=0 ; sofdm_symbol_size); // frequency index of current resource element // wf according to tables 7.4.5.3-2 to 7.4.5.3-5 if (kp == 0) wf = 1; @@ -620,17 +628,17 @@ void nr_generate_csi_rs(NR_DL_FRAME_PARMS frame_parms, // ZP CSI RS if (csi_params->csi_type == 2) { - ((int16_t*)dataF[p])[((l*frame_parms.ofdm_symbol_size + k)<<1)+(2*dataF_offset)] = 0; - ((int16_t*)dataF[p])[((l*frame_parms.ofdm_symbol_size + k)<<1)+1+(2*dataF_offset)] = 0; + ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+(2*dataF_offset)] = 0; + ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+1+(2*dataF_offset)] = 0; } else { - ((int16_t*)dataF[p])[((l*frame_parms.ofdm_symbol_size + k)<<1)+(2*dataF_offset)] = (beta*wt*wf*mod_csi[l][mprime<<1]) >> 15; - ((int16_t*)dataF[p])[((l*frame_parms.ofdm_symbol_size + k)<<1)+1+(2*dataF_offset)] = (beta*wt*wf*mod_csi[l][(mprime<<1) + 1]) >> 15; + ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+(2*dataF_offset)] = (beta*wt*wf*mod_csi[l][mprime<<1]) >> 15; + ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+1+(2*dataF_offset)] = (beta*wt*wf*mod_csi[l][(mprime<<1) + 1]) >> 15; } #ifdef NR_CSIRS_DEBUG printf("l,k (%d,%d) seq. index %d \t port %d \t (%d,%d)\n",l,k,mprime,p+3000, - ((int16_t*)dataF[p])[((l*frame_parms.ofdm_symbol_size + k)<<1)+(2*dataF_offset)], - ((int16_t*)dataF[p])[((l*frame_parms.ofdm_symbol_size + k)<<1)+1+(2*dataF_offset)]); + ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+(2*dataF_offset)], + ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+1+(2*dataF_offset)]); #endif } } @@ -638,23 +646,25 @@ void nr_generate_csi_rs(NR_DL_FRAME_PARMS frame_parms, } } } - nr_csi_rs_info->N_cdm_groups = size; - nr_csi_rs_info->CDM_group_size = gs; - nr_csi_rs_info->kprime = kprime; - nr_csi_rs_info->lprime = lprime; - nr_csi_rs_info->N_ports = ports; - memcpy(nr_csi_rs_info->j,j,16*sizeof(uint8_t)); - memcpy(nr_csi_rs_info->koverline,koverline,16*sizeof(uint8_t)); - memcpy(nr_csi_rs_info->loverline,loverline,16*sizeof(uint8_t)); + if (N_cdm_groups) *N_cdm_groups = size; + if (CDM_group_size) *CDM_group_size = gs; + if (k_prime) *k_prime = kprime; + if (l_prime) *l_prime = lprime; + if (N_ports) *N_ports = ports; + if (j_cdm) memcpy(j_cdm,j,16*sizeof(uint8_t)); + if (k_overline) memcpy(k_overline,koverline,16*sizeof(uint8_t)); + if (l_overline) memcpy(l_overline,loverline,16*sizeof(uint8_t)); #ifdef NR_CSIRS_DEBUG - LOG_I(NR_PHY, "nr_csi_rs_info->N_ports = %d\n", nr_csi_rs_info->N_ports); - LOG_I(NR_PHY, "nr_csi_rs_info->N_cdm_groups = %d\n", nr_csi_rs_info->N_cdm_groups); - LOG_I(NR_PHY, "nr_csi_rs_info->CDM_group_size = %d\n", nr_csi_rs_info->CDM_group_size); - LOG_I(NR_PHY, "nr_csi_rs_info->kprime = %d\n", nr_csi_rs_info->kprime); - LOG_I(NR_PHY, "nr_csi_rs_info->lprime = %d\n", nr_csi_rs_info->lprime); - for(int ji=0; jiN_cdm_groups; ji++) { - LOG_I(NR_PHY, "(CDM group %d) j = %d, koverline = %d, loverline = %d\n", ji, nr_csi_rs_info->j[ji], nr_csi_rs_info->koverline[ji], nr_csi_rs_info->loverline[ji]); + if (N_ports) LOG_I(NR_PHY, "nr_csi_info->N_ports = %d\n", *N_ports); + if (N_cdm_groups) LOG_I(NR_PHY, "nr_csi_info->N_cdm_groups = %d\n", *N_cdm_groups); + if (CDM_group_size) LOG_I(NR_PHY, "nr_csi_info->CDM_group_size = %d\n", *CDM_group_size); + if (k_prime) LOG_I(NR_PHY, "nr_csi_info->kprime = %d\n", *k_prime); + if (l_prime) LOG_I(NR_PHY, "nr_csi_info->lprime = %d\n", *l_prime); + if (N_cdm_groups) { + for(int ji=0; ji<*N_cdm_groups; ji++) { + LOG_I(NR_PHY, "(CDM group %d) j = %d, koverline = %d, loverline = %d\n", ji, j[ji], koverline[ji], loverline[ji]); + } } #endif } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index d70d991e7b2d7d45f14b4afe9c15fe6ebbb0002f..dc1ed47e0ffd4f7698201a05082a559f4830940e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -111,9 +111,10 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, // DMRS length is per OFDM symbol uint32_t dmrs_length = n_rb*6; //2(QPSK)*3(per RB)*6(REG per CCE) uint32_t encoded_length = dci_pdu->AggregationLevel*108; //2(QPSK)*9(per RB)*6(REG per CCE) - LOG_D(PHY, "DL_DCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d,reg_mapping %d),Scrambling_Id %d,ScramblingRNTI %x,PayloadSizeBits %d\n", - rb_offset, n_rb,dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType, - dci_pdu->ScramblingId,dci_pdu->ScramblingRNTI,dci_pdu->PayloadSizeBits); + if (dci_pdu->RNTI != 0xFFFF) + LOG_D(PHY, "DL_DCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d, reg_mapping %d), Scrambling_Id %d, ScramblingRNTI %x, PayloadSizeBits %d\n", + rb_offset, n_rb,dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType, + dci_pdu->ScramblingId,dci_pdu->ScramblingRNTI,dci_pdu->PayloadSizeBits); dmrs_length += rb_offset*6; // To accommodate more DMRS symbols in case of rb offset /// DMRS QPSK modulation @@ -122,11 +123,11 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, nr_modulation(gold_pdcch_dmrs[symb], dmrs_length, DMRS_MOD_ORDER, mod_dmrs[symb]); //Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_PDCCH_DMRS - if(dci_pdu->RNTI!=0xFFFF) { - for (int i=0; i>1; i++) - printf("symb %d i %d %p gold seq 0x%08x mod_dmrs %d %d\n", symb, i, - &gold_pdcch_dmrs[symb][i>>5],gold_pdcch_dmrs[symb][i>>5], mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1] ); - } + if(dci_pdu->RNTI!=0xFFFF) { + for (int i=0; i>1; i++) + printf("symb %d i %d %p gold seq 0x%08x mod_dmrs %d %d\n", symb, i, + &gold_pdcch_dmrs[symb][i>>5],gold_pdcch_dmrs[symb][i>>5], mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1]); + } #endif } @@ -265,7 +266,6 @@ void nr_generate_dci_top(processingData_L1tx_t *msgTx, int16_t amp, NR_DL_FRAME_PARMS *frame_parms) { - for (int i=0; inum_ul_pdcch; i++) nr_generate_dci(msgTx->gNB,&msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15,txdataF,amp,frame_parms,slot); for (int i=0; inum_dl_pdcch; i++) diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 109fac7e2da9c0f506401ca386b0e665ca2df086..37c353e2d2d94210ea21999024ce9af3ec39dba0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -337,12 +337,20 @@ void init_prach_ru_list(RU_t *ru); void free_nr_ru_prach_entry(RU_t *ru, int prach_id); uint8_t get_nr_prach_duration(uint8_t prach_format); -void nr_generate_csi_rs(NR_DL_FRAME_PARMS frame_parms, +void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, int32_t **dataF, - int16_t amp, - nr_csi_rs_info_t *nr_csi_rs_info, - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params, - int slot); + const int16_t amp, + nr_csi_info_t *nr_csi_info, + const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params, + const int slot, + uint8_t *N_cdm_groups, + uint8_t *CDM_group_size, + uint8_t *k_prime, + uint8_t *l_prime, + uint8_t *N_ports, + uint8_t *j_cdm, + uint8_t *k_overline, + uint8_t *l_overline); void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id); diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 5caf1afb78a85da722ded44abbb3ae55102d5964..85461df44149c4a100200aec9c45d607c09a117d 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -331,8 +331,8 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, corr[aa][l].r += xr[aa][l][n].r * idft12_re[seq_index][n] + xr[aa][l][n].i * idft12_im[seq_index][n]; corr[aa][l].i += xr[aa][l][n].r * idft12_im[seq_index][n] - xr[aa][l][n].i * idft12_re[seq_index][n]; } - corr[aa][l].r >>= 31; - corr[aa][l].i >>= 31; + corr[aa][l].r >>= 31; + corr[aa][l].i >>= 31; } } LOG_D(PHY,"PUCCH IDFT[%d/%d] = (%ld,%ld)=>%f\n", diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 79fd7a3dd2352bce0d8a27fa5ee85e62a3cd7435..43944b2fa876538cf4a04a28bf86ff1c7812098d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -33,16 +33,103 @@ #include #include +#include "executables/nr-softmodem-common.h" #include "nr_transport_proto_ue.h" #include "PHY/phy_extern_nr_ue.h" #include "common/utils/nr/nr_common.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_ESTIMATION/filt16a_32.h" +// 10*log10(pow(2,30)) +#define pow_2_30_dB 90 //#define NR_CSIRS_DEBUG +//#define NR_CSIIM_DEBUG -bool is_csi_rs_in_symbol(fapi_nr_dl_config_csirs_pdu_rel15_t csirs_config_pdu, int symbol) { +void nr_det_A_MF_2x2(int32_t *a_mf_00, + int32_t *a_mf_01, + int32_t *a_mf_10, + int32_t *a_mf_11, + int32_t *det_fin, + const unsigned short nb_rb) { + + int16_t nr_conjug2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1} ; + + __m128i ad_re_128, bc_re_128, det_re_128; + + __m128i *a_mf_00_128 = (__m128i *)a_mf_00; + __m128i *a_mf_01_128 = (__m128i *)a_mf_01; + __m128i *a_mf_10_128 = (__m128i *)a_mf_10; + __m128i *a_mf_11_128 = (__m128i *)a_mf_11; + __m128i *det_fin_128 = (__m128i *)det_fin; + + for (int rb = 0; rb<3*nb_rb; rb++) { + + //complex multiplication (I_a+jQ_a)(I_d+jQ_d) = (I_aI_d - Q_aQ_d) + j(Q_aI_d + I_aQ_d) + //The imag part is often zero, we compute only the real part + ad_re_128 = _mm_sign_epi16(a_mf_00_128[0],*(__m128i*)&nr_conjug2[0]); + ad_re_128 = _mm_madd_epi16(ad_re_128,a_mf_11_128[0]); //Re: I_a0*I_d0 - Q_a1*Q_d1 + + //complex multiplication (I_b+jQ_b)(I_c+jQ_c) = (I_bI_c - Q_bQ_c) + j(Q_bI_c + I_bQ_c) + //The imag part is often zero, we compute only the real part + bc_re_128 = _mm_sign_epi16(a_mf_01_128[0],*(__m128i*)&nr_conjug2[0]); + bc_re_128 = _mm_madd_epi16(bc_re_128,a_mf_10_128[0]); //Re: I_b0*I_c0 - Q_b1*Q_c1 + + det_re_128 = _mm_sub_epi32(ad_re_128, bc_re_128); + + //det in Q30 format + det_fin_128[0] = _mm_abs_epi32(det_re_128); + + det_fin_128+=1; + a_mf_00_128+=1; + a_mf_01_128+=1; + a_mf_10_128+=1; + a_mf_11_128+=1; + } + _mm_empty(); + _m_empty(); +} + +void nr_squared_matrix_element(int32_t *a, + int32_t *a_sq, + const unsigned short nb_rb) { + __m128i *a_128 = (__m128i *)a; + __m128i *a_sq_128 = (__m128i *)a_sq; + for (int rb=0; rb<3*nb_rb; rb++) { + a_sq_128[0] = _mm_madd_epi16(a_128[0], a_128[0]); + a_sq_128+=1; + a_128+=1; + } + _mm_empty(); + _m_empty(); +} + +void nr_numer_2x2(int32_t *a_00_sq, + int32_t *a_01_sq, + int32_t *a_10_sq, + int32_t *a_11_sq, + int32_t *num_fin, + const unsigned short nb_rb) { + __m128i *a_00_sq_128 = (__m128i *)a_00_sq; + __m128i *a_01_sq_128 = (__m128i *)a_01_sq; + __m128i *a_10_sq_128 = (__m128i *)a_10_sq; + __m128i *a_11_sq_128 = (__m128i *)a_11_sq; + __m128i *num_fin_128 = (__m128i *)num_fin; + for (int rb=0; rb<3*nb_rb; rb++) { + __m128i sq_a_plus_sq_d_128 = _mm_add_epi32(a_00_sq_128[0], a_11_sq_128[0]); + __m128i sq_b_plus_sq_c_128 = _mm_add_epi32(a_01_sq_128[0], a_10_sq_128[0]); + num_fin_128[0] = _mm_add_epi32(sq_a_plus_sq_d_128, sq_b_plus_sq_c_128); + num_fin_128+=1; + a_00_sq_128+=1; + a_01_sq_128+=1; + a_10_sq_128+=1; + a_11_sq_128+=1; + } + _mm_empty(); + _m_empty(); +} + +bool is_csi_rs_in_symbol(const fapi_nr_dl_config_csirs_pdu_rel15_t csirs_config_pdu, const int symbol) { bool ret = false; @@ -90,17 +177,27 @@ bool is_csi_rs_in_symbol(fapi_nr_dl_config_csirs_pdu_rel15_t csirs_config_pdu, i return ret; } -int nr_get_csi_rs_signal(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, - nr_csi_rs_info_t *nr_csi_rs_info, - int32_t **csi_rs_received_signal) { +int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, + const nr_csi_info_t *nr_csi_info, + const uint8_t N_cdm_groups, + const uint8_t CDM_group_size, + const uint8_t k_prime, + const uint8_t l_prime, + const uint8_t *j_cdm, + const uint8_t *k_overline, + const uint8_t *l_overline, + int32_t csi_rs_received_signal[][ue->frame_parms.samples_per_slot_wCP], + uint32_t *rsrp, + int *rsrp_dBm) { int32_t **rxdataF = ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + uint16_t meas_count = 0; + uint32_t rsrp_sum = 0; for (int ant_rx = 0; ant_rx < frame_parms->nb_antennas_rx; ant_rx++) { - memset(csi_rs_received_signal[ant_rx], 0, frame_parms->samples_per_frame_wCP*sizeof(int32_t)); for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) { @@ -109,36 +206,41 @@ int nr_get_csi_rs_signal(PHY_VARS_NR_UE *ue, continue; } - for (int cdm_id = 0; cdm_id < nr_csi_rs_info->N_cdm_groups; cdm_id++) { - for (int s = 0; s < nr_csi_rs_info->CDM_group_size; s++) { + for (int cdm_id = 0; cdm_id < N_cdm_groups; cdm_id++) { + for (int s = 0; s < CDM_group_size; s++) { // loop over frequency resource elements within a group - for (int kp = 0; kp <= nr_csi_rs_info->kprime; kp++) { + for (int kp = 0; kp <= k_prime; kp++) { - uint16_t k = (frame_parms->first_carrier_offset + (rb*NR_NB_SC_PER_RB)+nr_csi_rs_info->koverline[cdm_id] + kp) % frame_parms->ofdm_symbol_size; + uint16_t k = (frame_parms->first_carrier_offset + (rb*NR_NB_SC_PER_RB)+k_overline[cdm_id] + kp) % frame_parms->ofdm_symbol_size; // loop over time resource elements within a group - for (int lp = 0; lp <= nr_csi_rs_info->lprime; lp++) { - uint16_t symb = lp + nr_csi_rs_info->loverline[cdm_id]; + for (int lp = 0; lp <= l_prime; lp++) { + uint16_t symb = lp + l_overline[cdm_id]; uint64_t symbol_offset = symb*frame_parms->ofdm_symbol_size; - int16_t *rx_signal = (int16_t*)&rxdataF[ant_rx][symbol_offset]; - int16_t *rx_csi_rs_signal = (int16_t*)&csi_rs_received_signal[ant_rx][symbol_offset]; - rx_csi_rs_signal[k<<1] = rx_signal[k<<1]; - rx_csi_rs_signal[(k<<1)+1] = rx_signal[(k<<1)+1]; + c16_t *rx_signal = (c16_t*)&rxdataF[ant_rx][symbol_offset]; + c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset]; + rx_csi_rs_signal[k].r = rx_signal[k].r; + rx_csi_rs_signal[k].i = rx_signal[k].i; + + rsrp_sum += (((int32_t)(rx_csi_rs_signal[k].r)*rx_csi_rs_signal[k].r) + + ((int32_t)(rx_csi_rs_signal[k].i)*rx_csi_rs_signal[k].i)); + + meas_count++; #ifdef NR_CSIRS_DEBUG int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP; - uint16_t port_tx = s+nr_csi_rs_info->j[cdm_id]*nr_csi_rs_info->CDM_group_size; - int16_t *tx_csi_rs_signal = (int16_t*)&nr_csi_rs_info->csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset]; + uint16_t port_tx = s+j_cdm[cdm_id]*CDM_group_size; + c16_t *tx_csi_rs_signal = (c16_t*)&nr_csi_info->csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset]; LOG_I(NR_PHY, "l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n", symb, k, port_tx+3000, - tx_csi_rs_signal[k<<1], - tx_csi_rs_signal[(k<<1)+1], + tx_csi_rs_signal[k].r, + tx_csi_rs_signal[k].i, ant_rx, - rx_csi_rs_signal[k<<1], - rx_csi_rs_signal[(k<<1)+1]); + rx_csi_rs_signal[k].r, + rx_csi_rs_signal[k].i); #endif } } @@ -147,10 +249,19 @@ int nr_get_csi_rs_signal(PHY_VARS_NR_UE *ue, } } + + *rsrp = rsrp_sum/meas_count; + *rsrp_dBm = dB_fixed(*rsrp) + 30 - pow_2_30_dB + - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + +#ifdef NR_CSIRS_DEBUG + LOG_I(NR_PHY, "RSRP = %i (%i dBm)\n", *rsrp, *rsrp_dBm); +#endif + return 0; } -uint32_t calc_power_csirs(uint16_t *x, fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu) { +uint32_t calc_power_csirs(const uint16_t *x, const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu) { uint64_t sum_x = 0; uint64_t sum_x2 = 0; uint16_t size = 0; @@ -165,25 +276,38 @@ uint32_t calc_power_csirs(uint16_t *x, fapi_nr_dl_config_csirs_pdu_rel15_t *csir return sum_x2/size - (sum_x/size)*(sum_x/size); } -int nr_csi_rs_channel_estimation(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, - nr_csi_rs_info_t *nr_csi_rs_info, - int32_t **csi_rs_generated_signal, - int32_t **csi_rs_received_signal, - int32_t ***csi_rs_estimated_channel_freq, +int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, + const nr_csi_info_t *nr_csi_info, + const int32_t **csi_rs_generated_signal, + const int32_t csi_rs_received_signal[][ue->frame_parms.samples_per_slot_wCP], + const uint8_t N_cdm_groups, + const uint8_t CDM_group_size, + const uint8_t k_prime, + const uint8_t l_prime, + const uint8_t N_ports, + const uint8_t *j_cdm, + const uint8_t *k_overline, + const uint8_t *l_overline, + int32_t csi_rs_ls_estimated_channel[][N_ports][ue->frame_parms.ofdm_symbol_size], + int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size], + int16_t *log2_re, + int16_t *log2_maxh, uint32_t *noise_power) { - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP; + const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + const int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP; *noise_power = 0; + int maxh = 0; + int count = 0; for (int ant_rx = 0; ant_rx < frame_parms->nb_antennas_rx; ant_rx++) { /// LS channel estimation - for(uint16_t port_tx = 0; port_txN_ports; port_tx++) { - memset(nr_csi_rs_info->csi_rs_ls_estimated_channel[ant_rx][port_tx], 0, frame_parms->ofdm_symbol_size*sizeof(int32_t)); + for(uint16_t port_tx = 0; port_txofdm_symbol_size*sizeof(int32_t)); } for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) { @@ -193,32 +317,32 @@ int nr_csi_rs_channel_estimation(PHY_VARS_NR_UE *ue, continue; } - for (int cdm_id = 0; cdm_id < nr_csi_rs_info->N_cdm_groups; cdm_id++) { - for (int s = 0; s < nr_csi_rs_info->CDM_group_size; s++) { + for (int cdm_id = 0; cdm_id < N_cdm_groups; cdm_id++) { + for (int s = 0; s < CDM_group_size; s++) { - uint16_t port_tx = s+nr_csi_rs_info->j[cdm_id]*nr_csi_rs_info->CDM_group_size; + uint16_t port_tx = s+j_cdm[cdm_id]*CDM_group_size; // loop over frequency resource elements within a group - for (int kp = 0; kp <= nr_csi_rs_info->kprime; kp++) { + for (int kp = 0; kp <= k_prime; kp++) { uint16_t kinit = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; - uint16_t k = kinit + nr_csi_rs_info->koverline[cdm_id] + kp; + uint16_t k = kinit + k_overline[cdm_id] + kp; // loop over time resource elements within a group - for (int lp = 0; lp <= nr_csi_rs_info->lprime; lp++) { - uint16_t symb = lp + nr_csi_rs_info->loverline[cdm_id]; + for (int lp = 0; lp <= l_prime; lp++) { + uint16_t symb = lp + l_overline[cdm_id]; uint64_t symbol_offset = symb*frame_parms->ofdm_symbol_size; - int16_t *tx_csi_rs_signal = (int16_t*)&csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset]; - int16_t *rx_csi_rs_signal = (int16_t*)&csi_rs_received_signal[ant_rx][symbol_offset]; - int16_t *csi_rs_ls_estimated_channel = (int16_t*)&nr_csi_rs_info->csi_rs_ls_estimated_channel[ant_rx][port_tx][0]; + c16_t *tx_csi_rs_signal = (c16_t*)&csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset]; + c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset]; + c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0]; - int16_t csi_rs_ls_estimated_channel_re = (int16_t)(((int32_t)tx_csi_rs_signal[k<<1]*rx_csi_rs_signal[k<<1] + (int32_t)tx_csi_rs_signal[(k<<1)+1]*rx_csi_rs_signal[(k<<1)+1])>>nr_csi_rs_info->csi_rs_generated_signal_bits); - int16_t csi_rs_ls_estimated_channel_im = (int16_t)(((int32_t)tx_csi_rs_signal[k<<1]*rx_csi_rs_signal[(k<<1)+1] - (int32_t)tx_csi_rs_signal[(k<<1)+1]*rx_csi_rs_signal[k<<1])>>nr_csi_rs_info->csi_rs_generated_signal_bits); + int16_t csi_rs_ls_estimated_channel_re = (int16_t)(((int32_t)tx_csi_rs_signal[k].r*rx_csi_rs_signal[k].r + (int32_t)tx_csi_rs_signal[k].i*rx_csi_rs_signal[k].i)>>nr_csi_info->csi_rs_generated_signal_bits); + int16_t csi_rs_ls_estimated_channel_im = (int16_t)(((int32_t)tx_csi_rs_signal[k].r*rx_csi_rs_signal[k].i - (int32_t)tx_csi_rs_signal[k].i*rx_csi_rs_signal[k].r)>>nr_csi_info->csi_rs_generated_signal_bits); // This is not just the LS estimation for each (k,l), but also the sum of the different contributions // for the sake of optimizing the memory used. - csi_rs_ls_estimated_channel[kinit<<1] += csi_rs_ls_estimated_channel_re; - csi_rs_ls_estimated_channel[(kinit<<1)+1] += csi_rs_ls_estimated_channel_im; + csi_rs_ls_estimated_channel16[kinit].r += csi_rs_ls_estimated_channel_re; + csi_rs_ls_estimated_channel16[kinit].i += csi_rs_ls_estimated_channel_im; } } } @@ -232,16 +356,16 @@ int nr_csi_rs_channel_estimation(PHY_VARS_NR_UE *ue, } for(int k = 0; kofdm_symbol_size; k++) { LOG_I(NR_PHY, "l,k (%2d,%4d) | ", symb, k); - for(uint16_t port_tx = 0; port_txN_ports; port_tx++) { + for(uint16_t port_tx = 0; port_txofdm_symbol_size; - int16_t *tx_csi_rs_signal = (int16_t*)&csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset]; - int16_t *rx_csi_rs_signal = (int16_t*)&csi_rs_received_signal[ant_rx][symbol_offset]; - int16_t *csi_rs_ls_estimated_channel = (int16_t*)&nr_csi_rs_info->csi_rs_ls_estimated_channel[ant_rx][port_tx][0]; + c16_t *tx_csi_rs_signal = (c16_t*)&csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset]; + c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset]; + c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0]; printf("port_tx %d --> ant_rx %d, tx (%4d,%4d), rx (%4d,%4d), ls (%4d,%4d) | ", port_tx+3000, ant_rx, - tx_csi_rs_signal[k<<1], tx_csi_rs_signal[(k<<1)+1], - rx_csi_rs_signal[k<<1], rx_csi_rs_signal[(k<<1)+1], - csi_rs_ls_estimated_channel[k<<1], csi_rs_ls_estimated_channel[(k<<1)+1]); + tx_csi_rs_signal[k].r, tx_csi_rs_signal[k].i, + rx_csi_rs_signal[k].r, rx_csi_rs_signal[k].i, + csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i); } printf("\n"); } @@ -250,7 +374,7 @@ int nr_csi_rs_channel_estimation(PHY_VARS_NR_UE *ue, /// Channel interpolation - for(uint16_t port_tx = 0; port_txN_ports; port_tx++) { + for(uint16_t port_tx = 0; port_txofdm_symbol_size*sizeof(int32_t)); } @@ -261,37 +385,40 @@ int nr_csi_rs_channel_estimation(PHY_VARS_NR_UE *ue, continue; } + count++; + uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; - for(uint16_t port_tx = 0; port_txN_ports; port_tx++) { - int16_t *csi_rs_ls_estimated_channel = (int16_t*)&nr_csi_rs_info->csi_rs_ls_estimated_channel[ant_rx][port_tx][k]; + for(uint16_t port_tx = 0; port_txfirst_carrier_offset) ) { // Start of OFDM symbol case or first occupied subcarrier case - multadd_real_vector_complex_scalar(filt24_start, csi_rs_ls_estimated_channel, csi_rs_estimated_channel16, 24); + multadd_real_vector_complex_scalar(filt24_start, csi_rs_ls_estimated_channel16, csi_rs_estimated_channel16, 24); } else if( ( (k + NR_NB_SC_PER_RB) >= frame_parms->ofdm_symbol_size) || (rb == (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs-1)) ) { // End of OFDM symbol case or Last occupied subcarrier case - multadd_real_vector_complex_scalar(filt24_end, csi_rs_ls_estimated_channel, csi_rs_estimated_channel16 - 3*sizeof(uint64_t), 24); + multadd_real_vector_complex_scalar(filt24_end, csi_rs_ls_estimated_channel16, csi_rs_estimated_channel16 - 3*sizeof(uint64_t), 24); } else { // Middle case - multadd_real_vector_complex_scalar(filt24_middle, csi_rs_ls_estimated_channel, csi_rs_estimated_channel16 - 3*sizeof(uint64_t), 24); + multadd_real_vector_complex_scalar(filt24_middle, csi_rs_ls_estimated_channel16, csi_rs_estimated_channel16 - 3*sizeof(uint64_t), 24); } } } /// Power noise estimation - uint16_t noise_real[frame_parms->nb_antennas_rx][nr_csi_rs_info->N_ports][csirs_config_pdu->nr_of_rbs]; - uint16_t noise_imag[frame_parms->nb_antennas_rx][nr_csi_rs_info->N_ports][csirs_config_pdu->nr_of_rbs]; + uint16_t noise_real[frame_parms->nb_antennas_rx][N_ports][csirs_config_pdu->nr_of_rbs]; + uint16_t noise_imag[frame_parms->nb_antennas_rx][N_ports][csirs_config_pdu->nr_of_rbs]; for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) { if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) { continue; } uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; - for(uint16_t port_tx = 0; port_txN_ports; port_tx++) { - int16_t *csi_rs_ls_estimated_channel = (int16_t*)&nr_csi_rs_info->csi_rs_ls_estimated_channel[ant_rx][port_tx][k]; - int16_t *csi_rs_estimated_channel16 = (int16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][k]; - noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb] = abs(csi_rs_ls_estimated_channel[0]-csi_rs_estimated_channel16[0]); - noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb] = abs(csi_rs_ls_estimated_channel[1]-csi_rs_estimated_channel16[1]); + for(uint16_t port_tx = 0; port_txstart_rb] = abs(csi_rs_ls_estimated_channel16->r-csi_rs_estimated_channel16->r); + noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb] = abs(csi_rs_ls_estimated_channel16->i-csi_rs_estimated_channel16->i); + maxh = cmax3(maxh, abs(csi_rs_estimated_channel16->r), abs(csi_rs_estimated_channel16->i)); } } - for(uint16_t port_tx = 0; port_txN_ports; port_tx++) { + for(uint16_t port_tx = 0; port_txfirst_carrier_offset)/NR_NB_SC_PER_RB : (k + frame_parms->ofdm_symbol_size - frame_parms->first_carrier_offset)/NR_NB_SC_PER_RB; LOG_I(NR_PHY, "(k = %4d) |\t", k); - for(uint16_t port_tx = 0; port_txN_ports; port_tx++) { - int16_t *csi_rs_ls_estimated_channel = (int16_t*)&nr_csi_rs_info->csi_rs_ls_estimated_channel[ant_rx][port_tx][0]; - int16_t *csi_rs_estimated_channel16 = (int16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][0]; + for(uint16_t port_tx = 0; port_tx ant_rx %d : ls (%4d,%4d), int (%4d,%4d), noise (%4d,%4d) | ", port_tx+3000, ant_rx, - csi_rs_ls_estimated_channel[k<<1], csi_rs_ls_estimated_channel[(k<<1)+1], - csi_rs_estimated_channel16[k<<1], csi_rs_estimated_channel16[(k<<1)+1], + csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i, + csi_rs_estimated_channel16[k].r, csi_rs_estimated_channel16[k].i, rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb], rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb]); } @@ -317,7 +444,9 @@ int nr_csi_rs_channel_estimation(PHY_VARS_NR_UE *ue, } - *noise_power /= (frame_parms->nb_antennas_rx*nr_csi_rs_info->N_ports); + *noise_power /= (frame_parms->nb_antennas_rx*N_ports); + *log2_maxh = log2_approx(maxh-1); + *log2_re = log2_approx(count-1); #ifdef NR_CSIRS_DEBUG LOG_I(NR_PHY, "Noise power estimation based on CSI-RS: %i\n", *noise_power); @@ -326,7 +455,371 @@ int nr_csi_rs_channel_estimation(PHY_VARS_NR_UE *ue, return 0; } +int nr_csi_rs_ri_estimation(const PHY_VARS_NR_UE *ue, + const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, + const nr_csi_info_t *nr_csi_info, + const uint8_t N_ports, + int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size], + const int16_t log2_maxh, + uint8_t *rank_indicator) { + + const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + const int16_t cond_dB_threshold = 5; + int count = 0; + *rank_indicator = 0; + + if (ue->frame_parms.nb_antennas_rx == 1 || N_ports == 1) { + return 0; + } else if( !(ue->frame_parms.nb_antennas_rx == 2 && N_ports == 2) ) { + LOG_W(NR_PHY, "Rank indicator computation is not implemented for %i x %i system\n", + ue->frame_parms.nb_antennas_rx, N_ports); + return -1; + } + + /* Example 2x2: Hh x H = + * | conjch00 conjch10 | x | ch00 ch01 | = | conjch00*ch00+conjch10*ch10 conjch00*ch01+conjch10*ch11 | + * | conjch01 conjch11 | | ch10 ch11 | | conjch01*ch00+conjch11*ch10 conjch01*ch01+conjch11*ch11 | + */ + + int32_t csi_rs_estimated_conjch_ch[frame_parms->nb_antennas_rx][N_ports][frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); + int32_t csi_rs_estimated_A_MF[N_ports][N_ports][frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); + int32_t csi_rs_estimated_A_MF_sq[N_ports][N_ports][frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); + int32_t csi_rs_estimated_determ_fin[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); + int32_t csi_rs_estimated_numer_fin[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); + + const uint8_t sum_shift = 1; // log2(2x2) = 2, which is a shift of 1 bit + + for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) { + + if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) { + continue; + } + uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; + + for (int ant_rx_conjch = 0; ant_rx_conjch < frame_parms->nb_antennas_rx; ant_rx_conjch++) { + for(uint16_t port_tx_conjch = 0; port_tx_conjch < N_ports; port_tx_conjch++) { + for (int ant_rx_ch = 0; ant_rx_ch < frame_parms->nb_antennas_rx; ant_rx_ch++) { + for(uint16_t port_tx_ch = 0; port_tx_ch < N_ports; port_tx_ch++) { + + // conjch x ch computation + nr_conjch0_mult_ch1(&csi_rs_estimated_channel_freq[ant_rx_conjch][port_tx_conjch][k], + &csi_rs_estimated_channel_freq[ant_rx_ch][port_tx_ch][k], + &csi_rs_estimated_conjch_ch[ant_rx_conjch][port_tx_conjch][ant_rx_ch][port_tx_ch][k], + 1, + log2_maxh); + + // construct Hh x H elements + if(ant_rx_conjch == ant_rx_ch) { + nr_a_sum_b((__m128i *)&csi_rs_estimated_A_MF[port_tx_conjch][port_tx_ch][k], + (__m128i *)&csi_rs_estimated_conjch_ch[ant_rx_conjch][port_tx_conjch][ant_rx_ch][port_tx_ch][k], + 1); + } + } + } + } + } + + // compute the determinant of A_MF (denominator) + nr_det_A_MF_2x2(&csi_rs_estimated_A_MF[0][0][k], + &csi_rs_estimated_A_MF[0][1][k], + &csi_rs_estimated_A_MF[1][0][k], + &csi_rs_estimated_A_MF[1][1][k], + &csi_rs_estimated_determ_fin[k], + 1); + + // compute the square of A_MF (numerator) + nr_squared_matrix_element(&csi_rs_estimated_A_MF[0][0][k], &csi_rs_estimated_A_MF_sq[0][0][k], 1); + nr_squared_matrix_element(&csi_rs_estimated_A_MF[0][1][k], &csi_rs_estimated_A_MF_sq[0][1][k], 1); + nr_squared_matrix_element(&csi_rs_estimated_A_MF[1][0][k], &csi_rs_estimated_A_MF_sq[1][0][k], 1); + nr_squared_matrix_element(&csi_rs_estimated_A_MF[1][1][k], &csi_rs_estimated_A_MF_sq[1][1][k], 1); + nr_numer_2x2(&csi_rs_estimated_A_MF_sq[0][0][k], + &csi_rs_estimated_A_MF_sq[0][1][k], + &csi_rs_estimated_A_MF_sq[1][0][k], + &csi_rs_estimated_A_MF_sq[1][1][k], + &csi_rs_estimated_numer_fin[k], + 1); + +#ifdef NR_CSIRS_DEBUG + for(uint16_t port_tx_conjch = 0; port_tx_conjch < N_ports; port_tx_conjch++) { + for(uint16_t port_tx_ch = 0; port_tx_ch < N_ports; port_tx_ch++) { + c16_t *csi_rs_estimated_A_MF_k = (c16_t *) &csi_rs_estimated_A_MF[port_tx_conjch][port_tx_ch][k]; + LOG_I(NR_PHY, "(%i) csi_rs_estimated_A_MF[%i][%i] = (%i, %i)\n", + k, port_tx_conjch, port_tx_ch, csi_rs_estimated_A_MF_k->r, csi_rs_estimated_A_MF_k->i); + c16_t *csi_rs_estimated_A_MF_sq_k = (c16_t *) &csi_rs_estimated_A_MF_sq[port_tx_conjch][port_tx_ch][k]; + LOG_I(NR_PHY, "(%i) csi_rs_estimated_A_MF_sq[%i][%i] = (%i, %i)\n", + k, port_tx_conjch, port_tx_ch, csi_rs_estimated_A_MF_sq_k->r, csi_rs_estimated_A_MF_sq_k->i); + } + } + LOG_I(NR_PHY, "(%i) csi_rs_estimated_determ_fin = %i\n", k, csi_rs_estimated_determ_fin[k]); + LOG_I(NR_PHY, "(%i) csi_rs_estimated_numer_fin = %i\n", k, csi_rs_estimated_numer_fin[k]>>sum_shift); +#endif + + // compute the conditional number + for (int sc_idx=0; sc_idx < NR_NB_SC_PER_RB; sc_idx++) { + int8_t csi_rs_estimated_denum_db = dB_fixed(csi_rs_estimated_determ_fin[k + sc_idx]); + int8_t csi_rs_estimated_numer_db = dB_fixed(csi_rs_estimated_numer_fin[k + sc_idx]>>sum_shift); + int8_t cond_db = csi_rs_estimated_numer_db - csi_rs_estimated_denum_db; + +#ifdef NR_CSIRS_DEBUG + LOG_I(NR_PHY, "csi_rs_estimated_denum_db = %i\n", csi_rs_estimated_denum_db); + LOG_I(NR_PHY, "csi_rs_estimated_numer_db = %i\n", csi_rs_estimated_numer_db); + LOG_I(NR_PHY, "cond_db = %i\n", cond_db); +#endif + + if (cond_db < cond_dB_threshold) { + count++; + } else { + count--; + } + } + } + + // conditional number is lower than cond_dB_threshold in half on more REs + if (count > 0) { + *rank_indicator = 1; + } + +#ifdef NR_CSIRS_DEBUG + LOG_I(NR_PHY, "count = %i\n", count); + LOG_I(NR_PHY, "rank = %i\n", (*rank_indicator)+1); +#endif + + return 0; +} + +int nr_csi_rs_pmi_estimation(const PHY_VARS_NR_UE *ue, + const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, + const nr_csi_info_t *nr_csi_info, + const uint8_t N_ports, + const int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size], + const uint32_t interference_plus_noise_power, + const uint8_t rank_indicator, + const int16_t log2_re, + uint8_t *i1, + uint8_t *i2, + uint32_t *precoded_sinr_dB) { + + const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + memset(i1,0,3*sizeof(uint8_t)); + i2[0] = 0; + + // i1 is a three-element vector in the form of [i11 i12 i13], when CodebookType is specified as 'Type1SinglePanel'. + // Note that i13 is not applicable when the number of transmission layers is one of {1, 5, 6, 7, 8}. + // i2, for 'Type1SinglePanel' codebook type, it is a scalar when PMIMode is specified as 'wideband', and when PMIMode + // is specified as 'subband' or when PRGSize, the length of the i2 vector equals to the number of subbands or PRGs. + // Note that when the number of CSI-RS ports is 2, the applicable codebook type is 'Type1SinglePanel'. In this case, + // the precoding matrix is obtained by a single index (i2 field here) based on TS 38.214 Table 5.2.2.2.1-1. + // The first column is applicable if the UE is reporting a Rank = 1, whereas the second column is applicable if the + // UE is reporting a Rank = 2. + + if(N_ports == 1 || interference_plus_noise_power == 0) { + return 0; + } + + if(rank_indicator == 0 || rank_indicator == 1) { + + int32_t sum_re[4] = {0}; + int32_t sum_im[4] = {0}; + int32_t sum2_re[4] = {0}; + int32_t sum2_im[4] = {0}; + int32_t tested_precoded_sinr[4] = {0}; + + for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) { + + if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) { + continue; + } + uint16_t k = (frame_parms->first_carrier_offset + rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; + + for (int ant_rx = 0; ant_rx < frame_parms->nb_antennas_rx; ant_rx++) { + + c16_t *csi_rs_estimated_channel_p0 = (c16_t *) &csi_rs_estimated_channel_freq[ant_rx][0][k]; + c16_t *csi_rs_estimated_channel_p1 = (c16_t *) &csi_rs_estimated_channel_freq[ant_rx][1][k]; + + // H_p0 + 1*H_p1 = (H_p0_re + H_p1_re) + 1j*(H_p0_im + H_p1_im) + sum_re[0] += (csi_rs_estimated_channel_p0->r+csi_rs_estimated_channel_p1->r); + sum_im[0] += (csi_rs_estimated_channel_p0->i+csi_rs_estimated_channel_p1->i); + sum2_re[0] += ((csi_rs_estimated_channel_p0->r+csi_rs_estimated_channel_p1->r)*(csi_rs_estimated_channel_p0->r+csi_rs_estimated_channel_p1->r))>>log2_re; + sum2_im[0] += ((csi_rs_estimated_channel_p0->i+csi_rs_estimated_channel_p1->i)*(csi_rs_estimated_channel_p0->i+csi_rs_estimated_channel_p1->i))>>log2_re; + + // H_p0 + 1j*H_p1 = (H_p0_re - H_p1_im) + 1j*(H_p0_im + H_p1_re) + sum_re[1] += (csi_rs_estimated_channel_p0->r-csi_rs_estimated_channel_p1->i); + sum_im[1] += (csi_rs_estimated_channel_p0->i+csi_rs_estimated_channel_p1->r); + sum2_re[1] += ((csi_rs_estimated_channel_p0->r-csi_rs_estimated_channel_p1->i)*(csi_rs_estimated_channel_p0->r-csi_rs_estimated_channel_p1->i))>>log2_re; + sum2_im[1] += ((csi_rs_estimated_channel_p0->i+csi_rs_estimated_channel_p1->r)*(csi_rs_estimated_channel_p0->i+csi_rs_estimated_channel_p1->r))>>log2_re; + + // H_p0 - 1*H_p1 = (H_p0_re - H_p1_re) + 1j*(H_p0_im - H_p1_im) + sum_re[2] += (csi_rs_estimated_channel_p0->r-csi_rs_estimated_channel_p1->r); + sum_im[2] += (csi_rs_estimated_channel_p0->i-csi_rs_estimated_channel_p1->i); + sum2_re[2] += ((csi_rs_estimated_channel_p0->r-csi_rs_estimated_channel_p1->r)*(csi_rs_estimated_channel_p0->r-csi_rs_estimated_channel_p1->r))>>log2_re; + sum2_im[2] += ((csi_rs_estimated_channel_p0->i-csi_rs_estimated_channel_p1->i)*(csi_rs_estimated_channel_p0->i-csi_rs_estimated_channel_p1->i))>>log2_re; + + // H_p0 - 1j*H_p1 = (H_p0_re + H_p1_im) + 1j*(H_p0_im - H_p1_re) + sum_re[3] += (csi_rs_estimated_channel_p0->r+csi_rs_estimated_channel_p1->i); + sum_im[3] += (csi_rs_estimated_channel_p0->i-csi_rs_estimated_channel_p1->r); + sum2_re[3] += ((csi_rs_estimated_channel_p0->r+csi_rs_estimated_channel_p1->i)*(csi_rs_estimated_channel_p0->r+csi_rs_estimated_channel_p1->i))>>log2_re; + sum2_im[3] += ((csi_rs_estimated_channel_p0->i-csi_rs_estimated_channel_p1->r)*(csi_rs_estimated_channel_p0->i-csi_rs_estimated_channel_p1->r))>>log2_re; + } + } + + // We should perform >>nr_csi_info->log2_re here for all terms, but since sum2_re and sum2_im can be high values, + // we performed this above. + for(int p = 0; p<4; p++) { + int32_t power_re = sum2_re[p] - (sum_re[p]>>log2_re)*(sum_re[p]>>log2_re); + int32_t power_im = sum2_im[p] - (sum_im[p]>>log2_re)*(sum_im[p]>>log2_re); + tested_precoded_sinr[p] = (power_re+power_im)/(int32_t)interference_plus_noise_power; + } + + if(rank_indicator == 0) { + for(int tested_i2 = 0; tested_i2 < 4; tested_i2++) { + if(tested_precoded_sinr[tested_i2] > tested_precoded_sinr[i2[0]]) { + i2[0] = tested_i2; + } + } + *precoded_sinr_dB = dB_fixed(tested_precoded_sinr[i2[0]]); + } else { + i2[0] = tested_precoded_sinr[0]+tested_precoded_sinr[2] > tested_precoded_sinr[1]+tested_precoded_sinr[3] ? 0 : 1; + *precoded_sinr_dB = dB_fixed((tested_precoded_sinr[i2[0]] + tested_precoded_sinr[i2[0]+2])>>1); + } + + } else { + LOG_W(NR_PHY, "PMI computation is not implemented for rank indicator %i\n", rank_indicator+1); + return -1; + } + + return 0; +} + +int nr_csi_rs_cqi_estimation(const uint32_t precoded_sinr, + uint8_t *cqi) { + + *cqi = 0; + + // Default SINR table for an AWGN channel for SISO scenario, considering 0.1 BLER condition and TS 38.214 Table 5.2.2.1-2 + if(precoded_sinr>0 && precoded_sinr<=2) { + *cqi = 4; + } else if(precoded_sinr==3) { + *cqi = 5; + } else if(precoded_sinr>3 && precoded_sinr<=5) { + *cqi = 6; + } else if(precoded_sinr>5 && precoded_sinr<=7) { + *cqi = 7; + } else if(precoded_sinr>7 && precoded_sinr<=9) { + *cqi = 8; + } else if(precoded_sinr==10) { + *cqi = 9; + } else if(precoded_sinr>10 && precoded_sinr<=12) { + *cqi = 10; + } else if(precoded_sinr>12 && precoded_sinr<=15) { + *cqi = 11; + } else if(precoded_sinr==16) { + *cqi = 12; + } else if(precoded_sinr>16 && precoded_sinr<=18) { + *cqi = 13; + } else if(precoded_sinr==19) { + *cqi = 14; + } else if(precoded_sinr>19) { + *cqi = 15; + } + + return 0; +} + +int nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + const fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu, + uint32_t *interference_plus_noise_power) { + + int32_t **rxdataF = ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; + const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + + const uint16_t end_rb = csiim_config_pdu->start_rb + csiim_config_pdu->nr_of_rbs > csiim_config_pdu->bwp_size ? + csiim_config_pdu->bwp_size : csiim_config_pdu->start_rb + csiim_config_pdu->nr_of_rbs; + + int32_t count = 0; + int32_t sum_re = 0; + int32_t sum_im = 0; + int32_t sum2_re = 0; + int32_t sum2_im = 0; + + int l_csiim[4] = {-1, -1, -1, -1}; + + for(int symb_idx = 0; symb_idx < 4; symb_idx++) { + + uint8_t symb = csiim_config_pdu->l_csiim[symb_idx]; + bool done = false; + for (int symb_idx2 = 0; symb_idx2 < symb_idx; symb_idx2++) { + if (l_csiim[symb_idx2] == symb) { + done = true; + } + } + + if (done) { + continue; + } + + l_csiim[symb_idx] = symb; + uint64_t symbol_offset = symb*frame_parms->ofdm_symbol_size; + + for (int ant_rx = 0; ant_rx < frame_parms->nb_antennas_rx; ant_rx++) { + + c16_t *rx_signal = (c16_t*)&rxdataF[ant_rx][symbol_offset]; + + for (int rb = csiim_config_pdu->start_rb; rb < end_rb; rb++) { + + uint16_t sc0_offset = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; + + for (int sc_idx = 0; sc_idx<4; sc_idx++) { + + uint16_t sc = sc0_offset + csiim_config_pdu->k_csiim[sc_idx]; + +#ifdef NR_CSIIM_DEBUG + LOG_I(NR_PHY, "(ant_rx %i, sc %i) real %i, imag %i\n", ant_rx, rb, rx_signal[sc].r, rx_signal[sc].i); +#endif + + sum_re += rx_signal[sc].r; + sum_im += rx_signal[sc].i; + sum2_re += rx_signal[sc].r*rx_signal[sc].r; + sum2_im += rx_signal[sc].i*rx_signal[sc].i; + count++; + } + } + } + } + + int32_t power_re = sum2_re/count - (sum_re/count)*(sum_re/count); + int32_t power_im = sum2_im/count - (sum_im/count)*(sum_im/count); + + *interference_plus_noise_power = power_re + power_im; + +#ifdef NR_CSIIM_DEBUG + LOG_I(NR_PHY, "interference_plus_noise_power based on CSI-IM = %i\n", *interference_plus_noise_power); +#endif + + return 0; +} + int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id) { + + if(!ue->csiim_vars[gNB_id]->active) { + return -1; + } + + const fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu = (fapi_nr_dl_config_csiim_pdu_rel15_t*)&ue->csiim_vars[gNB_id]->csiim_config_pdu; + +#ifdef NR_CSIIM_DEBUG + LOG_I(NR_PHY, "csiim_config_pdu->bwp_size = %i\n", csiim_config_pdu->bwp_size); + LOG_I(NR_PHY, "csiim_config_pdu->bwp_start = %i\n", csiim_config_pdu->bwp_start); + LOG_I(NR_PHY, "csiim_config_pdu->subcarrier_spacing = %i\n", csiim_config_pdu->subcarrier_spacing); + LOG_I(NR_PHY, "csiim_config_pdu->start_rb = %i\n", csiim_config_pdu->start_rb); + LOG_I(NR_PHY, "csiim_config_pdu->nr_of_rbs = %i\n", csiim_config_pdu->nr_of_rbs); + LOG_I(NR_PHY, "csiim_config_pdu->k_csiim = %i.%i.%i.%i\n", csiim_config_pdu->k_csiim[0], csiim_config_pdu->k_csiim[1], csiim_config_pdu->k_csiim[2], csiim_config_pdu->k_csiim[3]); + LOG_I(NR_PHY, "csiim_config_pdu->l_csiim = %i.%i.%i.%i\n", csiim_config_pdu->l_csiim[0], csiim_config_pdu->l_csiim[1], csiim_config_pdu->l_csiim[2], csiim_config_pdu->l_csiim[3]); +#endif + + nr_csi_im_power_estimation(ue, proc, csiim_config_pdu, &ue->nr_csi_info->interference_plus_noise_power); + ue->nr_csi_info->csi_im_meas_computed = true; + return 0; } @@ -336,7 +829,7 @@ int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t return -1; } - fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = (fapi_nr_dl_config_csirs_pdu_rel15_t*)&ue->csirs_vars[gNB_id]->csirs_config_pdu; + const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = (fapi_nr_dl_config_csirs_pdu_rel15_t*)&ue->csirs_vars[gNB_id]->csirs_config_pdu; #ifdef NR_CSIRS_DEBUG LOG_I(NR_PHY, "csirs_config_pdu->subcarrier_spacing = %i\n", csirs_config_pdu->subcarrier_spacing); @@ -355,26 +848,122 @@ int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t LOG_I(NR_PHY, "csirs_config_pdu->power_control_offset_ss = %i\n", csirs_config_pdu->power_control_offset_ss); #endif - nr_generate_csi_rs(ue->frame_parms, - ue->nr_csi_rs_info->csi_rs_generated_signal, + const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int32_t csi_rs_received_signal[frame_parms->nb_antennas_rx][frame_parms->samples_per_slot_wCP]; + uint8_t N_cdm_groups = 0; + uint8_t CDM_group_size = 0; + uint8_t k_prime = 0; + uint8_t l_prime = 0; + uint8_t N_ports = 0; + uint8_t j_cdm[16]; + uint8_t k_overline[16]; + uint8_t l_overline[16]; + int16_t log2_re = 0; + int16_t log2_maxh = 0; + uint32_t rsrp = 0; + int rsrp_dBm = 0; + uint32_t noise_power = 0; + uint8_t rank_indicator = 0; + uint32_t precoded_sinr_dB = 0; + uint8_t cqi = 0; + uint8_t i1[3]; + uint8_t i2[1]; + + nr_generate_csi_rs(frame_parms, + ue->nr_csi_info->csi_rs_generated_signal, AMP, - ue->nr_csi_rs_info, + ue->nr_csi_info, (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *) csirs_config_pdu, - proc->nr_slot_rx); + proc->nr_slot_rx, + &N_cdm_groups, + &CDM_group_size, + &k_prime, + &l_prime, + &N_ports, + j_cdm, + k_overline, + l_overline); + + int32_t csi_rs_ls_estimated_channel[frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size]; + int32_t csi_rs_estimated_channel_freq[frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size]; nr_get_csi_rs_signal(ue, proc, csirs_config_pdu, - ue->nr_csi_rs_info, - ue->nr_csi_rs_info->csi_rs_received_signal); + ue->nr_csi_info, + N_cdm_groups, + CDM_group_size, + k_prime, + l_prime, + j_cdm, + k_overline, + l_overline, + csi_rs_received_signal, + &rsrp, + &rsrp_dBm); nr_csi_rs_channel_estimation(ue, proc, csirs_config_pdu, - ue->nr_csi_rs_info, - ue->nr_csi_rs_info->csi_rs_generated_signal, - ue->nr_csi_rs_info->csi_rs_received_signal, - ue->nr_csi_rs_info->csi_rs_estimated_channel_freq, - ue->nr_csi_rs_info->noise_power); + ue->nr_csi_info, + (const int32_t **) ue->nr_csi_info->csi_rs_generated_signal, + csi_rs_received_signal, + N_cdm_groups, + CDM_group_size, + k_prime, + l_prime, + N_ports, + j_cdm, + k_overline, + l_overline, + csi_rs_ls_estimated_channel, + csi_rs_estimated_channel_freq, + &log2_re, + &log2_maxh, + &noise_power); + + nr_csi_rs_ri_estimation(ue, + csirs_config_pdu, + ue->nr_csi_info, + N_ports, + csi_rs_estimated_channel_freq, + log2_maxh, + &rank_indicator); + + nr_csi_rs_pmi_estimation(ue, + csirs_config_pdu, + ue->nr_csi_info, + N_ports, + csi_rs_estimated_channel_freq, + ue->nr_csi_info->csi_im_meas_computed ? ue->nr_csi_info->interference_plus_noise_power : noise_power, + rank_indicator, + log2_re, + i1, + i2, + &precoded_sinr_dB); + + nr_csi_rs_cqi_estimation(precoded_sinr_dB, &cqi); + + LOG_I(NR_PHY, "RSRP = %i dBm, RI = %i, i1 = %i.%i.%i, i2 = %i, SINR = %i dB, CQI = %i\n", + rsrp_dBm, rank_indicator+1, i1[0], i1[1], i1[2], i2[0], precoded_sinr_dB, cqi); + + // Send CSI measurements to MAC + fapi_nr_csirs_measurements_t csirs_measurements; + csirs_measurements.rsrp = rsrp; + csirs_measurements.rsrp_dBm = rsrp_dBm; + csirs_measurements.rank_indicator = rank_indicator; + csirs_measurements.i1 = *i1; + csirs_measurements.i2 = *i2; + csirs_measurements.cqi = cqi; + 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, gNB_id, NULL); + nr_fill_rx_indication(rx_ind, FAPI_NR_CSIRS_IND, gNB_id, ue, NULL, NULL, 1, proc, (void *)&csirs_measurements); + if (ue->if_inst && ue->if_inst->dl_indication) { + ue->if_inst->dl_indication(&dl_indication, NULL); + } else { + free(rx_ind); + } + return 0; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 5f3af5bb3958aa5b80f3338b06d503ffb4c08091..ea7bde5377ffc9eb10aed4f776849348c24ab6f5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -362,7 +362,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, nr_gold_pdsch(ue, i, ue->scramblingID_dlsch[i]); } - nr_init_csi_rs(fp, ue->nr_csi_rs_info->nr_gold_csi_rs, fp->Nid_cell); + nr_init_csi_rs(fp, ue->nr_csi_info->nr_gold_csi_rs, fp->Nid_cell); // initialize the pusch dmrs for (int i=0; iactive == 1) { LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot); nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csirs->csirs_pdu.csi_rs_pdu_rel15; - nr_generate_csi_rs(gNB->frame_parms, gNB->common_vars.txdataF, AMP, gNB->nr_csi_rs_info, csi_params, slot); + nr_generate_csi_rs(&gNB->frame_parms, gNB->common_vars.txdataF, AMP, gNB->nr_csi_info, csi_params, slot, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); csirs->active = 0; } } diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 7672aee8a25a7121e0061b5060f41cb16817d1ef..fa354d228432f85487f1e3f76c2597b250671c7f 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -405,7 +405,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus, UE_nr_rxtx_proc_t *proc, - void * typeSpecific); + void *typeSpecific); bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 046f67a7d000c15f034ea1d90f8de53f1f340610..f4c863bb408c417ae5728986f229a3880fc5b9f9 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -393,7 +393,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ case FAPI_NR_DL_CONFIG_TYPE_CSI_IM: csiim_config_pdu = &dl_config->dl_config_list[i].csiim_config_pdu.csiim_config_rel15; memcpy((void*)&(csiim_vars->csiim_config_pdu), (void*)csiim_config_pdu, sizeof(fapi_nr_dl_config_csiim_pdu_rel15_t)); - csirs_vars->active = true; + csiim_vars->active = true; break; case FAPI_NR_DL_CONFIG_TYPE_CSI_RS: csirs_config_pdu = &dl_config->dl_config_list[i].csirs_config_pdu.csirs_config_rel15; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 38fa3880bbd09183590b4c2c5cb674d880c9c992..4a58b0fe9bd04563b17255fa85338d4e462a6915 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -121,9 +121,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus, - UE_nr_rxtx_proc_t *proc, - void * typeSpecific){ - + UE_nr_rxtx_proc_t *proc, + void *typeSpecific){ NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; @@ -176,6 +175,11 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.rsrp_dBm = ue->measurements.rsrp_dBm[gNB_id]; break; + case FAPI_NR_CSIRS_IND: + memcpy(&rx_ind->rx_indication_body[n_pdus - 1].csirs_measurements, + (fapi_nr_csirs_measurements_t*)typeSpecific, + sizeof(*(fapi_nr_csirs_measurements_t*)typeSpecific)); + break; default: break; } @@ -1691,6 +1695,19 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, // do procedures for CSI-IM if ((ue->csiim_vars[gNB_id]) && (ue->csiim_vars[gNB_id]->active == 1)) { + int l_csiim[4] = {-1, -1, -1, -1}; + for(int symb_idx = 0; symb_idx < 4; symb_idx++) { + bool nr_slot_fep_done = false; + for (int symb_idx2 = 0; symb_idx2 < symb_idx; symb_idx2++) { + if (l_csiim[symb_idx2] == ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx]) { + nr_slot_fep_done = true; + } + } + l_csiim[symb_idx] = ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx]; + if(nr_slot_fep_done == false) { + nr_slot_fep(ue, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], nr_slot_rx); + } + } nr_ue_csi_im_procedures(ue, proc, gNB_id); ue->csiim_vars[gNB_id]->active = 0; } diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index e81871b146b33c96e05eda711877d96108c84815..39cd5407955400f69478c7cd2e7717ba5bc1515c 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -114,16 +114,16 @@ int main(int argc, char **argv) //int run_initial_sync=0; int loglvl = OAILOG_WARNING; uint8_t dlsch_threads = 0; - float target_error_rate = 0.01; - uint64_t SSB_positions=0x01; - uint16_t nb_symb_sch = 12; - uint16_t nb_rb = 50; - uint8_t Imcs = 9; - uint8_t mcs_table = 0; - double DS_TDL = .03; - cpuf = get_cpu_freq_GHz(); - char gNBthreads[128]="n"; - int Tbslbrm = 950984; + float target_error_rate = 0.01; + uint64_t SSB_positions=0x01; + uint16_t nb_symb_sch = 12; + uint16_t nb_rb = 50; + uint8_t Imcs = 9; + uint8_t mcs_table = 0; + double DS_TDL = .03; + cpuf = get_cpu_freq_GHz(); + char gNBthreads[128]="n"; + int Tbslbrm = 950984; if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == 0) { exit_fun("[NR_DLSCHSIM] Error, configuration module init failed\n"); @@ -299,7 +299,7 @@ int main(int argc, char **argv) break; case 'X': - strncpy(gNBthreads, optarg, sizeof(gNBthreads)); + strncpy(gNBthreads, optarg, sizeof(gNBthreads)-1); gNBthreads[sizeof(gNBthreads)-1]=0; break; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 8500749fe285827f94987e0bfb4fb084b99a56bd..efbb0d9e8418fe00e59c6d71e206f540caf8b90b 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -670,7 +670,7 @@ int main(int argc, char **argv) break; case 'X': - strncpy(gNBthreads, optarg, sizeof(gNBthreads)); + strncpy(gNBthreads, optarg, sizeof(gNBthreads)-1); gNBthreads[sizeof(gNBthreads)-1]=0; break; diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index 21802cd41a9c1a8f0036d9cc56d9ec566988d768..75e3d998ff9a1fb5771e99f86d30a4f6cdffb181 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -40,4 +40,4 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus, UE_nr_rxtx_proc_t *proc, - void * typeSpecific ) {} + void *typeSpecific ) {} diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 2ecc8f2e99f45d58f6dc66098f17314ac25fd467..1298434679b1e5158085b1a71e2c13fa151b7b51 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -158,9 +158,9 @@ typedef enum { {GNB_CONFIG_STRING_NRCELLID, NULL, 0, u64ptr:NULL, defint64val:1, TYPE_UINT64, 0}, \ {GNB_CONFIG_STRING_MINRXTXTIME, NULL, 0, iptr:NULL, defintval:2, TYPE_INT, 0}, \ {GNB_CONFIG_STRING_ULPRBBLACKLIST, NULL, 0, strptr:NULL, defstrval:"", TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_UMONDEFAULTDRB, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \ +{GNB_CONFIG_STRING_UMONDEFAULTDRB, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_FORCE256QAMOFF, GNB_CONFIG_HLP_FORCE256QAMOFF, PARAMFLAG_BOOL, iptr:NULL, defintval:0, TYPE_INT, 0}, \ -{GNB_CONFIG_STRING_ENABLE_SDAP, GNB_CONFIG_HLP_STRING_ENABLE_SDAP, PARAMFLAG_BOOL, iptr:NULL, defintval:0, TYPE_INT, 0} \ +{GNB_CONFIG_STRING_ENABLE_SDAP, GNB_CONFIG_HLP_STRING_ENABLE_SDAP, PARAMFLAG_BOOL, iptr:NULL, defintval:0, TYPE_INT, 0}, \ } #define GNB_GNB_ID_IDX 0 diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 9123afd3248bb6f750f2c43ffd66a00f9bab113b..58e435f3f15aecfefb749dd61e6455b5b95fd962 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -39,6 +39,7 @@ #include #include "NR_SubcarrierSpacing.h" +#include "NR_CSI-ReportConfig.h" #include "openair1/SCHED_NR_UE/harq_nr.h" #define NR_SHORT_BSR_TABLE_SIZE 32 @@ -63,6 +64,7 @@ #define CCCH_PAYLOAD_SIZE_MAX 512 #define RAR_PAYLOAD_SIZE_MAX 128 #define MAX_BWP_SIZE 275 +#define MAX_CSI_REPORTCONFIG 48 typedef enum frequency_range_e { FR1 = 0, @@ -512,5 +514,37 @@ typedef struct Type0_PDCCH_CSS_config_s { bool active; } NR_Type0_PDCCH_CSS_config_t; +typedef struct { + uint8_t nb_ssbri_cri; + uint8_t cri_ssbri_bitlen; + uint8_t rsrp_bitlen; + uint8_t diff_rsrp_bitlen; +} L1_RSRP_bitlen_t; + +typedef struct{ + uint8_t ri_restriction; + uint8_t cri_bitlen; + uint8_t ri_bitlen; + uint8_t li_bitlen[8]; + uint8_t pmi_x1_bitlen[8]; + uint8_t pmi_x2_bitlen[8]; + uint8_t cqi_bitlen[8]; +} CSI_Meas_bitlen_t; + +typedef struct nr_csi_report { + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; + long periodicity; + uint16_t offset; + long ** SSB_Index_list; + long ** CSI_Index_list; +// uint8_t nb_of_nzp_csi_report; + uint8_t nb_of_csi_ssb_report; + L1_RSRP_bitlen_t CSI_report_bitlen; + CSI_Meas_bitlen_t csi_meas_bitlen; + int codebook_mode; + int N1; + int N2; +} nr_csi_report_t; + #endif /*__LAYER2_MAC_H__ */ diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 5d6f9a2f2e7263afc56e7c55eda935c22b6b1622..e2a7efcaa0559f5f15b10e5703455b9e1b8662cb 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -4221,3 +4221,521 @@ bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, } return valid; } + +//! Calculating number of bits set +uint8_t number_of_bits_set(uint8_t buf) { + uint8_t nb_of_bits_set = 0; + uint8_t mask = 0xff; + uint8_t index = 0; + + for (index=7; (buf & mask) && (index>=0) ; index--){ + if (buf & (1<>=1; + } + return nb_of_bits_set; +} + +void compute_rsrp_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t nb_resources, + nr_csi_report_t *csi_report) { + + if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == csi_reportconfig->groupBasedBeamReporting.present) { + if (NULL != csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + csi_report->CSI_report_bitlen.nb_ssbri_cri = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; + else + /*! From Spec 38.331 + * nrofReportedRS + * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE + * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report. + * When the field is absent the UE applies the value 1 + */ + csi_report->CSI_report_bitlen.nb_ssbri_cri= 1; + } else + csi_report->CSI_report_bitlen.nb_ssbri_cri= 2; + + if (nb_resources) { + csi_report->CSI_report_bitlen.cri_ssbri_bitlen =ceil(log2 (nb_resources)); + csi_report->CSI_report_bitlen.rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + csi_report->CSI_report_bitlen.diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + } else { + csi_report->CSI_report_bitlen.cri_ssbri_bitlen =0; + csi_report->CSI_report_bitlen.rsrp_bitlen = 0; + csi_report->CSI_report_bitlen.diff_rsrp_bitlen =0; + } +} + +uint8_t compute_ri_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + nr_csi_report_t *csi_report) { + + struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; + uint8_t nb_allowed_ri, ri_bitlen; + uint8_t ri_restriction = 0; + + if (codebookConfig == NULL) { + csi_report->csi_meas_bitlen.ri_bitlen=0; + return ri_restriction; + } + + // codebook type1 single panel + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==codebookConfig->codebookType.choice.type1->subType.present){ + struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel; + if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two){ + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + nb_allowed_ri = number_of_bits_set(ri_restriction); + ri_bitlen = ceil(log2(nb_allowed_ri)); + + ri_bitlen = ri_bitlen<1?ri_bitlen:1; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + } + if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo){ + if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present == + NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) { + // 4 ports + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + nb_allowed_ri = number_of_bits_set(ri_restriction); + ri_bitlen = ceil(log2(nb_allowed_ri)); + + ri_bitlen = ri_bitlen<2?ri_bitlen:2; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + } + else { + // more than 4 ports + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + nb_allowed_ri = number_of_bits_set(ri_restriction); + ri_bitlen = ceil(log2(nb_allowed_ri)); + + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + } + } + return ri_restriction; + } + else + AssertFatal(1==0,"Other configurations not yet implemented\n"); + return -1; +} + +void compute_li_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t ri_restriction, + nr_csi_report_t *csi_report) { + + struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; + for(int i=0; i<8; i++) { + if (codebookConfig == NULL || ((ri_restriction>>i)&0x01) == 0) + csi_report->csi_meas_bitlen.li_bitlen[i]=0; + else { + // codebook type1 single panel + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==codebookConfig->codebookType.choice.type1->subType.present) + csi_report->csi_meas_bitlen.li_bitlen[i]=ceil(log2(i+1))<2?ceil(log2(i+1)):2; + else + AssertFatal(1==0,"Other configurations not yet implemented\n"); + } + } +} + +void get_n1n2_o1o2_singlepanel(int *n1, int *n2, int *o1, int *o2, + struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo *morethantwo) { + + // Table 5.2.2.2.1-2 in 38.214 for supported configurations + switch(morethantwo->n1_n2.present){ + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction): + *n1 = 2; + *n2 = 1; + *o1 = 4; + *o2 = 1; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_two_TypeI_SinglePanel_Restriction): + *n1 = 2; + *n2 = 2; + *o1 = 4; + *o2 = 4; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_one_TypeI_SinglePanel_Restriction): + *n1 = 4; + *n2 = 1; + *o1 = 4; + *o2 = 1; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_three_two_TypeI_SinglePanel_Restriction): + *n1 = 3; + *n2 = 2; + *o1 = 4; + *o2 = 4; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_six_one_TypeI_SinglePanel_Restriction): + *n1 = 6; + *n2 = 1; + *o1 = 4; + *o2 = 1; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_two_TypeI_SinglePanel_Restriction): + *n1 = 4; + *n2 = 2; + *o1 = 4; + *o2 = 4; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_eight_one_TypeI_SinglePanel_Restriction): + *n1 = 8; + *n2 = 1; + *o1 = 4; + *o2 = 1; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_three_TypeI_SinglePanel_Restriction): + *n1 = 4; + *n2 = 3; + *o1 = 4; + *o2 = 4; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_six_two_TypeI_SinglePanel_Restriction): + *n1 = 4; + *n2 = 2; + *o1 = 4; + *o2 = 4; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_twelve_one_TypeI_SinglePanel_Restriction): + *n1 = 12; + *n2 = 1; + *o1 = 4; + *o2 = 1; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_four_TypeI_SinglePanel_Restriction): + *n1 = 4; + *n2 = 4; + *o1 = 4; + *o2 = 4; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_eight_two_TypeI_SinglePanel_Restriction): + *n1 = 8; + *n2 = 2; + *o1 = 4; + *o2 = 4; + break; + case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_sixteen_one_TypeI_SinglePanel_Restriction): + *n1 = 16; + *n2 = 1; + *o1 = 4; + *o2 = 1; + break; + default: + AssertFatal(1==0,"Not supported configuration for n1_n2 in codebook configuration"); + } +} + +void get_x1x2_bitlen_singlepanel(int n1, int n2, int o1, int o2, + int *x1, int *x2, int rank, int codebook_mode) { + + // Table 6.3.1.1.2-1 in 38.212 + switch(rank){ + case 1: + if(n2>1) { + if (codebook_mode == 1) { + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); + *x2 = 2; + } + else { + *x1 = ceil(log2(n1*o1/2)) + ceil(log2(n2*o2/2)); + *x2 = 4; + } + } + else{ + if (codebook_mode == 1) { + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); + *x2 = 2; + } + else { + *x1 = ceil(log2(n1*o1/2)); + *x2 = 4; + } + } + break; + case 2: + if(n1*n2 == 2) { + if (codebook_mode == 1) { + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); + *x2 = 1; + } + else { + *x1 = ceil(log2(n1*o1/2)); + *x2 = 3; + } + *x1 += 1; + } + else { + if(n2>1) { + if (codebook_mode == 1) { + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); + *x2 = 3; + } + else { + *x1 = ceil(log2(n1*o1/2)) + ceil(log2(n2*o2/2)); + *x2 = 3; + } + } + else{ + if (codebook_mode == 1) { + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); + *x2 = 1; + } + else { + *x1 = ceil(log2(n1*o1/2)); + *x2 = 3; + } + } + *x1 += 2; + } + break; + case 3: + case 4: + if(n1*n2 == 2) { + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); + *x2 = 1; + } + else { + if(n1*n2 >= 8) { + *x1 = ceil(log2(n1*o1/2)) + ceil(log2(n2*o2)) + 2; + *x2 = 1; + } + else { + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)) + 2; + *x2 = 1; + } + } + break; + case 5: + case 6: + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); + *x2 = 1; + break; + case 7: + case 8: + if(n1 == 4 && n2 == 1) { + *x1 = ceil(log2(n1*o1/2)) + ceil(log2(n2*o2)); + *x2 = 1; + } + else { + if(n1 > 2 && n2 == 2) { + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2/2)); + *x2 = 1; + } + else { + *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); + *x2 = 1; + } + } + break; + default: + AssertFatal(1==0,"Invalid rank in x1 x2 bit length computation\n"); + } +} + + +void compute_pmi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t ri_restriction, + nr_csi_report_t *csi_report) { + + struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; + for(int i=0; i<8; i++) { + csi_report->csi_meas_bitlen.pmi_x1_bitlen[i]=0; + csi_report->csi_meas_bitlen.pmi_x2_bitlen[i]=0; + if (codebookConfig == NULL || ((ri_restriction>>i)&0x01) == 0) + return; + else { + if(codebookConfig->codebookType.present == NR_CodebookConfig__codebookType_PR_type1) { + if(codebookConfig->codebookType.choice.type1->subType.present == NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel) { + if(codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present == + NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two) { + csi_report->N1 = 1; + csi_report->N2 = 1; + if (i==0) + csi_report->csi_meas_bitlen.pmi_x2_bitlen[i]=2; + if (i==1) + csi_report->csi_meas_bitlen.pmi_x2_bitlen[i]=1; + } + else { // more than two + int n1,n2,o1,o2,x1,x2; + get_n1n2_o1o2_singlepanel(&n1,&n2,&o1,&o2,codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.moreThanTwo); + get_x1x2_bitlen_singlepanel(n1,n2,o1,o2,&x1,&x2,i+1,codebookConfig->codebookType.choice.type1->codebookMode); + csi_report->N1 = n1; + csi_report->N2 = n2; + csi_report->codebook_mode = codebookConfig->codebookType.choice.type1->codebookMode; + csi_report->csi_meas_bitlen.pmi_x1_bitlen[i]=x1; + csi_report->csi_meas_bitlen.pmi_x2_bitlen[i]=x2; + } + } + else + AssertFatal(1==0,"Type1 Multi-panel Codebook Config not yet implemented\n"); + } + else + AssertFatal(1==0,"Type2 Codebook Config not yet implemented\n"); + } + } +} + +void compute_cqi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t ri_restriction, + nr_csi_report_t *csi_report) { + + struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; + struct NR_CSI_ReportConfig__reportFreqConfiguration *freq_config = csi_reportconfig->reportFreqConfiguration; + + if (*freq_config->cqi_FormatIndicator == NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI) { + for(int i=0; i<8; i++) { + if ((ri_restriction>>i)&0x01) { + csi_report->csi_meas_bitlen.cqi_bitlen[i] = 4; + if(codebookConfig != NULL) { + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel == codebookConfig->codebookType.choice.type1->subType.present){ + struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel; + if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo) { + if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present > + NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) { + // more than 4 antenna ports + if (i > 4) + csi_report->csi_meas_bitlen.cqi_bitlen[i] += 4; // CQI for second TB + } + } + } + } + } + else + csi_report->csi_meas_bitlen.cqi_bitlen[i] = 0; + } + } + else + AssertFatal(1==0,"Sub-band CQI reporting not yet supported"); +} + +//!TODO : same function can be written to handle csi_resources +void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report_t *csi_report_template) { + uint8_t csi_report_id = 0; + uint8_t nb_resources = 0; + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; + NR_CSI_ResourceConfigId_t csi_ResourceConfigId; + struct NR_CSI_ResourceConfig *csi_resourceconfig; + + // for each CSI measurement report configuration (list of CSI-ReportConfig) + LOG_D(NR_MAC,"Searching %d csi_reports\n",csi_MeasConfig->csi_ReportConfigToAddModList->list.count); + for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + // MAC structure for CSI measurement reports (per UE and per report) + nr_csi_report_t *csi_report = &csi_report_template[csi_report_id]; + // csi-ResourceConfigId of a CSI-ResourceConfig included in the configuration + // (either CSI-RS or SSB) + csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement; + // looking for CSI-ResourceConfig + int found_resource = 0; + int csi_resourceidx = 0; + while (found_resource == 0 && csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count) { + csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; + if ( csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) + found_resource = 1; + csi_resourceidx++; + } + AssertFatal(found_resource==1,"Not able to found any CSI-ResourceConfig with csi-ResourceConfigId %ld\n", + csi_ResourceConfigId); + + long resourceType = csi_resourceconfig->resourceType; + + reportQuantity_type = csi_reportconfig->reportQuantity.present; + csi_report->reportQuantity_type = reportQuantity_type; + + // setting the CSI or SSB index list + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == csi_report->reportQuantity_type) { + for (int csi_idx = 0; csi_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_idx++) { + if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ + //We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig + nb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.count; + csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.array; + csi_report->CSI_Index_list = NULL; + break; + } + } + } + else { + if (resourceType == NR_CSI_ResourceConfig__resourceType_periodic) { + AssertFatal(csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList != NULL, + "Wrong settings! Report quantity requires CSI-RS but csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList is NULL\n"); + for (int csi_idx = 0; csi_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_idx++) { + if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { + //For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212 + nb_resources = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.count; + csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.array; + csi_report->SSB_Index_list = NULL; + break; + } + } + } + else AssertFatal(1==0,"Only periodic resource configuration currently supported\n"); + } + LOG_D(NR_MAC,"nb_resources %d\n",nb_resources); + // computation of bit length depending on the report type + switch(reportQuantity_type){ + case (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP): + compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report); + break; + case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP): + compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report); + break; + case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI): + csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources)); + csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report); + compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); + break; + case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI): + csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources)); + csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report); + compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); + compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); + break; + case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI): + csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources)); + csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report); + compute_li_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); + compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); + compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); + break; + default: + AssertFatal(1==0,"Not yet supported CSI report quantity type"); + } + } +} + +uint16_t nr_get_csi_bitlen(nr_csi_report_t *csi_report_template, uint8_t csi_report_id) { + + uint16_t csi_bitlen = 0; + uint16_t max_bitlen = 0; + L1_RSRP_bitlen_t *CSI_report_bitlen = NULL; + CSI_Meas_bitlen_t *csi_meas_bitlen = NULL; + + if (csi_report_template[csi_report_id].reportQuantity_type == NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP || + csi_report_template[csi_report_id].reportQuantity_type == NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP) { + CSI_report_bitlen = &(csi_report_template[csi_report_id].CSI_report_bitlen); // This might need to be moodif for Aperiodic CSI-RS measurements + csi_bitlen += ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) + + CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen * + (CSI_report_bitlen->nb_ssbri_cri -1 ))); + } else { + csi_meas_bitlen = &(csi_report_template[csi_report_id].csi_meas_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements + uint16_t temp_bitlen; + for (int i=0; i<8; i++) { + temp_bitlen = (csi_meas_bitlen->cri_bitlen+ + csi_meas_bitlen->ri_bitlen+ + csi_meas_bitlen->li_bitlen[i]+ + csi_meas_bitlen->cqi_bitlen[i]+ + csi_meas_bitlen->pmi_x1_bitlen[i]+ + csi_meas_bitlen->pmi_x2_bitlen[i]); + if(temp_bitlen>max_bitlen) + max_bitlen = temp_bitlen; + } + csi_bitlen += max_bitlen; + } + + return csi_bitlen; +} \ No newline at end of file diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 6caddcff78e87c71294d8f7e3e13ed6ff914cf13..2b8d3c6652770bb5df056a1d3c77319f096d2b91 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -105,7 +105,7 @@ uint8_t get_pusch_mcs_table(long *mcs_Table, uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, uint8_t nb_preambles, uint8_t unpaired, - frequency_range_t); + frequency_range_t); int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPrecoder); @@ -234,4 +234,36 @@ void nr_mac_gNB_rrc_ul_failure_reset(const module_id_t Mod_instP, const frame_t frameP, const sub_frame_t subframeP, const rnti_t rntiP); + +uint8_t number_of_bits_set(uint8_t buf); + +void compute_rsrp_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t nb_resources, + nr_csi_report_t *csi_report); + +uint8_t compute_ri_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + nr_csi_report_t *csi_report); + +void compute_li_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t ri_restriction, + nr_csi_report_t *csi_report); + +void get_n1n2_o1o2_singlepanel(int *n1, int *n2, int *o1, int *o2, + struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo *morethantwo); + +void get_x1x2_bitlen_singlepanel(int n1, int n2, int o1, int o2, + int *x1, int *x2, int rank, int codebook_mode); + +void compute_pmi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t ri_restriction, + nr_csi_report_t *csi_report); + +void compute_cqi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t ri_restriction, + nr_csi_report_t *csi_report); + +void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report_t *csi_report_template); + +uint16_t nr_get_csi_bitlen(nr_csi_report_t *csi_report_template, uint8_t csi_report_id); + #endif diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 05b6634655bbe9581aecf843cd7427ee0c7914aa..35302eaafba9562134574c3b317b22c9b3a3dc26 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -399,6 +399,11 @@ typedef struct { /// measured SSB RSRP in dBm short ssb_rsrp_dBm; + nr_csi_report_t csi_report_template[MAX_CSI_REPORTCONFIG]; + + /// measurements from CSI-RS + fapi_nr_csirs_measurements_t csirs_measurements; + /// Last NDI of UL HARQ processes uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES]; /// first ULTX of UL HARQ processes diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index aa6879146643364686dc2d2c181631488c079ab9..161799fb6677c94a132cc6ac647683be26b0592e 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -194,6 +194,7 @@ int nr_get_sf_retxBSRTimer(uint8_t retxBSR_Timer); int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, fapi_nr_dci_indication_pdu_t *dci_ind); int nr_ue_process_dci_indication_pdu(module_id_t module_id, int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); +int8_t nr_ue_process_csirs_measurements(module_id_t module_id, frame_t frame, int slot, fapi_nr_csirs_measurements_t *csirs_measurements); uint32_t get_ssb_frame(uint32_t test); @@ -213,6 +214,18 @@ uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, NR_CSI_ResourceConfigId_t csi_ResourceConfigId, NR_CSI_MeasConfig_t *csi_MeasConfig); +uint8_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig); + +uint8_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig); + uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch, int csi_report_id, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index ccb1b4e72a1dd9f311668cb0b190beea81a0d03d..7df61be6275f9660301fd3d3d3b56e1ae5553c5e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1462,6 +1462,16 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr } +int8_t nr_ue_process_csirs_measurements(module_id_t module_id, + frame_t frame, + int slot, + fapi_nr_csirs_measurements_t *csirs_measurements) { + LOG_D(NR_MAC,"(%d.%d) Received CSI-RS measurements\n", frame, slot); + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + memcpy(&mac->csirs_measurements, csirs_measurements, sizeof(*csirs_measurements)); + return 0; +} + void set_harq_status(NR_UE_MAC_INST_t *mac, uint8_t pucch_id, uint8_t harq_id, @@ -2564,13 +2574,17 @@ uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP: n_csi_bits = get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); break; - case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP: case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI: + n_csi_bits = get_csirs_RI_PMI_CQI_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); + break; + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP: + n_csi_bits = get_csirs_RSRP_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); + break; case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1: case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI: case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI: case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI: - LOG_E(NR_MAC,"Measurement report based on CSI-RS not available\n"); + LOG_E(NR_MAC,"Measurement report %d based on CSI-RS is not available\n", csi_reportconfig->reportQuantity.present); break; default: AssertFatal(1==0,"Invalid CSI report quantity type %d\n",csi_reportconfig->reportQuantity.present); @@ -2658,6 +2672,122 @@ uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, return bits; } +uint8_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig) { + + int n_bits = 0; + uint32_t temp_payload = 0; + + for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { + + struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; + if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) { + + for (int csi_idx = 0; csi_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_idx++) { + if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { + + nr_csi_report_t *csi_report = &mac->csi_report_template[csi_reportconfig->reportConfigId]; + compute_csi_bitlen(csi_MeasConfig, mac->csi_report_template); + n_bits = nr_get_csi_bitlen(mac->csi_report_template, csi_reportconfig->reportConfigId); + + int cri_bitlen = csi_report->csi_meas_bitlen.cri_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_x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[mac->csirs_measurements.rank_indicator]; + int cqi_bitlen = csi_report->csi_meas_bitlen.cqi_bitlen[mac->csirs_measurements.rank_indicator]; + int padding_bitlen = n_bits - (cri_bitlen + ri_bitlen + pmi_x1_bitlen + pmi_x2_bitlen + cqi_bitlen); + + // 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)) | + (mac->csirs_measurements.i1<<(cri_bitlen+cqi_bitlen+pmi_x2_bitlen)) | + (mac->csirs_measurements.i2<<(cri_bitlen+cqi_bitlen)) | + (mac->csirs_measurements.cqi<csi_part1_payload = temp_payload; + return n_bits; +} + +uint8_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig) { + + int n_bits = 0; + uint32_t temp_payload = 0; + + for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { + + struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; + if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) { + + for (int csi_idx = 0; csi_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_idx++) { + if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { + + nr_csi_report_t *csi_report = &mac->csi_report_template[csi_reportconfig->reportConfigId]; + compute_csi_bitlen(csi_MeasConfig, mac->csi_report_template); + n_bits = nr_get_csi_bitlen(mac->csi_report_template, csi_reportconfig->reportConfigId); + + int cri_ssbri_bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen; + int rsrp_bitlen = csi_report->CSI_report_bitlen.rsrp_bitlen; + int diff_rsrp_bitlen = csi_report->CSI_report_bitlen.diff_rsrp_bitlen; + + if (cri_ssbri_bitlen > 0) { + LOG_E(NR_MAC, "Implementation for cri_ssbri_bitlen>0 is not supported yet!\n");; + } + + // TODO: Improvements will be needed to cri_ssbri_bitlen>0 + // 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; + } + + 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, "rsrp_bitlen = %d\n", rsrp_bitlen); + LOG_D(NR_MAC, "diff_rsrp_bitlen = %d\n", diff_rsrp_bitlen); + + LOG_D(NR_MAC, "n_bits = %d\n", n_bits); + LOG_D(NR_MAC, "csi_part1_payload = 0x%x\n", temp_payload); + + break; + } + } + } + } + + pucch->csi_part1_payload = temp_payload; + return n_bits; +} // returns index from RSRP // according to Table 10.1.6.1-1 in 38.133 diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index d32709e73136cd4cc66581f359ea8e5410a7a72b..b80bd120fc29d90c0bc1700c6e21545cc8bd9cb6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -927,8 +927,6 @@ void nr_schedule_ue_spec(module_id_t module_id, if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot)) return; - //if (slot==7 || slot == 17) return; - /* PREPROCESSOR */ gNB_mac->pre_processor_dl(module_id, frame, slot); const int CC_id = 0; @@ -1318,7 +1316,7 @@ void nr_schedule_ue_spec(module_id_t module_id, lcid < 4 ? "DCCH" : "DTCH", lcid, ndata, - bufEnd-buf-+sizeof(NR_MAC_SUBHEADER_LONG)); + bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); if (len == 0) break; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 01a574f83c2a80ee990b3b490a172a468fe75a5d..0acf5c41ba42dfd0560635ae627ddea7139a7d3b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1436,7 +1436,6 @@ void set_r_pucch_parms(int rsetindex, *start_symbol_index = default_pucch_firstsymb[rsetindex]; } - void prepare_dci(const NR_CellGroupConfig_t *CellGroup, dci_pdu_rel15_t *dci_pdu_rel15, nr_dci_format_t format, @@ -2386,7 +2385,7 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf CellGroup->spCellConfig->spCellConfigDedicated && CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig && CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup) { - compute_csi_bitlen(CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE); + compute_csi_bitlen(CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE->csi_report_template); } NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -3002,7 +3001,7 @@ void nr_mac_update_timers(module_id_t module_id, cg->spCellConfig->spCellConfigDedicated && cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig && cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup) { - compute_csi_bitlen (cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE); + compute_csi_bitlen (cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE->csi_report_template); } NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index a57b04668babc9076343dcc561ea2c5cc66bf506..fb8121978b0bb916fa29fcd03018bde99fe54fc5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -169,530 +169,6 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, } } - -//! Calculating number of bits set -uint8_t number_of_bits_set (uint8_t buf){ - uint8_t nb_of_bits_set = 0; - uint8_t mask = 0xff; - uint8_t index = 0; - - for (index=7; (buf & mask) && (index>=0) ; index--){ - if (buf & (1<>=1; - } - return nb_of_bits_set; -} - - -void compute_rsrp_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, - uint8_t nb_resources, - nr_csi_report_t *csi_report) { - - if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == csi_reportconfig->groupBasedBeamReporting.present) { - if (NULL != csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS) - csi_report->CSI_report_bitlen.nb_ssbri_cri = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; - else - /*! From Spec 38.331 - * nrofReportedRS - * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE - * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report. - * When the field is absent the UE applies the value 1 - */ - csi_report->CSI_report_bitlen.nb_ssbri_cri= 1; - } else - csi_report->CSI_report_bitlen.nb_ssbri_cri= 2; - - if (nb_resources) { - csi_report->CSI_report_bitlen.cri_ssbri_bitlen =ceil(log2 (nb_resources)); - csi_report->CSI_report_bitlen.rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP - csi_report->CSI_report_bitlen.diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP - } else { - csi_report->CSI_report_bitlen.cri_ssbri_bitlen =0; - csi_report->CSI_report_bitlen.rsrp_bitlen = 0; - csi_report->CSI_report_bitlen.diff_rsrp_bitlen =0; - } -} - - -uint8_t compute_ri_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, - nr_csi_report_t *csi_report){ - - struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; - uint8_t nb_allowed_ri, ri_bitlen; - uint8_t ri_restriction = 0; - - if (codebookConfig == NULL) { - csi_report->csi_meas_bitlen.ri_bitlen=0; - return ri_restriction; - } - - // codebook type1 single panel - if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==codebookConfig->codebookType.choice.type1->subType.present){ - struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel; - if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two){ - - ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; - - nb_allowed_ri = number_of_bits_set(ri_restriction); - ri_bitlen = ceil(log2(nb_allowed_ri)); - - ri_bitlen = ri_bitlen<1?ri_bitlen:1; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel - csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; - } - if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo){ - if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present == - NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) { - // 4 ports - - ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; - - nb_allowed_ri = number_of_bits_set(ri_restriction); - ri_bitlen = ceil(log2(nb_allowed_ri)); - - ri_bitlen = ri_bitlen<2?ri_bitlen:2; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel - csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; - } - else { - // more than 4 ports - - ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; - - nb_allowed_ri = number_of_bits_set(ri_restriction); - ri_bitlen = ceil(log2(nb_allowed_ri)); - - csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; - } - } - return ri_restriction; - } - else - AssertFatal(1==0,"Other configurations not yet implemented\n"); - return -1; -} - -void compute_li_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, - uint8_t ri_restriction, - nr_csi_report_t *csi_report){ - - struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; - for(int i=0; i<8; i++) { - if (codebookConfig == NULL || ((ri_restriction>>i)&0x01) == 0) - csi_report->csi_meas_bitlen.li_bitlen[i]=0; - else { - // codebook type1 single panel - if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==codebookConfig->codebookType.choice.type1->subType.present) - csi_report->csi_meas_bitlen.li_bitlen[i]=ceil(log2(i+1))<2?ceil(log2(i+1)):2; - else - AssertFatal(1==0,"Other configurations not yet implemented\n"); - } - } -} - -void get_n1n2_o1o2_singlepanel(int *n1, int *n2, int *o1, int *o2, - struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo *morethantwo) { - - // Table 5.2.2.2.1-2 in 38.214 for supported configurations - switch(morethantwo->n1_n2.present){ - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction): - *n1 = 2; - *n2 = 1; - *o1 = 4; - *o2 = 1; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_two_TypeI_SinglePanel_Restriction): - *n1 = 2; - *n2 = 2; - *o1 = 4; - *o2 = 4; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_one_TypeI_SinglePanel_Restriction): - *n1 = 4; - *n2 = 1; - *o1 = 4; - *o2 = 1; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_three_two_TypeI_SinglePanel_Restriction): - *n1 = 3; - *n2 = 2; - *o1 = 4; - *o2 = 4; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_six_one_TypeI_SinglePanel_Restriction): - *n1 = 6; - *n2 = 1; - *o1 = 4; - *o2 = 1; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_two_TypeI_SinglePanel_Restriction): - *n1 = 4; - *n2 = 2; - *o1 = 4; - *o2 = 4; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_eight_one_TypeI_SinglePanel_Restriction): - *n1 = 8; - *n2 = 1; - *o1 = 4; - *o2 = 1; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_three_TypeI_SinglePanel_Restriction): - *n1 = 4; - *n2 = 3; - *o1 = 4; - *o2 = 4; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_six_two_TypeI_SinglePanel_Restriction): - *n1 = 4; - *n2 = 2; - *o1 = 4; - *o2 = 4; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_twelve_one_TypeI_SinglePanel_Restriction): - *n1 = 12; - *n2 = 1; - *o1 = 4; - *o2 = 1; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_four_four_TypeI_SinglePanel_Restriction): - *n1 = 4; - *n2 = 4; - *o1 = 4; - *o2 = 4; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_eight_two_TypeI_SinglePanel_Restriction): - *n1 = 8; - *n2 = 2; - *o1 = 4; - *o2 = 4; - break; - case (NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_sixteen_one_TypeI_SinglePanel_Restriction): - *n1 = 16; - *n2 = 1; - *o1 = 4; - *o2 = 1; - break; - default: - AssertFatal(1==0,"Not supported configuration for n1_n2 in codebook configuration"); - } -} - -void get_x1x2_bitlen_singlepanel(int n1, int n2, int o1, int o2, - int *x1, int *x2, int rank, int codebook_mode) { - - // Table 6.3.1.1.2-1 in 38.212 - switch(rank){ - case 1: - if(n2>1) { - if (codebook_mode == 1) { - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); - *x2 = 2; - } - else { - *x1 = ceil(log2(n1*o1/2)) + ceil(log2(n2*o2/2)); - *x2 = 4; - } - } - else{ - if (codebook_mode == 1) { - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); - *x2 = 2; - } - else { - *x1 = ceil(log2(n1*o1/2)); - *x2 = 4; - } - } - break; - case 2: - if(n1*n2 == 2) { - if (codebook_mode == 1) { - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); - *x2 = 1; - } - else { - *x1 = ceil(log2(n1*o1/2)); - *x2 = 3; - } - *x1 += 1; - } - else { - if(n2>1) { - if (codebook_mode == 1) { - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); - *x2 = 3; - } - else { - *x1 = ceil(log2(n1*o1/2)) + ceil(log2(n2*o2/2)); - *x2 = 3; - } - } - else{ - if (codebook_mode == 1) { - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); - *x2 = 1; - } - else { - *x1 = ceil(log2(n1*o1/2)); - *x2 = 3; - } - } - *x1 += 2; - } - break; - case 3: - case 4: - if(n1*n2 == 2) { - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); - *x2 = 1; - } - else { - if(n1*n2 >= 8) { - *x1 = ceil(log2(n1*o1/2)) + ceil(log2(n2*o2)) + 2; - *x2 = 1; - } - else { - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)) + 2; - *x2 = 1; - } - } - break; - case 5: - case 6: - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); - *x2 = 1; - break; - case 7: - case 8: - if(n1 == 4 && n2 == 1) { - *x1 = ceil(log2(n1*o1/2)) + ceil(log2(n2*o2)); - *x2 = 1; - } - else { - if(n1 > 2 && n2 == 2) { - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2/2)); - *x2 = 1; - } - else { - *x1 = ceil(log2(n1*o1)) + ceil(log2(n2*o2)); - *x2 = 1; - } - } - break; - default: - AssertFatal(1==0,"Invalid rank in x1 x2 bit length computation\n"); - } -} - - -void compute_pmi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, - uint8_t ri_restriction, - nr_csi_report_t *csi_report){ - - struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; - for(int i=0; i<8; i++) { - csi_report->csi_meas_bitlen.pmi_x1_bitlen[i]=0; - csi_report->csi_meas_bitlen.pmi_x2_bitlen[i]=0; - if (codebookConfig == NULL || ((ri_restriction>>i)&0x01) == 0) - return; - else { - if(codebookConfig->codebookType.present == NR_CodebookConfig__codebookType_PR_type1) { - if(codebookConfig->codebookType.choice.type1->subType.present == NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel) { - if(codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present == - NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two) { - csi_report->N1 = 1; - csi_report->N2 = 1; - if (i==0) - csi_report->csi_meas_bitlen.pmi_x2_bitlen[i]=2; - if (i==1) - csi_report->csi_meas_bitlen.pmi_x2_bitlen[i]=1; - } - else { // more than two - int n1,n2,o1,o2,x1,x2; - get_n1n2_o1o2_singlepanel(&n1,&n2,&o1,&o2,codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.moreThanTwo); - get_x1x2_bitlen_singlepanel(n1,n2,o1,o2,&x1,&x2,i+1,codebookConfig->codebookType.choice.type1->codebookMode); - csi_report->N1 = n1; - csi_report->N2 = n2; - csi_report->codebook_mode = codebookConfig->codebookType.choice.type1->codebookMode; - csi_report->csi_meas_bitlen.pmi_x1_bitlen[i]=x1; - csi_report->csi_meas_bitlen.pmi_x2_bitlen[i]=x2; - } - } - else - AssertFatal(1==0,"Type1 Multi-panel Codebook Config not yet implemented\n"); - } - else - AssertFatal(1==0,"Type2 Codebook Config not yet implemented\n"); - } - } -} - -void compute_cqi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, - uint8_t ri_restriction, - nr_csi_report_t *csi_report){ - - struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; - struct NR_CSI_ReportConfig__reportFreqConfiguration *freq_config = csi_reportconfig->reportFreqConfiguration; - - if (*freq_config->cqi_FormatIndicator == NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI) { - for(int i=0; i<8; i++) { - if ((ri_restriction>>i)&0x01) { - csi_report->csi_meas_bitlen.cqi_bitlen[i] = 4; - if(codebookConfig != NULL) { - if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel == codebookConfig->codebookType.choice.type1->subType.present){ - struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel; - if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo) { - if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present > - NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) { - // more than 4 antenna ports - if (i > 4) - csi_report->csi_meas_bitlen.cqi_bitlen[i] += 4; // CQI for second TB - } - } - } - } - } - else - csi_report->csi_meas_bitlen.cqi_bitlen[i] = 0; - } - } - else - AssertFatal(1==0,"Sub-band CQI reporting not yet supported"); -} - -//!TODO : same function can be written to handle csi_resources -void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE){ - uint8_t csi_report_id = 0; - uint8_t nb_resources = 0; - NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; - NR_CSI_ResourceConfigId_t csi_ResourceConfigId; - struct NR_CSI_ResourceConfig *csi_resourceconfig; - - // for each CSI measurement report configuration (list of CSI-ReportConfig) - LOG_D(NR_MAC,"Searching %d csi_reports\n",csi_MeasConfig->csi_ReportConfigToAddModList->list.count); - for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ - struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; - // MAC structure for CSI measurement reports (per UE and per report) - nr_csi_report_t *csi_report = &UE->csi_report_template[csi_report_id]; - // csi-ResourceConfigId of a CSI-ResourceConfig included in the configuration - // (either CSI-RS or SSB) - csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement; - // looking for CSI-ResourceConfig - int found_resource = 0; - int csi_resourceidx = 0; - while (found_resource == 0 && csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count) { - csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; - if ( csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) - found_resource = 1; - csi_resourceidx++; - } - AssertFatal(found_resource==1,"Not able to found any CSI-ResourceConfig with csi-ResourceConfigId %ld\n", - csi_ResourceConfigId); - - long resourceType = csi_resourceconfig->resourceType; - - reportQuantity_type = csi_reportconfig->reportQuantity.present; - csi_report->reportQuantity_type = reportQuantity_type; - - // setting the CSI or SSB index list - if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == csi_report->reportQuantity_type) { - for (int csi_idx = 0; csi_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_idx++) { - if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceSetId == - *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ - //We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig - nb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.count; - csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.array; - csi_report->CSI_Index_list = NULL; - break; - } - } - } - else { - if (resourceType == NR_CSI_ResourceConfig__resourceType_periodic) { - AssertFatal(csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList != NULL, - "Wrong settings! Report quantity requires CSI-RS but csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList is NULL\n"); - for (int csi_idx = 0; csi_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_idx++) { - if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_ResourceSetId == - *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { - //For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212 - nb_resources = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.count; - csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.array; - csi_report->SSB_Index_list = NULL; - break; - } - } - } - else AssertFatal(1==0,"Only periodic resource configuration currently supported\n"); - } - LOG_D(NR_MAC,"nb_resources %d\n",nb_resources); - // computation of bit length depending on the report type - switch(reportQuantity_type){ - case (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP): - compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report); - break; - case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP): - compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report); - break; - case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI): - csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources)); - csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report); - compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); - break; - case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI): - csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources)); - csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report); - compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); - compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); - break; - case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI): - csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources)); - csi_report->csi_meas_bitlen.ri_restriction = compute_ri_bitlen(csi_reportconfig, csi_report); - compute_li_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); - compute_cqi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); - compute_pmi_bitlen(csi_reportconfig, csi_report->csi_meas_bitlen.ri_restriction, csi_report); - break; - default: - AssertFatal(1==0,"Not yet supported CSI report quantity type"); - } - } -} - - -uint16_t nr_get_csi_bitlen(NR_UE_info_t *UE, - uint8_t csi_report_id) { - - uint16_t csi_bitlen = 0; - uint16_t max_bitlen = 0; - L1_RSRP_bitlen_t * CSI_report_bitlen = NULL; - CSI_Meas_bitlen_t * csi_meas_bitlen = NULL; - - if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP==UE->csi_report_template[csi_report_id].reportQuantity_type|| - NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP==UE->csi_report_template[csi_report_id].reportQuantity_type){ - CSI_report_bitlen = &(UE->csi_report_template[csi_report_id].CSI_report_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements - csi_bitlen+= ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) + - CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen * - (CSI_report_bitlen->nb_ssbri_cri -1 ))); - } else{ - csi_meas_bitlen = &(UE->csi_report_template[csi_report_id].csi_meas_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements - uint16_t temp_bitlen; - for (int i=0; i<8; i++) { - temp_bitlen = (csi_meas_bitlen->cri_bitlen+ - csi_meas_bitlen->ri_bitlen+ - csi_meas_bitlen->li_bitlen[i]+ - csi_meas_bitlen->cqi_bitlen[i]+ - csi_meas_bitlen->pmi_x1_bitlen[i]+ - csi_meas_bitlen->pmi_x2_bitlen[i]); - if(temp_bitlen>max_bitlen) - max_bitlen = temp_bitlen; - } - csi_bitlen += max_bitlen; - } - - return csi_bitlen; -} - - void nr_csi_meas_reporting(int Mod_idP, frame_t frame, sub_frame_t slot) { @@ -700,7 +176,6 @@ void nr_csi_meas_reporting(int Mod_idP, NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - UE_iterator(RC.nrmac[Mod_idP]->UE_info.list, UE ) { const NR_CellGroupConfig_t *CellGroup = UE->CellGroup; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -760,7 +235,7 @@ void nr_csi_meas_reporting(int Mod_idP, curr_pucch->frame = frame; curr_pucch->ul_slot = sched_slot; curr_pucch->resource_indicator = res_index; - curr_pucch->csi_bits += nr_get_csi_bitlen(UE,csi_report_id); + curr_pucch->csi_bits += nr_get_csi_bitlen(UE->csi_report_template, csi_report_id); const NR_SIB1_t *sib1 = RC.nrmac[Mod_idP]->common_channels[0].sib1 ? RC.nrmac[Mod_idP]->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL; NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(sched_ctrl->active_ubwp, @@ -824,7 +299,6 @@ static void handle_dl_harq(NR_UE_info_t * UE, add_tail_nr_list(&UE->UE_sched_ctrl.available_dl_harq, harq_pid); harq->round = 0; harq->ndi ^= 1; - } else if (harq->round >= harq_round_max - 1) { abort_nr_dl_harq(UE, harq_pid); LOG_D(NR_MAC, "retransmission error for UE %04x (total %"PRIu64")\n", UE->rnti, UE->mac_stats.dl.errors); @@ -1177,7 +651,6 @@ void evaluate_rsrp_report(NR_UE_info_t *UE, stats->num_rsrp_meas++; } - void evaluate_cri_report(uint8_t *payload, uint8_t cri_bitlen, int cumul_bits, @@ -1593,7 +1066,6 @@ bool test_acknack_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl, return true; } - // this function returns an index to NR_sched_pucch structure // currently this structure contains PUCCH0 at index 0 and PUCCH2 at index 1 // if the function returns -1 it was not possible to schedule acknack @@ -1662,7 +1134,7 @@ int nr_acknack_scheduling(int mod_id, && csi_pucch->csi_bits > 0 && csi_pucch->frame == f && csi_pucch->ul_slot == s)) - nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, pucch, UE); + nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, pucch, UE); memset(pucch, 0, sizeof(*pucch)); pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; @@ -1735,7 +1207,7 @@ int nr_acknack_scheduling(int mod_id, csi_pucch->csi_bits > 0 && csi_pucch->frame == f && csi_pucch->ul_slot == s)) - nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, pucch, UE); + nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, pucch, UE); memset(pucch, 0, sizeof(*pucch)); pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; if(((s + 1)%nr_slots_period) == 0) @@ -1837,7 +1309,6 @@ int nr_acknack_scheduling(int mod_id, // FIXME currently we support at most 11 bits in pucch2 so skip also in that case if(!csi_pucch->simultaneous_harqcsi || ((csi_pucch->csi_bits + csi_pucch->dai_c) >= 11)) { - LOG_D(NR_MAC,"Cannot multiplex csi_pucch %d +csi_pucch->dai_c %d for %d.%d\n",csi_pucch->csi_bits,csi_pucch->dai_c,csi_pucch->frame,csi_pucch->ul_slot); nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, csi_pucch, UE); memset(csi_pucch, 0, sizeof(*csi_pucch)); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index f654e8e1a6120969a5450170924761b6e5e560df..20494c2b6bf795d44409e5be2b7e8009f111abda 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -336,38 +336,41 @@ int nr_process_mac_pdu( instance_t module_idP, case UL_SCH_LCID_DTCH ... (UL_SCH_LCID_DTCH + 28): // check if LCID is valid at current time. - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return 0; + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) { + return 0; + } - LOG_D(NR_MAC, "[UE %04x] %d.%d : ULSCH -> UL-%s %d (gNB %ld, %d bytes)\n", - UE->rnti, - frameP, - slot, - rx_lcid<4?"DCCH":"DTCH", - rx_lcid, - module_idP, - mac_len); - UE->mac_stats.ul.lc_bytes[rx_lcid] += mac_len; - - mac_rlc_data_ind(module_idP, - UE->rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *)(pduP + mac_subheader_len), - mac_len, - 1, - NULL); - - /* Updated estimated buffer when receiving data */ - if (sched_ctrl->estimated_ul_buffer >= mac_len) - sched_ctrl->estimated_ul_buffer -= mac_len; - else - sched_ctrl->estimated_ul_buffer = 0; - break; + LOG_D(NR_MAC, "[UE %04x] %d.%d : ULSCH -> UL-%s %d (gNB %ld, %d bytes)\n", + UE->rnti, + frameP, + slot, + rx_lcid<4?"DCCH":"DTCH", + rx_lcid, + module_idP, + mac_len); + UE->mac_stats.ul.lc_bytes[rx_lcid] += mac_len; + + mac_rlc_data_ind(module_idP, + UE->rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *)(pduP + mac_subheader_len), + mac_len, + 1, + NULL); + + /* Updated estimated buffer when receiving data */ + if (sched_ctrl->estimated_ul_buffer >= mac_len) { + sched_ctrl->estimated_ul_buffer -= mac_len; + } else { + sched_ctrl->estimated_ul_buffer = 0; + } + + break; default: LOG_E(NR_MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid); @@ -402,7 +405,7 @@ int nr_process_mac_pdu( instance_t module_idP, return 0; } -void abort_nr_ul_harq( NR_UE_info_t* UE, int8_t harq_pid) +void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid]; @@ -546,7 +549,6 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, else{ LOG_D(NR_MAC,"[UE %04x] Detected DTX : increasing UE TX power\n",UE->rnti); UE_scheduling_control->tpc0 = 1; - } #if defined(ENABLE_MAC_PAYLOAD_DEBUG) @@ -756,7 +758,6 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, return; } - LOG_D(NR_MAC, "Random Access %i Msg3 CRC did not pass)\n", i); ra->msg3_round++; @@ -846,10 +847,8 @@ static bool nr_UE_is_to_be_scheduled(const NR_ServingCellConfigCommon_t *scc, const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; const int now = frame * n + slot; - const NR_UE_sched_ctrl_t *sched_ctrl =&UE->UE_sched_ctrl; - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; int num_slots_per_period; @@ -1071,7 +1070,7 @@ static int comparator(const void *p, const void *q) { void pf_ul(module_id_t module_id, frame_t frame, sub_frame_t slot, - NR_UE_info_t *UE_list[], + NR_UE_info_t *UE_list[], int max_num_ue, int n_rb_sched, uint16_t *rballoc_mask) { @@ -1132,10 +1131,11 @@ void pf_ul(module_id_t module_id, /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ remainUEs--; + // we have filled all with mandatory retransmissions + // no need to schedule new transmissions if (remainUEs == 0) - // we have filled all with mandatory retransmissions - // no need to schedule new transmissions - return; + return; + continue; } const int B = max(0, sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes); @@ -1143,9 +1143,10 @@ void pf_ul(module_id_t module_id, const bool do_sched = nr_UE_is_to_be_scheduled(scc, 0, UE, sched_pusch->frame, sched_pusch->slot, nrmac->ulsch_max_frame_inactivity); LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n",UE->rnti,do_sched ? "yes" : "no"); - if ((B == 0 && !do_sched) || (sched_ctrl->rrc_processing_timer > 0)) + if ((B == 0 && !do_sched) || (sched_ctrl->rrc_processing_timer > 0)) { continue; - + } + const NR_bler_options_t *bo = &nrmac->ul_bler; const int max_mcs = bo->max_mcs; /* no per-user maximum MCS yet */ sched_pusch->mcs = get_mcs_from_bler(bo, stats, &UE->UE_sched_ctrl.ul_bler_stats, max_mcs, frame); @@ -1158,12 +1159,12 @@ void pf_ul(module_id_t module_id, const uint32_t Y = get_Y(sched_ctrl->search_space, slot, UE->rnti); uint8_t nr_of_candidates; for (int i=0; i<5; i++) { - // for now taking the lowest value among the available aggregation levels - find_aggregation_candidates(&sched_ctrl->aggregation_level, - &nr_of_candidates, - sched_ctrl->search_space, - 1<0) break; + // for now taking the lowest value among the available aggregation levels + find_aggregation_candidates(&sched_ctrl->aggregation_level, + &nr_of_candidates, + sched_ctrl->search_space, + 1<0) break; } int CCEIndex = find_pdcch_candidate(RC.nrmac[module_id], CC_id, @@ -1172,18 +1173,19 @@ void pf_ul(module_id_t module_id, &sched_ctrl->sched_pdcch, sched_ctrl->coreset, Y); - + if (CCEIndex<0) { - LOG_D(NR_MAC, "%4d.%2d no free CCE for UL DCI UE %04x (BSR 0)\n", frame, slot, UE->rnti); - continue; + LOG_D(NR_MAC, "%4d.%2d no free CCE for UL DCI UE %04x (BSR 0)\n", frame, slot, UE->rnti); + continue; } + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ remainUEs--; - + + // we have filled all with mandatory retransmissions + // no need to schedule new transmissions if (remainUEs == 0) - // we have filled all with mandatory retransmissions - // no need to schedule new transmissions - return; + return; /* Save PUSCH field */ /* we want to avoid a lengthy deduction of DMRS and other parameters in @@ -1278,7 +1280,7 @@ void pf_ul(module_id_t module_id, sched_ctrl->search_space, 1<0) - break; + break; } int CCEIndex = find_pdcch_candidate(RC.nrmac[module_id], CC_id, @@ -1379,8 +1381,8 @@ void pf_ul(module_id_t module_id, n_rb_sched -= sched_pusch->rbSize; for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++) - rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] ^= slbitmap; + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ remainUEs--; iterator++; @@ -1400,8 +1402,8 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t const int mu = scc ? scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing : scc_sib1->uplinkConfigCommon->initialUplinkBWP.genericParameters.subcarrierSpacing; + // no UEs if (nr_mac->UE_info.list[0] == NULL) - // no UEs return false; const int CC_id = 0; @@ -1448,8 +1450,7 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t UE_iterator(nr_mac->UE_info.list, UE2) { NR_UE_sched_ctrl_t *sched_ctrl = &UE2->UE_sched_ctrl; AssertFatal(K2 == get_K2(scc,scc_sib1,sched_ctrl->active_ubwp, tda, mu), - "Different K2, %d(UE%d) != %ld(UE%04x)\n", - K2, 0, get_K2(scc,scc_sib1,sched_ctrl->active_ubwp, tda, mu), UE2->rnti); + "Different K2, %d(UE%d) != %ld(UE%04x)\n", K2, 0, get_K2(scc,scc_sib1,sched_ctrl->active_ubwp, tda, mu), UE2->rnti); sched_ctrl->sched_pusch.slot = sched_slot; sched_ctrl->sched_pusch.frame = sched_frame; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 83097ae260cc2171bc4de3a56a43c26f389b3ec7..f37949c41f40c8bb6f9caabd3e1e6e65361970c7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -201,7 +201,7 @@ void config_uldci(const NR_SIB1_t *sib1, int n_ubwp, int bwp_id); -void nr_schedule_pucch(gNB_MAC_INST* nrmac, +void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP); @@ -216,12 +216,12 @@ void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP); -int nr_acknack_scheduling( int Mod_idP, - NR_UE_info_t * UE, - frame_t frameP, - sub_frame_t slotP, - int r_pucch, - int do_common); +int nr_acknack_scheduling(int Mod_idP, + NR_UE_info_t *UE, + frame_t frameP, + sub_frame_t slotP, + int r_pucch, + int do_common); void get_pdsch_to_harq_feedback(NR_UE_info_t *, int bwp_id, @@ -410,8 +410,6 @@ void nr_mac_remove_ra_rnti(module_id_t mod_id, rnti_t rnti); int nr_get_default_pucch_res(int pucch_ResourceCommon); -void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE); - int get_dlscs(nfapi_nr_config_request_t *cfg); int get_ulscs(nfapi_nr_config_request_t *cfg); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 1ae8767d105c303ec937f284fd76530250afe600..12a84b33d6fd8bae5cfddacbe8156a326ec7d4d1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -509,38 +509,6 @@ struct CSI_Report { #define MAX_SR_BITLEN 8 -typedef struct { - uint8_t nb_ssbri_cri; - uint8_t cri_ssbri_bitlen; - uint8_t rsrp_bitlen; - uint8_t diff_rsrp_bitlen; -}L1_RSRP_bitlen_t; - -typedef struct{ - uint8_t ri_restriction; - uint8_t cri_bitlen; - uint8_t ri_bitlen; - uint8_t li_bitlen[8]; - uint8_t pmi_x1_bitlen[8]; - uint8_t pmi_x2_bitlen[8]; - uint8_t cqi_bitlen[8]; -} CSI_Meas_bitlen_t; - -typedef struct nr_csi_report { - NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; - long periodicity; - uint16_t offset; - long ** SSB_Index_list; - long ** CSI_Index_list; -// uint8_t nb_of_nzp_csi_report; - uint8_t nb_of_csi_ssb_report; - L1_RSRP_bitlen_t CSI_report_bitlen; - CSI_Meas_bitlen_t csi_meas_bitlen; - int codebook_mode; - int N1; - int N2; -} nr_csi_report_t; - /*! As per the spec 38.212 and table: 6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set @@ -703,7 +671,6 @@ typedef struct NR_bler_options { } NR_bler_options_t; /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ -#define MAX_CSI_REPORTCONFIG 48 typedef struct { rnti_t rnti; /// scheduling control info diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index b6f760a86a65cd7c1423c3452d322fb0b42b86ad..cefafcba80fb6683ce6e832e5f7a062bdfd1552c 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1103,6 +1103,10 @@ int8_t handle_dlsch(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *u return 0; } +int8_t handle_csirs_measurements(module_id_t module_id, frame_t frame, int slot, fapi_nr_csirs_measurements_t *csirs_measurements) { + return nr_ue_process_csirs_measurements(module_id, frame, slot, csirs_measurements); +} + void update_harq_status(module_id_t module_id, uint8_t harq_pid, uint8_t ack_nack) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); @@ -1228,7 +1232,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_length, (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_start_subcarrier, (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; - free((dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu); + free((dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu); break; case FAPI_NR_RX_PDU_TYPE_SIB: ret_mask |= (handle_bcch_dlsch(dl_info->module_id, @@ -1243,6 +1247,12 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ case FAPI_NR_RX_PDU_TYPE_RAR: ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_RAR; break; + case FAPI_NR_CSIRS_IND: + ret_mask |= (handle_csirs_measurements(dl_info->module_id, + dl_info->frame, + dl_info->slot, + &(dl_info->rx_ind->rx_indication_body+i)->csirs_measurements)) << FAPI_NR_CSIRS_IND; + break; default: break; } diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 6dff1f113ff4685242c3e7baeb558c3c54d3a7f8..f67fb93c2344a1f3746097151a76e8fa41955824 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -548,7 +548,7 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay){ pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); *pusch_timedomainresourceallocation->k2 = k2; pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0,13); + pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0,13); ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); if(frame_type==TDD) { @@ -780,7 +780,8 @@ void scheduling_request_config(NR_ServingCellConfigCommon_t *scc, ASN_SEQUENCE_ADD(&pucch_Config->schedulingRequestResourceToAddModList->list,schedulingRequestResourceConfig); } -void set_dl_mcs_table(int scs, NR_UE_NR_Capability_t *cap, +void set_dl_mcs_table(int scs, + NR_UE_NR_Capability_t *cap, NR_SpCellConfig_t *SpCellConfig, NR_BWP_DownlinkDedicated_t *bwp_Dedicated, NR_ServingCellConfigCommon_t *scc) { @@ -820,7 +821,7 @@ void set_dl_mcs_table(int scs, NR_UE_NR_Capability_t *cap, if(bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table == NULL) bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table)); *bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256; -// set table 2 in correct entry in SpCellConfig->spCellConfigDedicated->csi_MeasConfig->csi_ReportConfigToAddModList->list + // set table 2 in correct entry in SpCellConfig->spCellConfigDedicated->csi_MeasConfig->csi_ReportConfigToAddModList->list AssertFatal(SpCellConfig!=NULL,"SpCellConfig shouldn't be null\n"); AssertFatal(SpCellConfig->spCellConfigDedicated!=NULL,"SpCellConfigDedicated shouldn't be null\n"); if (SpCellConfig->spCellConfigDedicated->csi_MeasConfig && diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index bab97e795c7056c1c9d5f5e2d9e91a5707435fa2..b1367a0c8a9a4240d0bb7536f6fc79a766f12e6d 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -138,7 +138,8 @@ void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config, const NR_ServingCellConfigCommon_t *servingcellconfigcommon, const int uid, const int do_srs); -void set_dl_mcs_table(int scs, NR_UE_NR_Capability_t *cap, +void set_dl_mcs_table(int scs, + NR_UE_NR_Capability_t *cap, NR_SpCellConfig_t *SpCellConfig, NR_BWP_DownlinkDedicated_t *bwp_Dedicated, NR_ServingCellConfigCommon_t *scc); diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 5b8995e06b3bb2c004e5f6d1181ec0fd3d89696a..7c0180e5e789e6cdb3a02a5a2eea91930d5dc869 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -675,7 +675,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp } if (samples_received == nsamps) s->wait_for_first_pps=0; - // bring RX data into 12 LSBs for softmodem RX + // bring RX data into 12 LSBs for softmodem RX for (int i=0; i