diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h
index 6f467aaadaa3dd8e42ebc39637801d6dfcb4dbc5..9dac378d32620e66853063dc57a01c52bef6290b 100644
--- a/targets/ARCH/COMMON/common_lib.h
+++ b/targets/ARCH/COMMON/common_lib.h
@@ -106,13 +106,13 @@ struct openair0_device_t {
    * the first channel. timestamp if the time (in samples) at which the first sample
    * MUST be sent
    * use flags = 1 to send as timestamp specfied*/
-  void (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, const void *buff, int nsamps, int flags);
+  void (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, const void **buff, int nsamps, int cc, int flags);
 
   /* Read 'nsamps' samples from each channel to buffers. buff[0] is the array for
    * the first channel. *ptimestamp is the time at which the first sample
    * was received.
    * Return the number of sample read */
-  int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void *buff, int nsamps);
+  int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int cc);
 
   /* Terminate operation of the transceiver -- free all associated resources */
   void (*trx_end_func)(openair0_device *device);
diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
index 5b683ea72ac22c86d55c947606031697d8c76f93..afbaeaab2f37681eec890d8757a6fee309d3a326 100644
--- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
+++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
@@ -186,13 +186,17 @@ int trx_eth_start(openair0_device *openair0) {
 
 }
 
-void trx_eth_write(openair0_device *device, openair0_timestamp timestamp, const void *buff, int nsamps, int flags)
+void trx_eth_write(openair0_device *device, openair0_timestamp timestamp, const void *buff, int nsamps, int cc, int flags)
 {
-  ethernet_write_data(device->Mod_id,timestamp,buff,0,nsamps);
+  int i;
+  for (i=0;i<cc;i++)
+    ethernet_write_data(device->Mod_id,timestamp,buff,i,nsamps);
 }
-int trx_eth_read(openair0_device *device, openair0_timestamp *ptimestamp, void *buff, int nsamps) {
+int trx_eth_read(openair0_device *device, openair0_timestamp *ptimestamp, void *buff, int nsamps,int cc) {
 
-  return(ethernet_read_data(device->Mod_id,ptimestamp,buff,0,nsamps));
+  int i;
+  for (i=0;i<cc;i++)
+    return(ethernet_read_data(device->Mod_id,ptimestamp,buff,0,nsamps));
 
 }
 
diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h
index 32a50575268f00fd5f829c18ecd46a62e43f8ad3..d00e6ad94a6eff1e3d296675f8c5624cd2ff7b98 100644
--- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h
+++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h
@@ -10,6 +10,6 @@
 
 int ethernet_socket_init(int Mod_id, char *dest_ip,int dest_port);
 
-int ethernet_write_data(int Mod_id, const void *buff, int nsamps);
+int ethernet_write_data(int Mod_id, const void *buff, int nsamps,int cc);
 
-int ethernet_read_data(int Mod_id,void *buff, int nsamps);
+int ethernet_read_data(int Mod_id,void *buff, int nsamps,int cc);
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index 8fe3683f130273421b547dbbbffcd7536a482a04..4b56ce3ec567f6a40f1291016440376b5a096b15 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -119,7 +119,7 @@ static void trx_usrp_end(openair0_device *device)
 	s->tx_stream->send("", 0, s->tx_md);
 	s->tx_md.end_of_burst = false;
 }
-static void trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, const void *buff, int nsamps, int flags)
+static void trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, const void **buff, int nsamps, int flags)
 {
   usrp_state_t *s = (usrp_state_t*)device->priv;
 
@@ -132,30 +132,30 @@ static void trx_usrp_write(openair0_device *device, openair0_timestamp timestamp
   s->tx_md.start_of_burst = false;
 }
 
-static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void *buff, int nsamps)
+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;
-  //TODO: only one channel is supported now
+  int samples_received[cc],i;
+  
   samples_received = s->rx_stream->recv(buff, nsamps, s->rx_md);
 
