mirror of https://github.com/pvnis/srsRAN_4G.git
Added High Speed Train model to channel emulator
parent
54974d935e
commit
d7c1a0bda9
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_HST_H_
|
||||||
|
#define SRSLTE_HST_H_
|
||||||
|
|
||||||
|
#include <srslte/srslte.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// System parameters
|
||||||
|
uint32_t srate_hz; // Sampling rate
|
||||||
|
|
||||||
|
// Model Parameters
|
||||||
|
float fd_hz; // Maximum Doppler Frequency
|
||||||
|
float ds_m; // eNb distance [m]
|
||||||
|
float dmin_m; // eNb Rail-track distance [m]
|
||||||
|
float period_s; // 2 * Ds / speed [s]
|
||||||
|
float init_time_s; // Time offset [s]
|
||||||
|
|
||||||
|
// State
|
||||||
|
float fs_hz; // Last doppler dispersion [Hz]
|
||||||
|
} srslte_channel_hst_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SRSLTE_API int srslte_channel_hst_init(srslte_channel_hst_t *q, float fd_hz, float period_d, float init_time_s);
|
||||||
|
|
||||||
|
SRSLTE_API void srslte_channel_hst_update_srate(srslte_channel_hst_t *q, uint32_t srate);
|
||||||
|
|
||||||
|
SRSLTE_API void srslte_channel_hst_execute(srslte_channel_hst_t *q,
|
||||||
|
cf_t *in,
|
||||||
|
cf_t *out,
|
||||||
|
uint32_t len,
|
||||||
|
const srslte_timestamp_t *ts);
|
||||||
|
|
||||||
|
SRSLTE_API void srslte_channel_hst_free(srslte_channel_hst_t *q);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //SRSLTE_HST_H_
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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/channel/hst.h"
|
||||||
|
|
||||||
|
int srslte_channel_hst_init(srslte_channel_hst_t *q, float fd_hz, float period_d, float init_time_s) {
|
||||||
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
|
|
||||||
|
if (q) {
|
||||||
|
q->fd_hz = fd_hz; // Hz
|
||||||
|
q->ds_m = 300.0f; // m
|
||||||
|
q->dmin_m = 2.0f; // m
|
||||||
|
q->period_s = period_d; // s
|
||||||
|
q->init_time_s = init_time_s; // s
|
||||||
|
q->fs_hz = NAN;
|
||||||
|
ret = SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void srslte_channel_hst_update_srate(srslte_channel_hst_t *q, uint32_t srate) {
|
||||||
|
if (q) {
|
||||||
|
q->srate_hz = srate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void srslte_channel_hst_execute(srslte_channel_hst_t *q, cf_t *in, cf_t *out, uint32_t len, const srslte_timestamp_t *ts) {
|
||||||
|
if (q) {
|
||||||
|
if (q->srate_hz) {
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Calculate time modulus in period
|
||||||
|
uint64_t mod_t_nsamples = ts_nsamples - period_nsamples * (ts_nsamples / period_nsamples);
|
||||||
|
float t = (float) mod_t_nsamples / (float) q->srate_hz;
|
||||||
|
|
||||||
|
float costheta = 0;
|
||||||
|
|
||||||
|
if (0 <= t && t <= q->period_s / 2.0f) {
|
||||||
|
float num = q->period_s / 4.0f - t;
|
||||||
|
float den = sqrtf(powf(q->dmin_m * q->period_s / (q->ds_m * 2), 2.0f) + powf(num, 2.0f));
|
||||||
|
costheta = num / den;
|
||||||
|
} else if (q->period_s / 2.0f < t && t < q->period_s) {
|
||||||
|
float num = -1.5f / 2.0f * q->period_s + t;
|
||||||
|
float den = sqrtf(powf(q->dmin_m * q->period_s / (q->ds_m * 2), 2.0f) + powf(num, 2.0f));
|
||||||
|
costheta = num / den;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate doppler shift
|
||||||
|
q->fs_hz = q->fd_hz * costheta;
|
||||||
|
|
||||||
|
// Apply doppler shift, assume the doppler does not vary in a sub-frame
|
||||||
|
srslte_vec_apply_cfo(in, -q->fs_hz / q->srate_hz, out, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void srslte_channel_hst_free(srslte_channel_hst_t *q) {
|
||||||
|
bzero(q, sizeof(srslte_channel_hst_t));
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* 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 <srslte/phy/channel/hst.h>
|
||||||
|
#include <srslte/phy/utils/debug.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static srslte_channel_hst_t hst = {};
|
||||||
|
|
||||||
|
static float fd_hz = 750;
|
||||||
|
static float period_s = 7.2;
|
||||||
|
static float init_time_s = 0;
|
||||||
|
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-f Doppler frequency [Default %.1f]\n", fd_hz);
|
||||||
|
printf("\t-t Period in seconds: [Default %.1f]\n", period_s);
|
||||||
|
printf("\t-i Initial time in seconds: [Default %.1f]\n", init_time_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, "ftisT")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'f':
|
||||||
|
fd_hz = strtof(argv[optind], NULL);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
period_s = strtof(argv[optind], NULL);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
init_time_s = strtof(argv[optind], NULL);
|
||||||
|
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
|
||||||
|
struct timeval t[3] = {};
|
||||||
|
|
||||||
|
// Parse arguments
|
||||||
|
parse_args(argc, argv);
|
||||||
|
|
||||||
|
// Initialise buffers
|
||||||
|
uint32_t size = srate_hz / 1000; // 1 ms samples
|
||||||
|
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_vec_gen_sine(1.0f, 0.0f, input_buffer, size);
|
||||||
|
|
||||||
|
// Initialise delay channel
|
||||||
|
if (ret == SRSLTE_SUCCESS) {
|
||||||
|
ret = srslte_channel_hst_init(&hst, fd_hz, period_s, init_time_s);
|
||||||
|
srslte_channel_hst_update_srate(&hst, 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 * period_s; j++) {
|
||||||
|
// Run delay channel
|
||||||
|
srslte_channel_hst_execute(&hst, input_buffer, output_buffer, size, &ts);
|
||||||
|
|
||||||
|
// Increment timestamp 1ms
|
||||||
|
srslte_timestamp_add(&ts, 0, 0.001);
|
||||||
|
|
||||||
|
float ideal_freq = hst.fs_hz;
|
||||||
|
float meas_freq = srslte_vec_estimate_frequency(output_buffer, size) * srate_hz;
|
||||||
|
if (fabsf(ideal_freq- meas_freq) > 0.5f) {
|
||||||
|
printf("Error [%03d.%03d] fs = [%6.1f | %6.1f] Hz\n", i, j, ideal_freq, meas_freq);
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gettimeofday(&t[2], NULL);
|
||||||
|
get_time_interval(t);
|
||||||
|
|
||||||
|
// Free
|
||||||
|
srslte_channel_hst_free(&hst);
|
||||||
|
|
||||||
|
if (input_buffer) {
|
||||||
|
free(input_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_buffer) {
|
||||||
|
free(output_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t nof_samples = sim_time_periods * 1000 * period_s * size;
|
||||||
|
double elapsed_us = t[0].tv_sec * 1e6 + t[0].tv_usec;
|
||||||
|
|
||||||
|
// Print result and exit
|
||||||
|
printf("Test fd=%.1fHz; period=%.1fs; init_time=%.1fs; srate_hz=%d; periods=%d; %s ... %.1f MSps\n",
|
||||||
|
fd_hz,
|
||||||
|
period_s,
|
||||||
|
init_time_s,
|
||||||
|
srate_hz,
|
||||||
|
sim_time_periods,
|
||||||
|
(ret == SRSLTE_SUCCESS) ? "Passed" : "Failed",
|
||||||
|
(double)nof_samples / elapsed_us);
|
||||||
|
exit(ret);
|
||||||
|
}
|
Loading…
Reference in New Issue