From 7995f413ef618080c90e34b5a1aeaa2b1f3d013a Mon Sep 17 00:00:00 2001 From: frtabu <francois.taburet@nokia-bell-labs.com> Date: Wed, 31 Jul 2019 18:31:02 +0200 Subject: [PATCH] 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) --- common/config/config_userapi.c | 18 +- common/config/config_userapi.h | 3 + common/utils/telnetsrv/telnetsrv.c | 8 +- openair1/SCHED/fapi_l1.c | 72 +- openair1/SIMULATION/TOOLS/random_channel.c | 1660 +++++++++++--------- openair1/SIMULATION/TOOLS/sim.h | 85 +- targets/ARCH/rfsimulator/simulator.c | 238 +-- 7 files changed, 1085 insertions(+), 999 deletions(-) diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c index 65e7a6dcc2..9b42dd209f 100644 --- a/common/config/config_userapi.c +++ b/common/config/config_userapi.c @@ -172,7 +172,7 @@ int config_get_processedint(paramdef_t *cfgoption) { return ret; } 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++) { printf(" %s%s: %s", @@ -204,6 +204,16 @@ int config_execcheck(paramdef_t *params,int numparams, char *prefix) { 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 ret= -1; @@ -438,7 +448,7 @@ int config_setdefault_intlist(paramdef_t *cfgoptions, char *prefix) { status=1; 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) { if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) { *(cfgoptions->dblptr)=cfgoptions->defdblval; 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; @@ -460,7 +470,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) { int config_assign_ipv4addr(paramdef_t *cfgoptions, char *ipv4addr) { 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) { printf_params("[CONFIG] %s: %s\n",cfgoptions->optname, ipv4addr); diff --git a/common/config/config_userapi.h b/common/config/config_userapi.h index cc07b1af5f..c00526aa4c 100644 --- a/common/config/config_userapi.h +++ b/common/config/config_userapi.h @@ -39,6 +39,7 @@ extern "C" { #endif +/* utility functions to ease usage of config module structures */ #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_GETP(P) ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgP[P] ) @@ -46,6 +47,8 @@ extern "C" #define CONFIG_SETRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags |= P; } #define CONFIG_CLEARRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags &= (~P); } #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 */ extern configmodule_interface_t *config_get_if(void); extern char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) ; diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index 7f8645be02..44ab07a49b 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -123,7 +123,7 @@ void client_printf(const char *message, ...) { if (telnetparams.new_socket > 0) { 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 { vprintf(message, va_args); } @@ -475,7 +475,7 @@ int process_command(char *buf) { memset(cmdb,0,sizeof(cmdb)); bufbck=strdup(buf); 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) printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n",j,modulename,cmd,cmdb); @@ -543,7 +543,7 @@ void run_telnetsrv(void) { char buf[TELNET_MAX_MSGLENGTH]; struct sockaddr cli_addr; unsigned int cli_len = sizeof(cli_addr); - int readc , filled; + int readc, filled; int status; int optval = 1; pthread_setname_np(pthread_self(), "telnet"); @@ -604,7 +604,7 @@ void run_telnetsrv(void) { } 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[1] == '!') { diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index 5f8b4ec3db..14babd829c 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -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->num_hi++; 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, @@ -186,6 +185,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro #endif harq_pid = dlsch0->harq_ids[proc->frame_tx%2][proc->subframe_tx]; + if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) { LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__); return; @@ -260,9 +260,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro dlsch0->harq_mask = 1; dlsch0_harq = dlsch0->harq_processes[0]; 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); - dlsch0->rnti = 0xFFFF; dlsch0->Kmimo = 1; dlsch0->Mdlharq = 4; @@ -569,8 +567,7 @@ void handle_uci_sr_pdu(PHY_VARS_eNB *eNB, nfapi_ul_config_request_pdu_t *ul_config_pdu, uint16_t frame, uint8_t subframe, - uint8_t srs_active) -{ + uint8_t srs_active) { LTE_eNB_UCI *uci = &eNB->uci_vars[UE_id]; if (NFAPI_MODE==NFAPI_MODE_VNF) return; @@ -803,13 +800,13 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { // clear DCI allocation maps for new subframe if (NFAPI_MODE!=NFAPI_MODE_VNF) - for (i=0; i<NUMBER_OF_UE_MAX; i++) { - if (eNB->ulsch[i]) { - ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; - ulsch_harq->dci_alloc=0; - ulsch_harq->rar_alloc=0; + for (i=0; i<NUMBER_OF_UE_MAX; i++) { + if (eNB->ulsch[i]) { + ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; + ulsch_harq->dci_alloc=0; + ulsch_harq->rar_alloc=0; + } } - } } for (i=0; i<number_dl_pdu; i++) { @@ -820,6 +817,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: 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); + 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); do_oai=1; @@ -832,11 +830,13 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { TX_req->tx_request_body.number_of_pdus); eNB->pbch_configured=1; do_oai=1; + //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)); if (NFAPI_MODE!=NFAPI_MODE_VNF) 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; case NFAPI_DL_CONFIG_MCH_PDU_TYPE: @@ -867,8 +867,8 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { dlsch_pdu_rel8->transport_blocks); if (1) { //sdu != NULL) - if (NFAPI_MODE!=NFAPI_MODE_VNF) - handle_nfapi_dlsch_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu, dlsch_pdu_rel8->transport_blocks-1, sdu); + if (NFAPI_MODE!=NFAPI_MODE_VNF) + handle_nfapi_dlsch_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu, dlsch_pdu_rel8->transport_blocks-1, sdu); } else { dont_send=1; LOG_E(MAC,"%s() NFAPI_DL_CONFIG_DLSCH_PDU_TYPE sdu is NULL DL_CFG:SFN/SF:%d:pdu_index:%d TX_REQ:SFN/SF:%d:pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(DL_req->sfn_sf), pdu_index, @@ -911,6 +911,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: if (NFAPI_MODE!=NFAPI_MODE_VNF) handle_nfapi_mpdcch_pdu(eNB,proc,dl_config_pdu); + eNB->mpdcch_vars[subframe&1].num_dci++; break; #endif @@ -918,10 +919,11 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { } 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; oai_nfapi_tx_req(Sched_INFO->TX_req); } + 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 Sched_INFO->UE_release_req->sfn_sf = frame << 4 | subframe; @@ -935,27 +937,27 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { eNB->pdcch_vars[NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf)&1].num_pdcch_symbols=0; } -if (NFAPI_MODE!=NFAPI_MODE_VNF) - 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]; - LOG_D(PHY,"NFAPI: hi_dci0_pdu %d : type %d\n",i,hi_dci0_req_pdu->pdu_type); - - switch (hi_dci0_req_pdu->pdu_type) { - case NFAPI_HI_DCI0_DCI_PDU_TYPE: - handle_nfapi_hi_dci0_dci_pdu(eNB,NFAPI_SFNSF2SFN(HI_DCI0_req->sfn_sf),NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf),proc,hi_dci0_req_pdu); - eNB->pdcch_vars[NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf)&1].num_dci++; - break; - - case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: - handle_nfapi_hi_dci0_mpdcch_dci_pdu(eNB,proc,hi_dci0_req_pdu); - eNB->mpdcch_vars[subframe&1].num_dci++; - break; - - case NFAPI_HI_DCI0_HI_PDU_TYPE: - handle_nfapi_hi_dci0_hi_pdu(eNB,NFAPI_SFNSF2SFN(HI_DCI0_req->sfn_sf),NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf),proc,hi_dci0_req_pdu); - break; + if (NFAPI_MODE!=NFAPI_MODE_VNF) + 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]; + LOG_D(PHY,"NFAPI: hi_dci0_pdu %d : type %d\n",i,hi_dci0_req_pdu->pdu_type); + + switch (hi_dci0_req_pdu->pdu_type) { + case NFAPI_HI_DCI0_DCI_PDU_TYPE: + handle_nfapi_hi_dci0_dci_pdu(eNB,NFAPI_SFNSF2SFN(HI_DCI0_req->sfn_sf),NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf),proc,hi_dci0_req_pdu); + eNB->pdcch_vars[NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf)&1].num_dci++; + break; + + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: + handle_nfapi_hi_dci0_mpdcch_dci_pdu(eNB,proc,hi_dci0_req_pdu); + eNB->mpdcch_vars[subframe&1].num_dci++; + break; + + case NFAPI_HI_DCI0_HI_PDU_TYPE: + handle_nfapi_hi_dci0_hi_pdu(eNB,NFAPI_SFNSF2SFN(HI_DCI0_req->sfn_sf),NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf),proc,hi_dci0_req_pdu); + break; + } } - } if (NFAPI_MODE!=NFAPI_MONOLITHIC) { if (number_ul_pdu>0) { diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index f056d51b5d..8d29573359 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -30,11 +30,29 @@ #include "sim.h" #include "scm_corrmat.h" #include "common/utils/LOG/log.h" +#include "common/utils/load_module_shlib.h" +#include "common/utils/telnetsrv/telnetsrv.h" + + + //#define DEBUG_CH #include "assertions.h" 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, uint8_t nb_tx, @@ -43,7 +61,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, uint8_t channel_length, double *amps, double *delays, - struct complex** R_sqrt, + struct complex **R_sqrt, double Td, double sampling_rate, double channel_bandwidth, @@ -53,30 +71,27 @@ void fill_channel_desc(channel_desc_t *chan_desc, double max_Doppler, int32_t channel_offset, double path_loss_dB, - uint8_t random_aoa) -{ - - + uint8_t random_aoa) { uint16_t i,j; double delta_tau; - 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_rx = nb_rx; chan_desc->nb_taps = nb_taps; chan_desc->channel_length = channel_length; chan_desc->amps = amps; LOG_D(OCM,"[CHANNEL] Doing delays ...\n"); + 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; + for (i=0; i<nb_taps; i++) chan_desc->delays[i] = ((double)i)*delta_tau; - } - else - chan_desc->delays = delays; + } else + chan_desc->delays = delays; + chan_desc->Td = Td; chan_desc->sampling_rate = sampling_rate; chan_desc->channel_bandwidth = channel_bandwidth; @@ -89,43 +104,46 @@ void fill_channel_desc(channel_desc_t *chan_desc, chan_desc->first_run = 1; chan_desc->ip = 0.0; chan_desc->max_Doppler = max_Doppler; - 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->a = (struct complex**) malloc(nb_taps*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->a = (struct complex **) malloc(nb_taps*sizeof(struct complex *)); LOG_D(OCM,"[CHANNEL] Filling ch \n"); 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++) - 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); + 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)); - 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"); + 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++) { - chan_desc->R_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complex *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; } } - } - else { - chan_desc->R_sqrt = (struct complex**) calloc(nb_taps,sizeof(struct complex*)); + } else { + chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); + for (i = 0; i<nb_taps; i++) { - //chan_desc->R_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); - //chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0]; - /* all chan_desc share the same R_sqrt, coming from caller */ - chan_desc->R_sqrt[i] = R_sqrt[0]; - } + //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]; + /* all chan_desc share the same R_sqrt, coming from caller */ + chan_desc->R_sqrt[i] = R_sqrt[0]; + } } for (i = 0; i<nb_taps; i++) { @@ -135,16 +153,15 @@ void fill_channel_desc(channel_desc_t *chan_desc, } 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]); chan_desc->nb_paths=10; - reset_meas(&chan_desc->random_channel); reset_meas(&chan_desc->interp_time); reset_meas(&chan_desc->interp_freq); 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}; @@ -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_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 ts_shift_delays[] = {0, 1/7.68}; @@ -170,9 +187,10 @@ double ts_shift_amps[] = {0, 1}; //correlation matrix for a 2x2 channel with full Tx correlation 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.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.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}; //correlation matrix for a fully correlated 2x1 channel (h1==h2) @@ -181,9 +199,10 @@ struct complex *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap}; //correlation matrix for a 2x2 channel with full Tx anti-correlation 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.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.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}; //correlation matrix for a fully anti-correlated 2x1 channel (h1==-h2) @@ -195,9 +214,10 @@ struct complex **R_sqrt_ptr2; // full correlation matrix in vectorized form for 2x2 channel, where h1 is perfectly orthogonal to h2 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.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.70711,0.0} +}; struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap}; // full correlation matrix for TM4 to make orthogonal effective channel @@ -206,37 +226,42 @@ 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}, - {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.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.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_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.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.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.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}; //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}, - {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}, {0.0,0.0}, {1.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}, {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_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.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.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.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_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.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.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.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}; @@ -250,15 +275,12 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, double channel_bandwidth, double forgetting_factor, 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)); uint16_t i,j; double sum_amps; double aoa,ricean_factor,Td,maxDoppler; int channel_length,nb_taps; - chan_desc->nb_tx = nb_tx; chan_desc->nb_rx = nb_rx; chan_desc->sampling_rate = sampling_rate; @@ -268,424 +290,514 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->path_loss_dB = path_loss_dB; chan_desc->first_run = 1; chan_desc->ip = 0.0; - LOG_I(OCM,"Channel Model (inside of new_channel_desc_scm)=%d\n\n", channel_model); switch (channel_model) { - case SCM_A: - LOG_W(OCM,"channel model not yet supported\n"); - free(chan_desc); - return(NULL); - case SCM_B: - LOG_W(OCM,"channel model not yet supported\n"); - free(chan_desc); - return(NULL); - case SCM_C: - chan_desc->nb_taps = 18; - 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)); - sum_amps = 0; - chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { - chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); - sum_amps += chan_desc->amps[i]; - } - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->amps[i] /= sum_amps; - chan_desc->delays = scm_c_delays; - chan_desc->ricean_factor = 1; - chan_desc->aoa = 0; - chan_desc->random_aoa = 0; - 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->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - 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->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - if (nb_tx==2 && nb_rx==2) { - for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } - else if (nb_tx==2 && nb_rx==1) { - for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex*) &R21_sqrt[i][0]; - } - else if (nb_tx==1 && nb_rx==2) { - for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex*) &R12_sqrt[i][0]; - } - else { - for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { - chan_desc->R_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; - } - LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); + case SCM_A: + LOG_W(OCM,"channel model not yet supported\n"); + free(chan_desc); + return(NULL); + + case SCM_B: + LOG_W(OCM,"channel model not yet supported\n"); + free(chan_desc); + return(NULL); + + case SCM_C: + chan_desc->nb_taps = 18; + 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)); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); + sum_amps += chan_desc->amps[i]; } - } - break; - 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"); - chan_desc->nb_taps = 18; - 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)); - sum_amps = 0; - chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { - chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); - sum_amps += chan_desc->amps[i]; - } - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->amps[i] /= sum_amps; - chan_desc->delays = scm_c_delays; - chan_desc->ricean_factor = 0.1; - chan_desc->aoa = 0; - chan_desc->random_aoa = 0; - 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->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - 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->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - if (nb_tx==2 && nb_rx==2) { - for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } - else if (nb_tx==2 && nb_rx==1) { - for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex*) &R21_sqrt[i][0]; - } - else if (nb_tx==1 && nb_rx==2) { - for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex*) &R12_sqrt[i][0]; - } - else { - for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { - chan_desc->R_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->amps[i] /= sum_amps; + + chan_desc->delays = scm_c_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + 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->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + 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->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + + if (nb_tx==2 && nb_rx==2) { + for (i = 0; i<6; i++) + chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + } else if (nb_tx==2 && nb_rx==1) { + for (i = 0; i<6; i++) + chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0]; + } else if (nb_tx==1 && nb_rx==2) { + for (i = 0; i<6; i++) + chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; + } else { + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + + 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; - case EPA: - chan_desc->nb_taps = 7; - chan_desc->Td = .410; - chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); - sum_amps = 0; - chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { - chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); - sum_amps += chan_desc->amps[i]; - } - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->amps[i] /= sum_amps; - chan_desc->delays = epa_delays; - chan_desc->ricean_factor = 1; - chan_desc->aoa = 0; - chan_desc->random_aoa = 0; - 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->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); - if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } - else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { - chan_desc->R_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + + break; + + 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"); + chan_desc->nb_taps = 18; + 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)); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->amps[i] /= sum_amps; + + chan_desc->delays = scm_c_delays; + chan_desc->ricean_factor = 0.1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + 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->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + 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->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + + if (nb_tx==2 && nb_rx==2) { + for (i = 0; i<6; i++) + chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + } else if (nb_tx==2 && nb_rx==1) { + for (i = 0; i<6; i++) + chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0]; + } else if (nb_tx==1 && nb_rx==2) { + for (i = 0; i<6; i++) + chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; + } else { + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + + 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 only implemented for nb_tx==2 and nb_rx==2, using identity\n"); } - } - break; - case EPA_low: - chan_desc->nb_taps = 7; - chan_desc->Td = .410; - chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); - sum_amps = 0; - chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { - chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); - sum_amps += chan_desc->amps[i]; - } - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->amps[i] /= sum_amps; - chan_desc->delays = epa_delays; - chan_desc->ricean_factor = 1; - chan_desc->aoa = 0; - chan_desc->random_aoa = 0; - 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->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); - if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); + + break; + + case EPA: + chan_desc->nb_taps = 7; + chan_desc->Td = .410; + chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0]; - } - else { - printf("Correlation matrices are implemented for 2 x 2 only"); - } - /*else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { - chan_desc->R_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->amps[i] /= sum_amps; + + chan_desc->delays = epa_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + 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->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + + if (nb_tx==2 && nb_rx==2) { + chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + + for (i = 0; i<6; i++) + chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + } else { + chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + + 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; - case EPA_high: - chan_desc->nb_taps = 7; - chan_desc->Td = .410; - chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); - sum_amps = 0; - chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { - chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); - sum_amps += chan_desc->amps[i]; - } - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->amps[i] /= sum_amps; - chan_desc->delays = epa_delays; - chan_desc->ricean_factor = 1; - chan_desc->aoa = 0; - chan_desc->random_aoa = 0; - 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->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); - if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); + + break; + + case EPA_low: + chan_desc->nb_taps = 7; + chan_desc->Td = .410; + chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0]; - } - else { - printf("Correlation matrices are implemented for 2 x 2 only"); - } - /*else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { - chan_desc->R_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->amps[i] /= sum_amps; + + chan_desc->delays = epa_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + 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->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + + if (nb_tx==2 && nb_rx==2) { + chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0]; + } else { + printf("Correlation matrices are implemented for 2 x 2 only"); + } + + /*else { + chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + 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; + + case EPA_high: + chan_desc->nb_taps = 7; + chan_desc->Td = .410; + chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->amps[i] /= sum_amps; + + chan_desc->delays = epa_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + 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->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + + if (nb_tx==2 && nb_rx==2) { + chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0]; + } else { + printf("Correlation matrices are implemented for 2 x 2 only"); } - }*/ - break; + + /*else { + chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); + } + }*/ + break; + case EPA_medium: - chan_desc->nb_taps = 7; - chan_desc->Td = .410; - chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); - sum_amps = 0; - chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { - chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); - sum_amps += chan_desc->amps[i]; - } - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->amps[i] /= sum_amps; - chan_desc->delays = epa_delays; - chan_desc->ricean_factor = 1; - chan_desc->aoa = 0; - chan_desc->random_aoa = 0; - 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->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); - if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); + chan_desc->nb_taps = 7; + chan_desc->Td = .410; + chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0]; - } else { - printf("Correlation matrices are implemented for 2 x 2 only"); - } - /*else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { - chan_desc->R_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->amps[i] /= sum_amps; + + chan_desc->delays = epa_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + 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->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + + if (nb_tx==2 && nb_rx==2) { + chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0]; + } else { + printf("Correlation matrices are implemented for 2 x 2 only"); + } + + /*else { + chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + 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; + + case EVA: + chan_desc->nb_taps = 9; + 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)); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]); + sum_amps += chan_desc->amps[i]; } - }*/ - break; - case EVA: - chan_desc->nb_taps = 9; - 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)); - sum_amps = 0; - chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { - chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]); - sum_amps += chan_desc->amps[i]; - } - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->amps[i] /= sum_amps; - chan_desc->delays = eva_delays; - chan_desc->ricean_factor = 1; - chan_desc->aoa = 0; - chan_desc->random_aoa = 0; - 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->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); - if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } - else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { - chan_desc->R_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->amps[i] /= sum_amps; + + chan_desc->delays = eva_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + 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->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + + if (nb_tx==2 && nb_rx==2) { + chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + + for (i = 0; i<6; i++) + chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + } else { + chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + + 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; - case ETU: - chan_desc->nb_taps = 9; - 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)); - sum_amps = 0; - chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { - chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]); - sum_amps += chan_desc->amps[i]; - } - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->amps[i] /= sum_amps; - chan_desc->delays = etu_delays; - chan_desc->ricean_factor = 1; - chan_desc->aoa = 0; - chan_desc->random_aoa = 0; - 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->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); - if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } - else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + + break; + + case ETU: + chan_desc->nb_taps = 9; + 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)); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->amps[i] /= sum_amps; + + chan_desc->delays = etu_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + 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->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + + if (nb_tx==2 && nb_rx==2) { + chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + + for (i = 0; i<6; i++) + chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + } else { + chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + + LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); + } + } + + break; + + case MBSFN: + chan_desc->nb_taps = 18; + 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)); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->amps[i] /= sum_amps; + + chan_desc->delays = mbsfn_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + 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->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + 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->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex *)); + 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)) { chan_desc->R_sqrt[i][j].x = 1.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"); } - } - break; - case MBSFN: - chan_desc->nb_taps = 18; - 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)); - sum_amps = 0; - chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { - chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]); - sum_amps += chan_desc->amps[i]; - } - for (i = 0; i<chan_desc->nb_taps; i++) - chan_desc->amps[i] /= sum_amps; - chan_desc->delays = mbsfn_delays; - chan_desc->ricean_factor = 1; - chan_desc->aoa = 0; - chan_desc->random_aoa = 0; - 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->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) - chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - 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->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex*)); - for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { - chan_desc->R_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; - } - LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); - } - break; - case Rayleigh8: + break; + + case Rayleigh8: nb_taps = 8; Td = 0.8; channel_length = (int)11+2*sampling_rate*Td; ricean_factor = 1; aoa = .03; maxDoppler = 0; - fill_channel_desc(chan_desc, nb_tx, nb_rx, @@ -706,88 +818,85 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, 0); break; - case Rice8: + case Rice8: nb_taps = 8; Td = 0.8; channel_length = (int)11+2*sampling_rate*Td; ricean_factor = 0.1; aoa = 0.7854; maxDoppler = 0; - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amps_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 1); + nb_rx, + nb_taps, + channel_length, + default_amps_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 1); break; - case Rayleigh1: + case Rayleigh1: nb_taps = 1; Td = 0; channel_length = 1; ricean_factor = 1; aoa = .03; maxDoppler = 0; - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); break; - case Rayleigh1_800: + case Rayleigh1_800: nb_taps = 1; Td = 0; channel_length = 1; ricean_factor = 1; aoa = .03; maxDoppler = 800; - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); break; - case Rayleigh1_corr: + case Rayleigh1_corr: nb_taps = 1; Td = 0; channel_length = 1; @@ -797,33 +906,31 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, if ((nb_tx==2) && (nb_rx==1)) { 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; - } - else + } else R_sqrt_ptr2 = NULL; fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); break; - case Rayleigh1_anticorr: + case Rayleigh1_anticorr: nb_taps = 1; Td = 0; channel_length = 1; @@ -833,118 +940,111 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, if ((nb_tx==2) && (nb_rx==1)) { //check this 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; - } - else + } else R_sqrt_ptr2 = NULL; fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); break; - case Rice1: + case Rice1: nb_taps = 1; Td = 0; channel_length = 1; ricean_factor = 0.1; aoa = 0.7854; maxDoppler = 0; - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); break; - case AWGN: + case AWGN: nb_taps = 1; Td = 0; channel_length = 1; ricean_factor = 0.0; aoa = 0.0; maxDoppler = 0; - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); printf("AWGN: ricean_factor %f\n",chan_desc->ricean_factor); - break; - case TS_SHIFT: + case TS_SHIFT: nb_taps = 2; Td = ts_shift_delays[1]; channel_length = 10; ricean_factor = 0.0; aoa = 0.0; maxDoppler = 0; - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - ts_shift_amps, - ts_shift_delays, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); + nb_rx, + nb_taps, + channel_length, + ts_shift_amps, + ts_shift_delays, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); printf("TS_SHIFT: ricean_factor %f\n",chan_desc->ricean_factor); - break; - case Rice1_corr: + case Rice1_corr: nb_taps = 1; Td = 0; channel_length = 1; @@ -954,33 +1054,31 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, if ((nb_tx==2) && (nb_rx==1)) { 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; - } - else + } else R_sqrt_ptr2 = NULL; fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 1); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 1); break; - case Rice1_anticorr: + case Rice1_anticorr: nb_taps = 1; Td = 0; channel_length = 1; @@ -990,33 +1088,31 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, if ((nb_tx==2) && (nb_rx==1)) { 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; - } - else + } else R_sqrt_ptr2 = NULL; fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 1); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 1); break; - case Rayleigh1_orthogonal: + case Rayleigh1_orthogonal: nb_taps = 1; Td = 0; channel_length = 1; @@ -1024,33 +1120,31 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, aoa = 0.03; maxDoppler = 0; - if ((nb_tx==2) && (nb_rx==2)) { R_sqrt_ptr2 = R_sqrt_22_orthogonal; - } - else + } else R_sqrt_ptr2 = NULL; fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); break; - case Rayleigh1_orth_eff_ch_TM4_prec_real: + case Rayleigh1_orth_eff_ch_TM4_prec_real: nb_taps = 1; Td = 0; channel_length = 1; @@ -1058,33 +1152,31 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, aoa = 0.03; maxDoppler = 0; - if ((nb_tx==2) && (nb_rx==2)) { R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real; - } - else + } else R_sqrt_ptr2 = NULL; fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 1); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 1); break; - case Rayleigh1_orth_eff_ch_TM4_prec_imag: + case Rayleigh1_orth_eff_ch_TM4_prec_imag: nb_taps = 1; Td = 0; channel_length = 1; @@ -1092,49 +1184,43 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, aoa = 0.03; maxDoppler = 0; - if ((nb_tx==2) && (nb_rx==2)) { R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag; - } - else + } else R_sqrt_ptr2 = NULL; fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); break; - case Rayleigh8_orth_eff_ch_TM4_prec_real: - - if ((nb_tx==2) && (nb_rx==2)) { + case Rayleigh8_orth_eff_ch_TM4_prec_real: + if ((nb_tx==2) && (nb_rx==2)) { R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real; //R_sqrt_ptr2 = NULL; - } - else + } else R_sqrt_ptr2 = NULL; - nb_taps = 8; Td = 0.8; channel_length = (int)11+2*sampling_rate*Td; ricean_factor = 1; aoa = .03; maxDoppler = 0; - fill_channel_desc(chan_desc, nb_tx, nb_rx, @@ -1153,10 +1239,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, channel_offset, path_loss_dB, 0); - break; - case Rayleigh8_orth_eff_ch_TM4_prec_imag: + case Rayleigh8_orth_eff_ch_TM4_prec_imag: nb_taps = 8; Td = 0.8; channel_length = (int)11+2*sampling_rate*Td; @@ -1166,11 +1251,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, if ((nb_tx==2) && (nb_rx==2)) { R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag; - } - else + } else R_sqrt_ptr2 = NULL; - fill_channel_desc(chan_desc, + fill_channel_desc(chan_desc, nb_tx, nb_rx, nb_taps, @@ -1190,40 +1274,38 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, 0); break; - default: - LOG_W(OCM,"channel model not yet supported\n"); - free(chan_desc); - return(NULL); + default: + LOG_W(OCM,"channel model not yet supported\n"); + free(chan_desc); + return(NULL); } + 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]); chan_desc->nb_paths = 10; - return(chan_desc); } -void free_channel_desc_scm(channel_desc_t * ch) { - // Must be made cleanly, a lot of leaks... - free(ch); +void free_channel_desc_scm(channel_desc_t *ch) { + // Must be made cleanly, a lot of leaks... + free(ch); } int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { - double s; int i,k,l,aarx,aatx; struct complex anew[NB_ANTENNAS_TX*NB_ANTENNAS_RX],acorr[NB_ANTENNAS_TX*NB_ANTENNAS_RX]; struct complex phase, alpha, beta; - 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); - 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)].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) { // that we can safely assume plane wave propagation. phase.x = cos(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)].y += phase.y * sqrt(1.0-desc->ricean_factor); } + #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); #endif @@ -1263,10 +1345,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { alpha.y = 0.0; beta.x = 0.0; beta.y = 0.0; - 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*) anew, 1, (void*) &beta, (void*) acorr, 1); + (void *) &alpha, (void *) desc->R_sqrt[i/3], desc->nb_rx*desc->nb_tx, + (void *) anew, 1, (void *) &beta, (void *) acorr, 1); /* for (aarx=0;aarx<desc->nb_rx;aarx++) { @@ -1278,10 +1359,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { } */ - if (desc->first_run==1){ - cblas_zcopy(desc->nb_tx*desc->nb_rx, (void*) acorr, 1, (void*) desc->a[i], 1); - } - else { + if (desc->first_run==1) { + cblas_zcopy(desc->nb_tx*desc->nb_rx, (void *) acorr, 1, (void *) desc->a[i], 1); + } else { // a = alpha*acorr+beta*a // a = beta*a // a = a+alpha*acorr @@ -1289,9 +1369,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { alpha.y = 0; beta.x = sqrt(desc->forgetting_factor); beta.y = 0; - 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_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); // 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; } @@ -1305,8 +1384,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { } } */ - } //nb_taps + stop_meas(&desc->random_channel); //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) { 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; } else { - 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].y = 0.0; @@ -1335,18 +1413,18 @@ 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].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); - } //nb_taps #ifdef DEBUG_CH - k=0; - printf("(%d,%d,%d)->(%f,%f)\n",k,aarx,aatx,desc->ch[aarx+(aatx*desc->nb_rx)][k].x,desc->ch[aarx+(aatx*desc->nb_rx)][k].y); + k=0; + printf("(%d,%d,%d)->(%f,%f)\n",k,aarx,aatx,desc->ch[aarx+(aatx*desc->nb_rx)][k].x,desc->ch[aarx+(aatx*desc->nb_rx)][k].y); #endif - } - } //channel_length - } //aatx - } //aarx - stop_meas(&desc->interp_time); + } + } //channel_length + } //aatx + } //aarx + + stop_meas(&desc->interp_time); } if (desc->first_run==1) @@ -1355,69 +1433,85 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { return (0); } -double N_RB2sampling_rate(uint16_t N_RB) -{ +double N_RB2sampling_rate(uint16_t N_RB) { double sampling_rate; + switch (N_RB) { - case 6: - sampling_rate = 1.92; - break; + case 6: + sampling_rate = 1.92; + break; - case 25: - sampling_rate = 7.68; - break; + case 25: + sampling_rate = 7.68; + break; - case 50: - sampling_rate = 15.36; - break; + case 50: + sampling_rate = 15.36; + break; - case 100: - sampling_rate = 30.72; - break; + case 100: + sampling_rate = 30.72; + break; - default: - AssertFatal(1==0,"Unknown N_PRB %d",N_RB); + default: + AssertFatal(1==0,"Unknown N_PRB %d",N_RB); } return(sampling_rate); } -double N_RB2channel_bandwidth(uint16_t N_RB) -{ +double N_RB2channel_bandwidth(uint16_t N_RB) { double channel_bandwidth; + switch (N_RB) { - case 6: - channel_bandwidth = 1.25; - break; + case 6: + channel_bandwidth = 1.25; + break; - case 25: - channel_bandwidth = 5.00; - break; + case 25: + channel_bandwidth = 5.00; + break; - case 50: - channel_bandwidth = 10.00; - break; + case 50: + channel_bandwidth = 10.00; + break; - case 100: - channel_bandwidth = 20.00; - break; + case 100: + channel_bandwidth = 20.00; + break; - default: - LOG_E(PHY,"Unknown N_PRB\n"); - return(-1); + default: + LOG_E(PHY,"Unknown N_PRB\n"); + return(-1); } + 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 #define sampling_rate 5.0 #define Td 2.0 main(int argc,char **argv) { - double amps[8] = {.8,.2,.1,.04,.02,.01,.005}; struct complex ch[(int)(1+2*sampling_rate*Td)],phase; int i; - randominit(); phase.x = 1.0; phase.y = 0; diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index bde7b92506..791a61f14e 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -147,7 +147,7 @@ typedef struct { /// Rice factor??? /// Walls (penetration loss) /// Nodes in the scenario - node_desc_t* nodes; + node_desc_t *nodes; } scenario_desc_t; typedef enum { @@ -180,29 +180,59 @@ typedef enum { EPA_medium, EPA_high, } 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" typedef struct { - channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs]; - channel_desc_t *UE2RU[NUMBER_OF_UE_MAX][NUMBER_OF_RU_MAX][MAX_NUM_CCs]; - double r_re_DL[NUMBER_OF_UE_MAX][2][30720]; - double r_im_DL[NUMBER_OF_UE_MAX][2][30720]; - double r_re_UL[NUMBER_OF_eNB_MAX][2][30720]; - double r_im_UL[NUMBER_OF_eNB_MAX][2][30720]; - int RU_output_mask[NUMBER_OF_UE_MAX]; - int UE_output_mask[NUMBER_OF_RU_MAX]; - pthread_mutex_t RU_output_mutex[NUMBER_OF_UE_MAX]; - pthread_mutex_t UE_output_mutex[NUMBER_OF_RU_MAX]; - pthread_mutex_t subframe_mutex; - int subframe_ru_mask; - int subframe_UE_mask; - openair0_timestamp current_ru_rx_timestamp[NUMBER_OF_RU_MAX][MAX_NUM_CCs]; - openair0_timestamp current_UE_rx_timestamp[MAX_MOBILES_PER_ENB][MAX_NUM_CCs]; - openair0_timestamp last_ru_rx_timestamp[NUMBER_OF_RU_MAX][MAX_NUM_CCs]; - openair0_timestamp last_UE_rx_timestamp[MAX_MOBILES_PER_ENB][MAX_NUM_CCs]; - double ru_amp[NUMBER_OF_RU_MAX]; - pthread_t rfsim_thread; + channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs]; + channel_desc_t *UE2RU[NUMBER_OF_UE_MAX][NUMBER_OF_RU_MAX][MAX_NUM_CCs]; + double r_re_DL[NUMBER_OF_UE_MAX][2][30720]; + double r_im_DL[NUMBER_OF_UE_MAX][2][30720]; + double r_re_UL[NUMBER_OF_eNB_MAX][2][30720]; + double r_im_UL[NUMBER_OF_eNB_MAX][2][30720]; + int RU_output_mask[NUMBER_OF_UE_MAX]; + int UE_output_mask[NUMBER_OF_RU_MAX]; + pthread_mutex_t RU_output_mutex[NUMBER_OF_UE_MAX]; + pthread_mutex_t UE_output_mutex[NUMBER_OF_RU_MAX]; + pthread_mutex_t subframe_mutex; + int subframe_ru_mask; + int subframe_UE_mask; + openair0_timestamp current_ru_rx_timestamp[NUMBER_OF_RU_MAX][MAX_NUM_CCs]; + openair0_timestamp current_UE_rx_timestamp[MAX_MOBILES_PER_ENB][MAX_NUM_CCs]; + openair0_timestamp last_ru_rx_timestamp[NUMBER_OF_RU_MAX][MAX_NUM_CCs]; + openair0_timestamp last_UE_rx_timestamp[MAX_MOBILES_PER_ENB][MAX_NUM_CCs]; + double ru_amp[NUMBER_OF_RU_MAX]; + pthread_t rfsim_thread; } sim_t; @@ -231,7 +261,7 @@ typedef struct { channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, uint8_t nb_rx, SCM_t channel_model, - double sampling_rate, + double sampling_rate, double channel_bandwidth, double forgetting_factor, int32_t channel_offset, @@ -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_RB2channel_bandwidth(uint16_t N_RB); + #include "targets/RT/USER/rfsim.h" void do_DL_sig(sim_t *sim, @@ -409,9 +449,10 @@ void do_DL_sig(sim_t *sim, int CC_id); 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); + #endif diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 638f5ed989..8367a451a3 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -29,6 +29,7 @@ #include "common_lib.h" #include <openair1/PHY/defs_eNB.h> #include "openair1/PHY/defs_UE.h" +#define CHANNELMOD_DYNAMICLOAD #include <openair1/SIMULATION/TOOLS/sim.h> #define PORT 4043 //default TCP port for this simulator @@ -44,25 +45,26 @@ extern double snr_dB; extern RAN_CONTEXT_t RC; // -#define MAX_RFSIMU_OPT 2 + #define RFSIMU_SECTION "rfsimulator" #define RFSIMU_OPTIONS_PARAMNAME "options" # define RFSIM_CONFIG_HELP_OPTIONS " list of comma separated options to enable rf simulator functionalities. Available options: \n"\ " chanmod: enable channel modelisation\n"\ " saviq: enable saving written iqs to a file\n" - /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ - /* configuration parameters for the rfsimulator device */ - /* optname helpstr paramflags XXXptr defXXXval type numelt */ - /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* configuration parameters for the rfsimulator device */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define RFSIMULATOR_PARAMS_DESC {\ - {"serveraddr", "<ip address to connect to>\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ - {"serverport", "<port to connect to>\n", 0, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\ - {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0}, \ - {"IQfile", "<file path to use when saving IQs>\n", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",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 },\ + {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 }\ + }; pthread_mutex_t Sockmutex; + typedef struct buffer_s { int conn_sock; openair0_timestamp lastReceivedTS; @@ -88,84 +90,9 @@ typedef struct { int tx_num_channels; double sample_rate; double tx_bw; + bool enable_channelmod; } 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) { buffer_t *ptr=&bridge->buf[sock]; @@ -183,26 +110,29 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ev.events = EPOLLIN | EPOLLRDHUP; ev.data.fd = sock; AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, ""); - // create channel simulation model for this mode reception - // snr_dB is pure global, coming from configuration paramter "-s" - // Fixme: referenceSignalPower should come from the right place - // but the datamodel is inconsistant - // legacy: RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower - // (must not come from ru[]->frame_parms as it doesn't belong to ru !!!) - // Legacy sets it as: - // ptr->channel_model->path_loss_dB = -132.24 + snr_dB - RC.ru[0]->frame_parms->pdsch_config_common.referenceSignalPower; - // we use directly the paramter passed on the command line ("-s") - // the value channel_model->path_loss_dB seems only a storage place (new_channel_desc_scm() only copy the passed value) - // Legacy changes directlty the variable channel_model->path_loss_dB place to place - // while calling new_channel_desc_scm() with path losses = 0 - ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, - AWGN, - bridge->sample_rate, - bridge->tx_bw, - 0.0, // forgetting_factor - 0, // maybe used for TA - 0); // path_loss in dB - random_channel(ptr->channel_model,false); + + if ( bridge->enable_channelmod==true) { + // create channel simulation model for this mode reception + // snr_dB is pure global, coming from configuration paramter "-s" + // Fixme: referenceSignalPower should come from the right place + // but the datamodel is inconsistant + // legacy: RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower + // (must not come from ru[]->frame_parms as it doesn't belong to ru !!!) + // Legacy sets it as: + // ptr->channel_model->path_loss_dB = -132.24 + snr_dB - RC.ru[0]->frame_parms->pdsch_config_common.referenceSignalPower; + // we use directly the paramter passed on the command line ("-s") + // the value channel_model->path_loss_dB seems only a storage place (new_channel_desc_scm() only copy the passed value) + // Legacy changes directlty the variable channel_model->path_loss_dB place to place + // while calling new_channel_desc_scm() with path losses = 0 + ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, + AWGN, + bridge->sample_rate, + bridge->tx_bw, + 0.0, // forgetting_factor + 0, // maybe used for TA + 0); // path_loss in dB + random_channel(ptr->channel_model,false); + } } void removeCirBuf(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\ For this, export RFSIMULATOR=enb (eNB case) or \n\ RFSIMULATOR=<an ip address> (UE case)\n\ + or use rfsimulator.serveraddr configuration option\n\ \x1b[m" enum blocking_t { @@ -284,43 +215,46 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { buf += l; } } - + void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { - char *saveF=NULL; - paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC; - + char *saveF=NULL; + paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC; 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); AssertFatal(ret >= 0, "configuration couldn't be performed"); - rfsimulator->saveIQfile = -1; + rfsimulator->saveIQfile = -1; + for(int i=0; i<rfsimu_params[p].numelt ; i++) { - if (strcmp(rfsimu_params[p].strlistptr[i],"saviq") == 0) { - rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666); - if ( rfsimulator->saveIQfile != -1 ) - LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF); - else - LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno)); - break; - } else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) { - load_module_shlib("chanmod",NULL,0,NULL); - } else { - fprintf(stderr,"Unknown rfsimulator option: %s\n",rfsimu_params[p].strlistptr[i]); - exit(-1); - } + if (strcmp(rfsimu_params[p].strlistptr[i],"saviq") == 0) { + rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666); + + if ( rfsimulator->saveIQfile != -1 ) + LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF); + else + LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno)); + + break; + } else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) { + init_channelmod(); + rfsimulator->enable_channelmod=true; + } else { + fprintf(stderr,"Unknown rfsimulator option: %s\n",rfsimu_params[p].strlistptr[i]); + exit(-1); + } } + /* for compatibility keep environment variable usage */ if ( getenv("RFSIMULATOR") != NULL ) { - rfsimulator->ip=getenv("RFSIMULATOR"); + rfsimulator->ip=getenv("RFSIMULATOR"); } - + if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 || - strncasecmp(rfsimulator->ip,"server",3) == 0 ) + strncasecmp(rfsimulator->ip,"server",3) == 0 ) rfsimulator->typeStamp = ENB_MAGICDL_FDD; else rfsimulator->typeStamp = UE_MAGICDL_FDD; - } int server_start(openair0_device *device) { @@ -383,13 +317,13 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi rfsimulator_state_t *t = device->priv; LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp); - for (int i=0; i<FD_SETSIZE; i++) { buffer_t *b=&t->buf[i]; if (b->conn_sock >= 0 ) { 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}; fullwrite(b->conn_sock,&header, sizeof(header), t); sample_t tmpSamples[nsamps][nbAnt]; @@ -546,42 +480,48 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo // no connected device (we are eNB, no UE is connected) if ( t->nextTimestamp == 0) LOG_W(HW,"No connected device, generating void samples...\n"); + if (!flushInput(t, 10)) { for (int x=0; x < nbAnt; x++) memset(samplesVoid[x],0,sampleToByte(nsamps,1)); t->nextTimestamp+=nsamps; + if ( ((t->nextTimestamp/nsamps)%100) == 0) LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp); + *ptimestamp = t->nextTimestamp-nsamps; pthread_mutex_unlock(&Sockmutex); return nsamps; } } else { - bool have_to_wait; do { have_to_wait=false; for ( int sock=0; sock<FD_SETSIZE; sock++) { - buffer_t *b=&t->buf[sock]; + buffer_t *b=&t->buf[sock]; + if ( b->circularBuf) { LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n", sock, b->lastWroteTS, b->lastReceivedTS, t->nextTimestamp+nsamps); - if ( b->lastReceivedTS > b->lastWroteTS ) { - // 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 - // with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power - struct complex16 v={0}; - void *samplesVoid[b->th.nbAnt]; - for ( int i=0; i <b->th.nbAnt; i++) - samplesVoid[i]=(void*)&v; - rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0); - } - } + + if ( b->lastReceivedTS > b->lastWroteTS ) { + // 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 + // with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power + struct complex16 v= {0}; + void *samplesVoid[b->th.nbAnt]; + + for ( int i=0; i <b->th.nbAnt; i++) + samplesVoid[i]=(void *)&v; + + rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0); + } + } if ( b->circularBuf ) if ( t->nextTimestamp+nsamps > b->lastReceivedTS ) { @@ -616,15 +556,17 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo random_channel(ptr->channel_model,0); for (int a=0; a<nbAnt; a++) { - if ( ptr->channel_model != NULL ) // apply a channel model + if ( ptr->channel_model != NULL ) // apply a channel model rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a], a, ptr->channel_model, nsamps, - t->nextTimestamp + t->nextTimestamp, + CirSize ); else { // no channel modeling sample_t *out=(sample_t *)samplesVoid[a]; + for ( int i=0; i < nsamps; i++ ) { out[i].r+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].r; out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].i; @@ -672,15 +614,9 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { // to change the log level, use this on command line // --log_config.hw_log_level debug rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1); - rfsimulator_readconfig(rfsimulator); - pthread_mutex_init(&Sockmutex, NULL); - - 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 ? server_start : start_ue; -- 2.26.2