Moved all block code (32, O/K) to FEC block

Fix missing header

Fix missing header
This commit is contained in:
Xavier Arteaga 2021-01-08 10:47:14 +01:00 committed by Xavier Arteaga
parent 95ce49acd4
commit ae3c5ec7d0
6 changed files with 172 additions and 178 deletions

View File

@ -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 <stdbool.h>
#include <stdint.h>
/**
* @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 ReedMuller 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 ReedMuller 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 ReedMuller 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

View File

@ -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 {

View File

@ -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];
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);
// 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);
return block_decode(llr_, data, data_len);
}

View File

@ -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)

View File

@ -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] = {};
// 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);
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);
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;
}
int32_t corr_i16 = 0;
gettimeofday(&t[1], NULL);
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;
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 = 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 / "

View File

@ -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;