diff --git a/NOTICE.txt b/NOTICE.txt
index b9eee02ed593c56d2d45c27e9332f23133158cc3..38d493284a64dc5872e2bbf35caf91b46ba0d2e4 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,3 +1,8 @@
+The source code of openairinterface5g is distributed under OAI Public License V1.0. 
+For more details of the license, refer to LICENSE file in the same directory.
+
+However, the source code also contains third party software that is acknowledged here for reference.
+
 Credits for LFDS user space source code located in folder openair2/UTILS/LFDS/liblfds6.1.1/
 http://liblfds.org/.
 Extract from http://liblfds.org/pages/downloads_and_license.html:
diff --git a/README.txt b/README.txt
index cca50342a0d2d982756a20a413187f0315a0aab7..04d02bf9c71c2577cadb6bc829169b9c2f4bca93 100644
--- a/README.txt
+++ b/README.txt
@@ -1,36 +1,41 @@
-OpenAirInterface is under OpenAirInterface Software Alliance license.
-├── http://www.openairinterface.org/?page_id=101
-├── http://www.openairinterface.org/?page_id=698
-
-The OpenAirInterface (OAI) software is composed of the following parts: 
-
-openairinterface5g
-├── cmake_targets: build utilities to compile (simulation, emulation and real-time platforms), and generated build files
-├── common : some common OAI utilities, other tools can be found at openair2/UTILS
-├── LICENSE
-├── maketags : script to generate emacs tags
-├── openair1 : 3GPP LTE Rel-10 PHY layer + PHY RF simulation and a subset of Rel 12 Features.
-├── openair2 :3GPP LTE Rel-10 RLC/MAC/PDCP/RRC/X2AP implementation. 
-    ├── LAYER2/RLC/ with the following subdirectories: UM_v9.3.0, TM_v9.3.0, and AM_v9.3.0. 
-    ├── LAYER2/PDCP/PDCP_v10.1.0. 
-    ├── RRC/LITE
-    ├── PHY_INTERFACE
-    ├── X2AP
-    ├── ENB_APP 
-├── openair3: 3GPP LTE Rel10 for S1AP, NAS GTPV1-U for both ENB and UE.
-    ├── GTPV1-U
-    ├── NAS 
-    ├── S1AP
-    ├── SCTP
-    ├── SECU
-    ├── UDP
-└── targets: top level wrapper for unitary simulation for PHY channels, system-level emulation (eNB-UE with and without S1), and realtime eNB and UE and RRH GW.
-
-
-RELEASE NOTES:
-
-v0.1 -> Last stable commit on develop branch before enhancement-10-harmony
-v0.2 -> Merge of enhancement-10-harmony to include NGFI RRH + New Interface for RF/BBU
-v0.3 -> Last stable commit on develop branch before the merge of feature-131-new-license. This is the last commit with GPL License
-v0.4 -> Merge of feature-131-new-license. It closes issue#131 and changes the license to OAI Public License V1.0
-v0.5 -> Merge of enhancement-10-harmony-lts. It includes fixes for Ubuntu 16.04 support
+OpenAirInterface is under OpenAirInterface Software Alliance license.
+├── http://www.openairinterface.org/?page_id=101
+├── http://www.openairinterface.org/?page_id=698
+
+It is distributed under OAI Public License V1.0. 
+The license information is distributed under LICENSE file in the same directory.
+Please see NOTICE.txt for third party software that is included in the sources.
+
+The OpenAirInterface (OAI) software is composed of the following parts: 
+
+openairinterface5g
+├── cmake_targets: build utilities to compile (simulation, emulation and real-time platforms), and generated build files
+├── common : some common OAI utilities, other tools can be found at openair2/UTILS
+├── LICENSE
+├── maketags : script to generate emacs tags
+├── openair1 : 3GPP LTE Rel-10 PHY layer + PHY RF simulation and a subset of Rel 12 Features.
+├── openair2 :3GPP LTE Rel-10 RLC/MAC/PDCP/RRC/X2AP implementation. 
+    ├── LAYER2/RLC/ with the following subdirectories: UM_v9.3.0, TM_v9.3.0, and AM_v9.3.0. 
+    ├── LAYER2/PDCP/PDCP_v10.1.0. 
+    ├── RRC/LITE
+    ├── PHY_INTERFACE
+    ├── X2AP
+    ├── ENB_APP 
+├── openair3: 3GPP LTE Rel10 for S1AP, NAS GTPV1-U for both ENB and UE.
+    ├── GTPV1-U
+    ├── NAS 
+    ├── S1AP
+    ├── SCTP
+    ├── SECU
+    ├── UDP
+└── targets: top level wrapper for unitary simulation for PHY channels, system-level emulation (eNB-UE with and without S1), and realtime eNB and UE and RRH GW.
+
+
+RELEASE NOTES:
+
+v0.1 -> Last stable commit on develop branch before enhancement-10-harmony
+v0.2 -> Merge of enhancement-10-harmony to include NGFI RRH + New Interface for RF/BBU
+v0.3 -> Last stable commit on develop branch before the merge of feature-131-new-license. This is the last commit with GPL License
+v0.4 -> Merge of feature-131-new-license. It closes issue#131 and changes the license to OAI Public License V1.0
+v0.5 -> Merge of enhancement-10-harmony-lts. It includes fixes for Ubuntu 16.04 support
+v0.5.1 -> Merge of bugfix-137-uplink-fixes. It includes stablity fixes for eNB
diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py
index 1dfd67b682e14a797ffa3c691b0a8e2b5602aaff..796235a77f767f01932396f9fc1366f1cf28bb30 100755
--- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py
+++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py
@@ -37,6 +37,8 @@ import math #from time import clock
 import xml.etree.ElementTree as ET
 import re
 
+from colorama import Fore, Back, Style
+
 import numpy as np
 
 import log
@@ -167,7 +169,7 @@ def sftp_module (username, password, hostname, ports, paramList,logfile):
    #paramiko logfile path should not be changed with multiple calls. The logs seem to in first file regardless
    error = ""
    #The lines below are outside exception loop to be sure to terminate the test case if the network connectivity goes down or there is authentication failure
-   transport = paramiko.Transport(hostname, ports)
+   transport = paramiko.Transport((hostname, ports))
    transport.connect(username = username, password = password)
    sftp = paramiko.SFTPClient.from_transport(transport)
    #  index =0 
@@ -1042,6 +1044,609 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
   write_file(xmlFile, xml, mode="w")
 
 
+
+
+# \brief handler for executing test cases (lte-softmodem-noS1)
+# \param testcase name of testcase
+# \param oldprogramList list of programs which must be terminated before running a test case
+# \param logdirOAI5GRepo directory on remote machine which has openairinterface5g repo installed
+# \param logdirOpenaircnRepo directory on remote machine which has openair-cn repo installed
+# \param MachineList list of all machines on which test cases can be run
+# \param user username with which to login
+# \param password password with which to login
+# \param CleanupAluLteBox string that contains commands to stop ALU Bell Labs LTEBox (specified in test_case_list.xml)
+# \param ExmimoRfStop command to stop EXMIMO Card
+# \param nruns_lte-softmodem global parameter to override number of runs (nruns) within the test case
+def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, user, password, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem, timeout_cmd):
+  #We ignore the password sent to this function for secuirity reasons for password present in log files
+  #It is recommended to add a line in /etc/sudoers that looks something like below. The line below will run sudo without password prompt
+  # your_user_name ALL=(ALL:ALL) NOPASSWD: ALL
+
+  indent="\t"
+  threads=[]
+
+  #
+  # Test case parameters
+  # -----------------------------------------------------------------------------
+  testcase_verdict = 'PASS'
+  testcase_time_start = datetime.datetime.now()
+  testcase_name   = testcase.get('id')
+  testcase_class  = testcase.findtext('class',default='')
+  testcase_desc   = testcase.findtext('desc',default='')
+  if timeout_cmd == '':
+     timeout_cmd = testcase.findtext('TimeOut_cmd',default='')
+  timeout_cmd = int(float(timeout_cmd))
+  timeout_thread = timeout_cmd + 60    #Timeout_thread is more than that of cmd to have room for compilation time, etc
+  if nruns_lte_softmodem == '':
+    nruns = testcase.findtext('nruns',default='')
+  else:
+    nruns = nruns_lte_softmodem
+  nruns = int(float(nruns))
+  tags = testcase.findtext('tags',default='')
+
+  max_ntries = testcase.findtext('max_ntries',default='')
+  if max_ntries :
+    max_ntries = int(float(max_ntries))
+  else :
+    max_ntries = nruns
+
+  print( indent + "> testcase time start     : " + str(testcase_time_start) )
+  print( indent + "> testcase class          : " + testcase_class )
+  print( indent + "> testcase description    : " + testcase_desc )
+  print( indent + "> testcase timeout        : " + str(timeout_cmd) )
+  print( indent + "> testcase thread timeout : " + str(timeout_thread) )
+  print( indent + "> number of runs          : " + str(nruns) )
+  print( indent + "> number of max tries     : " + str(max_ntries) )  
+  print( indent + "> testcase tags           : " + tags )
+
+  logdir_local_testcase = openairdir_local + '/cmake_targets/autotests/log/'+ testcasename
+  logdir_eNB_testcase   = logdirOAI5GRepo +'/cmake_targets/autotests/log/'+ testcasename 
+  logdir_UE_testcase    = logdirOAI5GRepo +'/cmake_targets/autotests/log/'+ testcasename 
+
+  #
+  # Local checks for test cases 
+  # -----------------------------------------------
+  
+  # Logging directory
+  if (not os.path.exists(logdir_local_testcase)):
+    os.system('mkdir -p ' + logdir_local_testcase)
+
+  #
+  # REMOTE MACHINE COMPILATION
+  # ------------------------------------------------
+  
+  eNBMachine = testcase.findtext('eNB',default='')
+  eNB_config_file = testcase.findtext('eNB_config_file',default='')
+  eNB_compile_prog = testcase.findtext('eNB_compile_prog',default='')
+  eNB_compile_prog_args = testcase.findtext('eNB_compile_prog_args',default='')
+
+  logfile_compile_eNB           = logdir_eNB_testcase + '/eNB_compile.log'
+  logfile_task_eNB_compile_out  = logdir_eNB_testcase + '/eNB_task_compile_out.log'
+  logfile_task_eNB_compile      = logdir_local_testcase + '/eNB_task_compile.log'
+
+  # Check that machine is in test setup machine list
+  print( Fore.WHITE + indent + "> testcase eNB machine    :"),
+  if (eNBMachine not in MachineList):
+    print( Fore.RED + eNBMachine + " not in test setup machine list")
+    testcase_verdict = 'INCON'
+  else :
+    print eNBMachine,
+    # get machine description
+    eNBMachineDesc = MachineDescDic[eNBMachine]                   
+    index_eNBMachine = MachineList.index(eNBMachine)
+    # check that openairinterface is installed on machine
+    oai_eNB = openair('localdomain', eNBMachine)
+    oai_eNB.connect(user, password)
+    cmd = 'cd ' + logdirOAI5GRepo + '; source oaienv ; env|grep --color=never OPENAIR'
+    res= oai_eNB.send_recv(cmd)
+    m = re.search('OPENAIR_HOME', res, re.DOTALL)
+    if  m:  
+      print
+      # Create testcase directory on remote eNB
+      cmd = 'rm -fr ' + logdir_eNB_testcase + ' ; mkdir -p ' + logdir_eNB_testcase
+      result = oai_eNB.send_recv(cmd)
+    
+      # Check if we need to compile lte-softmodem-noS1 on remote machine
+      eNB_compile_cmd = eNB_compile_prog + ' '+ eNB_compile_prog_args
+      if  ('last_compile_prog' in eNBMachineDesc) and eNBMachineDesc['last_compile_prog'] == eNB_compile_cmd:
+        print( Fore.WHITE + indent + "> eNB machine compilation : skipped -> "+eNB_compile_cmd )
+      else:
+        print( Fore.WHITE + indent + "> eNB machine compilation : triggered -> "+eNB_compile_cmd )
+        eNBMachineDesc['last_compile_prog'] = eNB_compile_prog + ' '+ eNB_compile_prog_args        # if last compilation is the same do not compile again
+        task_eNB_compile = ' ( uname -a ; date \n'
+        task_eNB_compile = task_eNB_compile + 'cd ' + logdirOAI5GRepo + ' ; source oaienv ; source cmake_targets/tools/build_helper \n'
+        task_eNB_compile = task_eNB_compile + 'env |grep OPENAIR  \n'
+        task_eNB_compile = task_eNB_compile + update_config_file(oai_eNB, eNB_config_file, logdirOAI5GRepo, '$OPENAIR_DIR/cmake_targets/autotests/tools/search_repl.py') + '\n'
+        if eNB_compile_cmd != "":
+          task_eNB_compile  = task_eNB_compile +  ' ( ' + eNB_compile_cmd + ' ) > ' + logfile_compile_eNB + ' 2>&1 \n'
+        task_eNB_compile =  task_eNB_compile + ' date ) > ' + logfile_task_eNB_compile_out + ' 2>&1  '
+        write_file(logfile_task_eNB_compile, task_eNB_compile, mode="w")
+
+
+        thread_eNB = oaiThread(1, "eNB_thread_compile", eNBMachine, user, password , task_eNB_compile, False, timeout_thread)
+        threads.append(thread_eNB)
+        thread_eNB.start()
+
+    else:
+      print( Fore.RED + " -> OAI5G not properly setup ! please check REMOTE MACHINE PREPARATION step")
+      testcase_verdict = 'INCON'
+
+
+  UEMachine = testcase.findtext('UE',default='')
+  UE_config_file = testcase.findtext('UE_config_file',default='')
+  UE_compile_prog = testcase.findtext('UE_compile_prog',default='')
+  UE_compile_prog_args = testcase.findtext('UE_compile_prog_args',default='')
+
+  logfile_compile_UE           = logdir_UE_testcase + '/UE_compile.log'
+  logfile_task_UE_compile_out  = logdir_UE_testcase + '/UE_task_compile_out.log'
+  logfile_task_UE_compile      = logdir_local_testcase + '/UE_task_compile.log'
+
+  # Check that machine is in test setup machine list
+  print( Fore.WHITE + indent + "> testcase UE machine     :"),
+  if (UEMachine not in MachineList):
+    print( Fore.RED + UEMachine + " not in test setup machine list")
+    testcase_verdict = 'INCON'
+  else :
+    print UEMachine,
+    # get machine description
+    UEMachineDesc = MachineDescDic[UEMachine]                   
+    index_UEMachine = MachineList.index(UEMachine)
+    # check that openairinterface is installed on machine
+    oai_UE = openair('localdomain', UEMachine)
+    oai_UE.connect(user, password)
+    cmd = 'cd ' + logdirOAI5GRepo + '; source oaienv ; env|grep --color=never OPENAIR'
+    res= oai_UE.send_recv(cmd)
+    m = re.search('OPENAIR_HOME', res, re.DOTALL)
+    if  m:  
+      print
+      # Create testcase directory on remote UE
+      cmd = 'rm -fr ' + logdir_UE_testcase + ' ; mkdir -p ' + logdir_UE_testcase
+      result = oai_UE.send_recv(cmd)
+    
+      # Check if we need to compile lte-softmodem-noS1 on remote machine
+      UE_compile_cmd = UE_compile_prog + ' '+ UE_compile_prog_args
+      if  ('last_compile_prog' in UEMachineDesc) and UEMachineDesc['last_compile_prog'] == UE_compile_cmd:
+        print( Fore.WHITE + indent + "> UE machine compilation  : skipped -> "+UE_compile_cmd )
+      else:
+        print( Fore.WHITE + indent + "> UE machine compilation  : triggered -> "+UE_compile_cmd )
+        UEMachineDesc['last_compile_prog'] = UE_compile_prog + ' '+ UE_compile_prog_args
+        task_UE_compile = ' ( uname -a ; date \n'
+        task_UE_compile = task_UE_compile + 'cd ' + logdirOAI5GRepo + ' ; source oaienv ; source cmake_targets/tools/build_helper \n'
+        task_UE_compile = task_UE_compile + 'env |grep OPENAIR  \n'
+        task_UE_compile = task_UE_compile + update_config_file(oai_UE, UE_config_file, logdirOAI5GRepo, '$OPENAIR_DIR/cmake_targets/autotests/tools/search_repl.py') + '\n'
+        if UE_compile_cmd != "":
+          task_UE_compile  = task_UE_compile +  ' ( ' + UE_compile_cmd + ' ) > ' + logfile_compile_UE + ' 2>&1 \n'
+        task_UE_compile =  task_UE_compile + ' date ) > ' + logfile_task_UE_compile_out + ' 2>&1  '
+        write_file(logfile_task_UE_compile, task_UE_compile, mode="w")
+
+        thread_UE = oaiThread(2, "UE_thread_compile", UEMachine, user, password , task_UE_compile, False, timeout_thread)
+        threads.append(thread_UE)
+        thread_UE.start()
+
+    else:
+      print( Fore.RED + " -> OAI5G not properly setup ! please check REMOTE MACHINE PREPARATION step")
+      testcase_verdict = 'INCON'
+
+
+
+
+
+
+  # Wait for Compilation thread to terminate
+  #-----------------------------------------
+  for t in threads:
+    t.join()
+
+    # TODO check that compilation is succeed
+    
+    #first we compile all the programs
+#    thread_UE = oaiThread(3, "UE_thread", UEMachine, user, password  , task_UE_compile, False, timeout_thread) 
+#    threads.append(thread_UE)
+#    thread_UE.start()
+    
+
+
+
+
+#  index_UEMachine = MachineList.index(UEMachine)
+#  oai_UE = openair('localdomain', UEMachine)
+#  oai_UE.connect(user, password)
+#  res = oai_UE.send_recv(cmd)
+#  res = oai_eNB.send_recv(cmd)
+
+
+
+  #
+  # RUN LOOP
+  # ------------------------------------------------
+  if testcase_verdict != 'PASS':      # if something went wrong to not run test cases
+    max_ntries=0
+
+  runs_results = []
+  nb_runs       = 0
+  nb_run_pass   = 0
+  nb_run_failed = 0
+  nb_run_inc    = 0
+  nb_run_skip   = 0
+
+  nb_seg_fault  = 0
+
+  for run in range(0,max_ntries):
+
+    if nruns == nb_run_pass + nb_run_failed:
+      break
+
+    nb_runs   += 1
+
+    #
+    # RUN initialization
+    # ----------------------------------------------------
+    print (Fore.WHITE + indent + "> RUN_"+str(run).zfill(2)+"                  : " ),
+ 
+    sys.stdout.flush()
+
+    run_start_time=datetime.datetime.now()
+
+    logdir_local_run = openairdir_local + '/cmake_targets/autotests/log/'+ testcasename + '/run_' + str(run)
+    logdir_eNB_run   = logdirOAI5GRepo +'/cmake_targets/autotests/log/'  + testcasename + '/run_' + str(run)
+    logdir_UE_run    = logdirOAI5GRepo +'/cmake_targets/autotests/log/'  + testcasename + '/run_' + str(run)
+
+    cmd = 'rm -fr ' + logdir_eNB_run + ' ; mkdir -p ' + logdir_eNB_run
+    result = oai_eNB.send_recv(cmd)
+    cmd = 'rm -fr ' + logdir_UE_run + ' ; mkdir -p ' +  logdir_UE_run
+    result = oai_UE.send_recv(cmd)
+    cmd = ' rm -fr ' + logdir_local_run + ' ; mkdir -p ' + logdir_local_run
+    result = os.system(cmd)
+
+
+    #
+    # RUN parametrization
+    # ----------------------------------------------------
+    eNB_pre_exec          = testcase.findtext('eNB_pre_exec',default='')
+    eNB_pre_exec_args     = testcase.findtext('eNB_pre_exec_args',default='')
+    eNB_main_exec         = testcase.findtext('eNB_main_exec',default='')
+    eNB_main_exec_args    = testcase.findtext('eNB_main_exec_args',default='')
+    eNB_traffic_exec      = testcase.findtext('eNB_traffic_exec',default='')
+    eNB_traffic_exec_args = testcase.findtext('eNB_traffic_exec_args',default='')
+    eNB_terminate_missing_procs = testcase.findtext('eNB_terminate_missing_procs',default='True')
+
+    logfile_exec_eNB      = logdir_eNB_run   + '/eNB_exec'     + '_' + str(run) + '_.log'
+    logfile_pre_exec_eNB  = logdir_eNB_run   + '/eNB_pre_exec' + '_' + str(run) + '_.log'
+    logfile_task_eNB_out  = logdir_eNB_run   + '/eNB_task_out' + '_' + str(run) + '_.log'
+    logfile_traffic_eNB   = logdir_eNB_run   + '/eNB_traffic'  + '_' + str(run) + '_.log'
+    logfile_task_eNB      = logdir_local_run + '/eNB_task'     + '_' + str(run) + '_.log'
+
+    task_eNB = ' ( uname -a ; date \n'
+    task_eNB = task_eNB + 'cd ' + logdirOAI5GRepo + ' ; source oaienv ; source cmake_targets/tools/build_helper \n'
+    task_eNB = task_eNB + 'env |grep OPENAIR  \n' + 'array_exec_pid=() \n'
+    if eNB_pre_exec != "":
+       task_eNB  = task_eNB +  ' ( date; ' + eNB_pre_exec + ' '+ eNB_pre_exec_args + ' ) > ' + logfile_pre_exec_eNB + ' 2>&1 \n'
+    if eNB_main_exec != "":
+       task_eNB = task_eNB + ' ( date; ' + addsudo(eNB_main_exec + ' ' + eNB_main_exec_args, '') + ' ) > ' + logfile_exec_eNB + ' 2>&1 & \n'
+       task_eNB = task_eNB + 'array_exec_pid+=($!) \n'
+       task_eNB = task_eNB + 'echo eNB_main_exec PID = $! \n'
+    if eNB_traffic_exec != "":
+       cmd_traffic = eNB_traffic_exec + ' ' + eNB_traffic_exec_args
+       if cmd_traffic.find('-c') >= 0:
+          cmd_traffic = cmd_traffic + ' -t ' + str(timeout_cmd - 80)
+       task_eNB = task_eNB + ' (date;  ' + cmd_traffic + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n'
+       task_eNB = task_eNB + 'array_exec_pid+=($!) \n'
+       task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n'
+    #terminate the eNB test case after timeout_cmd seconds
+    task_eNB  = task_eNB + finalize_deploy_script (timeout_cmd, eNB_terminate_missing_procs) + ' \n'
+    #task_eNB  = task_eNB + 'sleep ' +  str(timeout_cmd) + ' \n'
+    task_eNB  = task_eNB + 'handle_ctrl_c' + '\n' 
+    task_eNB  = task_eNB + ' ) > ' + logfile_task_eNB_out + ' 2>&1  '
+    write_file(logfile_task_eNB, task_eNB, mode="w")
+
+
+    UE_pre_exec                 = testcase.findtext('UE_pre_exec',default='')
+    UE_pre_exec_args            = testcase.findtext('UE_pre_exec_args',default='')
+    UE_main_exec                = testcase.findtext('UE_main_exec',default='')
+    UE_main_exec_args           = testcase.findtext('UE_main_exec_args',default='')
+    UE_traffic_exec             = testcase.findtext('UE_traffic_exec',default='')
+    UE_traffic_exec_args        = testcase.findtext('UE_traffic_exec_args',default='')
+    UE_terminate_missing_procs  = testcase.findtext('UE_terminate_missing_procs',default='True')
+    UE_search_expr_true         = testcase.findtext('UE_search_expr_true','')
+
+    logfile_exec_UE     = logdir_UE_run + '/UE_exec'     + '_' + str(run) + '_.log'
+    logfile_pre_exec_UE = logdir_UE_run + '/UE_pre_exec' + '_' + str(run) + '_.log'
+    logfile_task_UE_out = logdir_UE_run + '/UE_task_out' + '_' + str(run) + '_.log'
+    logfile_traffic_UE  = logdir_UE_run + '/UE_traffic'  + '_' + str(run) + '_.log'   
+    logfile_task_UE     = logdir_local_run + '/UE_task'  + '_' + str(run) + '_.log'
+  
+
+    task_UE = ' ( uname -a ; date \n'
+    task_UE = task_UE + 'array_exec_pid=()' + '\n'
+    task_UE = task_UE + 'cd ' + logdirOAI5GRepo + '\n'  
+    task_UE = task_UE + 'source oaienv \n'
+    task_UE = task_UE + 'source cmake_targets/tools/build_helper \n'
+    task_UE = task_UE + 'env |grep OPENAIR  \n'
+    if UE_pre_exec != "":
+      task_UE  = task_UE +  ' ( date; ' + UE_pre_exec + ' '+ UE_pre_exec_args + ' ) > ' + logfile_pre_exec_UE + ' 2>&1 \n'
+    if UE_main_exec != "":
+      task_UE = task_UE + ' ( date;  ' + addsudo(UE_main_exec + ' ' + UE_main_exec_args, '')  + ' ) > ' + logfile_exec_UE + ' 2>&1 & \n'
+      task_UE = task_UE + 'array_exec_pid+=($!) \n'
+      task_UE = task_UE + 'echo UE_main_exec PID = $! \n'
+    if UE_traffic_exec != "":
+       cmd_traffic = UE_traffic_exec + ' ' + UE_traffic_exec_args
+       if cmd_traffic.find('-c') >= 0:
+          cmd_traffic = cmd_traffic + ' -t ' + str(timeout_cmd - 60)
+       task_UE = task_UE + ' ( date;  ' + cmd_traffic + ' ) >' + logfile_traffic_UE + ' 2>&1 & \n'
+       task_UE = task_UE + 'array_exec_pid+=($!) \n'
+       task_UE = task_UE + 'echo UE_traffic_exec PID = $! \n'
+    #terminate the UE test case after timeout_cmd seconds
+    task_UE  = task_UE + finalize_deploy_script (timeout_cmd, UE_terminate_missing_procs) + ' \n'
+    #task_UE  = task_UE + 'sleep ' +  str(timeout_cmd) + ' \n'
+    task_UE  = task_UE + 'handle_ctrl_c' + '\n' 
+    task_UE  = task_UE + ' ) > ' + logfile_task_UE_out + ' 2>&1 '
+    write_file(logfile_task_UE, task_UE, mode="w")
+    #task_UE = 'echo \" ' + task_UE + '\" > ' + logfile_script_UE + ' 2>&1 ; ' + task_UE
+
+
+
+
+
+
+
+    #
+    # RUN work
+    # ----------------------------------------------------
+    thread_eNB = oaiThread(1, "eNB_thread", eNBMachine, user, password , task_eNB, False, timeout_thread)
+    thread_UE = oaiThread(2, "UE_thread", UEMachine, user, password  , task_UE, False, timeout_thread) 
+    threads=[]
+    threads.append(thread_eNB)
+    threads.append(thread_UE)
+    thread_eNB.start()
+    thread_UE.start()
+    for t in threads:
+       t.join()
+
+    #
+    # 
+    #-----------------------------------------------------
+    cleanOldProgramsAllMachines([oai_eNB, oai_UE] , oldprogramList, CleanUpAluLteBox, ExmimoRfStop, [logdir_eNB_run, logdir_UE_run], logdirOAI5GRepo)       
+
+    SSHSessionWrapper(eNBMachine, user, None, password, logdir_eNB_run, logdir_local_testcase, "get_all")
+   #print "Copying files from UEMachine : " + UEMachine + "logdir_UE = " + logdir_UE
+    SSHSessionWrapper(UEMachine, user, None, password, logdir_UE_run, logdir_local_testcase, "get_all")
+
+    metric_checks_flag = 1
+
+    fname = logdir_local_run+ '/UE_exec'     + '_' + str(run) + '_.log'
+    cell_synch_status = analyser.check_cell_synchro(fname)
+    if cell_synch_status == 'CELL_SYNCH':
+      print '!!!!!!!!!!!!!!  Cell synchronized !!!!!!!!!!!'
+    else :
+      print '!!!!!!!!!!!!!!  Cell NOT  NOT synchronized !!!!!!!!!!!'
+      metric_checks_flag = 0
+
+    ue_seg_fault_status = analyser.check_exec_seg_fault(fname)
+    if ue_seg_fault_status == 'SEG_FAULT' :
+      nb_seg_fault += 1
+
+    #
+    # Check metrics
+    #----------------------------------------------------
+    runs_metrics = []
+    run_traffic = []
+
+    if metric_checks_flag :
+      verdict = 'PASS'
+
+      # UE side metrics
+      metricList=testcase.findall('UE_metric')
+      for metric in metricList:
+        metric_def = {}
+        metric_def['id']            = metric.get('id') 
+        metric_def['description']   = metric.get('description') 
+        metric_def['regex']         = metric.get('regex') 
+        metric_def['unit_of_meas']  = metric.get('unit_of_meas') 
+        metric_def['pass_fail_stat']= metric.get('pass_fail_stat') 
+        metric_min_lim = metric.get('min_limit')
+        if metric_min_lim:
+          metric_def['min_limit']     = float(metric_min_lim)
+        metric_max_lim = metric.get('max_limit')
+        if metric_max_lim:
+          metric_def['max_limit']     = float(metric_max_lim)
+
+        fname = logdir_local_run+ '/UE_exec'     + '_' + str(run) + '_.log'
+
+        args = {'metric' : metric_def,
+                'file' : fname }
+    
+        metric_extracted = analyser.do_extract_metrics(args)
+
+        print "\t  > Metric "+metric_def['id']+" :"
+        print "\t\t> min       = "+ str( metric_extracted['metric_min'] )
+        print "\t\t> min_index = "+ str( metric_extracted['metric_min_index'] )
+        print "\t\t> max       = "+ str( metric_extracted['metric_max'] )
+        print "\t\t> max_index = "+ str( metric_extracted['metric_max_index'] )
+        print "\t\t> mean      = "+ str( metric_extracted['metric_mean'] )
+        print "\t\t> median    = "+ str( metric_extracted['metric_median'] )      
+
+        verdict = analyser.do_check_verdict(metric_def, metric_extracted)
+   
+        metric_fig = logdir_local_run+ '/UE_metric_'+ metric_def['id']+'_' + str(run) + '_.png'
+        analyser.do_img_metrics(metric_def, metric_extracted, metric_fig)
+
+
+        metric_fig_report = '../log/'+ testcasename + '/run_' + str(run) + '/UE_metric_'+ metric_def['id']+'_' + str(run) + '_.png'
+
+        run_metrics = dict( metric_id       = metric_def['id'],
+                            metric_desc     = metric_def['description'],
+                            metric_uom      = metric_def['unit_of_meas'],
+                            metric_min      = metric_extracted['metric_min'],
+                            metric_min_index= metric_extracted['metric_min_index'],
+                            metric_max      = metric_extracted['metric_max'],
+                            metric_max_index= metric_extracted['metric_max_index'],
+                            metric_mean     = metric_extracted['metric_mean'],
+                            metric_median   = metric_extracted['metric_median'],
+                            metric_fig      = metric_fig_report)
+
+        if metric_def['pass_fail_stat'] :
+          run_metrics['pass_fail_stat'] = metric_def['pass_fail_stat']
+        if metric_min_lim :
+          run_metrics['pass_fail_min_limit'] = metric_def['min_limit']
+        if metric_max_lim :
+          run_metrics['pass_fail_max_limit'] = metric_def['max_limit']
+
+        runs_metrics.append(run_metrics)
+
+      # Traffic analysis
+      if UE_traffic_exec != "":
+
+        fname = logdir_local_run+ '/UE_traffic'     + '_' + str(run) + '_.log'
+        args = {'file' : fname }
+        traffic_metrics = analyser.do_extract_traffic_metrics(args)
+        traffic_fig = logdir_local_run+ '/UE_traffic'+'_' + str(run) + '_.png'
+        analyser.do_img_traffic(traffic_metrics, traffic_fig)
+
+        traffic_fig_report= '../log/'+ testcasename + '/run_' + str(run) + '/UE_traffic'+'_' + str(run) + '_.png'
+
+        dur_pass_fail_crit = 'none'
+        if traffic_metrics['traffic_count'] == 0 :
+          verdict = 'FAIL'
+        elif UE_search_expr_true != "":
+          traffic_duration_limit = float(UE_search_expr_true)
+          dur_pass_fail_crit = str(traffic_duration_limit)
+  #        print 'traffic_duration_limit = '+str(traffic_duration_limit)
+  #        print 'traffic_metrics[interval_stop_max] = '+str(traffic_metrics['interval_stop_max'])
+          if traffic_metrics['interval_stop_max'] < traffic_duration_limit :
+            verdict = 'FAIL'
+
+
+        run_traffic = dict( traffic_count   = traffic_metrics['traffic_count'],
+                            bw_min          = traffic_metrics['bw_min'],
+                            bw_max          = traffic_metrics['bw_max'],
+                            bw_mean         = traffic_metrics['bw_mean'],
+                            bw_median       = traffic_metrics['bw_median'],
+                            jitter_min      = traffic_metrics['jitter_min'],
+                            jitter_max      = traffic_metrics['jitter_max'],
+                            jitter_mean     = traffic_metrics['jitter_mean'],
+                            jitter_median   = traffic_metrics['jitter_median'],
+                            rl_min          = traffic_metrics['rl_min'],
+                            rl_max          = traffic_metrics['rl_max'],
+                            rl_mean         = traffic_metrics['rl_mean'],
+                            rl_median       = traffic_metrics['rl_median'],
+                            iperf_duration  = traffic_metrics['interval_stop_max'],
+                            dur_pass_fail_crit = dur_pass_fail_crit,
+                            traffic_fig     = traffic_fig_report )
+      else:
+        run_traffic = dict( traffic_count   = 0)
+
+    else :
+      verdict = 'SKIP'
+
+
+
+    #
+    # RUN verdict and finalization
+    # ----------------------------------------------------
+    run_stop_time=datetime.datetime.now()
+    run_duration = run_stop_time-run_start_time
+#   print (Fore.WHITE + ("duration=" :"),
+    print (Fore.WHITE + indent + "> RUN duration            : "+ str(run_duration) +"s" )
+
+    print (Fore.WHITE + indent + "> RUN verdict             :"),
+
+    if verdict == 'PASS':
+      nb_run_pass   += 1
+      print ( Fore.GREEN + verdict)
+    elif verdict == 'FAIL':
+      nb_run_failed += 1
+      testcase_verdict = 'FAIL'
+      print ( Fore.RED + verdict)
+    elif verdict == 'SKIP':
+      nb_run_skip += 1
+      print ( Fore.YELLOW + verdict)
+    else:
+      nb_run_inc    += 1
+      if testcase_verdict == 'PASS' : testcase_verdict = 'INCON'
+      print (Fore.YELLOW+'INCONCLUSIVE')
+
+    run_results = dict( run_id=str(run),
+                        run_start_time = run_start_time,
+                        run_stop_time  = run_stop_time ,
+                        run_verdict    = verdict,
+                        ue_seg_fault_status = ue_seg_fault_status,
+                        run_duration   = run_duration,
+                        runs_metrics   = runs_metrics,
+                        run_traffic   = run_traffic)
+    runs_results.append(run_results)
+
+  # END RUN LOOP
+  #----------------------------------------------------
+
+  # Test case duration
+  # ----------------------------------  
+  testcase_time_stop = datetime.datetime.now()
+  print(Fore.WHITE + indent + "> testcase time stop      : " + str(testcase_time_start) ),
+  print " -> TestCase duration = "+str(testcase_time_stop - testcase_time_start)
+
+  # Save remote log files
+  # -----------------------------------  
+  #Now we change the permissions of the logfiles to avoid some of them being with root permissions
+  cmd = 'sudo -E chown -R ' + user + ' ' + logdir_eNB_testcase
+  res= oai_eNB.send_recv(cmd)
+  cmd = 'sudo -E chown -R ' + user + ' ' +  logdir_UE_testcase
+  res= oai_UE.send_recv(cmd)
+
+  # Save remote log files on MTC
+  #print "Copying files from eNBMachine " + eNBMachine + "logdir_eNB = " + logdir_eNB
+  SSHSessionWrapper(eNBMachine, user, None, password, logdir_eNB_testcase, openairdir_local + '/cmake_targets/autotests/log/', "get_all")
+  #print "Copying files from UEMachine : " + UEMachine + "logdir_UE = " + logdir_UE
+  SSHSessionWrapper(UEMachine, user, None, password, logdir_UE_testcase, openairdir_local + '/cmake_targets/autotests/log/', "get_all")
+
+  oai_eNB.disconnect()
+  oai_UE.disconnect()
+
+  # Set test case final verdict
+  # -----------------------------------
+  test_result_string = 'do be completed'
+
+  if testcase_verdict == 'PASS':
+    if nb_run_pass == 0 : 
+      testcase_verdict = 'INCON'
+
+  print(Fore.WHITE + indent + "> testcase final verdict  :"),
+  if testcase_verdict == 'PASS':
+    print ( Fore.GREEN + testcase_verdict)
+  elif testcase_verdict == 'FAIL':
+    print ( Fore.RED + testcase_verdict)
+  else:
+    print (Fore.YELLOW+'INCONCLUSIVE')
+
+  duration= testcase_time_stop - testcase_time_start
+  xmlFile = logdir_local_testcase + '/test.' + testcasename + '.xml'
+  xml="\n<testcase classname=\'"+ testcaseclass +  "\' name=\'" + testcasename + "."+tags +  "\' Run_result=\'" + test_result_string + "\' time=\'" + str(duration) + " s \' RESULT=\'" + testcase_verdict + "\'></testcase> \n"
+  write_file(xmlFile, xml, mode="w")
+
+
+  test_result = dict(testcase_name=testcasename,
+                     testcaseclass=testcaseclass, 
+                     testcase_verdict = testcase_verdict,
+                     testcase_time_start=testcase_time_start,
+                     testcase_time_stop=testcase_time_stop,
+                     tags=tags,
+                     nruns=nb_runs,
+                     nb_run_pass = nb_run_pass,
+                     nb_run_skip = nb_run_skip,
+                     nb_run_failed = nb_run_failed,
+                     nb_run_inc=nb_run_inc,
+                     nb_seg_fault = nb_seg_fault,
+                     testcase_timeout=timeout_cmd,
+                     testcase_duration = duration,
+                     testcase_eNBMachine =eNBMachine,
+                     testcase_UEMachine =UEMachine,
+                     runs_results = runs_results)
+  #test_results.append(test_result)
+
+  return testcase_verdict
+
+
+
+
 # \brief This function searches if test case is present in list of test cases that need to be executed by user
 # \param testcasename the test case to search for
 # \param testcasegroup list that is passed from the arguments
@@ -1149,12 +1754,14 @@ if openairdir_local is None:
 locallogdir = openairdir_local + '/cmake_targets/autotests/log'
 MachineList = ''
 MachineListGeneric=''
+MachineDescDic={}
 flag_remove_logdir=False
 flag_start_testcase=False
 nruns_lte_softmodem=''
 flag_skip_git_head_check=False
 flag_skip_oai_install=False
 Timeout_cmd=''
+xmlInputFile=''
 print "Number of arguments argc = " + str(len(sys.argv))
 #for index in range(1,len(sys.argv) ):
 #  print "argv_" + str(index) + " : " + sys.argv[index]
@@ -1218,6 +1825,9 @@ while i < len (sys.argv):
         i = i +1
     elif arg == '--skip-oai-install':
         flag_skip_oai_install=True
+    elif arg == '--test-suite' :
+        xmlInputFile = sys.argv[i+1]
+        i = i +1
     elif arg == '-h' :
         print "-s:  This flag *MUST* be set to start the test cases"
         print "-r:  Remove the log directory in autotests"
@@ -1235,6 +1845,7 @@ while i < len (sys.argv):
         print "--skip-git-head-check: skip checking of GitHead remote/local branch (only for debugging)"
         print "--timeout_cmd: Override the default parameter (timeout_cmd) in test_case_list.xml. This parameter is in seconds and should be > 120"
         print "--skip-oai-install: Skips the openairinterface5g installer"
