diff --git a/src/fe/controllerUser.c b/src/fe/controllerAppUser.c
similarity index 69%
rename from src/fe/controllerUser.c
rename to src/fe/controllerAppUser.c
index 536554b3e1ed2c4d744204b5051fd94c7abf9850..0a9b6ca35e09746b289669f4086d4551a4f15af5 100644
--- a/src/fe/controllerUser.c
+++ b/src/fe/controllerAppUser.c
@@ -137,103 +137,11 @@ struct rmIpcStr *daqPtr;
 int  getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); 
 
 // Include C code modules
-#ifdef ADC_MASTER
-	#include "rcguserIop.c"
-#else
 	#include "rcguser.c"
-#endif
-
 
 char daqArea[2*DAQ_DCU_SIZE];		// Space allocation for daqLib buffers
 int cpuId = 1;
 
-// All systems not running at 64K require up/down sampling to communicate I/O data
-// with IOP, which is running at 64K.
-// Following defines the filter coeffs for these up/down filters.
-#ifdef OVERSAMPLE
-
-#if defined(CORE_BIQUAD)
-
-/* Recalculated filters in biquad form */
-
-/* Oversamping base rate is 64K */
-/* Coeffs for the 2x downsampling (32K system) filter */
-static double __attribute__ ((unused)) feCoeff2x[9] =
-        {0.053628649721183,
-	 0.2568759660371100, -0.3225906481359000, 1.2568801238621801, 1.6774135096891700,
-	-0.2061764045745400, -1.0941543149527400, 2.0846376586498803, 2.1966597482716801};
-
-/* RCG V3.0 Coeffs for the 4x downsampling (16K system) filter */
-static double __attribute__ ((unused)) feCoeff4x[9] =
-	{0.054285975,
-	 0.3890221, -0.17645085, -0.0417771600000001, 0.41775916,
-	 0.52191125, -0.37884382, 1.52190741336686, 1.69347541336686};
-
-// Pre RCG 3.0 filters
-//	{0.014805052402446,  
-//	0.7166258547451800, -0.0683289874517300, 0.3031629575762000, 0.5171469569032900,
-//	0.6838596423885499, -0.2534855521841101, 1.6838609161411500, 1.7447155374502499};
-
-//
-// New Brian Lantz 4k decimation filter
-static double __attribute__ ((unused)) feCoeff16x[9] =
-        {0.010203728365,
-	0.8052941009065100, -0.0241751519071000, 0.3920490703701900, 0.5612099784288400,
-	0.8339678987936501, -0.0376022631287799, -0.0131581721533700, 0.1145865116421301};
-
-/* Coeffs for the 32x downsampling filter (2K system) */
-#if 0
-/* Original Rana coeffs from 40m lab elog */
-static double __attribute__ ((unused)) feCoeff32x[9] =
-        {0.0001104130574447,
-	0.9701834961388200, -0.0010837026165800, -0.0200761119821899, 0.0085463156103800,
-	0.9871502388637901, -0.0039246182095299, 3.9871502388637898, 3.9960753817904697};
-#endif
-
-/* Coeffs for the 32x downsampling filter (2K system) per Brian Lantz May 5, 2009 */
-static double __attribute__ ((unused)) feCoeff32x[9] =
-	{0.010581064947739,
-	 0.90444302586137004, -0.0063413204375699639, -0.056459743474659874, 0.032075154877300172, 
-  	 0.92390910024681006, -0.0097523655540199261, 0.077383808424050127, 0.14238741130302013};
-
-#else
-
-/* Oversamping base rate is 64K */
-/* Coeffs for the 2x downsampling (32K system) filter */
-static double __attribute__ ((unused)) feCoeff2x[9] =
-        {0.053628649721183,
-        -1.25687596603711,    0.57946661417301,    0.00000415782507,    1.00000000000000,
-        -0.79382359542546,    0.88797791037820,    1.29081406322442,    1.00000000000000};
-/* Coeffs for the 4x downsampling (16K system) filter */
-static double __attribute__ ((unused)) feCoeff4x[9] =
-	{0.014805052402446,  
-	-1.71662585474518,    0.78495484219691,   -1.41346289716898,   0.99893884152400,
-	-1.68385964238855,    0.93734519457266,    0.00000127375260,   0.99819981588176};
-//
-// New Brian Lantz 4k decimation filter
-static double __attribute__ ((unused)) feCoeff16x[9] =
-        {0.010203728365,
-        -1.80529410090651,   0.82946925281361,  -1.41324503053632,   0.99863016087226,
-        -1.83396789879365,   0.87157016192243,  -1.84712607094702,   0.99931484571793};
-//
-
-/* Coeffs for the 32x downsampling filter (2K system) per Brian Lantz May 5, 2009 */
-static double __attribute__ ((unused)) feCoeff32x[9] =
-	{0.010581064947739,
-        -1.90444302586137,    0.91078434629894,   -1.96090276933603,    0.99931924465090,
-        -1.92390910024681,    0.93366146580083,   -1.84652529182276,    0.99866506867980};
-#endif
-
-
-
-// History buffers for oversampling filters
-double dHistory[(MAX_ADC_MODULES * 32)][MAX_HISTRY];
-double dDacHistory[(MAX_DAC_MODULES * 16)][MAX_HISTRY];
-#else
-
-#define OVERSAMPLE_TIMES 1
-#endif
-
 #ifdef DUAL_DAQ_DC
 	#define MX_OK	15
 #else
@@ -251,7 +159,6 @@ int initialDiagReset = 1;
   char fp [64*1024];
 
 
-#ifdef ADC_SLAVE
 // Clear DAC channel shared memory map,
 // used to keep track of non-overlapping DAC channels among slave models
 //
@@ -264,7 +171,6 @@ void deallocate_dac_channels(void) {
 	   ioMemData->dacOutUsed[pd][jj] = 0;
   }
 }
-#endif
 unsigned int getGpsTimeProc() {
   FILE *timef;
   char line[100];
@@ -282,29 +188,6 @@ unsigned int getGpsTimeProc() {
 	fclose(timef);
 	return (mytime);
 }
-#ifdef ADC_MASTER
-  void initAdcModules(void) {
-	  int status;
-	  int jj;
-
-	  for(jj=0;jj<cdsPciModules.adcCount;jj++)
-	  {
-		  // Set ADC Present Flag
-		  pLocalEpics->epicsOutput.statAdc[jj] = 1;
-		  adcRdTimeErr[jj] = 0;
-	  }
-    	  printf("ADC setup complete \n");
-  }
-  void initDacModules(void) {
-	  int jj;
-	  int status;
-
-	  for(jj = 0; jj < cdsPciModules.dacCount; jj++) {
-		pLocalEpics->epicsOutput.statDac[jj] = DAC_FOUND_BIT;
-	  }
-	  printf("DAC setup complete \n");
- }
-#endif
 
 //***********************************************************************
 // TASK: fe_start()	
@@ -342,14 +225,6 @@ int fe_start()
   int limit = OVERFLOW_LIMIT_16BIT;      /// @param limit ADC/DAC overflow test value
   int mask = GSAI_DATA_MASK;            /// @param mask Bit mask for ADC/DAC read/writes
   int num_outs = MAX_DAC_CHN_PER_MOD;   /// @param num_outs Number of DAC channels variable
-#ifdef ADC_MASTER
-  volatile int *packedData;		/// @param *packedData Pointer to ADC PCI data space
-  volatile unsigned int *pDacData;	/// @param *pDacData Pointer to DAC PCI data space
-  int wtmin,wtmax;			/// @param wtmin Time window for startup on IRIG-B
-  int dacEnable = 0;
-  int pBits[9] = {1,2,4,8,16,32,64,128,256};	/// @param pBits[] Lookup table for quick power of 2 calcs
-  int sync21ppsCycles = 0;		/// @param sync32ppsCycles Number of attempts to sync to 1PPS
-#endif
   int dkiTrip = 0;
   RFM_FE_COMMS *pEpicsComms;		/// @param *pEpicsComms Pointer to EPICS shared memory space
   int timeHoldMax = 0;			/// @param timeHoldMax Max code cycle time since last diag reset
@@ -377,10 +252,8 @@ int fe_start()
   int ioClockDac = DAC_PRELOAD_CNT;
   int ioMemCntr = 0;
   int ioMemCntrDac = DAC_PRELOAD_CNT;
-#ifdef ADC_SLAVE
   int memCtr = 0;
   int ioClock = 0;
-#endif
   double dac_in =  0.0;			/// @param dac_in DAC value after upsample filtering
   int dac_out = 0;			/// @param dac_out Integer value sent to DAC FIFO
 
@@ -388,25 +261,6 @@ int fe_start()
 
   int clk, clk1;			// Used only when run on timer enabled (test mode)
 
-#ifdef ADC_MASTER
-  static float duotone[IOP_IO_RATE];		// Duotone timing diagnostic variables
-  static float duotoneDac[IOP_IO_RATE];
-  float duotoneTimeDac;
-  float duotoneTime;
-  static float duotoneTotal = 0.0;
-  static float duotoneMean = 0.0;
-  static float duotoneTotalDac = 0.0;
-  static float duotoneMeanDac = 0.0;
-  static int dacDuoEnable = 0;
-  static int dacTimingError = 0;
-  static int dacTimingErrorPending[MAX_DAC_MODULES];
-
-  volatile GSA_18BIT_DAC_REG *dac18bitPtr;	// Pointer to 16bit DAC memory area
-  volatile GSC_DAC_REG *dac16bitPtr;		// Pointer to 18bit DAC memory area
-  unsigned int usec = 0;
-  unsigned int offset = 0;
-#endif
-
 
   int cnt = 0;
   unsigned long cpc;
@@ -445,18 +299,9 @@ int fe_start()
   /// \> Zero out DAC outputs
   for (ii = 0; ii < MAX_DAC_MODULES; ii++)
   {
-#ifdef ADC_MASTER
-    dacTimingErrorPending[ii] = 0;
-#endif
     for (jj = 0; jj < 16; jj++) {
  	dacOut[ii][jj] = 0.0;
  	dacOutUsed[ii][jj] = 0;
-#ifdef ADC_MASTER
-	dacOutBufSize[ii] = 0;
-	// Zero out DAC channel map in the shared memory
-	// to be used to check on slaves' channel allocation
-	ioMemData->dacOutUsed[ii][jj] = 0;
-#endif
     }
   }
 
@@ -478,15 +323,8 @@ int fe_start()
   memset(proc_futures, 0, sizeof(proc_futures));
 
 /// \> Init code synchronization source.
-#ifdef ADC_MASTER
-  // Look for DIO card or IRIG-B Card
-  // if Contec 1616 BIO present, TDS slave will be used for timing.
-  if(cdsPciModules.cDio1616lCount) syncSource = SYNC_SRC_TDS;
-  else syncSource = SYNC_SRC_1PPS;
-#else
    // SLAVE processes get sync from ADC_MASTER
    syncSource = SYNC_SRC_MASTER;
-#endif
 
 printf("Sync source = %d\n",syncSource);
 
@@ -608,7 +446,6 @@ usleep(1000);
 
 /// \> Verify DAC channels defined for this app are not already in use. \n
 /// - ---- User apps are allowed to share DAC modules but not DAC channels.
-#ifdef ADC_SLAVE
   // See if my DAC channel map overlaps with already running models
   for (ii = 0; ii < cdsPciModules.dacCount; ii++) {
     int pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; // physical DAC number
@@ -635,7 +472,6 @@ usleep(1000);
       }
     }
   }
