mirror of https://github.com/pvnis/srsRAN_4G.git
Created 3GPP fading channel emulator
parent
64d50040e7
commit
c42fbbe6a5
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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_FADING_H
|
||||
#define SRSLTE_FADING_H
|
||||
|
||||
#include "srslte/phy/dft/dft.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
#define SRSLTE_CHANNEL_FADING_MAXTAPS 9
|
||||
|
||||
typedef enum {
|
||||
srslte_channel_fading_model_none = 0,
|
||||
srslte_channel_fading_model_epa,
|
||||
srslte_channel_fading_model_eva,
|
||||
srslte_channel_fading_model_etu,
|
||||
} srslte_channel_fading_model_t;
|
||||
|
||||
typedef struct {
|
||||
// Configuration parameters
|
||||
float srate; // Sampling rate: 1.92e6, 3.84e6, ..., 23.04e6, 30.72e6
|
||||
srslte_channel_fading_model_t model; // None, EPA, EVA, ETU
|
||||
float doppler; // Maximum doppler: 5, 70, 300
|
||||
|
||||
// Internal tap parametrization
|
||||
uint32_t N; // FFT size
|
||||
uint32_t path_delay; // Path delay
|
||||
double coeff_w[SRSLTE_CHANNEL_FADING_MAXTAPS]; // Angular Speed, random
|
||||
double coeff_a[SRSLTE_CHANNEL_FADING_MAXTAPS]; // Modulation Coefficient
|
||||
double coeff_p[SRSLTE_CHANNEL_FADING_MAXTAPS]; // Initial phase, random
|
||||
|
||||
// Utils
|
||||
srslte_dft_plan_t fft; // DFT to frequency domain
|
||||
srslte_dft_plan_t ifft; // DFT to time domain
|
||||
cf_t* temp; // Temporal buffer, length fft_size
|
||||
cf_t* h_freq; // Channel frequency response, length fft_size
|
||||
cf_t* y_freq; // Intermediate frequency domain buffer
|
||||
|
||||
// State variables
|
||||
cf_t* state; // Length fft_size/2
|
||||
} srslte_channel_fading_t;
|
||||
|
||||
SRSLTE_API int srslte_channel_fading_init(srslte_channel_fading_t* q, double srate, const char* model);
|
||||
|
||||
SRSLTE_API void srslte_channel_fading_free(srslte_channel_fading_t* q);
|
||||
|
||||
SRSLTE_API double srslte_channel_fading_execute(
|
||||
srslte_channel_fading_t* q, const cf_t* in, cf_t* out, uint32_t nof_samples, double init_time);
|
||||
|
||||
#endif // SRSLTE_FADING_H
|
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* 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/fading.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define COEFF_A_MIN 100
|
||||
#define COEFF_A_MAX 2000
|
||||
|
||||
/*
|
||||
* Tables provided in 36.104 R10 section B.2 Multi-path fading propagation conditions
|
||||
*/
|
||||
const static uint32_t nof_taps[4] = {1, 7, 9, 9};
|
||||
|
||||
const static float excess_tap_delay_ns[4][SRSLTE_CHANNEL_FADING_MAXTAPS] = {
|
||||
/* None */ {0, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN},
|
||||
/* EPA */ {0, 30, 70, 90, 110, 190, 410, NAN, NAN},
|
||||
/* EVA */ {0, 30, 150, 310, 370, 710, 1090, 1730, 2510},
|
||||
/* ETU */ {0, 50, 120, 200, 230, 500, 1600, 2300, 5000}};
|
||||
|
||||
const static float relative_power_db[4][SRSLTE_CHANNEL_FADING_MAXTAPS] = {
|
||||
/* None */ {+0.0f, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN},
|
||||
/* EPA */ {+0.0f, -1.0f, -2.0f, -3.0f, -8.0f, -17.2f, -20.8f, NAN, NAN},
|
||||
/* EVA */ {+0.0f, -1.5f, -1.4f, -3.6f, -0.6f, -9.1f, -7.0f, -12.0f, -16.9f},
|
||||
/* ETU */ {-1.0f, -1.0f, -1.0f, +0.0f, +0.0f, +0.0f, -3.0f, -5.0f, -7.0f},
|
||||
};
|
||||
|
||||
static inline int parse_model(srslte_channel_fading_t* q, const char* str)
|
||||
{
|
||||
int ret = SRSLTE_SUCCESS;
|
||||
uint32_t offset = 3;
|
||||
|
||||
if (strncmp("none", str, 4) == 0) {
|
||||
q->model = srslte_channel_fading_model_none;
|
||||
offset = 4;
|
||||
} else if (strncmp("epa", str, 3) == 0) {
|
||||
q->model = srslte_channel_fading_model_epa;
|
||||
} else if (strncmp("eva", str, 3) == 0) {
|
||||
q->model = srslte_channel_fading_model_eva;
|
||||
} else if (strncmp("etu", str, 3) == 0) {
|
||||
q->model = srslte_channel_fading_model_etu;
|
||||
} else {
|
||||
ret = SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (ret == SRSLTE_SUCCESS) {
|
||||
if (strlen(str) > offset) {
|
||||
q->doppler = (float)strtod(&str[offset], NULL);
|
||||
if (isnan(q->doppler) || isinf(q->doppler)) {
|
||||
ret = SRSLTE_ERROR;
|
||||
}
|
||||
} else {
|
||||
ret = SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline float get_doppler_dispersion(double t, double a, double w, double p)
|
||||
{
|
||||
return (float)(a * sin(w * t + p));
|
||||
}
|
||||
|
||||
static inline void
|
||||
generate_tap(float delay_ns, float power_db, float srate, float phase, cf_t* buf, uint32_t N, uint32_t path_delay)
|
||||
{
|
||||
float amplitude = powf(10.0f, power_db / 20.0f);
|
||||
float O = (delay_ns * 1e-9f * srate + path_delay) / (float)N;
|
||||
cf_t a0 = amplitude * cexpf(-_Complex_I * phase) / N;
|
||||
|
||||
for (int n = 0; n < N; n++) {
|
||||
buf[n] = a0;
|
||||
}
|
||||
|
||||
srslte_vec_apply_cfo(buf, -O, buf, N);
|
||||
}
|
||||
|
||||
static void generate_taps(srslte_channel_fading_t* q, double time)
|
||||
{
|
||||
// Initialise freq response
|
||||
bzero(q->h_freq, sizeof(cf_t) * q->N);
|
||||
|
||||
// Generate taps
|
||||
for (int i = 0; i < nof_taps[q->model]; i++) {
|
||||
// Compute phase for thee doppler dispersion
|
||||
float phase = get_doppler_dispersion(time, q->coeff_a[i], q->coeff_w[i], q->coeff_p[i]);
|
||||
|
||||
// Generate tab
|
||||
generate_tap(excess_tap_delay_ns[q->model][i], relative_power_db[q->model][i], q->srate, phase, q->temp, q->N,
|
||||
q->path_delay);
|
||||
|
||||
// Add to frequency response
|
||||
srslte_vec_sum_ccc(q->h_freq, q->temp, q->h_freq, q->N);
|
||||
}
|
||||
|
||||
// at this stage, q->h_freq should contain the frequency response
|
||||
}
|
||||
|
||||
static void filter_segment(srslte_channel_fading_t* q, const cf_t* input, cf_t* output, uint32_t nsamples)
|
||||
{
|
||||
// Fill Input vector
|
||||
memcpy(q->temp, input, sizeof(cf_t) * nsamples);
|
||||
bzero(&q->temp[nsamples], sizeof(cf_t) * (q->N - nsamples));
|
||||
|
||||
// Do FFT
|
||||
srslte_dft_run_c_zerocopy(&q->fft, q->temp, q->y_freq);
|
||||
|
||||
// Apply channel
|
||||
srslte_vec_prod_ccc(q->y_freq, q->h_freq, q->y_freq, q->N);
|
||||
|
||||
// Do iFFT
|
||||
srslte_dft_run_c_zerocopy(&q->ifft, q->y_freq, q->temp);
|
||||
|
||||
// Add state
|
||||
srslte_vec_sum_ccc(q->temp, q->state, q->temp, q->N);
|
||||
|
||||
// Copy output
|
||||
memcpy(output, q->temp, sizeof(cf_t) * nsamples);
|
||||
|
||||
// Copy state
|
||||
memcpy(q->state, &q->temp[nsamples], sizeof(cf_t) * (q->N - nsamples));
|
||||
bzero(&q->state[q->N - nsamples], sizeof(cf_t) * nsamples);
|
||||
}
|
||||
|
||||
int srslte_channel_fading_init(srslte_channel_fading_t* q, double srate, const char* model)
|
||||
{
|
||||
int ret = SRSLTE_ERROR;
|
||||
|
||||
if (q) {
|
||||
// Parse model
|
||||
if (parse_model(q, model) != SRSLTE_SUCCESS) {
|
||||
fprintf(stderr, "Error: invalid channel model '%s'\n", model);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Fill srate
|
||||
q->srate = (float)srate;
|
||||
|
||||
// Populate internal parameters
|
||||
q->N = SRSLTE_MAX((uint32_t)1 << (uint32_t)(
|
||||
round(log2(excess_tap_delay_ns[q->model][nof_taps[q->model] - 1] * 1e-9 * srate)) + 3),
|
||||
64);
|
||||
q->path_delay = q->N / 4;
|
||||
for (int i = 0; i < nof_taps[q->model]; i++) {
|
||||
q->coeff_a[i] = (((double)rand() / (double)RAND_MAX) * (COEFF_A_MAX - COEFF_A_MIN)) + COEFF_A_MIN;
|
||||
q->coeff_w[i] = 2.0 * M_PI * q->doppler / q->coeff_a[i];
|
||||
q->coeff_p[i] = ((double)rand() / (double)RAND_MAX) * M_PI / 2.0;
|
||||
}
|
||||
|
||||
// Plan FFT
|
||||
if (srslte_dft_plan_c(&q->fft, q->N, SRSLTE_DFT_FORWARD) != SRSLTE_SUCCESS) {
|
||||
fprintf(stderr, "Error: planning fft\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Plan iFFT
|
||||
if (srslte_dft_plan_c(&q->ifft, q->N, SRSLTE_DFT_BACKWARD) != SRSLTE_SUCCESS) {
|
||||
fprintf(stderr, "Error: planning ifft\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Allocate memory
|
||||
q->temp = srslte_vec_malloc(sizeof(cf_t) * q->N);
|
||||
if (!q->temp) {
|
||||
fprintf(stderr, "Error: allocating h_freq\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
q->h_freq = srslte_vec_malloc(sizeof(cf_t) * q->N);
|
||||
if (!q->h_freq) {
|
||||
fprintf(stderr, "Error: allocating h_freq\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
q->y_freq = srslte_vec_malloc(sizeof(cf_t) * q->N);
|
||||
if (!q->y_freq) {
|
||||
fprintf(stderr, "Error: allocating y_freq\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
q->state = srslte_vec_malloc(sizeof(cf_t) * q->N);
|
||||
if (!q->state) {
|
||||
fprintf(stderr, "Error: allocating y_freq\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
bzero(q->state, sizeof(cf_t) * q->N);
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
|
||||
clean_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void srslte_channel_fading_free(srslte_channel_fading_t* q)
|
||||
{
|
||||
if (q) {
|
||||
srslte_dft_plan_free(&q->fft);
|
||||
srslte_dft_plan_free(&q->ifft);
|
||||
|
||||
if (q->temp) {
|
||||
free(q->temp);
|
||||
}
|
||||
|
||||
if (q->h_freq) {
|
||||
free(q->h_freq);
|
||||
}
|
||||
|
||||
if (q->y_freq) {
|
||||
free(q->y_freq);
|
||||
}
|
||||
|
||||
if (q->state) {
|
||||
free(q->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double srslte_channel_fading_execute(
|
||||
srslte_channel_fading_t* q, const cf_t* in, cf_t* out, uint32_t nsamples, double init_time)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
|
||||
if (q) {
|
||||
// Generate taps
|
||||
generate_taps(q, init_time);
|
||||
|
||||
while (counter < nsamples) {
|
||||
// Do not process more than N / 4 samples
|
||||
uint32_t n = SRSLTE_MIN(q->N / 4, nsamples - counter);
|
||||
|
||||
// Execute
|
||||
filter_segment(q, &in[counter], &out[counter], n);
|
||||
|
||||
// Increment time
|
||||
init_time += n / q->srate;
|
||||
|
||||
// Increment counter
|
||||
counter += n;
|
||||
}
|
||||
}
|
||||
|
||||
// Return time
|
||||
return init_time;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
|
||||
add_executable(fading_channel_test fading_channel_test.c)
|
||||
|
||||
if(SRSGUI_FOUND)
|
||||
target_link_libraries(fading_channel_test ${SRSGUI_LIBRARIES})
|
||||
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 1000)
|
||||
add_test(fading_channel_test_eva70 fading_channel_test -m eva70 -s 23.04e6 -t 1000)
|
||||
add_test(fading_channel_test_etu300 fading_channel_test -m etu70 -s 23.04e6 -t 1000)
|
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* 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/fading.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
#include <memory.h>
|
||||
#include <srslte/phy/utils/debug.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef ENABLE_GUI
|
||||
#include "srsgui/srsgui.h"
|
||||
static bool enable_gui = false;
|
||||
#endif /* ENABLE_GUI */
|
||||
|
||||
static srslte_channel_fading_t channel_fading;
|
||||
|
||||
static char default_model[] = "epa5";
|
||||
static uint32_t duration_ms = 1000;
|
||||
static char* model = default_model;
|
||||
static uint32_t srate = (uint32_t)30.72e6;
|
||||
|
||||
#define INPUT_TYPE 0 /* 0: Dirac Delta; Otherwise: Random*/
|
||||
|
||||
static void usage(char* prog)
|
||||
{
|
||||
printf("Usage: %s [mts]\n", prog);
|
||||
printf("\t-m Channel model: epa5, eva70, etu300 [Default %s]\n", model);
|
||||
printf("\t-t Simulation time in ms: [Default %d]\n", duration_ms);
|
||||
printf("\t-s Sampling rate in Hz: [Default %d]\n", srate);
|
||||
#ifdef ENABLE_GUI
|
||||
printf("\t-g Enable GUI: [Default %s]\n", enable_gui ? "enabled" : "disabled");
|
||||
#endif /* ENABLE_GUI */
|
||||
}
|
||||
|
||||
static void parse_args(int argc, char** argv)
|
||||
{
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "mtsg")) != -1) {
|
||||
switch (opt) {
|
||||
case 'm':
|
||||
model = argv[optind];
|
||||
break;
|
||||
case 't':
|
||||
duration_ms = (uint32_t)atof(argv[optind]);
|
||||
break;
|
||||
case 's':
|
||||
srate = (uint32_t)atof(argv[optind]);
|
||||
break;
|
||||
#ifdef ENABLE_GUI
|
||||
case 'g':
|
||||
enable_gui ^= true;
|
||||
break;
|
||||
#endif /* ENABLE_GUI */
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int ret = SRSLTE_ERROR;
|
||||
cf_t* input_buffer = NULL;
|
||||
cf_t* output_buffer = NULL;
|
||||
struct timeval t[3] = {};
|
||||
uint64_t time_usec = 0;
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
||||
srslte_dft_plan_t ifft;
|
||||
srslte_dft_plan_c(&ifft, srate / 1000, SRSLTE_DFT_BACKWARD);
|
||||
|
||||
#ifdef ENABLE_GUI
|
||||
plot_real_t plot_fft = NULL;
|
||||
plot_real_t plot_h = NULL;
|
||||
plot_real_t plot_imp = NULL;
|
||||
|
||||
srslte_dft_plan_t fft = {};
|
||||
cf_t* fft_buffer = NULL;
|
||||
float* fft_mag = NULL;
|
||||
float* imp = NULL;
|
||||
|
||||
if (enable_gui) {
|
||||
sdrgui_init();
|
||||
sdrgui_init_title("SRS Fading channel");
|
||||
|
||||
plot_real_init(&plot_h);
|
||||
plot_real_setTitle(&plot_h, "Ideal channel");
|
||||
plot_real_setYAxisScale(&plot_h, -60, 20);
|
||||
plot_real_addToWindowGrid(&plot_h, (char*)"fading", 0, 0);
|
||||
|
||||
plot_real_init(&plot_fft);
|
||||
plot_real_setTitle(&plot_fft, "FFT measured");
|
||||
plot_real_setYAxisScale(&plot_fft, -60, 20);
|
||||
plot_real_addToWindowGrid(&plot_fft, (char*)"fading", 0, 1);
|
||||
|
||||
plot_real_init(&plot_imp);
|
||||
plot_real_setTitle(&plot_imp, "Impulse");
|
||||
plot_real_setYAxisScale(&plot_imp, 0, 5);
|
||||
plot_real_addToWindowGrid(&plot_imp, (char*)"fading", 0, 2);
|
||||
|
||||
srslte_dft_plan_c(&fft, srate / 1000, SRSLTE_DFT_FORWARD);
|
||||
|
||||
fft_buffer = srslte_vec_malloc(sizeof(cf_t) * srate / 1000);
|
||||
if (!fft_buffer) {
|
||||
fprintf(stderr, "Error: malloc\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
fft_mag = srslte_vec_malloc(sizeof(float) * srate / 1000);
|
||||
if (!fft_mag) {
|
||||
fprintf(stderr, "Error: malloc\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
imp = srslte_vec_malloc(sizeof(float) * srate / 1000);
|
||||
if (!imp) {
|
||||
fprintf(stderr, "Error: malloc\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_GUI */
|
||||
|
||||
// Initialise channel
|
||||
if (srslte_channel_fading_init(&channel_fading, srate, model)) {
|
||||
fprintf(stderr, "Error: initialising fading channel. model=%s, srate=%d\n", model, srate);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Allocate buffers
|
||||
input_buffer = srslte_vec_malloc(sizeof(cf_t) * srate / 1000);
|
||||
if (!input_buffer) {
|
||||
fprintf(stderr, "Error: allocating input buffer\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
#if INPUT_TYPE == 0
|
||||
bzero(input_buffer, sizeof(cf_t) * srate / 1000);
|
||||
input_buffer[0] = 1;
|
||||
#else
|
||||
for (int i = 0; i < srate / 1000; i++) {
|
||||
input_buffer[i] = cexpf(_Complex_I * ((double)rand() / (double)RAND_MAX) * M_PI / 2.0) / ((double)srate / 1000.0);
|
||||
}
|
||||
srslte_dft_run_c(&ifft, input_buffer, input_buffer);
|
||||
#endif
|
||||
|
||||
output_buffer = srslte_vec_malloc(sizeof(cf_t) * srate / 1000);
|
||||
if (!output_buffer) {
|
||||
fprintf(stderr, "Error: allocating output buffer\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
printf("-- Starting Fading channel simulator. srate=%.2fMHz; model=%s; duration=%dms\n", (double)srate / 1e6, model,
|
||||
duration_ms);
|
||||
|
||||
for (int i = 0; i < duration_ms; i++) {
|
||||
gettimeofday(&t[1], NULL);
|
||||
srslte_channel_fading_execute(&channel_fading, input_buffer, output_buffer, srate / 1000, (double)i / 1000.0);
|
||||
gettimeofday(&t[2], NULL);
|
||||
get_time_interval(t);
|
||||
time_usec += (uint64_t)(t->tv_sec * 1e6 + t->tv_usec);
|
||||
|
||||
#ifdef ENABLE_GUI
|
||||
if (enable_gui) {
|
||||
srslte_dft_run_c_zerocopy(&fft, output_buffer, fft_buffer);
|
||||
srslte_vec_prod_conj_ccc(fft_buffer, fft_buffer, fft_buffer, srate / 1000);
|
||||
for (int i = 0; i < srate / 1000; i++) {
|
||||
fft_mag[i] = 10.0f * log10f(__real__ fft_buffer[i]);
|
||||
}
|
||||
plot_real_setNewData(&plot_fft, fft_mag, srate / 1000);
|
||||
|
||||
for (int i = 0; i < channel_fading.N; i++) {
|
||||
fft_mag[i] = 20.0f * log10f(cabsf(channel_fading.h_freq[i]));
|
||||
}
|
||||
plot_real_setNewData(&plot_h, fft_mag, channel_fading.N);
|
||||
|
||||
for (int i = 0; i < srate / 1000; i++) {
|
||||
imp[i] = cabsf(output_buffer[i]);
|
||||
}
|
||||
plot_real_setNewData(&plot_imp, imp, channel_fading.N);
|
||||
|
||||
usleep(1000);
|
||||
}
|
||||
#endif /* ENABLE_GUI */
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
|
||||
clean_exit:
|
||||
if (ret) {
|
||||
printf("Error\n");
|
||||
} else {
|
||||
printf("Ok ... %.1f MSps\n", duration_ms * (srate / 1000.0) / (double)time_usec);
|
||||
}
|
||||
|
||||
srslte_dft_plan_free(&ifft);
|
||||
|
||||
#ifdef ENABLE_GUI
|
||||
if (enable_gui) {
|
||||
|
||||
if (fft_mag) {
|
||||
free(fft_mag);
|
||||
}
|
||||
if (imp) {
|
||||
free(imp);
|
||||
}
|
||||
if (fft_buffer) {
|
||||
free(fft_buffer);
|
||||
}
|
||||
srslte_dft_plan_free(&fft);
|
||||
sdrgui_exit();
|
||||
}
|
||||
#endif /* ENABLE_GUI */
|
||||
if (input_buffer) {
|
||||
free(input_buffer);
|
||||
}
|
||||
if (output_buffer) {
|
||||
free(output_buffer);
|
||||
}
|
||||
srslte_channel_fading_free(&channel_fading);
|
||||
srslte_dft_exit();
|
||||
exit(ret);
|
||||
}
|
Loading…
Reference in New Issue