+        print "--test-suite: Select a XML test-suite file"
         sys.exit()
     else :
         print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options"
@@ -1264,6 +1875,13 @@ cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"| awk \'{print $2}\' | sudo xargs
 
 os.system(cmd)
 
+try:
+  analyser = __import__("lib_autotest_analyser")
+except ImportError as err:
+  print('Import error: ' + str(err))
+  exit(0)
+
+
 if flag_start_testcase == False:
   print "You need to start the testcase by passing option -s. Use -h to see all options. Aborting now..."
   sys.exit(1)
@@ -1286,12 +1904,14 @@ os.system(cmd)
 
 print "host = " + host 
 print "user = " + user
-xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_list.xml"
+if xmlInputFile == '':
+  xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_list.xml"
 NFSResultsDir = '/mnt/sradio'
 cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash'
 logdir = '/tmp/' + 'OAITestFrameWork-' + user + '/'
 logdirOAI5GRepo = logdir + 'openairinterface5g/'
 logdirOpenaircnRepo = logdir + 'openair-cn/'
+patchdir = logdirOAI5GRepo + 'cmake_targets/autotests/patches/'
 
 if flag_remove_logdir == True:
    print "Removing directory: " + locallogdir
@@ -1333,6 +1953,8 @@ ExmimoRfStop = xmlRoot.findtext('ExmimoRfStop',default='')
 if nruns_lte_softmodem == '':
    nruns_lte_softmodem = xmlRoot.findtext('nruns_lte-softmodem',default='')
 
+OAI5GpatchFileList=xmlRoot.findall('OAI5GPatchFile')
+
 print "MachineList = " + MachineList
 print "GitOpenair-cnRepo = " + GitOpenaircnRepo
 print "GitOAI5GRepo = " + GitOAI5GRepo
@@ -1365,6 +1987,7 @@ MachineListGeneric = MachineListGeneric.split()
 #index=0
 for machine in MachineList: 
   oai_list.append( openair('localdomain',machine))
+  MachineDescDic[machine]={}
   #index = index + 1
 
 
@@ -1475,6 +2098,7 @@ for oai in oai_list:
       cmd = cmd +  'git checkout ' + GitOpenaircnRepoBranch  + '\n'
       cmd = cmd +  'env |grep OPENAIR'  + '\n'
       cmd = cmd + ' cd ' + logdir   + '\n'
+      cmd = cmd + 'mkdir -p ' + patchdir + '\n'
       cmd = cmd + ' ) > ' +  setuplogfile + ' 2>&1 \n'
       #cmd = cmd + 'echo \' ' + cmd  + '\' > ' + setup_script + ' 2>&1 \n '
       #result = oai_list[index].send_recv(cmd, False, 300 )
@@ -1500,8 +2124,27 @@ for t in threads_init_setup:
    localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt'
    remotefile = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
    port = 22
+
+   #Now we copy patch files and apply them
+   print "Installating patch files on machine " + MachineList[index]
+   for patchFile in OAI5GpatchFileList:
+     localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/patches/')+patchFile.get('name')
+     remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/patches/'+patchFile.get('name')
+     if patchFile.get('machine') == MachineList[index] or patchFile.get('machine') == None:     
+       if os.path.isfile(localfile):
+         print "\t> PATCH FILE :"+localfile
+         paramList=[]
+         paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
+         sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
+         cmd =  '  cd ' + logdirOAI5GRepo + ' ;git apply cmake_targets/autotests/patches/'+patchFile.get('name')
+         res = oai_list[index].send_recv(cmd)
    
    paramList=[]
+
+   setuplogfile  = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
+   setup_script  = locallogdir  + '/setup_script_' + MachineList[index] +  '_.txt'
+   localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt'
+   remotefile = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
    sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
    paramList.append ( {"operation":'get', "localfile":localfile, "remotefile":remotefile} )
    #sftp_module (user, pw, MachineList[index], port, localfile, remotefile, sftp_log, "get")
@@ -1574,6 +2217,23 @@ for testcase in testcaseList:
         SSHSessionWrapper('localhost', user, None, pw , NFSTestsResultsDir , locallogdir, "put_all")
         oai_localhost.disconnect()
 
+      elif testcaseclass == 'lte-softmodem-noS1' :
+        eNBMachine = testcase.findtext('eNB',default='')
+        UEMachine = testcase.findtext('UE',default='')
+        if (eNBMachine not in MachineList)|(UEMachine not in MachineList):
+           print "One of the machines is not in the machine list"
+           print "eNBMachine : " + eNBMachine + "UEMachine : " + UEMachine + "MachineList : " + ','.join(MachineList)
+        print "testcasename = " + testcasename + " class = " + testcaseclass
+        threadListGlobal = wait_testcaseclass_generic_threads(threadListGlobal, Timeout_execution)
+        
+        handle_testcaseclass_softmodem_noS1 (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, user, pw, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem, Timeout_cmd ) 
+
+        #The lines below are copied from below to trace the failure of some of the machines in test setup. These lines below need to be removed in long term
+        print "Creating xml file for overall results..."
+        cmd = "cat $OPENAIR_DIR/cmake_targets/autotests/log/*/*.xml > $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml "
+        res=os.system(cmd)
+        os.system('sync')
+
       elif (testcaseclass == 'compilation'): 
         threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, user, pw, CleanUpAluLteBox,Timeout_execution, ExmimoRfStop)
       elif (testcaseclass == 'execution'): 
