Add option to use global noise power for all RX channels in RFSimulator
Added new command line option to channelmod: noise_power_dBFS. This options allows the user to configure noise power in dBFS added instead of the per-channel value. This makes it so noise is not accumulated per channel reaching higher than expected values. The dBFS unit allows easy configuration. The gNB by default uses -36 dBFS setting. To reach 3dB SNR one should set the noise_power_dBFS value to -39. To configure using command line use --channelmod.noise_power_dBFS -50. Using this setting the gNB and nrUE connect without issue.
This commit is contained in:
@@ -42,12 +42,13 @@
|
||||
legacy: we regenerate each sub frame in UL, and each frame only in DL
|
||||
*/
|
||||
void rxAddInput(const c16_t *input_sig,
|
||||
c16_t *after_channel_sig,
|
||||
cf_t *after_channel_sig,
|
||||
int rxAnt,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS,
|
||||
uint32_t CirSize)
|
||||
uint32_t CirSize,
|
||||
bool add_noise)
|
||||
{
|
||||
if ((channelDesc->sat_height > 0) && (channelDesc->enable_dynamic_delay || channelDesc->enable_dynamic_Doppler)) { // model for transparent satellite on circular orbit
|
||||
/* assumptions:
|
||||
@@ -127,12 +128,12 @@ void rxAddInput(const c16_t *input_sig,
|
||||
const double pathLossLinear = pow(10,channelDesc->path_loss_dB/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;
|
||||
const double noise_per_sample = add_noise ? pow(10,channelDesc->noise_power_dB/10.0) * 256 : 0;
|
||||
const uint64_t dd = channelDesc->channel_offset;
|
||||
const int nbTx=channelDesc->nb_tx;
|
||||
|
||||
for (int i=0; i<nbSamples; i++) {
|
||||
struct complex16 *out_ptr=after_channel_sig+i;
|
||||
cf_t *out_ptr = after_channel_sig + i;
|
||||
struct complexd rx_tmp= {0};
|
||||
|
||||
for (int txAnt=0; txAnt < nbTx; txAnt++) {
|
||||
@@ -166,8 +167,8 @@ void rxAddInput(const c16_t *input_sig,
|
||||
channelDesc->Doppler_phase_cur[rxAnt] += channelDesc->Doppler_phase_inc;
|
||||
}
|
||||
|
||||
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 += rx_tmp.r * pathLossLinear + noise_per_sample * gaussZiggurat(0.0, 1.0);
|
||||
out_ptr->i += rx_tmp.i * pathLossLinear + noise_per_sample * gaussZiggurat(0.0, 1.0);
|
||||
out_ptr++;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,13 +23,15 @@
|
||||
|
||||
#ifndef __RFSIMULATOR_H
|
||||
#define __RFSIMULATOR_H
|
||||
#include <stdbool.h>
|
||||
void rxAddInput( const c16_t *input_sig,
|
||||
c16_t *after_channel_sig,
|
||||
cf_t *after_channel_sig,
|
||||
int rxAnt,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS,
|
||||
uint32_t CirSize
|
||||
uint32_t CirSize,
|
||||
bool apply_noise
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1006,7 +1006,9 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
|
||||
// Clear the output buffer
|
||||
for (int a=0; a<nbAnt; a++)
|
||||
memset(samplesVoid[a],0,sampleToByte(nsamps,1));
|
||||
|
||||
cf_t temp_array[nbAnt][nsamps];
|
||||
bool apply_noise_per_channel = get_noise_power_dBFS() == INVALID_DBFS_VALUE;
|
||||
int num_chanmod_channels = 0;
|
||||
// Add all input nodes signal in the output buffer
|
||||
for (int sock = 0; sock < MAX_FD_RFSIMU; sock++) {
|
||||
buffer_t *ptr=&t->buf[sock];
|
||||
@@ -1024,12 +1026,18 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
|
||||
|
||||
for (int a=0; a<nbAnt; a++) {//loop over number of Rx antennas
|
||||
if ( ptr->channel_model != NULL ) { // apply a channel model
|
||||
rxAddInput(ptr->circularBuf, (c16_t *) samplesVoid[a],
|
||||
if (num_chanmod_channels == 0) {
|
||||
memset(temp_array, 0, sizeof(temp_array));
|
||||
}
|
||||
num_chanmod_channels++;
|
||||
rxAddInput(ptr->circularBuf,
|
||||
temp_array[a],
|
||||
a,
|
||||
ptr->channel_model,
|
||||
nsamps,
|
||||
t->nextRxTstamp,
|
||||
CirSize);
|
||||
CirSize,
|
||||
apply_noise_per_channel);
|
||||
}
|
||||
else { // no channel modeling
|
||||
int nbAnt_tx = ptr->th.nbAnt; // number of Tx antennas
|
||||
@@ -1063,6 +1071,26 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
|
||||
} // end for a (number of rx antennas)
|
||||
}
|
||||
}
|
||||
if (apply_noise_per_channel && num_chanmod_channels > 0) {
|
||||
// Noise is already applied through the channel model
|
||||
for (int a = 0; a < nbAnt; a++) {
|
||||
sample_t *out = (sample_t *)samplesVoid[a];
|
||||
for (int i = 0; i < nsamps; i++) {
|
||||
out[i].r += lroundf(temp_array[a][i].r);
|
||||
out[i].i += lroundf(temp_array[a][i].i);
|
||||
}
|
||||
}
|
||||
} else if (num_chanmod_channels > 0) {
|
||||
// Apply noise from global setting
|
||||
int16_t noise_power = (int16_t)(32767.0 / powf(10.0, .05 * -get_noise_power_dBFS()));
|
||||
for (int a = 0; a < nbAnt; a++) {
|
||||
sample_t *out = (sample_t *)samplesVoid[a];
|
||||
for (int i = 0; i < nsamps; i++) {
|
||||
out[i].r += lroundf(temp_array[a][i].r + noise_power * gaussZiggurat(0.0, 1.0));
|
||||
out[i].i += lroundf(temp_array[a][i].i + noise_power * gaussZiggurat(0.0, 1.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ptimestamp = t->nextRxTstamp; // return the time of the first sample
|
||||
t->nextRxTstamp+=nsamps;
|
||||
|
||||
Reference in New Issue
Block a user