diff --git a/cuhd/lib/cuhd_imp.cpp b/cuhd/lib/cuhd_imp.cpp index 2f63ddbcc..732a2be34 100644 --- a/cuhd/lib/cuhd_imp.cpp +++ b/cuhd/lib/cuhd_imp.cpp @@ -100,12 +100,14 @@ int cuhd_start_rx_stream_nsamples(void *h, int nsamples) { return 0; } - - int cuhd_open(char *args, void **h) { cuhd_handler* handler = new cuhd_handler(); std::string _args=std::string(args); handler->usrp = uhd::usrp::multi_usrp::make(_args); + + // Try to set LTE clock + handler->usrp->set_master_clock_rate(30720000); + handler->usrp->set_clock_source("internal"); std::string otw, cpu; diff --git a/examples/pbch_ue.c b/examples/pbch_ue.c index a817dd738..1b70d3b68 100644 --- a/examples/pbch_ue.c +++ b/examples/pbch_ue.c @@ -57,7 +57,7 @@ #define NOF_PORTS 2 -float find_threshold = 30.0, track_threshold = 10.0; +float find_threshold = 20.0, track_threshold = 10.0; int max_track_lost = 20, nof_frames = -1; int track_len=300; char *input_file_name = NULL; diff --git a/lte/include/lte/fec/rm_conv.h b/lte/include/lte/fec/rm_conv.h index 58d3e2eb5..0eee8c0ad 100644 --- a/lte/include/lte/fec/rm_conv.h +++ b/lte/include/lte/fec/rm_conv.h @@ -33,8 +33,8 @@ #define TX_NULL 80 -int rm_conv_tx(char *input, char *output, int in_len, int out_len); -int rm_conv_rx(float *input, float *output, int in_len, int out_len); +int rm_conv_tx(char *input, int in_len, char *output, int out_len); +int rm_conv_rx(float *input, int in_len, float *output, int out_len); /* High-level API */ diff --git a/lte/include/lte/fec/rm_turbo.h b/lte/include/lte/fec/rm_turbo.h index 96aefadb3..fcee08fe3 100644 --- a/lte/include/lte/fec/rm_turbo.h +++ b/lte/include/lte/fec/rm_turbo.h @@ -26,19 +26,32 @@ */ -#ifndef RM_CONV_ -#define RM_CONV_ +#ifndef RM_TURBO_ +#define RM_TURBO_ +#ifndef RX_NULL #define RX_NULL 10000 +#endif + +#ifndef TX_NULL #define TX_NULL 80 +#endif +typedef struct { + int buffer_len; + char *buffer; + int *d2_perm; +} rm_turbo_t; -int rm_turbo_tx(char *input, char *output, int in_len, int out_len); -int rm_turbo_rx(float *input, float *output, int in_len, int out_len); +int rm_turbo_init(rm_turbo_t *q, int max_codeblock_len); +void rm_turbo_free(rm_turbo_t *q); +int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output, int out_len, int rv_idx); +int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, float *output, int out_len, int rv_idx); /* High-level API */ typedef struct { + rm_turbo_t q; struct rm_turbo_init { int direction; } init; @@ -47,6 +60,7 @@ typedef struct { struct rm_turbo_ctrl_in { int E; int S; + int rv_idx; } ctrl_in; void *output; int out_len; diff --git a/lte/lib/fec/src/rm_conv.c b/lte/lib/fec/src/rm_conv.c index ea90b83cf..d8270d243 100644 --- a/lte/lib/fec/src/rm_conv.c +++ b/lte/lib/fec/src/rm_conv.c @@ -34,14 +34,14 @@ #define NROWS_MAX NCOLS #define RATE 3 -unsigned char RM_PERM_CC[NCOLS] = +unsigned char RM_PERM_TC[NCOLS] = { 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31, 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30 }; -unsigned char RM_PERM_CC_INV[NCOLS] = { 16, 0, 24, 8, 20, 4, 28, 12, 18, 2, 26, +unsigned char RM_PERM_TC_INV[NCOLS] = { 16, 0, 24, 8, 20, 4, 28, 12, 18, 2, 26, 10, 22, 6, 30, 14, 17, 1, 25, 9, 21, 5, 29, 13, 19, 3, 27, 11, 23, 7, 31, 15 }; -int rm_conv_tx(char *input, char *output, int in_len, int out_len) { +int rm_conv_tx(char *input, int in_len, char *output, int out_len) { char tmp[RATE * NCOLS * NROWS_MAX]; int nrows, ndummy, K_p; @@ -64,10 +64,10 @@ int rm_conv_tx(char *input, char *output, int in_len, int out_len) { for (s = 0; s < 3; s++) { for (j = 0; j < NCOLS; j++) { for (i = 0; i < nrows; i++) { - if (i*NCOLS + RM_PERM_CC[j] < ndummy) { + if (i*NCOLS + RM_PERM_TC[j] < ndummy) { tmp[k] = TX_NULL; } else { - tmp[k] = input[(i*NCOLS + RM_PERM_CC[j]-ndummy)*3+s]; + tmp[k] = input[(i*NCOLS + RM_PERM_TC[j]-ndummy)*3+s]; } k++; } @@ -93,7 +93,7 @@ int rm_conv_tx(char *input, char *output, int in_len, int out_len) { /* Undoes Convolutional Code Rate Matching. * 3GPP TS 36.212 v10.1.0 section 5.1.4.2 */ -int rm_conv_rx(float *input, float *output, int in_len, int out_len) { +int rm_conv_rx(float *input, int in_len, float *output, int out_len) { int nrows, ndummy, K_p; int i, j, k; @@ -125,7 +125,7 @@ int rm_conv_rx(float *input, float *output, int in_len, int out_len) { d_i = (j % K_p) / nrows; d_j = (j % K_p) % nrows; - if (d_j * NCOLS + RM_PERM_CC[d_i] >= ndummy) { + if (d_j * NCOLS + RM_PERM_TC[d_i] >= ndummy) { if (tmp[j] == RX_NULL) { tmp[j] = input[k]; } else if (input[k] != RX_NULL) { @@ -144,7 +144,7 @@ int rm_conv_rx(float *input, float *output, int in_len, int out_len) { d_i = (i + ndummy) / NCOLS; d_j = (i + ndummy) % NCOLS; for (j = 0; j < RATE; j++) { - float o = tmp[K_p * j + RM_PERM_CC_INV[d_j] * nrows + float o = tmp[K_p * j + RM_PERM_TC_INV[d_j] * nrows + d_i]; if (o != RX_NULL) { output[i * RATE + j] = o; diff --git a/lte/lib/fec/src/rm_turbo.c b/lte/lib/fec/src/rm_turbo.c index ee0561f36..d057eb9df 100644 --- a/lte/lib/fec/src/rm_turbo.c +++ b/lte/lib/fec/src/rm_turbo.c @@ -27,87 +27,135 @@ #include #include +#include +#include +#include + #include "lte/fec/rm_turbo.h" #define NCOLS 32 #define NROWS_MAX NCOLS #define RATE 3 -unsigned char RM_PERM_CC[NCOLS] = +unsigned char RM_PERM_TC[NCOLS] = { 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31 }; -unsigned char RM_PERM_CC_INV[NCOLS] = { 16, 0, 24, 8, 20, 4, 28, 12, 18, 2, 26, - 10, 22, 6, 30, 14, 17, 1, 25, 9, 21, 5, 29, 13, 19, 3, 27, 11, 23, 7, - 31, 15 }; +int rm_turbo_init(rm_turbo_t *q, int buffer_len) { + q->buffer_len = buffer_len; + q->buffer = malloc(buffer_len * sizeof(float)); + if (!q->buffer) { + perror("malloc"); + return -1; + } + q->d2_perm = malloc(buffer_len * sizeof(int) / 3 + 1); + if (!q->d2_perm) { + perror("malloc"); + return -1; + } + return 0; +} + +void rm_turbo_free(rm_turbo_t *q) { + if (q->buffer) { + free(q->buffer); + } +} -int rm_turbo_tx(char *input, char *output, int in_len, int out_len) { +/* Turbo Code Rate Matching. + * 3GPP TS 36.212 v10.1.0 section 5.1.4.1 + * + * TODO: Soft buffer size limitation according to UE category + */ +int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output, int out_len, int rv_idx) { - char tmp[RATE * NCOLS * NROWS_MAX]; + char *tmp = (char*) q->buffer; int nrows, ndummy, K_p; - int i, j, k, s; + int i, j, k, s, kidx, N_cb, k0; nrows = (int) (in_len / RATE - 1) / NCOLS + 1; - if (nrows > NROWS_MAX) { - fprintf(stderr, "Input too large. Max input length is %d\n", - RATE * NCOLS * NROWS_MAX); + K_p = nrows * NCOLS; + if (3 * K_p > q->buffer_len) { + fprintf(stderr, + "Input too large. Max input length including dummy bits is %d\n", + q->buffer_len); return -1; } - K_p = nrows * NCOLS; + ndummy = K_p - in_len / RATE; if (ndummy < 0) { ndummy = 0; } - /* Sub-block interleaver 5.1.4.1.1 */ + /* Sub-block interleaver (5.1.4.1.1) and bit collection */ k = 0; - for (s = 0; s < 3; s++) { + for (s = 0; s < 2; s++) { for (j = 0; j < NCOLS; j++) { for (i = 0; i < nrows; i++) { - if (i * NCOLS + RM_PERM_CC[j] < ndummy) { - tmp[k] = TX_NULL; + if (s == 0) { + kidx = k%K_p; } else { - tmp[k] = input[(i * NCOLS + RM_PERM_CC[j] - ndummy) * 3 + s]; + kidx = K_p + 2 * (k%K_p); + } + if (i * NCOLS + RM_PERM_TC[j] < ndummy) { + tmp[kidx] = TX_NULL; + } else { + tmp[kidx] = input[(i * NCOLS + RM_PERM_TC[j] - ndummy) * 3 + s]; } k++; } } } - /* Bit collection, selection and transmission 5.1.4.1.2 */ + + // d_k^(2) goes through special permutation + for (k = 0; k < K_p; k++) { + kidx = (RM_PERM_TC[k / nrows] + NCOLS * (k % nrows) + 1) % K_p; + if ((kidx - ndummy) < 0) { + tmp[K_p + 2 * k + 1] = TX_NULL; + } else { + tmp[K_p + 2 * k + 1] = input[3 * (kidx - ndummy) + 2]; + } + } + + /* Bit selection and transmission 5.1.4.1.2 */ + N_cb = 3 * K_p; // TODO: Soft buffer size limitation + + k0 = nrows * (2 * (int) ceilf((float) N_cb / (float) (8 * nrows)) + * rv_idx + 2); k = 0; j = 0; + while (k < out_len) { - if (tmp[j] != TX_NULL) { - output[k] = tmp[j]; + if (tmp[(k0 + j) % N_cb] != TX_NULL) { + output[k] = tmp[(k0 + j) % N_cb]; k++; } j++; - if (j == RATE * K_p) { - j = 0; - } } return 0; } -/* Undoes Convolutional Code Rate Matching. - * 3GPP TS 36.212 v10.1.0 section 5.1.4.2 +/* Undoes Turbo Code Rate Matching. + * 3GPP TS 36.212 v10.1.0 section 5.1.4.1 */ -int rm_turbo_rx(float *input, float *output, int in_len, int out_len) { +int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, float *output, int out_len, int rv_idx) { - int nrows, ndummy, K_p; + int nrows, ndummy, K_p, k0, N_cb, jp, kidx; int i, j, k; int d_i, d_j; + bool isdummy; - float tmp[RATE * NCOLS * NROWS_MAX]; + float *tmp = (float*) q->buffer; nrows = (int) (out_len / RATE - 1) / NCOLS + 1; - if (nrows > NROWS_MAX) { - fprintf(stderr, "Output too large. Max output length is %d\n", - RATE * NCOLS * NROWS_MAX); + K_p = nrows * NCOLS; + if (3 * K_p > q->buffer_len) { + fprintf(stderr, + "Input too large. Max input length including dummy bits is %d\n", + q->buffer_len); return -1; } - K_p = nrows * NCOLS; ndummy = K_p - out_len / RATE; if (ndummy < 0) { @@ -119,24 +167,51 @@ int rm_turbo_rx(float *input, float *output, int in_len, int out_len) { } /* Undo bit collection. Account for dummy bits */ + N_cb = 3 * K_p; // TODO: Soft buffer size limitation + k0 = nrows * (2 * (int) ceilf((float) N_cb / (float) (8 * nrows)) + * rv_idx + 2); k = 0; j = 0; while (k < in_len) { - d_i = (j % K_p) / nrows; - d_j = (j % K_p) % nrows; + jp = (k0 + j) % N_cb; - if (d_j * NCOLS + RM_PERM_CC[d_i] >= ndummy) { - if (tmp[j] == RX_NULL) { - tmp[j] = input[k]; + if (jp == 32 || jp == 95 || jp == 0) { + i=0; + } + + 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; + } else { + isdummy = true; + } + } else { + int jpp = (jp-K_p-1)/2; + kidx = (RM_PERM_TC[jpp / nrows] + NCOLS * (jpp % nrows) + 1) % K_p; + q->d2_perm[kidx] = jpp; // save the permutation in a temporary buffer + if ((kidx - ndummy) < 0) { + isdummy = true; + } else { + isdummy = false; + } + } + + if (!isdummy) { + if (tmp[jp] == RX_NULL) { + tmp[jp] = input[k]; } else if (input[k] != RX_NULL) { - tmp[j] += input[k]; /* soft combine LLRs */ + tmp[jp] += input[k]; /* soft combine LLRs */ } k++; } j++; - if (j == RATE * K_p) { - j = 0; - } } /* interleaving and bit selection */ @@ -144,7 +219,13 @@ int rm_turbo_rx(float *input, float *output, int in_len, int out_len) { d_i = (i + ndummy) / NCOLS; d_j = (i + ndummy) % NCOLS; for (j = 0; j < RATE; j++) { - float o = tmp[K_p * j + RM_PERM_CC_INV[d_j] * nrows + d_i]; + if (j != 2) { + kidx = K_p * j + (j+1)*(RM_PERM_TC[d_j] * nrows + d_i); + } else { + // use the saved permuatation function to avoid computing the inverse + kidx = 2*q->d2_perm[(i+ndummy)%K_p]+K_p+1; + } + float o = tmp[kidx]; if (o != RX_NULL) { output[i * RATE + j] = o; } else { @@ -155,26 +236,27 @@ int rm_turbo_rx(float *input, float *output, int in_len, int out_len) { return 0; } + /** High-level API */ int rm_turbo_initialize(rm_turbo_hl* h) { - - return 0; + return rm_turbo_init(&h->q, 7000); } /** This function can be called in a subframe (1ms) basis */ int rm_turbo_work(rm_turbo_hl* hl) { if (hl->init.direction) { - //rm_turbo_tx(hl->input, hl->output, hl->in_len, hl->ctrl_in.S); - hl->out_len = hl->ctrl_in.S; - } else { - rm_turbo_rx(hl->input, hl->output, hl->in_len, hl->ctrl_in.E); + rm_turbo_tx(&hl->q, hl->input, hl->in_len, hl->output, hl->ctrl_in.E, hl->ctrl_in.rv_idx); hl->out_len = hl->ctrl_in.E; + } else { + rm_turbo_rx(&hl->q, hl->input, hl->in_len, hl->output, hl->ctrl_in.S, hl->ctrl_in.rv_idx); + hl->out_len = hl->ctrl_in.S; } return 0; } int rm_turbo_stop(rm_turbo_hl* hl) { + rm_turbo_free(&hl->q); return 0; } diff --git a/lte/lib/fec/src/turbodecoder.c2 b/lte/lib/fec/src/turbodecoder.c2 deleted file mode 100644 index a146236da..000000000 --- a/lte/lib/fec/src/turbodecoder.c2 +++ /dev/null @@ -1,304 +0,0 @@ -#include -#include -#include - -#include "lte/fec/permute.h" - -#include "lte/fec/turbodecoder.h" - - -void compute_beta(llr_t *beta, llr_t *data, llr_t *parity, int long_cb, int dec) { - llr_t m_b0, m_b1, m_b2, m_b3, m_b4, m_b5, m_b6, m_b7; - llr_t new0, new1, new2, new3, new4, new5, new6, new7; - llr_t old0, old1, old2, old3, old4, old5, old6, old7; - - llr_t x, y, xy; - int k; - int end = long_cb + RATE; - - old0 = beta[8 * (end) + 0]; - old1 = beta[8 * (end) + 1]; - old2 = beta[8 * (end) + 2]; - old3 = beta[8 * (end) + 3]; - old4 = beta[8 * (end) + 4]; - old5 = beta[8 * (end) + 5]; - old6 = beta[8 * (end) + 6]; - old7 = beta[8 * (end) + 7]; - - for (k = end - 1; k >= 0; k--) { - if (k > long_cb - 1) { - if (dec == 1) { - x = data[RATE * (long_cb ) + NINPUTS * (k - long_cb)]; - y = data[RATE * (long_cb ) + NINPUTS * (k - long_cb) + 1]; - } else { - x = data[RATE * (long_cb ) + NINPUTS * RATE + NINPUTS * (k - long_cb)]; - y = data[RATE * (long_cb ) + NINPUTS * RATE + NINPUTS * (k - long_cb) + 1]; - } - } else { - x = data[RATE * k]; - y = parity[RATE * k]; - } - xy = x + y; - - m_b0 = old4 + xy; - m_b1 = old4; - m_b2 = old5 + y; - m_b3 = old5 + x; - m_b4 = old6 + x; - m_b5 = old6 + y; - m_b6 = old7; - m_b7 = old7 + xy; - - new0 = old0; - new1 = old0 + xy; - new2 = old1 + x; - new3 = old1 + y; - new4 = old2 + y; - new5 = old2 + x; - new6 = old3 + xy; - new7 = old3; - - if (m_b0 > new0) new0 = m_b0; - beta[8 * k + 0] = new0; - old0 = new0; - - if (m_b1 > new1) new1 = m_b1; - beta[8 * k + 1] = new1; - old1 = new1; - - if (m_b2 > new2) new2 = m_b2; - beta[8 * k + 2] = new2; - old2 = new2; - - if (m_b3 > new3) new3 = m_b3; - beta[8 * k + 3] = new3; - old3 = new3; - - if (m_b4 > new4) new4 = m_b4; - beta[8 * k + 4] = new4; - old4 = new4; - - if (m_b5 > new5) new5 = m_b5; - beta[8 * k + 5] = new5; - old5 = new5; - - if (m_b6 > new6) new6 = m_b6; - beta[8 * k + 6] = new6; - old6 = new6; - - if (m_b7 > new7) new7 = m_b7; - beta[8 * k + 7] = new7; - old7 = new7; - - } - -} - -void compute_alfa(llr_t *alfa, llr_t *beta, llr_t *data, llr_t *parity, llr_t *output, int long_cb, int dec) { - llr_t m_b0, m_b1, m_b2, m_b3, m_b4, m_b5, m_b6, m_b7; - llr_t new0, new1, new2, new3, new4, new5, new6, new7; - llr_t old0, old1, old2, old3, old4, old5, old6, old7; - llr_t max1_0, max1_1, max1_2, max1_3, max1_4, max1_5, max1_6, max1_7; - llr_t max0_0, max0_1, max0_2, max0_3, max0_4, max0_5, max0_6, max0_7; - llr_t m1, m0; - llr_t x, y, xy; - llr_t out; - int k; - int end = long_cb; - - old0 = alfa[0]; - old1 = alfa[1]; - old2 = alfa[2]; - old3 = alfa[3]; - old4 = alfa[4]; - old5 = alfa[5]; - old6 = alfa[6]; - old7 = alfa[7]; - - for (k = 1; k < end + 1; k++) { - x = data[RATE * (k - 1)]; - y = parity[RATE * (k - 1)]; - - xy = x + y; - - m_b0 = old0; - m_b1 = old3 + y; - m_b2 = old4 + y; - m_b3 = old7; - m_b4 = old1; - m_b5 = old2 + y; - m_b6 = old5 + y; - m_b7 = old6; - - new0 = old1 + xy; - new1 = old2 + x; - new2 = old5 + x; - new3 = old6 + xy; - new4 = old0 + xy; - new5 = old3 + x; - new6 = old4 + x; - new7 = old7 + xy; - - max0_0 = m_b0 + beta[8 * k + 0]; - max0_1 = m_b1 + beta[8 * k + 1]; - max0_2 = m_b2 + beta[8 * k + 2]; - max0_3 = m_b3 + beta[8 * k + 3]; - max0_4 = m_b4 + beta[8 * k + 4]; - max0_5 = m_b5 + beta[8 * k + 5]; - max0_6 = m_b6 + beta[8 * k + 6]; - max0_7 = m_b7 + beta[8 * k + 7]; - - max1_0 = new0 + beta[8 * k + 0]; - max1_1 = new1 + beta[8 * k + 1]; - max1_2 = new2 + beta[8 * k + 2]; - max1_3 = new3 + beta[8 * k + 3]; - max1_4 = new4 + beta[8 * k + 4]; - max1_5 = new5 + beta[8 * k + 5]; - max1_6 = new6 + beta[8 * k + 6]; - max1_7 = new7 + beta[8 * k + 7]; - - m1 = max1_0; - if (max1_1 > m1) m1 = max1_1; - if (max1_2 > m1) m1 = max1_2; - if (max1_3 > m1) m1 = max1_3; - if (max1_4 > m1) m1 = max1_4; - if (max1_5 > m1) m1 = max1_5; - if (max1_6 > m1) m1 = max1_6; - if (max1_7 > m1) m1 = max1_7; - - m0 = max0_0; - if (max0_1 > m0) m0 = max0_1; - if (max0_2 > m0) m0 = max0_2; - if (max0_3 > m0) m0 = max0_3; - if (max0_4 > m0) m0 = max0_4; - if (max0_5 > m0) m0 = max0_5; - if (max0_6 > m0) m0 = max0_6; - if (max0_7 > m0) m0 = max0_7; - - - if (m_b0 > new0) new0 = m_b0; - old0 = new0; - - if (m_b1 > new1) new1 = m_b1; - old1 = new1; - - if (m_b2 > new2) new2 = m_b2; - old2 = new2; - - if (m_b3 > new3) new3 = m_b3; - old3 = new3; - - if (m_b4 > new4) new4 = m_b4; - old4 = new4; - - if (m_b5 > new5) new5 = m_b5; - old5 = new5; - - if (m_b6 > new6) new6 = m_b6; - old6 = new6; - - if (m_b7 > new7) new7 = m_b7; - old7 = new7; - - out = m1 - m0; - - /* - if (dec == 2) { - if (abs(out) < HALT_min) { - HALT_min = abs(out); - } - } - */ - output[k - 1] = out; - } - - alfa[0] = old0; - alfa[1] = old1; - alfa[2] = old2; - alfa[3] = old3; - alfa[4] = old4; - alfa[5] = old5; - alfa[6] = old6; - alfa[7] = old7; -} - -void DEC_RSC(tdec_t *q, llr_t *input, llr_t *output, int *per, int dec) { - int k; - int i; - int last_state = q->long_cb + RATE; - - /** Initialize alfa states */ - q->alfa[0] = 0; - for (k = 1; k < NUMSTATES; k++) { - q->alfa[k] = -INF; - } - - q->beta[last_state * NUMSTATES] = 0; - for (k = 1; k < NUMSTATES; k++) - q->beta[last_state * NUMSTATES + k] = -INF; - - /* copy data temporal buffer (to allow fastest loops)*/ - memcpy(q->data, input, RATE * last_state * sizeof (llr_t)); - - q->parity = &input[dec]; - - if (dec == 1) { - for (i = 0; i < last_state; i++) { - q->data[RATE * i] += q->W[i ]; - } - } else { - for (i = 0; i < last_state; i++) { - q->data[RATE * i] = q->LLR1[per[i ]] - q->W[per[i ]]; - } - } - - compute_beta(q->beta, q->data, &input[dec], q->long_cb, dec); - compute_alfa(q->alfa, q->beta, q->data, &input[dec], output, q->long_cb, dec); -} - -void decide(llr_t *LLR2, char *output, int *desper, int long_cb) { - int i; - - for (i = 0; i < long_cb; i++) - output[i] = (LLR2[desper[i]] > 0) ? 1 : 0; - -} - -void update_W(llr_t *W, llr_t *LLR1, llr_t *LLR2, int *desper, int long_cb) { - int i; - - for (i = 0; i < long_cb; i++) { - W[i] += LLR2[desper[i]] - LLR1[i]; - } -} - -int turbo_decoder(tdec_t *q, llr_t *input, char *output, int *halt) { - - int i; - long halt_mean=0; - int stop=0; - q->iteration = 0; - - - if (ComputePermutation(&q->permuta, q->long_cb,PER_UMTS)<0) - return -1; - - memset(q->W, 0, sizeof (llr_t) * q->long_cb); - - do { - if (q->iteration) - update_W(q->W, q->LLR1, q->LLR2, q->permuta.DESPER, q->long_cb); - - - DEC_RSC(q, input, q->LLR1, q->permuta.PER, 1); - - DEC_RSC(q, input, q->LLR2, q->permuta.PER, 2); - - q->iteration++; - - } while (q->iteration < q->max_iterations && stop==0); - decide(q->LLR2, output, q->permuta.DESPER, q->long_cb); - - return q->iteration; -} - diff --git a/lte/lib/fec/test/CMakeLists.txt b/lte/lib/fec/test/CMakeLists.txt index 95a9d5974..1d0cc28bb 100644 --- a/lte/lib/fec/test/CMakeLists.txt +++ b/lte/lib/fec/test/CMakeLists.txt @@ -27,6 +27,9 @@ ADD_EXECUTABLE(rm_conv_test rm_conv_test.c) TARGET_LINK_LIBRARIES(rm_conv_test lte) +ADD_EXECUTABLE(rm_turbo_test rm_turbo_test.c) +TARGET_LINK_LIBRARIES(rm_turbo_test lte) + ADD_TEST(rm_conv_test_1 rm_conv_test -t 480 -r 1920) ADD_TEST(rm_conv_test_2 rm_conv_test -t 1920 -r 480) diff --git a/lte/lib/fec/test/rm_conv_test.c b/lte/lib/fec/test/rm_conv_test.c index dc79ecceb..a6e8ab63f 100644 --- a/lte/lib/fec/test/rm_conv_test.c +++ b/lte/lib/fec/test/rm_conv_test.c @@ -100,7 +100,7 @@ int main(int argc, char **argv) { bits[i] = rand()%2; } - if (rm_conv_tx(bits, rm_bits, nof_tx_bits, nof_rx_bits)) { + if (rm_conv_tx(bits, nof_tx_bits, rm_bits, nof_rx_bits)) { exit(-1); } @@ -108,7 +108,7 @@ int main(int argc, char **argv) { rm_symbols[i] = rm_bits[i]?1:-1; } - if (rm_conv_rx(rm_symbols, unrm_symbols, nof_rx_bits, nof_tx_bits)) { + if (rm_conv_rx(rm_symbols, nof_rx_bits, unrm_symbols, nof_tx_bits)) { exit(-1); } diff --git a/lte/lib/fec/test/rm_turbo_test.c b/lte/lib/fec/test/rm_turbo_test.c index dc79ecceb..97adc0bfe 100644 --- a/lte/lib/fec/test/rm_turbo_test.c +++ b/lte/lib/fec/test/rm_turbo_test.c @@ -37,14 +37,15 @@ #include "lte.h" int nof_tx_bits=-1, nof_rx_bits=-1; +int rv_idx = 0; void usage(char *prog) { - printf("Usage: %s -t nof_tx_bits -r nof_rx_bits\n", prog); + printf("Usage: %s -t nof_tx_bits -r nof_rx_bits [-i rv_idx]\n", prog); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "tr")) != -1) { + while ((opt = getopt(argc, argv, "tri")) != -1) { switch (opt) { case 't': nof_tx_bits = atoi(argv[optind]); @@ -52,6 +53,9 @@ void parse_args(int argc, char **argv) { case 'r': nof_rx_bits = atoi(argv[optind]); break; + case 'i': + rv_idx = atoi(argv[optind]); + break; default: usage(argv[0]); exit(-1); @@ -72,6 +76,7 @@ int main(int argc, char **argv) { char *bits, *rm_bits; float *rm_symbols, *unrm_symbols; int nof_errors; + rm_turbo_t rm_turbo; parse_args(argc, argv); @@ -100,36 +105,38 @@ int main(int argc, char **argv) { bits[i] = rand()%2; } - if (rm_conv_tx(bits, rm_bits, nof_tx_bits, nof_rx_bits)) { - exit(-1); - } + rm_turbo_init(&rm_turbo, 1000); + + rm_turbo_tx(&rm_turbo, bits, nof_tx_bits, rm_bits, nof_rx_bits, rv_idx); for (i=0;i 0) != bits[i]) { nof_errors++; + printf("%.2f != %d\n", unrm_symbols[i], bits[i]); } } - if (nof_rx_bits > nof_tx_bits) { - if (nof_errors) { - printf("nof_errors=%d\n", nof_errors); - exit(-1); - } - } + + rm_turbo_free(&rm_turbo); free(bits); free(rm_bits); free(rm_symbols); free(unrm_symbols); + if (nof_tx_bits >= nof_rx_bits) { + if (nof_errors) { + printf("nof_errors=%d\n", nof_errors); + exit(-1); + } + } + printf("Ok\n"); exit(0); } diff --git a/lte/lib/phch/src/pbch.c b/lte/lib/phch/src/pbch.c index e6a413f08..146bc9710 100644 --- a/lte/lib/phch/src/pbch.c +++ b/lte/lib/phch/src/pbch.c @@ -382,7 +382,7 @@ int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, int src, int dst, int n, int n } /* unrate matching */ - rm_conv_rx(q->temp, q->pbch_rm_f, 4 * nof_bits, 120); + rm_conv_rx(q->temp, 4 * nof_bits, q->pbch_rm_f, 120); /* FIXME: If channel estimates are zero, received LLR are NaN. Check and return error */ for (j=0;j<120;j++) { @@ -531,7 +531,7 @@ void pbch_encode(pbch_t *q, pbch_mib_t *mib, cf_t *slot1_symbols[MAX_PORTS_CTRL] convcoder_encode(&q->encoder, q->data, q->data_enc, 40); - rm_conv_tx(q->data_enc, q->pbch_rm_b, 120, 4 * nof_bits); + rm_conv_tx(q->data_enc, 120, q->pbch_rm_b, 4 * nof_bits); } diff --git a/lte/lib/phch/src/pdcch.c b/lte/lib/phch/src/pdcch.c index 0a8fe4e7a..33bf768ac 100644 --- a/lte/lib/phch/src/pdcch.c +++ b/lte/lib/phch/src/pdcch.c @@ -338,7 +338,7 @@ unsigned short dci_decode(pdcch_t *q, float *e, char *data, int E, } */ /* unrate matching */ - rm_conv_rx(e, tmp, E, 3 * (nof_bits + 16)); + rm_conv_rx(e, E, tmp, 3 * (nof_bits + 16)); DEBUG("Viterbi input: ", 0); if (VERBOSE_ISDEBUG()) { @@ -543,7 +543,7 @@ void dci_encode(pdcch_t *q, char *data, char *e, int nof_bits, int E, unsigned s vec_fprint_b(stdout, tmp, 3 * (nof_bits + 16)); } - rm_conv_tx(tmp, e, 3 * (nof_bits + 16), E); + rm_conv_tx(tmp, 3 * (nof_bits + 16), e, E); } /** Converts the MIB message to symbols mapped to SLOT #1 ready for transmission