-#endif
 
   // Clear timing diags.
   adcHoldTime = 0;
@@ -650,43 +486,12 @@ usleep(1000);
   usrHoldTime = 0;		
   missedCycle = 0;
 
-#ifdef ADC_MASTER
-  /// \> If IOP,  Initialize the ADC modules
-  initAdcModules();
-#endif
-#ifdef ADC_SLAVE
   for(jj=0;jj<cdsPciModules.adcCount;jj++)
   {
   	  pLocalEpics->epicsOutput.statAdc[jj] = 1;
   }
-#endif
 
-#ifdef ADC_MASTER
-  /// \> If IOP, Initialize the DAC module variables
-  initDacModules();
-#endif
 
-#ifdef ADC_MASTER
-  if (run_on_timer) {	// NOT normal operating mode; used for test systems without I/O cards/chassis
-    printf("*******************************\n");
-    printf("*     Running on timer!       *\n");
-    printf("*******************************\n");
-          do {
-		usleep(1);
-    		clock_gettime(CLOCK_MONOTONIC, &myTimer[0]);
-		cycleTime = myTimer[0].tv_nsec / 1000;
-    	  } while(cycleTime > 10);
-	  // timeSec = myTimer[0].tv_sec - 1;
-	  timeSec = getGpsTimeProc();
-		startGpsTime = timeSec;
-		pLocalEpics->epicsOutput.startgpstime = startGpsTime;
-    printf("Triggered the ADC at %d and %d usec\n",timeSec,cycleTime);
-  } else {
-  	printf("Can't run with I/O \n");
-	exit(-1);
-  }
-#endif
-#ifdef ADC_SLAVE
 	// 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];
@@ -712,14 +517,11 @@ usleep(1000);
 	// Decrement GPS seconds as it will be incremented on first read cycle.
 	timeSec --;
 
-#endif
   onePpsTime = cycleNum;
-#ifdef ADC_SLAVE
   // timeSec = current_time() -1;
 	timeSec = ioMemData->gpsSecond;
         // timeSec = ioMemData->iodata[0][0].timeSec;
   printf ("Using local GPS time %d \n",timeSec);
-#endif
 
   clock_gettime(CLOCK_MONOTONIC, &adcTime);
 
@@ -790,227 +592,11 @@ usleep(1000);
 	  /// - ---- Check if DAC outputs are enabled, report error.
 	  if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE;
 
-#ifdef ADC_MASTER
-	  /// - ---- If IOP, Increment GPS second
-          timeSec ++;
-          pLocalEpics->epicsOutput.timeDiag = timeSec;
-	  if (cycle_gps_time == 0) {
-		startGpsTime = timeSec;
-		pLocalEpics->epicsOutput.startgpstime = startGpsTime;
-		printf("Cycle gps = %d\n",startGpsTime);
-	  }
-	  cycle_gps_time = timeSec;
-#endif
 	}
-#ifdef NO_CPU_SHUTDOWN
-		    usleep_range(5,9);
-#endif
         for(ll=0;ll<sampleCount;ll++)
         {
-/// IF IOP *************************** \n
-#ifdef ADC_MASTER2
-// Start of ADC Read *************************************************************************************
-	/// \> IF IOP, Wait for ADC data ready
-	/// - ---- On startup, only want to read one sample such that first cycle
-	/// coincides with GPS 1PPS. Thereafter, sampleCount will be 
-	/// increased to appropriate number of 65536 s/sec to match desired
-	/// code rate eg 32 samples each time thru before proceeding to match 2048 system.
-		// Read ADC data
-               for(jj=0;jj<cdsPciModules.adcCount;jj++)
-		{
-		    /// - ---- ADC DATA RDY is detected when last channel in memory no longer contains the
-		    /// dummy variable written during initialization and reset after the read.
-		    packedData = (int *)cdsPciModules.pci_adc[jj];
-                    if (cdsPciModules.adcType[jj] == GSC_18AISS6C) packedData += 5;
-               	    else packedData += 31;
-		
-		    rdtscl(cpuClock[CPU_TIME_RDY_ADC]);
-                    do {
-			/// - ---- Need to delay if not ready as constant banging of the input register
-			/// will slow down the ADC DMA.
-			// if(*packedData == DUMMY_ADC_VAL) {
-		    		rdtscl(cpuClock[CPU_TIME_ADC_WAIT]);
-				adcWait = (cpuClock[CPU_TIME_ADC_WAIT] - cpuClock[CPU_TIME_RDY_ADC])/CPURATE;
-			// }
-			/// - ---- Allow 1sec for data to be ready (should never take that long).
-                    }while((*packedData == DUMMY_ADC_VAL) && (adcWait < MAX_ADC_WAIT));
-
-			/// - ---- Added ADC timing diagnostics to verify timing consistent and all rdy together.
-		    if(jj==0)
-			    adcRdTime[jj] = (cpuClock[CPU_TIME_ADC_WAIT] - cpuClock[CPU_TIME_CYCLE_START]) / CPURATE;
-		    else
-			    adcRdTime[jj] = adcWait;
-	
-		    if(adcRdTime[jj] > adcRdTimeMax[jj]) adcRdTimeMax[jj] = adcRdTime[jj];
-
-		    if((jj==0) && (adcRdTimeMax[jj] > MAX_ADC_WAIT_CARD_0)) 
-			adcRdTimeErr[jj] ++;
-		    if((jj!=0) && (adcRdTimeMax[jj] > MAX_ADC_WAIT_CARD_S)) 
-			adcRdTimeErr[jj] ++;
-
-		    /// - --------- If data not ready in time, abort.
-		    /// Either the clock is missing or code is running too slow and ADC FIFO
-		    /// is overflowing.
-		    if (adcWait >= MAX_ADC_WAIT) {
-	  		pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
-	  		pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR;
-                        stop_working_threads = 1;
-			vmeDone = 1;
-                        printf("timeout %d %d \n",jj,adcWait);
-			continue;
-		    }
-		    if(jj == 0) 
-		    {
-			// Capture cpu clock for cpu meter diagnostics
-			rdtscl(cpuClock[CPU_TIME_CYCLE_START]);
-			/// \> If first cycle of a new second, capture IRIG-B time. Standard for aLIGO is
-			/// TSYNC_RCVR.
-			if(cycleNum == 0) 
-			{
-				// if SymCom type, just do write to lock current time and read later
-				// This save a couple three microseconds here
-				if(cdsPciModules.gpsType == SYMCOM_RCVR) lockGpsTime();
-				if(cdsPciModules.gpsType == TSYNC_RCVR) 
-				{
-					/// - ---- Reading second info will lock the time register, allowing
-					/// nanoseconds to be read later (on next cycle). Two step process used to 
-					/// save CPU time here, as each read can take 2usec or more.
-					timeSec = getGpsSecTsync();
-				}
-			}
-			
-		    }
-
-#ifndef RFM_DIRECT_READ
-#ifdef FUTURE_RFM_DMA_CHECK
-                    /// \> If RFM cards, verify DMA is complete
-                    if(jj == 0 && (cycleNum % 4) == 0 && cdsPciModules.pci_rfm[0])
-                                vmic5565DMAdone(0);
-                    if(jj == 0 && (cycleNum % 4) == 0 && cdsPciModules.pci_rfm[1])
-                                vmic5565DMAdone(1);
-#endif
-#endif
-
-                    /// \> Read adc data
-                    packedData = (int *)cdsPciModules.pci_adc[jj];
-		    /// - ---- First, and only first, channel should have upper bit marker set.
-		    /// If not, have a channel hopping error.
-                    if(!(*packedData & ADC_1ST_CHAN_MARKER)) 
-		    {
-  			 adcChanErr[jj] = 1;
-			 chanHop = 1;
-	  	 	 pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC;
-	 	    }	
-
-                    limit = OVERFLOW_LIMIT_16BIT;
-                    if (cdsPciModules.adcType[jj] == GSC_18AISS6C) {
-			limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit
-			offset = GSAF_DATA_CODE_OFFSET; // Data coding offset in 18-bit DAC
-			mask = GSAF_DATA_MASK;
-			num_outs = GSAF_CHAN_COUNT;
-                    } else {
-		    	// Various ADC models have different number of channels/data bits
-                    	offset = GSAI_DATA_CODE_OFFSET;
-                    	mask = GSAI_DATA_MASK;
-                    	num_outs = GSAI_CHAN_COUNT;
-		    }
-		    /// - ---- Determine next ipc memory location to load ADC data
-		    ioMemCntr = (cycleNum % IO_MEMORY_SLOTS);
-                    /// - ----  Read adc data from PCI mapped memory into local variables
-                    for(ii=0;ii<num_outs;ii++)
-                    {
-			// adcData is the integer representation of the ADC data
-			adcData[jj][ii] = (*packedData & mask);
-			adcData[jj][ii]  -= offset;
-#ifdef DEC_TEST
-			if(ii==0)
-			{
-				adcData[jj][ii] = dspPtr[0]->data[0].exciteInput;
-			}
-#endif
-			// dWord is the double representation of the ADC data
-			// This is the value used by the rest of the code calculations.
-			dWord[jj][ii] = adcData[jj][ii];
-			/// - ----  Load ADC value into ipc memory buffer
-			ioMemData->iodata[jj][ioMemCntr].data[ii] = adcData[jj][ii];
-			packedData ++;
-                    }
-		    /// - ---- Write GPS time and cycle count as indicator to slave that adc data is ready
-	  	    ioMemData->gpsSecond = timeSec;;
-		    ioMemData->iodata[jj][ioMemCntr].timeSec = timeSec;;
-		    ioMemData->iodata[jj][ioMemCntr].cycle = cycleNum;
-
-		    /// - ---- Check for ADC overflows
-                    for(ii=0;ii<num_outs;ii++)
-                    {
-			if((adcData[jj][ii] > limit) || (adcData[jj][ii] < -limit))
-			  {
-				overflowAdc[jj][ii] ++;
-				pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++;
-				overflowAcc ++;
-				adcOF[jj] = 1;
-				odcStateWord |= ODC_ADC_OVF;
-			  }
-                    }
-
-		   /// - ---- Clear out last ADC data read for test on next cycle
-                   packedData = (int *)cdsPciModules.pci_adc[jj];
-                   *packedData = 0x0;
-
-                   if (cdsPciModules.adcType[jj] == GSC_18AISS6C) packedData += GSAF_CHAN_COUNT_M1;
-                   else packedData += GSAI_CHAN_COUNT_M1;
-
-                   *packedData = DUMMY_ADC_VAL;
-
-#ifdef DIAG_TEST
-// For DIAGS ONLY !!!!!!!!
-// This will change ADC DMA BYTE count
-// -- Greater than normal will result in channel hopping.
-// -- Less than normal will result in ADC timeout.
-// In both cases, real-time kernel code should exit with errors to dmesg
-          	   if(pLocalEpics->epicsInput.bumpAdcRd != 0) {
-		   	gsc16ai64DmaBump(jj,pLocalEpics->epicsInput.bumpAdcRd);
-		   	pLocalEpics->epicsInput.bumpAdcRd = 0;
-		   }
-#endif
-		   /// - ---- Reset ADC DMA Start Flag \n
-		   /// - --------- This allows ADC to dump next data set whenever it is ready
-		   gsc16ai64DmaEnable(jj);
-            }
-
-
-		  // Try synching to 1PPS on ADC[0][31] if not using IRIG-B or TDS
-		  // Only try for 1 sec.
-                  if(!sync21pps)
-                  {
-			// 1PPS signal should rise above 4000 ADC counts if present.
-                        if((adcData[0][31] < ONE_PPS_THRESH) && (sync21ppsCycles < (CYCLE_PER_SECOND*OVERSAMPLE_TIMES))) 
-			{
-				ll = -1;
-				sync21ppsCycles ++;
-                        }else {
-				// Need to start clocking the DAC outputs.
-				gsc18ao8Enable(&cdsPciModules);
-				gsc16ao16Enable(&cdsPciModules);
-                                sync21pps = 1;
-				// 1PPS never found, so indicate NO SYNC to user
-				if(sync21ppsCycles >= (CYCLE_PER_SECOND*OVERSAMPLE_TIMES))
-				{
-					syncSource = SYNC_SRC_NONE;
-					printf("NO SYNC SOURCE FOUND %d %d\n",sync21ppsCycles,adcData[0][31]);
-				} else {
-				// 1PPS found and synched to
-					printf("GPS Trigg %d %d\n",adcData[0][31],sync21pps);
-					syncSource = SYNC_SRC_1PPS;
-				}
-				pLocalEpics->epicsOutput.timeErr = syncSource;
-                        }
-                }
-#endif
-/// END IF IOP \n
 
 /// IF USER APP  *************************** \n
-#ifdef ADC_SLAVE
 		/// \> SLAVE gets its adc data from MASTER via ipc shared memory\n
                for(jj=0;jj<cdsPciModules.adcCount;jj++)
 		{
@@ -1077,7 +663,6 @@ usleep(1000);
                 ioMemCntr = (ioMemCntr + 1) % IO_MEMORY_SLOTS;
         	clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_START]);
 
