diff --git a/lib/include/srslte/interfaces/rrc_nr_interface_types.h b/lib/include/srslte/interfaces/rrc_nr_interface_types.h index 873a5c27b..5c916b81c 100644 --- a/lib/include/srslte/interfaces/rrc_nr_interface_types.h +++ b/lib/include/srslte/interfaces/rrc_nr_interface_types.h @@ -178,11 +178,22 @@ struct phy_cfg_nr_t { // betaOffsetACK-Index1: 9 // betaOffsetACK-Index2: 9 // betaOffsetACK-Index3: 9 + pusch.beta_offsets.ack_index1 = 9; + pusch.beta_offsets.ack_index2 = 9; + pusch.beta_offsets.ack_index3 = 9; + // betaOffsetCSI-Part1-Index1: 6 // betaOffsetCSI-Part1-Index2: 6 + pusch.beta_offsets.csi1_index1 = 6; + pusch.beta_offsets.csi1_index2 = 6; + // betaOffsetCSI-Part2-Index1: 6 // betaOffsetCSI-Part2-Index2: 6 + pusch.beta_offsets.csi2_index1 = 6; + pusch.beta_offsets.csi2_index2 = 6; + // scaling: f1 (3) + pusch.scaling = 1; // pucch-Config: setup (1) // setup diff --git a/lib/include/srslte/phy/phch/phch_cfg_nr.h b/lib/include/srslte/phy/phch/phch_cfg_nr.h index f694eb80f..b6fc8a46e 100644 --- a/lib/include/srslte/phy/phch/phch_cfg_nr.h +++ b/lib/include/srslte/phy/phch/phch_cfg_nr.h @@ -144,6 +144,20 @@ typedef struct SRSLTE_API { srslte_sch_tb_t tb[SRSLTE_MAX_TB]; } srslte_sch_grant_nr_t; +/** + * @brief Beta offset configuration provided from upper layers + * @remark Configure according to TS 38.331 BetaOffsets + */ +typedef struct { + uint32_t ack_index1; ///< Use for up to 2 HARQ-ACK bits. Set to 11 if absent. + uint32_t ack_index2; ///< Use for up to 11 HARQ-ACK bits. Set to 11 if absent. + uint32_t ack_index3; ///< Use for more than 11 HARQ-ACK bits. Set to 11 if absent. + uint32_t csi1_index1; ///< Use for up to 11 CSI bits. Set to 13 if absent. + uint32_t csi1_index2; ///< Use for more than 11 CSI bits. Set to 13 if absent. + uint32_t csi2_index1; ///< Use for up to 11 CSI bits. Set to 13 if absent. + uint32_t csi2_index2; ///< Use for more than 11 CSI bits. Set to 13 if absent. +} srslte_beta_offsets_t; + /** * @brief flatten SCH configuration parameters provided by higher layers * @remark Described in TS 38.331 V15.10.0 Section PDSCH-Config @@ -188,6 +202,10 @@ typedef struct SRSLTE_API { bool rbg_size_cfg_1; ///< RBG size configuration (1 or 2) srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters + + /// PUSCH only + srslte_beta_offsets_t beta_offsets; /// Semi-static only. + float scaling; /// Indicates a scaling factor to limit the number of resource elements assigned to UCI on PUSCH. } srslte_sch_hl_cfg_nr_t; /** @@ -207,6 +225,7 @@ typedef struct SRSLTE_API { bool enable_transform_precoder; float beta_harq_ack_offset; float beta_csi_part1_offset; + float beta_csi_part2_offset; float scaling; bool freq_hopping_enabled; } srslte_sch_cfg_nr_t; diff --git a/lib/include/srslte/phy/phch/pusch_nr.h b/lib/include/srslte/phy/phch/pusch_nr.h index 2db7268e4..ffac74c42 100644 --- a/lib/include/srslte/phy/phch/pusch_nr.h +++ b/lib/include/srslte/phy/phch/pusch_nr.h @@ -115,6 +115,7 @@ SRSLTE_API uint32_t srslte_pusch_nr_rx_info(const srslte_pusch_nr_t* q, SRSLTE_API uint32_t srslte_pusch_nr_tx_info(const srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, const srslte_sch_grant_nr_t* grant, + const srslte_uci_value_nr_t* uci_value, char* str, uint32_t str_len); diff --git a/lib/include/srslte/phy/phch/ra_nr.h b/lib/include/srslte/phy/phch/ra_nr.h index c5e9eb928..1815e33da 100644 --- a/lib/include/srslte/phy/phch/ra_nr.h +++ b/lib/include/srslte/phy/phch/ra_nr.h @@ -121,4 +121,18 @@ SRSLTE_API int srslte_ra_ul_dci_to_grant_nr(const srslte_carrier_nr_t* carrie srslte_sch_cfg_nr_t* pusch_cfg, srslte_sch_grant_nr_t* pusch_grant); +/** + * @brief Setups the Uplink Control Information configuration for a PUSCH transmission + * + * @remark Implement procedure described in TS 38.213 9.3 UCI reporting in physical uplink shared channel + * + * @param pusch_hl_cfg PUSCH configuration provided by higher layers + * @param uci_cfg Uplink Control Information configuration for this PUSCH transmission + * @param pusch_cfg PUSCH configuration after applying the procedure + * @return SRSLTE_SUCCESS if the procedure is successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_ra_ul_set_grant_uci_nr(const srslte_sch_hl_cfg_nr_t* pusch_hl_cfg, + const srslte_uci_cfg_nr_t* uci_cfg, + srslte_sch_cfg_nr_t* pusch_cfg); + #endif // SRSLTE_RA_NR_H diff --git a/lib/include/srslte/phy/ue/ue_ul_nr.h b/lib/include/srslte/phy/ue/ue_ul_nr.h index d87f35556..6d2575009 100644 --- a/lib/include/srslte/phy/ue/ue_ul_nr.h +++ b/lib/include/srslte/phy/ue/ue_ul_nr.h @@ -67,8 +67,11 @@ SRSLTE_API int srslte_ue_ul_nr_encode_pucch(srslte_ue_ul_nr_t* SRSLTE_API void srslte_ue_ul_nr_free(srslte_ue_ul_nr_t* q); -SRSLTE_API int -srslte_ue_ul_nr_pusch_info(const srslte_ue_ul_nr_t* q, const srslte_sch_cfg_nr_t* cfg, char* str, uint32_t str_len); +SRSLTE_API int srslte_ue_ul_nr_pusch_info(const srslte_ue_ul_nr_t* q, + const srslte_sch_cfg_nr_t* cfg, + const srslte_uci_value_nr_t* uci_value, + char* str, + uint32_t str_len); SRSLTE_API int srslte_ue_ul_nr_pucch_info(const srslte_pucch_nr_resource_t* resource, const srslte_uci_data_nr_t* uci_data, diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 519c3b20c..b69bef529 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -1284,6 +1284,10 @@ uint32_t srslte_pusch_nr_rx_info(const srslte_pusch_nr_t* q, { uint32_t len = 0; + if (q == NULL || cfg == NULL || grant == NULL || str == NULL || str_len == 0) { + return 0; + } + len += srslte_pusch_nr_grant_info(cfg, grant, &str[len], str_len - len); if (q->evm_buffer != NULL) { @@ -1302,6 +1306,11 @@ uint32_t srslte_pusch_nr_rx_info(const srslte_pusch_nr_t* q, } if (res != NULL) { + srslte_uci_data_nr_t uci_data = {}; + uci_data.cfg = cfg->uci; + uci_data.value = res[0].uci; + len += srslte_uci_nr_info(&uci_data, &str[len], str_len - len); + len = srslte_print_check(str, str_len, len, ",crc={", 0); for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (grant->tb[i].enabled) { @@ -1326,13 +1335,25 @@ uint32_t srslte_pusch_nr_rx_info(const srslte_pusch_nr_t* q, uint32_t srslte_pusch_nr_tx_info(const srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, const srslte_sch_grant_nr_t* grant, + const srslte_uci_value_nr_t* uci_value, char* str, uint32_t str_len) { uint32_t len = 0; + if (q == NULL || cfg == NULL || grant == NULL || str == NULL || str_len == 0) { + return 0; + } + len += srslte_pusch_nr_grant_info(cfg, grant, &str[len], str_len - len); + if (uci_value != NULL) { + srslte_uci_data_nr_t uci_data = {}; + uci_data.cfg = cfg->uci; + uci_data.value = *uci_value; + len += srslte_uci_nr_info(&uci_data, &str[len], str_len - len); + } + if (q->meas_time_en) { len = srslte_print_check(str, str_len, len, ", t=%d us", q->meas_time_us); } diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 399c881da..d2c7f4ee2 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -11,6 +11,7 @@ */ #include "srslte/phy/phch/ra_nr.h" +#include "srslte/phy/phch/csi.h" #include "srslte/phy/phch/pdsch_nr.h" #include "srslte/phy/phch/ra_dl_nr.h" #include "srslte/phy/phch/ra_ul_nr.h" @@ -26,6 +27,8 @@ typedef struct { #define RA_NR_MCS_SIZE_TABLE2 28 #define RA_NR_MCS_SIZE_TABLE3 29 #define RA_NR_TBS_SIZE_TABLE 93 +#define RA_NR_BETA_OFFSET_HARQACK_SIZE 32 +#define RA_NR_BETA_OFFSET_CSI_SIZE 32 #define RA_NR_READ_TABLE(N) \ static double srslte_ra_nr_R_from_mcs_table##N(uint32_t mcs_idx) \ @@ -108,6 +111,23 @@ static const uint32_t ra_nr_tbs_table[RA_NR_TBS_SIZE_TABLE] = { 1192, 1224, 1256, 1288, 1320, 1352, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928, 2024, 2088, 2152, 2216, 2280, 2408, 2472, 2536, 2600, 2664, 2728, 2792, 2856, 2976, 3104, 3240, 3368, 3496, 3624, 3752, 3824}; +/** + * TS 38.213 V15.10.0 Table 9.3-1: Mapping of beta_offset values for HARQ-ACK information and the index signalled by + * higher layers + */ +static const float ra_nr_beta_offset_ack_table[RA_NR_BETA_OFFSET_HARQACK_SIZE] = { + 1.000f, 2.000f, 2.500f, 3.125f, 4.000f, 5.000f, 6.250f, 8.000f, 10.000f, 12.625f, 15.875f, + 20.000f, 31.000f, 50.000f, 80.000f, 126.000f, NAN, NAN, NAN, NAN, NAN, NAN, + NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN}; + +/** + * TS 38.213 V15.10.0 Table 9.3-2: Mapping of beta_offset values for CSI and the index signalled by higher layers + */ +static const float ra_nr_beta_offset_csi_table[RA_NR_BETA_OFFSET_HARQACK_SIZE] = { + 1.125f, 1.250f, 1.375f, 1.625f, 1.750f, 2.000f, 2.250f, 2.500f, 2.875f, 3.125f, 3.500f, + 4.000f, 5.000f, 6.250f, 8.000f, 10.000f, 12.625f, 15.875f, 20.000f, NAN, NAN, NAN, + NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN}; + typedef enum { ra_nr_table_1 = 0, ra_nr_table_2, ra_nr_table_3 } ra_nr_table_t; static ra_nr_table_t ra_nr_select_table_pusch_noprecoding(srslte_mcs_table_t mcs_table, @@ -636,3 +656,94 @@ int srslte_ra_ul_dci_to_grant_nr(const srslte_carrier_nr_t* carrier, return SRSLTE_SUCCESS; } + +/* + * Implements clauses related to HARQ-ACK beta offset selection from the section `9.3 UCI reporting in physical uplink + * shared channel` + */ +static float ra_ul_beta_offset_ack_semistatic(const srslte_beta_offsets_t* beta_offsets, + const srslte_uci_cfg_nr_t* uci_cfg) +{ + // Select Beta Offset index from the number of HARQ-ACK bits + uint32_t beta_offset_index = beta_offsets->ack_index1; + if (uci_cfg->o_ack > 11) { + beta_offset_index = beta_offsets->ack_index3; + } else if (uci_cfg->o_ack > 2) { + beta_offset_index = beta_offsets->ack_index1; + } + + // Protect table boundary + if (beta_offset_index > RA_NR_BETA_OFFSET_HARQACK_SIZE) { + ERROR("Beta offset index for HARQ-ACK (%d) for O_ack=%d exceeds table size (%d)", + beta_offset_index, + uci_cfg->o_ack, + RA_NR_BETA_OFFSET_HARQACK_SIZE); + return NAN; + } + + // Select beta offset from Table 9.3-1 + return ra_nr_beta_offset_ack_table[beta_offset_index]; +} + +/* + * Implements clauses related to HARQ-ACK beta offset selection from the section `9.3 UCI reporting in physical uplink + * shared channel` + */ +static float ra_ul_beta_offset_csi_semistatic(const srslte_beta_offsets_t* beta_offsets, + const srslte_uci_cfg_nr_t* uci_cfg, + bool part2) +{ + // Calculate number of CSI bits; CSI part 2 is not supported. + uint32_t O_csi = part2 ? 0 : srslte_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); + + // Select Beta Offset index from the number of HARQ-ACK bits + uint32_t beta_offset_index = part2 ? beta_offsets->csi2_index1 : beta_offsets->csi1_index1; + if (O_csi > 11) { + beta_offset_index = part2 ? beta_offsets->csi2_index2 : beta_offsets->csi1_index2; + } + + // Protect table boundary + if (beta_offset_index > RA_NR_BETA_OFFSET_CSI_SIZE) { + ERROR("Beta offset index for CSI (%d) for O_csi=%d exceeds table size (%d)", + beta_offset_index, + O_csi, + RA_NR_BETA_OFFSET_CSI_SIZE); + return NAN; + } + + // Select beta offset from Table 9.3-1 + return ra_nr_beta_offset_csi_table[beta_offset_index]; +} + +int srslte_ra_ul_set_grant_uci_nr(const srslte_sch_hl_cfg_nr_t* pusch_hl_cfg, + const srslte_uci_cfg_nr_t* uci_cfg, + srslte_sch_cfg_nr_t* pusch_cfg) +{ + // Select beta offsets + pusch_cfg->beta_harq_ack_offset = ra_ul_beta_offset_ack_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg); + if (!isnormal(pusch_cfg->beta_harq_ack_offset)) { + return SRSLTE_ERROR; + } + + pusch_cfg->beta_csi_part1_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, false); + if (!isnormal(pusch_cfg->beta_csi_part1_offset)) { + return SRSLTE_ERROR; + } + + pusch_cfg->beta_csi_part2_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, true); + if (!isnormal(pusch_cfg->beta_csi_part2_offset)) { + return SRSLTE_ERROR; + } + + // pusch_cfg->beta_csi_part2_offset = pusch_hl_cfg->beta_offset_csi2; + pusch_cfg->scaling = pusch_hl_cfg->scaling; + if (!isnormal(pusch_cfg->scaling)) { + ERROR("Invalid Scaling (%f)", pusch_cfg->scaling); + return SRSLTE_ERROR; + } + + // Copy UCI configuration + pusch_cfg->uci = *uci_cfg; + + return SRSLTE_SUCCESS; +} \ No newline at end of file diff --git a/lib/src/phy/ue/ue_ul_nr.c b/lib/src/phy/ue/ue_ul_nr.c index 43496a887..6c64b9a2b 100644 --- a/lib/src/phy/ue/ue_ul_nr.c +++ b/lib/src/phy/ue/ue_ul_nr.c @@ -230,12 +230,16 @@ void srslte_ue_ul_nr_free(srslte_ue_ul_nr_t* q) SRSLTE_MEM_ZERO(q, srslte_ue_ul_nr_t, 1); } -int srslte_ue_ul_nr_pusch_info(const srslte_ue_ul_nr_t* q, const srslte_sch_cfg_nr_t* cfg, char* str, uint32_t str_len) +int srslte_ue_ul_nr_pusch_info(const srslte_ue_ul_nr_t* q, + const srslte_sch_cfg_nr_t* cfg, + const srslte_uci_value_nr_t* uci_value, + char* str, + uint32_t str_len) { int len = 0; // Append PDSCH info - len += srslte_pusch_nr_tx_info(&q->pusch, cfg, &cfg->grant, &str[len], str_len - len); + len += srslte_pusch_nr_tx_info(&q->pusch, cfg, &cfg->grant, uci_value, &str[len], str_len - len); return len; } diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 7915c185d..8d7ea11ee 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -283,14 +283,18 @@ bool cc_worker::work_ul() mac_ul_grant.rnti = pusch_cfg.grant.rnti; mac_ul_grant.tti = ul_slot_cfg.idx; mac_ul_grant.tbs = pusch_cfg.grant.tb[0].tbs; - phy->stack->new_grant_ul(0, mac_ul_grant, &ul_action); - // Assignning MAC provided values to PUSCH config structs + // Set UCI configuration following procedures + srslte_ra_ul_set_grant_uci_nr(&phy->cfg.pusch, &uci_data.cfg, &pusch_cfg); + + // Assigning MAC provided values to PUSCH config structs pusch_cfg.grant.tb[0].softbuffer.tx = ul_action.tb.softbuffer; + // Setup data for encoding srslte_pusch_data_nr_t data = {}; data.payload = ul_action.tb.payload->msg; + data.uci = uci_data.value; // Encode PUSCH transmission if (srslte_ue_ul_nr_encode_pusch(&ue_ul, &ul_slot_cfg, &pusch_cfg, &data) < SRSLTE_SUCCESS) { @@ -301,7 +305,7 @@ bool cc_worker::work_ul() // PUSCH Logging if (logger.info.enabled()) { std::array str; - srslte_ue_ul_nr_pusch_info(&ue_ul, &pusch_cfg, str.data(), str.size()); + srslte_ue_ul_nr_pusch_info(&ue_ul, &pusch_cfg, &data.uci, str.data(), str.size()); logger.info(ul_action.tb.payload->msg, pusch_cfg.grant.tb[0].tbs / 8, "PUSCH (NR): cc=%d, %s, tti_tx=%d",