diff --git a/cmake_targets/autotests/tools/autotest_analyser.py b/cmake_targets/autotests/tools/autotest_analyser.py
new file mode 100755
index 0000000000000000000000000000000000000000..a75727ad65cfddf5a8ed2a561831e1859d555b6c
--- /dev/null
+++ b/cmake_targets/autotests/tools/autotest_analyser.py
@@ -0,0 +1,161 @@
+#! /usr/bin/python
+#******************************************************************************
+#
+# \file		autotest_analyser.py
+#
+# \par     Informations
+#            - \b Project  : UED Autotest Framework
+#            - \b Software : 
+#
+# \date		16 september 2016
+#
+# \version	0.1
+#
+# \brief	helper to test lib_autotest_analyser.py
+#
+# \author	Benoit ROBERT (benoit.robert@syrtem.com)
+#
+# \par		Statement of Ownership
+#           COPYRIGHT (c) 2016  BY SYRTEM S.A.R.L
+#           This software is furnished under license and may be used and copied 
+#			only in accordance with the terms of such license and with the inclusion
+#			of the above COPYRIGHT notice. This SOFTWARE or any other copies thereof
+#			may not be provided or otherwise made available to any other person. 
+#			No title to and ownership of the SOFTWARE is hereby transferred.
+#
+#			The information in this SOFTWARE is subject to change without notice 
+#			and should not be constructed as a commitment by SYRTEM.
+#           SYRTEM assumes no responsibility for the use or reliability of its 
+#			SOFTWARE on equipment or platform not explicitly validated by SYRTEM.
+#
+# *******************************************************************************
+
+import os
+import getopt
+import sys
+from subprocess import call
+
+
+
+#test_cases = ('030001', '030901', '031001', '031601', '031701', '031801', '031901', '032001', '032101', '032201', '032301', '032501', '032601', '032801')
+test_cases = ('030030' , '030030' ) 
+
+nb_run = 3
+
+def error_opt(msg):
+    print("Option error: " + msg)
+
+
+def main(args):
+	try:
+		analyser = __import__("lib_autotest_analyser")
+	except ImportError as err:
+		print('Import error: ' + str(err))
+		exit(0)
+
+
+	log_path = 'log_save_2016-08-14/log/'
+
+
+
+	metric = {}
+	metric['id'] 			= 'UE_DLSCH_BITRATE'
+	metric['description'] 	= 'UE downlink physical throughput'	
+	metric['regex'] 		= '(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)'
+	metric['unit_of_meas']	= 'kbps'
+	metric['min_limit']		= 14668.8
+
+
+#report_path = log_path+'/report/'
+
+#os.system(' mkdir -p ' + report_path)
+
+#analyser.create_report_html(report_path)
+
+#return(0)
+
+	for test_case in test_cases:
+
+#		print test_case
+		if test_case == '030001':
+			metric['min_limit']		= 500.0
+		if test_case == '030901':
+			metric['min_limit']		= 640.0
+		if test_case == '031001':
+			metric['min_limit']		= 3200.0
+		if test_case == '031601':
+			metric['min_limit']		= 5920.0
+		if test_case == '031701':
+			metric['min_limit']		= 6000.0
+		if test_case == '031801':
+			metric['min_limit']		= 6200.0
+		if test_case == '031901':
+			metric['min_limit']		= 7000.0
+		if test_case == '032001':
+			metric['min_limit']		= 7800.0
+		if test_case == '032101':
+			metric['min_limit']		= 8000.0
+		if test_case == '032201':
+			metric['min_limit']		= 9000.0
+		if test_case == '032301':
+			metric['min_limit']		= 10000.0
+		if test_case == '032501':
+			metric['min_limit']		= 11000.0
+		if test_case == '032601':
+			metric['min_limit']		= 12000.0
+		if test_case == '032801':
+			metric['min_limit']		= 12500.0
+
+		if test_case == '035201':
+			metric['min_limit']		= 14668.8
+		if test_case == '036001':
+			metric['min_limit']		= 25363.2
+
+
+
+		for i in range(0, nb_run):
+			fname = 'log//'+test_case+'/run_'+str(i)+'/UE_exec_'+str(i)+'_.log'
+			args = {'metric' : metric,
+					'file' : fname }
+
+			cell_synch_status = analyser.check_cell_synchro(fname)
+			if cell_synch_status == 'CELL_SYNCH':
+			  print '!!!!!!!!!!!!!!  Cell synchronized !!!!!!!!!!!'
+			  metric_checks_flag = 0
+			else :
+			  print '!!!!!!!!!!!!!!  Cell NOT  NOT synchronized !!!!!!!!!!!'
+	
+#			metric_extracted = analyser.do_extract_metrics(args)
+
+#			print "min       = "+ str( metric_extracted['metric_min'] )
+#			print "min_index = "+ str( metric_extracted['metric_min_index'] )
+#			print "max       = "+ str( metric_extracted['metric_max'] )
+#			print "max_index = "+ str( metric_extracted['metric_max_index'] )
+#			print "mean      = "+ str( metric_extracted['metric_mean'] )
+#			print "median    = "+ str( metric_extracted['metric_median'] )			
+
+#			verdict = analyser.do_check_verdict(metric, metric_extracted)
+#			print verdict
+
+#			fname= 'report/2016-9-8_toto/'+test_case+'/UE_metric_UE_DLSCH_BITRATE_'+str(i)+'_.png'
+#			fname= 'report/UE_metric_UE_DLSCH_BITRATE_'+test_case+'_'+str(i)+'.png'
+			
+#			print fname
+#			analyser.do_img_metrics(metric, metric_extracted, fname)
+
+#			fname = 'log//'+test_case+'/run_'+str(i)+'/UE_traffic_'+str(i)+'_.log'
+			
+#			args = {'file' : fname }
+
+#			traffic_metrics = analyser.do_extract_traffic_metrics(args)
+
+#			fname= 'report/iperf_'+test_case+'_'+str(i)+'.png'
+			
+#			print fname
+#			analyser.do_img_traffic(traffic_metrics, fname)
+
+
+
+if __name__ == "__main__":
+    main(sys.argv)
+
diff --git a/cmake_targets/autotests/tools/lib_autotest_analyser.py b/cmake_targets/autotests/tools/lib_autotest_analyser.py
new file mode 100644
index 0000000000000000000000000000000000000000..92dcc31e48dcae0ccd989a2e4e5d116bffee0add
--- /dev/null
+++ b/cmake_targets/autotests/tools/lib_autotest_analyser.py
@@ -0,0 +1,414 @@
+#******************************************************************************
+#
+# \file		lib_autotest_analyser.py
+#
+# \par     Informations
+#            - \b Project  : UED Autotest Framework
+#            - \b Software : 
+#
+# \date		16 september 2016
+#
+# \version	0.1
+#
+# \brief	library to extract metrics from autotest logs and assign a verdict
+#
+# \author	Benoit ROBERT (benoit.robert@syrtem.com)
+#
+# \par		Statement of Ownership
+#           COPYRIGHT (c) 2016  BY SYRTEM S.A.R.L
+#           This software is furnished under license and may be used and copied 
+#			only in accordance with the terms of such license and with the inclusion
+#			of the above COPYRIGHT notice. This SOFTWARE or any other copies thereof
+#			may not be provided or otherwise made available to any other person. 
+#			No title to and ownership of the SOFTWARE is hereby transferred.
+#
+#			The information in this SOFTWARE is subject to change without notice 
+#			and should not be constructed as a commitment by SYRTEM.
+#           SYRTEM assumes no responsibility for the use or reliability of its 
+#			SOFTWARE on equipment or platform not explicitly validated by SYRTEM.
+#
+# *******************************************************************************
+
+
+import re
+from pylab import *
+from matplotlib.font_manager import FontProperties
+
+import os
+from jinja2 import Environment, FileSystemLoader
+
+
+PATH = os.path.dirname(os.path.abspath(__file__))
+TEMPLATE_ENVIRONMENT = Environment(
+    autoescape=False,
+    loader=FileSystemLoader(os.path.join(PATH, 'templates')),
+    trim_blocks=False)
+
+
+def render_template(template_filename, context):
+    return TEMPLATE_ENVIRONMENT.get_template(template_filename).render(context)
+
+
+
+def init(args = None):
+    return
+
+
+#
+#
+#
+def do_extract_metrics(args):
+
+#	print ""
+#	print "do_extract_metrics ... "
+
+	fname 	= args['file']
+	metric 	= args['metric']
+#	print(fname)
+#	print 'metric id = ' + metric['id']
+#	print 'metric regex = ' + metric['regex']
+
+	count 		= 0
+	mmin 		= 0
+	mmin_index 	= 0
+	mmax  		= 0
+	mmax_index 	= 0
+	mean 		= 0
+	median 		= 0
+	
+
+	output = np.fromregex(fname,metric['regex'], [('id', 'S20'), ('metric', np.float), ('frame', np.int)] )
+#	print 'T0T0 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
+#	print output
+	count =  output['metric'].size
+#	print count
+	if count > 0:
+		mmin  		= np.amin(output['metric']);
+		mmin_index 	= np.argmin(output['metric']);
+		mmax  		= np.amax(output['metric']);
+		mmax_index 	= np.argmax(output['metric']); 			
+		mean 		= np.mean(output['metric']);
+		median 		= np.median(output['metric']);
+
+#		print ( ( (metric['min_limit'] > output['metric']).sum() / float(output['metric'].size) ) * 100 )
+
+	ret = {	'metric_count'		: count,
+			'metric_buf' 		: output,
+		 	'metric_min' 		: mmin, 
+		 	'metric_min_index' 	: mmin_index,
+			'metric_max' 		: mmax,
+		 	'metric_max_index' 	: mmax_index,
+			'metric_mean' 		: mean,
+			'metric_median' 	: median,
+			}
+	return(ret)
+
+#
+#
+#
+def do_check_verdict(metric_def, metric_data):
+	verdict = 'INCON'
+
+	pass_fail_stat = metric_def['pass_fail_stat']
+
+	if pass_fail_stat == 'max_value':
+		metric_stat = metric_data['metric_max']
+	elif pass_fail_stat == 'min_value':
+		metric_stat = metric_data['metric_min']
+	elif pass_fail_stat == 'mean_value':
+		metric_stat = metric_data['metric_mean']
+	elif pass_fail_stat == 'median_value':
+		metric_stat = metric_data['metric_median']
+	else :
+		print "do_check_verdict -> undef metric stat (pass_fail_stat in xml file)"
+		return verdict
+
+	if 'max_limit' in metric_def:
+		if  metric_stat > metric_def['max_limit']:
+			verdict =  'FAIL'
+		else:
+			verdict = 'PASS'
+
+	if 'min_limit' in metric_def:
+		if metric_stat < metric_def['min_limit']:
+			verdict = 'FAIL'
+		else:
+			verdict = 'PASS'
+	return verdict
+
+
+def do_print_metrics(metric_def, metric_data):
+
+
+	if metric_data['metric_count'] > 0 :
+
+#		output = np.array( metric_data['metric_buf'] , [('id', 'S20'), ('metric', np.float), ('frame', np.int)])
+		output = metric_data['metric_buf']
+#		print output
+
+		fontP = FontProperties()
+		fontP.set_size('small')
+
+		plt.scatter(output['frame'], output['metric'], color='b', alpha=0.33, s = 1 )
+		plt.plot([0, output['frame'][metric_data['metric_count']-1]],[ metric_def['min_limit'],metric_def['min_limit']], 'r-', lw=2) # Red straight line
+
+		plt.title('Physical throughput ')
+		plt.xlabel('frame')
+		plt.ylabel(metric_def['id'])
+		plt.legend(prop=fontP)
+		mng = plt.get_current_fig_manager()
+		plt.show()
+
+def do_img_metrics(metric_def, metric_data, fname):
+
+
+	if metric_data['metric_count'] > 0 :
+
+#		output = np.array( metric_data['metric_buf'] , [('id', 'S20'), ('metric', np.float), ('frame', np.int)])
+		output = metric_data['metric_buf']
+#		print 'TITI !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
+#		print output
+
+#		print metric_def['min_limit']
+#		print metric_data['metric_count']
+#		print output['frame'][metric_data['metric_count']-1]
+
+		fontP = FontProperties()
+		fontP.set_size('small')
+
+		plt.figure()
+
+#		print output['frame'].size
+#		print output['metric'].size
+
+		plt.scatter(output['frame'], output['metric'], color='b', alpha=0.33, s = 1 , label=metric_def['id'])
+		plt.plot([0, output['frame'][metric_data['metric_count']-1]],[ metric_def['min_limit'],metric_def['min_limit']], 'r-', lw=2, label='min limit') # Red straight line
+
+		plt.title('Physical throughput ('+metric_def['unit_of_meas']+')')
+		plt.xlabel('frame')
+		plt.ylabel(metric_def['id'])
+		
+		# Set graphic minimum Y axis
+		# -------------------------
+		if metric_data['metric_min'] == 0 :
+			plt.ylim(ymin=-metric_def['min_limit']/10)
+		else :	
+			plt.ylim(ymin=0)
+
+		y_axis_max = 0
+		if metric_data['metric_max'] >  metric_def['min_limit']:
+			y_axis_max =metric_data['metric_max']+metric_data['metric_max']/10
+		else:
+			y_axis_max =metric_def['min_limit']+metric_def['min_limit']/10
+
+		plt.ylim(ymax=y_axis_max)
+
+		lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
+		mng = plt.get_current_fig_manager()
+		plt.savefig(fname, bbox_extra_artists=(lgd,), bbox_inches='tight')
+		plt.close()
+
+#	with open(fname, 'r') as f:
+#		for line in f:
+#			m = re.search(metric['regex'], line)
+#			if m :
+#				print m.group(1) + " -> "+m.group(2)
+
+
+
+
+def do_extract_traffic_metrics(args):
+
+	print ""
+	print "do_extract_traffic_metrics ... "
+
+	fname 	= args['file']
+
+#	print(fname)
+#	print 'metric id = ' + metric['id']
+
+#[ ID] Interval       Transfer     Bandwidth        Jitter   Lost/Total Datagrams
+#[  3]  0.0- 1.0 sec   238 KBytes  1.95 Mbits/sec   0.980 ms    2/  174 (1.1%)
+# [  3]  0.0- 1.0 sec  63.2 KBytes   517 Kbits/sec   0.146 ms    1/   45 (2.2%)
+
+#	iperf_regex = '[\s*(\d+)]\s+\d+\.\d+-\s*(\d+\.\d+)\s+sec\s+(\d+).+(\d+\.\d+).+(\d+\.\d+).+(\d+)\/\s*(\d+)\s+\((\d+\.\d+)\%\)'
+	#                    ID          0.0            1.0                 63.2        KByte   517          Kbits/s   0.146
+	iperf_regex = '\[\s*(\d+)\]\s+(\d+\.*\d*)-\s*(\d+\.*\d*)\s+sec\s+(\d+\.*\d*)\s+(\D+)\s+(\d+\.*\d*)\s+(\D+)\s+(\d+\.*\d*)\s+ms\s+(\d+)\/\s*(\d+)\s+\((\d+\.*\d*)\%\)'
+#	print 'iperf regex = ' + iperf_regex
+
+	count 		= 0
+	bw_min 		= 0
+	bw_max 		= 0
+	bw_mean 	= 0
+	bw_median	= 0
+	jitter_min 		= 0
+	jitter_max 		= 0
+	jitter_mean 	= 0
+	jitter_median	= 0
+
+	rl_min 		= 0
+	rl_max 		= 0
+	rl_mean 	= 0
+	rl_median	= 0
+
+	interval_stop_max = 0
+	
+	output = np.fromregex(fname,iperf_regex, [('id', np.int) , ('interval_start', np.float), ('interval_stop', np.float), ('transfer', np.float), ('transfer_uom', 'S20') ,('bandwidth', np.float), ('bandwidth_uom', 'S20') ,('jitter', np.float), ('lost', np.int) , ('total', np.int), ('rate_lost', np.float) ] )
+
+	count = output['id'].size -1
+	# remove last line that is an iperf result resume
+
+	if count > 0:
+
+		output= np.delete(output, (count), axis=0 )
+#		print output
+
+		bw_min 		= np.amin(output['bandwidth']);
+		bw_max 		= np.amax(output['bandwidth']);
+		bw_mean 	= np.mean(output['bandwidth']);
+		bw_median	= np.median(output['bandwidth']);
+
+		jitter_min 		= np.amin(output['jitter']);
+		jitter_max 		= np.amax(output['jitter']);
+		jitter_mean 	= np.mean(output['jitter']);
+		jitter_median	= np.median(output['jitter']);
+
+		rl_min 		= np.amin(output['rate_lost']);
+		rl_max 		= np.amax(output['rate_lost']);
+		rl_mean 	= np.mean(output['rate_lost']);
+		rl_median	= np.median(output['rate_lost']);
+
+		interval_stop_max = np.amax(output['interval_stop']);
+
+	else :
+		count = 0
+
+
+	ret = {	'traffic_count'	: count,
+			'traffic_buf' 	: output,
+			'bw_min' 		: bw_min,
+			'bw_max' 		: bw_max,
+			'bw_mean' 		: bw_mean,
+			'bw_median'		: bw_median,
+			'jitter_min' 	: jitter_min,
+			'jitter_max' 	: jitter_max,
+			'jitter_mean' 	: jitter_mean,
+			'jitter_median'	: jitter_median,
+			'rl_min' 		: rl_min,
+			'rl_max' 		: rl_max,
+			'rl_mean' 		: rl_mean,
+			'rl_median'		: rl_median,
+			'interval_stop_max' : interval_stop_max
+			}
+	return(ret)
+
+
+
+
+def do_img_traffic(traffic_data, fname):
+
+
+	if traffic_data['traffic_count'] > 0 :
+
+		output = traffic_data['traffic_buf']
+
+
+		fontP = FontProperties()
+		fontP.set_size('small')
+
+		fig = plt.figure(1)
+
+		ax1= plt.subplot(311)
+		plt.plot(output['interval_stop'], output['bandwidth'], color='b' )
+		ax1.set_title('Bandwidth (Mbits/s)')
+		ax1.set_ylim(ymin=-1)
+		ax1.set_xlim(xmax=np.amax(output['interval_stop']))
+		text='min: '+str(traffic_data['bw_min'])+'\nmax: '+str(traffic_data['bw_max'])+'\nmean: '+str(traffic_data['bw_mean'])+'\nmedian: '+str(traffic_data['bw_median'])
+		ax1.text( np.amax(output['interval_stop'])+10,0,text)
+
+
+		ax2=plt.subplot(312)
+		plt.plot(output['interval_stop'], output['jitter'], color='b' )
+		ax2.set_title('Jitter (ms)')
+		ax2.set_xlim(xmax=np.amax(output['interval_stop']))
+		ax2.set_ylim(ymin=-1)
+		text='min: '+str(traffic_data['jitter_min'])+'\nmax: '+str(traffic_data['jitter_max'])+'\nmean: '+str(traffic_data['jitter_mean'])+'\nmedian: '+str(traffic_data['jitter_median'])
+		ax2.text( np.amax(output['interval_stop'])+10,0,text)
+
+		ax3=plt.subplot(313)
+		plt.plot(output['interval_stop'], output['rate_lost'], color='b')
+		ax3.set_title('Loss rate %')
+		ax3.set_xlim(xmax=np.amax(output['interval_stop']))
+		ax3.set_ylim(ymin=-1)
+		text='min: '+str(traffic_data['rl_min'])+'\nmax: '+str(traffic_data['rl_max'])+'\nmean: '+str(traffic_data['rl_mean'])+'\nmedian: '+str(traffic_data['rl_median'])
+		ax3.text( np.amax(output['interval_stop'])+10,0,text)
+
+
+#		plt.title('Physical throughput ('+metric_def['unit_of_meas']+')')
+		plt.xlabel('time (s)')
+#		plt.ylabel(metric_def['id'])
+		
+		# Set graphic minimum Y axis
+		# -------------------------
+#		if traffic_data['bw_min'] == 0 :
+#			plt.ylim(ymin=-metric_def['min_limit']/10)
+#		else :	
+#			plt.ylim(ymin=0)
+
+#		y_axis_max = 0
+#		if traffic_data['metric_max'] >  metric_def['min_limit']:
+#			y_axis_max =traffic_data['metric_max']+traffic_data['metric_max']/10
+#		else:
+#			y_axis_max =metric_def['min_limit']+metric_def['min_limit']/10
+#
+#		plt.ylim(ymax=y_axis_max)
+
+		plt.tight_layout()
+
+		lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
+		mng = plt.get_current_fig_manager()
+		plt.savefig(fname, bbox_inches='tight')
+		plt.close()
+
+
+
+
+def create_report_html(context):
+    fname = context['report_path']+"/index.html"
+  
+    #
+    with open(fname, 'w') as f:
+        html = render_template('index.html', context)
+        f.write(html)
+
+
+def create_test_report_detailed_html(context, fname ):
+    with open(fname, 'w') as f:
+        html = render_template('testcase_report.html', context)
+        f.write(html)
+
+
+def check_cell_synchro(fname):	
+
+	with open(fname, 'r') as f:
+		for line in f:
+
+			m = re.search('AUTOTEST Cell Sync \:', line)
+			if m :
+				print line
+				return 'CELL_SYNCH'
+
+	return 'CELL_NOT_SYNCH'
+
+
+def check_exec_seg_fault(fname):	
+
+	with open(fname, 'r') as f:
+		for line in f:
+			m = re.search('Segmentation fault', line)
+			if m :
+				print line
+				return 'SEG_FAULT'
+
+	return 'NO_SEG_FAULT'
+
diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper
index ac9739e5897cbafa3568e505a7b0e7669bc96a38..c5f2b877048c10b4a0e19cb238a99a6ac5c603dc 100755
--- a/cmake_targets/tools/build_helper
+++ b/cmake_targets/tools/build_helper
@@ -223,13 +223,15 @@ check_install_additional_tools (){
         android-tools-adb \
 	wvdial \
         python-numpy \
-    sshpass \
-    nscd \
-    bc \
-    ntp
+        sshpass \
+        nscd \
+        bc \
+        ntp \
+        python-scipy \
+        python-matplotlib
 
     $SUDO pip install paramiko
-    $SUDO pip install pyroute2
+    $SUDO pip install pyroute2 colorama
     $SUDO rm -fr /opt/ssh
     $SUDO GIT_SSL_NO_VERIFY=true git clone https://gitlab.eurecom.fr/oai/ssh.git /opt/ssh
     
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 321225a597f5c7ec8fc22576fb6795c32209b1fc..6e5e0ad7aa26f86d760c6df773782f076cbe23c5 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -61,6 +61,10 @@ ID = ENB_PHY_PUCCH_1_ENERGY
     DESC = eNodeB PUCCH 1 energy and threshold
     GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
     FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,energy : int,threshold
+ID = ENB_PHY_PHICH
+    DESC = eNodeB PHICH
+    GROUP = ALL:PHY:ENB
+    FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,NGROUP : int,NSF : int,ngroup : int,nseq : int,ACK : int,first_rb : int,n_DMRS
 
 #MAC logs
 ID = ENB_MAC_UE_DL_SDU
diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder.c b/openair1/PHY/CODING/3gpplte_turbo_decoder.c
index 931758c03bebb2077d00745c9f33d2ad70a7d644..c6976df16495685095be08c80588f304ed33ebb9 100644
--- a/openair1/PHY/CODING/3gpplte_turbo_decoder.c
+++ b/openair1/PHY/CODING/3gpplte_turbo_decoder.c
@@ -1058,7 +1058,7 @@ unsigned char phy_threegpplte_turbo_decoder_scalar(llr_t *y,
       break;
     }
 
-    if ((crc == oldcrc) && (crc!=0)) {
+    if (crc == oldcrc) {
       return(iteration_cnt);
     }
 
diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c
index 49bb9d102c2f28832711112da7c42e70cf5f26e9..4efd366bed2cb39058fa685b7e4f53baeb2dccb2 100644
--- a/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c
+++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c
@@ -1375,7 +1375,7 @@ unsigned char phy_threegpplte_turbo_decoder16avx2(int16_t *y,
       fprintf(fdavx2b,"oldcrc %x, crc %x, oldcrc_cw2 %x, crc_cw2 %x\n",oldcrc,crc,oldcrc_cw2,crc_cw2);
 #endif
 
-      if ((crc == oldcrc) && (crc!=0) && (crc_cw2 == oldcrc_cw2) && (crc_cw2!=0)) {
+      if (crc == oldcrc && crc_cw2 == oldcrc_cw2) {
         return(iteration_cnt);
       }
     }
diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse.c
index abcdc0521bccfe05304c667a44a476bd8c25857b..085dbb723c3eee5382886e253fdaebc5ac9a520e 100644
--- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse.c
+++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse.c
@@ -2556,7 +2556,7 @@ unsigned char phy_threegpplte_turbo_decoder(short *y,
 
       stop_meas(intl2_stats);
 
-      if ((crc == oldcrc) && (crc!=0)) {
+      if (crc == oldcrc) {
         return(iteration_cnt);
       }
     }
diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c
index dc789d0404a6c04324854699060dbf2547ddbfb3..a1e408dcda72ff57ec520b8138e0193266155f7c 100644
--- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c
+++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c
@@ -1612,7 +1612,7 @@ unsigned char phy_threegpplte_turbo_decoder16(short *y,
       fprintf(fdsse4,"oldcrc %x, crc %x\n",oldcrc,crc);
 #endif
 
-      if ((crc == oldcrc) && (crc!=0)) {
+      if (crc == oldcrc) {
         return(iteration_cnt);
       }
     }
diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c
index 1343aee07cff2b25a411fc266883896533d56f69..ff7e02a239b777db692c46773a79db67f5911fab 100644
--- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c
+++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c
@@ -1625,7 +1625,7 @@ unsigned char phy_threegpplte_turbo_decoder8(short *y,
 
       if (intl2_stats) stop_meas(intl2_stats);
 
-      if ((crc == oldcrc) && (crc!=0)) {
+      if (crc == oldcrc) {
         return(iteration_cnt);
       }
     }
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
index fc307655dd8ad120e7f71ab671eb452fb46e6be0..da678088fd5f1921036bd54df12e558e3bb721f3 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
@@ -7240,7 +7240,17 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB,
 
 
     if (cqi_req == 1) {
-      ulsch->harq_processes[harq_pid]->O_RI = 1; //we only support 2 antenna ports, so this is always 1 according to 3GPP 36.213 Table
+      /* 36.213 7.2.1 (release 10) says:
+       * "RI is only reported for transmission modes 3 and 4,
+       * as well as transmission modes 8 and 9 with PMI/RI reporting"
+       * This is for aperiodic reporting.
+       * TODO: deal with TM 8&9 correctly when they are implemented.
+       * TODO: deal with periodic reporting if we implement it.
+       */
+      if (transmission_mode == 3 || transmission_mode == 4)
+        ulsch->harq_processes[harq_pid]->O_RI = 1; //we only support 2 antenna ports, so this is always 1 according to 3GPP 36.213 Table
+      else
+        ulsch->harq_processes[harq_pid]->O_RI = 0;
 
       switch(transmission_mode) {
         // The aperiodic CQI reporting mode is fixed for every transmission mode instead of being configured by higher layer signaling
diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h
index deb1110a55343b8aedf2f3b9d43daeb70210c2b9..026ba4034029ade6c42faad40ca688af65fe071a 100644
--- a/openair1/PHY/LTE_TRANSPORT/defs.h
+++ b/openair1/PHY/LTE_TRANSPORT/defs.h
@@ -362,12 +362,18 @@ typedef struct {
   uint8_t TPC;
   /// First Allocated RB
   uint16_t first_rb;
+  /// First Allocated RB - previous scheduling
+  /// This is needed for PHICH generation which
+  /// is done after a new scheduling
+  uint16_t previous_first_rb;
   /// Current Number of RBs
   uint16_t nb_rb;
   /// Transport block size
   uint32_t TBS;
   /// The payload + CRC size in bits
   uint32_t B;
+  /// Number of soft channel bits
+  uint32_t G;
   /// CQI CRC status
   uint8_t cqi_crc_status;
   /// Pointer to CQI data
@@ -444,6 +450,10 @@ typedef struct {
   uint8_t Nsymb_initial;
   /// n_DMRS  for cyclic shift of DMRS (36.213 Table 9.1.2-2)
   uint8_t n_DMRS;
+  /// n_DMRS  for cyclic shift of DMRS (36.213 Table 9.1.2-2) - previous scheduling
+  /// This is needed for PHICH generation which
+  /// is done after a new scheduling
+  uint8_t previous_n_DMRS;
   /// n_DMRS 2 for cyclic shift of DMRS (36.211 Table 5.5.1.1.-1)
   uint8_t n_DMRS2;
   /// Flag to indicate that this ULSCH is for calibration information sent from UE (i.e. no MAC SDU to pass up)
diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c
index 1727ec53242739fd603665c08e08e15d7e4443ec..6b66ee0282084e68a27858e9e2c7dcef39eb9b4b 100644
--- a/openair1/PHY/LTE_TRANSPORT/phich.c
+++ b/openair1/PHY/LTE_TRANSPORT/phich.c
@@ -1453,8 +1453,12 @@ void generate_phich_top(PHY_VARS_eNB *eNB,
         LOG_D(PHY,"[eNB][PUSCH %d/%x] Frame %d subframe %d (pusch_subframe %d,pusch_frame %d) phich active %d\n",
               harq_pid,ulsch[UE_id]->rnti,proc->frame_tx,subframe,pusch_subframe,pusch_frame,ulsch[UE_id]->harq_processes[harq_pid]->phich_active);
 
-        ngroup_PHICH = (ulsch[UE_id]->harq_processes[harq_pid]->first_rb +
-                        ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%Ngroup_PHICH;
+        /* the HARQ process may have been reused by a new scheduling, so we use
+         * previous values of first_rb and n_DMRS to compute ngroup_PHICH and nseq_PHICH
+         */
+
+        ngroup_PHICH = (ulsch[UE_id]->harq_processes[harq_pid]->previous_first_rb +
+                        ulsch[UE_id]->harq_processes[harq_pid]->previous_n_DMRS)%Ngroup_PHICH;
 
         if ((frame_parms->tdd_config == 0) && (frame_parms->frame_type == TDD) ) {
 
@@ -1462,20 +1466,28 @@ void generate_phich_top(PHY_VARS_eNB *eNB,
             ngroup_PHICH += Ngroup_PHICH;
         }
 
-        nseq_PHICH = ((ulsch[UE_id]->harq_processes[harq_pid]->first_rb/Ngroup_PHICH) +
-                      ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%(2*NSF_PHICH);
+        nseq_PHICH = ((ulsch[UE_id]->harq_processes[harq_pid]->previous_first_rb/Ngroup_PHICH) +
+                      ulsch[UE_id]->harq_processes[harq_pid]->previous_n_DMRS)%(2*NSF_PHICH);
         LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Generating PHICH, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d dci_alloc %d)\n",
               eNB->Mod_id,harq_pid,proc->frame_tx,
               subframe,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH,
               ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK,
-              ulsch[UE_id]->harq_processes[harq_pid]->first_rb,
+              ulsch[UE_id]->harq_processes[harq_pid]->previous_first_rb,
               ulsch[UE_id]->harq_processes[harq_pid]->dci_alloc);
 
+        T(T_ENB_PHY_PHICH, T_INT(eNB->Mod_id), T_INT(proc->frame_tx), T_INT(subframe),
+          T_INT(UE_id), T_INT(ulsch[UE_id]->rnti), T_INT(harq_pid),
+          T_INT(Ngroup_PHICH), T_INT(NSF_PHICH),
+          T_INT(ngroup_PHICH), T_INT(nseq_PHICH),
+          T_INT(ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK),
+          T_INT(ulsch[UE_id]->harq_processes[harq_pid]->previous_first_rb),
+          T_INT(ulsch[UE_id]->harq_processes[harq_pid]->previous_n_DMRS));
+
         if (ulsch[UE_id]->Msg3_active == 1) {
           LOG_D(PHY,"[eNB %d][PUSCH %d][RAPROC] Frame %d, subframe %d: Generating Msg3 PHICH for UE %d, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d\n",
                 eNB->Mod_id,harq_pid,proc->frame_tx,subframe,
                 UE_id,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH,ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK,
-                ulsch[UE_id]->harq_processes[harq_pid]->first_rb);
+                ulsch[UE_id]->harq_processes[harq_pid]->previous_first_rb);
         }
 
         if (eNB->abstraction_flag == 0) {
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
index 9081455f000dafb0ebd5629d495d801deabbc9de..80dfb69877a157e1f1c56b8b5f816c36752faf00 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
@@ -228,7 +228,7 @@ int ulsch_decoding_data_2thread0(td_params* tdp) {
   LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
   LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
   int Q_m = get_Qm_ul(ulsch_harq->mcs);
-  int G = ulsch_harq->nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch;
+  int G = ulsch_harq->G;
   uint32_t E;
   uint32_t Gp,GpmodC,Nl=1;
   uint32_t C = ulsch_harq->C;
@@ -450,7 +450,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr
   LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
   LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
   int Q_m = get_Qm_ul(ulsch_harq->mcs);
-  int G = ulsch_harq->nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch;
+  int G = ulsch_harq->G;
   unsigned int E;
   int Cby2;
 
@@ -658,7 +658,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag)
   LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
   LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
   int Q_m = get_Qm_ul(ulsch_harq->mcs);
-  int G = ulsch_harq->nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch;
+  int G = ulsch_harq->G;
   unsigned int E;
 
   uint8_t (*tc)(int16_t *y,
@@ -1036,6 +1036,7 @@ unsigned int  ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
 #endif
 
   G = G - Q_RI - Q_CQI;
+  ulsch_harq->G = G;
 
   if ((int)G < 0) {
     LOG_E(PHY,"FATAL: ulsch_decoding.c G < 0 (%d) : Q_RI %d, Q_CQI %d\n",G,Q_RI,Q_CQI);
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 4163b8340c0aa2c1c5d2073af7955397922f8ce3..7ac6e2bf1fe6e7a148df8a1434d633a53807b093 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -1206,6 +1206,38 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
       eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
   }
 
+  /* save old HARQ information needed for PHICH generation */
+  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
+    if (eNB->ulsch[i]) {
+      /* Store first_rb and n_DMRS for correct PHICH generation below.
+       * For PHICH generation we need "old" values of last scheduling
+       * for this HARQ process. 'generate_eNB_dlsch_params' below will
+       * overwrite first_rb and n_DMRS and 'generate_phich_top', done
+       * after 'generate_eNB_dlsch_params', would use the "new" values
+       * instead of the "old" ones.
+       *
+       * This has been tested for FDD only, may be wrong for TDD.
+       *
+       * TODO: maybe we should restructure the code to be sure it
+       *       is done correctly. The main concern is if the code
+       *       changes and first_rb and n_DMRS are modified before
+       *       we reach here, then the PHICH processing will be wrong,
+       *       using wrong first_rb and n_DMRS values to compute
+       *       ngroup_PHICH and nseq_PHICH.
+       *
+       * TODO: check if that works with TDD.
+       */
+      if ((subframe_select(fp,ul_subframe)==SF_UL) ||
+          (fp->frame_type == FDD)) {
+        harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
+        eNB->ulsch[i]->harq_processes[harq_pid]->previous_first_rb =
+            eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
+        eNB->ulsch[i]->harq_processes[harq_pid]->previous_n_DMRS =
+            eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS;
+      }
+    }
+  }
+
 
   num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
   LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
index 617acff8b4a597592c7ce6e21d6bb9e4fec822f1..8ac2094efc31c4fd4c9823d31e3d685b87efb766 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
@@ -828,9 +828,6 @@ void schedule_ulsch_rnti(module_id_t   module_idP,
 	    UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
 	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul;
             mcs = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
-	    if ((cqi_req==1) && (mcs>19)) {
-		mcs=19;
-	    }
             if (UE_template->pre_allocated_rb_table_index_ul >=0) {
               rb_table_index=UE_template->pre_allocated_rb_table_index_ul;
             } else {
diff --git a/targets/DOCS/E-UTRAN_User_Guide.docx b/targets/DOCS/E-UTRAN_User_Guide.docx
old mode 100644
new mode 100755
index 824aa46e9a56b12d33802da83308aa83e7b07922..12a9d17da5f0fed5cd45a06cfc94ae853fb96840
Binary files a/targets/DOCS/E-UTRAN_User_Guide.docx and b/targets/DOCS/E-UTRAN_User_Guide.docx differ
diff --git a/targets/DOCS/E-UTRAN_User_Guide.pdf b/targets/DOCS/E-UTRAN_User_Guide.pdf
old mode 100644
new mode 100755
index 5005692944f0940d95d160f1ee734c0ce83cc619..3de31b24f2a95476c520378ac29ca6a41e8a2ea7
Binary files a/targets/DOCS/E-UTRAN_User_Guide.pdf and b/targets/DOCS/E-UTRAN_User_Guide.pdf differ
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf
index 191071d18cd8155fb1979219d390958e5e3ea254..868e499de6c58ede3ed14487d95d81c1e6ed18f2 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf
@@ -38,6 +38,7 @@ eNBs =
       Nid_cell_mbsfn          			      = 0;
       nb_antennas_tx          			      = 1;
       nb_antennas_rx          			      = 1;
+      nb_antenna_ports                        = 1;
       tx_gain                                            = 90;
       rx_gain                                            = 125;
       prach_root              			      = 0;
@@ -100,6 +101,7 @@ eNBs =
       ue_TimersAndConstants_t311			      = 10000;
       ue_TimersAndConstants_n310			      = 20;
       ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                         = 1;
 
       }
     );
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf
index 8e1e1441bf0f60974e2907bfaa4481b89fa81fbb..805bb1aba874380f0d99f5f11e3e26310e2c596d 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf
@@ -38,6 +38,7 @@ eNBs =
       Nid_cell_mbsfn          			      = 0;
       nb_antennas_tx          			      = 1;
       nb_antennas_rx          			      = 1;
+      nb_antenna_ports                        = 1;
       tx_gain                                            = 90;
       rx_gain                                            = 125;
       prach_root              			      = 0;
@@ -100,6 +101,7 @@ eNBs =
       ue_TimersAndConstants_t311			      = 10000;
       ue_TimersAndConstants_n310			      = 20;
       ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                         = 1;
 
       }
     );
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index d070b9108379664294e2a55210e0a76876ea9840..0741d88c42517e80a343295520ac0cd22624c3a5 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -1305,7 +1305,7 @@ extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
 
 void init_eNB_proc(int inst) {
   
-  int i;
+  int i=0;
   int CC_id;
   PHY_VARS_eNB *eNB;
   eNB_proc_t *proc;
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 117beb68d7f78caf9ced64df711991182029e230..3e089365ffff3b35397647978b44a77fa95105f2 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -1802,11 +1802,19 @@ int main( int argc, char **argv )
 
 
   // start the main thread
-  if (UE_flag == 1) init_UE(1);
+  if (UE_flag == 1) {
+    init_UE(1);
+    number_of_cards = 1;
+    
+    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+      PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
+      PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
+    }
+  }
   else { 
     init_eNB(node_function,node_timing,1,eth_params,single_thread_flag);
-  // Sleep to allow all threads to setup
-
+    // Sleep to allow all threads to setup
+    
     number_of_cards = 1;
     
     for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index c0e35181fd175d2cb32bc899b6c904bf8cba5c25..8e11a826385ecfd1b5691cb951c28a6205aaa7b5 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -220,7 +220,7 @@ static void *UE_thread_synch(void *arg)
   int current_band = 0;
   int current_offset = 0;
   sync_mode_t sync_mode = pbch;
-  int card;
+  int CC_id = UE->CC_id;
   int ind;
   int found;
   int freq_offset=0;
@@ -312,9 +312,8 @@ static void *UE_thread_synch(void *arg)
       printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
 
       if ((eutra_bands[ind].dl_min <= downlink_frequency[0][0]) && (eutra_bands[ind].dl_max >= downlink_frequency[0][0])) {
-        for (card=0; card<MAX_NUM_CCs; card++)
-          for (i=0; i<4; i++)
-            uplink_frequency_offset[card][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
+	for (i=0; i<4; i++)
+	  uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
 
         found = 1;
         break;
@@ -333,16 +332,16 @@ static void *UE_thread_synch(void *arg)
 
 
 
-    LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d)\n", downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0],oai_exit );
+    LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0],oai_exit, openair0_cfg[0].rx_num_channels);
 
-    for (i=0;i<openair0_cfg[0].rx_num_channels;i++) {
-      openair0_cfg[0].rx_freq[i] = downlink_frequency[0][i];
-      openair0_cfg[0].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
-      openair0_cfg[0].autocal[i] = 1;
-      if (uplink_frequency_offset[0][i] != 0) // 
-	openair0_cfg[0].duplex_mode = duplex_mode_FDD;
+    for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
+      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
+      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
+      openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
+      if (uplink_frequency_offset[CC_id][i] != 0) // 
+	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
       else //FDD
-	openair0_cfg[0].duplex_mode = duplex_mode_TDD;
+	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
     }
 
     sync_mode = pbch;
@@ -350,18 +349,14 @@ static void *UE_thread_synch(void *arg)
   } else if  (UE->UE_scan == 1) {
     current_band=0;
 
-    for (card=0; card<MAX_CARDS; card++) {
-      for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
-        downlink_frequency[card][i] = bands_to_scan.band_info[0].dl_min;
-        uplink_frequency_offset[card][i] = bands_to_scan.band_info[0].ul_min-bands_to_scan.band_info[0].dl_min;
-
-        openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i];
-        openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i];
-        openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;
-        printf( "UE synch: setting RX gain (%d,%d) to %f\n", card, i, openair0_cfg[card].rx_gain[i] );
-      }
+    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+      downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min;
+      uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min;
+      
+      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
+      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
+      openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
     }
-
   }
 
 
@@ -417,28 +412,19 @@ static void *UE_thread_synch(void *arg)
         oai_exit=1;
       }
 
-      for (card=0; card<MAX_CARDS; card++) {
-        for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
-          downlink_frequency[card][i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
-          uplink_frequency_offset[card][i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
-
-
-          openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i];
-          openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i];
-          openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;
-          printf("UE synch: setting RX gain (%d,%d) to %f\n",card,i,openair0_cfg[card].rx_gain[i]);
-        }
-
-      }
-
-      if (UE->UE_scan_carrier) {
-
-	for (i=0;i<openair0_cfg[0].rx_num_channels;i++)
-	  openair0_cfg[0].autocal[i] = 1;
+      for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+	downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
+	uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
 
+	openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
+	openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
+	openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
+	if (UE->UE_scan_carrier) {
+	  openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
+	}
+	
       }
 
-
       break;
  
     case pbch:
@@ -452,42 +438,42 @@ static void *UE_thread_synch(void *arg)
 
 	  UE->UE_scan_carrier = 0;
 	  // rerun with new cell parameters and frequency-offset
-	  for (i=0;i<openair0_cfg[0].rx_num_channels;i++) {
-	    openair0_cfg[0].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
-	    openair0_cfg[0].rx_freq[i] -= UE->common_vars.freq_offset;
-	    openair0_cfg[0].tx_freq[i] =  openair0_cfg[0].rx_freq[i]+uplink_frequency_offset[0][i];
-	    downlink_frequency[0][i] = openair0_cfg[0].rx_freq[i];
+	  for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
+	    openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
+	    openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= UE->common_vars.freq_offset;
+	    openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =  openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
+	    downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
 	    freq_offset=0;	    
 	  }
 
 	  // reconfigure for potentially different bandwidth
 	  switch(UE->frame_parms.N_RB_DL) {
 	  case 6:
-	    openair0_cfg[0].sample_rate =1.92e6;
-	    openair0_cfg[0].rx_bw          =.96e6;
-	    openair0_cfg[0].tx_bw          =.96e6;
+	    openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
+	    openair0_cfg[UE->rf_map.card].rx_bw          =.96e6;
+	    openair0_cfg[UE->rf_map.card].tx_bw          =.96e6;
 	    //            openair0_cfg[0].rx_gain[0] -= 12;
 	    break;
 	  case 25:
-	    openair0_cfg[0].sample_rate =7.68e6;
-	    openair0_cfg[0].rx_bw          =2.5e6;
-	    openair0_cfg[0].tx_bw          =2.5e6;
+	    openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
+	    openair0_cfg[UE->rf_map.card].rx_bw          =2.5e6;
+	    openair0_cfg[UE->rf_map.card].tx_bw          =2.5e6;
 	    //            openair0_cfg[0].rx_gain[0] -= 6;
 	    break;
 	  case 50:
-	    openair0_cfg[0].sample_rate =15.36e6;
-	    openair0_cfg[0].rx_bw          =5.0e6;
-	    openair0_cfg[0].tx_bw          =5.0e6;
+	    openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
+	    openair0_cfg[UE->rf_map.card].rx_bw          =5.0e6;
+	    openair0_cfg[UE->rf_map.card].tx_bw          =5.0e6;
 	    //            openair0_cfg[0].rx_gain[0] -= 3;
 	    break;
 	  case 100:
-	    openair0_cfg[0].sample_rate=30.72e6;
-	    openair0_cfg[0].rx_bw=10.0e6;
-	    openair0_cfg[0].tx_bw=10.0e6;
+	    openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
+	    openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
+	    openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
 	    //            openair0_cfg[0].rx_gain[0] -= 0;
 	    break;
 	  }
-
+	
 	  UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
 	  //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
 	  UE->rfdevice.trx_stop_func(&UE->rfdevice);	  
@@ -559,25 +545,19 @@ static void *UE_thread_synch(void *arg)
                downlink_frequency[0][0]+freq_offset,
                downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
 
-        for (card=0; card<MAX_CARDS; card++) {
-          for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
-            openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i]+freq_offset;
-            openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]+freq_offset;
-
-
-	    
-
-            openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
-	        UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
-	    
-          }
-        }
-
-	if (UE->UE_scan_carrier==1) {
-	  for (i=0;i<openair0_cfg[0].rx_num_channels;i++) {
-	    //	    openair0_cfg[0].autocal[i] = 1;
+	for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+	  openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset;
+	  openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset;
+	  
+	  openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
+	  
+	  if (UE->UE_scan_carrier==1) {
+	    openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
 	  }
 	}
+
+	UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
+	    
       }// initial_sync=0
 
       break;