diff --git a/doc/doxygen.cfg.in b/doc/doxygen.cfg.in
index c134254a70ecb5d6623a1e32bd83ec14f3e2680d..141c10c0f01913960884acd4bd5ea7348df8885d 100644
--- a/doc/doxygen.cfg.in
+++ b/doc/doxygen.cfg.in
@@ -31,7 +31,7 @@ PROJECT_NAME           = RCG
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 3.5
+PROJECT_NUMBER         = 4.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description for a project that appears at the top of each page and should give viewer a quick idea about the purpose of the project. Keep the description short.
 
diff --git a/doc/rcgsoftdevguideCcode.dox b/doc/rcgsoftdevguideCcode.dox
index d4729c3aac36f988055a98d9c0e135ffb8439b81..c0342e16e5685ca4017753905ad9be1d21ea22d5 100644
--- a/doc/rcgsoftdevguideCcode.dox
+++ b/doc/rcgsoftdevguideCcode.dox
@@ -4,15 +4,32 @@ This section provides a brief description of the various C code modules compiled
 \endverbatim
 \image html CcodeCompile.png "C Code Modules"
 	
+<b>Kernel Space Code Modules</b>
+
 <b>Module Initialization</b>
-- moduleLoad.c
-	- This file contains the main startup/initialization code. \n
+- These files contain the main startup/initialization code. \n
+    - moduleLoadIop.c   Code for production system IOP kernel object
+    - moduleLoadApp.c   Code for production system User App kernel object
+    - moduleLoadTS.c    Code for running IOP using Dolphin network timing
 
 <b>Scheduler</b>
-- controller.c
-	- This file contains the primary sequencer, or scheduler, code. \n
+- These files contain the primary sequencer, or scheduler, code. \n
+    - controllerIop.c   Code for production system IOP kernel object
+    - controllerApp.c   Code for production system User App kernel object
+    - controllerTS.c    Code for running IOP using Dolphin network timing
+    - controllerCymac.c Code for running a standalone test system
+    - controllerLR.c    Code for running with a long range PCIe extender
+
 Further information can be found at <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">LIGO T0900607 aLIGO CDS Realtime Sequencer Software</a>
 
+<b>User Space Code Modules</b>
+    - rcguserIop.c          Main code for initializing user space IOP software
+    - controllerIopUser.c   Main sequencer code for user space IOP
+
+    - rcguser.c             Main code for initializing user space app software
+    - controllerAppUser.c   Main sequencer code for user space app
+
+
 <b>Digital Filtering</b>
 - fm10Gen.c
 	- Contains the standard IIR/FIR filter routines.
@@ -41,8 +58,9 @@ Further information can be found at <a href="https://dcc.ligo.org/cgi-bin/privat
 - symmetricomGps.c \n
 - vmic5565.c \n
 
+
 <b>Real-time Networking </b>
-- commData2.c
+- commData3.c
 - dolphin.c
 
 
diff --git a/doc/top.dox b/doc/top.dox
index ac5fd66674a0e44c7ebe0ae6d721e477445ca2e2..4eecf1ad7d90f282fa5e2ed831f15ce4e7eda5d2 100644
--- a/doc/top.dox
+++ b/doc/top.dox
@@ -1,12 +1,12 @@
 /*!	\mainpage
-\Title RCG Version 2.8
+\Title RCG Version 4.0
 \tableofcontents
 
 This documentation is divided into the following sections:
 - \ref intro "CDS Overview Documentation"
 - \ref userguide "RCG User's Guide"
-- <a href="https://dcc.ligo.org/LIGO-T1300868">RCG V2.8 Release Notes</a>
 - <a href="https://dcc.ligo.org/LIGO-T1100625">RCG Runtime Diagnostics</a> 
+- <a href="https://awiki.ligo-wa.caltech.edu/wiki/CdsFrontEndDebian9">CDS Debian9 Build Instructions</a> 
 - \ref devguidetop "CDS Code Design and Development"
 	- \ref devguidercg "RCG Software"
 	- \ref devguidedaqd "CDS DAQ Data Concentrator/Framebuilder Software"
diff --git a/patches/linux-4.19-cs/README b/patches/linux-4.19-cs/README
new file mode 100644
index 0000000000000000000000000000000000000000..9654dd281dc4396593145ab06d1a3799442ee59c
--- /dev/null
+++ b/patches/linux-4.19-cs/README
@@ -0,0 +1,8 @@
+These are the patches developed by Keith Thorne and
+Rolf Bork to create a stable 'cs' (CPU Shutdown) 
+linux kernel 4.9 for CDS real-time.  All patches are required.
+
+- Basic CDS patch - adds CPU Shutdown
+kernel-4.9-cs.patch
+
+
diff --git a/patches/linux-4.19-cs/linux-4.19-cs.patch b/patches/linux-4.19-cs/linux-4.19-cs.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ffee7d8b0fe1fc32a90c31832711a02cdd40aaf2
--- /dev/null
+++ b/patches/linux-4.19-cs/linux-4.19-cs.patch
@@ -0,0 +1,45 @@
+diff -r -u -d linux-source-4.9.orig/arch/x86/kernel/smpboot.c linux-source-4.9.cs/arch/x86/kernel/smpboot.c
+--- linux-source-4.9.orig/arch/x86/kernel/smpboot.c	2019-04-05 15:29:15.000000000 -0500
++++ linux-source-4.9.cs/arch/x86/kernel/smpboot.c	2019-06-06 09:21:28.357716391 -0500
+@@ -1573,6 +1573,18 @@
+ 	common_cpu_die(cpu);
+ }
+ 
++static DEFINE_PER_CPU(void (*)(void), fe_code);
++
++int is_cpu_taken_by_rcg_model(unsigned int cpu) {
++        return 0 != per_cpu(fe_code, cpu);
++}
++EXPORT_SYMBOL(is_cpu_taken_by_rcg_model);
++
++void set_fe_code_idle(void (*ptr)(void), unsigned int cpu) {
++       per_cpu(fe_code, cpu) = ptr;
++}
++EXPORT_SYMBOL(set_fe_code_idle);
++
+ void play_dead_common(void)
+ {
+ 	idle_task_exit();
+@@ -1586,6 +1598,10 @@
+ 	 * With physical CPU hotplug, we should halt the cpu
+ 	 */
+ 	local_irq_disable();
++        if (per_cpu(fe_code, smp_processor_id())) {
++	       // Execute front-end code
++	       (*per_cpu(fe_code, smp_processor_id()))();
++	}
+ }
+ 
+ static bool wakeup_cpu0(void)
+diff -r -u -d linux-source-4.9.orig/kernel/cpu.c linux-source-4.9.cs/kernel/cpu.c
+--- linux-source-4.9.orig/kernel/cpu.c	2019-05-13 15:59:18.000000000 -0500
++++ linux-source-4.9.cs/kernel/cpu.c	2019-06-06 10:55:34.854916689 -0500
+@@ -1227,7 +1227,7 @@
+ {
+ 	return do_cpu_up(cpu, CPUHP_ONLINE);
+ }
+-EXPORT_SYMBOL_GPL(cpu_up);
++EXPORT_SYMBOL(cpu_up);
+ 
+ #ifdef CONFIG_PM_SLEEP_SMP
+ static cpumask_var_t frozen_cpus;
diff --git a/src/fe/controller.c b/src/fe/controller.c
index 08293cab8d1023fdd892e64319fd1c6fde08bb38..2e80997073b1ef5bcf978e84c196030f01dddd45 100644
--- a/src/fe/controller.c
+++ b/src/fe/controller.c
@@ -294,7 +294,7 @@ void deallocate_dac_channels(void) {
 #endif
 
 //***********************************************************************
-// TASK: fe_start()	
+// TASK: fe_start_v3()	
 // This routine is the skeleton for all front end code	
 //***********************************************************************
 /// This function is the main real-time sequencer or scheduler for all code built
@@ -306,7 +306,7 @@ void deallocate_dac_channels(void) {
 /// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn
 /// is triggered to sample by the 64KHz clock provided by the Timing Distribution System.
 ///	- 
-void *fe_start(void *arg)
+void *fe_start_v3(void *arg)
 {
   int longestWrite2 = 0;
   int tempClock[4];
diff --git a/src/fe/controllerApp.c b/src/fe/controllerApp.c
index fdcd8b516b2cea595fa0b20d823963e81c08dff5..3b0d4da7f043a1a9cd846975c4c70b4d9699f098 100644
--- a/src/fe/controllerApp.c
+++ b/src/fe/controllerApp.c
@@ -57,7 +57,7 @@ void deallocate_dac_channels(void) {
 }
 
 //***********************************************************************
-// TASK: fe_start()	
+// TASK: fe_start_app()	
 // This routine is the skeleton for all front end code	
 //***********************************************************************
 /// This function is the main real-time sequencer or scheduler for all code built
@@ -69,7 +69,7 @@ void deallocate_dac_channels(void) {
 /// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn
 /// is triggered to sample by the 64KHz clock provided by the Timing Distribution System.
 ///	- 
-void *fe_start(void *arg)
+void *fe_start_app(void *arg)
 {
   int ii,jj,kk,ll;			// Dummy loop counter variables
   static int clock1Min = 0;		///  @param clockMin Minute counter (Not Used??)
@@ -274,7 +274,7 @@ udelay(1000);
   // SLAVE needs to sync with MASTER by looking for cycle 0 count in ipc memory
   // Find memory buffer of first ADC to be used in SLAVE application.
   ll = cdsPciModules.adcConfig[0];
-  rdtscll(cpuClock[CPU_TIME_CYCLE_START]);
+  cpuClock[CPU_TIME_CYCLE_START] = rdtsc_ordered();
 
   pLocalEpics->epicsOutput.fe_status = INIT_SYNC;
     // Spin until cycle 0 detected in first ADC buffer location.
@@ -284,7 +284,7 @@ udelay(1000);
   pLocalEpics->epicsOutput.fe_status = NORMAL_RUN;
 
   timeSec = ioMemData->iodata[ll][0].timeSec;
-  rdtscll(cpuClock[CPU_TIME_CYCLE_END]);
+  cpuClock[CPU_TIME_CYCLE_END] = rdtsc_ordered();
   timeinfo.cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE;
   // Get GPS seconds from MASTER
   timeSec = ioMemData->gpsSecond;
@@ -299,7 +299,7 @@ udelay(1000);
   timeSec = current_time_fe() -1;
 #endif
 
-  rdtscll(adcinfo.adcTime);
+  adcinfo.adcTime = rdtsc_ordered();
 
   /// ******************************************************************************\n
   /// Enter the infinite FE control loop  ******************************************\n
@@ -354,7 +354,7 @@ udelay(1000);
 		/// \> Set counters for next read from ipc memory
         ioClock = (ioClock + 1) % IOP_IO_RATE;
         ioMemCntr = (ioMemCntr + 1) % IO_MEMORY_SLOTS;
-       	rdtscll(cpuClock[CPU_TIME_CYCLE_START]);
+  	cpuClock[CPU_TIME_CYCLE_START] = rdtsc_ordered();
 
 	}
 
@@ -364,9 +364,9 @@ udelay(1000);
 
 /// \> Call the front end specific application  ******************\n
 /// - -- This is where the user application produced by RCG gets called and executed. \n\n
-    rdtscll(cpuClock[CPU_TIME_USR_START]);
+    cpuClock[CPU_TIME_USR_START] = rdtsc_ordered();
  	iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0);
-    rdtscll(cpuClock[CPU_TIME_USR_END]);
+    cpuClock[CPU_TIME_USR_END] = rdtsc_ordered();
   	odcStateWord = 0;
 
 
@@ -542,7 +542,7 @@ udelay(1000);
     // // Update end of cycle information
     // // *****************************************************************
 	// Capture end of cycle time.
-    rdtscll(cpuClock[CPU_TIME_CYCLE_END]);
+    cpuClock[CPU_TIME_CYCLE_END] = rdtsc_ordered();
 
     captureEocTiming(cycleNum, cycle_gps_time, &timeinfo, &adcinfo);
 
diff --git a/src/fe/controllerAppUser.c b/src/fe/controllerAppUser.c
index 8a1e2bd77d4185b54540112ccb094c6ba2e0c8dd..bf31d5830ffaf97d4d9cd8e959b817ed02994998 100644
--- a/src/fe/controllerAppUser.c
+++ b/src/fe/controllerAppUser.c
@@ -119,7 +119,7 @@ unsigned int getGpsTimeProc() {
 }
 
 //***********************************************************************
-// TASK: fe_start()	
+// TASK: fe_start_app_user()	
 // This routine is the skeleton for all front end code	
 //***********************************************************************
 /// This function is the main real-time sequencer or scheduler for all code built
@@ -131,7 +131,7 @@ unsigned int getGpsTimeProc() {
 /// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn
 /// is triggered to sample by the 64KHz clock provided by the Timing Distribution System.
 ///	- 
-int fe_start()
+int fe_start_app_user()
 {
   int longestWrite2 = 0;
   int tempClock[4];
diff --git a/src/fe/controllerIop.c b/src/fe/controllerIop.c
index c6b7ef1dd49df47b5db215f0f7728945252202f9..bbabc84bfdcdc12a9289c80a2e1cafc4d478317c 100644
--- a/src/fe/controllerIop.c
+++ b/src/fe/controllerIop.c
@@ -72,7 +72,7 @@ int  getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec);
 #include <drv/adc_info.c>
 
 //***********************************************************************
-// TASK: fe_start()	
+// TASK: fe_start_iop()	
 // This routine is the skeleton for all front end code	
 //***********************************************************************
 /// This function is the main real-time sequencer or scheduler for all code built
@@ -84,7 +84,7 @@ int  getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec);
 /// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn
 /// is triggered to sample by the 64KHz clock provided by the Timing Distribution System.
 ///	- 
-void *fe_start(void *arg)
+void *fe_start_iop(void *arg)
 {
   int ii,jj,kk,ll;			// Dummy loop counter variables
   static int clock1Min = 0;		///  @param clockMin Minute counter (Not Used??)
@@ -340,7 +340,7 @@ adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo;
   timeSec = current_time_fe() -1;
 #endif
 
-  rdtscll(adcinfo.adcTime);
+  adcinfo.adcTime = rdtsc_ordered();
 
   /// ******************************************************************************\n
   /// Enter the infinite FE control loop  ******************************************\n
@@ -428,9 +428,9 @@ adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo;
 // **************************************************************************************
 /// \> Call the front end specific application  ******************\n
 /// - -- This is where the user application produced by RCG gets called and executed. \n\n
-    rdtscll(cpuClock[CPU_TIME_USR_START]);
+    cpuClock[CPU_TIME_USR_START] = rdtsc_ordered();
     iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0);
-    rdtscll(cpuClock[CPU_TIME_USR_END]);
+    cpuClock[CPU_TIME_USR_END] = rdtsc_ordered();
 // **************************************************************************************
 //
 //
@@ -831,7 +831,7 @@ adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo;
 // Update end of cycle information
 // *****************************************************************
     // Capture end of cycle time.
-    rdtscll(cpuClock[CPU_TIME_CYCLE_END]);
+    cpuClock[CPU_TIME_CYCLE_END] = rdtsc_ordered();
 
     /// \> Compute code cycle time diag information.
     captureEocTiming(cycleNum, cycle_gps_time, &timeinfo, &adcinfo);
diff --git a/src/fe/controllerIopUser.c b/src/fe/controllerIopUser.c
index a72a420060162238a4d81408310ea04c9bd10c24..2fd453b5e20be1288d641236a68eda99e48d0ee9 100644
--- a/src/fe/controllerIopUser.c
+++ b/src/fe/controllerIopUser.c
@@ -132,7 +132,7 @@ unsigned int getGpsTimeProc() {
  }
 
 //***********************************************************************
-// TASK: fe_start()	
+// TASK: fe_start_iop_user()	
 // This routine is the skeleton for all front end code	
 //***********************************************************************
 /// This function is the main real-time sequencer or scheduler for all code built
@@ -144,7 +144,7 @@ unsigned int getGpsTimeProc() {
 /// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn
 /// is triggered to sample by the 64KHz clock provided by the Timing Distribution System.
 ///	- 
-int fe_start()
+int fe_start_iop_user()
 {
   int longestWrite2 = 0;
   int tempClock[4];
diff --git a/src/fe/dolphin.c b/src/fe/dolphin.c
index ce2d456018f33bae2d21d500e91bc43cea85f239..9348f5cb277a63b813ff2884cdfb031e00ace896 100644
--- a/src/fe/dolphin.c
+++ b/src/fe/dolphin.c
@@ -1,3 +1,8 @@
+/// @file dolphin.c
+/// @brief File containing the Dolphin functions. \n
+///     @detail This file contains Dolphin init and cleanup routines for kernel module code.
+/// @author R.Bork
+
 #include <genif.h>
 #include "commData3.h"
 
@@ -23,6 +28,7 @@ signed32 session_callback(session_cb_arg_t IN arg,
 			  session_cb_status_t IN status,
 			  unsigned32 IN target_node,
 			  unsigned32 IN local_adapter_number) {
+/// @brief This function contains the required Dolphin callback routine. \n
   printkl("Session callback reason=%d status=%d target_node=%d\n", reason, status, target_node);
   // if (reason == SR_OK) iop_rfm_valid = 1;
   if (reason == SR_OK || status == SR_OK) iop_rfm_valid = 1;
@@ -33,6 +39,7 @@ signed32 session_callback(session_cb_arg_t IN arg,
   return 0;
 }
 
+/// Function for Dolphin connection callback
 signed32 connect_callback(void IN *arg,
 			  sci_r_segment_handle_t IN remote_segment_handle,
 			  unsigned32 IN reason, unsigned32 IN status) {
diff --git a/src/fe/moduleLoad.c b/src/fe/moduleLoad.c
index fcb559669ea94eea47e7ec2eb628550c1c8654c3..5c58c5a5c498f25a03148a02af6c4ac83294d3cc 100644
--- a/src/fe/moduleLoad.c
+++ b/src/fe/moduleLoad.c
@@ -9,7 +9,7 @@
 // These externs and "16" need to go to a header file (mbuf.h)
 extern void *kmalloc_area[16];
 extern int mbuf_allocate_area(char *name, int size, struct file *file);
-extern void *fe_start(void *arg);
+extern void *fe_start_v3(void *arg);
 extern int run_on_timer;
 extern char daqArea[2*DAQ_DCU_SIZE];           // Space allocation for daqLib buffers
 
@@ -1090,7 +1090,7 @@ printf("MASTER DAC SLOT %d %d\n",ii,cdsPciModules.dacConfig[ii]);
         pLocalEpics->epicsInput.vmeReset = 0;
 
 #ifdef NO_CPU_SHUTDOWN
-        sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID);
+        sthread = kthread_create(fe_start_v3, 0, "fe_start_v3/%d", CPUID);
         if (IS_ERR(sthread)){
                 printf("Failed to kthread_create()\n");
                 return -1;
@@ -1101,7 +1101,7 @@ printf("MASTER DAC SLOT %d %d\n",ii,cdsPciModules.dacConfig[ii]);
 
 
 #ifndef NO_CPU_SHUTDOWN
-        set_fe_code_idle(fe_start, CPUID);
+        set_fe_code_idle(fe_start_v3, CPUID);
         msleep(100);
 
 	cpu_down(CPUID);
diff --git a/src/fe/moduleLoadApp.c b/src/fe/moduleLoadApp.c
index 6342f7fa5d601ddd4395e4e993396ff2fef5a6a0..a3ab2cee2adc705790ed5e9fc14719ea0ae69e55 100644
--- a/src/fe/moduleLoadApp.c
+++ b/src/fe/moduleLoadApp.c
@@ -8,7 +8,7 @@
 // These externs and "16" need to go to a header file (mbuf.h)
 extern void *kmalloc_area[16];
 extern int mbuf_allocate_area(char *name, int size, struct file *file);
-extern void *fe_start(void *arg);
+extern void *fe_start_app(void *arg);
 extern char daqArea[2*DAQ_DCU_SIZE];           // Space allocation for daqLib buffers
 
 
@@ -324,7 +324,7 @@ int rt_fe_init (void)
         pLocalEpics->epicsInput.vmeReset = 0;
 
 #ifdef NO_CPU_SHUTDOWN
-        sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID);
+        sthread = kthread_create(fe_start_app, 0, "fe_start_app/%d", CPUID);
         if (IS_ERR(sthread)){
                 printk("Failed to kthread_create()\n");
                 return -1;
@@ -336,7 +336,7 @@ int rt_fe_init (void)
 		pLocalEpics->epicsOutput.fe_status = LOCKING_CORE;
 
 #ifndef NO_CPU_SHUTDOWN
-        set_fe_code_idle(fe_start, CPUID);
+        set_fe_code_idle(fe_start_app, CPUID);
         msleep(100);
 
 	cpu_down(CPUID);
diff --git a/src/fe/moduleLoadIop.c b/src/fe/moduleLoadIop.c
index bf3ff6c0cc67e54a1b5d622b283680e30d668e07..e2f9f4638e1d75aa9c3e3de5c52f602eff46318b 100644
--- a/src/fe/moduleLoadIop.c
+++ b/src/fe/moduleLoadIop.c
@@ -9,7 +9,7 @@
 // These externs and "16" need to go to a header file (mbuf.h)
 extern void *kmalloc_area[16];
 extern int mbuf_allocate_area(char *name, int size, struct file *file);
-extern void *fe_start(void *arg);
+extern void *fe_start_iop(void *arg);
 extern char daqArea[2*DAQ_DCU_SIZE];           // Space allocation for daqLib buffers
 struct task_struct *sthread;
 
@@ -44,7 +44,7 @@ int rt_iop_init (void)
 #endif
 
 #ifndef NO_CPU_SHUTDOWN
-	// See if our CPU core is free
+    /// Verify requested core is free.
     if (is_cpu_taken_by_rcg_model(CPUID)) {
 		printk(KERN_ALERT "Error: CPU %d already taken\n", CPUID);
 		return -1;
@@ -53,6 +53,7 @@ int rt_iop_init (void)
 
 
 #ifdef DOLPHIN_TEST
+    /// Initialize the Dolphin interface
 	status = init_dolphin(2);
 	if (status != 0) {
 		return -1;
@@ -62,7 +63,7 @@ int rt_iop_init (void)
 	jj = 0;
 
 
-// Allocate EPICS memory area
+    /// Allocate EPICS memory area
 	ret =  mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0);
     if (ret < 0) {
 		printk("mbuf_allocate_area() failed; ret = %d\n", ret);
@@ -73,7 +74,7 @@ int rt_iop_init (void)
     pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace;
     pLocalEpics->epicsOutput.fe_status = 0;
 
-	// Allocate IPC memory area
+	/// Allocate IPC memory area
 	ret =  mbuf_allocate_area("ipc", 16*1024*1024, 0);
     if (ret < 0) {
 		printk("mbuf_allocate_area(ipc) failed; ret = %d\n", ret);
@@ -81,11 +82,11 @@ int rt_iop_init (void)
 	}
     _ipc_shm = (unsigned char *)(kmalloc_area[ret]);
 
-// Assign pointer to IOP/USER app comms space
+    // Assign pointer to IOP/USER app comms space
   	ioMemData = (IO_MEM_DATA *)(_ipc_shm+ 0x4000);
 
 
-// Allocate DAQ memory area
+    /// Allocate DAQ memory area
 	sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER);
     ret =  mbuf_allocate_area(fname, 64*1024*1024, 0);
     if (ret < 0) {
@@ -96,7 +97,7 @@ int rt_iop_init (void)
  	daqPtr = (struct rmIpcStr *) _daq_shm;
 
     pLocalEpics->epicsOutput.fe_status = 1;
-	// Find and initialize all PCI I/O modules **************************************************
+    /// Find and initialize all PCIe I/O modules
 	// Following I/O card info is from feCode
 	cards = sizeof(cards_used)/sizeof(cards_used[0]);
 	cdsPciModules.cards = cards;
@@ -106,7 +107,7 @@ int rt_iop_init (void)
 	cdsPciModules.dioCount = 0;
 	cdsPciModules.doCount = 0;
 
-	// Call PCI initialization routine in map.c file.
+	/// Call PCI initialization routine in map.c file.
 	status = mapPciModules(&cdsPciModules);
 	if(status < cards)
 	{
@@ -114,7 +115,7 @@ int rt_iop_init (void)
 		cardCountErr = 1;
 	}
 
-	// Master send module counds to SLAVE via ipc shm
+	/// Master send module counts to SLAVE via ipc shm
 	ioMemData->totalCards = status;
 	ioMemData->adcCount = cdsPciModules.adcCount;
 	ioMemData->dacCount = cdsPciModules.dacCount;
@@ -158,6 +159,7 @@ int rt_iop_init (void)
 // Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O.
 // Master unit only maps the RFM I/O space and passes pointers to SLAVES.
 
+    /// Map VMIC RFM cards, if any
 	ioMemData->rfmCount = cdsPciModules.rfmCount;
 	for(ii=0;ii<cdsPciModules.rfmCount;ii++)
         {
@@ -166,6 +168,7 @@ int rt_iop_init (void)
 		ioMemData->pci_rfm_dma[ii] = cdsPciModules.pci_rfm_dma[ii];
 	}
 #ifdef DOLPHIN_TEST
+    /// Send Dolphin addresses to user app processes
 	// dolphinCount is number of segments
 	ioMemData->dolphinCount = cdsPciModules.dolphinCount;
 	// dolphin read/write 0 is for local PCIe network traffic
@@ -184,7 +187,7 @@ int rt_iop_init (void)
         ioMemData->dolphinWrite[1] = 0;
 #endif
 
-	// Print out all the I/O information
+	/// Print out all the I/O information to dmesg
 	  print_io_info(&cdsPciModules);
 
 
@@ -193,7 +196,7 @@ int rt_iop_init (void)
  
     pLocalEpics->epicsOutput.fe_status = 2;
 printk("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore);
-	// Ensure EPICS running else exit
+	/// Ensure EPICS running else exit
 	for (cnt = 0;  cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) {
         	msleep(1000);
 	}
@@ -208,8 +211,9 @@ printk("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRest
 
         pLocalEpics->epicsInput.vmeReset = 0;
 
+    /// Start the controller thread
 #ifdef NO_CPU_SHUTDOWN
-        sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID);
+        sthread = kthread_create(fe_start_iop, 0, "fe_start_iop/%d", CPUID);
         if (IS_ERR(sthread)){
                 printk("Failed to kthread_create()\n");
                 return -1;
@@ -223,7 +227,7 @@ printk("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRest
     pLocalEpics->epicsOutput.fe_status = 3;
 	printk("" SYSTEM_NAME_STRING_LOWER ": Locking CPU core %d\n", CPUID);
 	// The code runs on the disabled CPU
-    set_fe_code_idle(fe_start, CPUID);
+    set_fe_code_idle(fe_start_iop, CPUID);
     msleep(100);
 	cpu_down(CPUID);
 
@@ -231,11 +235,12 @@ printk("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRest
         return 0;
 }
 
+/// Kernel module cleanup function
 void rt_iop_cleanup(void) {
 #ifndef NO_CPU_SHUTDOWN
 	extern int cpu_up(unsigned int cpu);
 
-	// Unset the code callback
+	/// Unset the code callback
         set_fe_code_idle(0, CPUID);
 #endif
 
@@ -249,11 +254,13 @@ void rt_iop_cleanup(void) {
         msleep(1000);
 
 #ifdef DOLPHIN_TEST
+    /// Cleanup Dolphin card connections
 	finish_dolphin();
 #endif
 
 #ifndef NO_CPU_SHUTDOWN
 
+    /// Bring the CPU core back on line
 	// Unset the code callback
         set_fe_code_idle(0, CPUID);
 	// printkl("Will bring back CPU %d\n", CPUID);
diff --git a/src/fe/rcguser.c b/src/fe/rcguser.c
index 64049a9b932f3d019936da6d2ba7d363b02a1e6a..a230c63af2fdadb006914da49936b0786fd6a333 100644
--- a/src/fe/rcguser.c
+++ b/src/fe/rcguser.c
@@ -1,5 +1,5 @@
 ///	@file moduleLoad.c
-///	@brief File contains startup routines for real-time code.
+///	@brief File contains startup routines for running user app in user space.
 
 #include <unistd.h>
 #include <ctype.h>
@@ -20,7 +20,7 @@
 #include "moduleLoadCommon.c"
 
 // These externs and "16" need to go to a header file (mbuf.h)
-extern int fe_start();
+extern int fe_start_app_user();
 extern char daqArea[2*DAQ_DCU_SIZE];           // Space allocation for daqLib buffers
 extern char *addr;
 
@@ -374,7 +374,7 @@ int main (int argc, char **argv)
 	}
 
         pLocalEpics->epicsInput.vmeReset = 0;
-	fe_start();
+	fe_start_app_user();
 
         return 0;
 }
diff --git a/src/fe/rcguserIop.c b/src/fe/rcguserIop.c
index cc6cac227c3259971455e74511a5ea7e271b7561..ec936dd78eef84b89168d9bd6a645a3914e91a49 100644
--- a/src/fe/rcguserIop.c
+++ b/src/fe/rcguserIop.c
@@ -1,5 +1,5 @@
-///	@file moduleLoad.c
-///	@brief File contains startup routines for real-time code.
+///	@file rcguserIop.c
+///	@brief File contains startup routines for IOP running in user space.
 
 #include <unistd.h>
 #include <ctype.h>
@@ -19,7 +19,7 @@
 
 
 // These externs and "16" need to go to a header file (mbuf.h)
-extern int fe_start();
+extern int fe_start_iop_user();
 extern char daqArea[2*DAQ_DCU_SIZE];           // Space allocation for daqLib buffers
 extern char *addr;
 extern int cycleOffset;
@@ -429,7 +429,7 @@ printf("MASTER DAC SLOT %d %d\n",ii,cdsPciModules.dacConfig[ii]);
 	}
 
         pLocalEpics->epicsInput.vmeReset = 0;
-	fe_start();
+	fe_start_iop_user();
 
         return 0;
 }
diff --git a/src/include/drv/app_adc_read.c b/src/include/drv/app_adc_read.c
index c788cd64ac337a8144334a23ee9dbf5231092120..afb9cc043277be1df7526c6159d70b34f416b164 100644
--- a/src/include/drv/app_adc_read.c
+++ b/src/include/drv/app_adc_read.c
@@ -12,10 +12,10 @@ inline int app_adc_read (int ioMemCtr,int ioClk,adcInfo_t *adcinfo,int cpuClk[])
 		for(jj=0;jj<cdsPciModules.adcCount;jj++)
 		{
 			mm = cdsPciModules.adcConfig[jj];
-	    	rdtscll(cpuClk[CPU_TIME_RDY_ADC]);
+	    	cpuClk[CPU_TIME_RDY_ADC] = rdtsc_ordered();
 			/// - ---- Wait for proper timestamp in shared memory, indicating data ready.
             do{
-		   		rdtscll(cpuClk[CPU_TIME_ADC_WAIT]);
+	    			cpuClk[CPU_TIME_ADC_WAIT] = rdtsc_ordered();
 				adcinfo->adcWait = (cpuClk[CPU_TIME_ADC_WAIT] - cpuClk[CPU_TIME_RDY_ADC])/CPURATE;
             }while((ioMemData->iodata[mm][ioMemCtr].cycle != ioClk) && (adcinfo->adcWait < MAX_ADC_WAIT_SLAVE));
 			timeSec = ioMemData->iodata[mm][ioMemCtr].timeSec;
diff --git a/src/include/drv/daqLib.c b/src/include/drv/daqLib.c
index e77c1d8cd91e47a2fd5dc50e8d0130e61e0d92f0..9217b16b6d6d6e9985edc3bdfa4457c94aaa756a 100644
--- a/src/include/drv/daqLib.c
+++ b/src/include/drv/daqLib.c
@@ -1,223 +1,328 @@
-/*!	\file daqLib.c                                                	
+/*!	\file daqLib.c
  *	\brief File contains routines to support DAQ on realtime systems. \n
  *	\author R.Bork, A. Ivanov
 */
 
-volatile DAQ_INFO_BLOCK *pInfo;		///< Ptr to DAQ config in shmem.
-extern volatile char *_epics_shm;	///< Ptr to EPICS shmem block
-extern long daqBuffer;			///< Address of daqLib swing buffers.
-extern char *_daq_shm;			///< Pointer to DAQ base address in shared memory.
-struct rmIpcStr *dipc;			///< Pointer to DAQ IPC data in shared memory.
-struct cdsDaqNetGdsTpNum *tpPtr;	///< Pointer to TP table in shared memory.
-char *daqShmPtr;			///< Pointer to DAQ data in shared memory.
-char *pEpicsIntData;			///< Pointer to EPICS integer type data in shared memory.
-char *pEpicsDblData;			///< Pointer to EPICS double type data in shared memory.
-unsigned int curDaqBlockSize;		///< Total DAQ data rate diag
+volatile DAQ_INFO_BLOCK *pInfo;   ///< Ptr to DAQ config in shmem.
+extern volatile char *_epics_shm; ///< Ptr to EPICS shmem block
+extern long daqBuffer;            ///< Address of daqLib swing buffers.
+extern char *_daq_shm; ///< Pointer to DAQ base address in shared memory.
+struct rmIpcStr *dipc; ///< Pointer to DAQ IPC data in shared memory.
+struct cdsDaqNetGdsTpNum *tpPtr; ///< Pointer to TP table in shared memory.
+char *daqShmPtr;                 ///< Pointer to DAQ data in shared memory.
+char *pEpicsIntData; ///< Pointer to EPICS integer type data in shared memory.
+char *pEpicsDblData; ///< Pointer to EPICS double type data in shared memory.
+unsigned int curDaqBlockSize; ///< Total DAQ data rate diag
 // Added to get EPICS data for RCG V2.8
-char *pEpicsInt;				// Pointer to current DAQ data in shared memory.
+char *pEpicsInt; // Pointer to current DAQ data in shared memory.
 char *pEpicsInt1;
-float *pEpicsFloat;				// Pointer to current DAQ data in shared memory.
+float *pEpicsFloat; // Pointer to current DAQ data in shared memory.
 double *pEpicsDblData1;
 
 int daqConfig(struct DAQ_INFO_BLOCK *, struct DAQ_INFO_BLOCK *, char *);
-int loadLocalTable(DAQ_XFER_INFO *, DAQ_LKUP_TABLE [], int , DAQ_INFO_BLOCK *, DAQ_RANGE *);
-int daqWrite(int,int,struct DAQ_RANGE,int,double *[],struct FILT_MOD *,int,int [],double [],char *);
-
-inline
-double htond(double in) {
-    double retVal;
-    char* p = (char*)&retVal;
-    char* i = (char*)&in;
-    p[0] = i[7];
-    p[1] = i[6];
-    p[2] = i[5];
-    p[3] = i[4];
-
-    p[4] = i[3];
-    p[5] = i[2];
-    p[6] = i[1];
-    p[7] = i[0];
-
-    return retVal;
+int loadLocalTable(DAQ_XFER_INFO *, DAQ_LKUP_TABLE[], int, DAQ_INFO_BLOCK *,
+                   DAQ_RANGE *);
+int daqWrite(int, int, struct DAQ_RANGE, int, double *[], struct FILT_MOD *,
+             int, int[], double[], char *);
+
+inline double htond(double in) {
+  double retVal;
+  char *p = (char *)&retVal;
+  char *i = (char *)&in;
+  p[0] = i[7];
+  p[1] = i[6];
+  p[2] = i[5];
+  p[3] = i[4];
+
+  p[4] = i[3];
+  p[5] = i[2];
+  p[6] = i[1];
+  p[7] = i[0];
+
+  return retVal;
 }
 
-
 /* ******************************************************************** */
 /* Routine to connect and write to LIGO DAQ system       		*/
 /* ******************************************************************** */
 ///	@author R.Bork, A. Ivanov\n
-///	@brief This function provides for reading GDS TP/EXC and writing DAQ data. \n
-///	@detail For additional information in LIGO DCC, see <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=8037">T0900638 CDS Real-time DAQ Software</a>
-///	@param[in] flag 		Initialization flag (1=Init call, 0 = run)
-///	@param[in] dcuId		DAQ Data unit ID - unique within a control system
-///	@param[in] daqRange		Struct defining fron end valid test point and exc ranges.
+///	@brief This function provides for reading GDS TP/EXC and writing DAQ
+///data. \n
+///	@detail For additional information in LIGO DCC, see <a
+///href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=8037">T0900638
+///CDS Real-time DAQ Software</a>
+///	@param[in] flag 		Initialization flag (1=Init call, 0 =
+///run)
+///	@param[in] dcuId		DAQ Data unit ID - unique within a control
+///system
+///	@param[in] daqRange		Struct defining fron end valid test point
+///and exc ranges.
 ///	@param[in] sysRate		Data rate of the code / 16
-///	@param[in] *pFloatData[]	Pointer to TP data not associated with filter modules.
+///	@param[in] *pFloatData[]	Pointer to TP data not associated with
+///filter modules.
 ///	@param[in] *dspPtr		Pointer to array of filter module data.
 ///	@param[in] netStatus		Status of DAQ network
-///	@param[out] gdsMonitor[]	Array to return values of GDS TP/EXC selections.
-///	@param[out] excSignals[]	Array to write EXC signals not associated with filter modules.
+///	@param[out] gdsMonitor[]	Array to return values of GDS TP/EXC
+///selections.
+///	@param[out] excSignals[]	Array to write EXC signals not associated
+///with filter modules.
 ///	@return	Total size of data transmitted in KB/sec.
 
-int daqWrite(int flag,
-	     int dcuId,
-	     DAQ_RANGE daqRange,
-	     int sysRate,
-	     double *pFloatData[],
-	     FILT_MOD *dspPtr,
-	     int netStatus,
-	     int gdsMonitor[],
-	     double excSignal[],
-	     char *pEpics)
-{
-int ii,jj,kk;			/* Loop counters.			*/
-int status;			/* Return value from called routines.	*/
-unsigned int mydatatype;
-double dWord;			/* Temp value for storage of DAQ values */
-static int daqBlockNum;		/* 1-16, tracks DAQ cycle.		*/
-static int daqXmitBlockNum;	/* 1-16, tracks shmem DAQ block to write to.	*/
-static int excBlockNum;		/* 1-16, tracks EXC block to read from.	*/
-static int excDataSize;
-static DAQ_XFER_INFO xferInfo;
-static DAQ_LKUP_TABLE localTable[DCU_MAX_CHANNELS];
-static DAQ_LKUP_TABLE excTable[DCU_MAX_CHANNELS];
-static volatile char *pWriteBuffer;	/* Ptr to swing buff to write data	*/
-static int phase;		/* 0-1, switches swing buffers.		*/
-static int daqSlot;		/* 0-sysRate, data slot to write data	*/
-static int excSlot;		/* 0-sysRate, slot to read exc data	*/
-static DAQ_INFO_BLOCK dataInfo; /* Local DAQ config info buffer.	*/
-static int tpStart;		/* Marks address of first TP data	*/
-static volatile GDS_CNTRL_BLOCK *gdsPtr;  /* Ptr to shm to pass TP info to DAQ */
-static volatile char *exciteDataPtr;	  /* Ptr to EXC data in shmem.	*/
-static int validTp = 0;		/* Number of valid GDS sigs selected.	*/
-static int validTpNet = 0;		/* Number of valid GDS sigs selected.	*/
-static int validEx;		/* EXC signal set status indicator.	*/
-static int tpNum[DAQ_GDS_MAX_TP_ALLOWED]; 	/* TP/EXC selects to send to FB.	*/
-static int tpNumNet[DAQ_GDS_MAX_TP_ALLOWED]; 	/* TP/EXC selects to send to FB.	*/
-static int totalChans;		/* DAQ + TP + EXC chans selected.	*/
-int *statusPtr;
-volatile float *dataPtr;	/* Ptr to excitation chan data.		*/
-int exChanOffset;		/* shmem offset to next EXC value.	*/
-int tpx;
-static int buf_size;
-int i;
-int ltSlot;
-unsigned int exc;
-unsigned int tpn;
-int slot;
-int num_tps;
-unsigned int tpnum[DAQ_GDS_MAX_TP_ALLOWED];		// Current TP nums
-unsigned int excnum[DAQ_GDS_MAX_TP_ALLOWED];	// Current EXC nums
+int daqWrite(int flag, int dcuId, DAQ_RANGE daqRange, int sysRate,
+             double *pFloatData[], FILT_MOD *dspPtr, int netStatus,
+             int gdsMonitor[], double excSignal[], char *pEpics) {
+  int ii, jj, kk; /* Loop counters.			*/
+  int status;     /* Return value from called routines.	*/
+  unsigned int mydatatype;
+  double dWord;               /* Temp value for storage of DAQ values */
+  static int daqBlockNum;     /* 1-16, tracks DAQ cycle.		*/
+  static int daqXmitBlockNum; /* 1-16, tracks shmem DAQ block to write to.
+                                 */
+  static int excBlockNum;     /* 1-16, tracks EXC block to read from.	*/
+  static int excDataSize;
+  static DAQ_XFER_INFO xferInfo;
+  static DAQ_LKUP_TABLE localTable[DCU_MAX_CHANNELS];
+  static DAQ_LKUP_TABLE excTable[DCU_MAX_CHANNELS];
+  static volatile char *pWriteBuffer; /* Ptr to swing buff to write data
+                                         */
+  static int phase;                   /* 0-1, switches swing buffers.		*/
+  static int daqSlot;                 /* 0-sysRate, data slot to write data	*/
+  static int excSlot;                 /* 0-sysRate, slot to read exc data	*/
+  static DAQ_INFO_BLOCK dataInfo;     /* Local DAQ config info buffer.	*/
+  static int tpStart;                 /* Marks address of first TP data	*/
+  static volatile GDS_CNTRL_BLOCK
+      *gdsPtr;                         /* Ptr to shm to pass TP info to DAQ */
+  static volatile char *exciteDataPtr; /* Ptr to EXC data in shmem.	*/
+  static int validTp = 0;              /* Number of valid GDS sigs selected.	*/
+  static int validTpNet = 0;           /* Number of valid GDS sigs selected.	*/
+  static int validEx;                  /* EXC signal set status indicator.	*/
+  static int
+      tpNum[DAQ_GDS_MAX_TP_ALLOWED]; /* TP/EXC selects to send to FB.	*/
+  static int tpNumNet
+      [DAQ_GDS_MAX_TP_ALLOWED]; /* TP/EXC selects to send to FB.	*/
+  static int totalChans;        /* DAQ + TP + EXC chans selected.	*/
+  int *statusPtr;
+  volatile float *dataPtr; /* Ptr to excitation chan data.		*/
+  int exChanOffset;        /* shmem offset to next EXC value.	*/
+  int tpx;
+  static int buf_size;
+  int i;
+  int ltSlot;
+  unsigned int exc;
+  unsigned int tpn;
+  int slot;
+  int num_tps;
+  unsigned int tpnum[DAQ_GDS_MAX_TP_ALLOWED];  // Current TP nums
+  unsigned int excnum[DAQ_GDS_MAX_TP_ALLOWED]; // Current EXC nums
 
 #ifdef CORE_BIQUAD
-// BIQUAD Decimation filter coefficient definitions.
-// dCOEFF 2x      *************************************************************************
-static double dCoeff2x[13] = {0.02717257186578,
-        -0.1159055409088, -0.40753832312918, 2.66236735378793, 3.37073457156755,
-        -0.49505157452475, -1.10461941102831, 1.40184470311617, 1.79227686661261,
-        -0.74143396593712, -1.62740819248313, 0.72188475979666, 0.83591053325065};
-
-// dCOEFF 4x      *************************************************************************
-static double dCoeff4x[13] = {0.00426219526013,
-        0.46640482430571, -0.10620935923005, 2.50932081620118, 2.93670663266542,
-        0.43602772908265, -0.31016854747127, 0.75143527373544, 1.00523899718152,
-        0.44571894955428, -0.47692045639835, 0.36664098129003, 0.4440015753374};
-
-// dCOEFF 8x      *************************************************************************
-static double dCoeff8x[13] = {0.00162185538923,
-        0.73342532779703, -0.02862365091314, 1.44110125961504, 1.67905228090487,
-        0.77657563380963, -0.08304311675394, 0.18851328163424, 0.32889453107067,
-        0.83213081484618, -0.12573495191273, 0.0940911979108501, 0.13622543115194};
-
-// dCOEFF 16x     *************************************************************************
-static double dCoeff16x[13] = {0.00112590539483,
-        0.86616831686611, -0.00753654634986012, 0.48586805026482, 0.61216318704885,
-        0.90508101474565, -0.0215349711544799, 0.0149886842581499, 0.08837269835802,
-        0.94631370100442, -0.0320417955561, 0.0141281606027401, 0.0357726640422202};
-
-// dCOEFF 32x     *************************************************************************
-static double dCoeff32x[13] = {0.00102945292275,
-        0.93288074072411, -0.00194092797014001, 0.10751900551591, 0.17269733682166,
-        0.9570539169953, -0.00548573773340011, -0.0149997987966302, 0.0224605464746699,
-        0.98100244642901, -0.00807148639261013, -0.00189235941040011, 0.00903370776797985};
-
-// dCOEFF 64x     *************************************************************************
-static double dCoeff64x[13] = {0.00101894798776,
-        0.96638168022541, -0.000492974627960052, 0.01147570619135, 0.04460105133798,
-        0.97969775930388, -0.00138449271550001, -0.0132857101503898, 0.00563203783023014,
-        0.99249184543014, -0.0020244997813601, -0.00322227927422025, 0.00226137551427974};
-
-// dCOEFF 128x    *************************************************************************
-static double dCoeff128x[13] = {0.00102359688929,
-        0.98317523053482, -0.000124254191099959, -0.00545789721985002, 0.01124261805423,
-        0.9901470788001, -0.000347773996469902, -0.00809690612593994, 0.00140824107749005,
-        0.9967468102523, -0.000506888877139899, -0.00218112074794985, 0.000565180122610309};
-
-// dCOEFF 256x    *************************************************************************
-static double dCoeff256x[13] = {0.00102849104272,
-        0.99158359864769, -3.11926170200039e-05, -0.00556878740432998, 0.00281642133096005,
-        0.99514878857652, -8.7150981279982e-05, -0.00441208984599983, 0.000351970596200069,
-        0.99849900371282, -0.000126813612729926, -0.00123294150072994, 0.000141241173720053};
+  // BIQUAD Decimation filter coefficient definitions.
+  // dCOEFF 2x
+  // *************************************************************************
+  static double dCoeff2x[13] = {
+      0.02717257186578, -0.1159055409088,  -0.40753832312918, 2.66236735378793,
+      3.37073457156755, -0.49505157452475, -1.10461941102831, 1.40184470311617,
+      1.79227686661261, -0.74143396593712, -1.62740819248313, 0.72188475979666,
+      0.83591053325065};
+
+  // dCOEFF 4x
+  // *************************************************************************
+  static double dCoeff4x[13] = {
+      0.00426219526013, 0.46640482430571, -0.10620935923005, 2.50932081620118,
+      2.93670663266542, 0.43602772908265, -0.31016854747127, 0.75143527373544,
+      1.00523899718152, 0.44571894955428, -0.47692045639835, 0.36664098129003,
+      0.4440015753374};
+
+  // dCOEFF 8x
+  // *************************************************************************
+  static double dCoeff8x[13] = {
+      0.00162185538923, 0.73342532779703, -0.02862365091314, 1.44110125961504,
+      1.67905228090487, 0.77657563380963, -0.08304311675394, 0.18851328163424,
+      0.32889453107067, 0.83213081484618, -0.12573495191273, 0.0940911979108501,
+      0.13622543115194};
+
+  // dCOEFF 16x
+  // *************************************************************************
+  static double dCoeff16x[13] = {
+      0.00112590539483,    0.86616831686611,   -0.00753654634986012,
+      0.48586805026482,    0.61216318704885,   0.90508101474565,
+      -0.0215349711544799, 0.0149886842581499, 0.08837269835802,
+      0.94631370100442,    -0.0320417955561,   0.0141281606027401,
+      0.0357726640422202};
+
+  // dCOEFF 32x
+  // *************************************************************************
+  static double dCoeff32x[13] = {
+      0.00102945292275,     0.93288074072411,     -0.00194092797014001,
+      0.10751900551591,     0.17269733682166,     0.9570539169953,
+      -0.00548573773340011, -0.0149997987966302,  0.0224605464746699,
+      0.98100244642901,     -0.00807148639261013, -0.00189235941040011,
+      0.00903370776797985};
+
+  // dCOEFF 64x
+  // *************************************************************************
+  static double dCoeff64x[13] = {
+      0.00101894798776,     0.96638168022541,    -0.000492974627960052,
+      0.01147570619135,     0.04460105133798,    0.97969775930388,
+      -0.00138449271550001, -0.0132857101503898, 0.00563203783023014,
+      0.99249184543014,     -0.0020244997813601, -0.00322227927422025,
+      0.00226137551427974};
+
+  // dCOEFF 128x
+  // *************************************************************************
+  static double dCoeff128x[13] = {
+      0.00102359688929,      0.98317523053482,      -0.000124254191099959,
+      -0.00545789721985002,  0.01124261805423,      0.9901470788001,
+      -0.000347773996469902, -0.00809690612593994,  0.00140824107749005,
+      0.9967468102523,       -0.000506888877139899, -0.00218112074794985,
+      0.000565180122610309};
+
+  // dCOEFF 256x
+  // *************************************************************************
+  static double dCoeff256x[13] = {
+      0.00102849104272,     0.99158359864769,      -3.11926170200039e-05,
+      -0.00556878740432998, 0.00281642133096005,   0.99514878857652,
+      -8.7150981279982e-05, -0.00441208984599983,  0.000351970596200069,
+      0.99849900371282,     -0.000126813612729926, -0.00123294150072994,
+      0.000141241173720053};
 #else
-// SOS Decimation filter coefficient definitions.
-// dCOEFF 2x      *************************************************************************
-static double dCoeff2x[13] = {0.02717257186578,
-        -0.8840944590912, 0.29163278222038, 1.77827289469673, 1,
-        -0.50494842547525, 0.60956783650356, 0.89689627764092, 1,
-        -0.25856603406288, 0.88597422654601, 0.46331872573378, 1};
-
-// dCOEFF 4x      *************************************************************************
-static double dCoeff4x[13] = {0.00426219526013,
-        -1.46640482430571, 0.57261418353576, 1.04291599189547, 1,
-        -1.43602772908265, 0.74619627655392, -0.68459245534721, 1,
-        -1.44571894955428, 0.92263940595263, -1.07907796826425, 1};
-
-// dCOEFF 8x      *************************************************************************
-static double dCoeff8x[13] = {0.00162185538923,
-        -1.73342532779703, 0.76204897871017, -0.29232406818199, 1,
-        -1.77657563380963, 0.85961875056357, -1.58806235217539, 1,
-        -1.83213081484618, 0.95786576675891, -1.73803961693533, 1};
-
-// dCOEFF 16x     *************************************************************************
-static double dCoeff16x[13] = {0.00112590539483,
-        -1.86616831686611, 0.87370486321597, -1.38030026660129, 1,
-        -1.90508101474565, 0.92661598590013, -1.8900923304875, 1,
-        -1.94631370100442, 0.97835549656052, -1.93218554040168, 1};
-
-// dCOEFF 32x     *************************************************************************
-static double dCoeff32x[13] = {0.00102945292275,
-        -1.93288074072411, 0.93482166869425, -1.8253617352082, 1,
-        -1.9570539169953, 0.9625396547287, -1.97205371579193, 1,
-        -1.98100244642901, 0.98907393282162, -1.98289480583941, 1};
-
-// dCOEFF 64x     *************************************************************************
-static double dCoeff64x[13] = {0.00101894798776,
-        -1.96638168022541, 0.96687465485337, -1.95490597403406, 1,
-        -1.97969775930388, 0.98108225201938, -1.99298346945427, 1,
-        -1.99249184543014, 0.9945163452115, -1.99571412470436, 1};
-
-// dCOEFF 128x    *************************************************************************
-static double dCoeff128x[13] = {0.00102359688929,
-        -1.98317523053482, 0.98329948472592, -1.98863312775467, 1,
-        -1.9901470788001, 0.99049485279657, -1.99824398492604, 1,
-        -1.9967468102523, 0.99725369912944, -1.99892793100025, 1};
-
-// dCOEFF 256x    *************************************************************************
-static double dCoeff256x[13] = {0.00102849104272,
-        -1.99158359864769, 0.99161479126471, -1.99715238605202, 1,
-        -1.99514878857652, 0.9952359395578, -1.99956087842252, 1,
-        -1.99849900371282, 0.99862581732555, -1.99973194521355, 1};
+  // SOS Decimation filter coefficient definitions.
+  // dCOEFF 2x
+  // *************************************************************************
+  static double dCoeff2x[13] = {0.02717257186578,
+                                -0.8840944590912,
+                                0.29163278222038,
+                                1.77827289469673,
+                                1,
+                                -0.50494842547525,
+                                0.60956783650356,
+                                0.89689627764092,
+                                1,
+                                -0.25856603406288,
+                                0.88597422654601,
+                                0.46331872573378,
+                                1};
+
+  // dCOEFF 4x
+  // *************************************************************************
+  static double dCoeff4x[13] = {0.00426219526013,
+                                -1.46640482430571,
+                                0.57261418353576,
+                                1.04291599189547,
+                                1,
+                                -1.43602772908265,
+                                0.74619627655392,
+                                -0.68459245534721,
+                                1,
+                                -1.44571894955428,
+                                0.92263940595263,
+                                -1.07907796826425,
+                                1};
+
+  // dCOEFF 8x
+  // *************************************************************************
+  static double dCoeff8x[13] = {0.00162185538923,
+                                -1.73342532779703,
+                                0.76204897871017,
+                                -0.29232406818199,
+                                1,
+                                -1.77657563380963,
+                                0.85961875056357,
+                                -1.58806235217539,
+                                1,
+                                -1.83213081484618,
+                                0.95786576675891,
+                                -1.73803961693533,
+                                1};
+
+  // dCOEFF 16x
+  // *************************************************************************
+  static double dCoeff16x[13] = {0.00112590539483,
+                                 -1.86616831686611,
+                                 0.87370486321597,
+                                 -1.38030026660129,
+                                 1,
+                                 -1.90508101474565,
+                                 0.92661598590013,
+                                 -1.8900923304875,
+                                 1,
+                                 -1.94631370100442,
+                                 0.97835549656052,
+                                 -1.93218554040168,
+                                 1};
+
+  // dCOEFF 32x
+  // *************************************************************************
+  static double dCoeff32x[13] = {0.00102945292275,
+                                 -1.93288074072411,
+                                 0.93482166869425,
+                                 -1.8253617352082,
+                                 1,
+                                 -1.9570539169953,
+                                 0.9625396547287,
+                                 -1.97205371579193,
+                                 1,
+                                 -1.98100244642901,
+                                 0.98907393282162,
+                                 -1.98289480583941,
+                                 1};
+
+  // dCOEFF 64x
+  // *************************************************************************
+  static double dCoeff64x[13] = {0.00101894798776,
+                                 -1.96638168022541,
+                                 0.96687465485337,
+                                 -1.95490597403406,
+                                 1,
+                                 -1.97969775930388,
+                                 0.98108225201938,
+                                 -1.99298346945427,
+                                 1,
+                                 -1.99249184543014,
+                                 0.9945163452115,
+                                 -1.99571412470436,
+                                 1};
+
+  // dCOEFF 128x
+  // *************************************************************************
+  static double dCoeff128x[13] = {0.00102359688929,
+                                  -1.98317523053482,
+                                  0.98329948472592,
+                                  -1.98863312775467,
+                                  1,
+                                  -1.9901470788001,
+                                  0.99049485279657,
+                                  -1.99824398492604,
+                                  1,
+                                  -1.9967468102523,
+                                  0.99725369912944,
+                                  -1.99892793100025,
+                                  1};
+
+  // dCOEFF 256x
+  // *************************************************************************
+  static double dCoeff256x[13] = {0.00102849104272,
+                                  -1.99158359864769,
+                                  0.99161479126471,
+                                  -1.99715238605202,
+                                  1,
+                                  -1.99514878857652,
+                                  0.9952359395578,
+                                  -1.99956087842252,
+                                  1,
+                                  -1.99849900371282,
+                                  0.99862581732555,
+                                  -1.99973194521355,
+                                  1};
 #endif
 
-// History buffers for decimation IIR filters
-static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY];
-
-
+  // History buffers for decimation IIR filters
+  static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY];
 
-
-// ************************************************************************************** 
-/// If flag input is 1, then this is a startup initialization request from controller code.
-  if(flag == DAQ_CONNECT)	/* Initialize DAQ connection */
+  // **************************************************************************************
+  /// If flag input is 1, then this is a startup initialization request from
+  /// controller code.
+  if (flag == DAQ_CONNECT) /* Initialize DAQ connection */
   {
 
     /* First block to write out is last from previous second */
@@ -231,134 +336,150 @@ static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY];
     excSlot = 0;
 
     ///	\> CDS standard IIR filters will be used for decimation filtering from
-    /// the native application rate down to DAQ sample rate. \n 
+    /// the native application rate down to DAQ sample rate. \n
     /// \>\> Need to clear the decimation filter histories.
-    for(ii=0;ii<DCU_MAX_CHANNELS;ii++)
-	for(jj=0;jj<MAX_HISTRY;jj++)
-	     dHistory[ii][jj] = 0.0;
+    for (ii = 0; ii < DCU_MAX_CHANNELS; ii++)
+      for (jj = 0; jj < MAX_HISTRY; jj++)
+        dHistory[ii][jj] = 0.0;
 
     /// \> Setup Pointers to the various shared memories:\n
     /// ----  Assign Ptr to data shared memory to network driver (mx_stream) \n
     daqShmPtr = _daq_shm + CDS_DAQ_NET_DATA_OFFSET;
-    buf_size = DAQ_DCU_BLOCK_SIZE*2;
+    buf_size = DAQ_DCU_BLOCK_SIZE * 2;
     pWriteBuffer = (volatile char *)daqShmPtr;
-      pWriteBuffer += buf_size * 15;
+    pWriteBuffer += buf_size * 15;
     /// ----  Setup Ptr to interprocess comms with network driver
     dipc = (struct rmIpcStr *)(_daq_shm + CDS_DAQ_NET_IPC_OFFSET);
     /// ----  Setup Ptr to awgtpman shared memory (TP number table)
-    tpPtr = (struct cdsDaqNetGdsTpNum *)(_daq_shm + CDS_DAQ_NET_GDS_TP_TABLE_OFFSET);
+    tpPtr = (struct cdsDaqNetGdsTpNum *)(_daq_shm +
+                                         CDS_DAQ_NET_GDS_TP_TABLE_OFFSET);
 
     /// ----  Set up pointer to DAQ configuration information in shmem */
     pInfo = (DAQ_INFO_BLOCK *)(_epics_shm + DAQ_INFO_ADDRESS);
     /// ----  Set pointer to shared mem to pass GDS info to DAQ
     gdsPtr = (GDS_CNTRL_BLOCK *)(_epics_shm + DAQ_GDS_BLOCK_ADD);
     // Set pointer to EXC data in shmem.
-    if(sysRate < DAQ_16K_SAMPLE_SIZE)
-	{
-    	exciteDataPtr = (char *)(_epics_shm + DATA_OFFSET_DCU(DCU_ID_EX_2K));
-	}
-    else {
-    	exciteDataPtr = (char *)(_epics_shm + DATA_OFFSET_DCU(DCU_ID_EX_16K));
+    if (sysRate < DAQ_16K_SAMPLE_SIZE) {
+      exciteDataPtr = (char *)(_epics_shm + DATA_OFFSET_DCU(DCU_ID_EX_2K));
+    } else {
+      exciteDataPtr = (char *)(_epics_shm + DATA_OFFSET_DCU(DCU_ID_EX_16K));
     }
     excDataSize = 4 + 4 * sysRate;
 
-
     // Clear the reconfiguration flag in shmem.
     pInfo->reconfig = 0;
 
-    // Configure data channels *****************************************************
+    // Configure data channels
+    // *****************************************************
     // Return error if configuration is incorrect.
     /// \> Load DAQ configuration info from memory shared with EPICS
-    if((xferInfo.crcLength = daqConfig(&dataInfo,pInfo,pEpics)) == -1) return(-1);
+    if ((xferInfo.crcLength = daqConfig(&dataInfo, pInfo, pEpics)) == -1)
+      return (-1);
 
     /// \> Load local table information with channel info
-    if((status = loadLocalTable(&xferInfo,localTable,sysRate,&dataInfo,&daqRange)) == -1) return(-1);
+    if ((status = loadLocalTable(&xferInfo, localTable, sysRate, &dataInfo,
+                                 &daqRange)) == -1)
+      return (-1);
 
     // Set the start of TP data after DAQ data.
     tpStart = xferInfo.offsetAccum;
     totalChans = dataInfo.numChans;
 
     /// \> Clear out the GDS TP selections.
-    if (sysRate < DAQ_16K_SAMPLE_SIZE) tpx = 3; else tpx = 2;
-    for (ii=0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++) gdsPtr->tp[tpx][0][ii] = 0;
-    if(sysRate < DAQ_16K_SAMPLE_SIZE) tpx = 1; else tpx = 0;
-    for (ii=0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++) gdsPtr->tp[tpx][0][ii] = 0;
+    if (sysRate < DAQ_16K_SAMPLE_SIZE)
+      tpx = 3;
+    else
+      tpx = 2;
+    for (ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++)
+      gdsPtr->tp[tpx][0][ii] = 0;
+    if (sysRate < DAQ_16K_SAMPLE_SIZE)
+      tpx = 1;
+    else
+      tpx = 0;
+    for (ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++)
+      gdsPtr->tp[tpx][0][ii] = 0;
 
     /// \> Clear the GDS TP lookup table
     for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) {
-	tpNum[i] = 0;
-	tpNumNet[i] = 0;
+      tpNum[i] = 0;
+      tpNumNet[i] = 0;
     }
     validTp = 0;
     validTpNet = 0;
 
-    //printf("at connect TPnum[0]=%d\n", tpNum[0]);
+    // printf("at connect TPnum[0]=%d\n", tpNum[0]);
   } ///  End DAQ CONNECT INITIALIZATION ******************************
 
-/* ******************************************************************************** */
-/* Write Data to FB 			******************************************* */
-/* ******************************************************************************** */
-/// If flag=0, data is to be acquired. This is called every code cycle by controller.c
-/// ** Data Acquisition Mode ********************************************************
-  if(flag == DAQ_WRITE)
-  {
-    /// \> Calc data offset into current write swing buffer 
+  /* ********************************************************************************
+   */
+  /* Write Data to FB 			*******************************************
+   */
+  /* ********************************************************************************
+   */
+  /// If flag=0, data is to be acquired. This is called every code cycle by
+  /// controller.c
+  /// ** Data Acquisition Mode
+  /// ********************************************************
+  if (flag == DAQ_WRITE) {
+    /// \> Calc data offset into current write swing buffer
     daqSlot = (daqSlot + 1) % sysRate;
 
-
-    /// \> Write data into local swing buffer 
-    for(ii=0;ii<totalChans;ii++)
-    {
+    /// \> Write data into local swing buffer
+    for (ii = 0; ii < totalChans; ii++) {
 
       dWord = 0;
       /// \> Read data to a local variable, either from a FM TP or other TP */
-      if(localTable[ii].type == DAQ_SRC_FM_TP)
+      if (localTable[ii].type == DAQ_SRC_FM_TP)
       /* Data if from filter module testpoint */
       {
-	switch(localTable[ii].sigNum)
-	{
-	  case 0:
-	    dWord = dspPtr->data[localTable[ii].fmNum].filterInput;
-	    break;
-	  case 1:
-	    dWord = dspPtr->data[localTable[ii].fmNum].inputTestpoint;
-	    break;
-	  case 2:
-	    dWord = dspPtr->data[localTable[ii].fmNum].testpoint;
-	    break;
- 	  default:
-	    dWord = 0.0;
-	    break;
-	}
-      }
-      else if(localTable[ii].type == DAQ_SRC_NFM_TP)
+        switch (localTable[ii].sigNum) {
+        case 0:
+          dWord = dspPtr->data[localTable[ii].fmNum].filterInput;
+          break;
+        case 1:
+          dWord = dspPtr->data[localTable[ii].fmNum].inputTestpoint;
+          break;
+        case 2:
+          dWord = dspPtr->data[localTable[ii].fmNum].testpoint;
+          break;
+        default:
+          dWord = 0.0;
+          break;
+        }
+      } else if (localTable[ii].type == DAQ_SRC_NFM_TP)
       /* Data is from non filter module  testpoint */
       {
-	    dWord = *(pFloatData[localTable[ii].sigNum]);
-      }
-      else if(localTable[ii].type == DAQ_SRC_FM_EXC)
+        dWord = *(pFloatData[localTable[ii].sigNum]);
+      } else if (localTable[ii].type == DAQ_SRC_FM_EXC)
       /* Data is from filter module excitation */
       {
-	    dWord = dspPtr->data[localTable[ii].fmNum].exciteInput;
+        dWord = dspPtr->data[localTable[ii].fmNum].exciteInput;
       } else if (localTable[ii].type == DAQ_SRC_NFM_EXC) {
-	      // Extra excitation
-	      dWord = excSignal[localTable[ii].fmNum];
+        // Extra excitation
+        dWord = excSignal[localTable[ii].fmNum];
       }
 
-      /// \> Perform decimation filtering, if required.
+/// \> Perform decimation filtering, if required.
 #ifdef CORE_BIQUAD
 #define iir_filter iir_filter_biquad
 #endif
-      if(dataInfo.tp[ii].dataType != DAQ_DATATYPE_32BIT_UINT)
-      {
-	      if(localTable[ii].decFactor == 2) dWord = iir_filter(dWord,&dCoeff2x[0],DTAPS,&dHistory[ii][0]);
-	      if(localTable[ii].decFactor == 4) dWord = iir_filter(dWord,&dCoeff4x[0],DTAPS,&dHistory[ii][0]);
-	      if(localTable[ii].decFactor == 8) dWord = iir_filter(dWord,&dCoeff8x[0],DTAPS,&dHistory[ii][0]);
-	      if(localTable[ii].decFactor == 16) dWord = iir_filter(dWord,&dCoeff16x[0],DTAPS,&dHistory[ii][0]);
-	      if(localTable[ii].decFactor == 32) dWord = iir_filter(dWord,&dCoeff32x[0],DTAPS,&dHistory[ii][0]);
-	      if(localTable[ii].decFactor == 64) dWord = iir_filter(dWord,&dCoeff64x[0],DTAPS,&dHistory[ii][0]);
-	      if(localTable[ii].decFactor == 128) dWord = iir_filter(dWord,&dCoeff128x[0],DTAPS,&dHistory[ii][0]);
-	      if(localTable[ii].decFactor == 256) dWord = iir_filter(dWord,&dCoeff256x[0],DTAPS,&dHistory[ii][0]);
+      if (dataInfo.tp[ii].dataType != DAQ_DATATYPE_32BIT_UINT) {
+        if (localTable[ii].decFactor == 2)
+          dWord = iir_filter(dWord, &dCoeff2x[0], DTAPS, &dHistory[ii][0]);
+        if (localTable[ii].decFactor == 4)
+          dWord = iir_filter(dWord, &dCoeff4x[0], DTAPS, &dHistory[ii][0]);
+        if (localTable[ii].decFactor == 8)
+          dWord = iir_filter(dWord, &dCoeff8x[0], DTAPS, &dHistory[ii][0]);
+        if (localTable[ii].decFactor == 16)
+          dWord = iir_filter(dWord, &dCoeff16x[0], DTAPS, &dHistory[ii][0]);
+        if (localTable[ii].decFactor == 32)
+          dWord = iir_filter(dWord, &dCoeff32x[0], DTAPS, &dHistory[ii][0]);
+        if (localTable[ii].decFactor == 64)
+          dWord = iir_filter(dWord, &dCoeff64x[0], DTAPS, &dHistory[ii][0]);
+        if (localTable[ii].decFactor == 128)
+          dWord = iir_filter(dWord, &dCoeff128x[0], DTAPS, &dHistory[ii][0]);
+        if (localTable[ii].decFactor == 256)
+          dWord = iir_filter(dWord, &dCoeff256x[0], DTAPS, &dHistory[ii][0]);
       }
 #ifdef CORE_BIQUAD
 #undef iir_filter
@@ -366,180 +487,187 @@ static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY];
 
       /// \> Write fast data into the swing buffer.
       if ((daqSlot % localTable[ii].decFactor) == 0) {
-      	      mydatatype = dataInfo.tp[ii].dataType;
-	      switch(mydatatype) {
-		case DAQ_DATATYPE_16BIT_INT:
-			// Write short data; (XOR 1) here provides sample swapping
-			((short *)(pWriteBuffer + localTable[ii].offset))[(daqSlot/localTable[ii].decFactor)^1] = (short)dWord;
-			break;
-		case DAQ_DATATYPE_DOUBLE:
-			((double *)(pWriteBuffer + localTable[ii].offset))[daqSlot/localTable[ii].decFactor] = dWord;
-			break;
-		case DAQ_DATATYPE_32BIT_UINT:
-			// Write a 32-bit int (downcast from the double passed)
-			if (localTable[ii].decFactor == 1)
-			((unsigned int *)(pWriteBuffer + localTable[ii].offset))[daqSlot/localTable[ii].decFactor] = ((unsigned int)dWord);
-			else
-			((unsigned int *)(pWriteBuffer + localTable[ii].offset))[daqSlot/localTable[ii].decFactor]
-			                = ((unsigned int)dWord) & *((unsigned int *)(dHistory[ii]));
-			break;
-		case DAQ_DATATYPE_32BIT_INT:
-			((int *)(pWriteBuffer + localTable[ii].offset))[daqSlot] = (int)dWord;
-			break;
-		default:
-			// Write a 32-bit float (downcast from the double passed)
-			((float *)(pWriteBuffer + localTable[ii].offset))[daqSlot/localTable[ii].decFactor] = (float)dWord;
-			break;
-	      }
-      	} else if (dataInfo.tp[ii].dataType == DAQ_DATATYPE_32BIT_UINT) {
-              if ((daqSlot % localTable[ii].decFactor) == 1)
-	          *((unsigned int *)(dHistory[ii])) = (unsigned int)dWord;
-	      else
-	          *((unsigned int *)(dHistory[ii])) &= (unsigned int)dWord;
-	}
+        mydatatype = dataInfo.tp[ii].dataType;
+        switch (mydatatype) {
+        case DAQ_DATATYPE_16BIT_INT:
+          // Write short data; (XOR 1) here provides sample swapping
+          ((short *)(pWriteBuffer +
+                     localTable[ii]
+                         .offset))[(daqSlot / localTable[ii].decFactor) ^ 1] =
+              (short)dWord;
+          break;
+        case DAQ_DATATYPE_DOUBLE:
+          ((double *)(pWriteBuffer +
+                      localTable[ii]
+                          .offset))[daqSlot / localTable[ii].decFactor] = dWord;
+          break;
+        case DAQ_DATATYPE_32BIT_UINT:
+          // Write a 32-bit int (downcast from the double passed)
+          if (localTable[ii].decFactor == 1)
+            ((unsigned int *)(pWriteBuffer + localTable[ii].offset))
+                [daqSlot / localTable[ii].decFactor] = ((unsigned int)dWord);
+          else
+            ((unsigned int *)(pWriteBuffer + localTable[ii].offset))
+                [daqSlot / localTable[ii].decFactor] =
+                    ((unsigned int)dWord) & *((unsigned int *)(dHistory[ii]));
+          break;
+        case DAQ_DATATYPE_32BIT_INT:
+          ((int *)(pWriteBuffer + localTable[ii].offset))[daqSlot] = (int)dWord;
+          break;
+        default:
+          // Write a 32-bit float (downcast from the double passed)
+          ((float *)(pWriteBuffer +
+                     localTable[ii]
+                         .offset))[daqSlot / localTable[ii].decFactor] =
+              (float)dWord;
+          break;
+        }
+      } else if (dataInfo.tp[ii].dataType == DAQ_DATATYPE_32BIT_UINT) {
+        if ((daqSlot % localTable[ii].decFactor) == 1)
+          *((unsigned int *)(dHistory[ii])) = (unsigned int)dWord;
+        else
+          *((unsigned int *)(dHistory[ii])) &= (unsigned int)dWord;
+      }
     } /* end swing buffer write loop */
 
-/// \> Write EPICS data into swing buffer at 16Hz.
-if(daqSlot == DAQ_XFER_CYCLE_INT)
-{
-/// \>\> On 16Hz boundary: \n
-/// - ----  Write EPICS integer values to beginning of local write buffer
-
-      if(dataInfo.cpyepics2times)
-	{
-	      memcpy((void *)pWriteBuffer,pEpicsIntData,dataInfo.cpyIntSize[0]);
-	      pEpicsInt = (char *)pWriteBuffer;
-	      pEpicsInt += dataInfo.cpyIntSize[0];
-	      pEpicsInt1 = pEpicsIntData + dataInfo.cpyIntSize[0] + 4;
-	      memcpy(pEpicsInt,pEpicsInt1,dataInfo.cpyIntSize[1]);
-	} else {
-	      memcpy((void *)pWriteBuffer,pEpicsIntData,dataInfo.cpyIntSize[0]);
-	}
-
-}
-if(daqSlot == DAQ_XFER_CYCLE_DBL)
-{
-/// - ---- Write EPICS double values as float values after EPICS integer type data.
-    	pEpicsDblData1 = (double *)pEpicsDblData;
-    	pEpicsFloat = (float *)pWriteBuffer; 
-    	pEpicsFloat += dataInfo.numEpicsInts; 
- 	for(ii=0;ii<dataInfo.numEpicsFloats;ii++)
-	{
-		*pEpicsFloat = (float)*pEpicsDblData1;
-		pEpicsFloat ++;
-		pEpicsDblData1 ++;
-	}
-}
-if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers))
-{
-/// \>\> On 16Hz boundary + 1 (or more) cycle(s): \n
-/// - ----  Write filter module EPICS values as floats
-	jj = DAQ_XFER_FMD_PER_CYCLE * (daqSlot - DAQ_XFER_CYCLE_FMD);
-	if(daqSlot == (dataInfo.numEpicsFiltXfers - 1))
-	{
-		kk = jj + dataInfo.numEpicsFiltsLast;
-	} else {
-		kk = jj + DAQ_XFER_FMD_PER_CYCLE;
-	}
-	// printf("Cycle = %d jj = %d kk = %d\n",daqSlot,jj,kk);
- 	for(ii=jj;ii<kk;ii++)
-	{
-		*pEpicsFloat = (float)dspPtr->inputs[ii].offset;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->inputs[ii].outgain;;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->inputs[ii].limiter;;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->inputs[ii].gain_ramp_time;;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->inputs[ii].swReq;;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->inputs[ii].swMask;;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->data[ii].filterInput;;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->data[ii].exciteInput;;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->data[ii].output16Hz;;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->data[ii].output;;
-		pEpicsFloat ++;
-		*pEpicsFloat = (float)dspPtr->data[ii].swStatus;;
-		pEpicsFloat ++;
-	}
-}
-
+    /// \> Write EPICS data into swing buffer at 16Hz.
+    if (daqSlot == DAQ_XFER_CYCLE_INT) {
+      /// \>\> On 16Hz boundary: \n
+      /// - ----  Write EPICS integer values to beginning of local write buffer
+
+      if (dataInfo.cpyepics2times) {
+        memcpy((void *)pWriteBuffer, pEpicsIntData, dataInfo.cpyIntSize[0]);
+        pEpicsInt = (char *)pWriteBuffer;
+        pEpicsInt += dataInfo.cpyIntSize[0];
+        pEpicsInt1 = pEpicsIntData + dataInfo.cpyIntSize[0] + 4;
+        memcpy(pEpicsInt, pEpicsInt1, dataInfo.cpyIntSize[1]);
+      } else {
+        memcpy((void *)pWriteBuffer, pEpicsIntData, dataInfo.cpyIntSize[0]);
+      }
+    }
+    if (daqSlot == DAQ_XFER_CYCLE_DBL) {
+      /// - ---- Write EPICS double values as float values after EPICS integer
+      /// type data.
+      pEpicsDblData1 = (double *)pEpicsDblData;
+      pEpicsFloat = (float *)pWriteBuffer;
+      pEpicsFloat += dataInfo.numEpicsInts;
+      for (ii = 0; ii < dataInfo.numEpicsFloats; ii++) {
+        *pEpicsFloat = (float)*pEpicsDblData1;
+        pEpicsFloat++;
+        pEpicsDblData1++;
+      }
+    }
+    if ((daqSlot >= DAQ_XFER_CYCLE_FMD) &&
+        (daqSlot < dataInfo.numEpicsFiltXfers)) {
+      /// \>\> On 16Hz boundary + 1 (or more) cycle(s): \n
+      /// - ----  Write filter module EPICS values as floats
+      jj = DAQ_XFER_FMD_PER_CYCLE * (daqSlot - DAQ_XFER_CYCLE_FMD);
+      if (daqSlot == (dataInfo.numEpicsFiltXfers - 1)) {
+        kk = jj + dataInfo.numEpicsFiltsLast;
+      } else {
+        kk = jj + DAQ_XFER_FMD_PER_CYCLE;
+      }
+      // printf("Cycle = %d jj = %d kk = %d\n",daqSlot,jj,kk);
+      for (ii = jj; ii < kk; ii++) {
+        *pEpicsFloat = (float)dspPtr->inputs[ii].offset;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->inputs[ii].outgain;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->inputs[ii].limiter;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->inputs[ii].gain_ramp_time;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->inputs[ii].swReq;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->inputs[ii].swMask;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->data[ii].filterInput;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->data[ii].exciteInput;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->data[ii].output16Hz;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->data[ii].output;
+        pEpicsFloat++;
+        *pEpicsFloat = (float)dspPtr->data[ii].swStatus;
+        pEpicsFloat++;
+      }
+    }
 
-  /// \> Read in any selected EXC signals. \n
-  /// --- NOTE: EXC signals have to be read and loaded in advance by 1 cycle ie must be loaded and
-  /// available to the realtime application when the next code cycle is initiated.
-  excSlot = (excSlot + 1) % sysRate;
-  //if(validEx)
-  validEx = 0;
-  {
-	// Go through all test points
-  	for(ii=dataInfo.numChans;ii<totalChans;ii++)
-  	{
-		// Do not pickup any testpoints (type 0 or 1)
-		if (localTable[ii].type < DAQ_SRC_FM_EXC) continue;
-
-		exChanOffset = localTable[ii].sigNum * excDataSize;
-		statusPtr = (int *)(exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE + exChanOffset);
-		if(*statusPtr == 0)
-		{
-			validEx = FE_ERROR_EXC_SET;
-			dataPtr = (float *)(exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE + exChanOffset +
-					    excSlot * 4 + 4);
-			if(localTable[ii].type == DAQ_SRC_FM_EXC)
-			{
-				dspPtr->data[localTable[ii].fmNum].exciteInput = *dataPtr;
-			} else if (localTable[ii].type == DAQ_SRC_NFM_EXC) {
-				// extra excitation
-				excSignal[localTable[ii].fmNum] = *dataPtr;
-			}
-		}
-		// else dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0;
-		else {
-			if(localTable[ii].type == DAQ_SRC_FM_EXC)
-			{
-				dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0;
-			} else if (localTable[ii].type == DAQ_SRC_NFM_EXC) {
-				// extra excitation
-				excSignal[localTable[ii].fmNum] = 0.0;
-			}
-		}
-  	}
-  }
+    /// \> Read in any selected EXC signals. \n
+    /// --- NOTE: EXC signals have to be read and loaded in advance by 1 cycle
+    /// ie must be loaded and
+    /// available to the realtime application when the next code cycle is
+    /// initiated.
+    excSlot = (excSlot + 1) % sysRate;
+    // if(validEx)
+    validEx = 0;
+    {
+      // Go through all test points
+      for (ii = dataInfo.numChans; ii < totalChans; ii++) {
+        // Do not pickup any testpoints (type 0 or 1)
+        if (localTable[ii].type < DAQ_SRC_FM_EXC)
+          continue;
+
+        exChanOffset = localTable[ii].sigNum * excDataSize;
+        statusPtr = (int *)(exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE +
+                            exChanOffset);
+        if (*statusPtr == 0) {
+          validEx = FE_ERROR_EXC_SET;
+          dataPtr = (float *)(exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE +
+                              exChanOffset + excSlot * 4 + 4);
+          if (localTable[ii].type == DAQ_SRC_FM_EXC) {
+            dspPtr->data[localTable[ii].fmNum].exciteInput = *dataPtr;
+          } else if (localTable[ii].type == DAQ_SRC_NFM_EXC) {
+            // extra excitation
+            excSignal[localTable[ii].fmNum] = *dataPtr;
+          }
+        }
+        // else dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0;
+        else {
+          if (localTable[ii].type == DAQ_SRC_FM_EXC) {
+            dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0;
+          } else if (localTable[ii].type == DAQ_SRC_NFM_EXC) {
+            // extra excitation
+            excSignal[localTable[ii].fmNum] = 0.0;
+          }
+        }
+      }
+    }
 
-  /// \> Move to the next 1/16 EXC signal data block if end of 16Hz block
-  if(excSlot == (sysRate - 1)) excBlockNum = (excBlockNum + 1) % DAQ_NUM_DATA_BLOCKS;
+    /// \> Move to the next 1/16 EXC signal data block if end of 16Hz block
+    if (excSlot == (sysRate - 1))
+      excBlockNum = (excBlockNum + 1) % DAQ_NUM_DATA_BLOCKS;
 
     /// \> If last cycle of a 16Hz block:
-    if(daqSlot == (sysRate - 1))
+    if (daqSlot == (sysRate - 1))
     /* Done with 1/16 second DAQ data block */
     {
 
-	/// - -- Fill in the IPC table for DAQ network driver (mx_stream) \n
-        dipc->dcuId = dcuId; /// -   ------ DCU id of this system
-        dipc->crc = xferInfo.fileCrc; /// -   ------ Checksum of the configuration file
-        dipc->dataBlockSize = xferInfo.totalSizeNet; /// -   ------ Actual data size
-        /// -   ------  Data block number
-        dipc->bp[daqXmitBlockNum].cycle = daqXmitBlockNum;
-        /// -   ------  Data block CRC
-        dipc->bp[daqXmitBlockNum].crc = xferInfo.crcLength;
-	/// -   ------ Timestamp GPS Second
-	dipc->bp[daqXmitBlockNum].timeSec = (unsigned int) cycle_gps_time;
-	/// -   ------ Timestamp GPS nanoSecond - Actually cycle number
-        dipc->bp[daqXmitBlockNum].timeNSec = (unsigned int)daqXmitBlockNum;
-
-        /// - ------ Write test point info to DAQ net shared memory
-        tpPtr->count = validTpNet | validEx;
-        memcpy(tpPtr->tpNum, tpNumNet, sizeof(tpNumNet[0]) * validTp);
-
-        // As the last step set the cycle counter
-        // Frame builder is looking for cycle change
-	/// - ------ Write IPC cycle number. This will trigger DAQ network driver to send data to DAQ
-        dipc->cycle =daqXmitBlockNum; // Ready cycle (16 Hz)
+      /// - -- Fill in the IPC table for DAQ network driver (mx_stream) \n
+      dipc->dcuId = dcuId; /// -   ------ DCU id of this system
+      dipc->crc =
+          xferInfo.fileCrc; /// -   ------ Checksum of the configuration file
+      dipc->dataBlockSize =
+          xferInfo.totalSizeNet; /// -   ------ Actual data size
+      /// -   ------  Data block number
+      dipc->bp[daqXmitBlockNum].cycle = daqXmitBlockNum;
+      /// -   ------  Data block CRC
+      dipc->bp[daqXmitBlockNum].crc = xferInfo.crcLength;
+      /// -   ------ Timestamp GPS Second
+      dipc->bp[daqXmitBlockNum].timeSec = (unsigned int)cycle_gps_time;
+      /// -   ------ Timestamp GPS nanoSecond - Actually cycle number
+      dipc->bp[daqXmitBlockNum].timeNSec = (unsigned int)daqXmitBlockNum;
+
+      /// - ------ Write test point info to DAQ net shared memory
+      tpPtr->count = validTpNet | validEx;
+      memcpy(tpPtr->tpNum, tpNumNet, sizeof(tpNumNet[0]) * validTp);
+
+      // As the last step set the cycle counter
+      // Frame builder is looking for cycle change
+      /// - ------ Write IPC cycle number. This will trigger DAQ network driver
+      /// to send data to DAQ
+      dipc->cycle = daqXmitBlockNum; // Ready cycle (16 Hz)
 
       /// - -- Increment the 1/16 sec block counter
       daqBlockNum = (daqBlockNum + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND;
@@ -550,221 +678,230 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers))
       pWriteBuffer += buf_size * daqXmitBlockNum;
 
       //  - -- Check for reconfig request at start of each second
-      if((pInfo->reconfig == 1) && (daqBlockNum == 0))
-      {
-	    // printf("New daq config\n");
-	    pInfo->reconfig = 0;
-	    // Configure EPICS data channels
-	    xferInfo.crcLength = daqConfig(&dataInfo,pInfo,pEpics);
-	    if(xferInfo.crcLength)
-	    {
-		    status = loadLocalTable(&xferInfo,localTable,sysRate,&dataInfo,&daqRange);
-		    // Clear decimation filter history
-		    for(ii=0;ii<dataInfo.numChans;ii++)
-		    {
-		      for(jj=0;jj<MAX_HISTRY;jj++) dHistory[ii][jj] = 0.0;
-		    }
-
-		    tpStart = xferInfo.offsetAccum;
-		    totalChans = dataInfo.numChans;
-
-	    }
+      if ((pInfo->reconfig == 1) && (daqBlockNum == 0)) {
+        // printf("New daq config\n");
+        pInfo->reconfig = 0;
+        // Configure EPICS data channels
+        xferInfo.crcLength = daqConfig(&dataInfo, pInfo, pEpics);
+        if (xferInfo.crcLength) {
+          status = loadLocalTable(&xferInfo, localTable, sysRate, &dataInfo,
+                                  &daqRange);
+          // Clear decimation filter history
+          for (ii = 0; ii < dataInfo.numChans; ii++) {
+            for (jj = 0; jj < MAX_HISTRY; jj++)
+              dHistory[ii][jj] = 0.0;
+          }
+
+          tpStart = xferInfo.offsetAccum;
+          totalChans = dataInfo.numChans;
+        }
       }
-      /// - -- If last cycle of 1 sec time frame, check for new TP and load info.
-      // This will cause new TP to be written to local memory at start of 1 sec block.
-
-      if(daqBlockNum == 15)
-      {
-	// Offset by one into the TP/EXC tables for the 2K systems
-	unsigned int _2k_sys_offs = sysRate < DAQ_16K_SAMPLE_SIZE;
-	
-	// Helper function to search the lists
-	// Clears the found number from the lists
-	// tpnum and excnum lists of numbers do not intersect
-	inline int in_the_lists(unsigned int tp, unsigned int slot) {
-		int i;
-		for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++){
-			if (tpnum[i] == tp) return (tpnum[i] = 0, 1);
-                        if (excnum[i] == tp) {
-                                // Check if the excitation is still in the same slot
-                                if (i != excTable[slot].offset) return 0;
-                                return (excnum[i] = 0, 1);
-                        }
-		}
-		return 0;
-	}
-
-	// Helper function to find an empty slot in the localTable
-	inline unsigned int empty_slot(void) {
-		int i;
-		for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) {
-			if (tpNum[i] == 0) return i;	
-		}
-		return -1;
-	}
-
-	// Copy TP/EXC tables into my local memory
-	memcpy(excnum, (const void *)(gdsPtr->tp[_2k_sys_offs][0]), sizeof(excnum));
-	memcpy(tpnum, (const void *)(gdsPtr->tp[2 + _2k_sys_offs][0]), sizeof(tpnum));
-
-	/// - ------ Search and clear deselected test points
-	for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) {
-		if (tpNum[i] == 0) continue;
-		if (!in_the_lists(tpNum[i], i)) {
-		  tpNum[i] = 0; // Removed test point is cleared now
-		  ltSlot = dataInfo.numChans + i;
-
-		  // If we are clearing an EXC signal, reset filter module input
-		  if (localTable[ltSlot].type == DAQ_SRC_FM_EXC) {
-		    dspPtr->data[excTable[i].fmNum].exciteInput = 0.0;
-		    excTable[i].sigNum = 0;
-		  } else if (localTable[ltSlot].type == DAQ_SRC_NFM_EXC) {
-		    // Extra excitation
-		    excSignal[excTable[i].fmNum] = 0.0;
-		    excTable[i].sigNum = 0;
-		  }
-
-		  localTable[ltSlot].type = 0;
-          	  localTable[ltSlot].sysNum = 0;
-          	  localTable[ltSlot].fmNum = 0;
-          	  localTable[ltSlot].sigNum = 0;
-	  	  localTable[ltSlot].decFactor = 1;
-      		  dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
-		}
-	}
-	
-	// tpnum and excnum lists now have only the new test points
-	// Insert these new numbers into empty localTable slots
-	for (i = 0; i < (2 * DAQ_GDS_MAX_TP_ALLOWED); i++) {
-		exc = 0;
-		// Do test points first
-		if (i < DAQ_GDS_MAX_TP_ALLOWED) {
-			if (tpnum[i] == 0) continue;
-			tpn = tpnum[i];
-		} else {
-			if (excnum[i - DAQ_GDS_MAX_TP_ALLOWED] == 0) continue;
-			tpn = excnum[i - DAQ_GDS_MAX_TP_ALLOWED];
-			exc = 1;
-			ii = i - DAQ_GDS_MAX_TP_ALLOWED;
-		}
-
-        	//printf("tpn=%d at %d\n", tpn, i);
-		slot = empty_slot();
-		if (slot < 0) {
-			// No more slots left, table's full
-			break;
-		}
-
-		// localTable slot (shifted by the number of DAQ channels)
-		ltSlot = dataInfo.numChans + slot;
-
-		// Populate the slot with the information
-		if (!exc) {
-       		  if (tpn >= daqRange.filtTpMin && tpn < daqRange.filtTpMax) {
-		    jj = tpn - daqRange.filtTpMin;
-		    localTable[ltSlot].type = DAQ_SRC_FM_TP;
-          	    localTable[ltSlot].sysNum = jj / daqRange.filtTpSize;
-		    jj -= localTable[ltSlot].sysNum * daqRange.filtTpSize;
-          	    localTable[ltSlot].fmNum = jj / DAQ_NUM_FM_TP;
-          	    localTable[ltSlot].sigNum = jj % DAQ_NUM_FM_TP; 
-	  	    localTable[ltSlot].decFactor = 1;
-      		    dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
-
-		    //if (slot < 24) gdsMonitor[slot] = tpn;
-          	    gdsPtr->tp[2 + _2k_sys_offs][1][slot] = 0;
-		    tpNum[slot] = tpn;
-
-        	  } else if (tpn >= daqRange.xTpMin && tpn < daqRange.xTpMax) {
-	 	    jj = tpn - daqRange.xTpMin;
-		    localTable[ltSlot].type = DAQ_SRC_NFM_TP;
-		    localTable[ltSlot].sigNum = jj;
-	  	    localTable[ltSlot].decFactor = 1;
-      		    dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
-		    gdsPtr->tp[2 + _2k_sys_offs][1][slot] = 0;
-		    tpNum[slot] = tpn;
-		  
-		  }
-	        } else {
-
-        	  if (tpn >= daqRange.filtExMin && tpn < daqRange.filtExMax) {
-		    jj = tpn - daqRange.filtExMin;
-		    localTable[ltSlot].type = DAQ_SRC_FM_EXC;
-          	    localTable[ltSlot].sysNum = jj / daqRange.filtExSize;	// filtExSize = MAX_MODULES
-          	    localTable[ltSlot].fmNum = jj % daqRange.filtExSize;
-          	    localTable[ltSlot].sigNum = ii;
-	  	    localTable[ltSlot].decFactor = 1;
-
-		    excTable[slot].sigNum = tpn;
-		    excTable[slot].sysNum = localTable[ltSlot].sysNum;
-		    excTable[slot].fmNum = localTable[ltSlot].fmNum;
-                    excTable[slot].offset = i - DAQ_GDS_MAX_TP_ALLOWED;
-
-                    // Save the index into the TPman table
-      		    dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
-
-          	    gdsPtr->tp[_2k_sys_offs][1][slot] = 0;
-		    tpNum[slot] = tpn;
-
-        	  } else if (tpn >= daqRange.xExMin && tpn < daqRange.xExMax) {
-	 	    jj = tpn - daqRange.xExMin;
-		    localTable[ltSlot].type = DAQ_SRC_NFM_EXC;
-          	    localTable[ltSlot].sysNum = 0;	// filtExSize = MAX_MODULES
-          	    localTable[ltSlot].fmNum = jj;
-          	    // localTable[ltSlot].sigNum = slot;
-          	    localTable[ltSlot].sigNum = ii;
-	  	    localTable[ltSlot].decFactor = 1;
-
-		    excTable[slot].sigNum = tpn;
-		    excTable[slot].sysNum = localTable[ltSlot].sysNum;
-		    excTable[slot].fmNum = localTable[ltSlot].fmNum;
-                    excTable[slot].offset = i - DAQ_GDS_MAX_TP_ALLOWED;
-
-      		    dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
-		   // if (slot < 8) gdsMonitor[slot + 24] = tpn;
-          	    gdsPtr->tp[_2k_sys_offs][1][slot] = 0;
-		    tpNum[slot] = tpn;
-		  }
-		}
-	}
-
-	/// - ------ Calculate total number of test points to transmit
-	totalChans = dataInfo.numChans; // Set to the DAQ channels number
-	validTp = 0;
-	num_tps = 0;
-
-	// Skip empty slots at the end
-	for (i = DAQ_GDS_MAX_TP_ALLOWED-1; i >= 0; i--) {
-		if (tpNum[i]) {
-			num_tps = i + 1;
-			break;
-		}
-	}
-	totalChans += num_tps;
-	validTp = num_tps;
-
-	/// - ------ Calculate the total transmission size (DAQ +TP)
-	xferInfo.totalSize = xferInfo.crcLength + validTp * sysRate * 4;
-
-
-	// Assign offsets into the localTable
-	xferInfo.offsetAccum = tpStart;
-	for (i = 0; i < validTp; i++) {
-	    localTable[dataInfo.numChans + i].offset = xferInfo.offsetAccum;
-	    xferInfo.offsetAccum += sysRate * 4;
-	    if (i < 32) gdsMonitor[i] = tpNum[i];
-	}
-
-	for (i = validTp; i < 32; i++) gdsMonitor[i] = 0;
+      /// - -- If last cycle of 1 sec time frame, check for new TP and load
+      /// info.
+      // This will cause new TP to be written to local memory at start of 1 sec
+      // block.
+
+      if (daqBlockNum == 15) {
+        // Offset by one into the TP/EXC tables for the 2K systems
+        unsigned int _2k_sys_offs = sysRate < DAQ_16K_SAMPLE_SIZE;
+
+        // Helper function to search the lists
+        // Clears the found number from the lists
+        // tpnum and excnum lists of numbers do not intersect
+        inline int in_the_lists(unsigned int tp, unsigned int slot) {
+          int i;
+          for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) {
+            if (tpnum[i] == tp)
+              return (tpnum[i] = 0, 1);
+            if (excnum[i] == tp) {
+              // Check if the excitation is still in the same slot
+              if (i != excTable[slot].offset)
+                return 0;
+              return (excnum[i] = 0, 1);
+            }
+          }
+          return 0;
+        }
+
+        // Helper function to find an empty slot in the localTable
+        inline unsigned int empty_slot(void) {
+          int i;
+          for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) {
+            if (tpNum[i] == 0)
+              return i;
+          }
+          return -1;
+        }
+
+        // Copy TP/EXC tables into my local memory
+        // Had to change from memcpy to for loop for Debian 10.
+        for (ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++)
+          excnum[ii] = gdsPtr->tp[_2k_sys_offs][0][ii];
+        for (ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++)
+          tpnum[ii] = gdsPtr->tp[(2 + _2k_sys_offs)][0][ii];
+
+        /// - ------ Search and clear deselected test points
+        for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) {
+          if (tpNum[i] == 0)
+            continue;
+          if (!in_the_lists(tpNum[i], i)) {
+            tpNum[i] = 0; // Removed test point is cleared now
+            ltSlot = dataInfo.numChans + i;
+
+            // If we are clearing an EXC signal, reset filter module input
+            if (localTable[ltSlot].type == DAQ_SRC_FM_EXC) {
+              dspPtr->data[excTable[i].fmNum].exciteInput = 0.0;
+              excTable[i].sigNum = 0;
+            } else if (localTable[ltSlot].type == DAQ_SRC_NFM_EXC) {
+              // Extra excitation
+              excSignal[excTable[i].fmNum] = 0.0;
+              excTable[i].sigNum = 0;
+            }
+
+            localTable[ltSlot].type = 0;
+            localTable[ltSlot].sysNum = 0;
+            localTable[ltSlot].fmNum = 0;
+            localTable[ltSlot].sigNum = 0;
+            localTable[ltSlot].decFactor = 1;
+            dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
+          }
+        }
+
+        // tpnum and excnum lists now have only the new test points
+        // Insert these new numbers into empty localTable slots
+        for (i = 0; i < (2 * DAQ_GDS_MAX_TP_ALLOWED); i++) {
+          exc = 0;
+          // Do test points first
+          if (i < DAQ_GDS_MAX_TP_ALLOWED) {
+            if (tpnum[i] == 0)
+              continue;
+            tpn = tpnum[i];
+          } else {
+            if (excnum[i - DAQ_GDS_MAX_TP_ALLOWED] == 0)
+              continue;
+            tpn = excnum[i - DAQ_GDS_MAX_TP_ALLOWED];
+            exc = 1;
+            ii = i - DAQ_GDS_MAX_TP_ALLOWED;
+          }
+
+          // printf("tpn=%d at %d\n", tpn, i);
+          slot = empty_slot();
+          if (slot < 0) {
+            // No more slots left, table's full
+            break;
+          }
+
+          // localTable slot (shifted by the number of DAQ channels)
+          ltSlot = dataInfo.numChans + slot;
+
+          // Populate the slot with the information
+          if (!exc) {
+            if (tpn >= daqRange.filtTpMin && tpn < daqRange.filtTpMax) {
+              jj = tpn - daqRange.filtTpMin;
+              localTable[ltSlot].type = DAQ_SRC_FM_TP;
+              localTable[ltSlot].sysNum = jj / daqRange.filtTpSize;
+              jj -= localTable[ltSlot].sysNum * daqRange.filtTpSize;
+              localTable[ltSlot].fmNum = jj / DAQ_NUM_FM_TP;
+              localTable[ltSlot].sigNum = jj % DAQ_NUM_FM_TP;
+              localTable[ltSlot].decFactor = 1;
+              dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
+
+              // if (slot < 24) gdsMonitor[slot] = tpn;
+              gdsPtr->tp[2 + _2k_sys_offs][1][slot] = 0;
+              tpNum[slot] = tpn;
+
+            } else if (tpn >= daqRange.xTpMin && tpn < daqRange.xTpMax) {
+              jj = tpn - daqRange.xTpMin;
+              localTable[ltSlot].type = DAQ_SRC_NFM_TP;
+              localTable[ltSlot].sigNum = jj;
+              localTable[ltSlot].decFactor = 1;
+              dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
+              gdsPtr->tp[2 + _2k_sys_offs][1][slot] = 0;
+              tpNum[slot] = tpn;
+            }
+          } else {
+
+            if (tpn >= daqRange.filtExMin && tpn < daqRange.filtExMax) {
+              jj = tpn - daqRange.filtExMin;
+              localTable[ltSlot].type = DAQ_SRC_FM_EXC;
+              localTable[ltSlot].sysNum =
+                  jj / daqRange.filtExSize; // filtExSize = MAX_MODULES
+              localTable[ltSlot].fmNum = jj % daqRange.filtExSize;
+              localTable[ltSlot].sigNum = ii;
+              localTable[ltSlot].decFactor = 1;
+
+              excTable[slot].sigNum = tpn;
+              excTable[slot].sysNum = localTable[ltSlot].sysNum;
+              excTable[slot].fmNum = localTable[ltSlot].fmNum;
+              excTable[slot].offset = i - DAQ_GDS_MAX_TP_ALLOWED;
+
+              // Save the index into the TPman table
+              dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
+
+              gdsPtr->tp[_2k_sys_offs][1][slot] = 0;
+              tpNum[slot] = tpn;
+
+            } else if (tpn >= daqRange.xExMin && tpn < daqRange.xExMax) {
+              jj = tpn - daqRange.xExMin;
+              localTable[ltSlot].type = DAQ_SRC_NFM_EXC;
+              localTable[ltSlot].sysNum = 0; // filtExSize = MAX_MODULES
+              localTable[ltSlot].fmNum = jj;
+              // localTable[ltSlot].sigNum = slot;
+              localTable[ltSlot].sigNum = ii;
+              localTable[ltSlot].decFactor = 1;
+
+              excTable[slot].sigNum = tpn;
+              excTable[slot].sysNum = localTable[ltSlot].sysNum;
+              excTable[slot].fmNum = localTable[ltSlot].fmNum;
+              excTable[slot].offset = i - DAQ_GDS_MAX_TP_ALLOWED;
+
+              dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT;
+              // if (slot < 8) gdsMonitor[slot + 24] = tpn;
+              gdsPtr->tp[_2k_sys_offs][1][slot] = 0;
+              tpNum[slot] = tpn;
+            }
+          }
+        }
+
+        /// - ------ Calculate total number of test points to transmit
+        totalChans = dataInfo.numChans; // Set to the DAQ channels number
+        validTp = 0;
+        num_tps = 0;
+
+        // Skip empty slots at the end
+        for (i = DAQ_GDS_MAX_TP_ALLOWED - 1; i >= 0; i--) {
+          if (tpNum[i]) {
+            num_tps = i + 1;
+            break;
+          }
+        }
+        totalChans += num_tps;
+        validTp = num_tps;
+
+        /// - ------ Calculate the total transmission size (DAQ +TP)
+        xferInfo.totalSize = xferInfo.crcLength + validTp * sysRate * 4;
+
+        // Assign offsets into the localTable
+        xferInfo.offsetAccum = tpStart;
+        for (i = 0; i < validTp; i++) {
+          localTable[dataInfo.numChans + i].offset = xferInfo.offsetAccum;
+          xferInfo.offsetAccum += sysRate * 4;
+          if (i < 32)
+            gdsMonitor[i] = tpNum[i];
+        }
+
+        for (i = validTp; i < 32; i++)
+          gdsMonitor[i] = 0;
 
       } /* End normal check for new TP numbers */
 
-      // Network write is one cycle behind memory write, so now update tp nums for FB xmission
-      if(daqBlockNum == 0)
-      {
-	for(ii=0;ii<validTp;ii++)
-		tpNumNet[ii] = tpNum[ii];
-	validTpNet = validTp;
-	xferInfo.totalSizeNet = xferInfo.totalSize;
+      // Network write is one cycle behind memory write, so now update tp nums
+      // for FB xmission
+      if (daqBlockNum == 0) {
+        for (ii = 0; ii < validTp; ii++)
+          tpNumNet[ii] = tpNum[ii];
+        validTpNet = validTp;
+        xferInfo.totalSizeNet = xferInfo.totalSize;
       }
 
     } /* End done 16Hz Cycle */
@@ -772,8 +909,7 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers))
   } /* End case write */
 
   /// \> Return the FE total DAQ data rate */
-  return((xferInfo.totalSize*DAQ_NUM_DATA_BLOCKS_PER_SECOND)/1000);
-
+  return ((xferInfo.totalSize * DAQ_NUM_DATA_BLOCKS_PER_SECOND) / 1000);
 }
 
 // **************************************************************************************
@@ -785,231 +921,226 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers))
 ///	@param[in] pEpics	Pointer to beginning of EPICS data.
 ///	@return	Size, in bytes, of DAQ data.
 // **************************************************************************************