-	//handle the error code
-	switch(s->rx_md.error_code){
-		case uhd::rx_metadata_t::ERROR_CODE_NONE:
-			break;
-		case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
-			printf("[recv] USRP RX OVERFLOW!\n");
-			s->num_overflows++;
-			break;
-		case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
-			printf("[recv] USRP RX TIMEOUT!\n");
-			break;
-		default:
-			printf("[recv] Unexpected error on RX, Error code: 0x%x\n",s->rx_md.error_code);
-			break;
-	}
+  //handle the error code
+  switch(s->rx_md.error_code){
+  case uhd::rx_metadata_t::ERROR_CODE_NONE:
+    break;
+  case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
+    printf("[recv] USRP RX OVERFLOW!\n");
+    s->num_overflows++;
+    break;
+  case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
+    printf("[recv] USRP RX TIMEOUT!\n");
+    break;
+  default:
+    printf("[recv] Unexpected error on RX, Error code: 0x%x\n",s->rx_md.error_code);
+    break;
+  }
   s->rx_count += nsamps;
   s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
   *ptimestamp = s->rx_timestamp;
@@ -204,6 +204,8 @@ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cf
   // Initialize USRP device
   std::string args = "type=b200";
   uhd::device_addrs_t device_adds = uhd::device::find(args);
+  size_t i;
+
   if(device_adds.size() == 0)
   {
     std::cerr<<"No USRP Device Found. " << std::endl;
@@ -219,37 +221,51 @@ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cf
   s->usrp->set_rx_rate(openair0_cfg[0].sample_rate);
   s->usrp->set_tx_rate(openair0_cfg[0].sample_rate);
 
-  s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[0]);
-  s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[0]);
-  s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[0]);
-  s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[0]);
+  for(i=0;i<usrp->get_rx_num_channels();i++) {
+    if (i<openair0_cfg[0].rx_num_channels) {
+      s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i]);
+      s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]);
+    }
+  }
+  for(i=0;i<usrp->get_tx_num_channels();i++) {
+    if (i<openair0_cfg[0].tx_num_channels) {
+      s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i]);
+      s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[i]);
+    }
+  }
   s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw);
   s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw);
 
   // create tx & rx streamer
-  uhd::stream_args_t stream_args("sc16", "sc16");
-  s->tx_stream = s->usrp->get_tx_stream(stream_args);
-  s->rx_stream = s->usrp->get_rx_stream(stream_args);
+  uhd::stream_args_t stream_args_rx("sc16", "sc16");
+  uhd::stream_args_t stream_args_tx("sc16", "sc16");
+  for (i = 0; i<  openair0_cfg[0].rx_num_channels(); i++)
+      stream_args_rx.channels.push_back(i);
+  for (i = 0; i<  openair0_cfg[0].tx_num_channels(); i++)
+      stream_args_tx.channels.push_back(i);
+
+  s->tx_stream = s->usrp->get_tx_stream(stream_args_tx);
+  s->rx_stream = s->usrp->get_rx_stream(stream_args_rx);
 
   s->usrp->set_time_now(uhd::time_spec_t(0.0));
 
   // display USRP settings
-	std::cout << std::endl<<boost::format("Actual TX sample rate: %fMSps...") % (s->usrp->get_tx_rate()/1e6) << std::endl;
-	std::cout << boost::format("Actual RX sample rate: %fMSps...") % (s->usrp->get_rx_rate()/1e6) << std::endl;
-
-	std::cout << boost::format("Actual TX frequency: %fGHz...") % (s->usrp->get_tx_freq()/1e9) << std::endl;
-	std::cout << boost::format("Actual RX frequency: %fGHz...") % (s->usrp->get_rx_freq()/1e9) << std::endl;
-
-	std::cout << boost::format("Actual TX gain: %f...") % (s->usrp->get_tx_gain()) << std::endl;
-	std::cout << boost::format("Actual RX gain: %f...") % (s->usrp->get_rx_gain()) << std::endl;
-
-	std::cout << boost::format("Actual TX bandwidth: %fM...") % (s->usrp->get_tx_bandwidth()/1e6) << std::endl;
-	std::cout << boost::format("Actual RX bandwidth: %fM...") % (s->usrp->get_rx_bandwidth()/1e6) << std::endl;
-
-	std::cout << boost::format("Actual TX antenna: %s...") % (s->usrp->get_tx_antenna()) << std::endl;
-	std::cout << boost::format("Actual RX antenna: %s...") % (s->usrp->get_rx_antenna()) << std::endl;
-
-	std::cout << boost::format("Device timestamp: %f...") % (s->usrp->get_time_now().get_real_secs()) << std::endl;
+  std::cout << std::endl<<boost::format("Actual TX sample rate: %fMSps...") % (s->usrp->get_tx_rate()/1e6) << std::endl;
+  std::cout << boost::format("Actual RX sample rate: %fMSps...") % (s->usrp->get_rx_rate()/1e6) << std::endl;
+  
+  std::cout << boost::format("Actual TX frequency: %fGHz...") % (s->usrp->get_tx_freq()/1e9) << std::endl;
+  std::cout << boost::format("Actual RX frequency: %fGHz...") % (s->usrp->get_rx_freq()/1e9) << std::endl;
+  
+  std::cout << boost::format("Actual TX gain: %f...") % (s->usrp->get_tx_gain()) << std::endl;
+  std::cout << boost::format("Actual RX gain: %f...") % (s->usrp->get_rx_gain()) << std::endl;
+  
+  std::cout << boost::format("Actual TX bandwidth: %fM...") % (s->usrp->get_tx_bandwidth()/1e6) << std::endl;
+  std::cout << boost::format("Actual RX bandwidth: %fM...") % (s->usrp->get_rx_bandwidth()/1e6) << std::endl;
+  
+  std::cout << boost::format("Actual TX antenna: %s...") % (s->usrp->get_tx_antenna()) << std::endl;
+  std::cout << boost::format("Actual RX antenna: %s...") % (s->usrp->get_rx_antenna()) << std::endl;
+  
+  std::cout << boost::format("Device timestamp: %f...") % (s->usrp->get_time_now().get_real_secs()) << std::endl;
 
   device->priv = s;
   device->trx_start_func = trx_usrp_start;
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index cde85f16a2a2df5ec9fcf897e019713246a6a17e..ded6683971b8eb76091f9c07133d6d62a2615444 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -129,7 +129,7 @@ unsigned short config_frames[4] = {2,9,11,13};
 #define FRAME_PERIOD    100000000ULL
 #define DAQ_PERIOD      66667ULL
 
