Files
openairinterface5g/targets/ARCH/rfsimulator/apply_channelmod.c
T

98 lines
4.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
Author: Laurent THOMAS, Open Cells for Nokia
copyleft: OpenAirInterface Software Alliance and it's licence
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <common/utils/assertions.h>
#include <common/utils/LOG/log.h>
#include <common/config/config_userapi.h>
#include <openair1/SIMULATION/TOOLS/sim.h>
/*
Legacy study:
The parameters are:
gain&loss (decay, signal power, ...)
either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average
=> don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE
will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop)
lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas);
a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain
multi_path (auto convolution, ISI, ...)
either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes
legacy: we regenerate each sub frame in UL, and each frame only in DL
*/
void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_sig,
int rxAnt,
channel_desc_t *channelDesc,
int nbSamples,
uint64_t TS,
uint32_t CirSize
) {
// 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);
// Energy in one sample to calibrate input noise
//Fixme: modified the N0W computation, not understand the origin value
const double KT=1.38e-23*290; //Boltzman*temperature
// sampling rate is linked to acquisition band (the input pass band filter)
const double noise_figure_watt = KT*channelDesc->sampling_rate;
// Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ?
// the parameter "-s" is declared as SNR, but the input power is not well defined
// −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise)
const double rxGain= 132.24 - channelmod_get_snr_dB();
// sqrt(4*noise_figure_watt) is the thermal noise factor (volts)
// fixme: the last constant is pure trial results to make decent noise
const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10;
// Fixme: we don't fill the offset length samples at begining ?
// anyway, in today code, channel_offset=0
const int dd = abs(channelDesc->channel_offset);
const int nbTx=channelDesc->nb_tx;
for (int i=0; i<((int)nbSamples-dd); i++) {
struct complex16 *out_ptr=after_channel_sig+dd+i;
struct complex rx_tmp= {0};
for (int txAnt=0; txAnt < nbTx; txAnt++) {
const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)];
//const struct complex *channelModelEnd=channelModel+channelDesc->channel_length;
for (int l = 0; l<(int)channelDesc->channel_length; l++) {
// let's assume TS+i >= l
// fixme: the rfsimulator current structure is interleaved antennas
// this has been designed to not have to wait a full block transmission
// but it is not very usefull
// it would be better to split out each antenna in a separate flow
// that will allow to mix ru antennas freely
struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize];
rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y;
rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y;
} //l
}
out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
out_ptr++;
}
if ( (TS*nbTx)%CirSize+nbSamples <= CirSize )
// Cast to a wrong type for compatibility !
LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n",
10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)),
10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)),
channelDesc->path_loss_dB,
10*log10(noise_per_sample));
}