Commit 470ecad2 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge remote-tracking branch 'origin/add_chansimuparams' into develop_integration_2020_w31

parents e83acab6 d4bd2cdc
......@@ -2478,8 +2478,8 @@ add_library(uescope MODULE ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} ${XFORMS_
target_link_libraries(enbscope ${XFORMS_LIBRARIES})
target_link_libraries(uescope ${XFORMS_LIBRARIES})
add_library(gnbscope MODULE ${XFORMS_SOURCE_NR})
target_link_libraries(gnbscope ${XFORMS_LIBRARIES})
add_library(nrscope MODULE ${XFORMS_SOURCE_NR})
target_link_libraries(nrscope ${XFORMS_LIBRARIES})
add_library(rfsimulator MODULE
......@@ -2735,7 +2735,7 @@ add_executable(nr-softmodem
${OPENAIR_DIR}/common/utils/system.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${GTPU_need_ITTI}
${XFORMS_SOURCE_NR}
${XFORMSINTERFACE_SOURCE}
${T_SOURCE}
${CONFIG_SOURCES}
${SHLIB_LOADER_SOURCES}
......@@ -2777,7 +2777,7 @@ add_executable(nr-uesoftmodem
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${XFORMS_SOURCE_NR}
${XFORMSINTERFACE_SOURCE}
${T_SOURCE}
${UTIL_SRC}
${CONFIG_SOURCES}
......
......@@ -67,7 +67,7 @@ UE_TIMING_TRACE="False"
USRP_REC_PLAY="False"
BUILD_ECLIPSE=0
NR="False"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope msc"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope msc"
trap handle_ctrl_c INT
function print_help() {
......
......@@ -53,6 +53,7 @@
#include <sys/resource.h>
#include "common/utils/load_module_shlib.h"
#include "common/config/config_userapi.h"
#include "common/utils/threadPool/thread-pool.h"
#include "executables/softmodem-common.h"
#include <readline/history.h>
......@@ -507,12 +508,22 @@ int process_command(char *buf) {
}
rt= CMDSTATUS_FOUND;
} else if (strncasecmp(cmd,"get",3) == 0 || strncasecmp(cmd,"set",3) == 0) {
} else if (strcasecmp(cmd,"get") == 0 || strcasecmp(cmd,"set") == 0) {
rt= setgetvar(i,cmd[0],cmdb);
} else {
for (k=0 ; telnetparams.CmdParsers[i].cmd[k].cmdfunc != NULL ; k++) {
if (strncasecmp(cmd, telnetparams.CmdParsers[i].cmd[k].cmdname,sizeof(telnetparams.CmdParsers[i].cmd[k].cmdname)) == 0) {
telnetparams.CmdParsers[i].cmd[k].cmdfunc(cmdb, telnetparams.telnetdbg, client_printf);
if (telnetparams.CmdParsers[i].cmd[k].qptr != NULL) {
notifiedFIFO_elt_t *msg =newNotifiedFIFO_elt(sizeof(telnetsrv_qmsg_t),0,NULL,NULL);
telnetsrv_qmsg_t *cmddata=NotifiedFifoData(msg);
cmddata->cmdfunc=(qcmdfunc_t)telnetparams.CmdParsers[i].cmd[k].cmdfunc;
cmddata->prnt=client_printf;
cmddata->debug=telnetparams.telnetdbg;
cmddata->cmdbuff=strdup(cmdb);
pushNotifiedFIFO(telnetparams.CmdParsers[i].cmd[k].qptr, msg);
} else {
telnetparams.CmdParsers[i].cmd[k].cmdfunc(cmdb, telnetparams.telnetdbg, client_printf);
}
rt= CMDSTATUS_FOUND;
}
} /* for k */
......@@ -673,6 +684,16 @@ void run_telnetsrv(void) {
return;
}
void poll_telnetcmdq(void *qid, void *arg) {
notifiedFIFO_elt_t *msg = pollNotifiedFIFO((notifiedFIFO_t *)qid);
if (msg != NULL) {
telnetsrv_qmsg_t *msgdata=NotifiedFifoData(msg);
msgdata->cmdfunc(msgdata->cmdbuff,msgdata->debug,msgdata->prnt,arg);
free(msgdata->cmdbuff);
delNotifiedFIFO_elt(msg);
}
}
/*------------------------------------------------------------------------------------------------*/
/* load the commands delivered with the telnet server
*
......@@ -758,6 +779,7 @@ int telnetsrv_autoinit(void) {
*/
int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd) {
int i;
notifiedFIFO_t *afifo=NULL;
if( modulename == NULL || var == NULL || cmd == NULL) {
fprintf(stderr,"[TELNETSRV] Telnet server, add_telnetcmd: invalid parameters\n");
......@@ -769,6 +791,13 @@ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmdde
strncpy(telnetparams.CmdParsers[i].module,modulename,sizeof(telnetparams.CmdParsers[i].module)-1);
telnetparams.CmdParsers[i].cmd = cmd;
telnetparams.CmdParsers[i].var = var;
if (cmd->cmdflags & TELNETSRV_CMDFLAG_PUSHINTPOOLQ) {
if (afifo == NULL) {
afifo = malloc(sizeof(notifiedFIFO_t));
initNotifiedFIFO(afifo);
}
cmd->qptr = afifo;
}
printf("[TELNETSRV] Telnet server: module %i = %s added to shell\n",
i,telnetparams.CmdParsers[i].module);
break;
......@@ -797,8 +826,10 @@ int telnetsrv_checkbuildver(char *mainexec_buildversion, char **shlib_buildvers
}
int telnetsrv_getfarray(loader_shlibfunc_t **farray) {
*farray=malloc(sizeof(loader_shlibfunc_t));
*farray=malloc(sizeof(loader_shlibfunc_t)*2);
(*farray)[0].fname=TELNET_ADDCMD_FNAME;
(*farray)[0].fptr=(int (*)(void) )add_telnetcmd;
return 1;
(*farray)[1].fname=TELNET_POLLCMDQ_FNAME;
(*farray)[1].fptr=(int (*)(void) )poll_telnetcmdq;
return ( 2);
}
......@@ -53,13 +53,26 @@
/* to add a set of new command to the telnet server shell */
typedef void(*telnet_printfunc_t)(const char* format, ...);
typedef int(*cmdfunc_t)(char*, int, telnet_printfunc_t prnt);
typedef int(*qcmdfunc_t)(char*, int, telnet_printfunc_t prnt,void *arg);
#define TELNETSRV_CMDFLAG_PUSHINTPOOLQ (1<<0) // ask the telnet server to push the command in a thread pool queue
typedef struct cmddef {
char cmdname[TELNET_CMD_MAXSIZE];
char helpstr[TELNET_HELPSTR_SIZE];
cmdfunc_t cmdfunc;
unsigned int cmdflags;
void *qptr;
} telnetshell_cmddef_t;
/*----------------------------------------------------------------------------*/
/* structure used to send a command via a message queue to enable */
/* executing a command in a thread different from the telnet server thread */
typedef struct telnetsrv_qmsg {
qcmdfunc_t cmdfunc;
telnet_printfunc_t prnt;
int debug;
char *cmdbuff;
} telnetsrv_qmsg_t;
/*----------------------------------------------------------------------------*/
/*structure to be used when adding a module to the telnet server */
/* This is the first parameter of the add_telnetcmd function, which can be used */
......@@ -111,9 +124,6 @@ typedef struct {
} telnetsrv_params_t;
typedef int(*addcmdfunc_t)(char*, telnetshell_vardef_t*, telnetshell_cmddef_t*);
typedef void(*settelnetmodule_t)(char *name, void *ptr);
/*-------------------------------------------------------------------------------------------*/
......@@ -133,7 +143,9 @@ VT escape sequence definition, for smarter display....
/*---------------------------------------------------------------------------------------------*/
#define TELNET_ADDCMD_FNAME "add_telnetcmd"
#define TELNET_POLLCMDQ_FNAME "poll_telnetcmdq"
typedef int(*add_telnetcmd_func_t)(char *, telnetshell_vardef_t *, telnetshell_cmddef_t *);
typedef void(*poll_telnetcmdq_func_t)(void *qid,void *arg);
#ifdef TELNETSERVERCODE
int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd);
void set_sched(pthread_t tid, int pid,int priority);
......
......@@ -75,7 +75,7 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "system.h"
#include <openair2/GNB_APP/gnb_app.h>
#include "PHY/TOOLS/phy_scope_interface.h"
#include "PHY/TOOLS/nr_phy_scope.h"
#include "stats.h"
#include "nr-softmodem.h"
......@@ -156,7 +156,6 @@ char channels[128] = "0";
int rx_input_level_dBm;
uint32_t do_forms=0;
int otg_enabled;
//int number_of_cards = 1;
......@@ -454,7 +453,11 @@ static void get_options(void) {
paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ;
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
get_common_options(SOFTMODEM_GNB_BIT );
config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL);
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
......@@ -817,7 +820,6 @@ int main( int argc, char **argv )
configure_linux();
printf("Reading in command-line options\n");
get_options ();
get_common_options(SOFTMODEM_GNB_BIT );
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
fprintf(stderr,"Getting configuration failed\n");
......@@ -959,14 +961,14 @@ if(!IS_SOFTMODEM_NOS1)
printf("RC.nb_RU:%d\n", RC.nb_RU);
// once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
printf("ALL RUs ready - init gNBs\n");
if (do_forms==1) {
if(IS_SOFTMODEM_DOFORMS) {
scopeParms_t p;
p.argc=&argc;
p.argv=argv;
p.gNB=RC.gNB[0];
p.ru=RC.ru[0];
gNBinitScope(&p);
load_softscope("nr",&p);
}
if (nfapi_mode != 1 && nfapi_mode != 2) {
......
......@@ -19,21 +19,12 @@
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define CMDLINE_PARAMS_DESC_GNB { \
{"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \
{"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&wait_for_sync, defintval:0, TYPE_INT, 0}, \
{"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \
{"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \
{"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF, TYPE_UINT64, 0}, \
{"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, i8ptr:&threequarter_fs, defintval:0, TYPE_INT8, 0}, \
{"K" , CONFIG_HLP_ITTIL, PARAMFLAG_NOFREE, strptr:&itti_dump_file, defstrval:"/tmp/itti.dump", TYPE_STRING, 0}, \
{"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \
{"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \
{"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \
{"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)&parallel_config, defstrval:NULL, TYPE_STRING, 0}, \
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
{"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \
{"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \
}
......
......@@ -78,6 +78,9 @@ unsigned short config_frames[4] = {2,9,11,13};
/* Callbacks, globals and object handlers */
//#include "stats.h"
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
#include "PHY/TOOLS/phy_scope_interface.h"
#include "PHY/TOOLS/nr_phy_scope.h"
#include <executables/nr-uesoftmodem.h>
#include "executables/softmodem-common.h"
......@@ -148,14 +151,11 @@ char ref[128] = "internal";
char channels[128] = "0";
static char *parallel_config = NULL;
static char *worker_config = NULL;
int rx_input_level_dBm;
//static int online_log_messages=0;
uint32_t do_forms=0;
int otg_enabled;
//int number_of_cards = 1;
......@@ -758,8 +758,10 @@ int main( int argc, char **argv ) {
memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
configure_linux();
mlockall(MCL_CURRENT | MCL_FUTURE);
if (do_forms)
nrUEinitScope(PHY_vars_UE_g[0][0]);
if(IS_SOFTMODEM_DOFORMS) {
load_softscope("nr",PHY_vars_UE_g[0][0]);
}
number_of_cards = 1;
for(int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
......
......@@ -61,19 +61,11 @@
{"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \
{"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \
{"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \
{"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0,TYPE_UINT64, 0}, \
{"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:&do_forms, defintval:0, TYPE_INT, 0}, \
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0}, \
{"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \
{"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
{"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \
{"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, iptr:&vcdflag, defintval:0, TYPE_INT, 0}, \
{"numerology" , CONFIG_HLP_NUMEROLOGY, 0, iptr:&numerology, defintval:0, TYPE_INT, 0}, \
{"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \
{"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)&parallel_config, defstrval:NULL, TYPE_STRING, 0}, \
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
{"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \
{"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0}, \
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&UE_no_timing_correction, defintval:0, TYPE_INT, 0}, \
......
......@@ -26,6 +26,7 @@
#include <stdlib.h>
#include "nr_phy_scope.h"
#include "executables/nr-softmodem-common.h"
#include "executables/softmodem-common.h"
#include <forms.h>
#define TPUT_WINDOW_LENGTH 100
......@@ -768,6 +769,15 @@ void nrUEinitScope(PHY_VARS_NR_UE *ue) {
threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW);
}
void nrscope_autoinit(void *dataptr) {
AssertFatal( (IS_SOFTMODEM_GNB_BIT||IS_SOFTMODEM_5GUE_BIT),"Scope cannot find NRUE or GNB context");
if (IS_SOFTMODEM_GNB_BIT)
gNBinitScope(dataptr);
else
nrUEinitScope(dataptr);
}
// Kept to put back the functionality soon
#if 0
//FD_stats_form *form_stats=NULL,*form_stats_l2=NULL;
......@@ -795,6 +805,8 @@ static void reset_stats_gNB(FL_OBJECT *button,
}
}
static FD_stats_form *create_form_stats_form(int ID) {
FL_OBJECT *obj;
FD_stats_form *fdui = calloc(( sizeof *fdui ),1);
......
......@@ -40,8 +40,6 @@ typedef struct {
PHY_VARS_gNB *gNB;
} scopeParms_t;
void gNBinitScope(scopeParms_t *p);
void nrUEinitScope(PHY_VARS_NR_UE *ue);
extern RAN_CONTEXT_t RC;
#endif
......@@ -37,10 +37,10 @@
#define SOFTSCOPE_ENDFUNC_IDX 0
static loader_shlibfunc_t scope_fdesc[]= {{"end_forms",NULL}};
int load_softscope(char *exectype) {
int load_softscope(char *exectype, void *initarg) {
char libname[64];
sprintf(libname,"%.10sscope",exectype);
return load_module_shlib(libname,scope_fdesc,1,NULL);
return load_module_shlib(libname,scope_fdesc,1,initarg);
}
int end_forms(void) {
......
......@@ -31,5 +31,5 @@
*/
int load_softscope(char *exectype);
int load_softscope(char *exectype, void *initarg);
int end_forms(void) ;
......@@ -45,8 +45,12 @@ static mapping channelmod_names[] = {
};
static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt);
static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt);
static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt);
static telnetshell_cmddef_t channelmod_cmdarray[] = {
{"show","",channelmod_show_cmd},
{"help","",channelmod_print_help},
{"show","<predef,current>",channelmod_show_cmd},
{"modify","<channelid> <param> <value>",channelmod_modify_cmd},
{"","",NULL},
};
......@@ -56,14 +60,15 @@ static telnetshell_vardef_t channelmod_vardef[] = {
static double snr_dB=25;
static double sinr_dB=0;
static unsigned int max_chan;
static channel_desc_t** defined_channels;
void fill_channel_desc(channel_desc_t *chan_desc,
uint8_t nb_tx,
uint8_t nb_rx,
uint8_t nb_taps,
uint8_t channel_length,
double *amps,
double *delays,
double *delays,
struct complex **R_sqrt,
double Td,
double sampling_rate,
......@@ -88,6 +93,7 @@ void fill_channel_desc(channel_desc_t *chan_desc,
if (delays==NULL) {
chan_desc->delays = (double *) malloc(nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_DELAY ;
delta_tau = Td/nb_taps;
for (i=0; i<nb_taps; i++)
......@@ -129,10 +135,9 @@ void fill_channel_desc(channel_desc_t *chan_desc,
if (R_sqrt == NULL) {
chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_NTAPS ;
for (i = 0; i<nb_taps; i++) {
chan_desc->R_sqrt[i] = (struct complex *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex));
chan_desc->R_sqrt[i] = (struct complex *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex));
for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) {
chan_desc->R_sqrt[i][j].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0;
......@@ -140,7 +145,7 @@ void fill_channel_desc(channel_desc_t *chan_desc,
}
} else {
chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *));
for (i = 0; i<nb_taps; i++) {
//chan_desc->R_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex));
//chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0];
......@@ -170,7 +175,7 @@ void fill_channel_desc(channel_desc_t *chan_desc,
double mbsfn_delays[] = {0,.03,.15,.31,.37,1.09,12.490,12.52,12.64,12.80,12.86,13.58,27.49,27.52,27.64,27.80,27.86,28.58};
double mbsfn_amps_dB[] = {0,-1.5,-1.4,-3.6,-0.6,-7.0,-10,-11.5,-11.4,-13.6,-10.6,-17.0,-20,-21.5,-21.4,-23.6,-20.6,-27};
double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250};
double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250};
double scm_c_amps_dB[] = {0.00, -2.22, -3.98, -1.86, -4.08, -5.84, -1.08, -3.30, -5.06, -9.08, -11.30, -13.06, -15.14, -17.36, -19.12, -20.64, -22.85, -24.62};
double epa_delays[] = { 0,.03,.07,.09,.11,.19,.41};
......@@ -277,14 +282,26 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
SCM_t channel_model,
double sampling_rate,
double channel_bandwidth,
double forgetting_factor,
double forgetting_factor,
int32_t channel_offset,
double path_loss_dB) {
channel_desc_t *chan_desc = (channel_desc_t *)malloc(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++) {
if (defined_channels[i] == NULL) {
defined_channels[i]=chan_desc;
chan_desc->chan_idx=i;
break;
}
else {
AssertFatal(i<(max_chan-1),
"No more channel descriptors available, increase channelmod.max_chan parameter above %u\n",max_chan);
}
}
uint16_t i,j;
double sum_amps;
double aoa,ricean_factor,Td,maxDoppler;
int channel_length,nb_taps;
chan_desc->modelid = channel_model;
chan_desc->nb_tx = nb_tx;
chan_desc->nb_rx = nb_rx;
chan_desc->sampling_rate = sampling_rate;
......@@ -313,7 +330,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
sum_amps = 0;
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]);
sum_amps += chan_desc->amps[i];
......@@ -351,9 +368,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0];
} else {
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
for (i = 0; i<6; i++) {
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) {
chan_desc->R_sqrt[i][j].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0;
......@@ -372,7 +390,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
sum_amps = 0;
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]);
sum_amps += chan_desc->amps[i];
......@@ -410,6 +428,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0];
} else {
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
for (i = 0; i<6; i++) {
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
......@@ -423,14 +442,14 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
}
break;
case EPA:
chan_desc->nb_taps = 7;
chan_desc->Td = .410;
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
sum_amps = 0;
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i];
......@@ -449,7 +468,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
......@@ -463,7 +482,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} else {
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
for (i = 0; i<6; i++) {
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
......@@ -484,7 +503,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
sum_amps = 0;
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i];
......@@ -530,7 +549,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
}
}*/
break;
break;
case EPA_high:
chan_desc->nb_taps = 7;
......@@ -538,7 +557,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
sum_amps = 0;
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i];
......@@ -592,7 +611,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
sum_amps = 0;
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i];
......@@ -646,7 +665,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
sum_amps = 0;
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]);
sum_amps += chan_desc->amps[i];
......@@ -679,8 +698,8 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} else {
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
for (i = 0; i<6; i++) {
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
for (i = 0; i<6; i++) {
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) {
......@@ -700,7 +719,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
sum_amps = 0;
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]);
sum_amps += chan_desc->amps[i];
......@@ -733,7 +752,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} else {
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
for (i = 0; i<6; i++) {
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
......@@ -754,7 +773,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
sum_amps = 0;
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]);
sum_amps += chan_desc->amps[i];
......@@ -781,7 +800,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex *));
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6;
for (i = 0; i<6; i++) {
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
......@@ -1292,10 +1311,37 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->nb_paths = 10;
return(chan_desc);
}
void free_channel_desc_scm(channel_desc_t *ch) {
// Must be made cleanly, a lot of leaks...
free(ch);
defined_channels[ch->chan_idx]=NULL;
if(ch->free_flags&CHANMODEL_FREE_AMPS)
free(ch->amps);
for (int i = 0; i<ch->nb_tx*ch->nb_rx; i++) {
free(ch->ch[i]);
free(ch->chF[i]);
}
for (int i = 0; i<ch->nb_taps; i++) {
free(ch->a[i]);
}
if(ch->free_flags&CHANMODEL_FREE_DELAY)
free(ch->delays);
if(ch->free_flags&CHANMODEL_FREE_RSQRT_6)
for (int i = 0; i<6; i++)
free(ch->R_sqrt[i]);
if(ch->free_flags&CHANMODEL_FREE_RSQRT_NTAPS)
for (int i = 0; i<ch->nb_taps;i++)
free(ch->R_sqrt[i]);
free(ch->R_sqrt);
free(ch->ch);
free(ch->chF);
free(ch->a);
free(ch);
}
void set_channeldesc_owner(channel_desc_t *cdesc, uint32_t module_id) {
cdesc->module_id=module_id;
}
int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
......@@ -1408,11 +1454,11 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0;
for (l=0; l<desc->nb_taps; l++) {
if ((k - (desc->delays[l]*desc->sampling_rate) - NB_SAMPLES_CHANNEL_OFFSET) == 0)
if ((k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset) == 0)
s = 1.0;
else
s = sin(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - NB_SAMPLES_CHANNEL_OFFSET))/
(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - NB_SAMPLES_CHANNEL_OFFSET));
s = sin(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset))/
(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset));
desc->ch[aarx+(aatx*desc->nb_rx)][k].x += s*desc->a[l][aarx+(aatx*desc->nb_rx)].x;
desc->ch[aarx+(aatx*desc->nb_rx)][k].y += s*desc->a[l][aarx+(aatx*desc->nb_rx)].y;
......@@ -1436,7 +1482,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
return (0);
}
double N_RB2sampling_rate(uint16_t N_RB) {
double sampling_rate;
......@@ -1488,22 +1534,125 @@ double N_RB2channel_bandwidth(uint16_t N_RB) {
LOG_E(PHY,"Unknown N_PRB\n");
return(-1);
}
return(channel_bandwidth);
}
static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt ) {
prnt("channelmod commands can be used to display or modify channel models parameters\n");
prnt("channelmod show predef: display predefined model algorithms available in oai\n");
prnt("channelmod show current: display the currently used models in the running executable\n");
prnt("channelmod modify <model index> <param name> <param value>: set the specified parameters in a current model to the given value\n");
prnt(" <model index> specifies the model, the show current model command can be used to list the current models indexes\n");
prnt(" <param name> can be one of \"riceanf\", \"aoa\", \"randaoa\", \"ploss\", \"offset\", \"forgetf\"\n");
return CMDSTATUS_FOUND;
}
static void display_channelmodel(channel_desc_t *cd,int debug, telnet_printfunc_t prnt) {
char *module_id_str[]=MODULEID_STR_INIT;
if (cd->module_id != 0) {
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("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"));
prnt("max Doppler: %lf path loss: %lf rchannel offset: %i forget factor; %lf\n",
cd->max_Doppler, cd->path_loss_dB, cd->channel_offset, cd->forgetting_factor);
prnt("Initial phase: %lf nb_path: %i \n",
cd->ip, cd->nb_paths);
for (int i=0; i<cd->nb_taps ; i++) {
prnt("taps: %i lin. ampli. : %lf delay: %lf \n",i,cd->amps[i], cd->delays[i]);
}
}
static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt) {
for(int i=0; channelmod_names[i].name != NULL ; i++) {
prnt(" %i %s\n", i, map_int_to_str(channelmod_names,i ));
char *subcmd=NULL;
int s = sscanf(buff,"%ms\n",&subcmd);
if (s>0) {
if ( strcmp(subcmd,"predef") == 0) {
for (int i=0; channelmod_names[i].name != NULL ; i++) {
prnt(" %i %s\n", i, map_int_to_str(channelmod_names,i ));
}
} else if ( strcmp(subcmd,"current") == 0) {
for (int i=0; i < max_chan ; i++) {
if (defined_channels[i] != NULL) {
prnt("model %i %s: \n----------------\n", i, map_int_to_str(channelmod_names,defined_channels[i]->modelid));
display_channelmodel(defined_channels[i],debug,prnt);
}
}
} else {
channelmod_print_help(buff, debug, prnt);
}
free(subcmd);
}
return 0;
return CMDSTATUS_FOUND;
}
int modelid_fromname(char *modelname) {
int modelid=map_str_to_int(channelmod_names,modelname);
AssertFatal(modelid>0,
"random_channel.c: Error channel model %s unknown\n",modelname);
static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt) {
char *param=NULL, *value=NULL;
int cd_id= -1;
int s = sscanf(buff,"%i %ms %ms \n",&cd_id,&param, &value);
if (cd_id<0 || cd_id >= max_chan) {
prnt("ERROR, %i: Channel model id outof range (0-%i)\n",cd_id,max_chan-1);
return CMDSTATUS_FOUND;
}
if (defined_channels[cd_id]==NULL) {
prnt("ERROR, %i: Channel model has not been set\n",cd_id);
return CMDSTATUS_FOUND;
}
if (s==3) {
if ( strcmp(param,"riceanf") == 0) {
double dbl = atof(value);
if (dbl <0 || dbl > 1)
prnt("ERROR: ricean factor range: 0 to 1, %lf is outof range\n",dbl);
else
defined_channels[cd_id]->ricean_factor=dbl;
} else if ( strcmp(param,"aoa") == 0) {
double dbl = atof(value);
if (dbl <0 || dbl >6.28)
prnt("ERROR: angle of arrival range: 0 to 2*Pi, %lf is outof range\n",dbl);
else
defined_channels[cd_id]->aoa=dbl;
} else if ( strcmp(param,"randaoa") == 0) {
int i = atoi(value);
if (i!=0 && i!=1)
prnt("ERROR: randaoa is a boolean, must be 0 or 1\n");
else
defined_channels[cd_id]->random_aoa=i;
} else if ( strcmp(param,"ploss") == 0) {
double dbl = atof(value);
defined_channels[cd_id]->path_loss_dB=dbl;
} else if ( strcmp(param,"offset") == 0) {
int i = atoi(value);
defined_channels[cd_id]->channel_offset=i;
} else if ( strcmp(param,"forgetf") == 0) {
double dbl = atof(value);
if (dbl <0 || dbl > 1)
prnt("ERROR: forgetting factor range: 0 to 1 (disable variation), %lf is outof range\n",dbl);
else
defined_channels[cd_id]->forgetting_factor=dbl;
} else {
prnt("ERROR: %s, unknown channel parameter\n",param);
return CMDSTATUS_FOUND;
}
display_channelmodel(defined_channels[cd_id],debug,prnt);
free(param);
free(value);
random_channel(defined_channels[cd_id],false);
}
return CMDSTATUS_FOUND;
}
int modelid_fromname(char *modelname) {
int modelid=map_str_to_int(channelmod_names,modelname);
if (modelid < 0)
LOG_E(OCM,"random_channel.c: Error channel model %s unknown\n",modelname);
return modelid;
}
......@@ -1519,6 +1668,9 @@ void init_channelmod(void) {
paramdef_t channelmod_params[] = CHANNELMOD_PARAMS_DESC;
int ret = config_get( channelmod_params,sizeof(channelmod_params)/sizeof(paramdef_t),CHANNELMOD_SECTION);
AssertFatal(ret >= 0, "configuration couldn't be performed");
defined_channels=calloc(max_chan,sizeof( channel_desc_t*));
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 */
add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME);
......
......@@ -40,6 +40,16 @@ The present clause specifies several numerical functions for testing of digital
#define NB_SAMPLES_CHANNEL_OFFSET 4
typedef enum {
UNSPECIFIED_MODID=0,
RFSIMU_MODULEID=1
} channelmod_moduleid_t;
#define MODULEID_STR_INIT {"","rfsimulator"}
#define CHANMODEL_FREE_DELAY 1<<0
#define CHANMODEL_FREE_RSQRT_6 1<<1
#define CHANMODEL_FREE_RSQRT_NTAPS 1<<2
#define CHANMODEL_FREE_AMPS 1<<3
typedef struct {
///Number of tx antennas
uint8_t nb_tx;
......@@ -92,6 +102,14 @@ typedef struct {
time_stats_t interp_time;
time_stats_t interp_freq;
time_stats_t convolution;
/// index in the channel descriptors array
unsigned int chan_idx;
/// id of the channel modeling algorithm
int modelid;
/// identifies channel descriptor owner (the module which created this descriptor)
channelmod_moduleid_t module_id;
/// flags to properly trigger memory free
unsigned int free_flags;
} channel_desc_t;
typedef struct {
......@@ -214,8 +232,9 @@ typedef enum {
#define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n"
#define CHANNELMOD_SECTION "channelmod"
#define CHANNELMOD_PARAMS_DESC { \
{"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},\
{"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},\
{"max_chan, CONFIG_HLP_MAX_CHAN", 0, uptr:&max_chan, defintval:10, TYPE_UINT, 0},\
}
#include "platform_constants.h"
......@@ -273,9 +292,18 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
double forgetting_factor,
int32_t channel_offset,
double path_loss_dB);
/**
\brief free memory allocated for a model descriptor
\param ch points to the model, which cannot be used after calling this fuction
*/
void free_channel_desc_scm(channel_desc_t *ch);
/**
\brief This set the ownerid of a model descriptor, can be later used to check what module created a channel model
\param cdesc points to the model descriptor
\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);
/** \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.
\param desc Pointer to the channel descriptor
......
......@@ -44,6 +44,7 @@
#include <common/utils/assertions.h>
#include <common/utils/LOG/log.h>
#include <common/utils/load_module_shlib.h>
#include <common/utils/telnetsrv/telnetsrv.h>
#include <common/config/config_userapi.h>
#include "common_lib.h"
#include <openair1/PHY/defs_eNB.h>
......@@ -78,11 +79,25 @@ extern RAN_CONTEXT_t RC;
#define RFSIMULATOR_PARAMS_DESC {\
{"serveraddr", "<ip address to connect to>\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\
{"serverport", "<port to connect to>\n", 0, 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", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\
{"modelname", "<channel model name>\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 }\
{"modelname", "<channel model name>\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\
{"ploss", "<channel path loss in dB>\n", 0, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\
{"forgetfact", "<channel forget factor ((0 to 1)>\n", 0, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\
{"offset", "<channel offset in samps>\n", 0, 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 telnetshell_cmddef_t rfsimu_cmdarray[] = {
{"setmodel","<model name>",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ},
{"","",NULL},
};
static telnetshell_vardef_t rfsimu_vardef[] = {
{"",0,NULL}
};
pthread_mutex_t Sockmutex;
typedef struct complex16 sample_t; // 2*16 bits complex number
......@@ -114,6 +129,11 @@ typedef struct {
double sample_rate;
double tx_bw;
int channelmod;
double chan_pathloss;
double chan_forgetfact;
int chan_offset;
void *telnetcmd_qid;
poll_telnetcmdq_func_t poll_telnetcmdq;
} rfsimulator_state_t;
......@@ -150,11 +170,11 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
static bool init_done=false;
if (!init_done) {
uint64_t rand;
FILE *h=fopen("/dev/random","r");
if ( 1 != fread(&rand,sizeof(rand),1,h) )
LOG_W(HW, "Simulator can't read /dev/random\n");
fclose(h);
uint64_t rand;
FILE *h=fopen("/dev/random","r");
if ( 1 != fread(&rand,sizeof(rand),1,h) )
LOG_W(HW, "Simulator can't read /dev/random\n");
fclose(h);
randominit(rand);
tableNor(rand);
init_done=true;
......@@ -164,9 +184,10 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
bridge->channelmod,
bridge->sample_rate,
bridge->tx_bw,
0.0, // forgetting_factor
0, // maybe used for TA
0); // path_loss in dB
bridge->chan_forgetfact, // forgetting_factor
bridge->chan_offset, // maybe used for TA
bridge->chan_pathloss); // path_loss in dB
set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID);
random_channel(ptr->channel_model,false);
}
}
......@@ -293,6 +314,41 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
rfsimulator->typeStamp = UE_MAGICDL_FDD;
}
static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) {
char *modelname=NULL;
int s = sscanf(buff,"%ms\n",&modelname);
if (s == 1) {
int channelmod=modelid_fromname(modelname);
if (channelmod<0)
prnt("ERROR: model %s unknown\n",modelname);
else {
rfsimulator_state_t *t = (rfsimulator_state_t *)arg;
for (int i=0; i<FD_SETSIZE; i++) {
buffer_t *b=&t->buf[i];
if (b->conn_sock >= 0 ) {
channel_desc_t *newmodel=new_channel_desc_scm(t->tx_num_channels,t->rx_num_channels,
channelmod,
t->sample_rate,
t->tx_bw,
t->chan_forgetfact, // forgetting_factor
t->chan_offset, // maybe used for TA
t->chan_pathloss); // path_loss in dB
set_channeldesc_owner(newmodel, RFSIMU_MODULEID);
random_channel(newmodel,false);
channel_desc_t *oldmodel=b->channel_model;
b->channel_model=newmodel;
free_channel_desc_scm(oldmodel);
prnt("New model %s applied to channel connected to sock %d\n",modelname,i);
}
}
}
} else {
prnt("ERROR: no model specified\n");
}
free(modelname);
return CMDSTATUS_FOUND;
}
int server_start(openair0_device *device) {
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
t->typeStamp=ENB_MAGICDL_FDD;
......@@ -647,7 +703,8 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
// it seems legacy behavior is: never in UL, each frame in DL
if (reGenerateChannel)
random_channel(ptr->channel_model,0);
if (t->poll_telnetcmdq)
t->poll_telnetcmdq(t->telnetcmd_qid,t);
for (int a=0; a<nbAnt; a++) {
if ( ptr->channel_model != NULL ) // apply a channel model
rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a],
......@@ -742,5 +799,18 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
rfsimulator->tx_bw=openair0_cfg->tx_bw;
//randominit(0);
set_taus_seed(0);
/* 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);
if (addcmd != NULL) {
rfsimulator->poll_telnetcmdq = (poll_telnetcmdq_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_POLLCMDQ_FNAME);
addcmd("rfsimu",rfsimu_vardef,rfsimu_cmdarray);
for(int i=0; rfsimu_cmdarray[i].cmdfunc != NULL; i++) {
if ( rfsimu_cmdarray[i].qptr != NULL) {
rfsimulator->telnetcmd_qid = rfsimu_cmdarray[i].qptr;
break;
}
}
}
return 0;
}
......@@ -727,7 +727,7 @@ int main ( int argc, char **argv )
// end of CI modifications
//getchar();
if(IS_SOFTMODEM_DOFORMS)
load_softscope("enb");
load_softscope("enb",NULL);
itti_wait_tasks_end();
oai_exit=1;
LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit);
......
......@@ -759,7 +759,7 @@ int main( int argc, char **argv ) {
}
if(IS_SOFTMODEM_DOFORMS)
load_softscope("ue");
load_softscope("ue",NULL);
config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment