Merged soft demodulation improvements from marojevic

master
ismagom 11 years ago
commit 65760bb37d

@ -40,6 +40,9 @@
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 {

@ -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,20 +31,490 @@
#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" #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; typedef _Complex float cf_t;
// There are 3 implemenations: 1 - based on zones; 2 - using volk, 3 - straightforward C
#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 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) */
z[s] = 0;
} else { /* 4th Quadrand (lower-right) */
z[s] = 1;
}
} else {
if (im > 0) { /* 2nd Quadrand (upper-left) */
z[s] = 2;
} else { /* 3rd Quadrand (lower-left) */
z[s] = 3;
}
}
}
}
/**
* @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 d[10000][64];
float num[10000], den[10000]; float num[10000], den[10000];
static void compute_square_dist(const cf_t *in, cf_t *symbols, int N, int M) { static void compute_square_dist(const cf_t * in, cf_t * symbols, int N, int M)
{
int s; int s;
float *d_ptr; float *d_ptr;
for (s = 0; s < N; s++) { for (s = 0; s < N; s++) {
@ -53,7 +523,8 @@ static void compute_square_dist(const cf_t *in, cf_t *symbols, int N, int M) {
} }
} }
static void compute_min_dist(uint32_t (*S)[6][32], int N, int B, int M) { static void compute_min_dist(uint32_t(*S)[6][32], int N, int B, int M)
{
int s, b, i; int s, b, i;
for (s = 0; s < N; s++) { for (s = 0; s < N; s++) {
for (b = 0; b < B; b++) { /* bits per symbol */ for (b = 0; b < B; b++) { /* bits per symbol */
@ -73,11 +544,12 @@ static void compute_min_dist(uint32_t (*S)[6][32], int N, int B, int M) {
} }
} }
static void compute_llr(int N, int B, float sigma2, float *out) { static void compute_llr(int N, int B, float sigma2, float *out)
{
int s, b; int s, b;
for (s = 0; s < N; s++) { for (s = 0; s < N; s++) {
for (b = 0; b < B; b++) { /* bits per symbol */ for (b = 0; b < B; b++) { /* bits per symbol */
out[s * B + b] = (num[s * B + b]-den[s * B + b]) / sigma2; out[s * B + b] = (num[s * B + b] - den[s * B + b]) / sigma2;
} }
} }
} }
@ -86,6 +558,23 @@ 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) _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) { if (M <= 64) {
compute_square_dist(in, symbols, N, M); compute_square_dist(in, symbols, N, M);
@ -113,9 +602,9 @@ void 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;
@ -150,10 +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) if (s < 10)
printf("out[%d]=%f=%f/%f\n",s*B+b,out[s*B+b], num,den); 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);
*/ }
} }

