mirror of https://github.com/PentHertz/srsLTE.git
Fixed some issues in MIB detection and in cell search
This commit is contained in:
parent
60c559e351
commit
bd117093b4
|
@ -84,6 +84,9 @@ IF(${CUHD_FIND} GREATER -1)
|
||||||
add_executable(cell_search cell_search.c cell_search_utils.c)
|
add_executable(cell_search cell_search.c cell_search_utils.c)
|
||||||
target_link_libraries(cell_search lte_phy cuhd )
|
target_link_libraries(cell_search lte_phy cuhd )
|
||||||
|
|
||||||
|
add_executable(cell_measurement cell_measurement.c cell_search_utils.c)
|
||||||
|
target_link_libraries(cell_measurement cuhd lte_phy)
|
||||||
|
|
||||||
MESSAGE(STATUS " UHD examples will be installed.")
|
MESSAGE(STATUS " UHD examples will be installed.")
|
||||||
|
|
||||||
ELSE(${CUHD_FIND} GREATER -1)
|
ELSE(${CUHD_FIND} GREATER -1)
|
||||||
|
|
|
@ -121,7 +121,6 @@ int main(int argc, char **argv) {
|
||||||
void *uhd;
|
void *uhd;
|
||||||
ue_celldetect_t s;
|
ue_celldetect_t s;
|
||||||
ue_celldetect_result_t found_cells[3];
|
ue_celldetect_result_t found_cells[3];
|
||||||
cf_t *buffer;
|
|
||||||
int nof_freqs;
|
int nof_freqs;
|
||||||
lte_earfcn_t channels[MAX_EARFCN];
|
lte_earfcn_t channels[MAX_EARFCN];
|
||||||
uint32_t freq;
|
uint32_t freq;
|
||||||
|
@ -142,12 +141,6 @@ int main(int argc, char **argv) {
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = vec_malloc(sizeof(cf_t) * 96000);
|
|
||||||
if (!buffer) {
|
|
||||||
perror("malloc");
|
|
||||||
return LIBLTE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ue_celldetect_init(&s)) {
|
if (ue_celldetect_init(&s)) {
|
||||||
fprintf(stderr, "Error initiating UE sync module\n");
|
fprintf(stderr, "Error initiating UE sync module\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
@ -178,7 +171,7 @@ int main(int argc, char **argv) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
n = find_cell(uhd, &s, buffer, found_cells);
|
n = find_all_cells(uhd, found_cells);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
fprintf(stderr, "Error searching cell\n");
|
fprintf(stderr, "Error searching cell\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
@ -186,7 +179,7 @@ int main(int argc, char **argv) {
|
||||||
if (n == CS_CELL_DETECTED) {
|
if (n == CS_CELL_DETECTED) {
|
||||||
for (int i=0;i<3;i++) {
|
for (int i=0;i<3;i++) {
|
||||||
if (found_cells[i].peak > threshold/2) {
|
if (found_cells[i].peak > threshold/2) {
|
||||||
if (decode_pbch(uhd, buffer, &found_cells[i], nof_frames_total, &mib)) {
|
if (decode_pbch(uhd, &found_cells[i], nof_frames_total, &mib)) {
|
||||||
fprintf(stderr, "Error decoding PBCH\n");
|
fprintf(stderr, "Error decoding PBCH\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
@ -194,6 +187,8 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("\nBye\n");
|
||||||
|
|
||||||
ue_celldetect_free(&s);
|
ue_celldetect_free(&s);
|
||||||
cuhd_close(uhd);
|
cuhd_close(uhd);
|
||||||
|
|
|
@ -40,19 +40,26 @@
|
||||||
#ifndef DISABLE_UHD
|
#ifndef DISABLE_UHD
|
||||||
#include "liblte/cuhd/cuhd.h"
|
#include "liblte/cuhd/cuhd.h"
|
||||||
|
|
||||||
int decode_pbch(void *uhd, cf_t *buffer, ue_celldetect_result_t *found_cell, uint32_t nof_frames_total, pbch_mib_t *mib)
|
int decode_pbch(void *uhd, ue_celldetect_result_t *found_cell, uint32_t nof_frames_total, pbch_mib_t *mib)
|
||||||
{
|
{
|
||||||
ue_mib_t uemib;
|
ue_mib_t uemib;
|
||||||
int n;
|
int n;
|
||||||
|
int ret = LIBLTE_ERROR;
|
||||||
|
|
||||||
|
uint32_t nof_frames = 0;
|
||||||
|
uint32_t flen = MIB_FRAME_SIZE;
|
||||||
|
|
||||||
|
cf_t *buffer = vec_malloc(sizeof(cf_t) * flen);
|
||||||
|
if (!buffer) {
|
||||||
|
perror("malloc");
|
||||||
|
goto free_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
bzero(mib, sizeof(pbch_mib_t));
|
bzero(mib, sizeof(pbch_mib_t));
|
||||||
|
|
||||||
uint32_t nof_frames = 0;
|
|
||||||
uint32_t flen = MIB_FRAME_SIZE;
|
|
||||||
|
|
||||||
if (ue_mib_init(&uemib, found_cell->cell_id, found_cell->cp)) {
|
if (ue_mib_init(&uemib, found_cell->cell_id, found_cell->cp)) {
|
||||||
fprintf(stderr, "Error initiating PBCH decoder\n");
|
fprintf(stderr, "Error initiating PBCH decoder\n");
|
||||||
return LIBLTE_ERROR;
|
goto free_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO("Setting sampling frequency 1.92 MHz for PBCH decoding\n", 0);
|
INFO("Setting sampling frequency 1.92 MHz for PBCH decoding\n", 0);
|
||||||
|
@ -63,95 +70,203 @@ int decode_pbch(void *uhd, cf_t *buffer, ue_celldetect_result_t *found_cell, uin
|
||||||
do {
|
do {
|
||||||
if (cuhd_recv(uhd, buffer, flen, 1)<0) {
|
if (cuhd_recv(uhd, buffer, flen, 1)<0) {
|
||||||
fprintf(stderr, "Error receiving from USRP\n");
|
fprintf(stderr, "Error receiving from USRP\n");
|
||||||
return LIBLTE_ERROR;
|
goto free_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO("Calling ue_mib_decode() %d/%d\n", nof_frames, nof_frames_total);
|
DEBUG("Calling ue_mib_decode() %d/%d\n", nof_frames, nof_frames_total);
|
||||||
|
|
||||||
n = ue_mib_decode(&uemib, buffer, flen, mib);
|
n = ue_mib_decode(&uemib, buffer, flen, mib);
|
||||||
if (n == LIBLTE_ERROR || n == LIBLTE_ERROR_INVALID_INPUTS) {
|
if (n == LIBLTE_ERROR || n == LIBLTE_ERROR_INVALID_INPUTS) {
|
||||||
fprintf(stderr, "Error calling ue_mib_decode()\n");
|
fprintf(stderr, "Error calling ue_mib_decode()\n");
|
||||||
return LIBLTE_ERROR;
|
goto free_and_exit;
|
||||||
}
|
}
|
||||||
if (n == MIB_FRAME_UNALIGNED) {
|
if (n == MIB_FRAME_UNALIGNED) {
|
||||||
printf("Realigning frame\n");
|
printf("Realigning frame\n");
|
||||||
if (cuhd_recv(uhd, buffer, flen/2, 1)<0) {
|
if (cuhd_recv(uhd, buffer, 1500, 1)<0) {
|
||||||
fprintf(stderr, "Error receiving from USRP\n");
|
fprintf(stderr, "Error receiving from USRP\n");
|
||||||
return LIBLTE_ERROR;
|
goto free_and_exit;
|
||||||
}
|
}
|
||||||
|
bzero(buffer, flen * sizeof(cf_t));
|
||||||
}
|
}
|
||||||
nof_frames++;
|
nof_frames++;
|
||||||
} while (n != MIB_FOUND && nof_frames < 2*nof_frames_total);
|
} while (n != MIB_FOUND && nof_frames < 2*nof_frames_total);
|
||||||
|
|
||||||
if (n == MIB_FOUND) {
|
if (n == MIB_FOUND) {
|
||||||
printf("\n\nMIB decoded in %d ms (%d half frames)\n", nof_frames*5, nof_frames);
|
printf("\n\nMIB decoded in %d ms (%d half frames)\n", nof_frames*5, nof_frames);
|
||||||
pbch_mib_fprint(stdout, mib, found_cell->cell_id);
|
pbch_mib_fprint(stdout, mib, found_cell->cell_id);
|
||||||
|
ret = LIBLTE_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
printf("\nCould not decode MIB\n");
|
ret = LIBLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_and_exit:
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
cuhd_stop_rx_stream(uhd);
|
cuhd_stop_rx_stream(uhd);
|
||||||
cuhd_flush_buffer(uhd);
|
cuhd_flush_buffer(uhd);
|
||||||
|
|
||||||
ue_mib_free(&uemib);
|
ue_mib_free(&uemib);
|
||||||
|
|
||||||
return LIBLTE_SUCCESS;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int find_cell(void *uhd, ue_celldetect_t *s, cf_t *buffer, ue_celldetect_result_t found_cell[3])
|
int find_cell(void *uhd, ue_celldetect_result_t *found_cell, uint32_t N_id_2)
|
||||||
{
|
{
|
||||||
int n;
|
int ret = LIBLTE_ERROR;
|
||||||
|
ue_celldetect_t cd;
|
||||||
|
|
||||||
|
cf_t *buffer = vec_malloc(sizeof(cf_t) * 96000);
|
||||||
|
if (!buffer) {
|
||||||
|
perror("malloc");
|
||||||
|
goto free_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ue_celldetect_init(&cd)) {
|
||||||
|
fprintf(stderr, "Error initiating UE cell detect\n");
|
||||||
|
goto free_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ue_celldetect_set_nof_frames_detected(&cd, 50);
|
||||||
|
|
||||||
|
ue_celldetect_set_nof_frames_total(&cd, 500);
|
||||||
|
|
||||||
INFO("Setting sampling frequency 960 KHz for PSS search\n", 0);
|
INFO("Setting sampling frequency 960 KHz for PSS search\n", 0);
|
||||||
cuhd_set_rx_srate(uhd, 960000.0);
|
cuhd_set_rx_srate(uhd, 960000.0);
|
||||||
INFO("Starting receiver...\n", 0);
|
INFO("Starting receiver...\n", 0);
|
||||||
cuhd_start_rx_stream(uhd);
|
cuhd_start_rx_stream(uhd);
|
||||||
|
|
||||||
uint32_t nof_scanned_cells = 0;
|
|
||||||
uint32_t flen = 4800;
|
uint32_t flen = 4800;
|
||||||
int nof_detected_cells = 0;
|
int n;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
if (cuhd_recv(uhd, buffer, flen, 1)<0) {
|
if (cuhd_recv(uhd, buffer, flen, 1)<0) {
|
||||||
fprintf(stderr, "Error receiving from USRP\n");
|
fprintf(stderr, "Error receiving from USRP\n");
|
||||||
return LIBLTE_ERROR;
|
goto free_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG("Scanning cell at N_id_2=%d\n",N_id_2);
|
||||||
|
|
||||||
n = ue_celldetect_scan(s, buffer, flen, &found_cell[nof_scanned_cells]);
|
n = ue_celldetect_scan(&cd, buffer, flen, found_cell, N_id_2);
|
||||||
switch(n) {
|
switch(n) {
|
||||||
case CS_FRAME_UNALIGNED:
|
case CS_FRAME_UNALIGNED:
|
||||||
printf("Realigning frame\n");
|
printf("Realigning frame\n");
|
||||||
if (cuhd_recv(uhd, buffer, flen/2, 1)<0) {
|
if (cuhd_recv(uhd, buffer, flen/2, 1)<0) {
|
||||||
fprintf(stderr, "Error receiving from USRP\n");
|
fprintf(stderr, "Error receiving from USRP\n");
|
||||||
return LIBLTE_ERROR;
|
goto free_and_exit;
|
||||||
}
|
}
|
||||||
return LIBLTE_ERROR;
|
/* FIXME: What should we do here?? */
|
||||||
|
ret = -1;
|
||||||
|
goto free_and_exit;
|
||||||
case CS_CELL_DETECTED:
|
case CS_CELL_DETECTED:
|
||||||
nof_detected_cells++;
|
if (found_cell->peak > 0) {
|
||||||
if (found_cell[nof_scanned_cells].peak > 0) {
|
|
||||||
printf("\n\tCELL ID: %d, CP: %s, Peak: %.2f, Mode: %d/%d\n",
|
printf("\n\tCELL ID: %d, CP: %s, Peak: %.2f, Mode: %d/%d\n",
|
||||||
found_cell[nof_scanned_cells].cell_id,
|
found_cell->cell_id,
|
||||||
lte_cp_string(found_cell[nof_scanned_cells].cp),
|
lte_cp_string(found_cell->cp),
|
||||||
found_cell[nof_scanned_cells].peak, found_cell[nof_scanned_cells].mode,
|
found_cell->peak, found_cell->mode,
|
||||||
s->nof_frames_detected);
|
cd.nof_frames_detected);
|
||||||
}
|
}
|
||||||
|
|
||||||
nof_scanned_cells++;
|
ret = 1;
|
||||||
|
INFO("Cell found at N_id_2=%d\n",N_id_2);
|
||||||
break;
|
break;
|
||||||
case CS_CELL_NOT_DETECTED:
|
case CS_CELL_NOT_DETECTED:
|
||||||
nof_scanned_cells++;
|
ret = 0;
|
||||||
|
DEBUG("No cell found at N_id_2=%d\n",N_id_2);
|
||||||
break;
|
break;
|
||||||
case LIBLTE_ERROR:
|
case LIBLTE_ERROR:
|
||||||
case LIBLTE_ERROR_INVALID_INPUTS:
|
case LIBLTE_ERROR_INVALID_INPUTS:
|
||||||
|
ret = LIBLTE_ERROR;
|
||||||
fprintf(stderr, "Error calling cellsearch_scan()\n");
|
fprintf(stderr, "Error calling cellsearch_scan()\n");
|
||||||
return LIBLTE_ERROR;
|
goto free_and_exit;
|
||||||
}
|
}
|
||||||
} while(nof_scanned_cells < 3);
|
|
||||||
|
} while(n == 0);
|
||||||
|
|
||||||
|
free_and_exit:
|
||||||
|
free(buffer);
|
||||||
|
ue_celldetect_free(&cd);
|
||||||
INFO("Stopping receiver...\n", 0);
|
INFO("Stopping receiver...\n", 0);
|
||||||
cuhd_stop_rx_stream(uhd);
|
cuhd_stop_rx_stream(uhd);
|
||||||
cuhd_flush_buffer(uhd);
|
cuhd_flush_buffer(uhd);
|
||||||
|
|
||||||
return nof_detected_cells;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int find_all_cells(void *uhd, ue_celldetect_result_t found_cell[3])
|
||||||
|
{
|
||||||
|
|
||||||
|
uint32_t N_id_2;
|
||||||
|
int ret;
|
||||||
|
int nof_detected_cells = 0;
|
||||||
|
|
||||||
|
for (N_id_2=0;N_id_2<3;N_id_2++) {
|
||||||
|
ret = find_cell(uhd, &found_cell[N_id_2], N_id_2);
|
||||||
|
if (ret == 1) {
|
||||||
|
nof_detected_cells++;
|
||||||
|
} else if (ret == LIBLTE_ERROR) {
|
||||||
|
return LIBLTE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nof_detected_cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cell_search(void *uhd, int force_N_id_2, lte_cell_t *cell, pbch_mib_t *mib)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ue_celldetect_result_t found_cells[3];
|
||||||
|
bzero(found_cells, 3*sizeof(ue_celldetect_result_t));
|
||||||
|
|
||||||
|
if (force_N_id_2 >= 0) {
|
||||||
|
ret = find_cell(uhd, &found_cells[force_N_id_2], force_N_id_2);
|
||||||
|
} else {
|
||||||
|
ret = find_all_cells(uhd, found_cells);
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "Error searching cell\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int max_peak_cell = 0;
|
||||||
|
float max_peak_value = -1.0;
|
||||||
|
if (ret > 0) {
|
||||||
|
if (force_N_id_2 >= 0) {
|
||||||
|
max_peak_cell = force_N_id_2;
|
||||||
|
} else {
|
||||||
|
for (int i=0;i<3;i++) {
|
||||||
|
if (found_cells[i].peak > max_peak_value) {
|
||||||
|
max_peak_value = found_cells[i].peak;
|
||||||
|
max_peak_cell = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Decoding PBCH for cell %d (N_id_2=%d)\n", found_cells[max_peak_cell].cell_id, max_peak_cell);
|
||||||
|
if (decode_pbch(uhd, &found_cells[max_peak_cell], 400, mib)) {
|
||||||
|
fprintf(stderr, "Could not decode PBCH from CELL ID %d\n", found_cells[max_peak_cell].cell_id);
|
||||||
|
return LIBLTE_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Could not find any cell in this frequency\n");
|
||||||
|
return LIBLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell->cp = found_cells[max_peak_cell].cp;
|
||||||
|
cell->id = found_cells[max_peak_cell].cell_id;
|
||||||
|
cell->nof_prb = mib->nof_prb;
|
||||||
|
cell->nof_ports = mib->nof_ports;
|
||||||
|
|
||||||
|
/* set sampling frequency */
|
||||||
|
int srate = lte_sampling_freq_hz(cell->nof_prb);
|
||||||
|
if (srate != -1) {
|
||||||
|
cuhd_set_rx_srate(uhd, (double) srate);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid number of PRB %d\n", cell->nof_prb);
|
||||||
|
return LIBLTE_ERROR;
|
||||||
|
}
|
||||||
|
return LIBLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,12 +29,18 @@
|
||||||
#include "liblte/phy/phy.h"
|
#include "liblte/phy/phy.h"
|
||||||
|
|
||||||
int decode_pbch(void *uhd,
|
int decode_pbch(void *uhd,
|
||||||
cf_t *buffer,
|
|
||||||
ue_celldetect_result_t *found_cell,
|
ue_celldetect_result_t *found_cell,
|
||||||
uint32_t nof_frames_total,
|
uint32_t nof_frames_total,
|
||||||
pbch_mib_t *mib);
|
pbch_mib_t *mib);
|
||||||
|
|
||||||
|
int find_all_cells(void *uhd,
|
||||||
|
ue_celldetect_result_t found_cell[3]);
|
||||||
|
|
||||||
int find_cell(void *uhd,
|
int find_cell(void *uhd,
|
||||||
ue_celldetect_t *s,
|
ue_celldetect_result_t *found_cell,
|
||||||
cf_t *buffer,
|
uint32_t N_id_2);
|
||||||
ue_celldetect_result_t found_cell[3]);
|
|
||||||
|
int cell_search(void *uhd,
|
||||||
|
int force_N_id_2,
|
||||||
|
lte_cell_t *cell,
|
||||||
|
pbch_mib_t *mib);
|
|
@ -83,74 +83,27 @@ int iodev_init(iodev_t *q, iodev_cfg_t *config, lte_cell_t *cell, pbch_mib_t *mi
|
||||||
q->sf_idx = 9;
|
q->sf_idx = 9;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
#ifndef DISABLE_UHD
|
|
||||||
|
#ifndef DISABLE_UHD
|
||||||
|
|
||||||
printf("Opening UHD device...\n");
|
printf("Opening UHD device...\n");
|
||||||
if (cuhd_open(config->uhd_args, &q->uhd)) {
|
if (cuhd_open(config->uhd_args, &q->uhd)) {
|
||||||
fprintf(stderr, "Error opening uhd\n");
|
fprintf(stderr, "Error opening uhd\n");
|
||||||
return LIBLTE_ERROR;
|
return LIBLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
/* Set receiver gain */
|
||||||
cuhd_set_rx_gain(q->uhd, config->uhd_gain);
|
cuhd_set_rx_gain(q->uhd, config->uhd_gain);
|
||||||
|
|
||||||
/* set receiver frequency */
|
/* set receiver frequency */
|
||||||
cuhd_set_rx_freq(q->uhd, (double) config->uhd_freq);
|
cuhd_set_rx_freq(q->uhd, (double) config->uhd_freq);
|
||||||
|
|
||||||
cuhd_rx_wait_lo_locked(q->uhd);
|
cuhd_rx_wait_lo_locked(q->uhd);
|
||||||
DEBUG("Set uhd_freq to %.3f MHz\n", (double ) config->uhd_freq);
|
DEBUG("Set uhd_freq to %.3f MHz\n", (double ) config->uhd_freq);
|
||||||
|
|
||||||
int n;
|
if (cell_search(q->uhd, config->force_N_id_2, cell, mib)) {
|
||||||
ue_celldetect_t cd;
|
fprintf(stderr, "Cell not found\n");
|
||||||
ue_celldetect_result_t found_cells[3];
|
return LIBLTE_ERROR;
|
||||||
|
|
||||||
cf_t *buffer = vec_malloc(sizeof(cf_t) * 96000);
|
|
||||||
if (!buffer) {
|
|
||||||
perror("malloc");
|
|
||||||
return LIBLTE_ERROR;
|
|
||||||
}
|
|
||||||
if (ue_celldetect_init(&cd)) {
|
|
||||||
fprintf(stderr, "Error initiating UE cell detect\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
n = find_cell(q->uhd, &cd, buffer, found_cells);
|
|
||||||
if (n < 0) {
|
|
||||||
fprintf(stderr, "Error searching cell\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int max_peak_cell = 0;
|
|
||||||
float max_peak_value = -1.0;
|
|
||||||
if (n > 0) {
|
|
||||||
for (int i=0;i<3;i++) {
|
|
||||||
if (found_cells[i].peak > max_peak_value) {
|
|
||||||
max_peak_value = found_cells[i].peak;
|
|
||||||
max_peak_cell = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (decode_pbch(q->uhd, buffer, &found_cells[max_peak_cell], 400, mib)) {
|
|
||||||
fprintf(stderr, "Could not decode PBCH from CELL ID %d\n", found_cells[max_peak_cell].cell_id);
|
|
||||||
return LIBLTE_ERROR;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Could not find any cell in this frequency\n");
|
|
||||||
return LIBLTE_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
cell->cp = found_cells[max_peak_cell].cp;
|
|
||||||
cell->id = found_cells[max_peak_cell].cell_id;
|
|
||||||
cell->nof_prb = mib->nof_prb;
|
|
||||||
cell->nof_ports = mib->nof_ports;
|
|
||||||
|
|
||||||
/* set sampling frequency */
|
|
||||||
int srate = lte_sampling_freq_hz(cell->nof_prb);
|
|
||||||
if (srate != -1) {
|
|
||||||
cuhd_set_rx_srate(q->uhd, (double) srate);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Invalid number of PRB %d\n", cell->nof_prb);
|
|
||||||
return LIBLTE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG("Starting receiver...\n", 0);
|
|
||||||
cuhd_start_rx_stream(q->uhd);
|
cuhd_start_rx_stream(q->uhd);
|
||||||
|
|
||||||
if (ue_sync_init(&q->sframe, *cell, cuhd_recv_wrapper, q->uhd)) {
|
if (ue_sync_init(&q->sframe, *cell, cuhd_recv_wrapper, q->uhd)) {
|
||||||
|
@ -158,9 +111,6 @@ int iodev_init(iodev_t *q, iodev_cfg_t *config, lte_cell_t *cell, pbch_mib_t *mi
|
||||||
return LIBLTE_ERROR;
|
return LIBLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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(&q->sframe, true);
|
|
||||||
|
|
||||||
// Here, the subframe length and input buffer is managed by ue_sync
|
// Here, the subframe length and input buffer is managed by ue_sync
|
||||||
q->mode = UHD;
|
q->mode = UHD;
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ typedef struct LIBLTE_API {
|
||||||
uint32_t cell_id_file;
|
uint32_t cell_id_file;
|
||||||
uint32_t nof_prb_file;
|
uint32_t nof_prb_file;
|
||||||
uint32_t nof_ports_file;
|
uint32_t nof_ports_file;
|
||||||
|
int force_N_id_2;
|
||||||
|
|
||||||
float uhd_freq;
|
float uhd_freq;
|
||||||
float uhd_gain;
|
float uhd_gain;
|
||||||
|
|
|
@ -68,13 +68,14 @@ void args_default(prog_args_t *args) {
|
||||||
args->disable_plots = false;
|
args->disable_plots = false;
|
||||||
args->io_config.find_threshold = -1.0;
|
args->io_config.find_threshold = -1.0;
|
||||||
args->io_config.input_file_name = NULL;
|
args->io_config.input_file_name = NULL;
|
||||||
|
args->io_config.force_N_id_2 = -1; // Pick the best
|
||||||
args->io_config.uhd_args = "";
|
args->io_config.uhd_args = "";
|
||||||
args->io_config.uhd_freq = -1.0;
|
args->io_config.uhd_freq = -1.0;
|
||||||
args->io_config.uhd_gain = 60.0;
|
args->io_config.uhd_gain = 60.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage(prog_args_t *args, char *prog) {
|
void usage(prog_args_t *args, char *prog) {
|
||||||
printf("Usage: %s [cargfndvtb] [-i input_file | -f rx_frequency (in Hz)]\n", prog);
|
printf("Usage: %s [cargndvtbl] [-i input_file | -f rx_frequency (in Hz)]\n", prog);
|
||||||
printf("\t-c cell_id if reading from file [Default %d]\n", args->io_config.cell_id_file);
|
printf("\t-c cell_id if reading from file [Default %d]\n", args->io_config.cell_id_file);
|
||||||
printf("\t-p nof_prb if reading from file [Default %d]\n", args->io_config.nof_prb_file);
|
printf("\t-p nof_prb if reading from file [Default %d]\n", args->io_config.nof_prb_file);
|
||||||
printf("\t-o nof_ports if reading from file [Default %d]\n", args->io_config.nof_ports_file);
|
printf("\t-o nof_ports if reading from file [Default %d]\n", args->io_config.nof_ports_file);
|
||||||
|
@ -85,6 +86,7 @@ void usage(prog_args_t *args, char *prog) {
|
||||||
#else
|
#else
|
||||||
printf("\t UHD is disabled. CUHD library not available\n");
|
printf("\t UHD is disabled. CUHD library not available\n");
|
||||||
#endif
|
#endif
|
||||||
|
printf("\t-l Force N_id_2 [Default best]\n");
|
||||||
printf("\t-b Decode PBCH only [Default All channels]\n");
|
printf("\t-b Decode PBCH only [Default All channels]\n");
|
||||||
printf("\t-n nof_subframes [Default %d]\n", args->nof_subframes);
|
printf("\t-n nof_subframes [Default %d]\n", args->nof_subframes);
|
||||||
printf("\t-t PSS threshold [Default %f]\n", args->io_config.find_threshold);
|
printf("\t-t PSS threshold [Default %f]\n", args->io_config.find_threshold);
|
||||||
|
@ -99,7 +101,7 @@ void usage(prog_args_t *args, char *prog) {
|
||||||
void parse_args(prog_args_t *args, int argc, char **argv) {
|
void parse_args(prog_args_t *args, int argc, char **argv) {
|
||||||
int opt;
|
int opt;
|
||||||
args_default(args);
|
args_default(args);
|
||||||
while ((opt = getopt(argc, argv, "icagfndvtbpro")) != -1) {
|
while ((opt = getopt(argc, argv, "icagfndvtbprol")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'i':
|
case 'i':
|
||||||
args->io_config.input_file_name = argv[optind];
|
args->io_config.input_file_name = argv[optind];
|
||||||
|
@ -128,6 +130,9 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
|
||||||
case 'n':
|
case 'n':
|
||||||
args->nof_subframes = atoi(argv[optind]);
|
args->nof_subframes = atoi(argv[optind]);
|
||||||
break;
|
break;
|
||||||
|
case 'l':
|
||||||
|
args->io_config.force_N_id_2 = atoi(argv[optind]);
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
args->rnti= atoi(argv[optind]);
|
args->rnti= atoi(argv[optind]);
|
||||||
break;
|
break;
|
||||||
|
@ -144,6 +149,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
|
||||||
}
|
}
|
||||||
if (args->io_config.uhd_freq < 0 && args->io_config.input_file_name == NULL) {
|
if (args->io_config.uhd_freq < 0 && args->io_config.input_file_name == NULL) {
|
||||||
usage(args, argv[0]);
|
usage(args, argv[0]);
|
||||||
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
@ -177,10 +183,6 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Setup SIGINT handler */
|
|
||||||
printf("\n --- Press Ctrl+C to exit --- \n");
|
|
||||||
signal(SIGINT, sigintHandler);
|
|
||||||
|
|
||||||
/* Initialize subframe counter */
|
/* Initialize subframe counter */
|
||||||
sf_cnt = 0;
|
sf_cnt = 0;
|
||||||
|
|
||||||
|
@ -225,6 +227,7 @@ int main(int argc, char **argv) {
|
||||||
(int) ue_dl.pkt_errors, (int) ue_dl.pkts_total, (int) ue_dl.nof_trials,
|
(int) ue_dl.pkt_errors, (int) ue_dl.pkts_total, (int) ue_dl.nof_trials,
|
||||||
(float) ue_dl.pkt_errors / ue_dl.pkts_total,
|
(float) ue_dl.pkt_errors / ue_dl.pkts_total,
|
||||||
mean_exec_time);
|
mean_exec_time);
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifndef DISABLE_GRAPHICS
|
#ifndef DISABLE_GRAPHICS
|
||||||
if (!prog_args.disable_plots && iodev_get_sfidx(&iodev) == 5) {
|
if (!prog_args.disable_plots && iodev_get_sfidx(&iodev) == 5) {
|
||||||
|
|
|
@ -76,12 +76,43 @@ LIBLTE_API void chest_free(chest_t *q);
|
||||||
LIBLTE_API int chest_set_nof_ports(chest_t *q,
|
LIBLTE_API int chest_set_nof_ports(chest_t *q,
|
||||||
uint32_t nof_ports);
|
uint32_t nof_ports);
|
||||||
|
|
||||||
LIBLTE_API int chest_ce_ref(chest_t *q,
|
|
||||||
|
LIBLTE_API float chest_rsrp(chest_t *q,
|
||||||
|
uint32_t nslot,
|
||||||
|
uint32_t port_id);
|
||||||
|
|
||||||
|
LIBLTE_API float chest_rsrp_sf(chest_t *q,
|
||||||
|
uint32_t sf_idx);
|
||||||
|
|
||||||
|
LIBLTE_API float chest_rssi(chest_t *q,
|
||||||
|
cf_t *input);
|
||||||
|
|
||||||
|
LIBLTE_API float chest_rssi_sf(chest_t *q,
|
||||||
|
cf_t *input);
|
||||||
|
|
||||||
|
LIBLTE_API float chest_rsrq(chest_t *q,
|
||||||
|
cf_t *input,
|
||||||
|
uint32_t nslot,
|
||||||
|
uint32_t port_id);
|
||||||
|
|
||||||
|
LIBLTE_API float chest_rsrq_sf(chest_t *q,
|
||||||
|
cf_t *input,
|
||||||
|
uint32_t sf_idx);
|
||||||
|
|
||||||
|
LIBLTE_API int chest_measure_ref(chest_t *q,
|
||||||
cf_t *input,
|
cf_t *input,
|
||||||
uint32_t nslot,
|
uint32_t nslot,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
uint32_t nref);
|
uint32_t nref);
|
||||||
|
|
||||||
|
LIBLTE_API void chest_measure_slot(chest_t *q,
|
||||||
|
cf_t *input,
|
||||||
|
uint32_t nslot);
|
||||||
|
|
||||||
|
LIBLTE_API void chest_measure_sf(chest_t *q,
|
||||||
|
cf_t *input,
|
||||||
|
uint32_t sf_idx);
|
||||||
|
|
||||||
LIBLTE_API int chest_ce_slot_port(chest_t *q,
|
LIBLTE_API int chest_ce_slot_port(chest_t *q,
|
||||||
cf_t *input,
|
cf_t *input,
|
||||||
cf_t *ce,
|
cf_t *ce,
|
||||||
|
|
|
@ -45,8 +45,7 @@ typedef _Complex float cf_t;
|
||||||
typedef struct LIBLTE_API{
|
typedef struct LIBLTE_API{
|
||||||
uint32_t time_idx;
|
uint32_t time_idx;
|
||||||
uint32_t freq_idx;
|
uint32_t freq_idx;
|
||||||
cf_t simbol;
|
cf_t symbol;
|
||||||
cf_t recv_simbol;
|
|
||||||
}ref_t;
|
}ref_t;
|
||||||
|
|
||||||
typedef struct LIBLTE_API{
|
typedef struct LIBLTE_API{
|
||||||
|
@ -57,6 +56,7 @@ typedef struct LIBLTE_API{
|
||||||
uint32_t nof_prb;
|
uint32_t nof_prb;
|
||||||
ref_t *refs;
|
ref_t *refs;
|
||||||
cf_t *ch_est;
|
cf_t *ch_est;
|
||||||
|
cf_t *recv_symbol;
|
||||||
} refsignal_t;
|
} refsignal_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ typedef enum {CPNORM, CPEXT} lte_cp_t;
|
||||||
#define SLOT_IDX_CPNORM(idx, symbol_sz) (idx==0?(CP(symbol_sz, CPNORM_0_LEN)):(CP(symbol_sz, CPNORM_0_LEN)+idx*(symbol_sz+CP(symbol_sz, CPNORM_LEN))))
|
#define SLOT_IDX_CPNORM(idx, symbol_sz) (idx==0?(CP(symbol_sz, CPNORM_0_LEN)):(CP(symbol_sz, CPNORM_0_LEN)+idx*(symbol_sz+CP(symbol_sz, CPNORM_LEN))))
|
||||||
#define SLOT_IDX_CPEXT(idx, symbol_sz) (idx*(symbol_sz+CP(symbol_sz, CPEXT_LEN)))
|
#define SLOT_IDX_CPEXT(idx, symbol_sz) (idx*(symbol_sz+CP(symbol_sz, CPEXT_LEN)))
|
||||||
|
|
||||||
#define SAMPLE_IDX(nof_prb, symbol_idx, sample_idx) (symbol_idx*nof_prb*RE_X_RB + sample_idx)
|
#define SAMPLE_IDX(nof_prb, symbol_idx, sample_idx) ((symbol_idx)*(nof_prb)*(RE_X_RB) + sample_idx)
|
||||||
|
|
||||||
#define RS_VSHIFT(cell_id) (cell_id%6)
|
#define RS_VSHIFT(cell_id) (cell_id%6)
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,10 @@ typedef struct LIBLTE_API {
|
||||||
bool sss_en;
|
bool sss_en;
|
||||||
bool normalize_en;
|
bool normalize_en;
|
||||||
lte_cp_t cp;
|
lte_cp_t cp;
|
||||||
|
uint32_t m0;
|
||||||
|
uint32_t m1;
|
||||||
|
float m0_value;
|
||||||
|
float m1_value;
|
||||||
}sync_t;
|
}sync_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,6 +119,9 @@ LIBLTE_API float sync_get_cfo(sync_t *q);
|
||||||
/* Gets the CP length estimation from the last call to synch_run() */
|
/* Gets the CP length estimation from the last call to synch_run() */
|
||||||
LIBLTE_API lte_cp_t sync_get_cp(sync_t *q);
|
LIBLTE_API lte_cp_t sync_get_cp(sync_t *q);
|
||||||
|
|
||||||
|
/* Sets the CP length estimation (must do it if disabled) */
|
||||||
|
LIBLTE_API void sync_set_cp(sync_t *q, lte_cp_t cp);
|
||||||
|
|
||||||
/* Enables/Disables energy normalization every frame. If disabled, uses the mean */
|
/* Enables/Disables energy normalization every frame. If disabled, uses the mean */
|
||||||
LIBLTE_API void sync_normalize_en(sync_t *q,
|
LIBLTE_API void sync_normalize_en(sync_t *q,
|
||||||
bool enable);
|
bool enable);
|
||||||
|
|
|
@ -57,8 +57,8 @@
|
||||||
* TODO: Check also peak offset
|
* TODO: Check also peak offset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CS_DEFAULT_MAXFRAMES_TOTAL 300
|
#define CS_DEFAULT_MAXFRAMES_TOTAL 500
|
||||||
#define CS_DEFAULT_MAXFRAMES_DETECTED 30
|
#define CS_DEFAULT_MAXFRAMES_DETECTED 50
|
||||||
|
|
||||||
#define CS_DEFAULT_NOFFRAMES_TOTAL 100
|
#define CS_DEFAULT_NOFFRAMES_TOTAL 100
|
||||||
#define CS_DEFAULT_NOFFRAMES_DETECTED 10
|
#define CS_DEFAULT_NOFFRAMES_DETECTED 10
|
||||||
|
@ -87,8 +87,6 @@ typedef struct LIBLTE_API {
|
||||||
uint32_t current_nof_detected;
|
uint32_t current_nof_detected;
|
||||||
uint32_t current_nof_total;
|
uint32_t current_nof_total;
|
||||||
|
|
||||||
uint32_t current_N_id_2;
|
|
||||||
|
|
||||||
uint32_t *mode_ntimes;
|
uint32_t *mode_ntimes;
|
||||||
char *mode_counted;
|
char *mode_counted;
|
||||||
|
|
||||||
|
@ -109,7 +107,8 @@ LIBLTE_API void ue_celldetect_reset(ue_celldetect_t *q);
|
||||||
LIBLTE_API int ue_celldetect_scan(ue_celldetect_t *q,
|
LIBLTE_API int ue_celldetect_scan(ue_celldetect_t *q,
|
||||||
cf_t *signal,
|
cf_t *signal,
|
||||||
uint32_t nsamples,
|
uint32_t nsamples,
|
||||||
ue_celldetect_result_t *found_cell);
|
ue_celldetect_result_t *found_cell,
|
||||||
|
uint32_t N_id_2);
|
||||||
|
|
||||||
LIBLTE_API int ue_celldetect_set_nof_frames_total(ue_celldetect_t *q,
|
LIBLTE_API int ue_celldetect_set_nof_frames_total(ue_celldetect_t *q,
|
||||||
uint32_t nof_frames);
|
uint32_t nof_frames);
|
||||||
|
|
|
@ -55,10 +55,8 @@
|
||||||
#include "liblte/phy/phch/pbch.h"
|
#include "liblte/phy/phch/pbch.h"
|
||||||
#include "liblte/phy/common/fft.h"
|
#include "liblte/phy/common/fft.h"
|
||||||
|
|
||||||
#define MIB_FIND_THRESHOLD 0.6
|
|
||||||
|
|
||||||
#define MIB_NOF_PORTS 2
|
#define MIB_NOF_PORTS 2
|
||||||
|
|
||||||
#define MIB_FRAME_SIZE 9600
|
#define MIB_FRAME_SIZE 9600
|
||||||
|
|
||||||
#define MIB_FRAME_UNALIGNED -3
|
#define MIB_FRAME_UNALIGNED -3
|
||||||
|
|
|
@ -35,8 +35,11 @@
|
||||||
|
|
||||||
typedef _Complex float cf_t;
|
typedef _Complex float cf_t;
|
||||||
|
|
||||||
#define EXPAVERAGE(data, average, nframes) (((data) + (average) * (nframes)) / ((nframes) + 1))
|
// Cumulative moving average
|
||||||
|
#define VEC_CMA(data, average, n) ((data) + ((data) - (average)) / ((n)+1))
|
||||||
|
|
||||||
|
// Exponential moving average
|
||||||
|
#define VEC_EMA(data, average, alpha) ((factor)*(data)+(1-alpha)*(average))
|
||||||
|
|
||||||
/** Return the sum of all the elements */
|
/** Return the sum of all the elements */
|
||||||
LIBLTE_API int vec_acc_ii(int *x, uint32_t len);
|
LIBLTE_API int vec_acc_ii(int *x, uint32_t len);
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
#define SLOT_SZ(q) (q->nof_symbols * q->symbol_sz)
|
#define SLOT_SZ(q) (q->nof_symbols * q->symbol_sz)
|
||||||
#define SF_SZ(q) (2 * SLOT_SZ(q))
|
#define SF_SZ(q) (2 * SLOT_SZ(q))
|
||||||
|
|
||||||
#define VOLK_INTERP
|
//#define VOLK_INTERP
|
||||||
|
|
||||||
void chest_fprint(chest_t *q, FILE *stream, uint32_t nslot, uint32_t port_id) {
|
void chest_fprint(chest_t *q, FILE *stream, uint32_t nslot, uint32_t port_id) {
|
||||||
chest_ref_fprint(q, stream, nslot, port_id);
|
chest_ref_fprint(q, stream, nslot, port_id);
|
||||||
|
@ -62,8 +62,8 @@ void chest_ref_fprint(chest_t *q, FILE *stream, uint32_t nslot, uint32_t port_id
|
||||||
int i;
|
int i;
|
||||||
fprintf(stream, "refs%d=[",port_id);
|
fprintf(stream, "refs%d=[",port_id);
|
||||||
for (i=0;i<q->refsignal[port_id][nslot].nof_refs;i++) {
|
for (i=0;i<q->refsignal[port_id][nslot].nof_refs;i++) {
|
||||||
fprintf(stream, "%3.3f%+3.3fi, ", __real__ q->refsignal[port_id][nslot].refs[i].simbol,
|
fprintf(stream, "%3.3f%+3.3fi, ", __real__ q->refsignal[port_id][nslot].refs[i].symbol,
|
||||||
__imag__ q->refsignal[port_id][nslot].refs[i].simbol);
|
__imag__ q->refsignal[port_id][nslot].refs[i].symbol);
|
||||||
}
|
}
|
||||||
fprintf(stream, "];\n");
|
fprintf(stream, "];\n");
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,8 @@ void chest_recvsig_fprint(chest_t *q, FILE *stream, uint32_t nslot, uint32_t por
|
||||||
int i;
|
int i;
|
||||||
fprintf(stream, "recvsig%d=[",port_id);
|
fprintf(stream, "recvsig%d=[",port_id);
|
||||||
for (i=0;i<q->refsignal[port_id][nslot].nof_refs;i++) {
|
for (i=0;i<q->refsignal[port_id][nslot].nof_refs;i++) {
|
||||||
fprintf(stream, "%3.3f%+3.3fi, ", __real__ q->refsignal[port_id][nslot].refs[i].recv_simbol,
|
fprintf(stream, "%3.3f%+3.3fi, ", __real__ q->refsignal[port_id][nslot].recv_symbol[i],
|
||||||
__imag__ q->refsignal[port_id][nslot].refs[i].recv_simbol);
|
__imag__ q->refsignal[port_id][nslot].recv_symbol[i]);
|
||||||
}
|
}
|
||||||
fprintf(stream, "];\n");
|
fprintf(stream, "];\n");
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,59 @@ void chest_ce_fprint(chest_t *q, FILE *stream, uint32_t nslot, uint32_t port_id)
|
||||||
fprintf(stream, "];\n");
|
fprintf(stream, "];\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int chest_ce_ref(chest_t *q, cf_t *input, uint32_t nslot, uint32_t port_id, uint32_t nref) {
|
float chest_rsrp(chest_t *q, uint32_t nslot, uint32_t port_id) {
|
||||||
|
int nof_refs = q->refsignal[port_id][nslot].nof_refs;
|
||||||
|
cf_t *ch_est = q->refsignal[port_id][nslot].ch_est;
|
||||||
|
return crealf(vec_dot_prod_conj_ccc(ch_est, ch_est, nof_refs))/nof_refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
float chest_rsrp_sf(chest_t *q, uint32_t sf_idx) {
|
||||||
|
int n,p;
|
||||||
|
float rsrp=0;
|
||||||
|
for (p=0;p<q->nof_ports;p++) {
|
||||||
|
for (n=0;n<2;n++) {
|
||||||
|
rsrp+=chest_rsrp(q, 2*sf_idx+n, p)/(2*q->nof_ports);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rsrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
float chest_rssi(chest_t *q, cf_t *input) {
|
||||||
|
float rssi = 0;
|
||||||
|
int i;
|
||||||
|
int l[2];
|
||||||
|
if (q->nof_symbols == CPNORM_NSYMB) {
|
||||||
|
l[0] = 0; l[1] = 4;
|
||||||
|
} else {
|
||||||
|
l[0] = 0; l[1] = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<2;i++) {
|
||||||
|
cf_t *tmp = &input[l[i]*q->nof_re];
|
||||||
|
rssi += crealf(vec_dot_prod_conj_ccc(tmp, tmp, q->nof_re));
|
||||||
|
}
|
||||||
|
return rssi;
|
||||||
|
}
|
||||||
|
|
||||||
|
float chest_rssi_sf(chest_t *q, cf_t *input) {
|
||||||
|
int n;
|
||||||
|
int slotsz = q->nof_symbols*q->nof_re;
|
||||||
|
float rssi=0;
|
||||||
|
for (n=0;n<2;n++) {
|
||||||
|
rssi += chest_rssi(q, &input[n*slotsz]);
|
||||||
|
}
|
||||||
|
return rssi;
|
||||||
|
}
|
||||||
|
|
||||||
|
float chest_rsrq(chest_t *q, cf_t *input, uint32_t nslot, uint32_t port_id) {
|
||||||
|
return (q->nof_re/RE_X_RB) * chest_rsrp(q, nslot, port_id) / chest_rssi(q, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
float chest_rsrq_sf(chest_t *q, cf_t *input, uint32_t sf_idx) {
|
||||||
|
return (4*q->nof_ports*q->nof_re/RE_X_RB) * chest_rsrp_sf(q, sf_idx) / chest_rssi_sf(q, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
int chest_measure_ref(chest_t *q, cf_t *input, uint32_t nslot, uint32_t port_id, uint32_t nref) {
|
||||||
int fidx, tidx;
|
int fidx, tidx;
|
||||||
cf_t known_ref, channel_ref;
|
cf_t known_ref, channel_ref;
|
||||||
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
||||||
|
@ -107,10 +159,9 @@ int chest_ce_ref(chest_t *q, cf_t *input, uint32_t nslot, uint32_t port_id, uint
|
||||||
fidx = q->refsignal[port_id][nslot].refs[nref].freq_idx; // reference frequency index
|
fidx = q->refsignal[port_id][nslot].refs[nref].freq_idx; // reference frequency index
|
||||||
tidx = q->refsignal[port_id][nslot].refs[nref].time_idx; // reference time index
|
tidx = q->refsignal[port_id][nslot].refs[nref].time_idx; // reference time index
|
||||||
|
|
||||||
known_ref = q->refsignal[port_id][nslot].refs[nref].simbol;
|
known_ref = q->refsignal[port_id][nslot].refs[nref].symbol;
|
||||||
channel_ref = input[tidx * q->nof_re + fidx];
|
channel_ref = input[tidx * q->nof_re + fidx];
|
||||||
q->refsignal[port_id][nslot].refs[nref].recv_simbol = channel_ref;
|
q->refsignal[port_id][nslot].recv_symbol[nref] = channel_ref;
|
||||||
|
|
||||||
|
|
||||||
DEBUG("Reference %2d pos (%2d,%2d)=%3d %.2f dB %.2f/%.2f=%.2f\n", nref, tidx, fidx, tidx * q->nof_re + fidx,
|
DEBUG("Reference %2d pos (%2d,%2d)=%3d %.2f dB %.2f/%.2f=%.2f\n", nref, tidx, fidx, tidx * q->nof_re + fidx,
|
||||||
10*log10f(cabsf(channel_ref/known_ref)),
|
10*log10f(cabsf(channel_ref/known_ref)),
|
||||||
|
@ -130,10 +181,42 @@ int chest_ce_ref(chest_t *q, cf_t *input, uint32_t nslot, uint32_t port_id, uint
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void chest_measure_slot_port(chest_t *q, cf_t *input, uint32_t nslot, uint32_t port_id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
refsignal_t *r = &q->refsignal[port_id][nslot];
|
||||||
|
|
||||||
|
DEBUG("Estimating channel slot=%d port=%d using %d reference signals\n",
|
||||||
|
nslot, port_id, r->nof_refs);
|
||||||
|
|
||||||
|
for (i=0;i<r->nof_refs;i++) {
|
||||||
|
chest_measure_ref(q, input, nslot, port_id, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void chest_measure_slot(chest_t *q, cf_t *input, uint32_t nslot) {
|
||||||
|
int p;
|
||||||
|
for (p=0;p<q->nof_ports;p++) {
|
||||||
|
chest_measure_slot_port(q, input, nslot, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void chest_measure_sf(chest_t *q, cf_t *input, uint32_t sf_idx) {
|
||||||
|
int p, n, slotsz;
|
||||||
|
slotsz = q->nof_symbols*q->nof_re;
|
||||||
|
for (p=0;p<q->nof_ports;p++) {
|
||||||
|
for (n=0;n<2;n++) {
|
||||||
|
chest_measure_slot_port(q, &input[n*slotsz], 2*sf_idx+n, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Computes channel estimates for each reference in a slot and port.
|
/* Computes channel estimates for each reference in a slot and port.
|
||||||
* Saves the nof_prb * 12 * nof_symbols channel estimates in the array ce
|
* Saves the nof_prb * 12 * nof_symbols channel estimates in the array ce
|
||||||
*/
|
*/
|
||||||
int chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, uint32_t nslot, uint32_t port_id) {
|
int chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, uint32_t nslot, uint32_t port_id)
|
||||||
|
{
|
||||||
uint32_t i, j;
|
uint32_t i, j;
|
||||||
cf_t x[2], y[MAX_NSYMB];
|
cf_t x[2], y[MAX_NSYMB];
|
||||||
|
|
||||||
|
@ -147,13 +230,8 @@ int chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, uint32_t nslot, uint32
|
||||||
if (q->refsignal[port_id][nslot].nsymbols <= 2) {
|
if (q->refsignal[port_id][nslot].nsymbols <= 2) {
|
||||||
refsignal_t *r = &q->refsignal[port_id][nslot];
|
refsignal_t *r = &q->refsignal[port_id][nslot];
|
||||||
|
|
||||||
DEBUG("Estimating channel slot=%d port=%d using %d reference signals\n",
|
chest_measure_slot_port(q, input, nslot, port_id);
|
||||||
nslot, port_id, r->nof_refs);
|
|
||||||
|
|
||||||
for (i=0;i<r->nof_refs;i++) {
|
|
||||||
chest_ce_ref(q, input, nslot, port_id, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* interpolate the symbols with references
|
/* interpolate the symbols with references
|
||||||
* in the freq domain */
|
* in the freq domain */
|
||||||
for (i=0;i<r->nsymbols;i++) {
|
for (i=0;i<r->nsymbols;i++) {
|
||||||
|
|
|
@ -83,7 +83,7 @@ int refsignal_put(refsignal_t * q, cf_t * slot_symbols)
|
||||||
for (i = 0; i < q->nof_refs; i++) {
|
for (i = 0; i < q->nof_refs; i++) {
|
||||||
fidx = q->refs[i].freq_idx; // reference frequency index
|
fidx = q->refs[i].freq_idx; // reference frequency index
|
||||||
tidx = q->refs[i].time_idx; // reference time index
|
tidx = q->refs[i].time_idx; // reference time index
|
||||||
slot_symbols[SAMPLE_IDX(q->nof_prb, tidx, fidx)] = q->refs[i].simbol;
|
slot_symbols[SAMPLE_IDX(q->nof_prb, tidx, fidx)] = q->refs[i].symbol;
|
||||||
}
|
}
|
||||||
return LIBLTE_SUCCESS;
|
return LIBLTE_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
|
@ -153,6 +153,11 @@ int refsignal_init_LTEDL(refsignal_t * q, uint32_t port_id, uint32_t nslot,
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
q->recv_symbol = vec_malloc(q->nof_refs * sizeof(cf_t));
|
||||||
|
if (!q->recv_symbol) {
|
||||||
|
goto free_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
ns = nslot;
|
ns = nslot;
|
||||||
for (l = 0; l < nof_ref_symbols; l++) {
|
for (l = 0; l < nof_ref_symbols; l++) {
|
||||||
|
|
||||||
|
@ -169,9 +174,9 @@ int refsignal_init_LTEDL(refsignal_t * q, uint32_t port_id, uint32_t nslot,
|
||||||
mp = i + MAX_PRB - cell.nof_prb;
|
mp = i + MAX_PRB - cell.nof_prb;
|
||||||
|
|
||||||
/* generate signal */
|
/* generate signal */
|
||||||
__real__ q->refs[idx(l, i)].simbol =
|
__real__ q->refs[idx(l, i)].symbol =
|
||||||
(1 - 2 * (float) seq.c[2 * mp]) / sqrt(2);
|
(1 - 2 * (float) seq.c[2 * mp]) / sqrt(2);
|
||||||
__imag__ q->refs[idx(l, i)].simbol =
|
__imag__ q->refs[idx(l, i)].symbol =
|
||||||
(1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
|
(1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
|
||||||
|
|
||||||
/* mapping to resource elements */
|
/* mapping to resource elements */
|
||||||
|
@ -259,17 +264,17 @@ int rs_sequence(ref_t * refs, uint32_t len, float alpha, uint32_t ns, uint32_t c
|
||||||
cexpf(-I * M_PI * (float) q * (float) i * ((float) i + 1) / n_sz);
|
cexpf(-I * M_PI * (float) q * (float) i * ((float) i + 1) / n_sz);
|
||||||
}
|
}
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
refs[i].simbol = cfg->beta * cexpf(I * alpha * i) * x_q[i % n_sz];
|
refs[i].symbol = cfg->beta * cexpf(I * alpha * i) * x_q[i % n_sz];
|
||||||
}
|
}
|
||||||
free(x_q);
|
free(x_q);
|
||||||
} else {
|
} else {
|
||||||
if (len == RE_X_RB) {
|
if (len == RE_X_RB) {
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
refs[i].simbol = cfg->beta * cexpf(I * (phi_M_sc_12[u][i] * M_PI / 4 + alpha * i));
|
refs[i].symbol = cfg->beta * cexpf(I * (phi_M_sc_12[u][i] * M_PI / 4 + alpha * i));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
refs[i].simbol = cfg->beta * cexpf(I * (phi_M_sc_24[u][i] * M_PI / 4 + alpha * i));
|
refs[i].symbol = cfg->beta * cexpf(I * (phi_M_sc_24[u][i] * M_PI / 4 + alpha * i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
/* compute exponentially averaged execution time */
|
/* compute exponentially averaged execution time */
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
mean_texec = EXPAVERAGE((float) t[0].tv_usec, mean_texec, n-1);
|
mean_texec = VEC_CMA((float) t[0].tv_usec, mean_texec, n-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check MSE */
|
/* check MSE */
|
||||||
|
|
|
@ -559,7 +559,7 @@ int pdsch_decode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e,
|
||||||
|
|
||||||
} while (q->nof_iterations < TDEC_MAX_ITERATIONS && !early_stop);
|
} while (q->nof_iterations < TDEC_MAX_ITERATIONS && !early_stop);
|
||||||
|
|
||||||
q->average_nof_iterations = EXPAVERAGE((float) q->nof_iterations,
|
q->average_nof_iterations = VEC_CMA((float) q->nof_iterations,
|
||||||
q->average_nof_iterations,
|
q->average_nof_iterations,
|
||||||
q->average_nof_iterations_n);
|
q->average_nof_iterations_n);
|
||||||
q->average_nof_iterations_n++;
|
q->average_nof_iterations_n++;
|
||||||
|
|
|
@ -254,7 +254,7 @@ int pss_synch_find_pss(pss_synch_t *q, cf_t *input, float *corr_peak_value)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Find maximum of the absolute value of the correlation */
|
/* Find maximum of the absolute value of the correlation */
|
||||||
corr_peak_pos = vec_max_abs_ci(q->conv_output, conv_output_len);
|
corr_peak_pos = vec_max_abs_ci(q->conv_output, conv_output_len-1);
|
||||||
if (corr_peak_value) {
|
if (corr_peak_value) {
|
||||||
*corr_peak_value = cabsf(q->conv_output[corr_peak_pos]);
|
*corr_peak_value = cabsf(q->conv_output[corr_peak_pos]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ int sync_init(sync_t *q, uint32_t frame_size, uint32_t fft_size) {
|
||||||
bzero(q, sizeof(sync_t));
|
bzero(q, sizeof(sync_t));
|
||||||
q->detect_cp = true;
|
q->detect_cp = true;
|
||||||
q->normalize_en = true;
|
q->normalize_en = true;
|
||||||
|
q->mean_energy = 1.0;
|
||||||
q->sss_en = true;
|
q->sss_en = true;
|
||||||
q->N_id_2 = 1000;
|
q->N_id_2 = 1000;
|
||||||
q->N_id_1 = 1000;
|
q->N_id_1 = 1000;
|
||||||
|
@ -144,6 +145,9 @@ void sync_cp_en(sync_t *q, bool enabled) {
|
||||||
lte_cp_t sync_get_cp(sync_t *q) {
|
lte_cp_t sync_get_cp(sync_t *q) {
|
||||||
return q->cp;
|
return q->cp;
|
||||||
}
|
}
|
||||||
|
void sync_set_cp(sync_t *q, lte_cp_t cp) {
|
||||||
|
q->cp = cp;
|
||||||
|
}
|
||||||
|
|
||||||
/* CP detection algorithm taken from:
|
/* CP detection algorithm taken from:
|
||||||
* "SSS Detection Method for Initial Cell Search in 3GPP LTE FDD/TDD Dual Mode Receiver"
|
* "SSS Detection Method for Initial Cell Search in 3GPP LTE FDD/TDD Dual Mode Receiver"
|
||||||
|
@ -183,9 +187,7 @@ static lte_cp_t detect_cp(sync_t *q, cf_t *input, uint32_t peak_pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
int sync_sss(sync_t *q, cf_t *input, uint32_t peak_pos) {
|
int sync_sss(sync_t *q, cf_t *input, uint32_t peak_pos) {
|
||||||
uint32_t m0, m1;
|
|
||||||
int sss_idx, ret;
|
int sss_idx, ret;
|
||||||
float m0_value, m1_value;
|
|
||||||
|
|
||||||
sss_synch_set_N_id_2(&q->sss, q->N_id_2);
|
sss_synch_set_N_id_2(&q->sss, q->N_id_2);
|
||||||
|
|
||||||
|
@ -195,17 +197,15 @@ int sync_sss(sync_t *q, cf_t *input, uint32_t peak_pos) {
|
||||||
|
|
||||||
/* Make sure we have enough room to find SSS sequence */
|
/* Make sure we have enough room to find SSS sequence */
|
||||||
sss_idx = (int) peak_pos - 2*(q->fft_size + CP(q->fft_size, q->cp));
|
sss_idx = (int) peak_pos - 2*(q->fft_size + CP(q->fft_size, q->cp));
|
||||||
|
|
||||||
if (sss_idx < 0) {
|
if (sss_idx < 0) {
|
||||||
INFO("Not enough room to decode CP SSS (sss_idx=%d, peak_pos=%d)\n", sss_idx, peak_pos);
|
INFO("Not enough room to decode CP SSS (sss_idx=%d, peak_pos=%d)\n", sss_idx, peak_pos);
|
||||||
return LIBLTE_SUCCESS;
|
return LIBLTE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try Normal CP length */
|
sss_synch_m0m1(&q->sss, &input[sss_idx], &q->m0, &q->m0_value, &q->m1, &q->m1_value);
|
||||||
sss_synch_m0m1(&q->sss, &input[sss_idx], &m0, &m0_value, &m1, &m1_value);
|
|
||||||
|
|
||||||
q->sf_idx = sss_synch_subframe(m0, m1);
|
q->sf_idx = sss_synch_subframe(q->m0, q->m1);
|
||||||
ret = sss_synch_N_id_1(&q->sss, m0, m1);
|
ret = sss_synch_N_id_1(&q->sss, q->m0, q->m1);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
q->N_id_1 = (uint32_t) ret;
|
q->N_id_1 = (uint32_t) ret;
|
||||||
} else {
|
} else {
|
||||||
|
@ -223,14 +223,14 @@ int sync_find(sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_posit
|
||||||
|
|
||||||
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
||||||
|
|
||||||
float peak_unnormalized, energy;
|
float peak_unnormalized=0, energy=1;
|
||||||
|
|
||||||
if (q != NULL &&
|
if (q != NULL &&
|
||||||
input != NULL &&
|
input != NULL &&
|
||||||
lte_N_id_2_isvalid(q->N_id_2) &&
|
lte_N_id_2_isvalid(q->N_id_2) &&
|
||||||
fft_size_isvalid(q->fft_size))
|
fft_size_isvalid(q->fft_size))
|
||||||
{
|
{
|
||||||
uint32_t peak_pos;
|
int peak_pos;
|
||||||
|
|
||||||
if (peak_position) {
|
if (peak_position) {
|
||||||
*peak_position = 0;
|
*peak_position = 0;
|
||||||
|
@ -239,14 +239,17 @@ int sync_find(sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_posit
|
||||||
pss_synch_set_N_id_2(&q->pss, q->N_id_2);
|
pss_synch_set_N_id_2(&q->pss, q->N_id_2);
|
||||||
|
|
||||||
peak_pos = pss_synch_find_pss(&q->pss, &input[find_offset], &peak_unnormalized);
|
peak_pos = pss_synch_find_pss(&q->pss, &input[find_offset], &peak_unnormalized);
|
||||||
|
if (peak_pos < 0) {
|
||||||
|
fprintf(stderr, "Error calling finding PSS sequence\n");
|
||||||
|
return LIBLTE_ERROR;
|
||||||
|
}
|
||||||
if (q->normalize_en &&
|
if (q->normalize_en &&
|
||||||
peak_pos + find_offset >= q->fft_size)
|
peak_pos + find_offset >= q->fft_size)
|
||||||
{
|
{
|
||||||
/* Compute the energy of the received PSS sequence to normalize */
|
/* Compute the energy of the received PSS sequence to normalize */
|
||||||
cf_t *pss_ptr = &input[find_offset+peak_pos-q->fft_size];
|
cf_t *pss_ptr = &input[find_offset+peak_pos-q->fft_size];
|
||||||
energy = sqrtf(crealf(vec_dot_prod_conj_ccc(pss_ptr, pss_ptr, q->fft_size)) / (q->fft_size));
|
energy = sqrtf(crealf(vec_dot_prod_conj_ccc(pss_ptr, pss_ptr, q->fft_size)) / (q->fft_size));
|
||||||
q->mean_energy = EXPAVERAGE(energy, q->mean_energy, q->frame_cnt);
|
q->mean_energy = VEC_CMA(energy, q->mean_energy, q->frame_cnt);
|
||||||
} else {
|
} else {
|
||||||
if (q->mean_energy == 0.0) {
|
if (q->mean_energy == 0.0) {
|
||||||
q->mean_energy = 1.0;
|
q->mean_energy = 1.0;
|
||||||
|
@ -256,7 +259,7 @@ int sync_find(sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_posit
|
||||||
|
|
||||||
/* Normalize and compute mean peak value */
|
/* Normalize and compute mean peak value */
|
||||||
q->peak_value = peak_unnormalized/energy;
|
q->peak_value = peak_unnormalized/energy;
|
||||||
q->mean_peak_value = EXPAVERAGE(q->peak_value, q->mean_peak_value, q->frame_cnt);
|
q->mean_peak_value = VEC_CMA(q->peak_value, q->mean_peak_value, q->frame_cnt);
|
||||||
q->frame_cnt++;
|
q->frame_cnt++;
|
||||||
|
|
||||||
/* If peak is over threshold, compute CFO and SSS */
|
/* If peak is over threshold, compute CFO and SSS */
|
||||||
|
@ -264,25 +267,27 @@ int sync_find(sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_posit
|
||||||
if (find_offset + peak_pos >= q->fft_size) {
|
if (find_offset + peak_pos >= q->fft_size) {
|
||||||
q->cfo = pss_synch_cfo_compute(&q->pss, &input[find_offset+peak_pos-q->fft_size]);
|
q->cfo = pss_synch_cfo_compute(&q->pss, &input[find_offset+peak_pos-q->fft_size]);
|
||||||
if (q->sss_en) {
|
if (q->sss_en) {
|
||||||
if (sync_sss(q, input, find_offset + peak_pos) < 0) {
|
ret = sync_sss(q, input, find_offset + peak_pos);
|
||||||
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error synchronizing with SSS\n");
|
fprintf(stderr, "Error synchronizing with SSS\n");
|
||||||
return LIBLTE_ERROR;
|
return LIBLTE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
INFO("Warning: no space for CFO computation\n",0);
|
INFO("Warning: no space for CFO computation\n",0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peak_position) {
|
if (peak_position) {
|
||||||
*peak_position = peak_pos;
|
*peak_position = (uint32_t) peak_pos;
|
||||||
}
|
}
|
||||||
ret = 1;
|
|
||||||
} else {
|
} else {
|
||||||
ret = LIBLTE_SUCCESS;
|
ret = LIBLTE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO("SYNC ret=%d N_id_2=%d pos=%d peak=%.2f energy=%.3f threshold=%.2f sf_idx=%d\n",
|
INFO("SYNC ret=%d N_id_2=%d pos=%d peak=%.2f/%.2f=%.2f threshold=%.2f sf_idx=%d offset=%d\n",
|
||||||
ret, q->N_id_2, peak_pos, q->peak_value, energy, q->threshold, q->sf_idx);
|
ret, q->N_id_2, peak_pos, peak_unnormalized,energy,q->peak_value, q->threshold, q->sf_idx, find_offset);
|
||||||
|
|
||||||
} else if (lte_N_id_2_isvalid(q->N_id_2)) {
|
} else if (lte_N_id_2_isvalid(q->N_id_2)) {
|
||||||
fprintf(stderr, "Must call sync_set_N_id_2() first!\n");
|
fprintf(stderr, "Must call sync_set_N_id_2() first!\n");
|
||||||
|
|
|
@ -161,7 +161,7 @@ int main(int argc, char **argv) {
|
||||||
fft_size);
|
fft_size);
|
||||||
float x = peak_value/y;
|
float x = peak_value/y;
|
||||||
|
|
||||||
mean_peak = EXPAVERAGE(x, mean_peak, frame_cnt);
|
mean_peak = VEC_CMA(x, mean_peak, frame_cnt);
|
||||||
|
|
||||||
if (x >= threshold) {
|
if (x >= threshold) {
|
||||||
nof_det++;
|
nof_det++;
|
||||||
|
|
|
@ -109,7 +109,6 @@ void ue_celldetect_reset(ue_celldetect_t * q)
|
||||||
{
|
{
|
||||||
q->current_nof_detected = 0;
|
q->current_nof_detected = 0;
|
||||||
q->current_nof_total = 0;
|
q->current_nof_total = 0;
|
||||||
q->current_N_id_2 = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ue_celldetect_set_threshold(ue_celldetect_t * q, float threshold)
|
void ue_celldetect_set_threshold(ue_celldetect_t * q, float threshold)
|
||||||
|
@ -189,7 +188,8 @@ void decide_cell(ue_celldetect_t * q, ue_celldetect_result_t *found_cell)
|
||||||
int ue_celldetect_scan(ue_celldetect_t * q,
|
int ue_celldetect_scan(ue_celldetect_t * q,
|
||||||
cf_t *signal,
|
cf_t *signal,
|
||||||
uint32_t nsamples,
|
uint32_t nsamples,
|
||||||
ue_celldetect_result_t *found_cell)
|
ue_celldetect_result_t *found_cell,
|
||||||
|
uint32_t N_id_2)
|
||||||
{
|
{
|
||||||
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
||||||
uint32_t peak_idx;
|
uint32_t peak_idx;
|
||||||
|
@ -198,7 +198,8 @@ int ue_celldetect_scan(ue_celldetect_t * q,
|
||||||
|
|
||||||
if (q != NULL &&
|
if (q != NULL &&
|
||||||
signal != NULL &&
|
signal != NULL &&
|
||||||
nsamples >= 4800)
|
nsamples >= 4800 &&
|
||||||
|
lte_N_id_2_isvalid(N_id_2))
|
||||||
{
|
{
|
||||||
ret = LIBLTE_SUCCESS;
|
ret = LIBLTE_SUCCESS;
|
||||||
|
|
||||||
|
@ -209,16 +210,18 @@ int ue_celldetect_scan(ue_celldetect_t * q,
|
||||||
nof_input_frames = nsamples/4800;
|
nof_input_frames = nsamples/4800;
|
||||||
|
|
||||||
for (uint32_t nf=0;nf<nof_input_frames;nf++) {
|
for (uint32_t nf=0;nf<nof_input_frames;nf++) {
|
||||||
sync_set_N_id_2(&q->sfind, q->current_N_id_2);
|
if (sync_set_N_id_2(&q->sfind, N_id_2)) {
|
||||||
|
return LIBLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
INFO("[%3d/%3d]: Searching cells with N_id_2=%d. %d frames\n",
|
INFO("[%3d/%3d]: Searching cells with N_id_2=%d. %d frames\n",
|
||||||
q->current_nof_detected, q->current_nof_total, q->current_N_id_2, nof_input_frames);
|
q->current_nof_detected, q->current_nof_total, N_id_2, nof_input_frames);
|
||||||
|
|
||||||
/* Find peak and cell id */
|
/* Find peak and cell id */
|
||||||
ret = sync_find(&q->sfind, &signal[nf*4800], 0, &peak_idx);
|
ret = sync_find(&q->sfind, &signal[nf*4800], 0, &peak_idx);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
|
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
|
||||||
return -1;
|
return LIBLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If peak position does not allow to read SSS, return error -3 */
|
/* If peak position does not allow to read SSS, return error -3 */
|
||||||
|
@ -249,17 +252,13 @@ int ue_celldetect_scan(ue_celldetect_t * q,
|
||||||
/* Decide cell ID and CP if we detected up to nof_frames_detected */
|
/* Decide cell ID and CP if we detected up to nof_frames_detected */
|
||||||
if (q->current_nof_detected == q->nof_frames_detected) {
|
if (q->current_nof_detected == q->nof_frames_detected) {
|
||||||
decide_cell(q, found_cell);
|
decide_cell(q, found_cell);
|
||||||
q->current_N_id_2++;
|
|
||||||
q->current_nof_detected = q->current_nof_total = 0;
|
q->current_nof_detected = q->current_nof_total = 0;
|
||||||
ret = CS_CELL_DETECTED;
|
ret = CS_CELL_DETECTED;
|
||||||
/* Or go to the next N_id_2 if we didn't detect the cell */
|
|
||||||
} else if (q->current_nof_total == q->nof_frames_total) {
|
} else if (q->current_nof_total == q->nof_frames_total) {
|
||||||
q->current_N_id_2++;
|
|
||||||
q->current_nof_detected = q->current_nof_total = 0;
|
q->current_nof_detected = q->current_nof_total = 0;
|
||||||
ret = CS_CELL_NOT_DETECTED;
|
ret = CS_CELL_NOT_DETECTED;
|
||||||
}
|
} else {
|
||||||
if (q->current_N_id_2 == 3) {
|
ret = 0;
|
||||||
q->current_N_id_2 = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ int ue_dl_decode(ue_dl_t *q, cf_t *input, char *data, uint32_t sf_idx, uint16_t
|
||||||
|
|
||||||
gettimeofday(&t[2], NULL);
|
gettimeofday(&t[2], NULL);
|
||||||
get_time_interval(t);
|
get_time_interval(t);
|
||||||
mean_exec_time = (float) EXPAVERAGE((float) t[0].tv_usec, mean_exec_time, frame_cnt);
|
mean_exec_time = (float) VEC_CMA((float) t[0].tv_usec, mean_exec_time, frame_cnt);
|
||||||
frame_cnt++;
|
frame_cnt++;
|
||||||
|
|
||||||
for (int i=0;i<MAX_PORTS;i++) {
|
for (int i=0;i<MAX_PORTS;i++) {
|
||||||
|
|
|
@ -37,11 +37,13 @@
|
||||||
#include "liblte/phy/utils/vector.h"
|
#include "liblte/phy/utils/vector.h"
|
||||||
|
|
||||||
#define FIND_FFTSIZE 128
|
#define FIND_FFTSIZE 128
|
||||||
#define FIND_SFLEN 10*SF_LEN(FIND_FFTSIZE)
|
#define FIND_SFLEN 5*SF_LEN(FIND_FFTSIZE)
|
||||||
|
|
||||||
|
#define MIB_FIND_THRESHOLD 0.0
|
||||||
|
|
||||||
int ue_mib_init(ue_mib_t * q,
|
int ue_mib_init(ue_mib_t * q,
|
||||||
uint32_t cell_id,
|
uint32_t cell_id,
|
||||||
lte_cp_t cp)
|
lte_cp_t cp)
|
||||||
{
|
{
|
||||||
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
||||||
|
|
||||||
|
@ -80,6 +82,8 @@ int ue_mib_init(ue_mib_t * q,
|
||||||
sync_set_threshold(&q->sfind, MIB_FIND_THRESHOLD);
|
sync_set_threshold(&q->sfind, MIB_FIND_THRESHOLD);
|
||||||
sync_sss_en(&q->sfind, true);
|
sync_sss_en(&q->sfind, true);
|
||||||
sync_set_N_id_2(&q->sfind, cell_id % 3);
|
sync_set_N_id_2(&q->sfind, cell_id % 3);
|
||||||
|
sync_cp_en(&q->sfind, false);
|
||||||
|
sync_set_cp(&q->sfind, cp);
|
||||||
|
|
||||||
if (lte_fft_init(&q->fft, cp, cell.nof_prb)) {
|
if (lte_fft_init(&q->fft, cp, cell.nof_prb)) {
|
||||||
fprintf(stderr, "Error initializing FFT\n");
|
fprintf(stderr, "Error initializing FFT\n");
|
||||||
|
@ -137,39 +141,42 @@ void ue_mib_set_threshold(ue_mib_t * q, float threshold)
|
||||||
|
|
||||||
static int mib_decoder_run(ue_mib_t * q, cf_t *input, pbch_mib_t *mib)
|
static int mib_decoder_run(ue_mib_t * q, cf_t *input, pbch_mib_t *mib)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = LIBLTE_SUCCESS;
|
||||||
|
|
||||||
/* Run FFT for the slot symbols */
|
/* Run FFT for the slot symbols */
|
||||||
lte_fft_run_slot(&q->fft, input, q->slot1_symbols);
|
lte_fft_run_slot(&q->fft, input, q->slot1_symbols);
|
||||||
|
|
||||||
/* Get channel estimates of slot #1 for each port */
|
/* Get channel estimates of slot #1 for each port */
|
||||||
ret = chest_ce_slot(&q->chest, q->slot1_symbols, q->ce, 1);
|
ret = chest_ce_slot(&q->chest, q->slot1_symbols, q->ce, 1);
|
||||||
if (ret == LIBLTE_SUCCESS) {
|
if (ret < 0) {
|
||||||
|
return LIBLTE_ERROR;
|
||||||
/* Reset decoder if we missed a frame */
|
|
||||||
if ((q->last_frame_trial && (q->frame_cnt - q->last_frame_trial > 2)) ||
|
|
||||||
q->frame_cnt > 10)
|
|
||||||
{
|
|
||||||
ue_mib_reset(q);
|
|
||||||
INFO("Resetting PBCH decoder: last trial %u, now is %u\n",
|
|
||||||
q->last_frame_trial, q->frame_cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode PBCH */
|
|
||||||
ret = pbch_decode(&q->pbch, q->slot1_symbols, q->ce, mib);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "Error decoding PBCH\n");
|
|
||||||
} else if (ret == 1) {
|
|
||||||
INFO("MIB decoded: %u\n", q->frame_cnt/2);
|
|
||||||
ue_mib_reset(q);
|
|
||||||
ret = 1;
|
|
||||||
} else {
|
|
||||||
INFO("MIB not decoded: %u\n", q->frame_cnt / 2);
|
|
||||||
q->last_frame_trial = q->frame_cnt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset decoder if we missed a frame */
|
||||||
|
if ((q->last_frame_trial && (abs(q->frame_cnt - q->last_frame_trial) > 2)) ||
|
||||||
|
q->frame_cnt > 16)
|
||||||
|
{
|
||||||
|
INFO("Resetting PBCH decoder: last trial %u, now is %u\n",
|
||||||
|
q->last_frame_trial, q->frame_cnt);
|
||||||
|
ue_mib_reset(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decode PBCH */
|
||||||
|
ret = pbch_decode(&q->pbch, q->slot1_symbols, q->ce, mib);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "Error decoding PBCH\n");
|
||||||
|
} else if (ret == 1) {
|
||||||
|
INFO("MIB decoded: %u\n", q->frame_cnt/2);
|
||||||
|
ue_mib_reset(q);
|
||||||
|
ret = MIB_FOUND;
|
||||||
|
} else {
|
||||||
|
INFO("MIB not decoded: %u\n", q->frame_cnt / 2);
|
||||||
|
q->last_frame_trial = q->frame_cnt;
|
||||||
|
ret = LIBLTE_SUCCESS;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
int counter1=0,counter2=0,counter3=0,counter4=0;
|
||||||
|
|
||||||
int ue_mib_decode(ue_mib_t * q,
|
int ue_mib_decode(ue_mib_t * q,
|
||||||
cf_t *signal,
|
cf_t *signal,
|
||||||
|
@ -177,13 +184,18 @@ int ue_mib_decode(ue_mib_t * q,
|
||||||
pbch_mib_t *mib)
|
pbch_mib_t *mib)
|
||||||
{
|
{
|
||||||
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
||||||
uint32_t peak_idx;
|
uint32_t peak_idx=0;
|
||||||
uint32_t nof_input_frames;
|
uint32_t nof_input_frames;
|
||||||
|
|
||||||
|
|
||||||
if (q != NULL &&
|
if (q != NULL &&
|
||||||
signal != NULL)
|
signal != NULL)
|
||||||
{
|
{
|
||||||
|
if (nsamples < MIB_FRAME_SIZE) {
|
||||||
|
fprintf(stderr, "Error: nsamples must be greater than %d\n", MIB_FRAME_SIZE);
|
||||||
|
return LIBLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ret = LIBLTE_SUCCESS;
|
ret = LIBLTE_SUCCESS;
|
||||||
|
|
||||||
if (nsamples % MIB_FRAME_SIZE) {
|
if (nsamples % MIB_FRAME_SIZE) {
|
||||||
|
@ -200,26 +212,41 @@ int ue_mib_decode(ue_mib_t * q,
|
||||||
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
|
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If peak position does not allow to read SSS, return error -3 */
|
if (ret == 0) {
|
||||||
|
counter2++;
|
||||||
|
} else if (ret == 1) {
|
||||||
|
counter4++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we have space for reading the MIB and we are in Subframe #0 */
|
||||||
if (ret == 1 &&
|
if (ret == 1 &&
|
||||||
nf*MIB_FRAME_SIZE + peak_idx + 960 <= nsamples &&
|
nf*MIB_FRAME_SIZE + peak_idx + 960 <= nsamples &&
|
||||||
sync_sss_detected(&q->sfind) &&
|
sync_sss_detected(&q->sfind) &&
|
||||||
sync_get_sf_idx(&q->sfind) == 0)
|
sync_get_sf_idx(&q->sfind) == 0)
|
||||||
{
|
{
|
||||||
|
INFO("Trying to decode MIB\n",0);
|
||||||
ret = mib_decoder_run(q, &signal[nf*MIB_FRAME_SIZE+peak_idx], mib);
|
ret = mib_decoder_run(q, &signal[nf*MIB_FRAME_SIZE+peak_idx], mib);
|
||||||
|
counter3++;
|
||||||
} else if ((ret == LIBLTE_SUCCESS && peak_idx != 0) ||
|
} else if ((ret == LIBLTE_SUCCESS && peak_idx != 0) ||
|
||||||
(ret == 1 && nf*MIB_FRAME_SIZE + peak_idx + 960 > nsamples))
|
(ret == 1 && nf*MIB_FRAME_SIZE + peak_idx + 960 > nsamples))
|
||||||
{
|
{
|
||||||
|
printf("Not enough space for PBCH\n",0);
|
||||||
ret = MIB_FRAME_UNALIGNED;
|
ret = MIB_FRAME_UNALIGNED;
|
||||||
} else {
|
} else {
|
||||||
|
INFO("SSS not detected\n",0);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
counter1++;
|
||||||
|
INFO("Total: %3d - Sync0: %3d - Sync1: %3d - Tried: %3d - Peak: %4d - Ret: %d\n",counter1,counter2,counter4, counter3, peak_idx, ret);
|
||||||
|
|
||||||
q->frame_cnt++;
|
q->frame_cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ cf_t dummy[MAX_TIME_OFFSET];
|
||||||
#define CURRENT_SLOTLEN_RE SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
|
#define CURRENT_SLOTLEN_RE SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
|
||||||
#define CURRENT_SFLEN_RE SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
|
#define CURRENT_SFLEN_RE SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
|
||||||
|
|
||||||
#define FIND_THRESHOLD 1.0
|
#define FIND_THRESHOLD 1.2
|
||||||
#define TRACK_THRESHOLD 0.2
|
#define TRACK_THRESHOLD 0.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ float ue_sync_get_cfo(ue_sync_t *q) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float ue_sync_get_sfo(ue_sync_t *q) {
|
float ue_sync_get_sfo(ue_sync_t *q) {
|
||||||
return 1000*q->mean_time_offset/5;
|
return 1000*q->mean_time_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ue_sync_decode_sss_on_track(ue_sync_t *q, bool enabled) {
|
void ue_sync_decode_sss_on_track(ue_sync_t *q, bool enabled) {
|
||||||
|
@ -179,8 +179,9 @@ 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_sf_idx(&q->strack)) && q->decode_sss_on_track) {
|
if ((q->sf_idx != sync_get_sf_idx(&q->strack)) && q->decode_sss_on_track) {
|
||||||
INFO("Warning: Expected SF idx %d but got %d!\n",
|
INFO("Warning: Expected SF idx %d but got %d (%d,%g - %d,%g)!\n",
|
||||||
q->sf_idx, sync_get_sf_idx(&q->strack));
|
q->sf_idx, sync_get_sf_idx(&q->strack), q->strack.m0, q->strack.m1, q->strack.m0_value, q->strack.m1_value);
|
||||||
|
/* FIXME: What should we do in this case? */
|
||||||
q->sf_idx = sync_get_sf_idx(&q->strack);
|
q->sf_idx = sync_get_sf_idx(&q->strack);
|
||||||
q->state = SF_TRACK;
|
q->state = SF_TRACK;
|
||||||
} else {
|
} else {
|
||||||
|
@ -196,10 +197,9 @@ int track_peak_ok(ue_sync_t *q, uint32_t track_idx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compute cumulative moving average CFO */
|
/* compute cumulative moving average CFO */
|
||||||
q->cur_cfo = EXPAVERAGE(sync_get_cfo(&q->strack), q->cur_cfo, q->frame_ok_cnt);
|
q->cur_cfo = VEC_CMA(sync_get_cfo(&q->strack), q->cur_cfo, q->frame_ok_cnt);
|
||||||
|
|
||||||
/* compute cumulative moving average time offset */
|
/* compute cumulative moving average time offset */
|
||||||
q->mean_time_offset = (float) EXPAVERAGE((float) q->time_offset, q->mean_time_offset, q->frame_ok_cnt);
|
q->mean_time_offset = (float) VEC_CMA((float) q->time_offset, q->mean_time_offset, q->frame_ok_cnt);
|
||||||
|
|
||||||
q->peak_idx = CURRENT_SFLEN/2 + q->time_offset;
|
q->peak_idx = CURRENT_SFLEN/2 + q->time_offset;
|
||||||
q->frame_ok_cnt++;
|
q->frame_ok_cnt++;
|
||||||
|
@ -310,7 +310,7 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
|
||||||
#ifdef MEASURE_EXEC_TIME
|
#ifdef MEASURE_EXEC_TIME
|
||||||
gettimeofday(&t[2], NULL);
|
gettimeofday(&t[2], NULL);
|
||||||
get_time_interval(t);
|
get_time_interval(t);
|
||||||
q->mean_exec_time = (float) EXPAVERAGE((float) t[0].tv_usec, q->mean_exec_time, q->frame_total_cnt);
|
q->mean_exec_time = (float) VEC_CMA((float) t[0].tv_usec, q->mean_exec_time, q->frame_total_cnt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
|
|
|
@ -169,7 +169,7 @@ int find_cell(void *uhd, ue_celldetect_t *s, cf_t *buffer, ue_celldetect_result_
|
||||||
return LIBLTE_ERROR;
|
return LIBLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = ue_celldetect_scan(s, buffer, flen, found_cell);
|
n = ue_celldetect_scan(s, buffer, flen, found_cell, nof_scanned_cells);
|
||||||
switch(n) {
|
switch(n) {
|
||||||
case CS_FRAME_UNALIGNED:
|
case CS_FRAME_UNALIGNED:
|
||||||
printf("Realigning frame\n");
|
printf("Realigning frame\n");
|
||||||
|
|
Loading…
Reference in New Issue