From 83e3250c295d2987197489e685d050b0995ae265 Mon Sep 17 00:00:00 2001 From: ismagom Date: Tue, 24 Feb 2015 11:19:42 +0100 Subject: [PATCH] Added PRACH example. Added timed send/recv functions to cuhd --- cuhd/include/liblte/cuhd/cuhd.h | 24 +- cuhd/lib/cuhd_imp.cpp | 52 ++- lte/examples/CMakeLists.txt | 3 + lte/examples/cell_measurement.c | 4 +- lte/examples/cell_search.c | 2 +- lte/examples/cuhd_utils.c | 2 +- lte/examples/pdsch_ue.c | 8 +- lte/examples/prach_ue.c | 370 ++++++++++++++++++ lte/phy/include/liblte/phy/common/timestamp.h | 53 +++ lte/phy/include/liblte/phy/phch/pbch.h | 13 + lte/phy/include/liblte/phy/phy.h | 2 + .../include/liblte/phy/ue/ue_cell_search.h | 4 +- lte/phy/include/liblte/phy/ue/ue_dl.h | 6 +- lte/phy/include/liblte/phy/ue/ue_mib.h | 2 +- lte/phy/include/liblte/phy/ue/ue_sync.h | 10 +- lte/phy/include/liblte/phy/utils/vector.h | 8 + lte/phy/lib/common/src/timestamp.c | 82 ++++ lte/phy/lib/phch/src/pbch.c | 110 ++++++ lte/phy/lib/ue/src/ue_cell_search.c | 7 +- lte/phy/lib/ue/src/ue_dl.c | 13 +- lte/phy/lib/ue/src/ue_mib.c | 2 +- lte/phy/lib/ue/src/ue_sync.c | 12 +- 22 files changed, 746 insertions(+), 43 deletions(-) create mode 100644 lte/examples/prach_ue.c create mode 100644 lte/phy/include/liblte/phy/common/timestamp.h create mode 100644 lte/phy/lib/common/src/timestamp.c diff --git a/cuhd/include/liblte/cuhd/cuhd.h b/cuhd/include/liblte/cuhd/cuhd.h index e1604b93d..bf15fce25 100644 --- a/cuhd/include/liblte/cuhd/cuhd.h +++ b/cuhd/include/liblte/cuhd/cuhd.h @@ -71,27 +71,41 @@ LIBLTE_API int cuhd_recv(void *h, bool blocking); LIBLTE_API int cuhd_recv_timed(void *h, - void *data, - uint32_t nsamples, - bool blocking, - time_t *secs, - double *frac_secs); + void *data, + uint32_t nsamples, + bool blocking, + time_t *secs, + double *frac_secs); LIBLTE_API double cuhd_set_tx_srate(void *h, double freq); +LIBLTE_API void cuhd_set_tx_antenna(void *h, + char *name); + LIBLTE_API double cuhd_set_tx_gain(void *h, double gain); LIBLTE_API double cuhd_set_tx_freq(void *h, double freq); +LIBLTE_API double cuhd_set_tx_freq_offset(void *h, + double freq, + double off); + LIBLTE_API int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking); +LIBLTE_API int cuhd_send_timed(void *h, + void *data, + int nsamples, + int blocking, + time_t secs, + double frac_secs); + #ifdef __cplusplus } #endif diff --git a/cuhd/lib/cuhd_imp.cpp b/cuhd/lib/cuhd_imp.cpp index 53be35156..21703bcbd 100644 --- a/cuhd/lib/cuhd_imp.cpp +++ b/cuhd/lib/cuhd_imp.cpp @@ -214,11 +214,12 @@ int cuhd_recv(void *h, void *data, uint32_t nsamples, bool blocking) } int cuhd_recv_timed(void *h, - void *data, - uint32_t nsamples, - int blocking, - time_t *secs, - double *frac_secs) { + void *data, + uint32_t nsamples, + bool blocking, + time_t *secs, + double *frac_secs) +{ cuhd_handler* handler = static_cast(h); uhd::rx_metadata_t md; *secs = -1; @@ -247,7 +248,11 @@ int cuhd_recv_timed(void *h, } } - +void cuhd_set_tx_antenna(void *h, char *name) +{ + cuhd_handler *handler = static_cast < cuhd_handler * >(h); + handler->usrp->set_tx_antenna(name, 0); +} double cuhd_set_tx_gain(void *h, double gain) { cuhd_handler *handler = static_cast < cuhd_handler * >(h); @@ -269,6 +274,13 @@ double cuhd_set_tx_freq(void *h, double freq) return handler->usrp->get_tx_freq(); } +double cuhd_set_tx_freq_offset(void *h, double freq, double off) { + cuhd_handler* handler = static_cast(h); + handler->usrp->set_tx_freq(uhd::tune_request_t(freq, off)); + return handler->usrp->get_tx_freq(); +} + + int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking) { cuhd_handler *handler = static_cast < cuhd_handler * >(h); @@ -288,3 +300,31 @@ int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking) return handler->tx_stream->send(data, nsamples, md, 0.0); } } + + +int cuhd_send_timed(void *h, + void *data, + int nsamples, + int blocking, + time_t secs, + double frac_secs) { + cuhd_handler* handler = static_cast(h); + uhd::tx_metadata_t md; + md.has_time_spec = true; + md.time_spec = uhd::time_spec_t(secs, frac_secs); + if (blocking) { + int n=0,p; + complex_t *data_c = (complex_t*) data; + do { + p=handler->tx_stream->send(&data_c[n], nsamples-n, md); + md.has_time_spec = false; + if (p == -1) { + return -1; + } + n+=p; + } while(ntx_stream->send(data, nsamples, md, 0.0); + } +} diff --git a/lte/examples/CMakeLists.txt b/lte/examples/CMakeLists.txt index 74febba3b..477d06b15 100644 --- a/lte/examples/CMakeLists.txt +++ b/lte/examples/CMakeLists.txt @@ -83,6 +83,9 @@ IF(${CUHD_FIND} GREATER -1) add_executable(cell_search cell_search.c cuhd_utils.c) target_link_libraries(cell_search lte_rrc lte_phy cuhd ) + add_executable(prach_ue prach_ue.c cuhd_utils.c) + target_link_libraries(prach_ue lte_rrc lte_phy cuhd) + add_executable(cell_measurement cell_measurement.c cuhd_utils.c) target_link_libraries(cell_measurement cuhd lte_rrc lte_phy) diff --git a/lte/examples/cell_measurement.c b/lte/examples/cell_measurement.c index c37405d3f..364f3d097 100644 --- a/lte/examples/cell_measurement.c +++ b/lte/examples/cell_measurement.c @@ -120,7 +120,7 @@ int parse_args(prog_args_t *args, int argc, char **argv) { /* TODO: Do something with the output data */ uint8_t data[10000], data_unpacked[1000]; -int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples) { +int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, timestamp_t *q) { DEBUG(" ---- Receive %d samples ---- \n", nsamples); return cuhd_recv(h, data, nsamples, 1); } @@ -196,7 +196,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error initiating ue_sync\n"); return -1; } - if (ue_dl_init(&ue_dl, cell, 1234)) { + if (ue_dl_init(&ue_dl, cell)) { fprintf(stderr, "Error initiating UE downlink processing module\n"); return -1; } diff --git a/lte/examples/cell_search.c b/lte/examples/cell_search.c index 6f1072ac8..8bda32999 100644 --- a/lte/examples/cell_search.c +++ b/lte/examples/cell_search.c @@ -111,7 +111,7 @@ void parse_args(int argc, char **argv) { } } -int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples) { +int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, timestamp_t *t) { DEBUG(" ---- Receive %d samples ---- \n", nsamples); return cuhd_recv(h, data, nsamples, 1); } diff --git a/lte/examples/cuhd_utils.c b/lte/examples/cuhd_utils.c index 3199e3ec7..c0a67965d 100644 --- a/lte/examples/cuhd_utils.c +++ b/lte/examples/cuhd_utils.c @@ -43,7 +43,7 @@ #ifndef DISABLE_UHD #include "liblte/cuhd/cuhd.h" -int cuhd_recv_wrapper_cs(void *h, void *data, uint32_t nsamples) { +int cuhd_recv_wrapper_cs(void *h, void *data, uint32_t nsamples, timestamp_t *t) { DEBUG(" ---- Receive %d samples ---- \n", nsamples); return cuhd_recv(h, data, nsamples, 1); } diff --git a/lte/examples/pdsch_ue.c b/lte/examples/pdsch_ue.c index bfa045a1e..11940e9ab 100644 --- a/lte/examples/pdsch_ue.c +++ b/lte/examples/pdsch_ue.c @@ -107,7 +107,7 @@ void args_default(prog_args_t *args) { void usage(prog_args_t *args, char *prog) { printf("Usage: %s [agildnruv] -f rx_frequency (in Hz) | -i input_file\n", prog); -#ifndef DISABLE_GRAPHICS +#ifndef DISABLE_UHD 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 @@ -202,7 +202,7 @@ void sig_int_handler(int signo) } #ifndef DISABLE_UHD -int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples) { +int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, timestamp_t *t) { DEBUG(" ---- Receive %d samples ---- \n", nsamples); return cuhd_recv(h, data, nsamples, 1); } @@ -320,10 +320,12 @@ int main(int argc, char **argv) { #endif } - if (ue_dl_init(&ue_dl, cell, prog_args.rnti==SIRNTI?1:prog_args.rnti)) { // This is the User RNTI + if (ue_dl_init(&ue_dl, cell)) { // This is the User RNTI fprintf(stderr, "Error initiating UE downlink processing module\n"); exit(-1); } + + ue_dl_set_user_rnti(&ue_dl, prog_args.rnti==SIRNTI?1:prog_args.rnti); /* 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); diff --git a/lte/examples/prach_ue.c b/lte/examples/prach_ue.c new file mode 100644 index 000000000..5dcae6e1b --- /dev/null +++ b/lte/examples/prach_ue.c @@ -0,0 +1,370 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The libLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the libLTE library. + * + * libLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * A copy of the GNU Lesser General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liblte/rrc/rrc.h" +#include "liblte/phy/phy.h" + + +#include "liblte/cuhd/cuhd.h" +#include "cuhd_utils.h" + +cell_search_cfg_t cell_detect_config = { + 5000, + 100, // nof_frames_total + 16.0 // threshold +}; + +#define B210_DEFAULT_GAIN 40.0 +#define B210_DEFAULT_GAIN_CORREC 110.0 // Gain of the Rx chain when the gain is set to 40 + +float gain_offset = B210_DEFAULT_GAIN_CORREC; + +double pss_time_offset = (6/14)*10e-3; +double prach_time_offset = 4*10e-3; //Subframe 4 + + +/********************************************************************** + * Program arguments processing + ***********************************************************************/ +typedef struct { + int nof_subframes; + int force_N_id_2; + uint16_t rnti; + uint32_t file_nof_prb; + char *uhd_args; + float uhd_rx_freq; + float uhd_tx_freq; + float uhd_tx_freq_offset; + float uhd_gain; + int net_port; + char *net_address; + int net_port_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->file_nof_prb = 6; + args->uhd_args = ""; + args->uhd_rx_freq = 2112500000.0; + args->uhd_tx_freq = 1922500000.0; + args->uhd_tx_freq_offset = 8000000.0; + args->uhd_gain = 60.0; + args->net_port = -1; + args->net_address = "127.0.0.1"; + args->net_port_signal = -1; + args->net_address_signal = "127.0.0.1"; +} + +void usage(prog_args_t *args, char *prog) { + printf("Usage: %s [agfFrlnv]\n", prog); + printf("\t-a UHD args [Default %s]\n", args->uhd_args); + printf("\t-g UHD TX/RX gain [Default %.2f dB]\n", args->uhd_gain); + printf("\t-f UHD RX freq [Default %.1f MHz]\n", args->uhd_rx_freq/1000000); + printf("\t-F UHD TX freq [Default %.1f MHz]\n", args->uhd_tx_freq/1000000); + printf("\t-r RNTI [Default 0x%x]\n",args->rnti); + printf("\t-l Force N_id_2 [Default best]\n"); + printf("\t-n nof_subframes [Default %d]\n", args->nof_subframes); + printf("\t-v [set verbose to debug, default none]\n"); +} + +void parse_args(prog_args_t *args, int argc, char **argv) { + int opt; + args_default(args); + while ((opt = getopt(argc, argv, "agfFrlnv")) != -1) { + switch (opt) { + case 'a': + args->uhd_args = argv[optind]; + break; + case 'g': + args->uhd_gain = atof(argv[optind]); + break; + case 'f': + args->uhd_rx_freq = atof(argv[optind]); + break; + case 'F': + args->uhd_tx_freq = atof(argv[optind]); + break; + case 'n': + args->nof_subframes = atoi(argv[optind]); + break; + case 'r': + args->rnti = atoi(argv[optind]); + break; + case 'l': + args->force_N_id_2 = atoi(argv[optind]); + break; + case 'v': + verbose++; + break; + default: + usage(args, argv[0]); + exit(-1); + } + } + if (args->uhd_tx_freq < 0 && args->uhd_rx_freq < 0) { + usage(args, argv[0]); + exit(-1); + } +} +/**********************************************************************/ + +/* TODO: Do something with the output data */ +uint8_t data[20000], data_packed[20000]; + +bool go_exit = false; + +void sig_int_handler(int signo) +{ + if (signo == SIGINT) { + go_exit = true; + } +} + +int cuhd_recv_wrapper_timed(void *h, void *data, uint32_t nsamples, timestamp_t *uhd_time) { + DEBUG(" ---- Receive %d samples ---- \n", nsamples); + return cuhd_recv_timed(h, data, nsamples, 1, &uhd_time->full_secs, &uhd_time->frac_secs); +} + +extern float mean_exec_time; + +enum receiver_state { DECODE_MIB, SEND_PRACH} state; + +#define NOF_PRACH_SEQUENCES 52 + +ue_dl_t ue_dl; +ue_sync_t ue_sync; +prach_t prach; +cf_t *prach_buffers[NOF_PRACH_SEQUENCES]; +int prach_buffer_len; + +prog_args_t prog_args; + +uint32_t sfn = 0; // system frame number +cf_t *sf_buffer = NULL; + + +int generate_prach_sequences(){ + for(int i=0;i +#include "liblte/config.h" + +/*! + * A simple timestamp struct with separate variables for full and frac seconds. + * + * Separate variables are used to avoid loss of precision in our frac seconds. + * Only positive timestamps are supported. + */ + +typedef struct LIBLTE_API{ + time_t full_secs; + double frac_secs; +}timestamp_t; + +LIBLTE_API int timestamp_init(timestamp_t *t, time_t full_secs, double frac_secs); +LIBLTE_API int timestamp_copy(timestamp_t *dest, timestamp_t *src); +LIBLTE_API int timestamp_add(timestamp_t *t, time_t full_secs, double frac_secs); +LIBLTE_API int timestamp_sub(timestamp_t *t, time_t full_secs, double frac_secs); +LIBLTE_API double timestamp_real(timestamp_t *t); + +#endif // TIMESTAMP_ diff --git a/lte/phy/include/liblte/phy/phch/pbch.h b/lte/phy/include/liblte/phy/phch/pbch.h index d0399a4de..0f93e17fe 100644 --- a/lte/phy/include/liblte/phy/phch/pbch.h +++ b/lte/phy/include/liblte/phy/phch/pbch.h @@ -99,4 +99,17 @@ LIBLTE_API int pbch_encode(pbch_t *q, LIBLTE_API void pbch_decode_reset(pbch_t *q); +LIBLTE_API void pbch_mib_unpack(uint8_t *msg, + lte_cell_t *cell, + uint32_t *sfn); + +LIBLTE_API void pbch_mib_pack(lte_cell_t *cell, + uint32_t sfn, + uint8_t *msg); + +LIBLTE_API void pbch_mib_fprint(FILE *stream, + lte_cell_t *cell, + uint32_t sfn, + uint32_t cell_id); + #endif // PBCH_ diff --git a/lte/phy/include/liblte/phy/phy.h b/lte/phy/include/liblte/phy/phy.h index 4e27adb2d..8a1a3cbdb 100644 --- a/lte/phy/include/liblte/phy/phy.h +++ b/lte/phy/include/liblte/phy/phy.h @@ -48,6 +48,8 @@ #include "liblte/phy/utils/pack.h" #include "liblte/phy/utils/vector.h" +#include "liblte/phy/common/timestamp.h" +#include "liblte/phy/common/sequence.h" #include "liblte/phy/common/phy_common.h" #include "liblte/phy/common/fft.h" diff --git a/lte/phy/include/liblte/phy/ue/ue_cell_search.h b/lte/phy/include/liblte/phy/ue/ue_cell_search.h index 644ed955a..cdd0d50d6 100644 --- a/lte/phy/include/liblte/phy/ue/ue_cell_search.h +++ b/lte/phy/include/liblte/phy/ue/ue_cell_search.h @@ -86,12 +86,12 @@ typedef struct LIBLTE_API { LIBLTE_API int ue_cell_search_init(ue_cell_search_t *q, - int (recv_callback)(void*, void*, uint32_t), + int (recv_callback)(void*, void*, uint32_t,timestamp_t*), void *stream_handler); LIBLTE_API int ue_cell_search_init_max(ue_cell_search_t *q, uint32_t max_frames_total, - int (recv_callback)(void*, void*, uint32_t), + int (recv_callback)(void*, void*, uint32_t,timestamp_t*), void *stream_handler); LIBLTE_API void ue_cell_search_free(ue_cell_search_t *q); diff --git a/lte/phy/include/liblte/phy/ue/ue_dl.h b/lte/phy/include/liblte/phy/ue/ue_dl.h index 2128b82ba..71a4d1bba 100644 --- a/lte/phy/include/liblte/phy/ue/ue_dl.h +++ b/lte/phy/include/liblte/phy/ue/ue_dl.h @@ -81,8 +81,7 @@ typedef struct LIBLTE_API { /* This function shall be called just after the initial synchronization */ LIBLTE_API int ue_dl_init(ue_dl_t *q, - lte_cell_t cell, - uint16_t user_rnti); + lte_cell_t cell); LIBLTE_API void ue_dl_free(ue_dl_t *q); @@ -102,4 +101,7 @@ LIBLTE_API void ue_dl_reset(ue_dl_t *q); LIBLTE_API void ue_dl_set_rnti(ue_dl_t *q, uint16_t rnti); +LIBLTE_API void ue_dl_set_user_rnti(ue_dl_t *q, + uint16_t user_rnti); + #endif \ No newline at end of file diff --git a/lte/phy/include/liblte/phy/ue/ue_mib.h b/lte/phy/include/liblte/phy/ue/ue_mib.h index 836f014c8..f36dc6067 100644 --- a/lte/phy/include/liblte/phy/ue/ue_mib.h +++ b/lte/phy/include/liblte/phy/ue/ue_mib.h @@ -104,7 +104,7 @@ typedef struct { LIBLTE_API int ue_mib_sync_init(ue_mib_sync_t *q, uint32_t cell_id, lte_cp_t cp, - int (recv_callback)(void*, void*, uint32_t), + int (recv_callback)(void*, void*, uint32_t, timestamp_t *), void *stream_handler); LIBLTE_API void ue_mib_sync_free(ue_mib_sync_t *q); diff --git a/lte/phy/include/liblte/phy/ue/ue_sync.h b/lte/phy/include/liblte/phy/ue/ue_sync.h index 35d0c20a6..a768cc2be 100644 --- a/lte/phy/include/liblte/phy/ue/ue_sync.h +++ b/lte/phy/include/liblte/phy/ue/ue_sync.h @@ -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/common/timestamp.h" #include "liblte/phy/io/filesource.h" /************************************************************** @@ -64,8 +65,9 @@ typedef struct LIBLTE_API { sync_t strack; void *stream; - int (*recv_callback)(void*, void*, uint32_t); - + int (*recv_callback)(void*, void*, uint32_t, timestamp_t*); + timestamp_t last_timestamp; + filesource_t file_source; bool file_mode; @@ -105,7 +107,7 @@ typedef struct LIBLTE_API { LIBLTE_API int ue_sync_init(ue_sync_t *q, lte_cell_t cell, - int (recv_callback)(void*, void*, uint32_t), + int (recv_callback)(void*, void*, uint32_t, timestamp_t*), void *stream_handler); LIBLTE_API int ue_sync_init_file(ue_sync_t *q, @@ -135,6 +137,8 @@ LIBLTE_API float ue_sync_get_cfo(ue_sync_t *q); LIBLTE_API float ue_sync_get_sfo(ue_sync_t *q); +LIBLTE_API void ue_sync_get_last_timestamp(ue_sync_t *q, + timestamp_t *timestamp); diff --git a/lte/phy/include/liblte/phy/utils/vector.h b/lte/phy/include/liblte/phy/utils/vector.h index 00671534b..bf64ec93d 100644 --- a/lte/phy/include/liblte/phy/utils/vector.h +++ b/lte/phy/include/liblte/phy/utils/vector.h @@ -29,6 +29,10 @@ #ifndef VECTOR_ #define VECTOR_ +#ifdef __cplusplus +extern "C" { +#endif + #include #include #include "liblte/config.h" @@ -137,4 +141,8 @@ LIBLTE_API void vec_abs_square_cf(cf_t *x, float *abs_square, uint32_t len); /* argument of each vector element */ LIBLTE_API void vec_arg_cf(cf_t *x, float *arg, uint32_t len); +#ifdef __cplusplus +} +#endif + #endif // VECTOR_ diff --git a/lte/phy/lib/common/src/timestamp.c b/lte/phy/lib/common/src/timestamp.c new file mode 100644 index 000000000..a2a894e59 --- /dev/null +++ b/lte/phy/lib/common/src/timestamp.c @@ -0,0 +1,82 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The libLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the libLTE library. + * + * libLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * A copy of the GNU Lesser General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "liblte/phy/common/timestamp.h" +#include "math.h" + +int timestamp_init(timestamp_t *t, time_t full_secs, double frac_secs){ + int ret = LIBLTE_ERROR; + if(t != NULL && frac_secs >= 0.0){ + t->full_secs = full_secs; + t->frac_secs = frac_secs; + ret = LIBLTE_SUCCESS; + } + return ret; +} + +int timestamp_copy(timestamp_t *dest, timestamp_t *src){ + int ret = LIBLTE_ERROR; + if(dest != NULL && src != NULL){ + dest->full_secs = src->full_secs; + dest->frac_secs = src->frac_secs; + ret = LIBLTE_SUCCESS; + } + return ret; +} + +int timestamp_add(timestamp_t *t, time_t full_secs, double frac_secs){ + int ret = LIBLTE_ERROR; + if(t != NULL && frac_secs >= 0.0){ + t->frac_secs += frac_secs; + t->full_secs += full_secs; + double r = floor(t->frac_secs); + t->full_secs += r; + t->frac_secs -= r; + ret = LIBLTE_SUCCESS; + } + return ret; +} + +int timestamp_sub(timestamp_t *t, time_t full_secs, double frac_secs){ + int ret = LIBLTE_ERROR; + if(t != NULL && frac_secs >= 0.0){ + t->frac_secs -= frac_secs; + t->full_secs -= full_secs; + if(t->frac_secs < 0){ + t->frac_secs = 1-t->frac_secs; + t->full_secs--; + } + if(t->full_secs < 0) + return LIBLTE_ERROR; + ret = LIBLTE_SUCCESS; + } + return ret; +} + +double timestamp_real(timestamp_t *t){ + return t->frac_secs + t->full_secs; +} diff --git a/lte/phy/lib/phch/src/pbch.c b/lte/phy/lib/phch/src/pbch.c index b251882de..80b6337f9 100644 --- a/lte/phy/lib/phch/src/pbch.c +++ b/lte/phy/lib/phch/src/pbch.c @@ -241,6 +241,116 @@ void pbch_free(pbch_t *q) { } + +/** Unpacks MIB from PBCH message. + * msg buffer must be 24 byte length at least + */ +void pbch_mib_unpack(uint8_t *msg, lte_cell_t *cell, uint32_t *sfn) { + int bw, phich_res; + + bw = bit_unpack(&msg, 3); + switch (bw) { + case 0: + cell->nof_prb = 6; + break; + case 1: + cell->nof_prb = 15; + break; + default: + cell->nof_prb = (bw - 1) * 25; + break; + } + if (*msg) { + cell->phich_length = PHICH_EXT; + } else { + cell->phich_length = PHICH_NORM; + } + msg++; + + phich_res = bit_unpack(&msg, 2); + switch (phich_res) { + case 0: + cell->phich_resources = R_1_6; + break; + case 1: + cell->phich_resources = R_1_2; + break; + case 2: + cell->phich_resources = R_1; + break; + case 3: + cell->phich_resources = R_2; + break; + } + if (sfn) { + *sfn = bit_unpack(&msg, 8) << 2; + } +} + +/** Unpacks MIB from PBCH message. + * msg buffer must be 24 byte length at least + */ +void pbch_mib_pack(lte_cell_t *cell, uint32_t sfn, uint8_t *msg) { + int bw, phich_res = 0; + + bzero(msg, 24); + + if (cell->nof_prb <= 6) { + bw = 0; + } else if (cell->nof_prb <= 15) { + bw = 1; + } else { + bw = 1 + cell->nof_prb / 25; + } + bit_pack(bw, &msg, 3); + + *msg = cell->phich_length == PHICH_EXT; + msg++; + + switch (cell->phich_resources) { + case R_1_6: + phich_res = 0; + break; + case R_1_2: + phich_res = 1; + break; + case R_1: + phich_res = 2; + break; + case R_2: + phich_res = 3; + break; + } + bit_pack(phich_res, &msg, 2); + bit_pack(sfn >> 2, &msg, 8); +} + +void pbch_mib_fprint(FILE *stream, lte_cell_t *cell, uint32_t sfn, uint32_t cell_id) { + printf(" - Cell ID: %d\n", cell_id); + printf(" - Nof ports: %d\n", cell->nof_ports); + printf(" - PRB: %d\n", cell->nof_prb); + printf(" - PHICH Length: %s\n", + cell->phich_length == PHICH_EXT ? "Extended" : "Normal"); + printf(" - PHICH Resources: "); + switch (cell->phich_resources) { + case R_1_6: + printf("1/6"); + break; + case R_1_2: + printf("1/2"); + break; + case R_1: + printf("1"); + break; + case R_2: + printf("2"); + break; + } + printf("\n"); + printf(" - SFN: %d\n", sfn); +} + + void pbch_decode_reset(pbch_t *q) { q->frame_idx = 0; } diff --git a/lte/phy/lib/ue/src/ue_cell_search.c b/lte/phy/lib/ue/src/ue_cell_search.c index 5cab42fb8..6baa2e31c 100644 --- a/lte/phy/lib/ue/src/ue_cell_search.c +++ b/lte/phy/lib/ue/src/ue_cell_search.c @@ -39,13 +39,13 @@ float tmp_pss_corr[32*10000]; float tmp_sss_corr[31*10000]; -int ue_cell_search_init(ue_cell_search_t * q, int (recv_callback)(void*, void*, uint32_t), void *stream_handler) +int ue_cell_search_init(ue_cell_search_t * q, int (recv_callback)(void*, void*, uint32_t,timestamp_t*), void *stream_handler) { return ue_cell_search_init_max(q, CS_DEFAULT_MAXFRAMES_TOTAL, recv_callback, stream_handler); } int ue_cell_search_init_max(ue_cell_search_t * q, uint32_t max_frames, - int (recv_callback)(void*, void*, uint32_t), void *stream_handler) + int (recv_callback)(void*, void*, uint32_t,timestamp_t*), void *stream_handler) { int ret = LIBLTE_ERROR_INVALID_INPUTS; @@ -270,9 +270,6 @@ int ue_cell_search_scan_N_id_2(ue_cell_search_t * q, uint32_t N_id_2, ue_cell_se ret = 1; // A cell has been found. if (found_cell) { get_cell(q, nof_detected_frames, found_cell); - printf("Found CELL PHYID: %d, CP: %s, PSR: %.1f, Absolute Peak: %.1f dBm, Reliability: %.0f \%\n", - found_cell->cell_id, lte_cp_string(found_cell->cp), - found_cell->psr, 10*log10(found_cell->peak*1000), 100*found_cell->mode); } } else { ret = 0; // A cell was not found. diff --git a/lte/phy/lib/ue/src/ue_dl.c b/lte/phy/lib/ue/src/ue_dl.c index 5975b15d9..72a67a191 100644 --- a/lte/phy/lib/ue/src/ue_dl.c +++ b/lte/phy/lib/ue/src/ue_dl.c @@ -39,8 +39,7 @@ #define MAX_CANDIDATES 64 int ue_dl_init(ue_dl_t *q, - lte_cell_t cell, - uint16_t user_rnti) + lte_cell_t cell) { int ret = LIBLTE_ERROR_INVALID_INPUTS; @@ -52,7 +51,7 @@ int ue_dl_init(ue_dl_t *q, bzero(q, sizeof(ue_dl_t)); q->cell = cell; - q->user_rnti = user_rnti; + q->user_rnti = 0; q->pkt_errors = 0; q->pkts_total = 0; @@ -144,6 +143,10 @@ void ue_dl_free(ue_dl_t *q) { } } +void ue_dl_set_user_rnti(ue_dl_t *q, uint16_t user_rnti) { + q->user_rnti = user_rnti; +} + void ue_dl_set_rnti(ue_dl_t *q, uint16_t rnti) { q->current_rnti = rnti; pdsch_set_rnti(&q->pdsch, rnti); @@ -217,10 +220,6 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui nof_locations = pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, q->current_rnti); formats = ue_formats; nof_formats = nof_ue_formats; - if (q->current_rnti == 1234) { - nof_locations = 1; - nof_formats = 1; - } } /* Extract all PDCCH symbols and get LLRs */ diff --git a/lte/phy/lib/ue/src/ue_mib.c b/lte/phy/lib/ue/src/ue_mib.c index e8f6c7096..512aeca99 100644 --- a/lte/phy/lib/ue/src/ue_mib.c +++ b/lte/phy/lib/ue/src/ue_mib.c @@ -159,7 +159,7 @@ int ue_mib_decode(ue_mib_t * q, cf_t *input, int ue_mib_sync_init(ue_mib_sync_t *q, uint32_t cell_id, lte_cp_t cp, - int (recv_callback)(void*, void*, uint32_t), + int (recv_callback)(void*, void*, uint32_t, timestamp_t*), void *stream_handler) { lte_cell_t cell; diff --git a/lte/phy/lib/ue/src/ue_sync.c b/lte/phy/lib/ue/src/ue_sync.c index e5944f9cb..137342d7e 100644 --- a/lte/phy/lib/ue/src/ue_sync.c +++ b/lte/phy/lib/ue/src/ue_sync.c @@ -82,7 +82,7 @@ clean_exit: int ue_sync_init(ue_sync_t *q, lte_cell_t cell, - int (recv_callback)(void*, void*, uint32_t), + int (recv_callback)(void*, void*, uint32_t,timestamp_t*), void *stream_handler) { int ret = LIBLTE_ERROR_INVALID_INPUTS; @@ -201,6 +201,10 @@ void ue_sync_free(ue_sync_t *q) { bzero(q, sizeof(ue_sync_t)); } +void ue_sync_get_last_timestamp(ue_sync_t *q, timestamp_t *timestamp) { + memcpy(timestamp, &q->last_timestamp, sizeof(timestamp_t)); +} + uint32_t ue_sync_peak_idx(ue_sync_t *q) { return q->peak_idx; } @@ -250,7 +254,7 @@ static int find_peak_ok(ue_sync_t *q) { if (q->frame_find_cnt >= q->nof_avg_find_frames || q->peak_idx < 2*q->fft_size) { INFO("Realigning frame, reading %d samples\n", q->peak_idx+q->sf_len/2); /* Receive the rest of the subframe so that we are subframe aligned*/ - if (q->recv_callback(q->stream, q->input_buffer, q->peak_idx+q->sf_len/2) < 0) { + if (q->recv_callback(q->stream, q->input_buffer, q->peak_idx+q->sf_len/2, &q->last_timestamp) < 0) { return LIBLTE_ERROR; } @@ -297,7 +301,7 @@ static int track_peak_ok(ue_sync_t *q, uint32_t track_idx) { discard the offseted samples to align next frame */ if (q->time_offset > 0 && q->time_offset < MAX_TIME_OFFSET) { INFO("\nPositive time offset %d samples. Mean time offset %f.\n", q->time_offset, q->mean_time_offset); - if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset) < 0) { + if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset, &q->last_timestamp) < 0) { fprintf(stderr, "Error receiving from USRP\n"); return LIBLTE_ERROR; } @@ -337,7 +341,7 @@ static int receive_samples(ue_sync_t *q) { } /* Get N subframes from the USRP getting more samples and keeping the previous samples, if any */ - if (q->recv_callback(q->stream, &q->input_buffer[q->time_offset], q->frame_len - q->time_offset) < 0) { + if (q->recv_callback(q->stream, &q->input_buffer[q->time_offset], q->frame_len - q->time_offset, &q->last_timestamp) < 0) { return LIBLTE_ERROR; }