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 8ff7030af5..68e41c160f 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 @@ -37,18 +37,6 @@ typedef signed char int8_t; */ - -typedef struct { - uint8_t uci_format; - uint8_t uci_channel; - uint8_t harq_ack_bits; - uint32_t harq_ack; - uint8_t csi_bits; - uint32_t csi; - uint8_t sr_bits; - uint32_t sr; -} fapi_nr_uci_pdu_rel15_t; - typedef enum { RLM_no_monitoring = 0, RLM_out_of_sync = 1, @@ -257,10 +245,16 @@ typedef struct typedef struct { + // payloads with fixed array size + // no place to free the dinamically allocated + // vector without L1 implementation uint16_t harq_ack_bit_length; + uint64_t harq_payload; uint16_t csi_part1_bit_length; + uint64_t csi_part1_payload; uint16_t csi_part2_bit_length; - uint8_t alpha_scaling; + uint64_t csi_part2_payload; + uint8_t alpha_scaling; // 0 = 0.5, 1 = 0.65, 2 = 0.8, 3 = 1 uint8_t beta_offset_harq_ack; uint8_t beta_offset_csi1; uint8_t beta_offset_csi2; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 225a20aa36..7f34c25b45 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -123,6 +123,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch_ue->pusch_pdu; uint32_t tb_size = pusch_pdu->pusch_data.tb_size; + AssertFatal(pusch_pdu->pusch_uci.harq_ack_bit_length == 0 && + pusch_pdu->pusch_uci.csi_part1_bit_length == 0 && + pusch_pdu->pusch_uci.csi_part2_bit_length == 0, + "UCI on PUSCH not supported\n"); + int start_symbol = pusch_pdu->start_symbol_index; uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos; uint8_t number_of_symbols = pusch_pdu->nr_of_symbols; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index c6d1b72422..6202303d65 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -561,6 +561,7 @@ typedef struct NR_UE_UL_BWP { NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList_Common; NR_ConfiguredGrantConfig_t *configuredGrantConfig; NR_PUSCH_Config_t *pusch_Config; + NR_UCI_OnPUSCH_t *uci_onPusch; NR_PUCCH_Config_t *pucch_Config; NR_PUCCH_ConfigCommon_t *pucch_ConfigCommon; NR_SRS_Config_t *srs_Config; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index d254906a33..df79cbcabd 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -5018,7 +5018,8 @@ void compute_cqi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, } //!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) { +void compute_csi_bitlen(const 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; @@ -5039,7 +5040,7 @@ void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report_t *cs 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) + if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) found_resource = 1; csi_resourceidx++; } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index d055d76676..dc9285bc3f 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -307,7 +307,7 @@ 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); +void compute_csi_bitlen(const 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); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 2cda190f23..bcf477d52b 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -482,6 +482,19 @@ typedef struct { A_SEQUENCE_OF(NR_SearchSpace_t) list_SS; } NR_BWP_PDCCH_t; +typedef struct csi_payload { + uint32_t part1_payload; + uint32_t part2_payload; + int p1_bits; + int p2_bits; +} csi_payload_t; + +typedef enum { + WIDEBAND_ON_PUCCH, + SUBBAND_ON_PUCCH, + ON_PUSCH +} CSI_mapping_t; + /*!\brief Top level UE MAC structure */ typedef struct NR_UE_MAC_INST_s { module_id_t ue_id; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 1eac68350c..b401bcb20a 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -111,6 +111,8 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info); void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info); +csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t csi_request, int tda, long *K2); + /*! \fn int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id); \brief This function schedules a positive or negative SR for schedulingRequestID sr_id depending on the presence of any active SR and the prohibit timer. @@ -132,28 +134,26 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch); -uint8_t get_ssb_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); +csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + 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, +csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig, + CSI_mapping_t mapping_type); + +csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, struct NR_CSI_ReportConfig *csi_reportconfig, NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - NR_CSI_MeasConfig_t *csi_MeasConfig); + const 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, - NR_CSI_MeasConfig_t *csi_MeasConfig); +csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, + int csi_report_id, + CSI_mapping_t mapping_type, + NR_CSI_MeasConfig_t *csi_MeasConfig); uint8_t get_rsrp_index(int rsrp); uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp); @@ -367,6 +367,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, NR_tda_info_t *tda_info, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, dci_pdu_rel15_t *dci, + csi_payload_t *csi_report, RAR_grant_t *rar_grant, uint16_t rnti, int ss_type, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index f4812e639c..1c3ee94cec 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -443,7 +443,15 @@ static int nr_ue_process_dci_ul_00(NR_UE_MAC_INST_t *mac, if (!pdu) return -1; - int ret = nr_config_pusch_pdu(mac, &tda_info, &pdu->pusch_config_pdu, dci, NULL, dci_ind->rnti, dci_ind->ss_type, NR_UL_DCI_FORMAT_0_0); + int ret = nr_config_pusch_pdu(mac, + &tda_info, + &pdu->pusch_config_pdu, + dci, + NULL, + NULL, + dci_ind->rnti, + dci_ind->ss_type, + NR_UL_DCI_FORMAT_0_0); if (ret != 0) remove_ul_config_last_item(pdu); release_ul_config(pdu, false); @@ -489,6 +497,12 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac, // - SECOND_DAI // - SRS_RESOURCE_IND + /* CSI_REQUEST */ + long csi_K2 = -1; + csi_payload_t csi_report = {0}; + if (dci->csi_request.nbits > 0 && dci->csi_request.val > 0) + csi_report = nr_ue_aperiodic_csi_reporting(mac, dci->csi_request, dci->time_domain_assignment.val, &csi_K2); + /* SRS_REQUEST */ AssertFatal(dci->srs_request.nbits == 2, "If SUL is supported in the cell, there is an additional bit in SRS request field\n"); if (dci->srs_request.val > 0) @@ -504,6 +518,13 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac, dci_ind->ss_type, get_rnti_type(mac, dci_ind->rnti), dci->time_domain_assignment.val); + + if (dci->ulsch_indicator == 0) { + // in case of CSI on PUSCH and no ULSCH we need to use reportSlotOffset in trigger state + AssertFatal(csi_K2 > 0, "Invalid CSI K2 value %ld\n", csi_K2); + tda_info.k2 = csi_K2; + } + if (tda_info.nrOfSymbols == 0) return -1; @@ -515,7 +536,15 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac, fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); if (!pdu) return -1; - int ret = nr_config_pusch_pdu(mac, &tda_info, &pdu->pusch_config_pdu, dci, NULL, dci_ind->rnti, dci_ind->ss_type, NR_UL_DCI_FORMAT_0_1); + int ret = nr_config_pusch_pdu(mac, + &tda_info, + &pdu->pusch_config_pdu, + dci, + &csi_report, + NULL, + dci_ind->rnti, + dci_ind->ss_type, + NR_UL_DCI_FORMAT_0_1); if (ret != 0) remove_ul_config_last_item(pdu); release_ul_config(pdu, false); @@ -2584,14 +2613,12 @@ int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCC NR_CSI_MeasConfig_t *csi_measconfig = mac->sc_info.csi_MeasConfig; int csi_priority = INT_MAX; - for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++) { NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; - if(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic){ - + if(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic) { int period, offset; csi_period_offset(csirep, NULL, &period, &offset); - const int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs]; if (((n_slots_frame*frame + slot - offset)%period) == 0 && pucch_Config) { int csi_res_id = -1; @@ -2619,47 +2646,50 @@ int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCC // we discard previous report csi_priority = temp_priority; num_csi = 1; - pucch->n_csi = nr_get_csi_payload(mac, pucch, csi_report_id, csi_measconfig); + csi_payload_t csi = nr_get_csi_payload(mac, csi_report_id, WIDEBAND_ON_PUCCH, csi_measconfig); + pucch->n_csi = csi.p1_bits; + pucch->csi_part1_payload = csi.part1_payload; pucch->pucch_resource = csi_pucch; } else continue; } else { num_csi = 1; csi_priority = temp_priority; - pucch->n_csi = nr_get_csi_payload(mac, pucch, csi_report_id, csi_measconfig); + csi_payload_t csi = nr_get_csi_payload(mac, csi_report_id, WIDEBAND_ON_PUCCH, csi_measconfig); + pucch->n_csi = csi.p1_bits; + pucch->csi_part1_payload = csi.part1_payload; pucch->pucch_resource = csi_pucch; } } } else - AssertFatal(1==0,"Only periodic CSI reporting is currently implemented\n"); + AssertFatal(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_aperiodic, + "Not supported CSI report type\n"); } } return num_csi; } -uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, - PUCCH_sched_t *pucch, - int csi_report_id, - NR_CSI_MeasConfig_t *csi_MeasConfig) { - - int n_csi_bits = 0; - - AssertFatal(csi_MeasConfig->csi_ReportConfigToAddModList->list.count>0,"No CSI Report configuration available\n"); - +csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, + int csi_report_id, + CSI_mapping_t mapping_type, + NR_CSI_MeasConfig_t *csi_MeasConfig) +{ + AssertFatal(csi_MeasConfig->csi_ReportConfigToAddModList->list.count > 0,"No CSI Report configuration available\n"); + csi_payload_t csi = {0}; struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement; switch(csi_reportconfig->reportQuantity.present) { case NR_CSI_ReportConfig__reportQuantity_PR_none: break; case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP: - n_csi_bits = get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); + csi = get_ssb_rsrp_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig); break; case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI: - n_csi_bits = get_csirs_RI_PMI_CQI_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); + csi = get_csirs_RI_PMI_CQI_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig, mapping_type); break; case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP: - n_csi_bits = get_csirs_RSRP_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); + csi = get_csirs_RSRP_payload(mac, 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: @@ -2670,16 +2700,15 @@ uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, default: AssertFatal(1==0,"Invalid CSI report quantity type %d\n",csi_reportconfig->reportQuantity.present); } - return (n_csi_bits); + return csi; } -uint8_t get_ssb_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) { - +csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig) +{ int nb_ssb = 0; // nb of ssb in the resource int nb_meas = 0; // nb of ssb to report measurements on int bits = 0; @@ -2750,18 +2779,22 @@ uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, break; // resorce found } } - pucch->csi_part1_payload = temp_payload; - return bits; + AssertFatal(bits <= 32, "Not supporting CSI report with more than 32 bits\n"); + csi_payload_t csi = {.part1_payload = temp_payload, .p1_bits = bits, csi.p2_bits = 0}; + return csi; } -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; - uint64_t temp_payload = 0; +csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig, + CSI_mapping_t mapping_type) +{ + int p1_bits = 0; + int p2_bits = 0; + uint64_t temp_payload_1 = 0; + uint64_t temp_payload_2 = 0; + AssertFatal(mapping_type != SUBBAND_ON_PUCCH, "CSI mapping for subband PMI and CQI not implemented\n"); for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { @@ -2774,14 +2807,12 @@ uint8_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, nr_csi_report_t *csi_report = &mac->csi_report_template[csi_idx]; compute_csi_bitlen(csi_MeasConfig, mac->csi_report_template); - n_bits = nr_get_csi_bitlen(mac->csi_report_template, csi_idx); 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); if (get_softmodem_params()->emulate_l1) { static const uint8_t mcs_to_cqi[] = {0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, @@ -2794,38 +2825,53 @@ uint8_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, mac->csirs_measurements.cqi = mcs_to_cqi[mcs]; } + int padding_bitlen = 0; // TODO: Improvements will be needed to cri_bitlen>0 and pmi_x1_bitlen>0 - temp_payload = (mac->csirs_measurements.rank_indicator<<(cri_bitlen+cqi_bitlen+pmi_x2_bitlen+padding_bitlen+pmi_x1_bitlen)) | - (mac->csirs_measurements.i1<<(cri_bitlen+cqi_bitlen+pmi_x2_bitlen)) | - (mac->csirs_measurements.i2<<(cri_bitlen+cqi_bitlen)) | - (mac->csirs_measurements.cqi<csi_measurements.cri*/ << (cqi_bitlen + ri_bitlen)) | + (mac->csirs_measurements.rank_indicator << cqi_bitlen) | + (mac->csirs_measurements.cqi); + temp_payload_2 = (mac->csirs_measurements.i1 << pmi_x2_bitlen) | + mac->csirs_measurements.i2; + } + else { + p1_bits = nr_get_csi_bitlen(mac->csi_report_template, csi_idx); + padding_bitlen = p1_bits - (cri_bitlen + ri_bitlen + pmi_x1_bitlen + pmi_x2_bitlen + cqi_bitlen); + temp_payload_1 = (0/*mac->csi_measurements.cri*/ << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen + ri_bitlen)) | + (mac->csirs_measurements.rank_indicator << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen)) | + (mac->csirs_measurements.i1 << (cqi_bitlen + pmi_x2_bitlen)) | + (mac->csirs_measurements.i2 << (cqi_bitlen)) | + (mac->csirs_measurements.cqi); + } + temp_payload_1 = reverse_bits(temp_payload_1, p1_bits); + temp_payload_2 = reverse_bits(temp_payload_2, p2_bits); LOG_D(NR_MAC, "cri_bitlen = %d\n", cri_bitlen); LOG_D(NR_MAC, "ri_bitlen = %d\n", ri_bitlen); LOG_D(NR_MAC, "pmi_x1_bitlen = %d\n", pmi_x1_bitlen); LOG_D(NR_MAC, "pmi_x2_bitlen = %d\n", pmi_x2_bitlen); LOG_D(NR_MAC, "cqi_bitlen = %d\n", cqi_bitlen); - LOG_D(NR_MAC, "csi_part1_payload = 0x%lx\n", temp_payload); - LOG_D(NR_MAC, "n_bits = %d\n", n_bits); - + LOG_D(NR_MAC, "csi_part1_payload = 0x%lx\n", temp_payload_1); + LOG_D(NR_MAC, "csi_part2_payload = 0x%lx\n", temp_payload_2); + LOG_D(NR_MAC, "part1_bits = %d\n", p1_bits); + LOG_D(NR_MAC, "part2_bits = %d\n", p2_bits); break; } } } } - pucch->csi_part1_payload = temp_payload; - return n_bits; + AssertFatal(p1_bits <= 32 && p2_bits <= 32, "Not supporting CSI report with more than 32 bits\n"); + csi_payload_t csi = {.part1_payload = temp_payload_1, .part2_payload = temp_payload_2, .p1_bits = p1_bits, csi.p2_bits = p2_bits}; + return csi; } -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) { - +csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + const NR_CSI_MeasConfig_t *csi_MeasConfig) +{ int n_bits = 0; uint64_t temp_payload = 0; @@ -2875,9 +2921,9 @@ uint8_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, } } } - - pucch->csi_part1_payload = temp_payload; - return n_bits; + AssertFatal(n_bits <= 32, "Not supporting CSI report with more than 32 bits\n"); + csi_payload_t csi = {.part1_payload = temp_payload, .p1_bits = n_bits, csi.p2_bits = 0}; + return csi; } // returns index from RSRP @@ -4027,6 +4073,7 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d &tda_info, &pdu->pusch_config_pdu, NULL, + NULL, &rar_grant, rnti, NR_SearchSpace__searchSpaceType_PR_common, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 54065ad757..5b89fe2918 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -515,6 +515,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, NR_tda_info_t *tda_info, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, dci_pdu_rel15_t *dci, + csi_payload_t *csi_report, RAR_grant_t *rar_grant, uint16_t rnti, int ss_type, @@ -631,6 +632,38 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->tbslbrm = 0; } else if (dci) { + + if (dci->csi_request.nbits > 0 && dci->csi_request.val > 0) { + AssertFatal(csi_report, "CSI report needs to be present in case of CSI request\n"); + pusch_config_pdu->pusch_uci.csi_part1_bit_length = csi_report->p1_bits; + pusch_config_pdu->pusch_uci.csi_part1_payload = csi_report->part1_payload; + pusch_config_pdu->pusch_uci.csi_part2_bit_length = csi_report->p2_bits; + pusch_config_pdu->pusch_uci.csi_part2_payload = csi_report->part2_payload; + AssertFatal(pusch_Config && pusch_Config->uci_OnPUSCH, + "UCI on PUSCH need to be configured\n"); + pusch_config_pdu->pusch_uci.alpha_scaling = pusch_Config->uci_OnPUSCH->choice.setup->scaling; + AssertFatal(pusch_Config->uci_OnPUSCH->choice.setup->betaOffsets && + pusch_Config->uci_OnPUSCH->choice.setup->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_semiStatic, + "Only semistatic beta offset is supported\n"); + NR_BetaOffsets_t *beta_offsets = pusch_Config->uci_OnPUSCH->choice.setup->betaOffsets->choice.semiStatic; + pusch_config_pdu->pusch_uci.beta_offset_harq_ack = pusch_config_pdu->pusch_uci.harq_ack_bit_length > 2 ? + (pusch_config_pdu->pusch_uci.harq_ack_bit_length < 12 ? *beta_offsets->betaOffsetACK_Index2 : + *beta_offsets->betaOffsetACK_Index3) : + *beta_offsets->betaOffsetACK_Index1; + pusch_config_pdu->pusch_uci.beta_offset_csi1 = pusch_config_pdu->pusch_uci.csi_part1_bit_length < 12 ? + *beta_offsets->betaOffsetCSI_Part1_Index1 : + *beta_offsets->betaOffsetCSI_Part1_Index2; + pusch_config_pdu->pusch_uci.beta_offset_csi2 = pusch_config_pdu->pusch_uci.csi_part2_bit_length < 12 ? + *beta_offsets->betaOffsetCSI_Part2_Index1 : + *beta_offsets->betaOffsetCSI_Part2_Index2; + } + else { + pusch_config_pdu->pusch_uci.csi_part1_bit_length = 0; + pusch_config_pdu->pusch_uci.csi_part2_bit_length = 0; + } + + pusch_config_pdu->pusch_uci.harq_ack_bit_length = 0; + pusch_config_pdu->bwp_start = current_UL_BWP->BWPStart; pusch_config_pdu->bwp_size = current_UL_BWP->BWPSize; @@ -891,6 +924,47 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, return 0; } +csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t csi_request, int tda, long *k2) +{ + NR_CSI_AperiodicTriggerStateList_t *aperiodicTriggerStateList = mac->sc_info.aperiodicTriggerStateList; + AssertFatal(aperiodicTriggerStateList, "Received CSI request via DCI but aperiodicTriggerStateList is not present\n"); + int n_states = aperiodicTriggerStateList->list.count; + int n_ts = csi_request.nbits; + csi_payload_t csi = {0}; + AssertFatal(n_states <= ((1 << n_ts) - 1), "Case of subselection indication of trigger states not supported yet\n"); + int num_trig = 0; + for (int i = 0; i < n_ts; i++) { + // A non-zero codepoint of the CSI request field in the DCI is mapped to a CSI triggering state + // according to the order of the associated positions of the up to (2^n_ts -1) trigger states + // in CSI-AperiodicTriggerStateList with codepoint 1 mapped to the triggering state in the first position + if (csi_request.val & (1 << i)) { + AssertFatal(num_trig == 0, "Multiplexing more than 1 CSI report is not supported\n"); + NR_CSI_AperiodicTriggerState_t *trigger_state = aperiodicTriggerStateList->list.array[i]; + AssertFatal(trigger_state->associatedReportConfigInfoList.list.count == 1, + "Cannot handle more than 1 report configuration per state\n"); + NR_CSI_AssociatedReportConfigInfo_t *reportconfig = trigger_state->associatedReportConfigInfoList.list.array[0]; + NR_CSI_ReportConfigId_t id = reportconfig->reportConfigId; + NR_CSI_MeasConfig_t *csi_measconfig = mac->sc_info.csi_MeasConfig; + int found = -1; + for (int c = 0; c < csi_measconfig->csi_ReportConfigToAddModList->list.count; c++) { + NR_CSI_ReportConfig_t *report_config = csi_measconfig->csi_ReportConfigToAddModList->list.array[c]; + if (report_config->reportConfigId == id) { + struct NR_CSI_ReportConfig__reportConfigType__aperiodic__reportSlotOffsetList *offset_list = &report_config->reportConfigType.choice.aperiodic->reportSlotOffsetList; + AssertFatal(tda < offset_list->list.count, "TDA index from DCI %d exceeds slot offset list %d\n", tda, offset_list->list.count); + if (k2 == NULL || *k2 < *offset_list->list.array[tda]) + k2 = offset_list->list.array[tda]; + found = c; + break; + } + } + AssertFatal(found >= 0, "Couldn't find csi-ReportConfig with ID %ld\n", id); + num_trig++; + csi = nr_get_csi_payload(mac, found, ON_PUSCH, csi_measconfig); + } + } + return csi; +} + int configure_srs_pdu(NR_UE_MAC_INST_t *mac, NR_SRS_Resource_t *srs_resource, fapi_nr_ul_config_srs_pdu *srs_config_pdu, @@ -2185,7 +2259,7 @@ uint8_t set_csirs_measurement_bitmap(NR_CSI_MeasConfig_t *csi_measconfig, NR_CSI if (csi_res_id > NR_maxNrofCSI_ResourceConfigurations) return meas_bitmap; // CSI-RS for tracking for(int i = 0; i < csi_measconfig->csi_ReportConfigToAddModList->list.count; i++) { - struct NR_CSI_ReportConfig *report_config = csi_measconfig->csi_ReportConfigToAddModList->list.array[i]; + NR_CSI_ReportConfig_t *report_config = csi_measconfig->csi_ReportConfigToAddModList->list.array[i]; if(report_config->resourcesForChannelMeasurement != csi_res_id) continue; // bit 0 RSRP bit 1 RI bit 2 LI bit 3 PMI bit 4 CQI bit 5 i1