Optimized Soft demodulator for LTE modulations

master
ismagom 9 years ago
parent 50ec3a161e
commit 49717437c1

@ -76,6 +76,10 @@ SRSLTE_API int srslte_demod_soft_demodulate(srslte_demod_soft_t *q,
float* llr,
int nsymbols);
SRSLTE_API int srslte_demod_soft_demodulate_lte(srslte_mod_t modulation,
const cf_t* symbols,
float* llr,
int nsymbols);
/* High-level API */
typedef struct SRSLTE_API {

@ -76,7 +76,6 @@ typedef struct SRSLTE_API {
/* tx & rx objects */
srslte_modem_table_t mod;
srslte_demod_soft_t demod;
srslte_sequence_t seq;
srslte_viterbi_t decoder;
srslte_crc_t crc;

@ -72,8 +72,7 @@ typedef struct SRSLTE_API {
float data_f[PCFICH_CFI_LEN];
/* tx & rx objects */
srslte_modem_table_t mod;
srslte_demod_soft_t demod;
srslte_modem_table_t mod;
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_precoding_t precoding;

@ -78,7 +78,6 @@ typedef struct SRSLTE_API {
/* tx & rx objects */
srslte_modem_table_t mod;
srslte_demod_soft_t demod;
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_viterbi_t decoder;
srslte_crc_t crc;

@ -66,7 +66,7 @@ typedef struct SRSLTE_API {
/* tx & rx objects */
srslte_modem_table_t mod[4];
srslte_demod_soft_t demod;
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_precoding_t precoding;

@ -80,7 +80,6 @@ typedef struct SRSLTE_API {
/* tx & rx objects */
srslte_modem_table_t mod;
srslte_demod_soft_t demod;
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_precoding_t precoding;

@ -87,7 +87,6 @@ typedef struct SRSLTE_API {
/* tx & rx objects */
srslte_modem_table_t mod[4];
srslte_demod_soft_t demod;
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq_type2_fo;

@ -34,6 +34,7 @@
#include "srslte/modem/demod_soft.h"
#include "soft_algs.h"
//#define SCALE_DEMOD16QAM
int srslte_demod_soft_init(srslte_demod_soft_t *q, uint32_t max_symbols) {
int ret = SRSLTE_ERROR;
@ -83,6 +84,86 @@ void srslte_demod_soft_sigma_set(srslte_demod_soft_t *q, float sigma) {
q->sigma = 2*sigma;
}
void demod_bpsk_lte(const cf_t *symbols, float *llr, int nsymbols) {
for (int i=0;i<nsymbols;i++) {
llr[i] = -(crealf(symbols[i]) + cimagf(symbols[i]))/sqrt(2);
}
}
void demod_qpsk_lte(const cf_t *symbols, float *llr, int nsymbols) {
srslte_vec_sc_prod_fff((float*) symbols, -sqrt(2), llr, nsymbols*2);
}
void demod_16qam_lte(const cf_t *symbols, float *llr, int nsymbols) {
for (int i=0;i<nsymbols;i++) {
float yre = crealf(symbols[i]);
float yim = cimagf(symbols[i]);
#ifdef SCALE_DEMOD16QAM
llr[4*i+2] = (fabsf(yre)-2/sqrt(10))*sqrt(10);
llr[4*i+3] = (fabsf(yim)-2/sqrt(10))*sqrt(10);
if (llr[4*i+2] > 0) {
llr[4*i+0] = -yre/(3/sqrt(10));
} else {
llr[4*i+0] = -yre/(1/sqrt(10));
}
if (llr[4*i+3] > 0) {
llr[4*i+1] = -yim/(3/sqrt(10));
} else {
llr[4*i+1] = -yim/(1/sqrt(10));
}
#else
llr[4*i+0] = -yre;
llr[4*i+1] = -yim;
llr[4*i+2] = fabsf(yre)-2/sqrt(10);
llr[4*i+3] = fabsf(yim)-2/sqrt(10);
#endif
}
}
void demod_64qam_lte(const cf_t *symbols, float *llr, int nsymbols)
{
for (int i=0;i<nsymbols;i++) {
float yre = crealf(symbols[i]);
float yim = cimagf(symbols[i]);
llr[6*i+0] = -yre;
llr[6*i+1] = -yim;
llr[6*i+2] = fabsf(yre)-4/sqrt(42);
llr[6*i+3] = fabsf(yim)-4/sqrt(42);
llr[6*i+4] = fabsf(llr[6*i+2])-2/sqrt(42);
llr[6*i+5] = fabsf(llr[6*i+3])-2/sqrt(42);
}
}
int srslte_demod_soft_demodulate_lte(srslte_mod_t modulation, const cf_t* symbols, float* llr, int nsymbols) {
switch(modulation) {
case SRSLTE_MOD_BPSK:
demod_bpsk_lte(symbols, llr, nsymbols);
break;
case SRSLTE_MOD_QPSK:
demod_qpsk_lte(symbols, llr, nsymbols);
break;
case SRSLTE_MOD_16QAM:
demod_16qam_lte(symbols, llr, nsymbols);
break;
case SRSLTE_MOD_64QAM:
demod_64qam_lte(symbols, llr, nsymbols);
break;
default:
fprintf(stderr, "Invalid modulation %d\n", modulation);
return -1;
}
return 0;
}
int srslte_demod_soft_demodulate(srslte_demod_soft_t *q, const cf_t* symbols, float* llr, int nsymbols) {
switch(q->alg_type) {
case SRSLTE_DEMOD_SOFT_ALG_EXACT:
@ -90,20 +171,12 @@ int srslte_demod_soft_demodulate(srslte_demod_soft_t *q, const cf_t* symbols, fl
q->table->symbol_table, q->table->soft_table.idx, q->sigma);
break;
case SRSLTE_DEMOD_SOFT_ALG_APPROX:
if (nsymbols <= q->max_symbols) {
switch(q->table->nbits_x_symbol) {
case 2:
srslte_vec_sc_prod_fff((float*) symbols, -sqrt(2)/q->sigma, llr, nsymbols*2);
break;
default:
llr_approx(symbols, llr, nsymbols, q->table->nsymbols,
if (nsymbols <= q->max_symbols) {
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,
q->zones, q->dd);
break;
}
q->zones, q->dd);
} else {
fprintf(stderr, "Too many symbols (%d>%d)\n", nsymbols, q->max_symbols);
return -1;
@ -115,6 +188,8 @@ int srslte_demod_soft_demodulate(srslte_demod_soft_t *q, const cf_t* symbols, fl
/* High-Level API */
int srslte_demod_soft_initialize(srslte_demod_soft_hl* hl) {
srslte_modem_table_init(&hl->table);

@ -95,8 +95,7 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) {
int i;
srslte_modem_table_t mod;
srslte_demod_hard_t demod_hard;
srslte_demod_soft_t demod_soft;
srslte_demod_hard_t demod_hard;
uint8_t *input, *input_bytes, *output;
cf_t *symbols, *symbols_bytes;
float *llr, *llr2;
@ -117,11 +116,7 @@ int main(int argc, char **argv) {
exit(-1);
}
if (soft_output) {
srslte_demod_soft_init(&demod_soft, num_bits / mod.nbits_x_symbol);
srslte_demod_soft_table_set(&demod_soft, &mod);
srslte_demod_soft_alg_set(&demod_soft, soft_exact?SRSLTE_DEMOD_SOFT_ALG_EXACT:SRSLTE_DEMOD_SOFT_ALG_APPROX);
} else {
if (!soft_output) {
srslte_demod_hard_init(&demod_hard);
srslte_demod_hard_table_set(&demod_hard, modulation);
}
@ -204,7 +199,7 @@ int main(int argc, char **argv) {
if (soft_output) {
gettimeofday(&x, NULL);
srslte_demod_soft_demodulate(&demod_soft, symbols, llr, num_bits / mod.nbits_x_symbol);
srslte_demod_soft_demodulate_lte(modulation, 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);
@ -231,9 +226,6 @@ int main(int argc, char **argv) {
free(input_bytes);
srslte_modem_table_free(&mod);
if (soft_output) {
srslte_demod_soft_free(&demod_soft);
}
printf("Ok\n");
exit(0);

@ -109,10 +109,9 @@ float mse_threshold() {
int main(int argc, char **argv) {
int i;
srslte_modem_table_t mod;
srslte_demod_soft_t demod_soft;
uint8_t *input, *output;
cf_t *symbols;
float *llr_exact, *llr_approx;
float *llr;
parse_args(argc, argv);
@ -125,11 +124,6 @@ int main(int argc, char **argv) {
/* check that num_bits is multiple of num_bits x symbol */
num_bits = mod.nbits_x_symbol * (num_bits / mod.nbits_x_symbol);
srslte_demod_soft_init(&demod_soft, num_bits / mod.nbits_x_symbol);
srslte_demod_soft_table_set(&demod_soft, &mod);
srslte_demod_soft_sigma_set(&demod_soft, 2.0 / mod.nbits_x_symbol);
/* allocate buffers */
input = malloc(sizeof(uint8_t) * num_bits);
if (!input) {
@ -147,14 +141,8 @@ int main(int argc, char **argv) {
exit(-1);
}
llr_exact = malloc(sizeof(float) * num_bits);
if (!llr_exact) {
perror("malloc");
exit(-1);
}
llr_approx = malloc(sizeof(float) * num_bits);
if (!llr_approx) {
llr = malloc(sizeof(float) * num_bits);
if (!llr) {
perror("malloc");
exit(-1);
}
@ -163,7 +151,6 @@ int main(int argc, char **argv) {
srand(0);
int ret = -1;
double mse;
struct timeval t[3];
float mean_texec = 0.0;
for (int n=0;n<nof_frames;n++) {
@ -174,16 +161,8 @@ int main(int argc, char **argv) {
/* modulate */
srslte_mod_modulate(&mod, input, symbols, num_bits);
/* add noise */
srslte_ch_awgn_c(symbols, symbols, srslte_ch_awgn_get_variance(5.0, mod.nbits_x_symbol), num_bits / mod.nbits_x_symbol);
/* Compare exact with approximation algorithms */
srslte_demod_soft_alg_set(&demod_soft, SRSLTE_DEMOD_SOFT_ALG_EXACT);
srslte_demod_soft_demodulate(&demod_soft, symbols, llr_exact, num_bits / mod.nbits_x_symbol);
srslte_demod_soft_alg_set(&demod_soft, SRSLTE_DEMOD_SOFT_ALG_APPROX);
gettimeofday(&t[1], NULL);
srslte_demod_soft_demodulate(&demod_soft, symbols, llr_approx, num_bits / mod.nbits_x_symbol);
srslte_demod_soft_demodulate_lte(modulation, symbols, llr, num_bits / mod.nbits_x_symbol);
gettimeofday(&t[2], NULL);
get_time_interval(t);
@ -192,42 +171,35 @@ int main(int argc, char **argv) {
mean_texec = SRSLTE_VEC_CMA((float) t[0].tv_usec, mean_texec, n-1);
}
/* check MSE */
mse = 0.0;
for (i=0;i<num_bits;i++) {
float e = llr_exact[i] - llr_approx[i];
mse += e*e;
}
mse/=num_bits;
if (SRSLTE_VERBOSE_ISDEBUG()) {
printf("exact=");
srslte_vec_fprint_f(stdout, llr_exact, num_bits);
printf("bits=");
srslte_vec_fprint_b(stdout, input, num_bits);
printf("symbols=");
srslte_vec_fprint_c(stdout, symbols, num_bits/mod.nbits_x_symbol);
printf("approx=");
srslte_vec_fprint_f(stdout, llr_approx, num_bits);
printf("llr=");
srslte_vec_fprint_f(stdout, llr, num_bits);
}
if (mse > mse_threshold()) {
goto clean_exit;
// Check demodulation errors
for (int i=0;i<num_bits;i++) {
if (input[i] != (llr[i]>0?1:0)) {
printf("Error in bit %d\n", i);
goto clean_exit;
}
}
}
ret = 0;
clean_exit:
free(llr_exact);
free(llr_approx);
free(llr);
free(symbols);
free(output);
free(input);
srslte_modem_table_free(&mod);
srslte_demod_soft_free(&demod_soft);
if (ret == 0) {
printf("Ok Mean Throughput: %.2f. Mbps ExTime: %.2f us\n", num_bits/mean_texec, mean_texec);
} else {
printf("Error: MSE too large (%f > %f)\n", mse, mse_threshold());
}
printf("Mean Throughput: %.2f. Mbps ExTime: %.2f us\n", num_bits/mean_texec, mean_texec);
exit(ret);
}

@ -159,10 +159,6 @@ int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) {
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK, true)) {
goto clean;
}
srslte_demod_soft_init(&q->demod, q->nof_symbols);
srslte_demod_soft_table_set(&q->demod, &q->mod);
srslte_demod_soft_alg_set(&q->demod, SRSLTE_DEMOD_SOFT_ALG_APPROX);
if (srslte_sequence_pbch(&q->seq, q->cell.cp, q->cell.id)) {
goto clean;
}
@ -248,7 +244,6 @@ void srslte_pbch_free(srslte_pbch_t *q) {
srslte_sequence_free(&q->seq);
srslte_modem_table_free(&q->mod);
srslte_viterbi_free(&q->decoder);
srslte_demod_soft_free(&q->demod);
bzero(q, sizeof(srslte_pbch_t));
@ -484,9 +479,7 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
}
/* demodulate symbols */
srslte_demod_soft_sigma_set(&q->demod, 1.0);
srslte_demod_soft_demodulate(&q->demod, q->d,
&q->llr[nof_bits * (q->frame_idx - 1)], q->nof_symbols);
srslte_demod_soft_demodulate_lte(SRSLTE_MOD_QPSK, q->d, &q->llr[nof_bits * (q->frame_idx - 1)], q->nof_symbols);
/* We don't know where the 40 ms begin, so we try all combinations. E.g. if we received
* 4 frames, try 1,2,3,4 individually, 12, 23, 34 in pairs, 123, 234 and finally 1234.

@ -83,10 +83,6 @@ int srslte_pcfich_init(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t ce
goto clean;
}
srslte_demod_soft_init(&q->demod, q->nof_symbols);
srslte_demod_soft_table_set(&q->demod, &q->mod);
srslte_demod_soft_alg_set(&q->demod, SRSLTE_DEMOD_SOFT_ALG_APPROX);
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
if (srslte_sequence_pcfich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
goto clean;
@ -116,7 +112,6 @@ void srslte_pcfich_free(srslte_pcfich_t *q) {
}
srslte_modem_table_free(&q->mod);
srslte_precoding_free(&q->precoding);
srslte_demod_soft_free(&q->demod);
bzero(q, sizeof(srslte_pcfich_t));
}
@ -208,8 +203,7 @@ int srslte_pcfich_decode(srslte_pcfich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE
}
/* demodulate symbols */
srslte_demod_soft_sigma_set(&q->demod, 1.0);
srslte_demod_soft_demodulate(&q->demod, q->d, q->data_f, q->nof_symbols);
srslte_demod_soft_demodulate_lte(SRSLTE_MOD_QPSK, q->d, q->data_f, q->nof_symbols);
/* Scramble with the sequence for slot nslot */
srslte_scrambling_f(&q->seq[nsubframe], q->data_f);

@ -85,10 +85,6 @@ int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell
goto clean;
}
srslte_demod_soft_init(&q->demod, q->max_bits / 2);
srslte_demod_soft_table_set(&q->demod, &q->mod);
srslte_demod_soft_alg_set(&q->demod, SRSLTE_DEMOD_SOFT_ALG_APPROX);
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
// we need to pregenerate the sequence for the maximum number of bits, which is 8 times
// the maximum number of REGs (for CFI=3)
@ -171,8 +167,6 @@ void srslte_pdcch_free(srslte_pdcch_t *q) {
srslte_sequence_free(&q->seq[i]);
}
srslte_demod_soft_free(&q->demod);
srslte_precoding_free(&q->precoding);
srslte_modem_table_free(&q->mod);
srslte_viterbi_free(&q->decoder);
@ -424,9 +418,7 @@ int srslte_pdcch_extract_llr(srslte_pdcch_t *q, cf_t *sf_symbols, cf_t *ce[SRSLT
}
/* demodulate symbols */
//srslte_vec_sc_prod_fff((float*) q->d, -sqrt(2), q->llr, nof_symbols*2);
srslte_demod_soft_sigma_set(&q->demod, sqrt(0.5));
srslte_demod_soft_demodulate(&q->demod, q->d, q->llr, nof_symbols);
srslte_demod_soft_demodulate_lte(SRSLTE_MOD_QPSK, q->d, q->llr, nof_symbols);
/* descramble */
srslte_scrambling_f_offset(&q->seq[nsubframe], q->llr, 0, e_bits);

@ -223,9 +223,6 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) {
goto clean;
}
}
srslte_demod_soft_init(&q->demod, q->max_re);
srslte_demod_soft_alg_set(&q->demod, SRSLTE_DEMOD_SOFT_ALG_APPROX);
srslte_sch_init(&q->dl_sch);
@ -294,7 +291,6 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
for (i = 0; i < 4; i++) {
srslte_modem_table_free(&q->mod[i]);
}
srslte_demod_soft_free(&q->demod);
srslte_precoding_free(&q->precoding);
srslte_sch_free(&q->dl_sch);
@ -420,9 +416,7 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q,
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
srslte_demod_soft_sigma_set(&q->demod, sqrt(0.5));
srslte_demod_soft_table_set(&q->demod, &q->mod[cfg->grant.mcs.mod]);
srslte_demod_soft_demodulate(&q->demod, q->d, q->e, cfg->nbits.nof_re);
srslte_demod_soft_demodulate_lte(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re);
/* descramble */
if (rnti != q->rnti) {

@ -91,10 +91,6 @@ int srslte_phich_init(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell
goto clean;
}
srslte_demod_soft_init(&q->demod, SRSLTE_PHICH_MAX_NSYMB);
srslte_demod_soft_table_set(&q->demod, &q->mod);
srslte_demod_soft_alg_set(&q->demod, SRSLTE_DEMOD_SOFT_ALG_APPROX);
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
if (srslte_sequence_phich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
goto clean;
@ -278,10 +274,10 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE_M
if (SRSLTE_VERBOSE_ISDEBUG())
srslte_vec_fprint_c(stdout, q->z, SRSLTE_PHICH_NBITS);
srslte_demod_soft_demodulate(&q->demod, q->z, q->data_rx, SRSLTE_PHICH_NBITS);
srslte_demod_soft_demodulate_lte(SRSLTE_MOD_BPSK, q->z, q->data_rx, SRSLTE_PHICH_NBITS);
if (ack) {
*ack = srslte_phich_ack_decode(q->data_rx, distance);
*ack = srslte_phich_ack_decode(q->data_rx, distance);
}
return SRSLTE_SUCCESS;

@ -212,9 +212,6 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
goto clean;
}
srslte_demod_soft_init(&q->demod, q->max_re);
srslte_demod_soft_alg_set(&q->demod, SRSLTE_DEMOD_SOFT_ALG_APPROX);
srslte_sch_init(&q->dl_sch);
if (srslte_dft_precoding_init(&q->dft_precoding, cell.nof_prb)) {
@ -296,7 +293,6 @@ void srslte_pusch_free(srslte_pusch_t *q) {
for (i = 0; i < 4; i++) {
srslte_modem_table_free(&q->mod[i]);
}
srslte_demod_soft_free(&q->demod);
srslte_sch_free(&q->dl_sch);
bzero(q, sizeof(srslte_pusch_t));
@ -451,9 +447,7 @@ int srslte_pusch_decode(srslte_pusch_t *q,
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
srslte_demod_soft_sigma_set(&q->demod, sqrt(0.5));
srslte_demod_soft_table_set(&q->demod, &q->mod[cfg->grant.mcs.mod]);
srslte_demod_soft_demodulate(&q->demod, q->d, q->q, cfg->nbits.nof_re);
srslte_demod_soft_demodulate_lte(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re);
/* descramble */
srslte_scrambling_f_offset(&q->seq[cfg->sf_idx], q->q, 0, cfg->nbits.nof_bits);

@ -192,7 +192,7 @@ int main(int argc, char **argv) {
printf("Invalid received ACK: %d!=%d\n", ack[ngroup][nseq], ack_rx);
exit(-1);
}
if (distance < 5) {
if (distance < 1.5) {
printf("Error\n");
exit(-1);
}

@ -387,7 +387,7 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr
fprintf(stderr, "Error decoding PHICH\n");
return false;
}
if (ack_bit && distance > 5.0) {
if (ack_bit && distance > 1.5) {
return true;
} else {
return false;

Loading…
Cancel
Save