diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 5f5f09dfab550c8f63b04d96a48f139f8c3fcc2b..46fd189952e8b975a3526761aaabb0d70eb8ba94 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -494,7 +494,7 @@ include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS/")
 #set (option_HWEXMIMOLIB_lib "-l ")
 set(HWLIB_EXMIMO_SOURCE 
   ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
-  ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c
+#  ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c
   )
 add_library(oai_exmimodevif MODULE ${HWLIB_EXMIMO_SOURCE} )
 
@@ -535,8 +535,8 @@ if (${RF_BOARD} STREQUAL "EXMIMO")
   include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/")
   include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS/")
   set(HW_SOURCE ${HW_SOURCE}
-    ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
-    ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c)
+    ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c)
+#    ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c)
   set(option_HW_lib "-rdynamic -ldl")
 
 elseif (${RF_BOARD} STREQUAL "OAI_USRP")
@@ -1478,9 +1478,9 @@ add_boolean_option(OAI_NW_DRIVER_USE_NETLINK True "????")
 	${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/pgm_link.c
 	)
 
-	add_library(OPENAIR0_LIB
-	  ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
-	)
+#	add_library(OPENAIR0_LIB
+#	  ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
+#	)
 
 	# System packages that are required
 	# We use either the cmake buildin, in ubuntu are in: /usr/share/cmake*/Modules/
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index 96adfa004099a85db33d7be6a9b967dabb362a72..a289677373610259b045eca24fbf1904ae6e225d 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -692,7 +692,9 @@ function main() {
 	      
 	      #add exmimo compilation
 	      #TODO EXMIMO library support
-	     
+	      compilations \
+		  $build_dir oai_exmimodevif \
+		  liboai_exmimodevif.so $dbin/liboai_exmimodevif.so.$REL
 	      echo_info "liboai_device.so is linked to EXMIMO device library"       
 	  elif [ "$HW" == "OAI_USRP" ] ; then
 	      if [ -d "/usr/include/uhd" ] ; then
diff --git a/openair1/PHY/LTE_ESTIMATION/adjust_gain.c b/openair1/PHY/LTE_ESTIMATION/adjust_gain.c
index 48339de4cdbb28d8bda02b0f97da2654c389481f..da07687a9e987de03b6e93df652b747839b5fdb3 100644
--- a/openair1/PHY/LTE_ESTIMATION/adjust_gain.c
+++ b/openair1/PHY/LTE_ESTIMATION/adjust_gain.c
@@ -30,20 +30,10 @@
 #include "PHY/defs.h"
 #include "PHY/extern.h"
 
-#ifdef EXMIMO
-#include "openair0_lib.h"
-extern int card;
-#endif
-
 void
 phy_adjust_gain (PHY_VARS_UE *ue, uint32_t rx_power_fil_dB, uint8_t eNB_id)
 {
 
-#ifdef EXMIMO
-  exmimo_config_t *p_exmimo_config = openair0_exmimo_pci[card].exmimo_config_ptr;
-  uint16_t i;
-#endif
-
   LOG_D(PHY,"Gain control: rssi %d (%d,%d)\n",
          rx_power_fil_dB,
          ue->measurements.rssi,
@@ -80,77 +70,6 @@ phy_adjust_gain (PHY_VARS_UE *ue, uint32_t rx_power_fil_dB, uint8_t eNB_id)
 
   LOG_D(PHY,"Gain control: rx_total_gain_dB = %d (max %d,rxpf %d)\n",ue->rx_total_gain_dB,MAX_RF_GAIN,rx_power_fil_dB);
 
-#ifdef EXMIMO
-
-  if (ue->rx_total_gain_dB>ue->rx_gain_max[0]) {
-    ue->rx_total_gain_dB = ue->rx_gain_max[0];
-
-    for (i=0; i<ue->frame_parms.nb_antennas_rx; i++) {
-      p_exmimo_config->rf.rx_gain[i][0] = 30;
-    }
-
-  } else if (ue->rx_total_gain_dB<(ue->rx_gain_max[0]-30)) {
-    // for the moment we stay in max gain mode
-    ue->rx_total_gain_dB = ue->rx_gain_max[0] - 30;
-
-    for (i=0; i<ue->frame_parms.nb_antennas_rx; i++) {
-      p_exmimo_config->rf.rx_gain[i][0] = 0;
-    }
-
-    /*
-      ue->rx_gain_mode[0] = byp;
-      ue->rx_gain_mode[1] = byp;
-      exmimo_pci_interface->rf.rf_mode0 = 22991; //bypass
-      exmimo_pci_interface->rf.rf_mode1 = 22991; //bypass
-
-      if (ue->rx_total_gain_dB<(ue->rx_gain_byp[0]-50)) {
-      exmimo_pci_interface->rf.rx_gain00 = 0;
-      exmimo_pci_interface->rf.rx_gain10 = 0;
-      }
-    */
-  } else {
-
-    for (i=0; i<ue->frame_parms.nb_antennas_rx; i++) {
-      p_exmimo_config->rf.rx_gain[i][0] =  30 - ue->rx_gain_max[0] + ue->rx_total_gain_dB;
-    }
-  }
-
-  /*
-    break;
-  case med_gain:
-  case byp_gain:
-      if (ue->rx_total_gain_dB>ue->rx_gain_byp[0]) {
-          ue->rx_gain_mode[0]   = max_gain;
-          ue->rx_gain_mode[1]   = max_gain;
-          exmimo_pci_interface->rf.rf_mode0 = 55759; //max gain
-          exmimo_pci_interface->rf.rf_mode1 = 55759; //max gain
-
-          if (ue->rx_total_gain_dB>ue->rx_gain_max[0]) {
-              exmimo_pci_interface->rf.rx_gain00 = 50;
-              exmimo_pci_interface->rf.rx_gain10 = 50;
-          }
-          else {
-              exmimo_pci_interface->rf.rx_gain00 = 50 - ue->rx_gain_max[0] + ue->rx_total_gain_dB;
-              exmimo_pci_interface->rf.rx_gain10 = 50 - ue->rx_gain_max[1] + ue->rx_total_gain_dB;
-          }
-      }
-      else if (ue->rx_total_gain_dB<(ue->rx_gain_byp[0]-50)) {
-          exmimo_pci_interface->rf.rx_gain00 = 0;
-          exmimo_pci_interface->rf.rx_gain10 = 0;
-      }
-      else {
-          exmimo_pci_interface->rf.rx_gain00 = 50 - ue->rx_gain_byp[0] + ue->rx_total_gain_dB;
-          exmimo_pci_interface->rf.rx_gain10 = 50 - ue->rx_gain_byp[1] + ue->rx_total_gain_dB;
-      }
-      break;
-  default:
-      exmimo_pci_interface->rf.rx_gain00 = 50;
-      exmimo_pci_interface->rf.rx_gain10 = 50;
-      break;
-  }
-      */
-#endif
-
 #ifdef DEBUG_PHY
   /*  if ((ue->frame%100==0) || (ue->frame < 10))
   msg("[PHY][ADJUST_GAIN] frame %d,  rx_power = %d, rx_power_fil = %d, rx_power_fil_dB = %d, coef=%d, ncoef=%d, rx_total_gain_dB = %d (%d,%d,%d)\n",
diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/lte_dfts.c
index 375ea418d72e00389ebec52e092b540a6368d852..4fc332704bae044eab5a2d38372f1c2f2381bafd 100644
--- a/openair1/PHY/TOOLS/lte_dfts.c
+++ b/openair1/PHY/TOOLS/lte_dfts.c
@@ -6817,6 +6817,7 @@ void dft60(int16_t *x,int16_t *y,unsigned char scale)
 
     for (i=0; i<60; i++) {
       y128[i] = mulhi_int16(y128[i],norm128);
+      printf("y[%d] = (%d,%d)\n",i,((int16_t*)&y128[i])[0],((int16_t*)&y128[i])[1]);
     }
   }
 
@@ -18553,6 +18554,7 @@ int main(int argc, char**argv)
   simd_q15_t x[4096],y[4096],tw0,tw1,tw2,tw3;
 #endif
   int i;
+  simd_q15_t *x128=x,*y128=y;
 
   set_taus_seed(0);
   opp_enabled = 1;
@@ -18592,17 +18594,22 @@ int main(int argc, char**argv)
     ((int16_t *)&tw3)[5] = 0;
     ((int16_t *)&tw3)[6] = 32767;
     ((int16_t *)&tw3)[7] = 0;
-
+ */
     for (i=0;i<300;i++) {
 #if defined(__x86_64__) || defined(__i386__)
+#ifndef __AVX2__
       x[i] = _mm_set1_epi32(taus());
       x[i] = _mm_srai_epi16(x[i],4);
+#else
+      x[i] = _mm256_set1_epi32(taus());
+      x[i] = _mm256_srai_epi16(x[i],4);
+#endif
 #elif defined(__arm__)
       x[i] = (int16x8_t)vdupq_n_s32(taus());
       x[i] = vshrq_n_s16(x[i],4);
 #endif
     }
-
+      /*
     bfly2_tw1(x,x+1,y,y+1);
     printf("(%d,%d) (%d,%d) => (%d,%d) (%d,%d)\n",((int16_t*)&x[0])[0],((int16_t*)&x[0])[1],((int16_t*)&x[1])[0],((int16_t*)&x[1])[1],((int16_t*)&y[0])[0],((int16_t*)&y[0])[1],((int16_t*)&y[1])[0],((int16_t*)&y[1])[1]);
     printf("(%d,%d) (%d,%d) => (%d,%d) (%d,%d)\n",((int16_t*)&x[0])[0],((int16_t*)&x[0])[1],((int16_t*)&x[1])[0],((int16_t*)&x[1])[1],((int16_t*)&y[0])[2],((int16_t*)&y[0])[3],((int16_t*)&y[1])[2],((int16_t*)&y[1])[3]);
@@ -18743,27 +18750,27 @@ int main(int argc, char**argv)
     for (i=0;i<48;i++)
       printf("%d,%d,",((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]);
     printf("\n");
-
+ */
     dft60((int16_t *)x,(int16_t *)y,1);
     printf("\n\n60-point\n");
     printf("X: ");
     for (i=0;i<60;i++)
-      printf("%d,%d,",((int16_t*)(&x[i]))[0],((int16_t *)(&x[i]))[1]);
+      printf("%d,%d,",((int16_t*)(&x128[i]))[0],((int16_t *)(&x128[i]))[1]);
     printf("\nY:");
     for (i=0;i<60;i++)
-      printf("%d,%d,",((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]);
+      printf("%d,%d,",((int16_t*)(&y128[i]))[0],((int16_t *)(&y128[i]))[1]);
     printf("\n");
-
+    
     dft72((int16_t *)x,(int16_t *)y,1);
     printf("\n\n72-point\n");
     printf("X: ");
     for (i=0;i<72;i++)
-      printf("%d,%d,",((int16_t*)(&x[i]))[0],((int16_t *)(&x[i]))[1]);
+      printf("%d,%d,",((int16_t*)(&x128[i]))[0],((int16_t *)(&x128[i]))[1]);
     printf("\nY:");
     for (i=0;i<72;i++)
-      printf("%d: %d,%d\n",i,((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]);
+      printf("%d: %d,%d\n",i,((int16_t*)(&y128[i]))[0],((int16_t *)(&y128[i]))[1]);
     printf("\n");
-
+    /*
     dft96((int16_t *)x,(int16_t *)y,1);
     printf("\n\n96-point\n");
     printf("X: ");
@@ -18783,17 +18790,17 @@ int main(int argc, char**argv)
     for (i=0;i<108;i++)
       printf("%d: %d,%d\n",i,((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]);
     printf("\n");
-
+    */
     dft120((int16_t *)x,(int16_t *)y,1);
     printf("\n\n120-point\n");
     printf("X: ");
     for (i=0;i<120;i++)
-      printf("%d,%d,",((int16_t*)(&x[i]))[0],((int16_t *)(&x[i]))[1]);
+      printf("%d,%d,",((int16_t*)(&x128[i]))[0],((int16_t *)(&x128[i]))[1]);
     printf("\nY:");
     for (i=0;i<120;i++)
-      printf("%d: %d,%d\n",i,((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]);
+      printf("%d: %d,%d\n",i,((int16_t*)(&y128[i]))[0],((int16_t *)(&y128[i]))[1]);
     printf("\n");
-
+    /*
     dft144((int16_t *)x,(int16_t *)y,1);
     printf("\n\n144-point\n");
     printf("X: ");
diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h
index dc0b31af58c0b974c4597f2d6b540a98c718b591..f8ec3f8e58961584db2149ff0aa6147f7c9fd334 100644
--- a/targets/ARCH/COMMON/common_lib.h
+++ b/targets/ARCH/COMMON/common_lib.h
@@ -51,6 +51,9 @@
 #define BBU_LOCAL_RADIO_HEAD  0
 #define BBU_REMOTE_RADIO_HEAD 1
 
+#define MAX_CARDS 8
+
+
 typedef int64_t openair0_timestamp;
 typedef volatile int64_t openair0_vtimestamp;
 
@@ -59,9 +62,9 @@ typedef volatile int64_t openair0_vtimestamp;
 typedef struct openair0_device_t openair0_device;
 
 
-#ifndef EXMIMO
-#define MAX_CARDS 1
-#endif
+
+
+
 
 //#define USRP_GAIN_OFFSET (56.0)  // 86 calibrated for USRP B210 @ 2.6 GHz to get equivalent RS EPRE in OAI to SMBV100 output
 
@@ -145,16 +148,12 @@ typedef struct {
   unsigned int  samples_per_frame;
   //! the sample rate for both transmit and receive.
   double sample_rate;
-  //! number of samples per RX/TX packet (USRP + Ethernet)
-  unsigned int samples_per_packet; 
-  //! delay in sending samples (write)  due to hardware access, softmodem processing and fronthaul delay if exist
-  int tx_scheduling_advance;
+  //! flag to indicate that the device is doing mmapped DMA transfers
+  int mmapped_dma;
   //! offset in samples between TX and RX paths
   int tx_sample_advance;
-  //! configurable tx thread lauch delay 
-  int txlaunch_wait;               /* 1 or 0 */
-  //! configurable tx thread lauch delay 
-  int txlaunch_wait_slotcount;
+  int samples_per_packet;
+  int tx_scheduling_advance;
   //! number of RX channels (=RX antennas)
   int rx_num_channels;
   //! number of TX channels (=TX antennas)
@@ -165,7 +164,7 @@ typedef struct {
   //! \brief Center frequency in Hz for TX.
   //! index: [0..rx_num_channels[ !!! see lte-ue.c:427 FIXME iterates over rx_num_channels
   double tx_freq[4];
-
+  //! \brief memory
   //! \brief Pointer to Calibration table for RX gains
   rx_gain_calib_table_t *rx_gain_calib_table;
 
diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
index 427cd47be831bd4f266789d1d1af1ebf34176f46..a8b5f3e21b508c539bcfb1595a92b4da4d529d54 100644
--- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
+++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
@@ -36,17 +36,34 @@
 *  28.01.2013: Initial version
 */
 
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <unistd.h>
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h> 
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sched.h>
+#include <linux/sched.h>
+#include <signal.h>
+#include <execinfo.h>
+#include <getopt.h>
+#include <sys/sysinfo.h>
+#include <sys/ioctl.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <syscall.h>
 
 #include "openair0_lib.h"
 #include "openair_device.h"
 #include "common_lib.h"
+
+#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
 
@@ -66,6 +83,14 @@ static uint32_t                      rf_vcocal[4] =      {910,910,910,910};
 static uint32_t                      rf_vcocal_850[4] =  {2015, 2015, 2015, 2015};
 static uint32_t                      rf_rxdc[4] =        {32896,32896,32896,32896};
 
+
+
+extern volatile int                    oai_exit;
+
+
+void kill_watchdog(openair0_device *);
+void create_watchdog(openair0_device *);
+
 unsigned int log2_int( unsigned int x )
 {
   unsigned int ans = 0 ;
@@ -247,16 +272,279 @@ 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)
 
+static void *watchdog_thread(void *arg) {
+
+  int policy, s, j;
+  struct sched_param sparam;
+  char cpu_affinity[1024];
+  cpu_set_t cpuset;
+  exmimo_state_t *exm=((openair0_device *)arg)->priv;
+  openair0_config_t *cfg=&((openair0_device *)arg)->openair0_cfg[0];
+
+  volatile unsigned int *daq_mbox = openair0_daq_cnt();
+  unsigned int mbox,diff;
+
+  
+  /* 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 */
+  /* Enable CPU Affinity only if number of CPUs >2 */
+  CPU_ZERO(&cpuset);
+
+#ifdef CPU_AFFINITY
+  if (get_nprocs() > 2)
+  {
+    for (j = 1; j < get_nprocs(); j++)
+        CPU_SET(j, &cpuset);
+    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+    if (s != 0)
+    {
+      perror( "pthread_setaffinity_np");
+      printf("Error setting processor affinity");
+    }
+  }
+#endif //CPU_AFFINITY
+
+  /* Check the actual affinity mask assigned to the thread */
+
+  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+  if (s != 0)
+  {
+    perror( "pthread_getaffinity_np");
+    printf("Error getting processor affinity ");
+  }
+  memset(cpu_affinity,0,sizeof(cpu_affinity));
+  for (j = 0; j < CPU_SETSIZE; j++)
+     if (CPU_ISSET(j, &cpuset))
+     {  
+        char temp[1024];
+        sprintf (temp, " CPU_%d", j);
+        strcat(cpu_affinity, temp);
+     }
+
+  memset(&sparam, 0 , sizeof (sparam));
+  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
+  policy = SCHED_FIFO ; 
+  
+  s = pthread_setschedparam(pthread_self(), policy, &sparam);
+  if (s != 0)
+     {
+     perror("pthread_setschedparam : ");
+     printf("Error setting thread priority");
+     }
+  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
+  if (s != 0)
+   {
+     perror("pthread_getschedparam : ");
+     printf("Error getting thread priority");
+
+   }
+
+ printf("EXMIMO2 Watchdog TX thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",
+	sched_getcpu(),
+	syscall(__NR_gettid),
+	(policy == SCHED_FIFO)  ? "SCHED_FIFO" :
+	(policy == SCHED_RR)    ? "SCHED_RR" :
+	(policy == SCHED_OTHER) ? "SCHED_OTHER" :
+	"???",
+	sparam.sched_priority, 
+	cpu_affinity );
+
+
+
+
+  mlockall(MCL_CURRENT | MCL_FUTURE);
+
+  exm->watchdog_exit = 0;
+  exm->ts = 0;
+  exm->last_mbox = 0;
+  
+  if (cfg->sample_rate==30.72e6) {
+    exm->samples_per_tick  = 15360;
+    exm->samples_per_frame = 307200; 
+  }
+  else if (cfg->sample_rate==23.04e6) {
+    exm->samples_per_tick = 11520;
+    exm->samples_per_frame = 230400; 
+  }
+  else if (cfg->sample_rate==15.36e6) {
+    exm->samples_per_tick = 7680;
+    exm->samples_per_frame = 153600; 
+  }
+  else if (cfg->sample_rate==7.68e6) {
+    exm->samples_per_tick = 3840;
+    exm->samples_per_frame = 76800; 
+  }
+  else if (cfg->sample_rate==3.84e6) {
+    exm->samples_per_tick = 1920;
+    exm->samples_per_frame = 38400; 
+  }
+  else if (cfg->sample_rate==1.92e6) {
+    exm->samples_per_tick = 960;
+    exm->samples_per_frame = 19200; 
+  }
+  else {
+    printf("Unknown sampling rate %f, exiting \n",cfg->sample_rate);
+    exm->watchdog_exit=1;
+  }
+  // main loop to keep up with DMA transfers from exmimo2
+  while ((!oai_exit) && (!exm->watchdog_exit)) {
+
+    if (exm->daq_state == running) {
+
+      // grab time from MBOX
+      mbox = daq_mbox[0];
+      if (mbox<exm->last_mbox) { // wrap-around
+	diff = 150 + mbox - exm->last_mbox;
+      }
+      else {
+	diff = mbox - exm->last_mbox;
+      }
+      exm->last_mbox = mbox;
+
+      pthread_mutex_lock(&exm->watchdog_mutex);
+      exm->ts += (diff*exm->samples_per_frame/150) ; 
+
+      if (diff > 10)  // we're too late so exit
+	exm->watchdog_exit = 1;
+
+      if (exm->ts - exm->last_ts_rx > exm->samples_per_frame) {
+	exm->watchdog_exit = 1;
+	printf("RX Overflow, exiting\n");
+      }
+      pthread_mutex_unlock(&exm->watchdog_mutex);
+    }
+
+
+    usleep(500);  // sleep for 500us
+  }
+  
+  oai_exit=1;
+  return NULL;
+}
+
+void create_watchdog(openair0_device *dev) {
+  
+  exmimo_state_t *priv = dev->priv;
+  priv->watchdog_exit=0;
+#ifndef DEADLINE_SCHEDULER
+  priv->watchdog_sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO);  
+  pthread_attr_setschedparam(&priv->watchdog_attr,&priv->watchdog_sched_param);
+  pthread_attr_setschedpolicy(&priv->watchdog_attr,SCHED_FIFO);
+  pthread_create(&priv->watchdog,&priv->watchdog_attr,watchdog_thread,dev);
+#else
+  pthread_create(&priv->watchdog,NULL,watchdog_thread,devv);
+#endif
+  pthread_mutex_init(&priv->watchdog_mutex,NULL);
+
+
+}
+
+int trx_exmimo_start(openair0_device *device) {
+
+  exmimo_state_t *exm=device->priv;
+
+  openair0_start_rt_acquisition(0);
+  exm->daq_state = running;  
+
+  return(0);
+}
+
+int trx_exmimo_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc, int flags) {
+
+  return(0);
+}
+
+int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
+
+  exmimo_state_t *exm=device->priv;
+  openair0_config_t *cfg=&device->openair0_cfg[0];
+  openair0_timestamp ts,diff;
+  int i;
+
+  pthread_mutex_lock(&exm->watchdog_mutex);
+  ts = exm->ts;
+  pthread_mutex_unlock(&exm->watchdog_mutex);
+  while (ts < exm->last_ts_rx + nsamps) {
+
+    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)
+    usleep((unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate));
+    // get new timestamp, in case we have to sleep again
+    pthread_mutex_lock(&exm->watchdog_mutex);
+    ts = exm->ts;
+    pthread_mutex_unlock(&exm->watchdog_mutex);
+  }
+
+  if (cfg->mmapped_dma == 0) {  // if buff is not the dma buffer, do a memcpy, otherwise do nothing
+    for (i=0;i<cc;i++) {
+      memcpy(buff[i],
+	     openair0_exmimo_pci[0].adc_head[i]+(exm->last_ts_rx % exm->samples_per_frame),
+	     nsamps*sizeof(int));
+    }
+  }
+  
+  *ptimestamp=exm->last_ts_rx;
+  exm->last_ts_rx += nsamps;
+
+  return(0);
+}
+
+void trx_exmimo_end(openair0_device *device) {
+
+  exmimo_state_t *exm=device->priv;
+
+  exm->daq_state = idle;
+  openair0_stop(0);
+ 
+}
+
+int trx_exmimo_get_stats(openair0_device* device) {
+
+  return(0);
+
+}
+
+int trx_exmimo_reset_stats(openair0_device* device) {
+
+  return(0);
+
+}
+
+int trx_exmimo_stop(int card) {
+
+  return(0);
+
+}
+
+int trx_exmimo_set_freq(openair0_device* device, openair0_config_t *openair0_cfg1,int exmimo_dump_config) {
+
+  return(0);
+}
+
+int trx_exmimo_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) {
+
+  return(0);
+
+}
+
+void kill_watchdog(openair0_device *device) {
+
+  exmimo_state_t *exm=(exmimo_state_t *)device->priv;
+  exm->watchdog_exit=1;
+
+}
+
 int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
 
   // Initialize card
   //  exmimo_config_t         *p_exmimo_config;
   exmimo_id_t             *p_exmimo_id;
   int ret;
+  exmimo_state_t *exm = (exmimo_state_t *)malloc(sizeof(exmimo_state_t));
 
   ret = openair0_open();
-
-
+ 
   if ( ret != 0 ) {
     if (ret == -1)
       printf("Error opening /dev/openair0");
@@ -289,6 +577,23 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
 
   device->type             = EXMIMO_DEV; 
 
+  // Add stuff that was in lte-softmodem here
+
+  //
+  device->trx_start_func = trx_exmimo_start;
+  device->trx_end_func   = trx_exmimo_end;
+  device->trx_read_func  = trx_exmimo_read;
+  device->trx_write_func = trx_exmimo_write;
+  device->trx_get_stats_func   = trx_exmimo_get_stats;
+  device->trx_reset_stats_func = trx_exmimo_reset_stats;
+  device->trx_stop_func        = trx_exmimo_stop;
+  device->trx_set_freq_func    = trx_exmimo_set_freq;
+  device->trx_set_gains_func   = trx_exmimo_set_gains;
+  device->openair0_cfg = openair0_cfg;
+  device->priv = (void *)exm;
+
+  create_watchdog(device);
+
   return(0);
 }
 
@@ -326,8 +631,6 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
       p_exmimo_config->framing.multicard_syncmode=SYNCMODE_SLAVE;
 
     /* device specific */
-    openair0_cfg[card].txlaunch_wait = 1;//manage when TX processing is triggered
-    openair0_cfg[card].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
     openair0_cfg[card].iq_txshift = 4;//shift
     openair0_cfg[card].iq_rxrescale = 15;//rescale iqs
 
diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h
index 0abb27dee281c50aca2e280fd18358ae631513ca..a2f37b09dcf0a0a6bd7400db35976e96f5e3604d 100644
--- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h
+++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h
@@ -42,6 +42,29 @@
 #include "pcie_interface.h"
 #include "openair_device.h"
 #include "common_lib.h"
+#include <pthread.h>
+#include <sched.h>
+#include <linux/sched.h>
+
+typedef enum {
+  idle=0,
+  waiting_for_synch,
+  running
+} exmimo_daq_state_t;
+
+typedef struct {
+  pthread_t watchdog;
+  pthread_attr_t watchdog_attr;
+  struct sched_param watchdog_sched_param;
+  pthread_mutex_t watchdog_mutex;
+  int watchdog_exit;
+  exmimo_daq_state_t daq_state;
+  openair0_timestamp ts;
+  openair0_timestamp last_ts_rx;
+  int samples_per_tick;
+  int samples_per_frame;
+  int last_mbox;
+} exmimo_state_t;
 
 // Use this to access shared memory (configuration structures, adc/dac data buffers, ...)
 // contains userspace pointers
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 5275bb43bd41a647cfdcae3fef411cf876f5bb80..f59ec9ba646fc5481262225278b8013beeb872d1 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -129,7 +129,7 @@ extern volatile int             start_UE;
 #endif
 extern volatile int                    oai_exit;
 
-extern openair0_config_t openair0_cfg[MAX_CARDS];
+extern openair0_config_t *openair0_cfg;
 
 extern pthread_cond_t sync_cond;
 extern pthread_mutex_t sync_mutex;
@@ -1174,11 +1174,9 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
 {
 
   int i, CC_id;
-#ifndef EXMIMO
+
   uint16_t N_TA_offset = 0;
-#else
-  int j;
-#endif
+
   LTE_DL_FRAME_PARMS *frame_parms;
 
 
@@ -1191,8 +1189,6 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
       return(-1);
     }
 
-#ifndef EXMIMO
-
     if (frame_parms->frame_type == TDD) {
       if (frame_parms->N_RB_DL == 100)
         N_TA_offset = 624;
@@ -1202,8 +1198,9 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
         N_TA_offset = 624/4;
     }
 
-#endif
 
+
+    /*
     // replace RX signal buffers with mmaped HW versions
 #ifdef EXMIMO
     openair0_cfg[CC_id].tx_num_channels = 0;
@@ -1253,7 +1250,9 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
       }
     }
 
-#else // not EXMIMO
+#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*));
 
@@ -1275,7 +1274,7 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
 
     }
 
-#endif
+
   }
 
   return(0);
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index 991438d4d5cb2e24fe6446d2bb441d52f0f8f2db..66c60056b358554ed96e230b9d57815d1f423aff 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -100,6 +100,7 @@ extern pthread_cond_t sync_cond;
 extern pthread_mutex_t sync_mutex;
 extern int sync_var;
 
+
 extern openair0_config_t openair0_cfg[MAX_CARDS];
 extern uint32_t          downlink_frequency[MAX_NUM_CCs][4];
 extern int32_t           uplink_frequency_offset[MAX_NUM_CCs][4];