This completely removes the UESIM_EXPANSION define: it does not compile at the moment. Its function was to multiplex multiple UEs on the same TUN interface. However, this functionality is not needed since it is possible to allocate many TUN devices (i.e., >= 32).
798 lines
25 KiB
C
798 lines
25 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
/*! \file lte-uesoftmodem.c
|
|
* \brief Top-level threads for eNodeB
|
|
* \author R. Knopp, F. Kaltenberger, Navid Nikaein
|
|
* \date 2012
|
|
* \version 0.1
|
|
* \company Eurecom
|
|
* \email: {knopp, florian.kaltenberger, navid.nikaein}@eurecom.fr
|
|
* \note
|
|
* \warning
|
|
*/
|
|
|
|
|
|
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
|
#include <sched.h>
|
|
|
|
#include "rt_wrapper.h"
|
|
|
|
|
|
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
|
|
|
|
#include "assertions.h"
|
|
#include "msc.h"
|
|
|
|
#include "PHY/types.h"
|
|
|
|
#include "PHY/defs_UE.h"
|
|
#include "common/ran_context.h"
|
|
#include "common/config/config_userapi.h"
|
|
#include "common/utils/load_module_shlib.h"
|
|
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
|
|
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
|
|
|
#include "../../ARCH/COMMON/common_lib.h"
|
|
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
|
|
|
|
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
|
|
|
#include "PHY/phy_vars_ue.h"
|
|
#include "PHY/LTE_TRANSPORT/transport_vars.h"
|
|
#include "SCHED/sched_common_vars.h"
|
|
#include "PHY/MODULATION/modulation_vars.h"
|
|
|
|
#include "LAYER2/MAC/mac.h"
|
|
#include "LAYER2/MAC/mac_vars.h"
|
|
#include "LAYER2/MAC/mac_proto.h"
|
|
#include "RRC/LTE/rrc_vars.h"
|
|
#include "PHY_INTERFACE/phy_interface_vars.h"
|
|
#include "PHY/TOOLS/phy_scope_interface.h"
|
|
#include "common/utils/LOG/log.h"
|
|
#include "nfapi/oai_integration/vendor_ext.h"
|
|
#include "UTIL/OTG/otg_tx.h"
|
|
#include "UTIL/OTG/otg_externs.h"
|
|
#include "UTIL/MATH/oml.h"
|
|
#include "common/utils/LOG/vcd_signal_dumper.h"
|
|
#include "UTIL/OPT/opt.h"
|
|
|
|
#ifndef OPENAIR2
|
|
#include "UTIL/OTG/otg_vars.h"
|
|
#endif
|
|
|
|
#include "create_tasks.h"
|
|
#include "system.h"
|
|
|
|
|
|
#include "lte-softmodem.h"
|
|
|
|
|
|
/* temporary compilation wokaround (UE/eNB split */
|
|
uint16_t sf_ahead;
|
|
|
|
|
|
pthread_cond_t nfapi_sync_cond;
|
|
pthread_mutex_t nfapi_sync_mutex;
|
|
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
|
|
|
|
|
|
uint16_t sf_ahead=2;
|
|
int tddflag;
|
|
char *emul_iface;
|
|
|
|
|
|
pthread_cond_t sync_cond;
|
|
pthread_mutex_t sync_mutex;
|
|
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
|
|
int config_sync_var=-1;
|
|
|
|
uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
|
|
uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
|
|
|
|
volatile int oai_exit = 0;
|
|
|
|
unsigned int mmapped_dma=0;
|
|
|
|
|
|
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
|
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
|
|
|
|
|
|
|
int UE_scan = 1;
|
|
int UE_scan_carrier = 0;
|
|
|
|
runmode_t mode = normal_txrx;
|
|
|
|
FILE *input_fd=NULL;
|
|
int otg_enabled=0;
|
|
|
|
#if MAX_NUM_CCs == 1
|
|
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
|
|
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
|
|
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0}};
|
|
#else
|
|
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
|
|
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
|
|
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0},{20,0,0,0}};
|
|
#endif
|
|
|
|
double rx_gain_off = 0.0;
|
|
|
|
double sample_rate=30.72e6;
|
|
double bw = 10.0e6;
|
|
|
|
static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/;
|
|
|
|
|
|
uint8_t dci_Format = 0;
|
|
uint8_t agregation_Level =0xFF;
|
|
|
|
uint8_t nb_antenna_tx = 1;
|
|
uint8_t nb_antenna_rx = 1;
|
|
|
|
char ref[128] = "internal";
|
|
char channels[128] = "0";
|
|
|
|
int rx_input_level_dBm;
|
|
|
|
|
|
|
|
static LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
|
|
|
|
uint64_t num_missed_slots=0; // counter for the number of missed slots
|
|
|
|
// prototypes from function implemented in lte-ue.c, probably should be elsewhere in a include file.
|
|
extern void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface);
|
|
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
|
|
extern void get_uethreads_params(void);
|
|
|
|
int transmission_mode=1;
|
|
|
|
int usrp_tx_thread = 0;
|
|
|
|
|
|
char *usrp_args=NULL;
|
|
char *usrp_clksrc=NULL;
|
|
|
|
THREAD_STRUCT thread_struct;
|
|
/* struct for ethernet specific parameters given in eNB conf file */
|
|
eth_params_t *eth_params;
|
|
|
|
openair0_config_t openair0_cfg[MAX_CARDS];
|
|
|
|
double cpuf;
|
|
|
|
extern char uecap_xer[1024];
|
|
char uecap_xer_in=0;
|
|
|
|
int oaisim_flag=0;
|
|
//threads_t threads= {-1,-1,-1,-1,-1,-1,-1,-1};
|
|
|
|
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
|
|
* this is very hackish - find a proper solution
|
|
*/
|
|
uint8_t abstraction_flag=0;
|
|
|
|
/* forward declarations */
|
|
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
|
|
|
|
/*---------------------BMC: timespec helpers -----------------------------*/
|
|
|
|
struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
|
|
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
|
|
|
|
struct timespec clock_difftime(struct timespec start, struct timespec end) {
|
|
struct timespec temp;
|
|
|
|
if ((end.tv_nsec-start.tv_nsec)<0) {
|
|
temp.tv_sec = end.tv_sec-start.tv_sec-1;
|
|
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
|
|
} else {
|
|
temp.tv_sec = end.tv_sec-start.tv_sec;
|
|
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
void print_difftimes(void) {
|
|
#ifdef DEBUG
|
|
printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
|
|
#else
|
|
LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
|
|
#endif
|
|
}
|
|
|
|
void update_difftimes(struct timespec start, struct timespec end) {
|
|
struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
|
|
int changed = 0;
|
|
diff_time = clock_difftime(start, end);
|
|
|
|
if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) {
|
|
min_diff_time.tv_nsec = diff_time.tv_nsec;
|
|
changed = 1;
|
|
}
|
|
|
|
if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) {
|
|
max_diff_time.tv_nsec = diff_time.tv_nsec;
|
|
changed = 1;
|
|
}
|
|
|
|
#if 1
|
|
|
|
if (changed) print_difftimes();
|
|
|
|
#endif
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
|
|
return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
|
|
}
|
|
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
|
|
return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
|
|
}
|
|
|
|
|
|
void exit_function(const char *file, const char *function, const int line, const char *s) {
|
|
int CC_id;
|
|
logClean();
|
|
printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, ((s==NULL)?"":s));
|
|
oai_exit = 1;
|
|
|
|
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
|
if (PHY_vars_UE_g)
|
|
if (PHY_vars_UE_g[0])
|
|
if (PHY_vars_UE_g[0][CC_id])
|
|
if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
|
|
PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
|
|
}
|
|
|
|
sleep(1); //allow lte-softmodem threads to exit first
|
|
|
|
if(PHY_vars_UE_g != NULL )
|
|
itti_terminate_tasks (TASK_UNKNOWN);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
extern int16_t dlsch_demod_shift;
|
|
|
|
static void get_options(void) {
|
|
int CC_id=0;
|
|
int tddflag=0;
|
|
char *loopfile=NULL;
|
|
int dumpframe=0;
|
|
int timingadv=0;
|
|
uint8_t nfapi_mode = NFAPI_MONOLITHIC;
|
|
int simL1flag =0;
|
|
|
|
set_default_frame_parms(frame_parms);
|
|
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
|
|
/* unknown parameters on command line will be checked in main
|
|
after all init have been performed */
|
|
get_common_options(SOFTMODEM_4GUE_BIT );
|
|
get_uethreads_params();
|
|
paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
|
|
paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
|
|
config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL);
|
|
config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL);
|
|
nfapi_setmode(nfapi_mode);
|
|
|
|
if (simL1flag)
|
|
set_softmodem_optmask(SOFTMODEM_SIML1_BIT);
|
|
|
|
if (loopfile != NULL) {
|
|
printf("Input file for hardware emulation: %s",loopfile);
|
|
mode=loop_through_memory;
|
|
input_fd = fopen(loopfile,"r");
|
|
AssertFatal(input_fd != NULL,"Please provide a valid input file\n");
|
|
}
|
|
|
|
get_softmodem_params()->hw_timing_advance = timingadv;
|
|
|
|
if ( (cmdline_uemodeparams[CMDLINE_CALIBUERX_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue;
|
|
|
|
if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXMED_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_med;
|
|
|
|
if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXBYP_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_byp;
|
|
|
|
if (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr)
|
|
if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach;
|
|
|
|
if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr)
|
|
if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0) mode = no_L2_connect;
|
|
|
|
if (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr)
|
|
if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx;
|
|
|
|
if (dumpframe > 0) mode = rx_dump_frame;
|
|
|
|
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
|
frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
|
|
}
|
|
|
|
UE_scan=0;
|
|
|
|
if (tddflag > 0) {
|
|
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
|
frame_parms[CC_id]->frame_type = TDD;
|
|
frame_parms[CC_id]->tdd_config = tddflag;
|
|
}
|
|
}
|
|
|
|
if (frame_parms[0]->N_RB_DL !=0) {
|
|
if ( frame_parms[0]->N_RB_DL < 6 ) {
|
|
frame_parms[0]->N_RB_DL = 6;
|
|
printf ( "%i: Invalid number of ressource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL);
|
|
}
|
|
|
|
if ( frame_parms[0]->N_RB_DL > 100 ) {
|
|
frame_parms[0]->N_RB_DL = 100;
|
|
printf ( "%i: Invalid number of ressource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL);
|
|
}
|
|
|
|
if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) {
|
|
frame_parms[0]->N_RB_DL = 50;
|
|
printf ( "%i: Invalid number of ressource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL);
|
|
}
|
|
|
|
if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) {
|
|
frame_parms[0]->N_RB_DL = 25;
|
|
printf ( "%i: Invalid number of ressource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL);
|
|
}
|
|
|
|
UE_scan = 0;
|
|
frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL;
|
|
|
|
for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
|
|
frame_parms[CC_id]->N_RB_DL=frame_parms[0]->N_RB_DL;
|
|
frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL;
|
|
}
|
|
}
|
|
|
|
for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
|
|
rx_gain[0][CC_id] = rx_gain[0][0];
|
|
tx_gain[0][CC_id] = tx_gain[0][0];
|
|
}
|
|
}
|
|
|
|
|
|
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
|
|
int CC_id;
|
|
|
|
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
|
frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) calloc(1, sizeof(LTE_DL_FRAME_PARMS));
|
|
/* Set some default values that may be overwritten while reading options */
|
|
frame_parms[CC_id]->frame_type = FDD;
|
|
frame_parms[CC_id]->tdd_config = 3;
|
|
frame_parms[CC_id]->tdd_config_S = 0;
|
|
frame_parms[CC_id]->N_RB_DL = 100;
|
|
frame_parms[CC_id]->N_RB_UL = 100;
|
|
frame_parms[CC_id]->Ncp = NORMAL;
|
|
frame_parms[CC_id]->Ncp_UL = NORMAL;
|
|
frame_parms[CC_id]->Nid_cell = 0;
|
|
frame_parms[CC_id]->num_MBSFN_config = 0;
|
|
frame_parms[CC_id]->nb_antenna_ports_eNB = 1;
|
|
frame_parms[CC_id]->nb_antennas_tx = 1;
|
|
frame_parms[CC_id]->nb_antennas_rx = 1;
|
|
frame_parms[CC_id]->nushift = 0;
|
|
frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
|
|
frame_parms[CC_id]->phich_config_common.phich_duration = normal;
|
|
// UL RS Config
|
|
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
|
|
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
|
|
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
|
|
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
|
|
frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
|
|
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
|
|
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
|
|
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
|
|
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
|
|
downlink_frequency[CC_id][0] = DEFAULT_DLF; // Use float to avoid issue with frequency over 2^31.
|
|
downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
|
|
downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
|
|
downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
|
|
frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
|
|
}
|
|
}
|
|
|
|
void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) {
|
|
int card;
|
|
int i;
|
|
|
|
for (card=0; card<MAX_CARDS; card++) {
|
|
openair0_cfg[card].mmapped_dma=mmapped_dma;
|
|
openair0_cfg[card].configFilename = NULL;
|
|
|
|
if(frame_parms->N_RB_DL == 100) {
|
|
if (frame_parms->threequarter_fs) {
|
|
openair0_cfg[card].sample_rate=23.04e6;
|
|
openair0_cfg[card].samples_per_frame = 230400;
|
|
openair0_cfg[card].tx_bw = 10e6;
|
|
openair0_cfg[card].rx_bw = 10e6;
|
|
} else {
|
|
openair0_cfg[card].sample_rate=30.72e6;
|
|
openair0_cfg[card].samples_per_frame = 307200;
|
|
openair0_cfg[card].tx_bw = 10e6;
|
|
openair0_cfg[card].rx_bw = 10e6;
|
|
}
|
|
} else if(frame_parms->N_RB_DL == 50) {
|
|
openair0_cfg[card].sample_rate=15.36e6;
|
|
openair0_cfg[card].samples_per_frame = 153600;
|
|
openair0_cfg[card].tx_bw = 5e6;
|
|
openair0_cfg[card].rx_bw = 5e6;
|
|
} else if (frame_parms->N_RB_DL == 25) {
|
|
openair0_cfg[card].sample_rate=7.68e6;
|
|
openair0_cfg[card].samples_per_frame = 76800;
|
|
openair0_cfg[card].tx_bw = 2.5e6;
|
|
openair0_cfg[card].rx_bw = 2.5e6;
|
|
} else if (frame_parms->N_RB_DL == 6) {
|
|
openair0_cfg[card].sample_rate=1.92e6;
|
|
openair0_cfg[card].samples_per_frame = 19200;
|
|
openair0_cfg[card].tx_bw = 1.5e6;
|
|
openair0_cfg[card].rx_bw = 1.5e6;
|
|
}
|
|
|
|
if (frame_parms->frame_type==TDD)
|
|
openair0_cfg[card].duplex_mode = duplex_mode_TDD;
|
|
else //FDD
|
|
openair0_cfg[card].duplex_mode = duplex_mode_FDD;
|
|
|
|
openair0_cfg[card].Mod_id = 0;
|
|
openair0_cfg[card].num_rb_dl=frame_parms->N_RB_DL;
|
|
openair0_cfg[card].clock_source = get_softmodem_params()->clock_source;
|
|
openair0_cfg[card].time_source = get_softmodem_params()->timing_source;
|
|
openair0_cfg[card].tx_num_channels=min(2,frame_parms->nb_antennas_tx);
|
|
openair0_cfg[card].rx_num_channels=min(2,frame_parms->nb_antennas_rx);
|
|
|
|
for (i=0; i<4; i++) {
|
|
if (i<openair0_cfg[card].tx_num_channels)
|
|
openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
|
|
else
|
|
openair0_cfg[card].tx_freq[i]=0.0;
|
|
|
|
if (i<openair0_cfg[card].rx_num_channels)
|
|
openair0_cfg[card].rx_freq[i] = downlink_frequency[0][i];
|
|
else
|
|
openair0_cfg[card].rx_freq[i]=0.0;
|
|
|
|
openair0_cfg[card].autocal[i] = 1;
|
|
openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
|
|
openair0_cfg[card].rx_gain[i] = rxgain - rx_gain_off;
|
|
openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
|
|
printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
|
|
card,i, openair0_cfg[card].tx_gain[i],
|
|
openair0_cfg[card].rx_gain[i],
|
|
openair0_cfg[card].tx_freq[i],
|
|
openair0_cfg[card].rx_freq[i]);
|
|
}
|
|
|
|
if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* helper function to terminate a certain ITTI task
|
|
*/
|
|
void terminate_task(task_id_t task_id, module_id_t mod_id) {
|
|
LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
|
|
MessageDef *msg;
|
|
msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE);
|
|
itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
|
|
}
|
|
|
|
|
|
static inline void wait_nfapi_init(char *thread_name) {
|
|
printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
|
|
pthread_mutex_lock( &nfapi_sync_mutex );
|
|
|
|
while (nfapi_sync_var<0)
|
|
pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
|
|
|
|
pthread_mutex_unlock(&nfapi_sync_mutex);
|
|
printf( "NFAPI: got sync (%s)\n", thread_name);
|
|
}
|
|
|
|
int stop_L1L2(module_id_t enb_id) {
|
|
return 0;
|
|
}
|
|
|
|
|
|
int restart_L1L2(module_id_t enb_id) {
|
|
return 0;
|
|
}
|
|
|
|
void init_pdcp(void) {
|
|
uint32_t pdcp_initmask = (!IS_SOFTMODEM_NOS1) ? LINK_ENB_PDCP_TO_GTPV1U_BIT : (LINK_ENB_PDCP_TO_GTPV1U_BIT | PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT);
|
|
|
|
if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM || (nfapi_getmode()==NFAPI_UE_STUB_PNF)) {
|
|
pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
|
|
}
|
|
|
|
if (IS_SOFTMODEM_NOKRNMOD)
|
|
pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
|
|
|
|
pdcp_module_init(pdcp_initmask);
|
|
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
|
|
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
|
|
}
|
|
|
|
int main( int argc, char **argv ) {
|
|
int CC_id;
|
|
uint8_t abstraction_flag=0;
|
|
// Default value for the number of UEs. It will hold,
|
|
// if not changed from the command line option --num-ues
|
|
NB_UE_INST=1;
|
|
NB_THREAD_INST=1;
|
|
configmodule_interface_t *config_mod;
|
|
start_background_system();
|
|
config_mod = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY);
|
|
|
|
if (config_mod == NULL) {
|
|
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
|
|
}
|
|
|
|
mode = normal_txrx;
|
|
memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
|
|
set_latency_target();
|
|
logInit();
|
|
printf("Reading in command-line options\n");
|
|
|
|
for (int i=0; i<MAX_NUM_CCs; i++) tx_max_power[i]=23;
|
|
|
|
get_options ();
|
|
|
|
EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
|
|
printf("Running with %d UE instances\n",NB_UE_INST);
|
|
|
|
if (NB_UE_INST > 1 && (!IS_SOFTMODEM_SIML1) && NFAPI_MODE!=NFAPI_UE_STUB_PNF) {
|
|
printf("Running with more than 1 UE instance and simL1 is not active, this will result in undefined behaviour for now, exiting.\n");
|
|
abort();
|
|
}
|
|
|
|
// Checking option of nums_ue_thread.
|
|
if(NB_THREAD_INST < 1) {
|
|
printf("Running with 0 UE rxtx thread, exiting.\n");
|
|
abort();
|
|
}
|
|
|
|
// Checking option's relation between nums_ue_thread and num-ues
|
|
if(NB_UE_INST <NB_THREAD_INST ) {
|
|
printf("Number of UEs < number of UE rxtx threads, exiting.\n");
|
|
abort();
|
|
}
|
|
|
|
#if T_TRACER
|
|
T_Config_Init();
|
|
#endif
|
|
//randominit (0);
|
|
set_taus_seed (0);
|
|
cpuf=get_cpu_freq_GHz();
|
|
pthread_cond_init(&sync_cond,NULL);
|
|
pthread_mutex_init(&sync_mutex, NULL);
|
|
|
|
printf("ITTI init\n");
|
|
itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
|
|
|
|
// initialize mscgen log after ITTI
|
|
if (get_softmodem_params()->start_msc) {
|
|
load_module_shlib("msc",NULL,0,&msc_interface);
|
|
}
|
|
|
|
MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
|
|
init_opt();
|
|
init_pdcp();
|
|
//TTN for D2D
|
|
printf ("RRC control socket\n");
|
|
rrc_control_socket_init();
|
|
printf ("PDCP PC5S socket\n");
|
|
pdcp_pc5_socket_init();
|
|
// to make a graceful exit when ctrl-c is pressed
|
|
set_softmodem_sighandler();
|
|
check_clock();
|
|
#ifndef PACKAGE_VERSION
|
|
# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
|
|
#endif
|
|
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
|
|
|
|
// init the parameters
|
|
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
|
frame_parms[CC_id]->nb_antennas_tx = nb_antenna_tx;
|
|
frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx;
|
|
frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
|
|
}
|
|
|
|
NB_INST=1;
|
|
|
|
if(NFAPI_MODE==NFAPI_UE_STUB_PNF) {
|
|
PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE **)*NB_UE_INST);
|
|
|
|
for (int i=0; i<NB_UE_INST; i++) {
|
|
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
|
PHY_vars_UE_g[i] = malloc(sizeof(PHY_VARS_UE *)*MAX_NUM_CCs);
|
|
PHY_vars_UE_g[i][CC_id] = init_ue_vars(frame_parms[CC_id], i,abstraction_flag);
|
|
|
|
if (get_softmodem_params()->phy_test==1)
|
|
PHY_vars_UE_g[i][CC_id]->mac_enabled = 0;
|
|
else
|
|
PHY_vars_UE_g[i][CC_id]->mac_enabled = 1;
|
|
}
|
|
}
|
|
} else init_openair0(frame_parms[0],(int)rx_gain[0][0]);
|
|
|
|
if (IS_SOFTMODEM_SIML1 ) {
|
|
RCConfig_sim();
|
|
}
|
|
|
|
cpuf=get_cpu_freq_GHz();
|
|
|
|
|
|
#if 0 // #ifndef DEADLINE_SCHEDULER
|
|
|
|
printf("NO deadline scheduler\n");
|
|
/* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
|
|
cpu_set_t cpuset;
|
|
int s;
|
|
char cpu_affinity[1024];
|
|
CPU_ZERO(&cpuset);
|
|
#ifdef CPU_AFFINITY
|
|
int j;
|
|
if (get_nprocs() > 2) {
|
|
for (j = 2; j < get_nprocs(); j++)
|
|
CPU_SET(j, &cpuset);
|
|
|
|
s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
|
|
|
|
if (s != 0) {
|
|
perror( "pthread_setaffinity_np");
|
|
exit_fun("Error setting processor affinity");
|
|
}
|
|
LOG_I(HW, "Setting the affinity of main function to all CPUs, for device library to use CPU 0 only!\n");
|
|
}
|
|
|
|
#endif
|
|
/* Check the actual affinity mask assigned to the thread */
|
|
s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
|
|
|
|
if (s != 0) {
|
|
perror( "pthread_getaffinity_np");
|
|
exit_fun("Error getting processor affinity ");
|
|
}
|
|
|
|
memset(cpu_affinity, 0, sizeof(cpu_affinity));
|
|
|
|
for (int j = 0; j < CPU_SETSIZE; j++) {
|
|
if (CPU_ISSET(j, &cpuset)) {
|
|
char temp[1024];
|
|
sprintf(temp, " CPU_%d ", j);
|
|
strcat(cpu_affinity, temp);
|
|
}
|
|
}
|
|
|
|
LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
|
|
#endif
|
|
|
|
if (create_tasks_ue(NB_UE_INST) < 0) {
|
|
printf("cannot create ITTI tasks\n");
|
|
exit(-1); // need a softer mode
|
|
}
|
|
|
|
if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { // UE-STUB-PNF
|
|
UE_config_stub_pnf();
|
|
}
|
|
|
|
printf("ITTI tasks created\n");
|
|
mlockall(MCL_CURRENT | MCL_FUTURE);
|
|
rt_sleep_ns(10*100000000ULL);
|
|
int eMBMS_active = 0;
|
|
|
|
if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { // UE-STUB-PNF
|
|
config_sync_var=0;
|
|
wait_nfapi_init("main?");
|
|
//Panos: Temporarily we will be using single set of threads for multiple UEs.
|
|
//init_UE_stub(1,eMBMS_active,uecap_xer_in,emul_iface);
|
|
init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
|
|
} else {
|
|
init_UE(NB_UE_INST,eMBMS_active,uecap_xer_in,0,get_softmodem_params()->phy_test,UE_scan,UE_scan_carrier,mode,(int)rx_gain[0][0],tx_max_power[0],
|
|
frame_parms[0]);
|
|
}
|
|
|
|
if (get_softmodem_params()->phy_test==0) {
|
|
printf("Filling UE band info\n");
|
|
fill_ue_band_info();
|
|
dl_phy_sync_success (0, 0, 0, 1);
|
|
}
|
|
|
|
if (NFAPI_MODE != NFAPI_UE_STUB_PNF) {
|
|
number_of_cards = 1;
|
|
|
|
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
|
PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
|
|
PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
|
|
}
|
|
}
|
|
|
|
if (input_fd) {
|
|
printf("Reading in from file to antenna buffer %d\n",0);
|
|
|
|
if (fread(PHY_vars_UE_g[0][0]->common_vars.rxdata[0],
|
|
sizeof(int32_t),
|
|
frame_parms[0]->samples_per_tti*10,
|
|
input_fd) != frame_parms[0]->samples_per_tti*10)
|
|
printf("error reading from file\n");
|
|
}
|
|
|
|
//p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
|
|
|
|
if (IS_SOFTMODEM_SIML1 ) {
|
|
init_ocm();
|
|
PHY_vars_UE_g[0][0]->no_timing_correction = 1;
|
|
}
|
|
|
|
if(IS_SOFTMODEM_DOFORMS)
|
|
load_softscope("ue",NULL);
|
|
|
|
config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
|
|
printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex);
|
|
pthread_mutex_lock(&sync_mutex);
|
|
sync_var=0;
|
|
pthread_cond_broadcast(&sync_cond);
|
|
pthread_mutex_unlock(&sync_mutex);
|
|
printf("sync sent\n");
|
|
/*
|
|
printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
|
|
end_configmodule();
|
|
printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
|
|
*/
|
|
// wait for end of program
|
|
printf("TYPE <CTRL-C> TO TERMINATE\n");
|
|
//getchar();
|
|
printf("Entering ITTI signals handler\n");
|
|
itti_wait_tasks_end();
|
|
printf("Returned from ITTI signal handler\n");
|
|
oai_exit=1;
|
|
printf("oai_exit=%d\n",oai_exit);
|
|
|
|
// stop threads
|
|
if(IS_SOFTMODEM_DOFORMS)
|
|
end_forms();
|
|
|
|
printf("stopping MODEM threads\n");
|
|
pthread_cond_destroy(&sync_cond);
|
|
pthread_mutex_destroy(&sync_mutex);
|
|
|
|
// pthread_mutex_destroy(&ue_pf_po_mutex);
|
|
|
|
// *** Handle per CC_id openair0
|
|
if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func)
|
|
PHY_vars_UE_g[0][0]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][0]->rfdevice);
|
|
|
|
terminate_opt();
|
|
logClean();
|
|
printf("Bye.\n");
|
|
return 0;
|
|
}
|