diff --git a/lib/include/srslte/phy/channel/channel.h b/lib/include/srslte/phy/channel/channel.h index 76062658e..9278739f6 100644 --- a/lib/include/srslte/phy/channel/channel.h +++ b/lib/include/srslte/phy/channel/channel.h @@ -25,6 +25,7 @@ #include "delay.h" #include "fading.h" #include "rlf.h" +#include #include #include #include @@ -70,6 +71,8 @@ private: args_t args; }; +typedef std::unique_ptr channel_ptr; + } // namespace srslte #endif // SRSLTE_CHANNEL_H diff --git a/lib/include/srslte/phy/utils/random.h b/lib/include/srslte/phy/utils/random.h index cfcf753f4..311f3d936 100644 --- a/lib/include/srslte/phy/utils/random.h +++ b/lib/include/srslte/phy/utils/random.h @@ -40,6 +40,9 @@ SRSLTE_API float srslte_random_uniform_real_dist(srslte_random_t q, float min, f SRSLTE_API cf_t srslte_random_uniform_complex_dist(srslte_random_t q, float min, float max); +SRSLTE_API void +srslte_random_uniform_complex_dist_vector(srslte_random_t q, cf_t* vector, uint32_t nsamples, float min, float max); + SRSLTE_API float srslte_random_gauss_dist(srslte_random_t q, float std_dev); SRSLTE_API void srslte_random_free(srslte_random_t q); diff --git a/lib/src/phy/channel/delay.c b/lib/src/phy/channel/delay.c index 3554f5ce2..200add5a9 100644 --- a/lib/src/phy/channel/delay.c +++ b/lib/src/phy/channel/delay.c @@ -46,7 +46,7 @@ int srslte_channel_delay_init( srslte_channel_delay_t* q, float delay_min_us, float delay_max_us, uint32_t period_s, uint32_t srate_max_hz) { // Calculate buffer size - uint32_t buff_size = (uint32_t)ceilf(delay_max_us * (float)srate_max_hz); + uint32_t buff_size = (uint32_t)ceilf(delay_max_us * (float)srate_max_hz / 1e6f); // Create ring buffer int ret = srslte_ringbuffer_init(&q->rb, sizeof(cf_t) * buff_size); diff --git a/lib/src/phy/channel/test/CMakeLists.txt b/lib/src/phy/channel/test/CMakeLists.txt index f09158a85..77f68594f 100644 --- a/lib/src/phy/channel/test/CMakeLists.txt +++ b/lib/src/phy/channel/test/CMakeLists.txt @@ -27,4 +27,9 @@ endif(SRSGUI_FOUND) target_link_libraries(fading_channel_test srslte_phy srslte_common srslte_phy ${SEC_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) add_test(fading_channel_test_epa5 fading_channel_test -m epa5 -s 26.04e6 -t 100) add_test(fading_channel_test_eva70 fading_channel_test -m eva70 -s 23.04e6 -t 100) -add_test(fading_channel_test_etu300 fading_channel_test -m etu70 -s 23.04e6 -t 100) \ No newline at end of file +add_test(fading_channel_test_etu300 fading_channel_test -m etu70 -s 23.04e6 -t 100) + +add_executable(delay_channel_test delay_channel_test.c) +target_link_libraries(delay_channel_test srslte_phy srslte_common srslte_phy ${SEC_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +add_test(delay_channel_test delay_channel_test -m 10 -M 100 -t 1000 -T 1 -s 1.92e6) + diff --git a/lib/src/phy/channel/test/delay_channel_test.c b/lib/src/phy/channel/test/delay_channel_test.c new file mode 100644 index 000000000..aad5514dc --- /dev/null +++ b/lib/src/phy/channel/test/delay_channel_test.c @@ -0,0 +1,143 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE 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 Affero General Public License for more details. + * + * A copy of the GNU Affero 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 "srslte/phy/utils/vector.h" +#include +#include +#include +#include + +static srslte_channel_delay_t delay = {}; + +static uint32_t delay_min_us = 10; +static uint32_t delay_max_us = 3333; +static uint32_t delay_period_s = 1; +static uint32_t srate_hz = 1920000; +static uint32_t sim_time_periods = 1; + +#define INPUT_TYPE 0 /* 0: Dirac Delta; Otherwise: Random*/ + +static void usage(char* prog) +{ + printf("Usage: %s [mMtsT]\n", prog); + printf("\t-m Minimum delay in microseconds [Default %d]\n", delay_min_us); + printf("\t-M Maximum delay in microseconds [Default %d]\n", delay_max_us); + printf("\t-t Delay period in seconds: [Default %d]\n", delay_period_s); + printf("\t-s Sampling rate in Hz: [Default %d]\n", srate_hz); + printf("\t-T Simulation Time in periods: [Default %d]\n", sim_time_periods); +} + +static void parse_args(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "mMtsT")) != -1) { + switch (opt) { + case 'm': + delay_min_us = (uint32_t)strtol(argv[optind], NULL, 10); + break; + case 'M': + delay_max_us = (uint32_t)strtol(argv[optind], NULL, 10); + break; + case 't': + delay_period_s = (uint32_t)strtol(argv[optind], NULL, 10); + break; + case 's': + srate_hz = (uint32_t)strtof(argv[optind], NULL); + break; + case 'T': + sim_time_periods = (uint32_t)strtol(argv[optind], NULL, 10); + break; + default: + usage(argv[0]); + exit(-1); + } + } +} + +int main(int argc, char** argv) +{ + int ret = SRSLTE_SUCCESS; + cf_t* input_buffer = NULL; + cf_t* output_buffer = NULL; + srslte_timestamp_t ts = {}; // Initialised to zero + srslte_random_t random_gen = srslte_random_init(0x1234); + struct timeval t[3] = {}; + + // Parse arguments + parse_args(argc, argv); + + // Initialise buffers + uint32_t size = srate_hz / 1000; + input_buffer = srslte_vec_malloc(sizeof(cf_t) * size); + output_buffer = srslte_vec_malloc(sizeof(cf_t) * size); + if (!input_buffer || !output_buffer) { + fprintf(stderr, "Error: Allocating memory\n"); + ret = SRSLTE_ERROR; + } + + // Generate random samples + srslte_random_uniform_complex_dist_vector(random_gen, input_buffer, size, -1.0f, +1.0f); + + // Initialise delay channel + if (ret == SRSLTE_SUCCESS) { + ret = srslte_channel_delay_init(&delay, delay_min_us, delay_max_us, delay_period_s, srate_hz); + } + + // Run actual test + gettimeofday(&t[1], NULL); + for (int i = 0; i < sim_time_periods && ret == SRSLTE_SUCCESS; i++) { + for (int j = 0; j < 1000 * delay_period_s; j++) { + // Run delay channel + srslte_channel_delay_execute(&delay, input_buffer, output_buffer, size, &ts); + + // Increment timestamp 1ms + srslte_timestamp_add(&ts, 0, 0.001); + } + } + gettimeofday(&t[2], NULL); + get_time_interval(t); + + // Free + srslte_random_free(random_gen); + srslte_channel_delay_free(&delay); + + if (input_buffer) { + free(input_buffer); + } + + if (output_buffer) { + free(output_buffer); + } + + uint64_t nof_samples = sim_time_periods * 1000 * delay_period_s * size; + double elapsed_us = t[0].tv_sec * 1e6 + t[0].tv_usec; + + // Print result and exit + printf("Test delay_min_us=%d; delay_max_us=%d; delay_period_s=%d; srate_hz=%d; periods=%d; %s ... %.1f MSps\n", + delay_min_us, + delay_max_us, + delay_period_s, + srate_hz, + sim_time_periods, + (ret == SRSLTE_SUCCESS) ? "Passed" : "Failed", + (double)nof_samples / elapsed_us); + exit(ret); +} diff --git a/lib/src/phy/utils/random.cpp b/lib/src/phy/utils/random.cpp index 5baa77e07..911a542d8 100644 --- a/lib/src/phy/utils/random.cpp +++ b/lib/src/phy/utils/random.cpp @@ -98,6 +98,13 @@ cf_t srslte_random_uniform_complex_dist(srslte_random_t q, float min, float max) return ret; } +void srslte_random_uniform_complex_dist_vector(srslte_random_t q, cf_t* vector, uint32_t nsamples, float min, float max) +{ + for (int i = 0; i < nsamples; i++) { + vector[i] = srslte_random_uniform_complex_dist(q, min, max); + } +} + float srslte_random_gauss_dist(srslte_random_t q, float std_dev) { float ret = NAN; diff --git a/srsue/hdr/phy/sync.h b/srsue/hdr/phy/sync.h index 30c6307fa..4474758dc 100644 --- a/srsue/hdr/phy/sync.h +++ b/srsue/hdr/phy/sync.h @@ -282,7 +282,7 @@ private: phy_common* worker_com; prach* prach_buffer; async_scell_recv_vector* scell_sync; - srslte::channel* channel_emulator = nullptr; + srslte::channel_ptr channel_emulator = nullptr; // Object for synchronization of the primary cell srslte_ue_sync_t ue_sync; diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 6c1495843..6decf7161 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -93,8 +93,8 @@ void sync::init(radio_interface_phy* _radio, } if (worker_com->args->dl_channel_args.enable) { - channel_emulator = new srslte::channel(worker_com->args->dl_channel_args, - worker_com->args->nof_rx_ant * worker_com->args->nof_rx_ant); + channel_emulator = srslte::channel_ptr(new srslte::channel( + worker_com->args->dl_channel_args, worker_com->args->nof_rx_ant * worker_com->args->nof_rx_ant)); } nof_workers = workers_pool->get_nof_workers(); @@ -134,11 +134,6 @@ sync::~sync() } pthread_mutex_destroy(&rrc_mutex); srslte_ue_sync_free(&ue_sync); - - // Destroy channel emulator if created - if (channel_emulator) { - delete channel_emulator; - } } }