diff --git a/lib/include/srslte/phy/ue/ue_dl_nr.h b/lib/include/srslte/phy/ue/ue_dl_nr.h index 4e893e2e1..9e763941d 100644 --- a/lib/include/srslte/phy/ue/ue_dl_nr.h +++ b/lib/include/srslte/phy/ue/ue_dl_nr.h @@ -58,6 +58,43 @@ typedef struct SRSLTE_API { bool ra_search_space_present; } srslte_ue_dl_nr_pdcch_cfg_t; +typedef struct { + uint32_t v_dai_dl; + bool dci_format_1_1; +} srslte_pdsch_ack_resource_nr_t; + +typedef struct { + srslte_pdsch_ack_resource_nr_t resource; + uint32_t k; + uint8_t value[SRSLTE_MAX_CODEWORDS]; // 0/1 or 2 for DTX + bool present; // set to true if there is a PDSCH on serving cell c associated with PDCCH in PDCCH monitoring occasion + // m, or there is a PDCCH indicating SPS PDSCH release on serving cell c + bool dl_bwp_changed; // set to true if PDCCH monitoring occasion m is before an active DL BWP change on serving cell c + bool ul_bwp_changed; // set to true if an active UL BWP change on the PCell and an active DL BWP change is not + // triggered by a DCI format 1_1 in PDCCH monitoring occasion m + bool second_tb_present; // set to true if two TB were detected in the PDCCH monitoring occasion m +} srslte_pdsch_ack_m_nr_t; + +#define SRSLTE_UCI_NR_MAX_M 10 + +typedef struct { + uint32_t M; + srslte_pdsch_ack_m_nr_t m[SRSLTE_UCI_NR_MAX_M]; +} srslte_pdsch_ack_cc_nr_t; + +typedef struct { + srslte_pdsch_ack_cc_nr_t cc[SRSLTE_MAX_CARRIERS]; + uint32_t nof_cc; + bool use_pusch; // Ser to true, if UCI bits are carried by PUSCH +} srslte_pdsch_ack_nr_t; + +typedef struct SRSLTE_API { + bool harq_ack_spatial_bundling_pucch; ///< Param harq-ACK-SpatialBundlingPUCCH, set to true if provided + bool harq_ack_spatial_bundling_pusch; ///< Param harq-ACK-SpatialBundlingPUSCH, set to true if provided + bool pdsch_harq_ack_codebook_semi_static; ///< set to true for pdsch-HARQ-ACK-Codebook is set to semi-static + bool max_cw_sched_dci_is_2; ///< Param maxNrofCodeWordsScheduledByDCI, set to true if present and equal to 2 +} srslte_ue_dl_nr_harq_ack_cfg_t; + typedef struct SRSLTE_API { uint32_t max_prb; uint32_t nof_rx_antennas; @@ -116,4 +153,8 @@ SRSLTE_API int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q, char* str, uint32_t str_len); +SRSLTE_API int srslte_ue_dl_nr_gen_ack(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg, + const srslte_pdsch_ack_nr_t* ack_info, + uint8_t* uci_data); + #endif // SRSLTE_UE_DL_NR_H diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 2afed56be..e8f52ac21 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -522,6 +522,7 @@ int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier, pdsch_grant->dci_format = dci_dl->format; pdsch_grant->rnti = dci_dl->rnti; pdsch_grant->rnti_type = dci_dl->rnti_type; + pdsch_grant->tb[0].rv = dci_dl->rv; // 5.1.6.2 DM-RS reception procedure if (ra_dl_dmrs(pdsch_hl_cfg, pdsch_grant, &pdsch_cfg->dmrs) < SRSLTE_SUCCESS) { diff --git a/lib/src/phy/ue/ue_dl_nr.c b/lib/src/phy/ue/ue_dl_nr.c index cb150e41b..9708401dd 100644 --- a/lib/src/phy/ue/ue_dl_nr.c +++ b/lib/src/phy/ue/ue_dl_nr.c @@ -509,3 +509,130 @@ int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q, return len; } + +// Implements TS 38.213 Table 9.1.3-1: Value of counter DAI in DCI format 1_0 and of counter DAI or total DAI DCI format +// 1_1 +static uint32_t ue_dl_nr_V_DL_DAI(uint32_t dai) +{ + return dai + 1; +} + +static int +ue_dl_nr_gen_ack_type2(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg, const srslte_pdsch_ack_nr_t* ack_info, uint8_t* o_ack) +{ + bool harq_ack_spatial_bundling = + ack_info->use_pusch ? cfg->harq_ack_spatial_bundling_pusch : cfg->harq_ack_spatial_bundling_pucch; + + uint32_t m = 0; // PDCCH with DCI format 1_0 or DCI format 1_1 monitoring occasion index: lower index corresponds to + // earlier PDCCH with DCI format 1_0 or DCI format 1_1 monitoring occasion + uint32_t j = 0; + uint32_t V_temp = 0; + uint32_t V_temp2 = 0; + + uint32_t N_DL_cells = ack_info->nof_cc; // number of serving cells configured by higher layers for the UE + uint32_t M = ack_info->cc[0].M; // Set M to the number of PDCCH monitoring occasion(s) + + // The following code follows the exact pseudo-code provided in TS 38.213 9.1.3.1 Type-2 HARQ-ACK codebook ... + while (m < M) { + uint32_t c = 0; // serving cell index: lower indexes correspond to lower RRC indexes of corresponding cell + while (c < N_DL_cells) { + // Get ACK information of serving cell c for the PDCH monitoring occasion m + const srslte_pdsch_ack_m_nr_t* ack = &ack_info->cc[c].m[m]; + + // Get DAI counter value + uint32_t V_DL_CDAI = ue_dl_nr_V_DL_DAI(ack->resource.v_dai_dl); + uint32_t V_DL_TDAI = ack->resource.dci_format_1_1 ? ue_dl_nr_V_DL_DAI(ack->resource.v_dai_dl) : UINT32_MAX; + + // Get ACK values + uint32_t ack_tb0 = ack->value[0]; + uint32_t ack_tb1 = ack->value[1]; + + // For a PDCCH monitoring occasion with DCI format 1_0 or DCI format 1_1 in the active DL BWP of a serving cell, + // when a UE receives a PDSCH with one transport block and the value of maxNrofCodeWordsScheduledByDCI is 2, the + // HARQ-ACK information is associated with the first transport block and the UE generates a NACK for the second + // transport block if harq-ACK-SpatialBundlingPUCCH is not provided and generates HARQ-ACK information with + // value of ACK for the second transport block if harq-ACK-SpatialBundlingPUCCH is provided. + if (cfg->max_cw_sched_dci_is_2 && ack->second_tb_present) { + ack_tb1 = harq_ack_spatial_bundling ? 1 : 0; + } + + // if PDCCH monitoring occasion m is before an active DL BWP change on serving cell c or an active UL + // BWP change on the PCell and an active DL BWP change is not triggered by a DCI format 1_1 in PDCCH + // monitoring occasion m + if (ack->dl_bwp_changed || ack->ul_bwp_changed) { + c = c + 1; + } else { + if (ack->present) { + if (V_DL_CDAI <= V_temp) { + j = j + 1; + } + + V_temp = V_DL_CDAI; + + if (V_DL_TDAI == UINT32_MAX) { + V_temp2 = V_DL_CDAI; + } else { + V_temp2 = V_DL_TDAI; + } + + // if harq-ACK-SpatialBundlingPUCCH is not provided and m is a monitoring occasion for PDCCH with DCI format + // 1_0 or DCI format 1_1 and the UE is configured by maxNrofCodeWordsScheduledByDCI with reception of two + // transport blocks for at least one configured DL BWP of at least one serving cell, + if (!harq_ack_spatial_bundling && cfg->max_cw_sched_dci_is_2) { + o_ack[8 * j + 2 * (V_DL_CDAI - 1) + 0] = ack_tb0; + o_ack[8 * j + 2 * (V_DL_CDAI - 1) + 1] = ack_tb1; + } + // elseif harq-ACK-SpatialBundlingPUCCH is provided to the UE and m is a monitoring occasion for + // PDCCH with DCI format 1_1 and the UE is configured by maxNrofCodeWordsScheduledByDCI with + // reception of two transport blocks in at least one configured DL BWP of a serving cell, + else if (harq_ack_spatial_bundling && ack->resource.dci_format_1_1 && cfg->max_cw_sched_dci_is_2) { + o_ack[4 * j + (V_DL_CDAI - 1)] = ack_tb0 & ack_tb1; + } + // else + else { + o_ack[4 * j + (V_DL_CDAI - 1)] = ack_tb0; + } + } + c = c + 1; + } + } + m = m + 1; + } + if (V_temp2 < V_temp) { + j = j + 1; + } + + // if harq-ACK-SpatialBundlingPUCCH is not provided to the UE and the UE is configured by + // maxNrofCodeWordsScheduledByDCI with reception of two transport blocks for at least one configured DL BWP of a + // serving cell, + uint32_t O_ack = 4 * j + V_temp2; + if (!harq_ack_spatial_bundling && cfg->max_cw_sched_dci_is_2) { + O_ack = 2 * (4 * j + V_temp2); + } + + // Implement here SPS PDSCH reception + // ... + + return (int)O_ack; +} + +int srslte_ue_dl_nr_gen_ack(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg, + const srslte_pdsch_ack_nr_t* ack_info, + uint8_t* uci_data) +{ + // Check inputs + if (cfg == NULL || ack_info == NULL || uci_data == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + // According TS 38.213 9.1.2 Type-1 HARQ-ACK codebook determination + if (cfg->pdsch_harq_ack_codebook_semi_static) { + // This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = semi-static. + ERROR("Type-1 HARQ-ACK codebook determination is NOT implemented"); + return SRSLTE_ERROR; + } + + // According TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination + // This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = dynamic. + return ue_dl_nr_gen_ack_type2(cfg, ack_info, uci_data); +} diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index c9fb43c8c..5ef572e04 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -31,10 +31,11 @@ typedef struct { } phy_nr_args_t; typedef struct { - srslte_sch_hl_cfg_nr_t pdsch; - srslte_sch_hl_cfg_nr_t pusch; - srslte_prach_cfg_t prach; - srslte_ue_dl_nr_pdcch_cfg_t pdcch; + srslte_sch_hl_cfg_nr_t pdsch; + srslte_sch_hl_cfg_nr_t pusch; + srslte_prach_cfg_t prach; + srslte_ue_dl_nr_pdcch_cfg_t pdcch; + srslte_ue_dl_nr_harq_ack_cfg_t harq_ack; } phy_nr_cfg_t; class state @@ -84,6 +85,10 @@ public: cfg.prach.num_ra_preambles = 64; cfg.prach.hs_flag = false; + // physicalCellGroupConfig + // pdsch-HARQ-ACK-Codebook: dynamic (1) + cfg.harq_ack.pdsch_harq_ack_codebook_semi_static = false; + // commonControlResourceSet // controlResourceSetId: 1 // frequencyDomainResources: ff0000000000