More NR-PUCCH support

This commit is contained in:
Xavier Arteaga 2021-01-19 15:25:18 +01:00 committed by Xavier Arteaga
parent 697bdb4d6d
commit 4d96cf4a41
12 changed files with 585 additions and 243 deletions

View File

@ -27,12 +27,12 @@
* @param[out] slot_symbols Resource grid of the given slot
* @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_dmrs_pucch_format1_put(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_format1_t* resource,
cf_t* slot_symbols);
SRSLTE_API int srslte_dmrs_pucch_format1_put(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
cf_t* slot_symbols);
/**
* @brief Estimates NR-PUCCH format 1 resource elements from their DMRS in the provided resource grid
@ -45,12 +45,12 @@ SRSLTE_API int srslte_dmrs_pucch_format1_put(const srslte_pucch_nr_t*
* @param[out] res UL Channel estimator result
* @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_dmrs_pucch_format1_estimate(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_format1_t* resource,
const cf_t* slot_symbols,
srslte_chest_ul_res_t* res);
SRSLTE_API int srslte_dmrs_pucch_format1_estimate(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
const cf_t* slot_symbols,
srslte_chest_ul_res_t* res);
#endif // SRSLTE_DMRS_PUCCH_H

View File

@ -0,0 +1,86 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_PUCCH_CFG_NR_H
#define SRSLTE_PUCCH_CFG_NR_H
#include "srslte/config.h"
#include <stdbool.h>
#include <stdint.h>
typedef enum SRSLTE_API {
SRSLTE_PUCCH_NR_FORMAT_0 = 0,
SRSLTE_PUCCH_NR_FORMAT_1,
SRSLTE_PUCCH_NR_FORMAT_2,
SRSLTE_PUCCH_NR_FORMAT_3,
SRSLTE_PUCCH_NR_FORMAT_4,
SRSLTE_PUCCH_NR_FORMAT_ERROR,
} srslte_pucch_nr_format_t;
typedef enum SRSLTE_API {
SRSLTE_PUCCH_NR_GROUP_HOPPING_NEITHER = 0,
SRSLTE_PUCCH_NR_GROUP_HOPPING_ENABLE,
SRSLTE_PUCCH_NR_GROUP_HOPPING_DISABLE
} srslte_pucch_nr_group_hopping_t;
/**
* @brief PUCCH Common configuration
* @remark Defined in TS 38.331 PUCCH-ConfigCommon
*/
typedef struct SRSLTE_API {
uint32_t resource_common; ///< Configures a set of cell-specific PUCCH resources/parameters
srslte_pucch_nr_group_hopping_t group_hopping; ///< Configuration of group and sequence hopping
uint32_t hopping_id; ///< Cell-specific scrambling ID for group hopping and sequence hopping if enabled
bool hopping_id_present;
float p0_nominal; ///< Power control parameter P0 for PUCCH transmissions. Value in dBm. (-202..24)
} srslte_pucch_nr_common_cfg_t;
/**
* @brief Generic PUCCH Resource configuration
* @remark Defined in TS 38.331 PUCCH-Config
*/
typedef struct SRSLTE_API {
//
uint32_t starting_prb;
bool intra_slot_hopping;
uint32_t second_hop_prb;
// Common PUCCH-Resource parameters among all formats
srslte_pucch_nr_format_t format; ///< PUCCH format this configuration belongs
uint32_t nof_symbols; ///< Number of symbols
uint32_t start_symbol_idx; ///< Starting symbol index
double max_code_rate; ///< Maximum code rate (0.08, 0.15, 0.25, 0.35, 0.45, 0.60, 0.80)
bool enable_pi_bpsk; ///< Enables PI-BPSK
// Specific PUCCH-Resource
uint32_t initial_cyclic_shift; ///< Used by formats 0, 1
uint32_t time_domain_occ; ///< Used by format 1
uint32_t nof_prb; ///< Used by formats 2, 3
uint32_t occ_lenth; ///< Spreading factor, used by format 4
uint32_t occ_index; ///< Used by format 4
} srslte_pucch_nr_resource_t;
/**
* @brief Validates a PUCCH format 0 resource configuration provided by upper layers
* @param resource Resource configuration to validate
* @return SRSLTE_SUCCESS if valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_pucch_nr_format0_resource_valid(const srslte_pucch_nr_resource_t* resource);
/**
* @brief Validates a PUCCH format 1 resource configuration provided by upper layers
* @param resource Resource configuration to validate
* @return SRSLTE_SUCCESS if valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_pucch_nr_format1_resource_valid(const srslte_pucch_nr_resource_t* resource);
#endif // SRSLTE_PUCCH_CFG_NR_H

View File

@ -17,6 +17,7 @@
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/common/zc_sequence.h"
#include "srslte/phy/modem/modem_table.h"
#include "srslte/phy/phch/uci_nr.h"
#include <srslte/srslte.h>
#include <stdbool.h>
#include <stdint.h>
@ -31,57 +32,10 @@
*/
#define SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS 2
typedef enum SRSLTE_API {
SRSLTE_PUCCH_NR_FORMAT_0 = 0,
SRSLTE_PUCCH_NR_FORMAT_1,
SRSLTE_PUCCH_NR_FORMAT_2,
SRSLTE_PUCCH_NR_FORMAT_3,
SRSLTE_PUCCH_NR_FORMAT_4,
SRSLTE_PUCCH_NR_FORMAT_ERROR,
} srslte_pucch_nr_format_t;
typedef enum SRSLTE_API {
SRSLTE_PUCCH_NR_GROUP_HOPPING_NEITHER = 0,
SRSLTE_PUCCH_NR_GROUP_HOPPING_ENABLE,
SRSLTE_PUCCH_NR_GROUP_HOPPING_DISABLE
} srslte_pucch_nr_group_hopping_t;
/**
* @brief PUCCH Common configuration
* @remark Defined in TS 38.331 PUCCH-ConfigCommon
*/
typedef struct SRSLTE_API {
uint32_t resource_common; ///< Configures a set of cell-specific PUCCH resources/parameters
srslte_pucch_nr_group_hopping_t group_hopping; ///< Configuration of group and sequence hopping
uint32_t hopping_id; ///< Cell-specific scrambling ID for group hopping and sequence hopping if enabled
bool hopping_id_present;
float p0_nominal; ///< Power control parameter P0 for PUCCH transmissions. Value in dBm. (-202..24)
} srslte_pucch_nr_common_cfg_t;
/**
* @brief Generic PUCCH Resource configuration
* @remark Defined in TS 38.331 PUCCH-Config
*/
typedef struct SRSLTE_API {
//
uint32_t starting_prb;
bool intra_slot_frequency_hopping;
uint32_t second_hop_prb;
// Common PUCCH-Resource parameters among all formats
srslte_pucch_nr_format_t format; ///< PUCCH format this configuration belongs
uint32_t nof_symbols; ///< Number of symbols
uint32_t start_symbol_idx; ///< Starting symbol index
double max_code_rate; ///< Maximum code rate (0.08, 0.15, 0.25, 0.35, 0.45, 0.60, 0.80)
bool enable_pi_bpsk; ///< Enables PI-BPSK
// Specific PUCCH-Resource
uint32_t initial_cyclic_shift; ///< Used by formats 0, 1
uint32_t time_domain_occ; ///< Used by format 1
uint32_t nof_prb; ///< Used by formats 2, 3
uint32_t occ_lenth; ///< Spreading factor, used by format 4
uint32_t occ_index; ///< Used by format 4
} srslte_pucch_nr_resource_t;
srslte_uci_nr_args_t uci;
uint32_t max_nof_prb;
} srslte_pucch_nr_args_t;
typedef struct SRSLTE_API {
float rsrp;
@ -91,38 +45,17 @@ typedef struct SRSLTE_API {
float norm_corr;
} srslte_pucch_nr_measure_t;
/**
* @brief PUCCH Resource configuration for Format 0
* @remark Defined in TS 38.331 PUCCH-Config
*/
typedef struct SRSLTE_API {
uint32_t starting_prb;
uint32_t initial_cyclic_shift; ///< initialCyclicShift (0..11)
uint32_t start_symbol_idx; ///< startingSymbolIndex (0..13)
uint32_t nof_symbols; ///< nrofSymbols (1..2)
} srslte_pucch_nr_resource_format0_t;
/**
* @brief PUCCH Resource configuration for Format 1
* @remark Defined in TS 38.331 PUCCH-Config
*/
typedef struct SRSLTE_API {
uint32_t starting_prb;
uint32_t initial_cyclic_shift; ///< initialCyclicShift (0..11)
uint32_t start_symbol_idx; ///< startingSymbolIndex (0..10)
uint32_t nof_symbols; ///< nrofSymbols (4..14)
uint32_t time_domain_occ; ///< TimeDomainOCC(0..6)
bool intra_slot_hopping;
} srslte_pucch_nr_resource_format1_t;
/**
* @brief NR-PUCCH encoder/decoder object
*/
typedef struct SRSLTE_API {
uint32_t max_prb;
srslte_zc_sequence_lut_t r_uv_1prb;
cf_t format1_w_i_m[SRSLTE_PUCCH_NR_FORMAT1_N_MAX][SRSLTE_PUCCH_NR_FORMAT1_N_MAX][SRSLTE_PUCCH_NR_FORMAT1_N_MAX];
srslte_modem_table_t bpsk;
srslte_modem_table_t qpsk;
srslte_uci_nr_t uci;
uint8_t* b;
} srslte_pucch_nr_t;
/**
@ -130,7 +63,7 @@ typedef struct SRSLTE_API {
* @param q Object
* @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_pucch_nr_init(srslte_pucch_nr_t* q);
SRSLTE_API int srslte_pucch_nr_init(srslte_pucch_nr_t* q, const srslte_pucch_nr_args_t* args);
/**
* @brief Deallocates an NR-PUCCH encoder/decoder object
@ -173,13 +106,6 @@ SRSLTE_API int srslte_pucch_nr_alpha_idx(const srslte_carrier_nr_t* car
uint32_t m_cs,
uint32_t* alpha_idx);
/**
* @brief Validates a PUCCH format 1 resource configuration provided by upper layers
* @param resource Resource configuration to validate
* @return SRSLTE_SUCCESS if valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_pucch_nr_format0_resource_valid(const srslte_pucch_nr_resource_format0_t* resource);
/**
* @brief Encode and writes NR-PUCCH format 0 in the resource grid
* @remark Described in TS 38.211 clause 6.3.2.3 PUCCH format 0
@ -196,7 +122,7 @@ SRSLTE_API int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t*
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
srslte_pucch_nr_resource_format0_t* resource,
srslte_pucch_nr_resource_t* resource,
uint32_t m_cs,
cf_t* slot_symbols);
@ -216,18 +142,11 @@ SRSLTE_API int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t*
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
srslte_pucch_nr_resource_format0_t* resource,
srslte_pucch_nr_resource_t* resource,
uint32_t m_cs,
const cf_t* slot_symbols,
srslte_pucch_nr_measure_t* measure);
/**
* @brief Validates a PUCCH format 1 resource configuration provided by upper layers
* @param resource Resource configuration to validate
* @return SRSLTE_SUCCESS if valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_pucch_nr_format1_resource_valid(const srslte_pucch_nr_resource_format1_t* resource);
/**
* @brief Get NR-PUCCH orthogonal sequence w
* @remark Defined by TS 38.211 Table 6.3.2.4.1-2: Orthogonal sequences ... for PUCCH format 1
@ -252,14 +171,14 @@ SRSLTE_API cf_t srslte_pucch_nr_format1_w(const srslte_pucch_nr_t* q, uint32_t n
* @param[out] slot_symbols Resource grid of the given slot
* @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_format1_t* resource,
uint8_t* b,
uint32_t nof_bits,
cf_t* slot_symbols);
SRSLTE_API int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
uint8_t* b,
uint32_t nof_bits,
cf_t* slot_symbols);
/**
* @brief Decodes NR-PUCCH format 1
@ -274,13 +193,13 @@ SRSLTE_API int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t*
* @param[in] nof_bits Number of bits to decode in the message
* @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_format1_t* resource,
srslte_chest_ul_res_t* chest_res,
cf_t* slot_symbols,
SRSLTE_API int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
srslte_chest_ul_res_t* chest_res,
cf_t* slot_symbols,
uint8_t b[SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS],
uint32_t nof_bits);

View File

@ -16,7 +16,7 @@
#include <stdbool.h>
#include <stdint.h>
#define SRSLTE_UCI_NR_MAX_ACK_BITS 10
#define SRSLTE_UCI_NR_MAX_ACK_BITS 360
#define SRSLTE_UCI_NR_MAX_SR_BITS 10
#define SRSLTE_UCI_NR_MAX_CSI1_BITS 10
#define SRSLTE_UCI_NR_MAX_CSI2_BITS 10

View File

@ -15,9 +15,10 @@
#include "srslte/phy/fec/crc.h"
#include "srslte/phy/fec/polar/polar_code.h"
#include "srslte/phy/fec/polar/polar_decoder.h"
#include "srslte/phy/fec/polar/polar_encoder.h"
#include "srslte/phy/fec/polar/polar_rm.h"
#include "srslte/phy/phch/pucch_nr.h"
#include "srslte/phy/phch/pucch_cfg_nr.h"
#include "uci_cfg.h"
#include "uci_cfg_nr.h"
#include <stdbool.h>
@ -27,13 +28,10 @@ typedef struct {
bool disable_simd;
} srslte_uci_nr_args_t;
typedef struct {
} srslte_uci_nr_cfg_t;
typedef struct {
srslte_polar_rm_t rm;
srslte_polar_encoder_t encoder;
srslte_polar_decoder_t decoder;
srslte_crc_t crc6;
srslte_crc_t crc11;
srslte_polar_code_t code;

View File

@ -194,6 +194,7 @@ SRSLTE_API void srslte_vec_conj_cc(const cf_t* x, cf_t* y, const uint32_t len);
/* average vector power */
SRSLTE_API float srslte_vec_avg_power_cf(const cf_t* x, const uint32_t len);
SRSLTE_API float srslte_vec_avg_power_sf(const int16_t* x, const uint32_t len);
SRSLTE_API float srslte_vec_avg_power_bf(const int8_t* x, const uint32_t len);
/* Correlation between complex vectors x and y */
SRSLTE_API float srslte_vec_corr_ccc(const cf_t* x, cf_t* y, const uint32_t len);

View File

@ -15,7 +15,7 @@
#include "srslte/phy/utils/vector.h"
// Implements TS 38.211 table 6.4.1.3.1.1-1: Number of DM-RS symbols and the corresponding N_PUCCH...
static uint32_t dmrs_pucch_format1_n_pucch(const srslte_pucch_nr_resource_format1_t* resource, uint32_t m_prime)
static uint32_t dmrs_pucch_format1_n_pucch(const srslte_pucch_nr_resource_t* resource, uint32_t m_prime)
{
if (resource->intra_slot_hopping) {
if (m_prime == 0) {
@ -84,12 +84,12 @@ static uint32_t dmrs_pucch_format1_n_pucch(const srslte_pucch_nr_resource_format
return 0;
}
int srslte_dmrs_pucch_format1_put(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_format1_t* resource,
cf_t* slot_symbols)
int srslte_dmrs_pucch_format1_put(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
cf_t* slot_symbols)
{
if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL) {
@ -151,13 +151,13 @@ int srslte_dmrs_pucch_format1_put(const srslte_pucch_nr_t* q,
return SRSLTE_SUCCESS;
}
int srslte_dmrs_pucch_format1_estimate(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_format1_t* resource,
const cf_t* slot_symbols,
srslte_chest_ul_res_t* res)
int srslte_dmrs_pucch_format1_estimate(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
const cf_t* slot_symbols,
srslte_chest_ul_res_t* res)
{
if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL) {

View File

@ -0,0 +1,82 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/phy/phch/pucch_cfg_nr.h"
#include "srslte/phy/utils/debug.h"
int srslte_pucch_nr_format0_resource_valid(const srslte_pucch_nr_resource_t* resource)
{
if (resource == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (resource->format != SRSLTE_PUCCH_NR_FORMAT_0) {
ERROR("Invalid format (%d)\n", resource->format);
return SRSLTE_ERROR;
}
if (resource->nof_symbols != 1 && resource->nof_symbols != 2) {
ERROR("Invalid number of symbols (%d)\n", resource->nof_symbols);
return SRSLTE_ERROR;
}
if (resource->initial_cyclic_shift > 11) {
ERROR("Invalid initial cyclic shift (%d)\n", resource->initial_cyclic_shift);
return SRSLTE_ERROR;
}
if (resource->start_symbol_idx > 13) {
ERROR("Invalid initial start symbol idx (%d)\n", resource->start_symbol_idx);
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_pucch_nr_format1_resource_valid(const srslte_pucch_nr_resource_t* resource)
{
if (resource == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (resource->format != SRSLTE_PUCCH_NR_FORMAT_1) {
ERROR("Invalid format (%d)\n", resource->format);
return SRSLTE_ERROR;
}
if (resource->nof_symbols < 4 || resource->nof_symbols > 14) {
ERROR("Invalid number of symbols (%d)\n", resource->nof_symbols);
return SRSLTE_ERROR;
}
if (resource->initial_cyclic_shift > 11) {
ERROR("Invalid initial cyclic shift (%d)\n", resource->initial_cyclic_shift);
return SRSLTE_ERROR;
}
if (resource->start_symbol_idx > 10) {
ERROR("Invalid initial start symbol idx (%d)\n", resource->start_symbol_idx);
return SRSLTE_ERROR;
}
if (resource->time_domain_occ > 6) {
ERROR("Invalid time domain occ (%d)\n", resource->time_domain_occ);
return SRSLTE_ERROR;
}
if (resource->intra_slot_hopping) {
ERROR("Intra-slot hopping is not implemented\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}

View File

@ -90,64 +90,6 @@ int srslte_pucch_nr_alpha_idx(const srslte_carrier_nr_t* carrier,
return SRSLTE_SUCCESS;
}
int srslte_pucch_nr_format0_resource_valid(const srslte_pucch_nr_resource_format0_t* resource)
{
if (resource == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (resource->nof_symbols != 1 && resource->nof_symbols != 2) {
ERROR("Invalid number of symbols (%d)\n", resource->nof_symbols);
return SRSLTE_ERROR;
}
if (resource->initial_cyclic_shift > 11) {
ERROR("Invalid initial cyclic shift (%d)\n", resource->initial_cyclic_shift);
return SRSLTE_ERROR;
}
if (resource->start_symbol_idx > 13) {
ERROR("Invalid initial start symbol idx (%d)\n", resource->start_symbol_idx);
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_pucch_nr_format1_resource_valid(const srslte_pucch_nr_resource_format1_t* resource)
{
if (resource == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (resource->nof_symbols < 4 || resource->nof_symbols > 14) {
ERROR("Invalid number of symbols (%d)\n", resource->nof_symbols);
return SRSLTE_ERROR;
}
if (resource->initial_cyclic_shift > 11) {
ERROR("Invalid initial cyclic shift (%d)\n", resource->initial_cyclic_shift);
return SRSLTE_ERROR;
}
if (resource->start_symbol_idx > 10) {
ERROR("Invalid initial start symbol idx (%d)\n", resource->start_symbol_idx);
return SRSLTE_ERROR;
}
if (resource->time_domain_occ > 6) {
ERROR("Invalid time domain occ (%d)\n", resource->time_domain_occ);
return SRSLTE_ERROR;
}
if (resource->intra_slot_hopping) {
ERROR("Intra-slot hopping is not implemented\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
// TS 38.211 Table 6.3.2.4.1-2: Orthogonal sequences for PUCCH format 1
static uint32_t
pucch_nr_format1_rho[SRSLTE_PUCCH_NR_FORMAT1_N_MAX][SRSLTE_PUCCH_NR_FORMAT1_N_MAX][SRSLTE_PUCCH_NR_FORMAT1_N_MAX] =
@ -159,12 +101,21 @@ static uint32_t
{{}, {}, {}, {}, {}, {0, 5, 4, 3, 2, 1}, {0, 5, 3, 1, 6, 4, 2}},
{{}, {}, {}, {}, {}, {}, {0, 6, 5, 4, 3, 2, 1}}};
int srslte_pucch_nr_init(srslte_pucch_nr_t* q)
int srslte_pucch_nr_init(srslte_pucch_nr_t* q, const srslte_pucch_nr_args_t* args)
{
if (q == NULL) {
if (q == NULL || args == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Make sure object is zeroed
SRSLTE_MEM_ZERO(q, srslte_pucch_nr_t, 1);
// Save maximum number of PRB
q->max_prb = SRSLTE_MAX_PRB_NR;
if (args->max_nof_prb != 0) {
q->max_prb = args->max_nof_prb;
}
// Initialise ZC sequences for 1PRB
float alphas_1prb[SRSLTE_NRE] = {};
for (uint32_t i = 0; i < SRSLTE_NRE; i++) {
@ -193,6 +144,19 @@ int srslte_pucch_nr_init(srslte_pucch_nr_t* q)
}
}
if (srslte_uci_nr_init(&q->uci, &args->uci) < SRSLTE_SUCCESS) {
ERROR("Initiating UCI encoder/decoder\n");
return SRSLTE_ERROR;
}
// Allocate encoded bits b
uint32_t max_encoded_bits = q->max_prb * SRSLTE_NRE * 2 * SRSLTE_NSYMB_PER_SLOT_NR; // Assumes QPSK (Qm = 2)
q->b = srslte_vec_u8_malloc(max_encoded_bits);
if (q->b == NULL) {
ERROR("Malloc\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
@ -207,6 +171,10 @@ void srslte_pucch_nr_free(srslte_pucch_nr_t* q)
srslte_modem_table_free(&q->bpsk);
srslte_modem_table_free(&q->qpsk);
if (q->b != NULL) {
free(q->b);
}
SRSLTE_MEM_ZERO(q, srslte_pucch_nr_t, 1);
}
@ -214,7 +182,7 @@ int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
srslte_pucch_nr_resource_format0_t* resource,
srslte_pucch_nr_resource_t* resource,
uint32_t m_cs,
cf_t* slot_symbols)
{
@ -264,7 +232,7 @@ int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
srslte_pucch_nr_resource_format0_t* resource,
srslte_pucch_nr_resource_t* resource,
uint32_t m_cs,
const cf_t* slot_symbols,
srslte_pucch_nr_measure_t* measure)
@ -333,7 +301,7 @@ int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* q,
}
// Implements TS 38.211 table 6.3.2.4.1-1 Number of PUCCH symbols and the corresponding N_PUC...
static uint32_t pucch_nr_format1_n_pucch(const srslte_pucch_nr_resource_format1_t* resource, uint32_t m_prime)
static uint32_t pucch_nr_format1_n_pucch(const srslte_pucch_nr_resource_t* resource, uint32_t m_prime)
{
if (resource->intra_slot_hopping) {
if (m_prime == 0) {
@ -369,14 +337,14 @@ cf_t srslte_pucch_nr_format1_w(const srslte_pucch_nr_t* q, uint32_t n_pucch, uin
return q->format1_w_i_m[i][n_pucch - 1][m];
}
int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_format1_t* resource,
uint8_t* b,
uint32_t nof_bits,
cf_t* slot_symbols)
int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
uint8_t* b,
uint32_t nof_bits,
cf_t* slot_symbols)
{
uint32_t m_cs = 0;
@ -450,22 +418,18 @@ int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q,
return SRSLTE_SUCCESS;
}
int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_format1_t* resource,
srslte_chest_ul_res_t* chest_res,
cf_t* slot_symbols,
uint8_t b[SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS],
uint32_t nof_bits)
int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
srslte_chest_ul_res_t* chest_res,
cf_t* slot_symbols,
uint8_t b[SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS],
uint32_t nof_bits)
{
uint32_t m_cs = 0;
if (carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || b == NULL || slot_symbols == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (srslte_pucch_nr_format1_resource_valid(resource) < SRSLTE_SUCCESS) {
ERROR("Invalid PUCCH format 1 resource\n");
return SRSLTE_SUCCESS;
@ -533,5 +497,41 @@ int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q,
b[i] = llr[i] > 0.0f ? 1 : 0;
}
return SRSLTE_SUCCESS;
}
int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
const srslte_uci_cfg_nr_t* uci_cfg,
const srslte_uci_value_nr_t* uci_value,
cf_t* slot_symbols)
{
if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || uci_cfg == NULL ||
uci_value == NULL || slot_symbols == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (srslte_uci_nr_encode_pucch(&q->uci, resource, uci_cfg, uci_value, q->b) < SRSLTE_SUCCESS) {
ERROR("Error encoding UCI\n");
return SRSLTE_ERROR;
}
// Encode PUCCH
switch (resource->format) {
case SRSLTE_PUCCH_NR_FORMAT_2:
break;
case SRSLTE_PUCCH_NR_FORMAT_3:
case SRSLTE_PUCCH_NR_FORMAT_4:
ERROR("Not implemented\n");
return SRSLTE_ERROR;
default:
case SRSLTE_PUCCH_NR_FORMAT_ERROR:
ERROR("Invalid format\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}

View File

@ -36,7 +36,7 @@ static uint32_t starting_symbol_stride = 4;
static int test_pucch_format0(srslte_pucch_nr_t* pucch, const srslte_pucch_nr_common_cfg_t* cfg, cf_t* slot_symbols)
{
srslte_dl_slot_cfg_t slot = {};
srslte_pucch_nr_resource_format0_t resource = {};
srslte_pucch_nr_resource_t resource = {};
for (slot.idx = 0; slot.idx < SRSLTE_NSLOTS_PER_FRAME_NR(carrier.numerology); slot.idx++) {
for (resource.starting_prb = 0; resource.starting_prb < carrier.nof_prb;
@ -84,7 +84,7 @@ static int test_pucch_format1(srslte_pucch_nr_t* pucch,
cf_t* slot_symbols)
{
srslte_dl_slot_cfg_t slot = {};
srslte_pucch_nr_resource_format1_t resource = {};
srslte_pucch_nr_resource_t resource = {};
for (slot.idx = 0; slot.idx < SRSLTE_NSLOTS_PER_FRAME_NR(carrier.numerology); slot.idx++) {
for (resource.starting_prb = 0; resource.starting_prb < carrier.nof_prb;
@ -182,7 +182,8 @@ int main(int argc, char** argv)
goto clean_exit;
}
if (srslte_pucch_nr_init(&pucch) < SRSLTE_SUCCESS) {
srslte_pucch_nr_args_t pucch_args = {};
if (srslte_pucch_nr_init(&pucch, &pucch_args) < SRSLTE_SUCCESS) {
ERROR("PUCCH init\n");
goto clean_exit;
}

View File

@ -14,13 +14,15 @@
#include "srslte/phy/fec/block/block.h"
#include "srslte/phy/fec/polar/polar_chanalloc.h"
#include "srslte/phy/phch/uci_cfg.h"
#include "srslte/phy/utils/bit.h"
#include "srslte/phy/utils/vector.h"
// TS 38.212 section 5.2.1 Polar coding: The value of A is no larger than 1706.
#define UCI_NR_MAX_A 1906U
#define UCI_NR_MAX_A 1706U
#define UCI_NR_MAX_L 11U
#define UCI_NR_POLAR_MAX 2048U
#define UCI_NR_POLAR_RM_IBIL 0
#define UCI_NR_BLOCK_CORR_THRESHOLD 0.5f
int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args)
{
@ -29,9 +31,11 @@ int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args)
}
srslte_polar_encoder_type_t polar_encoder_type = SRSLTE_POLAR_ENCODER_PIPELINED;
srslte_polar_decoder_type_t polar_decoder_type = SRSLTE_POLAR_DECODER_SSC_C;
#ifdef LV_HAVE_AVX2
if (!args->disable_simd) {
polar_encoder_type = SRSLTE_POLAR_ENCODER_AVX2;
polar_decoder_type = SRSLTE_POLAR_DECODER_SSC_C_AVX2;
}
#endif // LV_HAVE_AVX2
@ -40,6 +44,11 @@ int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args)
return SRSLTE_ERROR;
}
if (srslte_polar_decoder_init(&q->decoder, polar_decoder_type, NMAX_LOG) < SRSLTE_SUCCESS) {
ERROR("Initialising polar encoder\n");
return SRSLTE_ERROR;
}
if (srslte_polar_rm_tx_init(&q->rm) < SRSLTE_SUCCESS) {
ERROR("Initialising polar RM\n");
return SRSLTE_ERROR;
@ -91,6 +100,7 @@ void srslte_uci_nr_free(srslte_uci_nr_t* q)
}
srslte_polar_encoder_free(&q->encoder);
srslte_polar_decoder_free(&q->decoder);
if (q->bit_sequence != NULL) {
free(q->bit_sequence);
@ -108,8 +118,7 @@ void srslte_uci_nr_free(srslte_uci_nr_t* q)
SRSLTE_MEM_ZERO(q, srslte_uci_nr_t, 1);
}
static int
uci_nr_sequence_generation_ack_sr(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence)
static int uci_nr_pack_ack_sr(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence)
{
int A = 0;
@ -124,12 +133,62 @@ uci_nr_sequence_generation_ack_sr(const srslte_uci_cfg_nr_t* cfg, const srslte_u
return A;
}
static int
uci_nr_sequence_generation(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence)
static int uci_nr_unpack_ack_sr(const srslte_uci_cfg_nr_t* cfg, const uint8_t* sequence, srslte_uci_value_nr_t* value)
{
int A = 0;
// Append ACK bits
srslte_vec_u8_copy(value->ack, &sequence[A], cfg->o_ack);
A += cfg->o_ack;
// Append SR bits
srslte_vec_u8_copy(value->sr, &sequence[A], cfg->o_sr);
A += cfg->o_sr;
return A;
}
static int uci_nr_A(const srslte_uci_cfg_nr_t* cfg)
{
// 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation
if (cfg->o_csi1 == 0 && cfg->o_csi2 == 0) {
return uci_nr_sequence_generation_ack_sr(cfg, value, sequence);
return cfg->o_ack + cfg->o_sr;
}
// 6.3.1.1.2 CSI only
if (cfg->o_ack == 0 && cfg->o_sr == 0) {
ERROR("CSI only are not implemented\n");
return SRSLTE_ERROR;
}
// 6.3.1.1.3 HARQ-ACK/SR and CSI
ERROR("HARQ-ACK/SR and CSI encoding are not implemented\n");
return SRSLTE_ERROR;
}
static int uci_nr_packing(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence)
{
// 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation
if (cfg->o_csi1 == 0 && cfg->o_csi2 == 0) {
return uci_nr_pack_ack_sr(cfg, value, sequence);
}
// 6.3.1.1.2 CSI only
if (cfg->o_ack == 0 && cfg->o_sr == 0) {
ERROR("CSI only are not implemented\n");
return SRSLTE_ERROR;
}
// 6.3.1.1.3 HARQ-ACK/SR and CSI
ERROR("HARQ-ACK/SR and CSI encoding are not implemented\n");
return SRSLTE_ERROR;
}
static int uci_nr_unpacking(const srslte_uci_cfg_nr_t* cfg, const uint8_t* sequence, srslte_uci_value_nr_t* value)
{
// 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation
if (cfg->o_csi1 == 0 && cfg->o_csi2 == 0) {
return uci_nr_unpack_ack_sr(cfg, sequence, value);
}
// 6.3.1.1.2 CSI only
@ -307,10 +366,40 @@ uci_nr_encode_3_11_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint3
return E;
}
static int uci_nr_decode_3_11_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)
{
// Check E for avoiding zero division
if (E < 1) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Compute average LLR power
float pwr = sqrtf(srslte_vec_avg_power_bf(llr, E));
if (!isnormal(pwr)) {
return SRSLTE_ERROR;
}
// Decode
float corr = (float)srslte_block_decode_i8(llr, E, q->bit_sequence, A);
// Normalise correlation
corr /= sqrtf(pwr) * E;
// Take decoded decision with threshold
*decoded_ok = (corr > UCI_NR_BLOCK_CORR_THRESHOLD);
return SRSLTE_SUCCESS;
}
#define CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN))
static int
uci_nr_encode_11_1906_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint32_t A, uint8_t* o, uint32_t E_uci)
uci_nr_encode_11_1706_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint32_t A, uint8_t* o, uint32_t E_uci)
{
// If ( A ≥ 360 and E ≥ 1088 ) or if A ≥ 1013 , I seg = 1 ; otherwise I seg = 0
uint32_t I_seg = 0;
@ -342,7 +431,7 @@ uci_nr_encode_11_1906_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, ui
for (uint32_t r = 0, s = 0; r < C; r++) {
uint32_t k = 0;
// Suffix A_prime - A zeros for the first CB only
// Prefix (A_prime - A) zeros for the first CB only
if (r == 0) {
for (uint32_t i = 0; i < (A_prime - A); i++) {
q->c[k++] = 0;
@ -372,18 +461,92 @@ uci_nr_encode_11_1906_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, ui
return E_uci;
}
int uci_nr_encode(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* uci_cfg,
const srslte_uci_value_nr_t* uci_value,
uint8_t* o,
uint32_t E_uci)
static int uci_nr_decode_11_1706_bit(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* cfg,
uint32_t A,
const int8_t* llr,
uint32_t E_uci,
bool* decoded_ok)
{
*decoded_ok = true;
// If ( A ≥ 360 and E ≥ 1088 ) or if A ≥ 1013 , I seg = 1 ; otherwise I seg = 0
uint32_t I_seg = 0;
if ((A >= 360 && E_uci >= 1088) || A >= 1013) {
I_seg = 1;
}
// Select CRC
srslte_crc_t* crc = &q->crc6;
if (A >= 20) {
crc = &q->crc11;
}
// Segmentation
uint32_t C = 1;
if (I_seg == 1) {
C = 2;
}
uint32_t A_prime = CEIL(A, C) * C;
// Get polar code
uint32_t K_r = A_prime / C + crc->order;
uint32_t E_r = E_uci / C;
if (srslte_polar_code_get(&q->code, K_r, E_r, 9U) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
// Write codeword
for (uint32_t r = 0, s = 0; r < C; r++) {
uint32_t k = 0;
// Undo rate matching
int8_t* d = (int8_t*)q->d;
srslte_polar_rm_rx_c(&q->rm, &llr[E_r * r], d, q->code.n, E_r, K_r, UCI_NR_POLAR_RM_IBIL);
// Decode bits
if (srslte_polar_decoder_decode_c(&q->decoder, d, q->allocated, q->code.n, q->code.F_set, q->code.F_set_size) <
SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
// Undo channel allocation
srslte_polar_chanalloc_rx(q->allocated, q->c, q->code.K, q->code.nPC, q->code.K_set, q->code.PC_set);
//
uint8_t* ptr = &q->c[q->code.K - crc->order];
uint32_t checksum1 = srslte_crc_checksum(crc, q->c, q->code.K);
uint32_t checksum2 = srslte_bit_pack(&ptr, crc->order);
(*decoded_ok) = ((*decoded_ok) && (checksum1 == checksum2));
// Prefix (A_prime - A) zeros for the first CB only
if (r == 0) {
for (uint32_t i = 0; i < (A_prime - A); i++) {
k++;
}
}
// Load codeword bits
while (k < A_prime / C) {
q->bit_sequence[s++] = q->c[k++];
}
}
return SRSLTE_SUCCESS;
}
static int uci_nr_encode(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* uci_cfg,
const srslte_uci_value_nr_t* uci_value,
uint8_t* o,
uint32_t E_uci)
{
if (q == NULL || uci_cfg == NULL || uci_value == NULL || o == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// 6.3.1.1 UCI bit sequence generation
int A = uci_nr_sequence_generation(uci_cfg, uci_value, q->bit_sequence);
int A = uci_nr_packing(uci_cfg, uci_value, q->bit_sequence);
if (A < SRSLTE_SUCCESS) {
ERROR("Generating bit sequence");
return SRSLTE_ERROR;
@ -400,17 +563,60 @@ int uci_nr_encode(srslte_uci_nr_t* q,
}
// 5.3.3.3 Encoding of other small block lengths
if (A <= 11) {
if (A <= SRSLTE_FEC_BLOCK_MAX_NOF_BITS) {
return uci_nr_encode_3_11_bit(q, uci_cfg, A, o, E_uci);
}
// Encoding of other sizes up to 1906
if (A < UCI_NR_MAX_A) {
return uci_nr_encode_11_1906_bit(q, uci_cfg, A, o, E_uci);
return uci_nr_encode_11_1706_bit(q, uci_cfg, A, o, E_uci);
}
return SRSLTE_ERROR;
}
static int uci_nr_decode(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* uci_cfg,
const int8_t* llr,
uint32_t E_uci,
srslte_uci_value_nr_t* uci_value)
{
if (q == NULL || uci_cfg == NULL || uci_value == 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\n");
return SRSLTE_ERROR;
}
// Decode LLR
if (A == 1) {
ERROR("Not implemented\n");
} else if (A == 2) {
ERROR("Not implemented\n");
} else if (A <= 11) {
if (uci_nr_decode_3_11_bit(q, uci_cfg, A, llr, E_uci, &uci_value->valid) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
} else if (A < UCI_NR_MAX_A) {
if (uci_nr_decode_11_1706_bit(q, uci_cfg, A, llr, E_uci, &uci_value->valid) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
} else {
ERROR("Invalid number of bits (A=%d)\n", A);
}
// Unpack bits
if (uci_nr_unpacking(uci_cfg, q->bit_sequence, uci_value) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
// Implements TS 38.212 Table 6.3.1.4-1: Total rate matching output sequence length Etot
static int uci_nr_pucch_E_tot(const srslte_pucch_nr_resource_t* pucch_cfg, const srslte_uci_cfg_nr_t* uci_cfg)
{
@ -418,8 +624,15 @@ static int uci_nr_pucch_E_tot(const srslte_pucch_nr_resource_t* pucch_cfg, const
return SRSLTE_ERROR_INVALID_INPUTS;
}
switch (pucch_cfg->format) {
// Compute total number of bits
uint32_t nof_bits = uci_cfg->o_sr + uci_cfg->o_ack + uci_cfg->o_csi1 + uci_cfg->o_csi2;
switch (pucch_cfg->format) {
case SRSLTE_PUCCH_NR_FORMAT_1:
if (nof_bits <= 2) {
return nof_bits;
}
break;
case SRSLTE_PUCCH_NR_FORMAT_2:
if (uci_cfg->modulation == SRSLTE_MOD_QPSK) {
return (int)(16 * pucch_cfg->nof_symbols * pucch_cfg->nof_prb);
@ -482,3 +695,23 @@ int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q,
return uci_nr_encode(q, uci_cfg, value, o, E_uci);
}
int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
const srslte_pucch_nr_resource_t* pucch_resource_cfg,
const srslte_uci_cfg_nr_t* uci_cfg,
const int8_t* llr,
srslte_uci_value_nr_t* value)
{
int E_tot = uci_nr_pucch_E_tot(pucch_resource_cfg, uci_cfg);
if (E_tot < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
int E_uci = uci_nr_pucch_E_uci(pucch_resource_cfg, uci_cfg, E_tot);
if (E_uci < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
return uci_nr_decode(q, uci_cfg, llr, E_uci, value);
}

View File

@ -543,6 +543,28 @@ float srslte_vec_avg_power_sf(const int16_t* x, const uint32_t len)
return acc;
}
float srslte_vec_avg_power_bf(const int8_t* x, const uint32_t len)
{
// Accumulator
float acc = 0.0f;
for (uint32_t i = 0; i < len; i++) {
// Read value and typecast to float
float t = (float)x[i];
// Square value
acc += t * t;
}
// Do average
if (len) {
acc /= len;
}
// Return accumulated value
return acc;
}
// Correlation assumes zero-mean x and y
float srslte_vec_corr_ccc(const cf_t* x, cf_t* y, const uint32_t len)
{