From afa8cd8424aac67b3c0c925701693b8a2e09c3d0 Mon Sep 17 00:00:00 2001 From: ismagom Date: Thu, 30 Jan 2014 14:45:59 +0000 Subject: [PATCH 1/5] Cell search program working --- examples/cell_search.c | 2 +- examples/equalizer_test.c | 13 +- examples/pss_scan_usrp.c | 331 ++++++++++++++++++++++------------ include/resampling/interp.h | 1 + include/sync/sfo.h | 2 +- include/sync/sync.h | 2 +- lib/ch_estimation/src/chest.c | 6 +- lib/resampling/src/interp.c | 11 ++ lib/sync/src/pss.c | 8 +- lib/sync/src/sfo.c | 16 ++ lib/sync/src/sync.c | 9 +- lib/utils/src/vector.c | 6 +- matlab/common/read_complex.m | 20 ++ matlab/common/write_complex.m | 22 +++ matlab/sync/check_pss.m | 19 +- matlab/sync/find_pss.m | 31 ++-- matlab/sync/ifo_pss.m | 13 ++ matlab/sync/ifo_pss_corr.m | 10 + matlab/sync/sfo_estimate.m | 19 +- uhd/uhd_imp.cpp | 2 +- 20 files changed, 377 insertions(+), 166 deletions(-) create mode 100644 matlab/common/read_complex.m create mode 100644 matlab/common/write_complex.m create mode 100644 matlab/sync/ifo_pss.m create mode 100644 matlab/sync/ifo_pss_corr.m diff --git a/examples/cell_search.c b/examples/cell_search.c index 0df21c6e9..e39ee7e58 100644 --- a/examples/cell_search.c +++ b/examples/cell_search.c @@ -176,7 +176,7 @@ int main(int argc, char **argv) { exit(-1); } - if (sync_init(&synch)) { + if (sync_init(&synch, 960)) { fprintf(stderr, "Error initiating PSS/SSS\n"); exit(-1); } diff --git a/examples/equalizer_test.c b/examples/equalizer_test.c index 2e626ef05..ea99d9b2d 100644 --- a/examples/equalizer_test.c +++ b/examples/equalizer_test.c @@ -85,6 +85,7 @@ int main(int argc, char **argv) { cf_t *input = NULL; cf_t *outfft = NULL; cf_t *ce = NULL; + int i; if (argc < 3) { usage(argv[0]); @@ -135,6 +136,7 @@ int main(int argc, char **argv) { bzero(input, sizeof(cf_t) * in_slot_length()); bzero(outfft, sizeof(cf_t) * slot_length()); + fprintf(f, "ce=zeros(%d, %d);\n", nof_slots * CP_NSYMB(cp), nof_prb * RE_X_RB); /* read all file or nof_slots */ slot_cnt = 0; while (in_slot_length() == filesource_read(&fsrc, input, in_slot_length()) @@ -144,11 +146,12 @@ int main(int argc, char **argv) { chest_ce_slot_port(&eq, outfft, ce, slot_cnt%20, 0); - chest_fprint(&eq, f, slot_cnt%20, 0); + //chest_fprint(&eq, f, slot_cnt%20, 0); - fprintf(f, "ce=["); - vec_fprint_c(f, ce, nof_prb * RE_X_RB * CP_NSYMB(cp)); - fprintf(f, "];\n"); + for (i=0;i rssi_threshold) + + int band, earfcn=-1; -float pss_threshold=15.0; -int earfcn_start, earfcn_end = -1; -float rssi_threshold = -42.0; +float find_threshold = 40.0, track_threshold = 25.0; +int earfcn_start=-1, earfcn_end = -1; +float rssi_threshold = -30.0; +int max_track_lost=9; +int nof_frames_find=8, nof_frames_track=100, nof_samples_rssi=50000; cf_t *input_buffer; float *cfo_v; -int *idx_v; +int *idx_v, *idx_valid, *t; float *p2a_v; void *uhd; int nof_bands; -int force_N_id_2; -float gain = 30.0; +float gain = 20.0; #define MAX_EARFCN 1000 lte_earfcn_t channels[MAX_EARFCN]; @@ -34,45 +43,28 @@ float freqs[MAX_EARFCN]; float cfo[MAX_EARFCN]; float p2a[MAX_EARFCN]; -#define MHZ 1000000 -#define SAMP_FREQ 1920000 -#define RSSI_FS 1000000 -#define RSSI_NSAMP 50000 -#define FLEN 9600 -#define FLEN_PERIOD 0.005 - -#define IS_SIGNAL(i) (10*log10f(rssi[i]) + 30 > rssi_threshold) +enum sync_state {INIT, FIND, TRACK, DONE}; void print_to_matlab(); void usage(char *prog) { - printf("Usage: %s [senvtr] -b band\n", prog); - printf("\t-s earfcn_start [Default %d]\n", earfcn_start); + 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-n number of frames [Default %d]\n", nof_slots); - printf("\t-v [set verbose to debug, default none]\n"); - printf("\t-t pss_threshold [Default %.2f]\n", pss_threshold); + 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 force_N_id_2 [Default no]\n"); - printf("\t-g gain [Default no %.2f dB]\n", gain); + 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-g gain [Default %.2f dB]\n", 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, "gfrtbsenv")) != -1) { + while ((opt = getopt(argc, argv, "bseRrFfTtgv")) != -1) { switch(opt) { - case 'g': - gain = atof(argv[optind]); - break; - case 'f': - force_N_id_2 = atoi(argv[optind]); - break; - case 't': - pss_threshold = atof(argv[optind]); - break; - case 'r': - rssi_threshold = -atof(argv[optind]); - break; case 'b': band = atoi(argv[optind]); break; @@ -82,8 +74,26 @@ void parse_args(int argc, char **argv) { case 'e': earfcn_end = atoi(argv[optind]); break; - case 'n': - nof_slots = atoi(argv[optind]); + 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': + gain = atof(argv[optind]); break; case 'v': verbose++; @@ -103,17 +113,27 @@ int base_init(int frame_length) { exit(-1); } - idx_v = malloc(nof_slots * sizeof(int)); + idx_v = malloc(nof_frames_track * sizeof(int)); if (!idx_v) { perror("malloc"); exit(-1); } - cfo_v = malloc(nof_slots * sizeof(float)); + 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_slots * sizeof(float)); + p2a_v = malloc(nof_frames_track * sizeof(float)); if (!p2a_v) { perror("malloc"); exit(-1); @@ -137,6 +157,8 @@ void base_free() { uhd_close(&uhd); free(input_buffer); free(idx_v); + free(idx_valid); + free(t); free(cfo_v); free(p2a_v); } @@ -158,14 +180,61 @@ float mean_valid(int *idx_v, float *x, int nof_frames) { } } -int main(int argc, char **argv) { - int frame_cnt; +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 max_peak_to_avg) { - max_peak_to_avg = p2a_v[frame_cnt]; - cell_id = sync_get_cell_id(&synch); + DEBUG("Starting receiver...\n",0); + uhd_start_rx_stream(uhd); + + /* init variables */ + frame_cnt = 0; + max_peak_to_avg = -99; + cell_id = -1; + + /* receive first frame */ + uhd_recv(uhd, input_buffer, FLEN, 1); + + /* set find_threshold and go to FIND state */ + sync_set_threshold(&synch, find_threshold); + sync_force_N_id_2(&synch, -1); + state = FIND; + break; + case FIND: + /* find peak in all frame */ + find_idx = sync_run(&synch, input_buffer, FLEN); + DEBUG("[%3d/%d]: PAR=%.2f\n", freq, nof_bands, sync_get_peak_to_avg(&synch)); + if (find_idx != -1) { + /* if found peak, go to track and set lower threshold */ + frame_cnt = -1; + last_found = 0; + sync_set_threshold(&synch, track_threshold); + sync_force_N_id_2(&synch, sync_get_N_id_2(&synch)); + 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(&synch))); + } else { + if (frame_cnt >= 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: + /* TODO: find peak around find_idx */ + idx_v[frame_cnt] = sync_run(&synch, input_buffer, FLEN); + p2a_v[frame_cnt] = sync_get_peak_to_avg(&synch); + + /* 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(&synch); + } + if (idx_v[frame_cnt] != -1) { cfo_v[frame_cnt] = sync_get_cfo(&synch); + last_found = frame_cnt; } else { cfo_v[frame_cnt] = 0.0; } - if (frame_cnt) { - memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t)); + /* if we missed to many frames 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; } - if (VERBOSE_ISINFO()) { - printf("[%4d] - idx: %5d\tpeak-to-avg: %3.2f\tcfo=%.3f\r", frame_cnt, - idx_v[frame_cnt], p2a_v[frame_cnt], cfo_v[frame_cnt]); - } - frame_cnt++; + 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, " + "RSSI %3.2f dBm, 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(rssi[freq]) + 30, + 10*log10f(p2a[freq]), cfo[freq] * 15, sfo / 1000, cell_id); + state = INIT; + freq++; + break; } - - cfo[i] = mean_valid(idx_v, cfo_v, nof_slots); - p2a[i] = sum_r(p2a_v, nof_slots) / nof_slots; - if (channels[i].id == 1900 - || channels[i].id == 1901) { - vec_fprint_i(stdout, idx_v, nof_slots); + if (state == TRACK || (state == FIND && frame_cnt)) { + memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t)); } - - sfo = sfo_estimate(idx_v, nof_slots, FLEN_PERIOD); - if (VERBOSE_ISINFO()) { - printf("\n"); - } - - printf("[%3d/%d]: EARFCN %d Freq. %.2f MHz, " - "RSSI %3.2f dBm, PSS %2.2f dB, CFO=%+2.1f KHz, SFO=%+2.1f KHz, CELL_ID=%3d\n", i, nof_bands, - channels[i].id, channels[i].fd, 10*log10f(rssi[i]) + 30, - 10*log10f(p2a[i]), cfo[i] * 15, sfo / 1000, cell_id); - print_to_matlab(); - - } else { - INFO("[%3d/%d]: EARFCN %d Freq. %.2f MHz. RSSI below threshold (%3.2f < %3.2f dBm)\n", - i, nof_bands, channels[i].id, channels[i].fd, 10*log10f(rssi[i]) + 30, rssi_threshold); + frame_cnt++; } } @@ -285,7 +390,7 @@ int main(int argc, char **argv) { sync_free(&synch); base_free(); - printf("Done\n"); + printf("\n\nDone\n"); exit(0); } diff --git a/include/resampling/interp.h b/include/resampling/interp.h index 9d42e3a1c..207a39573 100644 --- a/include/resampling/interp.h +++ b/include/resampling/interp.h @@ -21,3 +21,4 @@ typedef _Complex float cf_t; void interp_linear_offset(cf_t *input, cf_t *output, int M, int len, int off_st, int off_end); void interp_linear(cf_t *input, cf_t *output, int M, int len); +void interp_linear_f(float *input, float *output, int M, int len); diff --git a/include/sync/sfo.h b/include/sync/sfo.h index a2a45748e..a759184f1 100644 --- a/include/sync/sfo.h +++ b/include/sync/sfo.h @@ -20,6 +20,6 @@ #define SFO_ float sfo_estimate(int *t0, int len, float period); - +float sfo_estimate_period(int *t0, int *t, int len, float period); #endif diff --git a/include/sync/sync.h b/include/sync/sync.h index 59a2c2ad3..c3fc547fb 100644 --- a/include/sync/sync.h +++ b/include/sync/sync.h @@ -49,7 +49,7 @@ int sync_get_N_id_2(sync_t *q); int sync_get_N_id_1(sync_t *q); int sync_get_cell_id(sync_t *q); void sync_set_threshold(sync_t *q, float threshold); -int sync_init(sync_t *q); +int sync_init(sync_t *q, int frame_size); void sync_free(sync_t *q); #endif diff --git a/lib/ch_estimation/src/chest.c b/lib/ch_estimation/src/chest.c index 6f4ac002c..6a9020e3d 100644 --- a/lib/ch_estimation/src/chest.c +++ b/lib/ch_estimation/src/chest.c @@ -81,7 +81,7 @@ void chest_ce_ref(chest_t *q, cf_t *input, int nslot, int port_id, int nref) { q->refsignal[port_id][nslot].refs[nref].recv_simbol = channel_ref; /* FIXME: compare with treshold */ if (channel_ref != 0) { - q->refsignal[port_id][nslot].ch_est[nref] = known_ref/channel_ref; + q->refsignal[port_id][nslot].ch_est[nref] = channel_ref/known_ref; } else { q->refsignal[port_id][nslot].ch_est[nref] = 0; } @@ -118,14 +118,10 @@ void chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, int nslot, int port_i for (i=0;inof_prb * RE_X_RB; i++) { for (j=0;jnsymbols;j++) { x[j] = ce[r->symbols_ref[j] * q->nof_prb * RE_X_RB + i]; - printf("x[%d]=ce[%d]=%.3f\n", j, - r->symbols_ref[j] * q->nof_prb * RE_X_RB + i, - cabsf(x[j])); } interp_linear_offset(x, y, r->symbols_ref[1]-r->symbols_ref[0], 2, r->symbols_ref[0], 3); for (j=0;jnof_symbols;j++) { - printf("ce[%d] = y[%d] =%.3f\n", j * q->nof_prb * RE_X_RB + i, j, cabsf(x[j])); ce[j * q->nof_prb * RE_X_RB + i] = y[j]; } } diff --git a/lib/resampling/src/interp.c b/lib/resampling/src/interp.c index 657c29e4d..392b5e511 100644 --- a/lib/resampling/src/interp.c +++ b/lib/resampling/src/interp.c @@ -57,3 +57,14 @@ void interp_linear_offset(cf_t *input, cf_t *output, int M, int len, int off_st, void interp_linear(cf_t *input, cf_t *output, int M, int len) { interp_linear_offset(input, output, M, len, 0, 0); } + + +/* Performs 1st order integer linear interpolation */ +void interp_linear_f(float *input, float *output, int M, int len) { + int i, j; + for (i=0;i. */ +#include +#include #include "sync/sfo.h" /* Estimate SFO based on the array of time estimates t0 @@ -29,3 +31,17 @@ float sfo_estimate(int *t0, int len, float period) { } return sfo; } + +/* Same as sfo_estimate but period is non-uniform. + * Vector t is the sampling time times period for each t0 + */ +float sfo_estimate_period(int *t0, int *t, int len, float period) { + int i; + float sfo=0.0; + for (i=1;ipss_mode = PEAK_MEAN; for (N_id_2=0;N_id_2<3;N_id_2++) { - if (pss_synch_init(&q->pss[N_id_2], 960)) { + if (pss_synch_init(&q->pss[N_id_2], frame_size)) { fprintf(stderr, "Error initializing PSS object\n"); return -1; } @@ -153,10 +153,11 @@ int sync_run(sync_t *q, cf_t *input, int read_offset) { } if (peak_detected) { - INFO("PSS peak detected N_id_2=%d, pos=%d value=%.2f\n", N_id_2, peak_pos[N_id_2], peak_value[N_id_2]); q->cfo = pss_synch_cfo_compute(&q->pss[N_id_2], &input[read_offset + peak_pos[N_id_2]-128]); - INFO("Estimated CFO=%.4f\n", q->cfo); + + 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); sss_idx = read_offset + peak_pos[N_id_2]-2*(128+CP(128,CPNORM_LEN)); if (sss_idx>= 0) { diff --git a/lib/utils/src/vector.c b/lib/utils/src/vector.c index 1882cac45..1336173f5 100644 --- a/lib/utils/src/vector.c +++ b/lib/utils/src/vector.c @@ -117,7 +117,7 @@ void vec_fprint_c(FILE *stream, _Complex float *x, int len) { //if (!((i+1)%10)) // fprintf(stream, "\n"); } - fprintf(stream, "]\n"); + fprintf(stream, "];\n"); } void vec_fprint_f(FILE *stream, float *x, int len) { @@ -128,7 +128,7 @@ void vec_fprint_f(FILE *stream, float *x, int len) { //if (!((i+1)%10)) // fprintf(stream, "\n"); } - fprintf(stream, "]\n"); + fprintf(stream, "];\n"); } @@ -138,7 +138,7 @@ void vec_fprint_i(FILE *stream, int *x, int len) { for (i=0;i 0) axis([0 nf -0.5 0.5]) end subplot(1,3,3) plot(m_p) -fprintf('pss_mean=%g, pss_var=%g, cp_mean=%g, cp_var=%g m_p=%g sfo=%g Hz\n',mean(cfo),var(cfo), mean(cfo2), var(cfo2), mean(m_p), sfo) +fprintf('cfo_mean=%g Hz, cfo_std=%g Hz, m_p=%g sfo=%g Hz\n',15000*nanmean(cfo),15000*nanstd(cfo), nanmean(m_p), sfo) end diff --git a/matlab/sync/find_pss.m b/matlab/sync/find_pss.m index 8ed366e1b..60f420592 100644 --- a/matlab/sync/find_pss.m +++ b/matlab/sync/find_pss.m @@ -1,6 +1,10 @@ -function [ fs eps p_m w2] = find_pss( x, N_id_2, doplot) +function [ fs eps p_m w2] = find_pss( x, N_id_2, doplot, threshold) if nargin == 2 doplot = false; + threshold = 0; + end + if nargin == 3 + threshold = 0; end c=lte_pss_zc(N_id_2); @@ -10,26 +14,29 @@ function [ fs eps p_m w2] = find_pss( x, N_id_2, doplot) w2=conv(x,ccf); if (doplot) - plot(abs(w2)) + plot(10*log10(abs(w2)./mean(abs(w2)))); + axis([0 length(w2) 0 20]) end [m i]=max(abs(w2)); fs=i-960; p_m = m/mean(abs(w2)); + if doplot fprintf('Frame starts at %d, m=%g, p=%g, p/m=%g dB\n',fs, ... mean(abs(w2)), m, 10*log10(m/mean(abs(w2)))); end % Estimate PSS-aided CFO -% if (i - 129) -% y=ccf.*x(i-128:i-1); -% -% y0=y(1:64); -% y1=y(65:length(y)); -% -% eps=angle(conj(sum(y0))*sum(y1))/pi; -% else - eps = NaN; -% end + if (i > 200 && i threshold) + y=ccf.*x(i-128:i-1); + + y0=y(1:64); + y1=y(65:length(y)); + + eps=angle(conj(sum(y0))*sum(y1))/pi; + else + eps = NaN; + fs = NaN; + end end diff --git a/matlab/sync/ifo_pss.m b/matlab/sync/ifo_pss.m new file mode 100644 index 000000000..739cbe1a7 --- /dev/null +++ b/matlab/sync/ifo_pss.m @@ -0,0 +1,13 @@ +function [ ifo ] = ifo_pss( r_pss, x_pss) + +k=1; +v=-31:31; +c=zeros(length(v),1); +for i=v + c(k) = ifo_pss_corr(i, r_pss, x_pss); + k=k+1; +end +[m i]=max(c); +ifo=v(i); +plot(v,c); + diff --git a/matlab/sync/ifo_pss_corr.m b/matlab/sync/ifo_pss_corr.m new file mode 100644 index 000000000..c921cba9c --- /dev/null +++ b/matlab/sync/ifo_pss_corr.m @@ -0,0 +1,10 @@ +function [ corr ] = ifo_pss_corr( n, r_pss, x_pss) + + x=0; + for i=1:length(x_pss) + x=x+r_pss(1+mod(i+n-1,length(r_pss)))*conj(x_pss(i)); + end + corr=real(exp(1i*2*pi*9*n/128)*x); +% corr=abs(x); +end + diff --git a/matlab/sync/sfo_estimate.m b/matlab/sync/sfo_estimate.m index d9f46690f..f0160a868 100644 --- a/matlab/sync/sfo_estimate.m +++ b/matlab/sync/sfo_estimate.m @@ -1,7 +1,18 @@ -function [ sfo ] = sfo_estimate( fs, T ) +function [ sfo sfo_v ] = sfo_estimate( fs, T ) -sfo = 0; -for i=2:length(fs) - sfo=sfo + (fs(i)-fs(i-1))/length(fs)/T; + +nanfs=fs(~isnan(fs)); +idx=find(~isnan(fs)); +sfo_v = zeros(length(nanfs)-1,1); +for i=2:length(nanfs) + if (abs(nanfs(i)-nanfs(i-1))<9000) + sfo_v(i-1)=(nanfs(i)-nanfs(i-1))/T/(idx(i)-idx(i-1)); + else + sfo_v(i-1)=sfo_v(i-2); + end end +sfo = mean(sfo_v); + + + diff --git a/uhd/uhd_imp.cpp b/uhd/uhd_imp.cpp index 69d285b7c..1fa66766d 100644 --- a/uhd/uhd_imp.cpp +++ b/uhd/uhd_imp.cpp @@ -70,7 +70,7 @@ int uhd_open(char *args, void **h) { std::string _args=std::string(args); handler->usrp = uhd::usrp::multi_usrp::make(_args); - uhd::msg::register_handler(&my_handler); + //uhd::msg::register_handler(&my_handler); std::string otw, cpu; otw="sc16"; From c328a29e392d4abe66bc6aff8dc5e3d50128af05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ismael=20G=C3=B3mez-Miguelez?= Date: Thu, 30 Jan 2014 15:14:41 +0000 Subject: [PATCH 2/5] Update README.md --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/README.md b/README.md index 245ccaac8..961334bf3 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,56 @@ libLTE libLTE is a free and open-source LTE library for SDR UE and eNodeB. The library does not rely on any external dependencies or frameworks. +The license is LGPLv3. The project contains a set of Python tools for the automatic code generation of modules for popular SDR frameworks, including GNURadio, ALOE++, IRIS, and OSSIE. These tools are easy to use and adapt for generating targets for specific platforms or frameworks. +Download & Install Instructions +================================= + +``` +git clone https://github.com/ismagom/libLTE.git +cd libLTE +mkdir build +cd build +cmake ../ +make +sudo make install +``` + +Cell Search Example +==================== + +This program uses any hardware supported by the UHD driver to scan an LTE band for active cells. See http://niviuk.free.fr/lte_band.php for a list of available bands. The program first obtains a power spectral density of the entire band. For all frequencies with an RSSI higher than a threshold, it tries to find the LTE Primary Synchronization Signal (PSS) and then identifies the CELL ID using the Secondary Synchronization Signal (SSS). Finally, it estimates the Carrier Frequency Offset (CFO) and Sampling Frequency Offset (SFO). + +For instance, the command: + +``` pss_scan_usrp -b 3 ``` + + +Scans the LTE band 3 (1805 to 1880 MHz). Note that you need a hardware supporting these frequencies (e.g. SBX daughterboard for USRP). The program outputs the following: + +``` +Opening UHD device... +-- Opening a USRP2/N-Series device... +-- Current recv frame size: 1472 bytes +-- Current send frame size: 1472 bytes +RSSI scan: 749 freqs in band 3, RSSI threshold -30.00 dBm +Freq 1879.0 Mhz - RSSI: -43.96 dBm +Done. Starting PSS search on 75 channels + +UHD Warning: + The hardware does not support the requested RX sample rate: + Target sample rate: 1.920000 MSps + Actual sample rate: 1.923077 MSps +[199/749]: EARFCN 1399 Freq. 1824.90 MHz No PSS found +[200/749]: FOUND EARFCN 1400 Freq. 1825.00 MHz, RSSI -22.43 dBm, PAR 15.86 dB, CFO=-0.25 KHz, SFO=+3.099 KHz, CELL_ID=150 +[433/749]: EARFCN 1633 Freq. 1848.30 MHz No PSS found + +Done +``` + +indicating that a Cell with ID 150 has been found at 1825.0 MHz. PAR indicates the peak-to-average ratio (in dB) at the output of the PSS correlator. + +For more command arguments, type ``` pss_scan_usrp --help ``` + From 467c970fc917d901b7d15d77eb348df144c2eb17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ismael=20G=C3=B3mez-Miguelez?= Date: Thu, 30 Jan 2014 16:09:41 +0000 Subject: [PATCH 3/5] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 961334bf3..539310895 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,12 @@ The license is LGPLv3. The project contains a set of Python tools for the automatic code generation of modules for popular SDR frameworks, including GNURadio, ALOE++, IRIS, and OSSIE. These tools are easy to use and adapt for generating targets for specific platforms or frameworks. +Support +======== + +Mailing list: https://lists.sourceforge.net/lists/listinfo/liblte-users + + Download & Install Instructions ================================= From 893cab84f1e9f44e8a3826efa96163ce386f6caa Mon Sep 17 00:00:00 2001 From: ismagom Date: Fri, 31 Jan 2014 14:35:43 +0000 Subject: [PATCH 4/5] Fixed PRS sequence generation --- examples/CMakeLists.txt | 3 - examples/bch_test.c | 130 ------------------------------ examples/cell_search.c | 107 +++++++++++++----------- examples/equalizer_test.c | 14 +++- include/ch_estimation/chest.h | 1 - include/lte/base.h | 2 +- include/lte/fft.h | 7 +- include/phch/pbch.h | 2 +- lib/ch_estimation/src/chest.c | 13 +-- lib/ch_estimation/src/refsignal.c | 9 +-- lib/lte/src/fft.c | 42 +++++++--- lib/lte/src/sequence.c | 23 ++++-- lib/phch/src/pbch.c | 87 ++++++++++---------- lib/sync/src/sync.c | 2 +- matlab/sync/find_pss.m | 5 +- 15 files changed, 182 insertions(+), 265 deletions(-) delete mode 100644 examples/bch_test.c 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 (dft_plan_c2c(symbol_sz, dir, &q->fft_plan)) { + 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); + /* Try decoding for 1 to nof_ports antennas */ + for (nant=0;nantframe_idx++; + /* pre-decoder & matched filter */ + int i; + for (i=0;ipbch_symbols[i] /= ce[0][i]; + } - INFO("PBCH: %d frames in buffer\n", q->frame_idx); + /* layer demapper */ + //x = lte_pre_decoder_and_matched_filter(y_est, ce(1:n,:), "tx_diversity"); + //d = lte_layer_demapper(x, 1, "tx_diversity"); - /* 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); + /* 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; From a07f3966a359466eb20a4abef1c7869e072ea3a5 Mon Sep 17 00:00:00 2001 From: ismagom Date: Mon, 3 Feb 2014 20:34:28 +0100 Subject: [PATCH 5/5] Issue1 fixed --- examples/cell_search.c | 1 + examples/pss_scan_usrp.c | 77 ++++++++++++++++++++++++++-------------- include/sync/pss.h | 2 +- lib/sync/src/sync.c | 10 +++--- uhd/uhd_utils.c | 26 ++++++++------ 5 files changed, 73 insertions(+), 43 deletions(-) diff --git a/examples/cell_search.c b/examples/cell_search.c index 797b5d4e2..cff0a0369 100644 --- a/examples/cell_search.c +++ b/examples/cell_search.c @@ -221,6 +221,7 @@ int main(int argc, char **argv) { INFO("State Sync, Slot idx=%d\n", frame_idx); idx = sync_run(&synch, input_buffer, read_offset); if (idx != -1) { + idx -= 960; slot_start = read_offset + idx; read_length = idx; read_offset += FLEN; diff --git a/examples/pss_scan_usrp.c b/examples/pss_scan_usrp.c index ca4fc26bf..c7f1fef8e 100644 --- a/examples/pss_scan_usrp.c +++ b/examples/pss_scan_usrp.c @@ -18,15 +18,18 @@ #define FLEN 9600 #define FLEN_PERIOD 0.005 +#define RSSI_DECIM 20 + #define IS_SIGNAL(i) (10*log10f(rssi[i]) + 30 > rssi_threshold) int band, earfcn=-1; -float find_threshold = 40.0, track_threshold = 25.0; +float find_threshold = 40.0, track_threshold = 8.0; int earfcn_start=-1, earfcn_end = -1; float rssi_threshold = -30.0; int max_track_lost=9; int nof_frames_find=8, nof_frames_track=100, nof_samples_rssi=50000; +int track_len=500; cf_t *input_buffer; float *cfo_v; @@ -39,6 +42,7 @@ float gain = 20.0; #define MAX_EARFCN 1000 lte_earfcn_t channels[MAX_EARFCN]; float rssi[MAX_EARFCN]; +float rssi_d[MAX_EARFCN/RSSI_DECIM]; float freqs[MAX_EARFCN]; float cfo[MAX_EARFCN]; float p2a[MAX_EARFCN]; @@ -57,6 +61,7 @@ void usage(char *prog) { 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", gain); printf("\t-v [set verbose to debug, default none]\n"); } @@ -196,11 +201,10 @@ int preprocess_idx(int *in, int *out, int *period, int len) { int rssi_scan() { int n=0; int i; - float rssi_d[MAX_EARFCN/10]; if (nof_bands > 100) { /* scan every Mhz, that is 10 freqs */ - for (i=0;i= nof_frames_find) { state = INIT; @@ -337,22 +349,28 @@ int main(int argc, char **argv) { } break; case TRACK: - /* TODO: find peak around find_idx */ - idx_v[frame_cnt] = sync_run(&synch, input_buffer, FLEN); - p2a_v[frame_cnt] = sync_get_peak_to_avg(&synch); + 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(&synch); + cell_id = sync_get_cell_id(&strack); } - if (idx_v[frame_cnt] != -1) { - cfo_v[frame_cnt] = sync_get_cfo(&synch); + 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 frames it is not a cell, next freq */ + /* 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); @@ -370,9 +388,9 @@ int main(int argc, char **argv) { 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, " - "RSSI %3.2f dBm, 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(rssi[freq]) + 30, + 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++; @@ -387,7 +405,7 @@ int main(int argc, char **argv) { print_to_matlab(); - sync_free(&synch); + sync_free(&sfind); base_free(); printf("\n\nDone\n"); @@ -414,6 +432,13 @@ void print_to_matlab() { } fprintf(f, "];\n"); + + fprintf(f, "rssi_d=["); + for (i=0;ithreshold); - 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) { + if (peak_pos[N_id_2] + read_offset > 128) { if (q->pss_mode == ABSOLUTE) { if (peak_value[N_id_2] > q->threshold) { peak_detected = 1; @@ -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] - 960; + return peak_pos[N_id_2]; } else { return -1; } diff --git a/uhd/uhd_utils.c b/uhd/uhd_utils.c index 173164cb5..b33eb344b 100644 --- a/uhd/uhd_utils.c +++ b/uhd/uhd_utils.c @@ -5,9 +5,10 @@ #include "uhd.h" #include "utils/vector.h" +#include "utils/debug.h" int uhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs, int nsamp) { - int i; + int i, j; int ret = -1; _Complex float *buffer; double f; @@ -21,22 +22,25 @@ int uhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs uhd_set_rx_srate(uhd, fs); for (i=0;i