Merge remote-tracking branch 'origin/move_user_execs' into integration_2022_wk50
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
# include "intertask_interface.h"
|
||||
# include "create_tasks.h"
|
||||
# include "common/utils/LOG/log.h"
|
||||
# include "targets/RT/USER/lte-softmodem.h"
|
||||
# include "executables/lte-softmodem.h"
|
||||
# include "common/ran_context.h"
|
||||
|
||||
#include "sctp_eNB_task.h"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
# include "intertask_interface.h"
|
||||
# include "create_tasks.h"
|
||||
# include "common/utils/LOG/log.h"
|
||||
# include "targets/RT/USER/lte-softmodem.h"
|
||||
# include "executables/lte-softmodem.h"
|
||||
# include "common/ran_context.h"
|
||||
|
||||
#include "sctp_eNB_task.h"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,685 @@
|
||||
/*
|
||||
* 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-softmodem.c
|
||||
* \brief Top-level threads for eNodeB
|
||||
* \author R. Knopp, F. Kaltenberger, Navid Nikaein
|
||||
* \date 2012
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, 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 "PHY/defs_eNB.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/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 <openair1/PHY/phy_extern_ue.h>
|
||||
|
||||
#include "PHY/phy_vars.h"
|
||||
#include "SCHED/sched_common_vars.h"
|
||||
#include "LAYER2/MAC/mac_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/TOOLS/phy_scope_interface.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#ifdef SMBV
|
||||
#include "PHY/TOOLS/smbv.h"
|
||||
unsigned short config_frames[4] = {2,9,11,13};
|
||||
#endif
|
||||
#include "common/utils/LOG/log.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"
|
||||
#include "enb_config.h"
|
||||
|
||||
|
||||
#include "create_tasks.h"
|
||||
|
||||
|
||||
#include "PHY/INIT/phy_init.h"
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "lte-softmodem.h"
|
||||
#include "NB_IoT_interface.h"
|
||||
#include <executables/split_headers.h>
|
||||
|
||||
#if USING_GPROF
|
||||
# include "sys/gmon.h"
|
||||
#endif
|
||||
|
||||
pthread_cond_t nfapi_sync_cond;
|
||||
pthread_mutex_t nfapi_sync_mutex;
|
||||
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
#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] = {{110,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] = {{110,0,0,0},{20,0,0,0}};
|
||||
#endif
|
||||
|
||||
double rx_gain_off = 0.0;
|
||||
|
||||
double sample_rate=30.72e6;
|
||||
double bw = 10.0e6;
|
||||
|
||||
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;
|
||||
int otg_enabled;
|
||||
|
||||
uint64_t num_missed_slots=0; // counter for the number of missed slots
|
||||
|
||||
int split73=0;
|
||||
void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) {
|
||||
AssertFatal(false, "Must not be called in this context\n");
|
||||
}
|
||||
void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) {
|
||||
AssertFatal(false, "Must not be called in this context\n");
|
||||
}
|
||||
|
||||
RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mask,pthread_mutex_t *ru_mutex,pthread_cond_t *ru_cond);
|
||||
|
||||
extern void reset_opp_meas(void);
|
||||
extern void print_opp_meas(void);
|
||||
|
||||
|
||||
RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mask,pthread_mutex_t *ru_mutex,pthread_cond_t *ru_cond);
|
||||
|
||||
int transmission_mode=1;
|
||||
int emulate_rf = 0;
|
||||
int numerology = 0;
|
||||
|
||||
THREAD_STRUCT thread_struct;
|
||||
/* struct for ethernet specific parameters given in eNB conf file */
|
||||
eth_params_t *eth_params;
|
||||
|
||||
double cpuf;
|
||||
|
||||
int oaisim_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 ru_id;
|
||||
|
||||
if (s != NULL) {
|
||||
printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
|
||||
}
|
||||
close_log_mem();
|
||||
oai_exit = 1;
|
||||
|
||||
if (RC.ru == NULL)
|
||||
exit(-1); // likely init not completed, prevent crash or hang, exit now...
|
||||
|
||||
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
if (RC.ru[ru_id] && RC.ru[ru_id]->rfdevice.trx_end_func) {
|
||||
RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
|
||||
RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
|
||||
}
|
||||
|
||||
if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) {
|
||||
RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
|
||||
RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
sleep(1); //allow lte-softmodem threads to exit first
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static void get_options(void) {
|
||||
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
|
||||
get_common_options(SOFTMODEM_ENB_BIT );
|
||||
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
|
||||
|
||||
if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
|
||||
memset((void *)&RC,0,sizeof(RC));
|
||||
/* Read RC configuration file */
|
||||
RCConfig();
|
||||
NB_eNB_INST = RC.nb_inst;
|
||||
printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU);
|
||||
|
||||
if (!IS_SOFTMODEM_NONBIOT) {
|
||||
load_NB_IoT();
|
||||
printf(" nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n",
|
||||
RC.nb_nb_iot_rrc_inst, RC.nb_nb_iot_L1_inst, RC.nb_nb_iot_macrlc_inst);
|
||||
} else {
|
||||
printf("All Nb-IoT instances disabled\n");
|
||||
RC.nb_nb_iot_rrc_inst=RC.nb_nb_iot_L1_inst=RC.nb_nb_iot_macrlc_inst=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 *) malloc(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] = 2680000000; // 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];
|
||||
//printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
|
||||
frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
|
||||
}
|
||||
}
|
||||
|
||||
void wait_RUs(void) {
|
||||
/* do not modify the following LOG_UI message, which is used by CI */
|
||||
LOG_UI(ENB_APP,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
|
||||
// wait for all RUs to be configured over fronthaul
|
||||
pthread_mutex_lock(&RC.ru_mutex);
|
||||
|
||||
while (RC.ru_mask>0) {
|
||||
pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
|
||||
printf("RC.ru_mask:%02lx\n", RC.ru_mask);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&RC.ru_mutex);
|
||||
LOG_I(PHY,"RUs configured\n");
|
||||
}
|
||||
|
||||
void wait_eNBs(void) {
|
||||
int i,j;
|
||||
int waiting=1;
|
||||
|
||||
while (waiting==1) {
|
||||
printf("Waiting for eNB L1 instances to all get configured ... sleeping 50ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
|
||||
usleep(50*1000);
|
||||
waiting=0;
|
||||
|
||||
for (i=0; i<RC.nb_L1_inst; i++) {
|
||||
printf("RC.nb_L1_CC[%d]:%d\n", i, RC.nb_L1_CC[i]);
|
||||
|
||||
for (j=0; j<RC.nb_L1_CC[i]; j++) {
|
||||
if (RC.eNB[i][j]->configured==0) {
|
||||
waiting=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("eNB L1 are configured\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* helper function to terminate a certain ITTI task
|
||||
*/
|
||||
void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) {
|
||||
LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n",
|
||||
itti_get_task_name(from), from, itti_get_task_name(to), to);
|
||||
MessageDef *msg;
|
||||
msg = itti_alloc_new_message (from, 0, TERMINATE_MESSAGE);
|
||||
itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
|
||||
}
|
||||
|
||||
extern void free_transport(PHY_VARS_eNB *);
|
||||
extern void phy_free_RU(RU_t *);
|
||||
|
||||
static void init_pdcp(void) {
|
||||
if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
|
||||
pdcp_layer_init();
|
||||
uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
|
||||
(PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;
|
||||
|
||||
if (IS_SOFTMODEM_NOS1)
|
||||
pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ;
|
||||
|
||||
pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT;
|
||||
|
||||
pdcp_module_init(pdcp_initmask, 0);
|
||||
|
||||
if (NODE_IS_CU(RC.rrc[0]->node_type)) {
|
||||
pdcp_set_rlc_data_req_func(cu_send_to_du);
|
||||
} else {
|
||||
pdcp_set_rlc_data_req_func(rlc_data_req);
|
||||
pdcp_set_pdcp_data_ind_func(pdcp_data_ind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static 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 main ( int argc, char **argv )
|
||||
{
|
||||
int CC_id = 0;
|
||||
int ru_id;
|
||||
int node_type = ngran_eNB;
|
||||
|
||||
start_background_system();
|
||||
|
||||
if ( load_configmodule(argc,argv,0) == NULL) {
|
||||
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
|
||||
}
|
||||
|
||||
mode = normal_txrx;
|
||||
logInit();
|
||||
set_latency_target();
|
||||
printf("Reading in command-line options\n");
|
||||
get_options ();
|
||||
|
||||
EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
|
||||
|
||||
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
|
||||
fprintf(stderr,"Getting configuration failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#if T_TRACER
|
||||
T_Config_Init();
|
||||
#endif
|
||||
//randominit (0);
|
||||
set_taus_seed (0);
|
||||
printf("configuring for RAU/RRU\n");
|
||||
|
||||
if (opp_enabled ==1) {
|
||||
reset_opp_meas();
|
||||
}
|
||||
|
||||
cpuf=get_cpu_freq_GHz();
|
||||
printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED);
|
||||
itti_init(TASK_MAX, tasks_info);
|
||||
|
||||
init_opt();
|
||||
// to make a graceful exit when ctrl-c is pressed
|
||||
set_softmodem_sighandler();
|
||||
#ifndef PACKAGE_VERSION
|
||||
# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
|
||||
#endif
|
||||
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
|
||||
|
||||
/* Read configuration */
|
||||
if (RC.nb_inst > 0) {
|
||||
read_config_and_init();
|
||||
} else {
|
||||
printf("RC.nb_inst = 0, Initializing L1\n");
|
||||
RCconfig_L1();
|
||||
}
|
||||
|
||||
if (RC.nb_inst > 0) {
|
||||
/* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks
|
||||
* for monolithic/F1 modes */
|
||||
init_pdcp();
|
||||
|
||||
if (create_tasks(1) < 0) {
|
||||
printf("cannot create ITTI tasks\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
|
||||
MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ);
|
||||
RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration;
|
||||
itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
|
||||
}
|
||||
node_type = RC.rrc[0]->node_type;
|
||||
}
|
||||
|
||||
if (RC.nb_inst > 0 && NODE_IS_CU(node_type)) {
|
||||
protocol_ctxt_t ctxt;
|
||||
ctxt.module_id = 0 ;
|
||||
ctxt.instance = 0;
|
||||
ctxt.rntiMaybeUEid = 0;
|
||||
ctxt.enb_flag = 1;
|
||||
ctxt.frame = 0;
|
||||
ctxt.subframe = 0;
|
||||
pdcp_run(&ctxt);
|
||||
}
|
||||
|
||||
/* start threads if only L1 or not a CU */
|
||||
if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) {
|
||||
// init UE_PF_PO and mutex lock
|
||||
pthread_mutex_init(&ue_pf_po_mutex, NULL);
|
||||
memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs);
|
||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
pthread_cond_init(&sync_cond,NULL);
|
||||
pthread_mutex_init(&sync_mutex, NULL);
|
||||
|
||||
rt_sleep_ns(10*100000000ULL);
|
||||
|
||||
if (NFAPI_MODE!=NFAPI_MONOLITHIC) {
|
||||
LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
|
||||
pthread_cond_init(&sync_cond,NULL);
|
||||
pthread_mutex_init(&sync_mutex, NULL);
|
||||
}
|
||||
|
||||
if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF
|
||||
#if defined(PRE_SCD_THREAD)
|
||||
init_ru_vnf(); // ru pointer is necessary for pre_scd.
|
||||
#endif
|
||||
wait_nfapi_init("main?");
|
||||
}
|
||||
|
||||
LOG_I(ENB_APP,"START MAIN THREADS\n");
|
||||
// start the main threads
|
||||
number_of_cards = 1;
|
||||
printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
|
||||
|
||||
if (RC.nb_L1_inst > 0) {
|
||||
printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
|
||||
init_eNB(get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
|
||||
}
|
||||
for (int x=0; x < RC.nb_L1_inst; x++)
|
||||
for (int CC_id=0; CC_id<RC.nb_L1_CC[x]; CC_id++) {
|
||||
L1_rxtx_proc_t *L1proc= &RC.eNB[x][CC_id]->proc.L1_proc;
|
||||
L1_rxtx_proc_t *L1proctx= &RC.eNB[x][CC_id]->proc.L1_proc_tx;
|
||||
L1proc->threadPool = (tpool_t *)malloc(sizeof(tpool_t));
|
||||
L1proc->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 )
|
||||
initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true);
|
||||
else
|
||||
initTpool("n", L1proc->threadPool, true);
|
||||
initNotifiedFIFO(L1proc->respDecode);
|
||||
L1proctx->threadPool = L1proc->threadPool;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
printf("wait_eNBs()\n");
|
||||
wait_eNBs();
|
||||
printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
|
||||
|
||||
// RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator.
|
||||
// but RU thread deals with pre_scd and this is necessary in VNF and simulator.
|
||||
// some initialization is necessary and init_ru_vnf do this.
|
||||
if (RC.nb_RU > 0 && NFAPI_MODE != NFAPI_MODE_VNF) {
|
||||
RC.ru = RCconfig_RU(RC.nb_RU, RC.nb_L1_inst, RC.eNB, &RC.ru_mask, &RC.ru_mutex, &RC.ru_cond);
|
||||
LOG_I(PHY,
|
||||
"number of L1 instances %d, number of RU %d, number of CPU cores %d: Initializing RU threads\n",
|
||||
RC.nb_L1_inst, RC.nb_RU, get_nprocs());
|
||||
init_RU(RC.ru,RC.nb_RU,RC.eNB,RC.nb_L1_inst,RC.nb_L1_CC,get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync);
|
||||
|
||||
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
RC.ru[ru_id]->rf_map.card=0;
|
||||
RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
|
||||
}
|
||||
|
||||
config_sync_var=0;
|
||||
|
||||
if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF
|
||||
wait_nfapi_init("main?");
|
||||
}
|
||||
|
||||
printf("wait RUs\n");
|
||||
// end of CI modifications
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
// wait_RUs() is wrong and over complex!
|
||||
wait_RUs();
|
||||
LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU);
|
||||
// once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
|
||||
printf("ALL RUs ready - init eNBs\n");
|
||||
|
||||
if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) {
|
||||
LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n");
|
||||
init_eNB_afterRU();
|
||||
} else {
|
||||
LOG_I(ENB_APP,"NFAPI mode - DO NOT call init_eNB_afterRU()\n");
|
||||
}
|
||||
|
||||
LOG_UI(ENB_APP,"ALL RUs ready - ALL eNBs ready\n");
|
||||
// connect the TX/RX buffers
|
||||
sleep(1); /* wait for thread activation */
|
||||
LOG_I(ENB_APP,"Sending sync to all threads\n");
|
||||
pthread_mutex_lock(&sync_mutex);
|
||||
sync_var=0;
|
||||
pthread_cond_broadcast(&sync_cond);
|
||||
pthread_mutex_unlock(&sync_mutex);
|
||||
config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
|
||||
}
|
||||
|
||||
create_tasks_mbms(1);
|
||||
|
||||
// wait for end of program
|
||||
LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n");
|
||||
// CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
// end of CI modifications
|
||||
//getchar();
|
||||
if(IS_SOFTMODEM_DOSCOPE)
|
||||
load_softscope("enb",NULL);
|
||||
itti_wait_tasks_end();
|
||||
|
||||
#if USING_GPROF
|
||||
// Save the gprof data now (rather than via atexit) in case we crash while shutting down
|
||||
fprintf(stderr, "Recording gprof data...\n");
|
||||
_mcleanup();
|
||||
fprintf(stderr, "Recording gprof data...done\n");
|
||||
#endif // USING_GPROF
|
||||
|
||||
oai_exit=1;
|
||||
LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit);
|
||||
// stop threads
|
||||
|
||||
#if 0 //Disable clean up because this tends to crash (and unnecessary)
|
||||
if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
|
||||
if(IS_SOFTMODEM_DOSCOPE)
|
||||
end_forms();
|
||||
|
||||
LOG_I(ENB_APP,"stopping MODEM threads\n");
|
||||
stop_eNB(NB_eNB_INST);
|
||||
stop_RU(RC.nb_RU);
|
||||
|
||||
/* release memory used by the RU/eNB threads (incomplete), after all
|
||||
* threads have been stopped (they partially use the same memory) */
|
||||
for (int inst = 0; inst < NB_eNB_INST; inst++) {
|
||||
for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) {
|
||||
free_transport(RC.eNB[inst][cc_id]);
|
||||
phy_free_lte_eNB(RC.eNB[inst][cc_id]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int inst = 0; inst < RC.nb_RU; inst++) {
|
||||
phy_free_RU(RC.ru[inst]);
|
||||
}
|
||||
|
||||
free_lte_top();
|
||||
end_configmodule();
|
||||
pthread_cond_destroy(&sync_cond);
|
||||
pthread_mutex_destroy(&sync_mutex);
|
||||
pthread_cond_destroy(&nfapi_sync_cond);
|
||||
pthread_mutex_destroy(&nfapi_sync_mutex);
|
||||
pthread_mutex_destroy(&ue_pf_po_mutex);
|
||||
|
||||
for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
if (RC.ru[ru_id]->rfdevice.trx_end_func) {
|
||||
RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
|
||||
RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
|
||||
}
|
||||
|
||||
if (RC.ru[ru_id]->ifdevice.trx_end_func) {
|
||||
RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
|
||||
RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pdcp_module_cleanup();
|
||||
terminate_opt();
|
||||
logClean();
|
||||
printf("Bye.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
#ifndef LTE_SOFTMODEM_H
|
||||
#define LTE_SOFTMODEM_H
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <execinfo.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syscall.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "radio/COMMON/common_lib.h"
|
||||
//#undef MALLOC
|
||||
#include "assertions.h"
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_eNB.h"
|
||||
#include "PHY/defs_UE.h"
|
||||
#include "s1ap_eNB.h"
|
||||
#include "SIMULATION/ETH_TRANSPORT/proto.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************************************************************/
|
||||
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
|
||||
when calling config_get or config_getlist functions */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters defining UE running mode */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define CMDLINE_UEMODEPARAMS_DESC { \
|
||||
{"calib-ue-rx", CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \
|
||||
{"calib-ue-rx-med", CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \
|
||||
{"calib-ue-rx-byp", CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \
|
||||
{"debug-ue-prach", CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \
|
||||
{"no-L2-connect", CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \
|
||||
{"calib-prach-tx", CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \
|
||||
{"ue-dump-frame", CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \
|
||||
}
|
||||
#define CMDLINE_CALIBUERX_IDX 0
|
||||
#define CMDLINE_CALIBUERXMED_IDX 1
|
||||
#define CMDLINE_CALIBUERXBYP_IDX 2
|
||||
#define CMDLINE_DEBUGUEPRACH_IDX 3
|
||||
#define CMDLINE_NOL2CONNECT_IDX 4
|
||||
#define CMDLINE_CALIBPRACHTX_IDX 5
|
||||
#define CMDLINE_MEMLOOP_IDX 6
|
||||
#define CMDLINE_DUMPMEMORY_IDX 7
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
|
||||
|
||||
|
||||
#define CONFIG_HLP_SIML1 "activate RF simulator instead of HW\n"
|
||||
#define CONFIG_HLP_NUMUE "number of UE instances\n"
|
||||
#define CONFIG_HLP_UERXG "set UE RX gain\n"
|
||||
#define CONFIG_HLP_UERXGOFF "external UE amplifier offset\n"
|
||||
#define CONFIG_HLP_UETXG "set UE TX gain\n"
|
||||
#define CONFIG_HLP_UENANTR "set UE number of rx antennas\n"
|
||||
#define CONFIG_HLP_UENANTT "set UE number of tx antennas\n"
|
||||
#define CONFIG_HLP_UESCAN "set UE to scan around carrier\n"
|
||||
#define CONFIG_HLP_EMULIFACE "Set the interface name for the multicast transport for emulation mode (e.g. eth0, lo, etc.) \n"
|
||||
#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n"
|
||||
#define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n"
|
||||
#define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n"
|
||||
#define CONFIG_HLP_DMAMAP "use DMA memory mapping\n"
|
||||
#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n"
|
||||
#define CONFIG_HLP_TADV "Set timing_advance\n"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters specific to UE */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#define CMDLINE_UEPARAMS_DESC { \
|
||||
{"U", CONFIG_HLP_NUMUE, 0, u16ptr:&NB_UE_INST, defuintval:1, TYPE_UINT16, 0}, \
|
||||
{"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:130, TYPE_DOUBLE, 0}, \
|
||||
{"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&nb_antenna_rx, defuintval:1, TYPE_UINT8, 0}, \
|
||||
{"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&nb_antenna_tx, defuintval:1, TYPE_UINT8, 0}, \
|
||||
{"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&UE_scan_carrier, defintval:0, TYPE_INT, 0}, \
|
||||
{"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:23, TYPE_INT, 0}, \
|
||||
{"emul-iface", CONFIG_HLP_EMULIFACE, 0, strptr:&emul_iface, defstrval:"lo", TYPE_STRING, 100}, \
|
||||
{"L2-emul", NULL, 0, u8ptr:&nfapi_mode, defuintval:3, TYPE_UINT8, 0}, \
|
||||
{"num-ues", NULL, 0, u16ptr:&(NB_UE_INST), defuintval:1, TYPE_UINT16, 0}, \
|
||||
{"nums_ue_thread", NULL, 0, u16ptr:&(NB_THREAD_INST), defuintval:1, TYPE_UINT16, 0}, \
|
||||
{"r" , CONFIG_HLP_PRB, 0, u8ptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT8, 0}, \
|
||||
{"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \
|
||||
{"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:&usrp_args, defstrval:"type=b200",TYPE_STRING, 0}, \
|
||||
{"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \
|
||||
{"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \
|
||||
{"A", CONFIG_HLP_TADV, 0, iptr:&(timingadv), defintval:0, TYPE_INT, 0}, \
|
||||
{"ue-idx-standalone", NULL, 0, u16ptr:&ue_idx_standalone, defuintval:0xFFFF, TYPE_UINT16, 0}, \
|
||||
{"node-number", NULL, 0, u16ptr:&node_number, defuintval:2, TYPE_UINT16, 0}, \
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters specific to UE threads */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
|
||||
#define DEFAULT_DLF 2680000000
|
||||
|
||||
|
||||
uint64_t get_pdcp_optmask(void);
|
||||
extern pthread_cond_t sync_cond;
|
||||
extern pthread_mutex_t sync_mutex;
|
||||
extern int sync_var;
|
||||
|
||||
extern uint16_t ue_id_g;
|
||||
extern uint16_t node_number;
|
||||
|
||||
extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
|
||||
extern int rx_input_level_dBm;
|
||||
extern uint64_t num_missed_slots; // counter for the number of missed slots
|
||||
|
||||
extern int oaisim_flag;
|
||||
extern int oai_exit;
|
||||
|
||||
extern openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
extern pthread_cond_t sync_cond;
|
||||
extern pthread_mutex_t sync_mutex;
|
||||
extern int sync_var;
|
||||
extern int transmission_mode;
|
||||
extern double cpuf;
|
||||
|
||||
extern int emulate_rf;
|
||||
extern int numerology;
|
||||
extern int usrp_tx_thread;
|
||||
|
||||
// In lte-enb.c
|
||||
extern void stop_eNB(int);
|
||||
extern void kill_eNB_proc(int inst);
|
||||
extern void init_eNB(int single_thread_flag, int wait_for_sync);
|
||||
|
||||
// In lte-ru.c
|
||||
extern void stop_ru(RU_t *ru);
|
||||
extern void init_ru_vnf(void);
|
||||
extern void init_RU_proc(RU_t *ru);
|
||||
extern void stop_RU(int nb_ru);
|
||||
extern void kill_RU_proc(RU_t *ru);
|
||||
extern void set_function_spec_param(RU_t *ru);
|
||||
extern void init_RU(RU_t **rup,int nb_RU,PHY_VARS_eNB ***eNBp,int nb_L1,int *nb_CC,char *rf_config_file, int send_dmrssync);
|
||||
|
||||
// In lte-ue.c
|
||||
extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
|
||||
extern void fill_ue_band_info(void);
|
||||
|
||||
extern void init_UE(int nb_inst,
|
||||
int eMBMS_active,
|
||||
int uecap_xer_in,
|
||||
int timing_correction,
|
||||
int phy_test,
|
||||
int UE_scan,
|
||||
int UE_scan_carrier,
|
||||
runmode_t mode,
|
||||
int rxgain,
|
||||
int txpowermax,
|
||||
LTE_DL_FRAME_PARMS *fp);
|
||||
|
||||
extern void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char *name);
|
||||
|
||||
extern void reset_opp_meas(void);
|
||||
extern void print_opp_meas(void);
|
||||
|
||||
extern void init_td_thread(PHY_VARS_eNB *);
|
||||
extern void init_te_thread(PHY_VARS_eNB *);
|
||||
extern void kill_td_thread(PHY_VARS_eNB *);
|
||||
extern void kill_te_thread(PHY_VARS_eNB *);
|
||||
|
||||
extern void init_ocm(void);
|
||||
extern void init_ue_devices(PHY_VARS_UE *);
|
||||
|
||||
PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
|
||||
|
||||
void init_eNB_afterRU(void);
|
||||
|
||||
extern void init_UE_stub_single_thread(int nb_inst, int eMBMS_active, int uecap_xer_in, char *emul_iface);
|
||||
extern void init_UE_standalone_thread(int ue_idx);
|
||||
|
||||
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
|
||||
|
||||
extern void init_bler_table(void);
|
||||
void feptx_ofdm_2thread(RU_t *ru,
|
||||
int frame,
|
||||
int subframe);
|
||||
void* ru_thread_control( void* param );
|
||||
void wait_eNBs(void);
|
||||
void kill_feptx_thread(RU_t *ru);
|
||||
void init_fep_thread(RU_t *ru, pthread_attr_t *attr_fep);
|
||||
void init_feptx_thread(RU_t *ru, pthread_attr_t *attr_feptx);
|
||||
void fep_full(RU_t *ru, int subframe);
|
||||
void configure_ru(int, void *arg);
|
||||
void configure_rru(int, void *arg);
|
||||
void ru_fep_full_2thread(RU_t *ru,int subframe);
|
||||
void feptx_ofdm(RU_t*ru, int frame_tx, int tti_tx);
|
||||
void feptx_prec(struct RU_t_s *ru, int frame_tx, int tti_tx);
|
||||
void fill_rf_config(RU_t *ru, char *rf_config_file);
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,803 @@
|
||||
/*
|
||||
* 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 "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 "radio/COMMON/common_lib.h"
|
||||
#include "radio/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_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 "UTIL/MATH/oml.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"
|
||||
|
||||
/* temporary compilation wokaround (UE/eNB split */
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
int oaisim_flag=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) {
|
||||
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;
|
||||
uint16_t node_number;
|
||||
static void get_options(void) {
|
||||
int CC_id=0;
|
||||
int tddflag=0;
|
||||
int dumpframe=0;
|
||||
int timingadv=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(SOFTMODEM_4GUE_BIT );
|
||||
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);
|
||||
|
||||
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].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 (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 | PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT);
|
||||
|
||||
if (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, ue_id);
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 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);
|
||||
logInit();
|
||||
set_latency_target();
|
||||
printf("Reading in command-line options\n");
|
||||
|
||||
for (int i=0; i<MAX_NUM_CCs; i++) tx_max_power[i]=23;
|
||||
|
||||
get_options ();
|
||||
|
||||
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);
|
||||
|
||||
// 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, 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();
|
||||
#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 || 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");
|
||||
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 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(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();
|
||||
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%d.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);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include <common/utils/system.h>
|
||||
#include <common/config/config_userapi.h>
|
||||
#include <targets/RT/USER/lte-softmodem.h>
|
||||
#include "executables/lte-softmodem.h"
|
||||
#include <openair1/PHY/defs_eNB.h>
|
||||
#include <openair1/PHY/phy_extern.h>
|
||||
#include <nfapi/oai_integration/vendor_ext.h>
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
/*
|
||||
* This file replaces
|
||||
* targets/RT/USER/lte-softmodem.c
|
||||
* targets/RT/USER/rt_wrapper.c
|
||||
* targets/RT/USER/lte-ru.c
|
||||
* targets/RT/USER/lte-enb.c
|
||||
* targets/RT/USER/ru_control.c
|
||||
* executables/lte-softmodem.c
|
||||
* executables/rt_wrapper.c
|
||||
* executables/lte-ru.c
|
||||
* executables/lte-enb.c
|
||||
* executables/ru_control.c
|
||||
* openair1/SCHED/prach_procedures.c
|
||||
* The merger of OpenAir central code to this branch
|
||||
* should check if these 3 files are modified and analyze if code code has to be copied in here
|
||||
@@ -42,7 +42,7 @@
|
||||
static int DEFBANDS[] = {7};
|
||||
static int DEFENBS[] = {0};
|
||||
#include <common/config/config_userapi.h>
|
||||
#include <targets/RT/USER/lte-softmodem.h>
|
||||
#include "executables/lte-softmodem.h"
|
||||
#include <openair1/PHY/defs_eNB.h>
|
||||
#include <openair1/PHY/phy_extern.h>
|
||||
#include <nfapi/oai_integration/vendor_ext.h>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
#include "PHY_INTERFACE/phy_interface_vars.h"
|
||||
#include "gnb_config.h"
|
||||
#include "SIMULATION/TOOLS/sim.h"
|
||||
#include <targets/RT/USER/lte-softmodem.h>
|
||||
#include "executables/lte-softmodem.h"
|
||||
|
||||
#ifdef SMBV
|
||||
#include "PHY/TOOLS/smbv.h"
|
||||
|
||||
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
* 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 rfsim.c
|
||||
* \brief function for simulated RF device
|
||||
* \author R. Knopp
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
* \company Eurecom
|
||||
* \email: openair_tech@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <execinfo.h>
|
||||
#include <time.h>
|
||||
#include <mcheck.h>
|
||||
#include <sys/timerfd.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "rfsim.h"
|
||||
#include "openair1/SIMULATION/TOOLS/sim.h"
|
||||
#include "enb_config.h"
|
||||
#include "enb_paramdef.h"
|
||||
#include "platform_constants.h"
|
||||
#include "common/config/config_paramdesc.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "PHY/defs_UE.h"
|
||||
#include "PHY/defs_eNB.h"
|
||||
#include "PHY/defs_RU.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
RAN_CONTEXT_t RC;
|
||||
extern PHY_VARS_UE ***PHY_vars_UE_g;
|
||||
|
||||
|
||||
// put all of these in a common structure after
|
||||
sim_t sim;
|
||||
|
||||
|
||||
void init_ru_devices(void);
|
||||
|
||||
void init_RU(char *,int send_dmrssync);
|
||||
|
||||
void *rfsim_top(void *n_frames);
|
||||
|
||||
void wait_RUs(void) {
|
||||
int i;
|
||||
// wait for all RUs to be configured over fronthaul
|
||||
pthread_mutex_lock(&RC.ru_mutex);
|
||||
|
||||
while (RC.ru_mask>0) {
|
||||
pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&RC.ru_mutex);
|
||||
|
||||
// copy frame parameters from RU to UEs
|
||||
for (i=0; i<NB_UE_INST; i++) {
|
||||
sim.current_UE_rx_timestamp[i][0] = RC.ru[0]->frame_parms->samples_per_tti + RC.ru[0]->frame_parms->ofdm_symbol_size + RC.ru[0]->frame_parms->nb_prefix_samples0;
|
||||
}
|
||||
|
||||
for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) sim.current_ru_rx_timestamp[ru_id][0] = RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
|
||||
printf("RUs are ready, let's go\n");
|
||||
}
|
||||
|
||||
void wait_eNBs(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void RCConfig_sim(void) {
|
||||
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
|
||||
// Get num RU instances
|
||||
config_getlist( &RUParamList,NULL,0, NULL);
|
||||
RC.nb_RU = RUParamList.numelt;
|
||||
AssertFatal(RC.nb_RU>0,"we need at least 1 RU for simulation\n");
|
||||
printf("returned with %d rus\n",RC.nb_RU);
|
||||
init_RU(NULL,0);
|
||||
printf("Waiting for RUs to get set up\n");
|
||||
wait_RUs();
|
||||
init_ru_devices();
|
||||
static int nframes = 100000;
|
||||
AssertFatal(0 == pthread_create(&sim.rfsim_thread,
|
||||
NULL,
|
||||
rfsim_top,
|
||||
(void *)&nframes), "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ru_trx_start(openair0_device *device) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
void ru_trx_end(openair0_device *device) {
|
||||
return;
|
||||
}
|
||||
|
||||
int ru_trx_stop(openair0_device *device) {
|
||||
return(0);
|
||||
}
|
||||
int UE_trx_start(openair0_device *device) {
|
||||
return(0);
|
||||
}
|
||||
void UE_trx_end(openair0_device *device) {
|
||||
return;
|
||||
}
|
||||
int UE_trx_stop(openair0_device *device) {
|
||||
return(0);
|
||||
}
|
||||
int ru_trx_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dummy) {
|
||||
return(0);
|
||||
}
|
||||
int ru_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
return(0);
|
||||
}
|
||||
int UE_trx_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dummy) {
|
||||
return(0);
|
||||
}
|
||||
int UE_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
extern pthread_mutex_t subframe_mutex;
|
||||
extern int subframe_ru_mask,subframe_UE_mask;
|
||||
|
||||
|
||||
int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
|
||||
int ru_id = device->Mod_id;
|
||||
int CC_id = device->CC_id;
|
||||
int subframe;
|
||||
int sample_count=0;
|
||||
*ptimestamp = sim.last_ru_rx_timestamp[ru_id][CC_id];
|
||||
LOG_D(SIM,"RU_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps,
|
||||
(unsigned long long)sim.current_ru_rx_timestamp[ru_id][CC_id],
|
||||
(unsigned long long)sim.last_ru_rx_timestamp[ru_id][CC_id],
|
||||
(int)((*ptimestamp/RC.ru[ru_id]->frame_parms->samples_per_tti)%10));
|
||||
|
||||
// if we're at a subframe boundary generate UL signals for this ru
|
||||
|
||||
while (sample_count<nsamps) {
|
||||
while (sim.current_ru_rx_timestamp[ru_id][CC_id]<
|
||||
(nsamps+sim.last_ru_rx_timestamp[ru_id][CC_id])) {
|
||||
LOG_D(SIM,"RU: current TS %"PRIi64", last TS %"PRIi64", sleeping\n",sim.current_ru_rx_timestamp[ru_id][CC_id],sim.last_ru_rx_timestamp[ru_id][CC_id]);
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
subframe = (sim.last_ru_rx_timestamp[ru_id][CC_id]/RC.ru[ru_id]->frame_parms->samples_per_tti)%10;
|
||||
|
||||
if (subframe_select(RC.ru[ru_id]->frame_parms,subframe) != SF_DL || RC.ru[ru_id]->frame_parms->frame_type == FDD) {
|
||||
LOG_D(SIM,"RU_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
|
||||
subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)sim.current_ru_rx_timestamp[ru_id][CC_id]);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,1);
|
||||
do_UL_sig(&sim,
|
||||
subframe,
|
||||
0, // abstraction_flag
|
||||
RC.ru[ru_id]->frame_parms,
|
||||
0, // frame is only used for abstraction
|
||||
ru_id,
|
||||
CC_id);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,0);
|
||||
}
|
||||
|
||||
sim.last_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
sample_count += RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
}
|
||||
|
||||
return(nsamps);
|
||||
}
|
||||
|
||||
int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,1);
|
||||
int UE_id = device->Mod_id;
|
||||
int CC_id = device->CC_id;
|
||||
int subframe;
|
||||
int sample_count=0;
|
||||
int read_size;
|
||||
int sptti = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;
|
||||
*ptimestamp = sim.last_UE_rx_timestamp[UE_id][CC_id];
|
||||
LOG_D(PHY,"UE %d DL simulation 0: UE_trx_read nsamps %d TS %llu (%llu, offset %d) antenna %d\n",
|
||||
UE_id,
|
||||
nsamps,
|
||||
(unsigned long long)sim.current_UE_rx_timestamp[UE_id][CC_id],
|
||||
(unsigned long long)sim.last_UE_rx_timestamp[UE_id][CC_id],
|
||||
(int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti),
|
||||
cc);
|
||||
|
||||
if (nsamps < sptti)
|
||||
read_size = nsamps;
|
||||
else
|
||||
read_size = sptti;
|
||||
|
||||
while (sample_count<nsamps) {
|
||||
LOG_D(SIM,"UE %d: DL simulation 1: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
|
||||
|
||||
while (sim.current_UE_rx_timestamp[UE_id][CC_id] <
|
||||
(sim.last_UE_rx_timestamp[UE_id][CC_id]+read_size)) {
|
||||
LOG_D(SIM,"UE %d: DL simulation 2: UE_trx_read : current TS %"PRIi64", last TS %"PRIi64", sleeping\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
LOG_D(SIM,"UE %d: DL simulation 3: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
|
||||
// if we cross a subframe-boundary
|
||||
subframe = (sim.last_UE_rx_timestamp[UE_id][CC_id]/sptti)%10;
|
||||
// tell top-level we are busy
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
sim.subframe_UE_mask|=(1<<UE_id);
|
||||
LOG_D(SIM,"Setting UE_id %d mask to busy (%d)\n",UE_id,sim.subframe_UE_mask);
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
LOG_D(PHY,"UE %d: DL simulation 4: UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu,nsamps %d)\n",
|
||||
UE_id,subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)sim.current_UE_rx_timestamp[UE_id][CC_id],
|
||||
nsamps);
|
||||
LOG_D(SIM,"UE %d: DL simulation 5: Doing DL simulation for %d samples starting in subframe %d at offset %d\n",
|
||||
UE_id,nsamps,subframe,
|
||||
(int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti));
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_DL_SIGNAL,1);
|
||||
do_DL_sig(&sim,
|
||||
subframe,
|
||||
sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti,
|
||||
sptti,
|
||||
0, //abstraction_flag,
|
||||
&PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
|
||||
UE_id,
|
||||
CC_id);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_DL_SIGNAL,0);
|
||||
LOG_D(PHY,"UE %d: DL simulation 6: UE_trx_read @ TS %"PRIi64" (%"PRIi64")=> frame %d, subframe %d\n",
|
||||
UE_id, sim.current_UE_rx_timestamp[UE_id][CC_id],
|
||||
sim.last_UE_rx_timestamp[UE_id][CC_id],
|
||||
(int)((sim.last_UE_rx_timestamp[UE_id][CC_id]/(sptti*10))&1023),
|
||||
subframe);
|
||||
sim.last_UE_rx_timestamp[UE_id][CC_id] += read_size;
|
||||
sample_count += read_size;
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,0);
|
||||
return(nsamps);
|
||||
}
|
||||
|
||||
|
||||
int ru_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
|
||||
int ru_id = device->Mod_id;
|
||||
LTE_DL_FRAME_PARMS *frame_parms = RC.ru[ru_id]->frame_parms;
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
LOG_D(SIM,"[TXPATH] ru_trx_write: RU %d mask %d\n",ru_id,sim.subframe_ru_mask);
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
// compute amplitude of TX signal from first symbol in subframe
|
||||
// note: assumes that the packet is an entire subframe
|
||||
sim.ru_amp[ru_id] = 0;
|
||||
|
||||
for (int aa=0; aa<RC.ru[ru_id]->nb_tx; aa++) {
|
||||
sim.ru_amp[ru_id] += (double)signal_energy((int32_t *)buff[aa],frame_parms->ofdm_symbol_size)/(12*frame_parms->N_RB_DL);
|
||||
}
|
||||
|
||||
sim.ru_amp[ru_id] = sqrt(sim.ru_amp[ru_id]);
|
||||
LOG_D(PHY,"Setting amp for RU %d to %f (%d)\n",ru_id,sim.ru_amp[ru_id], dB_fixed((double)signal_energy((int32_t *)buff[0],frame_parms->ofdm_symbol_size)));
|
||||
// tell top-level we are done
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
sim.subframe_ru_mask|=(1<<ru_id);
|
||||
LOG_D(SIM,"Setting RU %d to busy\n",ru_id);
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
return(nsamps);
|
||||
}
|
||||
|
||||
int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
|
||||
return(nsamps);
|
||||
}
|
||||
|
||||
void init_ru_devices() {
|
||||
module_id_t ru_id;
|
||||
RU_t *ru;
|
||||
|
||||
// allocate memory for RU if not already done
|
||||
if (RC.ru==NULL) RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *));
|
||||
|
||||
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
LOG_D(SIM,"Initiaizing rfdevice for RU %d\n",ru_id);
|
||||
|
||||
if (RC.ru[ru_id]==NULL) RC.ru[ru_id] = (RU_t *)malloc(sizeof(RU_t));
|
||||
|
||||
ru = RC.ru[ru_id];
|
||||
ru->rfdevice.Mod_id = ru_id;
|
||||
ru->rfdevice.CC_id = 0;
|
||||
ru->rfdevice.trx_start_func = ru_trx_start;
|
||||
ru->rfdevice.trx_read_func = ru_trx_read;
|
||||
ru->rfdevice.trx_write_func = ru_trx_write;
|
||||
ru->rfdevice.trx_end_func = ru_trx_end;
|
||||
ru->rfdevice.trx_stop_func = ru_trx_stop;
|
||||
ru->rfdevice.trx_set_freq_func = ru_trx_set_freq;
|
||||
ru->rfdevice.trx_set_gains_func = ru_trx_set_gains;
|
||||
sim.last_ru_rx_timestamp[ru_id][0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void init_ue_devices(PHY_VARS_UE *UE) {
|
||||
AssertFatal(UE!=NULL,"UE context is not allocated\n");
|
||||
printf("Initializing UE %d.%d\n",UE->Mod_id,UE->CC_id);
|
||||
UE->rfdevice.Mod_id = UE->Mod_id;
|
||||
UE->rfdevice.CC_id = UE->CC_id;
|
||||
UE->rfdevice.trx_start_func = UE_trx_start;
|
||||
UE->rfdevice.trx_read_func = UE_trx_read;
|
||||
UE->rfdevice.trx_write_func = UE_trx_write;
|
||||
UE->rfdevice.trx_end_func = UE_trx_end;
|
||||
UE->rfdevice.trx_stop_func = UE_trx_stop;
|
||||
UE->rfdevice.trx_set_freq_func = UE_trx_set_freq;
|
||||
UE->rfdevice.trx_set_gains_func = UE_trx_set_gains;
|
||||
sim.last_UE_rx_timestamp[UE->Mod_id][UE->CC_id] = 0;
|
||||
}
|
||||
|
||||
void init_ocm(void) {
|
||||
module_id_t UE_id, ru_id;
|
||||
int CC_id;
|
||||
double DS_TDL = .03;
|
||||
randominit(0);
|
||||
set_taus_seed(0);
|
||||
init_channelmod();
|
||||
double snr_dB = channelmod_get_snr_dB();
|
||||
double sinr_dB = channelmod_get_sinr_dB();
|
||||
init_channel_vars ();//fp, &s_re, &s_im, &r_re, &r_im, &r_re0, &r_im0);
|
||||
// initialize channel descriptors
|
||||
LOG_I(PHY,"Initializing channel descriptors (nb_RU %d, nb_UE %d)\n",RC.nb_RU,NB_UE_INST);
|
||||
|
||||
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
|
||||
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
LOG_I(PHY,"Initializing channel descriptors (RU %d, UE %d) for N_RB_DL %d\n",ru_id,UE_id,
|
||||
RC.ru[ru_id]->frame_parms->N_RB_DL);
|
||||
sim.RU2UE[ru_id][UE_id][CC_id] =
|
||||
new_channel_desc_scm(RC.ru[ru_id]->nb_tx,
|
||||
PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_rx,
|
||||
AWGN,
|
||||
N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_DL),
|
||||
N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_DL),
|
||||
DS_TDL,
|
||||
CORR_LEVEL_LOW,
|
||||
0.0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
random_channel(sim.RU2UE[ru_id][UE_id][CC_id],0);
|
||||
LOG_D(OCM,"[SIM] Initializing channel (%s) from UE %d to ru %d\n", "AWGN", UE_id, ru_id);
|
||||
|
||||
sim.UE2RU[UE_id][ru_id][CC_id] =
|
||||
new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx,
|
||||
RC.ru[ru_id]->nb_rx,
|
||||
AWGN,
|
||||
N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_UL),
|
||||
N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_UL),
|
||||
DS_TDL,
|
||||
CORR_LEVEL_LOW,
|
||||
0.0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
random_channel(sim.UE2RU[UE_id][ru_id][CC_id],0);
|
||||
// to make channel reciprocal uncomment following line instead of previous. However this only works for SISO at the moment. For MIMO the channel would need to be transposed.
|
||||
//UE2RU[UE_id][ru_id] = RU2UE[ru_id][UE_id];
|
||||
AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
|
||||
AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
|
||||
|
||||
//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
|
||||
if (ru_id == (UE_id % RC.nb_RU)) {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
} else {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
}
|
||||
|
||||
LOG_I(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
|
||||
RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower,
|
||||
snr_dB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void update_ocm(double snr_dB,double sinr_dB) {
|
||||
module_id_t UE_id, ru_id;
|
||||
int CC_id;
|
||||
|
||||
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
|
||||
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
|
||||
AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
|
||||
|
||||
//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
|
||||
if (ru_id == (UE_id % RC.nb_RU)) {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
} else {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
}
|
||||
|
||||
LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
|
||||
RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower,
|
||||
snr_dB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void init_channel_vars(void) {
|
||||
int i;
|
||||
memset(sim.RU_output_mask,0,sizeof(int)*NUMBER_OF_UE_MAX);
|
||||
|
||||
for (i=0; i<NB_UE_INST; i++)
|
||||
pthread_mutex_init(&sim.RU_output_mutex[i],NULL);
|
||||
|
||||
memset(sim.UE_output_mask,0,sizeof(int)*NUMBER_OF_RU_MAX);
|
||||
|
||||
for (i=0; i<RC.nb_RU; i++)
|
||||
pthread_mutex_init(&sim.UE_output_mutex[i],NULL);
|
||||
}
|
||||
|
||||
|
||||
void *rfsim_top(void *n_frames) {
|
||||
wait_sync("rfsim_top");
|
||||
printf("Running rfsim with %d frames\n",*(int *)n_frames);
|
||||
|
||||
for (int frame = 0; frame < *(int *)n_frames; frame++) {
|
||||
for (int sf = 0; sf < 10; sf++) {
|
||||
int CC_id=0;
|
||||
int all_done=0;
|
||||
|
||||
while (all_done==0) {
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
int subframe_ru_mask_local = (subframe_select(RC.ru[0]->frame_parms,(sf+4)%10)!=SF_UL) ? sim.subframe_ru_mask : ((1<<RC.nb_RU)-1);
|
||||
int subframe_UE_mask_local = (RC.ru[0]->frame_parms->frame_type == FDD || subframe_select(RC.ru[0]->frame_parms,(sf+4)%10)!=SF_DL) ? sim.subframe_UE_mask : ((1<<NB_UE_INST)-1);
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
LOG_D(SIM,"Frame %d, Subframe %d, NB_RU %d, NB_UE %d: Checking masks %x,%x\n",frame,sf,RC.nb_RU,NB_UE_INST,subframe_ru_mask_local,subframe_UE_mask_local);
|
||||
|
||||
if ((subframe_ru_mask_local == ((1<<RC.nb_RU)-1)) &&
|
||||
(subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) all_done=1;
|
||||
else usleep(1500);
|
||||
}
|
||||
|
||||
//clear subframe masks for next round
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
sim.subframe_ru_mask=0;
|
||||
sim.subframe_UE_mask=0;
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
|
||||
// increment timestamps
|
||||
|
||||
for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
sim.current_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
LOG_D(SIM,"RU %d/%d: TS %"PRIi64"\n",ru_id,CC_id,sim.current_ru_rx_timestamp[ru_id][CC_id]);
|
||||
}
|
||||
|
||||
for (int UE_inst = 0; UE_inst<NB_UE_INST; UE_inst++) {
|
||||
sim.current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
|
||||
LOG_D(SIM,"UE %d/%d: TS %"PRIi64"\n",UE_inst,CC_id,sim.current_UE_rx_timestamp[UE_inst][CC_id]);
|
||||
}
|
||||
|
||||
if (oai_exit == 1) return((void *)NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return((void *)NULL);
|
||||
}
|
||||
@@ -0,0 +1,770 @@
|
||||
/*
|
||||
* 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 ru_control.c
|
||||
* \brief Top-level threads for RU entity
|
||||
* \author R. Knopp, F. Kaltenberger, Navid Nikaein
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sched.h>
|
||||
#include <linux/sched.h>
|
||||
#include <signal.h>
|
||||
#include <execinfo.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/sysinfo.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 "PHY/defs_common.h"
|
||||
#undef MALLOC //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/USERSPACE/LIB/ethernet_lib.h"
|
||||
|
||||
#include "PHY/LTE_TRANSPORT/if4_tools.h"
|
||||
|
||||
#include "PHY/LTE_TRANSPORT/transport_proto.h"
|
||||
#include "SCHED/sched_eNB.h"
|
||||
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
|
||||
#include "PHY/INIT/phy_init.h"
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
|
||||
int attach_rru(RU_t *ru);
|
||||
void configure_ru(RU_t *ru, void *arg);
|
||||
void configure_rru(RU_t *ru, void *arg);
|
||||
void fill_rf_config(RU_t *ru, char *rf_config_file);
|
||||
void* ru_thread_control( void* param );
|
||||
|
||||
extern int setup_RU_buffers(RU_t *ru);
|
||||
extern void reset_proc(RU_t *ru);
|
||||
extern void phy_init_RU(RU_t*);
|
||||
|
||||
extern const char ru_states[6][9];
|
||||
const char rru_format_options[4][20] = {"OAI_IF5_only","OAI_IF4p5_only","OAI_IF5_and_IF4p5","MBP_IF5"};
|
||||
const char rru_formats[3][20] = {"OAI_IF5","MBP_IF5","OAI_IF4p5"};
|
||||
const char ru_if_formats[4][20] = {"LOCAL_RF","REMOTE_OAI_IF5","REMOTE_MBP_IF5","REMOTE_OAI_IF4p5"};
|
||||
|
||||
extern int oai_exit;
|
||||
extern void wait_eNBs(void);
|
||||
|
||||
int send_tick(RU_t *ru)
|
||||
{
|
||||
RRU_CONFIG_msg_t rru_config_msg;
|
||||
|
||||
rru_config_msg.type = RAU_tick;
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
|
||||
|
||||
LOG_I(PHY,"Sending RAU tick to RRU %d\n",ru->idx);
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
|
||||
"RU %d cannot access remote radio\n",ru->idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int send_config(RU_t *ru,
|
||||
RRU_CONFIG_msg_t rru_config_msg)
|
||||
{
|
||||
rru_config_msg.type = RRU_config;
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
|
||||
|
||||
LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d\n",
|
||||
ru->idx,
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
|
||||
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
|
||||
"RU %d failed send configuration to remote radio\n",ru->idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int send_capab(RU_t *ru)
|
||||
{
|
||||
RRU_CONFIG_msg_t rru_config_msg;
|
||||
RRU_capabilities_t *cap;
|
||||
int i=0;
|
||||
|
||||
rru_config_msg.type = RRU_capabilities;
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
|
||||
cap = (RRU_capabilities_t*)&rru_config_msg.msg[0];
|
||||
LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",
|
||||
(int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx);
|
||||
switch (ru->function) {
|
||||
case NGFI_RRU_IF4p5:
|
||||
cap->FH_fmt = OAI_IF4p5_only;
|
||||
break;
|
||||
case NGFI_RRU_IF5:
|
||||
cap->FH_fmt = OAI_IF5_only;
|
||||
break;
|
||||
case MBP_RRU_IF5:
|
||||
cap->FH_fmt = MBP_IF5;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"RU_function is unknown %d\n",ru->function);
|
||||
break;
|
||||
}
|
||||
cap->num_bands = ru->num_bands;
|
||||
for (i=0;i<ru->num_bands;i++) {
|
||||
LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n",
|
||||
ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain);
|
||||
cap->band_list[i] = ru->band[i];
|
||||
cap->nb_rx[i] = ru->nb_rx;
|
||||
cap->nb_tx[i] = ru->nb_tx;
|
||||
cap->max_pdschReferenceSignalPower[i] = ru->max_pdschReferenceSignalPower;
|
||||
cap->max_rxgain[i] = ru->max_rxgain;
|
||||
}
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
|
||||
"RU %d failed send capabilities to RAU\n",ru->idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int attach_rru(RU_t *ru)
|
||||
{
|
||||
ssize_t msg_len,len;
|
||||
RRU_CONFIG_msg_t rru_config_msg;
|
||||
int received_capabilities=0;
|
||||
|
||||
wait_eNBs();
|
||||
// Wait for capabilities
|
||||
while (received_capabilities==0) {
|
||||
|
||||
memset((void*)&rru_config_msg,0,sizeof(rru_config_msg));
|
||||
rru_config_msg.type = RAU_tick;
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
|
||||
LOG_I(PHY,"Sending RAU tick to RRU %d\n",ru->idx);
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
|
||||
"RU %d cannot access remote radio\n",ru->idx);
|
||||
|
||||
msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
|
||||
|
||||
// wait for answer with timeout
|
||||
if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
|
||||
&rru_config_msg,
|
||||
msg_len))<0) {
|
||||
LOG_I(PHY,"Waiting for RRU %d\n",ru->idx);
|
||||
}
|
||||
else if (rru_config_msg.type == RRU_capabilities) {
|
||||
AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len);
|
||||
LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx,
|
||||
(int)rru_config_msg.len,(int)msg_len,
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->num_bands,
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0],
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_rxgain[0],
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_tx[0],
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_rx[0]);
|
||||
received_capabilities=1;
|
||||
}
|
||||
else {
|
||||
LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx);
|
||||
}
|
||||
}
|
||||
configure_ru(ru,
|
||||
(RRU_capabilities_t *)&rru_config_msg.msg[0]);
|
||||
|
||||
rru_config_msg.type = RRU_config;
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
|
||||
LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",ru->idx,
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
|
||||
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
|
||||
"RU %d failed send configuration to remote radio\n",ru->idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int connect_rau(RU_t *ru)
|
||||
{
|
||||
RRU_CONFIG_msg_t rru_config_msg;
|
||||
ssize_t msg_len;
|
||||
int tick_received = 0;
|
||||
int configuration_received = 0;
|
||||
RRU_capabilities_t *cap;
|
||||
int i;
|
||||
int len;
|
||||
|
||||
// wait for RAU_tick
|
||||
while (tick_received == 0) {
|
||||
|
||||
msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
|
||||
|
||||
if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
|
||||
&rru_config_msg,
|
||||
msg_len))<0) {
|
||||
LOG_I(PHY,"Waiting for RAU\n");
|
||||
}
|
||||
else {
|
||||
if (rru_config_msg.type == RAU_tick) {
|
||||
LOG_I(PHY,"Tick received from RAU\n");
|
||||
tick_received = 1;
|
||||
}
|
||||
else LOG_E(PHY,"Received erroneous message (%d)from RAU, expected RAU_tick\n",rru_config_msg.type);
|
||||
}
|
||||
}
|
||||
|
||||
// send capabilities
|
||||
|
||||
rru_config_msg.type = RRU_capabilities;
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
|
||||
cap = (RRU_capabilities_t*)&rru_config_msg.msg[0];
|
||||
LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",
|
||||
(int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx);
|
||||
switch (ru->function) {
|
||||
case NGFI_RRU_IF4p5:
|
||||
cap->FH_fmt = OAI_IF4p5_only;
|
||||
break;
|
||||
case NGFI_RRU_IF5:
|
||||
cap->FH_fmt = OAI_IF5_only;
|
||||
break;
|
||||
case MBP_RRU_IF5:
|
||||
cap->FH_fmt = MBP_IF5;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"RU_function is unknown %d\n",ru->function);
|
||||
break;
|
||||
}
|
||||
cap->num_bands = ru->num_bands;
|
||||
for (i=0;i<ru->num_bands;i++) {
|
||||
LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n",
|
||||
ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain);
|
||||
cap->band_list[i] = ru->band[i];
|
||||
cap->nb_rx[i] = ru->nb_rx;
|
||||
cap->nb_tx[i] = ru->nb_tx;
|
||||
cap->max_pdschReferenceSignalPower[i] = ru->max_pdschReferenceSignalPower;
|
||||
cap->max_rxgain[i] = ru->max_rxgain;
|
||||
}
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
|
||||
"RU %d failed send capabilities to RAU\n",ru->idx);
|
||||
|
||||
// wait for configuration
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
|
||||
while (configuration_received == 0) {
|
||||
|
||||
if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
|
||||
&rru_config_msg,
|
||||
rru_config_msg.len))<0) {
|
||||
LOG_I(PHY,"Waiting for configuration from RAU\n");
|
||||
}
|
||||
else {
|
||||
LOG_I(PHY,"Configuration received from RAU (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
|
||||
|
||||
configure_rru(ru,
|
||||
(void*)&rru_config_msg.msg[0]);
|
||||
configuration_received = 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int check_capabilities(RU_t *ru,
|
||||
RRU_capabilities_t *cap)
|
||||
{
|
||||
FH_fmt_options_t fmt = cap->FH_fmt;
|
||||
|
||||
int i;
|
||||
int found_band=0;
|
||||
|
||||
LOG_I(PHY,"RRU %d, num_bands %d, looking for band %d\n",ru->idx,cap->num_bands,ru->frame_parms->eutra_band);
|
||||
for (i=0;i<cap->num_bands;i++) {
|
||||
LOG_I(PHY,"band %d on RRU %d\n",cap->band_list[i],ru->idx);
|
||||
if (ru->frame_parms->eutra_band == cap->band_list[i]) {
|
||||
found_band=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_band == 0) {
|
||||
LOG_I(PHY,"Couldn't find target EUTRA band %d on RRU %d\n",ru->frame_parms->eutra_band,ru->idx);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
switch (ru->if_south) {
|
||||
case LOCAL_RF:
|
||||
AssertFatal(1==0, "This RU should not have a local RF, exiting\n");
|
||||
return(0);
|
||||
break;
|
||||
case REMOTE_IF5:
|
||||
if (fmt == OAI_IF5_only || fmt == OAI_IF5_and_IF4p5) return(0);
|
||||
break;
|
||||
case REMOTE_IF4p5:
|
||||
if (fmt == OAI_IF4p5_only || fmt == OAI_IF5_and_IF4p5) return(0);
|
||||
break;
|
||||
case REMOTE_MBP_IF5:
|
||||
if (fmt == MBP_IF5) return(0);
|
||||
break;
|
||||
default:
|
||||
LOG_I(PHY,"No compatible Fronthaul interface found for RRU %d\n", ru->idx);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void configure_ru(RU_t *ru,
|
||||
void *arg)
|
||||
{
|
||||
RRU_config_t *config = (RRU_config_t *)arg;
|
||||
RRU_capabilities_t *capabilities = (RRU_capabilities_t*)arg;
|
||||
int ret;
|
||||
|
||||
LOG_I(PHY, "Received capabilities from RRU %d\n",ru->idx);
|
||||
|
||||
|
||||
if (capabilities->FH_fmt < MAX_FH_FMTs) LOG_I(PHY, "RU FH options %s\n",rru_format_options[capabilities->FH_fmt]);
|
||||
|
||||
AssertFatal((ret=check_capabilities(ru,capabilities)) == 0,
|
||||
"Cannot configure RRU %d, check_capabilities returned %d\n", ru->idx,ret);
|
||||
// take antenna capabilities of RRU
|
||||
ru->nb_tx = capabilities->nb_tx[0];
|
||||
ru->nb_rx = capabilities->nb_rx[0];
|
||||
|
||||
// Pass configuration to RRU
|
||||
LOG_I(PHY, "Using %s fronthaul (%d), band %d \n",ru_if_formats[ru->if_south],ru->if_south,ru->frame_parms->eutra_band);
|
||||
// wait for configuration
|
||||
config->FH_fmt = ru->if_south;
|
||||
config->num_bands = 1;
|
||||
config->band_list[0] = ru->frame_parms->eutra_band;
|
||||
config->tx_freq[0] = ru->frame_parms->dl_CarrierFreq;
|
||||
config->rx_freq[0] = ru->frame_parms->ul_CarrierFreq;
|
||||
config->tdd_config[0] = ru->frame_parms->tdd_config;
|
||||
config->tdd_config_S[0] = ru->frame_parms->tdd_config_S;
|
||||
config->att_tx[0] = ru->att_tx;
|
||||
config->att_rx[0] = ru->att_rx;
|
||||
config->N_RB_DL[0] = ru->frame_parms->N_RB_DL;
|
||||
config->N_RB_UL[0] = ru->frame_parms->N_RB_UL;
|
||||
config->threequarter_fs[0] = ru->frame_parms->threequarter_fs;
|
||||
if (ru->if_south==REMOTE_IF4p5) {
|
||||
config->prach_FreqOffset[0] = ru->frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset;
|
||||
config->prach_ConfigIndex[0] = ru->frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
|
||||
LOG_I(PHY,"REMOTE_IF4p5: prach_FrequOffset %d, prach_ConfigIndex %d\n",
|
||||
config->prach_FreqOffset[0],config->prach_ConfigIndex[0]);
|
||||
|
||||
int i;
|
||||
for (i=0;i<4;i++) {
|
||||
config->emtc_prach_CElevel_enable[0][i] = ru->frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i];
|
||||
config->emtc_prach_FreqOffset[0][i] = ru->frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[i];
|
||||
config->emtc_prach_ConfigIndex[0][i] = ru->frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i];
|
||||
}
|
||||
}
|
||||
|
||||
init_frame_parms(ru->frame_parms,1);
|
||||
phy_init_RU(ru);
|
||||
}
|
||||
|
||||
void configure_rru(RU_t *ru,
|
||||
void *arg)
|
||||
{
|
||||
RRU_config_t *config = (RRU_config_t *)arg;
|
||||
|
||||
ru->frame_parms->eutra_band = config->band_list[0];
|
||||
ru->frame_parms->dl_CarrierFreq = config->tx_freq[0];
|
||||
ru->frame_parms->ul_CarrierFreq = config->rx_freq[0];
|
||||
if (ru->frame_parms->dl_CarrierFreq == ru->frame_parms->ul_CarrierFreq) {
|
||||
LOG_I(PHY,"Setting RRU to TDD frame type\n");
|
||||
ru->frame_parms->frame_type = TDD;
|
||||
ru->frame_parms->tdd_config = config->tdd_config[0];
|
||||
ru->frame_parms->tdd_config_S = config->tdd_config_S[0];
|
||||
}
|
||||
else ru->frame_parms->frame_type = FDD;
|
||||
|
||||
ru->att_tx = config->att_tx[0];
|
||||
ru->att_rx = config->att_rx[0];
|
||||
ru->frame_parms->N_RB_DL = config->N_RB_DL[0];
|
||||
ru->frame_parms->N_RB_UL = config->N_RB_UL[0];
|
||||
ru->frame_parms->threequarter_fs = config->threequarter_fs[0];
|
||||
ru->frame_parms->pdsch_config_common.referenceSignalPower = ru->max_pdschReferenceSignalPower-config->att_tx[0];
|
||||
|
||||
if (ru->function==NGFI_RRU_IF4p5) {
|
||||
ru->frame_parms->att_rx = ru->att_rx;
|
||||
ru->frame_parms->att_tx = ru->att_tx;
|
||||
LOG_I(PHY,"Setting ru->function to NGFI_RRU_IF4p5, prach_FrequOffset %d, prach_ConfigIndex %d, att (%d,%d)\n",
|
||||
config->prach_FreqOffset[0],config->prach_ConfigIndex[0],ru->att_tx,ru->att_rx);
|
||||
ru->frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset = config->prach_FreqOffset[0];
|
||||
ru->frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = config->prach_ConfigIndex[0];
|
||||
for (int i=0;i<4;i++) {
|
||||
ru->frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i] = config->emtc_prach_CElevel_enable[0][i];
|
||||
ru->frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[i] = config->emtc_prach_FreqOffset[0][i];
|
||||
ru->frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i] = config->emtc_prach_ConfigIndex[0][i];
|
||||
}
|
||||
}
|
||||
|
||||
init_frame_parms(ru->frame_parms,1);
|
||||
fill_rf_config(ru,ru->rf_config_file);
|
||||
phy_init_RU(ru);
|
||||
}
|
||||
|
||||
static int send_update_rru(RU_t * ru, LTE_DL_FRAME_PARMS * fp){
|
||||
//ssize_t msg_len/*,len*/;
|
||||
int i;
|
||||
RRU_CONFIG_msg_t rru_config_msg;
|
||||
memset((void *)&rru_config_msg,0,sizeof(rru_config_msg));
|
||||
rru_config_msg.type = RRU_config_update;
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
|
||||
LOG_I(PHY,"Sending RAU tick to RRU %d %lu bytes\n",ru->idx,rru_config_msg.len);
|
||||
|
||||
RRU_config_t *config = (RRU_config_t *)&rru_config_msg.msg[0];
|
||||
config->num_MBSFN_config=fp->num_MBSFN_config;
|
||||
for(i=0; i < fp->num_MBSFN_config; i++){
|
||||
config->MBSFN_config[i] = fp->MBSFN_config[i];
|
||||
LOG_W(PHY,"Configuration send to RAU (num MBSFN %d, MBSFN_SubframeConfig[%d] pattern is %x )\n",config->num_MBSFN_config,i,config->MBSFN_config[i].mbsfn_SubframeConfig);
|
||||
|
||||
}
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
|
||||
"RU %d cannot access remote radio\n",ru->idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* ru_thread_control( void* param )
|
||||
{
|
||||
RU_t *ru = (RU_t*)param;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
RRU_CONFIG_msg_t rru_config_msg;
|
||||
ssize_t msg_len;
|
||||
int len;
|
||||
int ru_sf_update=0; // SF config update flag (MBSFN)
|
||||
|
||||
// Start IF device if any
|
||||
if (ru->start_if) {
|
||||
LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx);
|
||||
AssertFatal(
|
||||
ru->start_if(ru,NULL) == 0, "Could not start the IF device\n");
|
||||
|
||||
if (ru->if_south != LOCAL_RF) wait_eNBs();
|
||||
}
|
||||
|
||||
|
||||
ru->state = (ru->function==eNodeB_3GPP || ru->if_south == REMOTE_IF5)? RU_RUN : RU_IDLE;
|
||||
LOG_I(PHY,"Control channel ON for RU %d\n", ru->idx);
|
||||
|
||||
while (!oai_exit) // Change the cond
|
||||
{
|
||||
msg_len = sizeof(RRU_CONFIG_msg_t); // TODO : check what should be the msg len
|
||||
|
||||
if (ru->state == RU_IDLE && ru->if_south != LOCAL_RF)
|
||||
send_tick(ru);
|
||||
|
||||
if (ru->state == RU_RUN && ru->if_south != LOCAL_RF){
|
||||
LTE_DL_FRAME_PARMS *fp = &ru->eNB_list[0]->frame_parms;
|
||||
LOG_D(PHY,"Check MBSFN SF changes\n");
|
||||
if(fp->num_MBSFN_config != ru_sf_update){
|
||||
ru_sf_update = fp->num_MBSFN_config;
|
||||
LOG_W(PHY,"RU SF should be updated ... calling send_update_rru(ru)\n");
|
||||
send_update_rru(ru,fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
|
||||
&rru_config_msg,
|
||||
msg_len))<0) {
|
||||
LOG_D(PHY,"Waiting msg for RU %d\n", ru->idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(rru_config_msg.type)
|
||||
{
|
||||
case RAU_tick: // RRU
|
||||
if (ru->if_south != LOCAL_RF){
|
||||
LOG_I(PHY,"Received Tick msg...Ignoring\n");
|
||||
}else{
|
||||
LOG_I(PHY,"Tick received from RAU\n");
|
||||
|
||||
if (send_capab(ru) == 0) ru->state = RU_CONFIG;
|
||||
}
|
||||
break;
|
||||
|
||||
case RRU_capabilities: // RAU
|
||||
if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_capab msg...Ignoring\n");
|
||||
|
||||
else{
|
||||
msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
|
||||
|
||||
AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len);
|
||||
LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx,
|
||||
(int)rru_config_msg.len,(int)msg_len,
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->num_bands,
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0],
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_rxgain[0],
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_tx[0],
|
||||
((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_rx[0]);
|
||||
|
||||
configure_ru(ru,(RRU_capabilities_t *)&rru_config_msg.msg[0]);
|
||||
|
||||
// send config
|
||||
if (send_config(ru,rru_config_msg) == 0) ru->state = RU_CONFIG;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RRU_config: // RRU
|
||||
if (ru->if_south == LOCAL_RF){
|
||||
LOG_I(PHY,"Configuration received from RAU (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
|
||||
|
||||
ru->frame_parms = calloc(1, sizeof(*ru->frame_parms));
|
||||
configure_rru(ru, (void*)&rru_config_msg.msg[0]);
|
||||
|
||||
|
||||
fill_rf_config(ru,ru->rf_config_file);
|
||||
init_frame_parms(ru->frame_parms,1);
|
||||
ru->frame_parms->nb_antennas_rx = ru->nb_rx;
|
||||
phy_init_RU(ru);
|
||||
|
||||
//if (ru->is_slave == 1) lte_sync_time_init(&ru->frame_parms);
|
||||
|
||||
if (ru->rfdevice.is_init != 1) openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
|
||||
|
||||
if (ru->rfdevice.trx_config_func) AssertFatal((ru->rfdevice.trx_config_func(&ru->rfdevice,&ru->openair0_cfg)==0),
|
||||
"Failed to configure RF device for RU %d\n",ru->idx);
|
||||
|
||||
if (setup_RU_buffers(ru)!=0) {
|
||||
printf("Exiting, cannot initialize RU Buffers\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// send CONFIG_OK
|
||||
|
||||
rru_config_msg.type = RRU_config_ok;
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t);
|
||||
LOG_I(PHY,"Sending CONFIG_OK to RAU %d\n", ru->idx);
|
||||
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
|
||||
"RU %d failed send CONFIG_OK to RAU\n",ru->idx);
|
||||
reset_proc(ru);
|
||||
ru->state = RU_READY;
|
||||
} else LOG_E(PHY,"Received RRU_config msg...Ignoring\n");
|
||||
|
||||
break;
|
||||
|
||||
case RRU_config_ok: // RAU
|
||||
if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_ok msg...Ignoring\n");
|
||||
else{
|
||||
|
||||
if (setup_RU_buffers(ru)!=0) {
|
||||
printf("Exiting, cannot initialize RU Buffers\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Set state to RUN for Master RU, Others on SYNC
|
||||
ru->state = (ru->is_slave == 1) ? RU_SYNC : RU_RUN ;
|
||||
ru->in_synch = 0;
|
||||
|
||||
|
||||
LOG_I(PHY, "Signaling main thread that RU %d (is_slave %d) is ready in state %s\n",ru->idx,ru->is_slave,ru_states[ru->state]);
|
||||
pthread_mutex_lock(ru->ru_mutex);
|
||||
*ru->ru_mask &= ~(1<<ru->idx);
|
||||
pthread_cond_signal(ru->ru_cond);
|
||||
pthread_mutex_unlock(ru->ru_mutex);
|
||||
|
||||
wait_sync("ru_thread_control");
|
||||
|
||||
// send start
|
||||
rru_config_msg.type = RRU_start;
|
||||
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len
|
||||
|
||||
|
||||
LOG_I(PHY,"Sending Start to RRU %d\n", ru->idx);
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),"Failed to send msg to RU %d\n",ru->idx);
|
||||
|
||||
|
||||
pthread_mutex_lock(&proc->mutex_ru);
|
||||
proc->instance_cnt_ru = 1;
|
||||
pthread_mutex_unlock(&proc->mutex_ru);
|
||||
if (pthread_cond_signal(&proc->cond_ru_thread) != 0) {
|
||||
LOG_E( PHY, "ERROR pthread_cond_signal for RU %d\n",ru->idx);
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RRU_config_update: //RRU
|
||||
if (ru->if_south == LOCAL_RF){
|
||||
LOG_W(PHY,"Configuration update received from RAU \n");
|
||||
|
||||
msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
|
||||
|
||||
LOG_W(PHY,"New MBSFN config received from RAU --- num_MBSFN_config %d\n",((RRU_config_t *)&rru_config_msg.msg[0])->num_MBSFN_config);
|
||||
ru->frame_parms->num_MBSFN_config = ((RRU_config_t *)&rru_config_msg.msg[0])->num_MBSFN_config;
|
||||
for(int i=0; i < ((RRU_config_t *)&rru_config_msg.msg[0])->num_MBSFN_config; i++){
|
||||
ru->frame_parms->MBSFN_config[i].mbsfn_SubframeConfig=((RRU_config_t *)&rru_config_msg.msg[0])->MBSFN_config[i].mbsfn_SubframeConfig;
|
||||
LOG_W(PHY,"Configuration received from RAU (num MBSFN %d, MBSFN_SubframeConfig[%d] pattern is %x )\n",
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->num_MBSFN_config,
|
||||
i,
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->MBSFN_config[i].mbsfn_SubframeConfig
|
||||
);
|
||||
}
|
||||
} else LOG_E(PHY,"Received RRU_config msg...Ignoring\n");
|
||||
break;
|
||||
case RRU_config_update_ok: //RAU
|
||||
if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_update_ok msg...Ignoring\n");
|
||||
else{
|
||||
LOG_W(PHY,"Received RRU_config_update_ok msg...\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case RRU_start: // RRU
|
||||
if (ru->if_south == LOCAL_RF){
|
||||
LOG_I(PHY,"Start received from RAU\n");
|
||||
|
||||
if (ru->state == RU_READY){
|
||||
|
||||
LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx);
|
||||
pthread_mutex_lock(ru->ru_mutex);
|
||||
*ru->ru_mask &= ~(1<<ru->idx);
|
||||
pthread_cond_signal(ru->ru_cond);
|
||||
pthread_mutex_unlock(ru->ru_mutex);
|
||||
|
||||
wait_sync("ru_thread_control");
|
||||
|
||||
ru->state = (ru->is_slave == 1) ? RU_SYNC : RU_RUN ;
|
||||
ru->cmd = EMPTY;
|
||||
pthread_mutex_lock(&proc->mutex_ru);
|
||||
proc->instance_cnt_ru = 1;
|
||||
pthread_mutex_unlock(&proc->mutex_ru);
|
||||
if (pthread_cond_signal(&proc->cond_ru_thread) != 0) {
|
||||
LOG_E( PHY, "ERROR pthread_cond_signal for RU %d\n",ru->idx);
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else LOG_E(PHY,"RRU not ready, cannot start\n");
|
||||
|
||||
} else LOG_E(PHY,"Received RRU_start msg...Ignoring\n");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case RRU_sync_ok: //RAU
|
||||
if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_sync_ok msg...Ignoring\n");
|
||||
else{
|
||||
if (ru->is_slave == 1){
|
||||
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Received RRU_sync_ok from RRU %d\n",ru->idx);
|
||||
// Just change the state of the RRU to unblock ru_thread()
|
||||
ru->state = RU_RUN;
|
||||
}else LOG_E(PHY,"Received RRU_sync_ok from a master RRU...Ignoring\n");
|
||||
}
|
||||
break;
|
||||
case RRU_frame_resynch: //RRU
|
||||
if (ru->if_south != LOCAL_RF) LOG_E(PHY,"Received RRU frame resynch message, should not happen in RAU\n");
|
||||
else {
|
||||
LOG_I(PHY,"Received RRU_frame_resynch command\n");
|
||||
ru->cmd = RU_FRAME_RESYNCH;
|
||||
ru->cmdval = ((uint16_t*)&rru_config_msg.msg[0])[0];
|
||||
LOG_I(PHY,"Received Frame Resynch message with value %d\n",ru->cmdval);
|
||||
}
|
||||
break;
|
||||
|
||||
case RRU_stop: // RRU
|
||||
if (ru->if_south == LOCAL_RF){
|
||||
LOG_I(PHY,"Stop received from RAU\n");
|
||||
|
||||
if (ru->state == RU_RUN || ru->state == RU_ERROR){
|
||||
|
||||
LOG_I(PHY,"Stopping RRU\n");
|
||||
ru->state = RU_READY;
|
||||
// TODO: stop ru_thread
|
||||
}else{
|
||||
LOG_I(PHY,"RRU not running, can't stop\n");
|
||||
}
|
||||
}else LOG_E(PHY,"Received RRU_stop msg...Ignoring\n");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ru->if_south != LOCAL_RF){
|
||||
if (ru->state == RU_IDLE){
|
||||
// Keep sending TICK
|
||||
send_tick(ru);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
} // switch
|
||||
} //else
|
||||
|
||||
|
||||
}//while
|
||||
return(NULL);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Form definition file generated by fdesign */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "stats.h"
|
||||
|
||||
|
||||
/***************************************
|
||||
***************************************/
|
||||
|
||||
FD_stats_form *
|
||||
create_form_stats_form( void )
|
||||
{
|
||||
FL_OBJECT *obj;
|
||||
FD_stats_form *fdui = fl_malloc( sizeof *fdui );
|
||||
|
||||
fdui->vdata = fdui->cdata = NULL;
|
||||
fdui->ldata = 0;
|
||||
|
||||
fdui->stats_form = fl_bgn_form( FL_NO_BOX, 1115, 900 );
|
||||
|
||||
obj = fl_add_box( FL_UP_BOX, 0, 0, 1115, 900, "" );
|
||||
|
||||
//fdui->stats_text = obj = fl_add_text( FL_NORMAL_TEXT, 60, 50, 1000, 810, "test" );
|
||||
//fl_set_object_lsize( obj, FL_TINY_SIZE );
|
||||
fdui->stats_text = obj = fl_add_browser( FL_NORMAL_BROWSER, 60, 50, 1000, 810, "test" );
|
||||
fl_set_browser_fontsize(obj,FL_TINY_SIZE);
|
||||
|
||||
fdui->stats_button = obj = fl_add_button( FL_PUSH_BUTTON, 60, 10, 130, 30, "Reset Stats" );
|
||||
fl_set_object_lalign( obj, FL_ALIGN_CENTER );
|
||||
fl_set_object_color( obj, FL_GREEN, FL_GREEN);
|
||||
fl_set_object_callback( obj, reset_stats, 0 );
|
||||
|
||||
|
||||
fl_end_form( );
|
||||
|
||||
fdui->stats_form->fdui = fdui;
|
||||
|
||||
return fdui;
|
||||
}
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netdb.h>
|
||||
#include <targets/RT/USER/lte-softmodem.h>
|
||||
#include "executables/lte-softmodem.h"
|
||||
|
||||
bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result) {
|
||||
struct addrinfo hints= {0}, *servinfo, *p;
|
||||
|
||||
Reference in New Issue
Block a user