-int daqConfig( DAQ_INFO_BLOCK *dataInfo,  	
-                DAQ_INFO_BLOCK *pInfo,	
-		char *pEpics
-              )
-{
-int ii,jj;      		// Loop counters
-int epicsIntXferSize = 0;	// Size, in bytes, of EPICS integer type data.
-int dataLength = 0;		// Total size, in bytes, of data to be sent
-int status = 0;
-int mydatatype;
-
-/// \> Verify correct channel count before proceeding. \n
-/// - ---- Required to be at least one and not more than DCU_MAX_CHANNELS.
-    status = pInfo->numChans;
-    // if((status < 1) || (status > DCU_MAX_CHANNELS))
-    if(status > DCU_MAX_CHANNELS)
-    {   
-	// printf("Invalid num daq chans = %d\n",status);
-	return(-1);
-    }
-
-    /// \> Get the number of fast channels to be acquired 
-    dataInfo->numChans = pInfo->numChans;
-
-/// \> Setup EPICS channel information/pointers
-    dataInfo->numEpicsInts = pInfo->numEpicsInts;
-    dataInfo->numEpicsFloats = pInfo->numEpicsFloats;
-    dataInfo->numEpicsFilts = pInfo->numEpicsFilts;
-    dataInfo->numEpicsTotal = pInfo->numEpicsTotal;
-/// \> Determine how many filter modules are to have their data transferred per cycle.
-/// - ---- This is to balance load (CPU time) across several cycles if number of filter modules > 100
-    dataInfo->numEpicsFiltXfers = MAX_MODULES/DAQ_XFER_FMD_PER_CYCLE;
-    dataInfo->numEpicsFiltsLast = DAQ_XFER_FMD_PER_CYCLE;
-    if(MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE) 
-    {
-	dataInfo->numEpicsFiltXfers ++;
-	dataInfo->numEpicsFiltsLast = (MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE);
-    }
-    dataInfo->numEpicsFiltXfers += DAQ_XFER_CYCLE_FMD;
-    pEpicsIntData = pEpics;
-    epicsIntXferSize = dataInfo->numEpicsInts * 4;
-
-    dataInfo->epicsdblDataOffset = 0;
-    dataInfo->cpyepics2times = 0;
-    dataInfo->cpyIntSize[0] = dataInfo->numEpicsInts * 4;
-    dataInfo->cpyIntSize[1] = 0;
-
-    ii = (sizeof(CDS_EPICS_OUT) / 4);
-    jj = dataInfo->numEpicsInts - ii;
-    // printf("Have %d CDS epics integer and %d USR epics integer channels\n",ii,jj);
-    ii *= 4;
-    jj *= 4;
-
-    /// \>  Look for memory holes ie integer types not ending on 8 byte boundary.
-    /// Need to check both standard CDS struct and User channels
-    /// - ---- If either doesn't end on 8 byte boundary, then a 4 byte hole will appear
-    /// before the double type data in shared memory.
-    if(ii % 8) {
-        // printf("Have int mem hole after CDS %d %d \n",ii,jj);
-        dataInfo->epicsdblDataOffset += 4;
-    }
-    if(jj % 8) {
-        // printf("Have int mem hole after user %d %d \n",ii,jj);
-        dataInfo->epicsdblDataOffset += 4;
-    }
-    if ((ii%8) &&(jj>0)) { 
-        /// - ---- If standard CDS struct doesn't end on 8 byte boundary, then
-        /// have 4 byte mem hole after CDS data
-        /// This will require 2 memcpys of integer data to get 8 byte alignment for xfer to DAQ buffer..
-        dataInfo->cpyIntSize[0] = ii;
-        dataInfo->cpyIntSize[1] = jj;        
-	dataInfo->cpyepics2times = 1;
-        // dataInfo->epicsdblDataOffset += 4;
-        // printf("Have mem holes after CDS  %d %d \nNeed to cpy ints twice - size 1 = %d size 2 = %d \n",ii,jj,dataInfo->cpyIntSize[0],dataInfo->cpyIntSize[1]);
-    }
+int daqConfig(DAQ_INFO_BLOCK *dataInfo, DAQ_INFO_BLOCK *pInfo, char *pEpics) {
+  int ii, jj;               // Loop counters
+  int epicsIntXferSize = 0; // Size, in bytes, of EPICS integer type data.
+  int dataLength = 0;       // Total size, in bytes, of data to be sent
+  int status = 0;
+  int mydatatype;
+
+  /// \> Verify correct channel count before proceeding. \n
+  /// - ---- Required to be at least one and not more than DCU_MAX_CHANNELS.
+  status = pInfo->numChans;
+  // if((status < 1) || (status > DCU_MAX_CHANNELS))
+  if (status > DCU_MAX_CHANNELS) {
+    // printf("Invalid num daq chans = %d\n",status);
+    return (-1);
+  }
 
-    /// \> Set the pointer to start of EPICS double type data in shared memory. \n
-    /// - ---- Ptr to double type data is at EPICS integer start + EPICS integer size + Memory holes
-    pEpicsDblData = (pEpicsIntData + epicsIntXferSize + dataInfo->epicsdblDataOffset);
-
-    // Send EPICS data diags to dmesg
-    // printf("DAQ EPICS INT DATA is at 0x%lx with size %d\n",(long)pEpicsIntData,epicsIntXferSize);
-    // printf("DAQ EPICS FLT DATA is at 0x%lx\n",(long)pEpicsDblData);
-    // printf("DAQ EPICS: Int = %d  Flt = %d Filters = %d Total = %d Fast = %d\n",dataInfo->numEpicsInts,dataInfo->numEpicsFloats,dataInfo->numEpicsFilts, dataInfo->numEpicsTotal, dataInfo->numChans);
-    // printf("DAQ EPICS: Number of Filter Module Xfers = %d last = %d\n",dataInfo->numEpicsFiltXfers,dataInfo->numEpicsFiltsLast);
-    /// \> Initialize CRC length with EPICS data size.
-    dataLength = 4 * dataInfo->numEpicsTotal;
-    // printf("crc length epics = %d\n",dataLength);
-
-    /// \>  Get the DAQ configuration information for all fast DAQ channels and calc a crc checksum length
-    for(ii=0;ii<dataInfo->numChans;ii++)
-    {
-      dataInfo->tp[ii].tpnum = pInfo->tp[ii].tpnum;
-      dataInfo->tp[ii].dataType = pInfo->tp[ii].dataType;
-      dataInfo->tp[ii].dataRate = pInfo->tp[ii].dataRate;
-      mydatatype = dataInfo->tp[ii].dataType;
-      dataLength += DAQ_DATA_TYPE_SIZE(mydatatype) * dataInfo->tp[ii].dataRate / DAQ_NUM_DATA_BLOCKS;
-      // if(mydatatype == 5) printf("Found double %d\n",DAQ_DATA_TYPE_SIZE(mydatatype));
-    }
-    /// \> Set DAQ bytes/sec global, which is output to EPICS by controller.c
-    curDaqBlockSize = dataLength * DAQ_NUM_DATA_BLOCKS_PER_SECOND;
+  /// \> Get the number of fast channels to be acquired
+  dataInfo->numChans = pInfo->numChans;
+
+  /// \> Setup EPICS channel information/pointers
+  dataInfo->numEpicsInts = pInfo->numEpicsInts;
+  dataInfo->numEpicsFloats = pInfo->numEpicsFloats;
+  dataInfo->numEpicsFilts = pInfo->numEpicsFilts;
+  dataInfo->numEpicsTotal = pInfo->numEpicsTotal;
+  /// \> Determine how many filter modules are to have their data transferred
+  /// per cycle.
+  /// - ---- This is to balance load (CPU time) across several cycles if number
+  /// of filter modules > 100
+  dataInfo->numEpicsFiltXfers = MAX_MODULES / DAQ_XFER_FMD_PER_CYCLE;
+  dataInfo->numEpicsFiltsLast = DAQ_XFER_FMD_PER_CYCLE;
+  if (MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE) {
+    dataInfo->numEpicsFiltXfers++;
+    dataInfo->numEpicsFiltsLast = (MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE);
+  }
+  dataInfo->numEpicsFiltXfers += DAQ_XFER_CYCLE_FMD;
+  pEpicsIntData = pEpics;
+  epicsIntXferSize = dataInfo->numEpicsInts * 4;
+
+  dataInfo->epicsdblDataOffset = 0;
+  dataInfo->cpyepics2times = 0;
+  dataInfo->cpyIntSize[0] = dataInfo->numEpicsInts * 4;
+  dataInfo->cpyIntSize[1] = 0;
+
+  ii = (sizeof(CDS_EPICS_OUT) / 4);
+  jj = dataInfo->numEpicsInts - ii;
+  // printf("Have %d CDS epics integer and %d USR epics integer
+  // channels\n",ii,jj);
+  ii *= 4;
+  jj *= 4;
+
+  /// \>  Look for memory holes ie integer types not ending on 8 byte boundary.
+  /// Need to check both standard CDS struct and User channels
+  /// - ---- If either doesn't end on 8 byte boundary, then a 4 byte hole will
+  /// appear
+  /// before the double type data in shared memory.
+  if (ii % 8) {
+    // printf("Have int mem hole after CDS %d %d \n",ii,jj);
+    dataInfo->epicsdblDataOffset += 4;
+  }
+  if (jj % 8) {
+    // printf("Have int mem hole after user %d %d \n",ii,jj);
+    dataInfo->epicsdblDataOffset += 4;
+  }
+  if ((ii % 8) && (jj > 0)) {
+    /// - ---- If standard CDS struct doesn't end on 8 byte boundary, then
+    /// have 4 byte mem hole after CDS data
+    /// This will require 2 memcpys of integer data to get 8 byte alignment for
+    /// xfer to DAQ buffer..
+    dataInfo->cpyIntSize[0] = ii;
+    dataInfo->cpyIntSize[1] = jj;
+    dataInfo->cpyepics2times = 1;
+    // dataInfo->epicsdblDataOffset += 4;
+    // printf("Have mem holes after CDS  %d %d \nNeed to cpy ints twice - size 1
+    // = %d size 2 = %d
+    // \n",ii,jj,dataInfo->cpyIntSize[0],dataInfo->cpyIntSize[1]);
+  }
 
-    /// \> RETURN dataLength, used in other code for CRC checksum byte count
-    return(dataLength);
+  /// \> Set the pointer to start of EPICS double type data in shared memory. \n
+  /// - ---- Ptr to double type data is at EPICS integer start + EPICS integer
+  /// size + Memory holes
+  pEpicsDblData =
+      (pEpicsIntData + epicsIntXferSize + dataInfo->epicsdblDataOffset);
+
+  // Send EPICS data diags to dmesg
+  // printf("DAQ EPICS INT DATA is at 0x%lx with size
+  // %d\n",(long)pEpicsIntData,epicsIntXferSize);
+  // printf("DAQ EPICS FLT DATA is at 0x%lx\n",(long)pEpicsDblData);
+  // printf("DAQ EPICS: Int = %d  Flt = %d Filters = %d Total = %d Fast =
+  // %d\n",dataInfo->numEpicsInts,dataInfo->numEpicsFloats,dataInfo->numEpicsFilts,
+  // dataInfo->numEpicsTotal, dataInfo->numChans);
+  // printf("DAQ EPICS: Number of Filter Module Xfers = %d last =
+  // %d\n",dataInfo->numEpicsFiltXfers,dataInfo->numEpicsFiltsLast);
+  /// \> Initialize CRC length with EPICS data size.
+  dataLength = 4 * dataInfo->numEpicsTotal;
+  // printf("crc length epics = %d\n",dataLength);
+
+  /// \>  Get the DAQ configuration information for all fast DAQ channels and
+  /// calc a crc checksum length
+  for (ii = 0; ii < dataInfo->numChans; ii++) {
+    dataInfo->tp[ii].tpnum = pInfo->tp[ii].tpnum;
+    dataInfo->tp[ii].dataType = pInfo->tp[ii].dataType;
+    dataInfo->tp[ii].dataRate = pInfo->tp[ii].dataRate;
+    mydatatype = dataInfo->tp[ii].dataType;
+    dataLength += DAQ_DATA_TYPE_SIZE(mydatatype) * dataInfo->tp[ii].dataRate /
+                  DAQ_NUM_DATA_BLOCKS;
+    // if(mydatatype == 5) printf("Found double
+    // %d\n",DAQ_DATA_TYPE_SIZE(mydatatype));
+  }
+  /// \> Set DAQ bytes/sec global, which is output to EPICS by controller.c
+  curDaqBlockSize = dataLength * DAQ_NUM_DATA_BLOCKS_PER_SECOND;
 
+  /// \> RETURN dataLength, used in other code for CRC checksum byte count
+  return (dataLength);
 }
 
 // **************************************************************************************
 ///	@author R.Bork\n
 ///	@brief This function populates the local DAQ/TP tables.
 ///	@param *pDxi	Pointer to struct with data transfer size information.
-///	@param localTable[]	Table to be populated with data pointer information
+///	@param localTable[]	Table to be populated with data pointer
+///information
 ///	@param sysRate			Number of code cycles in 1/16 second.
 ///	@param *dataInfo		DAQ configuration information
-///	@param *daqRange		Info on GDS TP number ranges which provides type information 
+///	@param *daqRange		Info on GDS TP number ranges which provides
+///type information
 ///	@return	0=OK or -1=FAIL
 // **************************************************************************************
-int loadLocalTable(DAQ_XFER_INFO *pDxi,
-		   DAQ_LKUP_TABLE localTable[],
-		   int sysRate,
-		   DAQ_INFO_BLOCK *dataInfo,
-	     	   DAQ_RANGE *daqRange
-		  )
-{
-int ii,jj;
-int mydatatype;
-
-
-    /// \> Get the .INI file crc checksum to pass to DAQ Framebuilders for config checking */
-    pDxi->fileCrc = pInfo->configFileCRC;
-    /// \> Calculate the number of bytes to xfer on each call, based on total number
-    ///   of bytes to write each 1/16sec and the front end data rate (2048/16384Hz)
-    pDxi->xferSize1 = pDxi->crcLength/sysRate;
-    pDxi->totalSize = pDxi->crcLength;
-    pDxi->totalSizeNet = pDxi->crcLength;
-
-    // printf (" xfer sizes = %d %d %d %d \n",sysRate,pDxi->xferSize1,pDxi->totalSize,pDxi->crcLength);
-    
-#if 0
-    /// \> Maintain 8 byte data boundaries for writing data, particularly important
-    ///    when DMA xfers are used on 5565 RFM modules. Note that this usually results
-    ///    in data not being written on every 2048/16384 cycle and last data xfer
-    ///    in a 1/16 sec block well may be shorter than the rest.	
- 	pDxi->xferSize1 = ((pDxi->xferSize1/8) + 1) * 8;
-	printf("DAQ resized %d\n", pDxi->xferSize1);
-#endif
-
-   /// \> Find first memory location for fast data in read/write swing buffers.
-    pDxi->offsetAccum = 4 * dataInfo->numEpicsTotal;
-    localTable[0].offset = pDxi->offsetAccum;
-
-   /// \> Fill in the local lookup table for finding data.
-   /// - (Need to develop a table of offset pointers to load data into swing buffers)  \n 
-   /// - (This is based on decimation factors and data size.)
-for(ii=0;ii<dataInfo->numChans;ii++)
-    {
-      if ((dataInfo->tp[ii].dataRate / DAQ_NUM_DATA_BLOCKS) > sysRate) {
-        /* Channel data rate is greater than system rate */
-        // printf("Channels %d has bad data rate %d\n", ii, dataInfo->tp[ii].dataRate);
-        return(-1);
-      } else {
+int loadLocalTable(DAQ_XFER_INFO *pDxi, DAQ_LKUP_TABLE localTable[],
+                   int sysRate, DAQ_INFO_BLOCK *dataInfo, DAQ_RANGE *daqRange) {
+  int ii, jj;
+  int mydatatype;
+
+  /// \> Get the .INI file crc checksum to pass to DAQ Framebuilders for config
+  /// checking */
+  pDxi->fileCrc = pInfo->configFileCRC;
+  /// \> Calculate the number of bytes to xfer on each call, based on total
+  /// number
+  ///   of bytes to write each 1/16sec and the front end data rate
+  ///   (2048/16384Hz)
+  pDxi->xferSize1 = pDxi->crcLength / sysRate;
+  pDxi->totalSize = pDxi->crcLength;
+  pDxi->totalSizeNet = pDxi->crcLength;
+
+  /// \> Find first memory location for fast data in read/write swing buffers.
+  pDxi->offsetAccum = 4 * dataInfo->numEpicsTotal;
+  localTable[0].offset = pDxi->offsetAccum;
+
+  /// \> Fill in the local lookup table for finding data.
+  /// - (Need to develop a table of offset pointers to load data into swing
+  /// buffers)  \n
+  /// - (This is based on decimation factors and data size.)
+  for (ii = 0; ii < dataInfo->numChans; ii++) {
+    if ((dataInfo->tp[ii].dataRate / DAQ_NUM_DATA_BLOCKS) > sysRate) {
+      /* Channel data rate is greater than system rate */
+      // printf("Channels %d has bad data rate %d\n", ii,
+      // dataInfo->tp[ii].dataRate);
+      return (-1);
+    } else {
       /// - ---- Load decimation factor
-      localTable[ii].decFactor = sysRate/(dataInfo->tp[ii].dataRate / DAQ_NUM_DATA_BLOCKS);
-      }
-
-      /// - ---- Calc offset into swing buffer for writing data
-      mydatatype = dataInfo->tp[ii].dataType;
-      pDxi->offsetAccum += (sysRate/localTable[ii].decFactor * DAQ_DATA_TYPE_SIZE(mydatatype));
-
-      localTable[ii+1].offset = pDxi->offsetAccum;
-      /// - ----  Need to determine if data is from a filter module TP or non-FM TP and tag accordingly
-      if((dataInfo->tp[ii].tpnum >= daqRange->filtTpMin) &&
-         (dataInfo->tp[ii].tpnum < daqRange->filtTpMax))
-      /* This is a filter module testpoint */
-      {
-        jj = dataInfo->tp[ii].tpnum - daqRange->filtTpMin;
-        /* Mark as coming from a filter module testpoint */
-        localTable[ii].type = DAQ_SRC_FM_TP;
-        /* Mark which system filter module is in */
-        localTable[ii].sysNum = jj / daqRange->filtTpSize;
-        jj -= localTable[ii].sysNum * daqRange->filtTpSize;
-        /* Mark which filter module within a system */
-        localTable[ii].fmNum = jj / DAQ_NUM_FM_TP;
-        /* Mark which of three testpoints to store */
-        localTable[ii].sigNum = jj % DAQ_NUM_FM_TP;
-      }
-      else if((dataInfo->tp[ii].tpnum >= daqRange->filtExMin) &&
-         (dataInfo->tp[ii].tpnum < daqRange->filtExMax))
-      /* This is a filter module excitation input */
-      {
-        /* Mark as coming from a filter module excitation input */
-        localTable[ii].type = DAQ_SRC_FM_EXC;
-        /* Mark filter module number */
-        localTable[ii].fmNum =  dataInfo->tp[ii].tpnum - daqRange->filtExMin;
-      }
-      else if((dataInfo->tp[ii].tpnum >= daqRange->xTpMin) &&
-         (dataInfo->tp[ii].tpnum < daqRange->xTpMax))
-      /* This testpoint is not part of a filter module */
-      {
-        jj = dataInfo->tp[ii].tpnum - daqRange->xTpMin;
-        /* Mark as a non filter module testpoint */
-        localTable[ii].type = DAQ_SRC_NFM_TP;
-        /* Mark the offset into the local data buffer */
-        localTable[ii].sigNum = jj;
-      }
-      // :TODO: this is broken, needs some work to make extra EXC work.
-      else if((dataInfo->tp[ii].tpnum >= daqRange->xExMin) &&
-         (dataInfo->tp[ii].tpnum < daqRange->xExMax))
-      /* This exc testpoint is not part of a filter module */
-      {
-	jj = dataInfo->tp[ii].tpnum - daqRange->xExMin;
-        /* Mark as a non filter module testpoint */
-        localTable[ii].type = DAQ_SRC_NFM_EXC;
-        /* Mark the offset into the local data buffer */
-        localTable[ii].fmNum = jj;
-        localTable[ii].sigNum = jj;
-      }
-      else
-      {
-        // printf("Invalid chan num found %d = %d\n",ii,dataInfo->tp[ii].tpnum);
-        return(-1);
-      }
-      // printf("Table %d Offset = %d  Type = %d\n",ii,localTable[ii].offset,dataInfo->tp[ii].dataType);
-}
-return(0);
-/// \> RETURN 0=OK or -1=FAIL
+      localTable[ii].decFactor =
+          sysRate / (dataInfo->tp[ii].dataRate / DAQ_NUM_DATA_BLOCKS);
+    }
 
+    /// - ---- Calc offset into swing buffer for writing data
+    mydatatype = dataInfo->tp[ii].dataType;
+    pDxi->offsetAccum +=
+        (sysRate / localTable[ii].decFactor * DAQ_DATA_TYPE_SIZE(mydatatype));
+
+    localTable[ii + 1].offset = pDxi->offsetAccum;
+    /// - ----  Need to determine if data is from a filter module TP or non-FM
+    /// TP and tag accordingly
+    if ((dataInfo->tp[ii].tpnum >= daqRange->filtTpMin) &&
+        (dataInfo->tp[ii].tpnum < daqRange->filtTpMax))
+    /* This is a filter module testpoint */
+    {
+      jj = dataInfo->tp[ii].tpnum - daqRange->filtTpMin;
+      /* Mark as coming from a filter module testpoint */
+      localTable[ii].type = DAQ_SRC_FM_TP;
+      /* Mark which system filter module is in */
+      localTable[ii].sysNum = jj / daqRange->filtTpSize;
+      jj -= localTable[ii].sysNum * daqRange->filtTpSize;
+      /* Mark which filter module within a system */
+      localTable[ii].fmNum = jj / DAQ_NUM_FM_TP;
+      /* Mark which of three testpoints to store */
+      localTable[ii].sigNum = jj % DAQ_NUM_FM_TP;
+    } else if ((dataInfo->tp[ii].tpnum >= daqRange->filtExMin) &&
+               (dataInfo->tp[ii].tpnum < daqRange->filtExMax))
+    /* This is a filter module excitation input */
+    {
+      /* Mark as coming from a filter module excitation input */
+      localTable[ii].type = DAQ_SRC_FM_EXC;
+      /* Mark filter module number */
+      localTable[ii].fmNum = dataInfo->tp[ii].tpnum - daqRange->filtExMin;
+    } else if ((dataInfo->tp[ii].tpnum >= daqRange->xTpMin) &&
+               (dataInfo->tp[ii].tpnum < daqRange->xTpMax))
+    /* This testpoint is not part of a filter module */
+    {
+      jj = dataInfo->tp[ii].tpnum - daqRange->xTpMin;
+      /* Mark as a non filter module testpoint */
+      localTable[ii].type = DAQ_SRC_NFM_TP;
+      /* Mark the offset into the local data buffer */
+      localTable[ii].sigNum = jj;
+    }
+    else if ((dataInfo->tp[ii].tpnum >= daqRange->xExMin) &&
+             (dataInfo->tp[ii].tpnum < daqRange->xExMax))
+    /* This exc testpoint is not part of a filter module */
+    {
+      jj = dataInfo->tp[ii].tpnum - daqRange->xExMin;
+      /* Mark as a non filter module testpoint */
+      localTable[ii].type = DAQ_SRC_NFM_EXC;
+      /* Mark the offset into the local data buffer */
+      localTable[ii].fmNum = jj;
+      localTable[ii].sigNum = jj;
+    } else {
+      // printf("Invalid chan num found %d = %d\n",ii,dataInfo->tp[ii].tpnum);
+      return (-1);
+    }
+    // printf("Table %d Offset = %d  Type =
+    // %d\n",ii,localTable[ii].offset,dataInfo->tp[ii].dataType);
+  }
+  return (0);
+  /// \> RETURN 0=OK or -1=FAIL
 }
diff --git a/src/include/drv/iop_adc_functions.c b/src/include/drv/iop_adc_functions.c
index 9842ddb110195bd0fd25e464202738fc654e9150..fabeaca9edaaabf44d1cb35fa4f16aa7a774b183 100644
--- a/src/include/drv/iop_adc_functions.c
+++ b/src/include/drv/iop_adc_functions.c
@@ -99,7 +99,6 @@ inline int sync_adc_2_1pps() {
 	    adcDummyData = (int *)cdsPciModules.pci_adc[0];
             adcDummyData += 31;
             gsc16ai64Enable1PPS(jj);
-            // rdtscll(cpuClock[jj]);
             status = gsc16ai64WaitDmaDone(0, adcDummyData);
             kk ++;
             udelay(2);
@@ -143,11 +142,11 @@ inline int iop_adc_read (adcInfo_t *adcinfo,int cpuClk[])
         packedData = (int *)cdsPciModules.pci_adc[jj];
         packedData += 31;
 		
-        rdtscll(cpuClk[CPU_TIME_RDY_ADC]);
+	cpuClk[CPU_TIME_RDY_ADC] = rdtsc_ordered();
         do {
             /// - ---- Need to delay if not ready as constant banging of the input register
             /// will slow down the ADC DMA.
-            rdtscll(cpuClk[CPU_TIME_ADC_WAIT]);
+	    cpuClk[CPU_TIME_ADC_WAIT] = rdtsc_ordered();
             adcinfo->adcWait = (cpuClk[CPU_TIME_ADC_WAIT] - cpuClk[CPU_TIME_RDY_ADC])/CPURATE;
             /// - ---- Allow 1sec for data to be ready (should never take that long).
         }while((*packedData == DUMMY_ADC_VAL) && (adcinfo->adcWait < MAX_ADC_WAIT));
@@ -192,7 +191,7 @@ inline int iop_adc_read (adcInfo_t *adcinfo,int cpuClk[])
         if(jj == 0) 
         {
         // Capture cpu clock for cpu meter diagnostics
-            rdtscll(cpuClk[CPU_TIME_CYCLE_START]);
+	    cpuClk[CPU_TIME_CYCLE_START] = rdtsc_ordered();
             /// \> If first cycle of a new second, capture IRIG-B time. Standard for aLIGO is
             /// TSYNC_RCVR.
             if(cycleNum == 0) 
@@ -311,11 +310,11 @@ inline int iop_adc_read_32 (adcInfo_t *adcinfo,int cpuClk[])
         packedData = (int *)cdsPciModules.pci_adc[jj];
         packedData += 63;
 		
-        rdtscll(cpuClk[CPU_TIME_RDY_ADC]);
+	cpuClk[CPU_TIME_RDY_ADC] = rdtsc_ordered();
         do {
             /// - ---- Need to delay if not ready as constant banging of the input register
             /// will slow down the ADC DMA.
-            rdtscll(cpuClk[CPU_TIME_ADC_WAIT]);
+	    cpuClk[CPU_TIME_ADC_WAIT] = rdtsc_ordered();
             adcinfo->adcWait = (cpuClk[CPU_TIME_ADC_WAIT] - cpuClk[CPU_TIME_RDY_ADC])/CPURATE;
             /// - ---- Allow 1sec for data to be ready (should never take that long).
         }while((*packedData == DUMMY_ADC_VAL) && (adcinfo->adcWait < MAX_ADC_WAIT));
@@ -353,7 +352,7 @@ inline int iop_adc_read_32 (adcInfo_t *adcinfo,int cpuClk[])
         if(jj == 0) 
         {
         // Capture cpu clock for cpu meter diagnostics
-            rdtscll(cpuClk[CPU_TIME_CYCLE_START]);
+	    cpuClk[CPU_TIME_CYCLE_START] = rdtsc_ordered();
             /// \> If first cycle of a new second, capture IRIG-B time. Standard for aLIGO is
             /// TSYNC_RCVR.
             if(cycleNum == 0) 
diff --git a/src/ix_stream/Makefile b/src/ix_stream/Makefile
index 940e44600ce77129a929c77f2b1132be58f3696c..c11190b414791511846580790874f677de3a3809 100644
--- a/src/ix_stream/Makefile
+++ b/src/ix_stream/Makefile
@@ -32,8 +32,7 @@ endif
 
 
 
-#all : ix_multi_stream ix_rcvr ix_rcvr_threads ix_dc_xmit ix_fb_rcv ix_convert zmq_rcv_ix_xmit
-all : omx_recv zmq_recv ix_recv
+all : ix_multi_stream ix_rcvr ix_rcvr_threads ix_dc_xmit ix_fb_rcv ix_convert zmq_rcv_ix_xmit
 
 rfm.o: ../drv/rfm.c
 	$(CC) $(CFLAGS) -c $< -o $@
@@ -44,25 +43,39 @@ param.o: ../drv/param.c
 crc.o: ../drv/crc.c
 	$(CC) $(CFLAGS) -c $< -o $@
 
-#ix_rcvr: ix_rcvr.c
-#	$(CC) $(CFLAGS) ix_rcvr.c -c -o ix_rcvr.o
-#	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o
-#	$(CC) $(FLAGS) -o ix_rcvr  ix_rcvr.o  rfm.o -L $(API_LIB_PATH) -lsisci
-#	sync
-
-#ix_rcvr_threads: ix_rcvr_threads.c
-#	$(CC) $(CFLAGS) ix_rcvr_threads.c -c -o ix_rcvr_threads.o
-#	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o
-#	$(CC) $(FLAGS) -o ix_rcvr_threads  ix_rcvr_threads.o  rfm.o -L $(API_LIB_PATH) -lsisci
-#	sync
-
-#ix_dc_xmit: ix_dc_xmit.c
-#	$(CC) $(CFLAGS) ix_dc_xmit.c -c -o ix_dc_xmit.o
-#	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o
-#	$(CC) $(FLAGS) -o ix_dc_xmit  ix_dc_xmit.o  rfm.o -L $(API_LIB_PATH) -lsisci
-#	sync
-
-zmq_recv: zmq_rcv_ix_xmit.c
+ix_rcvr: ix_rcvr.c 
+	$(CC) $(CFLAGS) ix_rcvr.c -c -o ix_rcvr.o 
+	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o 
+	$(CC) $(FLAGS) -o ix_rcvr  ix_rcvr.o  rfm.o -L $(API_LIB_PATH) -lsisci
+	sync
+
+ix_rcvr_threads: ix_rcvr_threads.c 
+	$(CC) $(CFLAGS) ix_rcvr_threads.c -c -o ix_rcvr_threads.o 
+	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o 
+	$(CC) $(FLAGS) -o ix_rcvr_threads  ix_rcvr_threads.o  rfm.o -L $(API_LIB_PATH) -lsisci
+	sync
+
+ix_dc_xmit: ix_dc_xmit.c 
+	$(CC) $(CFLAGS) ix_dc_xmit.c -c -o ix_dc_xmit.o 
+	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o 
+	$(CC) $(FLAGS) -o ix_dc_xmit  ix_dc_xmit.o  rfm.o -L $(API_LIB_PATH) -lsisci
+	sync
+
+mx2ix: mx2ix.c 
+	$(CC) $(CFLAGS) -I../zmq_stream -I/opt/open-mx/include mx2ix.c -c -o mx2ix.o
+	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o 
+	$(CC) $(CFLAGS) -I../zmq_stream ../zmq_stream/simple_pv.c -c -o simple_pv.o
+	$(CC) $(FLAGS) -o mx2ix  mx2ix.o  rfm.o simple_pv.o -L $(API_LIB_PATH) -L/opt/open-mx/lib -lsisci -lmyriexpress -lpthread
+	sync
+
+mx2rcv: mx2rcv.c 
+	$(CC) $(CFLAGS) -I../zmq_stream -I/opt/open-mx/include mx2rcv.c -c -o mx2rcv.o
+	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o 
+	$(CC) $(CFLAGS) -I../zmq_stream ../zmq_stream/simple_pv.c -c -o simple_pv.o
+	$(CC) $(FLAGS) -o mx2rcv  mx2rcv.o  rfm.o simple_pv.o -L $(API_LIB_PATH) -L/opt/open-mx/lib -lmyriexpress -lpthread
+	sync
+
+zmq_rcv_ix_xmit: zmq_rcv_ix_xmit.c 
 	$(CC) $(CFLAGS) -I../zmq_stream zmq_rcv_ix_xmit.c -c -o zmq_rcv_ix_xmit.o
 	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o
 	$(CC) $(CFLAGS) -I../zmq_stream ../zmq_stream/simple_pv.c -c -o simple_pv.o
@@ -71,7 +84,7 @@ zmq_recv: zmq_rcv_ix_xmit.c
 	$(CC) $(FLAGS) -o zmq_rcv_ix_xmit  zmq_rcv_ix_xmit.o  rfm.o zmq_transport.o dc_utils.o simple_pv.o -L $(API_LIB_PATH) -lsisci -lzmq -lpthread
 	sync
 
-ix_recv: ix_fb_rcv.c
+ix_fb_rcv: ix_fb_rcv.c 
 	$(CC) $(CFLAGS) ix_fb_rcv.c -c -o ix_fb_rcv.o 
 	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o 
 	$(CC) $(FLAGS) -o ix_fb_rcv  ix_fb_rcv.o  rfm.o -L $(API_LIB_PATH) -lsisci
diff --git a/src/ix_stream/mx2rcv.c b/src/ix_stream/mx2rcv.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e75f819f9586b986b31d9ecfe8ee6688d8ba290
--- /dev/null
+++ b/src/ix_stream/mx2rcv.c
@@ -0,0 +1,823 @@
+//
+/// @file mx2ix.c
+/// @brief  DAQ data concentrator code. Receives data via Open-MX and sends via Dolphin IX..
+//
+
+#include "myriexpress.h"
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include "../drv/crc.c"
+#include <time.h>
+#include "../include/daqmap.h"
+#include "../include/daq_core.h"
+#include "../zmq_stream/dc_utils.h"
+
+// #include "testlib.h"
+
+#include "../zmq_stream/simple_pv.h"
+
+#define __CDECL
+
+#define DO_HANDSHAKE 0
+
+
+
+#define MIN_DELAY_MS 5
+#define MAX_DELAY_MS 40
+
+#define MAX_FE_COMPUTERS 32
+
+#define MX_MUTEX_T pthread_mutex_t
+#define MX_MUTEX_INIT(mutex_) pthread_mutex_init(mutex_, 0)
+#define MX_MUTEX_LOCK(mutex_) pthread_mutex_lock(mutex_)
+#define MX_MUTEX_UNLOCK(mutex_) pthread_mutex_unlock(mutex_)
+
+#define MX_THREAD_T pthread_t
+#define MX_THREAD_CREATE(thread_, start_routine_, arg_) \
+pthread_create(thread_, 0, start_routine_, arg_)
+#define MX_THREAD_JOIN(thread_) pthread_join(thread, 0)
+
+MX_MUTEX_T stream_mutex;
+
+#define FILTER     0x12345
+#define MATCH_VAL  0xabcdef
+#define DFLT_EID   1
+#define DFLT_LEN   8192
+#define DFLT_END   128
+#define MAX_LEN    (1024*1024*1024) 
+#define DFLT_ITER  1000
+#define NUM_RREQ   16  /* currently constrained by  MX_MCP_RDMA_HANDLES_CNT*/
+#define NUM_SREQ   256  /* currently constrained by  MX_MCP_RDMA_HANDLES_CNT*/
+
+#define DO_HANDSHAKE 0
+#define MATCH_VAL_MAIN (1 << 31)
+#define MATCH_VAL_THREAD 1
+#define THREADS_PER_NIC     16
+#define IX_STOP_SEC     5
+
+// daq_multi_cycle_header_t *xmitHeader[IX_BLOCK_COUNT];
+
+extern void *findSharedMemorySize(char *,int);
+
+int do_verbose = 0;
+
+struct thread_info {
+    int index;
+    uint32_t match_val;
+    uint32_t tpn;
+    uint32_t bid;
+};
+struct thread_mon_info {
+    int index;
+    void *ctx;
+};
+struct thread_info thread_index[DCU_COUNT];
+char *sname[DCU_COUNT]; // Names of FE computers serving DAQ data
+char *local_iface[MAX_FE_COMPUTERS];
+daq_multi_dcu_data_t mxDataBlockSingle[MAX_FE_COMPUTERS];
+int64_t dataRecvTime[MAX_FE_COMPUTERS];
+const int mc_header_size = sizeof(daq_multi_cycle_header_t);
+int stop_working_threads = 0;
+int start_acq = 0;
+static volatile int keepRunning = 1;
+int thread_cycle[MAX_FE_COMPUTERS];
+int thread_timestamp[MAX_FE_COMPUTERS];
+int rcv_errors = 0;
+int dataRdy[MAX_FE_COMPUTERS];
+
+void
+usage()
+{
+    fprintf(stderr, "Usage: mx2ix [args] -s server names -m shared memory size -g IX channel \n");
+    fprintf(stderr, "-l filename - log file name\n");
+    fprintf(stderr, "-s - number of FE computers to connect (1-32): Default = 32\n");
+    fprintf(stderr, "-v - verbose prints diag test data\n");
+    fprintf(stderr, "-g - Dolphin IX channel to xmit on (0-3)\n");
+    fprintf(stderr, "-p - Debug pv prefix, requires -P as well\n");
+    fprintf(stderr, "-P - Path to a named pipe to send PV debug information to\n");
+    fprintf(stderr, "-d - Max delay in milli seconds to wait for a FE to send data, defaults to 10\n");
+    fprintf(stderr, "-t - Number of rcvr threads per NIC: default = 16\n");
+    fprintf(stderr, "-n - Data Concentrator number (0 or 1) : default = 0\n");
+    fprintf(stderr, "-h - help\n");
+}
+
+// *************************************************************************
+// Timing Diagnostic Routine
+// *************************************************************************
+static int64_t
+s_clock (void)
+{
+struct timeval tv;
+    gettimeofday (&tv, NULL);
+    return (int64_t) (tv.tv_sec * 1000 + tv.tv_usec / 1000);
+}
+
+// *************************************************************************
+// Catch Control C to end cod in controlled manner
+// *************************************************************************
+void intHandler(int dummy) {
+    keepRunning = 0;
+}
+
+void sigpipeHandler(int dummy)
+{}
+
+// **********************************************************************************************
+void print_diags(int nsys, int lastCycle, int sendLength, daq_multi_dcu_data_t *ixDataBlock,int dbs[]) {
+// **********************************************************************************************
+    int ii = 0;
+        // Print diags in verbose mode
+        fprintf(stderr,"Receive errors = %d\n",rcv_errors);
+        fprintf(stderr,"Time = %d\t size = %d\n",ixDataBlock->header.dcuheader[0].timeSec,sendLength);
+        fprintf(stderr,"DCU ID\tCycle \t TimeSec\tTimeNSec\tDataSize\tTPCount\tTPSize\tXmitSize\n");
+        for(ii=0;ii<nsys;ii++) {
+            fprintf(stderr,"%d",ixDataBlock->header.dcuheader[ii].dcuId);
+            fprintf(stderr,"\t%d",ixDataBlock->header.dcuheader[ii].cycle);
+            fprintf(stderr,"\t%d",ixDataBlock->header.dcuheader[ii].timeSec);
+            fprintf(stderr,"\t%d",ixDataBlock->header.dcuheader[ii].timeNSec);
+            fprintf(stderr,"\t\t%d",ixDataBlock->header.dcuheader[ii].dataBlockSize);
+            fprintf(stderr,"\t\t%d",ixDataBlock->header.dcuheader[ii].tpCount);
+            fprintf(stderr,"\t%d",ixDataBlock->header.dcuheader[ii].tpBlockSize);
+            fprintf(stderr,"\t%d",dbs[ii]);
+            fprintf(stderr,"\n ");
+        }
+}
+
+
+// *************************************************************************
+// Thread for receiving DAQ data via Open-MX
+// *************************************************************************
+void *rcvr_thread(void *arg) {
+    struct thread_info* my_info = (struct thread_info*)arg;
+    int mt = my_info->index;
+    uint32_t mv = my_info->match_val;
+    uint32_t board_id = my_info->bid;
+    uint32_t tpn = my_info->tpn;
+    int cycle = 0;
+    daq_multi_dcu_data_t *mxDataBlock;
+    mx_return_t ret;
+    int count, len, cur_req;
+    mx_status_t stat;
+    mx_request_t req[NUM_RREQ];
+    mx_segment_t seg;
+    uint32_t result;
+    char *buffer;
+    uint32_t filter;
+    mx_endpoint_t ep;
+    int myErrorStat = 0;
+
+    filter = FILTER;
+    int copySize;
+
+
+    int dblock = board_id * tpn + mt;
+    fprintf(stderr,"Starting receive loop for thread %d %d\n", board_id,mt);
+
+    ret = mx_open_endpoint(board_id, mt, filter, NULL, 0, &ep);
+    if (ret != MX_SUCCESS) {
+        fprintf(stderr, "Failed to open endpoint %s\n", mx_strerror(ret));
+        return(0);
+    }
+
+    fprintf(stderr,"waiting for someone to connect on CH %d\n",mt);
+    len = 0xf00000;
+    fprintf(stderr,"buffer length = %d\n",len);
+    buffer = (char *)malloc(len);
+    if (buffer == NULL) {
+       fprintf(stderr, "Can't allocate buffers here\n");
+       mx_close_endpoint(ep);
+       return(0);
+    }
+    len /= NUM_RREQ;
+    fprintf(stderr," length = %d\n",len);
+
+    for (cur_req = 0; cur_req < NUM_RREQ; cur_req++) {
+       seg.segment_ptr = &buffer[cur_req * len];
+       seg.segment_length = len;
+       mx_irecv(ep, &seg, 1, mv, MX_MATCH_MASK_NONE, 0,
+       &req[cur_req]);
+    }
+
+    mx_set_error_handler(MX_ERRORS_RETURN);
+
+    char *daqbuffer = (char *)&mxDataBlockSingle[dblock];
+    do {
+      for (count = 0; count < NUM_RREQ; count++) {
+         cur_req = count & (16 - 1);
+         mx_wait(ep, &req[cur_req],150, &stat, &result);
+         myErrorStat = 0;
+         if (!result) {
+             myErrorStat = 1;
+             count --;
+         }
+         if (stat.code != MX_STATUS_SUCCESS) {
+            myErrorStat = 2;
+         }
+         if(!myErrorStat) {
+            seg.segment_ptr = &buffer[cur_req * len];
+            mxDataBlock = (daq_multi_dcu_data_t *)seg.segment_ptr;
+            copySize = stat.xfer_length;
+            memcpy(daqbuffer,seg.segment_ptr,copySize);
+            // Get the message DAQ cycle number
+            cycle = mxDataBlock->header.dcuheader[0].cycle;
+            // Pass cycle and timestamp data back to main process
+            thread_cycle[dblock] = cycle;
+            thread_timestamp[dblock] = mxDataBlock->header.dcuheader[0].timeSec;
+            dataRecvTime[dblock] = s_clock();
+            mx_irecv(ep, &seg, 1, mv, MX_MATCH_MASK_NONE, 0, &req[cur_req]);
+         }
+
+       }
+    // Run until told to stop by main thread
+    } while(!stop_working_threads);
+    fprintf(stderr,"Stopping thread %d\n",mt);
+    usleep(200000);
+
+    mx_close_endpoint(ep);
+    return(0);
+
+}
+
+// *************************************************************************
+// Main Process
+// *************************************************************************
+int
+main(int argc, char **argv)
+{
+    pthread_t thread_id[MAX_FE_COMPUTERS];
+    unsigned int nsys = MAX_FE_COMPUTERS; // The number of mapped shared memories (number of data sources)
+    char *buffer_name = "ifo";
+    int c;
+    int ii;                 // Loop counter
+    int delay_ms = 10;
+    int delay_cycles = 0;
+
+    extern char *optarg;    // Needed to get arguments to program
+
+    // PV/debug information
+    char *pv_prefix = 0;
+    char *pv_debug_pipe_name = 0;
+    int pv_debug_pipe = -1;
+
+    // Declare shared memory data variables
+    daq_multi_cycle_header_t *ifo_header;
+    char *ifo;
+    char *ifo_data;
+    int cycle_data_size;
+    daq_multi_dcu_data_t *ifoDataBlock;
+    char *nextData;
+    int max_data_size_mb = 100;
+    int max_data_size = 0;
+    char *mywriteaddr;
+    int dc_number = 1;
+    
+
+    /* set up defaults */
+    int xmitData = 0;
+    int tpn = THREADS_PER_NIC;
+
+
+
+    // Get arguments sent to process
+    while ((c = getopt(argc, argv, "b:hs:m:g:vp:P:d:l:t:n:")) != EOF) switch(c) {
+    case 's':
+        nsys = atoi(optarg);
+        if(nsys > MAX_FE_COMPUTERS) {
+            fprintf(stderr,"Max number of FE computers is 32\n");
+            usage();
+            exit(1);
+        }
+        break;
+    case 'v':
+        do_verbose = 1;
+        break;
+    case 'n':
+        dc_number = atoi(optarg);
+        dc_number ++;
+        if(dc_number > 2) {
+            fprintf(stderr,"DC number must be 0 or 1\n");
+            usage();
+            exit(1);
+        }
+        break;
+    case 'm':
+        max_data_size_mb = atoi(optarg);
+        if (max_data_size_mb < 20){
+            fprintf(stderr,"Min data block size is 20 MB\n");
+            return -1;
+        }
+        if (max_data_size_mb > 100){
+            fprintf(stderr,"Max data block size is 100 MB\n");
+            return -1;
+        }
+        break;
+    case 't':
+            tpn = atoi(optarg);
+            break;
+    case 'b':
+        buffer_name = optarg;
+        break;
+    case 'p':
+        pv_prefix = optarg;
+        break;
+    case 'P':
+        pv_debug_pipe_name = optarg;
+        break;
+    case 'd':
+        delay_ms = atoi(optarg);
+        if (delay_ms < MIN_DELAY_MS || delay_ms > MAX_DELAY_MS) {
+            fprintf(stderr,"The delay factor must be between 5ms and 40ms\n");
+            return -1;
+        }
+        break;
+    case 'l':
+        if (0 == freopen(optarg, "w", stdout)) {
+            perror ("freopen");
+            exit (1);
+        }
+        setvbuf(stdout, NULL, _IOLBF, 0);
+        stderr = stdout;
+        break;
+    case 'h':
+    default:
+        usage();
+        exit(1);
+    }
+    max_data_size = max_data_size_mb * 1024*1024;
+    delay_cycles = delay_ms * 10;
+
+    mx_init();
+    // MX_MUTEX_INIT(&stream_mutex);
+
+    // set up to catch Control C
+    signal(SIGINT,intHandler);
+    // setup to ignore sig pipe
+    signal(SIGPIPE, sigpipeHandler);
+
+    fprintf(stderr,"Num of sys = %d\n",nsys);
+
+    // Get pointers to local DAQ mbuf
+    ifo = (char *)findSharedMemorySize(buffer_name,max_data_size_mb);
+    ifo_header = (daq_multi_cycle_header_t *)ifo;
+    ifo_data = (char *)ifo + sizeof(daq_multi_cycle_header_t);
+    cycle_data_size = (max_data_size - sizeof(daq_multi_cycle_header_t)) / DAQ_NUM_DATA_BLOCKS_PER_SECOND;
+    cycle_data_size -= (cycle_data_size % 8);
+    fprintf (stderr,"cycle data size = %d\t%d\n",cycle_data_size, max_data_size_mb);
+    sleep(3);
+    ifo_header->cycleDataSize = cycle_data_size;
+    ifo_header->maxCycle = DAQ_NUM_DATA_BLOCKS_PER_SECOND;
+
+#if 0
+    if(xmitData) {
+        // Connect to Dolphin
+        error = dolphin_init();
+        fprintf(stderr,"Read = 0x%lx \n Write = 0x%lx \n",(long)readAddr,(long)writeAddr);
+
+        // Set pointer to xmit header in Dolphin xmit data area.
+        mywriteaddr = (char *)writeAddr;
+        for(ii=0;ii<IX_BLOCK_COUNT;ii++) {
+            xmitHeader[ii] = (daq_multi_cycle_header_t *)mywriteaddr;
+            mywriteaddr += IX_BLOCK_SIZE;
+            xmitDataOffset[ii] = IX_BLOCK_SIZE * ii + sizeof(struct daq_multi_cycle_header_t);
+            fprintf(stderr,"Dolphin at 0x%lx and 0x%lx",(long)xmitHeader[ii],(long)xmitDataOffset[ii]);
+        }
+    }
+#endif
+
+    fprintf(stderr,"nsys = %d\n",nsys);
+
+    // Make 0MQ socket connections
+    for(ii=0;ii<nsys;ii++) {
+        // Create a thread to receive data from each data server
+        thread_index[ii].index = ii % tpn;
+        thread_index[ii].match_val = MATCH_VAL_MAIN;
+        thread_index[ii].tpn = tpn;
+        thread_index[ii].bid = ii/tpn;
+        pthread_create(&thread_id[ii],NULL,rcvr_thread,(void *)&thread_index[ii]);
+
+    }
+    int nextCycle = 0;
+    start_acq = 1;
+    int64_t mytime = 0;
+    int64_t mylasttime = 0;
+    int64_t myptime = 0;
+    int64_t n_cycle_time = 0;
+    int mytotaldcu = 0;
+    char *zbuffer;
+    size_t zbuffer_remaining = 0;
+    int dc_datablock_size = 0;
+    int datablock_size_running = 0;
+    int datablock_size_mb_s = 0;
+    static const int header_size = sizeof(daq_multi_dcu_header_t);
+    char dcstatus[4096];
+    char dcs[48];
+    int edcuid[10];
+    int estatus[10];
+    int edbs[10];
+    unsigned long ets = 0;
+    int timeout = 0;
+    int threads_rdy;
+    int any_rdy = 0;
+    int jj,kk;
+    int sendLength = 0;
+
+    int min_cycle_time = 1 << 30;
+    int pv_min_cycle_time = 0;
+    int max_cycle_time = 0;
+    int pv_max_cycle_time = 0;
+    int mean_cycle_time = 0;
+    int pv_mean_cycle_time = 0;
+    int pv_dcu_count = 0;
+    int pv_total_datablock_size = 0;
+    int pv_datablock_size_mb_s = 0;
+    int uptime = 0;
+    int pv_uptime = 0;
+    int gps_time = 0;
+    int pv_gps_time = 0;
+    int missed_flag = 0;
+    int missed_nsys[MAX_FE_COMPUTERS];
+    int64_t recv_time[MAX_FE_COMPUTERS];
+    int64_t min_recv_time = 0;
+    int recv_buckets[(MAX_DELAY_MS/5)+2];
+    int festatus = 0;
+    int pv_festatus = 0;
+    int ix_xmit_stop = 0;
+    SimplePV pvs[] = {
+            {
+                    "RECV_MIN_MS",
+                    SIMPLE_PV_INT,
+                    &pv_min_cycle_time,
+
+                    80,
+                    45,
+                    70,
+                    54,
+            },
+            {
+                    "RECV_MAX_MS",
+                    SIMPLE_PV_INT,
+                    &pv_max_cycle_time,
+
+                    80,
+                    45,
+                    70,
+                    54,
+            },
+            {
+                    "RECV_MEAN_MS",
+                    SIMPLE_PV_INT,
+                    &pv_mean_cycle_time,
+
+                    80,
+                    45,
+                    70,
+                    54,
+            },
+            {
+                    "DCU_COUNT",
+                    SIMPLE_PV_INT,
+                    &pv_dcu_count,
+
+                    120,
+                    0,
+                    115,
+                    0,
+            },
+            {
+                    "DATA_SIZE",
+                    SIMPLE_PV_INT,
+                    &pv_total_datablock_size,
+
+                    100*1024*1024,
+                    0,
+                    90*1024*1024,
+                    1*1024*1024,
+            },
+            {
+                    "DATA_RATE",
+                    SIMPLE_PV_INT,
+                    &pv_datablock_size_mb_s,
+
+                    100*1024*1024,
+                    0,
+                    90*1024*1024,
+                    1000000,
+            },
+            {
+                    "UPTIME_SECONDS",
+                    SIMPLE_PV_INT,
+                    &pv_uptime,
+
+                    100*1024*1024,
+                    0,
+                    90*1024*1024,
+
+                    1,
+            },
+            {
+                    "RCV_STATUS",
+                    SIMPLE_PV_INT,
+                    &pv_festatus,
+
+                    0xffffffff,
+                    0,
+                    0xfffffffe,
+
+                    1,
+            },
+            {
+                    "GPS",
+                    SIMPLE_PV_INT,
+                    &pv_gps_time,
+
+                    0xfffffff,
+                    0,
+                    0xfffffffe,
+
+                    1,
+            },
+
+    };
+    if (pv_debug_pipe_name)
+    {
+        pv_debug_pipe = open(pv_debug_pipe_name, O_NONBLOCK | O_RDWR, 0);
+        if (pv_debug_pipe < 0) {
+            fprintf(stderr, "Unable to open %s for writting (pv status)\n", pv_debug_pipe_name);
+            exit(1);
+        }
+    }
+
+    missed_flag = 1;
+    memset(&missed_nsys[0], 0, sizeof(missed_nsys));
+    memset(recv_buckets, 0, sizeof(recv_buckets));
+    do {
+        // Reset counters
+        timeout = 0;
+        for(ii=0;ii<nsys;ii++) dataRdy[ii] = 0;
+        for(ii=0;ii<nsys;ii++) thread_cycle[ii] = 50;
+        threads_rdy = 0;
+        any_rdy = 0;
+
+        // Wait up to 100ms until received data from at least 1 FE or timeout
+        do {
+            usleep(2000);
+            for(ii=0;ii<nsys;ii++) {
+                if(nextCycle == thread_cycle[ii]) any_rdy = 1;
+            }
+            timeout += 1;
+        }while(!any_rdy && timeout < 50);
+#ifndef TIME_INTERVAL_DIAG
+        mytime = s_clock();
+#endif
+
+        // Wait up to delay_ms ms in 1/10ms intervals until data received from everyone or timeout
+        timeout = 0;
+        do {
+            usleep(100);
+            for(ii=0;ii<nsys;ii++) {
+                if(nextCycle == thread_cycle[ii] && !dataRdy[ii]) threads_rdy ++;
+                if(nextCycle == thread_cycle[ii]) dataRdy[ii] = 1;
+            }
+            timeout += 1;
+        }while(threads_rdy < nsys && timeout < delay_cycles);
+        if(timeout >= 100) rcv_errors += (nsys - threads_rdy);
+#ifndef TIME_INTERVAL_DIAG
+        mylasttime = s_clock();
+#endif
+
+        if(any_rdy) {
+            int tbsize = 0;
+#ifdef TIME_INTERVAL_DIAG
+            // Timing diagnostics for time between cycles
+            mytime = s_clock();
+            myptime = mytime - mylasttime;
+            mylasttime = mytime;
+#else
+            // Timing diagnostics for rcv window
+            myptime = mylasttime - mytime;
+#endif
+
+            if (myptime < min_cycle_time) {
+                min_cycle_time = myptime;
+            }
+            if (myptime > max_cycle_time) {
+                max_cycle_time = myptime;
+            }
+            mean_cycle_time += myptime;
+            ++n_cycle_time;
+
+            // Reset total DCU counter
+            mytotaldcu = 0;
+            // Reset total DC data size counter
+            dc_datablock_size = 0;
+            // Get pointer to next data block in shared memory
+            nextData = (char *)ifo_data;
+            nextData += cycle_data_size * nextCycle;
+            ifoDataBlock = (daq_multi_dcu_data_t *)nextData;
+            zbuffer = (char *)nextData + header_size;
+            zbuffer_remaining = cycle_data_size - header_size;
+
+            min_recv_time = 0x7fffffffffffffff;
+            festatus = 0;
+            // Loop over all data buffers received from FE computers
+            for(ii=0;ii<nsys;ii++) {
+                recv_time[ii] = -1;
+                if(dataRdy[ii]) {
+                    festatus += (1 << ii);
+                    recv_time[ii] = dataRecvTime[ii];
+                    if (recv_time[ii] < min_recv_time) {
+                        min_recv_time = recv_time[ii];
+                    }
+                    if (do_verbose && nextCycle == 0) {
+                        fprintf(stderr, "+++%d\n", ii);
+                    }
+                    int myc = mxDataBlockSingle[ii].header.dcuTotalModels;
+                    // For each model, copy over data header information
+                    for(jj=0;jj<myc;jj++) {
+                        // Copy data header information
+                        ifoDataBlock->header.dcuheader[mytotaldcu].dcuId = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].dcuId;
+                        ifoDataBlock->header.dcuheader[mytotaldcu].fileCrc = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].fileCrc;
+                        ifoDataBlock->header.dcuheader[mytotaldcu].status = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].status;
+                        ifoDataBlock->header.dcuheader[mytotaldcu].cycle = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].cycle;
+                        if(!ix_xmit_stop) {
+                            ifoDataBlock->header.dcuheader[mytotaldcu].timeSec = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].timeSec;
+                            ifoDataBlock->header.dcuheader[mytotaldcu].timeNSec = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].timeNSec;
+                        }
+                        ifoDataBlock->header.dcuheader[mytotaldcu].dataCrc = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].dataCrc;
+                        ifoDataBlock->header.dcuheader[mytotaldcu].dataBlockSize = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].dataBlockSize;
+                        ifoDataBlock->header.dcuheader[mytotaldcu].tpBlockSize = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].tpBlockSize;
+                        ifoDataBlock->header.dcuheader[mytotaldcu].tpCount = 
+                                mxDataBlockSingle[ii].header.dcuheader[jj].tpCount;
+
+                        // Check for downstream DAQ reset request from EDCU
+                        if(mxDataBlockSingle[ii].header.dcuheader[jj].dcuId == 52 && 
+                            mxDataBlockSingle[ii].header.dcuheader[jj].tpCount == dc_number)
+                        {
+                            fprintf(stderr,"Got a DAQ Reset REQUEST %u\n",mxDataBlockSingle[ii].header.dcuheader[jj].timeSec);
+                            ifoDataBlock->header.dcuheader[mytotaldcu].tpCount = 0;
+                            ix_xmit_stop = 16 * IX_STOP_SEC;
+                        }
+                        for(kk=0;kk<DAQ_GDS_MAX_TP_NUM ;kk++)   
+                            ifoDataBlock->header.dcuheader[mytotaldcu].tpNum[kk] = mxDataBlockSingle[ii].header.dcuheader[jj].tpNum[kk];
+                        edbs[mytotaldcu] = mxDataBlockSingle[ii].header.dcuheader[jj].tpBlockSize + mxDataBlockSingle[ii].header.dcuheader[jj].dataBlockSize;
+                        // Get some diags
+                        if(ifoDataBlock->header.dcuheader[mytotaldcu].status != 0xbad)
+                            ets = mxDataBlockSingle[ii].header.dcuheader[jj].timeSec;
+                        estatus[mytotaldcu] = ifoDataBlock->header.dcuheader[mytotaldcu].status;
+                        edcuid[mytotaldcu] = ifoDataBlock->header.dcuheader[mytotaldcu].dcuId;
+                        // Increment total DCU count
+                        mytotaldcu ++;
+                    }
+                    // Get the size of the data to transfer
+                    int mydbs = mxDataBlockSingle[ii].header.fullDataBlockSize;
+                    // Get pointer to data in receive data block
+                    char *mbuffer = (char *)&mxDataBlockSingle[ii].dataBlock[0];
+                    if (mydbs > zbuffer_remaining)
+                    {
+                        fprintf(stderr,"Buffer overflow found.  Attempting to write %d bytes to zbuffer which has %d bytes remainging\n",
+                                (int)mydbs, (int)zbuffer_remaining);
+                        abort();
+                    }
+                    // Copy data from receive buffer to shared memory
+                    memcpy(zbuffer,mbuffer,mydbs);
+                    // Increment shared memory data buffer pointer for next data set
+                    zbuffer += mydbs;
+                    // Calc total size of data block for this cycle
+                    dc_datablock_size += mydbs;
+                    tbsize += mydbs;
+                } else {
+                    missed_nsys[ii] |= missed_flag;
+                    if (do_verbose && nextCycle == 0) {
+                        fprintf(stderr, "---%d\n", ii);
+                    } 
+                }
+            }
+            // Write total data block size to shared memory header
+            ifoDataBlock->header.fullDataBlockSize = dc_datablock_size;
+            // Write total dcu count to shared memory header
+            ifoDataBlock->header.dcuTotalModels = mytotaldcu;
+            // Set multi_cycle head cycle to indicate data ready for this cycle
+            ifo_header->curCycle = nextCycle;
+
+            // Calc IX message size
+            sendLength = header_size + ifoDataBlock->header.fullDataBlockSize;
+            for (ii = 0; ii < nsys; ++ii) {
+                recv_time[ii] -= min_recv_time;
+            }
+            datablock_size_running += dc_datablock_size;
+            if (nextCycle == 0) {
+                datablock_size_mb_s = datablock_size_running / 1024 ;
+                pv_datablock_size_mb_s = datablock_size_mb_s;
+                uptime ++;
+                pv_uptime = uptime;
+                gps_time = ifoDataBlock->header.dcuheader[0].timeSec;
+                pv_gps_time = gps_time;
+                pv_dcu_count = mytotaldcu;
+                pv_festatus = festatus;
+                mean_cycle_time = (n_cycle_time > 0 ? mean_cycle_time / n_cycle_time : 1 << 31);
+
+                pv_mean_cycle_time = mean_cycle_time;
+                pv_max_cycle_time = max_cycle_time;
+                pv_min_cycle_time = min_cycle_time;
+                send_pv_update(pv_debug_pipe, pv_prefix, pvs, sizeof(pvs)/sizeof(pvs[0]));
+
+                if (do_verbose) {
+                    fprintf(stderr,"\nData rdy for cycle = %d\t\tTime Interval = %ld msec\n", nextCycle, myptime);
+                    fprintf(stderr,"Min/Max/Mean cylce time %d/%d/%d msec over %ld cycles\n", min_cycle_time, max_cycle_time,
+                        mean_cycle_time, n_cycle_time);
+                    fprintf(stderr,"Total DCU = %d\t\t\tBlockSize = %d\n", mytotaldcu, dc_datablock_size);
+                    print_diags(mytotaldcu, nextCycle, sendLength, ifoDataBlock, edbs);
+                }
+                n_cycle_time = 0;
+                min_cycle_time = 1 << 30;
+                max_cycle_time = 0;
+                mean_cycle_time = 0;
+
+
+                missed_flag = 1;
+                datablock_size_running = 0;
+            } else {
+                missed_flag <<= 1;
+            }
+#if 0
+            if(xmitData && !ix_xmit_stop) {
+                if (sendLength > IX_BLOCK_SIZE)
+                {
+                    fprintf(stderr, "Buffer overflow.  Sending %d bytes into a dolphin block that holds %d\n",
+                    (int)sendLength, (int)IX_BLOCK_SIZE);
+                    abort();
+                }
+                // WRITEDATA to Dolphin Network
+                SCIMemCpy(sequence,nextData, remoteMap,xmitDataOffset[xmitBlockNum],sendLength,memcpyFlag,&error);
+                error = SCI_ERR_OK;
+                if (error != SCI_ERR_OK) {
+                    fprintf(stderr,"SCIMemCpy failed - Error code 0x%x\n",error);
+                    fprintf(stderr,"For reference the expected error codes are:\n");
+                    fprintf(stderr,"SCI_ERR_OUT_OF_RANGE = 0x%x\n", SCI_ERR_OUT_OF_RANGE);
+                    fprintf(stderr,"SCI_ERR_SIZE_ALIGNMENT = 0x%x\n", SCI_ERR_SIZE_ALIGNMENT);
+                    fprintf(stderr,"SCI_ERR_OFFSET_ALIGNMENT = 0x%x\n", SCI_ERR_OFFSET_ALIGNMENT);
+                    fprintf(stderr,"SCI_ERR_TRANSFER_FAILED = 0x%x\n", SCI_ERR_TRANSFER_FAILED);
+                    return error;
+                }
+                // Set data header information
+                unsigned int maxCycle = ifo_header->maxCycle;
+                unsigned int curCycle = ifo_header->curCycle;
+                xmitHeader[xmitBlockNum]->maxCycle = maxCycle;
+                xmitHeader[xmitBlockNum]->cycleDataSize = sendLength;;
+                // Send cycle last as indication of data ready for receivers
+                xmitHeader[xmitBlockNum]->curCycle = curCycle;
+                // Have to flush the buffers to make data go onto Dolphin network
+                SCIFlush(sequence,SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY);
+            }
+#endif
+            if(ix_xmit_stop)  {
+                ix_xmit_stop --;
+                if(ix_xmit_stop == 0) fprintf(stderr,"Restarting Dolphin Xmit\n");
+            }
+
+        }
+        sprintf(dcstatus,"%ld ",ets);
+        for(ii=0;ii<mytotaldcu;ii++) {
+            sprintf(dcs,"%d %d %d ",edcuid[ii],estatus[ii],edbs[ii]);
+            strcat(dcstatus,dcs);
+        }
+
+
+        // Increment cycle count
+        nextCycle ++;
+        nextCycle %= 16;
+    }while (keepRunning);   // End of infinite loop
+
+    // Stop Rcv Threads
+    fprintf(stderr,"stopping threads %d \n",nsys);
+    stop_working_threads = 1;
+
+    // Wait for threads to stop
+    sleep(5);
+    fprintf(stderr,"closing out MX\n");
+    mx_finalize();
+  
+    exit(0);
+}
diff --git a/src/mx_stream/Makefile b/src/mx_stream/Makefile
index 3dc71997cdb985f4a11640f4b2b1eb00aad86e52..40674cf5003490dd1a6008006605ef071563cd22 100644
--- a/src/mx_stream/Makefile
+++ b/src/mx_stream/Makefile
@@ -16,19 +16,21 @@ srcdir = .
 # rules to apply to Windows.
 TARGETS=mx_stream mx_multi_stream mx_mem_test
 