-//#define DEBUG_THREADS 1
+#define DEBUG_THREADS 1
 
 //#define USRP_DEBUG 1
 
@@ -150,8 +150,8 @@ void cleanup_rx_pdsch_thread(void);
 
 openair0_config_t openair0_cfg[MAX_CARDS];
 
-int32_t *rxdata;
-int32_t *txdata;
+int32_t **rxdata;
+int32_t **txdata;
 int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
 int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
 
@@ -1277,6 +1277,8 @@ static void *eNB_thread(void *arg)
   unsigned int rx_cnt = 0;
   unsigned int tx_cnt = tx_delay;
   //  int tx_offset;
+  void *rxp[2],*txp[2];
+  int i;
 
   hw_subframe = 0;
 #endif
@@ -1400,50 +1402,42 @@ static void *eNB_thread(void *arg)
 	unsigned int rxs;
 #ifndef USRP_DEBUG
 	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,1);
-	/*
-	// Grab 1/4 of RX buffer and get timestamp
-
-	rxs = openair0.trx_read_func(&openair0, 
-	&timestamp, 
-	&rxdata[rx_cnt*samples_per_packets], 
-	(samples_per_packets>>2));
-	if (rxs != (samples_per_packets>>2))
-	oai_exit=1;
-
-	*/
 
 	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_TXCNT,tx_cnt);
 	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_RXCNT,rx_cnt*samples_per_packets);
 
+	printf("hw_subframe %d: rx_cnt %d\n",hw_subframe,rx_cnt);
+
+	for (i=0;i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx;i++)
+	  rxp[i] = (void*)&rxdata[i][rx_cnt*samples_per_packets];
+
 	rxs = openair0.trx_read_func(&openair0, 
 				     &timestamp, 
-				     &rxdata[rx_cnt*samples_per_packets], 
-				     samples_per_packets);
+				     rxp, 
+				     samples_per_packets,
+				     PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx);
 
 	if (rxs != samples_per_packets)
 	  oai_exit=1;
+ 
+	printf("hw_subframe %d: tx_cnt %d\n",hw_subframe,tx_cnt);
 
 	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,0);
 
 	// Transmit TX buffer based on timestamp from RX
 	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,1);
+	
+	for (i=0;i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx;i++)
+	  txp[i] = (void*)&txdata[i][tx_cnt*samples_per_packets];
 	openair0.trx_write_func(&openair0, 
 				(timestamp+samples_per_packets*tx_delay-tx_forward_nsamps), 
-				&txdata[tx_cnt*samples_per_packets], 
+				txp,
 				samples_per_packets, 
+				PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx,
 				1);
+
+	
 	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
