File read in pdsch_ue

master
ismagom 10 years ago
parent 359b8dcd72
commit 5c8a94ddfc

@ -51,25 +51,27 @@ LIST(FIND OPTIONAL_LIBS graphics GRAPHICS_FIND)
# These two can be compiled without UHD or graphics support
#################################################################
IF(${CUHD_FIND} GREATER -1)
add_executable(pdsch_ue pdsch_ue.c cuhd_utils.c)
target_link_libraries(pdsch_ue lte_rrc lte_phy cuhd)
add_executable(pdsch_enodeb pdsch_enodeb.c)
target_link_libraries(pdsch_enodeb lte_rrc lte_phy cuhd)
IF(${GRAPHICS_FIND} EQUAL -1)
SET_TARGET_PROPERTIES(pdsch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
SET_TARGET_PROPERTIES(pdsch_enodeb PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
ELSE(${GRAPHICS_FIND} EQUAL -1)
target_link_libraries(pdsch_ue graphics)
target_link_libraries(pdsch_enodeb graphics)
ENDIF(${GRAPHICS_FIND} EQUAL -1)
ENDIF(${CUHD_FIND} GREATER -1)
add_executable(pdsch_ue pdsch_ue.c cuhd_utils.c)
target_link_libraries(pdsch_ue lte_rrc lte_phy)
add_executable(pdsch_enodeb pdsch_enodeb.c)
target_link_libraries(pdsch_enodeb lte_rrc lte_phy)
IF(${CUHD_FIND} EQUAL -1)
SET_TARGET_PROPERTIES(pdsch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
SET_TARGET_PROPERTIES(pdsch_enodeb PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
ELSE(${CUHD_FIND} EQUAL -1)
target_link_libraries(pdsch_ue cuhd)
target_link_libraries(pdsch_enodeb cuhd)
ENDIF(${CUHD_FIND} EQUAL -1)
IF(${GRAPHICS_FIND} EQUAL -1)
SET_TARGET_PROPERTIES(pdsch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
SET_TARGET_PROPERTIES(pdsch_enodeb PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
ELSE(${GRAPHICS_FIND} EQUAL -1)
target_link_libraries(pdsch_ue graphics)
target_link_libraries(pdsch_enodeb graphics)
ENDIF(${GRAPHICS_FIND} EQUAL -1)
#################################################################

@ -38,9 +38,13 @@
#include "liblte/rrc/rrc.h"
#include "liblte/phy/phy.h"
#include "liblte/graphics/plot/plot_waterfall.h"
#ifndef DISABLE_UHD
#include "liblte/cuhd/cuhd.h"
#include "cuhd_utils.h"
#include "liblte/graphics/plot/plot_waterfall.h"
#endif
#define STDOUT_COMPACT
@ -70,19 +74,23 @@ typedef struct {
bool disable_plots;
int force_N_id_2;
uint16_t rnti;
char *input_file_name;
uint32_t file_nof_prb;
char *uhd_args;
float uhd_freq;
float uhd_gain;
int net_port;
char *net_address;
int net_port_signal;
char *net_address_signal;
char *net_address_signal;
}prog_args_t;
void args_default(prog_args_t *args) {
args->nof_subframes = -1;
args->rnti = SIRNTI;
args->force_N_id_2 = -1; // Pick the best
args->input_file_name = NULL;
args->file_nof_prb = 6;
args->uhd_args = "";
args->uhd_freq = -1.0;
args->uhd_gain = 60.0;
@ -93,9 +101,15 @@ void args_default(prog_args_t *args) {
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [agldnruv] -f rx_frequency (in Hz)\n", prog);
printf("Usage: %s [agildnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
#ifndef DISABLE_GRAPHICS
printf("\t-a UHD args [Default %s]\n", args->uhd_args);
printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_gain);
#else
printf("\t UHD is disabled. CUHD library not available\n");
#endif
printf("\t-i input_file [Default USRP]\n");
printf("\t-p nof_prb for input file [Default %d]\n", args->file_nof_prb);
printf("\t-r RNTI [Default 0x%x]\n",args->rnti);
printf("\t-l Force N_id_2 [Default best]\n");
#ifndef DISABLE_GRAPHICS
@ -114,8 +128,14 @@ void usage(prog_args_t *args, char *prog) {
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "agldnvrfuUsS")) != -1) {
while ((opt = getopt(argc, argv, "aglipdnvrfuUsS")) != -1) {
switch (opt) {
case 'i':
args->input_file_name = argv[optind];
break;
case 'p':
args->file_nof_prb = atoi(argv[optind]);
break;
case 'a':
args->uhd_args = argv[optind];
break;
@ -157,7 +177,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
exit(-1);
}
}
if (args->uhd_freq < 0) {
if (args->uhd_freq < 0 && args->input_file_name == NULL) {
usage(args, argv[0]);
exit(-1);
}
@ -176,10 +196,12 @@ void sig_int_handler(int signo)
}
}
#ifndef DISABLE_UHD
int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv(h, data, nsamples, 1);
}
#endif
extern float mean_exec_time;
@ -217,53 +239,79 @@ int main(int argc, char **argv) {
exit(-1);
}
}
printf("Opening UHD device...\n");
if (cuhd_open(prog_args.uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
/* Set receiver gain */
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
/* set receiver frequency */
cuhd_set_rx_freq(uhd, (double) prog_args.uhd_freq);
cuhd_rx_wait_lo_locked(uhd);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000);
ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
exit(-1);
} else if (ret == 0) {
printf("Cell not found\n");
exit(0);
}
/* 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;
#ifndef DISABLE_UHD
if (!prog_args.input_file_name) {
printf("Opening UHD device...\n");
if (cuhd_open(prog_args.uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
/* Set receiver gain */
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
/* set receiver frequency */
cuhd_set_rx_freq(uhd, (double) prog_args.uhd_freq);
cuhd_rx_wait_lo_locked(uhd);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000);
ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
exit(-1);
} else if (ret == 0) {
printf("Cell not found\n");
exit(0);
}
/* 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;
}
INFO("Stopping UHD and flushing buffer...\r",0);
cuhd_stop_rx_stream(uhd);
cuhd_flush_buffer(uhd);
if (ue_mib_init(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
}
#endif
INFO("Stopping UHD and flushing buffer...\r",0);
cuhd_stop_rx_stream(uhd);
cuhd_flush_buffer(uhd);
if (ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper, uhd)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
/* If reading from file, go straight to PDSCH decoding. Otherwise, decode MIB first */
if (prog_args.input_file_name) {
state = DECODE_PDSCH;
/* preset cell configuration */
cell.id = 1;
cell.cp = CPNORM;
cell.phich_length = PHICH_NORM;
cell.phich_resources = R_1;
cell.nof_ports = 1;
cell.nof_prb = prog_args.file_nof_prb;
if (ue_sync_init_file(&ue_sync, prog_args.file_nof_prb, prog_args.input_file_name)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
} else {
state = DECODE_MIB;
if (ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper, uhd)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
}
if (ue_dl_init(&ue_dl, cell, prog_args.rnti==SIRNTI?1:prog_args.rnti)) { // This is the User RNTI
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
if (ue_mib_init(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
ue_dl_set_rnti(&ue_dl, prog_args.rnti);
@ -274,14 +322,18 @@ int main(int argc, char **argv) {
// Register Ctrl+C handler
signal(SIGINT, sig_int_handler);
#ifndef DISABLE_GRAPHICS
#ifndef DISABLE_GRAPHICS
if (!prog_args.disable_plots) {
init_plots(cell);
}
#endif
cuhd_start_rx_stream(uhd);
#endif
#ifndef DISABLE_UHD
if (!prog_args.input_file_name) {
cuhd_start_rx_stream(uhd);
}
#endif
// Variables for measurements
uint32_t nframes=0;
float rsrp=0.0, rsrq=0.0, snr=0.0;
@ -389,7 +441,7 @@ int main(int argc, char **argv) {
}
#ifndef DISABLE_GRAPHICS
if (!prog_args.disable_plots) {
do_plots(&ue_dl, ue_sync_get_sfidx(&ue_sync), &ue_sync);
do_plots(&ue_dl, ue_sync_get_sfidx(&ue_sync), !prog_args.input_file_name?&ue_sync:NULL);
}
#endif
} else if (ret == 0) {
@ -402,9 +454,14 @@ int main(int argc, char **argv) {
} // Main loop
ue_dl_free(&ue_dl);
ue_mib_free(&ue_mib);
ue_sync_free(&ue_sync);
cuhd_close(uhd);
#ifndef DISABLE_UHD
if (!prog_args.input_file_name) {
ue_mib_free(&ue_mib);
cuhd_close(uhd);
}
#endif
printf("\nBye\n");
exit(0);
}
@ -479,12 +536,15 @@ void do_plots(ue_dl_t *q, uint32_t sf_idx, ue_sync_t *qs) {
plot_waterfall_appendNewData(&poutfft, &tmp_plot[i*RE_X_RB*q->cell.nof_prb], RE_X_RB*q->cell.nof_prb);
}
plot_real_setNewData(&pce, tmp_plot2, REFSIGNAL_NUM_SF(q->cell.nof_prb,0));
int max = vec_max_fi(qs->strack.pss.conv_output_avg, qs->strack.pss.frame_size+qs->strack.pss.fft_size-1);
vec_sc_prod_fff(qs->strack.pss.conv_output_avg,
1/qs->strack.pss.conv_output_avg[max],
tmp_plot2,
qs->strack.pss.frame_size+qs->strack.pss.fft_size-1);
plot_real_setNewData(&p_sync, tmp_plot2, qs->strack.pss.frame_size);
if (qs) {
int max = vec_max_fi(qs->strack.pss.conv_output_avg, qs->strack.pss.frame_size+qs->strack.pss.fft_size-1);
vec_sc_prod_fff(qs->strack.pss.conv_output_avg,
1/qs->strack.pss.conv_output_avg[max],
tmp_plot2,
qs->strack.pss.frame_size+qs->strack.pss.fft_size-1);
plot_real_setNewData(&p_sync, tmp_plot2, qs->strack.pss.frame_size);
}
plot_scatter_setNewData(&pscatequal, q->pdsch.pdsch_d, nof_symbols);
plot_scatter_setNewData(&pscatequal_pdcch, q->pdcch.pdcch_d, 36*q->pdcch.nof_cce);

@ -36,6 +36,7 @@
#include "liblte/phy/ch_estimation/chest_dl.h"
#include "liblte/phy/phch/pbch.h"
#include "liblte/phy/common/fft.h"
#include "liblte/phy/io/filesource.h"
/**************************************************************
*
@ -46,6 +47,9 @@
* should be called regularly, returning every 1 ms. It reads from the
* USRP, aligns the samples to the subframe and performs time/freq synch.
*
* It is also possible to read the signal from a file using the init function
* ue_sync_init_file(). The sampling frequency is derived from the number of PRB.
*
* The function returns 1 when the signal is correctly acquired and the
* returned buffer is aligned with the subframe.
*
@ -62,6 +66,9 @@ typedef struct LIBLTE_API {
void *stream;
int (*recv_callback)(void*, void*, uint32_t);
filesource_t file_source;
bool file_mode;
ue_sync_state_t state;
cf_t *input_buffer;
@ -101,6 +108,10 @@ LIBLTE_API int ue_sync_init(ue_sync_t *q,
int (recv_callback)(void*, void*, uint32_t),
void *stream_handler);
LIBLTE_API int ue_sync_init_file(ue_sync_t *q,
uint32_t nof_prb,
char *file_name);
LIBLTE_API void ue_sync_free(ue_sync_t *q);
LIBLTE_API uint32_t ue_sync_sf_len(ue_sync_t *q);

@ -207,7 +207,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
int r = pdsch_decode(&pdsch, input_fft, ce, noise_power, data, sf_idx, &harq_process, rv);
tbs_is_zero:
if (nlhs >= 1) {
plhs[0] = mxCreateLogicalScalar(r == 0);
}

@ -34,9 +34,11 @@
#include "liblte/phy/ue/ue_sync.h"
#include "liblte/phy/io/filesource.h"
#include "liblte/phy/utils/debug.h"
#include "liblte/phy/utils/vector.h"
#define MAX_TIME_OFFSET 128
cf_t dummy[MAX_TIME_OFFSET];
@ -44,6 +46,40 @@ cf_t dummy[MAX_TIME_OFFSET];
#define TRACK_FRAME_SIZE 32
#define FIND_NOF_AVG_FRAMES 2
int ue_sync_init_file(ue_sync_t *q, uint32_t nof_prb, char *file_name) {
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
file_name != NULL &&
lte_nofprb_isvalid(nof_prb))
{
ret = LIBLTE_ERROR;
bzero(q, sizeof(ue_sync_t));
q->file_mode = true;
q->sf_len = SF_LEN(lte_symbol_sz(nof_prb));
if (filesource_init(&q->file_source, file_name, COMPLEX_FLOAT_BIN)) {
fprintf(stderr, "Error opening file %s\n", file_name);
goto clean_exit;
}
q->input_buffer = vec_malloc(q->sf_len * sizeof(cf_t));
if (!q->input_buffer) {
perror("malloc");
goto clean_exit;
}
ue_sync_reset(q);
ret = LIBLTE_SUCCESS;
}
clean_exit:
if (ret == LIBLTE_ERROR) {
ue_sync_free(q);
}
return ret;
}
int ue_sync_init(ue_sync_t *q,
lte_cell_t cell,
int (recv_callback)(void*, void*, uint32_t),
@ -65,7 +101,8 @@ int ue_sync_init(ue_sync_t *q,
q->cell = cell;
q->fft_size = lte_symbol_sz(q->cell.nof_prb);
q->sf_len = SF_LEN(q->fft_size);
q->file_mode = false;
if (cell.id == 1000) {
/* If the cell is unkown, decode SSS on track state */
q->decode_sss_on_track = true;
@ -155,9 +192,12 @@ void ue_sync_free(ue_sync_t *q) {
if (q->input_buffer) {
free(q->input_buffer);
}
sync_free(&q->sfind);
sync_free(&q->strack);
if (!q->file_mode) {
sync_free(&q->sfind);
sync_free(&q->strack);
} else {
filesource_free(&q->file_source);
}
bzero(q, sizeof(ue_sync_t));
}
@ -185,9 +225,11 @@ void ue_sync_decode_sss_on_track(ue_sync_t *q, bool enabled) {
}
void ue_sync_set_N_id_2(ue_sync_t *q, uint32_t N_id_2) {
ue_sync_reset(q);
sync_set_N_id_2(&q->strack, N_id_2);
sync_set_N_id_2(&q->sfind, N_id_2);
if (!q->file_mode) {
ue_sync_reset(q);
sync_set_N_id_2(&q->strack, N_id_2);
sync_set_N_id_2(&q->sfind, N_id_2);
}
}
static int find_peak_ok(ue_sync_t *q) {
@ -229,7 +271,7 @@ static int find_peak_ok(ue_sync_t *q) {
return 0;
}
int track_peak_ok(ue_sync_t *q, uint32_t track_idx) {
static int track_peak_ok(ue_sync_t *q, uint32_t track_idx) {
/* Make sure subframe idx is what we expect */
if ((q->sf_idx != sync_get_sf_idx(&q->strack)) && q->decode_sss_on_track) {
@ -269,7 +311,7 @@ int track_peak_ok(ue_sync_t *q, uint32_t track_idx) {
return 1;
}
int track_peak_no(ue_sync_t *q) {
static int track_peak_no(ue_sync_t *q) {
/* if we missed too many PSS go back to FIND */
q->frame_no_cnt++;
@ -316,87 +358,118 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
q->input_buffer != NULL)
{
if (receive_samples(q)) {
fprintf(stderr, "Error receiving samples\n");
return -1;
}
switch (q->state) {
case SF_FIND:
ret = sync_find(&q->sfind, q->input_buffer, 0, &q->peak_idx);
if (ret < 0) {
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
return LIBLTE_ERROR;
if (q->file_mode) {
usleep(1000);
int n = filesource_read(&q->file_source, q->input_buffer, q->sf_len);
if (n < 0) {
fprintf(stderr, "Error reading input file\n");
return LIBLTE_ERROR;
}
if (n == 0) {
filesource_seek(&q->file_source, 0);
q->sf_idx = 9;
int n = filesource_read(&q->file_source, q->input_buffer, q->sf_len);
if (n < 0) {
fprintf(stderr, "Error reading input file\n");
return LIBLTE_ERROR;
}
if (ret == 1) {
ret = find_peak_ok(q);
}
break;
case SF_TRACK:
ret = 1;
sync_sss_en(&q->strack, q->decode_sss_on_track);
q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10;
/* Every SF idx 0 and 5, find peak around known position q->peak_idx */
if (q->sf_idx == 0 || q->sf_idx == 5) {
#ifdef MEASURE_EXEC_TIME
struct timeval t[3];
gettimeofday(&t[1], NULL);
#endif
track_idx = 0;
/* track PSS/SSS around the expected PSS position */
ret = sync_find(&q->strack, q->input_buffer,
q->frame_len - q->sf_len/2 - q->fft_size - q->strack.frame_size/2,
&track_idx);
}
q->sf_idx++;
if (q->sf_idx == 10) {
q->sf_idx = 0;
}
INFO("Reading %d samples. sf_idx = %d\n", q->sf_len, q->sf_idx);
ret = 1;
*sf_symbols = q->input_buffer;
} else {
if (receive_samples(q)) {
fprintf(stderr, "Error receiving samples\n");
return LIBLTE_ERROR;
}
switch (q->state) {
case SF_FIND:
ret = sync_find(&q->sfind, q->input_buffer, 0, &q->peak_idx);
if (ret < 0) {
fprintf(stderr, "Error tracking correlation peak\n");
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
return LIBLTE_ERROR;
}
#ifdef MEASURE_EXEC_TIME
gettimeofday(&t[2], NULL);
get_time_interval(t);
q->mean_exec_time = (float) VEC_CMA((float) t[0].tv_usec, q->mean_exec_time, q->frame_total_cnt);
#endif
if (ret == 1) {
ret = track_peak_ok(q, track_idx);
} else {
ret = track_peak_no(q);
}
if (ret == LIBLTE_ERROR) {
fprintf(stderr, "Error processing tracking peak\n");
q->state = SF_FIND;
return LIBLTE_SUCCESS;
ret = find_peak_ok(q);
}
q->frame_total_cnt++;
}
/* Do CFO Correction if not done in track and deliver the frame */
if (!q->strack.correct_cfo) {
cfo_correct(&q->sfind.cfocorr,
q->input_buffer,
q->input_buffer,
-sync_get_cfo(&q->strack) / q->fft_size);
}
*sf_symbols = q->input_buffer;
break;
break;
case SF_TRACK:
ret = 1;
sync_sss_en(&q->strack, q->decode_sss_on_track);
q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10;
/* Every SF idx 0 and 5, find peak around known position q->peak_idx */
if (q->sf_idx == 0 || q->sf_idx == 5) {
#ifdef MEASURE_EXEC_TIME
struct timeval t[3];
gettimeofday(&t[1], NULL);
#endif
track_idx = 0;
/* track PSS/SSS around the expected PSS position */
ret = sync_find(&q->strack, q->input_buffer,
q->frame_len - q->sf_len/2 - q->fft_size - q->strack.frame_size/2,
&track_idx);
if (ret < 0) {
fprintf(stderr, "Error tracking correlation peak\n");
return LIBLTE_ERROR;
}
#ifdef MEASURE_EXEC_TIME
gettimeofday(&t[2], NULL);
get_time_interval(t);
q->mean_exec_time = (float) VEC_CMA((float) t[0].tv_usec, q->mean_exec_time, q->frame_total_cnt);
#endif
if (ret == 1) {
ret = track_peak_ok(q, track_idx);
} else {
ret = track_peak_no(q);
}
if (ret == LIBLTE_ERROR) {
fprintf(stderr, "Error processing tracking peak\n");
q->state = SF_FIND;
return LIBLTE_SUCCESS;
}
q->frame_total_cnt++;
}
/* Do CFO Correction if not done in track and deliver the frame */
if (!q->strack.correct_cfo) {
cfo_correct(&q->sfind.cfocorr,
q->input_buffer,
q->input_buffer,
-sync_get_cfo(&q->strack) / q->fft_size);
}
*sf_symbols = q->input_buffer;
break;
}
}
}
return ret;
}
void ue_sync_reset(ue_sync_t *q) {
if (!q->file_mode) {
sync_reset(&q->strack);
} else {
q->sf_idx = 9;
}
q->state = SF_FIND;
sync_reset(&q->strack);
q->frame_ok_cnt = 0;
q->frame_no_cnt = 0;
q->frame_total_cnt = 0;
@ -405,6 +478,6 @@ void ue_sync_reset(ue_sync_t *q) {
q->frame_find_cnt = 0;
#ifdef MEASURE_EXEC_TIME
q->mean_exec_time = 0;
#endif
#endif
}

Loading…
Cancel
Save