-#mx_stream: mx_stream.o rfm.o
+mx_stream: mx_stream.o rfm.o
 
-#mx_multi_stream: mx_multi_stream.o rfm.o
+mx_multi_stream: mx_multi_stream.o rfm.o
 
-#mx_crc_only: mx_crc_only.o rfm.o
+mx_crc_only: mx_crc_only.o rfm.o
 
-#mx_mem_test: mx_mem_test.o rfm.o
+mx_mem_test: mx_mem_test.o rfm.o
 
-#mx_stream_single: mx_stream_single.o rfm.o
+omx_recv: omx_recv.o rfm.o
 
-omx_xmit: mx_fe.o rfm.o
+mx_stream_single: mx_stream_single.o rfm.o
 
-#mx_rcv: mx_rcv.o rfm.o
+mx_fe: mx_fe.o rfm.o
+
+mx_rcv: mx_rcv.o rfm.o
 
 rfm.o: ../drv/rfm.c
 	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
@@ -36,7 +38,7 @@ rfm.o: ../drv/rfm.c
 CFLAGS = -I${prefix}/include -I.
 CFLAGS += -Wall -g -O2
 CFLAGS += $(OPTIM_CFLAGS)
-CPPFLAGS = -I../common -I$(top_srcdir)/common -I$(top_srcdir)/common/bsd -DNO_RTL  -D_XOPEN_SOURCE -D_BSD_SOURCE
+CPPFLAGS = -I../common -I$(top_srcdir)/common -I$(top_srcdir)/common/bsd -DNO_RTL  -D_XOPEN_SOURCE -D_DEFAULT_SOURCE
 #CPPFLAGS += -DMX_THREAD_SAFE=$(MX_THREAD_SAFE)
 
 LDFLAGS = -L${prefix}/lib -lmyriexpress -lpthread  -g
@@ -62,14 +64,7 @@ LDFLAGS = -L${prefix}/lib -lmyriexpress -lpthread  -g
 
 .PHONY: clean
 clean:
-	rm -f *.o mx_stream mx_multi_stream mx_stream_single mx_fe mx_rcv omx_xmit
-
-omx_recv: omx_recv.c
-	$(CC) $(CFLAGS) -I../zmq_stream -I/opt/open-mx/include omx_recv.c -c -o omx_recv.o
-	$(CC) $(CFLAGS) ../drv/rfm.c -c -o rfm.o
-	$(CC) $(CFLAGS) -I../zmq_stream ../zmq_stream/simple_pv.c -c -o simple_pv.o
-	$(CC) $(FLAGS) -o omx_recv  omx_recv.o  rfm.o simple_pv.o -L $(API_LIB_PATH) -L/opt/open-mx/lib -lmyriexpress -lpthread
-	sync
+	rm -f *.o mx_stream mx_multi_stream mx_stream_single mx_fe mx_rcv
 
 .PHONY: distclean
 distclean: clean
diff --git a/src/mx_stream/omx_recv.c b/src/mx_stream/omx_recv.c
index 89f846f65523d2fa20c4914f311e0ee4dff8d14b..85bfabc682a4906df1d90894b5f001ab93dfb8d0 100644
--- a/src/mx_stream/omx_recv.c
+++ b/src/mx_stream/omx_recv.c
@@ -1,7 +1,6 @@
 //
-/// @file omx_recv.c
-/// @brief  DAQ data concentrator code. Receives data via Open-MX and
-/// writes to local mbuf
+/// @file mx2ix.c
+/// @brief  DAQ data concentrator code. Receives data via Open-MX and sends via Dolphin IX..
 //
 
 #include "myriexpress.h"
@@ -102,16 +101,13 @@ int dataRdy[MAX_FE_COMPUTERS];
 void
 usage()
 {
-    fprintf(stderr, "Usage: omx_recv [args] -s server names -m shared memory size\n");
+    fprintf(stderr, "Usage: mx2ix [args] -s server names -m shared memory size -g IX channel \n");
     fprintf(stderr, "-l filename - log file name\n");
-    fprintf(stderr, "-s count - number of FE computers to connect (1-32): Default = 32\n");
+    fprintf(stderr, "-s - number of FE computers to connect (1-32): Default = 32\n");
     fprintf(stderr, "-v - verbose prints diag test data\n");
-    fprintf(stderr, "-p prefix - Debug pv prefix, requires -P as well\n");
-    fprintf(stderr, "-P path to pipe - Path to a named pipe to send PV debug information to\n");
-    fprintf(stderr, "-d ms - Max delay in milli seconds to wait for a FE to send data, defaults to 10\n");
-    fprintf(stderr, "-t thread count - Number of rcvr threads per NIC: default = 16\n");
-    fprintf(stderr, "-b mbuf name - output mbuf name [defaults to local_dc]")
-    fprintf(stderr, "-m size in MB - Size of the output mbuf in MB [20-100]");
+    fprintf(stderr, "-d - Max delay in milli seconds to wait for a FE to send data, defaults to 10\n");
+    fprintf(stderr, "-t - Number of rcvr threads per NIC: default = 16\n");
+    fprintf(stderr, "-n - Data Concentrator number (0 or 1) : default = 0\n");
     fprintf(stderr, "-h - help\n");
 }
 
