mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-18 07:00:30 +00:00
Compare commits
1 Commits
develop
...
rfsim-powe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff4c19596d |
@@ -628,6 +628,7 @@ typedef struct {
|
||||
uint64_t timestamp; // Timestamp value of first sample
|
||||
uint32_t option_value; // Option value
|
||||
uint32_t option_flag; // Option flag
|
||||
int16_t tx_power;
|
||||
} samplesBlockHeader_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -8,3 +8,13 @@ set_target_properties(rfsimulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BI
|
||||
|
||||
add_executable(replay_node stored_node.c)
|
||||
target_link_libraries (replay_node minimal_lib)
|
||||
|
||||
if (ENABLE_TESTS)
|
||||
add_library(rfsimulator_static STATIC
|
||||
simulator.c
|
||||
apply_channelmod.c
|
||||
../../openair1/PHY/TOOLS/signal_energy.c)
|
||||
target_include_directories(rfsimulator_static PUBLIC .)
|
||||
target_link_libraries(rfsimulator_static PUBLIC SIMU)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
@@ -58,16 +58,22 @@ void rxAddInput( const c16_t *input_sig,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS,
|
||||
uint32_t CirSize
|
||||
uint32_t CirSize,
|
||||
int16_t rx_gain,
|
||||
int16_t tx_power
|
||||
) {
|
||||
// channelDesc->path_loss_dB should contain the total path gain
|
||||
// so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...)
|
||||
// UE and NB gain control to be added
|
||||
// Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...)
|
||||
const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0);
|
||||
const double pathLossLinear = pow(10,(channelDesc->path_loss_dB + tx_power)/20.0);
|
||||
// Energy in one sample to calibrate input noise
|
||||
// the normalized OAI value seems to be 256 as average amplitude (numerical amplification = 1)
|
||||
const double noise_per_sample = pow(10,channelDesc->noise_power_dB/10.0) * 256;
|
||||
// Treat noise_power_dB as noise_power_dBm. Convert to sample value. 256 sample value is 0dBm.
|
||||
const double noise_per_sample = pow(10,channelDesc->noise_power_dB/20.0) * 256;
|
||||
|
||||
const double rx_gain_linear = pow(10,rx_gain/20.0);
|
||||
|
||||
const uint64_t dd = channelDesc->channel_offset;
|
||||
const int nbTx=channelDesc->nb_tx;
|
||||
|
||||
@@ -95,8 +101,8 @@ void rxAddInput( const c16_t *input_sig,
|
||||
}
|
||||
|
||||
// Fixme: lround(), rount(), ... is detected by valgrind as error, not found why
|
||||
out_ptr->r += lround(rx_tmp.r*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0));
|
||||
out_ptr->i += lround(rx_tmp.i*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0));
|
||||
out_ptr->r += lround(rx_gain_linear*(rx_tmp.r*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)));
|
||||
out_ptr->i += lround(rx_gain_linear*(rx_tmp.i*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)));
|
||||
out_ptr++;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,13 +23,17 @@
|
||||
|
||||
#ifndef __RFSIMULATOR_H
|
||||
#define __RFSIMULATOR_H
|
||||
#include "openair1/PHY/TOOLS/tools_defs.h"
|
||||
#include "openair1/SIMULATION/TOOLS/sim.h"
|
||||
void rxAddInput( const c16_t *input_sig,
|
||||
c16_t *after_channel_sig,
|
||||
int rxAnt,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS,
|
||||
uint32_t CirSize
|
||||
uint32_t CirSize,
|
||||
int16_t rx_gain,
|
||||
int16_t tx_power
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -177,6 +177,9 @@ typedef struct {
|
||||
poll_telnetcmdq_func_t poll_telnetcmdq;
|
||||
int wait_timeout;
|
||||
double prop_delay_ms;
|
||||
int tx_power;
|
||||
int tx_gain;
|
||||
int rx_gain;
|
||||
} rfsimulator_state_t;
|
||||
|
||||
static int allocCirBuf(rfsimulator_state_t *bridge, int sock)
|
||||
@@ -612,7 +615,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp
|
||||
buffer_t *b=&t->buf[i];
|
||||
|
||||
if (b->conn_sock >= 0 ) {
|
||||
samplesBlockHeader_t header = {nsamps, nbAnt, timestamp};
|
||||
samplesBlockHeader_t header = {nsamps, nbAnt, timestamp, 0, 0, t->tx_power + t->tx_gain};
|
||||
fullwrite(b->conn_sock,&header, sizeof(header), t);
|
||||
sample_t tmpSamples[nsamps][nbAnt];
|
||||
|
||||
@@ -898,7 +901,9 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
|
||||
ptr->channel_model,
|
||||
nsamps,
|
||||
t->nextRxTstamp,
|
||||
CirSize);
|
||||
CirSize,
|
||||
t->rx_gain,
|
||||
ptr->th.tx_power);
|
||||
}
|
||||
else { // no channel modeling
|
||||
int nbAnt_tx = ptr->th.nbAnt; // number of Tx antennas
|
||||
|
||||
5
radio/rfsimulator/tests/CMakeLists.txt
Normal file
5
radio/rfsimulator/tests/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
add_executable(test_rfsimulator test_rfsimulator.cpp)
|
||||
target_link_libraries(test_rfsimulator PRIVATE rfsimulator_static GTest::gtest minimal_lib nr_common)
|
||||
add_dependencies(tests test_rfsimulator)
|
||||
add_test(NAME test_rfsimulator
|
||||
COMMAND ./test_rfsimulator)
|
||||
132
radio/rfsimulator/tests/test_rfsimulator.cpp
Normal file
132
radio/rfsimulator/tests/test_rfsimulator.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
#include <gtest/gtest.h>
|
||||
extern "C" {
|
||||
#include "rfsimulator.h"
|
||||
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
||||
{
|
||||
if (assert) {
|
||||
abort();
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
configmodule_interface_t *uniqCfg;
|
||||
void *get_shlibmodule_fptr(char *modname, char *fname)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
#include "openair1/SIMULATION/TOOLS/sim.h"
|
||||
#include "nr_common.h"
|
||||
extern int32_t signal_energy_nodc(int32_t *input,uint32_t length);
|
||||
}
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
channel_desc_t *get_awgn_channel_106_rb(void)
|
||||
{
|
||||
double sample_rate;
|
||||
unsigned int samples_per_frame;
|
||||
double tx_bw;
|
||||
double rx_bw;
|
||||
double DS_TDL = .03;
|
||||
get_samplerate_and_bw(1, 106, 0, &sample_rate, &samples_per_frame, &tx_bw, &rx_bw);
|
||||
auto channel = new_channel_desc_scm(1, 1, AWGN, sample_rate / 1e6, 0, tx_bw, DS_TDL, 0.0, CORR_LEVEL_LOW, 0, 0, 0, -40);
|
||||
random_channel(channel, 0);
|
||||
return channel;
|
||||
}
|
||||
|
||||
const int32_t rfsim_0dbm_sample_ref = 256;
|
||||
const int32_t rfsim_k_value = rfsim_0dbm_sample_ref * rfsim_0dbm_sample_ref * 2;
|
||||
|
||||
TEST(rfsimulator, add_rx_input)
|
||||
{
|
||||
int size = 12 * 50;
|
||||
std::vector<c16_t> input;
|
||||
input.resize(size);
|
||||
std::fill(input.begin(), input.end(), (c16_t){rfsim_0dbm_sample_ref, rfsim_0dbm_sample_ref});
|
||||
std::vector<c16_t> output;
|
||||
output.resize(size);
|
||||
std::fill(output.begin(), output.end(), (c16_t){0, 0});
|
||||
int rxAnt = 0;
|
||||
|
||||
channel_desc_t *channel = get_awgn_channel_106_rb();
|
||||
int nbSamples = input.size();
|
||||
uint64_t TS = 0;
|
||||
uint32_t CirSize = sizeof(input);
|
||||
int16_t rx_gain = 0;
|
||||
int16_t tx_power = 0;
|
||||
rxAddInput(input.data(), output.data(), rxAnt, channel, nbSamples, TS, CirSize, rx_gain, tx_power);
|
||||
|
||||
int32_t input_power = signal_energy_nodc((int32_t*)input.data(), input.size());
|
||||
int32_t output_power = signal_energy_nodc((int32_t*)output.data(), output.size());
|
||||
std::cout << "Input : " << 10*log10(input_power) - 10*log10(rfsim_k_value) << " [dBm] " << std::endl;
|
||||
std::cout << "Output : " << 10*log10(output_power) - 10*log10(rfsim_k_value) << " [dBm]" << std::endl;
|
||||
|
||||
channel->path_loss_dB = -3;
|
||||
random_channel(channel, 0);
|
||||
std::fill(output.begin(), output.end(), (c16_t){0, 0});
|
||||
|
||||
rxAddInput(input.data(), output.data(), rxAnt, channel, nbSamples, TS, CirSize, rx_gain, tx_power);
|
||||
int32_t attenuated_power = signal_energy_nodc((int32_t*)output.data(), output.size());
|
||||
std::cout << "Output (3dB loss): " << 10*log10(attenuated_power) - 10*log10(rfsim_k_value) << " [dBm]" << std::endl;
|
||||
|
||||
channel->path_loss_dB = 3;
|
||||
random_channel(channel, 0);
|
||||
std::fill(output.begin(), output.end(), (c16_t){0, 0});
|
||||
|
||||
rxAddInput(input.data(), output.data(), rxAnt, channel, nbSamples, TS, CirSize, rx_gain, tx_power);
|
||||
int32_t increased_power = signal_energy_nodc((int32_t*)output.data(), output.size());
|
||||
std::cout << "Output (3dB gain): " << 10*log10(increased_power) - 10*log10(rfsim_k_value) << " [dBm]" << std::endl;
|
||||
|
||||
channel->path_loss_dB = 3;
|
||||
std::fill(output.begin(), output.end(), (c16_t){0, 0});
|
||||
|
||||
rxAddInput(input.data(), output.data(), rxAnt, channel, nbSamples, TS, CirSize, rx_gain, tx_power);
|
||||
increased_power = signal_energy_nodc((int32_t*)output.data(), output.size());
|
||||
std::cout << "Output (3dB gain) [no channel regeneration]: " << 10*log10(increased_power) - 10*log10(rfsim_k_value) << " [dBm]" << std::endl;
|
||||
|
||||
channel->path_loss_dB = 0;
|
||||
std::fill(output.begin(), output.end(), (c16_t){0, 0});
|
||||
|
||||
rxAddInput(input.data(), output.data(), rxAnt, channel, nbSamples, TS, CirSize, rx_gain, 3);
|
||||
increased_power = signal_energy_nodc((int32_t*)output.data(), output.size());
|
||||
std::cout << "Output (3dB gain) [increased tx power]: " << 10*log10(increased_power) - 10*log10(rfsim_k_value) << " [dBm]" << std::endl;
|
||||
|
||||
channel->path_loss_dB = 0;
|
||||
std::fill(output.begin(), output.end(), (c16_t){0, 0});
|
||||
|
||||
rxAddInput(input.data(), output.data(), rxAnt, channel, nbSamples, TS, CirSize, 3, tx_power);
|
||||
increased_power = signal_energy_nodc((int32_t*)output.data(), output.size());
|
||||
std::cout << "Output (3dB gain) [increased rx gain]: " << 10*log10(increased_power) - 10*log10(rfsim_k_value) << " [dBm]" << std::endl;
|
||||
|
||||
channel->path_loss_dB = 0;
|
||||
channel->noise_power_dB = -20;
|
||||
std::fill(output.begin(), output.end(), (c16_t){0, 0});
|
||||
std::fill(input.begin(), input.end(), (c16_t){0, 0});
|
||||
rxAddInput(input.data(), output.data(), rxAnt, channel, nbSamples, TS, CirSize, rx_gain, tx_power);
|
||||
increased_power = signal_energy_nodc((int32_t*)output.data(), output.size());
|
||||
std::cout << "Output (0dB gain, " << channel->noise_power_dB << "dBm noise): " << 10*log10(increased_power) - 10*log10(rfsim_k_value) << " [dBm]" << std::endl;
|
||||
|
||||
std::fill(input.begin(), input.end(), (c16_t){0, 0});
|
||||
std::fill(output.begin(), output.end(), (c16_t){0, 0});
|
||||
rxAddInput(input.data(), output.data(), rxAnt, channel, nbSamples, TS, CirSize, 3, tx_power);
|
||||
increased_power = signal_energy_nodc((int32_t*)output.data(), output.size());
|
||||
std::cout << "Output (3dB gain, " << channel->noise_power_dB << "dBm noise): " << 10*log10(increased_power) - 10*log10(rfsim_k_value) << " [dBm]" << std::endl;
|
||||
|
||||
channel->path_loss_dB = 0;
|
||||
channel->noise_power_dB = -30;
|
||||
random_channel(channel, 0);
|
||||
auto linear_gain = std::pow(10,3/20.0);
|
||||
int16_t sample = rfsim_0dbm_sample_ref * linear_gain;
|
||||
std::fill(input.begin(), input.end(), (c16_t){sample, sample});
|
||||
std::fill(output.begin(), output.end(), (c16_t){0, 0});
|
||||
|
||||
rxAddInput(input.data(), output.data(), rxAnt, channel, nbSamples, TS, CirSize, rx_gain, tx_power);
|
||||
increased_power = signal_energy_nodc((int32_t*)output.data(), output.size());
|
||||
std::cout << "Output (3dB) [digital sample gain]: " << 10*log10(increased_power) - 10*log10(rfsim_k_value) << " [dBm]" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
logInit();
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
Reference in New Issue
Block a user