mirror of https://github.com/PentHertz/srsLTE.git
Moved all block code (32, O/K) to FEC block
Fix missing header Fix missing header
This commit is contained in:
parent
95ce49acd4
commit
ae3c5ec7d0
|
@ -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 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
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 / "
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue