int main(int argc, char **argv) { viterbi_t dec; convcoder_t cod; modem_table_t modem; demod_soft_t demod; int frame_cnt; float *llr; char *data_tx, *data_rx, *symbols; cf_t *iq; int i; parse_args(argc,argv); if (!seed) { seed = time(NULL); } srand(seed); int coded_length = 3 * (frame_length + ((tail_biting)?0:6)); printf("Convolutional Code 1/3 K=7 Test\n"); printf(" Frame length: %d\n", frame_length); printf(" Codeword length: %d\n", coded_length); printf(" Tail bitting: %s\n", tail_biting?"yes":"no"); printf(" EbNo: %.2f\n", ebno_db); data_tx = malloc(frame_length * sizeof(char)); if (!data_tx) { perror("malloc"); exit(-1); } data_rx = malloc(frame_length * sizeof(char)); if (!data_rx) { perror("malloc"); exit(-1); } symbols = malloc(coded_length * sizeof(char)); if (!symbols) { perror("malloc"); exit(-1); } llr = malloc(coded_length * sizeof(float)); if (!llr) { perror("malloc"); exit(-1); } iq = malloc(coded_length * sizeof(cf_t)); if (!iq) { perror("malloc"); exit(-1); } cod.K = 7; cod.R = 3; cod.tail_biting = tail_biting; cod.framelength = frame_length; cod.poly[0] = 0x6D; cod.poly[1] = 0x4F; cod.poly[2] = 0x57; float var = sqrt(pow(10,-ebno_db/10)); modem_table_init(&modem); modem_table_std(&modem, LTE_QPSK, true); demod_soft_init(&demod); demod_soft_table_set(&demod, &modem); demod_soft_alg_set(&demod, APPROX); demod_soft_sigma_set(&demod, var); viterbi_init(&dec, viterbi_37, cod.poly, frame_length, tail_biting); /* read all file or nof_frames */ frame_cnt = 0; unsigned int errors=0; while (frame_cnt < nof_slots) { /* generate data_tx */ for (i=0;i<frame_length;i++) { data_tx[i] = message[i]; } convcoder_encode(&cod, data_tx, symbols); bit_fprint(stdout, symbols, 120); mod_modulate(&modem, symbols, iq, coded_length); if (ebno_db < 100.0) { ch_awgn(iq, iq, var, coded_length/2); } demod_soft_demodulate(&demod, iq, llr, coded_length/2); viterbi_decode(&dec, llr, data_rx); errors += bit_diff(data_tx, data_rx, frame_length); frame_cnt++; } printf("BER:\t%g\t%u errors\n", (float) errors/(frame_cnt*frame_length), errors); viterbi_free(&dec); free(data_tx); free(symbols); free(iq); free(llr); free(data_rx); printf("Done\n"); exit(0); }
/* Decodes the PBCH channel * * The PBCH spans in 40 ms. This function is called every 10 ms. It tries to decode the MIB * given the symbols of a subframe (1 ms). Successive calls will use more subframes * to help the decoding process. * * Returns 1 if successfully decoded MIB, 0 if not and -1 on error */ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[MAX_PORTS], pbch_mib_t *mib) { uint32_t src, dst, nb; uint32_t nant_[3] = { 1, 2, 4 }; uint32_t na, nant; int i; int nof_bits; cf_t *x[MAX_LAYERS]; int ret = LIBLTE_ERROR_INVALID_INPUTS; if (q != NULL && slot1_symbols != NULL && mib != NULL) { for (i=0;i<q->cell.nof_ports;i++) { if (ce_slot1[i] == NULL) { return LIBLTE_ERROR_INVALID_INPUTS; } } /* Set pointers for layermapping & precoding */ nof_bits = 2 * q->nof_symbols; /* number of layers equals number of ports */ for (i = 0; i < MAX_PORTS; i++) { x[i] = q->pbch_x[i]; } memset(&x[MAX_PORTS], 0, sizeof(cf_t*) * (MAX_LAYERS - MAX_PORTS)); /* extract symbols */ if (q->nof_symbols != pbch_get(slot1_symbols, q->pbch_symbols[0], q->cell)) { fprintf(stderr, "There was an error getting the PBCH symbols\n"); return LIBLTE_ERROR; } /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { if (q->nof_symbols != pbch_get(ce_slot1[i], q->ce[i], q->cell)) { fprintf(stderr, "There was an error getting the PBCH symbols\n"); return LIBLTE_ERROR; } } q->frame_idx++; ret = 0; /* Try decoding for 1 to cell.nof_ports antennas */ for (na = 0; na < q->cell.nof_ports && !ret; na++) { nant = nant_[na]; DEBUG("Trying %d TX antennas with %d frames\n", nant, q->frame_idx); /* in conctrol channels, only diversity is supported */ if (nant == 1) { /* no need for layer demapping */ predecoding_single_zf(q->pbch_symbols[0], q->ce[0], q->pbch_d, q->nof_symbols); } else { predecoding_diversity_zf(q->pbch_symbols[0], q->ce, x, nant, q->nof_symbols); layerdemap_diversity(x, q->pbch_d, nant, q->nof_symbols / nant); } /* demodulate symbols */ demod_soft_sigma_set(&q->demod, 1.0); demod_soft_demodulate(&q->demod, q->pbch_d, &q->pbch_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. * We know they are ordered. * * FIXME: There are unnecessary checks because 2,3,4 have already been processed in the previous * calls. */ for (nb = 0; nb < q->frame_idx && !ret; nb++) { for (dst = 0; (dst < 4 - nb) && !ret; dst++) { for (src = 0; src < q->frame_idx - nb && !ret; src++) { ret = pbch_decode_frame(q, mib, src, dst, nb + 1, nof_bits, nant); } } } } /* If not found, make room for the next packet of radio frame symbols */ if (q->frame_idx == 4) { memmove(q->pbch_llr, &q->pbch_llr[nof_bits], nof_bits * 3 * sizeof(float)); q->frame_idx = 3; } } return ret; }
int main(int argc, char **argv) { int i; modem_table_t mod; demod_soft_t demod_soft; char *input, *output; cf_t *symbols; float *llr_exact, *llr_approx; parse_args(argc, argv); /* initialize objects */ if (modem_table_lte(&mod, modulation, true)) { fprintf(stderr, "Error initializing modem table\n"); exit(-1); } /* check that num_bits is multiple of num_bits x symbol */ num_bits = mod.nbits_x_symbol * (num_bits / mod.nbits_x_symbol); demod_soft_init(&demod_soft); demod_soft_table_set(&demod_soft, &mod); demod_soft_sigma_set(&demod_soft, 2.0 / mod.nbits_x_symbol); /* allocate buffers */ input = malloc(sizeof(char) * num_bits); if (!input) { perror("malloc"); exit(-1); } output = malloc(sizeof(char) * num_bits); if (!output) { perror("malloc"); exit(-1); } symbols = malloc(sizeof(cf_t) * num_bits / mod.nbits_x_symbol); if (!symbols) { perror("malloc"); 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) { perror("malloc"); exit(-1); } /* generate random data */ srand(0); int ret = -1; double mse; struct timeval t[3]; float mean_texec = 0.0; for (int n=0;n<nof_frames;n++) { for (i=0;i<num_bits;i++) { input[i] = rand()%2; } /* modulate */ mod_modulate(&mod, input, symbols, num_bits); /* add noise */ ch_awgn_c(symbols, symbols, ch_awgn_get_variance(5.0, mod.nbits_x_symbol), num_bits / mod.nbits_x_symbol); /* Compare exact with approximation algorithms */ demod_soft_alg_set(&demod_soft, EXACT); demod_soft_demodulate(&demod_soft, symbols, llr_exact, num_bits / mod.nbits_x_symbol); demod_soft_alg_set(&demod_soft, APPROX); gettimeofday(&t[1], NULL); demod_soft_demodulate(&demod_soft, symbols, llr_approx, num_bits / mod.nbits_x_symbol); gettimeofday(&t[2], NULL); get_time_interval(t); /* compute exponentially averaged execution time */ if (n > 0) { mean_texec = EXPAVERAGE((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 (VERBOSE_ISDEBUG()) { printf("exact="); vec_fprint_f(stdout, llr_exact, num_bits); printf("approx="); vec_fprint_f(stdout, llr_approx, num_bits); } if (mse > mse_threshold()) { goto clean_exit; } } ret = 0; clean_exit: free(llr_exact); free(llr_approx); free(symbols); free(output); free(input); modem_table_free(&mod); 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()); } exit(ret); }