@ -26,6 +26,15 @@
*/ */
/*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);
*/
void llr_approx(const _Complex float *in, void llr_approx(const _Complex float *in,
float *out, float *out,
int N, int N,
@ -33,6 +42,8 @@ void llr_approx(const _Complex float *in,
int B, int B,
_Complex float *symbols, _Complex float *symbols,
uint32_t (*S)[6][32], 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); float sigma2);
void llr_exact(const _Complex float *in, void llr_exact(const _Complex float *in,
@ -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;
} }

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

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

@ -39,7 +39,7 @@
#endif #endif
int vec_acc_ii(int *x, uint32_t len) { int vec_acc_ii(int *x, uint32_t len) {
uint32_t i; int i;
int z=0; int z=0;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z+=x[i]; z+=x[i];
@ -53,7 +53,7 @@ float vec_acc_ff(float *x, uint32_t len) {
volk_32f_accumulator_s32f(&result,x,len); volk_32f_accumulator_s32f(&result,x,len);
return result; return result;
#else #else
uint32_t i; int i;
float z=0; float z=0;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z+=x[i]; z+=x[i];
@ -63,7 +63,7 @@ float vec_acc_ff(float *x, uint32_t len) {
} }
cf_t vec_acc_cc(cf_t *x, uint32_t len) { cf_t vec_acc_cc(cf_t *x, uint32_t len) {
uint32_t i; int i;
cf_t z=0; cf_t z=0;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z+=x[i]; z+=x[i];
@ -86,7 +86,7 @@ void vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoint
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
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i]-y[i]; z[i] = x[i]-y[i];
} }
@ -96,14 +96,14 @@ void vec_sub_fff(float *x, float *y, float *z, uint32_t len) {
} }
void vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) { void vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) {
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i]+y[i]; z[i] = x[i]+y[i];
} }
} }
void vec_sum_bbb(char *x, char *y, char *z, uint32_t len) { void vec_sum_bbb(char *x, char *y, char *z, uint32_t len) {
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i]+y[i]; z[i] = x[i]+y[i];
} }
@ -111,7 +111,7 @@ void vec_sum_bbb(char *x, char *y, char *z, uint32_t len) {
void vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) { void vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_FLOAT_FUNCTION #ifndef HAVE_VOLK_MULT_FLOAT_FUNCTION
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i]*h; z[i] = x[i]*h;
} }
@ -122,7 +122,7 @@ void vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) {
void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) { void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_FUNCTION #ifndef HAVE_VOLK_MULT_FUNCTION
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i]*h; z[i] = x[i]*h;
} }
@ -136,7 +136,7 @@ void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) {
void vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len) { void vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_FUNCTION #ifndef HAVE_VOLK_MULT_FUNCTION
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i]*h; z[i] = x[i]*h;
} }
@ -149,7 +149,7 @@ void vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len) {
#ifdef HAVE_VOLK_CONVERT_FI_FUNCTION #ifdef HAVE_VOLK_CONVERT_FI_FUNCTION
volk_32f_s32f_convert_16i(z, x, scale, len); volk_32f_s32f_convert_16i(z, x, scale, len);
#else #else
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = (int16_t) (x[i]*scale); z[i] = (int16_t) (x[i]*scale);
} }
@ -160,7 +160,7 @@ void vec_deinterleave_cf(cf_t *x, float *real, float *imag, uint32_t len) {
#ifdef HAVE_VOLK_DEINTERLEAVE_FUNCTION #ifdef HAVE_VOLK_DEINTERLEAVE_FUNCTION
volk_32fc_deinterleave_32f_x2(real, imag, x, len); volk_32fc_deinterleave_32f_x2(real, imag, x, len);
#else #else
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
real[i] = __real__ x[i]; real[i] = __real__ x[i];
imag[i] = __imag__ x[i]; imag[i] = __imag__ x[i];
@ -209,7 +209,7 @@ void *vec_realloc(void *ptr, uint32_t old_size, uint32_t new_size) {
void vec_fprint_c(FILE *stream, cf_t *x, uint32_t len) { void vec_fprint_c(FILE *stream, cf_t *x, uint32_t len) {
uint32_t i; int i;
fprintf(stream, "["); fprintf(stream, "[");
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
fprintf(stream, "%+2.2f%+2.2fi, ", __real__ x[i], __imag__ x[i]); fprintf(stream, "%+2.2f%+2.2fi, ", __real__ x[i], __imag__ x[i]);
@ -218,7 +218,7 @@ void vec_fprint_c(FILE *stream, cf_t *x, uint32_t len) {
} }
void vec_fprint_f(FILE *stream, float *x, uint32_t len) { void vec_fprint_f(FILE *stream, float *x, uint32_t len) {
uint32_t i; int i;
fprintf(stream, "["); fprintf(stream, "[");
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
fprintf(stream, "%+2.2f, ", x[i]); fprintf(stream, "%+2.2f, ", x[i]);
@ -228,7 +228,7 @@ void vec_fprint_f(FILE *stream, float *x, uint32_t len) {
void vec_fprint_b(FILE *stream, char *x, uint32_t len) { void vec_fprint_b(FILE *stream, char *x, uint32_t len) {
uint32_t i; int i;
fprintf(stream, "["); fprintf(stream, "[");
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
fprintf(stream, "%d, ", x[i]); fprintf(stream, "%d, ", x[i]);
@ -237,7 +237,7 @@ void vec_fprint_b(FILE *stream, char *x, uint32_t len) {
} }
void vec_fprint_i(FILE *stream, int *x, uint32_t len) { void vec_fprint_i(FILE *stream, int *x, uint32_t len) {
uint32_t i; int i;
fprintf(stream, "["); fprintf(stream, "[");
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
fprintf(stream, "%d, ", x[i]); fprintf(stream, "%d, ", x[i]);
@ -273,7 +273,7 @@ void vec_save_file(char *filename, void *buffer, uint32_t len) {
void vec_conj_cc(cf_t *x, cf_t *y, uint32_t len) { void vec_conj_cc(cf_t *x, cf_t *y, uint32_t len) {
#ifndef HAVE_VOLK_CONJ_FUNCTION #ifndef HAVE_VOLK_CONJ_FUNCTION
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
y[i] = conjf(x[i]); y[i] = conjf(x[i]);
} }
@ -284,7 +284,7 @@ void vec_conj_cc(cf_t *x, cf_t *y, uint32_t len) {
void vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len) { void vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_REAL_FUNCTION #ifndef HAVE_VOLK_MULT_REAL_FUNCTION
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i]*y[i]; z[i] = x[i]*y[i];
} }
@ -296,7 +296,7 @@ void vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len) {
void vec_prod_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) { void vec_prod_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT2_FUNCTION #ifndef HAVE_VOLK_MULT2_FUNCTION
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i]*y[i]; z[i] = x[i]*y[i];
} }
@ -308,7 +308,7 @@ void vec_prod_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
void vec_prod_conj_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) { void vec_prod_conj_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT2_CONJ_FUNCTION #ifndef HAVE_VOLK_MULT2_CONJ_FUNCTION
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i]*conjf(y[i]); z[i] = x[i]*conjf(y[i]);
} }
@ -318,7 +318,7 @@ void vec_prod_conj_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
} }
void vec_div_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) { void vec_div_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) {
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i] / y[i]; z[i] = x[i] / y[i];
} }
@ -328,7 +328,7 @@ void vec_div_fff(float *x, float *y, float *z, uint32_t len) {
#ifdef HAVE_VOLK_DIVIDE_FUNCTION #ifdef HAVE_VOLK_DIVIDE_FUNCTION
volk_32f_x2_divide_32f(z, x, y, len); volk_32f_x2_divide_32f(z, x, y, len);
#else #else
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = x[i] / y[i]; z[i] = x[i] / y[i];
} }
@ -383,7 +383,7 @@ float vec_dot_prod_fff(float *x, float *y, uint32_t len) {
float vec_avg_power_cf(cf_t *x, uint32_t len) { float vec_avg_power_cf(cf_t *x, uint32_t len) {
uint32_t j; int j;
float power = 0; float power = 0;
for (j=0;j<len;j++) { for (j=0;j<len;j++) {
power += crealf(x[j]*conjf(x[j])); power += crealf(x[j]*conjf(x[j]));
@ -393,7 +393,7 @@ float vec_avg_power_cf(cf_t *x, uint32_t len) {
void vec_abs_cf(cf_t *x, float *abs, uint32_t len) { void vec_abs_cf(cf_t *x, float *abs, uint32_t len) {
#ifndef HAVE_VOLK_MAG_FUNCTION #ifndef HAVE_VOLK_MAG_FUNCTION
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
abs[i] = cabsf(x[i]); abs[i] = cabsf(x[i]);
} }
@ -406,7 +406,7 @@ void vec_abs_cf(cf_t *x, float *abs, uint32_t len) {
void vec_arg_cf(cf_t *x, float *arg, uint32_t len) { void vec_arg_cf(cf_t *x, float *arg, uint32_t len) {
#ifndef HAVE_VOLK_ATAN_FUNCTION #ifndef HAVE_VOLK_ATAN_FUNCTION
uint32_t i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
arg[i] = cargf(x[i]); arg[i] = cargf(x[i]);
} }
@ -461,10 +461,10 @@ uint32_t vec_max_abs_ci(cf_t *x, uint32_t len) {
} }
void vec_quant_fuc(float *in, unsigned char *out, float gain, float offset, float clip, uint32_t len) { void vec_quant_fuc(float *in, unsigned char *out, float gain, float offset, float clip, uint32_t len) {
uint32_t i; int i;
uint32_t tmp; int tmp;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
tmp = (uint32_t) (offset + gain * in[i]); tmp = (int) (offset + gain * in[i]);
if (tmp < 0) if (tmp < 0)
tmp = 0; tmp = 0;
if (tmp > clip) if (tmp > clip)

Loading…
Cancel
Save