diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 70b0d7c29..d09f0101c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -28,9 +28,6 @@ target_link_libraries(equalizer_test ${LIBRARIES}) add_executable(viterbi_test viterbi_test.c) target_link_libraries(viterbi_test ${LIBRARIES}) -add_executable(bch_test bch_test.c) -target_link_libraries(bch_test ${LIBRARIES}) - add_executable(cell_search cell_search.c) target_link_libraries(cell_search ${LIBRARIES}) diff --git a/examples/bch_test.c b/examples/bch_test.c deleted file mode 100644 index 84bb6fdcb..000000000 --- a/examples/bch_test.c +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include -#include -#include - -#include "lte.h" - -char *input_file_name; -int frame_length=1920, symbol_sz=128, nof_slots=1; - -void usage(char *prog) { - printf("Usage: %s [ls] -i input_file\n", prog); - printf("\t-l frame_length [Default %d]\n", frame_length); - printf("\t-s symbol_sz [Default %d]\n", symbol_sz); - printf("\t-n nof_frames [Default %d]\n", nof_slots); - printf("\t-v [set verbose to debug, default none]\n"); -} - -void parse_args(int argc, char **argv) { - int opt; - while ((opt = getopt(argc, argv, "ilsnv")) != -1) { - switch(opt) { - case 'i': - input_file_name = argv[optind]; - break; - case 'l': - frame_length = atoi(argv[optind]); - break; - case 's': - symbol_sz = atoi(argv[optind]); - break; - case 'n': - nof_slots = atoi(argv[optind]); - break; - case 'v': - verbose++; - break; - default: - usage(argv[0]); - exit(-1); - } - } - if (!input_file_name) { - usage(argv[0]); - exit(-1); - } -} - -void fft_run_slot(dft_plan_t *fft_plan, cf_t *input, cf_t *output) { - int i; - for (i=0;i<7;i++) { - input += CP_NORM(i, symbol_sz); - dft_run_c2c(fft_plan, input, output); - input += symbol_sz; - output += symbol_sz; - } -} - -int main(int argc, char **argv) { - filesource_t fsrc; - pbch_mib_t pbch_data; - pbch_t pbch; - dft_plan_t fft_plan; - - int frame_cnt; - cf_t *input, *outfft; - - if (argc < 3) { - usage(argv[0]); - exit(-1); - } - - parse_args(argc,argv); - - if (filesource_init(&fsrc, input_file_name, COMPLEX_FLOAT)) { - fprintf(stderr, "Error opening file %s\n", input_file_name); - exit(-1); - } - - input = malloc(frame_length*sizeof(cf_t)); - if (!input) { - perror("malloc"); - exit(-1); - } - outfft = malloc(7*symbol_sz*sizeof(cf_t)); - if (!outfft) { - perror("malloc"); - exit(-1); - } - - /* Init FFT plan */ - if (dft_plan_c2c(symbol_sz, FORWARD, &fft_plan)) { - fprintf(stderr, "Error initiating FFT plan\n"); - exit(-1); - } - fft_plan.options = DFT_DC_OFFSET | DFT_MIRROR_POS | DFT_NORMALIZE; - - if (pbch_init(&pbch, 0, CPNORM)) { - fprintf(stderr, "Error initiating PBCH\n"); - exit(-1); - } - int res = 0; - frame_cnt = 0; - while (frame_length == filesource_read(&fsrc, input, frame_length) - && frame_cnt < nof_slots - && res == 0) { - - fft_run_slot(&fft_plan, &input[960], outfft); - - res = pbch_decode(&pbch, outfft, &pbch_data, 6, 1); - if (res == -1) { - fprintf(stderr, "Error decoding PBCH\n"); - break; - } - frame_cnt++; - } - - if (res == 1) { - printf("MIB found\n"); - } else { - printf("MIB not found after %d frames\n", frame_cnt); - } - - pbch_free(&pbch); - free(input); - free(outfft); - - printf("Done\n"); - exit(0); -} diff --git a/examples/cell_search.c b/examples/cell_search.c index e39ee7e58..797b5d4e2 100644 --- a/examples/cell_search.c +++ b/examples/cell_search.c @@ -8,16 +8,18 @@ char *input_file_name = NULL; int nof_slots=100; -float corr_peak_threshold=2.5; -int ntime = 4; -int nfreq = 10; +float corr_peak_threshold=15; int file_binary = 0; int force_N_id_2=-1; +int nof_ports = 1; + + +#define FLEN 9600 filesource_t fsrc; -cf_t *input_buffer, *fft_buffer; +cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS]; pbch_t pbch; -dft_plan_t fft_plan; +lte_fft_t fft; chest_t chest; sync_t synch; @@ -64,29 +66,43 @@ void parse_args(int argc, char **argv) { } int base_init() { + int i; + file_data_type_t type = file_binary?COMPLEX_FLOAT_BIN:COMPLEX_FLOAT; if (filesource_init(&fsrc, input_file_name, type)) { fprintf(stderr, "Error opening file %s\n", input_file_name); exit(-1); } - input_buffer = malloc(4 * 960 * sizeof(cf_t)); + input_buffer = malloc(4 * FLEN * sizeof(cf_t)); if (!input_buffer) { perror("malloc"); exit(-1); } - fft_buffer = malloc(CPNORM_NSYMB * 128 * sizeof(cf_t)); + + fft_buffer = malloc(CPNORM_NSYMB * 72 * sizeof(cf_t)); if (!fft_buffer) { perror("malloc"); return -1; } - /* Init FFT plan */ - if (dft_plan_c2c(128, FORWARD, &fft_plan)) { - fprintf(stderr, "Error initiating FFT plan\n"); + for (i=0;inof_prb, tidx, fidx), + cabsf(channel_ref),cabsf(known_ref),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 treshold */ if (channel_ref != 0) { q->refsignal[port_id][nslot].ch_est[nref] = channel_ref/known_ref; @@ -147,12 +151,11 @@ int chest_init(chest_t *q, lte_cp_t cp, int nof_prb, int nof_ports) { q->nof_ports = nof_ports; q->nof_symbols = CP_NSYMB(cp); - q->symbol_sz = lte_symbol_sz(nof_prb); q->cp = cp; q->nof_prb = nof_prb; - INFO("Initializing channel estimator size %dx%d nof_prb=%d, nof_ports=%d\n", - q->nof_symbols, q->symbol_sz, nof_prb, nof_ports); + INFO("Initializing channel estimator size %dx%d, nof_ports=%d\n", + q->nof_symbols, nof_prb, nof_ports); return 0; } @@ -165,8 +168,6 @@ int chest_ref_LTEDL_slot_port(chest_t *q, int port, int nslot, int cell_id) { return -1; } - INFO("Setting LTE DL reference signals port=%d, nslot=%d, cell_id=%d\n", port, nslot, cell_id); - 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; diff --git a/lib/ch_estimation/src/refsignal.c b/lib/ch_estimation/src/refsignal.c index f79cfe59a..8436f627f 100644 --- a/lib/ch_estimation/src/refsignal.c +++ b/lib/ch_estimation/src/refsignal.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "lte/base.h" #include "ch_estimation/refsignal.h" @@ -110,9 +111,6 @@ int refsignal_init_LTEDL(refsignal_t *q, int port_id, int nslot, memcpy(q->symbols_ref, lp, sizeof(int) * nof_ref_symbols); - DEBUG("Initializing %d CRS for LTE DL slot=%d, %d RE in %d symbols\n", - q->nof_refs, nslot, nof_refs_x_symbol, nof_ref_symbols); - q->refs = vec_malloc(q->nof_refs * sizeof(ref_t)); if (!q->refs) { goto free_and_exit; @@ -127,7 +125,6 @@ int refsignal_init_LTEDL(refsignal_t *q, int port_id, int nslot, 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; } @@ -142,13 +139,13 @@ int refsignal_init_LTEDL(refsignal_t *q, int port_id, int nslot, __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)+GUARD_RE(nof_prb); + q->refs[idx(l,i)].freq_idx = refsignal_k(i, v, cell_id); q->refs[idx(l,i)].time_idx = lp[l]; /* print only first slot */ if (ns == 0) { DEBUG("(%-2d,%2d) is mapped to (%-2d,%2d) (mp=%d, v=%d)\n", - l,i,q->refs[idx(l,i)].time_idx, q->refs[idx(l,i)].freq_idx-GUARD_RE(nof_prb), mp, v); + l,i,q->refs[idx(l,i)].time_idx, q->refs[idx(l,i)].freq_idx, mp, v); } } } diff --git a/lib/lte/src/fft.c b/lib/lte/src/fft.c index 5195140f6..9f6f2f6b3 100644 --- a/lib/lte/src/fft.c +++ b/lib/lte/src/fft.c @@ -15,38 +15,61 @@ * You should have received a copy of the GNU Lesser General Public License * along with OSLD-lib. If not, see . */ +#include #include #include #include "lte/base.h" #include "utils/dft.h" #include "lte/fft.h" +#include "utils/debug.h" -int lte_fft_init_(lte_fft_t *q, lte_cp_t cp_type, int symbol_sz, dft_dir_t dir) { +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); + if (symbol_sz == -1) { + fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); + return -1; + } if (dft_plan_c2c(symbol_sz, dir, &q->fft_plan)) { + 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_DC_OFFSET | DFT_MIRROR_POS | DFT_NORMALIZE; - q->nof_symbols = CP_NSYMB(cp_type); 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); bzero(q, sizeof(lte_fft_t)); } -int lte_fft_init(lte_fft_t *q, lte_cp_t cp_type, int symbol_sz) { - return lte_fft_init_(q, cp_type, symbol_sz, FORWARD); +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); } + void lte_fft_free(lte_fft_t *q) { lte_fft_free_(q); } -int lte_ifft_init(lte_fft_t *q, lte_cp_t cp_type, int symbol_sz) { - return lte_fft_init_(q, cp_type, symbol_sz, BACKWARD); + +int lte_ifft_init(lte_fft_t *q, lte_cp_t cp_type, int nof_prb) { + return lte_fft_init_(q, cp_type, nof_prb, BACKWARD); } + void lte_ifft_free(lte_fft_t *q) { lte_fft_free_(q); } @@ -58,9 +81,10 @@ 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, output); + 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->symbol_sz; + output += q->nof_re; } } diff --git a/lib/lte/src/sequence.c b/lib/lte/src/sequence.c index 7f85006ba..ec1a04a97 100644 --- a/lib/lte/src/sequence.c +++ b/lib/lte/src/sequence.c @@ -19,13 +19,11 @@ #include "lte/sequence.h" #include +#include #include #include #define Nc 1600 -#define GOLDMAXLEN (Nc*10) -static int x1[GOLDMAXLEN]; -static int x2[GOLDMAXLEN]; /* @@ -35,24 +33,37 @@ static int x2[GOLDMAXLEN]; */ void generate_prs_c(sequence_t *q, unsigned int seed) { int n; + unsigned int *x1; + unsigned int *x2; - assert(q->len + Nc + 31 < GOLDMAXLEN); + 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++) { - x1[n] = 0; 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]) & 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) { diff --git a/lib/phch/src/pbch.c b/lib/phch/src/pbch.c index 2ad4e95c8..7c4813f1d 100644 --- a/lib/phch/src/pbch.c +++ b/lib/phch/src/pbch.c @@ -40,39 +40,22 @@ int pbch_cp(cf_t *input, cf_t *output, int nof_prb, lte_cp_t cp, int cell_id, bo if (put) { ptr = input; output += nof_prb * RE_X_RB / 2 - 36; - output += GUARD_RE(nof_prb); } else { ptr = output; input += nof_prb * RE_X_RB / 2 - 36; - input += GUARD_RE(nof_prb); } /* symbol 0 & 1 */ for (i=0;i<2;i++) { phch_cp_prb_ref(&input, &output, cell_id%3, 4, 6, put); - if (put) { - output += 2*GUARD_RE(nof_prb); - } else { - input += 2*GUARD_RE(nof_prb); - } } /* symbols 2 & 3 */ if (CP_ISNORM(cp)) { for (i=0;i<2;i++) { phch_cp_prb(&input, &output, 6); - if (put) { - output += 2*GUARD_RE(nof_prb); - } else { - input += 2*GUARD_RE(nof_prb); - } } } else { phch_cp_prb(&input, &output, 6); - if (put) { - output += 2*GUARD_RE(nof_prb); - } else { - input += 2*GUARD_RE(nof_prb); - } phch_cp_prb_ref(&input, &output, cell_id%3, 4, 6, put); } if (put) { @@ -324,8 +307,9 @@ 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, pbch_mib_t *mib, int nof_prb, float ebno) { - int src, dst, res, nb; +int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t **ce, int nof_ports, + int nof_prb, float ebno, pbch_mib_t *mib) { + int src, dst, res, nb, nant; int nof_symbols = (CP_ISNORM(q->cp)) ? PBCH_RE_CPNORM: PBCH_RE_CPEXT; int nof_bits = 2 * nof_symbols; @@ -337,39 +321,52 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, pbch_mib_t *mib, int nof_prb, fl return -1; } - /* demodulate symbols */ - demod_soft_sigma_set(&q->demod, ebno); - demod_soft_demodulate(&q->demod, q->pbch_symbols, - &q->pbch_llr[nof_bits * q->frame_idx], nof_symbols); - - q->frame_idx++; - - INFO("PBCH: %d frames in buffer\n", q->frame_idx); - - /* 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. - */ - res = 0; - for (nb=0;nbframe_idx && !res;nb++) { - for (dst=0;(dst<4-nb) && !res;dst++) { - for (src=0;srcframe_idx && !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); + /* Try decoding for 1 to nof_ports antennas */ + for (nant=0;nantpbch_symbols[i] /= ce[0][i]; + } + + /* layer demapper */ + //x = lte_pre_decoder_and_matched_filter(y_est, ce(1:n,:), "tx_diversity"); + //d = lte_layer_demapper(x, 1, "tx_diversity"); + + /* demodulate symbols */ + demod_soft_sigma_set(&q->demod, ebno); + demod_soft_demodulate(&q->demod, q->pbch_symbols, + &q->pbch_llr[nof_bits * q->frame_idx], nof_symbols); + + q->frame_idx++; + + INFO("PBCH: %d frames in buffer\n", q->frame_idx); + + /* 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. + */ + res = 0; + for (nb=0;nbframe_idx && !res;nb++) { + for (dst=0;(dst<4-nb) && !res;dst++) { + for (src=0;srcframe_idx && !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); + } } } - } - if (res) { - q->frame_idx = 0; - return 1; - } else { - /* make room for the next packet of radio frame symbols */ - if (q->frame_idx == 4) { - memcpy(&q->pbch_llr[nof_bits], q->pbch_llr, nof_bits * 3 * sizeof(float)); - q->frame_idx = 3; + if (res) { + q->frame_idx = 0; + return 1; } - return 0; } + /* If not found, make room for the next packet of radio frame symbols */ + if (q->frame_idx == 4) { + memcpy(&q->pbch_llr[nof_bits], q->pbch_llr, nof_bits * 3 * sizeof(float)); + q->frame_idx = 3; + } + return 0; } diff --git a/lib/sync/src/sync.c b/lib/sync/src/sync.c index a63b375d2..04c125d3e 100644 --- a/lib/sync/src/sync.c +++ b/lib/sync/src/sync.c @@ -171,7 +171,7 @@ int sync_run(sync_t *q, cf_t *input, int read_offset) { INFO("SSS detected N_id_1=%d, slot_idx=%d, m0=%d, m1=%d\n", q->N_id_1, q->slot_id, m0, m1); - return peak_pos[N_id_2]; + return peak_pos[N_id_2] - 960; } else { return -1; } diff --git a/matlab/sync/find_pss.m b/matlab/sync/find_pss.m index 60f420592..bc16c9a91 100644 --- a/matlab/sync/find_pss.m +++ b/matlab/sync/find_pss.m @@ -14,8 +14,9 @@ function [ fs eps p_m w2] = find_pss( x, N_id_2, doplot, threshold) w2=conv(x,ccf); if (doplot) - plot(10*log10(abs(w2)./mean(abs(w2)))); - axis([0 length(w2) 0 20]) + %plot(10*log10(abs(w2)));%./mean(abs(w2)))); + plot(abs(w2)) + %axis([0 length(w2) 0 20]) end [m i]=max(abs(w2)); fs=i-960;