enhance channel model configuration

This commit is contained in:
frtabu
2021-03-10 02:33:31 +01:00
parent 3b1b74cfd2
commit 1f0e82664f
6 changed files with 226 additions and 66 deletions
@@ -0,0 +1,48 @@
/* configuration for channel modelisation */
/* To be included in main config file when */
/* channel modelisation is used (rfsimulator with chanmod options enabled) */
channelmod = {
max_chan=10;
modellist="modellist_rfsimu_1";
modellist_rfsimu_1 = (
{
model_name = "rfsimu_channel_ue0"
type = "AWGN";
ploss_dB = 0;
noise_power_dB = 0;
forgetfact = 0;
offset = 0;
ds_tdl = 0;
},
{
model_name = "rfsimu_channel_ue0"
type = "AWGN";
ploss_dB = 0;
noise_power_dB = 0;
forgetfact = 0;
offset = 0;
ds_tdl = 0;
},
);
modellist_rfsimu_2 = (
{
model_name = "rfsimu_channel_ue0"
type = "AWGN";
ploss_dB = 0;
noise_power_dB = 0;
forgetfact = 0;
offset = 0;
ds_tdl = 0;
},
{
model_name = "rfsimu_channel_ue0"
type = "AWGN";
ploss_dB = 0;
noise_power_dB = 0;
forgetfact = 0;
offset = 0;
ds_tdl = 0;
},
);
};
+1 -1
View File
@@ -255,7 +255,7 @@ int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix)
if ( ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgpath) == 0)) || /* short option, one "-" */ if ( ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgpath) == 0)) || /* short option, one "-" */
((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 )) || /* long option beginning with "--" */ ((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 )) || /* long option beginning with "--" */
((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgoptions[n].optname) == 0) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) || ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgoptions[n].optname) == 0) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) ||
((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 ) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) ) { ((strlen(oneargv) > 2) && (strcmp(oneargv + 2, cfgoptions[n].optname) == 0 ) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) ) {
char *valptr=NULL; char *valptr=NULL;
int ret; int ret;
config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED; config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED;
+1 -1
View File
@@ -495,7 +495,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,"%19s %19s %19[^\t\n]",modulename,cmd,cmdb); j = sscanf(buf,"%19s %19s %[^\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);
+82 -17
View File
@@ -61,7 +61,9 @@ static telnetshell_vardef_t channelmod_vardef[] = {
static double snr_dB=25; static double snr_dB=25;
static double sinr_dB=0; static double sinr_dB=0;
static unsigned int max_chan; static unsigned int max_chan;
static channel_desc_t** defined_channels; static channel_desc_t **defined_channels;
static char modellist_name[MAX_OPTNAME_SIZE]="";
void fill_channel_desc(channel_desc_t *chan_desc, void fill_channel_desc(channel_desc_t *chan_desc,
uint8_t nb_tx, uint8_t nb_tx,
uint8_t nb_rx, uint8_t nb_rx,
@@ -494,16 +496,17 @@ struct complex *R_sqrt_22_EPA_medium[1] = {R_sqrt_22_EPA_medium_tap};
//Rayleigh1_orth_eff_ch_TM4 //Rayleigh1_orth_eff_ch_TM4
channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
uint8_t nb_rx, uint8_t nb_rx,
SCM_t channel_model, SCM_t channel_model,
double sampling_rate, double sampling_rate,
double channel_bandwidth, double channel_bandwidth,
double DS_TDL, double DS_TDL,
double forgetting_factor, double forgetting_factor,
int32_t channel_offset, int32_t channel_offset,
double path_loss_dB, double path_loss_dB,
float noise_power_dB) { float noise_power_dB) {
channel_desc_t *chan_desc = (channel_desc_t *)calloc(1,sizeof(channel_desc_t)); channel_desc_t *chan_desc = (channel_desc_t *)calloc(1,sizeof(channel_desc_t));
for(int i=0; i<max_chan;i++) { for(int i=0; i<max_chan;i++) {
if (defined_channels[i] == NULL) { if (defined_channels[i] == NULL) {
@@ -540,6 +543,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
double *tdl_amps_dB; double *tdl_amps_dB;
double *tdl_delays; double *tdl_delays;
/* Spatial Channel Models (SCM) channel model from TR 38.901 Section 7.7.2 */
switch (channel_model) { switch (channel_model) {
case SCM_A: case SCM_A:
LOG_W(OCM,"channel model not yet supported\n"); LOG_W(OCM,"channel model not yet supported\n");
@@ -670,6 +674,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
break; break;
/* tapped delay line (TDL) channel model from TR 38.901 Section 7.7.2 */
case TDL_A: case TDL_A:
case TDL_B: case TDL_B:
case TDL_C: case TDL_C:
@@ -1631,8 +1636,21 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->nb_paths = 10; chan_desc->nb_paths = 10;
return(chan_desc); return(chan_desc);
} } /* channel_desc_t *new_channel_desc_scm */
channel_desc_t * find_channel_desc_fromname( char *modelname ) {
for(int i=0; i<max_chan;i++) {
if (defined_channels[i] != NULL) {
if (strcmp(defined_channels[i]->model_name,modelname) == 0)
return defined_channels[i];
}
}
LOG_E(OCM,"Model %s not found \n", modelname);
return NULL;
} /* channel_desc_t * new_channel_desc_fromconfig */
void free_channel_desc_scm(channel_desc_t *ch) { void free_channel_desc_scm(channel_desc_t *ch) {
// Must be made cleanly, a lot of leaks... // Must be made cleanly, a lot of leaks...
defined_channels[ch->chan_idx]=NULL; defined_channels[ch->chan_idx]=NULL;
@@ -1657,7 +1675,8 @@ void free_channel_desc_scm(channel_desc_t *ch) {
free(ch->R_sqrt); free(ch->R_sqrt);
free(ch->ch); free(ch->ch);
free(ch->chF); free(ch->chF);
free(ch->a); free(ch->a);
free(ch->model_name);
free(ch); free(ch);
} }
@@ -1665,6 +1684,12 @@ void set_channeldesc_owner(channel_desc_t *cdesc, uint32_t module_id) {
cdesc->module_id=module_id; cdesc->module_id=module_id;
} }
void set_channeldesc_name(channel_desc_t *cdesc,char *modelname) {
if(cdesc->model_name != NULL)
free(cdesc->model_name);
cdesc->model_name=strdup(modelname);
}
int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
double s; double s;
int i,k,l,aarx,aatx; int i,k,l,aarx,aatx;
@@ -1851,7 +1876,7 @@ double N_RB2channel_bandwidth(uint16_t N_RB) {
break; break;
default: default:
LOG_E(PHY,"Unknown N_PRB\n"); LOG_E(OCM,"Unknown N_PRB\n");
return(-1); return(-1);
} }
return(channel_bandwidth); return(channel_bandwidth);
@@ -1871,9 +1896,7 @@ static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt
static void display_channelmodel(channel_desc_t *cd,int debug, telnet_printfunc_t prnt) { static void display_channelmodel(channel_desc_t *cd,int debug, telnet_printfunc_t prnt) {
char *module_id_str[]=MODULEID_STR_INIT; char *module_id_str[]=MODULEID_STR_INIT;
if (cd->module_id != 0) { prnt("model owner: %s\n",(cd->module_id != 0)?module_id_str[cd->module_id]:"not set");
prnt("model owner: %s\n",module_id_str[cd->module_id]);
}
prnt("nb_tx: %i nb_rx: %i taps: %i bandwidth: %lf sampling: %lf\n",cd->nb_tx, cd->nb_rx, cd->nb_taps, cd->channel_bandwidth, cd->sampling_rate); prnt("nb_tx: %i nb_rx: %i taps: %i bandwidth: %lf sampling: %lf\n",cd->nb_tx, cd->nb_rx, cd->nb_taps, cd->channel_bandwidth, cd->sampling_rate);
prnt("channel length: %i Max path delay: %lf ricean fact.: %lf angle of arrival: %lf (randomized:%s)\n", prnt("channel length: %i Max path delay: %lf ricean fact.: %lf angle of arrival: %lf (randomized:%s)\n",
cd->channel_length, cd->Td, cd->ricean_factor, cd->aoa, (cd->random_aoa?"Yes":"No")); cd->channel_length, cd->Td, cd->ricean_factor, cd->aoa, (cd->random_aoa?"Yes":"No"));
@@ -1899,7 +1922,8 @@ static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt) {
} else if ( strcmp(subcmd,"current") == 0) { } else if ( strcmp(subcmd,"current") == 0) {
for (int i=0; i < max_chan ; i++) { for (int i=0; i < max_chan ; i++) {
if (defined_channels[i] != NULL) { if (defined_channels[i] != NULL) {
prnt("model %i %s: \n----------------\n", i, map_int_to_str(channelmod_names,defined_channels[i]->modelid)); prnt("model %i %s type %s: \n----------------\n", i, (defined_channels[i]->model_name !=NULL)?defined_channels[i]->model_name:"(no name set)",
map_int_to_str(channelmod_names,defined_channels[i]->modelid));
display_channelmodel(defined_channels[i],debug,prnt); display_channelmodel(defined_channels[i],debug,prnt);
} }
} }
@@ -1972,10 +1996,10 @@ static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt)
return CMDSTATUS_FOUND; return CMDSTATUS_FOUND;
} }
int modelid_fromname(char *modelname) { int modelid_fromstrtype(char *modeltype) {
int modelid=map_str_to_int(channelmod_names,modelname); int modelid=map_str_to_int(channelmod_names,modeltype);
if (modelid < 0) if (modelid < 0)
LOG_E(OCM,"random_channel.c: Error channel model %s unknown\n",modelname); LOG_E(OCM,"random_channel.c: Error channel model %s unknown\n",modeltype);
return modelid; return modelid;
} }
@@ -1989,18 +2013,59 @@ double channelmod_get_sinr_dB(void) {
void init_channelmod(void) { void init_channelmod(void) {
paramdef_t channelmod_params[] = CHANNELMOD_PARAMS_DESC; paramdef_t channelmod_params[] = CHANNELMOD_PARAMS_DESC;
int ret = config_get( channelmod_params,sizeof(channelmod_params)/sizeof(paramdef_t),CHANNELMOD_SECTION);
int numparams=sizeof(channelmod_params)/sizeof(paramdef_t);
int ret = config_get( channelmod_params,numparams,CHANNELMOD_SECTION);
AssertFatal(ret >= 0, "configuration couldn't be performed"); AssertFatal(ret >= 0, "configuration couldn't be performed");
defined_channels=calloc(max_chan,sizeof( channel_desc_t*)); defined_channels=calloc(max_chan,sizeof( channel_desc_t*));
AssertFatal(defined_channels!=NULL, "couldn't allocate %u channel descriptors\n",max_chan); AssertFatal(defined_channels!=NULL, "couldn't allocate %u channel descriptors\n",max_chan);
/* look for telnet server, if it is loaded, add the channel modeling commands to it */ /* look for telnet server, if it is loaded, add the channel modeling commands to it */
add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME);
if (addcmd != NULL) { if (addcmd != NULL) {
addcmd("channelmod",channelmod_vardef,channelmod_cmdarray); addcmd("channelmod",channelmod_vardef,channelmod_cmdarray);
} }
} } /* init_channelmod */
int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, double channel_bandwidth) {
paramdef_t achannel_params[] = CHANNELMOD_MODEL_PARAMS_DESC;
paramlist_def_t channel_list;
memset(&channel_list,0,sizeof(paramlist_def_t));
strncpy(channel_list.listname,modellist_name,MAX_OPTNAME_SIZE-1);
int numparams = sizeof(achannel_params)/sizeof(paramdef_t);
config_getlist( &channel_list,achannel_params,numparams, CHANNELMOD_SECTION);
AssertFatal(channel_list.numelt>0, "List %s.%s not found in config file\n",CHANNELMOD_SECTION,channel_list.listname);
int pindex_NAME = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_NAME_PNAME);
int pindex_DT = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_DT_PNAME );
int pindex_FF = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_FF_PNAME );
int pindex_CO = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_CO_PNAME );
int pindex_PL = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_PL_PNAME );
int pindex_NP = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_NP_PNAME );
int pindex_TYPE = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_TYPE_PNAME);
for (int i=0; i<channel_list.numelt; i++) {
int modid = modelid_fromstrtype( *(channel_list.paramarray[i][pindex_TYPE].strptr) );
if (modid <0) {
LOG_E(OCM,"Valid channel model types:\n");
for (int m=0; channelmod_names[i].name != NULL ; m++) {
printf(" %s ", map_int_to_str(channelmod_names,m ));
}
AssertFatal(0, "\n Choose a valid model type\n");
}
channel_desc_t *channeldesc_p = new_channel_desc_scm(nb_tx,nb_rx,modid,sampling_rate,channel_bandwidth,
*(channel_list.paramarray[i][pindex_DT].dblptr), *(channel_list.paramarray[i][pindex_FF].dblptr),
*(channel_list.paramarray[i][pindex_CO].iptr), *(channel_list.paramarray[i][pindex_PL].dblptr),
*(channel_list.paramarray[i][pindex_NP].dblptr) );
AssertFatal( (channeldesc_p!= NULL), "Could not allocate channel %s type %s \n",*(channel_list.paramarray[i][pindex_NAME].strptr), *(channel_list.paramarray[i][pindex_TYPE].strptr));
channeldesc_p->model_name = strdup(*(channel_list.paramarray[i][pindex_NAME].strptr));
LOG_I(OCM,"Model %s type %s allocated from config file, list %s\n",*(channel_list.paramarray[i][pindex_NAME].strptr),
*(channel_list.paramarray[i][pindex_TYPE].strptr), modellist_name);
} /* for loop on channel_list */
return channel_list.numelt;
} /* load_channelist */
#ifdef RANDOM_CHANNEL_MAIN #ifdef RANDOM_CHANNEL_MAIN
#define sampling_rate 5.0 #define sampling_rate 5.0
+46 -9
View File
@@ -107,8 +107,10 @@ typedef struct {
unsigned int chan_idx; unsigned int chan_idx;
/// id of the channel modeling algorithm /// id of the channel modeling algorithm
int modelid; int modelid;
/// identifies channel descriptor owner (the module which created this descriptor) /// identifies channel descriptor owner (the module which created this descriptor
channelmod_moduleid_t module_id; channelmod_moduleid_t module_id;
/// name of this descriptor,used for model created from config file at init time
char *model_name;
/// flags to properly trigger memory free /// flags to properly trigger memory free
unsigned int free_flags; unsigned int free_flags;
} channel_desc_t; } channel_desc_t;
@@ -242,12 +244,37 @@ typedef enum {
#define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n" #define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n"
#define CHANNELMOD_SECTION "channelmod" #define CHANNELMOD_SECTION "channelmod"
/* global channel modelization parameters */
#define CHANNELMOD_MODELLIST_PARANAME "modellist"
#define CHANNELMOD_HELP_MODELLIST "<list name> channel list name in config file describing the model type and its parameters\n"
#define CHANNELMOD_PARAMS_DESC { \ #define CHANNELMOD_PARAMS_DESC { \
{"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0},\ {"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0},\
{"sinr_dB", NULL, 0 , dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\ {"sinr_dB", NULL, 0, dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\
{"max_chan, CONFIG_HLP_MAX_CHAN", 0, uptr:&max_chan, defintval:10, TYPE_UINT, 0},\ {"max_chan", "Max number of runtime models", 0, uptr:&max_chan, defintval:10, TYPE_UINT, 0},\
{CHANNELMOD_MODELLIST_PARANAME, CHANNELMOD_HELP_MODELLIST, 0, strptr:(char **)&modellist_name, defstrval:"DefaultChannelList", TYPE_STRING, 60 },\
} }
/* parameters for one model */
#define CHANNELMOD_MODEL_NAME_PNAME "model_name"
#define CHANNELMOD_MODEL_TYPE_PNAME "type"
#define CHANNELMOD_MODEL_PL_PNAME "ploss_dB"
#define CHANNELMOD_MODEL_NP_PNAME "noise_power_dB"
#define CHANNELMOD_MODEL_FF_PNAME "forgetfact"
#define CHANNELMOD_MODEL_CO_PNAME "offset"
#define CHANNELMOD_MODEL_DT_PNAME "ds_tdl"
#define CHANNELMOD_MODEL_PARAMS_DESC { \
{CHANNELMOD_MODEL_NAME_PNAME, "name of the model\n", 0, strptr:NULL , defstrval:"", TYPE_STRING, 0 },\
{CHANNELMOD_MODEL_TYPE_PNAME, "name of the model type\n", 0, strptr:NULL , defstrval:"AWGN", TYPE_STRING, 0 },\
{CHANNELMOD_MODEL_PL_PNAME, "channel path loss in dB\n", 0, dblptr:NULL, defdblval:0, TYPE_DOUBLE, 0 },\
{CHANNELMOD_MODEL_NP_PNAME, "channel noise in dB\n", 0, dblptr:NULL, defdblval:0, TYPE_DOUBLE, 0 },\
{CHANNELMOD_MODEL_FF_PNAME, "channel forget factor ((0 to 1)\n", 0, dblptr:NULL, defdblval:0, TYPE_DOUBLE, 0 },\
{CHANNELMOD_MODEL_CO_PNAME, "channel offset in samps\n", 0, iptr:NULL, defintval:0, TYPE_INT, 0 },\
{CHANNELMOD_MODEL_DT_PNAME, "delay spread for TDL models\n", 0, dblptr:NULL, defdblval:0, TYPE_DOUBLE, 0 }\
}
#include "platform_constants.h" #include "platform_constants.h"
typedef struct { typedef struct {
@@ -276,13 +303,17 @@ typedef struct {
channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
uint8_t nb_rx, uint8_t nb_rx,
SCM_t channel_model, SCM_t channel_model,
double sampling_rate, double sampling_rate,
double channel_bandwidth, double channel_bandwidth,
double TDL_DS, double TDL_DS,
double forgetting_factor, double forgetting_factor,
int32_t channel_offset, int32_t channel_offset,
double path_loss_dB, double path_loss_dB,
float noise_power_dB); float noise_power_dB);
channel_desc_t *find_channel_desc_fromname( char *modelname );
/** /**
\brief free memory allocated for a model descriptor \brief free memory allocated for a model descriptor
\param ch points to the model, which cannot be used after calling this fuction \param ch points to the model, which cannot be used after calling this fuction
@@ -295,6 +326,12 @@ void free_channel_desc_scm(channel_desc_t *ch);
\param module_id identifies the channel model. should be define as a macro in simu.h \param module_id identifies the channel model. should be define as a macro in simu.h
*/ */
void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_id); void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_id);
/**
\brief This function set a model name to a model descriptor, can be later used to identify a allocated channel model
\param cdesc points to the model descriptor
\param module_name is the C string to use as model name for the channel pointed by cdesc
*/
void set_channeldesc_name(channel_desc_t *cdesc,char *modelname);
/** \fn void random_channel(channel_desc_t *desc) /** \fn void random_channel(channel_desc_t *desc)
\brief This routine generates a random channel response (time domain) according to a tapped delay line model. \brief This routine generates a random channel response (time domain) according to a tapped delay line model.
\param desc Pointer to the channel descriptor \param desc Pointer to the channel descriptor
@@ -454,11 +491,11 @@ void multipath_tv_channel(channel_desc_t *desc,
/**@} */ /**@} */
/**@} */ /**@} */
int modelid_fromname(char *modelname); int modelid_fromstrtype(char *modeltype);
double channelmod_get_snr_dB(void); double channelmod_get_snr_dB(void);
double channelmod_get_sinr_dB(void); double channelmod_get_sinr_dB(void);
void init_channelmod(void) ; void init_channelmod(void) ;
int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, double channel_bandwidth) ;
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);
+48 -38
View File
@@ -69,7 +69,9 @@ extern RAN_CONTEXT_t RC;
#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"\
" chanmod: enable channel modelisation\n"\ " chanmod: enable channel modelisation\n"\
" saviq: enable saving written iqs to a file\n" " saviq: enable saving written iqs to a file\n"
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -78,21 +80,21 @@ extern RAN_CONTEXT_t RC;
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define simOpt PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED #define simOpt PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED
#define RFSIMULATOR_PARAMS_DESC { \ #define RFSIMULATOR_PARAMS_DESC { \
{"serveraddr", "<ip address to connect to>\n", simOpt , strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ {"serveraddr", "<ip address to connect to>\n", simOpt, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\
{"serverport", "<port to connect to>\n", simOpt, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\ {"serverport", "<port to connect to>\n", simOpt, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\
{RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0 },\ {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0 },\
{"IQfile", "<file path to use when saving IQs>\n",simOpt, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\ {"IQfile", "<file path to use when saving IQs>\n",simOpt, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\
{"modelname", "<channel model name>\n", simOpt, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\ {"modelname", "<channel model name>\n", simOpt, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\
{"ploss", "<channel path loss in dB>\n", simOpt, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\ {"ploss", "<channel path loss in dB>\n", simOpt, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\
{"forgetfact", "<channel forget factor ((0 to 1)>\n", simOpt, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\ {"forgetfact", "<channel forget factor ((0 to 1)>\n", simOpt, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\
{"offset", "<channel offset in samps>\n", simOpt, iptr:&(rfsimulator->chan_offset), defintval:0, TYPE_INT, 0 }\ {"offset", "<channel offset in samps>\n", simOpt, iptr:&(rfsimulator->chan_offset), defintval:0, TYPE_INT, 0 }\
}; };
static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
static telnetshell_cmddef_t rfsimu_cmdarray[] = { static telnetshell_cmddef_t rfsimu_cmdarray[] = {
{"setmodel","<model name>",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, {"setmodel","<model name> <model type>",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ},
{"","",NULL}, {"","",NULL},
}; };
@@ -183,16 +185,9 @@ static void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
tableNor(rand); tableNor(rand);
init_done=true; init_done=true;
} }
char *modelname = (bridge->typeStamp == ENB_MAGICDL) ? "rfsimu_channel_ue0":"rfsimu_channel_enB0";
ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, ptr->channel_model=find_channel_desc_fromname(modelname); // path_loss in dB
bridge->channelmod, AssertFatal((ptr->channel_model!= NULL),"Channel model %s not found, check config file\n",modelname);
bridge->sample_rate,
bridge->tx_bw,
30e-9, // TDL delay-spread parameter
bridge->chan_forgetfact, // forgetting_factor
bridge->chan_offset, // maybe used for TA
bridge->chan_pathloss,
bridge->noise_power_dB); // path_loss in dB
set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID); set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID);
random_channel(ptr->channel_model,false); random_channel(ptr->channel_model,false);
} }
@@ -301,7 +296,8 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
break; break;
} else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) { } else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) {
init_channelmod(); init_channelmod();
rfsimulator->channelmod=modelid_fromname(modelname); load_channellist(rfsimulator->tx_num_channels, rfsimulator->rx_num_channels, rfsimulator->sample_rate, rfsimulator->tx_bw);
rfsimulator->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);
@@ -322,20 +318,27 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) { static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) {
char *modelname=NULL; char *modelname=NULL;
int s = sscanf(buff,"%ms\n",&modelname); char *modeltype=NULL;
if (debug)
prnt("rfsimu_setchanmod_cmd buffer \"%s\"\n",buff);
int s = sscanf(buff,"%m[^ ] %ms\n",&modelname, &modeltype);
if (s == 1) { if (s == 2) {
int channelmod=modelid_fromname(modelname); int channelmod=modelid_fromstrtype(modeltype);
if (channelmod<0) if (channelmod<0)
prnt("ERROR: model %s unknown\n",modelname); prnt("ERROR: model type %s unknown\n",modeltype);
else { else {
rfsimulator_state_t *t = (rfsimulator_state_t *)arg; rfsimulator_state_t *t = (rfsimulator_state_t *)arg;
int found=0;
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->channel_model==NULL)
continue;
if (b->channel_model->model_name==NULL)
continue;
if (b->conn_sock >= 0 && (strcmp(b->channel_model->model_name,modelname)==0)) {
if (b->conn_sock >= 0 ) {
channel_desc_t *newmodel=new_channel_desc_scm(t->tx_num_channels,t->rx_num_channels, channel_desc_t *newmodel=new_channel_desc_scm(t->tx_num_channels,t->rx_num_channels,
channelmod, channelmod,
t->sample_rate, t->sample_rate,
@@ -343,23 +346,29 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt,
30e-9, // TDL delay-spread parameter 30e-9, // TDL delay-spread parameter
t->chan_forgetfact, // forgetting_factor t->chan_forgetfact, // forgetting_factor
t->chan_offset, // maybe used for TA t->chan_offset, // maybe used for TA
t->chan_pathloss, t->chan_pathloss,
t->noise_power_dB t->noise_power_dB
); // path_loss in dB ); // path_loss in dB
set_channeldesc_owner(newmodel, RFSIMU_MODULEID); set_channeldesc_owner(newmodel, RFSIMU_MODULEID);
set_channeldesc_name(newmodel,modelname);
random_channel(newmodel,false); random_channel(newmodel,false);
channel_desc_t *oldmodel=b->channel_model; channel_desc_t *oldmodel=b->channel_model;
b->channel_model=newmodel; b->channel_model=newmodel;
free_channel_desc_scm(oldmodel); free_channel_desc_scm(oldmodel);
prnt("New model %s applied to channel connected to sock %d\n",modelname,i); prnt("New model type %s applied to channel %s connected to sock %d\n",modeltype,modelname,i);
found=1;
break;
} }
} } /* for */
if (found==0)
prnt("Channel %s not found or not currently used\n",modelname);
} }
} else { } else {
prnt("ERROR: no model specified\n"); prnt("ERROR: 2 parameters required: model name and model type (%i found)\n",s);
} }
free(modelname); free(modelname);
free(modeltype);
return CMDSTATUS_FOUND; return CMDSTATUS_FOUND;
} }
@@ -778,6 +787,11 @@ 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);
// initialize channel simulation
rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels;
rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels;
rfsimulator->sample_rate=openair0_cfg->sample_rate;
rfsimulator->tx_bw=openair0_cfg->tx_bw;
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 ? "server waiting opposite rfsimulators to connect" : "client: will connect to a rfsimulator server side"); LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL ? "server waiting opposite rfsimulators to connect" : "client: will connect to a rfsimulator server side");
@@ -802,11 +816,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
rfsimulator->buf[i].conn_sock=-1; rfsimulator->buf[i].conn_sock=-1;
AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,""); AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,"");
// initialize channel simulation
rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels;
rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels;
rfsimulator->sample_rate=openair0_cfg->sample_rate;
rfsimulator->tx_bw=openair0_cfg->tx_bw;
//randominit(0); //randominit(0);
set_taus_seed(0); set_taus_seed(0);
/* look for telnet server, if it is loaded, add the channel modeling commands to it */ /* look for telnet server, if it is loaded, add the channel modeling commands to it */