-#endif
 	}
 
 	// After first synced ADC read, must set to code to read number samples/cycle
@@ -1100,123 +685,6 @@ usleep(1000);
 /// - -- IOP (ADC_MASTER) reads DAC output values from memory shared with user apps and writes to DAC hardware. \n
 /// - -- USER APP (ADC_SLAVE) sends output values to memory shared with IOP. \n
 
-/// START OF IOP DAC WRITE ***************************************** \n
-#ifdef ADC_MASTER
-        /// \> If DAC FIFO error, always output zero to DAC modules. \n
-        /// - -- Code will require restart to clear.
-        // COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. 
-#ifndef DAC_WD_OVERRIDE
-        if(dacTimingError) iopDacEnable = 0;
-#endif
-        // Write out data to DAC modules
-	dkiTrip = 0;
-	/// \> Loop thru all DAC modules
-        for(jj=0;jj<cdsPciModules.dacCount;jj++)
-        {
-           	/// - -- Point to DAC memory buffer
-           	// pDacData = (unsigned int *)(cdsPciModules.pci_dac[jj]);
-        	/// - -- locate the proper DAC memory block
-        	mm = cdsPciModules.dacConfig[jj];
-        	/// - -- Determine if memory block has been set with the correct cycle count by Slave app.
-		if(ioMemData->iodata[mm][ioMemCntrDac].cycle == ioClockDac)
-		{
-			dacEnable |= pBits[jj];
-		}else {
-			dacEnable &= ~(pBits[jj]);
-			dacChanErr[jj] += 1;
-		}
-		/// - -- Set overflow limits, data mask, and chan count based on DAC type
-                limit = OVERFLOW_LIMIT_16BIT;
-                mask = GSAO_16BIT_MASK;
-                num_outs = GSAO_16BIT_CHAN_COUNT;
-                if (cdsPciModules.dacType[jj] == GSC_18AO8) {
-                        limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit
-                        mask = GSAO_18BIT_MASK;
-                        num_outs = GSAO_18BIT_CHAN_COUNT;
-
-
-                }
-		/// - -- For each DAC channel
-                for (ii=0; ii < num_outs; ii++)
-                {
-#ifdef FLIP_SIGNALS
-                        dacOut[jj][ii] *= -1;
-#endif
-			/// - ---- Read DAC output value from shared memory and reset memory to zero
-                        if((!dacChanErr[jj]) && (iopDacEnable)) {
-                                dac_out = ioMemData->iodata[mm][ioMemCntrDac].data[ii];
-                                /// - --------- Zero out data in case user app dies by next cycle
-                                /// when two or more apps share same DAC module.
-                                ioMemData->iodata[mm][ioMemCntrDac].data[ii] = 0;
-                        } else {
-				dac_out = 0;
-				dkiTrip = 1;
-			}
-                        /// - ----  Write out ADC duotone signal to first DAC, last channel, 
-			/// if DAC duotone is enabled.
-                        if((dacDuoEnable) && (ii==(num_outs-1)) && (jj == 0))
-                        {
-                                dac_out = adcData[0][ADC_DUOTONE_CHAN];
-                        }
-// Code below is only for use in DAQ test system.
-#ifdef DIAG_TEST
-                        if((ii==0) && (jj == 0))
-                        {
-                                if(cycleNum < 100) dac_out = limit / 20;
-                                else dac_out = 0;
-                        }
-                        if((ii==0) && (jj == 3))
-                        {
-                                if(cycleNum < 100) dac_out = limit / 20;
-                                else dac_out = 0;
-                        }
-#endif
-                        /// - ---- Check output values are within range of DAC \n
-                        /// - --------- If overflow, clip at DAC limits and report errors
-                        if(dac_out > limit || dac_out < -limit)
-                        {
-                                overflowDac[jj][ii] ++;
-				pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++;
-                                overflowAcc ++;
-                                dacOF[jj] = 1;
-				odcStateWord |= ODC_DAC_OVF;;
-				if(dac_out > limit) dac_out = limit;
-				else dac_out = -limit;
-                        }
-                        /// - ---- If DAQKILL tripped, set output to zero.
-                        if(!iopDacEnable) dac_out = 0;
-                        /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen.
-                        dacOutEpics[jj][ii] = dac_out;
-
-                        /// - ---- Load DAC testpoints
-                        floatDacOut[16*jj + ii] = dac_out;
-
-                        /// - ---- Write to DAC local memory area, for later xmit to DAC module
-                        // *pDacData =  (unsigned int)(dac_out & mask);
-                        // pDacData ++;
-		}
-                /// - -- Mark cycle count as having been used -1 \n
-                /// - --------- Forces slaves to mark this cycle or will not be used again by Master
-                ioMemData->iodata[mm][ioMemCntrDac].cycle = -1;
-                /// - -- DMA Write data to DAC module
-		#if 0
-                if(dacWriteEnable > 4) {
-                        if(cdsPciModules.dacType[jj] == GSC_16AO16) {
-                                gsc16ao16DmaStart(jj);
-                        } else {
-                                gsc18ao8DmaStart(jj);
-                        }
-                }
-		#endif
-	}
-        /// \> Increment DAC memory block pointers for next cycle
-        ioClockDac = (ioClockDac + 1) % IOP_IO_RATE;
-        ioMemCntrDac = (ioMemCntrDac + 1) % IO_MEMORY_SLOTS;
-        if(dacWriteEnable < 10) dacWriteEnable ++;
-/// END OF IOP DAC WRITE *************************************************
-
-#endif
-#ifdef ADC_SLAVE
 /// START OF USER APP DAC WRITE *****************************************
         // Write out data to DAC modules
 	/// \> Loop thru all DAC modules
@@ -1317,7 +785,6 @@ usleep(1000);
         if(dacWriteEnable < 10) dacWriteEnable ++;
 /// END OF USER APP DAC WRITE *************************************************
 
-#endif
 /// END OF DAC WRITE *************************************************
 
 
@@ -1330,9 +797,6 @@ usleep(1000);
         {
 	  pLocalEpics->epicsOutput.cpuMeter = timeHold;
 	  pLocalEpics->epicsOutput.cpuMeterMax = timeHoldMax;
-#ifdef ADC_MASTER
-  	  pLocalEpics->epicsOutput.dacEnable = dacEnable;
-#endif
           timeHoldHold = timeHold;
           timeHold = 0;
 	  timeHoldWhenHold = timeHoldWhen;
@@ -1376,20 +840,10 @@ usleep(1000);
 		ipcErrBits = 0;
 		
 		// feStatus = 0;
-#ifdef ADC_MASTER
-               for(jj=0;jj<cdsPciModules.adcCount;jj++) adcRdTimeMax[jj] = 0;
-#endif
 	  }
 	  // Flip the onePPS various once/sec as a watchdog monitor.
 	  // pLocalEpics->epicsOutput.onePps ^= 1;
 	  pLocalEpics->epicsOutput.diagWord = diagWord;
-#ifdef ADC_MASTER
-       	  for(jj=0;jj<cdsPciModules.adcCount;jj++) {
-		if(adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC)
-			pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC;
-		adcRdTimeErr[jj] = 0;
-	  }
-#endif
         }
 
 
@@ -1578,12 +1032,10 @@ usleep(1000);
 	  }
         }
 
-#ifdef ADC_SLAVE
         if(cycleNum == 1)
 	{
           pLocalEpics->epicsOutput.timeDiag = timeSec;
 	}
