Files
openairinterface5g/executables/lte-uesoftmodem.c
T
Robert Schmidt 8bffd1666d Avoid complete rebuild on cmake run with git info change
Before this commit, the following will trigger a complete rebuild:

- create another git name (git checkout -b test)
- run cmake again manually (cmake ..)
- run ninja again

The top-level CMakeLists.txt uses add_definitions() to add git
information to all targets; if some git information changes, this will
mark all command lines as dirty, triggering the build.

There is an easy solution: instead of passing this information on the
command line, pass it in a header. This commit uses configure_file() to
generate a file oai_version.h in the build directory with the same
information. Various sources files, e.g., main executables, use this to
output the same information as before. It is then also not necessary to
use header guards, as cmake takes care to create this file.

If cmake is re-run, it will update the header, and trigger only files
including this header will be rebuilt (which can be shown with the above
stpes). The information passed is the same as before, and updates the
information when the old method would have updated it.
2024-08-28 15:57:24 +02:00

781 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>
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#include "assertions.h"
#include "PHY/types.h"
#include "pdcp.h"
#include "PHY/defs_UE.h"
#include "common/oai_version.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 "radio/COMMON/common_lib.h"
#include "radio/ETHERNET/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 "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
#include "PHY_INTERFACE/phy_stub_UE.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 "SIMULATION/TOOLS/sim.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "create_tasks.h"
#include "system.h"
#include "lte-softmodem.h"
#include "executables/softmodem-common.h"
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=4;
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]
int oai_exit = 0;
unsigned int mmapped_dma=0;
UE_MAC_INST *UE_mac_inst = NULL;
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 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];
// 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);
int transmission_mode=1;
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;
/* 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;
bler_struct bler_data[NUM_MCS];
// needed for pdcp.c
RAN_CONTEXT_t RC;
instance_t CUuniqInstance=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, const int assert) {
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);
}
if(PHY_vars_UE_g != NULL )
itti_terminate_tasks (TASK_UNKNOWN);
if (assert) {
abort();
} else {
sleep(1); // allow lte-softmodem threads to exit first
exit(EXIT_SUCCESS);
}
}
extern int16_t dlsch_demod_shift;
uint16_t node_number;
static void get_options(configmodule_interface_t *cfg)
{
int CC_id=0;
int tddflag=0;
int dumpframe = 0;
uint8_t nfapi_mode = NFAPI_MONOLITHIC;
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(cfg, SOFTMODEM_4GUE_BIT);
paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
config_process_cmdline(cfg, cmdline_uemodeparams, sizeofArray(cmdline_uemodeparams), NULL);
config_process_cmdline(cfg, cmdline_ueparams, sizeofArray(cmdline_ueparams), NULL);
nfapi_setmode(nfapi_mode);
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].tune_offset = get_softmodem_params()->tune_offset;
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 %.0f, rx_gain %.0f, tx_freq %.0f, rx_freq %.0f, tune_offset %.0f\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],
openair0_cfg[card].tune_offset);
}
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 (TASK_ENB_APP, 0, 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);
}
static void init_pdcp(int ue_id) {
uint32_t pdcp_initmask = !IS_SOFTMODEM_NOS1 ? LINK_ENB_PDCP_TO_GTPV1U_BIT : LINK_ENB_PDCP_TO_GTPV1U_BIT;
if (IS_SOFTMODEM_RFSIM || (nfapi_getmode()==NFAPI_UE_STUB_PNF)) {
pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
}
// previous code was:
// if (IS_SOFTMODEM_NOKRNMOD)
// pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
// The kernel module (KRNMOD) has been removed from the project, so the 'if'
// was removed but the flag 'pdcp_initmask' was kept, as "no kernel module"
// was always set. further refactoring could take it out
pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
pdcp_module_init(pdcp_initmask, ue_id);
}
// Stupid function addition because UE itti messages queues definition is common with eNB
void *rrc_enb_process_msg(void *notUsed) {
AssertFatal(false,"");
return NULL;
}
int NB_UE_INST = 1;
configmodule_interface_t *uniqCfg = NULL;
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
start_background_system();
uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY);
if (uniqCfg == NULL) {
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
mode = normal_txrx;
memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
logInit();
lock_memory_to_ram();
printf("Reading in command-line options\n");
for (int i=0; i<MAX_NUM_CCs; i++) tx_max_power[i]=23;
get_options(uniqCfg);
if (NFAPI_MODE == NFAPI_MODE_STANDALONE_PNF) {
sf_ahead = 1;
}
printf("sf_ahead = %d\n", sf_ahead);
EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
printf("Running with %d UE instances\n",NB_UE_INST);
#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, tasks_info);
init_opt();
ue_id_g = (node_number == 0) ? 0 : node_number-2; //ue_id_g = 0, 1, ...,
if(node_number == 0)
{
init_pdcp(0);
}
else
{
init_pdcp(node_number-1);
}
//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();
// strdup to put the sring in the core file for post mortem identification
LOG_I(HW, "Version: %s\n", strdup(OAI_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
}
if(NFAPI_MODE==NFAPI_UE_STUB_PNF || NFAPI_MODE==NFAPI_MODE_STANDALONE_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]);
cpuf=get_cpu_freq_GHz();
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 || NFAPI_MODE==NFAPI_MODE_STANDALONE_PNF) { // UE-STUB-PNF
UE_config_stub_pnf();
}
printf("ITTI tasks created\n");
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 if (NFAPI_MODE==NFAPI_MODE_STANDALONE_PNF) {
init_queue(&dl_config_req_tx_req_queue);
init_queue(&hi_dci0_req_queue);
init_queue(&ul_config_req_queue);
init_bler_table();
config_sync_var=0;
if (sem_init(&sfn_semaphore, 0, 0) != 0)
{
LOG_E(MAC, "sem_init() error\n");
abort();
}
init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
init_UE_standalone_thread(ue_id_g);
} 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");
}
if(IS_SOFTMODEM_DOSCOPE)
load_softscope("ue",NULL);
config_check_unknown_cmdlineopt(uniqCfg, 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__);
We have to set properly PARAMFLAG_NOFREE
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(NULL);
printf("Returned from ITTI signal handler\n");
oai_exit=1;
printf("oai_exit=%d\n",oai_exit);
// stop threads
if(IS_SOFTMODEM_DOSCOPE)
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);
pdcp_module_cleanup();
terminate_opt();
logClean();
printf("Bye.\n");
return 0;
}
// Read in each MCS file and build BLER-SINR-TB table
void init_bler_table(void)
{
size_t bufSize = 1024;
char * line = NULL;
char * token;
char * temp = NULL;
const char *openair_dir = getenv("OPENAIR_DIR");
if (!openair_dir)
{
LOG_E(MAC, "No $OPENAIR_DIR\n");
abort();
}
// Maybe not needed... and may not work.
memset(bler_data, 0, sizeof(bler_data));
for (unsigned int i = 0; i < NUM_MCS; i++)
{
char fName[1024];
snprintf(fName, sizeof(fName), "%s/openair1/SIMULATION/LTE_PHY/BLER_SIMULATIONS/AWGN/AWGN_results/bler_tx1_chan18_nrx1_mcs%u.csv", openair_dir, i);
FILE *pFile = fopen(fName, "r");
if (!pFile)
{
LOG_E(MAC, "Bler File ERROR! - fopen(), file: %s\n", fName);
abort();
}
int nlines = 0;
while (getline(&line, &bufSize, pFile) > 0)
{
if (!strncmp(line,"SNR",3))
{
continue;
}
if (nlines > NUM_SINR)
{
LOG_E(MAC, "BLER FILE ERROR - num lines greater than expected - file: %s\n", fName);
abort();
}
token = strtok_r(line, ";", &temp);
int ncols = 0;
while (token != NULL)
{
if (ncols > NUM_BLER_COL)
{
LOG_E(MAC, "BLER FILE ERROR - num of cols greater than expected\n");
abort();
}
bler_data[i].bler_table[nlines][ncols] = strtof(token, NULL);
ncols++;
token = strtok_r(NULL, ";", &temp);
}
nlines++;
}
bler_data[i].length = nlines;
fclose(pFile);
}
}