From be6cb666e2f3a1f7a615b72baa8e93a63b48ce1b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 7 Jan 2021 13:46:49 +0100 Subject: [PATCH] Initial moved block coding to FEC --- lib/include/srslte/phy/phch/uci.h | 25 --- lib/src/phy/fec/CMakeLists.txt | 1 + lib/src/phy/fec/block/CMakeLists.txt | 13 ++ lib/src/phy/fec/block/block.c | 198 ++++++++++++++++++++++ lib/src/phy/fec/block/test/CMakeLists.txt | 16 ++ lib/src/phy/fec/block/test/block_test.c | 128 ++++++++++++++ lib/src/phy/phch/pucch.c | 5 +- lib/src/phy/phch/uci.c | 117 +------------ 8 files changed, 365 insertions(+), 138 deletions(-) create mode 100644 lib/src/phy/fec/block/CMakeLists.txt create mode 100644 lib/src/phy/fec/block/block.c create mode 100644 lib/src/phy/fec/block/test/CMakeLists.txt create mode 100644 lib/src/phy/fec/block/test/block_test.c diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index dd6442a22..9d5c45758 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -32,7 +32,6 @@ #define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13 #define SRSLTE_UCI_CQI_CODED_PUCCH_B 20 #define SRSLTE_UCI_STR_MAX_CHAR 32 -#define SRSLTE_UCI_M_BASIS_SEQ_LEN 32 typedef struct SRSLTE_API { srslte_crc_t crc; @@ -65,30 +64,6 @@ SRSLTE_API int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t* q, int16_t b_bits[SRSLTE_CQI_MAX_BITS], // aligned for simd uint8_t* cqi_data, uint32_t cqi_len); -/** - * Encodes Uplink Control Information using M-basis code block channel coding. - * - * @param input points to the bit to encode, one word per bit - * @param input_len number of bits to encode, the maximum number of bits is 11 - * @param output points to the encoded data, one word per bit - * @param output_len number of bits of encoded bits - */ -SRSLTE_API void -srslte_uci_encode_m_basis_bits(const uint8_t* input, uint32_t input_len, uint8_t* output, uint32_t output_len); - -/** - * Decodes Uplink Control Information using M-basis code block channel coding. - * - * @param llr points soft-bits - * @param nof_llr number of soft-bits, requires a minimum of 32 soft-bits - * @param data points to receice data, one word per bit - * @param data_len number of bits to decode, the maximum number of bits is 11 - * @return maximum correlation value - */ -SRSLTE_API int32_t srslte_uci_decode_m_basis_bits(const int16_t* llr, - uint32_t nof_llr, - uint8_t* data, - uint32_t data_len); SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t* q); diff --git a/lib/src/phy/fec/CMakeLists.txt b/lib/src/phy/fec/CMakeLists.txt index e2cbae0dc..8c6ced9a9 100644 --- a/lib/src/phy/fec/CMakeLists.txt +++ b/lib/src/phy/fec/CMakeLists.txt @@ -11,6 +11,7 @@ set(FEC_SOURCES crc.c softbuffer.c) +add_subdirectory(block) add_subdirectory(convolutional) add_subdirectory(ldpc) add_subdirectory(polar) diff --git a/lib/src/phy/fec/block/CMakeLists.txt b/lib/src/phy/fec/block/CMakeLists.txt new file mode 100644 index 000000000..be0d876d9 --- /dev/null +++ b/lib/src/phy/fec/block/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# 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. +# + +set(FEC_SOURCES ${FEC_SOURCES} + block/block.c + PARENT_SCOPE) + +add_subdirectory(test) diff --git a/lib/src/phy/fec/block/block.c b/lib/src/phy/fec/block/block.c new file mode 100644 index 000000000..4bdebae98 --- /dev/null +++ b/lib/src/phy/fec/block/block.c @@ -0,0 +1,198 @@ +/** + * + * \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/fec/block/block.h" +#include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/vector.h" + +// Use carry-less multiplication for parity check calculation only if AVX2 is available +#ifdef LV_HAVE_AVX2 +#include +#define USE_CARRYLESS_MULT 1 +#else +#define USE_CARRYLESS_MULT 0 +#endif // LV_HAVE_AVX2 + +// The following MACRO enables/disables LUT for the decoder +#define USE_LUT 1 + +// The following type is used for selecting the algorithm precision +typedef int16_t block_llr_t; + +/// Table 5.2.2.6.4-1: Basis sequence for (32, O) code compressed in uint16_t types +static const uint64_t M_basis_seq_b[SRSLTE_FEC_BLOCK_SIZE] = { + 0b10000000011, 0b11000000111, 0b11101001001, 0b10100001101, 0b10010001111, 0b10111010011, 0b11101010101, + 0b10110011001, 0b11010011011, 0b11001011101, 0b11011100101, 0b10101100111, 0b11110101001, 0b11010101011, + 0b10010110001, 0b11011110011, 0b01001110111, 0b00100111001, 0b00011111011, 0b00001100001, 0b10001000101, + 0b11000001011, 0b10110010001, 0b11100010111, 0b01111011111, 0b10011100011, 0b01100101101, 0b01110101111, + 0b00101110101, 0b00111111101, 0b11111111111, 0b00000000001, +}; + +static inline uint8_t encode_M_basis_seq_u16(uint16_t w, uint32_t bit_idx) +{ + // Apply mask + uint64_t d = w & M_basis_seq_b[bit_idx % SRSLTE_FEC_BLOCK_SIZE]; + +#if USE_CARRYLESS_MULT + // Compute parity using carry-less multiplication + const __m128i temp = _mm_clmulepi64_si128(_mm_set_epi64x(0, d), _mm_set_epi64x(0, 0xffffUL << 17UL), 0); + d = _mm_extract_epi32(temp, 1); +#else + // Compute parity using Bit Twiddling + d ^= d >> 8UL; + d ^= d >> 4UL; + d &= 0xFUL; + d = (0x6996U >> d); +#endif + + return (uint8_t)(d & 1UL); +} + +#if USE_LUT +static block_llr_t M_basis_seq_b_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 +__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; + } + } +} +#endif + +void srslte_block_encode(const uint8_t* input, uint32_t input_len, uint8_t* output, uint32_t output_len) +{ + // Limit number of input bits + input_len = SRSLTE_MIN(input_len, SRSLTE_FEC_BLOCK_MAX_NOF_BITS); + + // Pack input bits + uint16_t w = 0; + for (uint32_t i = 0; i < input_len; i++) { + w |= (input[i] & 1U) << i; + } + + // Encode bits + for (uint32_t i = 0; i < SRSLTE_MIN(output_len, SRSLTE_FEC_BLOCK_SIZE); i++) { + output[i] = encode_M_basis_seq_u16(w, i); + } + + // Avoid repeating operation by copying repeated sequence + for (uint32_t i = SRSLTE_FEC_BLOCK_SIZE; i < output_len; i++) { + output[i] = output[i % SRSLTE_FEC_BLOCK_SIZE]; + } +} + +static int32_t srslte_block_decode(const block_llr_t llr[SRSLTE_FEC_BLOCK_SIZE], 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 + + // Limit data to maximum + data_len = SRSLTE_MIN(data_len, SRSLTE_FEC_BLOCK_MAX_NOF_BITS); + + // Brute force all possible sequences + uint16_t max_guess = (1U << data_len); //< Maximum guess bit combination (excluded) + for (uint16_t guess = 0; guess < max_guess; guess++) { + 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]; + } +#else + for (uint32_t i = 0; i < SRSLTE_FEC_BLOCK_SIZE; i++) { + // On-the-fly sequence generation and product + corr += llr[i] * (encode_M_basis_seq_u16(guess, i) * 2 - 1); + } +#endif + + // Take decision + if (corr > max_corr) { + max_corr = corr; + max_data = guess; + } + } + + // Unpack + for (uint32_t i = 0; i < data_len; i++) { + data[i] = (uint8_t)((max_data >> i) & 1U); + } + + // Return correlation + return max_corr; +} + +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]; + + // Return invalid inputs if data is not provided + if (!llr || !data) { + ERROR("Invalid inputs\n"); + 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++) { + llr_[i % SRSLTE_FEC_BLOCK_SIZE] += (block_llr_t)llr[i]; + } + + return srslte_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]; + + // Return invalid inputs if data is not provided + if (!llr || !data) { + ERROR("Invalid inputs\n"); + 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++) { + llr_[i % SRSLTE_FEC_BLOCK_SIZE] += (block_llr_t)llr[i]; + } + + return srslte_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 new file mode 100644 index 000000000..cafbf16ca --- /dev/null +++ b/lib/src/phy/fec/block/test/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# 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. +# + +######################################################################## +# Viterbi TEST +######################################################################## + +add_executable(block_test block_test.c) +target_link_libraries(block_test srslte_phy) + +add_test(block_test block_test) diff --git a/lib/src/phy/fec/block/test/block_test.c b/lib/src/phy/fec/block/test/block_test.c new file mode 100644 index 000000000..2e38a5577 --- /dev/null +++ b/lib/src/phy/fec/block/test/block_test.c @@ -0,0 +1,128 @@ +/** + * + * \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/common/test_common.h" +#include "srslte/phy/fec/block/block.h" +#include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/random.h" +#include +#include +#include +#include +#include +#include +#include + +static uint32_t seed = 0x1234; +static uint32_t nof_repetitions = 1; +static uint32_t E = SRSLTE_FEC_BLOCK_SIZE; +static uint32_t A = 100; +static srslte_random_t random_gen = NULL; + +void usage(char* prog) +{ + printf("Usage: %s [Rv]\n", prog); + printf("\t-R Number of repetitions [Default %d]\n", nof_repetitions); + 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) { + switch (opt) { + case 'R': + nof_repetitions = (uint32_t)strtol(argv[optind], NULL, 10); + break; + case 'v': + srslte_verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } +} + +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; + + 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); + } + + gettimeofday(&t[1], NULL); + 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; + + 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; + } + + 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; + + 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; + } + + 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 / " + "%.2f Mbps\n", + block_size, + t_encode_us / (double)nof_repetitions, + total_bits / (double)t_encode_us, + t_decode_i16_us / (double)nof_repetitions, + total_bits / (double)t_decode_i16_us, + t_decode_i8_us / (double)nof_repetitions, + total_bits / (double)t_decode_i8_us); + + return SRSLTE_SUCCESS; +} + +int main(int argc, char** argv) +{ + parse_args(argc, argv); + random_gen = srslte_random_init(seed); + + for (uint32_t block_size = 3; block_size <= SRSLTE_FEC_BLOCK_MAX_NOF_BITS; block_size++) { + if (test(block_size) < SRSLTE_SUCCESS) { + break; + } + } + + srslte_random_free(random_gen); +} diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index bd26e2b11..63ffd9d2d 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -10,6 +10,7 @@ * */ +#include "srslte/phy/fec/block/block.h" #include "srslte/srslte.h" #include #include @@ -639,7 +640,7 @@ static int decode_signal_format3(srslte_pucch_t* q, srslte_scrambling_s_offset(seq, q->llr, 0, SRSLTE_PUCCH3_NOF_BITS); - return (int)srslte_uci_decode_m_basis_bits(q->llr, SRSLTE_PUCCH3_NOF_BITS, bits, SRSLTE_UCI_MAX_ACK_SR_BITS); + return (int)srslte_block_decode_i16(q->llr, SRSLTE_PUCCH3_NOF_BITS, bits, SRSLTE_UCI_MAX_ACK_SR_BITS); } else { ERROR("Error modulating PUCCH3 bits: rnti not set\n"); return SRSLTE_ERROR; @@ -699,7 +700,7 @@ static int encode_bits(srslte_pucch_cfg_t* cfg, temp[k] = (uint8_t)(uci_data->scheduling_request ? 1 : 0); k++; } - srslte_uci_encode_m_basis_bits(temp, k, pucch_bits, SRSLTE_PUCCH3_NOF_BITS); + srslte_block_encode(temp, k, pucch_bits, SRSLTE_PUCCH3_NOF_BITS); } return SRSLTE_SUCCESS; } diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 5fd7dd80a..e4883a1a5 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -20,6 +20,7 @@ #include #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" @@ -30,7 +31,7 @@ #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_UCI_M_BASIS_SEQ_LEN][SRSLTE_UCI_MAX_ACK_SR_BITS] = { +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}, @@ -44,30 +45,6 @@ static uint8_t M_basis_seq[SRSLTE_UCI_M_BASIS_SEQ_LEN][SRSLTE_UCI_MAX_ACK_SR_BIT {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }; -static inline bool encode_M_basis_seq_u16(uint16_t w, uint32_t bit_idx) -{ - /// Table 5.2.2.6.4-1: Basis sequence for (32, O) code compressed in uint16_t types - const uint16_t M_basis_seq_b[SRSLTE_UCI_M_BASIS_SEQ_LEN] = { - 0b10000000011, 0b11000000111, 0b11101001001, 0b10100001101, 0b10010001111, 0b10111010011, 0b11101010101, - 0b10110011001, 0b11010011011, 0b11001011101, 0b11011100101, 0b10101100111, 0b11110101001, 0b11010101011, - 0b10010110001, 0b11011110011, 0b01001110111, 0b00100111001, 0b00011111011, 0b00001100001, 0b10001000101, - 0b11000001011, 0b10110010001, 0b11100010111, 0b01111011111, 0b10011100011, 0b01100101101, 0b01110101111, - 0b00101110101, 0b00111111101, 0b11111111111, 0b00000000001, - }; - - // Apply mask - uint16_t d = (uint16_t)w & M_basis_seq_b[bit_idx % SRSLTE_UCI_M_BASIS_SEQ_LEN]; - - // Compute parity - d ^= (uint16_t)(d >> 8U); - d ^= (uint16_t)(d >> 4U); - d &= 0xf; - d = (0x6996U >> d) & 1U; - - // Return false if 0, otherwise it returns true - return (d != 0); -} - 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}, @@ -182,88 +159,6 @@ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t* q, } } -void srslte_uci_encode_m_basis_bits(const uint8_t* input, uint32_t input_len, uint8_t* output, uint32_t output_len) -{ - // Limit number of input bits - input_len = SRSLTE_MIN(input_len, SRSLTE_UCI_MAX_ACK_SR_BITS); - - // Pack input bits - uint16_t w = 0; - for (uint32_t i = 0; i < input_len; i++) { - w |= (input[i] & 1U) << i; - } - - // Encode bits - for (uint32_t i = 0; i < SRSLTE_MIN(output_len, SRSLTE_UCI_M_BASIS_SEQ_LEN); i++) { - output[i] = encode_M_basis_seq_u16(w, i); - } - - // Avoid repeating operation by copying repeated sequence - for (uint32_t i = SRSLTE_UCI_M_BASIS_SEQ_LEN; i < output_len; i++) { - output[i] = output[i % SRSLTE_UCI_M_BASIS_SEQ_LEN]; - } -} - -int32_t srslte_uci_decode_m_basis_bits(const int16_t* llr, uint32_t nof_llr, uint8_t* data, uint32_t data_len) -{ - int32_t max_corr = 0; ///< Stores maximum correlation - uint16_t max_data = 0; ///< Stores the word for maximum correlation - - // Return invalid inputs if data is not provided - if (!llr || !data) { - ERROR("Invalid inputs\n"); - return SRSLTE_ERROR_INVALID_INPUTS; - } - - // Return invalid inputs if not enough LLR are provided - if (nof_llr < SRSLTE_UCI_M_BASIS_SEQ_LEN) { - ERROR("Not enough LLR bits are provided %d. Required %d;\n", nof_llr, SRSLTE_UCI_M_BASIS_SEQ_LEN); - return SRSLTE_ERROR_INVALID_INPUTS; - } - - // Limit data to maximum - data_len = SRSLTE_MIN(data_len, SRSLTE_UCI_MAX_ACK_SR_BITS); - - // Brute force all possible sequences - uint16_t max_guess = (1 << data_len); ///< Maximum guess bit combination - for (uint16_t guess = 0; guess < max_guess; guess++) { - int32_t corr = 0; - - /// Compute correlation for the number of LLR - bool early_termination = false; - for (uint32_t i = 0; i < nof_llr && !early_termination; i++) { - // Encode guess word - bool d = encode_M_basis_seq_u16(guess, i); - - // Correlate - corr += (int32_t)(d ? llr[i] : -llr[i]); - - // Limit correlation to half range - corr = SRSLTE_MIN(corr, INT32_MAX / 2); - - /// Early terminates if at least SRSLTE_UCI_M_BASIS_SEQ_LEN/4 LLR processed and negative correlation - early_termination |= (i > SRSLTE_UCI_M_BASIS_SEQ_LEN / 4) && (corr < 0); - - /// Early terminates if the correlation overflows - early_termination |= (corr < -INT32_MAX / 2); - } - - // Take decision - if (corr > max_corr) { - max_corr = corr; - max_data = guess; - } - } - - // Unpack - for (uint32_t i = 0; i < data_len; i++) { - data[i] = (uint8_t)((max_data >> i) & 1U); - } - - // Return correlation - return max_corr; -} - void cqi_pusch_pregen(srslte_uci_cqi_pusch_t* q) { uint8_t word[11]; @@ -275,7 +170,7 @@ void cqi_pusch_pregen(srslte_uci_cqi_pusch_t* q) for (uint32_t w = 0; w < nwords; w++) { uint8_t* ptr = word; srslte_bit_unpack(w, &ptr, i + 1); - srslte_uci_encode_m_basis_bits(word, i + 1, &q->cqi_table[i][32 * w], SRSLTE_UCI_M_BASIS_SEQ_LEN); + 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; } @@ -829,8 +724,8 @@ int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t* cfg, int16_t llr_acc[32] = {}; ///< LLR accumulator uint32_t nof_acc = - (nof_bits == 1) ? Qm : (nof_bits == 2) ? Qm * 3 : SRSLTE_UCI_M_BASIS_SEQ_LEN; ///< Number of required LLR - uint32_t count_acc = 0; ///< LLR counter + (nof_bits == 1) ? Qm : (nof_bits == 2) ? Qm * 3 : SRSLTE_FEC_BLOCK_SIZE; ///< Number of required LLR + uint32_t count_acc = 0; ///< LLR counter for (uint32_t i = 0; i < Qprime; i++) { if (is_ri) { @@ -875,7 +770,7 @@ int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t* cfg, break; default: // For more than 2 bits... - corr = srslte_uci_decode_m_basis_bits(llr_acc, SRSLTE_UCI_M_BASIS_SEQ_LEN, data, nof_bits); + corr = srslte_block_decode_i16(llr_acc, SRSLTE_FEC_BLOCK_SIZE, data, nof_bits); } if (valid) {