From 5679797ed2e6b1ddbf8449b6e315c0887958476b Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Tue, 17 Jun 2014 10:11:41 +0100 Subject: [PATCH] Replacing tabs with spaces --- cuhd/lib/cuhd_utils.c | 64 +- examples/hl_example.c | 166 +-- examples/ll_example.c | 26 +- examples/pbch_enodeb.c | 366 ++--- examples/pbch_ue.c | 738 +++++----- examples/scan_mib.c | 840 +++++------ examples/scan_pss.c | 812 +++++------ examples/scan_rssi.c | 206 +-- examples/synch_file.c | 400 ++--- graphics/include/plot/plot_complex.h | 4 +- graphics/include/plot/plot_real.h | 2 +- graphics/include/plot/plot_scatter.h | 2 +- graphics/include/plot/plot_waterfall.h | 2 +- lte/include/lte/ch_estimation/chest.h | 44 +- lte/include/lte/ch_estimation/refsignal.h | 24 +- lte/include/lte/channel/ch_awgn.h | 16 +- lte/include/lte/common/base.h | 60 +- lte/include/lte/common/fft.h | 14 +- lte/include/lte/common/sequence.h | 4 +- lte/include/lte/fec/convcoder.h | 36 +- lte/include/lte/fec/crc.h | 16 +- lte/include/lte/fec/rm_conv.h | 22 +- lte/include/lte/fec/rm_turbo.h | 32 +- lte/include/lte/fec/tc_interl.h | 4 +- lte/include/lte/fec/turbocoder.h | 4 +- lte/include/lte/fec/turbodecoder.h | 20 +- lte/include/lte/fec/viterbi.h | 50 +- lte/include/lte/filter/filter2d.h | 12 +- lte/include/lte/io/binsource.h | 32 +- lte/include/lte/io/filesink.h | 22 +- lte/include/lte/io/filesource.h | 28 +- lte/include/lte/io/udpsink.h | 26 +- lte/include/lte/io/udpsource.h | 30 +- lte/include/lte/mimo/layermap.h | 8 +- lte/include/lte/mimo/precoding.h | 8 +- lte/include/lte/modem/demod_hard.h | 18 +- lte/include/lte/modem/demod_soft.h | 30 +- lte/include/lte/modem/mod.h | 16 +- lte/include/lte/modem/modem_table.h | 12 +- lte/include/lte/phch/dci.h | 32 +- lte/include/lte/phch/pbch.h | 60 +- lte/include/lte/phch/pcfich.h | 42 +- lte/include/lte/phch/pdcch.h | 68 +- lte/include/lte/phch/phich.h | 64 +- lte/include/lte/phch/ra.h | 102 +- lte/include/lte/phch/regs.h | 54 +- lte/include/lte/scrambling/scrambling.h | 48 +- lte/include/lte/sync/cfo.h | 10 +- lte/include/lte/sync/pss.h | 74 +- lte/include/lte/sync/sss.h | 66 +- lte/include/lte/sync/sync.h | 26 +- lte/include/lte/utils/cexptab.h | 4 +- lte/include/lte/utils/convolution.h | 20 +- lte/include/lte/utils/debug.h | 10 +- lte/include/lte/utils/dft.h | 28 +- lte/include/lte/utils/mux.h | 6 +- lte/lib/ch_estimation/src/chest.c | 368 ++--- lte/lib/ch_estimation/src/refsignal.c | 256 ++-- lte/lib/ch_estimation/test/chest_test.c | 386 ++--- lte/lib/channel/src/ch_awgn.c | 34 +- lte/lib/common/src/fft.c | 128 +- lte/lib/common/src/lte.c | 384 ++--- lte/lib/common/src/sequence.c | 104 +- lte/lib/common/test/fft_test.c | 186 +-- lte/lib/fec/src/convcoder.c | 58 +- lte/lib/fec/src/crc.c | 186 +-- lte/lib/fec/src/rm_conv.c | 214 +-- lte/lib/fec/src/rm_turbo.c | 372 ++--- lte/lib/fec/src/tc_interl_lte.c | 116 +- lte/lib/fec/src/tc_interl_umts.c | 370 ++--- lte/lib/fec/src/turbocoder.c | 172 +-- lte/lib/fec/src/turbodecoder.c | 464 +++--- lte/lib/fec/src/viterbi.c | 336 ++--- lte/lib/fec/src/viterbi37_port.c | 236 +-- lte/lib/fec/src/viterbi39.h | 4 +- lte/lib/fec/src/viterbi39_port.c | 204 +-- lte/lib/fec/test/crc_test.c | 114 +- lte/lib/fec/test/crc_test.h | 58 +- lte/lib/fec/test/rm_conv_test.c | 156 +- lte/lib/fec/test/rm_turbo_test.c | 186 +-- lte/lib/fec/test/turbocoder_test.c | 520 +++---- lte/lib/fec/test/turbocoder_test.h | 242 ++-- lte/lib/fec/test/viterbi_test.c | 564 ++++---- lte/lib/fec/test/viterbi_test.h | 62 +- lte/lib/filter/src/filter2d.c | 142 +- lte/lib/io/src/binsource.c | 142 +- lte/lib/io/src/filesink.c | 126 +- lte/lib/io/src/filesource.c | 154 +- lte/lib/io/src/udpsink.c | 80 +- lte/lib/io/src/udpsource.c | 82 +- lte/lib/mimo/src/layermap.c | 276 ++-- lte/lib/mimo/src/precoding.c | 308 ++-- lte/lib/mimo/test/layermap_test.c | 226 +-- lte/lib/mimo/test/precoding_test.c | 284 ++-- lte/lib/modem/src/demod_hard.c | 58 +- lte/lib/modem/src/demod_soft.c | 58 +- lte/lib/modem/src/hard_demod_lte.c | 186 +-- lte/lib/modem/src/hard_demod_lte.h | 8 +- lte/lib/modem/src/lte_tables.c | 422 +++--- lte/lib/modem/src/lte_tables.h | 14 +- lte/lib/modem/src/mod.c | 40 +- lte/lib/modem/src/modem_table.c | 110 +- lte/lib/modem/src/soft_algs.c | 126 +- lte/lib/modem/src/soft_algs.h | 4 +- lte/lib/modem/test/modem_test.c | 266 ++-- lte/lib/phch/src/dci.c | 1286 ++++++++--------- lte/lib/phch/src/pbch.c | 824 +++++------ lte/lib/phch/src/pcfich.c | 340 ++--- lte/lib/phch/src/pdcch.c | 888 ++++++------ lte/lib/phch/src/phich.c | 572 ++++---- lte/lib/phch/src/prb.c | 66 +- lte/lib/phch/src/prb.h | 6 +- lte/lib/phch/src/ra.c | 748 +++++----- lte/lib/phch/src/regs.c | 1034 ++++++------- lte/lib/phch/src/sequences.c | 16 +- lte/lib/phch/src/tbs_tables.h | 4 +- lte/lib/phch/test/dci_unpacking.c | 114 +- lte/lib/phch/test/pbch_file_test.c | 332 ++--- lte/lib/phch/test/pbch_test.c | 186 +-- lte/lib/phch/test/pcfich_file_test.c | 362 ++--- lte/lib/phch/test/pcfich_test.c | 218 +-- lte/lib/phch/test/pdcch_file_test.c | 480 +++--- lte/lib/phch/test/pdcch_test.c | 358 ++--- lte/lib/phch/test/phich_file_test.c | 424 +++--- lte/lib/phch/test/phich_test.c | 308 ++-- lte/lib/resampling/src/interp.c | 68 +- lte/lib/resampling/test/resample_arb_bench.c | 4 +- lte/lib/resampling/test/resample_arb_test.c | 2 +- lte/lib/scrambling/src/scrambling.c | 128 +- lte/lib/scrambling/test/scrambling_test.c | 220 +-- lte/lib/sync/src/cfo.c | 60 +- lte/lib/sync/src/find_sss.c | 136 +- lte/lib/sync/src/gen_sss.c | 184 +-- lte/lib/sync/src/pss.c | 490 +++---- lte/lib/sync/src/sfo.c | 28 +- lte/lib/sync/src/sss.c | 166 +-- lte/lib/sync/src/sync.c | 348 ++--- lte/lib/sync/test/cfo_test.c | 138 +- lte/lib/sync/test/sync_test.c | 228 +-- lte/lib/utils/src/bit.c | 30 +- lte/lib/utils/src/cexptab.c | 68 +- lte/lib/utils/src/convolution.c | 86 +- lte/lib/utils/src/debug.c | 12 +- lte/lib/utils/src/dft.c | 354 ++--- lte/lib/utils/src/matrix.c | 118 +- lte/lib/utils/src/mux.c | 42 +- lte/lib/utils/src/pack.c | 2 +- lte/lib/utils/src/vector.c | 258 ++-- scripts/xml2aloe/template/src/template.c | 64 +- scripts/xml2aloe/template/src/template.h | 8 +- .../xml2aloe/template/test/test_generate.c | 46 +- 151 files changed, 13188 insertions(+), 13188 deletions(-) diff --git a/cuhd/lib/cuhd_utils.c b/cuhd/lib/cuhd_utils.c index f755f073f..7011236d6 100644 --- a/cuhd/lib/cuhd_utils.c +++ b/cuhd/lib/cuhd_utils.c @@ -36,44 +36,44 @@ #include "lte/utils/debug.h" int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs, int nsamp) { - int i, j; - int ret = -1; - _Complex float *buffer; - double f; + int i, j; + int ret = -1; + _Complex float *buffer; + double f; - buffer = calloc(nsamp, sizeof(_Complex float)); - if (!buffer) { - goto free_and_exit; - } + buffer = calloc(nsamp, sizeof(_Complex float)); + if (!buffer) { + goto free_and_exit; + } - cuhd_set_rx_gain(uhd, 0.0); - cuhd_set_rx_srate(uhd, fs); + cuhd_set_rx_gain(uhd, 0.0); + cuhd_set_rx_srate(uhd, fs); - for (i=0;i0?1:0; - } - - printf("Hard errors: %u/%d\n",bit_diff(bs.output,demod_h.output,nbits),nbits); - printf("Soft errors: %u/%d\n",bit_diff(bs.output,tmp,nbits),nbits); - - free(bs.output); - free(mod.output); - free(ch.output); - free(demod_h.output); - free(demod_s.output); - free(tmp); - - printf("Exit\n"); - exit(0); + binsource_hl bs; + mod_hl mod; + ch_awgn_hl ch; + demod_soft_hl demod_s; + demod_hard_hl demod_h; + + bzero(&bs,sizeof(bs)); + bzero(&mod,sizeof(mod)); + bzero(&ch,sizeof(ch)); + bzero(&demod_s,sizeof(demod_s)); + bzero(&demod_h,sizeof(demod_h)); + + if (argc<3) { + usage(argv[0]); + exit(-1); + } + + int nbits = atoi(argv[1]); + float snr_db = atof(argv[2]); + float var = sqrt(pow(10,-snr_db/10)); + + bs.init.seed = 0; + bs.init.cache_seq_nbits = 0; + bs.ctrl_in.nbits = nbits; + bs.output = malloc(nbits); + + mod.in_len = nbits; + mod.init.std = LTE_BPSK; + mod.input = bs.output; + mod.output = malloc(nbits*sizeof(_Complex float)); + + ch.in_len = nbits; + ch.input = mod.output; + ch.ctrl_in.variance = var; + ch.output = malloc(nbits*sizeof(_Complex float)); + + demod_h.in_len = nbits; + demod_h.init.std = LTE_BPSK; + demod_h.input = ch.output; + demod_h.output = malloc(nbits); + + demod_s.in_len = nbits; + demod_s.init.std = LTE_BPSK; + demod_s.input = ch.output; + demod_s.output = malloc(sizeof(float)*nbits); + demod_s.ctrl_in.alg_type = APPROX; + demod_s.ctrl_in.sigma = var; + + if ( binsource_initialize(&bs) || + mod_initialize(&mod) || + ch_awgn_initialize(&ch) || + demod_hard_initialize(&demod_h) || + demod_soft_initialize(&demod_s) + ) { + printf("Error initializing modules\n"); + exit(-1); + } + + binsource_work(&bs); + mod_work(&mod); + ch_awgn_work(&ch); + demod_hard_work(&demod_h); + demod_soft_work(&demod_s); + + /* hard decision for soft demodulation */ + char* tmp = malloc(nbits); + for (int i=0;i0?1:0; + } + + printf("Hard errors: %u/%d\n",bit_diff(bs.output,demod_h.output,nbits),nbits); + printf("Soft errors: %u/%d\n",bit_diff(bs.output,tmp,nbits),nbits); + + free(bs.output); + free(mod.output); + free(ch.output); + free(demod_h.output); + free(demod_s.output); + free(tmp); + + printf("Exit\n"); + exit(0); } diff --git a/examples/ll_example.c b/examples/ll_example.c index 83f91b188..ef1d37d9d 100644 --- a/examples/ll_example.c +++ b/examples/ll_example.c @@ -32,20 +32,20 @@ #include "lte.h" int main(int argc, char **argv) { - binsource_t bs; - char* output; + binsource_t bs; + char* output; - binsource_init(&bs); - binsource_seed_time(&bs); + binsource_init(&bs); + binsource_seed_time(&bs); - output = malloc(100); + output = malloc(100); - if (binsource_generate(&bs,output,100)) { - printf("Error generating bits\n"); - exit(-1); - } - printf("output: "); - bit_fprint(stdout,output,100); - printf("Done\n"); - exit(0); + if (binsource_generate(&bs,output,100)) { + printf("Error generating bits\n"); + exit(-1); + } + printf("output: "); + bit_fprint(stdout,output,100); + printf("Done\n"); + exit(0); } diff --git a/examples/pbch_enodeb.c b/examples/pbch_enodeb.c index 4cf26bb68..f99977053 100644 --- a/examples/pbch_enodeb.c +++ b/examples/pbch_enodeb.c @@ -34,8 +34,8 @@ #include "lte.h" #ifndef DISABLE_UHD - #include "cuhd.h" - void *uhd; + #include "cuhd.h" + void *uhd; #endif char *output_file_name = NULL; @@ -53,231 +53,231 @@ pbch_t pbch; cf_t *slot_buffer = NULL, *output_buffer = NULL; int slot_n_re, slot_n_samples; -#define UHD_SAMP_FREQ 1920000 +#define UHD_SAMP_FREQ 1920000 void usage(char *prog) { - printf("Usage: %s [agmfoncvp]\n", prog); + printf("Usage: %s [agmfoncvp]\n", prog); #ifndef DISABLE_UHD - printf("\t-a UHD args [Default %s]\n", uhd_args); - printf("\t-g UHD TX gain [Default %.2f dB]\n", uhd_gain); - printf("\t-m UHD signal amplitude [Default %.2f]\n", uhd_amp); - printf("\t-f UHD TX frequency [Default %.1f MHz]\n", uhd_freq/1000000); + printf("\t-a UHD args [Default %s]\n", uhd_args); + printf("\t-g UHD TX gain [Default %.2f dB]\n", uhd_gain); + printf("\t-m UHD signal amplitude [Default %.2f]\n", uhd_amp); + printf("\t-f UHD TX frequency [Default %.1f MHz]\n", uhd_freq/1000000); #else - printf("\t UHD is disabled. CUHD library not available\n"); + printf("\t UHD is disabled. CUHD library not available\n"); #endif - printf("\t-o output_file [Default USRP]\n"); - printf("\t-n number of frames [Default %d]\n", nof_frames); - printf("\t-c cell id [Default %d]\n", cell_id); - printf("\t-p nof_prb [Default %d]\n", nof_prb); - printf("\t-v [set verbose to debug, default none]\n"); + printf("\t-o output_file [Default USRP]\n"); + printf("\t-n number of frames [Default %d]\n", nof_frames); + printf("\t-c cell id [Default %d]\n", cell_id); + printf("\t-p nof_prb [Default %d]\n", nof_prb); + printf("\t-v [set verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "agfmoncpv")) != -1) { - switch(opt) { - case 'a': - uhd_args = argv[optind]; - break; - case 'g': - uhd_gain = atof(argv[optind]); - break; - case 'm': - uhd_amp = atof(argv[optind]); - break; - case 'f': - uhd_freq = atof(argv[optind]); - break; - case 'o': - output_file_name = argv[optind]; - break; - case 'n': - nof_frames = atoi(argv[optind]); - break; - case 'p': - nof_prb = atoi(argv[optind]); - break; - case 'c': - cell_id = atoi(argv[optind]); - break; - case 'v': - verbose++; - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "agfmoncpv")) != -1) { + switch(opt) { + case 'a': + uhd_args = argv[optind]; + break; + case 'g': + uhd_gain = atof(argv[optind]); + break; + case 'm': + uhd_amp = atof(argv[optind]); + break; + case 'f': + uhd_freq = atof(argv[optind]); + break; + case 'o': + output_file_name = argv[optind]; + break; + case 'n': + nof_frames = atoi(argv[optind]); + break; + case 'p': + nof_prb = atoi(argv[optind]); + break; + case 'c': + cell_id = atoi(argv[optind]); + break; + case 'v': + verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } #ifdef DISABLE_UHD - if (!output_file_name) { - usage(argv[0]); - exit(-1); - } + if (!output_file_name) { + usage(argv[0]); + exit(-1); + } #endif } void base_init() { - /* init memory */ - slot_buffer = malloc(sizeof(cf_t) * slot_n_re); - if (!slot_buffer) { - perror("malloc"); - exit(-1); - } - output_buffer = malloc(sizeof(cf_t) * slot_n_samples); - if (!output_buffer) { - perror("malloc"); - exit(-1); - } - /* open file or USRP */ - if (output_file_name) { - if (filesink_init(&fsink, output_file_name, COMPLEX_FLOAT_BIN)) { - fprintf(stderr, "Error opening file %s\n", output_file_name); - exit(-1); - } - } else { + /* init memory */ + slot_buffer = malloc(sizeof(cf_t) * slot_n_re); + if (!slot_buffer) { + perror("malloc"); + exit(-1); + } + output_buffer = malloc(sizeof(cf_t) * slot_n_samples); + if (!output_buffer) { + perror("malloc"); + exit(-1); + } + /* open file or USRP */ + if (output_file_name) { + if (filesink_init(&fsink, output_file_name, COMPLEX_FLOAT_BIN)) { + fprintf(stderr, "Error opening file %s\n", output_file_name); + exit(-1); + } + } else { #ifndef DISABLE_UHD - printf("Opening UHD device...\n"); - if (cuhd_open(uhd_args,&uhd)) { - fprintf(stderr, "Error opening uhd\n"); - exit(-1); - } + printf("Opening UHD device...\n"); + if (cuhd_open(uhd_args,&uhd)) { + fprintf(stderr, "Error opening uhd\n"); + exit(-1); + } #else - printf("Error UHD not available. Select an output file\n"); - exit(-1); + printf("Error UHD not available. Select an output file\n"); + exit(-1); #endif - } - - /* create ifft object */ - if (lte_ifft_init(&ifft, CPNORM, nof_prb)) { - fprintf(stderr, "Error creating iFFT object\n"); - exit(-1); - } - if (pbch_init(&pbch, 6, cell_id, CPNORM)) { - fprintf(stderr, "Error creating PBCH object\n"); - exit(-1); - } + } + + /* create ifft object */ + if (lte_ifft_init(&ifft, CPNORM, nof_prb)) { + fprintf(stderr, "Error creating iFFT object\n"); + exit(-1); + } + if (pbch_init(&pbch, 6, cell_id, CPNORM)) { + fprintf(stderr, "Error creating PBCH object\n"); + exit(-1); + } } void base_free() { - pbch_free(&pbch); + pbch_free(&pbch); - lte_ifft_free(&ifft); + lte_ifft_free(&ifft); - if (slot_buffer) { - free(slot_buffer); - } - if (output_buffer) { - free(output_buffer); - } - if (output_file_name) { - filesink_free(&fsink); - } else { + if (slot_buffer) { + free(slot_buffer); + } + if (output_buffer) { + free(output_buffer); + } + if (output_file_name) { + filesink_free(&fsink); + } else { #ifndef DISABLE_UHD - cuhd_close(&uhd); + cuhd_close(&uhd); #endif - } + } } int main(int argc, char **argv) { - int nf, ns, N_id_2; - cf_t pss_signal[PSS_LEN]; - float sss_signal0[SSS_LEN]; // for subframe 0 - float sss_signal5[SSS_LEN]; // for subframe 5 - pbch_mib_t mib; - refsignal_t refs[NSLOTS_X_FRAME]; - int i; - cf_t *slot1_symbols[MAX_PORTS_CTRL]; + int nf, ns, N_id_2; + cf_t pss_signal[PSS_LEN]; + float sss_signal0[SSS_LEN]; // for subframe 0 + float sss_signal5[SSS_LEN]; // for subframe 5 + pbch_mib_t mib; + refsignal_t refs[NSLOTS_X_FRAME]; + int i; + cf_t *slot1_symbols[MAX_PORTS_CTRL]; #ifdef DISABLE_UHD - if (argc < 3) { - usage(argv[0]); - exit(-1); - } + if (argc < 3) { + usage(argv[0]); + exit(-1); + } #endif - parse_args(argc,argv); + parse_args(argc,argv); - N_id_2 = cell_id%3; - slot_n_re = CPNORM_NSYMB * nof_prb * RE_X_RB; - slot_n_samples = SLOT_LEN_CPNORM(lte_symbol_sz(nof_prb)); + N_id_2 = cell_id%3; + slot_n_re = CPNORM_NSYMB * nof_prb * RE_X_RB; + slot_n_samples = SLOT_LEN_CPNORM(lte_symbol_sz(nof_prb)); - /* this *must* be called after setting slot_len_* */ - base_init(); + /* this *must* be called after setting slot_len_* */ + base_init(); - /* Generate PSS/SSS signals */ - pss_generate(pss_signal, N_id_2); - sss_generate(sss_signal0, sss_signal5, cell_id); + /* Generate PSS/SSS signals */ + pss_generate(pss_signal, N_id_2); + sss_generate(sss_signal0, sss_signal5, cell_id); - /* Generate CRS signals */ - for (i=0;i max_track_lost) { - INFO("%d frames lost. Going back to FIND", frame_cnt - last_found); - printf("\r\n"); - fflush(stdout); - printf("\r\n"); - state = FIND; - } - - // Correct CFO - INFO("Correcting CFO=%.4f\n", cfo); - - cfo_correct(&cfocorr, input_buffer, -cfo/128); - - if (nslot == 0 && find_idx + 960 < FLEN) { - INFO("Finding MIB at idx %d\n", find_idx); - if (mib_decoder_run(&input_buffer[find_idx], &mib)) { - INFO("MIB detected attempt=%d\n", frame_cnt); - if (verbose == VERBOSE_NONE) { - if (!nof_found_mib) { - printf("\r\n"); - fflush(stdout); - printf("\r\n"); - printf(" - Phy. CellId:\t%d\n", cell_id); - pbch_mib_fprint(stdout, &mib); - } - } - nof_found_mib++; - } else { - INFO("MIB not found attempt %d\n",frame_cnt); - } - if (frame_cnt) { - printf("SFN: %4d, CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Errors: %4d/%4d, ErrorRate: %.1e\r", mib.sfn, - cfo*15, timeoffset/5, find_idx, frame_cnt-2*(nof_found_mib-1), frame_cnt, - (float) (frame_cnt-2*(nof_found_mib-1))/frame_cnt); - fflush(stdout); - } - } - if (input_file_name) { - usleep(5000); - } - nslot = (nslot+10)%20; - break; - } - frame_cnt++; - } - - base_free(); - - printf("\nBye\n"); - exit(0); + parse_args(argc,argv); + + if (base_init(FLEN)) { + fprintf(stderr, "Error initializing memory\n"); + exit(-1); + } + + sync_pss_det_peak_to_avg(&sfind); + sync_pss_det_peak_to_avg(&strack); + + if (!input_file_name) { + #ifndef DISABLE_UHD + INFO("Setting sampling frequency %.2f MHz\n", (float) SAMP_FREQ/MHZ); + cuhd_set_rx_srate(uhd, SAMP_FREQ); + cuhd_set_rx_gain(uhd, uhd_gain); + /* set uhd_freq */ + cuhd_set_rx_freq(uhd, (double) uhd_freq); + cuhd_rx_wait_lo_locked(uhd); + DEBUG("Set uhd_freq to %.3f MHz\n", (double) uhd_freq); + + DEBUG("Starting receiver...\n",0); + cuhd_start_rx_stream(uhd); + #endif + } + + printf("\n --- Press Ctrl+C to exit --- \n"); + signal(SIGINT, sigintHandler); + + state = FIND; + nslot = 0; + find_idx = 0; + cfo = 0; + mib.sfn = -1; + frame_cnt = 0; + last_found = 0; + sync_set_threshold(&sfind, find_threshold); + sync_force_N_id_2(&sfind, -1); + + while(!go_exit && (frame_cnt < nof_frames || nof_frames==-1)) { + INFO(" ----- RECEIVING %d SAMPLES ---- \n", FLEN); + if (input_file_name) { + n = filesource_read(&fsrc, input_buffer, FLEN); + if (n == -1) { + fprintf(stderr, "Error reading file\n"); + exit(-1); + } else if (n < FLEN) { + filesource_seek(&fsrc, 0); + filesource_read(&fsrc, input_buffer, FLEN); + } + } else { + #ifndef DISABLE_UHD + cuhd_recv(uhd, input_buffer, FLEN, 1); + #endif + } + + switch(state) { + case FIND: + /* find peak in all frame */ + find_idx = sync_run(&sfind, input_buffer); + INFO("FIND %3d:\tPAR=%.2f\n", frame_cnt, sync_get_peak_to_avg(&sfind)); + if (find_idx != -1) { + /* if found peak, go to track and set track threshold */ + cell_id = sync_get_cell_id(&sfind); + if (cell_id != -1) { + frame_cnt = -1; + last_found = 0; + sync_set_threshold(&strack, track_threshold); + sync_force_N_id_2(&strack, sync_get_N_id_2(&sfind)); + sync_force_cp(&strack, sync_get_cp(&sfind)); + mib_decoder_init(cell_id); + nof_found_mib = 0; + nslot = sync_get_slot_id(&sfind); + nslot=(nslot+10)%20; + cfo = 0; + timeoffset = 0; + printf("\n"); + state = TRACK; + } else { + printf("cellid=-1\n"); + } + } + if (verbose == VERBOSE_NONE) { + printf("Finding PSS... PAR=%.2f\r", sync_get_peak_to_avg(&sfind)); + } + break; + case TRACK: + /* Find peak around known position find_idx */ + INFO("TRACK %3d: PSS find_idx %d offset %d\n", frame_cnt, find_idx, find_idx - track_len); + track_idx = sync_run(&strack, &input_buffer[find_idx - track_len]); + + if (track_idx != -1) { + /* compute cumulative moving average CFO */ + cfo = (sync_get_cfo(&strack) + frame_cnt * cfo) / (frame_cnt + 1); + /* compute cumulative moving average time offset */ + timeoffset = (float) (track_idx-track_len + timeoffset * frame_cnt) / (frame_cnt + 1); + last_found = frame_cnt; + find_idx = (find_idx + track_idx - track_len)%FLEN; + if (nslot != sync_get_slot_id(&strack)) { + INFO("Expected slot %d but got %d\n", nslot, sync_get_slot_id(&strack)); + printf("\r\n"); + fflush(stdout); + printf("\r\n"); + state = FIND; + } + } else { + /* if sync not found, adjust time offset with the averaged value */ + find_idx = (find_idx + (int) timeoffset)%FLEN; + } + + /* if we missed too many PSS go back to FIND */ + if (frame_cnt - last_found > max_track_lost) { + INFO("%d frames lost. Going back to FIND", frame_cnt - last_found); + printf("\r\n"); + fflush(stdout); + printf("\r\n"); + state = FIND; + } + + // Correct CFO + INFO("Correcting CFO=%.4f\n", cfo); + + cfo_correct(&cfocorr, input_buffer, -cfo/128); + + if (nslot == 0 && find_idx + 960 < FLEN) { + INFO("Finding MIB at idx %d\n", find_idx); + if (mib_decoder_run(&input_buffer[find_idx], &mib)) { + INFO("MIB detected attempt=%d\n", frame_cnt); + if (verbose == VERBOSE_NONE) { + if (!nof_found_mib) { + printf("\r\n"); + fflush(stdout); + printf("\r\n"); + printf(" - Phy. CellId:\t%d\n", cell_id); + pbch_mib_fprint(stdout, &mib); + } + } + nof_found_mib++; + } else { + INFO("MIB not found attempt %d\n",frame_cnt); + } + if (frame_cnt) { + printf("SFN: %4d, CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Errors: %4d/%4d, ErrorRate: %.1e\r", mib.sfn, + cfo*15, timeoffset/5, find_idx, frame_cnt-2*(nof_found_mib-1), frame_cnt, + (float) (frame_cnt-2*(nof_found_mib-1))/frame_cnt); + fflush(stdout); + } + } + if (input_file_name) { + usleep(5000); + } + nslot = (nslot+10)%20; + break; + } + frame_cnt++; + } + + base_free(); + + printf("\nBye\n"); + exit(0); } diff --git a/examples/scan_mib.c b/examples/scan_mib.c index f092c046e..59ca08959 100644 --- a/examples/scan_mib.c +++ b/examples/scan_mib.c @@ -42,13 +42,13 @@ #include "cuhd.h" #endif -#define MHZ 1000000 -#define SAMP_FREQ 1920000 -#define RSSI_FS 1000000 -#define FLEN 9600 -#define FLEN_PERIOD 0.005 +#define MHZ 1000000 +#define SAMP_FREQ 1920000 +#define RSSI_FS 1000000 +#define FLEN 9600 +#define FLEN_PERIOD 0.005 -#define RSSI_DECIM 20 +#define RSSI_DECIM 20 #define IS_SIGNAL(i) (10*log10f(rssi[i]) + 30 > rssi_threshold) @@ -86,474 +86,474 @@ enum sync_state {INIT, FIND, TRACK, MIB, DONE}; void usage(char *prog) { - printf("Usage: %s [seRrFfTtgv] -b band\n", prog); - printf("\t-s earfcn_start [Default All]\n"); - printf("\t-e earfcn_end [Default All]\n"); - printf("\t-R rssi_nof_samples [Default %d]\n", nof_samples_rssi); - printf("\t-r rssi_threshold [Default %.2f dBm]\n", rssi_threshold); - printf("\t-F pss_find_nof_frames [Default %d]\n", nof_frames_find); - printf("\t-f pss_find_threshold [Default %.2f]\n", find_threshold); - printf("\t-T pss_track_nof_frames [Default %d]\n", nof_frames_track); - printf("\t-t pss_track_threshold [Default %.2f]\n", track_threshold); - printf("\t-l pss_track_len [Default %d]\n", track_len); - printf("\t-g gain [Default %.2f dB]\n", uhd_gain); - printf("\t-v [set verbose to debug, default none]\n"); + printf("Usage: %s [seRrFfTtgv] -b band\n", prog); + printf("\t-s earfcn_start [Default All]\n"); + printf("\t-e earfcn_end [Default All]\n"); + printf("\t-R rssi_nof_samples [Default %d]\n", nof_samples_rssi); + printf("\t-r rssi_threshold [Default %.2f dBm]\n", rssi_threshold); + printf("\t-F pss_find_nof_frames [Default %d]\n", nof_frames_find); + printf("\t-f pss_find_threshold [Default %.2f]\n", find_threshold); + printf("\t-T pss_track_nof_frames [Default %d]\n", nof_frames_track); + printf("\t-t pss_track_threshold [Default %.2f]\n", track_threshold); + printf("\t-l pss_track_len [Default %d]\n", track_len); + printf("\t-g gain [Default %.2f dB]\n", uhd_gain); + printf("\t-v [set verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "bseRrFfTtgv")) != -1) { - switch(opt) { - case 'b': - band = atoi(argv[optind]); - break; - case 's': - earfcn_start = atoi(argv[optind]); - break; - case 'e': - earfcn_end = atoi(argv[optind]); - break; - case 'R': - nof_samples_rssi = atoi(argv[optind]); - break; - case 'r': - rssi_threshold = -atof(argv[optind]); - break; - case 'F': - nof_frames_find = atoi(argv[optind]); - break; - case 'f': - find_threshold = atof(argv[optind]); - break; - case 'T': - nof_frames_track = atoi(argv[optind]); - break; - case 't': - track_threshold = atof(argv[optind]); - break; - case 'g': - uhd_gain = atof(argv[optind]); - break; - case 'v': - verbose++; - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "bseRrFfTtgv")) != -1) { + switch(opt) { + case 'b': + band = atoi(argv[optind]); + break; + case 's': + earfcn_start = atoi(argv[optind]); + break; + case 'e': + earfcn_end = atoi(argv[optind]); + break; + case 'R': + nof_samples_rssi = atoi(argv[optind]); + break; + case 'r': + rssi_threshold = -atof(argv[optind]); + break; + case 'F': + nof_frames_find = atoi(argv[optind]); + break; + case 'f': + find_threshold = atof(argv[optind]); + break; + case 'T': + nof_frames_track = atoi(argv[optind]); + break; + case 't': + track_threshold = atof(argv[optind]); + break; + case 'g': + uhd_gain = atof(argv[optind]); + break; + case 'v': + verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } } int base_init(int frame_length) { - int i; - - input_buffer = malloc(2 * frame_length * sizeof(cf_t)); - if (!input_buffer) { - perror("malloc"); - return -1; - } - - fft_buffer = malloc(CPNORM_NSYMB * 72 * sizeof(cf_t)); - if (!fft_buffer) { - perror("malloc"); - return -1; - } - - for (i=0;i 0) { - return mean/n; - } else { - return 0.0; - } + int i; + float mean = 0; + int n = 0; + for (i=0;i 0) { + return mean/n; + } else { + return 0.0; + } } int preprocess_idx(int *in, int *out, int *period, int len) { - int i, n; - n=0; - for (i=0;i 100) { - /* scan every Mhz, that is 10 freqs */ - for (i=0;i 100) { + /* scan every Mhz, that is 10 freqs */ + for (i=0;i= nof_frames_find) { - state = INIT; - freq++; - } - } - break; - case TRACK: - INFO("Tracking PSS find_idx %d offset %d\n", find_idx, find_idx - track_len); - - track_idx = sync_run(&strack, &input_buffer[FLEN + find_idx - track_len]); - p2a_v[frame_cnt] = sync_get_peak_to_avg(&strack); - - /* save cell id for the best peak-to-avg */ - if (p2a_v[frame_cnt] > max_peak_to_avg) { - max_peak_to_avg = p2a_v[frame_cnt]; - cell_id = sync_get_cell_id(&strack); - } - if (track_idx != -1) { - cfo_v[frame_cnt] = sync_get_cfo(&strack); - last_found = frame_cnt; - find_idx += track_idx - track_len; - idx_v[frame_cnt] = find_idx; - nslot = sync_get_slot_id(&strack); - } else { - idx_v[frame_cnt] = -1; - cfo_v[frame_cnt] = 0.0; - } - /* if we missed to many PSS it is not a cell, next freq */ - if (frame_cnt - last_found > max_track_lost) { - INFO("\n[%3d/%d]: EARFCN %d Freq. %.2f MHz %d frames lost\n", freq, nof_bands, - channels[freq].id, channels[freq].fd, frame_cnt - last_found); - - state = INIT; - freq++; - } else if (frame_cnt >= nof_frames_track) { - mib_decoder_init(cell_id); - - cfo[freq] = mean_valid(idx_v, cfo_v, frame_cnt); - p2a[freq] = mean_valid(idx_v, p2a_v, frame_cnt); - valid_frames = preprocess_idx(idx_v, idx_valid, t, frame_cnt); - sfo = sfo_estimate_period(idx_valid, t, valid_frames, FLEN_PERIOD); - - state = MIB; - nslot=(nslot+10)%20; - } - break; - case MIB: - INFO("Finding MIB at freq %.2f Mhz offset=%d, cell_id=%d, slot_idx=%d\n", channels[freq].fd, find_idx, cell_id, nslot); - - // TODO: Correct SFO - - // Correct CFO - INFO("Correcting CFO=%.4f\n", cfo[freq]); - cfo_correct(&cfocorr, &input_buffer[FLEN], (-cfo[freq])/128); - - if (nslot == 0) { - if (mib_decoder_run(&input_buffer[FLEN+find_idx], &mib)) { - INFO("MIB detected attempt=%d\n", mib_attempts); - state = DONE; - } else { - INFO("MIB not detected attempt=%d\n", mib_attempts); - if (mib_attempts == 0) { - freq++; - state = INIT; - } - } - mib_attempts++; - } - nslot = (nslot+10)%20; - - - break; - case DONE: - printf("\n[%3d/%d]: FOUND EARFCN %d Freq. %.2f MHz. " - "PAR %2.2f dB, CFO=%+.2f KHz, SFO=%+2.3f KHz, CELL_ID=%3d\n", freq, nof_bands, - channels[freq].id, channels[freq].fd, - 10*log10f(p2a[freq]), cfo[freq] * 15, sfo / 1000, cell_id); - pbch_mib_fprint(stdout, &mib); - state = INIT; - freq++; - break; - } - - /** FIXME: This is not necessary at all */ - if (state == TRACK || state == FIND) { - memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t)); - } - frame_cnt++; - } - } - - base_free(); - - printf("\n\nDone\n"); - exit(0); + /* set find_threshold and go to FIND state */ + sync_set_threshold(&sfind, find_threshold); + sync_force_N_id_2(&sfind, -1); + state = FIND; + break; + case FIND: + /* find peak in all frame */ + find_idx = sync_run(&sfind, &input_buffer[FLEN]); + DEBUG("[%3d/%d]: PAR=%.2f\n", freq, nof_bands, sync_get_peak_to_avg(&sfind)); + if (find_idx != -1) { + /* if found peak, go to track and set lower threshold */ + frame_cnt = -1; + last_found = 0; + max_peak_to_avg = -1; + sync_set_threshold(&strack, track_threshold); + sync_force_N_id_2(&strack, sync_get_N_id_2(&sfind)); + cell_id = sync_get_cell_id(&sfind); + + state = TRACK; + INFO("[%3d/%d]: EARFCN %d Freq. %.2f MHz PSS found PAR %.2f dB\n", freq, nof_bands, + channels[freq].id, channels[freq].fd, + 10*log10f(sync_get_peak_to_avg(&sfind))); + } else { + if (frame_cnt >= nof_frames_find) { + state = INIT; + freq++; + } + } + break; + case TRACK: + INFO("Tracking PSS find_idx %d offset %d\n", find_idx, find_idx - track_len); + + track_idx = sync_run(&strack, &input_buffer[FLEN + find_idx - track_len]); + p2a_v[frame_cnt] = sync_get_peak_to_avg(&strack); + + /* save cell id for the best peak-to-avg */ + if (p2a_v[frame_cnt] > max_peak_to_avg) { + max_peak_to_avg = p2a_v[frame_cnt]; + cell_id = sync_get_cell_id(&strack); + } + if (track_idx != -1) { + cfo_v[frame_cnt] = sync_get_cfo(&strack); + last_found = frame_cnt; + find_idx += track_idx - track_len; + idx_v[frame_cnt] = find_idx; + nslot = sync_get_slot_id(&strack); + } else { + idx_v[frame_cnt] = -1; + cfo_v[frame_cnt] = 0.0; + } + /* if we missed to many PSS it is not a cell, next freq */ + if (frame_cnt - last_found > max_track_lost) { + INFO("\n[%3d/%d]: EARFCN %d Freq. %.2f MHz %d frames lost\n", freq, nof_bands, + channels[freq].id, channels[freq].fd, frame_cnt - last_found); + + state = INIT; + freq++; + } else if (frame_cnt >= nof_frames_track) { + mib_decoder_init(cell_id); + + cfo[freq] = mean_valid(idx_v, cfo_v, frame_cnt); + p2a[freq] = mean_valid(idx_v, p2a_v, frame_cnt); + valid_frames = preprocess_idx(idx_v, idx_valid, t, frame_cnt); + sfo = sfo_estimate_period(idx_valid, t, valid_frames, FLEN_PERIOD); + + state = MIB; + nslot=(nslot+10)%20; + } + break; + case MIB: + INFO("Finding MIB at freq %.2f Mhz offset=%d, cell_id=%d, slot_idx=%d\n", channels[freq].fd, find_idx, cell_id, nslot); + + // TODO: Correct SFO + + // Correct CFO + INFO("Correcting CFO=%.4f\n", cfo[freq]); + cfo_correct(&cfocorr, &input_buffer[FLEN], (-cfo[freq])/128); + + if (nslot == 0) { + if (mib_decoder_run(&input_buffer[FLEN+find_idx], &mib)) { + INFO("MIB detected attempt=%d\n", mib_attempts); + state = DONE; + } else { + INFO("MIB not detected attempt=%d\n", mib_attempts); + if (mib_attempts == 0) { + freq++; + state = INIT; + } + } + mib_attempts++; + } + nslot = (nslot+10)%20; + + + break; + case DONE: + printf("\n[%3d/%d]: FOUND EARFCN %d Freq. %.2f MHz. " + "PAR %2.2f dB, CFO=%+.2f KHz, SFO=%+2.3f KHz, CELL_ID=%3d\n", freq, nof_bands, + channels[freq].id, channels[freq].fd, + 10*log10f(p2a[freq]), cfo[freq] * 15, sfo / 1000, cell_id); + pbch_mib_fprint(stdout, &mib); + state = INIT; + freq++; + break; + } + + /** FIXME: This is not necessary at all */ + if (state == TRACK || state == FIND) { + memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t)); + } + frame_cnt++; + } + } + + base_free(); + + printf("\n\nDone\n"); + exit(0); } diff --git a/examples/scan_pss.c b/examples/scan_pss.c index 2afec3330..97379d610 100644 --- a/examples/scan_pss.c +++ b/examples/scan_pss.c @@ -37,13 +37,13 @@ #include "lte.h" #include "cuhd.h" -#define MHZ 1000000 -#define SAMP_FREQ 1920000 -#define RSSI_FS 1000000 -#define FLEN 9600 -#define FLEN_PERIOD 0.005 +#define MHZ 1000000 +#define SAMP_FREQ 1920000 +#define RSSI_FS 1000000 +#define FLEN 9600 +#define FLEN_PERIOD 0.005 -#define RSSI_DECIM 20 +#define RSSI_DECIM 20 #define IS_SIGNAL(i) (10*log10f(rssi[i]) + 30 > rssi_threshold) @@ -77,433 +77,433 @@ enum sync_state {INIT, FIND, TRACK, DONE}; void print_to_matlab(); void usage(char *prog) { - printf("Usage: %s [seRrFfTtgv] -b band\n", prog); - printf("\t-s earfcn_start [Default All]\n"); - printf("\t-e earfcn_end [Default All]\n"); - printf("\t-R rssi_nof_samples [Default %d]\n", nof_samples_rssi); - printf("\t-r rssi_threshold [Default %.2f dBm]\n", rssi_threshold); - printf("\t-F pss_find_nof_frames [Default %d]\n", nof_frames_find); - printf("\t-f pss_find_threshold [Default %.2f]\n", find_threshold); - printf("\t-T pss_track_nof_frames [Default %d]\n", nof_frames_track); - printf("\t-t pss_track_threshold [Default %.2f]\n", track_threshold); - printf("\t-l pss_track_len [Default %d]\n", track_len); - printf("\t-g gain [Default %.2f dB]\n", uhd_gain); - printf("\t-v [set verbose to debug, default none]\n"); + printf("Usage: %s [seRrFfTtgv] -b band\n", prog); + printf("\t-s earfcn_start [Default All]\n"); + printf("\t-e earfcn_end [Default All]\n"); + printf("\t-R rssi_nof_samples [Default %d]\n", nof_samples_rssi); + printf("\t-r rssi_threshold [Default %.2f dBm]\n", rssi_threshold); + printf("\t-F pss_find_nof_frames [Default %d]\n", nof_frames_find); + printf("\t-f pss_find_threshold [Default %.2f]\n", find_threshold); + printf("\t-T pss_track_nof_frames [Default %d]\n", nof_frames_track); + printf("\t-t pss_track_threshold [Default %.2f]\n", track_threshold); + printf("\t-l pss_track_len [Default %d]\n", track_len); + printf("\t-g gain [Default %.2f dB]\n", uhd_gain); + printf("\t-v [set verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "bseRrFfTtgv")) != -1) { - switch(opt) { - case 'b': - band = atoi(argv[optind]); - break; - case 's': - earfcn_start = atoi(argv[optind]); - break; - case 'e': - earfcn_end = atoi(argv[optind]); - break; - case 'R': - nof_samples_rssi = atoi(argv[optind]); - break; - case 'r': - rssi_threshold = -atof(argv[optind]); - break; - case 'F': - nof_frames_find = atoi(argv[optind]); - break; - case 'f': - find_threshold = atof(argv[optind]); - break; - case 'T': - nof_frames_track = atoi(argv[optind]); - break; - case 't': - track_threshold = atof(argv[optind]); - break; - case 'g': - uhd_gain = atof(argv[optind]); - break; - case 'v': - verbose++; - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "bseRrFfTtgv")) != -1) { + switch(opt) { + case 'b': + band = atoi(argv[optind]); + break; + case 's': + earfcn_start = atoi(argv[optind]); + break; + case 'e': + earfcn_end = atoi(argv[optind]); + break; + case 'R': + nof_samples_rssi = atoi(argv[optind]); + break; + case 'r': + rssi_threshold = -atof(argv[optind]); + break; + case 'F': + nof_frames_find = atoi(argv[optind]); + break; + case 'f': + find_threshold = atof(argv[optind]); + break; + case 'T': + nof_frames_track = atoi(argv[optind]); + break; + case 't': + track_threshold = atof(argv[optind]); + break; + case 'g': + uhd_gain = atof(argv[optind]); + break; + case 'v': + verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } } int base_init(int frame_length) { - input_buffer = malloc(2 * frame_length * sizeof(cf_t)); - if (!input_buffer) { - perror("malloc"); - exit(-1); - } - - idx_v = malloc(nof_frames_track * sizeof(int)); - if (!idx_v) { - perror("malloc"); - exit(-1); - } - idx_valid = malloc(nof_frames_track * sizeof(int)); - if (!idx_valid) { - perror("malloc"); - exit(-1); - } - t = malloc(nof_frames_track * sizeof(int)); - if (!t) { - perror("malloc"); - exit(-1); - } - cfo_v = malloc(nof_frames_track * sizeof(float)); - if (!cfo_v) { - perror("malloc"); - exit(-1); - } - p2a_v = malloc(nof_frames_track * sizeof(float)); - if (!p2a_v) { - perror("malloc"); - exit(-1); - } - - bzero(cfo, sizeof(float) * MAX_EARFCN); - bzero(p2a, sizeof(float) * MAX_EARFCN); - - /* open UHD device */ - printf("Opening UHD device...\n"); - if (cuhd_open("",&uhd)) { - fprintf(stderr, "Error opening uhd\n"); - exit(-1); - } - - return 0; + input_buffer = malloc(2 * frame_length * sizeof(cf_t)); + if (!input_buffer) { + perror("malloc"); + exit(-1); + } + + idx_v = malloc(nof_frames_track * sizeof(int)); + if (!idx_v) { + perror("malloc"); + exit(-1); + } + idx_valid = malloc(nof_frames_track * sizeof(int)); + if (!idx_valid) { + perror("malloc"); + exit(-1); + } + t = malloc(nof_frames_track * sizeof(int)); + if (!t) { + perror("malloc"); + exit(-1); + } + cfo_v = malloc(nof_frames_track * sizeof(float)); + if (!cfo_v) { + perror("malloc"); + exit(-1); + } + p2a_v = malloc(nof_frames_track * sizeof(float)); + if (!p2a_v) { + perror("malloc"); + exit(-1); + } + + bzero(cfo, sizeof(float) * MAX_EARFCN); + bzero(p2a, sizeof(float) * MAX_EARFCN); + + /* open UHD device */ + printf("Opening UHD device...\n"); + if (cuhd_open("",&uhd)) { + fprintf(stderr, "Error opening uhd\n"); + exit(-1); + } + + return 0; } void base_free() { - cuhd_close(uhd); - free(input_buffer); - free(idx_v); - free(idx_valid); - free(t); - free(cfo_v); - free(p2a_v); + cuhd_close(uhd); + free(input_buffer); + free(idx_v); + free(idx_valid); + free(t); + free(cfo_v); + free(p2a_v); } float mean_valid(int *idx_v, float *x, int nof_frames) { - int i; - float mean = 0; - int n = 0; - for (i=0;i 0) { - return mean/n; - } else { - return 0.0; - } + int i; + float mean = 0; + int n = 0; + for (i=0;i 0) { + return mean/n; + } else { + return 0.0; + } } int preprocess_idx(int *in, int *out, int *period, int len) { - int i, n; - n=0; - for (i=0;i 100) { - /* scan every Mhz, that is 10 freqs */ - for (i=0;i 100) { + /* scan every Mhz, that is 10 freqs */ + for (i=0;i= nof_frames_find) { - state = INIT; - printf("[%3d/%d]: EARFCN %d Freq. %.2f MHz No PSS found\r", freq, nof_bands, - channels[freq].id, channels[freq].fd, frame_cnt - last_found); - if (VERBOSE_ISINFO()) { - printf("\n"); - } - freq++; - } - } - break; - case TRACK: - INFO("Tracking PSS find_idx %d offset %d\n", find_idx, find_idx + track_len); - - filesink_write(&fs, &input_buffer[FLEN+find_idx+track_len], track_len); - - track_idx = sync_run(&strack, &input_buffer[FLEN + find_idx - track_len]); - p2a_v[frame_cnt] = sync_get_peak_to_avg(&strack); - - /* save cell id for the best peak-to-avg */ - if (p2a_v[frame_cnt] > max_peak_to_avg) { - max_peak_to_avg = p2a_v[frame_cnt]; - cell_id = sync_get_cell_id(&strack); - } - if (track_idx != -1) { - cfo_v[frame_cnt] = sync_get_cfo(&strack); - last_found = frame_cnt; - find_idx += track_idx - track_len; - idx_v[frame_cnt] = find_idx; - } else { - idx_v[frame_cnt] = -1; - cfo_v[frame_cnt] = 0.0; - } - /* if we missed to many PSS it is not a cell, next freq */ - if (frame_cnt - last_found > max_track_lost) { - INFO("\n[%3d/%d]: EARFCN %d Freq. %.2f MHz %d frames lost\n", freq, nof_bands, - channels[freq].id, channels[freq].fd, frame_cnt - last_found); - - state = INIT; - freq++; - } else if (frame_cnt >= nof_frames_track) { - state = DONE; - } - break; - case DONE: - - cfo[freq] = mean_valid(idx_v, cfo_v, frame_cnt); - p2a[freq] = mean_valid(idx_v, p2a_v, frame_cnt); - valid_frames = preprocess_idx(idx_v, idx_valid, t, frame_cnt); - sfo = sfo_estimate_period(idx_valid, t, valid_frames, FLEN_PERIOD); - - printf("\n[%3d/%d]: FOUND EARFCN %d Freq. %.2f MHz. " - "PAR %2.2f dB, CFO=%+.2f KHz, SFO=%+2.3f KHz, CELL_ID=%3d\n", freq, nof_bands, - channels[freq].id, channels[freq].fd, - 10*log10f(p2a[freq]), cfo[freq] * 15, sfo / 1000, cell_id); - state = INIT; - freq++; - break; - } - if (state == TRACK || (state == FIND && frame_cnt)) { - memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t)); - } - frame_cnt++; - } - } - - print_to_matlab(); - - sync_free(&sfind); - base_free(); - - printf("\n\nDone\n"); - exit(0); + int frame_cnt, valid_frames; + int freq; + int cell_id; + sync_t sfind, strack; + float max_peak_to_avg; + float sfo; + int find_idx, track_idx, last_found; + enum sync_state state; + int n; + filesink_t fs; + + if (argc < 3) { + usage(argv[0]); + exit(-1); + } + + parse_args(argc,argv); + + if (base_init(FLEN)) { + fprintf(stderr, "Error initializing memory\n"); + exit(-1); + } + + if (sync_init(&sfind, FLEN)) { + fprintf(stderr, "Error initiating PSS/SSS\n"); + exit(-1); + } + sync_pss_det_peak_to_avg(&sfind); + + if (sync_init(&strack, track_len)) { + fprintf(stderr, "Error initiating PSS/SSS\n"); + exit(-1); + } + sync_pss_det_peak_to_avg(&strack); + + nof_bands = lte_band_get_fd_band(band, channels, earfcn_start, earfcn_end, MAX_EARFCN); + printf("RSSI scan: %d freqs in band %d, RSSI threshold %.2f dBm\n", nof_bands, band, rssi_threshold); + + n = rssi_scan(); + if (n == -1) { + exit(-1); + } + + printf("\nDone. Starting PSS search on %d channels\n", n); + usleep(500000); + INFO("Setting sampling frequency %.2f MHz\n", (float) SAMP_FREQ/MHZ); + cuhd_set_rx_srate(uhd, SAMP_FREQ); + + cuhd_set_rx_gain(uhd, uhd_gain); + + print_to_matlab(); + + filesink_init(&fs, "test.dat", COMPLEX_FLOAT_BIN); + + freq=0; + state = INIT; + find_idx = 0; + max_peak_to_avg = 0; + last_found = 0; + frame_cnt = 0; + while(freq= nof_frames_find) { + state = INIT; + printf("[%3d/%d]: EARFCN %d Freq. %.2f MHz No PSS found\r", freq, nof_bands, + channels[freq].id, channels[freq].fd, frame_cnt - last_found); + if (VERBOSE_ISINFO()) { + printf("\n"); + } + freq++; + } + } + break; + case TRACK: + INFO("Tracking PSS find_idx %d offset %d\n", find_idx, find_idx + track_len); + + filesink_write(&fs, &input_buffer[FLEN+find_idx+track_len], track_len); + + track_idx = sync_run(&strack, &input_buffer[FLEN + find_idx - track_len]); + p2a_v[frame_cnt] = sync_get_peak_to_avg(&strack); + + /* save cell id for the best peak-to-avg */ + if (p2a_v[frame_cnt] > max_peak_to_avg) { + max_peak_to_avg = p2a_v[frame_cnt]; + cell_id = sync_get_cell_id(&strack); + } + if (track_idx != -1) { + cfo_v[frame_cnt] = sync_get_cfo(&strack); + last_found = frame_cnt; + find_idx += track_idx - track_len; + idx_v[frame_cnt] = find_idx; + } else { + idx_v[frame_cnt] = -1; + cfo_v[frame_cnt] = 0.0; + } + /* if we missed to many PSS it is not a cell, next freq */ + if (frame_cnt - last_found > max_track_lost) { + INFO("\n[%3d/%d]: EARFCN %d Freq. %.2f MHz %d frames lost\n", freq, nof_bands, + channels[freq].id, channels[freq].fd, frame_cnt - last_found); + + state = INIT; + freq++; + } else if (frame_cnt >= nof_frames_track) { + state = DONE; + } + break; + case DONE: + + cfo[freq] = mean_valid(idx_v, cfo_v, frame_cnt); + p2a[freq] = mean_valid(idx_v, p2a_v, frame_cnt); + valid_frames = preprocess_idx(idx_v, idx_valid, t, frame_cnt); + sfo = sfo_estimate_period(idx_valid, t, valid_frames, FLEN_PERIOD); + + printf("\n[%3d/%d]: FOUND EARFCN %d Freq. %.2f MHz. " + "PAR %2.2f dB, CFO=%+.2f KHz, SFO=%+2.3f KHz, CELL_ID=%3d\n", freq, nof_bands, + channels[freq].id, channels[freq].fd, + 10*log10f(p2a[freq]), cfo[freq] * 15, sfo / 1000, cell_id); + state = INIT; + freq++; + break; + } + if (state == TRACK || (state == FIND && frame_cnt)) { + memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t)); + } + frame_cnt++; + } + } + + print_to_matlab(); + + sync_free(&sfind); + base_free(); + + printf("\n\nDone\n"); + exit(0); } void print_to_matlab() { - int i; - - FILE *f = fopen("output.m", "w"); - if (!f) { - perror("fopen"); - exit(-1); - } - fprintf(f, "fd=["); - for (i=0;i max_value) { - max_value = peak_value[i]; - N_id_2 = i; - } - } - } + if (force_N_id_2 != -1) { + N_id_2 = force_N_id_2; + peak_pos[N_id_2] = pss_synch_find_pss(&pss[N_id_2], input, &peak_value[N_id_2], &mean_value[N_id_2]); + } else { + for (N_id_2=0;N_id_2<3;N_id_2++) { + peak_pos[N_id_2] = pss_synch_find_pss(&pss[N_id_2], input, &peak_value[N_id_2], &mean_value[N_id_2]); + } + float max_value=-99999; + N_id_2=-1; + int i; + for (i=0;i<3;i++) { + if (peak_value[i] > max_value) { + max_value = peak_value[i]; + N_id_2 = i; + } + } + } - /* If peak detected */ - if (peak_value[N_id_2]/mean_value[N_id_2] > corr_peak_threshold) { + /* If peak detected */ + if (peak_value[N_id_2]/mean_value[N_id_2] > corr_peak_threshold) { - sss_idx = peak_pos[N_id_2]-2*(symbol_sz+CP(symbol_sz,CPNORM_LEN)); - if (sss_idx >= 0) { - sss_synch_m0m1(&sss[N_id_2], &input[sss_idx], - &m0, &m0_value, &m1, &m1_value); + sss_idx = peak_pos[N_id_2]-2*(symbol_sz+CP(symbol_sz,CPNORM_LEN)); + if (sss_idx >= 0) { + sss_synch_m0m1(&sss[N_id_2], &input[sss_idx], + &m0, &m0_value, &m1, &m1_value); - cfo[frame_cnt] = pss_synch_cfo_compute(&pss[N_id_2], &input[peak_pos[N_id_2]-128]); - printf("\t%d\t%d\t%d\t%d\t%.3f\t\t%3d\t%d\t%d\t%.3f\n", - frame_cnt,N_id_2, sss_synch_N_id_1(&sss[N_id_2], m0, m1), - sss_synch_subframe(m0, m1), peak_value[N_id_2]/mean_value[N_id_2], - peak_pos[N_id_2], m0, m1, - cfo[frame_cnt]); - } - } - gettimeofday(&tdata[2], NULL); - get_time_interval(tdata); - exec_time[frame_cnt] = tdata[0].tv_usec; - frame_cnt++; - } + cfo[frame_cnt] = pss_synch_cfo_compute(&pss[N_id_2], &input[peak_pos[N_id_2]-128]); + printf("\t%d\t%d\t%d\t%d\t%.3f\t\t%3d\t%d\t%d\t%.3f\n", + frame_cnt,N_id_2, sss_synch_N_id_1(&sss[N_id_2], m0, m1), + sss_synch_subframe(m0, m1), peak_value[N_id_2]/mean_value[N_id_2], + peak_pos[N_id_2], m0, m1, + cfo[frame_cnt]); + } + } + gettimeofday(&tdata[2], NULL); + get_time_interval(tdata); + exec_time[frame_cnt] = tdata[0].tv_usec; + frame_cnt++; + } - int i; - float avg_time=0; - for (i=0;i 10 Mh. - * hop_quart is 00 for > 10 Mhz and hop_quart_neg is 01 for > 10 Mhz. - */ - enum { - hop_disabled = -1, - hop_quart = 0, - hop_quart_neg = 1, - hop_half = 2, - hop_type_2 = 3 - } freq_hop_fl; - - ra_type2_t type2_alloc; - ra_mcs_t mcs; - uint8_t rv_idx; // If set to non-zero, a retransmission is requested with the same modulation - // than before (Format0 message, see also 8.6.1 in 36.2313). - bool ndi; - bool cqi_request; + /* 36.213 Table 8.4-2: hop_half is 0 for < 10 Mhz and 10 for > 10 Mh. + * hop_quart is 00 for > 10 Mhz and hop_quart_neg is 01 for > 10 Mhz. + */ + enum { + hop_disabled = -1, + hop_quart = 0, + hop_quart_neg = 1, + hop_half = 2, + hop_type_2 = 3 + } freq_hop_fl; + + ra_type2_t type2_alloc; + ra_mcs_t mcs; + uint8_t rv_idx; // If set to non-zero, a retransmission is requested with the same modulation + // than before (Format0 message, see also 8.6.1 in 36.2313). + bool ndi; + bool cqi_request; } ra_pusch_t; typedef struct LIBLTE_API { - uint8_t prb_idx[110]; - int nof_prb; + uint8_t prb_idx[110]; + int nof_prb; }ra_prb_slot_t; typedef struct LIBLTE_API { - ra_prb_slot_t slot1; - ra_prb_slot_t slot2; - bool is_dist; + ra_prb_slot_t slot1; + ra_prb_slot_t slot2; + bool is_dist; }ra_prb_t; diff --git a/lte/include/lte/phch/regs.h b/lte/include/lte/phch/regs.h index e104b6f4c..ba9ff42aa 100644 --- a/lte/include/lte/phch/regs.h +++ b/lte/include/lte/phch/regs.h @@ -33,49 +33,49 @@ #include "lte/config.h" #include "lte/common/base.h" -#define REGS_PHICH_NSYM 12 -#define REGS_PHICH_REGS_X_GROUP 3 +#define REGS_PHICH_NSYM 12 +#define REGS_PHICH_REGS_X_GROUP 3 -#define REGS_PCFICH_NSYM 16 -#define REGS_PCFICH_NREGS 4 +#define REGS_PCFICH_NSYM 16 +#define REGS_PCFICH_NREGS 4 -#define REGS_RE_X_REG 4 +#define REGS_RE_X_REG 4 typedef _Complex float cf_t; typedef struct LIBLTE_API { - int k[4]; - int k0; - int l; - bool assigned; + int k[4]; + int k0; + int l; + bool assigned; }regs_reg_t; typedef struct LIBLTE_API { - int nof_regs; - regs_reg_t **regs; + int nof_regs; + regs_reg_t **regs; }regs_ch_t; typedef struct LIBLTE_API { - int cell_id; - int nof_prb; - int max_ctrl_symbols; - int cfi; - int ngroups_phich; - int nof_ports; - lte_cp_t cp; - phich_resources_t phich_res; - phich_length_t phich_len; - regs_ch_t pcfich; - regs_ch_t *phich; // there are several phich - regs_ch_t pdcch[3]; /* PDCCH indexing, permutation and interleaving is computed for - the three possible CFI value */ - int nof_regs; - regs_reg_t *regs; + int cell_id; + int nof_prb; + int max_ctrl_symbols; + int cfi; + int ngroups_phich; + int nof_ports; + lte_cp_t cp; + phich_resources_t phich_res; + phich_length_t phich_len; + regs_ch_t pcfich; + regs_ch_t *phich; // there are several phich + regs_ch_t pdcch[3]; /* PDCCH indexing, permutation and interleaving is computed for + the three possible CFI value */ + int nof_regs; + regs_reg_t *regs; }regs_t; LIBLTE_API int regs_init(regs_t *h, int cell_id, int nof_prb, int nof_ports, - phich_resources_t phich_res, phich_length_t phich_len, lte_cp_t cp); + phich_resources_t phich_res, phich_length_t phich_len, lte_cp_t cp); LIBLTE_API void regs_free(regs_t *h); LIBLTE_API int regs_set_cfi(regs_t *h, int nof_ctrl_symbols); diff --git a/lte/include/lte/scrambling/scrambling.h b/lte/include/lte/scrambling/scrambling.h index ba0a770f7..b677b6d51 100644 --- a/lte/include/lte/scrambling/scrambling.h +++ b/lte/include/lte/scrambling/scrambling.h @@ -49,35 +49,35 @@ LIBLTE_API void scrambling_c_offset(sequence_t *s, cf_t *data, int offset, int l /* High-level API */ /* channel integer values */ -#define SCRAMBLING_PDSCH 0 /* also PUSCH */ -#define SCRAMBLING_PCFICH 1 -#define SCRAMBLING_PDCCH 2 -#define SCRAMBLING_PBCH 3 -#define SCRAMBLING_PMCH 4 -#define SCRAMBLING_PUCCH 5 +#define SCRAMBLING_PDSCH 0 /* also PUSCH */ +#define SCRAMBLING_PCFICH 1 +#define SCRAMBLING_PDCCH 2 +#define SCRAMBLING_PBCH 3 +#define SCRAMBLING_PMCH 4 +#define SCRAMBLING_PUCCH 5 typedef struct LIBLTE_API { - sequence_t seq[NSUBFRAMES_X_FRAME]; + sequence_t seq[NSUBFRAMES_X_FRAME]; }scrambling_t; typedef struct LIBLTE_API { - scrambling_t obj; - struct scrambling_init { - int hard; - int q; - int cell_id; - int nrnti; - int nMBSFN; - int channel; - int nof_symbols; // 7 normal 6 extended - } init; - void *input; // input type may be char or float depending on hard - int in_len; - struct scrambling_ctrl_in { - int subframe; - } ctrl_in; - void *output; - int out_len; + scrambling_t obj; + struct scrambling_init { + int hard; + int q; + int cell_id; + int nrnti; + int nMBSFN; + int channel; + int nof_symbols; // 7 normal 6 extended + } init; + void *input; // input type may be char or float depending on hard + int in_len; + struct scrambling_ctrl_in { + int subframe; + } ctrl_in; + void *output; + int out_len; }scrambling_hl; #endif // SCRAMBLING_ diff --git a/lte/include/lte/sync/cfo.h b/lte/include/lte/sync/cfo.h index 136eabb6c..b07291f4f 100644 --- a/lte/include/lte/sync/cfo.h +++ b/lte/include/lte/sync/cfo.h @@ -41,11 +41,11 @@ typedef _Complex float cf_t; #define CFO_CEXPTAB_SIZE 4096 typedef struct LIBLTE_API { - float last_freq; - float tol; - int nsamples; - cexptab_t tab; - cf_t *cur_cexp; + float last_freq; + float tol; + int nsamples; + cexptab_t tab; + cf_t *cur_cexp; }cfo_t; LIBLTE_API int cfo_init(cfo_t *h, int nsamples); diff --git a/lte/include/lte/sync/pss.h b/lte/include/lte/sync/pss.h index 78b4c1e0d..30a0cafb4 100644 --- a/lte/include/lte/sync/pss.h +++ b/lte/include/lte/sync/pss.h @@ -40,11 +40,11 @@ typedef _Complex float cf_t; /* this is only a shortcut */ #define CONVOLUTION_FFT #define DEFAULT_CORRELATION_TH 10000 -#define DEFAULT_NOSYNC_TIMEOUT 5 +#define DEFAULT_NOSYNC_TIMEOUT 5 -#define PSS_LEN_FREQ 129 // FFT-based convolution removes 1 leaving it in 128 -#define PSS_LEN 62 -#define PSS_RE 6*12 +#define PSS_LEN_FREQ 129 // FFT-based convolution removes 1 leaving it in 128 +#define PSS_LEN 62 +#define PSS_RE 6*12 @@ -64,25 +64,25 @@ typedef _Complex float cf_t; /* this is only a shortcut */ typedef struct LIBLTE_API { #ifdef CONVOLUTION_FFT - conv_fft_cc_t conv_fft; + conv_fft_cc_t conv_fft; #endif - int frame_size; - int N_id_2; - float current_cfo; - bool cfo_auto; // default true - int nof_nosync_frames; - int nosync_timeout_frames; // default 5 - float correlation_threshold; // default 10000 - int frame_start_idx; - int fb_wp; - - cf_t *pss_signal_freq; - cf_t *tmp_input; - float *conv_abs; - cf_t *frame_buffer; - cf_t *conv_output; - cf_t *tmp_nco; + int frame_size; + int N_id_2; + float current_cfo; + bool cfo_auto; // default true + int nof_nosync_frames; + int nosync_timeout_frames; // default 5 + float correlation_threshold; // default 10000 + int frame_start_idx; + int fb_wp; + + cf_t *pss_signal_freq; + cf_t *tmp_input; + float *conv_abs; + cf_t *frame_buffer; + cf_t *conv_output; + cf_t *tmp_nco; }pss_synch_t; typedef enum { PSS_TX, PSS_RX } pss_direction_t; @@ -111,24 +111,24 @@ LIBLTE_API int pss_synch_get_frame_start_idx(pss_synch_t *q); /* High-level API */ typedef struct LIBLTE_API { - pss_synch_t obj; - struct pss_synch_init { - int frame_size; // if 0, 2048 - int unsync_nof_pkts; - int N_id_2; - int do_cfo; - } init; - cf_t *input; - int in_len; - struct pss_synch_ctrl_in { - int correlation_threshold; - float manual_cfo; - } ctrl_in; - cf_t *output; - int out_len; + pss_synch_t obj; + struct pss_synch_init { + int frame_size; // if 0, 2048 + int unsync_nof_pkts; + int N_id_2; + int do_cfo; + } init; + cf_t *input; + int in_len; + struct pss_synch_ctrl_in { + int correlation_threshold; + float manual_cfo; + } ctrl_in; + cf_t *output; + int out_len; }pss_synch_hl; -#define DEFAULT_FRAME_SIZE 2048 +#define DEFAULT_FRAME_SIZE 2048 LIBLTE_API int pss_synch_initialize(pss_synch_hl* h); LIBLTE_API int pss_synch_work(pss_synch_hl* hl); diff --git a/lte/include/lte/sync/sss.h b/lte/include/lte/sync/sss.h index 538d6efb7..54e7adb50 100644 --- a/lte/include/lte/sync/sss.h +++ b/lte/include/lte/sync/sss.h @@ -43,40 +43,40 @@ typedef _Complex float cf_t; /* this is only a shortcut */ * symbol_sz is the OFDM symbol size (including CP), e.g. 137 for the 1.9 MHz */ #define SSS_SYMBOL_ST(subframe_sz, symbol_sz) (subframe_sz/2-2*symbol_sz) -#define SSS_POS_SYMBOL 33 +#define SSS_POS_SYMBOL 33 #define SSS_DFT_LEN 128 -#define N_SSS 31 -#define SSS_LEN 2*N_SSS +#define N_SSS 31 +#define SSS_LEN 2*N_SSS struct sss_tables{ - int z1[N_SSS][N_SSS]; - int c[2][N_SSS]; - int s[N_SSS][N_SSS]; - int N_id_2; + int z1[N_SSS][N_SSS]; + int c[2][N_SSS]; + int s[N_SSS][N_SSS]; + int N_id_2; }; /* Allocate 32 complex to make it multiple of 32-byte AVX instructions alignment requirement. * Should use vect_malloc() to make it platform agnostic. */ struct fc_tables{ - cf_t z1[N_SSS+1][N_SSS+1]; - cf_t c[2][N_SSS+1]; - cf_t s[N_SSS+1][N_SSS+1]; + cf_t z1[N_SSS+1][N_SSS+1]; + cf_t c[2][N_SSS+1]; + cf_t s[N_SSS+1][N_SSS+1]; }; /* Low-level API */ typedef struct LIBLTE_API { - dft_plan_t dftp_input; + dft_plan_t dftp_input; - float corr_peak_threshold; - int symbol_sz; - int subframe_sz; + float corr_peak_threshold; + int symbol_sz; + int subframe_sz; - int N_id_1_table[30][30]; - struct fc_tables fc_tables; + int N_id_1_table[30][30]; + struct fc_tables fc_tables; }sss_synch_t; @@ -90,7 +90,7 @@ LIBLTE_API void sss_put_slot(float *sss, cf_t *symbol, int nof_prb, lte_cp_t cp) LIBLTE_API int sss_synch_set_N_id_2(sss_synch_t *q, int N_id_2); LIBLTE_API void sss_synch_m0m1(sss_synch_t *q, cf_t *input, int *m0, float *m0_value, - int *m1, float *m1_value); + int *m1, float *m1_value); LIBLTE_API int sss_synch_subframe(int m0, int m1); LIBLTE_API int sss_synch_N_id_1(sss_synch_t *q, int m0, int m1); @@ -103,24 +103,24 @@ LIBLTE_API void sss_synch_set_subframe_sz(sss_synch_t *q, int subframe_sz); /* High-level API */ typedef struct LIBLTE_API { - sss_synch_t obj; - struct sss_synch_init { - int N_id_2; - } init; - cf_t *input; - int in_len; - struct sss_synch_ctrl_in { - int symbol_sz; - int subframe_sz; - int correlation_threshold; - } ctrl_in; - struct sss_synch_ctrl_out { - int subframe_idx; - int N_id_1; - } ctrl_out; + sss_synch_t obj; + struct sss_synch_init { + int N_id_2; + } init; + cf_t *input; + int in_len; + struct sss_synch_ctrl_in { + int symbol_sz; + int subframe_sz; + int correlation_threshold; + } ctrl_in; + struct sss_synch_ctrl_out { + int subframe_idx; + int N_id_1; + } ctrl_out; }sss_synch_hl; -#define DEFAULT_FRAME_SIZE 2048 +#define DEFAULT_FRAME_SIZE 2048 LIBLTE_API int sss_synch_initialize(sss_synch_hl* h); LIBLTE_API int sss_synch_work(sss_synch_hl* hl); diff --git a/lte/include/lte/sync/sync.h b/lte/include/lte/sync/sync.h index 2a581d087..972ffa5ae 100644 --- a/lte/include/lte/sync/sync.h +++ b/lte/include/lte/sync/sync.h @@ -50,19 +50,19 @@ enum sync_pss_det { ABSOLUTE, PEAK_MEAN}; typedef struct LIBLTE_API { - pss_synch_t pss[3]; // One for each N_id_2 - sss_synch_t sss[3]; // One for each N_id_2 - enum sync_pss_det pss_mode; - float threshold; - float peak_to_avg; - int force_N_id_2; - int N_id_2; - int N_id_1; - int slot_id; - float cfo; - lte_cp_t cp; - bool detect_cp; - bool sss_en; + pss_synch_t pss[3]; // One for each N_id_2 + sss_synch_t sss[3]; // One for each N_id_2 + enum sync_pss_det pss_mode; + float threshold; + float peak_to_avg; + int force_N_id_2; + int N_id_2; + int N_id_1; + int slot_id; + float cfo; + lte_cp_t cp; + bool detect_cp; + bool sss_en; }sync_t; diff --git a/lte/include/lte/utils/cexptab.h b/lte/include/lte/utils/cexptab.h index 5ebdfd690..647a89587 100644 --- a/lte/include/lte/utils/cexptab.h +++ b/lte/include/lte/utils/cexptab.h @@ -35,8 +35,8 @@ typedef _Complex float cf_t; typedef struct LIBLTE_API { - int size; - cf_t *tab; + int size; + cf_t *tab; }cexptab_t; LIBLTE_API int cexptab_init(cexptab_t *nco, int size); diff --git a/lte/include/lte/utils/convolution.h b/lte/include/lte/utils/convolution.h index ab6924022..3b32e5c72 100644 --- a/lte/include/lte/utils/convolution.h +++ b/lte/include/lte/utils/convolution.h @@ -33,16 +33,16 @@ #include "lte/utils/dft.h" typedef struct LIBLTE_API { - _Complex float *input_fft; - _Complex float *filter_fft; - _Complex float *output_fft; - _Complex float *output_fft2; - int input_len; - int filter_len; - int output_len; - dft_plan_t input_plan; - dft_plan_t filter_plan; - dft_plan_t output_plan; + _Complex float *input_fft; + _Complex float *filter_fft; + _Complex float *output_fft; + _Complex float *output_fft2; + int input_len; + int filter_len; + int output_len; + dft_plan_t input_plan; + dft_plan_t filter_plan; + dft_plan_t output_plan; }conv_fft_cc_t; LIBLTE_API int conv_fft_cc_init(conv_fft_cc_t *state, int input_len, int filter_len); diff --git a/lte/include/lte/utils/debug.h b/lte/include/lte/utils/debug.h index 4ded02ce0..8eb2bb34a 100644 --- a/lte/include/lte/utils/debug.h +++ b/lte/include/lte/utils/debug.h @@ -31,9 +31,9 @@ #include #include "lte/config.h" -#define VERBOSE_DEBUG 2 -#define VERBOSE_INFO 1 -#define VERBOSE_NONE 0 +#define VERBOSE_DEBUG 2 +#define VERBOSE_INFO 1 +#define VERBOSE_NONE 0 #include LIBLTE_API void get_time_interval(struct timeval * tdata); @@ -50,10 +50,10 @@ LIBLTE_API extern int verbose; #define PRINT_NONE verbose=VERBOSE_NONE #define DEBUG(_fmt, ...) if (verbose >= VERBOSE_DEBUG) \ - fprintf(stdout, "[DEBUG]: " _fmt, __VA_ARGS__) + fprintf(stdout, "[DEBUG]: " _fmt, __VA_ARGS__) #define INFO(_fmt, ...) if (verbose >= VERBOSE_INFO) \ - fprintf(stdout, "[INFO]: " _fmt, __VA_ARGS__) + fprintf(stdout, "[INFO]: " _fmt, __VA_ARGS__) #else // DEBUG_DISABLED diff --git a/lte/include/lte/utils/dft.h b/lte/include/lte/utils/dft.h index c1d76228b..452e445ba 100644 --- a/lte/include/lte/utils/dft.h +++ b/lte/include/lte/utils/dft.h @@ -41,30 +41,30 @@ typedef enum { - COMPLEX_2_COMPLEX, REAL_2_REAL, COMPLEX_2_REAL + COMPLEX_2_COMPLEX, REAL_2_REAL, COMPLEX_2_REAL }dft_mode_t; typedef enum { - FORWARD, BACKWARD + FORWARD, BACKWARD }dft_dir_t; -#define DFT_MIRROR_PRE 1 -#define DFT_PSD 2 -#define DFT_OUT_DB 4 -#define DFT_MIRROR_POS 8 +#define DFT_MIRROR_PRE 1 +#define DFT_PSD 2 +#define DFT_OUT_DB 4 +#define DFT_MIRROR_POS 8 #define DFT_NORMALIZE 16 #define DFT_DC_OFFSET 32 typedef struct LIBLTE_API { - int size; - int sign; - void *in; - void *out; - void *p; - int options; - dft_dir_t dir; - dft_mode_t mode; + int size; + int sign; + void *in; + void *out; + void *p; + int options; + dft_dir_t dir; + dft_mode_t mode; }dft_plan_t; typedef _Complex float dft_c_t; diff --git a/lte/include/lte/utils/mux.h b/lte/include/lte/utils/mux.h index bcc42f564..0e5d238ec 100644 --- a/lte/include/lte/utils/mux.h +++ b/lte/include/lte/utils/mux.h @@ -31,10 +31,10 @@ #include "lte/config.h" LIBLTE_API void mux(void **input, void *output, int *input_lengths, int *input_padding_pre, int nof_inputs, - int sample_sz); + int sample_sz); LIBLTE_API void demux(void *input, void **output, int *output_lengths, - int *output_padding_pre, int *output_padding_post, int nof_outputs, - int sample_sz); + int *output_padding_pre, int *output_padding_post, int nof_outputs, + int sample_sz); #endif // MUX_ diff --git a/lte/lib/ch_estimation/src/chest.c b/lte/lib/ch_estimation/src/chest.c index 48faccdc4..cc1e53a26 100644 --- a/lte/lib/ch_estimation/src/chest.c +++ b/lte/lib/ch_estimation/src/chest.c @@ -41,203 +41,203 @@ #define SF_SZ(q) (2 * SLOT_SZ(q)) void chest_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { - chest_ref_fprint(q, stream, nslot, port_id); - chest_recvsig_fprint(q, stream, nslot, port_id); - chest_ce_fprint(q, stream, nslot, port_id); + chest_ref_fprint(q, stream, nslot, port_id); + chest_recvsig_fprint(q, stream, nslot, port_id); + chest_ce_fprint(q, stream, nslot, port_id); } void chest_ref_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { - int i; - fprintf(stream, "refs%d=[",port_id); - for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { - fprintf(stream, "%3.3f%+3.3fi, ", __real__ q->refsignal[port_id][nslot].refs[i].simbol, - __imag__ q->refsignal[port_id][nslot].refs[i].simbol); - } - fprintf(stream, "];\n"); + int i; + fprintf(stream, "refs%d=[",port_id); + for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { + fprintf(stream, "%3.3f%+3.3fi, ", __real__ q->refsignal[port_id][nslot].refs[i].simbol, + __imag__ q->refsignal[port_id][nslot].refs[i].simbol); + } + fprintf(stream, "];\n"); } void chest_recvsig_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { - int i; - fprintf(stream, "recvsig%d=[",port_id); - for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { - fprintf(stream, "%3.3f%+3.3fi, ", __real__ q->refsignal[port_id][nslot].refs[i].recv_simbol, - __imag__ q->refsignal[port_id][nslot].refs[i].recv_simbol); - } - fprintf(stream, "];\n"); + int i; + fprintf(stream, "recvsig%d=[",port_id); + for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { + fprintf(stream, "%3.3f%+3.3fi, ", __real__ q->refsignal[port_id][nslot].refs[i].recv_simbol, + __imag__ q->refsignal[port_id][nslot].refs[i].recv_simbol); + } + fprintf(stream, "];\n"); } void chest_ce_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { - int i; - fprintf(stream, "mag%d=[",port_id); - for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { - fprintf(stream, "%3.3f, ", cabsf(q->refsignal[port_id][nslot].ch_est[i])); - } - fprintf(stream, "];\nphase%d=[",port_id); - for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { - fprintf(stream, "%3.3f, ", atan2f(__imag__ q->refsignal[port_id][nslot].ch_est[i], - __real__ q->refsignal[port_id][nslot].ch_est[i])); - } - fprintf(stream, "];\n"); + int i; + fprintf(stream, "mag%d=[",port_id); + for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { + fprintf(stream, "%3.3f, ", cabsf(q->refsignal[port_id][nslot].ch_est[i])); + } + fprintf(stream, "];\nphase%d=[",port_id); + for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { + fprintf(stream, "%3.3f, ", atan2f(__imag__ q->refsignal[port_id][nslot].ch_est[i], + __real__ q->refsignal[port_id][nslot].ch_est[i])); + } + fprintf(stream, "];\n"); } void chest_ce_ref(chest_t *q, cf_t *input, int nslot, int port_id, int nref) { - int fidx, tidx; - cf_t known_ref, channel_ref; - - fidx = q->refsignal[port_id][nslot].refs[nref].freq_idx; // reference frequency index - tidx = q->refsignal[port_id][nslot].refs[nref].time_idx; // reference time index - known_ref = q->refsignal[port_id][nslot].refs[nref].simbol; - channel_ref = input[SAMPLE_IDX(q->nof_prb, tidx, fidx)]; - q->refsignal[port_id][nslot].refs[nref].recv_simbol = channel_ref; - - DEBUG("Reference %2d pos (%2d,%2d)=%3d %.2f dB %.2f/%.2f=%.2f\n", nref, tidx, fidx, SAMPLE_IDX(q->nof_prb, tidx, fidx), - 10*log10f(cabsf(channel_ref/known_ref)), - cargf(channel_ref)/M_PI,cargf(known_ref)/M_PI,cargf(channel_ref/known_ref)/M_PI); - - /* FIXME: compare with threshold */ - if (channel_ref != 0) { - q->refsignal[port_id][nslot].ch_est[nref] = channel_ref/known_ref; - } else { - q->refsignal[port_id][nslot].ch_est[nref] = 0; - } + int fidx, tidx; + cf_t known_ref, channel_ref; + + fidx = q->refsignal[port_id][nslot].refs[nref].freq_idx; // reference frequency index + tidx = q->refsignal[port_id][nslot].refs[nref].time_idx; // reference time index + known_ref = q->refsignal[port_id][nslot].refs[nref].simbol; + channel_ref = input[SAMPLE_IDX(q->nof_prb, tidx, fidx)]; + q->refsignal[port_id][nslot].refs[nref].recv_simbol = channel_ref; + + DEBUG("Reference %2d pos (%2d,%2d)=%3d %.2f dB %.2f/%.2f=%.2f\n", nref, tidx, fidx, SAMPLE_IDX(q->nof_prb, tidx, fidx), + 10*log10f(cabsf(channel_ref/known_ref)), + cargf(channel_ref)/M_PI,cargf(known_ref)/M_PI,cargf(channel_ref/known_ref)/M_PI); + + /* FIXME: compare with threshold */ + if (channel_ref != 0) { + q->refsignal[port_id][nslot].ch_est[nref] = channel_ref/known_ref; + } else { + q->refsignal[port_id][nslot].ch_est[nref] = 0; + } } /* Computes channel estimates for each reference in a slot and port. * Saves the nof_prb * 12 * nof_symbols channel estimates in the array ce */ void chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, int nslot, int port_id) { - int i, j; - cf_t x[2], y[MAX_NSYMB]; - - assert(nslot >= 0 && nslot < NSLOTS_X_FRAME); - assert(port_id >= 0 && port_id < q->nof_ports); - assert(q->refsignal[port_id][nslot].nsymbols <= 2); - - refsignal_t *r = &q->refsignal[port_id][nslot]; - - INFO("Estimating channel slot=%d port=%d using %d reference signals\n", - nslot, port_id, r->nof_refs); - - for (i=0;inof_refs;i++) { - chest_ce_ref(q, input, nslot, port_id, i); - } - - /* interpolate the symbols with references - * in the freq domain */ - for (i=0;insymbols;i++) { - interp_linear_offset(&r->ch_est[i * r->nof_refs/2], - &ce[r->symbols_ref[i] * q->nof_prb * RE_X_RB], RE_X_RB/2, - r->nof_refs/2, r->voffset, RE_X_RB/2-r->voffset); - - } - /* now interpolate in the time domain */ - for (i=0;inof_prb * RE_X_RB; i++) { - if (r->nsymbols > 1) { - for (j=0;jnsymbols;j++) { - x[j] = ce[r->symbols_ref[j] * q->nof_prb * RE_X_RB + i]; - } - interp_linear_offset(x, y, r->symbols_ref[1]-r->symbols_ref[0], - 2, r->symbols_ref[0], 3); - } else { - for (j=0;jsymbols_ref[0] * q->nof_prb * RE_X_RB + i]; - } - } - for (j=0;jnof_symbols;j++) { - ce[j * q->nof_prb * RE_X_RB + i] = y[j]; - } - } + int i, j; + cf_t x[2], y[MAX_NSYMB]; + + assert(nslot >= 0 && nslot < NSLOTS_X_FRAME); + assert(port_id >= 0 && port_id < q->nof_ports); + assert(q->refsignal[port_id][nslot].nsymbols <= 2); + + refsignal_t *r = &q->refsignal[port_id][nslot]; + + INFO("Estimating channel slot=%d port=%d using %d reference signals\n", + nslot, port_id, r->nof_refs); + + for (i=0;inof_refs;i++) { + chest_ce_ref(q, input, nslot, port_id, i); + } + + /* interpolate the symbols with references + * in the freq domain */ + for (i=0;insymbols;i++) { + interp_linear_offset(&r->ch_est[i * r->nof_refs/2], + &ce[r->symbols_ref[i] * q->nof_prb * RE_X_RB], RE_X_RB/2, + r->nof_refs/2, r->voffset, RE_X_RB/2-r->voffset); + + } + /* now interpolate in the time domain */ + for (i=0;inof_prb * RE_X_RB; i++) { + if (r->nsymbols > 1) { + for (j=0;jnsymbols;j++) { + x[j] = ce[r->symbols_ref[j] * q->nof_prb * RE_X_RB + i]; + } + interp_linear_offset(x, y, r->symbols_ref[1]-r->symbols_ref[0], + 2, r->symbols_ref[0], 3); + } else { + for (j=0;jsymbols_ref[0] * q->nof_prb * RE_X_RB + i]; + } + } + for (j=0;jnof_symbols;j++) { + ce[j * q->nof_prb * RE_X_RB + i] = y[j]; + } + } } /* Computes channel estimates for each reference in a slot. * Saves the result for the p-th port to the pointer ce[p] */ void chest_ce_slot(chest_t *q, cf_t *input, cf_t **ce, int nslot) { - int p; - for (p=0;pnof_ports;p++) { - chest_ce_slot_port(q, input, ce[p], nslot, p); - } + int p; + for (p=0;pnof_ports;p++) { + chest_ce_slot_port(q, input, ce[p], nslot, p); + } } int chest_init(chest_t *q, chest_interp_t interp, lte_cp_t cp, int nof_prb, int nof_ports) { - if (nof_ports > MAX_PORTS) { - fprintf(stderr, "Error: Maximum ports %d\n", MAX_PORTS); - return -1; - } - bzero(q, sizeof(chest_t)); + if (nof_ports > MAX_PORTS) { + fprintf(stderr, "Error: Maximum ports %d\n", MAX_PORTS); + return -1; + } + bzero(q, sizeof(chest_t)); - q->nof_ports = nof_ports; - q->nof_symbols = CP_NSYMB(cp); - q->cp = cp; - q->nof_prb = nof_prb; + q->nof_ports = nof_ports; + q->nof_symbols = CP_NSYMB(cp); + q->cp = cp; + q->nof_prb = nof_prb; - switch(interp) { - case LINEAR: - q->interp = interp_linear_offset; - } + switch(interp) { + case LINEAR: + q->interp = interp_linear_offset; + } - INFO("Initializing channel estimator size %dx%d, nof_ports=%d\n", - q->nof_symbols, nof_prb, nof_ports); + INFO("Initializing channel estimator size %dx%d, nof_ports=%d\n", + q->nof_symbols, nof_prb, nof_ports); - return 0; + return 0; } int chest_ref_LTEDL_slot_port(chest_t *q, int port, int nslot, int cell_id) { - if (port < 0 || port > q->nof_ports) { - return -1; - } - if (nslot < 0 || nslot > NSLOTS_X_FRAME) { - return -1; - } - - if (refsignal_init_LTEDL(&q->refsignal[port][nslot], port, nslot, cell_id, q->cp, q->nof_prb)) { - fprintf(stderr, "Error initiating CRS port=%d, slot=%d\n", port, nslot); - return -1; - } - - return 0; + if (port < 0 || port > q->nof_ports) { + return -1; + } + if (nslot < 0 || nslot > NSLOTS_X_FRAME) { + return -1; + } + + if (refsignal_init_LTEDL(&q->refsignal[port][nslot], port, nslot, cell_id, q->cp, q->nof_prb)) { + fprintf(stderr, "Error initiating CRS port=%d, slot=%d\n", port, nslot); + return -1; + } + + return 0; } int chest_ref_LTEDL_slot(chest_t *q, int nslot, int cell_id) { - int p; - for (p=0;pnof_ports;p++) { - if (chest_ref_LTEDL_slot_port(q, p, nslot, cell_id)) { - return -1; - } - } - return 0; + int p; + for (p=0;pnof_ports;p++) { + if (chest_ref_LTEDL_slot_port(q, p, nslot, cell_id)) { + return -1; + } + } + return 0; } int chest_ref_LTEDL(chest_t *q, int cell_id) { - int n; - for (n=0;nnof_ports;p++) { - for (n=0;nrefsignal[p][n]); - } - } - bzero(q, sizeof(chest_t)); + int p, n; + for (p=0;pnof_ports;p++) { + for (n=0;nrefsignal[p][n]); + } + } + bzero(q, sizeof(chest_t)); } /* Fills l[2] with the symbols in the slot nslot that contain references. * returns the number of symbols with references (in the slot) */ int chest_ref_symbols(chest_t *q, int port_id, int nslot, int l[2]) { - if (nslot < 0 || nslot > NSLOTS_X_FRAME) { - return -1; - } - memcpy(l, q->refsignal[port_id][nslot].symbols_ref, sizeof(int) * q->refsignal[port_id][nslot].nsymbols); - return q->refsignal[port_id][nslot].nsymbols; + if (nslot < 0 || nslot > NSLOTS_X_FRAME) { + return -1; + } + memcpy(l, q->refsignal[port_id][nslot].symbols_ref, sizeof(int) * q->refsignal[port_id][nslot].nsymbols); + return q->refsignal[port_id][nslot].nsymbols; } @@ -245,50 +245,50 @@ int chest_ref_symbols(chest_t *q, int port_id, int nslot, int l[2]) { */ int chest_initialize(chest_hl* h) { - if (!h->init.nof_symbols) { - h->init.nof_symbols = CPNORM_NSYMB; // Normal CP - } - if (!h->init.nof_prb) { - h->init.nof_prb = 6; - } - - if (chest_init(&h->obj, LINEAR, (h->init.nof_symbols==CPNORM_NSYMB)?CPNORM:CPEXT, - h->init.nof_prb, h->init.nof_ports)) { - fprintf(stderr, "Error initializing equalizer\n"); - return -1; - } - if (h->init.cell_id != -1) { - if (chest_ref_LTEDL(&h->obj, h->init.cell_id)) { - fprintf(stderr, "Error initializing reference signal\n"); - return -1; - } - } - - return 0; + if (!h->init.nof_symbols) { + h->init.nof_symbols = CPNORM_NSYMB; // Normal CP + } + if (!h->init.nof_prb) { + h->init.nof_prb = 6; + } + + if (chest_init(&h->obj, LINEAR, (h->init.nof_symbols==CPNORM_NSYMB)?CPNORM:CPEXT, + h->init.nof_prb, h->init.nof_ports)) { + fprintf(stderr, "Error initializing equalizer\n"); + return -1; + } + if (h->init.cell_id != -1) { + if (chest_ref_LTEDL(&h->obj, h->init.cell_id)) { + fprintf(stderr, "Error initializing reference signal\n"); + return -1; + } + } + + return 0; } /** This function must be called in an slot basis (0.5ms) for LTE */ int chest_work(chest_hl* hl) { - int i; - chest_t *q = &hl->obj; - - if (hl->init.cell_id != hl->ctrl_in.cell_id) { - if (chest_ref_LTEDL(q, hl->init.cell_id)) { - fprintf(stderr, "Error initializing reference signal\n"); - return -1; - } - } - - for (i=0;iinit.nof_ports;i++) { - chest_ce_slot_port(q, hl->input, hl->output[i], 1, 0); - hl->out_len[i] = hl->in_len; - } - return 0; + int i; + chest_t *q = &hl->obj; + + if (hl->init.cell_id != hl->ctrl_in.cell_id) { + if (chest_ref_LTEDL(q, hl->init.cell_id)) { + fprintf(stderr, "Error initializing reference signal\n"); + return -1; + } + } + + for (i=0;iinit.nof_ports;i++) { + chest_ce_slot_port(q, hl->input, hl->output[i], 1, 0); + hl->out_len[i] = hl->in_len; + } + return 0; } int chest_stop(chest_hl* hl) { - chest_free(&hl->obj); - return 0; + chest_free(&hl->obj); + return 0; } diff --git a/lte/lib/ch_estimation/src/refsignal.c b/lte/lib/ch_estimation/src/refsignal.c index 5e1008846..46651819f 100644 --- a/lte/lib/ch_estimation/src/refsignal.c +++ b/lte/lib/ch_estimation/src/refsignal.c @@ -41,150 +41,150 @@ #define idx(x, y) (l*nof_refs_x_symbol+i) int refsignal_v(int port_id, int ns, int symbol_id) { - int v=-1; - switch(port_id) { - case 0: - if (symbol_id == 0) { - v=0; - } else { - v=3; - } - break; - case 1: - if (symbol_id == 0) { - v=3; - } else { - v=0; - } - break; - case 2: - v=3*(ns%2); - break; - case 3: - v=3+3*(ns%2); - break; - } - return v; + int v=-1; + switch(port_id) { + case 0: + if (symbol_id == 0) { + v=0; + } else { + v=3; + } + break; + case 1: + if (symbol_id == 0) { + v=3; + } else { + v=0; + } + break; + case 2: + v=3*(ns%2); + break; + case 3: + v=3+3*(ns%2); + break; + } + return v; } int refsignal_k(int m, int v, int cell_id) { - return 6*m+((v+(cell_id%6))%6); + return 6*m+((v+(cell_id%6))%6); } void refsignal_put(refsignal_t *q, cf_t *slot_symbols) { - int i; - int fidx, tidx; - for (i=0;inof_refs;i++) { - fidx = q->refs[i].freq_idx; // reference frequency index - tidx = q->refs[i].time_idx; // reference time index - slot_symbols[SAMPLE_IDX(q->nof_prb, tidx, fidx)] = q->refs[i].simbol; - } + int i; + int fidx, tidx; + for (i=0;inof_refs;i++) { + fidx = q->refs[i].freq_idx; // reference frequency index + tidx = q->refs[i].time_idx; // reference time index + slot_symbols[SAMPLE_IDX(q->nof_prb, tidx, fidx)] = q->refs[i].simbol; + } } /** Initializes refsignal_t object according to 3GPP 36.211 6.10.1 * */ int refsignal_init_LTEDL(refsignal_t *q, int port_id, int nslot, - int cell_id, lte_cp_t cp, int nof_prb) { - - unsigned int c_init; - int ns, l, lp[2]; - int N_cp; - int i; - int ret = -1; - sequence_t seq; - int v; - int mp; - int nof_refs_x_symbol, nof_ref_symbols; - - bzero(q, sizeof(refsignal_t)); - bzero(&seq, sizeof(sequence_t)); - - if (CP_ISNORM(cp)) { - N_cp = 1; - } else { - N_cp = 0; - } - - if (port_id < 0 || port_id > (MAX_PORTS - 1)) { - fprintf(stderr, "Invalid port id %d\n", port_id); - return -1; - } - - if (port_id < 2) { - nof_ref_symbols = 2; - lp[0] = 0; - lp[1] = CP_NSYMB(cp) - 3; - } else { - nof_ref_symbols = 1; - lp[0] = 1; - } - nof_refs_x_symbol = 2 * nof_prb; - - q->nof_refs = nof_refs_x_symbol * nof_ref_symbols; - q->nsymbols = nof_ref_symbols; - q->symbols_ref = malloc(sizeof(int) * nof_ref_symbols); - q->voffset = cell_id%6; - q->nof_prb = nof_prb; - if (!q->symbols_ref) { - return -1; - } - - memcpy(q->symbols_ref, lp, sizeof(int) * nof_ref_symbols); - - q->refs = vec_malloc(q->nof_refs * sizeof(ref_t)); - if (!q->refs) { - goto free_and_exit; - } - q->ch_est = vec_malloc(q->nof_refs * sizeof(cf_t)); - if (!q->ch_est) { - goto free_and_exit; - } - - ns = nslot; - for (l = 0; l < nof_ref_symbols; l++) { - - c_init = 1024 * (7 * (ns + 1) + lp[l] + 1) * (2 * cell_id + 1) - + 2 * cell_id + N_cp; - if (sequence_LTEPRS(&seq, 2 * 2 * MAX_PRB, c_init)) { - goto free_and_exit; - } - - v = refsignal_v(port_id, ns, lp[l]); - - for (i = 0; i < nof_refs_x_symbol; i++) { - mp = i + MAX_PRB - nof_prb; - - /* generate signal */ - __real__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp]) / sqrt(2); - __imag__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2); - - /* mapping to resource elements */ - q->refs[idx(l,i)].freq_idx = refsignal_k(i, v, cell_id); - q->refs[idx(l,i)].time_idx = lp[l]; - } - } - - ret = 0; + int cell_id, lte_cp_t cp, int nof_prb) { + + unsigned int c_init; + int ns, l, lp[2]; + int N_cp; + int i; + int ret = -1; + sequence_t seq; + int v; + int mp; + int nof_refs_x_symbol, nof_ref_symbols; + + bzero(q, sizeof(refsignal_t)); + bzero(&seq, sizeof(sequence_t)); + + if (CP_ISNORM(cp)) { + N_cp = 1; + } else { + N_cp = 0; + } + + if (port_id < 0 || port_id > (MAX_PORTS - 1)) { + fprintf(stderr, "Invalid port id %d\n", port_id); + return -1; + } + + if (port_id < 2) { + nof_ref_symbols = 2; + lp[0] = 0; + lp[1] = CP_NSYMB(cp) - 3; + } else { + nof_ref_symbols = 1; + lp[0] = 1; + } + nof_refs_x_symbol = 2 * nof_prb; + + q->nof_refs = nof_refs_x_symbol * nof_ref_symbols; + q->nsymbols = nof_ref_symbols; + q->symbols_ref = malloc(sizeof(int) * nof_ref_symbols); + q->voffset = cell_id%6; + q->nof_prb = nof_prb; + if (!q->symbols_ref) { + return -1; + } + + memcpy(q->symbols_ref, lp, sizeof(int) * nof_ref_symbols); + + q->refs = vec_malloc(q->nof_refs * sizeof(ref_t)); + if (!q->refs) { + goto free_and_exit; + } + q->ch_est = vec_malloc(q->nof_refs * sizeof(cf_t)); + if (!q->ch_est) { + goto free_and_exit; + } + + ns = nslot; + for (l = 0; l < nof_ref_symbols; l++) { + + c_init = 1024 * (7 * (ns + 1) + lp[l] + 1) * (2 * cell_id + 1) + + 2 * cell_id + N_cp; + if (sequence_LTEPRS(&seq, 2 * 2 * MAX_PRB, c_init)) { + goto free_and_exit; + } + + v = refsignal_v(port_id, ns, lp[l]); + + for (i = 0; i < nof_refs_x_symbol; i++) { + mp = i + MAX_PRB - nof_prb; + + /* generate signal */ + __real__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp]) / sqrt(2); + __imag__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2); + + /* mapping to resource elements */ + q->refs[idx(l,i)].freq_idx = refsignal_k(i, v, cell_id); + q->refs[idx(l,i)].time_idx = lp[l]; + } + } + + ret = 0; free_and_exit: - sequence_free(&seq); - if (ret == -1) { - refsignal_free(q); - } - return ret; + sequence_free(&seq); + if (ret == -1) { + refsignal_free(q); + } + return ret; } void refsignal_free(refsignal_t *q) { - if (q->symbols_ref) { - free(q->symbols_ref); - } - if (q->refs) { - free(q->refs); - } - if (q->ch_est) { - free(q->ch_est); - } - bzero(q, sizeof(refsignal_t)); + if (q->symbols_ref) { + free(q->symbols_ref); + } + if (q->refs) { + free(q->refs); + } + if (q->ch_est) { + free(q->ch_est); + } + bzero(q, sizeof(refsignal_t)); } diff --git a/lte/lib/ch_estimation/test/chest_test.c b/lte/lib/ch_estimation/test/chest_test.c index 16160e7d7..fd97399fe 100644 --- a/lte/lib/ch_estimation/test/chest_test.c +++ b/lte/lib/ch_estimation/test/chest_test.c @@ -40,212 +40,212 @@ lte_cp_t cp = CPNORM; char *output_matlab = NULL; void usage(char *prog) { - printf("Usage: %s [recov]\n", prog); + printf("Usage: %s [recov]\n", prog); - printf("\t-r nof_prb [Default %d]\n", nof_prb); - printf("\t-e extended cyclic prefix [Default normal]\n"); + printf("\t-r nof_prb [Default %d]\n", nof_prb); + printf("\t-e extended cyclic prefix [Default normal]\n"); - printf("\t-c cell_id (-1 tests all). [Default %d]\n", cell_id); + printf("\t-c cell_id (-1 tests all). [Default %d]\n", cell_id); - printf("\t-o output matlab file [Default %s]\n",output_matlab?output_matlab:"None"); - printf("\t-v increase verbosity\n"); + printf("\t-o output matlab file [Default %s]\n",output_matlab?output_matlab:"None"); + printf("\t-v increase verbosity\n"); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "recov")) != -1) { - switch(opt) { - case 'r': - nof_prb = atoi(argv[optind]); - break; - case 'e': - cp = CPEXT; - break; - case 'c': - cell_id = atoi(argv[optind]); - break; - case 'o': - output_matlab = argv[optind]; - break; - case 'v': - verbose++; - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "recov")) != -1) { + switch(opt) { + case 'r': + nof_prb = atoi(argv[optind]); + break; + case 'e': + cp = CPEXT; + break; + case 'c': + cell_id = atoi(argv[optind]); + break; + case 'o': + output_matlab = argv[optind]; + break; + case 'v': + verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } } int check_mse(float mod, float arg, int n_port) { - INFO("mod=%.4f, arg=%.4f, n_port=%d\n", mod, arg, n_port); - switch(n_port) { - case 0: - if (mod > 0.029) { - return -1; - } - if (arg > 0.029) { - return -1; - } - break; - case 1: - if (mod > 0.012) { - return -1; - } - if (arg > 0.012) { - return -1; - } - break; - case 2: - case 3: - if (mod > 3.33) { - return -1; - } - if (arg > 0.63) { - return -1; - } - break; - default: - return -1; - } - return 0; + INFO("mod=%.4f, arg=%.4f, n_port=%d\n", mod, arg, n_port); + switch(n_port) { + case 0: + if (mod > 0.029) { + return -1; + } + if (arg > 0.029) { + return -1; + } + break; + case 1: + if (mod > 0.012) { + return -1; + } + if (arg > 0.012) { + return -1; + } + break; + case 2: + case 3: + if (mod > 3.33) { + return -1; + } + if (arg > 0.63) { + return -1; + } + break; + default: + return -1; + } + return 0; } int main(int argc, char **argv) { - chest_t eq; - cf_t *input = NULL, *ce = NULL, *h = NULL; - refsignal_t refs; - int i, j, n_port, n_slot, cid, num_re; - int ret = -1; - int max_cid; - FILE *fmatlab = NULL; - float mse_mag, mse_phase; - - parse_args(argc,argv); - - if (output_matlab) { - fmatlab=fopen(output_matlab, "w"); - if (!fmatlab) { - perror("fopen"); - goto do_exit; - } - } - - num_re = nof_prb * RE_X_RB * CP_NSYMB(cp); - - input = malloc(num_re * sizeof(cf_t)); - if (!input) { - perror("malloc"); - goto do_exit; - } - h = malloc(num_re * sizeof(cf_t)); - if (!h) { - perror("malloc"); - goto do_exit; - } - ce = malloc(num_re * sizeof(cf_t)); - if (!ce) { - perror("malloc"); - goto do_exit; - } - - if (cell_id == -1) { - cid = 0; - max_cid = 504; - } else { - cid = cell_id; - max_cid = cell_id; - } - while(cid <= max_cid) { - if (chest_init(&eq, LINEAR, cp, nof_prb, MAX_PORTS)) { - fprintf(stderr, "Error initializing equalizer\n"); - goto do_exit; - } - - if (chest_ref_LTEDL(&eq, cid)) { - fprintf(stderr, "Error initializing reference signal\n"); - goto do_exit; - } - - for (n_slot=0;n_slotinput,hl->output,hl->ctrl_in.variance,hl->in_len); - hl->out_len = hl->in_len; - return 0; + ch_awgn_c(hl->input,hl->output,hl->ctrl_in.variance,hl->in_len); + hl->out_len = hl->in_len; + return 0; } int ch_awgn_stop(ch_awgn_hl* hl) { - return 0; + return 0; } diff --git a/lte/lib/common/src/fft.c b/lte/lib/common/src/fft.c index 40440caee..77916f54b 100644 --- a/lte/lib/common/src/fft.c +++ b/lte/lib/common/src/fft.c @@ -36,99 +36,99 @@ #include "lte/utils/vector.h" int lte_fft_init_(lte_fft_t *q, lte_cp_t cp_type, int nof_prb, dft_dir_t dir) { - int symbol_sz = lte_symbol_sz(nof_prb); + int symbol_sz = lte_symbol_sz(nof_prb); - if (symbol_sz == -1) { - fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); - return -1; - } + if (symbol_sz == -1) { + fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); + return -1; + } if (dft_plan_c2c(&q->fft_plan, symbol_sz, dir)) { - fprintf(stderr, "Error: Creating DFT plan\n"); - return -1; - } - q->tmp = malloc(symbol_sz * sizeof(cf_t)); - if (!q->tmp) { - perror("malloc"); - return -1; - } + fprintf(stderr, "Error: Creating DFT plan\n"); + return -1; + } + q->tmp = malloc(symbol_sz * sizeof(cf_t)); + if (!q->tmp) { + perror("malloc"); + return -1; + } - q->fft_plan.options = DFT_NORMALIZE; - if (dir==FORWARD) { - q->fft_plan.options |= DFT_DC_OFFSET | DFT_MIRROR_POS; - } else { - q->fft_plan.options |= DFT_DC_OFFSET | DFT_MIRROR_PRE; - } - q->symbol_sz = symbol_sz; - q->nof_symbols = CP_NSYMB(cp_type); - q->cp_type = cp_type; - q->nof_re = nof_prb * RE_X_RB; - q->nof_guards = ((symbol_sz - q->nof_re) / 2); - DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp_type=%s, nof_re=%d, nof_guards=%d\n", - dir==FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols, - q->cp_type==CPNORM?"Normal":"Extended", q->nof_re, q->nof_guards); - return 0; + q->fft_plan.options = DFT_NORMALIZE; + if (dir==FORWARD) { + q->fft_plan.options |= DFT_DC_OFFSET | DFT_MIRROR_POS; + } else { + q->fft_plan.options |= DFT_DC_OFFSET | DFT_MIRROR_PRE; + } + q->symbol_sz = symbol_sz; + q->nof_symbols = CP_NSYMB(cp_type); + q->cp_type = cp_type; + q->nof_re = nof_prb * RE_X_RB; + q->nof_guards = ((symbol_sz - q->nof_re) / 2); + DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp_type=%s, nof_re=%d, nof_guards=%d\n", + dir==FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols, + q->cp_type==CPNORM?"Normal":"Extended", q->nof_re, q->nof_guards); + return 0; } void lte_fft_free_(lte_fft_t *q) { - dft_plan_free(&q->fft_plan); - if (q->tmp) { - free(q->tmp); - } - bzero(q, sizeof(lte_fft_t)); + dft_plan_free(&q->fft_plan); + if (q->tmp) { + free(q->tmp); + } + bzero(q, sizeof(lte_fft_t)); } int lte_fft_init(lte_fft_t *q, lte_cp_t cp_type, int nof_prb) { - return lte_fft_init_(q, cp_type, nof_prb, FORWARD); + return lte_fft_init_(q, cp_type, nof_prb, FORWARD); } void lte_fft_free(lte_fft_t *q) { - lte_fft_free_(q); + lte_fft_free_(q); } int lte_ifft_init(lte_fft_t *q, lte_cp_t cp_type, int nof_prb) { - int i; - if (lte_fft_init_(q, cp_type, nof_prb, BACKWARD)) { - return -1; - } - /* set now zeros at CP */ - for (i=0;inof_symbols;i++) { - bzero(q->tmp, q->nof_guards * sizeof(cf_t)); - bzero(&q->tmp[q->nof_re + q->nof_guards], q->nof_guards * sizeof(cf_t)); - } - return 0; + int i; + if (lte_fft_init_(q, cp_type, nof_prb, BACKWARD)) { + return -1; + } + /* set now zeros at CP */ + for (i=0;inof_symbols;i++) { + bzero(q->tmp, q->nof_guards * sizeof(cf_t)); + bzero(&q->tmp[q->nof_re + q->nof_guards], q->nof_guards * sizeof(cf_t)); + } + return 0; } void lte_ifft_free(lte_fft_t *q) { - lte_fft_free_(q); + lte_fft_free_(q); } /* Transforms input samples into output OFDM symbols. * Performs FFT on a each symbol and removes CP. */ void lte_fft_run(lte_fft_t *q, cf_t *input, cf_t *output) { - int i; - for (i=0;inof_symbols;i++) { - input += CP_ISNORM(q->cp_type)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz); - dft_run_c2c(&q->fft_plan, input, q->tmp); - memcpy(output, &q->tmp[q->nof_guards], q->nof_re * sizeof(cf_t)); - input += q->symbol_sz; - output += q->nof_re; - } + int i; + for (i=0;inof_symbols;i++) { + input += CP_ISNORM(q->cp_type)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz); + dft_run_c2c(&q->fft_plan, input, q->tmp); + memcpy(output, &q->tmp[q->nof_guards], q->nof_re * sizeof(cf_t)); + input += q->symbol_sz; + output += q->nof_re; + } } /* Transforms input OFDM symbols into output samples. * Performs FFT on a each symbol and adds CP. */ void lte_ifft_run(lte_fft_t *q, cf_t *input, cf_t *output) { - int i, cp_len; - for (i=0;inof_symbols;i++) { - cp_len = CP_ISNORM(q->cp_type)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz); - memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); - dft_run_c2c(&q->fft_plan, q->tmp, &output[cp_len]); - input += q->nof_re; - /* add CP */ - memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t)); - output += q->symbol_sz + cp_len; - } + int i, cp_len; + for (i=0;inof_symbols;i++) { + cp_len = CP_ISNORM(q->cp_type)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz); + memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); + dft_run_c2c(&q->fft_plan, q->tmp, &output[cp_len]); + input += q->nof_re; + /* add CP */ + memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t)); + output += q->symbol_sz + cp_len; + } } diff --git a/lte/lib/common/src/lte.c b/lte/lib/common/src/lte.c index 657f6fdb6..909359c80 100644 --- a/lte/lib/common/src/lte.c +++ b/lte/lib/common/src/lte.c @@ -35,243 +35,243 @@ #include "lte/common/base.h" const int tc_cb_sizes[NOF_TC_CB_SIZES] = { 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, - 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, - 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344, - 352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, 448, 456, - 464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, 608, 624, - 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848, - 864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1056, 1088, - 1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472, - 1504, 1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856, - 1888, 1920, 1952, 1984, 2016, 2048, 2112, 2176, 2240, 2304, 2368, 2432, - 2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136, 3200, - 3264, 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, 3904, 3968, - 4032, 4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544, 4608, 4672, 4736, - 4800, 4864, 4928, 4992, 5056, 5120, 5184, 5248, 5312, 5376, 5440, 5504, - 5568, 5632, 5696, 5760, 5824, 5888, 5952, 6016, 6080, 6144 }; + 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, + 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344, + 352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, 448, 456, + 464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, 608, 624, + 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848, + 864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1056, 1088, + 1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472, + 1504, 1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856, + 1888, 1920, 1952, 1984, 2016, 2048, 2112, 2176, 2240, 2304, 2368, 2432, + 2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136, 3200, + 3264, 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, 3904, 3968, + 4032, 4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544, 4608, 4672, 4736, + 4800, 4864, 4928, 4992, 5056, 5120, 5184, 5248, 5312, 5376, 5440, 5504, + 5568, 5632, 5696, 5760, 5824, 5888, 5952, 6016, 6080, 6144 }; int lte_cb_size(int index) { - if (index >= 0 && index < NOF_TC_CB_SIZES) { - return tc_cb_sizes[index]; - } else { - return -1; - } + if (index >= 0 && index < NOF_TC_CB_SIZES) { + return tc_cb_sizes[index]; + } else { + return -1; + } } int lte_find_cb_index(int long_cb) { - int j = 0; - while (j < NOF_TC_CB_SIZES && tc_cb_sizes[j] < long_cb) { - j++; - } + int j = 0; + while (j < NOF_TC_CB_SIZES && tc_cb_sizes[j] < long_cb) { + j++; + } - if (j == NOF_TC_CB_SIZES) { - return -1; - } else { - return j; - } + if (j == NOF_TC_CB_SIZES) { + return -1; + } else { + return j; + } } const int lte_symbol_sz(int nof_prb) { - if (nof_prb<=0) { - return -1; - } - if (nof_prb<=6) { - return 128; - } else if (nof_prb<=15) { - return 256; - } else if (nof_prb<=25) { - return 512; - } else if (nof_prb<=50) { - return 1024; - } else if (nof_prb<=75) { - return 1536; - } else if (nof_prb<=100) { - return 2048; - } - return -1; + if (nof_prb<=0) { + return -1; + } + if (nof_prb<=6) { + return 128; + } else if (nof_prb<=15) { + return 256; + } else if (nof_prb<=25) { + return 512; + } else if (nof_prb<=50) { + return 1024; + } else if (nof_prb<=75) { + return 1536; + } else if (nof_prb<=100) { + return 2048; + } + return -1; } int lte_voffset(int symbol_id, int cell_id, int nof_ports) { - if (nof_ports == 1 && symbol_id==0) { - return (cell_id+3) % 6; - } else { - return cell_id % 6; - } + if (nof_ports == 1 && symbol_id==0) { + return (cell_id+3) % 6; + } else { + return cell_id % 6; + } } /* Returns the number of available RE per PRB */ int lte_re_x_prb(int ns, int symbol, int nof_ports, int nof_symbols) { - if (symbol == 0) { - if (((ns % 2) == 0) || (ns == 1)) { - return RE_X_RB - 4; - } else { - if (nof_ports == 1) { - return RE_X_RB - 2; - } else { - return RE_X_RB - 4; - } - } - } else if (symbol == 1) { - if (ns == 1) { - return RE_X_RB - 4; - } else if (nof_ports == 4) { - return RE_X_RB - 4; - } else { - return RE_X_RB; - } - } else if (symbol == nof_symbols - 3) { - if (nof_ports == 1) { - return RE_X_RB - 2; - } else { - return RE_X_RB - 4; - } - } else { - return RE_X_RB; - } + if (symbol == 0) { + if (((ns % 2) == 0) || (ns == 1)) { + return RE_X_RB - 4; + } else { + if (nof_ports == 1) { + return RE_X_RB - 2; + } else { + return RE_X_RB - 4; + } + } + } else if (symbol == 1) { + if (ns == 1) { + return RE_X_RB - 4; + } else if (nof_ports == 4) { + return RE_X_RB - 4; + } else { + return RE_X_RB; + } + } else if (symbol == nof_symbols - 3) { + if (nof_ports == 1) { + return RE_X_RB - 2; + } else { + return RE_X_RB - 4; + } + } else { + return RE_X_RB; + } } struct lte_band { - int band; - float fd_low_mhz; - int earfcn_offset; - int earfcn_max; - enum band_geographical_area area; + int band; + float fd_low_mhz; + int earfcn_offset; + int earfcn_max; + enum band_geographical_area area; }; struct lte_band lte_bands[NOF_LTE_BANDS] = { - {1, 2110, 0, 599, ALL}, - {2, 1930, 600, 1199, NAR}, - {3, 1805, 1200, 1949, ALL}, - {4, 2110, 1950, 2399, NAR}, - {5, 869, 2400, 2649, NAR}, - {6, 875, 2650, 2749, APAC}, - {7, 2620, 2750, 3449, EMEA}, - {8, 925, 3450, 3799, ALL}, - {9, 1844.9, 3800, 4149, APAC}, - {10, 2110, 4150, 4749, NAR}, - {11, 1475.9, 4750, 4949, JAPAN}, - {12, 729, 5010, 5179, NAR}, - {13, 746, 5180, 5279, NAR}, - {14, 758, 5280, 5379, NAR}, - {17, 734, 5730, 5849, NAR}, - {18, 860, 5850, 5999, JAPAN}, - {19, 875, 6000, 6149, JAPAN}, - {20, 791, 6150, 6449, EMEA}, - {21, 1495.9, 6450, 6599, JAPAN}, - {22, 3500, 6600, 7399, NA}, - {23, 2180, 7500, 7699, NAR}, - {24, 1525, 7700, 8039, NAR}, - {25, 1930, 8040, 8689, NAR}, - {26, 859, 8690, 9039, NAR}, - {27, 852, 9040, 9209, NAR}, - {28, 758, 9210, 9659, APAC}, - {29, 717, 9660, 9769, NAR}, - {30, 2350, 9770, 9869, NAR}, - {31, 462.5, 9870, 9919, CALA} + {1, 2110, 0, 599, ALL}, + {2, 1930, 600, 1199, NAR}, + {3, 1805, 1200, 1949, ALL}, + {4, 2110, 1950, 2399, NAR}, + {5, 869, 2400, 2649, NAR}, + {6, 875, 2650, 2749, APAC}, + {7, 2620, 2750, 3449, EMEA}, + {8, 925, 3450, 3799, ALL}, + {9, 1844.9, 3800, 4149, APAC}, + {10, 2110, 4150, 4749, NAR}, + {11, 1475.9, 4750, 4949, JAPAN}, + {12, 729, 5010, 5179, NAR}, + {13, 746, 5180, 5279, NAR}, + {14, 758, 5280, 5379, NAR}, + {17, 734, 5730, 5849, NAR}, + {18, 860, 5850, 5999, JAPAN}, + {19, 875, 6000, 6149, JAPAN}, + {20, 791, 6150, 6449, EMEA}, + {21, 1495.9, 6450, 6599, JAPAN}, + {22, 3500, 6600, 7399, NA}, + {23, 2180, 7500, 7699, NAR}, + {24, 1525, 7700, 8039, NAR}, + {25, 1930, 8040, 8689, NAR}, + {26, 859, 8690, 9039, NAR}, + {27, 852, 9040, 9209, NAR}, + {28, 758, 9210, 9659, APAC}, + {29, 717, 9660, 9769, NAR}, + {30, 2350, 9770, 9869, NAR}, + {31, 462.5, 9870, 9919, CALA} }; #define EOF_BAND 9919 int lte_str2mimotype(char *mimo_type_str, lte_mimo_type_t *type) { - if (!strcmp(mimo_type_str, "single")) { - *type = SINGLE_ANTENNA; - } else if (!strcmp(mimo_type_str, "diversity")) { - *type = TX_DIVERSITY; - } else if (!strcmp(mimo_type_str, "multiplex")) { - *type = SPATIAL_MULTIPLEX; - } else { - return -1; - } - return 0; + if (!strcmp(mimo_type_str, "single")) { + *type = SINGLE_ANTENNA; + } else if (!strcmp(mimo_type_str, "diversity")) { + *type = TX_DIVERSITY; + } else if (!strcmp(mimo_type_str, "multiplex")) { + *type = SPATIAL_MULTIPLEX; + } else { + return -1; + } + return 0; } char *lte_mimotype2str(lte_mimo_type_t type) { - switch(type) { - case SINGLE_ANTENNA: - return "single"; - case TX_DIVERSITY: - return "diversity"; - case SPATIAL_MULTIPLEX: - return "multiplex"; - } - return NULL; + switch(type) { + case SINGLE_ANTENNA: + return "single"; + case TX_DIVERSITY: + return "diversity"; + case SPATIAL_MULTIPLEX: + return "multiplex"; + } + return NULL; } float get_fd(struct lte_band *band, int earfcn) { - return band->fd_low_mhz + 0.1*(earfcn - band->earfcn_offset); + return band->fd_low_mhz + 0.1*(earfcn - band->earfcn_offset); } float lte_band_fd(int earfcn) { - int i; - i=0; - while(i < NOF_LTE_BANDS && lte_bands[i].earfcn_offset lte_bands[i].earfcn_max) { - fprintf(stderr, "Error: Invalid end earfcn %d. Max is %d\n", end_earfcn, lte_bands[i].earfcn_max); - return -1; - } - } - if (start_earfcn == -1) { - start_earfcn = lte_bands[i].earfcn_offset; - } else { - if (start_earfcn < lte_bands[i].earfcn_offset) { - fprintf(stderr, "Error: Invalid start earfcn %d. Min is %d\n", start_earfcn, lte_bands[i].earfcn_offset); - return -1; - } - } - nof_earfcn = end_earfcn - start_earfcn; + int i, j; + int nof_earfcn; + i=0; + while(i < NOF_LTE_BANDS && lte_bands[i].band != band) { + i++; + } + if (i == NOF_LTE_BANDS) { + fprintf(stderr, "Error: Invalid band %d\n", band); + return -1; + } + if (end_earfcn == -1) { + end_earfcn = lte_bands[i].earfcn_max; + } else { + if (end_earfcn > lte_bands[i].earfcn_max) { + fprintf(stderr, "Error: Invalid end earfcn %d. Max is %d\n", end_earfcn, lte_bands[i].earfcn_max); + return -1; + } + } + if (start_earfcn == -1) { + start_earfcn = lte_bands[i].earfcn_offset; + } else { + if (start_earfcn < lte_bands[i].earfcn_offset) { + fprintf(stderr, "Error: Invalid start earfcn %d. Min is %d\n", start_earfcn, lte_bands[i].earfcn_offset); + return -1; + } + } + nof_earfcn = end_earfcn - start_earfcn; - if (nof_earfcn > max_elems) { - nof_earfcn = max_elems; - } - for (j=0;j max_elems) { + nof_earfcn = max_elems; + } + for (j=0;j 0;i++) { - if (lte_bands[i].area == region) { - n = lte_band_get_fd_band(i, &earfcn[nof_fd], -1, -1, max_elems); - if (n != -1) { - nof_fd += n; - max_elems -= n; - } else { - return -1; - } - } - } - return nof_fd; + int i; + int n; + int nof_fd = 0; + for (i=0;i 0;i++) { + if (lte_bands[i].area == region) { + n = lte_band_get_fd_band(i, &earfcn[nof_fd], -1, -1, max_elems); + if (n != -1) { + nof_fd += n; + max_elems -= n; + } else { + return -1; + } + } + } + return nof_fd; } diff --git a/lte/lib/common/src/sequence.c b/lte/lib/common/src/sequence.c index 32e00359b..87dbbf4be 100644 --- a/lte/lib/common/src/sequence.c +++ b/lte/lib/common/src/sequence.c @@ -42,67 +42,67 @@ * Section 7.2 */ void generate_prs_c(sequence_t *q, unsigned int seed) { - int n; - unsigned int *x1; - unsigned int *x2; - - x1 = calloc(Nc + q->len + 31, sizeof(unsigned int)); - if (!x1) { - perror("calloc"); - return; - } - x2 = calloc(Nc + q->len + 31, sizeof(unsigned int)); - if (!x2) { - free(x1); - perror("calloc"); - return; - } - - for (n = 0; n < 31; n++) { - x2[n] = (seed >> n) & 0x1; - } - x1[0] = 1; - - for (n = 0; n < Nc + q->len; n++) { - x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1; - x2[n + 31] = (x2[n + 3] + x2[n + 2] + +x2[n+1] + x2[n]) & 0x1; - } - - for (n = 0; n < q->len; n++) { - q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1; - } - - free(x1); - free(x2); + int n; + unsigned int *x1; + unsigned int *x2; + + x1 = calloc(Nc + q->len + 31, sizeof(unsigned int)); + if (!x1) { + perror("calloc"); + return; + } + x2 = calloc(Nc + q->len + 31, sizeof(unsigned int)); + if (!x2) { + free(x1); + perror("calloc"); + return; + } + + for (n = 0; n < 31; n++) { + x2[n] = (seed >> n) & 0x1; + } + x1[0] = 1; + + for (n = 0; n < Nc + q->len; n++) { + x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1; + x2[n + 31] = (x2[n + 3] + x2[n + 2] + +x2[n+1] + x2[n]) & 0x1; + } + + for (n = 0; n < q->len; n++) { + q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1; + } + + free(x1); + free(x2); } int sequence_LTEPRS(sequence_t *q, int len, int seed) { - if (sequence_init(q, len)) { - return -1; - } - q->len = len; - generate_prs_c(q, seed); - return 0; + if (sequence_init(q, len)) { + return -1; + } + q->len = len; + generate_prs_c(q, seed); + return 0; } int sequence_init(sequence_t *q, int len) { - if (q->c && (q->len != len)) { - free(q->c); - } - if (!q->c) { - q->c = malloc(len * sizeof(char)); - if (!q->c) { - return -1; - } - } - return 0; + if (q->c && (q->len != len)) { + free(q->c); + } + if (!q->c) { + q->c = malloc(len * sizeof(char)); + if (!q->c) { + return -1; + } + } + return 0; } void sequence_free(sequence_t *q) { - if (q->c) { - free(q->c); - } - bzero(q, sizeof(sequence_t)); + if (q->c) { + free(q->c); + } + bzero(q, sizeof(sequence_t)); } diff --git a/lte/lib/common/test/fft_test.c b/lte/lib/common/test/fft_test.c index 2e4feff2a..2b3c1188c 100644 --- a/lte/lib/common/test/fft_test.c +++ b/lte/lib/common/test/fft_test.c @@ -38,104 +38,104 @@ int nof_prb = -1; lte_cp_t cp = CPNORM; void usage(char *prog) { - printf("Usage: %s\n", prog); - printf("\t-n nof_prb [Default All]\n"); - printf("\t-e extended cyclic prefix [Default Normal]\n"); + printf("Usage: %s\n", prog); + printf("\t-n nof_prb [Default All]\n"); + printf("\t-e extended cyclic prefix [Default Normal]\n"); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "ne")) != -1) { - switch (opt) { - case 'n': - nof_prb = atoi(argv[optind]); - break; - case 'e': - cp = CPEXT; - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "ne")) != -1) { + switch (opt) { + case 'n': + nof_prb = atoi(argv[optind]); + break; + case 'e': + cp = CPEXT; + break; + default: + usage(argv[0]); + exit(-1); + } + } } int main(int argc, char **argv) { - lte_fft_t fft, ifft; - cf_t *input, *outfft, *outifft; - float mse; - int n_prb, max_prb, n_re; - int i; - - parse_args(argc, argv); - - if (nof_prb == -1) { - n_prb = 6; - max_prb = 100; - } else { - n_prb = nof_prb; - max_prb = nof_prb; - } - while(n_prb <= max_prb) { - n_re = CP_NSYMB(cp) * n_prb * RE_X_RB; - - printf("Running test for %d PRB, %d RE... ", n_prb, n_re);fflush(stdout); - - input = malloc(sizeof(cf_t) * n_re); - if (!input) { - perror("malloc"); - exit(-1); - } - outfft = malloc(sizeof(cf_t) * SLOT_LEN_CPNORM(lte_symbol_sz(n_prb))); - if (!outfft) { - perror("malloc"); - exit(-1); - } - outifft = malloc(sizeof(cf_t) * n_re); - if (!outifft) { - perror("malloc"); - exit(-1); - } - - if (lte_fft_init(&fft, cp, n_prb)) { - fprintf(stderr, "Error initializing FFT\n"); - exit(-1); - } - if (lte_ifft_init(&ifft, cp, n_prb)) { - fprintf(stderr, "Error initializing iFFT\n"); - exit(-1); - } - - for (i=0;i= 0.07) { - printf("MSE too large\n"); - exit(-1); - } - - lte_fft_free(&fft); - lte_ifft_free(&ifft); - - free(input); - free(outfft); - free(outifft); - - n_prb++; - } - fftwf_cleanup(); - exit(0); + lte_fft_t fft, ifft; + cf_t *input, *outfft, *outifft; + float mse; + int n_prb, max_prb, n_re; + int i; + + parse_args(argc, argv); + + if (nof_prb == -1) { + n_prb = 6; + max_prb = 100; + } else { + n_prb = nof_prb; + max_prb = nof_prb; + } + while(n_prb <= max_prb) { + n_re = CP_NSYMB(cp) * n_prb * RE_X_RB; + + printf("Running test for %d PRB, %d RE... ", n_prb, n_re);fflush(stdout); + + input = malloc(sizeof(cf_t) * n_re); + if (!input) { + perror("malloc"); + exit(-1); + } + outfft = malloc(sizeof(cf_t) * SLOT_LEN_CPNORM(lte_symbol_sz(n_prb))); + if (!outfft) { + perror("malloc"); + exit(-1); + } + outifft = malloc(sizeof(cf_t) * n_re); + if (!outifft) { + perror("malloc"); + exit(-1); + } + + if (lte_fft_init(&fft, cp, n_prb)) { + fprintf(stderr, "Error initializing FFT\n"); + exit(-1); + } + if (lte_ifft_init(&ifft, cp, n_prb)) { + fprintf(stderr, "Error initializing iFFT\n"); + exit(-1); + } + + for (i=0;i= 0.07) { + printf("MSE too large\n"); + exit(-1); + } + + lte_fft_free(&fft); + lte_ifft_free(&ifft); + + free(input); + free(outfft); + free(outifft); + + n_prb++; + } + fftwf_cleanup(); + exit(0); } diff --git a/lte/lib/fec/src/convcoder.c b/lte/lib/fec/src/convcoder.c index 4fbd3e203..97a3b157e 100644 --- a/lte/lib/fec/src/convcoder.c +++ b/lte/lib/fec/src/convcoder.c @@ -34,47 +34,47 @@ #include "parity.h" int convcoder_encode(convcoder_t *q, char *input, char *output, int frame_length) { - unsigned int sr; - int i,j; - int len = q->tail_biting ? frame_length : (frame_length + q->K - 1); + unsigned int sr; + int i,j; + int len = q->tail_biting ? frame_length : (frame_length + q->K - 1); - if (q->tail_biting) { - sr = 0; - for (i=frame_length - q->K + 1; iR;j++) { - output[q->R * i + j] = parity(sr & q->poly[j]); - } - } + if (q->tail_biting) { + sr = 0; + for (i=frame_length - q->K + 1; iR;j++) { + output[q->R * i + j] = parity(sr & q->poly[j]); + } + } - return q->R*len; + return q->R*len; } int convcoder_initialize(convcoder_hl* h) { - return 0; + return 0; } int convcoder_work(convcoder_hl* hl) { - hl->obj.K = hl->ctrl_in.constraint_length; - hl->obj.R = hl->ctrl_in.rate; - hl->obj.poly[0] = hl->ctrl_in.generator_0; - hl->obj.poly[1] = hl->ctrl_in.generator_1; - hl->obj.poly[2] = hl->ctrl_in.generator_2; - hl->obj.tail_biting = hl->ctrl_in.tail_bitting?true:false; - hl->out_len = convcoder_encode(&hl->obj, hl->input, hl->output, hl->in_len); - return 0; + hl->obj.K = hl->ctrl_in.constraint_length; + hl->obj.R = hl->ctrl_in.rate; + hl->obj.poly[0] = hl->ctrl_in.generator_0; + hl->obj.poly[1] = hl->ctrl_in.generator_1; + hl->obj.poly[2] = hl->ctrl_in.generator_2; + hl->obj.tail_biting = hl->ctrl_in.tail_bitting?true:false; + hl->out_len = convcoder_encode(&hl->obj, hl->input, hl->output, hl->in_len); + return 0; } int convcoder_stop(convcoder_hl* h) { - return 0; + return 0; } diff --git a/lte/lib/fec/src/crc.c b/lte/lib/fec/src/crc.c index e2de27c4f..f64325b75 100644 --- a/lte/lib/fec/src/crc.c +++ b/lte/lib/fec/src/crc.c @@ -34,121 +34,121 @@ void gen_crc_table(crc_t *h) { - int i, j, ord = (h->order - 8); - unsigned long bit, crc; - - for (i = 0; i < 256; i++) { - crc = ((unsigned long) i) << ord; - for (j = 0; j < 8; j++) { - bit = crc & h->crchighbit; - crc <<= 1; - if (bit) - crc ^= h->polynom; - } - h->table[i] = crc & h->crcmask; - } + int i, j, ord = (h->order - 8); + unsigned long bit, crc; + + for (i = 0; i < 256; i++) { + crc = ((unsigned long) i) << ord; + for (j = 0; j < 8; j++) { + bit = crc & h->crchighbit; + crc <<= 1; + if (bit) + crc ^= h->polynom; + } + h->table[i] = crc & h->crcmask; + } } unsigned long crctable(crc_t *h) { - // Polynom order 8, 16, 24 or 32 only. - int ord = h->order - 8; - unsigned long crc = h->crcinit; - unsigned char byte = h->byte; + // Polynom order 8, 16, 24 or 32 only. + int ord = h->order - 8; + unsigned long crc = h->crcinit; + unsigned char byte = h->byte; - crc = (crc << 8) ^ h->table[((crc >> (ord)) & 0xff) ^ byte]; - h->crcinit = crc; - return (crc & h->crcmask); + crc = (crc << 8) ^ h->table[((crc >> (ord)) & 0xff) ^ byte]; + h->crcinit = crc; + return (crc & h->crcmask); } unsigned long reversecrcbit(unsigned int crc, int nbits, crc_t *h) { - unsigned long m, rmask = 0x1; + unsigned long m, rmask = 0x1; - for (m = 0; m < nbits; m++) { - if ((rmask & crc) == 0x01) - crc = (crc ^ h->polynom) >> 1; - else - crc = crc >> 1; - } - return (crc & h->crcmask); + for (m = 0; m < nbits; m++) { + if ((rmask & crc) == 0x01) + crc = (crc ^ h->polynom) >> 1; + else + crc = crc >> 1; + } + return (crc & h->crcmask); } int crc_set_init(crc_t *crc_par, unsigned long crc_init_value) { - crc_par->crcinit = crc_init_value; - if (crc_par->crcinit != (crc_par->crcinit & crc_par->crcmask)) { - printf("ERROR, invalid crcinit in crc_set_init().\n"); - return -1; - } - return 0; + crc_par->crcinit = crc_init_value; + if (crc_par->crcinit != (crc_par->crcinit & crc_par->crcmask)) { + printf("ERROR, invalid crcinit in crc_set_init().\n"); + return -1; + } + return 0; } int crc_init(crc_t *h, unsigned int crc_poly, int crc_order) { - // Set crc working default parameters - h->polynom = crc_poly; - h->order = crc_order; - h->crcinit = 0x00000000; + // Set crc working default parameters + h->polynom = crc_poly; + h->order = crc_order; + h->crcinit = 0x00000000; - // Compute bit masks for whole CRC and CRC high bit - h->crcmask = ((((unsigned long) 1 << (h->order - 1)) - 1) << 1) - | 1; - h->crchighbit = (unsigned long) 1 << (h->order - 1); + // Compute bit masks for whole CRC and CRC high bit + h->crcmask = ((((unsigned long) 1 << (h->order - 1)) - 1) << 1) + | 1; + h->crchighbit = (unsigned long) 1 << (h->order - 1); - // check parameters - if (h->order % 8 != 0) { - fprintf(stderr, "ERROR, invalid order=%d, it must be 8, 16, 24 or 32.\n", - h->order); - return -1; - } + // check parameters + if (h->order % 8 != 0) { + fprintf(stderr, "ERROR, invalid order=%d, it must be 8, 16, 24 or 32.\n", + h->order); + return -1; + } - if (crc_set_init(h, h->crcinit)) { - fprintf(stderr, "Error setting CRC init word\n"); - return -1; - } + if (crc_set_init(h, h->crcinit)) { + fprintf(stderr, "Error setting CRC init word\n"); + return -1; + } - // generate lookup table - gen_crc_table(h); + // generate lookup table + gen_crc_table(h); - return 0; + return 0; } unsigned int crc_checksum(crc_t *h, char *data, int len) { - int i, k, len8, res8, a = 0; - unsigned int crc = 0; - char *pter; - - crc_set_init(h, 0); - - // Pack bits into bytes - len8 = (len >> 3); - res8 = (len - (len8 << 3)); - if (res8 > 0) { - a = 1; - } - - // Calculate CRC - for (i = 0; i < len8 + a; i++) { - pter = (char *) (data + 8 * i); - if (i == len8) { - h->byte = 0x00; - for (k = 0; k < res8; k++) { - h->byte |= ((unsigned char) *(pter + k)) << (7 - k); - } - } else { - h->byte = (unsigned char) (unpack_bits(&pter, 8) & 0xFF); - } - crc = crctable(h); - } - - // Reverse CRC res8 positions - if (a == 1) { - crc = reversecrcbit(crc, 8 - res8, h); - } - - //Return CRC value - return crc; + int i, k, len8, res8, a = 0; + unsigned int crc = 0; + char *pter; + + crc_set_init(h, 0); + + // Pack bits into bytes + len8 = (len >> 3); + res8 = (len - (len8 << 3)); + if (res8 > 0) { + a = 1; + } + + // Calculate CRC + for (i = 0; i < len8 + a; i++) { + pter = (char *) (data + 8 * i); + if (i == len8) { + h->byte = 0x00; + for (k = 0; k < res8; k++) { + h->byte |= ((unsigned char) *(pter + k)) << (7 - k); + } + } else { + h->byte = (unsigned char) (unpack_bits(&pter, 8) & 0xFF); + } + crc = crctable(h); + } + + // Reverse CRC res8 positions + if (a == 1) { + crc = reversecrcbit(crc, 8 - res8, h); + } + + //Return CRC value + return crc; } @@ -156,10 +156,10 @@ unsigned int crc_checksum(crc_t *h, char *data, int len) { * The buffer data must be len + crc_order bytes */ void crc_attach(crc_t *h, char *data, int len) { - unsigned int checksum = crc_checksum(h, data, len); + unsigned int checksum = crc_checksum(h, data, len); - // Add CRC - char *ptr = &data[len]; - pack_bits(checksum, &ptr, h->order); + // Add CRC + char *ptr = &data[len]; + pack_bits(checksum, &ptr, h->order); } diff --git a/lte/lib/fec/src/rm_conv.c b/lte/lib/fec/src/rm_conv.c index 66afbd0a4..2e8a2653e 100644 --- a/lte/lib/fec/src/rm_conv.c +++ b/lte/lib/fec/src/rm_conv.c @@ -35,58 +35,58 @@ #define RATE 3 unsigned char RM_CONV_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 }; + { 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_CONV_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 }; + 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, int in_len, char *output, int out_len) { - char tmp[RATE * NCOLS * NROWS_MAX]; - int nrows, ndummy, K_p; - - int i, j, k, s; - - 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); - return -1; - } - K_p = nrows * NCOLS; - ndummy = K_p - in_len / RATE; - if (ndummy < 0) { - ndummy = 0; - } - /* Sub-block interleaver 5.1.4.2.1 */ - k=0; - for (s = 0; s < 3; s++) { - for (j = 0; j < NCOLS; j++) { - for (i = 0; i < nrows; i++) { + char tmp[RATE * NCOLS * NROWS_MAX]; + int nrows, ndummy, K_p; + + int i, j, k, s; + + 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); + return -1; + } + K_p = nrows * NCOLS; + ndummy = K_p - in_len / RATE; + if (ndummy < 0) { + ndummy = 0; + } + /* Sub-block interleaver 5.1.4.2.1 */ + k=0; + for (s = 0; s < 3; s++) { + for (j = 0; j < NCOLS; j++) { + for (i = 0; i < nrows; i++) { if (i*NCOLS + RM_CONV_PERM_TC[j] < ndummy) { - tmp[k] = TX_NULL; - } else { + tmp[k] = TX_NULL; + } else { tmp[k] = input[(i*NCOLS + RM_CONV_PERM_TC[j]-ndummy)*3+s]; - } - k++; - } - } - } - /* Bit collection, selection and transmission 5.1.4.2.2 */ - k = 0; - j = 0; - while (k < out_len) { - if (tmp[j] != TX_NULL) { - output[k] = tmp[j]; - k++; - } - j++; - if (j == RATE * K_p) { - j = 0; - } - } - return 0; + } + k++; + } + } + } + /* Bit collection, selection and transmission 5.1.4.2.2 */ + k = 0; + j = 0; + while (k < out_len) { + if (tmp[j] != TX_NULL) { + output[k] = tmp[j]; + k++; + } + j++; + if (j == RATE * K_p) { + j = 0; + } + } + return 0; } @@ -95,87 +95,87 @@ 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) { - int nrows, ndummy, K_p; - int i, j, k; - int d_i, d_j; + int nrows, ndummy, K_p; + int i, j, k; + int d_i, d_j; - float tmp[RATE * NCOLS * NROWS_MAX]; + float tmp[RATE * NCOLS * NROWS_MAX]; - 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); - return -1; - } - K_p = nrows * NCOLS; + 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); + return -1; + } + K_p = nrows * NCOLS; - ndummy = K_p - out_len / RATE; - if (ndummy < 0) { - ndummy = 0; - } + ndummy = K_p - out_len / RATE; + if (ndummy < 0) { + ndummy = 0; + } - for (i = 0; i < RATE * K_p; i++) { - tmp[i] = RX_NULL; - } + for (i = 0; i < RATE * K_p; i++) { + tmp[i] = RX_NULL; + } - /* Undo bit collection. Account for dummy bits */ - k = 0; - j = 0; - while (k < in_len) { - d_i = (j % K_p) / nrows; - d_j = (j % K_p) % nrows; + /* Undo bit collection. Account for dummy bits */ + k = 0; + j = 0; + while (k < in_len) { + d_i = (j % K_p) / nrows; + d_j = (j % K_p) % nrows; if (d_j * NCOLS + RM_CONV_PERM_TC[d_i] >= ndummy) { - if (tmp[j] == RX_NULL) { - tmp[j] = input[k]; - } else if (input[k] != RX_NULL) { - tmp[j] += input[k]; /* soft combine LLRs */ - } - k++; - } - j++; - if (j == RATE * K_p) { - j = 0; - } - } - - /* interleaving and bit selection */ - for (i = 0; i < out_len / RATE; i++) { - d_i = (i + ndummy) / NCOLS; - d_j = (i + ndummy) % NCOLS; - for (j = 0; j < RATE; j++) { + if (tmp[j] == RX_NULL) { + tmp[j] = input[k]; + } else if (input[k] != RX_NULL) { + tmp[j] += input[k]; /* soft combine LLRs */ + } + k++; + } + j++; + if (j == RATE * K_p) { + j = 0; + } + } + + /* interleaving and bit selection */ + for (i = 0; i < out_len / RATE; i++) { + d_i = (i + ndummy) / NCOLS; + d_j = (i + ndummy) % NCOLS; + for (j = 0; j < RATE; j++) { float o = tmp[K_p * j + RM_CONV_PERM_TC_INV[d_j] * nrows - + d_i]; - if (o != RX_NULL) { - output[i * RATE + j] = o; - } else { - output[i * RATE + j] = 0; - } - } - } - return 0; + + d_i]; + if (o != RX_NULL) { + output[i * RATE + j] = o; + } else { + output[i * RATE + j] = 0; + } + } + } + return 0; } /** High-level API */ int rm_conv_initialize(rm_conv_hl* h) { - return 0; + return 0; } /** This function can be called in a subframe (1ms) basis */ int rm_conv_work(rm_conv_hl* hl) { - if (hl->init.direction) { - //rm_conv_tx(hl->input, hl->output, hl->in_len, hl->ctrl_in.S); - hl->out_len = hl->ctrl_in.S; - } else { - rm_conv_rx(hl->input, hl->output, hl->in_len, hl->ctrl_in.E); - hl->out_len = hl->ctrl_in.E; - } - return 0; + if (hl->init.direction) { + //rm_conv_tx(hl->input, hl->output, hl->in_len, hl->ctrl_in.S); + hl->out_len = hl->ctrl_in.S; + } else { + rm_conv_rx(hl->input, hl->output, hl->in_len, hl->ctrl_in.E); + hl->out_len = hl->ctrl_in.E; + } + return 0; } int rm_conv_stop(rm_conv_hl* hl) { - return 0; + return 0; } diff --git a/lte/lib/fec/src/rm_turbo.c b/lte/lib/fec/src/rm_turbo.c index d057eb9df..5c7acd792 100644 --- a/lte/lib/fec/src/rm_turbo.c +++ b/lte/lib/fec/src/rm_turbo.c @@ -38,28 +38,28 @@ #define RATE 3 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 }; + { 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 }; 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; + 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); - } + if (q->buffer) { + free(q->buffer); + } } /* Turbo Code Rate Matching. @@ -69,71 +69,71 @@ 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) { - char *tmp = (char*) q->buffer; - int nrows, ndummy, K_p; - - int i, j, k, s, kidx, N_cb, k0; - - nrows = (int) (in_len / RATE - 1) / NCOLS + 1; - 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; - } - - ndummy = K_p - in_len / RATE; - if (ndummy < 0) { - ndummy = 0; - } - - /* Sub-block interleaver (5.1.4.1.1) and bit collection */ - k = 0; - for (s = 0; s < 2; s++) { - for (j = 0; j < NCOLS; j++) { - for (i = 0; i < nrows; i++) { - if (s == 0) { - kidx = k%K_p; - } else { - 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++; - } - } - } - - // 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[(k0 + j) % N_cb] != TX_NULL) { - output[k] = tmp[(k0 + j) % N_cb]; - k++; - } - j++; - } - return 0; + char *tmp = (char*) q->buffer; + int nrows, ndummy, K_p; + + int i, j, k, s, kidx, N_cb, k0; + + nrows = (int) (in_len / RATE - 1) / NCOLS + 1; + 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; + } + + ndummy = K_p - in_len / RATE; + if (ndummy < 0) { + ndummy = 0; + } + + /* Sub-block interleaver (5.1.4.1.1) and bit collection */ + k = 0; + for (s = 0; s < 2; s++) { + for (j = 0; j < NCOLS; j++) { + for (i = 0; i < nrows; i++) { + if (s == 0) { + kidx = k%K_p; + } else { + 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++; + } + } + } + + // 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[(k0 + j) % N_cb] != TX_NULL) { + output[k] = tmp[(k0 + j) % N_cb]; + k++; + } + j++; + } + return 0; } /* Undoes Turbo Code Rate Matching. @@ -141,122 +141,122 @@ int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output, int out_le */ 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, k0, N_cb, jp, kidx; - int i, j, k; - int d_i, d_j; - bool isdummy; - - float *tmp = (float*) q->buffer; - - nrows = (int) (out_len / RATE - 1) / NCOLS + 1; - 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; - } - - ndummy = K_p - out_len / RATE; - if (ndummy < 0) { - ndummy = 0; - } - - for (i = 0; i < RATE * K_p; i++) { - tmp[i] = RX_NULL; - } - - /* 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) { - jp = (k0 + j) % N_cb; - - 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[jp] += input[k]; /* soft combine LLRs */ - } - k++; - } - j++; - } - - /* interleaving and bit selection */ - for (i = 0; i < out_len / RATE; i++) { - d_i = (i + ndummy) / NCOLS; - d_j = (i + ndummy) % NCOLS; - for (j = 0; j < RATE; j++) { - 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 { - output[i * RATE + j] = 0; - } - } - } - return 0; + int nrows, ndummy, K_p, k0, N_cb, jp, kidx; + int i, j, k; + int d_i, d_j; + bool isdummy; + + float *tmp = (float*) q->buffer; + + nrows = (int) (out_len / RATE - 1) / NCOLS + 1; + 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; + } + + ndummy = K_p - out_len / RATE; + if (ndummy < 0) { + ndummy = 0; + } + + for (i = 0; i < RATE * K_p; i++) { + tmp[i] = RX_NULL; + } + + /* 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) { + jp = (k0 + j) % N_cb; + + 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[jp] += input[k]; /* soft combine LLRs */ + } + k++; + } + j++; + } + + /* interleaving and bit selection */ + for (i = 0; i < out_len / RATE; i++) { + d_i = (i + ndummy) / NCOLS; + d_j = (i + ndummy) % NCOLS; + for (j = 0; j < RATE; j++) { + 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 { + output[i * RATE + j] = 0; + } + } + } + return 0; } /** High-level API */ int rm_turbo_initialize(rm_turbo_hl* h) { - return rm_turbo_init(&h->q, 7000); + 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->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; + if (hl->init.direction) { + 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; + rm_turbo_free(&hl->q); + return 0; } diff --git a/lte/lib/fec/src/tc_interl_lte.c b/lte/lib/fec/src/tc_interl_lte.c index 1db75cf92..bfaf4232c 100644 --- a/lte/lib/fec/src/tc_interl_lte.c +++ b/lte/lib/fec/src/tc_interl_lte.c @@ -40,68 +40,68 @@ ************************************************/ const int f1_list[NOF_TC_CB_SIZES] = { 3, 7, 19, 7, 7, 11, 5, 11, 7, 41, 103, 15, 9, 17, - 9, 21, 101, 21, 57, 23, 13, 27, 11, 27, 85, 29, 33, 15, 17, 33, 103, 19, - 19, 37, 19, 21, 21, 115, 193, 21, 133, 81, 45, 23, 243, 151, 155, 25, - 51, 47, 91, 29, 29, 247, 29, 89, 91, 157, 55, 31, 17, 35, 227, 65, 19, - 37, 41, 39, 185, 43, 21, 155, 79, 139, 23, 217, 25, 17, 127, 25, 239, - 17, 137, 215, 29, 15, 147, 29, 59, 65, 55, 31, 17, 171, 67, 35, 19, 39, - 19, 199, 21, 211, 21, 43, 149, 45, 49, 71, 13, 17, 25, 183, 55, 127, 27, - 29, 29, 57, 45, 31, 59, 185, 113, 31, 17, 171, 209, 253, 367, 265, 181, - 39, 27, 127, 143, 43, 29, 45, 157, 47, 13, 111, 443, 51, 51, 451, 257, - 57, 313, 271, 179, 331, 363, 375, 127, 31, 33, 43, 33, 477, 35, 233, - 357, 337, 37, 71, 71, 37, 39, 127, 39, 39, 31, 113, 41, 251, 43, 21, 43, - 45, 45, 161, 89, 323, 47, 23, 47, 263 }; + 9, 21, 101, 21, 57, 23, 13, 27, 11, 27, 85, 29, 33, 15, 17, 33, 103, 19, + 19, 37, 19, 21, 21, 115, 193, 21, 133, 81, 45, 23, 243, 151, 155, 25, + 51, 47, 91, 29, 29, 247, 29, 89, 91, 157, 55, 31, 17, 35, 227, 65, 19, + 37, 41, 39, 185, 43, 21, 155, 79, 139, 23, 217, 25, 17, 127, 25, 239, + 17, 137, 215, 29, 15, 147, 29, 59, 65, 55, 31, 17, 171, 67, 35, 19, 39, + 19, 199, 21, 211, 21, 43, 149, 45, 49, 71, 13, 17, 25, 183, 55, 127, 27, + 29, 29, 57, 45, 31, 59, 185, 113, 31, 17, 171, 209, 253, 367, 265, 181, + 39, 27, 127, 143, 43, 29, 45, 157, 47, 13, 111, 443, 51, 51, 451, 257, + 57, 313, 271, 179, 331, 363, 375, 127, 31, 33, 43, 33, 477, 35, 233, + 357, 337, 37, 71, 71, 37, 39, 127, 39, 39, 31, 113, 41, 251, 43, 21, 43, + 45, 45, 161, 89, 323, 47, 23, 47, 263 }; const int f2_list[NOF_TC_CB_SIZES] = { 10, 12, 42, 16, 18, 20, 22, 24, 26, 84, 90, 32, - 34, 108, 38, 120, 84, 44, 46, 48, 50, 52, 36, 56, 58, 60, 62, 32, 198, - 68, 210, 36, 74, 76, 78, 120, 82, 84, 86, 44, 90, 46, 94, 48, 98, 40, - 102, 52, 106, 72, 110, 168, 114, 58, 118, 180, 122, 62, 84, 64, 66, 68, - 420, 96, 74, 76, 234, 80, 82, 252, 86, 44, 120, 92, 94, 48, 98, 80, 102, - 52, 106, 48, 110, 112, 114, 58, 118, 60, 122, 124, 84, 64, 66, 204, 140, - 72, 74, 76, 78, 240, 82, 252, 86, 88, 60, 92, 846, 48, 28, 80, 102, 104, - 954, 96, 110, 112, 114, 116, 354, 120, 610, 124, 420, 64, 66, 136, 420, - 216, 444, 456, 468, 80, 164, 504, 172, 88, 300, 92, 188, 96, 28, 240, - 204, 104, 212, 192, 220, 336, 228, 232, 236, 120, 244, 248, 168, 64, - 130, 264, 134, 408, 138, 280, 142, 480, 146, 444, 120, 152, 462, 234, - 158, 80, 96, 902, 166, 336, 170, 86, 174, 176, 178, 120, 182, 184, 186, - 94, 190, 480 }; + 34, 108, 38, 120, 84, 44, 46, 48, 50, 52, 36, 56, 58, 60, 62, 32, 198, + 68, 210, 36, 74, 76, 78, 120, 82, 84, 86, 44, 90, 46, 94, 48, 98, 40, + 102, 52, 106, 72, 110, 168, 114, 58, 118, 180, 122, 62, 84, 64, 66, 68, + 420, 96, 74, 76, 234, 80, 82, 252, 86, 44, 120, 92, 94, 48, 98, 80, 102, + 52, 106, 48, 110, 112, 114, 58, 118, 60, 122, 124, 84, 64, 66, 204, 140, + 72, 74, 76, 78, 240, 82, 252, 86, 88, 60, 92, 846, 48, 28, 80, 102, 104, + 954, 96, 110, 112, 114, 116, 354, 120, 610, 124, 420, 64, 66, 136, 420, + 216, 444, 456, 468, 80, 164, 504, 172, 88, 300, 92, 188, 96, 28, 240, + 204, 104, 212, 192, 220, 336, 228, 232, 236, 120, 244, 248, 168, 64, + 130, 264, 134, 408, 138, 280, 142, 480, 146, 444, 120, 152, 462, 234, + 158, 80, 96, 902, 166, 336, 170, 86, 174, 176, 178, 120, 182, 184, 186, + 94, 190, 480 }; int tc_interl_LTE_init(tc_interl_t *h, int long_cb) { - int cb_table_idx, f1, f2; - unsigned long long i, j; - - cb_table_idx = lte_find_cb_index(long_cb); - if (cb_table_idx == -1) { - fprintf(stderr, "Can't find long_cb=%d in valid TC CB table\n", long_cb); - return -1; - } - - h->forward = h->reverse = NULL; - h->forward = malloc(sizeof(int) * (long_cb)); - if (!h->forward) { - return -1; - } - h->reverse = malloc(sizeof(int) * (long_cb)); - if (!h->reverse) { - perror("malloc"); - free(h->forward); - h->forward = h->reverse = NULL; - return -1; - } - - f1 = f1_list[cb_table_idx]; - f2 = f2_list[cb_table_idx]; - - DEBUG("table_idx: %d, f1: %d, f2: %d\n", cb_table_idx, f1, f2); - - h->forward[0] = 0; - h->reverse[0] = 0; - for (i = 1; i < long_cb; i++) { - j = (f1*i + f2*i*i) % (long_cb); - h->forward[i] = j; - h->reverse[j] = i; - } - return 0; + int cb_table_idx, f1, f2; + unsigned long long i, j; + + cb_table_idx = lte_find_cb_index(long_cb); + if (cb_table_idx == -1) { + fprintf(stderr, "Can't find long_cb=%d in valid TC CB table\n", long_cb); + return -1; + } + + h->forward = h->reverse = NULL; + h->forward = malloc(sizeof(int) * (long_cb)); + if (!h->forward) { + return -1; + } + h->reverse = malloc(sizeof(int) * (long_cb)); + if (!h->reverse) { + perror("malloc"); + free(h->forward); + h->forward = h->reverse = NULL; + return -1; + } + + f1 = f1_list[cb_table_idx]; + f2 = f2_list[cb_table_idx]; + + DEBUG("table_idx: %d, f1: %d, f2: %d\n", cb_table_idx, f1, f2); + + h->forward[0] = 0; + h->reverse[0] = 0; + for (i = 1; i < long_cb; i++) { + j = (f1*i + f2*i*i) % (long_cb); + h->forward[i] = j; + h->reverse[j] = i; + } + return 0; } diff --git a/lte/lib/fec/src/tc_interl_umts.c b/lte/lib/fec/src/tc_interl_umts.c index a71d2f0e0..635afd761 100644 --- a/lte/lib/fec/src/tc_interl_umts.c +++ b/lte/lib/fec/src/tc_interl_umts.c @@ -31,7 +31,7 @@ #include "lte/fec/tc_interl.h" #include "lte/fec/turbocoder.h" -#define TURBO_RATE 3 +#define TURBO_RATE 3 int mcd(int x, int y); @@ -41,217 +41,217 @@ int mcd(int x, int y); * ************************************************/ -#define MAX_ROWS 20 -#define MAX_COLS 256 +#define MAX_ROWS 20 +#define MAX_COLS 256 const unsigned short table_p[52] = { 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, - 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, - 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, - 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257 }; + 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, + 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, + 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257 }; const unsigned char table_v[52] = { 3, 2, 2, 3, 2, 5, 2, 3, 2, 6, 3, 5, 2, 2, 2, - 2, 7, 5, 3, 2, 3, 5, 2, 5, 2, 6, 3, 3, 2, 3, 2, 2, 6, 5, 2, 5, 2, 2, 2, - 19, 5, 2, 3, 2, 3, 2, 6, 3, 7, 7, 6, 3 }; + 2, 7, 5, 3, 2, 3, 5, 2, 5, 2, 6, 3, 3, 2, 3, 2, 2, 6, 5, 2, 5, 2, 2, 2, + 19, 5, 2, 3, 2, 3, 2, 6, 3, 7, 7, 6, 3 }; void tc_interl_free(tc_interl_t *h) { - if (h->forward) { - free(h->forward); - } - if (h->reverse) { - free(h->reverse); - } - h->forward = h->reverse = NULL; + if (h->forward) { + free(h->forward); + } + if (h->reverse) { + free(h->reverse); + } + h->forward = h->reverse = NULL; } int tc_interl_UMTS_init(tc_interl_t *h, int long_cb) { - int i, j; - int res, prim, aux; - int kp, k; - int *per, *desper; - unsigned char v; - unsigned short p; - unsigned short s[MAX_COLS], q[MAX_ROWS], r[MAX_ROWS], T[MAX_ROWS]; - unsigned short U[MAX_COLS * MAX_ROWS]; - int M_Rows, M_Cols, M_long; + int i, j; + int res, prim, aux; + int kp, k; + int *per, *desper; + unsigned char v; + unsigned short p; + unsigned short s[MAX_COLS], q[MAX_ROWS], r[MAX_ROWS], T[MAX_ROWS]; + unsigned short U[MAX_COLS * MAX_ROWS]; + int M_Rows, M_Cols, M_long; - h->forward = h->reverse = NULL; - h->forward = malloc(sizeof(int) * (long_cb)); - if (!h->forward) { - return -1; - } - h->reverse = malloc(sizeof(int) * (long_cb)); - if (!h->reverse) { - perror("malloc"); - free(h->forward); - h->forward = h->reverse = NULL; - return -1; - } - M_long = long_cb; + h->forward = h->reverse = NULL; + h->forward = malloc(sizeof(int) * (long_cb)); + if (!h->forward) { + return -1; + } + h->reverse = malloc(sizeof(int) * (long_cb)); + if (!h->reverse) { + perror("malloc"); + free(h->forward); + h->forward = h->reverse = NULL; + return -1; + } + M_long = long_cb; - /* Find R*/ - if ((40 <= M_long) && (M_long <= 159)) - M_Rows = 5; - else if (((160 <= M_long) && (M_long <= 200)) - || ((481 <= M_long) && (M_long <= 530))) - M_Rows = 10; - else - M_Rows = 20; + /* Find R*/ + if ((40 <= M_long) && (M_long <= 159)) + M_Rows = 5; + else if (((160 <= M_long) && (M_long <= 200)) + || ((481 <= M_long) && (M_long <= 530))) + M_Rows = 10; + else + M_Rows = 20; - /* Find p i v*/ - if ((481 <= M_long) && (M_long <= 530)) { - p = 53; - v = 2; - M_Cols = p; - } else { - i = 0; - do { - p = table_p[i]; - v = table_v[i]; - i++; - } while (M_long > (M_Rows * (p + 1))); + /* Find p i v*/ + if ((481 <= M_long) && (M_long <= 530)) { + p = 53; + v = 2; + M_Cols = p; + } else { + i = 0; + do { + p = table_p[i]; + v = table_v[i]; + i++; + } while (M_long > (M_Rows * (p + 1))); - } + } - /* Find C*/ - if ((M_long) <= (M_Rows) * ((p) - 1)) - M_Cols = (p) - 1; - else if (((M_Rows) * (p - 1) < M_long) && (M_long <= (M_Rows) * (p))) - M_Cols = p; - else if ((M_Rows) * (p) < M_long) - M_Cols = (p) + 1; + /* Find C*/ + if ((M_long) <= (M_Rows) * ((p) - 1)) + M_Cols = (p) - 1; + else if (((M_Rows) * (p - 1) < M_long) && (M_long <= (M_Rows) * (p))) + M_Cols = p; + else if ((M_Rows) * (p) < M_long) + M_Cols = (p) + 1; - q[0] = 1; - prim = 6; + q[0] = 1; + prim = 6; - for (i = 1; i < M_Rows; i++) { - do { - prim++; - res = mcd(prim, p - 1); - } while (res != 1); - q[i] = prim; - } + for (i = 1; i < M_Rows; i++) { + do { + prim++; + res = mcd(prim, p - 1); + } while (res != 1); + q[i] = prim; + } - s[0] = 1; - for (i = 1; i < p - 1; i++) { - s[i] = (v * s[i - 1]) % p; - } + s[0] = 1; + for (i = 1; i < p - 1; i++) { + s[i] = (v * s[i - 1]) % p; + } - if (M_long <= 159 && M_long >= 40) { - T[0] = 4; - T[1] = 3; - T[2] = 2; - T[3] = 1; - T[4] = 0; - } else if ((M_long <= 200 && M_long >= 160) - || (M_long <= 530 && M_long >= 481)) { - T[0] = 9; - T[1] = 8; - T[2] = 7; - T[3] = 6; - T[4] = 5; - T[5] = 4; - T[6] = 3; - T[7] = 2; - T[8] = 1; - T[9] = 0; - } else if ((M_long <= 2480 && M_long >= 2281) - || (M_long <= 3210 && M_long >= 3161)) { - T[0] = 19; - T[1] = 9; - T[2] = 14; - T[3] = 4; - T[4] = 0; - T[5] = 2; - T[6] = 5; - T[7] = 7; - T[8] = 12; - T[9] = 18; - T[10] = 16; - T[11] = 13; - T[12] = 17; - T[13] = 15; - T[14] = 3; - T[15] = 1; - T[16] = 6; - T[17] = 11; - T[18] = 8; - T[19] = 10; - } else { - T[0] = 19; - T[1] = 9; - T[2] = 14; - T[3] = 4; - T[4] = 0; - T[5] = 2; - T[6] = 5; - T[7] = 7; - T[8] = 12; - T[9] = 18; - T[10] = 10; - T[11] = 8; - T[12] = 13; - T[13] = 17; - T[14] = 3; - T[15] = 1; - T[16] = 16; - T[17] = 6; - T[18] = 15; - T[19] = 11; - } + if (M_long <= 159 && M_long >= 40) { + T[0] = 4; + T[1] = 3; + T[2] = 2; + T[3] = 1; + T[4] = 0; + } else if ((M_long <= 200 && M_long >= 160) + || (M_long <= 530 && M_long >= 481)) { + T[0] = 9; + T[1] = 8; + T[2] = 7; + T[3] = 6; + T[4] = 5; + T[5] = 4; + T[6] = 3; + T[7] = 2; + T[8] = 1; + T[9] = 0; + } else if ((M_long <= 2480 && M_long >= 2281) + || (M_long <= 3210 && M_long >= 3161)) { + T[0] = 19; + T[1] = 9; + T[2] = 14; + T[3] = 4; + T[4] = 0; + T[5] = 2; + T[6] = 5; + T[7] = 7; + T[8] = 12; + T[9] = 18; + T[10] = 16; + T[11] = 13; + T[12] = 17; + T[13] = 15; + T[14] = 3; + T[15] = 1; + T[16] = 6; + T[17] = 11; + T[18] = 8; + T[19] = 10; + } else { + T[0] = 19; + T[1] = 9; + T[2] = 14; + T[3] = 4; + T[4] = 0; + T[5] = 2; + T[6] = 5; + T[7] = 7; + T[8] = 12; + T[9] = 18; + T[10] = 10; + T[11] = 8; + T[12] = 13; + T[13] = 17; + T[14] = 3; + T[15] = 1; + T[16] = 16; + T[17] = 6; + T[18] = 15; + T[19] = 11; + } - for (i = 0; i < M_Rows; i++) { - r[T[i]] = q[i]; - } + for (i = 0; i < M_Rows; i++) { + r[T[i]] = q[i]; + } - for (i = 0; i < M_Rows; i++) { - for (j = 0; j < p - 1; j++) { - U[i * M_Cols + j] = s[(j * r[i]) % (p - 1)]; - if (M_Cols == (p - 1)) - U[i * M_Cols + j] -= 1; - } - } + for (i = 0; i < M_Rows; i++) { + for (j = 0; j < p - 1; j++) { + U[i * M_Cols + j] = s[(j * r[i]) % (p - 1)]; + if (M_Cols == (p - 1)) + U[i * M_Cols + j] -= 1; + } + } - if (M_Cols == p) { - for (i = 0; i < M_Rows; i++) - U[i * M_Cols + p - 1] = 0; - } else if (M_Cols == p + 1) { - for (i = 0; i < M_Rows; i++) { - U[i * M_Cols + p - 1] = 0; - U[i * M_Cols + p] = p; - } - if (M_long == M_Cols * M_Rows) { - aux = U[(M_Rows - 1) * M_Cols + p]; - U[(M_Rows - 1) * M_Cols + p] = U[(M_Rows - 1) * M_Cols + 0]; - U[(M_Rows - 1) * M_Cols + 0] = aux; - } - } + if (M_Cols == p) { + for (i = 0; i < M_Rows; i++) + U[i * M_Cols + p - 1] = 0; + } else if (M_Cols == p + 1) { + for (i = 0; i < M_Rows; i++) { + U[i * M_Cols + p - 1] = 0; + U[i * M_Cols + p] = p; + } + if (M_long == M_Cols * M_Rows) { + aux = U[(M_Rows - 1) * M_Cols + p]; + U[(M_Rows - 1) * M_Cols + p] = U[(M_Rows - 1) * M_Cols + 0]; + U[(M_Rows - 1) * M_Cols + 0] = aux; + } + } - per = h->forward; - desper = h->reverse; + per = h->forward; + desper = h->reverse; - k = 0; - for (j = 0; j < M_Cols; j++) { - for (i = 0; i < M_Rows; i++) { - kp = T[i] * M_Cols + U[i * M_Cols + j]; - if (kp < M_long) { - desper[kp] = k; - per[k] = kp; - k++; - } - } - } + k = 0; + for (j = 0; j < M_Cols; j++) { + for (i = 0; i < M_Rows; i++) { + kp = T[i] * M_Cols + U[i * M_Cols + j]; + if (kp < M_long) { + desper[kp] = k; + per[k] = kp; + k++; + } + } + } - return 0; + return 0; } int mcd(int x, int y) { - int r = 1; + int r = 1; - while (r) { - r = x % y; - x = y; - y = r; - } - return x; + while (r) { + r = x % y; + x = y; + y = r; + } + return x; } diff --git a/lte/lib/fec/src/turbocoder.c b/lte/lib/fec/src/turbocoder.c index 4ff72df26..509cef252 100644 --- a/lte/lib/fec/src/turbocoder.c +++ b/lte/lib/fec/src/turbocoder.c @@ -33,102 +33,102 @@ int tcod_init(tcod_t *h, int long_cb) { - if (tc_interl_LTE_init(&h->interl, long_cb)) { - return -1; - } - h->long_cb = long_cb; - return 0; + if (tc_interl_LTE_init(&h->interl, long_cb)) { + return -1; + } + h->long_cb = long_cb; + return 0; } void tcod_free(tcod_t *h) { - tc_interl_free(&h->interl); - h->long_cb = 0; + tc_interl_free(&h->interl); + h->long_cb = 0; } void tcod_encode(tcod_t *h, char *input, char *output) { - - char reg1_0,reg1_1,reg1_2, reg2_0,reg2_1,reg2_2; - int i,k=0,j; - char bit; - char in,out; - int *per; + + char reg1_0,reg1_1,reg1_2, reg2_0,reg2_1,reg2_2; + int i,k=0,j; + char bit; + char in,out; + int *per; - per=h->interl.forward; - - reg1_0=0; - reg1_1=0; - reg1_2=0; - - reg2_0=0; - reg2_1=0; - reg2_2=0; - - k=0; - for (i=0;ilong_cb;i++) { - bit=input[i]; - - output[k]=bit; - k++; - - in=bit^(reg1_2^reg1_1); - out=reg1_2^(reg1_0^in); + per=h->interl.forward; + + reg1_0=0; + reg1_1=0; + reg1_2=0; + + reg2_0=0; + reg2_1=0; + reg2_2=0; + + k=0; + for (i=0;ilong_cb;i++) { + bit=input[i]; + + output[k]=bit; + k++; + + in=bit^(reg1_2^reg1_1); + out=reg1_2^(reg1_0^in); - reg1_2=reg1_1; - reg1_1=reg1_0; - reg1_0=in; - - output[k]=out; - k++; - - bit=input[per[i]]; - - in=bit^(reg2_2^reg2_1); - out=reg2_2^(reg2_0^in); + reg1_2=reg1_1; + reg1_1=reg1_0; + reg1_0=in; + + output[k]=out; + k++; + + bit=input[per[i]]; + + in=bit^(reg2_2^reg2_1); + out=reg2_2^(reg2_0^in); - reg2_2=reg2_1; - reg2_1=reg2_0; - reg2_0=in; - - output[k]=out; - k++; - } - - k=3*h->long_cb; - - /* TAILING CODER #1 */ - for (j=0;jlong_cb; + + /* TAILING CODER #1 */ + for (j=0;jlong_cb + RATE; - llr_t *beta = s->beta; - int i; - - for (i=0;i<8;i++) { - old[i] = beta[8 * (end) + i]; - } - - for (k = end - 1; k >= 0; k--) { - x = input[k]; - y = parity[k]; - - xy = x + y; - - m_b[0] = old[4] + xy; - m_b[1] = old[4]; - m_b[2] = old[5] + y; - m_b[3] = old[5] + x; - m_b[4] = old[6] + x; - m_b[5] = old[6] + y; - m_b[6] = old[7]; - m_b[7] = old[7] + xy; - - new[0] = old[0]; - new[1] = old[0] + xy; - new[2] = old[1] + x; - new[3] = old[1] + y; - new[4] = old[2] + y; - new[5] = old[2] + x; - new[6] = old[3] + xy; - new[7] = old[3]; - - for (i=0;i<8;i++) { - if (m_b[i] > new[i]) - new[i] = m_b[i]; - beta[8 * k + i] = new[i]; - old[i] = new[i]; - } - } + llr_t m_b[8], new[8], old[8]; + llr_t x, y, xy; + int k; + int end = s->long_cb + RATE; + llr_t *beta = s->beta; + int i; + + for (i=0;i<8;i++) { + old[i] = beta[8 * (end) + i]; + } + + for (k = end - 1; k >= 0; k--) { + x = input[k]; + y = parity[k]; + + xy = x + y; + + m_b[0] = old[4] + xy; + m_b[1] = old[4]; + m_b[2] = old[5] + y; + m_b[3] = old[5] + x; + m_b[4] = old[6] + x; + m_b[5] = old[6] + y; + m_b[6] = old[7]; + m_b[7] = old[7] + xy; + + new[0] = old[0]; + new[1] = old[0] + xy; + new[2] = old[1] + x; + new[3] = old[1] + y; + new[4] = old[2] + y; + new[5] = old[2] + x; + new[6] = old[3] + xy; + new[7] = old[3]; + + for (i=0;i<8;i++) { + if (m_b[i] > new[i]) + new[i] = m_b[i]; + beta[8 * k + i] = new[i]; + old[i] = new[i]; + } + } } void map_gen_alpha(map_gen_t *s, llr_t *input, llr_t *parity, llr_t *output) { - llr_t m_b[8], new[8], old[8], max1[8], max0[8]; - llr_t m1, m0; - llr_t x, y, xy; - llr_t out; - int k; - int end = s->long_cb; - llr_t *beta = s->beta; - int i; - - old[0] = 0; - for (i=1;i<8;i++) { - old[i] = -INF; - } - - for (k = 1; k < end + 1; k++) { - x = input[k - 1]; - y = parity[k - 1]; - - xy = x + y; - - m_b[0] = old[0]; - m_b[1] = old[3] + y; - m_b[2] = old[4] + y; - m_b[3] = old[7]; - m_b[4] = old[1]; - m_b[5] = old[2] + y; - m_b[6] = old[5] + y; - m_b[7] = old[6]; - - new[0] = old[1] + xy; - new[1] = old[2] + x; - new[2] = old[5] + x; - new[3] = old[6] + xy; - new[4] = old[0] + xy; - new[5] = old[3] + x; - new[6] = old[4] + x; - new[7] = old[7] + xy; - - for (i=0;i<8;i++) { - max0[i] = m_b[i] + beta[8 * k + i]; - max1[i] = new[i] + beta[8 * k + i]; - } - - m1 = max1[0]; - m0 = max0[0]; - - for (i=1;i<8;i++) { - if (max1[i] > m1) - m1 = max1[i]; - if (max0[i] > m0) - m0 = max0[i]; - } - - for (i=0;i<8;i++) { - if (m_b[i] > new[i]) - new[i] = m_b[i]; - old[i] = new[i]; - } - - out = m1 - m0; - output[k - 1] = out; - } + llr_t m_b[8], new[8], old[8], max1[8], max0[8]; + llr_t m1, m0; + llr_t x, y, xy; + llr_t out; + int k; + int end = s->long_cb; + llr_t *beta = s->beta; + int i; + + old[0] = 0; + for (i=1;i<8;i++) { + old[i] = -INF; + } + + for (k = 1; k < end + 1; k++) { + x = input[k - 1]; + y = parity[k - 1]; + + xy = x + y; + + m_b[0] = old[0]; + m_b[1] = old[3] + y; + m_b[2] = old[4] + y; + m_b[3] = old[7]; + m_b[4] = old[1]; + m_b[5] = old[2] + y; + m_b[6] = old[5] + y; + m_b[7] = old[6]; + + new[0] = old[1] + xy; + new[1] = old[2] + x; + new[2] = old[5] + x; + new[3] = old[6] + xy; + new[4] = old[0] + xy; + new[5] = old[3] + x; + new[6] = old[4] + x; + new[7] = old[7] + xy; + + for (i=0;i<8;i++) { + max0[i] = m_b[i] + beta[8 * k + i]; + max1[i] = new[i] + beta[8 * k + i]; + } + + m1 = max1[0]; + m0 = max0[0]; + + for (i=1;i<8;i++) { + if (max1[i] > m1) + m1 = max1[i]; + if (max0[i] > m0) + m0 = max0[i]; + } + + for (i=0;i<8;i++) { + if (m_b[i] > new[i]) + new[i] = m_b[i]; + old[i] = new[i]; + } + + out = m1 - m0; + output[k - 1] = out; + } } int map_gen_init(map_gen_t *h, int long_cb) { - bzero(h, sizeof(map_gen_t)); - h->beta = malloc(sizeof(llr_t) * (long_cb + TOTALTAIL + 1)* NUMSTATES); - if (!h->beta) { - perror("malloc"); - return -1; - } - h->long_cb = long_cb; - return 0; + bzero(h, sizeof(map_gen_t)); + h->beta = malloc(sizeof(llr_t) * (long_cb + TOTALTAIL + 1)* NUMSTATES); + if (!h->beta) { + perror("malloc"); + return -1; + } + h->long_cb = long_cb; + return 0; } void map_gen_free(map_gen_t *h) { - if (h->beta) { - free(h->beta); - } - bzero(h, sizeof(map_gen_t)); + if (h->beta) { + free(h->beta); + } + bzero(h, sizeof(map_gen_t)); } void map_gen_dec(map_gen_t *h, llr_t *input, llr_t *parity, llr_t *output) { - int k; + int k; - h->beta[(h->long_cb + TAIL) * NUMSTATES] = 0; - for (k = 1; k < NUMSTATES; k++) - h->beta[(h->long_cb + TAIL) * NUMSTATES + k] = -INF; + h->beta[(h->long_cb + TAIL) * NUMSTATES] = 0; + for (k = 1; k < NUMSTATES; k++) + h->beta[(h->long_cb + TAIL) * NUMSTATES + k] = -INF; - map_gen_beta(h, input, parity); - map_gen_alpha(h, input, parity, output); + map_gen_beta(h, input, parity); + map_gen_alpha(h, input, parity, output); } @@ -165,135 +165,135 @@ void map_gen_dec(map_gen_t *h, llr_t *input, llr_t *parity, llr_t *output) { * ************************************************/ int tdec_init(tdec_t *h, int long_cb) { - int ret = -1; - bzero(h, sizeof(tdec_t)); - int len = long_cb + TOTALTAIL; - - h->llr1 = malloc(sizeof(llr_t) * len); - if (!h->llr1) { - perror("malloc"); - goto clean_and_exit; - } - h->llr2 = malloc(sizeof(llr_t) * len); - if (!h->llr2) { - perror("malloc"); - goto clean_and_exit; - } - h->w = malloc(sizeof(llr_t) * len); - if (!h->w) { - perror("malloc"); - goto clean_and_exit; - } - h->syst = malloc(sizeof(llr_t) * len); - if (!h->syst) { - perror("malloc"); - goto clean_and_exit; - } - h->parity = malloc(sizeof(llr_t) * len); - if (!h->parity) { - perror("malloc"); - goto clean_and_exit; - } - - if (map_gen_init(&h->dec, long_cb)) { - goto clean_and_exit; - } - - h->long_cb = long_cb; - - if (tc_interl_LTE_init(&h->interleaver, h->long_cb) < 0) { - goto clean_and_exit; - } - - ret = 0; + int ret = -1; + bzero(h, sizeof(tdec_t)); + int len = long_cb + TOTALTAIL; + + h->llr1 = malloc(sizeof(llr_t) * len); + if (!h->llr1) { + perror("malloc"); + goto clean_and_exit; + } + h->llr2 = malloc(sizeof(llr_t) * len); + if (!h->llr2) { + perror("malloc"); + goto clean_and_exit; + } + h->w = malloc(sizeof(llr_t) * len); + if (!h->w) { + perror("malloc"); + goto clean_and_exit; + } + h->syst = malloc(sizeof(llr_t) * len); + if (!h->syst) { + perror("malloc"); + goto clean_and_exit; + } + h->parity = malloc(sizeof(llr_t) * len); + if (!h->parity) { + perror("malloc"); + goto clean_and_exit; + } + + if (map_gen_init(&h->dec, long_cb)) { + goto clean_and_exit; + } + + h->long_cb = long_cb; + + if (tc_interl_LTE_init(&h->interleaver, h->long_cb) < 0) { + goto clean_and_exit; + } + + ret = 0; clean_and_exit: - if (ret == -1) { - tdec_free(h); - } - return ret; + if (ret == -1) { + tdec_free(h); + } + return ret; } void tdec_free(tdec_t *h) { - if (h->llr1) { - free(h->llr1); - } - if (h->llr2) { - free(h->llr2); - } - if (h->w) { - free(h->w); - } - if (h->syst) { - free(h->syst); - } - if (h->parity) { - free(h->parity); - } - - map_gen_free(&h->dec); - - tc_interl_free(&h->interleaver); - - bzero(h, sizeof(tdec_t)); + if (h->llr1) { + free(h->llr1); + } + if (h->llr2) { + free(h->llr2); + } + if (h->w) { + free(h->w); + } + if (h->syst) { + free(h->syst); + } + if (h->parity) { + free(h->parity); + } + + map_gen_free(&h->dec); + + tc_interl_free(&h->interleaver); + + bzero(h, sizeof(tdec_t)); } void tdec_iteration(tdec_t *h, llr_t *input) { - int i; - - // Prepare systematic and parity bits for MAP DEC #1 - for (i = 0; i < h->long_cb; i++) { - h->syst[i] = input[RATE * i] + h->w[i]; - h->parity[i] = input[RATE * i + 1]; - } - for (i=h->long_cb;ilong_cb+RATE;i++) { - h->syst[i] = input[RATE * h->long_cb + NINPUTS * (i - h->long_cb)]; - h->parity[i] = input[RATE * h->long_cb + NINPUTS * (i - h->long_cb) + 1]; - } - - // Run MAP DEC #1 - map_gen_dec(&h->dec, h->syst, h->parity, h->llr1); - - // Prepare systematic and parity bits for MAP DEC #1 - for (i = 0; i < h->long_cb; i++) { - h->syst[i] = h->llr1[h->interleaver.forward[i]] - h->w[h->interleaver.forward[i]]; - h->parity[i] = input[RATE * i + 2]; - } - for (i=h->long_cb;ilong_cb+RATE;i++) { - h->syst[i] = input[RATE * h->long_cb + NINPUTS * RATE + NINPUTS * (i - h->long_cb)]; - h->parity[i] = input[RATE * h->long_cb + NINPUTS * RATE + NINPUTS * (i - h->long_cb) + 1]; - } - - // Run MAP DEC #1 - map_gen_dec(&h->dec, h->syst, h->parity, h->llr2); - - // Update a-priori LLR from the last iteration - for (i = 0; i < h->long_cb; i++) { - h->w[i] += h->llr2[h->interleaver.reverse[i]] - h->llr1[i]; - } + int i; + + // Prepare systematic and parity bits for MAP DEC #1 + for (i = 0; i < h->long_cb; i++) { + h->syst[i] = input[RATE * i] + h->w[i]; + h->parity[i] = input[RATE * i + 1]; + } + for (i=h->long_cb;ilong_cb+RATE;i++) { + h->syst[i] = input[RATE * h->long_cb + NINPUTS * (i - h->long_cb)]; + h->parity[i] = input[RATE * h->long_cb + NINPUTS * (i - h->long_cb) + 1]; + } + + // Run MAP DEC #1 + map_gen_dec(&h->dec, h->syst, h->parity, h->llr1); + + // Prepare systematic and parity bits for MAP DEC #1 + for (i = 0; i < h->long_cb; i++) { + h->syst[i] = h->llr1[h->interleaver.forward[i]] - h->w[h->interleaver.forward[i]]; + h->parity[i] = input[RATE * i + 2]; + } + for (i=h->long_cb;ilong_cb+RATE;i++) { + h->syst[i] = input[RATE * h->long_cb + NINPUTS * RATE + NINPUTS * (i - h->long_cb)]; + h->parity[i] = input[RATE * h->long_cb + NINPUTS * RATE + NINPUTS * (i - h->long_cb) + 1]; + } + + // Run MAP DEC #1 + map_gen_dec(&h->dec, h->syst, h->parity, h->llr2); + + // Update a-priori LLR from the last iteration + for (i = 0; i < h->long_cb; i++) { + h->w[i] += h->llr2[h->interleaver.reverse[i]] - h->llr1[i]; + } } void tdec_reset(tdec_t *h) { - memset(h->w, 0, sizeof(llr_t) * h->long_cb); + memset(h->w, 0, sizeof(llr_t) * h->long_cb); } void tdec_decision(tdec_t *h, char *output) { - int i; - for (i = 0; i < h->long_cb; i++) { - output[i] = (h->llr2[h->interleaver.reverse[i]] > 0) ? 1 : 0; - } + int i; + for (i = 0; i < h->long_cb; i++) { + output[i] = (h->llr2[h->interleaver.reverse[i]] > 0) ? 1 : 0; + } } void tdec_run_all(tdec_t *h, llr_t *input, char *output, int nof_iterations) { - int iter = 0; + int iter = 0; - tdec_reset(h); + tdec_reset(h); - do { - tdec_iteration(h, input); - iter++; - } while (iter < nof_iterations); + do { + tdec_iteration(h, input); + iter++; + } while (iter < nof_iterations); - tdec_decision(h, output); + tdec_decision(h, output); } diff --git a/lte/lib/fec/src/viterbi.c b/lte/lib/fec/src/viterbi.c index 98bfe7289..dc47923c6 100644 --- a/lte/lib/fec/src/viterbi.c +++ b/lte/lib/fec/src/viterbi.c @@ -39,222 +39,222 @@ #define DEB 0 int decode37(void *o, unsigned char *symbols, char *data, int frame_length) { - viterbi_t *q = o; - int i; + viterbi_t *q = o; + int i; - int best_state; + int best_state; - if (frame_length > q->framebits) { - fprintf(stderr, "Initialized decoder for max frame length %d bits\n", - q->framebits); - return -1; - } + if (frame_length > q->framebits) { + fprintf(stderr, "Initialized decoder for max frame length %d bits\n", + q->framebits); + return -1; + } - /* Initialize Viterbi decoder */ - init_viterbi37_port(q->ptr, q->tail_biting ? -1 : 0); + /* Initialize Viterbi decoder */ + init_viterbi37_port(q->ptr, q->tail_biting ? -1 : 0); - /* Decode block */ - if (q->tail_biting) { - memcpy(q->tmp, symbols, 3 * frame_length * sizeof(char)); - for (i = 0; i < 3 * (q->K - 1); i++) { - q->tmp[i + 3 * frame_length] = q->tmp[i]; - } - } else { - q->tmp = symbols; - } + /* Decode block */ + if (q->tail_biting) { + memcpy(q->tmp, symbols, 3 * frame_length * sizeof(char)); + for (i = 0; i < 3 * (q->K - 1); i++) { + q->tmp[i + 3 * frame_length] = q->tmp[i]; + } + } else { + q->tmp = symbols; + } - update_viterbi37_blk_port(q->ptr, q->tmp, frame_length + q->K - 1, - q->tail_biting ? &best_state : NULL); + update_viterbi37_blk_port(q->ptr, q->tmp, frame_length + q->K - 1, + q->tail_biting ? &best_state : NULL); - /* Do Viterbi chainback */ - chainback_viterbi37_port(q->ptr, data, frame_length, - q->tail_biting ? best_state : 0); + /* Do Viterbi chainback */ + chainback_viterbi37_port(q->ptr, data, frame_length, + q->tail_biting ? best_state : 0); - return q->framebits; + return q->framebits; } int decode39(void *o, unsigned char *symbols, char *data, int frame_length) { - viterbi_t *q = o; + viterbi_t *q = o; - if (frame_length > q->framebits) { - fprintf(stderr, "Initialized decoder for max frame length %d bits\n", - q->framebits); - return -1; - } + if (frame_length > q->framebits) { + fprintf(stderr, "Initialized decoder for max frame length %d bits\n", + q->framebits); + return -1; + } - /* Initialize Viterbi decoder */ - init_viterbi39_port(q->ptr, 0); + /* Initialize Viterbi decoder */ + init_viterbi39_port(q->ptr, 0); - /* Decode block */ - update_viterbi39_blk_port(q->ptr, symbols, frame_length + q->K - 1); + /* Decode block */ + update_viterbi39_blk_port(q->ptr, symbols, frame_length + q->K - 1); - /* Do Viterbi chainback */ - chainback_viterbi39_port(q->ptr, data, frame_length, 0); + /* Do Viterbi chainback */ + chainback_viterbi39_port(q->ptr, data, frame_length, 0); - return q->framebits; + return q->framebits; } void free37(void *o) { - viterbi_t *q = o; - if (q->symbols_uc) { - free(q->symbols_uc); - } - if (q->tmp) { - free(q->tmp); - } - delete_viterbi37_port(q->ptr); + viterbi_t *q = o; + if (q->symbols_uc) { + free(q->symbols_uc); + } + if (q->tmp) { + free(q->tmp); + } + delete_viterbi37_port(q->ptr); } void free39(void *o) { - viterbi_t *q = o; - if (q->symbols_uc) { - free(q->symbols_uc); - } - delete_viterbi39_port(q->ptr); + viterbi_t *q = o; + if (q->symbols_uc) { + free(q->symbols_uc); + } + delete_viterbi39_port(q->ptr); } int init37(viterbi_t *q, int poly[3], int framebits, bool tail_biting) { - q->K = 7; - q->R = 3; - q->framebits = framebits; - q->tail_biting = tail_biting; - q->decode = decode37; - q->free = free37; - q->symbols_uc = malloc(3 * (q->framebits + q->K - 1) * sizeof(char)); - if (!q->symbols_uc) { - perror("malloc"); - return -1; - } - if (q->tail_biting) { - q->tmp = malloc(3 * (q->framebits + q->K - 1) * sizeof(char)); - if (!q->tmp) { - perror("malloc"); - free37(q); - return -1; - } - } else { - q->tmp = NULL; - } + q->K = 7; + q->R = 3; + q->framebits = framebits; + q->tail_biting = tail_biting; + q->decode = decode37; + q->free = free37; + q->symbols_uc = malloc(3 * (q->framebits + q->K - 1) * sizeof(char)); + if (!q->symbols_uc) { + perror("malloc"); + return -1; + } + if (q->tail_biting) { + q->tmp = malloc(3 * (q->framebits + q->K - 1) * sizeof(char)); + if (!q->tmp) { + perror("malloc"); + free37(q); + return -1; + } + } else { + q->tmp = NULL; + } - if ((q->ptr = create_viterbi37_port(poly, framebits)) == NULL) { - fprintf(stderr, "create_viterbi37 failed\n"); - free37(q); - return -1; - } else { - return 0; - } + if ((q->ptr = create_viterbi37_port(poly, framebits)) == NULL) { + fprintf(stderr, "create_viterbi37 failed\n"); + free37(q); + return -1; + } else { + return 0; + } } int init39(viterbi_t *q, int poly[3], int framebits, bool tail_biting) { - q->K = 9; - q->R = 3; - q->framebits = framebits; - q->tail_biting = tail_biting; - q->decode = decode39; - q->free = free39; - if (q->tail_biting) { - fprintf(stderr, - "Error: Tailbitting not supported in 1/3 K=9 decoder\n"); - return -1; - } - q->symbols_uc = malloc(3 * (q->framebits + q->K - 1) * sizeof(char)); - if (!q->symbols_uc) { - perror("malloc"); - return -1; - } - if ((q->ptr = create_viterbi39_port(poly, framebits)) == NULL) { - fprintf(stderr, "create_viterbi37 failed\n"); - free39(q); - return -1; - } else { - return 0; - } + q->K = 9; + q->R = 3; + q->framebits = framebits; + q->tail_biting = tail_biting; + q->decode = decode39; + q->free = free39; + if (q->tail_biting) { + fprintf(stderr, + "Error: Tailbitting not supported in 1/3 K=9 decoder\n"); + return -1; + } + q->symbols_uc = malloc(3 * (q->framebits + q->K - 1) * sizeof(char)); + if (!q->symbols_uc) { + perror("malloc"); + return -1; + } + if ((q->ptr = create_viterbi39_port(poly, framebits)) == NULL) { + fprintf(stderr, "create_viterbi37 failed\n"); + free39(q); + return -1; + } else { + return 0; + } } int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], - int max_frame_length, bool tail_bitting) { - switch (type) { - case viterbi_37: - return init37(q, poly, max_frame_length, tail_bitting); - case viterbi_39: - return init39(q, poly, max_frame_length, tail_bitting); - default: - fprintf(stderr, "Decoder not implemented\n"); - return -1; - } + int max_frame_length, bool tail_bitting) { + switch (type) { + case viterbi_37: + return init37(q, poly, max_frame_length, tail_bitting); + case viterbi_39: + return init39(q, poly, max_frame_length, tail_bitting); + default: + fprintf(stderr, "Decoder not implemented\n"); + return -1; + } } void viterbi_free(viterbi_t *q) { - q->free(q); + q->free(q); } /* symbols are real-valued */ int viterbi_decode_f(viterbi_t *q, float *symbols, char *data, int frame_length) { - int len; - if (frame_length > q->framebits) { - fprintf(stderr, "Initialized decoder for max frame length %d bits\n", - q->framebits); - return -1; - } - if (q->tail_biting) { - len = 3 * frame_length; - } else { - len = 3 * (frame_length + q->K - 1); - } - vec_quant_fuc(symbols, q->symbols_uc, 32, 127.5, 255, len); - return q->decode(q, q->symbols_uc, data, frame_length); + int len; + if (frame_length > q->framebits) { + fprintf(stderr, "Initialized decoder for max frame length %d bits\n", + q->framebits); + return -1; + } + if (q->tail_biting) { + len = 3 * frame_length; + } else { + len = 3 * (frame_length + q->K - 1); + } + vec_quant_fuc(symbols, q->symbols_uc, 32, 127.5, 255, len); + return q->decode(q, q->symbols_uc, data, frame_length); } int viterbi_decode_uc(viterbi_t *q, unsigned char *symbols, char *data, - int frame_length) { - return q->decode(q, symbols, data, frame_length); + int frame_length) { + return q->decode(q, symbols, data, frame_length); } int viterbi_initialize(viterbi_hl* h) { - int poly[3]; - viterbi_type_t type; - if (h->init.rate == 2) { - if (h->init.constraint_length == 7) { - type = viterbi_27; - } else if (h->init.constraint_length == 9) { - type = viterbi_29; - } else { - fprintf(stderr, "Unsupported decoder %d/%d\n", h->init.rate, - h->init.constraint_length); - return -1; - } - } else if (h->init.rate == 3) { - if (h->init.constraint_length == 7) { - type = viterbi_37; - } else if (h->init.constraint_length == 9) { - type = viterbi_39; - } else { - fprintf(stderr, "Unsupported decoder %d/%d\n", h->init.rate, - h->init.constraint_length); - return -1; - } - } else { - fprintf(stderr, "Unsupported decoder %d/%d\n", h->init.rate, - h->init.constraint_length); - return -1; - } - poly[0] = h->init.generator_0; - poly[1] = h->init.generator_1; - poly[2] = h->init.generator_2; - return viterbi_init(&h->obj, type, poly, h->init.frame_length, - h->init.tail_bitting ? true : false); + int poly[3]; + viterbi_type_t type; + if (h->init.rate == 2) { + if (h->init.constraint_length == 7) { + type = viterbi_27; + } else if (h->init.constraint_length == 9) { + type = viterbi_29; + } else { + fprintf(stderr, "Unsupported decoder %d/%d\n", h->init.rate, + h->init.constraint_length); + return -1; + } + } else if (h->init.rate == 3) { + if (h->init.constraint_length == 7) { + type = viterbi_37; + } else if (h->init.constraint_length == 9) { + type = viterbi_39; + } else { + fprintf(stderr, "Unsupported decoder %d/%d\n", h->init.rate, + h->init.constraint_length); + return -1; + } + } else { + fprintf(stderr, "Unsupported decoder %d/%d\n", h->init.rate, + h->init.constraint_length); + return -1; + } + poly[0] = h->init.generator_0; + poly[1] = h->init.generator_1; + poly[2] = h->init.generator_2; + return viterbi_init(&h->obj, type, poly, h->init.frame_length, + h->init.tail_bitting ? true : false); } int viterbi_work(viterbi_hl* hl) { - if (hl->in_len != hl->init.frame_length) { - fprintf(stderr, "Expected input length %d but got %d\n", - hl->init.frame_length, hl->in_len); - return -1; - } - return viterbi_decode_f(&hl->obj, hl->input, hl->output, hl->init.frame_length); + if (hl->in_len != hl->init.frame_length) { + fprintf(stderr, "Expected input length %d but got %d\n", + hl->init.frame_length, hl->in_len); + return -1; + } + return viterbi_decode_f(&hl->obj, hl->input, hl->output, hl->init.frame_length); } int viterbi_stop(viterbi_hl* h) { - viterbi_free(&h->obj); - return 0; + viterbi_free(&h->obj); + return 0; } diff --git a/lte/lib/fec/src/viterbi37_port.c b/lte/lib/fec/src/viterbi37_port.c index 56ee3645c..7eb311324 100644 --- a/lte/lib/fec/src/viterbi37_port.c +++ b/lte/lib/fec/src/viterbi37_port.c @@ -10,117 +10,117 @@ #include typedef union { - unsigned int w[64]; + unsigned int w[64]; } metric_t; typedef union { - unsigned long w[2]; + unsigned long w[2]; } decision_t; static union { - unsigned char c[128]; + unsigned char c[128]; } Branchtab37[3]; /* State info for instance of Viterbi decoder */ struct v37 { - metric_t metrics1; /* path metric buffer 1 */ - metric_t metrics2; /* path metric buffer 2 */ - decision_t *dp; /* Pointer to current decision */ - metric_t *old_metrics, *new_metrics; /* Pointers to path metrics, swapped on every bit */ - decision_t *decisions; /* Beginning of decisions for block */ + metric_t metrics1; /* path metric buffer 1 */ + metric_t metrics2; /* path metric buffer 2 */ + decision_t *dp; /* Pointer to current decision */ + metric_t *old_metrics, *new_metrics; /* Pointers to path metrics, swapped on every bit */ + decision_t *decisions; /* Beginning of decisions for block */ }; /* Initialize Viterbi decoder for start of new frame */ int init_viterbi37_port(void *p, int starting_state) { - struct v37 *vp = p; - int i; - - if (p == NULL) - return -1; - for (i = 0; i < 64; i++) - vp->metrics1.w[i] = 63; - - vp->old_metrics = &vp->metrics1; - vp->new_metrics = &vp->metrics2; - vp->dp = vp->decisions; - if (starting_state != -1) { - vp->old_metrics->w[starting_state & 255] = 0; /* Bias known start state */ - } - return 0; + struct v37 *vp = p; + int i; + + if (p == NULL) + return -1; + for (i = 0; i < 64; i++) + vp->metrics1.w[i] = 63; + + vp->old_metrics = &vp->metrics1; + vp->new_metrics = &vp->metrics2; + vp->dp = vp->decisions; + if (starting_state != -1) { + vp->old_metrics->w[starting_state & 255] = 0; /* Bias known start state */ + } + return 0; } void set_viterbi37_polynomial_port(int polys[3]) { - int state; - - for (state = 0; state < 32; state++) { - Branchtab37[0].c[state] = - (polys[0] < 0) ^ parity((2 * state) & abs(polys[0])) ? 255 : 0; - Branchtab37[1].c[state] = - (polys[1] < 0) ^ parity((2 * state) & abs(polys[1])) ? 255 : 0; - Branchtab37[2].c[state] = - (polys[2] < 0) ^ parity((2 * state) & abs(polys[2])) ? 255 : 0; - } + int state; + + for (state = 0; state < 32; state++) { + Branchtab37[0].c[state] = + (polys[0] < 0) ^ parity((2 * state) & abs(polys[0])) ? 255 : 0; + Branchtab37[1].c[state] = + (polys[1] < 0) ^ parity((2 * state) & abs(polys[1])) ? 255 : 0; + Branchtab37[2].c[state] = + (polys[2] < 0) ^ parity((2 * state) & abs(polys[2])) ? 255 : 0; + } } /* Create a new instance of a Viterbi decoder */ void *create_viterbi37_port(int polys[3], int len) { - struct v37 *vp; + struct v37 *vp; - set_viterbi37_polynomial_port(polys); + set_viterbi37_polynomial_port(polys); - if ((vp = (struct v37 *) malloc(sizeof(struct v37))) == NULL) - return NULL ; + if ((vp = (struct v37 *) malloc(sizeof(struct v37))) == NULL) + return NULL ; - if ((vp->decisions = (decision_t *) malloc((len + 6) * sizeof(decision_t))) - == NULL) { - free(vp); - return NULL ; - } - init_viterbi37_port(vp, 0); + if ((vp->decisions = (decision_t *) malloc((len + 6) * sizeof(decision_t))) + == NULL) { + free(vp); + return NULL ; + } + init_viterbi37_port(vp, 0); - return vp; + return vp; } /* Viterbi chainback */ int chainback_viterbi37_port(void *p, char *data, /* Decoded output data */ - unsigned int nbits, /* Number of data bits */ - unsigned int endstate) { /* Terminal encoder state */ - struct v37 *vp = p; - decision_t *d; - - if (p == NULL) - return -1; - - d = vp->decisions; - - /* Make room beyond the end of the encoder register so we can - * accumulate a full byte of decoded data - */ - endstate %= 64; - endstate <<= 2; - - /* The store into data[] only needs to be done every 8 bits. - * But this avoids a conditional branch, and the writes will - * combine in the cache anyway - */ - d += 6; /* Look past tail */ - while (nbits-- != 0) { - int k; - - k = (d[nbits].w[(endstate >> 2) / 32] >> ((endstate >> 2) % 32)) & 1; - endstate = (endstate >> 1) | (k << 7); - data[nbits] = k; - } - return 0; + unsigned int nbits, /* Number of data bits */ + unsigned int endstate) { /* Terminal encoder state */ + struct v37 *vp = p; + decision_t *d; + + if (p == NULL) + return -1; + + d = vp->decisions; + + /* Make room beyond the end of the encoder register so we can + * accumulate a full byte of decoded data + */ + endstate %= 64; + endstate <<= 2; + + /* The store into data[] only needs to be done every 8 bits. + * But this avoids a conditional branch, and the writes will + * combine in the cache anyway + */ + d += 6; /* Look past tail */ + while (nbits-- != 0) { + int k; + + k = (d[nbits].w[(endstate >> 2) / 32] >> ((endstate >> 2) % 32)) & 1; + endstate = (endstate >> 1) | (k << 7); + data[nbits] = k; + } + return 0; } /* Delete instance of a Viterbi decoder */ void delete_viterbi37_port(void *p) { - struct v37 *vp = p; + struct v37 *vp = p; - if (vp != NULL) { - free(vp->decisions); - free(vp); - } + if (vp != NULL) { + free(vp->decisions); + free(vp); + } } /* C-language butterfly */ @@ -146,44 +146,44 @@ unsigned int metric,m0,m1,decision;\ */ int update_viterbi37_blk_port(void *p, unsigned char *syms, int nbits, int *best_state) { - struct v37 *vp = p; - decision_t *d; - - if (p == NULL) - return -1; - int k=0; - d = (decision_t *) vp->dp; - while (nbits--) { - void *tmp; - unsigned char sym0, sym1, sym2; - int i; - - d->w[0] = d->w[1] = 0; - - sym0 = *syms++; - sym1 = *syms++; - sym2 = *syms++; - - k++; - for (i = 0; i < 32; i++) - BFLY(i); - - d++; - tmp = vp->old_metrics; - vp->old_metrics = vp->new_metrics; - vp->new_metrics = tmp; - } - if (best_state) { - int i, bst=0; - unsigned int minmetric=UINT_MAX; - for (i=0;i<64;i++) { - if (vp->old_metrics->w[i] < minmetric) { - bst = i; - minmetric = vp->old_metrics->w[i]; - } - } - *best_state = bst; - } - vp->dp = d; - return 0; + struct v37 *vp = p; + decision_t *d; + + if (p == NULL) + return -1; + int k=0; + d = (decision_t *) vp->dp; + while (nbits--) { + void *tmp; + unsigned char sym0, sym1, sym2; + int i; + + d->w[0] = d->w[1] = 0; + + sym0 = *syms++; + sym1 = *syms++; + sym2 = *syms++; + + k++; + for (i = 0; i < 32; i++) + BFLY(i); + + d++; + tmp = vp->old_metrics; + vp->old_metrics = vp->new_metrics; + vp->new_metrics = tmp; + } + if (best_state) { + int i, bst=0; + unsigned int minmetric=UINT_MAX; + for (i=0;i<64;i++) { + if (vp->old_metrics->w[i] < minmetric) { + bst = i; + minmetric = vp->old_metrics->w[i]; + } + } + *best_state = bst; + } + vp->dp = d; + return 0; } diff --git a/lte/lib/fec/src/viterbi39.h b/lte/lib/fec/src/viterbi39.h index f9179d2bc..a5830d145 100644 --- a/lte/lib/fec/src/viterbi39.h +++ b/lte/lib/fec/src/viterbi39.h @@ -30,7 +30,7 @@ void *create_viterbi39_port(int polys[3], int len); int init_viterbi39_port(void *p, int starting_state); int chainback_viterbi39_port(void *p, char *data, /* Decoded output data */ - unsigned int nbits, /* Number of data bits */ - unsigned int endstate); + unsigned int nbits, /* Number of data bits */ + unsigned int endstate); void delete_viterbi39_port(void *p); int update_viterbi39_blk_port(void *p, unsigned char *syms, int nbits); diff --git a/lte/lib/fec/src/viterbi39_port.c b/lte/lib/fec/src/viterbi39_port.c index 0ed0e55c0..fe57297c7 100644 --- a/lte/lib/fec/src/viterbi39_port.c +++ b/lte/lib/fec/src/viterbi39_port.c @@ -9,113 +9,113 @@ #include "parity.h" typedef union { - unsigned int w[256]; + unsigned int w[256]; } metric_t; typedef union { - unsigned long w[8]; + unsigned long w[8]; } decision_t; static union { - unsigned char c[128]; + unsigned char c[128]; } Branchtab39[3]; /* State info for instance of Viterbi decoder */ struct v39 { - metric_t metrics1; /* path metric buffer 1 */ - metric_t metrics2; /* path metric buffer 2 */ - decision_t *dp; /* Pointer to current decision */ - metric_t *old_metrics, *new_metrics; /* Pointers to path metrics, swapped on every bit */ - decision_t *decisions; /* Beginning of decisions for block */ + metric_t metrics1; /* path metric buffer 1 */ + metric_t metrics2; /* path metric buffer 2 */ + decision_t *dp; /* Pointer to current decision */ + metric_t *old_metrics, *new_metrics; /* Pointers to path metrics, swapped on every bit */ + decision_t *decisions; /* Beginning of decisions for block */ }; /* Initialize Viterbi decoder for start of new frame */ int init_viterbi39_port(void *p, int starting_state) { - struct v39 *vp = p; - int i; - - if (p == NULL) - return -1; - for (i = 0; i < 256; i++) - vp->metrics1.w[i] = 63; - - vp->old_metrics = &vp->metrics1; - vp->new_metrics = &vp->metrics2; - vp->dp = vp->decisions; - vp->old_metrics->w[starting_state & 255] = 0; /* Bias known start state */ - return 0; + struct v39 *vp = p; + int i; + + if (p == NULL) + return -1; + for (i = 0; i < 256; i++) + vp->metrics1.w[i] = 63; + + vp->old_metrics = &vp->metrics1; + vp->new_metrics = &vp->metrics2; + vp->dp = vp->decisions; + vp->old_metrics->w[starting_state & 255] = 0; /* Bias known start state */ + return 0; } void set_viterbi39_polynomial_port(int polys[3]) { - int state; - - for (state = 0; state < 128; state++) { - Branchtab39[0].c[state] = - (polys[0] < 0) ^ parity((2 * state) & abs(polys[0])) ? 255 : 0; - Branchtab39[1].c[state] = - (polys[1] < 0) ^ parity((2 * state) & abs(polys[1])) ? 255 : 0; - Branchtab39[2].c[state] = - (polys[2] < 0) ^ parity((2 * state) & abs(polys[2])) ? 255 : 0; - } + int state; + + for (state = 0; state < 128; state++) { + Branchtab39[0].c[state] = + (polys[0] < 0) ^ parity((2 * state) & abs(polys[0])) ? 255 : 0; + Branchtab39[1].c[state] = + (polys[1] < 0) ^ parity((2 * state) & abs(polys[1])) ? 255 : 0; + Branchtab39[2].c[state] = + (polys[2] < 0) ^ parity((2 * state) & abs(polys[2])) ? 255 : 0; + } } /* Create a new instance of a Viterbi decoder */ void *create_viterbi39_port(int polys[3], int len) { - struct v39 *vp; + struct v39 *vp; - set_viterbi39_polynomial_port(polys); + set_viterbi39_polynomial_port(polys); - if ((vp = (struct v39 *) malloc(sizeof(struct v39))) == NULL) - return NULL ; + if ((vp = (struct v39 *) malloc(sizeof(struct v39))) == NULL) + return NULL ; - if ((vp->decisions = (decision_t *) malloc((len + 8) * sizeof(decision_t))) - == NULL) { - free(vp); - return NULL ; - } - init_viterbi39_port(vp, 0); + if ((vp->decisions = (decision_t *) malloc((len + 8) * sizeof(decision_t))) + == NULL) { + free(vp); + return NULL ; + } + init_viterbi39_port(vp, 0); - return vp; + return vp; } /* Viterbi chainback */ int chainback_viterbi39_port(void *p, char *data, /* Decoded output data */ - unsigned int nbits, /* Number of data bits */ - unsigned int endstate) { /* Terminal encoder state */ - struct v39 *vp = p; - decision_t *d; - - if (p == NULL) - return -1; - - d = vp->decisions; - /* Make room beyond the end of the encoder register so we can - * accumulate a full byte of decoded data - */ - endstate %= 256; - - /* The store into data[] only needs to be done every 8 bits. - * But this avoids a conditional branch, and the writes will - * combine in the cache anyway - */ - d += 8; /* Look past tail */ - while (nbits-- != 0) { - int k; - - k = (d[nbits].w[(endstate) / 32] >> (endstate % 32)) & 1; - endstate = (endstate >> 1) | (k << 7); - data[nbits] = k; - } - return 0; + unsigned int nbits, /* Number of data bits */ + unsigned int endstate) { /* Terminal encoder state */ + struct v39 *vp = p; + decision_t *d; + + if (p == NULL) + return -1; + + d = vp->decisions; + /* Make room beyond the end of the encoder register so we can + * accumulate a full byte of decoded data + */ + endstate %= 256; + + /* The store into data[] only needs to be done every 8 bits. + * But this avoids a conditional branch, and the writes will + * combine in the cache anyway + */ + d += 8; /* Look past tail */ + while (nbits-- != 0) { + int k; + + k = (d[nbits].w[(endstate) / 32] >> (endstate % 32)) & 1; + endstate = (endstate >> 1) | (k << 7); + data[nbits] = k; + } + return 0; } /* Delete instance of a Viterbi decoder */ void delete_viterbi39_port(void *p) { - struct v39 *vp = p; + struct v39 *vp = p; - if (vp != NULL) { - free(vp->decisions); - free(vp); - } + if (vp != NULL) { + free(vp->decisions); + free(vp); + } } /* C-language butterfly */ @@ -141,32 +141,32 @@ unsigned int metric,m0,m1,decision;\ */ int update_viterbi39_blk_port(void *p, unsigned char *syms, int nbits) { - struct v39 *vp = p; - decision_t *d; - - if (p == NULL) - return -1; - - d = (decision_t *) vp->dp; - while (nbits--) { - void *tmp; - unsigned char sym0, sym1, sym2; - int i; - - for (i = 0; i < 8; i++) - d->w[i] = 0; - sym0 = *syms++; - sym1 = *syms++; - sym2 = *syms++; - - for (i = 0; i < 128; i++) - BFLY(i); - - d++; - tmp = vp->old_metrics; - vp->old_metrics = vp->new_metrics; - vp->new_metrics = tmp; - } - vp->dp = d; - return 0; + struct v39 *vp = p; + decision_t *d; + + if (p == NULL) + return -1; + + d = (decision_t *) vp->dp; + while (nbits--) { + void *tmp; + unsigned char sym0, sym1, sym2; + int i; + + for (i = 0; i < 8; i++) + d->w[i] = 0; + sym0 = *syms++; + sym1 = *syms++; + sym2 = *syms++; + + for (i = 0; i < 128; i++) + BFLY(i); + + d++; + tmp = vp->old_metrics; + vp->old_metrics = vp->new_metrics; + vp->new_metrics = tmp; + } + vp->dp = d; + return 0; } diff --git a/lte/lib/fec/test/crc_test.c b/lte/lib/fec/test/crc_test.c index e21c89c4d..e1244f59f 100644 --- a/lte/lib/fec/test/crc_test.c +++ b/lte/lib/fec/test/crc_test.c @@ -41,75 +41,75 @@ unsigned int crc_poly = 0x1864CFB; unsigned int seed = 1; void usage(char *prog) { - printf("Usage: %s [nlps]\n", prog); - printf("\t-n num_bits [Default %d]\n", num_bits); - printf("\t-l crc_length [Default %d]\n", crc_length); - printf("\t-p crc_poly (Hex) [Default 0x%x]\n", crc_poly); - printf("\t-s seed [Default 0=time]\n"); + printf("Usage: %s [nlps]\n", prog); + printf("\t-n num_bits [Default %d]\n", num_bits); + printf("\t-l crc_length [Default %d]\n", crc_length); + printf("\t-p crc_poly (Hex) [Default 0x%x]\n", crc_poly); + printf("\t-s seed [Default 0=time]\n"); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "nlps")) != -1) { - switch (opt) { - case 'n': - num_bits = atoi(argv[optind]); - break; - case 'l': - crc_length = atoi(argv[optind]); - break; - case 'p': - crc_poly = (unsigned int) strtoul(argv[optind], NULL, 16); - break; - case 's': - seed = (unsigned int) strtoul(argv[optind], NULL, 0); - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "nlps")) != -1) { + switch (opt) { + case 'n': + num_bits = atoi(argv[optind]); + break; + case 'l': + crc_length = atoi(argv[optind]); + break; + case 'p': + crc_poly = (unsigned int) strtoul(argv[optind], NULL, 16); + break; + case 's': + seed = (unsigned int) strtoul(argv[optind], NULL, 0); + break; + default: + usage(argv[0]); + exit(-1); + } + } } int main(int argc, char **argv) { - int i; - char *data; - unsigned int crc_word, expected_word; - crc_t crc_p; + int i; + char *data; + unsigned int crc_word, expected_word; + crc_t crc_p; - parse_args(argc, argv); + parse_args(argc, argv); - data = malloc(sizeof(char) * (num_bits + crc_length * 2)); - if (!data) { - perror("malloc"); - exit(-1); - } + data = malloc(sizeof(char) * (num_bits + crc_length * 2)); + if (!data) { + perror("malloc"); + exit(-1); + } - if (!seed) { - seed = time(NULL); - } - srand(seed); + if (!seed) { + seed = time(NULL); + } + srand(seed); - // Generate data - for (i = 0; i < num_bits; i++) { - data[i] = rand() % 2; - } + // Generate data + for (i = 0; i < num_bits; i++) { + data[i] = rand() % 2; + } - //Initialize CRC params and tables - if (crc_init(&crc_p, crc_poly, crc_length)) { - exit(-1); - } + //Initialize CRC params and tables + if (crc_init(&crc_p, crc_poly, crc_length)) { + exit(-1); + } - // generate CRC word - crc_word = crc_checksum(&crc_p, data, num_bits); + // generate CRC word + crc_word = crc_checksum(&crc_p, data, num_bits); - free(data); + free(data); - // check if generated word is as expected - if (get_expected_word(num_bits, crc_length, crc_poly, seed, - &expected_word)) { - fprintf(stderr, "Test parameters not defined in test_results.h\n"); - exit(-1); - } - exit(expected_word != crc_word); + // check if generated word is as expected + if (get_expected_word(num_bits, crc_length, crc_poly, seed, + &expected_word)) { + fprintf(stderr, "Test parameters not defined in test_results.h\n"); + exit(-1); + } + exit(expected_word != crc_word); } diff --git a/lte/lib/fec/test/crc_test.h b/lte/lib/fec/test/crc_test.h index e52faeaf4..6968b07b0 100644 --- a/lte/lib/fec/test/crc_test.h +++ b/lte/lib/fec/test/crc_test.h @@ -30,42 +30,42 @@ #include "lte/fec/crc.h" typedef struct { - int n; - int l; - unsigned int p; - unsigned int s; - unsigned int word; + int n; + int l; + unsigned int p; + unsigned int s; + unsigned int word; }expected_word_t; static expected_word_t expected_words[] = { - {5001, 24, LTE_CRC24A, 1, 0x1C5C97}, // LTE CRC24A (36.212 Sec 5.1.1) - {5001, 24, LTE_CRC24B, 1, 0x36D1F0}, // LTE CRC24B - {5001, 16, LTE_CRC16, 1, 0x7FF4}, // LTE CRC16: 0x7FF4 - {5001, 8, LTE_CRC8, 1, 0xF0}, // LTE CRC8 0xF8 + {5001, 24, LTE_CRC24A, 1, 0x1C5C97}, // LTE CRC24A (36.212 Sec 5.1.1) + {5001, 24, LTE_CRC24B, 1, 0x36D1F0}, // LTE CRC24B + {5001, 16, LTE_CRC16, 1, 0x7FF4}, // LTE CRC16: 0x7FF4 + {5001, 8, LTE_CRC8, 1, 0xF0}, // LTE CRC8 0xF8 - {-1, -1, 0, 0, 0} + {-1, -1, 0, 0, 0} }; int get_expected_word(int n, int l, unsigned int p, unsigned int s, unsigned int *word) { - int i; - i=0; - while(expected_words[i].n != -1) { - if (expected_words[i].l == l - && expected_words[i].p == p - && expected_words[i].s == s) { - break; - } else { - i++; - } - } - if (expected_words[i].n == -1) { - return -1; - } else { - if (word) { - *word = expected_words[i].word; - } - return 0; - } + int i; + i=0; + while(expected_words[i].n != -1) { + if (expected_words[i].l == l + && expected_words[i].p == p + && expected_words[i].s == s) { + break; + } else { + i++; + } + } + if (expected_words[i].n == -1) { + return -1; + } else { + if (word) { + *word = expected_words[i].word; + } + return 0; + } } diff --git a/lte/lib/fec/test/rm_conv_test.c b/lte/lib/fec/test/rm_conv_test.c index a6e8ab63f..7c0be9e0e 100644 --- a/lte/lib/fec/test/rm_conv_test.c +++ b/lte/lib/fec/test/rm_conv_test.c @@ -39,97 +39,97 @@ int nof_tx_bits=-1, nof_rx_bits=-1; 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\n", prog); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "tr")) != -1) { - switch (opt) { - case 't': - nof_tx_bits = atoi(argv[optind]); - break; - case 'r': - nof_rx_bits = atoi(argv[optind]); - break; - default: - usage(argv[0]); - exit(-1); - } - } - if (nof_tx_bits == -1) { - usage(argv[0]); - exit(-1); - } - if (nof_rx_bits == -1) { - usage(argv[0]); - exit(-1); - } + int opt; + while ((opt = getopt(argc, argv, "tr")) != -1) { + switch (opt) { + case 't': + nof_tx_bits = atoi(argv[optind]); + break; + case 'r': + nof_rx_bits = atoi(argv[optind]); + break; + default: + usage(argv[0]); + exit(-1); + } + } + if (nof_tx_bits == -1) { + usage(argv[0]); + exit(-1); + } + if (nof_rx_bits == -1) { + usage(argv[0]); + exit(-1); + } } int main(int argc, char **argv) { - int i; - char *bits, *rm_bits; - float *rm_symbols, *unrm_symbols; - int nof_errors; + int i; + char *bits, *rm_bits; + float *rm_symbols, *unrm_symbols; + int nof_errors; - parse_args(argc, argv); + parse_args(argc, argv); - bits = malloc(sizeof(char) * nof_tx_bits); - if (!bits) { - perror("malloc"); - exit(-1); - } - rm_bits = malloc(sizeof(char) * nof_rx_bits); - if (!rm_bits) { - perror("malloc"); - exit(-1); - } - rm_symbols = malloc(sizeof(float) * nof_rx_bits); - if (!rm_symbols) { - perror("malloc"); - exit(-1); - } - unrm_symbols = malloc(sizeof(float) * nof_tx_bits); - if (!unrm_symbols) { - perror("malloc"); - exit(-1); - } + bits = malloc(sizeof(char) * nof_tx_bits); + if (!bits) { + perror("malloc"); + exit(-1); + } + rm_bits = malloc(sizeof(char) * nof_rx_bits); + if (!rm_bits) { + perror("malloc"); + exit(-1); + } + rm_symbols = malloc(sizeof(float) * nof_rx_bits); + if (!rm_symbols) { + perror("malloc"); + exit(-1); + } + unrm_symbols = malloc(sizeof(float) * nof_tx_bits); + if (!unrm_symbols) { + perror("malloc"); + exit(-1); + } - for (i=0;i 0) != bits[i]) { - nof_errors++; - } - } - if (nof_rx_bits > nof_tx_bits) { - if (nof_errors) { - printf("nof_errors=%d\n", nof_errors); - exit(-1); - } - } + nof_errors = 0; + for (i=0;i 0) != bits[i]) { + nof_errors++; + } + } + if (nof_rx_bits > nof_tx_bits) { + if (nof_errors) { + printf("nof_errors=%d\n", nof_errors); + exit(-1); + } + } - free(bits); - free(rm_bits); - free(rm_symbols); - free(unrm_symbols); + free(bits); + free(rm_bits); + free(rm_symbols); + free(unrm_symbols); - printf("Ok\n"); - exit(0); + printf("Ok\n"); + exit(0); } diff --git a/lte/lib/fec/test/rm_turbo_test.c b/lte/lib/fec/test/rm_turbo_test.c index 97adc0bfe..f76109f68 100644 --- a/lte/lib/fec/test/rm_turbo_test.c +++ b/lte/lib/fec/test/rm_turbo_test.c @@ -40,103 +40,103 @@ 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 [-i rv_idx]\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, "tri")) != -1) { - switch (opt) { - case 't': - nof_tx_bits = atoi(argv[optind]); - break; - case 'r': - nof_rx_bits = atoi(argv[optind]); - break; - case 'i': - rv_idx = atoi(argv[optind]); - break; - default: - usage(argv[0]); - exit(-1); - } - } - if (nof_tx_bits == -1) { - usage(argv[0]); - exit(-1); - } - if (nof_rx_bits == -1) { - usage(argv[0]); - exit(-1); - } + int opt; + while ((opt = getopt(argc, argv, "tri")) != -1) { + switch (opt) { + case 't': + nof_tx_bits = atoi(argv[optind]); + break; + case 'r': + nof_rx_bits = atoi(argv[optind]); + break; + case 'i': + rv_idx = atoi(argv[optind]); + break; + default: + usage(argv[0]); + exit(-1); + } + } + if (nof_tx_bits == -1) { + usage(argv[0]); + exit(-1); + } + if (nof_rx_bits == -1) { + usage(argv[0]); + exit(-1); + } } int main(int argc, char **argv) { - int i; - char *bits, *rm_bits; - float *rm_symbols, *unrm_symbols; - int nof_errors; - rm_turbo_t rm_turbo; - - parse_args(argc, argv); - - bits = malloc(sizeof(char) * nof_tx_bits); - if (!bits) { - perror("malloc"); - exit(-1); - } - rm_bits = malloc(sizeof(char) * nof_rx_bits); - if (!rm_bits) { - perror("malloc"); - exit(-1); - } - rm_symbols = malloc(sizeof(float) * nof_rx_bits); - if (!rm_symbols) { - perror("malloc"); - exit(-1); - } - unrm_symbols = malloc(sizeof(float) * nof_tx_bits); - if (!unrm_symbols) { - perror("malloc"); - exit(-1); - } - - for (i=0;i 0) != bits[i]) { - nof_errors++; - printf("%.2f != %d\n", unrm_symbols[i], bits[i]); - } - } - - 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); + int i; + char *bits, *rm_bits; + float *rm_symbols, *unrm_symbols; + int nof_errors; + rm_turbo_t rm_turbo; + + parse_args(argc, argv); + + bits = malloc(sizeof(char) * nof_tx_bits); + if (!bits) { + perror("malloc"); + exit(-1); + } + rm_bits = malloc(sizeof(char) * nof_rx_bits); + if (!rm_bits) { + perror("malloc"); + exit(-1); + } + rm_symbols = malloc(sizeof(float) * nof_rx_bits); + if (!rm_symbols) { + perror("malloc"); + exit(-1); + } + unrm_symbols = malloc(sizeof(float) * nof_tx_bits); + if (!unrm_symbols) { + perror("malloc"); + exit(-1); + } + + for (i=0;i 0) != bits[i]) { + nof_errors++; + printf("%.2f != %d\n", unrm_symbols[i], bits[i]); + } + } + + 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/fec/test/turbocoder_test.c b/lte/lib/fec/test/turbocoder_test.c index ad28ee470..d7bcdae3e 100644 --- a/lte/lib/fec/test/turbocoder_test.c +++ b/lte/lib/fec/test/turbocoder_test.c @@ -46,279 +46,279 @@ float ebno_db = 100.0; unsigned int seed = 0; int K = -1; -#define MAX_ITERATIONS 4 +#define MAX_ITERATIONS 4 int nof_iterations = MAX_ITERATIONS; int test_known_data = 0; int test_errors = 0; -#define SNR_POINTS 8 -#define SNR_MIN 0.0 -#define SNR_MAX 4.0 +#define SNR_POINTS 8 +#define SNR_MIN 0.0 +#define SNR_MAX 4.0 void usage(char *prog) { - printf("Usage: %s [nlesv]\n", prog); - printf("\t-k Test with known data (ignores frame_length) [Default disabled]\n"); - printf("\t-i nof_iterations [Default %d]\n", nof_iterations); - printf("\t-n nof_frames [Default %d]\n", nof_frames); - printf("\t-l frame_length [Default %d]\n", frame_length); - printf("\t-e ebno in dB [Default scan]\n"); - printf("\t-t test: check errors on exit [Default disabled]\n"); - printf("\t-s seed [Default 0=time]\n"); + printf("Usage: %s [nlesv]\n", prog); + printf("\t-k Test with known data (ignores frame_length) [Default disabled]\n"); + printf("\t-i nof_iterations [Default %d]\n", nof_iterations); + printf("\t-n nof_frames [Default %d]\n", nof_frames); + printf("\t-l frame_length [Default %d]\n", frame_length); + printf("\t-e ebno in dB [Default scan]\n"); + printf("\t-t test: check errors on exit [Default disabled]\n"); + printf("\t-s seed [Default 0=time]\n"); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "inlstvekt")) != -1) { - switch (opt) { - case 'n': - nof_frames = atoi(argv[optind]); - break; - case 'k': - test_known_data = 1; - break; - case 't': - test_errors = 1; - break; - case 'i': - nof_iterations = atoi(argv[optind]); - break; - case 'l': - frame_length = atoi(argv[optind]); - break; - case 'e': - ebno_db = atof(argv[optind]); - break; - case 's': - seed = (unsigned int) strtoul(argv[optind], NULL, 0); - break; - case 'v': - verbose++; - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "inlstvekt")) != -1) { + switch (opt) { + case 'n': + nof_frames = atoi(argv[optind]); + break; + case 'k': + test_known_data = 1; + break; + case 't': + test_errors = 1; + break; + case 'i': + nof_iterations = atoi(argv[optind]); + break; + case 'l': + frame_length = atoi(argv[optind]); + break; + case 'e': + ebno_db = atof(argv[optind]); + break; + case 's': + seed = (unsigned int) strtoul(argv[optind], NULL, 0); + break; + case 'v': + verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } } void output_matlab(float ber[MAX_ITERATIONS][SNR_POINTS], int snr_points) { - int i, j; - FILE *f = fopen("turbocoder_snr.m", "w"); - if (!f) { - perror("fopen"); - exit(-1); - } - fprintf(f, "ber=["); - for (j=0;j known_data_errors[j]) { - fprintf(stderr, "Expected %d errors but got %d\n", - known_data_errors[j], errors[j]); - exit(-1); - }else { - printf("Iter %d ok\n", j+1); - } - } - } else { - for (j=0;j get_expected_errors(frame_cnt, seed, j+1, frame_length, ebno_db)) { - fprintf(stderr, "Expected %d errors but got %d\n", - get_expected_errors(frame_cnt, seed, j+1, frame_length, ebno_db), - errors[j]); - exit(-1); - } else { - printf("Iter %d ok\n", j+1); - } - } - } - } - } - } - - free(data_tx); - free(symbols); - free(llr); - free(llr_c); - free(data_rx); - - tdec_free(&tdec); - tcod_free(&tcod); - - printf("\n"); - output_matlab(ber, snr_points); - printf("Done\n"); - exit(0); + int frame_cnt; + float *llr; + unsigned char *llr_c; + char *data_tx, *data_rx, *symbols; + int i, j; + float var[SNR_POINTS]; + int snr_points; + float ber[MAX_ITERATIONS][SNR_POINTS]; + unsigned int errors[100]; + int coded_length; + struct timeval tdata[3]; + float mean_usec; + tdec_t tdec; + tcod_t tcod; + + parse_args(argc, argv); + + if (!seed) { + seed = time(NULL); + } + srand(seed); + + if (test_known_data) { + frame_length = KNOWN_DATA_LEN; + } else { + frame_length = lte_cb_size(lte_find_cb_index(frame_length)); + } + + coded_length = 3*(frame_length)+TOTALTAIL; + + printf(" Frame length: %d\n", frame_length); + if (ebno_db < 100.0) { + 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); + } + llr_c = malloc(coded_length * sizeof(char)); + if (!llr_c) { + perror("malloc"); + exit(-1); + } + + if (tcod_init(&tcod, frame_length)) { + fprintf(stderr, "Error initiating Turbo coder\n"); + exit(-1); + } + + if (tdec_init(&tdec, frame_length)) { + fprintf(stderr, "Error initiating Turbo decoder\n"); + exit(-1); + } + + float ebno_inc, esno_db; + ebno_inc = (SNR_MAX - SNR_MIN) / SNR_POINTS; + if (ebno_db == 100.0) { + snr_points = SNR_POINTS; + for (i = 0; i < snr_points; i++) { + ebno_db = SNR_MIN + i * ebno_inc; + esno_db = ebno_db + 10 * log10((double) 1 / 3); + var[i] = sqrt(1 / (pow(10, esno_db / 10))); + } + } else { + esno_db = ebno_db + 10 * log10((double) 1 / 3); + var[0] = sqrt(1 / (pow(10, esno_db / 10))); + snr_points = 1; + } + for (i = 0; i < snr_points; i++) { + mean_usec = 0; + frame_cnt = 0; + bzero(errors, sizeof(int) * MAX_ITERATIONS); + while (frame_cnt < nof_frames) { + + /* generate data_tx */ + for (j = 0; j < frame_length; j++) { + if (test_known_data) { + data_tx[j] = known_data[j]; + } else { + data_tx[j] = rand() % 2; + } + } + + /* coded BER */ + if (test_known_data) { + for (j=0;j known_data_errors[j]) { + fprintf(stderr, "Expected %d errors but got %d\n", + known_data_errors[j], errors[j]); + exit(-1); + }else { + printf("Iter %d ok\n", j+1); + } + } + } else { + for (j=0;j get_expected_errors(frame_cnt, seed, j+1, frame_length, ebno_db)) { + fprintf(stderr, "Expected %d errors but got %d\n", + get_expected_errors(frame_cnt, seed, j+1, frame_length, ebno_db), + errors[j]); + exit(-1); + } else { + printf("Iter %d ok\n", j+1); + } + } + } + } + } + } + + free(data_tx); + free(symbols); + free(llr); + free(llr_c); + free(data_rx); + + tdec_free(&tdec); + tcod_free(&tcod); + + printf("\n"); + output_matlab(ber, snr_points); + printf("Done\n"); + exit(0); } diff --git a/lte/lib/fec/test/turbocoder_test.h b/lte/lib/fec/test/turbocoder_test.h index 768f5406b..b0b64ded1 100644 --- a/lte/lib/fec/test/turbocoder_test.h +++ b/lte/lib/fec/test/turbocoder_test.h @@ -28,141 +28,141 @@ #include typedef struct { - int n; - unsigned int s; - int iterations; - int len; - float ebno; - int errors; + int n; + unsigned int s; + int iterations; + int len; + float ebno; + int errors; } expected_errors_t; static expected_errors_t expected_errors[] = { - { 100, 1, 1, 504, 1.0, 3989 }, - { 100, 1, 2, 504, 1.0, 1922 }, - { 100, 1, 3, 504, 1.0, 1096 }, - { 100, 1, 4, 504, 1.0, 957 }, + { 100, 1, 1, 504, 1.0, 3989 }, + { 100, 1, 2, 504, 1.0, 1922 }, + { 100, 1, 3, 504, 1.0, 1096 }, + { 100, 1, 4, 504, 1.0, 957 }, - { 100, 1, 1, 504, 2.0, 803 }, - { 100, 1, 2, 504, 2.0, 47 }, - { 100, 1, 3, 504, 2.0, 7 }, - { 100, 1, 4, 504, 2.0, 0 }, + { 100, 1, 1, 504, 2.0, 803 }, + { 100, 1, 2, 504, 2.0, 47 }, + { 100, 1, 3, 504, 2.0, 7 }, + { 100, 1, 4, 504, 2.0, 0 }, - { 100, 1, 1, 6144, 1.5, 24719 }, - { 100, 1, 2, 6144, 1.5, 897 }, - { 100, 1, 3, 6144, 1.5, 2 }, - { 100, 1, 4, 6144, 1.5, 0 }, - { -1, 0, -1, -1, -1.0, -1} + { 100, 1, 1, 6144, 1.5, 24719 }, + { 100, 1, 2, 6144, 1.5, 897 }, + { 100, 1, 3, 6144, 1.5, 2 }, + { 100, 1, 4, 6144, 1.5, 0 }, + { -1, 0, -1, -1, -1.0, -1} }; int get_expected_errors(int n, unsigned int s, int iterations, int len, float ebno) { - int i; - i = 0; - while (expected_errors[i].n != -1) { - if (expected_errors[i].n == n - && expected_errors[i].s == s - && expected_errors[i].len == len - && expected_errors[i].iterations == iterations - && expected_errors[i].ebno == ebno) { - break; - } else { - i++; - } - } - return expected_errors[i].errors; + int i; + i = 0; + while (expected_errors[i].n != -1) { + if (expected_errors[i].n == n + && expected_errors[i].s == s + && expected_errors[i].len == len + && expected_errors[i].iterations == iterations + && expected_errors[i].ebno == ebno) { + break; + } else { + i++; + } + } + return expected_errors[i].errors; } #define KNOWN_DATA_NFRAMES 1 -#define KNOWN_DATA_SEED 1 -#define KNOWN_DATA_EBNO 0.5 +#define KNOWN_DATA_SEED 1 +#define KNOWN_DATA_EBNO 0.5 const int known_data_errors[4] = {47, 18, 0, 0}; -#define KNOWN_DATA_LEN 504 +#define KNOWN_DATA_LEN 504 const char known_data[KNOWN_DATA_LEN] = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, - 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, - 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, - 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, - 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, - 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, - 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, - 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, - 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, - 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, - 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, - 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, - 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, - 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, - 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, - 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, - 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1 }; + 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, + 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, + 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, + 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, + 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, + 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, + 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, + 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1 }; const char known_data_encoded[3 * KNOWN_DATA_LEN + 12] = { 0, 0, 0, 0, 0, 1, 1, - 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, - 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, - 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, - 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, - 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, - 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, - 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, - 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, - 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, - 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, - 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, - 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, - 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, - 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, - 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, - 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, - 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, - 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, - 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, - 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, - 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, - 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, - 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, - 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, - 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, - 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, - 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, - 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, - 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, - 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, - 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, - 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, - 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, - 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, - 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, - 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, - 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, - 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, - 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, - 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, - 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, - 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, - 1, 0, 1, 1, 1 }; + 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, + 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, + 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, + 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, + 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, + 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, + 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, + 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, + 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, + 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, + 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, + 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, + 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, + 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, + 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, + 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, + 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, + 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, + 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, + 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, + 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, + 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, + 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, + 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, + 1, 0, 1, 1, 1 }; diff --git a/lte/lib/fec/test/viterbi_test.c b/lte/lib/fec/test/viterbi_test.c index 76dd14754..1ca2e7443 100644 --- a/lte/lib/fec/test/viterbi_test.c +++ b/lte/lib/fec/test/viterbi_test.c @@ -45,298 +45,298 @@ unsigned int seed = 0; bool tail_biting = false; int K = -1; -#define SNR_POINTS 10 -#define SNR_MIN 0.0 -#define SNR_MAX 5.0 +#define SNR_POINTS 10 +#define SNR_MIN 0.0 +#define SNR_MAX 5.0 -#define NCODS 3 -#define NTYPES 1+NCODS +#define NCODS 3 +#define NTYPES 1+NCODS void usage(char *prog) { - printf("Usage: %s [nlestk]\n", prog); - printf("\t-n nof_frames [Default %d]\n", nof_frames); - printf("\t-l frame_length [Default %d]\n", frame_length); - printf("\t-e ebno in dB [Default scan]\n"); - printf("\t-s seed [Default 0=time]\n"); - printf("\t-t tail_bitting [Default %s]\n", tail_biting ? "yes" : "no"); - printf("\t-k constraint length [Default both]\n", K); + printf("Usage: %s [nlestk]\n", prog); + printf("\t-n nof_frames [Default %d]\n", nof_frames); + printf("\t-l frame_length [Default %d]\n", frame_length); + printf("\t-e ebno in dB [Default scan]\n"); + printf("\t-s seed [Default 0=time]\n"); + printf("\t-t tail_bitting [Default %s]\n", tail_biting ? "yes" : "no"); + printf("\t-k constraint length [Default both]\n", K); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "nlstek")) != -1) { - switch (opt) { - case 'n': - nof_frames = atoi(argv[optind]); - break; - case 'l': - frame_length = atoi(argv[optind]); - break; - case 'e': - ebno_db = atof(argv[optind]); - break; - case 's': - seed = (unsigned int) strtoul(argv[optind], NULL, 0); - break; - case 't': - tail_biting = true; - break; - case 'k': - K = atoi(argv[optind]); - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "nlstek")) != -1) { + switch (opt) { + case 'n': + nof_frames = atoi(argv[optind]); + break; + case 'l': + frame_length = atoi(argv[optind]); + break; + case 'e': + ebno_db = atof(argv[optind]); + break; + case 's': + seed = (unsigned int) strtoul(argv[optind], NULL, 0); + break; + case 't': + tail_biting = true; + break; + case 'k': + K = atoi(argv[optind]); + break; + default: + usage(argv[0]); + exit(-1); + } + } } void output_matlab(float ber[NTYPES][SNR_POINTS], int snr_points, - convcoder_t cod[NCODS], int ncods) { - int i, j, n; - FILE *f = fopen("viterbi_snr.m", "w"); - if (!f) { - perror("fopen"); - exit(-1); - } - fprintf(f, "ber=["); - for (j = 0; j < NTYPES; j++) { - for (i = 0; i < snr_points; i++) { - fprintf(f, "%g ", ber[j][i]); - } - fprintf(f, "; "); - } - fprintf(f, "];\n"); - fprintf(f, "snr=linspace(%g,%g-%g/%d,%d);\n", SNR_MIN, SNR_MAX, SNR_MAX, - snr_points, snr_points); - fprintf(f, "semilogy(snr,ber,snr,0.5*erfc(sqrt(10.^(snr/10))));\n"); - fprintf(f, "legend('uncoded',"); - for (n=0;n max_coded_length) { - max_coded_length = coded_length[i]; - } - viterbi_init(&dec[i], viterbi_type[i], cod[i].poly, frame_length, cod[i].tail_biting); - printf("Convolutional Code 1/3 K=%d Tail bitting: %s\n", cod[i].K, cod[i].tail_biting ? "yes" : "no"); - } - - printf(" Frame length: %d\n", frame_length); - if (ebno_db < 100.0) { - printf(" EbNo: %.2f\n", ebno_db); - } - - data_tx = malloc(frame_length * sizeof(char)); - if (!data_tx) { - perror("malloc"); - exit(-1); - } - - for (i = 0; i < NTYPES; i++) { - data_rx[i] = malloc(frame_length * sizeof(char)); - if (!data_rx[i]) { - perror("malloc"); - exit(-1); - } - } - - symbols = malloc(max_coded_length * sizeof(char)); - if (!symbols) { - perror("malloc"); - exit(-1); - } - llr = malloc(max_coded_length * sizeof(float)); - if (!llr) { - perror("malloc"); - exit(-1); - } - llr_c = malloc(2 * max_coded_length * sizeof(char)); - if (!llr_c) { - perror("malloc"); - exit(-1); - } - - float ebno_inc, esno_db; - ebno_inc = (SNR_MAX - SNR_MIN) / SNR_POINTS; - if (ebno_db == 100.0) { - snr_points = SNR_POINTS; - for (i = 0; i < snr_points; i++) { - ebno_db = SNR_MIN + i * ebno_inc; - esno_db = ebno_db + 10 * log10((double) 1 / 3); - var[i] = sqrt(1 / (pow(10, esno_db / 10))); - varunc[i] = sqrt(1 / (pow(10, ebno_db / 10))); - } - } else { - esno_db = ebno_db + 10 * log10((double) 1 / 3); - var[0] = sqrt(1 / (pow(10, esno_db / 10))); - varunc[0] = sqrt(1 / (pow(10, ebno_db / 10))); - snr_points = 1; - } - - float Gain = 32; - - for (i = 0; i < snr_points; i++) { - frame_cnt = 0; - for (j = 0; j < NTYPES; j++) { - errors[j] = 0; - } - while (frame_cnt < nof_frames) { - - /* generate data_tx */ - for (j = 0; j < frame_length; j++) { - data_tx[j] = rand() % 2; - } - - /* uncoded BER */ - for (j = 0; j < frame_length; j++) { - llr[j] = data_tx[j] ? sqrt(2) : -sqrt(2); - } - ch_awgn_f(llr, llr, varunc[i], frame_length); - for (j = 0; j < frame_length; j++) { - data_rx[0][j] = llr[j] > 0 ? 1 : 0; - } - - /* coded BER */ - for (n=0;n expected_errors); - } - } else { - printf("\n"); - output_matlab(ber, snr_points, cod, ncods); - printf("Done\n"); - exit(0); - } + int frame_cnt; + float *llr; + unsigned char *llr_c; + char *data_tx, *data_rx[NTYPES], *symbols; + int i, j; + float var[SNR_POINTS], varunc[SNR_POINTS]; + int snr_points; + float ber[NTYPES][SNR_POINTS]; + unsigned int errors[NTYPES]; + viterbi_type_t viterbi_type[NCODS]; + viterbi_t dec[NCODS]; + convcoder_t cod[NCODS]; + int coded_length[NCODS]; + int n, ncods, max_coded_length; + + + parse_args(argc, argv); + + if (!seed) { + seed = time(NULL); + } + srand(seed); + + switch (K) { + case 9: + cod[0].poly[0] = 0x1ed; + cod[0].poly[1] = 0x19b; + cod[0].poly[2] = 0x127; + cod[0].tail_biting = false; + cod[0].K = 9; + viterbi_type[0] = viterbi_39; + ncods=1; + break; + case 7: + cod[0].poly[0] = 0x6D; + cod[0].poly[1] = 0x4F; + cod[0].poly[2] = 0x57; + cod[0].K = 7; + cod[0].tail_biting = tail_biting; + viterbi_type[0] = viterbi_37; + ncods=1; + break; + default: + cod[0].poly[0] = 0x1ed; + cod[0].poly[1] = 0x19b; + cod[0].poly[2] = 0x127; + cod[0].tail_biting = false; + cod[0].K = 9; + viterbi_type[0] = viterbi_39; + cod[1].poly[0] = 0x6D; + cod[1].poly[1] = 0x4F; + cod[1].poly[2] = 0x57; + cod[1].tail_biting = false; + cod[1].K = 7; + viterbi_type[1] = viterbi_37; + cod[2].poly[0] = 0x6D; + cod[2].poly[1] = 0x4F; + cod[2].poly[2] = 0x57; + cod[2].tail_biting = true; + cod[2].K = 7; + viterbi_type[2] = viterbi_37; + ncods=3; + } + + max_coded_length = 0; + for (i=0;i max_coded_length) { + max_coded_length = coded_length[i]; + } + viterbi_init(&dec[i], viterbi_type[i], cod[i].poly, frame_length, cod[i].tail_biting); + printf("Convolutional Code 1/3 K=%d Tail bitting: %s\n", cod[i].K, cod[i].tail_biting ? "yes" : "no"); + } + + printf(" Frame length: %d\n", frame_length); + if (ebno_db < 100.0) { + printf(" EbNo: %.2f\n", ebno_db); + } + + data_tx = malloc(frame_length * sizeof(char)); + if (!data_tx) { + perror("malloc"); + exit(-1); + } + + for (i = 0; i < NTYPES; i++) { + data_rx[i] = malloc(frame_length * sizeof(char)); + if (!data_rx[i]) { + perror("malloc"); + exit(-1); + } + } + + symbols = malloc(max_coded_length * sizeof(char)); + if (!symbols) { + perror("malloc"); + exit(-1); + } + llr = malloc(max_coded_length * sizeof(float)); + if (!llr) { + perror("malloc"); + exit(-1); + } + llr_c = malloc(2 * max_coded_length * sizeof(char)); + if (!llr_c) { + perror("malloc"); + exit(-1); + } + + float ebno_inc, esno_db; + ebno_inc = (SNR_MAX - SNR_MIN) / SNR_POINTS; + if (ebno_db == 100.0) { + snr_points = SNR_POINTS; + for (i = 0; i < snr_points; i++) { + ebno_db = SNR_MIN + i * ebno_inc; + esno_db = ebno_db + 10 * log10((double) 1 / 3); + var[i] = sqrt(1 / (pow(10, esno_db / 10))); + varunc[i] = sqrt(1 / (pow(10, ebno_db / 10))); + } + } else { + esno_db = ebno_db + 10 * log10((double) 1 / 3); + var[0] = sqrt(1 / (pow(10, esno_db / 10))); + varunc[0] = sqrt(1 / (pow(10, ebno_db / 10))); + snr_points = 1; + } + + float Gain = 32; + + for (i = 0; i < snr_points; i++) { + frame_cnt = 0; + for (j = 0; j < NTYPES; j++) { + errors[j] = 0; + } + while (frame_cnt < nof_frames) { + + /* generate data_tx */ + for (j = 0; j < frame_length; j++) { + data_tx[j] = rand() % 2; + } + + /* uncoded BER */ + for (j = 0; j < frame_length; j++) { + llr[j] = data_tx[j] ? sqrt(2) : -sqrt(2); + } + ch_awgn_f(llr, llr, varunc[i], frame_length); + for (j = 0; j < frame_length; j++) { + data_rx[0][j] = llr[j] > 0 ? 1 : 0; + } + + /* coded BER */ + for (n=0;n expected_errors); + } + } else { + printf("\n"); + output_matlab(ber, snr_points, cod, ncods); + printf("Done\n"); + exit(0); + } } diff --git a/lte/lib/fec/test/viterbi_test.h b/lte/lib/fec/test/viterbi_test.h index c0080b6ff..b01d4b03a 100644 --- a/lte/lib/fec/test/viterbi_test.h +++ b/lte/lib/fec/test/viterbi_test.h @@ -28,44 +28,44 @@ #include typedef struct { - int n; - unsigned int s; - int len; - int k; - bool tail; - float ebno; - int errors; + int n; + unsigned int s; + int len; + int k; + bool tail; + float ebno; + int errors; }expected_errors_t; static expected_errors_t expected_errors[] = { - {1000, 1, 40, 7, true, 0.0, 5363}, - {1000, 1, 40, 7, true, 2.0, 356}, - {1000, 1, 40, 7, true, 3.0, 48}, - {1000, 1, 40, 7, true, 4.5, 0}, + {1000, 1, 40, 7, true, 0.0, 5363}, + {1000, 1, 40, 7, true, 2.0, 356}, + {1000, 1, 40, 7, true, 3.0, 48}, + {1000, 1, 40, 7, true, 4.5, 0}, - {100, 1, 1000, 7, true, 0.0, 8753}, - {100, 1, 1000, 7, true, 2.0, 350}, - {100, 1, 1000, 7, true, 3.0, 33}, - {100, 1, 1000, 7, true, 4.5, 0}, + {100, 1, 1000, 7, true, 0.0, 8753}, + {100, 1, 1000, 7, true, 2.0, 350}, + {100, 1, 1000, 7, true, 3.0, 33}, + {100, 1, 1000, 7, true, 4.5, 0}, - {-1, -1, -1, -1, true, -1.0, -1} + {-1, -1, -1, -1, true, -1.0, -1} }; int get_expected_errors(int n, unsigned int s, int len, int k, bool tail, float ebno) { - int i; - i=0; - while(expected_errors[i].n != -1) { - if (expected_errors[i].n == n - && expected_errors[i].s == s - && expected_errors[i].len == len - && expected_errors[i].k == k - && expected_errors[i].tail == tail - && expected_errors[i].ebno == ebno) { - break; - } else { - i++; - } - } - return expected_errors[i].errors; + int i; + i=0; + while(expected_errors[i].n != -1) { + if (expected_errors[i].n == n + && expected_errors[i].s == s + && expected_errors[i].len == len + && expected_errors[i].k == k + && expected_errors[i].tail == tail + && expected_errors[i].ebno == ebno) { + break; + } else { + i++; + } + } + return expected_errors[i].errors; } diff --git a/lte/lib/filter/src/filter2d.c b/lte/lib/filter/src/filter2d.c index daf11742c..6b3cc0213 100644 --- a/lte/lib/filter/src/filter2d.c +++ b/lte/lib/filter/src/filter2d.c @@ -43,113 +43,113 @@ #define idx(a, b) ((a)*(q->szfreq)+b) int filter2d_init(filter2d_t* q, float **taps, int ntime, int nfreq, int sztime, - int szfreq) { + int szfreq) { - int ret = -1; - bzero(q, sizeof(filter2d_t)); + int ret = -1; + bzero(q, sizeof(filter2d_t)); - if (matrix_init((void***)&q->taps, ntime, nfreq, sizeof(float))) { - goto free_and_exit; - } + if (matrix_init((void***)&q->taps, ntime, nfreq, sizeof(float))) { + goto free_and_exit; + } - matrix_copy((void**) q->taps, (void**) taps, ntime, nfreq, sizeof(float)); + matrix_copy((void**) q->taps, (void**) taps, ntime, nfreq, sizeof(float)); - q->output = vec_malloc((ntime+sztime)*(szfreq)*sizeof(cf_t)); - if (!q->output) { - goto free_and_exit; - } + q->output = vec_malloc((ntime+sztime)*(szfreq)*sizeof(cf_t)); + if (!q->output) { + goto free_and_exit; + } - bzero(q->output, (ntime+sztime)*(szfreq)*sizeof(cf_t)); + bzero(q->output, (ntime+sztime)*(szfreq)*sizeof(cf_t)); - q->nfreq = nfreq; - q->ntime = ntime; - q->szfreq = szfreq; - q->sztime = sztime; + q->nfreq = nfreq; + q->ntime = ntime; + q->szfreq = szfreq; + q->sztime = sztime; - ret = 0; + ret = 0; - free_and_exit: if (ret == -1) { - filter2d_free(q); - } - return ret; + free_and_exit: if (ret == -1) { + filter2d_free(q); + } + return ret; } void filter2d_free(filter2d_t *q) { - matrix_free((void**) q->taps, q->ntime); - if (q->output) { - free(q->output); - } - bzero(q, sizeof(filter2d_t)); + matrix_free((void**) q->taps, q->ntime); + if (q->output) { + free(q->output); + } + bzero(q, sizeof(filter2d_t)); } int filter2d_init_default(filter2d_t* q, int ntime, int nfreq, int sztime, - int szfreq) { + int szfreq) { - int i, j; - int ret = -1; - float **taps; + int i, j; + int ret = -1; + float **taps; - if (matrix_init((void***) &taps, ntime, nfreq, sizeof(float))) { - goto free_and_exit; - } + if (matrix_init((void***) &taps, ntime, nfreq, sizeof(float))) { + goto free_and_exit; + } - /* Compute the default 2-D interpolation mesh */ - for (i = 0; i < ntime; i++) { - for (j = 0; j < nfreq; j++) { - if (j < nfreq / 2) - taps[i][j] = (j + 1.0) / (2.0 * intceil(nfreq, 2)); + /* Compute the default 2-D interpolation mesh */ + for (i = 0; i < ntime; i++) { + for (j = 0; j < nfreq; j++) { + if (j < nfreq / 2) + taps[i][j] = (j + 1.0) / (2.0 * intceil(nfreq, 2)); - else if (j == nfreq / 2) - taps[i][j] = 0.5; + else if (j == nfreq / 2) + taps[i][j] = 0.5; - else if (j > nfreq / 2) - taps[i][j] = (nfreq - j) / (2.0 * intceil(nfreq, 2)); - } - } + else if (j > nfreq / 2) + taps[i][j] = (nfreq - j) / (2.0 * intceil(nfreq, 2)); + } + } - INFO("Using default interpolation matrix of size %dx%d\n", ntime, nfreq); - if (verbose >= VERBOSE_DEBUG) { - matrix_fprintf_f(stdout, taps, ntime, nfreq); - } + INFO("Using default interpolation matrix of size %dx%d\n", ntime, nfreq); + if (verbose >= VERBOSE_DEBUG) { + matrix_fprintf_f(stdout, taps, ntime, nfreq); + } - if (filter2d_init(q, taps, ntime, nfreq, sztime, szfreq)) { - goto free_and_exit; - } + if (filter2d_init(q, taps, ntime, nfreq, sztime, szfreq)) { + goto free_and_exit; + } - ret = 0; + ret = 0; free_and_exit: - matrix_free((void**) taps, ntime); - return ret; + matrix_free((void**) taps, ntime); + return ret; } /* Moves the last ntime symbols to the start and clears the remaining of the output. * Should be called, for instance, before filtering each OFDM frame. */ void filter2d_reset(filter2d_t *q) { - int i; - - for (i = 0; i < q->ntime; i++) { - memcpy(&q->output[idx(i,0)], &q->output[idx(q->sztime + i,0)], - sizeof(cf_t) * (q->szfreq)); - } - for (; i < q->ntime + q->sztime; i++) { - memset(&q->output[idx(i,0)], 0, sizeof(cf_t) * (q->szfreq)); - } + int i; + + for (i = 0; i < q->ntime; i++) { + memcpy(&q->output[idx(i,0)], &q->output[idx(q->sztime + i,0)], + sizeof(cf_t) * (q->szfreq)); + } + for (; i < q->ntime + q->sztime; i++) { + memset(&q->output[idx(i,0)], 0, sizeof(cf_t) * (q->szfreq)); + } } /** Adds samples x to the from the given time/freq indexes to the filter * and computes the output. */ void filter2d_add(filter2d_t *q, cf_t x, int time_idx, int freq_idx) { - int i, j; + int i, j; - int ntime = q->ntime; - int nfreq = q->nfreq; + int ntime = q->ntime; + int nfreq = q->nfreq; - for (i = 0; i < ntime; i++) { - for (j = 0; j < nfreq; j++) { - q->output[idx(i+time_idx, j+freq_idx - nfreq/2)] += x * (cf_t)(q->taps[i][j]); - } - } + for (i = 0; i < ntime; i++) { + for (j = 0; j < nfreq; j++) { + q->output[idx(i+time_idx, j+freq_idx - nfreq/2)] += x * (cf_t)(q->taps[i][j]); + } + } } diff --git a/lte/lib/io/src/binsource.c b/lte/lib/io/src/binsource.c index cea416d5f..bf8fea741 100644 --- a/lte/lib/io/src/binsource.c +++ b/lte/lib/io/src/binsource.c @@ -38,21 +38,21 @@ /* Internal functions */ static int gen_seq_buff(binsource_t* q, int nwords) { - if (q->seq_buff_nwords != nwords) { - free(q->seq_buff); - q->seq_buff_nwords = 0; - } - if (!q->seq_buff_nwords) { - q->seq_buff = malloc(nwords*sizeof(uint32_t)); - if (!q->seq_buff) { - return -1; - } - q->seq_buff_nwords = nwords; - } - for (int i=0;iseq_buff_nwords;i++) { - q->seq_buff[i] = rand_r(&q->seed); - } - return 0; + if (q->seq_buff_nwords != nwords) { + free(q->seq_buff); + q->seq_buff_nwords = 0; + } + if (!q->seq_buff_nwords) { + q->seq_buff = malloc(nwords*sizeof(uint32_t)); + if (!q->seq_buff) { + return -1; + } + q->seq_buff_nwords = nwords; + } + for (int i=0;iseq_buff_nwords;i++) { + q->seq_buff[i] = rand_r(&q->seed); + } + return 0; } /* Low-level API */ @@ -61,62 +61,62 @@ static int gen_seq_buff(binsource_t* q, int nwords) { * Initializes the binsource object. */ void binsource_init(binsource_t* q) { - bzero((void*) q,sizeof(binsource_t)); + bzero((void*) q,sizeof(binsource_t)); } /** * Destroys binsource object */ void binsource_free(binsource_t* q) { - if (q->seq_buff) { - free(q->seq_buff); - } - bzero(q, sizeof(binsource_t)); + if (q->seq_buff) { + free(q->seq_buff); + } + bzero(q, sizeof(binsource_t)); } /** * Sets a new seed */ void binsource_seed_set(binsource_t* q, unsigned int seed) { - q->seed = seed; + q->seed = seed; } /** * Sets local time as seed. */ void binsource_seed_time(binsource_t *q) { - struct timeval t1; - gettimeofday(&t1, NULL); - q->seed = t1.tv_usec * t1.tv_sec; + struct timeval t1; + gettimeofday(&t1, NULL); + q->seed = t1.tv_usec * t1.tv_sec; } /** * Generates a sequence of nbits random bits */ int binsource_cache_gen(binsource_t* q, int nbits) { - if (gen_seq_buff(q,DIV(nbits,32))) { - return -1; - } - q->seq_cache_nbits = nbits; - q->seq_cache_rp = 0; - return 0; + if (gen_seq_buff(q,DIV(nbits,32))) { + return -1; + } + q->seq_cache_nbits = nbits; + q->seq_cache_rp = 0; + return 0; } static int int_2_bits(uint32_t* src, char* dst, int nbits) { - int n; - n=nbits/32; - for (int i=0;iseq_cache_rp += int_2_bits(&q->seq_buff[q->seq_cache_rp],bits,nbits); + q->seq_cache_rp += int_2_bits(&q->seq_buff[q->seq_cache_rp],bits,nbits); } /** @@ -125,11 +125,11 @@ void binsource_cache_cpy(binsource_t* q, char *bits, int nbits) { */ int binsource_generate(binsource_t* q, char *bits, int nbits) { - if (gen_seq_buff(q,DIV(nbits,32))) { - return -1; - } - int_2_bits(q->seq_buff,bits,nbits); - return 0; + if (gen_seq_buff(q,DIV(nbits,32))) { + return -1; + } + int_2_bits(q->seq_buff,bits,nbits); + return 0; } @@ -139,42 +139,42 @@ int binsource_generate(binsource_t* q, char *bits, int nbits) { /* High-Level API */ int binsource_initialize(binsource_hl* hl) { - binsource_init(&hl->obj); - if (hl->init.seed) { - binsource_seed_set(&hl->obj,hl->init.seed); - } else { - binsource_seed_time(&hl->obj); - } + binsource_init(&hl->obj); + if (hl->init.seed) { + binsource_seed_set(&hl->obj,hl->init.seed); + } else { + binsource_seed_time(&hl->obj); + } - if (hl->init.cache_seq_nbits) { - if (binsource_cache_gen(&hl->obj,hl->init.cache_seq_nbits)) { - return -1; - } - } + if (hl->init.cache_seq_nbits) { + if (binsource_cache_gen(&hl->obj,hl->init.cache_seq_nbits)) { + return -1; + } + } - return 0; + return 0; } int binsource_work(binsource_hl* hl) { - int ret = -1; - - if (hl->init.cache_seq_nbits) { - binsource_cache_cpy(&hl->obj,hl->output,hl->ctrl_in.nbits); - ret = 0; - } else { - ret = binsource_generate(&hl->obj,hl->output,hl->ctrl_in.nbits); - } - if (!ret) { - hl->out_len = hl->ctrl_in.nbits; - } else { - hl->out_len = 0; - } - return ret; + int ret = -1; + + if (hl->init.cache_seq_nbits) { + binsource_cache_cpy(&hl->obj,hl->output,hl->ctrl_in.nbits); + ret = 0; + } else { + ret = binsource_generate(&hl->obj,hl->output,hl->ctrl_in.nbits); + } + if (!ret) { + hl->out_len = hl->ctrl_in.nbits; + } else { + hl->out_len = 0; + } + return ret; } int binsource_stop(binsource_hl* hl) { - binsource_free(&hl->obj); - return 0; + binsource_free(&hl->obj); + return 0; } diff --git a/lte/lib/io/src/filesink.c b/lte/lib/io/src/filesink.c index c03feea3a..1eddd78c2 100644 --- a/lte/lib/io/src/filesink.c +++ b/lte/lib/io/src/filesink.c @@ -35,85 +35,85 @@ #include "lte/io/filesink.h" int filesink_init(filesink_t *q, char *filename, data_type_t type) { - bzero(q, sizeof(filesink_t)); - q->f = fopen(filename, "w"); - if (!q->f) { - perror("fopen"); - return -1; - } - q->type = type; - return 0; + bzero(q, sizeof(filesink_t)); + q->f = fopen(filename, "w"); + if (!q->f) { + perror("fopen"); + return -1; + } + q->type = type; + return 0; } void filesink_free(filesink_t *q) { - if (q->f) { - fclose(q->f); - } - bzero(q, sizeof(filesink_t)); + if (q->f) { + fclose(q->f); + } + bzero(q, sizeof(filesink_t)); } int filesink_write(filesink_t *q, void *buffer, int nsamples) { - int i; - float *fbuf = (float*) buffer; - _Complex float *cbuf = (_Complex float*) buffer; - _Complex short *sbuf = (_Complex short*) buffer; - int size; + int i; + float *fbuf = (float*) buffer; + _Complex float *cbuf = (_Complex float*) buffer; + _Complex short *sbuf = (_Complex short*) buffer; + int size; - switch(q->type) { - case FLOAT: - for (i=0;if,"%g\n",fbuf[i]); - } - break; - case COMPLEX_FLOAT: - for (i=0;i= 0) - fprintf(q->f,"%g+%gi\n",__real__ cbuf[i],__imag__ cbuf[i]); - else - fprintf(q->f,"%g-%gi\n",__real__ cbuf[i],fabsf(__imag__ cbuf[i])); - } - break; - case COMPLEX_SHORT: - for (i=0;i= 0) - fprintf(q->f,"%hd+%hdi\n",__real__ sbuf[i],__imag__ sbuf[i]); - else - fprintf(q->f,"%hd-%hdi\n",__real__ sbuf[i],(short) abs(__imag__ sbuf[i])); - } - break; - case FLOAT_BIN: - case COMPLEX_FLOAT_BIN: - case COMPLEX_SHORT_BIN: - if (q->type == FLOAT_BIN) { - size = sizeof(float); - } else if (q->type == COMPLEX_FLOAT_BIN) { - size = sizeof(_Complex float); - } else if (q->type == COMPLEX_SHORT_BIN) { - size = sizeof(_Complex short); - } - return fwrite(buffer, size, nsamples, q->f); - break; - default: - i = -1; - break; - } - return i; + switch(q->type) { + case FLOAT: + for (i=0;if,"%g\n",fbuf[i]); + } + break; + case COMPLEX_FLOAT: + for (i=0;i= 0) + fprintf(q->f,"%g+%gi\n",__real__ cbuf[i],__imag__ cbuf[i]); + else + fprintf(q->f,"%g-%gi\n",__real__ cbuf[i],fabsf(__imag__ cbuf[i])); + } + break; + case COMPLEX_SHORT: + for (i=0;i= 0) + fprintf(q->f,"%hd+%hdi\n",__real__ sbuf[i],__imag__ sbuf[i]); + else + fprintf(q->f,"%hd-%hdi\n",__real__ sbuf[i],(short) abs(__imag__ sbuf[i])); + } + break; + case FLOAT_BIN: + case COMPLEX_FLOAT_BIN: + case COMPLEX_SHORT_BIN: + if (q->type == FLOAT_BIN) { + size = sizeof(float); + } else if (q->type == COMPLEX_FLOAT_BIN) { + size = sizeof(_Complex float); + } else if (q->type == COMPLEX_SHORT_BIN) { + size = sizeof(_Complex short); + } + return fwrite(buffer, size, nsamples, q->f); + break; + default: + i = -1; + break; + } + return i; } int filesink_initialize(filesink_hl* h) { - return filesink_init(&h->obj, h->init.file_name, h->init.data_type); + return filesink_init(&h->obj, h->init.file_name, h->init.data_type); } int filesink_work(filesink_hl* h) { - if (filesink_write(&h->obj, h->input, h->in_len)<0) { - return -1; - } - return 0; + if (filesink_write(&h->obj, h->input, h->in_len)<0) { + return -1; + } + return 0; } int filesink_stop(filesink_hl* h) { - filesink_free(&h->obj); - return 0; + filesink_free(&h->obj); + return 0; } diff --git a/lte/lib/io/src/filesource.c b/lte/lib/io/src/filesource.c index d2dd1217b..3e789d4fe 100644 --- a/lte/lib/io/src/filesource.c +++ b/lte/lib/io/src/filesource.c @@ -33,104 +33,104 @@ #include "lte/io/filesource.h" int filesource_init(filesource_t *q, char *filename, data_type_t type) { - bzero(q, sizeof(filesource_t)); - q->f = fopen(filename, "r"); - if (!q->f) { - perror("fopen"); - return -1; - } - q->type = type; - return 0; + bzero(q, sizeof(filesource_t)); + q->f = fopen(filename, "r"); + if (!q->f) { + perror("fopen"); + return -1; + } + q->type = type; + return 0; } void filesource_free(filesource_t *q) { - if (q->f) { - fclose(q->f); - } - bzero(q, sizeof(filesource_t)); + if (q->f) { + fclose(q->f); + } + bzero(q, sizeof(filesource_t)); } void filesource_seek(filesource_t *q, int pos) { - fseek(q->f, pos, SEEK_SET); + fseek(q->f, pos, SEEK_SET); } int read_complex_f(FILE *f, _Complex float *y) { - char in_str[64]; - _Complex float x; - if (NULL == fgets(in_str, 64, f)) { - return -1; - } else { - if (index(in_str, 'i') || index(in_str, 'j')) { - sscanf(in_str,"%f%fi",&(__real__ x),&(__imag__ x)); - } else { - __imag__ x = 0; - sscanf(in_str,"%f",&(__real__ x)); - } - *y = x; - return 0; - } + char in_str[64]; + _Complex float x; + if (NULL == fgets(in_str, 64, f)) { + return -1; + } else { + if (index(in_str, 'i') || index(in_str, 'j')) { + sscanf(in_str,"%f%fi",&(__real__ x),&(__imag__ x)); + } else { + __imag__ x = 0; + sscanf(in_str,"%f",&(__real__ x)); + } + *y = x; + return 0; + } } int filesource_read(filesource_t *q, void *buffer, int nsamples) { - int i; - float *fbuf = (float*) buffer; - _Complex float *cbuf = (_Complex float*) buffer; - _Complex short *sbuf = (_Complex short*) buffer; - int size; + int i; + float *fbuf = (float*) buffer; + _Complex float *cbuf = (_Complex float*) buffer; + _Complex short *sbuf = (_Complex short*) buffer; + int size; - switch(q->type) { - case FLOAT: - for (i=0;if,"%g\n",&fbuf[i])) - break; - } - break; - case COMPLEX_FLOAT: - for (i=0;if, &cbuf[i])) { - break; - } - } - break; - case COMPLEX_SHORT: - for (i=0;if,"%hd%hdi\n",&(__real__ sbuf[i]),&(__imag__ sbuf[i]))) - break; - } - break; - case FLOAT_BIN: - case COMPLEX_FLOAT_BIN: - case COMPLEX_SHORT_BIN: - if (q->type == FLOAT_BIN) { - size = sizeof(float); - } else if (q->type == COMPLEX_FLOAT_BIN) { - size = sizeof(_Complex float); - } else if (q->type == COMPLEX_SHORT_BIN) { - size = sizeof(_Complex short); - } - return fread(buffer, size, nsamples, q->f); - break; - default: - i = -1; - break; - } - return i; + switch(q->type) { + case FLOAT: + for (i=0;if,"%g\n",&fbuf[i])) + break; + } + break; + case COMPLEX_FLOAT: + for (i=0;if, &cbuf[i])) { + break; + } + } + break; + case COMPLEX_SHORT: + for (i=0;if,"%hd%hdi\n",&(__real__ sbuf[i]),&(__imag__ sbuf[i]))) + break; + } + break; + case FLOAT_BIN: + case COMPLEX_FLOAT_BIN: + case COMPLEX_SHORT_BIN: + if (q->type == FLOAT_BIN) { + size = sizeof(float); + } else if (q->type == COMPLEX_FLOAT_BIN) { + size = sizeof(_Complex float); + } else if (q->type == COMPLEX_SHORT_BIN) { + size = sizeof(_Complex short); + } + return fread(buffer, size, nsamples, q->f); + break; + default: + i = -1; + break; + } + return i; } int filesource_initialize(filesource_hl* h) { - return filesource_init(&h->obj, h->init.file_name, h->init.data_type); + return filesource_init(&h->obj, h->init.file_name, h->init.data_type); } int filesource_work(filesource_hl* h) { - h->out_len = filesource_read(&h->obj, h->output, h->ctrl_in.nsamples); - if (h->out_len < 0) { - return -1; - } - return 0; + h->out_len = filesource_read(&h->obj, h->output, h->ctrl_in.nsamples); + if (h->out_len < 0) { + return -1; + } + return 0; } int filesource_stop(filesource_hl* h) { - filesource_free(&h->obj); - return 0; + filesource_free(&h->obj); + return 0; } diff --git a/lte/lib/io/src/udpsink.c b/lte/lib/io/src/udpsink.c index 52884407f..d2d59daa7 100644 --- a/lte/lib/io/src/udpsink.c +++ b/lte/lib/io/src/udpsink.c @@ -38,65 +38,65 @@ #include "lte/io/udpsink.h" int udpsink_init(udpsink_t *q, char *address, int port, data_type_t type) { - bzero(q, sizeof(udpsink_t)); + bzero(q, sizeof(udpsink_t)); - q->sockfd=socket(AF_INET,SOCK_DGRAM,0); + q->sockfd=socket(AF_INET,SOCK_DGRAM,0); - q->servaddr.sin_family = AF_INET; - q->servaddr.sin_addr.s_addr=inet_addr(address); - q->servaddr.sin_port=htons(port); + q->servaddr.sin_family = AF_INET; + q->servaddr.sin_addr.s_addr=inet_addr(address); + q->servaddr.sin_port=htons(port); - q->type = type; - return 0; + q->type = type; + return 0; } void udpsink_free(udpsink_t *q) { - if (q->sockfd) { - close(q->sockfd); - } - bzero(q, sizeof(udpsink_t)); + if (q->sockfd) { + close(q->sockfd); + } + bzero(q, sizeof(udpsink_t)); } int udpsink_write(udpsink_t *q, void *buffer, int nsamples) { - int size; + int size; - switch(q->type) { - case FLOAT: - case COMPLEX_FLOAT: - case COMPLEX_SHORT: - fprintf(stderr, "Not implemented\n"); - return -1; - case FLOAT_BIN: - case COMPLEX_FLOAT_BIN: - case COMPLEX_SHORT_BIN: - if (q->type == FLOAT_BIN) { - size = sizeof(float); - } else if (q->type == COMPLEX_FLOAT_BIN) { - size = sizeof(_Complex float); - } else if (q->type == COMPLEX_SHORT_BIN) { - size = sizeof(_Complex short); - } - return sendto(q->sockfd, buffer, nsamples * size, 0, - &q->servaddr, sizeof(struct sockaddr_in)); - break; - } - return -1; + switch(q->type) { + case FLOAT: + case COMPLEX_FLOAT: + case COMPLEX_SHORT: + fprintf(stderr, "Not implemented\n"); + return -1; + case FLOAT_BIN: + case COMPLEX_FLOAT_BIN: + case COMPLEX_SHORT_BIN: + if (q->type == FLOAT_BIN) { + size = sizeof(float); + } else if (q->type == COMPLEX_FLOAT_BIN) { + size = sizeof(_Complex float); + } else if (q->type == COMPLEX_SHORT_BIN) { + size = sizeof(_Complex short); + } + return sendto(q->sockfd, buffer, nsamples * size, 0, + &q->servaddr, sizeof(struct sockaddr_in)); + break; + } + return -1; } int udpsink_initialize(udpsink_hl* h) { - return udpsink_init(&h->obj, h->init.address, h->init.port, h->init.data_type); + return udpsink_init(&h->obj, h->init.address, h->init.port, h->init.data_type); } int udpsink_work(udpsink_hl* h) { - if (udpsink_write(&h->obj, h->input, h->in_len)<0) { - return -1; - } - return 0; + if (udpsink_write(&h->obj, h->input, h->in_len)<0) { + return -1; + } + return 0; } int udpsink_stop(udpsink_hl* h) { - udpsink_free(&h->obj); - return 0; + udpsink_free(&h->obj); + return 0; } diff --git a/lte/lib/io/src/udpsource.c b/lte/lib/io/src/udpsource.c index 846d08608..2a3bc2344 100644 --- a/lte/lib/io/src/udpsource.c +++ b/lte/lib/io/src/udpsource.c @@ -36,65 +36,65 @@ #include "lte/io/udpsource.h" int udpsource_init(udpsource_t *q, char *address, int port, data_type_t type) { - bzero(q, sizeof(udpsource_t)); + bzero(q, sizeof(udpsource_t)); - q->sockfd=socket(AF_INET,SOCK_DGRAM,0); + q->sockfd=socket(AF_INET,SOCK_DGRAM,0); - q->servaddr.sin_family = AF_INET; - q->servaddr.sin_addr.s_addr=inet_addr(address); - q->servaddr.sin_port=htons(port); - bind(q->sockfd,(struct sockaddr *)&q->servaddr,sizeof(struct sockaddr_in)); + q->servaddr.sin_family = AF_INET; + q->servaddr.sin_addr.s_addr=inet_addr(address); + q->servaddr.sin_port=htons(port); + bind(q->sockfd,(struct sockaddr *)&q->servaddr,sizeof(struct sockaddr_in)); - q->type = type; - return 0; + q->type = type; + return 0; } void udpsource_free(udpsource_t *q) { - if (q->sockfd) { - close(q->sockfd); - } - bzero(q, sizeof(udpsource_t)); + if (q->sockfd) { + close(q->sockfd); + } + bzero(q, sizeof(udpsource_t)); } int udpsource_read(udpsource_t *q, void *buffer, int nsamples) { - int size; + int size; - switch(q->type) { - case FLOAT: - case COMPLEX_FLOAT: - case COMPLEX_SHORT: - fprintf(stderr, "Not implemented\n"); - return -1; - case FLOAT_BIN: - case COMPLEX_FLOAT_BIN: - case COMPLEX_SHORT_BIN: - if (q->type == FLOAT_BIN) { - size = sizeof(float); - } else if (q->type == COMPLEX_FLOAT_BIN) { - size = sizeof(_Complex float); - } else if (q->type == COMPLEX_SHORT_BIN) { - size = sizeof(_Complex short); - } - return recv(q->sockfd, buffer, size * nsamples, 0); - break; - } - return -1; + switch(q->type) { + case FLOAT: + case COMPLEX_FLOAT: + case COMPLEX_SHORT: + fprintf(stderr, "Not implemented\n"); + return -1; + case FLOAT_BIN: + case COMPLEX_FLOAT_BIN: + case COMPLEX_SHORT_BIN: + if (q->type == FLOAT_BIN) { + size = sizeof(float); + } else if (q->type == COMPLEX_FLOAT_BIN) { + size = sizeof(_Complex float); + } else if (q->type == COMPLEX_SHORT_BIN) { + size = sizeof(_Complex short); + } + return recv(q->sockfd, buffer, size * nsamples, 0); + break; + } + return -1; } int udpsource_initialize(udpsource_hl* h) { - return udpsource_init(&h->obj, h->init.address, h->init.port, h->init.data_type); + return udpsource_init(&h->obj, h->init.address, h->init.port, h->init.data_type); } int udpsource_work(udpsource_hl* h) { - h->out_len = udpsource_read(&h->obj, h->output, h->ctrl_in.nsamples); - if (h->out_len < 0) { - return -1; - } - return 0; + h->out_len = udpsource_read(&h->obj, h->output, h->ctrl_in.nsamples); + if (h->out_len < 0) { + return -1; + } + return 0; } int udpsource_stop(udpsource_hl* h) { - udpsource_free(&h->obj); - return 0; + udpsource_free(&h->obj); + return 0; } diff --git a/lte/lib/mimo/src/layermap.c b/lte/lib/mimo/src/layermap.c index b178b953d..316c8fe79 100644 --- a/lte/lib/mimo/src/layermap.c +++ b/lte/lib/mimo/src/layermap.c @@ -36,41 +36,41 @@ int layermap_single(cf_t *d, cf_t *x, int nof_symbols) { - memcpy(x, d, sizeof(cf_t) * nof_symbols); - return nof_symbols; + memcpy(x, d, sizeof(cf_t) * nof_symbols); + return nof_symbols; } int layermap_diversity(cf_t *d, cf_t *x[MAX_LAYERS], int nof_layers, int nof_symbols) { - int i, j; - for (i=0;i MAX_CODEWORDS) { - fprintf(stderr, "Maximum number of codewords is %d (nof_cw=%d)\n", MAX_CODEWORDS, nof_cw); - return -1; - } - if (nof_layers > MAX_LAYERS) { - fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers); - return -1; - } - if (nof_layers < nof_cw) { - fprintf(stderr, "Number of codewords must be lower or equal than number of layers\n"); - return -1; - } - - switch(type) { - case SINGLE_ANTENNA: - if (nof_cw == 1 && nof_layers == 1) { - return layermap_single(x[0], d[0], nof_symbols[0]); - } else { - fprintf(stderr, "Number of codewords and layers must be 1 for transmission on single antenna ports\n"); - return -1; - } - break; - case TX_DIVERSITY: - if (nof_cw == 1) { - if (nof_layers == 2 || nof_layers == 4) { - return layermap_diversity(d[0], x, nof_layers, nof_symbols[0]); - } else { - fprintf(stderr, "Number of layers must be 2 or 4 for transmit diversity\n"); - return -1; - } - } else { - fprintf(stderr, "Number of codewords must be 1 for transmit diversity\n"); - return -1; - } - break; - case SPATIAL_MULTIPLEX: - return layermap_multiplex(d, x, nof_cw, nof_layers, nof_symbols); - break; - } - return 0; + int nof_symbols[MAX_CODEWORDS], lte_mimo_type_t type) { + + if (nof_cw > MAX_CODEWORDS) { + fprintf(stderr, "Maximum number of codewords is %d (nof_cw=%d)\n", MAX_CODEWORDS, nof_cw); + return -1; + } + if (nof_layers > MAX_LAYERS) { + fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers); + return -1; + } + if (nof_layers < nof_cw) { + fprintf(stderr, "Number of codewords must be lower or equal than number of layers\n"); + return -1; + } + + switch(type) { + case SINGLE_ANTENNA: + if (nof_cw == 1 && nof_layers == 1) { + return layermap_single(x[0], d[0], nof_symbols[0]); + } else { + fprintf(stderr, "Number of codewords and layers must be 1 for transmission on single antenna ports\n"); + return -1; + } + break; + case TX_DIVERSITY: + if (nof_cw == 1) { + if (nof_layers == 2 || nof_layers == 4) { + return layermap_diversity(d[0], x, nof_layers, nof_symbols[0]); + } else { + fprintf(stderr, "Number of layers must be 2 or 4 for transmit diversity\n"); + return -1; + } + } else { + fprintf(stderr, "Number of codewords must be 1 for transmit diversity\n"); + return -1; + } + break; + case SPATIAL_MULTIPLEX: + return layermap_multiplex(d, x, nof_cw, nof_layers, nof_symbols); + break; + } + return 0; } @@ -131,34 +131,34 @@ int layermap_type(cf_t *d[MAX_CODEWORDS], cf_t *x[MAX_LAYERS], int nof_cw, int n int layerdemap_single(cf_t *x, cf_t *d, int nof_symbols) { - memcpy(d, x, sizeof(cf_t) * nof_symbols); - return nof_symbols; + memcpy(d, x, sizeof(cf_t) * nof_symbols); + return nof_symbols; } int layerdemap_diversity(cf_t *x[MAX_LAYERS], cf_t *d, int nof_layers, int nof_layer_symbols) { - int i, j; - for (i=0;i MAX_CODEWORDS) { - fprintf(stderr, "Maximum number of codewords is %d (nof_cw=%d)\n", MAX_CODEWORDS, nof_cw); - return -1; - } - if (nof_layers > MAX_LAYERS) { - fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers); - return -1; - } - if (nof_layers < nof_cw) { - fprintf(stderr, "Number of codewords must be lower or equal than number of layers\n"); - return -1; - } - - switch(type) { - case SINGLE_ANTENNA: - if (nof_cw == 1 && nof_layers == 1) { - nof_symbols[0] = layerdemap_single(x[0], d[0], nof_layer_symbols); - nof_symbols[1] = 0; - } else { - fprintf(stderr, "Number of codewords and layers must be 1 for transmission on single antenna ports\n"); - return -1; - } - break; - case TX_DIVERSITY: - if (nof_cw == 1) { - if (nof_layers == 2 || nof_layers == 4) { - nof_symbols[0] = layerdemap_diversity(x, d[0], nof_layers, nof_layer_symbols); - nof_symbols[1] = 0; - } else { - fprintf(stderr, "Number of layers must be 2 or 4 for transmit diversity\n"); - return -1; - } - } else { - fprintf(stderr, "Number of codewords must be 1 for transmit diversity\n"); - return -1; - } - break; - case SPATIAL_MULTIPLEX: - return layerdemap_multiplex(x, d, nof_layers, nof_cw, nof_layer_symbols, nof_symbols); - break; - } - return 0; + int nof_layer_symbols, int nof_symbols[MAX_CODEWORDS], lte_mimo_type_t type) { + + if (nof_cw > MAX_CODEWORDS) { + fprintf(stderr, "Maximum number of codewords is %d (nof_cw=%d)\n", MAX_CODEWORDS, nof_cw); + return -1; + } + if (nof_layers > MAX_LAYERS) { + fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers); + return -1; + } + if (nof_layers < nof_cw) { + fprintf(stderr, "Number of codewords must be lower or equal than number of layers\n"); + return -1; + } + + switch(type) { + case SINGLE_ANTENNA: + if (nof_cw == 1 && nof_layers == 1) { + nof_symbols[0] = layerdemap_single(x[0], d[0], nof_layer_symbols); + nof_symbols[1] = 0; + } else { + fprintf(stderr, "Number of codewords and layers must be 1 for transmission on single antenna ports\n"); + return -1; + } + break; + case TX_DIVERSITY: + if (nof_cw == 1) { + if (nof_layers == 2 || nof_layers == 4) { + nof_symbols[0] = layerdemap_diversity(x, d[0], nof_layers, nof_layer_symbols); + nof_symbols[1] = 0; + } else { + fprintf(stderr, "Number of layers must be 2 or 4 for transmit diversity\n"); + return -1; + } + } else { + fprintf(stderr, "Number of codewords must be 1 for transmit diversity\n"); + return -1; + } + break; + case SPATIAL_MULTIPLEX: + return layerdemap_multiplex(x, d, nof_layers, nof_cw, nof_layer_symbols, nof_symbols); + break; + } + return 0; } diff --git a/lte/lib/mimo/src/precoding.c b/lte/lib/mimo/src/precoding.c index 8cc033233..f6ed753aa 100644 --- a/lte/lib/mimo/src/precoding.c +++ b/lte/lib/mimo/src/precoding.c @@ -38,178 +38,178 @@ #include "lte/utils/vector.h" int precoding_single(cf_t *x, cf_t *y, int nof_symbols) { - memcpy(y, x, nof_symbols * sizeof(cf_t)); - return nof_symbols; + memcpy(y, x, nof_symbols * sizeof(cf_t)); + return nof_symbols; } int precoding_diversity(cf_t *x[MAX_LAYERS], cf_t *y[MAX_PORTS], int nof_ports, int nof_symbols) { - int i; - if (nof_ports == 2) { - /* FIXME: Use VOLK here */ - for (i=0;i MAX_PORTS) { - fprintf(stderr, "Maximum number of ports is %d (nof_ports=%d)\n", MAX_PORTS, nof_ports); - return -1; - } - if (nof_layers > MAX_LAYERS) { - fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers); - return -1; - } - - switch(type) { - case SINGLE_ANTENNA: - if (nof_ports == 1 && nof_layers == 1) { - return precoding_single(x[0], y[0], nof_symbols); - } else { - fprintf(stderr, "Number of ports and layers must be 1 for transmission on single antenna ports\n"); - return -1; - } - break; - case TX_DIVERSITY: - if (nof_ports == nof_layers) { - return precoding_diversity(x, y, nof_ports, nof_symbols); - } else { - fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n"); - return -1; - } - case SPATIAL_MULTIPLEX: - fprintf(stderr, "Spatial multiplexing not supported\n"); - return -1; - } - return 0; + lte_mimo_type_t type) { + + if (nof_ports > MAX_PORTS) { + fprintf(stderr, "Maximum number of ports is %d (nof_ports=%d)\n", MAX_PORTS, nof_ports); + return -1; + } + if (nof_layers > MAX_LAYERS) { + fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers); + return -1; + } + + switch(type) { + case SINGLE_ANTENNA: + if (nof_ports == 1 && nof_layers == 1) { + return precoding_single(x[0], y[0], nof_symbols); + } else { + fprintf(stderr, "Number of ports and layers must be 1 for transmission on single antenna ports\n"); + return -1; + } + break; + case TX_DIVERSITY: + if (nof_ports == nof_layers) { + return precoding_diversity(x, y, nof_ports, nof_symbols); + } else { + fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n"); + return -1; + } + case SPATIAL_MULTIPLEX: + fprintf(stderr, "Spatial multiplexing not supported\n"); + return -1; + } + return 0; } /* ZF detector */ int predecoding_single_zf(cf_t *y, cf_t *ce, cf_t *x, int nof_symbols) { - vec_div_ccc(y, ce, x, nof_symbols); - return nof_symbols; + vec_div_ccc(y, ce, x, nof_symbols); + return nof_symbols; } /* ZF detector */ int predecoding_diversity_zf(cf_t *y[MAX_PORTS], cf_t *ce[MAX_PORTS], - cf_t *x[MAX_LAYERS], int nof_ports, int nof_symbols) { - int i; - cf_t h0, h1, h2, h3, r0, r1, r2, r3; - float hh, hh02, hh13; - if (nof_ports == 2) { - /* TODO: Use VOLK here */ - for (i=0;i MAX_PORTS) { - fprintf(stderr, "Maximum number of ports is %d (nof_ports=%d)\n", MAX_PORTS, nof_ports); - return -1; - } - if (nof_layers > MAX_LAYERS) { - fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers); - return -1; - } - - - switch(type) { - case SINGLE_ANTENNA: - if (nof_ports == 1 && nof_layers == 1) { - return predecoding_single_zf(y[0], ce[0], x[0], nof_symbols); - } else{ - fprintf(stderr, "Number of ports and layers must be 1 for transmission on single antenna ports\n"); - return -1; - } - break; - case TX_DIVERSITY: - if (nof_ports == nof_layers) { - return predecoding_diversity_zf(y, ce, x, nof_ports, nof_symbols); - } else { - fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n"); - return -1; - } - break; - case SPATIAL_MULTIPLEX: - fprintf(stderr, "Spatial multiplexing not supported\n"); - return -1; - } - return 0; + cf_t *x[MAX_LAYERS], int nof_ports, int nof_layers, int nof_symbols, lte_mimo_type_t type) { + + if (nof_ports > MAX_PORTS) { + fprintf(stderr, "Maximum number of ports is %d (nof_ports=%d)\n", MAX_PORTS, nof_ports); + return -1; + } + if (nof_layers > MAX_LAYERS) { + fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers); + return -1; + } + + + switch(type) { + case SINGLE_ANTENNA: + if (nof_ports == 1 && nof_layers == 1) { + return predecoding_single_zf(y[0], ce[0], x[0], nof_symbols); + } else{ + fprintf(stderr, "Number of ports and layers must be 1 for transmission on single antenna ports\n"); + return -1; + } + break; + case TX_DIVERSITY: + if (nof_ports == nof_layers) { + return predecoding_diversity_zf(y, ce, x, nof_ports, nof_symbols); + } else { + fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n"); + return -1; + } + break; + case SPATIAL_MULTIPLEX: + fprintf(stderr, "Spatial multiplexing not supported\n"); + return -1; + } + return 0; } diff --git a/lte/lib/mimo/test/layermap_test.c b/lte/lib/mimo/test/layermap_test.c index 0c701cc4b..cb85765ed 100644 --- a/lte/lib/mimo/test/layermap_test.c +++ b/lte/lib/mimo/test/layermap_test.c @@ -41,123 +41,123 @@ int nof_cw = 1, nof_layers = 1; char *mimo_type_name = NULL; void usage(char *prog) { - printf("Usage: %s -m [single|diversity|multiplex] -c [nof_cw] -l [nof_layers]\n", prog); - printf("\t-n num_symbols [Default %d]\n", nof_symbols); + printf("Usage: %s -m [single|diversity|multiplex] -c [nof_cw] -l [nof_layers]\n", prog); + printf("\t-n num_symbols [Default %d]\n", nof_symbols); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "mcln")) != -1) { - switch (opt) { - case 'n': - nof_symbols = atoi(argv[optind]); - break; - case 'c': - nof_cw = atoi(argv[optind]); - break; - case 'l': - nof_layers = atoi(argv[optind]); - break; - case 'm': - mimo_type_name = argv[optind]; - break; - default: - usage(argv[0]); - exit(-1); - } - } - if (!mimo_type_name) { - usage(argv[0]); - exit(-1); - } + int opt; + while ((opt = getopt(argc, argv, "mcln")) != -1) { + switch (opt) { + case 'n': + nof_symbols = atoi(argv[optind]); + break; + case 'c': + nof_cw = atoi(argv[optind]); + break; + case 'l': + nof_layers = atoi(argv[optind]); + break; + case 'm': + mimo_type_name = argv[optind]; + break; + default: + usage(argv[0]); + exit(-1); + } + } + if (!mimo_type_name) { + usage(argv[0]); + exit(-1); + } } int main(int argc, char **argv) { - int i, j, num_errors, symbols_layer; - cf_t *d[MAX_CODEWORDS], *x[MAX_LAYERS], *dp[MAX_CODEWORDS]; - lte_mimo_type_t type; - int nof_symb_cw[MAX_CODEWORDS]; - int n[2]; - - parse_args(argc, argv); - - if (lte_str2mimotype(mimo_type_name, &type)) { - fprintf(stderr, "Invalid MIMO type %s\n", mimo_type_name); - exit(-1); - } - - if (nof_cw > 1) { - n[0] = nof_layers / nof_cw; - n[1] = nof_layers - n[0]; - nof_symb_cw[0] = nof_symbols * n[0]; - nof_symb_cw[1] = nof_symbols * n[1]; - } else { - nof_symb_cw[0] = nof_symbols; - nof_symb_cw[1] = 0; - } - - for (i=0;i 1) { + n[0] = nof_layers / nof_cw; + n[1] = nof_layers - n[0]; + nof_symb_cw[0] = nof_symbols * n[0]; + nof_symb_cw[1] = nof_symbols * n[1]; + } else { + nof_symb_cw[0] = nof_symbols; + nof_symb_cw[1] = 0; + } + + for (i=0;i MAX_PORTS || nof_layers > MAX_LAYERS) { - fprintf(stderr, "Invalid number of layers or ports\n"); - exit(-1); - } - - if (lte_str2mimotype(mimo_type_name, &type)) { - fprintf(stderr, "Invalid MIMO type %s\n", mimo_type_name); - exit(-1); - } - - for (i=0;i MSE_THRESHOLD) { - printf("MSE: %f\n", mse); - exit(-1); - } else { - printf("Ok\n"); - exit(0); - } + int i, j; + float mse; + cf_t *x[MAX_LAYERS], *r[MAX_PORTS], *y[MAX_PORTS], *h[MAX_PORTS], *xr[MAX_LAYERS]; + lte_mimo_type_t type; + + parse_args(argc, argv); + + if (nof_ports > MAX_PORTS || nof_layers > MAX_LAYERS) { + fprintf(stderr, "Invalid number of layers or ports\n"); + exit(-1); + } + + if (lte_str2mimotype(mimo_type_name, &type)) { + fprintf(stderr, "Invalid MIMO type %s\n", mimo_type_name); + exit(-1); + } + + for (i=0;i MSE_THRESHOLD) { + printf("MSE: %f\n", mse); + exit(-1); + } else { + printf("Ok\n"); + exit(0); + } } diff --git a/lte/lib/modem/src/demod_hard.c b/lte/lib/modem/src/demod_hard.c index a251cdf39..e341e47d7 100644 --- a/lte/lib/modem/src/demod_hard.c +++ b/lte/lib/modem/src/demod_hard.c @@ -34,53 +34,53 @@ void demod_hard_init(demod_hard_t* q) { - bzero((void*) q, sizeof(demod_hard_t)); + bzero((void*) q, sizeof(demod_hard_t)); } void demod_hard_table_set(demod_hard_t* q, enum modem_std table) { - q->table = table; + q->table = table; } int demod_hard_demodulate(demod_hard_t* q, cf_t* symbols, char *bits, int nsymbols) { - int nbits=-1; - switch(q->table) { - case LTE_BPSK: - hard_bpsk_demod(symbols,bits,nsymbols); - nbits=nsymbols; - break; - case LTE_QPSK: - hard_qpsk_demod(symbols,bits,nsymbols); - nbits=nsymbols*2; - break; - case LTE_QAM16: - hard_qam16_demod(symbols,bits,nsymbols); - nbits=nsymbols*4; - break; - case LTE_QAM64: - hard_qam64_demod(symbols,bits,nsymbols); - nbits=nsymbols*6; - break; - } - return nbits; + int nbits=-1; + switch(q->table) { + case LTE_BPSK: + hard_bpsk_demod(symbols,bits,nsymbols); + nbits=nsymbols; + break; + case LTE_QPSK: + hard_qpsk_demod(symbols,bits,nsymbols); + nbits=nsymbols*2; + break; + case LTE_QAM16: + hard_qam16_demod(symbols,bits,nsymbols); + nbits=nsymbols*4; + break; + case LTE_QAM64: + hard_qam64_demod(symbols,bits,nsymbols); + nbits=nsymbols*6; + break; + } + return nbits; } int demod_hard_initialize(demod_hard_hl* hl) { - demod_hard_init(&hl->obj); - demod_hard_table_set(&hl->obj,hl->init.std); + demod_hard_init(&hl->obj); + demod_hard_table_set(&hl->obj,hl->init.std); - return 0; + return 0; } int demod_hard_work(demod_hard_hl* hl) { - int ret = demod_hard_demodulate(&hl->obj,hl->input,hl->output,hl->in_len); - hl->out_len = ret; - return 0; + int ret = demod_hard_demodulate(&hl->obj,hl->input,hl->output,hl->in_len); + hl->out_len = ret; + return 0; } int demod_hard_stop(demod_hard_hl* hl) { - return 0; + return 0; } diff --git a/lte/lib/modem/src/demod_soft.c b/lte/lib/modem/src/demod_soft.c index 3b42467e3..1aaf81227 100644 --- a/lte/lib/modem/src/demod_soft.c +++ b/lte/lib/modem/src/demod_soft.c @@ -35,58 +35,58 @@ void demod_soft_init(demod_soft_t *q) { - bzero((void*)q,sizeof(demod_soft_t)); + bzero((void*)q,sizeof(demod_soft_t)); } void demod_soft_table_set(demod_soft_t *q, modem_table_t *table) { - q->table = table; + q->table = table; } void demod_soft_alg_set(demod_soft_t *q, enum alg alg_type) { - q->alg_type = alg_type; + q->alg_type = alg_type; } void demod_soft_sigma_set(demod_soft_t *q, float sigma) { - q->sigma = 2*sigma; + q->sigma = 2*sigma; } int demod_soft_demodulate(demod_soft_t *q, const cf_t* symbols, float* llr, int nsymbols) { - switch(q->alg_type) { - case EXACT: - llr_exact(symbols, llr, nsymbols, q->table->nsymbols, q->table->nbits_x_symbol, - q->table->symbol_table, q->table->soft_table.idx, q->sigma); - break; - case APPROX: - llr_approx(symbols, llr, nsymbols, q->table->nsymbols, q->table->nbits_x_symbol, - q->table->symbol_table, q->table->soft_table.idx, q->sigma); - break; - } - return nsymbols*q->table->nbits_x_symbol; + switch(q->alg_type) { + case EXACT: + llr_exact(symbols, llr, nsymbols, q->table->nsymbols, q->table->nbits_x_symbol, + q->table->symbol_table, q->table->soft_table.idx, q->sigma); + break; + case APPROX: + llr_approx(symbols, llr, nsymbols, q->table->nsymbols, q->table->nbits_x_symbol, + q->table->symbol_table, q->table->soft_table.idx, q->sigma); + break; + } + return nsymbols*q->table->nbits_x_symbol; } /* High-Level API */ int demod_soft_initialize(demod_soft_hl* hl) { - modem_table_init(&hl->table); - if (modem_table_std(&hl->table,hl->init.std,true)) { - return -1; - } - demod_soft_init(&hl->obj); - hl->obj.table = &hl->table; + modem_table_init(&hl->table); + if (modem_table_std(&hl->table,hl->init.std,true)) { + return -1; + } + demod_soft_init(&hl->obj); + hl->obj.table = &hl->table; - return 0; + return 0; } int demod_soft_work(demod_soft_hl* hl) { - hl->obj.sigma = hl->ctrl_in.sigma; - hl->obj.alg_type = hl->ctrl_in.alg_type; - int ret = demod_soft_demodulate(&hl->obj,hl->input,hl->output,hl->in_len); - hl->out_len = ret; - return 0; + hl->obj.sigma = hl->ctrl_in.sigma; + hl->obj.alg_type = hl->ctrl_in.alg_type; + int ret = demod_soft_demodulate(&hl->obj,hl->input,hl->output,hl->in_len); + hl->out_len = ret; + return 0; } int demod_soft_stop(demod_soft_hl* hl) { - modem_table_free(&hl->table); - return 0; + modem_table_free(&hl->table); + return 0; } diff --git a/lte/lib/modem/src/hard_demod_lte.c b/lte/lib/modem/src/hard_demod_lte.c index b726c6217..a6c07d264 100644 --- a/lte/lib/modem/src/hard_demod_lte.c +++ b/lte/lib/modem/src/hard_demod_lte.c @@ -48,23 +48,23 @@ */ inline void hard_bpsk_demod(const cf_t* in, char* out, int N) { - int s; + int s; - for (s=0; s 0) { - if ((__imag__ in[s] > 0) || (__real__ in[s] > -__imag__ in[s])) { - out[s] = 0x0; - } else { - out[s] = 0x1; - } - } else { - if ((__imag__ in[s] < 0) || (__imag__ in[s] < -__real__ in[s])) { - out[s] = 0x1; - } else { - out[s] = 0x0; - } - } - } + for (s=0; s 0) { + if ((__imag__ in[s] > 0) || (__real__ in[s] > -__imag__ in[s])) { + out[s] = 0x0; + } else { + out[s] = 0x1; + } + } else { + if ((__imag__ in[s] < 0) || (__imag__ in[s] < -__real__ in[s])) { + out[s] = 0x1; + } else { + out[s] = 0x0; + } + } + } } /** @@ -83,20 +83,20 @@ inline void hard_bpsk_demod(const cf_t* in, char* out, int N) */ inline void hard_qpsk_demod(const cf_t* in, char* out, int N) { - int s; + int s; - for (s=0; s 0) { - out[2*s] = 0x0; - } else { - out[2*s] = 0x1; - } - if (__imag__ in[s] > 0) { - out[2*s+1] = 0x0; - } else { - out[2*s+1] = 0x1; - } - } + for (s=0; s 0) { + out[2*s] = 0x0; + } else { + out[2*s] = 0x1; + } + if (__imag__ in[s] > 0) { + out[2*s+1] = 0x0; + } else { + out[2*s+1] = 0x1; + } + } } /** @@ -117,33 +117,33 @@ inline void hard_qpsk_demod(const cf_t* in, char* out, int N) */ inline void hard_qam16_demod(const cf_t* in, char* out, int N) { - int s; + int s; - for (s=0; s 0) { - out[4*s] = 0x0; - } else { - out[4*s] = 0x1; - } + for (s=0; s 0) { + out[4*s] = 0x0; + } else { + out[4*s] = 0x1; + } - if ((__real__ in[s] > QAM16_THRESHOLD) || (__real__ in[s] < -QAM16_THRESHOLD)) { - out[4*s+2] = 0x1; - } else { - out[4*s+2] = 0x0; - } + if ((__real__ in[s] > QAM16_THRESHOLD) || (__real__ in[s] < -QAM16_THRESHOLD)) { + out[4*s+2] = 0x1; + } else { + out[4*s+2] = 0x0; + } - if (__imag__ in[s] > 0) { - out[4*s+1] = 0x0; - } else { - out[4*s+1] = 0x1; - } + if (__imag__ in[s] > 0) { + out[4*s+1] = 0x0; + } else { + out[4*s+1] = 0x1; + } - if ((__imag__ in[s] > QAM16_THRESHOLD) || (__imag__ in[s] < -QAM16_THRESHOLD)) { - out[4*s+3] = 0x1; - } else { - out[4*s+3] = 0x0; - } - } + if ((__imag__ in[s] > QAM16_THRESHOLD) || (__imag__ in[s] < -QAM16_THRESHOLD)) { + out[4*s+3] = 0x1; + } else { + out[4*s+3] = 0x0; + } + } } /** @@ -159,47 +159,47 @@ inline void hard_qam16_demod(const cf_t* in, char* out, int N) */ inline void hard_qam64_demod(const cf_t* in, char* out, int N) { - int s; + int s; - for (s=0; s 0){ - out[6*s] = 0x0; - } else { - out[6*s] = 0x1; - } - if ((__real__ in[s] > QAM64_THRESHOLD_3) || (__real__ in[s] < -QAM64_THRESHOLD_3)) { - out[6*s+2] = 0x1; - out[6*s+4] = 0x1; - } else if ((__real__ in[s] > QAM64_THRESHOLD_2) || (__real__ in[s] < -QAM64_THRESHOLD_2)) { - out[6*s+2] = 0x1; - out[6*s+4] = 0x0; - } else if ((__real__ in[s] > QAM64_THRESHOLD_1) || (__real__ in[s] < -QAM64_THRESHOLD_1)) { - out[6*s+2] = 0x0; - out[6*s+4] = 0x0; - } else { - out[6*s+2] = 0x0; - out[6*s+4] = 0x1; - } + for (s=0; s 0){ + out[6*s] = 0x0; + } else { + out[6*s] = 0x1; + } + if ((__real__ in[s] > QAM64_THRESHOLD_3) || (__real__ in[s] < -QAM64_THRESHOLD_3)) { + out[6*s+2] = 0x1; + out[6*s+4] = 0x1; + } else if ((__real__ in[s] > QAM64_THRESHOLD_2) || (__real__ in[s] < -QAM64_THRESHOLD_2)) { + out[6*s+2] = 0x1; + out[6*s+4] = 0x0; + } else if ((__real__ in[s] > QAM64_THRESHOLD_1) || (__real__ in[s] < -QAM64_THRESHOLD_1)) { + out[6*s+2] = 0x0; + out[6*s+4] = 0x0; + } else { + out[6*s+2] = 0x0; + out[6*s+4] = 0x1; + } - /* bits associated with/obtained from quadrature component: b1, b3, b5 */ - if (__imag__ in[s] > 0){ - out[6*s+1] = 0x0; - } else { - out[6*s+1] = 0x1; - } - if ((__imag__ in[s] > QAM64_THRESHOLD_3) || (__imag__ in[s] < -QAM64_THRESHOLD_3)) { - out[6*s+3] = 0x1; - out[6*s+5] = 0x1; - } else if ((__imag__ in[s] > QAM64_THRESHOLD_2) || (__imag__ in[s] < -QAM64_THRESHOLD_2)) { - out[6*s+3] = 0x1; - out[6*s+5] = 0x0; - } else if ((__imag__ in[s] > QAM64_THRESHOLD_1) || (__imag__ in[s] < -QAM64_THRESHOLD_1)) { - out[6*s+3] = 0x0; - out[6*s+5] = 0x0; - } else { - out[6*s+3] = 0x0; - out[6*s+5] = 0x1; - } - } + /* bits associated with/obtained from quadrature component: b1, b3, b5 */ + if (__imag__ in[s] > 0){ + out[6*s+1] = 0x0; + } else { + out[6*s+1] = 0x1; + } + if ((__imag__ in[s] > QAM64_THRESHOLD_3) || (__imag__ in[s] < -QAM64_THRESHOLD_3)) { + out[6*s+3] = 0x1; + out[6*s+5] = 0x1; + } else if ((__imag__ in[s] > QAM64_THRESHOLD_2) || (__imag__ in[s] < -QAM64_THRESHOLD_2)) { + out[6*s+3] = 0x1; + out[6*s+5] = 0x0; + } else if ((__imag__ in[s] > QAM64_THRESHOLD_1) || (__imag__ in[s] < -QAM64_THRESHOLD_1)) { + out[6*s+3] = 0x0; + out[6*s+5] = 0x0; + } else { + out[6*s+3] = 0x0; + out[6*s+5] = 0x1; + } + } } diff --git a/lte/lib/modem/src/hard_demod_lte.h b/lte/lib/modem/src/hard_demod_lte.h index be79212e8..f41a65f65 100644 --- a/lte/lib/modem/src/hard_demod_lte.h +++ b/lte/lib/modem/src/hard_demod_lte.h @@ -30,10 +30,10 @@ /* Assume perfect amplitude and phase alignment. * Check threshold values for real case * or implement dynamic threshold adjustent as a function of received symbol amplitudes */ -#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 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) void hard_bpsk_demod(const cf_t* in, char* out, int N); void hard_qpsk_demod(const cf_t* in, char* out, int N); diff --git a/lte/lib/modem/src/lte_tables.c b/lte/lib/modem/src/lte_tables.c index cc169fbf0..7d65f4df5 100644 --- a/lte/lib/modem/src/lte_tables.c +++ b/lte/lib/modem/src/lte_tables.c @@ -38,243 +38,243 @@ * Set the BPSK modulation table */ void set_BPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod) { - // LTE-BPSK constellation: - // Q - // | 0 - //---------> I - // 1 | - table[0] = BPSK_LEVEL + BPSK_LEVEL*_Complex_I; - table[1] = -BPSK_LEVEL -BPSK_LEVEL*_Complex_I; + // LTE-BPSK constellation: + // Q + // | 0 + //---------> I + // 1 | + table[0] = BPSK_LEVEL + BPSK_LEVEL*_Complex_I; + table[1] = -BPSK_LEVEL -BPSK_LEVEL*_Complex_I; - if (!compute_soft_demod) { - return; - } + if (!compute_soft_demod) { + return; + } - /* BSPK symbols containing a '0' and a '1' (only two symbols, 1 bit) */ - soft_table->idx[0][0][0] = 0; - soft_table->idx[1][0][0] = 1; + /* BSPK symbols containing a '0' and a '1' (only two symbols, 1 bit) */ + soft_table->idx[0][0][0] = 0; + soft_table->idx[1][0][0] = 1; } /** * Set the QPSK modulation table */ void set_QPSKtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod) { - int i,j; + int i,j; - // LTE-QPSK constellation: - // Q - // 10 | 00 - //-----------> I - // 11 | 01 - table[0] = QPSK_LEVEL + QPSK_LEVEL*_Complex_I; - table[1] = QPSK_LEVEL - QPSK_LEVEL*_Complex_I; - table[2] = -QPSK_LEVEL + QPSK_LEVEL*_Complex_I; - table[3] = -QPSK_LEVEL - QPSK_LEVEL*_Complex_I; - for (i=0;i<6;i++) { - for (j=0;j<32;j++) { - soft_table->idx[0][i][j] = 0; - soft_table->idx[1][i][j] = 0; - } - } + // LTE-QPSK constellation: + // Q + // 10 | 00 + //-----------> I + // 11 | 01 + table[0] = QPSK_LEVEL + QPSK_LEVEL*_Complex_I; + table[1] = QPSK_LEVEL - QPSK_LEVEL*_Complex_I; + table[2] = -QPSK_LEVEL + QPSK_LEVEL*_Complex_I; + table[3] = -QPSK_LEVEL - QPSK_LEVEL*_Complex_I; + for (i=0;i<6;i++) { + for (j=0;j<32;j++) { + soft_table->idx[0][i][j] = 0; + soft_table->idx[1][i][j] = 0; + } + } - if (!compute_soft_demod) { - return; - } + if (!compute_soft_demod) { + return; + } - /* QSPK symbols containing a '0' at the different bit positions */ - soft_table->idx[0][0][0] = 0; - soft_table->idx[0][0][1] = 1; - soft_table->idx[0][1][0] = 0; - soft_table->idx[0][1][1] = 2; - /* QSPK symbols containing a '1' at the different bit positions */ - soft_table->idx[1][0][0] = 2; - soft_table->idx[1][0][1] = 3; - soft_table->idx[1][1][0] = 1; - soft_table->idx[1][1][1] = 3; + /* QSPK symbols containing a '0' at the different bit positions */ + soft_table->idx[0][0][0] = 0; + soft_table->idx[0][0][1] = 1; + soft_table->idx[0][1][0] = 0; + soft_table->idx[0][1][1] = 2; + /* QSPK symbols containing a '1' at the different bit positions */ + soft_table->idx[1][0][0] = 2; + soft_table->idx[1][0][1] = 3; + soft_table->idx[1][1][0] = 1; + soft_table->idx[1][1][1] = 3; } /** * Set the 16QAM modulation table */ void set_16QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod) { - int i,j; - // LTE-16QAM constellation: - // Q - // 1011 1001 | 0001 0011 - // 1010 1000 | 0000 0010 - //---------------------------------> I - // 1110 1100 | 0100 0110 - // 1111 1101 | 0101 0111 - table[0] = QAM16_LEVEL_1 + QAM16_LEVEL_1*_Complex_I; - table[1] = QAM16_LEVEL_1 + QAM16_LEVEL_2*_Complex_I; - table[2] = QAM16_LEVEL_2 + QAM16_LEVEL_1*_Complex_I; - table[3] = QAM16_LEVEL_2 + QAM16_LEVEL_2*_Complex_I; - table[4] = QAM16_LEVEL_1 - QAM16_LEVEL_1*_Complex_I; - table[5] = QAM16_LEVEL_1 - QAM16_LEVEL_2*_Complex_I; - table[6] = QAM16_LEVEL_2 - QAM16_LEVEL_1*_Complex_I; - table[7] = QAM16_LEVEL_2 - QAM16_LEVEL_2*_Complex_I; - table[8] = -QAM16_LEVEL_1 + QAM16_LEVEL_1*_Complex_I; - table[9] = -QAM16_LEVEL_1 + QAM16_LEVEL_2*_Complex_I; - table[10] = -QAM16_LEVEL_2 + QAM16_LEVEL_1*_Complex_I; - table[11] = -QAM16_LEVEL_2 + QAM16_LEVEL_2*_Complex_I; - table[12] = -QAM16_LEVEL_1 - QAM16_LEVEL_1*_Complex_I; - table[13] = -QAM16_LEVEL_1 - QAM16_LEVEL_2*_Complex_I; - table[14] = -QAM16_LEVEL_2 - QAM16_LEVEL_1*_Complex_I; - table[15] = -QAM16_LEVEL_2 - QAM16_LEVEL_2*_Complex_I; - for (i=0;i<6;i++) { - for (j=0;j<32;j++) { - soft_table->idx[0][i][j] = 0; - soft_table->idx[1][i][j] = 0; - } - } - if (!compute_soft_demod) { - return; - } + int i,j; + // LTE-16QAM constellation: + // Q + // 1011 1001 | 0001 0011 + // 1010 1000 | 0000 0010 + //---------------------------------> I + // 1110 1100 | 0100 0110 + // 1111 1101 | 0101 0111 + table[0] = QAM16_LEVEL_1 + QAM16_LEVEL_1*_Complex_I; + table[1] = QAM16_LEVEL_1 + QAM16_LEVEL_2*_Complex_I; + table[2] = QAM16_LEVEL_2 + QAM16_LEVEL_1*_Complex_I; + table[3] = QAM16_LEVEL_2 + QAM16_LEVEL_2*_Complex_I; + table[4] = QAM16_LEVEL_1 - QAM16_LEVEL_1*_Complex_I; + table[5] = QAM16_LEVEL_1 - QAM16_LEVEL_2*_Complex_I; + table[6] = QAM16_LEVEL_2 - QAM16_LEVEL_1*_Complex_I; + table[7] = QAM16_LEVEL_2 - QAM16_LEVEL_2*_Complex_I; + table[8] = -QAM16_LEVEL_1 + QAM16_LEVEL_1*_Complex_I; + table[9] = -QAM16_LEVEL_1 + QAM16_LEVEL_2*_Complex_I; + table[10] = -QAM16_LEVEL_2 + QAM16_LEVEL_1*_Complex_I; + table[11] = -QAM16_LEVEL_2 + QAM16_LEVEL_2*_Complex_I; + table[12] = -QAM16_LEVEL_1 - QAM16_LEVEL_1*_Complex_I; + table[13] = -QAM16_LEVEL_1 - QAM16_LEVEL_2*_Complex_I; + table[14] = -QAM16_LEVEL_2 - QAM16_LEVEL_1*_Complex_I; + table[15] = -QAM16_LEVEL_2 - QAM16_LEVEL_2*_Complex_I; + for (i=0;i<6;i++) { + for (j=0;j<32;j++) { + soft_table->idx[0][i][j] = 0; + soft_table->idx[1][i][j] = 0; + } + } + if (!compute_soft_demod) { + return; + } - /* Matrices identifying the zeros and ones of LTE-16QAM constellation */ - for (i=0;i<8;i++) { - soft_table->idx[0][0][i] = i; /* symbols with a '0' at the bit0 (leftmost)*/ - soft_table->idx[1][0][i] = i+8; /* symbols with a '1' at the bit0 (leftmost)*/ - } - /* symbols with a '0' ans '1' at the bit position 1: */ - for (i=0;i<4;i++) { - soft_table->idx[0][1][i] = i; - soft_table->idx[0][1][i+4] = i+8; - soft_table->idx[1][1][i] = i+4; - soft_table->idx[1][1][i+4] = i+12; - } - /* symbols with a '0' ans '1' at the bit position 2: */ - for (j=0;j<4;j++) { - for (i=0;i<2;i++) { - soft_table->idx[0][2][i+2*j] = i + 4*j; - soft_table->idx[1][2][i+2*j] = i+2 + 4*j; - } - } - /* symbols with a '0' ans '1' at the bit position 3: */ - for (i=0;i<8;i++) { - soft_table->idx[0][3][i] = 2*i; - soft_table->idx[1][3][i] = 2*i+1; - } + /* Matrices identifying the zeros and ones of LTE-16QAM constellation */ + for (i=0;i<8;i++) { + soft_table->idx[0][0][i] = i; /* symbols with a '0' at the bit0 (leftmost)*/ + soft_table->idx[1][0][i] = i+8; /* symbols with a '1' at the bit0 (leftmost)*/ + } + /* symbols with a '0' ans '1' at the bit position 1: */ + for (i=0;i<4;i++) { + soft_table->idx[0][1][i] = i; + soft_table->idx[0][1][i+4] = i+8; + soft_table->idx[1][1][i] = i+4; + soft_table->idx[1][1][i+4] = i+12; + } + /* symbols with a '0' ans '1' at the bit position 2: */ + for (j=0;j<4;j++) { + for (i=0;i<2;i++) { + soft_table->idx[0][2][i+2*j] = i + 4*j; + soft_table->idx[1][2][i+2*j] = i+2 + 4*j; + } + } + /* symbols with a '0' ans '1' at the bit position 3: */ + for (i=0;i<8;i++) { + soft_table->idx[0][3][i] = 2*i; + soft_table->idx[1][3][i] = 2*i+1; + } } /** * Set the 64QAM modulation table */ void set_64QAMtable(cf_t* table, soft_table_t *soft_table, bool compute_soft_demod) { - int i,j; - // LTE-64QAM constellation: - // see [3GPP TS 36.211 version 10.5.0 Release 10, Section 7.1.4] - table[0] = QAM64_LEVEL_2 + QAM64_LEVEL_2*_Complex_I; - table[1] = QAM64_LEVEL_2 + QAM64_LEVEL_1*_Complex_I; - table[2] = QAM64_LEVEL_1 + QAM64_LEVEL_2*_Complex_I; - table[3] = QAM64_LEVEL_1 + QAM64_LEVEL_1*_Complex_I; - table[4] = QAM64_LEVEL_2 + QAM64_LEVEL_3*_Complex_I; - table[5] = QAM64_LEVEL_2 + QAM64_LEVEL_4*_Complex_I; - table[6] = QAM64_LEVEL_1 + QAM64_LEVEL_3*_Complex_I; - table[7] = QAM64_LEVEL_1 + QAM64_LEVEL_4*_Complex_I; - table[8] = QAM64_LEVEL_3 + QAM64_LEVEL_2*_Complex_I; - table[9] = QAM64_LEVEL_3 + QAM64_LEVEL_1*_Complex_I; - table[10] = QAM64_LEVEL_4 + QAM64_LEVEL_2*_Complex_I; - table[11] = QAM64_LEVEL_4 + QAM64_LEVEL_1*_Complex_I; - table[12] = QAM64_LEVEL_3 + QAM64_LEVEL_3*_Complex_I; - table[13] = QAM64_LEVEL_3 + QAM64_LEVEL_4*_Complex_I; - table[14] = QAM64_LEVEL_4 + QAM64_LEVEL_3*_Complex_I; - table[15] = QAM64_LEVEL_4 + QAM64_LEVEL_4*_Complex_I; - table[16] = QAM64_LEVEL_2 - QAM64_LEVEL_2*_Complex_I; - table[17] = QAM64_LEVEL_2 - QAM64_LEVEL_1*_Complex_I; - table[18] = QAM64_LEVEL_1 - QAM64_LEVEL_2*_Complex_I; - table[19] = QAM64_LEVEL_1 - QAM64_LEVEL_1*_Complex_I; - table[20] = QAM64_LEVEL_2 - QAM64_LEVEL_3*_Complex_I; - table[21] = QAM64_LEVEL_2 - QAM64_LEVEL_4*_Complex_I; - table[22] = QAM64_LEVEL_1 - QAM64_LEVEL_3*_Complex_I; - table[23] = QAM64_LEVEL_1 - QAM64_LEVEL_4*_Complex_I; - table[24] = QAM64_LEVEL_3 - QAM64_LEVEL_2*_Complex_I; - table[25] = QAM64_LEVEL_3 - QAM64_LEVEL_1*_Complex_I; - table[26] = QAM64_LEVEL_4 - QAM64_LEVEL_2*_Complex_I; - table[27] = QAM64_LEVEL_4 - QAM64_LEVEL_1*_Complex_I; - table[28] = QAM64_LEVEL_3 - QAM64_LEVEL_3*_Complex_I; - table[29] = QAM64_LEVEL_3 - QAM64_LEVEL_4*_Complex_I; - table[30] = QAM64_LEVEL_4 - QAM64_LEVEL_3*_Complex_I; - table[31] = QAM64_LEVEL_4 - QAM64_LEVEL_4*_Complex_I; - table[32] = -QAM64_LEVEL_2 + QAM64_LEVEL_2*_Complex_I; - table[33] = -QAM64_LEVEL_2 + QAM64_LEVEL_1*_Complex_I; - table[34] = -QAM64_LEVEL_1 + QAM64_LEVEL_2*_Complex_I; - table[35] = -QAM64_LEVEL_1 + QAM64_LEVEL_1*_Complex_I; - table[36] = -QAM64_LEVEL_2 + QAM64_LEVEL_3*_Complex_I; - table[37] = -QAM64_LEVEL_2 + QAM64_LEVEL_4*_Complex_I; - table[38] = -QAM64_LEVEL_1 + QAM64_LEVEL_3*_Complex_I; - table[39] = -QAM64_LEVEL_1 + QAM64_LEVEL_4*_Complex_I; - table[40] = -QAM64_LEVEL_3 + QAM64_LEVEL_2*_Complex_I; - table[41] = -QAM64_LEVEL_3 + QAM64_LEVEL_1*_Complex_I; - table[42] = -QAM64_LEVEL_4 + QAM64_LEVEL_2*_Complex_I; - table[43] = -QAM64_LEVEL_4 + QAM64_LEVEL_1*_Complex_I; - table[44] = -QAM64_LEVEL_3 + QAM64_LEVEL_3*_Complex_I; - table[45] = -QAM64_LEVEL_3 + QAM64_LEVEL_4*_Complex_I; - table[46] = -QAM64_LEVEL_4 + QAM64_LEVEL_3*_Complex_I; - table[47] = -QAM64_LEVEL_4 + QAM64_LEVEL_4*_Complex_I; - table[48] = -QAM64_LEVEL_2 - QAM64_LEVEL_2*_Complex_I; - table[49] = -QAM64_LEVEL_2 - QAM64_LEVEL_1*_Complex_I; - table[50] = -QAM64_LEVEL_1 - QAM64_LEVEL_2*_Complex_I; - table[51] = -QAM64_LEVEL_1 - QAM64_LEVEL_1*_Complex_I; - table[52] = -QAM64_LEVEL_2 - QAM64_LEVEL_3*_Complex_I; - table[53] = -QAM64_LEVEL_2 - QAM64_LEVEL_4*_Complex_I; - table[54] = -QAM64_LEVEL_1 - QAM64_LEVEL_3*_Complex_I; - table[55] = -QAM64_LEVEL_1 - QAM64_LEVEL_4*_Complex_I; - table[56] = -QAM64_LEVEL_3 - QAM64_LEVEL_2*_Complex_I; - table[57] = -QAM64_LEVEL_3 - QAM64_LEVEL_1*_Complex_I; - table[58] = -QAM64_LEVEL_4 - QAM64_LEVEL_2*_Complex_I; - table[59] = -QAM64_LEVEL_4 - QAM64_LEVEL_1*_Complex_I; - table[60] = -QAM64_LEVEL_3 - QAM64_LEVEL_3*_Complex_I; - table[61] = -QAM64_LEVEL_3 - QAM64_LEVEL_4*_Complex_I; - table[62] = -QAM64_LEVEL_4 - QAM64_LEVEL_3*_Complex_I; - table[63] = -QAM64_LEVEL_4 - QAM64_LEVEL_4*_Complex_I; + int i,j; + // LTE-64QAM constellation: + // see [3GPP TS 36.211 version 10.5.0 Release 10, Section 7.1.4] + table[0] = QAM64_LEVEL_2 + QAM64_LEVEL_2*_Complex_I; + table[1] = QAM64_LEVEL_2 + QAM64_LEVEL_1*_Complex_I; + table[2] = QAM64_LEVEL_1 + QAM64_LEVEL_2*_Complex_I; + table[3] = QAM64_LEVEL_1 + QAM64_LEVEL_1*_Complex_I; + table[4] = QAM64_LEVEL_2 + QAM64_LEVEL_3*_Complex_I; + table[5] = QAM64_LEVEL_2 + QAM64_LEVEL_4*_Complex_I; + table[6] = QAM64_LEVEL_1 + QAM64_LEVEL_3*_Complex_I; + table[7] = QAM64_LEVEL_1 + QAM64_LEVEL_4*_Complex_I; + table[8] = QAM64_LEVEL_3 + QAM64_LEVEL_2*_Complex_I; + table[9] = QAM64_LEVEL_3 + QAM64_LEVEL_1*_Complex_I; + table[10] = QAM64_LEVEL_4 + QAM64_LEVEL_2*_Complex_I; + table[11] = QAM64_LEVEL_4 + QAM64_LEVEL_1*_Complex_I; + table[12] = QAM64_LEVEL_3 + QAM64_LEVEL_3*_Complex_I; + table[13] = QAM64_LEVEL_3 + QAM64_LEVEL_4*_Complex_I; + table[14] = QAM64_LEVEL_4 + QAM64_LEVEL_3*_Complex_I; + table[15] = QAM64_LEVEL_4 + QAM64_LEVEL_4*_Complex_I; + table[16] = QAM64_LEVEL_2 - QAM64_LEVEL_2*_Complex_I; + table[17] = QAM64_LEVEL_2 - QAM64_LEVEL_1*_Complex_I; + table[18] = QAM64_LEVEL_1 - QAM64_LEVEL_2*_Complex_I; + table[19] = QAM64_LEVEL_1 - QAM64_LEVEL_1*_Complex_I; + table[20] = QAM64_LEVEL_2 - QAM64_LEVEL_3*_Complex_I; + table[21] = QAM64_LEVEL_2 - QAM64_LEVEL_4*_Complex_I; + table[22] = QAM64_LEVEL_1 - QAM64_LEVEL_3*_Complex_I; + table[23] = QAM64_LEVEL_1 - QAM64_LEVEL_4*_Complex_I; + table[24] = QAM64_LEVEL_3 - QAM64_LEVEL_2*_Complex_I; + table[25] = QAM64_LEVEL_3 - QAM64_LEVEL_1*_Complex_I; + table[26] = QAM64_LEVEL_4 - QAM64_LEVEL_2*_Complex_I; + table[27] = QAM64_LEVEL_4 - QAM64_LEVEL_1*_Complex_I; + table[28] = QAM64_LEVEL_3 - QAM64_LEVEL_3*_Complex_I; + table[29] = QAM64_LEVEL_3 - QAM64_LEVEL_4*_Complex_I; + table[30] = QAM64_LEVEL_4 - QAM64_LEVEL_3*_Complex_I; + table[31] = QAM64_LEVEL_4 - QAM64_LEVEL_4*_Complex_I; + table[32] = -QAM64_LEVEL_2 + QAM64_LEVEL_2*_Complex_I; + table[33] = -QAM64_LEVEL_2 + QAM64_LEVEL_1*_Complex_I; + table[34] = -QAM64_LEVEL_1 + QAM64_LEVEL_2*_Complex_I; + table[35] = -QAM64_LEVEL_1 + QAM64_LEVEL_1*_Complex_I; + table[36] = -QAM64_LEVEL_2 + QAM64_LEVEL_3*_Complex_I; + table[37] = -QAM64_LEVEL_2 + QAM64_LEVEL_4*_Complex_I; + table[38] = -QAM64_LEVEL_1 + QAM64_LEVEL_3*_Complex_I; + table[39] = -QAM64_LEVEL_1 + QAM64_LEVEL_4*_Complex_I; + table[40] = -QAM64_LEVEL_3 + QAM64_LEVEL_2*_Complex_I; + table[41] = -QAM64_LEVEL_3 + QAM64_LEVEL_1*_Complex_I; + table[42] = -QAM64_LEVEL_4 + QAM64_LEVEL_2*_Complex_I; + table[43] = -QAM64_LEVEL_4 + QAM64_LEVEL_1*_Complex_I; + table[44] = -QAM64_LEVEL_3 + QAM64_LEVEL_3*_Complex_I; + table[45] = -QAM64_LEVEL_3 + QAM64_LEVEL_4*_Complex_I; + table[46] = -QAM64_LEVEL_4 + QAM64_LEVEL_3*_Complex_I; + table[47] = -QAM64_LEVEL_4 + QAM64_LEVEL_4*_Complex_I; + table[48] = -QAM64_LEVEL_2 - QAM64_LEVEL_2*_Complex_I; + table[49] = -QAM64_LEVEL_2 - QAM64_LEVEL_1*_Complex_I; + table[50] = -QAM64_LEVEL_1 - QAM64_LEVEL_2*_Complex_I; + table[51] = -QAM64_LEVEL_1 - QAM64_LEVEL_1*_Complex_I; + table[52] = -QAM64_LEVEL_2 - QAM64_LEVEL_3*_Complex_I; + table[53] = -QAM64_LEVEL_2 - QAM64_LEVEL_4*_Complex_I; + table[54] = -QAM64_LEVEL_1 - QAM64_LEVEL_3*_Complex_I; + table[55] = -QAM64_LEVEL_1 - QAM64_LEVEL_4*_Complex_I; + table[56] = -QAM64_LEVEL_3 - QAM64_LEVEL_2*_Complex_I; + table[57] = -QAM64_LEVEL_3 - QAM64_LEVEL_1*_Complex_I; + table[58] = -QAM64_LEVEL_4 - QAM64_LEVEL_2*_Complex_I; + table[59] = -QAM64_LEVEL_4 - QAM64_LEVEL_1*_Complex_I; + table[60] = -QAM64_LEVEL_3 - QAM64_LEVEL_3*_Complex_I; + table[61] = -QAM64_LEVEL_3 - QAM64_LEVEL_4*_Complex_I; + table[62] = -QAM64_LEVEL_4 - QAM64_LEVEL_3*_Complex_I; + table[63] = -QAM64_LEVEL_4 - QAM64_LEVEL_4*_Complex_I; - if (!compute_soft_demod) { - return; - } + if (!compute_soft_demod) { + return; + } - /* Matrices identifying the zeros and ones of LTE-64QAM constellation */ + /* Matrices identifying the zeros and ones of LTE-64QAM constellation */ - for (i=0;i<32;i++) { - soft_table->idx[0][0][i] = i; /* symbols with a '0' at the bit0 (leftmost)*/ - soft_table->idx[1][0][i] = i+32; /* symbols with a '1' at the bit0 (leftmost)*/ - } - /* symbols with a '0' ans '1' at the bit position 1: */ - for (i=0;i<16;i++) { - soft_table->idx[0][1][i] = i; - soft_table->idx[0][1][i+16] = i+32; - soft_table->idx[1][1][i] = i+16; - soft_table->idx[1][1][i+16] = i+48; - } - /* symbols with a '0' ans '1' at the bit position 2: */ - for (i=0;i<8;i++) { - soft_table->idx[0][2][i] = i; - soft_table->idx[0][2][i+8] = i+16; - soft_table->idx[0][2][i+16] = i+32; - soft_table->idx[0][2][i+24] = i+48; - soft_table->idx[1][2][i] = i+8; - soft_table->idx[1][2][i+8] = i+24; - soft_table->idx[1][2][i+16] = i+40; - soft_table->idx[1][2][i+24] = i+56; - } - /* symbols with a '0' ans '1' at the bit position 3: */ - for (j=0;j<8;j++) { - for (i=0;i<4;i++) { - soft_table->idx[0][3][i+4*j] = i + 8*j; - soft_table->idx[1][3][i+4*j] = i+4 + 8*j; - } - } - /* symbols with a '0' ans '1' at the bit position 4: */ - for (j=0;j<16;j++) { - for (i=0;i<2;i++) { - soft_table->idx[0][4][i+2*j] = i + 4*j; - soft_table->idx[1][4][i+2*j] = i+2 + 4*j; - } - } - /* symbols with a '0' ans '1' at the bit position 5: */ - for (i=0;i<32;i++) { - soft_table->idx[0][5][i] = 2*i; - soft_table->idx[1][5][i] = 2*i+1; - } + for (i=0;i<32;i++) { + soft_table->idx[0][0][i] = i; /* symbols with a '0' at the bit0 (leftmost)*/ + soft_table->idx[1][0][i] = i+32; /* symbols with a '1' at the bit0 (leftmost)*/ + } + /* symbols with a '0' ans '1' at the bit position 1: */ + for (i=0;i<16;i++) { + soft_table->idx[0][1][i] = i; + soft_table->idx[0][1][i+16] = i+32; + soft_table->idx[1][1][i] = i+16; + soft_table->idx[1][1][i+16] = i+48; + } + /* symbols with a '0' ans '1' at the bit position 2: */ + for (i=0;i<8;i++) { + soft_table->idx[0][2][i] = i; + soft_table->idx[0][2][i+8] = i+16; + soft_table->idx[0][2][i+16] = i+32; + soft_table->idx[0][2][i+24] = i+48; + soft_table->idx[1][2][i] = i+8; + soft_table->idx[1][2][i+8] = i+24; + soft_table->idx[1][2][i+16] = i+40; + soft_table->idx[1][2][i+24] = i+56; + } + /* symbols with a '0' ans '1' at the bit position 3: */ + for (j=0;j<8;j++) { + for (i=0;i<4;i++) { + soft_table->idx[0][3][i+4*j] = i + 8*j; + soft_table->idx[1][3][i+4*j] = i+4 + 8*j; + } + } + /* symbols with a '0' ans '1' at the bit position 4: */ + for (j=0;j<16;j++) { + for (i=0;i<2;i++) { + soft_table->idx[0][4][i+2*j] = i + 4*j; + soft_table->idx[1][4][i+2*j] = i+2 + 4*j; + } + } + /* symbols with a '0' ans '1' at the bit position 5: */ + for (i=0;i<32;i++) { + soft_table->idx[0][5][i] = 2*i; + soft_table->idx[1][5][i] = 2*i+1; + } } diff --git a/lte/lib/modem/src/lte_tables.h b/lte/lib/modem/src/lte_tables.h index 1e5280137..77544a62a 100644 --- a/lte/lib/modem/src/lte_tables.h +++ b/lte/lib/modem/src/lte_tables.h @@ -30,15 +30,15 @@ #define QPSK_LEVEL 1/sqrt(2) -#define QAM16_LEVEL_1 1/sqrt(10) -#define QAM16_LEVEL_2 3/sqrt(10) +#define QAM16_LEVEL_1 1/sqrt(10) +#define QAM16_LEVEL_2 3/sqrt(10) -#define QAM64_LEVEL_1 1/sqrt(42) -#define QAM64_LEVEL_2 3/sqrt(42) -#define QAM64_LEVEL_3 5/sqrt(42) -#define QAM64_LEVEL_4 7/sqrt(42) +#define QAM64_LEVEL_1 1/sqrt(42) +#define QAM64_LEVEL_2 3/sqrt(42) +#define QAM64_LEVEL_3 5/sqrt(42) +#define QAM64_LEVEL_4 7/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 * symbol from the bit sequence */ diff --git a/lte/lib/modem/src/mod.c b/lte/lib/modem/src/mod.c index 968f202ba..a80473db5 100644 --- a/lte/lib/modem/src/mod.c +++ b/lte/lib/modem/src/mod.c @@ -36,38 +36,38 @@ /** Low-level API */ int mod_modulate(modem_table_t* q, const char *bits, cf_t* symbols, int nbits) { - int i,j,idx; - char *b_ptr=(char*) bits; - j=0; - for (i=0;inbits_x_symbol) { - idx = bit_unpack(&b_ptr,q->nbits_x_symbol); - assert(idx >= 0 && idx < q->nsymbols); - symbols[j] = q->symbol_table[idx]; - j++; - } - return j; + int i,j,idx; + char *b_ptr=(char*) bits; + j=0; + for (i=0;inbits_x_symbol) { + idx = bit_unpack(&b_ptr,q->nbits_x_symbol); + assert(idx >= 0 && idx < q->nsymbols); + symbols[j] = q->symbol_table[idx]; + j++; + } + return j; } /* High-Level API */ int mod_initialize(mod_hl* hl) { - modem_table_init(&hl->obj); - if (modem_table_std(&hl->obj,hl->init.std,false)) { - return -1; - } + modem_table_init(&hl->obj); + if (modem_table_std(&hl->obj,hl->init.std,false)) { + return -1; + } - return 0; + return 0; } int mod_work(mod_hl* hl) { - int ret = mod_modulate(&hl->obj,hl->input,hl->output,hl->in_len); - hl->out_len = ret; - return 0; + int ret = mod_modulate(&hl->obj,hl->input,hl->output,hl->in_len); + hl->out_len = ret; + return 0; } int mod_stop(mod_hl* hl) { - modem_table_free(&hl->obj); - return 0; + modem_table_free(&hl->obj); + return 0; } diff --git a/lte/lib/modem/src/modem_table.c b/lte/lib/modem/src/modem_table.c index 3ec2888c0..61437a175 100644 --- a/lte/lib/modem/src/modem_table.c +++ b/lte/lib/modem/src/modem_table.c @@ -38,72 +38,72 @@ /** Internal functions */ static int table_create(modem_table_t* q) { - q->symbol_table = malloc(q->nsymbols*sizeof(cf_t)); - return q->symbol_table==NULL; + q->symbol_table = malloc(q->nsymbols*sizeof(cf_t)); + return q->symbol_table==NULL; } void modem_table_init(modem_table_t* q) { - bzero((void*)q,sizeof(modem_table_t)); + bzero((void*)q,sizeof(modem_table_t)); } void modem_table_free(modem_table_t* q) { - if (q->symbol_table) { - free(q->symbol_table); - } - bzero(q, sizeof(modem_table_t)); + if (q->symbol_table) { + free(q->symbol_table); + } + bzero(q, sizeof(modem_table_t)); } void modem_table_reset(modem_table_t* q) { - modem_table_free(q); - modem_table_init(q); + modem_table_free(q); + modem_table_init(q); } int modem_table_set(modem_table_t* q, cf_t* table, soft_table_t *soft_table, int nsymbols, int nbits_x_symbol) { - if (q->nsymbols) { - return -1; - } - q->nsymbols = nsymbols; - if (table_create(q)) { - return -1; - } - memcpy(q->symbol_table,table,q->nsymbols*sizeof(cf_t)); - memcpy(&q->soft_table,soft_table,sizeof(soft_table_t)); - q->nbits_x_symbol = nbits_x_symbol; - return 0; + if (q->nsymbols) { + return -1; + } + q->nsymbols = nsymbols; + if (table_create(q)) { + return -1; + } + memcpy(q->symbol_table,table,q->nsymbols*sizeof(cf_t)); + memcpy(&q->soft_table,soft_table,sizeof(soft_table_t)); + q->nbits_x_symbol = nbits_x_symbol; + return 0; } int modem_table_std(modem_table_t* q, enum modem_std std, bool compute_soft_demod) { - switch(std) { - case LTE_BPSK: - q->nbits_x_symbol = 1; - q->nsymbols = 2; - if (table_create(q)) { - return -1; - } - set_BPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod); - break; - case LTE_QPSK: - q->nbits_x_symbol = 2; - q->nsymbols = 4; - if (table_create(q)) { - return -1; - } - set_QPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod); - break; - case LTE_QAM16: - q->nbits_x_symbol = 4; - q->nsymbols = 16; - if (table_create(q)) { - return -1; - } - set_16QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod); - break; - case LTE_QAM64: - q->nbits_x_symbol = 6; - q->nsymbols = 64; - if (table_create(q)) { - return -1; - } - set_64QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod); - break; - } - return 0; + switch(std) { + case LTE_BPSK: + q->nbits_x_symbol = 1; + q->nsymbols = 2; + if (table_create(q)) { + return -1; + } + set_BPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod); + break; + case LTE_QPSK: + q->nbits_x_symbol = 2; + q->nsymbols = 4; + if (table_create(q)) { + return -1; + } + set_QPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod); + break; + case LTE_QAM16: + q->nbits_x_symbol = 4; + q->nsymbols = 16; + if (table_create(q)) { + return -1; + } + set_16QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod); + break; + case LTE_QAM64: + q->nbits_x_symbol = 6; + q->nsymbols = 64; + if (table_create(q)) { + return -1; + } + set_64QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod); + break; + } + return 0; } diff --git a/lte/lib/modem/src/soft_algs.c b/lte/lib/modem/src/soft_algs.c index 3180a117a..7268d2a31 100644 --- a/lte/lib/modem/src/soft_algs.c +++ b/lte/lib/modem/src/soft_algs.c @@ -51,48 +51,48 @@ * \param sigma2 Noise vatiance */ void llr_approx(const _Complex float *in, float *out, int N, int M, int B, - _Complex float *symbols, int (*S)[6][32], float sigma2) { - int i, s, b; - float num, den; - float new_num, new_den; - float idiff0, qdiff0, idiff1, qdiff1; - int change_sign = -1; + _Complex float *symbols, int (*S)[6][32], float sigma2) { + int i, s, b; + float num, den; + float new_num, new_den; + float idiff0, qdiff0, idiff1, qdiff1; + int change_sign = -1; - for (s=0; s=0 ? 1 : 0; - } - } else { - demod_hard_demodulate(&demod_hard, symbols, output, num_bits / mod.nbits_x_symbol); - } - - /* check errors */ - for (i=0;i=0 ? 1 : 0; + } + } else { + demod_hard_demodulate(&demod_hard, symbols, output, num_bits / mod.nbits_x_symbol); + } + + /* check errors */ + for (i=0;imsg = calloc(sizeof(dci_msg_t), max_dcis); - if (!q->msg) { - perror("malloc"); - return -1; - } - q->nof_dcis = 0; - q->max_dcis = max_dcis; - return 0; + q->msg = calloc(sizeof(dci_msg_t), max_dcis); + if (!q->msg) { + perror("malloc"); + return -1; + } + q->nof_dcis = 0; + q->max_dcis = max_dcis; + return 0; } void dci_free(dci_t *q) { - if (q->msg) { - free(q->msg); - } + if (q->msg) { + free(q->msg); + } } void dci_candidate_fprint(FILE *f, dci_candidate_t *q) { - fprintf(f, "L: %d, nCCE: %d, RNTI: 0x%x, nBits: %d\n", - q->L, q->ncce, q->rnti, q->nof_bits); + fprintf(f, "L: %d, nCCE: %d, RNTI: 0x%x, nBits: %d\n", + q->L, q->ncce, q->rnti, q->nof_bits); } int dci_msg_candidate_set(dci_msg_t *msg, int L, int nCCE, unsigned short rnti) { - if (L >= 0 && L <=3) { - msg->location.L = (unsigned char) L; - } else { - fprintf(stderr, "Invalid L %d\n", L); - return -1; - } - if (nCCE >= 0 && nCCE <= 87) { - msg->location.ncce = (unsigned char) nCCE; - } else { - fprintf(stderr, "Invalid nCCE %d\n", nCCE); - return -1; - } - msg->location.rnti = rnti; - return 0; + if (L >= 0 && L <=3) { + msg->location.L = (unsigned char) L; + } else { + fprintf(stderr, "Invalid L %d\n", L); + return -1; + } + if (nCCE >= 0 && nCCE <= 87) { + msg->location.ncce = (unsigned char) nCCE; + } else { + fprintf(stderr, "Invalid nCCE %d\n", nCCE); + return -1; + } + msg->location.rnti = rnti; + return 0; } int riv_nbits(int nof_prb) { - return (int) ceilf(log2f((float) nof_prb*((float) nof_prb+1)/2)); + return (int) ceilf(log2f((float) nof_prb*((float) nof_prb+1)/2)); } const int ambiguous_sizes[10] = {12, 14, 16, 20, 24, 26, 32, 40, 44, 56}; bool is_ambiguous_size(int size) { - int i; - for (i=0;i<10;i++) { - if (size == ambiguous_sizes[i]) { - return true; - } - } - return false; + int i; + for (i=0;i<10;i++) { + if (size == ambiguous_sizes[i]) { + return true; + } + } + return false; } @@ -102,68 +102,68 @@ bool is_ambiguous_size(int size) { * PAYLOAD sizeof functions * ********************************/ int dci_format0_sizeof_(int nof_prb) { - return 1+1+riv_nbits(nof_prb)+5+1+2+3+1; + return 1+1+riv_nbits(nof_prb)+5+1+2+3+1; } int dci_format1A_sizeof(int nof_prb) { - int n; - n = 1+1+riv_nbits(nof_prb)+5+3+1+2+2; - while(n < dci_format0_sizeof_(nof_prb)) { - n++; - } - if (is_ambiguous_size(n)) { - n++; - } - return n; + int n; + n = 1+1+riv_nbits(nof_prb)+5+3+1+2+2; + while(n < dci_format0_sizeof_(nof_prb)) { + n++; + } + if (is_ambiguous_size(n)) { + n++; + } + return n; } int dci_format0_sizeof(int nof_prb) { - int n = dci_format0_sizeof_(nof_prb); - while (n < dci_format1A_sizeof(nof_prb)) { - n++; - } - return n; + int n = dci_format0_sizeof_(nof_prb); + while (n < dci_format1A_sizeof(nof_prb)) { + n++; + } + return n; } int dci_format1_sizeof(int nof_prb) { - int n = (int) ceilf((float) nof_prb/ra_type0_P(nof_prb))+5+3+1+2+2; - if (nof_prb > 10) { - n++; - } - while(n == dci_format0_sizeof(nof_prb) - || n == dci_format1A_sizeof(nof_prb) - || is_ambiguous_size(n)) { - n++; - } - return n; + int n = (int) ceilf((float) nof_prb/ra_type0_P(nof_prb))+5+3+1+2+2; + if (nof_prb > 10) { + n++; + } + while(n == dci_format0_sizeof(nof_prb) + || n == dci_format1A_sizeof(nof_prb) + || is_ambiguous_size(n)) { + n++; + } + return n; } int dci_format1C_sizeof(int nof_prb) { - int n_vrb_dl_gap1 = ra_type2_n_vrb_dl(nof_prb, true); - int n_step = ra_type2_n_rb_step(nof_prb); - int n = + riv_nbits((int) n_vrb_dl_gap1/n_step) + 5; - if (nof_prb >= 50) { - n++; - } - return n; + int n_vrb_dl_gap1 = ra_type2_n_vrb_dl(nof_prb, true); + int n_step = ra_type2_n_rb_step(nof_prb); + int n = + riv_nbits((int) n_vrb_dl_gap1/n_step) + 5; + if (nof_prb >= 50) { + n++; + } + return n; } int dci_format_sizeof(dci_format_t format, int nof_prb) { - switch(format) { - case Format0: - return dci_format0_sizeof(nof_prb); - case Format1: - return dci_format1_sizeof(nof_prb); - case Format1A: - return dci_format1A_sizeof(nof_prb); - case Format1C: - return dci_format1C_sizeof(nof_prb); - default: - return -1; - } + switch(format) { + case Format0: + return dci_format0_sizeof(nof_prb); + case Format1: + return dci_format1_sizeof(nof_prb); + case Format1A: + return dci_format1A_sizeof(nof_prb); + case Format1C: + return dci_format1C_sizeof(nof_prb); + default: + return -1; + } } @@ -180,79 +180,79 @@ int dci_format_sizeof(dci_format_t format, int nof_prb) { */ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, int nof_prb) { - /* pack bits */ - char *y = msg->data; - int n_ul_hop; - - *y++ = 0; // format differentiation - if (data->freq_hop_fl == hop_disabled) { // frequency hopping - *y++ = 0; - n_ul_hop = 0; - } else { - *y++ = 1; - if (nof_prb < 50) { - n_ul_hop = 1; // Table 8.4-1 of 36.213 - *y++ = data->freq_hop_fl & 1; - } else { - n_ul_hop = 2; // Table 8.4-1 of 36.213 - *y++ = (data->freq_hop_fl & 2) >> 1; - *y++ = data->freq_hop_fl & 1; - } - } - - /* pack RIV according to 8.1 of 36.213 */ - uint32_t riv; - if (data->type2_alloc.L_crb) { - riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start, nof_prb); - } else { - riv = data->type2_alloc.riv; - } - bit_pack(riv, &y, riv_nbits(nof_prb) - n_ul_hop); - - /* pack MCS according to 8.6.1 of 36.213 */ - uint32_t mcs; - if (data->cqi_request) { - mcs = 29; - } else { - if (data->rv_idx) { - mcs = 28 + data->rv_idx; - } else { - if (data->mcs.mod == MOD_NULL) { - mcs = data->mcs.mcs_idx; - } else { - if (data->mcs.tbs) { - if (data->mcs.tbs) { - data->mcs.tbs_idx = ra_tbs_to_table_idx(data->mcs.tbs, ra_nprb_ul(data, nof_prb)); - } - } - mcs = ra_mcs_to_table_idx(&data->mcs); - } - } - } - - bit_pack(mcs, &y, 5); - - *y++ = data->ndi; - - // TCP commands not implemented - *y++ = 0; - *y++ = 0; - - // DM RS not implemented - *y++ = 0; - *y++ = 0; - *y++ = 0; - - // CQI request - *y++ = data->cqi_request; - - // Padding with zeros - int n = dci_format0_sizeof(nof_prb); - while (y-msg->data < n) { - *y++ = 0; - } - msg->location.nof_bits = (y - msg->data); - return 0; + /* pack bits */ + char *y = msg->data; + int n_ul_hop; + + *y++ = 0; // format differentiation + if (data->freq_hop_fl == hop_disabled) { // frequency hopping + *y++ = 0; + n_ul_hop = 0; + } else { + *y++ = 1; + if (nof_prb < 50) { + n_ul_hop = 1; // Table 8.4-1 of 36.213 + *y++ = data->freq_hop_fl & 1; + } else { + n_ul_hop = 2; // Table 8.4-1 of 36.213 + *y++ = (data->freq_hop_fl & 2) >> 1; + *y++ = data->freq_hop_fl & 1; + } + } + + /* pack RIV according to 8.1 of 36.213 */ + uint32_t riv; + if (data->type2_alloc.L_crb) { + riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start, nof_prb); + } else { + riv = data->type2_alloc.riv; + } + bit_pack(riv, &y, riv_nbits(nof_prb) - n_ul_hop); + + /* pack MCS according to 8.6.1 of 36.213 */ + uint32_t mcs; + if (data->cqi_request) { + mcs = 29; + } else { + if (data->rv_idx) { + mcs = 28 + data->rv_idx; + } else { + if (data->mcs.mod == MOD_NULL) { + mcs = data->mcs.mcs_idx; + } else { + if (data->mcs.tbs) { + if (data->mcs.tbs) { + data->mcs.tbs_idx = ra_tbs_to_table_idx(data->mcs.tbs, ra_nprb_ul(data, nof_prb)); + } + } + mcs = ra_mcs_to_table_idx(&data->mcs); + } + } + } + + bit_pack(mcs, &y, 5); + + *y++ = data->ndi; + + // TCP commands not implemented + *y++ = 0; + *y++ = 0; + + // DM RS not implemented + *y++ = 0; + *y++ = 0; + *y++ = 0; + + // CQI request + *y++ = data->cqi_request; + + // Padding with zeros + int n = dci_format0_sizeof(nof_prb); + while (y-msg->data < n) { + *y++ = 0; + } + msg->location.nof_bits = (y - msg->data); + return 0; } /* Unpacks DCI format 0 data and store result in msg according * to 36.212 5.3.3.1.1 @@ -261,66 +261,66 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, int nof_prb) { */ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, int nof_prb) { - /* pack bits */ - char *y = msg->data; - int n_ul_hop; - - /* Make sure it's a Format0 message */ - if (msg->location.nof_bits != dci_format_sizeof(Format0, nof_prb)) { - fprintf(stderr, "Invalid message length for format 0\n"); - return -1; - } - if (*y++ != 0) { - fprintf(stderr, "Invalid format differentiation field value. This is Format1A\n"); - return -1; - } - if (*y++ == 0) { - data->freq_hop_fl = hop_disabled; - n_ul_hop = 0; - } else { - if (nof_prb < 50) { - n_ul_hop = 1; // Table 8.4-1 of 36.213 - data->freq_hop_fl = *y++; - } else { - n_ul_hop = 2; // Table 8.4-1 of 36.213 - data->freq_hop_fl = y[0]<<1 | y[1]; - y += 2; - } - } - /* unpack RIV according to 8.1 of 36.213 */ - uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - n_ul_hop); - ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start, nof_prb, nof_prb); - bit_pack(riv, &y, riv_nbits(nof_prb) - n_ul_hop); - data->type2_alloc.riv = riv; - - /* unpack MCS according to 8.6 of 36.213 */ - uint32_t mcs = bit_unpack(&y, 5); - - data->ndi = *y++?true:false; - - // TCP and DM RS commands not implemented - y+= 5; - - // CQI request - data->cqi_request = *y++?true:false; - - // 8.6.2 First paragraph - if (mcs <= 28) { - ra_mcs_from_idx_ul(mcs, &data->mcs); - data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, ra_nprb_ul(data, nof_prb)); - } - - // 8.6.1 and 8.6.2 36.213 second paragraph - if (mcs == 29 && data->cqi_request && ra_nprb_ul(data, nof_prb) <= 4) { - data->mcs.mod = QPSK; - } - if (mcs > 29) { - // Else leave MOD_NULL and use the previously used PUSCH modulation - data->mcs.mod = MOD_NULL; - data->rv_idx = mcs - 28; - } - - return 0; + /* pack bits */ + char *y = msg->data; + int n_ul_hop; + + /* Make sure it's a Format0 message */ + if (msg->location.nof_bits != dci_format_sizeof(Format0, nof_prb)) { + fprintf(stderr, "Invalid message length for format 0\n"); + return -1; + } + if (*y++ != 0) { + fprintf(stderr, "Invalid format differentiation field value. This is Format1A\n"); + return -1; + } + if (*y++ == 0) { + data->freq_hop_fl = hop_disabled; + n_ul_hop = 0; + } else { + if (nof_prb < 50) { + n_ul_hop = 1; // Table 8.4-1 of 36.213 + data->freq_hop_fl = *y++; + } else { + n_ul_hop = 2; // Table 8.4-1 of 36.213 + data->freq_hop_fl = y[0]<<1 | y[1]; + y += 2; + } + } + /* unpack RIV according to 8.1 of 36.213 */ + uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - n_ul_hop); + ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start, nof_prb, nof_prb); + bit_pack(riv, &y, riv_nbits(nof_prb) - n_ul_hop); + data->type2_alloc.riv = riv; + + /* unpack MCS according to 8.6 of 36.213 */ + uint32_t mcs = bit_unpack(&y, 5); + + data->ndi = *y++?true:false; + + // TCP and DM RS commands not implemented + y+= 5; + + // CQI request + data->cqi_request = *y++?true:false; + + // 8.6.2 First paragraph + if (mcs <= 28) { + ra_mcs_from_idx_ul(mcs, &data->mcs); + data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, ra_nprb_ul(data, nof_prb)); + } + + // 8.6.1 and 8.6.2 36.213 second paragraph + if (mcs == 29 && data->cqi_request && ra_nprb_ul(data, nof_prb) <= 4) { + data->mcs.mod = QPSK; + } + if (mcs > 29) { + // Else leave MOD_NULL and use the previously used PUSCH modulation + data->mcs.mod = MOD_NULL; + data->rv_idx = mcs - 28; + } + + return 0; } /* Packs DCI format 1 data to a sequence of bits and store them in msg according @@ -331,116 +331,116 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, int nof_prb) { int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb) { - /* pack bits */ - char *y = msg->data; - - if (nof_prb > 10) { - *y++ = data->alloc_type; - } - - /* Resource allocation: type0 or type 1 */ - int P = ra_type0_P(nof_prb); - int alloc_size = (int) ceilf((float) nof_prb/P); - switch(data->alloc_type) { - case alloc_type0: - bit_pack(data->type0_alloc.rbg_bitmask, &y, alloc_size); - break; - case alloc_type1: - bit_pack(data->type1_alloc.rbg_subset, &y, (int) ceilf(log2f(P))); - *y++ = data->type1_alloc.shift?1:0; - bit_pack(data->type1_alloc.vrb_bitmask, &y, alloc_size - (int) ceilf(log2f(P)) - 1); - break; - default: - fprintf(stderr, "Format 1 accepts type0 or type1 resource allocation only\n"); - return -1; - - } - /* pack MCS according to 7.1.7 of 36.213 */ - uint32_t mcs; - if (data->mcs.mod == MOD_NULL) { - mcs = data->mcs.mcs_idx; - } else { - if (data->mcs.tbs) { - data->mcs.tbs_idx = ra_tbs_to_table_idx(data->mcs.tbs, ra_nprb_dl(data, nof_prb)); - } - mcs = ra_mcs_to_table_idx(&data->mcs); - } - bit_pack(mcs, &y, 5); - - /* harq process number */ - bit_pack(data->harq_process, &y, 3); - - *y++ = data->ndi; - - // rv version - bit_pack(data->rv_idx, &y, 2); - - // TPC not implemented - *y++ = 0; - *y++ = 0; - - // Padding with zeros - int n = dci_format1_sizeof(nof_prb); - while (y-msg->data < n) { - *y++ = 0; - } - msg->location.nof_bits = (y - msg->data); - - return 0; + /* pack bits */ + char *y = msg->data; + + if (nof_prb > 10) { + *y++ = data->alloc_type; + } + + /* Resource allocation: type0 or type 1 */ + int P = ra_type0_P(nof_prb); + int alloc_size = (int) ceilf((float) nof_prb/P); + switch(data->alloc_type) { + case alloc_type0: + bit_pack(data->type0_alloc.rbg_bitmask, &y, alloc_size); + break; + case alloc_type1: + bit_pack(data->type1_alloc.rbg_subset, &y, (int) ceilf(log2f(P))); + *y++ = data->type1_alloc.shift?1:0; + bit_pack(data->type1_alloc.vrb_bitmask, &y, alloc_size - (int) ceilf(log2f(P)) - 1); + break; + default: + fprintf(stderr, "Format 1 accepts type0 or type1 resource allocation only\n"); + return -1; + + } + /* pack MCS according to 7.1.7 of 36.213 */ + uint32_t mcs; + if (data->mcs.mod == MOD_NULL) { + mcs = data->mcs.mcs_idx; + } else { + if (data->mcs.tbs) { + data->mcs.tbs_idx = ra_tbs_to_table_idx(data->mcs.tbs, ra_nprb_dl(data, nof_prb)); + } + mcs = ra_mcs_to_table_idx(&data->mcs); + } + bit_pack(mcs, &y, 5); + + /* harq process number */ + bit_pack(data->harq_process, &y, 3); + + *y++ = data->ndi; + + // rv version + bit_pack(data->rv_idx, &y, 2); + + // TPC not implemented + *y++ = 0; + *y++ = 0; + + // Padding with zeros + int n = dci_format1_sizeof(nof_prb); + while (y-msg->data < n) { + *y++ = 0; + } + msg->location.nof_bits = (y - msg->data); + + return 0; } int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { - /* pack bits */ - char *y = msg->data; - - /* Make sure it's a Format1 message */ - if (msg->location.nof_bits != dci_format_sizeof(Format1, nof_prb)) { - fprintf(stderr, "Invalid message length for format 1\n"); - return -1; - } - - if (nof_prb > 10) { - data->alloc_type = *y++; - } else { - data->alloc_type = alloc_type0; - } - - /* Resource allocation: type0 or type 1 */ - int P = ra_type0_P(nof_prb); - int alloc_size = (int) ceilf((float) nof_prb/P); - switch(data->alloc_type) { - case alloc_type0: - data->type0_alloc.rbg_bitmask = bit_unpack(&y, alloc_size); - break; - case alloc_type1: - data->type1_alloc.rbg_subset = bit_unpack(&y, (int) ceilf(log2f(P))); - data->type1_alloc.shift = *y++?true:false; - data->type1_alloc.vrb_bitmask = bit_unpack(&y, alloc_size - (int) ceilf(log2f(P)) - 1); - break; - default: - fprintf(stderr, "Format 1 accepts type0 or type1 resource allocation only\n"); - return -1; - - } - /* pack MCS according to 7.1.7 of 36.213 */ - uint32_t mcs = bit_unpack(&y, 5); - data->mcs.mcs_idx = mcs; - ra_mcs_from_idx_dl(mcs, &data->mcs); - data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, ra_nprb_dl(data, nof_prb)); - - /* harq process number */ - data->harq_process = bit_unpack(&y, 3); - - data->ndi = *y++?true:false; - - // rv version - data->rv_idx = bit_unpack(&y, 2); - - // TPC not implemented - - - return 0; + /* pack bits */ + char *y = msg->data; + + /* Make sure it's a Format1 message */ + if (msg->location.nof_bits != dci_format_sizeof(Format1, nof_prb)) { + fprintf(stderr, "Invalid message length for format 1\n"); + return -1; + } + + if (nof_prb > 10) { + data->alloc_type = *y++; + } else { + data->alloc_type = alloc_type0; + } + + /* Resource allocation: type0 or type 1 */ + int P = ra_type0_P(nof_prb); + int alloc_size = (int) ceilf((float) nof_prb/P); + switch(data->alloc_type) { + case alloc_type0: + data->type0_alloc.rbg_bitmask = bit_unpack(&y, alloc_size); + break; + case alloc_type1: + data->type1_alloc.rbg_subset = bit_unpack(&y, (int) ceilf(log2f(P))); + data->type1_alloc.shift = *y++?true:false; + data->type1_alloc.vrb_bitmask = bit_unpack(&y, alloc_size - (int) ceilf(log2f(P)) - 1); + break; + default: + fprintf(stderr, "Format 1 accepts type0 or type1 resource allocation only\n"); + return -1; + + } + /* pack MCS according to 7.1.7 of 36.213 */ + uint32_t mcs = bit_unpack(&y, 5); + data->mcs.mcs_idx = mcs; + ra_mcs_from_idx_dl(mcs, &data->mcs); + data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, ra_nprb_dl(data, nof_prb)); + + /* harq process number */ + data->harq_process = bit_unpack(&y, 3); + + data->ndi = *y++?true:false; + + // rv version + data->rv_idx = bit_unpack(&y, 2); + + // TPC not implemented + + + return 0; } @@ -450,96 +450,96 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { */ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb, bool crc_is_crnti) { - /* pack bits */ - char *y = msg->data; - - *y++ = 1; // format differentiation - - if (data->alloc_type != alloc_type2) { - fprintf(stderr, "Format 1A accepts type2 resource allocation only\n"); - return -1; - } - - *y++ = data->type2_alloc.mode; // localized or distributed VRB assignment - - if (data->type2_alloc.mode == t2_loc) { - if (data->type2_alloc.L_crb > nof_prb) { - fprintf(stderr, "L_CRB=%d can not exceed system BW for localized type2\n", data->type2_alloc.L_crb); - return -1; - } - } else { - int n_vrb_dl; - if (crc_is_crnti && nof_prb > 50) { - n_vrb_dl = 16; - } else { - n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap==t2_ng1); - } - if (data->type2_alloc.L_crb > n_vrb_dl) { - fprintf(stderr, "L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n", data->type2_alloc.L_crb, n_vrb_dl); - return -1; - } - } - /* pack RIV according to 7.1.6.3 of 36.213 */ - uint32_t riv; - if (data->type2_alloc.L_crb) { - riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start, nof_prb); - } else { - riv = data->type2_alloc.riv; - } - int nb_gap = 0; - if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) { - nb_gap = 1; - *y++ = data->type2_alloc.n_gap; - } - bit_pack(riv, &y, riv_nbits(nof_prb)-nb_gap); - - // in format1A, MCS = TBS according to 7.1.7.2 of 36.213 - uint32_t mcs; - if (data->mcs.mod == MOD_NULL) { - mcs = data->mcs.mcs_idx; - } else { - if (data->mcs.tbs) { - // In format 1A, n_prb_1a is 2 or 3 if crc is not scrambled with C-RNTI - int n_prb; - if (!crc_is_crnti) { - n_prb = ra_nprb_dl(data, nof_prb); - } else { - n_prb = data->type2_alloc.n_prb1a==nprb1a_2?2:3; - } - data->mcs.tbs_idx = ra_tbs_to_table_idx(data->mcs.tbs, n_prb); - } - mcs = data->mcs.tbs_idx; - } - bit_pack(mcs, &y, 5); - - bit_pack(data->harq_process, &y, 3); - - if (!crc_is_crnti && nof_prb >= 50 && data->type2_alloc.mode == t2_dist) { - *y++ = data->type2_alloc.n_gap; - } else { - y++; // bit reserved - } - - // rv version - bit_pack(data->rv_idx, &y, 2); - - if (crc_is_crnti) { - // TPC not implemented - *y++ = 0; - *y++ = 0; - } else { - y++; // MSB of TPC is reserved - *y++ = data->type2_alloc.n_prb1a; // LSB indicates N_prb_1a for TBS - } - - // Padding with zeros - int n = dci_format1A_sizeof(nof_prb); - while (y-msg->data < n) { - *y++ = 0; - } - msg->location.nof_bits = (y - msg->data); - - return 0; + /* pack bits */ + char *y = msg->data; + + *y++ = 1; // format differentiation + + if (data->alloc_type != alloc_type2) { + fprintf(stderr, "Format 1A accepts type2 resource allocation only\n"); + return -1; + } + + *y++ = data->type2_alloc.mode; // localized or distributed VRB assignment + + if (data->type2_alloc.mode == t2_loc) { + if (data->type2_alloc.L_crb > nof_prb) { + fprintf(stderr, "L_CRB=%d can not exceed system BW for localized type2\n", data->type2_alloc.L_crb); + return -1; + } + } else { + int n_vrb_dl; + if (crc_is_crnti && nof_prb > 50) { + n_vrb_dl = 16; + } else { + n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap==t2_ng1); + } + if (data->type2_alloc.L_crb > n_vrb_dl) { + fprintf(stderr, "L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n", data->type2_alloc.L_crb, n_vrb_dl); + return -1; + } + } + /* pack RIV according to 7.1.6.3 of 36.213 */ + uint32_t riv; + if (data->type2_alloc.L_crb) { + riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start, nof_prb); + } else { + riv = data->type2_alloc.riv; + } + int nb_gap = 0; + if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) { + nb_gap = 1; + *y++ = data->type2_alloc.n_gap; + } + bit_pack(riv, &y, riv_nbits(nof_prb)-nb_gap); + + // in format1A, MCS = TBS according to 7.1.7.2 of 36.213 + uint32_t mcs; + if (data->mcs.mod == MOD_NULL) { + mcs = data->mcs.mcs_idx; + } else { + if (data->mcs.tbs) { + // In format 1A, n_prb_1a is 2 or 3 if crc is not scrambled with C-RNTI + int n_prb; + if (!crc_is_crnti) { + n_prb = ra_nprb_dl(data, nof_prb); + } else { + n_prb = data->type2_alloc.n_prb1a==nprb1a_2?2:3; + } + data->mcs.tbs_idx = ra_tbs_to_table_idx(data->mcs.tbs, n_prb); + } + mcs = data->mcs.tbs_idx; + } + bit_pack(mcs, &y, 5); + + bit_pack(data->harq_process, &y, 3); + + if (!crc_is_crnti && nof_prb >= 50 && data->type2_alloc.mode == t2_dist) { + *y++ = data->type2_alloc.n_gap; + } else { + y++; // bit reserved + } + + // rv version + bit_pack(data->rv_idx, &y, 2); + + if (crc_is_crnti) { + // TPC not implemented + *y++ = 0; + *y++ = 0; + } else { + y++; // MSB of TPC is reserved + *y++ = data->type2_alloc.n_prb1a; // LSB indicates N_prb_1a for TBS + } + + // Padding with zeros + int n = dci_format1A_sizeof(nof_prb); + while (y-msg->data < n) { + *y++ = 0; + } + msg->location.nof_bits = (y - msg->data); + + return 0; } /* Unpacks DCI format 1A for compact scheduling of PDSCH words according to 36.212 5.3.3.1.3 @@ -547,74 +547,74 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb, bool crc_i */ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, bool crc_is_crnti) { - /* pack bits */ - char *y = msg->data; - - /* Make sure it's a Format0 message */ - if (msg->location.nof_bits != dci_format_sizeof(Format1A, nof_prb)) { - fprintf(stderr, "Invalid message length for format 1A\n"); - return -1; - } - if (*y++ != 1) { - fprintf(stderr, "Invalid format differentiation field value. This is Format0\n"); - return -1; - } - - data->alloc_type = alloc_type2; - data->type2_alloc.mode = *y++; - - // by default, set N_gap to 1 - data->type2_alloc.n_gap = t2_ng1; - - /* unpack RIV according to 7.1.6.3 of 36.213 */ - int nb_gap = 0; - if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) { - nb_gap = 1; - data->type2_alloc.n_gap = *y++; - } - int nof_vrb; - if (data->type2_alloc.mode == t2_loc) { - nof_vrb = nof_prb; - } else { - nof_vrb = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1); - } - uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - nb_gap); - ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start, nof_prb, nof_vrb); - data->type2_alloc.riv = riv; - - // unpack MCS - data->mcs.mcs_idx = bit_unpack(&y, 5); - - data->harq_process = bit_unpack(&y, 3); - - if (!crc_is_crnti && nof_prb >= 50 && data->type2_alloc.mode == t2_dist) { - data->type2_alloc.n_gap = *y++; - } else { - y++; // bit reserved - } - - // rv version - bit_pack(data->rv_idx, &y, 2); - - if (crc_is_crnti) { - // TPC not implemented - y++; - y++; - } else { - y++; // MSB of TPC is reserved - *y++ = data->type2_alloc.n_prb1a; // LSB indicates N_prb_1a for TBS - } - data->mcs.tbs_idx = data->mcs.mcs_idx; - int n_prb; - if (crc_is_crnti) { - n_prb = ra_nprb_dl(data, nof_prb); - } else { - n_prb = data->type2_alloc.n_prb1a==nprb1a_2?2:3; - } - data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, n_prb); - data->mcs.mod = QPSK; - - return 0; + /* pack bits */ + char *y = msg->data; + + /* Make sure it's a Format0 message */ + if (msg->location.nof_bits != dci_format_sizeof(Format1A, nof_prb)) { + fprintf(stderr, "Invalid message length for format 1A\n"); + return -1; + } + if (*y++ != 1) { + fprintf(stderr, "Invalid format differentiation field value. This is Format0\n"); + return -1; + } + + data->alloc_type = alloc_type2; + data->type2_alloc.mode = *y++; + + // by default, set N_gap to 1 + data->type2_alloc.n_gap = t2_ng1; + + /* unpack RIV according to 7.1.6.3 of 36.213 */ + int nb_gap = 0; + if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) { + nb_gap = 1; + data->type2_alloc.n_gap = *y++; + } + int nof_vrb; + if (data->type2_alloc.mode == t2_loc) { + nof_vrb = nof_prb; + } else { + nof_vrb = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1); + } + uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - nb_gap); + ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start, nof_prb, nof_vrb); + data->type2_alloc.riv = riv; + + // unpack MCS + data->mcs.mcs_idx = bit_unpack(&y, 5); + + data->harq_process = bit_unpack(&y, 3); + + if (!crc_is_crnti && nof_prb >= 50 && data->type2_alloc.mode == t2_dist) { + data->type2_alloc.n_gap = *y++; + } else { + y++; // bit reserved + } + + // rv version + bit_pack(data->rv_idx, &y, 2); + + if (crc_is_crnti) { + // TPC not implemented + y++; + y++; + } else { + y++; // MSB of TPC is reserved + *y++ = data->type2_alloc.n_prb1a; // LSB indicates N_prb_1a for TBS + } + data->mcs.tbs_idx = data->mcs.mcs_idx; + int n_prb; + if (crc_is_crnti) { + n_prb = ra_nprb_dl(data, nof_prb); + } else { + n_prb = data->type2_alloc.n_prb1a==nprb1a_2?2:3; + } + data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, n_prb); + data->mcs.mod = QPSK; + + return 0; } /* Format 1C for compact scheduling of PDSCH words @@ -622,196 +622,196 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, bool crc */ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb) { - /* pack bits */ - char *y = msg->data; - - if (data->alloc_type != alloc_type2 || data->type2_alloc.mode != t2_dist) { - fprintf(stderr, "Format 1C accepts distributed type2 resource allocation only\n"); - return -1; - } - - if (nof_prb >= 50) { - *y++ = data->type2_alloc.n_gap; - } - int n_step = ra_type2_n_rb_step(nof_prb); - int n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap==t2_ng1); - - if (data->type2_alloc.L_crb > ((int) n_vrb_dl/n_step)*n_step) { - fprintf(stderr, "L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n", data->type2_alloc.L_crb, - ((int) n_vrb_dl/n_step)*n_step); - return -1; - } - if (data->type2_alloc.L_crb % n_step) { - fprintf(stderr, "L_crb must be multiple of n_step\n"); - return -1; - } - if (data->type2_alloc.RB_start % n_step) { - fprintf(stderr, "RB_start must be multiple of n_step\n"); - return -1; - } - int L_p = data->type2_alloc.L_crb/n_step; - int RB_p = data->type2_alloc.RB_start/n_step; - int n_vrb_p = (int) n_vrb_dl / n_step; - - uint32_t riv; - if (data->type2_alloc.L_crb) { - riv = ra_type2_to_riv(L_p, RB_p, n_vrb_p); - } else { - riv = data->type2_alloc.riv; - } - bit_pack(riv, &y, riv_nbits((int) n_vrb_dl/n_step)); - - // in format1C, MCS = TBS according to 7.1.7.2 of 36.213 - uint32_t mcs; - if (data->mcs.mod == MOD_NULL) { - mcs = data->mcs.mcs_idx; - } else { - if (data->mcs.tbs) { - data->mcs.tbs_idx = ra_tbs_to_table_idx_format1c(data->mcs.tbs); - } - mcs = data->mcs.tbs_idx; - } - bit_pack(mcs, &y, 5); - - msg->location.nof_bits = (y - msg->data); - - return 0; + /* pack bits */ + char *y = msg->data; + + if (data->alloc_type != alloc_type2 || data->type2_alloc.mode != t2_dist) { + fprintf(stderr, "Format 1C accepts distributed type2 resource allocation only\n"); + return -1; + } + + if (nof_prb >= 50) { + *y++ = data->type2_alloc.n_gap; + } + int n_step = ra_type2_n_rb_step(nof_prb); + int n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap==t2_ng1); + + if (data->type2_alloc.L_crb > ((int) n_vrb_dl/n_step)*n_step) { + fprintf(stderr, "L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n", data->type2_alloc.L_crb, + ((int) n_vrb_dl/n_step)*n_step); + return -1; + } + if (data->type2_alloc.L_crb % n_step) { + fprintf(stderr, "L_crb must be multiple of n_step\n"); + return -1; + } + if (data->type2_alloc.RB_start % n_step) { + fprintf(stderr, "RB_start must be multiple of n_step\n"); + return -1; + } + int L_p = data->type2_alloc.L_crb/n_step; + int RB_p = data->type2_alloc.RB_start/n_step; + int n_vrb_p = (int) n_vrb_dl / n_step; + + uint32_t riv; + if (data->type2_alloc.L_crb) { + riv = ra_type2_to_riv(L_p, RB_p, n_vrb_p); + } else { + riv = data->type2_alloc.riv; + } + bit_pack(riv, &y, riv_nbits((int) n_vrb_dl/n_step)); + + // in format1C, MCS = TBS according to 7.1.7.2 of 36.213 + uint32_t mcs; + if (data->mcs.mod == MOD_NULL) { + mcs = data->mcs.mcs_idx; + } else { + if (data->mcs.tbs) { + data->mcs.tbs_idx = ra_tbs_to_table_idx_format1c(data->mcs.tbs); + } + mcs = data->mcs.tbs_idx; + } + bit_pack(mcs, &y, 5); + + msg->location.nof_bits = (y - msg->data); + + return 0; } int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { - uint16_t L_p, RB_p; - - /* pack bits */ - char *y = msg->data; - - if (msg->location.nof_bits != dci_format_sizeof(Format1C, nof_prb)) { - fprintf(stderr, "Invalid message length for format 1C\n"); - return -1; - } - data->alloc_type = alloc_type2; - data->type2_alloc.mode = t2_dist; - if (nof_prb >= 50) { - data->type2_alloc.n_gap = *y++; - } - int n_step = ra_type2_n_rb_step(nof_prb); - int n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap==t2_ng1); - - uint32_t riv = bit_unpack(&y, riv_nbits((int) n_vrb_dl/n_step)); - int n_vrb_p = (int) n_vrb_dl / n_step; - - ra_type2_from_riv(riv, &L_p, &RB_p, n_vrb_p, n_vrb_p); - data->type2_alloc.L_crb = L_p * n_step; - data->type2_alloc.RB_start = RB_p * n_step; - data->type2_alloc.riv = riv; - - data->mcs.mcs_idx = bit_unpack(&y, 5); - data->mcs.tbs_idx = data->mcs.mcs_idx; - data->mcs.tbs = ra_tbs_from_idx_format1c(data->mcs.tbs_idx); - data->mcs.mod = QPSK; - - msg->location.nof_bits = (y - msg->data); - - return 0; + uint16_t L_p, RB_p; + + /* pack bits */ + char *y = msg->data; + + if (msg->location.nof_bits != dci_format_sizeof(Format1C, nof_prb)) { + fprintf(stderr, "Invalid message length for format 1C\n"); + return -1; + } + data->alloc_type = alloc_type2; + data->type2_alloc.mode = t2_dist; + if (nof_prb >= 50) { + data->type2_alloc.n_gap = *y++; + } + int n_step = ra_type2_n_rb_step(nof_prb); + int n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap==t2_ng1); + + uint32_t riv = bit_unpack(&y, riv_nbits((int) n_vrb_dl/n_step)); + int n_vrb_p = (int) n_vrb_dl / n_step; + + ra_type2_from_riv(riv, &L_p, &RB_p, n_vrb_p, n_vrb_p); + data->type2_alloc.L_crb = L_p * n_step; + data->type2_alloc.RB_start = RB_p * n_step; + data->type2_alloc.riv = riv; + + data->mcs.mcs_idx = bit_unpack(&y, 5); + data->mcs.tbs_idx = data->mcs.mcs_idx; + data->mcs.tbs = ra_tbs_from_idx_format1c(data->mcs.tbs_idx); + data->mcs.mod = QPSK; + + msg->location.nof_bits = (y - msg->data); + + return 0; } int dci_msg_pack_pdsch(ra_pdsch_t *data, dci_msg_t *msg, dci_format_t format, int nof_prb, bool crc_is_crnti) { - switch(format) { - case Format1: - return dci_format1_pack(data, msg, nof_prb); - case Format1A: - return dci_format1As_pack(data, msg, nof_prb, crc_is_crnti); - case Format1C: - return dci_format1Cs_pack(data, msg, nof_prb); - default: - fprintf(stderr, "Invalid DCI format %s for PDSCH resource allocation\n", dci_format_string(format)); - return -1; - } + switch(format) { + case Format1: + return dci_format1_pack(data, msg, nof_prb); + case Format1A: + return dci_format1As_pack(data, msg, nof_prb, crc_is_crnti); + case Format1C: + return dci_format1Cs_pack(data, msg, nof_prb); + default: + fprintf(stderr, "Invalid DCI format %s for PDSCH resource allocation\n", dci_format_string(format)); + return -1; + } } int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, bool crc_is_crnti) { - if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) { - return dci_format1_unpack(msg, data, nof_prb); - } else if (msg->location.nof_bits == dci_format_sizeof(Format1A, nof_prb)) { - return dci_format1As_unpack(msg, data, nof_prb, crc_is_crnti); - } else if (msg->location.nof_bits == dci_format_sizeof(Format1C, nof_prb)) { - return dci_format1Cs_unpack(msg, data, nof_prb); - } else { - return -1; - } + if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) { + return dci_format1_unpack(msg, data, nof_prb); + } else if (msg->location.nof_bits == dci_format_sizeof(Format1A, nof_prb)) { + return dci_format1As_unpack(msg, data, nof_prb, crc_is_crnti); + } else if (msg->location.nof_bits == dci_format_sizeof(Format1C, nof_prb)) { + return dci_format1Cs_unpack(msg, data, nof_prb); + } else { + return -1; + } } int dci_msg_pack_pusch(ra_pusch_t *data, dci_msg_t *msg, int nof_prb) { - return dci_format0_pack(data, msg, nof_prb); + return dci_format0_pack(data, msg, nof_prb); } int dci_msg_unpack_pusch(dci_msg_t *msg, ra_pusch_t *data, int nof_prb) { - return dci_format0_unpack(msg, data, nof_prb); + return dci_format0_unpack(msg, data, nof_prb); } char* dci_format_string(dci_format_t format) { - switch(format) { - case Format0: - return "Format0"; - case Format1: - return "Format1"; - case Format1A: - return "Format1A"; - case Format1C: - return "Format1C"; - default: - return "N/A"; // fatal error - } + switch(format) { + case Format0: + return "Format0"; + case Format1: + return "Format1"; + case Format1A: + return "Format1A"; + case Format1C: + return "Format1C"; + default: + return "N/A"; // fatal error + } } void dci_msg_type_fprint(FILE *f, dci_msg_type_t type) { - switch(type.type) { - case PUSCH_SCHED: - fprintf(f,"%s PUSCH Scheduling\n", dci_format_string(type.format)); - break; - case PDSCH_SCHED: - fprintf(f,"%s PDSCH Scheduling\n", dci_format_string(type.format)); - break; - case RA_PROC_PDCCH: - fprintf(f,"%s Random access initiated by PDCCH\n", dci_format_string(type.format)); - break; - case MCCH_CHANGE: - fprintf(f,"%s MCCH change notification\n", dci_format_string(type.format)); - break; - case TPC_COMMAND: - fprintf(f,"%s TPC command\n", dci_format_string(type.format)); - break; - } + switch(type.type) { + case PUSCH_SCHED: + fprintf(f,"%s PUSCH Scheduling\n", dci_format_string(type.format)); + break; + case PDSCH_SCHED: + fprintf(f,"%s PDSCH Scheduling\n", dci_format_string(type.format)); + break; + case RA_PROC_PDCCH: + fprintf(f,"%s Random access initiated by PDCCH\n", dci_format_string(type.format)); + break; + case MCCH_CHANGE: + fprintf(f,"%s MCCH change notification\n", dci_format_string(type.format)); + break; + case TPC_COMMAND: + fprintf(f,"%s TPC command\n", dci_format_string(type.format)); + break; + } } int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, int nof_prb, unsigned short crnti) { - if (msg->location.nof_bits == dci_format_sizeof(Format0, nof_prb) - && !msg->data[0]) { - type->type = PUSCH_SCHED; - type->format = Format0; - return 0; - } else if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) { - type->type = PDSCH_SCHED; // only these 2 types supported - type->format = Format1; - return 0; - } else if (msg->location.nof_bits == dci_format_sizeof(Format1A, nof_prb)) { - if (msg->location.rnti == crnti) { - type->type = RA_PROC_PDCCH; - type->format = Format1A; - } else { - type->type = PDSCH_SCHED; // only these 2 types supported - type->format = Format1A; - } - return 0; - } else if (msg->location.nof_bits == dci_format_sizeof(Format1C, nof_prb)) { - if (msg->location.rnti == MRNTI) { - type->type = MCCH_CHANGE; - type->format = Format1C; - } else { - type->type = PDSCH_SCHED; // only these 2 types supported - type->format = Format1C; - } - return 0; - } - return -1; + if (msg->location.nof_bits == dci_format_sizeof(Format0, nof_prb) + && !msg->data[0]) { + type->type = PUSCH_SCHED; + type->format = Format0; + return 0; + } else if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) { + type->type = PDSCH_SCHED; // only these 2 types supported + type->format = Format1; + return 0; + } else if (msg->location.nof_bits == dci_format_sizeof(Format1A, nof_prb)) { + if (msg->location.rnti == crnti) { + type->type = RA_PROC_PDCCH; + type->format = Format1A; + } else { + type->type = PDSCH_SCHED; // only these 2 types supported + type->format = Format1A; + } + return 0; + } else if (msg->location.nof_bits == dci_format_sizeof(Format1C, nof_prb)) { + if (msg->location.rnti == MRNTI) { + type->type = MCCH_CHANGE; + type->format = Format1C; + } else { + type->type = PDSCH_SCHED; // only these 2 types supported + type->format = Format1C; + } + return 0; + } + return -1; } diff --git a/lte/lib/phch/src/pbch.c b/lte/lib/phch/src/pbch.c index 146bc9710..4b1671b7d 100644 --- a/lte/lib/phch/src/pbch.c +++ b/lte/lib/phch/src/pbch.c @@ -43,47 +43,47 @@ #include "lte/utils/debug.h" const char crc_mask[4][16] = { - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1} + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1} }; bool pbch_exists(int nframe, int nslot) { - return (!(nframe % 5) && nslot == 1); + return (!(nframe % 5) && nslot == 1); } int pbch_cp(cf_t *input, cf_t *output, int nof_prb, lte_cp_t cp, int cell_id, bool put) { - int i; - cf_t *ptr; - assert(cell_id >= 0); - if (put) { - ptr = input; - output += nof_prb * RE_X_RB / 2 - 36; - } else { - ptr = output; - input += nof_prb * RE_X_RB / 2 - 36; - } - - /* symbol 0 & 1 */ - for (i=0;i<2;i++) { - prb_cp_ref(&input, &output, cell_id%3, 4, 6, put); - } - /* symbols 2 & 3 */ - if (CP_ISNORM(cp)) { - for (i=0;i<2;i++) { - prb_cp(&input, &output, 6); - } - } else { - prb_cp(&input, &output, 6); - prb_cp_ref(&input, &output, cell_id%3, 4, 6, put); - } - if (put) { - return input - ptr; - } else { - return output - ptr; - } + int i; + cf_t *ptr; + assert(cell_id >= 0); + if (put) { + ptr = input; + output += nof_prb * RE_X_RB / 2 - 36; + } else { + ptr = output; + input += nof_prb * RE_X_RB / 2 - 36; + } + + /* symbol 0 & 1 */ + for (i=0;i<2;i++) { + prb_cp_ref(&input, &output, cell_id%3, 4, 6, put); + } + /* symbols 2 & 3 */ + if (CP_ISNORM(cp)) { + for (i=0;i<2;i++) { + prb_cp(&input, &output, 6); + } + } else { + prb_cp(&input, &output, 6); + prb_cp_ref(&input, &output, cell_id%3, 4, 6, put); + } + if (put) { + return input - ptr; + } else { + return output - ptr; + } } /** @@ -94,7 +94,7 @@ int pbch_cp(cf_t *input, cf_t *output, int nof_prb, lte_cp_t cp, int cell_id, bo * 36.211 10.3 section 6.6.4 */ int pbch_put(cf_t *pbch, cf_t *slot1_data, int nof_prb, lte_cp_t cp, int cell_id) { - return pbch_cp(pbch, slot1_data, nof_prb, cp, cell_id, true); + return pbch_cp(pbch, slot1_data, nof_prb, cp, cell_id, true); } /** @@ -105,176 +105,176 @@ int pbch_put(cf_t *pbch, cf_t *slot1_data, int nof_prb, lte_cp_t cp, int cell_id * 36.211 10.3 section 6.6.4 */ int pbch_get(cf_t *slot1_data, cf_t *pbch, int nof_prb, lte_cp_t cp, int cell_id) { - return pbch_cp(slot1_data, pbch, nof_prb, cp, cell_id, false); + return pbch_cp(slot1_data, pbch, nof_prb, cp, cell_id, false); } /** Initializes the PBCH transmitter and receiver */ int pbch_init(pbch_t *q, int nof_prb, int cell_id, lte_cp_t cp) { - int ret = -1; - if (cell_id < 0) { - return -1; - } - bzero(q, sizeof(pbch_t)); - q->cell_id = cell_id; - q->cp = cp; - q->nof_prb = nof_prb; - - if (modem_table_std(&q->mod, LTE_QPSK, true)) { - goto clean; - } - demod_soft_init(&q->demod); - demod_soft_table_set(&q->demod, &q->mod); - demod_soft_alg_set(&q->demod, APPROX); - if (sequence_pbch(&q->seq_pbch, q->cp, q->cell_id)) { - goto clean; - } - - int poly[3] = {0x6D, 0x4F, 0x57}; - if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) { - goto clean; - } - if (crc_init(&q->crc, LTE_CRC16, 16)) { - goto clean; - } - q->encoder.K = 7; - q->encoder.R = 3; - q->encoder.tail_biting = true; - memcpy(q->encoder.poly, poly, 3 * sizeof(int)); - - q->nof_symbols = (CP_ISNORM(q->cp)) ? PBCH_RE_CPNORM: PBCH_RE_CPEXT; - - q->pbch_d = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->pbch_d) { - goto clean; - } - int i; - for (i=0;ice[i] = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->ce[i]) { - goto clean; - } - q->pbch_x[i] = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->pbch_x[i]) { - goto clean; - } - q->pbch_symbols[i] = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->pbch_symbols[i]) { - goto clean; - } - } - q->pbch_llr = malloc(sizeof(float) * q->nof_symbols * 4 * 2); - if (!q->pbch_llr) { - goto clean; - } - q->temp = malloc(sizeof(float) * q->nof_symbols * 4 * 2); - if (!q->temp) { - goto clean; - } - q->pbch_rm_f = malloc(sizeof(float) * 120); - if (!q->pbch_rm_f) { - goto clean; - } - q->pbch_rm_b = malloc(sizeof(float) * q->nof_symbols * 4 * 2); - if (!q->pbch_rm_b) { - goto clean; - } - q->data = malloc(sizeof(char) * 40); - if (!q->data) { - goto clean; - } - q->data_enc = malloc(sizeof(char) * 120); - if (!q->data_enc) { - goto clean; - } - - ret = 0; + int ret = -1; + if (cell_id < 0) { + return -1; + } + bzero(q, sizeof(pbch_t)); + q->cell_id = cell_id; + q->cp = cp; + q->nof_prb = nof_prb; + + if (modem_table_std(&q->mod, LTE_QPSK, true)) { + goto clean; + } + demod_soft_init(&q->demod); + demod_soft_table_set(&q->demod, &q->mod); + demod_soft_alg_set(&q->demod, APPROX); + if (sequence_pbch(&q->seq_pbch, q->cp, q->cell_id)) { + goto clean; + } + + int poly[3] = {0x6D, 0x4F, 0x57}; + if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) { + goto clean; + } + if (crc_init(&q->crc, LTE_CRC16, 16)) { + goto clean; + } + q->encoder.K = 7; + q->encoder.R = 3; + q->encoder.tail_biting = true; + memcpy(q->encoder.poly, poly, 3 * sizeof(int)); + + q->nof_symbols = (CP_ISNORM(q->cp)) ? PBCH_RE_CPNORM: PBCH_RE_CPEXT; + + q->pbch_d = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->pbch_d) { + goto clean; + } + int i; + for (i=0;ice[i] = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->ce[i]) { + goto clean; + } + q->pbch_x[i] = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->pbch_x[i]) { + goto clean; + } + q->pbch_symbols[i] = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->pbch_symbols[i]) { + goto clean; + } + } + q->pbch_llr = malloc(sizeof(float) * q->nof_symbols * 4 * 2); + if (!q->pbch_llr) { + goto clean; + } + q->temp = malloc(sizeof(float) * q->nof_symbols * 4 * 2); + if (!q->temp) { + goto clean; + } + q->pbch_rm_f = malloc(sizeof(float) * 120); + if (!q->pbch_rm_f) { + goto clean; + } + q->pbch_rm_b = malloc(sizeof(float) * q->nof_symbols * 4 * 2); + if (!q->pbch_rm_b) { + goto clean; + } + q->data = malloc(sizeof(char) * 40); + if (!q->data) { + goto clean; + } + q->data_enc = malloc(sizeof(char) * 120); + if (!q->data_enc) { + goto clean; + } + + ret = 0; clean: - if (ret == -1) { - pbch_free(q); - } - return ret; + if (ret == -1) { + pbch_free(q); + } + return ret; } void pbch_free(pbch_t *q) { - if (q->pbch_d) { - free(q->pbch_d); - } - int i; - for (i=0;ice[i]) { - free(q->ce[i]); - } - if (q->pbch_x[i]) { - free(q->pbch_x[i]); - } - if (q->pbch_symbols[i]) { - free(q->pbch_symbols[i]); - } - } - if (q->pbch_llr) { - free(q->pbch_llr); - } - if (q->temp) { - free(q->temp); - } - if (q->pbch_rm_f) { - free(q->pbch_rm_f); - } - if (q->pbch_rm_b) { - free(q->pbch_rm_b); - } - if (q->data_enc) { - free(q->data_enc); - } - if (q->data) { - free(q->data); - } - sequence_free(&q->seq_pbch); - modem_table_free(&q->mod); - viterbi_free(&q->decoder); + if (q->pbch_d) { + free(q->pbch_d); + } + int i; + for (i=0;ice[i]) { + free(q->ce[i]); + } + if (q->pbch_x[i]) { + free(q->pbch_x[i]); + } + if (q->pbch_symbols[i]) { + free(q->pbch_symbols[i]); + } + } + if (q->pbch_llr) { + free(q->pbch_llr); + } + if (q->temp) { + free(q->temp); + } + if (q->pbch_rm_f) { + free(q->pbch_rm_f); + } + if (q->pbch_rm_b) { + free(q->pbch_rm_b); + } + if (q->data_enc) { + free(q->data_enc); + } + if (q->data) { + free(q->data); + } + sequence_free(&q->seq_pbch); + modem_table_free(&q->mod); + viterbi_free(&q->decoder); } /** Unpacks MIB from PBCH message. * msg buffer must be 24 byte length at least */ void pbch_mib_unpack(char *msg, pbch_mib_t *mib) { - int bw, phich_res; - - bw = bit_unpack(&msg, 3); - switch(bw) { - case 0: - mib->nof_prb = 6; - break; - case 1: - mib->nof_prb = 15; - break; - default: - mib->nof_prb = (bw-1)*25; - break; - } - if (*msg) { - mib->phich_length = PHICH_EXT; - } else { - mib->phich_length = PHICH_NORM; - } - msg++; - - phich_res = bit_unpack(&msg, 2); - switch(phich_res) { - case 0: - mib->phich_resources = R_1_6; - break; - case 1: - mib->phich_resources = R_1_2; - break; - case 2: - mib->phich_resources = R_1; - break; - case 3: - mib->phich_resources = R_2; - break; - } - mib->sfn = bit_unpack(&msg, 8) << 2; + int bw, phich_res; + + bw = bit_unpack(&msg, 3); + switch(bw) { + case 0: + mib->nof_prb = 6; + break; + case 1: + mib->nof_prb = 15; + break; + default: + mib->nof_prb = (bw-1)*25; + break; + } + if (*msg) { + mib->phich_length = PHICH_EXT; + } else { + mib->phich_length = PHICH_NORM; + } + msg++; + + phich_res = bit_unpack(&msg, 2); + switch(phich_res) { + case 0: + mib->phich_resources = R_1_6; + break; + case 1: + mib->phich_resources = R_1_2; + break; + case 2: + mib->phich_resources = R_1; + break; + case 3: + mib->phich_resources = R_2; + break; + } + mib->sfn = bit_unpack(&msg, 8) << 2; } @@ -282,73 +282,73 @@ void pbch_mib_unpack(char *msg, pbch_mib_t *mib) { * msg buffer must be 24 byte length at least */ void pbch_mib_pack(pbch_mib_t *mib, char *msg) { - int bw, phich_res=0; - - bzero(msg, 24); - - if (mib->nof_prb<=6) { - bw = 0; - } else if (mib->nof_prb <= 15) { - bw = 1; - } else { - bw = 1 + mib->nof_prb/25; - } - bit_pack(bw, &msg, 3); - - *msg = mib->phich_length == PHICH_EXT; - msg++; - - switch(mib->phich_resources) { - case R_1_6: - phich_res = 0; - break; - case R_1_2: - phich_res = 1; - break; - case R_1: - phich_res = 2; - break; - case R_2: - phich_res = 3; - break; - } - bit_pack(phich_res, &msg, 2); - bit_pack(mib->sfn >> 2, &msg, 8); + int bw, phich_res=0; + + bzero(msg, 24); + + if (mib->nof_prb<=6) { + bw = 0; + } else if (mib->nof_prb <= 15) { + bw = 1; + } else { + bw = 1 + mib->nof_prb/25; + } + bit_pack(bw, &msg, 3); + + *msg = mib->phich_length == PHICH_EXT; + msg++; + + switch(mib->phich_resources) { + case R_1_6: + phich_res = 0; + break; + case R_1_2: + phich_res = 1; + break; + case R_1: + phich_res = 2; + break; + case R_2: + phich_res = 3; + break; + } + bit_pack(phich_res, &msg, 2); + bit_pack(mib->sfn >> 2, &msg, 8); } void pbch_mib_fprint(FILE *stream, pbch_mib_t *mib) { - printf(" - Nof ports: %d\n", mib->nof_ports); - printf(" - PRB: %d\n", mib->nof_prb); - printf(" - PHICH Length: %s\n", mib->phich_length==PHICH_EXT?"Extended":"Normal"); - printf(" - PHICH Resources: "); - switch(mib->phich_resources) { - case R_1_6: - printf("1/6"); - break; - case R_1_2: - printf("1/2"); - break; - case R_1: - printf("1"); - break; - case R_2: - printf("2"); - break; - } - printf("\n"); - printf(" - SFN: %d\n", mib->sfn); + printf(" - Nof ports: %d\n", mib->nof_ports); + printf(" - PRB: %d\n", mib->nof_prb); + printf(" - PHICH Length: %s\n", mib->phich_length==PHICH_EXT?"Extended":"Normal"); + printf(" - PHICH Resources: "); + switch(mib->phich_resources) { + case R_1_6: + printf("1/6"); + break; + case R_1_2: + printf("1/2"); + break; + case R_1: + printf("1"); + break; + case R_2: + printf("2"); + break; + } + printf("\n"); + printf(" - SFN: %d\n", mib->sfn); } void pbch_decode_reset(pbch_t *q) { - q->frame_idx = 0; + q->frame_idx = 0; } void crc_set_mask(char *data, int nof_ports) { - int i; - for (i=0;i<16;i++) { - data[24+i] = (data[24+i] + crc_mask[nof_ports-1][i]) % 2; - } + int i; + for (i=0;i<16;i++) { + data[24+i] = (data[24+i] + crc_mask[nof_ports-1][i]) % 2; + } } @@ -360,59 +360,59 @@ void crc_set_mask(char *data, int nof_ports) { * Returns 0 if the data is correct, -1 otherwise */ int pbch_crc_check(pbch_t *q, char *bits, int nof_ports) { - char data[40]; - memcpy(data, bits, 40 * sizeof(char)); - crc_set_mask(data, nof_ports); - return crc_checksum(&q->crc, data, 40); + char data[40]; + memcpy(data, bits, 40 * sizeof(char)); + crc_set_mask(data, nof_ports); + return crc_checksum(&q->crc, data, 40); } int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, int src, int dst, int n, int nof_bits, int nof_ports) { - int j; - - memcpy(&q->temp[dst*nof_bits], &q->pbch_llr[src*nof_bits], n*nof_bits*sizeof(float)); - - /* descramble */ - scrambling_f_offset(&q->seq_pbch, &q->temp[dst*nof_bits], dst*nof_bits, n*nof_bits); - - for (j=0;jtemp[j] = RX_NULL; - } - for (j=(dst+n)*nof_bits;j<4*nof_bits;j++) { - q->temp[j] = RX_NULL; - } - - /* unrate matching */ - 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++) { - if (isnan(q->pbch_rm_f[j]) || isinf(q->pbch_rm_f[j])) { - return 0; - } - } - - /* decode */ - viterbi_decode_f(&q->decoder, q->pbch_rm_f, q->data, 40); - - int c=0; - for (j=0;j<40;j++) { - c+=q->data[j]; - } - if (!c) { - c=1; - } - - if (!pbch_crc_check(q, q->data, nof_ports)) { - /* unpack MIB */ - pbch_mib_unpack(q->data, mib); - - mib->nof_ports = nof_ports; - mib->sfn += dst-src; - - return 1; - } else { - return 0; - } + int j; + + memcpy(&q->temp[dst*nof_bits], &q->pbch_llr[src*nof_bits], n*nof_bits*sizeof(float)); + + /* descramble */ + scrambling_f_offset(&q->seq_pbch, &q->temp[dst*nof_bits], dst*nof_bits, n*nof_bits); + + for (j=0;jtemp[j] = RX_NULL; + } + for (j=(dst+n)*nof_bits;j<4*nof_bits;j++) { + q->temp[j] = RX_NULL; + } + + /* unrate matching */ + 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++) { + if (isnan(q->pbch_rm_f[j]) || isinf(q->pbch_rm_f[j])) { + return 0; + } + } + + /* decode */ + viterbi_decode_f(&q->decoder, q->pbch_rm_f, q->data, 40); + + int c=0; + for (j=0;j<40;j++) { + c+=q->data[j]; + } + if (!c) { + c=1; + } + + if (!pbch_crc_check(q, q->data, nof_ports)) { + /* unpack MIB */ + pbch_mib_unpack(q->data, mib); + + mib->nof_ports = nof_ports; + mib->sfn += dst-src; + + return 1; + } else { + return 0; + } } /* Decodes the PBCH channel @@ -424,139 +424,139 @@ int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, int src, int dst, int n, int n * 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[MAX_PORTS_CTRL], float ebno, pbch_mib_t *mib) { - int src, dst, res, nb; - int nant_[3] = {1, 2, 4}; - int na, nant; - - /* Set pointers for layermapping & precoding */ - int i; - int nof_bits = 2 * q->nof_symbols; - cf_t *x[MAX_LAYERS]; - - /* number of layers equals number of ports */ - for (i=0;ipbch_x[i]; - } - memset(&x[MAX_PORTS_CTRL], 0, sizeof(cf_t*) * (MAX_LAYERS - MAX_PORTS_CTRL)); - - /* extract symbols */ - if (q->nof_symbols != pbch_get(slot1_symbols, q->pbch_symbols[0], q->nof_prb, - q->cp, q->cell_id)) { - fprintf(stderr, "There was an error getting the PBCH symbols\n"); - return -1; - } - - /* extract channel estimates */ - for (i=0;inof_symbols != pbch_get(ce[i], q->ce[i], q->nof_prb, - q->cp, q->cell_id)) { - fprintf(stderr, "There was an error getting the PBCH symbols\n"); - return -1; - } - } - - q->frame_idx++; - res = 0; - - /* Try decoding for 1 to 4 antennas */ - for (na=0;na<3 && !res;na++) { - nant = nant_[na]; - - INFO("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, 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, ebno); - 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;nbframe_idx && !res;nb++) { - for (dst=0;(dst<4-nb) && !res;dst++) { - for (src=0;srcframe_idx-nb && !res;src++) { - DEBUG("Trying %d blocks at offset %d as subframe mod4 number %d\n", nb+1, src, dst); - res = 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 res; + int src, dst, res, nb; + int nant_[3] = {1, 2, 4}; + int na, nant; + + /* Set pointers for layermapping & precoding */ + int i; + int nof_bits = 2 * q->nof_symbols; + cf_t *x[MAX_LAYERS]; + + /* number of layers equals number of ports */ + for (i=0;ipbch_x[i]; + } + memset(&x[MAX_PORTS_CTRL], 0, sizeof(cf_t*) * (MAX_LAYERS - MAX_PORTS_CTRL)); + + /* extract symbols */ + if (q->nof_symbols != pbch_get(slot1_symbols, q->pbch_symbols[0], q->nof_prb, + q->cp, q->cell_id)) { + fprintf(stderr, "There was an error getting the PBCH symbols\n"); + return -1; + } + + /* extract channel estimates */ + for (i=0;inof_symbols != pbch_get(ce[i], q->ce[i], q->nof_prb, + q->cp, q->cell_id)) { + fprintf(stderr, "There was an error getting the PBCH symbols\n"); + return -1; + } + } + + q->frame_idx++; + res = 0; + + /* Try decoding for 1 to 4 antennas */ + for (na=0;na<3 && !res;na++) { + nant = nant_[na]; + + INFO("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, 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, ebno); + 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;nbframe_idx && !res;nb++) { + for (dst=0;(dst<4-nb) && !res;dst++) { + for (src=0;srcframe_idx-nb && !res;src++) { + DEBUG("Trying %d blocks at offset %d as subframe mod4 number %d\n", nb+1, src, dst); + res = 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 res; } /** Converts the MIB message to symbols mapped to SLOT #1 ready for transmission */ void pbch_encode(pbch_t *q, pbch_mib_t *mib, cf_t *slot1_symbols[MAX_PORTS_CTRL], int nof_ports) { - int i; - int nof_bits = 2 * q->nof_symbols; + int i; + int nof_bits = 2 * q->nof_symbols; - assert(nof_ports <= MAX_PORTS_CTRL); + assert(nof_ports <= MAX_PORTS_CTRL); - /* Set pointers for layermapping & precoding */ - cf_t *x[MAX_LAYERS]; + /* Set pointers for layermapping & precoding */ + cf_t *x[MAX_LAYERS]; - /* number of layers equals number of ports */ - for (i=0;ipbch_x[i]; - } - memset(&x[nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - nof_ports)); + /* number of layers equals number of ports */ + for (i=0;ipbch_x[i]; + } + memset(&x[nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - nof_ports)); - if (q->frame_idx == 0) { - /* pack MIB */ - pbch_mib_pack(mib, q->data); + if (q->frame_idx == 0) { + /* pack MIB */ + pbch_mib_pack(mib, q->data); - /* encode & modulate */ - crc_attach(&q->crc, q->data, 24); - crc_set_mask(q->data, nof_ports); + /* encode & modulate */ + crc_attach(&q->crc, q->data, 24); + crc_set_mask(q->data, nof_ports); - convcoder_encode(&q->encoder, q->data, q->data_enc, 40); + convcoder_encode(&q->encoder, q->data, q->data_enc, 40); - rm_conv_tx(q->data_enc, 120, q->pbch_rm_b, 4 * nof_bits); + rm_conv_tx(q->data_enc, 120, q->pbch_rm_b, 4 * nof_bits); - } + } - scrambling_b_offset(&q->seq_pbch, &q->pbch_rm_b[q->frame_idx * nof_bits], - q->frame_idx * nof_bits, nof_bits); - mod_modulate(&q->mod, &q->pbch_rm_b[q->frame_idx * nof_bits], q->pbch_d, nof_bits); + scrambling_b_offset(&q->seq_pbch, &q->pbch_rm_b[q->frame_idx * nof_bits], + q->frame_idx * nof_bits, nof_bits); + mod_modulate(&q->mod, &q->pbch_rm_b[q->frame_idx * nof_bits], q->pbch_d, nof_bits); - /* layer mapping & precoding */ - if (nof_ports > 1) { - layermap_diversity(q->pbch_d, x, nof_ports, q->nof_symbols); - precoding_diversity(x, q->pbch_symbols, nof_ports, q->nof_symbols/nof_ports); - } else { - memcpy(q->pbch_symbols[0], q->pbch_d, q->nof_symbols * sizeof(cf_t)); - } + /* layer mapping & precoding */ + if (nof_ports > 1) { + layermap_diversity(q->pbch_d, x, nof_ports, q->nof_symbols); + precoding_diversity(x, q->pbch_symbols, nof_ports, q->nof_symbols/nof_ports); + } else { + memcpy(q->pbch_symbols[0], q->pbch_d, q->nof_symbols * sizeof(cf_t)); + } - /* mapping to resource elements */ - for (i=0;ipbch_symbols[i], slot1_symbols[i], q->nof_prb, q->cp, q->cell_id); - } - q->frame_idx++; - if (q->frame_idx == 4) { - q->frame_idx = 0; - } + /* mapping to resource elements */ + for (i=0;ipbch_symbols[i], slot1_symbols[i], q->nof_prb, q->cp, q->cell_id); + } + q->frame_idx++; + if (q->frame_idx == 4) { + q->frame_idx = 0; + } } diff --git a/lte/lib/phch/src/pcfich.c b/lte/lib/phch/src/pcfich.c index 5422cf54f..4afd56f6b 100644 --- a/lte/lib/phch/src/pcfich.c +++ b/lte/lib/phch/src/pcfich.c @@ -45,84 +45,84 @@ // Table 5.3.4-1 static char cfi_table[4][PCFICH_CFI_LEN] = { - {0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1}, - {1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0}, - {1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // reserved + {0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1}, + {1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0}, + {1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // reserved }; bool pcfich_exists(int nframe, int nslot) { - return true; + return true; } /** Initializes the pcfich channel receiver */ int pcfich_init(pcfich_t *q, regs_t *regs, int cell_id, int nof_prb, int nof_tx_ports, lte_cp_t cp) { - int ret = -1; - if (cell_id < 0) { - return -1; - } - bzero(q, sizeof(pcfich_t)); - q->cell_id = cell_id; - q->cp = cp; - q->regs = regs; - q->nof_prb = nof_prb; - q->nof_tx_ports = nof_tx_ports; - - if (modem_table_std(&q->mod, LTE_QPSK, false)) { - goto clean; - } - - demod_hard_init(&q->demod); - demod_hard_table_set(&q->demod, LTE_QPSK); - - for (int nsf=0;nsfseq_pcfich[nsf], 2*nsf, q->cell_id)) { - goto clean; - } - } - - q->nof_symbols = PCFICH_RE; - - ret = 0; + int ret = -1; + if (cell_id < 0) { + return -1; + } + bzero(q, sizeof(pcfich_t)); + q->cell_id = cell_id; + q->cp = cp; + q->regs = regs; + q->nof_prb = nof_prb; + q->nof_tx_ports = nof_tx_ports; + + if (modem_table_std(&q->mod, LTE_QPSK, false)) { + goto clean; + } + + demod_hard_init(&q->demod); + demod_hard_table_set(&q->demod, LTE_QPSK); + + for (int nsf=0;nsfseq_pcfich[nsf], 2*nsf, q->cell_id)) { + goto clean; + } + } + + q->nof_symbols = PCFICH_RE; + + ret = 0; clean: - if (ret == -1) { - pcfich_free(q); - } - return ret; + if (ret == -1) { + pcfich_free(q); + } + return ret; } void pcfich_free(pcfich_t *q) { - for (int ns=0;nsseq_pcfich[ns]); - } - modem_table_free(&q->mod); + for (int ns=0;nsseq_pcfich[ns]); + } + modem_table_free(&q->mod); } /** Finds the CFI with minimum distance with the vector of received 32 bits. * Saves the CFI value in the cfi pointer and returns the distance. */ int pcfich_cfi_decode(char bits[PCFICH_CFI_LEN], int *cfi) { - int i, j; - int distance, index=-1; - int min = 32; - - for (i=0;i<3;i++) { - distance = 0; - for (j=0;j 3) { - fprintf(stderr, "Invalid CFI %d\n", cfi); - return -1; - } - memcpy(bits, cfi_table[cfi-1], PCFICH_CFI_LEN * sizeof(char)); - return 0; + if (cfi < 1 || cfi > 3) { + fprintf(stderr, "Invalid CFI %d\n", cfi); + return -1; + } + memcpy(bits, cfi_table[cfi-1], PCFICH_CFI_LEN * sizeof(char)); + return 0; } @@ -145,117 +145,117 @@ int pcfich_cfi_encode(int cfi, char bits[PCFICH_CFI_LEN]) { * Returns 1 if successfully decoded the CFI, 0 if not and -1 on error */ int pcfich_decode(pcfich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS_CTRL], int nsubframe, int *cfi, int *distance) { - int dist; - - /* Set pointers for layermapping & precoding */ - int i; - cf_t *x[MAX_LAYERS]; - cf_t *ce_precoding[MAX_PORTS]; - cf_t *symbols_precoding[MAX_PORTS]; - - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid nslot %d\n", nsubframe); - return -1; - } - - /* number of layers equals number of ports */ - for (i=0;ipcfich_x[i]; - } - for (i=0;ice[i]; - symbols_precoding[i] = q->pcfich_symbols[i]; - } - - /* extract symbols */ - if (q->nof_symbols != regs_pcfich_get(q->regs, slot_symbols, q->pcfich_symbols[0])) { - fprintf(stderr, "There was an error getting the PCFICH symbols\n"); - return -1; - } - - /* extract channel estimates */ - for (i=0;inof_tx_ports;i++) { - if (q->nof_symbols != regs_pcfich_get(q->regs, ce[i], q->ce[i])) { - fprintf(stderr, "There was an error getting the PCFICH symbols\n"); - return -1; - } - } - - /* in control channels, only diversity is supported */ - if (q->nof_tx_ports == 1) { - /* no need for layer demapping */ - predecoding_single_zf(q->pcfich_symbols[0], q->ce[0], q->pcfich_d, q->nof_symbols); - } else { - predecoding_diversity_zf(symbols_precoding, ce_precoding, x, q->nof_tx_ports, q->nof_symbols); - layerdemap_diversity(x, q->pcfich_d, q->nof_tx_ports, q->nof_symbols/q->nof_tx_ports); - } - - /* demodulate symbols */ - demod_hard_demodulate(&q->demod, q->pcfich_d, q->data, q->nof_symbols); - - /* Scramble with the sequence for slot nslot */ - scrambling_b(&q->seq_pcfich[nsubframe], q->data); - - /* decode CFI */ - dist = pcfich_cfi_decode(q->data, cfi); - if (distance) { - *distance = dist; - } - if (dist < PCFICH_MAX_DISTANCE) { - return 1; - } else { - return 0; - } + int dist; + + /* Set pointers for layermapping & precoding */ + int i; + cf_t *x[MAX_LAYERS]; + cf_t *ce_precoding[MAX_PORTS]; + cf_t *symbols_precoding[MAX_PORTS]; + + if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { + fprintf(stderr, "Invalid nslot %d\n", nsubframe); + return -1; + } + + /* number of layers equals number of ports */ + for (i=0;ipcfich_x[i]; + } + for (i=0;ice[i]; + symbols_precoding[i] = q->pcfich_symbols[i]; + } + + /* extract symbols */ + if (q->nof_symbols != regs_pcfich_get(q->regs, slot_symbols, q->pcfich_symbols[0])) { + fprintf(stderr, "There was an error getting the PCFICH symbols\n"); + return -1; + } + + /* extract channel estimates */ + for (i=0;inof_tx_ports;i++) { + if (q->nof_symbols != regs_pcfich_get(q->regs, ce[i], q->ce[i])) { + fprintf(stderr, "There was an error getting the PCFICH symbols\n"); + return -1; + } + } + + /* in control channels, only diversity is supported */ + if (q->nof_tx_ports == 1) { + /* no need for layer demapping */ + predecoding_single_zf(q->pcfich_symbols[0], q->ce[0], q->pcfich_d, q->nof_symbols); + } else { + predecoding_diversity_zf(symbols_precoding, ce_precoding, x, q->nof_tx_ports, q->nof_symbols); + layerdemap_diversity(x, q->pcfich_d, q->nof_tx_ports, q->nof_symbols/q->nof_tx_ports); + } + + /* demodulate symbols */ + demod_hard_demodulate(&q->demod, q->pcfich_d, q->data, q->nof_symbols); + + /* Scramble with the sequence for slot nslot */ + scrambling_b(&q->seq_pcfich[nsubframe], q->data); + + /* decode CFI */ + dist = pcfich_cfi_decode(q->data, cfi); + if (distance) { + *distance = dist; + } + if (dist < PCFICH_MAX_DISTANCE) { + return 1; + } else { + return 0; + } } /** Encodes CFI and maps symbols to the slot */ int pcfich_encode(pcfich_t *q, int cfi, cf_t *slot_symbols[MAX_PORTS_CTRL], int nsubframe) { - int i; - - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid nslot %d\n", nsubframe); - return -1; - } - - /* Set pointers for layermapping & precoding */ - cf_t *x[MAX_LAYERS]; - cf_t *symbols_precoding[MAX_PORTS]; - - /* number of layers equals number of ports */ - for (i=0;inof_tx_ports;i++) { - x[i] = q->pcfich_x[i]; - } - for (i=0;ipcfich_symbols[i]; - } - - /* pack MIB */ - pcfich_cfi_encode(cfi, q->data); - - /* scramble for slot sequence nslot */ - scrambling_b(&q->seq_pcfich[nsubframe], q->data); - - mod_modulate(&q->mod, q->data, q->pcfich_d, PCFICH_CFI_LEN); - - /* layer mapping & precoding */ - if (q->nof_tx_ports > 1) { - layermap_diversity(q->pcfich_d, x, q->nof_tx_ports, q->nof_symbols); - precoding_diversity(x, symbols_precoding, q->nof_tx_ports, q->nof_symbols/q->nof_tx_ports); - } else { - memcpy(q->pcfich_symbols[0], q->pcfich_d, q->nof_symbols * sizeof(cf_t)); - } - - /* mapping to resource elements */ - for (i=0;inof_tx_ports;i++) { - if (regs_pcfich_put(q->regs, q->pcfich_symbols[i], slot_symbols[i]) < 0) { - fprintf(stderr, "Error putting PCHICH resource elements\n"); - return -1; - } - } - - return 0; + int i; + + if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { + fprintf(stderr, "Invalid nslot %d\n", nsubframe); + return -1; + } + + /* Set pointers for layermapping & precoding */ + cf_t *x[MAX_LAYERS]; + cf_t *symbols_precoding[MAX_PORTS]; + + /* number of layers equals number of ports */ + for (i=0;inof_tx_ports;i++) { + x[i] = q->pcfich_x[i]; + } + for (i=0;ipcfich_symbols[i]; + } + + /* pack MIB */ + pcfich_cfi_encode(cfi, q->data); + + /* scramble for slot sequence nslot */ + scrambling_b(&q->seq_pcfich[nsubframe], q->data); + + mod_modulate(&q->mod, q->data, q->pcfich_d, PCFICH_CFI_LEN); + + /* layer mapping & precoding */ + if (q->nof_tx_ports > 1) { + layermap_diversity(q->pcfich_d, x, q->nof_tx_ports, q->nof_symbols); + precoding_diversity(x, symbols_precoding, q->nof_tx_ports, q->nof_symbols/q->nof_tx_ports); + } else { + memcpy(q->pcfich_symbols[0], q->pcfich_d, q->nof_symbols * sizeof(cf_t)); + } + + /* mapping to resource elements */ + for (i=0;inof_tx_ports;i++) { + if (regs_pcfich_put(q->regs, q->pcfich_symbols[i], slot_symbols[i]) < 0) { + fprintf(stderr, "Error putting PCHICH resource elements\n"); + return -1; + } + } + + return 0; } diff --git a/lte/lib/phch/src/pdcch.c b/lte/lib/phch/src/pdcch.c index 33bf768ac..700b5f8a7 100644 --- a/lte/lib/phch/src/pdcch.c +++ b/lte/lib/phch/src/pdcch.c @@ -42,15 +42,15 @@ #include "lte/utils/vector.h" #include "lte/utils/debug.h" -#define PDCCH_NOF_FORMATS 4 -#define PDCCH_FORMAT_NOF_CCE(i) (1<b)?b:a) @@ -59,86 +59,86 @@ const dci_format_t ue_formats[NOF_UE_FORMATS] = {Format0, Format1}; // 1A has th * 36.213 9.1 */ int gen_common_search(dci_candidate_t *c, int nof_cce, int nof_bits, unsigned short rnti) { - int i, l, L, k; - k = 0; - for (l = 3; l > 1; l--) { - L = (1 << l); - for (i = 0; i < MIN(nof_cce,16) / (L); i++) { - c[k].L = l; - c[k].nof_bits = nof_bits; - c[k].rnti = rnti; - c[k].ncce = (L) * (i % (nof_cce / (L))); - INFO("Common SS Candidate %d: RNTI: 0x%x, nCCE: %d, Nbits: %d, L: %d\n", - k, c[k].rnti, c[k].ncce, c[k].nof_bits, c[k].L); - k++; - } - } - return k; + int i, l, L, k; + k = 0; + for (l = 3; l > 1; l--) { + L = (1 << l); + for (i = 0; i < MIN(nof_cce,16) / (L); i++) { + c[k].L = l; + c[k].nof_bits = nof_bits; + c[k].rnti = rnti; + c[k].ncce = (L) * (i % (nof_cce / (L))); + INFO("Common SS Candidate %d: RNTI: 0x%x, nCCE: %d, Nbits: %d, L: %d\n", + k, c[k].rnti, c[k].ncce, c[k].nof_bits, c[k].L); + k++; + } + } + return k; } /** * 36.213 9.1 */ int gen_ue_search(dci_candidate_t *c, int nof_cce, int nof_bits, unsigned short rnti, int subframe) { - int i, l, L, k, m; - unsigned int Yk; - const int S[4] = { 6, 12, 8, 16 }; - k = 0; - if (!subframe) { - INFO("UE-specific candidates for RNTI: 0x%x, NofBits: %d, NofCCE: %d\n", - rnti, nof_bits, nof_cce); - if (VERBOSE_ISINFO()) printf("[INFO]: "); - } - for (l = 3; l >= 0; l--) { - L = (1 << l); - for (i = 0; i < MIN(nof_cce/L,16/S[l]); i++) { - c[k].L = l; - c[k].nof_bits = nof_bits; - c[k].rnti = rnti; - Yk = rnti; - for (m = 0; m < subframe; m++) { - Yk = (39827 * Yk) % 65537; - } - c[k].ncce = L * ((Yk + i) % (nof_cce / L)); - if (!subframe) { - if (VERBOSE_ISINFO()) { - printf("(%d, %d), ", c[k].ncce, c[k].L); - } - } - k++; - } - } - if (!subframe) { - if (VERBOSE_ISINFO()) printf("\n"); - } - return k; + int i, l, L, k, m; + unsigned int Yk; + const int S[4] = { 6, 12, 8, 16 }; + k = 0; + if (!subframe) { + INFO("UE-specific candidates for RNTI: 0x%x, NofBits: %d, NofCCE: %d\n", + rnti, nof_bits, nof_cce); + if (VERBOSE_ISINFO()) printf("[INFO]: "); + } + for (l = 3; l >= 0; l--) { + L = (1 << l); + for (i = 0; i < MIN(nof_cce/L,16/S[l]); i++) { + c[k].L = l; + c[k].nof_bits = nof_bits; + c[k].rnti = rnti; + Yk = rnti; + for (m = 0; m < subframe; m++) { + Yk = (39827 * Yk) % 65537; + } + c[k].ncce = L * ((Yk + i) % (nof_cce / L)); + if (!subframe) { + if (VERBOSE_ISINFO()) { + printf("(%d, %d), ", c[k].ncce, c[k].L); + } + } + k++; + } + } + if (!subframe) { + if (VERBOSE_ISINFO()) printf("\n"); + } + return k; } void pdcch_init_common(pdcch_t *q, pdcch_search_t *s, unsigned short rnti) { - int k, i; - s->nof_candidates = NOF_COMMON_FORMATS*(MIN(q->nof_cce,16) / 4 + MIN(q->nof_cce,16) / 8); - if (s->nof_candidates) { - s->candidates[0] = malloc(sizeof(dci_candidate_t) * s->nof_candidates); - dci_candidate_t *c = s->candidates[0]; - s->nof_candidates = 0; - if (c) { - // Format 1A and 1C L=4 and L=8, 4 and 2 candidates, only if nof_cce > 16 - k = 0; - for(i=0;inof_cce, - dci_format_sizeof(common_formats[i], q->nof_prb), SIRNTI); - s->nof_candidates++; - } - } - } + int k, i; + s->nof_candidates = NOF_COMMON_FORMATS*(MIN(q->nof_cce,16) / 4 + MIN(q->nof_cce,16) / 8); + if (s->nof_candidates) { + s->candidates[0] = malloc(sizeof(dci_candidate_t) * s->nof_candidates); + dci_candidate_t *c = s->candidates[0]; + s->nof_candidates = 0; + if (c) { + // Format 1A and 1C L=4 and L=8, 4 and 2 candidates, only if nof_cce > 16 + k = 0; + for(i=0;inof_cce, + dci_format_sizeof(common_formats[i], q->nof_prb), SIRNTI); + s->nof_candidates++; + } + } + } } /** 36.213 v9.3 Table 7.1-1: System Information DCI messages * Expect DCI formats 1C and 1A in the common search space */ void pdcch_init_search_si(pdcch_t *q) { - pdcch_init_common(q, &q->search_mode[SEARCH_SI], SIRNTI); - q->current_search_mode = SEARCH_SI; + pdcch_init_common(q, &q->search_mode[SEARCH_SI], SIRNTI); + q->current_search_mode = SEARCH_SI; } /** 36.213 v9.3 Table 7.1-5 @@ -146,173 +146,173 @@ void pdcch_init_search_si(pdcch_t *q) { * DCI Format 1A and 1 + PUSCH scheduling format 0 */ void pdcch_init_search_ue(pdcch_t *q, unsigned short c_rnti) { - int l, n, k, i; - pdcch_search_t *s = &q->search_mode[SEARCH_UE]; - s->nof_candidates = 0; - for (l=0;l<3;l++) { - s->nof_candidates += NOF_UE_FORMATS*(MIN(q->nof_cce,16) / (1<nof_candidates, c_rnti); - if (s->nof_candidates) { - for (n=0;ncandidates[n] = malloc(sizeof(dci_candidate_t) * s->nof_candidates); - dci_candidate_t *c = s->candidates[n]; - - if (c) { - // Expect Formats 1, 1A, 0 - k = 0; - for(i=0;inof_cce, - dci_format_sizeof(ue_formats[i], q->nof_prb), c_rnti, n); - } - } - } - } - q->current_search_mode = SEARCH_UE; + int l, n, k, i; + pdcch_search_t *s = &q->search_mode[SEARCH_UE]; + s->nof_candidates = 0; + for (l=0;l<3;l++) { + s->nof_candidates += NOF_UE_FORMATS*(MIN(q->nof_cce,16) / (1<nof_candidates, c_rnti); + if (s->nof_candidates) { + for (n=0;ncandidates[n] = malloc(sizeof(dci_candidate_t) * s->nof_candidates); + dci_candidate_t *c = s->candidates[n]; + + if (c) { + // Expect Formats 1, 1A, 0 + k = 0; + for(i=0;inof_cce, + dci_format_sizeof(ue_formats[i], q->nof_prb), c_rnti, n); + } + } + } + } + q->current_search_mode = SEARCH_UE; } /** 36.213 v9.3 Table 7.1-3 * Expect DCI formats 1C and 1A in the common search space */ void pdcch_init_search_ra(pdcch_t *q, unsigned short ra_rnti) { - pdcch_init_common(q, &q->search_mode[SEARCH_RA], ra_rnti); - q->current_search_mode = SEARCH_RA; + pdcch_init_common(q, &q->search_mode[SEARCH_RA], ra_rnti); + q->current_search_mode = SEARCH_RA; } void pdcch_set_search_si(pdcch_t *q) { - q->current_search_mode = SEARCH_SI; + q->current_search_mode = SEARCH_SI; } void pdcch_set_search_ue(pdcch_t *q) { - q->current_search_mode = SEARCH_UE; + q->current_search_mode = SEARCH_UE; } void pdcch_set_search_ra(pdcch_t *q) { - q->current_search_mode = SEARCH_RA; + q->current_search_mode = SEARCH_RA; } /** Initializes the PDCCH transmitter and receiver */ int pdcch_init(pdcch_t *q, regs_t *regs, int nof_prb, int nof_ports, - int cell_id, lte_cp_t cp) { - int ret = -1; - int i; - - if (cell_id < 0) { - return -1; - } - if (nof_ports > MAX_PORTS_CTRL) { - fprintf(stderr, "Invalid number of ports %d\n", nof_ports); - return -1; - } - bzero(q, sizeof(pdcch_t)); - q->cell_id = cell_id; - q->cp = cp; - q->regs = regs; - q->nof_ports = nof_ports; - q->nof_prb = nof_prb; - q->current_search_mode = SEARCH_NONE; - - q->nof_regs = (regs_pdcch_nregs(q->regs)/9)*9; - q->nof_cce = q->nof_regs / 9; - q->nof_symbols = 4 * q->nof_regs; - q->nof_bits = 2 * q->nof_symbols; - - INFO("Init PDCCH: %d CCEs (%d REGs), %d bits, %d symbols, %d ports\n", q->nof_cce, - q->nof_regs, q->nof_bits, q->nof_symbols, q->nof_ports); - - if (modem_table_std(&q->mod, LTE_QPSK, true)) { - goto clean; - } - if (crc_init(&q->crc, LTE_CRC16, 16)) { - goto clean; - } - - demod_soft_init(&q->demod); - demod_soft_table_set(&q->demod, &q->mod); - demod_soft_alg_set(&q->demod, APPROX); - - for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { - if (sequence_pdcch(&q->seq_pdcch[i], 2 * i, q->cell_id, q->nof_bits)) { - goto clean; - } - } - - int poly[3] = { 0x6D, 0x4F, 0x57 }; - if (viterbi_init(&q->decoder, viterbi_37, poly, DCI_MAX_BITS + 16, true)) { - goto clean; - } - - q->pdcch_e = malloc(sizeof(char) * q->nof_bits); - if (!q->pdcch_e) { - goto clean; - } - - q->pdcch_llr = malloc(sizeof(float) * q->nof_bits); - if (!q->pdcch_llr) { - goto clean; - } - - q->pdcch_d = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->pdcch_d) { - goto clean; - } - - for (i = 0; i < MAX_PORTS_CTRL; i++) { - q->ce[i] = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->ce[i]) { - goto clean; - } - q->pdcch_x[i] = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->pdcch_x[i]) { - goto clean; - } - q->pdcch_symbols[i] = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->pdcch_symbols[i]) { - goto clean; - } - } - ret = 0; - clean: if (ret == -1) { - pdcch_free(q); - } - return ret; + int cell_id, lte_cp_t cp) { + int ret = -1; + int i; + + if (cell_id < 0) { + return -1; + } + if (nof_ports > MAX_PORTS_CTRL) { + fprintf(stderr, "Invalid number of ports %d\n", nof_ports); + return -1; + } + bzero(q, sizeof(pdcch_t)); + q->cell_id = cell_id; + q->cp = cp; + q->regs = regs; + q->nof_ports = nof_ports; + q->nof_prb = nof_prb; + q->current_search_mode = SEARCH_NONE; + + q->nof_regs = (regs_pdcch_nregs(q->regs)/9)*9; + q->nof_cce = q->nof_regs / 9; + q->nof_symbols = 4 * q->nof_regs; + q->nof_bits = 2 * q->nof_symbols; + + INFO("Init PDCCH: %d CCEs (%d REGs), %d bits, %d symbols, %d ports\n", q->nof_cce, + q->nof_regs, q->nof_bits, q->nof_symbols, q->nof_ports); + + if (modem_table_std(&q->mod, LTE_QPSK, true)) { + goto clean; + } + if (crc_init(&q->crc, LTE_CRC16, 16)) { + goto clean; + } + + demod_soft_init(&q->demod); + demod_soft_table_set(&q->demod, &q->mod); + demod_soft_alg_set(&q->demod, APPROX); + + for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { + if (sequence_pdcch(&q->seq_pdcch[i], 2 * i, q->cell_id, q->nof_bits)) { + goto clean; + } + } + + int poly[3] = { 0x6D, 0x4F, 0x57 }; + if (viterbi_init(&q->decoder, viterbi_37, poly, DCI_MAX_BITS + 16, true)) { + goto clean; + } + + q->pdcch_e = malloc(sizeof(char) * q->nof_bits); + if (!q->pdcch_e) { + goto clean; + } + + q->pdcch_llr = malloc(sizeof(float) * q->nof_bits); + if (!q->pdcch_llr) { + goto clean; + } + + q->pdcch_d = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->pdcch_d) { + goto clean; + } + + for (i = 0; i < MAX_PORTS_CTRL; i++) { + q->ce[i] = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->ce[i]) { + goto clean; + } + q->pdcch_x[i] = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->pdcch_x[i]) { + goto clean; + } + q->pdcch_symbols[i] = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->pdcch_symbols[i]) { + goto clean; + } + } + ret = 0; + clean: if (ret == -1) { + pdcch_free(q); + } + return ret; } void pdcch_free(pdcch_t *q) { - int i, j; - - for (i=0;isearch_mode[i].candidates[j]) { - free(q->search_mode[i].candidates[j]); - } - } - } - if (q->pdcch_e) { - free(q->pdcch_e); - } - if (q->pdcch_llr) { - free(q->pdcch_llr); - } - if (q->pdcch_d) { - free(q->pdcch_d); - } - for (i = 0; i < MAX_PORTS_CTRL; i++) { - if (q->ce[i]) { - free(q->ce[i]); - } - if (q->pdcch_x[i]) { - free(q->pdcch_x[i]); - } - if (q->pdcch_symbols[i]) { - free(q->pdcch_symbols[i]); - } - } - - for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { - sequence_free(&q->seq_pdcch[i]); - } - - modem_table_free(&q->mod); - viterbi_free(&q->decoder); + int i, j; + + for (i=0;isearch_mode[i].candidates[j]) { + free(q->search_mode[i].candidates[j]); + } + } + } + if (q->pdcch_e) { + free(q->pdcch_e); + } + if (q->pdcch_llr) { + free(q->pdcch_llr); + } + if (q->pdcch_d) { + free(q->pdcch_d); + } + for (i = 0; i < MAX_PORTS_CTRL; i++) { + if (q->ce[i]) { + free(q->ce[i]); + } + if (q->pdcch_x[i]) { + free(q->pdcch_x[i]); + } + if (q->pdcch_symbols[i]) { + free(q->pdcch_symbols[i]); + } + } + + for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { + sequence_free(&q->seq_pdcch[i]); + } + + modem_table_free(&q->mod); + viterbi_free(&q->decoder); } /** 36.212 5.3.3.2 to 5.3.3.4 @@ -322,165 +322,165 @@ void pdcch_free(pdcch_t *q) { * TODO: UE transmit antenna selection CRC mask */ unsigned short dci_decode(pdcch_t *q, float *e, char *data, int E, - int nof_bits) { + int nof_bits) { - float tmp[3 * (DCI_MAX_BITS + 16)]; - unsigned short p_bits, crc_res; - char *x; + float tmp[3 * (DCI_MAX_BITS + 16)]; + unsigned short p_bits, crc_res; + char *x; - assert(nof_bits < DCI_MAX_BITS); + assert(nof_bits < DCI_MAX_BITS); -/* char a[] = {1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0}; +/* char a[] = {1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0}; - float *b = malloc(sizeof(E)); - for (int i=0;idecoder, tmp, data, nof_bits + 16); - - if (VERBOSE_ISDEBUG()) { - bit_fprint(stdout, data, nof_bits+16); - } - - x = &data[nof_bits]; - p_bits = (unsigned short) bit_unpack(&x, 16); - crc_res = ((unsigned short) crc_checksum(&q->crc, data, nof_bits) & 0xffff); - DEBUG("p_bits: 0x%x, crc_res: 0x%x, tot: 0x%x\n", p_bits, crc_res, p_bits ^ crc_res); - return (p_bits ^ crc_res); + /* unrate matching */ + rm_conv_rx(e, E, tmp, 3 * (nof_bits + 16)); + + DEBUG("Viterbi input: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_f(stdout, tmp, 3 * (nof_bits + 16)); + } + + /* viterbi decoder */ + viterbi_decode_f(&q->decoder, tmp, data, nof_bits + 16); + + if (VERBOSE_ISDEBUG()) { + bit_fprint(stdout, data, nof_bits+16); + } + + x = &data[nof_bits]; + p_bits = (unsigned short) bit_unpack(&x, 16); + crc_res = ((unsigned short) crc_checksum(&q->crc, data, nof_bits) & 0xffff); + DEBUG("p_bits: 0x%x, crc_res: 0x%x, tot: 0x%x\n", p_bits, crc_res, p_bits ^ crc_res); + return (p_bits ^ crc_res); } int pdcch_decode_candidate(pdcch_t *q, float *llr, dci_candidate_t *c, - dci_msg_t *msg) { - unsigned short crc_res; - DEBUG("Trying Candidate: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", - c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, - c->rnti); - crc_res = dci_decode(q, &llr[72 * c->ncce], msg->data, - PDCCH_FORMAT_NOF_BITS(c->L), c->nof_bits); - - if (c->rnti == crc_res) { - memcpy(&msg->location, c, sizeof(dci_candidate_t)); - INFO( - "FOUND Candidate: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", - c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, - c->rnti); - return 1; - } - return 0; + dci_msg_t *msg) { + unsigned short crc_res; + DEBUG("Trying Candidate: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", + c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, + c->rnti); + crc_res = dci_decode(q, &llr[72 * c->ncce], msg->data, + PDCCH_FORMAT_NOF_BITS(c->L), c->nof_bits); + + if (c->rnti == crc_res) { + memcpy(&msg->location, c, sizeof(dci_candidate_t)); + INFO( + "FOUND Candidate: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", + c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, + c->rnti); + return 1; + } + return 0; } int pdcch_extract_llr(pdcch_t *q, cf_t *slot1_symbols, cf_t *ce[MAX_PORTS_CTRL], - float *llr, int nsubframe, float ebno) { - - /* Set pointers for layermapping & precoding */ - int i; - cf_t *x[MAX_LAYERS]; - - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid subframe %d\n", nsubframe); - return -1; - } - - if (ebno == 0.0) { - fprintf(stderr, "EbNo is Zero\n"); - return -1; - } - - /* number of layers equals number of ports */ - for (i = 0; i < q->nof_ports; i++) { - x[i] = q->pdcch_x[i]; - } - memset(&x[q->nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->nof_ports)); - - /* extract symbols */ - int n = regs_pdcch_get(q->regs, slot1_symbols, q->pdcch_symbols[0]); - if (q->nof_symbols != n) { - fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", q->nof_symbols, n); - return -1; - } - - /* extract channel estimates */ - for (i = 0; i < q->nof_ports; i++) { - n = regs_pdcch_get(q->regs, ce[i], q->ce[i]); - if (q->nof_symbols != n) { - fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", q->nof_symbols, n); - return -1; - } - } - - /* in control channels, only diversity is supported */ - if (q->nof_ports == 1) { - /* no need for layer demapping */ - predecoding_single_zf(q->pdcch_symbols[0], q->ce[0], q->pdcch_d, - q->nof_symbols); - } else { - predecoding_diversity_zf(q->pdcch_symbols, q->ce, x, q->nof_ports, - q->nof_symbols); - layerdemap_diversity(x, q->pdcch_d, q->nof_ports, - q->nof_symbols / q->nof_ports); - } - - DEBUG("pdcch d symbols: ", 0); - if (VERBOSE_ISDEBUG()) { - vec_fprint_c(stdout, q->pdcch_d, q->nof_symbols); - } - - /* demodulate symbols */ - demod_soft_sigma_set(&q->demod, ebno); - demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, q->nof_symbols); - - DEBUG("llr: ", 0); - if (VERBOSE_ISDEBUG()) { - vec_fprint_f(stdout, q->pdcch_llr, q->nof_bits); - } - - /* descramble */ - scrambling_f_offset(&q->seq_pdcch[nsubframe], llr, 0, q->nof_bits); - - return 0; + float *llr, int nsubframe, float ebno) { + + /* Set pointers for layermapping & precoding */ + int i; + cf_t *x[MAX_LAYERS]; + + if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { + fprintf(stderr, "Invalid subframe %d\n", nsubframe); + return -1; + } + + if (ebno == 0.0) { + fprintf(stderr, "EbNo is Zero\n"); + return -1; + } + + /* number of layers equals number of ports */ + for (i = 0; i < q->nof_ports; i++) { + x[i] = q->pdcch_x[i]; + } + memset(&x[q->nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->nof_ports)); + + /* extract symbols */ + int n = regs_pdcch_get(q->regs, slot1_symbols, q->pdcch_symbols[0]); + if (q->nof_symbols != n) { + fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", q->nof_symbols, n); + return -1; + } + + /* extract channel estimates */ + for (i = 0; i < q->nof_ports; i++) { + n = regs_pdcch_get(q->regs, ce[i], q->ce[i]); + if (q->nof_symbols != n) { + fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", q->nof_symbols, n); + return -1; + } + } + + /* in control channels, only diversity is supported */ + if (q->nof_ports == 1) { + /* no need for layer demapping */ + predecoding_single_zf(q->pdcch_symbols[0], q->ce[0], q->pdcch_d, + q->nof_symbols); + } else { + predecoding_diversity_zf(q->pdcch_symbols, q->ce, x, q->nof_ports, + q->nof_symbols); + layerdemap_diversity(x, q->pdcch_d, q->nof_ports, + q->nof_symbols / q->nof_ports); + } + + DEBUG("pdcch d symbols: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_c(stdout, q->pdcch_d, q->nof_symbols); + } + + /* demodulate symbols */ + demod_soft_sigma_set(&q->demod, ebno); + demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, q->nof_symbols); + + DEBUG("llr: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_f(stdout, q->pdcch_llr, q->nof_bits); + } + + /* descramble */ + scrambling_f_offset(&q->seq_pdcch[nsubframe], llr, 0, q->nof_bits); + + return 0; } int pdcch_decode_current_mode(pdcch_t *q, float *llr, dci_t *dci, int subframe) { - int k, i; - - if (q->current_search_mode == SEARCH_UE) { - k = subframe; - } else { - k = 0; - } - - for (i = 0; i < q->search_mode[q->current_search_mode].nof_candidates - && dci->nof_dcis < dci->max_dcis; i++) { - if (pdcch_decode_candidate(q, q->pdcch_llr, - &q->search_mode[q->current_search_mode].candidates[k][i], - &dci->msg[dci->nof_dcis])) { - dci->nof_dcis++; - } - } - return dci->nof_dcis; + int k, i; + + if (q->current_search_mode == SEARCH_UE) { + k = subframe; + } else { + k = 0; + } + + for (i = 0; i < q->search_mode[q->current_search_mode].nof_candidates + && dci->nof_dcis < dci->max_dcis; i++) { + if (pdcch_decode_candidate(q, q->pdcch_llr, + &q->search_mode[q->current_search_mode].candidates[k][i], + &dci->msg[dci->nof_dcis])) { + dci->nof_dcis++; + } + } + return dci->nof_dcis; } int pdcch_decode_si(pdcch_t *q, float *llr, dci_t *dci) { - pdcch_set_search_si(q); - return pdcch_decode_current_mode(q, llr, dci, 0); + pdcch_set_search_si(q); + return pdcch_decode_current_mode(q, llr, dci, 0); } int pdcch_decode_ra(pdcch_t *q, float *llr, dci_t *dci) { - pdcch_set_search_ra(q); - return pdcch_decode_current_mode(q, llr, dci, 0); + pdcch_set_search_ra(q); + return pdcch_decode_current_mode(q, llr, dci, 0); } int pdcch_decode_ue(pdcch_t *q, float *llr, dci_t *dci, int nsubframe) { - pdcch_set_search_ue(q); - return pdcch_decode_current_mode(q, llr, dci, nsubframe); + pdcch_set_search_ue(q); + return pdcch_decode_current_mode(q, llr, dci, nsubframe); } @@ -491,118 +491,118 @@ int pdcch_decode_ue(pdcch_t *q, float *llr, dci_t *dci, int nsubframe) { * Returns number of messages stored in dci */ int pdcch_decode(pdcch_t *q, cf_t *slot1_symbols, cf_t *ce[MAX_PORTS_CTRL], - dci_t *dci, int nsubframe, float ebno) { + dci_t *dci, int nsubframe, float ebno) { - if (pdcch_extract_llr(q, slot1_symbols, ce, q->pdcch_llr, nsubframe, - ebno)) { - return -1; - } + if (pdcch_extract_llr(q, slot1_symbols, ce, q->pdcch_llr, nsubframe, + ebno)) { + return -1; + } - if (q->current_search_mode != SEARCH_NONE) { - return pdcch_decode_current_mode(q, q->pdcch_llr, dci, nsubframe); - } + if (q->current_search_mode != SEARCH_NONE) { + return pdcch_decode_current_mode(q, q->pdcch_llr, dci, nsubframe); + } - return 0; + return 0; } void crc_set_mask_rnti(char *crc, unsigned short rnti) { - int i; - char mask[16]; - char *r = mask; + int i; + char mask[16]; + char *r = mask; - INFO("Mask CRC with RNTI 0x%x\n", rnti); + INFO("Mask CRC with RNTI 0x%x\n", rnti); - bit_pack(rnti, &r, 16); - for (i = 0; i < 16; i++) { - crc[i] = (crc[i] + mask[i]) % 2; - } + bit_pack(rnti, &r, 16); + for (i = 0; i < 16; i++) { + crc[i] = (crc[i] + mask[i]) % 2; + } } /** 36.212 5.3.3.2 to 5.3.3.4 * TODO: UE transmit antenna selection CRC mask */ void dci_encode(pdcch_t *q, char *data, char *e, int nof_bits, int E, unsigned short rnti) { - convcoder_t encoder; - char tmp[3 * (DCI_MAX_BITS + 16)]; + convcoder_t encoder; + char tmp[3 * (DCI_MAX_BITS + 16)]; - assert(nof_bits < DCI_MAX_BITS); + assert(nof_bits < DCI_MAX_BITS); - int poly[3] = { 0x6D, 0x4F, 0x57 }; - encoder.K = 7; - encoder.R = 3; - encoder.tail_biting = true; - memcpy(encoder.poly, poly, 3 * sizeof(int)); + int poly[3] = { 0x6D, 0x4F, 0x57 }; + encoder.K = 7; + encoder.R = 3; + encoder.tail_biting = true; + memcpy(encoder.poly, poly, 3 * sizeof(int)); - crc_attach(&q->crc, data, nof_bits); - crc_set_mask_rnti(&data[nof_bits], rnti); + crc_attach(&q->crc, data, nof_bits); + crc_set_mask_rnti(&data[nof_bits], rnti); - convcoder_encode(&encoder, data, tmp, nof_bits + 16); + convcoder_encode(&encoder, data, tmp, nof_bits + 16); - DEBUG("CConv output: ", 0); - if (VERBOSE_ISDEBUG()) { - vec_fprint_b(stdout, tmp, 3 * (nof_bits + 16)); - } + DEBUG("CConv output: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_b(stdout, tmp, 3 * (nof_bits + 16)); + } - rm_conv_tx(tmp, 3 * (nof_bits + 16), e, E); + rm_conv_tx(tmp, 3 * (nof_bits + 16), e, E); } /** Converts the MIB message to symbols mapped to SLOT #1 ready for transmission */ int pdcch_encode(pdcch_t *q, dci_t *dci, cf_t *slot1_symbols[MAX_PORTS_CTRL], - int nsubframe) { - int i; - /* Set pointers for layermapping & precoding */ - cf_t *x[MAX_LAYERS]; - - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid subframe %d\n", nsubframe); - return -1; - } - - /* number of layers equals number of ports */ - for (i = 0; i < q->nof_ports; i++) { - x[i] = q->pdcch_x[i]; - } - memset(&x[q->nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->nof_ports)); - - /* should add elements? Or maybe random bits to facilitate power estimation */ - bzero(q->pdcch_e, q->nof_bits); - - /* Encode DCIs */ - for (i = 0; i < dci->nof_dcis; i++) { - /* do some sanity checks */ - if (dci->msg[i].location.ncce + PDCCH_FORMAT_NOF_CCE(dci->msg[i].location.L) > q->nof_cce - || dci->msg[i].location.L > 3 - || dci->msg[i].location.nof_bits > DCI_MAX_BITS) { - fprintf(stderr, "Illegal DCI message %d\n", i); - return -1; - } - INFO("Encoding DCI %d: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", - i, dci->msg[i].location.nof_bits, PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), - dci->msg[i].location.ncce, dci->msg[i].location.L, dci->msg[i].location.rnti); - - dci_encode(q, dci->msg[i].data, &q->pdcch_e[72 * dci->msg[i].location.ncce], - dci->msg[i].location.nof_bits, PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), - dci->msg[i].location.rnti); - } - - scrambling_b_offset(&q->seq_pdcch[nsubframe], q->pdcch_e, 0, q->nof_bits); - - mod_modulate(&q->mod, q->pdcch_e, q->pdcch_d, q->nof_bits); - - /* layer mapping & precoding */ - if (q->nof_ports > 1) { - layermap_diversity(q->pdcch_d, x, q->nof_ports, q->nof_symbols); - precoding_diversity(x, q->pdcch_symbols, q->nof_ports, - q->nof_symbols / q->nof_ports); - } else { - memcpy(q->pdcch_symbols[0], q->pdcch_d, q->nof_symbols * sizeof(cf_t)); - } - - /* mapping to resource elements */ - for (i = 0; i < q->nof_ports; i++) { - regs_pdcch_put(q->regs, q->pdcch_symbols[i], slot1_symbols[i]); - } - return 0; + int nsubframe) { + int i; + /* Set pointers for layermapping & precoding */ + cf_t *x[MAX_LAYERS]; + + if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { + fprintf(stderr, "Invalid subframe %d\n", nsubframe); + return -1; + } + + /* number of layers equals number of ports */ + for (i = 0; i < q->nof_ports; i++) { + x[i] = q->pdcch_x[i]; + } + memset(&x[q->nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->nof_ports)); + + /* should add elements? Or maybe random bits to facilitate power estimation */ + bzero(q->pdcch_e, q->nof_bits); + + /* Encode DCIs */ + for (i = 0; i < dci->nof_dcis; i++) { + /* do some sanity checks */ + if (dci->msg[i].location.ncce + PDCCH_FORMAT_NOF_CCE(dci->msg[i].location.L) > q->nof_cce + || dci->msg[i].location.L > 3 + || dci->msg[i].location.nof_bits > DCI_MAX_BITS) { + fprintf(stderr, "Illegal DCI message %d\n", i); + return -1; + } + INFO("Encoding DCI %d: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", + i, dci->msg[i].location.nof_bits, PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), + dci->msg[i].location.ncce, dci->msg[i].location.L, dci->msg[i].location.rnti); + + dci_encode(q, dci->msg[i].data, &q->pdcch_e[72 * dci->msg[i].location.ncce], + dci->msg[i].location.nof_bits, PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), + dci->msg[i].location.rnti); + } + + scrambling_b_offset(&q->seq_pdcch[nsubframe], q->pdcch_e, 0, q->nof_bits); + + mod_modulate(&q->mod, q->pdcch_e, q->pdcch_d, q->nof_bits); + + /* layer mapping & precoding */ + if (q->nof_ports > 1) { + layermap_diversity(q->pdcch_d, x, q->nof_ports, q->nof_symbols); + precoding_diversity(x, q->pdcch_symbols, q->nof_ports, + q->nof_symbols / q->nof_ports); + } else { + memcpy(q->pdcch_symbols[0], q->pdcch_d, q->nof_symbols * sizeof(cf_t)); + } + + /* mapping to resource elements */ + for (i = 0; i < q->nof_ports; i++) { + regs_pdcch_put(q->regs, q->pdcch_symbols[i], slot1_symbols[i]); + } + return 0; } diff --git a/lte/lib/phch/src/phich.c b/lte/lib/phch/src/phich.c index d38c5ea67..28166dbbe 100644 --- a/lte/lib/phch/src/phich.c +++ b/lte/lib/phch/src/phich.c @@ -44,92 +44,92 @@ /** Table 6.9.1-2 */ const cf_t w_normal[PHICH_NORM_NSEQUENCES][4] = { { 1, 1, 1, 1 }, - { 1, -1, 1, -1 }, { 1, 1, -1, -1 }, { 1, -1, -1, 1 }, { I, I, I, I }, { - I, -I, I, -I }, { I, I, -I, -I }, { I, -I, -I, I } }; + { 1, -1, 1, -1 }, { 1, 1, -1, -1 }, { 1, -1, -1, 1 }, { I, I, I, I }, { + I, -I, I, -I }, { I, I, -I, -I }, { I, -I, -I, I } }; const cf_t w_ext[PHICH_EXT_NSEQUENCES][2] = { { 1, 1 }, { 1, -1 }, { I, I }, { I, -I } }; bool phich_exists(int nframe, int nslot) { - return true; + return true; } int phich_ngroups(phich_t *q) { - return regs_phich_ngroups(q->regs); + return regs_phich_ngroups(q->regs); } void phich_reset(phich_t *q, cf_t *slot_symbols[MAX_PORTS_CTRL]) { - int i; - for (i=0;iregs, slot_symbols[i]); - } + int i; + for (i=0;iregs, slot_symbols[i]); + } } /** Initializes the phich channel receiver */ int phich_init(phich_t *q, regs_t *regs, int cell_id, int nof_prb, - int nof_tx_ports, lte_cp_t cp) { - int ret = -1; - bzero(q, sizeof(phich_t)); - q->cp = cp; - q->regs = regs; - q->nof_prb = nof_prb; - q->nof_tx_ports = nof_tx_ports; - - if (modem_table_std(&q->mod, LTE_BPSK, false)) { - goto clean; - } - - demod_hard_init(&q->demod); - demod_hard_table_set(&q->demod, LTE_BPSK); - - for (int nsf = 0; nsf < NSUBFRAMES_X_FRAME; nsf++) { - if (sequence_phich(&q->seq_phich[nsf], 2 * nsf, cell_id)) { - goto clean; - } - } - - ret = 0; - clean: if (ret == -1) { - phich_free(q); - } - return ret; + int nof_tx_ports, lte_cp_t cp) { + int ret = -1; + bzero(q, sizeof(phich_t)); + q->cp = cp; + q->regs = regs; + q->nof_prb = nof_prb; + q->nof_tx_ports = nof_tx_ports; + + if (modem_table_std(&q->mod, LTE_BPSK, false)) { + goto clean; + } + + demod_hard_init(&q->demod); + demod_hard_table_set(&q->demod, LTE_BPSK); + + for (int nsf = 0; nsf < NSUBFRAMES_X_FRAME; nsf++) { + if (sequence_phich(&q->seq_phich[nsf], 2 * nsf, cell_id)) { + goto clean; + } + } + + ret = 0; + clean: if (ret == -1) { + phich_free(q); + } + return ret; } void phich_free(phich_t *q) { - for (int ns = 0; ns < NSUBFRAMES_X_FRAME; ns++) { - sequence_free(&q->seq_phich[ns]); - } - modem_table_free(&q->mod); + for (int ns = 0; ns < NSUBFRAMES_X_FRAME; ns++) { + sequence_free(&q->seq_phich[ns]); + } + modem_table_free(&q->mod); } /* Decodes ACK * */ char phich_ack_decode(char bits[PHICH_NBITS], int *distance) { - int i, n; - - n = 0; - for (i = 0; i < PHICH_NBITS; i++) { - n += bits[i]; - } - INFO("PHICH decoder: %d, %d, %d\n", bits[0], bits[1], bits[2]); - if (n >= 2) { - if (distance) { - *distance = 3-n; - } - return 1; - } else { - if (distance) { - *distance = n; - } - return 0; - } + int i, n; + + n = 0; + for (i = 0; i < PHICH_NBITS; i++) { + n += bits[i]; + } + INFO("PHICH decoder: %d, %d, %d\n", bits[0], bits[1], bits[2]); + if (n >= 2) { + if (distance) { + *distance = 3-n; + } + return 1; + } else { + if (distance) { + *distance = n; + } + return 0; + } } /** Encodes the ACK * 36.212 */ void phich_ack_encode(char ack, char bits[PHICH_NBITS]) { - memset(bits, ack, 3 * sizeof(char)); + memset(bits, ack, 3 * sizeof(char)); } /* Decodes the phich channel and saves the CFI in the cfi pointer. @@ -137,240 +137,240 @@ void phich_ack_encode(char ack, char bits[PHICH_NBITS]) { * Returns 1 if successfully decoded the CFI, 0 if not and -1 on error */ int phich_decode(phich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS_CTRL], - int ngroup, int nseq, int nsubframe, char *ack, int *distance) { - - /* Set pointers for layermapping & precoding */ - int i, j; - cf_t *x[MAX_LAYERS]; - cf_t *ce_precoding[MAX_PORTS]; - cf_t *symbols_precoding[MAX_PORTS]; - - DEBUG("Decoding PHICH Ngroup: %d, Nseq: %d\n", ngroup, nseq); - - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid nslot %d\n", nsubframe); - return -1; - } - - if (CP_ISEXT(q->cp)) { - if (nseq < 0 || nseq > PHICH_EXT_NSEQUENCES) { - fprintf(stderr, "Invalid nseq %d\n", nseq); - return -1; - } - } else { - if (nseq < 0 || nseq > PHICH_NORM_NSEQUENCES) { - fprintf(stderr, "Invalid nseq %d\n", nseq); - return -1; - } - } - if (ngroup >= regs_phich_ngroups(q->regs)) { - fprintf(stderr, "Invalid ngroup %d\n", ngroup); - return -1; - } - - /* number of layers equals number of ports */ - for (i = 0; i < MAX_PORTS_CTRL; i++) { - x[i] = q->phich_x[i]; - } - for (i = 0; i < MAX_PORTS; i++) { - ce_precoding[i] = q->ce[i]; - symbols_precoding[i] = q->phich_symbols[i]; - } - - /* extract symbols */ - if (PHICH_MAX_NSYMB - != regs_phich_get(q->regs, slot_symbols, q->phich_symbols[0], - ngroup)) { - fprintf(stderr, "There was an error getting the phich symbols\n"); - return -1; - } - - /* extract channel estimates */ - for (i = 0; i < q->nof_tx_ports; i++) { - if (PHICH_MAX_NSYMB - != regs_phich_get(q->regs, ce[i], q->ce[i], ngroup)) { - fprintf(stderr, "There was an error getting the phich symbols\n"); - return -1; - } - } - - /* in control channels, only diversity is supported */ - if (q->nof_tx_ports == 1) { - /* no need for layer demapping */ - predecoding_single_zf(q->phich_symbols[0], q->ce[0], q->phich_d0, - PHICH_MAX_NSYMB); - } else { - predecoding_diversity_zf(symbols_precoding, ce_precoding, x, - q->nof_tx_ports, PHICH_MAX_NSYMB); - layerdemap_diversity(x, q->phich_d0, q->nof_tx_ports, - PHICH_MAX_NSYMB / q->nof_tx_ports); - } - DEBUG("Recv!!: \n",0); - DEBUG("d0: ",0); - if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d0, PHICH_MAX_NSYMB); - - if (CP_ISEXT(q->cp)) { - if (ngroup % 2) { - for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { - q->phich_d[2 * i + 0] = q->phich_d0[4 * i + 2]; - q->phich_d[2 * i + 1] = q->phich_d0[4 * i + 3]; - } - } else { - for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { - q->phich_d[2 * i + 0] = q->phich_d0[4 * i]; - q->phich_d[2 * i + 1] = q->phich_d0[4 * i + 1]; - } - } - } else { - memcpy(q->phich_d, q->phich_d0, PHICH_MAX_NSYMB * sizeof(cf_t)); - } - - DEBUG("d: ",0); - if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d, PHICH_EXT_MSYMB); - - scrambling_c(&q->seq_phich[nsubframe], q->phich_d); - - /* De-spreading */ - if (CP_ISEXT(q->cp)) { - for (i=0;iphich_z[i] = 0; - for (j=0;jphich_z[i] += conjf(w_ext[nseq][j]) * - q->phich_d[i*PHICH_EXT_NSF+j]/PHICH_EXT_NSF; - } - } - } else { - for (i=0;iphich_z[i] = 0; - for (j=0;jphich_z[i] += conjf(w_normal[nseq][j]) * - q->phich_d[i*PHICH_NORM_NSF+j]/PHICH_NORM_NSF; - } - } - } - - DEBUG("z: ",0); - if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_z, PHICH_NBITS); - - demod_hard_demodulate(&q->demod, q->phich_z, q->data, PHICH_NBITS); - - if (ack) { - *ack = phich_ack_decode(q->data, distance); - } - - return 0; + int ngroup, int nseq, int nsubframe, char *ack, int *distance) { + + /* Set pointers for layermapping & precoding */ + int i, j; + cf_t *x[MAX_LAYERS]; + cf_t *ce_precoding[MAX_PORTS]; + cf_t *symbols_precoding[MAX_PORTS]; + + DEBUG("Decoding PHICH Ngroup: %d, Nseq: %d\n", ngroup, nseq); + + if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { + fprintf(stderr, "Invalid nslot %d\n", nsubframe); + return -1; + } + + if (CP_ISEXT(q->cp)) { + if (nseq < 0 || nseq > PHICH_EXT_NSEQUENCES) { + fprintf(stderr, "Invalid nseq %d\n", nseq); + return -1; + } + } else { + if (nseq < 0 || nseq > PHICH_NORM_NSEQUENCES) { + fprintf(stderr, "Invalid nseq %d\n", nseq); + return -1; + } + } + if (ngroup >= regs_phich_ngroups(q->regs)) { + fprintf(stderr, "Invalid ngroup %d\n", ngroup); + return -1; + } + + /* number of layers equals number of ports */ + for (i = 0; i < MAX_PORTS_CTRL; i++) { + x[i] = q->phich_x[i]; + } + for (i = 0; i < MAX_PORTS; i++) { + ce_precoding[i] = q->ce[i]; + symbols_precoding[i] = q->phich_symbols[i]; + } + + /* extract symbols */ + if (PHICH_MAX_NSYMB + != regs_phich_get(q->regs, slot_symbols, q->phich_symbols[0], + ngroup)) { + fprintf(stderr, "There was an error getting the phich symbols\n"); + return -1; + } + + /* extract channel estimates */ + for (i = 0; i < q->nof_tx_ports; i++) { + if (PHICH_MAX_NSYMB + != regs_phich_get(q->regs, ce[i], q->ce[i], ngroup)) { + fprintf(stderr, "There was an error getting the phich symbols\n"); + return -1; + } + } + + /* in control channels, only diversity is supported */ + if (q->nof_tx_ports == 1) { + /* no need for layer demapping */ + predecoding_single_zf(q->phich_symbols[0], q->ce[0], q->phich_d0, + PHICH_MAX_NSYMB); + } else { + predecoding_diversity_zf(symbols_precoding, ce_precoding, x, + q->nof_tx_ports, PHICH_MAX_NSYMB); + layerdemap_diversity(x, q->phich_d0, q->nof_tx_ports, + PHICH_MAX_NSYMB / q->nof_tx_ports); + } + DEBUG("Recv!!: \n",0); + DEBUG("d0: ",0); + if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d0, PHICH_MAX_NSYMB); + + if (CP_ISEXT(q->cp)) { + if (ngroup % 2) { + for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { + q->phich_d[2 * i + 0] = q->phich_d0[4 * i + 2]; + q->phich_d[2 * i + 1] = q->phich_d0[4 * i + 3]; + } + } else { + for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { + q->phich_d[2 * i + 0] = q->phich_d0[4 * i]; + q->phich_d[2 * i + 1] = q->phich_d0[4 * i + 1]; + } + } + } else { + memcpy(q->phich_d, q->phich_d0, PHICH_MAX_NSYMB * sizeof(cf_t)); + } + + DEBUG("d: ",0); + if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d, PHICH_EXT_MSYMB); + + scrambling_c(&q->seq_phich[nsubframe], q->phich_d); + + /* De-spreading */ + if (CP_ISEXT(q->cp)) { + for (i=0;iphich_z[i] = 0; + for (j=0;jphich_z[i] += conjf(w_ext[nseq][j]) * + q->phich_d[i*PHICH_EXT_NSF+j]/PHICH_EXT_NSF; + } + } + } else { + for (i=0;iphich_z[i] = 0; + for (j=0;jphich_z[i] += conjf(w_normal[nseq][j]) * + q->phich_d[i*PHICH_NORM_NSF+j]/PHICH_NORM_NSF; + } + } + } + + DEBUG("z: ",0); + if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_z, PHICH_NBITS); + + demod_hard_demodulate(&q->demod, q->phich_z, q->data, PHICH_NBITS); + + if (ack) { + *ack = phich_ack_decode(q->data, distance); + } + + return 0; } /** Encodes ACK/NACK bits, modulates and inserts into resource. * The parameter ack is an array of phich_ngroups() pointers to buffers of nof_sequences chars */ int phich_encode(phich_t *q, char ack, int ngroup, int nseq, int nsubframe, - cf_t *slot_symbols[MAX_PORTS_CTRL]) { - int i; - - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid nslot %d\n", nsubframe); - return -1; - } - - if (CP_ISEXT(q->cp)) { - if (nseq < 0 || nseq > PHICH_EXT_NSEQUENCES) { - fprintf(stderr, "Invalid nseq %d\n", nseq); - return -1; - } - } else { - if (nseq < 0 || nseq > PHICH_NORM_NSEQUENCES) { - fprintf(stderr, "Invalid nseq %d\n", nseq); - return -1; - } - } - if (ngroup >= regs_phich_ngroups(q->regs)) { - fprintf(stderr, "Invalid ngroup %d\n", ngroup); - return -1; - } - - /* Set pointers for layermapping & precoding */ - cf_t *x[MAX_LAYERS]; - cf_t *symbols_precoding[MAX_PORTS]; - - /* number of layers equals number of ports */ - for (i = 0; i < q->nof_tx_ports; i++) { - x[i] = q->phich_x[i]; - } - for (i = 0; i < MAX_PORTS; i++) { - symbols_precoding[i] = q->phich_symbols[i]; - } - - /* encode ACK/NACK bit */ - phich_ack_encode(ack, q->data); - - mod_modulate(&q->mod, q->data, q->phich_z, PHICH_NBITS); - - DEBUG("data: ",0); - if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_z, PHICH_NBITS); - - /* Spread with w */ - if (CP_ISEXT(q->cp)) { - for (i = 0; i < PHICH_EXT_MSYMB; i++) { - q->phich_d[i] = w_ext[nseq][i % PHICH_EXT_NSF] - * q->phich_z[i / PHICH_EXT_NSF]; - } - } else { - for (i = 0; i < PHICH_NORM_MSYMB; i++) { - q->phich_d[i] = w_normal[nseq][i % PHICH_NORM_NSF] - * q->phich_z[i / PHICH_NORM_NSF]; - } - } - - DEBUG("d: ",0); - if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d, PHICH_EXT_MSYMB); - - scrambling_c(&q->seq_phich[nsubframe], q->phich_d); - - /* align to REG */ - if (CP_ISEXT(q->cp)) { - if (ngroup % 2) { - for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { - q->phich_d0[4 * i + 0] = 0; - q->phich_d0[4 * i + 1] = 0; - q->phich_d0[4 * i + 2] = q->phich_d[2 * i]; - q->phich_d0[4 * i + 3] = q->phich_d[2 * i + 1]; - } - } else { - for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { - q->phich_d0[4 * i + 0] = q->phich_d[2 * i]; - q->phich_d0[4 * i + 1] = q->phich_d[2 * i + 1]; - q->phich_d0[4 * i + 2] = 0; - q->phich_d0[4 * i + 3] = 0; - } - } - } else { - memcpy(q->phich_d0, q->phich_d, PHICH_MAX_NSYMB * sizeof(cf_t)); - } - - DEBUG("d0: ",0); - if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d0, PHICH_MAX_NSYMB); - - - /* layer mapping & precoding */ - if (q->nof_tx_ports > 1) { - layermap_diversity(q->phich_d0, x, q->nof_tx_ports, PHICH_MAX_NSYMB); - precoding_diversity(x, symbols_precoding, q->nof_tx_ports, - PHICH_MAX_NSYMB / q->nof_tx_ports); - /**FIXME: According to 6.9.2, Precoding for 4 tx ports is different! */ - } else { - memcpy(q->phich_symbols[0], q->phich_d0, PHICH_MAX_NSYMB * sizeof(cf_t)); - } - - /* mapping to resource elements */ - for (i = 0; i < q->nof_tx_ports; i++) { - if (regs_phich_add(q->regs, q->phich_symbols[i], ngroup, - slot_symbols[i]) < 0) { - fprintf(stderr, "Error putting PCHICH resource elements\n"); - return -1; - } - } - - return 0; + cf_t *slot_symbols[MAX_PORTS_CTRL]) { + int i; + + if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { + fprintf(stderr, "Invalid nslot %d\n", nsubframe); + return -1; + } + + if (CP_ISEXT(q->cp)) { + if (nseq < 0 || nseq > PHICH_EXT_NSEQUENCES) { + fprintf(stderr, "Invalid nseq %d\n", nseq); + return -1; + } + } else { + if (nseq < 0 || nseq > PHICH_NORM_NSEQUENCES) { + fprintf(stderr, "Invalid nseq %d\n", nseq); + return -1; + } + } + if (ngroup >= regs_phich_ngroups(q->regs)) { + fprintf(stderr, "Invalid ngroup %d\n", ngroup); + return -1; + } + + /* Set pointers for layermapping & precoding */ + cf_t *x[MAX_LAYERS]; + cf_t *symbols_precoding[MAX_PORTS]; + + /* number of layers equals number of ports */ + for (i = 0; i < q->nof_tx_ports; i++) { + x[i] = q->phich_x[i]; + } + for (i = 0; i < MAX_PORTS; i++) { + symbols_precoding[i] = q->phich_symbols[i]; + } + + /* encode ACK/NACK bit */ + phich_ack_encode(ack, q->data); + + mod_modulate(&q->mod, q->data, q->phich_z, PHICH_NBITS); + + DEBUG("data: ",0); + if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_z, PHICH_NBITS); + + /* Spread with w */ + if (CP_ISEXT(q->cp)) { + for (i = 0; i < PHICH_EXT_MSYMB; i++) { + q->phich_d[i] = w_ext[nseq][i % PHICH_EXT_NSF] + * q->phich_z[i / PHICH_EXT_NSF]; + } + } else { + for (i = 0; i < PHICH_NORM_MSYMB; i++) { + q->phich_d[i] = w_normal[nseq][i % PHICH_NORM_NSF] + * q->phich_z[i / PHICH_NORM_NSF]; + } + } + + DEBUG("d: ",0); + if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d, PHICH_EXT_MSYMB); + + scrambling_c(&q->seq_phich[nsubframe], q->phich_d); + + /* align to REG */ + if (CP_ISEXT(q->cp)) { + if (ngroup % 2) { + for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { + q->phich_d0[4 * i + 0] = 0; + q->phich_d0[4 * i + 1] = 0; + q->phich_d0[4 * i + 2] = q->phich_d[2 * i]; + q->phich_d0[4 * i + 3] = q->phich_d[2 * i + 1]; + } + } else { + for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { + q->phich_d0[4 * i + 0] = q->phich_d[2 * i]; + q->phich_d0[4 * i + 1] = q->phich_d[2 * i + 1]; + q->phich_d0[4 * i + 2] = 0; + q->phich_d0[4 * i + 3] = 0; + } + } + } else { + memcpy(q->phich_d0, q->phich_d, PHICH_MAX_NSYMB * sizeof(cf_t)); + } + + DEBUG("d0: ",0); + if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d0, PHICH_MAX_NSYMB); + + + /* layer mapping & precoding */ + if (q->nof_tx_ports > 1) { + layermap_diversity(q->phich_d0, x, q->nof_tx_ports, PHICH_MAX_NSYMB); + precoding_diversity(x, symbols_precoding, q->nof_tx_ports, + PHICH_MAX_NSYMB / q->nof_tx_ports); + /**FIXME: According to 6.9.2, Precoding for 4 tx ports is different! */ + } else { + memcpy(q->phich_symbols[0], q->phich_d0, PHICH_MAX_NSYMB * sizeof(cf_t)); + } + + /* mapping to resource elements */ + for (i = 0; i < q->nof_tx_ports; i++) { + if (regs_phich_add(q->regs, q->phich_symbols[i], ngroup, + slot_symbols[i]) < 0) { + fprintf(stderr, "Error putting PCHICH resource elements\n"); + return -1; + } + } + + return 0; } diff --git a/lte/lib/phch/src/prb.c b/lte/lib/phch/src/prb.c index bf3651867..a51b9d9df 100644 --- a/lte/lib/phch/src/prb.c +++ b/lte/lib/phch/src/prb.c @@ -33,48 +33,48 @@ #include "lte/common/base.h" void prb_cp_ref(cf_t **input, cf_t **output, int offset, int nof_refs, - int nof_prb, bool advance_output) { - int i; + int nof_prb, bool advance_output) { + int i; - int ref_interval = ((RE_X_RB / nof_refs) - 1); - memcpy(*output, *input, offset * sizeof(cf_t)); - *input += offset; - *output += offset; - for (i = 0; i < nof_refs * nof_prb - 1; i++) { - if (advance_output) { - (*output)++; - } else { - (*input)++; - } - memcpy(*output, *input, ref_interval * sizeof(cf_t)); - *output += ref_interval; - *input += ref_interval; - } - if (ref_interval - offset > 0) { - if (advance_output) { - (*output)++; - } else { - (*input)++; - } - memcpy(*output, *input, (ref_interval - offset) * sizeof(cf_t)); - *output += (ref_interval - offset); - *input += (ref_interval - offset); - } + int ref_interval = ((RE_X_RB / nof_refs) - 1); + memcpy(*output, *input, offset * sizeof(cf_t)); + *input += offset; + *output += offset; + for (i = 0; i < nof_refs * nof_prb - 1; i++) { + if (advance_output) { + (*output)++; + } else { + (*input)++; + } + memcpy(*output, *input, ref_interval * sizeof(cf_t)); + *output += ref_interval; + *input += ref_interval; + } + if (ref_interval - offset > 0) { + if (advance_output) { + (*output)++; + } else { + (*input)++; + } + memcpy(*output, *input, (ref_interval - offset) * sizeof(cf_t)); + *output += (ref_interval - offset); + *input += (ref_interval - offset); + } } void prb_cp(cf_t **input, cf_t **output, int nof_prb) { - memcpy(*output, *input, sizeof(cf_t) * RE_X_RB * nof_prb); - *input += nof_prb * RE_X_RB; - *output += nof_prb * RE_X_RB; + memcpy(*output, *input, sizeof(cf_t) * RE_X_RB * nof_prb); + *input += nof_prb * RE_X_RB; + *output += nof_prb * RE_X_RB; } void prb_put_ref_(cf_t **input, cf_t **output, int offset, int nof_refs, - int nof_prb) { - prb_cp_ref(input, output, offset, nof_refs, nof_prb, false); + int nof_prb) { + prb_cp_ref(input, output, offset, nof_refs, nof_prb, false); } void prb_get_ref_(cf_t **input, cf_t **output, int offset, int nof_refs, - int nof_prb) { - prb_cp_ref(input, output, offset, nof_refs, nof_prb, true); + int nof_prb) { + prb_cp_ref(input, output, offset, nof_refs, nof_prb, true); } diff --git a/lte/lib/phch/src/prb.h b/lte/lib/phch/src/prb.h index 4adf29389..328a2e389 100644 --- a/lte/lib/phch/src/prb.h +++ b/lte/lib/phch/src/prb.h @@ -29,9 +29,9 @@ typedef _Complex float cf_t; void prb_cp_ref(cf_t **input, cf_t **output, int offset, int nof_refs, - int nof_prb, bool advance_input); + int nof_prb, bool advance_input); void prb_cp(cf_t **input, cf_t **output, int nof_prb); void prb_put_ref_(cf_t **input, cf_t **output, int offset, int nof_refs, - int nof_prb); + int nof_prb); void phch_get_prb_ref(cf_t **input, cf_t **output, int offset, int nof_refs, - int nof_prb); + int nof_prb); diff --git a/lte/lib/phch/src/ra.c b/lte/lib/phch/src/ra.c index 936d2169a..65c3bea4f 100644 --- a/lte/lib/phch/src/ra.c +++ b/lte/lib/phch/src/ra.c @@ -41,478 +41,478 @@ void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb) { - int i, j, nrows; - nrows = (prb->nof_prb - 1)/ 25 + 1; - for (j=0;jnof_prb-j*25);i++) { - fprintf(f, "%3d, ", prb->prb_idx[j*25+i]); - } - fprintf(f, "\n"); - } + int i, j, nrows; + nrows = (prb->nof_prb - 1)/ 25 + 1; + for (j=0;jnof_prb-j*25);i++) { + fprintf(f, "%3d, ", prb->prb_idx[j*25+i]); + } + fprintf(f, "\n"); + } } /** Compute PRB allocation for Downlink as defined in 8.1 of 36.213 */ int ra_prb_get_ul(ra_prb_slot_t *prb, ra_pusch_t *ra, int nof_prb) { - int i; - if (ra->type2_alloc.mode != t2_loc) { - fprintf(stderr, "Uplink only accepts type2 localized scheduling\n"); - return -1; - } - for (i=0;itype2_alloc.L_crb;i++) { - prb->prb_idx[i] = i+ra->type2_alloc.RB_start; - prb->nof_prb++; - } - return 0; + int i; + if (ra->type2_alloc.mode != t2_loc) { + fprintf(stderr, "Uplink only accepts type2 localized scheduling\n"); + return -1; + } + for (i=0;itype2_alloc.L_crb;i++) { + prb->prb_idx[i] = i+ra->type2_alloc.RB_start; + prb->nof_prb++; + } + return 0; } /** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */ int ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, int nof_prb) { - int i, j; - uint32_t bitmask; - int P = ra_type0_P(nof_prb); - ra_prb_slot_t *prb; - - bzero(prb_dist, sizeof(ra_prb_t)); - switch(ra->alloc_type) { - case alloc_type0: - prb = &prb_dist->slot1; - prb_dist->is_dist = false; - bitmask = ra->type0_alloc.rbg_bitmask; - int nb = (int) ceilf((float)nof_prb/P); - for (i=0;iprb_idx[prb->nof_prb] = i*P+j; - prb->nof_prb++; - } - } - } - break; - case alloc_type1: - prb = &prb_dist->slot1; - prb_dist->is_dist = false; - int n_rb_type1 = ra_type1_N_rb(nof_prb); - int n_rb_rbg_subset; - if (ra->type1_alloc.rbg_subset < (nof_prb/P) % P) { - n_rb_rbg_subset = ((nof_prb-1)/(P*P)) * P + P; - } else if (ra->type1_alloc.rbg_subset == ((nof_prb/P) % P)) { - n_rb_rbg_subset = ((nof_prb-1)/(P*P)) * P + ((nof_prb-1)%P)+1; - } else { - n_rb_rbg_subset = ((nof_prb-1)/(P*P)) * P; - } - int shift = ra->type1_alloc.shift?(n_rb_rbg_subset-n_rb_type1):0; - bitmask = ra->type1_alloc.vrb_bitmask; - for (i=0;iprb_idx[prb->nof_prb] = ((i+shift)/P)*P*P+ - ra->type1_alloc.rbg_subset*P+(i+shift)%P; - prb->nof_prb++; - } - } - break; - case alloc_type2: - if (ra->type2_alloc.mode == t2_loc) { - prb = &prb_dist->slot1; - prb_dist->is_dist = false; - for (i=0;itype2_alloc.L_crb;i++) { - prb->prb_idx[i] = i+ra->type2_alloc.RB_start; - prb->nof_prb++; - } - } else { - /* Mapping of Virtual to Physical RB for distributed type is defined in - * 6.2.3.2 of 36.211 - */ - prb_dist->is_dist = true; - int N_gap, N_tilde_vrb, n_tilde_vrb, n_tilde_prb, n_tilde2_prb, N_null, N_row, n_vrb; - int n_tilde_prb_odd, n_tilde_prb_even; - if (ra->type2_alloc.n_gap == t2_ng1) { - N_tilde_vrb = nof_prb; - N_gap = ra_type2_ngap(nof_prb, true); - } else { - N_tilde_vrb = 2*nof_prb; - N_gap = ra_type2_ngap(nof_prb, false); - } - N_row = (int) ceilf((float) N_tilde_vrb/(4*P))*P; - N_null = 4*N_row-N_tilde_vrb; - for (i=0;itype2_alloc.L_crb;i++) { - n_vrb = i+ra->type2_alloc.RB_start; - n_tilde_vrb = n_vrb%N_tilde_vrb; - n_tilde_prb = 2*N_row*(n_tilde_vrb % 2)+n_tilde_vrb/2+N_tilde_vrb*(n_vrb/N_tilde_vrb); - n_tilde2_prb = N_row*(n_tilde_vrb % 4)+n_tilde_vrb/4+N_tilde_vrb*(n_vrb/N_tilde_vrb); - - if (N_null != 0 && n_tilde_vrb >= (N_tilde_vrb - N_null) && (n_tilde_vrb%2) == 1) { - n_tilde_prb_odd = n_tilde_prb-N_row; - } else if (N_null != 0 && n_tilde_vrb >= (N_tilde_vrb - N_null) && (n_tilde_vrb%2) == 0) { - n_tilde_prb_odd = n_tilde_prb-N_row+N_null/2; - } else if (N_null != 0 && n_tilde_vrb < (N_tilde_vrb - N_null) && (n_tilde_vrb%4) >= 2) { - n_tilde_prb_odd = n_tilde2_prb-N_null/2; - } else { - n_tilde_prb_odd = n_tilde2_prb; - } - n_tilde_prb_even = (n_tilde_prb_odd+N_tilde_vrb/2)%N_tilde_vrb+N_tilde_vrb*(n_vrb/N_tilde_vrb); - - if (n_tilde_prb_odd < N_tilde_vrb/2) { - prb_dist->slot1.prb_idx[i] = n_tilde_prb_odd; - } else { - prb_dist->slot1.prb_idx[i] = n_tilde_prb_odd+N_gap-N_tilde_vrb/2; - } - prb_dist->slot1.nof_prb++; - if (n_tilde_prb_even < N_tilde_vrb/2) { - prb_dist->slot2.prb_idx[i] = n_tilde_prb_even; - } else { - prb_dist->slot2.prb_idx[i] = n_tilde_prb_even+N_gap-N_tilde_vrb/2; - } - prb_dist->slot2.nof_prb++; - } - } - break; - default: - return -1; - } - return 0; + int i, j; + uint32_t bitmask; + int P = ra_type0_P(nof_prb); + ra_prb_slot_t *prb; + + bzero(prb_dist, sizeof(ra_prb_t)); + switch(ra->alloc_type) { + case alloc_type0: + prb = &prb_dist->slot1; + prb_dist->is_dist = false; + bitmask = ra->type0_alloc.rbg_bitmask; + int nb = (int) ceilf((float)nof_prb/P); + for (i=0;iprb_idx[prb->nof_prb] = i*P+j; + prb->nof_prb++; + } + } + } + break; + case alloc_type1: + prb = &prb_dist->slot1; + prb_dist->is_dist = false; + int n_rb_type1 = ra_type1_N_rb(nof_prb); + int n_rb_rbg_subset; + if (ra->type1_alloc.rbg_subset < (nof_prb/P) % P) { + n_rb_rbg_subset = ((nof_prb-1)/(P*P)) * P + P; + } else if (ra->type1_alloc.rbg_subset == ((nof_prb/P) % P)) { + n_rb_rbg_subset = ((nof_prb-1)/(P*P)) * P + ((nof_prb-1)%P)+1; + } else { + n_rb_rbg_subset = ((nof_prb-1)/(P*P)) * P; + } + int shift = ra->type1_alloc.shift?(n_rb_rbg_subset-n_rb_type1):0; + bitmask = ra->type1_alloc.vrb_bitmask; + for (i=0;iprb_idx[prb->nof_prb] = ((i+shift)/P)*P*P+ + ra->type1_alloc.rbg_subset*P+(i+shift)%P; + prb->nof_prb++; + } + } + break; + case alloc_type2: + if (ra->type2_alloc.mode == t2_loc) { + prb = &prb_dist->slot1; + prb_dist->is_dist = false; + for (i=0;itype2_alloc.L_crb;i++) { + prb->prb_idx[i] = i+ra->type2_alloc.RB_start; + prb->nof_prb++; + } + } else { + /* Mapping of Virtual to Physical RB for distributed type is defined in + * 6.2.3.2 of 36.211 + */ + prb_dist->is_dist = true; + int N_gap, N_tilde_vrb, n_tilde_vrb, n_tilde_prb, n_tilde2_prb, N_null, N_row, n_vrb; + int n_tilde_prb_odd, n_tilde_prb_even; + if (ra->type2_alloc.n_gap == t2_ng1) { + N_tilde_vrb = nof_prb; + N_gap = ra_type2_ngap(nof_prb, true); + } else { + N_tilde_vrb = 2*nof_prb; + N_gap = ra_type2_ngap(nof_prb, false); + } + N_row = (int) ceilf((float) N_tilde_vrb/(4*P))*P; + N_null = 4*N_row-N_tilde_vrb; + for (i=0;itype2_alloc.L_crb;i++) { + n_vrb = i+ra->type2_alloc.RB_start; + n_tilde_vrb = n_vrb%N_tilde_vrb; + n_tilde_prb = 2*N_row*(n_tilde_vrb % 2)+n_tilde_vrb/2+N_tilde_vrb*(n_vrb/N_tilde_vrb); + n_tilde2_prb = N_row*(n_tilde_vrb % 4)+n_tilde_vrb/4+N_tilde_vrb*(n_vrb/N_tilde_vrb); + + if (N_null != 0 && n_tilde_vrb >= (N_tilde_vrb - N_null) && (n_tilde_vrb%2) == 1) { + n_tilde_prb_odd = n_tilde_prb-N_row; + } else if (N_null != 0 && n_tilde_vrb >= (N_tilde_vrb - N_null) && (n_tilde_vrb%2) == 0) { + n_tilde_prb_odd = n_tilde_prb-N_row+N_null/2; + } else if (N_null != 0 && n_tilde_vrb < (N_tilde_vrb - N_null) && (n_tilde_vrb%4) >= 2) { + n_tilde_prb_odd = n_tilde2_prb-N_null/2; + } else { + n_tilde_prb_odd = n_tilde2_prb; + } + n_tilde_prb_even = (n_tilde_prb_odd+N_tilde_vrb/2)%N_tilde_vrb+N_tilde_vrb*(n_vrb/N_tilde_vrb); + + if (n_tilde_prb_odd < N_tilde_vrb/2) { + prb_dist->slot1.prb_idx[i] = n_tilde_prb_odd; + } else { + prb_dist->slot1.prb_idx[i] = n_tilde_prb_odd+N_gap-N_tilde_vrb/2; + } + prb_dist->slot1.nof_prb++; + if (n_tilde_prb_even < N_tilde_vrb/2) { + prb_dist->slot2.prb_idx[i] = n_tilde_prb_even; + } else { + prb_dist->slot2.prb_idx[i] = n_tilde_prb_even+N_gap-N_tilde_vrb/2; + } + prb_dist->slot2.nof_prb++; + } + } + break; + default: + return -1; + } + return 0; } /* Returns the number of allocated PRB for Uplink */ int ra_nprb_ul(ra_pusch_t *ra, int nof_prb) { - return ra->type2_alloc.L_crb; + return ra->type2_alloc.L_crb; } /* Returns the number of allocated PRB for Downlink */ int ra_nprb_dl(ra_pdsch_t *ra, int nof_prb) { - int nprb; - int nof_rbg, P; - switch(ra->alloc_type) { - case alloc_type0: - // Get the number of allocated RBG except the last RBG - nof_rbg = bit_count(ra->type0_alloc.rbg_bitmask & 0xFFFFFFFE); - P = ra_type0_P(nof_prb); - if (nof_rbg > (int) ceilf((float)nof_prb/P)) { - fprintf(stderr, "Number of RGB (%d) can not exceed %d\n", nof_prb, - (int) ceilf((float)nof_prb/P)); - return -1; - } - nprb = nof_rbg * P; - - // last RBG may have smaller size. Add if set - int P_last = (nof_prb%P); - if (!P_last) P_last = P; - nprb += P_last*(ra->type0_alloc.rbg_bitmask&1); - break; - case alloc_type1: - nprb = bit_count(ra->type1_alloc.vrb_bitmask); - if (nprb > ra_type1_N_rb(nof_prb)) { - fprintf(stderr, "Number of RB (%d) can not exceed %d\n", nprb, - ra_type1_N_rb(nof_prb)); - return -1; - } - break; - case alloc_type2: - nprb = ra->type2_alloc.L_crb; - break; - default: - return -1; - } - return nprb; + int nprb; + int nof_rbg, P; + switch(ra->alloc_type) { + case alloc_type0: + // Get the number of allocated RBG except the last RBG + nof_rbg = bit_count(ra->type0_alloc.rbg_bitmask & 0xFFFFFFFE); + P = ra_type0_P(nof_prb); + if (nof_rbg > (int) ceilf((float)nof_prb/P)) { + fprintf(stderr, "Number of RGB (%d) can not exceed %d\n", nof_prb, + (int) ceilf((float)nof_prb/P)); + return -1; + } + nprb = nof_rbg * P; + + // last RBG may have smaller size. Add if set + int P_last = (nof_prb%P); + if (!P_last) P_last = P; + nprb += P_last*(ra->type0_alloc.rbg_bitmask&1); + break; + case alloc_type1: + nprb = bit_count(ra->type1_alloc.vrb_bitmask); + if (nprb > ra_type1_N_rb(nof_prb)) { + fprintf(stderr, "Number of RB (%d) can not exceed %d\n", nprb, + ra_type1_N_rb(nof_prb)); + return -1; + } + break; + case alloc_type2: + nprb = ra->type2_alloc.L_crb; + break; + default: + return -1; + } + return nprb; } /* RBG size for type0 scheduling as in table 7.1.6.1-1 of 36.213 */ int ra_type0_P(int nof_prb) { - if (nof_prb <= 10) { - return 1; - } else if (nof_prb <= 26) { - return 2; - } else if (nof_prb <= 63) { - return 3; - } else { - return 4; - } + if (nof_prb <= 10) { + return 1; + } else if (nof_prb <= 26) { + return 2; + } else if (nof_prb <= 63) { + return 3; + } else { + return 4; + } } /* Returns N_rb_type1 according to section 7.1.6.2 */ int ra_type1_N_rb(int nof_prb) { - int P = ra_type0_P(nof_prb); - return (int) ceilf((float) nof_prb/P) - (int) ceilf(log2f((float) P)) - 1; + int P = ra_type0_P(nof_prb); + return (int) ceilf((float) nof_prb/P) - (int) ceilf(log2f((float) P)) - 1; } /* Convert Type2 scheduling L_crb and RB_start to RIV value */ uint32_t ra_type2_to_riv(uint16_t L_crb, uint16_t RB_start, int nof_prb) { - uint32_t riv; - if (L_crb <= (int) nof_prb/2) { - riv = nof_prb*(L_crb-1) + RB_start; - } else { - riv = nof_prb*(nof_prb-L_crb+1) + nof_prb - 1 - RB_start; - } - return riv; + uint32_t riv; + if (L_crb <= (int) nof_prb/2) { + riv = nof_prb*(L_crb-1) + RB_start; + } else { + riv = nof_prb*(nof_prb-L_crb+1) + nof_prb - 1 - RB_start; + } + return riv; } /* Convert Type2 scheduling RIV value to L_crb and RB_start values */ void ra_type2_from_riv(uint32_t riv, uint16_t *L_crb, uint16_t *RB_start, int nof_prb, int nof_vrb) { - *L_crb = (int) (riv/nof_prb) + 1; - *RB_start = riv%nof_prb; - if (*L_crb > nof_vrb - *RB_start) { - *L_crb = nof_prb - (int) (riv/nof_prb) + 1; - *RB_start = nof_prb - riv%nof_prb - 1; - } + *L_crb = (int) (riv/nof_prb) + 1; + *RB_start = riv%nof_prb; + if (*L_crb > nof_vrb - *RB_start) { + *L_crb = nof_prb - (int) (riv/nof_prb) + 1; + *RB_start = nof_prb - riv%nof_prb - 1; + } } /* Table 6.2.3.2-1 in 36.211 */ int ra_type2_ngap(int nof_prb, bool ngap_is_1) { - if (nof_prb <= 10) { - return nof_prb/2; - } else if (nof_prb == 11) { - return 4; - } else if (nof_prb <= 19) { - return 8; - } else if (nof_prb <= 26) { - return 12; - } else if (nof_prb <= 44) { - return 18; - } else if (nof_prb <= 49) { - return 27; - } else if (nof_prb <= 63) { - return ngap_is_1?27:9; - } else if (nof_prb <= 79) { - return ngap_is_1?32:16; - } else { - return ngap_is_1?48:16; - } + if (nof_prb <= 10) { + return nof_prb/2; + } else if (nof_prb == 11) { + return 4; + } else if (nof_prb <= 19) { + return 8; + } else if (nof_prb <= 26) { + return 12; + } else if (nof_prb <= 44) { + return 18; + } else if (nof_prb <= 49) { + return 27; + } else if (nof_prb <= 63) { + return ngap_is_1?27:9; + } else if (nof_prb <= 79) { + return ngap_is_1?32:16; + } else { + return ngap_is_1?48:16; + } } /* Table 7.1.6.3-1 in 36.213 */ int ra_type2_n_rb_step(int nof_prb) { - if (nof_prb < 50) { - return 2; - } else { - return 4; - } + if (nof_prb < 50) { + return 2; + } else { + return 4; + } } /* as defined in 6.2.3.2 of 36.211 */ int ra_type2_n_vrb_dl(int nof_prb, bool ngap_is_1) { - int ngap = ra_type2_ngap(nof_prb, ngap_is_1); - if (ngap_is_1) { - return 2*(ngap<(nof_prb-ngap)?ngap:nof_prb-ngap); - } else { - return ((int) nof_prb/ngap)*2*ngap; - } + int ngap = ra_type2_ngap(nof_prb, ngap_is_1); + if (ngap_is_1) { + return 2*(ngap<(nof_prb-ngap)?ngap:nof_prb-ngap); + } else { + return ((int) nof_prb/ngap)*2*ngap; + } } /* Converts ra_mcs_t structure to MCS index for both Uplink and Downlink */ uint8_t ra_mcs_to_table_idx(ra_mcs_t *mcs) { - switch (mcs->mod) { - case QPSK: - return mcs->tbs_idx; - case QAM16: - return mcs->tbs_idx + 1; - case QAM64: - return mcs->tbs_idx + 2; - default: - return 0; - } + switch (mcs->mod) { + case QPSK: + return mcs->tbs_idx; + case QAM16: + return mcs->tbs_idx + 1; + case QAM64: + return mcs->tbs_idx + 2; + default: + return 0; + } } /* Converts MCS index to ra_mcs_t structure for Downlink as defined inTable 7.1.7.1-1 on 36.213 */ int ra_mcs_from_idx_dl(uint8_t idx, ra_mcs_t *mcs) { - if (idx < 10) { - mcs->mod = QPSK; - mcs->tbs_idx = idx; - } else if (idx < 17) { - mcs->mod = QAM16; - mcs->tbs_idx = idx-1; - } else if (idx < 29) { - mcs->mod = QAM64; - mcs->tbs_idx = idx-2; - } else if (idx == 29) { - mcs->mod = QPSK; - mcs->tbs_idx = 0; - } else if (idx == 30) { - mcs->mod = QAM16; - mcs->tbs_idx = 0; - } else if (idx == 31) { - mcs->mod = QAM64; - mcs->tbs_idx = 0; - } else { - mcs->mod = MOD_NULL; - mcs->tbs_idx = 0; - return -1; - } - return 0; + if (idx < 10) { + mcs->mod = QPSK; + mcs->tbs_idx = idx; + } else if (idx < 17) { + mcs->mod = QAM16; + mcs->tbs_idx = idx-1; + } else if (idx < 29) { + mcs->mod = QAM64; + mcs->tbs_idx = idx-2; + } else if (idx == 29) { + mcs->mod = QPSK; + mcs->tbs_idx = 0; + } else if (idx == 30) { + mcs->mod = QAM16; + mcs->tbs_idx = 0; + } else if (idx == 31) { + mcs->mod = QAM64; + mcs->tbs_idx = 0; + } else { + mcs->mod = MOD_NULL; + mcs->tbs_idx = 0; + return -1; + } + return 0; } /* Converts MCS index to ra_mcs_t structure for Uplink as defined in Table 8.6.1-1 on 36.213 */ int ra_mcs_from_idx_ul(uint8_t idx, ra_mcs_t *mcs) { - if (idx < 11) { - mcs->mod = QPSK; - mcs->tbs_idx = idx; - } else if (idx < 21) { - mcs->mod = QAM16; - mcs->tbs_idx = idx-1; - } else if (idx < 29) { - mcs->mod = QAM64; - mcs->tbs_idx = idx-2; - } else { - mcs->mod = MOD_NULL; - mcs->tbs_idx = 0; - return -1; - } - return 0; + if (idx < 11) { + mcs->mod = QPSK; + mcs->tbs_idx = idx; + } else if (idx < 21) { + mcs->mod = QAM16; + mcs->tbs_idx = idx-1; + } else if (idx < 29) { + mcs->mod = QAM64; + mcs->tbs_idx = idx-2; + } else { + mcs->mod = MOD_NULL; + mcs->tbs_idx = 0; + return -1; + } + return 0; } /* Downlink Transport Block size for Format 1C as defined in 7.1.7.2.2-1 on 36.213 */ int ra_tbs_from_idx_format1c(uint8_t tbs_idx) { - if (tbs_idx < 32) { - return tbs_format1c_table[tbs_idx]; - } else { - return -1; - } + if (tbs_idx < 32) { + return tbs_format1c_table[tbs_idx]; + } else { + return -1; + } } /* Returns lowest nearest index of TBS value in table 7.1.7.2.2-1 on 36.213 * or -1 if the TBS value is not within the valid TBS values */ int ra_tbs_to_table_idx_format1c(int tbs) { - int idx; - if (tbs < tbs_format1c_table[0]) { - return -1; - } - for (idx=1;idx<32;idx++) { - if (tbs_format1c_table[idx-1] <= tbs && - tbs_format1c_table[idx] >= tbs) { - return idx; - } - } - return -1; + int idx; + if (tbs < tbs_format1c_table[0]) { + return -1; + } + for (idx=1;idx<32;idx++) { + if (tbs_format1c_table[idx-1] <= tbs && + tbs_format1c_table[idx] >= tbs) { + return idx; + } + } + return -1; } /* Downlink Transport Block size determination as defined in 7.1.7.2 on 36.213 */ int ra_tbs_from_idx(uint8_t tbs_idx, int n_prb ) { - if (tbs_idx < 27 && n_prb > 0 && n_prb <= 110) { - return tbs_table[tbs_idx][n_prb-1]; - } else { - return -1; - } + if (tbs_idx < 27 && n_prb > 0 && n_prb <= 110) { + return tbs_table[tbs_idx][n_prb-1]; + } else { + return -1; + } } /* Returns lowest nearest index of TBS value in table 7.1.7.2 on 36.213 * or -1 if the TBS value is not within the valid TBS values */ int ra_tbs_to_table_idx(int tbs, int n_prb) { - int idx; - if (n_prb > 0 && n_prb <= 110) { - return -1; - } - if (tbs < tbs_table[0][n_prb]) { - return -1; - } - for (idx=1;idx<28;idx++) { - if (tbs_table[idx-1][n_prb] <= tbs && - tbs_table[idx][n_prb] >= tbs) { - return idx; - } - } - return -1; + int idx; + if (n_prb > 0 && n_prb <= 110) { + return -1; + } + if (tbs < tbs_table[0][n_prb]) { + return -1; + } + for (idx=1;idx<28;idx++) { + if (tbs_table[idx-1][n_prb] <= tbs && + tbs_table[idx][n_prb] >= tbs) { + return idx; + } + } + return -1; } char *ra_mod_string(ra_mod_t mod) { - switch (mod) { - case QPSK: - return "QPSK"; - case QAM16: - return "QAM16"; - case QAM64: - return "QAM64"; - default: - return "N/A"; - } + switch (mod) { + case QPSK: + return "QPSK"; + case QAM16: + return "QAM16"; + case QAM64: + return "QAM64"; + default: + return "N/A"; + } } void ra_pusch_fprint(FILE *f, ra_pusch_t *ra, int nof_prb) { - fprintf(f, "Frequency Hopping:\t"); - if (ra->freq_hop_fl == hop_disabled) { - fprintf(f, "No"); - } else { - fprintf(f, "Yes"); + fprintf(f, "Frequency Hopping:\t"); + if (ra->freq_hop_fl == hop_disabled) { + fprintf(f, "No"); + } else { + fprintf(f, "Yes"); - } + } } char *ra_type_string(ra_type_t alloc_type) { - switch(alloc_type) { - case alloc_type0: - return "Type 0"; - case alloc_type1: - return "Type 1"; - case alloc_type2: - return "Type 2"; - default: - return "N/A"; - } + switch(alloc_type) { + case alloc_type0: + return "Type 0"; + case alloc_type1: + return "Type 1"; + case alloc_type2: + return "Type 2"; + default: + return "N/A"; + } } void ra_pdsch_set_mcs_index(ra_pdsch_t *ra, uint8_t mcs_idx) { - ra->mcs.mod = MOD_NULL; - ra->mcs.mcs_idx = mcs_idx; + ra->mcs.mod = MOD_NULL; + ra->mcs.mcs_idx = mcs_idx; } void ra_pdsch_set_mcs(ra_pdsch_t *ra, ra_mod_t mod, uint8_t tbs_idx) { - ra->mcs.mod = mod; - ra->mcs.tbs_idx = tbs_idx; + ra->mcs.mod = mod; + ra->mcs.tbs_idx = tbs_idx; } void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, int nof_prb) { - fprintf(f, " - Resource Allocation Type:\t\t%s\n",ra_type_string(ra->alloc_type)); - switch(ra->alloc_type) { - case alloc_type0: - fprintf(f, " + Resource Block Group Size:\t\t%d\n",ra_type0_P(nof_prb)); - fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n",ra->type0_alloc.rbg_bitmask); - break; - case alloc_type1: - fprintf(f, " + Resource Block Group Size:\t\t%d\n",ra_type0_P(nof_prb)); - fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n",ra->type1_alloc.vrb_bitmask); - fprintf(f, " + RBG Subset:\t\t\t%d\n",ra->type1_alloc.rbg_subset); - fprintf(f, " + RBG Shift:\t\t\t\t%s\n",ra->type1_alloc.shift?"Yes":"No"); - break; - case alloc_type2: - fprintf(f, " + Type:\t\t\t\t%s\n", - ra->type2_alloc.mode==t2_loc?"Localized":"Distributed"); - fprintf(f, " + Resource Indicator Value:\t\t%d\n",ra->type2_alloc.riv); - if (ra->type2_alloc.mode == t2_loc) { - fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", - ra->type2_alloc.L_crb, ra->type2_alloc.RB_start); - } else { - fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", - ra->type2_alloc.L_crb, ra->type2_alloc.RB_start); - fprintf(f, " + VRB gap selection:\t\t\tGap %d\n", - ra->type2_alloc.n_gap == t2_ng1?1:2); - fprintf(f, " + VRB gap:\t\t\t\t%d\n", - ra_type2_ngap(nof_prb, ra->type2_alloc.n_gap == t2_ng1)); - } - break; - } - - ra_prb_t alloc; - ra_prb_get_dl(&alloc, ra, nof_prb); - if (alloc.is_dist) { - fprintf(f, " - PRB Bitmap Assignment 1st slot:\n"); - ra_prb_fprint(f, &alloc.slot1); - fprintf(f, " - PRB Bitmap Assignment 2nd slot:\n"); - ra_prb_fprint(f, &alloc.slot2); - } else { - fprintf(f, " - PRB Bitmap Assignment:\n"); - ra_prb_fprint(f, &alloc.slot1); - } - - fprintf(f, " - Number of PRBs:\t\t\t%d\n", ra_nprb_dl(ra, nof_prb)); - fprintf(f, " - Modulation and coding scheme index:\t%d\n", ra->mcs.mcs_idx); - fprintf(f, " - Modulation type:\t\t\t%s\n", ra_mod_string(ra->mcs.mod)); - fprintf(f, " - Transport block size:\t\t%d\n", ra->mcs.tbs); - fprintf(f, " - HARQ process:\t\t\t%d\n", ra->harq_process); - fprintf(f, " - New data indicator:\t\t\t%s\n", ra->ndi?"Yes":"No"); - fprintf(f, " - Redundancy version:\t\t\t%d\n", ra->rv_idx); - fprintf(f, " - TPC command for PUCCH:\t\t--\n"); + fprintf(f, " - Resource Allocation Type:\t\t%s\n",ra_type_string(ra->alloc_type)); + switch(ra->alloc_type) { + case alloc_type0: + fprintf(f, " + Resource Block Group Size:\t\t%d\n",ra_type0_P(nof_prb)); + fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n",ra->type0_alloc.rbg_bitmask); + break; + case alloc_type1: + fprintf(f, " + Resource Block Group Size:\t\t%d\n",ra_type0_P(nof_prb)); + fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n",ra->type1_alloc.vrb_bitmask); + fprintf(f, " + RBG Subset:\t\t\t%d\n",ra->type1_alloc.rbg_subset); + fprintf(f, " + RBG Shift:\t\t\t\t%s\n",ra->type1_alloc.shift?"Yes":"No"); + break; + case alloc_type2: + fprintf(f, " + Type:\t\t\t\t%s\n", + ra->type2_alloc.mode==t2_loc?"Localized":"Distributed"); + fprintf(f, " + Resource Indicator Value:\t\t%d\n",ra->type2_alloc.riv); + if (ra->type2_alloc.mode == t2_loc) { + fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", + ra->type2_alloc.L_crb, ra->type2_alloc.RB_start); + } else { + fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", + ra->type2_alloc.L_crb, ra->type2_alloc.RB_start); + fprintf(f, " + VRB gap selection:\t\t\tGap %d\n", + ra->type2_alloc.n_gap == t2_ng1?1:2); + fprintf(f, " + VRB gap:\t\t\t\t%d\n", + ra_type2_ngap(nof_prb, ra->type2_alloc.n_gap == t2_ng1)); + } + break; + } + + ra_prb_t alloc; + ra_prb_get_dl(&alloc, ra, nof_prb); + if (alloc.is_dist) { + fprintf(f, " - PRB Bitmap Assignment 1st slot:\n"); + ra_prb_fprint(f, &alloc.slot1); + fprintf(f, " - PRB Bitmap Assignment 2nd slot:\n"); + ra_prb_fprint(f, &alloc.slot2); + } else { + fprintf(f, " - PRB Bitmap Assignment:\n"); + ra_prb_fprint(f, &alloc.slot1); + } + + fprintf(f, " - Number of PRBs:\t\t\t%d\n", ra_nprb_dl(ra, nof_prb)); + fprintf(f, " - Modulation and coding scheme index:\t%d\n", ra->mcs.mcs_idx); + fprintf(f, " - Modulation type:\t\t\t%s\n", ra_mod_string(ra->mcs.mod)); + fprintf(f, " - Transport block size:\t\t%d\n", ra->mcs.tbs); + fprintf(f, " - HARQ process:\t\t\t%d\n", ra->harq_process); + fprintf(f, " - New data indicator:\t\t\t%s\n", ra->ndi?"Yes":"No"); + fprintf(f, " - Redundancy version:\t\t\t%d\n", ra->rv_idx); + fprintf(f, " - TPC command for PUCCH:\t\t--\n"); } diff --git a/lte/lib/phch/src/regs.c b/lte/lib/phch/src/regs.c index 6583dbdc3..ad7bbfb62 100644 --- a/lte/lib/phch/src/regs.c +++ b/lte/lib/phch/src/regs.c @@ -44,137 +44,137 @@ regs_reg_t *regs_find_reg(regs_t *h, int k, int l); ***************************************************************/ void regs_pdcch_free(regs_t *h) { - int i; - for (i=0;i<3;i++) { - if (h->pdcch[i].regs) { - free(h->pdcch[i].regs); - } - } + int i; + for (i=0;i<3;i++) { + if (h->pdcch[i].regs) { + free(h->pdcch[i].regs); + } + } } -#define PDCCH_NCOLS 32 +#define PDCCH_NCOLS 32 const unsigned char PDCCH_PERM[PDCCH_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 }; + { 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 }; /** Initialize REGs for PDCCH * 36.211 10.3 section 6.8.5 */ int regs_pdcch_init(regs_t *h) { - int i, m, cfi, nof_ctrl_symbols; - int ret = -1; - int nrows, ndummy, j, k, kp; - regs_reg_t **tmp = NULL; - - bzero(&h->pdcch, sizeof(regs_ch_t)); - - for (cfi=0;cfi<3;cfi++) { - if (h->nof_prb < 10) { - nof_ctrl_symbols = cfi+2; - } else { - nof_ctrl_symbols = cfi+1; - } - - tmp = malloc(sizeof(regs_reg_t*) * h->nof_regs); - if (!tmp) { - perror("malloc"); - goto clean_and_exit; - } - - /* Number and count REGs for this CFI */ - m=0; - for (i=0;inof_regs;i++) { - if (h->regs[i].l < nof_ctrl_symbols && !h->regs[i].assigned) { - tmp[m] = &h->regs[i]; - m++; - } - } - - h->pdcch[cfi].nof_regs = m; - - h->pdcch[cfi].regs = malloc(sizeof(regs_reg_t*) * h->pdcch[cfi].nof_regs); - if (!h->pdcch[cfi].regs) { - perror("malloc"); - goto clean_and_exit; - } - - /* Interleave REGs */ - nrows = (h->pdcch[cfi].nof_regs-1)/PDCCH_NCOLS+1; - ndummy = PDCCH_NCOLS*nrows - h->pdcch[cfi].nof_regs; - if (ndummy < 0) { - ndummy = 0; - } - - k=0; - for (j = 0; j < PDCCH_NCOLS; j++) { - for (i = 0; i < nrows; i++) { - if (i*PDCCH_NCOLS + PDCCH_PERM[j] >= ndummy) { - m = i*PDCCH_NCOLS + PDCCH_PERM[j]-ndummy; - kp = (k-h->cell_id)%h->pdcch[cfi].nof_regs; - if (kp < 0) { - kp += h->pdcch[cfi].nof_regs; - } - h->pdcch[cfi].regs[m] = tmp[kp]; - k++; - } - } - } - h->pdcch[cfi].nof_regs = (h->pdcch[cfi].nof_regs/9)*9; - free(tmp); - tmp = NULL; - if (VERBOSE_ISINFO() && cfi == 1) { - for (i=0;ipdcch[cfi].nof_regs;i++) { - INFO("Logical PDCCH REG#%d:%d (%d,%d)\n", i%9,i/9, - h->pdcch[cfi].regs[i]->k0, h->pdcch[cfi].regs[i]->l); - } - } - } - - ret = 0; + int i, m, cfi, nof_ctrl_symbols; + int ret = -1; + int nrows, ndummy, j, k, kp; + regs_reg_t **tmp = NULL; + + bzero(&h->pdcch, sizeof(regs_ch_t)); + + for (cfi=0;cfi<3;cfi++) { + if (h->nof_prb < 10) { + nof_ctrl_symbols = cfi+2; + } else { + nof_ctrl_symbols = cfi+1; + } + + tmp = malloc(sizeof(regs_reg_t*) * h->nof_regs); + if (!tmp) { + perror("malloc"); + goto clean_and_exit; + } + + /* Number and count REGs for this CFI */ + m=0; + for (i=0;inof_regs;i++) { + if (h->regs[i].l < nof_ctrl_symbols && !h->regs[i].assigned) { + tmp[m] = &h->regs[i]; + m++; + } + } + + h->pdcch[cfi].nof_regs = m; + + h->pdcch[cfi].regs = malloc(sizeof(regs_reg_t*) * h->pdcch[cfi].nof_regs); + if (!h->pdcch[cfi].regs) { + perror("malloc"); + goto clean_and_exit; + } + + /* Interleave REGs */ + nrows = (h->pdcch[cfi].nof_regs-1)/PDCCH_NCOLS+1; + ndummy = PDCCH_NCOLS*nrows - h->pdcch[cfi].nof_regs; + if (ndummy < 0) { + ndummy = 0; + } + + k=0; + for (j = 0; j < PDCCH_NCOLS; j++) { + for (i = 0; i < nrows; i++) { + if (i*PDCCH_NCOLS + PDCCH_PERM[j] >= ndummy) { + m = i*PDCCH_NCOLS + PDCCH_PERM[j]-ndummy; + kp = (k-h->cell_id)%h->pdcch[cfi].nof_regs; + if (kp < 0) { + kp += h->pdcch[cfi].nof_regs; + } + h->pdcch[cfi].regs[m] = tmp[kp]; + k++; + } + } + } + h->pdcch[cfi].nof_regs = (h->pdcch[cfi].nof_regs/9)*9; + free(tmp); + tmp = NULL; + if (VERBOSE_ISINFO() && cfi == 1) { + for (i=0;ipdcch[cfi].nof_regs;i++) { + INFO("Logical PDCCH REG#%d:%d (%d,%d)\n", i%9,i/9, + h->pdcch[cfi].regs[i]->k0, h->pdcch[cfi].regs[i]->l); + } + } + } + + ret = 0; clean_and_exit: - if (tmp) { - free(tmp); - } - if (ret == -1) { - regs_pdcch_free(h); - } - return ret; + if (tmp) { + free(tmp); + } + if (ret == -1) { + regs_pdcch_free(h); + } + return ret; } int regs_pdcch_nregs(regs_t *h) { - if (h->cfi == -1) { - fprintf(stderr, "Must call regs_set_cfi() first\n"); - return -1; - } else { - return h->pdcch[h->cfi].nof_regs; - } + if (h->cfi == -1) { + fprintf(stderr, "Must call regs_set_cfi() first\n"); + return -1; + } else { + return h->pdcch[h->cfi].nof_regs; + } } /** Copy quadruplets to REGs and cyclic shift them, according to the * second part of 6.8.5 in 36.211 */ int regs_pdcch_put(regs_t *h, cf_t *pdcch_symbols, cf_t *slot_symbols) { - if (h->cfi == -1) { - fprintf(stderr, "Must call regs_set_cfi() first\n"); - return -1; - } - int i; - for (i=0;ipdcch[h->cfi].nof_regs;i++) { - regs_put_reg(h->pdcch[h->cfi].regs[i], &pdcch_symbols[i*4], slot_symbols, h->nof_prb); - } - return h->pdcch[h->cfi].nof_regs*4; + if (h->cfi == -1) { + fprintf(stderr, "Must call regs_set_cfi() first\n"); + return -1; + } + int i; + for (i=0;ipdcch[h->cfi].nof_regs;i++) { + regs_put_reg(h->pdcch[h->cfi].regs[i], &pdcch_symbols[i*4], slot_symbols, h->nof_prb); + } + return h->pdcch[h->cfi].nof_regs*4; } int regs_pdcch_get(regs_t *h, cf_t *slot_symbols, cf_t *pdcch_symbols) { - if (h->cfi == -1) { - fprintf(stderr, "Must call regs_set_cfi() first\n"); - return -1; - } - int i; - for (i=0;ipdcch[h->cfi].nof_regs;i++) { - regs_get_reg(h->pdcch[h->cfi].regs[i], slot_symbols, &pdcch_symbols[i*4], h->nof_prb); - } - return h->pdcch[h->cfi].nof_regs*4; + if (h->cfi == -1) { + fprintf(stderr, "Must call regs_set_cfi() first\n"); + return -1; + } + int i; + for (i=0;ipdcch[h->cfi].nof_regs;i++) { + regs_get_reg(h->pdcch[h->cfi].regs[i], slot_symbols, &pdcch_symbols[i*4], h->nof_prb); + } + return h->pdcch[h->cfi].nof_regs*4; } @@ -190,138 +190,138 @@ int regs_pdcch_get(regs_t *h, cf_t *slot_symbols, cf_t *pdcch_symbols) { * 36.211 10.3 section 6.9.3 */ int regs_phich_init(regs_t *h) { - float ng; - int i,ni,li,n[3],nreg,mi; - regs_reg_t **regs_phich[3]; - int ret = -1; - - switch(h->phich_res) { - case R_1_6: - ng = (float) 1/6; - break; - case R_1_2: - ng = (float) 1/2; - break; - case R_1: - ng = 1; - break; - case R_2: - ng = 2; - break; - default: - ng = 0; - break; - } - h->ngroups_phich = (int) ceilf(ng * ((float) h->nof_prb/8)); - h->phich = malloc(sizeof(regs_ch_t) * h->ngroups_phich); - if (!h->phich) { - perror("malloc"); - return -1; - } - INFO("Creating %d PHICH mapping units. %s length, Ng=%.2f\n",h->ngroups_phich, - h->phich_len==PHICH_EXT?"Extended":"Normal",ng); - for (i=0;ingroups_phich;i++) { - h->phich[i].nof_regs = REGS_PHICH_REGS_X_GROUP; - h->phich[i].regs = malloc(sizeof(regs_reg_t*) * REGS_PHICH_REGS_X_GROUP); - if (!h->phich[i].regs) { - perror("malloc"); - goto clean_and_exit; - } - } - - /** Here begins the mapping algorithm */ - - /* Step 2. Count REGs not assigned to PCFICH */ - bzero(n, 3*sizeof(int)); - for (i=0;inof_regs;i++) { - if (h->regs[i].l < 3 && !h->regs[i].assigned) { - n[h->regs[i].l]++; - } - } - - bzero(regs_phich, sizeof(regs_reg_t*) * 3); - for (i=0;i<3;i++) { - regs_phich[i] = malloc(n[i] * sizeof(regs_reg_t*)); - if (!regs_phich[i]) { - perror("malloc"); - goto clean_and_exit; - } - } - - bzero(n, 3 * sizeof(int)); - /* Step 3. Number REGs not assigned to PCFICH */ - for (i=0;inof_regs;i++) { - // they are already sorted starting from the REG with the lowest frequency-domain index - if (h->regs[i].l < 3 && !h->regs[i].assigned) { - regs_phich[h->regs[i].l][n[h->regs[i].l]++] = &h->regs[i]; - } - } - - nreg=0; - for (mi=0;mingroups_phich;mi++) { // here ngroups is the number of mapping units - for (i=0;i<3;i++) { - li=h->phich_len==PHICH_EXT?i:0; // Step 7 - ni=((h->cell_id*n[li]/n[0])+mi+i*n[li]/3) % n[li]; // Step 8 - h->phich[mi].regs[i] = regs_phich[li][ni]; - h->phich[mi].regs[i]->assigned = true; - INFO("Assigned PHICH REG#%d (%d,%d)\n",nreg,h->phich[mi].regs[i]->k0,li); - nreg++; - } - } - - // now the number of mapping units = number of groups for normal cp. For extended cp - // ngroups = 2 * number mapping units - if (CP_ISEXT(h->cp)) { - h->ngroups_phich *= 2; - } - ret = 0; + float ng; + int i,ni,li,n[3],nreg,mi; + regs_reg_t **regs_phich[3]; + int ret = -1; + + switch(h->phich_res) { + case R_1_6: + ng = (float) 1/6; + break; + case R_1_2: + ng = (float) 1/2; + break; + case R_1: + ng = 1; + break; + case R_2: + ng = 2; + break; + default: + ng = 0; + break; + } + h->ngroups_phich = (int) ceilf(ng * ((float) h->nof_prb/8)); + h->phich = malloc(sizeof(regs_ch_t) * h->ngroups_phich); + if (!h->phich) { + perror("malloc"); + return -1; + } + INFO("Creating %d PHICH mapping units. %s length, Ng=%.2f\n",h->ngroups_phich, + h->phich_len==PHICH_EXT?"Extended":"Normal",ng); + for (i=0;ingroups_phich;i++) { + h->phich[i].nof_regs = REGS_PHICH_REGS_X_GROUP; + h->phich[i].regs = malloc(sizeof(regs_reg_t*) * REGS_PHICH_REGS_X_GROUP); + if (!h->phich[i].regs) { + perror("malloc"); + goto clean_and_exit; + } + } + + /** Here begins the mapping algorithm */ + + /* Step 2. Count REGs not assigned to PCFICH */ + bzero(n, 3*sizeof(int)); + for (i=0;inof_regs;i++) { + if (h->regs[i].l < 3 && !h->regs[i].assigned) { + n[h->regs[i].l]++; + } + } + + bzero(regs_phich, sizeof(regs_reg_t*) * 3); + for (i=0;i<3;i++) { + regs_phich[i] = malloc(n[i] * sizeof(regs_reg_t*)); + if (!regs_phich[i]) { + perror("malloc"); + goto clean_and_exit; + } + } + + bzero(n, 3 * sizeof(int)); + /* Step 3. Number REGs not assigned to PCFICH */ + for (i=0;inof_regs;i++) { + // they are already sorted starting from the REG with the lowest frequency-domain index + if (h->regs[i].l < 3 && !h->regs[i].assigned) { + regs_phich[h->regs[i].l][n[h->regs[i].l]++] = &h->regs[i]; + } + } + + nreg=0; + for (mi=0;mingroups_phich;mi++) { // here ngroups is the number of mapping units + for (i=0;i<3;i++) { + li=h->phich_len==PHICH_EXT?i:0; // Step 7 + ni=((h->cell_id*n[li]/n[0])+mi+i*n[li]/3) % n[li]; // Step 8 + h->phich[mi].regs[i] = regs_phich[li][ni]; + h->phich[mi].regs[i]->assigned = true; + INFO("Assigned PHICH REG#%d (%d,%d)\n",nreg,h->phich[mi].regs[i]->k0,li); + nreg++; + } + } + + // now the number of mapping units = number of groups for normal cp. For extended cp + // ngroups = 2 * number mapping units + if (CP_ISEXT(h->cp)) { + h->ngroups_phich *= 2; + } + ret = 0; clean_and_exit: - if (ret == -1) { - if (h->phich) { - for (i=0;ingroups_phich;i++) { - if (h->phich[i].regs) { - free(h->phich[i].regs); - } - } - free(h->phich); - } - } - for (i=0;i<3;i++) { - if (regs_phich[i]) { - free(regs_phich[i]); - } - } - return ret; + if (ret == -1) { + if (h->phich) { + for (i=0;ingroups_phich;i++) { + if (h->phich[i].regs) { + free(h->phich[i].regs); + } + } + free(h->phich); + } + } + for (i=0;i<3;i++) { + if (regs_phich[i]) { + free(regs_phich[i]); + } + } + return ret; } void regs_phich_free(regs_t *h) { - int i; - if (h->phich) { - if (CP_ISEXT(h->cp)) { - h->ngroups_phich /= 2; - } - for (i=0;ingroups_phich;i++) { - if (h->phich[i].regs) { - free(h->phich[i].regs); - } - } - free(h->phich); - } + int i; + if (h->phich) { + if (CP_ISEXT(h->cp)) { + h->ngroups_phich /= 2; + } + for (i=0;ingroups_phich;i++) { + if (h->phich[i].regs) { + free(h->phich[i].regs); + } + } + free(h->phich); + } } int regs_phich_nregs(regs_t *h) { - int i, n; - n=0; - for (i=0;ingroups_phich;i++) { - n += h->phich[i].nof_regs; - } - return n; + int i, n; + n=0; + for (i=0;ingroups_phich;i++) { + n += h->phich[i].nof_regs; + } + return n; } int regs_phich_ngroups(regs_t *h) { - return h->ngroups_phich; + return h->ngroups_phich; } /** @@ -332,19 +332,19 @@ int regs_phich_ngroups(regs_t *h) { * Returns the number of written symbols, or -1 on error */ int regs_phich_add(regs_t *h, cf_t phich_symbols[REGS_PHICH_NSYM], int ngroup, cf_t *slot_symbols) { - int i; - if (ngroup < 0 || ngroup > h->ngroups_phich) { - fprintf(stderr, "Error invalid ngroup %d\n", ngroup); - return -1; - } - if (CP_ISEXT(h->cp)) { - ngroup /= 2; - } - regs_ch_t *rch = &h->phich[ngroup]; - for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) { - regs_add_reg(rch->regs[i], &phich_symbols[i*REGS_RE_X_REG], slot_symbols, h->nof_prb); - } - return i*REGS_RE_X_REG; + int i; + if (ngroup < 0 || ngroup > h->ngroups_phich) { + fprintf(stderr, "Error invalid ngroup %d\n", ngroup); + return -1; + } + if (CP_ISEXT(h->cp)) { + ngroup /= 2; + } + regs_ch_t *rch = &h->phich[ngroup]; + for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) { + regs_add_reg(rch->regs[i], &phich_symbols[i*REGS_RE_X_REG], slot_symbols, h->nof_prb); + } + return i*REGS_RE_X_REG; } /** @@ -353,20 +353,20 @@ int regs_phich_add(regs_t *h, cf_t phich_symbols[REGS_PHICH_NSYM], int ngroup, c * Returns the number of written symbols, or -1 on error */ int regs_phich_reset(regs_t *h, cf_t *slot_symbols) { - int i; - int ngroup, ng; - for (ngroup = 0;ngroup < h->ngroups_phich;CP_ISEXT(h->cp)?ngroup+=2:ngroup++) { - if (CP_ISEXT(h->cp)) { - ng = ngroup/2; - } else { - ng = ngroup; - } - regs_ch_t *rch = &h->phich[ng]; - for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) { - regs_reset_reg(rch->regs[i], slot_symbols, h->nof_prb); - } - } - return 0; + int i; + int ngroup, ng; + for (ngroup = 0;ngroup < h->ngroups_phich;CP_ISEXT(h->cp)?ngroup+=2:ngroup++) { + if (CP_ISEXT(h->cp)) { + ng = ngroup/2; + } else { + ng = ngroup; + } + regs_ch_t *rch = &h->phich[ng]; + for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) { + regs_reset_reg(rch->regs[i], slot_symbols, h->nof_prb); + } + } + return 0; } /** @@ -375,19 +375,19 @@ int regs_phich_reset(regs_t *h, cf_t *slot_symbols) { * Returns the number of written symbols, or -1 on error */ int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_NSYM], int ngroup) { - int i; - if (ngroup < 0 || ngroup > h->ngroups_phich) { - fprintf(stderr, "Error invalid ngroup %d\n", ngroup); - return -1; - } - if (CP_ISEXT(h->cp)) { - ngroup /= 2; - } - regs_ch_t *rch = &h->phich[ngroup]; - for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) { - regs_get_reg(rch->regs[i], slot_symbols, &phich_symbols[i*REGS_RE_X_REG], h->nof_prb); - } - return i*REGS_RE_X_REG; + int i; + if (ngroup < 0 || ngroup > h->ngroups_phich) { + fprintf(stderr, "Error invalid ngroup %d\n", ngroup); + return -1; + } + if (CP_ISEXT(h->cp)) { + ngroup /= 2; + } + regs_ch_t *rch = &h->phich[ngroup]; + for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) { + regs_get_reg(rch->regs[i], slot_symbols, &phich_symbols[i*REGS_RE_X_REG], h->nof_prb); + } + return i*REGS_RE_X_REG; } @@ -410,49 +410,49 @@ int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_ * 36.211 10.3 section 6.7.4 */ int regs_pcfich_init(regs_t *h) { - int i, k_hat, k; - regs_ch_t *ch = &h->pcfich; - - ch->regs = malloc(sizeof(regs_reg_t*) * REGS_PCFICH_NREGS); - if (!ch->regs) { - perror("malloc"); - return -1; - } - ch->nof_regs = REGS_PCFICH_NREGS; - - INFO("PCFICH allocating %d regs. CellID: %d, PRB: %d\n", ch->nof_regs, h->cell_id, h->nof_prb); - - k_hat = (RE_X_RB / 2) * (h->cell_id % (2 * h->nof_prb)); - for (i = 0; i < REGS_PCFICH_NREGS; i++) { - - k = (k_hat + (i * h->nof_prb / 2) * (RE_X_RB / 2)) - % (h->nof_prb * RE_X_RB); - ch->regs[i] = regs_find_reg(h, k, 0); - if (!ch->regs[i]) { - fprintf(stderr, "Error allocating PCFICH: REG (%d,0) not found\n", - k); - return -1; - } else if (ch->regs[i]->assigned) { - fprintf(stderr, - "Error allocating PCFICH: REG (%d,0) already allocated\n", - k); - return -1; - } else { - ch->regs[i]->assigned = true; - INFO("Assigned PCFICH REG#%d (%d,0)\n", i, k); - } - } - return 0; + int i, k_hat, k; + regs_ch_t *ch = &h->pcfich; + + ch->regs = malloc(sizeof(regs_reg_t*) * REGS_PCFICH_NREGS); + if (!ch->regs) { + perror("malloc"); + return -1; + } + ch->nof_regs = REGS_PCFICH_NREGS; + + INFO("PCFICH allocating %d regs. CellID: %d, PRB: %d\n", ch->nof_regs, h->cell_id, h->nof_prb); + + k_hat = (RE_X_RB / 2) * (h->cell_id % (2 * h->nof_prb)); + for (i = 0; i < REGS_PCFICH_NREGS; i++) { + + k = (k_hat + (i * h->nof_prb / 2) * (RE_X_RB / 2)) + % (h->nof_prb * RE_X_RB); + ch->regs[i] = regs_find_reg(h, k, 0); + if (!ch->regs[i]) { + fprintf(stderr, "Error allocating PCFICH: REG (%d,0) not found\n", + k); + return -1; + } else if (ch->regs[i]->assigned) { + fprintf(stderr, + "Error allocating PCFICH: REG (%d,0) already allocated\n", + k); + return -1; + } else { + ch->regs[i]->assigned = true; + INFO("Assigned PCFICH REG#%d (%d,0)\n", i, k); + } + } + return 0; } void regs_pcfich_free(regs_t *h) { - if (h->pcfich.regs) { - free(h->pcfich.regs); - } + if (h->pcfich.regs) { + free(h->pcfich.regs); + } } int regs_pcfich_nregs(regs_t *h) { - return h->pcfich.nof_regs; + return h->pcfich.nof_regs; } /** @@ -461,13 +461,13 @@ int regs_pcfich_nregs(regs_t *h) { * Returns the number of written symbols, or -1 on error */ int regs_pcfich_put(regs_t *h, cf_t pcfich_symbols[REGS_PCFICH_NSYM], cf_t *slot_symbols) { - regs_ch_t *rch = &h->pcfich; + regs_ch_t *rch = &h->pcfich; - int i; - for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) { - regs_put_reg(rch->regs[i], &pcfich_symbols[i*REGS_RE_X_REG], slot_symbols, h->nof_prb); - } - return i*REGS_RE_X_REG; + int i; + for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) { + regs_put_reg(rch->regs[i], &pcfich_symbols[i*REGS_RE_X_REG], slot_symbols, h->nof_prb); + } + return i*REGS_RE_X_REG; } /** @@ -476,12 +476,12 @@ int regs_pcfich_put(regs_t *h, cf_t pcfich_symbols[REGS_PCFICH_NSYM], cf_t *slot * Returns the number of written symbols, or -1 on error */ int regs_pcfich_get(regs_t *h, cf_t *slot_symbols, cf_t ch_data[REGS_PCFICH_NSYM]) { - regs_ch_t *rch = &h->pcfich; - int i; - for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) { - regs_get_reg(rch->regs[i], slot_symbols, &ch_data[i*REGS_RE_X_REG], h->nof_prb); - } - return i*REGS_RE_X_REG; + regs_ch_t *rch = &h->pcfich; + int i; + for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) { + regs_get_reg(rch->regs[i], slot_symbols, &ch_data[i*REGS_RE_X_REG], h->nof_prb); + } + return i*REGS_RE_X_REG; } @@ -504,13 +504,13 @@ int regs_pcfich_get(regs_t *h, cf_t *slot_symbols, cf_t ch_data[REGS_PCFICH_NSYM ***************************************************************/ regs_reg_t *regs_find_reg(regs_t *h, int k, int l) { - int i; - for (i=0;inof_regs;i++) { - if (h->regs[i].l == l && h->regs[i].k0 == k) { - return &h->regs[i]; - } - } - return NULL; + int i; + for (i=0;inof_regs;i++) { + if (h->regs[i].l == l && h->regs[i].k0 == k) { + return &h->regs[i]; + } + } + return NULL; } /** @@ -519,31 +519,31 @@ regs_reg_t *regs_find_reg(regs_t *h, int k, int l) { */ int regs_num_x_symbol(int symbol, int nof_port, lte_cp_t cp) { - switch (symbol) { - case 0: - return 2; - case 1: - switch (nof_port) { - case 1: - case 2: - return 3; - case 4: - return 2; - default: - return -1; - } - break; - case 2: - return 3; - case 3: - if (CP_ISNORM(cp)) { - return 3; - } else { - return 2; - } - default: - return -1; - } + switch (symbol) { + case 0: + return 2; + case 1: + switch (nof_port) { + case 1: + case 2: + return 3; + case 4: + return 2; + default: + return -1; + } + break; + case 2: + return 3; + case 3: + if (CP_ISNORM(cp)) { + return 3; + } else { + return 2; + } + default: + return -1; + } } /** @@ -551,76 +551,76 @@ int regs_num_x_symbol(int symbol, int nof_port, lte_cp_t cp) { * 36.211 Section 6.2.4 */ int regs_reg_init(regs_reg_t *reg, int symbol, int nreg, int k0, int maxreg, int vo) { - int i, j, z; - - reg->l = symbol; - reg->assigned = false; - - switch (maxreg) { - case 2: - reg->k0 = k0 + nreg * 6; - /* there are two references in the middle */ - j = z = 0; - for (i = 0; i < vo; i++) { - reg->k[j] = k0 + nreg * 6 + i; - j++; - } - for (i = 0; i < 2; i++) { - reg->k[j] = k0 + nreg * 6 + i + vo + 1; - j++; - } - z = j; - for (i = 0; i < 4 - z; i++) { - reg->k[j] = k0 + nreg * 6 + vo + 3 + i + 1; - j++; - } - if (j != 4) { - fprintf(stderr, "Something went wrong: expected 2 references\n"); - return -1; - } - break; - - case 3: - reg->k0 = k0 + nreg * 4; - /* there is no reference */ - for (i = 0; i < 4; i++) { - reg->k[i] = k0 + nreg * 4 + i; - } - break; - default: - fprintf(stderr, "Invalid number of REGs per PRB: %d\n", maxreg); - return -1; - } - return 0; + int i, j, z; + + reg->l = symbol; + reg->assigned = false; + + switch (maxreg) { + case 2: + reg->k0 = k0 + nreg * 6; + /* there are two references in the middle */ + j = z = 0; + for (i = 0; i < vo; i++) { + reg->k[j] = k0 + nreg * 6 + i; + j++; + } + for (i = 0; i < 2; i++) { + reg->k[j] = k0 + nreg * 6 + i + vo + 1; + j++; + } + z = j; + for (i = 0; i < 4 - z; i++) { + reg->k[j] = k0 + nreg * 6 + vo + 3 + i + 1; + j++; + } + if (j != 4) { + fprintf(stderr, "Something went wrong: expected 2 references\n"); + return -1; + } + break; + + case 3: + reg->k0 = k0 + nreg * 4; + /* there is no reference */ + for (i = 0; i < 4; i++) { + reg->k[i] = k0 + nreg * 4 + i; + } + break; + default: + fprintf(stderr, "Invalid number of REGs per PRB: %d\n", maxreg); + return -1; + } + return 0; } void regs_free(regs_t *h) { - if (h->regs) { - free(h->regs); - } - regs_pcfich_free(h); - regs_phich_free(h); - regs_pdcch_free(h); - - bzero(h, sizeof(regs_t)); + if (h->regs) { + free(h->regs); + } + regs_pcfich_free(h); + regs_phich_free(h); + regs_pdcch_free(h); + + bzero(h, sizeof(regs_t)); } /** Sets the CFI value for this subframe (CFI must be in the range 1..3). */ int regs_set_cfi(regs_t *h, int cfi) { - if (cfi > 0 && cfi <= 3) { - if (h->phich_len == PHICH_EXT && - ((h->nof_prb < 10 && cfi < 2) || (h->nof_prb >= 10 && cfi < 3))) { - fprintf(stderr, "PHICH length is extended. The number of control symbols should be at least 3.\n"); - return -1; - } else { - h->cfi = cfi - 1; - return 0; - } - } else { - fprintf(stderr, "Invalid CFI %d\n", cfi); - return -1; - } + if (cfi > 0 && cfi <= 3) { + if (h->phich_len == PHICH_EXT && + ((h->nof_prb < 10 && cfi < 2) || (h->nof_prb >= 10 && cfi < 3))) { + fprintf(stderr, "PHICH length is extended. The number of control symbols should be at least 3.\n"); + return -1; + } else { + h->cfi = cfi - 1; + return 0; + } + } else { + fprintf(stderr, "Invalid CFI %d\n", cfi); + return -1; + } } /** @@ -629,85 +629,85 @@ int regs_set_cfi(regs_t *h, int cfi) { * Returns 0 if OK, -1 on error */ int regs_init(regs_t *h, int cell_id, int nof_prb, int nof_ports, - phich_resources_t phich_res, phich_length_t phich_len, lte_cp_t cp) { - int ret = -1; - int i, j[4], jmax, n[4], prb, k; - int vo = cell_id % 3; - int max_ctrl_symbols = nof_prb<10?4:3; - - bzero(h, sizeof(regs_t)); - - h->cell_id = cell_id; - h->nof_prb = nof_prb; - h->max_ctrl_symbols = max_ctrl_symbols; - h->cfi = -1; // not yet initialized - h->phich_res = phich_res; - h->phich_len = phich_len; - h->cp = cp; - h->nof_ports = nof_ports; - - h->nof_regs = 0; - for (i = 0; i < max_ctrl_symbols; i++) { - n[i] = regs_num_x_symbol(i, nof_ports, cp); - if (n[i] == -1) { - return -1; - } - h->nof_regs += nof_prb * n[i]; - } - INFO("Indexing %d REGs. CellId: %d, %d PRB, CP: %s\n", h->nof_regs, h->cell_id, h->nof_prb, - CP_ISNORM(cp)?"Normal":"Extended"); - h->regs = malloc(sizeof(regs_reg_t) * h->nof_regs); - if (!h->regs) { - perror("malloc"); - goto clean_and_exit; - } - - /* Sort REGs according to PDCCH mapping, beggining from the lowest l index then k */ - bzero(j, sizeof(int) * 4); - k = i = prb = jmax = 0; - while (k < h->nof_regs) { - if (n[i] == 3 || (n[i] == 2 && jmax != 1)) { - if (regs_reg_init(&h->regs[k], i, j[i], prb * RE_X_RB, n[i], vo)) { - fprintf(stderr, "Error initializing REGs\n"); - goto clean_and_exit; - } - DEBUG("Available REG #%3d: l=%d, prb=%d, nreg=%d (k0=%d)\n", k, i, prb, j[i], - h->regs[k].k0); - j[i]++; - k++; - } - i++; - if (i == max_ctrl_symbols) { - i = 0; - jmax++; - } - if (jmax == 3) { - prb++; - bzero(j, sizeof(int) * 4); - jmax = 0; - } - } - if (regs_pcfich_init(h)) { - fprintf(stderr, "Error initializing PCFICH REGs\n"); - goto clean_and_exit; - } - - if (regs_phich_init(h)) { - fprintf(stderr, "Error initializing PHICH REGs\n"); - goto clean_and_exit; - } - if (regs_pdcch_init(h)) { - fprintf(stderr, "Error initializing PDCCH REGs\n"); - goto clean_and_exit; - } - - ret = 0; + phich_resources_t phich_res, phich_length_t phich_len, lte_cp_t cp) { + int ret = -1; + int i, j[4], jmax, n[4], prb, k; + int vo = cell_id % 3; + int max_ctrl_symbols = nof_prb<10?4:3; + + bzero(h, sizeof(regs_t)); + + h->cell_id = cell_id; + h->nof_prb = nof_prb; + h->max_ctrl_symbols = max_ctrl_symbols; + h->cfi = -1; // not yet initialized + h->phich_res = phich_res; + h->phich_len = phich_len; + h->cp = cp; + h->nof_ports = nof_ports; + + h->nof_regs = 0; + for (i = 0; i < max_ctrl_symbols; i++) { + n[i] = regs_num_x_symbol(i, nof_ports, cp); + if (n[i] == -1) { + return -1; + } + h->nof_regs += nof_prb * n[i]; + } + INFO("Indexing %d REGs. CellId: %d, %d PRB, CP: %s\n", h->nof_regs, h->cell_id, h->nof_prb, + CP_ISNORM(cp)?"Normal":"Extended"); + h->regs = malloc(sizeof(regs_reg_t) * h->nof_regs); + if (!h->regs) { + perror("malloc"); + goto clean_and_exit; + } + + /* Sort REGs according to PDCCH mapping, beggining from the lowest l index then k */ + bzero(j, sizeof(int) * 4); + k = i = prb = jmax = 0; + while (k < h->nof_regs) { + if (n[i] == 3 || (n[i] == 2 && jmax != 1)) { + if (regs_reg_init(&h->regs[k], i, j[i], prb * RE_X_RB, n[i], vo)) { + fprintf(stderr, "Error initializing REGs\n"); + goto clean_and_exit; + } + DEBUG("Available REG #%3d: l=%d, prb=%d, nreg=%d (k0=%d)\n", k, i, prb, j[i], + h->regs[k].k0); + j[i]++; + k++; + } + i++; + if (i == max_ctrl_symbols) { + i = 0; + jmax++; + } + if (jmax == 3) { + prb++; + bzero(j, sizeof(int) * 4); + jmax = 0; + } + } + if (regs_pcfich_init(h)) { + fprintf(stderr, "Error initializing PCFICH REGs\n"); + goto clean_and_exit; + } + + if (regs_phich_init(h)) { + fprintf(stderr, "Error initializing PHICH REGs\n"); + goto clean_and_exit; + } + if (regs_pdcch_init(h)) { + fprintf(stderr, "Error initializing PDCCH REGs\n"); + goto clean_and_exit; + } + + ret = 0; clean_and_exit: - if (ret == -1) { - regs_free(h); - } - return ret; + if (ret == -1) { + regs_free(h); + } + return ret; } #define REG_IDX(r, i, n) r->k[i]+r->l*n*RE_X_RB @@ -716,12 +716,12 @@ clean_and_exit: * Puts one REG data (4 symbols) in the slot symbols array */ int regs_put_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_prb) { - int i; - for (i = 0; i < REGS_RE_X_REG; i++) { - DEBUG("PUT REG: i=%d, (k=%d,l=%d)\n", i, REG_IDX(reg, i, nof_prb),reg->l); - slot_symbols[REG_IDX(reg, i, nof_prb)] = reg_data[i]; - } - return REGS_RE_X_REG; + int i; + for (i = 0; i < REGS_RE_X_REG; i++) { + DEBUG("PUT REG: i=%d, (k=%d,l=%d)\n", i, REG_IDX(reg, i, nof_prb),reg->l); + slot_symbols[REG_IDX(reg, i, nof_prb)] = reg_data[i]; + } + return REGS_RE_X_REG; } /** @@ -729,14 +729,14 @@ int regs_put_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_pr * Used by PHICH */ int regs_add_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_prb) { - int i; - for (i = 0; i < REGS_RE_X_REG; i++) { - slot_symbols[REG_IDX(reg, i, nof_prb)] += reg_data[i]; - DEBUG("ADD REG: i=%d, (k=%d,l=%d): %.1f+%.1fi\n", i, REG_IDX(reg, i, nof_prb),reg->l, - __real__ slot_symbols[REG_IDX(reg, i, nof_prb)], - __imag__ slot_symbols[REG_IDX(reg, i, nof_prb)]); - } - return REGS_RE_X_REG; + int i; + for (i = 0; i < REGS_RE_X_REG; i++) { + slot_symbols[REG_IDX(reg, i, nof_prb)] += reg_data[i]; + DEBUG("ADD REG: i=%d, (k=%d,l=%d): %.1f+%.1fi\n", i, REG_IDX(reg, i, nof_prb),reg->l, + __real__ slot_symbols[REG_IDX(reg, i, nof_prb)], + __imag__ slot_symbols[REG_IDX(reg, i, nof_prb)]); + } + return REGS_RE_X_REG; } @@ -744,24 +744,24 @@ int regs_add_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_pr * Reset REG data (4 symbols) in the slot symbols array */ int regs_reset_reg(regs_reg_t *reg, cf_t *slot_symbols, int nof_prb) { - int i; - for (i = 0; i < REGS_RE_X_REG; i++) { - DEBUG("RESET REG: i=%d, (k=%d,l=%d)\n", i, REG_IDX(reg, i, nof_prb),reg->l); - slot_symbols[REG_IDX(reg, i, nof_prb)] = 0; - } - return REGS_RE_X_REG; + int i; + for (i = 0; i < REGS_RE_X_REG; i++) { + DEBUG("RESET REG: i=%d, (k=%d,l=%d)\n", i, REG_IDX(reg, i, nof_prb),reg->l); + slot_symbols[REG_IDX(reg, i, nof_prb)] = 0; + } + return REGS_RE_X_REG; } /** * Gets one REG data (4 symbols) from the slot symbols array */ int regs_get_reg(regs_reg_t *reg, cf_t *slot_symbols, cf_t *reg_data, int nof_prb) { - int i; - for (i = 0; i < REGS_RE_X_REG; i++) { - reg_data[i] = slot_symbols[REG_IDX(reg, i, nof_prb)]; - //DEBUG("GET REG: i=%d, (k=%d,l=%d): %.1f+%.1fi\n", i, REG_IDX(reg, i, nof_prb),reg->l, - // __real__ reg_data[i], __imag__ reg_data[i]); - } - return REGS_RE_X_REG; + int i; + for (i = 0; i < REGS_RE_X_REG; i++) { + reg_data[i] = slot_symbols[REG_IDX(reg, i, nof_prb)]; + //DEBUG("GET REG: i=%d, (k=%d,l=%d): %.1f+%.1fi\n", i, REG_IDX(reg, i, nof_prb),reg->l, + // __real__ reg_data[i], __imag__ reg_data[i]); + } + return REGS_RE_X_REG; } diff --git a/lte/lib/phch/src/sequences.c b/lte/lib/phch/src/sequences.c index 21a851300..b6ddb8fe4 100644 --- a/lte/lib/phch/src/sequences.c +++ b/lte/lib/phch/src/sequences.c @@ -34,16 +34,16 @@ * 36.211 6.6.1 */ int sequence_pbch(sequence_t *seq, lte_cp_t cp, int cell_id) { - bzero(seq, sizeof(sequence_t)); - return sequence_LTEPRS(seq, CP_ISNORM(cp)?1920:1728, cell_id); + bzero(seq, sizeof(sequence_t)); + return sequence_LTEPRS(seq, CP_ISNORM(cp)?1920:1728, cell_id); } /** * 36.211 6.7.1 */ int sequence_pcfich(sequence_t *seq, int nslot, int cell_id) { - bzero(seq, sizeof(sequence_t)); - return sequence_LTEPRS(seq, 32, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id); + bzero(seq, sizeof(sequence_t)); + return sequence_LTEPRS(seq, 32, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id); } @@ -51,14 +51,14 @@ int sequence_pcfich(sequence_t *seq, int nslot, int cell_id) { * 36.211 6.9.1 */ int sequence_phich(sequence_t *seq, int nslot, int cell_id) { - bzero(seq, sizeof(sequence_t)); - return sequence_LTEPRS(seq, 12, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id); + bzero(seq, sizeof(sequence_t)); + return sequence_LTEPRS(seq, 12, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id); } /** * 36.211 6.8.2 */ int sequence_pdcch(sequence_t *seq, int nslot, int cell_id, int len) { - bzero(seq, sizeof(sequence_t)); - return sequence_LTEPRS(seq, len, (nslot/2) * 512 + cell_id); + bzero(seq, sizeof(sequence_t)); + return sequence_LTEPRS(seq, len, (nslot/2) * 512 + cell_id); } diff --git a/lte/lib/phch/src/tbs_tables.h b/lte/lib/phch/src/tbs_tables.h index 3a6cad731..1563fb2e0 100644 --- a/lte/lib/phch/src/tbs_tables.h +++ b/lte/lib/phch/src/tbs_tables.h @@ -1,7 +1,7 @@ const int tbs_format1c_table[32] = { - 40, 56, 72, 120, 136, 144, 176, 208, 224, 256, 280, 296, 328, 336, 392, 488, - 552, 600, 632, 696, 776, 840, 904, 1000, 1064, 1128, 1224, 1288, 1384, 1480, 1608, 1736 + 40, 56, 72, 120, 136, 144, 176, 208, 224, 256, 280, 296, 328, 336, 392, 488, + 552, 600, 632, 696, 776, 840, 904, 1000, 1064, 1128, 1224, 1288, 1384, 1480, 1608, 1736 }; diff --git a/lte/lib/phch/test/dci_unpacking.c b/lte/lib/phch/test/dci_unpacking.c index 97b3266ee..49ca02293 100644 --- a/lte/lib/phch/test/dci_unpacking.c +++ b/lte/lib/phch/test/dci_unpacking.c @@ -34,72 +34,72 @@ #include "lte.h" void usage(char *prog) { - printf("Usage: %s nof_prb length_bits Word0 Word1 ...\n", prog); + printf("Usage: %s nof_prb length_bits Word0 Word1 ...\n", prog); } int main(int argc, char **argv) { - dci_msg_t msg; - ra_pdsch_t ra_dl; - ra_pdsch_t ra_ul; - int len, rlen; - int nof_prb; - int nwords; - int i; - char *y; + dci_msg_t msg; + ra_pdsch_t ra_dl; + ra_pdsch_t ra_ul; + int len, rlen; + int nof_prb; + int nwords; + int i; + char *y; - if (argc < 3) { - usage(argv[0]); - exit(-1); - } + if (argc < 3) { + usage(argv[0]); + exit(-1); + } - nof_prb = atoi(argv[1]); - len = atoi(argv[2]); + nof_prb = atoi(argv[1]); + len = atoi(argv[2]); - nwords = (len-1)/32+1; + nwords = (len-1)/32+1; - if (argc < 3 + nwords) { - usage(argv[0]); - exit(-1); - } + if (argc < 3 + nwords) { + usage(argv[0]); + exit(-1); + } - y = msg.data; - rlen = 0; - unsigned int x; - for (i=0;i 1) { - for (j=0;j 1) { + for (j=0;jlen); + scrambling_f_offset(s, data, 0, s->len); } void scrambling_f_offset(sequence_t *s, float *data, int offset, int len) { - int i; - assert (len + offset <= s->len); + int i; + assert (len + offset <= s->len); - for (i = 0; i < len; i++) { - data[i] = data[i]*(1-2*s->c[i+offset]); - } + for (i = 0; i < len; i++) { + data[i] = data[i]*(1-2*s->c[i+offset]); + } } void scrambling_c(sequence_t *s, cf_t *data) { - scrambling_c_offset(s, data, 0, s->len); + scrambling_c_offset(s, data, 0, s->len); } void scrambling_c_offset(sequence_t *s, cf_t *data, int offset, int len) { - int i; - assert (len + offset <= s->len); + int i; + assert (len + offset <= s->len); - for (i = 0; i < len; i++) { - data[i] = data[i]*(1-2*s->c[i+offset]); - } + for (i = 0; i < len; i++) { + data[i] = data[i]*(1-2*s->c[i+offset]); + } } void scrambling_b(sequence_t *s, char *data) { - int i; + int i; - for (i = 0; i < s->len; i++) { - data[i] = (data[i] + s->c[i]) % 2; - } + for (i = 0; i < s->len; i++) { + data[i] = (data[i] + s->c[i]) % 2; + } } void scrambling_b_offset(sequence_t *s, char *data, int offset, int len) { - int i; - assert (len + offset <= s->len); - for (i = 0; i < len; i++) { - data[i] = (data[i] + s->c[i+offset]) % 2; - } + int i; + assert (len + offset <= s->len); + for (i = 0; i < len; i++) { + data[i] = (data[i] + s->c[i+offset]) % 2; + } } /** High-level API */ int compute_sequences(scrambling_hl* h) { - switch (h->init.channel) { - case SCRAMBLING_PBCH: - return sequence_pbch(&h->obj.seq[0], h->init.nof_symbols == CPNORM_NSYMB?CPNORM:CPEXT, - h->init.cell_id); - case SCRAMBLING_PDSCH: - case SCRAMBLING_PCFICH: - for (int ns=0;nsobj.seq[ns], 2*ns, h->init.cell_id); - } - return 0; - case SCRAMBLING_PDCCH: - case SCRAMBLING_PMCH: - case SCRAMBLING_PUCCH: - fprintf(stderr, "Not implemented\n"); - return -1; - default: - fprintf(stderr, "Invalid channel %d\n", h->init.channel); - return -1; - } + switch (h->init.channel) { + case SCRAMBLING_PBCH: + return sequence_pbch(&h->obj.seq[0], h->init.nof_symbols == CPNORM_NSYMB?CPNORM:CPEXT, + h->init.cell_id); + case SCRAMBLING_PDSCH: + case SCRAMBLING_PCFICH: + for (int ns=0;nsobj.seq[ns], 2*ns, h->init.cell_id); + } + return 0; + case SCRAMBLING_PDCCH: + case SCRAMBLING_PMCH: + case SCRAMBLING_PUCCH: + fprintf(stderr, "Not implemented\n"); + return -1; + default: + fprintf(stderr, "Invalid channel %d\n", h->init.channel); + return -1; + } } int scrambling_initialize(scrambling_hl* h) { - bzero(&h->obj, sizeof(scrambling_t)); + bzero(&h->obj, sizeof(scrambling_t)); - return compute_sequences(h); + return compute_sequences(h); } /** This function can be called in a subframe (1ms) basis for LTE */ int scrambling_work(scrambling_hl* hl) { - int sf; - if (hl->init.channel == SCRAMBLING_PBCH) { - sf = 0; - } else { - sf = hl->ctrl_in.subframe; - } - sequence_t *seq = &hl->obj.seq[sf]; - - if (hl->init.hard) { - memcpy(hl->output, hl->input, sizeof(char) * hl->in_len); - scrambling_b(seq, hl->output); - } else { - memcpy(hl->output, hl->input, sizeof(float) * hl->in_len); - scrambling_f(seq, hl->output); - } - hl->out_len = hl->in_len; - return 0; + int sf; + if (hl->init.channel == SCRAMBLING_PBCH) { + sf = 0; + } else { + sf = hl->ctrl_in.subframe; + } + sequence_t *seq = &hl->obj.seq[sf]; + + if (hl->init.hard) { + memcpy(hl->output, hl->input, sizeof(char) * hl->in_len); + scrambling_b(seq, hl->output); + } else { + memcpy(hl->output, hl->input, sizeof(float) * hl->in_len); + scrambling_f(seq, hl->output); + } + hl->out_len = hl->in_len; + return 0; } int scrambling_stop(scrambling_hl* hl) { - int i; - for (i=0;iobj.seq[i]); - } - return 0; + int i; + for (i=0;iobj.seq[i]); + } + return 0; } diff --git a/lte/lib/scrambling/test/scrambling_test.c b/lte/lib/scrambling/test/scrambling_test.c index b246c4a84..f15b577ff 100644 --- a/lte/lib/scrambling/test/scrambling_test.c +++ b/lte/lib/scrambling/test/scrambling_test.c @@ -42,124 +42,124 @@ lte_cp_t cp = CPNORM; int cell_id = -1; void usage(char *prog) { - printf("Usage: %s [ef] -c cell_id -s [PBCH, PDSCH, PDCCH, PMCH, PUCCH]\n", prog); - printf("\t -e CP extended [Default CP Normal]\n"); - printf("\t -f scramble floats [Default bits]\n"); + printf("Usage: %s [ef] -c cell_id -s [PBCH, PDSCH, PDCCH, PMCH, PUCCH]\n", prog); + printf("\t -e CP extended [Default CP Normal]\n"); + printf("\t -f scramble floats [Default bits]\n"); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "csef")) != -1) { - switch (opt) { - case 'c': - cell_id = atoi(argv[optind]); - break; - case 'e': - cp = CPEXT; - break; - case 'f': - do_floats = true; - break; - case 's': - sequence_name = argv[optind]; - break; - default: - usage(argv[0]); - exit(-1); - } - } - if (cell_id == -1) { - usage(argv[0]); - exit(-1); - } - if (!sequence_name) { - usage(argv[0]); - exit(-1); - } + int opt; + while ((opt = getopt(argc, argv, "csef")) != -1) { + switch (opt) { + case 'c': + cell_id = atoi(argv[optind]); + break; + case 'e': + cp = CPEXT; + break; + case 'f': + do_floats = true; + break; + case 's': + sequence_name = argv[optind]; + break; + default: + usage(argv[0]); + exit(-1); + } + } + if (cell_id == -1) { + usage(argv[0]); + exit(-1); + } + if (!sequence_name) { + usage(argv[0]); + exit(-1); + } } int init_sequence(sequence_t *seq, char *name) { - if (!strcmp(name, "PBCH")) { - return sequence_pbch(seq, cp, cell_id); - } else { - fprintf(stderr, "Unsupported sequence name %s\n", name); - return -1; - } + if (!strcmp(name, "PBCH")) { + return sequence_pbch(seq, cp, cell_id); + } else { + fprintf(stderr, "Unsupported sequence name %s\n", name); + return -1; + } } int main(int argc, char **argv) { - int i; - sequence_t seq; - char *input_b, *scrambled_b; - float *input_f, *scrambled_f; - - parse_args(argc, argv); - - if (init_sequence(&seq, sequence_name) == -1) { - fprintf(stderr, "Error initiating sequence %s\n", sequence_name); - exit(-1); - } - - if (!do_floats) { - input_b = malloc(sizeof(char) * seq.len); - if (!input_b) { - perror("malloc"); - exit(-1); - } - scrambled_b = malloc(sizeof(char) * seq.len); - if (!scrambled_b) { - perror("malloc"); - exit(-1); - } - - for (i=0;itab, CFO_CEXPTAB_SIZE)) { - goto clean; - } - h->cur_cexp = malloc(sizeof(cf_t) * nsamples); - if (!h->cur_cexp) { - goto clean; - } - h->tol = CFO_TOLERANCE; - h->last_freq = 0; - h->nsamples = nsamples; - cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples); + if (cexptab_init(&h->tab, CFO_CEXPTAB_SIZE)) { + goto clean; + } + h->cur_cexp = malloc(sizeof(cf_t) * nsamples); + if (!h->cur_cexp) { + goto clean; + } + h->tol = CFO_TOLERANCE; + h->last_freq = 0; + h->nsamples = nsamples; + cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples); - ret = 0; + ret = 0; clean: - if (ret == -1) { - cfo_free(h); - } - return ret; + if (ret == -1) { + cfo_free(h); + } + return ret; } void cfo_free(cfo_t *h) { - cexptab_free(&h->tab); - if (h->cur_cexp) { - free(h->cur_cexp); - } - bzero(h, sizeof(cf_t)); + cexptab_free(&h->tab); + if (h->cur_cexp) { + free(h->cur_cexp); + } + bzero(h, sizeof(cf_t)); } void cfo_set_tol(cfo_t *h, float tol) { - h->tol = tol; + h->tol = tol; } void cfo_correct(cfo_t *h, cf_t *x, float freq) { - if (fabs(h->last_freq - freq) > h->tol) { - h->last_freq = freq; - cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples); - INFO("CFO generating new table for frequency %.4f\n", freq); - } - vec_prod_ccc(h->cur_cexp, x, x, h->nsamples); + if (fabs(h->last_freq - freq) > h->tol) { + h->last_freq = freq; + cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples); + INFO("CFO generating new table for frequency %.4f\n", freq); + } + vec_prod_ccc(h->cur_cexp, x, x, h->nsamples); } diff --git a/lte/lib/sync/src/find_sss.c b/lte/lib/sync/src/find_sss.c index b6e6d06e8..05f0940e1 100644 --- a/lte/lib/sync/src/find_sss.c +++ b/lte/lib/sync/src/find_sss.c @@ -32,18 +32,18 @@ #include "lte/sync/sss.h" cf_t corr_sz(cf_t *z, cf_t *s) { - cf_t sum; - cf_t zsprod[32]; - vec_prod_ccc(z, s, zsprod, N_SSS - 1); - sum = vec_acc_cc(zsprod, N_SSS - 1); + cf_t sum; + cf_t zsprod[32]; + vec_prod_ccc(z, s, zsprod, N_SSS - 1); + sum = vec_acc_cc(zsprod, N_SSS - 1); - return sum; + return sum; } void corr_all_zs(cf_t *z, cf_t s[32][32], cf_t *output) { - int m; - for (m = 0; m < N_SSS; m++) { - output[m] = corr_sz(z, s[m]); - } + int m; + for (m = 0; m < N_SSS; m++) { + output[m] = corr_sz(z, s[m]); + } } @@ -54,71 +54,71 @@ void corr_all_zs(cf_t *z, cf_t s[32][32], cf_t *output) { * * * Source: "SSS Detection Method for Initial Cell Search in 3GPP LTE FDD/TDD Dual Mode Receiver" - * Jung-In Kim, Jung-Su Han, Hee-Jin Roh and Hyung-Jin Choi + * Jung-In Kim, Jung-Su Han, Hee-Jin Roh and Hyung-Jin Choi * */ void sss_synch_m0m1(sss_synch_t *q, cf_t *input, int *m0, float *m0_value, - int *m1, float *m1_value) { - - /* This is aprox 3-4 kbytes of stack. Consider moving to sss_synch_t?? */ - cf_t zdelay[N_SSS+1],zconj[N_SSS+1],zprod[N_SSS+1]; - cf_t y[2][N_SSS+1], z[N_SSS+1], tmp[N_SSS+1]; - float tmp_real[N_SSS+1]; - cf_t input_fft[SSS_DFT_LEN]; - - int i; - - dft_run_c2c(&q->dftp_input, input, input_fft); - - for (i = 0; i < N_SSS; i++) { - y[0][i] = input_fft[SSS_POS_SYMBOL + 2 * i]; - y[1][i] = input_fft[SSS_POS_SYMBOL + 2 * i + 1]; - } - - vec_prod_ccc(y[0], q->fc_tables.c[0], z, N_SSS); - memcpy(zdelay, &z[1], (N_SSS - 1) * sizeof(cf_t)); - vec_conj_cc(z, zconj, N_SSS - 1); - vec_prod_ccc(zdelay, zconj, zprod, N_SSS - 1); - - corr_all_zs(zprod, q->fc_tables.s, tmp); - vec_abs_cf(tmp, tmp_real, N_SSS); - *m0 = vec_max_fi(tmp_real, N_SSS); - if (m0_value) { - *m0_value = tmp_real[*m0]; - } - - vec_prod_ccc(y[1], q->fc_tables.c[1], tmp, N_SSS); - vec_prod_ccc(tmp, q->fc_tables.z1[*m0], z, N_SSS); - memcpy(zdelay, &z[1], (N_SSS - 1) * sizeof(cf_t)); - vec_conj_cc(z, zconj, N_SSS - 1); - vec_prod_ccc(zdelay, zconj, zprod, N_SSS - 1); - - corr_all_zs(zprod, q->fc_tables.s, tmp); - vec_abs_cf(tmp, tmp_real, N_SSS); - *m1 = vec_max_fi(tmp_real, N_SSS); - if (m1_value) { - *m1_value = tmp_real[*m1]; - } + int *m1, float *m1_value) { + + /* This is aprox 3-4 kbytes of stack. Consider moving to sss_synch_t?? */ + cf_t zdelay[N_SSS+1],zconj[N_SSS+1],zprod[N_SSS+1]; + cf_t y[2][N_SSS+1], z[N_SSS+1], tmp[N_SSS+1]; + float tmp_real[N_SSS+1]; + cf_t input_fft[SSS_DFT_LEN]; + + int i; + + dft_run_c2c(&q->dftp_input, input, input_fft); + + for (i = 0; i < N_SSS; i++) { + y[0][i] = input_fft[SSS_POS_SYMBOL + 2 * i]; + y[1][i] = input_fft[SSS_POS_SYMBOL + 2 * i + 1]; + } + + vec_prod_ccc(y[0], q->fc_tables.c[0], z, N_SSS); + memcpy(zdelay, &z[1], (N_SSS - 1) * sizeof(cf_t)); + vec_conj_cc(z, zconj, N_SSS - 1); + vec_prod_ccc(zdelay, zconj, zprod, N_SSS - 1); + + corr_all_zs(zprod, q->fc_tables.s, tmp); + vec_abs_cf(tmp, tmp_real, N_SSS); + *m0 = vec_max_fi(tmp_real, N_SSS); + if (m0_value) { + *m0_value = tmp_real[*m0]; + } + + vec_prod_ccc(y[1], q->fc_tables.c[1], tmp, N_SSS); + vec_prod_ccc(tmp, q->fc_tables.z1[*m0], z, N_SSS); + memcpy(zdelay, &z[1], (N_SSS - 1) * sizeof(cf_t)); + vec_conj_cc(z, zconj, N_SSS - 1); + vec_prod_ccc(zdelay, zconj, zprod, N_SSS - 1); + + corr_all_zs(zprod, q->fc_tables.s, tmp); + vec_abs_cf(tmp, tmp_real, N_SSS); + *m1 = vec_max_fi(tmp_real, N_SSS); + if (m1_value) { + *m1_value = tmp_real[*m1]; + } } void convert_tables(struct fc_tables *fc_tables, struct sss_tables *in) { - int i, j; - bzero(fc_tables, sizeof(struct fc_tables)); - for (i = 0; i < N_SSS; i++) { - for (j = 0; j < N_SSS; j++) { - __real__ fc_tables->z1[i][j] = (float) in->z1[i][j]; - } - } - for (i = 0; i < N_SSS; i++) { - for (j = 0; j < N_SSS - 1; j++) { - __real__ fc_tables->s[i][j] = (float) in->s[i][j + 1] * in->s[i][j]; - } - } - for (i = 0; i < 2; i++) { - for (j = 0; j < N_SSS; j++) { - __real__ fc_tables->c[i][j] = (float) in->c[i][j]; - } - } + int i, j; + bzero(fc_tables, sizeof(struct fc_tables)); + for (i = 0; i < N_SSS; i++) { + for (j = 0; j < N_SSS; j++) { + __real__ fc_tables->z1[i][j] = (float) in->z1[i][j]; + } + } + for (i = 0; i < N_SSS; i++) { + for (j = 0; j < N_SSS - 1; j++) { + __real__ fc_tables->s[i][j] = (float) in->s[i][j + 1] * in->s[i][j]; + } + } + for (i = 0; i < 2; i++) { + for (j = 0; j < N_SSS; j++) { + __real__ fc_tables->c[i][j] = (float) in->c[i][j]; + } + } } diff --git a/lte/lib/sync/src/gen_sss.c b/lte/lib/sync/src/gen_sss.c index de75c189b..a54940ea2 100644 --- a/lte/lib/sync/src/gen_sss.c +++ b/lte/lib/sync/src/gen_sss.c @@ -37,128 +37,128 @@ */ void generate_zsc_tilde(int *z_tilde, int *s_tilde, int *c_tilde) { - int i; - int x[N_SSS]; - bzero(x, sizeof(int) * N_SSS); - x[4] = 1; - - for (i = 0; i < 26; i++) - x[i + 5] = (x[i + 2] + x[i]) % 2; - for (i = 0; i < N_SSS; i++) - s_tilde[i] = 1 - 2 * x[i]; - - for (i = 0; i < 26; i++) - x[i + 5] = (x[i + 3] + x[i]) % 2; - for (i = 0; i < N_SSS; i++) - c_tilde[i] = 1 - 2 * x[i]; - - for (i = 0; i < 26; i++) - x[i + 5] = (x[i + 4] + x[i + 2] + x[i + 1] + x[i]) % 2; - for (i = 0; i < N_SSS; i++) - z_tilde[i] = 1 - 2 * x[i]; + int i; + int x[N_SSS]; + bzero(x, sizeof(int) * N_SSS); + x[4] = 1; + + for (i = 0; i < 26; i++) + x[i + 5] = (x[i + 2] + x[i]) % 2; + for (i = 0; i < N_SSS; i++) + s_tilde[i] = 1 - 2 * x[i]; + + for (i = 0; i < 26; i++) + x[i + 5] = (x[i + 3] + x[i]) % 2; + for (i = 0; i < N_SSS; i++) + c_tilde[i] = 1 - 2 * x[i]; + + for (i = 0; i < 26; i++) + x[i + 5] = (x[i + 4] + x[i + 2] + x[i + 1] + x[i]) % 2; + for (i = 0; i < N_SSS; i++) + z_tilde[i] = 1 - 2 * x[i]; } void generate_m0m1(int N_id_1, int *m0, int *m1) { - int q_prime = N_id_1 / (N_SSS - 1); - int q = (N_id_1 + (q_prime * (q_prime + 1) / 2)) / (N_SSS - 1); - int m_prime = N_id_1 + (q * (q + 1) / 2); - *m0 = m_prime % N_SSS; - *m1 = (*m0 + m_prime / N_SSS + 1) % N_SSS; + int q_prime = N_id_1 / (N_SSS - 1); + int q = (N_id_1 + (q_prime * (q_prime + 1) / 2)) / (N_SSS - 1); + int m_prime = N_id_1 + (q * (q + 1) / 2); + *m0 = m_prime % N_SSS; + *m1 = (*m0 + m_prime / N_SSS + 1) % N_SSS; } /* table[m0][m1-1]=N_id_1 */ void generate_N_id_1_table(int table[30][30]) { - int m0, m1; - int N_id_1; - for (N_id_1=0;N_id_1<168;N_id_1++) { - generate_m0m1(N_id_1, &m0, &m1); - table[m0][m1-1] = N_id_1; - } + int m0, m1; + int N_id_1; + for (N_id_1=0;N_id_1<168;N_id_1++) { + generate_m0m1(N_id_1, &m0, &m1); + table[m0][m1-1] = N_id_1; + } } void generate_s(int *s, int *s_tilde, int m0_m1) { - int i; - for (i = 0; i < N_SSS; i++) { - s[i] = s_tilde[(i + m0_m1) % N_SSS]; - } + int i; + for (i = 0; i < N_SSS; i++) { + s[i] = s_tilde[(i + m0_m1) % N_SSS]; + } } void generate_s_all(int s[N_SSS][N_SSS], int *s_tilde) { - int i; - for (i = 0; i < N_SSS; i++) { - generate_s(s[i], s_tilde, i); - } + int i; + for (i = 0; i < N_SSS; i++) { + generate_s(s[i], s_tilde, i); + } } void generate_c(int *c, int *c_tilde, int N_id_2, int is_c0) { - int i; - for (i = 0; i < N_SSS; i++) { - c[i] = c_tilde[(i + N_id_2 + (is_c0 > 0 ? 3 : 0)) % N_SSS]; - } + int i; + for (i = 0; i < N_SSS; i++) { + c[i] = c_tilde[(i + N_id_2 + (is_c0 > 0 ? 3 : 0)) % N_SSS]; + } } void generate_z(int *z, int *z_tilde, int m0_m1) { - int i; - for (i = 0; i < N_SSS; i++) { - z[i] = z_tilde[(i + (m0_m1 % 8)) % N_SSS]; - } + int i; + for (i = 0; i < N_SSS; i++) { + z[i] = z_tilde[(i + (m0_m1 % 8)) % N_SSS]; + } } void generate_z_all(int z[N_SSS][N_SSS], int *z_tilde) { - int i; - for (i = 0; i < N_SSS; i++) { - generate_z(z[i], z_tilde, i); - } + int i; + for (i = 0; i < N_SSS; i++) { + generate_z(z[i], z_tilde, i); + } } void generate_sss_all_tables(struct sss_tables *tables, int N_id_2) { - int i; - int s_t[N_SSS], c_t[N_SSS], z_t[N_SSS]; - - generate_zsc_tilde(z_t, s_t, c_t); - generate_s_all(tables->s, s_t); - generate_z_all(tables->z1, z_t); - for (i = 0; i < 2; i++) { - generate_c(tables->c[i], c_t, N_id_2, i); - } - tables->N_id_2 = N_id_2; + int i; + int s_t[N_SSS], c_t[N_SSS], z_t[N_SSS]; + + generate_zsc_tilde(z_t, s_t, c_t); + generate_s_all(tables->s, s_t); + generate_z_all(tables->z1, z_t); + for (i = 0; i < 2; i++) { + generate_c(tables->c[i], c_t, N_id_2, i); + } + tables->N_id_2 = N_id_2; } void sss_generate(float *signal0, float *signal5, int cell_id) { - int i; - int id1 = cell_id / 3; - int id2 = cell_id % 3; - int m0; - int m1; - int s_t[N_SSS], c_t[N_SSS], z_t[N_SSS]; - int s0[N_SSS], s1[N_SSS], c0[N_SSS], c1[N_SSS], z1_0[N_SSS], z1_1[N_SSS]; - - generate_m0m1(id1, &m0, &m1); - generate_zsc_tilde(z_t, s_t, c_t); - - generate_s(s0, s_t, m0); - generate_s(s1, s_t, m1); - - generate_c(c0, c_t, id2, 0); - generate_c(c1, c_t, id2, 1); - - generate_z(z1_0, z_t, m0); - generate_z(z1_1, z_t, m1); - - for (i = 0; i < N_SSS; i++) { - /** Even Resource Elements: Sub-frame 0*/ - signal0[2 * i] = (float) (s0[i] * c0[i]); - /** Odd Resource Elements: Sub-frame 0*/ - signal0[2 * i + 1] = (float) (s1[i] * c1[i] * z1_0[i]); - } - for (i = 0; i < N_SSS; i++) { - /** Even Resource Elements: Sub-frame 5*/ - signal5[2 * i] = (float) (s1[i] * c0[i]); - /** Odd Resource Elements: Sub-frame 5*/ - signal5[2 * i + 1] = (float) (s0[i] * c1[i] * z1_1[i]); - } + int i; + int id1 = cell_id / 3; + int id2 = cell_id % 3; + int m0; + int m1; + int s_t[N_SSS], c_t[N_SSS], z_t[N_SSS]; + int s0[N_SSS], s1[N_SSS], c0[N_SSS], c1[N_SSS], z1_0[N_SSS], z1_1[N_SSS]; + + generate_m0m1(id1, &m0, &m1); + generate_zsc_tilde(z_t, s_t, c_t); + + generate_s(s0, s_t, m0); + generate_s(s1, s_t, m1); + + generate_c(c0, c_t, id2, 0); + generate_c(c1, c_t, id2, 1); + + generate_z(z1_0, z_t, m0); + generate_z(z1_1, z_t, m1); + + for (i = 0; i < N_SSS; i++) { + /** Even Resource Elements: Sub-frame 0*/ + signal0[2 * i] = (float) (s0[i] * c0[i]); + /** Odd Resource Elements: Sub-frame 0*/ + signal0[2 * i + 1] = (float) (s1[i] * c1[i] * z1_0[i]); + } + for (i = 0; i < N_SSS; i++) { + /** Even Resource Elements: Sub-frame 5*/ + signal5[2 * i] = (float) (s1[i] * c0[i]); + /** Odd Resource Elements: Sub-frame 5*/ + signal5[2 * i + 1] = (float) (s0[i] * c1[i] * z1_1[i]); + } } diff --git a/lte/lib/sync/src/pss.c b/lte/lib/sync/src/pss.c index f32ba1f86..596be1fbe 100644 --- a/lte/lib/sync/src/pss.c +++ b/lte/lib/sync/src/pss.c @@ -37,85 +37,85 @@ #include "lte/utils/vector.h" #include "lte/utils/convolution.h" -#define NOT_SYNC 0xF0F0F0F0 +#define NOT_SYNC 0xF0F0F0F0 /* Initializes the object. subframe_size is the size, in samples, of the 1ms subframe * */ int pss_synch_init(pss_synch_t *q, int frame_size) { - int ret = -1; - bzero(q, sizeof(pss_synch_t)); - - q->pss_signal_freq = vec_malloc((PSS_LEN_FREQ + frame_size) * sizeof(cf_t)); - if (!q->pss_signal_freq) { - fprintf(stderr, "Error allocating memory\n"); - goto clean_and_exit; - } - q->conv_abs = vec_malloc((PSS_LEN_FREQ + frame_size) * sizeof(float)); - if (!q->conv_abs) { - fprintf(stderr, "Error allocating memory\n"); - goto clean_and_exit; - } - q->tmp_input = vec_malloc((PSS_LEN_FREQ + frame_size) * sizeof(cf_t)); - if (!q->tmp_input) { - fprintf(stderr, "Error allocating memory\n"); - goto clean_and_exit; - } - q->frame_buffer = vec_malloc(4 * frame_size * sizeof(cf_t)); - if (!q->frame_buffer) { - fprintf(stderr, "Error allocating memory\n"); - goto clean_and_exit; - } - q->conv_output = vec_malloc((PSS_LEN_FREQ + frame_size) * sizeof(cf_t)); - if (!q->conv_output) { - fprintf(stderr, "Error allocating memory\n"); - goto clean_and_exit; - } + int ret = -1; + bzero(q, sizeof(pss_synch_t)); + + q->pss_signal_freq = vec_malloc((PSS_LEN_FREQ + frame_size) * sizeof(cf_t)); + if (!q->pss_signal_freq) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + q->conv_abs = vec_malloc((PSS_LEN_FREQ + frame_size) * sizeof(float)); + if (!q->conv_abs) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + q->tmp_input = vec_malloc((PSS_LEN_FREQ + frame_size) * sizeof(cf_t)); + if (!q->tmp_input) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + q->frame_buffer = vec_malloc(4 * frame_size * sizeof(cf_t)); + if (!q->frame_buffer) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + q->conv_output = vec_malloc((PSS_LEN_FREQ + frame_size) * sizeof(cf_t)); + if (!q->conv_output) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } #ifdef CONVOLUTION_FFT - if (conv_fft_cc_init(&q->conv_fft, frame_size, PSS_LEN_FREQ)) { - fprintf(stderr, "Error initiating convolution FFT\n"); - goto clean_and_exit; - } + if (conv_fft_cc_init(&q->conv_fft, frame_size, PSS_LEN_FREQ)) { + fprintf(stderr, "Error initiating convolution FFT\n"); + goto clean_and_exit; + } #endif - q->correlation_threshold = DEFAULT_CORRELATION_TH; - q->nosync_timeout_frames = DEFAULT_NOSYNC_TIMEOUT; - q->cfo_auto = true; - q->N_id_2 = -1; - q->frame_size = frame_size; - q->frame_start_idx = NOT_SYNC; - q->fb_wp = 0; - - ret = 0; - clean_and_exit: if (ret == -1) { - pss_synch_free(q); - } - return ret; + q->correlation_threshold = DEFAULT_CORRELATION_TH; + q->nosync_timeout_frames = DEFAULT_NOSYNC_TIMEOUT; + q->cfo_auto = true; + q->N_id_2 = -1; + q->frame_size = frame_size; + q->frame_start_idx = NOT_SYNC; + q->fb_wp = 0; + + ret = 0; + clean_and_exit: if (ret == -1) { + pss_synch_free(q); + } + return ret; } void pss_synch_free(pss_synch_t *q) { - if (q->pss_signal_freq) { - free(q->pss_signal_freq); - } - if (q->conv_abs) { - free(q->conv_abs); - } - if (q->tmp_input) { - free(q->tmp_input); - } - if (q->frame_buffer) { - free(q->frame_buffer); - } - if (q->conv_output) { - free(q->conv_output); - } + if (q->pss_signal_freq) { + free(q->pss_signal_freq); + } + if (q->conv_abs) { + free(q->conv_abs); + } + if (q->tmp_input) { + free(q->tmp_input); + } + if (q->frame_buffer) { + free(q->frame_buffer); + } + if (q->conv_output) { + free(q->conv_output); + } #ifdef CONVOLUTION_FFT - conv_fft_cc_free(&q->conv_fft); + conv_fft_cc_free(&q->conv_fft); #endif - bzero(q, sizeof(pss_synch_t)); + bzero(q, sizeof(pss_synch_t)); } /** @@ -123,83 +123,83 @@ void pss_synch_free(pss_synch_t *q) { * @param signal Output array. */ int pss_generate(cf_t *signal, int N_id_2) { - int i; - float arg; - const float root_value[] = { 25.0, 29.0, 34.0 }; - int root_idx; - - int sign = -1; - - if (N_id_2 < 0 || N_id_2 > 2) { - fprintf(stderr, "Invalid N_id_2 %d\n", N_id_2); - return -1; - } - - root_idx = N_id_2; - - for (i = 0; i < PSS_LEN / 2; i++) { - arg = (float) sign * M_PI * root_value[root_idx] - * ((float) i * ((float) i + 1.0)) / 63.0; - __real__ signal[i] = cosf(arg); - __imag__ signal[i] = sinf(arg); - } - for (i = PSS_LEN / 2; i < PSS_LEN; i++) { - arg = (float) sign * M_PI * root_value[root_idx] - * (((float) i + 2.0) * ((float) i + 1.0)) / 63.0; - __real__ signal[i] = cosf(arg); - __imag__ signal[i] = sinf(arg); - } - return 0; + int i; + float arg; + const float root_value[] = { 25.0, 29.0, 34.0 }; + int root_idx; + + int sign = -1; + + if (N_id_2 < 0 || N_id_2 > 2) { + fprintf(stderr, "Invalid N_id_2 %d\n", N_id_2); + return -1; + } + + root_idx = N_id_2; + + for (i = 0; i < PSS_LEN / 2; i++) { + arg = (float) sign * M_PI * root_value[root_idx] + * ((float) i * ((float) i + 1.0)) / 63.0; + __real__ signal[i] = cosf(arg); + __imag__ signal[i] = sinf(arg); + } + for (i = PSS_LEN / 2; i < PSS_LEN; i++) { + arg = (float) sign * M_PI * root_value[root_idx] + * (((float) i + 2.0) * ((float) i + 1.0)) / 63.0; + __real__ signal[i] = cosf(arg); + __imag__ signal[i] = sinf(arg); + } + return 0; } /** 36.211 10.3 section 6.11.1.2 */ void pss_put_slot(cf_t *pss_signal, cf_t *slot, int nof_prb, lte_cp_t cp) { - int k; - k = (CP_NSYMB(cp) - 1) * nof_prb * RE_X_RB + nof_prb * RE_X_RB / 2 - 31; - memset(&slot[k - 5], 0, 5 * sizeof(cf_t)); - memcpy(&slot[k], pss_signal, PSS_LEN * sizeof(cf_t)); - memset(&slot[k + PSS_LEN], 0, 5 * sizeof(cf_t)); + int k; + k = (CP_NSYMB(cp) - 1) * nof_prb * RE_X_RB + nof_prb * RE_X_RB / 2 - 31; + memset(&slot[k - 5], 0, 5 * sizeof(cf_t)); + memcpy(&slot[k], pss_signal, PSS_LEN * sizeof(cf_t)); + memset(&slot[k + PSS_LEN], 0, 5 * sizeof(cf_t)); } /** Sets the current N_id_2 value. Initializes the object for this PSS sequence * Returns -1 on error, 0 otherwise */ int pss_synch_set_N_id_2(pss_synch_t *q, int N_id_2) { - q->N_id_2 = N_id_2; + q->N_id_2 = N_id_2; - dft_plan_t plan; - cf_t pss_signal_pad[PSS_LEN_FREQ]; - cf_t pss_signal_time[PSS_LEN]; + dft_plan_t plan; + cf_t pss_signal_pad[PSS_LEN_FREQ]; + cf_t pss_signal_time[PSS_LEN]; - if (N_id_2 < 0 || N_id_2 > 2) { - fprintf(stderr, "Invalid N_id_2 %d\n", N_id_2); - return -1; - } + if (N_id_2 < 0 || N_id_2 > 2) { + fprintf(stderr, "Invalid N_id_2 %d\n", N_id_2); + return -1; + } - pss_generate(pss_signal_time, N_id_2); + pss_generate(pss_signal_time, N_id_2); - memset(pss_signal_pad, 0, PSS_LEN_FREQ * sizeof(cf_t)); - memset(q->pss_signal_freq, 0, PSS_LEN_FREQ * sizeof(cf_t)); - memcpy(&pss_signal_pad[33], pss_signal_time, PSS_LEN * sizeof(cf_t)); + memset(pss_signal_pad, 0, PSS_LEN_FREQ * sizeof(cf_t)); + memset(q->pss_signal_freq, 0, PSS_LEN_FREQ * sizeof(cf_t)); + memcpy(&pss_signal_pad[33], pss_signal_time, PSS_LEN * sizeof(cf_t)); if (dft_plan(&plan, PSS_LEN_FREQ - 1, COMPLEX_2_COMPLEX, BACKWARD)) { - return -1; - } - plan.options = DFT_MIRROR_PRE | DFT_DC_OFFSET; + return -1; + } + plan.options = DFT_MIRROR_PRE | DFT_DC_OFFSET; - dft_run_c2c(&plan, pss_signal_pad, q->pss_signal_freq); + dft_run_c2c(&plan, pss_signal_pad, q->pss_signal_freq); - vec_sc_prod_cfc(q->pss_signal_freq, (float) 1 / (PSS_LEN_FREQ - 1), - pss_signal_pad, PSS_LEN_FREQ); + vec_sc_prod_cfc(q->pss_signal_freq, (float) 1 / (PSS_LEN_FREQ - 1), + pss_signal_pad, PSS_LEN_FREQ); - vec_conj_cc(pss_signal_pad, q->pss_signal_freq, PSS_LEN_FREQ); + vec_conj_cc(pss_signal_pad, q->pss_signal_freq, PSS_LEN_FREQ); - q->N_id_2 = N_id_2; + q->N_id_2 = N_id_2; - dft_plan_free(&plan); + dft_plan_free(&plan); - return 0; + return 0; } /** Returns the index of the PSS correlation peak in a subframe. @@ -209,50 +209,50 @@ int pss_synch_set_N_id_2(pss_synch_t *q, int N_id_2) { * Input buffer must be subframe_size long. */ int pss_synch_find_pss(pss_synch_t *q, cf_t *input, float *corr_peak_value, - float *corr_mean_value) { - int corr_peak_pos; - int conv_output_len; + float *corr_mean_value) { + int corr_peak_pos; + int conv_output_len; - memset(&q->pss_signal_freq[PSS_LEN_FREQ], 0, q->frame_size * sizeof(cf_t)); - memcpy(q->tmp_input, input, q->frame_size * sizeof(cf_t)); - memset(&q->tmp_input[q->frame_size], 0, PSS_LEN_FREQ * sizeof(cf_t)); + memset(&q->pss_signal_freq[PSS_LEN_FREQ], 0, q->frame_size * sizeof(cf_t)); + memcpy(q->tmp_input, input, q->frame_size * sizeof(cf_t)); + memset(&q->tmp_input[q->frame_size], 0, PSS_LEN_FREQ * sizeof(cf_t)); #ifdef CONVOLUTION_FFT - conv_output_len = conv_fft_cc_run(&q->conv_fft, q->tmp_input, - q->pss_signal_freq, q->conv_output); + conv_output_len = conv_fft_cc_run(&q->conv_fft, q->tmp_input, + q->pss_signal_freq, q->conv_output); #else - conv_output_len = conv_cc(input, q->pss_signal_freq, q->conv_output, q->frame_size, PSS_LEN_FREQ); + conv_output_len = conv_cc(input, q->pss_signal_freq, q->conv_output, q->frame_size, PSS_LEN_FREQ); #endif - vec_abs_cf(q->conv_output, q->conv_abs, conv_output_len); - corr_peak_pos = vec_max_fi(q->conv_abs, conv_output_len); - if (corr_peak_value) { - *corr_peak_value = q->conv_abs[corr_peak_pos]; - } - if (corr_mean_value) { - *corr_mean_value = vec_acc_ff(q->conv_abs, conv_output_len) - / conv_output_len; - } - - return (int) corr_peak_pos; + vec_abs_cf(q->conv_output, q->conv_abs, conv_output_len); + corr_peak_pos = vec_max_fi(q->conv_abs, conv_output_len); + if (corr_peak_value) { + *corr_peak_value = q->conv_abs[corr_peak_pos]; + } + if (corr_mean_value) { + *corr_mean_value = vec_acc_ff(q->conv_abs, conv_output_len) + / conv_output_len; + } + + return (int) corr_peak_pos; } /* Returns the CFO estimation given a PSS received sequence * * Source: An Efficient CFO Estimation Algorithm for the Downlink of 3GPP-LTE - * Feng Wang and Yu Zhu + * Feng Wang and Yu Zhu */ float pss_synch_cfo_compute(pss_synch_t* q, cf_t *pss_recv) { - cf_t y0, y1, yr; - cf_t y[PSS_LEN_FREQ - 1]; + cf_t y0, y1, yr; + cf_t y[PSS_LEN_FREQ - 1]; - vec_prod_ccc_unalign(q->pss_signal_freq, pss_recv, y, PSS_LEN_FREQ - 1); + vec_prod_ccc_unalign(q->pss_signal_freq, pss_recv, y, PSS_LEN_FREQ - 1); - y0 = vec_acc_cc(y, (PSS_LEN_FREQ - 1) / 2); - y1 = vec_acc_cc(&y[(PSS_LEN_FREQ - 1) / 2], (PSS_LEN_FREQ - 1) / 2); - yr = conjf(y0) * y1; + y0 = vec_acc_cc(y, (PSS_LEN_FREQ - 1) / 2); + y1 = vec_acc_cc(&y[(PSS_LEN_FREQ - 1) / 2], (PSS_LEN_FREQ - 1) / 2); + yr = conjf(y0) * y1; - return atan2f(__imag__ yr, __real__ yr) / M_PI; + return atan2f(__imag__ yr, __real__ yr) / M_PI; } /** This function is designed to be called periodically on a subframe basis. @@ -265,134 +265,134 @@ float pss_synch_cfo_compute(pss_synch_t* q, cf_t *pss_recv) { * If synchronized, subsequent calls to this function align the input buffer to the subframe beginning. */ int pss_synch_frame(pss_synch_t *q, cf_t *input, cf_t *output, int nsamples) { - int max_idx, tmp_start_idx; - int retval; - float max_value; - - if (nsamples != q->frame_size) { - fprintf(stderr, "Configured for frame size %d but got %d samples\n", - q->frame_size, nsamples); - return -1; - } - - if (q->N_id_2 < 0) { - fprintf(stderr, - "N_id_2 must be configured before calling pss_synch()\n"); - return -1; - } - - max_idx = pss_synch_find_pss(q, input, &max_value, NULL); - if (max_value > q->correlation_threshold) { - tmp_start_idx = max_idx - nsamples / 2; - if (q->frame_start_idx != tmp_start_idx) { - printf("Re-synchronizing: new index is %d, old was %d\n", - tmp_start_idx, q->frame_start_idx); - } - q->frame_start_idx = tmp_start_idx; - } else { - if (q->nosync_timeout_frames > 0) { - q->nof_nosync_frames++; - if (q->nof_nosync_frames >= q->nosync_timeout_frames) { - q->frame_start_idx = NOT_SYNC; - } - } - } - - if (q->frame_start_idx == NOT_SYNC) { - - memcpy(q->frame_buffer, input, nsamples * sizeof(cf_t)); - retval = 0; - - } else if (q->frame_start_idx > 0) { - - if (q->fb_wp) { - memcpy(&q->frame_buffer[(nsamples - q->frame_start_idx)], input, - q->frame_start_idx * sizeof(cf_t)); - memcpy(output, q->frame_buffer, nsamples * sizeof(cf_t)); - retval = nsamples; - } else { - retval = 0; - } - memcpy(q->frame_buffer, &input[q->frame_start_idx], - (nsamples - q->frame_start_idx) * sizeof(cf_t)); - q->fb_wp = 1; - - } else { - - memcpy(output, &q->frame_buffer[nsamples + q->frame_start_idx], - (-q->frame_start_idx) * sizeof(cf_t)); - memcpy(&output[-q->frame_start_idx], input, - (nsamples + q->frame_start_idx) * sizeof(cf_t)); - memcpy(&q->frame_buffer[nsamples + q->frame_start_idx], - &input[nsamples + q->frame_start_idx], - (-q->frame_start_idx) * sizeof(cf_t)); - retval = nsamples; - } - - if (q->frame_start_idx != NOT_SYNC && q->cfo_auto && retval) { - q->current_cfo = pss_synch_cfo_compute(q, - &output[q->frame_size / 2 - PSS_LEN_FREQ + 1]); - } - - return retval; + int max_idx, tmp_start_idx; + int retval; + float max_value; + + if (nsamples != q->frame_size) { + fprintf(stderr, "Configured for frame size %d but got %d samples\n", + q->frame_size, nsamples); + return -1; + } + + if (q->N_id_2 < 0) { + fprintf(stderr, + "N_id_2 must be configured before calling pss_synch()\n"); + return -1; + } + + max_idx = pss_synch_find_pss(q, input, &max_value, NULL); + if (max_value > q->correlation_threshold) { + tmp_start_idx = max_idx - nsamples / 2; + if (q->frame_start_idx != tmp_start_idx) { + printf("Re-synchronizing: new index is %d, old was %d\n", + tmp_start_idx, q->frame_start_idx); + } + q->frame_start_idx = tmp_start_idx; + } else { + if (q->nosync_timeout_frames > 0) { + q->nof_nosync_frames++; + if (q->nof_nosync_frames >= q->nosync_timeout_frames) { + q->frame_start_idx = NOT_SYNC; + } + } + } + + if (q->frame_start_idx == NOT_SYNC) { + + memcpy(q->frame_buffer, input, nsamples * sizeof(cf_t)); + retval = 0; + + } else if (q->frame_start_idx > 0) { + + if (q->fb_wp) { + memcpy(&q->frame_buffer[(nsamples - q->frame_start_idx)], input, + q->frame_start_idx * sizeof(cf_t)); + memcpy(output, q->frame_buffer, nsamples * sizeof(cf_t)); + retval = nsamples; + } else { + retval = 0; + } + memcpy(q->frame_buffer, &input[q->frame_start_idx], + (nsamples - q->frame_start_idx) * sizeof(cf_t)); + q->fb_wp = 1; + + } else { + + memcpy(output, &q->frame_buffer[nsamples + q->frame_start_idx], + (-q->frame_start_idx) * sizeof(cf_t)); + memcpy(&output[-q->frame_start_idx], input, + (nsamples + q->frame_start_idx) * sizeof(cf_t)); + memcpy(&q->frame_buffer[nsamples + q->frame_start_idx], + &input[nsamples + q->frame_start_idx], + (-q->frame_start_idx) * sizeof(cf_t)); + retval = nsamples; + } + + if (q->frame_start_idx != NOT_SYNC && q->cfo_auto && retval) { + q->current_cfo = pss_synch_cfo_compute(q, + &output[q->frame_size / 2 - PSS_LEN_FREQ + 1]); + } + + return retval; } void pss_synch_set_timeout(pss_synch_t *q, int nof_frames) { - q->nosync_timeout_frames = nof_frames; + q->nosync_timeout_frames = nof_frames; } void pss_synch_set_threshold(pss_synch_t *q, float threshold) { - q->correlation_threshold = threshold; + q->correlation_threshold = threshold; } void pss_synch_set_cfo_mode(pss_synch_t *q, bool cfo_auto) { - q->cfo_auto = cfo_auto; + q->cfo_auto = cfo_auto; } float pss_synch_get_cfo(pss_synch_t *q) { - return q->current_cfo; + return q->current_cfo; } int pss_synch_get_frame_start_idx(pss_synch_t *q) { - return q->frame_start_idx; + return q->frame_start_idx; } /** High-level API */ int pss_synch_initialize(pss_synch_hl* h) { - int fs = h->init.frame_size; - if (!fs) { - fs = DEFAULT_FRAME_SIZE; - } - if (pss_synch_init(&h->obj, fs)) { - return -1; - } - if (h->init.unsync_nof_pkts) { - pss_synch_set_timeout(&h->obj, h->init.unsync_nof_pkts); - } - - pss_synch_set_N_id_2(&h->obj, h->init.N_id_2); - if (h->init.do_cfo) { - pss_synch_set_cfo_mode(&h->obj, true); - } else { - pss_synch_set_cfo_mode(&h->obj, false); - } - return 0; + int fs = h->init.frame_size; + if (!fs) { + fs = DEFAULT_FRAME_SIZE; + } + if (pss_synch_init(&h->obj, fs)) { + return -1; + } + if (h->init.unsync_nof_pkts) { + pss_synch_set_timeout(&h->obj, h->init.unsync_nof_pkts); + } + + pss_synch_set_N_id_2(&h->obj, h->init.N_id_2); + if (h->init.do_cfo) { + pss_synch_set_cfo_mode(&h->obj, true); + } else { + pss_synch_set_cfo_mode(&h->obj, false); + } + return 0; } int pss_synch_work(pss_synch_hl* hl) { - if (hl->ctrl_in.correlation_threshold) { - pss_synch_set_threshold(&hl->obj, hl->ctrl_in.correlation_threshold); - } + if (hl->ctrl_in.correlation_threshold) { + pss_synch_set_threshold(&hl->obj, hl->ctrl_in.correlation_threshold); + } - hl->out_len = pss_synch_frame(&hl->obj, hl->input, hl->output, hl->in_len); + hl->out_len = pss_synch_frame(&hl->obj, hl->input, hl->output, hl->in_len); - return 0; + return 0; } int pss_synch_stop(pss_synch_hl* hl) { - pss_synch_free(&hl->obj); - return 0; + pss_synch_free(&hl->obj); + return 0; } diff --git a/lte/lib/sync/src/sfo.c b/lte/lib/sync/src/sfo.c index 2d13d2d2e..d484f93ab 100644 --- a/lte/lib/sync/src/sfo.c +++ b/lte/lib/sync/src/sfo.c @@ -34,24 +34,24 @@ * of length len. The parameter period is the time between t0 samples */ float sfo_estimate(int *t0, int len, float period) { - int i; - float sfo=0.0; - for (i=1;idftp_input, SSS_DFT_LEN, COMPLEX_2_COMPLEX, FORWARD)) { - return -1; - } - generate_N_id_1_table(q->N_id_1_table); - q->dftp_input.options = DFT_MIRROR_POS | DFT_DC_OFFSET; - return 0; + return -1; + } + generate_N_id_1_table(q->N_id_1_table); + q->dftp_input.options = DFT_MIRROR_POS | DFT_DC_OFFSET; + return 0; } void sss_synch_free(sss_synch_t *q) { - dft_plan_free(&q->dftp_input); - bzero(q, sizeof(sss_synch_t)); + dft_plan_free(&q->dftp_input); + bzero(q, sizeof(sss_synch_t)); } /** Initializes the SSS sequences for the given N_id_2 */ int sss_synch_set_N_id_2(sss_synch_t *q, int N_id_2) { - if (N_id_2 < 0 || N_id_2 > 2) { - fprintf(stderr, "Invalid N_id_2 %d\n", N_id_2); - return -1; - } + if (N_id_2 < 0 || N_id_2 > 2) { + fprintf(stderr, "Invalid N_id_2 %d\n", N_id_2); + return -1; + } - struct sss_tables sss_tables; - generate_sss_all_tables(&sss_tables, N_id_2); - convert_tables(&q->fc_tables, &sss_tables); + struct sss_tables sss_tables; + generate_sss_all_tables(&sss_tables, N_id_2); + convert_tables(&q->fc_tables, &sss_tables); - return 0; + return 0; } /** 36.211 10.3 section 6.11.2.2 */ void sss_put_slot(float *sss, cf_t *slot, int nof_prb, lte_cp_t cp) { - int i, k; - - k = (CP_NSYMB(cp) - 2) * nof_prb * RE_X_RB + nof_prb * RE_X_RB / 2 - 31; - memset(&slot[k - 5], 0, 5 * sizeof(cf_t)); - for (i = 0; i < SSS_LEN; i++) { - __real__ slot[k + i] = sss[i]; - __imag__ slot[k + i] = 0; - } - memset(&slot[k + SSS_LEN], 0, 5 * sizeof(cf_t)); + int i, k; + + k = (CP_NSYMB(cp) - 2) * nof_prb * RE_X_RB + nof_prb * RE_X_RB / 2 - 31; + memset(&slot[k - 5], 0, 5 * sizeof(cf_t)); + for (i = 0; i < SSS_LEN; i++) { + __real__ slot[k + i] = sss[i]; + __imag__ slot[k + i] = 0; + } + memset(&slot[k + SSS_LEN], 0, 5 * sizeof(cf_t)); } /* In this function, input points to the beginning of the subframe. Saves result in subframe_idx and N_id_1 @@ -90,99 +90,99 @@ void sss_put_slot(float *sss, cf_t *slot, int nof_prb, lte_cp_t cp) { * using sss_synch_set_threshold() and sss_synch_set_symbol_sz(). */ int sss_synch_frame(sss_synch_t *q, cf_t *input, int *subframe_idx, int *N_id_1) { - int m0, m1; - float m0_value, m1_value; - - if (q->subframe_sz <= 0 || q->symbol_sz <= 0) { - return -1; - } - - sss_synch_m0m1(q, &input[SSS_SYMBOL_ST(q->subframe_sz, q->symbol_sz)], &m0, - &m0_value, &m1, &m1_value); - - if (m0_value > q->corr_peak_threshold - && m1_value > q->corr_peak_threshold) { - if (subframe_idx) { - *subframe_idx = sss_synch_subframe(m0, m1); - } - if (N_id_1) { - *N_id_1 = sss_synch_N_id_1(q, m0, m1); - } - return 1; - } else { - return 0; - } + int m0, m1; + float m0_value, m1_value; + + if (q->subframe_sz <= 0 || q->symbol_sz <= 0) { + return -1; + } + + sss_synch_m0m1(q, &input[SSS_SYMBOL_ST(q->subframe_sz, q->symbol_sz)], &m0, + &m0_value, &m1, &m1_value); + + if (m0_value > q->corr_peak_threshold + && m1_value > q->corr_peak_threshold) { + if (subframe_idx) { + *subframe_idx = sss_synch_subframe(m0, m1); + } + if (N_id_1) { + *N_id_1 = sss_synch_N_id_1(q, m0, m1); + } + return 1; + } else { + return 0; + } } /** Used by sss_synch_frame() to compute the beginning of the SSS symbol * symbol_sz MUST INCLUDE THE CYCLIC PREFIX SIZE */ void sss_synch_set_symbol_sz(sss_synch_t *q, int symbol_sz) { - q->symbol_sz = symbol_sz; + q->symbol_sz = symbol_sz; } /** Used by sss_synch_frame() to compute the beginning of the SSS symbol */ void sss_synch_set_subframe_sz(sss_synch_t *q, int subframe_sz) { - q->subframe_sz = subframe_sz; + q->subframe_sz = subframe_sz; } /** Sets the SSS correlation peak detection threshold */ void sss_synch_set_threshold(sss_synch_t *q, float threshold) { - q->corr_peak_threshold = threshold; + q->corr_peak_threshold = threshold; } /** Returns the subframe index based on the m0 and m1 values */ int sss_synch_subframe(int m0, int m1) { - if (m1 > m0) { - return 0; - } else { - return 5; - } + if (m1 > m0) { + return 0; + } else { + return 5; + } } /** Returns the N_id_1 value based on the m0 and m1 values */ int sss_synch_N_id_1(sss_synch_t *q, int m0, int m1) { - if (m0 < 0 || m0 > 29 || m1 < 0 || m1 > 29) { - return -1; - } - if (m1 > m0) { - return q->N_id_1_table[m0][m1 - 1]; - } else { - return q->N_id_1_table[m1][m0 - 1]; - } + if (m0 < 0 || m0 > 29 || m1 < 0 || m1 > 29) { + return -1; + } + if (m1 > m0) { + return q->N_id_1_table[m0][m1 - 1]; + } else { + return q->N_id_1_table[m1][m0 - 1]; + } } /** High-level API */ int sss_synch_initialize(sss_synch_hl* h) { - if (sss_synch_init(&h->obj)) { - return -1; - } - sss_synch_set_N_id_2(&h->obj, h->init.N_id_2); + if (sss_synch_init(&h->obj)) { + return -1; + } + sss_synch_set_N_id_2(&h->obj, h->init.N_id_2); - return 0; + return 0; } int sss_synch_work(sss_synch_hl* hl) { - if (hl->ctrl_in.correlation_threshold) { - sss_synch_set_threshold(&hl->obj, hl->ctrl_in.correlation_threshold); - } - if (hl->ctrl_in.subframe_sz) { - sss_synch_set_subframe_sz(&hl->obj, hl->ctrl_in.subframe_sz); - } - if (hl->ctrl_in.symbol_sz) { - sss_synch_set_symbol_sz(&hl->obj, hl->ctrl_in.symbol_sz); - } - sss_synch_frame(&hl->obj, hl->input, &hl->ctrl_out.subframe_idx, - &hl->ctrl_out.N_id_1); - - return 0; + if (hl->ctrl_in.correlation_threshold) { + sss_synch_set_threshold(&hl->obj, hl->ctrl_in.correlation_threshold); + } + if (hl->ctrl_in.subframe_sz) { + sss_synch_set_subframe_sz(&hl->obj, hl->ctrl_in.subframe_sz); + } + if (hl->ctrl_in.symbol_sz) { + sss_synch_set_symbol_sz(&hl->obj, hl->ctrl_in.symbol_sz); + } + sss_synch_frame(&hl->obj, hl->input, &hl->ctrl_out.subframe_idx, + &hl->ctrl_out.N_id_1); + + return 0; } int sss_synch_stop(sss_synch_hl* hl) { - sss_synch_free(&hl->obj); - return 0; + sss_synch_free(&hl->obj); + return 0; } diff --git a/lte/lib/sync/src/sync.c b/lte/lib/sync/src/sync.c index 6e2172b46..bac87bc42 100644 --- a/lte/lib/sync/src/sync.c +++ b/lte/lib/sync/src/sync.c @@ -34,223 +34,223 @@ #include "lte/sync/sync.h" int sync_init(sync_t *q, int frame_size) { - int N_id_2; - - bzero(q, sizeof(sync_t)); - q->force_N_id_2 = -1; - q->threshold = 1.5; - q->pss_mode = PEAK_MEAN; - q->detect_cp = true; - q->sss_en = true; - - for (N_id_2=0;N_id_2<3;N_id_2++) { - if (pss_synch_init(&q->pss[N_id_2], frame_size)) { - fprintf(stderr, "Error initializing PSS object\n"); - return -1; - } - if (pss_synch_set_N_id_2(&q->pss[N_id_2], N_id_2)) { - fprintf(stderr, "Error initializing N_id_2\n"); - return -1; - } - if (sss_synch_init(&q->sss[N_id_2])) { - fprintf(stderr, "Error initializing SSS object\n"); - return -1; - } - if (sss_synch_set_N_id_2(&q->sss[N_id_2], N_id_2)) { - fprintf(stderr, "Error initializing N_id_2\n"); - return -1; - } - DEBUG("PSS and SSS initiated N_id_2=%d\n", N_id_2); - } - - return 0; + int N_id_2; + + bzero(q, sizeof(sync_t)); + q->force_N_id_2 = -1; + q->threshold = 1.5; + q->pss_mode = PEAK_MEAN; + q->detect_cp = true; + q->sss_en = true; + + for (N_id_2=0;N_id_2<3;N_id_2++) { + if (pss_synch_init(&q->pss[N_id_2], frame_size)) { + fprintf(stderr, "Error initializing PSS object\n"); + return -1; + } + if (pss_synch_set_N_id_2(&q->pss[N_id_2], N_id_2)) { + fprintf(stderr, "Error initializing N_id_2\n"); + return -1; + } + if (sss_synch_init(&q->sss[N_id_2])) { + fprintf(stderr, "Error initializing SSS object\n"); + return -1; + } + if (sss_synch_set_N_id_2(&q->sss[N_id_2], N_id_2)) { + fprintf(stderr, "Error initializing N_id_2\n"); + return -1; + } + DEBUG("PSS and SSS initiated N_id_2=%d\n", N_id_2); + } + + return 0; } void sync_free(sync_t *q) { - int N_id_2; + int N_id_2; - for (N_id_2=0;N_id_2<3;N_id_2++) { - pss_synch_free(&q->pss[N_id_2]); - sss_synch_free(&q->sss[N_id_2]); - } + for (N_id_2=0;N_id_2<3;N_id_2++) { + pss_synch_free(&q->pss[N_id_2]); + sss_synch_free(&q->sss[N_id_2]); + } } void sync_pss_det_absolute(sync_t *q) { - q->pss_mode = ABSOLUTE; + q->pss_mode = ABSOLUTE; } void sync_pss_det_peak_to_avg(sync_t *q) { - q->pss_mode = PEAK_MEAN; + q->pss_mode = PEAK_MEAN; } void sync_set_threshold(sync_t *q, float threshold) { - q->threshold = threshold; + q->threshold = threshold; } void sync_force_N_id_2(sync_t *q, int force_N_id_2) { - q->force_N_id_2 = force_N_id_2; + q->force_N_id_2 = force_N_id_2; } void sync_force_cp(sync_t *q, lte_cp_t cp) { - q->cp = cp; - q->detect_cp = false; + q->cp = cp; + q->detect_cp = false; } void sync_sss_en(sync_t *q, bool enabled) { - q->sss_en = enabled; + q->sss_en = enabled; } int sync_get_cell_id(sync_t *q) { - if (q->N_id_1 >=0 && q->N_id_2 >= 0) { - return q->N_id_1*3 + q->N_id_2; - } else { - return -1; - } + if (q->N_id_1 >=0 && q->N_id_2 >= 0) { + return q->N_id_1*3 + q->N_id_2; + } else { + return -1; + } } int sync_get_N_id_1(sync_t *q) { - return q->N_id_1; + return q->N_id_1; } int sync_get_N_id_2(sync_t *q) { - return q->N_id_2; + return q->N_id_2; } int sync_get_slot_id(sync_t *q) { - return q->slot_id; + return q->slot_id; } float sync_get_cfo(sync_t *q) { - return q->cfo; + return q->cfo; } float sync_get_peak_to_avg(sync_t *q) { - return q->peak_to_avg; + return q->peak_to_avg; } lte_cp_t sync_get_cp(sync_t *q) { - return q->cp; + return q->cp; } int sync_run(sync_t *q, cf_t *input) { - int N_id_2, peak_pos[3], sss_idx_n, sss_idx_e; - int m0, m1; - float m0_value_e, m1_value_e,m0_value_n, m1_value_n; - int slot_id_e, N_id_1_e, slot_id_n, N_id_1_n; - float peak_value[3]; - float mean_value[3]; - float max=-999; - int i; - int peak_detected; - - if (q->force_N_id_2 == -1) { - for (N_id_2=0;N_id_2<3;N_id_2++) { - peak_pos[N_id_2] = pss_synch_find_pss(&q->pss[N_id_2], input, - &peak_value[N_id_2], &mean_value[N_id_2]); - } - for (i=0;i<3;i++) { - if (peak_value[i] > max) { - max = peak_value[i]; - N_id_2 = i; - } - } - } else { - N_id_2 = q->force_N_id_2; - peak_pos[N_id_2] = pss_synch_find_pss(&q->pss[N_id_2], input, - &peak_value[N_id_2], &mean_value[N_id_2]); - } - - q->peak_to_avg = peak_value[N_id_2] / mean_value[N_id_2]; - - DEBUG("PSS possible peak N_id_2=%d, pos=%d peak=%.2f par=%.2f threshold=%.2f\n", - N_id_2, peak_pos[N_id_2], peak_value[N_id_2], q->peak_to_avg, q->threshold); - - /* If peak detected */ - peak_detected = 0; - if (peak_pos[N_id_2] - 128 >= 0) { - if (q->pss_mode == ABSOLUTE) { - if (peak_value[N_id_2] > q->threshold) { - peak_detected = 1; - } - } else { - if (q->peak_to_avg > q->threshold) { - peak_detected = 1; - } - } - } - if (peak_detected) { - - q->cfo = pss_synch_cfo_compute(&q->pss[N_id_2], &input[peak_pos[N_id_2]-128]); - - INFO("PSS peak detected N_id_2=%d, pos=%d peak=%.2f par=%.2f th=%.2f cfo=%.4f\n", N_id_2, - peak_pos[N_id_2], peak_value[N_id_2], q->peak_to_avg, q->threshold, q->cfo); - - if (q->sss_en) { - - /* Make sure we have enough room to find SSS sequence */ - sss_idx_n = peak_pos[N_id_2]-2*(128+CP(128,CPNORM_LEN)); - sss_idx_e = peak_pos[N_id_2]-2*(128+CP(128,CPEXT_LEN)); - - if (q->detect_cp) { - if (sss_idx_n < 0 || sss_idx_e < 0) { - INFO("Not enough room to decode SSS (%d, %d)\n", sss_idx_n, sss_idx_e); - return -1; - } - } else { - if (CP_ISNORM(q->cp)) { - if (sss_idx_n < 0) { - INFO("Not enough room to decode SSS (%d)\n", sss_idx_n); - return -1; - } - } else { - if (sss_idx_e < 0) { - INFO("Not enough room to decode SSS (%d)\n", sss_idx_e); - return -1; - } - } - } - N_id_1_e = -1; - N_id_1_n = -1; - slot_id_e = -1; - slot_id_n = -1; - /* try Normal CP length */ - if (q->detect_cp || CP_ISNORM(q->cp)) { - sss_synch_m0m1(&q->sss[N_id_2], &input[sss_idx_n], - &m0, &m0_value_n, &m1, &m1_value_n); - - slot_id_n = 2 * sss_synch_subframe(m0, m1); - N_id_1_n = sss_synch_N_id_1(&q->sss[N_id_2], m0, m1); - } - - if (q->detect_cp || CP_ISEXT(q->cp)) { - /* Now try Extended CP length */ - sss_synch_m0m1(&q->sss[N_id_2], &input[sss_idx_e], - &m0, &m0_value_e, &m1, &m1_value_e); - - slot_id_e = 2 * sss_synch_subframe(m0, m1); - N_id_1_e = sss_synch_N_id_1(&q->sss[N_id_2], m0, m1); - } - - /* Correlation with extended CP hypoteshis is greater than with normal? */ - if ((q->detect_cp && m0_value_e * m1_value_e > m0_value_n * m1_value_n) - || CP_ISEXT(q->cp)) { - q->cp = CPEXT; - q->slot_id = slot_id_e; - q->N_id_1 = N_id_1_e; - /* then is normal CP */ - } else { - q->cp = CPNORM; - q->slot_id = slot_id_n; - q->N_id_1 = N_id_1_n; - } - q->N_id_2 = N_id_2; - - INFO("SSS detected N_id_1=%d, slot_idx=%d, %s CP\n", - q->N_id_1, q->slot_id, CP_ISNORM(q->cp)?"Normal":"Extended"); - } - - return peak_pos[N_id_2]; - - } else { - return -1; - } + int N_id_2, peak_pos[3], sss_idx_n, sss_idx_e; + int m0, m1; + float m0_value_e, m1_value_e,m0_value_n, m1_value_n; + int slot_id_e, N_id_1_e, slot_id_n, N_id_1_n; + float peak_value[3]; + float mean_value[3]; + float max=-999; + int i; + int peak_detected; + + if (q->force_N_id_2 == -1) { + for (N_id_2=0;N_id_2<3;N_id_2++) { + peak_pos[N_id_2] = pss_synch_find_pss(&q->pss[N_id_2], input, + &peak_value[N_id_2], &mean_value[N_id_2]); + } + for (i=0;i<3;i++) { + if (peak_value[i] > max) { + max = peak_value[i]; + N_id_2 = i; + } + } + } else { + N_id_2 = q->force_N_id_2; + peak_pos[N_id_2] = pss_synch_find_pss(&q->pss[N_id_2], input, + &peak_value[N_id_2], &mean_value[N_id_2]); + } + + q->peak_to_avg = peak_value[N_id_2] / mean_value[N_id_2]; + + DEBUG("PSS possible peak N_id_2=%d, pos=%d peak=%.2f par=%.2f threshold=%.2f\n", + N_id_2, peak_pos[N_id_2], peak_value[N_id_2], q->peak_to_avg, q->threshold); + + /* If peak detected */ + peak_detected = 0; + if (peak_pos[N_id_2] - 128 >= 0) { + if (q->pss_mode == ABSOLUTE) { + if (peak_value[N_id_2] > q->threshold) { + peak_detected = 1; + } + } else { + if (q->peak_to_avg > q->threshold) { + peak_detected = 1; + } + } + } + if (peak_detected) { + + q->cfo = pss_synch_cfo_compute(&q->pss[N_id_2], &input[peak_pos[N_id_2]-128]); + + INFO("PSS peak detected N_id_2=%d, pos=%d peak=%.2f par=%.2f th=%.2f cfo=%.4f\n", N_id_2, + peak_pos[N_id_2], peak_value[N_id_2], q->peak_to_avg, q->threshold, q->cfo); + + if (q->sss_en) { + + /* Make sure we have enough room to find SSS sequence */ + sss_idx_n = peak_pos[N_id_2]-2*(128+CP(128,CPNORM_LEN)); + sss_idx_e = peak_pos[N_id_2]-2*(128+CP(128,CPEXT_LEN)); + + if (q->detect_cp) { + if (sss_idx_n < 0 || sss_idx_e < 0) { + INFO("Not enough room to decode SSS (%d, %d)\n", sss_idx_n, sss_idx_e); + return -1; + } + } else { + if (CP_ISNORM(q->cp)) { + if (sss_idx_n < 0) { + INFO("Not enough room to decode SSS (%d)\n", sss_idx_n); + return -1; + } + } else { + if (sss_idx_e < 0) { + INFO("Not enough room to decode SSS (%d)\n", sss_idx_e); + return -1; + } + } + } + N_id_1_e = -1; + N_id_1_n = -1; + slot_id_e = -1; + slot_id_n = -1; + /* try Normal CP length */ + if (q->detect_cp || CP_ISNORM(q->cp)) { + sss_synch_m0m1(&q->sss[N_id_2], &input[sss_idx_n], + &m0, &m0_value_n, &m1, &m1_value_n); + + slot_id_n = 2 * sss_synch_subframe(m0, m1); + N_id_1_n = sss_synch_N_id_1(&q->sss[N_id_2], m0, m1); + } + + if (q->detect_cp || CP_ISEXT(q->cp)) { + /* Now try Extended CP length */ + sss_synch_m0m1(&q->sss[N_id_2], &input[sss_idx_e], + &m0, &m0_value_e, &m1, &m1_value_e); + + slot_id_e = 2 * sss_synch_subframe(m0, m1); + N_id_1_e = sss_synch_N_id_1(&q->sss[N_id_2], m0, m1); + } + + /* Correlation with extended CP hypoteshis is greater than with normal? */ + if ((q->detect_cp && m0_value_e * m1_value_e > m0_value_n * m1_value_n) + || CP_ISEXT(q->cp)) { + q->cp = CPEXT; + q->slot_id = slot_id_e; + q->N_id_1 = N_id_1_e; + /* then is normal CP */ + } else { + q->cp = CPNORM; + q->slot_id = slot_id_n; + q->N_id_1 = N_id_1_n; + } + q->N_id_2 = N_id_2; + + INFO("SSS detected N_id_1=%d, slot_idx=%d, %s CP\n", + q->N_id_1, q->slot_id, CP_ISNORM(q->cp)?"Normal":"Extended"); + } + + return peak_pos[N_id_2]; + + } else { + return -1; + } } diff --git a/lte/lib/sync/test/cfo_test.c b/lte/lib/sync/test/cfo_test.c index 13db50c75..4d2445901 100644 --- a/lte/lib/sync/test/cfo_test.c +++ b/lte/lib/sync/test/cfo_test.c @@ -36,84 +36,84 @@ #include "lte.h" -#define MAX_MSE 0.1 +#define MAX_MSE 0.1 float freq = 0; int num_samples = 1000; void usage(char *prog) { - printf("Usage: %s -f freq -n num_samples\n", prog); + printf("Usage: %s -f freq -n num_samples\n", prog); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "nf")) != -1) { - switch (opt) { - case 'n': - num_samples = atoi(argv[optind]); - break; - case 'f': - freq = atof(argv[optind]); - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "nf")) != -1) { + switch (opt) { + case 'n': + num_samples = atoi(argv[optind]); + break; + case 'f': + freq = atof(argv[optind]); + break; + default: + usage(argv[0]); + exit(-1); + } + } } int main(int argc, char **argv) { - int i; - cf_t *input, *output; - cfo_t cfocorr; - float mse; - - if (argc < 5) { - usage(argv[0]); - exit(-1); - } - - parse_args(argc, argv); - - input = malloc(sizeof(cf_t) * num_samples); - if (!input) { - perror("malloc"); - exit(-1); - } - output = malloc(sizeof(cf_t) * num_samples); - if (!output) { - perror("malloc"); - exit(-1); - } - - for (i=0;i MAX_MSE) { - printf("MSE too large\n"); - exit(-1); - } else { - printf("Ok\n"); - exit(0); - } + int i; + cf_t *input, *output; + cfo_t cfocorr; + float mse; + + if (argc < 5) { + usage(argv[0]); + exit(-1); + } + + parse_args(argc, argv); + + input = malloc(sizeof(cf_t) * num_samples); + if (!input) { + perror("malloc"); + exit(-1); + } + output = malloc(sizeof(cf_t) * num_samples); + if (!output) { + perror("malloc"); + exit(-1); + } + + for (i=0;i MAX_MSE) { + printf("MSE too large\n"); + exit(-1); + } else { + printf("Ok\n"); + exit(0); + } } diff --git a/lte/lib/sync/test/sync_test.c b/lte/lib/sync/test/sync_test.c index a74504b82..c46681875 100644 --- a/lte/lib/sync/test/sync_test.c +++ b/lte/lib/sync/test/sync_test.c @@ -39,128 +39,128 @@ int cell_id = -1, offset = 0; lte_cp_t cp = CPNORM; -#define FLEN 9600 +#define FLEN 9600 void usage(char *prog) { - printf("Usage: %s [coev]\n", prog); - printf("\t-c cell_id [Default check for all]\n"); - printf("\t-o offset [Default %d]\n", offset); - printf("\t-e extended CP [Default normal]\n"); - printf("\t-v verbose\n"); + printf("Usage: %s [coev]\n", prog); + printf("\t-c cell_id [Default check for all]\n"); + printf("\t-o offset [Default %d]\n", offset); + printf("\t-e extended CP [Default normal]\n"); + printf("\t-v verbose\n"); } void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "coev")) != -1) { - switch (opt) { - case 'c': - cell_id = atoi(argv[optind]); - break; - case 'o': - offset = atoi(argv[optind]); - break; - case 'e': - cp = CPEXT; - break; - case 'v': - verbose++; - break; - default: - usage(argv[0]); - exit(-1); - } - } + int opt; + while ((opt = getopt(argc, argv, "coev")) != -1) { + switch (opt) { + case 'c': + cell_id = atoi(argv[optind]); + break; + case 'o': + offset = atoi(argv[optind]); + break; + case 'e': + cp = CPEXT; + break; + case 'v': + verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } } int main(int argc, char **argv) { - int N_id_2, ns, find_ns; - cf_t *buffer, *fft_buffer; - cf_t pss_signal[PSS_LEN]; - float sss_signal0[SSS_LEN]; // for subframe 0 - float sss_signal5[SSS_LEN]; // for subframe 5 - int cid, max_cid, find_idx; - sync_t sync; - lte_fft_t ifft; - - parse_args(argc, argv); - - buffer = malloc(sizeof(cf_t) * FLEN); - if (!buffer) { - perror("malloc"); - exit(-1); - } - - fft_buffer = malloc(sizeof(cf_t) * 2 * FLEN); - if (!fft_buffer) { - perror("malloc"); - exit(-1); - } - - if (lte_ifft_init(&ifft, cp, 6)) { - fprintf(stderr, "Error creating iFFT object\n"); - exit(-1); - } - - if (sync_init(&sync, FLEN)) { - fprintf(stderr, "Error initiating PSS/SSS\n"); - return -1; - } - - sync_set_threshold(&sync, 20); - sync_force_N_id_2(&sync, -1); - - if (cell_id == -1) { - cid = 0; - max_cid = 149; - } else { - cid = cell_id; - max_cid = cell_id; + int N_id_2, ns, find_ns; + cf_t *buffer, *fft_buffer; + cf_t pss_signal[PSS_LEN]; + float sss_signal0[SSS_LEN]; // for subframe 0 + float sss_signal5[SSS_LEN]; // for subframe 5 + int cid, max_cid, find_idx; + sync_t sync; + lte_fft_t ifft; + + parse_args(argc, argv); + + buffer = malloc(sizeof(cf_t) * FLEN); + if (!buffer) { + perror("malloc"); + exit(-1); + } + + fft_buffer = malloc(sizeof(cf_t) * 2 * FLEN); + if (!fft_buffer) { + perror("malloc"); + exit(-1); + } + + if (lte_ifft_init(&ifft, cp, 6)) { + fprintf(stderr, "Error creating iFFT object\n"); + exit(-1); + } + + if (sync_init(&sync, FLEN)) { + fprintf(stderr, "Error initiating PSS/SSS\n"); + return -1; + } + + sync_set_threshold(&sync, 20); + sync_force_N_id_2(&sync, -1); + + if (cell_id == -1) { + cid = 0; + max_cid = 149; + } else { + cid = cell_id; + max_cid = cell_id; } - while(cid <= max_cid) { - N_id_2 = cid%3; - - /* Generate PSS/SSS signals */ - pss_generate(pss_signal, N_id_2); - sss_generate(sss_signal0, sss_signal5, cid); - - for (ns=0;ns<2;ns++) { - memset(buffer, 0, sizeof(cf_t) * FLEN); - pss_put_slot(pss_signal, buffer, 6, cp); - sss_put_slot(ns?sss_signal5:sss_signal0, buffer, 6, cp); - - /* Transform to OFDM symbols */ - memset(fft_buffer, 0, sizeof(cf_t) * 2 * FLEN); - lte_ifft_run(&ifft, buffer, &fft_buffer[offset]); - - find_idx = sync_run(&sync, fft_buffer); - find_ns = sync_get_slot_id(&sync); - printf("cell_id: %d find: %d, offset: %d, ns=%d find_ns=%d\n", cid, find_idx, offset, - ns, find_ns); - if (find_idx != offset + 960) { - printf("offset != find_offset: %d != %d\n", find_idx, offset + 960); - exit(-1); - } - if (ns*10 != find_ns) { - printf("ns != find_ns\n", 10 * ns, find_ns); - exit(-1); - } - if (sync_get_cp(&sync) != cp) { - printf("Detected CP should be %s\n", CP_ISNORM(cp)?"Normal":"Extended"); - exit(-1); - } - } - cid++; - } - - free(fft_buffer); - free(buffer); - - sync_free(&sync); - lte_ifft_free(&ifft); - - fftwf_cleanup(); - - printf("Ok\n"); - exit(0); + while(cid <= max_cid) { + N_id_2 = cid%3; + + /* Generate PSS/SSS signals */ + pss_generate(pss_signal, N_id_2); + sss_generate(sss_signal0, sss_signal5, cid); + + for (ns=0;ns<2;ns++) { + memset(buffer, 0, sizeof(cf_t) * FLEN); + pss_put_slot(pss_signal, buffer, 6, cp); + sss_put_slot(ns?sss_signal5:sss_signal0, buffer, 6, cp); + + /* Transform to OFDM symbols */ + memset(fft_buffer, 0, sizeof(cf_t) * 2 * FLEN); + lte_ifft_run(&ifft, buffer, &fft_buffer[offset]); + + find_idx = sync_run(&sync, fft_buffer); + find_ns = sync_get_slot_id(&sync); + printf("cell_id: %d find: %d, offset: %d, ns=%d find_ns=%d\n", cid, find_idx, offset, + ns, find_ns); + if (find_idx != offset + 960) { + printf("offset != find_offset: %d != %d\n", find_idx, offset + 960); + exit(-1); + } + if (ns*10 != find_ns) { + printf("ns != find_ns\n", 10 * ns, find_ns); + exit(-1); + } + if (sync_get_cp(&sync) != cp) { + printf("Detected CP should be %s\n", CP_ISNORM(cp)?"Normal":"Extended"); + exit(-1); + } + } + cid++; + } + + free(fft_buffer); + free(buffer); + + sync_free(&sync); + lte_ifft_free(&ifft); + + fftwf_cleanup(); + + printf("Ok\n"); + exit(0); } diff --git a/lte/lib/utils/src/bit.c b/lte/lib/utils/src/bit.c index 22b356f9f..a25a3f430 100644 --- a/lte/lib/utils/src/bit.c +++ b/lte/lib/utils/src/bit.c @@ -47,31 +47,31 @@ uint32_t bit_unpack(char **bits, int nof_bits) unsigned int value=0; for(i=0; isize = size; - h->tab = malloc(sizeof(cf_t) * size); - if (h->tab) { - for (i = 0; i < size; i++) { - h->tab[i] = cexpf(_Complex_I * 2 * M_PI * (float) i / size); - } - return 0; - } else { - return -1; - } + h->size = size; + h->tab = malloc(sizeof(cf_t) * size); + if (h->tab) { + for (i = 0; i < size; i++) { + h->tab[i] = cexpf(_Complex_I * 2 * M_PI * (float) i / size); + } + return 0; + } else { + return -1; + } } void cexptab_free(cexptab_t *h) { - if (h->tab) { - free(h->tab); - } - bzero(h, sizeof(cexptab_t)); + if (h->tab) { + free(h->tab); + } + bzero(h, sizeof(cexptab_t)); } void cexptab_gen(cexptab_t *h, cf_t *x, float freq, int len) { - int i; - unsigned int idx; - float phase_inc = freq * h->size; - float phase=0; + int i; + unsigned int idx; + float phase_inc = freq * h->size; + float phase=0; - for (i = 0; i < len; i++) { - while (phase >= (float) h->size) { - phase -= (float) h->size; - } - while (phase < 0) { - phase += (float) h->size; - } - idx = (unsigned int) phase; - x[i] = h->tab[idx]; - phase += phase_inc; + for (i = 0; i < len; i++) { + while (phase >= (float) h->size) { + phase -= (float) h->size; + } + while (phase < 0) { + phase += (float) h->size; + } + idx = (unsigned int) phase; + x[i] = h->tab[idx]; + phase += phase_inc; - } + } } void cexptab_gen_direct(cf_t *x, float freq, int len) { - int i; - for (i = 0; i < len; i++) { - x[i] = cexpf(_Complex_I * 2 * M_PI * freq * i); - } + int i; + for (i = 0; i < len; i++) { + x[i] = cexpf(_Complex_I * 2 * M_PI * freq * i); + } } diff --git a/lte/lib/utils/src/convolution.c b/lte/lib/utils/src/convolution.c index 93ac4db56..ba3b4cbc9 100644 --- a/lte/lib/utils/src/convolution.c +++ b/lte/lib/utils/src/convolution.c @@ -35,64 +35,64 @@ int conv_fft_cc_init(conv_fft_cc_t *state, int input_len, int filter_len) { - state->input_len = input_len; - state->filter_len = filter_len; - state->output_len = input_len+filter_len-1; - state->input_fft = vec_malloc(sizeof(_Complex float)*state->output_len); - state->filter_fft = vec_malloc(sizeof(_Complex float)*state->output_len); - state->output_fft = vec_malloc(sizeof(_Complex float)*state->output_len); - if (!state->input_fft || !state->filter_fft || !state->output_fft) { - return -1; - } + state->input_len = input_len; + state->filter_len = filter_len; + state->output_len = input_len+filter_len-1; + state->input_fft = vec_malloc(sizeof(_Complex float)*state->output_len); + state->filter_fft = vec_malloc(sizeof(_Complex float)*state->output_len); + state->output_fft = vec_malloc(sizeof(_Complex float)*state->output_len); + if (!state->input_fft || !state->filter_fft || !state->output_fft) { + return -1; + } if (dft_plan(&state->input_plan,state->output_len,COMPLEX_2_COMPLEX,FORWARD)) { - return -2; - } + return -2; + } if (dft_plan(&state->filter_plan,state->output_len,COMPLEX_2_COMPLEX,FORWARD)) { - return -3; - } + return -3; + } if (dft_plan(&state->output_plan,state->output_len,COMPLEX_2_COMPLEX,BACKWARD)) { - return -4; - } - return 0; + return -4; + } + return 0; } void conv_fft_cc_free(conv_fft_cc_t *state) { - if (state->input_fft) { - free(state->input_fft); - } - if (state->filter_fft) { - free(state->filter_fft); - } - if (state->output_fft) { - free(state->output_fft); - } - dft_plan_free(&state->input_plan); - dft_plan_free(&state->filter_plan); - dft_plan_free(&state->output_plan); + if (state->input_fft) { + free(state->input_fft); + } + if (state->filter_fft) { + free(state->filter_fft); + } + if (state->output_fft) { + free(state->output_fft); + } + dft_plan_free(&state->input_plan); + dft_plan_free(&state->filter_plan); + dft_plan_free(&state->output_plan); } int conv_fft_cc_run(conv_fft_cc_t *state, _Complex float *input, _Complex float *filter, _Complex float *output) { - dft_run_c2c(&state->input_plan, input, state->input_fft); - dft_run_c2c(&state->filter_plan, filter, state->filter_fft); + dft_run_c2c(&state->input_plan, input, state->input_fft); + dft_run_c2c(&state->filter_plan, filter, state->filter_fft); - vec_prod_ccc(state->input_fft,state->filter_fft,state->output_fft,state->output_len); + vec_prod_ccc(state->input_fft,state->filter_fft,state->output_fft,state->output_len); - dft_run_c2c(&state->output_plan, state->output_fft, output); + dft_run_c2c(&state->output_plan, state->output_fft, output); - return state->output_len; + return state->output_len; } int conv_cc(_Complex float *input, _Complex float *filter, _Complex float *output, int input_len, int filter_len) { - int i,j; - int output_len; - output_len=input_len+filter_len-1; - memset(output,0,output_len*sizeof(_Complex float)); - for (i=0;iin = fftwf_malloc(size_in*len); - plan->out = fftwf_malloc(size_out*len); + plan->in = fftwf_malloc(size_in*len); + plan->out = fftwf_malloc(size_out*len); } int dft_plan_c2c(dft_plan_t *plan, const int dft_points, dft_dir_t dir) { - int sign; - sign = (dir == FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; - allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points); + int sign; + sign = (dir == FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; + allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points); - plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, 0U); - if (!plan->p) { - return -1; - } + plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, 0U); + if (!plan->p) { + return -1; + } - plan->size = dft_points; - plan->mode = COMPLEX_2_COMPLEX; + plan->size = dft_points; + plan->mode = COMPLEX_2_COMPLEX; - return 0; + return 0; } int dft_plan_r2r(dft_plan_t *plan, const int dft_points, dft_dir_t dir) { - int sign; - sign = (dir == FORWARD) ? FFTW_R2HC : FFTW_HC2R; + int sign; + sign = (dir == FORWARD) ? FFTW_R2HC : FFTW_HC2R; - allocate(plan,sizeof(float),sizeof(float), dft_points); + allocate(plan,sizeof(float),sizeof(float), dft_points); - plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, 0U); - if (!plan->p) { - return -1; - } + plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, 0U); + if (!plan->p) { + return -1; + } - plan->size = dft_points; - plan->mode = REAL_2_REAL; + plan->size = dft_points; + plan->mode = REAL_2_REAL; - return 0; + return 0; } int dft_plan_c2r(dft_plan_t *plan, const int dft_points, dft_dir_t dir) { if (dft_plan_c2c(plan, dft_points, dir)) { - return -1; - } - plan->mode = COMPLEX_2_REAL; - return 0; + return -1; + } + plan->mode = COMPLEX_2_REAL; + return 0; } static void copy(char *dst, char *src, int size_d, int len, int mirror, int dc_offset) { - int offset=dc_offset?1:0; - int hlen; - if (mirror == DFT_MIRROR_PRE) { - hlen = div(len,2); - memset(dst,0,size_d*offset); - memcpy(&dst[offset*size_d], &src[size_d*hlen], size_d*(hlen-offset)); - memcpy(&dst[hlen*size_d], src, size_d*(len - hlen)); - } else if (mirror == DFT_MIRROR_POS) { - hlen = div(len,2); - memcpy(dst, &src[size_d*hlen], size_d*hlen); - memcpy(&dst[hlen*size_d], &src[size_d*offset], size_d*(len - hlen)); - } else { - memcpy(dst,src,size_d*len); - } + int offset=dc_offset?1:0; + int hlen; + if (mirror == DFT_MIRROR_PRE) { + hlen = div(len,2); + memset(dst,0,size_d*offset); + memcpy(&dst[offset*size_d], &src[size_d*hlen], size_d*(hlen-offset)); + memcpy(&dst[hlen*size_d], src, size_d*(len - hlen)); + } else if (mirror == DFT_MIRROR_POS) { + hlen = div(len,2); + memcpy(dst, &src[size_d*hlen], size_d*hlen); + memcpy(&dst[hlen*size_d], &src[size_d*offset], size_d*(len - hlen)); + } else { + memcpy(dst,src,size_d*len); + } } void dft_run(dft_plan_t *plan, void *in, void *out) { - switch(plan->mode) { - case COMPLEX_2_COMPLEX: - dft_run_c2c(plan,in,out); - break; - case REAL_2_REAL: - dft_run_r2r(plan,in,out); - break; - case COMPLEX_2_REAL: - dft_run_c2r(plan,in,out); - break; - } + switch(plan->mode) { + case COMPLEX_2_COMPLEX: + dft_run_c2c(plan,in,out); + break; + case REAL_2_REAL: + dft_run_r2r(plan,in,out); + break; + case COMPLEX_2_REAL: + dft_run_c2r(plan,in,out); + break; + } } void dft_run_c2c(dft_plan_t *plan, dft_c_t *in, dft_c_t *out) { - float norm; - int i; - fftwf_complex *f_out = plan->out; - - copy((char*) plan->in,(char*) in,sizeof(dft_c_t),plan->size,plan->options & DFT_MIRROR_PRE, - plan->options & DFT_DC_OFFSET); - - fftwf_execute(plan->p); - - if (plan->options & DFT_NORMALIZE) { - /**FIXME: Use VOLK */ - norm = sqrtf(plan->size); - for (i=0;isize;i++) { - f_out[i] /= norm; - } - } - if (plan->options & DFT_OUT_DB) { - for (i=0;isize;i++) { - f_out[i] = 10*log10(f_out[i]); - } - } - copy((char*) out,(char*) plan->out,sizeof(dft_c_t),plan->size,plan->options & DFT_MIRROR_POS, - plan->options & DFT_DC_OFFSET); + float norm; + int i; + fftwf_complex *f_out = plan->out; + + copy((char*) plan->in,(char*) in,sizeof(dft_c_t),plan->size,plan->options & DFT_MIRROR_PRE, + plan->options & DFT_DC_OFFSET); + + fftwf_execute(plan->p); + + if (plan->options & DFT_NORMALIZE) { + /**FIXME: Use VOLK */ + norm = sqrtf(plan->size); + for (i=0;isize;i++) { + f_out[i] /= norm; + } + } + if (plan->options & DFT_OUT_DB) { + for (i=0;isize;i++) { + f_out[i] = 10*log10(f_out[i]); + } + } + copy((char*) out,(char*) plan->out,sizeof(dft_c_t),plan->size,plan->options & DFT_MIRROR_POS, + plan->options & DFT_DC_OFFSET); } void dft_run_r2r(dft_plan_t *plan, dft_r_t *in, dft_r_t *out) { - float norm; - int i; - int len = plan->size; - float *f_out = plan->out; - - copy((char*) plan->in,(char*) in,sizeof(dft_r_t),plan->size,plan->options & DFT_MIRROR_PRE, - plan->options & DFT_DC_OFFSET); - - fftwf_execute(plan->p); - - if (plan->options & DFT_NORMALIZE) { - norm = plan->size; - for (i=0;ioptions & DFT_PSD) { - for (i=0;i<(len+1)/2-1;i++) { + float norm; + int i; + int len = plan->size; + float *f_out = plan->out; + + copy((char*) plan->in,(char*) in,sizeof(dft_r_t),plan->size,plan->options & DFT_MIRROR_PRE, + plan->options & DFT_DC_OFFSET); + + fftwf_execute(plan->p); + + if (plan->options & DFT_NORMALIZE) { + norm = plan->size; + for (i=0;ioptions & DFT_PSD) { + for (i=0;i<(len+1)/2-1;i++) { out[i] = sqrtf(f_out[i]*f_out[i]+f_out[len-i-1]*f_out[len-i-1]); - } - } - if (plan->options & DFT_OUT_DB) { - for (i=0;ioptions & DFT_OUT_DB) { + for (i=0;iout; - - copy((char*) plan->in,(char*) in,sizeof(dft_r_t),plan->size,plan->options & DFT_MIRROR_PRE, - plan->options & DFT_DC_OFFSET); - - fftwf_execute(plan->p); - - if (plan->options & DFT_NORMALIZE) { - norm = plan->size; - for (i=0;isize;i++) { - f_out[i] /= norm; - } - } - if (plan->options & DFT_PSD) { - for (i=0;isize;i++) { - out[i] = (__real__ f_out[i])*(__real__ f_out[i])+ - (__imag__ f_out[i])*(__imag__ f_out[i]); - if (!(plan->options & DFT_OUT_DB)) { - out[i] = sqrtf(out[i]); - } - } - } - if (plan->options & DFT_OUT_DB) { - for (i=0;isize;i++) { - out[i] = 10*log10(out[i]); - } - } + int i; + float norm; + float *f_out = plan->out; + + copy((char*) plan->in,(char*) in,sizeof(dft_r_t),plan->size,plan->options & DFT_MIRROR_PRE, + plan->options & DFT_DC_OFFSET); + + fftwf_execute(plan->p); + + if (plan->options & DFT_NORMALIZE) { + norm = plan->size; + for (i=0;isize;i++) { + f_out[i] /= norm; + } + } + if (plan->options & DFT_PSD) { + for (i=0;isize;i++) { + out[i] = (__real__ f_out[i])*(__real__ f_out[i])+ + (__imag__ f_out[i])*(__imag__ f_out[i]); + if (!(plan->options & DFT_OUT_DB)) { + out[i] = sqrtf(out[i]); + } + } + } + if (plan->options & DFT_OUT_DB) { + for (i=0;isize;i++) { + out[i] = 10*log10(out[i]); + } + } } void dft_plan_free(dft_plan_t *plan) { - if (!plan) return; - if (!plan->size) return; - if (plan->in) fftwf_free(plan->in); - if (plan->out) fftwf_free(plan->out); - if (plan->p) fftwf_destroy_plan(plan->p); - bzero(plan, sizeof(dft_plan_t)); + if (!plan) return; + if (!plan->size) return; + if (plan->in) fftwf_free(plan->in); + if (plan->out) fftwf_free(plan->out); + if (plan->p) fftwf_destroy_plan(plan->p); + bzero(plan, sizeof(dft_plan_t)); } void dft_plan_free_vector(dft_plan_t *plan, int nof_plans) { - int i; - for (i=0;im) { - m=x[i]; - p=i; - } - } - return p; + int i; + float m=-FLT_MAX; + int p=0; + for (i=0;im) { + m=x[i]; + p=i; + } + } + return p; #endif } void vec_quant_fuc(float *in, unsigned char *out, float gain, float offset, float clip, int len) { - int i; - int tmp; - for (i=0;i clip) - tmp = clip; - out[i] = (unsigned char) tmp; - } + int i; + int tmp; + for (i=0;i clip) + tmp = clip; + out[i] = (unsigned char) tmp; + } } diff --git a/scripts/xml2aloe/template/src/template.c b/scripts/xml2aloe/template/src/template.c index cdf1cdf14..0236244d5 100644 --- a/scripts/xml2aloe/template/src/template.c +++ b/scripts/xml2aloe/template/src/template.c @@ -44,57 +44,57 @@ int out_len[NOF_OUTPUT_ITF]; int initialize() { - /* Initialization Parameters */ - --init_parameters-- + /* Initialization Parameters */ + --init_parameters-- - /* Input Control Parameters */ - --input_parameters_getid-- + /* Input Control Parameters */ + --input_parameters_getid-- - /* Initialization function */ - return -name-_initialize(&-name-); + /* Initialization function */ + return -name-_initialize(&-name-); } int work(void **inp, void **out) { - int i,n; + int i,n; #if NOF_INPUTS>1 - for (i=0;i1 - for (i=0;i