From ae3c5ec7d0dd176b73e8ca103c84b7526ab8b9ba Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 8 Jan 2021 10:47:14 +0100 Subject: [PATCH] Moved all block code (32, O/K) to FEC block Fix missing header Fix missing header --- lib/include/srslte/phy/fec/block/block.h | 65 +++++++++++++ lib/include/srslte/phy/phch/uci.h | 2 - lib/src/phy/fec/block/block.c | 81 ++++++++--------- lib/src/phy/fec/block/test/CMakeLists.txt | 4 +- lib/src/phy/fec/block/test/block_test.c | 84 +++++++++-------- lib/src/phy/phch/uci.c | 106 +++------------------- 6 files changed, 168 insertions(+), 174 deletions(-) create mode 100644 lib/include/srslte/phy/fec/block/block.h diff --git a/lib/include/srslte/phy/fec/block/block.h b/lib/include/srslte/phy/fec/block/block.h new file mode 100644 index 000000000..640acc5f3 --- /dev/null +++ b/lib/include/srslte/phy/fec/block/block.h @@ -0,0 +1,65 @@ +/** + * + * \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_BLOCK_H +#define SRSLTE_BLOCK_H + +#include "srslte/config.h" +#include +#include + +/** + * @brief Maximum number of bits that can be encoded + */ +#define SRSLTE_FEC_BLOCK_MAX_NOF_BITS 11U + +/** + * @brief Block coding output complete length + */ +#define SRSLTE_FEC_BLOCK_SIZE 32U + +/** + * @brief Encodes unpacked data using Reed–Muller code block channel coding. + * + * @remark Described by 3GPP 36.212 section 5.2.3.3 for 4G/LTE + * @remark Described by 3GPP 38.212 section 5.3.3.3 for 5G/LTE + * + * @param[in] input provides unpacked bits to encode + * @param[in] input_len number of bits to encode, the maximum number of bits is SRSLTE_FEC_BLOCK_MAX_NOF_BITS + * @param[out] output points to the unpacked encoded data + * @param[in] output_len number of bits of encoded bits + */ +SRSLTE_API void srslte_block_encode(const uint8_t* input, uint32_t input_len, uint8_t* output, uint32_t output_len); + +/** + * @brief Decodes 16-bit signed data using Reed–Muller code block channel coding. + * + * @param[in] llr Provides received LLRs + * @param[in] nof_llr number of available LLRs + * @param[out] data Data destination to store unpacked received bits + * @param[in] data_len number of bits to decode, the maximum number of bits is SRSLTE_FEC_BLOCK_MAX_NOF_BITS + * @return Decoded bits correlation if provided arguments are valid, otherwise SRSLTE_ERROR code + */ +SRSLTE_API int32_t srslte_block_decode_i16(const int16_t* llr, uint32_t nof_llr, uint8_t* data, uint32_t data_len); + +/** + * @brief Decodes 8-bit signed data using Reed–Muller code block channel coding. + * + * @param[in] llr Provides received LLRs + * @param[in] nof_llr number of available LLRs + * @param[out] data Data destination to store unpacked received bits + * @param[in] data_len number of bits to decode, the maximum number of bits is SRSLTE_FEC_BLOCK_MAX_NOF_BITS + * @return Decoded bits correlation if provided arguments are valid, otherwise SRSLTE_ERROR code + */ +SRSLTE_API int32_t srslte_block_decode_i8(const int8_t* llr, uint32_t nof_llr, uint8_t* data, uint32_t data_len); + +#endif // SRSLTE_BLOCK_H diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index 9d5c45758..2fe03d433 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -39,8 +39,6 @@ typedef struct SRSLTE_API { uint8_t tmp_cqi[SRSLTE_UCI_MAX_CQI_LEN_PUSCH]; uint8_t encoded_cqi[3 * SRSLTE_UCI_MAX_CQI_LEN_PUSCH]; int16_t encoded_cqi_s[3 * SRSLTE_UCI_MAX_CQI_LEN_PUSCH]; - uint8_t* cqi_table[11]; - int16_t* cqi_table_s[11]; } srslte_uci_cqi_pusch_t; typedef struct SRSLTE_API { diff --git a/lib/src/phy/fec/block/block.c b/lib/src/phy/fec/block/block.c index 4bdebae98..4e473fd99 100644 --- a/lib/src/phy/fec/block/block.c +++ b/lib/src/phy/fec/block/block.c @@ -58,15 +58,23 @@ static inline uint8_t encode_M_basis_seq_u16(uint16_t w, uint32_t bit_idx) } #if USE_LUT -static block_llr_t M_basis_seq_b_lut[1U << SRSLTE_FEC_BLOCK_MAX_NOF_BITS][SRSLTE_FEC_BLOCK_SIZE]; +// Encoded unpacked table +static uint8_t block_unpacked_lut[1U << SRSLTE_FEC_BLOCK_MAX_NOF_BITS][SRSLTE_FEC_BLOCK_SIZE]; -// Initialization function, as the table does not change, it can be initialised as constructor +// LLR signed table +static block_llr_t block_llr_lut[1U << SRSLTE_FEC_BLOCK_MAX_NOF_BITS][SRSLTE_FEC_BLOCK_SIZE]; + +// Initialization function, as the table is read-only after initialization, it can be initialised from constructor __attribute__((constructor)) static void srslte_block_init() { for (uint32_t word = 0; word < (1U << SRSLTE_FEC_BLOCK_MAX_NOF_BITS); word++) { for (uint32_t i = 0; i < SRSLTE_FEC_BLOCK_SIZE; i++) { - // Encode guess word - M_basis_seq_b_lut[word][i] = encode_M_basis_seq_u16(word, i) * 2 - 1; + uint8_t e = encode_M_basis_seq_u16(word, i); + // Encoded unpacked byte + block_unpacked_lut[word][i] = e; + + // Encoded LLR + block_llr_lut[word][i] = (block_llr_t)e * 2 - 1; } } } @@ -74,16 +82,28 @@ __attribute__((constructor)) static void srslte_block_init() void srslte_block_encode(const uint8_t* input, uint32_t input_len, uint8_t* output, uint32_t output_len) { + if (!input || !output) { + ERROR("Invalid inputs\n"); + return; + } + // Limit number of input bits input_len = SRSLTE_MIN(input_len, SRSLTE_FEC_BLOCK_MAX_NOF_BITS); - // Pack input bits + // Pack input bits (reversed) uint16_t w = 0; for (uint32_t i = 0; i < input_len; i++) { w |= (input[i] & 1U) << i; } // Encode bits +#if USE_LUT + uint32_t i = 0; + for (; i < output_len / SRSLTE_FEC_BLOCK_SIZE; i++) { + srslte_vec_u8_copy(&output[i * SRSLTE_FEC_BLOCK_SIZE], block_unpacked_lut[w], SRSLTE_FEC_BLOCK_SIZE); + } + srslte_vec_u8_copy(&output[i * SRSLTE_FEC_BLOCK_SIZE], block_unpacked_lut[w], output_len % SRSLTE_FEC_BLOCK_SIZE); +#else // USE_LUT for (uint32_t i = 0; i < SRSLTE_MIN(output_len, SRSLTE_FEC_BLOCK_SIZE); i++) { output[i] = encode_M_basis_seq_u16(w, i); } @@ -92,9 +112,10 @@ void srslte_block_encode(const uint8_t* input, uint32_t input_len, uint8_t* outp for (uint32_t i = SRSLTE_FEC_BLOCK_SIZE; i < output_len; i++) { output[i] = output[i % SRSLTE_FEC_BLOCK_SIZE]; } +#endif // USE_LUT } -static int32_t srslte_block_decode(const block_llr_t llr[SRSLTE_FEC_BLOCK_SIZE], uint8_t* data, uint32_t data_len) +static int32_t block_decode(const block_llr_t* llr, uint8_t* data, uint32_t data_len) { int32_t max_corr = 0; //< Stores maximum correlation uint32_t max_data = 0; //< Stores the word for maximum correlation @@ -108,11 +129,9 @@ static int32_t srslte_block_decode(const block_llr_t llr[SRSLTE_FEC_BLOCK_SIZE], int32_t corr = 0; #if USE_LUT // Load sequence from LUT - block_llr_t* sequence = M_basis_seq_b_lut[guess]; - // Dot product for (uint32_t i = 0; i < SRSLTE_FEC_BLOCK_SIZE; i++) { - corr += llr[i] * sequence[i]; + corr += llr[i] * block_llr_lut[guess][i]; } #else for (uint32_t i = 0; i < SRSLTE_FEC_BLOCK_SIZE; i++) { @@ -128,7 +147,7 @@ static int32_t srslte_block_decode(const block_llr_t llr[SRSLTE_FEC_BLOCK_SIZE], } } - // Unpack + // Bit unpack (reversed) for (uint32_t i = 0; i < data_len; i++) { data[i] = (uint8_t)((max_data >> i) & 1U); } @@ -139,7 +158,7 @@ static int32_t srslte_block_decode(const block_llr_t llr[SRSLTE_FEC_BLOCK_SIZE], int32_t srslte_block_decode_i8(const int8_t* llr, uint32_t nof_llr, uint8_t* data, uint32_t data_len) { - block_llr_t llr_[SRSLTE_FEC_BLOCK_SIZE]; + block_llr_t llr_[SRSLTE_FEC_BLOCK_SIZE] = {}; // Return invalid inputs if data is not provided if (!llr || !data) { @@ -147,29 +166,17 @@ int32_t srslte_block_decode_i8(const int8_t* llr, uint32_t nof_llr, uint8_t* dat return SRSLTE_ERROR_INVALID_INPUTS; } - // Return invalid inputs if not enough LLR are provided - if (nof_llr < SRSLTE_FEC_BLOCK_SIZE) { - ERROR("Not enough LLR bits are provided %d. Required %d;\n", nof_llr, SRSLTE_FEC_BLOCK_SIZE); - return SRSLTE_ERROR_INVALID_INPUTS; - } - - // Load the minimum of LLRs - uint32_t i = 0; - for (; i < SRSLTE_FEC_BLOCK_SIZE; i++) { - llr_[i] = (block_llr_t)llr[i]; - } - - // Combine the rest of LLRs - for (; i < nof_llr; i++) { + // Accumulate all copies of the 32-length sequence + for (uint32_t i = 0; i < nof_llr; i++) { llr_[i % SRSLTE_FEC_BLOCK_SIZE] += (block_llr_t)llr[i]; } - return srslte_block_decode(llr_, data, data_len); + return block_decode(llr_, data, data_len); } int32_t srslte_block_decode_i16(const int16_t* llr, uint32_t nof_llr, uint8_t* data, uint32_t data_len) { - block_llr_t llr_[SRSLTE_FEC_BLOCK_SIZE]; + block_llr_t llr_[SRSLTE_FEC_BLOCK_SIZE] = {}; // Return invalid inputs if data is not provided if (!llr || !data) { @@ -177,22 +184,12 @@ int32_t srslte_block_decode_i16(const int16_t* llr, uint32_t nof_llr, uint8_t* d return SRSLTE_ERROR_INVALID_INPUTS; } - // Return invalid inputs if not enough LLR are provided - if (nof_llr < SRSLTE_FEC_BLOCK_SIZE) { - ERROR("Not enough LLR bits are provided %d. Required %d;\n", nof_llr, SRSLTE_FEC_BLOCK_SIZE); - return SRSLTE_ERROR_INVALID_INPUTS; - } - - // Load the minimum of LLRs + // Accumulate all copies of the 32-length sequence uint32_t i = 0; - for (; i < SRSLTE_FEC_BLOCK_SIZE; i++) { - llr_[i] = (block_llr_t)llr[i]; - } - - // Combine the rest of LLRs - for (; i < nof_llr; i++) { - llr_[i % SRSLTE_FEC_BLOCK_SIZE] += (block_llr_t)llr[i]; + for (; i < nof_llr / SRSLTE_FEC_BLOCK_SIZE; i++) { + srslte_vec_sum_sss(&llr[i * SRSLTE_FEC_BLOCK_SIZE], llr_, llr_, SRSLTE_FEC_BLOCK_SIZE); } + srslte_vec_sum_sss(&llr[i * SRSLTE_FEC_BLOCK_SIZE], llr_, llr_, nof_llr % SRSLTE_FEC_BLOCK_SIZE); - return srslte_block_decode(llr_, data, data_len); + return block_decode(llr_, data, data_len); } diff --git a/lib/src/phy/fec/block/test/CMakeLists.txt b/lib/src/phy/fec/block/test/CMakeLists.txt index cafbf16ca..89098f865 100644 --- a/lib/src/phy/fec/block/test/CMakeLists.txt +++ b/lib/src/phy/fec/block/test/CMakeLists.txt @@ -13,4 +13,6 @@ add_executable(block_test block_test.c) target_link_libraries(block_test srslte_phy) -add_test(block_test block_test) +add_test(block_test_20 block_test -E 20) +add_test(block_test_32 block_test -E 32) +add_test(block_test_48 block_test -E 48) diff --git a/lib/src/phy/fec/block/test/block_test.c b/lib/src/phy/fec/block/test/block_test.c index 2e38a5577..fdccfedaf 100644 --- a/lib/src/phy/fec/block/test/block_test.c +++ b/lib/src/phy/fec/block/test/block_test.c @@ -31,17 +31,21 @@ void usage(char* prog) { printf("Usage: %s [Rv]\n", prog); printf("\t-R Number of repetitions [Default %d]\n", nof_repetitions); + printf("\t-E Number of encoded bits [Default %d]\n", E); printf("\t-v increase verbose [Default %d]\n", srslte_verbose); } void parse_args(int argc, char** argv) { int opt; - while ((opt = getopt(argc, argv, "Rv")) != -1) { + while ((opt = getopt(argc, argv, "REv")) != -1) { switch (opt) { case 'R': nof_repetitions = (uint32_t)strtol(argv[optind], NULL, 10); break; + case 'E': + E = (uint32_t)strtol(argv[optind], NULL, 10); + break; case 'v': srslte_verbose++; break; @@ -54,50 +58,54 @@ void parse_args(int argc, char** argv) int test(uint32_t block_size) { - struct timeval t[3] = {}; - uint8_t tx[SRSLTE_FEC_BLOCK_MAX_NOF_BITS] = {}; - uint8_t rx[SRSLTE_FEC_BLOCK_MAX_NOF_BITS] = {}; - uint8_t encoded[SRSLTE_FEC_BLOCK_SIZE] = {}; - int16_t llr_i16[SRSLTE_FEC_BLOCK_SIZE] = {}; - int8_t llr_i8[SRSLTE_FEC_BLOCK_SIZE] = {}; - uint64_t t_encode_us = 0; - uint64_t t_decode_i16_us = 0; - uint64_t t_decode_i8_us = 0; + struct timeval t[3] = {}; + uint8_t tx[SRSLTE_FEC_BLOCK_MAX_NOF_BITS] = {}; + uint8_t rx[SRSLTE_FEC_BLOCK_MAX_NOF_BITS] = {}; + uint8_t encoded[4 * SRSLTE_FEC_BLOCK_SIZE] = {}; + int16_t llr_i16[4 * SRSLTE_FEC_BLOCK_SIZE] = {}; + int8_t llr_i8[4 * SRSLTE_FEC_BLOCK_SIZE] = {}; - for (uint32_t r = 0; r < nof_repetitions; r++) { - // Generate random data - for (uint32_t i = 0; i < block_size; i++) { - tx[i] = (uint8_t)srslte_random_uniform_int_dist(random_gen, 0, 1); - } + // Generate random data + for (uint32_t i = 0; i < block_size; i++) { + tx[i] = (uint8_t)srslte_random_uniform_int_dist(random_gen, 0, 1); + } - gettimeofday(&t[1], NULL); + gettimeofday(&t[1], NULL); + for (uint32_t r = 0; r < nof_repetitions; r++) { srslte_block_encode(tx, block_size, encoded, E); - gettimeofday(&t[2], NULL); - get_time_interval(t); - t_encode_us += t[0].tv_sec * 1000000 + t[0].tv_usec; + } + gettimeofday(&t[2], NULL); + get_time_interval(t); + uint64_t t_encode_us = t[0].tv_sec * 1000000 + t[0].tv_usec; - for (uint32_t i = 0; i < E; i++) { - int32_t llr = (encoded[i] == 0) ? -A : +A; - llr_i16[i] = (int16_t)llr; - llr_i8[i] = (int8_t)llr; - } + for (uint32_t i = 0; i < E; i++) { + int32_t llr = (encoded[i] == 0) ? -A : +A; + llr_i16[i] = (int16_t)llr; + llr_i8[i] = (int8_t)llr; + } + + int32_t corr_i16 = 0; + gettimeofday(&t[1], NULL); - gettimeofday(&t[1], NULL); - int32_t corr_i16 = srslte_block_decode_i16(llr_i16, E, rx, block_size); - gettimeofday(&t[2], NULL); - get_time_interval(t); - TESTASSERT(corr_i16 == E * A); - TESTASSERT(memcmp(tx, rx, block_size) == 0); - t_decode_i16_us += t[0].tv_sec * 1000000 + t[0].tv_usec; + for (uint32_t r = 0; r < nof_repetitions; r++) { + corr_i16 = srslte_block_decode_i16(llr_i16, E, rx, block_size); + } + gettimeofday(&t[2], NULL); + get_time_interval(t); + TESTASSERT(corr_i16 == E * A); + TESTASSERT(memcmp(tx, rx, block_size) == 0); + uint64_t t_decode_i16_us = t[0].tv_sec * 1000000 + t[0].tv_usec; - gettimeofday(&t[1], NULL); - int32_t corr_i8 = srslte_block_decode_i8(llr_i8, E, rx, block_size); - gettimeofday(&t[2], NULL); - get_time_interval(t); - TESTASSERT(corr_i8 == E * A); - TESTASSERT(memcmp(tx, rx, block_size) == 0); - t_decode_i8_us += t[0].tv_sec * 1000000 + t[0].tv_usec; + gettimeofday(&t[1], NULL); + int32_t corr_i8 = 0; + for (uint32_t r = 0; r < nof_repetitions; r++) { + corr_i8 = srslte_block_decode_i8(llr_i8, E, rx, block_size); } + gettimeofday(&t[2], NULL); + get_time_interval(t); + TESTASSERT(corr_i8 == E * A); + TESTASSERT(memcmp(tx, rx, block_size) == 0); + uint64_t t_decode_i8_us = t[0].tv_sec * 1000000 + t[0].tv_usec; double total_bits = (double)(block_size * nof_repetitions); INFO("Block size %d PASSED! Encoder: %.1f us / %.1f Mbps; 16 bit Decoder: %.1f us / %.2f Mbps; 8 bit decoder: %.1f / " diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index e4883a1a5..2757ab4e7 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -21,7 +21,6 @@ #include "srslte/phy/common/phy_common.h" #include "srslte/phy/fec/block/block.h" -#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/convolutional/convcoder.h" #include "srslte/phy/fec/convolutional/rm_conv.h" #include "srslte/phy/fec/crc.h" @@ -30,21 +29,7 @@ #include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/vector.h" -/* Table 5.2.2.6.4-1: Basis sequence for (32, O) code */ -static uint8_t M_basis_seq[SRSLTE_FEC_BLOCK_SIZE][SRSLTE_UCI_MAX_ACK_SR_BITS] = { - {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1}, {1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, - {1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1}, {1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1}, {1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1}, - {1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1}, {1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1}, {1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1}, - {1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1}, {1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1}, {1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1}, - {1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1}, {1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1}, {1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1}, - {1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1}, {1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0}, {1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0}, - {1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0}, {1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, {1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}, - {1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1}, {1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1}, {1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1}, - {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}, {1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1}, {1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0}, - {1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0}, {1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0}, {1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -}; - +/* Table 5.2.3.3-1: Basis sequences for (20, A) code */ static uint8_t M_basis_seq_pucch[20][13] = { {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}, {1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1}, {1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1}, @@ -159,37 +144,6 @@ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t* q, } } -void cqi_pusch_pregen(srslte_uci_cqi_pusch_t* q) -{ - uint8_t word[11]; - - for (int i = 0; i < 11; i++) { - uint32_t nwords = (1 << (i + 1)); - q->cqi_table[i] = srslte_vec_u8_malloc(nwords * 32); - q->cqi_table_s[i] = srslte_vec_i16_malloc(nwords * 32); - for (uint32_t w = 0; w < nwords; w++) { - uint8_t* ptr = word; - srslte_bit_unpack(w, &ptr, i + 1); - srslte_block_encode(word, i + 1, &q->cqi_table[i][32 * w], SRSLTE_FEC_BLOCK_SIZE); - for (int j = 0; j < 32; j++) { - q->cqi_table_s[i][32 * w + j] = 2 * q->cqi_table[i][32 * w + j] - 1; - } - } - } -} - -void cqi_pusch_pregen_free(srslte_uci_cqi_pusch_t* q) -{ - for (int i = 0; i < 11; i++) { - if (q->cqi_table[i]) { - free(q->cqi_table[i]); - } - if (q->cqi_table_s[i]) { - free(q->cqi_table_s[i]); - } - } -} - int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t* q) { if (srslte_crc_init(&q->crc, SRSLTE_LTE_CRC8, 8)) { @@ -200,16 +154,12 @@ int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t* q) return SRSLTE_ERROR; } - cqi_pusch_pregen(q); - return SRSLTE_SUCCESS; } void srslte_uci_cqi_free(srslte_uci_cqi_pusch_t* q) { srslte_viterbi_free(&q->viterbi); - - cqi_pusch_pregen_free(q); } static uint32_t Q_prime_cqi(srslte_pusch_cfg_t* cfg, uint32_t O, float beta, uint32_t Q_prime_ri) @@ -244,48 +194,19 @@ uint32_t srslte_qprime_cqi_ext(uint32_t L_prb, uint32_t nof_symbols, uint32_t tb */ int encode_cqi_short(srslte_uci_cqi_pusch_t* q, uint8_t* data, uint32_t nof_bits, uint8_t* q_bits, uint32_t Q) { - if (nof_bits <= 11 && nof_bits > 0 && q != NULL && data != NULL && q_bits != NULL) { - uint8_t* ptr = data; - uint32_t w = srslte_bit_pack(&ptr, nof_bits); - - for (int i = 0; i < Q; i++) { - q_bits[i] = q->cqi_table[nof_bits - 1][w * 32 + (i % 32)]; - } + if (nof_bits <= SRSLTE_FEC_BLOCK_MAX_NOF_BITS && nof_bits > 0 && q != NULL && data != NULL && q_bits != NULL) { + srslte_block_encode(data, nof_bits, q_bits, Q); return SRSLTE_SUCCESS; - } else { - return SRSLTE_ERROR_INVALID_INPUTS; } + return SRSLTE_ERROR_INVALID_INPUTS; } // For decoding the block-encoded CQI we use ML decoding int decode_cqi_short(srslte_uci_cqi_pusch_t* q, int16_t* q_bits, uint32_t Q, uint8_t* data, uint32_t nof_bits) { - if (nof_bits <= 11 && nof_bits > 0 && q != NULL && data != NULL && q_bits != NULL) { - // Accumulate all copies of the 32-length sequence - if (Q > 32) { - int i = 1; - for (; i < Q / 32; i++) { - srslte_vec_sum_sss(&q_bits[i * 32], q_bits, q_bits, 32); - } - srslte_vec_sum_sss(&q_bits[i * 32], q_bits, q_bits, Q % 32); - } - - uint32_t max_w = 0; - int32_t max_corr = INT32_MIN; - for (uint32_t w = 0; w < (1 << nof_bits); w++) { - - // Calculate correlation with pregenerated word and select maximum - int32_t corr = srslte_vec_dot_prod_sss(&q->cqi_table_s[nof_bits - 1][w * 32], q_bits, SRSLTE_MIN(32, Q)); - if (corr > max_corr) { - max_corr = corr; - max_w = w; - } - } - // Convert word to bits again - uint8_t* ptr = data; - srslte_bit_unpack(max_w, &ptr, nof_bits); - - INFO("Decoded CQI: w=%d, corr=%d\n", max_w, max_corr); + if (nof_bits <= SRSLTE_FEC_BLOCK_MAX_NOF_BITS && nof_bits > 0 && q != NULL && data != NULL && q_bits != NULL) { + int32_t max_corr = srslte_block_decode_i16(q_bits, Q, data, nof_bits); + INFO("Decoded CQI: corr=%d\n", max_corr); return SRSLTE_SUCCESS; } else { return SRSLTE_ERROR_INVALID_INPUTS; @@ -566,12 +487,15 @@ encode_ack_long(const uint8_t* data, uint32_t O_ack, uint8_t Q_m, uint32_t Q_pri return 0; } + // Encoded bits + uint8_t q[SRSLTE_FEC_BLOCK_SIZE] = {}; + + // Encode + srslte_block_encode(data, O_ack, q, SRSLTE_FEC_BLOCK_SIZE); + + // Convert to UCI bits for (uint32_t i = 0; i < Q_ack; i++) { - uint32_t q_i = 0; - for (uint32_t n = 0; n < O_ack; n++) { - q_i = (q_i + (data[n] * M_basis_seq[i % 32][n])) % 2; - } - q_encoded_bits[i].type = q_i ? UCI_BIT_1 : UCI_BIT_0; + q_encoded_bits[i].type = q[i % SRSLTE_FEC_BLOCK_SIZE] ? UCI_BIT_1 : UCI_BIT_0; } return Q_ack;