diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d09f0101c..ee0100143 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -42,5 +42,9 @@ add_executable(pss_scan_usrp pss_scan_usrp.c ../uhd/uhd_imp.cpp ../uhd/uhd_utils target_link_libraries(pss_scan_usrp ${LIBRARIES} ${UHD_LIBRARIES}) +include_directories(${UHD_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../uhd) +add_executable(mib_scan_usrp mib_scan_usrp.c ../uhd/uhd_imp.cpp ../uhd/uhd_utils.c) +target_link_libraries(mib_scan_usrp ${LIBRARIES} ${UHD_LIBRARIES}) + diff --git a/examples/cell_search.c b/examples/cell_search.c index cff0a0369..e8f30f609 100644 --- a/examples/cell_search.c +++ b/examples/cell_search.c @@ -8,7 +8,7 @@ char *input_file_name = NULL; int nof_slots=100; -float corr_peak_threshold=15; +float corr_peak_threshold=30; int file_binary = 0; int force_N_id_2=-1; int nof_ports = 1; @@ -94,7 +94,7 @@ int base_init() { } } - if (chest_init(&chest, CPNORM, 6, 1)) { + if (chest_init(&chest, LINEAR, CPNORM, 6, 1)) { fprintf(stderr, "Error initializing equalizer\n"); return -1; } diff --git a/examples/equalizer_test.c b/examples/equalizer_test.c index ff685fc03..cd37ecdd3 100644 --- a/examples/equalizer_test.c +++ b/examples/equalizer_test.c @@ -124,7 +124,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error: initializing FFT\n"); goto do_exit; } - if (chest_init(&eq, cp, nof_prb, 1)) { + if (chest_init(&eq, LINEAR, cp, nof_prb, 1)) { fprintf(stderr, "Error initializing equalizer\n"); goto do_exit; } diff --git a/examples/mib_scan_usrp.c b/examples/mib_scan_usrp.c new file mode 100644 index 000000000..15805a1d8 --- /dev/null +++ b/examples/mib_scan_usrp.c @@ -0,0 +1,592 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lte.h" + +#define DISABLE_UHD + +#ifndef DISABLE_UHD +#include "uhd.h" +#include "uhd_utils.h" +#endif + +#define MHZ 1000000 +#define SAMP_FREQ 1920000 +#define RSSI_FS 1000000 +#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 = 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; +int nof_ports; + +cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS]; +pbch_t pbch; +lte_fft_t fft; +chest_t chest; +sync_t sfind, strack; + +float *cfo_v; +int *idx_v, *idx_valid, *t; +float *p2a_v; +void *uhd; +int nof_bands; +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]; + +enum sync_state {INIT, FIND, TRACK, MIB, 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", 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': + 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 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= 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) { + state = MIB; + nslot=(nslot+10)%20; + } + break; + case MIB: + INFO("Finding MIB at freq %.2f Mhz\n", channels[freq].fd); + 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); + + // TODO: Correct SFO + + // Correct CFO + INFO("Correcting CFO=%.4f\n", cfo[freq]); + nco_cexp_f_direct(&input_buffer[FLEN], -cfo[freq]/128, FLEN); + + if (nslot == 10) { + if (mib_decoder_run(&input_buffer[FLEN+find_idx+FLEN/10], &mib)) { + INFO("MIB detected attempt=%d\n", mib_attempts); + state = DONE; + } else { + INFO("MIB not detected attempt=%d\n", mib_attempts); + if (mib_attempts >= 20) { + freq++; + state = INIT; + } + } + mib_attempts++; + } else { + 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 && frame_cnt)) { + memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t)); + } + frame_cnt++; + } + } + + print_to_matlab(); + + 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 -typedef enum { - CONVCODER_27, CONVCODER_29, CONVCODER_37, CONVCODER_39 -}viterbi_type_t; - -typedef struct { - void *ptr; - int R; - int K; - unsigned int framebits; - bool tail_biting; - int poly[3]; - int (*decode) (void*, float*, char*); - void (*free) (void*); -}viterbi_t; -int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int framebits, bool tail_bitting); -void viterbi_free(viterbi_t *q); -int viterbi_decode(viterbi_t *q, float *symbols, char *data); typedef struct { int R; @@ -49,6 +31,29 @@ typedef struct { bool tail_biting; }convcoder_t; -int conv_encode(convcoder_t *q, char *input, char *output); +int convcoder_encode(convcoder_t *q, char *input, char *output); + + +/* High-level API */ +typedef struct { + convcoder_t obj; + struct convcoder_ctrl_in { + int rate; + int constraint_length; + int tail_bitting; + int generator_0; + int generator_1; + int generator_2; + int frame_length; + } ctrl_in; + char *input; + int in_len; + char *output; + int out_len; +}convcoder_hl; + +int convcoder_initialize(convcoder_hl* h); +int convcoder_work(convcoder_hl* hl); +int convcoder_stop(convcoder_hl* h); #endif diff --git a/include/fec/viterbi.h b/include/fec/viterbi.h new file mode 100644 index 000000000..63d192488 --- /dev/null +++ b/include/fec/viterbi.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013, Ismael Gomez-Miguelez . + * This file is part of OSLD-lib (http://https://github.com/ismagom/osld-lib) + * + * OSLD-lib is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OSLD-lib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OSLD-lib. If not, see . + */ + +#ifndef VITERBI_ +#define VITERBI_ + +#include + +typedef enum { + viterbi_27, viterbi_29, viterbi_37, viterbi_39 +}viterbi_type_t; + +typedef struct { + void *ptr; + int R; + int K; + unsigned int framebits; + bool tail_biting; + int poly[3]; + int (*decode) (void*, float*, char*); + void (*free) (void*); +}viterbi_t; + +int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int framebits, bool tail_bitting); +void viterbi_free(viterbi_t *q); +int viterbi_decode(viterbi_t *q, float *symbols, char *data); + + +/* High-level API */ +typedef struct { + viterbi_t obj; + struct viterbi_init { + int rate; + int constraint_length; + int tail_bitting; + int generator_0; + int generator_1; + int generator_2; + int frame_length; + } init; + float *input; + int in_len; + char *output; + int out_len; +}viterbi_hl; + +int viterbi_initialize(viterbi_hl* h); +int viterbi_work(viterbi_hl* hl); +int viterbi_stop(viterbi_hl* h); + +#endif diff --git a/include/io/binsource.h b/include/io/binsource.h index fa7e7c2b6..eb926cfb1 100644 --- a/include/io/binsource.h +++ b/include/io/binsource.h @@ -50,7 +50,7 @@ typedef struct { int nbits; // Number of bits to generate } ctrl_in; char* output; - int* out_len; + int out_len; }binsource_hl; int binsource_initialize(binsource_hl* h); diff --git a/include/io/filesource.h b/include/io/filesource.h index 0defaefdd..c574da05c 100644 --- a/include/io/filesource.h +++ b/include/io/filesource.h @@ -48,7 +48,7 @@ typedef struct { int nsamples; // Number of samples to read } ctrl_in; void* output; - int* out_len; + int out_len; }filesource_hl; int filesource_initialize(filesource_hl* h); diff --git a/include/lte.h b/include/lte.h index 4e576303a..5870022ab 100644 --- a/include/lte.h +++ b/include/lte.h @@ -41,6 +41,7 @@ #include "channel/ch_awgn.h" +#include "fec/viterbi.h" #include "fec/convcoder.h" #include "fec/crc.h" diff --git a/include/modem/demod_hard.h b/include/modem/demod_hard.h index 197059800..2d0ab7238 100644 --- a/include/modem/demod_hard.h +++ b/include/modem/demod_hard.h @@ -48,11 +48,12 @@ typedef struct { int in_len; char* output; - int *out_len; + int out_len; }demod_hard_hl; int demod_hard_initialize(demod_hard_hl* hl); int demod_hard_work(demod_hard_hl* hl); +int demod_hard_stop(demod_hard_hl* hl); #endif diff --git a/include/modem/demod_soft.h b/include/modem/demod_soft.h index ecc200dee..917b432ae 100644 --- a/include/modem/demod_soft.h +++ b/include/modem/demod_soft.h @@ -57,7 +57,7 @@ typedef struct { }ctrl_in; float* output; - int *out_len; + int out_len; }demod_soft_hl; diff --git a/include/modem/mod.h b/include/modem/mod.h index 6b63dc7a6..198153b50 100644 --- a/include/modem/mod.h +++ b/include/modem/mod.h @@ -39,7 +39,7 @@ typedef struct { int in_len; cf* output; - int *out_len; + int out_len; }mod_hl; int mod_initialize(mod_hl* hl); diff --git a/include/phch/pbch.h b/include/phch/pbch.h index 497fa26ac..97b4b00d8 100644 --- a/include/phch/pbch.h +++ b/include/phch/pbch.h @@ -25,6 +25,7 @@ #include "scrambling/scrambling.h" #include "ratematching/rm_conv.h" #include "fec/convcoder.h" +#include "fec/viterbi.h" #include "fec/crc.h" #define PBCH_RE_CPNORM 240 diff --git a/include/ratematching/rm_conv.h b/include/ratematching/rm_conv.h index 2d9278a07..d71f24adc 100644 --- a/include/ratematching/rm_conv.h +++ b/include/ratematching/rm_conv.h @@ -36,7 +36,7 @@ typedef struct { int S; } ctrl_in; void *output; - int *out_len; + int out_len; }rm_conv_hl; int rm_conv_initialize(rm_conv_hl* h); diff --git a/include/scrambling/scrambling.h b/include/scrambling/scrambling.h index f934de948..b5990f030 100644 --- a/include/scrambling/scrambling.h +++ b/include/scrambling/scrambling.h @@ -59,7 +59,7 @@ typedef struct { int subframe; } ctrl_in; void *output; - int *out_len; + int out_len; }scrambling_hl; #endif diff --git a/include/sync/pss.h b/include/sync/pss.h index 67b3a8554..f1ce7b7b5 100644 --- a/include/sync/pss.h +++ b/include/sync/pss.h @@ -114,7 +114,7 @@ typedef struct { float manual_cfo; } ctrl_in; cf_t *output; - int *out_len; + int out_len; }pss_synch_hl; #define DEFAULT_FRAME_SIZE 2048 diff --git a/include/utils/vector.h b/include/utils/vector.h index a236fcaf0..475937fab 100644 --- a/include/utils/vector.h +++ b/include/utils/vector.h @@ -21,24 +21,42 @@ #include -int sum_i(int *x, int len); -float sum_r(float *x, int len); -_Complex float sum_c(_Complex float *x, int len); +typedef _Complex float cf_t; + +/** Return the sum of all the elements */ +int vec_acc_ii(int *x, int len); +float vec_acc_ff(float *x, int len); +cf_t vec_acc_cc(cf_t *x, int len); void *vec_malloc(int size); -void vec_fprint_c(FILE *stream, _Complex float *x, int len); + +/* print vectors */ +void vec_fprint_c(FILE *stream, cf_t *x, int len); void vec_fprint_f(FILE *stream, float *x, int len); void vec_fprint_i(FILE *stream, int *x, int len); +/* sum two vectors */ void vec_sum_ch(char *z, char *x, char *y, int len); -void vec_sum_c(_Complex float *z, _Complex float *x, _Complex float *y, int len); -void vec_mult_c_r(_Complex float *x,_Complex float *y, float h, int len); -void vec_mult_c(_Complex float *x,_Complex float *y, _Complex float h, int len); -void vec_conj(_Complex float *x, _Complex float *y, int len); -float vec_power(_Complex float *x, int len); -void vec_dot_prod(_Complex float *x,_Complex float *y, _Complex float *z, int len); -void vec_dot_prod_u(_Complex float *x,_Complex float *y, _Complex float *z, int len); -void vec_max(float *x, float *max, int *pos, int len); -void vec_abs(_Complex float *x, float *abs, int len); +void vec_sum_ccc(cf_t *z, cf_t *x, cf_t *y, int len); + +/* scalar product */ +void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, int len); +void vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, int len); + +/* dot product */ +void vec_dot_prod_ccc(cf_t *x, cf_t *y, cf_t *z, int len); +void vec_dot_prod_ccc_unalign(cf_t *x, cf_t *y, cf_t *z, int len); + +/* conjugate */ +void vec_conj_cc(cf_t *x, cf_t *y, int len); + +/* average vector power */ +float vec_avg_power_cf(cf_t *x, int len); + +/* return the index of the maximum value in the vector */ +int vec_max_fi(float *x, int len); + +/* magnitude of each vector element */ +void vec_abs_cf(cf_t *x, float *abs, int len); #endif diff --git a/lib/ch_estimation/src/chest.c b/lib/ch_estimation/src/chest.c index 0e71f2b24..f2cd2e57a 100644 --- a/lib/ch_estimation/src/chest.c +++ b/lib/ch_estimation/src/chest.c @@ -80,8 +80,8 @@ void chest_ce_ref(chest_t *q, cf_t *input, int nslot, int port_id, int nref) { channel_ref = input[SAMPLE_IDX(q->nof_prb, tidx, fidx)]; q->refsignal[port_id][nslot].refs[nref].recv_simbol = channel_ref; - DEBUG("Reference %d pos (%d,%d)=%d %.2f/%.2f=%.2f %.2f/%.2f=%.2f\n", nref, tidx, fidx, SAMPLE_IDX(q->nof_prb, tidx, fidx), - cabsf(channel_ref),cabsf(known_ref),cabsf(channel_ref/known_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 treshold */ if (channel_ref != 0) { @@ -141,7 +141,7 @@ void chest_ce_slot(chest_t *q, cf_t *input, cf_t **ce, int nslot) { } } -int chest_init(chest_t *q, lte_cp_t cp, int nof_prb, int nof_ports) { +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); @@ -154,6 +154,11 @@ int chest_init(chest_t *q, lte_cp_t cp, int nof_prb, int nof_ports) { q->cp = cp; q->nof_prb = nof_prb; + 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); @@ -222,50 +227,45 @@ int chest_ref_symbols(chest_t *q, int port_id, int nslot, int l[2]) { */ int chest_initialize(chest_hl* h) { - if (!h->init.ntime) { - h->init.ntime = 7; - } - if (!h->init.nfreq) { - h->init.nfreq = 10; - } if (!h->init.nof_symbols) { h->init.nof_symbols = CPNORM_NSYMB; // Normal CP } - if (!h->init.port_id) { - h->init.port_id = 0; - } - if (!h->init.cell_id) { - h->init.cell_id = 0; - } if (!h->init.nof_prb) { h->init.nof_prb = 6; } -/* if (chest_LTEDL_init(&h->obj, h->init.ntime, h->init.nfreq, - h->init.nof_symbols==CPNORM_NSYMB, h->init.cell_id, h->init.nof_prb)) { + 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 can be called in a subframe (1ms) or slot basis (0.5ms) for LTE */ +/** 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->in_len == SF_SZ(q)) { - *hl->out_len = chest_LTEDL_run_sf(q, hl->input, hl->output, hl->ctrl_in.slot_id/2); - } else if (hl->in_len == SLOT_SZ(q)) { - *hl->out_len = chest_LTEDL_run_slot(q, hl->input, hl->output, hl->ctrl_in.slot_id); - } - */ - if (*hl->out_len < 0) { - return -1; - } else { - return 0; + 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) { diff --git a/lib/channel/src/ch_awgn.c b/lib/channel/src/ch_awgn.c index 7509c8b21..003e6e3a7 100644 --- a/lib/channel/src/ch_awgn.c +++ b/lib/channel/src/ch_awgn.c @@ -43,8 +43,10 @@ int ch_awgn_initialize(ch_awgn_hl* hl) { int ch_awgn_work(ch_awgn_hl* hl) { ch_awgn(hl->input,hl->output,hl->ctrl_in.variance,hl->in_len); - if (hl->out_len) { - *hl->out_len = hl->in_len; - } + hl->out_len = hl->in_len; + return 0; +} + +int ch_awgn_stop(ch_awgn_hl* hl) { return 0; } diff --git a/lib/fec/src/convcoder.c b/lib/fec/src/convcoder.c index ddc992ca9..ce60e7b45 100644 --- a/lib/fec/src/convcoder.c +++ b/lib/fec/src/convcoder.c @@ -16,85 +16,14 @@ * along with OSLD-lib. If not, see . */ -/**@TODO frontend to FEC library if installed - */ #include #include #include #include "fec/convcoder.h" #include "parity.h" -#include "viterbi37.h" - -#define DEB 0 - -int decode37(void *o, float *symbols, char *data) { - viterbi_t *q = o; - int i; - int len = q->tail_biting ? q->framebits : (q->framebits + q->K - 1); - float amp = 0; - - for (i=0;i<3*len;i++) { - if (fabsf(symbols[i] > amp)) { - amp = symbols[i]; - } - } - - /* Decode it and make sure we get the right answer */ - /* Initialize Viterbi decoder */ - init_viterbi37_port(q->ptr, q->tail_biting?-1:0); - - /* Decode block */ - update_viterbi37_blk_port(q->ptr, symbols,q->framebits + q->K - 1, amp, len); - - /* Do Viterbi chainback */ - chainback_viterbi37_port(q->ptr, data, q->framebits, 0); - - return q->framebits; -} - -void free37(void *o) { - viterbi_t *q = o; - delete_viterbi37_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; - - if ((q->ptr = create_viterbi37_port(poly, framebits, tail_biting)) == NULL) { - fprintf(stderr, "create_viterbi37 failed\n"); - return -1; - } else { - return 0; - } -} - -int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int framebits, bool tail_bitting) { - switch(type) { - case CONVCODER_37: - return init37(q, poly, framebits, tail_bitting); - default: - fprintf(stderr, "Decoder not implemented\n"); - return -1; - } -} - -void viterbi_free(viterbi_t *q) { - q->free(q); -} - -/* symbols are real-valued */ -int viterbi_decode(viterbi_t *q, float *symbols, char *data) { - return q->decode(q, symbols, data); -} - -int conv_encode(convcoder_t *q, char *input, char *output) { +int convcoder_encode(convcoder_t *q, char *input, char *output) { unsigned int sr; int i,j; int len = q->tail_biting ? q->framelength : (q->framelength + q->K - 1); @@ -102,24 +31,42 @@ int conv_encode(convcoder_t *q, char *input, char *output) { if (q->tail_biting) { sr = 0; for (i=q->framelength - q->K + 1; iframelength; i++) { - if (DEB) printf("%3d: sr=%3d, bit=%d\n",i,sr&7,input[i]); sr = (sr << 1) | (input[i] & 1); } } else { sr = 0; } - if (DEB) printf("state st=%d\n",sr&7); for (i = 0; i < len; i++) { int bit = (i < q->framelength) ? (input[i] & 1) : 0; sr = (sr << 1) | bit; - if (DEB) printf("%d, ",input[i]); for (j=0;jR;j++) { output[q->R * i + j] = parity(sr & q->poly[j]); } } - if (DEB) printf("\n"); - if (DEB) printf("state fin=%u\n",sr&7); + return q->R*len; } + + +int convcoder_initialize(convcoder_hl* h) { + 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.framelength = hl->in_len; + 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); + return 0; +} + +int convcoder_stop(convcoder_hl* h) { + return 0; +} diff --git a/lib/fec/src/viterbi.c b/lib/fec/src/viterbi.c new file mode 100644 index 000000000..074d2db7e --- /dev/null +++ b/lib/fec/src/viterbi.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2013, Ismael Gomez-Miguelez . + * This file is part of OSLD-lib (http://https://github.com/ismagom/osld-lib) + * + * OSLD-lib is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OSLD-lib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OSLD-lib. If not, see . + */ + +/**@TODO frontend to FEC library if installed + */ + +#include +#include +#include + +#include "fec/viterbi.h" +#include "parity.h" +#include "viterbi37.h" + +#define DEB 0 + +int decode37(void *o, float *symbols, char *data) { + viterbi_t *q = o; + int i; + int len = q->tail_biting ? q->framebits : (q->framebits + q->K - 1); + float amp = 0; + + for (i=0;i<3*len;i++) { + if (fabsf(symbols[i] > amp)) { + amp = symbols[i]; + } + } + + /* Decode it and make sure we get the right answer */ + /* Initialize Viterbi decoder */ + init_viterbi37_port(q->ptr, q->tail_biting?-1:0); + + /* Decode block */ + update_viterbi37_blk_port(q->ptr, symbols,q->framebits + q->K - 1, amp, len); + + /* Do Viterbi chainback */ + chainback_viterbi37_port(q->ptr, data, q->framebits, 0); + + return q->framebits; +} + +void free37(void *o) { + viterbi_t *q = o; + delete_viterbi37_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; + + if ((q->ptr = create_viterbi37_port(poly, framebits, tail_biting)) == NULL) { + fprintf(stderr, "create_viterbi37 failed\n"); + return -1; + } else { + return 0; + } +} + +int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int framebits, bool tail_bitting) { + switch(type) { + case viterbi_37: + return init37(q, poly, framebits, tail_bitting); + default: + fprintf(stderr, "Decoder not implemented\n"); + return -1; + } +} + +void viterbi_free(viterbi_t *q) { + q->free(q); +} + +/* symbols are real-valued */ +int viterbi_decode(viterbi_t *q, float *symbols, char *data) { + return q->decode(q, symbols, data); +} + + +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 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(&hl->obj, hl->input, hl->output); +} + +int viterbi_stop(viterbi_hl* h) { + viterbi_free(&h->obj); + return 0; +} diff --git a/lib/io/src/binsource.c b/lib/io/src/binsource.c index 88baa3e4f..a3093b22e 100644 --- a/lib/io/src/binsource.c +++ b/lib/io/src/binsource.c @@ -155,12 +155,10 @@ int binsource_work(binsource_hl* hl) { } else { ret = binsource_generate(&hl->obj,hl->output,hl->ctrl_in.nbits); } - if (hl->out_len) { - if (!ret) { - *hl->out_len = hl->ctrl_in.nbits; - } else { - *hl->out_len = 0; - } + if (!ret) { + hl->out_len = hl->ctrl_in.nbits; + } else { + hl->out_len = 0; } return ret; } diff --git a/lib/io/src/filesource.c b/lib/io/src/filesource.c index 6677d7eae..80c28066b 100644 --- a/lib/io/src/filesource.c +++ b/lib/io/src/filesource.c @@ -92,8 +92,8 @@ int filesource_initialize(filesource_hl* h) { } int filesource_work(filesource_hl* h) { - *h->out_len = filesource_read(&h->obj, h->output, h->ctrl_in.nsamples); - if (*h->out_len < 0) { + h->out_len = filesource_read(&h->obj, h->output, h->ctrl_in.nsamples); + if (h->out_len < 0) { return -1; } return 0; diff --git a/lib/modem/src/demod_hard.c b/lib/modem/src/demod_hard.c index 0c2a7abf6..d694659a0 100644 --- a/lib/modem/src/demod_hard.c +++ b/lib/modem/src/demod_hard.c @@ -65,11 +65,12 @@ int demod_hard_initialize(demod_hard_hl* hl) { int demod_hard_work(demod_hard_hl* hl) { int ret = demod_hard_demodulate(&hl->obj,hl->input,hl->output,hl->in_len); - if (hl->out_len) { - *hl->out_len = ret; - } + hl->out_len = ret; return 0; } +int demod_hard_stop(demod_hard_hl* hl) { + return 0; +} diff --git a/lib/modem/src/demod_soft.c b/lib/modem/src/demod_soft.c index 8f158e0f0..3426132a6 100644 --- a/lib/modem/src/demod_soft.c +++ b/lib/modem/src/demod_soft.c @@ -72,9 +72,7 @@ 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); - if (hl->out_len) { - *hl->out_len = ret; - } + hl->out_len = ret; return 0; } diff --git a/lib/modem/src/mod.c b/lib/modem/src/mod.c index b78c36b68..979139615 100644 --- a/lib/modem/src/mod.c +++ b/lib/modem/src/mod.c @@ -49,9 +49,7 @@ int mod_initialize(mod_hl* hl) { int mod_work(mod_hl* hl) { int ret = mod_modulate(&hl->obj,hl->input,hl->output,hl->in_len); - if (hl->out_len) { - *hl->out_len = ret; - } + hl->out_len = ret; return 0; } diff --git a/lib/phch/src/pbch.c b/lib/phch/src/pbch.c index 7c4813f1d..0d57f37ad 100644 --- a/lib/phch/src/pbch.c +++ b/lib/phch/src/pbch.c @@ -137,7 +137,7 @@ int pbch_init(pbch_t *q, int cell_id, lte_cp_t cp) { } int poly[3] = {0x6D, 0x4F, 0x57}; - if (viterbi_init(&q->decoder, CONVCODER_37, poly, 40, true)) { + if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) { goto clean; } int nof_symbols = (CP_ISNORM(q->cp)) ? PBCH_RE_CPNORM: PBCH_RE_CPEXT; @@ -275,7 +275,7 @@ int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, int src, int dst, int n, int n } /* unrate matching */ - rm_conv_rx(q->temp, q->pbch_rm, 4*nof_bits, 120); + rm_conv_rx(q->temp, q->pbch_rm, 4 * nof_bits, 120); /* decode */ viterbi_decode(&q->decoder, q->pbch_rm, q->data); @@ -324,15 +324,13 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t **ce, int nof_ports, /* 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"); + /*@TODO: layer demapping */ /* demodulate symbols */ demod_soft_sigma_set(&q->demod, ebno); diff --git a/lib/ratematching/src/rm_conv.c b/lib/ratematching/src/rm_conv.c index af4a5dbe5..2710775d8 100644 --- a/lib/ratematching/src/rm_conv.c +++ b/lib/ratematching/src/rm_conv.c @@ -102,10 +102,10 @@ int rm_conv_initialize(rm_conv_hl* h) { 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; + 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; + hl->out_len = hl->ctrl_in.E; } return 0; } diff --git a/lib/resampling/src/interp.c b/lib/resampling/src/interp.c index 392b5e511..068495e3f 100644 --- a/lib/resampling/src/interp.c +++ b/lib/resampling/src/interp.c @@ -41,15 +41,14 @@ void interp_linear_offset(cf_t *input, cf_t *output, int M, int len, int off_st, mag = mag0 + j*(mag1-mag0)/M; arg = arg0 + j*(arg1-arg0)/M; output[i*M+j+off_st] = mag * cexpf(I * arg); -// DEBUG("output[%d] = input[%d]+%d*(input[%d]-input[%d])/%d = %.3f+%.3f = %.3f delta=%.3f\n", -// i*M+j, i, j, i+1, i, M, cabsf(input[i]), cabsf(j*(input[i+1] - input[i])/M), -// cabsf(output[i*M+j])); } } - for (j=0;j 1) { + for (j=0;joutput, hl->input, sizeof(float) * hl->in_len); scrambling_float(seq, hl->output); } - *(hl->out_len) = hl->in_len; + hl->out_len = hl->in_len; return 0; } diff --git a/lib/sync/src/find_sss.c b/lib/sync/src/find_sss.c index 8d7df4b80..7b4a08ac3 100644 --- a/lib/sync/src/find_sss.c +++ b/lib/sync/src/find_sss.c @@ -24,8 +24,8 @@ cf_t corr_sz(cf_t *z, cf_t *s) { cf_t sum; cf_t zsprod[32]; - vec_dot_prod(z, s, zsprod, N_SSS - 1); - sum = sum_c(zsprod, N_SSS - 1); + vec_dot_prod_ccc(z, s, zsprod, N_SSS - 1); + sum = vec_acc_cc(zsprod, N_SSS - 1); return sum; } @@ -66,24 +66,30 @@ void sss_synch_m0m1(sss_synch_t *q, cf_t *input, int *m0, float *m0_value, y[1][i] = input_fft[SSS_POS_SYMBOL + 2 * i + 1]; } - vec_dot_prod(y[0], q->fc_tables.c[0], z, N_SSS); + vec_dot_prod_ccc(y[0], q->fc_tables.c[0], z, N_SSS); memcpy(zdelay, &z[1], (N_SSS - 1) * sizeof(cf_t)); - vec_conj(z, zconj, N_SSS - 1); - vec_dot_prod(zdelay, zconj, zprod, N_SSS - 1); + vec_conj_cc(z, zconj, N_SSS - 1); + vec_dot_prod_ccc(zdelay, zconj, zprod, N_SSS - 1); corr_all_zs(zprod, q->fc_tables.s, tmp); - vec_abs(tmp, tmp_real, N_SSS); - vec_max(tmp_real, m0_value, m0, N_SSS); + 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_dot_prod(y[1], q->fc_tables.c[1], tmp, N_SSS); - vec_dot_prod(tmp, q->fc_tables.z1[*m0], z, N_SSS); + vec_dot_prod_ccc(y[1], q->fc_tables.c[1], tmp, N_SSS); + vec_dot_prod_ccc(tmp, q->fc_tables.z1[*m0], z, N_SSS); memcpy(zdelay, &z[1], (N_SSS - 1) * sizeof(cf_t)); - vec_conj(z, zconj, N_SSS - 1); - vec_dot_prod(zdelay, zconj, zprod, N_SSS - 1); + vec_conj_cc(z, zconj, N_SSS - 1); + vec_dot_prod_ccc(zdelay, zconj, zprod, N_SSS - 1); corr_all_zs(zprod, q->fc_tables.s, tmp); - vec_abs(tmp, tmp_real, N_SSS); - vec_max(tmp_real, m1_value, m1, N_SSS); + vec_abs_cf(tmp, tmp_real, N_SSS); + *m1 = vec_max_fi(tmp_real, N_SSS); + if (m1_value) { + *m1_value = tmp_real[*m1]; + } } diff --git a/lib/sync/src/pss.c b/lib/sync/src/pss.c index d4295a3e4..8d339f123 100644 --- a/lib/sync/src/pss.c +++ b/lib/sync/src/pss.c @@ -174,10 +174,10 @@ int pss_synch_set_N_id_2(pss_synch_t *q, int N_id_2) { dft_run_c2c(&plan, pss_signal_pad, q->pss_signal_freq); - vec_mult_c_r(q->pss_signal_freq, pss_signal_pad, - (float) 1 / (PSS_LEN_FREQ - 1), 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(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; @@ -206,13 +206,16 @@ int pss_synch_find_pss(pss_synch_t *q, cf_t *input, float *corr_peak_value, floa conv_output_len = conv_cc(input, q->pss_signal_freq, q->conv_output, q->frame_size, PSS_LEN_FREQ); #endif - vec_abs(q->conv_output, q->conv_abs, conv_output_len); - vec_max(q->conv_abs, corr_peak_value, &corr_peak_pos, conv_output_len); + 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 = sum_r(q->conv_abs, conv_output_len) / conv_output_len; + *corr_mean_value = vec_acc_ff(q->conv_abs, conv_output_len) / conv_output_len; } - return corr_peak_pos; + return (int) corr_peak_pos; } /* Returns the CFO estimation given a PSS received sequence @@ -224,10 +227,10 @@ 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]; - vec_dot_prod_u(q->pss_signal_freq, pss_recv, y, PSS_LEN_FREQ - 1); + vec_dot_prod_ccc_unalign(q->pss_signal_freq, pss_recv, y, PSS_LEN_FREQ - 1); - y0 = sum_c(y, (PSS_LEN_FREQ - 1)/2); - y1 = sum_c(&y[(PSS_LEN_FREQ - 1)/2], (PSS_LEN_FREQ - 1)/2); + 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; @@ -380,10 +383,7 @@ int pss_synch_work(pss_synch_hl* hl) { 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); - if (*hl->out_len < 0) { - return -1; - } + hl->out_len = pss_synch_frame(&hl->obj, hl->input, hl->output, hl->in_len); return 0; } diff --git a/lib/utils/src/convolution.c b/lib/utils/src/convolution.c index 017835580..b6ff45d08 100644 --- a/lib/utils/src/convolution.c +++ b/lib/utils/src/convolution.c @@ -66,7 +66,7 @@ int conv_fft_cc_run(conv_fft_cc_t *state, _Complex float *input, _Complex float dft_run_c2c(&state->input_plan, input, state->input_fft); dft_run_c2c(&state->filter_plan, filter, state->filter_fft); - vec_dot_prod(state->input_fft,state->filter_fft,state->output_fft,state->output_len); + vec_dot_prod_ccc(state->input_fft,state->filter_fft,state->output_fft,state->output_len); dft_run_c2c(&state->output_plan, state->output_fft, output); diff --git a/lib/utils/src/vector.c b/lib/utils/src/vector.c index 1336173f5..a2c49c16f 100644 --- a/lib/utils/src/vector.c +++ b/lib/utils/src/vector.c @@ -27,23 +27,23 @@ #include "volk/volk.h" #endif -int sum_i(int *x, int len) { +int vec_acc_ii(int *x, int len) { int i; - int y=0; + int z=0; for (i=0;im) { m=x[i]; p=i; } } - if (pos) *pos=p; - if (max) *max=m; + return p; #else unsigned int target=0; volk_32f_index_max_16u_a(&target,x,(unsigned int) len); - if (pos) *pos=(int) target; - if (max) *max=x[target]; + return (int) target; #endif } diff --git a/matlab/common/read_real.m b/matlab/common/read_real.m new file mode 100644 index 000000000..2447d11ce --- /dev/null +++ b/matlab/common/read_real.m @@ -0,0 +1,18 @@ +function [ out ] = read_real( filename, count ) +%READ_COMPLEX Summary of this function goes here +% Detailed explanation goes here + + [tidin msg]=fopen(filename,'r'); + if (tidin==-1) + fprintf('error opening %s: %s\n',filename, msg); + out=[]; + return + end + + if (nargin==1) + count=inf; + end + + out=fread(tidin,count,'single'); +end + diff --git a/matlab/sync/find_pss.m b/matlab/sync/find_pss.m index bc16c9a91..2fbc8dc38 100644 --- a/matlab/sync/find_pss.m +++ b/matlab/sync/find_pss.m @@ -28,7 +28,7 @@ function [ fs eps p_m w2] = find_pss( x, N_id_2, doplot, threshold) end % Estimate PSS-aided CFO - if (i > 200 && i threshold) + if (i > 128 && i threshold) y=ccf.*x(i-128:i-1); y0=y(1:64); diff --git a/uhd/uhd_imp.cpp b/uhd/uhd_imp.cpp index 1fa66766d..91a04d983 100644 --- a/uhd/uhd_imp.cpp +++ b/uhd/uhd_imp.cpp @@ -15,8 +15,6 @@ typedef _Complex float complex_t; #define SAMPLE_SZ sizeof(complex_t) -void uhd_rx_stream(void *h); - bool isLocked(void *h) { uhd_handler* handler = static_cast(h); diff --git a/uhd/uhd_utils.c b/uhd/uhd_utils.c index b33eb344b..89548991e 100644 --- a/uhd/uhd_utils.c +++ b/uhd/uhd_utils.c @@ -36,7 +36,7 @@ int uhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs goto free_and_exit; } } - rssi[i] = vec_power(buffer, nsamp); + rssi[i] = vec_avg_power_cf(buffer, nsamp); printf("[%3d]: Freq %4.1f Mhz - RSSI: %3.2f dBm\r", i, f/1000000, 10*log10f(rssi[i]) + 30); fflush(stdout); if (VERBOSE_ISINFO()) { printf("\n");