mirror of https://github.com/PentHertz/srsLTE.git
commit
1cbbbe9b9a
|
@ -43,6 +43,7 @@ CHECK_FUNCTION_EXISTS_MATH(volk_32fc_s32f_atan2_32f HAVE_VOLK_ATAN_FUNCTION)
|
||||||
CHECK_FUNCTION_EXISTS_MATH(volk_32f_s32f_convert_16i HAVE_VOLK_CONVERT_FI_FUNCTION)
|
CHECK_FUNCTION_EXISTS_MATH(volk_32f_s32f_convert_16i HAVE_VOLK_CONVERT_FI_FUNCTION)
|
||||||
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_deinterleave_32f_x2 HAVE_VOLK_DEINTERLEAVE_FUNCTION)
|
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_deinterleave_32f_x2 HAVE_VOLK_DEINTERLEAVE_FUNCTION)
|
||||||
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_subtract_32f HAVE_VOLK_SUB_FLOAT_FUNCTION)
|
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_subtract_32f HAVE_VOLK_SUB_FLOAT_FUNCTION)
|
||||||
|
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_square_dist_32f HAVE_VOLK_SQUARE_DIST_FUNCTION)
|
||||||
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_deinterleave_real_32f HAVE_VOLK_DEINTERLEAVE_FUNCTION)
|
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_deinterleave_real_32f HAVE_VOLK_DEINTERLEAVE_FUNCTION)
|
||||||
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_index_max_16u HAVE_VOLK_MAX_ABS_FUNCTION)
|
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_index_max_16u HAVE_VOLK_MAX_ABS_FUNCTION)
|
||||||
|
|
||||||
|
@ -55,6 +56,9 @@ ENDIF()
|
||||||
IF(${HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION})
|
IF(${HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION})
|
||||||
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION")
|
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
IF(${HAVE_VOLK_SQUARE_DIST_FUNCTION})
|
||||||
|
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_SQUARE_DIST_FUNCTION")
|
||||||
|
ENDIF()
|
||||||
IF(${HAVE_VOLK_DEINTERLEAVE_FUNCTION})
|
IF(${HAVE_VOLK_DEINTERLEAVE_FUNCTION})
|
||||||
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DEINTERLEAVE_FUNCTION")
|
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DEINTERLEAVE_FUNCTION")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
|
@ -40,12 +40,15 @@
|
||||||
typedef _Complex float cf_t;
|
typedef _Complex float cf_t;
|
||||||
typedef struct LIBLTE_API {
|
typedef struct LIBLTE_API {
|
||||||
uint32_t idx[2][6][32];
|
uint32_t idx[2][6][32];
|
||||||
|
uint32_t min_idx[2][64][6]; /* NEW: for each constellation point zone (2, 4, 16, 64 for BPSK, QPSK, 16QAM, 64QAM) the 2x(1, 2, 4, and 6 closest constellation points) for each bit, respectively. */
|
||||||
|
uint32_t d_idx[64][7]; /* NEW: for each constellation point zone (2, 4, 16, 64 for BPSK, QPSK, 16QAM, 64QAM) the 2, 3, 5 and 7 indices to constellation points that need to be computed for any recevied symbol modulated as BPSK, QPSK, 16QAM, and 64QAM, respectively. */
|
||||||
|
|
||||||
}soft_table_t;
|
}soft_table_t;
|
||||||
|
|
||||||
typedef struct LIBLTE_API {
|
typedef struct LIBLTE_API {
|
||||||
cf_t* symbol_table; // bit-to-symbol mapping
|
cf_t* symbol_table; // bit-to-symbol mapping
|
||||||
soft_table_t soft_table; // symbol-to-bit mapping (used in soft demodulating)
|
soft_table_t soft_table; // symbol-to-bit mapping (used in soft demodulating)
|
||||||
uint32_t nsymbols; // number of modulation symbols
|
uint32_t nsymbols; // number of modulation symbols
|
||||||
uint32_t nbits_x_symbol; // number of bits per symbol
|
uint32_t nbits_x_symbol; // number of bits per symbol
|
||||||
}modem_table_t;
|
}modem_table_t;
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
typedef _Complex float cf_t;
|
typedef _Complex float cf_t;
|
||||||
|
|
||||||
#define EXPAVERAGE(data, average, nframes) ((data + average * nframes) / (nframes + 1))
|
#define EXPAVERAGE(data, average, nframes) (((data) + (average) * (nframes)) / ((nframes) + 1))
|
||||||
|
|
||||||
|
|
||||||
/** Return the sum of all the elements */
|
/** Return the sum of all the elements */
|
||||||
|
@ -64,6 +64,9 @@ LIBLTE_API void vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len);
|
||||||
/* substract two vectors z=x-y */
|
/* substract two vectors z=x-y */
|
||||||
LIBLTE_API void vec_sub_fff(float *x, float *y, float *z, uint32_t len);
|
LIBLTE_API void vec_sub_fff(float *x, float *y, float *z, uint32_t len);
|
||||||
|
|
||||||
|
/* Square distance */
|
||||||
|
LIBLTE_API void vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints);
|
||||||
|
|
||||||
/* scalar product */
|
/* scalar product */
|
||||||
LIBLTE_API void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len);
|
LIBLTE_API void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len);
|
||||||
LIBLTE_API void vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len);
|
LIBLTE_API void vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len);
|
||||||
|
|
|
@ -58,8 +58,10 @@ int demod_soft_demodulate(demod_soft_t *q, const cf_t* symbols, float* llr, int
|
||||||
q->table->symbol_table, q->table->soft_table.idx, q->sigma);
|
q->table->symbol_table, q->table->soft_table.idx, q->sigma);
|
||||||
break;
|
break;
|
||||||
case APPROX:
|
case APPROX:
|
||||||
llr_approx(symbols, llr, nsymbols, q->table->nsymbols, q->table->nbits_x_symbol,
|
/* llr_approx(symbols, llr, nsymbols, q->table->nsymbols, q->table->nbits_x_symbol,
|
||||||
q->table->symbol_table, q->table->soft_table.idx, q->sigma);
|
q->table->symbol_table, q->table->soft_table.idx, q->sigma);
|
||||||
|
*/ llr_approx(symbols, llr, nsymbols, q->table->nsymbols, q->table->nbits_x_symbol,
|
||||||
|
q->table->symbol_table, q->table->soft_table.idx, q->table->soft_table.d_idx, q->table->soft_table.min_idx, q->sigma);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return nsymbols*q->table->nbits_x_symbol;
|
return nsymbols*q->table->nbits_x_symbol;
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include "liblte/phy/modem/modem_table.h"
|
#include "liblte/phy/modem/modem_table.h"
|
||||||
#include "lte_tables.h"
|
#include "lte_tables.h"
|
||||||
|
|
||||||
|
void LLR_approx_params(const cf_t* table, soft_table_t *soft_table, int B);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the BPSK modulation table */
|
* Set the BPSK modulation table */
|
||||||
void set_BPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod)
|
void set_BPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod)
|
||||||
|
@ -53,6 +55,18 @@ void set_BPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demo
|
||||||
/* BSPK symbols containing a '0' and a '1' (only two symbols, 1 bit) */
|
/* BSPK symbols containing a '0' and a '1' (only two symbols, 1 bit) */
|
||||||
soft_table->idx[0][0][0] = 0;
|
soft_table->idx[0][0][0] = 0;
|
||||||
soft_table->idx[1][0][0] = 1;
|
soft_table->idx[1][0][0] = 1;
|
||||||
|
|
||||||
|
/* set two matrices for LLR approx. calculation */
|
||||||
|
soft_table->min_idx[0][0][0] = 0;
|
||||||
|
soft_table->min_idx[0][1][0] = 0;
|
||||||
|
soft_table->min_idx[1][0][0] = 1;
|
||||||
|
soft_table->min_idx[1][1][0] = 1;
|
||||||
|
|
||||||
|
soft_table->d_idx[0][0] = 0;
|
||||||
|
soft_table->d_idx[0][1] = 1;
|
||||||
|
soft_table->d_idx[1][0] = 0;
|
||||||
|
soft_table->d_idx[1][1] = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,6 +105,8 @@ void set_QPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demo
|
||||||
soft_table->idx[1][0][1] = 3;
|
soft_table->idx[1][0][1] = 3;
|
||||||
soft_table->idx[1][1][0] = 1;
|
soft_table->idx[1][1][0] = 1;
|
||||||
soft_table->idx[1][1][1] = 3;
|
soft_table->idx[1][1][1] = 3;
|
||||||
|
|
||||||
|
LLR_approx_params(table, soft_table, 2); /* last param indicating B (bits per symbol) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,6 +172,8 @@ void set_16QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_dem
|
||||||
soft_table->idx[0][3][i] = 2*i;
|
soft_table->idx[0][3][i] = 2*i;
|
||||||
soft_table->idx[1][3][i] = 2*i+1;
|
soft_table->idx[1][3][i] = 2*i+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLR_approx_params(table, soft_table, 4); /* last param indication B (bits per symbol) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -277,4 +295,96 @@ void set_64QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_dem
|
||||||
soft_table->idx[0][5][i] = 2*i;
|
soft_table->idx[0][5][i] = 2*i;
|
||||||
soft_table->idx[1][5][i] = 2*i+1;
|
soft_table->idx[1][5][i] = 2*i+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLR_approx_params(table, soft_table, 6); /* last param indication modulation */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Precompute two tables for calculating the distances based on the received symbol location relative to the constellation points */
|
||||||
|
void LLR_approx_params(const cf_t* table, soft_table_t *soft_table, int B) {
|
||||||
|
|
||||||
|
int i, j, b, k;
|
||||||
|
float x, y, d0, d1, min_d0, min_d1;
|
||||||
|
int M, D;
|
||||||
|
uint32_t min_idx0[64][6], min_idx1[64][6];
|
||||||
|
uint32_t count;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
|
||||||
|
D = B+1; /* number of different distances to be computed */
|
||||||
|
//M = pow(2,B); /* number of constellation points */
|
||||||
|
switch (B) {
|
||||||
|
case 1: {M = 2; break;} /* BPSK */
|
||||||
|
case 2: {M = 4; break;} /* QPSK */
|
||||||
|
case 4: {M = 16; break;} /* 16QAM */
|
||||||
|
case 6: {M = 64; break;} /* 64QAM */
|
||||||
|
default: {M = 4; break;} /* QPSK */
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<M;i++) { /* constellation points */
|
||||||
|
for (b=0;b<B;b++) { /* bits per symbol */
|
||||||
|
min_d0 = 100;
|
||||||
|
min_d1 = 100;
|
||||||
|
|
||||||
|
for (j=0;j<M/2;j++) { /* half the symbols have a '0', the other half a '1' at any bit position of modulation symbol */
|
||||||
|
x = __real__ table[i] - __real__ table[soft_table->idx[0][b][j]];
|
||||||
|
y = __imag__ table[i] - __imag__ table[soft_table->idx[0][b][j]];
|
||||||
|
d0 = x*x + y*y;
|
||||||
|
if (d0 < min_d0) {
|
||||||
|
min_d0 = d0;
|
||||||
|
min_idx0[i][b] = soft_table->idx[0][b][j];
|
||||||
|
}
|
||||||
|
|
||||||
|
x = __real__ table[i] - __real__ table[soft_table->idx[1][b][j]];
|
||||||
|
y = __imag__ table[i] - __imag__ table[soft_table->idx[1][b][j]];
|
||||||
|
d1 = x*x + y*y;
|
||||||
|
if (d1 < min_d1) {
|
||||||
|
min_d1 = d1;
|
||||||
|
min_idx1[i][b] = soft_table->idx[1][b][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<M;i++) {
|
||||||
|
for (j=0;j<D;j++) {
|
||||||
|
soft_table->d_idx[i][j] = -1; /* intialization */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<M;i++) {
|
||||||
|
count = 0;
|
||||||
|
for (b=0;b<B;b++) { /* bit(b) = 0 */
|
||||||
|
flag = 0;
|
||||||
|
for (k=0;k<count;k++) {
|
||||||
|
if (min_idx0[i][b] == soft_table->d_idx[i][k]) {
|
||||||
|
soft_table->min_idx[0][i][b] = k;
|
||||||
|
flag = 1; /* no new entry to idxdx */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == 0) { /* new entry to min and d_idx */
|
||||||
|
soft_table->d_idx[i][count] = min_idx0[i][b];
|
||||||
|
soft_table->min_idx[0][i][b] = count;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (b=0;b<B;b++) { /* bit(b) = 1 */
|
||||||
|
flag = 0;
|
||||||
|
for (k=0;k<count;k++) {
|
||||||
|
if (min_idx1[i][b] == soft_table->d_idx[i][k]) {
|
||||||
|
soft_table->min_idx[1][i][b] = k;
|
||||||
|
flag = 1; /* no new entry to d_idx */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == 0) { /* new entry to min and d_idx */
|
||||||
|
soft_table->d_idx[i][count] = min_idx1[i][b];
|
||||||
|
soft_table->min_idx[1][i][b] = count;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,14 @@
|
||||||
#define QAM64_LEVEL_3 5/sqrt(42)
|
#define QAM64_LEVEL_3 5/sqrt(42)
|
||||||
#define QAM64_LEVEL_4 7/sqrt(42)
|
#define QAM64_LEVEL_4 7/sqrt(42)
|
||||||
|
|
||||||
|
//////////////// NUEVO //////////////////////
|
||||||
|
/* HARD DEMODULATION Thresholds, necessary for obtaining the zone of received symbol for optimized LLR approx implementation */
|
||||||
|
#define QAM16_THRESHOLD 2/sqrt(10)
|
||||||
|
#define QAM64_THRESHOLD_1 2/sqrt(42)
|
||||||
|
#define QAM64_THRESHOLD_2 4/sqrt(42)
|
||||||
|
#define QAM64_THRESHOLD_3 6/sqrt(42)
|
||||||
|
//=========================================//
|
||||||
|
|
||||||
#define QAM64_LEVEL_x 2/sqrt(42)
|
#define QAM64_LEVEL_x 2/sqrt(42)
|
||||||
/* this is not an QAM64 level, but, rather, an auxiliary value that can be used for computing the
|
/* this is not an QAM64 level, but, rather, an auxiliary value that can be used for computing the
|
||||||
* symbol from the bit sequence */
|
* symbol from the bit sequence */
|
||||||
|
|
|
@ -31,56 +31,560 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <complex.h>
|
#include <complex.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "soft_algs.h"
|
#include "soft_algs.h"
|
||||||
|
#include "liblte/phy/utils/vector.h"
|
||||||
|
|
||||||
#define LLR_APPROX_USE_VOLK
|
#define QAM16_THRESHOLD 2/sqrt(10)
|
||||||
|
#define QAM64_THRESHOLD_1 2/sqrt(42)
|
||||||
|
#define QAM64_THRESHOLD_2 4/sqrt(42)
|
||||||
|
#define QAM64_THRESHOLD_3 6/sqrt(42)
|
||||||
|
|
||||||
|
|
||||||
#ifdef LLR_APPROX_USE_VOLK
|
typedef _Complex float cf_t;
|
||||||
void
|
|
||||||
llr_approx(const _Complex float *in, float *out, int N, int M, int B,
|
// There are 3 implemenations: 1 - based on zones; 2 - using volk, 3 - straightforward C
|
||||||
_Complex float *symbols, uint32_t(*S)[6][32], float sigma2)
|
#define LLR_APPROX_IMPLEMENTATION 1
|
||||||
|
|
||||||
|
#if LLR_APPROX_IMPLEMENTATION == 1
|
||||||
|
|
||||||
|
float dd[10000][7]; // 7 distances that are needed to compute LLR approx for 64QAM
|
||||||
|
uint32_t zone[10000]; // Zone of received symbol with respect to grid of QAM constellation diagram
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup Received modulation symbol zone
|
||||||
|
* Determine location of received modulation symbol
|
||||||
|
*
|
||||||
|
* \param in input symbol (_Complex float)
|
||||||
|
* \param z associated zone in constellation diagram (int)
|
||||||
|
* \param N number of symbols
|
||||||
|
*/
|
||||||
|
static void zone_QPSK(const cf_t * in, uint32_t * z, int N)
|
||||||
{
|
{
|
||||||
int i, s, b;
|
|
||||||
float num, den;
|
|
||||||
int change_sign = -1;
|
|
||||||
float x, y, d[64];
|
|
||||||
|
|
||||||
for (s = 0; s < N; s++) { /* recevied symbols */
|
int s;
|
||||||
/* Compute the distances squared d[i] between the received symbol and all constellation points */
|
float re, im;
|
||||||
for (i = 0; i < M; i++) {
|
|
||||||
x = __real__ in[s] - __real__ symbols[i];
|
|
||||||
y = __imag__ in[s] - __imag__ symbols[i];
|
|
||||||
d[i] = x * x + y * y;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (b = 0; b < B; b++) { /* bits per symbol */
|
for (s = 0; s < N; s++) {
|
||||||
/* initiate num[b] and den[b] */
|
|
||||||
num = d[S[0][b][0]];
|
|
||||||
den = d[S[1][b][0]];
|
|
||||||
|
|
||||||
/* Minimum distance squared search between recevied symbol and a constellation point with a
|
re = __real__ in[s];
|
||||||
'1' and a '0' for each bit position */
|
im = __imag__ in[s];
|
||||||
for (i = 1; i < M / 2; i++) { /* half the constellation points have '1'|'0' at any given bit position */
|
|
||||||
if (d[S[0][b][i]] < num) {
|
if (re > 0) {
|
||||||
num = d[S[0][b][i]];
|
if (im > 0) { /* 1st Quadrand (upper-right) */
|
||||||
}
|
z[s] = 0;
|
||||||
if (d[S[1][b][i]] < den) {
|
} else { /* 4th Quadrand (lower-right) */
|
||||||
den = d[S[1][b][i]];
|
z[s] = 1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (im > 0) { /* 2nd Quadrand (upper-left) */
|
||||||
|
z[s] = 2;
|
||||||
|
} else { /* 3rd Quadrand (lower-left) */
|
||||||
|
z[s] = 3;
|
||||||
}
|
}
|
||||||
/* Theoretical LLR and approximate LLR values are positive if
|
|
||||||
* symbol(s) with '0' is/are closer and negative if symbol(s)
|
|
||||||
* with '1' are closer.
|
|
||||||
* Change sign if mapping negative to '0' and positive to '1' */
|
|
||||||
out[s * B + b] = change_sign * (den - num) / sigma2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
/**
|
||||||
|
* @ingroup Received modulation symbol zone
|
||||||
|
* Determine location of received modulation symbol
|
||||||
|
*
|
||||||
|
* \param in input symbol (_Complex float)
|
||||||
|
* \param z associated zone in constellation diagram (int)
|
||||||
|
* \param N number of symbols
|
||||||
|
*/
|
||||||
|
static void zone_QAM16(const cf_t * in, uint32_t * z, int N)
|
||||||
|
{
|
||||||
|
|
||||||
|
int s;
|
||||||
|
float re, im;
|
||||||
|
|
||||||
|
for (s = 0; s < N; s++) {
|
||||||
|
|
||||||
|
re = __real__ in[s];
|
||||||
|
im = __imag__ in[s];
|
||||||
|
|
||||||
|
if (re > 0) {
|
||||||
|
if (im > 0) { /* 1st Quadrand (upper-right) */
|
||||||
|
if (re > QAM16_THRESHOLD) {
|
||||||
|
if (im > QAM16_THRESHOLD) {
|
||||||
|
z[s] = 3;
|
||||||
|
} else {
|
||||||
|
z[s] = 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (im > QAM16_THRESHOLD) {
|
||||||
|
z[s] = 1;
|
||||||
|
} else {
|
||||||
|
z[s] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { /* 4th Quadrand (lower-right) */
|
||||||
|
if (re > QAM16_THRESHOLD) {
|
||||||
|
if (im < -QAM16_THRESHOLD) {
|
||||||
|
z[s] = 7;
|
||||||
|
} else {
|
||||||
|
z[s] = 6;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (im < -QAM16_THRESHOLD) {
|
||||||
|
z[s] = 5;
|
||||||
|
} else {
|
||||||
|
z[s] = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (im > 0) { /* 2nd Quadrand (upper-left) */
|
||||||
|
if (re < -QAM16_THRESHOLD) {
|
||||||
|
if (im > QAM16_THRESHOLD) {
|
||||||
|
z[s] = 11;
|
||||||
|
} else {
|
||||||
|
z[s] = 10;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (im > QAM16_THRESHOLD) {
|
||||||
|
z[s] = 9;
|
||||||
|
} else {
|
||||||
|
z[s] = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { /* 3rd Quadrand (lower-left) */
|
||||||
|
if (re < -QAM16_THRESHOLD) {
|
||||||
|
if (im < -QAM16_THRESHOLD) {
|
||||||
|
z[s] = 15;
|
||||||
|
} else {
|
||||||
|
z[s] = 14;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (im < -QAM16_THRESHOLD) {
|
||||||
|
z[s] = 13;
|
||||||
|
} else {
|
||||||
|
z[s] = 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup Received modulation symbol zone
|
||||||
|
* Determine location of received modulation symbol
|
||||||
|
*
|
||||||
|
* \param in input symbol (_Complex float)
|
||||||
|
* \param z associated zone in constellation diagram (int)
|
||||||
|
* \param N number of symbols
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void zone_QAM64(const cf_t * in, uint32_t * z, int N)
|
||||||
|
{
|
||||||
|
|
||||||
|
int s;
|
||||||
|
float re, im;
|
||||||
|
|
||||||
|
for (s = 0; s < N; s++) {
|
||||||
|
|
||||||
|
re = __real__ in[s];
|
||||||
|
im = __imag__ in[s];
|
||||||
|
|
||||||
|
if (re > 0) {
|
||||||
|
|
||||||
|
if (im > 0) {
|
||||||
|
|
||||||
|
if (re > QAM64_THRESHOLD_2) {
|
||||||
|
|
||||||
|
if (re > QAM64_THRESHOLD_3) {
|
||||||
|
|
||||||
|
if (im > QAM64_THRESHOLD_2) {
|
||||||
|
if (im > QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 15;
|
||||||
|
} else {
|
||||||
|
z[s] = 14;
|
||||||
|
}
|
||||||
|
} else if (im > QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 10;
|
||||||
|
} else {
|
||||||
|
z[s] = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (im > QAM64_THRESHOLD_2) {
|
||||||
|
if (im > QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 13;
|
||||||
|
} else {
|
||||||
|
z[s] = 12;
|
||||||
|
}
|
||||||
|
} else if (im > QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 8;
|
||||||
|
} else {
|
||||||
|
z[s] = 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (re > QAM64_THRESHOLD_1) {
|
||||||
|
|
||||||
|
if (im > QAM64_THRESHOLD_2) {
|
||||||
|
if (im > QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 5;
|
||||||
|
} else {
|
||||||
|
z[s] = 4;
|
||||||
|
}
|
||||||
|
} else if (im > QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 0;
|
||||||
|
} else {
|
||||||
|
z[s] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (im > QAM64_THRESHOLD_2) {
|
||||||
|
if (im > QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 7;
|
||||||
|
} else {
|
||||||
|
z[s] = 6;
|
||||||
|
}
|
||||||
|
} else if (im > QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 2;
|
||||||
|
} else {
|
||||||
|
z[s] = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { /* forth quadrant (lower-right) */
|
||||||
|
|
||||||
|
if (re > QAM64_THRESHOLD_2) {
|
||||||
|
|
||||||
|
if (re > QAM64_THRESHOLD_3) {
|
||||||
|
|
||||||
|
if (im < -QAM64_THRESHOLD_2) {
|
||||||
|
if (im < -QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 31;
|
||||||
|
} else {
|
||||||
|
z[s] = 30;
|
||||||
|
}
|
||||||
|
} else if (im < -QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 26;
|
||||||
|
} else {
|
||||||
|
z[s] = 27;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (im < -QAM64_THRESHOLD_2) {
|
||||||
|
if (im < -QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 29;
|
||||||
|
} else {
|
||||||
|
z[s] = 28;
|
||||||
|
}
|
||||||
|
} else if (im < -QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 24;
|
||||||
|
} else {
|
||||||
|
z[s] = 25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (re > QAM64_THRESHOLD_1) {
|
||||||
|
|
||||||
|
if (im < -QAM64_THRESHOLD_2) {
|
||||||
|
if (im < -QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 21;
|
||||||
|
} else {
|
||||||
|
z[s] = 20;
|
||||||
|
}
|
||||||
|
} else if (im < -QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 16;
|
||||||
|
} else {
|
||||||
|
z[s] = 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (im < -QAM64_THRESHOLD_2) {
|
||||||
|
if (im < -QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 23;
|
||||||
|
} else {
|
||||||
|
z[s] = 22;
|
||||||
|
}
|
||||||
|
} else if (im < -QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 18;
|
||||||
|
} else {
|
||||||
|
z[s] = 19;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { /* re < 0 */
|
||||||
|
|
||||||
|
if (im > 0) { /* second quadrant (upper-left) */
|
||||||
|
|
||||||
|
if (re < -QAM64_THRESHOLD_2) {
|
||||||
|
|
||||||
|
if (re < -QAM64_THRESHOLD_3) {
|
||||||
|
|
||||||
|
if (im > QAM64_THRESHOLD_2) {
|
||||||
|
if (im > QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 47;
|
||||||
|
} else {
|
||||||
|
z[s] = 46;
|
||||||
|
}
|
||||||
|
} else if (im > QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 42;
|
||||||
|
} else {
|
||||||
|
z[s] = 43;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (im > QAM64_THRESHOLD_2) {
|
||||||
|
if (im > QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 45;
|
||||||
|
} else {
|
||||||
|
z[s] = 44;
|
||||||
|
}
|
||||||
|
} else if (im > QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 40;
|
||||||
|
} else {
|
||||||
|
z[s] = 41;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (re < -QAM64_THRESHOLD_1) {
|
||||||
|
|
||||||
|
if (im > QAM64_THRESHOLD_2) {
|
||||||
|
if (im > QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 37;
|
||||||
|
} else {
|
||||||
|
z[s] = 36;
|
||||||
|
}
|
||||||
|
} else if (im > QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 32;
|
||||||
|
} else {
|
||||||
|
z[s] = 33;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (im > QAM64_THRESHOLD_2) {
|
||||||
|
if (im > QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 39;
|
||||||
|
} else {
|
||||||
|
z[s] = 38;
|
||||||
|
}
|
||||||
|
} else if (im > QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 34;
|
||||||
|
} else {
|
||||||
|
z[s] = 35;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { /* third quadrant (lower-left) */
|
||||||
|
if (re < -QAM64_THRESHOLD_2) {
|
||||||
|
|
||||||
|
if (re < -QAM64_THRESHOLD_3) {
|
||||||
|
|
||||||
|
if (im < -QAM64_THRESHOLD_2) {
|
||||||
|
if (im < -QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 63;
|
||||||
|
} else {
|
||||||
|
z[s] = 62;
|
||||||
|
}
|
||||||
|
} else if (im < -QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 58;
|
||||||
|
} else {
|
||||||
|
z[s] = 59;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (im < -QAM64_THRESHOLD_2) {
|
||||||
|
if (im < -QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 61;
|
||||||
|
} else {
|
||||||
|
z[s] = 60;
|
||||||
|
}
|
||||||
|
} else if (im < -QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 56;
|
||||||
|
} else {
|
||||||
|
z[s] = 57;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (re < -QAM64_THRESHOLD_1) {
|
||||||
|
|
||||||
|
if (im < -QAM64_THRESHOLD_2) {
|
||||||
|
if (im < -QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 53;
|
||||||
|
} else {
|
||||||
|
z[s] = 52;
|
||||||
|
}
|
||||||
|
} else if (im < -QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 48;
|
||||||
|
} else {
|
||||||
|
z[s] = 49;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (im < -QAM64_THRESHOLD_2) {
|
||||||
|
if (im < -QAM64_THRESHOLD_3) {
|
||||||
|
z[s] = 55;
|
||||||
|
} else {
|
||||||
|
z[s] = 54;
|
||||||
|
}
|
||||||
|
} else if (im < -QAM64_THRESHOLD_1) {
|
||||||
|
z[s] = 50;
|
||||||
|
} else {
|
||||||
|
z[s] = 51;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compute_zone(const cf_t * in, uint32_t * z, int N, int B)
|
||||||
|
{
|
||||||
|
switch (B) {
|
||||||
|
case 1:{
|
||||||
|
memset(zone, 0, N * sizeof(int));
|
||||||
|
break;
|
||||||
|
} /* BPSK */
|
||||||
|
case 2:{
|
||||||
|
zone_QPSK(in, z, N);
|
||||||
|
break;
|
||||||
|
} /* QPSK */
|
||||||
|
case 4:{
|
||||||
|
zone_QAM16(in, z, N);
|
||||||
|
break;
|
||||||
|
} /* 16QAM */
|
||||||
|
case 6:{
|
||||||
|
zone_QAM64(in, z, N);
|
||||||
|
break;
|
||||||
|
} /* 64QAM */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compute_square_dist(const cf_t * in, cf_t * symbols,
|
||||||
|
uint32_t(*idx)[7], int N, int B)
|
||||||
|
{
|
||||||
|
int s, b;
|
||||||
|
float *d_ptr;
|
||||||
|
cf_t symbols_extract[7];
|
||||||
|
|
||||||
|
for (s = 0; s < N; s++) { /* N: number of received symbols */
|
||||||
|
d_ptr = dd[s];
|
||||||
|
for (b = 0; b < B + 1; b++) {
|
||||||
|
symbols_extract[b] = symbols[idx[zone[s]][b]]; /* only subset of distances to constellation points needed for LLR approx */
|
||||||
|
//x = __real__ in[s] - __real__ symbols[idx[zone[s]][b]];
|
||||||
|
//y = __imag__ in[s] - __imag__ symbols[idx[zone[s]][b]];
|
||||||
|
//dd[s][b] = x*x + y*y;
|
||||||
|
//printf("\n%f + j %f", __real__ symbols_extract[b], __imag__ symbols_extract[b]);
|
||||||
|
}
|
||||||
|
vec_square_dist(in[s], symbols_extract, d_ptr, B + 1); /* B+1 distances to be computed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compute_llr(int N, int B, uint32_t(*min)[64][6], float sigma2,
|
||||||
|
float *out)
|
||||||
|
{
|
||||||
|
int s, b;
|
||||||
|
for (s = 0; s < N; s++) {
|
||||||
|
for (b = 0; b < B; b++) { /* bits per symbol */
|
||||||
|
out[s * B + b] =
|
||||||
|
(dd[s][min[0][zone[s]][b]] - dd[s][min[1][zone[s]][b]]) / sigma2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
|
||||||
|
_Complex float *symbols, uint32_t(*S)[6][32], uint32_t(*idx)[7],
|
||||||
|
uint32_t(*min)[64][6], float sigma2)
|
||||||
|
{
|
||||||
|
if ((M == 2) || (M == 4) || (M == 16) || (M == 64)) {
|
||||||
|
compute_zone(in, zone, N, B);
|
||||||
|
compute_square_dist(in, symbols, idx, N, B);
|
||||||
|
compute_llr(N, B, min, sigma2, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif LLR_APPROX_IMPLEMENTATION == 2
|
||||||
|
|
||||||
|
float d[10000][64];
|
||||||
|
float num[10000], den[10000];
|
||||||
|
|
||||||
|
static void compute_square_dist(const cf_t * in, cf_t * symbols, int N, int M)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
float *d_ptr;
|
||||||
|
for (s = 0; s < N; s++) {
|
||||||
|
d_ptr = d[s];
|
||||||
|
vec_square_dist(in[s], symbols, d_ptr, M);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compute_min_dist(uint32_t(*S)[6][32], int N, int B, int M)
|
||||||
|
{
|
||||||
|
int s, b, i;
|
||||||
|
for (s = 0; s < N; s++) {
|
||||||
|
for (b = 0; b < B; b++) { /* bits per symbol */
|
||||||
|
/* initiate num[b] and den[b] */
|
||||||
|
num[s * B + b] = 1e10;
|
||||||
|
den[s * B + b] = 1e10;
|
||||||
|
|
||||||
|
for (i = 0; i < M / 2; i++) {
|
||||||
|
if (d[s][S[0][b][i]] < num[s * B + b]) {
|
||||||
|
num[s * B + b] = d[s][S[0][b][i]];
|
||||||
|
}
|
||||||
|
if (d[s][S[1][b][i]] < den[s * B + b]) {
|
||||||
|
den[s * B + b] = d[s][S[1][b][i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compute_llr(int N, int B, float sigma2, float *out)
|
||||||
|
{
|
||||||
|
int s, b;
|
||||||
|
for (s = 0; s < N; s++) {
|
||||||
|
for (b = 0; b < B; b++) { /* bits per symbol */
|
||||||
|
out[s * B + b] = (num[s * B + b] - den[s * B + b]) / sigma2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
|
||||||
|
_Complex float *symbols, uint32_t(*S)[6][32], float sigma2)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (M <= 64) {
|
||||||
|
compute_square_dist(in, symbols, N, M);
|
||||||
|
|
||||||
|
compute_min_dist(S, N, B, M);
|
||||||
|
|
||||||
|
compute_llr(N, B, sigma2, out);
|
||||||
|
}
|
||||||
|
for (b = 0; b < B; b++) { /* bits per symbol */
|
||||||
|
out[s * B + b] = (num[s * B + b] - den[s * B + b]) / sigma2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
|
||||||
|
_Complex float *symbols, uint32_t(*S)[6][32], uint32_t(*idx)[7],
|
||||||
|
uint32_t(*min)[64][6], float sigma2)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (M <= 64) {
|
||||||
|
compute_square_dist(in, symbols, N, M);
|
||||||
|
|
||||||
|
compute_min_dist(S, N, B, M);
|
||||||
|
|
||||||
|
compute_llr(N, B, sigma2, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup Soft Modulation Demapping based on the approximate
|
* @ingroup Soft Modulation Demapping based on the approximate
|
||||||
|
@ -98,9 +602,9 @@ llr_approx(const _Complex float *in, float *out, int N, int M, int B,
|
||||||
* \param S Soft demapping auxiliary matrix
|
* \param S Soft demapping auxiliary matrix
|
||||||
* \param sigma2 Noise vatiance
|
* \param sigma2 Noise vatiance
|
||||||
*/
|
*/
|
||||||
void
|
void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
|
||||||
llr_approx(const _Complex float *in, float *out, int N, int M, int B,
|
_Complex float *symbols, uint32_t(*S)[6][32], uint32_t(*idx)[7],
|
||||||
_Complex float *symbols, uint32_t(*S)[6][32], float sigma2)
|
uint32_t(*min)[64][6], float sigma2)
|
||||||
{
|
{
|
||||||
int i, s, b;
|
int i, s, b;
|
||||||
float num, den;
|
float num, den;
|
||||||
|
@ -135,8 +639,12 @@ llr_approx(const _Complex float *in, float *out, int N, int M, int B,
|
||||||
* with '1' are closer.
|
* with '1' are closer.
|
||||||
* Change sign if mapping negative to '0' and positive to '1' */
|
* Change sign if mapping negative to '0' and positive to '1' */
|
||||||
out[s * B + b] = change_sign * (den - num) / sigma2;
|
out[s * B + b] = change_sign * (den - num) / sigma2;
|
||||||
|
if (s < 10)
|
||||||
|
printf("out[%d]=%f=%f/%f\n", s * B + b, out[s * B + b], num, den);
|
||||||
}
|
}
|
||||||
}
|
/* if (s<10)
|
||||||
|
printf("out[%d]=%f=%f/%f\n",s*B+b,out[s*B+b], num,den);
|
||||||
|
*/ }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +667,7 @@ llr_approx(const _Complex float *in, float *out, int N, int M, int B,
|
||||||
* \param sigma2 Noise vatiance
|
* \param sigma2 Noise vatiance
|
||||||
*/
|
*/
|
||||||
void llr_exact(const _Complex float *in, float *out, int N, int M, int B,
|
void llr_exact(const _Complex float *in, float *out, int N, int M, int B,
|
||||||
_Complex float *symbols, uint32_t(*S)[6][32], float sigma2)
|
_Complex float *symbols, uint32_t(*S)[6][32], float sigma2)
|
||||||
{
|
{
|
||||||
int i, s, b;
|
int i, s, b;
|
||||||
float num, den;
|
float num, den;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
void llr_approx(const _Complex float *in,
|
/*void llr_approx(const _Complex float *in,
|
||||||
float *out,
|
float *out,
|
||||||
int N,
|
int N,
|
||||||
int M,
|
int M,
|
||||||
|
@ -34,6 +34,17 @@ void llr_approx(const _Complex float *in,
|
||||||
_Complex float *symbols,
|
_Complex float *symbols,
|
||||||
uint32_t (*S)[6][32],
|
uint32_t (*S)[6][32],
|
||||||
float sigma2);
|
float sigma2);
|
||||||
|
*/
|
||||||
|
void llr_approx(const _Complex float *in,
|
||||||
|
float *out,
|
||||||
|
int N,
|
||||||
|
int M,
|
||||||
|
int B,
|
||||||
|
_Complex float *symbols,
|
||||||
|
uint32_t (*S)[6][32],
|
||||||
|
uint32_t (*idx)[7], /*64x7 table of integers [0..63], indices to 7 distances to be computed */
|
||||||
|
uint32_t (*min)[64][6], /*2x64x6 table of integers [0..6], indices to 2x6 nearest symbols */
|
||||||
|
float sigma2);
|
||||||
|
|
||||||
void llr_exact(const _Complex float *in,
|
void llr_exact(const _Complex float *in,
|
||||||
float *out,
|
float *out,
|
||||||
|
@ -43,3 +54,4 @@ void llr_exact(const _Complex float *in,
|
||||||
_Complex float *symbols,
|
_Complex float *symbols,
|
||||||
uint32_t (*S)[6][32],
|
uint32_t (*S)[6][32],
|
||||||
float sigma2);
|
float sigma2);
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
|
|
||||||
#include "liblte/phy/phy.h"
|
#include "liblte/phy/phy.h"
|
||||||
|
|
||||||
|
time_t start, finish;
|
||||||
|
struct timeval x, y;
|
||||||
|
|
||||||
int num_bits = 1000;
|
int num_bits = 1000;
|
||||||
lte_mod_t modulation;
|
lte_mod_t modulation;
|
||||||
bool soft_output = false, soft_exact = false;
|
bool soft_output = false, soft_exact = false;
|
||||||
|
@ -98,6 +101,10 @@ int main(int argc, char **argv) {
|
||||||
cf_t *symbols;
|
cf_t *symbols;
|
||||||
float *llr;
|
float *llr;
|
||||||
|
|
||||||
|
// unsigned long strt, fin;
|
||||||
|
// strt = x->tv_usec;
|
||||||
|
// fin = y->tv_usec;
|
||||||
|
|
||||||
parse_args(argc, argv);
|
parse_args(argc, argv);
|
||||||
|
|
||||||
/* initialize objects */
|
/* initialize objects */
|
||||||
|
@ -156,7 +163,12 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
/* demodulate */
|
/* demodulate */
|
||||||
if (soft_output) {
|
if (soft_output) {
|
||||||
|
|
||||||
|
gettimeofday(&x, NULL);
|
||||||
demod_soft_demodulate(&demod_soft, symbols, llr, num_bits / mod.nbits_x_symbol);
|
demod_soft_demodulate(&demod_soft, symbols, llr, num_bits / mod.nbits_x_symbol);
|
||||||
|
gettimeofday(&y, NULL);
|
||||||
|
printf("\nElapsed time [ns]: %d\n", (int) y.tv_usec - (int) x.tv_usec);
|
||||||
|
|
||||||
for (i=0;i<num_bits;i++) {
|
for (i=0;i<num_bits;i++) {
|
||||||
output[i] = llr[i]>=0 ? 1 : 0;
|
output[i] = llr[i]>=0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ float mse_threshold() {
|
||||||
case LTE_QAM16:
|
case LTE_QAM16:
|
||||||
return 0.11;
|
return 0.11;
|
||||||
case LTE_QAM64:
|
case LTE_QAM64:
|
||||||
return 0.18;
|
return 0.19;
|
||||||
default:
|
default:
|
||||||
return -1.0;
|
return -1.0;
|
||||||
}
|
}
|
||||||
|
@ -129,6 +129,7 @@ int main(int argc, char **argv) {
|
||||||
demod_soft_table_set(&demod_soft, &mod);
|
demod_soft_table_set(&demod_soft, &mod);
|
||||||
demod_soft_sigma_set(&demod_soft, 2.0 / mod.nbits_x_symbol);
|
demod_soft_sigma_set(&demod_soft, 2.0 / mod.nbits_x_symbol);
|
||||||
|
|
||||||
|
|
||||||
/* allocate buffers */
|
/* allocate buffers */
|
||||||
input = malloc(sizeof(char) * num_bits);
|
input = malloc(sizeof(char) * num_bits);
|
||||||
if (!input) {
|
if (!input) {
|
||||||
|
@ -159,7 +160,7 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate random data */
|
/* generate random data */
|
||||||
srand(time(NULL));
|
srand(0);
|
||||||
|
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
double mse;
|
double mse;
|
||||||
|
@ -187,7 +188,9 @@ int main(int argc, char **argv) {
|
||||||
get_time_interval(t);
|
get_time_interval(t);
|
||||||
|
|
||||||
/* compute exponentially averaged execution time */
|
/* compute exponentially averaged execution time */
|
||||||
mean_texec = EXPAVERAGE((float) t[0].tv_usec, mean_texec, n);
|
if (n > 0) {
|
||||||
|
mean_texec = EXPAVERAGE((float) t[0].tv_usec, mean_texec, n-1);
|
||||||
|
}
|
||||||
|
|
||||||
/* check MSE */
|
/* check MSE */
|
||||||
mse = 0.0;
|
mse = 0.0;
|
||||||
|
|
|
@ -30,8 +30,6 @@
|
||||||
#include <complex.h>
|
#include <complex.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define EXPAVERAGE(data, average, nframes) ((data + average * nframes) / (nframes + 1))
|
|
||||||
|
|
||||||
#define CURRENT_FFTSIZE lte_symbol_sz(q->cell.nof_prb)
|
#define CURRENT_FFTSIZE lte_symbol_sz(q->cell.nof_prb)
|
||||||
#define CURRENT_SFLEN SF_LEN(CURRENT_FFTSIZE, q->cell.cp)
|
#define CURRENT_SFLEN SF_LEN(CURRENT_FFTSIZE, q->cell.cp)
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,19 @@ cf_t vec_acc_cc(cf_t *x, uint32_t len) {
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints) {
|
||||||
|
#ifndef HAVE_VOLK_SQUARE_DIST_FUNCTION
|
||||||
|
uint32_t i;
|
||||||
|
cf_t diff;
|
||||||
|
for (i=0;i<npoints;i++) {
|
||||||
|
diff = symbol - points[i];
|
||||||
|
distance[i] = crealf(diff) * crealf(diff) + cimagf(diff) * cimagf(diff);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
volk_32fc_x2_square_dist_32f(distance,&symbol,points,npoints);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void vec_sub_fff(float *x, float *y, float *z, uint32_t len) {
|
void vec_sub_fff(float *x, float *y, float *z, uint32_t len) {
|
||||||
#ifndef HAVE_VOLK_SUB_FLOAT_FUNCTION
|
#ifndef HAVE_VOLK_SUB_FLOAT_FUNCTION
|
||||||
int i;
|
int i;
|
||||||
|
|
Loading…
Reference in New Issue