mirror of https://github.com/PentHertz/srsLTE.git
Initial UCI bits multiplexing in PUSCH
This commit is contained in:
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);
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param report_list Provides the CSI report list
|
||||
|
|
|
@ -130,6 +130,7 @@ typedef struct SRSLTE_API {
|
|||
// Resource set context
|
||||
uint32_t nof_ports; ///< Number of antenna ports
|
||||
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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -208,6 +208,7 @@ typedef struct SRSLTE_API {
|
|||
float beta_harq_ack_offset;
|
||||
float beta_csi_part1_offset;
|
||||
float scaling;
|
||||
bool freq_hopping_enabled;
|
||||
} srslte_sch_cfg_nr_t;
|
||||
|
||||
#endif // SRSLTE_PHCH_CFG_NR_H
|
||||
|
|
|
@ -50,8 +50,17 @@ typedef struct SRSLTE_API {
|
|||
srslte_evm_buffer_t* evm_buffer;
|
||||
bool meas_time_en;
|
||||
uint32_t meas_time_us;
|
||||
uint8_t* uci_ack;
|
||||
uint8_t* uci_csi;
|
||||
uint8_t* g_ulsch; ///< Temporal Encoded UL-SCH data
|
||||
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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -107,10 +107,10 @@ SRSLTE_API srslte_basegraph_t srslte_sch_nr_select_basegraph(uint32_t tbs, doubl
|
|||
* @param cfg SCH object
|
||||
* @return
|
||||
*/
|
||||
SRSLTE_API int srslte_sch_nr_fill_cfg(const srslte_carrier_nr_t* carrier,
|
||||
const srslte_sch_cfg_t* sch_cfg,
|
||||
const srslte_sch_tb_t* tb,
|
||||
srslte_sch_nr_tb_info_t* cfg);
|
||||
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_tb_t* tb,
|
||||
srslte_sch_nr_tb_info_t* cfg);
|
||||
|
||||
/**
|
||||
* @brief Initialises an SCH object as transmitter
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#define SRSLTE_UCI_CFG_NR_H
|
||||
|
||||
#include "csi_cfg.h"
|
||||
#include "srslte/phy/common/phy_common.h"
|
||||
#include "srslte/phy/common/phy_common_nr.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -35,6 +35,37 @@
|
|||
*/
|
||||
#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
|
||||
*/
|
||||
|
@ -44,18 +75,10 @@ typedef struct SRSLTE_API {
|
|||
uint32_t o_sr; ///< Number of SR bits
|
||||
srslte_csi_report_cfg_t csi[SRSLTE_CSI_MAX_NOF_REPORT]; ///< CSI report configuration
|
||||
uint32_t nof_csi; ///< Number of CSI reports
|
||||
|
||||
/// PUSCH only parameters
|
||||
bool without_ul_sch; ///< Set to true if no UL-SCH data is scheduled
|
||||
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
|
||||
union {
|
||||
srslte_uci_nr_pucch_cfg_t pucch; ///< Configuration for transmission in PUCCH
|
||||
srslte_uci_nr_pusch_cfg_t pusch; ///< Configuration for transmission in PUSCH
|
||||
};
|
||||
} 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);
|
||||
|
||||
/**
|
||||
* @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] cfg PUSCH transmission configuration
|
||||
* @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
|
||||
* @param[in,out] q NR-UCI object
|
||||
* @param[in] cfg PUSCH transmission configuration
|
||||
* @param[in] cfg UCI configuration
|
||||
* @param[in] value UCI value
|
||||
* @param[out] o_ack Encoded ack bits
|
||||
* @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,
|
||||
const srslte_sch_cfg_nr_t* cfg,
|
||||
const srslte_uci_cfg_nr_t* cfg,
|
||||
const srslte_uci_value_nr_t* value,
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
const srslte_csi_report_value_t* report_value,
|
||||
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:
|
||||
*
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | 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 -->
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
||||
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
|
||||
|
|
|
@ -33,6 +33,24 @@ int pusch_nr_init_common(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* arg
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -151,6 +169,32 @@ void srslte_pusch_nr_free(srslte_pusch_nr_t* q)
|
|||
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++) {
|
||||
if (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) {
|
||||
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;
|
||||
}
|
||||
|
||||
// int pusch_nr_mux_uci(srslte_pusch_nr_t* q) {
|
||||
// uint8_t *g_ul_sch; // coded bits for UL-SCH
|
||||
// uint8_t *g_ack; // coded bits for HARQ-ACK
|
||||
// uint8_t *g_csi_p1; // coded bits for CSI part 1
|
||||
// uint8_t *g_csi_p2; // coded bits for CSI part 2
|
||||
//
|
||||
//}
|
||||
static inline int
|
||||
pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, srslte_uci_cfg_nr_t* uci_cfg)
|
||||
{
|
||||
// Initially, copy all fields
|
||||
*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,
|
||||
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
|
||||
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");
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
@ -500,12 +859,26 @@ int srslte_pusch_nr_encode(srslte_pusch_nr_t* q,
|
|||
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
|
||||
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) {
|
||||
ERROR("Error encoding HARQ-ACK bits");
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
// 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++) {
|
||||
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
|
||||
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) {
|
||||
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
|
||||
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");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
@ -631,6 +1009,25 @@ int srslte_pusch_nr_decode(srslte_pusch_nr_t* q,
|
|||
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;
|
||||
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
|
||||
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, 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};
|
||||
|
||||
|
@ -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) {
|
||||
// Row 1
|
||||
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) {
|
||||
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
|
||||
} 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) {
|
||||
// Row 2
|
||||
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) {
|
||||
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) {
|
||||
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
|
||||
} 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 {
|
||||
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
|
||||
// - up to 2 HARQ-ACK
|
||||
// - 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) {
|
||||
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) {
|
||||
ERROR("SR resource ID (%d) exceeds the maximum ID (%d)", sr_resource_id, SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES);
|
||||
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
|
||||
// - 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) {
|
||||
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
|
||||
|
@ -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
|
||||
// transmission of HARQ-ACK information on PUCCH in an initial UL BWP of N BWP PRBs.
|
||||
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_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)
|
||||
|
|
|
@ -65,10 +65,10 @@ uint32_t sch_nr_n_prb_lbrm(uint32_t nof_prb)
|
|||
return 273;
|
||||
}
|
||||
|
||||
int srslte_sch_nr_fill_cfg(const srslte_carrier_nr_t* carrier,
|
||||
const srslte_sch_cfg_t* sch_cfg,
|
||||
const srslte_sch_tb_t* tb,
|
||||
srslte_sch_nr_tb_info_t* cfg)
|
||||
int srslte_sch_nr_fill_tb_info(const srslte_carrier_nr_t* carrier,
|
||||
const srslte_sch_cfg_t* sch_cfg,
|
||||
const srslte_sch_tb_t* tb,
|
||||
srslte_sch_nr_tb_info_t* cfg)
|
||||
{
|
||||
if (!sch_cfg || !tb || !cfg) {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -514,7 +514,7 @@ int sch_nr_decode(srslte_sch_nr_t* q,
|
|||
int8_t* input_ptr = e_bits;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,13 +27,12 @@ static srslte_carrier_nr_t carrier = {
|
|||
1 // max_mimo_layers
|
||||
};
|
||||
|
||||
static uint32_t n_prb = 0; // Set to 0 for steering
|
||||
static uint32_t mcs = 30; // Set to 30 for steering
|
||||
static srslte_sch_cfg_nr_t pusch_cfg = {};
|
||||
static srslte_sch_grant_nr_t pusch_grant = {};
|
||||
static uint16_t rnti = 0x1234;
|
||||
static uint32_t nof_ack_bits = 0;
|
||||
static uint32_t nof_csi_bits = 0;
|
||||
static uint32_t n_prb = 0; // Set to 0 for steering
|
||||
static uint32_t mcs = 30; // Set to 30 for steering
|
||||
static srslte_sch_cfg_nr_t pusch_cfg = {};
|
||||
static uint16_t rnti = 0x1234;
|
||||
static uint32_t nof_ack_bits = 0;
|
||||
static uint32_t nof_csi_bits = 0;
|
||||
|
||||
void usage(char* prog)
|
||||
{
|
||||
|
@ -159,20 +158,20 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
// 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");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// 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");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
pusch_grant.nof_layers = carrier.max_mimo_layers;
|
||||
pusch_grant.dci_format = srslte_dci_format_nr_1_0;
|
||||
pusch_grant.rnti = rnti;
|
||||
pusch_cfg.grant.nof_layers = carrier.max_mimo_layers;
|
||||
pusch_cfg.grant.dci_format = srslte_dci_format_nr_1_0;
|
||||
pusch_cfg.grant.rnti = rnti;
|
||||
|
||||
uint32_t n_prb_start = 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
ERROR("Initiating chest");
|
||||
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 (mcs = mcs_start; mcs < mcs_end; mcs++) {
|
||||
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;
|
||||
if (srslte_ra_nr_fill_tb(&pusch_cfg, &pusch_grant, mcs, &pusch_grant.tb[0]) < SRSLTE_SUCCESS) {
|
||||
pusch_cfg.grant.dci_format = srslte_dci_format_nr_0_0;
|
||||
if (srslte_ra_nr_fill_tb(&pusch_cfg, &pusch_cfg.grant, mcs, &pusch_cfg.grant.tb[0]) < SRSLTE_SUCCESS) {
|
||||
ERROR("Error filing tb");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
@ -212,10 +215,10 @@ int main(int argc, char** argv)
|
|||
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);
|
||||
}
|
||||
pusch_grant.tb[tb].softbuffer.tx = &softbuffer_tx;
|
||||
pusch_cfg.grant.tb[tb].softbuffer.tx = &softbuffer_tx;
|
||||
}
|
||||
|
||||
// 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");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
|
||||
pusch_grant.tb[tb].softbuffer.rx = &softbuffer_rx;
|
||||
srslte_softbuffer_rx_reset(pusch_grant.tb[tb].softbuffer.rx);
|
||||
pusch_cfg.grant.tb[tb].softbuffer.rx = &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.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");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
@ -264,18 +268,18 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
float mse = 0.0f;
|
||||
uint32_t nof_re = srslte_ra_dl_nr_slot_nof_re(&pusch_cfg, &pusch_grant);
|
||||
for (uint32_t i = 0; i < pusch_grant.nof_layers; i++) {
|
||||
uint32_t nof_re = srslte_ra_dl_nr_slot_nof_re(&pusch_cfg, &pusch_cfg.grant);
|
||||
for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) {
|
||||
for (uint32_t j = 0; j < nof_re; j++) {
|
||||
mse += cabsf(pusch_tx.d[i][j] - pusch_rx.d[i][j]);
|
||||
}
|
||||
}
|
||||
if (nof_re * pusch_grant.nof_layers > 0) {
|
||||
mse = mse / (nof_re * pusch_grant.nof_layers);
|
||||
if (nof_re * pusch_cfg.grant.nof_layers > 0) {
|
||||
mse = mse / (nof_re * pusch_cfg.grant.nof_layers);
|
||||
}
|
||||
if (mse > 0.001) {
|
||||
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);
|
||||
srslte_vec_fprint_c(stdout, pusch_tx.d[i], nof_re);
|
||||
printf("d_rx[%d]=", i);
|
||||
|
@ -285,20 +289,20 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (memcmp(data_tx[0].payload, data_rx[0].payload, pusch_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);
|
||||
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_cfg.grant.tb[0].tbs);
|
||||
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: ");
|
||||
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;
|
||||
}
|
||||
|
||||
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/ch_estimation/dmrs_sch.h"
|
||||
#include "srslte/phy/fec/block/block.h"
|
||||
#include "srslte/phy/fec/polar/polar_chanalloc.h"
|
||||
#include "srslte/phy/phch/csi.h"
|
||||
#include "srslte/phy/phch/sch_nr.h"
|
||||
#include "srslte/phy/phch/uci_cfg.h"
|
||||
#include "srslte/phy/utils/bit.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;
|
||||
}
|
||||
|
||||
static int
|
||||
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)
|
||||
static int uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
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:
|
||||
while (i < E) {
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
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)
|
||||
static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E)
|
||||
{
|
||||
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 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;
|
||||
|
||||
switch (modulation) {
|
||||
switch (cfg->pusch.modulation) {
|
||||
case SRSLTE_MOD_BPSK:
|
||||
case SRSLTE_MOD_QPSK:
|
||||
while (i < E) {
|
||||
|
@ -643,21 +639,16 @@ static int uci_nr_decode_11_1706_bit(srslte_uci_nr_t* q,
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
static int uci_nr_encode(srslte_uci_nr_t* q,
|
||||
const srslte_uci_cfg_nr_t* uci_cfg,
|
||||
srslte_mod_t mod,
|
||||
uint32_t A,
|
||||
uint8_t* o,
|
||||
uint32_t E_uci)
|
||||
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)
|
||||
{
|
||||
// 5.3.3.1 Encoding of 1-bit information
|
||||
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
|
||||
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
|
||||
|
@ -781,7 +772,7 @@ int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q,
|
|||
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,
|
||||
|
@ -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;
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
srslte_sch_nr_tb_info_t tb_info = {};
|
||||
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(A); // Number of CRC bits
|
||||
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_l0_sum = 0;
|
||||
for (uint32_t l = sch_cfg->grant.S; l < sch_cfg->grant.S + sch_cfg->grant.L; l++) {
|
||||
uint32_t M_ptrs_sc = 0; // Not implemented yet
|
||||
uint32_t M_pusch_sc = sch_cfg->grant.nof_prb * SRSLTE_NRE;
|
||||
uint32_t M_uci_sc = M_pusch_sc - M_ptrs_sc;
|
||||
|
||||
// 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
|
||||
M_uci_sum += M_uci_sc;
|
||||
|
||||
// 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) {
|
||||
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) * beta_pusch_offset * M_uci_sum) / (float)K_sum), 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 A = cfg->uci.o_ack;
|
||||
|
||||
// Check inputs
|
||||
if (q == NULL || cfg == NULL) {
|
||||
if (cfg == NULL) {
|
||||
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) {
|
||||
A = 2;
|
||||
uint32_t L_ack = srslte_uci_nr_crc_len(O_ack); // Number of CRC bits
|
||||
uint32_t Qm = srslte_mod_bits_x_symbol(cfg->modulation); // modulation order of the PUSCH
|
||||
|
||||
uint32_t M_uci_sum = 0;
|
||||
uint32_t M_uci_l0_sum = 0;
|
||||
for (uint32_t l = 0; l < SRSLTE_NSYMB_PER_SLOT_NR; l++) {
|
||||
M_uci_sum += cfg->M_uci_sc[l];
|
||||
if (l >= cfg->l0) {
|
||||
M_uci_l0_sum += cfg->M_uci_sc[l];
|
||||
}
|
||||
}
|
||||
|
||||
int Q_ack_prime = uci_nr_Q_ack_prime(q, cfg, A);
|
||||
if (!isnormal(cfg->R)) {
|
||||
ERROR("Invalid Rate (%f)", cfg->R);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (cfg->K_sum == 0) {
|
||||
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) * cfg->beta_harq_ack_offset * M_uci_sum) / cfg->K_sum),
|
||||
cfg->alpha * M_uci_l0_sum);
|
||||
}
|
||||
|
||||
int srslte_uci_nr_pusch_ack_nof_bits(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack)
|
||||
{
|
||||
// Check inputs
|
||||
if (cfg == NULL) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
int Q_ack_prime = srslte_uci_nr_pusch_ack_nof_re(cfg, O_ack);
|
||||
if (Q_ack_prime < SRSLTE_SUCCESS) {
|
||||
ERROR("Error calculating number of RE");
|
||||
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,
|
||||
const srslte_sch_cfg_nr_t* cfg,
|
||||
const srslte_uci_cfg_nr_t* cfg,
|
||||
const srslte_uci_value_nr_t* value,
|
||||
uint8_t* o)
|
||||
{
|
||||
int A = cfg->uci.o_ack;
|
||||
int A = cfg->o_ack;
|
||||
|
||||
// Check inputs
|
||||
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.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;
|
||||
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;
|
||||
} 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
|
||||
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) {
|
||||
ERROR("Error calculating number of encoded bits");
|
||||
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 {
|
||||
if (ack->present) {
|
||||
// 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.rnti = ack_info->cc[c].m[m].resource.rnti;
|
||||
uci_data->cfg.pucch.resource_id = ack_info->cc[c].m[m].resource.pucch_resource_id;
|
||||
uci_data->cfg.pucch.rnti = ack_info->cc[c].m[m].resource.rnti;
|
||||
|
||||
if (V_DL_CDAI <= V_temp) {
|
||||
j = j + 1;
|
||||
|
|
|
@ -73,9 +73,9 @@ public:
|
|||
carrier.max_mimo_layers = 1;
|
||||
|
||||
// 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[1].K_csi_rs = 4;
|
||||
csi_measurements[1].K_csi_rs = 4;
|
||||
csi_measurements[0].nof_ports = 1;
|
||||
}
|
||||
|
||||
|
@ -294,10 +294,10 @@ public:
|
|||
}
|
||||
|
||||
// Configure SR fields in UCI data
|
||||
uci_data.cfg.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.sr_positive_present = sr_count_positive > 0;
|
||||
uci_data.value.sr = sr_count_positive;
|
||||
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.pucch.sr_positive_present = sr_count_positive > 0;
|
||||
uci_data.value.sr = sr_count_positive;
|
||||
}
|
||||
|
||||
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.rnti = stack->get_ul_sched_rnti_nr(tti).id;
|
||||
uci_data.cfg.pucch.rnti = stack->get_ul_sched_rnti_nr(tti).id;
|
||||
}
|
||||
};
|
||||
} // namespace nr
|
||||
|
|
Loading…
Reference in New Issue