Apply minor comments in NR-PUCCH

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent 4c6944b883
commit 4fe34b5e5b

@ -33,6 +33,7 @@
#define SRSLTE_PUCCH_NR_FORMAT1_MIN_NSYMB 4 #define SRSLTE_PUCCH_NR_FORMAT1_MIN_NSYMB 4
#define SRSLTE_PUCCH_NR_FORMAT1_MAX_NSYMB 14 #define SRSLTE_PUCCH_NR_FORMAT1_MAX_NSYMB 14
#define SRSLTE_PUCCH_NR_FORMAT1_MAX_STARTSYMB 10 #define SRSLTE_PUCCH_NR_FORMAT1_MAX_STARTSYMB 10
#define SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS 2
/** /**
* NR-PUCCH Format 2 ranges * NR-PUCCH Format 2 ranges
@ -42,6 +43,7 @@
#define SRSLTE_PUCCH_NR_FORMAT2_MIN_NSYMB 1 #define SRSLTE_PUCCH_NR_FORMAT2_MIN_NSYMB 1
#define SRSLTE_PUCCH_NR_FORMAT2_MAX_NSYMB 2 #define SRSLTE_PUCCH_NR_FORMAT2_MAX_NSYMB 2
#define SRSLTE_PUCCH_NR_FORMAT2_MAX_STARTSYMB 13 #define SRSLTE_PUCCH_NR_FORMAT2_MAX_STARTSYMB 13
#define SRSLTE_PUCCH_NR_FORMAT2_MIN_NOF_BITS 3
/** /**
* NR-PUCCH Format 3 ranges * NR-PUCCH Format 3 ranges

@ -24,11 +24,6 @@
*/ */
#define SRSLTE_PUCCH_NR_FORMAT1_N_MAX 7 #define SRSLTE_PUCCH_NR_FORMAT1_N_MAX 7
/**
* @brief Maximum number of bit that NR-PUCCH format 1 can carry
*/
#define SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS 2
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_uci_nr_args_t uci; srslte_uci_nr_args_t uci;
uint32_t max_nof_prb; uint32_t max_nof_prb;

@ -18,8 +18,9 @@
#include "uci_cfg_nr.h" #include "uci_cfg_nr.h"
/** /**
* @brief * @brief Calculates the minimum number of PRB required for transmitting NR-PUCCH Format 2, 3 or 4
* @return * @remark Based in TS 38.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR in a PUCCH
* @return The number of PRB if the provided configuration is valid, SRSLTE_ERROR code otherwise
*/ */
SRSLTE_API int srslte_ra_ul_nr_pucch_format_2_3_min_prb(const srslte_pucch_nr_resource_t* resource, SRSLTE_API int srslte_ra_ul_nr_pucch_format_2_3_min_prb(const srslte_pucch_nr_resource_t* resource,
const srslte_uci_cfg_nr_t* uci_cfg); const srslte_uci_cfg_nr_t* uci_cfg);

@ -17,26 +17,49 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
/**
* @brief Maximum number of HARQ ACK feedback bits that can be carried in Uplink Control Information (UCI) message
*/
#define SRSLTE_UCI_NR_MAX_ACK_BITS 360 #define SRSLTE_UCI_NR_MAX_ACK_BITS 360
/**
* @brief Maximum number of Scheduling Request (SR) bits that can be carried in Uplink Control Information (UCI) message
*/
#define SRSLTE_UCI_NR_MAX_SR_BITS 10 #define SRSLTE_UCI_NR_MAX_SR_BITS 10
/**
* @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 10
/**
* @brief Maximum number of Channel State Information part 2 (CSI2) bits that can be carried in Uplink Control
* Information (UCI) message
*/
#define SRSLTE_UCI_NR_MAX_CSI2_BITS 10 #define SRSLTE_UCI_NR_MAX_CSI2_BITS 10
/**
* @brief Uplink Control Information (UCI) message configuration
*/
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint32_t o_ack; ///< Number of HARQ-ACK bits uint32_t o_ack; ///< Number of HARQ-ACK bits
uint32_t o_sr; ///< Number of SR bits uint32_t o_sr; ///< Number of SR bits
uint32_t o_csi1; ///< Number of CSI1 report number of bits uint32_t o_csi1; ///< Number of CSI1 report number of bits
uint32_t o_csi2; ///< Number of CSI2 report number of bits uint32_t o_csi2; ///< Number of CSI2 report number of bits
srslte_mod_t modulation; ///< Modulation srslte_mod_t modulation; ///< Modulation (PUSCH only)
uint16_t rnti; ///< RNTI uint16_t rnti; ///< RNTI
} srslte_uci_cfg_nr_t; } srslte_uci_cfg_nr_t;
/**
* @brief Uplink Control Information (UCI) message packed information
*/
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t ack[SRSLTE_UCI_NR_MAX_ACK_BITS]; uint8_t ack[SRSLTE_UCI_NR_MAX_ACK_BITS]; ///< HARQ ACK feedback bits
uint8_t sr[SRSLTE_UCI_NR_MAX_SR_BITS]; uint8_t sr[SRSLTE_UCI_NR_MAX_SR_BITS]; ///< Scheduling Request bits
uint8_t csi1[SRSLTE_UCI_NR_MAX_CSI1_BITS]; uint8_t csi1[SRSLTE_UCI_NR_MAX_CSI1_BITS]; ///< Channel State Information part 1
uint8_t csi2[SRSLTE_UCI_NR_MAX_CSI2_BITS]; uint8_t csi2[SRSLTE_UCI_NR_MAX_CSI2_BITS]; ///< Channel State Information part 2
bool valid; bool valid; ///< Indicates whether the message has been decoded successfully, ignored in the transmitter
} srslte_uci_value_nr_t; } srslte_uci_value_nr_t;
#endif // SRSLTE_UCI_CFG_NR_H #endif // SRSLTE_UCI_CFG_NR_H

@ -24,8 +24,12 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
/**
* @brief NR-UCI Encoder/decoder initialization arguments
*/
typedef struct { typedef struct {
bool disable_simd; bool disable_simd; ///< Disable Polar code SIMD
float block_code_threshold; ///< Set normalised block code threshold (receiver only)
} srslte_uci_nr_args_t; } srslte_uci_nr_args_t;
typedef struct { typedef struct {
@ -40,10 +44,20 @@ typedef struct {
uint8_t* c; ///< UCI code-block prior encoding or after decoding uint8_t* c; ///< UCI code-block prior encoding or after decoding
uint8_t* allocated; ///< Polar code intermediate uint8_t* allocated; ///< Polar code intermediate
uint8_t* d; ///< Polar code encoded intermediate uint8_t* d; ///< Polar code encoded intermediate
float block_code_threshold;
} srslte_uci_nr_t; } srslte_uci_nr_t;
/**
* @brief Calculates the number of bits carried by PUCCH formats 2, 3 and 4 from the PUCCH resource
* @remark Defined in TS 38.212 Table 6.3.1.4-1: Total rate matching output sequence length Etot
* @param resource PUCCH format 2, 3 or 4 Resource provided by upper layers
* @return The number of bits if the provided resource is valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_uci_nr_pucch_format_2_3_4_E(const srslte_pucch_nr_resource_t* resource);
/** /**
* @brief Calculates in advance how many CRC bits will be appended for a given amount of UCI bits (A) * @brief Calculates in advance how many CRC bits will be appended for a given amount of UCI bits (A)
* @remark Defined in TS 38.212 section 6.3.1.2 Code block segmentation and CRC attachment
* @param A Number of UCI bits to transmit * @param A Number of UCI bits to transmit
*/ */
SRSLTE_API uint32_t srslte_uci_nr_crc_len(uint32_t A); SRSLTE_API uint32_t srslte_uci_nr_crc_len(uint32_t A);

@ -380,7 +380,7 @@ int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q,
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
if (nof_bits > 2) { if (nof_bits > SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS) {
ERROR("Invalid number of bits (%d)\n", nof_bits); ERROR("Invalid number of bits (%d)\n", nof_bits);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -458,7 +458,7 @@ int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q,
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
if (nof_bits > 2) { if (nof_bits > SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS) {
ERROR("Invalid number of bits (%d)\n", nof_bits); ERROR("Invalid number of bits (%d)\n", nof_bits);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -544,7 +544,7 @@ static int pucch_nr_format2_encode(srslte_pucch_nr_t* q,
} }
// Calculate number of encoded symbols // Calculate number of encoded symbols
uint32_t E = 16 * resource->nof_symbols * resource->nof_prb; uint32_t E = srslte_uci_nr_pucch_format_2_3_4_E(resource);
// 6.3.2.5.1 Scrambling // 6.3.2.5.1 Scrambling
uint32_t cinit = pucch_nr_format2_cinit(cfg, uci_cfg); uint32_t cinit = pucch_nr_format2_cinit(cfg, uci_cfg);
@ -584,7 +584,7 @@ static int pucch_nr_format2_decode(srslte_pucch_nr_t* q,
} }
// Calculate number of encoded symbols // Calculate number of encoded symbols
uint32_t E = 16 * resource->nof_symbols * resource->nof_prb; uint32_t E = srslte_uci_nr_pucch_format_2_3_4_E(resource);
// Undo mapping to physical resources // Undo mapping to physical resources
uint32_t l_start = resource->start_symbol_idx; uint32_t l_start = resource->start_symbol_idx;

@ -34,7 +34,7 @@ static uint32_t starting_prb_stride = 4;
static uint32_t starting_symbol_stride = 4; static uint32_t starting_symbol_stride = 4;
static srslte_random_t random_gen = NULL; static srslte_random_t random_gen = NULL;
static int format = -1; static int format = -1;
static float snr_db = 30.0f; static float snr_db = 20.0f;
static srslte_channel_awgn_t awgn = {}; static srslte_channel_awgn_t awgn = {};
static int test_pucch_format0(srslte_pucch_nr_t* pucch, const srslte_pucch_nr_common_cfg_t* cfg, cf_t* slot_symbols) static int test_pucch_format0(srslte_pucch_nr_t* pucch, const srslte_pucch_nr_common_cfg_t* cfg, cf_t* slot_symbols)
@ -176,15 +176,20 @@ static int test_pucch_format2(srslte_pucch_nr_t* pucch,
SRSLTE_MIN(SRSLTE_PUCCH_NR_FORMAT2_MAX_STARTSYMB, SRSLTE_NSYMB_PER_SLOT_NR - resource.nof_symbols); SRSLTE_MIN(SRSLTE_PUCCH_NR_FORMAT2_MAX_STARTSYMB, SRSLTE_NSYMB_PER_SLOT_NR - resource.nof_symbols);
resource.start_symbol_idx += starting_symbol_stride) { resource.start_symbol_idx += starting_symbol_stride) {
// Maximum code rate is reserved
for (resource.max_code_rate = 0; resource.max_code_rate < SRSLTE_PUCCH_NR_MAX_CODE_RATE;
resource.max_code_rate++) {
srslte_uci_cfg_nr_t uci_cfg = {}; srslte_uci_cfg_nr_t uci_cfg = {};
for (uci_cfg.o_ack = 12; uci_cfg.o_ack <= SRSLTE_UCI_NR_MAX_ACK_BITS; uci_cfg.o_ack++) { for (uci_cfg.o_ack = SRSLTE_PUCCH_NR_FORMAT2_MIN_NOF_BITS; uci_cfg.o_ack <= SRSLTE_UCI_NR_MAX_ACK_BITS;
uci_cfg.o_ack++) {
srslte_uci_value_nr_t uci_value = {}; srslte_uci_value_nr_t uci_value = {};
// Maximum code rate is reserved
uint32_t max_code_rate_end = SRSLTE_PUCCH_NR_MAX_CODE_RATE;
if (uci_cfg.o_ack == 11) {
max_code_rate_end = SRSLTE_PUCCH_NR_MAX_CODE_RATE - 1;
}
for (resource.max_code_rate = 0; resource.max_code_rate < max_code_rate_end; resource.max_code_rate++) {
// Skip case if not enough PRB are used // Skip case if not enough PRB are used
int min_nof_prb = srslte_ra_ul_nr_pucch_format_2_3_min_prb(&resource, &uci_cfg); int min_nof_prb = srslte_ra_ul_nr_pucch_format_2_3_min_prb(&resource, &uci_cfg);
TESTASSERT(min_nof_prb > SRSLTE_SUCCESS); TESTASSERT(min_nof_prb > SRSLTE_SUCCESS);
@ -217,9 +222,13 @@ static int test_pucch_format2(srslte_pucch_nr_t* pucch,
// Estimate channel // Estimate channel
TESTASSERT(srslte_dmrs_pucch_format2_estimate( TESTASSERT(srslte_dmrs_pucch_format2_estimate(
pucch, &carrier, cfg, &slot, &resource, slot_symbols, chest_res) == SRSLTE_SUCCESS); pucch, &carrier, cfg, &slot, &resource, slot_symbols, chest_res) == SRSLTE_SUCCESS);
INFO("RSRP=%+.2f; EPRE=%+.2f; SNR=%+.2f;\n",
chest_res->rsrp_dBfs,
chest_res->epre_dBfs,
chest_res->snr_db);
TESTASSERT(fabsf(chest_res->rsrp_dBfs - 0.0f) < 3.0f); TESTASSERT(fabsf(chest_res->rsrp_dBfs - 0.0f) < 3.0f);
TESTASSERT(fabsf(chest_res->epre_dBfs - 0.0f) < 3.0f); TESTASSERT(fabsf(chest_res->epre_dBfs - 0.0f) < 3.0f);
TESTASSERT(fabsf(chest_res->snr_db - snr_db) < 10.0f); TESTASSERT(fabsf(chest_res->snr_db - snr_db) < 20.0f);
// Decode PUCCH // Decode PUCCH
srslte_uci_value_nr_t uci_value_rx = {}; srslte_uci_value_nr_t uci_value_rx = {};

@ -26,7 +26,7 @@
#define UCI_NR_POLAR_MAX 2048U #define UCI_NR_POLAR_MAX 2048U
#define UCI_NR_POLAR_RM_IBIL 0 #define UCI_NR_POLAR_RM_IBIL 0
#define UCI_NR_PUCCH_POLAR_N_MAX 10 #define UCI_NR_PUCCH_POLAR_N_MAX 10
#define UCI_NR_BLOCK_CORR_THRESHOLD 0.5f #define UCI_NR_BLOCK_DEFAULT_CORR_THRESHOLD 0.5f
uint32_t srslte_uci_nr_crc_len(uint32_t A) uint32_t srslte_uci_nr_crc_len(uint32_t A)
{ {
@ -109,6 +109,12 @@ int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args)
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (isnormal(args->block_code_threshold)) {
q->block_code_threshold = args->block_code_threshold;
} else {
q->block_code_threshold = UCI_NR_BLOCK_DEFAULT_CORR_THRESHOLD;
}
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -410,25 +416,38 @@ static int uci_nr_decode_3_11_bit(srslte_uci_nr_t* q,
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
// Compute average LLR power if (A == 11 && E <= 16) {
float pwr = sqrtf(srslte_vec_avg_power_bf(llr, E)); ERROR("NR-UCI Impossible to decode A=%d; E=%d\n", A, E);
if (!isnormal(pwr)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { // Compute average LLR power
UCI_NR_INFO_RX("Block decoding NR-UCI llr="); float pwr = srslte_vec_avg_power_bf(llr, E);
srslte_vec_fprint_bs(stdout, llr, E); if (!isnormal(pwr)) {
return SRSLTE_ERROR;
} }
// Decode // Decode
float corr = (float)srslte_block_decode_i8(llr, E, q->bit_sequence, A); float corr = (float)srslte_block_decode_i8(llr, E, q->bit_sequence, A);
// Normalise correlation // Normalise correlation
corr /= sqrtf(pwr) * E; float norm_corr = corr / (sqrtf(pwr) * E);
// Take decoded decision with threshold // Take decoded decision with threshold
*decoded_ok = (corr > UCI_NR_BLOCK_CORR_THRESHOLD); *decoded_ok = (corr > q->block_code_threshold);
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) {
UCI_NR_INFO_RX("Block decoding NR-UCI llr=");
srslte_vec_fprint_bs(stdout, llr, E);
UCI_NR_INFO_RX("Block decoding NR-UCI A=%d; E=%d; pwr=%f; corr=%f; norm=%f; thr=%f; %s\n",
A,
E,
pwr,
corr,
norm_corr,
q->block_code_threshold,
*decoded_ok ? "OK" : "KO");
}
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -687,38 +706,31 @@ static int uci_nr_decode(srslte_uci_nr_t* q,
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
// Implements TS 38.212 Table 6.3.1.4-1: Total rate matching output sequence length Etot int srslte_uci_nr_pucch_format_2_3_4_E(const srslte_pucch_nr_resource_t* resource)
static int uci_nr_pucch_E_tot(const srslte_pucch_nr_resource_t* pucch_cfg, const srslte_uci_cfg_nr_t* uci_cfg)
{ {
if (pucch_cfg == NULL || uci_cfg == NULL) { if (resource == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
switch (pucch_cfg->format) { switch (resource->format) {
case SRSLTE_PUCCH_NR_FORMAT_2: case SRSLTE_PUCCH_NR_FORMAT_2:
return (int)(16 * pucch_cfg->nof_symbols * pucch_cfg->nof_prb); return (int)(16 * resource->nof_symbols * resource->nof_prb);
case SRSLTE_PUCCH_NR_FORMAT_3: case SRSLTE_PUCCH_NR_FORMAT_3:
if (uci_cfg->modulation == SRSLTE_MOD_QPSK) { if (!resource->enable_pi_bpsk) {
return (int)(24 * pucch_cfg->nof_symbols * pucch_cfg->nof_prb); return (int)(24 * resource->nof_symbols * resource->nof_prb);
} }
if (uci_cfg->modulation == SRSLTE_MOD_BPSK) { return (int)(12 * resource->nof_symbols * resource->nof_prb);
return (int)(12 * pucch_cfg->nof_symbols * pucch_cfg->nof_prb);
}
break;
case SRSLTE_PUCCH_NR_FORMAT_4: case SRSLTE_PUCCH_NR_FORMAT_4:
if (pucch_cfg->occ_lenth != 1 && pucch_cfg->occ_lenth != 2) { if (resource->occ_lenth != 1 && resource->occ_lenth != 2) {
ERROR("Invalid spreading factor (%d)\n", pucch_cfg->occ_lenth); ERROR("Invalid spreading factor (%d)\n", resource->occ_lenth);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (uci_cfg->modulation == SRSLTE_MOD_QPSK) { if (!resource->enable_pi_bpsk) {
return (int)(24 * pucch_cfg->nof_symbols / pucch_cfg->occ_lenth); return (int)(24 * resource->nof_symbols / resource->occ_lenth);
}
if (uci_cfg->modulation == SRSLTE_MOD_BPSK) {
return (int)(12 * pucch_cfg->nof_symbols / pucch_cfg->occ_lenth);
} }
break; return (int)(12 * resource->nof_symbols / resource->occ_lenth);
default: default:
return SRSLTE_ERROR; ERROR("Invalid case\n");
} }
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -741,7 +753,7 @@ int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q,
const srslte_uci_value_nr_t* value, const srslte_uci_value_nr_t* value,
uint8_t* o) uint8_t* o)
{ {
int E_tot = uci_nr_pucch_E_tot(pucch_resource_cfg, uci_cfg); int E_tot = srslte_uci_nr_pucch_format_2_3_4_E(pucch_resource_cfg);
if (E_tot < SRSLTE_SUCCESS) { if (E_tot < SRSLTE_SUCCESS) {
ERROR("Error calculating number of bits\n"); ERROR("Error calculating number of bits\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -762,7 +774,7 @@ int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
int8_t* llr, int8_t* llr,
srslte_uci_value_nr_t* value) srslte_uci_value_nr_t* value)
{ {
int E_tot = uci_nr_pucch_E_tot(pucch_resource_cfg, uci_cfg); int E_tot = srslte_uci_nr_pucch_format_2_3_4_E(pucch_resource_cfg);
if (E_tot < SRSLTE_SUCCESS) { if (E_tot < SRSLTE_SUCCESS) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }

Loading…
Cancel
Save