From dedf0f2f78bc7d0eb0977eed0d82442727f8a63b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 1 Aug 2019 11:18:24 +0200 Subject: [PATCH] Added initial time to delay channel simulator --- lib/include/srslte/phy/channel/channel.h | 14 ++- lib/include/srslte/phy/channel/delay.h | 13 ++- lib/src/phy/channel/channel.cc | 31 +++++- lib/src/phy/channel/delay.c | 42 +++++--- lib/src/phy/channel/test/delay_channel_test.c | 9 +- srsue/src/main.cc | 14 ++- srsue/ue.conf.example | 97 +++++++++++++------ 7 files changed, 159 insertions(+), 61 deletions(-) diff --git a/lib/include/srslte/phy/channel/channel.h b/lib/include/srslte/phy/channel/channel.h index 5e095f728..06f5e77fe 100644 --- a/lib/include/srslte/phy/channel/channel.h +++ b/lib/include/srslte/phy/channel/channel.h @@ -27,6 +27,7 @@ #include "hst.h" #include "rlf.h" #include +#include #include #include #include @@ -48,13 +49,14 @@ public: bool hst_enable = false; float hst_fd_hz = 750.0f; float hst_period_s = 7.2f; - float hst_init_time_s = 7.2f; + float hst_init_time_s = 0.0f; // Delay options - bool delay_enable = false; - float delay_min_us = 10; - float delay_max_us = 100; - uint32_t delay_period_s = 3600; + bool delay_enable = false; + float delay_min_us = 10; + float delay_max_us = 100; + float delay_period_s = 3600; + float delay_init_time_s = 0; // RLF options bool rlf_enable = false; @@ -64,6 +66,7 @@ public: channel(const args_t& channel_args, uint32_t _nof_ports); ~channel(); + void set_logger(log_filter* _log_h); void set_srate(uint32_t srate); void run(cf_t* in[SRSLTE_MAX_PORTS], cf_t* out[SRSLTE_MAX_PORTS], uint32_t len, const srslte_timestamp_t& t); @@ -74,6 +77,7 @@ private: srslte_channel_rlf_t* rlf = nullptr; // RLF has no buffers / no multiple instance is required cf_t* buffer_in = nullptr; cf_t* buffer_out = nullptr; + log_filter* log_h = nullptr; uint32_t nof_ports = 0; uint32_t current_srate = 0; args_t args = {}; diff --git a/lib/include/srslte/phy/channel/delay.h b/lib/include/srslte/phy/channel/delay.h index c98e7e44f..96d2d5800 100644 --- a/lib/include/srslte/phy/channel/delay.h +++ b/lib/include/srslte/phy/channel/delay.h @@ -29,9 +29,12 @@ typedef struct { float delay_min_us; float delay_max_us; - uint32_t period_s; + float period_s; + float init_time_s; uint32_t srate_max_hz; uint32_t srate_hz; + float delay_us; + float delay_nsamples; srslte_ringbuffer_t rb; cf_t* zero_buffer; @@ -41,8 +44,12 @@ typedef struct { extern "C" { #endif -SRSLTE_API int srslte_channel_delay_init( - srslte_channel_delay_t* q, float delay_min_ns, float delay_max_ns, uint32_t period_s, uint32_t srate_max_hz); +SRSLTE_API int srslte_channel_delay_init(srslte_channel_delay_t* q, + float delay_min_us, + float delay_max_us, + float period_s, + float init_time_s, + uint32_t srate_max_hz); SRSLTE_API void srslte_channel_delay_update_srate(srslte_channel_delay_t* q, uint32_t srate_hz); diff --git a/lib/src/phy/channel/channel.cc b/lib/src/phy/channel/channel.cc index 001cd7836..d43b1be34 100644 --- a/lib/src/phy/channel/channel.cc +++ b/lib/src/phy/channel/channel.cc @@ -55,8 +55,12 @@ channel::channel(const channel::args_t& channel_args, uint32_t _nof_ports) // Create delay if (channel_args.delay_enable && ret == SRSLTE_SUCCESS) { delay[i] = (srslte_channel_delay_t*)calloc(sizeof(srslte_channel_delay_t), 1); - ret = srslte_channel_delay_init( - delay[i], channel_args.delay_min_us, channel_args.delay_max_us, channel_args.delay_period_s, srate_max); + ret = srslte_channel_delay_init(delay[i], + channel_args.delay_min_us, + channel_args.delay_max_us, + channel_args.delay_period_s, + channel_args.delay_init_time_s, + srate_max); } else { delay[i] = nullptr; } @@ -112,6 +116,11 @@ channel::~channel() } } +void channel::set_logger(log_filter* _log_h) +{ + log_h = _log_h; +} + void channel::run(cf_t* in[SRSLTE_MAX_PORTS], cf_t* out[SRSLTE_MAX_PORTS], uint32_t len, const srslte_timestamp_t& t) { // check input pointers @@ -147,6 +156,24 @@ void channel::run(cf_t* in[SRSLTE_MAX_PORTS], cf_t* out[SRSLTE_MAX_PORTS], uint3 memcpy(out[i], buffer_in, sizeof(cf_t) * len); } } + + if (log_h) { + // Logging + std::stringstream str; + + str << "t=" << t.full_secs + t.frac_secs << "s; "; + + if (delay[0]) { + str << "delay=" << delay[0]->delay_us << "us; "; + } + + if (hst) { + str << "hst=" << hst->fs_hz << "Hz; "; + } + + log_h->debug("%s\n", str.str().c_str()); + } + } else { for (uint32_t i = 0; i < nof_ports; i++) { // Check buffers are not null diff --git a/lib/src/phy/channel/delay.c b/lib/src/phy/channel/delay.c index 200add5a9..c7c902db7 100644 --- a/lib/src/phy/channel/delay.c +++ b/lib/src/phy/channel/delay.c @@ -23,18 +23,27 @@ #include #include -static inline double caulculate_delay_us(srslte_channel_delay_t* q, const srslte_timestamp_t* ts) +static inline double calculate_delay_us(srslte_channel_delay_t* q, const srslte_timestamp_t* ts) { - uint32_t mod_secs = (uint32_t)(ts->full_secs % q->period_s); - double arg = 2.0 * M_PI * ((double)mod_secs + ts->frac_secs) / (double)q->period_s; + // Convert period from seconds to samples + uint64_t period_nsamples = (uint64_t)roundf(q->period_s * q->srate_hz); + + // Convert timestamp to samples + uint64_t ts_nsamples = srslte_timestamp_uint64(ts, q->srate_hz) + (uint64_t)q->init_time_s * q->srate_hz; + + // Calculate time modulus in period + uint64_t mod_t_nsamples = ts_nsamples - period_nsamples * (ts_nsamples / period_nsamples); + double t = (double)mod_t_nsamples / (double)q->srate_hz; + + double arg = 2.0 * M_PI * t / (double)q->period_s; double delay_us = q->delay_min_us + (q->delay_max_us - q->delay_min_us) * (1.0 + sin(arg)) / 2.0; return delay_us; } -static inline uint32_t caulculate_delay_nsamples(srslte_channel_delay_t* q, double delay_us) +static inline uint32_t calculate_delay_nsamples(srslte_channel_delay_t* q) { - return (uint32_t)round(delay_us * (double)q->srate_hz / 1e6); + return (uint32_t)round(q->delay_us * (double)q->srate_hz / 1e6); } static inline uint32_t ringbuffer_available_nsamples(srslte_channel_delay_t* q) @@ -42,8 +51,12 @@ static inline uint32_t ringbuffer_available_nsamples(srslte_channel_delay_t* q) return srslte_ringbuffer_status(&q->rb) / sizeof(cf_t); } -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) +int srslte_channel_delay_init(srslte_channel_delay_t* q, + float delay_min_us, + float delay_max_us, + float period_s, + float init_time_s, + uint32_t srate_max_hz) { // Calculate buffer size uint32_t buff_size = (uint32_t)ceilf(delay_max_us * (float)srate_max_hz / 1e6f); @@ -63,6 +76,7 @@ int srslte_channel_delay_init( q->srate_max_hz = srate_max_hz; q->srate_hz = srate_max_hz; q->period_s = period_s; + q->init_time_s = init_time_s; return ret; } @@ -85,18 +99,18 @@ void srslte_channel_delay_free(srslte_channel_delay_t* q) void srslte_channel_delay_execute( srslte_channel_delay_t* q, const cf_t* in, cf_t* out, uint32_t len, const srslte_timestamp_t* ts) { - double delay_us = caulculate_delay_us(q, ts); - uint32_t delay_nsamples = caulculate_delay_nsamples(q, delay_us); + q->delay_us = calculate_delay_us(q, ts); + q->delay_nsamples = calculate_delay_nsamples(q); uint32_t available_nsamples = ringbuffer_available_nsamples(q); - uint32_t read_nsamples = SRSLTE_MIN(delay_nsamples, len); + uint32_t read_nsamples = SRSLTE_MIN(q->delay_nsamples, len); uint32_t copy_nsamples = (len > read_nsamples) ? (len - read_nsamples) : 0; - if (available_nsamples < delay_nsamples) { - uint32_t nzeros = delay_nsamples - available_nsamples; + if (available_nsamples < q->delay_nsamples) { + uint32_t nzeros = q->delay_nsamples - available_nsamples; bzero(q->zero_buffer, sizeof(cf_t) * nzeros); srslte_ringbuffer_write(&q->rb, q->zero_buffer, sizeof(cf_t) * nzeros); - } else if (available_nsamples > delay_nsamples) { - srslte_ringbuffer_read(&q->rb, q->zero_buffer, sizeof(cf_t) * (available_nsamples - delay_nsamples)); + } else if (available_nsamples > q->delay_nsamples) { + srslte_ringbuffer_read(&q->rb, q->zero_buffer, sizeof(cf_t) * (available_nsamples - q->delay_nsamples)); } // Read buffered samples diff --git a/lib/src/phy/channel/test/delay_channel_test.c b/lib/src/phy/channel/test/delay_channel_test.c index aad5514dc..14e2192ec 100644 --- a/lib/src/phy/channel/test/delay_channel_test.c +++ b/lib/src/phy/channel/test/delay_channel_test.c @@ -29,7 +29,8 @@ 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 float delay_period_s = 1; +static float delay_init_time_s = 0; static uint32_t srate_hz = 1920000; static uint32_t sim_time_periods = 1; @@ -40,7 +41,7 @@ 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-t Delay period in seconds: [Default %.1f]\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); } @@ -98,7 +99,7 @@ int main(int argc, char** argv) // Initialise delay channel if (ret == SRSLTE_SUCCESS) { - ret = srslte_channel_delay_init(&delay, delay_min_us, delay_max_us, delay_period_s, srate_hz); + ret = srslte_channel_delay_init(&delay, delay_min_us, delay_max_us, delay_period_s, delay_init_time_s, srate_hz); } // Run actual test @@ -131,7 +132,7 @@ int main(int argc, char** argv) 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", + printf("Test delay_min_us=%d; delay_max_us=%d; delay_period_s=%.1f; srate_hz=%d; periods=%d; %s ... %.1f MSps\n", delay_min_us, delay_max_us, delay_period_s, diff --git a/srsue/src/main.cc b/srsue/src/main.cc index d9ed8c5f6..1127dfd0c 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -162,24 +162,34 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("channel.dl.fading.enable", bpo::value(&args->phy.dl_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model") ("channel.dl.fading.model", bpo::value(&args->phy.dl_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)") ("channel.dl.delay.enable", bpo::value(&args->phy.dl_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator") - ("channel.dl.delay.period", bpo::value(&args->phy.dl_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") + ("channel.dl.delay.period_s", bpo::value(&args->phy.dl_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") + ("channel.dl.delay.init_time_s", bpo::value(&args->phy.dl_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds") ("channel.dl.delay.maximum_us", bpo::value(&args->phy.dl_channel_args.delay_max_us)->default_value(100.0f), "Maximum delay in microseconds") ("channel.dl.delay.minimum_us", bpo::value(&args->phy.dl_channel_args.delay_min_us)->default_value(10.0f), "Minimum delay in microseconds") ("channel.dl.rlf.enable", bpo::value(&args->phy.dl_channel_args.rlf_enable)->default_value(false), "Enable/Disable Radio-Link Failure simulator") ("channel.dl.rlf.t_on_ms", bpo::value(&args->phy.dl_channel_args.rlf_t_on_ms)->default_value(10000), "Time for On state of the channel (ms)") ("channel.dl.rlf.t_off_ms", bpo::value(&args->phy.dl_channel_args.rlf_t_off_ms)->default_value(2000), "Time for Off state of the channel (ms)") + ("channel.dl.hst.enable", bpo::value(&args->phy.dl_channel_args.hst_enable)->default_value(false), "Enable/Disable HST simulator") + ("channel.dl.hst.period_s", bpo::value(&args->phy.dl_channel_args.hst_period_s)->default_value(7.2f), "HST simulation period in seconds") + ("channel.dl.hst.fd_hz", bpo::value(&args->phy.dl_channel_args.hst_fd_hz)->default_value(+750.0f), "Doppler frequency in Hz") + ("channel.dl.hst.init_time_s", bpo::value(&args->phy.dl_channel_args.hst_init_time_s)->default_value(0), "Initial time in seconds") /* Uplink Channel emulator section */ ("channel.ul.enable", bpo::value(&args->phy.ul_channel_args.enable)->default_value(false), "Enable/Disable internal Uplink channel emulator") ("channel.ul.fading.enable", bpo::value(&args->phy.ul_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model") ("channel.ul.fading.model", bpo::value(&args->phy.ul_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)") ("channel.ul.delay.enable", bpo::value(&args->phy.ul_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator") - ("channel.ul.delay.period", bpo::value(&args->phy.ul_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") + ("channel.ul.delay.period_s", bpo::value(&args->phy.ul_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") + ("channel.ul.delay.init_time_s", bpo::value(&args->phy.ul_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds") ("channel.ul.delay.maximum_us", bpo::value(&args->phy.ul_channel_args.delay_max_us)->default_value(100.0f), "Maximum delay in microseconds") ("channel.ul.delay.minimum_us", bpo::value(&args->phy.ul_channel_args.delay_min_us)->default_value(10.0f), "Minimum delay in microseconds") ("channel.ul.rlf.enable", bpo::value(&args->phy.ul_channel_args.rlf_enable)->default_value(false), "Enable/Disable Radio-Link Failure simulator") ("channel.ul.rlf.t_on_ms", bpo::value(&args->phy.ul_channel_args.rlf_t_on_ms)->default_value(10000), "Time for On state of the channel (ms)") ("channel.ul.rlf.t_off_ms", bpo::value(&args->phy.ul_channel_args.rlf_t_off_ms)->default_value(2000), "Time for Off state of the channel (ms)") + ("channel.ul.hst.enable", bpo::value(&args->phy.ul_channel_args.hst_enable)->default_value(false), "Enable/Disable HST simulator") + ("channel.ul.hst.period_s", bpo::value(&args->phy.ul_channel_args.hst_period_s)->default_value(7.2f), "HST simulation period in seconds") + ("channel.ul.hst.fd_hz", bpo::value(&args->phy.ul_channel_args.hst_fd_hz)->default_value(-750.0f), "Doppler frequency in Hz") + ("channel.ul.hst.init_time_s", bpo::value(&args->phy.ul_channel_args.hst_init_time_s)->default_value(0), "Initial time in seconds") /* PHY section */ ("phy.worker_cpu_mask", diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index acb9345c2..3310ab2da 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -183,45 +183,80 @@ enable = false ##################################################################### # Channel emulator options: -# dl.enable: Enable/Disable internal Downlink channel emulator +# enable: Enable/Disable internal Downlink/Uplink channel emulator # # -- Fading emulator -# dl.fading.enable: Enable/disable fading simulator -# dl.fading.model: Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc) +# fading.enable: Enable/disable fading simulator +# fading.model: Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc) # # -- Delay Emulator delay(t) = delay_min + (delay_max - delay_min) * (1 + sin(2pi*t/period)) / 2 # Maximum speed [m/s]: (delay_max - delay_min) * pi * 300 / period -# dl.delay.enable: Enable/disable delay simulator -# dl.delay.period: Delay period in seconds (integer). -# dl.delay.maximum_us: Maximum delay in microseconds -# dl.delay.minumum_us: Minimum delay in microseconds +# delay.enable: Enable/disable delay simulator +# delay.period_s: Delay period in seconds. +# delay.init_time_s: Delay initial time in seconds. +# delay.maximum_us: Maximum delay in microseconds +# delay.minumum_us: Minimum delay in microseconds # # -- Radio-Link Failure (RLF) Emulator -# dl.rlf.enable: Enable/disable RLF simulator -# dl.rlf.t_on_ms: Time for On state of the channel (ms) -# dl.rlf.t_off_ms: Time for Off state of the channel (ms) +# rlf.enable: Enable/disable RLF simulator +# rlf.t_on_ms: Time for On state of the channel (ms) +# rlf.t_off_ms: Time for Off state of the channel (ms) +# +# -- High Speed Train Doppler model simulator +# hst.enable: Enable/Disable HST simulator +# hst.period_s: HST simulation period in seconds +# hst.fd_hz: Doppler frequency in Hz +# hst.init_time_s: Initial time in seconds ##################################################################### -[channel] -#dl.enable = false -#dl.fading.enable = false -#dl.fading.model = none -#dl.delay.enable = false -#dl.delay.period = 3600 -#dl.delay.maximum_us = 100 -#dl.delay.minimum_us = 10 -#dl.rlf.enable = false -#dl.rlf.t_on_ms = 10000 -#dl.rlf.t_off_ms = 2000 -#ul.enable = false -#ul.fading.enable = false -#ul.fading.model = none -#ul.delay.enable = false -#ul.delay.period = 3600 -#ul.delay.maximum_us = 100 -#ul.delay.minimum_us = 10 -#ul.rlf.enable = false -#ul.rlf.t_on_ms = 10000 -#ul.rlf.t_off_ms = 2000 +[channel.dl] +#enable = false + +[channel.dl.fading] +#enable = false +#model = none + +[channel.dl.delay] +#enable = false +#period_s = 3600 +#init_time_s = 0 +#maximum_us = 100 +#minimum_us = 10 + +[channel.dl.rlf] +#enable = false +#t_on_ms = 10000 +#t_off_ms = 2000 + +[channel.dl.hst] +#enable = false +#period_s = 7.2 +#fd_hz = 750.0 +#init_time_s = 0.0 + +[channel.ul] +#enable = false + +[channel.ul.fading] +#enable = false +#model = none + +[channel.ul.delay] +#enable = false +#period_s = 3600 +#init_time_s = 0 +#maximum_us = 100 +#minimum_us = 10 + +[channel.ul.rlf] +#enable = false +#t_on_ms = 10000 +#t_off_ms = 2000 + +[channel.ul.hst] +#enable = false +#period_s = 7.2 +#fd_hz = -750.0 +#init_time_s = 0.0 ##################################################################### # PHY configuration options