diff --git a/targets/RT/USER/ru_control.c b/targets/RT/USER/ru_control.c
new file mode 100644
index 0000000000..bc2224cdcd
--- /dev/null
+++ b/targets/RT/USER/ru_control.c
@@ -0,0 +1,757 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+*******************************************************************************/
+
+/*! \file lte-ru.c
+ * \brief Top-level threads for RU entity
+ * \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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "rt_wrapper.h"
+
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "assertions.h"
+#include "msc.h"
+
+#include "PHY/types.h"
+
+#include "PHY/defs_common.h"
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+
+
+#include "../../ARCH/COMMON/common_lib.h"
+#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
+
+#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/LTE_TRANSPORT/if5_tools.h"
+
+#include "PHY/phy_extern.h"
+#include "LAYER2/MAC/mac_extern.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 "LAYER2/MAC/mac.h"
+#include "LAYER2/MAC/mac_extern.h"
+#include "LAYER2/MAC/mac_proto.h"
+#include "RRC/LTE/rrc_extern.h"
+#include "PHY_INTERFACE/phy_interface.h"
+
+#include "UTIL/LOG/log_extern.h"
+#include "UTIL/OTG/otg_tx.h"
+#include "UTIL/OTG/otg_externs.h"
+#include "UTIL/MATH/oml.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+#include "enb_config.h"
+
+void configure_ru(int idx,
+ void *arg);
+
+void configure_rru(int idx,
+ void *arg);
+
+int attach_rru(RU_t *ru);
+
+void fill_rf_config(RU_t *ru, char *rf_config_file);
+
+void* ru_thread_control( void* param );
+
+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",RC.ru[0]->function);
+ break;
+ }
+ cap->num_bands = ru->num_bands;
+ for (i=0;inum_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->idx,
+ (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",RC.ru[0]->function);
+ break;
+ }
+ cap->num_bands = ru->num_bands;
+ for (i=0;inum_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->idx,
+ (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;inum_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(int idx,
+ void *arg) {
+
+ RU_t *ru = RC.ru[idx];
+ 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",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", 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]);
+
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 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];
+ }
+#endif
+ }
+
+ init_frame_parms(&ru->frame_parms,1);
+ phy_init_RU(ru);
+}
+
+void configure_rru(int idx,
+ void *arg) {
+
+ RRU_config_t *config = (RRU_config_t *)arg;
+ RU_t *ru = RC.ru[idx];
+
+ 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) {
+ 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];
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 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];
+ }
+#endif
+ }
+
+ init_frame_parms(&ru->frame_parms,1);
+
+ fill_rf_config(ru,ru->rf_config_file);
+
+
+// phy_init_RU(ru);
+
+}
+
+
+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, ret;
+
+
+ // 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_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 ((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->idx,(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]);
+
+ configure_rru(ru->idx, (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){
+ ret = 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(&RC.ru_mutex);
+ RC.ru_mask &= ~(1<idx);
+ pthread_cond_signal(&RC.ru_cond);
+ pthread_mutex_unlock(&RC.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_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(&RC.ru_mutex);
+ RC.ru_mask &= ~(1<idx);
+ pthread_cond_signal(&RC.ru_cond);
+ pthread_mutex_unlock(&RC.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_config_ok msg...Ignoring\n");
+ else{
+ if (ru->is_slave == 1){
+ LOG_I(PHY,"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 messaage 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);
+}