Added initial time to delay channel simulator

This commit is contained in:
Xavier Arteaga 2019-08-01 11:18:24 +02:00 committed by Xavier Arteaga
parent 368690ea6b
commit dedf0f2f78
7 changed files with 159 additions and 61 deletions

View File

@ -27,6 +27,7 @@
#include "hst.h"
#include "rlf.h"
#include <memory>
#include <srslte/common/log_filter.h>
#include <srslte/config.h>
#include <srslte/srslte.h>
#include <string>
@ -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 = {};

View File

@ -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);

View File

@ -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

View File

@ -23,18 +23,27 @@
#include <srslte/phy/channel/delay.h>
#include <srslte/srslte.h>
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

View File

@ -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,

View File

@ -162,24 +162,34 @@ static int parse_args(all_args_t* args, int argc, char* argv[])
("channel.dl.fading.enable", bpo::value<bool>(&args->phy.dl_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model")
("channel.dl.fading.model", bpo::value<std::string>(&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<bool>(&args->phy.dl_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator")
("channel.dl.delay.period", bpo::value<uint32_t>(&args->phy.dl_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)")
("channel.dl.delay.period_s", bpo::value<float>(&args->phy.dl_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)")
("channel.dl.delay.init_time_s", bpo::value<float>(&args->phy.dl_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds")
("channel.dl.delay.maximum_us", bpo::value<float>(&args->phy.dl_channel_args.delay_max_us)->default_value(100.0f), "Maximum delay in microseconds")
("channel.dl.delay.minimum_us", bpo::value<float>(&args->phy.dl_channel_args.delay_min_us)->default_value(10.0f), "Minimum delay in microseconds")
("channel.dl.rlf.enable", bpo::value<bool>(&args->phy.dl_channel_args.rlf_enable)->default_value(false), "Enable/Disable Radio-Link Failure simulator")
("channel.dl.rlf.t_on_ms", bpo::value<uint32_t >(&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<uint32_t >(&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<bool>(&args->phy.dl_channel_args.hst_enable)->default_value(false), "Enable/Disable HST simulator")
("channel.dl.hst.period_s", bpo::value<float>(&args->phy.dl_channel_args.hst_period_s)->default_value(7.2f), "HST simulation period in seconds")
("channel.dl.hst.fd_hz", bpo::value<float>(&args->phy.dl_channel_args.hst_fd_hz)->default_value(+750.0f), "Doppler frequency in Hz")
("channel.dl.hst.init_time_s", bpo::value<float>(&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<bool>(&args->phy.ul_channel_args.enable)->default_value(false), "Enable/Disable internal Uplink channel emulator")
("channel.ul.fading.enable", bpo::value<bool>(&args->phy.ul_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model")
("channel.ul.fading.model", bpo::value<std::string>(&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<bool>(&args->phy.ul_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator")
("channel.ul.delay.period", bpo::value<uint32_t>(&args->phy.ul_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)")
("channel.ul.delay.period_s", bpo::value<float>(&args->phy.ul_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)")
("channel.ul.delay.init_time_s", bpo::value<float>(&args->phy.ul_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds")
("channel.ul.delay.maximum_us", bpo::value<float>(&args->phy.ul_channel_args.delay_max_us)->default_value(100.0f), "Maximum delay in microseconds")
("channel.ul.delay.minimum_us", bpo::value<float>(&args->phy.ul_channel_args.delay_min_us)->default_value(10.0f), "Minimum delay in microseconds")
("channel.ul.rlf.enable", bpo::value<bool>(&args->phy.ul_channel_args.rlf_enable)->default_value(false), "Enable/Disable Radio-Link Failure simulator")
("channel.ul.rlf.t_on_ms", bpo::value<uint32_t >(&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<uint32_t >(&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<bool>(&args->phy.ul_channel_args.hst_enable)->default_value(false), "Enable/Disable HST simulator")
("channel.ul.hst.period_s", bpo::value<float>(&args->phy.ul_channel_args.hst_period_s)->default_value(7.2f), "HST simulation period in seconds")
("channel.ul.hst.fd_hz", bpo::value<float>(&args->phy.ul_channel_args.hst_fd_hz)->default_value(-750.0f), "Doppler frequency in Hz")
("channel.ul.hst.init_time_s", bpo::value<float>(&args->phy.ul_channel_args.hst_init_time_s)->default_value(0), "Initial time in seconds")
/* PHY section */
("phy.worker_cpu_mask",

View File

@ -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