From 69a7658c545a33189d573701babee2e87fb57240 Mon Sep 17 00:00:00 2001
From: frtabu <francois.taburet@nokia-bell-labs.com>
Date: Mon, 16 Dec 2019 17:53:22 +0100
Subject: [PATCH] USRP device cleanup including record player as config option
 + some cppcheck warning/errors fixes

---
 cmake_targets/CMakeLists.txt                  |   1 +
 common/config/config_userapi.c                |   5 +-
 openair1/PHY/NR_TRANSPORT/nr_ulsch.h          |   2 +-
 openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c |  25 +-
 .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c   |  53 +-
 openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c        |   9 +-
 .../NR_UE_TRANSPORT/nr_transport_proto_ue.h   |   2 +-
 openair1/PHY/NR_UE_TRANSPORT/pbch_nr.c        |   2 +-
 openair1/SCHED_NR_UE/fapi_nr_ue_l1.c          |  14 +-
 openair1/SIMULATION/NR_PHY/dlschsim.c         |   2 +-
 openair2/COMMON/platform_types.h              |   7 +
 openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c       |  10 +-
 openair2/NETWORK_DRIVER/UE_IP/common.c        |   6 +-
 openair2/UTIL/OTG/otg_rx_socket.c             |   2 +-
 targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp  | 926 ++++++++----------
 targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.h    |  68 +-
 .../ARCH/USRP/USERSPACE/LIB/usrp_lib_config.c |  73 ++
 17 files changed, 584 insertions(+), 623 deletions(-)
 create mode 100644 targets/ARCH/USRP/USERSPACE/LIB/usrp_lib_config.c

diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index a0620d8345..e429b9e58f 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -529,6 +529,7 @@ set (SHLIB_LOADER_SOURCES
 include_directories("${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/")
 set(HWLIB_USRP_SOURCE
   ${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+  ${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib_config.c
   )
 add_library(oai_usrpdevif MODULE ${HWLIB_USRP_SOURCE} )
 target_link_libraries(oai_usrpdevif uhd)
diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c
index 56c3c0951f..67fdc2c920 100644
--- a/common/config/config_userapi.c
+++ b/common/config/config_userapi.c
@@ -386,13 +386,12 @@ int config_setdefault_string(paramdef_t *cfgoptions, char *prefix) {
     status=1;
 
     if (cfgoptions->numelt == 0 ) {
-      config_check_valptr(cfgoptions, (char **)(cfgoptions->strptr), sizeof(char *));
       config_check_valptr(cfgoptions, cfgoptions->strptr, strlen(cfgoptions->defstrval)+1);
       sprintf(*(cfgoptions->strptr), "%s",cfgoptions->defstrval);
       printf_params("[CONFIG] %s.%s set to default value \"%s\"\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, *(cfgoptions->strptr));
     } else {
-      sprintf((char *)*(cfgoptions->strptr), "%s",cfgoptions->defstrval);
-      printf_params("[CONFIG] %s.%s set to default value \"%s\"\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, (char *)*(cfgoptions->strptr));
+      sprintf((char *)(cfgoptions->strptr), "%s",cfgoptions->defstrval);
+      printf_params("[CONFIG] %s.%s set to default value \"%s\"\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, (char *)(cfgoptions->strptr));
     }
   }
 
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
index dc7489ea51..b3a4948a2a 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
@@ -32,7 +32,7 @@
 
 #include "PHY/defs_gNB.h"
 
-void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch);
+void free_gNB_ulsch(NR_gNB_ULSCH_t **ulsch);
 
 NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag);
 
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
index db0c601b25..2e8f2af5f5 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
@@ -58,10 +58,9 @@ static uint64_t nb_error_decod =0;
 
 //extern double cpuf;
 
-void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch)
-{
-
+void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr) {
   int i,r;
+  NR_gNB_ULSCH_t *ulsch = *ulschptr;
 
   if (ulsch) {
     for (i=0; i<NR_MAX_ULSCH_HARQ_PROCESSES; i++) {
@@ -92,7 +91,7 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch)
       }
     }
     free16(ulsch,sizeof(NR_gNB_ULSCH_t));
-    ulsch = NULL;
+    *ulschptr = NULL;
   }
 }
 
@@ -168,8 +167,7 @@ NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint8_t N_RB_UL, uint8
   }
 
   printf("new_gNB_ulsch with size %zu: exit_flag = %u\n",sizeof(NR_UL_gNB_HARQ_t), exit_flag);
-  free_gNB_ulsch(ulsch);
-  
+  free_gNB_ulsch(&ulsch);
   return(NULL);
 }
 
@@ -307,6 +305,10 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
   t_nrLDPC_dec_params* p_decParams    = &decParams;
   t_nrLDPC_time_stats procTime;
   t_nrLDPC_time_stats* p_procTime     = &procTime ;
+  if (!harq_process) {
+    printf("ulsch_decoding.c: NULL harq_process pointer\n");
+    return (ulsch->max_ldpc_iterations + 1);
+  }
   t_nrLDPC_procBuf** p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf;
 
   int16_t  z [68*384];
@@ -338,11 +340,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
     return (ulsch->max_ldpc_iterations + 1);
   }
 
-  if (!harq_process) {
-    printf("ulsch_decoding.c: NULL harq_process pointer\n");
-    return (ulsch->max_ldpc_iterations + 1);
-  }
-
   if (!frame_parms) {
     printf("ulsch_decoding.c: NULL frame_parms pointer\n");
     return (ulsch->max_ldpc_iterations + 1);
@@ -531,7 +528,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
       write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0);
     }
 
-    printf("decoder input(segment %d) :",r);
+    printf("decoder input(segment %u) :",r);
     int i; 
     for (i=0;i<(3*8*Kr_bytes)+12;i++)
       printf("%d : %d\n",i,harq_process->d[r][i]);
@@ -620,7 +617,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
       //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]);
       for (int k=0;k<A>>3;k++)
        printf("output decoder [%d] =  0x%02x \n", k, harq_process->c[r][k]);
-      printf("no_iterations_ldpc %d (ret %d)\n",no_iteration_ldpc,ret);
+      printf("no_iterations_ldpc %d (ret %u)\n",no_iteration_ldpc,ret);
       //write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4);
 #endif
 
@@ -708,7 +705,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
     offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0));
 
 #ifdef DEBUG_ULSCH_DECODING
-    printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes);
+    printf("Segment %u : Kr= %u bytes\n",r,Kr_bytes);
     printf("copied %d bytes to b sequence (harq_pid %d)\n",
            (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid);
     printf("b[0] = %x,c[%d] = %x\n",
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
index 53d481919e..6a277cdc42 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
@@ -56,11 +56,11 @@ notifiedFIFO_elt_t *msgToPush;
 
 //extern double cpuf;
 
-void free_nr_ue_dlsch(NR_UE_DLSCH_t *dlsch)
+void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr)
 {
 
   int i,r;
-
+  NR_UE_DLSCH_t *dlsch=*dlschptr;
   if (dlsch) {
     for (i=0; i<dlsch->Mdlharq; i++) {
       if (dlsch->harq_processes[i]) {
@@ -175,7 +175,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint
   }
 
   printf("new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag);
-  free_nr_ue_dlsch(dlsch);
+  free_nr_ue_dlsch(&dlsch);
 
   return(NULL);
 }
@@ -232,6 +232,11 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
   t_nrLDPC_dec_params* p_decParams = &decParams;
   t_nrLDPC_time_stats procTime;
   t_nrLDPC_time_stats* p_procTime =&procTime ;
+  
+  if (!harq_process) {
+    printf("dlsch_decoding.c: NULL harq_process pointer\n");
+    return(dlsch->max_ldpc_iterations + 1);
+  }
   t_nrLDPC_procBuf** p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf;
     
   int16_t z [68*384];
@@ -260,11 +265,6 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
     return(dlsch->max_ldpc_iterations + 1);
   }
 
-  if (!harq_process) {
-    printf("dlsch_decoding.c: NULL harq_process pointer\n");
-    return(dlsch->max_ldpc_iterations + 1);
-  }
-
   if (!frame_parms) {
     printf("dlsch_decoding.c: NULL frame_parms pointer\n");
     return(dlsch->max_ldpc_iterations + 1);
@@ -498,7 +498,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
       write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0);
     }
 
-    printf("decoder input(segment %d) :",r);
+    printf("decoder input(segment %u) :",r);
     int i;
     for (i=0;i<(3*8*Kr_bytes)+12;i++)
       printf("%d : %d\n",i,harq_process->d[r][i]);
@@ -564,7 +564,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
 
       // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int
       if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) {
-        printf("\x1B[34m" "Segment %d CRC OK\n\033[0m",r);
+        printf("\x1B[34m" "Segment %u CRC OK\n\033[0m",r);
         //Temporary hack
         no_iteration_ldpc = dlsch->max_ldpc_iterations;
         ret = no_iteration_ldpc;
@@ -594,7 +594,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
       //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]);
       for (int k=0;k<A>>3;k++)
         printf("output decoder [%d] =  0x%02x \n", k, harq_process->c[r][k]);
-      printf("no_iterations_ldpc %d (ret %d)\n",no_iteration_ldpc,ret);
+      printf("no_iterations_ldpc %d (ret %u)\n",no_iteration_ldpc,ret);
       //write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4);
 #endif
 
@@ -696,7 +696,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
     offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0));
 
 #ifdef DEBUG_DLSCH_DECODING
-    printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes);
+    printf("Segment %u : Kr= %u bytes\n",r,Kr_bytes);
     printf("copied %d bytes to b sequence (harq_pid %d)\n",
               (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid);
               printf("b[0] = %x,c[%d] = %x\n",
@@ -766,6 +766,10 @@ uint32_t  nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
   t_nrLDPC_time_stats procTime;
   t_nrLDPC_time_stats* p_procTime =&procTime ;
   int8_t llrProcBuf[OAI_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32)));
+    if (!harq_process) {
+    printf("dlsch_decoding.c: NULL harq_process pointer\n");
+    return(dlsch->max_ldpc_iterations);
+  }
   t_nrLDPC_procBuf* p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[0];
   uint8_t Nl=4;
   int16_t z [68*384];
@@ -796,10 +800,7 @@ uint32_t  nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
     return(dlsch->max_ldpc_iterations);
   }
 
-  if (!harq_process) {
-    printf("dlsch_decoding.c: NULL harq_process pointer\n");
-    return(dlsch->max_ldpc_iterations);
-  }
+
 
   if (!frame_parms) {
     printf("dlsch_decoding.c: NULL frame_parms pointer\n");
@@ -1006,7 +1007,7 @@ uint32_t  nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
 
 #ifdef DEBUG_DLSCH_DECODING
         for (int i =0; i<16; i++)
-              printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
+              printf("rx output deinterleaving w[%d]= %d r_offset %u\n", i,harq_process->w[r][i], r_offset);
 #endif
 
 #if UE_TIMING_TRACE
@@ -1065,7 +1066,7 @@ uint32_t  nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
  
 #ifdef DEBUG_DLSCH_DECODING   
     for (int i =0; i<16; i++)
-      printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
+      printf("rx output ratematching d[%d]= %d r_offset %u\n", i,harq_process->d[r][i], r_offset);
 #endif
 
 #ifdef DEBUG_DLSCH_DECODING
@@ -1075,7 +1076,7 @@ uint32_t  nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
       write_output("decoder_in.m","dec",&harq_process->d[0][96],(3*8*Kr_bytes)+12,1,0);
     }
 
-    printf("decoder input(segment %d) :",r);
+    printf("decoder input(segment %u) :",r);
     for (int i=0;i<(3*8*Kr_bytes);i++)
       printf("%d : %d\n",i,harq_process->d[r][i]);
     printf("\n");
@@ -1153,7 +1154,7 @@ uint32_t  nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
       }
 
       if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) {
-        printf("Segment %d CRC OK\n",r);
+        printf("Segment %u CRC OK\n",r);
         ret = 2;
       }
       else {
@@ -1162,7 +1163,7 @@ uint32_t  nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
       }
 
     //if (!nb_total_decod%10000){
-        printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout);
+        printf("Error number of iteration LPDC %d %lu/%lu \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout);
     //}
 
     //else
@@ -1303,7 +1304,7 @@ uint32_t  nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
       offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0));
 
 #ifdef DEBUG_DLSCH_DECODING
-      printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes);
+      printf("Segment %u : Kr= %u bytes\n",r,Kr_bytes);
       printf("copied %d bytes to b sequence (harq_pid %d)\n",
                 (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid);
                 printf("b[0] = %x,c[%d] = %x\n",
@@ -1391,7 +1392,7 @@ void *nr_dlsch_decoding_process(void *arg)
   //printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag);
   p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[r];
   nb_symb_sch = harq_process->nb_symbols;
-  printf("dlsch decoding process frame %d slot %d segment %d r %d nb symb %d \n", frame, proc->nr_tti_rx, proc->num_seg, r, harq_process->nb_symbols);
+  printf("dlsch decoding process frame %d slot %d segment %d r %u nb symb %d \n", frame, proc->nr_tti_rx, proc->num_seg, r, harq_process->nb_symbols);
 
 
   /*
@@ -1554,7 +1555,7 @@ void *nr_dlsch_decoding_process(void *arg)
 
 #ifdef DEBUG_DLSCH_DECODING
     for (int i =0; i<16; i++)
-              printf("rx output thread 0 deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
+              printf("rx output thread 0 deinterleaving w[%d]= %d r_offset %u\n", i,harq_process->w[r][i], r_offset);
 #endif
 
 #if UE_TIMING_TRACE
@@ -1615,7 +1616,7 @@ void *nr_dlsch_decoding_process(void *arg)
               write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0);
     }
 
-    printf("decoder input(segment %d) :",r);
+    printf("decoder input(segment %u) :",r);
     int i; for (i=0;i<(3*8*Kr_bytes)+12;i++)
       printf("%d : %d\n",i,harq_process->d[r][i]);
       printf("\n");
@@ -1684,7 +1685,7 @@ void *nr_dlsch_decoding_process(void *arg)
 
         // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int
         if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) {
-          printf("Segment %d CRC OK\n",r);
+          printf("Segment %u CRC OK\n",r);
           ret = 2;
         }
         else {
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
index 1e17f6dab0..a744bb1ef4 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
@@ -71,7 +71,7 @@ uint16_t nr_pbch_extract(int **rxdataF,
     rxF        = &rxdataF[aarx][(symbol+s_offset)*frame_parms->ofdm_symbol_size];
     rxF_ext    = &rxdataF_ext[aarx][symbol*20*12];
 #ifdef DEBUG_PBCH
-    printf("extract_rbs (nushift %d): rx_offset=%d, symbol %d\n",frame_parms->nushift,
+    printf("extract_rbs (nushift %d): rx_offset=%d, symbol %u\n",frame_parms->nushift,
            (rx_offset + ((symbol+s_offset)*(frame_parms->ofdm_symbol_size))),symbol);
     int16_t *p = (int16_t *)rxF;
 
@@ -425,7 +425,8 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
   int max_h=0;
   int symbol;
   //uint8_t pbch_a[64];
-  uint8_t *pbch_a = malloc(sizeof(uint8_t) * 32);
+//FT ?? cppcheck doesn't like pbch_a allocation because of line 525..and i don't get what this variable is for..
+//uint8_t *pbch_a = malloc(sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
   //uint32_t pbch_a_prime;
   int16_t *pbch_e_rx;
   uint8_t *decoded_output = nr_ue_pbch_vars->decoded_output;
@@ -438,7 +439,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
   //uint8_t decoderListSize = 8, pathMetricAppr = 0;
   //time_stats_t polar_decoder_init,polar_rate_matching,decoding,bit_extraction,deinterleaving;
   //time_stats_t path_metric,sorting,update_LLR;
-  memset(&pbch_a[0], 0, sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
+// FT ?? cppcheck fix  memset(&pbch_a[0], 0, sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
   //printf("nr_pbch_ue nid_cell %d\n",frame_parms->Nid_cell);
 
   pbch_e_rx = &nr_ue_pbch_vars->llr[0];
@@ -522,7 +523,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
 #endif
   pbch_e_rx = nr_ue_pbch_vars->llr;
   //demod_pbch_e = nr_ue_pbch_vars->demod_pbch_e;
-  pbch_a = nr_ue_pbch_vars->pbch_a;
+// FT?? cppcheck fix -  pbch_a = nr_ue_pbch_vars->pbch_a;
 #ifdef DEBUG_PBCH
   //pbch_e_rx = &nr_ue_pbch_vars->llr[0];
   short *p = (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][20*12]);
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
index 7559115a29..a4a329b2cf 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
@@ -47,7 +47,7 @@
     \brief This function frees memory allocated for a particular DLSCH at UE
     @param dlsch Pointer to DLSCH to be removed
 */
-void free_nr_ue_dlsch(NR_UE_DLSCH_t *dlsch);
+void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlsch);
 
 /** \fn new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag)
     \brief This function allocates structures for a particular DLSCH at UE
diff --git a/openair1/PHY/NR_UE_TRANSPORT/pbch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pbch_nr.c
index 334faafecd..4012322111 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/pbch_nr.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/pbch_nr.c
@@ -59,7 +59,7 @@
 uint32_t *pseudo_random_gold_sequence(length M_PN, uint32_t cinit)
 {
   int size = M_PN * sizeof(uint32_t);
-  int size_x = (sizeof(int)*M_PN + size;
+  int size_x = sizeof(int)*M_PN + size;
   int *x1 = malloc(size_x);
   int *x2 = malloc(size_x);
 
diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
index 1bd7071b99..1b61260d10 100644
--- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
+++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
@@ -42,14 +42,16 @@ extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
 
 int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response)
 {
-  /// module id
-  module_id_t module_id = scheduled_response->module_id; 
-  /// component carrier id
-  uint8_t cc_id = scheduled_response->CC_id;
-  uint32_t i;
-  int slot = scheduled_response->slot;
+
 
   if(scheduled_response != NULL){
+    /// module id
+    module_id_t module_id = scheduled_response->module_id; 
+    /// component carrier id
+    uint8_t cc_id = scheduled_response->CC_id;
+    uint32_t i;
+    int slot = scheduled_response->slot; 	
+    
     // Note: we have to handle the thread IDs for this. To be revisited completely.
     uint8_t thread_id = PHY_vars_UE_g[module_id][cc_id]->current_thread_id[slot];
     NR_UE_PDCCH *pdcch_vars2 = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[thread_id][0];
diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c
index aab762b9e2..2980187c42 100644
--- a/openair1/SIMULATION/NR_PHY/dlschsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlschsim.c
@@ -623,7 +623,7 @@ int main(int argc, char **argv)
 		printf("gNB %d\n", i);
 		free_gNB_dlsch(gNB->dlsch[0][i]);
 		printf("UE %d\n", i);
-		free_nr_ue_dlsch(UE->dlsch[0][0][i]);
+		free_nr_ue_dlsch(&(UE->dlsch[0][0][i]));
 	}
 
 	for (i = 0; i < 2; i++) {
diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h
index 49c1b340a6..2555be081a 100644
--- a/openair2/COMMON/platform_types.h
+++ b/openair2/COMMON/platform_types.h
@@ -302,5 +302,12 @@ typedef struct protocol_ctxt_s {
 #define CHECK_CTXT_ARGS(CTXT_Pp)
 
 #define exit_fun(msg) exit_function(__FILE__,__FUNCTION__,__LINE__,msg)
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 void exit_function(const char *file, const char *function, const int line, const char *s);
+#ifdef __cplusplus
+}
+#endif
 #endif
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
index b56e8b11e9..8ee8cdc1c0 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
@@ -221,7 +221,7 @@ rlc_op_status_t rlc_data_req     (const protocol_ctxt_t *const ctxt_pP,
   nr_rlc_ue_t *ue;
   nr_rlc_entity_t *rb;
 
-  LOG_D(RLC, "%s rnti %d srb_flag %d rb_id %d mui %d confirm %d sdu_size %d MBMS_flag %d\n",
+  LOG_D(RLC, "%s rnti %d srb_flag %d rb_id %ld mui %d confirm %d sdu_size %d MBMS_flag %d\n",
         __FUNCTION__, rnti, srb_flagP, rb_idP, muiP, confirmP, sdu_sizeP,
         MBMS_flagP);
 
@@ -824,24 +824,24 @@ rlc_op_status_t rrc_rlc_config_req   (
   }
   if ((srb_flagP && !(rb_idP >= 1 && rb_idP <= 2)) ||
       (!srb_flagP && !(rb_idP >= 1 && rb_idP <= 5))) {
-    LOG_E(RLC, "%s:%d:%s: bad rb_id (%d) (is_srb %d)\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP);
+    LOG_E(RLC, "%s:%d:%s: bad rb_id (%ld) (is_srb %d)\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP);
     exit(1);
   }
   nr_rlc_manager_lock(nr_rlc_ue_manager);
-  LOG_D(RLC, "%s:%d:%s: remove rb %d (is_srb %d) for UE %d\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP, ctxt_pP->rnti);
+  LOG_D(RLC, "%s:%d:%s: remove rb %ld (is_srb %d) for UE %d\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP, ctxt_pP->rnti);
   ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ctxt_pP->rnti);
   if (srb_flagP) {
     if (ue->srb[rb_idP-1] != NULL) {
       ue->srb[rb_idP-1]->delete(ue->srb[rb_idP-1]);
       ue->srb[rb_idP-1] = NULL;
     } else
-      LOG_W(RLC, "removing non allocated SRB %d, do nothing\n", rb_idP);
+      LOG_W(RLC, "removing non allocated SRB %ld, do nothing\n", rb_idP);
   } else {
     if (ue->drb[rb_idP-1] != NULL) {
       ue->drb[rb_idP-1]->delete(ue->drb[rb_idP-1]);
       ue->drb[rb_idP-1] = NULL;
     } else
-      LOG_W(RLC, "removing non allocated DRB %d, do nothing\n", rb_idP);
+      LOG_W(RLC, "removing non allocated DRB %ld, do nothing\n", rb_idP);
   }
   /* remove UE if it has no more RB configured */
   for (i = 0; i < 2; i++)
diff --git a/openair2/NETWORK_DRIVER/UE_IP/common.c b/openair2/NETWORK_DRIVER/UE_IP/common.c
index 0d66f42357..86e00ef674 100644
--- a/openair2/NETWORK_DRIVER/UE_IP/common.c
+++ b/openair2/NETWORK_DRIVER/UE_IP/common.c
@@ -193,7 +193,7 @@ ue_ip_common_class_wireless2ip(
       break;
 
     default:
-      printk("[UE_IP_DRV][%s] begin RB %d Inst %d Length %d bytes\n",__FUNCTION__,rb_idP,instP,data_lenP);
+      printk("[UE_IP_DRV][%s] begin RB %ld Inst %d Length %d bytes\n",__FUNCTION__,rb_idP,instP,data_lenP);
       printk("[UE_IP_DRV][%s] Inst %d: receive unknown message (version=%d)\n",__FUNCTION__,instP,ipv_p->version);
   }
 
@@ -318,7 +318,7 @@ ue_ip_common_ip2wireless(
 
   if (bytes_wrote != UE_IP_PDCPH_SIZE) {
     printk("[UE_IP_DRV][%s] problem while writing PDCP's header (bytes wrote = %d)\n",__FUNCTION__,bytes_wrote);
-    printk("rb_id %d, Wrote %d, Header Size %d \n", pdcph.rb_id, bytes_wrote, UE_IP_PDCPH_SIZE);
+    printk("rb_id %ld, Wrote %d, Header Size %d \n", pdcph.rb_id, bytes_wrote, UE_IP_PDCPH_SIZE);
     priv_p->stats.tx_dropped ++;
     return;
   }
@@ -326,7 +326,7 @@ ue_ip_common_ip2wireless(
   bytes_wrote += ue_ip_netlink_send((char *)skb_pP->data,skb_pP->len);
 
   if (bytes_wrote != skb_pP->len+UE_IP_PDCPH_SIZE) {
-    printk("[UE_IP_DRV][%s] Inst %d, RB_ID %d: problem while writing PDCP's data, bytes_wrote = %d, Data_len %d, PDCPH_SIZE %d\n",
+    printk("[UE_IP_DRV][%s] Inst %d, RB_ID %ld: problem while writing PDCP's data, bytes_wrote = %d, Data_len %d, PDCPH_SIZE %d\n",
            __FUNCTION__,
            instP,
            pdcph.rb_id,
diff --git a/openair2/UTIL/OTG/otg_rx_socket.c b/openair2/UTIL/OTG/otg_rx_socket.c
index 9e9b6bf4a1..a343910efd 100644
--- a/openair2/UTIL/OTG/otg_rx_socket.c
+++ b/openair2/UTIL/OTG/otg_rx_socket.c
@@ -195,7 +195,7 @@ void server_socket_tcp_ip4()
 
 
               /* create  new thread for the new connection */
-              threadCreate(&id, (void *)recv_ip4_tcp, (void*)csock), "OTG", -1, OAI_PRIORITY_RT_LOW);
+              threadCreate(&id, (void *)recv_ip4_tcp, (void*)csock, "OTG", -1, OAI_PRIORITY_RT_LOW);
               LOG_I(OTG,"SOCKET:: TCP-IP4 :: Client n=%d finish transmission\n", cmpt_cl);
               cmpt_cl+=1;
             }
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index 8cfa398615..bb05808142 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -30,9 +30,9 @@
 #include <stdio.h>
 #include <uhd/version.hpp>
 #if UHD_VERSION < 3110000
-#include <uhd/utils/thread_priority.hpp>
+  #include <uhd/utils/thread_priority.hpp>
 #else
-#include <uhd/utils/thread.hpp>
+  #include <uhd/utils/thread.hpp>
 #endif
 #include <uhd/usrp/multi_usrp.hpp>
 #include <uhd/version.hpp>
@@ -48,26 +48,28 @@
 #include "common/utils/LOG/log.h"
 #include "common_lib.h"
 #include "assertions.h"
-#include <sys/sysinfo.h>
+
 #include <sys/resource.h>
 
+#include "usrp_lib.h"
+
 #ifdef __SSE4_1__
-#  include <smmintrin.h>
+  #include <smmintrin.h>
 #endif
 
 #ifdef __AVX2__
-#  include <immintrin.h>
+  #include <immintrin.h>
 #endif
 
 #ifdef __arm__
-#  include <arm_neon.h>
+  #include <arm_neon.h>
 #endif
 
 /** @addtogroup _USRP_PHY_RF_INTERFACE_
  * @{
  */
 
-/*! \brief USRP Configuration */
+
 typedef struct {
 
   // --------------------------------
@@ -106,7 +108,8 @@ typedef struct {
   int first_tx;
   //! timestamp of RX packet
   openair0_timestamp rx_timestamp;
-
+  uint32_t recplay_mode;
+  recplay_state_t *recplay_state;
 } usrp_state_t;
 
 //void print_notes(void)
@@ -128,10 +131,10 @@ int check_ref_locked(usrp_state_t *s,size_t mboard) {
 
     for (int i = 0; i < 30 and not ref_locked; i++) {
       ref_locked = s->usrp->get_mboard_sensor("ref_locked", mboard).to_bool();
-      
+
       if (not ref_locked) {
-	std::cout << "." << std::flush;
-	boost::this_thread::sleep(boost::posix_time::seconds(1));
+        std::cout << "." << std::flush;
+        boost::this_thread::sleep(boost::posix_time::seconds(1));
       }
     }
 
@@ -140,13 +143,11 @@ int check_ref_locked(usrp_state_t *s,size_t mboard) {
     } else {
       std::cout << "FAILED" << std::endl;
     }
-
   } else {
     std::cout << boost::format("ref_locked sensor not present on this board.\n");
   }
 
   return ref_locked;
-
 }
 
 static int sync_to_gps(openair0_device *device) {
@@ -179,14 +180,13 @@ static int sync_to_gps(openair0_device *device) {
 
     for (size_t mboard = 0; mboard < num_mboards; mboard++) {
       std::cout << "Synchronizing mboard " << mboard << ": " << s->usrp->get_mboard_name(mboard) << std::endl;
-
       bool ref_locked = check_ref_locked(s,mboard);
 
       if (ref_locked) {
-	std::cout << boost::format("Ref Locked\n");
+        std::cout << boost::format("Ref Locked\n");
       } else {
-	std::cout << "Failed to lock to GPSDO 10 MHz Reference. Exiting." << std::endl;
-	exit(EXIT_FAILURE);
+        std::cout << "Failed to lock to GPSDO 10 MHz Reference. Exiting." << std::endl;
+        exit(EXIT_FAILURE);
       }
 
       //Wait for GPS lock
@@ -265,175 +265,134 @@ static int sync_to_gps(openair0_device *device) {
   return EXIT_SUCCESS;
 }
 
-#if defined(USRP_REC_PLAY)
-#include "usrp_lib.h"
-static FILE    *pFile = NULL;
-int             mmapfd = 0;
-int             iqfd = 0;
-int             use_mmap = 1; // default is to use mmap
-struct stat     sb;
-iqrec_t        *ms_sample = NULL;                      // memory for all subframes
-unsigned int    nb_samples = 0;
-unsigned int    cur_samples = 0;
-int64_t         wrap_count = 0;
-int64_t         wrap_ts = 0;
-unsigned int    u_sf_mode = 0;                         // 1=record, 2=replay
-unsigned int    u_sf_record = 0;                       // record mode
-unsigned int    u_sf_replay = 0;                       // replay mode
-char            u_sf_filename[1024] = "";              // subframes file path
-unsigned int    u_sf_max = DEF_NB_SF;                  // max number of recorded subframes
-unsigned int    u_sf_loops = DEF_SF_NB_LOOP;           // number of loops in replay mode
-unsigned int    u_sf_read_delay = DEF_SF_DELAY_READ;   // read delay in replay mode
-unsigned int    u_sf_write_delay = DEF_SF_DELAY_WRITE; // write delay in replay mode
-
-char config_opt_sf_file[] = CONFIG_OPT_SF_FILE;
-char config_def_sf_file[] = DEF_SF_FILE;
-char config_hlp_sf_file[] = CONFIG_HLP_SF_FILE;
-char config_opt_sf_rec[] = CONFIG_OPT_SF_REC;
-char config_hlp_sf_rec[] = CONFIG_HLP_SF_REC;
-char config_opt_sf_rep[] = CONFIG_OPT_SF_REP;
-char config_hlp_sf_rep[] = CONFIG_HLP_SF_REP;
-char config_opt_sf_max[] = CONFIG_OPT_SF_MAX;
-char config_hlp_sf_max[] = CONFIG_HLP_SF_MAX;
-char config_opt_sf_loops[] = CONFIG_OPT_SF_LOOPS;
-char config_hlp_sf_loops[] = CONFIG_HLP_SF_LOOPS;
-char config_opt_sf_rdelay[] = CONFIG_OPT_SF_RDELAY;
-char config_hlp_sf_rdelay[] = CONFIG_HLP_SF_RDELAY;
-char config_opt_sf_wdelay[] = CONFIG_OPT_SF_WDELAY;
-char config_hlp_sf_wdelay[] = CONFIG_HLP_SF_WDELAY;
-
-#endif
-
 /*! \brief Called to start the USRP transceiver. Return 0 if OK, < 0 if error
     @param device pointer to the device structure specific to the RF hardware target
 */
 static int trx_usrp_start(openair0_device *device) {
-#if defined(USRP_REC_PLAY)
+  usrp_state_t *s = (usrp_state_t *)device->priv;
 
-  if (u_sf_mode != 2) { // not replay mode
-#endif
-    uhd::set_thread_priority_safe(1.0);
-    usrp_state_t *s = (usrp_state_t *)device->priv;
-    // setup GPIO for TDD, GPIO(4) = ATR_RX
-    //set data direction register (DDR) to output
-    s->usrp->set_gpio_attr("FP0", "DDR", 0x7f, 0x7f);
-    //set control register to ATR
-    s->usrp->set_gpio_attr("FP0", "CTRL", 0x7f,0x7f);
-    //set ATR register
-    s->usrp->set_gpio_attr("FP0", "ATR_RX", (1<<4)|(1<<6), 0x7f);
-    // init recv and send streaming
-    uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
-    LOG_I(HW,"Time in secs now: %llu \n", s->usrp->get_time_now().to_ticks(s->sample_rate));
-    LOG_I(HW,"Time in secs last pps: %llu \n", s->usrp->get_time_last_pps().to_ticks(s->sample_rate));
-
-    if (s->use_gps == 1 || device->openair0_cfg[0].time_source == external) {
-      s->wait_for_first_pps = 1;
-      cmd.time_spec = s->usrp->get_time_last_pps() + uhd::time_spec_t(1.0);
-    } else {
-      s->wait_for_first_pps = 0;
-      cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.005);
-    }
+  if ( s->recplay_mode == RECPLAY_REPLAYMODE)
+    return 0;
 
-    cmd.stream_now = false; // start at constant delay
-    s->rx_stream->issue_stream_cmd(cmd);
-    /*s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate);
-    s->tx_md.has_time_spec = true;
-    s->tx_md.start_of_burst = true;
-    s->tx_md.end_of_burst = false;*/
-    s->rx_count = 0;
-    s->tx_count = 0;
-    s->rx_timestamp = 0;
-#if defined(USRP_REC_PLAY)
+  // setup GPIO for TDD, GPIO(4) = ATR_RX
+  //set data direction register (DDR) to output
+  s->usrp->set_gpio_attr("FP0", "DDR", 0x7f, 0x7f);
+  //set control register to ATR
+  s->usrp->set_gpio_attr("FP0", "CTRL", 0x7f,0x7f);
+  //set ATR register
+  s->usrp->set_gpio_attr("FP0", "ATR_RX", (1<<4)|(1<<6), 0x7f);
+  // init recv and send streaming
+  uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
+  LOG_I(HW,"Time in secs now: %llu \n", s->usrp->get_time_now().to_ticks(s->sample_rate));
+  LOG_I(HW,"Time in secs last pps: %llu \n", s->usrp->get_time_last_pps().to_ticks(s->sample_rate));
+
+  if (s->use_gps == 1 || device->openair0_cfg[0].time_source == external) {
+    s->wait_for_first_pps = 1;
+    cmd.time_spec = s->usrp->get_time_last_pps() + uhd::time_spec_t(1.0);
+  } else {
+    s->wait_for_first_pps = 0;
+    cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.005);
   }
 
-#endif
+  cmd.stream_now = false; // start at constant delay
+  s->rx_stream->issue_stream_cmd(cmd);
+  /*s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate);
+  s->tx_md.has_time_spec = true;
+  s->tx_md.start_of_burst = true;
+  s->tx_md.end_of_burst = false;*/
+  s->rx_count = 0;
+  s->tx_count = 0;
+  s->rx_timestamp = 0;
   return 0;
 }
 /*! \brief Terminate operation of the USRP transceiver -- free all associated resources
  * \param device the hardware to use
  */
 static void trx_usrp_end(openair0_device *device) {
-#if defined(USRP_REC_PLAY) // For some ugly reason, this can be called several times...
-  static int done = 0;
+  if (device == NULL)
+    return;
 
-  if (done == 1) return;
-
-  done = 1;
+  usrp_state_t *s = (usrp_state_t *)device->priv;
 
+  if (s == NULL)
+    return;
 
-  if (u_sf_mode != 2) { // not subframes replay
-#endif
-    usrp_state_t *s = (usrp_state_t *)device->priv;
+  if (s->recplay_mode != RECPLAY_REPLAYMODE) { // not subframes replay
     s->rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
     //send a mini EOB packet
     s->tx_md.end_of_burst = true;
     s->tx_stream->send("", 0, s->tx_md);
     s->tx_md.end_of_burst = false;
     sleep(1);
-#if defined(USRP_REC_PLAY)
   }
 
-#endif
-#if defined(USRP_REC_PLAY)
-
-  if (u_sf_mode == 1) { // subframes store
-    pFile = fopen (u_sf_filename,"wb+");
+  if (s->recplay_mode == RECPLAY_RECORDMODE) { // subframes store
+    s->recplay_state->pFile = fopen (s->recplay_state->u_sf_filename,"wb+");
 
-    if (pFile == NULL) {
-      std::cerr << "Cannot open " << u_sf_filename << std::endl;
+    if (s->recplay_state->pFile == NULL) {
+      std::cerr << "Cannot open " << s->recplay_state->u_sf_filename << std::endl;
     } else {
       unsigned int i = 0;
       unsigned int modu = 0;
 
-      if ((modu = nb_samples % 10) != 0) {
-        nb_samples -= modu; // store entire number of frames
+      if ((modu = s->recplay_state->nb_samples % 10) != 0) {
+        s->recplay_state->nb_samples -= modu; // store entire number of frames
       }
 
-      std::cerr << "Writing " << nb_samples << " subframes to " << u_sf_filename << " ..." << std::endl;
+      std::cerr << "Writing " << s->recplay_state->nb_samples << " subframes to " << s->recplay_state->u_sf_filename << " ..." << std::endl;
 
-      for (i = 0; i < nb_samples; i++) {
-        fwrite(ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), pFile);
+      for (i = 0; i < s->recplay_state->nb_samples; i++) {
+        fwrite(s->recplay_state->ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), s->recplay_state->pFile);
       }
 
-      fclose (pFile);
-      std::cerr << "File " << u_sf_filename << " closed." << std::endl;
+      fclose (s->recplay_state->pFile);
+      std::cerr << "File " << s->recplay_state->u_sf_filename << " closed." << std::endl;
     }
-  }
 
-  if (u_sf_mode == 1) { // record
-    if (ms_sample != NULL) {
-      free((void *)ms_sample);
-      ms_sample = NULL;
+    if (s->recplay_state->ms_sample != NULL) {
+      free((void *)s->recplay_state->ms_sample);
+      s->recplay_state->ms_sample = NULL;
     }
-  }
-
-  if (u_sf_mode == 2) { // replay
-    if (use_mmap) {
-      if (ms_sample != MAP_FAILED) {
-        munmap(ms_sample, sb.st_size);
-        ms_sample = NULL;
+  } else if (s->recplay_mode == RECPLAY_REPLAYMODE) { // replay
+    if (s->recplay_state->use_mmap) {
+      if (s->recplay_state->ms_sample != MAP_FAILED) {
+        munmap(s->recplay_state->ms_sample, s->recplay_state->mapsize);
+        s->recplay_state->ms_sample = NULL;
       }
 
-      if (mmapfd != 0) {
-        close(mmapfd);
-        mmapfd = 0;
+      if (s->recplay_state->mmapfd != 0) {
+        close(s->recplay_state->mmapfd);
+        s->recplay_state->mmapfd = 0;
       }
     } else {
-      if (ms_sample != NULL) {
-        free(ms_sample);
-        ms_sample = NULL;
+      if (s->recplay_state->ms_sample != NULL) {
+        free(s->recplay_state->ms_sample);
+        s->recplay_state->ms_sample = NULL;
       }
 
-      if (iqfd != 0) {
-        close(iqfd);
-        iqfd = 0;
+      if (s->recplay_state->iqfd != 0) {
+        close(s->recplay_state->iqfd);
+        s->recplay_state->iqfd = 0;
       }
     }
   }
-
-#endif
 }
-
+/*! \brief Write iqs function when in replay mode, just introduce a delay, as configured at init time,
+      @param device pointer to the device structure specific to the RF hardware target
+      @param timestamp The timestamp at which the first sample MUST be sent
+      @param buff Buffer which holds the samples
+      @param nsamps number of samples to be sent
+      @param antenna_id index of the antenna if the device has multiple antennas
+      @param flags flags must be set to TRUE if timestamp parameter needs to be applied
+*/
+static int trx_usrp_write_recplay(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
+  struct timespec req;
+  usrp_state_t *s = (usrp_state_t *)device->priv;
+  req.tv_sec = 0;
+  req.tv_nsec = s->recplay_state->u_sf_write_delay * 1000;
+  nanosleep(&req, NULL);
+  return nsamps;
+}
 /*! \brief Called to send samples to the USRP RF target
       @param device pointer to the device structure specific to the RF hardware target
       @param timestamp The timestamp at which the first sample MUST be sent
@@ -444,14 +403,8 @@ static void trx_usrp_end(openair0_device *device) {
 */
 static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
   int ret=0;
-#if defined(USRP_REC_PLAY)
-
-  if (u_sf_mode != 2) { // not replay mode
-#endif
-    usrp_state_t *s = (usrp_state_t *)device->priv;
-
-    int nsamps2;  // aligned to upper 32 or 16 byte boundary
-
+  usrp_state_t *s = (usrp_state_t *)device->priv;
+  int nsamps2;  // aligned to upper 32 or 16 byte boundary
 #if defined(__x86_64) || defined(__i386__)
   #ifdef __AVX2__
       nsamps2 = (nsamps+7)>>3;
@@ -464,23 +417,24 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
     nsamps2 = (nsamps+3)>>2;
     int16x8_t buff_tx[8][nsamps2];
 #else
-    #error Unsupported CPU architecture, USRP device cannot be built
+#error Unsupported CPU architecture, USRP device cannot be built
 #endif
 
-    // bring RX data into 12 LSBs for softmodem RX
-    for (int i=0; i<cc; i++) {
-      for (int j=0; j<nsamps2; j++) {
+  // bring RX data into 12 LSBs for softmodem RX
+  for (int i=0; i<cc; i++) {
+    for (int j=0; j<nsamps2; j++) {
 #if defined(__x86_64__) || defined(__i386__)
 #ifdef __AVX2__
-        buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
+      buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
 #else
-        buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4);
+      buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4);
 #endif
 #elif defined(__arm__)
-        buff_tx[i][j] = vshlq_n_s16(((int16x8_t *)buff[i])[j],4);
+      buff_tx[i][j] = vshlq_n_s16(((int16x8_t *)buff[i])[j],4);
 #endif
-      }
     }
+  }
+
 
     boolean_t first_packet_state=false,last_packet_state=false;
 
@@ -495,56 +449,43 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
       first_packet_state = false;
       last_packet_state  = true;
     } else if (flags == 4) { // start and end
-    //  s->tx_md.start_of_burst = true;
-    //  s->tx_md.end_of_burst = true;
+      //  s->tx_md.start_of_burst = true;
+      //  s->tx_md.end_of_burst = true;
       first_packet_state = true;
       last_packet_state  = true;
     } else if (flags==1) { // middle of burst
-    //  s->tx_md.start_of_burst = false;
-    //  s->tx_md.end_of_burst = false;
+      //  s->tx_md.start_of_burst = false;
+      //  s->tx_md.end_of_burst = false;
       first_packet_state = false;
       last_packet_state  = false;
-    }
-    else if (flags==10) { // fail safe mode
-     // s->tx_md.has_time_spec = false;
-     // s->tx_md.start_of_burst = false;
-     // s->tx_md.end_of_burst = true;
-     first_packet_state = false;
-     last_packet_state  = true;
+    } else if (flags==10) { // fail safe mode
+      // s->tx_md.has_time_spec = false;
+      // s->tx_md.start_of_burst = false;
+      // s->tx_md.end_of_burst = true;
+      first_packet_state = false;
+      last_packet_state  = true;
     }
 
     s->tx_md.has_time_spec  = true;
-    s->tx_md.start_of_burst = (s->tx_count==0) ? true : first_packet_state; 
+    s->tx_md.start_of_burst = (s->tx_count==0) ? true : first_packet_state;
     s->tx_md.end_of_burst   = last_packet_state;
     s->tx_md.time_spec      = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate);
-
     s->tx_count++;
 
     if (cc>1) {
-       std::vector<void *> buff_ptrs;
+      std::vector<void *> buff_ptrs;
 
-       for (int i=0; i<cc; i++)
-         buff_ptrs.push_back(&(((int16_t*)buff_tx[i])[0]));
+      for (int i=0; i<cc; i++)
+        buff_ptrs.push_back(&(((int16_t *)buff_tx[i])[0]));
 
-       ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md);
+      ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md);
     } else ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md);
+  if (ret != nsamps) LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps);
 
-     if (ret != nsamps) LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps);
- 
-#if defined(USRP_REC_PLAY)
-  } else {
-    struct timespec req;
-    req.tv_sec = 0;
-    req.tv_nsec = u_sf_write_delay * 1000;
-    nanosleep(&req, NULL);
-    ret = nsamps;
-  }
-
-#endif
   return ret;
 }
 
-/*! \brief Receive samples from hardware.
+/*! \brief Receive samples from iq file.
  * Read \ref 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.
@@ -555,190 +496,206 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
  * \param antenna_id Index of antenna for which to receive samples
  * \returns the number of sample read
 */
-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;
+static int trx_usrp_read_recplay(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
   int samples_received=0;
-  int nsamps2;  // aligned to upper 32 or 16 byte boundary
-#if defined(USRP_REC_PLAY)
+  static unsigned int    cur_samples;
+  static int64_t         wrap_count;
+  static int64_t  wrap_ts;
+  usrp_state_t *s = (usrp_state_t *)device->priv;
 
-  if (u_sf_mode != 2) { // not replay mode
-#endif
-#if defined(__x86_64) || defined(__i386__)
-#ifdef __AVX2__
-    nsamps2 = (nsamps+7)>>3;
-    __m256i buff_tmp[8][nsamps2];
-#else
-    nsamps2 = (nsamps+3)>>2;
-    __m128i buff_tmp[8][nsamps2];
-#endif
-#elif defined(__arm__)
-    nsamps2 = (nsamps+3)>>2;
-    int16x8_t buff_tmp[8][nsamps2];
-#endif
 
-    if (device->type == USRP_B200_DEV) {
-      if (cc>1) {
-        // receive multiple channels (e.g. RF A and RF B)
-        std::vector<void *> buff_ptrs;
+  if (cur_samples == s->recplay_state->nb_samples) {
+    cur_samples = 0;
+    wrap_count++;
+    if (wrap_count == s->recplay_state->u_sf_loops) {
+      std::cerr << "USRP device terminating subframes replay mode after " << s->recplay_state->u_sf_loops << " loops." << std::endl;
+      exit_function(__FILE__, __FUNCTION__, __LINE__,"replay ended, triggering process termination\n");
+    }
 
-        for (int i=0; i<cc; i++) buff_ptrs.push_back(buff_tmp[i]);
+    wrap_ts = wrap_count * (s->recplay_state->nb_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000));
 
-        samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md);
+    if (!s->recplay_state->use_mmap) {
+      if (lseek(s->recplay_state->iqfd, 0, SEEK_SET) == 0) {
+        std::cerr << "Seeking at the beginning of IQ file" << std::endl;
       } else {
-        // receive a single channel (e.g. from connector RF A)
-        samples_received=0;
+        std::cerr << "Problem seeking at the beginning of IQ file" << std::endl;
+      }
+    }
+  }
 
-        while (samples_received != nsamps) {
-          samples_received += s->rx_stream->recv(buff_tmp[0]+samples_received,
-                                                 nsamps-samples_received, s->rx_md);
+  if (s->recplay_state->use_mmap) {
+    if (cur_samples < s->recplay_state->nb_samples) {
+      *ptimestamp = (s->recplay_state->ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts;
 
-          if  ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE))
-            break;
+      if (cur_samples == 0) {
+        std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
+                  << " ts=" << *ptimestamp << std::endl;
+      }
 
-          if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) {
-            printf("sleep...\n"); //usleep(100);
-          }
-        }
+      memcpy(buff[0], &s->recplay_state->ms_sample[cur_samples].samples[0], nsamps*4);
+      cur_samples++;
+    }
+  } else {
+    // read sample from file
+    if (read(s->recplay_state->iqfd, s->recplay_state->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) {
+      std::cerr << "pb reading iqfile at index " << sizeof(iqrec_t)*cur_samples << std::endl;
+      close(s->recplay_state->iqfd);
+      free(s->recplay_state->ms_sample);
+      s->recplay_state->ms_sample = NULL;
+      s->recplay_state->iqfd = 0;
+      exit(-1);
+    }
 
-        if (samples_received == nsamps) s->wait_for_first_pps=0;
+    if (cur_samples < s->recplay_state->nb_samples) {
+      static int64_t ts0 = 0;
+
+      if ((cur_samples == 0) && (wrap_count == 0)) {
+        ts0 = s->recplay_state->ms_sample->ts;
       }
 
-      // bring RX data into 12 LSBs for softmodem RX
-      for (int i=0; i<cc; i++) {
-        for (int j=0; j<nsamps2; j++) {
-#if defined(__x86_64__) || defined(__i386__)
-#ifdef __AVX2__
-	  // FK: in some cases the buffer might not be 32 byte aligned, so we cannot use avx2
-
-	  if ((((uintptr_t) buff[i])&0x1F)==0) {
-	    ((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
-	  }
-	  else {
-	    ((__m128i *)buff[i])[2*j] = _mm_srai_epi16(((__m128i*)buff_tmp[i])[2*j],4);
-	    ((__m128i *)buff[i])[2*j+1] = _mm_srai_epi16(((__m128i*)buff_tmp[i])[2*j+1],4);
-	  }
-#else
-          ((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4);
-#endif
-#elif defined(__arm__)
-          ((int16x8_t *)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4);
-#endif
-        }
+      *ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts;
+
+      if (cur_samples == 0) {
+        std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
+                  << " ts=" << *ptimestamp << std::endl;
       }
-    } else if (device->type == USRP_X300_DEV) {
-      if (cc>1) {
-        // receive multiple channels (e.g. RF A and RF B)
-        std::vector<void *> buff_ptrs;
 
-        for (int i=0; i<cc; i++) buff_ptrs.push_back(buff[i]);
+      memcpy(buff[0], &s->recplay_state->ms_sample->samples[0], nsamps*4);
+      cur_samples++;
+      // Prepare for next read
+      off_t where = lseek(s->recplay_state->iqfd, cur_samples * sizeof(iqrec_t), SEEK_SET);
 
-        samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md,1.0);
-      } else {
-        // receive a single channel (e.g. from connector RF A)
-        samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md,1.0);
+      if (where < 0) {
+        LOG_E(HW,"Cannot lseek in iqfile: %s\n",strerror(errno));
       }
     }
+  }
 
-    if (samples_received < nsamps)
-      LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps);
+  struct timespec req;
 
-    if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE)
-      LOG_E(HW, "%s\n", s->rx_md.to_pp_string(true).c_str());
+  req.tv_sec = 0;
 
-    s->rx_count += nsamps;
-    s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
-    *ptimestamp = s->rx_timestamp;
-#if defined (USRP_REC_PLAY)
-  }
+  req.tv_nsec = s->recplay_state->u_sf_read_delay * 1000;
 
-#endif
-#if defined(USRP_REC_PLAY)
+  nanosleep(&req, NULL);
 
-  if (u_sf_mode == 1) { // record mode
-    // Copy subframes to memory (later dump on a file)
-    if (nb_samples < u_sf_max) {
-      (ms_sample+nb_samples)->header = BELL_LABS_IQ_HEADER;
-      (ms_sample+nb_samples)->ts = *ptimestamp;
-      memcpy((ms_sample+nb_samples)->samples, buff[0], nsamps*4);
-      nb_samples++;
-    }
-  } else if (u_sf_mode == 2) { // replay mode
-    if (cur_samples == nb_samples) {
-      cur_samples = 0;
-      wrap_count++;
-
-      if (wrap_count == u_sf_loops) {
-        std::cerr << "USRP device terminating subframes replay mode after " << u_sf_loops << " loops." << std::endl;
-        return 0; // should make calling process exit
-      }
+  return nsamps;
+
+  return samples_received;
+}
 
-      wrap_ts = wrap_count * (nb_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000));
 
-      if (!use_mmap) {
-        if (lseek(iqfd, 0, SEEK_SET) == 0) {
-          std::cerr << "Seeking at the beginning of IQ file" << std::endl;
-        } else {
-          std::cerr << "Problem seeking at the beginning of IQ file" << std::endl;
-        }
-      }
-    }
+/*! \brief Receive samples from hardware.
+ * Read \ref 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.
+ * \param device the hardware to use
+ * \param[out] ptimestamp the time at which the first sample was received.
+ * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps.
+ * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
+ * \param antenna_id Index of antenna for which to receive samples
+ * \returns the number of sample read
+*/
+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;
+  int nsamps2;  // aligned to upper 32 or 16 byte boundary
+#if defined(__x86_64) || defined(__i386__)
+#ifdef __AVX2__
+  nsamps2 = (nsamps+7)>>3;
+  __m256i buff_tmp[2][nsamps2];
+#else
+  nsamps2 = (nsamps+3)>>2;
+  __m128i buff_tmp[2][nsamps2];
+#endif
+#elif defined(__arm__)
+  nsamps2 = (nsamps+3)>>2;
+  int16x8_t buff_tmp[2][nsamps2];
+#endif
 
-    if (use_mmap) {
-      if (cur_samples < nb_samples) {
-        *ptimestamp = (ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts;
+  if (device->type == USRP_B200_DEV) {
+    if (cc>1) {
+      // receive multiple channels (e.g. RF A and RF B)
+      std::vector<void *> buff_ptrs;
 
-        if (cur_samples == 0) {
-          std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
-                    << " ts=" << *ptimestamp << std::endl;
-        }
+      for (int i=0; i<cc; i++) buff_ptrs.push_back(buff_tmp[i]);
 
-        memcpy(buff[0], &ms_sample[cur_samples].samples[0], nsamps*4);
-        cur_samples++;
-      }
+      samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md);
     } else {
-      // read sample from file
-      if (read(iqfd, ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) {
-        std::cerr << "pb reading iqfile at index " << sizeof(iqrec_t)*cur_samples << std::endl;
-        close(iqfd);
-        free(ms_sample);
-        ms_sample = NULL;
-        iqfd = 0;
-        exit(-1);
-      }
+      // receive a single channel (e.g. from connector RF A)
+      samples_received=0;
+
+      while (samples_received != nsamps) {
+        samples_received += s->rx_stream->recv(buff_tmp[0]+samples_received,
+                                               nsamps-samples_received, s->rx_md);
 
-      if (cur_samples < nb_samples) {
-        static int64_t ts0 = 0;
+        if  ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE))
+          break;
 
-        if ((cur_samples == 0) && (wrap_count == 0)) {
-          ts0 = ms_sample->ts;
+        if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) {
+          printf("sleep...\n"); //usleep(100);
         }
+      }
 
-        *ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts;
+      if (samples_received == nsamps) s->wait_for_first_pps=0;
+    }
+
+    // bring RX data into 12 LSBs for softmodem RX
+    for (int i=0; i<cc; i++) {
+      for (int j=0; j<nsamps2; j++) {
+#if defined(__x86_64__) || defined(__i386__)
+#ifdef __AVX2__
+        // FK: in some cases the buffer might not be 32 byte aligned, so we cannot use avx2
 
-        if (cur_samples == 0) {
-          std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
-                    << " ts=" << *ptimestamp << std::endl;
+        if ((((uintptr_t) buff[i])&0x1F)==0) {
+          ((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
+        } else {
+          ((__m128i *)buff[i])[2*j] = _mm_srai_epi16(((__m128i *)buff_tmp[i])[2*j],4);
+          ((__m128i *)buff[i])[2*j+1] = _mm_srai_epi16(((__m128i *)buff_tmp[i])[2*j+1],4);
         }
 
-        memcpy(buff[0], &ms_sample->samples[0], nsamps*4);
-        cur_samples++;
-        // Prepare for next read
-        off_t where = lseek(iqfd, cur_samples * sizeof(iqrec_t), SEEK_SET);
+#else
+        ((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4);
+#endif
+#elif defined(__arm__)
+        ((int16x8_t *)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4);
+#endif
       }
     }
+  } else if (device->type == USRP_X300_DEV) {
+    if (cc>1) {
+      // receive multiple channels (e.g. RF A and RF B)
+      std::vector<void *> buff_ptrs;
 
-    struct timespec req;
+      for (int i=0; i<cc; i++) buff_ptrs.push_back(buff[i]);
 
-    req.tv_sec = 0;
+      samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md,1.0);
+    } else {
+      // receive a single channel (e.g. from connector RF A)
+      samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md,1.0);
+    }
+  }
 
-    req.tv_nsec = u_sf_read_delay * 1000;
+  if (samples_received < nsamps)
+    LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps);
 
-    nanosleep(&req, NULL);
+  if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE)
+    LOG_E(HW, "%s\n", s->rx_md.to_pp_string(true).c_str());
 
-    return nsamps;
+  s->rx_count += nsamps;
+  s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
+  *ptimestamp = s->rx_timestamp;
+
+  if (s->recplay_mode == RECPLAY_RECORDMODE) { // record mode
+    // Copy subframes to memory (later dump on a file)
+    if (s->recplay_state->nb_samples < s->recplay_state->u_sf_max) {
+      (s->recplay_state->ms_sample+s->recplay_state->nb_samples)->header = BELL_LABS_IQ_HEADER;
+      (s->recplay_state->ms_sample+s->recplay_state->nb_samples)->ts = *ptimestamp;
+      memcpy((s->recplay_state->ms_sample+s->recplay_state->nb_samples)->samples, buff[0], nsamps*4);
+      s->recplay_state->nb_samples++;
+    } else     exit_function(__FILE__, __FUNCTION__, __LINE__,"Recording reaches max iq limit\n");
   }
 
-#endif
   return samples_received;
 }
 
@@ -868,7 +825,6 @@ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_
 
   if (bw_gain_adjust==1) {
     switch ((int)openair0_cfg[0].sample_rate) {
-
       case 46080000:
         break;
 
@@ -940,117 +896,37 @@ static void uhd_set_thread_priority(void) {
   uhd::set_thread_priority_safe(1.0);
 }
 
-#if defined(USRP_REC_PLAY)
-extern "C" {
-  /*! \brief Initializer for USRP record/playback config
-   * \param parameter array description
-   * \returns  0 on success
-   */
-  int trx_usrp_recplay_config_init(paramdef_t *usrp_recplay_params) {
-    // --subframes-file
-    memcpy(usrp_recplay_params[0].optname, config_opt_sf_file, strlen(config_opt_sf_file));
-    usrp_recplay_params[0].helpstr = config_hlp_sf_file;
-    usrp_recplay_params[0].paramflags=PARAMFLAG_NOFREE;
-    usrp_recplay_params[0].strptr=(char **)&u_sf_filename;
-    usrp_recplay_params[0].defstrval = NULL;
-    usrp_recplay_params[0].type=TYPE_STRING;
-    usrp_recplay_params[0].numelt=sizeof(u_sf_filename);
-    // --subframes-record
-    memcpy(usrp_recplay_params[1].optname, config_opt_sf_rec, strlen(config_opt_sf_rec));
-    usrp_recplay_params[1].helpstr = config_hlp_sf_rec;
-    usrp_recplay_params[1].paramflags=PARAMFLAG_BOOL;
-    usrp_recplay_params[1].uptr=&u_sf_record;
-    usrp_recplay_params[1].defuintval=0;
-    usrp_recplay_params[1].type=TYPE_UINT;
-    usrp_recplay_params[1].numelt=0;
-    // --subframes-replay
-    memcpy(usrp_recplay_params[2].optname, config_opt_sf_rep, strlen(config_opt_sf_rep));
-    usrp_recplay_params[2].helpstr = config_hlp_sf_rep;
-    usrp_recplay_params[2].paramflags=PARAMFLAG_BOOL;
-    usrp_recplay_params[2].uptr=&u_sf_replay;
-    usrp_recplay_params[2].defuintval=0;
-    usrp_recplay_params[2].type=TYPE_UINT;
-    usrp_recplay_params[2].numelt=0;
-    // --subframes-max
-    memcpy(usrp_recplay_params[3].optname, config_opt_sf_max, strlen(config_opt_sf_max));
-    usrp_recplay_params[3].helpstr = config_hlp_sf_max;
-    usrp_recplay_params[3].paramflags=0;
-    usrp_recplay_params[3].uptr=&u_sf_max;
-    usrp_recplay_params[3].defuintval=DEF_NB_SF;
-    usrp_recplay_params[3].type=TYPE_UINT;
-    usrp_recplay_params[3].numelt=0;
-    // --subframes-loops
-    memcpy(usrp_recplay_params[4].optname, config_opt_sf_loops, strlen(config_opt_sf_loops));
-    usrp_recplay_params[4].helpstr = config_hlp_sf_loops;
-    usrp_recplay_params[4].paramflags=0;
-    usrp_recplay_params[4].uptr=&u_sf_loops;
-    usrp_recplay_params[4].defuintval=DEF_SF_NB_LOOP;
-    usrp_recplay_params[4].type=TYPE_UINT;
-    usrp_recplay_params[4].numelt=0;
-    // --subframes-read-delay
-    memcpy(usrp_recplay_params[5].optname, config_opt_sf_rdelay, strlen(config_opt_sf_rdelay));
-    usrp_recplay_params[5].helpstr = config_hlp_sf_rdelay;
-    usrp_recplay_params[5].paramflags=0;
-    usrp_recplay_params[5].uptr=&u_sf_read_delay;
-    usrp_recplay_params[5].defuintval=DEF_SF_DELAY_READ;
-    usrp_recplay_params[5].type=TYPE_UINT;
-    usrp_recplay_params[5].numelt=0;
-    // --subframes-write-delay
-    memcpy(usrp_recplay_params[6].optname, config_opt_sf_wdelay, strlen(config_opt_sf_wdelay));
-    usrp_recplay_params[6].helpstr = config_hlp_sf_wdelay;
-    usrp_recplay_params[6].paramflags=0;
-    usrp_recplay_params[6].uptr=&u_sf_write_delay;
-    usrp_recplay_params[6].defuintval=DEF_SF_DELAY_WRITE;
-    usrp_recplay_params[6].type=TYPE_UINT;
-    usrp_recplay_params[6].numelt=0;
-    return 0; // always ok
-  }
+void noop_func(void) {
+  return;
 }
-#endif
-
 extern "C" {
   int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
-#if defined(USRP_REC_PLAY)
-    paramdef_t usrp_recplay_params[7];
-    struct sysinfo systeminfo;
-    // to check
-    static int done = 0;
-
-    if (done == 1) {
+    LOG_D(HW, "openair0_cfg[0].sdr_addrs == '%s'\n", openair0_cfg[0].sdr_addrs);
+    LOG_D(HW, "openair0_cfg[0].clock_source == '%d'\n", openair0_cfg[0].clock_source);
+    usrp_state_t *s ;
+
+    if ( device->priv == NULL) {
+      s=(usrp_state_t *)calloc(sizeof(usrp_state_t),1);
+      device->priv=s;
+      AssertFatal( s!=NULL,"USRP device: memory allocation failure\n");
+    } else {
+      LOG_E(HW, "multiple device init detected\n");
       return 0;
-    } // prevent from multiple init
-
-    done = 1;
-    // end to check
-    // Use mmap for IQ files for systems with less than 6GB total RAM
-    sysinfo(&systeminfo);
-
-    if (systeminfo.totalram < 6144000000) {
-      use_mmap = 0;
-    }
-
-    memset(usrp_recplay_params, 0, 7*sizeof(paramdef_t));
-    memset(&u_sf_filename[0], 0, 1024);
-
-    if (trx_usrp_recplay_config_init(usrp_recplay_params) != 0) {
-      std::cerr << "USRP device record/replay mode configuration error exiting" << std::endl;
-      return -1;
-    }
-
-    config_process_cmdline(usrp_recplay_params,sizeof(usrp_recplay_params)/sizeof(paramdef_t),NULL);
-
-    if (strlen(u_sf_filename) == 0) {
-      (void) strcpy(u_sf_filename, DEF_SF_FILE);
     }
 
-    if (u_sf_replay == 1) u_sf_mode = 2;
-
-    if (u_sf_record == 1) u_sf_mode = 1;
-
-    if (u_sf_mode == 2) {
+    device->openair0_cfg = openair0_cfg;
+    read_usrpconfig(&(s->recplay_mode), &(s->recplay_state));
+    device->trx_start_func = trx_usrp_start;
+    device->trx_get_stats_func = trx_usrp_get_stats;
+    device->trx_reset_stats_func = trx_usrp_reset_stats;
+    device->trx_end_func   = trx_usrp_end;
+    device->trx_stop_func  = trx_usrp_stop;
+    device->trx_set_freq_func = trx_usrp_set_freq;
+    device->trx_set_gains_func   = trx_usrp_set_gains;
+
+    if ( s->recplay_mode == RECPLAY_REPLAYMODE) {
       // Replay subframes from from file
       int bw_gain_adjust=0;
-      device->openair0_cfg = openair0_cfg;
       device->type = USRP_B200_DEV;
       openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
       bw_gain_adjust=1;
@@ -1060,45 +936,30 @@ extern "C" {
       openair0_cfg[0].iq_txshift = 4;//shift
       openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
       set_rx_gain_offset(&openair0_cfg[0],0,bw_gain_adjust);
-      device->priv = NULL;
-      device->trx_start_func = trx_usrp_start;
-      device->trx_write_func = trx_usrp_write;
-      device->trx_read_func  = trx_usrp_read;
-      device->trx_get_stats_func = trx_usrp_get_stats;
-      device->trx_reset_stats_func = trx_usrp_reset_stats;
-      device->trx_end_func   = trx_usrp_end;
-      device->trx_stop_func  = trx_usrp_stop;
-      device->trx_set_freq_func = trx_usrp_set_freq;
-      device->trx_set_gains_func   = trx_usrp_set_gains;
-      device->openair0_cfg = openair0_cfg;
-      device->uhd_set_thread_priority = uhd_set_thread_priority;
-      std::cerr << "USRP device initialized in subframes replay mode for " << u_sf_loops << " loops. Use mmap="
-                << use_mmap << std::endl;
+      device->trx_write_func = trx_usrp_write_recplay;
+      device->trx_read_func  = trx_usrp_read_recplay;
+      device->uhd_set_thread_priority = noop_func;
+      std::cerr << "USRP device initialized in subframes replay mode for " << s->recplay_state->u_sf_loops << " loops. Use mmap="
+                << s->recplay_state->use_mmap << std::endl;
     } else {
-#endif
-      usrp_state_t *s = (usrp_state_t *)calloc(sizeof(usrp_state_t),1);
-
       // Initialize USRP device
-      device->openair0_cfg = openair0_cfg;
       int vers=0,subvers=0,subsubvers=0;
       int bw_gain_adjust=0;
-#if defined(USRP_REC_PLAY)
 
-      if (u_sf_mode == 1) {
+      if (s->recplay_mode == RECPLAY_RECORDMODE) {
         std::cerr << "USRP device initialized in subframes record mode" << std::endl;
       }
 
-#endif
       sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers);
       LOG_I(HW,"UHD version %s (%d.%d.%d)\n",
             uhd::get_version_string().c_str(),vers,subvers,subsubvers);
-
       std::string args;
+
       if (openair0_cfg[0].sdr_addrs == NULL) {
         args = "type=b200";
       } else {
         args = openair0_cfg[0].sdr_addrs;
-	LOG_I(HW,"Checking for USRP with args %s\n",openair0_cfg[0].sdr_addrs);
+        LOG_I(HW,"Checking for USRP with args %s\n",openair0_cfg[0].sdr_addrs);
       }
 
       uhd::device_addrs_t device_adds = uhd::device::find(args);
@@ -1109,8 +970,8 @@ extern "C" {
         return -1;
       } else if (device_adds.size() > 1) {
         LOG_E(HW,"More than one USRP Device Found. Please specify device more precisely in config file.\n");
-	free(s);
-	return -1;
+        free(s);
+        return -1;
       }
 
       LOG_I(HW,"Found USRP %s\n", device_adds[0].get("type").c_str());
@@ -1123,6 +984,7 @@ extern "C" {
         args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
         args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=7680, recv_frame_size=7680" ;
       }
+
       if (device_adds[0].get("type") == "n3xx") {
         printf("Found USRP n300\n");
         device->type=USRP_X300_DEV; //treat it as X300 for now
@@ -1136,60 +998,55 @@ extern "C" {
         device->type=USRP_X300_DEV;
         usrp_master_clock = 184.32e6;
         args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
+
         // USRP recommended: https://files.ettus.com/manual/page_usrp_x3x0_config.html
         if ( 0 != system("sysctl -w net.core.rmem_max=33554432 net.core.wmem_max=33554432") )
-        	LOG_W(HW,"Can't set kernel parameters for X3xx\n");
+          LOG_W(HW,"Can't set kernel parameters for X3xx\n");
       }
 
       s->usrp = uhd::usrp::multi_usrp::make(args);
-      device->priv = s;
 
       if (args.find("clock_source")==std::string::npos) {
-	LOG_I(HW, "Using clock_source == '%d'\n", openair0_cfg[0].clock_source);
-
-	if (openair0_cfg[0].clock_source == internal) {
-	  //in UHD 3.14 we could use
-	  //s->usrp->set_sync_source("clock_source=internal","time_source=internal");
-	  s->usrp->set_time_source("internal");
-	  s->usrp->set_clock_source("internal");
-	}
-	else if (openair0_cfg[0].clock_source == external ) {
-	  //s->usrp->set_sync_source("clock_source=external","time_source=external");
-	  s->usrp->set_time_source("external");
-	  s->usrp->set_clock_source("external");
-	}
-	else if (openair0_cfg[0].clock_source==gpsdo) {
-	  s->usrp->set_clock_source("gpsdo");
-	  s->usrp->set_time_source("gpsdo");
-	}
+        LOG_I(HW, "Using clock_source == '%d'\n", openair0_cfg[0].clock_source);
+
+        if (openair0_cfg[0].clock_source == internal) {
+          //in UHD 3.14 we could use
+          //s->usrp->set_sync_source("clock_source=internal","time_source=internal");
+          s->usrp->set_time_source("internal");
+          s->usrp->set_clock_source("internal");
+        } else if (openair0_cfg[0].clock_source == external ) {
+          //s->usrp->set_sync_source("clock_source=external","time_source=external");
+          s->usrp->set_time_source("external");
+          s->usrp->set_clock_source("external");
+        } else if (openair0_cfg[0].clock_source==gpsdo) {
+          s->usrp->set_clock_source("gpsdo");
+          s->usrp->set_time_source("gpsdo");
+        }
       } else {
-	LOG_W(HW, "clock_source already specified in device arguments! Ignoring command line parameter\n");
+        LOG_W(HW, "clock_source already specified in device arguments! Ignoring command line parameter\n");
       }
 
       if (s->usrp->get_clock_source(0) == "gpsdo") {
-	s->use_gps = 1;
+        s->use_gps = 1;
+
         if (sync_to_gps(device)==EXIT_SUCCESS) {
           LOG_I(HW,"USRP synced with GPS!\n");
-	}
-	else {
+        } else {
           LOG_I(HW,"USRP fails to sync with GPS. Exiting.\n");
           exit(EXIT_FAILURE);
         }
-      }	else if (s->usrp->get_clock_source(0) == "external") {
-	if (check_ref_locked(s,0)) {
-	  LOG_I(HW,"USRP locked to external reference!\n");
-	} else {
-	  LOG_I(HW,"Failed to lock to external reference. Exiting.\n");
-	  exit(EXIT_FAILURE);
-	}
+      } else if (s->usrp->get_clock_source(0) == "external") {
+        if (check_ref_locked(s,0)) {
+          LOG_I(HW,"USRP locked to external reference!\n");
+        } else {
+          LOG_I(HW,"Failed to lock to external reference. Exiting.\n");
+          exit(EXIT_FAILURE);
+        }
       }
-      
-      
+
       if (device->type==USRP_X300_DEV) {
         openair0_cfg[0].rx_gain_calib_table = calib_table_x310;
-#if defined(USRP_REC_PLAY)
         std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; // Bell Labs info
-#endif
         LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate);
 
         switch ((int)openair0_cfg[0].sample_rate) {
@@ -1208,7 +1065,7 @@ extern "C" {
             openair0_cfg[0].tx_bw                 = 80e6;
             openair0_cfg[0].rx_bw                 = 80e6;
             break;
-            
+
           case 61440000:
             // from usrp_time_offset
             //openair0_cfg[0].samples_per_packet    = 2048;
@@ -1264,19 +1121,15 @@ extern "C" {
         if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) {
           openair0_cfg[0].rx_gain_calib_table = calib_table_b210;
           bw_gain_adjust=0;
-#if defined(USRP_REC_PLAY)
           std::cerr << "-- Using calibration table: calib_table_b210" << std::endl; // Bell Labs info
-#endif
         } else {
           openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
           bw_gain_adjust=1;
-#if defined(USRP_REC_PLAY)
           std::cerr << "-- Using calibration table: calib_table_b210_38" << std::endl; // Bell Labs info
-#endif
         }
 
         switch ((int)openair0_cfg[0].sample_rate) {
-	case 46080000:
+          case 46080000:
             s->usrp->set_master_clock_rate(46.08e6);
             //openair0_cfg[0].samples_per_packet    = 1024;
             openair0_cfg[0].tx_sample_advance     = 115;
@@ -1284,7 +1137,7 @@ extern "C" {
             openair0_cfg[0].rx_bw                 = 40e6;
             break;
 
-	case 30720000:
+          case 30720000:
             s->usrp->set_master_clock_rate(30.72e6);
             //openair0_cfg[0].samples_per_packet    = 1024;
             openair0_cfg[0].tx_sample_advance     = 115;
@@ -1373,7 +1226,6 @@ extern "C" {
       // display USRP settings
       LOG_I(HW,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6);
       sleep(1);
-
       // create tx & rx streamer
       uhd::stream_args_t stream_args_rx("sc16", "sc16");
       int samples=openair0_cfg[0].sample_rate;
@@ -1422,21 +1274,12 @@ extern "C" {
         LOG_I(HW,"  Actual TX gain: %f...\n", s->usrp->get_tx_gain(i));
         LOG_I(HW,"  Actual TX bandwidth: %fM...\n", s->usrp->get_tx_bandwidth(i)/1e6);
         LOG_I(HW,"  Actual TX antenna: %s...\n", s->usrp->get_tx_antenna(i).c_str());
-	LOG_I(HW,"  Actual TX packet size: %lu\n",s->tx_stream->get_max_num_samps());
+        LOG_I(HW,"  Actual TX packet size: %lu\n",s->tx_stream->get_max_num_samps());
       }
 
       LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs());
-      device->priv = s;
-      device->trx_start_func = trx_usrp_start;
       device->trx_write_func = trx_usrp_write;
       device->trx_read_func  = trx_usrp_read;
-      device->trx_get_stats_func = trx_usrp_get_stats;
-      device->trx_reset_stats_func = trx_usrp_reset_stats;
-      device->trx_end_func   = trx_usrp_end;
-      device->trx_stop_func  = trx_usrp_stop;
-      device->trx_set_freq_func = trx_usrp_set_freq;
-      device->trx_set_gains_func   = trx_usrp_set_gains;
-      device->openair0_cfg = openair0_cfg;
       device->uhd_set_thread_priority = uhd_set_thread_priority;
       s->sample_rate = openair0_cfg[0].sample_rate;
 
@@ -1450,87 +1293,82 @@ extern "C" {
 
       if(is_equal(s->sample_rate, (double)7.68e6))
         s->tx_forward_nsamps = 50;
-
-
-#if defined(USRP_REC_PLAY)
     }
 
-#endif
-#if defined(USRP_REC_PLAY)
-
-    if (u_sf_mode == 1) { // record mode
-      ms_sample = (iqrec_t *) malloc(u_sf_max * sizeof(iqrec_t));
+    if (s->recplay_mode == RECPLAY_RECORDMODE) { // record mode
+      s->recplay_state->ms_sample = (iqrec_t *) malloc(s->recplay_state->u_sf_max * sizeof(iqrec_t));
 
-      if (ms_sample == NULL) {
+      if (s->recplay_state->ms_sample == NULL) {
         std::cerr<< "Memory allocation failed for subframe record or replay mode." << std::endl;
         exit(-1);
       }
 
-      memset(ms_sample, 0, u_sf_max * BELL_LABS_IQ_BYTES_PER_SF);
-    }
-
-    if (u_sf_mode == 2) {
-      if (use_mmap) {
+      memset(s->recplay_state->ms_sample, 0, s->recplay_state->u_sf_max * BELL_LABS_IQ_BYTES_PER_SF);
+    } else if (s->recplay_mode == RECPLAY_REPLAYMODE) {
+      if (s->recplay_state->use_mmap) {
         // use mmap
-        mmapfd = open(u_sf_filename, O_RDONLY | O_LARGEFILE);
+        s->recplay_state->mmapfd = open(s->recplay_state->u_sf_filename, O_RDONLY | O_LARGEFILE);
 
-        if (mmapfd != 0) {
-          fstat(mmapfd, &sb);
-          std::cerr << "Loading subframes using mmap() from " << u_sf_filename << " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl;
-          ms_sample = (iqrec_t *) mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, mmapfd, 0);
+        if (s->recplay_state->mmapfd != 0) {
+          struct stat sb;
+          fstat(s->recplay_state->mmapfd, &sb);
+          s->recplay_state->mapsize=sb.st_size;
+          std::cerr << "Loading subframes using mmap() from " << s->recplay_state->u_sf_filename << " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl;
+          s->recplay_state->ms_sample = (iqrec_t *) mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->recplay_state->mmapfd, 0);
 
-          if (ms_sample != MAP_FAILED) {
-            nb_samples = (sb.st_size / sizeof(iqrec_t));
-            int aligned = (((unsigned long)ms_sample & 31) == 0)? 1:0;
-            std::cerr<< "Loaded "<< nb_samples << " subframes." << std::endl;
+          if (s->recplay_state->ms_sample != MAP_FAILED) {
+            s->recplay_state->nb_samples = (sb.st_size / sizeof(iqrec_t));
+            int aligned = (((unsigned long)s->recplay_state->ms_sample & 31) == 0)? 1:0;
+            std::cerr<< "Loaded "<< s->recplay_state->nb_samples << " subframes." << std::endl;
 
             if (aligned == 0) {
               std::cerr<< "mmap address is not 32 bytes aligned, exiting." << std::endl;
-              close(mmapfd);
+              close(s->recplay_state->mmapfd);
               exit(-1);
             }
           } else {
             std::cerr << "Cannot mmap file, exiting." << std::endl;
-            close(mmapfd);
+            close(s->recplay_state->mmapfd);
             exit(-1);
           }
         } else {
-          std::cerr << "Cannot open " << u_sf_filename << " , exiting." << std::endl;
+          std::cerr << "Cannot open " << s->recplay_state->u_sf_filename << " , exiting." << std::endl;
           exit(-1);
         }
       } else {
-        iqfd = open(u_sf_filename, O_RDONLY | O_LARGEFILE);
-
-        if (iqfd != 0) {
-          fstat(iqfd, &sb);
-          nb_samples = (sb.st_size / sizeof(iqrec_t));
-          std::cerr << "Loading " << nb_samples << " subframes from " << u_sf_filename
+        s->recplay_state->iqfd = open(s->recplay_state->u_sf_filename, O_RDONLY | O_LARGEFILE);
+
+        if (s->recplay_state->iqfd != 0) {
+          struct stat sb;
+          fstat(s->recplay_state->iqfd, &sb);
+          s->recplay_state->mapsize=sb.st_size;
+          s->recplay_state->nb_samples = (sb.st_size / sizeof(iqrec_t));
+          std::cerr << "Loading " << s->recplay_state->nb_samples << " subframes from " << s->recplay_state->u_sf_filename
                     << " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl;
           // allocate buffer for 1 sample at a time
-          ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t));
+          s->recplay_state->ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t));
 
-          if (ms_sample == NULL) {
+          if (s->recplay_state->ms_sample == NULL) {
             std::cerr<< "Memory allocation failed for individual subframe replay mode." << std::endl;
-            close(iqfd);
+            close(s->recplay_state->iqfd);
             exit(-1);
           }
 
-          memset(ms_sample, 0, sizeof(iqrec_t));
+          memset(s->recplay_state->ms_sample, 0, sizeof(iqrec_t));
 
           // point at beginning of file
-          if (lseek(iqfd, 0, SEEK_SET) == 0) {
+          if (lseek(s->recplay_state->iqfd, 0, SEEK_SET) == 0) {
             std::cerr << "Initial seek at beginning of the file" << std::endl;
           } else {
             std::cerr << "Problem initial seek at beginning of the file" << std::endl;
           }
         } else {
-          std::cerr << "Cannot open " << u_sf_filename << " , exiting." << std::endl;
+          std::cerr << "Cannot open " << s->recplay_state->u_sf_filename << " , exiting." << std::endl;
           exit(-1);
         }
       }
     }
 
-#endif
     return 0;
   }
 
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.h b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.h
index 228d3a5857..d29cf41db2 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.h
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.h
@@ -26,8 +26,6 @@
  * \author: bruno.mongazon-cazavet@nokia-bell-labs.com
  */
 
-#if defined (USRP_REC_PLAY)
-
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -35,6 +33,29 @@
 #include "common/config/config_paramdesc.h"
 #include "common/config/config_userapi.h"
 
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#define CONFIG_OPT_RECPLAY "enable_recplay"
+
+#define  CONFIG_HLP_RECPLAY  "Allow record player"
+#define USRP_SECTION "device.usrp"
+/* inclusion for device configuration */
+/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*                                            command line parameters for USRP record/playback                                                                               */
+/*   optname                     helpstr                paramflags                      XXXptr                  defXXXval                            type           numelt   */
+/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+#define USRP_DEVICE_PARAMS_DESC {  \
+    {CONFIG_OPT_RECPLAY,      CONFIG_HLP_RECPLAY, PARAMFLAG_BOOL,   uptr:&enable_recplay,                 defuintval:0,                    TYPE_UINT,     0} \
+  }
+
+
+/* inclusions for record player */
+#define RECPLAY_DISABLED     0
+#define RECPLAY_RECORDMODE   1
+#define RECPLAY_REPLAYMODE   2
+
 #define BELL_LABS_IQ_HEADER       0xabababababababab
 #define BELL_LABS_IQ_PER_SF       7680 // Up to 5MHz bw for now
 #define BELL_LABS_IQ_BYTES_PER_SF (BELL_LABS_IQ_PER_SF * 4)
@@ -46,13 +67,13 @@ typedef struct {
   unsigned char samples[BELL_LABS_IQ_BYTES_PER_SF]; // iq's for one subframe
 } iqrec_t;
 #define DEF_NB_SF           120000               // default nb of sf or ms to capture (2 minutes at 5MHz)
-#define DEF_SF_FILE         "/home/nokia/iqfile" // default subframes file name
+#define DEF_SF_FILE         "/tmp/iqfile"        // default subframes file name
 #define DEF_SF_DELAY_READ   700                  // default read delay  µs (860=real)
 #define DEF_SF_DELAY_WRITE  15                   // default write delay µs (15=real)
 #define DEF_SF_NB_LOOP      5                    // default nb loops
 
 
-/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
+/* help strings definition for config options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
 #define CONFIG_HLP_SF_FILE      "Path of the file used for subframes record or replay"
 #define CONFIG_HLP_SF_REC       "Record subframes from USRP driver into a file for later replay"
 #define CONFIG_HLP_SF_REP       "Replay subframes into USRP driver from a file"
@@ -61,7 +82,7 @@ typedef struct {
 #define CONFIG_HLP_SF_RDELAY    "Delay in microseconds to read a subframe in replay mode"
 #define CONFIG_HLP_SF_WDELAY    "Delay in microseconds to write a subframe in replay mode"
 
-/* keyword strings for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
+/* keyword strings for config options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
 #define CONFIG_OPT_SF_FILE      "subframes-file"
 #define CONFIG_OPT_SF_REC       "subframes-record"
 #define CONFIG_OPT_SF_REP       "subframes-replay"
@@ -70,20 +91,41 @@ typedef struct {
 #define CONFIG_OPT_SF_RDELAY    "subframes-read-delay"
 #define CONFIG_OPT_SF_WDELAY    "subframes-write-delay"
 
+#define USRP_RECPLAY_SECTION "device.recplay"
 /* For information only - the macro is not usable in C++ */
 /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
 /*                                            command line parameters for USRP record/playback                                                                               */
 /*   optname                     helpstr                paramflags                      XXXptr                  defXXXval                            type           numelt   */
 /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
 #define USRP_RECPLAY_PARAMS_DESC {  \
-{"subframes-file",        	 CONFIG_HLP_SF_FILE,	0,		  strptr:(char **)&u_sf_filename,       defstrval:DEF_SF_FILE, 		   TYPE_STRING,   sizeof(u_sf_filename)}, \
-{"subframes-record",      	 CONFIG_HLP_SF_REC,	PARAMFLAG_BOOL,	  uptr:&u_sf_record,	                defuintval:0,			   TYPE_UINT,	  0}, \
-{"subframes-replay",      	 CONFIG_HLP_SF_REP,	PARAMFLAG_BOOL,	  uptr:&u_sf_replay,	                defuintval:0,			   TYPE_UINT,	  0}, \
-{"subframes-max",              	 CONFIG_HLP_SF_MAX,    	0,                uptr:&u_sf_max,			defintval:DEF_NB_SF,	       	   TYPE_UINT,	  0}, \
-{"subframes-loops",           	 CONFIG_HLP_SF_LOOPS,   0,                uptr:&u_sf_loops,			defintval:DEF_SF_NB_LOOP,	   TYPE_UINT,	  0}, \
-{"subframes-read-delay",         CONFIG_HLP_SF_RDELAY,  0,                uptr:&u_sf_read_delay,	      	defintval:DEF_SF_DELAY_READ,	   TYPE_UINT,	  0}, \
-{"subframes-write-delay",        CONFIG_HLP_SF_WDELAY,  0,                uptr:&u_sf_write_delay,		defintval:DEF_SF_DELAY_WRITE,	   TYPE_UINT,	  0}, \
+    {CONFIG_OPT_SF_FILE,      CONFIG_HLP_SF_FILE, 0,              strptr:(char **)((*recplay_state)->u_sf_filename),       defstrval:DEF_SF_FILE,            TYPE_STRING,   1024}, \
+    {CONFIG_OPT_SF_REC,       CONFIG_HLP_SF_REC,  PARAMFLAG_BOOL,   uptr:&(u_sf_record),                  defuintval:0,                TYPE_UINT,   0}, \
+    {CONFIG_OPT_SF_REP,       CONFIG_HLP_SF_REP,  PARAMFLAG_BOOL,   uptr:&(u_sf_replay),                  defuintval:0,                TYPE_UINT,   0}, \
+    {CONFIG_OPT_SF_MAX,       CONFIG_HLP_SF_MAX,    0,                uptr:&((*recplay_state)->u_sf_max),                 defintval:DEF_NB_SF,             TYPE_UINT,   0}, \
+    {CONFIG_OPT_SF_LOOPS,     CONFIG_HLP_SF_LOOPS,  0,                uptr:&((*recplay_state)->u_sf_loops),                 defintval:DEF_SF_NB_LOOP,        TYPE_UINT,   0}, \
+    {CONFIG_OPT_SF_RDELAY,    CONFIG_HLP_SF_RDELAY, 0,                uptr:&((*recplay_state)->u_sf_read_delay),              defintval:DEF_SF_DELAY_READ,     TYPE_UINT,   0}, \
+    {CONFIG_OPT_SF_WDELAY,    CONFIG_HLP_SF_WDELAY, 0,                uptr:&((*recplay_state)->u_sf_write_delay),           defintval:DEF_SF_DELAY_WRITE,    TYPE_UINT,   0}, \
+  }/*! \brief USRP Configuration and state */
+
+typedef struct {
+  FILE            *pFile;
+  int             mmapfd;
+  int             iqfd;
+  int             use_mmap; // default is to use mmap
+  size_t          mapsize;
+  iqrec_t        *ms_sample;                      // memory for all subframes
+  unsigned int    nb_samples;
+  char            u_sf_filename[1024];              // subframes file path
+  unsigned int    u_sf_max ;                  // max number of recorded subframes
+  unsigned int    u_sf_loops ;           // number of loops in replay mode
+  unsigned int    u_sf_read_delay;   // read delay in replay mode
+  unsigned int    u_sf_write_delay ; // write delay in replay mode
+} recplay_state_t;
+
+
+extern int read_usrpconfig(uint32_t *recplay_mode, recplay_state_t **recplay_state);
+#ifdef __cplusplus
 }
-#endif // BELL_LABS_MUST
+#endif
 #endif // __USRP_LIB_H
 
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib_config.c b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib_config.c
new file mode 100644
index 0000000000..ebf1d61eed
--- /dev/null
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib_config.c
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/** usrp_lib_config.c
+ *
+ * \author: HongliangXU : hong-liang-xu@agilent.com
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/sysinfo.h>
+#include <sys/resource.h>
+#include "common/utils/LOG/log.h"
+#include "assertions.h"
+#include "common_lib.h"
+#include "usrp_lib.h"
+
+
+int read_usrpconfig(uint32_t *recplay_mode, recplay_state_t **recplay_state) {
+unsigned int    u_sf_record = 0;                       // record mode
+unsigned int    u_sf_replay = 0;                       // replay mode
+uint32_t enable_recplay;
+
+    paramdef_t usrp_params[] = USRP_DEVICE_PARAMS_DESC;
+    config_get(usrp_params,sizeof(usrp_params)/sizeof(paramdef_t),USRP_SECTION);
+    if (enable_recplay) {
+      *recplay_state = calloc(sizeof(recplay_state_t),1);      
+      paramdef_t usrp_recplay_params[]=USRP_RECPLAY_PARAMS_DESC ;
+      struct sysinfo systeminfo;
+ 
+    // Use mmap for IQ files for systems with less than 6GB total RAM
+      sysinfo(&systeminfo);
+
+      if (systeminfo.totalram < 6144000000) {
+        (*recplay_state)->use_mmap = 0;
+      } else {
+        (*recplay_state)->use_mmap = 1;
+      }
+
+      memset((*recplay_state)->u_sf_filename, 0, 1024);
+      config_get(usrp_recplay_params,sizeof(usrp_recplay_params)/sizeof(paramdef_t),USRP_RECPLAY_SECTION);
+
+      if (strlen((*recplay_state)->u_sf_filename) == 0) {
+        (void) strcpy((
+        	*recplay_state)->u_sf_filename, DEF_SF_FILE);
+      }
+    } /* record player enabled */
+    if (u_sf_replay == 1) *recplay_mode = RECPLAY_REPLAYMODE;
+
+    if (u_sf_record == 1) *recplay_mode = RECPLAY_RECORDMODE;
+
+
+    return 0;
+  }
\ No newline at end of file
-- 
2.26.2