-	/*
-	// Grab remaining 3/4 of RX buffer
-	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,1);
-	rxs = openair0.trx_read_func(&openair0, 
-	&timestamp, 
-	&rxdata[(rx_cnt*samples_per_packets)+(samples_per_packets>>2)], 
-	3*((samples_per_packets>>2)));
-	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,0);
-	if (rxs != (3*(samples_per_packets>>2)))
-	oai_exit=1;
-	*/
 #else
 	rt_sleep_ns(1000000);
 #endif
@@ -1891,15 +1885,17 @@ static void *UE_thread(void *arg) {
 
   int slot=1,frame=0,hw_slot,last_slot, next_slot,hw_subframe=0,rx_cnt=0,tx_cnt=0;
   // unsigned int aa;
-  int dummy[samples_per_packets];
+  int dummy[2][samples_per_packets];
   int dummy_dump = 0;
   int tx_enabled=0;
   int start_rx_stream=0;
   int rx_off_diff = 0;
   int rx_correction_timer = 0;
+  int i;
 
   openair0_timestamp time0,time1;
   unsigned int rxs;
+  void *rxp[2],*txp[2];
 
   printf("waiting for USRP sync (UE_thread)\n");
 #ifdef RTAI
@@ -1926,10 +1922,14 @@ static void *UE_thread(void *arg) {
       vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,1);
   
 #ifndef USRP_DEBUG
+
+      for (i=0;i<PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx;i++)
+	rxp[i] = (dummy_dump==0) ? (void*)&rxdata[i][rx_cnt*samples_per_packets] : (void*)dummy[i];
       rxs = openair0.trx_read_func(&openair0,
 				   &timestamp,
-				   (dummy_dump==0) ? &rxdata[rx_cnt*samples_per_packets] : dummy,
-				   samples_per_packets - ((rx_cnt==0) ? rx_off_diff : 0));
+				   rxp,
+				   samples_per_packets - ((rx_cnt==0) ? rx_off_diff : 0),
+				   PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx);
       if (rxs != (samples_per_packets- ((rx_cnt==0) ? rx_off_diff : 0)))
 	oai_exit=1;
 
@@ -1939,11 +1939,15 @@ static void *UE_thread(void *arg) {
       // Transmit TX buffer based on timestamp from RX
       if (tx_enabled) {
 	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,1);
+	for (i=0;i<PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx;i++)
+	  txp[i] = (void*)&txdata[i][tx_cnt*samples_per_packets];
 	openair0.trx_write_func(&openair0,
 				(timestamp+samples_per_packets*tx_delay-tx_forward_nsamps),
-				&txdata[tx_cnt*samples_per_packets],
+				txp,
 				samples_per_packets,
+				PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx,
 				1);
+				
 	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
       }
 #else
@@ -2061,7 +2065,8 @@ static void *UE_thread(void *arg) {
 	    rxs = openair0.trx_read_func(&openair0,
 					 &timestamp,
 					 &rxdata[0],
-					 PHY_vars_UE_g[0][0]->rx_offset);
+					 PHY_vars_UE_g[0][0]->rx_offset,
+					 PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx);
 #else
 	    rt_sleep_ns(10000000);
 #endif
@@ -3037,8 +3042,8 @@ int main(int argc, char **argv) {
     // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC. 
     // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
 #ifndef EXMIMO
-    openair0_cfg[card].tx_num_channels=1;
-    openair0_cfg[card].rx_num_channels=1;
+    openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx));
+    openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx));
     for (i=0;i<4;i++) {
       openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
       openair0_cfg[card].rx_gain[i] = ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB : 
@@ -3323,7 +3328,7 @@ int main(int argc, char **argv) {
   }
 
   // Sleep to allow all threads to setup
-  //sleep(1);
+  sleep(1);
 
 #ifndef EXMIMO
 #ifndef USRP_DEBUG
diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c
index 78b2f2f8edda0156818c496bfbf561f3764f9a4e..5788ae1442f7f0fcb68cd86b716bad563175e56b 100644
--- a/targets/SIMU/USER/oaisim.c
+++ b/targets/SIMU/USER/oaisim.c
@@ -719,7 +719,6 @@ void *l2l1_task(void *args_p) {
 	      // PHY_vars_eNB_g[eNB_id]->frame = frame;
 	      if ((slot&1) == 0) 
 		phy_procedures_eNB_lte (slot>>1,PHY_vars_eNB_g[eNB_inst], abstraction_flag, no_relay, NULL);
-
 #ifdef PRINT_STATS
 	      if(last_slot==9 && frame%10==0)
 		if(eNB_avg_thr)