From 08d89933e1677e890d4ed6c68a5c18fd30071934 Mon Sep 17 00:00:00 2001
From: Raymond Knopp <knopp@eurecom.fr>
Date: Thu, 23 Jun 2016 19:08:01 +0200
Subject: [PATCH] expressmimo TX ok.

---
 openair1/SCHED/phy_procedures_lte_eNb.c       |  10 +-
 targets/ARCH/COMMON/common_lib.h              |   4 +
 .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c  |  87 +++++++--
 targets/RT/USER/lte-enb.c                     | 166 +++++++++---------
 targets/RT/USER/lte-softmodem.c               |  33 +++-
 5 files changed, 193 insertions(+), 107 deletions(-)

diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index c4a57836d0..9b1ab9d2ce 100755
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -2562,8 +2562,14 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl
       proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
 
       if (proc->first_rx == 0) {
-        AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)",proc->subframe_rx,subframe);
-        AssertFatal(proc->frame_rx == frame, "Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)",proc->frame_rx,frame);
+        if (proc->subframe_rx != subframe){
+	  LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe);
+	  exit_fun("Exiting");
+	}
+        if (proc->frame_rx != frame) {
+	  LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame);
+	  exit_fun("Exiting");
+	}
       } else {
         proc->first_rx = 0;
 			}
diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h
index f8ec3f8e58..6e112f5e43 100644
--- a/targets/ARCH/COMMON/common_lib.h
+++ b/targets/ARCH/COMMON/common_lib.h
@@ -158,6 +158,10 @@ typedef struct {
   int rx_num_channels;
   //! number of TX channels (=TX antennas)
   int tx_num_channels;
+  //! \brief RX base addresses for mmapped_dma
+  int32_t* rxbase[4];
+  //! \brief TX base addresses for mmapped_dma
+  int32_t* txbase[4];
   //! \brief Center frequency in Hz for RX.
   //! index: [0..rx_num_channels[
   double rx_freq[4];
diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
index b608c8acd2..89b43a22cf 100644
--- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
+++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
@@ -64,7 +64,10 @@
 
 #include <pthread.h>
 
+
 #define max(a,b) ((a)>(b) ? (a) : (b))
+
+
 exmimo_pci_interface_bot_virtual_t openair0_exmimo_pci[MAX_CARDS]; // contains userspace pointers for each card
 
 char *bigshm_top[MAX_CARDS] = INIT_ZEROS;
@@ -90,6 +93,7 @@ extern volatile int                    oai_exit;
 
 void kill_watchdog(openair0_device *);
 void create_watchdog(openair0_device *);
+void rt_sleep(struct timespec *,long );
 
 unsigned int log2_int( unsigned int x )
 {
@@ -272,6 +276,20 @@ 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)
 
+void rt_sleep(struct timespec *ts,long tv_nsec) {
+
+  clock_gettime(CLOCK_MONOTONIC, ts);
+
+  ts->tv_nsec += tv_nsec;
+
+  if (ts->tv_nsec>=1000000000L) {
+    ts->tv_nsec -= 1000000000L;
+    ts->tv_sec++;
+  }
+
+  clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts, NULL);
+
+}
 static void *watchdog_thread(void *arg) {
 
   int policy, s, j;
@@ -284,7 +302,12 @@ static void *watchdog_thread(void *arg) {
   volatile unsigned int *daq_mbox = openair0_daq_cnt();
   unsigned int mbox,diff;
   int first_acquisition;
-  
+  struct timespec sleep_time,wait;
+
+
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
   /* Set affinity mask to include CPUs 1 to MAX_CPUS */
   /* CPU 0 is reserved for UHD threads */
   /* CPU 1 is reserved for all TX threads */
@@ -388,6 +411,8 @@ static void *watchdog_thread(void *arg) {
 
   first_acquisition=1;
   // main loop to keep up with DMA transfers from exmimo2
+
+  int cnt_diff0=0;
   while ((!oai_exit) && (!exm->watchdog_exit)) {
 
     if (exm->daq_state == running) {
@@ -403,7 +428,7 @@ static void *watchdog_thread(void *arg) {
       }
       exm->last_mbox = mbox;
 
-      pthread_mutex_lock(&exm->watchdog_mutex);
+      pthread_mutex_timedlock(&exm->watchdog_mutex,&wait);
       exm->ts += (diff*exm->samples_per_frame/150) ; 
 
       if (first_acquisition==1) //set last read to a closest subframe boundary
@@ -416,9 +441,14 @@ static void *watchdog_thread(void *arg) {
       first_acquisition=0;
 
       if (diff == 0) {
-	exm->watchdog_exit = 1;
-        printf("exiting, HW stopped\n");
+	cnt_diff0++;
+	if (cnt_diff0 == 10) {
+	  exm->watchdog_exit = 1;
+	  printf("exiting, HW stopped\n");
+	}
       }
+      else
+	cnt_diff0=0;
 
       if (exm->ts - exm->last_ts_rx > exm->samples_per_frame) {
 	exm->watchdog_exit = 1;
@@ -427,12 +457,11 @@ static void *watchdog_thread(void *arg) {
       //      printf("ts %lu, last_ts_rx %lu, mbox %d, diff %d\n",exm->ts, exm->last_ts_rx,mbox,diff);
       pthread_mutex_unlock(&exm->watchdog_mutex);
     }
-
-
-    usleep(500);  // sleep for 500us
+    rt_sleep(&sleep_time,250000L);
   }
   
   oai_exit=1;
+  printf("Exiting watchdog\n");
   return NULL;
 }
 
@@ -473,13 +502,23 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi
 
   exmimo_state_t *exm=device->priv;
   openair0_config_t *cfg=&device->openair0_cfg[0];
-  openair0_timestamp ts,diff;
+  openair0_timestamp old_ts=0,ts,diff;
+  struct timespec sleep_time;
+  unsigned long tv_nsec;
   //  int i;
+  struct timespec wait;
 
-  pthread_mutex_lock(&exm->watchdog_mutex);
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
+  if (exm->watchdog_exit == 1)
+    return(0);
+
+  pthread_mutex_timedlock(&exm->watchdog_mutex,&wait);
   ts = exm->ts;
   pthread_mutex_unlock(&exm->watchdog_mutex);
-  while (ts < exm->last_ts_rx + nsamps) {
+  while ((ts < exm->last_ts_rx + nsamps) && 
+	 (exm->watchdog_exit==0)) {
 
     diff = exm->last_ts_rx+nsamps - ts; // difference in samples between current timestamp and last RX received sample
     // go to sleep until we should have enough samples (1024 for a bit more)
@@ -487,14 +526,21 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi
     printf("Reading %d samples, ts %lu, last_ts_rx %lu (%lu) => sleeping %u us\n",nsamps,ts,exm->last_ts_rx,exm->last_ts_rx+nsamps,
 	   (unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate));
 #endif
-    usleep((unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate));
+    tv_nsec=(unsigned long)((double)(diff+3840)*1e9/cfg->sample_rate);
+    //    tv_nsec = 500000L;
+    old_ts = ts;
+    rt_sleep(&sleep_time,tv_nsec);
 #ifdef DEBUG_EXMIMO
     printf("back\n");
 #endif
     // get new timestamp, in case we have to sleep again
-    pthread_mutex_lock(&exm->watchdog_mutex);
+    pthread_mutex_timedlock(&exm->watchdog_mutex,&wait);
     ts = exm->ts;
     pthread_mutex_unlock(&exm->watchdog_mutex);
+    if (old_ts == ts) {
+      printf("ts stopped, returning\n");
+      return(0);
+    }
   }
 
   /*
@@ -511,6 +557,7 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi
   *ptimestamp=exm->last_ts_rx;
   exm->last_ts_rx += nsamps;
 
+
   return(nsamps);
 }
 
@@ -659,6 +706,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
     /* device specific */
     openair0_cfg[card].iq_txshift = 4;//shift
     openair0_cfg[card].iq_rxrescale = 15;//rescale iqs
+    openair0_cfg[card].mmapped_dma = 1;
 
     if (openair0_cfg[card].sample_rate==30.72e6) {
       resampling_factor = 0;
@@ -690,6 +738,10 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
 #endif
 
     for (ant=0; ant<4; ant++) {
+
+      openair0_cfg[card].rxbase[ant] = (int32_t*)openair0_exmimo_pci[card].adc_head[ant];
+      openair0_cfg[card].txbase[ant] = (int32_t*)openair0_exmimo_pci[card].dac_head[ant];
+
       if (openair0_cfg[card].rx_freq[ant] || openair0_cfg[card].tx_freq[ant]) {
 	ACTIVE_RF += (1<<ant)<<5;
         p_exmimo_config->rf.rf_mode[ant] = RF_MODE_BASE;
@@ -697,14 +749,14 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
 	printf("card %d, antenna %d, autocal %d\n",card,ant,openair0_cfg[card].autocal[ant]);
       }
 
-      if (openair0_cfg[card].tx_freq[ant]) {
+      if (openair0_cfg[card].tx_freq[ant]>0) {
         p_exmimo_config->rf.rf_mode[ant] += (TXEN + DMAMODE_TX + TXLPFNORM + TXLPFEN + tx_filter);
         p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant];
         p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant];
-
+        printf("openair0 : programming card %d TX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]);
       }
 
-      if (openair0_cfg[card].rx_freq[ant]) {
+      if (openair0_cfg[card].rx_freq[ant]>0) {
         p_exmimo_config->rf.rf_mode[ant] += (RXEN + DMAMODE_RX + RXLPFNORM + RXLPFEN + rx_filter);
 
         p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant];
@@ -786,13 +838,14 @@ int openair0_reconfig(openair0_config_t *openair0_cfg)
       if (openair0_cfg[card].tx_freq[ant]) {
         p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant];
         p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant];
-        //printf("openair0 : programming TX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]);
+        printf("openair0 : programming TX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]);
       }
 
+
       if (openair0_cfg[card].rx_freq[ant]) {
         p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant];
         p_exmimo_config->rf.rx_gain[ant][0] = (unsigned int)openair0_cfg[card].rx_gain[ant];
-        //printf("openair0 : programming RX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]);
+        printf("openair0 : programming RX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]);
 
         switch (openair0_cfg[card].rxg_mode[ant]) {
         default:
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 51f21b57c8..f915afcb46 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -337,6 +337,10 @@ static void* eNB_thread_rxtx( void* param ) {
   struct sched_param sparam;
   char cpu_affinity[1024];
   cpu_set_t cpuset;
+  struct timespec wait;
+
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
 
   /* Set affinity mask to include CPUs 1 to MAX_CPUS */
   /* CPU 0 is reserved for UHD threads */
@@ -402,7 +406,7 @@ static void* eNB_thread_rxtx( void* param ) {
   while (!oai_exit) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
 
-    if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
+    if (pthread_mutex_timedlock(&proc->mutex_rxtx,&wait) != 0) {
       LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RXn-TXnp4\n");
       exit_fun("nothing to add");
       break;
@@ -442,7 +446,7 @@ static void* eNB_thread_rxtx( void* param ) {
        * (may be relaxed in the future for performance reasons)
        */
       
-      if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
+      if (pthread_mutex_timedlock(&sync_phy_proc.mutex_phy_proc_tx,&wait) != 0) {
         LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX\n");
         exit_fun("nothing to add");
         break;
@@ -569,9 +573,9 @@ static void* eNB_thread_rxtx( void* param ) {
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
 
-#ifdef DEBUG_THREADS
-  printf( "Exiting eNB thread TX\n");
-#endif
+
+  printf( "Exiting eNB thread RXn_TXnp4\n");
+
 
   eNB_thread_rxtx_status = 0;
   return &eNB_thread_rxtx_status;
@@ -613,6 +617,10 @@ static void* eNB_thread_rx_common( void* param ) {
   FILE  *rx_time_file = NULL;
   char rx_time_name[101];
   //int i;
+  struct timespec wait;
+
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
 
   if (opp_enabled == 1) {
     snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf", "eNB");
@@ -766,7 +774,7 @@ static void* eNB_thread_rx_common( void* param ) {
 
     // wake up TX for subframe n+4
     // lock the TX mutex and make sure the thread is ready
-    if (pthread_mutex_lock(&proc_rxtx->mutex_rxtx) != 0) {
+    if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) {
       LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc_rxtx->instance_cnt_rxtx );
       exit_fun( "error locking mutex_rxtx" );
       break;
@@ -815,9 +823,9 @@ static void* eNB_thread_rx_common( void* param ) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
   }
  
-#ifdef DEBUG_THREADS
-  printf( "Exiting eNB thread RXn-TXnp4\n");
-#endif
+
+  printf( "Exiting eNB thread rx_common\n");
+
  
   eNB_thread_rx_status = 0;
   return &eNB_thread_rx_status;
@@ -832,8 +840,16 @@ static void* eNB_thread_rx_common( void* param ) {
 static void* eNB_thread_prach( void* param ) {
   static int eNB_thread_prach_status;
 
+ 
+
   eNB_proc_t *proc = (eNB_proc_t*)param;
   PHY_VARS_eNB *eNB= PHY_vars_eNB_g[0][proc->CC_id];
+
+  struct timespec wait;
+
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
   // set default return value
   eNB_thread_prach_status = 0;
 
@@ -935,7 +951,7 @@ static void* eNB_thread_prach( void* param ) {
     
     if (oai_exit) break;
         
-    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
+    if (pthread_mutex_timedlock(&proc->mutex_prach,&wait) != 0) {
       LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH\n");
       exit_fun( "error locking mutex" );
       break;
@@ -957,7 +973,7 @@ static void* eNB_thread_prach( void* param ) {
     prach_procedures(eNB,0);
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
     
-    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
+    if (pthread_mutex_timedlock(&proc->mutex_prach,&wait) != 0) {
       LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n");
       exit_fun( "error locking mutex" );
       break;
@@ -972,9 +988,9 @@ static void* eNB_thread_prach( void* param ) {
     } 
   }
 
-#ifdef DEBUG_THREADS
+
   printf( "Exiting eNB thread PRACH\n");
-#endif
+
 
   eNB_thread_prach_status = 0;
   return &eNB_thread_prach_status;
@@ -1083,16 +1099,17 @@ void kill_eNB_proc(void) {
     
     proc_rxtx[0].instance_cnt_rxtx = 0; // FIXME data race!
     proc_rxtx[1].instance_cnt_rxtx = 0; // FIXME data race!
+    proc->instance_cnt_prach = 0;
     pthread_cond_signal( &proc_rxtx[0].cond_rxtx );    
-    pthread_cond_signal( &proc_rxtx[0].cond_rxtx );
+    pthread_cond_signal( &proc_rxtx[1].cond_rxtx );
+    pthread_cond_signal( &proc->cond_prach );
     pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
-    
-#ifdef DEBUG_THREADS
-    printf( "Joining eNB TX CC_id %d thread\n", CC_id);
-#endif
+
+    pthread_join( proc->pthread_rx, (void**)&status );    
+
 
     int result,i;
-    for (i=0;i<1;i++) {
+    for (i=0;i<2;i++) {
       pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status );
     
 #ifdef DEBUG_THREADS
@@ -1151,6 +1168,7 @@ void kill_eNB_proc(void) {
 int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]) {
 
   int i, CC_id;
+  int j;
 
   uint16_t N_TA_offset = 0;
 
@@ -1174,77 +1192,61 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
         N_TA_offset = 624/4;
     }
 
-    /*
+ 
+
+    if (openair0_cfg[CC_id].mmapped_dma == 1) {
     // replace RX signal buffers with mmaped HW versions
-#ifdef EXMIMO
-    openair0_cfg[CC_id].tx_num_channels = 0;
-    openair0_cfg[CC_id].rx_num_channels = 0;
-
-    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
-      printf("Mapping eNB CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
-      free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
-      phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i];
-
-      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
-        printf("Error with rf_map! A channel has already been allocated!\n");
-        return(-1);
-      } else {
-        openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
-        openair0_cfg[rf_map[CC_id].card].rx_gain[rf_map[CC_id].chain+i] = rx_gain[CC_id][i];
-        openair0_cfg[rf_map[CC_id].card].rx_num_channels++;
+      
+      for (i=0; i<frame_parms->nb_antennas_rx; i++) {
+	printf("Mapping eNB CC_id %d, rx_ant %d\n",CC_id,i);
+	free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
+	phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = openair0_cfg[CC_id].rxbase[i];
+	
+	
+	
+	printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
+	
+	for (j=0; j<16; j++) {
+	  printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j]);
+	  phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j] = 16-j;
+	}
       }
-
-      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
-
-      for (j=0; j<16; j++) {
-        printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j]);
-        phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j] = 16-j;
+      
+      for (i=0; i<frame_parms->nb_antennas_tx; i++) {
+	printf("Mapping eNB CC_id %d, tx_ant %d\n",CC_id,i);
+	free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
+	phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = openair0_cfg[CC_id].txbase[i];//(int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i];
+	
+	printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
+	
+	for (j=0; j<16; j++) {
+	  printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j]);
+	  phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j] = 16-j;
+	}
       }
     }
+    else {  // not memory-mapped DMA 
+    
 
-    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
-      printf("Mapping eNB CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
-      free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
-      phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i];
-
-      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
-        printf("Error with rf_map! A channel has already been allocated!\n");
-        return(-1);
-      } else {
-        openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i];
-        openair0_cfg[rf_map[CC_id].card].tx_gain[rf_map[CC_id].chain+i] = tx_gain[CC_id][i];
-        openair0_cfg[rf_map[CC_id].card].tx_num_channels++;
+      rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
+      txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
+      
+      for (i=0; i<frame_parms->nb_antennas_rx; i++) {
+	free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
+	rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
+	phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD         FIXME! N_TA_offset > 16 => access of unallocated memory
+	memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
+	printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset);      
       }
-
-      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
-
-      for (j=0; j<16; j++) {
-        printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j]);
-        phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j] = 16-j;
+      
+      for (i=0; i<frame_parms->nb_antennas_tx; i++) {
+	free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
+	txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
+	phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i];
+	memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
+	printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
       }
     }
-
-#else // not EXMIMO 
-    */
-
-    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
-    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
-
-    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
-      free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
-      rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
-      phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD         FIXME! N_TA_offset > 16 => access of unallocated memory
-      memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
-      printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset);      
-    }
-
-    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
-      free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
-      txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
-      phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i];
-      memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
-      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
-    }
   }
 
   return(0);
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 61a8ccd9a0..0cd5d4d0fc 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -416,11 +416,20 @@ void help (void) {
 
 void exit_fun(const char* s)
 {
+  int CC_id;
+
   if (s != NULL) {
     printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
   }
 
   oai_exit = 1;
+  
+  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func)
+      PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice);
+    if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func)
+      PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice);  
+  }
 
 #if defined(ENABLE_ITTI)
   sleep(1); //allow lte-softmodem threads to exit first
@@ -1563,8 +1572,16 @@ int main( int argc, char **argv )
 
     for (i=0; i<4; i++) {
 
-      openair0_cfg[card].tx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] : downlink_frequency[0][i]+uplink_frequency_offset[0][i];
-      openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i];
+      if (i<openair0_cfg[card].tx_num_channels)
+	openair0_cfg[card].tx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] : downlink_frequency[0][i]+uplink_frequency_offset[0][i];
+      else
+	openair0_cfg[card].tx_freq[i]=0.0;
+
+      if (i<openair0_cfg[card].rx_num_channels)
+	openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i];
+      else
+	openair0_cfg[card].rx_freq[i]=0.0;
+
       printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
              card,i, openair0_cfg[card].tx_gain[i],
              openair0_cfg[card].rx_gain[i],
@@ -1952,11 +1969,15 @@ int main( int argc, char **argv )
   pthread_cond_destroy(&sync_cond);
   pthread_mutex_destroy(&sync_mutex);
 
-  // *** Handle per CC_id openair0 
-  openair0.trx_end_func(&openair0);
+  // *** Handle per CC_id openair0
+  if (UE_flag==1)
+    openair0.trx_end_func(&openair0);
+
   for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
-    PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice);  
-    PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice);  
+    if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func)
+      PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice);  
+    if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func)
+      PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice);  
   }
 
   if (ouput_vcd)
-- 
2.26.2