Initial version of LUT-based rate recovery

This commit is contained in:
ismagom 2015-09-22 17:30:14 +01:00
parent 49717437c1
commit 67ad3677a9
3 changed files with 144 additions and 35 deletions

View File

@ -77,6 +77,12 @@ SRSLTE_API int srslte_rm_turbo_rx(float *w_buff,
uint32_t rv_idx,
uint32_t nof_filler_bits);
SRSLTE_API int srslte_rm_turbo_rx_lut(float *input,
uint32_t in_len,
float *output,
uint32_t out_len,
uint32_t rv_idx, uint32_t cb_idx);
/* High-level API */
typedef struct SRSLTE_API {

View File

@ -50,6 +50,7 @@ static uint32_t interleaver_parity_bits[SRSLTE_NOF_TC_CB_SIZES][2*6148];
static uint32_t k0_vec[SRSLTE_NOF_TC_CB_SIZES][4][2];
static bool rm_turbo_tables_generated = false;
uint32_t table_buffer[6144], table_output[6144];
void srslte_rm_turbo_gentable_systematic(uint32_t *table_bits, uint32_t k0_vec[4][2], uint32_t nrows, int ndummy) {
@ -120,6 +121,7 @@ void srslte_rm_turbo_gentable_parity(uint32_t *table_parity, uint32_t k0_vec[4][
}
}
void srslte_rm_turbo_gentables() {
if (!rm_turbo_tables_generated) {
rm_turbo_tables_generated = true;
@ -141,7 +143,9 @@ void srslte_rm_turbo_gentables() {
srslte_rm_turbo_gentable_systematic(interleaver_systematic_bits[cb_idx], k0_vec[cb_idx], nrows, ndummy);
srslte_rm_turbo_gentable_parity(interleaver_parity_bits[cb_idx], k0_vec[cb_idx], in_len/3, nrows, ndummy);
}
}
}
srslte_rm_turbo_gentable_receive(table_buffer, table_output, 132, 0);
}
@ -289,6 +293,8 @@ int srslte_rm_turbo_rx(float *w_buff, uint32_t w_buff_len, float *input, uint32_
int d_i, d_j;
bool isdummy;
nrows = (uint32_t) (out_len / 3 - 1) / NCOLS + 1;
K_p = nrows * NCOLS;
if (3 * K_p > w_buff_len) {
@ -313,7 +319,7 @@ int srslte_rm_turbo_rx(float *w_buff, uint32_t w_buff_len, float *input, uint32_
N_cb = 3 * K_p; // TODO: Soft buffer size limitation
k0 = nrows
* (2 * (uint32_t) ceilf((float) N_cb / (float) (8 * nrows)) * rv_idx + 2);
k = 0;
j = 0;
while (k < in_len) {
@ -352,10 +358,13 @@ int srslte_rm_turbo_rx(float *w_buff, uint32_t w_buff_len, float *input, uint32_
} else if (input[k] != SRSLTE_RX_NULL) {
w_buff[jp] += input[k]; /* soft combine LLRs */
}
k++;
}
t k++;
}
j++;
}
//printf("wbuff:\n");
//srslte_vec_fprint_f(stdout, w_buff, out_len);
/* interleaving and bit selection */
for (i = 0; i < out_len / 3; i++) {
@ -378,9 +387,99 @@ int srslte_rm_turbo_rx(float *w_buff, uint32_t w_buff_len, float *input, uint32_
}
}
}
return 0;
}
void srslte_rm_turbo_gentable_receive(uint32_t *table_buffer, uint32_t *table_output, uint32_t cb_len, uint32_t rv_idx)
{
int nrows = (uint32_t) (cb_len / 3 - 1) / NCOLS + 1;
int ndummy = nrows*NCOLS - cb_len / 3;
if (ndummy < 0) {
ndummy = 0;
}
/* Undo bit collection. Account for dummy bits */
int N_cb = 3*nrows*NCOLS;
int k0 = nrows*(2*(uint32_t) ceilf((float) N_cb/(float) (8*nrows))*rv_idx+2);
printf("cb_len=%d, N_cb=%d, ndummy=%d, nrows=%d\n", cb_len, N_cb, ndummy, nrows);
int kidx;
int K_p = nrows * NCOLS;
int k = 0, jp=0, j=0;
bool isdummy = false;
int d_i, d_j;
while (k < cb_len) {
jp = (k0 + j) % N_cb;
if (jp < K_p || !(jp % 2)) {
if (jp >= K_p) {
d_i = ((jp - K_p) / 2) / nrows;
d_j = ((jp - K_p) / 2) % nrows;
} else {
d_i = jp / nrows;
d_j = jp % nrows;
}
if (d_j * NCOLS + RM_PERM_TC[d_i] >= ndummy) {
isdummy = false;
if (d_j * NCOLS + RM_PERM_TC[d_i] - ndummy < 0) {
isdummy = true;
}
} else {
isdummy = true;
}
} else {
uint32_t jpp = (jp - K_p - 1) / 2;
kidx = (RM_PERM_TC[jpp / nrows] + NCOLS * (jpp % nrows) + 1) % K_p;
if ((kidx - ndummy) < 0) {
isdummy = true;
} else {
isdummy = false;
}
}
if (!isdummy) {
table_buffer[k] = jp%(3*nrows*NCOLS);
k++;
}
j++;
}
for (int i = 0; i < cb_len / 3; i++) {
d_i = (i + ndummy) / NCOLS;
d_j = (i + ndummy) % NCOLS;
for (j = 0; j < 3; j++) {
if (j != 2) {
kidx = K_p * j + (j + 1) * (RM_PERM_TC[d_j] * nrows + d_i);
} else {
k = (i + ndummy - 1) % K_p;
if (k < 0)
k += K_p;
kidx = (k / NCOLS + nrows * RM_PERM_TC[k % NCOLS]) % K_p;
kidx = 2 * kidx + K_p + 1;
}
table_output[kidx] = 3*i+j;
}
}
}
int srslte_rm_turbo_rx_lut(float *input, uint32_t in_len, float *output, uint32_t out_len, uint32_t rv_idx, uint32_t cb_idx)
{
for (int i=0;i<in_len;i++) {
output[table_output[table_buffer[i%out_len]]] += input[i];
}
return 0;
}
/** High-level API */
int srslte_rm_turbo_initialize(srslte_rm_turbo_hl* h) {

View File

@ -86,18 +86,13 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) {
int i;
uint8_t *bits, *bits_out, *rm_bits, *rm_bits2, *rm_bits2_bytes, *w_buff_c;
float *rm_symbols, *unrm_symbols, *w_buff_f;
float *rm_symbols, *unrm_symbols, *unrm_symbols2, *w_buff_f;
int nof_errors;
parse_args(argc, argv);
srslte_rm_turbo_gentables();
for (cb_idx=0;cb_idx<188;cb_idx++) {
for (rv_idx=0;rv_idx<4;rv_idx++) {
printf("cb_len=%d, rv_idx=%d\n", cb_idx, rv_idx);
if (cb_idx != -1) {
nof_tx_bits = 3*srslte_cbsegm_cbsize(cb_idx)+12;
}
@ -147,6 +142,11 @@ int main(int argc, char **argv) {
perror("malloc");
exit(-1);
}
unrm_symbols2 = malloc(sizeof(float) * nof_tx_bits);
if (!unrm_symbols2) {
perror("malloc");
exit(-1);
}
for (i = 0; i < nof_tx_bits; i++) {
bits[i] = rand() % 2;
@ -191,38 +191,42 @@ int main(int argc, char **argv) {
srslte_bit_unpack_vector(rm_bits2_bytes, rm_bits2, nof_rx_bits);
for (int i=0;i<nof_rx_bits;i++) {
if (rm_bits[i] != rm_bits2[i]) {
printf("error in bit %d\n", i);
exit(-1);
}
}
}
}
printf("OK\n");
exit(0);
printf("RM: ");
srslte_vec_fprint_b(stdout, rm_bits, nof_rx_bits);
for (i = 0; i < nof_rx_bits; i++) {
rm_symbols[i] = (float) rm_bits[i] ? 1 : -1;
}
for (int i=0;i<nof_rx_bits;i++) {
rm_symbols[i] = rand()%10-5;
}
srslte_rm_turbo_rx(w_buff_f, nof_rx_bits * 10, rm_symbols, nof_rx_bits, unrm_symbols, nof_tx_bits,
rv_idx, nof_filler_bits);
printf("UMRM: ");
srslte_vec_fprint_f(stdout, unrm_symbols, nof_tx_bits);
bzero(w_buff_f, nof_rx_bits*10*sizeof(float));
struct timeval t[3];
gettimeofday(&t[1], NULL);
srslte_rm_turbo_rx(w_buff_f, nof_rx_bits * 10, rm_symbols, nof_rx_bits, unrm_symbols, nof_tx_bits, rv_idx, 0);
gettimeofday(&t[2], NULL);
get_time_interval(t);
printf("Old=%d us\n", t[0].tv_usec);
bzero(unrm_symbols2, nof_tx_bits*sizeof(float));
gettimeofday(&t[1], NULL);
srslte_rm_turbo_rx_lut(rm_symbols, nof_rx_bits, unrm_symbols2, nof_tx_bits, rv_idx, cb_idx);
gettimeofday(&t[2], NULL);
get_time_interval(t);
printf("New=%d us\n", t[0].tv_usec);
for (int i=0;i<nof_tx_bits;i++) {
if (unrm_symbols[i] != unrm_symbols2[i]) {
printf("error in bit %d %f!=%f\n", i, unrm_symbols[i], unrm_symbols2[i]);
exit(-1);
}
}
printf("Ok\n");
exit(0);
for (i=0;i<nof_tx_bits;i++) {
bits_out[i] = unrm_symbols[i]>0?1:0;
}
printf("BITS: ");
srslte_vec_fprint_b(stdout, bits_out, nof_tx_bits);
printf("BITS: ");
srslte_vec_fprint_b(stdout, bits, nof_tx_bits);
nof_errors = 0;
for (i = 0; i < nof_tx_bits; i++) {
if (bits_out[i] != bits[i]) {