-#endif
 /// \> Cycle 20, Update latest DAC output values to EPICS
         if(subcycle == HKP_DAC_EPICS_UPDATES)
 	{
@@ -1722,23 +1174,13 @@ usleep(1000);
 	adcTime.tv_nsec = cpuClock[CPU_TIME_CYCLE_START].tv_nsec;
 	// Calc the max time of one cycle of the user code
 	// For IOP, more interested in time to get thru ADC read code and send to slave apps
-#ifdef ADC_MASTER2
-	usrTime = (cpuClock[CPU_TIME_USR_START] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE;
-#else
 	usrTime = BILLION * (cpuClock[CPU_TIME_USR_END].tv_sec - cpuClock[CPU_TIME_CYCLE_START].tv_sec) + 
 			     cpuClock[CPU_TIME_USR_END].tv_nsec - cpuClock[CPU_TIME_CYCLE_START].tv_nsec;
 	usrTime /= 1000;
-#endif
 	if(usrTime > usrHoldTime) usrHoldTime = usrTime;
 
         /// \> Update internal cycle counters
           cycleNum += 1;
-#ifdef DIAG_TEST
-          if(pLocalEpics->epicsInput.bumpCycle != 0) {
-	  	cycleNum += pLocalEpics->epicsInput.bumpCycle;
-		pLocalEpics->epicsInput.bumpCycle = 0;
-	  }
-#endif
           cycleNum %= CYCLE_PER_SECOND;
 	  clock1Min += 1;
 	  clock1Min %= CYCLE_PER_MINUTE;
@@ -1764,9 +1206,7 @@ usleep(1000);
   printf("exiting from fe_code()\n");
   pLocalEpics->epicsOutput.cpuMeter = 0;
 
-#ifdef ADC_SLAVE
   deallocate_dac_channels();
-#endif
 
   /* System reset command received */
   return (void *)-1;
diff --git a/src/fe/controllerIopUser.c b/src/fe/controllerIopUser.c
new file mode 100644
index 0000000000000000000000000000000000000000..97ca3717566b7089c6a824bab0e5aa748dd45bc8
--- /dev/null
+++ b/src/fe/controllerIopUser.c
@@ -0,0 +1,1167 @@
+/*----------------------------------------------------------------------*/
+/*                                                                      */
+/*                      -------------------                             */
+/*                                                                      */
+/*                             LIGO                                     */
+/*                                                                      */
+/*        THE LASER INTERFEROMETER GRAVITATIONAL WAVE OBSERVATORY.      */
+/*                                                                      */
+/*                     (C) The LIGO Project, 2012.                      */
+/*                                                                      */
+/*                                                                      */
+/*----------------------------------------------------------------------*/
+
+///	@file controller.c
+///	@brief Main scheduler program for compiled real-time kernal object. \n
+/// 	@detail More information can be found in the following DCC document:
+///<	<a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 CDS RT Sequencer Software</a>
+///	@author R.Bork, A.Ivanov
+///     @copyright Copyright (C) 2014 LIGO Project      \n
+///<    California Institute of Technology              \n
+///<    Massachusetts Institute of Technology           \n\n
+///     @license This program is free software: you can redistribute it and/or modify
+///<    it under the terms of the GNU General Public License as published by
+///<    the Free Software Foundation, version 3 of the License.                 \n
+///<    This program is distributed in the hope that it will be useful,
+///<    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///<    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+///<    GNU General Public License for more details.
+
+
+
+/// Can't use printf in kernel module so redefine to use Linux printk function
+#include <linux/version.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <drv/cdsHardware.h>
+#include "inlineMath.h"
+
+
+#include "fm10Gen.h"		// CDS filter module defs and C code
+#include "feComms.h"		// Lvea control RFM network defs.
+#include "daqmap.h"		// DAQ network layout
+#include "controller.h"
+
+#ifndef NO_DAQ
+#include "drv/fb.h"
+#include "drv/daqLib.c"		// DAQ/GDS connection software
+#endif
+
+#include "drv/epicsXfer.c"	// User defined EPICS to/from FE data transfer function
+#include "drv/mapuser.h"
+// #include "timing.c"		// timing module / IRIG-B  functions
+
+#include "drv/inputFilterModule.h"		
+#include "drv/inputFilterModule1.h"		
+
+#ifdef DOLPHIN_TEST
+#include "dolphin.c"
+#endif
+
+#define BILLION 1000000000L
+
+// Contec 64 input bits plus 64 output bits (Standard for aLIGO)
+/// Contec6464 input register values
+unsigned int CDIO6464InputInput[MAX_DIO_MODULES]; // Binary input bits
+/// Contec6464 - Last output request sent to module.
+unsigned int CDIO6464LastOutState[MAX_DIO_MODULES]; // Current requested value of the BO bits
+/// Contec6464 values to be written to the output register
+unsigned int CDIO6464Output[MAX_DIO_MODULES]; // Binary output bits
+
+// This Contect 16 input / 16 output DIO card is used to control timing slave by IOP
+/// Contec1616 input register values
+unsigned int CDIO1616InputInput[MAX_DIO_MODULES]; // Binary input bits
+/// Contec1616 output register values read back from the module
+unsigned int CDIO1616Input[MAX_DIO_MODULES]; // Current value of the BO bits
+/// Contec1616 values to be written to the output register
+unsigned int CDIO1616Output[MAX_DIO_MODULES]; // Binary output bits
+/// Holds ID number of Contec1616 DIO card(s) used for timing control.
+int tdsControl[3];	// Up to 3 timing control modules allowed in case I/O chassis are daisy chained
+/// Total number of timing control modules found on bus
+int tdsCount = 0;
+
+
+/// Maintains present cycle count within a one second period.
+int cycleNum = 0;
+unsigned int odcStateWord = 0xffff;
+/// Value of readback from DAC FIFO size registers; used in diags for FIFO overflow/underflow.
+int out_buf_size = 0; // test checking DAC buffer size
+unsigned int cycle_gps_time = 0; // Time at which ADCs triggered
+unsigned int cycle_gps_event_time = 0; // Time at which ADCs triggered
+unsigned int   cycle_gps_ns = 0;
+unsigned int   cycle_gps_event_ns = 0;
+unsigned int   gps_receiver_locked = 0; // Lock/unlock flag for GPS time card
+/// GPS time in GPS seconds
+unsigned int timeSec = 0;
+unsigned int timeSecDiag = 0;
+/* 1 - error occured on shmem; 2 - RFM; 3 - Dolphin */
+unsigned int ipcErrBits = 0;
+struct timespec adcTime;			///< Used in code cycle timing
+struct timespec myTimer[2];			///< Used in code cycle timing
+int adcHoldTime;		///< Stores time between code cycles
+int adcHoldTimeMax;		///< Stores time between code cycles
+int adcHoldTimeEverMax;		///< Maximum cycle time recorded
+int adcHoldTimeEverMaxWhen;
+int cpuTimeEverMax;		///< Maximum code cycle time recorded
+int cpuTimeEverMaxWhen;
+int startGpsTime;
+int adcHoldTimeMin;
+int adcHoldTimeAvg;
+int adcHoldTimeAvgPerSec;
+int usrTime;			///< Time spent in user app code
+int usrHoldTime;		///< Max time spent in user app code
+int cardCountErr = 0;
+int cycleTime;			///< Current cycle time
+int timeHold = 0;			///< Max code cycle time within 1 sec period
+int timeHoldHold = 0;			///< Max code cycle time within 1 sec period; hold for another sec
+int timeHoldWhen= 0;			///< Cycle number within last second when maximum reached; running
+int timeHoldWhenHold = 0;		///< Cycle number within last second when maximum reached
+
+// The following are for timing histograms written to /proc files
+#if defined(SERVO64K) || defined(SERVO32K)
+unsigned int cycleHist[32];
+unsigned int cycleHistMax[32];
+unsigned int cycleHistWhen[32];
+unsigned int cycleHistWhenHold[32];
+#elif defined(SERVO16K)
+unsigned int cycleHist[64];
+unsigned int cycleHistMax[64];
+unsigned int cycleHistWhen[64];
+unsigned int cycleHistWhenHold[64];
+#endif
+
+
+struct rmIpcStr *daqPtr;
+
+int  getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); 
+
+// Include C code modules
+#include "rcguserIop.c"
+
+
+char daqArea[2*DAQ_DCU_SIZE];		// Space allocation for daqLib buffers
+int cpuId = 1;
+
+#ifdef DUAL_DAQ_DC
+	#define MX_OK	15
+#else
+	#define MX_OK	3
+#endif
+
+// Whether run on internal timer (when no ADC cards found)
+int run_on_timer = 0;
+
+// Initial diag reset flag
+int initialDiagReset = 1;
+
+// Cache flushing mumbo jumbo suggested by Thomas Gleixner, it is probably useless
+// Did not see any effect
+  char fp [64*1024];
+
+
+unsigned int getGpsTimeProc() {
+  FILE *timef;
+  char line[100];
+  int status;
+  unsigned int mytime;
+
+	timef = fopen("/sys/kernel/gpstime/time","r");
+	if(!timef) {
+		printf("Cannot find GPS time \n");
+		return(0);
+	}
+	fgets(line,100,timef);
+	mytime = atoi(line);
+	printf("GPS TIME is %d\n",mytime);
+	fclose(timef);
+	return (mytime);
+}
+  void initAdcModules(void) {
+	  int status;
+	  int jj;
+
+	  for(jj=0;jj<cdsPciModules.adcCount;jj++)
+	  {
+		  // Set ADC Present Flag
+		  pLocalEpics->epicsOutput.statAdc[jj] = 1;
+		  adcRdTimeErr[jj] = 0;
+	  }
+    	  printf("ADC setup complete \n");
+  }
+  void initDacModules(void) {
+	  int jj;
+	  int status;
+
+	  for(jj = 0; jj < cdsPciModules.dacCount; jj++) {
+		pLocalEpics->epicsOutput.statDac[jj] = DAC_FOUND_BIT;
+	  }
+	  printf("DAC setup complete \n");
+ }
+
+//***********************************************************************
+// TASK: fe_start()	
+// This routine is the skeleton for all front end code	
+//***********************************************************************
+/// This function is the main real-time sequencer or scheduler for all code built
+/// using the RCG. \n
+/// There are two primary modes of operation, based on two compile options: \n
+///	- ADC_MASTER: Software is compiled as an I/O Processor (IOP). 
+///	- ADC_SLAVE: Normal user control process.
+/// This code runs in a continuous loop at the rate specified in the RCG model. The
+/// 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 longestWrite2 = 0;
+  int tempClock[4];
+  int ii,jj,kk,ll,mm;			// Dummy loop counter variables
+  static int clock1Min = 0;		///  @param clockMin Minute counter (Not Used??)
+  struct timespec tp;
+  static struct timespec cpuClock[CPU_TIMER_CNT];	///  @param cpuClock[] Code timing diag variables
+  static int chanHop = 0;		/// @param chanHop Adc channel hopping status
+
+  int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD];	/// @param adcData[][]  ADC raw data
+  int adcChanErr[MAX_ADC_MODULES];
+  int adcWait = 0;
+  int adcOF[MAX_ADC_MODULES];		/// @param adcOF[]  ADC overrange counters
+
+  // int dacChanErr[MAX_DAC_MODULES];
+  int dacOF[MAX_DAC_MODULES];		/// @param dacOF[]  DAC overrange counters
+  static int dacWriteEnable = 0;	/// @param dacWriteEnable  No DAC outputs until >4 times through code
+  					///< Code runs longer for first few cycles on startup as it settles in,
+					///< so this helps prevent long cycles during that time.
+  int limit = OVERFLOW_LIMIT_16BIT;      /// @param limit ADC/DAC overflow test value
+  int mask = GSAI_DATA_MASK;            /// @param mask Bit mask for ADC/DAC read/writes
+  int num_outs = MAX_DAC_CHN_PER_MOD;   /// @param num_outs Number of DAC channels variable
+  volatile int *packedData;		/// @param *packedData Pointer to ADC PCI data space
+  volatile unsigned int *pDacData;	/// @param *pDacData Pointer to DAC PCI data space
+  int wtmin,wtmax;			/// @param wtmin Time window for startup on IRIG-B
+  int dacEnable = 0;
+  int pBits[9] = {1,2,4,8,16,32,64,128,256};	/// @param pBits[] Lookup table for quick power of 2 calcs
+  int sync21ppsCycles = 0;		/// @param sync32ppsCycles Number of attempts to sync to 1PPS
+  int dkiTrip = 0;
+  RFM_FE_COMMS *pEpicsComms;		/// @param *pEpicsComms Pointer to EPICS shared memory space
+  int timeHoldMax = 0;			/// @param timeHoldMax Max code cycle time since last diag reset
+  int myGmError2 = 0;			/// @param myGmError2 Myrinet error variable
+  int status;				/// @param status Typical function return value
+  float onePps;				/// @param onePps Value of 1PPS signal, if used, for diagnostics
+  int onePpsHi = 0;			/// @param onePpsHi One PPS diagnostic check
+  int onePpsTime = 0;			/// @param onePpsTime One PPS diagnostic check
+#ifdef DIAG_TEST
+  float onePpsTest;			/// @param onePpsTest Value of 1PPS signal, if used, for diagnostics
+  int onePpsHiTest[10];			/// @param onePpsHiTest[] One PPS diagnostic check
+  int onePpsTimeTest[10];		/// @param onePpsTimeTest[] One PPS diagnostic check
+#endif
+  int dcuId;				/// @param dcuId DAQ ID number for this process
+  static int missedCycle = 0;		/// @param missedCycle Incremented error counter when too many values in ADC FIFO
+  int diagWord = 0;			/// @param diagWord Code diagnostic bit pattern returned to EPICS
+  int system = 0;
+  int sampleCount = 1;			/// @param sampleCount Number of ADC samples to take per code cycle
+  int sync21pps = 0;			/// @param sync21pps Code startup sync to 1PPS flag
+  int syncSource = SYNC_SRC_NONE;	/// @param syncSource Code startup synchronization source
+  int mxStat = 0;			/// @param mxStat Net diags when myrinet express is used
+  int mxDiag = 0;
+  int mxDiagR = 0;
+// ****** Share data
+  int ioClockDac = DAC_PRELOAD_CNT;
+  int ioMemCntr = 0;
+  int ioMemCntrDac = DAC_PRELOAD_CNT;
+  double dac_in =  0.0;			/// @param dac_in DAC value after upsample filtering
+  int dac_out = 0;			/// @param dac_out Integer value sent to DAC FIFO
+
+  int feStatus = 0;
+
+  int clk, clk1;			// Used only when run on timer enabled (test mode)
+
+  static float duotone[IOP_IO_RATE];		// Duotone timing diagnostic variables
+  static float duotoneDac[IOP_IO_RATE];
+  float duotoneTimeDac;
+  float duotoneTime;
+  static float duotoneTotal = 0.0;
+  static float duotoneMean = 0.0;
+  static float duotoneTotalDac = 0.0;
+  static float duotoneMeanDac = 0.0;
+  static int dacDuoEnable = 0;
+  static int dacTimingError = 0;
+  static int dacTimingErrorPending[MAX_DAC_MODULES];
+
+  volatile GSA_18BIT_DAC_REG *dac18bitPtr;	// Pointer to 16bit DAC memory area
+  volatile GSC_DAC_REG *dac16bitPtr;		// Pointer to 18bit DAC memory area
+  unsigned int usec = 0;
+  unsigned int offset = 0;
+
+
+  int cnt = 0;
+  unsigned long cpc;
+
+/// **********************************************************************************************\n
+/// Start Initialization Process \n
+/// **********************************************************************************************\n
+  memset (tempClock, 0, sizeof(tempClock));
+
+  /// \> Flush L1 cache
+  memset (fp, 0, 64*1024);
+  memset (fp, 1, 64*1024);
+
+  fz_daz(); /// \> Kill the denorms!
+
+// Set memory for cycle time history diagnostics
+#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K)
+  memset(cycleHist, 0, sizeof(cycleHist));
+  memset(cycleHistMax, 0, sizeof(cycleHistMax));
+  memset(cycleHistWhen, 0, sizeof(cycleHistWhen));
+  memset(cycleHistWhenHold, 0, sizeof(cycleHistWhenHold));
+#endif
+
+  /// \> Init comms with EPICS processor */
+  pEpicsComms = (RFM_FE_COMMS *)_epics_shm;
+  pLocalEpics = (CDS_EPICS *)&pEpicsComms->epicsSpace;
+  pEpicsDaq = (char *)&(pLocalEpics->epicsOutput);
+// printf("Epics at 0x%x and DAQ at 0x%x  size = %d \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN));
+
+#ifdef OVERSAMPLE
+  /// \> Zero out filter histories
+  memset(dHistory, 0, sizeof(dHistory));
+  memset(dDacHistory, 0, sizeof(dDacHistory));
+#endif
+
+  /// \> Zero out DAC outputs
+  for (ii = 0; ii < MAX_DAC_MODULES; ii++)
+  {
+    dacTimingErrorPending[ii] = 0;
+    for (jj = 0; jj < 16; jj++) {
+ 	dacOut[ii][jj] = 0.0;
+ 	dacOutUsed[ii][jj] = 0;
+	dacOutBufSize[ii] = 0;
+	// Zero out DAC channel map in the shared memory
+	// to be used to check on slaves' channel allocation
+	ioMemData->dacOutUsed[ii][jj] = 0;
+    }
+  }
+
+  /// \> Set pointers to filter module data buffers. \n
+  /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD data.\n
+  /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n
+  /// - -------- Allow daqLib.c to retrieve filter module data directly from shared memory. \n
+  /// - -------- Avoid copy of filter module data between to memory locations, which was slow. \n
+    pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace);
+    pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace);
+    dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace);
+
+  /// \> Clear the FE reset which comes from Epics
+  pLocalEpics->epicsInput.vmeReset = 0;
+
+  // Clear input masks
+  pLocalEpics->epicsInput.burtRestore_mask = 0;
+  pLocalEpics->epicsInput.dacDuoSet_mask = 0;
+  memset(proc_futures, 0, sizeof(proc_futures));
+
+/// \> Init code synchronization source.
+  // Look for DIO card or IRIG-B Card
+  // if Contec 1616 BIO present, TDS slave will be used for timing.
+   syncSource = SYNC_SRC_TIMER;
+
+printf("Sync source = %d\n",syncSource);
+
+
+/// \> Wait for BURT restore.\n
+/// - ---- Code will exit if BURT flag not set by EPICS sequencer.
+  // Do not proceed until EPICS has had a BURT restore *******************************
+  printf("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore);
+  cnt = 0;
+  do{
+	usleep(80000);
+  	printf("Waiting for EPICS BURT %d\n", cnt++);
+  }while(!pLocalEpics->epicsInput.burtRestore);
+
+  printf("BURT Restore Complete\n");
+
+// BURT has completed *******************************************************************
+
+/// < Read in all Filter Module EPICS coeff settings
+    for(ii=0;ii<MAX_MODULES;ii++)
+    {
+	checkFiltReset(ii, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]);
+    }
+
+  // Need this FE dcuId to make connection to FB
+  dcuId = pLocalEpics->epicsInput.dcuId;
+  pLocalEpics->epicsOutput.dcuId = dcuId;
+
+  // Reset timing diagnostics
+  pLocalEpics->epicsOutput.diagWord = 0;
+  pLocalEpics->epicsOutput.timeDiag = 0;
+  pLocalEpics->epicsOutput.timeErr = syncSource;
+
+/// \> Init IIR filter banks
+//   Initialize filter banks  *********************************************
+  for (system = 0; system < NUM_SYSTEMS; system++) {
+    for(ii=0;ii<MAX_MODULES;ii++){
+      for(jj=0;jj<FILTERS;jj++){
+        for(kk=0;kk<MAX_COEFFS;kk++){
+          dspCoeff[system].coeffs[ii].filtCoeff[jj][kk] = 0.0;
+        }
+        dspCoeff[system].coeffs[ii].filtSections[jj] = 0;
+      }
+    }
+  }
+
+  /// \> Initialize all filter module excitation signals to zero 
+  for (system = 0; system < NUM_SYSTEMS; system++)
+    for(ii=0;ii<MAX_MODULES;ii++)
+       // dsp[system].data[ii].exciteInput = 0.0;
+       pDsp[0]->data[ii].exciteInput = 0.0;
+
+
+  /// \> Initialize IIR filter bank values
+    if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) {
+    	printf("Filter module init failed, exiting\n");
+	return 0;
+    }
+
+  printf("Initialized servo control parameters.\n");
+
+usleep(1000);
+
+/// \> Initialize DAQ variable/software 
+#if !defined(NO_DAQ) && !defined(IOP_TASK)
+  /// - ---- Set data range limits for daqLib routine 
+#if defined(SERVO2K) || defined(SERVO4K)
+  daq.filtExMin = GDS_2K_EXC_MIN;
+  daq.filtTpMin = GDS_2K_TP_MIN;
+#else
+  daq.filtExMin = GDS_16K_EXC_MIN;
+  daq.filtTpMin = GDS_16K_TP_MIN;
+#endif
+  daq.filtExMax = daq.filtExMin + MAX_MODULES;
+  daq.filtExSize = MAX_MODULES;
+  daq.xExMin = daq.filtExMax;
+  daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC;
+  daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3;
+  daq.filtTpSize = MAX_MODULES * 3;
+  daq.xTpMin = daq.filtTpMax;
+  daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP;
+
+  printf("DAQ Ex Min/Max = %d %d\n",daq.filtExMin,daq.filtExMax);
+  printf("DAQ XEx Min/Max = %d %d\n",daq.xExMin,daq.xExMax);
+  printf("DAQ Tp Min/Max = %d %d\n",daq.filtTpMin,daq.filtTpMax);
+  printf("DAQ XTp Min/Max = %d %d\n",daq.xTpMin,daq.xTpMax);
+
+  /// - ---- Assign DAC testpoint pointers
+  for (ii = 0; ii <  cdsPciModules.dacCount; ii++)
+	for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) // 16 per DAC regardless of the actual
+		testpoint[MAX_DAC_CHN_PER_MOD * ii + jj] = floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj;
+
+  // Zero out storage
+  memset(floatDacOut, 0, sizeof(floatDacOut));
+
+#endif
+  pLocalEpics->epicsOutput.ipcStat = 0;
+  pLocalEpics->epicsOutput.fbNetStat = 0;
+  pLocalEpics->epicsOutput.tpCnt = 0;
+
+#if !defined(NO_DAQ) && !defined(IOP_TASK)
+  /// - ---- Initialize DAQ function
+  status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq);
+  if(status == -1) 
+  {
+    printf("DAQ init failed -- exiting\n");
+    vmeDone = 1;
+    return(0);
+  }
+#endif
+
+
+  // Clear the code exit flag
+  vmeDone = 0;
+
+  /// \> Call user application software initialization routine.
+  printf("Calling feCode() to initialize\n");
+  iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1);
+
+/// \> Verify DAC channels defined for this app are not already in use. \n
+/// - ---- User apps are allowed to share DAC modules but not DAC channels.
+
+  // Clear timing diags.
+  adcHoldTime = 0;
+  adcHoldTimeMax = 0;
+  adcHoldTimeEverMax = 0;	
+  adcHoldTimeEverMaxWhen = 0;	
+  cpuTimeEverMax = 0;		
+  cpuTimeEverMaxWhen = 0;	
+  startGpsTime = 0;
+  adcHoldTimeMin = 0xffff;	
+  adcHoldTimeAvg = 0;		
+  usrHoldTime = 0;		
+  missedCycle = 0;
+
+  /// \> If IOP,  Initialize the ADC modules
+  initAdcModules();
+
+  /// \> If IOP, Initialize the DAC module variables
+  initDacModules();
+
+  if (run_on_timer) {	// NOT normal operating mode; used for test systems without I/O cards/chassis
+    printf("*******************************\n");
+    printf("*     Running on timer!       *\n");
+    printf("*******************************\n");
+          do {
+		usleep(1);
+    		clock_gettime(CLOCK_MONOTONIC, &myTimer[0]);
+		cycleTime = myTimer[0].tv_nsec / 1000;
+    	  } while(cycleTime > 10);
+	  // timeSec = myTimer[0].tv_sec - 1;
+	  timeSec = getGpsTimeProc();
+		startGpsTime = timeSec;
+		pLocalEpics->epicsOutput.startgpstime = startGpsTime;
+    printf("Triggered the ADC at %d and %d usec\n",timeSec,cycleTime);
+  } else {
+  	printf("Can't run with I/O \n");
+	exit(-1);
+  }
+  onePpsTime = cycleNum;
+
+  clock_gettime(CLOCK_MONOTONIC, &adcTime);
+
+  /// ******************************************************************************\n
+  /// Enter the infinite FE control loop  ******************************************\n
+
+  /// ******************************************************************************\n
+  // Calculate how many CPU cycles per code cycle
+  // cpc = cpu_khz * 1000;
+  // cpc /= CYCLE_PER_SECOND;
+
+
+  while(!vmeDone){ 	// Run forever until user hits reset
+  	if (run_on_timer) {  // NO ADC present, so run on CPU realtime clock
+	  // Pause until next cycle begins
+	  if (cycleNum == 0) {
+	    	//printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec);
+	  	pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec);
+	  }
+	  // This is local CPU timer (no ADCs)
+	  // advance to the next cycle polling CPU cycles and microsleeping
+	  do {
+    		clock_gettime(CLOCK_MONOTONIC, &myTimer[1]);
+	        clk = BILLION * (myTimer[1].tv_sec - myTimer[0].tv_sec) + 
+	    	                 myTimer[1].tv_nsec - myTimer[0].tv_nsec;
+	  	clk /= 1000;
+	  } while(clk < 15);
+	    myTimer[0].tv_sec = myTimer[1].tv_sec;
+	    myTimer[0].tv_nsec = myTimer[1].tv_nsec;
+	    // printf("My clock is %d and %d usec \n", myTimer[0].tv_sec, (myTimer[0].tv_nsec / 1000));
+
+	    ioMemCntr = (cycleNum % IO_MEMORY_SLOTS);
+	    // Write GPS time and cycle count as indicator to slave that adc data is ready
+            for(jj=0;jj<cdsPciModules.adcCount;jj++)
+	    {
+		    for(ii=0;ii<IO_MEMORY_SLOT_VALS;ii++)
+		    {
+			ioMemData->iodata[jj][ioMemCntr].data[ii] = cycleNum/4;
+		    }
+	    	ioMemData->iodata[jj][ioMemCntr].timeSec = timeSec;;
+	    	ioMemData->iodata[jj][ioMemCntr].cycle = cycleNum;
+	    }
+	    ioMemData->gpsSecond = timeSec;
+	  clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_START]);
+
+         if(cycleNum == 0) {
+
+	  // Increment GPS second on cycle 0
+          timeSec ++;
+          pLocalEpics->epicsOutput.timeDiag = timeSec;
+	  }
+	} else {
+	// **********************************************************************************************************
+	// NORMAL OPERATION -- Wait for ADC data ready
+	// On startup, only want to read one sample such that first cycle
+	// coincides with GPS 1PPS. Thereafter, sampleCount will be 
+	// increased to appropriate number of 65536 s/sec to match desired
+	// code rate eg 32 samples each time thru before proceeding to match 2048 system.
+	// **********************************************************************************************************
+
+/// \> On 1PPS mark \n
+       if(cycleNum == 0)
+        {
+	  /// - ---- Check awgtpman status.
+	  //printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec);
+	  pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec);
+	  if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG;
+	  /// - ---- Check if DAC outputs are enabled, report error.
+	  if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE;
+
+	  /// - ---- If IOP, Increment GPS second
+          timeSec ++;
+          pLocalEpics->epicsOutput.timeDiag = timeSec;
+	  if (cycle_gps_time == 0) {
+		startGpsTime = timeSec;
+		pLocalEpics->epicsOutput.startgpstime = startGpsTime;
+		printf("Cycle gps = %d\n",startGpsTime);
+	  }
+	  cycle_gps_time = timeSec;
+	}
+
+	// After first synced ADC read, must set to code to read number samples/cycle
+        sampleCount = OVERSAMPLE_TIMES;
+	}
+/// End of ADC Read **************************************************************************************
+
+
+
+/// \> Call the front end specific application  ******************\n
+/// - -- This is where the user application produced by RCG gets called and executed. \n\n
+         clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_START]);
+ 	iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0);
+         clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_END]);
+
+  	odcStateWord = 0;
+/// WRITE DAC OUTPUTS ***************************************** \n
+
+/// Writing of DAC outputs is dependent on code compile option: \n
+/// - -- IOP (ADC_MASTER) reads DAC output values from memory shared with user apps and writes to DAC hardware. \n
+/// - -- USER APP (ADC_SLAVE) sends output values to memory shared with IOP. \n
+
+/// START OF IOP DAC WRITE ***************************************** \n
+        /// \> If DAC FIFO error, always output zero to DAC modules. \n
+        /// - -- Code will require restart to clear.
+        // COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. 
+#ifndef DAC_WD_OVERRIDE
+        if(dacTimingError) iopDacEnable = 0;
+#endif
+        // Write out data to DAC modules
+	dkiTrip = 0;
+	/// \> Loop thru all DAC modules
+        for(jj=0;jj<cdsPciModules.dacCount;jj++)
+        {
+           	/// - -- Point to DAC memory buffer
+           	// pDacData = (unsigned int *)(cdsPciModules.pci_dac[jj]);
+        	/// - -- locate the proper DAC memory block
+        	mm = cdsPciModules.dacConfig[jj];
+        	/// - -- Determine if memory block has been set with the correct cycle count by Slave app.
+		if(ioMemData->iodata[mm][ioMemCntrDac].cycle == ioClockDac)
+		{
+			dacEnable |= pBits[jj];
+		}else {
+			dacEnable &= ~(pBits[jj]);
+			dacChanErr[jj] += 1;
+		}
+		/// - -- Set overflow limits, data mask, and chan count based on DAC type
+                limit = OVERFLOW_LIMIT_16BIT;
+                mask = GSAO_16BIT_MASK;
+                num_outs = GSAO_16BIT_CHAN_COUNT;
+                if (cdsPciModules.dacType[jj] == GSC_18AO8) {
+                        limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit
+                        mask = GSAO_18BIT_MASK;
+                        num_outs = GSAO_18BIT_CHAN_COUNT;
+
+
+                }
+		/// - -- For each DAC channel
+                for (ii=0; ii < num_outs; ii++)
+                {
+#ifdef FLIP_SIGNALS
+                        dacOut[jj][ii] *= -1;
+#endif
+			/// - ---- Read DAC output value from shared memory and reset memory to zero
+                        if((!dacChanErr[jj]) && (iopDacEnable)) {
+                                dac_out = ioMemData->iodata[mm][ioMemCntrDac].data[ii];
+                                /// - --------- Zero out data in case user app dies by next cycle
+                                /// when two or more apps share same DAC module.
+                                ioMemData->iodata[mm][ioMemCntrDac].data[ii] = 0;
+                        } else {
+				dac_out = 0;
+				dkiTrip = 1;
+			}
+                        /// - ----  Write out ADC duotone signal to first DAC, last channel, 
+			/// if DAC duotone is enabled.
+                        if((dacDuoEnable) && (ii==(num_outs-1)) && (jj == 0))
+                        {
+                                dac_out = adcData[0][ADC_DUOTONE_CHAN];
+                        }
+// Code below is only for use in DAQ test system.
+#ifdef DIAG_TEST
+                        if((ii==0) && (jj == 0))
+                        {
+                                if(cycleNum < 100) dac_out = limit / 20;
+                                else dac_out = 0;
+                        }
+                        if((ii==0) && (jj == 3))
+                        {
+                                if(cycleNum < 100) dac_out = limit / 20;
+                                else dac_out = 0;
+                        }
+#endif
+                        /// - ---- Check output values are within range of DAC \n
+                        /// - --------- If overflow, clip at DAC limits and report errors
+                        if(dac_out > limit || dac_out < -limit)
+                        {
+                                overflowDac[jj][ii] ++;
+				pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++;
+                                overflowAcc ++;
+                                dacOF[jj] = 1;
+				odcStateWord |= ODC_DAC_OVF;;
+				if(dac_out > limit) dac_out = limit;
+				else dac_out = -limit;
+                        }
+                        /// - ---- If DAQKILL tripped, set output to zero.
+                        if(!iopDacEnable) dac_out = 0;
+                        /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen.
+                        dacOutEpics[jj][ii] = dac_out;
+
+                        /// - ---- Load DAC testpoints
+                        floatDacOut[16*jj + ii] = dac_out;
+
+                        /// - ---- Write to DAC local memory area, for later xmit to DAC module
+                        // *pDacData =  (unsigned int)(dac_out & mask);
+                        // pDacData ++;
+		}
+                /// - -- Mark cycle count as having been used -1 \n
+                /// - --------- Forces slaves to mark this cycle or will not be used again by Master
+                ioMemData->iodata[mm][ioMemCntrDac].cycle = -1;
+                /// - -- DMA Write data to DAC module
+		#if 0
+                if(dacWriteEnable > 4) {
+                        if(cdsPciModules.dacType[jj] == GSC_16AO16) {
+                                gsc16ao16DmaStart(jj);
+                        } else {
+                                gsc18ao8DmaStart(jj);
+                        }
+                }
+		#endif
+	}
+        /// \> Increment DAC memory block pointers for next cycle
+        ioClockDac = (ioClockDac + 1) % IOP_IO_RATE;
+        ioMemCntrDac = (ioMemCntrDac + 1) % IO_MEMORY_SLOTS;
+        if(dacWriteEnable < 10) dacWriteEnable ++;
+/// END OF IOP DAC WRITE *************************************************
+
+/// END OF DAC WRITE *************************************************
+
+
+/// BEGIN HOUSEKEEPING ************************************************ \n
+
+        pLocalEpics->epicsOutput.cycle = cycleNum;
+
+/// \> Cycle 18, Send timing info to EPICS at 1Hz
+	if(cycleNum ==HKP_TIMING_UPDATES)	
+        {
+	  pLocalEpics->epicsOutput.cpuMeter = timeHold;
+	  pLocalEpics->epicsOutput.cpuMeterMax = timeHoldMax;
+  	  pLocalEpics->epicsOutput.dacEnable = dacEnable;
+          timeHoldHold = timeHold;
+          timeHold = 0;
+	  timeHoldWhenHold = timeHoldWhen;
+
+#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K)
+	  memcpy(cycleHistMax, cycleHist, sizeof(cycleHist));
+	  memset(cycleHist, 0, sizeof(cycleHist));
+	  memcpy(cycleHistWhenHold, cycleHistWhen, sizeof(cycleHistWhen));
+	  memset(cycleHistWhen, 0, sizeof(cycleHistWhen));
+#endif
+	  if (timeSec % 4 == 0) pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeMin;
+	  else if (timeSec % 4 == 1)
+		pLocalEpics->epicsOutput.adcWaitTime =  adcHoldTimeMax;
+	  else
+	  	pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeAvg/CYCLE_PER_SECOND;
+	  adcHoldTimeAvgPerSec = adcHoldTimeAvg/CYCLE_PER_SECOND;
+	  adcHoldTimeMax = 0;
+	  adcHoldTimeMin = 0xffff;
+	  adcHoldTimeAvg = 0;
+	  if((adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcHoldTime < CYCLE_TIME_ALRM_LO)) 
+	  {
+	  	diagWord |= FE_ADC_HOLD_ERR;
+		feStatus |= FE_ERROR_TIMING;
+	  
+	  }
+	  if(timeHoldMax > CYCLE_TIME_ALRM) 
+	  {
+	  	diagWord |= FE_PROC_TIME_ERR;
+		feStatus |= FE_ERROR_TIMING;
+	  }
+	  pLocalEpics->epicsOutput.stateWord = feStatus;
+  	  feStatus = 0;
+  	  if(pLocalEpics->epicsInput.diagReset || initialDiagReset)
+	  {
+		initialDiagReset = 0;
+		pLocalEpics->epicsInput.diagReset = 0;
+		pLocalEpics->epicsInput.ipcDiagReset = 1;
+  		// pLocalEpics->epicsOutput.diags[1] = 0;
+		timeHoldMax = 0;
+	  	diagWord = 0;
+		ipcErrBits = 0;
+		
+		// feStatus = 0;
+               for(jj=0;jj<cdsPciModules.adcCount;jj++) adcRdTimeMax[jj] = 0;
+	  }
+	  // Flip the onePPS various once/sec as a watchdog monitor.
+	  // pLocalEpics->epicsOutput.onePps ^= 1;
+	  pLocalEpics->epicsOutput.diagWord = diagWord;
+       	  for(jj=0;jj<cdsPciModules.adcCount;jj++) {
+		if(adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC)
+			pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC;
+		adcRdTimeErr[jj] = 0;
+	  }
+        }
+
+
+/// \> Check for requests for filter module clear history requests. This is spread out over a number of cycles.
+	// Spread out filter coeff update, but keep updates at 16 Hz
+	// here we are rounding up:
+	//   x/y rounded up equals (x + y - 1) / y
+	//
+	{ 
+		static const unsigned int mpc = (MAX_MODULES + (FE_RATE / 16) - 1) / (FE_RATE / 16); // Modules per cycle
+		unsigned int smpc = mpc * subcycle; // Start module counter
+		unsigned int empc = smpc + mpc; // End module counter
+		unsigned int i;
+		for (i = smpc; i < MAX_MODULES && i < empc ; i++) 
+			checkFiltReset(i, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]);
+	}
+
+	/// \> Check if code exit is requested
+	if(cycleNum == MAX_MODULES) 
+		vmeDone = stop_working_threads | checkEpicsReset(cycleNum, (struct CDS_EPICS *)pLocalEpics);
+
+	// If synced to 1PPS on startup, continue to check that code
+	// is still in sync with 1PPS.
+	// This is NOT normal aLIGO mode.
+	if(syncSource == SYNC_SRC_1PPS)
+	{
+
+		// Assign chan 32 to onePps 
+		onePps = adcData[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN];
+		if((onePps > ONE_PPS_THRESH) && (onePpsHi == 0))  
+		{
+			onePpsTime = cycleNum;
+			onePpsHi = 1;
+		}
+		if(onePps < ONE_PPS_THRESH) onePpsHi = 0;  
+
+		// Check if front end continues to be in sync with 1pps
+		// If not, set sync error flag
+		if(onePpsTime > 1) pLocalEpics->epicsOutput.timeErr |= TIME_ERR_1PPS;
+	}
+#ifdef DIAG_TEST
+	for(ii=0;ii<10;ii++)
+	{
+		if(ii<5) onePpsTest = adcData[0][ii];
+		else onePpsTest = adcData[1][(ii-5)];
+		if((onePpsTest > 400) && (onePpsHiTest[ii] == 0))  
+		{
+			onePpsTimeTest[ii] = cycleNum;
+			onePpsHiTest[ii] = 1;
+			if((ii == 0) || (ii == 5)) pLocalEpics->epicsOutput.timingTest[ii] = cycleNum * 15.26;
+			// Slaves do not see 1pps until after IOP signal loops around and back into ADC channel 0,
+			// therefore, need to subtract IOP loop time.
+			else pLocalEpics->epicsOutput.timingTest[ii] = (cycleNum * 15.26) - pLocalEpics->epicsOutput.timingTest[0];
+		}
+		// Reset the diagnostic for next cycle
+		if(cycleNum > 2000) onePpsHiTest[ii] = 0;  
+	}
+#endif
+
+#ifdef ADC_NOTHING
+/// \> Cycle 10 to number of BIO cards:\n
+ /// - ---- If User App, Read Dio cards once per second \n
+ /// - ---- IOP does not handle binary I/O module traffic, as it can take too long
+
+	if(cdsPciModules.doCount)
+        // if((cycleNum < (HKP_READ_DIO + cdsPciModules.doCount)) && (cycleNum >= HKP_READ_DIO))
+        {
+                // kk = cycleNum - HKP_READ_DIO;
+		kk = cycleNum % cdsPciModules.doCount;
+                ii = cdsPciModules.doInstance[kk];
+                if(cdsPciModules.doType[kk] == ACS_8DIO)
+                {
+	  		rioInputInput[ii] = accesIiro8ReadInputRegister(&cdsPciModules, kk) & 0xff;
+	  		rioInputOutput[ii] = accesIiro8ReadOutputRegister(&cdsPciModules, kk) & 0xff;
+                }
+                if(cdsPciModules.doType[kk] == ACS_16DIO)
+                {
+                        rioInput1[ii] = accesIiro16ReadInputRegister(&cdsPciModules, kk) & 0xffff;
+                }
+		if(cdsPciModules.doType[kk] == ACS_24DIO)
+		{
+		  dioInput[ii] = accesDio24ReadInputRegister(&cdsPciModules, kk);
+		}
+		if (cdsPciModules.doType[kk] == CON_6464DIO) {
+	 		CDIO6464InputInput[ii] = contec6464ReadInputRegister(&cdsPciModules, kk);
+		}
+		if (cdsPciModules.doType[kk] == CDI64) {
+	 		CDIO6464InputInput[ii] = contec6464ReadInputRegister(&cdsPciModules, kk);
+		}
+        }
+/// \> If user app, write Dio cards only on change
+        for(kk=0;kk < cdsPciModules.doCount;kk++)
+        {
+                ii = cdsPciModules.doInstance[kk];
+                if((cdsPciModules.doType[kk] == ACS_8DIO) && (rioOutput[ii] != rioOutputHold[ii]))
+                {
+                        accesIiro8WriteOutputRegister(&cdsPciModules, kk, rioOutput[ii]);
+                        rioOutputHold[ii] = rioOutput[ii];
+                } else 
+                if((cdsPciModules.doType[kk] == ACS_16DIO) && (rioOutput1[ii] != rioOutputHold1[ii]))
+                {
+                        accesIiro16WriteOutputRegister(&cdsPciModules, kk, rioOutput1[ii]);
+                        rioOutputHold1[ii] = rioOutput1[ii];
+                } else 
+                if(cdsPciModules.doType[kk] == CON_32DO)
+                {
+                        if (CDO32Input[ii] != CDO32Output[ii]) {
+                          CDO32Input[ii] = contec32WriteOutputRegister(&cdsPciModules, kk, CDO32Output[ii]);
+                        }
+		} else if (cdsPciModules.doType[kk] == CON_6464DIO) {
+			if (CDIO6464LastOutState[ii] != CDIO6464Output[ii]) {
+			  CDIO6464LastOutState[ii] = contec6464WriteOutputRegister(&cdsPciModules, kk, CDIO6464Output[ii]);
+			}
+		} else if (cdsPciModules.doType[kk] == CDO64) {
+			if (CDIO6464LastOutState[ii] != CDIO6464Output[ii]) {
+			  CDIO6464LastOutState[ii] = contec6464WriteOutputRegister(&cdsPciModules, kk, CDIO6464Output[ii]);
+			}
+                } else
+                if((cdsPciModules.doType[kk] == ACS_24DIO) && (dioOutputHold[ii] != dioOutput[ii]))
+		{
+                        accesDio24WriteOutputRegister(&cdsPciModules, kk, dioOutput[ii]);
+			dioOutputHold[ii] = dioOutput[ii];
+		}
+        }
+
+#endif end remove
+
+/// \>  Write data to DAQ.
+#ifndef NO_DAQ
+		
+		// Call daqLib
+		pLocalEpics->epicsOutput.daqByteCnt = 
+			daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq);
+		// Send the current DAQ block size to the awgtpman for TP number checking
+	  	pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize;
+	  	pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff;
+		feStatus |= (FE_ERROR_EXC_SET & tpPtr->count);
+		if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET;
+		else odcStateWord &= ~(ODC_EXC_SET);
+		if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) 
+			feStatus |= FE_ERROR_DAQ;
+#endif
+
+/// \> Cycle 19, write updated diag info to EPICS
+	if(cycleNum == HKP_DIAG_UPDATES)	
+        {
+	  pLocalEpics->epicsOutput.userTime = usrHoldTime;
+	  pLocalEpics->epicsOutput.ipcStat = ipcErrBits;
+	  if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC;
+	  // Create FB status word for return to EPICS
+	  mxStat = 0;
+	  mxDiagR = daqPtr->reqAck;
+	  if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1;
+	  if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2;
+#ifdef DUAL_DAQ_DC
+	  if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4;
+	  if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8;
+#endif
+	  pLocalEpics->epicsOutput.fbNetStat = mxStat;
+  	  mxDiag = mxDiagR;
+	  if(mxStat != MX_OK)
+		feStatus |= FE_ERROR_DAQ;;
+	  usrHoldTime = 0;
+  	  if(pLocalEpics->epicsInput.overflowReset)
+	  {
+                if (pLocalEpics->epicsInput.overflowReset) {
+                   for (ii = 0; ii < 16; ii++) {
+                      for (jj = 0; jj < cdsPciModules.adcCount; jj++) {
+                         overflowAdc[jj][ii] = 0;
+                         overflowAdc[jj][ii + 16] = 0;
+			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
+			pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0;
+                      }
+
+                      for (jj = 0; jj < cdsPciModules.dacCount; jj++) {
+                         pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
+                      }
+                   }
+                }
+	  }
+  	  if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT))
+	  {
+		pLocalEpics->epicsInput.overflowReset = 0;
+		pLocalEpics->epicsOutput.ovAccum = 0;
+		overflowAcc = 0;
+	  }
+        }
+
+/// \> Cycle 20, Update latest DAC output values to EPICS
+        if(subcycle == HKP_DAC_EPICS_UPDATES)
+	{
+	      // Send DAC output values at 16Hzfb
+	      for(jj=0;jj<cdsPciModules.dacCount;jj++)
+	      {
+	    	for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++)
+	    	{
+			pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii];
+		}
+	      }
+	}
+
+/// \> Cycle 21, Update ADC/DAC status to EPICS.
+        if(cycleNum == HKP_ADC_DAC_STAT_UPDATES)
+        {
+	  pLocalEpics->epicsOutput.ovAccum = overflowAcc;
+	  for(jj=0;jj<cdsPciModules.adcCount;jj++)
+	  {
+	    // SET/CLR Channel Hopping Error
+	    if(adcChanErr[jj]) 
+	    {
+	    	pLocalEpics->epicsOutput.statAdc[jj] &= ~(2);
+		feStatus |= FE_ERROR_ADC;;
+	    }
+ 	    else pLocalEpics->epicsOutput.statAdc[jj] |= 2;
+	    adcChanErr[jj] = 0;
+	    // SET/CLR Overflow Error
+	    if(adcOF[jj]) 
+	    {
+	    	pLocalEpics->epicsOutput.statAdc[jj] &= ~(4);
+		feStatus |= FE_ERROR_OVERFLOW;;
+	    }
+ 	    else pLocalEpics->epicsOutput.statAdc[jj] |= 4;
+	    adcOF[jj] = 0;
+	    for(ii=0;ii<32;ii++)
+	    {
+
+                if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
+		   pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0;
+                }
+		pLocalEpics->epicsOutput.overflowAdc[jj][ii] = overflowAdc[jj][ii];
+		overflowAdc[jj][ii] = 0;
+
+	    }
+	  }
+	  // If ADC channels not where they should be, we have no option but to exit
+	  // from the RT code ie loops would be working with wrong input data.
+	  if (chanHop) {
+	  	pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
+	         stop_working_threads = 1;
+	         vmeDone = 1;
+	         printf("Channel Hopping Detected on one or more ADC modules !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+	         printf("Check GDSTP screen ADC status bits to id affected ADC modules\n");
+	         printf("Code is exiting ..............\n");
+	 	 continue;    
+	  }
+	  for(jj=0;jj<cdsPciModules.dacCount;jj++)
+	  {
+	    if(dacOF[jj]) 
+	    {
+	    	pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT);
+		feStatus |= FE_ERROR_OVERFLOW;;
+	    }
+ 	    else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT;
+	    dacOF[jj] = 0;
+	    if(dacChanErr[jj]) 
+	    {
+	    	pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT);
+	    }
+ 	    else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT;
+	    dacChanErr[jj] = 0;
+	    for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++)
+	    {
+
+                if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) {
+		   pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0;
+                }
+		pLocalEpics->epicsOutput.overflowDac[jj][ii] = overflowDac[jj][ii];
+		overflowDac[jj][ii] = 0;
+
+	    }
+	  }
+        }
+	// Capture end of cycle time.
+         clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_END]);
+
+	/// \> Compute code cycle time diag information.
+	cycleTime = BILLION * (cpuClock[CPU_TIME_CYCLE_END].tv_sec - cpuClock[CPU_TIME_CYCLE_START].tv_sec) + 
+			     cpuClock[CPU_TIME_CYCLE_END].tv_nsec - cpuClock[CPU_TIME_CYCLE_START].tv_nsec;
+	cycleTime /= 1000;
+	if (cycleTime > (1000000/CYCLE_PER_SECOND))  {
+		// printf("cycle %d time %d; adcWait %d; write1 %d; write2 %d; longest write2 %d\n", cycleNum, cycleTime, adcWait, (tempClock[1]-tempClock[0])/CPURATE, (tempClock[3]-tempClock[2])/CPURATE, longestWrite2);
+	}
+	// Hold the max cycle time over the last 1 second
+	if(cycleTime > timeHold) { 
+		timeHold = cycleTime;
+		timeHoldWhen = cycleNum;
+	}
+	// Hold the max cycle time since last diag reset
+	if(cycleTime > timeHoldMax) timeHoldMax = cycleTime;
+#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K)
+// This produces cycle time histogram in /proc file
+	{
+#if defined(SERVO64K) || defined(SERVO32K)
+		static const int nb = 31;
+#elif defined(SERVO16K)
+		static const int nb = 63;
+#endif
+
+		cycleHist[cycleTime<nb?cycleTime:nb]++;
+		cycleHistWhen[cycleTime<nb?cycleTime:nb] = cycleNum;
+	}
+#endif
+	// BILLION
+	adcHoldTime = BILLION * (cpuClock[CPU_TIME_CYCLE_START].tv_sec - adcTime.tv_sec) + 
+			     cpuClock[CPU_TIME_CYCLE_START].tv_nsec - adcTime.tv_nsec;
+	adcHoldTime /= 1000;
+	// Avoid calculating the max hold time for the first few seconds
+	 pLocalEpics->epicsOutput.startgpstime = startGpsTime;
+	if (cycleNum != 0 && (startGpsTime+3) < cycle_gps_time) {
+		if(adcHoldTime > adcHoldTimeMax) adcHoldTimeMax = adcHoldTime;
+		if(adcHoldTime < adcHoldTimeMin) adcHoldTimeMin = adcHoldTime;
+		adcHoldTimeAvg += adcHoldTime;
+		if (adcHoldTimeMax > adcHoldTimeEverMax)  {
+			adcHoldTimeEverMax = adcHoldTimeMax;
+			adcHoldTimeEverMaxWhen = cycle_gps_time;
+			//printf("Maximum adc hold time %d on cycle %d gps %d\n", adcHoldTimeMax, cycleNum, cycle_gps_time);
+		}
+		if (timeHoldMax > cpuTimeEverMax)  {
+			cpuTimeEverMax = timeHoldMax;
+			cpuTimeEverMaxWhen = cycle_gps_time;
+		}
+	}
+	adcTime.tv_sec = cpuClock[CPU_TIME_CYCLE_START].tv_sec;
+	adcTime.tv_nsec = cpuClock[CPU_TIME_CYCLE_START].tv_nsec;
+	// Calc the max time of one cycle of the user code
+	// For IOP, more interested in time to get thru ADC read code and send to slave apps
+	usrTime = BILLION * (cpuClock[CPU_TIME_USR_END].tv_sec - cpuClock[CPU_TIME_CYCLE_START].tv_sec) + 
+			     cpuClock[CPU_TIME_USR_END].tv_nsec - cpuClock[CPU_TIME_CYCLE_START].tv_nsec;
+	usrTime /= 1000;
+	if(usrTime > usrHoldTime) usrHoldTime = usrTime;
+
+        /// \> Update internal cycle counters
+          cycleNum += 1;
+          cycleNum %= CYCLE_PER_SECOND;
+	  clock1Min += 1;
+	  clock1Min %= CYCLE_PER_MINUTE;
+          if(subcycle == DAQ_CYCLE_CHANGE) 
+	  {
+		daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND;
+		if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle;
+	  }
+          if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/
+            {
+              /* Reset the data cycle counter */
+              subcycle = 0;
+  
+            }
+          else{
+            /* Increment the internal cycle counter */
+            subcycle ++;                                                
+          }
+
+/// \> If not exit request, then continue INFINITE LOOP  *******
+  }
+
+  printf("exiting from fe_code()\n");
+  pLocalEpics->epicsOutput.cpuMeter = 0;
+
+
+  /* System reset command received */
+  return (void *)-1;
+}