Commit 7995f413 authored by frtabu's avatar frtabu

add config options for rfsimulator, set a common lib for l1sim and...

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)
parent 4d073a75
...@@ -172,7 +172,7 @@ int config_get_processedint(paramdef_t *cfgoption) { ...@@ -172,7 +172,7 @@ int config_get_processedint(paramdef_t *cfgoption) {
return ret; return ret;
} }
void config_printhelp(paramdef_t *params,int numparams, char *prefix) { void config_printhelp(paramdef_t *params,int numparams, char *prefix) {
printf("\n-----Help for section %-26s: %03i entries------\n",(prefix==NULL)?"(root section)":prefix ,numparams); printf("\n-----Help for section %-26s: %03i entries------\n",(prefix==NULL)?"(root section)":prefix,numparams);
for (int i=0 ; i<numparams ; i++) { for (int i=0 ; i<numparams ; i++) {
printf(" %s%s: %s", printf(" %s%s: %s",
...@@ -204,6 +204,16 @@ int config_execcheck(paramdef_t *params,int numparams, char *prefix) { ...@@ -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;
...@@ -438,7 +448,7 @@ int config_setdefault_intlist(paramdef_t *cfgoptions, char *prefix) { ...@@ -438,7 +448,7 @@ int config_setdefault_intlist(paramdef_t *cfgoptions, char *prefix) {
status=1; status=1;
for (int j=0; j<cfgoptions->numelt ; j++) { for (int j=0; j<cfgoptions->numelt ; j++) {
printf_params("[CONFIG] %s[%i] set to default value %i\n",cfgoptions->optname ,j,(int)cfgoptions->iptr[j]); printf_params("[CONFIG] %s[%i] set to default value %i\n",cfgoptions->optname,j,(int)cfgoptions->iptr[j]);
} }
} }
...@@ -452,7 +462,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) { ...@@ -452,7 +462,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) {
if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) { if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) {
*(cfgoptions->dblptr)=cfgoptions->defdblval; *(cfgoptions->dblptr)=cfgoptions->defdblval;
status=1; status=1;
printf_params("[CONFIG] %s set to default value %lf\n",cfgoptions->optname , *(cfgoptions->dblptr)); printf_params("[CONFIG] %s set to default value %lf\n",cfgoptions->optname, *(cfgoptions->dblptr));
} }
return status; return status;
...@@ -460,7 +470,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) { ...@@ -460,7 +470,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) {
int config_assign_ipv4addr(paramdef_t *cfgoptions, char *ipv4addr) { int config_assign_ipv4addr(paramdef_t *cfgoptions, char *ipv4addr) {
config_check_valptr(cfgoptions,(char **)&(cfgoptions->uptr), sizeof(int)); config_check_valptr(cfgoptions,(char **)&(cfgoptions->uptr), sizeof(int));
int rst=inet_pton(AF_INET, ipv4addr ,cfgoptions->uptr ); int rst=inet_pton(AF_INET, ipv4addr,cfgoptions->uptr );
if (rst == 1 && *(cfgoptions->uptr) > 0) { if (rst == 1 && *(cfgoptions->uptr) > 0) {
printf_params("[CONFIG] %s: %s\n",cfgoptions->optname, ipv4addr); printf_params("[CONFIG] %s: %s\n",cfgoptions->optname, ipv4addr);
......
...@@ -39,6 +39,7 @@ extern "C" ...@@ -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" ...@@ -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) ;
......
...@@ -123,7 +123,7 @@ void client_printf(const char *message, ...) { ...@@ -123,7 +123,7 @@ void client_printf(const char *message, ...) {
if (telnetparams.new_socket > 0) { if (telnetparams.new_socket > 0) {
vsnprintf(telnetparams.msgbuff,sizeof(telnetparams.msgbuff)-1,message, va_args); vsnprintf(telnetparams.msgbuff,sizeof(telnetparams.msgbuff)-1,message, va_args);
send(telnetparams.new_socket,telnetparams.msgbuff , strlen(telnetparams.msgbuff), MSG_NOSIGNAL); send(telnetparams.new_socket,telnetparams.msgbuff, strlen(telnetparams.msgbuff), MSG_NOSIGNAL);
} else { } else {
vprintf(message, va_args); vprintf(message, va_args);
} }
...@@ -475,7 +475,7 @@ int process_command(char *buf) { ...@@ -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);
...@@ -543,7 +543,7 @@ void run_telnetsrv(void) { ...@@ -543,7 +543,7 @@ void run_telnetsrv(void) {
char buf[TELNET_MAX_MSGLENGTH]; char buf[TELNET_MAX_MSGLENGTH];
struct sockaddr cli_addr; struct sockaddr cli_addr;
unsigned int cli_len = sizeof(cli_addr); unsigned int cli_len = sizeof(cli_addr);
int readc , filled; int readc, filled;
int status; int status;
int optval = 1; int optval = 1;
pthread_setname_np(pthread_self(), "telnet"); pthread_setname_np(pthread_self(), "telnet");
...@@ -604,7 +604,7 @@ void run_telnetsrv(void) { ...@@ -604,7 +604,7 @@ void run_telnetsrv(void) {
} }
if (telnetparams.telnetdbg > 0) if (telnetparams.telnetdbg > 0)
printf("[TELNETSRV] Command received: readc %i filled %i \"%s\"\n", readc, filled ,buf); printf("[TELNETSRV] Command received: readc %i filled %i \"%s\"\n", readc, filled,buf);
if (buf[0] == '!') { if (buf[0] == '!') {
if (buf[1] == '!') { if (buf[1] == '!') {
......
...@@ -122,7 +122,6 @@ void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxt ...@@ -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 ...@@ -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 ...@@ -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, ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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
...@@ -918,10 +919,11 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { ...@@ -918,10 +919,11 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
} }
if ((NFAPI_MODE!=NFAPI_MONOLITHIC) && do_oai && !dont_send) { if ((NFAPI_MODE!=NFAPI_MONOLITHIC) && do_oai && !dont_send) {
if(Sched_INFO->TX_req->tx_request_body.number_of_pdus > 0){ if(Sched_INFO->TX_req->tx_request_body.number_of_pdus > 0) {
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;
...@@ -935,7 +937,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { ...@@ -935,7 +937,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
eNB->pdcch_vars[NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf)&1].num_pdcch_symbols=0; eNB->pdcch_vars[NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf)&1].num_pdcch_symbols=0;
} }
if (NFAPI_MODE!=NFAPI_MODE_VNF) if (NFAPI_MODE!=NFAPI_MODE_VNF)
for (i=0; i<number_hi_dci0_pdu; i++) { for (i=0; i<number_hi_dci0_pdu; i++) {
hi_dci0_req_pdu = &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[i]; hi_dci0_req_pdu = &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[i];
LOG_D(PHY,"NFAPI: hi_dci0_pdu %d : type %d\n",i,hi_dci0_req_pdu->pdu_type); LOG_D(PHY,"NFAPI: hi_dci0_pdu %d : type %d\n",i,hi_dci0_req_pdu->pdu_type);
......
...@@ -30,11 +30,29 @@ ...@@ -30,11 +30,29 @@
#include "sim.h" #include "sim.h"
#include "scm_corrmat.h" #include "scm_corrmat.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "common/utils/load_module_shlib.h"
#include "common/utils/telnetsrv/telnetsrv.h"
//#define DEBUG_CH //#define DEBUG_CH
#include "assertions.h" #include "assertions.h"
extern void print_shorts(char *s,__m128i *x); extern void print_shorts(char *s,__m128i *x);
static mapping channelmod_names[] = {
CHANNELMOD_MAP_INIT
};
static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt);
static telnetshell_cmddef_t channelmod_cmdarray[] = {
{"show","",channelmod_show_cmd},
{"","",NULL},
};
static telnetshell_vardef_t channelmod_vardef[] = {
{"",0,NULL}
};
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,
...@@ -43,7 +61,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, ...@@ -43,7 +61,7 @@ void fill_channel_desc(channel_desc_t *chan_desc,
uint8_t channel_length, uint8_t channel_length,
double *amps, double *amps,
double *delays, double *delays,
struct complex** R_sqrt, struct complex **R_sqrt,
double Td, double Td,
double sampling_rate, double sampling_rate,
double channel_bandwidth, double channel_bandwidth,
...@@ -53,30 +71,27 @@ void fill_channel_desc(channel_desc_t *chan_desc, ...@@ -53,30 +71,27 @@ void fill_channel_desc(channel_desc_t *chan_desc,
double max_Doppler, double max_Doppler,
int32_t channel_offset, int32_t channel_offset,
double path_loss_dB, double path_loss_dB,
uint8_t random_aoa) uint8_t random_aoa) {
{
uint16_t i,j; uint16_t i,j;
double delta_tau; double delta_tau;
LOG_I(OCM,"[CHANNEL] Getting new channel descriptor, nb_tx %d, nb_rx %d, nb_taps %d, channel_length %d\n", LOG_I(OCM,"[CHANNEL] Getting new channel descriptor, nb_tx %d, nb_rx %d, nb_taps %d, channel_length %d\n",
nb_tx,nb_rx,nb_taps,channel_length); nb_tx,nb_rx,nb_taps,channel_length);
chan_desc->nb_tx = nb_tx; chan_desc->nb_tx = nb_tx;
chan_desc->nb_rx = nb_rx; chan_desc->nb_rx = nb_rx;
chan_desc->nb_taps = nb_taps; chan_desc->nb_taps = nb_taps;
chan_desc->channel_length = channel_length; chan_desc->channel_length = channel_length;
chan_desc->amps = amps; chan_desc->amps = amps;
LOG_D(OCM,"[CHANNEL] Doing delays ...\n"); LOG_D(OCM,"[CHANNEL] Doing delays ...\n");
if (delays==NULL) { if (delays==NULL) {
chan_desc->delays = (double*) malloc(nb_taps*sizeof(double)); chan_desc->delays = (double *) malloc(nb_taps*sizeof(double));
delta_tau = Td/nb_taps; delta_tau = Td/nb_taps;
for (i=0; i<nb_taps; i++) for (i=0; i<nb_taps; i++)
chan_desc->delays[i] = ((double)i)*delta_tau; chan_desc->delays[i] = ((double)i)*delta_tau;
} } else
else
chan_desc->delays = delays; chan_desc->delays = delays;
chan_desc->Td = Td; chan_desc->Td = Td;
chan_desc->sampling_rate = sampling_rate; chan_desc->sampling_rate = sampling_rate;
chan_desc->channel_bandwidth = channel_bandwidth; chan_desc->channel_bandwidth = channel_bandwidth;
...@@ -89,37 +104,40 @@ void fill_channel_desc(channel_desc_t *chan_desc, ...@@ -89,37 +104,40 @@ void fill_channel_desc(channel_desc_t *chan_desc,
chan_desc->first_run = 1; chan_desc->first_run = 1;
chan_desc->ip = 0.0; chan_desc->ip = 0.0;
chan_desc->max_Doppler = max_Doppler; chan_desc->max_Doppler = max_Doppler;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(nb_taps*sizeof(struct complex *));
LOG_D(OCM,"[CHANNEL] Filling ch \n"); LOG_D(OCM,"[CHANNEL] Filling ch \n");
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); // allocate for up to 100 RBs, 12 samples per RB chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); // allocate for up to 100 RBs, 12 samples per RB
LOG_D(OCM,"[CHANNEL] Filling a (nb_taps %d)\n",nb_taps); LOG_D(OCM,"[CHANNEL] Filling a (nb_taps %d)\n",nb_taps);
for (i = 0; i<nb_taps; i++) { for (i = 0; i<nb_taps; i++) {
LOG_D(OCM,"tap %d (%p,%zu)\n",i,&chan_desc->a[i],nb_tx*nb_rx * sizeof(struct complex)); LOG_D(OCM,"tap %d (%p,%zu)\n",i,&chan_desc->a[i],nb_tx*nb_rx * sizeof(struct complex));
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
} }
LOG_D(OCM,"[CHANNEL] Doing R_sqrt ...\n"); LOG_D(OCM,"[CHANNEL] Doing R_sqrt ...\n");
if (R_sqrt == NULL) { if (R_sqrt == NULL) {
chan_desc->R_sqrt = (struct complex**) calloc(nb_taps,sizeof(struct complex*)); chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *));
for (i = 0; i<nb_taps; i++) { 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0; chan_desc->R_sqrt[i][j].y = 0.0;
} }
} }
} } else {
else { chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *));
chan_desc->R_sqrt = (struct complex**) calloc(nb_taps,sizeof(struct complex*));
for (i = 0; i<nb_taps; i++) { 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));
//chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0]; //chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0];
...@@ -135,16 +153,15 @@ void fill_channel_desc(channel_desc_t *chan_desc, ...@@ -135,16 +153,15 @@ void fill_channel_desc(channel_desc_t *chan_desc,
} }
LOG_D(OCM,"[CHANNEL] RF %f\n",chan_desc->ricean_factor); LOG_D(OCM,"[CHANNEL] RF %f\n",chan_desc->ricean_factor);
for (i=0;i<chan_desc->nb_taps;i++)
for (i=0; i<chan_desc->nb_taps; i++)
LOG_D(OCM,"[CHANNEL] tap %d: amp %f, delay %f\n",i,chan_desc->amps[i],chan_desc->delays[i]); LOG_D(OCM,"[CHANNEL] tap %d: amp %f, delay %f\n",i,chan_desc->amps[i],chan_desc->delays[i]);
chan_desc->nb_paths=10; chan_desc->nb_paths=10;
reset_meas(&chan_desc->random_channel); reset_meas(&chan_desc->random_channel);
reset_meas(&chan_desc->interp_time); reset_meas(&chan_desc->interp_time);
reset_meas(&chan_desc->interp_freq); reset_meas(&chan_desc->interp_freq);
reset_meas(&chan_desc->convolution); reset_meas(&chan_desc->convolution);
} }
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_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};
...@@ -162,7 +179,7 @@ double eva_amps_dB[] = {0.0,-1.5,-1.4,-3.6,-0.6,-9.1,-7.0,-12.0,-16.9}; ...@@ -162,7 +179,7 @@ double eva_amps_dB[] = {0.0,-1.5,-1.4,-3.6,-0.6,-9.1,-7.0,-12.0,-16.9};
double etu_delays[] = { 0,.05,.12,.2,.23,.5,1.6,2.3,5.0}; double etu_delays[] = { 0,.05,.12,.2,.23,.5,1.6,2.3,5.0};
double etu_amps_dB[] = {-1.0,-1.0,-1.0,0.0,0.0,0.0,-3.0,-5.0,-7.0}; double etu_amps_dB[] = {-1.0,-1.0,-1.0,0.0,0.0,0.0,-3.0,-5.0,-7.0};
double default_amps_lin[] = {0.3868472 , 0.3094778 , 0.1547389 , 0.0773694 , 0.0386847 , 0.0193424 , 0.0096712 , 0.0038685}; double default_amps_lin[] = {0.3868472, 0.3094778, 0.1547389, 0.0773694, 0.0386847, 0.0193424, 0.0096712, 0.0038685};
double default_amp_lin[] = {1}; double default_amp_lin[] = {1};
double ts_shift_delays[] = {0, 1/7.68}; double ts_shift_delays[] = {0, 1/7.68};
...@@ -172,7 +189,8 @@ double ts_shift_amps[] = {0, 1}; ...@@ -172,7 +189,8 @@ double ts_shift_amps[] = {0, 1};
struct complex R_sqrt_22_corr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, struct complex R_sqrt_22_corr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0},
{0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0},
{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0},
{0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}}; {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}
};
struct complex *R_sqrt_22_corr[1] = {R_sqrt_22_corr_tap}; struct complex *R_sqrt_22_corr[1] = {R_sqrt_22_corr_tap};
//correlation matrix for a fully correlated 2x1 channel (h1==h2) //correlation matrix for a fully correlated 2x1 channel (h1==h2)
...@@ -183,7 +201,8 @@ struct complex *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap}; ...@@ -183,7 +201,8 @@ struct complex *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap};
struct complex R_sqrt_22_anticorr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, struct complex R_sqrt_22_anticorr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0},
{0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {-0.70711,0},
{-0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0},
{0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0}}; {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0}
};
struct complex *R_sqrt_22_anticorr[1] = {R_sqrt_22_anticorr_tap}; struct complex *R_sqrt_22_anticorr[1] = {R_sqrt_22_anticorr_tap};
//correlation matrix for a fully anti-correlated 2x1 channel (h1==-h2) //correlation matrix for a fully anti-correlated 2x1 channel (h1==-h2)
...@@ -197,7 +216,8 @@ struct complex **R_sqrt_ptr2; ...@@ -197,7 +216,8 @@ struct complex **R_sqrt_ptr2;
struct complex R_sqrt_22_orthogonal_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, struct complex R_sqrt_22_orthogonal_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0},
{0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0},
{0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0},
{0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.70711,0.0}}; {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.70711,0.0}
};
struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap}; struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap};
// full correlation matrix for TM4 to make orthogonal effective channel // full correlation matrix for TM4 to make orthogonal effective channel
...@@ -208,7 +228,8 @@ struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap}; ...@@ -208,7 +228,8 @@ struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap};
struct complex R_sqrt_22_orth_eff_ch_TM4_prec_real_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, struct complex R_sqrt_22_orth_eff_ch_TM4_prec_real_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0},
{0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {-0.70711,0.0},
{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0},
{0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}}; {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}
};
struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_real_tap}; struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_real_tap};
...@@ -217,26 +238,30 @@ struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff ...@@ -217,26 +238,30 @@ struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff
struct complex R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap[16] = {{0.70711,0.0}, {0.0,0.0}, {0.0, -0.70711}, {0.0,0.0}, struct complex R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap[16] = {{0.70711,0.0}, {0.0,0.0}, {0.0, -0.70711}, {0.0,0.0},
{0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0,0.70711}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0,0.70711},
{0.0,-0.70711}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.0,-0.70711}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0},
{0.0, 0.0}, {0.0,0.70711}, {0.0, 0.0}, {-0.70711,0.0}}; {0.0, 0.0}, {0.0,0.70711}, {0.0, 0.0}, {-0.70711,0.0}
};
struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_imag[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap}; struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_imag[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap};
//Correlation matrix for EPA channel //Correlation matrix for EPA channel
struct complex R_sqrt_22_EPA_low_tap[16] = {{1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, struct complex R_sqrt_22_EPA_low_tap[16] = {{1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0},
{0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0},
{0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0},
{0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}}; {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}
};
struct complex *R_sqrt_22_EPA_low[1] = {R_sqrt_22_EPA_low_tap}; struct complex *R_sqrt_22_EPA_low[1] = {R_sqrt_22_EPA_low_tap};
struct complex R_sqrt_22_EPA_high_tap[16] = {{0.7179,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0}, struct complex R_sqrt_22_EPA_high_tap[16] = {{0.7179,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0},
{0.4500,0.0}, {0.7179,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.7179,0.0}, {0.2821,0.0}, {0.4500,0.0},
{0.4500,0.0}, {0.2821,0.0}, {0.7179,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.7179,0.0}, {0.4500,0.0},
{0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.7179,0.0}}; {0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.7179,0.0}
};
struct complex *R_sqrt_22_EPA_high[1] = {R_sqrt_22_EPA_high_tap}; struct complex *R_sqrt_22_EPA_high[1] = {R_sqrt_22_EPA_high_tap};
struct complex R_sqrt_22_EPA_medium_tap[16] = {{0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0}, struct complex R_sqrt_22_EPA_medium_tap[16] = {{0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0},
{0.5249,0.0}, {0.8375,0.0}, {0.0806,0.0}, {0.1286,0.0}, {0.5249,0.0}, {0.8375,0.0}, {0.0806,0.0}, {0.1286,0.0},
{0.1286,0.0}, {0.0806,0.0}, {0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0}, {0.8375,0.0}, {0.5249,0.0},
{0.0806,0.0}, {0.1286,0.0}, {0.5249,0.0}, {0.8375,0.0}}; {0.0806,0.0}, {0.1286,0.0}, {0.5249,0.0}, {0.8375,0.0}
};
struct complex *R_sqrt_22_EPA_medium[1] = {R_sqrt_22_EPA_medium_tap}; struct complex *R_sqrt_22_EPA_medium[1] = {R_sqrt_22_EPA_medium_tap};
...@@ -250,15 +275,12 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -250,15 +275,12 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
double channel_bandwidth, double channel_bandwidth,
double forgetting_factor, double forgetting_factor,
int32_t channel_offset, int32_t channel_offset,
double path_loss_dB) 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 *)malloc(sizeof(channel_desc_t));
uint16_t i,j; uint16_t i,j;
double sum_amps; double sum_amps;
double aoa,ricean_factor,Td,maxDoppler; double aoa,ricean_factor,Td,maxDoppler;
int channel_length,nb_taps; int channel_length,nb_taps;
chan_desc->nb_tx = nb_tx; chan_desc->nb_tx = nb_tx;
chan_desc->nb_rx = nb_rx; chan_desc->nb_rx = nb_rx;
chan_desc->sampling_rate = sampling_rate; chan_desc->sampling_rate = sampling_rate;
...@@ -268,7 +290,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -268,7 +290,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->path_loss_dB = path_loss_dB; chan_desc->path_loss_dB = path_loss_dB;
chan_desc->first_run = 1; chan_desc->first_run = 1;
chan_desc->ip = 0.0; chan_desc->ip = 0.0;
LOG_I(OCM,"Channel Model (inside of new_channel_desc_scm)=%d\n\n", channel_model); LOG_I(OCM,"Channel Model (inside of new_channel_desc_scm)=%d\n\n", channel_model);
switch (channel_model) { switch (channel_model) {
...@@ -276,186 +297,224 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -276,186 +297,224 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
LOG_W(OCM,"channel model not yet supported\n"); LOG_W(OCM,"channel model not yet supported\n");
free(chan_desc); free(chan_desc);
return(NULL); return(NULL);
case SCM_B: case SCM_B:
LOG_W(OCM,"channel model not yet supported\n"); LOG_W(OCM,"channel model not yet supported\n");
free(chan_desc); free(chan_desc);
return(NULL); return(NULL);
case SCM_C: case SCM_C:
chan_desc->nb_taps = 18; chan_desc->nb_taps = 18;
chan_desc->Td = 4.625; chan_desc->Td = 4.625;
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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = scm_c_delays; chan_desc->delays = scm_c_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); 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->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} } else if (nb_tx==2 && nb_rx==1) {
else if (nb_tx==2 && nb_rx==1) {
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R21_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0];
} } else if (nb_tx==1 && nb_rx==2) {
else if (nb_tx==1 && nb_rx==2) {
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R12_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0];
} } else {
else {
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0; chan_desc->R_sqrt[i][j].y = 0.0;
} }
LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx);
} }
} }
break; break;
case SCM_D: case SCM_D:
LOG_W(OCM,"This is not the real SCM-D model! It is just SCM-C with an additional Rice factor!\n"); LOG_W(OCM,"This is not the real SCM-D model! It is just SCM-C with an additional Rice factor!\n");
chan_desc->nb_taps = 18; chan_desc->nb_taps = 18;
chan_desc->Td = 4.625; chan_desc->Td = 4.625;
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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = scm_c_delays; chan_desc->delays = scm_c_delays;
chan_desc->ricean_factor = 0.1; chan_desc->ricean_factor = 0.1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); 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->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} } else if (nb_tx==2 && nb_rx==1) {
else if (nb_tx==2 && nb_rx==1) {
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R21_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0];
} } else if (nb_tx==1 && nb_rx==2) {
else if (nb_tx==1 && nb_rx==2) {
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R12_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0];
} } else {
else {
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0; chan_desc->R_sqrt[i][j].y = 0.0;
} }
LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx);
} }
} }
break; break;
case EPA: case EPA:
chan_desc->nb_taps = 7; chan_desc->nb_taps = 7;
chan_desc->Td = .410; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = epa_delays; chan_desc->delays = epa_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} } else {
else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0; chan_desc->R_sqrt[i][j].y = 0.0;
} }
LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
} }
} }
break; break;
case EPA_low: case EPA_low:
chan_desc->nb_taps = 7; chan_desc->nb_taps = 7;
chan_desc->Td = .410; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = epa_delays; chan_desc->delays = epa_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0]; chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0];
} } else {
else {
printf("Correlation matrices are implemented for 2 x 2 only"); printf("Correlation matrices are implemented for 2 x 2 only");
} }
/*else { /*else {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { for (i = 0; i<6; i++) {
...@@ -468,39 +527,48 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -468,39 +527,48 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
} }
}*/ }*/
break; break;
case EPA_high: case EPA_high:
chan_desc->nb_taps = 7; chan_desc->nb_taps = 7;
chan_desc->Td = .410; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = epa_delays; chan_desc->delays = epa_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0]; chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0];
} } else {
else {
printf("Correlation matrices are implemented for 2 x 2 only"); printf("Correlation matrices are implemented for 2 x 2 only");
} }
/*else { /*else {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { for (i = 0; i<6; i++) {
...@@ -513,38 +581,48 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -513,38 +581,48 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
} }
}*/ }*/
break; break;
case EPA_medium: case EPA_medium:
chan_desc->nb_taps = 7; chan_desc->nb_taps = 7;
chan_desc->Td = .410; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = epa_delays; chan_desc->delays = epa_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0]; chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0];
} else { } else {
printf("Correlation matrices are implemented for 2 x 2 only"); printf("Correlation matrices are implemented for 2 x 2 only");
} }
/*else { /*else {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { for (i = 0; i<6; i++) {
...@@ -557,135 +635,169 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -557,135 +635,169 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
} }
}*/ }*/
break; break;
case EVA: case EVA:
chan_desc->nb_taps = 9; chan_desc->nb_taps = 9;
chan_desc->Td = 2.51; chan_desc->Td = 2.51;
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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = eva_delays; chan_desc->delays = eva_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} } else {
else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0; chan_desc->R_sqrt[i][j].y = 0.0;
} }
LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
} }
} }
break; break;
case ETU: case ETU:
chan_desc->nb_taps = 9; chan_desc->nb_taps = 9;
chan_desc->Td = 5.0; chan_desc->Td = 5.0;
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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = etu_delays; chan_desc->delays = etu_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} } else {
else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0; chan_desc->R_sqrt[i][j].y = 0.0;
} }
LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
} }
} }
break; break;
case MBSFN: case MBSFN:
chan_desc->nb_taps = 18; chan_desc->nb_taps = 18;
chan_desc->Td = 28.58; chan_desc->Td = 28.58;
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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = mbsfn_delays; chan_desc->delays = mbsfn_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); 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->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex*));
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0; chan_desc->R_sqrt[i][j].y = 0.0;
} }
LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
} }
break; break;
case Rayleigh8:
case Rayleigh8:
nb_taps = 8; nb_taps = 8;
Td = 0.8; Td = 0.8;
channel_length = (int)11+2*sampling_rate*Td; channel_length = (int)11+2*sampling_rate*Td;
ricean_factor = 1; ricean_factor = 1;
aoa = .03; aoa = .03;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc, fill_channel_desc(chan_desc,
nb_tx, nb_tx,
nb_rx, nb_rx,
...@@ -713,7 +825,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -713,7 +825,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 0.1; ricean_factor = 0.1;
aoa = 0.7854; aoa = 0.7854;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -740,7 +851,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -740,7 +851,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 1; ricean_factor = 1;
aoa = .03; aoa = .03;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -767,7 +877,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -767,7 +877,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 1; ricean_factor = 1;
aoa = .03; aoa = .03;
maxDoppler = 800; maxDoppler = 800;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -797,11 +906,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -797,11 +906,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==1)) { if ((nb_tx==2) && (nb_rx==1)) {
R_sqrt_ptr2 = R_sqrt_21_corr; R_sqrt_ptr2 = R_sqrt_21_corr;
} } else if ((nb_tx==2) && (nb_rx==2)) {
else if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_corr; R_sqrt_ptr2 = R_sqrt_22_corr;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -833,11 +940,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -833,11 +940,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==1)) { //check this if ((nb_tx==2) && (nb_rx==1)) { //check this
R_sqrt_ptr2 = R_sqrt_21_anticorr; R_sqrt_ptr2 = R_sqrt_21_anticorr;
} } else if ((nb_tx==2) && (nb_rx==2)) {
else if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_anticorr; R_sqrt_ptr2 = R_sqrt_22_anticorr;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -866,7 +971,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -866,7 +971,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 0.1; ricean_factor = 0.1;
aoa = 0.7854; aoa = 0.7854;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -893,7 +997,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -893,7 +997,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 0.0; ricean_factor = 0.0;
aoa = 0.0; aoa = 0.0;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -912,7 +1015,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -912,7 +1015,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
path_loss_dB, path_loss_dB,
0); 0);
printf("AWGN: ricean_factor %f\n",chan_desc->ricean_factor); printf("AWGN: ricean_factor %f\n",chan_desc->ricean_factor);
break; break;
case TS_SHIFT: case TS_SHIFT:
...@@ -922,7 +1024,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -922,7 +1024,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 0.0; ricean_factor = 0.0;
aoa = 0.0; aoa = 0.0;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -941,7 +1042,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -941,7 +1042,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
path_loss_dB, path_loss_dB,
0); 0);
printf("TS_SHIFT: ricean_factor %f\n",chan_desc->ricean_factor); printf("TS_SHIFT: ricean_factor %f\n",chan_desc->ricean_factor);
break; break;
case Rice1_corr: case Rice1_corr:
...@@ -954,11 +1054,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -954,11 +1054,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==1)) { if ((nb_tx==2) && (nb_rx==1)) {
R_sqrt_ptr2 = R_sqrt_21_corr; R_sqrt_ptr2 = R_sqrt_21_corr;
} } else if ((nb_tx==2) && (nb_rx==2)) {
else if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_corr; R_sqrt_ptr2 = R_sqrt_22_corr;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -990,11 +1088,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -990,11 +1088,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==1)) { if ((nb_tx==2) && (nb_rx==1)) {
R_sqrt_ptr2 = R_sqrt_21_anticorr; R_sqrt_ptr2 = R_sqrt_21_anticorr;
} } else if ((nb_tx==2) && (nb_rx==2)) {
else if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_anticorr; R_sqrt_ptr2 = R_sqrt_22_anticorr;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -1024,11 +1120,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1024,11 +1120,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
aoa = 0.03; aoa = 0.03;
maxDoppler = 0; maxDoppler = 0;
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orthogonal; R_sqrt_ptr2 = R_sqrt_22_orthogonal;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -1058,11 +1152,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1058,11 +1152,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
aoa = 0.03; aoa = 0.03;
maxDoppler = 0; maxDoppler = 0;
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real; R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -1092,11 +1184,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1092,11 +1184,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
aoa = 0.03; aoa = 0.03;
maxDoppler = 0; maxDoppler = 0;
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag; R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -1119,22 +1209,18 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1119,22 +1209,18 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
break; break;
case Rayleigh8_orth_eff_ch_TM4_prec_real: case Rayleigh8_orth_eff_ch_TM4_prec_real:
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real; R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real;
//R_sqrt_ptr2 = NULL; //R_sqrt_ptr2 = NULL;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
nb_taps = 8; nb_taps = 8;
Td = 0.8; Td = 0.8;
channel_length = (int)11+2*sampling_rate*Td; channel_length = (int)11+2*sampling_rate*Td;
ricean_factor = 1; ricean_factor = 1;
aoa = .03; aoa = .03;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc, fill_channel_desc(chan_desc,
nb_tx, nb_tx,
nb_rx, nb_rx,
...@@ -1153,7 +1239,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1153,7 +1239,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
channel_offset, channel_offset,
path_loss_dB, path_loss_dB,
0); 0);
break; break;
case Rayleigh8_orth_eff_ch_TM4_prec_imag: case Rayleigh8_orth_eff_ch_TM4_prec_imag:
...@@ -1166,8 +1251,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1166,8 +1251,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag; R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc, fill_channel_desc(chan_desc,
...@@ -1195,35 +1279,33 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1195,35 +1279,33 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
free(chan_desc); free(chan_desc);
return(NULL); return(NULL);
} }
LOG_D(OCM,"[CHANNEL] RF %f\n",chan_desc->ricean_factor); LOG_D(OCM,"[CHANNEL] RF %f\n",chan_desc->ricean_factor);
for (i=0;i<chan_desc->nb_taps;i++)
for (i=0; i<chan_desc->nb_taps; i++)
LOG_D(OCM,"[CHANNEL] tap %d: amp %f, delay %f\n",i,chan_desc->amps[i],chan_desc->delays[i]); LOG_D(OCM,"[CHANNEL] tap %d: amp %f, delay %f\n",i,chan_desc->amps[i],chan_desc->delays[i]);
chan_desc->nb_paths = 10; chan_desc->nb_paths = 10;
return(chan_desc); return(chan_desc);
} }
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...
free(ch); free(ch);
} }
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;
struct complex anew[NB_ANTENNAS_TX*NB_ANTENNAS_RX],acorr[NB_ANTENNAS_TX*NB_ANTENNAS_RX]; struct complex anew[NB_ANTENNAS_TX*NB_ANTENNAS_RX],acorr[NB_ANTENNAS_TX*NB_ANTENNAS_RX];
struct complex phase, alpha, beta; struct complex phase, alpha, beta;
AssertFatal(desc->nb_tx<=NB_ANTENNAS_TX && desc->nb_rx <= NB_ANTENNAS_RX, AssertFatal(desc->nb_tx<=NB_ANTENNAS_TX && desc->nb_rx <= NB_ANTENNAS_RX,
"random_channel.c: Error: temporary buffer for channel not big enough (%d,%d)\n",desc->nb_tx,desc->nb_rx); "random_channel.c: Error: temporary buffer for channel not big enough (%d,%d)\n",desc->nb_tx,desc->nb_rx);
start_meas(&desc->random_channel); start_meas(&desc->random_channel);
for (i=0;i<(int)desc->nb_taps;i++) {
for (aarx=0;aarx<desc->nb_rx;aarx++) {
for (aatx=0;aatx<desc->nb_tx;aatx++) {
for (i=0; i<(int)desc->nb_taps; i++) {
for (aarx=0; aarx<desc->nb_rx; aarx++) {
for (aatx=0; aatx<desc->nb_tx; aatx++) {
anew[aarx+(aatx*desc->nb_rx)].x = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); anew[aarx+(aatx*desc->nb_rx)].x = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0);
anew[aarx+(aatx*desc->nb_rx)].y = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); anew[aarx+(aatx*desc->nb_rx)].y = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0);
...@@ -1237,10 +1319,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1237,10 +1319,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
// that we can safely assume plane wave propagation. // that we can safely assume plane wave propagation.
phase.x = cos(M_PI*((aarx-aatx)*sin(desc->aoa))); phase.x = cos(M_PI*((aarx-aatx)*sin(desc->aoa)));
phase.y = sin(M_PI*((aarx-aatx)*sin(desc->aoa))); phase.y = sin(M_PI*((aarx-aatx)*sin(desc->aoa)));
anew[aarx+(aatx*desc->nb_rx)].x += phase.x * sqrt(1.0-desc->ricean_factor); anew[aarx+(aatx*desc->nb_rx)].x += phase.x * sqrt(1.0-desc->ricean_factor);
anew[aarx+(aatx*desc->nb_rx)].y += phase.y * sqrt(1.0-desc->ricean_factor); anew[aarx+(aatx*desc->nb_rx)].y += phase.y * sqrt(1.0-desc->ricean_factor);
} }
#ifdef DEBUG_CH #ifdef DEBUG_CH
printf("(%d,%d,%d) %f->(%f,%f) (%f,%f) phase (%f,%f)\n",aarx,aatx,i,desc->amps[i],anew[aarx+(aatx*desc->nb_rx)].x,anew[aarx+(aatx*desc->nb_rx)].y,desc->aoa,desc->ricean_factor,phase.x,phase.y); printf("(%d,%d,%d) %f->(%f,%f) (%f,%f) phase (%f,%f)\n",aarx,aatx,i,desc->amps[i],anew[aarx+(aatx*desc->nb_rx)].x,anew[aarx+(aatx*desc->nb_rx)].y,desc->aoa,desc->ricean_factor,phase.x,phase.y);
#endif #endif
...@@ -1263,10 +1345,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1263,10 +1345,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
alpha.y = 0.0; alpha.y = 0.0;
beta.x = 0.0; beta.x = 0.0;
beta.y = 0.0; beta.y = 0.0;
cblas_zgemv(CblasRowMajor, CblasNoTrans, desc->nb_tx*desc->nb_rx, desc->nb_tx*desc->nb_rx, cblas_zgemv(CblasRowMajor, CblasNoTrans, desc->nb_tx*desc->nb_rx, desc->nb_tx*desc->nb_rx,
(void*) &alpha, (void*) desc->R_sqrt[i/3], desc->nb_rx*desc->nb_tx, (void *) &alpha, (void *) desc->R_sqrt[i/3], desc->nb_rx*desc->nb_tx,
(void*) anew, 1, (void*) &beta, (void*) acorr, 1); (void *) anew, 1, (void *) &beta, (void *) acorr, 1);
/* /*
for (aarx=0;aarx<desc->nb_rx;aarx++) { for (aarx=0;aarx<desc->nb_rx;aarx++) {
...@@ -1278,10 +1359,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1278,10 +1359,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
} }
*/ */
if (desc->first_run==1){ if (desc->first_run==1) {
cblas_zcopy(desc->nb_tx*desc->nb_rx, (void*) acorr, 1, (void*) desc->a[i], 1); cblas_zcopy(desc->nb_tx*desc->nb_rx, (void *) acorr, 1, (void *) desc->a[i], 1);
} } else {
else {
// a = alpha*acorr+beta*a // a = alpha*acorr+beta*a
// a = beta*a // a = beta*a
// a = a+alpha*acorr // a = a+alpha*acorr
...@@ -1289,9 +1369,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1289,9 +1369,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
alpha.y = 0; alpha.y = 0;
beta.x = sqrt(desc->forgetting_factor); beta.x = sqrt(desc->forgetting_factor);
beta.y = 0; beta.y = 0;
cblas_zscal(desc->nb_tx*desc->nb_rx, (void*) &beta, (void*) desc->a[i], 1); cblas_zscal(desc->nb_tx*desc->nb_rx, (void *) &beta, (void *) desc->a[i], 1);
cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void*) &alpha, (void*) acorr, 1, (void*) desc->a[i], 1); cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) &alpha, (void *) acorr, 1, (void *) desc->a[i], 1);
// desc->a[i][aarx+(aatx*desc->nb_rx)].x = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].x) + sqrt(1-desc->forgetting_factor)*anew.x; // desc->a[i][aarx+(aatx*desc->nb_rx)].x = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].x) + sqrt(1-desc->forgetting_factor)*anew.x;
// desc->a[i][aarx+(aatx*desc->nb_rx)].y = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].y) + sqrt(1-desc->forgetting_factor)*anew.y; // desc->a[i][aarx+(aatx*desc->nb_rx)].y = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].y) + sqrt(1-desc->forgetting_factor)*anew.y;
} }
...@@ -1305,8 +1384,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1305,8 +1384,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
} }
} }
*/ */
} //nb_taps } //nb_taps
stop_meas(&desc->random_channel); stop_meas(&desc->random_channel);
//memset((void *)desc->ch[aarx+(aatx*desc->nb_rx)],0,(int)(desc->channel_length)*sizeof(struct complex)); //memset((void *)desc->ch[aarx+(aatx*desc->nb_rx)],0,(int)(desc->channel_length)*sizeof(struct complex));
...@@ -1320,7 +1399,6 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1320,7 +1399,6 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
desc->ch[aarx+(aatx*desc->nb_rx)][0].x = desc->a[0][aarx+(aatx*desc->nb_rx)].x; desc->ch[aarx+(aatx*desc->nb_rx)][0].x = desc->a[0][aarx+(aatx*desc->nb_rx)].x;
desc->ch[aarx+(aatx*desc->nb_rx)][0].y = desc->a[0][aarx+(aatx*desc->nb_rx)].y; desc->ch[aarx+(aatx*desc->nb_rx)][0].y = desc->a[0][aarx+(aatx*desc->nb_rx)].y;
} else { } else {
for (k=0; k<(int)desc->channel_length; k++) { for (k=0; k<(int)desc->channel_length; k++) {
desc->ch[aarx+(aatx*desc->nb_rx)][k].x = 0.0; desc->ch[aarx+(aatx*desc->nb_rx)][k].x = 0.0;
desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0; desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0;
...@@ -1335,7 +1413,6 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1335,7 +1413,6 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
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].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; desc->ch[aarx+(aatx*desc->nb_rx)][k].y += s*desc->a[l][aarx+(aatx*desc->nb_rx)].y;
// printf("l %d : desc->ch.x %f\n",l,desc->a[l][aarx+(aatx*desc->nb_rx)].x); // printf("l %d : desc->ch.x %f\n",l,desc->a[l][aarx+(aatx*desc->nb_rx)].x);
} //nb_taps } //nb_taps
#ifdef DEBUG_CH #ifdef DEBUG_CH
...@@ -1346,6 +1423,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1346,6 +1423,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
} //channel_length } //channel_length
} //aatx } //aatx
} //aarx } //aarx
stop_meas(&desc->interp_time); stop_meas(&desc->interp_time);
} }
...@@ -1355,9 +1433,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1355,9 +1433,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
return (0); return (0);
} }
double N_RB2sampling_rate(uint16_t N_RB) double N_RB2sampling_rate(uint16_t N_RB) {
{
double sampling_rate; double sampling_rate;
switch (N_RB) { switch (N_RB) {
case 6: case 6:
sampling_rate = 1.92; sampling_rate = 1.92;
...@@ -1382,9 +1460,9 @@ double N_RB2sampling_rate(uint16_t N_RB) ...@@ -1382,9 +1460,9 @@ double N_RB2sampling_rate(uint16_t N_RB)
return(sampling_rate); return(sampling_rate);
} }
double N_RB2channel_bandwidth(uint16_t N_RB) double N_RB2channel_bandwidth(uint16_t N_RB) {
{
double channel_bandwidth; double channel_bandwidth;
switch (N_RB) { switch (N_RB) {
case 6: case 6:
channel_bandwidth = 1.25; channel_bandwidth = 1.25;
...@@ -1406,18 +1484,34 @@ double N_RB2channel_bandwidth(uint16_t N_RB) ...@@ -1406,18 +1484,34 @@ double N_RB2channel_bandwidth(uint16_t N_RB)
LOG_E(PHY,"Unknown N_PRB\n"); LOG_E(PHY,"Unknown N_PRB\n");
return(-1); return(-1);
} }
return(channel_bandwidth); return(channel_bandwidth);
} }
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 ));
}
return 0;
}
void init_channelmod(void) {
/* look for telnet server, if it is loaded, add the coding commands to it */
add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME);
if (addcmd != NULL) {
addcmd("channelmod",channelmod_vardef,channelmod_cmdarray);
}
}
#ifdef RANDOM_CHANNEL_MAIN #ifdef RANDOM_CHANNEL_MAIN
#define sampling_rate 5.0 #define sampling_rate 5.0
#define Td 2.0 #define Td 2.0
main(int argc,char **argv) { main(int argc,char **argv) {
double amps[8] = {.8,.2,.1,.04,.02,.01,.005}; double amps[8] = {.8,.2,.1,.04,.02,.01,.005};
struct complex ch[(int)(1+2*sampling_rate*Td)],phase; struct complex ch[(int)(1+2*sampling_rate*Td)],phase;
int i; int i;
randominit(); randominit();
phase.x = 1.0; phase.x = 1.0;
phase.y = 0; phase.y = 0;
......
...@@ -147,7 +147,7 @@ typedef struct { ...@@ -147,7 +147,7 @@ typedef struct {
/// Rice factor??? /// Rice factor???
/// Walls (penetration loss) /// Walls (penetration loss)
/// Nodes in the scenario /// Nodes in the scenario
node_desc_t* nodes; node_desc_t *nodes;
} scenario_desc_t; } scenario_desc_t;
typedef enum { typedef enum {
...@@ -180,6 +180,36 @@ typedef enum { ...@@ -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, ...@@ -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, ...@@ -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 @@ ...@@ -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,25 +45,26 @@ ...@@ -44,25 +45,26 @@
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"\
" 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"
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* configuration parameters for the rfsimulator device */ /* configuration parameters for the rfsimulator device */
/* optname helpstr paramflags XXXptr defXXXval type numelt */ /* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define RFSIMULATOR_PARAMS_DESC {\ #define RFSIMULATOR_PARAMS_DESC {\
{"serveraddr", "<ip address to connect to>\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ {"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 },\ {"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 }\ {"IQfile", "<file path to use when saving IQs>\n", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 }\
}; };
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 { ...@@ -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) { ...@@ -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
...@@ -203,6 +132,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ...@@ -203,6 +132,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
0, // maybe used for TA 0, // maybe used for TA
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) {
...@@ -231,6 +161,7 @@ void socketError(rfsimulator_state_t *bridge, int sock) { ...@@ -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) { ...@@ -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) { ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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) { ...@@ -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;
......
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