add config options for rfsimulator, set a common lib for l1sim and rfsimulator, avoid simulation sources to be added twice in some execs (tau.c)
This commit is contained in:
@@ -204,6 +204,16 @@ int config_execcheck(paramdef_t *params,int numparams, char *prefix) {
|
|||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_paramidx_fromname(paramdef_t *params,int numparams, char *name) {
|
||||||
|
for (int i=0; i<numparams ; i++) {
|
||||||
|
if (strcmp(name,params[i].optname) == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,"[CONFIG]config_paramidx_fromname , %s is not a valid parameter name\n",name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int config_get(paramdef_t *params,int numparams, char *prefix) {
|
int config_get(paramdef_t *params,int numparams, char *prefix) {
|
||||||
int ret= -1;
|
int ret= -1;
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ extern "C"
|
|||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* utility functions to ease usage of config module structures */
|
||||||
#define CONFIG_GETSOURCE ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgmode )
|
#define CONFIG_GETSOURCE ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgmode )
|
||||||
#define CONFIG_GETNUMP ( (config_get_if()==NULL) ? 0 : config_get_if()->num_cfgP )
|
#define CONFIG_GETNUMP ( (config_get_if()==NULL) ? 0 : config_get_if()->num_cfgP )
|
||||||
#define CONFIG_GETP(P) ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgP[P] )
|
#define CONFIG_GETP(P) ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgP[P] )
|
||||||
@@ -46,6 +47,8 @@ extern "C"
|
|||||||
#define CONFIG_SETRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags |= P; }
|
#define CONFIG_SETRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags |= P; }
|
||||||
#define CONFIG_CLEARRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags &= (~P); }
|
#define CONFIG_CLEARRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags &= (~P); }
|
||||||
#define CONFIG_ISPARAMFLAGSET(P,F) ( !!(P.paramflags & F))
|
#define CONFIG_ISPARAMFLAGSET(P,F) ( !!(P.paramflags & F))
|
||||||
|
extern int config_paramidx_fromname(paramdef_t *params,int numparams, char *name);
|
||||||
|
|
||||||
/* utility functions, to be used by configuration module and/or configuration libraries */
|
/* utility functions, to be used by configuration module and/or configuration libraries */
|
||||||
extern configmodule_interface_t *config_get_if(void);
|
extern configmodule_interface_t *config_get_if(void);
|
||||||
extern char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) ;
|
extern char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) ;
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ int process_command(char *buf) {
|
|||||||
memset(cmdb,0,sizeof(cmdb));
|
memset(cmdb,0,sizeof(cmdb));
|
||||||
bufbck=strdup(buf);
|
bufbck=strdup(buf);
|
||||||
rt=CMDSTATUS_NOTFOUND;
|
rt=CMDSTATUS_NOTFOUND;
|
||||||
j = sscanf(buf,"%9s %9s %9[^\t\n]",modulename,cmd,cmdb);
|
j = sscanf(buf,"%19s %19s %19[^\t\n]",modulename,cmd,cmdb);
|
||||||
|
|
||||||
if (telnetparams.telnetdbg > 0)
|
if (telnetparams.telnetdbg > 0)
|
||||||
printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n",j,modulename,cmd,cmdb);
|
printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n",j,modulename,cmd,cmdb);
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxt
|
|||||||
phich->config[phich->num_hi].n_DMRS = hi_dci0_config_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms;
|
phich->config[phich->num_hi].n_DMRS = hi_dci0_config_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms;
|
||||||
phich->num_hi++;
|
phich->num_hi++;
|
||||||
AssertFatal(phich->num_hi<32,"Maximum number of phich reached in subframe\n");
|
AssertFatal(phich->num_hi<32,"Maximum number of phich reached in subframe\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,
|
void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,
|
||||||
@@ -186,6 +185,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
harq_pid = dlsch0->harq_ids[proc->frame_tx%2][proc->subframe_tx];
|
harq_pid = dlsch0->harq_ids[proc->frame_tx%2][proc->subframe_tx];
|
||||||
|
|
||||||
if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
|
if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
|
||||||
LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
|
LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
|
||||||
return;
|
return;
|
||||||
@@ -260,9 +260,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro
|
|||||||
dlsch0->harq_mask = 1;
|
dlsch0->harq_mask = 1;
|
||||||
dlsch0_harq = dlsch0->harq_processes[0];
|
dlsch0_harq = dlsch0->harq_processes[0];
|
||||||
dlsch0_harq->pdu = sdu;
|
dlsch0_harq->pdu = sdu;
|
||||||
|
|
||||||
LOG_D(PHY,"NFAPI: frame %d, subframe %d (TX %d.%d): Programming SI-BR (%d) => %d\n",frame,subframe,proc->frame_tx,proc->subframe_tx,rel13->pdsch_payload_type,UE_id);
|
LOG_D(PHY,"NFAPI: frame %d, subframe %d (TX %d.%d): Programming SI-BR (%d) => %d\n",frame,subframe,proc->frame_tx,proc->subframe_tx,rel13->pdsch_payload_type,UE_id);
|
||||||
|
|
||||||
dlsch0->rnti = 0xFFFF;
|
dlsch0->rnti = 0xFFFF;
|
||||||
dlsch0->Kmimo = 1;
|
dlsch0->Kmimo = 1;
|
||||||
dlsch0->Mdlharq = 4;
|
dlsch0->Mdlharq = 4;
|
||||||
@@ -569,8 +567,7 @@ void handle_uci_sr_pdu(PHY_VARS_eNB *eNB,
|
|||||||
nfapi_ul_config_request_pdu_t *ul_config_pdu,
|
nfapi_ul_config_request_pdu_t *ul_config_pdu,
|
||||||
uint16_t frame,
|
uint16_t frame,
|
||||||
uint8_t subframe,
|
uint8_t subframe,
|
||||||
uint8_t srs_active)
|
uint8_t srs_active) {
|
||||||
{
|
|
||||||
LTE_eNB_UCI *uci = &eNB->uci_vars[UE_id];
|
LTE_eNB_UCI *uci = &eNB->uci_vars[UE_id];
|
||||||
|
|
||||||
if (NFAPI_MODE==NFAPI_MODE_VNF) return;
|
if (NFAPI_MODE==NFAPI_MODE_VNF) return;
|
||||||
@@ -820,6 +817,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
|
|||||||
case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE:
|
case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE:
|
||||||
if (NFAPI_MODE!=NFAPI_MODE_VNF)
|
if (NFAPI_MODE!=NFAPI_MODE_VNF)
|
||||||
handle_nfapi_dci_dl_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu);
|
handle_nfapi_dci_dl_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu);
|
||||||
|
|
||||||
eNB->pdcch_vars[NFAPI_SFNSF2SF(DL_req->sfn_sf)&1].num_dci++;
|
eNB->pdcch_vars[NFAPI_SFNSF2SF(DL_req->sfn_sf)&1].num_dci++;
|
||||||
//LOG_E(PHY,"Incremented num_dci:%d but already set??? dl_config:num_dci:%d\n", eNB->pdcch_vars[subframe&1].num_dci, number_dci);
|
//LOG_E(PHY,"Incremented num_dci:%d but already set??? dl_config:num_dci:%d\n", eNB->pdcch_vars[subframe&1].num_dci, number_dci);
|
||||||
do_oai=1;
|
do_oai=1;
|
||||||
@@ -832,11 +830,13 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
|
|||||||
TX_req->tx_request_body.number_of_pdus);
|
TX_req->tx_request_body.number_of_pdus);
|
||||||
eNB->pbch_configured=1;
|
eNB->pbch_configured=1;
|
||||||
do_oai=1;
|
do_oai=1;
|
||||||
|
|
||||||
//LOG_D(PHY,"%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE TX:%d/%d RX:%d/%d TXREQ:%d/%d\n",
|
//LOG_D(PHY,"%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE TX:%d/%d RX:%d/%d TXREQ:%d/%d\n",
|
||||||
//__FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->frame_rx, proc->subframe_rx, NFAPI_SFNSF2SFN(TX_req->sfn_sf), NFAPI_SFNSF2SF(TX_req->sfn_sf));
|
//__FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->frame_rx, proc->subframe_rx, NFAPI_SFNSF2SFN(TX_req->sfn_sf), NFAPI_SFNSF2SF(TX_req->sfn_sf));
|
||||||
if (NFAPI_MODE!=NFAPI_MODE_VNF)
|
if (NFAPI_MODE!=NFAPI_MODE_VNF)
|
||||||
handle_nfapi_bch_pdu(eNB,proc,dl_config_pdu,
|
handle_nfapi_bch_pdu(eNB,proc,dl_config_pdu,
|
||||||
TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index].segments[0].segment_data);
|
TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index].segments[0].segment_data);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NFAPI_DL_CONFIG_MCH_PDU_TYPE:
|
case NFAPI_DL_CONFIG_MCH_PDU_TYPE:
|
||||||
@@ -911,6 +911,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
|
|||||||
case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE:
|
case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE:
|
||||||
if (NFAPI_MODE!=NFAPI_MODE_VNF)
|
if (NFAPI_MODE!=NFAPI_MODE_VNF)
|
||||||
handle_nfapi_mpdcch_pdu(eNB,proc,dl_config_pdu);
|
handle_nfapi_mpdcch_pdu(eNB,proc,dl_config_pdu);
|
||||||
|
|
||||||
eNB->mpdcch_vars[subframe&1].num_dci++;
|
eNB->mpdcch_vars[subframe&1].num_dci++;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -922,6 +923,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
|
|||||||
Sched_INFO->TX_req->sfn_sf = frame << 4 | subframe;
|
Sched_INFO->TX_req->sfn_sf = frame << 4 | subframe;
|
||||||
oai_nfapi_tx_req(Sched_INFO->TX_req);
|
oai_nfapi_tx_req(Sched_INFO->TX_req);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sched_INFO->DL_req->sfn_sf = frame << 4 | subframe;
|
Sched_INFO->DL_req->sfn_sf = frame << 4 | subframe;
|
||||||
oai_nfapi_dl_config_req(Sched_INFO->DL_req); // DJP - .dl_config_request_body.dl_config_pdu_list[0]); // DJP - FIXME TODO - yuk - only copes with 1 pdu
|
oai_nfapi_dl_config_req(Sched_INFO->DL_req); // DJP - .dl_config_request_body.dl_config_pdu_list[0]); // DJP - FIXME TODO - yuk - only copes with 1 pdu
|
||||||
Sched_INFO->UE_release_req->sfn_sf = frame << 4 | subframe;
|
Sched_INFO->UE_release_req->sfn_sf = frame << 4 | subframe;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -180,6 +180,36 @@ typedef enum {
|
|||||||
EPA_medium,
|
EPA_medium,
|
||||||
EPA_high,
|
EPA_high,
|
||||||
} SCM_t;
|
} SCM_t;
|
||||||
|
#define CHANNELMOD_MAP_INIT \
|
||||||
|
{"custom",custom},\
|
||||||
|
{"SCM_A",SCM_A},\
|
||||||
|
{"SCM_B",SCM_B},\
|
||||||
|
{"SCM_C",SCM_C},\
|
||||||
|
{"SCM_D",SCM_D},\
|
||||||
|
{"EPA",EPA},\
|
||||||
|
{"EVA",EVA},\
|
||||||
|
{"ETU",ETU},\
|
||||||
|
{"MBSFN",MBSFN},\
|
||||||
|
{"Rayleigh8",Rayleigh8},\
|
||||||
|
{"Rayleigh1",Rayleigh1},\
|
||||||
|
{"Rayleigh1_800",Rayleigh1_800},\
|
||||||
|
{"Rayleigh1_corr",Rayleigh1_corr},\
|
||||||
|
{"Rayleigh1_anticorr",Rayleigh1_anticorr},\
|
||||||
|
{"Rice8",Rice8},\
|
||||||
|
{"Rice1",Rice1},\
|
||||||
|
{"Rice1_corr",Rice1_corr},\
|
||||||
|
{"Rice1_anticorr",Rice1_anticorr},\
|
||||||
|
{"AWGN",AWGN},\
|
||||||
|
{"Rayleigh1_orthogonal",Rayleigh1_orthogonal},\
|
||||||
|
{"Rayleigh1_orth_eff_ch_TM4_prec_real",Rayleigh1_orth_eff_ch_TM4_prec_real},\
|
||||||
|
{"Rayleigh1_orth_eff_ch_TM4_prec_imag",Rayleigh1_orth_eff_ch_TM4_prec_imag},\
|
||||||
|
{"Rayleigh8_orth_eff_ch_TM4_prec_real",Rayleigh8_orth_eff_ch_TM4_prec_real},\
|
||||||
|
{"Rayleigh8_orth_eff_ch_TM4_prec_imag",Rayleigh8_orth_eff_ch_TM4_prec_imag},\
|
||||||
|
{"TS_SHIFT",TS_SHIFT},\
|
||||||
|
{"EPA_low",EPA_low},\
|
||||||
|
{"EPA_medium",EPA_medium},\
|
||||||
|
{"EPA_high",EPA_high},\
|
||||||
|
{NULL, -1}
|
||||||
|
|
||||||
#include "platform_constants.h"
|
#include "platform_constants.h"
|
||||||
|
|
||||||
@@ -395,9 +425,19 @@ void multipath_tv_channel(channel_desc_t *desc,
|
|||||||
/**@} */
|
/**@} */
|
||||||
/**@} */
|
/**@} */
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
void init_channelmod(void) ;
|
||||||
|
|
||||||
double N_RB2sampling_rate(uint16_t N_RB);
|
double N_RB2sampling_rate(uint16_t N_RB);
|
||||||
double N_RB2channel_bandwidth(uint16_t N_RB);
|
double N_RB2channel_bandwidth(uint16_t N_RB);
|
||||||
|
|
||||||
|
|
||||||
#include "targets/RT/USER/rfsim.h"
|
#include "targets/RT/USER/rfsim.h"
|
||||||
|
|
||||||
void do_DL_sig(sim_t *sim,
|
void do_DL_sig(sim_t *sim,
|
||||||
@@ -412,6 +452,7 @@ void do_UL_sig(sim_t *sim,
|
|||||||
uint16_t subframe,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms,
|
uint16_t subframe,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms,
|
||||||
uint32_t frame,int ru_id,uint8_t CC_id);
|
uint32_t frame,int ru_id,uint8_t CC_id);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "common_lib.h"
|
#include "common_lib.h"
|
||||||
#include <openair1/PHY/defs_eNB.h>
|
#include <openair1/PHY/defs_eNB.h>
|
||||||
#include "openair1/PHY/defs_UE.h"
|
#include "openair1/PHY/defs_UE.h"
|
||||||
|
#define CHANNELMOD_DYNAMICLOAD
|
||||||
#include <openair1/SIMULATION/TOOLS/sim.h>
|
#include <openair1/SIMULATION/TOOLS/sim.h>
|
||||||
|
|
||||||
#define PORT 4043 //default TCP port for this simulator
|
#define PORT 4043 //default TCP port for this simulator
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
extern double snr_dB;
|
extern double snr_dB;
|
||||||
extern RAN_CONTEXT_t RC;
|
extern RAN_CONTEXT_t RC;
|
||||||
//
|
//
|
||||||
#define MAX_RFSIMU_OPT 2
|
|
||||||
#define RFSIMU_SECTION "rfsimulator"
|
#define RFSIMU_SECTION "rfsimulator"
|
||||||
#define RFSIMU_OPTIONS_PARAMNAME "options"
|
#define RFSIMU_OPTIONS_PARAMNAME "options"
|
||||||
# define RFSIM_CONFIG_HELP_OPTIONS " list of comma separated options to enable rf simulator functionalities. Available options: \n"\
|
# define RFSIM_CONFIG_HELP_OPTIONS " list of comma separated options to enable rf simulator functionalities. Available options: \n"\
|
||||||
@@ -63,6 +64,7 @@ extern RAN_CONTEXT_t RC;
|
|||||||
|
|
||||||
pthread_mutex_t Sockmutex;
|
pthread_mutex_t Sockmutex;
|
||||||
|
|
||||||
|
|
||||||
typedef struct buffer_s {
|
typedef struct buffer_s {
|
||||||
int conn_sock;
|
int conn_sock;
|
||||||
openair0_timestamp lastReceivedTS;
|
openair0_timestamp lastReceivedTS;
|
||||||
@@ -88,84 +90,9 @@ typedef struct {
|
|||||||
int tx_num_channels;
|
int tx_num_channels;
|
||||||
double sample_rate;
|
double sample_rate;
|
||||||
double tx_bw;
|
double tx_bw;
|
||||||
|
bool enable_channelmod;
|
||||||
} rfsimulator_state_t;
|
} rfsimulator_state_t;
|
||||||
|
|
||||||
/*
|
|
||||||
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
|
|
||||||
) {
|
|
||||||
// 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 - 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
|
void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||||
buffer_t *ptr=&bridge->buf[sock];
|
buffer_t *ptr=&bridge->buf[sock];
|
||||||
@@ -183,6 +110,8 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
|
|||||||
ev.events = EPOLLIN | EPOLLRDHUP;
|
ev.events = EPOLLIN | EPOLLRDHUP;
|
||||||
ev.data.fd = sock;
|
ev.data.fd = sock;
|
||||||
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
|
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
|
||||||
|
|
||||||
|
if ( bridge->enable_channelmod==true) {
|
||||||
// create channel simulation model for this mode reception
|
// create channel simulation model for this mode reception
|
||||||
// snr_dB is pure global, coming from configuration paramter "-s"
|
// snr_dB is pure global, coming from configuration paramter "-s"
|
||||||
// Fixme: referenceSignalPower should come from the right place
|
// Fixme: referenceSignalPower should come from the right place
|
||||||
@@ -204,6 +133,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
|
|||||||
0); // path_loss in dB
|
0); // path_loss in dB
|
||||||
random_channel(ptr->channel_model,false);
|
random_channel(ptr->channel_model,false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
|
void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||||
AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, "");
|
AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, "");
|
||||||
@@ -231,6 +161,7 @@ void socketError(rfsimulator_state_t *bridge, int sock) {
|
|||||||
rfsimulator: error: you have to run one UE and one eNB\n\
|
rfsimulator: error: you have to run one UE and one eNB\n\
|
||||||
For this, export RFSIMULATOR=enb (eNB case) or \n\
|
For this, export RFSIMULATOR=enb (eNB case) or \n\
|
||||||
RFSIMULATOR=<an ip address> (UE case)\n\
|
RFSIMULATOR=<an ip address> (UE case)\n\
|
||||||
|
or use rfsimulator.serveraddr configuration option\n\
|
||||||
\x1b[m"
|
\x1b[m"
|
||||||
|
|
||||||
enum blocking_t {
|
enum blocking_t {
|
||||||
@@ -290,26 +221,30 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
|
|||||||
void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
|
void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
|
||||||
char *saveF=NULL;
|
char *saveF=NULL;
|
||||||
paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC;
|
paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC;
|
||||||
|
|
||||||
int p = config_paramidx_fromname(rfsimu_params,sizeof(rfsimu_params)/sizeof(paramdef_t), RFSIMU_OPTIONS_PARAMNAME) ;
|
int p = config_paramidx_fromname(rfsimu_params,sizeof(rfsimu_params)/sizeof(paramdef_t), RFSIMU_OPTIONS_PARAMNAME) ;
|
||||||
int ret = config_get( rfsimu_params,sizeof(rfsimu_params)/sizeof(paramdef_t),RFSIMU_SECTION);
|
int ret = config_get( rfsimu_params,sizeof(rfsimu_params)/sizeof(paramdef_t),RFSIMU_SECTION);
|
||||||
AssertFatal(ret >= 0, "configuration couldn't be performed");
|
AssertFatal(ret >= 0, "configuration couldn't be performed");
|
||||||
rfsimulator->saveIQfile = -1;
|
rfsimulator->saveIQfile = -1;
|
||||||
|
|
||||||
for(int i=0; i<rfsimu_params[p].numelt ; i++) {
|
for(int i=0; i<rfsimu_params[p].numelt ; i++) {
|
||||||
if (strcmp(rfsimu_params[p].strlistptr[i],"saviq") == 0) {
|
if (strcmp(rfsimu_params[p].strlistptr[i],"saviq") == 0) {
|
||||||
rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666);
|
rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666);
|
||||||
|
|
||||||
if ( rfsimulator->saveIQfile != -1 )
|
if ( rfsimulator->saveIQfile != -1 )
|
||||||
LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF);
|
LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF);
|
||||||
else
|
else
|
||||||
LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno));
|
LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) {
|
} else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) {
|
||||||
load_module_shlib("chanmod",NULL,0,NULL);
|
init_channelmod();
|
||||||
|
rfsimulator->enable_channelmod=true;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,"Unknown rfsimulator option: %s\n",rfsimu_params[p].strlistptr[i]);
|
fprintf(stderr,"Unknown rfsimulator option: %s\n",rfsimu_params[p].strlistptr[i]);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for compatibility keep environment variable usage */
|
/* for compatibility keep environment variable usage */
|
||||||
if ( getenv("RFSIMULATOR") != NULL ) {
|
if ( getenv("RFSIMULATOR") != NULL ) {
|
||||||
rfsimulator->ip=getenv("RFSIMULATOR");
|
rfsimulator->ip=getenv("RFSIMULATOR");
|
||||||
@@ -320,7 +255,6 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
|
|||||||
rfsimulator->typeStamp = ENB_MAGICDL_FDD;
|
rfsimulator->typeStamp = ENB_MAGICDL_FDD;
|
||||||
else
|
else
|
||||||
rfsimulator->typeStamp = UE_MAGICDL_FDD;
|
rfsimulator->typeStamp = UE_MAGICDL_FDD;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int server_start(openair0_device *device) {
|
int server_start(openair0_device *device) {
|
||||||
@@ -383,13 +317,13 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi
|
|||||||
rfsimulator_state_t *t = device->priv;
|
rfsimulator_state_t *t = device->priv;
|
||||||
LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp);
|
LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp);
|
||||||
|
|
||||||
|
|
||||||
for (int i=0; i<FD_SETSIZE; i++) {
|
for (int i=0; i<FD_SETSIZE; i++) {
|
||||||
buffer_t *b=&t->buf[i];
|
buffer_t *b=&t->buf[i];
|
||||||
|
|
||||||
if (b->conn_sock >= 0 ) {
|
if (b->conn_sock >= 0 ) {
|
||||||
if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize)
|
if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize)
|
||||||
LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS);
|
LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS);
|
||||||
|
|
||||||
samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
|
samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
|
||||||
fullwrite(b->conn_sock,&header, sizeof(header), t);
|
fullwrite(b->conn_sock,&header, sizeof(header), t);
|
||||||
sample_t tmpSamples[nsamps][nbAnt];
|
sample_t tmpSamples[nsamps][nbAnt];
|
||||||
@@ -546,19 +480,21 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
|||||||
// no connected device (we are eNB, no UE is connected)
|
// no connected device (we are eNB, no UE is connected)
|
||||||
if ( t->nextTimestamp == 0)
|
if ( t->nextTimestamp == 0)
|
||||||
LOG_W(HW,"No connected device, generating void samples...\n");
|
LOG_W(HW,"No connected device, generating void samples...\n");
|
||||||
|
|
||||||
if (!flushInput(t, 10)) {
|
if (!flushInput(t, 10)) {
|
||||||
for (int x=0; x < nbAnt; x++)
|
for (int x=0; x < nbAnt; x++)
|
||||||
memset(samplesVoid[x],0,sampleToByte(nsamps,1));
|
memset(samplesVoid[x],0,sampleToByte(nsamps,1));
|
||||||
|
|
||||||
t->nextTimestamp+=nsamps;
|
t->nextTimestamp+=nsamps;
|
||||||
|
|
||||||
if ( ((t->nextTimestamp/nsamps)%100) == 0)
|
if ( ((t->nextTimestamp/nsamps)%100) == 0)
|
||||||
LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
|
LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
|
||||||
|
|
||||||
*ptimestamp = t->nextTimestamp-nsamps;
|
*ptimestamp = t->nextTimestamp-nsamps;
|
||||||
pthread_mutex_unlock(&Sockmutex);
|
pthread_mutex_unlock(&Sockmutex);
|
||||||
return nsamps;
|
return nsamps;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
bool have_to_wait;
|
bool have_to_wait;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -566,19 +502,23 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
|||||||
|
|
||||||
for ( int sock=0; sock<FD_SETSIZE; sock++) {
|
for ( int sock=0; sock<FD_SETSIZE; sock++) {
|
||||||
buffer_t *b=&t->buf[sock];
|
buffer_t *b=&t->buf[sock];
|
||||||
|
|
||||||
if ( b->circularBuf) {
|
if ( b->circularBuf) {
|
||||||
LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n",
|
LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n",
|
||||||
sock, b->lastWroteTS,
|
sock, b->lastWroteTS,
|
||||||
b->lastReceivedTS,
|
b->lastReceivedTS,
|
||||||
t->nextTimestamp+nsamps);
|
t->nextTimestamp+nsamps);
|
||||||
|
|
||||||
if ( b->lastReceivedTS > b->lastWroteTS ) {
|
if ( b->lastReceivedTS > b->lastWroteTS ) {
|
||||||
// The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance
|
// The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance
|
||||||
// This occurs for example when UE is in sync mode: it doesn't transmit
|
// This occurs for example when UE is in sync mode: it doesn't transmit
|
||||||
// with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power
|
// with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power
|
||||||
struct complex16 v= {0};
|
struct complex16 v= {0};
|
||||||
void *samplesVoid[b->th.nbAnt];
|
void *samplesVoid[b->th.nbAnt];
|
||||||
|
|
||||||
for ( int i=0; i <b->th.nbAnt; i++)
|
for ( int i=0; i <b->th.nbAnt; i++)
|
||||||
samplesVoid[i]=(void *)&v;
|
samplesVoid[i]=(void *)&v;
|
||||||
|
|
||||||
rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0);
|
rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -621,10 +561,12 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
|||||||
a,
|
a,
|
||||||
ptr->channel_model,
|
ptr->channel_model,
|
||||||
nsamps,
|
nsamps,
|
||||||
t->nextTimestamp
|
t->nextTimestamp,
|
||||||
|
CirSize
|
||||||
);
|
);
|
||||||
else { // no channel modeling
|
else { // no channel modeling
|
||||||
sample_t *out=(sample_t *)samplesVoid[a];
|
sample_t *out=(sample_t *)samplesVoid[a];
|
||||||
|
|
||||||
for ( int i=0; i < nsamps; i++ ) {
|
for ( int i=0; i < nsamps; i++ ) {
|
||||||
out[i].r+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].r;
|
out[i].r+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].r;
|
||||||
out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].i;
|
out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].i;
|
||||||
@@ -672,15 +614,9 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
|||||||
// to change the log level, use this on command line
|
// to change the log level, use this on command line
|
||||||
// --log_config.hw_log_level debug
|
// --log_config.hw_log_level debug
|
||||||
rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
|
rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
|
||||||
|
|
||||||
rfsimulator_readconfig(rfsimulator);
|
rfsimulator_readconfig(rfsimulator);
|
||||||
|
|
||||||
pthread_mutex_init(&Sockmutex, NULL);
|
pthread_mutex_init(&Sockmutex, NULL);
|
||||||
|
|
||||||
|
|
||||||
LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE");
|
LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE");
|
||||||
|
|
||||||
|
|
||||||
device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ?
|
device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ?
|
||||||
server_start :
|
server_start :
|
||||||
start_ue;
|
start_ue;
|
||||||
|
|||||||
Reference in New Issue
Block a user