mirror of https://github.com/PentHertz/srsLTE.git
More NR-PUCCH support
This commit is contained in:
parent
697bdb4d6d
commit
4d96cf4a41
|
@ -31,7 +31,7 @@ SRSLTE_API int srslte_dmrs_pucch_format1_put(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,
|
||||
const srslte_pucch_nr_resource_format1_t* resource,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
cf_t* slot_symbols);
|
||||
|
||||
/**
|
||||
|
@ -49,7 +49,7 @@ SRSLTE_API int srslte_dmrs_pucch_format1_estimate(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,
|
||||
const srslte_pucch_nr_resource_format1_t* resource,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
const cf_t* slot_symbols,
|
||||
srslte_chest_ul_res_t* res);
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
@ -256,7 +175,7 @@ SRSLTE_API int srslte_pucch_nr_format1_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,
|
||||
const srslte_pucch_nr_resource_format1_t* resource,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
uint8_t* b,
|
||||
uint32_t nof_bits,
|
||||
cf_t* slot_symbols);
|
||||
|
@ -278,7 +197,7 @@ SRSLTE_API int srslte_pucch_nr_format1_decode(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,
|
||||
const srslte_pucch_nr_resource_format1_t* resource,
|
||||
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],
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
@ -88,7 +88,7 @@ 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,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
cf_t* slot_symbols)
|
||||
{
|
||||
|
||||
|
@ -155,7 +155,7 @@ int srslte_dmrs_pucch_format1_estimate(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,
|
||||
const srslte_pucch_nr_resource_format1_t* resource,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
const cf_t* slot_symbols,
|
||||
srslte_chest_ul_res_t* res)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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) {
|
||||
|
@ -373,7 +341,7 @@ 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,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
uint8_t* b,
|
||||
uint32_t nof_bits,
|
||||
cf_t* slot_symbols)
|
||||
|
@ -454,7 +422,7 @@ 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,
|
||||
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],
|
||||
|
@ -462,10 +430,6 @@ int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q,
|
|||
{
|
||||
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;
|
||||
|
@ -535,3 +499,39 @@ int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q,
|
|||
|
||||
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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,7 +461,81 @@ 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,
|
||||
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,
|
||||
|
@ -383,7 +546,7 @@ int uci_nr_encode(srslte_uci_nr_t* q,
|
|||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue