Initial UCI bits multiplexing in PUSCH

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent f4e9d00ea8
commit 9dffad87f2

@ -37,6 +37,14 @@ SRSLTE_API int srslte_csi_generate_reports(const srslte_csi_hl_cfg_t* cfg,
*/ */
SRSLTE_API int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports); SRSLTE_API int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports);
/**
* @brief Checks if the report list contains part 2 CSI report
* @param report_list Report list
* @param nof_reports Number of reports in the list
* @return True if at least one report contains part 2, false otherwise
*/
SRSLTE_API bool srslte_csi_has_part2(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports);
/** /**
* @brief Pack CSI part 1 bits for a PUCCH transmission * @brief Pack CSI part 1 bits for a PUCCH transmission
* @param report_list Provides the CSI report list * @param report_list Provides the CSI report list

@ -130,6 +130,7 @@ typedef struct SRSLTE_API {
// Resource set context // Resource set context
uint32_t nof_ports; ///< Number of antenna ports uint32_t nof_ports; ///< Number of antenna ports
uint32_t K_csi_rs; ///< Number of CSI-RS in the corresponding resource set uint32_t K_csi_rs; ///< Number of CSI-RS in the corresponding resource set
bool has_part2; ///< Set to true if the report has part 2
} srslte_csi_report_cfg_t; } srslte_csi_report_cfg_t;
/** /**

@ -208,6 +208,7 @@ typedef struct SRSLTE_API {
float beta_harq_ack_offset; float beta_harq_ack_offset;
float beta_csi_part1_offset; float beta_csi_part1_offset;
float scaling; float scaling;
bool freq_hopping_enabled;
} srslte_sch_cfg_nr_t; } srslte_sch_cfg_nr_t;
#endif // SRSLTE_PHCH_CFG_NR_H #endif // SRSLTE_PHCH_CFG_NR_H

@ -50,8 +50,17 @@ typedef struct SRSLTE_API {
srslte_evm_buffer_t* evm_buffer; srslte_evm_buffer_t* evm_buffer;
bool meas_time_en; bool meas_time_en;
uint32_t meas_time_us; uint32_t meas_time_us;
uint8_t* uci_ack; uint8_t* g_ulsch; ///< Temporal Encoded UL-SCH data
uint8_t* uci_csi; uint8_t* g_ack; ///< Temporal Encoded HARQ-ACK bits
uint8_t* g_csi1; ///< Temporal Encoded CSI part 1 bits
uint8_t* g_csi2; ///< Temporal Encoded CSI part 2 bits
uint32_t* pos_ulsch; ///< Reserved resource elements for HARQ-ACK multiplexing position
uint32_t* pos_ack; ///< Reserved resource elements for HARQ-ACK multiplexing position
uint32_t* pos_csi1; ///< Reserved resource elements for CSI part 1 multiplexing position
uint32_t* pos_csi2; ///< Reserved resource elements for CSI part 1 multiplexing position
uint32_t G_ack; ///< Number of encoded HARQ-ACK bits
uint32_t G_csi1; ///< Number of encoded CSI part 1 bits
uint32_t G_csi2; ///< Number of encoded CSI part 2 bits
} srslte_pusch_nr_t; } srslte_pusch_nr_t;
/** /**

@ -52,7 +52,7 @@ SRSLTE_API int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code * @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/ */
SRSLTE_API int SRSLTE_API int
srslte_ra_ul_nr_pdsch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant); srslte_ra_ul_nr_pusch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant);
/** /**
* @brief Calculates the number of PUSCH-DMRS CDM groups without data for DCI format 0_0 * @brief Calculates the number of PUSCH-DMRS CDM groups without data for DCI format 0_0

@ -107,10 +107,10 @@ SRSLTE_API srslte_basegraph_t srslte_sch_nr_select_basegraph(uint32_t tbs, doubl
* @param cfg SCH object * @param cfg SCH object
* @return * @return
*/ */
SRSLTE_API int srslte_sch_nr_fill_cfg(const srslte_carrier_nr_t* carrier, SRSLTE_API int srslte_sch_nr_fill_tb_info(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_t* sch_cfg, const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb, const srslte_sch_tb_t* tb,
srslte_sch_nr_tb_info_t* cfg); srslte_sch_nr_tb_info_t* cfg);
/** /**
* @brief Initialises an SCH object as transmitter * @brief Initialises an SCH object as transmitter

@ -14,7 +14,7 @@
#define SRSLTE_UCI_CFG_NR_H #define SRSLTE_UCI_CFG_NR_H
#include "csi_cfg.h" #include "csi_cfg.h"
#include "srslte/phy/common/phy_common.h" #include "srslte/phy/common/phy_common_nr.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@ -35,6 +35,37 @@
*/ */
#define SRSLTE_UCI_NR_MAX_CSI1_BITS 10 #define SRSLTE_UCI_NR_MAX_CSI1_BITS 10
/**
* @brief Uplink Control Information bits configuration for PUCCH transmission
*/
typedef struct {
uint16_t rnti; ///< RNTI
uint32_t resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1
uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or 1_1
uint32_t sr_resource_id; ///< Scheduling request resource identifier, only valid if positive SR
bool sr_positive_present; ///< Set to true if there is at least one positive SR
} srslte_uci_nr_pucch_cfg_t;
/**
* @brief Uplink Control Information bits configuration for PUSCH transmission
*/
typedef struct {
uint32_t l0; ///< First OFDM symbol that does not carry DMRS of the PUSCH, after the first DMRS symbol(s)
uint32_t l1; ///< OFDM symbol index of the first OFDM symbol that does not carry DMRS
uint32_t M_pusch_sc[SRSLTE_NSYMB_PER_SLOT_NR]; ///< Number of potential RE for PUSCH transmission
uint32_t M_pusch_sc_acc[SRSLTE_NSYMB_PER_SLOT_NR]; ///< Number of potential RE for PUSCH before the symbol
uint32_t M_uci_sc[SRSLTE_NSYMB_PER_SLOT_NR]; ///< Number of potential RE for UCI transmission
uint32_t K_sum; ///< Sum of UL-SCH code block sizes, set to zero if no UL-SCH
srslte_mod_t modulation; ///< Modulation for the PUSCH
uint32_t nof_layers; ///< Number of layers for PUSCH
float R; ///< Code rate of the PUSCH
float alpha; ///< Higher layer parameter scaling
float beta_harq_ack_offset;
float beta_csi_part1_offset;
uint32_t nof_re;
} srslte_uci_nr_pusch_cfg_t;
/** /**
* @brief Uplink Control Information (UCI) message configuration * @brief Uplink Control Information (UCI) message configuration
*/ */
@ -44,18 +75,10 @@ typedef struct SRSLTE_API {
uint32_t o_sr; ///< Number of SR bits uint32_t o_sr; ///< Number of SR bits
srslte_csi_report_cfg_t csi[SRSLTE_CSI_MAX_NOF_REPORT]; ///< CSI report configuration srslte_csi_report_cfg_t csi[SRSLTE_CSI_MAX_NOF_REPORT]; ///< CSI report configuration
uint32_t nof_csi; ///< Number of CSI reports uint32_t nof_csi; ///< Number of CSI reports
union {
/// PUSCH only parameters srslte_uci_nr_pucch_cfg_t pucch; ///< Configuration for transmission in PUCCH
bool without_ul_sch; ///< Set to true if no UL-SCH data is scheduled srslte_uci_nr_pusch_cfg_t pusch; ///< Configuration for transmission in PUSCH
bool has_csi_part2; ///< Set to true if the CSI reports have part 2 };
/// PUCCH only parameters
uint16_t rnti; ///< RNTI
uint32_t pucch_resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1
uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or 1_1
uint32_t sr_resource_id; ///< Scheduling request resource identifier, only valid if positive SR
bool sr_positive_present; ///< Set to true if there is at least one positive SR
} srslte_uci_cfg_nr_t; } srslte_uci_cfg_nr_t;
/** /**

@ -125,23 +125,33 @@ SRSLTE_API int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
srslte_uci_value_nr_t* value); srslte_uci_value_nr_t* value);
/** /**
* @brief Calculates the total number of encoded bits for HARQ-ACK * @brief Calculates total number of resource elements for HARQ-ACK multiplexing in PUSCH
* @remark Implementation according to TS 38.312 clause 6.3.2.4.1.1 for UCI encoded by polar code
* @remark Implementation according to TS 38.312 clause 6.3.2.4.2.1 for UCI encoded by channel codig of small lengths
* @param cfg UCI NR PUSCH configuration
* @param O_ack Number of ACK
* @return The number of resource elements for HARQ-ACK in a PUSCH transmission
*/
SRSLTE_API int srslte_uci_nr_pusch_ack_nof_re(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack);
/**
* @brief Calculates total number of ebncoded bits for HARQ-ACK multiplexing in PUSCH
* @param[in,out] q NR-UCI object * @param[in,out] q NR-UCI object
* @param[in] cfg PUSCH transmission configuration * @param[in] cfg PUSCH transmission configuration
* @return The number of encoded bits if successful, SRSLTE_ERROR code otherwise * @return The number of encoded bits if successful, SRSLTE_ERROR code otherwise
*/ */
SRSLTE_API int srslte_uci_nr_pusch_E_uci_ack(srslte_uci_nr_t* q, const srslte_sch_cfg_nr_t* cfg); SRSLTE_API int srslte_uci_nr_pusch_ack_nof_bits(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack);
/** /**
* @brief Encodes HARQ-ACK bits for PUSCH transmission * @brief Encodes HARQ-ACK bits for PUSCH transmission
* @param[in,out] q NR-UCI object * @param[in,out] q NR-UCI object
* @param[in] cfg PUSCH transmission configuration * @param[in] cfg UCI configuration
* @param[in] value UCI value * @param[in] value UCI value
* @param[out] o_ack Encoded ack bits * @param[out] o_ack Encoded ack bits
* @return The number of encoded bits if successful, SRSLTE_ERROR code otherwise * @return The number of encoded bits if successful, SRSLTE_ERROR code otherwise
*/ */
SRSLTE_API int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q, SRSLTE_API int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q,
const srslte_sch_cfg_nr_t* cfg, const srslte_uci_cfg_nr_t* cfg,
const srslte_uci_value_nr_t* value, const srslte_uci_value_nr_t* value,
uint8_t* o_ack); uint8_t* o_ack);

@ -172,6 +172,20 @@ int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof
return (int)count; return (int)count;
} }
bool srslte_csi_has_part2(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports)
{
if (report_list == NULL || nof_reports == 0) {
return false;
}
for (uint32_t i = 0; i < nof_reports; i++) {
if (report_list[i].has_part2) {
return true;
}
}
return false;
}
int srslte_csi_part1_pack(const srslte_csi_report_cfg_t* report_cfg, int srslte_csi_part1_pack(const srslte_csi_report_cfg_t* report_cfg,
const srslte_csi_report_value_t* report_value, const srslte_csi_report_value_t* report_value,
uint32_t nof_reports, uint32_t nof_reports,

@ -194,7 +194,7 @@ static void srslte_pdsch_re_cp(cf_t* sf_symbols, cf_t* symbols, uint32_t count,
* As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with group 2: * As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with group 2:
* *
* +---+---+---+---+---+---+---+---+---+---+---+---+ * +---+---+---+---+---+---+---+---+---+---+---+---+
* | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 | * | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 |
* +---+---+---+---+---+---+---+---+---+---+---+---+ * +---+---+---+---+---+---+---+---+---+---+---+---+
* -- k --> * -- k -->
* *

@ -538,7 +538,7 @@ static uint32_t pucch_nr_format2_cinit(const srslte_carrier_nr_t* carri
{ {
uint32_t n_id = (pucch_cfg->scrambling_id_present) ? pucch_cfg->scrambling_id_present : carrier->id; uint32_t n_id = (pucch_cfg->scrambling_id_present) ? pucch_cfg->scrambling_id_present : carrier->id;
return ((uint32_t)uci_cfg->rnti << 15U) + n_id; return ((uint32_t)uci_cfg->pucch.rnti << 15U) + n_id;
} }
// Implements TS 38.211 section 6.3.2.5 PUCCH format 2 // Implements TS 38.211 section 6.3.2.5 PUCCH format 2

@ -33,6 +33,24 @@ int pusch_nr_init_common(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* arg
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->g_ulsch = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->g_ack = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->g_csi1 = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->g_csi2 = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
if (q->g_ack == NULL || q->g_csi1 == NULL || q->g_csi2 == NULL || q->g_ulsch == NULL) {
ERROR("Malloc");
return SRSLTE_ERROR;
}
q->pos_ulsch = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->pos_ack = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->pos_csi1 = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->pos_csi2 = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
if (q->pos_ack == NULL || q->pos_csi1 == NULL || q->pos_csi2 == NULL || q->pos_ulsch == NULL) {
ERROR("Malloc");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -151,6 +169,32 @@ void srslte_pusch_nr_free(srslte_pusch_nr_t* q)
return; return;
} }
if (q->g_ulsch != NULL) {
free(q->g_ulsch);
}
if (q->g_ack != NULL) {
free(q->g_ack);
}
if (q->g_csi1 != NULL) {
free(q->g_csi1);
}
if (q->g_csi2 != NULL) {
free(q->g_csi2);
}
if (q->pos_ulsch != NULL) {
free(q->pos_ulsch);
}
if (q->pos_ack != NULL) {
free(q->pos_ack);
}
if (q->pos_csi1 != NULL) {
free(q->pos_csi1);
}
if (q->pos_csi2 != NULL) {
free(q->pos_csi2);
}
for (uint32_t cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) { for (uint32_t cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) {
if (q->b[cw]) { if (q->b[cw]) {
free(q->b[cw]); free(q->b[cw]);
@ -176,6 +220,8 @@ void srslte_pusch_nr_free(srslte_pusch_nr_t* q)
if (q->evm_buffer != NULL) { if (q->evm_buffer != NULL) {
srslte_evm_free(q->evm_buffer); srslte_evm_free(q->evm_buffer);
} }
SRSLTE_MEM_ZERO(q, srslte_pusch_nr_t, 1);
} }
/** /**
@ -420,13 +466,302 @@ pusch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_sch_cfg_nr_t* cf
return cinit; return cinit;
} }
// int pusch_nr_mux_uci(srslte_pusch_nr_t* q) { static inline int
// uint8_t *g_ul_sch; // coded bits for UL-SCH pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, srslte_uci_cfg_nr_t* uci_cfg)
// uint8_t *g_ack; // coded bits for HARQ-ACK {
// uint8_t *g_csi_p1; // coded bits for CSI part 1 // Initially, copy all fields
// uint8_t *g_csi_p2; // coded bits for CSI part 2 *uci_cfg = cfg->uci;
//
//} // Reset UCI PUSCH configuration
SRSLTE_MEM_ZERO(&uci_cfg->pusch, srslte_uci_nr_pusch_cfg_t, 1);
// Get DMRS symbol indexes
uint32_t nof_dmrs_l = 0;
uint32_t dmrs_l[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int n = srslte_dmrs_sch_get_symbols_idx(&cfg->dmrs, &cfg->grant, dmrs_l);
if (n < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
nof_dmrs_l = (uint32_t)n;
// Find OFDM symbol index of the first OFDM symbol after the first set of consecutive OFDM symbol(s) carrying DMRS
// Starts at first OFDM symbol carrying DMRS
for (uint32_t l = dmrs_l[0], dmrs_l_idx = 0; l < cfg->grant.S + cfg->grant.L; l++) {
// Check if it is not carrying DMRS...
if (l != dmrs_l[dmrs_l_idx]) {
// Set value and stop iterating
uci_cfg->pusch.l0 = l;
break;
}
// Move to the next DMRS OFDM symbol index
if (dmrs_l_idx < nof_dmrs_l) {
dmrs_l_idx++;
}
}
// Find OFDM symbol index of the first OFDM symbol that does not carry DMRS
// Starts at first OFDM symbol of the PUSCH transmission
for (uint32_t l = cfg->grant.S, dmrs_l_idx = 0; l < cfg->grant.S + cfg->grant.L; l++) {
// Check if it is not carrying DMRS...
if (l != dmrs_l[dmrs_l_idx]) {
uci_cfg->pusch.l1 = l;
break;
}
// Move to the next DMRS OFDM symbol index
if (dmrs_l_idx < nof_dmrs_l) {
dmrs_l_idx++;
}
}
// Number of DMRS per PRB
int n_prb_dmrs = srslte_dmrs_sch_get_N_prb(&cfg->dmrs, &cfg->grant);
if (n_prb_dmrs < SRSLTE_SUCCESS) {
ERROR("Error calculating number of DMRS per PRB");
return SRSLTE_ERROR;
}
// Accumulative Resource Element shall start in zero
uci_cfg->pusch.M_pusch_sc_acc[0] = 0;
// Set UCI RE number of candidates per OFDM symbol according to TS 38.312 6.3.2.4.2.1
for (uint32_t l = 0, dmrs_l_idx = 0; l < SRSLTE_NSYMB_PER_SLOT_NR; l++) {
// Skip if OFDM symbol is outside of the PUSCH transmission
if (l < cfg->grant.S || l >= (cfg->grant.S + cfg->grant.L) || l == dmrs_l[dmrs_l_idx]) {
uci_cfg->pusch.M_pusch_sc[l] = 0;
uci_cfg->pusch.M_pusch_sc_acc[l + 1] = uci_cfg->pusch.M_pusch_sc_acc[l] + uci_cfg->pusch.M_pusch_sc[l];
uci_cfg->pusch.M_uci_sc[l] = 0;
continue;
}
// OFDM symbol carries DMRS
if (l == dmrs_l[dmrs_l_idx]) {
// Calculate PUSCH RE candidates
uci_cfg->pusch.M_pusch_sc[l] = cfg->grant.nof_prb * (SRSLTE_NRE - n_prb_dmrs);
uci_cfg->pusch.M_pusch_sc_acc[l + 1] = uci_cfg->pusch.M_pusch_sc_acc[l] + uci_cfg->pusch.M_pusch_sc[l];
// The Number of RE candidates for UCI are 0
uci_cfg->pusch.M_uci_sc[l] = 0;
// Advance DMRS symbol index
dmrs_l_idx++;
// Skip to next symbol
continue;
}
// Number of RE for Phase Tracking Reference Signals (PT-RS)
uint32_t M_ptrs_sc = 0; // Not implemented yet
// Number of RE given by the grant
uci_cfg->pusch.M_pusch_sc[l] = cfg->grant.nof_prb * SRSLTE_NRE;
// Calculate the number of UCI candidates
uci_cfg->pusch.M_uci_sc[l] = uci_cfg->pusch.M_pusch_sc[l] - M_ptrs_sc;
}
// Generate SCH Transport block information
srslte_sch_nr_tb_info_t sch_tb_info = {};
if (srslte_sch_nr_fill_tb_info(&q->carrier, &cfg->sch_cfg, &cfg->grant.tb[0], &sch_tb_info) < SRSLTE_SUCCESS) {
ERROR("Generating TB info");
return SRSLTE_ERROR;
}
// Calculate the sum of codeblock sizes
for (uint32_t i = 0; i < sch_tb_info.C; i++) {
// Accumulate codeblock size if mask is enabled
uci_cfg->pusch.K_sum += (sch_tb_info.mask[i]) ? sch_tb_info.Kr : 0;
}
// Set other PUSCH parameters
uci_cfg->pusch.modulation = cfg->grant.tb[0].mod;
uci_cfg->pusch.nof_layers = cfg->grant.nof_layers;
uci_cfg->pusch.R = (float)cfg->grant.tb[0].R;
uci_cfg->pusch.alpha = cfg->scaling;
uci_cfg->pusch.beta_harq_ack_offset = cfg->beta_harq_ack_offset;
uci_cfg->pusch.beta_csi_part1_offset = cfg->beta_csi_part1_offset;
uci_cfg->pusch.nof_re = cfg->grant.tb[0].nof_re;
return SRSLTE_SUCCESS;
}
#define CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN))
// Implements TS 38.212 6.2.7 Data and control multiplexing (for NR-PUSCH)
static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t* cfg)
{
// Bit positions
uint32_t* pos_ulsch = q->pos_ulsch; // coded bits for UL-SCH
uint32_t* pos_ack = q->pos_ack; // coded bits for HARQ-ACK
uint32_t* pos_csi1 = q->pos_csi1; // coded bits for CSI part 1
uint32_t* pos_csi2 = q->pos_csi2; // coded bits for CSI part 2
// Key OFDM symbol indexes
uint32_t l1 =
cfg->pusch.l0; // First OFDM symbol that does not carry DMRS of the PUSCH, after the first DMRS symbol(s)
uint32_t l1_csi = cfg->pusch.l1; // OFDM symbol index of the first OFDM symbol that does not carry DMRS
// Number of UCI bits
uint32_t G_ack = q->G_ack;
uint32_t G_csi1 = q->G_csi1;
uint32_t G_csi2 = q->G_csi2;
// Other...
uint32_t Nl = cfg->pusch.nof_layers;
uint32_t Qm = srslte_mod_bits_x_symbol(cfg->pusch.modulation);
// If 2 or less HARQ-ACK bits, use reserve
uint32_t G_ack_rvd = 0;
if (cfg->o_ack <= 2) {
G_ack_rvd = G_ack;
G_ack = 0;
}
// Counters
uint32_t m_ack_count = 0;
uint32_t m_csi1_count = 0;
uint32_t m_csi2_count = 0;
uint32_t m_ulsch_count = 0;
uint32_t m_all_count = 0;
for (uint32_t l = 0; l < SRSLTE_NSYMB_PER_SLOT_NR; l++) {
// Skip if symbol has potential for data
if (cfg->pusch.M_pusch_sc[l] == 0) {
continue;
}
// Put UL-SCH only if this OFDM symbol has no potential for UCI
if (cfg->pusch.M_uci_sc[l] == 0) {
for (uint32_t i = 0; i < cfg->pusch.M_pusch_sc[l] * Qm * Nl; i++) {
pos_ulsch[m_ulsch_count++] = m_all_count++;
}
continue;
}
uint32_t M_ulsch_sc = cfg->pusch.M_pusch_sc[l];
uint32_t M_uci_sc = cfg->pusch.M_uci_sc[l];
uint32_t M_uci_rvd = 0;
// Compute HARQ-ACK bits multiplexing
uint32_t ack_d = 0;
uint32_t ack_m_re_count = 0;
if (l >= l1 && m_ack_count < G_ack_rvd) {
if (cfg->o_ack <= 2) {
ack_d = 1;
ack_m_re_count = M_ulsch_sc;
if (G_ack_rvd - m_ack_count < M_uci_sc * Nl * Qm) {
ack_d = (M_uci_sc * Nl * Qm) / (G_ack_rvd - m_ack_count);
ack_m_re_count = CEIL(G_ack_rvd - m_ack_count, Nl * Qm);
}
M_uci_rvd = ack_m_re_count;
} else {
ack_d = 1;
ack_m_re_count = M_ulsch_sc;
if (G_ack - m_ack_count < M_uci_sc * Nl * Qm) {
ack_d = (M_uci_sc * Nl * Qm) / (G_ack_rvd - m_ack_count);
ack_m_re_count = M_ulsch_sc;
}
M_uci_sc -= ack_m_re_count;
}
}
// Compute CSI part 1 bits multiplexing
uint32_t csi1_d = 0;
uint32_t csi1_m_re_count = 0;
if (l >= l1_csi && M_uci_sc > M_uci_rvd && m_csi1_count < G_csi1) {
csi1_d = 1;
csi1_m_re_count = M_uci_sc - M_uci_rvd;
if (G_csi1 - m_csi1_count < (M_uci_sc - M_uci_rvd) * Nl * Qm) {
csi1_d = ((M_uci_sc - M_uci_rvd) * Nl * Qm) / (G_csi1 - m_csi1_count);
csi1_m_re_count = CEIL(G_csi1 - m_csi1_count, Nl * Qm);
}
M_uci_sc -= csi1_m_re_count;
}
// Compute CSI part 2 bits multiplexing
uint32_t csi2_d = 0;
uint32_t csi2_m_re_count = 0;
if (l >= l1_csi && M_uci_sc > M_uci_rvd && m_csi2_count < G_csi2) {
csi2_d = 1;
csi2_m_re_count = M_uci_sc - M_uci_rvd;
if (G_csi2 - m_csi2_count < (M_uci_sc - M_uci_rvd) * Nl * Qm) {
csi2_d = ((M_uci_sc - M_uci_rvd) * Nl * Qm) / (G_csi2 - m_csi2_count);
csi2_m_re_count = CEIL(G_csi2 - m_csi2_count, Nl * Qm);
}
M_uci_sc -= csi2_m_re_count;
}
// Leave the rest for UL-SCH
uint32_t ulsch_m_re_count = M_uci_sc;
for (uint32_t i = 0, csi1_i = 0, csi2_i = 0; i < cfg->pusch.M_pusch_sc[l] * Qm * Nl; i++) {
if (ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack) {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_ack[m_ack_count++] = m_all_count++;
}
ack_m_re_count--;
} else if (csi1_m_re_count != 0 && csi1_i % csi1_d == 0 && m_csi1_count < G_csi1) {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_csi1[m_csi1_count++] = m_all_count++;
}
csi1_m_re_count--;
csi1_i++;
} else if (csi2_m_re_count != 0 && csi2_i % csi2_d == 0 && m_csi2_count < G_csi2) {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_csi2[m_csi2_count++] = m_all_count++;
}
csi2_m_re_count--;
csi1_i++;
csi2_i++;
} else {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_ulsch[m_ulsch_count++] = m_all_count++;
}
ulsch_m_re_count--;
csi1_i++;
csi2_i++;
}
// Set reserved bits
if (i % ack_d == 0 && m_ack_count < G_ack_rvd) {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_ack[m_ack_count++] = m_all_count++;
}
ack_m_re_count--;
}
}
// Checks that all RE are allocated as planned
if (ack_m_re_count != 0) {
ERROR("ack_m_re_count=%d", ack_m_re_count);
}
if (csi1_m_re_count != 0) {
ERROR("csi1_m_re_count=%d", csi1_m_re_count);
}
if (csi2_m_re_count != 0) {
ERROR("csi2_m_re_count=%d", csi2_m_re_count);
}
if (ulsch_m_re_count != 0) {
ERROR("ulsch_m_re_count=%d", ulsch_m_re_count);
}
}
if (G_ack_rvd != 0 && G_ack_rvd != m_ack_count) {
ERROR("Not matched %d!=%d", G_ack_rvd, m_ack_count);
}
if (G_ack != 0 && G_ack != m_ack_count) {
ERROR("Not matched %d!=%d", G_ack, m_ack_count);
}
if (G_csi1 != 0 && G_csi1 != m_csi1_count) {
ERROR("Not matched %d!=%d", G_csi1, m_csi1_count);
}
if (G_csi2 != 0 && G_csi2 != m_csi2_count) {
ERROR("Not matched %d!=%d", G_csi2, m_csi2_count);
}
return SRSLTE_SUCCESS;
}
static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q, static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg, const srslte_sch_cfg_nr_t* cfg,
@ -453,7 +788,7 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
} }
// Encode SCH // Encode SCH
if (srslte_ulsch_nr_encode(&q->sch, &cfg->sch_cfg, tb, data, q->b[tb->cw_idx]) < SRSLTE_SUCCESS) { if (srslte_ulsch_nr_encode(&q->sch, &cfg->sch_cfg, tb, data, q->g_ulsch) < SRSLTE_SUCCESS) {
ERROR("Error in SCH encoding"); ERROR("Error in SCH encoding");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -463,6 +798,30 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits); srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits);
} }
// Multiplex UL-SCH
for (uint32_t i = 0; i < tb->nof_bits; i++) {
q->b[tb->cw_idx][q->pos_ulsch[i]] = q->g_ulsch[i];
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("UL-SCH bit positions:");
srslte_vec_fprint_i(stdout, (int*)q->pos_ulsch, tb->nof_bits);
}
// Multiplex CSI part 1
for (uint32_t i = 0; i < q->G_csi1; i++) {
q->b[tb->cw_idx][q->pos_csi1[i]] = q->g_csi1[i];
}
// Multiplex CSI part 2
for (uint32_t i = 0; i < q->G_csi2; i++) {
q->b[tb->cw_idx][q->pos_csi2[i]] = q->g_csi2[i];
}
// Multiplex HARQ-ACK
for (uint32_t i = 0; i < q->G_ack; i++) {
q->b[tb->cw_idx][q->pos_ack[i]] = q->g_ack[i];
}
// 7.3.1.1 Scrambling // 7.3.1.1 Scrambling
uint32_t cinit = pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx); uint32_t cinit = pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx);
srslte_sequence_apply_bit(q->b[tb->cw_idx], q->b[tb->cw_idx], tb->nof_bits, cinit); srslte_sequence_apply_bit(q->b[tb->cw_idx], q->b[tb->cw_idx], tb->nof_bits, cinit);
@ -500,12 +859,26 @@ int srslte_pusch_nr_encode(srslte_pusch_nr_t* q,
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
// Fill UCI configuration for PUSCH configuration
srslte_uci_cfg_nr_t uci_cfg = {};
if (pusch_nr_fill_uci_cfg(q, cfg, &uci_cfg) < SRSLTE_SUCCESS) {
ERROR("Error filling UCI configuration for PUSCH");
return SRSLTE_ERROR;
}
// Encode HARQ-ACK bits // Encode HARQ-ACK bits
int E_uci_ack = srslte_uci_nr_encode_pusch_ack(&q->uci, cfg, &data[0].uci, q->uci_ack); int E_uci_ack = srslte_uci_nr_encode_pusch_ack(&q->uci, &uci_cfg, &data[0].uci, q->g_ack);
if (E_uci_ack < SRSLTE_SUCCESS) { if (E_uci_ack < SRSLTE_SUCCESS) {
ERROR("Error encoding HARQ-ACK bits"); ERROR("Error encoding HARQ-ACK bits");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->G_ack = E_uci_ack;
// Generate PUSCH UCI/UL-SCH multiplexing
if (pusch_nr_gen_mux_uci(q, &uci_cfg) < SRSLTE_SUCCESS) {
ERROR("Error generating PUSCH mux tables");
return SRSLTE_ERROR;
}
// 7.3.1.1 and 7.3.1.2 // 7.3.1.1 and 7.3.1.2
uint32_t nof_cw = 0; uint32_t nof_cw = 0;
@ -592,21 +965,26 @@ static inline int pusch_nr_decode_codeword(srslte_pusch_nr_t* q,
res->evm = srslte_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits); res->evm = srslte_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits);
} }
// Change LLR sign // Demultiplex UL-SCH, change sign
int8_t* g_ulsch_llr = (int8_t*)q->g_ulsch;
for (uint32_t i = 0; i < tb->nof_bits; i++) { for (uint32_t i = 0; i < tb->nof_bits; i++) {
llr[i] = -llr[i]; g_ulsch_llr[i] = -llr[q->pos_ulsch[i]];
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("UL-SCH bit positions:");
srslte_vec_fprint_i(stdout, (int*)q->pos_ulsch, tb->nof_bits);
} }
// Descrambling // Descrambling
srslte_sequence_apply_c(llr, llr, tb->nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx)); srslte_sequence_apply_c(g_ulsch_llr, g_ulsch_llr, tb->nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx));
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("b="); DEBUG("b=");
srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits); srslte_vec_fprint_bs(stdout, g_ulsch_llr, tb->nof_bits);
} }
// Decode SCH // Decode SCH
if (srslte_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, res->payload, &res->crc) < SRSLTE_SUCCESS) { if (srslte_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, g_ulsch_llr, res->payload, &res->crc) < SRSLTE_SUCCESS) {
ERROR("Error in SCH decoding"); ERROR("Error in SCH decoding");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -631,6 +1009,25 @@ int srslte_pusch_nr_decode(srslte_pusch_nr_t* q,
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
} }
// Check number of layers
if (q->max_layers < grant->nof_layers) {
ERROR("Error number of layers (%d) exceeds configured maximum (%d)", grant->nof_layers, q->max_layers);
return SRSLTE_ERROR;
}
// Fill UCI configuration for PUSCH configuration
srslte_uci_cfg_nr_t uci_cfg = {};
if (pusch_nr_fill_uci_cfg(q, cfg, &uci_cfg) < SRSLTE_SUCCESS) {
ERROR("Error filling UCI configuration for PUSCH");
return SRSLTE_ERROR;
}
// Generate PUSCH UCI/UL-SCH multiplexing
if (pusch_nr_gen_mux_uci(q, &uci_cfg) < SRSLTE_SUCCESS) {
ERROR("Error generating PUSCH mux tables");
return SRSLTE_ERROR;
}
uint32_t nof_cw = 0; uint32_t nof_cw = 0;
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
nof_cw += grant->tb[tb].enabled ? 1 : 0; nof_cw += grant->tb[tb].enabled ? 1 : 0;

@ -42,7 +42,7 @@ static const ue_ra_time_resource_t ue_ul_default_A_lut[16] = {{srslte_sch_mappin
{srslte_sch_mapping_type_A, 3, 0, 14}, {srslte_sch_mapping_type_A, 3, 0, 14},
{srslte_sch_mapping_type_A, 3, 0, 10}}; {srslte_sch_mapping_type_A, 3, 0, 10}};
int srslte_ra_ul_nr_pdsch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant) int srslte_ra_ul_nr_pusch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant)
{ {
uint32_t j[4] = {1, 1, 2, 3}; uint32_t j[4] = {1, 1, 2, 3};
@ -141,7 +141,7 @@ int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
if (ss_type == srslte_search_space_type_rar) { if (ss_type == srslte_search_space_type_rar) {
// Row 1 // Row 1
if (cfg->nof_common_time_ra == 0) { if (cfg->nof_common_time_ra == 0) {
srslte_ra_ul_nr_pdsch_time_resource_default_A(cfg->scs_cfg, m, grant); srslte_ra_ul_nr_pusch_time_resource_default_A(cfg->scs_cfg, m, grant);
} else if (m < SRSLTE_MAX_NOF_DL_ALLOCATION && m < cfg->nof_common_time_ra) { } else if (m < SRSLTE_MAX_NOF_DL_ALLOCATION && m < cfg->nof_common_time_ra) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant); ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
} else { } else {
@ -154,7 +154,7 @@ int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id == 0) { SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id == 0) {
// Row 2 // Row 2
if (cfg->nof_common_time_ra == 0) { if (cfg->nof_common_time_ra == 0) {
srslte_ra_ul_nr_pdsch_time_resource_default_A(cfg->scs_cfg, m, grant); srslte_ra_ul_nr_pusch_time_resource_default_A(cfg->scs_cfg, m, grant);
} else if (m < SRSLTE_MAX_NOF_DL_ALLOCATION) { } else if (m < SRSLTE_MAX_NOF_DL_ALLOCATION) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant); ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
} }
@ -168,7 +168,7 @@ int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
} else if (cfg->nof_common_time_ra > 0) { } else if (cfg->nof_common_time_ra > 0) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant); ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
} else { } else {
srslte_ra_ul_nr_pdsch_time_resource_default_A(cfg->scs_cfg, m, grant); srslte_ra_ul_nr_pusch_time_resource_default_A(cfg->scs_cfg, m, grant);
} }
} else { } else {
ERROR("Unhandled case"); ERROR("Unhandled case");
@ -461,9 +461,9 @@ int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
// - At least one positive SR // - At least one positive SR
// - up to 2 HARQ-ACK // - up to 2 HARQ-ACK
// - No CSI report // - No CSI report
if (uci_cfg->sr_positive_present > 0 && uci_cfg->o_ack <= SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS && if (uci_cfg->pucch.sr_positive_present > 0 && uci_cfg->o_ack <= SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS &&
uci_cfg->nof_csi == 0) { uci_cfg->nof_csi == 0) {
uint32_t sr_resource_id = uci_cfg->sr_resource_id; uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id;
if (sr_resource_id >= SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES) { if (sr_resource_id >= SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES) {
ERROR("SR resource ID (%d) exceeds the maximum ID (%d)", sr_resource_id, SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES); ERROR("SR resource ID (%d) exceeds the maximum ID (%d)", sr_resource_id, SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES);
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -486,7 +486,7 @@ int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
// - More than 2 HARQ-ACK // - More than 2 HARQ-ACK
// - No CSI report // - No CSI report
if (uci_cfg->o_sr > 0 && uci_cfg->o_ack > SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS && uci_cfg->nof_csi == 0) { if (uci_cfg->o_sr > 0 && uci_cfg->o_ack > SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS && uci_cfg->nof_csi == 0) {
return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch_resource_id, resource); return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, resource);
} }
// Use format 2, 3 or 4 CSI report resource from higher layers // Use format 2, 3 or 4 CSI report resource from higher layers
@ -502,10 +502,10 @@ int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
// a PUCCH resource set is provided by pucch-ResourceCommon through an index to a row of Table 9.2.1-1 for size // a PUCCH resource set is provided by pucch-ResourceCommon through an index to a row of Table 9.2.1-1 for size
// transmission of HARQ-ACK information on PUCCH in an initial UL BWP of N BWP PRBs. // transmission of HARQ-ACK information on PUCCH in an initial UL BWP of N BWP PRBs.
if (!pucch_cfg->enabled) { if (!pucch_cfg->enabled) {
uint32_t r_pucch = (2 * uci_cfg->n_cce_0) + 2 * uci_cfg->pucch_resource_id; uint32_t r_pucch = (2 * uci_cfg->pucch.n_cce_0) + 2 * uci_cfg->pucch.resource_id;
return ra_ul_nr_pucch_resource_default(r_pucch, resource); return ra_ul_nr_pucch_resource_default(r_pucch, resource);
} }
return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch_resource_id, resource); return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, resource);
} }
uint32_t srslte_ra_ul_nr_nof_sr_bits(uint32_t K) uint32_t srslte_ra_ul_nr_nof_sr_bits(uint32_t K)

@ -65,10 +65,10 @@ uint32_t sch_nr_n_prb_lbrm(uint32_t nof_prb)
return 273; return 273;
} }
int srslte_sch_nr_fill_cfg(const srslte_carrier_nr_t* carrier, int srslte_sch_nr_fill_tb_info(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_t* sch_cfg, const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb, const srslte_sch_tb_t* tb,
srslte_sch_nr_tb_info_t* cfg) srslte_sch_nr_tb_info_t* cfg)
{ {
if (!sch_cfg || !tb || !cfg) { if (!sch_cfg || !tb || !cfg) {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
@ -372,7 +372,7 @@ static inline int sch_nr_encode(srslte_sch_nr_t* q,
uint8_t* output_ptr = e_bits; uint8_t* output_ptr = e_bits;
srslte_sch_nr_tb_info_t cfg = {}; srslte_sch_nr_tb_info_t cfg = {};
if (srslte_sch_nr_fill_cfg(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) { if (srslte_sch_nr_fill_tb_info(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -514,7 +514,7 @@ int sch_nr_decode(srslte_sch_nr_t* q,
int8_t* input_ptr = e_bits; int8_t* input_ptr = e_bits;
srslte_sch_nr_tb_info_t cfg = {}; srslte_sch_nr_tb_info_t cfg = {};
if (srslte_sch_nr_fill_cfg(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) { if (srslte_sch_nr_fill_tb_info(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }

@ -27,13 +27,12 @@ static srslte_carrier_nr_t carrier = {
1 // max_mimo_layers 1 // max_mimo_layers
}; };
static uint32_t n_prb = 0; // Set to 0 for steering static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering static uint32_t mcs = 30; // Set to 30 for steering
static srslte_sch_cfg_nr_t pusch_cfg = {}; static srslte_sch_cfg_nr_t pusch_cfg = {};
static srslte_sch_grant_nr_t pusch_grant = {}; static uint16_t rnti = 0x1234;
static uint16_t rnti = 0x1234; static uint32_t nof_ack_bits = 0;
static uint32_t nof_ack_bits = 0; static uint32_t nof_csi_bits = 0;
static uint32_t nof_csi_bits = 0;
void usage(char* prog) void usage(char* prog)
{ {
@ -159,20 +158,20 @@ int main(int argc, char** argv)
} }
// Use grant default A time resources with m=0 // Use grant default A time resources with m=0
if (srslte_ra_ul_nr_pdsch_time_resource_default_A(carrier.numerology, 0, &pusch_grant) < SRSLTE_SUCCESS) { if (srslte_ra_ul_nr_pusch_time_resource_default_A(carrier.numerology, 0, &pusch_cfg.grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant"); ERROR("Error loading default grant");
goto clean_exit; goto clean_exit;
} }
// Load number of DMRS CDM groups without data // Load number of DMRS CDM groups without data
if (srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(&pusch_cfg, &pusch_grant) < SRSLTE_SUCCESS) { if (srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(&pusch_cfg, &pusch_cfg.grant) < SRSLTE_SUCCESS) {
ERROR("Error loading number of DMRS CDM groups without data"); ERROR("Error loading number of DMRS CDM groups without data");
goto clean_exit; goto clean_exit;
} }
pusch_grant.nof_layers = carrier.max_mimo_layers; pusch_cfg.grant.nof_layers = carrier.max_mimo_layers;
pusch_grant.dci_format = srslte_dci_format_nr_1_0; pusch_cfg.grant.dci_format = srslte_dci_format_nr_1_0;
pusch_grant.rnti = rnti; pusch_cfg.grant.rnti = rnti;
uint32_t n_prb_start = 1; uint32_t n_prb_start = 1;
uint32_t n_prb_end = carrier.nof_prb + 1; uint32_t n_prb_end = carrier.nof_prb + 1;
@ -188,6 +187,10 @@ int main(int argc, char** argv)
mcs_end = SRSLTE_MIN(mcs + 1, mcs_end); mcs_end = SRSLTE_MIN(mcs + 1, mcs_end);
} }
pusch_cfg.scaling = 0.650f;
pusch_cfg.beta_harq_ack_offset = 5.000f;
pusch_cfg.beta_csi_part1_offset = 5.000f;
if (srslte_chest_dl_res_init(&chest, carrier.nof_prb) < SRSLTE_SUCCESS) { if (srslte_chest_dl_res_init(&chest, carrier.nof_prb) < SRSLTE_SUCCESS) {
ERROR("Initiating chest"); ERROR("Initiating chest");
goto clean_exit; goto clean_exit;
@ -196,11 +199,11 @@ int main(int argc, char** argv)
for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) { for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) {
for (mcs = mcs_start; mcs < mcs_end; mcs++) { for (mcs = mcs_start; mcs < mcs_end; mcs++) {
for (uint32_t n = 0; n < SRSLTE_MAX_PRB_NR; n++) { for (uint32_t n = 0; n < SRSLTE_MAX_PRB_NR; n++) {
pusch_grant.prb_idx[n] = (n < n_prb); pusch_cfg.grant.prb_idx[n] = (n < n_prb);
} }
pusch_grant.dci_format = srslte_dci_format_nr_0_0; pusch_cfg.grant.dci_format = srslte_dci_format_nr_0_0;
if (srslte_ra_nr_fill_tb(&pusch_cfg, &pusch_grant, mcs, &pusch_grant.tb[0]) < SRSLTE_SUCCESS) { if (srslte_ra_nr_fill_tb(&pusch_cfg, &pusch_cfg.grant, mcs, &pusch_cfg.grant.tb[0]) < SRSLTE_SUCCESS) {
ERROR("Error filing tb"); ERROR("Error filing tb");
goto clean_exit; goto clean_exit;
} }
@ -212,10 +215,10 @@ int main(int argc, char** argv)
continue; continue;
} }
for (uint32_t i = 0; i < pusch_grant.tb[tb].tbs; i++) { for (uint32_t i = 0; i < pusch_cfg.grant.tb[tb].tbs; i++) {
data_tx[tb].payload[i] = (uint8_t)srslte_random_uniform_int_dist(rand_gen, 0, UINT8_MAX); data_tx[tb].payload[i] = (uint8_t)srslte_random_uniform_int_dist(rand_gen, 0, UINT8_MAX);
} }
pusch_grant.tb[tb].softbuffer.tx = &softbuffer_tx; pusch_cfg.grant.tb[tb].softbuffer.tx = &softbuffer_tx;
} }
// Generate HARQ ACK bits // Generate HARQ ACK bits
@ -238,22 +241,23 @@ int main(int argc, char** argv)
} }
} }
if (srslte_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_grant, data_tx, sf_symbols) < SRSLTE_SUCCESS) { if (srslte_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_cfg.grant, data_tx, sf_symbols) < SRSLTE_SUCCESS) {
ERROR("Error encoding"); ERROR("Error encoding");
goto clean_exit; goto clean_exit;
} }
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
pusch_grant.tb[tb].softbuffer.rx = &softbuffer_rx; pusch_cfg.grant.tb[tb].softbuffer.rx = &softbuffer_rx;
srslte_softbuffer_rx_reset(pusch_grant.tb[tb].softbuffer.rx); srslte_softbuffer_rx_reset(pusch_cfg.grant.tb[tb].softbuffer.rx);
} }
for (uint32_t i = 0; i < pusch_grant.tb->nof_re; i++) { for (uint32_t i = 0; i < pusch_cfg.grant.tb->nof_re; i++) {
chest.ce[0][0][i] = 1.0f; chest.ce[0][0][i] = 1.0f;
} }
chest.nof_re = pusch_grant.tb->nof_re; chest.nof_re = pusch_cfg.grant.tb->nof_re;
if (srslte_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_grant, &chest, sf_symbols, data_rx) < SRSLTE_SUCCESS) { if (srslte_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &chest, sf_symbols, data_rx) <
SRSLTE_SUCCESS) {
ERROR("Error encoding"); ERROR("Error encoding");
goto clean_exit; goto clean_exit;
} }
@ -264,18 +268,18 @@ int main(int argc, char** argv)
} }
float mse = 0.0f; float mse = 0.0f;
uint32_t nof_re = srslte_ra_dl_nr_slot_nof_re(&pusch_cfg, &pusch_grant); uint32_t nof_re = srslte_ra_dl_nr_slot_nof_re(&pusch_cfg, &pusch_cfg.grant);
for (uint32_t i = 0; i < pusch_grant.nof_layers; i++) { for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) {
for (uint32_t j = 0; j < nof_re; j++) { for (uint32_t j = 0; j < nof_re; j++) {
mse += cabsf(pusch_tx.d[i][j] - pusch_rx.d[i][j]); mse += cabsf(pusch_tx.d[i][j] - pusch_rx.d[i][j]);
} }
} }
if (nof_re * pusch_grant.nof_layers > 0) { if (nof_re * pusch_cfg.grant.nof_layers > 0) {
mse = mse / (nof_re * pusch_grant.nof_layers); mse = mse / (nof_re * pusch_cfg.grant.nof_layers);
} }
if (mse > 0.001) { if (mse > 0.001) {
ERROR("MSE error (%f) is too high", mse); ERROR("MSE error (%f) is too high", mse);
for (uint32_t i = 0; i < pusch_grant.nof_layers; i++) { for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) {
printf("d_tx[%d]=", i); printf("d_tx[%d]=", i);
srslte_vec_fprint_c(stdout, pusch_tx.d[i], nof_re); srslte_vec_fprint_c(stdout, pusch_tx.d[i], nof_re);
printf("d_rx[%d]=", i); printf("d_rx[%d]=", i);
@ -285,20 +289,20 @@ int main(int argc, char** argv)
} }
if (!data_rx[0].crc) { if (!data_rx[0].crc) {
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_grant.tb[0].tbs); ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_cfg.grant.tb[0].tbs);
goto clean_exit; goto clean_exit;
} }
if (memcmp(data_tx[0].payload, data_rx[0].payload, pusch_grant.tb[0].tbs / 8) != 0) { if (memcmp(data_tx[0].payload, data_rx[0].payload, pusch_cfg.grant.tb[0].tbs / 8) != 0) {
ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_grant.tb[0].tbs); ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_cfg.grant.tb[0].tbs);
printf("Tx data: "); printf("Tx data: ");
srslte_vec_fprint_byte(stdout, data_tx[0].payload, pusch_grant.tb[0].tbs / 8); srslte_vec_fprint_byte(stdout, data_tx[0].payload, pusch_cfg.grant.tb[0].tbs / 8);
printf("Rx data: "); printf("Rx data: ");
srslte_vec_fprint_byte(stdout, data_tx[0].payload, pusch_grant.tb[0].tbs / 8); srslte_vec_fprint_byte(stdout, data_tx[0].payload, pusch_cfg.grant.tb[0].tbs / 8);
goto clean_exit; goto clean_exit;
} }
printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pusch_grant.tb[0].tbs, data_rx[0].evm); printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pusch_cfg.grant.tb[0].tbs, data_rx[0].evm);
} }
} }

@ -11,11 +11,9 @@
*/ */
#include "srslte/phy/phch/uci_nr.h" #include "srslte/phy/phch/uci_nr.h"
#include "srslte/phy/ch_estimation/dmrs_sch.h"
#include "srslte/phy/fec/block/block.h" #include "srslte/phy/fec/block/block.h"
#include "srslte/phy/fec/polar/polar_chanalloc.h" #include "srslte/phy/fec/polar/polar_chanalloc.h"
#include "srslte/phy/phch/csi.h" #include "srslte/phy/phch/csi.h"
#include "srslte/phy/phch/sch_nr.h"
#include "srslte/phy/phch/uci_cfg.h" #include "srslte/phy/phch/uci_cfg.h"
#include "srslte/phy/utils/bit.h" #include "srslte/phy/utils/bit.h"
#include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/vector.h"
@ -258,13 +256,12 @@ static int uci_nr_unpack_pucch(const srslte_uci_cfg_nr_t* cfg, uint8_t* sequence
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
static int static int uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E)
uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, srslte_mod_t modulation, uint8_t* o, uint32_t E)
{ {
uint32_t i = 0; uint32_t i = 0;
srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1; srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1;
switch (modulation) { switch (cfg->pusch.modulation) {
case SRSLTE_MOD_BPSK: case SRSLTE_MOD_BPSK:
while (i < E) { while (i < E) {
o[i++] = c0; o[i++] = c0;
@ -317,15 +314,14 @@ uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, srslte_mo
return E; return E;
} }
static int static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E)
uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, srslte_mod_t modulation, uint8_t* o, uint32_t E)
{ {
uint32_t i = 0; uint32_t i = 0;
srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1; srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1;
srslte_uci_bit_type_t c1 = (q->bit_sequence[1] == 0) ? UCI_BIT_0 : UCI_BIT_1; srslte_uci_bit_type_t c1 = (q->bit_sequence[1] == 0) ? UCI_BIT_0 : UCI_BIT_1;
srslte_uci_bit_type_t c2 = ((q->bit_sequence[0] ^ q->bit_sequence[1]) == 0) ? UCI_BIT_0 : UCI_BIT_1; srslte_uci_bit_type_t c2 = ((q->bit_sequence[0] ^ q->bit_sequence[1]) == 0) ? UCI_BIT_0 : UCI_BIT_1;
switch (modulation) { switch (cfg->pusch.modulation) {
case SRSLTE_MOD_BPSK: case SRSLTE_MOD_BPSK:
case SRSLTE_MOD_QPSK: case SRSLTE_MOD_QPSK:
while (i < E) { while (i < E) {
@ -643,21 +639,16 @@ static int uci_nr_decode_11_1706_bit(srslte_uci_nr_t* q,
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
static int uci_nr_encode(srslte_uci_nr_t* q, static int uci_nr_encode(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* uci_cfg, uint32_t A, uint8_t* o, uint32_t E_uci)
const srslte_uci_cfg_nr_t* uci_cfg,
srslte_mod_t mod,
uint32_t A,
uint8_t* o,
uint32_t E_uci)
{ {
// 5.3.3.1 Encoding of 1-bit information // 5.3.3.1 Encoding of 1-bit information
if (A == 1) { if (A == 1) {
return uci_nr_encode_1bit(q, uci_cfg, mod, o, E_uci); return uci_nr_encode_1bit(q, uci_cfg, o, E_uci);
} }
// 5.3.3.2 Encoding of 2-bit information // 5.3.3.2 Encoding of 2-bit information
if (A == 2) { if (A == 2) {
return uci_nr_encode_2bit(q, uci_cfg, mod, o, E_uci); return uci_nr_encode_2bit(q, uci_cfg, o, E_uci);
} }
// 5.3.3.3 Encoding of other small block lengths // 5.3.3.3 Encoding of other small block lengths
@ -781,7 +772,7 @@ int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q,
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
return uci_nr_encode(q, uci_cfg, SRSLTE_MOD_NITEMS, A, o, E_uci); return uci_nr_encode(q, uci_cfg, A, o, E_uci);
} }
int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q, int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
@ -816,7 +807,7 @@ uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uin
{ {
uint32_t len = 0; uint32_t len = 0;
len = srslte_print_check(str, str_len, len, "rnti=0x%x", uci_data->cfg.rnti); len = srslte_print_check(str, str_len, len, "rnti=0x%x", uci_data->cfg.pucch.rnti);
if (uci_data->cfg.o_ack > 0) { if (uci_data->cfg.o_ack > 0) {
char str2[10]; char str2[10];
@ -835,92 +826,59 @@ uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uin
return len; return len;
} }
static int uci_nr_Q_ack_prime(srslte_uci_nr_t* q, const srslte_sch_cfg_nr_t* sch_cfg, uint32_t A) int srslte_uci_nr_pusch_ack_nof_re(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack)
{ {
// Get UL-SCH TB information if (cfg == NULL) {
srslte_sch_nr_tb_info_t tb_info = {}; return SRSLTE_ERROR_INVALID_INPUTS;
if (srslte_sch_nr_fill_cfg(&q->carrier, &sch_cfg->sch_cfg, &sch_cfg->grant.tb[0], &tb_info) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
// Get DMRS symbol indexes
uint32_t nof_dmrs_l = 0;
uint32_t dmrs_l[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int n = srslte_dmrs_sch_get_symbols_idx(&sch_cfg->dmrs, &sch_cfg->grant, dmrs_l);
if (n < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
} }
nof_dmrs_l = (uint32_t)n;
uint32_t O_ack = A; // Number of HARQ-ACK bits uint32_t L_ack = srslte_uci_nr_crc_len(O_ack); // Number of CRC bits
uint32_t L_ack = srslte_uci_nr_crc_len(A); // Number of CRC bits uint32_t Qm = srslte_mod_bits_x_symbol(cfg->modulation); // modulation order of the PUSCH
float beta_pusch_offset = sch_cfg->beta_harq_ack_offset; // Beta offset given by higher layers
uint32_t C_ulsch = tb_info.C; // number of code blocks for UL-SCH of the PUSCH
float alpha = sch_cfg->scaling; // Higher layer parameter scaling
float R = (float)sch_cfg->grant.tb[0].R; // code rate of the PUSCH
float Qm = srslte_mod_bits_x_symbol(sch_cfg->grant.tb[0].mod); // modulation order of the PUSCH
uint32_t K_sum = 0;
for (uint32_t i = 0; i < SRSLTE_MIN(C_ulsch, SRSLTE_SCH_NR_MAX_NOF_CB_LDPC); i++) {
K_sum += tb_info.mask[i] ? 0 : tb_info.Kr;
}
uint32_t dmrs_l_idx = 0;
uint32_t M_uci_sum = 0; uint32_t M_uci_sum = 0;
uint32_t M_uci_l0_sum = 0; uint32_t M_uci_l0_sum = 0;
for (uint32_t l = sch_cfg->grant.S; l < sch_cfg->grant.S + sch_cfg->grant.L; l++) { for (uint32_t l = 0; l < SRSLTE_NSYMB_PER_SLOT_NR; l++) {
uint32_t M_ptrs_sc = 0; // Not implemented yet M_uci_sum += cfg->M_uci_sc[l];
uint32_t M_pusch_sc = sch_cfg->grant.nof_prb * SRSLTE_NRE; if (l >= cfg->l0) {
uint32_t M_uci_sc = M_pusch_sc - M_ptrs_sc; M_uci_l0_sum += cfg->M_uci_sc[l];
// If the OFDM symbol contains DMRS, no UCI is mapped
if (l == dmrs_l[dmrs_l_idx] && dmrs_l_idx < nof_dmrs_l) {
M_uci_sc = 0;
dmrs_l_idx++;
} }
}
// Add subcarriers that can contain UCI RE if (!isnormal(cfg->R)) {
M_uci_sum += M_uci_sc; ERROR("Invalid Rate (%f)", cfg->R);
return SRSLTE_ERROR;
// Start adding after the first DMRS symbol
if (dmrs_l_idx > 0) {
M_uci_l0_sum += M_uci_sc;
}
} }
if (sch_cfg->uci.without_ul_sch) { if (cfg->K_sum == 0) {
return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * beta_pusch_offset) / (Qm * R)), alpha * M_uci_l0_sum); return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * cfg->beta_harq_ack_offset) / (Qm * cfg->R)),
cfg->alpha * M_uci_l0_sum);
} }
return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * beta_pusch_offset * M_uci_sum) / (float)K_sum), alpha * M_uci_l0_sum); return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * cfg->beta_harq_ack_offset * M_uci_sum) / cfg->K_sum),
cfg->alpha * M_uci_l0_sum);
} }
int srslte_uci_nr_pusch_E_uci_ack(srslte_uci_nr_t* q, const srslte_sch_cfg_nr_t* cfg) int srslte_uci_nr_pusch_ack_nof_bits(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack)
{ {
int A = cfg->uci.o_ack;
// Check inputs // Check inputs
if (q == NULL || cfg == NULL) { if (cfg == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
if (cfg->uci.without_ul_sch && cfg->uci.nof_csi > 1 && !cfg->uci.has_csi_part2 && cfg->uci.o_ack < 2) { int Q_ack_prime = srslte_uci_nr_pusch_ack_nof_re(cfg, O_ack);
A = 2;
}
int Q_ack_prime = uci_nr_Q_ack_prime(q, cfg, A);
if (Q_ack_prime < SRSLTE_SUCCESS) { if (Q_ack_prime < SRSLTE_SUCCESS) {
ERROR("Error calculating number of RE");
return Q_ack_prime; return Q_ack_prime;
} }
return (int)(Q_ack_prime * cfg->grant.nof_layers * srslte_mod_bits_x_symbol(cfg->grant.tb[0].mod)); return (int)(Q_ack_prime * cfg->nof_layers * srslte_mod_bits_x_symbol(cfg->modulation));
} }
int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q, int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q,
const srslte_sch_cfg_nr_t* cfg, const srslte_uci_cfg_nr_t* cfg,
const srslte_uci_value_nr_t* value, const srslte_uci_value_nr_t* value,
uint8_t* o) uint8_t* o)
{ {
int A = cfg->uci.o_ack; int A = cfg->o_ack;
// Check inputs // Check inputs
if (q == NULL || cfg == NULL || value == NULL || o == NULL) { if (q == NULL || cfg == NULL || value == NULL || o == NULL) {
@ -929,20 +887,21 @@ int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q,
// 6.3.2.1 UCI bit sequence generation // 6.3.2.1 UCI bit sequence generation
// 6.3.2.1.1 HARQ-ACK // 6.3.2.1.1 HARQ-ACK
if (cfg->uci.without_ul_sch && cfg->uci.nof_csi > 1 && !cfg->uci.has_csi_part2 && cfg->uci.o_ack < 2) { bool has_csi_part2 = srslte_csi_has_part2(cfg->csi, cfg->nof_csi);
if (cfg->pusch.K_sum == 0 && cfg->nof_csi > 1 && !has_csi_part2 && cfg->o_ack < 2) {
A = 2; A = 2;
q->bit_sequence[0] = (cfg->uci.o_ack == 0) ? 0 : value->ack[0]; q->bit_sequence[0] = (cfg->o_ack == 0) ? 0 : value->ack[0];
q->bit_sequence[1] = 0; q->bit_sequence[1] = 0;
} else { } else {
srslte_vec_u8_copy(q->bit_sequence, value->ack, cfg->uci.o_ack); srslte_vec_u8_copy(q->bit_sequence, value->ack, cfg->o_ack);
} }
// Compute total of encoded bits according to 6.3.2.4 Rate matching // Compute total of encoded bits according to 6.3.2.4 Rate matching
int E_uci = srslte_uci_nr_pusch_E_uci_ack(q, cfg); int E_uci = srslte_uci_nr_pusch_ack_nof_bits(&cfg->pusch, A);
if (E_uci < SRSLTE_SUCCESS) { if (E_uci < SRSLTE_SUCCESS) {
ERROR("Error calculating number of encoded bits"); ERROR("Error calculating number of encoded bits");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
return uci_nr_encode(q, &cfg->uci, cfg->grant.tb[0].mod, A, o, E_uci); return uci_nr_encode(q, cfg, A, o, E_uci);
} }

@ -574,8 +574,8 @@ static int ue_dl_nr_gen_ack_type2(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
} else { } else {
if (ack->present) { if (ack->present) {
// Load ACK resource data into UCI info // Load ACK resource data into UCI info
uci_data->cfg.pucch_resource_id = ack_info->cc[c].m[m].resource.pucch_resource_id; uci_data->cfg.pucch.resource_id = ack_info->cc[c].m[m].resource.pucch_resource_id;
uci_data->cfg.rnti = ack_info->cc[c].m[m].resource.rnti; uci_data->cfg.pucch.rnti = ack_info->cc[c].m[m].resource.rnti;
if (V_DL_CDAI <= V_temp) { if (V_DL_CDAI <= V_temp) {
j = j + 1; j = j + 1;

@ -73,9 +73,9 @@ public:
carrier.max_mimo_layers = 1; carrier.max_mimo_layers = 1;
// Hard-coded values, this should be set when the measurements take place // Hard-coded values, this should be set when the measurements take place
csi_measurements[0].K_csi_rs = 1; csi_measurements[0].K_csi_rs = 1;
csi_measurements[0].nof_ports = 1; csi_measurements[0].nof_ports = 1;
csi_measurements[1].K_csi_rs = 4; csi_measurements[1].K_csi_rs = 4;
csi_measurements[0].nof_ports = 1; csi_measurements[0].nof_ports = 1;
} }
@ -294,10 +294,10 @@ public:
} }
// Configure SR fields in UCI data // Configure SR fields in UCI data
uci_data.cfg.sr_resource_id = sr_resource_id[0]; uci_data.cfg.pucch.sr_resource_id = sr_resource_id[0];
uci_data.cfg.o_sr = srslte_ra_ul_nr_nof_sr_bits(sr_count_all); uci_data.cfg.o_sr = srslte_ra_ul_nr_nof_sr_bits(sr_count_all);
uci_data.cfg.sr_positive_present = sr_count_positive > 0; uci_data.cfg.pucch.sr_positive_present = sr_count_positive > 0;
uci_data.value.sr = sr_count_positive; uci_data.value.sr = sr_count_positive;
} }
void get_periodic_csi(const uint32_t& tti, srslte_uci_data_nr_t& uci_data) void get_periodic_csi(const uint32_t& tti, srslte_uci_data_nr_t& uci_data)
@ -307,7 +307,7 @@ public:
uci_data.cfg.nof_csi = n; uci_data.cfg.nof_csi = n;
} }
uci_data.cfg.rnti = stack->get_ul_sched_rnti_nr(tti).id; uci_data.cfg.pucch.rnti = stack->get_ul_sched_rnti_nr(tti).id;
} }
}; };
} // namespace nr } // namespace nr

Loading…
Cancel
Save