Added CSI part1 and 1/2 bit HARQ-ACK multiplexing on PUSCH

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent dc2542901a
commit 97435b085e

@ -35,7 +35,7 @@ SRSLTE_API int srslte_csi_generate_reports(const srslte_csi_hl_cfg_t* cfg,
* @param nof_reports Number of CSI reports in the list * @param nof_reports Number of CSI reports in the list
* @return The number of bits if the provided list is valid, SRSLTE_ERROR code otherwise * @return The number of bits if the provided list is valid, SRSLTE_ERROR code otherwise
*/ */
SRSLTE_API int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports); SRSLTE_API int srslte_csi_part1_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 * @brief Checks if the report list contains part 2 CSI report
@ -46,7 +46,7 @@ SRSLTE_API int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, u
SRSLTE_API bool srslte_csi_has_part2(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports); 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 or PUSCH transmission
* @param report_list Provides the CSI report list * @param report_list Provides the CSI report list
* @param nof_reports Number of CSI reports in the list * @param nof_reports Number of CSI reports in the list
* @param o_csi1 CSI bits * @param o_csi1 CSI bits
@ -59,6 +59,21 @@ SRSLTE_API int srslte_csi_part1_pack(const srslte_csi_report_cfg_t* report_cfg
uint8_t* o_csi1, uint8_t* o_csi1,
uint32_t max_o_csi1); uint32_t max_o_csi1);
/**
*@brief Unpacks CSI part 1 bits for PUCCH or PUSCH transmission
* @param report_list Provides the CSI report list
* @param nof_reports Number of CSI reports in the list
* @param o_csi1 CSI bits
* @param max_o_csi1 Maximum number of CSI bits
* @param report_value
* @return SRSLTE_SUCCESS if provided data is valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_csi_part1_unpack(const srslte_csi_report_cfg_t* report_cfg,
uint32_t nof_reports,
uint8_t* o_csi1,
uint32_t max_o_csi1,
srslte_csi_report_value_t* report_value);
/** /**
* @brief Converts to string a given list of CSI reports * @brief Converts to string a given list of CSI reports
* @param report_cfg Report configuration list * @param report_cfg Report configuration list

@ -33,7 +33,7 @@
* @brief Maximum number of Channel State Information part 1 (CSI1) bits that can be carried in Uplink Control * @brief Maximum number of Channel State Information part 1 (CSI1) bits that can be carried in Uplink Control
* Information (UCI) message * Information (UCI) message
*/ */
#define SRSLTE_UCI_NR_MAX_CSI1_BITS 10 #define SRSLTE_UCI_NR_MAX_CSI1_BITS 360
/** /**
* @brief Uplink Control Information bits configuration for PUCCH transmission * @brief Uplink Control Information bits configuration for PUCCH transmission
@ -61,8 +61,9 @@ typedef struct {
float R; ///< Code rate of the PUSCH float R; ///< Code rate of the PUSCH
float alpha; ///< Higher layer parameter scaling float alpha; ///< Higher layer parameter scaling
float beta_harq_ack_offset; float beta_harq_ack_offset;
float beta_csi_part1_offset; float beta_csi1_offset;
uint32_t nof_re; uint32_t nof_re;
bool csi_part2_present;
} srslte_uci_nr_pusch_cfg_t; } srslte_uci_nr_pusch_cfg_t;
/** /**

@ -31,6 +31,7 @@
typedef struct { typedef struct {
bool disable_simd; ///< Disable Polar code SIMD bool disable_simd; ///< Disable Polar code SIMD
float block_code_threshold; ///< Set normalised block code threshold (receiver only) float block_code_threshold; ///< Set normalised block code threshold (receiver only)
float one_bit_threshold; ///< Decode threshold for 1 bit (receiver only)
} srslte_uci_nr_args_t; } srslte_uci_nr_args_t;
typedef struct { typedef struct {
@ -42,11 +43,12 @@ typedef struct {
srslte_crc_t crc6; srslte_crc_t crc6;
srslte_crc_t crc11; srslte_crc_t crc11;
srslte_polar_code_t code; srslte_polar_code_t code;
uint8_t* bit_sequence; ///< UCI bit sequence uint8_t* bit_sequence; ///< UCI bit sequence
uint8_t* c; ///< UCI code-block prior encoding or after decoding uint8_t* c; ///< UCI code-block prior encoding or after decoding
uint8_t* allocated; ///< Polar code intermediate uint8_t* allocated; ///< Polar code intermediate
uint8_t* d; ///< Polar code encoded intermediate uint8_t* d; ///< Polar code encoded intermediate
float block_code_threshold; float block_code_threshold; ///< Decode threshold for block code (3-11 bits)
float one_bit_threshold; ///< Decode threshold for 1 bit
} srslte_uci_nr_t; } srslte_uci_nr_t;
/** /**
@ -125,18 +127,7 @@ 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 total number of resource elements for HARQ-ACK multiplexing in PUSCH * @brief Calculates total number of encoded bits 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 * @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
*/ */
@ -168,6 +159,39 @@ SRSLTE_API int srslte_uci_nr_decode_pusch_ack(srslte_uci_nr_t* q,
int8_t* llr, int8_t* llr,
srslte_uci_value_nr_t* value); srslte_uci_value_nr_t* value);
/**
* @brief Calculates total number of encoded bits for CSI part 1 multiplexing in PUSCH
* @param[in] cfg UCI configuration
* @return The number of encoded bits if valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_uci_nr_pusch_csi1_nof_bits(const srslte_uci_cfg_nr_t* cfg);
/**
* @brief Encodes CSI part 1 bits for PUSCH transmission
* @param[in,out] q NR-UCI object
* @param[in] cfg UCI configuration
* @param[in] value UCI value
* @param[out] o_ack Encoded CSI part 1 bits
* @return The number of encoded bits if successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_uci_nr_encode_pusch_csi1(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* cfg,
const srslte_uci_value_nr_t* value,
uint8_t* o);
/**
* @brief Decodes CSI part 1 bits for PUSCH transmission
* @param[in,out] q NR-UCI object
* @param[in] cfg UCI configuration
* @param[in] llr Provides softbits LLR
* @param[out] value UCI value
* @return SRSLTE_SUCCESS if the decoding process was successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_uci_nr_decode_pusch_csi1(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* cfg,
int8_t* llr,
srslte_uci_value_nr_t* value);
/** /**
* @brief Calculates the total number of UCI bits * @brief Calculates the total number of UCI bits
* @param uci_cfg UCI configuration * @param uci_cfg UCI configuration

@ -123,7 +123,7 @@ int get_code_params(srslte_polar_code_t* c, const uint16_t K, const uint16_t E,
} }
if (K + nPC >= E) { if (K + nPC >= E) {
ERROR(" Rate-matched codeword length (E) not supported, choose E > %d", K + nPC); ERROR(" Rate-matched codeword length (E=%d) not supported, choose E > %d", E, K + nPC);
return -1; return -1;
} }

@ -12,6 +12,7 @@
#include "srslte/phy/phch/csi.h" #include "srslte/phy/phch/csi.h"
#include "srslte/phy/utils/bit.h" #include "srslte/phy/utils/bit.h"
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
#include <math.h> #include <math.h>
#define CSI_WIDEBAND_CSI_NOF_BITS 4 #define CSI_WIDEBAND_CSI_NOF_BITS 4
@ -82,9 +83,9 @@ static uint32_t csi_wideband_cri_ri_pmi_cqi_nof_bits(const srslte_csi_report_cfg
return 0; return 0;
} }
static int csi_wideband_cri_ri_pmi_cqi_pack(const srslte_csi_report_cfg_t* cfg, static uint32_t csi_wideband_cri_ri_pmi_cqi_pack(const srslte_csi_report_cfg_t* cfg,
const srslte_csi_report_value_t* value, const srslte_csi_report_value_t* value,
uint8_t* o_csi1) uint8_t* o_csi1)
{ {
// Compute number of bits for CRI // Compute number of bits for CRI
uint32_t nof_bits_cri = 0; uint32_t nof_bits_cri = 0;
@ -101,6 +102,46 @@ static int csi_wideband_cri_ri_pmi_cqi_pack(const srslte_csi_report_cfg_t* cfg
return nof_bits_cri + CSI_WIDEBAND_CSI_NOF_BITS; return nof_bits_cri + CSI_WIDEBAND_CSI_NOF_BITS;
} }
static uint32_t csi_wideband_cri_ri_pmi_cqi_unpack(const srslte_csi_report_cfg_t* cfg,
uint8_t* o_csi1,
srslte_csi_report_value_t* value)
{
// Compute number of bits for CRI
uint32_t nof_bits_cri = 0;
if (cfg->K_csi_rs > 0) {
nof_bits_cri = (uint32_t)ceilf(log2f((float)cfg->K_csi_rs));
}
// Write wideband CQI
value->wideband_cri_ri_pmi_cqi.cqi = srslte_bit_pack(&o_csi1, CSI_WIDEBAND_CSI_NOF_BITS);
// Compute number of bits for CRI and write
value->cri = srslte_bit_pack(&o_csi1, nof_bits_cri);
return nof_bits_cri + CSI_WIDEBAND_CSI_NOF_BITS;
}
static uint32_t csi_none_nof_bits(const srslte_csi_report_cfg_t* cfg)
{
return cfg->K_csi_rs;
}
static uint32_t
csi_none_pack(const srslte_csi_report_cfg_t* cfg, const srslte_csi_report_value_t* value, uint8_t* o_csi1)
{
srslte_vec_u8_copy(o_csi1, (uint8_t*)value->none, cfg->K_csi_rs);
return cfg->K_csi_rs;
}
static uint32_t
csi_none_unpack(const srslte_csi_report_cfg_t* cfg, const uint8_t* o_csi1, srslte_csi_report_value_t* value)
{
srslte_vec_u8_copy((uint8_t*)value->none, o_csi1, cfg->K_csi_rs);
return cfg->K_csi_rs;
}
int srslte_csi_generate_reports(const srslte_csi_hl_cfg_t* cfg, int srslte_csi_generate_reports(const srslte_csi_hl_cfg_t* cfg,
uint32_t slot_idx, uint32_t slot_idx,
const srslte_csi_measurements_t measurements[SRSLTE_CSI_MAX_NOF_RESOURCES], const srslte_csi_measurements_t measurements[SRSLTE_CSI_MAX_NOF_RESOURCES],
@ -152,7 +193,7 @@ int srslte_csi_generate_reports(const srslte_csi_hl_cfg_t* cfg,
return (int)count; return (int)count;
} }
int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports) int srslte_csi_part1_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports)
{ {
uint32_t count = 0; uint32_t count = 0;
@ -166,6 +207,8 @@ int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof
const srslte_csi_report_cfg_t* report = &report_list[i]; const srslte_csi_report_cfg_t* report = &report_list[i];
if (report->quantity && report->quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) { if (report->quantity && report->quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
count += csi_wideband_cri_ri_pmi_cqi_nof_bits(report); count += csi_wideband_cri_ri_pmi_cqi_nof_bits(report);
} else if (report->quantity == SRSLTE_CSI_REPORT_QUANTITY_NONE) {
count += csi_none_nof_bits(report);
} }
} }
@ -198,7 +241,7 @@ int srslte_csi_part1_pack(const srslte_csi_report_cfg_t* report_cfg,
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
int n = srslte_csi_nof_bits(report_cfg, nof_reports); int n = srslte_csi_part1_nof_bits(report_cfg, nof_reports);
if (n > (int)max_o_csi1) { if (n > (int)max_o_csi1) {
ERROR("The maximum number of CSI bits (%d) is not enough to accommodate %d bits", max_o_csi1, n); ERROR("The maximum number of CSI bits (%d) is not enough to accommodate %d bits", max_o_csi1, n);
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -208,6 +251,42 @@ int srslte_csi_part1_pack(const srslte_csi_report_cfg_t* report_cfg,
if (report_cfg[i].freq_cfg == SRSLTE_CSI_REPORT_FREQ_WIDEBAND && if (report_cfg[i].freq_cfg == SRSLTE_CSI_REPORT_FREQ_WIDEBAND &&
report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) { report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
count += csi_wideband_cri_ri_pmi_cqi_pack(&report_cfg[i], &report_value[i], &o_csi1[count]); count += csi_wideband_cri_ri_pmi_cqi_pack(&report_cfg[i], &report_value[i], &o_csi1[count]);
} else if (report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_NONE) {
count += csi_none_pack(&report_cfg[i], &report_value[i], &o_csi1[count]);
} else {
ERROR("CSI frequency (%d) and quantity (%d) combination is not implemented",
report_cfg[i].freq_cfg,
report_cfg[i].quantity);
}
}
return (int)count;
}
int srslte_csi_part1_unpack(const srslte_csi_report_cfg_t* report_cfg,
uint32_t nof_reports,
uint8_t* o_csi1,
uint32_t max_o_csi1,
srslte_csi_report_value_t* report_value)
{
uint32_t count = 0;
if (report_cfg == NULL || report_value == NULL || o_csi1 == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
int n = srslte_csi_part1_nof_bits(report_cfg, nof_reports);
if (n > (int)max_o_csi1) {
ERROR("The maximum number of CSI bits (%d) is not enough to accommodate %d bits", max_o_csi1, n);
return SRSLTE_ERROR;
}
for (uint32_t i = 0; i < nof_reports && count < max_o_csi1; i++) {
if (report_cfg[i].freq_cfg == SRSLTE_CSI_REPORT_FREQ_WIDEBAND &&
report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
count += csi_wideband_cri_ri_pmi_cqi_unpack(&report_cfg[i], &o_csi1[count], &report_value[i]);
} else if (report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_NONE) {
count += csi_none_unpack(&report_cfg[i], &o_csi1[count], &report_value[i]);
} else { } else {
ERROR("CSI frequency (%d) and quantity (%d) combination is not implemented", ERROR("CSI frequency (%d) and quantity (%d) combination is not implemented",
report_cfg[i].freq_cfg, report_cfg[i].freq_cfg,
@ -229,6 +308,10 @@ uint32_t srslte_csi_str(const srslte_csi_report_cfg_t* report_cfg,
if (report_cfg[i].freq_cfg == SRSLTE_CSI_REPORT_FREQ_WIDEBAND && if (report_cfg[i].freq_cfg == SRSLTE_CSI_REPORT_FREQ_WIDEBAND &&
report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) { report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
len = srslte_print_check(str, str_len, len, ", cqi=%d", report_value[i].wideband_cri_ri_pmi_cqi.cqi); len = srslte_print_check(str, str_len, len, ", cqi=%d", report_value[i].wideband_cri_ri_pmi_cqi.cqi);
} else if (report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_NONE) {
char tmp[20] = {};
srslte_vec_sprint_bin(tmp, sizeof(tmp), report_value[i].none, report_cfg->K_csi_rs);
len = srslte_print_check(str, str_len, len, ", csi=%s", tmp);
} }
} }
return len; return len;

@ -14,7 +14,9 @@
#include "srslte/phy/mimo/layermap.h" #include "srslte/phy/mimo/layermap.h"
#include "srslte/phy/mimo/precoding.h" #include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/modem/demod_soft.h" #include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/phch/csi.h"
#include "srslte/phy/phch/ra_nr.h" #include "srslte/phy/phch/ra_nr.h"
#include "srslte/phy/phch/uci_cfg.h"
int pusch_nr_init_common(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args) int pusch_nr_init_common(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args)
{ {
@ -33,19 +35,19 @@ 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_ulsch = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
q->g_ack = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR); q->g_ack = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
q->g_csi1 = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR); q->g_csi1 = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
q->g_csi2 = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR); q->g_csi2 = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
if (q->g_ack == NULL || q->g_csi1 == NULL || q->g_csi2 == NULL || q->g_ulsch == NULL) { if (q->g_ack == NULL || q->g_csi1 == NULL || q->g_csi2 == NULL || q->g_ulsch == NULL) {
ERROR("Malloc"); ERROR("Malloc");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->pos_ulsch = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR); q->pos_ulsch = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
q->pos_ack = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR); q->pos_ack = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
q->pos_csi1 = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR); q->pos_csi1 = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
q->pos_csi2 = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR); q->pos_csi2 = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
if (q->pos_ack == NULL || q->pos_csi1 == NULL || q->pos_csi2 == NULL || q->pos_ulsch == NULL) { if (q->pos_ack == NULL || q->pos_csi1 == NULL || q->pos_csi2 == NULL || q->pos_ulsch == NULL) {
ERROR("Malloc"); ERROR("Malloc");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -566,13 +568,13 @@ static inline int pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_c
} }
// Set other PUSCH parameters // Set other PUSCH parameters
q->uci_cfg.pusch.modulation = cfg->grant.tb[0].mod; q->uci_cfg.pusch.modulation = cfg->grant.tb[0].mod;
q->uci_cfg.pusch.nof_layers = cfg->grant.nof_layers; q->uci_cfg.pusch.nof_layers = cfg->grant.nof_layers;
q->uci_cfg.pusch.R = (float)cfg->grant.tb[0].R; q->uci_cfg.pusch.R = (float)cfg->grant.tb[0].R;
q->uci_cfg.pusch.alpha = cfg->scaling; q->uci_cfg.pusch.alpha = cfg->scaling;
q->uci_cfg.pusch.beta_harq_ack_offset = cfg->beta_harq_ack_offset; q->uci_cfg.pusch.beta_harq_ack_offset = cfg->beta_harq_ack_offset;
q->uci_cfg.pusch.beta_csi_part1_offset = cfg->beta_csi_part1_offset; q->uci_cfg.pusch.beta_csi1_offset = cfg->beta_csi_part1_offset;
q->uci_cfg.pusch.nof_re = cfg->grant.tb[0].nof_re; q->uci_cfg.pusch.nof_re = cfg->grant.tb[0].nof_re;
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -685,27 +687,33 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
uint32_t ulsch_m_re_count = M_uci_sc; 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]; i++) { for (uint32_t i = 0, csi1_i = 0, csi2_i = 0; i < cfg->pusch.M_pusch_sc[l]; i++) {
// Check if RE is reserved for ACK
bool reserved = false;
if (ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack_rvd) {
reserved = true;
}
if (ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack) { if (ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack) {
for (uint32_t j = 0; j < Nl * Qm; j++) { for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_ack[m_ack_count++] = m_all_count++; pos_ack[m_ack_count++] = m_all_count + j;
} }
ack_m_re_count--; ack_m_re_count--;
} else if (csi1_m_re_count != 0 && csi1_i % csi1_d == 0 && m_csi1_count < G_csi1) { } else if (!reserved && csi1_m_re_count != 0 && csi1_i % csi1_d == 0 && m_csi1_count < G_csi1) {
for (uint32_t j = 0; j < Nl * Qm; j++) { for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_csi1[m_csi1_count++] = m_all_count++; pos_csi1[m_csi1_count++] = m_all_count + j;
} }
csi1_m_re_count--; csi1_m_re_count--;
csi1_i++; csi1_i++;
} else if (csi2_m_re_count != 0 && csi2_i % csi2_d == 0 && m_csi2_count < G_csi2) { } 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++) { for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_csi2[m_csi2_count++] = m_all_count++; pos_csi2[m_csi2_count++] = m_all_count + j;
} }
csi2_m_re_count--; csi2_m_re_count--;
csi1_i++; csi1_i++;
csi2_i++; csi2_i++;
} else { } else {
for (uint32_t j = 0; j < Nl * Qm; j++) { for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_ulsch[m_ulsch_count++] = m_all_count++; pos_ulsch[m_ulsch_count++] = m_all_count + j;
} }
ulsch_m_re_count--; ulsch_m_re_count--;
csi1_i++; csi1_i++;
@ -713,12 +721,15 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
} }
// Set reserved bits // Set reserved bits
if (ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack_rvd) { if (reserved) {
for (uint32_t j = 0; j < Nl * Qm; j++) { for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_ack[m_ack_count++] = m_all_count++; pos_ack[m_ack_count++] = m_all_count + j;
} }
ack_m_re_count--; ack_m_re_count--;
} }
// Increment all bit counter
m_all_count += Nl * Qm;
} }
// Assert that all RE have been allocated // Assert that all RE have been allocated
@ -806,8 +817,18 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
ERROR("Error encoding HARQ-ACK bits"); ERROR("Error encoding HARQ-ACK bits");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->G_ack = E_uci_ack; q->G_ack = (uint32_t)E_uci_ack;
q->G_csi1 = 0;
// Encode CSI part 1
int E_uci_csi1 = srslte_uci_nr_encode_pusch_csi1(&q->uci, &q->uci_cfg, uci, q->g_csi1);
if (E_uci_csi1 < SRSLTE_SUCCESS) {
ERROR("Error encoding HARQ-ACK bits");
return SRSLTE_ERROR;
}
q->G_csi1 = (uint32_t)E_uci_csi1;
// Encode CSI part 2
// ... Not implemented
q->G_csi2 = 0; q->G_csi2 = 0;
// Generate PUSCH UCI/UL-SCH multiplexing // Generate PUSCH UCI/UL-SCH multiplexing
@ -851,6 +872,20 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
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);
// Special Scrambling condition
if (q->uci_cfg.o_ack <= 2) {
for (uint32_t i = 0; i < q->G_ack; i++) {
uint32_t idx = q->pos_ack[i];
if (q->g_ack[i] == (uint8_t)UCI_BIT_REPETITION) {
if (idx != 0) {
q->b[tb->cw_idx][idx] = q->b[tb->cw_idx][idx - 1];
}
} else if (q->g_ack[i] == (uint8_t)UCI_BIT_PLACEHOLDER) {
q->b[tb->cw_idx][idx] = 1;
}
}
}
// 7.3.1.2 Modulation // 7.3.1.2 Modulation
srslte_mod_modulate(&q->modem_tables[tb->mod], q->b[tb->cw_idx], q->d[tb->cw_idx], tb->nof_bits); srslte_mod_modulate(&q->modem_tables[tb->mod], q->b[tb->cw_idx], q->d[tb->cw_idx], tb->nof_bits);
@ -964,14 +999,24 @@ static inline int pusch_nr_decode_codeword(srslte_pusch_nr_t* q,
srslte_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re); srslte_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re);
} }
// Calculate UCI bits // Calculate HARQ-ACK bits
int n = srslte_uci_nr_pusch_ack_nof_bits(&q->uci_cfg.pusch, q->uci_cfg.o_ack); int n = srslte_uci_nr_pusch_ack_nof_bits(&q->uci_cfg.pusch, q->uci_cfg.o_ack);
if (n < SRSLTE_SUCCESS) { if (n < SRSLTE_SUCCESS) {
ERROR("Calculating G_ack"); ERROR("Calculating G_ack");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->G_ack = (uint32_t)n; q->G_ack = (uint32_t)n;
q->G_csi1 = 0;
// Calculate CSI part 1 bits
n = srslte_uci_nr_pusch_csi1_nof_bits(&q->uci_cfg);
if (n < SRSLTE_SUCCESS) {
ERROR("Calculating G_csi1");
return SRSLTE_ERROR;
}
q->G_csi1 = (uint32_t)n;
// Calculate CSI part 2 bits
// ... Not implemented
q->G_csi2 = 0; q->G_csi2 = 0;
// Generate PUSCH UCI/UL-SCH multiplexing // Generate PUSCH UCI/UL-SCH multiplexing
@ -1042,6 +1087,17 @@ static inline int pusch_nr_decode_codeword(srslte_pusch_nr_t* q,
} }
} }
// Decode CSI part 1
if (q->G_csi1) {
if (srslte_uci_nr_decode_pusch_csi1(&q->uci, &q->uci_cfg, g_csi1, &res->uci)) {
ERROR("Error in UCI decoding");
return SRSLTE_ERROR;
}
}
// Decode CSI part 2
// ... Not implemented
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }

@ -373,7 +373,7 @@ int srslte_ra_ul_nr_pucch_format_2_3_min_prb(const srslte_pucch_nr_resource_t* r
} }
// Compute total number of UCI bits // Compute total number of UCI bits
uint32_t O_total = uci_cfg->o_ack + uci_cfg->o_sr + srslte_csi_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); uint32_t O_total = uci_cfg->o_ack + uci_cfg->o_sr + srslte_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi);
// Add CRC bits if any // Add CRC bits if any
O_total += srslte_uci_nr_crc_len(O_total); O_total += srslte_uci_nr_crc_len(O_total);

@ -631,8 +631,17 @@ add_nr_test(pdsch_nr_test pdsch_nr_test -p 6 -m 20)
add_executable(pusch_nr_test pusch_nr_test.c) add_executable(pusch_nr_test pusch_nr_test.c)
target_link_libraries(pusch_nr_test srslte_phy) target_link_libraries(pusch_nr_test srslte_phy)
add_nr_test(pusch_nr_test pusch_nr_test -p 6 -m 20) add_nr_test(pusch_nr_test pusch_nr_test -p 6 -m 20)
add_nr_test(pusch_nr_ack_4_test pusch_nr_test -p 50 -m 20 -A 4) add_nr_test(pusch_nr_ack1_test pusch_nr_test -p 50 -m 20 -A 1)
add_nr_test(pusch_nr_ack_20_test pusch_nr_test -p 50 -m 20 -A 20) add_nr_test(pusch_nr_ack2_test pusch_nr_test -p 50 -m 20 -A 2)
add_nr_test(pusch_nr_ack4_test pusch_nr_test -p 50 -m 20 -A 4)
add_nr_test(pusch_nr_ack20_test pusch_nr_test -p 50 -m 20 -A 20)
add_nr_test(pusch_nr_csi4_test pusch_nr_test -p 50 -m 20 -C 4)
add_nr_test(pusch_nr_csi20_test pusch_nr_test -p 50 -m 20 -C 20)
add_nr_test(pusch_nr_ack1_csi4_test pusch_nr_test -p 50 -m 20 -A 1 -C 4)
add_nr_test(pusch_nr_ack2_csi4_test pusch_nr_test -p 50 -m 20 -A 2 -C 4)
add_nr_test(pusch_nr_ack4_csi4_test pusch_nr_test -p 50 -m 20 -A 4 -C 4)
add_nr_test(pusch_nr_ack20_csi4_test pusch_nr_test -p 50 -m 20 -A 20 -C 4)
add_executable(pdcch_nr_test pdcch_nr_test.c) add_executable(pdcch_nr_test pdcch_nr_test.c)
target_link_libraries(pdcch_nr_test srslte_phy) target_link_libraries(pdcch_nr_test srslte_phy)

@ -188,8 +188,8 @@ int main(int argc, char** argv)
} }
pusch_cfg.scaling = 0.5f; pusch_cfg.scaling = 0.5f;
pusch_cfg.beta_harq_ack_offset = 1.500f; pusch_cfg.beta_harq_ack_offset = 2.0f;
pusch_cfg.beta_csi_part1_offset = 1.500f; pusch_cfg.beta_csi_part1_offset = 2.0f;
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");
@ -231,15 +231,18 @@ int main(int argc, char** argv)
} }
// Generate CSI report bits // Generate CSI report bits
uint8_t csi_report[SRSLTE_UCI_NR_MAX_CSI1_BITS]; uint8_t csi_report_tx[SRSLTE_UCI_NR_MAX_CSI1_BITS] = {};
uint8_t csi_report_rx[SRSLTE_UCI_NR_MAX_CSI1_BITS] = {};
if (nof_csi_bits > 0) { if (nof_csi_bits > 0) {
pusch_cfg.uci.csi[0].quantity = SRSLTE_CSI_REPORT_QUANTITY_NONE; pusch_cfg.uci.csi[0].quantity = SRSLTE_CSI_REPORT_QUANTITY_NONE;
pusch_cfg.uci.csi[0].K_csi_rs = nof_csi_bits; pusch_cfg.uci.csi[0].K_csi_rs = nof_csi_bits;
pusch_cfg.uci.nof_csi = 1; pusch_cfg.uci.nof_csi = 1;
data_tx->uci.csi[0].none = csi_report; data_tx->uci.csi[0].none = csi_report_tx;
for (uint32_t i = 0; i < nof_csi_bits; i++) { for (uint32_t i = 0; i < nof_csi_bits; i++) {
csi_report[i] = (uint8_t)srslte_random_uniform_int_dist(rand_gen, 0, 1); csi_report_tx[i] = (uint8_t)srslte_random_uniform_int_dist(rand_gen, 0, 1);
} }
data_rx->uci.csi[0].none = csi_report_rx;
} }
if (srslte_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_cfg.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) {
@ -325,6 +328,18 @@ int main(int argc, char** argv)
} }
} }
// Validate CSI is decoded successfully
if (nof_csi_bits > 0) {
if (memcmp(data_tx[0].uci.csi[0].none, data_rx[0].uci.csi[0].none, nof_csi_bits) != 0) {
ERROR("UCI CSI bits are unmatched");
printf("Tx data: ");
srslte_vec_fprint_byte(stdout, data_tx[0].uci.csi[0].none, nof_csi_bits);
printf("Rx data: ");
srslte_vec_fprint_byte(stdout, data_rx[0].uci.csi[0].none, nof_csi_bits);
goto clean_exit;
}
}
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); 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);
} }
} }

@ -26,6 +26,7 @@
#define UCI_NR_POLAR_RM_IBIL 0 #define UCI_NR_POLAR_RM_IBIL 0
#define UCI_NR_PUCCH_POLAR_N_MAX 10 #define UCI_NR_PUCCH_POLAR_N_MAX 10
#define UCI_NR_BLOCK_DEFAULT_CORR_THRESHOLD 0.5f #define UCI_NR_BLOCK_DEFAULT_CORR_THRESHOLD 0.5f
#define UCI_NR_ONE_BIT_CORR_THRESHOLD 0.5f
uint32_t srslte_uci_nr_crc_len(uint32_t A) uint32_t srslte_uci_nr_crc_len(uint32_t A)
{ {
@ -113,6 +114,11 @@ int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args)
} else { } else {
q->block_code_threshold = UCI_NR_BLOCK_DEFAULT_CORR_THRESHOLD; q->block_code_threshold = UCI_NR_BLOCK_DEFAULT_CORR_THRESHOLD;
} }
if (isnormal(args->one_bit_threshold)) {
q->one_bit_threshold = args->one_bit_threshold;
} else {
q->one_bit_threshold = UCI_NR_ONE_BIT_CORR_THRESHOLD;
}
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -200,7 +206,7 @@ static int uci_nr_unpack_ack_sr(const srslte_uci_cfg_nr_t* cfg, uint8_t* sequenc
static int uci_nr_A(const srslte_uci_cfg_nr_t* cfg) static int uci_nr_A(const srslte_uci_cfg_nr_t* cfg)
{ {
int o_csi = srslte_csi_nof_bits(cfg->csi, cfg->nof_csi); int o_csi = srslte_csi_part1_nof_bits(cfg->csi, cfg->nof_csi);
// 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation // 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation
if (o_csi == 0) { if (o_csi == 0) {
@ -219,7 +225,7 @@ static int uci_nr_A(const srslte_uci_cfg_nr_t* cfg)
static int uci_nr_pack_pucch(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence) static int uci_nr_pack_pucch(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence)
{ {
int o_csi = srslte_csi_nof_bits(cfg->csi, cfg->nof_csi); int o_csi = srslte_csi_part1_nof_bits(cfg->csi, cfg->nof_csi);
// 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation // 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation
if (o_csi == 0) { if (o_csi == 0) {
@ -238,7 +244,7 @@ static int uci_nr_pack_pucch(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_va
static int uci_nr_unpack_pucch(const srslte_uci_cfg_nr_t* cfg, uint8_t* sequence, srslte_uci_value_nr_t* value) static int uci_nr_unpack_pucch(const srslte_uci_cfg_nr_t* cfg, uint8_t* sequence, srslte_uci_value_nr_t* value)
{ {
int o_csi = srslte_csi_nof_bits(cfg->csi, cfg->nof_csi); int o_csi = srslte_csi_part1_nof_bits(cfg->csi, cfg->nof_csi);
// 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation // 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation
if (o_csi == 0) { if (o_csi == 0) {
@ -270,39 +276,39 @@ static int uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg
case SRSLTE_MOD_QPSK: case SRSLTE_MOD_QPSK:
while (i < E) { while (i < E) {
o[i++] = c0; o[i++] = c0;
o[i++] = UCI_BIT_REPETITION; o[i++] = (uint8_t)UCI_BIT_REPETITION;
} }
break; break;
case SRSLTE_MOD_16QAM: case SRSLTE_MOD_16QAM:
while (i < E) { while (i < E) {
o[i++] = c0; o[i++] = c0;
o[i++] = UCI_BIT_REPETITION; o[i++] = (uint8_t)UCI_BIT_REPETITION;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
} }
break; break;
case SRSLTE_MOD_64QAM: case SRSLTE_MOD_64QAM:
while (i < E) { while (i < E) {
while (i < E) { while (i < E) {
o[i++] = c0; o[i++] = c0;
o[i++] = UCI_BIT_REPETITION; o[i++] = (uint8_t)UCI_BIT_REPETITION;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
} }
} }
break; break;
case SRSLTE_MOD_256QAM: case SRSLTE_MOD_256QAM:
while (i < E) { while (i < E) {
o[i++] = c0; o[i++] = c0;
o[i++] = UCI_BIT_REPETITION; o[i++] = (uint8_t)UCI_BIT_REPETITION;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
} }
break; break;
case SRSLTE_MOD_NITEMS: case SRSLTE_MOD_NITEMS:
@ -311,15 +317,67 @@ static int uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) {
UCI_NR_INFO_TX("One bit encoded NR-UCI; o=");
srslte_vec_fprint_b(stdout, o, E);
}
return E; return E;
} }
static int uci_nr_decode_1_bit(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* cfg,
uint32_t A,
const int8_t* llr,
uint32_t E,
bool* decoded_ok)
{
uint32_t Qm = srslte_mod_bits_x_symbol(cfg->pusch.modulation);
if (Qm == 0) {
ERROR("Invalid modulation (%s)", srslte_mod_string(cfg->pusch.modulation));
return SRSLTE_ERROR;
}
// Correlate LLR
float corr = 0.0f;
float pwr = 0.0f;
for (uint32_t i = 0; i < E; i += Qm) {
float t = (float)llr[i];
corr += t;
pwr += t * t;
}
// Normalise correlation
float norm_corr = Qm * corr / (E * sqrtf(pwr));
// Take decoded decision with threshold
*decoded_ok = (norm_corr > q->one_bit_threshold);
// Save decoded bit
q->bit_sequence[0] = (corr < 0) ? 0 : 1;
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) {
UCI_NR_INFO_RX("One bit decoding NR-UCI llr=");
srslte_vec_fprint_bs(stdout, llr, E);
UCI_NR_INFO_RX("One bit decoding NR-UCI A=%d; E=%d; pwr=%f; corr=%f; norm=%f; thr=%f; %s",
A,
E,
pwr,
corr,
norm_corr,
q->block_code_threshold,
*decoded_ok ? "OK" : "KO");
}
return SRSLTE_SUCCESS;
}
static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, 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; uint32_t i = 0;
srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1; uint8_t c0 = (uint8_t)((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; uint8_t c1 = (uint8_t)((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; uint8_t c2 = (uint8_t)(((q->bit_sequence[0] ^ q->bit_sequence[1]) == 0) ? UCI_BIT_0 : UCI_BIT_1);
switch (cfg->pusch.modulation) { switch (cfg->pusch.modulation) {
case SRSLTE_MOD_BPSK: case SRSLTE_MOD_BPSK:
@ -334,38 +392,38 @@ static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg
while (i < E) { while (i < E) {
o[i++] = c0; o[i++] = c0;
o[i++] = c1; o[i++] = c1;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = c2; o[i++] = c2;
o[i++] = c0; o[i++] = c0;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = c1; o[i++] = c1;
o[i++] = c2; o[i++] = c2;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
} }
break; break;
case SRSLTE_MOD_64QAM: case SRSLTE_MOD_64QAM:
while (i < E) { while (i < E) {
o[i++] = c0; o[i++] = c0;
o[i++] = c1; o[i++] = c1;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = c2; o[i++] = c2;
o[i++] = c0; o[i++] = c0;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = c1; o[i++] = c1;
o[i++] = c2; o[i++] = c2;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
} }
break; break;
case SRSLTE_MOD_256QAM: case SRSLTE_MOD_256QAM:
@ -373,28 +431,28 @@ static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg
while (i < E) { while (i < E) {
o[i++] = c0; o[i++] = c0;
o[i++] = c1; o[i++] = c1;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = c2; o[i++] = c2;
o[i++] = c0; o[i++] = c0;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = c1; o[i++] = c1;
o[i++] = c2; o[i++] = c2;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER; o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
} }
break; break;
case SRSLTE_MOD_NITEMS: case SRSLTE_MOD_NITEMS:
@ -403,9 +461,68 @@ static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) {
UCI_NR_INFO_TX("Two bit encoded NR-UCI; o=");
srslte_vec_fprint_b(stdout, o, E);
}
return E; return E;
} }
static int uci_nr_decode_2_bit(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* cfg,
uint32_t A,
const int8_t* llr,
uint32_t E,
bool* decoded_ok)
{
uint32_t Qm = srslte_mod_bits_x_symbol(cfg->pusch.modulation);
if (Qm == 0) {
ERROR("Invalid modulation (%s)", srslte_mod_string(cfg->pusch.modulation));
return SRSLTE_ERROR;
}
// Correlate LLR
float corr[3] = {};
if (Qm == 1) {
for (uint32_t i = 0; i < E / Qm; i++) {
corr[i % 3] = llr[i];
}
} else {
for (uint32_t i = 0, j = 0; i < E; i += Qm) {
corr[(j++) % 3] = llr[i + 0];
corr[(j++) % 3] = llr[i + 1];
}
}
// Take decoded decision
bool c0 = corr[0] > 0.0f;
bool c1 = corr[1] > 0.0f;
bool c2 = corr[2] > 0.0f;
// Check redundancy bit
*decoded_ok = (c2 == (c0 ^ c1));
// Save decoded bits
q->bit_sequence[0] = c0 ? 1 : 0;
q->bit_sequence[1] = c1 ? 1 : 0;
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) {
UCI_NR_INFO_RX("Two bit decoding NR-UCI llr=");
srslte_vec_fprint_bs(stdout, llr, E);
UCI_NR_INFO_RX("Two bit decoding NR-UCI A=%d; E=%d; Qm=%d; c0=%d; c1=%d; c2=%d %s",
A,
E,
Qm,
c0,
c1,
c2,
*decoded_ok ? "OK" : "KO");
}
return SRSLTE_SUCCESS;
}
static int static int
uci_nr_encode_3_11_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint32_t A, uint8_t* o, uint32_t E) uci_nr_encode_3_11_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint32_t A, uint8_t* o, uint32_t E)
{ {
@ -439,6 +556,7 @@ static int uci_nr_decode_3_11_bit(srslte_uci_nr_t* q,
// Compute average LLR power // Compute average LLR power
float pwr = srslte_vec_avg_power_bf(llr, E); float pwr = srslte_vec_avg_power_bf(llr, E);
if (!isnormal(pwr)) { if (!isnormal(pwr)) {
ERROR("Received all zeros");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -491,6 +609,7 @@ uci_nr_encode_11_1706_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, ui
uint32_t K_r = A_prime / C + L; uint32_t K_r = A_prime / C + L;
uint32_t E_r = E_uci / C; uint32_t E_r = E_uci / C;
if (srslte_polar_code_get(&q->code, K_r, E_r, UCI_NR_PUCCH_POLAR_N_MAX) < SRSLTE_SUCCESS) { if (srslte_polar_code_get(&q->code, K_r, E_r, UCI_NR_PUCCH_POLAR_N_MAX) < SRSLTE_SUCCESS) {
ERROR("Error computing Polar code");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -662,25 +781,26 @@ static int uci_nr_encode(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* uci_cfg,
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
static int static int uci_nr_decode(srslte_uci_nr_t* q,
uci_nr_decode(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* uci_cfg, int8_t* llr, uint32_t E_uci, bool* valid) const srslte_uci_cfg_nr_t* uci_cfg,
int8_t* llr,
uint32_t A,
uint32_t E_uci,
bool* valid)
{ {
if (q == NULL || uci_cfg == NULL || valid == NULL || llr == NULL) { if (q == NULL || uci_cfg == NULL || valid == NULL || llr == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
// 6.3.1.1 UCI bit sequence generation
int A = uci_nr_A(uci_cfg);
if (A < SRSLTE_SUCCESS) {
ERROR("Error getting number of bits");
return SRSLTE_ERROR;
}
// Decode LLR // Decode LLR
if (A == 1) { if (A == 1) {
ERROR("Not implemented"); if (uci_nr_decode_1_bit(q, uci_cfg, A, llr, E_uci, valid) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
} else if (A == 2) { } else if (A == 2) {
ERROR("Not implemented"); if (uci_nr_decode_2_bit(q, uci_cfg, A, llr, E_uci, valid) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
} else if (A <= 11) { } else if (A <= 11) {
if (uci_nr_decode_3_11_bit(q, uci_cfg, A, llr, E_uci, valid) < SRSLTE_SUCCESS) { if (uci_nr_decode_3_11_bit(q, uci_cfg, A, llr, E_uci, valid) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -782,7 +902,14 @@ int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (uci_nr_decode(q, uci_cfg, llr, E_uci, &value->valid) < SRSLTE_SUCCESS) { // 6.3.1.1 UCI bit sequence generation
int A = uci_nr_A(uci_cfg);
if (A < SRSLTE_SUCCESS) {
ERROR("Error getting number of bits");
return SRSLTE_ERROR;
}
if (uci_nr_decode(q, uci_cfg, llr, A, E_uci, &value->valid) < SRSLTE_SUCCESS) {
ERROR("Error decoding UCI bits"); ERROR("Error decoding UCI bits");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -802,7 +929,7 @@ uint32_t srslte_uci_nr_total_bits(const srslte_uci_cfg_nr_t* uci_cfg)
return 0; return 0;
} }
return uci_cfg->o_ack + uci_cfg->o_sr + srslte_csi_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); return uci_cfg->o_ack + uci_cfg->o_sr + srslte_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi);
} }
uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uint32_t str_len) uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uint32_t str_len)
@ -828,7 +955,7 @@ uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uin
return len; return len;
} }
int srslte_uci_nr_pusch_ack_nof_re(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack) static int uci_nr_pusch_Q_prime_ack(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack)
{ {
if (cfg == NULL) { if (cfg == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
@ -866,7 +993,7 @@ int srslte_uci_nr_pusch_ack_nof_bits(const srslte_uci_nr_pusch_cfg_t* cfg, uint3
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
int Q_ack_prime = srslte_uci_nr_pusch_ack_nof_re(cfg, O_ack); int Q_ack_prime = uci_nr_pusch_Q_prime_ack(cfg, O_ack);
if (Q_ack_prime < SRSLTE_SUCCESS) { if (Q_ack_prime < SRSLTE_SUCCESS) {
ERROR("Error calculating number of RE"); ERROR("Error calculating number of RE");
return Q_ack_prime; return Q_ack_prime;
@ -935,7 +1062,7 @@ int srslte_uci_nr_decode_pusch_ack(srslte_uci_nr_t* q,
} }
// Decode // Decode
if (uci_nr_decode(q, cfg, llr, E_uci, &value->valid) < SRSLTE_SUCCESS) { if (uci_nr_decode(q, cfg, llr, A, E_uci, &value->valid) < SRSLTE_SUCCESS) {
ERROR("Error decoding UCI"); ERROR("Error decoding UCI");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -943,5 +1070,133 @@ int srslte_uci_nr_decode_pusch_ack(srslte_uci_nr_t* q,
// Unpack // Unpack
srslte_vec_u8_copy(value->ack, q->bit_sequence, A); srslte_vec_u8_copy(value->ack, q->bit_sequence, A);
return SRSLTE_SUCCESS;
}
static int uci_nr_pusch_Q_prime_csi1(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_csi1, uint32_t O_ack)
{
if (cfg == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
uint32_t L_ack = srslte_uci_nr_crc_len(O_csi1); // Number of CRC bits
uint32_t Qm = srslte_mod_bits_x_symbol(cfg->modulation); // modulation order of the PUSCH
uint32_t Q_prime_ack = 0;
int n = uci_nr_pusch_Q_prime_ack(cfg, SRSLTE_MAX(2, O_ack));
if (n < SRSLTE_ERROR) {
ERROR("Calculating Q_prime_ack");
return SRSLTE_ERROR;
}
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];
}
}
if (!isnormal(cfg->R)) {
ERROR("Invalid Rate (%f)", cfg->R);
return SRSLTE_ERROR;
}
if (cfg->K_sum == 0) {
if (cfg->csi_part2_present) {
return (int)SRSLTE_MIN(ceilf(((O_csi1 + L_ack) * cfg->beta_csi1_offset) / (Qm * cfg->R)),
cfg->alpha * M_uci_l0_sum - Q_prime_ack);
}
return (int)(M_uci_sum - Q_prime_ack);
}
return (int)SRSLTE_MIN(ceilf(((O_csi1 + L_ack) * cfg->beta_csi1_offset * M_uci_sum) / cfg->K_sum),
ceilf(cfg->alpha * M_uci_l0_sum) - Q_prime_ack);
}
int srslte_uci_nr_pusch_csi1_nof_bits(const srslte_uci_cfg_nr_t* cfg)
{
// Check inputs
if (cfg == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
int O_csi1 = srslte_csi_part1_nof_bits(cfg->csi, cfg->nof_csi);
if (O_csi1 < SRSLTE_SUCCESS) {
ERROR("Errpr calculating CSI part 1 number of bits");
return SRSLTE_ERROR;
}
uint32_t O_ack = SRSLTE_MAX(2, cfg->o_ack);
int Q_csi1_prime = uci_nr_pusch_Q_prime_csi1(&cfg->pusch, (uint32_t)O_csi1, O_ack);
if (Q_csi1_prime < SRSLTE_SUCCESS) {
ERROR("Error calculating number of RE");
return Q_csi1_prime;
}
return (int)(Q_csi1_prime * cfg->pusch.nof_layers * srslte_mod_bits_x_symbol(cfg->pusch.modulation));
}
int srslte_uci_nr_encode_pusch_csi1(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* cfg,
const srslte_uci_value_nr_t* value,
uint8_t* o)
{
// Check inputs
if (q == NULL || cfg == NULL || value == NULL || o == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
int A = srslte_csi_part1_pack(cfg->csi, value->csi, cfg->nof_csi, q->bit_sequence, SRSLTE_UCI_NR_MAX_NOF_BITS);
if (A < SRSLTE_SUCCESS) {
ERROR("Error packing CSI part 1 report");
return SRSLTE_ERROR;
}
// Compute total of encoded bits according to 6.3.2.4 Rate matching
int E_uci = srslte_uci_nr_pusch_csi1_nof_bits(cfg);
if (E_uci < SRSLTE_SUCCESS) {
ERROR("Error calculating number of encoded bits");
return SRSLTE_ERROR;
}
return uci_nr_encode(q, cfg, A, o, E_uci);
}
int srslte_uci_nr_decode_pusch_csi1(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* cfg,
int8_t* llr,
srslte_uci_value_nr_t* value)
{
// Check inputs
if (q == NULL || cfg == NULL || llr == NULL || value == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Compute total of encoded bits according to 6.3.2.4 Rate matching
int E_uci = srslte_uci_nr_pusch_csi1_nof_bits(cfg);
if (E_uci < SRSLTE_SUCCESS) {
ERROR("Error calculating number of encoded bits");
return SRSLTE_ERROR;
}
int A = srslte_csi_part1_nof_bits(cfg->csi, cfg->nof_csi);
if (A < SRSLTE_SUCCESS) {
ERROR("Error getting number of CSI part 1 bits");
return SRSLTE_ERROR;
}
// Decode
if (uci_nr_decode(q, cfg, llr, (uint32_t)A, (uint32_t)E_uci, &value->valid) < SRSLTE_SUCCESS) {
ERROR("Error decoding UCI");
return SRSLTE_ERROR;
}
// Unpack
if (srslte_csi_part1_unpack(cfg->csi, cfg->nof_csi, q->bit_sequence, A, value->csi) < SRSLTE_SUCCESS) {
ERROR("Error unpacking CSI");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
Loading…
Cancel
Save