diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 10c29cfc1e..e4aa519f84 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -392,7 +392,7 @@ elseif (${RF_BOARD} STREQUAL "ETHERNET")
set(HW_SOURCE ${HW_SOURCE}
${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
)
- set(LOWLATENCY False)
+ set(LOWLATENCY True)
elseif (${RF_BOARD} STREQUAL "CPRIGW")
set(HW_SOURCE ${HW_SOURCE}
@@ -1558,6 +1558,7 @@ add_executable(lte-softmodem
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
${OPENAIR_TARGETS}/SIMU/USER/init_lte.c
${OPENAIR_TARGETS}/COMMON/create_tasks.c
+ ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
${OPENAIRCN_DIR}/NAS/UE/nas_ue_task.c
${GTPU_need_ITTI}
@@ -1591,6 +1592,7 @@ add_executable(lte-softmodem-nos1
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
${OPENAIR_TARGETS}/SIMU/USER/init_lte.c
${OPENAIR_TARGETS}/COMMON/create_tasks.c
+ ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
#${OPENAIR2_DIR}/RRC/NAS/nas_config.c # enable if you want rrc to mount ip interface
#${OPENAIR2_DIR}/RRC/NAS/rb_config.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
@@ -1725,7 +1727,8 @@ add_executable(rrh_gw
${OPENAIR_TARGETS}/RT/USER/rrh_gw.c
${OPENAIR_TARGETS}/RT/USER/eNB_transport_IQ.c
${OPENAIR_TARGETS}/RT/USER/UE_transport_IQ.c
- ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
+ ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
+ ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
${HW_SOURCE}
)
diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c
index 62b380fddb..a1223e6ca5 100644
--- a/openair2/UTIL/LOG/vcd_signal_dumper.c
+++ b/openair2/UTIL/LOG/vcd_signal_dumper.c
@@ -92,6 +92,8 @@ const char* eurecomVariablesNames[] = {
"diff2",
"hw_subframe",
"hw_frame",
+ "hw_subframe_rx",
+ "hw_frame_rx",
"txcnt",
"rxcnt",
"trx_ts",
@@ -103,6 +105,8 @@ const char* eurecomVariablesNames[] = {
"hw_cnt_tx",
"lhw_cnt_tx",
"pck_rx",
+ "pck_tx",
+ "cnt",
"dummy_dump",
"itti_send_msg",
"itti_poll_msg",
@@ -150,6 +154,8 @@ const char* eurecomFunctionsNames[] = {
"eNB_rx_sleep",
"eNB_tx_sleep",
"eNB_proc_sleep",
+ "trx_read_rf",
+ "trx_write_rf",
/* PHY signals */
"ue_synch",
diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h
index 825b05d535..7ec2e2445e 100644
--- a/openair2/UTIL/LOG/vcd_signal_dumper.h
+++ b/openair2/UTIL/LOG/vcd_signal_dumper.h
@@ -64,6 +64,8 @@ typedef enum {
VCD_SIGNAL_DUMPER_VARIABLES_DIFF,
VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME,
VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME,
+ VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME_RX,
+ VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME_RX,
VCD_SIGNAL_DUMPER_VARIABLES_TXCNT,
VCD_SIGNAL_DUMPER_VARIABLES_RXCNT,
VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS,
@@ -75,6 +77,8 @@ typedef enum {
VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT,
VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT,
VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK,
+ VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK,
+ VCD_SIGNAL_DUMPER_VARIABLES_CNT,
VCD_SIGNAL_DUMPER_VARIABLES_DUMMY_DUMP,
VCD_SIGNAL_DUMPER_VARIABLE_ITTI_SEND_MSG,
VCD_SIGNAL_DUMPER_VARIABLE_ITTI_POLL_MSG,
@@ -116,8 +120,7 @@ typedef enum {
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_TX,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX,
- /* RRH signals */
-
+ /* RRH signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX,
@@ -125,6 +128,8 @@ typedef enum {
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_SLEEP,
+ VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF,
+ VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF,
/* PHY signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,
diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c
index 97817e6eac..6ebf709ec9 100644
--- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c
+++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c
@@ -185,7 +185,7 @@ int trx_brf_set_gains(openair0_device* device) {
}
-int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
+int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) {
int status;
int card=0;
diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c
new file mode 100644
index 0000000000..63f086ff1d
--- /dev/null
+++ b/targets/ARCH/COMMON/common_lib.c
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ 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@eurecom.fr
+
+ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+/*! \file common_lib.c
+ * \brief common APIs for different RF frontend device
+ * \author HongliangXU, Navid Nikaein
+ * \date 2015
+ * \version 0.2
+ * \company Eurecom
+ * \maintainer: navid.nikaein@eurecom.fr
+ * \note
+ * \warning
+ */
+#include
+#include "common_lib.h"
+
+
+int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
+
+#ifdef ETHERNET
+ device->type=ETH_IF;
+ device->func_type = BBU_FUNC;
+ openair0_dev_init_eth(device, openair0_cfg);
+ printf(" openair0_dev_init_eth ...\n");
+#elif EXMIMO
+ device->type=EXMIMO_IF;
+ openair0_dev_init_exmimo(device, openair0_cfg);
+ printf("openair0_dev_init_exmimo...\n");
+#elif OAI_USRP
+ device->type=USRP_IF;
+ openair0_dev_init_usrp(device, openair0_cfg);
+ printf("openair0_dev_init_usrp ...\n");
+#elif OAI_BLADERF
+ device->type=BLADERF_IF;
+ openair0_dev_init_bladerf(device, openair0_cfg);
+ printf(" openair0_dev_init_bladerf ...\n");
+#endif
+
+}
diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h
index dc9f30f4df..a6851b0dbe 100644
--- a/targets/ARCH/COMMON/common_lib.h
+++ b/targets/ARCH/COMMON/common_lib.h
@@ -134,7 +134,13 @@ typedef struct {
-/*!\brief device type */
+/*!\brief interface types that apply to modules (RRH_BBU/RRH_UE) created in RRH (rrh_gw.c)
+ and are defined with respect to the RF device that is present in RRH
+ -RRH_BBU modules have two devices, one is by default ETHERNET (will have ETH_IF) and the other one is a
+ RF device (EXMIMO,USRP,BLADERF) or no device (NONE_IF).
+ -RRH_UE modules have two devices one is by default ETHERNET (will have ETH_IF)
+ and the other one by default not present so it will have NONE_IF
+ */
typedef enum {
MIN_DEV_TYPE = 0,
/*!\brief device is ETH */
@@ -152,10 +158,10 @@ typedef enum {
} dev_type_t;
-/*!\brief type */
+/*!\brief openair0 device host type */
typedef enum {
MIN_FUNC_TYPE = 0,
- /*!\brief device functions within a BBU */
+ /*!\brief device functions within a BBU */
BBU_FUNC,
/*!\brief device functions within a RRH */
RRH_FUNC,
@@ -264,23 +270,20 @@ extern "C"
#endif
/*! \brief Initialize Openair RF target. It returns 0 if OK */
-int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg);
- //int openair0_stop(int card);
-
-//ETHERNET
-/*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */
-int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg);
- //int openair0_stop_eth(int card);
- //int openair0_set_gains_eth(openair0_device* device, openair0_config_t *openair0_cfg);
- //int openair0_set_frequencies_eth(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config);
-
-//USPRP
+ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg);
+
+ //USRP
/*! \brief Get the current timestamp of USRP */
-openair0_timestamp get_usrp_time(openair0_device *device);
-
+ openair0_timestamp get_usrp_time(openair0_device *device);
/*! \brief Set the RX frequency of USRP RF TARGET */
-int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg);
-
+ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg);
+
+//extern
+/*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */
+ int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg);
+ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg);
+ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg);
+ int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg);
/*@}*/
#ifdef __cplusplus
diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
index 9f299fa58e..6dd457d9b5 100644
--- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
+++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
@@ -26,7 +26,7 @@
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
-/*! \fileethernet_lib.c
+/*! \file ethernet_lib.c
* \brief API to stream I/Q samples over standard ethernet
* \author Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp
* \date 2015
@@ -52,25 +52,328 @@
#include "common_lib.h"
#include "ethernet_lib.h"
+//#define DEBUG 1
int num_devices_eth = 0;
int dest_addr_len[MAX_INST];
char sendbuf[MAX_INST][BUF_SIZ]; /*TODO*/
-/* Initialization of UDP Socket to communicate with one destination */
-int ethernet_socket_init(openair0_device *device) {
+/*! \fn static int eth_socket_init(openair0_device *device)
+* \brief initialization of UDP Socket to communicate with one destination
+* \param[in] *device openair device for which the socket will be created
+* \param[out]
+* \return 0 on success, otherwise -1
+* \note
+* @ingroup _oai
+*/
+static int eth_socket_init(openair0_device *device);
+
+/*! \fn static int eth_set_dev_conf(openair0_device *device)
+* \brief
+* \param[in] *device openair device
+* \param[out]
+* \return 0 on success, otherwise -1
+* \note
+* @ingroup _oai
+*/
+static int eth_set_dev_conf(openair0_device *device);
+
+/*! \fn static int eth_get_dev_conf(openair0_device *device)
+* \brief
+* \param[in] *device openair device
+* \param[out]
+* \return 0 on success, otherwise -1
+* \note
+* @ingroup _oai
+*/
+static int eth_get_dev_conf(openair0_device *device);
+
+
+
+int trx_eth_start(openair0_device *device) {
+
+ /* initialize socket */
+ if (eth_socket_init(device)!=0) {
+ return -1;
+ }
+
+ /* RRH gets openair0 device configuration BBU sets openair0 device configuration*/
+ if (device->func_type == BBU_FUNC) {
+ return eth_set_dev_conf(device);
+ } else {
+ return eth_get_dev_conf(device);
+ }
+
+ return 0;
+}
+
+
+int trx_eth_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) {
+
+ int n_written=0,i;
+ uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
+ eth_state_t *eth = (eth_state_t*)device->priv;
+ int Mod_id = device->Mod_id;
+ int sendto_flag =0;
+ sendto_flag|=MSG_DONTWAIT;
+
+ for (i=0;isockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
+
+ while(n_written < nsamps) {
+ /* Send packet */
+ if ((n_written += sendto(eth->sockfd[Mod_id],
+ buff2,
+ (nsamps<<2)+header_size,
+ 0,
+ (struct sockaddr*)ð->dest_addr[Mod_id],
+ dest_addr_len[Mod_id])) < 0) {
+ perror("ETHERNET WRITE");
+ exit(-1);
+ }
+ }
+
+#if DEBUG
+ printf("Buffer head TX: nu=%d an_id=%d ts%d samples_send=%d i=%d data=%x\n",
+ *(int16_t *)buff2,
+ *(int16_t *)(buff2 + sizeof(int16_t)),
+ *(openair0_timestamp *)(buff2 + sizeof(int32_t)),
+ n_written>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t)));
+#endif
+
+ /* tx buffer values restored */
+ *(int32_t *)buff2 = temp0;
+ *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
+ }
+ return n_written;
+
+}
+
+int trx_eth_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
+
+ int bytes_received=0;
+ int block_cnt=0;
+ int ret=0,i;
+ uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
- int i = 0;
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
- // struct sockaddr_in *dest = &dest_addr[Mod_id];
+ for (i=0;isockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
+
+ while(bytes_received < (int)((nsamps<<2))) {
+ ret=recvfrom(eth->sockfd[Mod_id],
+ buff2+bytes_received,
+ (nsamps<<2)+header_size-bytes_received,
+ 0,//MSG_DONTWAIT,
+ (struct sockaddr *)ð->dest_addr[Mod_id],
+ (socklen_t *)&dest_addr_len[Mod_id]);
+
+ if (ret==-1) {
+ if (errno == EAGAIN) {
+ perror("ETHERNET READ: ");
+ return((nsamps<<2) + header_size);
+ } else if (errno == EWOULDBLOCK) {
+ block_cnt++;
+ usleep(10);
+
+ if (block_cnt == 100) return(-1);
+ }
+ } else {
+ bytes_received+=ret;
+ }
+ }
+
+#if DEBUG
+ printf("Buffer head RX: nu=%d an_id=%d ts%d samples_recv=%d i=%d data=%x\n",
+ *(int16_t *)buff2,
+ *(int16_t *)(buff2 + sizeof(int16_t)),
+ *(openair0_timestamp *)(buff2 + sizeof(int32_t)),
+ ret>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t)));
+#endif
+
+ /* store the timestamp value from packet's header */
+ *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
+
+ /* tx buffer values restored */
+ *(int32_t *)buff2 = temp0;
+ *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
+ }
+ return nsamps;
+
+}
+
+void trx_eth_end(openair0_device *device) {
+
+ eth_state_t *eth = (eth_state_t*)device->priv;
+ int Mod_id = device->Mod_id;
+ /*destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */
+ if ( close(eth->sockfd[Mod_id]) <0 ) {
+ perror("ETHERNET: Failed to close socket");
+ exit(0);
+ } else {
+ printf("[RRH] socket for mod_id %d has been successfully closed.\n",Mod_id);
+ }
+
+}
+
+
+int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) {
+
+ int Mod_id = device->Mod_id;
+ eth_state_t *eth = (eth_state_t*)device->priv;
+
+ /* BBU sends a message to RRH */
+ if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) {
+ perror("ETHERNET: ");
+ exit(0);
+ }
+
+ return 0;
+}
+
+
+
+int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) {
+
+ eth_state_t *eth = (eth_state_t*)device->priv;
+ int Mod_id = device->Mod_id;
+
+ /* RRH receives from BBU a message */
+ if (recvfrom(eth->sockfd[Mod_id],
+ msg,
+ msg_len,
+ 0,
+ (struct sockaddr *)ð->dest_addr[Mod_id],
+ (socklen_t *)&dest_addr_len[Mod_id])==-1) {
+ perror("ETHERNET: ");
+ exit(0);
+ }
+
+ return 0;
+}
+
+
+static int eth_set_dev_conf(openair0_device *device) {
+
+ int Mod_id = device->Mod_id;
+ eth_state_t *eth = (eth_state_t*)device->priv;
+ void *msg;
+ ssize_t msg_len;
+
+
+ /* a BBU client sents to RRH a set of configuration parameters (openair0_config_t)
+ so that RF front end is configured appropriately and
+ frame/packet size etc. can be set */
+
+ msg=malloc(sizeof(openair0_config_t));
+ msg_len=sizeof(openair0_config_t);
+ memcpy(msg,(void*)&device->openair0_cfg,msg_len);
+
+ if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) {
+ perror("ETHERNET: ");
+ exit(0);
+ }
+
+ return 0;
+}
+
+
+static int eth_get_dev_conf(openair0_device *device) {
+
+ eth_state_t *eth = (eth_state_t*)device->priv;
+ int Mod_id = device->Mod_id;
+ char str[INET_ADDRSTRLEN];
+ void *msg;
+ ssize_t msg_len;
+
+ msg=malloc(sizeof(openair0_config_t));
+ msg_len=sizeof(openair0_config_t);
+
+ /* RRH receives from BBU openair0_config_t */
+ if (recvfrom(eth->sockfd[Mod_id],
+ msg,
+ msg_len,
+ 0,
+ (struct sockaddr *)ð->dest_addr[Mod_id],
+ (socklen_t *)&dest_addr_len[Mod_id])==-1) {
+ perror("ETHERNET: ");
+ exit(0);
+ }
+
+ memcpy((void*)&device->openair0_cfg,msg,msg_len);
+ inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
+ device->openair0_cfg.remote_port =ntohs(eth->dest_addr[Mod_id].sin_port);
+ device->openair0_cfg.remote_ip=str;
+ /*apply additional configuration*/
+ //ethernet_tune (device, RING_PAR);
+ // printf("[RRH] write mod_%d %d to %s:%d\n",Mod_id,eth->sockfd[Mod_id],str,ntohs(eth->dest_addr[Mod_id].sin_port));
+
+ return 0;
+}
+
+
+
+int trx_eth_stop(int card) {
+ return(0);
+}
+
+int trx_eth_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
+ return(0);
+}
+
+int trx_eth_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) {
+ return(0);
+}
+
+int trx_eth_get_stats(openair0_device* device) {
+ return(0);
+}
+
+int trx_eth_reset_stats(openair0_device* device) {
+ return(0);
+}
+
+
+static int eth_socket_init(openair0_device *device) {
+
+ int i = 0;
+ eth_state_t *eth = (eth_state_t*)device->priv;
+ int Mod_id = device->Mod_id;
char str[INET_ADDRSTRLEN];
const char *dest_ip;
- int dest_port;
+ int dest_port=0;
- if (device->func_type == RRH_FUNC ){
+ if (device->func_type == RRH_FUNC ) {
dest_ip = device->openair0_cfg.my_ip;
dest_port = device->openair0_cfg.my_port;
printf("[RRH] ip addr %s port %d\n",dest_ip, dest_port);
@@ -87,8 +390,9 @@ int ethernet_socket_init(openair0_device *device) {
}
/* initialize destination address */
- for (i=0; i< MAX_INST; i++)
+ for (i=0; i< MAX_INST; i++) {
bzero((void *)&(eth->dest_addr[i]), sizeof(eth->dest_addr[i]));
+ }
// bzero((void *)dest,sizeof(struct sockaddr_in));
eth->dest_addr[Mod_id].sin_family = AF_INET;
@@ -98,359 +402,126 @@ int ethernet_socket_init(openair0_device *device) {
inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
/* if RRH, then I am the server, so bind */
- if (device->func_type == RRH_FUNC ){
+ if (device->func_type == RRH_FUNC ) {
if (bind(eth->sockfd[Mod_id],(struct sockaddr *)ð->dest_addr[Mod_id], dest_addr_len[Mod_id])<0) {
perror("ETHERNET: Cannot bind to socket");
exit(0);
- }else {
+ } else {
printf("[RRH] binding mod_%d to %s:%d\n",Mod_id,str,ntohs(eth->dest_addr[Mod_id].sin_port));
}
- }else {
+ } else {
printf("[BBU] Connecting to %s:%d\n",str,ntohs(eth->dest_addr[Mod_id].sin_port));
}
return 0;
}
-void ethernet_socket_opt (openair0_device *device){
+int ethernet_tune(openair0_device *device , eth_opt_t option) {
+
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id=device->Mod_id;
- int sndbuf_size=0, rcvbuf_size=0;
- socklen_t optlen;
- /* chang the MTU of the eth interface */
- struct ifreq ifr;
-
- optlen = sizeof(int);
-
- if (getsockopt(eth->sockfd[Mod_id],
- SOL_SOCKET,
- SO_SNDBUF,
- &sndbuf_size,&optlen))
- printf("error:getsockopt()\n");
-
- if (getsockopt(eth->sockfd[Mod_id],
- SOL_SOCKET,
- SO_RCVBUF,
- &rcvbuf_size,&optlen))
- printf("error:getsockopt()\n");
+ unsigned int sndbuf_size=0, rcvbuf_size=0;
+ struct timeval snd_timeout, rcv_timeout;
+ struct ifreq ifr;
+ char system_cmd[256];
+ char* if_name=DEFAULT_IF;
- printf( "sndbuf_size= %d bytes rcvbuf_size= %d bytes\n", sndbuf_size,
- rcvbuf_size);
-
- ifr.ifr_addr.sa_family = AF_INET;
- //iap->ifa_name is bond1:xx
- strncpy(ifr.ifr_name, DEFAULT_IF, sizeof(ifr.ifr_name));
- ifr.ifr_mtu = device->openair0_cfg.samples_per_packet*5;
- if (ioctl(eth->sockfd[Mod_id], SIOCSIFMTU, (caddr_t)&ifr) < 0 )
- perror ("Can't set the MTU");
- else
- printf("[ETHERNET] %s MTU size has changed to %d\n",DEFAULT_IF,ifr.ifr_mtu);
-
-}
-
-
-int trx_eth_set_dev_conf(openair0_device *device) {
-
- int Mod_id = device->Mod_id;
- eth_state_t *eth = (eth_state_t*)device->priv;
- void *msg;
- ssize_t msg_len;
-
-
- /* send to RRH (server) required configuration parameters:
- -number of downlink RBs (so that frame/packet size can be set accordingly)
- -rx_num_0channels
- -tx_num_channels
- -rx_freq
- -tx_freq
- -rxg_mode[4]
- -rx_gain
- -tx_gain
- -rx_bw
- -tx_bw
- -autocal */
-
- msg=malloc(sizeof(openair0_config_t));
- msg_len=sizeof(openair0_config_t);
- memcpy(msg,(void*)&device->openair0_cfg,msg_len);
-
- if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1){
- perror("ETHERNET: ");
- exit(0);
- }
-
- return 0;
-}
-
-
-
-int trx_eth_get_dev_conf(openair0_device *device) {
-
- eth_state_t *eth = (eth_state_t*)device->priv;
- int Mod_id = device->Mod_id;
- char str[INET_ADDRSTRLEN];
- void *msg;
- ssize_t msg_len;
-
- msg=malloc(sizeof(openair0_config_t));
- msg_len=sizeof(openair0_config_t);
-
- /* receive from client (lte-softmodem) */
- if (recvfrom(eth->sockfd[Mod_id],
- msg,
- msg_len,
- 0,
- (struct sockaddr *)ð->dest_addr[Mod_id],
- (socklen_t *)&dest_addr_len[Mod_id])==-1){
- perror("ETHERNET: ");
- exit(0);
- }
-
- memcpy((void*)&device->openair0_cfg,msg,msg_len);
- inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
- device->openair0_cfg.remote_port =ntohs(eth->dest_addr[Mod_id].sin_port);
- device->openair0_cfg.remote_ip=str;
- //ethernet_socket_opt (device);
- // printf("[RRH] write mod_%d %d to %s:%d\n",Mod_id,eth->sockfd[Mod_id],str,ntohs(eth->dest_addr[Mod_id].sin_port));
-
- return 0;
-}
-
-int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) {
-
- int Mod_id = device->Mod_id;
- eth_state_t *eth = (eth_state_t*)device->priv;
-
- if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1){
- perror("ETHERNET: ");
- exit(0);
- }
-
- return 0;
-}
-
-
-
-int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) {
-
- eth_state_t *eth = (eth_state_t*)device->priv;
- int Mod_id = device->Mod_id;
-
- /* receive from client (lte-softmodem) */
- if (recvfrom(eth->sockfd[Mod_id],
- msg,
- msg_len,
- 0,
- (struct sockaddr *)ð->dest_addr[Mod_id],
- (socklen_t *)&dest_addr_len[Mod_id])==-1){
- perror("ETHERNET: ");
- exit(0);
- }
-
-
- return 0;
-}
-
-
-int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id) {
-
- int n_written;
- uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
- eth_state_t *eth = (eth_state_t*)device->priv;
- int Mod_id = device->Mod_id;
- int sendto_flag =0;
- sendto_flag|=MSG_DONTWAIT;
-
- /* buff[antenna_id] points to the position in tx buffer where the payload to be sent is
- buff2 points to the position in tx buffer where the packet header will be placed */
- void *buff2 = (void*)(buff[antenna_id]-header_size); // (void*)((unsigned char *)buff[antenna_id]-header_size);
-
- /* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/
- int32_t temp0 = *(int32_t *)buff2;
- openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
-
- n_written = 0;
-
- *(int16_t *)(buff2 + sizeof(int16_t))=1+(antenna_id<<1);
- *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp;
-
- /* printf("[RRH]write mod_%d %d , len %d, buff %p antenna %d\n",
- Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
-
-while(n_written < nsamps) {
- /* Send packet */
- if ((n_written += sendto(eth->sockfd[Mod_id],
- buff2,
- (nsamps<<2)+header_size,
- 0,
- (struct sockaddr*)ð->dest_addr[Mod_id],
- dest_addr_len[Mod_id])) < 0) {
- perror("ETHERNET WRITE");
- exit(-1);
- }
- }
-
-/* printf("Buffer head TX: nu=%d an_id=%d ts%d byte_send=%d \n", *(int16_t *)buff2,
- *(int16_t *)(buff2 + sizeof(int16_t)),
- *(openair0_timestamp *)(buff2 + sizeof(int32_t)),
- n_written>>2);*/
-
- /* tx buffer values restored */
- *(int32_t *)buff2 = temp0;
- *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
- return n_written;
-
-}
-
-
-int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int antenna_id) {
-
- int bytes_received;
- int block_cnt;
- int ret;
- uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
-
-
- /* buff[antenna_id] points to the position in rx buffer where the payload to be received will be placed
- buff2 points to the position in rx buffer where the packet header will be placed */
- void *buff2 = (void*)(buff[antenna_id]-header_size);
-
- /* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/
- int32_t temp0 = *(int32_t *)buff2;
- openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
-
- eth_state_t *eth = (eth_state_t*)device->priv;
- int Mod_id = device->Mod_id;
-
- bytes_received=0;
- block_cnt=0;
-
- /* printf("[RRH] read mod_%d %d,len %d, buff %p antenna %d\n",
- Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
-
- while(bytes_received < (int)((nsamps<<2))) {
- ret=recvfrom(eth->sockfd[Mod_id],
- buff2+bytes_received,
- (nsamps<<2)+header_size-bytes_received,
- 0,//MSG_DONTWAIT,
- (struct sockaddr *)ð->dest_addr[Mod_id],
- (socklen_t *)&dest_addr_len[Mod_id]);
-
- if (ret==-1) {
- if (errno == EAGAIN) {
- perror("ETHERNET READ: ");
- return((nsamps<<2) + header_size);
- } else if (errno == EWOULDBLOCK) {
- block_cnt++;
- usleep(10);
-
- if (block_cnt == 100) return(-1);
- }
+ /****************** socket level options ************************/
+ if (option== SND_BUF_SIZE) { /* transmit socket buffer size */
+ if (setsockopt(eth->sockfd[Mod_id],
+ SOL_SOCKET,
+ SO_SNDBUF,
+ &sndbuf_size,sizeof(sndbuf_size))) {
+ perror("[ETHERNET] setsockopt()");
} else {
- bytes_received+=ret;
+ printf( "sndbuf_size= %d bytes\n", sndbuf_size);
+ }
+ } else if (option== RCV_BUF_SIZE) { /* receive socket buffer size */
+ if (setsockopt(eth->sockfd[Mod_id],
+ SOL_SOCKET,
+ SO_RCVBUF,
+ &rcvbuf_size,sizeof(rcvbuf_size))) {
+ perror("[ETHERNET] setsockopt()");
+ } else {
+ printf( "rcvbuf_size= %d bytes\n", rcvbuf_size);
+ }
+ } else if (option==RCV_TIMEOUT) {
+ rcv_timeout.tv_sec = 0;
+ rcv_timeout.tv_usec = 180;//less than rt_period
+ if (setsockopt(eth->sockfd[Mod_id],
+ SOL_SOCKET,
+ SO_RCVTIMEO,
+ (char *)&rcv_timeout,sizeof(rcv_timeout))) {
+ perror("[ETHERNET] setsockopt()");
+ } else {
+ printf( "rcv_timeout= %d usecs\n", rcv_timeout.tv_usec);
+ }
+ } else if (option==SND_TIMEOUT) {
+ snd_timeout.tv_sec = 0;
+ snd_timeout.tv_usec = 180;//less than rt_period
+ if (setsockopt(eth->sockfd[Mod_id],
+ SOL_SOCKET,
+ SO_SNDTIMEO,
+ (char *)&snd_timeout,sizeof(snd_timeout))) {
+ perror("[ETHERNET] setsockopt()");
+ } else {
+ printf( "snd_timeout= %d usecs\n", snd_timeout.tv_usec);
}
}
- /*
- printf("Buffer head RX: nu=%d an_id=%d ts%d byte_recv=%d\n", *(int16_t *)buff2,
- *(int16_t *)(buff2 + sizeof(int16_t)),
- *(openair0_timestamp *)(buff2 + sizeof(int32_t)),
- ret>>2);*/
- /* store the timestamp value from packet's header */
- *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
-
- /* tx buffer values restored */
- *(int32_t *)buff2 = temp0;
- *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
- // printf("Received %d samples, timestamp = %d\n",bytes_received>>2,*(int32_t*)timestamp);
-
- return nsamps;
-
-}
+ /******************* interface level options *************************/
+ else if (option==MTU_SIZE) { /* change MTU of the eth interface */
+ ifr.ifr_addr.sa_family = AF_INET;
+ strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name));
+ ifr.ifr_mtu =8960;
+ if (ioctl(eth->sockfd[Mod_id],SIOCSIFMTU,(caddr_t)&ifr) < 0 )
+ perror ("[ETHERNET] Can't set the MTU");
+ else
+ printf("[ETHERNET] %s MTU size has changed to %d\n",DEFAULT_IF,ifr.ifr_mtu);
+ } else if (option==TX_Q_LEN) { /* change TX queue length of eth interface */
+ ifr.ifr_addr.sa_family = AF_INET;
+ strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name));
+ ifr.ifr_qlen =3000 ;
+ if (ioctl(eth->sockfd[Mod_id],SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 )
+ perror ("[ETHERNET] Can't set the txqueuelen");
+ else
+ printf("[ETHERNET] %s txqueuelen size has changed to %d\n",DEFAULT_IF,ifr.ifr_qlen);
-int trx_eth_start(openair0_device *device){
-
- if (ethernet_socket_init(device)!=0) {
- return -1;
+
+ /******************* device level options *************************/
+ } else if (option==COALESCE_PAR) {
+ if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs 3",DEFAULT_IF) > 0) {
+ system(system_cmd);
+ printf("[ETHERNET] Coalesce parameters %s\n",system_cmd);
+ } else {
+ perror("[ETHERNET] Can't set coalesce parameters\n");
+ }
+
+ } else if (option==PAUSE_PAR ) {
+ if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",DEFAULT_IF) > 0) {
+ system(system_cmd);
+ printf("[ETHERNET] Pause parameters %s\n",system_cmd);
+ } else {
+ perror("[ETHERNET] Can't set pause parameters\n");
+ }
+ } else if (option==RING_PAR ) {
+ if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx 4096 tx 4096",DEFAULT_IF) > 0) {
+ system(system_cmd);
+ printf("[ETHERNET] Ring parameters %s\n",system_cmd);
+ } else {
+ perror("[ETHERNET] Can't set ring parameters\n");
+ }
+
}
-
- if (device->func_type == BBU_FUNC ) {
- return trx_eth_set_dev_conf(device);
- }
- else{
- return trx_eth_get_dev_conf(device);
- }
- return(0);
-}
-
-int trx_eth_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int antenna_id, int flags) {
-
- return ethernet_write_data(device,timestamp,buff,nsamps,antenna_id);
-}
-
-int trx_eth_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int antenna_id) {
-
- return(ethernet_read_data(device,ptimestamp,buff,nsamps,antenna_id));
-
-}
-
-int trx_eth_stop(int card) {
- return(0);
-}
-
-int trx_eth_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
- return(0);
-}
-
-int trx_eth_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) {
- return(0);
-}
-
-
-int trx_eth_get_stats(openair0_device* device) {
-
- return(0);
-
-}
-
-int trx_eth_reset_stats(openair0_device* device) {
-
- return(0);
-
-}
-
-int openair0_set_gains(openair0_device* device,
- openair0_config_t *openair0_cfg) {
-
- return(0);
-}
-
-int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg, int dummy) {
-
- return(0);
+ return 0;
}
-void trx_eth_end(openair0_device *device) {
-
- eth_state_t *eth = (eth_state_t*)device->priv;
- int Mod_id = device->Mod_id;
- /*destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */
- if ( close(eth->sockfd[Mod_id]) <0 ) {
- perror("ETHERNET: Failed to close socket");
- exit(0);
- }else {
- printf("[RRH] socket for mod_id %d has been successfully closed.",Mod_id);
- }
-
-}
-
-
-int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg){
+int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg) {
eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t));
int card = 0;
diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h
index 8914ff5809..628fcb377c 100644
--- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h
+++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h
@@ -48,7 +48,7 @@
#include
#define MAX_INST 4
-#define DEFAULT_IF "eth0"
+#define DEFAULT_IF "lo"
#define BUF_SIZ 8960 /*Jumbo frame size*/
typedef struct {
@@ -103,21 +103,51 @@ struct eth_meta_data{
};
+
+/*!\brief packet header */
typedef struct {
- /* packet's timestamp */
+ /*!\brief packet's timestamp */
openair0_timestamp timestamp;
- /* variable declared for alignment purposes (sample size=32 bit) */
+ /*!\brief variable declared for alignment purposes (sample size=32 bit) */
int16_t not_used;
- /* antenna port used to resynchronize*/
+ /*!\brief antenna port used to resynchronize */
int16_t antenna_id;
} header_t;
+/*!\brief different options for ethernet tuning in socket and driver level */
+typedef enum {
+ MIN_OPT = 0,
+ /*!\brief socket send buffer size in bytes */
+ SND_BUF_SIZE,
+ /*!\brief socket receive buffer size in bytes */
+ RCV_BUF_SIZE,
+ /*!\brief receiving timeout */
+ RCV_TIMEOUT,
+ /*!\brief sending timeout */
+ SND_TIMEOUT,
+ /*!\brief maximun transmission unit size in bytes */
+ MTU_SIZE,
+ /*!\brief TX queue length */
+ TX_Q_LEN,
+ /*!\brief RX/TX ring parameters of ethernet device */
+ RING_PAR,
+ /*!\brief interruptions coalesence mechanism of ethernet device */
+ COALESCE_PAR,
+ /*!\brief pause parameters of ethernet device */
+ PAUSE_PAR,
+ MAX_OPT
+} eth_opt_t;
-int ethernet_socket_init(openair0_device *device);
-int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id);
-
-int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int antenna_id);
-
-void ethernet_socket_opt (openair0_device *device);
+/*! \fn int ethernet_tune (openair0_device *device, eth_opt_t option)
+* \brief this function allows you to configure certain ethernet parameters in socket or device level
+* \param[in] openair0 device which bears the socket
+* \param[in] name of parameter to configure
+* \return 0 on success, otherwise -1
+* \note
+* @ingroup _oai
+*/
+int ethernet_tune (openair0_device *device, eth_opt_t option);
+int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc) ;
+int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int cc);
diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
index 01eca4bf6a..71c1009039 100644
--- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
+++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
@@ -247,7 +247,7 @@ int openair0_stop_without_reset(int card)
#define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX)
#define RF_MODE_BASE (LNA1ON + RFBBNORM)
-int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
+int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg) {
// Initialize card
// exmimo_config_t *p_exmimo_config;
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index d62497b262..192ed503e2 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -154,7 +154,6 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
{
-
usrp_state_t *s = (usrp_state_t*)device->priv;
int samples_received=0,i,j;
int nsamps2; // aligned to upper 32 or 16 byte boundary
@@ -182,31 +181,26 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
// receive a single channel (e.g. from connector RF A)
samples_received = s->rx_stream->recv(buff_tmp[0], nsamps, s->rx_md);
}
-
+
// bring RX data into 12 LSBs for softmodem RX
for (int i=0;irx_md.error_code){
case uhd::rx_metadata_t::ERROR_CODE_NONE:
@@ -225,6 +219,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
s->rx_count += nsamps;
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp;
+
return samples_received;
}
@@ -334,7 +329,7 @@ int trx_usrp_reset_stats(openair0_device* device) {
}
-int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg)
+int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg)
{
uhd::set_thread_priority_safe(1.0);
usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t));
@@ -499,6 +494,5 @@ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cf
s->tx_forward_nsamps = 90;
if(is_equal(s->sample_rate, (double)7.68e6))
s->tx_forward_nsamps = 50;
-
return 0;
}
diff --git a/targets/RT/USER/UE_transport_IQ.c b/targets/RT/USER/UE_transport_IQ.c
index f88e22dbfa..e986046d81 100644
--- a/targets/RT/USER/UE_transport_IQ.c
+++ b/targets/RT/USER/UE_transport_IQ.c
@@ -89,15 +89,8 @@ void *rrh_UE_thread_status;
void *rx_ue[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_rx
void *tx_ue[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_tx
-/*! \fn void create_UE_trx_threads( openair0_device *dev_ue, uint8_t RT_flag,uint8_t NRT_flag)
-* \brief this function
-* \param[in]
-* \param[out]
-* \return
-* \note
-* @ingroup _oai
-*/
-void create_UE_trx_threads( rrh_module_t *dev_ue, uint8_t RT_flag,uint8_t NRT_flag) {
+
+void config_UE_mod( rrh_module_t *dev_ue, uint8_t RT_flag,uint8_t NRT_flag) {
int i;
int error_code_UE, error_code_proc_UE;
diff --git a/targets/RT/USER/eNB_transport_IQ.c b/targets/RT/USER/eNB_transport_IQ.c
index 43981257ec..eaad2ebb24 100644
--- a/targets/RT/USER/eNB_transport_IQ.c
+++ b/targets/RT/USER/eNB_transport_IQ.c
@@ -28,7 +28,7 @@
*******************************************************************************/
/*! \file eNB_transport_IQ.c
- * \brief eNB transport IQ sampels
+ * \brief eNB transport IQ samples
* \author Katerina Trilyraki, Navid Nikaein, Raymond Knopp
* \date 2015
* \version 0.1
@@ -53,158 +53,202 @@
#define PRINTF_PERIOD 3750
#define HEADER_SIZE ((sizeof(int32_t) + sizeof(openair0_timestamp))>>2)
-//#undef LOWLATENCY
-/******************************************************************************
- ** FUNCTION PROTOTYPES **
- ******************************************************************************/
-void *rrh_eNB_rx_thread(void *);
-void *rrh_eNB_tx_thread(void *);
-void *rrh_proc_eNB_thread(void *);
-void *rrh_eNB_thread(void *);
-void set_rt_period( openair0_config_t openair0_cfg);
-void check_dev_config( rrh_module_t *mod_enb);
-
-
-pthread_t main_rrh_eNB_thread;
-pthread_attr_t attr, attr_proc;
-struct sched_param sched_param_rrh;
pthread_cond_t sync_eNB_cond[4];
pthread_mutex_t sync_eNB_mutex[4];
+pthread_mutex_t sync_trx_mutex=PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t sync_trx_cond=PTHREAD_COND_INITIALIZER;
+
openair0_timestamp nrt_eNB_counter[4]= {0,0,0,0};
int32_t overflow_rx_buffer_eNB[4]= {0,0,0,0};
int32_t nsamps_eNB[4]= {0,0,0,0};
int32_t eNB_tx_started=0,eNB_rx_started=0;
int32_t counter_eNB_rx[4]= {0,0,0,0};
int32_t counter_eNB_tx[4]= {0,0,0,0};
-
uint8_t RT_flag_eNB,NRT_flag_eNB;
-int32_t **tx_buffer_eNB, **rx_buffer_eNB;
void *rrh_eNB_thread_status;
+int sync_eNB_rx[4]= {-1,-1,-1,-1};
+unsigned int sync_trx=0;
+
+int32_t **tx_buffer_eNB;
+int32_t **rx_buffer_eNB;
void **rx_eNB; //was fixed to 2 ant
void **tx_eNB; //was fixed to 2 ant
-int sync_eNB_rx[4]= {-1,-1,-1,-1};
-openair0_timestamp timestamp_eNB_tx[4]= {0,0,0,0},timestamp_eNB_rx[4]= {0,0,0,0};
+openair0_timestamp timestamp_eNB_tx[4]= {0,0,0,0};// all antennas must have the same ts
+openair0_timestamp timestamp_eNB_rx[4]= {0,0,0,0};
+openair0_timestamp timestamp_rx=0,timestamp_tx=0;
-unsigned int rx_pos=0, next_rx_pos=0;
-unsigned int tx_pos=0, prev_tx_pos=0;
+unsigned int rx_pos=0, next_rx_pos=0;
+unsigned int tx_pos=0, tx_pos_rf=0, prev_tx_pos=0;
+unsigned int rt_period=0;
+
+struct itimerspec timerspec;
+pthread_mutex_t timer_mutex;
-/*! \fn void create_eNB_trx_threads( rrh_module_t *dev_enb, uint8_t RT_flag,uint8_t NRT_flag)
+
+/*! \fn void *rrh_eNB_rx_thread(void *arg)
* \brief this function
* \param[in]
- * \param[out]
- * \return
+ * \return none
* \note
* @ingroup _oai
*/
-void create_eNB_trx_threads( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag){
+void *rrh_eNB_rx_thread(void *);
+/*! \fn void *rrh_eNB_tx_thread(void *arg)
+ * \brief this function
+ * \param[in]
+ * \return none
+ * \note
+ * @ingroup _oai
+ */
+void *rrh_eNB_tx_thread(void *);
+/*! \fn void *rrh_eNB_thread(void *arg)
+ * \brief this function
+ * \param[in]
+ * \return none
+ * \note
+ * @ingroup _oai
+ */
+void *rrh_eNB_thread(void *);
+/*! \fn void check_dev_config( rrh_module_t *mod_enb)
+ * \brief this function
+ * \param[in] *mod_enb
+ * \return none
+ * \note
+ * @ingroup _oai
+ */
+static void check_dev_config( rrh_module_t *mod_enb);
+/*! \fn void calc_rt_period_ns( openair0_config_t openair0_cfg)
+ * \brief this function
+ * \param[in] openair0_cfg
+ * \return none
+ * \note
+ * @ingroup _oai
+ */
+static void calc_rt_period_ns( openair0_config_t openair0_cfg);
+
+
+
+void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) {
- //int i;
- int error_code_eNB;
+ int error_code_eNB;
+ pthread_t main_rrh_eNB_thread;
+ pthread_attr_t attr;
+ struct sched_param sched_param_rrh;
RT_flag_eNB=RT_flag;
NRT_flag_eNB=NRT_flag;
+
+ /* handshake with client to exchange parameters */
+ mod_enb->eth_dev.trx_start_func(&mod_enb->eth_dev);//change port make it plus_id
+
+ /* if a RF iterface is added to RRH module get the configuration parameters sent from eNB */
+ if (mod_enb->devs->type != NONE_IF ) {
+
+ memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t));
+
+ /* certain parameters have to be updated (calibration related)*/
+ if ( mod_enb->devs->type == EXMIMO_IF ) {
+ if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175;
+ mod_enb->devs->openair0_cfg.tx_delay = 8;
+ }
+ else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95;
+ mod_enb->devs->openair0_cfg.tx_delay = 5;
+ }
+ else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 1024;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70;
+ mod_enb->devs->openair0_cfg.tx_delay = 6;
+ }
+ else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 256;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40;
+ mod_enb->devs->openair0_cfg.tx_delay = 8;
+ }
+ }
+ else if (mod_enb->devs->type == USRP_IF) {
+ if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175;
+ mod_enb->devs->openair0_cfg.tx_delay = 8;
+ }
+ else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95;
+ mod_enb->devs->openair0_cfg.tx_delay = 5;
+ }
+ else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 1024;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70;
+ mod_enb->devs->openair0_cfg.tx_delay = 6;
+ }
+ else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 256;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40;
+ mod_enb->devs->openair0_cfg.tx_delay = 8;
+ }
+ }
+ else if(mod_enb->devs->type == BLADERF_IF) {
+ if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175;
+ mod_enb->devs->openair0_cfg.tx_delay = 8;
+ }
+ else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95;
+ mod_enb->devs->openair0_cfg.tx_delay = 5;
+ }
+ else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 1024;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70;
+ mod_enb->devs->openair0_cfg.tx_delay = 6;
+ }
+ else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) {
+ mod_enb->devs->openair0_cfg.samples_per_packet = 256;
+ mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40;
+ mod_enb->devs->openair0_cfg.tx_delay = 8;
+ }
+ }
+
+ /* check sanity of configuration parameters and print */
+ check_dev_config(mod_enb);
+
+ /* initialize and configure the RF device */
+ if (openair0_device_init(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){
+ LOG_E(RRH,"Exiting, cannot initialize RF device.\n");
+ exit(-1);
+ }
+ else {
+ LOG_I(RRH,"RF device has been successfully initialized.\n");
+ }
+
+ /* start RF device */
+ if (mod_enb->devs->type == EXMIMO_IF ) {
+
+ } else {
+ if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0)
+ LOG_E(RRH,"Unable to initiate RF device.\n");
+ }
+ LOG_I(RRH,"RF device has been initiated.\n");
+ }
+ /* create main eNB module thread
+ main_rrh_eNB_thread allocates memory
+ for TX/RX buffers and creates TX/RX
+ threads for every eNB module */
pthread_attr_init(&attr);
sched_param_rrh.sched_priority = sched_get_priority_max(SCHED_FIFO);
pthread_attr_setschedparam(&attr,&sched_param_rrh);
pthread_attr_setschedpolicy(&attr,SCHED_FIFO);
- /*for (i=0; i<4; i++) {
- pthread_mutex_init(&sync_eNB_mutex[i],NULL);
- pthread_cond_init(&sync_eNB_cond[i],NULL);
- }*/
-
- /* handshake with client to exchange parameters */
- mod_enb->eth_dev.trx_start_func(&mod_enb->eth_dev);//change port make it plus_id
-
- memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t));
-
- /* update certain parameters */
- if ( mod_enb->devs->type == EXMIMO_IF ) {
- if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
- mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175;
- mod_enb->devs->openair0_cfg.tx_delay = 8;
- }
- else if( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ){
- mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95;
- mod_enb->devs->openair0_cfg.tx_delay = 5;
- }
- else if( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ){
- mod_enb->devs->openair0_cfg.samples_per_packet = 1024;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70;
- mod_enb->devs->openair0_cfg.tx_delay = 6;
- }
- else if( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ){
- mod_enb->devs->openair0_cfg.samples_per_packet = 256;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40;
- mod_enb->devs->openair0_cfg.tx_delay = 8;
- }
- }
- else if (mod_enb->devs->type == USRP_IF) {
- if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
- mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175;
- mod_enb->devs->openair0_cfg.tx_delay = 8;
- }
- else if( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) {
- mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95;
- mod_enb->devs->openair0_cfg.tx_delay = 5;
- }
- else if( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) {
- mod_enb->devs->openair0_cfg.samples_per_packet = 1024;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70;
- mod_enb->devs->openair0_cfg.tx_delay = 6;
- }
- else if( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) {
- mod_enb->devs->openair0_cfg.samples_per_packet = 256;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40;
- mod_enb->devs->openair0_cfg.tx_delay = 8;
- }
- }
- else if (mod_enb->devs->type == BLADERF_IF) {
- if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
- mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175;
- mod_enb->devs->openair0_cfg.tx_delay = 8;
- }
- else if( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ){
- mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95;
- mod_enb->devs->openair0_cfg.tx_delay = 5;
- }
- else if( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ){
- mod_enb->devs->openair0_cfg.samples_per_packet = 1024;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70;
- mod_enb->devs->openair0_cfg.tx_delay = 6;
- }
- else if( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ){
- mod_enb->devs->openair0_cfg.samples_per_packet = 256;
- mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40;
- mod_enb->devs->openair0_cfg.tx_delay = 8;
- }
- }
-
- /* check sanity of received configuration parameters and print */
- check_dev_config(mod_enb);
-
-#ifndef ETHERNET
- /* initialize and apply configuration to associated RF device */
- if (openair0_device_init(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){
- LOG_E(RRH,"Exiting, cannot initialize RF device.\n");
- exit(-1);
- }
- else {
- LOG_I(RRH,"RF device has been successfully initialized.\n");
- }
-
-#endif
-
error_code_eNB = pthread_create(&main_rrh_eNB_thread, &attr, rrh_eNB_thread, (void *)mod_enb);
+
if (error_code_eNB) {
LOG_E(RRH,"Error while creating eNB thread\n");
exit(-1);
@@ -212,16 +256,9 @@ void create_eNB_trx_threads( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT
}
-/*! \fn void *rrh_eNB_thread(void *arg)
- * \brief this function
- * \param[in]
- * \param[out]
- * \return
- * \note
- * @ingroup _oai
- */
-void *rrh_eNB_thread(void *arg)
-{
+
+void *rrh_eNB_thread(void *arg) {
+
rrh_module_t *dev=(rrh_module_t *)arg;
pthread_t eNB_rx_thread, eNB_tx_thread;
int error_code_eNB_rx, error_code_eNB_tx;
@@ -229,42 +266,35 @@ void *rrh_eNB_thread(void *arg)
void *tmp;
unsigned int samples_per_frame=0;
-
+ samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
+
while (rrh_exit==0) {
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX, 1 );
-
-
- if (dev->devs->type != NONE_IF) {
- set_rt_period(dev->eth_dev.openair0_cfg);
- }
- samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX, 1 );
+ /* calculate packet period */
+ calc_rt_period_ns(dev->eth_dev.openair0_cfg);
+
/* allocate memory for TX/RX buffers
each antenna port has a TX and a RX buffer
each TX and RX buffer is of (samples_per_frame + HEADER_SIZE) samples (size of samples is 4 bytes) */
rx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*));
- tx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
-
- LOG_I(RRH,"rx ch %d %p and tx ch %d %p\n",
- dev->eth_dev.openair0_cfg.rx_num_channels,
- rx_buffer_eNB,
- dev->eth_dev.openair0_cfg.tx_num_channels,
- tx_buffer_eNB);
+ tx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
+ LOG_D(RRH,"rx_buffer_eNB address =%p tx_buffer_eNB address =%p \n",rx_buffer_eNB,tx_buffer_eNB);
/* rx_buffer_eNB points to the beginning of data */
for (i=0; ieth_dev.openair0_cfg.rx_num_channels; i++) {
- tmp=(void *)malloc(sizeof(int32_t)*(samples_per_frame + HEADER_SIZE));
- memset(tmp,0,sizeof(int32_t)*(samples_per_frame + HEADER_SIZE));
- rx_buffer_eNB[i]=( tmp + (HEADER_SIZE*sizeof(int32_t)) );
- LOG_I(RRH," rx ch %d %p |%p\n",i,rx_buffer_eNB[i],tmp);
+ tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32));
+ memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32));
+ rx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) );
+ LOG_D(RRH,"i=%d rx_buffer_eNB[i]=%p tmp= %p\n",i,rx_buffer_eNB[i],tmp);
}
/* tx_buffer_eNB points to the beginning of data */
for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++) {
- tmp=(void *)malloc(sizeof(int32_t)*(samples_per_frame + HEADER_SIZE));
- memset(tmp,0,sizeof(int32_t)*(samples_per_frame + HEADER_SIZE));
- tx_buffer_eNB[i]=( tmp + (HEADER_SIZE*sizeof(int32_t)) );
- LOG_I(RRH," tx ch %d %p| %p \n", i,tx_buffer_eNB[i],tmp);
+ tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32));
+ memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32));
+ tx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) );
+ LOG_D(RRH,"i= %d tx_buffer_eNB[i]=%p tmp= %p \n",i,tx_buffer_eNB[i],tmp);
}
/* dummy initialization for TX/RX buffers */
for (i=0; ieth_dev.openair0_cfg.rx_num_channels; i++) {
@@ -277,20 +307,28 @@ void *rrh_eNB_thread(void *arg)
for (j=0; jeth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*));
tx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
-
-
+
+ /* init mutexes */
+ for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++) {
+ pthread_mutex_init(&sync_eNB_mutex[i],NULL);
+ pthread_cond_init(&sync_eNB_cond[i],NULL);
+ }
+ /* init mutexes */
+ pthread_mutex_init(&sync_trx_mutex,NULL);
+
+ /* create eNB module's TX/RX threads */
#ifdef LOWLATENCY
error_code_eNB_rx = pthread_create(&eNB_rx_thread, NULL, rrh_eNB_rx_thread, (void *)dev);
- error_code_eNB_tx = pthread_create(&eNB_tx_thread, NULL, rrh_eNB_tx_thread, (void *)dev);
+ error_code_eNB_tx = pthread_create(&eNB_tx_thread, NULL, rrh_eNB_tx_thread, (void *)dev);
LOG_I(RRH,"[eNB][SCHED] deadline scheduling applied to eNB TX/RX threads\n");
#else
pthread_attr_t attr_eNB_rx, attr_eNB_tx;
struct sched_param sched_param_eNB_rx, sched_param_eNB_tx;
+
pthread_attr_init(&attr_eNB_rx);
pthread_attr_init(&attr_eNB_tx);
sched_param_eNB_rx.sched_priority = sched_get_priority_max(SCHED_FIFO);
@@ -313,29 +351,62 @@ void *rrh_eNB_thread(void *arg)
LOG_E(RRH,"[eNB] Error while creating eNB TX thread\n");
exit(-1);
}
+
+ /* create timer thread; when no RF device is present a software clock is generated */
+ if (dev->devs->type == NONE_IF) {
+ int error_code_timer;
+ pthread_t main_timer_proc_thread;
+
+ LOG_I(RRH,"Creating timer thread with rt period %d ns.\n",rt_period);
+
+ /* setup the timer to generate an interrupt:
+ -for the first time in (sample_per_packet/sample_rate) ns
+ -and then every (sample_per_packet/sample_rate) ns */
+ timerspec.it_value.tv_sec = rt_period/1000000000;
+ timerspec.it_value.tv_nsec = rt_period%1000000000;
+ timerspec.it_interval.tv_sec = rt_period/1000000000;
+ timerspec.it_interval.tv_nsec = rt_period%1000000000;
+
+
+#ifdef LOWLATENCY
+ error_code_timer = pthread_create(&main_timer_proc_thread, NULL, timer_proc, (void *)&timerspec);
+ LOG_I(RRH,"[eNB][SCHED] deadline scheduling applied to timer thread \n");
+#else
+ pthread_attr_t attr_timer;
+ struct sched_param sched_param_timer;
+
+ pthread_attr_init(&attr_timer);
+ sched_param_timer.sched_priority = sched_get_priority_max(SCHED_FIFO-1);
+ pthread_attr_setschedparam(&attr_timer,&sched_param_timer);
+ pthread_attr_setschedpolicy(&attr_timer,SCHED_FIFO-1);
+
+ pthread_mutex_init(&timer_mutex,NULL);
+
+ error_code_timer = pthread_create(&main_timer_proc_thread, &attr_timer, timer_proc, (void *)&timerspec);
+ LOG_I(RRH,"[eNB][SCHED] FIFO scheduling applied to timer thread \n");
+#endif
+
+ if (error_code_timer) {
+ LOG_E(RRH,"Error while creating timer proc thread\n");
+ exit(-1);
+ }
+
+ }
+
while (rrh_exit==0)
sleep(1);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX,0 );
- } //while (eNB_exit==0)
-
+ }
+
rrh_eNB_thread_status = 0;
pthread_exit(&rrh_eNB_thread_status);
return(0);
}
-
-/*! \fn void *rrh_eNB_rx_thread(void *arg)
- * \brief this function
- * \param[in]
- * \param[out]
- * \return
- * \note
- * @ingroup _oai
- */
-void *rrh_eNB_rx_thread(void *arg){
+void *rrh_eNB_rx_thread(void *arg) {
/* measuremnt related vars */
struct timespec time0,time1,time2;
@@ -345,19 +416,23 @@ void *rrh_eNB_rx_thread(void *arg){
struct timespec time_req_1us, time_rem_1us;
rrh_module_t *dev = (rrh_module_t *)arg;
ssize_t bytes_sent;
- int i, spp ,pck_rx=0;
- openair0_vtimestamp last_hw_counter=0; //volatile int64_t
- unsigned int samples_per_frame=0;
+ int i=0 ,pck_rx=0, s_cnt=0;
+ openair0_timestamp last_hw_counter=0; //volatile int64_t
+ unsigned int samples_per_frame=0,samples_per_subframe=0, spp_rf=0, spp_eth=0;
uint8_t loopback=0,measurements=0;
+ unsigned int subframe=0;
+ unsigned int frame=0;
- //RTIME sleep_ns=1000;
time_req_1us.tv_sec = 0;
time_req_1us.tv_nsec =1000; //time_req_1us.tv_nsec = (int)rt_period/2;--->granularity issue
- spp = dev->eth_dev.openair0_cfg.samples_per_packet;
+ spp_eth = dev->eth_dev.openair0_cfg.samples_per_packet;
+ spp_rf = dev->devs->openair0_cfg.samples_per_packet;
+
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
+ samples_per_subframe = (unsigned int)samples_per_frame/10;
loopback = dev->loopback;
measurements = dev->measurements;
- next_rx_pos = spp;
+ next_rx_pos = spp_eth;
#ifdef LOWLATENCY
struct sched_attr attr;
@@ -369,248 +444,298 @@ void *rrh_eNB_rx_thread(void *arg){
attr.sched_priority = 0;
attr.sched_policy = SCHED_DEADLINE;
- attr.sched_runtime = (0.1 * 100) * 10000; //
- attr.sched_deadline = rt_period;// 0.1 * 1000000; //
- attr.sched_period = rt_period; //0.1 * 1000000; // each TX/RX thread has
-
+ attr.sched_runtime = (0.8 * 100) * 10000;//4 * 10000;
+ attr.sched_deadline = (0.9 * 100) * 10000;//rt_period-2000;
+ attr.sched_period = 1 * 1000000;//rt_period;
+
if (sched_setattr(0, &attr, flags) < 0 ) {
perror("[SCHED] eNB RX thread: sched_setattr failed (run with sudo)\n");
exit(-1);
}
#endif
- while (rrh_exit == 0) {
-
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 1 );
- VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_HWCNT, hw_counter );
- VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_LHWCNT, last_hw_counter );
- VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK, pck_rx );
-
- for (i=0; ieth_dev.openair0_cfg.rx_num_channels; i++){
- if (!eNB_rx_started) {
- eNB_rx_started=1; // set this flag to 1 to indicate that eNB started
- if (RT_flag_eNB==1) {
- last_hw_counter=hw_counter;
- }
- } else {
- if (RT_flag_eNB==1) {
- if (hw_counter > last_hw_counter+1) {
- printf("LR");
- } else {
- while (hw_counter < last_hw_counter+1){
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP, 1 );
- nanosleep(&time_req_1us,&time_rem_1us);
- //rt_sleep_ns(sleep_ns);
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP, 0 );
- }
+ while (rrh_exit == 0) {
+ while (rx_pos <(1 + subframe)*samples_per_subframe) {
+ LOG_D(RRH,"starting a new send:%d %d\n",sync_trx,frame);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 1 );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME_RX, frame);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME_RX, subframe );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK, pck_rx );
+ LOG_D(RRH,"pack=%d rx_pos=%d subframe=%d frame=%d\n ",pck_rx, rx_pos, subframe,frame);
+
+ if (dev->devs->type == NONE_IF) {
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_HWCNT, hw_counter );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_LHWCNT, last_hw_counter );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_CNT, s_cnt );
+ if (!eNB_rx_started) {
+ eNB_rx_started=1; // set this flag to 1 to indicate that eNB started
+ if (RT_flag_eNB==1) {
+ last_hw_counter=hw_counter;//get current counter
+ }
+ } else {
+ if (RT_flag_eNB==1) {
+ if (hw_counter > last_hw_counter+1) {
+ printf("LR");
+ } else {
+ while ((hw_counter < last_hw_counter+1)) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP, 1 );
+ nanosleep(&time_req_1us,&time_rem_1us); //rt_sleep_ns(sleep_ns);
+ s_cnt++;
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP, 0 );
+ }
+ }
}
}
}
-
- if (measurements == 1 )
- clock_gettime(CLOCK_MONOTONIC,&time1);
- /* LOG_I(RRH,"send for%d at %d with %d |%d|%d| \n",i,rx_pos,timestamp_eNB_rx[i],((timestamp_eNB_rx[i]+spp)%samples_per_frame),next_rx_pos );
-
- if ((timestamp_UE_tx[i]%samples_per_frame < next_rx_pos) && (UE_tx_started==1)) {
- printf("eNB underflow\n");
- if (NRT_flag_eNB==1) {
- while ((timestamp_UE_tx[i]%samples_per_frame) < spp)
- nanosleep(&time_req_1us,&time_rem_1us);
- }
- }
- if (((rx_pos)< timestamp_UE_tx[i]%samples_per_frame) && (next_rx_pos > (timestamp_UE_tx[i]%samples_per_frame)) && (UE_tx_started==1)) {
- printf("eNB underflow\n");
- if (NRT_flag_eNB==1) {
- while (next_rx_pos > (timestamp_UE_tx[i]%samples_per_frame))
- nanosleep(&time_req_1us,&time_rem_1us);
- }
- }*/
+ if (measurements == 1 ) clock_gettime(CLOCK_MONOTONIC,&time1);
+
if (loopback == 1 ) {
if (sync_eNB_rx[i]==0) {
rx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos];
LOG_I(RRH,"tx_buffer_eNB[i][tx_pos]=%d ,tx_pos=%d\n",tx_buffer_eNB[i][tx_pos],tx_pos);
- }
- else{
+ } else {
rx_eNB[i] = (void*)&rx_buffer_eNB[i][rx_pos];
LOG_I(RRH,"rx_buffer_eNB[i][rx_pos]=%d ,rx_pos=%d\n",rx_buffer_eNB[i][rx_pos],rx_pos);
}
- }
+ }
+
+ for (i=0; ieth_dev.openair0_cfg.rx_num_channels; i++) {
+ rx_eNB[i] = (void*)&rx_buffer_eNB[i][rx_pos];
+ LOG_D(RRH," rx_eNB[i]=%p rx_buffer_eNB[i][rx_pos]=%p ,rx_pos=%d, i=%d ts=%d\n",rx_eNB[i],&rx_buffer_eNB[i][rx_pos],rx_pos,i,timestamp_rx);
+ }
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos );
+ if (dev->devs->type != NONE_IF) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF, 1 );
+ /* Read operation to RF device (RX)*/
+ if ( dev->devs->trx_read_func (dev->devs,
+ ×tamp_rx,
+ rx_eNB,
+ spp_rf,
+ dev->devs->openair0_cfg.rx_num_channels
+ )<0) {
+ perror("RRH eNB : USRP read");
+ }
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF, 0 );
+ }
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_TS, timestamp_rx&0xffffffff );
- rx_eNB[i] = (void*)&rx_buffer_eNB[i][rx_pos];
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
+ if ((bytes_sent = dev->eth_dev.trx_write_func (&dev->eth_dev,
+ timestamp_rx,
+ rx_eNB,
+ spp_eth,
+ dev->eth_dev.openair0_cfg.rx_num_channels,
+ 0))<0) {
+ perror("RRH eNB : ETHERNET write");
+ }
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
- VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos );
- VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_TS, timestamp_eNB_rx[i]&0xffffffff );
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
-
- //LOG_D(RRH," rx_eNB[i]=%p rx_buffer_eNB[i][rx_pos]=%p ,rx_pos=%d, i=%d ts=%d\n",rx_eNB[i],&rx_buffer_eNB[i][rx_pos],rx_pos,i,timestamp_eNB_rx[i]);
- if ((bytes_sent = dev->eth_dev.trx_write_func (&dev->eth_dev,
- timestamp_eNB_rx[i],
- rx_eNB,
- spp,
- i,
- 0))<0){
- perror("RRH eNB : sendto for RX");
- }
+ /* when there is no RF timestamp is updated by number of samples */
+ if (dev->devs->type == NONE_IF) {
+ timestamp_rx+=spp_eth;
+ last_hw_counter=hw_counter;
+ }
+
+ if (measurements == 1 ) {
+
+ clock_gettime(CLOCK_MONOTONIC,&time2);
+
+ if (trace_cnt++ > 10) {
+ total_rx_time = (unsigned int)(time2.tv_nsec - time0.tv_nsec);
+ if (total_rx_time < 0)
+ total_rx_time=1000000000-total_rx_time;
+
+ if ((total_rx_time > 0) && (total_rx_time < 1000000000)) {
+ trial++;
+ if (total_rx_time < min_rx_time)
+ min_rx_time = total_rx_time;
+ if (total_rx_time > max_rx_time){
+ max_rx_time = total_rx_time;
+ LOG_I(RRH,"Max value %d update at rx_position %d \n",total_rx_time,timestamp_rx);
+ }
+ average_rx_time = (long long unsigned int)((average_rx_time*trial)+total_rx_time)/(trial+1);
+ }
+ if (s_period++ == PRINTF_PERIOD) {
+ s_period=0;
+ LOG_I(RRH,"Average eNB RX time : %lu\tMax RX time : %lu\tMin RX time : %lu\n",average_rx_time,max_rx_time,min_rx_time);
+ }
+ }
+
+ memcpy(&time0,&time2,sizeof(struct timespec));
+ }
+
+ if (loopback == 1 ) {
+ pthread_mutex_lock(&sync_eNB_mutex[i]);
+ sync_eNB_rx[i]--;
+ pthread_mutex_unlock(&sync_eNB_mutex[i]);
+ }
+
+ rx_pos += spp_eth;
+ pck_rx++;
+ next_rx_pos=(rx_pos+spp_eth);
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 0 );
+ /**/
+ if (frame>50) {
+ pthread_mutex_lock(&sync_trx_mutex);
+ while (sync_trx) {
+ pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex);
+ }
+ sync_trx=1;
+ LOG_D(RRH,"out of while send:%d %d\n",sync_trx,frame);
+ pthread_cond_signal(&sync_trx_cond);
+ pthread_mutex_unlock(&sync_trx_mutex);
+ }
+ } // while
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
-
- timestamp_eNB_rx[i]+=spp;
- last_hw_counter=hw_counter;
-
- if (measurements == 1 ) {
-
- clock_gettime(CLOCK_MONOTONIC,&time2);
-
- if (trace_cnt++ > 10) {
- total_rx_time = (unsigned int)(time2.tv_nsec - time0.tv_nsec);
- if (total_rx_time < 0)
- total_rx_time=1000000000-total_rx_time;
-
- if ((total_rx_time > 0) && (total_rx_time < 1000000000)) {
- trial++;
- if (total_rx_time < min_rx_time)
- min_rx_time = total_rx_time;
- if (total_rx_time > max_rx_time){
- max_rx_time = total_rx_time;
- LOG_I(RRH,"Max value %d update at rx_position %d \n",total_rx_time,timestamp_eNB_rx[i]);
- }
- average_rx_time = (long long unsigned int)((average_rx_time*trial)+total_rx_time)/(trial+1);
- }
- if (s_period++ == PRINTF_PERIOD) {
- s_period=0;
- LOG_I(RRH,"Average eNB RX time : %lu\tMax RX time : %lu\tMin RX time : %lu\n",average_rx_time,max_rx_time,min_rx_time);
- }
- }
-
- memcpy(&time0,&time2,sizeof(struct timespec));
- }
-
- if (loopback == 1 ){
- pthread_mutex_lock(&sync_eNB_mutex[i]);
- sync_eNB_rx[i]--;
- pthread_mutex_unlock(&sync_eNB_mutex[i]);
- }
-
- }//for each antenna
+ subframe++;
+ s_cnt=0;
- rx_pos += spp;
- pck_rx++;
- next_rx_pos=(rx_pos+spp);
-
+ /* wrap around rx buffer index */
if (next_rx_pos >= samples_per_frame)
next_rx_pos -= samples_per_frame;
if (rx_pos >= samples_per_frame)
rx_pos -= samples_per_frame;
-
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 0 );
+ /* wrap around subframe number */
+ if (subframe == 10 ) {
+ subframe = 0;
+ frame++;
+ }
+
+
} //while (eNB_exit==0)
- return(0);
+ return 0;
}
-/*! \fn void *rrh_eNB_tx_thread(void *arg)
- * \brief this function
- * \param[in]
- * \param[out]
- * \return
- * \note
- * @ingroup _oai
- */
-void *rrh_eNB_tx_thread(void *arg){
+void *rrh_eNB_tx_thread(void *arg) {
struct timespec time0a,time0,time1,time2;
rrh_module_t *dev = (rrh_module_t *)arg;
struct timespec time_req_1us, time_rem_1us;
ssize_t bytes_received;
- int spp,i;
+ int i;
openair0_timestamp last_hw_counter=0;
- unsigned int samples_per_frame=0;
+ unsigned int samples_per_frame=0,samples_per_subframe=0;
+ unsigned int spp_rf=0, spp_eth=0;
uint8_t loopback=0,measurements=0;
-
+ unsigned int subframe=0,frame=0;
+ unsigned int pck_tx=0;
+
#ifdef LOWLATENCY
struct sched_attr attr;
unsigned int flags = 0;
-
+
attr.size = sizeof(attr);
attr.sched_flags = 0;
attr.sched_nice = 0;
attr.sched_priority = 0;
-
+
attr.sched_policy = SCHED_DEADLINE;
- attr.sched_runtime = (0.1 * 100) * 10000; //
- attr.sched_deadline = rt_period;//0.1 * 1000000; //
- attr.sched_period = rt_period;//0.1 * 1000000; // each TX/RX thread has
-
+ attr.sched_runtime = (0.8 * 100) * 10000;
+ attr.sched_deadline = (0.9 * 100) * 10000;
+ attr.sched_period = 1 * 1000000;
+
if (sched_setattr(0, &attr, flags) < 0 ) {
perror("[SCHED] eNB TX thread: sched_setattr failed\n");
exit(-1);
}
#endif
-
- tx_pos=0;
- time_req_1us.tv_sec = 0;
- time_req_1us.tv_nsec = 1000;
- spp = dev->eth_dev.openair0_cfg.samples_per_packet;
+
+ time_req_1us.tv_sec = 1;
+ time_req_1us.tv_nsec = 0;
+ spp_eth = dev->eth_dev.openair0_cfg.samples_per_packet;
+ spp_rf = dev->devs->openair0_cfg.samples_per_packet;
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
+ samples_per_subframe = (unsigned int)samples_per_frame/10;
+ tx_pos=0;
+ //tx_pos_rf=spp_rf*dev->devs->openair0_cfg.tx_delay;
+
loopback = dev->loopback;
measurements = dev->measurements;
- while (rrh_exit == 0) {
-
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 1 );
- VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT, hw_counter );
- VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT, last_hw_counter );
-
- if (measurements == 1 )
- clock_gettime(CLOCK_MONOTONIC,&time0a);
-
- for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++){
- if (!eNB_tx_started) {
- eNB_tx_started=1; // set this flag to 1 to indicate that eNB started
- if (RT_flag_eNB==1) {
- last_hw_counter=hw_counter;
- }
- } else {
- if (RT_flag_eNB==1) {
- if (hw_counter > last_hw_counter+1) {
- printf("LT");
- } else {
- while (hw_counter < last_hw_counter+1){
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 1 );
- nanosleep(&time_req_1us,&time_rem_1us);
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 0 );
- }
- }
- }
+ while (rrh_exit == 0) {
+ while (tx_pos < (1 + subframe)*samples_per_subframe) {
+
+ LOG_D(RRH,"bef lock read:%d %d\n",sync_trx,frame);
+ pthread_mutex_lock(&sync_trx_mutex);
+
+ while (!sync_trx) {
+ LOG_D(RRH,"in sync read:%d %d\n",sync_trx,frame);
+ pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex);
}
-
- if (measurements == 1 )
- clock_gettime(CLOCK_MONOTONIC,&time1);
-
- tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos];
+ LOG_D(RRH,"out of while read:%d %d\n",sync_trx,frame);
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 1 );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, subframe );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK, pck_tx );
+
+ /*
+ if (dev->devs->type == NONE_IF) {
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT, hw_counter );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT, last_hw_counter );
+
+ if (!eNB_tx_started) {
+ eNB_tx_started=1; // set this flag to 1 to indicate that eNB started
+ if (RT_flag_eNB==1) {
+ last_hw_counter=hw_counter;
+ }
+ } else {
+ if (RT_flag_eNB==1) {
+ if (hw_counter > last_hw_counter+1) {
+ printf("LT");
+ } else {
+ while ((hw_counter < last_hw_counter+1)) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 1 );
+ nanosleep(&time_req_1us,&time_rem_1us);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 0 );
+ }
+ }
+ }
+ }
+ } */
+
+ if (measurements == 1 ) clock_gettime(CLOCK_MONOTONIC,&time1);
+ for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++) tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos]; //RF!!!!!
+
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TXCNT, tx_pos );
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
- bytes_received = dev->eth_dev.trx_read_func(&dev->eth_dev,
- ×tamp_eNB_tx[i],
- tx_eNB,
- spp,
- i);
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
- VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_TS, timestamp_eNB_tx[i]&0xffffffff );
- if (NRT_flag_eNB==1) {
- nrt_eNB_counter[i]++;
- }
- prev_tx_pos=tx_pos;
- tx_pos += spp;
-
- if (tx_pos >= samples_per_frame)
- tx_pos -= samples_per_frame;
- last_hw_counter=hw_counter;
-
+ /* Read operation to ETHERNET device */
+ if (( bytes_received = dev->eth_dev.trx_read_func(&dev->eth_dev,
+ ×tamp_tx,
+ tx_eNB,
+ spp_eth,
+ dev->eth_dev.openair0_cfg.tx_num_channels))<0) {
+ perror("RRH eNB : ETHERNET read");
+ }
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
+
+ if (dev->devs->type != NONE_IF) {
+ LOG_D(RRH," tx_buffer_eNB[i][tx_pos]=%x t_buffer_eNB[i][tx_pos+1]=%x t_buffer_eNB[i][tx_pos+2]=%x \n",tx_buffer_eNB[0][tx_pos],tx_buffer_eNB[0][tx_pos+1],tx_buffer_eNB[0][tx_pos+2]);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF, 1 );
+ /* Write operation to RF device (TX)*/
+ if ( dev->devs->trx_write_func (dev->devs,
+ timestamp_tx,
+ tx_eNB,
+ spp_rf,
+ dev->devs->openair0_cfg.tx_num_channels,
+ 0)<0){
+ perror("RRH eNB : USRP write");
+ }
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF, 0 );
+ }
+
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_TS, timestamp_tx&0xffffffff );
+
+
+ if (dev->devs->type == NONE_IF) last_hw_counter=hw_counter;
+
+
if (loopback ==1 ) {
while (sync_eNB_rx[i]==0)
nanosleep(&time_req_1us,&time_rem_1us);
@@ -618,30 +743,47 @@ void *rrh_eNB_tx_thread(void *arg){
pthread_mutex_lock(&sync_eNB_mutex[i]);
sync_eNB_rx[i]++;
pthread_mutex_unlock(&sync_eNB_mutex[i]);
- }
+ }
- }
- if (measurements == 1 ) {
- clock_gettime(CLOCK_MONOTONIC,&time2);
- memcpy(&time0,&time2,sizeof(struct timespec));
+ if (measurements == 1 ) {
+ clock_gettime(CLOCK_MONOTONIC,&time2);
+ memcpy(&time0,&time2,sizeof(struct timespec));
+ }
+
+ prev_tx_pos=tx_pos;
+ tx_pos += spp_eth;
+ pck_tx++;
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 );
+ sync_trx=0;
+ pthread_cond_signal(&sync_trx_cond);
+ pthread_mutex_unlock(&sync_trx_mutex);
}
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 );
- }
- return(0);
+ /* wrap around tx buffer index */
+ if (tx_pos >= samples_per_frame)
+ tx_pos -= samples_per_frame;
+ /* wrap around subframe number */
+ subframe++;
+ if (subframe == 10 ) {
+ subframe = 0; // the radio frame is complete, start over
+ frame++;
+ }
+
+ } //while (eNB_exit==0)
+ return 0;
}
-//needs to be fixed
-void set_rt_period( openair0_config_t openair0_cfg){
+
+static void calc_rt_period_ns( openair0_config_t openair0_cfg) {
rt_period= (double)(openair0_cfg.samples_per_packet/(openair0_cfg.samples_per_frame/10.0)*1000000);
AssertFatal(rt_period > 0, "Invalid rt period !%u\n", rt_period);
- //only in case of NRT with emulated UE
- //create_timer_thread();
+ LOG_I(RRH,"[eNB] Real time period is set to %u ns\n", rt_period);
}
-void check_dev_config( rrh_module_t *mod_enb) {
+static void check_dev_config( rrh_module_t *mod_enb) {
AssertFatal( (mod_enb->devs->openair0_cfg.num_rb_dl==100 || mod_enb->devs->openair0_cfg.num_rb_dl==50 || mod_enb->devs->openair0_cfg.num_rb_dl==25 || mod_enb->devs->openair0_cfg.num_rb_dl==6) , "Invalid number of resource blocks! %d\n", mod_enb->devs->openair0_cfg.num_rb_dl);
@@ -656,7 +798,7 @@ void check_dev_config( rrh_module_t *mod_enb) {
AssertFatal( mod_enb->devs->openair0_cfg.tx_gain[0] > 0.0 ,"Invalid TX gain! %f\n", mod_enb->devs->openair0_cfg.tx_gain[0]);
AssertFatal( mod_enb->devs->openair0_cfg.rx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.rx_bw);
AssertFatal( mod_enb->devs->openair0_cfg.tx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.tx_bw);
- // AssertFatal( mod_enb->devs->openair0_cfg.autocal[0] > 0 , "Invalid auto calibration choice! %d\n", mod_enb->devs->openair0_cfg.autocal[0]);
+ AssertFatal( mod_enb->devs->openair0_cfg.autocal[0] > 0 , "Invalid auto calibration choice! %d\n", mod_enb->devs->openair0_cfg.autocal[0]);
printf("\n---------------------RF device configuration parameters---------------------\n");
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 1867e6181d..2faa4e796d 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -2991,23 +2991,7 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
openair0.func_type = BBU_FUNC;
openair0_cfg[0].log_level = glog_level;
-
-#ifdef ETHERNET
- openair0.type=ETH_IF; // not used for the moment
- openair0.func_type = BBU_FUNC;
- openair0_dev_init_eth(&openair0, &openair0_cfg[0]);
-#else
-#ifdef EXMIMO
- openair0.type=EXMIMO_IF;
- printf("Setting the HW to EXMIMO and initializing openair0 ...\n");
-#elif OAI_USRP
- openair0.type=USRP_IF;
- printf("Setting the HW to USRP and initializing openair0 ...\n");
-#elif OAI_BLADERF
- openair0.type=BLADERF_IF;
- printf("Setting the HW to BLADERF and initializing openair0 ...\n");
-#endif
-
+
if ((mode!=loop_through_memory) &&
(openair0_device_init(&openair0, &openair0_cfg[0]) <0)) {
printf("Exiting, cannot initialize device\n");
@@ -3015,8 +2999,7 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
}
else if (mode==loop_through_memory) {
}
-#endif
-
+
printf("Done\n");
mac_xface = malloc(sizeof(MAC_xface));
diff --git a/targets/RT/USER/rrh.c b/targets/RT/USER/rrh.c
index 7e4e549351..ff4776754b 100644
--- a/targets/RT/USER/rrh.c
+++ b/targets/RT/USER/rrh.c
@@ -58,8 +58,8 @@
#define RRH_UE_PORT 51000
#define RRH_UE_DEST_IP "127.0.0.1"
-#define FRAME_MAX_SIZE 307200
-#define DEFAULT_PERIOD_NS 133333
+#define FRAME_MAX_SIZE 307200//76800
+#define DEFAULT_PERIOD_NS 133333//200000
#define START_CMD 1
#define PRINTF_PERIOD 3750
diff --git a/targets/RT/USER/rrh.gtkw b/targets/RT/USER/rrh.gtkw
index 8eb2333489..22a5a9f575 100644
--- a/targets/RT/USER/rrh.gtkw
+++ b/targets/RT/USER/rrh.gtkw
@@ -1,25 +1,29 @@
[*]
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
-[*] Thu Jul 9 09:53:25 2015
+[*] Thu Sep 17 14:23:43 2015
[*]
[dumpfile] "/tmp/openair_dump_rrh.vcd"
-[dumpfile_mtime] "Thu Jul 9 09:52:29 2015"
-[dumpfile_size] 170586112
-[savefile] "/home/sud/openair4G/targets/RT/USER/eNB2.gtkw"
-[timestart] 16177999000
-[size] 1535 876
+[dumpfile_mtime] "Thu Sep 17 14:21:43 2015"
+[dumpfile_size] 636509125
+[savefile] "/home/guepe/openair4G/targets/RT/USER/rrh.gtkw"
+[timestart] 17746655400
+[size] 1855 1056
[pos] -1 -1
-*-17.749426 16178576148 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+*-15.826077 17746846200 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[sst_width] 224
[signals_width] 230
[sst_expanded] 1
-[sst_vpaned_height] 230
+[sst_vpaned_height] 287
+@24
+[color] 1
+variables.hw_frame_rx[63:0]
+[color] 1
+variables.hw_subframe_rx[63:0]
@28
[color] 1
functions.eNB_rx
functions.eNB_rx_sleep
-[color] 7
-functions.trx_write
+functions.trx_write_rf
@c00024
variables.rxcnt[63:0]
@28
@@ -89,23 +93,27 @@ variables.rxcnt[63:0]
(63)variables.rxcnt[63:0]
@1401200
-group_end
+@24
+variables.pck_rx[63:0]
+variables.hw_frame[63:0]
+variables.hw_subframe[63:0]
@28
[color] 1
functions.eNB_tx
functions.eNB_tx_sleep
+functions.trx_read_rf
+[color] 7
+functions.trx_write
[color] 7
functions.trx_read
@24
variables.txcnt[63:0]
variables.rx_ts[63:0]
variables.tx_ts[63:0]
-variables.pck_rx[63:0]
variables.hw_cnt_rx[63:0]
variables.lhw_cnt_rx[63:0]
-variables.hw_frame[63:0]
-@28
-functions.eNB_tm
-@29
-functions.eNB_trx
+@25
+[color] 3
+variables.cnt[63:0]
[pattern_trace] 1
[pattern_trace] 0
diff --git a/targets/RT/USER/rrh_gw.c b/targets/RT/USER/rrh_gw.c
index 204dc6d0b6..2ff213b147 100644
--- a/targets/RT/USER/rrh_gw.c
+++ b/targets/RT/USER/rrh_gw.c
@@ -60,17 +60,17 @@
#include "log_extern.h"
#include "vcd_signal_dumper.h"
-//#undef LOWLATENCY
+/*****************************************************************************************
+ * ---------- *
+ * ------- RRH_BBU_IF ------- RRH_RF_IF -------USRP - COTS_UE- *
+ * - BBU - --------------- - RRH - ------------- -------BLADERF ---------- *
+ * ------- ------- -------EXMIMO *
+ * --------- *
+ * -------ETH_IF - EMU_UE- *
+ * --------- *
+ *****************************************************************************************/
+
-/******************************************************************************
- ** FUNCTION PROTOTYPES **
- ******************************************************************************/
-static void debug_init(void);
-static void get_options(int argc, char *argv[]);
-static void print_help(void);
-static void get_RFinterfaces(void);
-static rrh_module_t new_module(unsigned int id);
-int get_ip_address(char* if_name);
char rrh_ip[20] = "192.168.12.242"; // there is code to detect the my ip address
int rrh_port = 50000; // has to be an option
@@ -98,25 +98,51 @@ uint8_t measurements_flag=0;
/* Default operation as RRH:
- there are neither eNB nor UE modules
- - no RF device is asscociated with RRH */
+ - no RF hardware is specified (NONE_IF)
+ - default ethernet interface is local */
uint8_t num_eNB_mod=0;
uint8_t num_UE_mod=0;
uint8_t num_EXMIMO_mod=0;
uint8_t num_USRP_mod=0;
uint8_t hardware_target=NONE_IF;
+char* if_name="lo";
rrh_module_t *enb_array;
rrh_module_t *ue_array;
-pthread_mutex_t timer_mutex;
openair0_vtimestamp hw_counter=0;
-unsigned int rt_period=0;
-struct itimerspec timerspec;
-char* if_name="lo";
+
+
+
+static void debug_init(void);
+static void get_options(int argc, char *argv[]);
+static void print_help(void);
+
+/*!\fn static rrh_module_t new_module(unsigned int id);
+* \brief creation of a eNB/UE module
+* \param[in] module id
+* \return module
+* \note
+* @ingroup _oai
+*/
+static rrh_module_t new_module(unsigned int id);
+
+/*!\fn static int get_ip_address(char* if_name)
+ * \brief retrieves IP address from the specified network interface
+ * \param[in] name of network interface
+ * \return 0
+ * \note
+ * @ingroup _oai
+ */
+static int get_ip_address(char* if_name);
+
+
+
+
int main(int argc, char **argv) {
-
+
unsigned int i;
/* parse input arguments */
@@ -125,58 +151,16 @@ int main(int argc, char **argv) {
debug_init();
/* */
set_latency_target();
- /*make a graceful exit when ctrl-c is pressed */
+ /* make a graceful exit when ctrl-c is pressed */
signal(SIGSEGV, signal_handler);
signal(SIGINT, signal_handler);
- /*probe RF front end devices interfaced to RRH */
- // get_RFinterfaces();
-
-#ifdef ETHERNET
- int error_code_timer;
- pthread_t main_timer_proc_thread;
-
- LOG_I(RRH,"Creating timer thread with rt period %d ns.\n",rt_period);
-
- /* setup the timer to generate an interrupt:
- -for the first time in (sample_per_packet/sample_rate) ns
- -and then every (sample_per_packet/sample_rate) ns */
- timerspec.it_value.tv_sec = rt_period/1000000000;
- timerspec.it_value.tv_nsec = rt_period%1000000000;
- timerspec.it_interval.tv_sec = rt_period/1000000000;
- timerspec.it_interval.tv_nsec = rt_period%1000000000;
-
-
- //#ifndef LOWLATENCY
- pthread_attr_t attr_timer;
- struct sched_param sched_param_timer;
-
- pthread_attr_init(&attr_timer);
- sched_param_timer.sched_priority = sched_get_priority_max(SCHED_FIFO);
- pthread_attr_setschedparam(&attr_timer,&sched_param_timer);
- pthread_attr_setschedpolicy(&attr_timer,SCHED_FIFO);
-
- pthread_mutex_init(&timer_mutex,NULL);
-
- error_code_timer = pthread_create(&main_timer_proc_thread, &attr_timer, timer_proc, (void *)&timerspec);
- LOG_I(RRH,"[SCHED] FIFO scheduling applied to timer thread \n");
- /*#else
- error_code_timer = pthread_create(&main_timer_proc_thread, NULL, timer_proc, (void *)&timerspec);
- LOG_I(RRH,"[SCHED] deadline scheduling applied to timer thread \n");
- #endif*/
-
- if (error_code_timer) {
- LOG_E(RRH,"Error while creating timer proc thread\n");
- exit(-1);
- }
-#endif
-
/* create modules based on input arguments */
if (eNB_flag==1){
enb_array=(rrh_module_t*)malloc(num_eNB_mod*sizeof(rrh_module_t));
for(i=0;isin_addr));
+ LOG_I(RRH,"Got IP address %s from interface %s\n", rrh_ip,if_name);
- ioctl(fd, SIOCGIFADDR, &ifr);
-
- close(fd);
-
- /* display result */
- snprintf(&rrh_ip[0],20,"%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
- printf("Got IP address %s from interface %s\n", rrh_ip,if_name);
- return 0;
+ return 0;
}
-/*!\fn void print_help(void)
-* \brief this function
-* \param[in]
-* \param[out]
-* \return
-* \note
-* @ingroup _oai
-*/
+
static void print_help(void) {
puts("Usage: \n");
@@ -504,7 +348,7 @@ static void print_help(void) {
puts("\t -n create eNB module\n");
puts("\t -u create UE module\n");
puts("\t -g define global log level\n");
- puts("\t -i set the RRH interface (default eth0)\n");
+ puts("\t -i set the RRH interface (default lo)\n");
puts("\t -r define rrh log level\n");
puts("\t -e define eNB log level\n");
puts("\t -x enable real time bahaviour\n");
@@ -516,16 +360,85 @@ static void print_help(void) {
}
-/*! \fn void exit_fun(const char* s)
-* \brief this function
-* \param[in]
-* \param[out]
-* \return
-* \note
-* @ingroup _oai
-*/
-void exit_fun(const char* s)
-{
+
+void *timer_proc(void *arg) {
+
+ timer_t timerid;
+ struct itimerspec *timer= (struct itimerspec *)arg ; // the timer data structure
+ struct itimerspec *old_value;
+
+
+#ifdef LOWLATENCY
+ struct sched_attr attr;
+ unsigned int flags = 0;
+
+ attr.size = sizeof(attr);
+ attr.sched_flags = 0;
+ attr.sched_nice = 0;
+ attr.sched_priority = 0;
+
+ attr.sched_policy = SCHED_DEADLINE;
+ attr.sched_runtime = (0.1 * 100) * 10000; //
+ attr.sched_deadline = rt_period-30000;//(0.1 * 100) * 10000;
+ attr.sched_period = rt_period;//(0.1 * 100) * 10000; // each TX/RX thread has, as a function of RT PERIOD ??
+
+ if (sched_setattr(0, &attr, flags) < 0 ) {
+ perror("[SCHED] timer thread: sched_setattr failed\n");
+ exit(-1);
+ }
+#endif
+
+ if (timer_create (CLOCK_REALTIME, NULL, &timerid) == -1) {
+ fprintf (stderr, "couldn't create a timer\n");
+ perror (NULL);
+ exit (EXIT_FAILURE);
+ }
+
+ signal(SIGALRM, timer_signal_handler);
+ LOG_I(RRH,"Timer has started!\n");
+ timer_settime (timerid, 0, timer, old_value);
+
+ while (!rrh_exit) {
+ sleep(1);
+ }
+
+ timer_delete(timerid);
+
+ return (0);
+}
+
+
+void timer_signal_handler(int sig) {
+
+ if (sig == SIGALRM) {
+ pthread_mutex_lock(&timer_mutex);
+ hw_counter ++;
+ pthread_mutex_unlock(&timer_mutex);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_CNT, hw_counter);//USED ELSEWHERE
+ }
+}
+
+
+void signal_handler(int sig) {
+
+ void *array[10];
+ size_t size;
+
+ if (sig==SIGSEGV) {
+ // get void*'s for all entries on the stack
+ size = backtrace(array, 10);
+
+ // print out all the frames to stderr
+ fprintf(stderr, "Error: signal %d:\n", sig);
+ backtrace_symbols_fd(array, size, 2);
+ exit(-1);
+ } else {
+ printf("trying to exit gracefully...\n");
+ rrh_exit = 1;
+ }
+}
+
+void exit_fun(const char* s) {
if (s != NULL) {
printf("%s %s() Exiting RRH: %s\n",__FILE__, __FUNCTION__, s);
}
@@ -534,66 +447,3 @@ void exit_fun(const char* s)
}
-/*! \fn static void get_RFinterfaces(void)
-* \brief this function
-* \param[in]
-* \param[out]
-* \return
-* \note
-* @ingroup _oai
-*/
-static void get_RFinterfaces(void) {
-
- EXMIMO_flag=1;
- USRP_flag=1;
- num_EXMIMO_mod=1;
- num_USRP_mod=1;
-
-}
-
-
-/*!\fn void create_timer_thread(void)
-* \brief this function
-* \param[in]
-* \param[out]
-* \return
-* \note
-* @ingroup _oai
-*/
-void create_timer_thread() {
-
- int error_code_timer;
- pthread_t main_timer_proc_thread;
-
- LOG_I(RRH,"Creating timer thread with rt period %d ns.\n",rt_period);
-
- /* setup the timer to generate an interrupt:
- -for the first time in (sample_per_packet/sample_rate) ns
- -and then every (sample_per_packet/sample_rate) ns */
- timerspec.it_value.tv_sec = rt_period/1000000000;
- timerspec.it_value.tv_nsec = rt_period%1000000000;
- timerspec.it_interval.tv_sec = rt_period/1000000000;
- timerspec.it_interval.tv_nsec = rt_period%1000000000;
-
- pthread_mutex_init(&timer_mutex,NULL);
-
-#ifndef LOWLATENCY
- pthread_attr_t attr_timer;
- struct sched_param sched_param_timer;
-
- pthread_attr_init(&attr_timer);
- sched_param_timer.sched_priority = sched_get_priority_max(SCHED_FIFO-1);
- pthread_attr_setschedparam(&attr_timer,&sched_param_timer);
- pthread_attr_setschedpolicy(&attr_timer,SCHED_FIFO-1);
- error_code_timer = pthread_create(&main_timer_proc_thread, &attr_timer, timer_proc, (void *)&timerspec);
- LOG_I(RRH,"[SCHED] FIFO scheduling applied to timer thread \n");
-#else
- error_code_timer = pthread_create(&main_timer_proc_thread, NULL, timer_proc, (void *)&timerspec);
- LOG_I(RRH,"[SCHED] deadline scheduling applied to timer thread \n");
-#endif
-
- if (error_code_timer) {
- LOG_E(RRH,"Error while creating timer proc thread\n");
- exit(-1);
- }
-}
diff --git a/targets/RT/USER/rrh_gw.h b/targets/RT/USER/rrh_gw.h
index 7d6d89b9d1..37852c3b11 100644
--- a/targets/RT/USER/rrh_gw.h
+++ b/targets/RT/USER/rrh_gw.h
@@ -45,41 +45,68 @@
#include "vcd_signal_dumper.h"
#include "assertions.h"
-#define DEFAULT_PERIOD_NS 200000
+#define DEFAULT_PERIOD_NS 200000 /* default value is calculated for 25 PRB */
#define RRH_UE_PORT 51000
#define RRH_UE_DEST_IP "127.0.0.1"
/*! \brief RRH supports two types of modules: eNB and UE
- each module is associated a device of type ETH_IF
- and optionally with an RF device (USRP/BLADERF/EXMIMO) */
+ each module is associated with an ethernet device (device of ETH_IF)
+ and optionally with a RF device (device type can be USRP_IF/BLADERF_IF/EXMIMO_IF/NONE_IF)
+ UE modules will always have RF device type NONE_IF */
typedef struct {
- //! module id
+/*! \brief module id */
uint8_t id;
- //! loopback flag
- uint8_t loopback;
- //! measurement flag
- uint8_t measurements;
- //! module's ethernet device
- openair0_device eth_dev;
- //! pointer to RF module's device (pointer->since its optional)
- openair0_device *devs;
-
+/*! \brief! loopback flag */
+uint8_t loopback;
+/*! \brief measurement flag */
+uint8_t measurements;
+/*! \brief module's ethernet device */
+openair0_device eth_dev;
+/*! \brief pointer to RF module's device (pointer->since it's optional) */
+openair0_device *devs;
}rrh_module_t;
-
-/******************************************************************************
- ** FUNCTION PROTOTYPES **
- ******************************************************************************/
-void signal_handler(int sig);
+/*! \fn void timer_signal_handler(int sig)
+ * \brief this function
+ * \param[in] signal type
+ * \return none
+ * \note
+ * @ingroup _oai
+*/
void timer_signal_handler(int);
+
+/*! \fn void *timer_proc(void *arg)
+ * \brief this function
+ * \param[in]
+ * \param[out]
+ * \return
+ * \note
+ * @ingroup _oai
+ */
void *timer_proc(void *);
-void create_timer_thread(void);
+
+/*! \fn void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag,uint8_t NRT_flag)
+ * \brief receive and apply configuration to modules' optional device
+ * \param[in] *mod_enb pointer to module
+ * \param[in] RT_flag real time flag
+ * \return none
+ * \note
+ * @ingroup _oai
+ */
+void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag);
+
+/*! \fn void config_UE_mod( rrh_module_t *dev_ue, uint8_t RT_flag,uint8_t NRT_flag)
+ * \brief this function
+ * \param[in] *mod_ue pointer to module
+ * \param[in]
+ * \return none
+ * \note
+ * @ingroup _oai
+ */
+void config_UE_mod( rrh_module_t *dev_ue, uint8_t RT_flag, uint8_t NRT_flag);
-/******************************************************************************
- ** FUNCTION PROTOTYPES **
- ******************************************************************************/
-void create_UE_trx_threads( rrh_module_t *dev_ue, uint8_t RT_flag, uint8_t NRT_flag);
-void create_eNB_trx_threads( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag);
+
+void signal_handler(int sig);
#endif