mirror of https://github.com/PentHertz/srsLTE.git
Added CSI part1 and 1/2 bit HARQ-ACK multiplexing on PUSCH
This commit is contained in:
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
|
||||
* @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
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* @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 nof_reports Number of CSI reports in the list
|
||||
* @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,
|
||||
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
|
||||
* @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
|
||||
* 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
|
||||
|
@ -61,8 +61,9 @@ typedef struct {
|
|||
float R; ///< Code rate of the PUSCH
|
||||
float alpha; ///< Higher layer parameter scaling
|
||||
float beta_harq_ack_offset;
|
||||
float beta_csi_part1_offset;
|
||||
float beta_csi1_offset;
|
||||
uint32_t nof_re;
|
||||
bool csi_part2_present;
|
||||
} srslte_uci_nr_pusch_cfg_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
typedef struct {
|
||||
bool disable_simd; ///< Disable Polar code SIMD
|
||||
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;
|
||||
|
||||
typedef struct {
|
||||
|
@ -42,11 +43,12 @@ typedef struct {
|
|||
srslte_crc_t crc6;
|
||||
srslte_crc_t crc11;
|
||||
srslte_polar_code_t code;
|
||||
uint8_t* bit_sequence; ///< UCI bit sequence
|
||||
uint8_t* c; ///< UCI code-block prior encoding or after decoding
|
||||
uint8_t* allocated; ///< Polar code intermediate
|
||||
uint8_t* d; ///< Polar code encoded intermediate
|
||||
float block_code_threshold;
|
||||
uint8_t* bit_sequence; ///< UCI bit sequence
|
||||
uint8_t* c; ///< UCI code-block prior encoding or after decoding
|
||||
uint8_t* allocated; ///< Polar code intermediate
|
||||
uint8_t* d; ///< Polar code encoded intermediate
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -125,18 +127,7 @@ SRSLTE_API int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
|
|||
srslte_uci_value_nr_t* value);
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @brief Calculates total number of encoded bits for HARQ-ACK multiplexing in PUSCH
|
||||
* @param[in] cfg PUSCH transmission configuration
|
||||
* @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,
|
||||
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
|
||||
* @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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "srslte/phy/phch/csi.h"
|
||||
#include "srslte/phy/utils/bit.h"
|
||||
#include "srslte/phy/utils/debug.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
#include <math.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
static int csi_wideband_cri_ri_pmi_cqi_pack(const srslte_csi_report_cfg_t* cfg,
|
||||
const srslte_csi_report_value_t* value,
|
||||
uint8_t* o_csi1)
|
||||
static uint32_t csi_wideband_cri_ri_pmi_cqi_pack(const srslte_csi_report_cfg_t* cfg,
|
||||
const srslte_csi_report_value_t* value,
|
||||
uint8_t* o_csi1)
|
||||
{
|
||||
// Compute number of bits for CRI
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
uint32_t slot_idx,
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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];
|
||||
if (report->quantity && report->quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
ERROR("The maximum number of CSI bits (%d) is not enough to accommodate %d bits", max_o_csi1, n);
|
||||
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 &&
|
||||
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]);
|
||||
} 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 {
|
||||
ERROR("CSI frequency (%d) and quantity (%d) combination is not implemented",
|
||||
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 &&
|
||||
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);
|
||||
} 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;
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
#include "srslte/phy/mimo/layermap.h"
|
||||
#include "srslte/phy/mimo/precoding.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/uci_cfg.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
q->g_ulsch = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
|
||||
q->g_ack = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
|
||||
q->g_csi1 = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_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) {
|
||||
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);
|
||||
q->pos_ulsch = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
|
||||
q->pos_ack = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
|
||||
q->pos_csi1 = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_NOF_BITS_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) {
|
||||
ERROR("Malloc");
|
||||
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
|
||||
q->uci_cfg.pusch.modulation = cfg->grant.tb[0].mod;
|
||||
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.alpha = cfg->scaling;
|
||||
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.nof_re = cfg->grant.tb[0].nof_re;
|
||||
q->uci_cfg.pusch.modulation = cfg->grant.tb[0].mod;
|
||||
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.alpha = cfg->scaling;
|
||||
q->uci_cfg.pusch.beta_harq_ack_offset = cfg->beta_harq_ack_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;
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
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--;
|
||||
} 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++) {
|
||||
pos_csi1[m_csi1_count++] = m_all_count++;
|
||||
pos_csi1[m_csi1_count++] = m_all_count + j;
|
||||
}
|
||||
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++;
|
||||
pos_csi2[m_csi2_count++] = m_all_count + j;
|
||||
}
|
||||
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++;
|
||||
pos_ulsch[m_ulsch_count++] = m_all_count + j;
|
||||
}
|
||||
ulsch_m_re_count--;
|
||||
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
|
||||
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++) {
|
||||
pos_ack[m_ack_count++] = m_all_count++;
|
||||
pos_ack[m_ack_count++] = m_all_count + j;
|
||||
}
|
||||
ack_m_re_count--;
|
||||
}
|
||||
|
||||
// Increment all bit counter
|
||||
m_all_count += Nl * Qm;
|
||||
}
|
||||
|
||||
// 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");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->G_ack = E_uci_ack;
|
||||
q->G_csi1 = 0;
|
||||
q->G_ack = (uint32_t)E_uci_ack;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (n < SRSLTE_SUCCESS) {
|
||||
ERROR("Calculating G_ack");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->G_ack = (uint32_t)n;
|
||||
q->G_csi1 = 0;
|
||||
q->G_ack = (uint32_t)n;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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)
|
||||
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_ack_4_test pusch_nr_test -p 50 -m 20 -A 4)
|
||||
add_nr_test(pusch_nr_ack_20_test pusch_nr_test -p 50 -m 20 -A 20)
|
||||
add_nr_test(pusch_nr_ack1_test pusch_nr_test -p 50 -m 20 -A 1)
|
||||
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)
|
||||
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.beta_harq_ack_offset = 1.500f;
|
||||
pusch_cfg.beta_csi_part1_offset = 1.500f;
|
||||
pusch_cfg.beta_harq_ack_offset = 2.0f;
|
||||
pusch_cfg.beta_csi_part1_offset = 2.0f;
|
||||
|
||||
if (srslte_chest_dl_res_init(&chest, carrier.nof_prb) < SRSLTE_SUCCESS) {
|
||||
ERROR("Initiating chest");
|
||||
|
@ -231,15 +231,18 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
// 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) {
|
||||
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.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++) {
|
||||
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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define UCI_NR_POLAR_RM_IBIL 0
|
||||
#define UCI_NR_PUCCH_POLAR_N_MAX 10
|
||||
#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)
|
||||
{
|
||||
|
@ -113,6 +114,11 @@ int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args)
|
|||
} else {
|
||||
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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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
|
||||
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)
|
||||
{
|
||||
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
|
||||
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)
|
||||
{
|
||||
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
|
||||
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:
|
||||
while (i < E) {
|
||||
o[i++] = c0;
|
||||
o[i++] = UCI_BIT_REPETITION;
|
||||
o[i++] = (uint8_t)UCI_BIT_REPETITION;
|
||||
}
|
||||
break;
|
||||
case SRSLTE_MOD_16QAM:
|
||||
while (i < E) {
|
||||
o[i++] = c0;
|
||||
o[i++] = UCI_BIT_REPETITION;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_REPETITION;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
}
|
||||
break;
|
||||
case SRSLTE_MOD_64QAM:
|
||||
while (i < E) {
|
||||
while (i < E) {
|
||||
o[i++] = c0;
|
||||
o[i++] = UCI_BIT_REPETITION;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_REPETITION;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SRSLTE_MOD_256QAM:
|
||||
while (i < E) {
|
||||
o[i++] = c0;
|
||||
o[i++] = UCI_BIT_REPETITION;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_REPETITION;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
uint32_t i = 0;
|
||||
uint8_t c0 = (uint8_t)((q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1);
|
||||
uint8_t c1 = (uint8_t)((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) {
|
||||
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) {
|
||||
o[i++] = c0;
|
||||
o[i++] = c1;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = c2;
|
||||
o[i++] = c0;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = c1;
|
||||
o[i++] = c2;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
}
|
||||
break;
|
||||
case SRSLTE_MOD_64QAM:
|
||||
while (i < E) {
|
||||
o[i++] = c0;
|
||||
o[i++] = c1;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = c2;
|
||||
o[i++] = c0;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = c1;
|
||||
o[i++] = c2;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
}
|
||||
break;
|
||||
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) {
|
||||
o[i++] = c0;
|
||||
o[i++] = c1;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = c2;
|
||||
o[i++] = c0;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = c1;
|
||||
o[i++] = c2;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
o[i++] = (uint8_t)UCI_BIT_PLACEHOLDER;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
float pwr = srslte_vec_avg_power_bf(llr, E);
|
||||
if (!isnormal(pwr)) {
|
||||
ERROR("Received all zeros");
|
||||
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 E_r = E_uci / C;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
static int
|
||||
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)
|
||||
static int uci_nr_decode(srslte_uci_nr_t* q,
|
||||
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) {
|
||||
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
|
||||
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) {
|
||||
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) {
|
||||
if (uci_nr_decode_3_11_bit(q, uci_cfg, A, llr, E_uci, valid) < SRSLTE_SUCCESS) {
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -782,7 +902,14 @@ int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
|
|||
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");
|
||||
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 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)
|
||||
|
@ -828,7 +955,7 @@ uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uin
|
|||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
ERROR("Error calculating number of RE");
|
||||
return Q_ack_prime;
|
||||
|
@ -935,7 +1062,7 @@ int srslte_uci_nr_decode_pusch_ack(srslte_uci_nr_t* q,
|
|||
}
|
||||
|
||||
// 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");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
@ -943,5 +1070,133 @@ int srslte_uci_nr_decode_pusch_ack(srslte_uci_nr_t* q,
|
|||
// Unpack
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue