Merge pull request #42 from ismagom/master

Fixed SCAN_MIB example. Fixed other issues with synchronization and AGC ...
master
Ismael Gómez-Miguelez 11 years ago
commit c5ad9c5178

@ -46,7 +46,7 @@ int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double f
goto free_and_exit; goto free_and_exit;
} }
cuhd_set_rx_gain(uhd, 0.0); cuhd_set_rx_gain(uhd, 20.0);
cuhd_set_rx_srate(uhd, fs); cuhd_set_rx_srate(uhd, fs);
for (i=0;i<nof_bands;i++) { for (i=0;i<nof_bands;i++) {
@ -55,7 +55,7 @@ int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double f
f = (double) freqs[i]; f = (double) freqs[i];
cuhd_set_rx_freq(uhd, f); cuhd_set_rx_freq(uhd, f);
cuhd_rx_wait_lo_locked(uhd); cuhd_rx_wait_lo_locked(uhd);
usleep(10000);
cuhd_start_rx_stream(uhd); cuhd_start_rx_stream(uhd);
/* discard first samples */ /* discard first samples */

@ -81,10 +81,6 @@ int iodev_init(iodev_t *q, iodev_cfg_t *config) {
DEBUG("Starting receiver...\n", 0); DEBUG("Starting receiver...\n", 0);
cuhd_start_rx_stream(q->uhd); cuhd_start_rx_stream(q->uhd);
if (config->find_threshold > 0.0) {
ue_sync_set_threshold(&q->sframe, config->find_threshold);
}
ue_sync_init(&q->sframe, cuhd_set_rx_srate, cuhd_recv_wrapper, q->uhd); ue_sync_init(&q->sframe, cuhd_set_rx_srate, cuhd_recv_wrapper, q->uhd);
// Here, the subframe length and input buffer is managed by ue_sync // Here, the subframe length and input buffer is managed by ue_sync

@ -161,7 +161,7 @@ int main(int argc, char **argv) {
uint32_t sf_idx; uint32_t sf_idx;
pbch_mib_t mib; pbch_mib_t mib;
bool printed_sib = false; bool printed_sib = false;
uint32_t rlen; int rlen;
parse_args(&prog_args, argc, argv); parse_args(&prog_args, argc, argv);
@ -184,6 +184,12 @@ int main(int argc, char **argv) {
sf_cnt = 0; sf_cnt = 0;
sf_idx = 0; sf_idx = 0;
/* Decodes the SSS signal during the tracking phase. Extra overhead, but makes sure we are in the correct subframe */
ue_sync_decode_sss_on_track(&iodev.sframe, true);
/* Decodes the PBCH on each frame. Around 10% more overhead, but makes sure we are in the current System Frame Number (SFN) */
ue_sync_pbch_always(&iodev.sframe, false);
/* Main loop */ /* Main loop */
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) { while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
@ -194,7 +200,10 @@ int main(int argc, char **argv) {
} }
/* iodev_receive returns 1 if successfully read 1 aligned subframe */ /* iodev_receive returns 1 if successfully read 1 aligned subframe */
if (ret == 1) { if (ret == 0) {
printf("Finding PSS... Peak: %8.1f, Output level: %+.2f dB\r",
sync_get_peak_value(&iodev.sframe.s), 10*log10f(agc_get_gain(&iodev.sframe.agc)));
} else if (ret == 1) {
if (!ue_dl_initiated) { if (!ue_dl_initiated) {
if (iodev_isUSRP(&iodev)) { if (iodev_isUSRP(&iodev)) {
cell = ue_sync_get_cell(&iodev.sframe); cell = ue_sync_get_cell(&iodev.sframe);
@ -229,9 +238,11 @@ int main(int argc, char **argv) {
printed_sib = true; printed_sib = true;
} }
if (!(sf_cnt % 10)) { if (!(sf_cnt % 10)) {
printf("Cell ID: %3d, RSSI: %+.2f dBm, CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Errors: %4d/%4d, BLER: %.1e\r", printf("RSSI: %+.2f dBm, CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Errors: %4d/%4d, BLER: %.1e\r",
cell.id, 20*log10f(agc_get_rssi(&iodev.sframe.agc)), iodev.sframe.cur_cfo * 15, iodev.sframe.mean_time_offset / 5, iodev.sframe.peak_idx, 20*log10f(agc_get_rssi(&iodev.sframe.agc))+30,
ue_sync_get_cfo(&iodev.sframe)/1000, ue_sync_get_sfo(&iodev.sframe)/1000, iodev.sframe.peak_idx,
(int) ue_dl.pkt_errors, (int) ue_dl.pkts_total, (float) ue_dl.pkt_errors / ue_dl.pkts_total); (int) ue_dl.pkt_errors, (int) ue_dl.pkts_total, (float) ue_dl.pkt_errors / ue_dl.pkts_total);
fflush(stdout); fflush(stdout);
if (VERBOSE_ISINFO()) { if (VERBOSE_ISINFO()) {
printf("\n"); printf("\n");
@ -250,6 +261,7 @@ int main(int argc, char **argv) {
} }
} }
} }
if (prog_args.nof_subframes > 0) { if (prog_args.nof_subframes > 0) {
sf_cnt++; sf_cnt++;
} }

@ -36,73 +36,45 @@
#include "liblte/phy/phy.h" #include "liblte/phy/phy.h"
//#define DISABLE_UHD
#ifndef DISABLE_UHD #ifndef DISABLE_UHD
#include "liblte/cuhd/cuhd.h" #include "liblte/cuhd/cuhd.h"
#endif #endif
#define MHZ 1000000 #define MHZ 1000000
#define SAMP_FREQ 1920000 #define SAMP_FREQ 1920000
#define RSSI_FS 1000000
#define FLEN 9600 #define FLEN 9600
#define FLEN_PERIOD 0.005 #define FLEN_PERIOD 0.005
#define RSSI_DECIM 20
#define IS_SIGNAL(i) (10*log10f(rssi[i]) + 30 > rssi_threshold)
int band, earfcn=-1; int band = -1;
float find_threshold = 10.0;
int earfcn_start=-1, earfcn_end = -1; int earfcn_start=-1, earfcn_end = -1;
float rssi_threshold = -45.0; int nof_frames_find=200;
int max_track_lost=9;
int nof_frames_find=20, nof_frames_track=100, nof_samples_rssi=50000;
int track_len=500; float uhd_gain = 60.0;
char *uhd_args="";
cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS];
pbch_t pbch;
lte_fft_t fft;
chest_t chest;
sync_t ssync;
cfo_t cfocorr;
float *cfo_v;
int *idx_v, *idx_valid, *t;
float *p2a_v;
void *uhd;
int nof_bands;
float uhd_gain = 20.0;
#define MAX_EARFCN 1000 #define MAX_EARFCN 1000
lte_earfcn_t channels[MAX_EARFCN]; 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 usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [seRrFfTgv] -b band\n", prog); printf("Usage: %s [asefgv] -b band\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-g UHD gain [Default %.2f dB]\n", uhd_gain);
printf("\t-s earfcn_start [Default All]\n"); printf("\t-s earfcn_start [Default All]\n");
printf("\t-e earfcn_end [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-f nof_frames_find [Default %d]\n", nof_frames_find);
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-l pss_track_len [Default %d]\n", track_len);
printf("\t-g gain [Default %.2f dB]\n", uhd_gain);
printf("\t-v [set verbose to debug, default none]\n"); printf("\t-v [set verbose to debug, default none]\n");
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "bseRrFfTgv")) != -1) { while ((opt = getopt(argc, argv, "asefgvb")) != -1) {
switch(opt) { switch(opt) {
case 'a':
uhd_args = argv[optind];
break;
case 'b': case 'b':
band = atoi(argv[optind]); band = atoi(argv[optind]);
break; break;
@ -112,20 +84,8 @@ void parse_args(int argc, char **argv) {
case 'e': case 'e':
earfcn_end = atoi(argv[optind]); earfcn_end = atoi(argv[optind]);
break; 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': case 'f':
find_threshold = atof(argv[optind]); nof_frames_find = atoi(argv[optind]);
break;
case 'T':
nof_frames_track = atoi(argv[optind]);
break; break;
case 'g': case 'g':
uhd_gain = atof(argv[optind]); uhd_gain = atof(argv[optind]);
@ -138,225 +98,26 @@ void parse_args(int argc, char **argv) {
exit(-1); exit(-1);
} }
} }
if (band == -1) {
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<MAX_PORTS;i++) {
ce[i] = malloc(CPNORM_NSYMB * 72 * sizeof(cf_t));
if (!ce[i]) {
perror("malloc");
return -1;
}
}
if (sync_init(&ssync, FLEN, 128, 128)) {
fprintf(stderr, "Error initiating PSS/SSS\n");
return -1;
}
if (chest_init(&chest, CPNORM, 6, MAX_PORTS)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
if (lte_fft_init(&fft, CPNORM, 6)) {
fprintf(stderr, "Error initializing FFT\n");
return -1;
}
if (cfo_init(&cfocorr, FLEN)) {
fprintf(stderr, "Error initiating CFO\n");
return -1;
}
idx_v = malloc(nof_frames_track * sizeof(int));
if (!idx_v) {
perror("malloc");
return -1;
}
idx_valid = malloc(nof_frames_track * sizeof(int));
if (!idx_valid) {
perror("malloc");
return -1;
}
t = malloc(nof_frames_track * sizeof(int));
if (!t) {
perror("malloc");
return -1;
}
cfo_v = malloc(nof_frames_track * sizeof(float));
if (!cfo_v) {
perror("malloc");
return -1;
}
p2a_v = malloc(nof_frames_track * sizeof(float));
if (!p2a_v) {
perror("malloc");
return -1;
}
bzero(cfo, sizeof(float) * MAX_EARFCN);
bzero(p2a, sizeof(float) * MAX_EARFCN);
/* open UHD device */
#ifndef DISABLE_UHD
printf("Opening UHD device...\n");
if (cuhd_open("",&uhd)) {
fprintf(stderr, "Error opening uhd\n");
return -1;
}
#endif
return 0;
}
void base_free() {
int i;
#ifndef DISABLE_UHD
cuhd_close(uhd);
#endif
sync_free(&ssync);
lte_fft_free(&fft);
chest_free(&chest);
cfo_free(&cfocorr);
free(input_buffer);
free(fft_buffer);
for (i=0;i<MAX_PORTS;i++) {
free(ce[i]);
}
free(idx_v);
free(idx_valid);
free(t);
free(cfo_v);
free(p2a_v);
}
float mean_valid(int *idx_v, float *x, int nof_frames) {
int i;
float mean = 0;
int n = 0;
for (i=0;i<nof_frames;i++) {
if (idx_v[i] != -1) {
mean += x[i];
n++;
}
}
if (n > 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<len;i++) {
if (in[i] != -1) {
out[n] = in[i];
period[n] = i;
n++;
}
}
return n;
}
int rssi_scan() {
int n=0;
int i;
if (nof_bands > 100) {
/* scan every Mhz, that is 10 freqs */
for (i=0;i<nof_bands;i+=RSSI_DECIM) {
freqs[n] = channels[i].fd * MHZ;
n++;
}
#ifndef DISABLE_UHD
if (cuhd_rssi_scan(uhd, freqs, rssi_d, n, (double) RSSI_FS, nof_samples_rssi)) {
fprintf(stderr, "Error while doing RSSI scan\n");
return -1;
}
#endif
/* linearly interpolate the rssi vector */
interp_linear_f(rssi_d, rssi, RSSI_DECIM, n);
} else {
for (i=0;i<nof_bands;i++) {
freqs[i] = channels[i].fd * MHZ;
}
#ifndef DISABLE_UHD
if (cuhd_rssi_scan(uhd, freqs, rssi, nof_bands, (double) RSSI_FS, nof_samples_rssi)) {
fprintf(stderr, "Error while doing RSSI scan\n");
return -1;
}
#endif
n = nof_bands;
}
return n;
}
int mib_decoder_init(int cell_id) {
lte_cell_t cell;
cell.id = cell_id;
cell.nof_prb = 6;
cell.nof_ports = 2;
cell.cp = CPNORM;
if (chest_ref_LTEDL(&chest, cell)) {
fprintf(stderr, "Error initializing reference signal\n");
return -1;
}
if (pbch_init(&pbch, cell)) {
fprintf(stderr, "Error initiating PBCH\n");
return -1;
}
DEBUG("PBCH initiated cell_id=%d\n", cell_id);
return 0;
} }
int mib_decoder_run(cf_t *input, pbch_mib_t *mib) { int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples) {
int i; DEBUG(" ---- Receive %d samples ---- \n", nsamples);
lte_fft_run_slot(&fft, input, fft_buffer); return cuhd_recv(h, data, nsamples, 1);
/* Get channel estimates for each port */
for (i=0;i<MAX_PORTS;i++) {
chest_ce_slot_port(&chest, fft_buffer, ce[i], 1, i);
} }
DEBUG("Decoding PBCH\n", 0);
return pbch_decode(&pbch, fft_buffer, ce, mib);
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
int frame_cnt, valid_frames;
int freq;
int cell_id;
float max_peak_to_avg;
float sfo;
uint32_t track_idx, find_idx;
int last_found;
enum sync_state state;
int n;
int mib_attempts;
int nslot;
pbch_mib_t mib;
int ret; int ret;
int frame_cnt;
int nof_freqs;
uint32_t freq;
ue_sync_t uesync;
void *uhd;
cf_t *buffer;
if (argc < 3) { if (argc < 3) {
usage(argv[0]); usage(argv[0]);
@ -365,188 +126,75 @@ int main(int argc, char **argv) {
parse_args(argc,argv); parse_args(argc,argv);
if (base_init(FLEN)) { printf("Opening UHD device...\n");
fprintf(stderr, "Error initializing memory\n"); if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1); exit(-1);
} }
sync_pss_det_peak_to_avg(&ssync); /* set uhd_gain */
cuhd_set_rx_gain(uhd, uhd_gain);
nof_bands = lte_band_get_fd_band(band, channels, earfcn_start, earfcn_end, MAX_EARFCN);
printf("RSSI scan: %d freqs in band %d, RSSI threshold %.2f dBm\n", nof_bands, band, rssi_threshold);
n = rssi_scan(); nof_freqs = lte_band_get_fd_band(band, channels, earfcn_start, earfcn_end, MAX_EARFCN);
if (n == -1) { if (nof_freqs < 0) {
fprintf(stderr, "Error getting EARFCN list\n");
exit(-1); exit(-1);
} }
printf("\nDone. Starting PSS search on %d channels\n", n);
usleep(500000);
INFO("Setting sampling frequency %.2f MHz\n", (float) SAMP_FREQ/MHZ);
#ifndef DISABLE_UHD
cuhd_set_rx_srate(uhd, SAMP_FREQ);
cuhd_set_rx_gain(uhd, uhd_gain);
#endif
freq=0;
state = INIT;
nslot = 0;
sfo = 0;
find_idx = 0;
frame_cnt = 0;
max_peak_to_avg = -1;
last_found = 0;
cell_id = 0;
while(freq<nof_bands) {
/* scan only bands above rssi_threshold */
if (!IS_SIGNAL(freq)) {
INFO("[%3d/%d]: Skipping EARFCN %d %.2f MHz RSSI %.2f dB\n", freq, nof_bands,
channels[freq].id, channels[freq].fd,10*log10f(rssi[freq]) + 30);
freq++;
} else {
if (state != INIT && state != DONE) {
#ifndef DISABLE_UHD
DEBUG(" ----- RECEIVING %d SAMPLES ---- \n", FLEN);
cuhd_recv(uhd, &input_buffer[FLEN], FLEN, 1);
#endif
}
switch(state) {
case INIT:
DEBUG("Stopping receiver...\n",0);
#ifndef DISABLE_UHD
cuhd_stop_rx_stream(uhd);
for (freq=0;freq<nof_freqs;freq++) {
/* set freq */ /* set freq */
cuhd_stop_rx_stream(uhd);
cuhd_set_rx_freq(uhd, (double) channels[freq].fd * MHZ); cuhd_set_rx_freq(uhd, (double) channels[freq].fd * MHZ);
cuhd_rx_wait_lo_locked(uhd); cuhd_rx_wait_lo_locked(uhd);
DEBUG("Set freq to %.3f MHz\n", (double) channels[freq].fd);
if (ue_sync_init(&uesync, cuhd_set_rx_srate, cuhd_recv_wrapper, uhd)) {
fprintf(stderr, "Error initiating UE sync\n");
exit(-1);
}
ue_sync_set_nof_pbch_decodes(&uesync, 1);
ue_sync_decode_sss_on_track(&uesync, true);
ue_sync_change_srate(&uesync, false);
DEBUG("Starting receiver...\n",0); DEBUG("Starting receiver...\n",0);
cuhd_start_rx_stream(uhd); cuhd_start_rx_stream(uhd);
#endif usleep(10000);
/* init variables */
frame_cnt = 0;
max_peak_to_avg = -1;
cell_id = -1;
/* receive first frame */
#ifndef DISABLE_UHD
cuhd_recv(uhd, input_buffer, FLEN, 1);
#endif
/* set find_threshold and go to FIND state */
sync_set_threshold(&ssync, find_threshold, find_threshold/2);
state = FIND;
break;
case FIND:
/* find peak in all frame */
ret = sync_find(&ssync, &input_buffer[FLEN], &find_idx);
DEBUG("[%3d/%d]: PAR=%.2f\n", freq, nof_bands, sync_get_peak_value(&ssync));
if (ret == 1) {
/* if found peak, go to track and set lower threshold */
frame_cnt = -1;
last_found = 0;
max_peak_to_avg = -1;
cell_id = sync_get_cell_id(&ssync);
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_value(&ssync)));
} else {
if (frame_cnt >= nof_frames_find) {
state = INIT;
freq++;
}
}
break;
case TRACK:
INFO("Tracking PSS find_idx %d offset %d\n", find_idx, find_idx - track_len);
ret = sync_track(&ssync, input_buffer, FLEN + find_idx - track_len, &track_idx);
p2a_v[frame_cnt] = sync_get_peak_value(&ssync);
/* save cell id for the best peak-to-avg */ /* Receive up to a maximum of nof_frames_find */
if (p2a_v[frame_cnt] > max_peak_to_avg) { frame_cnt = 0;
max_peak_to_avg = p2a_v[frame_cnt]; ret = 0;
cell_id = sync_get_cell_id(&ssync); ue_sync_reset(&uesync);
} agc_reset(&uesync.agc);
if (ret == 1) {
cfo_v[frame_cnt] = sync_get_cfo(&ssync); while(frame_cnt < nof_frames_find && ret == 0) {
last_found = frame_cnt; ret = ue_sync_get_buffer(&uesync, &buffer);
find_idx += track_idx - track_len; if (ret < 0) {
idx_v[frame_cnt] = find_idx; fprintf(stderr, "Error calling ue_sync_work()\n");
nslot = sync_get_slot_id(&ssync); exit(-1);
} 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 */ frame_cnt++;
if (frame_cnt - last_found > max_track_lost) { printf("[%3d/%d]: EARFCN %d Freq. %.2f MHz looking for PSS. RSSI: %+2.2f dB...\r", freq, nof_freqs,
INFO("\n[%3d/%d]: EARFCN %d Freq. %.2f MHz %d frames lost\n", freq, nof_bands, channels[freq].id, channels[freq].fd, 20*log10f(agc_get_rssi(&uesync.agc)));fflush(stdout);
channels[freq].id, channels[freq].fd, frame_cnt - last_found); if (VERBOSE_ISINFO()) {
printf("\n");
state = INIT;
freq++;
} else if (frame_cnt >= nof_frames_track) {
mib_decoder_init(cell_id);
cfo[freq] = mean_valid(idx_v, cfo_v, frame_cnt);
p2a[freq] = mean_valid(idx_v, p2a_v, frame_cnt);
valid_frames = preprocess_idx(idx_v, idx_valid, t, frame_cnt);
sfo = sfo_estimate_period(idx_valid, t, valid_frames, FLEN_PERIOD);
state = MIB;
nslot=(nslot+10)%20;
} }
break;
case MIB:
INFO("Finding MIB at freq %.2f Mhz offset=%d, cell_id=%d, slot_idx=%d\n", channels[freq].fd, find_idx, cell_id, nslot);
// TODO: Correct SFO
// Correct CFO
INFO("Correcting CFO=%.4f\n", cfo[freq]);
cfo_correct(&cfocorr, &input_buffer[FLEN], &input_buffer[FLEN], (-cfo[freq])/128);
if (nslot == 0) {
if (mib_decoder_run(&input_buffer[FLEN+find_idx], &mib)) {
INFO("MIB detected attempt=%d\n", mib_attempts);
state = DONE;
} else {
INFO("MIB not detected attempt=%d\n", mib_attempts);
if (mib_attempts == 0) {
freq++;
state = INIT;
} }
if (ret == 1) {
if (VERBOSE_ISINFO()) {
printf("[%3d/%d]: EARFCN %d Freq. %.2f MHz FOUND MIB ", freq, nof_freqs,
channels[freq].id, channels[freq].fd);
} }
mib_attempts++; printf("RSSI: %+.2f dBm, CFO: %+.4f KHz\n",
20*log10f(agc_get_rssi(&uesync.agc)), ue_sync_get_cfo(&uesync));
printf("\n");fflush(stdout);
} }
nslot = (nslot+10)%20;
break; ue_sync_free(&uesync);
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 */ cuhd_close(uhd);
if (state == TRACK || state == FIND) {
memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t));
}
frame_cnt++;
}
}
base_free();
printf("\n\nDone\n"); printf("\n\nDone\n");
exit(0); exit(0);

@ -41,27 +41,35 @@
*/ */
typedef _Complex float cf_t; typedef _Complex float cf_t;
#define AGC_DEFAULT_BW (1e-2f) #define AGC_DEFAULT_BW (5e-2)
typedef struct LIBLTE_API{ typedef struct LIBLTE_API{
float bandwidth; float bandwidth;
float gain; float gain;
float y_out; float y_out;
bool lock; bool lock;
bool isfirst;
} agc_t; } agc_t;
LIBLTE_API int agc_init (agc_t *q); LIBLTE_API int agc_init (agc_t *q);
LIBLTE_API void agc_free(agc_t *q); LIBLTE_API void agc_free(agc_t *q);
LIBLTE_API void agc_reset(agc_t *q);
LIBLTE_API void agc_set_bandwidth(agc_t *q, LIBLTE_API void agc_set_bandwidth(agc_t *q,
float bandwidth); float bandwidth);
LIBLTE_API float agc_get_rssi(agc_t *q); LIBLTE_API float agc_get_rssi(agc_t *q);
LIBLTE_API void agc_lock(agc_t *q, bool enable); LIBLTE_API float agc_get_output_level(agc_t *q);
LIBLTE_API float agc_get_gain(agc_t *q);
LIBLTE_API void agc_lock(agc_t *q,
bool enable);
LIBLTE_API void agc_push(agc_t *q, LIBLTE_API void agc_process(agc_t *q,
cf_t *input, cf_t *input,
cf_t *output, cf_t *output,
uint32_t len); uint32_t len);

@ -100,6 +100,7 @@ LIBLTE_API int pbch_encode(pbch_t *q,
LIBLTE_API void pbch_decode_reset(pbch_t *q); LIBLTE_API void pbch_decode_reset(pbch_t *q);
LIBLTE_API void pbch_mib_fprint(FILE *stream, LIBLTE_API void pbch_mib_fprint(FILE *stream,
pbch_mib_t *mib); pbch_mib_t *mib,
uint32_t cell_id);
#endif // PBCH_ #endif // PBCH_

@ -61,15 +61,16 @@
* *
*************************************************************/ *************************************************************/
typedef enum LIBLTE_API { SF_FIND, SF_TRACK} ue_sync_state_t; typedef enum LIBLTE_API { SF_AGC, SF_FIND, SF_TRACK} ue_sync_state_t;
#define SYNC_PBCH_NOF_PRB 6 #define SYNC_PBCH_NOF_PRB 6
#define SYNC_PBCH_NOF_PORTS 2 #define SYNC_PBCH_NOF_PORTS 2
#define TRACK_MAX_LOST 10 #define TRACK_MAX_LOST 10
#define PSS_THRESHOLD 1
#define NOF_MIB_DECODES 10 #define DEFAULT_NOF_MIB_DECODES 10
#define AGC_NOF_FRAMES 100
#define MEASURE_EXEC_TIME #define MEASURE_EXEC_TIME
@ -112,6 +113,8 @@ typedef struct LIBLTE_API {
bool pbch_decode_always; bool pbch_decode_always;
bool pbch_decoder_enabled; bool pbch_decoder_enabled;
uint32_t pbch_last_trial; uint32_t pbch_last_trial;
bool change_srate;
uint32_t nof_mib_decodes;
bool decode_sss_on_track; bool decode_sss_on_track;
@ -134,24 +137,28 @@ LIBLTE_API void ue_sync_free(ue_sync_t *q);
LIBLTE_API int ue_sync_get_buffer(ue_sync_t *q, LIBLTE_API int ue_sync_get_buffer(ue_sync_t *q,
cf_t **sf_symbols); cf_t **sf_symbols);
LIBLTE_API void ue_sync_set_nof_pbch_decodes(ue_sync_t *q,
uint32_t nof_pbch_decodes);
LIBLTE_API void ue_sync_reset(ue_sync_t *q); LIBLTE_API void ue_sync_reset(ue_sync_t *q);
LIBLTE_API void ue_sync_decode_sss_on_track(ue_sync_t *q, bool enabled); LIBLTE_API void ue_sync_decode_sss_on_track(ue_sync_t *q,
bool enabled);
LIBLTE_API void ue_sync_pbch_enable(ue_sync_t *q, bool enabled); LIBLTE_API void ue_sync_pbch_enable(ue_sync_t *q,
bool enabled);
LIBLTE_API void ue_sync_pbch_always(ue_sync_t *q, bool enabled); LIBLTE_API void ue_sync_change_srate(ue_sync_t *q,
bool enabled);
LIBLTE_API void ue_sync_set_threshold(ue_sync_t *q, LIBLTE_API void ue_sync_pbch_always(ue_sync_t *q,
float threshold); bool enabled);
LIBLTE_API ue_sync_state_t ue_sync_get_state(ue_sync_t *q); LIBLTE_API ue_sync_state_t ue_sync_get_state(ue_sync_t *q);
LIBLTE_API uint32_t ue_sync_get_sfidx(ue_sync_t *q); LIBLTE_API uint32_t ue_sync_get_sfidx(ue_sync_t *q);
LIBLTE_API uint32_t ue_sync_get_peak_idx(ue_sync_t *q);
LIBLTE_API lte_cell_t ue_sync_get_cell(ue_sync_t *q); LIBLTE_API lte_cell_t ue_sync_get_cell(ue_sync_t *q);
LIBLTE_API pbch_mib_t ue_sync_get_mib(ue_sync_t *q); LIBLTE_API pbch_mib_t ue_sync_get_mib(ue_sync_t *q);

@ -41,10 +41,7 @@
int agc_init (agc_t *q) { int agc_init (agc_t *q) {
bzero(q, sizeof(agc_t)); bzero(q, sizeof(agc_t));
q->bandwidth = AGC_DEFAULT_BW; agc_reset(q);
q->lock = false;
q->gain = 1.0;
q->y_out = 1.0;
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
@ -52,6 +49,14 @@ void agc_free(agc_t *q) {
bzero(q, sizeof(agc_t)); bzero(q, sizeof(agc_t));
} }
void agc_reset(agc_t *q) {
q->bandwidth = AGC_DEFAULT_BW;
q->lock = false;
q->gain = 1.0;
q->y_out = 1.0;
q->isfirst = true;
}
void agc_set_bandwidth(agc_t *q, float bandwidth) { void agc_set_bandwidth(agc_t *q, float bandwidth) {
q->bandwidth = bandwidth; q->bandwidth = bandwidth;
} }
@ -60,11 +65,20 @@ float agc_get_rssi(agc_t *q) {
return 1.0/q->gain; return 1.0/q->gain;
} }
float agc_get_output_level(agc_t *q) {
return q->y_out;
}
float agc_get_gain(agc_t *q) {
return q->gain;
}
void agc_lock(agc_t *q, bool enable) { void agc_lock(agc_t *q, bool enable) {
q->lock = enable; q->lock = enable;
} }
void agc_push(agc_t *q, cf_t *input, cf_t *output, uint32_t len) { void agc_process(agc_t *q, cf_t *input, cf_t *output, uint32_t len) {
// Apply current gain to input signal // Apply current gain to input signal
vec_sc_prod_cfc(input, q->gain, output, len); vec_sc_prod_cfc(input, q->gain, output, len);
@ -72,8 +86,15 @@ void agc_push(agc_t *q, cf_t *input, cf_t *output, uint32_t len) {
// compute output energy estimate // compute output energy estimate
float y = sqrtf(crealf(vec_dot_prod_conj_ccc(output, output, len))/len); float y = sqrtf(crealf(vec_dot_prod_conj_ccc(output, output, len))/len);
if (q->isfirst) {
q->y_out = y;
q->gain = 1/y;
q->isfirst = false;
} else {
q->y_out = (1-q->bandwidth) * q->y_out + q->bandwidth * y; q->y_out = (1-q->bandwidth) * q->y_out + q->bandwidth * y;
if (!q->lock) { if (!q->lock) {
q->gain *= expf(-0.5*q->bandwidth*logf(q->y_out)); q->gain *= expf(-0.5*q->bandwidth*logf(q->y_out));
} }
} }
DEBUG("AGC gain: %.3f y_out=%.3f, y=%.3f\n", q->gain, q->y_out, y);
}

@ -295,7 +295,7 @@ char *lte_mimotype2str(lte_mimo_type_t type) {
} }
float get_fd(struct lte_band *band, uint32_t earfcn) { float get_fd(struct lte_band *band, uint32_t earfcn) {
if (earfcn > band->earfcn_offset) { if (earfcn >= band->earfcn_offset) {
return band->fd_low_mhz + 0.1*(earfcn - band->earfcn_offset); return band->fd_low_mhz + 0.1*(earfcn - band->earfcn_offset);
} else { } else {
return 0.0; return 0.0;

@ -330,7 +330,8 @@ void pbch_mib_pack(pbch_mib_t *mib, char *msg) {
bit_pack(mib->sfn >> 2, &msg, 8); bit_pack(mib->sfn >> 2, &msg, 8);
} }
void pbch_mib_fprint(FILE *stream, pbch_mib_t *mib) { void pbch_mib_fprint(FILE *stream, pbch_mib_t *mib, uint32_t cell_id) {
printf(" - Cell ID: %d\n", cell_id);
printf(" - Nof ports: %d\n", mib->nof_ports); printf(" - Nof ports: %d\n", mib->nof_ports);
printf(" - PRB: %d\n", mib->nof_prb); printf(" - PRB: %d\n", mib->nof_prb);
printf(" - PHICH Length: %s\n", printf(" - PHICH Length: %s\n",
@ -376,7 +377,20 @@ uint32_t pbch_crc_check(pbch_t *q, char *bits, uint32_t nof_ports) {
char data[40]; char data[40];
memcpy(data, bits, 40 * sizeof(char)); memcpy(data, bits, 40 * sizeof(char));
crc_set_mask(data, nof_ports); crc_set_mask(data, nof_ports);
return crc_checksum(&q->crc, data, 40); int ret = crc_checksum(&q->crc, data, 40);
if (ret == 0) {
uint32_t chkzeros=0;
for (int i=0;i<24 && !chkzeros;i++) {
chkzeros += data[i];
}
if (chkzeros) {
return 0;
} else {
return -1;
}
} else {
return ret;
}
} }
int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, uint32_t src, uint32_t dst, uint32_t n, int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, uint32_t src, uint32_t dst, uint32_t n,
@ -522,8 +536,6 @@ int pbch_decode(pbch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], pbch_mib_t *mi
for (nb = 0; nb < q->frame_idx && !ret; nb++) { for (nb = 0; nb < q->frame_idx && !ret; nb++) {
for (dst = 0; (dst < 4 - nb) && !ret; dst++) { for (dst = 0; (dst < 4 - nb) && !ret; dst++) {
for (src = 0; src < q->frame_idx - nb && !ret; src++) { for (src = 0; src < q->frame_idx - nb && !ret; src++) {
DEBUG("Trying %d blocks at offset %d as subframe mod4 number %d\n",
nb + 1, src, dst);
ret = pbch_decode_frame(q, mib, src, dst, nb + 1, nof_bits, nant); ret = pbch_decode_frame(q, mib, src, dst, nb + 1, nof_bits, nant);
} }

@ -145,6 +145,7 @@ int ue_dl_receive(ue_dl_t *q, cf_t *input, char *data, uint32_t sf_idx, uint32_t
uint32_t nof_locations; uint32_t nof_locations;
uint16_t crc_rem; uint16_t crc_rem;
dci_format_t format; dci_format_t format;
int ret = LIBLTE_ERROR;
/* If we are looking for SI Blocks, search only in appropiate places */ /* If we are looking for SI Blocks, search only in appropiate places */
if ((rnti == SIRNTI && (sfn % 2) == 0 && sf_idx == 5) || if ((rnti == SIRNTI && (sfn % 2) == 0 && sf_idx == 5) ||
@ -226,14 +227,18 @@ int ue_dl_receive(ue_dl_t *q, cf_t *input, char *data, uint32_t sf_idx, uint32_t
} }
} }
if (q->harq_process[0].mcs.mod > 0) { if (q->harq_process[0].mcs.mod > 0) {
if (pdsch_decode(&q->pdsch, q->sf_symbols, q->ce, data, sf_idx, ret = pdsch_decode(&q->pdsch, q->sf_symbols, q->ce, data, sf_idx,
&q->harq_process[0], rvidx)) { &q->harq_process[0], rvidx);
if (ret == LIBLTE_ERROR) {
if (rnti == SIRNTI && rvidx == 1) { if (rnti == SIRNTI && rvidx == 1) {
q->pkt_errors++; q->pkt_errors++;
} else { } else if (rnti != SIRNTI) {
q->pkt_errors++; q->pkt_errors++;
} }
} else { } else if (ret == LIBLTE_ERROR_INVALID_INPUTS) {
fprintf(stderr, "Error calling pdsch_decode()\n");
return LIBLTE_ERROR;
} else if (ret == LIBLTE_SUCCESS) {
if (VERBOSE_ISINFO()) { if (VERBOSE_ISINFO()) {
INFO("Decoded Message: ", 0); INFO("Decoded Message: ", 0);
vec_fprint_hex(stdout, data, ra_dl.mcs.tbs); vec_fprint_hex(stdout, data, ra_dl.mcs.tbs);
@ -241,6 +246,8 @@ int ue_dl_receive(ue_dl_t *q, cf_t *input, char *data, uint32_t sf_idx, uint32_t
} }
if (rnti == SIRNTI && rvidx == 1) { if (rnti == SIRNTI && rvidx == 1) {
q->pkts_total++; q->pkts_total++;
} else if (rnti != SIRNTI) {
q->pkts_total++;
} }
} }
} }
@ -249,7 +256,7 @@ int ue_dl_receive(ue_dl_t *q, cf_t *input, char *data, uint32_t sf_idx, uint32_t
} }
} }
if (crc_rem == rnti) { if (crc_rem == rnti && ret == LIBLTE_SUCCESS) {
return ra_dl.mcs.tbs; return ra_dl.mcs.tbs;
} else { } else {
return 0; return 0;

@ -54,6 +54,29 @@ cf_t dummy[MAX_TIME_OFFSET];
static int mib_decoder_initialize(ue_sync_t *q); static int mib_decoder_initialize(ue_sync_t *q);
static void mib_decoder_free(ue_sync_t *q); static void mib_decoder_free(ue_sync_t *q);
static void update_threshold(ue_sync_t *q) {
int symbol_sz = lte_symbol_sz(q->cell.nof_prb);
if (symbol_sz > 0) {
switch (symbol_sz) {
case 128:
sync_set_threshold(&q->s, 20000, 2000);
break;
case 256:
sync_set_threshold(&q->s, 25000, 2500);
break;
case 512:
sync_set_threshold(&q->s, 38000, 3800);
break;
case 1024:
sync_set_threshold(&q->s, 50000, 5000);
break;
case 2048:
sync_set_threshold(&q->s, 80000, 4000);
}
}
}
int ue_sync_init(ue_sync_t *q, int ue_sync_init(ue_sync_t *q,
double (set_rate_callback)(void*, double), double (set_rate_callback)(void*, double),
int (recv_callback)(void*, void*, uint32_t), int (recv_callback)(void*, void*, uint32_t),
@ -62,7 +85,9 @@ int ue_sync_init(ue_sync_t *q,
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
stream_handler != NULL) stream_handler != NULL &&
set_rate_callback != NULL &&
recv_callback != NULL)
{ {
ret = LIBLTE_ERROR; ret = LIBLTE_ERROR;
@ -80,7 +105,8 @@ int ue_sync_init(ue_sync_t *q,
q->pbch_decoder_enabled = true; q->pbch_decoder_enabled = true;
q->pbch_decode_always = false; q->pbch_decode_always = false;
q->decode_sss_on_track = false; q->decode_sss_on_track = false;
q->change_srate = true;
q->nof_mib_decodes = DEFAULT_NOF_MIB_DECODES;
q->stream = stream_handler; q->stream = stream_handler;
q->recv_callback = recv_callback; q->recv_callback = recv_callback;
q->set_rate_callback = set_rate_callback; q->set_rate_callback = set_rate_callback;
@ -128,7 +154,7 @@ int ue_sync_init(ue_sync_t *q,
} }
} }
sync_set_threshold(&q->s, PSS_THRESHOLD, PSS_THRESHOLD); update_threshold(q);
ret = LIBLTE_SUCCESS; ret = LIBLTE_SUCCESS;
} }
@ -161,10 +187,6 @@ void ue_sync_free(ue_sync_t *q) {
agc_free(&q->agc); agc_free(&q->agc);
} }
void ue_sync_set_threshold(ue_sync_t *q, float threshold) {
sync_set_threshold(&q->s, threshold, threshold/2);
}
lte_cell_t ue_sync_get_cell(ue_sync_t *q) { lte_cell_t ue_sync_get_cell(ue_sync_t *q) {
return q->cell; return q->cell;
} }
@ -181,6 +203,10 @@ ue_sync_state_t ue_sync_get_state(ue_sync_t *q) {
return q->state; return q->state;
} }
void ue_sync_change_srate(ue_sync_t *q, bool enabled) {
q->change_srate = enabled;
}
static int update_srate(ue_sync_t *q) { static int update_srate(ue_sync_t *q) {
struct timeval t[3]; struct timeval t[3];
@ -192,7 +218,7 @@ static int update_srate(ue_sync_t *q) {
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
if (NOF_MIB_DECODES > 1) { if (q->nof_mib_decodes > 1) {
mib_decoder_free(q); mib_decoder_free(q);
if (mib_decoder_initialize(q)) { if (mib_decoder_initialize(q)) {
fprintf(stderr, "Error reinitializing MIB decoder\n"); fprintf(stderr, "Error reinitializing MIB decoder\n");
@ -203,10 +229,12 @@ static int update_srate(ue_sync_t *q) {
// Finally set the new sampling rate // Finally set the new sampling rate
q->set_rate_callback(q->stream, (float) lte_sampling_freq_hz(q->cell.nof_prb)); q->set_rate_callback(q->stream, (float) lte_sampling_freq_hz(q->cell.nof_prb));
update_threshold(q);
ue_sync_reset(q); ue_sync_reset(q);
printf("Set sampling rate %.2f MHz, fft_size=%d, sf_len=%d Texec=%d us\n", INFO("Set sampling rate %.2f MHz, fft_size=%d, sf_len=%d Threshold=%.2f/%.2f Texec=%d us\n",
(float) lte_sampling_freq_hz(q->cell.nof_prb)/1000000, (float) lte_sampling_freq_hz(q->cell.nof_prb)/1000000,
CURRENT_FFTSIZE, CURRENT_SFLEN, (int) t[0].tv_usec); CURRENT_FFTSIZE, CURRENT_SFLEN, q->s.find_threshold, q->s.track_threshold, (int) t[0].tv_usec);
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
@ -239,6 +267,10 @@ void ue_sync_decode_sss_on_track(ue_sync_t *q, bool enabled) {
q->decode_sss_on_track = enabled; q->decode_sss_on_track = enabled;
} }
void ue_sync_set_nof_pbch_decodes(ue_sync_t *q, uint32_t nof_pbch_decodes) {
q->nof_mib_decodes = nof_pbch_decodes;
}
static int mib_decoder_initialize(ue_sync_t *q) { static int mib_decoder_initialize(ue_sync_t *q) {
if (lte_fft_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { if (lte_fft_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
@ -289,9 +321,11 @@ static int mib_decoder_run(ue_sync_t *q) {
q->cell.nof_prb = q->mib.nof_prb; q->cell.nof_prb = q->mib.nof_prb;
if (!q->pbch_decoded) { if (!q->pbch_decoded) {
printf("MIB decoded:\n"); printf("\n\nMIB decoded:\n");
pbch_mib_fprint(stdout, &q->mib); pbch_mib_fprint(stdout, &q->mib, q->cell.id);
if (q->change_srate) {
ret = update_srate(q); ret = update_srate(q);
}
} else { } else {
INFO("MIB decoded #%d SFN: %d\n", q->pbch_decoded, q->mib.sfn); INFO("MIB decoded #%d SFN: %d\n", q->pbch_decoded, q->mib.sfn);
} }
@ -300,7 +334,7 @@ static int mib_decoder_run(ue_sync_t *q) {
pbch_decode_reset(&q->pbch); pbch_decode_reset(&q->pbch);
} else { } else {
INFO("MIB not decoded: %d\n", q->frame_total_cnt); INFO("MIB not decoded: %d\n", q->frame_total_cnt/2);
q->pbch_last_trial = q->frame_total_cnt; q->pbch_last_trial = q->frame_total_cnt;
} }
@ -336,8 +370,8 @@ static int find_peak_ok(ue_sync_t *q) {
q->state = SF_TRACK; q->state = SF_TRACK;
ret = LIBLTE_SUCCESS; ret = LIBLTE_SUCCESS;
INFO("Found peak %d, SF_idx: %d, Cell_id: %d CP: %s\n", INFO("Found peak at %d, value %.3f, SF_idx: %d, Cell_id: %d CP: %s\n",
q->peak_idx, q->sf_idx, q->cell.id, lte_cp_string(q->cell.cp)); q->peak_idx, sync_get_peak_value(&q->s), q->sf_idx, q->cell.id, lte_cp_string(q->cell.cp));
if (q->peak_idx < CURRENT_SFLEN) { if (q->peak_idx < CURRENT_SFLEN) {
q->sf_idx++; q->sf_idx++;
@ -355,7 +389,7 @@ int track_peak_ok(ue_sync_t *q, uint32_t track_idx) {
/* Make sure subframe idx is what we expect */ /* Make sure subframe idx is what we expect */
if ((q->sf_idx != sync_get_slot_id(&q->s)/2) && q->decode_sss_on_track) { if ((q->sf_idx != sync_get_slot_id(&q->s)/2) && q->decode_sss_on_track) {
printf("\nWarning: Expected SF idx %d but got %d!\n", INFO("\nWarning: Expected SF idx %d but got %d!\n",
q->sf_idx, sync_get_slot_id(&q->s)/2); q->sf_idx, sync_get_slot_id(&q->s)/2);
q->sf_idx = sync_get_slot_id(&q->s)/2; q->sf_idx = sync_get_slot_id(&q->s)/2;
} else { } else {
@ -396,7 +430,7 @@ int track_peak_no(ue_sync_t *q) {
printf("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt); printf("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt);
q->state = SF_FIND; q->state = SF_FIND;
} else { } else {
INFO("Tracking peak not found, %d lost\n", (int) q->frame_no_cnt); INFO("Tracking peak not found. Peak %.3f, %d lost\n", sync_get_peak_value(&q->s), (int) q->frame_no_cnt);
} }
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
@ -404,6 +438,7 @@ int track_peak_no(ue_sync_t *q) {
static int receive_samples(ue_sync_t *q) { static int receive_samples(ue_sync_t *q) {
if (q->cell.nof_prb >= 6 && q->cell.nof_prb <= 100) {
/* A negative time offset means there are samples in our buffer for the next subframe, /* A negative time offset means there are samples in our buffer for the next subframe,
because we are sampling too fast. because we are sampling too fast.
*/ */
@ -422,6 +457,9 @@ static int receive_samples(ue_sync_t *q) {
q->time_offset = 0; q->time_offset = 0;
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} else {
return LIBLTE_ERROR_INVALID_INPUTS;
}
} }
int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) { int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
@ -439,9 +477,17 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
return -1; return -1;
} }
agc_push(&q->agc, q->receive_buffer, q->input_buffer, CURRENT_SFLEN); agc_process(&q->agc, q->receive_buffer, q->input_buffer, CURRENT_SFLEN);
switch (q->state) { switch (q->state) {
case SF_AGC:
q->frame_total_cnt++;
if (q->frame_total_cnt >= AGC_NOF_FRAMES) {
q->state = SF_FIND;
q->frame_total_cnt = 0;
}
ret = 0;
break;
case SF_FIND: case SF_FIND:
q->s.sss_en = true; q->s.sss_en = true;
@ -469,6 +515,16 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
fprintf(stderr, "Error processing find peak \n"); fprintf(stderr, "Error processing find peak \n");
} }
} }
} else if (q->peak_idx != 0) {
uint32_t rlen;
if (q->peak_idx < CURRENT_SFLEN/2) {
rlen = CURRENT_SFLEN/2-q->peak_idx;
} else {
rlen = q->peak_idx;
}
if (q->recv_callback(q->stream, q->receive_buffer, rlen) < 0) {
return LIBLTE_ERROR;
}
} }
break; break;
case SF_TRACK: case SF_TRACK:
@ -508,14 +564,14 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
ret = track_peak_no(q); ret = track_peak_no(q);
} }
INFO("TRACK %3d: SF=%d Track_idx=%d Offset=%d CFO: %f\n", INFO("TRACK %3d: Value=%.3f SF=%d Track_idx=%d Offset=%d CFO: %f\n",
(int) q->frame_total_cnt, q->sf_idx, track_idx, q->time_offset, sync_get_cfo(&q->s)); (int) q->frame_total_cnt, sync_get_peak_value(&q->s), q->sf_idx, track_idx, q->time_offset, sync_get_cfo(&q->s));
q->frame_total_cnt++; q->frame_total_cnt++;
if (ret == LIBLTE_ERROR) { if (ret == LIBLTE_ERROR) {
fprintf(stderr, "Error processing tracking peak\n"); fprintf(stderr, "Error processing tracking peak\n");
ue_sync_reset(q); q->state = SF_FIND;
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
} }
@ -527,7 +583,7 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
/* At subframe 0, try to decode PBCH if not yet decoded */ /* At subframe 0, try to decode PBCH if not yet decoded */
if (q->sf_idx == 0) { if (q->sf_idx == 0) {
if(q->pbch_decoder_enabled && if(q->pbch_decoder_enabled &&
(q->pbch_decoded < NOF_MIB_DECODES || q->pbch_decode_always)) (q->pbch_decoded < q->nof_mib_decodes || q->pbch_decode_always))
{ {
mib_decoder_run(q); mib_decoder_run(q);
} else { } else {
@ -537,7 +593,7 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
if (ret == LIBLTE_SUCCESS) { if (ret == LIBLTE_SUCCESS) {
if (q->pbch_decoder_enabled) { if (q->pbch_decoder_enabled) {
if (q->pbch_decoded >= NOF_MIB_DECODES) { if (q->pbch_decoded >= q->nof_mib_decodes) {
ret = 1; ret = 1;
} else { } else {
ret = 0; ret = 0;
@ -554,7 +610,7 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
} }
void ue_sync_reset(ue_sync_t *q) { void ue_sync_reset(ue_sync_t *q) {
q->state = SF_FIND; q->state = SF_AGC;
q->pbch_last_trial = 0; q->pbch_last_trial = 0;
q->frame_ok_cnt = 0; q->frame_ok_cnt = 0;
@ -566,5 +622,7 @@ void ue_sync_reset(ue_sync_t *q) {
#ifdef MEASURE_EXEC_TIME #ifdef MEASURE_EXEC_TIME
q->mean_exec_time = 0; q->mean_exec_time = 0;
#endif #endif
pbch_decode_reset(&q->pbch);
} }

@ -222,11 +222,11 @@ int main(int argc, char **argv) {
} else { } else {
if (mib.nof_ports == 2 && mib.nof_prb == 50 && mib.phich_length == PHICH_NORM if (mib.nof_ports == 2 && mib.nof_prb == 50 && mib.phich_length == PHICH_NORM
&& mib.phich_resources == R_1 && mib.sfn == 28) { && mib.phich_resources == R_1 && mib.sfn == 28) {
pbch_mib_fprint(stdout, &mib); pbch_mib_fprint(stdout, &mib, cell.id);
printf("This is the signal.1.92M.dat file\n"); printf("This is the signal.1.92M.dat file\n");
exit(0); exit(0);
} else { } else {
pbch_mib_fprint(stdout, &mib); pbch_mib_fprint(stdout, &mib, cell.id);
printf("This is an unknown file\n"); printf("This is an unknown file\n");
exit(-1); exit(-1);
} }

@ -138,7 +138,7 @@ int main(int argc, char **argv) {
printf("OK\n"); printf("OK\n");
exit(0); exit(0);
} else { } else {
pbch_mib_fprint(stdout, &mib_rx); pbch_mib_fprint(stdout, &mib_rx, cell.id);
exit(-1); exit(-1);
} }
} }

@ -173,13 +173,7 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (threshold > 0.0) {
ue_sync_set_threshold(&s, threshold);
}
ue_sync_pbch_enable(&s, true); ue_sync_pbch_enable(&s, true);
// ue_sync_pbch_always(&s, true);
// ue_sync_decode_sss_on_track(&s, true);
signal_detected = true; signal_detected = true;
frame_cnt = 0; frame_cnt = 0;

@ -262,7 +262,7 @@ int pss_synch_find_pss(pss_synch_t *q, cf_t *input,
vec_abs_cf(q->conv_output, q->conv_abs, 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); corr_peak_pos = vec_max_fi(q->conv_abs, conv_output_len);
if (corr_peak_value) { if (corr_peak_value) {
*corr_peak_value = q->conv_abs[corr_peak_pos] / conv_output_len; *corr_peak_value = q->conv_abs[corr_peak_pos];
} }
if (corr_mean_value) { if (corr_mean_value) {
*corr_mean_value = vec_acc_ff(q->conv_abs, conv_output_len) *corr_mean_value = vec_acc_ff(q->conv_abs, conv_output_len)

@ -299,16 +299,18 @@ int sync_track(sync_t *q, cf_t *input, uint32_t offset, uint32_t *peak_position)
DEBUG("PSS possible tracking peak pos=%d peak=%.2f threshold=%.2f\n", DEBUG("PSS possible tracking peak pos=%d peak=%.2f threshold=%.2f\n",
peak_pos, peak_value, q->track_threshold); peak_pos, peak_value, q->track_threshold);
if (peak_value > q->track_threshold) { if (q->peak_value > q->track_threshold) {
if (offset + peak_pos > q->fft_size) {
q->cfo = pss_synch_cfo_compute(&q->pss_track, &input[offset+peak_pos-q->fft_size]); q->cfo = pss_synch_cfo_compute(&q->pss_track, &input[offset+peak_pos-q->fft_size]);
if (q->sss_en) { if (q->sss_en) {
if (sync_sss(q, input, offset + peak_pos, false) < 0) { if (sync_sss(q, input, offset + peak_pos, false) < 0) {
fprintf(stderr, "Error synchronizing with SSS\n"); fprintf(stderr, "Error synchronizing with SSS\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
} }
} else {
printf("Warning: no space for CFO computation\n");
}
if (peak_position) { if (peak_position) {
*peak_position = peak_pos; *peak_position = peak_pos;
} }
@ -317,6 +319,7 @@ int sync_track(sync_t *q, cf_t *input, uint32_t offset, uint32_t *peak_position)
ret = LIBLTE_SUCCESS; ret = LIBLTE_SUCCESS;
} }
} }
return ret; return ret;
} }
@ -351,12 +354,14 @@ int sync_find(sync_t *q, cf_t *input, uint32_t *peak_position) {
} }
} }
if (peak_pos[N_id_2] > q->fft_size) {
if (q->pss_mode == ABSOLUTE) { if (q->pss_mode == ABSOLUTE) {
q->peak_value = peak_value[N_id_2]; q->peak_value = peak_value[N_id_2];
} else { } else {
q->peak_value = peak_value[N_id_2] / mean_value[N_id_2]; q->peak_value = peak_value[N_id_2] / mean_value[N_id_2];
} }
if (peak_position) {
*peak_position = 0;
} }
DEBUG("PSS possible peak N_id_2=%d, pos=%d peak=%.2f threshold=%.2f\n", DEBUG("PSS possible peak N_id_2=%d, pos=%d peak=%.2f threshold=%.2f\n",
@ -364,6 +369,9 @@ int sync_find(sync_t *q, cf_t *input, uint32_t *peak_position) {
/* If peak detected */ /* If peak detected */
if (q->peak_value > q->find_threshold) { if (q->peak_value > q->find_threshold) {
if (peak_pos[N_id_2] > q->fft_size &&
peak_pos[N_id_2] + q->fft_size < q->find_frame_size)
{
q->N_id_2 = N_id_2; q->N_id_2 = N_id_2;
pss_synch_set_N_id_2(&q->pss_find, q->N_id_2); pss_synch_set_N_id_2(&q->pss_find, q->N_id_2);
q->cfo = pss_synch_cfo_compute(&q->pss_find, &input[peak_pos[N_id_2]-q->fft_size]); q->cfo = pss_synch_cfo_compute(&q->pss_find, &input[peak_pos[N_id_2]-q->fft_size]);
@ -377,6 +385,7 @@ int sync_find(sync_t *q, cf_t *input, uint32_t *peak_position) {
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
} }
}
if (peak_position) { if (peak_position) {
*peak_position = peak_pos[N_id_2]; *peak_position = peak_pos[N_id_2];

@ -107,11 +107,11 @@ int main(int argc, char **argv) {
return -1; return -1;
} }
sync_set_threshold(&sync, 20, 10); sync_set_threshold(&sync, 1, 1);
if (cell_id == -1) { if (cell_id == -1) {
cid = 0; cid = 0;
max_cid = 149; max_cid = 49;
} else { } else {
cid = cell_id; cid = cell_id;
max_cid = cell_id; max_cid = cell_id;

@ -362,8 +362,7 @@ float vec_avg_power_cf(cf_t *x, uint32_t len) {
int j; int j;
float power = 0; float power = 0;
for (j=0;j<len;j++) { for (j=0;j<len;j++) {
power += (__real__ x[j]) * (__real__ x[j]) + power += crealf(x[j]*conjf(x[j]));
(__imag__ x[j]) * (__imag__ x[j]);
} }
return power / len; return power / len;
} }

Loading…
Cancel
Save