@@ -259,8 +255,8 @@ int
 main(int argc, char **argv)
 {
     pthread_t thread_id[MAX_FE_COMPUTERS];
-    unsigned int nsys = MAX_FE_COMPUTERS; // The number of mapped shared memories (number of data sources)
-    char *buffer_name = "local_dc";
+    int nsys = MAX_FE_COMPUTERS; // The number of mapped shared memories (number of data sources)
+    char *buffer_name = "ifo";
     int c;
     int ii;                 // Loop counter
     int delay_ms = 10;
@@ -268,11 +264,6 @@ main(int argc, char **argv)
 
     extern char *optarg;    // Needed to get arguments to program
 
-    // PV/debug information
-    char *pv_prefix = 0;
-    char *pv_debug_pipe_name = 0;
-    int pv_debug_pipe = -1;
-
     // Declare shared memory data variables
     daq_multi_cycle_header_t *ifo_header;
     char *ifo;
@@ -283,16 +274,20 @@ main(int argc, char **argv)
     int max_data_size_mb = 100;
     int max_data_size = 0;
     char *mywriteaddr;
-
+    int dc_number = 1;
+    
 
     /* set up defaults */
-    int xmitData = 0;
     int tpn = THREADS_PER_NIC;
 
 
+    if (argc<3) {
+        usage();
+        return(-1);
+    }
 
     // Get arguments sent to process
-    while ((c = getopt(argc, argv, "b:hs:m:vp:P:d:l:t:n:")) != EOF) switch(c) {
+    while ((c = getopt(argc, argv, "b:hs:m:vp:d:l:t:n:")) != EOF) switch(c) {
     case 's':
         nsys = atoi(optarg);
         if(nsys > MAX_FE_COMPUTERS) {
@@ -304,6 +299,15 @@ main(int argc, char **argv)
     case 'v':
         do_verbose = 1;
         break;
+    case 'n':
+        dc_number = atoi(optarg);
+        dc_number ++;
+        if(dc_number > 2) {
+            fprintf(stderr,"DC number must be 0 or 1\n");
+            usage();
+            exit(1);
+        }
+        break;
     case 'm':
         max_data_size_mb = atoi(optarg);
         if (max_data_size_mb < 20){
@@ -321,12 +325,6 @@ main(int argc, char **argv)
     case 'b':
         buffer_name = optarg;
         break;
-    case 'p':
-        pv_prefix = optarg;
-        break;
-    case 'P':
-        pv_debug_pipe_name = optarg;
-        break;
     case 'd':
         delay_ms = atoi(optarg);
         if (delay_ms < MIN_DELAY_MS || delay_ms > MAX_DELAY_MS) {
@@ -347,6 +345,7 @@ main(int argc, char **argv)
         usage();
         exit(1);
     }
+
     max_data_size = max_data_size_mb * 1024*1024;
     delay_cycles = delay_ms * 10;
 
@@ -394,7 +393,6 @@ main(int argc, char **argv)
     size_t zbuffer_remaining = 0;
     int dc_datablock_size = 0;
     int datablock_size_running = 0;
-    int datablock_size_mb_s = 0;
     static const int header_size = sizeof(daq_multi_dcu_header_t);
     char dcstatus[4096];
     char dcs[48];
@@ -409,130 +407,16 @@ main(int argc, char **argv)
     int sendLength = 0;
 
     int min_cycle_time = 1 << 30;
-    int pv_min_cycle_time = 0;
     int max_cycle_time = 0;
-    int pv_max_cycle_time = 0;
     int mean_cycle_time = 0;
-    int pv_mean_cycle_time = 0;
-    int pv_dcu_count = 0;
-    int pv_total_datablock_size = 0;
-    int pv_datablock_size_mb_s = 0;
     int uptime = 0;
-    int pv_uptime = 0;
-    int gps_time = 0;
-    int pv_gps_time = 0;
     int missed_flag = 0;
     int missed_nsys[MAX_FE_COMPUTERS];
     int64_t recv_time[MAX_FE_COMPUTERS];
     int64_t min_recv_time = 0;
     int recv_buckets[(MAX_DELAY_MS/5)+2];
     int festatus = 0;
-    int pv_festatus = 0;
-
-    SimplePV pvs[] = {
-            {
-                    "RECV_MIN_MS",
-                    SIMPLE_PV_INT,
-                    &pv_min_cycle_time,
-
-                    80,
-                    45,
-                    70,
-                    54,
-            },
-            {
-                    "RECV_MAX_MS",
-                    SIMPLE_PV_INT,
-                    &pv_max_cycle_time,
-
-                    80,
-                    45,
-                    70,
-                    54,
-            },
-            {
-                    "RECV_MEAN_MS",
-                    SIMPLE_PV_INT,
-                    &pv_mean_cycle_time,
-
-                    80,
-                    45,
-                    70,
-                    54,
-            },
-            {
-                    "DCU_COUNT",
-                    SIMPLE_PV_INT,
-                    &pv_dcu_count,
-
-                    120,
-                    0,
-                    115,
-                    0,
-            },
-            {
-                    "DATA_SIZE",
-                    SIMPLE_PV_INT,
-                    &pv_total_datablock_size,
-
-                    100*1024*1024,
-                    0,
-                    90*1024*1024,
-                    1*1024*1024,
-            },
-            {
-                    "DATA_RATE",
-                    SIMPLE_PV_INT,
-                    &pv_datablock_size_mb_s,
-
-                    100*1024*1024,
-                    0,
-                    90*1024*1024,
-                    1000000,
-            },
-            {
-                    "UPTIME_SECONDS",
-                    SIMPLE_PV_INT,
-                    &pv_uptime,
-
-                    100*1024*1024,
-                    0,
-                    90*1024*1024,
-
-                    1,
-            },
-            {
-                    "RCV_STATUS",
-                    SIMPLE_PV_INT,
-                    &pv_festatus,
-
-                    0xffffffff,
-                    0,
-                    0xfffffffe,
-
-                    1,
-            },
-            {
-                    "GPS",
-                    SIMPLE_PV_INT,
-                    &pv_gps_time,
-
-                    0xfffffff,
-                    0,
-                    0xfffffffe,
-
-                    1,
-            },
-
-    };
-    if (pv_debug_pipe_name)
-    {
-        pv_debug_pipe = open(pv_debug_pipe_name, O_NONBLOCK | O_RDWR, 0);
-        if (pv_debug_pipe < 0) {
-            fprintf(stderr, "Unable to open %s for writting (pv status)\n", pv_debug_pipe_name);
-            exit(1);
-        }
-    }
+    int ix_xmit_stop = 0;
 
     missed_flag = 1;
     memset(&missed_nsys[0], 0, sizeof(missed_nsys));
@@ -630,12 +514,12 @@ main(int argc, char **argv)
                                 mxDataBlockSingle[ii].header.dcuheader[jj].status;
                         ifoDataBlock->header.dcuheader[mytotaldcu].cycle = 
                                 mxDataBlockSingle[ii].header.dcuheader[jj].cycle;
-
+                        if(!ix_xmit_stop) {
                             ifoDataBlock->header.dcuheader[mytotaldcu].timeSec = 
                                 mxDataBlockSingle[ii].header.dcuheader[jj].timeSec;
                             ifoDataBlock->header.dcuheader[mytotaldcu].timeNSec = 
                                 mxDataBlockSingle[ii].header.dcuheader[jj].timeNSec;
-
+                        }
                         ifoDataBlock->header.dcuheader[mytotaldcu].dataCrc = 
                                 mxDataBlockSingle[ii].header.dcuheader[jj].dataCrc;
                         ifoDataBlock->header.dcuheader[mytotaldcu].dataBlockSize = 
@@ -645,7 +529,15 @@ main(int argc, char **argv)
                         ifoDataBlock->header.dcuheader[mytotaldcu].tpCount = 
                                 mxDataBlockSingle[ii].header.dcuheader[jj].tpCount;
 
-                        for(kk=0;kk<DAQ_GDS_MAX_TP_NUM ;kk++)
+                        // Check for downstream DAQ reset request from EDCU
+                        if(mxDataBlockSingle[ii].header.dcuheader[jj].dcuId == 52 && 
+                            mxDataBlockSingle[ii].header.dcuheader[jj].tpCount == dc_number)
+                        {
+                            fprintf(stderr,"Got a DAQ Reset REQUEST %u\n",mxDataBlockSingle[ii].header.dcuheader[jj].timeSec);
+                            ifoDataBlock->header.dcuheader[mytotaldcu].tpCount = 0;
+                            ix_xmit_stop = 16 * IX_STOP_SEC;
+                        }
+                        for(kk=0;kk<DAQ_GDS_MAX_TP_NUM ;kk++)   
                             ifoDataBlock->header.dcuheader[mytotaldcu].tpNum[kk] = mxDataBlockSingle[ii].header.dcuheader[jj].tpNum[kk];
                         edbs[mytotaldcu] = mxDataBlockSingle[ii].header.dcuheader[jj].tpBlockSize + mxDataBlockSingle[ii].header.dcuheader[jj].dataBlockSize;
                         // Get some diags
@@ -694,21 +586,9 @@ main(int argc, char **argv)
             }
             datablock_size_running += dc_datablock_size;
             if (nextCycle == 0) {
-                datablock_size_mb_s = datablock_size_running / 1024 ;
-                pv_datablock_size_mb_s = datablock_size_mb_s;
                 uptime ++;
-                pv_uptime = uptime;
-                gps_time = ifoDataBlock->header.dcuheader[0].timeSec;
-                pv_gps_time = gps_time;
-                pv_dcu_count = mytotaldcu;
-                pv_festatus = festatus;
                 mean_cycle_time = (n_cycle_time > 0 ? mean_cycle_time / n_cycle_time : 1 << 31);
 
-                pv_mean_cycle_time = mean_cycle_time;
-                pv_max_cycle_time = max_cycle_time;
-                pv_min_cycle_time = min_cycle_time;
-                send_pv_update(pv_debug_pipe, pv_prefix, pvs, sizeof(pvs)/sizeof(pvs[0]));
-
                 if (do_verbose) {
                     fprintf(stderr,"\nData rdy for cycle = %d\t\tTime Interval = %ld msec\n", nextCycle, myptime);
                     fprintf(stderr,"Min/Max/Mean cylce time %d/%d/%d msec over %ld cycles\n", min_cycle_time, max_cycle_time,
@@ -727,6 +607,11 @@ main(int argc, char **argv)
             } else {
                 missed_flag <<= 1;
             }
+            if(ix_xmit_stop)  {
+                ix_xmit_stop --;
+                if(ix_xmit_stop == 0) fprintf(stderr,"Restarting Dolphin Xmit\n");
+            }
+
         }
         sprintf(dcstatus,"%ld ",ets);
         for(ii=0;ii<mytotaldcu;ii++) {