diff --git a/.gitignore b/.gitignore
index 08984e819a0f918d635fad66421c9dde84b7b287..b3bfc9c0452c69fd2cc3032fa08ddbe863bd8791 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,9 @@
 *.so.*
 *.ko
 *.o
+*.o.cmd
+*.o.d
+*.ko.cmd
 *.a
 \#*
 .\#*
diff --git a/Makefile.in b/Makefile.in
index ec0f0e606513720d6efd8094ed9e2d3b459865c9..dd5eabd64de3fbc5694157e22393f330399298cd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -4,6 +4,9 @@ SHELL = /bin/sh
 
 top_srcdir := `readlink -m @top_srcdir@`
 srcdir := `readlink -m @srcdir@`
+bld_dir:= $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
+models_dir:= $(bld_dir)/models
+bld_utils_dir:= $(bld_dir)/utils
 linux_version := '@linux_version@'
 VPATH=$(srcdir)
 
@@ -24,67 +27,99 @@ PERFORMANCEFLAGS=-DNDEBUG -g -O5
 RELEASEFLAGS=-DNDEBUG -DNPROBE -g -O5
 #DEBUGFLAGS=-DNDEBUG -O5 -unroll=16
 DEVFLAGS=@DEVFLAGS@
+NUM_BUILD_THREDS?=1
+
+define DIE
+(tail $(bld_log); cat $(err_log) && /bin/false)
+endef
 
 %: clean-%
-	@mkdir -p src/epics/util src/fe target build src/epics/fmseq config src/include
-	@ln -fs $(srcdir)/src/epics/util/lib src/epics/util > /dev/null 2>&1 || /bin/true
-	@ln -fs $(srcdir)/src/include/drv src/include > /dev/null 2>&1 || /bin/true
-	@ln -fs $(srcdir)/src/epics/simLink src/epics > /dev/null 2>&1 || /bin/true
-	@ln -fs $(srcdir)/src/epics/util/GNUmakefile src/epics/util > /dev/null 2>&1 || /bin/true
+
+	@# Set path variables so we don't need the whole path everywhere
+	$(eval model_bld_dir := $(bld_dir)/models/$@/)
+	$(eval target_dir := $(model_bld_dir)/target/)
+	$(eval model_log_dir := $(bld_dir)/models/$@/logs)
+	$(eval err_log := $(model_log_dir)/$@_error.log)
+	$(eval bld_log := $(model_log_dir)/$@.log)
+	$(eval kern_bld_dir := $(model_bld_dir)/kernel_mod/)
+	$(eval us_bld_dir := $(model_bld_dir)/userspace/)
+	$(eval epics_dir := $(model_bld_dir)/epics/)
+	$(eval epics_src_dir := $(epics_dir)/src/)
+	$(eval epics_build_dir := $(target_dir)/$@epics/)
+	$(eval bld_info_dir := $(target_dir)/build_info/)
+	$(eval target_bin_dir := $(target_dir)/bin/)
+
+
+
+	@mkdir -p $(bld_utils_dir)/epics/util $(models_dir) $(epics_dir)/fmseq $(models_dir)/$@/include $(model_log_dir)
+	@mkdir -p $(target_dir)/ $(target_bin_dir)/
+	@ln -fs $(srcdir)/src/epics/util/lib $(bld_utils_dir)/epics/util > /dev/null 2>&1 || /bin/true
+	@ln -fs $(srcdir)/src/epics/simLink $(bld_utils_dir)/epics > /dev/null 2>&1 || /bin/true
+	@ln -fs $(srcdir)/src/epics/util/Makefile.kernel $(bld_utils_dir)/epics/util > /dev/null 2>&1 || /bin/true
+	@ln -fs $(srcdir)/src/epics/util/Userspace_CMakeLists.cmake $(bld_utils_dir)/epics/util > /dev/null 2>&1
+	@cp $(srcdir)/support/symvers/ModuleIOP.symvers $(models_dir)/
+	@cp $(srcdir)/src/epics/util/checkForErrors.sh $(bld_utils_dir)
+
 	@echo Parsing the model $@...
-	@make -C src/epics/util -sf Makefile $@ > $@.log 2>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false)
+	@srcdir=$(srcdir)/src/epics/util/ make -C $(bld_utils_dir)/epics/util -sf Makefile $@ > $(bld_log) 2>$(err_log) || $(DIE)
 	@echo Done
-	@/bin/rm -rf build/$@epics-medm
-	@/bin/rm -rf build/$@epics-config
-	@/bin/mv -f build/$@epics/medm build/$@epics-medm
-	@/bin/mv -f build/$@epics/config build/$@epics-config
-	@/bin/rm -rf target/$@epics build/$@epics;
+	@/bin/rm -rf $(epics_dir)/$@epics-medm
+	@/bin/rm -rf $(epics_dir)/$@epics-config
+	@/bin/mv -f  $(epics_src_dir)/medm $(epics_dir)/$@epics-medm
+	@/bin/mv -f  $(epics_src_dir)/config $(epics_dir)/$@epics-config
+	@/bin/rm -rf $(epics_build_dir)/ $(epics_src_dir)/;
+
 	@echo Building EPICS sequencers...
-	@env RCG_SRC_DIR=$(srcdir) PERL5LIB=$(srcdir)/src/epics/util make -f config/Makefile.$@epics RCG_SRC_DIR=$(srcdir) >> $@.log 2>>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false)
+	@env RCG_SRC_DIR=$(srcdir) PERL5LIB=$(srcdir)/src/epics/util make -f $(epics_dir)/Makefile.$@epics >> $(bld_log) 2>>$(err_log) || $(DIE)
 	@echo Done
-	@($(srcdir)/src/epics/util/nameLengthChk.pl $@) >> $@.log 2>>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false)
-	@/bin/mkdir -p build/$@epics
-	@/bin/mv -f build/$@epics-medm build/$@epics/medm
-	@/bin/mv -f build/$@epics-config build/$@epics/config
+	@($(srcdir)/src/epics/util/nameLengthChk.pl $@ $(epics_src_dir)/ $(epics_build_dir)/ ) >> $(bld_log) 2>>$(err_log) || $(DIE)
+	@/bin/mkdir -p $(epics_src_dir)
+	@/bin/mv -f $(epics_dir)/$@epics-medm $(epics_src_dir)/medm
+	@/bin/mv -f $(epics_dir)/$@epics-config $(epics_src_dir)/config
+	
+
 ifndef RCG_BUILD_NO_KOBJ
 	@echo Building front-end Linux kernel module $@...
-	@make -sC src/fe/$@ clean
-# copy IOP symbol file to build area if found
-	@cp src/fe/ModuleIOP.symvers src/fe/$@ > /dev/null 2>&1 || /bin/true
-	@cat /opt/DIS/lib/modules/$(linux_version)/*.symvers > src/fe/$@/Module.symvers || /bin/true
-# build the FE model
-	@make -C src/fe/$@ >> $@.log 2>>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false)
-# save IOP symbol for other models, if we don't already have it 
-	@if [ ! -f src/fe/ModuleIOP.symvers ] ; then if grep IOP src/fe/$@/Module.symvers > /dev/null ; then grep IOP src/fe/$@/Module.symvers > src/fe/ModuleIOP.symvers; fi; fi
-	@$(srcdir)/src/epics/util/checkUndefined.pl $@_error.log >> $@.log 2>>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false)
+	@make -j $(NUM_BUILD_THREDS) -C $(kern_bld_dir) >> $(bld_log) 2>>$(err_log) || $(DIE)
+	@$(srcdir)/src/epics/util/checkUndefined.pl $(err_log) >> $(bld_log) 2>>$(err_log) || $(DIE)
+	@mv $(kern_bld_dir)/$@.ko $(target_bin_dir)
 	@echo Done
 endif
+
 ifdef RCG_BUILD_USP
 	@echo Building front-end user space object $@...
-	@/bin/rm -rf src/fe/$@_usp/*.o ;
-	@make -C src/fe/$@_usp >> $@.log 2>>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false)
+	@if [ ! -L $(us_bld_dir)/src ]; then ln -s $(srcdir)/src/ $(us_bld_dir)/src; fi
+	@mkdir -p $(us_bld_dir)/build
+	@cmake -B$(us_bld_dir)/build/ -S$(us_bld_dir) -DMODEL_NAME=$@ >> $(bld_log) 2>>$(err_log) || $(DIE)
+	@make -j $(NUM_BUILD_THREDS) -C $(us_bld_dir)/build >> $(bld_log) 2>>$(err_log) || $(DIE)
+	@mv $(us_bld_dir)/build/$@ $(target_bin_dir)
 	@echo Done
 endif
-	@/bin/mkdir -p target/$@epics/src
-	@echo $(srcdir) > target/$@epics/src/rcg_location.txt
-	@echo Build date `date` > target/$@epics/src/build.txt
-	@echo Compiled on `hostname` >> target/$@epics/src/build.txt
-	@echo RCG_LIB_PATH=${RCG_LIB_PATH} >> target/$@epics/src/build.txt
-	@tar Ccf $(srcdir) - --exclude rcg.tar.gz --exclude build --exclude target . | gzip > target/$@epics/src/rcg.tar.gz
-	@cp src/epics/util/sources.$@ target/$@epics/src/src_locations.txt
-	@cp $@.log target/$@epics/src
-	@cp $@_error.log target/$@epics/src
-	@sort src/epics/util/sources.$@ | uniq |  tar czTf - target/$@epics/src/sources.tar.gz > /dev/null 2>&1
+
+	@#Save build config and source files for traceability
+	@/bin/mkdir -p $(bld_info_dir)
+	@echo $(srcdir) > $(bld_info_dir)/rcg_location.txt
+	@(cd $(srcdir) && git rev-parse HEAD) > $(bld_info_dir)/rcg_git_hash.txt
+	@(cd $(srcdir) && git --no-pager diff) > $(bld_info_dir)/rcg_git_diff.txt
+	@echo Build date `date` > $(bld_info_dir)/build.txt
+	@echo Compiled on `hostname` >> $(bld_info_dir)/build.txt
+	@echo RCG_LIB_PATH=${RCG_LIB_PATH} >> $(bld_info_dir)/build.txt
+	@tar Ccf $(srcdir) - --exclude rcg.tar.gz --exclude $(epics_build_dir)/   . | gzip > $(bld_info_dir)/rcg.tar.gz
+	@cp $(epics_dir)/sources.$@ $(bld_info_dir)/src_locations.txt
+	@cp $(bld_log) $(bld_info_dir)
+	@cp $(err_log) $(bld_info_dir)
+	@sort $(epics_dir)/sources.$@ | uniq |  tar czTf - $(bld_info_dir)/sources.tar.gz > /dev/null 2>&1
+
 	@echo RCG source code directory:
 	@echo $(srcdir)
 	@echo The following files were used for this build:
-	@sort src/epics/util/sources.$@ | uniq
+	@sort $(epics_dir)/sources.$@ | uniq
 	@echo
 	@echo  Successfully compiled $@
 	@echo '***********************************************'
-	@echo  Compile Warnings, found in $@_warnings.log:
+	@echo  Compile Warnings, found in $(model_log_dir)/$@_warnings.log:
 	@echo '***********************************************'
-	@cat   $@_warnings.log 
+	@cat   $(model_log_dir)/$@_warnings.log 
 	@echo '***********************************************'
 
 
@@ -100,8 +135,8 @@ reclean:
 
 clean-%:
 	@system=$(subst clean-,,$@); echo Cleaning $${system}...; \
-        /bin/rm -rf target/$${system}epics build/$${system}epics; \
-        (make -siC src/fe/$${system}/Makefile clean 2>/dev/null); echo Done
+        /bin/rm -rf  models/$${system}/target/; \
+        (make -siC $(models_dir)/$${system}/Makefile clean 2>/dev/null); echo Done;
 
 install-adclist-%:
 	@system=$(subst install-adclist-,,$@); $(srcdir)/install-adclist $${system} $(srcdir)
@@ -112,30 +147,6 @@ install-%:
 uninstall-%:
 	@system=$(subst uninstall-,,$@); $(srcdir)/uninstall $${system} $(srcdir)
 
-#MDL_MODELS = x1cdst1 x1isiham x1isiitmx x1iss x1lsc x1omc1 x1psl x1susetmx x1susetmy x1susitmx x1susitmy x1susquad1 x1susquad2 x1susquad3 x1susquad4 x1x12 x1x13 x1x14 x1x15 x1x16 x1x20 x1x21 x1x22 x1x23
-
-#MDL_MODELS = $(wildcard src/epics/simLink/l1*.mdl)
-#MDL_MODELS = $(shell cd src/epics/simLink; ls m1*.mdl | sed 's/.mdl//')
-#MDL_MODELS=\
-#l1ioplsc0 l1lsc l1omc1 l1omc2 l1lsctest\
-#l1iopasc0 l1asctest l1ascwfs\
-#l1iopoaf0 l1pemlvea\
-#l1iopseib1 l1isiitmy l1seiitmy\
-#l1iopseib2 l1isibs l1seibs\
-#l1iopseib3 l1isiitmx l1seiitmx\
-#l1iopseih16 l1seiham1 l1seiham6\
-#l1iopseih23 l1isiham3 l1hpiham3 \
-#l1iopseih45 l1seiham4 l1seiham5\
-#l1iopsusbsc123 l1susbs l1susitmy l1susitmx\
-#l1iopsush2a l1susquad l1susprm3\
-#l1iopsush2b\
-#l1iopsush34 l1susmc2 l1sussr2 l1suspr2\
-#l1iopsusauxh34 l1susauxh34\
-#l1iopsush56 l1sussr3 l1sussrm\
-#l1ioppsl0 l1psldbb l1pslfss l1pslpmc l1psliss\
-#l1ioppemex l1pemex l1susetmx l1isietmx\
-#l1ioppemey l1pemey l1susetmy l1isietmy
-#
 
 MDL_MODELS = $(shell if [ -e /etc/rt.sh ]; then /etc/rt.sh; fi)
 
diff --git a/NEWS b/NEWS
index 0bf6fa2bb5fcc8f1970feff6fbe52b6f2aa00b2a..decd9729d573793ee77b5666fe2a570d1c3ba9d0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,15 @@
 ==================================================================================================
+Changes for 4.2.8
+==================================================================================================
+- fixed issue where two testpoints couldn't be opened at the same time from the same model
+- fixed RCG bug where deep part links could cause infinite recursion of references
+- delays inserted in shutdown to help prevent zombie luts in the dolphin drivers
+- epics process fails gracefully and with better messages when it can't open a file
+- BURT_RESTORE no longer needed in safe.snap file to start model
+- DACKILL variables in default safe.snap set to more sensible values
+- EDCU now supplies DATA_RATE_KB_PER_S epics variable
+- RCG install step now creats chans/tmp.  Build now creates chans/ipc/<ifo>.ipc
+==================================================================================================
 Changes for 4.2.7
 ==================================================================================================
 - Fixed more calculation out of order bugs.
diff --git a/config/Makefile.linux b/config/Makefile.linux
index f6e7bbd28dd386ef5cdeb6b2ab97ba1fb4afa947..63d30404f5671c18552f623aefa504ec7d0f3b2a 100644
--- a/config/Makefile.linux
+++ b/config/Makefile.linux
@@ -1,14 +1,17 @@
 # Linux Epics IOC system build rules
 
+MODEL_NAME := $(subst epics,,$(TARGET))
 
 EPICS_VERSION := $(shell pkg-config --modversion epics-base)
 EPICS_BIN_PATH := $(shell pkg-config --variable=bindir epics-base)
+FMSEQ_OUTPUT_DIR :=$(MODEL_EPICS_DIR)/fmseq
+
 
 # Sequencer synchronization; to fix broken seq package
 SRC += $(RCG_SRC_DIR)/src/drv/sync.c
 
 # Do not delete these intermediate files
-.SECONDARY: build/$(TARGET)/*.i
+.SECONDARY: $(MODEL_EPICS_SRC_DIR)/*.i
 
 # Preprocessor is used on .st file to get .i which is later fed to SNC
 PREPROCESS = /usr/bin/gcc -x c -E -P 
@@ -17,7 +20,7 @@ PREPROCESS = /usr/bin/gcc -x c -E -P
 CFLAGS += $(EXTRA_CFLAGS)
 CFLAGS += $(shell pkg-config --cflags epics-base)
 CFLAGS += -I/usr/lib/rmnet -I/usr/lib/rfm2g
-CFLAGS += -Isrc/include
+CFLAGS += -I$(MODEL_EPICS_DIR)/../include
 CFLAGS += -I$(RCG_SRC_DIR)/src/include -I$(RCG_SRC_DIR)/src/include/drv
 ifeq (,$(findstring tcsepics, $(TARGET)))
 CFLAGS += -DRFM_EPICS -DNO_FM10GEN_C_CODE
@@ -70,102 +73,96 @@ LIBFLAGS += -lpthread -lreadline -lcurses -lrt
 # User Makefiles's $(SRC) variable is split here in sequencer source
 # and all the rest, which should be C files
 SEQ_SRCS = $(filter %.st, $(SRC))
-CSRCS = $(filter-out %.st, $(SRC))
+CSRCS = $(filter-out %.cc, $(filter-out %.st, $(SRC)))
 # Required Epics files
-CCSRCS += build/$(TARGET)/registerRecordDeviceDriver.cc
+CCSRCS += $(filter %.cc, $(SRC))
+CCSRCS += $(MODEL_EPICS_SRC_DIR)/registerRecordDeviceDriver.cc
 
 # Each .st file gets preprocessed twice to make one C and one C++
 # file. C++ file has different name. Both files are exactly the same
 # in content
-SEQ_ISRC = $(addprefix build/$(TARGET)/, $(notdir $(SEQ_SRCS:%st=%i)))
-#SEQ_CCSRC = $(addprefix build/$(TARGET)/, $(notdir $(SEQ_SRCS:%.st=%_foo.cc)))
-SEQ_CCSRC += $(addprefix build/$(TARGET)/, $(notdir $(SEQ_SRCS:%st=%c)))
-SEQ_OBJ = $(addprefix build/$(TARGET)/, $(notdir $(SEQ_SRCS:%st=%o)))
-#SEQ_OBJ += $(addprefix build/$(TARGET)/, $(notdir $(SEQ_SRCS:%.st=%_foo.o)))
-SEQ_OBJ += $(addprefix build/$(TARGET)/, $(notdir $(CSRCS:%.c=%.o)))
-SEQ_OBJ += $(addprefix build/$(TARGET)/, $(notdir $(CCSRCS:%.cc=%.o)))
+SEQ_ISRC = $(addprefix $(MODEL_EPICS_SRC_DIR)/, $(notdir $(SEQ_SRCS:%st=%i)))
+#SEQ_CCSRC = $(addprefix $(MODEL_EPICS_SRC_DIR)/, $(notdir $(SEQ_SRCS:%.st=%_foo.cc)))
+SEQ_CCSRC += $(addprefix $(MODEL_EPICS_SRC_DIR)/, $(notdir $(SEQ_SRCS:%st=%c)))
+SEQ_OBJ = $(addprefix $(MODEL_EPICS_SRC_DIR)/, $(notdir $(SEQ_SRCS:%st=%o)))
+#SEQ_OBJ += $(addprefix $(MODEL_EPICS_SRC_DIR)/, $(notdir $(SEQ_SRCS:%.st=%_foo.o)))
+SEQ_OBJ += $(addprefix $(MODEL_EPICS_SRC_DIR)/, $(notdir $(CSRCS:%.c=%.o)))
+SEQ_OBJ += $(addprefix $(MODEL_EPICS_SRC_DIR)/, $(notdir $(CCSRCS:%.cc=%.o)))
 
 # Standard Epics IOC database definition file
-DBD += $(RCG_SRC_DIR)/src/epics/dbd/a.dbd build/$(TARGET)/*.dbd
+DBD += $(RCG_SRC_DIR)/src/epics/dbd/a.dbd $(MODEL_EPICS_SRC_DIR)/*.dbd
 
 # Main target to make an Epics IOC server
-all: target build/$(TARGET)/$(TARGET) install
+all: target $(MODEL_EPICS_BUILD_DIR)/$(TARGET) install
 
-# Install built epics IOC into target/$(TARGET)
+# Install built epics IOC into build/$(TARGET)
 install: $(DB)
-	mkdir -p target/$(TARGET)/db
-	cp build/$(TARGET)/$(TARGET) target/$(TARGET)
-	/bin/rm -f target/$(TARGET)/db/*/autoBurt.req
+	mkdir -p $(MODEL_EPICS_BUILD_DIR)/db
+	/bin/rm -f $(MODEL_EPICS_BUILD_DIR)/db/*/autoBurt.req
 	for ifo in $(IFO) ; do \
 	  system=`echo $(subst epics,,$(TARGET)) | tr a-z A-Z | cut -c1-3`; \
 	  model=`echo $(subst epics,,$(TARGET))`; \
 	  ucmodel=`echo $(subst epics,,$(TARGET)) | tr a-z A-Z `; \
 	  ifo0=`echo $$ifo | sed 's/[0-9]/0/g'`; \
-	  mkdir -p target/$(TARGET)/db/$$ifo; \
-	  echo "#!/bin/sh" > target/$(TARGET)/startup$$ifo; \
-	  echo "if fuser -s ioc$$ifo.log; then" >> target/$(TARGET)/startup$$ifo; \
-	  echo "echo Another copy of Epics process running already\!" >> target/$(TARGET)/startup$$ifo; \
-	  echo "exit 1" >> target/$(TARGET)/startup$$ifo; \
-	  echo "fi" >> target/$(TARGET)/startup$$ifo; \
-	  echo "mkdir -p /opt/rtcds/$(SITE)/${ifo}/log/$$model" >> target/$(TARGET)/startup$$ifo; \
-	  echo ./$(TARGET) $(TARGET)$$ifo.cmd \> /opt/rtcds/$(SITE)/${ifo}/log/$$model/ioc$$ifo.log 2\>\&1 \& >> target/$(TARGET)/startup$$ifo ; \
-	  echo echo $(TARGET) $$ifo IOC Server started >> target/$(TARGET)/startup$$ifo ; \
-	  chmod +x target/$(TARGET)/startup$$ifo ; \
-	  /bin/rm -f target/$(TARGET)/$(TARGET)$$ifo.cmd ; \
-	  echo "dbLoadDatabase \"base.dbd\"" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-	  echo 'registerRecordDeviceDriver(pdbbase)' >> target/$(TARGET)/$(TARGET)$$ifo.cmd ; \
+	  mkdir -p $(MODEL_EPICS_BUILD_DIR)/db/$$ifo; \
+	  /bin/rm -f $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd ; \
+	  echo "dbLoadDatabase \"base.dbd\"" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+	  echo 'registerRecordDeviceDriver(pdbbase)' >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd ; \
 	  for i in $(DB) ; do \
-		cat $$i | sed s/%IFO%/$$ifo/g\;s/%IFO0%/$$ifo0/g\;s/%SYS%/$$system/g > target/$(TARGET)/db/$$ifo/`basename $$i`; \
-		grep record  target/$(TARGET)/db/$$ifo/`basename $$i` | egrep 'DACKILL|record\(ao|record\(stringout' | egrep -v 'DACKILL_PANIC|_SDF_' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "RO %s\n", $$0 }' >> target/$(TARGET)/db/$$ifo/autoBurt.req; \
-		grep record  target/$(TARGET)/db/$$ifo/`basename $$i` | egrep 'record\(stringin' | egrep -v 'SDF_NAME | _SDF_' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "%s\n", $$0 }' >> target/$(TARGET)/db/$$ifo/autoBurt.req; \
-		grep record  target/$(TARGET)/db/$$ifo/`basename $$i` | egrep 'record\(ao' | egrep -v 'record\(mbbi' | egrep -v 'SWSTAT|DACKILL|_SDF_' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "%s.HSV\n%s.LSV\n%s.HIGH\n%s.LOW\n", $$0, $$0, $$0, $$0 }' >> target/$(TARGET)/db/$$ifo/autoBurt.req; \
-                grep record  target/$(TARGET)/db/$$ifo/`basename $$i` | egrep 'SWSTAT|DACKILL' | egrep -v 'DACKILL_PANIC' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "RO %s.HSV\nRO %s.LSV\nRO %s.LOW\n", $$0, $$0, $$0 }' >> target/$(TARGET)/db/$$ifo/autoBurt.req; \
+		cat $$i | sed s/%IFO%/$$ifo/g\;s/%IFO0%/$$ifo0/g\;s/%SYS%/$$system/g > $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i`; \
+		grep record  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | egrep 'DACKILL|record\(ao|record\(stringout' | egrep -v 'DACKILL_PANIC|DACKILL_BPTIME|_SDF_' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "RO %s\n", $$0 }' >> $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/autoBurt.req; \
+		grep record  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | egrep 'record\(stringin' | egrep -v 'SDF_NAME | _SDF_' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "%s\n", $$0 }' >> $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/autoBurt.req; \
+		grep record  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | egrep 'record\(ao' | egrep -v 'record\(mbbi' | egrep -v 'SWSTAT|DACKILL|_SDF_' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "%s.HSV\n%s.LSV\n%s.HIGH\n%s.LOW\n", $$0, $$0, $$0, $$0 }' >> $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/autoBurt.req; \
+                grep record  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | egrep 'SWSTAT|DACKILL' | egrep -v 'DACKILL_PANIC' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "RO %s.HSV\nRO %s.LSV\nRO %s.LOW\n", $$0, $$0, $$0 }' >> $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/autoBurt.req; \
+		\
+		grep record  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | egrep 'record\(bo|record\(bi' | egrep -v '_SDF_' | sed 's/.*"\(.*\)\".*/\1/g' >> $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/autoBurt.req; \
+		grep record  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | egrep 'record\(bo|record\(bi' | egrep -v '_SDF_' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "%s.OSV\n%s.ZSV\n", $$0, $$0 }' >> $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/autoBurt.req; \
 		\
-		grep record  target/$(TARGET)/db/$$ifo/`basename $$i` | egrep 'record\(bo|record\(bi' | egrep -v '_SDF_' | sed 's/.*"\(.*\)\".*/\1/g' >> target/$(TARGET)/db/$$ifo/autoBurt.req; \
-		grep record  target/$(TARGET)/db/$$ifo/`basename $$i` | egrep 'record\(bo|record\(bi' | egrep -v '_SDF_' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "%s.OSV\n%s.ZSV\n", $$0, $$0 }' >> target/$(TARGET)/db/$$ifo/autoBurt.req; \
+		grep record  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | egrep 'DACKILL_BPTIME' |  sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "%s\n", $$0 }' >> $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/autoBurt.req; \
 		\
-		grep record  target/$(TARGET)/db/$$ifo/`basename $$i` | egrep -v 'DACKILL|SDF_RELOAD|_SDF_|record\(ao|record\(string|record\(bi|record\(bo'| sed 's/.*"\(.*\)\".*/\1/g' >> target/$(TARGET)/db/$$ifo/autoBurt.req; \
-		grep record  target/$(TARGET)/db/$$ifo/`basename $$i` | egrep -v 'SWSTAT|DACKILL|_SDF_|record\(ao|record\(string|record\(bi|record\(bo|record\(mbbi' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "%s.HSV\n%s.LSV\n%s.HIGH\n%s.LOW\n", $$0 , $$0, $$0, $$0 }' >> target/$(TARGET)/db/$$ifo/autoBurt.req; \
+		grep record  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | egrep -v 'DACKILL|SDF_RELOAD|_SDF_|record\(ao|record\(string|record\(bi|record\(bo'| sed 's/.*"\(.*\)\".*/\1/g' >> $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/autoBurt.req; \
+		grep record  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | egrep -v 'SWSTAT|DACKILL|_SDF_|record\(ao|record\(string|record\(bi|record\(bo|record\(mbbi' | sed 's/.*"\(.*\)\".*/\1/g' | awk '{ printf "%s.HSV\n%s.LSV\n%s.HIGH\n%s.LOW\n", $$0 , $$0, $$0, $$0 }' >> $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/autoBurt.req; \
 		\
-		echo "dbLoadRecords \"db/$${ifo}/`basename $$i`\"" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet DAQ_FILE /opt/rtcds/$(SITE)/${ifo}/chans/daq/$$ucmodel.ini" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet DAQ_DIR /opt/rtcds/$(SITE)/${ifo}/chans/daq/" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet FOTON_FILE /opt/rtcds/$(SITE)/${ifo}/chans/$$ucmodel.txt" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet FOTON_DIFF_FILE /opt/rtcds/$(SITE)/${ifo}/chans/tmp/$$ucmodel.diff" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet COEFF_FILE /opt/rtcds/$(SITE)/${ifo}/chans/tmp/$$ucmodel.txt" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet LOG_DIR /opt/rtcds/$(SITE)/${ifo}/log/$$model" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet SDF_DIR /opt/rtcds/$(SITE)/${ifo}/target/$$model/$(TARGET)/burt/" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-                echo "epicsEnvSet SDF_FILE safe" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-                echo "epicsEnvSet SDF_MODEL $$model" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet MODEL_SITE $(SITE)" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet MODEL_IFO ${ifo}" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo "epicsEnvSet SYNC_SRC $(SYNC_SRC)" >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		echo -n 'epicsEnvSet PREFIX '>> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
-		grep _GRD_RB_STAT0  target/$(TARGET)/db/$$ifo/`basename $$i` | head -1 | sed 's/[^"]*"\([^"]*\)_GRD_RB_STAT0.*/\1/g' >>  target/$(TARGET)/$(TARGET)$$ifo.cmd; \
+		echo "dbLoadRecords \"db/$${ifo}/`basename $$i`\"" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet DAQ_FILE /opt/rtcds/$(SITE)/${ifo}/chans/daq/$$ucmodel.ini" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet DAQ_DIR /opt/rtcds/$(SITE)/${ifo}/chans/daq/" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet FOTON_FILE /opt/rtcds/$(SITE)/${ifo}/chans/$$ucmodel.txt" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet FOTON_DIFF_FILE /opt/rtcds/$(SITE)/${ifo}/chans/tmp/$$ucmodel.diff" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet COEFF_FILE /opt/rtcds/$(SITE)/${ifo}/chans/tmp/$$ucmodel.txt" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet LOG_DIR /opt/rtcds/$(SITE)/${ifo}/log/$$model" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet SDF_DIR /opt/rtcds/$(SITE)/${ifo}/target/$$model/$(TARGET)/burt/" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+                echo "epicsEnvSet SDF_FILE safe" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+                echo "epicsEnvSet SDF_MODEL $$model" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet MODEL_SITE $(SITE)" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet MODEL_IFO ${ifo}" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet SYNC_SRC $(SYNC_SRC)" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo "epicsEnvSet SDF_FILE_LOADED 0" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		echo -n 'epicsEnvSet PREFIX '>> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
+		grep _GRD_RB_STAT0  $(MODEL_EPICS_BUILD_DIR)/db/$$ifo/`basename $$i` | head -1 | sed 's/[^"]*"\([^"]*\)_GRD_RB_STAT0.*/\1/g' >>  $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
 	  done ; \
 	done
 	for ifo in $(IFO) ; do \
-	  echo "iocInit" >> target/$(TARGET)/$(TARGET)$$ifo.cmd ; \
+	  echo "iocInit" >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd ; \
 	  for i in $(SEQ) ; do \
-		echo "seq &$$i" | sed s/%IFO%/$$ifo/g\;s/%SITE%/`if test $$ifo = L1 ; then echo llo ; else echo lho ; fi`/g >> target/$(TARGET)/$(TARGET)$$ifo.cmd; \
+		echo "seq &$$i" | sed s/%IFO%/$$ifo/g\;s/%SITE%/`if test $$ifo = L1 ; then echo llo ; else echo lho ; fi`/g >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)$$ifo.cmd; \
 	  done ; \
 	done
 	for i in $(SEQH1) ; do \
-		echo "seq &$$i" | sed s/%IFO%/H1/g\;s/%SITE%/lho/g >> target/$(TARGET)/$(TARGET)H1.cmd; \
+		echo "seq &$$i" | sed s/%IFO%/H1/g\;s/%SITE%/lho/g >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)H1.cmd; \
 	done
 	for i in $(SEQH2) ; do \
-		echo "seq &$$i" | sed s/%IFO%/H2/g\;s/%SITE%/lho/g >> target/$(TARGET)/$(TARGET)H2.cmd; \
+		echo "seq &$$i" | sed s/%IFO%/H2/g\;s/%SITE%/lho/g >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)H2.cmd; \
 	done
 	for i in $(SEQL1) ; do \
-		echo "seq &$$i" | sed s/%IFO%/L1/g\;s/%SITE%/llo/g >> target/$(TARGET)/$(TARGET)L1.cmd; \
+		echo "seq &$$i" | sed s/%IFO%/L1/g\;s/%SITE%/llo/g >> $(MODEL_EPICS_BUILD_DIR)/$(TARGET)L1.cmd; \
 	done
-	echo 'This is generated directory. Please make changes in CVS and reinstall from scratch.' > target/$(TARGET)/README.making_changes
-	echo 'Changes made to files in this directory will be lost.' >> target/$(TARGET)/README.making_changes
-	echo >> target/$(TARGET)/README.making_changes
-	echo 'Built on date' `date` >> target/$(TARGET)/README.making_changes
+	echo 'This is generated directory. Please make changes in CVS and reinstall from scratch.' > $(MODEL_EPICS_BUILD_DIR)/README.making_changes
+	echo 'Changes made to files in this directory will be lost.' >> $(MODEL_EPICS_BUILD_DIR)/README.making_changes
+	echo >> $(MODEL_EPICS_BUILD_DIR)/README.making_changes
+	echo 'Built on date' `date` >> $(MODEL_EPICS_BUILD_DIR)/README.making_changes
 
 # Epics IOC server link target
-build/$(TARGET)/$(TARGET): $(SEQ_OBJ)
+$(MODEL_EPICS_BUILD_DIR)/$(TARGET): $(SEQ_OBJ)
 	$(CXX) -o $@ $? $(LIBFLAGS)
 
 # Object files depend on sources
@@ -176,82 +173,84 @@ $(SEQ_CCSRC): $(SEQ_ISRC)
 
 # Make installation target directory
 target:
-	@mkdir -p build/$(TARGET)
+	@mkdir -p $(MODEL_EPICS_SRC_DIR)
+	@mkdir -p $(MODEL_EPICS_BUILD_DIR)
 
 # Preprocess a sequencer file
-build/$(TARGET)/%.i: src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%.i: src/epics/seq/%.st
 	$(PREPROCESS) $(CFLAGS) $< > $@
 
-build/$(TARGET)/%.i: src/epics/seq/lsc/%.st
+$(MODEL_EPICS_SRC_DIR)/%.i: src/epics/seq/lsc/%.st
 	$(PREPROCESS) $(CFLAGS) $< > $@
 
-build/$(TARGET)/%.i: src/epics/seq/sus/%.st
+$(MODEL_EPICS_SRC_DIR)/%.i: src/epics/seq/sus/%.st
 	$(PREPROCESS) $(CFLAGS) $< > $@
 
-build/$(TARGET)/%.i: src/epics/seq/quad/%.st
+$(MODEL_EPICS_SRC_DIR)/%.i: src/epics/seq/quad/%.st
 	$(PREPROCESS) $(CFLAGS) $< > $@
 
 # Preprocess generated sequencer file
 # Preprocess generated sequencer file
-.PRECIOUS: build/$(TARGET)/%.st
-build/$(TARGET)/%.i: build/$(TARGET)/%.st
+.PRECIOUS: $(MODEL_EPICS_SRC_DIR)/%.st
+$(MODEL_EPICS_SRC_DIR)/%.i: $(MODEL_EPICS_SRC_DIR)/%.st
 	$(PREPROCESS) $(CFLAGS) $< > $@
 
 # Generate sequencer file using fmseq.pl
-build/$(TARGET)/%.st: src/epics/fmseq/% $(FMSEQFILES)
-	(cd src/epics/fmseq; \
+# Warning the mvs below are not commented out, so be careful
+$(MODEL_EPICS_SRC_DIR)/%.st: $(FMSEQ_OUTPUT_DIR)/% $(FMSEQFILES)
+	(cd $(FMSEQ_OUTPUT_DIR); \
 	 cat $(notdir $<) | cpp $(CFLAGS) -  | grep -v ^# | $(if $(FMSEQ), $(FMSEQ), $(RCG_SRC_DIR)/src/epics/util/fmseq.pl) $(notdir $<) &&\
 	 mv $(notdir $<)_proc.h ../../include/ &&\
-	 mv $(notdir $<).* ../../../build/$(TARGET))
+	 mv $(notdir $<).* ../../../../$(MODEL_EPICS_SRC_DIR))
 
 
 # Replicate sequencer source, because I am too lazy to write re-entrant code
 # Following block of rules used to replicate fmseq.pl generated sequencers
-build/$(TARGET)/%1.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%1.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\11/g > $@
-build/$(TARGET)/%2.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%2.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\12/g > $@
-build/$(TARGET)/%3.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%3.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\13/g > $@
-build/$(TARGET)/%4.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%4.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\14/g > $@
-build/$(TARGET)/%5.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%5.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\15/g > $@
-build/$(TARGET)/%6.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%6.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\16/g > $@
-build/$(TARGET)/%7.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%7.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\17/g > $@
-build/$(TARGET)/%8.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%8.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\18/g > $@
-build/$(TARGET)/%9.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%9.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\19/g > $@
-build/$(TARGET)/%10.st: build/$(TARGET)/%.st
+$(MODEL_EPICS_SRC_DIR)/%10.st: $(MODEL_EPICS_SRC_DIR)/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\110/g > $@
 
 # Replicate sequncers
-build/$(TARGET)/%1.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%1.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\11/g > $@
-build/$(TARGET)/%2.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%2.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\12/g > $@
-build/$(TARGET)/%3.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%3.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\13/g > $@
-build/$(TARGET)/%4.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%4.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\14/g > $@
-build/$(TARGET)/%5.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%5.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\15/g > $@
-build/$(TARGET)/%6.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%6.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\16/g > $@
-build/$(TARGET)/%7.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%7.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\17/g > $@
-build/$(TARGET)/%8.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%8.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\18/g > $@
-build/$(TARGET)/%9.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%9.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\19/g > $@
-build/$(TARGET)/%10.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
+$(MODEL_EPICS_SRC_DIR)/%10.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	cat $< | sed s/program\\w\*\\\(\.\*\\\)/program\ \\110/g > $@
 
 # Build C++ version of sequencer code
-#build/$(TARGET)/%_foo.cc: build/$(TARGET)/%.i
+#$(MODEL_EPICS_SRC_DIR)/%_foo.cc: $(MODEL_EPICS_SRC_DIR)/%.i
 #	$(SNC) $< -o $@
 # Build C version of sequencer code
 %.c: %.i
@@ -259,26 +258,26 @@ build/$(TARGET)/%10.st: $(RCG_SRC_DIR)/src/epics/seq/%.st
 	echo 'registrar('`basename $(@:%.c=%)`'Registrar)' > $(@:%c=%dbd) 
 
 # Compile sequencer-related C code
-build/$(TARGET)/%o: $(RCG_SRC_DIR)/src/epics/seq/%c
+$(MODEL_EPICS_SRC_DIR)/%o: $(RCG_SRC_DIR)/src/epics/seq/%c
 	$(CC) -c $(CFLAGS) $< -o $@
 
 # Compile driver C code
-build/$(TARGET)/%o: $(RCG_SRC_DIR)/src/drv/%c
+$(MODEL_EPICS_SRC_DIR)/%o: $(RCG_SRC_DIR)/src/drv/%c
 	$(CC) -c $(CFLAGS) $< -o $@
 
 # Compile sequencer-related C++ code
-build/$(TARGET)/%o: $(RCG_SRC_DIR)/src/epics/seq/%cc
+$(MODEL_EPICS_SRC_DIR)/%o: $(RCG_SRC_DIR)/src/epics/seq/%cc
 	$(CXX) -c $(CFLAGS) $< -o $@
 
 # Compile generate C++ code
-#build/$(TARGET)/%_foo.o: build/$(TARGET)/%_foo.cc
+#$(MODEL_EPICS_SRC_DIR)/%_foo.o: $(MODEL_EPICS_SRC_DIR)/%_foo.cc
 #	$(CXX) -c $(CFLAGS) $< -o $@
 
 # Generate records and sequencers generation code
-build/$(TARGET)/registerRecordDeviceDriver.cc: 
-	cat $(DBD) > build/$(TARGET)/full.dbd
-	$(REGGEN) build/$(TARGET)/full.dbd  registerRecordDeviceDriver > $@
-	/bin/rm -f build/$(TARGET)/full.dbd
+$(MODEL_EPICS_SRC_DIR)/registerRecordDeviceDriver.cc: 
+	cat $(DBD) > $(MODEL_EPICS_SRC_DIR)/full.dbd
+	$(REGGEN) $(MODEL_EPICS_SRC_DIR)/full.dbd  registerRecordDeviceDriver > $@
+	/bin/rm -f $(MODEL_EPICS_SRC_DIR)/full.dbd
 
 
 # Targets not files
diff --git a/configure b/configure
index 1024404c5d134f9d1a26be3b3cc2e1bd79fa9d60..f2268eb08315d9190a7e1426047fa80f72903592 100755
--- a/configure
+++ b/configure
@@ -2835,7 +2835,7 @@ if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
 fi
 
-ac_config_files="$ac_config_files src/epics/util/Makefile"
+ac_config_files="$ac_config_files utils/epics/util/Makefile:src/epics/util/Makefile.in"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -3543,7 +3543,7 @@ for ac_config_target in $ac_config_targets
 do
   case $ac_config_target in
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
-    "src/epics/util/Makefile") CONFIG_FILES="$CONFIG_FILES src/epics/util/Makefile" ;;
+    "utils/epics/util/Makefile") CONFIG_FILES="$CONFIG_FILES utils/epics/util/Makefile:src/epics/util/Makefile.in" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
@@ -4701,7 +4701,7 @@ for ac_config_target in $ac_config_targets
 do
   case $ac_config_target in
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
-    "src/epics/util/Makefile") CONFIG_FILES="$CONFIG_FILES src/epics/util/Makefile" ;;
+    "utils/epics/util/Makefile") CONFIG_FILES="$CONFIG_FILES utils/epics/util/Makefile:src/epics/util/Makefile.in" ;;
     "doc/doxygen.cfg") CONFIG_FILES="$CONFIG_FILES doc/doxygen.cfg" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -5860,7 +5860,7 @@ for ac_config_target in $ac_config_targets
 do
   case $ac_config_target in
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
-    "src/epics/util/Makefile") CONFIG_FILES="$CONFIG_FILES src/epics/util/Makefile" ;;
+    "utils/epics/util/Makefile") CONFIG_FILES="$CONFIG_FILES utils/epics/util/Makefile:src/epics/util/Makefile.in" ;;
     "doc/doxygen.cfg") CONFIG_FILES="$CONFIG_FILES doc/doxygen.cfg" ;;
     "doc/doxScript") CONFIG_FILES="$CONFIG_FILES doc/doxScript" ;;
 
diff --git a/configure.in b/configure.in
index dca3d6c44dc81c87fb8dcf89d6a397fd4ae01228..61201f361959864b3d2d9178ed234e8c0f530011 100644
--- a/configure.in
+++ b/configure.in
@@ -8,6 +8,6 @@ dnl Check for configuration options
 dnl ==========================
 
 AC_OUTPUT( Makefile )
-AC_OUTPUT( src/epics/util/Makefile )
+AC_OUTPUT( utils/epics/util/Makefile:src/epics/util/Makefile.in )
 AC_OUTPUT( doc/doxygen.cfg )
 AC_OUTPUT( doc/doxScript )
diff --git a/doc/NoiseUse.dox b/doc/NoiseUse.dox
index cc214f65255a4d5e18894793efd8c2783807fdbc..78dafdb69e135607fc8ce1f71165da608f8df48d 100644
--- a/doc/NoiseUse.dox
+++ b/doc/NoiseUse.dox
@@ -15,8 +15,9 @@ This block utilizes the pseudo-random number generator from page 342
 (section 7.1) of the third edition of Numerical recipies.  It has been 
 written as an inline function call.
 
-This block utilizes the rdtscl c function once to get the system time to
- set the initial random seed used by the generator for the entire model.
+This block utilizes the rdtsc_ordered() function (kernel space) and 
+clock_gettime() (userspace) once to get the system time to set the 
+initial random seed used by the generator for the entire model.
 
 Each instance of this block then calls the same inline function to get a
 random number with equal probability between 0 and 1 on each cycle.
diff --git a/install b/install
index 4f4853e6d0a931f82c7ebdacc62eae6983533e74..a3b0af97b2defbcd18ecdeca7248ab556598088e 100755
--- a/install
+++ b/install
@@ -10,7 +10,16 @@ else
     srcdir=$2
 fi
 
-if ! test -e target/${system}epics/${system}epics; then
+MODEL_BUILD_DIR=models/${system}
+MODEL_TARGET_DIR=${MODEL_BUILD_DIR}/target/
+TARGET_BIN_DIR=${MODEL_TARGET_DIR}/bin/
+MODEL_INC_DIR=${MODEL_BUILD_DIR}/include
+EPICS_DIR=${MODEL_BUILD_DIR}/epics/
+EPICS_SRC_DIR=${EPICS_DIR}/src/
+EPICS_BUILD_DIR=${MODEL_TARGET_DIR}/${system}epics/
+BUILD_INFO_DIR=${MODEL_TARGET_DIR}/build_info/
+
+if ! test -e ${EPICS_BUILD_DIR}; then
     echo "Please make $system first." >&2
     exit 1
 fi
@@ -24,7 +33,7 @@ site=${site^^*}
 ifo=${ifo^^*}
 site_letter=${ifo:0:1}
 upper_system=`echo $system | tr a-z A-Z`
-targetcpu=`grep TARGET_CPU src/include/${system}.h | head -1 | awk '{print $3}'`
+targetcpu=`grep TARGET_CPU ${MODEL_INC_DIR}/${system}.h | head -1 | awk '{print $3}'`
 cur_date=`date +%y%m%d_%H%M%S`
 
 RTCDS=/opt/rtcds/${site,,*}/${ifo,,*}
@@ -40,14 +49,16 @@ mkdir -p $TARGET
 echo "Installing channel file..."
 
 mkdir -p $RTCDS/chans/filter_archive/$system
+chmod 775 $RTCDS/chans/filter_archive/$system
 
 if test -e $RTCDS/chans/${upper_system}.txt; then
     cp  $RTCDS/chans/${upper_system}.txt $RTCDS/chans/filter_archive/$system/${upper_system}_${cur_date}_install.txt || exit 1
-    head -4 build/${system}epics/config/${ifo}${upper_system}.txt > $RTCDS/chans/${upper_system}.txt
-    grep '^# MODULES' build/${system}epics/config/${ifo}${upper_system}.txt >> $RTCDS/chans/${upper_system}.txt
+    head -4 ${EPICS_SRC_DIR}/config/${ifo}${upper_system}.txt > $RTCDS/chans/${upper_system}.txt
+    grep '^# MODULES' ${EPICS_SRC_DIR}/config/${ifo}${upper_system}.txt >> $RTCDS/chans/${upper_system}.txt
     tail -n +5 $RTCDS/chans/filter_archive/$system/${upper_system}_${cur_date}_install.txt | grep -v '^# MODULES' >> $RTCDS/chans/${upper_system}.txt
+
 else
-    cp -p build/${system}epics/config/${ifo}${upper_system}.txt  $RTCDS/chans/${upper_system}.txt
+    cp -p ${EPICS_SRC_DIR}/config/${ifo}${upper_system}.txt  $RTCDS/chans/${upper_system}.txt
 fi
 
 ##########
@@ -61,13 +72,16 @@ fi
 
 mkdir -p $TARGET/{bin,scripts,logs}
 chmod 775 $TARGET/logs
+mkdir -p $RTCDS/chans/tmp
+chmod 775 $RTCDS/chans/tmp
 mkdir -p $TARGET/${system}epics/burt
+chmod 775 $TARGET/${system}epics/burt
 if [ -e $RTCDS/target_archive/${system}/${system}_$cur_date/${system}epics/burt ]; then
     cp -pr $RTCDS/target_archive/${system}/${system}_$cur_date/${system}epics/burt $TARGET/${system}epics
 fi
-cp -pr target/${system}epics $TARGET
-mv -f $TARGET/${system}epics/src $TARGET
-chmod -R a-w $TARGET/src
+cp -pr ${EPICS_BUILD_DIR}/* $TARGET/${system}epics #Copy epics process dir to install dir
+cp -rf ${BUILD_INFO_DIR} $TARGET
+chmod -R a-w $TARGET/build_info
 if test -e $TARGET/${system}epics/db/*/autoBurt.req; then
     mv -f $TARGET/${system}epics/db/*/autoBurt.req $TARGET/${system}epics || exit 3
 fi
@@ -82,8 +96,8 @@ if test -e $RTCDS/medm/${system}; then
 fi
 
 mkdir -p $RTCDS/medm/${system}
-(cd build/${system}epics/medm; find . -name "*.adl" | xargs -r cp --parents -r -t $RTCDS/medm/${system})
-(cd build/${system}epics/medm; find . -name "*.ui" | xargs -r cp --parents -r -t $RTCDS/medm/${system})
+(cd ${EPICS_SRC_DIR}/medm; find . -name "*.adl" | xargs -r cp --parents -r -t $RTCDS/medm/${system})
+(cd ${EPICS_SRC_DIR}/medm; find . -name "*.ui" | xargs -r cp --parents -r -t $RTCDS/medm/${system})
 
 ##########
 
@@ -92,11 +106,11 @@ echo "Installing RT components..."
 if test -e $TARGET/bin/${system}.ko; then
     mv -f $TARGET/bin/${system}.ko $TARGET/archive/${system}fe_${cur_date}.ko || exit 4
 fi
-if test -e src/fe/${system}/${system}.ko; then
-    cp -fp src/fe/${system}/${system}.ko $TARGET/bin/
+if test -e ${TARGET_BIN_DIR}/${system}.ko; then
+    cp -fp ${TARGET_BIN_DIR}/${system}.ko $TARGET/bin/
 fi
-if test -e src/fe/${system}_usp/${system}; then
-    cp -fp src/fe/${system}_usp/${system} $TARGET/bin/
+if test -e ${TARGET_BIN_DIR}/${system}; then
+    cp -fp ${TARGET_BIN_DIR}/${system} $TARGET/bin/
 fi
 if test -e $TARGET/bin/${system}; then
     echo  'taskset -c '$targetcpu $TARGET/bin/${system} '-m ' ${system} ' >  '$TARGET/logs/log.txt ' 2>& 1 &' > $TARGET/scripts/startup${ifo}usp
@@ -105,13 +119,13 @@ fi
 
 ##########
 
-gds_node=`grep rmid build/${system}epics/${system}.par | head -1 | sed 's/[^0-9]*\([0-9]*\)/\1/'`
+gds_node=`grep rmid ${EPICS_SRC_DIR}/${system}.par | head -1 | sed 's/[^0-9]*\([0-9]*\)/\1/'`
 if [ x$gds_node != "x" ]; then
 
     echo "Installing GDS components..."
 
-    datarate=`grep datarate build/${system}epics/${system}.par | head -1 | sed 's/[^0-9]*\([0-9]*\)/\1/'`
-    targethost=`grep TARGET_HOST_NAME src/include/${system}.h | head -1 | awk '{print $3}'`
+    datarate=`grep datarate ${EPICS_SRC_DIR}/${system}.par | head -1 | sed 's/[^0-9]*\([0-9]*\)/\1/'`
+    targethost=`grep TARGET_HOST_NAME ${MODEL_INC_DIR}/${system}.h | head -1 | awk '{print $3}'`
     if test ${datarate} -lt 16384; then
 	datarate_mult=`expr ${datarate} / 2048`
     else
@@ -126,7 +140,7 @@ if [ x$gds_node != "x" ]; then
     ##########
 
     echo "Updating testpoint config file..."
-    if [[ $gds_node -lt 256 ]] && test -e src/fe/${system}/${system}.ko; then
+    if [[ $gds_node -lt 256 ]] && test -e ${TARGET_BIN_DIR}/${system}.ko; then
       if test -e $RTCDS/target/gds/param/testpoint.par; then
         mv -f $RTCDS/target/gds/param/testpoint.par $RTCDS/target/gds/param/archive/testpoint_${cur_date}.par || exit 1
         testpoint_par_infname=$RTCDS/target/gds/param/archive/testpoint_${cur_date}.par
@@ -142,11 +156,11 @@ if [ x$gds_node != "x" ]; then
     if test -e $RTCDS/target/gds/param/tpchn_${system}.par; then
 	mv -f $RTCDS/target/gds/param/tpchn_${system}.par $RTCDS/target/gds/param/archive/tpchn_${system}_${cur_date}.par || exit 1
     fi
-    cp -p build/${system}epics/${system}.par $RTCDS/target/gds/param/tpchn_${system}.par
+    cp -p ${EPICS_SRC_DIR}/${system}.par $RTCDS/target/gds/param/tpchn_${system}.par
     mkdir -p $TARGET/param
-    cp -p build/${system}epics/${system}.par $TARGET/param/tpchn_${system}.par
+    cp -p ${EPICS_SRC_DIR}/${system}.par $TARGET/param/tpchn_${system}.par
     mkdir -p  $RTCDS/chans/adc
-    cp -p build/${system}epics/config/adcListSorted.txt  $RTCDS/chans/adc/${system}_adclist.txt
+    cp -p ${EPICS_SRC_DIR}/config/adcListSorted.txt  $RTCDS/chans/adc/${system}_adclist.txt
     if test ${datarate_mult} -gt 1; then
         datarate_mult_flag=-${datarate_mult}
     else
@@ -161,12 +175,12 @@ if [ x$gds_node != "x" ]; then
         mv -f $RTCDS/chans/daq/${upper_system}.ini $RTCDS/chans/daq/archive/${upper_system}_${cur_date}.ini || exit 2
         #
         # Do not update anything now, file is generated from the model
-        #echo $srcdir/src/epics/util/updateDaqConfig1.pl -daq_old=$RTCDS/chans/daq/archive/${upper_system}_${cur_date}.ini -old=$RTCDS/target/gds/param/archive/tpchn_${system}.par -new=build/${system}epics/${system}.par -daq=build/${system}epics/${system}.ini 
-        # $srcdir/src/epics/util/updateDaqConfig1.pl -daq_old=$RTCDS/chans/daq/archive/${upper_system}_${cur_date}.ini -old=$RTCDS/target/gds/param/archive/tpchn_${system}_${cur_date}.par -new=build/${system}epics/${system}.par -daq=build/${system}epics/${system}.ini > $RTCDS/chans/daq/${upper_system}.ini 
+        #echo $srcdir/src/epics/util/updateDaqConfig1.pl -daq_old=$RTCDS/chans/daq/archive/${upper_system}_${cur_date}.ini -old=$RTCDS/target/gds/param/archive/tpchn_${system}.par -new=${EPICS_SRC_DIR}/${system}.par -daq=${EPICS_SRC_DIR}/${system}.ini 
+        # $srcdir/src/epics/util/updateDaqConfig1.pl -daq_old=$RTCDS/chans/daq/archive/${upper_system}_${cur_date}.ini -old=$RTCDS/target/gds/param/archive/tpchn_${system}_${cur_date}.par -new=${EPICS_SRC_DIR}/${system}.par -daq=${EPICS_SRC_DIR}/${system}.ini > $RTCDS/chans/daq/${upper_system}.ini 
         #else
-        #  cp -p build/${system}epics/${system}.ini $RTCDS/chans/daq/${upper_system}.ini
+        #  cp -p ${EPICS_SRC_DIR}/${system}.ini $RTCDS/chans/daq/${upper_system}.ini
     fi
-    cp -p build/${system}epics/${system}.ini $RTCDS/chans/daq/${upper_system}.ini
+    cp -p ${EPICS_SRC_DIR}/${system}.ini $RTCDS/chans/daq/${upper_system}.ini
 
     cp $RTCDS/chans/daq/${upper_system}.ini $TARGET/param/${upper_system}.ini
     #echo Installing EDCU ini file
diff --git a/src/daqd/CMakeLists.txt b/src/daqd/CMakeLists.txt
index 778acc01539ae7b0d28bc9d1be3597d4c35c8cdd..eeb7f9f23ddea26b55fde4f477a320d2c39cf57c 100644
--- a/src/daqd/CMakeLists.txt
+++ b/src/daqd/CMakeLists.txt
@@ -192,7 +192,7 @@ add_executable(test_crc32 checksum_crc32.cc
 		tests/test_checksum_crc32.cc
 		../drv/crc.c)
 target_compile_definitions(test_crc32 PRIVATE CRC32_AUTO_GENERATE_TABLE)
-target_include_directories(test_crc32 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+target_include_directories(test_crc32 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../include/)
 target_link_libraries(test_crc32 PUBLIC catch2)
 add_test(NAME test_crc32
 		COMMAND test_crc32
@@ -202,7 +202,7 @@ add_executable(test_crc32_table_lookup
 		checksum_crc32.cc
 		tests/test_checksum_crc32.cc
 		../drv/crc.c)
-target_include_directories(test_crc32_table_lookup PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+target_include_directories(test_crc32_table_lookup PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../include/)
 target_link_libraries(test_crc32_table_lookup PUBLIC catch2)
 add_test(NAME test_crc32_table_lookup
 		COMMAND test_crc32_table_lookup
diff --git a/src/daqd/daqd.cc b/src/daqd/daqd.cc
index b70a5e7c9c41495ea36ec6b9b64693f9a7635305..51b1125500a3f05e20072d435d3e0c122315ed78 100644
--- a/src/daqd/daqd.cc
+++ b/src/daqd/daqd.cc
@@ -40,10 +40,8 @@
 #include "framecpp/Common/MD5SumFilter.hh"
 #include "run_number_client.hh"
 #include "daqmap.h"
-extern "C" {
 #include "crc.h"
 #include "param.h"
-}
 
 using namespace std;
 
@@ -2212,4 +2210,4 @@ shutdown_server( )
     DEBUG1( cerr << "shut\n" );
     exit( 0 );
     return 0;
-}
\ No newline at end of file
+}
diff --git a/src/daqd/tests/test_checksum_crc32.cc b/src/daqd/tests/test_checksum_crc32.cc
index 35be2a8cac32a94921c6ad720c6e90c41a73cd45..5072f6ab57c180e75bcdff37276168ec95892b68 100644
--- a/src/daqd/tests/test_checksum_crc32.cc
+++ b/src/daqd/tests/test_checksum_crc32.cc
@@ -11,6 +11,8 @@
 
 #include "checksum_crc32.hh"
 
+#include "crc.h" //crctab Global
+
 typedef std::pair< std::string, uint32_t > test_type;
 typedef std::vector< test_type >           test_list;
 
@@ -59,7 +61,6 @@ generate_inputs( )
     return inputs;
 }
 
-extern unsigned int crctab[ 256 ];
 
 unsigned int older_crc(unsigned char* cp, unsigned long read_size)
 {
@@ -109,4 +110,4 @@ TEST_CASE( "Test the crc32 class" )
         REQUIRE( sum.result( ) == input.second );
         REQUIRE( older_crc ( (unsigned char*)input.first.data(), input.first.size()) == input.second );
     }
-}
\ No newline at end of file
+}
diff --git a/src/drv/rts-cpu-isolator/.gitignore b/src/drv/.gitignore
similarity index 100%
rename from src/drv/rts-cpu-isolator/.gitignore
rename to src/drv/.gitignore
diff --git a/src/drv/CMakeLists.txt b/src/drv/CMakeLists.txt
index d5533398fafd488de9a6c468c6f4aad63f8e2ca8..52b2a08e7ede9ad031332553286d1c54649223c5 100644
--- a/src/drv/CMakeLists.txt
+++ b/src/drv/CMakeLists.txt
@@ -1,4 +1,7 @@
 add_subdirectory(mbuf/mbuf_probe)
+add_subdirectory(mbuf/userapace_test)
+add_subdirectory(gpstime/tests)
+add_subdirectory(gpstime/gps_module_utils)
 add_subdirectory(python)
 
 add_library(shmem STATIC shmem.c rfm.c)
diff --git a/src/drv/crc.c b/src/drv/crc.c
index 55af55f7e0850d9ea43567449efa074de44f604c..bccc775ae26172559ab10535289149c92e109304 100644
--- a/src/drv/crc.c
+++ b/src/drv/crc.c
@@ -1,7 +1,10 @@
 ///	@file crc.c
 ///	@brief Contains functions for performing CRC checksum calculations.
 
-unsigned int crctab[256] =
+#include "../include/crc.h"
+
+
+const unsigned int crctab[256] =
 {
   0x0,
   0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
diff --git a/src/drv/fmReadCoeff.c b/src/drv/fmReadCoeff.c
index 90d2410b4f75e6d80f7dc80265131018ef211377..a34320a713013035f374f4a7a7ec014f25a025c3 100644
--- a/src/drv/fmReadCoeff.c
+++ b/src/drv/fmReadCoeff.c
@@ -27,12 +27,12 @@
 #define FM_SUBSYS_NUM 1
 #endif
 
-#include "fm10Gen.h"
+#include "fm10Gen_types.h"
 #include "fmReadCoeff.h"
 #include "crc.h"
+#include "util/user/check_file_crc.h"
 
 int        getwords( char*, char*[], int );
-extern int checkFileCrc( char* );
 
 /* Cat string and make upper case */
 static char*
diff --git a/src/drv/gpstime/.gitignore b/src/drv/gpstime/.gitignore
index 524ad3c05d93f198c535d5f4f28f220ee1b8fcb9..f0aeb7754150932ce5778e8bd09371107204de7a 100644
--- a/src/drv/gpstime/.gitignore
+++ b/src/drv/gpstime/.gitignore
@@ -4,3 +4,4 @@
 *.symvers
 *.d
 *.o.d
+temp/
diff --git a/src/drv/gpstime/Makefile b/src/drv/gpstime/Makefile
index 72cb447021f433098bfdf71f24a7c0715b7cb8e9..8139d2d76b2d6e8e84cd79de924cc459cdbe40aa 100644
--- a/src/drv/gpstime/Makefile
+++ b/src/drv/gpstime/Makefile
@@ -8,12 +8,14 @@
 #
 MODULENAME 	:= gpstime
 
+mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
+mkfile_dir := $(dir $(mkfile_path))
+
 
 ### should not need to change stuff below ######################
 
 
 KDIR		:= /lib/modules/$(shell uname -r)/build
-#KDIR		:= /exports/linux-2.6.12.2/
 KVER		:= $(shell uname -r)
 PWD		:= $(shell pwd)
 
@@ -24,12 +26,17 @@ INSTDIR		:= /lib/modules/$(KVER)/extra
 
 SYMVERSDIR	:= /var/cache/$(MODULENAME)
 
+obj-m += $(MODULENAME).o
+$(MODULENAME)-y := $(MODULENAME)_core.o 
+$(MODULENAME)-y += ../../include/drv/spectracomGPS.o
+$(MODULENAME)-y += ../../include/drv/symmetricomGps.o
+$(MODULENAME)-y += ../../include/drv/ligoPcieTiming_core.o
+
+ccflags-y += -I$(mkfile_dir)/../../include/ 
+
 ifeq ($(KERNELRELEASE),)
-#all:	$(MODULENAME)_test
 all:
 	$(MAKE) -C $(KDIR) M=$(PWD) modules
-else
-  obj-m	:= $(MODULENAME).o
 endif
 
 stest: stest.c
@@ -75,4 +82,7 @@ test: all
 
 clean:
 	rm -f *.o *.ko Module.symvers *.mod.c .*.cmd stest modules.order
+	rm -f ../../include/drv/*.o
+	rm -f ../../include/drv/.*o.cmd
+
 
diff --git a/src/drv/gpstime/gps_module_utils/CMakeLists.txt b/src/drv/gpstime/gps_module_utils/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4cf1f553aa6619c8fbcad93c47b27731eea8cbb8
--- /dev/null
+++ b/src/drv/gpstime/gps_module_utils/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_executable(gps_module_utils
+        gps_module_utils.cc)
+target_include_directories(gps_module_utils PUBLIC
+        "${CMAKE_CURRENT_SOURCE_DIR}/../")
+
+install(TARGETS gps_module_utils DESTINATION bin)
\ No newline at end of file
diff --git a/src/drv/gpstime/gps_module_utils/gps_module_utils.cc b/src/drv/gpstime/gps_module_utils/gps_module_utils.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3c961b1c64278e6d43b6207801f71f3fc357d96a
--- /dev/null
+++ b/src/drv/gpstime/gps_module_utils/gps_module_utils.cc
@@ -0,0 +1,185 @@
+//
+// Created by jonathan.hanks on 2/28/22.
+//
+
+#include <algorithm>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <iterator>
+#include <string>
+#include <vector>
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <asm/ioctl.h>
+
+
+#include "gpstime.h"
+
+enum class Action {
+    PAUSE,
+    RESUME,
+    RESET,
+    STEP,
+    TIME,
+    STATUS,
+};
+
+class FDHolder {
+    constexpr static int invalid() noexcept
+    {
+        return -1;
+    }
+public:
+    FDHolder() = default;
+    explicit FDHolder(const char*name, int mode=O_RDWR): fd_{::open(name, mode)} {}
+    FDHolder(const FDHolder&) = delete;
+    FDHolder(FDHolder&& other) noexcept: fd_{other.fd_}
+    {
+        other.fd_ = invalid();
+    }
+    ~FDHolder()
+    {
+        close();
+    }
+    FDHolder& operator=(const FDHolder&) = delete;
+    FDHolder& operator=(FDHolder&& other) noexcept
+    {
+        close();
+        fd_ = other.fd_;
+        other.fd_ = invalid();
+        return *this;
+    }
+    int get() const
+    {
+        return fd_;
+    }
+    operator bool() const noexcept
+    {
+        return fd_ != invalid();
+    }
+private:
+    void
+    close() noexcept
+    {
+        if (fd_ != invalid())
+        {
+            ::close(fd_);
+            fd_ = invalid();
+        }
+    }
+    int fd_{invalid()};
+};
+
+template <typename C, typename OutContainer = std::vector< typename C::key_type > >
+OutContainer
+keys(const C& container)
+{
+    OutContainer out{};
+    for (const auto& cur:container)
+    {
+        out.emplace_back(cur.first);
+    }
+    return out;
+}
+
+void
+usage(char* progname, const std::vector<std::string>&& options)
+{
+    std::cout << "Usage:\n\t" << progname << " <option>\n\n";
+    std::cout << "Where option is one of:\n\t";
+    std::copy(options.begin(), options.end(), std::ostream_iterator<std::string>(std::cout, "\n\t"));
+    std::exit(1);
+}
+
+Action
+select_action(int argc, char* argv[])
+{
+    std::map<std::string, Action> action_map{
+        {"pause", Action::PAUSE},
+        {"resume", Action::RESUME},
+        {"reset", Action::RESET},
+        {"step", Action::STEP},
+        {"time", Action::TIME},
+        {"status", Action::STATUS}
+    };
+    for (auto i = 1; i < argc; ++i)
+    {
+        std::string arg{argv[i]};
+        auto it = action_map.find(arg);
+        if (it == action_map.end())
+        {
+            usage(argv[0], keys(action_map));
+        }
+        return it->second;
+    }
+    usage(argv[0], keys(action_map));
+    throw std::runtime_error("bad arguments");
+}
+
+void
+ioctl_simple(int fd, int ioctl_command)
+{
+    long dummy[3];
+    ioctl( fd, ioctl_command, &dummy );
+}
+
+void
+ioctl_time(int fd) {
+    unsigned long t[3];
+    ioctl( fd, IOCTL_SYMMETRICOM_TIME, &t);
+    t[1] *= 1000;
+    t[1] += t[2];
+    std::cout << t[0] << ":" << t[1] << "\n";
+}
+
+void
+read_status()
+{
+    std::fstream input("/sys/kernel/gpstime/debug_pause_status", std::ios::binary | std::ios_base::in );
+    if (input)
+    {
+        std::vector<char> data{};
+        data.resize(1024);
+        input.read(data.data(), 1024);
+        data[1024-1] = '\0';
+        std::cout << data.data() << std::endl;
+    }
+
+}
+
+int
+main(int argc, char* argv[])
+{
+    FDHolder fd("/dev/gpstime");
+    switch (select_action(argc, argv))
+    {
+    case Action::PAUSE:
+        ioctl_simple(fd.get(), IOCTL_GPSTIME_PAUSE);
+        break;
+    case Action::RESUME:
+        ioctl_simple(fd.get(), IOCTL_GPSTIME_RESUME);
+        break;
+    case Action::RESET:
+        ioctl_simple(fd.get(), IOCTL_GPSTIME_RESET );
+        break;
+    case Action::STEP:
+        ioctl_simple(fd.get(), IOCTL_GPSTIME_STEP);
+        break;
+    case Action::TIME:
+        ioctl_time(fd.get());
+        break;
+    case Action::STATUS:
+        read_status();
+        break;
+    default:
+        throw std::runtime_error("Unknown option");
+    }
+    return 0;
+}
\ No newline at end of file
diff --git a/src/drv/gpstime/gpstime.h b/src/drv/gpstime/gpstime.h
index dd2dfa10e63849a9de32e2c35abe202cf8b914a3..95bb76840a5937cc2d504bb344184a865180fbc9 100644
--- a/src/drv/gpstime/gpstime.h
+++ b/src/drv/gpstime/gpstime.h
@@ -1,6 +1,7 @@
 #ifndef LIGO_GPSTIME_H
 #define LIGO_GPSTIME_H
 
+#include <linux/ioctl.h>
 
 // Get GPS card status (locked or unlocked)
 #define IOCTL_SYMMETRICOM_STATUS 0
@@ -8,6 +9,11 @@
 // Get current GPS time
 #define IOCTL_SYMMETRICOM_TIME 1
 
+#define IOCTL_GPSTIME_PAUSE _IO('x', 2)
+#define IOCTL_GPSTIME_RESUME _IO('x', 3)
+#define IOCTL_GPSTIME_RESET _IO('x', 4)
+#define IOCTL_GPSTIME_STEP _IO('x', 5)
+
 // Define the type of manual synchronization that
 // must be done to the system to get correct time
 #define STATUS_SYMMETRICOM_NO_SYNC 0
diff --git a/src/drv/gpstime/gpstime.c b/src/drv/gpstime/gpstime_core.c
similarity index 72%
rename from src/drv/gpstime/gpstime.c
rename to src/drv/gpstime/gpstime_core.c
index b37c0fd4c7aea6f16a462c2f3dced19a59e7b9a4..8574f9f674bdcc99664b41295251bdd18d7c965c 100644
--- a/src/drv/gpstime/gpstime.c
+++ b/src/drv/gpstime/gpstime_core.c
@@ -24,6 +24,7 @@
 #include <linux/proc_fs.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
+#include <linux/spinlock.h>
 
 #ifdef MODVERSIONS
 #  include <linux/modversions.h>
@@ -31,17 +32,24 @@
 #include <asm/io.h>
 #include "gpstime.h"
 #include "gpstime_kernel.h"
+#include "timespec_utils.h"
 
 #include "../../include/drv/cdsHardware.h"
 #include "../../include/proc.h"
 
 CDS_HARDWARE cdsPciModules;
 
+#define NANO_IN_SEC 1000000000
+
 #define IN_LIGO_GPS_KERNEL_DRIVER 1
 
-#include "../../include/drv/spectracomGPS.c"
-#include "../../include/drv/symmetricomGps.c"
-#include "../../include/drv/ligoPcieTiming_core.c"
+//From advligorts/src/include/
+#include "drv/spectracomGPS.h"
+#include "drv/symmetricomGps.h"
+#include "drv/ligoPcieTiming.h"
+//#include "../../include/drv/spectracomGPS.c"
+//#include "../../include/drv/symmetricomGps.c"
+//#include "../../include/drv/ligoPcieTiming_core.c"
 
 #define CDS_LOCAL_GPS_BUFFER_SIZE 30
 
@@ -54,6 +62,149 @@ struct proc_dir_entry *proc_gps_offset_entry;
 
 atomic64_t gps_offset = ATOMIC_INIT(0);
 
+typedef struct gps_pause_info {
+    ligo_duration pause_offset;
+    LIGO_TIMESPEC pause_time;
+    ligo_duration pause_step;
+    int paused;
+} gps_pause_info;
+
+#define PAUSE_STATE_REALTIME 0
+#define PAUSE_STATE_PAUSED 1
+#define PAUSE_STATE_BEHIND 2
+
+// track if we have had a pause operation ever
+// this is reset on a reset.
+static atomic64_t gps_has_been_paused = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(gps_pause_lock);
+static gps_pause_info pause_info;
+
+static inline void
+gps_pause_init(void)
+{
+    spin_lock(&gps_pause_lock);
+    atomic64_set(&gps_has_been_paused, 0);
+    pause_info.pause_offset.tv_sec = 0;
+    pause_info.pause_offset.tv_nsec = 0;
+    pause_info.pause_time.tv_sec = 0;
+    pause_info.pause_time.tv_nsec = 0;
+    pause_info.pause_step.tv_sec = 0;
+    pause_info.pause_step.tv_nsec = (NANO_IN_SEC/16);
+    pause_info.paused = 0;
+    spin_unlock(&gps_pause_lock);
+}
+
+static inline int
+gps_pause_state(void)
+{
+    int state = PAUSE_STATE_REALTIME;
+    spin_lock(&gps_pause_lock);
+    if (pause_info.paused)
+    {
+        state = PAUSE_STATE_PAUSED;
+    }
+    else if (pause_info.pause_offset.tv_sec != 0 || pause_info.pause_offset.tv_nsec != 0)
+    {
+        state = PAUSE_STATE_BEHIND;
+    }
+    spin_unlock(&gps_pause_lock);
+    return state;
+}
+
+static inline void
+gps_pause_pause(void)
+{
+    LIGO_TIMESPEC real_time;
+    ligo_get_current_kernel_time(&real_time);
+    spin_lock(&gps_pause_lock);
+    atomic64_set(&gps_has_been_paused, 1);
+    if (pause_info.paused == 0)
+    {
+        pause_info.paused = 1;
+        pause_info.pause_time = ltimespec_sub(real_time, pause_info.pause_offset);
+    }
+    spin_unlock(&gps_pause_lock);
+}
+
+static inline void
+gps_pause_resume(void)
+{
+    LIGO_TIMESPEC real_time;
+    ligo_get_current_kernel_time(&real_time);
+    spin_lock(&gps_pause_lock);
+    if (pause_info.paused)
+    {
+        pause_info.paused = 0;
+        pause_info.pause_offset = ltimespec_difference(real_time, pause_info.pause_time);
+    }
+    spin_unlock(&gps_pause_lock);
+}
+
+static inline void
+gps_pause_step(void)
+{
+    spin_lock(&gps_pause_lock);
+    if (pause_info.paused)
+    {
+        pause_info.pause_time = ltimespec_add(pause_info.pause_time, pause_info.pause_step);
+    }
+    spin_unlock(&gps_pause_lock);
+}
+
+static inline ligo_duration
+gps_pause_get_step_size(void)
+{
+    ligo_duration result;
+    spin_lock(&gps_pause_lock);
+    result = pause_info.pause_step;
+    spin_unlock(&gps_pause_lock);
+    return result;
+}
+
+static inline void
+gps_pause_set_step_size(ligo_duration step_size)
+{
+    if (step_size.tv_sec < 0 || step_size.tv_nsec < 0)
+    {
+        return;
+    }
+    if (step_size.tv_nsec >= NANO_IN_SEC)
+    {
+        step_size.tv_sec += step_size.tv_nsec / NANO_IN_SEC;
+        step_size.tv_nsec = step_size.tv_nsec % NANO_IN_SEC;
+    }
+    spin_lock(&gps_pause_lock);
+    pause_info.pause_step = step_size;
+    spin_unlock(&gps_pause_lock);
+}
+
+static inline LIGO_TIMESPEC
+gps_pause_now(void)
+{
+    LIGO_TIMESPEC result;
+    LIGO_TIMESPEC real_time;
+
+    // stay lock free if we have never been paused
+    if (atomic64_read(&gps_has_been_paused) == 0)
+    {
+        ligo_get_current_kernel_time(&result);
+        return result;
+    }
+
+    spin_lock( &gps_pause_lock );
+    if ( pause_info.paused )
+    {
+        result = pause_info.pause_time;
+    }
+    else
+    {
+        ligo_get_current_kernel_time( &real_time );
+        result = ltimespec_sub( real_time, pause_info.pause_offset );
+    }
+    spin_unlock( &gps_pause_lock );
+    return result;
+}
+
 /* What type of syncing does the driver need */
 static int gps_module_sync_type = STATUS_SYMMETRICOM_NO_SYNC;
 
@@ -102,11 +253,11 @@ int get_cur_time(unsigned long *req) {
   offset = atomic64_read(&gps_offset);
 
   if (card_present && card_type == GPSTIME_SPECTRACOM_CARD) {
-	sync = getGpsTimeTsync(&timeSec, &timeUsec);
+	sync = getGpsTimeTsync(&cdsPciModules, &timeSec, &timeUsec);
 	req[0] = timeSec; req[1] = timeUsec; req[2] = 0;
   } else if (card_present && card_type == GPSTIME_SYMMETRICOM_CARD) {
-  	lockGpsTime();
-	sync = getGpsTime(&timeSec, &timeUsec);
+  	lockGpsTime( &cdsPciModules );
+	sync = getGpsTime(&cdsPciModules, &timeSec, &timeUsec);
 	req[0] = timeSec; req[1] = timeUsec; req[2] = 0;
   } else if (card_present && card_type == GPSTIME_LIGO_PCI_CARD) { 
         sync = lptc_get_gps_time(&cdsPciModules, &timeSec, &timeUsec);
@@ -114,9 +265,9 @@ int get_cur_time(unsigned long *req) {
   } else {
       // Get current kernel time (in GPS)
       LIGO_TIMESPEC t;
-      ligo_get_current_kernel_time(&t);
-	  req[0] = t.tv_sec; req[1] = t.tv_nsec/1000; req[2] = t.tv_nsec%1000;
-	  sync = 1;
+      t = gps_pause_now();
+      req[0] = t.tv_sec; req[1] = t.tv_nsec/1000; req[2] = t.tv_nsec%1000;
+      sync = 1;
   }
   req[0] += offset;
   return sync;
@@ -127,6 +278,7 @@ static long symmetricom_ioctl(struct file *inode, unsigned int cmd, unsigned lon
     unsigned long req[3];
     unsigned long res = 0;
 
+    /* printk("symmetricom_ioctl called cmd = %d arg = %d", (int)cmd, (int)arg); */
     switch(cmd){
         case IOCTL_SYMMETRICOM_STATUS:
             res = get_cur_time(req);
@@ -135,11 +287,39 @@ static long symmetricom_ioctl(struct file *inode, unsigned int cmd, unsigned lon
         case IOCTL_SYMMETRICOM_TIME:
             get_cur_time(req);
             if (copy_to_user ((void *) arg, req,  sizeof (req))) return -EFAULT;
-		    break;
+            break;
+        case IOCTL_GPSTIME_PAUSE:
+            if (card_present)
+            {
+                return -EINVAL;
+            }
+            gps_pause_pause();
+            break;
+        case IOCTL_GPSTIME_RESUME:
+            if (card_present)
+            {
+                return -EINVAL;
+            }
+            gps_pause_resume();
+            break;
+        case IOCTL_GPSTIME_RESET:
+            if (card_present)
+            {
+                return -EINVAL;
+            }
+            gps_pause_init();
+            break;
+        case IOCTL_GPSTIME_STEP:
+            if (card_present)
+            {
+                return -EINVAL;
+            }
+            gps_pause_step();
+            break;
         default:
                 return -EINVAL;
         }
-        return -EINVAL;
+        return 0;
 }
 
 /* This is called to translate an item in the sequence to output.
@@ -309,6 +489,40 @@ static ssize_t gpstime_sysfs_gpstime_show(struct kobject *kobj, struct kobj_attr
     return sysfs_emit(buf, "%ld.%02ld\n", req[0], req[1]/10000);
 }
 
+static ssize_t gpstime_sysfs_pause_status_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
+    switch (gps_pause_state())
+    {
+    case PAUSE_STATE_REALTIME: return sysfs_emit(buf, "%d realtime\n", PAUSE_STATE_REALTIME);
+    case PAUSE_STATE_PAUSED: return sysfs_emit(buf, "%d paused\n", PAUSE_STATE_PAUSED);
+    case PAUSE_STATE_BEHIND: return sysfs_emit(buf, "%d behind\n", PAUSE_STATE_BEHIND);
+    }
+    return sysfs_emit(buf, "-1 unknown state\n");
+}
+
+static ssize_t gpstime_sysfs_pause_step_size_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+    ligo_duration step_size = gps_pause_get_step_size();
+    s64 step_size_nano = (step_size.tv_sec * NANO_IN_SEC) + step_size.tv_nsec;
+    return sysfs_emit(buf, "%lld\n", step_size_nano);
+}
+
+static ssize_t gpstime_sysfs_pause_step_size_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
+{
+    ligo_duration new_step;
+    s64 new_step_nano = 0;
+    int conv_ret = 0;
+
+    if ((conv_ret = kstrtoll(buf, 10, &new_step_nano)) != 0) {
+        printk("gpstime_sysfs_pause_step_size_store error converting offset into an integer - %s %d", (conv_ret == -ERANGE ? "range" : "overflow"), conv_ret);
+        return -EFAULT;
+    }
+    new_step.tv_sec = new_step_nano / NANO_IN_SEC;
+    new_step.tv_nsec = new_step_nano % NANO_IN_SEC;
+    gps_pause_set_step_size(new_step);
+
+    /* tell it we consumed everything */
+    return (ssize_t)count;
+}
 
 static void config_proc_entry(struct proc_dir_entry *proc_entry, int uid)
 {
@@ -375,12 +589,12 @@ int ligo_gpstime_get_ts(LIGO_TIMESPEC * ts)
     switch (card_type)
     {
         case GPSTIME_SPECTRACOM_CARD:
-            sync = getGpsTimeTsync(&timeSec, &timeUsec);
+            sync = getGpsTimeTsync(&cdsPciModules, &timeSec, &timeUsec);
             save = timeUsec;
             break;
         case GPSTIME_SYMMETRICOM_CARD:
-            lockGpsTime();
-            sync = getGpsTime(&timeSec, &timeUsec);
+            lockGpsTime( &cdsPciModules );
+            sync = getGpsTime(&cdsPciModules, &timeSec, &timeUsec);
             break;
         case GPSTIME_LIGO_PCI_CARD:
             sync = lptc_get_gps_time(&cdsPciModules, &timeSec, &timeUsec);
@@ -405,6 +619,8 @@ static struct kobj_attribute sysfs_gps_offset_type_attr = __ATTR(offset_type, 04
 static struct kobj_attribute sysfs_gps_offset_attr = __ATTR(offset, 0644, gpstime_sysfs_gps_offset_show, gpstime_sysfs_gps_offset_store);
 static struct kobj_attribute sysfs_status_attr = __ATTR(status, 0444, gpstime_sysfs_status_show, NULL);
 static struct kobj_attribute sysfs_gpstime_attr = __ATTR(time, 0444, gpstime_sysfs_gpstime_show, NULL);
+static struct kobj_attribute sysfs_pause_status_attr = __ATTR(debug_pause_status, 0444, gpstime_sysfs_pause_status_show, NULL);
+static struct kobj_attribute sysfs_pause_step_size_attr = __ATTR(debug_pause_step_size, 0644, gpstime_sysfs_pause_step_size_show, gpstime_sysfs_pause_step_size_store);
 
 /* group the attributes together for bulk operations */
 static struct attribute *gpstime_fields[] = {
@@ -414,6 +630,8 @@ static struct attribute *gpstime_fields[] = {
         &sysfs_gps_offset_attr.attr,
         &sysfs_status_attr.attr,
         &sysfs_gpstime_attr.attr,
+        &sysfs_pause_status_attr.attr,
+        &sysfs_pause_step_size_attr.attr,
         NULL,
 };
 
@@ -543,6 +761,7 @@ static int __init symmetricom_init(void)
             gps_module_sync_type = STATUS_SYMMETRICOM_NO_SYNC;
         }
 
+        gps_pause_init();
 
         return ret;
 out_remove_proc_entry:
diff --git a/src/drv/gpstime/gpstime_kernel.h b/src/drv/gpstime/gpstime_kernel.h
index f350f3038a430c251011c1aff37114a17ab35b19..5d8af58939ad2c67243df6c5289d8633832b0e09 100644
--- a/src/drv/gpstime/gpstime_kernel.h
+++ b/src/drv/gpstime/gpstime_kernel.h
@@ -4,6 +4,11 @@
 #include <linux/version.h>
 #include <linux/time.h>
 
+// linux/timekeeping.h does not include all the headers it uses
+// so we must include linux/ktime.h before using it
+//
+#include <linux/ktime.h>
+#include <linux/timekeeping.h> 
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
 #error "This kernel version is no longer supported by the gpstime module"
diff --git a/src/drv/gpstime/tests/CMakeLists.txt b/src/drv/gpstime/tests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d1c77bf9847772c7d75d47537673afeadcbb87fb
--- /dev/null
+++ b/src/drv/gpstime/tests/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(unittests)
+add_subdirectory(get_time_from_dev)
diff --git a/src/drv/gpstime/tests/get_time_from_dev/CMakeLists.txt b/src/drv/gpstime/tests/get_time_from_dev/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..70848889affb7a8de50a9edd51bc43822b63317f
--- /dev/null
+++ b/src/drv/gpstime/tests/get_time_from_dev/CMakeLists.txt
@@ -0,0 +1,11 @@
+project(get_time_from_dev)
+
+add_executable(${PROJECT_NAME}
+        stest.c)
+
+target_include_directories(${PROJECT_NAME} PUBLIC
+        "${CMAKE_CURRENT_SOURCE_DIR}/../../")
+
+add_test(NAME ${PROJECT_NAME}
+        COMMAND ${PROJECT_NAME}
+        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
diff --git a/src/drv/gpstime/stest.c b/src/drv/gpstime/tests/get_time_from_dev/stest.c
similarity index 82%
rename from src/drv/gpstime/stest.c
rename to src/drv/gpstime/tests/get_time_from_dev/stest.c
index bda07a4b43f4165c60fa4de459854b67ea7d6b1f..4d4e8783e54bad5cbb9fb64db4d2e4165d294300 100644
--- a/src/drv/gpstime/stest.c
+++ b/src/drv/gpstime/tests/get_time_from_dev/stest.c
@@ -21,14 +21,14 @@ int main (void)
 
   if ((fd = open ("/dev/gpstime", O_RDWR | O_SYNC)) < 0) {
       perror ("open");
-      exit (-1);
+      exit (1);
   }
 
   unsigned long req = 0;
   unsigned long t[3];
-  ioctl (fd, IOCTL_SYMMETRICOM_STATUS, &req);
+  if (ioctl (fd, IOCTL_SYMMETRICOM_STATUS, &req) < 0) exit(2);
   printf("%ld\n", req);
-  ioctl (fd, IOCTL_SYMMETRICOM_TIME, &t);
+  if( ioctl (fd, IOCTL_SYMMETRICOM_TIME, &t) < 0) exit(3);
   printf("%ds %du %dn\n", t[0], t[1], t[2]);
   return(0);
 }
diff --git a/src/drv/gpstime/tests/unittests/CMakeLists.txt b/src/drv/gpstime/tests/unittests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ec1e92daf896bc2e02720331c40b7a7ff1a281a8
--- /dev/null
+++ b/src/drv/gpstime/tests/unittests/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_executable(test_gpstime_unittests
+        test_main.cc
+        test_timespec.cc)
+target_include_directories(test_gpstime_unittests PUBLIC
+        "${CMAKE_CURRENT_SOURCE_DIR}/../../")
+target_link_libraries(test_gpstime_unittests PUBLIC
+        catch2)
+
+add_test(NAME test_gpstime_unittests
+        COMMAND test_gpstime_unittests
+        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
diff --git a/src/drv/gpstime/tests/unittests/test_main.cc b/src/drv/gpstime/tests/unittests/test_main.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a4bd0fd3276e83aa331c443bf9caf3ee4f9483af
--- /dev/null
+++ b/src/drv/gpstime/tests/unittests/test_main.cc
@@ -0,0 +1,5 @@
+//
+// Created by jonathan.hanks on 2/28/22.
+//
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
\ No newline at end of file
diff --git a/src/drv/gpstime/tests/unittests/test_timespec.cc b/src/drv/gpstime/tests/unittests/test_timespec.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cd2566e70005f158ef24d08d54a56bd64476f842
--- /dev/null
+++ b/src/drv/gpstime/tests/unittests/test_timespec.cc
@@ -0,0 +1,94 @@
+//
+// Created by jonathan.hanks on 2/28/22.
+//
+#include "catch.hpp"
+#include <cstdint>
+#include <vector>
+#include <time.h>
+#define LIGO_TIMESPEC timespec
+#include "timespec_utils.h"
+
+static inline LIGO_TIMESPEC
+ts(std::int64_t sec, std::int64_t nsec)
+{
+    LIGO_TIMESPEC t{};
+    t.tv_sec = sec;
+    t.tv_nsec = nsec;
+    return t;
+}
+
+static inline ligo_duration
+dur(std::int64_t sec, std::int64_t nsec)
+{
+    ligo_duration t{};
+    t.tv_sec = sec;
+    t.tv_nsec = nsec;
+    return t;
+}
+
+TEST_CASE("You can add LIGO_TIMESPECs together")
+{
+    struct test_case_def {
+        LIGO_TIMESPEC t0;
+        ligo_duration duration;
+        LIGO_TIMESPEC expected;
+    };
+    std::vector<test_case_def> test_cases{
+        {ts(0,0), dur(0,0), ts(0,0)},
+        {ts(1,0), dur(0,1), ts(1,1)},
+        {ts(1,999999999), dur(0,1), ts(2,0)},
+        {ts(1,999999999), dur(5,2), ts(7,1)},
+        {ts(1,1), dur(0,999999999), ts(2,0)},
+        {ts(1,2), dur(5,999999999), ts(7,1)},
+    };
+    for (const auto& test_case:test_cases)
+    {
+        auto results = ltimespec_add(test_case.t0, test_case.duration);
+        REQUIRE(results.tv_sec == test_case.expected.tv_sec);
+        REQUIRE(results.tv_nsec == test_case.expected.tv_nsec);
+    }
+}
+
+TEST_CASE("You can take the subtract a duration from a LIGO_TIMESPEC")
+{
+    struct test_case_def {
+        LIGO_TIMESPEC t0;
+        ligo_duration duration;
+        LIGO_TIMESPEC expected;
+    };
+    std::vector<test_case_def> test_cases{
+        {ts(0,0), dur(0,0), ts(0,0)},
+        {ts(1,0), dur(0,1), ts(0,999999999)},
+        {ts(1,999999999), dur(0,1), ts(1,999999998)},
+        {ts(1,999999999), dur(5,2), ts(-4,999999997)},
+        { ts(5, 3), dur(3, 7), ts(1, 999999996)},
+    };
+    for (const auto& test_case:test_cases)
+    {
+        auto results = ltimespec_sub(test_case.t0, test_case.duration);
+        REQUIRE(results.tv_sec == test_case.expected.tv_sec);
+        REQUIRE(results.tv_nsec == test_case.expected.tv_nsec);
+    }
+}
+
+TEST_CASE("You can take the difference between LIGO_TIMESPECs")
+{
+    struct test_case_def {
+        LIGO_TIMESPEC t0;
+        LIGO_TIMESPEC t1;
+        ligo_duration expected;
+    };
+    std::vector<test_case_def> test_cases{
+        {ts(0,0), ts(0,0), dur(0,0)},
+        {ts(1,0), ts(0,1), dur(0,999999999)},
+        {ts(1,999999999), ts(0,1), dur(1,999999998)},
+        {ts(1,999999999), ts(5,2), dur(-4,999999997)},
+        { ts(5, 3), ts(3, 7), dur(1, 999999996)},
+    };
+    for (const auto& test_case:test_cases)
+    {
+        auto results = ltimespec_difference(test_case.t0, test_case.t1);
+        REQUIRE(results.tv_sec == test_case.expected.tv_sec);
+        REQUIRE(results.tv_nsec == test_case.expected.tv_nsec);
+    }
+}
diff --git a/src/drv/gpstime/timespec_utils.h b/src/drv/gpstime/timespec_utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..247b211b300e7b6be995b6f903549562d28a9634
--- /dev/null
+++ b/src/drv/gpstime/timespec_utils.h
@@ -0,0 +1,89 @@
+//
+// Created by jonathan.hanks on 2/28/22.
+// Note, this function explicitly does not include defines for LIGO_TIMESPEC
+// so that it can be overidden to test from userspace.
+#ifndef DAQD_TRUNK_TIMESPEC_UTILS_H
+#define DAQD_TRUNK_TIMESPEC_UTILS_H
+
+#ifdef __KERNEL__
+
+/**
+ * @brief ligo_duration represents a time span
+ */
+typedef struct ligo_duration {
+    s64 tv_sec;
+    s64 tv_nsec;
+} ligo_duration;
+
+#else
+
+#include <stdint.h>
+
+typedef struct ligo_duration {
+    int64_t tv_sec;
+    int64_t tv_nsec;
+} ligo_duration;
+
+#endif
+
+/**
+ * @brief Find the difference between two timespecs
+ * @param t1 input time 1
+ * @param t2 input time 2
+ * @return t1 - t2
+ */
+static inline ligo_duration
+ltimespec_difference(LIGO_TIMESPEC t1, LIGO_TIMESPEC t2)
+{
+    ligo_duration results;
+    if (t2.tv_nsec > t1.tv_nsec)
+    {
+        t1.tv_nsec += 1000000000;
+        t1.tv_sec--;
+    }
+    results.tv_sec = t1.tv_sec - t2.tv_sec;
+    results.tv_nsec = t1.tv_nsec - t2.tv_nsec;
+    return results;
+}
+
+/**
+ * @brief Subtract a duration from a time returning the new time
+ * @param t0 input time
+ * @param duration amount to subtract
+ * @return t0 - duration
+ */
+static inline LIGO_TIMESPEC
+ltimespec_sub(LIGO_TIMESPEC t0, ligo_duration duration)
+{
+    LIGO_TIMESPEC results;
+    if (duration.tv_nsec > t0.tv_nsec)
+    {
+        t0.tv_nsec += 1000000000;
+        t0.tv_sec--;
+    }
+    results.tv_sec = t0.tv_sec - duration.tv_sec;
+    results.tv_nsec = t0.tv_nsec - duration.tv_nsec;
+    return results;
+}
+
+/**
+ * @brief Add two timespecs, returning the sum
+ * @param t0 input time
+ * @param duration duration to add to the time t0
+ * @return t1 + t2
+ */
+static inline LIGO_TIMESPEC
+ltimespec_add(LIGO_TIMESPEC t0, ligo_duration duration)
+{
+    LIGO_TIMESPEC results;
+    results.tv_sec = t0.tv_sec + duration.tv_sec;
+    results.tv_nsec = t0.tv_nsec + duration.tv_nsec;
+    if (results.tv_nsec >= 1000000000)
+    {
+        results.tv_nsec -= 1000000000;
+        results.tv_sec++;
+    }
+    return results;
+}
+
+#endif // DAQD_TRUNK_TIMESPEC_UTILS_H
diff --git a/src/drv/mbuf/kernel_interface_test/Makefile b/src/drv/mbuf/kernel_interface_test/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..0e52564160f8d34ad0c1955396ebdd125aeb222b
--- /dev/null
+++ b/src/drv/mbuf/kernel_interface_test/Makefile
@@ -0,0 +1,18 @@
+# obj-m specifie we're a kernel module.
+obj-m += mbuf_test.o
+mbuf_test-y := src/module.o
+
+KBUILD_EXTRA_SYMBOLS ?= $(RCG_SRC)/src/drv/mbuf/Module.symvers
+
+
+# Set the path to the Kernel build utils.
+KBUILD=/lib/modules/$(shell uname -r)/build/
+ 
+default:
+	$(MAKE) -C $(KBUILD) M=$(PWD) modules
+
+clean:
+	$(MAKE) -C $(KBUILD) M=$(PWD) clean
+
+menuconfig:
+	$(MAKE) -C $(KBUILD) M=$(PWD) menuconfig
diff --git a/src/drv/mbuf/kernel_interface_test/README.md b/src/drv/mbuf/kernel_interface_test/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..967e86754e99d1b9693d058241eeddc93a0177ff
--- /dev/null
+++ b/src/drv/mbuf/kernel_interface_test/README.md
@@ -0,0 +1,47 @@
+# kernel_interface_test
+This is a small kernel module that will test the mbuf kernel space interfaces. All you need to do to run it, is load and unload this module while `mbuf` is loaded.
+
+## Building 
+If you are building in the source tree, you need to first build the mbuf module in the directory above. You then need to define the `RCG_SRC` environmental variable so it points to your `advligorts` repository.
+
+```sh
+~/git/advligorts/src/drv/mbuf$ export RCG_SRC=~/git/advligorts/
+~/git/advligorts/src/drv/mbuf$ make #Build the mbuf module
+...
+~/git/advligorts/src/drv/mbuf$ cd kernel_interface_test/
+~/git/advligorts/src/drv/mbuf/kernel_interface_test$ make #Build the test module
+...
+~/git/advligorts/src/drv/mbuf/kernel_interface_test$ sudo insmod mbuf_test.ko; sudo rmmod mbuf_test.ko
+```
+
+If you don't want to build the `mbuf` module in the source tree you need to define `KBUILD_EXTRA_SYMBOLS` so that is points to your installed `mbuf` `Module.symvers` file.
+```sh
+~/git/advligorts/src/drv/mbuf/kernel_interface_test$ KBUILD_EXTRA_SYMBOLS=/path/to/Module.symvers make
+```
+
+
+### Getting Test Results
+You can view the test results with `dmesg`
+```sh
+sudo dmesg
+```
+#### Example Test Output
+```sh
+[44248.587289] mbuf-test: module starting tests.
+[44248.691329] Test typical_use: Passed
+[44248.700367] Test too_small_alloc: Passed
+[44248.709542] Test alloc_and_lookup: Passed
+[44249.267501] Test fill_all_areas: Passed
+[44249.267503] mbuf-test Return code messages:
+[44249.267504] mbuf-test : MBUF_KERNEL_CODE_OK :
+[44249.267505] mbuf-test : MBUF_KERNEL_CODE_NO_BUFFERS : The mbuf module does not have any more free areas for the requested buffer
+[44249.267506] mbuf-test : MBUF_KERNEL_CODE_ALLOC_FAILED : The buffer allocation failed
+[44249.267506] mbuf-test : MBUF_KERNEL_CODE_SZ_ERROR : A buffer with the name already allocated, and the requested size does not match
+[44249.267507] mbuf-test : MBUF_KERNEL_CODE_NAME_NOT_FOUND : A buffer with the requested name could not be found
+[44249.267508] mbuf-test : MBUF_KERNEL_CODE_LAST : Unsupported Error Code
+[44249.267509] Test error_lookup: Passed
+[44249.267510] mbuf-test: module unloaded from 0x0000000023f8b040
+```
+
+### A Note On Failure
+Because mbuf is a stateful module, if one test case fails it can leave the module in a bad state and successive test might fail even though there is nothing wrong with them. Find out why the first test is failing, fix that, and it might resolve all successive tests.
diff --git a/src/drv/mbuf/kernel_interface_test/src/module.c b/src/drv/mbuf/kernel_interface_test/src/module.c
new file mode 100644
index 0000000000000000000000000000000000000000..27d13212672b8109fc48ea2159fd94f13843d07b
--- /dev/null
+++ b/src/drv/mbuf/kernel_interface_test/src/module.c
@@ -0,0 +1,274 @@
+#include "../../mbuf_kernel.h"
+
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+
+//  Define the module metadata.
+#define MODULE_NAME "mbuf-test"
+
+#define EXPECTED_MAX_AREAS 64
+
+MODULE_DESCRIPTION("Module that tests the kernel space interface of mbuf");
+MODULE_AUTHOR("Ezekiel Dohmen ezekiel.dohmen@ligo.org");
+MODULE_LICENSE("Dual BSD/GPL");
+
+typedef bool (*testFunctionPtr_t)(void);
+
+void print_test_result(const char * name, testFunctionPtr_t tFunc)
+{
+    char msg[128];
+    if( tFunc() == false) 
+        strcpy(msg, "Failed");
+    else
+        strcpy(msg, "Passed");
+        
+    printk("Test %s: %s\n", name, msg);
+}
+
+
+bool typical_use( void )
+{
+    volatile void * buffer = NULL;
+    enum MBUF_KERNEL_CODE res;
+    int i;
+
+    for(i=0; i<10; ++i)
+    {
+        //Allocate buffer
+        res = mbuf_allocate_area(MODULE_NAME, 64 * 1024 * 1024, &buffer);
+        if (res != MBUF_KERNEL_CODE_OK ) return false;
+        if (buffer == NULL) return false;
+
+        //Clean Up
+        res = mbuf_release_area(MODULE_NAME);
+        if( res != MBUF_KERNEL_CODE_OK ) return false;
+    }
+
+    return true;
+}
+
+bool too_small_alloc( void )
+{
+    volatile void * buffer = NULL;
+    enum MBUF_KERNEL_CODE res;
+
+    //Allocate buffer
+    res = mbuf_allocate_area(MODULE_NAME, 64 * 1024 * 1024, &buffer);
+    if (res != MBUF_KERNEL_CODE_OK ) return false;
+    if (buffer == NULL) return false;
+
+    //Generate some size errors
+    res = mbuf_allocate_area(MODULE_NAME, 64 * 1024 * 1024 * 2, &buffer);
+    if (res != MBUF_KERNEL_CODE_SZ_ERROR) return false;
+
+    res = mbuf_allocate_area(MODULE_NAME, (62 * 1024 * 1024) , &buffer);
+    if (res != MBUF_KERNEL_CODE_SZ_ERROR) return false;
+   
+    //Clean up
+    res = mbuf_release_area(MODULE_NAME);
+    if( res != MBUF_KERNEL_CODE_OK ) return false;
+
+
+    return true;
+}
+
+
+bool alloc_and_lookup_base( size_t size )
+{
+    volatile void * buffer = NULL;
+    volatile void *  last_buffer;
+    enum MBUF_KERNEL_CODE res;
+    int i;
+
+    //Allocate buffer
+    res = mbuf_allocate_area(MODULE_NAME, size, &buffer);
+    if (res != MBUF_KERNEL_CODE_OK ) return false;
+    if (buffer == NULL) return false;
+
+    last_buffer = buffer;
+
+    for(i=0; i<1024; ++i)
+    {
+        res = mbuf_allocate_area(MODULE_NAME, size, &buffer);
+        if(buffer != last_buffer) return false;
+        last_buffer = buffer;
+    }
+
+    //Release all buffers
+    for(i=0; i<1025; ++i)
+    {
+        res = mbuf_release_area(MODULE_NAME);
+        if( res != MBUF_KERNEL_CODE_OK ) return false;
+    }
+
+    //Make sure the usage count is at 0
+    for(i=0; i<1024; ++i)
+    {
+        res = mbuf_release_area(MODULE_NAME);
+        //Expect to not find it
+        if( res != MBUF_KERNEL_CODE_NAME_NOT_FOUND ) return false;
+    }//We look here to make sure we don't change anything in the module when we miss
+
+    return true;
+}
+
+bool alloc_and_lookup( void )
+{
+    return alloc_and_lookup_base(64 * 1024 * 1024);
+}
+
+bool non_page_sz_check( void )
+{
+    return alloc_and_lookup_base(64);
+}
+
+bool fill_all_areas( void )
+{
+    char name[128];
+    volatile void * buffer = NULL;
+    enum MBUF_KERNEL_CODE res;
+    int i;
+
+    //Fill all the areas
+    for(i=0; i<EXPECTED_MAX_AREAS; ++i)
+    {
+        snprintf(name, 128, "shmem_%d", i);
+        //printk("%d, name: %s\n",i,name);
+        res = mbuf_allocate_area(name, 64 * 1024 * 1024, &buffer);
+        if (res != MBUF_KERNEL_CODE_OK ) return false;
+    }
+
+    for(i=0; i<EXPECTED_MAX_AREAS; ++i)
+    {
+        //Make sure we can't allocate any more areas
+        res = mbuf_allocate_area("shmem_9999", 64 * 1024 * 1024, &buffer);
+        if (res != MBUF_KERNEL_CODE_NO_BUFFERS ) return false;
+    }//More than once, just for fun
+
+
+    //Free all the areas
+    for(i=0; i<EXPECTED_MAX_AREAS; ++i)
+    {
+        snprintf(name, 128, "shmem_%d", i);
+        res = mbuf_release_area(name);
+        if (res != MBUF_KERNEL_CODE_OK ) return false;
+    }
+
+
+    return true;
+}
+
+
+
+bool error_lookup( void )
+{
+    char error_msg[MBUF_ERROR_MSG_ALLOC_LEN];
+
+    mbuf_lookup_error_msg( MBUF_KERNEL_CODE_OK, error_msg);
+    printk("%s Return code messages:\n", MODULE_NAME);
+    printk("%s : MBUF_KERNEL_CODE_OK : %s", MODULE_NAME, error_msg);
+
+    mbuf_lookup_error_msg( MBUF_KERNEL_CODE_NO_BUFFERS, error_msg);
+    printk("%s : MBUF_KERNEL_CODE_NO_BUFFERS : %s", MODULE_NAME, error_msg);
+
+    mbuf_lookup_error_msg( MBUF_KERNEL_CODE_ALLOC_FAILED, error_msg);
+    printk("%s : MBUF_KERNEL_CODE_ALLOC_FAILED : %s", MODULE_NAME, error_msg);
+
+    mbuf_lookup_error_msg( MBUF_KERNEL_CODE_SZ_ERROR, error_msg);
+    printk("%s : MBUF_KERNEL_CODE_SZ_ERROR : %s", MODULE_NAME, error_msg);
+
+    mbuf_lookup_error_msg( MBUF_KERNEL_CODE_NAME_NOT_FOUND, error_msg);
+    printk("%s : MBUF_KERNEL_CODE_NAME_NOT_FOUND : %s", MODULE_NAME, error_msg);
+
+    mbuf_lookup_error_msg( MBUF_KERNEL_CODE_LAST, error_msg);
+    printk("%s : MBUF_KERNEL_CODE_LAST : %s", MODULE_NAME, error_msg);
+
+
+    return true;
+}
+
+bool alloc_fill_read ( void )
+{
+    volatile void * buffer = NULL;
+    enum MBUF_KERNEL_CODE res;
+    int i;
+    size_t size = 64 * 1024 * 1024;
+    volatile unsigned char* mem;
+
+    //Allocate buffer
+    res = mbuf_allocate_area(MODULE_NAME, size, &buffer);
+    if (res != MBUF_KERNEL_CODE_OK ) return false;
+    if (buffer == NULL) return false;
+
+
+    mem = buffer;
+    unsigned char val = 0;
+    for(i=0; i<size; ++i) //Fill up buffer
+    {
+        mem[i] = val++;
+    }
+
+    //Verify nothing has changed
+    for(i=0; i<size-1; ++i)
+    {
+        if ( (mem[i+1] != mem[i] + 1) && mem[i+1] != 0)
+            return false;
+    }
+
+    //Clean Up
+    res = mbuf_release_area(MODULE_NAME);
+    if( res != MBUF_KERNEL_CODE_OK ) return false;
+    
+    return true;
+}
+
+bool alloc_1M_buffer( void )
+{
+    volatile void * buffer = NULL;
+    enum MBUF_KERNEL_CODE res;
+    size_t size = 1 * 1024 * 1024;
+
+    //Allocate buffer
+    res = mbuf_allocate_area(MODULE_NAME, size, &buffer);
+    if (res != MBUF_KERNEL_CODE_OK ) return false;
+    if (buffer == NULL) return false;
+
+    //Clean Up
+    res = mbuf_release_area(MODULE_NAME);
+    if( res != MBUF_KERNEL_CODE_OK ) return false;
+
+    return true;
+
+}
+
+static int __init test_init(void)
+{
+    pr_info("%s: module starting tests.\n", MODULE_NAME);
+
+    //Run all tests
+    print_test_result("typical_use", typical_use);
+    print_test_result("too_small_alloc", too_small_alloc);
+    print_test_result("alloc_and_lookup", alloc_and_lookup);
+    print_test_result("non_page_sz_check", non_page_sz_check);
+    print_test_result("alloc_1M_buffer", alloc_1M_buffer);
+
+
+    return 0;
+}
+
+static void __exit test_exit(void)
+{
+    print_test_result("fill_all_areas", fill_all_areas);
+    print_test_result("error_lookup", error_lookup);
+    print_test_result("alloc_fill_read", alloc_fill_read);
+
+    pr_info("%s: module unloaded from 0x%p\n", MODULE_NAME, test_exit);
+}
+
+
+
+module_init(test_init);
+module_exit(test_exit);
+
diff --git a/src/drv/mbuf/kvmem.c b/src/drv/mbuf/kvmem.c
index dc9c486bc2cb208c0347b7e895bb0a6c3a0efd14..7483c808f374eaa0f00742e133f6b4e7ba335560 100644
--- a/src/drv/mbuf/kvmem.c
+++ b/src/drv/mbuf/kvmem.c
@@ -28,159 +28,192 @@
 static __inline__ int vm_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to)
 {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
-	vma->vm_flags |= VM_RESERVED;
+    vma->vm_flags |= VM_RESERVED;
 #else
-	vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);
+    vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);
 #endif
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14)
-	return vm_insert_page(vma, from, vmalloc_to_page((void *)to));
+    return vm_insert_page(vma, from, vmalloc_to_page((void *)to));
 #else
-	return mm_remap_page_range(vma, from, kvirt_to_pa(to), PAGE_SIZE, PAGE_SHARED);
+    return mm_remap_page_range(vma, from, kvirt_to_pa(to), PAGE_SIZE, PAGE_SHARED);
 #endif
 }
 
 static __inline__ int km_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size)
 {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
-	vma->vm_flags |= VM_RESERVED;
+    vma->vm_flags |= VM_RESERVED;
 #else
-	vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);
+    vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);
 #endif
-	return mm_remap_page_range(vma, from, virt_to_phys((void *)to), size, PAGE_SHARED);
+    return mm_remap_page_range(vma, from, virt_to_phys((void *)to), size, PAGE_SHARED);
 }
 
-/* allocate user space mmapable block of memory in kernel space */
-void *rvmalloc(unsigned long size)
+/**
+ * The signedness of the size parameter to rvmalloc and rvfree is
+ * important. We have an issue if size is ever not a PAGE_SIZE multiple.
+ * When we subtract PAGE_SIZE from it in the page reservation section, 
+ * we would expect a negative result that should get us out of the loop. 
+ * But if size is unsigned that can't happen. 
+ */
+
+
+/** @brief allocate user space mmapable block of memory in kernel space
+ *
+ *  @param size The size of the buffer that should be allocated
+ *              Must be signed, see note above
+ *
+ *  @return A pointer to the allocated buffer if successful, 0 otherwise
+ */
+void *rvmalloc(long size)
 {
-	void *mem;
-	unsigned long adr;
-        
-	if ((mem = vmalloc(size))) {
-	        adr = (unsigned long)mem;
-		while (size > 0) {
-//			mem_map_reserve(virt_to_page(UVIRT_TO_KVA(adr)));
-			SetPageReserved(vmalloc_to_page((void *)adr));
-			adr  += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-	}
-	return mem;
+    void* mem;
+    char* adr;
+    
+    if (size < 1) return 0;    
+
+    if ((mem = vmalloc(size))) {
+        adr = (char*)mem;
+        while (size > 0) {
+            SetPageReserved(vmalloc_to_page((void *)adr));
+            adr  += PAGE_SIZE;
+            size -= PAGE_SIZE;
+        }
+    }
+    return mem;
 }
 
-void rvfree(void *mem, unsigned long size)
+/** @brief Frees the block of memory allocated with rvmalloc
+ *
+ *  @param mem A pointer to the block of memory you would 
+ *             like to free
+ *
+ *  @param size The size of the buffer that was allocated
+ *              Must be signed, see note above. We need this 
+ *              value so that we can free all the reserved pages
+ *              from rvmalloc(). vmalloc() will align the size to 
+ *              a page boundary, but if a non-aligned size is used
+ *              the page res/free logic will still wor.
+ *
+ *  @return Void
+ */
+void rvfree(void *mem, long size)
 {
-        unsigned long adr;
-        
-	if ((adr = (unsigned long)mem)) {
-		while (size > 0) {
-//			mem_map_unreserve(virt_to_page(UVIRT_TO_KVA(adr)));
-			ClearPageReserved(vmalloc_to_page((void *)adr));
-			adr  += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-		vfree(mem);
-	}
+    char* adr;
+    
+    if (size < 1) return;    
+
+    if ((adr = (char*)mem)) {
+        while (size > 0) {
+            ClearPageReserved(vmalloc_to_page((void *)adr));
+            adr  += PAGE_SIZE;
+            size -= PAGE_SIZE;
+        }
+        vfree(mem);
+    }
 }
 
 /* this function will map (fragment of) rvmalloc'ed memory area to user space */
 int rvmmap(void *mem, unsigned long memsize, struct vm_area_struct *vma)
 {
-	unsigned long pos, size, offset;
-	unsigned long start  = vma->vm_start;
-
-	/* this is not time critical code, so we check the arguments */
-	/* vma->vm_offset HAS to be checked (and is checked)*/
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
-		return -EFAULT;
-	}
-	offset = vma->vm_pgoff << PAGE_SHIFT;
-	size = vma->vm_end - start;
-	if ((size + offset) > memsize) {
-		return -EFAULT;
-	}
-	pos = (unsigned long)mem + offset;
-	if (pos%PAGE_SIZE || start%PAGE_SIZE || size%PAGE_SIZE) {
-		return -EFAULT;
-	}
-	while (size > 0) {
-//		if (mm_remap_page_range(vma, start, kvirt_to_pa(pos), PAGE_SIZE, PAGE_SHARED)) {
-		if (vm_remap_page_range(vma, start, pos)) {
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos   += PAGE_SIZE;
-		size  -= PAGE_SIZE;
-	}
-	return 0;
+    unsigned long pos, offset;
+    long size;
+    unsigned long start  = vma->vm_start;
+
+    /* this is not time critical code, so we check the arguments */
+    /* vma->vm_offset HAS to be checked (and is checked)*/
+    if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
+        return -EFAULT;
+    }
+    offset = vma->vm_pgoff << PAGE_SHIFT;
+    size = vma->vm_end - start;
+    if ((size + offset) > memsize) {
+        return -EFAULT;
+    }
+    pos = (unsigned long)mem + offset;
+    if (pos%PAGE_SIZE || start%PAGE_SIZE || size%PAGE_SIZE) {
+        return -EFAULT;
+    }
+    while (size > 0) {
+//      if (mm_remap_page_range(vma, start, kvirt_to_pa(pos), PAGE_SIZE, PAGE_SHARED)) {
+        if (vm_remap_page_range(vma, start, pos)) {
+            return -EAGAIN;
+        }
+        start += PAGE_SIZE;
+        pos   += PAGE_SIZE;
+        size  -= PAGE_SIZE;
+    }
+    return 0;
 }
 
 /* allocate user space mmapable block of memory in kernel space */
 void *rkmalloc(int *msize, int suprt)
 {
-	unsigned long mem, adr, size;
+    unsigned long mem, adr;
+    long size;
         
-	if (*msize <= KMALLOC_LIMIT) {
-		mem = (unsigned long)kmalloc(*msize, suprt);
-	} else {
-		mem = (unsigned long)__get_free_pages(suprt, get_order(*msize));
-	}
-	if (mem) {
-		adr  = PAGE_ALIGN(mem);
-		size = *msize -= (adr - mem);
-		while (size > 0) {
-//			mem_map_reserve(virt_to_page(adr));
-			SetPageReserved(virt_to_page(adr));
-			adr  += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-	}
-	return (void *)mem;
+    if (*msize <= KMALLOC_LIMIT) {
+        mem = (unsigned long)kmalloc(*msize, suprt);
+    } else {
+        mem = (unsigned long)__get_free_pages(suprt, get_order(*msize));
+    }
+    if (mem) {
+        adr  = PAGE_ALIGN(mem);
+        size = *msize -= (adr - mem);
+        while (size > 0) {
+//          mem_map_reserve(virt_to_page(adr));
+            SetPageReserved(virt_to_page(adr));
+            adr  += PAGE_SIZE;
+            size -= PAGE_SIZE;
+        }
+    }
+    return (void *)mem;
 }
 
-void rkfree(void *mem, unsigned long size)
+void rkfree(void *mem, long size)
 {
         unsigned long adr;
         
-	if ((adr = (unsigned long)mem)) {
-		unsigned long sz = size;
-		adr  = PAGE_ALIGN((unsigned long)mem);
-		while (size > 0) {
-//			mem_map_unreserve(virt_to_page(adr));
-			ClearPageReserved(virt_to_page(adr));
-			adr  += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-		if (sz <= KMALLOC_LIMIT) {
-			kfree(mem);
-		} else {
-			free_pages((unsigned long)mem, get_order(sz));
-		}
-	}
+    if ((adr = (unsigned long)mem)) {
+        long sz = size;
+        adr  = PAGE_ALIGN((unsigned long)mem);
+        while (size > 0) {
+//          mem_map_unreserve(virt_to_page(adr));
+            ClearPageReserved(virt_to_page(adr));
+            adr  += PAGE_SIZE;
+            size -= PAGE_SIZE;
+        }
+        if (sz <= KMALLOC_LIMIT) {
+            kfree(mem);
+        } else {
+            free_pages((unsigned long)mem, get_order(sz));
+        }
+    }
 }
 
 /* this function will map an rkmalloc'ed memory area to user space */
 int rkmmap(void *mem, unsigned long memsize, struct vm_area_struct *vma)
 {
-	unsigned long pos, size, offset;
-	unsigned long start  = vma->vm_start;
-
-	/* this is not time critical code, so we check the arguments */
-	/* vma->vm_offset HAS to be checked (and is checked)*/
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
-		return -EFAULT;
-	}
-	offset = vma->vm_pgoff << PAGE_SHIFT;
-	size = vma->vm_end - start;
-	if ((size + offset) > memsize) {
-		return -EFAULT;
-	}
-	pos = (unsigned long)mem + offset;
-	if (pos%PAGE_SIZE || start%PAGE_SIZE || size%PAGE_SIZE) {
-		return -EFAULT;
-	}
-//	if (mm_remap_page_range(vma, start, virt_to_phys((void *)pos), size, PAGE_SHARED)) {
-	if (km_remap_page_range(vma, start, pos, size)) {
-		return -EAGAIN;
-	}
-	return 0;
+    unsigned long pos, size, offset;
+    unsigned long start  = vma->vm_start;
+
+    /* this is not time critical code, so we check the arguments */
+    /* vma->vm_offset HAS to be checked (and is checked)*/
+    if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
+        return -EFAULT;
+    }
+    offset = vma->vm_pgoff << PAGE_SHIFT;
+    size = vma->vm_end - start;
+    if ((size + offset) > memsize) {
+        return -EFAULT;
+    }
+    pos = (unsigned long)mem + offset;
+    if (pos%PAGE_SIZE || start%PAGE_SIZE || size%PAGE_SIZE) {
+        return -EFAULT;
+    }
+//  if (mm_remap_page_range(vma, start, virt_to_phys((void *)pos), size, PAGE_SHARED)) {
+    if (km_remap_page_range(vma, start, pos, size)) {
+        return -EAGAIN;
+    }
+    return 0;
 }
diff --git a/src/drv/mbuf/mbuf.c b/src/drv/mbuf/mbuf.c
index 268dd7f966c8983afe7e21df0ce36d532ff0433a..7ab055ba6a8fb6746bc18445b9e306fae1dc3489 100644
--- a/src/drv/mbuf/mbuf.c
+++ b/src/drv/mbuf/mbuf.c
@@ -27,6 +27,7 @@
 #endif
 #include <asm/io.h>
 #include "mbuf.h"
+#include "mbuf_kernel.h"
 
 #include "kvmem.c"
 
@@ -66,253 +67,280 @@ static struct file_operations mbuf_fops = {
         .owner = THIS_MODULE,
 };
 
-// internal data
-// How many memory areas we will support
-#define MAX_AREAS 64
-
-// pointer to the kmalloc'd area, rounded up to a page boundary
-void *kmalloc_area[MAX_AREAS];
-
-EXPORT_SYMBOL(kmalloc_area);
 
 // To be used by the IOP to store Dolphin memory state
 int iop_rfm_valid;
 EXPORT_SYMBOL(iop_rfm_valid);
 
+
+
+//
+// Internal data
+//
+
+// Defines the max memory areas we will support
+#define MAX_AREAS 64
+
+// pointer to the kmalloc'd area, rounded up to a page boundary
+static void *kmalloc_area[MAX_AREAS];
+
 // Memory area tags (OM1, OM2, etc)
-char mtag[MAX_AREAS][MBUF_NAME_LEN + 1];
+static char mtag[MAX_AREAS][MBUF_NAME_LEN + 1];
 
 // Memory usage counters
-unsigned int usage_cnt[MAX_AREAS];
+static unsigned int usage_cnt[MAX_AREAS];
 
 // Memory area sizes
-unsigned int kmalloc_area_size[MAX_AREAS];
+static unsigned int kmalloc_area_size[MAX_AREAS];
 
+static DEFINE_SPINLOCK(lock);
 
-/* character device open method */
-static int mbuf_open(struct inode *inode, struct file *filp)
+
+/// @brief Stores the error message mapping for each MBUF_KERNEL_CODE.
+///        The number of entries here MUST match the number of MBUF_KERNEL_CODE
+///        enums defined.
+static const char error_msgs[][MBUF_ERROR_MSG_ALLOC_LEN] =
 {
-        return 0;
+    {""},
+    {"The mbuf module does not have any more free areas for the requested buffer"},
+    {"The buffer allocation failed"},
+    {"A buffer with the name already allocated, and the requested size does not match"},
+    {"A buffer with the requested name could not be found"},
+    {"Unsupported Error Code"}
+};
+
+
+
+// Attempts to lookup an allocated buffer's index by name
+// Returns the index in kmalloc_area where the buffer is located if found,
+// and -1 if no buffer with the requested name was found.
+// This is an internal helper function, the caller MUST
+// acquire lock before calling this function
+static int find_mbuf_index(const char * name)
+{
+    int i =0;
+    for (i = 0; i < MAX_AREAS; i++) {
+        if (0 == strcmp (mtag[i], name)) {
+            return i;
+        }
+    }
+    return -1;
 }
 
-static DEFINE_SPINLOCK(lock);
 
-int mbuf_release_area(char *name, struct file *file) {
-	int i;
+void mbuf_lookup_error_msg( enum MBUF_KERNEL_CODE code, char* error_msg)
+{
+    int err_indx;
+    if(code < MBUF_KERNEL_CODE_OK || code >= MBUF_KERNEL_CODE_LAST)
+        err_indx = MBUF_KERNEL_CODE_LAST;
 
-	if ((int)atomic_read(&mbuf_verbosity) > 0) {
-        printk(KERN_INFO
-        " mbuf_release_area %s\n", name);
+    strncpy(error_msg, error_msgs[code], MBUF_ERROR_MSG_MAX_LEN);
+
+    return;
+}
+EXPORT_SYMBOL(mbuf_lookup_error_msg);
+
+
+enum MBUF_KERNEL_CODE mbuf_release_area_file(const char* name, struct file *file) 
+{
+    //Attempt to release the buffer
+    enum MBUF_KERNEL_CODE ret = mbuf_release_area(name);
+
+    //If the release is good, clear out the file private data
+    if(ret == MBUF_KERNEL_CODE_OK){
+        if (file) {
+            file->private_data = 0;
+        }
     }
-	spin_lock(&lock);
-	// See if allocated
-	for (i = 0; i < MAX_AREAS; i++) {
-		if (0 == strcmp (mtag[i], name)) {
-		// Found the area
-		usage_cnt[i]--;
-		if (usage_cnt[i] <= 0 ){
-				mtag[i][0] = 0;
-				usage_cnt[i] = 0;
-				if (file) file->private_data = 0;
-				rvfree(kmalloc_area[i], kmalloc_area_size[i]);
-				kmalloc_area[i] = 0;
-				kmalloc_area_size[i] = 0;
-			}
-			spin_unlock(&lock);
-			return 0;
-		}
-	}
-	spin_unlock(&lock);
-        return -1;
+    return ret;
 }
 
-EXPORT_SYMBOL(mbuf_release_area);
+enum MBUF_KERNEL_CODE mbuf_release_area(const char* name) 
+{
+    int i, verbose;
 
-// Returns index of allocated area
-// -1 if no slots
-// This is an internal helper function, the caller MUST
-// acquire lock before calling this function
-static int _mbuf_allocate_area_safe(char *name, int size) {
-    int i, s;
+    verbose = (int)atomic_read(&mbuf_verbosity);
 
-    // See if already allocated
+    spin_lock(&lock);
+    // See if allocated
     for (i = 0; i < MAX_AREAS; i++) {
         if (0 == strcmp (mtag[i], name)) {
-            // Found the area, make sure it is big enough
-            if (kmalloc_area_size[i] < size) {
-                return -1;
+            // Found the area
+            usage_cnt[i]--;
+            if (usage_cnt[i] <= 0 ){
+                mtag[i][0] = 0;
+                usage_cnt[i] = 0;
+                rvfree(kmalloc_area[i], kmalloc_area_size[i]);
+                kmalloc_area[i] = 0;
+                kmalloc_area_size[i] = 0;
             }
-            usage_cnt[i]++;
-            return i;
+            spin_unlock(&lock);
+            if(verbose) printk(KERN_INFO " mbuf_release_area - released buffer %s\n", name);
+            return MBUF_KERNEL_CODE_OK;
         }
     }
 
+    //We only get here if we don't find the buffer
+    spin_unlock(&lock);
+    if(verbose) printk(KERN_INFO " mbuf_release_area - %s could not be found\n", name);
+    return MBUF_KERNEL_CODE_NAME_NOT_FOUND;
+}
+EXPORT_SYMBOL(mbuf_release_area);
+
+
+int mbuf_allocate_area_file(const char* name, unsigned int size, struct file *file)
+{
+    enum MBUF_KERNEL_CODE ret;
+    volatile void * buffer_ptr;
+    int buffer_index;
+
+    //Try to allocate buffer
+    ret = mbuf_allocate_area(name, size, &buffer_ptr);
+    if(ret != MBUF_KERNEL_CODE_OK) return -1;
+
+    //Get the index of the buffer we just created
+    spin_lock(&lock);
+    buffer_index = find_mbuf_index(name);
+    spin_unlock(&lock);
+    if( buffer_index < 0) return -1;
+
+    if (file) file -> private_data = mtag [buffer_index];
+
+    return buffer_index;
+}
+
+
+// Returns pointer to buffer allocated, or 0 (NULL) if there was an error.
+// 0x0 if no slots
+enum MBUF_KERNEL_CODE mbuf_allocate_area(const char *name, unsigned int size, volatile void ** buffer_ptr) {
+    int i, verbose;
+    int mod;
+
+    verbose = (int)atomic_read(&mbuf_verbosity);
+
+    spin_lock(&lock);
+
+    //Round up the requested size to the closest page size
+    mod = size % PAGE_SIZE;
+    if (mod != 0) {
+        size += PAGE_SIZE - mod;
+    }
+
+
+    // See if we already have a buffer with the name
+    i = find_mbuf_index(name);
+    if (i >= 0)
+    {
+        if (kmalloc_area_size[i] != size) {
+            *buffer_ptr = NULL;
+            spin_unlock(&lock);
+            return MBUF_KERNEL_CODE_SZ_ERROR;
+        }
+
+        ++usage_cnt[i];
+        *buffer_ptr = kmalloc_area[i];
+        spin_unlock(&lock);
+        if(verbose) printk(KERN_INFO " mbuf_allocate_area - increased usage count of %s\n", name);
+        return MBUF_KERNEL_CODE_OK;
+    }
+
+    
     // Find first free slot
     for (i = 0; i < MAX_AREAS; i++) {
         if (kmalloc_area[i] == 0) break;
     }
-
+    
     // Out of slots
     if (i >= MAX_AREAS) {
-        return -1;
+        *buffer_ptr = NULL;
+        spin_unlock(&lock);
+        if(verbose){
+            printk(KERN_INFO " mbuf_allocate_area - Could not create "
+                             "buffer : %s, out of free slots\n", name);
+        }
+        return MBUF_KERNEL_CODE_NO_BUFFERS;
     }
 
-    s = size;
     kmalloc_area[i] = 0;
-    kmalloc_area[i] = rvmalloc (size); //rkmalloc (&s, GFP_KERNEL);
+    kmalloc_area[i] = rvmalloc (size); 
 
-    //printk("rvmalloc() returned %p\n", kmalloc_area[i]);
-    //printk("rkmalloc() returned %p %d\n", kmalloc_area[i], s);
-    //rkfree(kmalloc_area[i], s);
-    //kmalloc_area[i] = 0;
     if (kmalloc_area[i] == 0) {
+        *buffer_ptr = NULL;
+        spin_unlock(&lock);
         printk("malloc() failed\n");
-        return -1;
+        return MBUF_KERNEL_CODE_ALLOC_FAILED;
     }
-    if (one_fill) memset(kmalloc_area[i], 0xff, size);
 
+    //1 fill if the allocation was good, and we are configured to do so
+    if (one_fill) memset(kmalloc_area[i], 0xff, size);
 
     kmalloc_area_size[i] = size;
     strncpy(mtag[i], name, MBUF_NAME_LEN);
     mtag[i][MBUF_NAME_LEN] = 0;
     usage_cnt[i] = 1;
-    return i;
-}
-
-// Returns index of allocated area
-// -1 if no slots
-int mbuf_allocate_area_safe(char *name, int size, struct file *file) {
-    int result = -1;
-
-    if (!name || size <= 0) return result;
-
-    spin_lock(&lock);
-    result = _mbuf_allocate_area_safe(name, size);
-    if (result >= 0 && file) {
-        file -> private_data = mtag[result];
-    }
+    *buffer_ptr = kmalloc_area[i];
     spin_unlock(&lock);
-
-    return result;
-}
-
-// Returns index of allocated area
-// -1 if no slots
-int mbuf_allocate_area(char *name, int size, struct file *file) {
-	int i, s;
-
-	spin_lock(&lock);
-	// See if already allocated
-	for (i = 0; i < MAX_AREAS; i++) {
-		if (0 == strcmp (mtag[i], name)) {
-			// Found the area
-			usage_cnt[i]++;
-               		if (file) file -> private_data = mtag [i];
-			spin_unlock(&lock);
-			return i;
-		}
-	}
-	
-	// Find first free slot
-	for (i = 0; i < MAX_AREAS; i++) {
-		if (kmalloc_area[i] == 0) break;
-	}
-	
-	// Out of slots
-	if (i >= MAX_AREAS) {
-		spin_unlock(&lock);
-		return -1;
-	}
-
-	s = size;
-	kmalloc_area[i] = 0;
-	kmalloc_area[i] = rvmalloc (size); //rkmalloc (&s, GFP_KERNEL);
-	if (one_fill) memset(kmalloc_area[i], 0xff, size);
-
-	//printk("rvmalloc() returned %p\n", kmalloc_area[i]);
-	//printk("rkmalloc() returned %p %d\n", kmalloc_area[i], s);
-	//rkfree(kmalloc_area[i], s);
-	//kmalloc_area[i] = 0;
-	if (kmalloc_area[i] == 0) {
-        spin_unlock(&lock);
-        printk("malloc() failed\n");
-	       	return -1;
-	}
-
-	kmalloc_area_size[i] = size;
-	strncpy(mtag[i], name, MBUF_NAME_LEN);
-	mtag[i][MBUF_NAME_LEN] = 0;
-	usage_cnt[i] = 1;
-        if (file) file -> private_data = mtag [i];
-	spin_unlock(&lock);
-        return i;
+    if(verbose) printk(KERN_INFO " mbuf_allocate_area - Created new buffer %s, sz: %u\n", name, size);
+    return MBUF_KERNEL_CODE_OK;
 }
 
 EXPORT_SYMBOL(mbuf_allocate_area);
 
+/* character device open method */
+static int mbuf_open(struct inode *inode, struct file *filp)
+{
+        return 0;
+}
+
 /* character device last close method */
 static int mbuf_release(struct inode *inode, struct file *filp)
 {
-	char *name;
-        if (filp -> private_data == 0) return 0;
-	name = (char *) filp -> private_data;
-	mbuf_release_area(name, filp);
-        return 0;
+    char *name;
+    if (filp -> private_data == 0) return 0;
+    name = (char *) filp -> private_data;
+    mbuf_release_area_file(name, filp);
+    return 0;
 }
 
 // helper function, mmap's the kmalloc'd area which is physically contiguous
 int mmap_kmem(unsigned int i, struct vm_area_struct *vma)
 {
-        long length = vma->vm_end - vma->vm_start;
+    long length = vma->vm_end - vma->vm_start;
 
-	if (kmalloc_area_size[i] < length) {
-		//printk("mbuf mmap() request to map 0x%lx bytes; allocated 0x%lx\n", length, kmalloc_area_size[i]);
-		return -EINVAL;
-	}
-	//printk("mbuf mmap() length is 0x%lx\n", length);
-
-	return rvmmap(kmalloc_area[i], length, vma);
+    if (kmalloc_area_size[i] < length) {
+        //printk("mbuf mmap() request to map 0x%lx bytes; allocated 0x%lx\n", length, kmalloc_area_size[i]);
+        return -EINVAL;
+    }
+    //printk("mbuf mmap() length is 0x%lx\n", length);
 
-#if 0
-        /* map the whole physically contiguous area in one piece */
-        if ((ret = remap_pfn_range(vma,
-                                   vma->vm_start,
-                                   ((unsigned int )(kmalloc_area[i])) >> PAGE_SHIFT,
-                                   length,
-                                   vma->vm_page_prot)) < 0) {
-                return ret;
-        }
-        
-        return 0;
-#endif
+    return rvmmap(kmalloc_area[i], length, vma);
 }
 
 /* character device mmap method */
 static int mbuf_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	int i;
-	char *name;
+    int i;
+    char *name;
 
-        if (file -> private_data == 0) return -EINVAL;
-	name = (char *) file -> private_data;
-	// Find our memory area
-        for (i = 0; i < MAX_AREAS; i++) {
-             if (0 == strcmp (mtag[i], name)) {
-		return mmap_kmem (i, vma);
-	     }
-	}
-	return -EINVAL;
+    if (file -> private_data == 0) return -EINVAL;
+    name = (char *) file -> private_data;
+    // Find our memory area
+    for (i = 0; i < MAX_AREAS; i++) {
+        if (0 == strcmp (mtag[i], name)) {
+            return mmap_kmem (i, vma);
+        }
+    }
+    return -EINVAL;
 }
 
 
 
 static long mbuf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	int res;
-    int mod = 0;
-	int verbose = 0;
+    int res;
+    int verbose = 0;
     struct mbuf_request_struct req;
-        void __user *argp = (void __user *)arg;
+    void __user *argp = (void __user *)arg;
 
     verbose = (int)atomic_read(&mbuf_verbosity);
 
@@ -322,81 +350,73 @@ static long mbuf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
     }
     switch(cmd){
     case IOCTL_MBUF_ALLOCATE:
-		{
-          if (copy_from_user (&req, (void *) argp, sizeof (req))) {
-			return -EFAULT;
-		  }
-          // the size should be a multiple of page size
-          mod = req.size % PAGE_SIZE;
-          if (mod != 0) {
-              req.size += PAGE_SIZE - mod;
-          }
-          if (verbose > 0) {
-              printk(KERN_INFO
-              "mbuf_ioctl: name:%.32s, size:%d, cmd:%d, file:%p\n", req.name, (int) req.size, cmd, file);
-          }
-		  res = mbuf_allocate_area(req.name, req.size, file);
-		  if (res >= 0) {
-			return kmalloc_area_size[res];
-		  } else {
-			return -EINVAL;
-		  }
-		}
-		break;
+    {
+        if (copy_from_user (&req, (void *) argp, sizeof (req))) {
+            return -EFAULT;
+        }
+        if (verbose > 0) {
+            printk(KERN_INFO
+            "mbuf_ioctl: name:%.32s, size:%d, cmd:%d, file:%p\n", req.name, (int) req.size, cmd, file);
+        }
+        res = mbuf_allocate_area_file(req.name, req.size, file);
+        if (res < 0) return -EINVAL; //If there was an issue
+        return kmalloc_area_size[res];
+    }
+    break;
     case IOCTL_MBUF_DEALLOCATE:
-		{
-        	  if (copy_from_user (&req, (void *) argp, sizeof (req))) {
-			return -EFAULT;
-		  }
-          //printk("mbuf_ioctl: name:%.32s, size:%d, cmd:%d, file:%p\n", req.name, req.size, cmd, file);
-		  res = mbuf_release_area(req.name, file);
-		  if (res >= 0) {
-			return  0;
-		  } else {
-			return -EINVAL;
-		  }
-		} 
-                break;
+    {
+        if (copy_from_user (&req, (void *) argp, sizeof (req))) {
+            return -EFAULT;
+        }
+        //printk("mbuf_ioctl: name:%.32s, size:%d, cmd:%d, file:%p\n", req.name, req.size, cmd, file);
+        res = mbuf_release_area_file(req.name, file);
+        if (res == MBUF_KERNEL_CODE_OK) {
+            return  0;
+        } else {
+            return -EINVAL;
+        }
+    } 
+    break;
 
     case IOCTL_MBUF_INFO:
 #if 0
-		for (i = 0; i < MAX_AREAS; i++) {
-			if (kmalloc_area[i]) {
-        		  printk("mbuf %d: name:%.32s, size:%d, usage:%d\n",
-				 i, mtag[i], kmalloc_area_size[i], usage_cnt[i]);
-			}
-		}
+        for (i = 0; i < MAX_AREAS; i++) {
+            if (kmalloc_area[i]) {
+                  printk("mbuf %d: name:%.32s, size:%d, usage:%d\n",
+                 i, mtag[i], kmalloc_area_size[i], usage_cnt[i]);
+            }
+        }
 #endif
                 return 1;
-		break;
-        default:		
-                return -EINVAL;
+    break;
+    default:        
+        return -EINVAL;
     }
     return -EINVAL;
 }
 
 static ssize_t mbuf_sysfs_status(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
-	size_t remaining = PAGE_SIZE;
-	size_t count = 0;
-	size_t tmp = 0;
-	char *cur = buf;
-	int i = 0;
-
-	spin_lock(&lock);
-
-	for (i = 0; i < MAX_AREAS; i++) {
-		if (kmalloc_area[i] == 0) continue;
-		tmp = snprintf(cur, remaining, "%s: %d %d\n", mtag[i], kmalloc_area_size[i], usage_cnt[i]);
-		if (tmp > remaining)
-			break;
-		cur += tmp;
-		remaining -= tmp;
-		count += tmp;
-	}
-
-	spin_unlock(&lock);
-
-	return count;
+    size_t remaining = PAGE_SIZE;
+    size_t count = 0;
+    size_t tmp = 0;
+    char *cur = buf;
+    int i = 0;
+
+    spin_lock(&lock);
+
+    for (i = 0; i < MAX_AREAS; i++) {
+        if (kmalloc_area[i] == 0) continue;
+        tmp = snprintf(cur, remaining, "%s: %d %d\n", mtag[i], kmalloc_area_size[i], usage_cnt[i]);
+        if (tmp > remaining)
+            break;
+        cur += tmp;
+        remaining -= tmp;
+        count += tmp;
+    }
+
+    spin_unlock(&lock);
+
+    return count;
 }
 
 static ssize_t mbuf_sysfs_verbosity_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {
@@ -435,68 +455,68 @@ static struct kobj_attribute sysfs_mbuf_verbosity_attr = __ATTR(verbosity, 0644,
 
 /* group attributes together for bulk operations */
 static struct attribute *mbuf_fields[] = {
-		&sysfs_mbuf_status_attr.attr,
-		&sysfs_mbuf_verbosity_attr.attr,
-		NULL,
+        &sysfs_mbuf_status_attr.attr,
+        &sysfs_mbuf_verbosity_attr.attr,
+        NULL,
 };
 
 static struct attribute_group mbuf_attr_group = {
-		.attrs = mbuf_fields,
+        .attrs = mbuf_fields,
 };
 
 /* module initialization - called at module load time */
 static int __init mbuf_init(void)
 {
-	int i;
-        int ret = -EINVAL;
+    int i;
+    int ret = -EINVAL;
 
-        /* get the major number of the character device */
-        if ((ret = alloc_chrdev_region(&mbuf_dev, 0, 1, "mbuf")) < 0) {
-                printk(KERN_ERR "could not allocate major number for mbuf\n");
-                goto out;
-        }
+    /* get the major number of the character device */
+    if ((ret = alloc_chrdev_region(&mbuf_dev, 0, 1, "mbuf")) < 0) {
+            printk(KERN_ERR "could not allocate major number for mbuf\n");
+            goto out;
+    }
 
-        if (IS_ERR(mbuf_class = class_create( THIS_MODULE, "ligo_mbuf" )))
-        {
-                printk(KERN_ERR "could not allocate device class for mbuf\n");
-                goto out_unalloc_region;
-        };
+    if (IS_ERR(mbuf_class = class_create( THIS_MODULE, "ligo_mbuf" )))
+    {
+            printk(KERN_ERR "could not allocate device class for mbuf\n");
+            goto out_unalloc_region;
+    };
 
-        if (IS_ERR(mbuf_device = device_create( mbuf_class, NULL, mbuf_dev, NULL, "mbuf" )))
-        {
-                printk(KERN_ERR "could not create device file for mbuf\n");
-                goto out_cleanup_class;
-        }
+    if (IS_ERR(mbuf_device = device_create( mbuf_class, NULL, mbuf_dev, NULL, "mbuf" )))
+    {
+            printk(KERN_ERR "could not create device file for mbuf\n");
+            goto out_cleanup_class;
+    }
 
-        /* initialize the device structure and register the device with the kernel */
-        cdev_init(&mbuf_cdev, &mbuf_fops);
-        if ((ret = cdev_add(&mbuf_cdev, mbuf_dev, 1)) < 0) {
-                printk(KERN_ERR "could not allocate chrdev for buf\n");
-                goto out_cleanup_device;
-        }
+    /* initialize the device structure and register the device with the kernel */
+    cdev_init(&mbuf_cdev, &mbuf_fops);
+    if ((ret = cdev_add(&mbuf_cdev, mbuf_dev, 1)) < 0) {
+            printk(KERN_ERR "could not allocate chrdev for buf\n");
+            goto out_cleanup_device;
+    }
+
+    mbuf_sysfs_dir = kobject_create_and_add("mbuf", kernel_kobj);
+    if (mbuf_sysfs_dir == NULL) {
+        printk(KERN_ERR "Could not create /sys/kernel/mbuf directory!\n");
+        goto out_unalloc_region;
+    }
 
-	mbuf_sysfs_dir = kobject_create_and_add("mbuf", kernel_kobj);
-	if (mbuf_sysfs_dir == NULL) {
-		printk(KERN_ERR "Could not create /sys/kernel/mbuf directory!\n");
-		goto out_unalloc_region;
-	}
-
-	if (sysfs_create_group(mbuf_sysfs_dir, &mbuf_attr_group) != 0) {
-		printk(KERN_ERR "Could not create /sys/kernel/mbuf/... fields!\n");
-		goto out_remove_sysfs;
-	}
-
-	// Init local data structs
-	for ( i = 0; i < MAX_AREAS; i++) {
-		kmalloc_area[i] = 0;
-		mtag[i][0] = 0;
-		usage_cnt[i] = 0;
-	}
-	ret = 0;
-	return ret;
+    if (sysfs_create_group(mbuf_sysfs_dir, &mbuf_attr_group) != 0) {
+        printk(KERN_ERR "Could not create /sys/kernel/mbuf/... fields!\n");
+        goto out_remove_sysfs;
+    }
+
+    // Init local data structs
+    for ( i = 0; i < MAX_AREAS; i++) {
+        kmalloc_area[i] = 0;
+        mtag[i][0] = 0;
+        usage_cnt[i] = 0;
+    }
+    ret = 0;
+    return ret;
 
   out_remove_sysfs:
-	kobject_del(mbuf_sysfs_dir);
+    kobject_del(mbuf_sysfs_dir);
   out_cleanup_device:
         device_destroy( mbuf_class, mbuf_dev );
   out_cleanup_class:
@@ -515,9 +535,9 @@ static void __exit mbuf_exit(void)
         /* remove the character deivce */
         cdev_del(&mbuf_cdev);
         unregister_chrdev_region(mbuf_dev, 1);
-	if (mbuf_sysfs_dir != NULL) {
-		kobject_del(mbuf_sysfs_dir);
-	}
+    if (mbuf_sysfs_dir != NULL) {
+        kobject_del(mbuf_sysfs_dir);
+    }
 }
 
 module_init(mbuf_init);
diff --git a/src/drv/mbuf/mbuf.h b/src/drv/mbuf/mbuf.h
index e9153015afc3dc3884fa023bd83ff733bc91733d..4e8c5ab5e15cbe66da818e29a800752f64f0524e 100644
--- a/src/drv/mbuf/mbuf.h
+++ b/src/drv/mbuf/mbuf.h
@@ -1,3 +1,11 @@
+#ifndef LIGO_MBUF_H
+#define LIGO_MBUF_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdio.h> //size_t
+#endif
 
 // Maximum length of memory buffer tag
 #define MBUF_NAME_LEN 32
@@ -16,4 +24,4 @@ struct mbuf_request_struct{
 // Kill a buffer 
 #define IOCTL_MBUF_DEALLOCATE _IOW(0,2,struct mbuf_request_struct)
 
-
+#endif //LIGO_MBUF_H
diff --git a/src/drv/mbuf/mbuf_kernel.h b/src/drv/mbuf/mbuf_kernel.h
new file mode 100644
index 0000000000000000000000000000000000000000..18fbe132c92ba9378f229de610aece0db3e325bb
--- /dev/null
+++ b/src/drv/mbuf/mbuf_kernel.h
@@ -0,0 +1,72 @@
+#ifndef LIGO_MBUF_KERNEL_H
+#define LIGO_MBUF_KERNEL_H
+/** @brief This header is for the kernel module to mbuf, kernel 
+ *        space interface. Mbuf exports the below symbols.
+ */
+
+/** Used by the IOP to store Dolphin memory state */
+extern int iop_rfm_valid;
+
+/** @brief This enum defines all possible error codes that can be
+ *        returned by the kernel interface. You can use mbuf_lookup_error_msg()
+ *        to retrieve a string version of the error code.
+ */
+enum MBUF_KERNEL_CODE
+{
+    MBUF_KERNEL_CODE_OK = 0,
+    MBUF_KERNEL_CODE_NO_BUFFERS = 1,
+    MBUF_KERNEL_CODE_ALLOC_FAILED = 2,
+    MBUF_KERNEL_CODE_SZ_ERROR = 3,
+    MBUF_KERNEL_CODE_NAME_NOT_FOUND = 4,
+    MBUF_KERNEL_CODE_LAST 
+};
+
+/** A buffer of MBUF_ERROR_MSG_ALLOC_LEN must be passed as the second argument to mbuf_lookup_error_msg(...) */
+#define MBUF_ERROR_MSG_MAX_LEN 128
+#define MBUF_ERROR_MSG_ALLOC_LEN (MBUF_ERROR_MSG_MAX_LEN+1)
+
+/** @brief Requests that a shared memory buffer be allocated with the name requested.
+ *         If a buffer already exists with the requested name, then a pointer to that 
+ *         buffer is returned. If the buffer does not exist, it is allocated and 
+ *         a pointer to it returned.  
+ *         
+ *  @param name The name of the shared memory buffer to create/lookup
+ *         
+ *  @param size The size (in bytes) of the buffer to create/lookup
+ *
+ *  @param buffer_ptr The address of a pointer where the shared buffer's address
+ *                    should be written
+ *         
+ *  @return MBUF_KERNEL_CODE_OK : no errors were encountered
+ *          MBUF_KERNEL_CODE_NO_BUFFERS : mbuf is out of shared buffer spaces and cannot you a new one
+ *          MBUF_KERNEL_CODE_ALLOC_FAILED : The system call to allocate memory failed, check the size you 
+ *                                          are requesting, or the system might be out of memory
+ *          MBUF_KERNEL_CODE_SZ_ERROR : Returned if the size used to lookup a buffer does not match
+ *                                      the size used in the first allocation for the buffer of that name
+ */
+enum MBUF_KERNEL_CODE mbuf_allocate_area(const char *name, unsigned int size, volatile void ** buffer_ptr);
+
+/** @brief Releases the callers used of the shared memory. When all users of a shared buffer
+ *         have released it, this function will free the memory on the last release.
+ *         
+ *  @param name The name of the shared memory buffer to release
+ *         
+ *  @return MBUF_KERNEL_CODE_OK : no errors were encountered
+ *          MBUF_KERNEL_CODE_NAME_NOT_FOUND : A shared buffer with the given name was not found
+ */
+enum MBUF_KERNEL_CODE mbuf_release_area(const char *name);
+
+/** @brief Allows callers to lookup error messages from their returned error codes
+ *         Useful for error messages
+ *
+ *  @param code The error code that should be looked up
+ *         
+ *  @param error_msg A buffer for the retrieved error code to be written. Should have at
+ *                   least MBUF_ERROR_MSG_ALLOC_LEN bytes allocated for it
+ *         
+ *  @return Void.
+ */
+void mbuf_lookup_error_msg( enum MBUF_KERNEL_CODE code, char* error_msg);
+
+#endif // LIGO_MBUF_KERNEL_H
+
diff --git a/src/drv/mbuf/mbuf_probe/mbuf_probe.cc b/src/drv/mbuf/mbuf_probe/mbuf_probe.cc
index 80c385de6464c6dfa22f58a2213d9d86c886184d..11c7ad8ee4997b4c57cd7148436689802a671988 100644
--- a/src/drv/mbuf/mbuf_probe/mbuf_probe.cc
+++ b/src/drv/mbuf/mbuf_probe/mbuf_probe.cc
@@ -255,10 +255,11 @@ parse_options( int argc, char* argv[] )
 };
 
 void
-shmem_inc_segment_count( const char* sys_name )
+shmem_inc_segment_count( const char* sys_name, size_t buf_sz_mb )
 {
     int    fd = -1;
     size_t name_len = 0;
+    int ret1, ret2;
 
     if ( !sys_name )
         return;
@@ -274,10 +275,20 @@ shmem_inc_segment_count( const char* sys_name )
         return;
     }
     struct mbuf_request_struct req;
-    req.size = 1;
+    req.size = buf_sz_mb * 1024 * 1024;
     strcpy( req.name, sys_name );
-    ioctl( fd, IOCTL_MBUF_ALLOCATE, &req );
-    ioctl( fd, IOCTL_MBUF_ALLOCATE, &req );
+    //When we close the fd, our shmem will get cleaned up once
+    //so we call IOCTL_MBUF_ALLOCATE 2 times so one stays open
+    ret1 = ioctl( fd, IOCTL_MBUF_ALLOCATE, &req ); 
+    ret2 = ioctl( fd, IOCTL_MBUF_ALLOCATE, &req );
+
+    if(ret1 < req.size || ret2 < req.size)
+    {
+        fprintf( stderr, "Couldn't lookup the already allocated buffer "
+                         "(%s) to increase the usage count.\n", sys_name);
+    }
+
+
     close( fd );
 }
 
@@ -303,7 +314,10 @@ shmem_dec_segment_count( const char* sys_name )
     struct mbuf_request_struct req;
     req.size = 1;
     strcpy( req.name, sys_name );
-    ioctl( fd, IOCTL_MBUF_DEALLOCATE, &req );
+    if(ioctl( fd, IOCTL_MBUF_DEALLOCATE, &req ) != 0)
+    {
+        fprintf( stderr, "There was an issue decrementing the use count of the %s shmem.\n", sys_name);
+    }
     close( fd );
 }
 
@@ -472,7 +486,7 @@ main( int argc, char* argv[] )
                       << opts.buffer_name << "\n";
             return 1;
         }
-        shmem_inc_segment_count( opts.buffer_name.c_str( ) );
+        shmem_inc_segment_count( opts.buffer_name.c_str( ),  opts.buffer_size_mb );
         break;
     }
     case COPY:
diff --git a/src/drv/mbuf/userapace_test/CMakeLists.txt b/src/drv/mbuf/userapace_test/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9fa33b3f01228f35c4bf883accad6b2562853bd8
--- /dev/null
+++ b/src/drv/mbuf/userapace_test/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(this_target mbuf_userspace_utest)
+
+add_executable(${this_target}
+        test.cc)
+
+target_include_directories(mbuf_probe PRIVATE
+        ${CMAKE_CURRENT_SOURCE_DIR}/..
+        )
+
+add_test(NAME "mbuf_userspace_utest"
+            COMMAND mbuf_userspace_utest
+            WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+
+#target_requires_cpp11(mbuf_probe PRIVATE)
+
+#install(TARGETS mbuf_probe DESTINATION bin)
diff --git a/src/drv/mbuf/userapace_test/test.cc b/src/drv/mbuf/userapace_test/test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a7f33b223bd508c562645323a7a20361b26cec63
--- /dev/null
+++ b/src/drv/mbuf/userapace_test/test.cc
@@ -0,0 +1,160 @@
+#include "../mbuf.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define EXPECTED_MAX_AREAS 64
+
+void typical_use( )
+{
+    int fd, i;
+    size_t len = 64 * 1024 * 1024;
+    long buf_len;
+    volatile void* mapped_buf;
+    struct mbuf_request_struct req = {len, "c_test_buffer"};
+
+    if ((fd = open ("/dev/mbuf", O_RDWR | O_SYNC)) < 0) {
+        perror ("open");
+        exit(-1);
+    }
+
+    //buf_len = ioctl (fd, IOCTL_MBUF_ALLOCATE, &req);
+    buf_len = ioctl (fd, IOCTL_MBUF_ALLOCATE, &req);
+    if(buf_len < len) exit(-1);
+
+    mapped_buf = (volatile void*)mmap( 0,
+                                     buf_len,
+                                     PROT_READ | PROT_WRITE,
+                                     MAP_SHARED,
+                                     fd,
+                                     0 );
+
+    if ( mapped_buf == MAP_FAILED ) exit(-1);
+
+
+    volatile unsigned char* mem = (volatile unsigned char*) mapped_buf;
+    unsigned char val = 0;
+    for(i=0; i<len; ++i) //Fill up buffer
+    {
+        mem[i] = val++;
+    }
+
+    //Verify nothing has changed
+    for(i=0; i<len-1; ++i)
+    {
+        if ( (mem[i+1] != mem[i] + 1) && mem[i+1] != 0)
+            exit(-1);
+    }
+
+
+    //Clean up
+    if (munmap( (void*)( mapped_buf ), buf_len ) != 0) exit(-1);
+    close(fd);
+
+}
+
+void fill_all_areas()
+{
+    int fds[EXPECTED_MAX_AREAS+1];
+    size_t len = 64 * 1024 * 1024;
+    long buf_len;
+    int i;
+    volatile void* mapped_buffers[EXPECTED_MAX_AREAS+1];
+
+    struct mbuf_request_struct req = {len, "" };
+    
+
+
+
+    //Fill all the areas
+    for(i=0; i<EXPECTED_MAX_AREAS; ++i)
+    {
+        if ((fds[i] = open ("/dev/mbuf", O_RDWR | O_SYNC)) < 0) {
+            perror ("open");
+            exit(-1);
+        }
+
+        snprintf(req.name, MBUF_NAME_LEN+1, "shmem_%d", i);
+        buf_len = ioctl (fds[i], IOCTL_MBUF_ALLOCATE, &req);
+        //printf("%d, name: %s, ret: %d\n",i, req.name, buf_len);
+        if(buf_len < (long)len)
+        {
+            printf("Error: Could not allocate all the buffers, failed at buffer %s\n", req.name);
+            exit(-1);
+        }
+
+        mapped_buffers[i] = (volatile void*)mmap( 0,
+                                     buf_len,
+                                     PROT_READ | PROT_WRITE,
+                                     MAP_SHARED,
+                                     fds[i],
+                                     0 );
+
+        //printf("mapped_buffers[%d] : %p\n", i, mapped_buffers[i]);
+        if ( mapped_buffers[i] == MAP_FAILED )
+        { 
+            printf("Error: i: %d - Could not map all the buffers.\n", i);
+            exit(-1);
+        }
+    }
+
+    //
+    //We are full, make sure this one fails!
+    if ((fds[i] = open ("/dev/mbuf", O_RDWR | O_SYNC)) < 0) {
+            perror ("open");
+            exit(-1);
+    }
+    snprintf(req.name, MBUF_NAME_LEN+1, "shmem_%d", i);
+    buf_len = ioctl (fds[i], IOCTL_MBUF_ALLOCATE, &req);
+    //printf("%d, name: %s, ret: %d\n",i, req.name, buf_len);
+    if (buf_len >= 0)
+    {
+        printf("Error; Did not fail where expected! ret: %d\n", buf_len);
+        exit(-1); 
+    }
+
+
+
+
+    //Clean up
+    for(i=0; i<EXPECTED_MAX_AREAS; ++i)
+    {
+        //Clean up
+        if (munmap( (void*)( mapped_buffers[i] ), len ) != 0) exit(-1);
+        close(fds[i]);
+    }
+
+
+
+
+
+
+}
+
+
+// Returns 0 if all tests pass
+//
+//
+int main()
+{
+    typical_use();
+    fill_all_areas();
+
+    return 0;
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/drv/python/ligo_shmem.cc b/src/drv/python/ligo_shmem.cc
index 99cf29e25ef23c195fa081683c115a687da202e4..b137b48272cd47b156c79b932a1a35a969b4a23d 100644
--- a/src/drv/python/ligo_shmem.cc
+++ b/src/drv/python/ligo_shmem.cc
@@ -27,6 +27,11 @@ namespace
         Shmem objects implement the python buffer protocol, so they may be
         efficiently used with systems like numpy.
 
+        To specify the type of buffer to create (LIGO mbuf or
+        posix shared memory) add a prefix to the name 'mbuf://' for
+        a LIGO mbuf or 'shm://' for a posix shared memory buffer.  The
+        default if no prefix is given is to use a LIGO mbuf.
+
         For example to get a live updating view of the data, you can create a
         shmem object then create a numpy array from it with copy = false.
 
diff --git a/src/drv/rfm.c b/src/drv/rfm.c
index 415e914977b2635838eec4350bc2973047319d17..a2c1b414c54de4e45e666adccda675190e469883 100644
--- a/src/drv/rfm.c
+++ b/src/drv/rfm.c
@@ -53,11 +53,10 @@ findSharedMemorySize(char *sys_name, int size_mb)
         return 0;
     }
 
-    struct mbuf_request_struct req;
+    struct mbuf_request_struct req = {0, {0,}};
     req.size = size_bytes;
     strcpy(req.name, sys);
-    ioctl (fd, IOCTL_MBUF_ALLOCATE, &req);
-    ioctl (fd, IOCTL_MBUF_INFO, &req);
+    if (ioctl (fd, IOCTL_MBUF_ALLOCATE, &req) < req.size) return NULL;
 
     addr = (volatile unsigned char *)mmap(0, size_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     if (addr == MAP_FAILED) {
@@ -65,7 +64,7 @@ findSharedMemorySize(char *sys_name, int size_mb)
         perror("mmap");
         _exit(-1);
     }
-    printf(" %s mmapped address is 0x%lx\n", sys, (long)addr);
+    printf(" %s mmapped address is %p\n", sys, addr);
     return addr;
 }
 
diff --git a/src/drv/susWatchdogFilters.c b/src/drv/susWatchdogFilters.c
index 75e0d28c64b9ec1ac3d15f503ac6683960ad6b40..d043ca8502ada318b97689f8fdeb8e7dc4d886d9 100644
--- a/src/drv/susWatchdogFilters.c
+++ b/src/drv/susWatchdogFilters.c
@@ -16,6 +16,20 @@
 
 #define LOCAL_TAPS 3
 
+//
+// This is not a great solution, we should consider 
+// splitting these functions into seprate files, 
+// but all models that use this would need to be updated
+//
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+#else
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+
 /// 100mHz 6th order Butterworth High Pass
 static double coeff100mHzHP[13] = {0.9999814787757688,
 -1.9999814786838519, 0.9999814787757688, -2.0000000000000000, 1.0000000000000000,
@@ -71,3 +85,10 @@ void FILTER10MHZLP(double *argin, int nargin, double *argout, int nargout){
 
 	argout[0] = iir_filter(argin[0], &coeff10mHzLP[0],LOCAL_TAPS, &fixedFilterHistory[0]);
 }
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#else
+#pragma GCC diagnostic pop
+#endif
+
diff --git a/src/epics/CMakeLists.txt b/src/epics/CMakeLists.txt
index 807298ee007e48af880e82bb27b64ad38ffc04db..ac390263c324215f18de77852cd54ec1f25befaf 100644
--- a/src/epics/CMakeLists.txt
+++ b/src/epics/CMakeLists.txt
@@ -1 +1,2 @@
-add_subdirectory(seq)
\ No newline at end of file
+add_subdirectory(seq)
+add_subdirectory(edcu)
diff --git a/src/epics/edcu/CMakeLists.txt b/src/epics/edcu/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3863c819c1a3ff2a4b02ca46de1e712e230f3885
--- /dev/null
+++ b/src/epics/edcu/CMakeLists.txt
@@ -0,0 +1,36 @@
+if (Boost_FOUND)
+
+    add_executable(standalone_edc
+            standalone_edcu.cc
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../drv/rfm.c)
+    #target_compile_options(standalone_edc PRIVATE -fsanitize=address)
+    #target_link_libraries(standalone_edc PRIVATE asan)
+    #target_compile_options(standalone_edc PRIVATE
+    #        -fstack-protector -fstack-protector-strong)
+    target_include_directories(standalone_edc PUBLIC
+            "${CMAKE_CURRENT_SOURCE_DIR}/../../include"
+            "${CMAKE_CURRENT_SOURCE_DIR}/../../include/drv"
+            ${Boost_INCLUDE_DIRS})
+    target_link_libraries(standalone_edc PUBLIC
+            args
+            epics::ca
+            driver::ini_parsing
+            pv::simple_pv
+            ${Boost_LIBRARIES}
+            ${CMAKE_THREAD_LIBS_INIT}
+            driver::gpsclock)
+    target_requires_cpp11(standalone_edc PUBLIC)
+
+    configure_file(test/epics_test.py ${CMAKE_CURRENT_BINARY_DIR}/epics_test.py COPYONLY)
+    configure_file(test/daqdrc_standalone_edc_live_test ${CMAKE_CURRENT_BINARY_DIR}/daqdrc_standalone_edc_live_test COPYONLY)
+    configure_file(test/test_standalone_edc_live_nds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test_standalone_edc_live_nds.sh @ONLY)
+
+    add_test(NAME test_standalone_edc_live_nds
+            COMMAND /bin/bash ./test_standalone_edc_live_nds.sh
+            WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+    install(TARGETS standalone_edc DESTINATION bin)
+
+else(Boost_FOUND)
+    message(WARNING "The standalone_edc will not be build as boost was not found")
+endif (Boost_FOUND)
\ No newline at end of file
diff --git a/src/epics/seq/gps.hh b/src/epics/edcu/gps.hh
similarity index 100%
rename from src/epics/seq/gps.hh
rename to src/epics/edcu/gps.hh
diff --git a/src/epics/seq/standalone_edcu.cc b/src/epics/edcu/standalone_edcu.cc
similarity index 98%
rename from src/epics/seq/standalone_edcu.cc
rename to src/epics/edcu/standalone_edcu.cc
index e4c277b5323cdf2bdcaac8be2a12539be090ac78..f453d9cba9644ca458672d399a613d6672aa99f3 100644
--- a/src/epics/seq/standalone_edcu.cc
+++ b/src/epics/edcu/standalone_edcu.cc
@@ -58,6 +58,7 @@ extern "C" {
 #include "gps.hh"
 #include "args.h"
 #include "simple_pv.h"
+#include "util/user/check_file_crc.h"
 
 #include <iostream>
 
@@ -248,8 +249,6 @@ private:
 
 // Function prototypes
 // ****************************************************************************************
-int checkFileCrc( const char* );
-
 typedef union edc_data_t
 {
     int16_t data_int16;
@@ -1170,31 +1169,6 @@ edcuInitialize( const std::string& mbuf_name,
     return EdcuClock( sync_source, delay_ms );
 }
 
-/// Common routine to check file CRC.
-///	@param[in] *fName	Name of file to check.
-///	@return File CRC or -1 if file not found.
-int
-checkFileCrc( const char* fName )
-{
-    char        buffer[ 256 ];
-    FILE*       pipePtr;
-    struct stat statBuf;
-    long        chkSum = -99999;
-    strcpy( buffer, "cksum " );
-    strcat( buffer, fName );
-    if ( !stat( fName, &statBuf ) )
-    {
-        if ( ( pipePtr = popen( buffer, "r" ) ) != NULL )
-        {
-            fgets( buffer, 256, pipePtr );
-            pclose( pipePtr );
-            sscanf( buffer, "%ld", &chkSum );
-        }
-        return ( chkSum );
-    }
-    return ( -1 );
-}
-
 std::pair< std::string, int >
 parse_address( const std::string& str )
 {
diff --git a/src/epics/seq/test/daqdrc_standalone_edc_live_test b/src/epics/edcu/test/daqdrc_standalone_edc_live_test
similarity index 100%
rename from src/epics/seq/test/daqdrc_standalone_edc_live_test
rename to src/epics/edcu/test/daqdrc_standalone_edc_live_test
diff --git a/src/epics/seq/test/epics_test.py b/src/epics/edcu/test/epics_test.py
similarity index 100%
rename from src/epics/seq/test/epics_test.py
rename to src/epics/edcu/test/epics_test.py
diff --git a/src/epics/seq/test/test_standalone_edc_live_nds.sh.in b/src/epics/edcu/test/test_standalone_edc_live_nds.sh.in
similarity index 100%
rename from src/epics/seq/test/test_standalone_edc_live_nds.sh.in
rename to src/epics/edcu/test/test_standalone_edc_live_nds.sh.in
diff --git a/src/epics/seq/CMakeLists.txt b/src/epics/seq/CMakeLists.txt
index 1b75be152417cbcd099cb5e8d38e6ba894596144..1eefade905f3de55de52695323f9ccd78596a68a 100644
--- a/src/epics/seq/CMakeLists.txt
+++ b/src/epics/seq/CMakeLists.txt
@@ -1,36 +1,22 @@
-if (Boost_FOUND)
+add_executable(test_sequencer_unit_tests
+        test/test_main.cc
+        test/test_burtfile.cc
+        test/test_simple_range.cc
+        test/test_fixed_size_string.cc
+        test/test_fixed_size_vector.cc
+        )
+target_include_directories(test_sequencer_unit_tests PUBLIC
+        ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(test_sequencer_unit_tests PUBLIC
+    catch2)
 
-add_executable(standalone_edc
-        standalone_edcu.cc
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../drv/rfm.c)
-#target_compile_options(standalone_edc PRIVATE -fsanitize=address)
-#target_link_libraries(standalone_edc PRIVATE asan)
-#target_compile_options(standalone_edc PRIVATE
-#        -fstack-protector -fstack-protector-strong)
-target_include_directories(standalone_edc PUBLIC
-        "${CMAKE_CURRENT_SOURCE_DIR}/../../include"
-        "${CMAKE_CURRENT_SOURCE_DIR}/../../include/drv"
-        ${Boost_INCLUDE_DIRS})
-target_link_libraries(standalone_edc PUBLIC
-        args
-        epics::ca
-        driver::ini_parsing
-        pv::simple_pv
-        ${Boost_LIBRARIES}
-        ${CMAKE_THREAD_LIBS_INIT}
-        driver::gpsclock)
-target_requires_cpp11(standalone_edc PUBLIC)
+add_executable(casdf_seq
+        main.cc
+        sdf_file_loaded.c)
+target_link_libraries(casdf_seq PUBLIC ini_parsing shmem epics::seq epics::ca)
+target_compile_definitions(casdf_seq PUBLIC "-DCA_SDF=1")
 
-configure_file(test/epics_test.py ${CMAKE_CURRENT_BINARY_DIR}/epics_test.py COPYONLY)
-configure_file(test/daqdrc_standalone_edc_live_test ${CMAKE_CURRENT_BINARY_DIR}/daqdrc_standalone_edc_live_test COPYONLY)
-configure_file(test/test_standalone_edc_live_nds.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test_standalone_edc_live_nds.sh @ONLY)
-
-add_test(NAME test_standalone_edc_live_nds
-        COMMAND /bin/bash ./test_standalone_edc_live_nds.sh
-        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
-
-install(TARGETS standalone_edc DESTINATION bin)
-
-else(Boost_FOUND)
-    message(WARNING "The standalone_edc will not be build as boost was not found")
-endif (Boost_FOUND)
\ No newline at end of file
+add_executable(modelsdf_seq
+        main.cc
+        sdf_file_loaded.c)
+target_link_libraries(modelsdf_seq PUBLIC ini_parsing shmem epics::seq epics::ca)
diff --git a/src/epics/seq/Makefile b/src/epics/seq/Makefile
deleted file mode 100644
index e167994a60f861b583b2c579b7d0383aa61758d2..0000000000000000000000000000000000000000
--- a/src/epics/seq/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-LIBFLAGS += -lezca
-
-edcu.o	edcu.c
diff --git a/src/epics/seq/burt_file.hh b/src/epics/seq/burt_file.hh
new file mode 100644
index 0000000000000000000000000000000000000000..d7755ae4c44ef4c8fdabdb9984be18c726249216
--- /dev/null
+++ b/src/epics/seq/burt_file.hh
@@ -0,0 +1,149 @@
+//
+// Created by jonathan.hanks on 4/2/22.
+//
+
+#ifndef DAQD_TRUNK_BURT_FILE_HH
+#define DAQD_TRUNK_BURT_FILE_HH
+
+#include "fixed_size_string.hh"
+#include "fixed_size_vector.hh"
+
+namespace BURT
+{
+
+    using parsed_word = embedded::fixed_string< 128 >;
+    using parsed_line = embedded::fixed_size_vector< parsed_word, 4 >;
+
+    /**
+     * @brief Encode a string for output into a BURT file.
+     * @note BURT encoding of strings does not escape quotes,
+     *       and lists empty strings as \0 (backslash and 0)
+     *
+     * @tparam SRC_SIZE
+     * @tparam DEST_SIZE Must be at least 2 greater than SRC_SIZE
+     * @param src Input string to encode.
+     * @param dest Destination for an encoded version of src.
+     */
+    template < std::size_t SRC_SIZE, std::size_t DEST_SIZE >
+    void
+    encodeString( const embedded::fixed_string< SRC_SIZE >& src,
+                  embedded::fixed_string< DEST_SIZE >&      dest )
+    {
+        static_assert(
+            DEST_SIZE >= ( SRC_SIZE + 2 ),
+            "The destination buffer must be at least bytes larger than "
+            "the source to account for quoting" );
+        static_assert(
+            DEST_SIZE >= 2,
+            "The destination buffer must be long enough to burt encode "
+            "a NULL string" );
+
+        if ( src.empty( ) )
+        {
+            dest = "\\0";
+            return;
+        }
+
+        bool expand = false;
+
+        for ( char ch : src )
+        {
+            if ( ch == ' ' || ch == '\t' || ch == '\n' || ch == '"' )
+            {
+                expand = true;
+                break;
+            }
+        }
+        // we already bounds check this above
+        if ( expand )
+        {
+            dest.printf( "\"%s\"", src.c_str( ) );
+        }
+        else
+        {
+            dest = src;
+        }
+    }
+
+    /// Common routine to parse lines read from BURT/SDF files..
+    ///	@param[in] *s	Pointer to line of chars to parse.
+    ///	@param[out]     Output containing all the identified words in the line
+    ///	@return wc	Number of words in the line.
+    template < std::size_t N_WORDS, std::size_t WORD_LEN >
+    static inline int
+    parseLine( const char*                             s,
+               embedded::fixed_size_vector< embedded::fixed_string< WORD_LEN >,
+                                            N_WORDS >& out )
+    {
+        int lastwasspace = 1;
+
+        const char* lastquote = nullptr;
+        const char* qch = nullptr;
+
+        out.clear( );
+        embedded::fixed_string< WORD_LEN > cur_word{ };
+
+        while ( *s != 0 && *s != '\n' && out.capacity( ) > out.size( ) )
+        {
+            if ( *s == ' ' || *s == '\t' )
+            {
+                if ( !lastwasspace )
+                {
+                    out.push_back( cur_word );
+                    cur_word.clear( );
+                }
+                lastwasspace = 1;
+            }
+            else if ( *s != '"' || !lastwasspace )
+            {
+                cur_word += *s;
+                lastwasspace = 0;
+            }
+            else
+            {
+                // quote
+                // burt does not escape quotes, you have to look for the last
+                // quote and just take it.
+                lastquote = nullptr;
+                qch = s + 1;
+
+                while ( *qch && *qch != '\n' )
+                {
+                    if ( *qch == '"' )
+                        lastquote = qch;
+                    ++qch;
+                }
+                if ( !lastquote )
+                    lastquote = qch;
+                ++s;
+                // copy from (s,qch) then set lastwasspace
+                while ( s < lastquote )
+                {
+                    cur_word += *s;
+                    ++s;
+                }
+                out.push_back( cur_word );
+                cur_word.clear( );
+                lastwasspace = 1;
+                if ( !( *s ) || *s == '\n' || out.size( ) == out.capacity( ) )
+                    break;
+            }
+            ++s;
+        }
+        if ( !cur_word.empty( ) )
+        {
+            out.push_back( cur_word );
+        }
+        for ( auto& word : out )
+        {
+            if ( word == "\\0" )
+            {
+                word = "";
+            }
+        }
+        return out.size( );
+    }
+
+} // namespace BURT
+
+#endif // DAQD_TRUNK_BURT_FILE_HH
diff --git a/src/epics/seq/edcu.c b/src/epics/seq/edcu.c
deleted file mode 100644
index 49c1598f5dcc26baa47d91c53a12c76c39eb04cc..0000000000000000000000000000000000000000
--- a/src/epics/seq/edcu.c
+++ /dev/null
@@ -1,951 +0,0 @@
-///	@file /src/epics/seq/edcu.c
-///	@brief Contains required 'main' function to startup EPICS sequencers, along with supporting routines. 
-///<		This code is taken from EPICS example included in the EPICS distribution and modified for LIGO use.
-
-/********************COPYRIGHT NOTIFICATION**********************************
-This software was developed under a United States Government license
-described on the COPYRIGHT_UniversityOfChicago file included as part
-of this distribution.
-****************************************************************************/
-
-// TODO:
-// - Make appropriate log file entries
-// - Get rid of need to build skeleton.st
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-
-#include "iocsh.h"
-#include "dbStaticLib.h"
-#include "crc.h"
-#include "dbCommon.h"
-#include "recSup.h"
-#include "dbDefs.h"
-#include "dbFldTypes.h"
-#include "dbAccess.h"
-
-#define epicsExportSharedSymbols
-#include "asLib.h"
-#include "asCa.h"
-#include "asDbLib.h"
-
-#include <daqmap.h>
-#include <param.h>
-// #include "fm10Gen.h"
-#include "findSharedMemory.h"
-#include "cadef.h"
-#include "fb.h"
-#include "../../drv/gpstime/gpstime.h"
-
-#include <pthread.h>
-
-#define EDCU_MAX_CHANS	50000
-// Gloabl variables		****************************************************************************************
-char timechannel[256];		///< Name of the GPS time channel for timestamping.
-char reloadtimechannel[256];	///< Name of EPICS channel which contains the BURT reload requests.
-struct timespec t;
-char logfilename[128];
-char edculogfilename[128];
-unsigned char naughtyList[EDCU_MAX_CHANS][64];
-
-// Function prototypes		****************************************************************************************
-int checkFileCrc(char *);
-void getSdfTime(char *);
-void logFileEntry(char *);
-void* check_crc(void* arg);
-
-unsigned long daqFileCrc;
-typedef struct daqd_c {
-	int num_chans;
-	int con_chans;
-	int val_events;
-	int con_events;
-	float channel_value[EDCU_MAX_CHANS];
-	char channel_name[EDCU_MAX_CHANS][64];
-	int channel_status[EDCU_MAX_CHANS];
-	long gpsTime;
-	long epicsSync;
-} daqd_c;
-
-typedef struct check_crc_params {
-    char *ini_filename;
-    int   orig_crc;
-    dbAddr message_dest;
-} check_crc_params;
-
-int num_chans_index = -1;
-int con_chans_index = -1;
-int nocon_chans_index = -1;
-int internal_channel_count = 0;
-pthread_t check_crc_thread;
-
-daqd_c daqd_edcu1;
-static struct rmIpcStr *dipc;
-static struct rmIpcStr *sipc;
-static char *shmDataPtr;
-static struct cdsDaqNetGdsTpNum *shmTpTable;
-static const int buf_size = DAQ_DCU_BLOCK_SIZE;
-static const int header_size = sizeof(struct rmIpcStr) + sizeof(struct cdsDaqNetGdsTpNum);
-static DAQ_XFER_INFO xferInfo;
-static float dataBuffer[2][EDCU_MAX_CHANS];
-static int timeIndex;
-static int cycleIndex;
-static int symmetricom_fd = -1;
-int timemarks[16] = {1000,63500,126000,188500,251000,313500,376000,438500,501000,563500,626000,688500,751000,813500,876000,938500};
-int nextTrig = 0;
-
-
-// End Header ************************************************************
-//
-
-// **************************************************************************
-/// Get current GPS time from the symmetricom IRIG-B card
-unsigned long symm_gps_time(unsigned long *frac, int *stt) {
-// **************************************************************************
-    unsigned long t[3];
-    ioctl (symmetricom_fd, IOCTL_SYMMETRICOM_TIME, &t);
-    t[1] *= 1000;
-    t[1] += t[2];
-    if (frac) *frac = t[1];
-         if (stt) *stt = 0;
-         // return  t[0] + daqd.symm_gps_offset;
-         return  t[0];
-}
-// **************************************************************************
-void waitGpsTrigger(unsigned long gpssec, int cycle)
-// No longer used in favor of sync to IOP
-// **************************************************************************
-{
-unsigned long gpsSec, gpsuSec;
-int gpsx;
-	do{
-		usleep(1000);
-		gpsSec = symm_gps_time(&gpsuSec, &gpsx);
-		gpsuSec /= 1000;
-	}while(gpsSec < gpssec || gpsuSec < timemarks[cycle]); 
-}
-
-// **************************************************************************
-long waitNewCycle(long *gps_sec)
-// **************************************************************************
-{
-  static long newCycle = 0;
-  static int lastCycle = 0;
-  static int sync21pps = 1;
-  unsigned long lastSec;
-
-    if(sync21pps)  {
-        for (;sipc->cycle;) usleep(1000); 
-        printf("Found Sync at %ld %ld\n",sipc->bp[lastCycle].timeSec, sipc->bp[lastCycle].timeNSec);
-        sync21pps = 0;
-    }
-    do {
-        usleep(1000);
-        newCycle = sipc->cycle;
-    }while (newCycle == lastCycle);
-    *gps_sec = sipc->bp[newCycle].timeSec;
-    // printf("new cycle %d %ld\n",newCycle,*gps_sec);
-    lastCycle = newCycle;
-    return newCycle;
-}
-
-// **************************************************************************
-/// See if the GPS card is locked.
-int symm_gps_ok() {
-// **************************************************************************
-    unsigned long req = 0;
-    ioctl (symmetricom_fd, IOCTL_SYMMETRICOM_STATUS, &req);
-    printf("Symmetricom status: %s\n", req? "LOCKED": "UNCLOCKED");
-   return req;
-}
-
-// **************************************************************************
-unsigned long symm_initialize()
-// **************************************************************************
-{
-	symmetricom_fd =  open ("/dev/gpstime", O_RDWR | O_SYNC);
-	if (symmetricom_fd < 0) {
-	       perror("/dev/gpstime");
-	       exit(1);
-	}
-	unsigned long gpsSec, gpsuSec;
-	int gpsx;
-	int gpssync;
-	gpssync =  symm_gps_ok();
-	gpsSec = symm_gps_time(&gpsuSec, &gpsx);
-	printf("GPS SYNC = %d %d\n",gpssync,gpsx);
-	printf("GPS SEC = %ld  USEC = %ld  OTHER = %d\n",gpsSec,gpsuSec,gpsx);
-	// Set system to start 2 sec from now.
-	gpsSec += 2;
-	return(gpsSec);
-}
-
-// **************************************************************************
-void connectCallback(struct connection_handler_args args) {
-// **************************************************************************
-        unsigned long chnum = (unsigned long)ca_puser(args.chid);
-	daqd_edcu1.channel_status[chnum] = args.op == CA_OP_CONN_UP? 0: 0xbad;
-        if (args.op == CA_OP_CONN_UP) daqd_edcu1.con_chans++; else daqd_edcu1.con_chans--;
-        daqd_edcu1.con_events++;
-}
-
-
-// **************************************************************************
-void subscriptionHandler(struct event_handler_args args) {
-// **************************************************************************
- 	daqd_edcu1.val_events++;
-        if (args.status != ECA_NORMAL) {
-        	return;
-        }
-        if (args.type == DBR_FLOAT) {
-        	float val = *((float *)args.dbr);
-                daqd_edcu1.channel_value[(unsigned long)args.usr] = val;
-        }else{
-		printf("Arg type unknown\n");
-	}
-}
-
-// **************************************************************************
-int edcuClearSdf(char *pref)
-// **************************************************************************
-{
-unsigned char clearString[64] = "          ";
-int flength = 62;
-long status;
-dbAddr saddr;
-int ii;
-char s[64];
-char s1[64];
-char s2[64];
-char s3[64];
-char s4[64];
-dbAddr baddr;
-dbAddr maddr;
-dbAddr taddr;
-dbAddr daddr;
-
-
-
-	for(ii=0;ii<40;ii++)
-        {
-	 sprintf(s, "%s_%s_STAT%d", pref,"SDF_SP", ii);
-	 status = dbNameToAddr(s,&saddr);
-	 status = dbPutField(&saddr,DBR_UCHAR,clearString,16);
-
-	 sprintf(s1, "%s_%s_STAT%d_BURT", pref,"SDF_SP", ii);
-	 status = dbNameToAddr(s1,&baddr);
-	 status = dbPutField(&baddr,DBR_UCHAR,clearString,flength);
-
-	 sprintf(s2, "%s_%s_STAT%d_LIVE", pref,"SDF_SP", ii);
-	 status = dbNameToAddr(s2,&maddr);
-	 status = dbPutField(&maddr,DBR_UCHAR,clearString,flength);
-
-	 sprintf(s3, "%s_%s_STAT%d_TIME", pref,"SDF_SP", ii);
-	 status = dbNameToAddr(s3,&taddr);
-	 status = dbPutField(&taddr,DBR_UCHAR,clearString,flength);
-
-	  sprintf(s4, "%s_%s_STAT%d_DIFF", pref,"SDF_SP", ii);
-	  status = dbNameToAddr(s4,&daddr);
-	  status = dbPutField(&daddr,DBR_UCHAR,clearString,flength);
-
-	 }
-
-
-}
-
-// **************************************************************************
-int edcuFindUnconnChannels()
-// **************************************************************************
-{
-int ii;
-int dcc = 0;
-
-	for (ii=0;ii<daqd_edcu1.num_chans;ii++)
-	{
-		if(daqd_edcu1.channel_status[ii] != 0)
-		{
-			sprintf(naughtyList[dcc],"%s",daqd_edcu1.channel_name[ii]);
-			dcc ++;
-		}
-	}
-	return(dcc);
-}
-// **************************************************************************
-int edcuReportUnconnChannels(char *pref, int dc, int offset)
-// **************************************************************************
-{
-int ii;
-dbAddr saddr;
-dbAddr laddr;
-dbAddr sperroraddr;
-char s[64];
-char sl[64];
-long status;
-int flength = 62;
-unsigned char tmpstr[64];
-int rc = 0;
-int myindex = 0;
-int numDisp = 0;
-int lineNum = 0;
-int erucError = 0;
-
-
-	myindex = offset * 40;
-	if(myindex > dc) {
-		myindex = 0;
-		erucError = -1;
-	}
-	rc = myindex + 40;
-	if(rc > dc) rc = dc;
-	// printf("Naught =  %d to %d\n",myindex,rc);
-	// printf("In error listing \n");
-	for (ii=myindex;ii<rc;ii++)
-	{
-		sprintf(s, "%s_%s_STAT%d", pref,"SDF_SP", (ii - myindex));
-		status = dbNameToAddr(s,&saddr);
-		if(status) 
-		{
-			printf("Can't connect to %s\n",s);
-		} else {
-			sprintf(tmpstr,"%s",naughtyList[ii]);
-			status = dbPutField(&saddr,DBR_UCHAR,tmpstr,flength);
-			numDisp ++;
-		}
-		sprintf(sl, "%s_SDF_LINE_%d", pref, (ii - myindex));
-		status = dbNameToAddr(sl,&laddr);
-		if(status) 
-		{
-			printf("Can't connect to %s\n",s);
-		} else {
-			lineNum = ii + 1;
-			status = dbPutField(&laddr,DBR_LONG,&lineNum,1);
-		}
-	}
-	// Clear out remaining reporting channels.
-	sprintf(tmpstr,"%s","  ");
-	for (ii=numDisp;ii<40;ii++) {
-		sprintf(s, "%s_%s_STAT%d", pref,"SDF_SP", ii);
-		status = dbNameToAddr(s,&saddr);
-		status = dbPutField(&saddr,DBR_UCHAR,tmpstr,flength);
-		// sprintf(sl, "%s_SDF_LINE_%d", pref, (ii - myindex));
-		sprintf(sl, "%s_SDF_LINE_%d", pref, ii);
-		status = dbNameToAddr(sl,&laddr);
-		lineNum += 1;
-		status = dbPutField(&laddr,DBR_LONG,&lineNum,1);
-	}
-	 char speStat[256]; sprintf(speStat, "%s_%s", pref, "SDF_TABLE_ENTRIES");             // Setpoint diff counter
-	 status = dbNameToAddr(speStat,&sperroraddr);                    // Get Address
-	 status = dbPutField(&sperroraddr,DBR_LONG,&dc,1);          // Init to zero.
-
-	return(erucError);
-}
-
-/**
- * Scan the input text for the first non-whitespace character and return a pointer to that location.
- * @param line NULL terminated string to check.
- * @return Pointer to the the first non whitespace (space, tab, nl, cr) character.  Returns NULL iff
- * line is NULL.
- */
-const char* skip_whitespace(const char* line)
-{
-    const char* cur = line;
-    char ch = 0;
-    if (!line)
-    {
-        return NULL;
-    }
-    ch = *cur;
-    while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
-    {
-        ++cur;
-        ch = *cur;
-    }
-    return cur;
-}
-
-/**
- * Given a line with an comment denoted by '#' terminate
- * the line at the start of the comment.
- * @param line The line to modify, a NULL terminated string
- * @note This may modify the string pointed to by line.
- * This is safe to call with a NULL pointer.
- */
-void remove_line_comments(char *line)
-{
-    char ch = 0;
-
-    if (!line)
-    {
-        return;
-    }
-    while ((ch = *line))
-    {
-        if (ch == '#')
-        {
-            *line = '\0';
-            return;
-        }
-        ++line;
-    }
-}
-
-/**
- * Given a NULL terminated string remove any trailing whitespace
- * @param line The line to modify, a NULL terminated string
- * @note This may modify the string pointed to by line.
- * This is safe to call with a NULL pointer.
- */
-void remove_trailing_whitespace(char* newname)
-{
-    char* cur = newname;
-    char* last_non_ws = NULL;
-    char ch = 0;
-
-    if (!newname)
-    {
-        return;
-    }
-    ch = *cur;
-    while (ch)
-    {
-        if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
-        {
-            last_non_ws = cur;
-        }
-        ++cur;
-        ch = *cur;
-    }
-    if (!last_non_ws)
-    {
-        *newname = '\0';
-    }
-    else
-    {
-        last_non_ws++;
-        *last_non_ws = '\0';
-    }
-}
-
-// **************************************************************************
-void edcuCreateChanFile(char *fdir, char *edcuinifilename, char *fecid) {
-// **************************************************************************
-    int ok = 0;
-    int i = 0;
-    int status = 0;
-    char errMsg[64] = "";
-    FILE *daqfileptr = NULL;
-    FILE *edcuini = NULL;
-    FILE *edcumaster = NULL;
-    char masterfile[64] = "";
-    char edcuheaderfilename[64] = "";
-    char line[128] = "";
-    char *newname = 0;
-    char edcufilename[64] = "";
-    char *dcuid = 0;
-
-
-	sprintf(errMsg,"%s",fecid);
-	dcuid = strtok(errMsg,"-");
-	dcuid = strtok(NULL,"-");
-	sprintf(masterfile, "%s%s", fdir, "edcumaster.txt");
-	sprintf(edcuheaderfilename, "%s%s", fdir, "edcuheader.txt");
-
-	// Open the master file which contains list of EDCU files to read channels from.
-	edcumaster = fopen(masterfile,"r");
-	if(edcumaster == NULL) {
-		sprintf(errMsg,"DAQ FILE ERROR: FILE %s DOES NOT EXIST\n",masterfile);
-        logFileEntry(errMsg);
-        goto done;
-    }
-	// Open the file to write the composite channel list.
-	edcuini = fopen(edcuinifilename,"w");
-	if(edcuini == NULL) {
-		sprintf(errMsg,"DAQ FILE ERROR: FILE %s DOES NOT EXIST\n",edcuinifilename);
-        logFileEntry(errMsg);
-        goto done;
-    }
-
-	// Write standard header into .ini file
-	fprintf(edcuini,"%s","[default] \n");
-	fprintf(edcuini,"%s","gain=1.00 \n");
-	fprintf(edcuini,"%s","datatype=4 \n");
-	fprintf(edcuini,"%s","ifoid=0 \n");
-	fprintf(edcuini,"%s","slope=1 \n");
-	fprintf(edcuini,"%s","acquire=3 \n");
-	fprintf(edcuini,"%s","offset=0 \n");
-	fprintf(edcuini,"%s","units=undef \n");
-	fprintf(edcuini,"%s%s%s","dcuid=",dcuid," \n");
-	fprintf(edcuini,"%s","datarate=16 \n\n");
-
-	// Read the master file entries.
-	while(fgets(line,sizeof line,edcumaster) != NULL) {
-		newname = strtok(line,"\n");
-		if (!newname)
-        {
-		    continue;
-        }
-		newname = (char*)skip_whitespace(newname);
-        remove_line_comments(newname);
-        remove_trailing_whitespace(newname);
-
-		if (*newname == '\0')
-        {
-		    continue;
-        }
-		strcpy(edcufilename,fdir);
-		strcat(edcufilename,newname);
-		printf("File in master = %s\n",edcufilename);
-		daqfileptr = fopen(edcufilename,"r");
-		if(daqfileptr == NULL) {
-			sprintf(errMsg,"DAQ FILE ERROR: FILE %s DOES NOT EXIST OR CANNOT BE READ!\n",edcufilename);
-			logFileEntry(errMsg);
-			goto done;
-		}
-		while(fgets(line,sizeof line,daqfileptr) != NULL) {
-			fprintf(edcuini,"%s",line);
-		}
-		fclose(daqfileptr);
-		daqfileptr = NULL;
-	}
-	ok = 1;
-done:
-    if (daqfileptr) fclose(daqfileptr);
-	if (edcuini) fclose(edcuini);
-    if (edcumaster) fclose(edcumaster);
-    if (!ok)
-    {
-        exit(1);
-    }
-}
-
-// **************************************************************************
-void edcuCreateChanList(char *daqfilename) {
-// **************************************************************************
-int i;
-int status;
-FILE *daqfileptr;
-FILE *edculog;
-char errMsg[64];
-// char daqfile[64];
-char line[128];
-char *newname;
-
-
-char *pref = getenv("PREFIX");
-char eccname[256]; sprintf(eccname, "%s_%s", pref, "EDCU_CHAN_CONN");
-char chcntname[256]; sprintf(chcntname, "%s_%s", pref, "EDCU_CHAN_CNT");
-char cnfname[256]; sprintf(cnfname, "%s_%s", pref, "EDCU_CHAN_NOCON"); 
-
-
-	// sprintf(daqfile, "%s%s", fdir, "EDCU.ini");
-	daqd_edcu1.num_chans = 0;
-	daqfileptr = fopen(daqfilename,"r");
-	if(daqfileptr == NULL) {
-		sprintf(errMsg,"DAQ FILE ERROR: FILE %s DOES NOT EXIST\n",daqfilename);
-	        logFileEntry(errMsg);
-        }
-	edculog = fopen(edculogfilename,"w");
-	if(daqfileptr == NULL) {
-		sprintf(errMsg,"DAQ FILE ERROR: FILE %s DOES NOT EXIST\n",edculogfilename);
-	        logFileEntry(errMsg);
-        }
-	while(fgets(line,sizeof line,daqfileptr) != NULL) {
-		fprintf(edculog,"%s",line);
-		status = strlen(line);
-		if(strncmp(line,"[",1) == 0 && status > 0) {
-			newname = strtok(line,"]");
-			// printf("status = %d New name = %s and %s\n",status,line,newname);
-			newname = strtok(line,"[");
-			// printf("status = %d New name = %s and %s\n",status,line,newname);
-			if(strcmp(newname,"default") == 0) {
-				printf("DEFAULT channel = %s\n", newname);
-			} else {
-				// printf("NEW channel = %s\n", newname);
-				sprintf(daqd_edcu1.channel_name[daqd_edcu1.num_chans],"%s",newname);
-				daqd_edcu1.num_chans ++;
-			}
-		}
-	}
-	fclose(daqfileptr);
-	fclose(edculog);
-
-	xferInfo.crcLength = 4 * daqd_edcu1.num_chans;
-	printf("CRC data length = %d\n",xferInfo.crcLength);
-
-	     chid chid1;
-	ca_context_create(ca_enable_preemptive_callback);
-
-
-     	for (i = 0; i < daqd_edcu1.num_chans; i++) {
-            if (strcmp(daqd_edcu1.channel_name[i], chcntname) == 0) {
-                num_chans_index = i;
-                internal_channel_count = internal_channel_count + 1;
-                daqd_edcu1.channel_status[i] = 0;
-            }
-            else if (strcmp(daqd_edcu1.channel_name[i], eccname) == 0) {
-                con_chans_index = i;
-                internal_channel_count = internal_channel_count + 1;
-                daqd_edcu1.channel_status[i] = 0;
-            }
-            else if (strcmp(daqd_edcu1.channel_name[i], cnfname) == 0) {
-                nocon_chans_index = i;
-                internal_channel_count = internal_channel_count + 1;
-                daqd_edcu1.channel_status[i] = 0;
-            }
-            else {
-        	     status = ca_create_channel(daqd_edcu1.channel_name[i], connectCallback, (void *)i, 0, &chid1);
-	             status = ca_create_subscription(DBR_FLOAT, 0, chid1, DBE_VALUE,
-		    	     subscriptionHandler, (void *)i, 0);
-            }
-    	}
-
-    daqd_edcu1.con_chans = daqd_edcu1.con_chans + internal_channel_count;
-
-	timeIndex = 0;
-}
-
-// **************************************************************************
-void edcuWriteData(int daqBlockNum, unsigned long cycle_gps_time, int dcuId, int daqreset)
-// **************************************************************************
-{
-float *daqData;
-int buf_size;
-int ii;
-
-
-
-    if (num_chans_index != -1) {
-        daqd_edcu1.channel_value[num_chans_index] = daqd_edcu1.num_chans;
-    }
-
-    if (con_chans_index != -1) {
-        daqd_edcu1.channel_value[con_chans_index] = daqd_edcu1.con_chans;
-    }
-
-    if (nocon_chans_index != -1) {
-        daqd_edcu1.channel_value[nocon_chans_index] = daqd_edcu1.num_chans - daqd_edcu1.con_chans;
-    }
-
-
-
-		
-	buf_size = DAQ_DCU_BLOCK_SIZE*DAQ_NUM_SWING_BUFFERS;
-	daqData = (float *)(shmDataPtr + (buf_size * daqBlockNum));
-    memcpy(daqData, daqd_edcu1.channel_value, daqd_edcu1.num_chans * sizeof(float));
-	dipc->dcuId = dcuId;
-	dipc->crc = daqFileCrc;
-	dipc->dataBlockSize = xferInfo.crcLength;
-	dipc->bp[daqBlockNum].cycle = daqBlockNum;
-	dipc->bp[daqBlockNum].crc = xferInfo.crcLength;
-	dipc->bp[daqBlockNum].timeSec = (unsigned int) cycle_gps_time;
-	dipc->bp[daqBlockNum].timeNSec = (unsigned int)daqBlockNum;
-    if(daqreset) {
-        shmTpTable->count = 1;
-        shmTpTable->tpNum[0] = daqreset;
-    } else {
-        shmTpTable->count = 0;
-        shmTpTable->tpNum[0] = 0;
-    }
-	dipc->cycle = daqBlockNum;	// Triggers sending of data by mx_stream.
-
-}
-
-// **************************************************************************
-void edcuInitialize(char *shmem_fname, char *sync_source)
-// **************************************************************************
-{
-
-	// Find start of DAQ shared memory
-	void *dcu_addr = findSharedMemory(shmem_fname);
-	// Find the IPC area to communicate with mxstream
-	dipc = (struct rmIpcStr *)((char *)dcu_addr + CDS_DAQ_NET_IPC_OFFSET);
-	// Find the DAQ data area.
-    shmDataPtr = (char *)((char *)dcu_addr + CDS_DAQ_NET_DATA_OFFSET);
-    shmTpTable = (struct cdsDaqNetGdsTpNum *)((char *)dcu_addr + CDS_DAQ_NET_GDS_TP_TABLE_OFFSET);
-    // Find Sync source
-	void *sync_addr = findSharedMemory(sync_source);
-	sipc = (struct rmIpcStr *)((char *)sync_addr + CDS_DAQ_NET_IPC_OFFSET);
-}
-
-
-
-/// Common routine to check file CRC.
-///	@param[in] *fName	Name of file to check.
-///	@return File CRC or -1 if file not found.
-int checkFileCrc(char *fName)
-{
-char buffer[256];
-FILE *pipePtr;
-struct stat statBuf;
-long chkSum = -99999;
-      	strcpy(buffer, "cksum "); 
-      	strcat(buffer, fName); 
-      	if (!stat(fName, &statBuf) ) { 
-         	if ((pipePtr = popen(buffer, "r")) != NULL) {
-            	fgets(buffer, 256, pipePtr);
-            	pclose(pipePtr); 
-            	sscanf(buffer, "%ld", &chkSum);
-         	} 
-		return(chkSum);
-    	}    
-	return(-1);
-}
-
-/// Routine for reading GPS time from model EPICS record.
-///	@param[out] timestring 	Pointer to char string in which GPS time is to be written.
-void getSdfTime(char *timestring)
-{
-
-	dbAddr paddr;
-	long ropts = 0;
-	long nvals = 1;
-	long status;
-
-	status = dbNameToAddr(timechannel,&paddr);
-	status = dbGetField(&paddr,DBR_STRING,timestring,&ropts,&nvals,NULL);
-}
-
-/// Routine for logging messages to ioc.log file.
-/// 	@param[in] message Ptr to string containing message to be logged.
-void logFileEntry(char *message)
-{
-	FILE *log;
-	char timestring[256];
-	long status;
-	dbAddr paddr;
-
-	getSdfTime(timestring);
-	log = fopen(logfilename,"a");
-	if(log == NULL) {
-		status = dbNameToAddr(reloadtimechannel,&paddr);
-		status = dbPutField(&paddr,DBR_STRING,"ERR - NO LOG FILE FOUND",1);
-	} else {
-		fprintf(log,"%s\n%s\n",timestring,message);
-		fprintf(log,"***************************************************\n");
-		fclose(log);
-	}
-
-}
-
-/// Called on EPICS startup; This is generic EPICS provided function, modified for LIGO use.
-int main(int argc,char *argv[])
-{
-	// Addresses for SDF EPICS records.
-	// Initialize request for file load on startup.
-	long status;
-	int request;
-	int daqTrigger;
-	long ropts = 0;
-	long nvals = 1;
-	int rdstatus = 0;
-	char timestring[128];
-	int ii;
-	long coeffFileCrc;
-	char modfilemsg[] = "Modified File Detected ";
-	struct stat st = {0};
-	char filemsg[128];
-	char logmsg[256];
-	int pageNum = 0;
-	int pageNumDisp = 0;
-    int daqreset = 0;
-    char errMsg[64];
-    char *dcuid;
-    int send_daq_reset = 0;
-
-    check_crc_params crc_params;
-
-    if(argc>=2) {
-        iocsh(argv[1]);
-
-    memset(&crc_params, 0, sizeof(crc_params));
-
-	// printf("Executing post script commands\n");
-	// Get environment variables from startup command to formulate EPICS record names.
-	char *pref = getenv("PREFIX");
-	char *modelname =  getenv("SDF_MODEL");
-	char daqsharedmemname[64];
-	sprintf(daqsharedmemname, "%s%s", modelname, "_daq");
-	char *sync =  getenv("SYNC_SRC");
-	char syncsharedmemname[64];
-	sprintf(syncsharedmemname, "%s%s", sync, "_daq");
-	char *targetdir =  getenv("TARGET_DIR");
-	char *daqFile =  getenv("DAQ_FILE");
-	char *daqDir =  getenv("DAQ_DIR");
-	char *coeffFile =  getenv("COEFF_FILE");
-	char *logdir = getenv("LOG_DIR");
-	if(stat(logdir, &st) == -1) mkdir(logdir,0777);
-	sprintf(errMsg,"%s",pref);
-	dcuid = strtok(errMsg,"-");
-	dcuid = strtok(NULL,"-");
-    int mydcuid = atoi(dcuid);
-	// strcat(sdf,"_safe");
-	printf("My prefix is %s\n",pref);
-	printf("My dcuid is %d\n",mydcuid);
-	sprintf(logfilename, "%s%s", logdir, "/ioc.log");
-	printf("LOG FILE = %s\n",logfilename);
-sleep(2);
-	// **********************************************
-	//
-	dbAddr eccaddr;
-	char eccname[256]; sprintf(eccname, "%s_%s", pref, "EDCU_CHAN_CONN");			// Number of setting channels in EPICS db
-	status = dbNameToAddr(eccname,&eccaddr);
-
-	dbAddr chcntaddr;
-	// char chcntname[256]; sprintf(chcntname, "%s", "X1:DAQ-FEC_54_EPICS_CHAN_CNT");	// Request to monitor all channels.
-	char chcntname[256]; sprintf(chcntname, "%s_%s", pref, "EDCU_CHAN_CNT");	// Request to monitor all channels.
-	status = dbNameToAddr(chcntname,&chcntaddr);		// Get Address.
-
-	dbAddr chnotfoundaddr;
-	char cnfname[256]; sprintf(cnfname, "%s_%s", pref, "EDCU_CHAN_NOCON");		// Number of channels not found.
-	status = dbNameToAddr(cnfname,&chnotfoundaddr);
-
-	dbAddr daqbyteaddr;
-	char daqbytename[256]; sprintf(daqbytename, "%s_%s", pref, "DAQ_BYTE_COUNT");	// Request to monitor all channels.
-	status = dbNameToAddr(daqbytename,&daqbyteaddr);		// Get Address.
-
-	char moddaqfilemsg[256]; sprintf(moddaqfilemsg, "%s_%s", pref, "MSGDAQ");	// Record to write if DAQ file changed.
-	status = dbNameToAddr(moddaqfilemsg, &(crc_params.message_dest));
-
-	sprintf(timechannel,"%s_%s", pref, "TIME_STRING");
-	// printf("timechannel = %s\n",timechannel);
-	
-	dbAddr reloadtimeaddr;
-	sprintf(reloadtimechannel,"%s_%s", pref, "MSGDAQ");			// Time of last BURT reload
-	status = dbNameToAddr(reloadtimechannel,&reloadtimeaddr);
-
-	getSdfTime(timestring);
-	status = dbPutField(&reloadtimeaddr,DBR_STRING,timestring,1);
-
-	dbAddr gpstimedisplayaddr;
-	char gpstimedisplayname[256]; sprintf(gpstimedisplayname, "%s_%s", pref, "TIME_DIAG");	// SDF Save command.
-	status = dbNameToAddr(gpstimedisplayname,&gpstimedisplayaddr);		// Get Address.
-
-	dbAddr pagereqaddr;
-	char pagereqname[256]; sprintf(pagereqname, "%s_%s", pref, "SDF_PAGE");	// SDF Page request.
-	status = dbNameToAddr(pagereqname,&pagereqaddr);		// Get Address.
-
-	dbAddr daqresetaddr;
-	char daqresetname[256]; sprintf(daqresetname, "%s_%s", pref, "EDCU_DAQ_RESET");	// SDF Page request.
-	status = dbNameToAddr(daqresetname,&daqresetaddr);		// Get Address.
-
-// EDCU STUFF ********************************************************************************************************
-	
-	sprintf(edculogfilename, "%s%s", logdir, "/edcu.log");
-	for (ii=0;ii<EDCU_MAX_CHANS;ii++) daqd_edcu1.channel_status[ii] = 0xbad;
-	edcuInitialize(daqsharedmemname,syncsharedmemname);
-	edcuCreateChanFile(daqDir,daqFile,pref);
-	edcuCreateChanList(daqFile);
-	status = dbPutField(&chcntaddr,DBR_LONG,&daqd_edcu1.num_chans,1);
-	int datarate = daqd_edcu1.num_chans * 64 / 1000;
-	status = dbPutField(&daqbyteaddr,DBR_LONG,&datarate,1);
-
-// Start SPECT
-	daqd_edcu1.gpsTime = symm_initialize();
-	daqd_edcu1.epicsSync = 0;
-
-// End SPECT
-
-	int dropout = 0;
-	int numDC = 0;
-	int cycle = 0;
-	int numReport = 0;
-
-	// Initialize DAQ and COEFF file CRC checksums for later compares.
-	daqFileCrc = checkFileCrc(daqFile);
-	printf("DAQ file CRC = %u \n",daqFileCrc);  
-	coeffFileCrc = checkFileCrc(coeffFile);
-	sprintf(logmsg,"%s\n%s = %u\n%s = %d","EDCU code restart","File CRC",daqFileCrc,"Chan Cnt",daqd_edcu1.num_chans);
-	logFileEntry(logmsg);
-	edcuClearSdf(pref);
-
-    crc_params.ini_filename = daqFile;
-    crc_params.orig_crc = daqFileCrc;
-
-    pthread_create(&check_crc_thread, NULL, check_crc, &crc_params);
-	// Start Infinite Loop 		*******************************************************************************
-	for(;;) {
-		dropout = 0;
-        daqd_edcu1.epicsSync = waitNewCycle(&daqd_edcu1.gpsTime);
-		edcuWriteData(daqd_edcu1.epicsSync, daqd_edcu1.gpsTime,mydcuid,send_daq_reset);
-        send_daq_reset = 0;
-		status = dbPutField(&gpstimedisplayaddr,DBR_LONG,&daqd_edcu1.gpsTime,1);		// Init to zero.
-		status = dbPutField(&daqbyteaddr,DBR_LONG,&datarate,1);
-		int conChans = daqd_edcu1.con_chans;
-		status = dbPutField(&eccaddr,DBR_LONG,&conChans,1);
-        // Check unconnected channels once per second
-		if (daqd_edcu1.epicsSync == 0) {
-			status = dbGetField(&daqresetaddr,DBR_LONG,&daqreset,&ropts,&nvals,NULL);
-            if(daqreset) {
-                status = dbPutField(&daqresetaddr,DBR_LONG,&ropts,1);  // Init to zero.
-                send_daq_reset = daqreset;
-            }
-			status = dbGetField(&pagereqaddr,DBR_LONG,&pageNum,&ropts,&nvals,NULL);
-            if((int)pageNum != 0) {
-                pageNumDisp += pageNum;
-                if(pageNumDisp < 0) pageNumDisp = 0;
-                status = dbPutField(&pagereqaddr,DBR_LONG,&ropts,1);                // Init to zero.
-            }
-			numDC = edcuFindUnconnChannels();
-            if(numDC < (pageNumDisp * 40)) pageNumDisp --; 
-			numReport = edcuReportUnconnChannels(pref,numDC,pageNumDisp);
-		}
-		status = dbPutField(&chnotfoundaddr,DBR_LONG,&numDC,1);
-	}
-	sleep(0xfffffff);
-    } else
-    	iocsh(NULL);
-    return(0);
-}
-
-
-/**
- * @brief main loop for the crc checking thread.
- * @param arg Input structure defining the epics variables to set.
- * @return null
- * @note this is outside of the main thread so that it does not stall
- * the filling of the mbuf while waiting for filesystem I/O (ie crc check
- * of the file).
- */
-void* check_crc(void* arg) {
-    check_crc_params* crc_params = (check_crc_params*)arg;
-    char okfilemsg[] = "";
-    char modfilemsg[] = "Modified File Detected ";
-    int cur_crc = 0;
-    int was_ok = 1;
-
-
-    if (!crc_params)
-    {
-        logFileEntry("Unable to check the ini file");
-        return 0;
-    }
-
-    while (1) {
-        sleep(5);
-        cur_crc = checkFileCrc(crc_params->ini_filename);
-
-        if (cur_crc != crc_params->orig_crc) {
-            dbPutField(&(crc_params->message_dest),DBR_STRING,modfilemsg,1);
-            if (was_ok) {
-                logFileEntry("Detected Change to DAQ Config file.");
-            }
-            was_ok = 0;
-        } else {
-            dbPutField(&(crc_params->message_dest), DBR_STRING, okfilemsg, 1);
-            if (!was_ok) {
-                logFileEntry("DAQ config file restored to its expected state.");
-            }
-            was_ok = 1;
-        }
-    }
-    return 0;
-}
-
diff --git a/src/epics/seq/epics_channel.hh b/src/epics/seq/epics_channel.hh
new file mode 100644
index 0000000000000000000000000000000000000000..6ce05b9400de15b66abc7fc0527688f1aa1b1e51
--- /dev/null
+++ b/src/epics/seq/epics_channel.hh
@@ -0,0 +1,138 @@
+//
+// Created by jonathan.hanks on 9/7/21.
+//
+// Error codes returned by dbNameToAddr are defined in the
+// modules/database/src/ioc/dbStatic/dbStaticLib.h file of the epics-base
+// git repository. https://git.launchpad.net/epics-base/tree/
+
+#ifndef DAQD_TRUNK_EPICS_CHANNEL_HH
+#define DAQD_TRUNK_EPICS_CHANNEL_HH
+
+#include <cstdint>
+#include <type_traits>
+#include <stdexcept>
+
+#include "dbAccess.h"
+
+#include "epics_channel_common.hh"
+
+namespace epics
+{
+    namespace detail
+    {
+        template < PVType T >
+        struct epics_lookup
+        {
+        };
+
+        template <>
+        struct epics_lookup<PVType::UInt16>
+        {
+            static const auto value = DBF_USHORT;
+        };
+
+        template <>
+        struct epics_lookup<PVType::Int32>
+        {
+            static const auto value = DBF_LONG;
+        };
+
+        template <>
+        struct epics_lookup<PVType::UInt32>
+        {
+            static const auto value = DBF_ULONG;
+        };
+
+        template <>
+        struct epics_lookup<PVType::Float64>
+        {
+            static const auto value = DBF_DOUBLE;
+        };
+
+        template <>
+        struct epics_lookup<PVType::String>
+        {
+            static const auto value = DBF_STRING;
+        };
+    }
+
+    template<PVType DataType>
+    class DBEntry {
+        static constexpr const dbfType epicsType = detail::epics_lookup<DataType>::value;
+    public:
+        struct ValidateAddress {};
+
+        using value_type = typename type_lookup<DataType>::type;
+
+        explicit DBEntry(channel_name name)
+        {
+            dbNameToAddr(name.c_str(), &addr_);
+        }
+
+        DBEntry(channel_name name, ValidateAddress tag)
+        {
+            auto status = dbNameToAddr(name.c_str(), &addr_);
+            if ( status )
+            {
+                throw std::runtime_error("Failure with PV lookup in the EPICS "
+                                          "database. If this is the first PV "
+                                          "this usually signifies an error "
+                                          "with the .cmd passed to iocsh(), "
+                                          "or a misconfigured EPICS "
+                                          "environment");
+            }
+        }
+
+        DBEntry(channel_name name, const char* val)
+        {
+            static_assert(epicsType == DBF_STRING, "Initialization by const char* must be on a string type");
+            auto status = dbNameToAddr(name.c_str(), &addr_);
+            if ( status )
+            {
+                throw std::runtime_error("dbNameToAddr(" + std::string(name.c_str()) +
+                                         ") : Failed with the return code: " + std::to_string(status) );
+            }
+            dbPutField(&addr_, epicsType, reinterpret_cast<const void*>(val), 1);
+        }
+
+
+        DBEntry(channel_name name, const value_type& val)
+        {
+            auto status = dbNameToAddr(name.c_str(), &addr_);
+            if ( status )
+            {
+                throw std::runtime_error("dbNameToAddr(" + std::string(name.c_str()) +
+                                         ") : Failed with the return code: " + std::to_string(status) );
+            }
+            dbPutField(&addr_, epicsType, reinterpret_cast<const void*>(&val), 1);
+        }
+
+        void
+        set(const value_type& val)
+        {
+            dbPutField(&addr_, epicsType, reinterpret_cast<const void*>(&val), 1);
+        }
+
+        void
+        set(const char* val)
+        {
+            static_assert(epicsType == DBF_STRING, "Setting a const char* must be done on a string type");
+            dbPutField(&addr_, epicsType, reinterpret_cast<const void*>(val), 1);
+        }
+
+        void
+        get(value_type& val)
+        {
+            long ropts{0};
+            long nvals{1};
+            dbGetField(&addr_, epicsType, &val, &ropts, &nvals, nullptr);
+        }
+    private:
+
+
+        dbAddr addr_{};
+    };
+
+}
+
+#endif //DAQD_TRUNK_EPICS_CHANNEL_HH
diff --git a/src/epics/seq/epics_channel_common.hh b/src/epics/seq/epics_channel_common.hh
new file mode 100644
index 0000000000000000000000000000000000000000..2f3d3af8d04bdd2f6d571b9d6fe837070d1ebd96
--- /dev/null
+++ b/src/epics/seq/epics_channel_common.hh
@@ -0,0 +1,66 @@
+//
+// Created by jonathan.hanks on 3/21/22.
+//
+
+#ifndef DAQD_TRUNK_EPICS_CHANNEL_TYPES_HH
+#define DAQD_TRUNK_EPICS_CHANNEL_TYPES_HH
+
+#include "fixed_size_string.hh"
+
+namespace epics
+{
+    using channel_name = embedded::fixed_string<256>;
+
+    inline channel_name
+    make_name(const char* prefix, const char* name)
+    {
+        channel_name output{};
+        output.printf("%s_%s", prefix, name);
+        return output;
+    }
+
+    enum class PVType {
+        UInt16,
+        Int32,
+        UInt32,
+        Float64,
+        String,
+    };
+
+    template < PVType T >
+    struct type_lookup
+    {
+    };
+
+    template <>
+    struct type_lookup<PVType::UInt16>
+    {
+        using type=std::uint16_t;
+    };
+
+    template <>
+    struct type_lookup<PVType::Int32>
+    {
+        using type=std::int32_t;
+    };
+
+    template <>
+    struct type_lookup<PVType::UInt32>
+    {
+        using type=std::uint32_t;
+    };
+
+    template <>
+    struct type_lookup<PVType::Float64>
+    {
+        using type=double;
+    };
+
+    template <>
+    struct type_lookup<PVType::String>
+    {
+        using type=embedded::fixed_string<256>;
+    };
+}
+
+#endif // DAQD_TRUNK_EPICS_CHANNEL_TYPES_HH
diff --git a/src/epics/seq/fixed_size_string.hh b/src/epics/seq/fixed_size_string.hh
new file mode 100644
index 0000000000000000000000000000000000000000..f457dc821f7d0d77a785722e57399b2f78f217ee
--- /dev/null
+++ b/src/epics/seq/fixed_size_string.hh
@@ -0,0 +1,303 @@
+//
+// Created by jonathan.hanks on 8/16/18.
+//
+
+#ifndef FIXED_SIZE_STRING_FIXED_SIZE_STRING_HH
+#define FIXED_SIZE_STRING_FIXED_SIZE_STRING_HH
+
+#include <algorithm>
+#include <cstdarg>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+
+namespace embedded
+{
+
+    /*!
+     * @brief A fixed size string abstraction that knows its bounds and does not
+     * overflow.
+     * @tparam max_size
+     * @note this class does not allocation and should not throw an exception
+     * ever.
+     */
+    template < std::size_t max_size >
+    class fixed_string
+    {
+        static_assert( max_size >= 1, "Fixed string capacity must be >= 1" );
+
+    public:
+        typedef std::size_t size_type;
+
+        /**
+         * @brief the buffer object is a way to get raw access to manipulate the
+         * fixed_string.  It looses most protections of the fixed_string class,
+         * but ensures that the buffer is null terminated when the buffer is
+         * destroyed.
+         */
+        class buffer
+        {
+            friend class fixed_string;
+            explicit buffer( char* buf ) : buf_{ buf }
+            {
+            }
+
+        public:
+            buffer( buffer&& other ) noexcept = default;
+            ~buffer( )
+            {
+                if ( buf_ )
+                {
+                    buf_[ fixed_string< max_size >::last_index( ) ] = '\0';
+                }
+            }
+            buffer( const buffer& other ) = delete;
+            buffer& operator=( const buffer& other ) = delete;
+            buffer& operator=( buffer&& other ) noexcept = default;
+
+            char*
+            data( ) noexcept
+            {
+                return buf_;
+            }
+            constexpr size_type
+            capacity( ) const noexcept
+            {
+                return max_size;
+            }
+
+        private:
+            char* buf_;
+        };
+
+        fixed_string( ) noexcept : data_( )
+        {
+            data_[ 0 ] = '\0';
+        }
+        fixed_string( const fixed_string& ) noexcept = default;
+
+        template < std::size_t other_max_size >
+        explicit fixed_string(
+            const fixed_string< other_max_size >& other ) noexcept : data_( )
+        {
+            copy_in_data( other.c_str( ) );
+        }
+        explicit fixed_string( const char* in ) noexcept : data_( )
+        {
+            copy_in_data( in );
+        }
+
+        fixed_string& operator=( const fixed_string& other ) noexcept = default;
+
+        template < std::size_t other_max_size >
+        fixed_string&
+        operator=( const fixed_string< other_max_size >& other ) noexcept
+        {
+            operator=( other.c_str( ) );
+            return *this;
+        }
+
+        fixed_string&
+        operator=( const char* in ) noexcept
+        {
+            copy_in_data( in );
+            return *this;
+        }
+
+        fixed_string&
+        operator+=( char in ) noexcept
+        {
+            if ( in && ( remaining( ) > 0 ) )
+            {
+                size_type cur_size = size( );
+                data_[ cur_size ] = in;
+                data_[ cur_size + 1 ] = 0;
+            }
+            return *this;
+        }
+
+        fixed_string&
+        operator+=( const char* in ) noexcept
+        {
+            if ( in )
+            {
+                size_type cur_size = size( );
+                size_type in_size = std::min( std::strlen( in ), remaining( ) );
+                std::memcpy( data_ + cur_size, in, in_size );
+                data_[ cur_size + in_size ] = 0;
+            }
+            return *this;
+        }
+
+        template < std::size_t in_max >
+        fixed_string&
+        operator+=( const fixed_string< in_max >& in ) noexcept
+        {
+            size_type in_size = std::min( in.size( ), remaining( ) );
+            if ( in_size > 0 )
+            {
+                size_type cur_size = size( );
+                std::memcpy( data_ + cur_size, in.c_str( ), in_size );
+                data_[ cur_size + in_size ] = 0;
+            }
+            return *this;
+        }
+
+        explicit operator const char*( ) const noexcept
+        {
+            return c_str( );
+        }
+
+        void
+        clear( ) noexcept
+        {
+            data_[ 0 ] = '\0';
+        }
+
+        size_type
+        printf( const char* fmt, ... ) noexcept
+        {
+            if ( !fmt )
+            {
+                clear( );
+                return 0;
+            }
+            va_list args;
+            va_start( args, fmt );
+            size_type results = std::vsnprintf( data_, capacity( ), fmt, args );
+            va_end( args );
+            return results;
+        }
+
+        bool
+        operator!=( const fixed_string& other ) const noexcept
+        {
+            return !operator==( other );
+        }
+
+        bool
+        operator!=( const char* str ) const noexcept
+        {
+            return !operator==( str );
+        }
+
+        template < std::size_t other_max_size >
+        bool
+        operator!=( const fixed_string< other_max_size >& other ) const noexcept
+        {
+            return !operator==( other );
+        }
+
+        bool
+        operator==( const fixed_string& other ) const noexcept
+        {
+            return std::strcmp( c_str( ), other.c_str( ) ) == 0;
+        }
+
+        bool
+        operator==( const char* str ) const noexcept
+        {
+            static const char* dummy = "";
+            return std::strcmp( c_str( ), ( str ? str : dummy ) ) == 0;
+        }
+
+        template < std::size_t other_max_size >
+        bool
+        operator==( const fixed_string< other_max_size >& other ) const noexcept
+        {
+            return std::strcmp( c_str( ), other.c_str( ) ) == 0;
+        }
+
+        size_type
+        remaining( ) const noexcept
+        {
+            return last_index( ) - size( );
+        }
+
+        constexpr size_type
+        capacity( ) const noexcept
+        {
+            return max_size;
+        }
+
+        size_type
+        size( ) const noexcept
+        {
+            return std::strlen( data_ );
+        }
+
+        bool
+        empty( ) const noexcept
+        {
+            return size( ) == 0;
+        }
+
+        const char*
+        c_str( ) const noexcept
+        {
+            return data_;
+        }
+
+        const char*
+        data( ) const noexcept
+        {
+            return data_;
+        }
+
+        const char*
+        begin( ) const noexcept
+        {
+            return data_;
+        }
+
+        const char*
+        end( ) const noexcept
+        {
+            return data_ + size( );
+        }
+
+        void
+        pop_back_n( size_type n ) noexcept
+        {
+            if ( n > 0 )
+            {
+                auto length = size( );
+                auto remove = std::min( length, n );
+                data_[ length - remove ] = '\0';
+            }
+        }
+
+        buffer
+        get_buffer( ) noexcept
+        {
+            return buffer( data_ );
+        }
+
+    private:
+        void
+        copy_in_data( const char* in ) noexcept
+        {
+            if ( in )
+            {
+                size_type in_size =
+                    std::min( std::strlen( in ), last_index( ) );
+                std::memcpy( data_, in, in_size );
+                data_[ in_size ] = 0;
+            }
+            else
+            {
+                data_[ 0 ] = 0;
+            }
+        }
+
+        static constexpr size_type
+        last_index( ) noexcept
+        {
+            return max_size - 1;
+        }
+        char data_[ max_size ];
+    };
+
+} // namespace embedded
+
+#endif // FIXED_SIZE_STRING_FIXED_SIZE_STRING_HH
diff --git a/src/epics/seq/fixed_size_vector.hh b/src/epics/seq/fixed_size_vector.hh
new file mode 100644
index 0000000000000000000000000000000000000000..6c060a5eff4ee7e80b63ccb7b81ba71cafab4fda
--- /dev/null
+++ b/src/epics/seq/fixed_size_vector.hh
@@ -0,0 +1,240 @@
+//
+// Created by jonathan.hanks on 11/13/20.
+//
+
+#ifndef DAQD_TRUNK_FIXED_SIZE_VECTOR_HH
+#define DAQD_TRUNK_FIXED_SIZE_VECTOR_HH
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+namespace embedded
+{
+
+    /*!
+     * @brief a simple vector with a fixed backing store.
+     * @details
+     * @tparam T the type being stored, some constraints are place on T to keep
+     * the vector noexcept
+     * @tparam max_size
+     */
+    template < typename T, std::size_t max_size >
+    class fixed_size_vector
+    {
+        static_assert( std::is_nothrow_copy_constructible< T >::value,
+                       "T must be no throw copy constructable" );
+        static_assert( std::is_nothrow_copy_assignable< T >::value,
+                       "T must be no throw copy assignable" );
+        static_assert( std::is_nothrow_move_constructible< T >::value,
+                       "T must be no throw move constructable" );
+        static_assert( std::is_nothrow_move_assignable< T >::value,
+                       "T must be no throw move assignable" );
+        static_assert( std::is_nothrow_destructible< T >::value,
+                       "T must be no throw destructable" );
+
+        using storage_type =
+            typename std::aligned_storage< sizeof( T ), alignof( T ) >::type;
+
+    public:
+        using value_type = T;
+        using size_type = std::size_t;
+        using iterator = typename std::add_pointer< T >::type;
+        using const_iterator = typename std::add_pointer<
+            typename std::add_const< T >::type >::type;
+
+        ~fixed_size_vector( )
+        {
+            clear( );
+        }
+
+        size_type
+        size( ) const noexcept
+        {
+            return entries_;
+        }
+
+        bool
+        empty( ) const noexcept
+        {
+            return size( ) == 0;
+        }
+
+        constexpr size_type
+                  capacity( ) const noexcept
+        {
+            return max_size;
+        }
+
+        iterator
+        begin( ) noexcept
+        {
+            return reinterpret_cast< T* >( &storage_[ 0 ] );
+        }
+
+        iterator
+        end( ) noexcept
+        {
+            return begin( ) + entries_;
+        }
+
+        const_iterator
+        begin( ) const noexcept
+        {
+            return reinterpret_cast< const_iterator >( &storage_[ 0 ] );
+        }
+
+        const_iterator
+        end( ) const noexcept
+        {
+            return begin( ) + entries_;
+        }
+
+        const_iterator
+        cbegin( ) const noexcept
+        {
+            return begin( );
+        }
+
+        const_iterator
+        cend( ) const noexcept
+        {
+            return end( );
+        }
+
+        /*!
+         * @brief push an entry onto the back of the vector if space is
+         * available.
+         * @param val
+         * @return true on success, else false (no change made to the vector)
+         */
+        bool
+        push_back( const T& val ) noexcept
+        {
+            if ( size( ) < capacity( ) )
+            {
+                T* dest = reinterpret_cast< T* >( &storage_[ entries_ ] );
+                new ( dest ) T( std::move( val ) );
+                ++entries_;
+                return true;
+            }
+            return false;
+        }
+
+        /*!
+         * @brief push an entry onto the back of the vector if space is
+         * available.
+         * @param val
+         * @return true on success, else false (no change made to the vector)
+         */
+        bool
+        push_back( T&& val ) noexcept
+        {
+            if ( size( ) < capacity( ) )
+            {
+                T* dest = reinterpret_cast< T* >( &storage_[ entries_ ] );
+                new ( dest ) T( std::move( val ) );
+                ++entries_;
+                return true;
+            }
+            return false;
+        }
+
+        /*!
+         * @brief emplace an entry onto the back of the vector if space is
+         * available.
+         * @tparam Args The argument types to pass to T's constructor
+         * @param args The argument to pass to T's constructor
+         * @return true on success, else false (no change made to the vector)
+         */
+        template < typename... Args >
+        bool
+        emplace_back( Args... args ) noexcept
+        {
+            if ( size( ) < capacity( ) )
+            {
+                T* dest = reinterpret_cast< T* >( &storage_[ entries_ ] );
+                new ( dest ) T( std::forward< Args >( args )... );
+                ++entries_;
+                return true;
+            }
+            return false;
+        }
+
+        T& operator[]( size_type index ) noexcept
+        {
+            return *reinterpret_cast< T* >( &storage_[ index ] );
+        }
+
+        const T& operator[]( size_type index ) const noexcept
+        {
+            return *reinterpret_cast< const T* >( &storage_[ index ] );
+        }
+
+        void
+        pop_back( ) noexcept
+        {
+            if ( !empty( ) )
+            {
+                size_type index = entries_ - 1;
+                T*        cur = reinterpret_cast< T* >( &storage_[ index ] );
+                cur->~T( );
+                entries_--;
+            }
+        }
+
+        template < typename T_ = T,
+                   typename std::enable_if<
+                       std::is_trivially_destructible< T_ >::value,
+                       int >::type = 0 >
+        void
+        clear( )
+        {
+            entries_ = 0;
+        }
+
+        template < typename T_ = T,
+                   typename std::enable_if<
+                       !std::is_trivially_destructible< T_ >::value,
+                       int >::type = 0 >
+        void
+        clear( )
+        {
+            while ( !empty( ) )
+            {
+                pop_back( );
+            }
+        }
+
+        T&
+        front() noexcept
+        {
+            return operator[](0);
+        }
+
+        T&
+        back() noexcept
+        {
+            return operator[](entries_-1);
+        }
+
+        const T&
+        front() const noexcept
+        {
+            return operator[](0);
+        }
+
+        const T&
+        back() const noexcept
+        {
+            return operator[](entries_-1);
+        }
+
+    private:
+        storage_type storage_[ max_size ]{};
+        size_type    entries_{ 0 };
+    };
+
+} // namespace embedded
+
+#endif // DAQD_TRUNK_FIXED_SIZE_VECTOR_HH
diff --git a/src/epics/seq/main.c b/src/epics/seq/main.cc
similarity index 54%
rename from src/epics/seq/main.c
rename to src/epics/seq/main.cc
index 53bf10d2d5bf5886472526b30dc28e424b683f86..695027a1d91d4cdd142e36d49ae7ae10228098b0 100644
--- a/src/epics/seq/main.c
+++ b/src/epics/seq/main.cc
@@ -19,6 +19,7 @@ of this distribution.
 /*
  * Main program for demo sequencer
  */
+#include "epics_channel.hh"
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
@@ -28,6 +29,13 @@ of this distribution.
 #include <sys/stat.h>
 #include <errno.h>
 #include <ctype.h>
+#include <algorithm>
+#include <array>
+#include <iterator>
+#include <memory>
+#include <functional>
+#include <cstdio> //std::{fopen, fclose, fflush}
+
 
 #ifdef USE_SYSTEM_TIME
 #include <time.h>
@@ -35,36 +43,48 @@ of this distribution.
 
 #include "iocsh.h"
 #include "dbStaticLib.h"
-#include "crc.h"
+extern "C" {
+    #include "crc.h"
+}
 #include "dbCommon.h"
 #include "recSup.h"
 #include "dbDefs.h"
 #include "dbFldTypes.h"
 #include "dbAccess.h"
+#include "envDefs.h"
 #include "math.h"
 #include "rcgversion.h"
+#include "burt_file.hh"
+#include "sdf_file_loaded.h"
+#include "util/user/check_file_crc.h"
 
 #define epicsExportSharedSymbols
 #include "asLib.h"
 #include "asCa.h"
 #include "asDbLib.h"
 
+#include "fixed_size_string.hh"
+#include "fixed_size_vector.hh"
+#include "simple_range.hh"
+
+using embedded::fixed_string;
+using embedded::fixed_size_vector;
+
 #ifdef CA_SDF
+#include <mutex>
 
-// The identifiers below were defined in the EPICS local db headers but
-// also are defined in cadef.h.
-// They are undefined here to avoid compiler warnings.
+// Including the DB/IOC based code + CA based client code gives warnings on redefinitions
+// so undef these before including the CA code.
 #undef DBR_SHORT
 #undef DBR_GR_LONG
 #undef DBR_GR_DOUBLE
-#undef DBR_CTRL_LONG
+#undef DBR_GR_LONG
 #undef DBR_CTRL_DOUBLE
+#undef DBR_CTRL_LONG
 #undef DBR_PUT_ACKT
 #undef DBR_PUT_ACKS
 #undef VALID_DB_REQ
 #undef INVALID_DB_REQ
-
-#include <pthread.h>
 #include "cadef.h"
 #endif
 
@@ -99,6 +119,14 @@ of this distribution.
 #define CA_STATE_RUNNING 2
 #define CA_STATE_EXIT 3
 
+enum SDF_TYPE {
+    SDF_NUM=0,
+    SDF_STR=1,
+    SDF_UNKNOWN=-1,
+};
+
+using PV_INT_TYPE = unsigned int;
+
 #if 0
 /// Pointers to status record
 DBENTRY  *pdbentry_status[2][10];
@@ -125,12 +153,12 @@ unsigned int fltrConst[17] = {16, 64, 256, 1024, 4096, 16384,
 };
 union Data {
 	double chval;
-	char strval[64];
+	fixed_string<64> strval{};
 };
 
 /// Structure for holding BURT settings in local memory.
 typedef struct CDS_CD_TABLE {
-	char chname[128];
+	fixed_string<128> chname;
 	int datatype;
 	union Data data;
 	int mask;
@@ -138,7 +166,7 @@ typedef struct CDS_CD_TABLE {
 	int filterswitch;
 	int filterNum;
 	int error;
-	char errMsg[64];
+	fixed_string<64> errMsg;
 	int chFlag;
 #ifdef CA_SDF
 	int connected;
@@ -147,7 +175,7 @@ typedef struct CDS_CD_TABLE {
 
 /// Structure for creating/holding filter module switch settings.
 typedef struct FILTER_TABLE {
-	char fname[64];
+	fixed_string<64> fname;
 	int swreq;
 	int swmask;
 	int sw[2];
@@ -158,15 +186,15 @@ typedef struct FILTER_TABLE {
 
 /// Structure for table data to be presented to operators.
 typedef struct SET_ERR_TABLE {
-	char chname[64];
-	char burtset[64];
-	char liveset[64];
-	char timeset[64];
-	char diff[64];
+	fixed_string<64> chname;
+	fixed_string<64> burtset;
+	fixed_string<64> liveset;
+	fixed_string<64> timeset;
+	fixed_string<64> diff;
 	double liveval;
 	int sigNum;
 	int chFlag;
-	int filtNum;
+	int filtNum{-1};
 	unsigned int sw[2];
 } SET_ERR_TABLE;
 
@@ -185,11 +213,19 @@ typedef struct EPICS_CA_TABLE {
 /// Structure to hold start up information for the CA thread
 typedef struct CA_STARTUP_INFO {
 	char *fname;		// name of the request file to parse
-	char *prefix;		// ifo name
 } CA_STARTUP_INFO;
 
 #endif
 
+using table_range = embedded::range<SET_ERR_TABLE*>;
+
+template <std::size_t entry_count>
+table_range
+make_range(fixed_size_vector<SET_ERR_TABLE, entry_count>& cont)
+{
+    return embedded::make_range(&cont[0], &cont[0] + cont.size());
+}
+
 // Gloabl variables		****************************************************************************************
 int chNum = 0;			///< Total number of channels held in the local lookup table.
 int chNotMon = 0;		///< Total number of channels not being monitored.
@@ -201,30 +237,30 @@ int chNotFound = 0;		///< Total number of channels read from BURT file which did
 int chNotInit = 0;		///< Total number of channels not initialized by the safe.snap BURT file.
 int rderror = 0;
 #ifndef USE_SYSTEM_TIME
-char timechannel[256];		///< Name of the GPS time channel for timestamping.
+std::unique_ptr< epics::DBEntry< epics::PVType::String > > timechannel{nullptr}; ///the GPS time channel for timestamping.
 #endif
 char reloadtimechannel[256];	///< Name of EPICS channel which contains the BURT reload requests.
 struct timespec t;
 char logfilename[128];
 
-CDS_CD_TABLE cdTable[SDF_MAX_TSIZE];		///< Table used to hold EPICS database info for monitoring settings.
-CDS_CD_TABLE cdTableP[SDF_MAX_CHANS];		///< Temp table filled on BURT read and set to EPICS channels.
-FILTER_TABLE filterTable[SDF_MAX_FMSIZE];			///< Table for holding filter module switch settings for comparisons.
-SET_ERR_TABLE setErrTable[SDF_ERR_TSIZE];	///< Table used to report settings diffs.
-SET_ERR_TABLE unknownChans[SDF_ERR_TSIZE];	///< Table used to report channels not found in local database.
-SET_ERR_TABLE uninitChans[SDF_ERR_TSIZE];	///< Table used to report channels not initialized by BURT safe.snap.
-SET_ERR_TABLE unMonChans[SDF_MAX_TSIZE];	///< Table used to report channels not being monitored.
-SET_ERR_TABLE readErrTable[SDF_ERR_TSIZE];	///< Table used to report file read errors..
-SET_ERR_TABLE cdTableList[SDF_MAX_TSIZE];	///< Table used to report file read errors..
-time_t timeTable[SDF_MAX_CHANS];		///< Holds timestamps for cdTableP
+fixed_size_vector<CDS_CD_TABLE, SDF_MAX_TSIZE> cdTable;       ///< Table used to hold EPICS database info for monitoring settings.
+fixed_size_vector<CDS_CD_TABLE, SDF_MAX_CHANS> cdTableP;      ///< Temp table filled on BURT read and set to EPICS channels.
+fixed_size_vector<FILTER_TABLE, SDF_MAX_FMSIZE> filterTable;  ///< Table for holding filter module switch settings for comparisons.
+fixed_size_vector<SET_ERR_TABLE, SDF_ERR_TSIZE> setErrTable;  ///< Table used to report settings diffs.
+fixed_size_vector<SET_ERR_TABLE, SDF_ERR_TSIZE> unknownChans; ///< Table used to report channels not found in local database.
+fixed_size_vector<SET_ERR_TABLE, SDF_ERR_TSIZE> uninitChans;  ///< Table used to report channels not initialized by BURT safe.snap.
+fixed_size_vector<SET_ERR_TABLE, SDF_MAX_TSIZE> unMonChans;	  ///< Table used to report channels not being monitored.
+fixed_size_vector<SET_ERR_TABLE, SDF_ERR_TSIZE> readErrTable; ///< Table used to report file read errors..
+fixed_size_vector<SET_ERR_TABLE, SDF_MAX_TSIZE> cdTableList;  ///< Table used to report file read errors..
+fixed_size_vector<time_t, SDF_MAX_CHANS> timeTable;           ///< Holds timestamps for cdTableP
 
-int filterMasks[SDF_MAX_FMSIZE];		///< Filter monitor masks, as manipulated by the user
+fixed_size_vector<int, SDF_MAX_FMSIZE> filterMasks;		///< Filter monitor masks, as manipulated by the user
 
-dbAddr fmMaskChan[SDF_MAX_FMSIZE];		///< We reflect the mask value into these channels
-dbAddr fmMaskChanCtrl[SDF_MAX_FMSIZE];		///< We signal bit changes to the masks on these channels
+fixed_size_vector<dbAddr, SDF_MAX_FMSIZE> fmMaskChan;		///< We reflect the mask value into these channels
+fixed_size_vector<dbAddr, SDF_MAX_FMSIZE> fmMaskChanCtrl;		///< We signal bit changes to the masks on these channels
 
 #ifdef CA_SDF
-SET_ERR_TABLE disconnectChans[SDF_MAX_TSIZE];
+fixed_size_vector<SET_ERR_TABLE, SDF_MAX_TSIZE> disconnectChans;
 
 // caTable, caConnTAble, chConnNum, chEnumDetermined are protected by the caTableMutex
 EPICS_CA_TABLE caTable[SDF_MAX_TSIZE];		    ///< Table used to hold the data returned by channel access
@@ -244,68 +280,64 @@ int chEnumDetermined = 0;			///< Total number of enums whos types have been dete
 long chDisconnected = 0;		///< Total number of channels that are disconnected.  This is used as the max index for disconnectedChans
 long chDisconnectedCount = 0;   ///< The count of the disconnected channels.  Seperate from chDisconnected so that it can be updated even when the table is not updated.
 
-pthread_t caThread;
-pthread_mutex_t caStateMutex;
-pthread_mutex_t caTableMutex;
-pthread_mutex_t caEvidMutex;
+
+std::mutex caStateMutex;
+std::mutex caTableMutex;
+std::mutex caEvidMutex;
+
+using lock_guard = std::lock_guard<std::mutex>;
 
 int caThreadState;
 long droppedPVCount;
 
-#define ADDRESS int
-#define SETUP setupCASDF();
-#define CLEANUP cleanupCASDF();
-#define GET_ADDRESS(NAME,ADDRP) getCAIndex((NAME),(ADDRP))
-#define PUT_VALUE(ADDR,TYPE,PVAL) setCAValue((ADDR),(TYPE),(PVAL))
-#define PUT_VALUE_INT(ADDR,PVAL) setCAValueEPICSLong((ADDR),(PVAL))
-#define GET_VALUE_NUM(ADDR,DESTP,TIMEP,CONNP) syncEpicsDoubleValue((ADDR),(DESTP),(TIMEP),(CONNP))
-#define GET_VALUE_INT(ADDR,DESTP,TIMEP,CONNP) syncEpicsIntValue((ADDR),(DESTP),(TIMEP),(CONNP))
-#define GET_VALUE_STR(ADDR,DESTP,LEN,TIMEP,CONNP) syncEpicsStrValue((ADDR),(DESTP),(LEN),(TIMEP),(CONNP))
+using ADDRESS = int;
+
+
 #else
-#define ADDRESS dbAddr
-#define SETUP
-#define CLEANUP
-#define GET_ADDRESS(NAME,ADDRP) dbNameToAddr((NAME),(ADDRP))
-#define PUT_VALUE(ADDR,TYPE,PVAL) dbPutField(&(ADDR),((TYPE)==SDF_NUM ? DBR_DOUBLE : DBR_STRING),(PVAL),1)
-#define PUT_VALUE_INT(ADDR,PVAL) dbPutField(&(ADDR),DBR_LONG,(int *)(PVAL),1);
-#define GET_VALUE_NUM(ADDR,DESTP,TIMEP,CONNP) getDbValueDouble(&(ADDR),(double*)(DESTP),(TIMEP))
-#define GET_VALUE_INT(ADDR,DESTP,TIMEP,CONNP) getDbValueLong(&(ADDR),(unsigned int*)(DESTP),(TIMEP))
-#define GET_VALUE_STR(ADDR,DESTP,LEN,TIMEP,CONNP) getDbValueString(&(ADDR),(char*)(DESTP),(LEN),(TIMEP))
+using ADDRESS = dbAddr;
 #endif
 
-#define SDF_NUM		0
-#define SDF_STR		1
-#define SDF_UNKNOWN	-1
-
 
 // Function prototypes		****************************************************************************************
-int isAlarmChannel(char *);
-int checkFileCrc(char *);
-int checkFileMod( char* , time_t* , int );
+bool isAlarmChannelRaw(const char *);
+int checkFileMod( const char* , time_t* , int );
 unsigned int filtCtrlBitConvert(unsigned int);
-void getSdfTime(char *, int size);
-void logFileEntry(char *);
-void getEpicsSettings(int, time_t *);
-int writeTable2File(char *,char *,int,CDS_CD_TABLE *);
-int savesdffile(int,int,char *,char *,char *,char *,char *,dbAddr,dbAddr,dbAddr); 
-int createSortTableEntries(int,int,char *,int *,time_t*);
-int reportSetErrors(char *,int,SET_ERR_TABLE *,int,int);
-int spChecker(int,SET_ERR_TABLE *,int,char *,int,int *);
-void newfilterstats(int);
-int writeEpicsDb(int,CDS_CD_TABLE *,int);
-int readConfig( char *,char *,int,char *);
-int parseLine(char *, int,char *,char *,char *,char *,char *,char *);
-int modifyTable(int,SET_ERR_TABLE *);
-int resetSelectedValues(int,SET_ERR_TABLE *);
-void clearTableSelections(int,SET_ERR_TABLE *, int *);
-void setAllTableSelections(int,SET_ERR_TABLE *, int *,int);
-void changeSelectCB_uninit(int, SET_ERR_TABLE *, int *);
-void decodeChangeSelect(int, int, int, SET_ERR_TABLE *, int *, void (*)(int, SET_ERR_TABLE *, int *));
-int appendAlarms2File(char *,char *,char *);
+void getSdfTime(embedded::fixed_string<256>&);
+void logFileEntry(const char *);
+void getEpicsSettings();
+
+template <std::size_t entry_count>
+bool writeTable2File(const char *burtdir, const char *filename, int ftype, fixed_size_vector<CDS_CD_TABLE, entry_count>& myTable);
+
+int savesdffile(int,int,const char *,const char *,const char *,const char *,const char *,epics::DBEntry<epics::PVType::String>&,epics::DBEntry<epics::PVType::String>&,epics::DBEntry<epics::PVType::String>&);
+int createSortTableEntries(int,int,const char *,int *,time_t*);
+template <std::size_t entry_count>
+int reportSetErrors(char *,fixed_size_vector<SET_ERR_TABLE, entry_count>&,int,int);
+template <std::size_t entry_count>
+int spChecker(int,fixed_size_vector<SET_ERR_TABLE, entry_count>&,int,const char *,int,int *);
+void newfilterstats();
+
+template <std::size_t entry_count>
+int writeEpicsDb(fixed_size_vector<CDS_CD_TABLE, entry_count>&,int);
+int readConfig( const char *, const char *,int, const char *);
+int modifyTable(table_range);
+template <std::size_t entry_count>
+int resetSelectedValues(fixed_size_vector<SET_ERR_TABLE, entry_count>&);
+template <std::size_t entry_count>
+void clearTableSelections(fixed_size_vector<SET_ERR_TABLE, entry_count>& dcsErrTable, int sc[]);
+void setAllTableSelections(table_range, int *,int);
+void changeSelectCB_uninit(SET_ERR_TABLE&, int *);
+void decodeChangeSelect(int, int, table_range, int *, void (*)(SET_ERR_TABLE&, int *));
+int appendAlarms2File(const char *,const char *,const char *);
 void registerFilters();
-void setupFMArrays(char *,int*,dbAddr*,dbAddr*);
-void resyncFMArrays(int *,dbAddr*);
-void processFMChanCommands(int*,dbAddr*,dbAddr*,int*,int,SET_ERR_TABLE*);
+void setupFMArrays(char *,fixed_size_vector<int, SDF_MAX_FMSIZE>&,
+        fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&,
+        fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&);
+void resyncFMArrays(fixed_size_vector<int, SDF_MAX_FMSIZE>&,fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&);
+void processFMChanCommands(fixed_size_vector<int, SDF_MAX_FMSIZE>&,
+        fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&,
+        fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&,
+        int*,table_range);
 void countDisconnectedChannels(int);
 void saveStrSetPoint(int, const char*);
 void updateStrVarSetPoint(int);
@@ -314,21 +346,21 @@ long countDisconnectedChans();
 
 void nullCACallback(struct event_handler_args);
 
-int getCAIndex(char *, ADDRESS *);
+bool getCAIndex(const char *, ADDRESS *);
 
 int canFindCAChannel(char *entry);
-int setCAValue(ADDRESS, int, void *);
-int setCAValueEPICSLong(ADDRESS, unsigned int *);
+bool setCAValue(ADDRESS, SDF_TYPE, const void *);
+bool setCAValueLong(ADDRESS, const PV_INT_TYPE *);
 
-int syncEpicsDoubleValue(ADDRESS, double *, time_t *, int *);
-int syncEpicsIntValue(ADDRESS, unsigned int *, time_t *, int *);
-int syncEpicsStrValue(ADDRESS, char *, int, time_t *, int *);
+bool syncEpicsDoubleValue(ADDRESS, double *, time_t *, int *);
+bool syncEpicsIntValue(ADDRESS, PV_INT_TYPE *, time_t *, int *);
+bool syncEpicsStrValue(ADDRESS, char *, int, time_t *, int *);
 
 void subscriptionHandler(struct event_handler_args);
 void connectCallback(struct connection_handler_args);
 void registerPV(char *);
 int daqToSDFDataType(int);
-void parseChannelListReq(char *, char *);
+void parseChannelListReq(char *);
 
 int getCAThreadState();
 void setCAThreadState(int state);
@@ -339,16 +371,103 @@ void syncCAConnections(long *);
 void *caMainLoop(void *);
 
 
-void initCAConnections(char *, char *);
+void initCAConnections(char *);
 void setupCASDF();
 void cleanupCASDF();
+
+void SETUP()
+{
+    setupCASDF();
+}
+void CLEANUP()
+{
+    cleanupCASDF();
+}
+
+bool GET_ADDRESS(const char* name, ADDRESS* addr)
+{
+    return getCAIndex(name, addr);
+}
+bool PUT_VALUE(ADDRESS addr, SDF_TYPE type, const void* pval)
+{
+    return setCAValue(addr, type, pval);
+}
+bool PUT_VALUE_INT(ADDRESS addr, const PV_INT_TYPE* val)
+{
+    return setCAValueLong(addr, val);
+}
+bool GET_VALUE_NUM(ADDRESS addr, double* dest, time_t* tp, int* connp)
+{
+    return syncEpicsDoubleValue(addr, dest, tp, connp);
+}
+bool GET_VALUE_INT(ADDRESS addr, PV_INT_TYPE* dest, time_t* tp, int* connp)
+{
+    return syncEpicsIntValue(addr, dest, tp, connp);
+}
+bool GET_VALUE_STR(ADDRESS addr, char* dest, int dest_size, time_t* tp, int *connp) {
+    return syncEpicsStrValue(addr, dest, dest_size, tp, connp);
+}
 #else
-int getDbValueDouble(ADDRESS*,double *,time_t *);
-int getDbValueString(ADDRESS*,char *, int, time_t *);
-int getDbValueLong(ADDRESS *,unsigned int * ,time_t *);
+bool getDbValueDouble(ADDRESS*,double *,time_t *);
+bool getDbValueString(ADDRESS*,char *, int, time_t *);
+bool getDbValueLong(ADDRESS *,PV_INT_TYPE * ,time_t *);
 void dbDumpRecords(DBBASE *,const char *);
+
+void SETUP()
+{}
+
+void CLEANUP()
+{}
+
+bool GET_ADDRESS(const char* name, ADDRESS* addr)
+{
+    return dbNameToAddr(name, addr) == 0;
+}
+
+bool PUT_VALUE(ADDRESS addr, SDF_TYPE type, const void* pval)
+{
+    return dbPutField(&addr,(type==SDF_NUM ? DBR_DOUBLE : DBR_STRING),pval,1) == 0;
+}
+bool PUT_VALUE_INT(ADDRESS addr, const PV_INT_TYPE *val)
+{
+    return dbPutField(&addr, DBR_LONG, val, 1) == 0;
+}
+bool GET_VALUE_NUM(ADDRESS addr, double* dest, time_t* tp, int* connp)
+{
+    return getDbValueDouble(&addr, dest, tp);
+}
+bool GET_VALUE_INT(ADDRESS addr, PV_INT_TYPE* dest, time_t* tp, int* connp)
+{
+    return getDbValueLong(&addr, dest, tp);
+}
+bool GET_VALUE_STR(ADDRESS addr, char* dest, int max_len, time_t *tp, int* connp)
+{
+    return getDbValueString(&addr, dest, max_len, tp);
+}
 #endif
 
+template <typename StringLike>
+bool
+PUT_VALUE_STR(ADDRESS addr, const StringLike& value)
+{
+    return PUT_VALUE(addr, SDF_STR, reinterpret_cast<void*>(const_cast<char*>(value.c_str())));
+}
+
+template <typename StringLike>
+bool
+GET_ADDRESS(const StringLike& name, ADDRESS* addr)
+{
+    return GET_ADDRESS(name.c_str(), addr);
+}
+
+template <typename StringLike>
+bool
+GET_VALUE_STR(ADDRESS addr, StringLike& dest, time_t *tp, int* connp)
+{
+    auto buffer = dest.get_buffer();
+    return GET_VALUE_STR(addr, buffer.data(), buffer.capacity(), tp, connp);
+}
+
 #ifdef VERBOSE_DEBUG
 #define D_NOW (__output_iter == 0)
 #define D(...) {if (__output_iter == 0) { fprintf(stderr, __VA_ARGS__); } }
@@ -384,150 +503,94 @@ void iterate_output_counter() {}
 //
 
 /// Given a channel name return 1 if it is an alarm channel, else 1
-int isAlarmChannel(char *chname) {
-	if (!chname) return 0;
-	return ((strstr(chname,".HIGH") != NULL) || 
-		(strstr(chname,".HIHI") != NULL) || 
-		(strstr(chname,".LOW") != NULL) || 
-		(strstr(chname,".LOLO") != NULL) || 
-		(strstr(chname,".HSV") != NULL) || 
-		(strstr(chname,".OSV") != NULL) || 
-		(strstr(chname,".ZSV") != NULL) || 
-		(strstr(chname,".LSV") != NULL) );
-}
-
-/// Common routine to parse lines read from BURT/SDF files..
-///	@param[in] *s	Pointer to line of chars to parse.
-///     @param[in] bufSize Size in characters of each output buffer str1 thru str6
-///	@param[out] str1 thru str6 	String pointers to return individual words from line.
-///	@return wc	Number of words in the line.
-int parseLine(char *s, int bufSize, char *str1, char *str2, char *str3, char *str4, char *str5,char *str6)
-{
-  int wc = 0;
-  int ii = 0;
-  int cursize = 0;
-  int lastwasspace = 0;
-  
-  char *lastquote = 0;
-  char *qch = 0;
-  char *out[7];
-  
-  out[0]=str1;
-  out[1]=str2;
-  out[2]=str3;
-  out[3]=str4;
-  out[4]=str5;
-  out[5]=str6;
-  out[6]=0;
-  for (ii = 0; out[ii]; ++ii) { *(out[ii]) = '\0'; }
-
-  while (*s != 0 && *s != '\n') {
-    if (*s == '\t') *s = ' ';
-    if (*s == ' ') {
-      // force the null termination of the output buffer
-      out[wc][bufSize-1] = '\0';
-      if (!lastwasspace) {
-	++wc;
-	// check for the end of the output buffers
-	if (!out[wc]) break;
-      }
-      lastwasspace = 1;
-      cursize = 0;
-    } else if (*s != '"' || !lastwasspace) {
-      // regular character
-      if (cursize < bufSize) {
-	strncat(out[wc], s, 1);
-	cursize++;
-      }
-      lastwasspace = 0;
-    } else {
-      // quote
-      // burt does not escape quotes, you have to look for the last quote and just take it.
-      lastquote = 0;
-      qch = s+1;
-      
-      while (*qch && *qch !='\n') {
-	if (*qch == '"') lastquote = qch;
-	++qch;
-      }
-      if (!lastquote) lastquote = qch;
-      ++s;
-      // copy from (s,qch) then set lastwasspace
-      while (s < lastquote) {
-	if (cursize < bufSize) {
-	  strncat(out[wc], s, 1);
-	  cursize++;
-	}
-	++s;
-      }
-      ++wc;
-      lastwasspace = 1;
-      if (!(*s) || *s == '\n' || !out[wc]) break;
+template <typename StringLike>
+bool isAlarmChannel(const StringLike& chname) {
+	return isAlarmChannelRaw(chname.c_str());
+//    return ((strstr(chname.c_str(),".HIGH") != NULL) ||
+//		(strstr(chname.c_str(),".HIHI") != NULL) ||
+//		(strstr(chname.c_str(),".LOW") != NULL) ||
+//		(strstr(chname.c_str(),".LOLO") != NULL) ||
+//		(strstr(chname.c_str(),".HSV") != NULL) ||
+//		(strstr(chname.c_str(),".OSV") != NULL) ||
+//		(strstr(chname.c_str(),".ZSV") != NULL) ||
+//		(strstr(chname.c_str(),".LSV") != NULL) );
+}
+
+bool isAlarmChannelRaw(const char* chname) {
+    if (chname == nullptr)
+    {
+        return false;
     }
-    ++s;
-  }
-  if (out[wc] && out[wc][0]) {
-    out[wc][bufSize-1]='\0';
-    ++wc;
-  }
-  for (ii = 0; out[ii]; ++ii) {
-    if (strcmp(out[ii], "\\0") == 0) strcpy(out[ii], "");
-  }
-  return wc;
+    return ((strstr(chname,".HIGH") != nullptr) ||
+            (strstr(chname,".HIHI") != nullptr) ||
+            (strstr(chname,".LOW") != nullptr) ||
+            (strstr(chname,".LOLO") != nullptr) ||
+            (strstr(chname,".HSV") != nullptr) ||
+            (strstr(chname,".OSV") != nullptr) ||
+            (strstr(chname,".ZSV") != nullptr) ||
+            (strstr(chname,".LSV") != nullptr) );
 }
 
+
+
 /// Common routine to clear all entries for table changes..
 ///	@param[in] numEntries		Number of entries in the table.	
 ///	@param[in] dcsErrtable 		Pointer to table
 ///	@param[out] sc 			Pointer to change counters.
-void clearTableSelections(int numEntries,SET_ERR_TABLE *dcsErrTable, int sc[])
+template <std::size_t entry_count>
+void clearTableSelections(fixed_size_vector<SET_ERR_TABLE, entry_count>& dcsErrTable, int sc[])
 {
-int ii;
+    int ii;
 	for(ii=0;ii<3;ii++) sc[ii] = 0;
-	for(ii=0;ii<numEntries;ii++) dcsErrTable[ii].chFlag = 0;
-	for(ii=0;ii<numEntries;ii++) dcsErrTable[ii].filtNum = -1;
+	for (auto& entry:dcsErrTable)
+    {
+	    entry.chFlag = 0;
+	    entry.filtNum = -1;
+    }
 }
 
-
 /// Common routine to set all entries for table changes..
 ///	@param[in] numEntries		Number of entries in the table.	
 ///	@param[in] dcsErrtable 		Pointer to table
 ///	@param[out] sc 			Pointer to change counters.
 ///	@param[in] selectOp 		Present selection.
-void setAllTableSelections(int numEntries,SET_ERR_TABLE *dcsErrTable, int sc[],int selectOpt)
+void setAllTableSelections(table_range dcsErrTable, int sc[],int selectOpt)
 {
-int ii;
-int filtNum = -1;
-long status = 0;
+    int filtNum = -1;
+    long status = 0;
+
 	switch(selectOpt) {
 		case 1:
 			sc[0] = 0;
-			for(ii=0;ii<numEntries;ii++) {
-				dcsErrTable[ii].chFlag |= 2;
+			for (auto& entry:dcsErrTable)
+			{
+				entry.chFlag |= 2;
 				sc[0] ++;
-				if(dcsErrTable[ii].chFlag & 4) {
-					dcsErrTable[ii].chFlag &= ~(4);
+				if(entry.chFlag & 4) {
+					entry.chFlag &= ~(4);
 					sc[1] --;
 				}
 			}
 			break;
 		case 2:
 			sc[1] = 0;
-			for(ii=0;ii<numEntries;ii++) {
-				dcsErrTable[ii].chFlag |= 4;
+            for (auto& entry:dcsErrTable)
+			{
+				entry.chFlag |= 4;
 				sc[1] ++;
-				if(dcsErrTable[ii].chFlag & 2) {
-					dcsErrTable[ii].chFlag &= ~(2);
+				if(entry.chFlag & 2) {
+					entry.chFlag &= ~(2);
 					sc[0] --;
 				}
 			}
 			break;
 		case 3:
-			sc[2] = numEntries;
-			for(ii=0;ii<numEntries;ii++) {
-				dcsErrTable[ii].chFlag |= 8;
+			sc[2] = std::distance(dcsErrTable.begin(), dcsErrTable.end());
+            for (auto& entry:dcsErrTable)
+			{
+				entry.chFlag |= 8;
 				
-				filtNum = dcsErrTable[ii].filtNum;
+				filtNum = entry.filtNum;
 				if (filtNum >= 0) {
 					if (filterMasks[filtNum] == filterTable[filtNum].mask) {
 						filterMasks[filtNum] = ((ALL_SWSTAT_BITS & filterMasks[filtNum]) > 0 ? 0 : ~0);
@@ -545,12 +608,12 @@ long status = 0;
 ///	@param[in] index		Number providing the index into the dcsErrTable
 ///	@param[in] dcsErrTable		Pointer to table
 ///	@param[out] selectCounter	Pointer to change counters
-void changeSelectCB_uninit(int index, SET_ERR_TABLE *dcsErrTable, int selectCounter[])
+void changeSelectCB_uninit(SET_ERR_TABLE &errTableEntry, int selectCounter[])
 {
-	int revertBit = dcsErrTable[index].chFlag & 2;
-	int acceptBit = dcsErrTable[index].chFlag & 4;
-	int monBit = dcsErrTable[index].chFlag & 8;
-	int otherBits = 0; //dcsErrTable[index].chFlag | ~(2 | 4 | 8);
+	int revertBit = errTableEntry.chFlag & 2;
+	int acceptBit = errTableEntry.chFlag & 4;
+	int monBit = errTableEntry.chFlag & 8;
+	int otherBits = 0; //errTableEntry.chFlag | ~(2 | 4 | 8);
 
 	// revert is not defined on this table
 	if (revertBit) {
@@ -562,7 +625,7 @@ void changeSelectCB_uninit(int index, SET_ERR_TABLE *dcsErrTable, int selectCoun
 		acceptBit = 4;
 		selectCounter[1] ++;
 	} 
-	dcsErrTable[index].chFlag = revertBit | acceptBit | monBit | otherBits;
+	errTableEntry.chFlag = revertBit | acceptBit | monBit | otherBits;
 }
 
 /// Common routine to set/unset individual entries for table changes..
@@ -571,40 +634,42 @@ void changeSelectCB_uninit(int index, SET_ERR_TABLE *dcsErrTable, int selectCoun
 ///	@param[in] totalItems		Number items selected for change.
 ///	@param[in] dcsErrtable 		Pointer to table
 ///	@param[out] selectCounter 	Pointer to change counters.
-void decodeChangeSelect(int selNum, int page, int totalItems, SET_ERR_TABLE *dcsErrTable, int selectCounter[], void (*cb)(int, SET_ERR_TABLE*, int*))
+void decodeChangeSelect(int selNum, int page, table_range dcsErrTable, int selectCounter[], void (*cb)(SET_ERR_TABLE&, int*))
 {
-int selectBit;
-int selectLine;
+    int selectBit;
+    int selectLine;
 
 	selectBit = selNum / 100;
 	selectLine = selNum % 100 - 1;
 	selNum += page * SDF_ERR_DSIZE;
 	selectLine += page * SDF_ERR_DSIZE;
-	if(selectLine < totalItems) {
+
+	auto selection = dcsErrTable.begin() + selectLine;
+	if(selection < dcsErrTable.end()) {
 		switch (selectBit) {
 			case 0:
-				dcsErrTable[selectLine].chFlag ^= 2;
-				if(dcsErrTable[selectLine].chFlag & 2) selectCounter[0] ++;
+				selection->chFlag ^= 2;
+				if(selection->chFlag & 2) selectCounter[0] ++;
 				else selectCounter[0] --;
-				if(dcsErrTable[selectLine].chFlag & 4) {
-					dcsErrTable[selectLine].chFlag &= ~(4);
+				if(selection->chFlag & 4) {
+					selection->chFlag &= ~(4);
 					selectCounter[1] --;
 				}
 				break;
 			case 1:
-				dcsErrTable[selectLine].chFlag ^= 4;
-				if(dcsErrTable[selectLine].chFlag & 4) selectCounter[1] ++;
+				selection->chFlag ^= 4;
+				if(selection->chFlag & 4) selectCounter[1] ++;
 				else selectCounter[1] --;
-				if(dcsErrTable[selectLine].chFlag & 2) {
-					dcsErrTable[selectLine].chFlag &= ~(2);
+				if(selection->chFlag & 2) {
+					selection->chFlag &= ~(2);
 					selectCounter[0] --;
 				}
 				break;
 			case 2:
 				/* we only handle non-filter bank entries here */
-				if (dcsErrTable[selectLine].filtNum < 0) {
-					dcsErrTable[selectLine].chFlag ^= 8;
-					if(dcsErrTable[selectLine].chFlag & 8) selectCounter[2] ++;
+				if (selection->filtNum < 0) {
+					selection->chFlag ^= 8;
+					if(selection->chFlag & 8) selectCounter[2] ++;
 					else selectCounter[2] --;
 				}
 				break;
@@ -612,13 +677,13 @@ int selectLine;
 				break;
 		}
 		if (cb)
-			cb(selectLine, dcsErrTable, selectCounter);
+			cb(*selection, selectCounter);
 	}
 }
 
 // Check for file modification time changes
 int
-checkFileMod( char* fName, time_t* last_mod_time, int gettime )
+checkFileMod( const char* fName, time_t* last_mod_time, int gettime )
 {
     struct stat statBuf;
     if ( !stat( fName, &statBuf ) )
@@ -644,32 +709,7 @@ checkFileMod( char* fName, time_t* last_mod_time, int gettime )
     }
 }
 
-/// Common routine to check file CRC.
-///	@param[in] *fName	Name of file to check.
-///	@return File CRC or -1 if file not found.
-int checkFileCrc(char *fName)
-{
-    char         cbuf[ 128 ];
-    char*        cp;
-    int          flen = 0;
-    int          clen = 0;
-    unsigned int crc = 0;
-    FILE*        fp = fopen( fName, "r" );
-    if ( fp == NULL )
-    {
-        return 0;
-    }
 
-    while ( ( cp = fgets( cbuf, 128, fp ) ) != NULL )
-    {
-        clen = strlen( cbuf );
-        flen += clen;
-        crc = crc_ptr( cbuf, clen, crc );
-    }
-    crc = crc_len( flen, crc );
-    fclose( fp );
-    return crc;
-}
 
 /// Quick convert of filter switch settings to match SWMASK
 ///	@param[in] v	UINT32 representation of filter module switch setting.
@@ -686,7 +726,8 @@ unsigned int filtCtrlBitConvert(unsigned int v) {
 ///	@param[in] v			SWSTAT representation of switch setting.	
 ///	@param[out] filterstring	Returned string representation of switch setting.	
 ///	@return				Always zero at this point.
-int filtStrBitConvert(int stype, unsigned int v, char *filterstring) {
+template <typename StringLike>
+int filtStrBitConvert(int stype, unsigned int v, StringLike& filterstring) {
 unsigned int val[5],jj;
 unsigned int x;
 char bitDefShort[16][8] = {"IN,","OF,","1,","2,",
@@ -704,26 +745,26 @@ char bitDefLong[16][8] = {"IN,","OF,","F1,","F2,",
 	val[3] = (v & 0x1000) << 1;		// Output
 	val[4] = (v & 0x18000) >> 1;		// Dec and Hold
 	x = val[0] + val[1] + val[2] + val[3] + val[4];
-	sprintf(filterstring,"%s","");
+	filterstring.clear();
 	for(jj=0;jj<16;jj++) {
-		if(x & 1 && stype == 0) strcat(filterstring,bitDefShort[jj]);
-		if(x & 1 && stype == 1) strcat(filterstring,bitDefLong[jj]);
+		if(x & 1 && stype == 0) filterstring += bitDefShort[jj];
+		if(x & 1 && stype == 1) filterstring += bitDefLong[jj];
 		x = x >> 1;
 	}
-	filterstring[strlen(filterstring) - 1] = 0;
 	// strcat(filterstring,"\0");
         return(0);
 }
 
 /// Given the a filter table entry print out the bits set in the mask.
 /// @param[in] filter the filter table entry to extract the current value from
-/// @param[out] dest buffer to put the results in. must be >= 64 bytes
-void createSwitchText(FILTER_TABLE *filter, char *dest) {
+/// @param[out] dest buffer to put the results in
+template <typename StringLike>
+void createSwitchText(FILTER_TABLE *filter, StringLike& dest) {
 #if 1
 	int sw1s=0;
 	int sw2s=0;
 
-	dest[0] = 0;
+	dest.clear();
 	sw1s = (int)cdTableP[filter->sw[0]].data.chval;
 	sw2s = (int)cdTableP[filter->sw[1]].data.chval;
 #else
@@ -749,10 +790,10 @@ void createSwitchText(FILTER_TABLE *filter, char *dest) {
 }
 
 /// Routine to check filter switch settings and provide info on switches not set as requested.
-/// @param[in] fcount	Number of filters in the control model.
 /// @param[in] monitorAll	Global monitoring flag.
 /// @return	Number of errant switch settings found.
-int checkFilterSwitches(int fcount, SET_ERR_TABLE setErrTable[], int monitorAll, int displayall, int wcflag, char *wcstr, int *diffcntr)
+template <std::size_t entry_count>
+int checkFilterSwitches(fixed_size_vector<SET_ERR_TABLE, entry_count>& setErrTable, int monitorAll, int displayall, int wcflag, const char *wcstr, int *diffcntr)
 {
 unsigned int refVal=0;
 unsigned int presentVal=0;
@@ -760,15 +801,14 @@ unsigned int x=0,y=0;
 unsigned int mask = 0;
 unsigned int maskedRefVal = 0;
 unsigned int maskedSwReqVal = 0;
-int ii=0,jj=0;
+int jj=0;
 int errCnt = 0;
-char swname[3][64];
-char tmpname[64];
+fixed_string<64>swname[3];
+fixed_string<64> tmpname;
 time_t mtime=0;
-char localtimestring[256];
-char swstrE[64];
-char swstrB[64];
-char swstrD[64];
+fixed_string<64> swstrE;
+fixed_string<64> swstrB;
+fixed_string<64> swstrD;
 struct buffer {
 	time_t t;
 	unsigned int rval;
@@ -778,38 +818,36 @@ ADDRESS paddr1;
 ADDRESS paddr2;
 long status=0;
 
-    swstrE[0]='\0';
-    swstrB[0]='\0';
-    swstrD[0]='\0';
-	for(ii=0;ii<fcount;ii++)
-	{
+    auto filtNum = -1;
+    for (const auto& curFilt:filterTable)
+    {
+        ++filtNum;
 		bzero(buffer, sizeof(struct buffer)*2);
-		bzero(swname[0],sizeof(swname[0]));
-		bzero(swname[1],sizeof(swname[1]));
-		strcpy(swname[0],filterTable[ii].fname);
-		strcat(swname[0],"SW1S");
-		strcpy(swname[1],filterTable[ii].fname);
-		strcat(swname[1],"SW2S");
-		sprintf(swname[2],"%s",filterTable[ii].fname);
-		strcat(swname[2],"SWSTR");
-		status = GET_ADDRESS(swname[0],&paddr);
-		status = GET_VALUE_INT(paddr,&(buffer[0].rval),&(buffer[0].t), 0);
-		status = GET_ADDRESS(swname[1],&paddr1);
-		status = GET_VALUE_INT(paddr1,&(buffer[1].rval),&(buffer[1].t), 0);
+
+		swname[0] = curFilt.fname;
+		swname[0] += "SW1S";
+		swname[1] = curFilt.fname;
+		swname[1] += "SW2S";
+		swname[2] = curFilt.fname;
+		swname[2] += "SWSTR";
+		GET_ADDRESS(swname[0],&paddr);
+		GET_VALUE_INT(paddr,&(buffer[0].rval),&(buffer[0].t), 0);
+		GET_ADDRESS(swname[1],&paddr1);
+		GET_VALUE_INT(paddr1,&(buffer[1].rval),&(buffer[1].t), 0);
 		for(jj=0;jj<2;jj++) {
 			if(buffer[jj].rval > 0xffff || buffer[jj].rval < 0)	// Switch setting overrange
 			{
-				sprintf(setErrTable[errCnt].chname,"%s", swname[jj]);
-				sprintf(setErrTable[errCnt].burtset, "%s", " ");
-				sprintf(setErrTable[errCnt].liveset, "0x%x", buffer[jj].rval);
-				sprintf(setErrTable[errCnt].diff, "%s", "OVERRANGE");
-				setErrTable[errCnt].liveval = 0.0;
-				setErrTable[errCnt].sigNum = filterTable[ii].sw[jj];
+			    setErrTable.emplace_back();
+			    auto& curErr = setErrTable.back();
+				curErr.chname = swname[jj];
+				curErr.burtset = " ";
+				curErr.liveset.printf("0x%x", buffer[jj].rval);
+				curErr.diff = "OVERRANGE";
+				curErr.liveval = 0.0;
+				curErr.sigNum = curFilt.sw[jj];
 				// take the latest change time between the SW1S & SW2S channels
 				mtime = (buffer[0].t >= buffer[1].t ? buffer[0].t : buffer[1].t);
-				strcpy(localtimestring, ctime(&mtime));
-				localtimestring[strlen(localtimestring) - 1] = 0;
-				sprintf(setErrTable[errCnt].timeset, "%s", localtimestring);
+				curErr.timeset = ctime(&mtime);
 				buffer[jj].rval &= 0xffff;
 				errCnt ++;
 			}
@@ -818,44 +856,43 @@ long status=0;
 		refVal = filtCtrlBitConvert(presentVal);
 		filtStrBitConvert(0,refVal,swstrE);
 		x = refVal;
-		status = GET_ADDRESS(swname[2],&paddr2);
-		status = PUT_VALUE(paddr2,SDF_STR,swstrE);
-		setErrTable[errCnt].filtNum = -1;
+		GET_ADDRESS(swname[2],&paddr2);
+		PUT_VALUE_STR(paddr2,swstrE);
+		//setErrTable[errCnt].filtNum = -1;
 
-		mask = (unsigned int)filterTable[ii].mask;
+		mask = (unsigned int)curFilt.mask;
 		maskedRefVal = refVal & mask;
-		maskedSwReqVal = filterTable[ii].swreq & mask;
-		if(( maskedRefVal != maskedSwReqVal && errCnt < SDF_ERR_TSIZE && (mask || monitorAll) && filterTable[ii].init) )
+		maskedSwReqVal = curFilt.swreq & mask;
+		if(( maskedRefVal != maskedSwReqVal && errCnt < SDF_ERR_TSIZE && (mask || monitorAll) && curFilt.init) )
 			*diffcntr += 1;
-		if(( maskedRefVal != maskedSwReqVal && errCnt < SDF_ERR_TSIZE && (mask || monitorAll) && filterTable[ii].init) || displayall)
+		if(( maskedRefVal != maskedSwReqVal && errCnt < SDF_ERR_TSIZE && (mask || monitorAll) && curFilt.init) || displayall)
 		{
 			filtStrBitConvert(1,refVal,swstrE);
-			filtStrBitConvert(1,filterTable[ii].swreq,swstrB);
+			filtStrBitConvert(1,curFilt.swreq,swstrB);
 			x = maskedRefVal ^ maskedSwReqVal;
 			filtStrBitConvert(1,x,swstrD);
-			bzero(tmpname,sizeof(tmpname));
-			strncpy(tmpname,filterTable[ii].fname,(strlen(filterTable[ii].fname)-1));
-
-			if(!wcflag || (wcflag && (strstr(tmpname,wcstr) != NULL))) {
-			sprintf(setErrTable[errCnt].chname,"%s", tmpname);
-			sprintf(setErrTable[errCnt].burtset, "%s", swstrB);
-			sprintf(setErrTable[errCnt].liveset, "%s", swstrE);
-			sprintf(setErrTable[errCnt].diff, "%s", swstrD);
-			
-			setErrTable[errCnt].liveval = 0.0;
-			setErrTable[errCnt].sigNum = filterTable[ii].sw[0] + (filterTable[ii].sw[1] * SDF_MAX_TSIZE);
-			setErrTable[errCnt].filtNum = ii;
-			setErrTable[errCnt].sw[0] = buffer[0].rval;
-			setErrTable[errCnt].sw[1] = buffer[1].rval;
-			if(filterTable[ii].mask & ALL_SWSTAT_BITS) setErrTable[errCnt].chFlag |= 0x1;
-			else setErrTable[errCnt].chFlag &= 0xe;
-
-			// take the latest change time between the SW1S & SW2S channels
-			mtime = (buffer[0].t >= buffer[1].t ? buffer[0].t : buffer[1].t);
-			strcpy(localtimestring, ctime(&mtime));
-			localtimestring[strlen(localtimestring) - 1] = 0;
-			sprintf(setErrTable[errCnt].timeset, "%s", localtimestring);
-			errCnt ++;
+			tmpname = curFilt.fname;
+
+			if(!wcflag || (wcflag && (strstr(tmpname.c_str(),wcstr) != NULL))) {
+			    setErrTable.emplace_back();
+			    auto& curErr = setErrTable.back();
+                curErr.chname = tmpname;
+                curErr.burtset = swstrB;
+                curErr.liveset = swstrE;
+                curErr.diff = swstrD;
+
+                curErr.liveval = 0.0;
+                curErr.sigNum = curFilt.sw[0] + (curFilt.sw[1] * SDF_MAX_TSIZE);
+                curErr.filtNum = filtNum;
+                curErr.sw[0] = buffer[0].rval;
+                curErr.sw[1] = buffer[1].rval;
+                if(curFilt.mask & ALL_SWSTAT_BITS) curErr.chFlag |= 0x1;
+                else curErr.chFlag &= 0xe;
+
+                // take the latest change time between the SW1S & SW2S channels
+                mtime = (buffer[0].t >= buffer[1].t ? buffer[0].t : buffer[1].t);
+                curErr.timeset = ctime(&mtime);
+                errCnt ++;
 			}
 		}
 	}
@@ -865,7 +902,7 @@ long status=0;
 /// Routine for reading and formatting the time as a string.
 ///	@param[out] timestring 	Pointer to char string in which GPS time is to be written.
 /// @note This can use the GPS time from the model, or if configured with USE_SYSTEM_TIME the system time.
-void getSdfTime(char *timestring, int size)
+void getSdfTime(embedded::fixed_string<256>& timestring)
 {
 #ifdef USE_SYSTEM_TIME
 	time_t t=0;
@@ -873,107 +910,88 @@ void getSdfTime(char *timestring, int size)
 
 	t = time(NULL);
 	localtime_r(&t, &tdata);
-	if (timestring && size > 0) {
-		if (strftime(timestring, size, "%a %b %e %H:%M:%S %Y", &tdata) == 0) {
-			timestring[0] = '\0';
-		}
-	}
+
+    auto buf = timestring.get_buffer();
+    strftime(buf.data(), buf.capacity(), "%a %b %e %H:%M:%S %Y", &tdata);
 #else
 	dbAddr paddr;
 	long ropts = 0;
 	long nvals = 1;
 	long status;
 
-	status = dbNameToAddr(timechannel,&paddr);
-	status = dbGetField(&paddr,DBR_STRING,timestring,&ropts,&nvals,NULL);
+    timechannel->get(timestring);
 #endif
 }
 
 /// Routine for logging messages to ioc.log file.
 /// 	@param[in] message Ptr to string containing message to be logged.
-void logFileEntry(char *message)
+void logFileEntry(const char *message)
 {
-	FILE *log=0;
-	char timestring[256];
-	long status=0;
-	dbAddr paddr;
+    static std::unique_ptr < std::FILE, std::function<void(std::FILE*) > > fp = nullptr;
+    static bool open_attempted = false;
 
-	getSdfTime(timestring, 256);
-	log = fopen(logfilename,"a");
-	if(log == NULL) {
-		status = dbNameToAddr(reloadtimechannel,&paddr);
-		status = dbPutField(&paddr,DBR_STRING,"ERR - NO LOG FILE FOUND",1);
-	} else {
-		fprintf(log,"%s\n%s\n",timestring,message);
-		fprintf(log,"***************************************************\n");
-		fclose(log);
-	}
+    embedded::fixed_string<256> timestring{};
+    dbAddr paddr;
+    getSdfTime(timestring);
 
+    if(fp.get() == nullptr && !open_attempted )
+    {
+        open_attempted = true;
+        fp = std::unique_ptr < std::FILE, std::function<void(std::FILE*)>>(
+            std::fopen(logfilename, "a"),
+            [](std::FILE * fp) { std::fclose(fp); });
+
+        if(fp.get() == NULL) {
+            dbNameToAddr(reloadtimechannel, &paddr);
+            dbPutField(&paddr, DBR_STRING, "ERR - NO LOG FILE FOUND",1);
+            embedded::fixed_string<256> error_msg( "Failed to open log file: ");
+            error_msg += logfilename;
+            error_msg +=  " : ";
+            perror(error_msg.c_str());
+        }
+    }
+
+
+    if(fp.get() != nullptr)
+    {
+        fprintf(fp.get(), "%s\n%s\n", timestring.c_str(), message);
+        fprintf(fp.get(), "***************************************************\n");
+        //We might not need this fflush, but adding it in case the 
+        //flush as part of the fclose() was required
+        fflush(fp.get()); 
+    }
 }
 
 
 /// Function to read all settings, listed in main table, from the EPICS database.
 ///	@param[in] numchans The number of channels listed in the main table.
 ///	@param[out] times (Optional) An array of at least numchans time_t values to put change times in
-void getEpicsSettings(int numchans, time_t *times)
+void getEpicsSettings()
 {
-int ii;
-long status;
-int chcount = 0;
-double dval = 0;
-ADDRESS geaddr;
-long statusR = 0;
-char sval[64];
-time_t *change_t = 0;
-
-	for(ii=0;ii<numchans;ii++)
-	{
-		// Load main table settings into temp (cdTableP)
-		sprintf(cdTableP[ii].chname,"%s",cdTable[ii].chname);
-		cdTableP[ii].datatype = cdTable[ii].datatype;
-		cdTableP[ii].mask = cdTable[ii].mask;
-		cdTableP[ii].initialized = cdTable[ii].initialized;
-		// Find address of channel
-		status = GET_ADDRESS(cdTableP[ii].chname,&geaddr);
-		if(!status) {
-			change_t = ( times ? &times[ii] : 0 );
-			if(cdTableP[ii].datatype == SDF_NUM)
-			{
-				statusR = GET_VALUE_NUM(geaddr,&dval,change_t, NULL); //&(cdTableP[ii].connected));
-				if (!statusR) cdTableP[ii].data.chval = (cdTable[ii].filterswitch ? (int)dval & 0xffff : dval);
-			} else {
-				statusR = GET_VALUE_STR(geaddr,sval,sizeof(sval),change_t, NULL); //&(cdTableP[ii].connected));
-				if(!statusR) sprintf(cdTableP[ii].data.strval,"%s",sval);
-			}
-			chcount ++;
-		}
-	}
-}
-
-void encodeBURTString(char *src, char *dest, int dest_size) {
-	char *ch = 0;
-	int expand = 0;
-
-	if (!src || !dest || dest_size < 1) return;
-	dest[0]='\0';
-	// make sure the destination can handle expansion which is two characters + a NULL
-	if (dest_size < (strlen(src) + 3)) return;
-	if (strlen(src) == 0) {
-		strcpy(dest, "\\0");
-	} else {
-		for (ch = src; *ch; ++ch) {
-			if (*ch == ' ' || *ch == '\t' || *ch == '\n' || *ch == '"') {
-				expand = 1;
-				break;
-			}
-		}
-		// we already bounds check this above
-		if (expand) {
-			sprintf(dest, "\"%s\"", src);
-		} else {
-			strcpy(dest, src);
-		}
-	}
+    cdTableP.clear();
+    std::transform(cdTable.begin(), cdTable.end(), std::back_inserter( cdTableP),
+                   [](const CDS_CD_TABLE& entry) -> CDS_CD_TABLE {
+        CDS_CD_TABLE result;
+        result.chname = entry.chname;
+        result.datatype = entry.datatype;
+        result.mask = entry.mask;
+        result.initialized = entry.initialized;
+
+        ADDRESS geaddr;
+        if(GET_ADDRESS(result.chname,&geaddr)) {
+            time_t* change_t = nullptr;
+           if(result.datatype == SDF_NUM)
+           {
+               double dval;
+               if (GET_VALUE_NUM(geaddr,&dval,change_t, NULL)) {
+                   result.data.chval = (entry.filterswitch ? (int) dval & 0xffff : dval);
+               }
+           } else {
+               GET_VALUE_STR(geaddr,result.data.strval, change_t, NULL);
+           }
+       }
+        return result;
+    });
 }
 
 // writeTable2File ftype options:
@@ -981,17 +999,19 @@ void encodeBURTString(char *src, char *dest, int dest_size) {
 #define SDF_FILE_PARAMS_ONLY	1
 #define SDF_FILE_BURT_ONLY	2
 /// Common routine for saving table data to BURT files.
-int writeTable2File(char *burtdir,
-		    char *filename, 		///< Name of file to write
+template <std::size_t entry_count>
+bool writeTable2File(const char *burtdir,
+                     const char *filename, 		///< Name of file to write
 		    int ftype, 			///< Type of file to write
-		    CDS_CD_TABLE myTable[])	///< Table to be written.
+		    fixed_size_vector<CDS_CD_TABLE, entry_count>& myTable)	///< Table to be written.
 {
         int ii;
-        FILE *csFile=0;
-        char filemsg[128];
-	char timestring[128];
-	char monitorstring[128];
-	char burtString[64+2];
+        FILE *csFile=nullptr;
+        embedded::fixed_string<128> filemsg;
+	embedded::fixed_string<256> timestring;
+	embedded::fixed_string<128> monitorstring;
+
+	embedded::fixed_string<64+2> burtString;
 #ifdef CA_SDF
 	int precision = 20;
 #else
@@ -999,18 +1019,18 @@ int writeTable2File(char *burtdir,
 #endif
     // Write out local monitoring table as snap file.
         errno=0;
-	burtString[0] = '\0';
+	burtString = "";
         csFile = fopen(filename,"w");
-        if (csFile == NULL)
+        if (csFile == nullptr)
         {
-            sprintf(filemsg,"ERROR Failed to open %s - %s",filename,strerror(errno));
-            logFileEntry(filemsg);
-	    return(-1);
+            filemsg.printf("ERROR Failed to open %s - %s",filename,strerror(errno));
+            logFileEntry(filemsg.c_str());
+	    return(false);
         }
 	// Write BURT header
-	getSdfTime(timestring, 128);
+	getSdfTime(timestring);
 	fprintf(csFile,"%s\n","--- Start BURT header");
-	fprintf(csFile,"%s%s\n","Time:      ",timestring);
+	fprintf(csFile,"%s%s\n","Time:      ",timestring.c_str());
 	fprintf(csFile,"%s\n","Login ID: controls ()");
 	fprintf(csFile,"%s\n","Eff  UID: 1001 ");
 	fprintf(csFile,"%s\n","Group ID: 1001 ");
@@ -1021,48 +1041,52 @@ int writeTable2File(char *burtdir,
 	fprintf(csFile,"%s\n","Req File: autoBurt.req ");
 	fprintf(csFile,"%s\n","--- End BURT header");
 
-	for(ii=0;ii<chNum;ii++)
+	for (const auto& entry:myTable)
 	{
-		if (myTable[ii].filterswitch) {
-			if ((myTable[ii].mask & ALL_SWSTAT_BITS)== ~0) {
-				strcpy(monitorstring, "1");
-			} else if ((myTable[ii].mask & ALL_SWSTAT_BITS) == 0) {
-				strcpy(monitorstring, "0");
+		if (entry.filterswitch) {
+			if ((entry.mask & ALL_SWSTAT_BITS)== ~0) {
+                            monitorstring = "1";
+			} else if ((entry.mask & ALL_SWSTAT_BITS) == 0) {
+                            monitorstring = "0";
 			} else {
-				snprintf(monitorstring, sizeof(monitorstring), "0x%x", myTable[ii].mask);
-			}
+                            monitorstring.printf("0x%x", entry.mask);
+                        }
 		} else {
-			if (myTable[ii].mask)
-				strcpy(monitorstring,"1");
-			else
-				strcpy(monitorstring,"0");
-		}
+			if (entry.mask)
+                        {
+                            monitorstring = "1";
+                        } else
+                        {
+                            monitorstring = "0";
+                        }
+                }
 		switch(ftype)
 		{
 		   case SDF_WITH_INIT_FLAG:
 			if(myTable[ii].datatype == SDF_NUM) {
-				fprintf(csFile,"%s %d %.*e %s %d\n",myTable[ii].chname,1,precision,myTable[ii].data.chval,monitorstring,myTable[ii].initialized);
+				fprintf(csFile,"%s %d %.*e %s %d\n",entry.chname.c_str(),1,precision,entry.data.chval,monitorstring.c_str(),entry.initialized);
 			} else {
-				encodeBURTString(myTable[ii].data.strval, burtString, sizeof(burtString));
-				fprintf(csFile,"%s %d %s %s %d\n",myTable[ii].chname,1,burtString,monitorstring,myTable[ii].initialized);
+                            BURT::encodeString( entry.data.strval, burtString );
+				fprintf(csFile,"%s %d %s %s %d\n",entry.chname.c_str(),1,burtString.c_str(),monitorstring.c_str(),entry.initialized);
 			}
 			break;
 		   case SDF_FILE_PARAMS_ONLY:
-			if(myTable[ii].initialized) {
-				if(myTable[ii].datatype == SDF_NUM) {
-					fprintf(csFile,"%s %d %.*e %s\n",myTable[ii].chname,1,precision,myTable[ii].data.chval,monitorstring);
+			if(entry.initialized) {
+				if(entry.datatype == SDF_NUM) {
+					fprintf(csFile,"%s %d %.*e %s\n",entry.chname.c_str(),1,precision,entry.data.chval,monitorstring.c_str());
 				} else {
-					encodeBURTString(myTable[ii].data.strval, burtString, sizeof(burtString));
-					fprintf(csFile,"%s %d %s %s\n",myTable[ii].chname,1,burtString,monitorstring);
+                                    BURT::encodeString( entry.data.strval,
+                                                        burtString );
+					fprintf(csFile,"%s %d %s %s\n",entry.chname.c_str(),1,burtString.c_str(),monitorstring.c_str());
 				}
 			}
 			break;
 		   case SDF_FILE_BURT_ONLY:
-			if(myTable[ii].datatype == SDF_NUM) {
-				fprintf(csFile,"%s %d %.*e\n",myTable[ii].chname,1,precision,myTable[ii].data.chval);
+			if(entry.datatype == SDF_NUM) {
+				fprintf(csFile,"%s %d %.*e\n",entry.chname.c_str(),1,precision,entry.data.chval);
 			} else {
-				encodeBURTString(myTable[ii].data.strval, burtString, sizeof(burtString));
-				fprintf(csFile,"%s %d %s \n",myTable[ii].chname,1,burtString);
+                            BURT::encodeString( entry.data.strval, burtString );
+				fprintf(csFile,"%s %d %s \n",entry.chname.c_str(),1,burtString.c_str());
 			}
 			break;
 		   default:
@@ -1070,6 +1094,7 @@ int writeTable2File(char *burtdir,
 		}
 	}
 	fclose(csFile);
+	return true;
 }
 
 /// Function to append alarm settings to saved files..
@@ -1077,15 +1102,15 @@ int writeTable2File(char *burtdir,
 ///	@param[in] sdffile	Name of the file being saved.
 ///	@param[in] currentload	Base file name of the associated alarms.snap file..
 int appendAlarms2File(
-		char *sdfdir,
-		char *sdffile,
-		char *currentload
+		const char *sdfdir,
+		const char *sdffile,
+		const char *currentload
 		)
 {
 char sdffilename[256];
 char alarmfilename[256];
-FILE *cdf=0;
-FILE *adf=0;
+FILE *cdf=nullptr;
+FILE *adf=nullptr;
 char line[128];
 char errMsg[128];
 int lderror = 0;
@@ -1093,15 +1118,15 @@ int lderror = 0;
 	sprintf(alarmfilename,"%s%s_alarms.snap",sdfdir,currentload);
 	// printf("sdffile = %s  \nalarmfile = %s\n",sdffilename,alarmfilename);
 	adf = fopen(alarmfilename,"r");
-	if(adf == NULL) return(-1);
+	if(adf == nullptr) return(-1);
 		cdf = fopen(sdffilename,"a");
-		if(cdf == NULL) {
+		if(cdf == nullptr) {
 			sprintf(errMsg,"New SDF request ERROR: FILE %s DOES NOT EXIST\n",sdffilename);
 			logFileEntry(errMsg);
 			lderror = 4;
 			return(lderror);
 		}
-		while(fgets(line,sizeof line,adf) != NULL)
+		while(fgets(line,sizeof line,adf) != nullptr)
 		{
 			fprintf(cdf,"%s",line);
 		}
@@ -1122,23 +1147,23 @@ int lderror = 0;
 /// Routine used to decode and handle BURT save requests.
 int savesdffile(int saveType, 		///< Save file format definition.
 		int saveOpts, 		///< Save file options.
-		char *sdfdir, 		///< Directory to save file in.
-		char *model, 		///< Name of the model used to build file name.
-		char *currentfile, 	///< Name of file last read (Used if option is to overwrite).
-		char *saveasfile,	///< Name of file to be saved.
-		char *currentload,	///< Name of file, less directory info.
-		dbAddr sfaddr,		///< Address of EPICS channel to write save file name.
-		dbAddr staddr,		///< Address of EPICS channel to write save file time.
-		dbAddr rladdr)
+		const char *sdfdir, 		///< Directory to save file in.
+		const char *model, 		///< Name of the model used to build file name.
+		const char *currentfile, 	///< Name of file last read (Used if option is to overwrite).
+		const char *saveasfile,	///< Name of file to be saved.
+		const char *currentload,	///< Name of file, less directory info.
+		epics::DBEntry<epics::PVType::String>& save_file_entry,		///< Address of EPICS channel to write save file name.
+		epics::DBEntry<epics::PVType::String>& save_time_entry,		///< Address of EPICS channel to write save file time.
+		epics::DBEntry<epics::PVType::String>& reload_time_entry)
 {
 char filename[256];
 char ftype[16];
 int status;
 char filemsg[128];
-char timestring[64];
-char shortfilename[64];
+embedded::fixed_string<256> timestring{};
+embedded::fixed_string<256> shortfilename{};
 
-	time_t now = time(NULL);
+	time_t now = time(nullptr);
 	struct tm *mytime  = localtime(&now);
 
 	switch(saveOpts)
@@ -1146,29 +1171,29 @@ char shortfilename[64];
 		case SAVE_TIME_NOW:
 			sprintf(filename,"%s%s_%d%02d%02d_%02d%02d%02d.snap", sdfdir,currentload,
 			(mytime->tm_year - 100),  (mytime->tm_mon + 1),  mytime->tm_mday,  mytime->tm_hour,  mytime->tm_min,  mytime->tm_sec);
-			sprintf(shortfilename,"%s_%d%02d%02d_%02d%02d%02d", currentload,
+            shortfilename.printf("%s_%d%02d%02d_%02d%02d%02d", currentload,
 			(mytime->tm_year - 100),  (mytime->tm_mon + 1),  mytime->tm_mday,  mytime->tm_hour,  mytime->tm_min,  mytime->tm_sec);
 			// printf("File to save is TIME NOW: %s\n",filename);
 			break;
 		case SAVE_OVERWRITE:
 			sprintf(filename,"%s",currentfile);
-			sprintf(shortfilename,"%s",currentload);
+			shortfilename.printf("%s",currentload);
 			// printf("File to save is OVERWRITE: %s\n",filename);
 			break;
 		case SAVE_BACKUP:
 			sprintf(filename,"%s%s_%d%02d%02d_%02d%02d%02d.snap",sdfdir,currentload,
 			(mytime->tm_year - 100),  (mytime->tm_mon + 1),  mytime->tm_mday,  mytime->tm_hour,  mytime->tm_min,  mytime->tm_sec);
-			sprintf(shortfilename,"%s",currentload);
+			shortfilename.printf("%s",currentload);
 			// printf("File to save is BACKUP: %s\n",filename);
 			break;
 		case SAVE_OVERWRITE_TABLE:
 			sprintf(filename,"%s%s.snap",sdfdir,currentload);
-			sprintf(shortfilename,"%s",currentload);
+			shortfilename.printf("%s",currentload);
 			// printf("File to save is BACKUP OVERWRITE: %s\n",filename);
 			break;
 		case SAVE_AS:
 			sprintf(filename,"%s%s.snap",sdfdir,saveasfile);
-			sprintf(shortfilename,"%s",saveasfile);
+			shortfilename.printf("%s",saveasfile);
 			// printf("File to save is SAVE_AS: %s\n",filename);
 			break;
 
@@ -1180,13 +1205,12 @@ char shortfilename[64];
 	{
 		case SAVE_TABLE_AS_SDF:
 			// printf("Save table as sdf\n");
-			status = writeTable2File(sdfdir,filename,SDF_FILE_PARAMS_ONLY,cdTable);
-			if(status != 0) {
+			if(!writeTable2File(sdfdir,filename,SDF_FILE_PARAMS_ONLY,cdTable)) {
                             sprintf(filemsg,"FAILED FILE SAVE %s",filename);
 			    logFileEntry(filemsg);
                             return(-2);
 			}
-			status = appendAlarms2File(sdfdir,shortfilename,currentload);
+			status = appendAlarms2File(sdfdir,shortfilename.c_str(),currentload);
 			if(status != 0) {
                             sprintf(filemsg,"FAILED To Append Alarms -  %s",currentload);
 			    logFileEntry(filemsg);
@@ -1196,9 +1220,8 @@ char shortfilename[64];
                         break;
 		case SAVE_EPICS_AS_SDF:
 			// printf("Save epics as sdf\n");
-			getEpicsSettings(chNum, NULL);
-			status = writeTable2File(sdfdir,filename,SDF_FILE_PARAMS_ONLY,cdTableP);
-			if(status != 0) {
+			getEpicsSettings();
+			if(!writeTable2File(sdfdir,filename,SDF_FILE_PARAMS_ONLY,cdTableP)) {
                             sprintf(filemsg,"FAILED EPICS SAVE %s",filename);
 			    logFileEntry(filemsg);
                             return(-2);
@@ -1211,12 +1234,14 @@ char shortfilename[64];
 			return(-1);
 	}
 	logFileEntry(filemsg);
-	getSdfTime(timestring, 128);
+	getSdfTime(timestring);
 	// printf(" Time of save = %s\n",timestring);
-	status = dbPutField(&sfaddr,DBR_STRING,shortfilename,1);
-	status = dbPutField(&staddr,DBR_STRING,timestring,1);
-	status = dbPutField(&rladdr,DBR_STRING,timestring,1);
+    save_file_entry.set(shortfilename);
+	save_time_entry.set(timestring);
+	reload_time_entry.set(timestring);
 	return(0);
+
+	// I can type above your caret
 }
 
 
@@ -1242,7 +1267,7 @@ void resetASG(char *name, int lock) {
 #endif
 
 /// Routine used to create local tables for reporting uninitialize and not monitored channels on request.
-int createSortTableEntries(int numEntries,int wcval,char *wcstring,int *noInit,time_t *times)
+int createSortTableEntries(int numEntries,int wcval,const char *wcstring,int *noInit,time_t *times)
 {
 int ii,jj;
 int notMon = 0;
@@ -1252,10 +1277,10 @@ int lnb = 0;	// line b - non mon chan list index
 #ifdef CA_SDF
 int lnc = 0;	// line c - disconnected chan list index
 #endif
-char tmpname[64];
+fixed_string<64> tmpname;
 time_t mtime=0;
 long nvals = 1;
-char liveset[64];
+fixed_string<64> liveset;
 double liveval = 0.0;
 
 	chNotInit = 0;
@@ -1270,14 +1295,13 @@ double liveval = 0.0;
 	for(ii=0;ii<fmNum;ii++) {
 		if(!filterTable[ii].init) chNotInit += 1;
 		if(filterTable[ii].init && !(filterTable[ii].mask & ALL_SWSTAT_BITS)) chNotMon += 1;
-		if(wcval  && (ret = strstr(filterTable[ii].fname,wcstring) == NULL)) {
+		if(wcval  && (ret = strstr(filterTable[ii].fname.c_str(),wcstring) == NULL)) {
 			continue;
 		}
-		bzero(tmpname,sizeof(tmpname));
-		strncpy(tmpname,filterTable[ii].fname,(strlen(filterTable[ii].fname)-1));
+		tmpname = filterTable[ii].fname;
 		if(!filterTable[ii].init) {
-			sprintf(uninitChans[lna].chname,"%s",tmpname);
-			strcpy(uninitChans[lna].burtset,"");
+			uninitChans[lna].chname.printf("%s",tmpname);
+			uninitChans[lna].burtset.clear();
 			uninitChans[lna].liveval = 0.0;
 			uninitChans[lna].sw[0] = (int)cdTableP[filterTable[ii].sw[0]].data.chval;
 			uninitChans[lna].sw[1] = (int)cdTableP[filterTable[ii].sw[1]].data.chval;
@@ -1287,7 +1311,8 @@ double liveval = 0.0;
 			lna ++;
 		}
 		if(filterTable[ii].init && !(filterTable[ii].mask & ALL_SWSTAT_BITS)) {
-			sprintf(unMonChans[lnb].chname,"%s",tmpname);
+
+		    unMonChans[lnb].chname = tmpname;
 			unMonChans[lnb].liveval = 0.0;
 			unMonChans[lnb].sw[0] = (int)cdTableP[filterTable[ii].sw[0]].data.chval;
 			unMonChans[lnb].sw[1] = (int)cdTableP[filterTable[ii].sw[1]].data.chval;
@@ -1302,7 +1327,7 @@ double liveval = 0.0;
 	{
 #ifdef VERBOSE_DEBUG
 		if (D_NOW) {
-			if (strcmp(cdTable[jj].chname, TEST_CHAN) == 0) {
+			if (strcmp(cdTable[jj].chname.c_str(), TEST_CHAN) == 0) {
 				D("%s: init: %d mask: %d filter: %d\n", TEST_CHAN, cdTable[jj].initialized, cdTable[jj].mask, cdTable[jj].filterswitch);	
 			}
 		}
@@ -1313,65 +1338,54 @@ double liveval = 0.0;
 #ifdef CA_SDF
 		if(!cdTable[jj].connected) chDisconnected += 1;
 #endif
-		if(wcval  && (ret = strstr(cdTable[jj].chname,wcstring) == NULL)) {
+		if(wcval  && (ret = strstr(cdTable[jj].chname.c_str(),wcstring) == NULL)) {
 			continue;
 		}
 		// Uninitialized channels
 		if(!cdTable[jj].initialized && !cdTable[jj].filterswitch) {
-			// printf("Chan %s not init %d %d %d\n",cdTable[jj].chname,cdTable[jj].initialized,jj,numEntries);
+			// printf("Chan %s not init %d %d %d\n",cdTable[jj].chname.c_str(),cdTable[jj].initialized,jj,numEntries);
 			if(lna < SDF_ERR_TSIZE) {
-				sprintf(uninitChans[lna].chname,"%s",cdTable[jj].chname);
+				uninitChans[lna].chname = cdTable[jj].chname;
 				if(cdTable[jj].datatype == SDF_NUM) {
 					liveval = cdTableP[jj].data.chval;
-					snprintf(liveset, sizeof(liveset),"%.10lf", liveval);
+					liveset.printf("%.10lf", liveval);
 
 				} else {
 					liveval = 0.0;
-					strncpy(liveset, cdTableP[jj].data.strval, sizeof(liveset));
-					liveset[sizeof(liveset)-1] = '\0';
+					liveset = cdTableP[jj].data.strval;
 				}
-				strncpy(uninitChans[lna].liveset, liveset, sizeof(uninitChans[lna].liveset));
-				uninitChans[lna].liveset[sizeof(uninitChans[lna].liveset)-1] = '\0';
+				uninitChans[lna].liveset = liveset;
 				uninitChans[lna].liveval = liveval;
 				uninitChans[lna].sigNum = jj;
 				uninitChans[lna].filtNum = -1;
 
-				if (times) {
-					snprintf(unMonChans[lna].timeset, sizeof(unMonChans[lna].timeset), "%s", (times ? ctime(&times[jj]) : " "));
-				} else {
-					sprintf(unMonChans[lna].timeset,"%s"," ");
-				}
+    		    unMonChans[lna].timeset = (times ? ctime(&times[jj]) : " ");
 
-				sprintf(uninitChans[lna].timeset,"%s"," ");
-				sprintf(uninitChans[lna].diff,"%s"," ");
-				lna ++;
+				uninitChans[lna].timeset = " ";
+				uninitChans[lna].diff = " ";
+				lna++;
 			}
 		}
 		// Unmonitored channels
 		if(cdTable[jj].initialized && !cdTable[jj].mask && !cdTable[jj].filterswitch) {
 			if(lnb < SDF_ERR_TSIZE) {
-				sprintf(unMonChans[lnb].chname,"%s",cdTable[jj].chname);
+				unMonChans[lnb].chname = cdTable[jj].chname;
 				if(cdTable[jj].datatype == SDF_NUM)
 				{
-					snprintf(unMonChans[lnb].burtset, sizeof(unMonChans[lnb].burtset),"%.10lf",cdTable[jj].data.chval);
-					snprintf(unMonChans[lnb].liveset, sizeof(unMonChans[lnb].liveset),"%.10lf",cdTableP[jj].data.chval);
+					unMonChans[lnb].burtset.printf("%.10lf",cdTable[jj].data.chval);
+					unMonChans[lnb].liveset.printf("%.10lf",cdTableP[jj].data.chval);
 					unMonChans[lnb].liveval = cdTableP[jj].data.chval;
 				} else {
-					sprintf(unMonChans[lnb].burtset,"%s",cdTable[jj].data.strval);
-					sprintf(unMonChans[lnb].liveset,"%s",cdTableP[jj].data.strval);
+					unMonChans[lnb].burtset = cdTable[jj].data.strval;
+					unMonChans[lnb].liveset = cdTableP[jj].data.strval;
 					unMonChans[lnb].liveval = 0.0;
 				}
 
                 unMonChans[lnb].sigNum = jj;
 				unMonChans[lnb].filtNum = -1;
 
-				if (times) {
-					snprintf(unMonChans[lnb].timeset, sizeof(unMonChans[lnb].timeset), "%s", (times ? ctime(&times[jj]) : " "));
-					sprintf(unMonChans[lnb].diff,"%s"," ");
-				} else {
-					sprintf(unMonChans[lnb].timeset,"%s"," ");
-					sprintf(unMonChans[lnb].diff,"%s"," ");
-				}
+                unMonChans[lnb].timeset = (times ? ctime(&times[jj]) : " ");
+                unMonChans[lnb].diff = " ";
 
 				lnb ++;
 			}
@@ -1379,25 +1393,22 @@ double liveval = 0.0;
 #ifdef CA_SDF
 		if(!cdTable[jj].connected && !cdTable[jj].filterswitch) {
 			if (lnc < SDF_ERR_TSIZE) {
-				sprintf(disconnectChans[lnc].chname, "%s", cdTable[jj].chname);
+				disconnectChans[lnc].chname = cdTable[jj].chname;
 				if(cdTable[jj].datatype == SDF_NUM) {
 					liveval = cdTableP[jj].data.chval;
-					snprintf(liveset, sizeof(liveset),"%.10lf", liveval);
+					liveset.printf("%.10lf", liveval);
 
 				} else {
 					liveval = 0.0;
-					strncpy(liveset, cdTableP[jj].data.strval, sizeof(liveset));
-					liveset[sizeof(liveset)-1] = '\0';
+					liveset = cdTableP[jj].data.strval;
 				}
-				strncpy(disconnectChans[lnc].liveset, liveset, sizeof(disconnectChans[lnc].liveset));
-				disconnectChans[lnc].liveset[sizeof(disconnectChans[lnc].liveset)-1] = '\0';
+				disconnectChans[lnc].liveset = liveset;
 				disconnectChans[lnc].liveval = liveval;
                 disconnectChans[lnc].sigNum = jj;
 				disconnectChans[lnc].filtNum = -1;
-				sprintf(disconnectChans[lnc].timeset,"%s"," ");
-				sprintf(disconnectChans[lnc].diff,"%s"," ");
-				lnc ++;
-
+				disconnectChans[lnc].timeset = " ";
+				disconnectChans[lnc].diff = " ";
+				lnc++;
 			}
 		}
 #endif
@@ -1405,24 +1416,24 @@ double liveval = 0.0;
 	// Clear out the uninit tables.
 	for(jj=lna;jj<(lna + 50);jj++)
 	{
-		sprintf(uninitChans[jj].chname,"%s"," ");
-		sprintf(uninitChans[jj].burtset,"%s"," ");
-		sprintf(uninitChans[jj].liveset,"%s"," ");
+		uninitChans[jj].chname = " ";
+		uninitChans[jj].burtset = " ";
+		uninitChans[jj].liveset = " ";
 		uninitChans[jj].liveval = 0.0;
-		sprintf(uninitChans[jj].timeset,"%s"," ");
-		sprintf(uninitChans[jj].diff,"%s"," ");
+		uninitChans[jj].timeset = " ";
+		uninitChans[jj].diff = " ";
         uninitChans[jj].sigNum = 0;         // is this the right value, should it be -1?
 		uninitChans[jj].filtNum = -1;
 	}
 	// Clear out the unmon tables.
 	for(jj=lnb;jj<(lnb + 50);jj++)
 	{
-		sprintf(unMonChans[jj].chname,"%s"," ");
-		sprintf(unMonChans[jj].burtset,"%s"," ");
-		sprintf(unMonChans[jj].liveset,"%s"," ");
+		unMonChans[jj].chname = " ";
+		unMonChans[jj].burtset = " ";
+		unMonChans[jj].liveset = " ";
 		unMonChans[jj].liveval = 0.0;
-		sprintf(unMonChans[jj].timeset,"%s"," ");
-		sprintf(unMonChans[jj].diff,"%s"," ");
+		unMonChans[jj].timeset = " ";
+		unMonChans[jj].diff = " ";
         unMonChans[jj].sigNum = 0;
 		unMonChans[jj].filtNum = -1;
 	}
@@ -1430,12 +1441,12 @@ double liveval = 0.0;
 	// Clear out the disconnected tables.
 	for(jj=lnc;jj<(lnc + 50);jj++)
 	{
-		sprintf(disconnectChans[jj].chname,"%s"," ");
-		sprintf(disconnectChans[jj].burtset,"%s"," ");
-		sprintf(disconnectChans[jj].liveset,"%s"," ");
+		disconnectChans[jj].chname = " ";
+		disconnectChans[jj].burtset = " ";
+		disconnectChans[jj].liveset = " ";
 		disconnectChans[jj].liveval = 0.0;
-		sprintf(disconnectChans[jj].timeset,"%s"," ");
-		sprintf(disconnectChans[jj].diff,"%s"," ");
+		disconnectChans[jj].timeset = " ";
+		disconnectChans[jj].diff = " ";
         disconnectChans[jj].sigNum = 0;
 		disconnectChans[jj].filtNum = -1;
 	}
@@ -1445,9 +1456,9 @@ double liveval = 0.0;
 }
 
 /// Common routine to load monitoring tables into EPICS channels for MEDM screen.
+template <std::size_t entry_count>
 int reportSetErrors(char *pref,			///< Channel name prefix from EPICS environment. 
-		     int numEntries, 			///< Number of entries in table to be reported.
-		     SET_ERR_TABLE setErrTable[],	///< Which table to report to EPICS channels.
+		     fixed_size_vector<SET_ERR_TABLE , entry_count>& setErrTable,	///< Which table to report to EPICS channels.
 		     int page,                      ///< Which page of 40 to display.
              int linkInFilters)				///< Should the SDF_FM_LINE values be set.
 {
@@ -1483,21 +1494,22 @@ int minusOne = -1;
 
 	// Get the page number to display
 	mypage = page;
-	// Calculat start index to the diff table.
+	// Calculate start index to the diff table.
 	myindex = page *  SDF_ERR_DSIZE;
+	int numEntries = setErrTable.size();
 	if(myindex == numEntries && numEntries > 0) {
 		mypage --;
 		myindex = mypage *  SDF_ERR_DSIZE;
 	}
 	// If index is > number of entries in the table, then page back.
-        if(myindex > numEntries) {
+    if(myindex > numEntries) {
 		mypage = numEntries / SDF_ERR_DSIZE;
 		myindex = mypage *  SDF_ERR_DSIZE;
-        }
+    }
 	// Set the stop index to the diff table.
 	rc = myindex + SDF_ERR_DSIZE;
 	// If stop index beyond last diff table entry, set it to last entry.
-        if(rc > numEntries) rc = numEntries;
+    if(rc > numEntries) rc = numEntries;
 	numDisp = rc - myindex;
 
 	// Fill in table entries.
@@ -1505,8 +1517,8 @@ int minusOne = -1;
 	{
 		sprintf(s, "%s_%s_STAT%d", pref,"SDF_SP", lineNum);
 		status = dbNameToAddr(s,&saddr);
-		//sprintf(stmp, "%s%s", (setErrTable[ii].filtNum >= 0 ? "* " : ""), setErrTable[ii].chname);
-		status = dbPutField(&saddr,DBR_UCHAR,&setErrTable[ii].chname,flength);
+		//sprintf(stmp, "%s%s", (setErrTable[ii].filtNum >= 0 ? "* " : ""), setErrTable[ii].chname.c_str());
+		status = dbPutField(&saddr,DBR_UCHAR,setErrTable[ii].chname.c_str(),flength);
 
 		sprintf(s1, "%s_%s_STAT%d_BURT", pref,"SDF_SP", lineNum);
 		status = dbNameToAddr(s1,&baddr);
@@ -1541,7 +1553,7 @@ int minusOne = -1;
 	}
 
 	// Clear out empty table entries.
-	for(ii=numDisp;ii<40;ii++)
+	for(ii=numDisp;ii<SDF_ERR_DSIZE;ii++)
 	{
 		sprintf(s, "%s_%s_STAT%d", pref,"SDF_SP", ii);
 		status = dbNameToAddr(s,&saddr);
@@ -1590,21 +1602,22 @@ int minusOne = -1;
 //	- Present Value
 //	- Time the present setting was applied.
 /// Setpoint monitoring routine.
-int spChecker(int monitorAll, SET_ERR_TABLE setErrTable[],int wcVal, char *wcstring, int listAll, int *totalDiffs)
+template <std::size_t entry_count>
+int spChecker(int monitorAll, fixed_size_vector<SET_ERR_TABLE, entry_count>& setErrTable,int wcVal, const char *wcstring, int listAll, int *totalDiffs)
 {
    	int errCntr = 0;
 	ADDRESS paddr;
 	long status=0;
-	int ii;
+	//int ii;
 	double rval;
-	char sval[128];
+	fixed_string<128> sval;
 	time_t mtime;
-	char localtimestring[256];
+	fixed_string<256> localtimestring;
 	int localErr = 0;
-	char liveset[64];
-	char burtset[64];
-	char diffB2L[64];
-	char swName[64];
+	fixed_string<64> liveset;
+	fixed_string<64> burtset;
+	fixed_string<64> diffB2L;
+	fixed_string<64> swName;
 	double sdfdiff = 0.0;
 	double liveval = 0.0;
 	int filtDiffs=0;
@@ -1621,72 +1634,76 @@ int spChecker(int monitorAll, SET_ERR_TABLE setErrTable[],int wcVal, char *wcstr
 */
 #endif
 	// Check filter switch settings first
-	     errCntr = checkFilterSwitches(fmNum,setErrTable,monitorAll,listAll,wcVal,wcstring,&filtDiffs);
-	     *totalDiffs = filtDiffs;
-	     if(chNum) {
-		for(ii=0;ii<chNum;ii++) {
+        setErrTable.clear();
+	    errCntr = checkFilterSwitches(setErrTable,monitorAll,listAll,wcVal,wcstring,&filtDiffs);
+	    *totalDiffs = filtDiffs;
+
+	    int index = -1;
+	    for (auto& curSP: cdTable)
+        {
+	        ++index;
 			if((errCntr < SDF_ERR_TSIZE) && 		// Within table max size
-			  ((cdTable[ii].mask != 0) || (monitorAll)) && 	// Channel is to be monitored
-			   cdTable[ii].initialized && 			// Channel was set in BURT
-			   cdTable[ii].filterswitch == 0 ||		// Not a filter switch channel
-			   (listAll && cdTable[ii].filterswitch == 0))
+			  ((curSP.mask != 0) || (monitorAll)) && 	// Channel is to be monitored
+			   curSP.initialized && 			// Channel was set in BURT
+			   curSP.filterswitch == 0 ||		// Not a filter switch channel
+			   (listAll && curSP.filterswitch == 0))
 			{
 				localErr = 0;
 				mtime = 0;
 				// Find address of channel
-				status = GET_ADDRESS(cdTable[ii].chname,&paddr);
+				GET_ADDRESS(curSP.chname,&paddr);
 				// If this is a digital data type, then get as double.
-				if(cdTable[ii].datatype == SDF_NUM)
+				if(curSP.datatype == SDF_NUM)
 				{
-					status = GET_VALUE_NUM(paddr,&rval,&mtime, NULL); //&(cdTable[ii].connected));
-					if(cdTable[ii].data.chval != rval || listAll)
+					GET_VALUE_NUM(paddr,&rval,&mtime, NULL); //&(curSP.connected));
+					if(curSP.data.chval != rval || listAll)
 					{
-						sdfdiff = fabs(cdTable[ii].data.chval - rval);
-						snprintf(burtset,sizeof(burtset),"%.10lf",cdTable[ii].data.chval);
-						snprintf(liveset,sizeof(liveset),"%.10lf",rval);
+						sdfdiff = fabs(curSP.data.chval - rval);
+						burtset.printf("%.10lf",curSP.data.chval);
+						liveset.printf("%.10lf",rval);
 						liveval = rval;
-						snprintf(diffB2L,sizeof(diffB2L),"%.8le",sdfdiff);
+						diffB2L.printf("%.8le",sdfdiff);
 						localErr = 1;
 					}
 				// If this is a string type, then get as string.
 				} else {
-                    updateStrVarSetPoint(ii);
-					status = GET_VALUE_STR(paddr,sval,sizeof(sval),&mtime, NULL); //&(cdTable[ii].connected));
-					if(strcmp(cdTable[ii].data.strval,sval) != 0 || listAll)
+                    updateStrVarSetPoint(index);
+					GET_VALUE_STR(paddr,sval,&mtime, NULL); //&(curSP.connected));
+					if(sval != curSP.data.strval || listAll)
 					{
-						sprintf(burtset,"%s",cdTable[ii].data.strval);
-						sprintf(liveset,"%s",sval);
+						burtset = curSP.data.strval;
+						liveset = sval;
 						liveval = 0.0;
-						sprintf(diffB2L,"%s","                                   ");
+						diffB2L.printf("%s","                                   ");
 						localErr = 1;
 					}
 				}
 				if(localErr) *totalDiffs += 1;
-				if(localErr && wcVal  && (strstr(cdTable[ii].chname,wcstring) == NULL))
+				if(localErr && wcVal  && (strstr(curSP.chname.c_str(),wcstring) == NULL))
 					localErr = 0;
 				// If a diff was found, then write info the EPICS setpoint diff table.
 				if(localErr)
 				{
-					sprintf(setErrTable[errCntr].chname,"%s", cdTable[ii].chname);
-
-					sprintf(setErrTable[errCntr].burtset, "%s", burtset);
-
-					sprintf(setErrTable[errCntr].liveset, "%s", liveset);
-					setErrTable[errCntr].liveval = liveval;
-					sprintf(setErrTable[errCntr].diff, "%s", diffB2L);
-					setErrTable[errCntr].sigNum = ii;
-					setErrTable[errCntr].filtNum = -1;
-
-					strcpy(localtimestring, ctime(&mtime));
-					localtimestring[strlen(localtimestring) - 1] = 0;
-					sprintf(setErrTable[errCntr].timeset, "%s", localtimestring);
-					if(cdTable[ii].mask) setErrTable[errCntr].chFlag |= 1;
-					else setErrTable[errCntr].chFlag &= ~(1);
+				    setErrTable.emplace_back();
+				    auto& curErr = setErrTable.back();
+					curErr.chname = curSP.chname;
+
+					curErr.burtset = burtset;
+
+					curErr.liveset = liveset;
+					curErr.liveval = liveval;
+					curErr.diff = diffB2L;
+					curErr.sigNum = index;
+					curErr.filtNum = -1;
+
+					localtimestring = ctime(&mtime);
+					curErr.timeset = localtimestring;
+					if(curSP.mask) curErr.chFlag |= 1;
+					else curErr.chFlag &= ~(1);
 					errCntr ++;
 				}
 			}
 		}
-	     }
 	return(errCntr);
 }
 
@@ -1696,29 +1713,30 @@ int spChecker(int monitorAll, SET_ERR_TABLE setErrTable[],int wcVal, char *wcstr
 /// @param modTable[in] An array of SET_ERR_TABLE entries that hold the current views state to be merged with cdTable
 ///
 /// @remark modifies cdTable
-int modifyTable(int numEntries,SET_ERR_TABLE modTable[])
+int modifyTable(table_range modTable)
 {
-int ii,jj;
-int fmIndex = -1;
-unsigned int sn,sn1;
-int found = 0;
-	for(ii=0;ii<numEntries;ii++)
+    int jj;
+    int fmIndex = -1;
+    unsigned int sn,sn1;
+    int found = 0;
+
+	for (const auto& entry:modTable)
 	{
 		// if accept or monitor is set
-		if(modTable[ii].chFlag > 3) 
+		if(entry.chFlag > 3)
 		{
 			found = 0;
 			for(jj=0;jj<chNum;jj++)
 			{
-				if (strcmp(cdTable[jj].chname,modTable[ii].chname) == 0) {
-					if ( CHFLAG_ACCEPT_BIT(modTable[ii].chFlag) ) {
-						if(cdTable[jj].datatype == SDF_NUM) cdTable[jj].data.chval = modTable[ii].liveval;/* atof(modTable[ii].liveset);*/
-						else sprintf(cdTable[jj].data.strval,"%s",modTable[ii].liveset);
+				if (cdTable[jj].chname == entry.chname) {
+					if ( CHFLAG_ACCEPT_BIT(entry.chFlag) ) {
+						if(cdTable[jj].datatype == SDF_NUM) cdTable[jj].data.chval = entry.liveval;/* atof(entry.liveset);*/
+						else cdTable[jj].data.strval = entry.liveset;
 						cdTable[jj].initialized = 1;
 						found = 1;
 						fmIndex = cdTable[jj].filterNum;
 					}
-					if(CHFLAG_MONITOR_BIT(modTable[ii].chFlag)) {
+					if(CHFLAG_MONITOR_BIT(entry.chFlag)) {
 						fmIndex = cdTable[jj].filterNum;
 						if (fmIndex >= 0 && fmIndex < SDF_MAX_FMSIZE) {
 							// filter module use the manualy modified state, cannot just toggle
@@ -1731,21 +1749,21 @@ int found = 0;
 					}
 				}
 			}
-			if(modTable[ii].filtNum >= 0 && !found) { 
-				fmIndex = modTable[ii].filtNum;
+			if(entry.filtNum >= 0 && !found) {
+				fmIndex = entry.filtNum;
 				// printf("This is a filter from diffs = %s\n",filterTable[fmIndex].fname);
 				filterTable[fmIndex].newSet = 1;
-				sn = modTable[ii].sigNum;
+				sn = entry.sigNum;
 				sn1 = sn / SDF_MAX_TSIZE;
 				sn %= SDF_MAX_TSIZE;
-				if(CHFLAG_ACCEPT_BIT(modTable[ii].chFlag)) {
-					cdTable[sn].data.chval = modTable[ii].sw[0];
+				if(CHFLAG_ACCEPT_BIT(entry.chFlag)) {
+					cdTable[sn].data.chval = entry.sw[0];
 					cdTable[sn].initialized = 1;
-					cdTable[sn1].data.chval = modTable[ii].sw[1];
+					cdTable[sn1].data.chval = entry.sw[1];
 					cdTable[sn1].initialized = 1;
 					filterTable[fmIndex].init = 1;
 				}
-				if(CHFLAG_MONITOR_BIT(modTable[ii].chFlag)) {
+				if(CHFLAG_MONITOR_BIT(entry.chFlag)) {
 					filterTable[fmIndex].mask = filterMasks[fmIndex];
 				 	cdTable[sn].mask = filterMasks[fmIndex];
 				 	cdTable[sn1].mask = filterMasks[fmIndex];
@@ -1753,33 +1771,33 @@ int found = 0;
 			}
 		}
 	}
-	newfilterstats(fmNum);
+	newfilterstats();
 	return(0);
 }
 
-int resetSelectedValues(int errNum, SET_ERR_TABLE modTable[])
+template <std::size_t entry_count>
+int resetSelectedValues(fixed_size_vector<SET_ERR_TABLE, entry_count>& modTable)
 {
 long status;
-int ii;
 int sn;
 int sn1 = 0;
 ADDRESS saddr;
 
-	for(ii=0;ii<errNum;ii++)
+	for(const auto& entry:modTable)
 	{
-		if (modTable[ii].chFlag & 2)
+		if (entry.chFlag & 2)
 		{
-			sn = modTable[ii].sigNum;
+			sn = entry.sigNum;
 			if(sn > SDF_MAX_TSIZE) {
 				sn1 = sn / SDF_MAX_TSIZE;
 				sn %= SDF_MAX_TSIZE;
 			}
-			status = GET_ADDRESS(cdTable[sn].chname,&saddr);
-			if (cdTable[sn].datatype == SDF_NUM) status = PUT_VALUE(saddr,SDF_NUM,&(cdTable[sn].data.chval));
-			else status = PUT_VALUE(saddr,SDF_STR,cdTable[sn].data.strval);;
+			GET_ADDRESS(cdTable[sn].chname,&saddr);
+			if (cdTable[sn].datatype == SDF_NUM) PUT_VALUE(saddr,SDF_NUM,&(cdTable[sn].data.chval));
+			else PUT_VALUE(saddr,SDF_STR,cdTable[sn].data.strval.c_str());;
 			if(sn1) {
-				status = GET_ADDRESS(cdTable[sn1].chname,&saddr);
-				status = PUT_VALUE(saddr,SDF_NUM,&(cdTable[sn1].data.chval));
+				GET_ADDRESS(cdTable[sn1].chname,&saddr);
+				PUT_VALUE(saddr,SDF_NUM,&(cdTable[sn1].data.chval));
 			}
 		}
 	}
@@ -1787,48 +1805,44 @@ ADDRESS saddr;
 }
 
 /// This function sets filter module request fields to aid in decoding errant filter module switch settings.
-void newfilterstats(int numchans) {
+void newfilterstats() {
 	ADDRESS paddr;
 	long status;
-	int ii;
-	FILE *log=0;
-	char chname[128];
-	int mask = 0x1ffff;
+
+	FILE *log=nullptr;
+	fixed_string<128> chname;
+	unsigned int mask = 0x1ffff;
 	int tmpreq;
 	int counter = 0;
 	int rsw1,rsw2;
 	unsigned int tmpL = 0;
 
 	printf("In newfilterstats\n");
-	for(ii=0;ii<numchans;ii++) {
-		if(filterTable[ii].newSet) {
+	for(auto& filterEntry:filterTable) {
+		if(filterEntry.newSet) {
 			counter ++;
-			filterTable[ii].newSet = 0;
-			filterTable[ii].init = 1;
-			rsw1 = filterTable[ii].sw[0];
-			rsw2 = filterTable[ii].sw[1];
-			filterTable[ii].mask =  cdTable[rsw1].mask | cdTable[rsw2].mask;;
-			cdTable[rsw1].mask = filterTable[ii].mask;
-			cdTable[rsw2].mask = filterTable[ii].mask;
+			filterEntry.newSet = 0;
+			filterEntry.init = 1;
+			rsw1 = filterEntry.sw[0];
+			rsw2 = filterEntry.sw[1];
+			filterEntry.mask =  cdTable[rsw1].mask | cdTable[rsw2].mask;;
+			cdTable[rsw1].mask = filterEntry.mask;
+			cdTable[rsw2].mask = filterEntry.mask;
 			tmpreq =  ((unsigned int)cdTable[rsw1].data.chval & 0xffff) + 
 				(((unsigned int)cdTable[rsw2].data.chval & 0xffff) << 16);
-			filterTable[ii].swreq = filtCtrlBitConvert(tmpreq);
-			bzero(chname,sizeof(chname));
+			filterEntry.swreq = filtCtrlBitConvert(tmpreq);
 			// Find address of channel
-			strcpy(chname,filterTable[ii].fname);
-			strcat(chname,"SWREQ");
-			status = GET_ADDRESS(chname,&paddr);
-			if(!status) {
-				tmpL = (unsigned int)filterTable[ii].swreq;
-				status = PUT_VALUE_INT(paddr,&tmpL);
+			chname  = filterEntry.fname;
+			chname += "SWREQ";
+			if(GET_ADDRESS(chname,&paddr)) {
+				tmpL = (unsigned int)filterEntry.swreq;
+				PUT_VALUE_INT(paddr,&tmpL);
 			}
-			bzero(chname,sizeof(chname));
 			// Find address of channel
-			strcpy(chname,filterTable[ii].fname);
-			strcat(chname,"SWMASK");
-			status = GET_ADDRESS(chname,&paddr);
-			if(!status) {
-				status = PUT_VALUE_INT(paddr,(unsigned int*)&mask);
+			chname = filterEntry.fname;
+			chname += "SWMASK";
+			if(GET_ADDRESS(chname,&paddr)) {
+				PUT_VALUE_INT(paddr,&mask);
 			}
 			// printf("New filter %d %s = 0x%x\t0x%x\t0x%x\n",ii,filterTable[ii].fname,filterTable[ii].swreq,filterTable[ii].sw[0],filterTable[ii].sw[1]);
 		}
@@ -1837,47 +1851,43 @@ void newfilterstats(int numchans) {
 }
 
 /// This function writes BURT settings to EPICS records.
-int writeEpicsDb(int numchans,		///< Number of channels to write
-	         CDS_CD_TABLE myTable[],	///< Table with data to be written.
+template <std::size_t entry_count>
+int writeEpicsDb(fixed_size_vector<CDS_CD_TABLE, entry_count>& myTable,	///< Table with data to be written.
 	     	 int command) 		///< Write request.
 {
 	ADDRESS paddr;
 	long status;
 	int ii;
 
-	// chNotFound = 0;
 	switch (command)
 	{
 		case SDF_LOAD_DB_ONLY:
 		case SDF_LOAD_PARTIAL:
-			for(ii=0;ii<numchans;ii++) {
-				// Find address of channel
-				status = GET_ADDRESS(myTable[ii].chname,&paddr);
-				if (!status)
-				{
-					if (myTable[ii].datatype == SDF_NUM)
-					{
-						status = PUT_VALUE(paddr,SDF_NUM,&(myTable[ii].data.chval));
-					} else {
-						status = PUT_VALUE(paddr,SDF_STR,myTable[ii].data.strval);
-					}
-				}
-				else {				// Write errors to chan not found table.
-				printf("CNF for %s = %d\n",myTable[ii].chname,status);
-				#if 0
-					if(chNotFound < SDF_ERR_TSIZE) {
-						sprintf(unknownChans[chNotFound].chname,"%s",myTable[ii].chname);
-						sprintf(unknownChans[chNotFound].liveset,"%s"," ");
-						unknownChans[chNotFound].liveval = 0.0;
-						sprintf(unknownChans[chNotFound].timeset,"%s"," ");
-						sprintf(unknownChans[chNotFound].diff,"%s"," ");
-						unknownChans[chNotFound].chFlag = 0;
-					}
-					chNotFound ++;
-				#endif
-				}
-			}
-			break;
+
+		    for (const auto& entry:myTable)
+		    {
+                        // Find address of channel
+                        if (GET_ADDRESS(entry.chname,&paddr))
+                        {
+                            if (entry.datatype == SDF_NUM)
+                            {
+                                PUT_VALUE(paddr,SDF_NUM,&(entry.data.chval));
+                            } else {
+                                PUT_VALUE(paddr,SDF_STR,entry.data.strval.c_str());
+                            }
+                        }
+                        else {				// Write errors to chan not found table.
+                            printf("CNF for %s = %d\n",entry.chname.c_str(),status);
+                        }
+                    }
+                    // Set the SDF_FILE_LOADED environment var to 1,
+                    // signalling to the epipcs sequencer to
+                    // trigger a BURT_RESTORE
+
+                    {
+                        set_sdf_file_loaded(1);
+                    }
+                    break;
 		case SDF_READ_ONLY:
 			// If request was only to re-read the BURT file, then don't want to apply new settings.
 			// This is typically the case where only mask fields were changed in the BURT file to
@@ -1886,24 +1896,24 @@ int writeEpicsDb(int numchans,		///< Number of channels to write
 			break;
 		case SDF_RESET:
 			// Only want to set those channels marked by a mask back to their original BURT setting.
-			for(ii=0;ii<numchans;ii++) {
-				// FIXME: check does this make sense w/ a bitmask in mask?
-				// can filter modules get here?  It seems that they will, so would we need
-				// to mask the value we set ?
-			    if(myTable[ii].mask) {
-			    	//Find address of channel
-			    	status = GET_ADDRESS(myTable[ii].chname,&paddr);
-			    	if (!status)
-			    	{
-			    		if (myTable[ii].datatype == SDF_NUM)
-						{
-							status = PUT_VALUE(paddr,SDF_NUM,&(myTable[ii].data.chval));
-						} else {
-							status = PUT_VALUE(paddr,SDF_STR,myTable[ii].data.strval);
-						}
-			    	}
-			    }
-			}
+			for (const auto& entry: myTable)
+			{
+                // FIXME: check does this make sense w/ a bitmask in mask?
+                // can filter modules get here?  It seems that they will, so would we need
+                // to mask the value we set ?
+                if(entry.mask) {
+                    //Find address of channel
+                    if (GET_ADDRESS(entry.chname,&paddr))
+                    {
+                        if (entry.datatype == SDF_NUM)
+                        {
+                            PUT_VALUE(paddr,SDF_NUM,&(entry.data.chval));
+                        } else {
+                            PUT_VALUE(paddr,SDF_STR,entry.data.strval.c_str());
+                        }
+                    }
+                }
+            }
 			break;
 		default:
 			printf("writeEpicsDb setting routine got unknown request \n");
@@ -1916,27 +1926,27 @@ int writeEpicsDb(int numchans,		///< Number of channels to write
 
 
 /// Function to read BURT files and load data into local tables.
-int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
-		char *sdfile, 		///< Name of the file to read.
+int readConfig( const char *pref,		///< EPICS channel prefix from EPICS environment.
+		const char *sdfile, 		///< Name of the file to read.
 		int command,		///< Read file request type.
-		char *alarmfile)
+		const char *alarmfile)
 {
-	FILE *cdf=0;
-	FILE *adf=0;
+	FILE *cdf=nullptr;
+	FILE *adf=nullptr;
 	char c=0;
 	int ii=0;
 	int lock=0;
-	char s1[128],s2[128],s3[128],s4[128],s5[128],s6[128],s7[128],s8[128];
 	char ls[6][64];
-	dbAddr paddr;
+	ADDRESS paddr;
+	dbAddr reloadDbAddr;
 	long status=0;
 	int lderror = 0;
 	int ropts = 0;
 	int nvals = 1;
 	int starttime=0,totaltime=0;
-	char timestring[256];
+	embedded::fixed_string<256> timestring{};
 	char line[128];
-	char *fs=0;
+	char *fs=nullptr;
 	char ifo[4];
 	double tmpreq = 0;
 	char fname[128];
@@ -1947,8 +1957,11 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 	int isalarm = 0;
 	int lineCnt = 0;
 
-	s1[0]=s2[0]=s3[0]=s4[0]=s5[0]=s6[0]=s7[0]=s8[0]='\0';
-	timestring[0]='\0';
+    //Header vars
+    int in_header = 0;
+    const static char* header_start = "--- Start";
+    const static char* header_end = "--- End";
+
 	line[0]='\0';
 	ifo[0]='\0';
 	fname[0]=errMsg[0]='\0';
@@ -1958,59 +1971,81 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 	clock_gettime(CLOCK_REALTIME,&t);
 	starttime = t.tv_nsec;
 
-	getSdfTime(timestring, 256);
+	getSdfTime(timestring);
 
 	if(command == SDF_RESET) {
-		lderror = writeEpicsDb(chNum,cdTable,command);
+		lderror = writeEpicsDb(cdTable,command);
 	} else {
 		printf("PARTIAL %s\n",sdfile);
 		cdf = fopen(sdfile,"r");
-		if(cdf == NULL) {
-			sprintf(errMsg,"New SDF request ERROR: FILE %s DOES NOT EXIST\n",sdfile);
+		if(cdf == nullptr) {
+			snprintf(errMsg, 64, "New SDF request ERROR: FILE %s DOES NOT EXIST", sdfile);
 			logFileEntry(errMsg);
 			lderror = 4;
+			perror(errMsg);
+			fprintf(stderr, "sdfile : %s\n", sdfile);
 			return(lderror);
 		}
 		adf = fopen(alarmfile,"w");
+		if(adf == nullptr)
+		{
+			snprintf(errMsg, 64, "New SDF request ERROR: failed open alarm file");
+			logFileEntry(errMsg);
+			lderror = 4;
+			perror(errMsg);
+			fprintf(stderr, "alarmfile : %s\n", alarmfile);
+			return(lderror);
+		}
 		chNumP = 0;
 		alarmCnt = 0;
-		// Put dummy in s4 as this column may or may not exist.
-		strcpy(s4,"x");
-		bzero(s3,sizeof(s3));
 		strncpy(ifo,pref,3);
 		chNotFound = 0;
-		while(fgets(line,sizeof line,cdf) != NULL)
+		while(fgets(line,sizeof line,cdf) != nullptr)
 		{
-			isalarm = 0;
-			lineCnt ++;
-			strcpy(s4,"x");
-			argcount = parseLine(line,sizeof(s1),s1,s2,s3,s4,s5,s6);
-			if (strcmp(s4, "") == 0) strcpy(s4, "0");
-			if(argcount == -1) {
-				sprintf(readErrTable[rderror].chname,"%s", s1);
-				sprintf(readErrTable[rderror].burtset, "%s", "Improper quotations ");
-				sprintf(readErrTable[rderror].liveset, "Line # %d", lineCnt);
-				readErrTable[rderror].liveval = 0.0;
-				sprintf(readErrTable[rderror].diff, "%s", sdfile);
-				sprintf(readErrTable[rderror].timeset, "%s", timestring);
-				rderror ++;
-				printf("Read error --- %s\n",s1);
+
+			if (in_header)
+			{
+				if (strstr(line, header_end) == line)
+				{
+					in_header = 0;
+				}
 				continue;
 			}
-			// Only 3 = no monit flag
-			// >=4 count be monit flag or string with quotes
+			else if (strstr( line, header_start) == line)
+			{
+				in_header = 1;
+				continue;
+			}
+
+
+			isalarm = 0;
+			lineCnt ++;
+                        BURT::parsed_line words{};
+			argcount = BURT::parseLine(line, words);
+                        // Only 3 = no monit flag
+                        // >=4 count be monit flag or string with quotes
+                        if ( argcount < 3 )
+                        {
+                            continue;
+                        }
+                        if ( argcount < 4 )
+                        {
+                            words.push_back(BURT::parsed_word("0"));
+                        }
+                        const char* s1 = words[0].c_str();
+                        const char* s2 = words[1].c_str();
+                        const char* s3 = words[2].c_str();
+                        const char* s4 = words[3].c_str();
 			// If 1st three chars match IFO ie checking this this line is not BURT header or channel marked RO
-			if(strncmp(s1,ifo,3) == 0 && 
+			if(
 			// Don't allow load of SWSTAT or SWMASK, which are set by this program.
-				strstr(s1,"_SWMASK") == NULL &&
-				strstr(s1,"_SDF_NAME") == NULL &&
-				strstr(s1,"_SWREQ") == NULL &&
+				strstr(s1,"_SWMASK") == nullptr &&
+				strstr(s1,"_SDF_NAME") == nullptr &&
+				strstr(s1,"_SWREQ") == nullptr &&
 				argcount > 2)
 			{
-				// Clear out the local tabel channel name string.
-				bzero(cdTableP[chNumP].chname,strlen(cdTableP[chNumP].chname));
 				// Load channel name into local table.
-				strcpy(cdTableP[chNumP].chname,s1);
+				cdTableP[chNumP].chname = s1;
 				// Check if s4 (monitor or not) is set (0/1). If doesn/'t exist in file, set to zero in local table.
 				if(argcount > 3 && isdigit(s4[0])) {
 					// printf("%s %s %s %s\n",s1,s2,s3,s4);
@@ -2025,7 +2060,7 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 							cdTableP[chNumP].mask = 0;
 						if (cdTableP[chNumP].mask > 0) cdTableP[chNumP].mask = ~0;
 					}
-					// printf("mask: %d %s\n", cdTableP[chNumP].mask, cdTableP[chNumP].chname);
+					// printf("mask: %d %s\n", cdTableP[chNumP].mask, cdTableP[chNumP].chname.c_str());
 				} else {
 					cdTableP[chNumP].mask = 0;
 				}
@@ -2039,11 +2074,11 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 					if(isdigit(s3[0])) {
 						cdTableP[chNumP].datatype = SDF_NUM;
 						cdTableP[chNumP].data.chval = atof(s3);
-						// printf("Alarm set - %s = %f\n",cdTableP[chNumP].chname,cdTableP[chNumP].data.chval);
+						// printf("Alarm set - %s = %f\n",cdTableP[chNumP].chname.c_str(),cdTableP[chNumP].data.chval);
 					} else {
 						cdTableP[chNumP].datatype = SDF_STR;
-						sprintf(cdTableP[chNumP].data.strval,"%s",s3);
-						// printf("Alarm set - %s = %s\n",cdTableP[chNumP].chname,cdTableP[chNumP].data.strval);
+						cdTableP[chNumP].data.strval = s3;
+						// printf("Alarm set - %s = %s\n",cdTableP[chNumP].chname.c_str(),cdTableP[chNumP].data.strval.c_str());
 					}
 					fprintf(adf,"%s %s %s\n",s1,s2,s3);
 				} 
@@ -2052,7 +2087,7 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 				   // Add settings to local table.
 				   for(ii=0;ii<chNum;ii++)
 				   {
-					if(strcmp(cdTable[ii].chname,cdTableP[chNumP].chname) == 0)
+					if(cdTable[ii].chname == cdTableP[chNumP].chname)
 					{
 					    saveStrSetPoint(ii, s3);
 						fmatch = 1;
@@ -2060,23 +2095,23 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 						{
 							// s3[strlen(s3) - 1] = 0;
 							cdTableP[chNumP].datatype = SDF_STR;
-							sprintf(cdTableP[chNumP].data.strval,"%s",s3);
+							cdTableP[chNumP].data.strval = s3;
 							if(command != SDF_LOAD_DB_ONLY)
 							{
-								sprintf(cdTable[ii].data.strval,"%s",s3);
+								cdTable[ii].data.strval = s3;
 							}
 						} else {
 							cdTableP[chNumP].datatype = SDF_NUM;
 							cdTableP[chNumP].data.chval = atof(s3);
 							if(cdTable[ii].filterswitch) {
 								if(cdTableP[chNumP].data.chval > 0xffff) {
-									sprintf(readErrTable[rderror].chname,"%s", cdTable[ii].chname);
-									sprintf(readErrTable[rderror].burtset, "0x%x", (int)cdTableP[chNumP].data.chval);
-									sprintf(readErrTable[rderror].liveset, "%s", "OVERRANGE");
+									readErrTable[rderror].chname = cdTable[ii].chname;
+									readErrTable[rderror].burtset.printf("0x%x", (int)cdTableP[chNumP].data.chval);
+									readErrTable[rderror].liveset = "OVERRANGE";
 									readErrTable[rderror].liveval = 0.0;
-									sprintf(readErrTable[rderror].diff, "%s", "MAX VAL = 0xffff");
-									sprintf(readErrTable[rderror].timeset, "%s", timestring);
-									printf("Read error --- %s\n", cdTable[ii].chname);
+									readErrTable[rderror].diff = "MAX VAL = 0xffff";
+									readErrTable[rderror].timeset = timestring;
+									printf("Read error --- %s\n", cdTable[ii].chname.c_str());
 									rderror ++;
 								}
 								cdTableP[chNumP].data.chval = (int) cdTableP[chNumP].data.chval & 0xffff;
@@ -2091,18 +2126,18 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 						}
 					}
 				   }
-				   // if(!fmatch) printf("NEW channel not found %s %d\n",cdTableP[chNumP].chname,chNumP);
+				   // if(!fmatch) printf("NEW channel not found %s %d\n",cdTableP[chNumP].chname.c_str(),chNumP);
 				}
 				// The following loads info into the filter module table if a FM switch
 				fmIndex = -1;
-				if(((strstr(s1,"_SW1S") != NULL) && (strstr(s1,"_SW1S.") == NULL)) ||
-					((strstr(s1,"_SW2S") != NULL) && (strstr(s1,"_SW2S.") == NULL)))
+				if(((strstr(s1,"_SW1S") != nullptr) && (strstr(s1,"_SW1S.") == nullptr)) ||
+					((strstr(s1,"_SW2S") != nullptr) && (strstr(s1,"_SW2S.") == nullptr)))
 				{
 				   	bzero(fname,sizeof(fname));
 					strncpy(fname,s1,(strlen(s1)-4));
 				   	for(ii=0;ii<fmNum;ii++)
 				   	{
-						if(strcmp(filterTable[ii].fname,fname) == 0) 
+						if(filterTable[ii].fname == fname)
 						{
 							fmIndex = ii;
 							filterTable[fmIndex].newSet = 1;
@@ -2113,19 +2148,17 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 				if(fmatch) {
 					chNumP ++;
 				} else {
-					// printf("CNF for %s \n",cdTableP[chNumP].chname);
+					// printf("CNF for %s \n",cdTableP[chNumP].chname.c_str());
 					if(chNotFound < SDF_ERR_TSIZE) {
-						sprintf(unknownChans[chNotFound].chname,"%s",cdTableP[chNumP].chname);
-                                                ADDRESS tmpaddr;
-						status = GET_ADDRESS(cdTableP[chNumP].chname, &tmpaddr);
-						if(!status) {
-							sprintf(unknownChans[chNotFound].liveset,"%s","RO Channel ");
+						unknownChans[chNotFound].chname = cdTableP[chNumP].chname;
+						if(GET_ADDRESS(cdTableP[chNumP].chname,&paddr)) {
+							unknownChans[chNotFound].liveset  = "RO Channel ";
 						} else {
-							sprintf(unknownChans[chNotFound].liveset,"%s","  ");
+							unknownChans[chNotFound].liveset = "  ";
 						}
 						unknownChans[chNotFound].liveval = 0.0;
-						sprintf(unknownChans[chNotFound].timeset,"%s"," ");
-						sprintf(unknownChans[chNotFound].diff,"%s"," ");
+						unknownChans[chNotFound].timeset = " ";
+						unknownChans[chNotFound].diff = " ";
 						unknownChans[chNotFound].chFlag = 0;
 					}
 					chNotFound ++;
@@ -2144,9 +2177,9 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 		fclose(cdf);
 		fclose(adf);
 		printf("Loading epics %d\n",chNumP);
-		lderror = writeEpicsDb(chNumP,cdTableP,command);
+		lderror = writeEpicsDb(cdTableP,command);
 		sleep(2);
-		newfilterstats(fmNum);
+		newfilterstats();
 		fmtInit = 1;
 	}
 
@@ -2155,13 +2188,13 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 	totaltime = t.tv_nsec - starttime;
 	if(totaltime < 0) totaltime += 1000000000;
 	if(command == SDF_LOAD_PARTIAL) {
-		sprintf(errMsg,"New SDF request (w/table update): %s\nFile = %s\nTotal Chans = %d with load time = %d usec\n",timestring,sdfile,chNumP,(totaltime/1000));
+		sprintf(errMsg,"New SDF request (w/table update): %s\nFile = %s\nTotal Chans = %d with load time = %d usec\n",timestring.c_str(), sdfile, chNumP, (totaltime/1000));
 	} else if(command == SDF_LOAD_DB_ONLY){
-		sprintf(errMsg,"New SDF request (No table update): %s\nFile = %s\nTotal Chans = %d with load time = %d usec\n",timestring,sdfile,chNumP,(totaltime/1000));
+		sprintf(errMsg,"New SDF request (No table update): %s\nFile = %s\nTotal Chans = %d with load time = %d usec\n",timestring.c_str(), sdfile, chNumP, (totaltime/1000));
 	}
 	logFileEntry(errMsg);
-	status = dbNameToAddr(reloadtimechannel,&paddr);
-	status = dbPutField(&paddr,DBR_STRING,timestring,1);
+	status = dbNameToAddr(reloadtimechannel,&reloadDbAddr);
+	status = dbPutField(&reloadDbAddr,DBR_STRING,timestring.c_str(),1);
 	printf("Number of read errors = %d\n",rderror);
 	if(rderror) lderror = 2;
 	return(lderror);
@@ -2169,25 +2202,27 @@ int readConfig( char *pref,		///< EPICS channel prefix from EPICS environment.
 
 void registerFilters() {
 	int ii = 0;
-	char tmpstr[64];
+	fixed_string<64> tmpstr;
 	int amatch = 0, jj = 0;
 	fmNum = 0;
 	for(ii=0;ii<chNum;ii++) {
 		if(cdTable[ii].filterswitch == 1)
 		{
-			strncpy(filterTable[fmNum].fname,cdTable[ii].chname,(strlen(cdTable[ii].chname)-4));
-			snprintf(tmpstr, sizeof(tmpstr),"%s%s",filterTable[fmNum].fname,"SW2S");
+			filterTable[fmNum].fname = cdTable[ii].chname;
+            filterTable[fmNum].fname.pop_back_n(4);
+			tmpstr = filterTable[fmNum].fname;
+			tmpstr += "SW2S";
 			filterTable[fmNum].sw[0] = ii;
 			cdTable[ii].filterNum = fmNum;
 			amatch = 0;
 			for(jj=0;jj<chNum;jj++) {
-				if(strcmp(tmpstr,cdTable[jj].chname) == 0)
+				if(tmpstr == cdTable[jj].chname)
 				{
 					filterTable[fmNum].sw[1] = jj;
 					amatch = 1;
 				}
 			}
-			if(!amatch) printf("No match for %s\n",tmpstr);
+			if(!amatch) printf("No match for %s\n",tmpstr.c_str());
 			fmNum ++;
 		}
 	}
@@ -2196,40 +2231,50 @@ void registerFilters() {
 
 /// Provide initial values to the filterMasks arrray and the SDF_FM_MASK and SDF_FM_MASK_CTRL variables
 ///
-void setupFMArrays(char *pref, int *fmMasks, dbAddr *fmMaskAddr, dbAddr *fmCtrlAddr) {
+void setupFMArrays(char *pref,fixed_size_vector<int, SDF_MAX_FMSIZE>& fmMasks,
+                   fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmMaskAddr,
+                   fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmCtrlAddr) {
 	int ii = 0;
 	int sw1 = 0;
 	int sw2 = 0;
-	long status = 0;
-	char name[256];
-	char ctrl[256];
+	fixed_string<256> name;
+	fixed_string<256> ctrl;
 	int zero = 0;
 
-	for (ii = 0; ii < SDF_MAX_FMSIZE; ++ii) {
-		sw1 = filterTable[ii].sw[0];
-		sw2 = filterTable[ii].sw[1];
-		fmMasks[ii] = filterTable[ii].mask = cdTable[sw1].mask | cdTable[sw2].mask;
+	fmMasks.clear();
+	fmMaskAddr.clear();
+	fmCtrlAddr.clear();
+	for (ii = 0; ii < filterTable.size(); ++ii)
+	{
+        sw1 = filterTable[ii].sw[0];
+        sw2 = filterTable[ii].sw[1];
+        fmMasks[ii] = filterTable[ii].mask = cdTable[sw1].mask | cdTable[sw2].mask;
 
-		sprintf(name, "%s_SDF_FM_MASK_%d", pref, ii);
-		status = dbNameToAddr(name, &fmMaskAddr[ii]);
-		status = dbPutField(&fmMaskAddr[ii],DBR_LONG,&(fmMasks[ii]),1);
+        name.printf("%s_SDF_FM_MASK_%d", pref, ii);
+        fmMaskAddr.emplace_back();
+        dbNameToAddr(name.c_str(), &fmMaskAddr[ii]);
+        dbPutField(&fmMaskAddr[ii],DBR_LONG,&(fmMasks[ii]),1);
 
-		sprintf(ctrl, "%s_SDF_FM_MASK_CTRL_%d", pref, ii);
-		status = dbNameToAddr(ctrl, &fmCtrlAddr[ii]);
-		status = dbPutField(&fmCtrlAddr[ii],DBR_LONG,&zero,1);
+        ctrl.printf("%s_SDF_FM_MASK_CTRL_%d", pref, ii);
+        fmCtrlAddr.emplace_back();
+        dbNameToAddr(ctrl.c_str(), &fmCtrlAddr[ii]);
+        dbPutField(&fmCtrlAddr[ii],DBR_LONG,&zero,1);
 
-	} 
+    }
 }
 
 /// Copy the filter mask information from cdTable into fmMasks
 ///
-void resyncFMArrays(int *fmMasks, dbAddr *fmMaskAddr) {
+void resyncFMArrays(fixed_size_vector<int, SDF_MAX_FMSIZE>&fmMasks,
+                    fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmMaskAddr)
+{
 	int ii = 0;
 	int sw1 = 0;
 	int sw2 = 0;
 	long status = 0;
 
-	for (ii = 0; ii < SDF_MAX_FMSIZE; ++ii) {
+
+	for (ii = 0; ii < filterTable.size(); ++ii) {
 		sw1 = filterTable[ii].sw[0];
 		sw2 = filterTable[ii].sw[1];
 		fmMasks[ii] = filterTable[ii].mask = (cdTable[sw1].mask | cdTable[sw2].mask) & ALL_SWSTAT_BITS;
@@ -2253,7 +2298,11 @@ void resyncFMArrays(int *fmMasks, dbAddr *fmMaskAddr) {
 ///
 /// @remark Each of the input arrays is expected to have a length of SDF_MAX_FMSIZE
 /// with fmNum in actual use.
-void processFMChanCommands(int *fMask, dbAddr *fmMaskAddr, dbAddr *fmCtrlAddr, int *selectCounter, int errCnt, SET_ERR_TABLE *setErrTable) {
+void processFMChanCommands(
+        fixed_size_vector<int, SDF_MAX_FMSIZE>& fMask,
+        fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmMaskAddr,
+        fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmCtrlAddr,
+        int *selectCounter, table_range setErrTable) {
 	int ii = 0;
 	int jj = 0;
 	int refMask = 0;
@@ -2265,7 +2314,8 @@ void processFMChanCommands(int *fMask, dbAddr *fmMaskAddr, dbAddr *fmCtrlAddr, i
 	long nvals = 1;
 	int foundCh = 0;
 
-	for (ii = 0; ii < SDF_MAX_FMSIZE && ii < fmNum; ++ii) {
+	//std::distance(setErrTable.begin(), setErrTable.end());
+	for (ii = 0; ii < filterTable.size(); ++ii) {
 		status = dbGetField(&fmCtrlAddr[ii], DBR_LONG, &ctrl, &ropts, &nvals, NULL);
 
 		// only do work if there is a change
@@ -2282,15 +2332,22 @@ void processFMChanCommands(int *fMask, dbAddr *fmMaskAddr, dbAddr *fmCtrlAddr, i
 		foundCh = 0;
 		/* if there is a change, update4 the selection count) */
 		if (differsPre != differsPost) {
-			for (jj = 0; jj < errCnt && setErrTable[jj].filtNum >= 0 && setErrTable[jj].filtNum != ii; ++jj) {}
-			if (jj < errCnt && setErrTable[jj].filtNum == ii) {
-				setErrTable[jj].chFlag ^= CHFLAG_MONITOR_BIT_VAL;
-				foundCh = setErrTable[jj].chFlag;
+		    // search through setErrTable
+			//for (jj = 0; jj < errCnt && setErrTable[jj].filtNum >= 0 && setErrTable[jj].filtNum != ii; ++jj) {}
+			auto match = std::find_if(setErrTable.begin(), setErrTable.end(), [ii](const SET_ERR_TABLE& cur) -> bool {
+			    return cur.filtNum == ii;
+			});
+			// act on search
+			//if (jj < errCnt && setErrTable[jj].filtNum == ii)
+			if ( match != setErrTable.end())
+			{
+				match->chFlag ^= CHFLAG_MONITOR_BIT_VAL;
+				foundCh = match->chFlag;
 				selectCounter[2] += ( differsPre ? -1 : 1 );
 			}
 		}
 
-		printf("Signal 0x%x set on '%s' ref=0x%x pre=0x%x post=0x%x pre/post diff(%d,%d) chFlag = 0x%x\n", ctrl, filterTable[ii].fname, refMask, preMask, fMask[ii], differsPre, differsPost, foundCh);
+		printf("Signal 0x%x set on '%s' ref=0x%x pre=0x%x post=0x%x pre/post diff(%d,%d) chFlag = 0x%x\n", ctrl, filterTable[ii].fname.c_str(), refMask, preMask, fMask[ii], differsPre, differsPost, foundCh);
 
 		dbPutField(&fmMaskAddr[ii],DBR_LONG,&(fMask[ii]),1);
 
@@ -2329,7 +2386,7 @@ void updateStrVarSetPoint(int index)
 {
     if (caStringSetpointInitted[index] == 1)
     {
-        strcpy(cdTable[index].data.strval, caStringSetpoint[index]);
+        cdTable[index].data.strval = caStringSetpoint[index];
         caStringSetpointInitted[index] = 2;
     }
 }
@@ -2351,53 +2408,53 @@ long countDisconnectedChans()
 
 void nullCACallback(struct event_handler_args args) {}
 
-int getCAIndex(char *entry, ADDRESS *addr) {
+bool getCAIndex(const char *entry, ADDRESS *addr) {
 	int ii = 0;
 
-	if (!entry || !addr) return 1;
+	if (!entry || !addr) return false;
 	for (ii = 0; ii < chNum; ++ii) {
-		if (strcmp(cdTable[ii].chname, entry) == 0) {
+		if (cdTable[ii].chname == entry) {
 			*addr = ii;
-			return 0;
+			return true;
 		}
 	}
 	*addr = -1;
-	return 1;
+	return false;
 }
 
-int setCAValue(ADDRESS ii, int type, void *data)
+bool setCAValue(ADDRESS ii, SDF_TYPE type, const void *data)
 {
+	bool result = false;
 	int status = ECA_NORMAL;
-	int result = 1;
-	
+
 	if (ii >= 0 && ii < chNum) {
 		if (type == SDF_NUM) {
 			status = ca_put_callback(DBR_DOUBLE, caTable[ii].chanid, (double *)data, nullCACallback, NULL);
 		} else {
 			status = ca_put_callback(DBR_STRING, caTable[ii].chanid, (char *)data, nullCACallback, NULL);
 		}
-		result = (status == ECA_NORMAL ? 0 : 1);
+		result = (status == ECA_NORMAL);
 	}
 	return result;
 }
 
-int setCAValueEPICSLong(ADDRESS ii, unsigned int *data) {
+bool setCAValueLong(ADDRESS ii, const PV_INT_TYPE *data) {
 	double tmp = 0.0;
 
-	if (!data) return 1;
+	if (!data) return false;
 	tmp = (double)*data;
-	return setCAValue(ii,SDF_NUM,(void*)&tmp);
+	return setCAValue(ii,SDF_NUM,(const void*)&tmp);
 }
 
-int syncEpicsDoubleValue(int index, double *dest, time_t *tp, int *connp) {
+bool syncEpicsDoubleValue(ADDRESS index, double *dest, time_t *tp, int *connp) {
 	int debug = 0;
-	if (!dest || index < 0 || index >= chNum) return 1;
+	if (!dest || index < 0 || index >= chNum) return false;
 #if VERBOSE_DEBUG
-	if (strcmp(cdTable[caTable[index].chanIndex].chname, TEST_CHAN) == 0) {
+	if (strcmp(cdTable[caTable[index].chanIndex].chname.c_str(), TEST_CHAN) == 0) {
 		debug=1;
 	}
 #endif
-	pthread_mutex_lock(&caTableMutex);
+	lock_guard l_(caTableMutex);
 	if (caTable[index].datatype == SDF_NUM) {
 		*dest = caTable[index].data.chval;
 		if (tp) {
@@ -2407,27 +2464,26 @@ int syncEpicsDoubleValue(int index, double *dest, time_t *tp, int *connp) {
 			*connp = caTable[index].connected;
 		}
 	}
-	pthread_mutex_unlock(&caTableMutex);
-	return 0;
+	return true;
 }
 
-int syncEpicsIntValue(ADDRESS index, unsigned int *dest, time_t *tp, int *connp) {
+bool syncEpicsIntValue(ADDRESS index, PV_INT_TYPE *dest, time_t *tp, int *connp) {
+	bool result = true;
 	double tmp = 0.0;
-	int result = 0;
 
-	if (!dest) return 1;
+	if (!dest) return false;
 	result = syncEpicsDoubleValue(index, &tmp, tp, connp);
-	*dest = (unsigned int)(tmp);
+	*dest = (PV_INT_TYPE)(tmp);
 	return result;
 }
 
-int syncEpicsStrValue(int index, char *dest, int dest_size, time_t *tp, int *connp) {
-	if (!dest || index < 0 || index >= chNum || dest_size < 1) return 1;
+bool syncEpicsStrValue(ADDRESS index, char *dest, int dest_size, time_t *tp, int *connp) {
+	if (!dest || index < 0 || index >= chNum || dest_size < 1) return false;
 	dest[0] = '\0';
-	pthread_mutex_lock(&caTableMutex);
+	lock_guard l_(caTableMutex);
 	if (caTable[index].datatype == SDF_STR) {
-		const int MAX_STR_LEN = sizeof(caTable[index].data.strval);
-		strncpy(dest, caTable[index].data.strval, (dest_size < MAX_STR_LEN ? dest_size : MAX_STR_LEN));
+		const int MAX_STR_LEN = caTable[index].data.strval.capacity();
+		strncpy(dest, caTable[index].data.strval.c_str(), (dest_size < MAX_STR_LEN ? dest_size : MAX_STR_LEN));
 		dest[dest_size-1] = '\0';
 		if (tp) {
 			*tp = caTable[index].mod_time;
@@ -2436,14 +2492,13 @@ int syncEpicsStrValue(int index, char *dest, int dest_size, time_t *tp, int *con
 			*connp = caTable[index].connected;
 		}
 	}
-	pthread_mutex_unlock(&caTableMutex);
-	return 0;
+	return true;
 }
 
 /// Routine to handle subscription callbacks
 void subscriptionHandler(struct event_handler_args args) {
 	float val = 0.0;
-	EPICS_CA_TABLE *entry = args.usr;
+	EPICS_CA_TABLE *entry = reinterpret_cast<EPICS_CA_TABLE*>(args.usr);
 	EPICS_CA_TABLE *origEntry = entry;
 	int initialRedirIndex = 0;
 
@@ -2451,7 +2506,7 @@ void subscriptionHandler(struct event_handler_args args) {
 		return;
 	}
 
-	pthread_mutex_lock(&caTableMutex);
+	lock_guard l_(caTableMutex);
 
 	// If this entry has just reconnected, then do not write the old copy, write to the temporary/redir dest
 	initialRedirIndex = entry->redirIndex;
@@ -2465,15 +2520,13 @@ void subscriptionHandler(struct event_handler_args args) {
 
 	// if we are getting data, we must be connected.
 	entry->connected = 1;
-	const int MAX_STR_LEN = sizeof(entry->data.strval);
 	if (args.type == DBR_TIME_DOUBLE) {
 		struct dbr_time_double *dVal = (struct dbr_time_double *)args.dbr;
 		entry->data.chval = dVal->value;
 		entry->mod_time = dVal->stamp.secPastEpoch + POSIX_TIME_AT_EPICS_EPOCH;
 	} else if (args.type == DBR_TIME_STRING) {
 		struct dbr_time_string *sVal = (struct dbr_time_string *)args.dbr;
-		strncpy(entry->data.strval, sVal->value, MAX_STR_LEN);
-		entry->data.strval[MAX_STR_LEN - 1] = '\0';
+		entry->data.strval = sVal->value;
 		entry->mod_time = sVal->stamp.secPastEpoch + POSIX_TIME_AT_EPICS_EPOCH;
 	} else if (args.type == DBR_GR_ENUM) {
 		struct dbr_gr_enum *eVal = (struct dbr_gr_enum *)args.dbr;
@@ -2497,16 +2550,14 @@ void subscriptionHandler(struct event_handler_args args) {
 			entry->data.chval = (double)(eVal->value);
 		} else {
 			if (eVal->value > 0 && eVal->value < eVal->no_str) {
-				strncpy(entry->data.strval, eVal->strs[eVal->value], MAX_STR_LEN);
+                            entry->data.strval = eVal->strs[eVal->value];
 			} else {
-				snprintf(entry->data.strval, MAX_STR_LEN, "Unexpected enum value received - %d", (int)eVal->value);
+			    entry->data.strval.printf("Unexpected enum value received - %d", (int)eVal->value);
 			}
-			entry->data.strval[MAX_STR_LEN - 1] = '\0';
 		}
 		// The dbr_gr_enum type does not have time information, so we use current time
 		entry->mod_time = time(NULL);
 	}
-	pthread_mutex_unlock(&caTableMutex);
 }
 
 void connectCallback(struct connection_handler_args args) {
@@ -2533,70 +2584,73 @@ void connectCallback(struct connection_handler_args args) {
 			}
 		}
 
-		pthread_mutex_lock(&caTableMutex);
-		if (args.op == CA_OP_CONN_UP) {
-			// connection
-			if (is_enum) {
-				entry->redirIndex = entry->chanIndex + SDF_MAX_TSIZE;
-				connEntry = &(caConnEnumTable[entry->chanIndex]);
-			} else {
-				// reserve a new conn table entry if one is not already reserved
-				if (entry->redirIndex < 0) {
-					entry->redirIndex = chConnNum;
-					++chConnNum;
-				}
-				connEntry = &(caConnTable[entry->redirIndex]);
-			}
-			entry->chanid = args.chid;
+        {
+            lock_guard l_(caTableMutex);
+            if (args.op == CA_OP_CONN_UP) {
+                // connection
+                if (is_enum) {
+                    entry->redirIndex = entry->chanIndex + SDF_MAX_TSIZE;
+                    connEntry = &(caConnEnumTable[entry->chanIndex]);
+                } else {
+                    // reserve a new conn table entry if one is not already reserved
+                    if (entry->redirIndex < 0) {
+                        entry->redirIndex = chConnNum;
+                        ++chConnNum;
+                    }
+                    connEntry = &(caConnTable[entry->redirIndex]);
+                }
+                entry->chanid = args.chid;
 
-			// now copy items over to the connection record
-			connEntry->redirIndex = -1;
+                // now copy items over to the connection record
+                connEntry->redirIndex = -1;
 
-			connEntry->datatype = sdf_type;
-			connEntry->data.chval = 0.0;
-			entry->connected = 1;
-			connEntry->connected = 1;
-			connEntry->mod_time = 0;
-			connEntry->chanid = args.chid;
-			connEntry->chanIndex = entry->chanIndex;
-			typeChange = (connEntry->datatype != entry->datatype);
+                connEntry->datatype = sdf_type;
+                connEntry->data.chval = 0.0;
+                entry->connected = 1;
+                connEntry->connected = 1;
+                connEntry->mod_time = 0;
+                connEntry->chanid = args.chid;
+                connEntry->chanIndex = entry->chanIndex;
+                typeChange = (connEntry->datatype != entry->datatype);
 
-		} else {
-			// disconnect
-			entry->connected = 0;
-		}
-		pthread_mutex_unlock(&caTableMutex);
+            } else {
+                // disconnect
+                entry->connected = 0;
+            }
+        }
 
-		// now register/clear the subscription callback
-		pthread_mutex_lock(&caEvidMutex);
-		if (args.op == CA_OP_CONN_UP) {
-			// connect
-			// if we are subscribed but the types are wrong, then unsubscribe
-			if (caEvid[chanIndex] && typeChange) {
-				ca_clear_subscription(caEvid[chanIndex]);
-				caEvid[chanIndex] = 0;
-			}
-			// if we are not subscribed become subscribed
-			if (!caEvid[chanIndex]) {
-				chtype subtype = (sdf_type == SDF_NUM ? DBR_TIME_DOUBLE : DBR_TIME_STRING);
-				if (is_enum) {
-					subtype = DBR_GR_ENUM;
-				}
-				ca_create_subscription(subtype, 0, args.chid, DBE_VALUE, subscriptionHandler, entry, &(caEvid[chanIndex]));
-			}
-		} else {
-			// disconnect
-			if (caEvid[chanIndex]) {
-				ca_clear_subscription(caEvid[chanIndex]);
-				caEvid[chanIndex] = 0;
-			}
-		}
-		pthread_mutex_unlock(&caEvidMutex);
+        {
+            // now register/clear the subscription callback
+            lock_guard l_(caEvidMutex);
+            if (args.op == CA_OP_CONN_UP) {
+                // connect
+                // if we are subscribed but the types are wrong, then unsubscribe
+                if (caEvid[chanIndex] && typeChange) {
+                    ca_clear_subscription(caEvid[chanIndex]);
+                    caEvid[chanIndex] = 0;
+                }
+                // if we are not subscribed become subscribed
+                if (!caEvid[chanIndex]) {
+                    chtype subtype = (sdf_type == SDF_NUM ? DBR_TIME_DOUBLE : DBR_TIME_STRING);
+                    if (is_enum) {
+                        subtype = DBR_GR_ENUM;
+                    }
+                    ca_create_subscription(subtype, 0, args.chid, DBE_VALUE, subscriptionHandler, entry,
+                                           &(caEvid[chanIndex]));
+                }
+            } else {
+                // disconnect
+                if (caEvid[chanIndex]) {
+                    ca_clear_subscription(caEvid[chanIndex]);
+                    caEvid[chanIndex] = 0;
+                }
+            }
+        }
 	}
 }
 
 /// Routine to register a channel
-void registerPV(char *PVname)
+void registerPV(const char *PVname)
 {
 	long status=0;
 	chid chid1;
@@ -2606,19 +2660,19 @@ void registerPV(char *PVname)
 		return;
 	}
 	//printf("Registering %s\n", PVname);
-	pthread_mutex_lock(&caTableMutex);
-	caTable[chNum].datatype = SDF_NUM;
-	caTable[chNum].connected = 0;
-	strncpy(cdTable[chNum].chname, PVname, 128);
-	cdTable[chNum].chname[128-1] = '\0';
-	cdTable[chNum].datatype = SDF_NUM;
-	cdTable[chNum].initialized = 0;
-	cdTable[chNum].filterswitch = 0;
-	cdTable[chNum].filterNum = -1;
-	cdTable[chNum].error = 0;
-	cdTable[chNum].initialized = 0;
-	cdTable[chNum].mask = 0;
-	pthread_mutex_unlock(&caTableMutex);
+    {
+        lock_guard l_(caTableMutex);
+        caTable[chNum].datatype = SDF_NUM;
+        caTable[chNum].connected = 0;
+        cdTable[chNum].chname = PVname;
+        cdTable[chNum].datatype = SDF_NUM;
+        cdTable[chNum].initialized = 0;
+        cdTable[chNum].filterswitch = 0;
+        cdTable[chNum].filterNum = -1;
+        cdTable[chNum].error = 0;
+        cdTable[chNum].initialized = 0;
+        cdTable[chNum].mask = 0;
+    }
 
 	status = ca_create_channel(PVname, connectCallback, &(caTable[chNum]), 0, &chid1);
 
@@ -2649,46 +2703,55 @@ int daqToSDFDataType(int daqtype) {
 /// Parse an BURT request file and register each channel to be monitored
 /// @input fname - name of the file to open
 /// @input pref - the ifo name, should be 3 characters
-void parseChannelListReq(char *fname, char *pref) {
+void parseChannelListReq(char *fname) {
 	FILE *f = 0;
-	char ifo[4];
 	char line[128];
-	char s1[128],s2[128],s3[128],s4[128],s5[128],s6[128],s7[128],s8[128];
 	int argcount = 0;
+        int in_header = 0;
+        const static char* header_start = "--- Start";
+        const static char* header_end = "--- End";
 
-	line[0]=s1[0]=s2[0]=s3[0]=s4[0]=s5[0]=s6[0]=s7[0]=s8[0]='\0';
-	strncpy(ifo, pref, 3);
-	ifo[3] = '\0';
+	line[0]='\0';
 	f = fopen(fname, "r");
 	if (!f) return;
 
+        embedded::fixed_size_vector<embedded::fixed_string<128>, 1> words;
+
 	while (fgets(line, sizeof(line), f) != NULL) {
-		argcount = parseLine(line, sizeof(s1), s1, s2, s3, s4, s5, s6);
+                if (in_header)
+                {
+                    if (strstr(line, header_end) == line)
+                    {
+                        in_header = 0;
+                    }
+                    continue;
+                }
+                else if (strstr( line, header_start) == line)
+                {
+                    in_header = 1;
+                    continue;
+                }
+                argcount = BURT::parseLine(line, words);
 		if (argcount < 1) continue;
-		if (strncmp(s1, ifo, 3) != 0) continue;
-		if (strstr(s1,"_SWMASK") != NULL ||	
-			strstr(s1,"_SDF_NAME") != NULL ||
-			strstr(s1,"_SWREQ") != NULL) continue;
-		if (isAlarmChannel(s1)) continue;
-		registerPV(s1);
+		if (strstr(words.front().c_str(),"_SWMASK") != NULL ||
+			strstr(words.front().c_str(),"_SDF_NAME") != NULL ||
+			strstr(words.front().c_str(),"_SWREQ") != NULL) continue;
+		if (isAlarmChannelRaw(words.front().c_str())) continue;
+		registerPV(words.front().c_str());
 	}
 	fclose(f);
 }
 
 /// Routine to get the state of the CA Thread
 int getCAThreadState() {
-	int state = 0;
-	pthread_mutex_lock(&caStateMutex);
-	state = caThreadState;
-	pthread_mutex_unlock(&caStateMutex);
-	return state;
+	lock_guard l_(caStateMutex);
+	return caThreadState;
 }
 
 /// Routine to set the state of the CA Thread
 void setCAThreadState(int state) {
-	pthread_mutex_lock(&caStateMutex);
+	lock_guard l_(caStateMutex);
 	caThreadState = state;
-	pthread_mutex_unlock(&caStateMutex);
 }
 
 // copy the given entry (which should be in caConnTable or caConnEnumTable) to caTable
@@ -2724,7 +2787,7 @@ void syncCAConnections(long *disconnected_count)
 	int chanIndex = SDF_MAX_TSIZE;
 	chtype subtype = DBR_TIME_DOUBLE;
 
-	pthread_mutex_lock(&caTableMutex);
+	lock_guard l_(caTableMutex);
 	// sync all non-enum channel connections that have taken place
 	for (ii = 0; ii < chConnNum; ++ii) {
 		copyConnectedCAEntry(&(caConnTable[ii]));
@@ -2762,7 +2825,6 @@ void syncCAConnections(long *disconnected_count)
 	//	}
 	//	*disconnected_count = tmp;
 	//}
-	pthread_mutex_unlock(&caTableMutex);
 }
 
 /// Main loop of the CA Thread
@@ -2776,22 +2838,21 @@ void *caMainLoop(void *param)
 	}
 	ca_context_create(ca_enable_preemptive_callback);
 	setCAThreadState(CA_STATE_PARSING);
-	parseChannelListReq(info->fname, info->prefix);
+	parseChannelListReq(info->fname);
 	registerFilters();
 	printf("Done with parsing, CA thread continuing\n");
 	setCAThreadState(CA_STATE_RUNNING);
+	return nullptr;
 }
 
 /// Routine used to read in all channels to monitor from an INI file and create local connections
-void initCAConnections(char *fname, char *prefix)
+void initCAConnections(char *fname)
 {
 	int err = 0;
 	int state = CA_STATE_OFF;
 	CA_STARTUP_INFO param;
 
 	param.fname = fname;
-	param.prefix = prefix;
-
 
 	setCAThreadState(CA_STATE_OFF);
 	caMainLoop(&param);
@@ -2811,7 +2872,7 @@ void setupCASDF()
 		caTable[ii].datatype = SDF_NUM;
 		caTable[ii].data.chval = 0.0;
 		caTable[ii].connected = 0;
-		caTable[ii].chanid = (void *)-1;
+		caTable[ii].chanid = nullptr;
 		caTable[ii].mod_time = (time_t)0;
 		caTable[ii].chanIndex = ii;
 
@@ -2819,7 +2880,7 @@ void setupCASDF()
 		caConnTable[ii].datatype = SDF_NUM;
 		caConnTable[ii].data.chval = 0.0;
 		caConnTable[ii].connected = 0;
-		caConnTable[ii].chanid = (void *)-1;
+		caConnTable[ii].chanid = nullptr;
 		caConnTable[ii].mod_time = (time_t)0;
 		caConnTable[ii].chanIndex = 0;
 
@@ -2827,7 +2888,7 @@ void setupCASDF()
 		caConnEnumTable[ii].datatype = SDF_UNKNOWN;
 		caConnEnumTable[ii].data.chval = 0.0;
 		caConnEnumTable[ii].connected = 0;
-		caConnEnumTable[ii].chanid = (void *)-1;
+		caConnEnumTable[ii].chanid = nullptr;
 		caConnEnumTable[ii].mod_time = (time_t)0;
 		caConnEnumTable[ii].chanIndex = ii;
 
@@ -2853,20 +2914,13 @@ void setupCASDF()
 		bzero((void *)&(readErrTable[ii]), sizeof(readErrTable[ii]));
 	}
 	droppedPVCount = 0;
-	pthread_mutex_init(&caStateMutex, NULL);	// FIXME check for errors
-	pthread_mutex_init(&caTableMutex, NULL);
-	pthread_mutex_init(&caEvidMutex, NULL);
 }
 
 /// Routine to tear-down mutexes and other resources used by the CA SDF system
 void cleanupCASDF()
 {
-	pthread_mutex_destroy(&caEvidMutex);
-	pthread_mutex_destroy(&caTableMutex);
-	pthread_mutex_destroy(&caStateMutex);
 }
 #else
-
 void countDisconnectedChannels(int curTable)
 {
 }
@@ -2879,17 +2933,18 @@ void updateStrVarSetPoint(int index)
 {
 }
 
-int getDbValueDouble(ADDRESS *paddr,double *dest,time_t *tp) {
+bool getDbValueDouble(ADDRESS *paddr,double *dest,time_t *tp) {
+
 	struct buffer {
 		DBRtime
 		double dval;
 	} buffer;
 	long options = DBR_TIME;
 	long nvals = 1;
-	int result = 1;
+	bool result = false;
 
 	if (dest && paddr) {
-		result = dbGetField(paddr, DBR_DOUBLE, &buffer, &options, &nvals, NULL);
+		result = dbGetField(paddr, DBR_DOUBLE, &buffer, &options, &nvals, NULL) == 0;
 		*dest = buffer.dval;
 		if (tp) {
 			*tp = buffer.time.secPastEpoch + POSIX_TIME_AT_EPICS_EPOCH;
@@ -2897,17 +2952,17 @@ int getDbValueDouble(ADDRESS *paddr,double *dest,time_t *tp) {
 	}
 	return result;
 }
-int getDbValueLong(ADDRESS *paddr,unsigned int *dest,time_t *tp) {
+bool getDbValueLong(ADDRESS *paddr,PV_INT_TYPE *dest,time_t *tp) {
 	struct buffer {
 		DBRtime
 		unsigned int dval;
 	} buffer;
 	long options = DBR_TIME;
 	long nvals = 1;
-	int result = 1;
+	bool result = false;
 
 	if (dest && paddr) {
-		result = dbGetField(paddr, DBR_LONG, &buffer, &options, &nvals, NULL);
+		result = dbGetField(paddr, DBR_LONG, &buffer, &options, &nvals, NULL) == 0;
 		*dest = buffer.dval;
 		if (tp) {
 			*tp = buffer.time.secPastEpoch + POSIX_TIME_AT_EPICS_EPOCH;
@@ -2915,16 +2970,16 @@ int getDbValueLong(ADDRESS *paddr,unsigned int *dest,time_t *tp) {
 	}
 	return result;
 }
-int getDbValueString(ADDRESS *paddr,char *dest, int max_len, time_t *tp) {
+bool getDbValueString(ADDRESS *paddr,char *dest, int max_len, time_t *tp) {
 	struct buffer {
 		DBRtime
 		char sval[128];
 	} strbuffer;
 	long options = DBR_TIME;
 	long nvals = 1;
-	int result = 1;
+	bool result = false;
 	if (dest && paddr && (max_len > 0)) {
-		result = dbGetField(paddr,DBR_STRING,&strbuffer,&options,&nvals,NULL);
+		result = dbGetField(paddr,DBR_STRING,&strbuffer,&options,&nvals,NULL) == 0;
 		strncpy(dest, strbuffer.sval, max_len);
 		dest[max_len-1]='\0';
 		if (tp) {
@@ -2972,9 +3027,9 @@ void dbDumpRecords(DBBASE *pdbbase, const char *pref)
                 printf("\n  Alias:%s\n",dbGetRecordName(pdbentry));
             } else {
 		//fprintf(stderr, "processing %s\n", dbGetRecordName(pdbentry));
-		sprintf(cdTable[chNum].chname,"%s",dbGetRecordName(pdbentry));
+		cdTable[chNum].chname = dbGetRecordName(pdbentry);
 		// do not monitor the the SDF mask channels, they are part of this IOC
-		if (strncmp(cdTable[chNum].chname, mask_pref, pref_len)==0) {
+		if ( cdTable[chNum].chname == mask_pref ) {
             --cnt;
             continue;
 		}
@@ -2982,12 +3037,12 @@ void dbDumpRecords(DBBASE *pdbbase, const char *pref)
 		cdTable[chNum].filterNum = -1;
 		// Check if this is a filter module
 		// If so, initialize parameters
-		if((strstr(cdTable[chNum].chname,"_SW1S") != NULL) && (strstr(cdTable[chNum].chname,"_SW1S.") == NULL))
+		if((strstr(cdTable[chNum].chname.c_str(),"_SW1S") != NULL) && (strstr(cdTable[chNum].chname.c_str(),"_SW1S.") == NULL))
 		{
 			cdTable[chNum].filterswitch = 1;
 			fmNum ++;
 		}
-		if((strstr(cdTable[chNum].chname,"_SW2S") != NULL) && (strstr(cdTable[chNum].chname,"_SW2S.") == NULL))
+		if((strstr(cdTable[chNum].chname.c_str(),"_SW2S") != NULL) && (strstr(cdTable[chNum].chname.c_str(),"_SW2S.") == NULL))
 		{
 			cdTable[chNum].filterswitch = 2;
 		}
@@ -2996,7 +3051,7 @@ void dbDumpRecords(DBBASE *pdbbase, const char *pref)
 			cdTable[chNum].data.chval = 0.0;
 		} else {
 			cdTable[chNum].datatype = SDF_STR;
-			sprintf(cdTable[chNum].data.strval,"");
+			cdTable[chNum].data.strval = "";
 		}
 		cdTable[chNum].mask = 0;
 		cdTable[chNum].initialized = 0;
@@ -3041,42 +3096,6 @@ void listLocalRecords(DBBASE *pdbbase) {
 /// Called on EPICS startup; This is generic EPICS provided function, modified for LIGO use.
 int main(int argc,char *argv[])
 {
-	// Addresses for SDF EPICS records.
-	dbAddr reload_addr;
-	dbAddr sdfname_addr;
-	dbAddr reloadstat_addr;
-	dbAddr loadedfile_addr;
-	dbAddr sperroraddr;
-	dbAddr alrmchcountaddr;
-#ifdef CA_SDF
-	dbAddr disconnectcountaddr;
-	dbAddr droppedcountaddr;
-#endif
-	dbAddr filesetcntaddr;
-	dbAddr fulldbcntaddr;
-	dbAddr monchancntaddr;
-	dbAddr tablesortreqaddr;
-	dbAddr wcreqaddr;
-	dbAddr chnotfoundaddr;
-	dbAddr chnotinitaddr;
-	dbAddr sorttableentriesaddr;
-	dbAddr monflagaddr;
-	dbAddr reloadtimeaddr;
-	dbAddr rcgversion_addr;
-	dbAddr msgstraddr;
-	dbAddr edbloadedaddr;
-	dbAddr savecmdaddr;
-	dbAddr saveasaddr;
-	dbAddr wcstringaddr;
-	dbAddr savetypeaddr;
-	dbAddr saveoptsaddr;
-	dbAddr savefileaddr;
-	dbAddr savetimeaddr;
-	dbAddr daqmsgaddr;
-	dbAddr coeffmsgaddr;
-	dbAddr resetoneaddr;
-	dbAddr selectaddr[4];
-	dbAddr pagelockaddr[3];	// why is this an array of 3.  It looks like we can make this a single value
 #ifdef CA_SDF
 	// CA_SDF does not do a partial load on startup.
 	int sdfReq = SDF_READ_ONLY;
@@ -3090,8 +3109,8 @@ int main(int argc,char *argv[])
 	long nvals = 1;
 	int rdstatus = 0;
 	int burtstatus = 0;
-	char loadedSdf[256];
-	char sdffileloaded[256];
+	embedded::fixed_string<256> loadedSdf{};
+	embedded::fixed_string<256> sdffileloaded{};
    	int sperror = 0;
 	int noMon = 0;
 	int noInit = 0;
@@ -3104,9 +3123,9 @@ int main(int argc,char *argv[])
 	int monFlag = 0;
 	int sdfSaveReq = 0;
 	int saveType = 0;
-	char saveTypeString[64];
+	embedded::fixed_string<256> saveTypeString{};
 	int saveOpts = 0;
-	char saveOptsString[64];
+    embedded::fixed_string<256> saveOptsString{};
 	int fivesectimer = 0;
 	long daqFileCrc = 0;
 	long coeffFileCrc = 0;
@@ -3130,18 +3149,13 @@ int main(int argc,char *argv[])
 	int selectAll = 0;
 	int freezeTable = 0;
 	int zero = 0;
-	char backupName[64];
+	embedded::fixed_string<256> backupName{};
 	int lastTable = 0;
 	int cdSort = 0;
 	int diffCnt = 0;
-    	char errMsg[128];
+  	char errMsg[128];
 
-    loadedSdf[0] = '\0';
-    sdffileloaded[0] = '\0';
     tsrString[0] = '\0';
-    saveTypeString[0] = '\0';
-    saveOptsString[0] = '\0';
-    backupName[0] = '\0';
     errMsg[0] = '\0';
 
     if(argc>=2) {
@@ -3171,156 +3185,107 @@ int main(int argc,char *argv[])
 	char *fotonDiffFile = getenv("FOTON_DIFF_FILE");
 	char *logdir = getenv("LOG_DIR");
 	char myDiffCmd[256];
-	SET_ERR_TABLE *currentTable = 0;
-	int currentTableCnt = 0;
+	table_range currentTable;
+
 
 	if(stat(logdir, &st) == -1) mkdir(logdir,0777);
 	// strcat(sdf,"_safe");
-	char sdf[256];
-	char sdfile[256];
-	char sdalarmfile[256];
-	char bufile[256];
-	char saveasfilename[128];
-	char wcstring[64];
-	
-    strncpy(sdf, sdfenv, sizeof(sdf));
-    sdf[sizeof(sdf)-1] = '\0';
+	embedded::fixed_string<256> sdf;
+    embedded::fixed_string<256>  sdfile;
+	embedded::fixed_string<256>  sdalarmfile;
+	embedded::fixed_string<256>  bufile;
+    embedded::fixed_string<256>  saveasfilename;
+    embedded::fixed_string<256>  wcstring;
+
+    sdf = sdfenv;
 	
 	printf("My prefix is %s\n",pref);
-	sprintf(sdfile, "%s%s%s", sdfDir, sdf,".snap");					// Initialize with BURT_safe.snap
-	sprintf(bufile, "%s%s", sdfDir, "fec.snap");					// Initialize table dump file
+	sdfile.printf("%s%s%s", sdfDir, sdf.c_str(), ".snap");  // Initialize with BURT_safe.snap
+	bufile.printf("%s%s", sdfDir, "fec.snap");					// Initialize table dump file
 	sprintf(logfilename, "%s%s", logdir, "/ioc.log");					// Initialize table dump file
-	printf("SDF FILE = %s\n",sdfile);
-	printf("CURRENt FILE = %s\n",bufile);
+	printf("SDF FILE = %s\n",sdfile.c_str() );
+	printf("CURRENt FILE = %s\n",bufile.c_str() );
 	printf("LOG FILE = %s\n",logfilename);
-sleep(5);
+	sleep(5);
 	int majorversion = RCG_VERSION_MAJOR;
 	int subversion1 = RCG_VERSION_MINOR;
 	int subversion2 = RCG_VERSION_SUB;
 	int myreleased = RCG_VERSION_REL;
 	double myversion;
 
-	SETUP;
-	// listLocalRecords(*iocshPpdbbase);
-	myversion = majorversion + 0.1 * subversion1 + 0.01 * subversion2;
-	if(!myreleased) myversion *= -1.0;
-	char rcgversionname[256]; sprintf(rcgversionname, "%s_%s", pref, "RCG_VERSION");	// Set RCG Version EPICS
-	status = dbNameToAddr(rcgversionname,&rcgversion_addr);
-	status = dbPutField(&rcgversion_addr,DBR_DOUBLE,&myversion,1);
-
-	// Create BURT/SDF EPICS channel names
-	char reloadChan[256]; sprintf(reloadChan, "%s_%s", pref, "SDF_RELOAD");		// Request to load new BURT
-	// Set request to load safe.snap on startup
-	status = dbNameToAddr(reloadChan,&reload_addr);
-	status = dbPutField(&reload_addr,DBR_LONG,&sdfReq,1);		// Init request for startup.
-
-	char reloadStat[256]; sprintf(reloadStat, "%s_%s", pref, "SDF_RELOAD_STATUS");	// Status of last reload
-	status = dbNameToAddr(reloadStat,&reloadstat_addr);
-	status = dbPutField(&reloadstat_addr,DBR_LONG,&rdstatus,1);	// Init to zero.
+    auto common_name = [pref](const char* name) -> epics::channel_name {
+        return epics::make_name(pref, name);
+    };
 
-	char sdfFileName[256]; sprintf(sdfFileName, "%s_%s", pref, "SDF_NAME");		// Name of file to load next request
-	// Initialize BURT file to be loaded next request = safe.snap
-	status = dbNameToAddr(sdfFileName,&sdfname_addr);		// Get Address
-	status = dbPutField(&sdfname_addr,DBR_STRING,sdf,1);		// Init to safe.snap
 
-	char loadedFile[256]; sprintf(loadedFile, "%s_%s", pref, "SDF_LOADED");		// Name of file presently loaded
-	status = dbNameToAddr(loadedFile,&loadedfile_addr);		//Get Address
-
-	char edbloadedFile[256]; sprintf(edbloadedFile, "%s_%s", pref, "SDF_LOADED_EDB");	// Name of file presently loaded
-	status = dbNameToAddr(edbloadedFile,&edbloadedaddr);		// Get Address
-
-	char speStat[256]; sprintf(speStat, "%s_%s", pref, "SDF_DIFF_CNT");		// Setpoint diff counter
-	status = dbNameToAddr(speStat,&sperroraddr);			// Get Address
-	status = dbPutField(&sperroraddr,DBR_LONG,&sperror,1);		// Init to zero.
-
-	char spaStat[256]; sprintf(spaStat, "%s_%s", pref, "SDF_ALARM_CNT");		// Number of alarm settings in a BURT file.
-	status = dbNameToAddr(spaStat,&alrmchcountaddr);		// Get Address
-	status = dbPutField(&alrmchcountaddr,DBR_LONG,&alarmCnt,1);	// Init to zero.
+	SETUP();
+#ifndef USE_SYSTEM_TIME
+        timechannel = std::make_unique< epics::DBEntry< epics::PVType::String > >( common_name("TIME_STRING") );
+#endif
 
-	char fcc[256]; sprintf(fcc, "%s_%s", pref, "SDF_FULL_CNT");			// Number of setting channels in EPICS db
-	status = dbNameToAddr(fcc,&fulldbcntaddr);
+  	sprintf(reloadtimechannel,"%s_%s", pref, "SDF_RELOAD_TIME");			// Time of last BURT reload
 
-	char fsc[256]; sprintf(fsc, "%s_%s", pref, "SDF_FILE_SET_CNT");			// Number of settings inBURT file
-	status = dbNameToAddr(fsc,&filesetcntaddr);
+	// listLocalRecords(*iocshPpdbbase);
+	myversion = majorversion + 0.1 * subversion1 + 0.01 * subversion2;
+	if(!myreleased)
+        {
+            myversion *= -1.0;
+        }
+	epics::DBEntry< epics::PVType::Float64 > rcgversion_channel(common_name("RCG_VERSION"), myversion);
+        rcgversion_channel.set( myversion );
 
-	char mcc[256]; sprintf(mcc, "%s_%s", pref, "SDF_UNMON_CNT");			// Number of settings NOT being monitored.
-	status = dbNameToAddr(mcc,&monchancntaddr);
 
-#ifdef CA_SDF
-	char dsc[256]; sprintf(dsc, "%s_%s", pref, "SDF_DISCONNECTED_CNT");
-	status = dbNameToAddr(dsc,&disconnectcountaddr);
+	// Create BURT/SDF EPICS channel names
 
-	char dpdc[256]; sprintf(dpdc, "%s_%s", pref, "SDF_DROPPED_CNT");
-	status = dbNameToAddr(dpdc,&droppedcountaddr);
-#endif
+    epics::DBEntry< epics::PVType::Int32 > reload_channel(common_name("SDF_RELOAD"), sdfReq); // Init request for startup.
+    epics::DBEntry< epics::PVType::Int32 > reload_stat( common_name("SDF_RELOAD_STATUS"), rdstatus); // Init to zero
 
-	char tsrname[256]; sprintf(tsrname, "%s_%s", pref, "SDF_SORT");			// SDF Table sorting request
-	status = dbNameToAddr(tsrname,&tablesortreqaddr);
+    // Initialize BURT file to be loaded next request = safe.snap
+    epics::DBEntry<epics::PVType::String> sdfname_channel(common_name("SDF_NAME"), sdf);
 
-	char wcname[256]; sprintf(wcname, "%s_%s", pref, "SDF_WILDCARD");			// SDF Table sorting request
-	status = dbNameToAddr(wcname,&wcreqaddr);
-	status = dbPutField(&wcreqaddr,DBR_LONG,&zero,1);		// Init to zero.
+    epics::DBEntry<epics::PVType::String> loadedfile_channel(common_name("SDF_LOADED"));
 
-	char cnfname[256]; sprintf(cnfname, "%s_%s", pref, "SDF_DROP_CNT");		// Number of channels not found.
-	status = dbNameToAddr(cnfname,&chnotfoundaddr);
+    epics::DBEntry< epics::PVType::String > edbloaded_channel(common_name("SDF_LOADED_EDB"));	// Name of file presently loaded
 
-	char cniname[256]; sprintf(cniname, "%s_%s", pref, "SDF_UNINIT_CNT");		// Number of channels not initialized.
-	status = dbNameToAddr(cniname,&chnotinitaddr);
+	epics::DBEntry< epics::PVType::Int32 > sperror_channel(common_name("SDF_DIFF_CNT"), sperror); // Setpoint diff counter
+    epics::DBEntry< epics::PVType::Int32 > alrmchcount_channel(common_name("SDF_ALARM_CNT"), alarmCnt); // Number of alarm settings in a BURT file.
+    epics::DBEntry< epics::PVType::Int32 > fulldbcnt_channel(common_name("SDF_FULL_CNT"));// Number of setting channels in EPICS db
 
-	char stename[256]; sprintf(stename, "%s_%s", pref, "SDF_TABLE_ENTRIES");	// Number of entries in an SDF reporting table.
-	status = dbNameToAddr(stename,&sorttableentriesaddr);
+    epics::DBEntry< epics::PVType::Int32 > filesetcnt_channel(common_name("SDF_FILE_SET_CNT")); // Number of settings inBURT file
+    epics::DBEntry< epics::PVType::Int32 > unmonchancnt_channel(common_name("SDF_UNMON_CNT")); // Number of settings NOT being monitored.
 
-	char monflagname[256]; sprintf(monflagname, "%s_%s", pref, "SDF_MON_ALL");	// Request to monitor all channels.
-	status = dbNameToAddr(monflagname,&monflagaddr);		// Get Address.
-	status = dbPutField(&monflagaddr,DBR_LONG,&rdstatus,1);		// Init to zero.
+#ifdef CA_SDF
+    epics::DBEntry< epics::PVType::Int32 > disconnectcount_channel(common_name("SDF_DISCONNECTED_CNT"));
 
-	char savecmdname[256]; sprintf(savecmdname, "%s_%s", pref, "SDF_SAVE_CMD");	// SDF Save command.
-	status = dbNameToAddr(savecmdname,&savecmdaddr);		// Get Address.
-	status = dbPutField(&savecmdaddr,DBR_LONG,&rdstatus,1);		// Init to zero.
+    epics::DBEntry< epics::PVType::Int32 > droppedcount_channel(common_name("SDF_DROPPED_CNT"));
+#endif
 
-	char pagelockname[128]; sprintf(pagelockname, "%s_%s", pref, "SDF_TABLE_LOCK");	// SDF Save command.
-	status = dbNameToAddr(pagelockname,&(pagelockaddr[0]));		// Get Address.
-	status = dbPutField(&(pagelockaddr[0]),DBR_LONG,&freezeTable,1);		// Init to zero.
+    epics::DBEntry< epics::PVType::UInt16 > tablesortreq_channel(common_name("SDF_SORT"));// SDF Table sorting request
+    epics::DBEntry< epics::PVType::Int32 > wcreq_channel(common_name("SDF_WILDCARD"), 0);               // SDF Table sorting request
+    epics::DBEntry< epics::PVType::Int32 > chnotfound_channel(common_name("SDF_DROP_CNT")); // Number of channels not found.
+    epics::DBEntry< epics::PVType::Int32 > chnotinit_channel(common_name("SDF_UNINIT_CNT"));// Number of channels not initialized.
+    epics::DBEntry< epics::PVType::Int32 > sorttableentries_channel(common_name("SDF_TABLE_ENTRIES")); // Number of entries in an SDF reporting table.
+    epics::DBEntry< epics::PVType::Int32 > monflag_channel(common_name("SDF_MON_ALL"), rdstatus); // Request to monitor all channels.
+    epics::DBEntry< epics::PVType::Int32 > savecmd_channel(common_name("SDF_SAVE_CMD"), rdstatus);	// SDF Save command.
+    epics::DBEntry< epics::PVType::Int32 > pagelock_channel(common_name("SDF_TABLE_LOCK"), freezeTable); // SDF Save command.
 
-	char saveasname[256]; sprintf(saveasname, "%s_%s", pref, "SDF_SAVE_AS_NAME");	// SDF Save as file name.
 	// Clear out the save as file name request
-	status = dbNameToAddr(saveasname,&saveasaddr);			// Get Address.
-	status = dbPutField(&saveasaddr,DBR_STRING,"default",1);	// Set as dummy 'default'
-
-	char wcstringname[256]; sprintf(wcstringname, "%s_%s", pref, "SDF_WC_STR");	// SDF Save as file name.
-	status = dbNameToAddr(wcstringname,&wcstringaddr);			// Get Address.
-	status = dbPutField(&wcstringaddr,DBR_STRING,"",1);		// Set as dummy 'default'
-
-	char savetypename[256]; sprintf(savetypename, "%s_%s", pref, "SDF_SAVE_TYPE");	// SDF Save file type.
-	status = dbNameToAddr(savetypename,&savetypeaddr);
-
-	char saveoptsname[256]; sprintf(saveoptsname, "%s_%s", pref, "SDF_SAVE_OPTS");	// SDF Save file options.
-	status = dbNameToAddr(saveoptsname,&saveoptsaddr);
-
-	char savefilename[256]; sprintf(savefilename, "%s_%s", pref, "SDF_SAVE_FILE");	// SDF Name of last file saved.
-	status = dbNameToAddr(savefilename,&savefileaddr);
-	status = dbPutField(&savefileaddr,DBR_STRING,"",1);
+    epics::DBEntry< epics::PVType::String > saveas_channel(common_name("SDF_SAVE_AS_NAME"), epics::channel_name("default")); // Set as dummy 'default'
 
-	char savetimename[256]; sprintf(savetimename, "%s_%s", pref, "SDF_SAVE_TIME");	// SDF Time of last file save.
-	status = dbNameToAddr(savetimename,&savetimeaddr);
-	status = dbPutField(&savetimeaddr,DBR_STRING,"",1);
+	epics::DBEntry< epics::PVType::String > wcstring_channel(common_name("SDF_WC_STR"), "");// SDF Save as file name.
 
-	char moddaqfilemsg[256]; sprintf(moddaqfilemsg, "%s_%s", pref, "MSGDAQ");	// Record to write if DAQ file changed.
-	status = dbNameToAddr(moddaqfilemsg,&daqmsgaddr);
+    epics::DBEntry< epics::PVType::String > savetype_channel( common_name("SDF_SAVE_TYPE"));// SDF Save file type.
+    epics::DBEntry< epics::PVType::String > saveopts_channel( common_name("SDF_SAVE_OPTS"));// SDF Save file options.
 
-	char modcoefffilemsg[128]; sprintf(modcoefffilemsg, "%s_%s", pref, "MSG2");	// Record to write if Coeff file changed.
-	status = dbNameToAddr(modcoefffilemsg,&coeffmsgaddr);
+    epics::DBEntry<epics::PVType::String> savefile_channel(common_name("SDF_SAVE_FILE"), ""); // SDF Name of last file saved.
+    epics::DBEntry<epics::PVType::String> savetime_channel( common_name("SDF_SAVE_TIME"), ""); // SDF Time of last file save.
+    epics::DBEntry< epics::PVType::String > daqmsg_channel(common_name("MSGDAQ"));// Record to write if DAQ file changed.
+    epics::DBEntry< epics::PVType::String > coeffmsg_channel(common_name("MSG2"));	// Record to write if Coeff file changed.
 
+    epics::DBEntry< epics::PVType::String > msgstr_channel(common_name("SDF_MSG_STR"), "");// SDF Time of last file save.
 	char msgstrname[128]; sprintf(msgstrname, "%s_%s", pref, "SDF_MSG_STR");	// SDF Time of last file save.
-	status = dbNameToAddr(msgstrname,&msgstraddr);
-	status = dbPutField(&msgstraddr,DBR_STRING,"",1);
 
-#ifndef USE_SYSTEM_TIME
-	sprintf(timechannel,"%s_%s", pref, "TIME_STRING");
-	// printf("timechannel = %s\n",timechannel);
-#endif
-	sprintf(reloadtimechannel,"%s_%s", pref, "SDF_RELOAD_TIME");			// Time of last BURT reload
-	status = dbNameToAddr(reloadtimechannel,&reloadtimeaddr);
+    epics::DBEntry<epics::PVType::String> reloadtime_channel(common_name("SDF_RELOAD_TIME"), ""); // Time of last BURT reload
 
 	int pageNum = 0;
 	int pageNumSet = 0;
@@ -3329,23 +3294,14 @@ sleep(5);
         status = dbNameToAddr(pagereqname,&pagereqaddr);                // Get Address.
 
 	unsigned int resetNum = 0;
-	char resetOneName[256]; sprintf(resetOneName, "%s_%s", pref, "SDF_RESET_CHAN");	// SDF reset one value.
-	status = dbNameToAddr(resetOneName,&resetoneaddr);
-	status = dbPutField(&resetoneaddr,DBR_LONG,&resetNum,1);
-
-	char selectName[256]; 
-	sprintf(selectName, "%s_%s", pref, "SDF_SELECT_SUM0");	// SDF reset one value.
-	status = dbNameToAddr(selectName,&selectaddr[0]);
-	status = dbPutField(&selectaddr[0],DBR_LONG,&resetNum,1);
-	sprintf(selectName, "%s_%s", pref, "SDF_SELECT_SUM1");	// SDF reset one value.
-	status = dbNameToAddr(selectName,&selectaddr[1]);
-	status = dbPutField(&selectaddr[1],DBR_LONG,&resetNum,1);
-	sprintf(selectName, "%s_%s", pref, "SDF_SELECT_SUM2");	// SDF reset one value.
-	status = dbNameToAddr(selectName,&selectaddr[2]);
-	status = dbPutField(&selectaddr[2],DBR_LONG,&resetNum,1);
-	sprintf(selectName, "%s_%s", pref, "SDF_SELECT_ALL");	// SDF reset one value.
-	status = dbNameToAddr(selectName,&selectaddr[3]);
-	status = dbPutField(&selectaddr[3],DBR_LONG,&selectAll,1);
+    epics::DBEntry< epics::PVType::UInt32 > resetone_channel(common_name("SDF_RESET_CHAN"), resetNum);	// SDF reset one value.
+
+    std::array< epics::DBEntry< epics::PVType::Int32 >, 4> select_channel{
+            epics::DBEntry< epics::PVType::Int32 >(common_name("SDF_SELECT_SUM0"), 0),
+            epics::DBEntry< epics::PVType::Int32 >(common_name("SDF_SELECT_SUM1"), 0),
+            epics::DBEntry< epics::PVType::Int32 >(common_name("SDF_SELECT_SUM2"), 0),
+            epics::DBEntry< epics::PVType::Int32 >(common_name("SDF_SELECT_ALL"), selectAll),
+    };
 
 	dbAddr confirmwordaddr;
 	char confirmwordname[64]; 
@@ -3358,14 +3314,14 @@ sleep(5);
 		char *buffer=0;
 		char fname[]="/monitor.req";
 		int len = strlen(sdfDir)+strlen(fname)+1;
-		buffer = malloc(len);
+		buffer = (char*)malloc(len);
 		if (!buffer) {
 			fprintf(stderr, "Unable to allocate memory to hold the path to monitor.req, aborting!");
 			exit(1);
 		}
 		strcpy(buffer, sdfDir);
 		strcat(buffer, fname);
-		initCAConnections(buffer, pref);
+		initCAConnections(buffer);
 		free(buffer);
 	}
 #else
@@ -3389,10 +3345,10 @@ sleep(5);
     status = checkFileMod( coeffFile, &coeffFileMt, 1 );
     status = checkFileMod( fotonFile, &fotonFileMt, 1 );
 
-	reportSetErrors(pref, 0,setErrTable,0,1);
+	reportSetErrors(pref,setErrTable,0,1);
 
 	sleep(1);       // Need to wait before first restore to allow sequencers time to do their initialization.
-	cdSort = spChecker(monFlag,cdTableList,wcVal,wcstring,1,&status);
+	cdSort = spChecker(monFlag,cdTableList,wcVal,wcstring.c_str(),1,&status);
 
 	// Start Infinite Loop 		*******************************************************************************
 	for(;;) {
@@ -3403,119 +3359,142 @@ sleep(5);
 			// see bug 965
 			ca_poll();
 			syncCAConnections(NULL);
-			status = dbPutField(&disconnectcountaddr,DBR_LONG,&chDisconnectedCount,1);
-			status = dbPutField(&droppedcountaddr,DBR_LONG,&droppedPVCount,1); 
+            disconnectcount_channel.set(chDisconnectedCount);
+            droppedcount_channel.set(droppedPVCount);
 		}
 #endif
 		fivesectimer = (fivesectimer + 1) % 50;		// Increment 5 second timer for triggering CRC checks.
 		// Check for reload request
-		status = dbGetField(&reload_addr,DBR_LONG,&request,&ropts,&nvals,NULL);
+        reload_channel.get(request);
+
 		// Get BURT Read File Name
-		status = dbNameToAddr(sdfFileName,&sdfname_addr);
-		status = dbGetField(&sdfname_addr,DBR_STRING,sdf,&ropts,&nvals,NULL);
+        sdfname_channel.get(sdf);
+		////status = dbNameToAddr(sdfFileName,&sdfname_addr);
+		////status = dbGetField(&sdfname_addr,DBR_STRING,sdf,&ropts,&nvals,NULL);
 
 		//  Create full filename including directory and extension.
-		sprintf(sdfile, "%s%s%s", sdfDir, sdf,".snap");
-		sprintf(sdalarmfile, "%s%s%s", sdfDir, sdf,"_alarms.snap");
+        sdfile.printf("%s%s%s", sdfDir, sdf.c_str(), ".snap");
+        sdalarmfile.printf("%s%s%s", sdfDir, sdf.c_str(), "_alarms.snap");
+
 		// Check if file name != to one presently loaded
-		if(strcmp(sdf,loadedSdf) != 0) burtstatus |= 1;
-		else burtstatus &= ~(1);
-		if(burtstatus == 0)
-				status = dbPutField(&msgstraddr,DBR_STRING," ",1);
-		if(burtstatus == 1)
-				status = dbPutField(&msgstraddr,DBR_STRING,"New SDF File Pending",1);
-		if(burtstatus & 2)
-				status = dbPutField(&msgstraddr,DBR_STRING,"Read Error: Errant line(s) in file",1);
-		if(burtstatus & 4)
-				status = dbPutField(&msgstraddr,DBR_STRING,"Read Error: File Not Found",1);
+
+        if (sdf != loadedSdf) {
+            burtstatus |= 1;
+        }
+        else
+        {
+            burtstatus &= ~(1);
+        }
+		//if(strcmp(sdf,loadedSdf) != 0) burtstatus |= 1;
+		//else burtstatus &= ~(1);
+
+		if(burtstatus == 0) {
+            msgstr_channel.set(" ");
+        }
+		if(burtstatus == 1) {
+            msgstr_channel.set("New SDF File Pending");
+        }
+		if(burtstatus & 2) {
+            msgstr_channel.set("Read Error: Errant line(s) in file");
+        }
+		if(burtstatus & 4) {
+            msgstr_channel.set("Read Error: File Not Found");
+        }
 		if(request != 0) {		// If there is a read file request, then:
-			status = dbPutField(&reload_addr,DBR_LONG,&ropts,1);	// Clear the read request.
+			reload_channel.set(ropts);
 			reqValid = 1;
 			if(reqValid) {
-				rdstatus = readConfig(pref,sdfile,request,sdalarmfile);
+				rdstatus = readConfig(pref,sdfile.c_str(),request,sdalarmfile.c_str());
 				resyncFMArrays(filterMasks,fmMaskChan);
 				if (rdstatus) burtstatus |= rdstatus;
 				else burtstatus &= ~(6);
 				if(burtstatus < 4) {
 					switch (request){
 						case SDF_LOAD_DB_ONLY:
-							strcpy(loadedSdf,sdf); 
-							status = dbPutField(&edbloadedaddr,DBR_STRING,loadedSdf,1);
+                            loadedSdf = sdf;
+                            edbloaded_channel.set(loadedSdf);
 							break;
 						case SDF_RESET:
 							break;
 						case SDF_LOAD_PARTIAL:
-							strcpy(loadedSdf,sdf); 
-							status = dbPutField(&loadedfile_addr,DBR_STRING,loadedSdf,1);
-							status = dbPutField(&edbloadedaddr,DBR_STRING,loadedSdf,1);
+							loadedSdf = sdf;
+                            loadedfile_channel.set(loadedSdf);
+                            edbloaded_channel.set(loadedSdf);
 							break;
 						case SDF_READ_ONLY:
-							strcpy(loadedSdf,sdf); 
-							status = dbPutField(&loadedfile_addr,DBR_STRING,loadedSdf,1);
+							loadedSdf = sdf;
+                            loadedfile_channel.set(loadedSdf);
 							break;
 						default:
 							logFileEntry("Invalid READ Request");
 							reqValid = 0;
 							break;
 					}
-					status = dbPutField(&reloadstat_addr,DBR_LONG,&rdstatus,1);
+                    reload_stat.set(rdstatus);
 					// Get the file CRC for later checking if file changed.
-					sprintf(sdffileloaded, "%s%s%s", sdfDir, loadedSdf,".snap");
-					sdfFileCrc = checkFileCrc(sdffileloaded);
+					sdffileloaded.printf("%s%s%s", sdfDir, loadedSdf.c_str(), ".snap");
+					sdfFileCrc = checkFileCrc(sdffileloaded.c_str());
                     // Get the file mod time
-                    status = checkFileMod( sdffileloaded, &sdfFileMt, 1 );
+                    status = checkFileMod( sdffileloaded.c_str(), &sdfFileMt, 1 );
 					// Calculate and report the number of settings in the BURT file.
 					setChans = chNumP - alarmCnt;
-					status = dbPutField(&filesetcntaddr,DBR_LONG,&setChans,1);
+                    filesetcnt_channel.set(setChans);
 					// Report number of settings in the main table.
 					setChans = chNum - fmNum;
-					status = dbPutField(&fulldbcntaddr,DBR_LONG,&setChans,1);
+                    fulldbcnt_channel.set(setChans);
 					// Sort channels for data reporting via the MEDM table.
-					getEpicsSettings(chNum,NULL);
-					noMon = createSortTableEntries(chNum,0,"",&noInit,NULL);
+					getEpicsSettings();
+					noMon = createSortTableEntries(chNum,0,"",&noInit,nullptr);
 					// Calculate and report number of channels NOT being monitored.
-					status = dbPutField(&monchancntaddr,DBR_LONG,&chNotMon,1);
-					status = dbPutField(&alrmchcountaddr,DBR_LONG,&alarmCnt,1);
+					unmonchancnt_channel.set(chNotMon);
+					alrmchcount_channel.set(alarmCnt);
 					// Report number of channels in BURT file that are not in local database.
-					status = dbPutField(&chnotfoundaddr,DBR_LONG,&chNotFound,1);
+					chnotfound_channel.set(chNotFound);
 					// Report number of channels that have not been initialized via a BURT read.
-					status = dbPutField(&chnotinitaddr,DBR_LONG,&chNotInit,1);
+					chnotinit_channel.set(chNotInit);
 					// Write out local monitoring table as snap file.
-					status = writeTable2File(sdfDir,bufile,SDF_WITH_INIT_FLAG,cdTable);
+					writeTable2File(sdfDir,bufile.c_str(),SDF_WITH_INIT_FLAG,cdTable);
 				}
 			}
 		}
-		status = dbPutField(&reloadstat_addr,DBR_LONG,&burtstatus,1);
+        reload_stat.set(burtstatus);
+
 		// sleep(1);
 		// Check for SAVE requests
-		status = dbGetField(&savecmdaddr,DBR_LONG,&sdfSaveReq,&ropts,&nvals,NULL);
+        savecmd_channel.get(sdfSaveReq);
 		if(sdfSaveReq)	// If there is a SAVE file request, then:
 		{
 			// Clear the save file request
-			status = dbPutField(&savecmdaddr,DBR_LONG,&ropts,1);
+            savecmd_channel.set(ropts);
 			// Determine file type
-			status = dbGetField(&savetypeaddr,DBR_STRING,saveTypeString,&ropts,&nvals,NULL);
+            savetype_channel.get(saveTypeString);
 			saveType = 0;
-                        if(strcmp(saveTypeString,"TABLE TO FILE") == 0) saveType = SAVE_TABLE_AS_SDF;
-                        if(strcmp(saveTypeString,"EPICS DB TO FILE") == 0) saveType = SAVE_EPICS_AS_SDF;
+            if(saveTypeString == "TABLE TO FILE") {
+                saveType = SAVE_TABLE_AS_SDF;
+            }
+            if(saveTypeString == "EPICS DB TO FILE") {
+                saveType = SAVE_EPICS_AS_SDF;
+            }
 			// Determine file options
                         saveOpts = 0;
-			status = dbGetField(&saveoptsaddr,DBR_STRING,saveOptsString,&ropts,&nvals,NULL);
-                        if(strcmp(saveOptsString,"TIME NOW") == 0) saveOpts = SAVE_TIME_NOW;
-                        if(strcmp(saveOptsString,"OVERWRITE") == 0) saveOpts = SAVE_OVERWRITE;
-                        if(strcmp(saveOptsString,"SAVE AS") == 0) saveOpts = SAVE_AS;
+			saveopts_channel.get(saveOptsString);
+            if(saveOptsString == "TIME NOW") saveOpts = SAVE_TIME_NOW;
+            if(saveOptsString == "OVERWRITE") saveOpts = SAVE_OVERWRITE;
+            if(saveOptsString == "SAVE AS") saveOpts = SAVE_AS;
 			// Determine if request is valid.
 			if(saveType && saveOpts)
 			{
 				// Get saveas filename
-				status = dbGetField(&saveasaddr,DBR_STRING,saveasfilename,&ropts,&nvals,NULL);
-				if(saveOpts == SAVE_OVERWRITE) 
-					savesdffile(saveType,SAVE_TIME_NOW,sdfDir,modelname,sdfile,saveasfilename,loadedSdf,savefileaddr,savetimeaddr,reloadtimeaddr);
+                saveas_channel.get(saveasfilename);
+				if(saveOpts == SAVE_OVERWRITE) {
+                    savesdffile(saveType, SAVE_TIME_NOW, sdfDir, modelname, sdfile.c_str(), saveasfilename.c_str(), loadedSdf.c_str(),
+                                savefile_channel, savetime_channel, reloadtime_channel);
+                }
 				// Save the file
-				savesdffile(saveType,saveOpts,sdfDir,modelname,sdfile,saveasfilename,loadedSdf,savefileaddr,savetimeaddr,reloadtimeaddr);
+				savesdffile(saveType,saveOpts,sdfDir,modelname,sdfile.c_str(),saveasfilename.c_str(),loadedSdf.c_str(),savefile_channel,savetime_channel,reloadtime_channel);
 				if(saveOpts == SAVE_OVERWRITE)  {
-						sdfFileCrc = checkFileCrc(sdffileloaded);
-                        status = checkFileMod( sdffileloaded, &sdfFileMt, 1 );
+						sdfFileCrc = checkFileCrc(sdffileloaded.c_str());
+                        status = checkFileMod( sdffileloaded.c_str(), &sdfFileMt, 1 );
                 }
 			} else {
 				logFileEntry("Invalid SAVE File Request");
@@ -3523,20 +3502,20 @@ sleep(5);
 		}
 		// Check present settings vs BURT settings and report diffs.
 		// Check if MON ALL CHANNELS is set
-		status = dbGetField(&monflagaddr,DBR_LONG,&monFlag,&ropts,&nvals,NULL);
-		status = dbGetField(&wcstringaddr,DBR_STRING,wcstring,&ropts,&nvals,NULL);
-		status = dbGetField(&wcstringaddr,DBR_STRING,saveasfilename,&ropts,&nvals,NULL);
+        monflag_channel.get(monFlag);
+		wcstring_channel.get(wcstring);
+		saveasfilename = wcstring;
 		// Call the diff checking function.
 		if(!freezeTable)
-			sperror = spChecker(monFlag,setErrTable,wcVal,wcstring,0,&diffCnt);
+			sperror = spChecker(monFlag,setErrTable,wcVal,wcstring.c_str(),0,&diffCnt);
 		// Report number of diffs found.
-		status = dbPutField(&sperroraddr,DBR_LONG,&diffCnt,1);
+        sperror_channel.set(diffCnt);
 		// Table sorting and presentation
-		status = dbGetField(&tablesortreqaddr,DBR_USHORT,&tsrVal,&ropts,&nvals,NULL);
-		status = dbGetField(&wcreqaddr,DBR_USHORT,&wcVal,&ropts,&nvals,NULL);
+        tablesortreq_channel.set(tsrVal);
+        wcreq_channel.set(wcVal);
 		status = dbGetField(&pagereqaddr,DBR_LONG,&pageNumSet,&ropts,&nvals,NULL);
 		status = dbGetField(&confirmwordaddr,DBR_LONG,&confirmVal,&ropts,&nvals,NULL);
-		status = dbGetField(&selectaddr[3],DBR_LONG,&selectAll,&ropts,&nvals,NULL);
+		select_channel[3].get(selectAll);
 		if(pageNumSet != 0) {
 			pageNum += pageNumSet;
 			if(pageNum < 0) pageNum = 0;
@@ -3547,237 +3526,232 @@ sleep(5);
 			case SDF_TABLE_DIFFS:
 				// Need to clear selections when moving between tables.
 				if(lastTable !=  SDF_TABLE_DIFFS) {
-					clearTableSelections(sperror,setErrTable, selectCounter);
+					clearTableSelections(setErrTable, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 				}
-				pageDisp = reportSetErrors(pref, sperror,setErrTable,pageNum,1);
-				currentTable = setErrTable;
-				currentTableCnt = sperror;
-				status = dbPutField(&sorttableentriesaddr,DBR_LONG,&sperror,1);
-				status = dbGetField(&resetoneaddr,DBR_LONG,&resetNum,&ropts,&nvals,NULL);
+				pageDisp = reportSetErrors(pref, setErrTable,pageNum,1);
+				currentTable = make_range(setErrTable);
+
+                sorttableentries_channel.set(sperror);
+                resetone_channel.get(resetNum);
 				if(selectAll) {
-					setAllTableSelections(sperror,setErrTable, selectCounter,selectAll);
+					setAllTableSelections(make_range(setErrTable), selectCounter,selectAll);
 				}
 				if(resetNum) {
-					decodeChangeSelect(resetNum, pageDisp, sperror, setErrTable,selectCounter, NULL);
+					decodeChangeSelect(resetNum, pageDisp, make_range(setErrTable),selectCounter, NULL);
 				}
 				if(confirmVal) {
-					if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(sperror, setErrTable);
+					if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(setErrTable);
 					if((selectCounter[1] || selectCounter[2]) && (confirmVal & 2)) {
 						// Save present table as timenow.
-						status = dbGetField(&loadedfile_addr,DBR_STRING,backupName,&ropts,&nvals,NULL);
+                        loadedfile_channel.get(backupName);
 						// printf("BACKING UP: %s\n",backupName);
-						savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile,saveasfilename,backupName,
-							    savefileaddr,savetimeaddr,reloadtimeaddr);
+						savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile.c_str(),saveasfilename.c_str(),
+                                    backupName.c_str(),savefile_channel,savetime_channel,reloadtime_channel);
 						// Overwrite the table with new values
-						status = modifyTable(sperror,setErrTable);
+						status = modifyTable(make_range(setErrTable));
 						// Overwrite file
-						savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile,saveasfilename,
-							    backupName,savefileaddr,savetimeaddr,reloadtimeaddr);
-						sdfFileCrc = checkFileCrc(sdffileloaded);
-                        status = checkFileMod( sdffileloaded, &sdfFileMt, 1 );
-						status = writeTable2File(sdfDir,bufile,SDF_WITH_INIT_FLAG,cdTable);
+						savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile.c_str(),saveasfilename.c_str(),
+							    backupName.c_str(),savefile_channel,savetime_channel,reloadtime_channel);
+						sdfFileCrc = checkFileCrc(sdffileloaded.c_str());
+                        status = checkFileMod( sdffileloaded.c_str(), &sdfFileMt, 1 );
+						writeTable2File(sdfDir,bufile.c_str(),SDF_WITH_INIT_FLAG,cdTable);
 					}
-					clearTableSelections(sperror,setErrTable, selectCounter);
+					clearTableSelections(setErrTable, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 					status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1);
-					noMon = createSortTableEntries(chNum,wcVal,wcstring,&noInit,NULL);
-					status = dbPutField(&monchancntaddr,DBR_LONG,&chNotMon,1);
+					noMon = createSortTableEntries(chNum,wcVal,wcstring.c_str(),&noInit,NULL);
+                    unmonchancnt_channel.set(chNotMon);
 				}
 				lastTable = SDF_TABLE_DIFFS;
 				break;
 			case SDF_TABLE_NOT_FOUND:
 				// Need to clear selections when moving between tables.
 				if(lastTable != SDF_TABLE_NOT_FOUND) {
-					clearTableSelections(sperror,setErrTable, selectCounter);
+					clearTableSelections(setErrTable, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 				}
-				pageDisp = reportSetErrors(pref, chNotFound,unknownChans,pageNum,1);
-				currentTable = unknownChans;
-				currentTableCnt = chNotFound;
-				status = dbPutField(&sorttableentriesaddr,DBR_LONG,&chNotFound,1);
+				pageDisp = reportSetErrors(pref, unknownChans,pageNum,1);
+				currentTable = make_range(unknownChans);
+
+                sorttableentries_channel.set(chNotFound);
 				/*if (resetNum > 200) {
-					decodeChangeSelect(resetNum, pageDisp, chNotFound, unknownChans,selectCounter, NULL);
+					decodeChangeSelect(resetNum, pageDisp, make_range(unknownChans),selectCounter, NULL);
 				}*/
 				lastTable =  SDF_TABLE_NOT_FOUND;
 				break;
 			case SDF_TABLE_NOT_INIT:
 				if(lastTable != SDF_TABLE_NOT_INIT) {
-					clearTableSelections(sperror,setErrTable, selectCounter);
+					clearTableSelections(setErrTable, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 				}
 				if (!freezeTable)
-					getEpicsSettings(chNum,NULL);
-				noMon = createSortTableEntries(chNum,wcVal,wcstring,&noInit,NULL);
-				pageDisp = reportSetErrors(pref, noInit, uninitChans,pageNum,1);
-				currentTable = uninitChans;
-				currentTableCnt = noInit;
-				status = dbGetField(&resetoneaddr,DBR_LONG,&resetNum,&ropts,&nvals,NULL);
+					getEpicsSettings();
+				noMon = createSortTableEntries(chNum,wcVal,wcstring.c_str(),&noInit,NULL);
+				pageDisp = reportSetErrors(pref, uninitChans,pageNum,1);
+				currentTable = make_range(uninitChans);
+                resetone_channel.get(resetNum);
 				if(selectAll == 2 || selectAll == 3) {
-					setAllTableSelections(noInit,uninitChans,selectCounter,selectAll);
+					setAllTableSelections(make_range(uninitChans),selectCounter,selectAll);
 					if (selectAll == 3)
-						setAllTableSelections(noInit,uninitChans,selectCounter,2);
+						setAllTableSelections(make_range(uninitChans),selectCounter,2);
 				}
 				if(resetNum > 100) {
-					decodeChangeSelect(resetNum, pageDisp, noInit, uninitChans,selectCounter, changeSelectCB_uninit);
+					decodeChangeSelect(resetNum, pageDisp, make_range(uninitChans),selectCounter, changeSelectCB_uninit);
 				}
 				if(confirmVal) {
-					if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(noInit, uninitChans);
+					if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(uninitChans);
 					if(selectCounter[1] && (confirmVal & 2)) {
 						// Save present table as timenow.
-						status = dbGetField(&loadedfile_addr,DBR_STRING,backupName,&ropts,&nvals,NULL);
+						loadedfile_channel.get(backupName);
 						// printf("BACKING UP: %s\n",backupName);
-						savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile,saveasfilename,backupName,
-							    savefileaddr,savetimeaddr,reloadtimeaddr);
+						savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile.c_str(),saveasfilename.c_str(),backupName.c_str(),
+							    savefile_channel,savetime_channel,reloadtime_channel);
 						// Overwrite the table with new values
-						status = modifyTable(noInit,uninitChans);
+						status = modifyTable(make_range(uninitChans));
 						// Overwrite file
-						savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile,saveasfilename,
-							    backupName,savefileaddr,savetimeaddr,reloadtimeaddr);
-						sdfFileCrc = checkFileCrc(sdffileloaded);
-                        status = checkFileMod( sdffileloaded, &sdfFileMt, 1 );
-						status = writeTable2File(sdfDir,bufile,SDF_WITH_INIT_FLAG,cdTable);
+						savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile.c_str(),saveasfilename.c_str(),
+							    backupName.c_str(),savefile_channel,savetime_channel,reloadtime_channel);
+						sdfFileCrc = checkFileCrc(sdffileloaded.c_str());
+                        status = checkFileMod( sdffileloaded.c_str(), &sdfFileMt, 1 );
+						writeTable2File(sdfDir,bufile.c_str(),SDF_WITH_INIT_FLAG,cdTable);
 					}
-					clearTableSelections(chNotInit,uninitChans, selectCounter);
+					clearTableSelections(uninitChans, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 					status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1);
 				}
-				status = dbPutField(&sorttableentriesaddr,DBR_LONG,&noInit,1);
-				status = dbPutField(&chnotinitaddr,DBR_LONG,&chNotInit,1);
+                sorttableentries_channel.set(noInit);
+				chnotinit_channel.set(chNotInit);
 				lastTable = SDF_TABLE_NOT_INIT;
 				break;
 			case SDF_TABLE_NOT_MONITORED:
 				D("In not mon\n");
 				if(lastTable != SDF_TABLE_NOT_MONITORED) {
-					clearTableSelections(noMon,unMonChans, selectCounter);
+					clearTableSelections(unMonChans, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 					status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1);
 				}
 				if (!freezeTable)
-					getEpicsSettings(chNum,NULL); //timeTable);
-				noMon = createSortTableEntries(chNum,wcVal,wcstring,&noInit,NULL);//timeTable);
-				status = dbPutField(&monchancntaddr,DBR_LONG,&chNotMon,1);
-				pageDisp = reportSetErrors(pref, noMon, unMonChans,pageNum,1);
-				currentTable = unMonChans;
-				currentTableCnt = noMon;
-				status = dbGetField(&resetoneaddr,DBR_LONG,&resetNum,&ropts,&nvals,NULL);
+					getEpicsSettings(); //timeTable);
+				noMon = createSortTableEntries(chNum,wcVal,wcstring.c_str(),&noInit,NULL);//timeTable);
+				unmonchancnt_channel.set(chNotMon);
+				pageDisp = reportSetErrors(pref, unMonChans,pageNum,1);
+				currentTable = make_range(unMonChans);
+                resetone_channel.get(resetNum);
 				if(selectAll) {
-					setAllTableSelections(noMon,unMonChans,selectCounter,selectAll);
+					setAllTableSelections(make_range(unMonChans),selectCounter,selectAll);
 				}
 				if(resetNum) {
-					decodeChangeSelect(resetNum, pageDisp, noMon, unMonChans,selectCounter, NULL);
+					decodeChangeSelect(resetNum, pageDisp, make_range(unMonChans),selectCounter, NULL);
 				}
 				if(confirmVal) {
-					if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(noMon, unMonChans);
+					if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(unMonChans);
 					if((selectCounter[1] || selectCounter[2]) && (confirmVal & 2)) {
 						// Save present table as timenow.
-						status = dbGetField(&loadedfile_addr,DBR_STRING,backupName,&ropts,&nvals,NULL);
+                        loadedfile_channel.get(backupName);
 						// printf("BACKING UP: %s\n",backupName);
-						savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile,saveasfilename,backupName,
-							    savefileaddr,savetimeaddr,reloadtimeaddr);
+						savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile.c_str(),saveasfilename.c_str(),backupName.c_str(),
+							    savefile_channel,savetime_channel,reloadtime_channel);
 						// Overwrite the table with new values
-						status = modifyTable(noMon,unMonChans);
+						status = modifyTable(make_range(unMonChans));
 						// Overwrite file
-						savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile,saveasfilename,
-							    backupName,savefileaddr,savetimeaddr,reloadtimeaddr);
-						sdfFileCrc = checkFileCrc(sdffileloaded);
-                        status = checkFileMod( sdffileloaded, &sdfFileMt, 1 );
-						status = writeTable2File(sdfDir,bufile,SDF_WITH_INIT_FLAG,cdTable);
+						savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile.c_str(),saveasfilename.c_str(),
+							    backupName.c_str(),savefile_channel,savetime_channel,reloadtime_channel);
+						sdfFileCrc = checkFileCrc(sdffileloaded.c_str());
+                        status = checkFileMod( sdffileloaded.c_str(), &sdfFileMt, 1 );
+						writeTable2File(sdfDir,bufile.c_str(),SDF_WITH_INIT_FLAG,cdTable);
 					}
 					// noMon = createSortTableEntries(chNum,wcVal,wcstring);
-					clearTableSelections(noMon,unMonChans, selectCounter);
+					clearTableSelections(unMonChans, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 					status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1);
 					// Calculate and report number of channels NOT being monitored.
 				}
-				status = dbPutField(&sorttableentriesaddr,DBR_LONG,&noMon,1);
+                sorttableentries_channel.set(noMon);
 				lastTable = SDF_TABLE_NOT_MONITORED;
 				break;
 			case SDF_TABLE_FULL:
 				if(lastTable != SDF_TABLE_FULL) {
-					clearTableSelections(cdSort,cdTableList, selectCounter);
+					clearTableSelections(cdTableList, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 				}
 				if (!freezeTable)
-					cdSort = spChecker(monFlag,cdTableList,wcVal,wcstring,1,&status);
-				pageDisp = reportSetErrors(pref, cdSort, cdTableList,pageNum,1);
-				currentTable = cdTableList;
-				currentTableCnt = cdSort;
-				status = dbGetField(&resetoneaddr,DBR_LONG,&resetNum,&ropts,&nvals,NULL);
+					cdSort = spChecker(monFlag,cdTableList,wcVal,wcstring.c_str(),1,&status);
+				pageDisp = reportSetErrors(pref, cdTableList,pageNum,1);
+				currentTable = make_range(cdTableList);
+                resetone_channel.get(resetNum);
 				if(selectAll == 3) {
-					setAllTableSelections(cdSort,cdTableList,selectCounter,selectAll);
+					setAllTableSelections(make_range(cdTableList),selectCounter,selectAll);
 				}
 				if(resetNum) {
-					decodeChangeSelect(resetNum, pageDisp, cdSort, cdTableList,selectCounter, NULL);
+					decodeChangeSelect(resetNum, pageDisp, make_range(cdTableList),selectCounter, NULL);
 				}
 				if(confirmVal) {
-					if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(cdSort, cdTableList);
+					if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(cdTableList);
 					if((selectCounter[1] || selectCounter[2]) && (confirmVal & 2)) {
 						// Save present table as timenow.
-						status = dbGetField(&loadedfile_addr,DBR_STRING,backupName,&ropts,&nvals,NULL);
+                        loadedfile_channel.get(backupName);
 						// printf("BACKING UP: %s\n",backupName);
-						savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile,saveasfilename,
-							    backupName,savefileaddr,savetimeaddr,reloadtimeaddr);
+						savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile.c_str(),saveasfilename.c_str(),
+							    backupName.c_str(),savefile_channel,savetime_channel,reloadtime_channel);
 						// Overwrite the table with new values
-						status = modifyTable(cdSort,cdTableList);
+						status = modifyTable(make_range(cdTableList));
 						// Overwrite file
-						savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile,saveasfilename,
-							    backupName,savefileaddr,savetimeaddr,reloadtimeaddr);
-						sdfFileCrc = checkFileCrc(sdffileloaded);
-                        status = checkFileMod( sdffileloaded, &sdfFileMt, 1 );
-						status = writeTable2File(sdfDir,bufile,SDF_WITH_INIT_FLAG,cdTable);
+						savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile.c_str(),saveasfilename.c_str(),
+							    backupName.c_str(),savefile_channel,savetime_channel,reloadtime_channel);
+						sdfFileCrc = checkFileCrc(sdffileloaded.c_str());
+                        status = checkFileMod( sdffileloaded.c_str(), &sdfFileMt, 1 );
+						writeTable2File(sdfDir,bufile.c_str(),SDF_WITH_INIT_FLAG,cdTable);
 					}
-					clearTableSelections(cdSort,cdTableList, selectCounter);
+					clearTableSelections(cdTableList, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 					status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1);
-					noMon = createSortTableEntries(chNum,wcVal,wcstring,&noInit,NULL);
+					noMon = createSortTableEntries(chNum,wcVal,wcstring.c_str(),&noInit,NULL);
 					// Calculate and report number of channels NOT being monitored.
-					status = dbPutField(&monchancntaddr,DBR_LONG,&chNotMon,1);
+					unmonchancnt_channel.set(chNotMon);
 				}
-				status = dbPutField(&sorttableentriesaddr,DBR_LONG,&cdSort,1);
+                sorttableentries_channel.set(cdSort);
 				lastTable = SDF_TABLE_FULL;
 				break;
 #ifdef CA_SDF
 			case SDF_TABLE_DISCONNECTED:
 				if(lastTable != SDF_TABLE_DISCONNECTED) {
-					clearTableSelections(cdSort,cdTableList, selectCounter);
+					clearTableSelections(cdTableList, selectCounter);
 					resyncFMArrays(filterMasks,fmMaskChan);
 					confirmVal = 0;
 				}
-				noMon = createSortTableEntries(chNum,wcVal,wcstring,&noInit,NULL);
-				pageDisp =  reportSetErrors(pref, chDisconnected, disconnectChans, pageNum,0);
+				noMon = createSortTableEntries(chNum,wcVal,wcstring.c_str(),&noInit,NULL);
+				pageDisp =  reportSetErrors(pref, disconnectChans, pageNum,0);
 				chDisconnectedCount = chDisconnected;
-				currentTable = disconnectChans;
-				currentTableCnt = chDisconnected;
-				status = dbPutField(&sorttableentriesaddr,DBR_LONG,&chDisconnected, 1);
+				currentTable = make_range(disconnectChans);
+                sorttableentries_channel.set(chDisconnected);
 				if (resetNum > 200) {
-					decodeChangeSelect(resetNum, pageDisp, chDisconnected, disconnectChans, selectCounter, NULL);
+					decodeChangeSelect(resetNum, pageDisp, make_range(disconnectChans), selectCounter, NULL);
 				}
 				break;
 #endif
 			default:
-				pageDisp = reportSetErrors(pref, sperror,setErrTable,pageNum,1);
-				status = dbPutField(&sorttableentriesaddr,DBR_LONG,&sperror,1);
-				currentTable = setErrTable;
-				currentTableCnt = sperror;
+				pageDisp = reportSetErrors(pref, setErrTable,pageNum,1);
+				sorttableentries_channel.set(sperror);
+				currentTable = make_range(setErrTable);
 				break;
 		}
 		if (selectAll) {
 			selectAll = 0;
-			status = dbPutField(&selectaddr[3],DBR_LONG,&selectAll,1);
+            select_channel[3].set(selectAll);
 		}
 		if (resetNum) {
 			resetNum = 0;
-			status = dbPutField(&resetoneaddr,DBR_LONG,&resetNum,1);
+            resetone_channel.set(resetNum);
 		}
 		if(pageDisp != pageNum) {
 			pageNum = pageDisp;
@@ -3785,11 +3759,11 @@ sleep(5);
 		freezeTable = 0;
 		for(ii=0;ii<3;ii++) {
 			freezeTable += selectCounter[ii];
-			status = dbPutField(&selectaddr[ii],DBR_LONG,&selectCounter[ii],1);
+            select_channel[ii].set(selectCounter[ii]);
 		}
-		status = dbPutField(&(pagelockaddr[0]),DBR_LONG,&freezeTable,1);
+        pagelock_channel.set(freezeTable);
 
-		processFMChanCommands(filterMasks, fmMaskChan,fmMaskChanCtrl,selectCounter, currentTableCnt, currentTable);
+		processFMChanCommands(filterMasks, fmMaskChan,fmMaskChanCtrl,selectCounter, currentTable);
 
 		// Check file CRCs every 5 seconds.
 		// DAQ and COEFF file checking was moved from skeleton.st to here RCG V2.9.
@@ -3801,7 +3775,7 @@ sleep(5);
 			status = checkFileCrc(daqFile);
 			if(status != daqFileCrc) {
 				daqFileCrc = status;
-				status = dbPutField(&daqmsgaddr,DBR_STRING,modfilemsg,1);
+                daqmsg_channel.set(modfilemsg);
 				logFileEntry("Detected Change to DAQ Config file.");
 			}
             }
@@ -3813,9 +3787,9 @@ sleep(5);
 			coeffFileCrc = checkFileCrc(coeffFile);
 			fotonFileCrc = checkFileCrc(fotonFile);
 			if(fotonFileCrc != coeffFileCrc) {
-				status = dbPutField(&coeffmsgaddr,DBR_STRING,modfilemsg,1);
+                coeffmsg_channel.set(modfilemsg);
 			} else {
-				status = dbPutField(&coeffmsgaddr,DBR_STRING,"",1);
+                coeffmsg_channel.set("");
 			}
 			if(fotonFileCrc != prevFotonFileCrc || prevCoeffFileCrc != coeffFileCrc) {
 				sprintf(myDiffCmd,"%s %s %s %s %s","diff",fotonFile,coeffFile," > ",fotonDiffFile);
@@ -3825,19 +3799,18 @@ sleep(5);
 			}
             }
             // Check SDF file modified
-            fm_flag = checkFileMod( sdffileloaded, &sdfFileMt, 0 );
+            fm_flag = checkFileMod( sdffileloaded.c_str(), &sdfFileMt, 0 );
             if ( fm_flag )
             {
-			status = checkFileCrc(sdffileloaded);
+			status = checkFileCrc(sdffileloaded.c_str());
 			if(status == -1) {
 				sdfFileCrc = status;
 				logFileEntry("SDF file not found.");
-				dbPutField(&reloadtimeaddr,DBR_STRING,"File Not Found",1);
-			} 
+			}
 			if(status != sdfFileCrc) {
 				sdfFileCrc = status;
 				logFileEntry("Detected Change to SDF file.");
-				dbPutField(&reloadtimeaddr,DBR_STRING,modfilemsg,1);
+				reloadtime_channel.set(modfilemsg);
 			}
             }
 		}
@@ -3846,6 +3819,6 @@ sleep(5);
 	sleep(0xfffffff);
     } else
     	iocsh(NULL);
-    CLEANUP;
+    CLEANUP();
     return(0);
 }
diff --git a/src/epics/seq/sdf_file_loaded.c b/src/epics/seq/sdf_file_loaded.c
new file mode 100644
index 0000000000000000000000000000000000000000..e8fec78f8d7187e86170f76aedaf7809631711db
--- /dev/null
+++ b/src/epics/seq/sdf_file_loaded.c
@@ -0,0 +1,12 @@
+
+static int sdf_file_loaded=0;
+
+int get_sdf_file_loaded()
+{
+    return sdf_file_loaded;
+}
+
+extern void set_sdf_file_loaded(int sfl)
+{
+    sdf_file_loaded = sfl;
+}
\ No newline at end of file
diff --git a/src/epics/seq/sdf_monitor.c b/src/epics/seq/sdf_monitor.c
index 13d3cfe38c2635b9a50ee99c6d883b86ea95749f..cab7c70b588da56043a098d4ebe373d13825ea39 100644
--- a/src/epics/seq/sdf_monitor.c
+++ b/src/epics/seq/sdf_monitor.c
@@ -44,6 +44,7 @@ of this distribution.
 #include "cadef.h"
 #include "fb.h"
 #include "../../drv/gpstime/gpstime.h"
+#include "util/user/check_file_crc.h"
 
 #define GSDF_MAX_CHANS	30000
 // Gloabl variables		****************************************************************************************
@@ -57,7 +58,6 @@ char statelogfilename[128];
 unsigned char naughtyList[GSDF_MAX_CHANS][64];
 
 // Function prototypes		****************************************************************************************
-int checkFileCrc(char *);
 void getSdfTime(char *);
 void logFileEntry(char *);
 
@@ -444,29 +444,6 @@ void gsdfInitialize(char *shmem_fname)
 }
 
 
-
-/// Common routine to check file CRC.
-///	@param[in] *fName	Name of file to check.
-///	@return File CRC or -1 if file not found.
-int checkFileCrc(char *fName)
-{
-char buffer[256];
-FILE *pipePtr;
-struct stat statBuf;
-long chkSum = -99999;
-      	strcpy(buffer, "cksum "); 
-      	strcat(buffer, fName); 
-      	if (!stat(fName, &statBuf) ) { 
-         	if ((pipePtr = popen(buffer, "r")) != NULL) {
-            	fgets(buffer, 256, pipePtr);
-            	pclose(pipePtr); 
-            	sscanf(buffer, "%ld", &chkSum);
-         	} 
-		return(chkSum);
-    	}    
-	return(-1);
-}
-
 /// Routine for reading GPS time from model EPICS record.
 ///	@param[out] timestring 	Pointer to char string in which GPS time is to be written.
 void getSdfTime(char *timestring)
diff --git a/src/epics/seq/simple_range.hh b/src/epics/seq/simple_range.hh
new file mode 100644
index 0000000000000000000000000000000000000000..36cbb0aefb8bc0e0af4e61b4d3db54a1d575fec6
--- /dev/null
+++ b/src/epics/seq/simple_range.hh
@@ -0,0 +1,78 @@
+//
+// Created by jonathan.hanks on 11/17/20.
+//
+
+#ifndef DAQD_TRUNK_SIMPLE_RANGE_HH
+#define DAQD_TRUNK_SIMPLE_RANGE_HH
+
+#include <type_traits>
+#include <utility>
+
+namespace embedded
+{
+    /*!
+     * @brief a very simple range class, just tracks two iterators in one unit, [start, end)
+     * @tparam It the iterator type, which must be noexcept on copy and move
+     */
+    template <typename It>
+    class range
+    {
+        static_assert(std::is_nothrow_copy_constructible<It>::value, "It must be no throw copy constructable");
+        static_assert(std::is_nothrow_copy_assignable<It>::value, "It must be no throw copyable");
+        static_assert(std::is_nothrow_move_constructible<It>::value, "It must be no throw move constructable");
+        static_assert(std::is_nothrow_move_assignable<It>::value, "It must be no throw movable");
+    public:
+        using iterator = It;
+
+        range() noexcept: start_{}, end_{} {}
+        range(const range&) noexcept = default;
+        range(range&&) noexcept = default;
+        range(It it1, It it2) noexcept: start_{std::move(it1)}, end_{std::move(it2)} {}
+        range& operator=(const range&) noexcept = default;
+        range& operator=(range&&) noexcept = default;
+
+        iterator
+        begin() noexcept
+        {
+            return start_;
+        }
+
+        iterator
+        end() noexcept
+        {
+            return end_;
+        }
+
+        const iterator
+        begin() const noexcept
+        {
+            return start_;
+        }
+
+        const iterator
+        end() const noexcept
+        {
+            return end_;
+        }
+
+    private:
+        It start_;
+        It end_;
+    };
+
+    /*!
+     * @brief Given two iterators of type It construct a range
+     * @tparam It
+     * @param start
+     * @param end
+     * @return the resulting range
+     */
+    template <typename It>
+    range<It>
+    make_range(It start, It end)
+    {
+        return range<It>(std::move(start), std::move(end));
+    }
+}
+
+#endif //DAQD_TRUNK_SIMPLE_RANGE_HH
diff --git a/src/epics/seq/test/test_burtfile.cc b/src/epics/seq/test/test_burtfile.cc
new file mode 100644
index 0000000000000000000000000000000000000000..677bd8c156aae67b1e8a458214e32e5658b59c4c
--- /dev/null
+++ b/src/epics/seq/test/test_burtfile.cc
@@ -0,0 +1,84 @@
+//
+// Created by jonathan.hanks on 4/2/22.
+//
+#include "catch.hpp"
+#include "burt_file.hh"
+#include <string>
+#include <vector>
+
+TEST_CASE( "Test encodeString" )
+{
+    struct TestCase
+    {
+        const char* input;
+        const char* expected_output;
+    };
+    std::vector< TestCase > test_cases{
+        { nullptr, "\\0" },
+        { "", "\\0" },
+        { "abc", "abc" },
+        { "abc def", "\"abc def\"" },
+        { "abc\"d\"ef", "\"abc\"d\"ef\"" },
+        { "abc\"def", "\"abc\"def\"" },
+        { "abc\ndef", "\"abc\ndef\"" },
+        { "abc\tdef", "\"abc\tdef\"" },
+    };
+    for ( const auto& test_case : test_cases )
+    {
+        embedded::fixed_string< 18 > src( test_case.input );
+        embedded::fixed_string< 20 > dest;
+        BURT::encodeString( src, dest );
+        REQUIRE( strcmp( test_case.expected_output, dest.c_str( ) ) == 0 );
+    }
+}
+#include <iostream>
+TEST_CASE( "Test parseLine" )
+{
+    struct TestCase
+    {
+        const char*                input;
+        std::vector< std::string > expected_output;
+    };
+    std::vector< TestCase > test_cases{
+        { "", {} },
+        { "\\0", { "" } },
+        { "abc", { "abc" } },
+        { "abc def", { "abc", "def" } },
+        { "abc\tdef", { "abc", "def" } },
+        /* newline ends the parsing */
+        { "abc\ndef", { "abc" } },
+        { "0 1 2 3 4 5", { "0", "1", "2", "3", "4", "5" } },
+        { "0 1 2 \\0 4 5", { "0", "1", "2", "", "4", "5" } },
+        /* shouldn't include the quote in the output */
+        { "\"0\" 1 2 3 4 5", { "0", "1", "2", "3", "4", "5" } },
+        { "0 1 2 3 4 5 6", { "0", "1", "2", "3", "4", "5" } },
+        { "0 1 2 3 4 5 6 7 8 9 10", { "0", "1", "2", "3", "4", "5" } },
+        { "0 \" 1 2 3 4 5 \" 6 7 8 9 10",
+          { "0", " 1 2 3 4 5 ", "6", "7", "8", "9" } },
+        { "0 \" 1\t2\t3 4 5 \" 6 7 8 9 10",
+          { "0", " 1\t2\t3 4 5 ", "6", "7", "8", "9" } },
+        { "0 \" 1\t2\n\t3 4 5 \" 6 7 8 9 10", { "0", " 1\t2" } },
+        { "012345678901234567890", { "01234567890123" } },
+        { "012345678901234567890 012345678901234567890",
+          { "01234567890123", "01234567890123" } },
+        /* Make sure the quote is not in the output */
+        { "\"012345678901234567890\" 012345678901234567890",
+          { "01234567890123", "01234567890123" } },
+        /* truncate, and do not overflow */
+        { "012345678901234567890 \"abcdefghijklmnop\" ABC",
+          { "01234567890123", "abcdefghijklmn", "ABC" } },
+    };
+    for ( const auto& test_case : test_cases )
+    {
+        embedded::fixed_size_vector< embedded::fixed_string< 15 >, 6 > out{ };
+
+        std::cout << test_case.input << "\n";
+        int wc = BURT::parseLine( test_case.input, out );
+        REQUIRE( wc == test_case.expected_output.size( ) );
+        REQUIRE( wc == out.size( ) );
+        for ( auto i = 0; i < wc; ++i )
+        {
+            REQUIRE( out[ i ] == test_case.expected_output[ i ].c_str( ) );
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/epics/seq/test/test_fixed_size_string.cc b/src/epics/seq/test/test_fixed_size_string.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fafb843b378ec087879610808b1203f470d21371
--- /dev/null
+++ b/src/epics/seq/test/test_fixed_size_string.cc
@@ -0,0 +1,417 @@
+//
+// Created by jonathan.hanks on 8/16/18.
+//
+#include "catch.hpp"
+
+#include "fixed_size_string.hh"
+
+#include <cstring>
+#include <type_traits>
+#include <vector>
+
+static_assert(
+    std::is_trivially_copyable< embedded::fixed_string< 64 > >::value,
+    "Must be trivial" );
+static_assert( std::is_standard_layout< embedded::fixed_string< 64 > >::value,
+               "Must be standard layout" );
+static_assert(
+    std::is_nothrow_constructible< embedded::fixed_string< 64 > >::value,
+    "Must be nothrow constructable" );
+static_assert(
+    std::is_nothrow_copy_constructible< embedded::fixed_string< 64 > >::value,
+    "Must be nothrow copy constructable" );
+static_assert(
+    std::is_nothrow_copy_assignable< embedded::fixed_string< 64 > >::value,
+    "Must be nothrow copy assignable" );
+static_assert( std::is_nothrow_swappable< embedded::fixed_string< 64 > >::value,
+               "Must be nothrow swappable" );
+
+TEST_CASE( "You can create a fixed_size_string" )
+{
+
+    SECTION( "Create an empty string" )
+    {
+        embedded::fixed_string< 64 > s;
+        REQUIRE( s.capacity( ) == 64 );
+        REQUIRE( s.remaining( ) == 63 );
+        REQUIRE( sizeof( s ) >= 64 );
+        REQUIRE( s.size( ) == 0 );
+        REQUIRE( std::strcmp( s.c_str( ), "" ) == 0 );
+        REQUIRE( s.c_str( ) == s.data( ) );
+    }
+    SECTION( "Create a string from a literal" )
+    {
+        std::vector< const char* > tests;
+        tests.push_back( "This is a test" );
+        tests.push_back( (char*)0 );
+        tests.push_back( "" );
+        tests.push_back( " " );
+        tests.push_back(
+            "123456789012345678901234567890123456789012345678901234567890123" );
+        tests.push_back( "12345678901234567890123456789012345678901234567890123"
+                         "45678901234" );
+        tests.push_back( "12345678901234567890123456789012345678901234567890123"
+                         "456789012345" );
+
+        for ( int i = 0; i < tests.size( ); ++i )
+        {
+            embedded::fixed_string< 64 > s( tests[ i ] );
+            REQUIRE( s.capacity( ) == 64 );
+            REQUIRE( s.c_str( ) == s.data( ) );
+            if ( tests[ i ] )
+            {
+                if ( strlen( tests[ i ] ) >= s.capacity( ) )
+                {
+                    REQUIRE( strncmp( s.c_str( ),
+                                      tests[ i ],
+                                      s.capacity( ) - 1 ) == 0 );
+                    REQUIRE( strlen( s.c_str( ) ) == s.capacity( ) - 1 );
+                    REQUIRE( s.size( ) == s.capacity( ) - 1 );
+                }
+                else
+                {
+                    REQUIRE( strcmp( s.c_str( ), tests[ i ] ) == 0 );
+                    REQUIRE( strlen( tests[ i ] ) == s.size( ) );
+                }
+            }
+            else
+            {
+                REQUIRE( strcmp( s.c_str( ), "" ) == 0 );
+                REQUIRE( s.size( ) == 0 );
+            }
+        }
+    }
+    SECTION( "Create via copy constructor" )
+    {
+        embedded::fixed_string< 64 > s0( "Hello World!" );
+        embedded::fixed_string< 64 > s1( s0 );
+        REQUIRE( s0.size( ) == s1.size( ) );
+        REQUIRE( s0.capacity( ) == s1.capacity( ) );
+        REQUIRE( strcmp( s0.c_str( ), s1.c_str( ) ) == 0 );
+        REQUIRE( strcmp( s0.c_str( ), "Hello World!" ) == 0 );
+    }
+    SECTION( "Create via copy constructor from different size "
+             "embedded::fixed_string using copy constructor" )
+    {
+        embedded::fixed_string< 32 > s0( "Hello World!" );
+        embedded::fixed_string< 64 > s1( s0 );
+        REQUIRE( s0.size( ) == s1.size( ) );
+        REQUIRE( s0.capacity( ) == 32 );
+        REQUIRE( s1.capacity( ) == 64 );
+        REQUIRE( strcmp( s0.c_str( ), s1.c_str( ) ) == 0 );
+        REQUIRE( strcmp( s0.c_str( ), "Hello World!" ) == 0 );
+    }
+    SECTION( "Create via copy constructor to a smaller size "
+             "embedded::fixed_string using copy constructor" )
+    {
+        embedded::fixed_string< 32 > s0( "Hello World!" );
+        embedded::fixed_string< 6 >  s1( s0 );
+        REQUIRE( s0.size( ) == 12 );
+        REQUIRE( s1.size( ) == 5 );
+        REQUIRE( s0.capacity( ) == 32 );
+        REQUIRE( s1.capacity( ) == 6 );
+        REQUIRE( strcmp( s0.c_str( ), s1.c_str( ) ) != 0 );
+        REQUIRE( strcmp( s1.c_str( ), "Hello" ) == 0 );
+    }
+    SECTION( "Create via copy constructor from different size "
+             "embedded::fixed_string using c_str()" )
+    {
+        embedded::fixed_string< 32 > s0( "Hello World!" );
+        embedded::fixed_string< 64 > s1( s0.c_str( ) );
+        REQUIRE( s0.size( ) == s1.size( ) );
+        REQUIRE( s0.capacity( ) == 32 );
+        REQUIRE( s1.capacity( ) == 64 );
+        REQUIRE( strcmp( s0.c_str( ), s1.c_str( ) ) == 0 );
+        REQUIRE( strcmp( s0.c_str( ), "Hello World!" ) == 0 );
+    }
+    SECTION( "Copy operators should work" )
+    {
+        embedded::fixed_string< 64 > s;
+        REQUIRE( s.size( ) == 0 );
+        embedded::fixed_string< 64 > other( "Hello World!" );
+        s = other;
+        REQUIRE( s.size( ) == other.size( ) );
+        REQUIRE( strcmp( s.c_str( ), other.c_str( ) ) == 0 );
+
+        const char* goodbye = "Goodbye World!";
+        s = goodbye;
+        REQUIRE( s.size( ) == strlen( goodbye ) );
+        REQUIRE( strcmp( s.c_str( ), goodbye ) == 0 );
+
+        std::vector< const char* > tests;
+        tests.push_back( "This is a test" );
+        tests.push_back( (char*)0 );
+        tests.push_back( "" );
+        tests.push_back( " " );
+        tests.push_back(
+            "123456789012345678901234567890123456789012345678901234567890123" );
+        tests.push_back( "12345678901234567890123456789012345678901234567890123"
+                         "45678901234" );
+        tests.push_back( "12345678901234567890123456789012345678901234567890123"
+                         "456789012345" );
+
+        for ( int i = 0; i < tests.size( ); ++i )
+        {
+            s = tests[ i ];
+            if ( tests[ i ] )
+            {
+                if ( strlen( tests[ i ] ) >= s.capacity( ) )
+                {
+                    REQUIRE( strncmp( s.c_str( ),
+                                      tests[ i ],
+                                      s.capacity( ) - 1 ) == 0 );
+                    REQUIRE( strlen( s.c_str( ) ) == s.capacity( ) - 1 );
+                    REQUIRE( s.size( ) == s.capacity( ) - 1 );
+                }
+                else
+                {
+                    REQUIRE( strcmp( s.c_str( ), tests[ i ] ) == 0 );
+                    REQUIRE( strlen( tests[ i ] ) == s.size( ) );
+                }
+            }
+            else
+            {
+                REQUIRE( strcmp( s.c_str( ), "" ) == 0 );
+                REQUIRE( s.size( ) == 0 );
+            }
+        }
+    }
+}
+
+TEST_CASE( "Copy operators work even when the sizes are different, it just may "
+           "truncate" )
+{
+    embedded::fixed_string< 64 > s0( "123456" );
+    embedded::fixed_string< 32 > s1;
+    embedded::fixed_string< 6 >  s2;
+    embedded::fixed_string< 64 > s3( "123456" );
+
+    s1 = s0;
+    REQUIRE( s1 == "123456" );
+    s2 = s0;
+    REQUIRE( s2 == "12345" );
+    s3 = s2;
+    REQUIRE( s3 == "12345" );
+}
+
+TEST_CASE( "You can append to a fixed size string" )
+{
+    embedded::fixed_string< 64 > s;
+    embedded::fixed_string< 6 >  single( "0" );
+    embedded::fixed_string< 6 >  five( "00000" );
+
+    for ( int i = 1; i <= 100; ++i )
+    {
+        s += '0';
+        std::size_t expected_zeros =
+            ( i < s.capacity( ) ? i : s.capacity( ) - 1 );
+        REQUIRE( s.size( ) == expected_zeros );
+        std::size_t j = 0;
+        for ( ; j < expected_zeros && s.c_str( )[ j ] == '0'; ++j )
+        {
+        }
+        REQUIRE( j == expected_zeros );
+    }
+    s.clear( );
+    for ( int i = 1; i <= 100; ++i )
+    {
+        s += "0";
+        std::size_t expected_zeros =
+            ( i < s.capacity( ) ? i : s.capacity( ) - 1 );
+        REQUIRE( s.size( ) == expected_zeros );
+        std::size_t j = 0;
+        for ( ; j < expected_zeros && s.c_str( )[ j ] == '0'; ++j )
+        {
+        }
+        REQUIRE( j == expected_zeros );
+    }
+    s = "";
+    for ( int i = 1; i <= 100; ++i )
+    {
+        s += "00000";
+        std::size_t expected_zeros =
+            ( i * 5 < s.capacity( ) ? i * 5 : s.capacity( ) - 1 );
+        REQUIRE( s.size( ) == expected_zeros );
+        std::size_t j = 0;
+        for ( ; j < expected_zeros && s.c_str( )[ j ] == '0'; ++j )
+        {
+        }
+        REQUIRE( j == expected_zeros );
+    }
+    s = "";
+    for ( int i = 1; i <= 100; ++i )
+    {
+        s += single;
+        std::size_t expected_zeros =
+            ( i < s.capacity( ) ? i : s.capacity( ) - 1 );
+        REQUIRE( s.size( ) == expected_zeros );
+        std::size_t j = 0;
+        for ( ; j < expected_zeros && s.c_str( )[ j ] == '0'; ++j )
+        {
+        }
+        REQUIRE( j == expected_zeros );
+    }
+    s = "";
+    for ( int i = 1; i <= 100; ++i )
+    {
+        s += five;
+        std::size_t expected_zeros =
+            ( i * 5 < s.capacity( ) ? i * 5 : s.capacity( ) - 1 );
+        REQUIRE( s.size( ) == expected_zeros );
+        std::size_t j = 0;
+        for ( ; j < expected_zeros && s.c_str( )[ j ] == '0'; ++j )
+        {
+        }
+        REQUIRE( j == expected_zeros );
+    }
+    s = "abab";
+    s += s;
+    REQUIRE( s.size( ) == 8 );
+    REQUIRE( strcmp( s.c_str( ), "abababab" ) == 0 );
+    REQUIRE( s.remaining( ) == 63 - 8 );
+}
+
+TEST_CASE( "You can do printf style formatted printing" )
+{
+    embedded::fixed_string< 64 > s;
+    s.printf( "%d", 123456 );
+    REQUIRE( strcmp( s.c_str( ), "123456" ) == 0 );
+    s.printf( "%s", "abcdefg" );
+    REQUIRE( strcmp( s.c_str( ), "abcdefg" ) == 0 );
+    s.printf(
+        "%s",
+        "12345678901234567890123456789012345678901234567890123456789012345" );
+    REQUIRE( s.size( ) == 63 );
+    REQUIRE( strcmp( s.c_str( ),
+                     "123456789012345678901234567890123456789012345678901234567"
+                     "890123" ) == 0 );
+    s.printf(
+        "%d %s",
+        -1,
+        "12345678901234567890123456789012345678901234567890123456789012345" );
+    REQUIRE( s.size( ) == 63 );
+    REQUIRE(
+        strcmp(
+            s.c_str( ),
+            "-1 "
+            "123456789012345678901234567890123456789012345678901234567890" ) ==
+        0 );
+}
+
+TEST_CASE( "You can check for a zero length string by using empty()" )
+{
+    embedded::fixed_string< 64 > s0( "" );
+    REQUIRE( s0.empty( ) );
+
+    s0 = "abc";
+    REQUIRE( !s0.empty( ) );
+}
+
+TEST_CASE( "You can use begin/end on a fixed_size_string" )
+{
+    embedded::fixed_string< 64 > s0( "" );
+
+    REQUIRE( s0.begin( ) == s0.end( ) );
+    REQUIRE( s0.begin( ) == s0.c_str( ) );
+
+    s0 = "a";
+    REQUIRE( s0.end( ) == s0.begin( ) + 1 );
+    REQUIRE( s0.begin( ) == s0.c_str( ) );
+
+    s0 = "abc";
+    REQUIRE( s0.end( ) == s0.begin( ) + 3 );
+    REQUIRE( s0.begin( ) == s0.c_str( ) );
+}
+
+TEST_CASE( "You can assign and append via char arrays" )
+{
+    embedded::fixed_string< 64 > s0( "123456" );
+    char                         blob[ 1 ][ 8 ] = { "abc" };
+
+    s0 += blob[ 0 ];
+    REQUIRE( s0 == "123456abc" );
+}
+
+TEST_CASE( "clear will reset the fixed_string to be empty" )
+{
+    embedded::fixed_string< 64 > s0( "123456" );
+    REQUIRE( s0.size( ) > 0 );
+    s0.clear( );
+    REQUIRE( s0.size( ) == 0 );
+    REQUIRE( s0 == "" );
+}
+
+TEST_CASE(
+    "printf with a null format string is equal to a format string of \"\"" )
+{
+    embedded::fixed_string< 64 > s0( "123456" );
+    REQUIRE( s0.printf( nullptr ) == 0 );
+    REQUIRE( s0 == "" );
+}
+
+TEST_CASE(
+    "You can compare with a fixed_string using operator== and operator!=" )
+{
+    embedded::fixed_string< 64 > s0( "123456" ), s1( "123456789" );
+
+    REQUIRE( s0 == s0 );
+    REQUIRE( s0 != s1 );
+}
+
+TEST_CASE( "You can compare with a fixed_string using operator== and "
+           "operator!= even when capacities are different" )
+{
+    embedded::fixed_string< 64 > s0( "1234" ), s1( "123456789" );
+    embedded::fixed_string< 6 >  s2( "1234" );
+
+    REQUIRE( s0 == s2 );
+    REQUIRE( s1 != s2 );
+}
+
+TEST_CASE( "You can compare with a char* using operator== and operator!=" )
+{
+    embedded::fixed_string< 64 > s0( "123456" );
+
+    REQUIRE( s0 == "123456" );
+    REQUIRE( s0 != "1234567890" );
+}
+
+TEST_CASE( "It is safe to compare with a null char*, it matches an empty "
+           "fixed_string" )
+{
+    embedded::fixed_string< 64 > s0( "123456" );
+    embedded::fixed_string< 64 > s1;
+    REQUIRE( s0.size( ) > 0 );
+    REQUIRE( s1.size( ) == 0 );
+    REQUIRE( s0 != nullptr );
+    REQUIRE( s1 == "" );
+    REQUIRE( s1 == nullptr );
+}
+
+TEST_CASE( "You can remove characters from the end" )
+{
+    embedded::fixed_string< 64 > s0( "1234567890" );
+
+    REQUIRE( s0.size( ) == 10 );
+    s0.pop_back_n( 4 );
+    REQUIRE( s0.size( ) == 6 );
+    REQUIRE( s0 == "123456" );
+    s0.pop_back_n( 1 );
+    REQUIRE( s0.size( ) == 5 );
+    s0.pop_back_n( 10 );
+    REQUIRE( s0.size( ) == 0 );
+}
+
+TEST_CASE( "For direct manipulation you can get a buffer which cleans up when "
+           "it is done" )
+{
+    embedded::fixed_string< 10 > s0( "abc" );
+
+    {
+        auto buf = s0.get_buffer( );
+        std::fill( buf.data( ), buf.data( ) + buf.capacity( ), 1 );
+        REQUIRE( buf.data( )[ buf.capacity( ) - 1 ] == 1 );
+        REQUIRE( s0.data( )[ s0.capacity( ) - 1 ] == 1 );
+    }
+    REQUIRE( s0.data( )[ s0.capacity( ) - 1 ] == '\0' );
+}
\ No newline at end of file
diff --git a/src/epics/seq/test/test_fixed_size_vector.cc b/src/epics/seq/test/test_fixed_size_vector.cc
new file mode 100644
index 0000000000000000000000000000000000000000..602dd286a92e73c2d5bf9caec2478218905d5df4
--- /dev/null
+++ b/src/epics/seq/test/test_fixed_size_vector.cc
@@ -0,0 +1,223 @@
+//
+// Created by jonathan.hanks on 11/13/20.
+//
+
+#include "catch.hpp"
+
+#include "fixed_size_vector.hh"
+
+#include <algorithm>
+
+TEST_CASE( "You can create a fixed size vector" )
+{
+    embedded::fixed_size_vector< int, 20 > v0;
+
+    REQUIRE( v0.size( ) == 0 );
+    REQUIRE( v0.empty( ) );
+    REQUIRE( v0.capacity( ) == 20 );
+    REQUIRE( v0.begin( ) == v0.end( ) );
+
+    const embedded::fixed_size_vector< int, 20 > v1;
+    REQUIRE( v1.begin( ) == v1.end( ) );
+    REQUIRE( v1.cbegin( ) == v1.cend( ) );
+    REQUIRE( v1.begin( ) == v1.cbegin( ) );
+    REQUIRE( v1.end( ) == v1.cend( ) );
+
+    static_assert(
+        std::is_same<
+            int*,
+            typename embedded::fixed_size_vector< int, 20 >::iterator >::value,
+        "The iterator is a pointer" );
+    static_assert(
+        std::is_same< const int*,
+                      typename embedded::fixed_size_vector< int, 20 >::
+                          const_iterator >::value,
+        "The iterator is pointer to const" );
+}
+
+TEST_CASE( "You can add elements to the back of a fixed size vector" )
+{
+    embedded::fixed_size_vector< int, 20 > v0;
+    REQUIRE( v0.push_back( 5 ) );
+    REQUIRE( v0.size( ) == 1 );
+    REQUIRE( v0.capacity( ) == 20 );
+    REQUIRE( v0.push_back( 6 ) );
+    REQUIRE( v0.size( ) == 2 );
+    REQUIRE( v0.capacity( ) == 20 );
+    REQUIRE( v0.push_back( 7 ) );
+    REQUIRE( v0.size( ) == 3 );
+    REQUIRE( v0.capacity( ) == 20 );
+    REQUIRE( v0.end( ) == v0.begin( ) + v0.size( ) );
+    REQUIRE( *v0.begin( ) == 5 );
+    REQUIRE( *( v0.begin( ) + 1 ) == 6 );
+    REQUIRE( *( v0.begin( ) + 2 ) == 7 );
+}
+
+TEST_CASE( "You can add elements to the back of a fixed size vector with "
+           "emplace_back" )
+{
+    embedded::fixed_size_vector< int, 20 > v0;
+    REQUIRE( v0.emplace_back( 5 ) );
+    REQUIRE( v0.size( ) == 1 );
+    REQUIRE( v0.capacity( ) == 20 );
+    REQUIRE( v0.emplace_back( 6 ) );
+    REQUIRE( v0.size( ) == 2 );
+    REQUIRE( v0.capacity( ) == 20 );
+    REQUIRE( v0.emplace_back( 7 ) );
+    REQUIRE( v0.size( ) == 3 );
+    REQUIRE( v0.capacity( ) == 20 );
+    REQUIRE( v0.end( ) == v0.begin( ) + v0.size( ) );
+    REQUIRE( *v0.begin( ) == 5 );
+    REQUIRE( *( v0.begin( ) + 1 ) == 6 );
+    REQUIRE( *( v0.begin( ) + 2 ) == 7 );
+}
+
+TEST_CASE( "Attempting to add elements when full returns a false value" )
+{
+    embedded::fixed_size_vector< int, 20 > v0;
+    for ( auto i = 0; i < v0.capacity( ); ++i )
+    {
+        REQUIRE( v0.push_back( i ) );
+    }
+    REQUIRE( v0.size( ) == v0.capacity( ) );
+    REQUIRE( v0.push_back( 42 ) == false );
+    REQUIRE( v0.emplace_back( 43 ) == false );
+    REQUIRE( v0.size( ) == v0.capacity( ) );
+}
+
+TEST_CASE( "You can access elements via []" )
+{
+    embedded::fixed_size_vector< int, 20 > v0;
+    for ( auto i = 0; i < v0.capacity( ); ++i )
+    {
+        REQUIRE( v0.push_back( i ) );
+    }
+    for ( auto i = 0; i < v0.capacity( ); ++i )
+    {
+        REQUIRE( v0[ i ] == i );
+    }
+}
+
+TEST_CASE( "You can pop an entry off of the end of a vector" )
+{
+    embedded::fixed_size_vector< int, 20 > v0;
+    for ( auto i = 0; i < v0.capacity( ); ++i )
+    {
+        REQUIRE( v0.push_back( i ) );
+    }
+    REQUIRE( v0.end( ) == v0.begin( ) + v0.capacity( ) );
+    REQUIRE( v0.size( ) == v0.capacity( ) );
+
+    v0.pop_back( );
+    REQUIRE( v0.end( ) == v0.begin( ) + v0.capacity( ) - 1 );
+    REQUIRE( v0.size( ) == v0.capacity( ) - 1 );
+}
+
+TEST_CASE( "You can clear a fixed sized vector to empty it" )
+{
+    embedded::fixed_size_vector< int, 20 > v0;
+    for ( auto i = 0; i < v0.capacity( ); ++i )
+    {
+        REQUIRE( v0.push_back( i ) );
+    }
+    REQUIRE( v0.end( ) == v0.begin( ) + v0.capacity( ) );
+    REQUIRE( v0.size( ) == v0.capacity( ) );
+
+    v0.clear( );
+    REQUIRE( v0.size( ) == 0 );
+    REQUIRE( v0.begin( ) == v0.end( ) );
+    REQUIRE( v0.capacity( ) == 20 );
+}
+
+class DestructionNotifier
+{
+public:
+    explicit DestructionNotifier( int* counter_dest ) : counter_{ counter_dest }
+    {
+    }
+    DestructionNotifier( const DestructionNotifier& ) noexcept = default;
+    DestructionNotifier&
+    operator=( const DestructionNotifier& ) noexcept = default;
+
+    ~DestructionNotifier( )
+    {
+        ( *counter_ )++;
+    }
+
+private:
+    int* counter_;
+};
+
+TEST_CASE( "Destructors are called on items in the fixed size vector when it "
+           "is destroyed or elements are popped off" )
+{
+    int counter = 0;
+
+    {
+        embedded::fixed_size_vector< DestructionNotifier, 10 > v0;
+
+        v0.emplace_back( &counter );
+        REQUIRE( !v0.empty( ) );
+        REQUIRE( counter == 0 );
+        v0.pop_back( );
+        REQUIRE( v0.empty( ) );
+        REQUIRE( counter == 1 );
+
+        counter = 0;
+        while ( v0.emplace_back( &counter ) )
+        {
+        }
+        REQUIRE( v0.size( ) == v0.capacity( ) );
+    }
+    REQUIRE( counter == 10 );
+}
+
+TEST_CASE( "We have defined enough to make the this usable by std::algorithms" )
+{
+    embedded::fixed_size_vector< int, 20 > v0;
+    v0.emplace_back( 5 );
+    v0.emplace_back( 4 );
+    v0.emplace_back( 3 );
+    v0.emplace_back( 2 );
+    v0.emplace_back( 1 );
+    std::sort( v0.begin( ), v0.end( ) );
+    REQUIRE( v0[ 0 ] == 1 );
+    REQUIRE( v0[ 1 ] == 2 );
+    REQUIRE( v0[ 2 ] == 3 );
+    REQUIRE( v0[ 3 ] == 4 );
+    REQUIRE( v0[ 4 ] == 5 );
+}
+
+TEST_CASE( "We can use front()/back() to reference the first/last elements when there are more than one.")
+{
+    embedded::fixed_size_vector<int, 20> v0;
+    v0.push_back(5);
+    REQUIRE( v0.front() == v0.back() );
+    v0.front() = 42;
+    REQUIRE( v0[0] == 42 );
+    v0.back() = 44;
+    REQUIRE( v0[0] == 44 );
+    v0.push_back(10);
+    REQUIRE( v0.front() == 44 );
+    REQUIRE( v0.back() == 10 );
+    REQUIRE( v0[0] == v0.front() );
+    REQUIRE( v0[1] == v0.back() );
+}
+
+TEST_CASE( "We can use front()/back() in a const setting as well")
+{
+    embedded::fixed_size_vector<int, 20> v0;
+    v0.push_back(5);
+
+    const auto& vconst = v0;
+    REQUIRE( vconst.front() == vconst.back() );
+}
+
+// static_assert(std::is_trivially_destructible<embedded::fixed_size_vector<int,
+// 20> >::value, "For trivial destructable types the fixed sized vector should
+// be trivially destructable");
+static_assert(
+    !std::is_trivially_destructible<
+        embedded::fixed_size_vector< DestructionNotifier, 10 > >::value,
+    "for non-trivially destructable types the fixed size vector is not "
+    "trivially destructable" );
\ No newline at end of file
diff --git a/src/epics/seq/test/test_main.cc b/src/epics/seq/test/test_main.cc
new file mode 100644
index 0000000000000000000000000000000000000000..063e87874ea57a58d37496c85910b1f6cd2c6415
--- /dev/null
+++ b/src/epics/seq/test/test_main.cc
@@ -0,0 +1,2 @@
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
\ No newline at end of file
diff --git a/src/epics/seq/test/test_simple_range.cc b/src/epics/seq/test/test_simple_range.cc
new file mode 100644
index 0000000000000000000000000000000000000000..efe9d32164013a1b4315294b7d56b8453dfff966
--- /dev/null
+++ b/src/epics/seq/test/test_simple_range.cc
@@ -0,0 +1,18 @@
+//
+// Created by jonathan.hanks on 11/17/20.
+//
+#include "catch.hpp"
+
+#include "simple_range.hh"
+
+#include <vector>
+
+TEST_CASE("You can create a simple range from two iterators")
+{
+    using it_type = typename std::vector<int>::iterator;
+    std::vector<int> backing_store{1,2,3,4,5,6,7,8,9,0};
+
+    embedded::range<it_type> rng = embedded::make_range(backing_store.begin() + 3, backing_store.begin() + 3 + 3);
+    REQUIRE( *rng.begin() == 4 );
+    REQUIRE( *rng.end() == 7 );
+}
diff --git a/src/epics/simLink/CDS_PARTS.mdl b/src/epics/simLink/CDS_PARTS.mdl
index 63688b88e6b018dad82680643777eef4c5c400f0..7047ff25b22590db7e3003e4e9e378a0d5070004 100644
--- a/src/epics/simLink/CDS_PARTS.mdl
+++ b/src/epics/simLink/CDS_PARTS.mdl
@@ -1,12 +1,12 @@
 Library {
   Name			  "CDS_PARTS"
   Version		  9.3
-  SavedCharacterEncoding  "ISO-8859-1"
-  WebScopes_FoundationPlugin "on"
+  SavedCharacterEncoding  "UTF-8"
   DiagnosticSuppressor	  "on"
   SLCCPlugin		  "on"
-  NotesPlugin		  "on"
+  WebScopes_FoundationPlugin "on"
   LogicAnalyzerPlugin	  "on"
+  NotesPlugin		  "on"
   LibraryType		  "BlockLibrary"
   EnableAccessToBaseWorkspace on
   ScopeRefreshTime	  0.035000
@@ -14,7 +14,7 @@ Library {
   DisableAllScopes	  off
   FPTRunName		  "Run 1"
   MaxMDLFileLineLength	  120
-  LastSavedArchitecture	  "maci64"
+  LastSavedArchitecture	  "glnxa64"
   Object {
     $PropName		    "BdWindowsInfo"
     $ObjectID		    1
@@ -24,17 +24,17 @@ Library {
       $ObjectID		      2
       $ClassName	      "Simulink.WindowInfo"
       IsActive		      [1]
-      Location		      [343.0, 42.0, 1036.0, 877.0]
+      Location		      [729.0, 64.0, 1036.0, 877.0]
       Object {
 	$PropName		"ModelBrowserInfo"
 	$ObjectID		3
 	$ClassName		"Simulink.ModelBrowserInfo"
-	Visible			[0]
+	Visible			[1]
 	DockPosition		"Left"
 	Width			[50]
 	Height			[50]
 	Filter			[9]
-	Minimized		"Unset"
+	Minimized		"Off"
       }
       Object {
 	$PropName		"ExplorerBarInfo"
@@ -47,11 +47,11 @@ Library {
 	$ObjectID		5
 	$ClassName		"Simulink.EditorInfo"
 	IsActive		[1]
-	ViewObjType		"SimulinkTopLevel"
-	LoadSaveID		"0"
-	Extents			[998.0, 712.0]
-	ZoomFactor		[1.4799999999999998]
-	Offset			[1.1368683772161603e-13, 0.0]
+	ViewObjType		"SimulinkSubsys"
+	LoadSaveID		"150"
+	Extents			[735.0, 687.0]
+	ZoomFactor		[1.5]
+	Offset			[-17.569047619048717, 227.907229427522]
       }
       Object {
 	$PropName		"DockComponentsInfo"
@@ -68,15 +68,15 @@ Library {
 	Height			[480]
 	Minimized		"Unset"
       }
-      WindowState	      "AAAA/wAAAAD9AAAAAgAAAAAAAAC9AAAB+PwCAAAAA/sAAAAWAEQAbwBjAGsAVwBpAGQAZwBlAHQAMwEAAAAxAAAB+AAAA"
+      WindowState	      "AAAA/wAAAAD9AAAAAgAAAAAAAAD1AAAC8PwCAAAAA/sAAAAWAEQAbwBjAGsAVwBpAGQAZwBlAHQAMwEAAAAxAAAB+AAAA"
       "AAAAAAA+wAAABYARABvAGMAawBXAGkAZABnAGUAdAA0AAAAAAD/////AAAAAAAAAAD7AAAAUgBHAEwAVQBFADIAIAB0AHIAZQBlACAAYwBvAG0Ac"
-      "ABvAG4AZQBuAHQALwBHAEwAVQBFADIAIAB0AHIAZQBlACAAYwBvAG0AcABvAG4AZQBuAHQAAAAAAP////8AAABrAP///wAAAAEAAAAAAAAAAPwCA"
+      "ABvAG4AZQBuAHQALwBHAEwAVQBFADIAIAB0AHIAZQBlACAAYwBvAG0AcABvAG4AZQBuAHQBAAAAQAAAAvAAAACAAP///wAAAAEAAAAAAAAAAPwCA"
       "AAAAfsAAABUAEcATABVAEUAMgA6AFAAcgBvAHAAZQByAHQAeQBJAG4AcwBwAGUAYwB0AG8AcgAvAFAAcgBvAHAAZQByAHQAeQAgAEkAbgBzAHAAZ"
-      "QBjAHQAbwByAAAAAAD/////AAABrAD///8AAAQMAAADAwAAAAEAAAACAAAAAQAAAAL8AAAAAQAAAAIAAAAP/////wAAAAAA/////wAAAAAAAAAA/"
+      "QBjAHQAbwByAAAAAAD/////AAABrAD///8AAAMFAAAC8AAAAAEAAAACAAAAAQAAAAL8AAAAAQAAAAIAAAAP/////wAAAAAA/////wAAAAAAAAAA/"
       "////wEAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/"
-      "////wEAAACE/////wAAAAAAAAAA/////wEAAAD2/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/"
-      "////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wEAAAFL/////wAAAAAAAAAA/"
-      "////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA"
+      "////wEAAACK/////wAAAAAAAAAA/////wEAAADy/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/"
+      "////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wEAAAFK/////wAAAAAAAAAA/"
+      "////wEAAAGB/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA"
     }
   }
   HideAutomaticNames	  on
@@ -84,11 +84,11 @@ Library {
   Creator		  "aivanov"
   UpdateHistory		  "UpdateHistoryNever"
   ModifiedByFormat	  "%<Auto>"
-  LastModifiedBy	  "rolf"
+  LastModifiedBy	  "ezekiel.dohmen"
   ModifiedDateFormat	  "%<Auto>"
-  LastModifiedDate	  "Thu Dec 17 08:21:58 2020"
-  RTWModifiedTimeStamp	  530093207
-  ModelVersionFormat	  "1.%<AutoIncrement:396>"
+  LastModifiedDate	  "Tue Apr 12 10:14:15 2022"
+  RTWModifiedTimeStamp	  571659248
+  ModelVersionFormat	  "1.%<AutoIncrement:404>"
   SampleTimeColors	  off
   SampleTimeAnnotations	  off
   LibraryLinkDisplay	  "all"
@@ -168,7 +168,7 @@ Library {
       Description	      ""
       Array {
 	Type			"Handle"
-	Dimension		9
+	Dimension		10
 	Simulink.SolverCC {
 	  $ObjectID		  8
 	  Version		  "19.0.0"
@@ -879,6 +879,21 @@ Library {
 	  CovStopTime		  0
 	  CovMcdcMode		  "Masking"
 	}
+	hdlcoderui.hdlcc {
+	  $ObjectID		  19
+	  Version		  "19.0.0"
+	  DisabledProps		  []
+	  Description		  "HDL Coder custom configuration component"
+	  Components		  []
+	  Name			  "HDL Coder"
+	  Array {
+	    Type		    "Cell"
+	    Dimension		    1
+	    Cell		    " "
+	    PropName		    "HDLConfigFile"
+	  }
+	  HDLCActiveTab		  "0"
+	}
 	PropName		"Components"
       }
       Name		      "Configuration"
@@ -1177,12 +1192,12 @@ Library {
   }
   System {
     Name		    "CDS_PARTS"
-    Location		    [343, 42, 1379, 919]
-    Open		    on
+    Location		    [729, 64, 1765, 941]
+    Open		    off
     PortBlocksUseCompactNotation off
     SetExecutionDomain	    off
     ExecutionDomainType	    "Deduce"
-    ModelBrowserVisibility  off
+    ModelBrowserVisibility  on
     ModelBrowserWidth	    200
     ScreenColor		    "white"
     PaperOrientation	    "portrait"
@@ -1192,9 +1207,9 @@ Library {
     TiledPaperMargins	    [0.500000, 0.500000, 0.500000, 0.500000]
     TiledPageScale	    1
     ShowPageBoundaries	    off
-    ZoomFactor		    "148"
+    ZoomFactor		    "100"
     ReportName		    "simulink-default.rpt"
-    SIDHighWatermark	    "379"
+    SIDHighWatermark	    "389"
     SimulinkSubDomain	    "Simulink"
     Block {
       BlockType		      SubSystem
@@ -1212,7 +1227,7 @@ Library {
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"portrait"
@@ -1241,7 +1256,7 @@ Library {
 	    PortBlocksUseCompactNotation off
 	    SetExecutionDomain	    off
 	    ExecutionDomainType	    "Deduce"
-	    ModelBrowserVisibility  off
+	    ModelBrowserVisibility  on
 	    ModelBrowserWidth	    200
 	    ScreenColor		    "white"
 	    PaperOrientation	    "landscape"
@@ -1546,7 +1561,7 @@ Library {
 	    PortBlocksUseCompactNotation off
 	    SetExecutionDomain	    off
 	    ExecutionDomainType	    "Deduce"
-	    ModelBrowserVisibility  off
+	    ModelBrowserVisibility  on
 	    ModelBrowserWidth	    200
 	    ScreenColor		    "white"
 	    PaperOrientation	    "landscape"
@@ -1609,7 +1624,7 @@ Library {
 	    PortBlocksUseCompactNotation off
 	    SetExecutionDomain	    off
 	    ExecutionDomainType	    "Deduce"
-	    ModelBrowserVisibility  off
+	    ModelBrowserVisibility  on
 	    ModelBrowserWidth	    200
 	    ScreenColor		    "white"
 	    PaperOrientation	    "landscape"
@@ -2185,7 +2200,7 @@ Library {
 	    PortBlocksUseCompactNotation off
 	    SetExecutionDomain	    off
 	    ExecutionDomainType	    "Deduce"
-	    ModelBrowserVisibility  off
+	    ModelBrowserVisibility  on
 	    ModelBrowserWidth	    200
 	    ScreenColor		    "white"
 	    PaperOrientation	    "landscape"
@@ -2729,7 +2744,7 @@ Library {
 	    Annotation {
 	      SID		      "98:321"
 	      Name		      "CONTEC6464 Binary I/O Modules "
-	      Position		      [26, 11, 289, 31]
+	      Position		      [26, 11, 289, 38]
 	      InternalMargins	      [0, 0, 0, 0]
 	      ZOrder		      -1
 	      FontName		      "times"
@@ -2738,7 +2753,7 @@ Library {
 	    Annotation {
 	      SID		      "98:322"
 	      Name		      "Card 0 "
-	      Position		      [125, 101, 179, 121]
+	      Position		      [125, 101, 179, 128]
 	      InternalMargins	      [0, 0, 0, 0]
 	      ZOrder		      -2
 	      FontName		      "times"
@@ -2747,7 +2762,7 @@ Library {
 	    Annotation {
 	      SID		      "98:323"
 	      Name		      "Card 1 "
-	      Position		      [300, 101, 354, 121]
+	      Position		      [300, 101, 354, 128]
 	      InternalMargins	      [0, 0, 0, 0]
 	      ZOrder		      -3
 	      FontName		      "times"
@@ -2756,7 +2771,7 @@ Library {
 	    Annotation {
 	      SID		      "98:324"
 	      Name		      "Card 2 "
-	      Position		      [480, 101, 534, 121]
+	      Position		      [480, 101, 534, 128]
 	      InternalMargins	      [0, 0, 0, 0]
 	      ZOrder		      -4
 	      FontName		      "times"
@@ -2765,7 +2780,7 @@ Library {
 	    Annotation {
 	      SID		      "98:325"
 	      Name		      "User Application Parts *********************************"
-	      Position		      [29, 76, 495, 96]
+	      Position		      [29, 76, 495, 103]
 	      InternalMargins	      [0, 0, 0, 0]
 	      ZOrder		      -5
 	      FontName		      "times"
@@ -2774,7 +2789,7 @@ Library {
 	    Annotation {
 	      SID		      "98:326"
 	      Name		      "IOP Parts *********************************"
-	      Position		      [36, 351, 408, 371]
+	      Position		      [36, 351, 408, 378]
 	      InternalMargins	      [0, 0, 0, 0]
 	      ZOrder		      -6
 	      FontName		      "times"
@@ -2783,7 +2798,7 @@ Library {
 	    Annotation {
 	      SID		      "98:327"
 	      Name		      "Card 3 "
-	      Position		      [670, 101, 724, 121]
+	      Position		      [670, 101, 724, 128]
 	      InternalMargins	      [0, 0, 0, 0]
 	      ZOrder		      -7
 	      FontName		      "times"
@@ -3096,7 +3111,7 @@ Library {
 	Annotation {
 	  SID			  "335"
 	  Name			  "Binary I/O Modules *******************************************************************"
-	  Position		  [20, 821, 774, 841]
+	  Position		  [20, 821, 773, 848]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -1
 	  FontName		  "times"
@@ -3105,7 +3120,7 @@ Library {
 	Annotation {
 	  SID			  "336"
 	  Name			  "Digital to Analog (DAC) Modules ********"
-	  Position		  [25, 306, 350, 326]
+	  Position		  [25, 306, 351, 333]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -2
 	  FontName		  "times"
@@ -3114,7 +3129,7 @@ Library {
 	Annotation {
 	  SID			  "337"
 	  Name			  "Real-time Communications ********"
-	  Position		  [24, 556, 300, 576]
+	  Position		  [24, 556, 300, 583]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -3
 	  FontName		  "times"
@@ -3123,7 +3138,7 @@ Library {
 	Annotation {
 	  SID			  "338"
 	  Name			  " aLIGO Real-time Code Generator - I/O Parts Library"
-	  Position		  [126, 7, 644, 33]
+	  Position		  [126, 7, 644, 42]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -4
 	  FontName		  "times"
@@ -3132,7 +3147,7 @@ Library {
 	Annotation {
 	  SID			  "339"
 	  Name			  "Analog to Digial (ADC) Modules ***************************************************"
-	  Position		  [33, 56, 741, 76]
+	  Position		  [33, 56, 740, 83]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -5
 	  FontName		  "times"
@@ -3156,7 +3171,7 @@ Library {
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"portrait"
@@ -3259,7 +3274,7 @@ Library {
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"landscape"
@@ -3296,7 +3311,7 @@ Library {
 	  SID			  "6:7"
 	  Name			  "#DAQ Channels\n\nONE_DAQ_CHANNEL 2048\nANOTHER_DAQ_CHANNEL 1024\nSCIENCE_FRAME_CHAN* 1024\nUINT32_CHAN ui"
 	  "nt32 2048\nDAQ_CHANNEL_AT_DEFAULT_RATE"
-	  Position		  [66, 81, 294, 181]
+	  Position		  [66, 81, 294, 216]
 	  InternalMargins	  [0, 0, 0, 0]
 	  HorizontalAlignment	  "left"
 	  DropShadow		  on
@@ -3337,12 +3352,12 @@ Library {
       RequestExecContextInheritance off
       System {
 	Name			"EpicsParts"
-	Location		[1419, 271, 2439, 1254]
+	Location		[729, 64, 1765, 941]
 	Open			off
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"portrait"
@@ -3367,6 +3382,12 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsEpicsOutLong/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3379,13 +3400,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag13"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3399,13 +3421,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag14"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3419,13 +3442,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag15"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3439,13 +3463,14 @@ Library {
 	  BackgroundColor	  "magenta"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag16"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3459,13 +3484,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag17"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3479,13 +3505,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag18"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3499,13 +3526,14 @@ Library {
 	  BackgroundColor	  "magenta"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag19"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3519,13 +3547,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag20"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3539,13 +3568,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag21"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3559,13 +3589,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag22"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3579,13 +3610,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag23"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3609,6 +3641,12 @@ Library {
 	  LibraryVersion	  "1.6"
 	  SourceBlock		  "cdsEpicsBinIn/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3624,6 +3662,12 @@ Library {
 	  LibraryVersion	  "1.4"
 	  SourceBlock		  "cdsEpicsCounter/EpicsCounter"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3649,6 +3693,12 @@ Library {
 	  LibraryVersion	  "1.7"
 	  SourceBlock		  "cdsEpicsInCtrl/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3671,6 +3721,12 @@ Library {
 	  LibraryVersion	  "1.3"
 	  SourceBlock		  "cdsEpicsIn/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3687,6 +3743,12 @@ Library {
 	  LibraryVersion	  "1.6"
 	  SourceBlock		  "cdsEpicsMbbi/EpicsMbbi"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3703,6 +3765,12 @@ Library {
 	  LibraryVersion	  "1.3"
 	  SourceBlock		  "cdsEpicsMbbo/EpicsMbbo"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3718,6 +3786,12 @@ Library {
 	  LibraryVersion	  "1.6"
 	  SourceBlock		  "cdsEpicsMomentary/EpicsMomentary"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3737,6 +3811,12 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsEpicsOut/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3770,6 +3850,12 @@ Library {
 	  LibraryVersion	  "1.3"
 	  SourceBlock		  "cdsRemoteIntlk/Name"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3786,6 +3872,12 @@ Library {
 	  LibraryVersion	  "1.4"
 	  SourceBlock		  "cdsEpicsStringIn/EpicsStringIn"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Ground
@@ -3819,6 +3911,12 @@ Library {
 	  LibraryVersion	  "1.4"
 	  SourceBlock		  "cdsEzCaRead/cdsEzCaRead"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -3837,6 +3935,12 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsEzCaWrite/cdsEzCaWrite"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Line {
 	  ZOrder		  1
@@ -3855,7 +3959,7 @@ Library {
 	Annotation {
 	  SID			  "332"
 	  Name			  "RCG EPICS Parts Library ******************************"
-	  Position		  [55, 21, 520, 41]
+	  Position		  [55, 21, 520, 48]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -1
 	  FontName		  "times"
@@ -3864,7 +3968,7 @@ Library {
 	Annotation {
 	  SID			  "333"
 	  Name			  "Custom For Guardian Scripts ***************************"
-	  Position		  [42, 471, 502, 491]
+	  Position		  [42, 471, 502, 498]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -2
 	  FontName		  "times"
@@ -3885,12 +3989,12 @@ Library {
       RequestExecContextInheritance off
       System {
 	Name			"Filters/\nGDS"
-	Location		[1419, 271, 2439, 1254]
+	Location		[729, 64, 1765, 941]
 	Open			off
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"portrait"
@@ -3913,13 +4017,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag24"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3933,13 +4038,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag25"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3953,13 +4059,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag26"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3973,13 +4080,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag27"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -3993,13 +4101,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag28"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4013,13 +4122,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag29"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4033,13 +4143,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag30"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4055,6 +4166,12 @@ Library {
 	  LibraryVersion	  "1.5"
 	  SourceBlock		  "cdsInputFilter/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4069,6 +4186,12 @@ Library {
 	  LibraryVersion	  "1.8"
 	  SourceBlock		  "cdsEXC/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4129,6 +4252,12 @@ Library {
 	  LibraryVersion	  "1.9"
 	  SourceBlock		  "cdsFiltCtrl/IIR FM with control"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4189,6 +4318,12 @@ Library {
 	  LibraryVersion	  "1.15"
 	  SourceBlock		  "cdsFiltCtrl2/IIR FM with control 2"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4221,6 +4356,12 @@ Library {
 	  LibraryVersion	  "1.3"
 	  SourceBlock		  "cdsFilt/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4239,6 +4380,12 @@ Library {
 	  LibraryVersion	  "1.4"
 	  SourceBlock		  "cdsPPFIR/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4255,6 +4402,12 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsRms/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4269,6 +4422,12 @@ Library {
 	  LibraryVersion	  "1.5"
 	  SourceBlock		  "cdsTP/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4285,6 +4444,12 @@ Library {
 	  LibraryVersion	  "1.8"
 	  SourceBlock		  "cdsTrueRMS/TrueRMS"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Annotation {
 	  SID			  "334"
@@ -4308,12 +4473,12 @@ Library {
       RequestExecContextInheritance off
       System {
 	Name			"MatrixParts"
-	Location		[857, 306, 1877, 1289]
+	Location		[729, 64, 1765, 941]
 	Open			off
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"portrait"
@@ -4372,13 +4537,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag31"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4392,13 +4558,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag32"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4412,13 +4579,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag33"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4432,13 +4600,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag34"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4452,13 +4621,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag35"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4472,13 +4642,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag36"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4492,13 +4663,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag37"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4512,13 +4684,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag38"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4532,13 +4705,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag39"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -4557,6 +4731,12 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsMatrix/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4580,6 +4760,12 @@ Library {
 	  LibraryVersion	  "1.4"
 	  SourceBlock		  "cdsProduct/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4596,6 +4782,12 @@ Library {
 	  LibraryVersion	  "1.1"
 	  SourceBlock		  "cdsSubtract8/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4612,6 +4804,12 @@ Library {
 	  LibraryVersion	  "1.1"
 	  SourceBlock		  "cdsSwitch1/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Mux
@@ -4660,9 +4858,15 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsRampMuxMatrix/Subsystem"
 	  SourceType		  "SubSystem"
-	}
-	Block {
-	  BlockType		  Reference
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
+	}
+	Block {
+	  BlockType		  Reference
 	  Name			  "RampSwitch"
 	  SID			  "305"
 	  Tag			  "cdsRampSwitch"
@@ -4676,6 +4880,12 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsRampSwitch/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4692,6 +4902,12 @@ Library {
 	  LibraryVersion	  "1.6"
 	  SourceBlock		  "cdsBit2Word/cdsBit2Word"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4707,6 +4923,12 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsFiltMuxMatrix/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4723,6 +4945,12 @@ Library {
 	  LibraryVersion	  "1.3"
 	  SourceBlock		  "cdsMuxMatrix/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -4739,6 +4967,12 @@ Library {
 	  LibraryVersion	  "1.6"
 	  SourceBlock		  "cdsWord2Bit/cdsWord2Bit"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Line {
 	  ZOrder		  1
@@ -4813,12 +5047,12 @@ Library {
       RequestExecContextInheritance off
       System {
 	Name			"Osc/Phase"
-	Location		[694, 33, 1730, 1080]
-	Open			off
+	Location		[729, 64, 1765, 941]
+	Open			on
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"portrait"
@@ -4828,7 +5062,7 @@ Library {
 	TiledPaperMargins	[0.500000, 0.500000, 0.500000, 0.500000]
 	TiledPageScale		1
 	ShowPageBoundaries	off
-	ZoomFactor		"125"
+	ZoomFactor		"150"
 	SimulinkSubDomain	"Simulink"
 	Block {
 	  BlockType		  Reference
@@ -4836,12 +5070,12 @@ Library {
 	  SID			  "109"
 	  Description		  "Saturation Count"
 	  Ports			  []
-	  Position		  [227, 590, 267, 629]
+	  Position		  [227, 710, 267, 749]
 	  ZOrder		  -1
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.358"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag40"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
@@ -4862,7 +5096,7 @@ Library {
 	  BackgroundColor	  "magenta"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.358"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag41"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
@@ -4883,7 +5117,7 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.358"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag42"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
@@ -4904,7 +5138,7 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.358"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag43"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
@@ -4925,7 +5159,7 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.358"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag44"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
@@ -4946,7 +5180,7 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.358"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag45"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
@@ -4967,7 +5201,7 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.358"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
 	  UserData		  "DataTag46"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
@@ -4977,6 +5211,47 @@ Library {
 	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
+	Block {
+	  BlockType		  Reference
+	  Name			  "DocBlock7"
+	  SID			  "386"
+	  Description		  "GaussianNoiseGenerator"
+	  Ports			  []
+	  Position		  [252, 585, 292, 624]
+	  ZOrder		  12
+	  BackgroundColor	  "yellow"
+	  ShowName		  off
+	  AttributesFormatString  "%<Description>"
+	  LibraryVersion	  "1.453"
+	  UserDataPersistent	  on
+	  UserData		  "DataTag47"
+	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
+	  SourceType		  "DocBlock"
+	  SourceProductName	  "Simulink"
+	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
+	  DocumentType		  "Text"
+	}
+	Block {
+	  BlockType		  Reference
+	  Name			  "GaussianNoiseGenerator"
+	  SID			  "389"
+	  Tag			  "cdsGaussianNoiseGenerator"
+	  Ports			  [1, 1]
+	  Position		  [65, 584, 165, 626]
+	  ZOrder		  15
+	  BackgroundColor	  "[1.000000, 0.576471, 0.435294]"
+	  AttributesFormatString  "%<Tag>"
+	  LibraryVersion	  "1.4"
+	  SourceBlock		  "cdsGaussianNoiseGenerator/Subsystem"
+	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
+	}
 	Block {
 	  BlockType		  Ground
 	  Name			  "Ground"
@@ -4998,25 +5273,37 @@ Library {
 	  Position		  [5, 380, 25, 400]
 	  ZOrder		  5
 	}
+	Block {
+	  BlockType		  Ground
+	  Name			  "Ground3"
+	  SID			  "384"
+	  Position		  [20, 595, 40, 615]
+	  ZOrder		  11
+	}
 	Block {
 	  BlockType		  Reference
-	  Name			  "Noise Generator"
+	  Name			  "NoiseGeneratorName"
 	  SID			  "130"
 	  Tag			  "cdsNoise"
 	  Description		  "White Noise Generator"
 	  Ports			  [1, 1]
 	  Position		  [80, 483, 165, 527]
 	  ZOrder		  -8
-	  BackgroundColor	  "[1.000000, 0.577622, 0.434895]"
+	  BackgroundColor	  "[1.000000, 0.576471, 0.435294]"
 	  AttributesFormatString  "%<Tag>"
 	  LibraryVersion	  "1.5"
 	  SourceBlock		  "cdsNoise/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
 	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
-	  Name			  "Oscillator Fixed Phase Name"
+	  Name			  "OscillatorFixedPhaseName"
 	  SID			  "369"
 	  Tag			  "cdsOscFixedPhase"
 	  Description		  "ADL=OSC.adl"
@@ -5028,11 +5315,16 @@ Library {
 	  LibraryVersion	  "1.10"
 	  SourceBlock		  "cdsOscFixedPhase/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
 	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
-	  Name			  "Oscillator Name"
+	  Name			  "OscillatorName"
 	  SID			  "131"
 	  Tag			  "cdsOsc"
 	  Description		  "ADL=OSC.adl"
@@ -5045,11 +5337,16 @@ Library {
 	  LibraryVersion	  "1.6"
 	  SourceBlock		  "cdsOsc/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
 	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
-	  Name			  "Oscillator Set Phase Name"
+	  Name			  "OscillatorSetPhaseName"
 	  SID			  "372"
 	  Tag			  "cdsOscSetPhase"
 	  Description		  "ADL=OSC.adl"
@@ -5061,11 +5358,16 @@ Library {
 	  LibraryVersion	  "1.10"
 	  SourceBlock		  "cdsOscSetPhase/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
 	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
-	  Name			  "Phase Rotator Name"
+	  Name			  "PhaseRotatorName"
 	  SID			  "132"
 	  Tag			  "cdsPhase"
 	  Description		  "Phase Rotator"
@@ -5078,11 +5380,16 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsPhase/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
 	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
-	  Name			  "Rotator Name"
+	  Name			  "RotatorName"
 	  SID			  "133"
 	  Tag			  "cdsWfsPhase"
 	  Description		  "WFS Phase Rotator"
@@ -5095,6 +5402,11 @@ Library {
 	  LibraryVersion	  "1.2"
 	  SourceBlock		  "cdsWfsPhase/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
 	  ContentPreviewEnabled	  off
 	}
 	Block {
@@ -5104,7 +5416,7 @@ Library {
 	  Tag			  "cdsSatCount"
 	  Description		  "Saturation count"
 	  Ports			  [1, 2]
-	  Position		  [35, 563, 165, 627]
+	  Position		  [35, 683, 165, 747]
 	  ZOrder		  -12
 	  BackgroundColor	  "red"
 	  DropShadow		  on
@@ -5112,33 +5424,45 @@ Library {
 	  LibraryVersion	  "1.6"
 	  SourceBlock		  "cdsSatCount/Saturation Count Name"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
 	  ContentPreviewEnabled	  off
 	}
 	Line {
 	  ZOrder		  1
 	  SrcBlock		  "Ground"
 	  SrcPort		  1
-	  DstBlock		  "Oscillator Name"
+	  DstBlock		  "OscillatorName"
 	  DstPort		  1
 	}
 	Line {
 	  ZOrder		  2
 	  SrcBlock		  "Ground1"
 	  SrcPort		  1
-	  DstBlock		  "Noise Generator"
+	  DstBlock		  "NoiseGeneratorName"
 	  DstPort		  1
 	}
 	Line {
 	  ZOrder		  3
 	  SrcBlock		  "Ground2"
 	  SrcPort		  1
-	  DstBlock		  "Oscillator Fixed Phase Name"
+	  DstBlock		  "OscillatorFixedPhaseName"
+	  DstPort		  1
+	}
+	Line {
+	  ZOrder		  8
+	  SrcBlock		  "Ground3"
+	  SrcPort		  1
+	  DstBlock		  "GaussianNoiseGenerator"
 	  DstPort		  1
 	}
 	Annotation {
 	  SID			  "342"
 	  Name			  "RCG OSC/Phase Parts Library"
-	  Position		  [70, 11, 294, 31]
+	  Position		  [70, 11, 294, 38]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -1
 	  FontName		  "times"
@@ -5158,12 +5482,12 @@ Library {
       RequestExecContextInheritance off
       System {
 	Name			"RT Links"
-	Location		[857, 306, 1877, 1289]
+	Location		[729, 64, 1765, 941]
 	Open			off
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"landscape"
@@ -5186,13 +5510,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag47"
+	  UserData		  "DataTag48"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5206,13 +5531,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag48"
+	  UserData		  "DataTag49"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5226,13 +5552,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag49"
+	  UserData		  "DataTag50"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5247,6 +5574,12 @@ Library {
 	  LibraryVersion	  "1.7"
 	  SourceBlock		  "cdsGps/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -5260,6 +5593,12 @@ Library {
 	  LibraryVersion	  "1.1"
 	  SourceBlock		  "cdsModelRate/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -5274,6 +5613,12 @@ Library {
 	  LibraryVersion	  "1.4"
 	  SourceBlock		  "cdsStateWord/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
       }
     }
@@ -5288,12 +5633,12 @@ Library {
       RequestExecContextInheritance off
       System {
 	Name			"WatchDogs"
-	Location		[1319, 176, 2347, 1191]
+	Location		[729, 64, 1765, 941]
 	Open			off
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"portrait"
@@ -5321,6 +5666,12 @@ Library {
 	  FontSize		  12
 	  SourceBlock		  "cdsDacKill/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -5337,6 +5688,12 @@ Library {
 	  LibraryVersion	  "1.3"
 	  SourceBlock		  "cdsDacKillIop/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -5352,6 +5709,12 @@ Library {
 	  LibraryVersion	  "1.3"
 	  SourceBlock		  "cdsDacKillTimed/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -5364,13 +5727,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag50"
+	  UserData		  "DataTag51"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5384,13 +5748,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag51"
+	  UserData		  "DataTag52"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5404,13 +5769,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag52"
+	  UserData		  "DataTag53"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5424,13 +5790,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag53"
+	  UserData		  "DataTag54"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5444,13 +5811,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag54"
+	  UserData		  "DataTag55"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5464,13 +5832,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag55"
+	  UserData		  "DataTag56"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5484,13 +5853,14 @@ Library {
 	  BackgroundColor	  "yellow"
 	  ShowName		  off
 	  AttributesFormatString  "%<Description>"
-	  LibraryVersion	  "1.281"
+	  LibraryVersion	  "1.453"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag56"
+	  UserData		  "DataTag57"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
 	  SourceProductBaseCode	  "SL"
+	  ContentPreviewEnabled	  off
 	  DocumentType		  "Text"
 	}
 	Block {
@@ -5508,6 +5878,12 @@ Library {
 	  LibraryVersion	  "1.4"
 	  SourceBlock		  "cdsHWWD/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -5524,6 +5900,12 @@ Library {
 	  LibraryVersion	  "1.1"
 	  SourceBlock		  "cdsSusWd/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -5537,6 +5919,12 @@ Library {
 	  LibraryVersion	  "1.7"
 	  SourceBlock		  "SUS_IOP_WD/WD"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -5550,6 +5938,12 @@ Library {
 	  LibraryVersion	  "1.11"
 	  SourceBlock		  "SUS_IOP_WD_2_DC_RMS/WD"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
 	Block {
 	  BlockType		  Reference
@@ -5565,6 +5959,12 @@ Library {
 	  LibraryVersion	  "1.3"
 	  SourceBlock		  "cdsWD/Subsystem"
 	  SourceType		  "SubSystem"
+	  ShowPortLabels	  "FromPortIcon"
+	  SystemSampleTime	  "-1"
+	  GeneratePreprocessorConditionals off
+	  AllowZeroVariantControls off
+	  PropagateVariantConditions off
+	  ContentPreviewEnabled	  off
 	}
       }
     }
@@ -5584,7 +5984,7 @@ Library {
 	PortBlocksUseCompactNotation off
 	SetExecutionDomain	off
 	ExecutionDomainType	"Deduce"
-	ModelBrowserVisibility	off
+	ModelBrowserVisibility	on
 	ModelBrowserWidth	200
 	ScreenColor		"white"
 	PaperOrientation	"portrait"
@@ -5688,7 +6088,7 @@ Library {
 	  AttributesFormatString  "%<Description>"
 	  LibraryVersion	  "1.281"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag57"
+	  UserData		  "DataTag58"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
@@ -5708,7 +6108,7 @@ Library {
 	  AttributesFormatString  "%<Description>"
 	  LibraryVersion	  "1.281"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag58"
+	  UserData		  "DataTag59"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
@@ -5728,7 +6128,7 @@ Library {
 	  AttributesFormatString  "%<Description>"
 	  LibraryVersion	  "1.281"
 	  UserDataPersistent	  on
-	  UserData		  "DataTag59"
+	  UserData		  "DataTag60"
 	  SourceBlock		  "simulink/Model-Wide\nUtilities/DocBlock"
 	  SourceType		  "DocBlock"
 	  SourceProductName	  "Simulink"
@@ -5893,7 +6293,7 @@ Library {
 	Annotation {
 	  SID			  "343"
 	  Name			  "MUXs"
-	  Position		  [156, 548, 215, 574]
+	  Position		  [156, 548, 215, 581]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -1
 	  FontSize		  24
@@ -5901,7 +6301,7 @@ Library {
 	Annotation {
 	  SID			  "344"
 	  Name			  "BUS CREATOR"
-	  Position		  [246, 553, 366, 573]
+	  Position		  [246, 553, 366, 578]
 	  InternalMargins	  [0, 0, 0, 0]
 	  ZOrder		  -2
 	  FontSize		  18
@@ -5965,7 +6365,7 @@ Library {
       SID		      "364"
       Name		      "Note: \nIn V2.8 and later:\nBIQUAD IIR filter algorithm set \nas default.\nshmem_daq=1 set as defau"
       "lt, so no\nlonger a required setting.\n"
-      Position		      [22, 297, 222, 369]
+      Position		      [22, 297, 222, 404]
       InternalMargins	      [0, 0, 0, 0]
       ZOrder		      -1
       FontWeight	      "bold"
@@ -5974,7 +6374,7 @@ Library {
       SID		      "345"
       Name		      "One cdsParameters block is\nrequired per User Model.\nPart is shown with the 6\nrequired fields. Ad"
       "ditional\noptions described in DOC block. "
-      Position		      [25, 95, 219, 147]
+      Position		      [25, 95, 219, 167]
       InternalMargins	      [0, 0, 0, 0]
       ZOrder		      -2
     }
@@ -5982,7 +6382,7 @@ Library {
       SID		      "346"
       Name		      "Matlab Parts Library for Use with aLIGO Real-time Code Generator - V4\nDefault Matlab Version is no"
       "w 2019a"
-      Position		      [63, 11, 595, 49]
+      Position		      [63, 11, 595, 63]
       InternalMargins	      [0, 0, 0, 0]
       ZOrder		      -3
       FontName		      "times"
@@ -5991,7 +6391,7 @@ Library {
   }
 }
 MatData {
-  NumRecords		  60
+  NumRecords		  61
   DataRecord {
     Tag			    DataTag0
     Data		    "  %)30     .    ^ 0   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
@@ -6846,6 +7246,26 @@ MatData {
   }
   DataRecord {
     Tag			    DataTag47
+    Data		    "  %)30     .    4 4   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
+    "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
+    "PX   \" !   !@    @    $          4    (     0   $T$   !         !    !-!   1V%U<W-I86Y.;VES94=E;F5R871O<CH*/3T]/3"
+    "T]/3T]/3T]/3T]\"E1H:7,@8FQO8VL@9V5N97)A=&5S(&$@<F%N9&]M(&YU;6)E<B!F<F]M(&$@;F]R;6%L(&1I<W1R:6)U=&EO;B!W:71H(&$@\"F"
+    "UE86X@;V8@,\"P@86YD(&$@<W1A;F1A<F0@9&5V:6%T:6]N(&]F(#$N\"@I5<V%G93H*0V]N;F5C=\"!T:&4@;W5T<'5T(\"=.;VES92<@=&\\@=&A"
+    "E(&1E<VER960@4D-'('!A<G0L(&=E;F5R86QL>2!A(&9I;'1E<B!B86YK\"G1O(&]F9G-E=\"P@<V-A;&4L(&%N9\"!O=&AE<G=I<V4@<VAA<&4@=&"
+    "AE(&]U='!U=\"!N;VES92X*\"D]P97)A=&EO;CH*5&AI<R!B;&]C:R!U=&EL:7IE<R!A('-L:6=H=&QY('-T<FEP<&5D(&1O=VX@=F5R<VEO;B!O9B"
+    "!T:&4@<6YO<FTH*2 *9G5N8W1I;VX@9&5F:6YE9\"!B>2!T:&4@4B!P<F]J96-T+@IH='1P<SHO+W-V;BYR+7!R;VIE8W0N;W)G+U(O=')U;FLO<W)"
+    "C+VYM871H+W%N;W)M+F,*\"E1H92!M971H;V0@=7-E9\"!I<R!I;G9E<G-E('1R86YS9F]R;2!S86UP;&EN9R!T;R!G96YE<F%T92!G875S<VEA;B!"
+    "N;VES92X*\"E1H:7,@8FQO8VL@=71I;&EZ97,@9V5T7W)A;F1O;5]B>71E<R@I(&9R;VT@=&AE(#QL:6YU>\"]R86YD;VTN:#XL( IK97)N96P@:&5"
+    "A9&5R+\"!T:&ES('!R;W9I9&5S(#8T(&)I=',@;V8@96YT<F]P>2!U<V5D('1O('-A;7!L92!T:&4@:6YV97)S92 *=')A;G-F;W)M('=I=&@N\"@I"
+    "%86-H(&EN<W1A;F-E(&]F('1H:7,@8FQO8VL@8V%L;',@=&AE('-A;64@:6YL:6YE(&9U;F-T:6]N('1O(&=E=\" *=&AE(&YE>'0@<F%N9&]M(&1O"
+    "=6)L92!S86UP;&5D(&9R;VT@=&AE(&1I<W1R:6)U=&EO;BX*\"E)%1D5214Y#10H@\"D)E87-L97DL($HN($0N(&%N9\"!3+B!'+B!3<')I;F=E<B "
+    "H,3DW-RDN\"D%L9V]R:71H;2!!4R Q,3$Z(%1H92!P97)C96YT86=E('!O:6YT<R!O9B!T:&4@;F]R;6%L(&1I<W1R:6)U=&EO;BP*07!P;&EE9\"!"
+    "3=&%T:7-T:6-S+\" R-BP@,3$X+3$R,2X*( I7:6-H=7)A+\"!-+DHN(\"@Q.3@X*2X*06QG;W)I=&AM($%3(#(T,3H@5&AE(%!E<F-E;G1A9V4@4&"
+    "]I;G1S(&]F('1H92!.;W)M86P@1&ES=')I8G5T:6]N+@I!<'!L:65D(%-T871I<W1I8W,L(#,W+\" T-S<M-#@T+@H*    #@   #     &    \" "
+    "    0         !0    @    !     P    $         $  # %185  "
+  }
+  DataRecord {
+    Tag			    DataTag48
     Data		    "  %)30     .    6 $   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
     "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
     "PX   \"(    !@    @    $          4    (     0   %4    !         !    !5    1U!3#0HZ#0H]/3T]#0H-\"E1H:7,@<&%R=\"!O"
@@ -6853,7 +7273,7 @@ MatData {
     "  4    (     0    ,    !         !   P!46%0 "
   }
   DataRecord {
-    Tag			    DataTag48
+    Tag			    DataTag49
     Data		    "  %)30     .    @ ,   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
     "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
     "PX   \"P @  !@    @    $          4    (     0   'H\"   !         !    !Z @  4U1!5$573U)$#0HZ#0H]/3T]#0H-\"E1O('!R"
@@ -6867,7 +7287,7 @@ MatData {
     "P@87,@8GD@1&%T879I97=E<BX-\"@        X    P    !@    @    $          4    (     0    ,    !         !   P!46%0 "
   }
   DataRecord {
-    Tag			    DataTag49
+    Tag			    DataTag50
     Data		    "  %)30     .    0 $   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
     "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
     "PX   !P    !@    @    $          4    (     0   #H    !         !     Z    1U!3#0HZ#0H]/3T]#0H-\"E1H:7,@<&%R=\"!O="
@@ -6875,7 +7295,7 @@ MatData {
     "  P!46%0 "
   }
   DataRecord {
-    Tag			    DataTag50
+    Tag			    DataTag51
     Data		    "  %)30     .    V $   8    (     @         %    \"     $    !     0         %  0 \"     $    0    =F5R<"
     "VEO;@!C;VYT96YT  X    X    !@    @    &          4    (     0    $    !          D    (    FIF9F9F9\\3\\.    2 $  "
     " 8    (    !          %    \"     $    1 0   0         0    $0$  &-D<U-U<U=D.@T*/3T]/3T]/3T]#0H-\"E1H:7,@9G5N8W1I;"
@@ -6884,7 +7304,7 @@ MatData {
     "G1E<F9E<F]M971E<BDN#0H-\"E1H:7,@8FQO8VL@<VAO=6QD(&YO=\"!B92!U<V5D(&EN(&%N>2!N97<@9&5S:6=N<RX-\"@         "
   }
   DataRecord {
-    Tag			    DataTag51
+    Tag			    DataTag52
     Data		    "  %)30     .      <   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
     "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
     "PX    P!@  !@    @    $          4    (     0   /\\%   !         !    #_!0  8V1S5V%T8VAD;V<Z#0H]/3T]/3T-\"@T*5&AI<"
@@ -6909,7 +7329,7 @@ MatData {
     "T('-I9VYA;',N#0H #@   #     &    \"     0         !0    @    !     P    $         $  # %185  "
   }
   DataRecord {
-    Tag			    DataTag52
+    Tag			    DataTag53
     Data		    "  %)30     .    \" 8   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R"
     "<VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S"
     "/PX    X!0  !@    @    $          4    (     0    0%   !         !     $!0  8V1S5T0Z#0H]/3T]/3T-\"@T*5&AI<R!B;&]C:"
@@ -6931,7 +7351,7 @@ MatData {
     "T97(N( T*      X    P    !@    @    $          4    (     0    ,    !         !   P!46%0 "
   }
   DataRecord {
-    Tag			    DataTag53
+    Tag			    DataTag54
     Data		    "  %)30     .    D 0   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
     "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
     "PX   #  P  !@    @    $          4    (     0   (P#   !         !    \", P  8V1S1&%Q2VEL;#H-\"CT]/3T]/0T*#0I4:&4@8"
@@ -6949,7 +7369,7 @@ MatData {
     " @    !     P    $         $  # %185  "
   }
   DataRecord {
-    Tag			    DataTag54
+    Tag			    DataTag55
     Data		    "  %)30     .    > 4   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
     "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
     "PX   \"H!   !@    @    $          4    (     0   '@$   !         !    !X!   8V1S1&%C2VEL;$EO<#H-\"CT]/3T]/0T*#0I4:"
@@ -6970,7 +7390,7 @@ MatData {
     "  P!46%0 "
   }
   DataRecord {
-    Tag			    DataTag55
+    Tag			    DataTag56
     Data		    "  %)30     .    6 (   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
     "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
     "PX   \"( 0  !@    @    $          4    (     0   %0!   !         !    !4 0  8V1S5T0R.@T*/3T]/3T]#0H-\"E1H:7,@8FQO8"
@@ -6981,7 +7401,7 @@ MatData {
     "          %    \"     $    #     0         0  , 5%A4  "
   }
   DataRecord {
-    Tag			    DataTag56
+    Tag			    DataTag57
     Data		    "  %)30     .    : 4   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
     "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
     "PX   \"8!   !@    @    $          4    (     0   &0$   !         !    !D!   8V1S1&%C2VEL;%1I;65D.@T*/3T]/3T]#0H-\""
@@ -7001,14 +7421,14 @@ MatData {
     "7!A<W-I;F<B#0H     #@   #     &    \"     0         !0    @    !     P    $         $  # %185  "
   }
   DataRecord {
-    Tag			    DataTag57
+    Tag			    DataTag58
     Data		    "  %)30     .    * $   8    (     @         %    \"     $    !     0         %  0 \"     $    0    =F5R<"
     "VEO;@!C;VYT96YT  X    X    !@    @    &          4    (     0    $    !          D    (    FIF9F9F9\\3\\.    F    "
     " 8    (    !          %    \"     $   !G     0         0    9P   %5N:71$96QA>3H-\"CT]/3T]/3T]/3T-\"@T*5&AI<R!B;&]C"
     ":R!I<R!U<V5D(&9E960@8F%C:R!V86QU97,@;VX@=&AE(&YE>'0@8V]D92!C>6-L92!O9B!T:&4@<V]F='=A<F4N#0H "
   }
   DataRecord {
-    Tag			    DataTag58
+    Tag			    DataTag59
     Data		    "  %)30     .    D \\   8    (     @         %    \"     $    !     0         %  0 \"     $    0    =F5R"
     "<VEO;@!C;VYT96YT  X    X    !@    @    &          4    (     0    $    !          D    (    FIF9F9F9\\3\\.      \\"
     "   8    (    !          %    \"     $   !F!P   0         1    S X  $T 80!T &@ 1@!U &X 8P!T &D ;P!N #H #0 * #T /0 ]"
@@ -7060,7 +7480,7 @@ MatData {
     " ( !B &4 ( !S &4 =  @ '0 ;P @ 'H 90!R &\\ +@ -  H       "
   }
   DataRecord {
-    Tag			    DataTag59
+    Tag			    DataTag60
     Data		    "  %)30     .    P D   8    (     @         %    \"     $    !     0         %  0 \"     $    8    =F5R<"
     "VEO;@!C;VYT96YT &9O<FUA=   #@   #@    &    \"     8         !0    @    !     0    $         \"0    @    S,S,S,S/S/"
     "PX   #P\"   !@    @    $          4    (     0   +D(   !         !    \"Y\"   1F-N.@T*/3T]/0T*#0I4:&ES(&UO9'5L92!I"
diff --git a/src/epics/simLink/lib/cdsGaussianNoiseGenerator.mdl b/src/epics/simLink/lib/cdsGaussianNoiseGenerator.mdl
new file mode 100644
index 0000000000000000000000000000000000000000..a2bab3abfaedaa81be9a13e2e16cf87078c8a84e
--- /dev/null
+++ b/src/epics/simLink/lib/cdsGaussianNoiseGenerator.mdl
@@ -0,0 +1,1145 @@
+Library {
+  Name			  "cdsGaussianNoise"
+  Version		  9.3
+  SavedCharacterEncoding  "UTF-8"
+  DiagnosticSuppressor	  "on"
+  SLCCPlugin		  "on"
+  WebScopes_FoundationPlugin "on"
+  LogicAnalyzerPlugin	  "on"
+  NotesPlugin		  "on"
+  LibraryType		  "BlockLibrary"
+  EnableAccessToBaseWorkspace on
+  ScopeRefreshTime	  0.035000
+  OverrideScopeRefreshTime on
+  DisableAllScopes	  off
+  FPTRunName		  "Run 1"
+  MaxMDLFileLineLength	  120
+  LastSavedArchitecture	  "glnxa64"
+  Object {
+    $PropName		    "BdWindowsInfo"
+    $ObjectID		    1
+    $ClassName		    "Simulink.BDWindowsInfo"
+    Object {
+      $PropName		      "WindowsInfo"
+      $ObjectID		      2
+      $ClassName	      "Simulink.WindowInfo"
+      IsActive		      [1]
+      Location		      [117.0, 61.0, 716.0, 564.0]
+      Object {
+	$PropName		"ModelBrowserInfo"
+	$ObjectID		3
+	$ClassName		"Simulink.ModelBrowserInfo"
+	Visible			[1]
+	DockPosition		"Left"
+	Width			[50]
+	Height			[50]
+	Filter			[9]
+	Minimized		"On"
+      }
+      Object {
+	$PropName		"ExplorerBarInfo"
+	$ObjectID		4
+	$ClassName		"Simulink.ExplorerBarInfo"
+	Visible			[1]
+      }
+      Object {
+	$PropName		"EditorsInfo"
+	$ObjectID		5
+	$ClassName		"Simulink.EditorInfo"
+	IsActive		[1]
+	ViewObjType		"SimulinkTopLevel"
+	LoadSaveID		"0"
+	Extents			[592.0, 374.0]
+	ZoomFactor		[1.0]
+	Offset			[0.0, 0.0]
+      }
+      Object {
+	$PropName		"DockComponentsInfo"
+	$ObjectID		6
+	$ClassName		"Simulink.DockComponentInfo"
+	Type			"GLUE2:PropertyInspector"
+	ID			"Property Inspector"
+	Visible			[1]
+	CreateCallback		""
+	UserData		""
+	Floating		[0]
+	DockPosition		"Right"
+	Width			[640]
+	Height			[480]
+	Minimized		"On"
+      }
+      WindowState	      "AAAA/wAAAAD9AAAAAgAAAAAAAAC9AAAB+PwCAAAAA/sAAAAWAEQAbwBjAGsAVwBpAGQAZwBlAHQAMwEAAAAxAAAB+AAAA"
+      "AAAAAAA+wAAABYARABvAGMAawBXAGkAZABnAGUAdAA0AAAAAAD/////AAAAAAAAAAD7AAAAUgBHAEwAVQBFADIAIAB0AHIAZQBlACAAYwBvAG0Ac"
+      "ABvAG4AZQBuAHQALwBHAEwAVQBFADIAIAB0AHIAZQBlACAAYwBvAG0AcABvAG4AZQBuAHQAAAAAAP////8AAACAAP///wAAAAEAAAAAAAAAAPwCA"
+      "AAAAfsAAABUAEcATABVAEUAMgA6AFAAcgBvAHAAZQByAHQAeQBJAG4AcwBwAGUAYwB0AG8AcgAvAFAAcgBvAHAAZQByAHQAeQAgAEkAbgBzAHAAZ"
+      "QBjAHQAbwByAAAAAAD/////AAABrAD///8AAAJ2AAABtwAAAAEAAAACAAAAAQAAAAL8AAAABAAAAAAAAAABAAAANgBjAG8AbABsAGEAcABzAGkAY"
+      "gBsAGUAUABhAG4AZQBsAFQAbwBvAGwAQgBhAHIATABlAGYAdAMAAAAA/////wAAAAAAAAAAAAAAAQAAAAEAAAA4AGMAbwBsAGwAYQBwAHMAaQBiA"
+      "GwAZQBQAGEAbgBlAGwAVABvAG8AbABCAGEAcgBSAGkAZwBoAHQDAAAAAP////8AAAAAAAAAAAAAAAIAAAAP/////wAAAAAA/////wAAAAAAAAAA/"
+      "////wEAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/"
+      "////wEAAACK/////wAAAAAAAAAA/////wEAAADy/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/"
+      "////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAA/////wEAAAFK/////wAAAAAAAAAA/"
+      "////wEAAAGB/////wAAAAAAAAAA/////wAAAAAA/////wAAAAAAAAAAAAAAAwAAAAEAAAA6AGMAbwBsAGwAYQBwAHMAaQBiAGwAZQBQAGEAbgBlA"
+      "GwAVABvAG8AbABCAGEAcgBCAG8AdAB0AG8AbQAAAAAA/////wAAAAAAAAAA"
+    }
+  }
+  HideAutomaticNames	  on
+  Created		  "Mon Apr 11 16:37:21 2022"
+  Creator		  "ezekiel.dohmen"
+  UpdateHistory		  "UpdateHistoryNever"
+  ModifiedByFormat	  "%<Auto>"
+  LastModifiedBy	  "ezekiel.dohmen"
+  ModifiedDateFormat	  "%<Auto>"
+  LastModifiedDate	  "Tue Apr 12 09:53:07 2022"
+  RTWModifiedTimeStamp	  571657983
+  ModelVersionFormat	  "1.%<AutoIncrement:4>"
+  SampleTimeColors	  off
+  SampleTimeAnnotations	  off
+  LibraryLinkDisplay	  "disabled"
+  WideLines		  off
+  ShowLineDimensions	  off
+  ShowPortDataTypes	  off
+  ShowAllPropagatedSignalLabels	off
+  PortDataTypeDisplayFormat "AliasTypeOnly"
+  ShowEditTimeErrors	  on
+  ShowEditTimeWarnings	  on
+  ShowEditTimeAdvisorChecks off
+  ShowPortUnits		  off
+  ShowDesignRanges	  off
+  ShowLoopsOnError	  on
+  IgnoreBidirectionalLines off
+  ShowStorageClass	  off
+  ShowTestPointIcons	  on
+  ShowSignalResolutionIcons on
+  ShowViewerIcons	  on
+  SortedOrder		  off
+  VariantCondition	  off
+  ShowSubsystemDomainSpec off
+  ExecutionContextIcon	  off
+  ShowLinearizationAnnotations on
+  ShowVisualizeInsertedRTB on
+  ShowMarkup		  on
+  BlockNameDataTip	  off
+  BlockParametersDataTip  off
+  BlockDescriptionStringDataTip	off
+  BlockVariantConditionDataTip off
+  ToolBar		  on
+  StatusBar		  on
+  BrowserShowLibraryLinks off
+  FunctionConnectors	  off
+  BrowserLookUnderMasks	  off
+  MultiThreadCoSim	  on
+  SimulationMode	  "normal"
+  PauseTimes		  "5"
+  NumberOfSteps		  1
+  SnapshotBufferSize	  10
+  SnapshotInterval	  10
+  NumberOfLastSnapshots	  0
+  LinearizationMsg	  "none"
+  Profile		  off
+  ParamWorkspaceSource	  "MATLABWorkspace"
+  ExtModeBatchMode	  off
+  ExtModeEnableFloating	  on
+  ExtModeTrigType	  "manual"
+  ExtModeTrigMode	  "normal"
+  ExtModeTrigPort	  "1"
+  ExtModeTrigElement	  "any"
+  ExtModeTrigDuration	  1000
+  ExtModeTrigDurationFloating "auto"
+  ExtModeTrigHoldOff	  0
+  ExtModeTrigDelay	  0
+  ExtModeTrigDirection	  "rising"
+  ExtModeTrigLevel	  0
+  ExtModeArchiveMode	  "off"
+  ExtModeAutoIncOneShot	  off
+  ExtModeIncDirWhenArm	  off
+  ExtModeAddSuffixToVar	  off
+  ExtModeWriteAllDataToWs off
+  ExtModeArmWhenConnect	  on
+  ExtModeSkipDownloadWhenConnect off
+  ExtModeLogAll		  on
+  ExtModeAutoUpdateStatusClock on
+  ShowModelReferenceBlockVersion off
+  ShowModelReferenceBlockIO off
+  OrderedModelArguments	  on
+  Array {
+    Type		    "Handle"
+    Dimension		    1
+    Simulink.ConfigSet {
+      $ObjectID		      7
+      Version		      "19.0.0"
+      DisabledProps	      []
+      Description	      ""
+      Array {
+	Type			"Handle"
+	Dimension		10
+	Simulink.SolverCC {
+	  $ObjectID		  8
+	  Version		  "19.0.0"
+	  DisabledProps		  []
+	  Description		  ""
+	  Components		  []
+	  StartTime		  "0.0"
+	  StopTime		  "10.0"
+	  AbsTol		  "auto"
+	  AutoScaleAbsTol	  on
+	  FixedStep		  "auto"
+	  InitialStep		  "auto"
+	  MaxOrder		  5
+	  ZcThreshold		  "auto"
+	  ConsecutiveZCsStepRelTol "10*128*eps"
+	  MaxConsecutiveZCs	  "1000"
+	  ExtrapolationOrder	  4
+	  NumberNewtonIterations  1
+	  MaxStep		  "auto"
+	  MinStep		  "auto"
+	  MaxConsecutiveMinStep	  "1"
+	  RelTol		  "1e-3"
+	  EnableMultiTasking	  off
+	  ConcurrentTasks	  off
+	  Solver		  "VariableStepAuto"
+	  SolverName		  "VariableStepAuto"
+	  SolverJacobianMethodControl "auto"
+	  ShapePreserveControl	  "DisableAll"
+	  ZeroCrossControl	  "UseLocalSettings"
+	  ZeroCrossAlgorithm	  "Nonadaptive"
+	  AlgebraicLoopSolver	  "TrustRegion"
+	  SolverInfoToggleStatus  off
+	  IsAutoAppliedInSIP	  off
+	  SolverResetMethod	  "Fast"
+	  PositivePriorityOrder	  off
+	  AutoInsertRateTranBlk	  off
+	  SampleTimeConstraint	  "Unconstrained"
+	  InsertRTBMode		  "Whenever possible"
+	  SampleTimeProperty	  []
+	  DecoupledContinuousIntegration off
+	  MinimalZcImpactIntegration off
+	  SolverOrder		  3
+	}
+	Simulink.DataIOCC {
+	  $ObjectID		  9
+	  Version		  "19.0.0"
+	  DisabledProps		  []
+	  Description		  ""
+	  Components		  []
+	  Decimation		  "1"
+	  ExternalInput		  "[t, u]"
+	  FinalStateName	  "xFinal"
+	  InitialState		  "xInitial"
+	  LimitDataPoints	  off
+	  MaxDataPoints		  "1000"
+	  LoadExternalInput	  off
+	  LoadInitialState	  off
+	  SaveFinalState	  off
+	  SaveOperatingPoint	  off
+	  SaveFormat		  "Dataset"
+	  SignalLoggingSaveFormat "Dataset"
+	  SaveOutput		  on
+	  SaveState		  off
+	  SignalLogging		  on
+	  DSMLogging		  on
+	  InspectSignalLogs	  off
+	  VisualizeSimOutput	  on
+	  StreamToWorkspace	  off
+	  StreamVariableName	  "streamout"
+	  SaveTime		  on
+	  ReturnWorkspaceOutputs  on
+	  StateSaveName		  "xout"
+	  TimeSaveName		  "tout"
+	  OutputSaveName	  "yout"
+	  SignalLoggingName	  "logsout"
+	  DSMLoggingName	  "dsmout"
+	  OutputOption		  "RefineOutputTimes"
+	  OutputTimes		  "[]"
+	  ReturnWorkspaceOutputsName "out"
+	  Refine		  "1"
+	  LoggingToFile		  off
+	  DatasetSignalFormat	  "timeseries"
+	  LoggingFileName	  "out.mat"
+	  LoggingIntervals	  "[-inf, inf]"
+	}
+	Simulink.OptimizationCC {
+	  $ObjectID		  10
+	  Version		  "19.0.0"
+	  Array {
+	    Type		    "Cell"
+	    Dimension		    8
+	    Cell		    "BooleansAsBitfields"
+	    Cell		    "PassReuseOutputArgsAs"
+	    Cell		    "PassReuseOutputArgsThreshold"
+	    Cell		    "ZeroExternalMemoryAtStartup"
+	    Cell		    "ZeroInternalMemoryAtStartup"
+	    Cell		    "OptimizeModelRefInitCode"
+	    Cell		    "NoFixptDivByZeroProtection"
+	    Cell		    "UseSpecifiedMinMax"
+	    PropName		    "DisabledProps"
+	  }
+	  Description		  ""
+	  Components		  []
+	  BlockReduction	  on
+	  BooleanDataType	  on
+	  ConditionallyExecuteInputs on
+	  DefaultParameterBehavior "Tunable"
+	  UseDivisionForNetSlopeComputation "off"
+	  GainParamInheritBuiltInType off
+	  UseFloatMulNetSlope	  off
+	  DefaultUnderspecifiedDataType	"double"
+	  UseSpecifiedMinMax	  off
+	  InlineInvariantSignals  off
+	  OptimizeBlockIOStorage  on
+	  BufferReuse		  on
+	  EnhancedBackFolding	  off
+	  CachingGlobalReferences off
+	  GlobalBufferReuse	  on
+	  StrengthReduction	  off
+	  AdvancedOptControl	  ""
+	  ExpressionFolding	  on
+	  BooleansAsBitfields	  off
+	  BitfieldContainerType	  "uint_T"
+	  EnableMemcpy		  on
+	  MemcpyThreshold	  64
+	  PassReuseOutputArgsAs	  "Structure reference"
+	  PassReuseOutputArgsThreshold 12
+	  ExpressionDepthLimit	  128
+	  LocalBlockOutputs	  on
+	  RollThreshold		  5
+	  StateBitsets		  off
+	  DataBitsets		  off
+	  ActiveStateOutputEnumStorageType "Native Integer"
+	  ZeroExternalMemoryAtStartup on
+	  ZeroInternalMemoryAtStartup on
+	  InitFltsAndDblsToZero	  off
+	  NoFixptDivByZeroProtection off
+	  EfficientFloat2IntCast  off
+	  EfficientMapNaN2IntZero on
+	  LifeSpan		  "auto"
+	  MaxStackSize		  "Inherit from target"
+	  BufferReusableBoundary  on
+	  SimCompilerOptimization "off"
+	  AccelVerboseBuild	  off
+	  OptimizeBlockOrder	  "off"
+	  OptimizeDataStoreBuffers on
+	  BusAssignmentInplaceUpdate on
+	  DifferentSizesBufferReuse off
+	  OptimizationLevel	  "level2"
+	  OptimizationPriority	  "Balanced"
+	  OptimizationCustomize	  on
+	  UseRowMajorAlgorithm	  off
+	  LabelGuidedReuse	  off
+	  MultiThreadedLoops	  off
+	  DenormalBehavior	  "GradualUnderflow"
+	}
+	Simulink.DebuggingCC {
+	  $ObjectID		  11
+	  Version		  "19.0.0"
+	  Array {
+	    Type		    "Cell"
+	    Dimension		    1
+	    Cell		    "UseOnlyExistingSharedCode"
+	    PropName		    "DisabledProps"
+	  }
+	  Description		  ""
+	  Components		  []
+	  RTPrefix		  "error"
+	  ConsistencyChecking	  "none"
+	  ArrayBoundsChecking	  "none"
+	  SignalInfNanChecking	  "none"
+	  StringTruncationChecking "error"
+	  SignalRangeChecking	  "none"
+	  ReadBeforeWriteMsg	  "UseLocalSettings"
+	  WriteAfterWriteMsg	  "UseLocalSettings"
+	  WriteAfterReadMsg	  "UseLocalSettings"
+	  AlgebraicLoopMsg	  "warning"
+	  ArtificialAlgebraicLoopMsg "warning"
+	  SaveWithDisabledLinksMsg "warning"
+	  SaveWithParameterizedLinksMsg	"warning"
+	  CheckSSInitialOutputMsg on
+	  UnderspecifiedInitializationDetection	"Simplified"
+	  MergeDetectMultiDrivingBlocksExec "error"
+	  CheckExecutionContextPreStartOutputMsg off
+	  CheckExecutionContextRuntimeOutputMsg	off
+	  SignalResolutionControl "UseLocalSettings"
+	  BlockPriorityViolationMsg "warning"
+	  MinStepSizeMsg	  "warning"
+	  TimeAdjustmentMsg	  "none"
+	  MaxConsecutiveZCsMsg	  "error"
+	  MaskedZcDiagnostic	  "warning"
+	  IgnoredZcDiagnostic	  "warning"
+	  SolverPrmCheckMsg	  "none"
+	  InheritedTsInSrcMsg	  "warning"
+	  MultiTaskDSMMsg	  "error"
+	  MultiTaskCondExecSysMsg "error"
+	  MultiTaskRateTransMsg	  "error"
+	  SingleTaskRateTransMsg  "none"
+	  TasksWithSamePriorityMsg "warning"
+	  ExportedTasksRateTransMsg "none"
+	  SigSpecEnsureSampleTimeMsg "warning"
+	  CheckMatrixSingularityMsg "none"
+	  IntegerOverflowMsg	  "warning"
+	  Int32ToFloatConvMsg	  "warning"
+	  ParameterDowncastMsg	  "error"
+	  ParameterOverflowMsg	  "error"
+	  ParameterUnderflowMsg	  "none"
+	  ParameterPrecisionLossMsg "warning"
+	  ParameterTunabilityLossMsg "warning"
+	  FixptConstUnderflowMsg  "none"
+	  FixptConstOverflowMsg	  "none"
+	  FixptConstPrecisionLossMsg "none"
+	  UnderSpecifiedDataTypeMsg "none"
+	  UnnecessaryDatatypeConvMsg "none"
+	  VectorMatrixConversionMsg "none"
+	  InvalidFcnCallConnMsg	  "error"
+	  FcnCallInpInsideContextMsg "error"
+	  SignalLabelMismatchMsg  "none"
+	  UnconnectedInputMsg	  "warning"
+	  UnconnectedOutputMsg	  "warning"
+	  UnconnectedLineMsg	  "warning"
+	  UseOnlyExistingSharedCode "error"
+	  SFcnCompatibilityMsg	  "none"
+	  FrameProcessingCompatibilityMsg "error"
+	  UniqueDataStoreMsg	  "none"
+	  BusObjectLabelMismatch  "warning"
+	  RootOutportRequireBusObject "warning"
+	  AssertControl		  "UseLocalSettings"
+	  AllowSymbolicDim	  on
+	  RowMajorDimensionSupport off
+	  ModelReferenceIOMsg	  "none"
+	  ModelReferenceMultiInstanceNormalModeStructChecksumCheck "error"
+	  ModelReferenceVersionMismatchMessage "none"
+	  ModelReferenceIOMismatchMessage "none"
+	  UnknownTsInhSupMsg	  "warning"
+	  ModelReferenceDataLoggingMessage "warning"
+	  ModelReferenceSymbolNameMessage "warning"
+	  ModelReferenceExtraNoncontSigs "error"
+	  StateNameClashWarn	  "none"
+	  OperatingPointInterfaceChecksumMismatchMsg "warning"
+	  NonCurrentReleaseOperatingPointMsg "error"
+	  ChecksumConsistencyForSSReuse	"none"
+	  PregeneratedLibrarySubsystemCodeDiagnostic "warning"
+	  MatchCodeGenerationContextForUpdateDiagram "none"
+	  InitInArrayFormatMsg	  "warning"
+	  StrictBusMsg		  "ErrorLevel1"
+	  BusNameAdapt		  "WarnAndRepair"
+	  NonBusSignalsTreatedAsBus "none"
+	  SymbolicDimMinMaxWarning "warning"
+	  LossOfSymbolicDimsSimulationWarning "warning"
+	  LossOfSymbolicDimsCodeGenerationWarning "error"
+	  SymbolicDimsDataTypeCodeGenerationDiagnostic "error"
+	  BlockIODiagnostic	  "none"
+	  SFUnusedDataAndEventsDiag "warning"
+	  SFUnexpectedBacktrackingDiag "error"
+	  SFInvalidInputDataAccessInChartInitDiag "warning"
+	  SFNoUnconditionalDefaultTransitionDiag "error"
+	  SFTransitionOutsideNaturalParentDiag "warning"
+	  SFUnreachableExecutionPathDiag "warning"
+	  SFUndirectedBroadcastEventsDiag "warning"
+	  SFTransitionActionBeforeConditionDiag	"warning"
+	  SFOutputUsedAsStateInMooreChartDiag "error"
+	  SFTemporalDelaySmallerThanSampleTimeDiag "warning"
+	  SFSelfTransitionDiag	  "warning"
+	  SFExecutionAtInitializationDiag "warning"
+	  SFMachineParentedDataDiag "warning"
+	  IntegerSaturationMsg	  "warning"
+	  AllowedUnitSystems	  "all"
+	  UnitsInconsistencyMsg	  "warning"
+	  AllowAutomaticUnitConversions	on
+	  RCSCRenamedMsg	  "warning"
+	  RCSCObservableMsg	  "warning"
+	  ForceCombineOutputUpdateInSim	off
+	  UnitDatabase		  ""
+	  UnderSpecifiedDimensionMsg "none"
+	  DebugExecutionForFMUViaOutOfProcess off
+	  ArithmeticOperatorsInVariantConditions "error"
+	}
+	Simulink.HardwareCC {
+	  $ObjectID		  12
+	  Version		  "19.0.0"
+	  DisabledProps		  []
+	  Description		  ""
+	  Components		  []
+	  ProdBitPerChar	  8
+	  ProdBitPerShort	  16
+	  ProdBitPerInt		  32
+	  ProdBitPerLong	  32
+	  ProdBitPerLongLong	  64
+	  ProdBitPerFloat	  32
+	  ProdBitPerDouble	  64
+	  ProdBitPerPointer	  64
+	  ProdBitPerSizeT	  64
+	  ProdBitPerPtrDiffT	  64
+	  ProdLargestAtomicInteger "Char"
+	  ProdLargestAtomicFloat  "Float"
+	  ProdIntDivRoundTo	  "Zero"
+	  ProdEndianess		  "LittleEndian"
+	  ProdWordSize		  64
+	  ProdShiftRightIntArith  on
+	  ProdLongLongMode	  off
+	  ProdHWDeviceType	  "Intel->x86-64 (Windows64)"
+	  TargetBitPerChar	  8
+	  TargetBitPerShort	  16
+	  TargetBitPerInt	  32
+	  TargetBitPerLong	  32
+	  TargetBitPerLongLong	  64
+	  TargetBitPerFloat	  32
+	  TargetBitPerDouble	  64
+	  TargetBitPerPointer	  32
+	  TargetBitPerSizeT	  32
+	  TargetBitPerPtrDiffT	  32
+	  TargetLargestAtomicInteger "Char"
+	  TargetLargestAtomicFloat "None"
+	  TargetShiftRightIntArith on
+	  TargetLongLongMode	  off
+	  TargetIntDivRoundTo	  "Undefined"
+	  TargetEndianess	  "Unspecified"
+	  TargetWordSize	  32
+	  TargetPreprocMaxBitsSint 32
+	  TargetPreprocMaxBitsUint 32
+	  TargetHWDeviceType	  "Specified"
+	  TargetUnknown		  off
+	  ProdEqTarget		  on
+	  UseEmbeddedCoderFeatures on
+	  UseSimulinkCoderFeatures on
+	  HardwareBoardFeatureSet "EmbeddedCoderHSP"
+	}
+	Simulink.ModelReferenceCC {
+	  $ObjectID		  13
+	  Version		  "19.0.0"
+	  DisabledProps		  []
+	  Description		  ""
+	  Components		  []
+	  UpdateModelReferenceTargets "IfOutOfDateOrStructuralChange"
+	  EnableRefExpFcnMdlSchedulingChecks on
+	  CheckModelReferenceTargetMessage "error"
+	  EnableParallelModelReferenceBuilds off
+	  ParallelModelReferenceErrorOnInvalidPool on
+	  ParallelModelReferenceMATLABWorkerInit "None"
+	  ModelReferenceNumInstancesAllowed "Multi"
+	  PropagateVarSize	  "Infer from blocks in model"
+	  ModelDependencies	  ""
+	  ModelReferencePassRootInputsByReference on
+	  ModelReferenceMinAlgLoopOccurrences off
+	  PropagateSignalLabelsOutOfModel on
+	  SupportModelReferenceSimTargetCustomCode off
+	}
+	Simulink.SFSimCC {
+	  $ObjectID		  14
+	  Version		  "19.0.0"
+	  DisabledProps		  []
+	  Description		  ""
+	  Components		  []
+	  SimCustomSourceCode	  ""
+	  SimCustomHeaderCode	  ""
+	  SimCustomInitializer	  ""
+	  SimCustomTerminator	  ""
+	  SimReservedNameArray	  []
+	  SimUserSources	  ""
+	  SimUserIncludeDirs	  ""
+	  SimUserLibraries	  ""
+	  SimUserDefines	  ""
+	  SimCustomCompilerFlags  ""
+	  SimCustomLinkerFlags	  ""
+	  SFSimEcho		  on
+	  SimCtrlC		  on
+	  SimIntegrity		  on
+	  SimUseLocalCustomCode	  on
+	  SimParseCustomCode	  on
+	  SimAnalyzeCustomCode	  off
+	  SimBuildMode		  "sf_incremental_build"
+	  SimGenImportedTypeDefs  off
+	  ModelFunctionsGlobalVisibility "on"
+	  CompileTimeRecursionLimit 50
+	  EnableRuntimeRecursion  on
+	  MATLABDynamicMemAlloc	  on
+	  MATLABDynamicMemAllocThreshold 65536
+	  CustomCodeFunctionArrayLayout	[]
+	  DefaultCustomCodeFunctionArrayLayout "NotSpecified"
+	}
+	Simulink.RTWCC {
+	  $BackupClass		  "Simulink.RTWCC"
+	  $ObjectID		  15
+	  Version		  "19.0.0"
+	  Array {
+	    Type		    "Cell"
+	    Dimension		    16
+	    Cell		    "IncludeHyperlinkInReport"
+	    Cell		    "GenerateTraceInfo"
+	    Cell		    "GenerateTraceReport"
+	    Cell		    "GenerateTraceReportSl"
+	    Cell		    "GenerateTraceReportSf"
+	    Cell		    "GenerateTraceReportEml"
+	    Cell		    "PortableWordSizes"
+	    Cell		    "GenerateWebview"
+	    Cell		    "GenerateCodeMetricsReport"
+	    Cell		    "GenerateCodeReplacementReport"
+	    Cell		    "GenerateMissedCodeReplacementReport"
+	    Cell		    "GenerateErtSFunction"
+	    Cell		    "CreateSILPILBlock"
+	    Cell		    "CodeExecutionProfiling"
+	    Cell		    "CodeProfilingSaveOptions"
+	    Cell		    "CodeProfilingInstrumentation"
+	    PropName		    "DisabledProps"
+	  }
+	  SystemTargetFile	  "grt.tlc"
+	  HardwareBoard		  "None"
+	  ShowCustomHardwareApp	  off
+	  ShowEmbeddedHardwareApp off
+	  TLCOptions		  ""
+	  GenCodeOnly		  off
+	  MakeCommand		  "make_rtw"
+	  GenerateMakefile	  on
+	  PackageGeneratedCodeAndArtifacts off
+	  PackageName		  ""
+	  TemplateMakefile	  "grt_default_tmf"
+	  PostCodeGenCommand	  ""
+	  Description		  ""
+	  GenerateReport	  off
+	  RTWVerbose		  on
+	  RetainRTWFile		  off
+	  RTWBuildHooks		  []
+	  ProfileTLC		  off
+	  TLCDebug		  off
+	  TLCCoverage		  off
+	  TLCAssert		  off
+	  RTWUseLocalCustomCode	  on
+	  RTWUseSimCustomCode	  off
+	  CustomSourceCode	  ""
+	  CustomHeaderCode	  ""
+	  CustomInclude		  ""
+	  CustomSource		  ""
+	  CustomLibrary		  ""
+	  CustomDefine		  ""
+	  CustomBLASCallback	  ""
+	  CustomLAPACKCallback	  ""
+	  CustomFFTCallback	  ""
+	  CustomInitializer	  ""
+	  CustomTerminator	  ""
+	  Toolchain		  "Automatically locate an installed toolchain"
+	  BuildConfiguration	  "Faster Builds"
+	  CustomToolchainOptions  []
+	  IncludeHyperlinkInReport off
+	  LaunchReport		  off
+	  PortableWordSizes	  off
+	  CreateSILPILBlock	  "None"
+	  CodeExecutionProfiling  off
+	  CodeExecutionProfileVariable "executionProfile"
+	  CodeProfilingSaveOptions "SummaryOnly"
+	  CodeProfilingInstrumentation "off"
+	  SILDebugging		  off
+	  TargetLang		  "C"
+	  IncludeBusHierarchyInRTWFileBlockHierarchyMap	off
+	  GenerateTraceInfo	  off
+	  GenerateTraceReport	  off
+	  GenerateTraceReportSl	  off
+	  GenerateTraceReportSf	  off
+	  GenerateTraceReportEml  off
+	  GenerateWebview	  off
+	  GenerateCodeMetricsReport off
+	  GenerateCodeReplacementReport	off
+	  GenerateMissedCodeReplacementReport off
+	  RTWCompilerOptimization "off"
+	  ObjectivePriorities	  []
+	  RTWCustomCompilerOptimizations ""
+	  CheckMdlBeforeBuild	  "Off"
+	  SharedConstantsCachingThreshold 1024
+	  Array {
+	    Type		    "Handle"
+	    Dimension		    2
+	    Simulink.CodeAppCC {
+	      $ObjectID		      16
+	      Version		      "19.0.0"
+	      Array {
+		Type			"Cell"
+		Dimension		28
+		Cell			"IgnoreCustomStorageClasses"
+		Cell			"IgnoreTestpoints"
+		Cell			"BlockCommentType"
+		Cell			"InsertBlockDesc"
+		Cell			"InsertPolySpaceComments"
+		Cell			"SFDataObjDesc"
+		Cell			"MATLABFcnDesc"
+		Cell			"SimulinkDataObjDesc"
+		Cell			"DefineNamingRule"
+		Cell			"SignalNamingRule"
+		Cell			"ParamNamingRule"
+		Cell			"InternalIdentifier"
+		Cell			"InlinedPrmAccess"
+		Cell			"CustomSymbolStr"
+		Cell			"CustomSymbolStrGlobalVar"
+		Cell			"CustomSymbolStrType"
+		Cell			"CustomSymbolStrField"
+		Cell			"CustomSymbolStrFcn"
+		Cell			"CustomSymbolStrModelFcn"
+		Cell			"CustomSymbolStrFcnArg"
+		Cell			"CustomSymbolStrBlkIO"
+		Cell			"CustomSymbolStrTmpVar"
+		Cell			"CustomSymbolStrMacro"
+		Cell			"CustomSymbolStrUtil"
+		Cell			"CustomSymbolStrEmxType"
+		Cell			"CustomSymbolStrEmxFcn"
+		Cell			"CustomUserTokenString"
+		Cell			"ReqsInCode"
+		PropName		"DisabledProps"
+	      }
+	      Description	      ""
+	      Components	      []
+	      Comment		      ""
+	      ForceParamTrailComments off
+	      GenerateComments	      on
+	      CommentStyle	      "Auto"
+	      IgnoreCustomStorageClasses on
+	      IgnoreTestpoints	      off
+	      MaxIdLength	      31
+	      PreserveName	      off
+	      PreserveNameWithParent  off
+	      ShowEliminatedStatement off
+	      OperatorAnnotations     off
+	      SimulinkDataObjDesc     off
+	      SFDataObjDesc	      off
+	      MATLABFcnDesc	      off
+	      MangleLength	      1
+	      SharedChecksumLength    8
+	      CustomSymbolStrGlobalVar "$R$N$M"
+	      CustomSymbolStrType     "$N$R$M_T"
+	      CustomSymbolStrField    "$N$M"
+	      CustomSymbolStrFcn      "$R$N$M$F"
+	      CustomSymbolStrModelFcn "$R$N"
+	      CustomSymbolStrFcnArg   "rt$I$N$M"
+	      CustomSymbolStrBlkIO    "rtb_$N$M"
+	      CustomSymbolStrTmpVar   "$N$M"
+	      CustomSymbolStrMacro    "$R$N$M"
+	      CustomSymbolStrUtil     "$N$C"
+	      CustomSymbolStrEmxType  "emxArray_$M$N"
+	      CustomSymbolStrEmxFcn   "emx$M$N"
+	      CustomUserTokenString   ""
+	      CustomCommentsFcn	      ""
+	      DefineNamingRule	      "None"
+	      DefineNamingFcn	      ""
+	      ParamNamingRule	      "None"
+	      ParamNamingFcn	      ""
+	      SignalNamingRule	      "None"
+	      SignalNamingFcn	      ""
+	      InsertBlockDesc	      off
+	      InsertPolySpaceComments off
+	      SimulinkBlockComments   on
+	      BlockCommentType	      "BlockPathComment"
+	      StateflowObjectComments off
+	      MATLABSourceComments    off
+	      EnableCustomComments    off
+	      InternalIdentifierFile  ""
+	      InternalIdentifier      "Shortened"
+	      InlinedPrmAccess	      "Literals"
+	      ReqsInCode	      off
+	      UseSimReservedNames     off
+	      ReservedNameArray	      []
+	    }
+	    Simulink.GRTTargetCC {
+	      $BackupClass	      "Simulink.TargetCC"
+	      $ObjectID		      17
+	      Version		      "19.0.0"
+	      Array {
+		Type			"Cell"
+		Dimension		16
+		Cell			"IncludeMdlTerminateFcn"
+		Cell			"SuppressErrorStatus"
+		Cell			"ERTCustomFileBanners"
+		Cell			"GenerateSampleERTMain"
+		Cell			"ExistingSharedCode"
+		Cell			"GenerateTestInterfaces"
+		Cell			"ModelStepFunctionPrototypeControlCompliant"
+		Cell			"GenerateAllocFcn"
+		Cell			"PurelyIntegerCode"
+		Cell			"SupportComplex"
+		Cell			"SupportAbsoluteTime"
+		Cell			"SupportContinuousTime"
+		Cell			"SupportNonInlinedSFcns"
+		Cell			"RemoveDisableFunc"
+		Cell			"RemoveResetFunc"
+		Cell			"PreserveStateflowLocalDataDimensions"
+		PropName		"DisabledProps"
+	      }
+	      Description	      ""
+	      Components	      []
+	      TargetFcnLib	      "ansi_tfl_table_tmw.mat"
+	      TargetLibSuffix	      ""
+	      TargetPreCompLibLocation ""
+	      GenFloatMathFcnCalls    "NOT IN USE"
+	      TargetLangStandard      "C99 (ISO)"
+	      CodeReplacementLibrary  "None"
+	      UtilityFuncGeneration   "Auto"
+	      MultiwordTypeDef	      "System defined"
+	      MultiwordLength	      2048
+	      DynamicStringBufferSize 256
+	      GenerateFullHeader      on
+	      InferredTypesCompatibility off
+	      ExistingSharedCode      ""
+	      GenerateSampleERTMain   off
+	      GenerateTestInterfaces  off
+	      ModelReferenceCompliant on
+	      ParMdlRefBuildCompliant on
+	      CompOptLevelCompliant   on
+	      ConcurrentExecutionCompliant on
+	      IncludeMdlTerminateFcn  on
+	      GeneratePreprocessorConditionals "Use local settings"
+	      CombineOutputUpdateFcns on
+	      CombineSignalStateStructs	off
+	      GroupInternalDataByFunction off
+	      SuppressErrorStatus     off
+	      IncludeFileDelimiter    "Auto"
+	      ERTCustomFileBanners    off
+	      SupportAbsoluteTime     on
+	      LogVarNameModifier      "rt_"
+	      MatFileLogging	      on
+	      MultiInstanceERTCode    off
+	      CodeInterfacePackaging  "Nonreusable function"
+	      PurelyIntegerCode	      off
+	      SupportNonFinite	      on
+	      SupportComplex	      on
+	      SupportContinuousTime   on
+	      SupportNonInlinedSFcns  on
+	      RemoveDisableFunc	      off
+	      RemoveResetFunc	      off
+	      SupportVariableSizeSignals off
+	      ParenthesesLevel	      "Nominal"
+	      CastingMode	      "Nominal"
+	      PreserveStateflowLocalDataDimensions off
+	      MATLABClassNameForMDSCustomization "Simulink.SoftwareTarget.GRTCustomization"
+	      ModelStepFunctionPrototypeControlCompliant off
+	      CPPClassGenCompliant    on
+	      AutosarCompliant	      off
+	      MDXCompliant	      off
+	      GRTInterface	      off
+	      GenerateAllocFcn	      off
+	      UseToolchainInfoCompliant	on
+	      GenerateSharedConstants on
+	      CoderGroups	      []
+	      AccessMethods	      []
+	      LookupTableObjectStructAxisOrder "1,2,3,4,..."
+	      LUTObjectStructOrderExplicitValues "Size,Breakpoints,Table"
+	      LUTObjectStructOrderEvenSpacing "Size,Breakpoints,Table"
+	      ArrayLayout	      "Column-major"
+	      UnsupportedSFcnMsg      "error"
+	      ERTHeaderFileRootName   "$R$E"
+	      ERTSourceFileRootName   "$R$E"
+	      ERTDataFileRootName     "$R_data"
+	      UseMalloc		      off
+	      ExtMode		      off
+	      ExtModeStaticAlloc      off
+	      ExtModeTesting	      off
+	      ExtModeStaticAllocSize  1000000
+	      ExtModeTransport	      0
+	      ExtModeMexFile	      "ext_comm"
+	      ExtModeMexArgs	      ""
+	      ExtModeIntrfLevel	      "Level1"
+	      RTWCAPISignals	      off
+	      RTWCAPIParams	      off
+	      RTWCAPIStates	      off
+	      RTWCAPIRootIO	      off
+	      GenerateASAP2	      off
+	      MultiInstanceErrorCode  "Error"
+	    }
+	    PropName		    "Components"
+	  }
+	}
+	SlCovCC.ConfigComp {
+	  $ObjectID		  18
+	  Version		  "19.0.0"
+	  DisabledProps		  []
+	  Description		  "Simulink Coverage Configuration Component"
+	  Components		  []
+	  Name			  "Simulink Coverage"
+	  CovEnable		  off
+	  CovScope		  "EntireSystem"
+	  CovIncludeTopModel	  on
+	  RecordCoverage	  off
+	  CovPath		  "/"
+	  CovSaveName		  "covdata"
+	  CovCompData		  ""
+	  CovMetricSettings	  "dwe"
+	  CovFilter		  ""
+	  CovHTMLOptions	  ""
+	  CovNameIncrementing	  off
+	  CovHtmlReporting	  off
+	  CovForceBlockReductionOff on
+	  CovEnableCumulative	  on
+	  CovSaveCumulativeToWorkspaceVar off
+	  CovSaveSingleToWorkspaceVar off
+	  CovCumulativeVarName	  "covCumulativeData"
+	  CovCumulativeReport	  off
+	  CovSaveOutputData	  on
+	  CovOutputDir		  "slcov_output/$ModelName$"
+	  CovDataFileName	  "$ModelName$_cvdata"
+	  CovShowResultsExplorer  on
+	  CovReportOnPause	  on
+	  CovModelRefEnable	  "off"
+	  CovModelRefExcluded	  ""
+	  CovExternalEMLEnable	  on
+	  CovSFcnEnable		  on
+	  CovBoundaryAbsTol	  1e-05
+	  CovBoundaryRelTol	  0.01
+	  CovUseTimeInterval	  off
+	  CovStartTime		  0
+	  CovStopTime		  0
+	  CovMcdcMode		  "Masking"
+	}
+	hdlcoderui.hdlcc {
+	  $ObjectID		  19
+	  Version		  "19.0.0"
+	  DisabledProps		  []
+	  Description		  "HDL Coder custom configuration component"
+	  Components		  []
+	  Name			  "HDL Coder"
+	  Array {
+	    Type		    "Cell"
+	    Dimension		    1
+	    Cell		    " "
+	    PropName		    "HDLConfigFile"
+	  }
+	  HDLCActiveTab		  "0"
+	}
+	PropName		"Components"
+      }
+      Name		      "Configuration"
+      CurrentDlgPage	      "Solver"
+      ConfigPrmDlgPosition    [ 465, 173, 1455, 843 ]
+      ExtraOptions	      ""
+    }
+    PropName		    "ConfigurationSets"
+  }
+  ExplicitPartitioning	  off
+  BlockDefaults {
+    ForegroundColor	    "black"
+    BackgroundColor	    "white"
+    DropShadow		    off
+    NamePlacement	    "normal"
+    FontName		    "Helvetica"
+    FontSize		    10
+    FontWeight		    "normal"
+    FontAngle		    "normal"
+    ShowName		    on
+    HideAutomaticName	    on
+    BlockRotation	    0
+    BlockMirror		    off
+  }
+  AnnotationDefaults {
+    HorizontalAlignment	    "left"
+    VerticalAlignment	    "top"
+    ForegroundColor	    "black"
+    BackgroundColor	    "white"
+    DropShadow		    off
+    FontName		    "Helvetica"
+    FontSize		    10
+    FontWeight		    "normal"
+    FontAngle		    "normal"
+    MarkupType		    "model"
+    UseDisplayTextAsClickCallback off
+    AnnotationType	    "note_annotation"
+    FixedHeight		    off
+    FixedWidth		    off
+    Interpreter		    "off"
+  }
+  LineDefaults {
+    FontName		    "Helvetica"
+    FontSize		    9
+    FontWeight		    "normal"
+    FontAngle		    "normal"
+  }
+  MaskDefaults {
+    SelfModifiable	    "off"
+    IconFrame		    "on"
+    IconOpaque		    "opaque"
+    RunInitForIconRedraw    "analyze"
+    IconRotate		    "none"
+    PortRotate		    "default"
+    IconUnits		    "autoscale"
+  }
+  MaskParameterDefaults {
+    Evaluate		    "on"
+    Tunable		    "on"
+    NeverSave		    "off"
+    Internal		    "off"
+    ReadOnly		    "off"
+    Enabled		    "on"
+    Visible		    "on"
+    ToolTip		    "on"
+  }
+  BlockParameterDefaults {
+    Block {
+      BlockType		      Inport
+      Port		      "1"
+      OutputFunctionCall      off
+      OutMin		      "[]"
+      OutMax		      "[]"
+      OutDataTypeStr	      "Inherit: auto"
+      LockScale		      off
+      BusOutputAsStruct	      off
+      Unit		      "inherit"
+      PortDimensions	      "-1"
+      VarSizeSig	      "Inherit"
+      SampleTime	      "-1"
+      SignalType	      "auto"
+      SamplingMode	      "auto"
+      LatchByDelayingOutsideSignal off
+      LatchInputForFeedbackSignals off
+      Interpolate	      on
+    }
+    Block {
+      BlockType		      Outport
+      Port		      "1"
+      OutMin		      "[]"
+      OutMax		      "[]"
+      OutDataTypeStr	      "Inherit: auto"
+      LockScale		      off
+      BusOutputAsStruct	      off
+      Unit		      "inherit"
+      PortDimensions	      "-1"
+      VarSizeSig	      "Inherit"
+      SampleTime	      "-1"
+      SignalType	      "auto"
+      SamplingMode	      "auto"
+      EnsureOutportIsVirtual  off
+      SourceOfInitialOutputValue "Dialog"
+      OutputWhenDisabled      "held"
+      InitialOutput	      "[]"
+      MustResolveToSignalObject	off
+      OutputWhenUnConnected   off
+      OutputWhenUnconnectedValue "0"
+      VectorParamsAs1DForOutWhenUnconnected off
+    }
+    Block {
+      BlockType		      SubSystem
+      ShowPortLabels	      "FromPortIcon"
+      Permissions	      "ReadWrite"
+      PermitHierarchicalResolution "All"
+      TreatAsAtomicUnit	      off
+      MinAlgLoopOccurrences   off
+      PropExecContextOutsideSubsystem off
+      ScheduleAs	      "Sample time"
+      SystemSampleTime	      "-1"
+      RTWSystemCode	      "Auto"
+      RTWFcnNameOpts	      "Auto"
+      RTWFileNameOpts	      "Auto"
+      FunctionInterfaceSpec   "void_void"
+      FunctionWithSeparateData off
+      RTWMemSecFuncInitTerm   "Inherit from model"
+      RTWMemSecFuncExecute    "Inherit from model"
+      RTWMemSecDataConstants  "Inherit from model"
+      RTWMemSecDataInternal   "Inherit from model"
+      RTWMemSecDataParameters "Inherit from model"
+      SimViewingDevice	      off
+      DataTypeOverride	      "UseLocalSettings"
+      DataTypeOverrideAppliesTo	"AllNumericTypes"
+      MinMaxOverflowLogging   "UseLocalSettings"
+      Opaque		      off
+      MaskHideContents	      off
+      SFBlockType	      "NONE"
+      VariantControlMode      "Expression"
+      Variant		      off
+      GeneratePreprocessorConditionals off
+      AllowZeroVariantControls off
+      PropagateVariantConditions off
+      TreatAsGroupedWhenPropagatingVariantConditions on
+      ContentPreviewEnabled   off
+      IsWebBlock	      off
+      IsObserver	      off
+      Latency		      "0"
+      AutoFrameSizeCalculation off
+      IsWebBlockPanel	      off
+    }
+  }
+  System {
+    Name		    "cdsGaussianNoise"
+    Location		    [117, 61, 833, 625]
+    Open		    on
+    PortBlocksUseCompactNotation off
+    SetExecutionDomain	    off
+    ExecutionDomainType	    "Deduce"
+    ModelBrowserVisibility  on
+    ModelBrowserWidth	    200
+    ScreenColor		    "white"
+    PaperOrientation	    "landscape"
+    PaperPositionMode	    "auto"
+    PaperType		    "usletter"
+    PaperUnits		    "inches"
+    TiledPaperMargins	    [0.500000, 0.500000, 0.500000, 0.500000]
+    TiledPageScale	    1
+    ShowPageBoundaries	    off
+    ZoomFactor		    "100"
+    ReportName		    "simulink-default.rpt"
+    SIDHighWatermark	    "11"
+    SimulinkSubDomain	    "Simulink"
+    Block {
+      BlockType		      Inport
+      Name		      "Ground"
+      SID		      "6"
+      Position		      [160, 178, 190, 192]
+      ZOrder		      6
+      IconDisplay	      "Port number"
+    }
+    Block {
+      BlockType		      SubSystem
+      Name		      "Subsystem"
+      SID		      "9"
+      Ports		      [1, 1]
+      Position		      [230, 164, 330, 206]
+      ZOrder		      7
+      RequestExecContextInheritance off
+      System {
+	Name			"Subsystem"
+	Location		[117, 61, 833, 625]
+	Open			off
+	PortBlocksUseCompactNotation off
+	SetExecutionDomain	off
+	ExecutionDomainType	"Deduce"
+	ModelBrowserVisibility	on
+	ModelBrowserWidth	200
+	ScreenColor		"white"
+	PaperOrientation	"landscape"
+	PaperPositionMode	"auto"
+	PaperType		"usletter"
+	PaperUnits		"inches"
+	TiledPaperMargins	[0.500000, 0.500000, 0.500000, 0.500000]
+	TiledPageScale		1
+	ShowPageBoundaries	off
+	ZoomFactor		"100"
+	SimulinkSubDomain	"Simulink"
+	Block {
+	  BlockType		  Inport
+	  Name			  "Ground"
+	  SID			  "10"
+	  Position		  [110, 103, 140, 117]
+	  ZOrder		  -1
+	  IconDisplay		  "Port number"
+	}
+	Block {
+	  BlockType		  Outport
+	  Name			  "GNoise"
+	  SID			  "11"
+	  Position		  [240, 103, 270, 117]
+	  ZOrder		  -2
+	  IconDisplay		  "Port number"
+	}
+      }
+    }
+    Block {
+      BlockType		      Outport
+      Name		      "GNoise"
+      SID		      "8"
+      Position		      [370, 178, 400, 192]
+      ZOrder		      4
+      IconDisplay	      "Port number"
+    }
+    Line {
+      ZOrder		      8
+      SrcBlock		      "Ground"
+      SrcPort		      1
+      DstBlock		      "Subsystem"
+      DstPort		      1
+    }
+    Line {
+      ZOrder		      9
+      SrcBlock		      "Subsystem"
+      SrcPort		      1
+      DstBlock		      "GNoise"
+      DstPort		      1
+    }
+  }
+}
diff --git a/src/epics/util/Makefile.in b/src/epics/util/Makefile.in
index e4fe370a1ecf1b0087ea83a9b5cddf8f34da285a..c8c9031e52eece334f6e638522a9d11364a61131 100644
--- a/src/epics/util/Makefile.in
+++ b/src/epics/util/Makefile.in
@@ -3,8 +3,8 @@
 SHELL = /bin/sh
 
 top_srcdir=`readlink -m @top_srcdir@`
-srcdir=@srcdir@
-VPATH=@srcdir@
+#srcdir=@srcdir@
+#VPATH=@srcdir@
 
 prefix      = @prefix@
 exec_prefix = @exec_prefix@
@@ -23,11 +23,17 @@ PERFORMANCEFLAGS=-DNDEBUG -g -O5
 RELEASEFLAGS=-DNDEBUG -DNPROBE -g -O5
 #DEBUGFLAGS=-DNDEBUG -O5 -unroll=16
 DEVFLAGS=@DEVFLAGS@
-MBUFSYM := $(shell $(srcdir)/find_module_symvers -q mbuf)
-GPSSYM := $(shell $(srcdir)/find_module_symvers -q gpstime)
-CPUISOSYM := $(shell $(srcdir)/find_module_symvers -q rts-cpu-isolator)
+ifndef MBUF_SYM
+MBUF_SYM := $(shell $(srcdir)/find_module_symvers -q mbuf)
+endif
+ifndef GPSTIME_SYM
+GPSTIME_SYM := $(shell $(srcdir)/find_module_symvers -q gpstime)
+endif
+ifndef RTS_CPU_ISOLATOR_SYM
+RTS_CPU_ISOLATOR_SYM := $(shell $(srcdir)/find_module_symvers -q rts-cpu-isolator)
+endif
 
 %:
-	env RCG_SRC_DIR=$(top_srcdir) PERL5LIB=$(srcdir) MBUFSYM=$(MBUFSYM) GPSSYM=$(GPSSYM) CPUISOSYM=$(CPUISOSYM) $(srcdir)/feCodeGen.pl $@.mdl $@
+	env RCG_SRC_DIR=$(top_srcdir) PERL5LIB=$(srcdir) MBUF_SYM=$(MBUF_SYM) GPSTIME_SYM=$(GPSTIME_SYM) RTS_CPU_ISOLATOR_SYM=$(RTS_CPU_ISOLATOR_SYM) $(srcdir)/feCodeGen.pl $@.mdl $@
 
 all: 
diff --git a/src/epics/util/Makefile.kernel b/src/epics/util/Makefile.kernel
new file mode 100644
index 0000000000000000000000000000000000000000..121633eac359ddff5137bb5ba194527fb6facfb5
--- /dev/null
+++ b/src/epics/util/Makefile.kernel
@@ -0,0 +1,117 @@
+# This makefile is copied in from src/epics/util/Makefile.kernel.iop
+#
+mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
+mkfile_dir := $(dir $(mkfile_path))
+
+ifndef RCG_SRC
+$(error The environmental variable RCG_SRC is not set)
+endif
+
+ifeq ("$(wildcard $(RCG_SRC)/src/)","")
+$(error The environmental variable RCG_SRC might not be set correctly, we expect a $(RCG_SRC)/src/ dir)
+endif
+
+$(shell mkdir -p $(mkfile_dir)/src/)
+$(shell cp -rp $(RCG_SRC)/src/include/ $(mkfile_dir)/src/)
+$(shell cp -rp $(RCG_SRC)/src/fe/ $(mkfile_dir)/src/)
+$(shell cp -rp $(RCG_SRC)/src/drv/ $(mkfile_dir)/src/)
+$(shell cp -rp $(RCG_SRC)/src/shmem/ $(mkfile_dir)/src/)
+
+# Include the generated make variables, written by
+# the feCodeGen.pl script.
+include $(mkfile_dir)/KernelVars.mk
+
+
+ifndef MODEL_NAME
+$(error MODEL_NAME must be set when calling this makefile)
+endif
+
+
+#
+# Add all kernel common object files
+COMMON_OBJ_FILES := $(MODEL_NAME)_core.o
+COMMON_OBJ_FILES += src/drv/crc.o
+COMMON_OBJ_FILES += src/fe/moduleLoad.o
+COMMON_OBJ_FILES += src/fe/moduleLoadCommon.o
+COMMON_OBJ_FILES += src/fe/print_io_info.o
+COMMON_OBJ_FILES += src/fe/verify_card_count.o
+COMMON_OBJ_FILES += src/fe/commData3.o
+COMMON_OBJ_FILES += src/include/controller.o
+COMMON_OBJ_FILES += src/include/controllerko.o
+COMMON_OBJ_FILES += src/include/drv/accesDio24.o
+COMMON_OBJ_FILES += src/include/drv/accesIIRO16.o
+COMMON_OBJ_FILES += src/include/drv/accesIIRO8.o
+COMMON_OBJ_FILES += src/include/drv/contec32o.o
+COMMON_OBJ_FILES += src/include/drv/contec6464.o
+COMMON_OBJ_FILES += src/include/drv/daqLib.o
+COMMON_OBJ_FILES += src/include/drv/dtoa.o
+COMMON_OBJ_FILES += src/include/drv/epicsXfer.o
+COMMON_OBJ_FILES += src/include/drv/fm10Gen.o
+
+
+#
+# IOP Specific Object Files
+ifdef IOP_MODEL
+IOP_EXTRA_OBJ := src/fe/controllerIop.o
+IOP_EXTRA_OBJ += src/fe/map_cards_2_slots.o
+IOP_EXTRA_OBJ += src/fe/map.o
+IOP_EXTRA_OBJ += src/fe/verify_slots.o
+IOP_EXTRA_OBJ += src/include/drv/contec1616.o
+IOP_EXTRA_OBJ += src/include/drv/gsc_adc_common.o
+IOP_EXTRA_OBJ += src/include/drv/gsc_dac_common.o
+IOP_EXTRA_OBJ += src/include/drv/gsc16ai64.o
+IOP_EXTRA_OBJ += src/include/drv/gsc16ao16.o
+IOP_EXTRA_OBJ += src/include/drv/gsc18ai32.o
+IOP_EXTRA_OBJ += src/include/drv/gsc18ai64.o
+IOP_EXTRA_OBJ += src/include/drv/gsc18ao8.o
+IOP_EXTRA_OBJ += src/include/drv/gsc20ao8.o
+IOP_EXTRA_OBJ += src/include/drv/ligoPcieTiming_core.o
+IOP_EXTRA_OBJ += src/include/drv/ligoPcieTiming.o
+IOP_EXTRA_OBJ += src/include/drv/plx_9056.o
+IOP_EXTRA_OBJ += src/include/drv/spectracomGPS.o
+
+ifdef BUILD_WITH_DOLPHIN
+IOP_EXTRA_OBJ += src/fe/dolphin.o
+endif #BUILD_WITH_DOLPHIN
+
+#
+# Virtual IO (VIO) / Dolphin Timing special DAC ADC functions
+# IOP models only
+ifneq ($(and $(RUN_WO_IO_MODULES),$(USE_DOLPHIN_TIMING)),)
+DAC_ADC_EXTRA_OBJ :=
+else
+# Add extra objects for real ADC/DACs
+DAC_ADC_EXTRA_OBJ := src/include/drv/iop_adc_functions.o
+DAC_ADC_EXTRA_OBJ += src/include/drv/iop_dac_functions.o
+DAC_ADC_EXTRA_OBJ += src/fe/sync21pps.o
+endif
+
+
+else # NOT IOP_MODEL (APP)
+#
+# App Specific Object Files
+APP_EXTRA_OBJ += src/fe/controllerApp.o
+APP_EXTRA_OBJ += src/fe/mapApp.o
+endif
+
+
+
+#
+# Define kernel module source files
+#
+obj-m := $(MODEL_NAME).o
+$(MODEL_NAME)-y += $(COMMON_OBJ_FILES)
+$(MODEL_NAME)-y += $(DAC_ADC_EXTRA_OBJ) 
+$(MODEL_NAME)-y += $(IOP_EXTRA_OBJ) 
+$(MODEL_NAME)-y += $(APP_EXTRA_OBJ) 
+
+# Set the path to the Kernel build utils.
+KBUILD=/lib/modules/$(shell uname -r)/build/
+
+default:
+	$(MAKE) -C $(KBUILD) SUBDIRS=$(mkfile_dir) M=$(mkfile_dir) modules
+
+
+clean:
+	$(MAKE) -C $(KBUILD) M=$(PWD) clean
+
diff --git a/src/epics/util/Userspace_CMakeLists.cmake b/src/epics/util/Userspace_CMakeLists.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..219f6fbeb9373a9c069074ec42c70375f425e6f4
--- /dev/null
+++ b/src/epics/util/Userspace_CMakeLists.cmake
@@ -0,0 +1,84 @@
+cmake_minimum_required(VERSION 3.0)
+
+if(NOT MODEL_NAME)
+    message(FATAL_ERROR "MODEL_NAME must be defined when generating the build files with CMake.")
+endif()
+
+project (${MODEL_NAME})
+
+option(USE_STDLIB_MATH "This option uses the stdlib's math.h implementation instead of the inline assembly default" OFF)
+
+# We want to use ${MODEL_NAME} for the library name, cmake will complain
+# if we pass it in because the exe name matches, remove the "lib"
+# prefix, add it back manually and cmake does not complain
+set(CMAKE_STATIC_LIBRARY_PREFIX "")
+
+set(LIB_NAME lib${MODEL_NAME})
+
+# Include generated FLAGS, options and INC dirs.
+include(${CMAKE_CURRENT_SOURCE_DIR}/UserspaceVars.cmake)
+
+if(${USE_STDLIB_MATH}) 
+    list(APPEND CFLAGS "-DUSE_STDLIB_MATH=1") 
+endif()
+
+# Turn the ; seperated list into space seperated list and add to CFLAGS
+string(REPLACE ";" " " CFLAGS_SPACE_SEPERATED "${CFLAGS}")
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CFLAGS_SPACE_SEPERATED}" )
+
+#
+# Define all the source files we need that are common to IOP and APP builds
+#
+list(APPEND COMMON_SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}_core.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/fe/print_io_info.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/include/controller.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/include/controllerko.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/drv/crc.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/include/drv/fm10Gen.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/include/drv/epicsXfer.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/include/drv/daqLib.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/fe/rcguserCommon.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/fe/commDataUsp.c"
+                     "${CMAKE_CURRENT_SOURCE_DIR}/src/drv/rfm.c")
+
+
+if(BUILD_USP_GPSCLOCK)
+    list(APPEND COMMON_SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/drv/gpsclock.c")
+endif()
+
+
+if(IOP_MODEL)
+    list(APPEND MODEL_SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/fe/controllerIopUser.c"
+                         "${CMAKE_CURRENT_SOURCE_DIR}/src/fe/rcguserIop.c")
+else() #Control Model
+    list(APPEND MODEL_SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/fe/controllerAppUser.c"
+                         "${CMAKE_CURRENT_SOURCE_DIR}/src/fe/rcguser.c"
+                         "${CMAKE_CURRENT_SOURCE_DIR}/src/fe/mapApp.c")
+endif(IOP_MODEL)
+
+if(DEFINED USE_DOLPHIN_TIMING OR DEFINED XMIT_DOLPHIN_TIME)
+
+else()
+# Looks like userspace controllerIopUser uses initAdcModules() which are inline
+# https://git.ligo.org/cds/advligorts/-/blob/master/src/fe/controllerIopUser.c#L550
+endif()
+
+#
+# Configure and build the library
+list(APPEND LIB_SRC_LIST ${COMMON_SRC_LIST} "${CMAKE_CURRENT_SOURCE_DIR}/src/fe/mapApp.c")
+add_library(${LIB_NAME} ${LIB_SRC_LIST})
+target_include_directories(${LIB_NAME} PUBLIC ${INC_DIRS})
+
+if (${USE_STDLIB_MATH})
+    target_link_libraries(${LIB_NAME} PUBLIC -lm)
+endif()
+
+
+#
+# Configure and build the model. ${INC_DIRS} is defined by UserspaceVars.cmake
+add_executable(${PROJECT_NAME} ${MODEL_SRC_LIST} )
+target_include_directories(${PROJECT_NAME} PRIVATE ${INC_DIRS})
+target_link_libraries(${PROJECT_NAME} PRIVATE ${LIB_NAME})
+
+
+
diff --git a/src/epics/util/checkForErrors.sh b/src/epics/util/checkForErrors.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9f47e8b7f12b7eea6ba0eb3925d8c6f7c3bc3a05
--- /dev/null
+++ b/src/epics/util/checkForErrors.sh
@@ -0,0 +1,21 @@
+#!/bin/bash 
+this_script_path=`realpath $0`
+this_script_dir=`dirname ${this_script_path}`
+err_logs=`find $this_script_dir/../models/*/logs/ -name *_error.log`
+any_errors=0
+
+for file in $err_logs
+do
+    sz=`stat -c %s $file`
+    if [ $sz -gt 0 ]
+    then
+        any_errors=$((any_errors+1))
+        echo "Errors in: $file"
+    fi
+done
+
+if [ $any_errors -eq 0 ] 
+then
+    echo "No Errors in built models."
+fi
+
diff --git a/src/epics/util/feCodeGen.pl b/src/epics/util/feCodeGen.pl
index 6cb853f2a86941ad19a64e6022799edf79ea9d2a..d66d729b0a1889245b9fefc368a5cb789201dd77 100755
--- a/src/epics/util/feCodeGen.pl
+++ b/src/epics/util/feCodeGen.pl
@@ -6,6 +6,8 @@
 
 #// \n\n This script is invoked by the auto generated build/src/epics/util/Makefile. \n\n\n
 use File::Path;
+use File::Copy;
+use File::Path qw(make_path);
 use Cwd;
 require "lib/SUM.pm";
 require "lib/AND.pm";
@@ -68,9 +70,9 @@ die "Usage: $PROGRAM_NAME <MDL file> <Output file name> [<DCUID number>] [<ifo>]
 #Setup current working directory and pointer to RCG source directory.
 $currWorkDir = &Cwd::cwd();
 $rcg_src_dir = $ENV{"RCG_SRC_DIR"};
-$mbufsymfile = $ENV{"MBUFSYM"};
-$gpssymfile = $ENV{"GPSSYM"};
-$cpuisolatorfile = $ENV{"CPUISOSYM"};
+$mbufsymfile = $ENV{"MBUF_SYM"};
+$gpssymfile = $ENV{"GPSTIME_SYM"};
+$cpuisolatorfile = $ENV{"RTS_CPU_ISOLATOR_SYM"};
 $dolphinGen = 2;
 
 if (! length $rcg_src_dir) { $rcg_src_dir = "$currWorkDir/../../.."; }
@@ -105,7 +107,7 @@ print "Generating Firm Real-time code for patched vanilla Linux kernel\n";
 
 # Get MAX_DIO_MODULES allowed from header file.
 # This is used by Parser3.pm to stop compile if RCG limits exceeded.
-my $mdmStr = `grep "define MAX_DIO_MODULES" ../../include/drv/cdsHardware.h`;
+my $mdmStr = `grep "define MAX_DIO_MODULES" $rcg_src_dir/src/include/drv/cdsHardware.h`;
 my @mdmNum = ($mdmStr =~ m/(\d+)/);
 $maxDioMod = pop(@mdmNum);
 
@@ -165,6 +167,8 @@ $dkTimesCalled = 0;
 $remoteGpsPart = 0;
 $remoteGPS = 0;
 $requireIOcnt = 1;
+$noiseGeneratorSeed = "none";
+$gaussNoiseGeneratorSeed = "none";
 #Following provide for non standard IOP clock rates
 $adcclock = 64;
 $modelrate = 64;
@@ -183,54 +187,52 @@ $ifo_from_mdl_name = substr($skeleton, 0, 2);
 
 #//	- Create the paths for RCG output files. \n
 print "file out is $skeleton\n";
-$cFile = "../../fe/";
-$cFile .= $ARGV[1];
-$cFileDirectory = $cFile;
-$cFileDirectory2 = $cFileDirectory . "_usp";
-$cFile .= "/";
-$cFile .= $ARGV[1];
-$cFile .= ".c";
-$cFile2 = $cFileDirectory2;
-$cFile2 .= "/";
-$cFile2 .= $ARGV[1];
-$cFile2 .= ".c";
-$hFile = "../../include/";
-$hFile .= $ARGV[1];
-$hFile .= ".h";
-$mFile = "../../fe/";
-$mFile .= $ARGV[1];
-$mFile .= "/";
-$mFile .= "Makefile";
-$mFile2 = $cFileDirectory2;
-$mFile2 .= "/";
-$mFile2 .= "Makefile";
-$meFile = "../../../config/";
+
+$modelCodeFilepath = "../../../models/";
+$modelCodeFilepath .= $skeleton;
+
+$modelCodeKernDir = $modelCodeFilepath . "/kernel_mod/";
+$modelCodeUspDir = $modelCodeFilepath . "/userspace/";
+$modelEpicsCodeDir = $modelCodeFilepath . "/epics/";
+
+#This generates /path/to/module(_usp)/modelname_core.c
+$modelCodeKernFilepath = $modelCodeKernDir. $skeleton . "_core.c"; 
+$modelCodeUspFilepath = $modelCodeUspDir . $skeleton . "_core.c";
+
+$modelHeaderFilepath = $modelCodeFilepath. "/include/";
+$modelHeaderFilepath .= $skeleton;
+$modelHeaderFilepath .= ".h";
+
+$meFile = $modelEpicsCodeDir;
 $meFile .= "Makefile\.";
 $meFile .= $ARGV[1];
 $meFile .= epics;
-$epicsScreensDir = "../../../build/" . $ARGV[1] . "epics/medm";
-$caqtdmScreensDir = "../../../build/" . $ARGV[1] . "epics/medm";
-$configFilesDir = "../../../build/" . $ARGV[1] . "epics/config";
-$compileMessageDir = "../../../";
-$warnMsgFile = $compileMessageDir . $ARGV[1] . "_warnings.log";
-$connectErrFile = $compileMessageDir . $ARGV[1] . "_partConnectErrors.log";
-$partConnectFile = $compileMessageDir . $ARGV[1] . "_partConnectionList.txt";
+
+$epicsScreensDir = $modelEpicsCodeDir ."src/medm";
+$caqtdmScreensDir = $modelEpicsCodeDir . "src/medm";
+$configFilesDir = $modelEpicsCodeDir . "src/config";
+$compileMessageDir = $modelCodeFilepath . "/logs/";
+
+$warnMsgFile = $compileMessageDir . $skeleton . "_warnings.log";
+$connectErrFile = $compileMessageDir . $skeleton . "_partConnectErrors.log";
+$partConnectFile = $compileMessageDir . $skeleton . "_partConnectionList.txt";
 $partConnectFileFilteredADC = $configFilesDir . "/partConnectionListFilteredADC.txt";
-$partSequenceFile = $compileMessageDir . $ARGV[1] . "_partSequence.txt";
+$partSequenceFile = $compileMessageDir . $skeleton . "_partSequence.txt";
 
 # This is where the various RCG output files are created and opened.
 if (@ARGV == 2) { $skeleton = $ARGV[1]; }
 # Open files for EPICS generation by fmseq.pl
 # Need to open early as Parser3.pm will write filter name info first.
-open(EPICS,">../fmseq/".$ARGV[1]) || die "cannot open output file for writing";
-open(DAQ,">../fmseq/".$ARGV[1]."_daq") || die "cannot open DAQ output file for writing";
+open(EPICS,">$modelEpicsCodeDir/fmseq/".$ARGV[1]) || die "cannot open output file for writing";
+open(DAQ,">$modelEpicsCodeDir/fmseq/".$ARGV[1]."_daq") || die "cannot open DAQ output file for writing";
 # Open compilation message files
 open(WARNINGS,">$warnMsgFile") || die "cannot open compile warnings output file for writing";
 open(CONN_ERRORS,">$connectErrFile") || die "cannot open compile warnings output file for writing";
-mkdir $cFileDirectory, 0755;
-mkdir $cFileDirectory2, 0755;
-open(OUT,">./".$cFile) || die "cannot open c file for writing $cFile";
-open(OUT2,">./".$cFile2) || die "cannot open c file for writing $cFile2";
+make_path( $modelCodeKernDir, { mode => 0755 });
+make_path( $modelCodeUspDir, { mode => 0755 });
+make_path( $modelEpicsCodeDir, { mode => 0755 });
+open(OUT,">./".$modelCodeKernFilepath) || die "cannot open c file for writing $modelCodeKernFilepath";
+open(OUT2,">./".$modelCodeUspFilepath) || die "cannot open c file for writing $modelCodeUspFilepath";
 # Save existing front-end Makefile
 @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
   my ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
@@ -241,7 +243,7 @@ if (-e $hfname) {
 	system("/bin/mv -f $hfname $hfname~");
 }
 # Need to open header file early, as calls in Parser3.pm will start the writing process.
-open(OUTH,">./".$hFile) || die "cannot open header file for writing";
+open(OUTH,">./".$modelHeaderFilepath) || die "cannot open header file for writing:".$modelHeaderFilepath;
 
 
 $mySeq = 0;
@@ -288,12 +290,11 @@ $dbg_level = 2;
 
 
 my $system_name = $ARGV[1];
-print OUTH "\#ifndef \U$system_name";
-print OUTH "_H_INCLUDED\n\#define \U$system_name";
-print OUTH "_H_INCLUDED\n";
+my $header_guard_string = "\U$system_name"."_H_INCLUDED";
+print OUTH "\#ifndef ".$header_guard_string."\n";
+print OUTH "\#define ".$header_guard_string."\n";
 print OUTH "\#define SYSTEM_NAME_STRING_LOWER \"\L$system_name\"\n";
 
-
 require "lib/ParsingDiagnostics.pm";
 
 #Initialize various parser variables.
@@ -801,7 +802,7 @@ print "Found $dacCnt DAC modules part is $dacPartNum[0]\n";
 print "Found $boCnt Binary modules part is $boPartNum[0]\n";
 
 ($::maxAdcModules, $::maxDacModules) =
-	CDS::Util::findDefine("src/include/drv/cdsHardware.h",
+	CDS::Util::findDefine("src/include/drv/cdsHardware.h", #Rest of path added in function
 			"MAX_ADC_MODULES", "MAX_DAC_MODULES");
 
 die "***ERROR: Too many ADC modules (MAX = $::maxAdcModules): ADC defined = $adcCnt\n" if ($adcCnt > $::maxAdcModules);
@@ -1161,10 +1162,17 @@ $inCnt = 0;
 #// Start the process of writing files.\n
 #//	- Write Epics/real-time data structures to header file.
 #//	- Write Epics structs common to all CDS front ends to the .h file.
+
+
 print OUTH "#define MAX_FIR \t $firCnt\n";
 print OUTH "#define MAX_FIR_POLY \t $firCnt\n\n";
 print EPICS "\nEPICS CDS_EPICS dspSpace coeffSpace epicsSpace\n\n";
 print EPICS "\n\n";
+
+print OUTH "#include \"drv/cdsHardware.h\"\n";
+$totalCardCount = $adcCnt + $dacCnt + $boCnt;
+print OUTH "extern CDS_CARDS cards_used[" . $totalCardCount . "];\n\n";
+
 print OUTH "typedef struct CDS_EPICS_IN {\n";
 print OUTH "\tint vmeReset;\n";
 print EPICS "MOMENTARY FEC\_$dcuId\_VME_RESET epicsInput.vmeReset int ao 0\n";
@@ -1556,7 +1564,6 @@ for($ii=0;$ii<$partCnt;$ii++)
   		print OUTH "\#define TARGET_CPU 1\n";
 	}
 	print OUTH "\#define TARGET_METER $cpuM\n";
-	print OUTH "\#endif\n";
 
 	#//	- Write EPICS database info file for later use by fmseq.pl in generating EPICS code/database.
 	#//		- Write info common to all models.
@@ -1628,24 +1635,35 @@ for($ii=0;$ii<$partCnt;$ii++)
 	# Start process of writing .c file. **********************************************************************
 	#//		- Standard opening information.
     print OUT <<END;
-    // ******* This is a computer generated file *******
-    // ******* DO NOT HAND EDIT ************************
+// ******* This is a computer generated file *******
+// ******* DO NOT HAND EDIT ************************
 
-    #include "fe.h"
+#include "fe.h"
+#include FE_HEADER
 
 END
 
-    # Define the code cycle rate
+    # Define the code cycle rate, TODO FE code also defines this
     print OUT "#define FE_RATE\t$gdsrate\n";
+
+    #Calculate and print IPC rate into HEADER
     if($gdsrate > 65536) {
-        print OUT "#define IPC_RATE\t65536\n\n";
+        print OUTH "#define IPC_RATE\t65536\n\n";
     } elsif ($ipcrate > 0) {
-        print OUT "#define IPC_RATE\t$ipcrate\n\n";
+        print OUTH "#define IPC_RATE\t$ipcrate\n\n";
         $ipccycle = $gdsrate / $ipcrate;
 	} else {
-        print OUT "#define IPC_RATE\t$gdsrate\n\n";
+        print OUTH "#define IPC_RATE\t$gdsrate\n\n";
     }
 
+    print OUTH "//#include \"fm10Gen_types.h\" //We can't include fm10Gen_types.h because we have a circular dependency.\n";
+    print OUTH "//So we just forward declare for now. \n";
+    print OUTH "typedef struct FILT_MOD FILT_MOD;\n";
+    print OUTH "typedef struct COEF COEF;\n";
+    print OUTH "\#ifdef __cplusplus\nextern \"C\" {\n\#endif\n"; 
+    print OUTH "int feCode(int cycle, double dWord[][32], double dacOut[][16], FILT_MOD *dsp_ptr, COEF *dspCoeff, CDS_EPICS *pLocalEpics, int feInit);\n\n";
+    print OUTH "\#ifdef __cplusplus\n}\n\#endif\n";
+
 
 	@adcCardNum;
 	@dacCardNum;
@@ -1700,6 +1718,8 @@ int feCode(int cycle,
 {
 
 int ii, dacFault;
+ii = 0; //Use so IOP models don't have a warning, some parts count on this being declared so we need it
+dacFault = 1; // Enabling DAC outs for those who don't have DAC KILL WD, 1 is normal no error case
 
 if(feInit)
 {
@@ -1725,8 +1745,6 @@ END
 		}
 	}
 	print OUT "\} else \{\n";
-	print OUT "// Enabling DAC outs for those who don't have DAC KILL WD \n";
-	print OUT "dacFault = 1;\n";
 
 	#//		- Main processing thread.
 	# IPCx PART CODE
@@ -1856,12 +1874,6 @@ print "\tPart number is $remoteGpsPart\n";
 
 }
 
-if($iopModel == 1) {
-	print OUT "#include \"$rcg_src_dir/src/fe/controllerIop.c\"\n";
-} else {
-  	print OUT "#include \"$rcg_src_dir/src/fe/controllerApp.c\"\n";
-}
-
 
 if($partsRemaining != 0) {
 	print WARNINGS "WARNING -- NOT ALL PARTS CONNECTED !!!!\n";
@@ -1881,35 +1893,16 @@ close OUT;
 close OUTD;
 close WARNINGS;
 
-#// Write the User Space Code Here
-open(OUT,"<./".$cFile) || die "cannot open c file for reading $cFile";
-open(OUT2,">./".$cFile2) || die "cannot open c file for writing $cFile2";
-while(my $line = <OUT>) {
-	if(index($line,"fe.h") != -1) {
-		print OUT2 "#include \"feuser.h\" \n";
-		print OUT2 "#include \<stdbool.h\> \n";
-	} 
-	elsif(index($line,"COMMDATA_INLINE") != -1 && $iopModel != 1) {
-		print OUT2 "#define COMMDATA_USP\n";
-	}
-	elsif(index($line,"controller") != -1 && $iopModel != 1) {
-		print OUT2 "#include \"$rcg_src_dir/src/fe/controllerAppUser.c\"\n";
-	}
-	elsif(index($line,"controller") != -1 && $iopModel == 1) {
-		print OUT2 "#include \"$rcg_src_dir/src/fe/controllerIopUser.c\"\n";
-	} else {
-		print OUT2 "$line";
-	}
-}
-close OUT;
-close OUT2;
+#// Write out the User Space Code Here (Just copy it, same code file for both)
+copy("./".$modelCodeKernFilepath, "./".$modelCodeUspFilepath) or die "copy failed: $! : ";
+	
 
 #//	- Write C code MAKEFILE
-require "lib/createKernelMakefile.pm";
-("CDS::KernelMakefile::createCmakefile") -> ($mFile);
+require "lib/createKernelModuleBuildEnv.pm";
+("CDS::KernelMakefileUtils::createKernelMakefiles") -> ($modelCodeKernDir);
 #//	- Write User Space C code MAKEFILE
-require "lib/createUserMakefile.pm";
-("CDS::USP_makefile::createUSPmakefile") -> ();
+require "lib/createUserModuleBuildEnv.pm";
+("CDS::USP_Cmake_Utils::createUSP_CmakeFiles") -> ($modelCodeUspDir);
 #//	- Write EPICS code MAKEFILE
 require "lib/createEpicsMakefile.pm";
 ("CDS::EpicsMakefile::createEpicsMfile") -> ($meFile);
@@ -1997,26 +1990,27 @@ print "Found $dacCnt DAC modules part is $dacPartNum[0]\n";
 
 if($::iopModel)
 {
-system("cp $rcg_src_dir/src/epics/util/IOP_IO_STATUS.adl IOP_IO_STATUS.adl");
-system("cat IOP_IO_STATUS.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_IOP_IO_STATUS.adl");
+#system("cp $rcg_src_dir/src/epics/util/IOP_IO_STATUS.adl IOP_IO_STATUS.adl");
+system("cat $rcg_src_dir/src/epics/util/IOP_IO_STATUS.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_IOP_IO_STATUS.adl");
 }
 #//		-  Generate SDF Restore Screen
-system("cp $rcg_src_dir/src/epics/util/SDF_RESTORE.adl SDF_RESTORE.adl");
-system("cat SDF_RESTORE.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_SDF_RESTORE.adl");
+#system("cp $rcg_src_dir/src/epics/util/SDF_RESTORE.adl SDF_RESTORE.adl");
+system("cat $rcg_src_dir/src/epics/util/SDF_RESTORE.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_SDF_RESTORE.adl");
 #//		-  Generate SDF Save Screen
-system("cp $rcg_src_dir/src/epics/util/SDF_SAVE.adl SDF_SAVE.adl");
-system("cat SDF_SAVE.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_SDF_SAVE.adl");
+#system("cp $rcg_src_dir/src/epics/util/SDF_SAVE.adl SDF_SAVE.adl");
+system("cat $rcg_src_dir/src/epics/util/SDF_SAVE.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_SDF_SAVE.adl");
 #//		-  Generate GDS Table Screen
-system("cp $rcg_src_dir/src/epics/util/GDS_TABLE.adl GDS_TABLE.adl");
-system("cat GDS_TABLE.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_GDS_TABLE.adl");
+#system("cp $rcg_src_dir/src/epics/util/GDS_TABLE.adl GDS_TABLE.adl");
+system("cat $rcg_src_dir/src/epics/util/GDS_TABLE.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_GDS_TABLE.adl");
 
 #//		-  Generate SDF Table Screen
 if ($::casdf) {
-system("cp $rcg_src_dir/src/epics/util/SDF_TABLE_CA.adl SDF_TABLE.adl");
+#system("cp $rcg_src_dir/src/epics/util/SDF_TABLE_CA.adl SDF_TABLE.adl");
+system("cat $rcg_src_dir/src/epics/util/SDF_TABLE_CA.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_SDF_TABLE.adl");
 } else {
-system("cp $rcg_src_dir/src/epics/util/SDF_TABLE.adl SDF_TABLE.adl");
+#system("cp $rcg_src_dir/src/epics/util/SDF_TABLE.adl SDF_TABLE.adl");
+system("cat $rcg_src_dir/src/epics/util/SDF_TABLE.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_SDF_TABLE.adl");
 }
-system("cat SDF_TABLE.adl | sed '$sed_arg' > $epicsScreensDir/$sysname" . "_SDF_TABLE.adl");
 
 my $cur_subsys_num = 0;
 
@@ -2294,9 +2288,10 @@ while (my $cf = readdir $dh) {
 
 #//	-  Print source file names into a file
 #
-open(OUT,">sources.\L$sysname\E") || die "cannot open \"sources.$sysname\" file for writing ";
+open(OUT,">$modelEpicsCodeDir/sources.\L$sysname\E") || die "cannot open \"$modelEpicsCodeDir/sources.$sysname\" file for writing ";
 print OUT join("\n", @sources), "\n";
 close OUT;
+print OUTH "\#endif //".$header_guard_string."\n";
 close OUTH;
 
 #//	
diff --git a/src/epics/util/fmseq.pl b/src/epics/util/fmseq.pl
index aa6d388242918f8f251e477f4290b9b0be87910a..eea92757e924e8980062a803f6b80d364c2519d7 100755
--- a/src/epics/util/fmseq.pl
+++ b/src/epics/util/fmseq.pl
@@ -285,6 +285,18 @@ while (<IN>) {
 	$vinit .= "%%       pEpics->${v_var} = evar_$v_name;\n";
 	$vinit .= "%%       pEpics->${v_var}_mask = 0;\n";
 
+	# allow burt restore to be triggered by a change in epics
+	# environment variable SDF_FILE_LOAD
+	if ($v_name =~ /BURT_RESTORE/) {
+ 	    $vupdate .= "%% sdf_file_loaded = get_sdf_file_loaded();\n";
+ 	    $vupdate .= "%% if(sdf_file_loaded != sdf_file_loaded_old) {\n";
+ 	    $vupdate .= "%%    printf(\"BURT_RESTORE triggered to %d\\n\", sdf_file_loaded);\n";
+ 	    $vupdate .= "%%    sdf_file_loaded_old = sdf_file_loaded;\n";
+ 	    $vupdate .= "%%    evar_$v_name = sdf_file_loaded;\n";
+ 	    $vupdate .= "      pvPut(evar_$v_name);\n";
+ 	    $vupdate .= "%% }\n";
+	}
+
         if ($ve_type ne "bi") {
 	$vupdate .= "%% if (pEpics->${v_var}_mask) {\n";
 	$vupdate .= "%%  evar_$v_name = pEpics->${v_var};\n";
diff --git a/src/epics/util/lib/GaussianNoiseGenerator.pm b/src/epics/util/lib/GaussianNoiseGenerator.pm
new file mode 100644
index 0000000000000000000000000000000000000000..ba425632fbaa0ca67e472f2c533a80e83ad48164
--- /dev/null
+++ b/src/epics/util/lib/GaussianNoiseGenerator.pm
@@ -0,0 +1,103 @@
+package CDS::GaussianNoiseGenerator;
+use Exporter;
+@ISA = ('Exporter');
+
+#//     \page GaussianNoiseGenerator Noise.pm
+#//     Documentation for GaussianNoiseGenerator.pm
+#//     This GaussianNoiseGenerator part generates gaussian 
+#//     random noise with 0 mean and 1 standard deviation.
+#//     
+#//     
+#//
+#// \n
+
+
+$printed = 0;
+$init_code_printed = 0;
+1;
+
+sub partType {
+    return GaussianNoiseGenerator;
+}
+
+# Print Epics communication structure into a header file
+# Current part number is passed as first argument
+sub printHeaderStruct {
+    my ($i) = @_;
+}
+
+# Print Epics variable definitions
+# Current part number is passed as first argument
+sub printEpics {
+    my ($i) = @_;
+}
+
+
+# Print variable declarations int front-end file
+# Current part number is passed as first argument
+sub printFrontEndVars  {
+    my ($i) = @_;
+
+    print ::OUT "static double \L$::xpartName[$i];\n";
+    if ($printed) { return; }
+
+    $state_name = "gauss_gen_prng_state";
+    print ::OUT "static uint64_t $state_name\[2\];\n";
+    print ::OUT "static inline double gaussianRandomDouble( void ) \n";
+    print ::OUT "{\n";
+    print ::OUT "   return qnorm5_s( ((double)xoroshiroPP_next( $state_name )/0xFFFFFFFFFFFFFFFF), 1, 0);\n";
+    print ::OUT "}\n";
+
+    $printed = 1;
+}
+
+# Check inputs are connected
+sub checkInputConnect {
+    my ($i) = @_;
+    return "";
+}
+
+# Figure out part input code
+# Argument 1 is the part number
+# Argument 2 is the input number
+# Returns calculated input code
+sub fromExp {
+    my ($i, $j) = @_;
+    my $from = $::partInNum[$i][$j];
+    return "\L$::xpartName[$from]";
+}
+
+# Return front end initialization code
+# Argument 1 is the part number
+# Returns calculated code string
+sub frontEndInitCode {
+    my ($i) = @_;
+
+    if ($init_code_printed) { return ""; }
+    my $calcExp  =  "\L$::xpartName[$i] = 0;\n";
+    if( $::gaussNoiseGeneratorSeed eq "none")
+    {
+        $calcExp .= "ligo_get_random_bytes(gauss_gen_prng_state, sizeof(gauss_gen_prng_state));\n";
+    }
+    else
+    {
+        #We don't want to have a zero seed for the RNG, so we take any user seed and 
+        #add a constant to it, that way we can support a 0 gaussNoiseGeneratorSeed
+        $calcExp .= "gauss_gen_prng_state[0] = 0x38ECAC5FB3251641ULL;\n";
+        $calcExp .= "gauss_gen_prng_state[1] = 0x145E556BD545B56BULL + $::gaussNoiseGeneratorSeed;\n";
+    }
+
+    $init_code_printed = 1;
+    return $calcExp;
+}
+
+
+# Return front end code
+# Argument 1 is the part number
+# Returns calculated code string
+sub frontEndCode {
+    my ($i) = @_;
+    my $calcExp = "// GaussiaNoiseGenerator\n";
+    $calcExp .= "\L$::xpartName[$i] " . "= gaussianRandomDouble();\n";
+    return $calcExp;
+}
diff --git a/src/epics/util/lib/IPCmonitor.pm b/src/epics/util/lib/IPCmonitor.pm
index 4a976dff515559e81d889239cc62a81db93c0958..d0f26f0353da1c739a973cbb4cadc44f2d1fd8b1 100644
--- a/src/epics/util/lib/IPCmonitor.pm
+++ b/src/epics/util/lib/IPCmonitor.pm
@@ -1,5 +1,7 @@
 package CDS::IPCmonitor;
 use Exporter;
+use Fcntl qw(:flock);
+use File::Path;
 @ISA = ('Exporter');
 
 #//	\page IPCx IPCx.pm
@@ -227,13 +229,22 @@ my @ipcxMaxNum = (-999,-999,-999,-999);
 
    # Develop name of IPC parameter file based on return from above.
         #my ($i) = @_;
-	my $iFile = $::target;
-	$iFile .= "/chans/ipc/";
-	$iFile .= $::ifo;
-	$iFile .= "\.ipc";
+        my $iFilePath =  $::target;
+	$iFilePath .= "/chans/ipc/";
+	my $iFile .= $iFilePath . $::ifo;
+        $iFile .= "\.ipc";
    # Open and input data from IPC parameter file
+   File::Path::make_path($iFilePath);
+   unless (-e $iFile)
+   {
+   	open(TOUCH, ">>$iFile");
+   	close(TOUCH);
+   }
+
    open(IPCIN, "<$iFile") || die "***ERROR: IPCx parameter file $iFile not found\n";
+   flock(IPCIN, LOCK_SH) || die "***ERROR: IPCx parameter file $iFile not locked: $!\n";
    chomp(@inData=<IPCIN>);
+   flock(IPCIN, LOCK_UN) || die "***ERROR: IPCx parameter file $iFile not unlocked: $!\n";
    close IPCIN;
 
    #
diff --git a/src/epics/util/lib/IPCx.pm b/src/epics/util/lib/IPCx.pm
index 714f86e114fa84f2c02455400113e00683b1d2eb..7230da1f4238f336c2c12047e0b3ee0f99f504bf 100644
--- a/src/epics/util/lib/IPCx.pm
+++ b/src/epics/util/lib/IPCx.pm
@@ -1,6 +1,8 @@
 package CDS::IPCx;
 use File::Path qw( make_path );
 use Exporter;
+use File::Path;
+use Fcntl qw(:flock);
 @ISA = ('Exporter');
 
 #//	\page IPCx IPCx.pm
@@ -332,24 +334,22 @@ if ($::ipcxCnt > 0) {
 
 
    # Develop name of IPC parameter file based on return from above.
-    my $iFile = $::target;
-    $iFile .= "/chans/ipc/";
-    if ( !-d $iFile ) {
-        make_path $iFile or die "***ERROR: Could not create the $iFile directory for the IPCx parameter file\n";
-    }
-    $iFile .= $::ifo;
-    $iFile .= "\.ipc";
-
-
-    #Create the file if it doesn't exist
-    if( !-e $iFile) {
-        open my $fc, ">", $iFile or die "***ERROR: Could not create the empty IPCx parameter file $iFile\n";
-        close $fc;
-    }
-
+   my $iFilePath =  $::target;
+   $iFilePath .= "/chans/ipc/";
+   my $iFile .= $iFilePath . $::ifo;
+   $iFile .= "\.ipc";
    # Open and input data from IPC parameter file
+   File::Path::make_path($iFilePath);
+   unless (-e $iFile)
+   {
+     open(TOUCH, ">>$iFile");
+     close(TOUCH);
+   }
+
    open(IPCIN, "<$iFile") || die "***ERROR: IPCx parameter file $iFile not found\n";
+   flock(IPCIN, LOCK_SH) || die "***ERROR: Failed to lock file $iFIle: $!\n";
    chomp(@inData=<IPCIN>);
+   flock(IPCIN, LOCK_UN) || die "***ERROR: Failed to unlock file $iFIle: $!\n";
    close IPCIN;
 
    #
@@ -590,7 +590,9 @@ $ipcxRcvrCnt = 0;
    # Check if there are any IPCx modules to add to the IPCx parts matrix
    #
    if ($ipcxNotFound > 0) {
+
       open (IPCOUT, ">>$iFile") || die "***ERROR: Could not open IPCx parameter file $iFile for output\n";
+      flock (IPCOUT, LOCK_EX) || die "***ERROR: Failed to lock IPCx parameter file $iFile for output: $!\n";
 
       $ipcxRate = 983040/$::rate;
       $ipcxNew = 0;
@@ -668,6 +670,7 @@ $ipcxRcvrCnt = 0;
          }
       }
 
+      flock (IPCOUT, LOCK_UN) || die "***ERROR: Failed to unlock IPCx parameter file $iFile for output: $!\n";
       close IPCOUT;
 
 
diff --git a/src/epics/util/lib/Noise.pm b/src/epics/util/lib/Noise.pm
index 59a467d55eb9142f56822ada19b820155bf19a07..1e9243cca04afd543e7290ed021a5884e1bc1aed 100644
--- a/src/epics/util/lib/Noise.pm
+++ b/src/epics/util/lib/Noise.pm
@@ -4,6 +4,10 @@ use Exporter;
 
 #//     \page Noise Noise.pm
 #//     Documentation for Noise.pm
+#//     This Noise part generates uniform random noise in the 
+#//     (0, 1) range. This block utilizes the pseudo-random number 
+#//     generator from page 342  (section 7.1) of the third edition 
+#//     of Numerical recipies. 
 #//
 #// \n
 
@@ -13,32 +17,33 @@ $init_code_printed = 0;
 1;
 
 sub partType {
-	return Noise;
+    return Noise;
 }
 
 # Print Epics communication structure into a header file
 # Current part number is passed as first argument
 sub printHeaderStruct {
-        my ($i) = @_;
+    my ($i) = @_;
 }
 
 # Print Epics variable definitions
 # Current part number is passed as first argument
 sub printEpics {
-        my ($i) = @_;
+    my ($i) = @_;
 }
 
 
 # Print variable declarations int front-end file
 # Current part number is passed as first argument
 sub printFrontEndVars  {
-        my ($i) = @_;
-	print ::OUT "static double \L$::xpartName[$i];\n";
-	if ($printed) { return; }
-	print ::OUT << "END";
-static unsigned long noise_seed = 4101842887655102017LL;\n
-static unsigned long noise_u, noise_v, noise_w;
-inline unsigned long noise_int64() {
+    my ($i) = @_;
+    print ::OUT "static double \L$::xpartName[$i];\n";
+    if ($printed) { return; }
+
+    print ::OUT << "END";
+static unsigned long noise_seed = 0;
+static unsigned long noise_u = 0, noise_v = 0, noise_w = 0;
+static inline unsigned long noise_int64( void ) {
    noise_u = noise_u * 2862933555777941757LL + 7046029254386353087LL;
    noise_v ^= noise_v >> 17; noise_v ^= noise_v << 31; noise_v ^= noise_v >> 8;
    noise_w = 4294957665U * (noise_w & 0xffffffff) + (noise_w >> 32);
@@ -46,11 +51,11 @@ inline unsigned long noise_int64() {
    noise_x ^= noise_x >> 35; noise_x ^= noise_x <<4;
    return (noise_x + noise_v) ^ noise_w;
 }
-inline double noise_doub() { return 5.42101086242752217E-20 * noise_int64(); }
-inline noise_ran(unsigned long j) {
+static inline double noise_doub( void ) { return 5.42101086242752217E-20 * noise_int64(); }
+static inline void noise_set_seed(unsigned long seed) {
    noise_v = 4101842887655102017LL;
    noise_w = 1;
-   noise_u = j ^ noise_v; noise_int64();
+   noise_u = seed ^ noise_v; noise_int64();
    noise_v = noise_u; noise_int64();
    noise_w = noise_v; noise_int64();
 }
@@ -60,8 +65,8 @@ $printed = 1;
 
 # Check inputs are connected
 sub checkInputConnect {
-        my ($i) = @_;
-        return "";
+    my ($i) = @_;
+    return "";
 }
 
 # Figure out part input code
@@ -69,23 +74,30 @@ sub checkInputConnect {
 # Argument 2 is the input number
 # Returns calculated input code
 sub fromExp {
-        my ($i, $j) = @_;
-        my $from = $::partInNum[$i][$j];
-        return "\L$::xpartName[$from]";
+    my ($i, $j) = @_;
+    my $from = $::partInNum[$i][$j];
+    return "\L$::xpartName[$from]";
 }
 
 # Return front end initialization code
 # Argument 1 is the part number
 # Returns calculated code string
 sub frontEndInitCode {
-	my ($i) = @_;
-	if ($init_code_printed) { return ""; }
-        my $calcExp  =  "\L$::xpartName[$i] = 0;\n";
-	$calcExp    .=  "for (;noise_seed == 4101842887655102017LL;) {\n";
-        $calcExp    .=  "   rdtscl(noise_seed);\n";
-        $calcExp    .=  "}\n";
-	$init_code_printed = 1;
-	return $calcExp;
+    my ($i) = @_;
+    if ($init_code_printed) { return ""; }
+    my $calcExp  =  "\L$::xpartName[$i] = 0;\n";
+
+    #If we don't have an explicit seed set, get one from the tsc register
+    if ( $::noiseGeneratorSeed eq "none" ) {
+        $calcExp    .=  "noise_seed = getMonotonic_ns_utin64();\n";
+    }
+    else {
+        $calcExp    .=  "noise_seed = " . $::noiseGeneratorSeed . "UL;\n";
+    }
+    $calcExp    .=  "noise_set_seed(noise_seed);\n";
+
+    $init_code_printed = 1;
+    return $calcExp;
 }
 
 
@@ -93,7 +105,8 @@ sub frontEndInitCode {
 # Argument 1 is the part number
 # Returns calculated code string
 sub frontEndCode {
-	my ($i) = @_;
-        my $calcExp = "// Noise\n";
-        $calcExp .= "\L$::xpartName[$i] = noise_doub();\n";
+    my ($i) = @_;
+    my $calcExp = "// Noise\n";
+    $calcExp .= "\L$::xpartName[$i] = noise_doub();\n";
+    return $calcExp;
 }
diff --git a/src/epics/util/lib/Parameters.pm b/src/epics/util/lib/Parameters.pm
index 776f55800f937d233e4fe031a37cf0016ff59dd2..9b72c12b7f5a75c75a2e424dafa17e06e25819a1 100644
--- a/src/epics/util/lib/Parameters.pm
+++ b/src/epics/util/lib/Parameters.pm
@@ -232,6 +232,14 @@ sub parseParams {
                 {
 				    $::requireIOcnt = $spp[1];
                 }
+                case "noiseGeneratorSeed"
+                {
+                    $::noiseGeneratorSeed = $spp[1];
+                }
+                case "gaussNoiseGeneratorSeed"
+                {
+                    $::gaussNoiseGeneratorSeed = $spp[1];
+                }
                 case "virtualIOP"
                 {
 				    $::virtualiop = $spp[1];
diff --git a/src/epics/util/lib/Phase.pm b/src/epics/util/lib/Phase.pm
index b9d3b2e8c6c74d0a358306f42cad60b3fa2cff42..ad765bc9e316f5f27e0c0417a4fb758550137b33 100644
--- a/src/epics/util/lib/Phase.pm
+++ b/src/epics/util/lib/Phase.pm
@@ -32,7 +32,7 @@ sub printEpics {
 # Current part number is passed as first argument
 sub printFrontEndVars  {
         my ($i) = @_;
-        print ::OUT "static double \L$::xpartName[$i]\_E;\n";
+        #print ::OUT "static double \L$::xpartName[$i]\_E;\n";
         print ::OUT "static double \L$::xpartName[$i]\[2\];\n";
 }
 
diff --git a/src/epics/util/lib/Product.pm b/src/epics/util/lib/Product.pm
index 2c1a80f6ff320ed10feb512b8836ad26243a5645..793f05d6c039808659ba9528b47ba6106656e82e 100644
--- a/src/epics/util/lib/Product.pm
+++ b/src/epics/util/lib/Product.pm
@@ -35,7 +35,7 @@ sub printEpics {
 sub printFrontEndVars  {
         my ($i) = @_;
         print ::OUT "double \L$::xpartName[$i]\[8\];\n";
-        print ::OUT "double $::xpartName[$i]\_CALC;\n";
+        print ::OUT "float $::xpartName[$i]\_CALC;\n";
 }
 
 # Check inputs are connected
diff --git a/src/epics/util/lib/Util.pm b/src/epics/util/lib/Util.pm
index 23d2f372af147533270899719dcc63549c0cf840..c3f6cd0c4c408d112690e381e0db4cb7e879c173 100644
--- a/src/epics/util/lib/Util.pm
+++ b/src/epics/util/lib/Util.pm
@@ -17,7 +17,7 @@ sub findDefine {
 
    # Determine allowed maximum IPC number
    open(CD2, "$::rcg_src_dir/" . $fname)
-	|| die "***ERROR: could not open $fname header\n";
+	|| die "***ERROR: could not open $::rcg_src_dir/$fname header\n";
    my @inData=<CD2>;
    close CD2;
    foreach $i (@defs) {
diff --git a/src/epics/util/lib/createEpicsMakefile.pm b/src/epics/util/lib/createEpicsMakefile.pm
index 78d42aa434cde62e0886c000e11bf7b3c4eb279c..9d62d2ad001ac744993b33306cc451de73ef5b30 100644
--- a/src/epics/util/lib/createEpicsMakefile.pm
+++ b/src/epics/util/lib/createEpicsMakefile.pm
@@ -13,8 +13,12 @@ my ($fileName) = @_;
 	print OUTME "# Define Epics system name. It should be unique.\n";
 	print OUTME "TARGET = $::skeleton";
 	print OUTME "epics\n";
-	print OUTME "\n";
-	print OUTME "SRC = build/\$(TARGET)/";
+    print OUTME "MODEL_BUILD_DIR:= models/$::skeleton/\n";
+    print OUTME "MODEL_EPICS_DIR:= \$(MODEL_BUILD_DIR)/epics\n";
+    print OUTME "MODEL_EPICS_SRC_DIR:= \$(MODEL_EPICS_DIR)/src\n";
+    print OUTME "MODEL_EPICS_BUILD_DIR:= \$(MODEL_BUILD_DIR)/target/$::skeleton"."epics/\n";
+    print OUTME "\n";
+	print OUTME "SRC = \$(MODEL_EPICS_SRC_DIR)/";
 	print OUTME "$::skeleton";
 	print OUTME "\.st\n";
 	print OUTME "\n";
@@ -23,8 +27,9 @@ my ($fileName) = @_;
 	}elsif ($globalsdf) {
 	print OUTME "SRC += $::rcg_src_dir/src/epics/seq/sdf_monitor.c\n";
 	} else {
-	print OUTME "SRC += $::rcg_src_dir/src/epics/seq/main.c\n";
+	print OUTME "SRC += $::rcg_src_dir/src/epics/seq/main.cc\n";
 	}
+	print OUTME "SRC += $::rcg_src_dir/src/epics/seq/sdf_file_loaded.c\n";
 	print OUTME "SRC += $::rcg_src_dir/src/drv/rfm.c\n";
 	print OUTME "SRC += $::rcg_src_dir/src/drv/param.c\n";
 	print OUTME "SRC += $::rcg_src_dir/src/drv/crc.c\n";
@@ -42,7 +47,7 @@ my ($fileName) = @_;
 	}
 	print OUTME "\n";
 	#print OUTME "DB += src/epics/db/local_time.db\n";
-	print OUTME "DB += build/\$(TARGET)/";
+	print OUTME "DB += \$(MODEL_EPICS_SRC_DIR)/";
 	print OUTME "$::skeleton";
 	print OUTME "1\.db\n";
 	print OUTME "\n";
@@ -92,9 +97,9 @@ my ($fileName) = @_;
 	}
 	print OUTME "include $::rcg_src_dir/config/Makefile.linux\n";
 	print OUTME "\n";
-	print OUTME "build/\$(TARGET)/";
+	print OUTME "\$(MODEL_EPICS_SRC_DIR)/";
 	print OUTME "$::skeleton";
-	print OUTME "1\.db: build/\$(TARGET)/";
+	print OUTME "1\.db: \$(MODEL_EPICS_SRC_DIR)/";
 	print OUTME "$::skeleton";
 	print OUTME "\.db\n";
 	print OUTME "\tsed 's/%SYS%/";
diff --git a/src/epics/util/lib/createKernelMakefile.pm b/src/epics/util/lib/createKernelModuleBuildEnv.pm
similarity index 70%
rename from src/epics/util/lib/createKernelMakefile.pm
rename to src/epics/util/lib/createKernelModuleBuildEnv.pm
index e17fccf5e4917c5c7654508d204403badf3d8972..7c9afd34d48cb094dd3b1e41661a70f8133e3f66 100644
--- a/src/epics/util/lib/createKernelMakefile.pm
+++ b/src/epics/util/lib/createKernelModuleBuildEnv.pm
@@ -1,23 +1,51 @@
-package CDS::KernelMakefile;
+package CDS::KernelMakefileUtils;
 use Exporter;
 @ISA = ('Exporter');
 
-#// \b sub \b createCmakefile \n
-#// Generate the user C code Makefile  \n\n
-sub createCmakefile{
-my ($fileName) = @_;
+#// \b sub \b createKernelMakefiles \n
+#// Move the standard kernel makefile into the build dir
+#// and generate KernelVars.mk build env file.  \n\n
+sub createKernelMakefiles{
+my ($makefileDir) = @_;
 
 # Compile options common to all runtime configurations
-system ("/bin/cp GNUmakefile  ../../fe/$::skeleton");
-open(OUTM,">./".$fileName) || die "cannot open Makefile file for writing";
+system ("/bin/cp Makefile.kernel $::modelCodeKernDir/Makefile");
+
+open(OUTM,">./".$makefileDir."KernelVars.mk") || die "cannot open Makefile (".$makefileDir."KernelVars.mk) file for writing";
 
 print OUTM "# CPU-Shutdown Real Time Linux\n";
+print OUTM "MODEL_NAME:=$::skeleton\n";
+if ($::iopModel > -1) {
+    print OUTM "IOP_MODEL:=1\n";
+}
+if ($::dolphinTiming > -1 or $::virtualiop == 2) {
+    print OUTM "USE_DOLPHIN_TIMING:=1\n";
+}
+if ($::dolphin_time_xmit > -1) {
+    print OUTM "XMIT_DOLPHIN_TIME:=1\n";
+}
+if ($::virtualiop != 1) {
+    if ($::pciNet > 0) {
+        print OUTM "BUILD_WITH_DOLPHIN:=1\n";
+    }
+}
+
+#
+# Start KBUILD_EXTRA_SYMBOLS for the kernel module build
 print OUTM "KBUILD_EXTRA_SYMBOLS = $::mbufsymfile\n";
 print OUTM "KBUILD_EXTRA_SYMBOLS += $::gpssymfile\n";
 print OUTM "KBUILD_EXTRA_SYMBOLS += $::cpuisolatorfile\n";
-print OUTM "KBUILD_EXTRA_SYMBOLS += \$(PWD)/ModuleIOP.symvers\n";
-print OUTM "ALL \+= user_mmap \$(TARGET_RTL)\n";
-print OUTM "EXTRA_CFLAGS += -O -w -I../../include\n";
+
+#if ($::iopModel == -1) { #Not IOP model - Leaving this in (for now) so we can inject symbols we want by editing the symvers file
+    print OUTM "KBUILD_EXTRA_SYMBOLS += \$(mkfile_dir)/../../ModuleIOP.symvers\n";
+#}
+
+print OUTM "EXTRA_CFLAGS += -std=gnu11 \n";
+print OUTM "EXTRA_CFLAGS += -O \n";
+print OUTM "EXTRA_CFLAGS += -Wno-date-time \n";
+print OUTM "EXTRA_CFLAGS += -Wno-declaration-after-statement #Off explicitly because kbuild sets it on\n ";
+print OUTM "EXTRA_CFLAGS += -Wframe-larger-than=4096 #KBuild'd default is 2048, but we are making it a bit larger\n ";
+print OUTM "EXTRA_CFLAGS += -Wno-unused-function #Pattern of c file inclusion and usage of some of the functions makes this a hard fix\n";
 print OUTM "EXTRA_CFLAGS += -I$::rcg_src_dir/src/drv/\n";
 
 print OUTM "EXTRA_CFLAGS += $::servoflag \n";
@@ -143,13 +171,30 @@ if ($::iopModel > -1) {  #************ SETUP FOR IOP ***************
         if ($::dolphinGen == 2) {
           print OUTM "#Enable use of PCIe RFM Network Gen 2\n";
           print OUTM "DISDIR = /opt/srcdis\n";
-          print OUTM "KBUILD_EXTRA_SYMBOLS += \$(DISDIR)/src/SCI_SOCKET/ksocket/LINUX/Module.symvers\n";
-          print OUTM "EXTRA_CFLAGS += -DOS_IS_LINUX=1 -D_DIS_KERNEL_=1 -I\$(DISDIR)/src/IRM_GX/drv/src -I\$(DISDIR)/src/IRM_GX/drv/src/LINUX -I\$(DISDIR)/src/include -I\$(DISDIR)/src/include/dis -I\$(DISDIR)/src/COMMON/osif/kernel/include -I\$(DISDIR)/src/COMMON/osif/kernel/include/LINUX -DDOLPHIN_TEST=1  -DDIS_BROADCAST=0x80000000\n";
+          print OUTM "KERNEL_RELEASE := \$(shell uname -r)\n";
+
+          print OUTM "KBUILD_EXTRA_SYMBOLS += /opt/DIS/lib/modules/\$(KERNEL_RELEASE)/dis_sisci.symvers\n";
+          print OUTM "EXTRA_CFLAGS += -DDOLPHIN_TEST=1 -DDIS_BROADCAST=0x80000000\n";
+          print OUTM "EXTRA_CFLAGS += -DOS_IS_LINUX=1 -D_DIS_KERNEL_=1 \n";
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/include/ \n";
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/include/dis/ \n";
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/IRM_GX/drv/src \n";
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/IRM_GX/drv/src/LINUX \n";
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/COMMON/osif/kernel/include \n";
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/COMMON/osif/kernel/include/LINUX \n";
+          
 	} else {
           print OUTM "#Enable use of PCIe RFM Network Gen 1\n";
           print OUTM "DISDIR = /opt/srcdis\n";
           print OUTM "KBUILD_EXTRA_SYMBOLS += \$(DISDIR)/src/SCI_SOCKET/ksocket/lib/LINUX/Module.symvers\n";
-          print OUTM "EXTRA_CFLAGS += -DOS_IS_LINUX=1 -D_KERNEL=1 -I\$(DISDIR)/src/IRM/drv/src -I\$(DISDIR)/src/IRM/drv/src/LINUX -I\$(DISDIR)/src/include -I\$(DISDIR)/src/include/dis -DDOLPHIN_TEST=1  -DDIS_BROADCAST=0x80000000\n";
+            
+          print OUTM "EXTRA_CFLAGS += -DOS_IS_LINUX=1 -D_KERNEL=1 \n";
+          print OUTM "EXTRA_CFLAGS += -DDOLPHIN_TEST=1 -DDIS_BROADCAST=0x80000000\n";
+
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/IRM/drv/src \n";
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/IRM/drv/src/LINUX \n";
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/include \n";
+          print OUTM "EXTRA_CFLAGS += -I\$(DISDIR)/src/include/dis \n";
         }
   }
  }
@@ -209,25 +254,9 @@ if ($::iopModel < 1) {   #************ SETUP FOR USER APP ***************
 }  #******************* END SETUP FOR USER APP
 
 
-
-print OUTM "\n";
-print OUTM "ifneq (\$(CDIR),)\n";
-print OUTM "override EXTRA_CFLAGS += \$(patsubst %,-I../../../%,\$(CDIR))\n";
-print OUTM "endif\n";
-
-print OUTM "\n";
-print OUTM "all: \$(ALL)\n";
-print OUTM "\n";
-print OUTM "clean:\n";
-print OUTM "\trm -f \$(ALL) *.o\n";
-print OUTM "\n";
-
 print OUTM "EXTRA_CFLAGS += -DMODULE -DNO_RTL=1\n";
-print OUTM "EXTRA_CFLAGS += -I\$(SUBDIRS)/../../include -I$::rcg_src_dir/src/include\n";
+print OUTM "EXTRA_CFLAGS += -I\$(SUBDIRS)/../../../models/" . "\L$::skeleton" . "/include -I$::rcg_src_dir/src/include\n";
 print OUTM "EXTRA_CFLAGS += -ffast-math -m80387 -msse2 -fno-builtin-sincos -mpreferred-stack-boundary=4\n";
-
-print OUTM "obj-m += $::skeleton" . ".o\n";
-
 print OUTM "\n";
 close OUTM;
 }
diff --git a/src/epics/util/lib/createUserMakefile.pm b/src/epics/util/lib/createUserMakefile.pm
deleted file mode 100644
index 154941d127aff39526fe7d01cc8477c44b8e8ee5..0000000000000000000000000000000000000000
--- a/src/epics/util/lib/createUserMakefile.pm
+++ /dev/null
@@ -1,219 +0,0 @@
-package CDS::USP_makefile;
-use Exporter;
-@ISA = ('Exporter');
-
-#// \b sub \b createUsermakefile \n
-#// Generate the user C code Makefile  \n\n
-sub createUSPmakefile{
-
-open(OUTM,">./".$::mFile2) || die "cannot open Makefile file for writing";
-
-print OUTM "# User Space Linux\n";
-print OUTM "CFLAGS += -O -w -I../../include\n";
-
-print OUTM "CFLAGS += $::servoflag \n";
-
-if ($::iopModel > -1) {  #************ SETUP FOR IOP ***************
-#Following used for IOP running at 128K 
-  if($::adcclock ==128) {
-  print OUTM "CFLAGS += -DIOP_IO_RATE=131072\n";
-  } else {
-  print OUTM "CFLAGS += -DIOP_IO_RATE=65536\n";
-  }
-# Invoked if IOP cycle rate slower than ADC clock rate
-  print OUTM "CFLAGS += -DUNDERSAMPLE=$::clock_div\n";
-  print OUTM "CFLAGS += -DADC_MEMCPY_RATE=$::adcclock\n";
-} 
-
-print OUTM "CFLAGS += -D";
-print OUTM "\U$::skeleton";
-print OUTM "_CODE\n";
-print OUTM "CFLAGS += -DFE_SRC=\\\"\L$::skeleton/\L$::skeleton.c\\\"\n";
-print OUTM "CFLAGS += -DFE_HEADER=\\\"\L$::skeleton.h\\\"\n";
-#print OUTM "CFLAGS += -DFE_PROC_FILE=\\\"\L$::{skeleton}_proc.h\\\"\n";
-
-print OUTM "CFLAGS += -g\n";
-
-if ($::remoteGPS) {
-  print OUTM "CFLAGS += -DREMOTE_GPS\n";
-}
-if($::systemName eq "sei" || $::useFIRs)
-{
-print OUTM "CFLAGS += -DFIR_FILTERS\n";
-}
-if ($::no_sync) {
-  print OUTM "#Comment out to enable 1PPS synchronization\n";
-  print OUTM "CFLAGS += -DNO_SYNC\n";
-} else {
-  print OUTM "#Uncomment to disable 1PPS signal sinchronization (channel 31 (last), ADC 0)\n";
-  print OUTM "#CFLAGS += -DNO_SYNC\n";
-}
-if (0 == $::dac_testpoint_names && 0 == $::::extraTestPoints && 0 == $::filtCnt) {
-	print "Not compiling DAQ into the front-end\n";
-	$::no_daq = 1;
-}
-if ($::no_daq) {
-  print OUTM "#Comment out to enable DAQ\n";
-  print OUTM "CFLAGS += -DNO_DAQ\n";
-}
-
-# Use oversampling code if not 64K system
-#if($::modelrate < 64) {
-#  if ($::no_oversampling) {
-#    print OUTM "#Uncomment to oversample A/D inputs\n";
-#    print OUTM "#CFLAGS += -DOVERSAMPLE\n";
-#    print OUTM "#Uncomment to interpolate D/A outputs\n";
-#    print OUTM "#CFLAGS += -DOVERSAMPLE_DAC\n";
-#  } else {
-#    print OUTM "#Comment out to stop A/D oversampling\n";
-#    print OUTM "CFLAGS += -DOVERSAMPLE\n";
-#    if ($::no_dac_interpolation) {
-#    } else {
-#      print OUTM "#Comment out to stop interpolating D/A outputs\n";
-#      print OUTM "CFLAGS += -DOVERSAMPLE_DAC\n";
-#    }
-#  }
-#}
-
-#Following used with IOP running at 64K (NORMAL)
-
-
-
-if($::modelrate < 64) {
-  if($::adcclock ==64) {
-    print OUTM "CFLAGS += -DIOP_IO_RATE=65536\n";
-    if($::modelrate < 64) {
-        my $drate = 64/$::modelrate;
-        if($drate == 8 or $drate > 32) {
-            die "RCG does not support a user model rate $::modelrate" . "K with IOP data at $::adcclock" ."K\n"  ;
-        }
-        print OUTM "CFLAGS += -DOVERSAMPLE\n";
-        print OUTM "CFLAGS += -DOVERSAMPLE_DAC\n";
-        print OUTM "CFLAGS += -DOVERSAMPLE_TIMES=$drate\n";
-        print OUTM "CFLAGS += -DFE_OVERSAMPLE_COEFF=feCoeff$drate"."x\n";
-        print OUTM "CFLAGS += -DADC_MEMCPY_RATE=1\n";
-    }
-  }
-}
-
-print OUTM "CFLAGS += -DUNDERSAMPLE=1\n";
-$modelrate_cps = $::modelrate * 1024;
-print OUTM "CFLAGS += -DMODEL_RATE_CPS=$modelrate_cps\n";
-
-if ($::iopModel > -1) {
-  $::modelType = "IOP";
-  if($::diagTest > -1) {
-  print OUTM "CFLAGS += -DDIAG_TEST\n";
-  }
-  if($::dacWdOverride > -1) {
-  print OUTM "CFLAGS += -DDAC_WD_OVERRIDE\n";
-  }
-  # ADD DAC_AUTOCAL to IOPs
-  print OUTM "CFLAGS += -DDAC_AUTOCAL\n";
-} else {
-  print OUTM "#Uncomment to run on an I/O Master \n";
-  print OUTM "#CFLAGS += -DIOP_MODEL\n";
-}
-if ($::iopModel < 1) {
-  print OUTM "CFLAGS += -DCONTROL_MODEL\n";
-  $::modelType = "CONTROL";
-} 
-if ($::dolphin_time_xmit > -1) {
-  print OUTM "CFLAGS += -DXMIT_DOLPHIN_TIME=1\n";
-} 
-if ($::dolphinTiming > -1) {
-  print OUTM "CFLAGS += -DUSE_DOLPHIN_TIMING=1\n";
-} 
-if ($::flipSignals) {
-  print OUTM "CFLAGS += -DFLIP_SIGNALS=1\n";
-}
-
- if ($::virtualiop != 1) {
-if ($::pciNet > 0) {
-print OUTM "#Enable use of PCIe RFM Network Gen 2\n";
-print OUTM "DOLPHIN_PATH = /opt/srcdis\n";
-print OUTM "CFLAGS += -DHAVE_CONFIG_H -I\$::(DOLPHIN_PATH)/src/include/dis -I\$::(DOLPHIN_PATH)/src/include -I\$::(DOLPHIN_PATH)/src/SISCI/cmd/test/lib -I\$::(DOLPHIN_PATH)/src/SISCI/src -I\$::(DOLPHIN_PATH)/src/SISCI/api -I\$::(DOLPHIN_PATH)/src/SISCI/cmd/include -I\$::(DOLPHIN_PATH)/src/IRM_GX/drv/src -I\$::(DOLPHIN_PATH)/src/IRM_GX/drv/src/LINUX -DOS_IS_LINUX=196616 -DLINUX -DUNIX  -DLITTLE_ENDIAN -DDIS_LITTLE_ENDIAN -DCPU_WORD_IS_64_BIT -DCPU_ADDR_IS_64_BIT -DCPU_WORD_SIZE=64 -DCPU_ADDR_SIZE=64 -DCPU_ARCH_IS_X86_64 -DADAPTER_IS_IX   -m64 -D_REENTRANT\n";
-}
-}
-
-if ($::specificCpu > -1) {
-  print OUTM "#Comment out to run on first available CPU\n";
-  print OUTM "CFLAGS += -DSPECIFIC_CPU=$::specificCpu\n";
-} else {
-  print OUTM "#Uncomment to run on a specific CPU\n";
-  print OUTM "#CFLAGS += -DSPECIFIC_CPU=2\n";
-}
-
-# Set BIQUAD as default starting RCG V2.8
-  print OUTM "#Comment out to go back to old iir_filter calculation form\n";
-  print OUTM "CFLAGS += -DALL_BIQUAD=1 -DCORE_BIQUAD=1\n";
-
-if ($::::directDacWrite) {
-  print OUTM "CFLAGS += -DDIRECT_DAC_WRITE=1\n";
-} else {
-  print OUTM "#CFLAGS += -DDIRECT_DAC_WRITE=1\n";
-}
-
-if ($::::noZeroPad) {
-  print OUTM "CFLAGS += -DNO_ZERO_PAD=1\n";
-} else {
-  print OUTM "#CFLAGS += -DNO_ZERO_PAD=1\n";
-}
-
-if ($::::optimizeIO) {
-  print OUTM "CFLAGS += -DNO_DAC_PRELOAD=1\n";
-} else {
-  print OUTM "#CFLAGS += -DNO_DAC_PRELOAD=1\n";
-}
-
-if ($::::rfmDelay) {
-  print OUTM "#Comment out to run without RFM Delayed by 1 cycle\n";
-  print OUTM "CFLAGS += -DRFM_DELAY=1\n";
-} else {
-  print OUTM "#Clear comment to run with RFM Delayed by 1 cycle\n";
-  print OUTM "#CFLAGS += -DRFM_DELAY=1\n";
-}
-  print OUTM "CFLAGS += -DUSER_SPACE=1\n";
-  print OUTM "CFLAGS += -fno-builtin-sincos\n";
-
-if ($::userspacegps) {
-  print OUTM "CFLAGS += -DUSE_GPSCLOCK\n";
-}
-
-print OUTM "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/opt/DIS/lib64\n";
-print OUTM "API_LIB_PATH=/opt/DIS/lib64\n";
-print OUTM "\n\n";
-
-print OUTM "\n";
-#print OUTM "all: \$(ALL)\n";
-print OUTM "\n";
-#print OUTM "clean:\n";
-#print OUTM "\trm -f \$(ALL) *.o\n";
-print OUTM "\n";
-
-print OUTM "CFLAGS += -I\$(SUBDIRS)/../../include -I$::rcg_src_dir\/src/drv -I$::rcg_src_dir\/src/include \n";
-if ($::pciNet > 0 && $::virtualiop != 1) {
-print OUTM "LDFLAGS = -L \$(API_LIB_PATH) -lsisci\n";
-} else {
-print OUTM "LDFLAGS = -L \$(API_LIB_PATH) \n";
-}
-
-print OUTM "TARGET=$::skeleton\n\n\n";
-if ($::userspacegps) {
-print OUTM "$::skeleton: $::skeleton.o gpsclock.o rfm.o \n\n";
-} else {
-print OUTM "$::skeleton: $::skeleton.o rfm.o \n\n";
-}
-print OUTM "rfm.o: $::rcg_src_dir\/src/drv/rfm.c \n";
-my $ccf = "\$\(CC\) \$\(CFLAGS\) \$\(CPPFLAGS\) \-c \$\< \-o \$\@";
-print OUTM "\t$ccf \n";
-if ($::userspacegps) {
-print OUTM "gpsclock.o: $::rcg_src_dir\/src/drv/gpsclock.c \n";
-print OUTM "\t$ccf \n";
-}
-print OUTM ".c.o: \n";
-print OUTM "\t$ccf \n";
-
-print OUTM "\n";
-close OUTM;
-}
diff --git a/src/epics/util/lib/createUserModuleBuildEnv.pm b/src/epics/util/lib/createUserModuleBuildEnv.pm
new file mode 100644
index 0000000000000000000000000000000000000000..eb93f690b7ef224eb0a3b690f67ea21365f47f50
--- /dev/null
+++ b/src/epics/util/lib/createUserModuleBuildEnv.pm
@@ -0,0 +1,243 @@
+package CDS::USP_Cmake_Utils;
+use Exporter;
+@ISA = ('Exporter');
+
+#// \b sub \b createUSP_CmakeFiles \n
+#// Move the standard userspace cmake file into the build dir
+#// and generate UserspaceVars.cmake build env file.  \n\n
+sub createUSP_CmakeFiles{
+my ($makefileDir) = @_;
+
+    system("/bin/cp Userspace_CMakeLists.cmake  $::modelCodeUspDir/CMakeLists.txt");
+
+
+    open(OUTM,">./".$makefileDir."/UserspaceVars.cmake") || die "cannot open UserspaceVars.txt file for writing";
+
+    print OUTM "# User Space Linux\n";
+    if ($::iopModel > -1) {
+        print OUTM "set(IOP_MODEL YES)\n";
+    }
+    if($::userspacegps)
+    {
+        print OUTM "set(BUILD_USP_GPSCLOCK YES)\n";
+    }
+    if ($::dolphinTiming > -1 or $::virtualiop == 2) {
+        print OUTM "set(USE_DOLPHIN_TIMING YES)\n";
+    }
+    if ($::dolphin_time_xmit > -1) {
+        print OUTM "set(XMIT_DOLPHIN_TIME YES)\n";
+    }
+
+    print OUTM "list(APPEND CFLAGS \"-O2\")\n";
+    print OUTM "list(APPEND CFLAGS \"$::servoflag\")\n";
+
+    if ($::iopModel > -1) {  #************ SETUP FOR IOP ***************
+        #Following used for IOP running at 128K 
+        if($::adcclock == 128) {
+            print OUTM "list(APPEND CFLAGS \"-DIOP_IO_RATE=131072\")\n";
+        } else {
+            print OUTM "list(APPEND CFLAGS \"-DIOP_IO_RATE=65536\")\n";
+        }
+        # Invoked if IOP cycle rate slower than ADC clock rate
+        print OUTM "list(APPEND CFLAGS \"-DUNDERSAMPLE=$::clock_div\")\n";
+        print OUTM "list(APPEND CFLAGS \"-DADC_MEMCPY_RATE=$::adcclock\")\n";
+    } 
+
+    print OUTM "list(APPEND CFLAGS \"-D";
+    print OUTM "\U$::skeleton";
+    print OUTM "_CODE\")\n";
+
+    print OUTM "list(APPEND CFLAGS \"-DFE_SRC=\\\\\\\"\L$::skeleton/\L$::skeleton.c\\\\\\\"\")\n";
+    print OUTM "list(APPEND CFLAGS \"-DFE_HEADER=\\\\\\\"\L$::skeleton.h\\\\\\\"\")\n";
+
+    print OUTM "list(APPEND CFLAGS \"-g\")\n";
+
+    if ($::remoteGPS) {
+        print OUTM "list(APPEND CFLAGS \"-DREMOTE_GPS\")\n";
+    }
+    if($::systemName eq "sei" || $::useFIRs)
+    {
+        print OUTM "list(APPEND CFLAGS \"-DFIR_FILTERS\")\n";
+    }
+    if ($::no_sync) {
+        print OUTM "#Comment out to enable 1PPS synchronization\n";
+        print OUTM "list(APPEND CFLAGS \"-DNO_SYNC\")\n";
+    } else {
+        print OUTM "#Uncomment to disable 1PPS signal sinchronization (channel 31 (last), ADC 0)\n";
+        print OUTM "#list(APPEND CFLAGS \"-DNO_SYNC\")\n";
+    }
+    if (0 == $::dac_testpoint_names && 0 == $::::extraTestPoints && 0 == $::filtCnt) {
+        print "Not compiling DAQ into the front-end\n";
+        $::no_daq = 1;
+    }
+    if ($::no_daq) {
+        print OUTM "#Comment out to enable DAQ\n";
+        print OUTM "list(APPEND CFLAGS \"-DNO_DAQ\")\n";
+    }
+
+    # Use oversampling code if not 64K system
+    #if($::modelrate < 64) {
+    #  if ($::no_oversampling) {
+    #    print OUTM "#Uncomment to oversample A/D inputs\n";
+    #    print OUTM "#CFLAGS += -DOVERSAMPLE\n";
+    #    print OUTM "#Uncomment to interpolate D/A outputs\n";
+    #    print OUTM "#CFLAGS += -DOVERSAMPLE_DAC\n";
+    #  } else {
+    #    print OUTM "#Comment out to stop A/D oversampling\n";
+    #    print OUTM "CFLAGS += -DOVERSAMPLE\n";
+    #    if ($::no_dac_interpolation) {
+    #    } else {
+    #      print OUTM "#Comment out to stop interpolating D/A outputs\n";
+    #      print OUTM "CFLAGS += -DOVERSAMPLE_DAC\n";
+    #    }
+    #  }
+    #}
+
+    if ($::iopModel < 1) {
+        print OUTM "list(APPEND CFLAGS \"-DUNDERSAMPLE=1\")\n";
+        print OUTM "list(APPEND CFLAGS \"-DADC_MEMCPY_RATE=1\")\n";
+    }
+
+
+    #Following used with IOP running at 64K (NORMAL)
+    if($::adcclock >= 64) {
+
+        #All user models currently view the IOP as running at 65536 even when they are faster
+        print OUTM "list(APPEND CFLAGS \"-DIOP_IO_RATE=65536\")\n";
+
+        if($::modelrate < 64) {
+            my $drate = 64/$::modelrate;
+            if($drate == 8 or $drate > 32) {
+                die "RCG does not support a user model rate $::modelrate" . "K with IOP data at $::adcclock" ."K\n"  ;
+            }
+            print OUTM "list(APPEND CFLAGS \"-DOVERSAMPLE\")\n";
+            print OUTM "list(APPEND CFLAGS \"-DOVERSAMPLE_DAC\")\n";
+            print OUTM "list(APPEND CFLAGS \"-DOVERSAMPLE_TIMES=$drate\")\n";
+            print OUTM "list(APPEND CFLAGS \"-DFE_OVERSAMPLE_COEFF=feCoeff$drate"."x\")\n";
+            print OUTM "list(APPEND CFLAGS \"-DADC_MEMCPY_RATE=1\")\n";
+        }
+    }
+    else
+    {
+        die "Unsupported ADC clock rate: ". $::adcclock . "\n";
+    }
+
+    print OUTM "list(APPEND CFLAGS \"-DUNDERSAMPLE=1\")\n";
+    $modelrate_cps = $::modelrate * 1024;
+    print OUTM "list(APPEND CFLAGS \"-DMODEL_RATE_CPS=$modelrate_cps\")\n";
+
+    if ($::iopModel > -1) {
+        $::modelType = "IOP";
+        if($::diagTest > -1) {
+            print OUTM "list(APPEND CFLAGS \"-DDIAG_TEST\")\n";
+        }
+        if($::dacWdOverride > -1) {
+            print OUTM "list(APPEND CFLAGS \"-DDAC_WD_OVERRIDE\")\n";
+        }
+        # ADD DAC_AUTOCAL to IOPs
+        print OUTM "list(APPEND CFLAGS \"-DDAC_AUTOCAL\")\n";
+    } else {
+        print OUTM "#Uncomment to run on an I/O Master \n";
+        print OUTM "#list(APPEND CFLAGS \"-DIOP_MODEL\")\n";
+    }
+    if ($::iopModel < 1) {
+        print OUTM "list(APPEND CFLAGS \"-DCONTROL_MODEL\")\n";
+        $::modelType = "CONTROL";
+    } 
+    if ($::dolphin_time_xmit > -1) {
+        print OUTM "list(APPEND CFLAGS \"-DXMIT_DOLPHIN_TIME=1\")\n";
+    } 
+    if ($::dolphinTiming > -1) {
+        print OUTM "list(APPEND CFLAGS \"-DUSE_DOLPHIN_TIMING=1\")\n";
+    } 
+    if ($::flipSignals) {
+        print OUTM "list(APPEND CFLAGS \"-DFLIP_SIGNALS=1\")\n";
+    }
+
+    if ($::virtualiop != 1) {
+        if ($::pciNet > 0) {
+            print OUTM "#Enable use of PCIe RFM Network Gen 2\n";
+            print OUTM "set(DOLPHIN_PATH \"/opt/srcdis\")\n";
+            print OUTM "list(APPEND CFLAGS \"-DHAVE_CONFIG_H -DOS_IS_LINUX=196616 -DLINUX -DUNIX " .
+            "-DLITTLE_ENDIAN -DDIS_LITTLE_ENDIAN -DCPU_WORD_IS_64_BIT -DCPU_ADDR_IS_64_BIT ".
+            "-DCPU_WORD_SIZE=64 -DCPU_ADDR_SIZE=64 -DCPU_ARCH_IS_X86_64 -DADAPTER_IS_IX ".
+            "-m64 -D_REENTRANT\")\n"; 
+        }
+    }
+
+    if ($::specificCpu > -1) {
+        print OUTM "#Comment out to run on first available CPU\n";
+        print OUTM "list(APPEND CFLAGS \"-DSPECIFIC_CPU=$::specificCpu\")\n";
+    } else {
+        print OUTM "#Uncomment to run on a specific CPU\n";
+        print OUTM "#list(APPEND CFLAGS \"-DSPECIFIC_CPU=$::specificCpu\")\n";
+    }
+
+    # Set BIQUAD as default starting RCG V2.8
+    print OUTM "#Comment out to go back to old iir_filter calculation form\n";
+    print OUTM "list(APPEND CFLAGS \"-DALL_BIQUAD=1 -DCORE_BIQUAD=1\")\n";
+
+    if ($::::directDacWrite) {
+        print OUTM "list(APPEND CFLAGS \"DDIRECT_DAC_WRITE=1\")\n";
+    } else {
+        print OUTM "#list(APPEND CFLAGS \"DDIRECT_DAC_WRITE=1\")\n";
+    }
+
+    if ($::::noZeroPad) {
+        print OUTM "CFLAGS += -DNO_ZERO_PAD=1\n";
+        print OUTM "list(APPEND CFLAGS \"-DNO_ZERO_PAD=1\")\n";
+    } else {
+        print OUTM "#CFLAGS += -DNO_ZERO_PAD=1\n";
+        print OUTM "#list(APPEND CFLAGS \"-DNO_ZERO_PAD=1\")\n";
+    }
+
+    if ($::::optimizeIO) {
+        print OUTM "list(APPEND CFLAGS \"-DNO_DAC_PRELOAD=1\")\n";
+    } else {
+        print OUTM "#list(APPEND CFLAGS \"-DNO_DAC_PRELOAD=1\")\n";
+    }
+
+    if ($::::rfmDelay) {
+        print OUTM "#Comment out to run without RFM Delayed by 1 cycle\n";
+        print OUTM "list(APPEND CFLAGS \"-DRFM_DELAY=1\")\n";
+    } else {
+        print OUTM "#Clear comment to run with RFM Delayed by 1 cycle\n";
+        print OUTM "#list(APPEND CFLAGS \"-DRFM_DELAY=1\")\n";
+    }
+
+    print OUTM "list(APPEND CFLAGS \"-DUSER_SPACE=1 -fno-builtin-sincos \")\n";
+
+    if ($::userspacegps) {
+        print OUTM "list(APPEND CFLAGS \"-DUSE_GPSCLOCK\")\n";
+    }
+
+    print OUTM "set(ENV{LD_LIBRARY_PATH} \"\$ENV{LD_LIBRARY_PATH}:/opt/DIS/lib64 \")\n";
+    print OUTM "set(API_LIB_PATH \"/opt/DIS/lib64\")\n";
+    print OUTM "\n\n";
+
+    print OUTM "\n";
+    print OUTM "\n";
+    print OUTM "\n";
+
+    #
+    # Start Include Dirs
+    if ($::virtualiop != 1) {
+        if ($::pciNet > 0) {
+            print OUTM "list(APPEND INC_DIRS \"\${DOLPHIN_PATH}/src/include/dis \${DOLPHIN_PATH}/src/include ".
+            "\${DOLPHIN_PATH}/src/SISCI/cmd/test/lib \${DOLPHIN_PATH}/src/SISCI/src \${DOLPHIN_PATH}/src/SISCI/api ".
+            "\${DOLPHIN_PATH}/src/SISCI/cmd/include \${DOLPHIN_PATH}/src/IRM_GX/drv/src ".
+            "\${DOLPHIN_PATH}/src/IRM_GX/drv/src/LINUX \")\n";
+        }
+    }
+
+    print OUTM "list(APPEND INC_DIRS \"\${PROJECT_SOURCE_DIR}/../../../models/" . "\L$::skeleton" ."/include\"  \"$::rcg_src_dir\/src/include\")\n";
+
+    if ($::pciNet > 0 && $::virtualiop != 1) {
+        print OUTM "list(APPEND LDFLAGS \"-L \${API_LIB_PATH} -lsisci \")\n";
+    } else {
+        print OUTM "list(APPEND LDFLAGS \"-L \${API_LIB_PATH}\")\n";
+    }
+
+    print OUTM "\n";
+    close OUTM;
+}
diff --git a/src/epics/util/nameLengthChk.pl b/src/epics/util/nameLengthChk.pl
index fdee9e933a7953e3d2863710a94388af066aab6b..e141b7b52eb804ce0e319a3de468d43d8f80eb72 100755
--- a/src/epics/util/nameLengthChk.pl
+++ b/src/epics/util/nameLengthChk.pl
@@ -1,16 +1,23 @@
 #!/usr/bin/perl
- 
+
+my $total_args = $#ARGV + 1;
+if($total_args ne 3)
+{
+    die "***ERROR - You need to pass in three arguments : <IFO> <EPICS_SRC_DIR> <EPICS_BUILD_DIR>\n";
+}
+
 #
 #  We will need the ifo name in upper case as part of the file path.
 #
 $ifoName = uc(substr($ARGV[0], 0, 2) );
- 
+
+$model_epics_src_dir = $ARGV[1];
+$model_epics_build_dir = $ARGV[2];
+
 #
 #  Assemble file path & name of the .db file.
 #
-$fileName = "target/";
-$fileName .= $ARGV[0];
-$fileName .= "epics/db/";
+$fileName = "$model_epics_build_dir/db/";
 $fileName .= $ifoName;
 $fileName .= "/";
 $fileName .= $ARGV[0];
@@ -60,9 +67,7 @@ else  {
 #
 #  Assemble file path & name of the .ini file.
 #
-$fileName = "build/";
-$fileName .= $ARGV[0];
-$fileName .= "epics/";
+$fileName = "$model_epics_src_dir/";
 $fileName .= $ARGV[0];
 $fileName .= "\.ini";
  
diff --git a/src/epics/util/post_build_script.py b/src/epics/util/post_build_script.py
index e44acd9280beffb74cfeb7b93869d6ca6fba4e84..b9a5af282b8a2bafa76d13b940e253e42eb746fb 100755
--- a/src/epics/util/post_build_script.py
+++ b/src/epics/util/post_build_script.py
@@ -487,6 +487,12 @@ else:
     elif '_DACDT_ENABLE' in word[0]:
       tmp = word[0] + ' 1 OFF 1 \n'
       sdf.write(tmp)
+    elif '_DACKILL_BPTIME' in word[0]:
+      tmp = word[0] + ' 1 600 1 \n'
+      sdf.write(tmp)
+    elif '_DACKILL_PANIC' in word[0]:
+      tmp = word[0] + ' 1 NORMAL 1 \n'
+      sdf.write(tmp)
     else:
       tmp = word[0] + ' 1 1.000000000000000e+00 1 \n'
       sdf.write(tmp)
diff --git a/src/epics/util/skeleton.st b/src/epics/util/skeleton.st
index 6d81feb2ce1a1902026be7a9c373f991c3e34c20..01335bebbc31f3c9fc56cfd94342ca085785aeec 100644
--- a/src/epics/util/skeleton.st
+++ b/src/epics/util/skeleton.st
@@ -36,6 +36,7 @@ program %SEQUENCER_NAME%
 %% #include "fmReadCoeff.h"
 %% #include "feComms.h"
 %% #include "findSharedMemory.h"
+%% #include "sdf_file_loaded.h"
 %% #define FE_ERROR_CFC 0x400
 
 /* Cat string and make upper case */                                     /* MA */
@@ -83,6 +84,12 @@ program %SEQUENCER_NAME%
 %% static %EPICS_TYPE% *pEpics = &pEpicsSpace;
 #endif
 
+%% // set to 1 when safe.snap (or any sdf file) is finished loading
+%% // triggers setting BURT_RESTORE=1
+%% int sdf_file_loaded = 0;
+%% // remember previous value so we only trigger once on transition
+%% int sdf_file_loaded_old = 0;
+
 %% char *build_date = __DATE__ " " __TIME__;
 
 string build_time;
diff --git a/src/fe/commData3.c b/src/fe/commData3.c
index 0689def092ad6f298fc9a11872dd25613f30ef6e..8c170569715da53cb38bc23595f81739dff057b6 100644
--- a/src/fe/commData3.c
+++ b/src/fe/commData3.c
@@ -17,23 +17,18 @@
 ///<    WARRANTY; without even the implied warranty of MERCHANTABILITY or
 ///<    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 ///<    for more details.
-
 #include "commData3.h"
-// #include "isnan.h"
-#include <asm/cacheflush.h>
+#include "controller.h" //cdsPciModules, _shmipc_shm
 
-#ifdef COMMDATA_INLINE
-#define INLINE static inline
-#else
-#define INLINE
-#endif
+
+#include <asm/cacheflush.h>
 
 ///	This function is called from the user application to initialize
 /// communications structures 	and pointers.
 ///	@param[in] connects = total number of IPC connections in the application
 ///	@param[in] rate = Sample rate of the calling application eg 2048
 ///	@param[in,out] ipcInfo[] = Stucture to hold information about each IPC
-INLINE void
+void
 commData3Init(
     int connects, // total number of IPC connections in the application
     int rate, // Sample rate of the calling application eg 2048, 16384, etc.
@@ -41,16 +36,17 @@ commData3Init(
 )
 {
     int           ii;
-    unsigned long ipcMemOffset;
+    //Set ipcMemOffset to default value, will re-set below
+    unsigned long ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM0_OFFSET;
 
-// printf("size of data block = 0x%x\n", sizeof(CDS_IPC_COMMS));
-// printf("Dolphin num = %d \n",cdsPciModules.dolphinCount);
-// printf("\tLocal at 0x%x and 0x%x
+// printl("size of data block = 0x%x\n", sizeof(CDS_IPC_COMMS));
+// printl("Dolphin num = %d \n",cdsPciModules.dolphinCount);
+// printl("\tLocal at 0x%x and 0x%x
 // \n",cdsPciModules.dolphinRead[0],cdsPciModules.dolphinWrite[0]);
-// printf("\tRFM   at 0x%x and 0x%x
+// printl("\tRFM   at 0x%x and 0x%x
 // \n",cdsPciModules.dolphinRead[1],cdsPciModules.dolphinWrite[1]);
 #ifdef RFM_DELAY
-// printf("Model compiled with RFM DELAY !!\n");
+// printl("Model compiled with RFM DELAY !!\n");
 #endif
     for ( ii = 0; ii < connects; ii++ )
     {
@@ -85,8 +81,9 @@ commData3Init(
         // Save pointers to the IPC communications memory locations.
         if ( ipcInfo[ ii ].netType == IRFM0 )
             ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM0_OFFSET;
-        if ( ipcInfo[ ii ].netType == IRFM1 )
+        else if ( ipcInfo[ ii ].netType == IRFM1 )
             ipcMemOffset = IPC_PCIE_BASE_OFFSET + RFM1_OFFSET;
+
         if ( ( ipcInfo[ ii ].netType == IRFM0 ||
                ipcInfo[ ii ].netType == IRFM1 ) &&
              ( ipcInfo[ ii ].mode == ISND ) &&
@@ -136,18 +133,18 @@ commData3Init(
                 (CDS_IPC_COMMS*)( (volatile char*)( cdsPciModules
                                                         .dolphinWrite[ 0 ] ) +
                                   IPC_PCIE_BASE_OFFSET );
-            // printf("Net Type = PCIE SEND IPC at 0x%p
+            // printl("Net Type = PCIE SEND IPC at 0x%p
             // *********************************\n",ipcInfo[ii].pIpcData);
         }
 #if 0
 	// Following for diags, if desired. Otherwise, leave out as it fills dmesg
 	if(ipcInfo[ii].mode == ISND && ipcInfo[ii].netType != ISHME) {
-        printf("IPC Number = %d\n",ipcInfo[ii].ipcNum);
-        printf("IPC Name = %s\n",ipcInfo[ii].name);
-        printf("Sender Model Name = %s\n",ipcInfo[ii].senderModelName);
-        printf("RCV Rate  = %d\n",ipcInfo[ii].rcvRate);
-        printf("Send Computer Number  = %d\n",ipcInfo[ii].sendNode);
-        printf("Send address  = %lx\n",(unsigned long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data);
+        printl("IPC Number = %d\n",ipcInfo[ii].ipcNum);
+        printl("IPC Name = %s\n",ipcInfo[ii].name);
+        printl("Sender Model Name = %s\n",ipcInfo[ii].senderModelName);
+        printl("RCV Rate  = %d\n",ipcInfo[ii].rcvRate);
+        printl("Send Computer Number  = %d\n",ipcInfo[ii].sendNode);
+        printl("Send address  = %lx\n",(unsigned long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data);
 	}
 #endif
     }
@@ -156,7 +153,7 @@ commData3Init(
     {
         if ( ipcInfo[ ii ].mode == ISND && ipcInfo[ ii ].netType != ISHME )
         {
-            // printf("IPC Name = %s
+            // printl("IPC Name = %s
             // \t%d\t%d\t%lx\t%lx\n",ipcInfo[ii].name,ipcInfo[ii].netType,ipcInfo[ii].ipcNum,
             // (unsigned
             // long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data,
@@ -174,7 +171,7 @@ commData3Init(
 ///	@param[in] timeSec = Present GPS time in GPS seconds
 ///	@param[in] cycle = Present cycle of the user application making this
 /// call.
-INLINE void commData3Send(
+void commData3Send(
     int          connects, // Total number of IPC connections in the application
     CDS_IPC_INFO ipcInfo[], // IPC information structure
     int          timeSec, // Present GPS Second
@@ -328,7 +325,7 @@ INLINE void commData3Send(
 ///	@param[in] timeSec = Present GPS time in GPS seconds
 ///	@param[in] cycle = Present cycle of the user application making this
 /// call.
-INLINE void commData3Receive(
+void commData3Receive(
     int          connects, // Total number of IPC connections in the application
     CDS_IPC_INFO ipcInfo[], // IPC information structure
     int          timeSec, // Present GPS Second
@@ -430,3 +427,4 @@ INLINE void commData3Receive(
         }
     }
 }
+
diff --git a/src/fe/commDataUsp.c b/src/fe/commDataUsp.c
index 0069048426d141026047e417c8701c1d6b53afef..376d710eb5b1ae7c708c25af5975d4fb8884d2de 100644
--- a/src/fe/commDataUsp.c
+++ b/src/fe/commDataUsp.c
@@ -17,30 +17,29 @@
 ///<    WARRANTY; without even the implied warranty of MERCHANTABILITY or
 ///<    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 ///<    for more details.
+
 #include "commData3.h"
-#include <stddef.h>
+#include "controller.h"
+#include "util/printl.h"
+
 #ifdef DOLPHIN_TEST
 #include "sisci_types.h"
 #include "sisci_api.h"
 #include "sisci_error.h"
 #include "sisci_demolib.h"
-#endif
+#endif //DOLPHIN_TEST
+
+#include <stdio.h>
+#include <stddef.h>
 
-// #include "isnan.h"
-// #include <asm/cacheflush.h>
 
-#ifdef COMMDATA_INLINE
-#define INLINE static inline
-#else
-#define INLINE
-#endif
 
 ///	This function is called from the user application to initialize
 /// communications structures 	and pointers.
 ///	@param[in] connects = total number of IPC connections in the application
 ///	@param[in] rate = Sample rate of the calling application eg 2048
 ///	@param[in,out] ipcInfo[] = Stucture to hold information about each IPC
-INLINE void
+void
 commData3Init(
     int connects, // total number of IPC connections in the application
     int rate, // Sample rate of the calling application eg 2048, 16384, etc.
@@ -50,14 +49,14 @@ commData3Init(
     int           ii;
     unsigned long ipcMemOffset;
 
-// printf("size of data block = 0x%x\n", sizeof(CDS_IPC_COMMS));
-// printf("Dolphin num = %d \n",cdsPciModules.dolphinCount);
-// printf("\tLocal at 0x%x and 0x%x
+// printl("size of data block = 0x%x\n", sizeof(CDS_IPC_COMMS));
+// printl("Dolphin num = %d \n",cdsPciModules.dolphinCount);
+// printl("\tLocal at 0x%x and 0x%x
 // \n",cdsPciModules.dolphinRead[0],cdsPciModules.dolphinWrite[0]);
-// printf("\tRFM   at 0x%x and 0x%x
+// printl("\tRFM   at 0x%x and 0x%x
 // \n",cdsPciModules.dolphinRead[1],cdsPciModules.dolphinWrite[1]);
 #ifdef RFM_DELAY
-// printf("Model compiled with RFM DELAY !!\n");
+// printl("Model compiled with RFM DELAY !!\n");
 #endif
     for ( ii = 0; ii < connects; ii++ )
     {
@@ -143,19 +142,19 @@ commData3Init(
                 (CDS_IPC_COMMS*)( (volatile char*)( cdsPciModules
                                                         .dolphinWrite[ 0 ] ) +
                                   IPC_PCIE_BASE_OFFSET );
-            // printf("Net Type = PCIE SEND IPC at 0x%p
+            // printl("Net Type = PCIE SEND IPC at 0x%p
             // *********************************\n",ipcInfo[ii].pIpcData);
         }
 	// Following for diags, if desired. Otherwise, leave out as it fills dmesg
 	// if(ipcInfo[ii].mode == ISND && ipcInfo[ii].netType != ISHME) {
 	if(ipcInfo[ii].mode == ISND) {
-        printf("IPC Number = %d\n",ipcInfo[ii].ipcNum);
-        printf("IPC Name = %s\n",ipcInfo[ii].name);
-        printf("Sender Model Name = %s\n",ipcInfo[ii].senderModelName);
-        printf("IPC Net  = %d\n",ipcInfo[ii].netType);
-        printf("Send Computer Number  = %d\n",ipcInfo[ii].sendNode);
-        printf("Send address  = %lx\n",(unsigned long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data);
-        printf("*******************\n");
+        printl("IPC Number = %d\n",ipcInfo[ii].ipcNum);
+        printl("IPC Name = %s\n",ipcInfo[ii].name);
+        printl("Sender Model Name = %s\n",ipcInfo[ii].senderModelName);
+        printl("IPC Net  = %d\n",ipcInfo[ii].netType);
+        printl("Send Computer Number  = %d\n",ipcInfo[ii].sendNode);
+        printl("Send address  = %lx\n",(unsigned long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data);
+        printl("*******************\n");
 	}
     }
     // Send connection list to dmesg
@@ -163,7 +162,7 @@ commData3Init(
     {
         if ( ipcInfo[ ii ].mode == ISND && ipcInfo[ ii ].netType != ISHME )
         {
-            // printf("IPC Name = %s
+            // printl("IPC Name = %s
             // \t%d\t%d\t%lx\t%lx\n",ipcInfo[ii].name,ipcInfo[ii].netType,ipcInfo[ii].ipcNum,
             // (unsigned
             // long)&ipcInfo[ii].pIpcDataWrite[0]->dBlock[0][ipcInfo[ii].ipcNum].data,
@@ -181,7 +180,8 @@ commData3Init(
 ///	@param[in] timeSec = Present GPS time in GPS seconds
 ///	@param[in] cycle = Present cycle of the user application making this
 /// call.
-INLINE void commData3Send(
+void
+commData3Send(
     int          connects, // Total number of IPC connections in the application
     CDS_IPC_INFO ipcInfo[], // IPC information structure
     int          timeSec, // Present GPS Second
@@ -314,7 +314,8 @@ INLINE void commData3Send(
 ///	@param[in] timeSec = Present GPS time in GPS seconds
 ///	@param[in] cycle = Present cycle of the user application making this
 /// call.
-INLINE void commData3Receive(
+void
+commData3Receive(
     int          connects, // Total number of IPC connections in the application
     CDS_IPC_INFO ipcInfo[], // IPC information structure
     int          timeSec, // Present GPS Second
@@ -380,7 +381,7 @@ INLINE void commData3Receive(
                     else
                     {
                         ipcInfo[ ii ].errFlag++;
-                        //printf("bad IPC %ld %ld\n", syncWord, mySyncWord);
+                        // printl("bad IPC %ld %ld\n", syncWord, mySyncWord);
                     }
                 }
                 else
@@ -410,3 +411,4 @@ INLINE void commData3Receive(
         }
     }
 }
+
diff --git a/src/fe/controllerApp.c b/src/fe/controllerApp.c
index 4cfe954c8a91eb1012ba079f9279308ddc04b8a9..782a483b00d7a924f02e2f0760bf9040a3ff7106 100644
--- a/src/fe/controllerApp.c
+++ b/src/fe/controllerApp.c
@@ -31,19 +31,27 @@
 ///<    for more details.
 
 #include "controllerko.h"
-
-// Include C code modules
-#include "mapApp.c"
-#include "moduleLoad.c"
-#include <drv/mapVirtual.h>
-#include <drv/app_adc_read.c>
-#include <drv/app_dac_functions.c>
-#include <drv/app_dio_routines.c>
-#include <drv/dac_info.c>
+#include "mapApp.h"
+#include "feComms.h"
+#include "modelRateInfo.h"
+#include "fm10Gen.h"
+#include "util/printl.h"
+
+#include "../fe/timing_common.h" //captureEocTiming
+#include "../fe/timing_kernel.h"
+
+#include "drv/daqLib.h" //curDaqBlockSize, tpPtr
+#include "drv/cdsHardware.h"
+#include "drv/epicsXfer.h"
+#include "drv/app_adc_read.h"
+#include "drv/app_dac_functions.h"
+#include "drv/app_dio_routines.h"
+#include "drv/dac_info.h"
+
+#include <linux/delay.h> //udelay()
+#include <asm/cacheflush.h> //clflush_cache_range()
 
 int startGpsTime = 0;
-int getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec );
-int killipc = 0;
 
 //***********************************************************************
 // TASK: fe_start_controller()
@@ -368,7 +376,7 @@ fe_start_controller( void )
 #endif
         for ( ll = 0; ll < sampleCount; ll++ )
         {
-            status = app_adc_read( ioMemCntr, ioClock, &adcinfo, cpuClock );
+            status = app_adc_read( ioMemCntr, ioClock, &adcinfo, cpuClock, &startGpsTime );
 
             // Return of non zero = ADC timeout error.
             if ( status )
@@ -429,7 +437,7 @@ fe_start_controller( void )
         if ( ( cycleNum % 2048 ) == 0 )
         {
             usleep_range( 1, 3 );
-            printk( "cycleNum = %d\n", cycleNum );
+            printl( "cycleNum = %d\n", cycleNum );
         }
 #endif
 
diff --git a/src/fe/controllerAppUser.c b/src/fe/controllerAppUser.c
index 97782b74545fce0ff150b868d9ecfe7a1af22549..e43da6598f9bbcd43006f993d8a516cac098f743 100644
--- a/src/fe/controllerAppUser.c
+++ b/src/fe/controllerAppUser.c
@@ -31,37 +31,37 @@
 ///<    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 <stdint.h>
-// #include <drv/cdsHardware.h>
-#include "inlineMath.h"
-
+//#include "util/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 "cds_types.h"
 #include "controller.h"
+#include "timing_common.h" // timing module / IRIG-B  functions
+#include "util/printl.h"
 
 #ifndef NO_DAQ
 #include "drv/fb.h"
-#include "drv/daqLib.c" // DAQ/GDS connection software
+#include "drv/daqLib.h" // DAQ/GDS connection software
 #endif
-
-#include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function
+#include "drv/epicsXfer.h" // User defined EPICS to/from FE data transfer function
 #include "drv/mapuser.h"
-#include "timing_common.h" // timing module / IRIG-B  functions
-
 #include "drv/inputFilterModule.h"
 #include "drv/inputFilterModule1.h"
-#include "drv/app_dac_functions.c"
-#include "drv/dac_info.c"
+#include "drv/app_dac_functions.h"
+#include "drv/dac_info.h"
 
 // #include "dolphin_usp.c"
 
+#include <linux/version.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+
 #ifdef USE_GPSCLOCK
 #include "drv/gpsclock.h"
 #else
@@ -72,8 +72,8 @@ gpsclock_timestring(char* line, int size)
     timef = fopen( "/sys/kernel/gpstime/time", "r" );
     if ( !timef )
     {
-        printf( "Cannot find GPS time \n" );
-        return ( 0 );
+        printl( "Cannot find GPS time \n" );
+        return;
     }
     fgets( line, 100, timef );
     fclose(timef);
@@ -82,32 +82,11 @@ gpsclock_timestring(char* line, int size)
 
 #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
-// receiver 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.
-
-// Include C code modules
-#include "rcguser.c"
-int             getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec );
-struct timespec adcTime; ///< Used in code cycle timing
-int             timeHoldHold =
+
+static struct timespec adcTime; ///< Used in code cycle timing
+static int             timeHoldHold =
     0; ///< Max code cycle time within 1 sec period; hold for another sec
-struct timespec myTimer[ 2 ]; ///< Used in code cycle timing
+static struct timespec myTimer[ 2 ]; ///< Used in code cycle timing
 
 unsigned int
 getGpsTimeProc( )
@@ -117,7 +96,7 @@ getGpsTimeProc( )
 
     gpsclock_timestring(line, 100);
     mytime = atoi( line );
-    printf( "GPS TIME is %d\n", mytime );
+    printl( "GPS TIME is %d\n", mytime );
     return ( mytime );
 }
 
@@ -207,7 +186,7 @@ fe_start_app_user( )
     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
+    // printl("Epics at 0x%x and DAQ at 0x%x  size = %d
     // \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN));
 
 #ifdef OVERSAMPLE
@@ -292,11 +271,11 @@ fe_start_app_user( )
     /// \> Initialize IIR filter bank values
     if ( initVars( pDsp[ 0 ], pDsp[ 0 ], dspCoeff, MAX_MODULES, pCoeff[ 0 ] ) )
     {
-        printf( "Filter module init failed, exiting\n" );
+        printl( "Filter module init failed, exiting\n" );
         return 0;
     }
 
-    printf( "Initialized servo control parameters.\n" );
+    printl( "Initialized servo control parameters.\n" );
 
     usleep( 1000 );
 
@@ -319,10 +298,10 @@ fe_start_app_user( )
     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 );
+    printl( "DAQ Ex Min/Max = %d %d\n", daq.filtExMin, daq.filtExMax );
+    printl( "DAQ XEx Min/Max = %d %d\n", daq.xExMin, daq.xExMax );
+    printl( "DAQ Tp Min/Max = %d %d\n", daq.filtTpMin, daq.filtTpMax );
+    printl( "DAQ XTp Min/Max = %d %d\n", daq.xTpMin, daq.xTpMax );
 
     /// - ---- Assign DAC testpoint pointers
     for ( ii = 0; ii < cdsPciModules.dacCount; ii++ )
@@ -353,7 +332,7 @@ fe_start_app_user( )
                        pEpicsDaq );
     if ( status == -1 )
     {
-        printf( "DAQ init failed -- exiting\n" );
+        printl( "DAQ init failed -- exiting\n" );
         vmeDone = 1;
         return ( 0 );
     }
@@ -363,7 +342,7 @@ fe_start_app_user( )
     vmeDone = 0;
 
     /// \> Call user application software initialization routine.
-    printf( "Calling feCode() to initialize\n" );
+    printl( "Calling feCode() to initialize\n" );
     iopDacEnable = feCode( cycleNum,
                            dWord,
                            dacOut,
@@ -393,7 +372,7 @@ fe_start_app_user( )
     // application.
     pLocalEpics->epicsOutput.fe_status = INIT_SYNC;
     ll = cdsPciModules.adcConfig[ 0 ];
-    printf( "waiting to sync %d\n", ioMemData->iodata[ ll ][ 0 ].cycle );
+    printl( "waiting to sync %d\n", ioMemData->iodata[ ll ][ 0 ].cycle );
     clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_CYCLE_START ] );
 
     // Spin until cycle 0 detected in first ADC buffer location.
@@ -409,7 +388,7 @@ fe_start_app_user( )
         cpuClock[ CPU_TIME_CYCLE_END ].tv_nsec -
         cpuClock[ CPU_TIME_CYCLE_START ].tv_nsec;
     timeinfo.cycleTime /= 1000;
-    printf( "Synched %d\n", timeinfo.cycleTime );
+    printl( "Synched %d\n", timeinfo.cycleTime );
     // Need to set sync21pps so code will not try to sync with 1pps pulse later.
     sync21pps = 1;
     // Get GPS seconds from MASTER
@@ -419,7 +398,7 @@ fe_start_app_user( )
     timeSec--;
 
     onePpsTime = cycleNum;
-    printf( "Using local GPS time %d \n", timeSec );
+    printl( "Using local GPS time %d \n", timeSec );
     pLocalEpics->epicsOutput.fe_status = NORMAL_RUN;
 
     clock_gettime( CLOCK_MONOTONIC, &adcTime );
@@ -448,7 +427,7 @@ fe_start_app_user( )
         if ( cycleNum == 0 )
         {
             /// - ---- Check awgtpman status.
-            // printf("awgtpman gps = %d local = %d\n",
+            // printl("awgtpman gps = %d local = %d\n",
             // pEpicsComms->padSpace.awgtpman_gps, timeSec);
             pLocalEpics->epicsOutput.awgStat =
                 ( pEpicsComms->padSpace.awgtpman_gps != timeSec );
@@ -495,7 +474,7 @@ fe_start_app_user( )
                 /// DAC channel reservation and exit the code.
                 if ( adcinfo.adcWait >= MAX_ADC_WAIT_CONTROL )
                 {
-                    printf( "ADC TIMEOUT %d %d %d %d\n",
+                    printl( "ADC TIMEOUT %d %d %d %d\n",
                             mm,
                             ioMemData->iodata[ mm ][ ioMemCntr ].cycle,
                             ioMemCntr,
@@ -503,7 +482,7 @@ fe_start_app_user( )
                     pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
                     pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR;
                     deallocate_dac_channels( );
-                    return (void*)-1;
+                    return -1;
                 }
                 for ( ii = 0; ii < MAX_ADC_CHN_PER_MOD; ii++ )
                 {
@@ -850,11 +829,11 @@ fe_start_app_user( )
         /// \> If not exit request, then continue INFINITE LOOP  *******
     }
 
-    printf( "exiting from fe_code()\n" );
+    printl( "exiting from fe_code()\n" );
     pLocalEpics->epicsOutput.cpuMeter = 0;
 
     deallocate_dac_channels( );
 
     /* System reset command received */
-    return (void*)-1;
+    return -1;
 }
diff --git a/src/fe/controllerIop.c b/src/fe/controllerIop.c
index 82df23108cc956327b94e77e6176522a7c89bd5d..259f7b166fb42abb8467d2954b61ae28c140c802 100644
--- a/src/fe/controllerIop.c
+++ b/src/fe/controllerIop.c
@@ -30,19 +30,38 @@
 ///<    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 ///<    for more details.
 
+#include "controllerIop.h" //Externs shared globals
 #include "controllerko.h"
-
-#ifdef DOLPHIN_TEST
-#include "dolphin.c"
-#endif
+#include "cds_types.h"
+#include "feComms.h"
+#include "fm10Gen_types.h"
+#include "controller.h"
+#include "modelRateInfo.h"
+#include "drv/daqLib.h"
+#include "../fe/timing_kernel.h"
+#include "../fe/sync21pps.h"
+#include "drv/gsc_adc_common.h" //GSAI_ALL_CARDS
+#include "drv/gsc_dac_common.h" //DAC_CLK_ENABLE
+#include "drv/contec1616.h" //stop_tds_clocks()
+#include "drv/ligoPcieTiming.h" //lptc_*()
+#include "fm10Gen.h" //checkFiltReset()
+#include "../fe/timing_common.h" //captureEocTiming()
+#include "drv/epicsXfer.h" //checkEpicsReset()
+#include FE_HEADER //fecode()
+
+
+#include <linux/delay.h> //udelay()
+#include <asm/cacheflush.h>
+
+
+//
+// Start Exported Global data (controllerIop.h)
+//
 
 #if defined( XMIT_DOLPHIN_TIME ) || defined( USE_DOLPHIN_TIMING )
 volatile TIMING_SIGNAL* pcieTimer;
 #endif
 
-// Duotone diags struct
-duotone_diag_t dt_diag;
-
 // Variables for setting IOP->APP I/O
 int ioClockDac = DAC_PRELOAD_CNT;
 // int ioMemCntr = 0;
@@ -52,34 +71,34 @@ int dacEnable = 0;
 int dacWriteEnable =
     0; /// @param dacWriteEnable  No DAC outputs until >4 times through code
 int        dacTimingErrorPending[ MAX_DAC_MODULES ];
-static int dacTimingError = 0;
-int        dacWatchDog = 0;
+int dacTimingError = 0;
+//int        dacWatchDog = 0; Unused
 
 int pBits[ 9 ] = { 1, 2, 4, 8, 16, 32, 64, 128, 256 };
 
-int getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec );
+// Duotone diags struct
+duotone_diag_t dt_diag; //Used by iop_dac_functions.c
+
+
 
-// Include C code modules
-#include "moduleLoad.c"
 #if defined( RUN_WO_IO_MODULES ) || defined( USE_DOLPHIN_TIMING )
-#include "mapVirtual.c"
-#include <drv/no_ioc_timing.c>
-#include "verify_slots.c"
-#include <drv/dac_info.c>
-#include <drv/adc_info.c>
-
-// dummy placeholder function that should never be called when there's no IOC
-int iop_dac_preload() {return 0;}
+#include "drv/no_ioc_timing.h"
+#include "drv/dac_info.h"
+#include "drv/adc_info.h"
+#include "drv/no_ioc_dac_preload.h"
 #else
-#include "map.c"
-#include <drv/iop_adc_functions.c>
-#include <drv/iop_dac_functions.c>
-#include "sync21pps.c"
-#include "verify_slots.c"
-#include <drv/dac_info_ioc2.c>
-#include <drv/adc_info_ioc2.c>
+#include "drv/iop_adc_functions.h"
+#include "drv/iop_dac_functions.h"
+#include "drv/dac_info_ioc2.h"
+#include "drv/adc_info_ioc2.h"
+#include "../fe/sync21pps.h"
+
 #endif
 
+#include "drv/map.h"
+#include "verify_slots.h"
+#include "drv/spectracomGPS.h"
+#include "drv/symmetricomGps.h"
 
 //***********************************************************************
 // TASK: fe_start_controller()
@@ -94,17 +113,15 @@ int iop_dac_preload() {return 0;}
 void
 fe_start_controller( void )
 {
-    int        ii, jj, kk, ll; // Dummy loop counter variables
+    int        ii, jj, kk; // Dummy loop counter variables
     static int cpuClock[ CPU_TIMER_CNT ]; ///  @param cpuClock[] Code timing
                                           ///  diag variables
 
     volatile RFM_FE_COMMS* pEpicsComms; /// @param *pEpicsComms Pointer to EPICS
                                         /// shared memory space
     int status; /// @param status Typical function return value
-    one_pps_sync_t onePps;
-    onePps.time = IOP_IO_RATE * 4; /// @param onePpsTime One PPS diagnostic check
-    unsigned long nanotime = 100000;
     int           sync21pps = 0; ///@param flag for code sync to 1PPS signal
+
 // FOR DIAGNOSTIC TESTING ONLY
 #ifdef DIAG_TEST
     loopbacktest_t loopback;
@@ -133,8 +150,6 @@ fe_start_controller( void )
                             // than code
     int        hkp_cycle = 0;
     double     adcval[ MAX_ADC_MODULES ][ MAX_ADC_CHN_PER_MOD ];
-    volatile u32        dacWDread = 0;
-    int        dacnum = 0;
     adcInfo_t* padcinfo;
     // Normally preload DAC FIFOs on startup, but can be bypassed
 #ifdef NO_DAC_PRELOAD
@@ -147,6 +162,16 @@ fe_start_controller( void )
     int dac_fault_armed = 1;
 #endif
 
+#if !defined( RUN_WO_IO_MODULES ) && !defined( USE_DOLPHIN_TIMING )
+    volatile u32        dacWDread = 0;
+    int                 dacnum = 0;
+#endif
+
+    one_pps_sync_t onePps;
+    onePps.time = IOP_IO_RATE * 4; /// @param onePpsTime One PPS diagnostic check
+
+
+
     /// **********************************************************************************************\n
     /// Start Initialization Process \n
     /// **********************************************************************************************\n
@@ -450,8 +475,8 @@ fe_start_controller( void )
         timeSec = current_time_fe( ) - 1;
         if ( cdsPciModules.gpsType == TSYNC_RCVR )
         {
-            timeSec = getGpsSecTsync( );
-            gps_receiver_locked = getGpsuSecTsync( &usec );
+            timeSec = getGpsSecTsync( &cdsPciModules );
+            gps_receiver_locked = getGpsuSecTsync( &cdsPciModules, &usec );
             // Subtract a second because first cycle will increment by one
             timeSec--;
         }
@@ -482,9 +507,12 @@ fe_start_controller( void )
         }
         break;
 #endif
+#ifdef RUN_WO_IO_MODULES
+    //sync2cpuclock() is only declared/defined if RUN_WO_IO_MODULES
     case SYNC_SRC_TIMER:
-        timeSec = sync2cpuclock( );
+        timeSec = sync2cpuclock( ); 
         break;
+#endif
     case SYNC_SRC_INTERNAL:
         gscEnableAdcModule ( &cdsPciModules,GSAI_ALL_CARDS,GSAI_DMA_MODE );
         gscEnableDacModule ( &cdsPciModules,GSAI_ALL_CARDS,DAC_CLK_ENABLE );
@@ -677,7 +705,7 @@ fe_start_controller( void )
                 {
                     // Retrieve time set in at adc read and report offset from
                     // 1PPS
-                    gps_receiver_locked = getGpsTime( &timeSec, &usec );
+                    gps_receiver_locked = getGpsTime( &cdsPciModules, &timeSec, &usec );
                     pLocalEpics->epicsOutput.irigbTime = usec;
                     if ( ( usec > MAX_IRIGB_SKEW || usec < MIN_IRIGB_SKEW ) &&
                          cdsPciModules.gpsType != 0 )
@@ -705,7 +733,7 @@ fe_start_controller( void )
                  ( syncSource == SYNC_SRC_TDS || syncSource == SYNC_SRC_LTC ) )
             {
                 if ( cdsPciModules.gpsType == TSYNC_RCVR )
-                    gps_receiver_locked = getGpsuSecTsync( &usec );
+                    gps_receiver_locked = getGpsuSecTsync( &cdsPciModules, &usec );
                 if ( syncSource == SYNC_SRC_LTC )
                     usec = lptc_get_gps_usec( &cdsPciModules ) - USEC_PER_CYCLE;
                 pLocalEpics->epicsOutput.irigbTime = usec;
@@ -1145,7 +1173,7 @@ fe_start_controller( void )
                         lptc_get_lptc_status( &cdsPciModules );
                 }
             }
-#endif
+#endif //!defined( RUN_WO_IO_MODULES ) && !defined( USE_DOLPHIN_TIMING )
 
             // *****************************************************************
             // Update end of cycle information
diff --git a/src/fe/controllerIop.h b/src/fe/controllerIop.h
new file mode 100644
index 0000000000000000000000000000000000000000..e627c193f9bafd9c3350b143f92eb0a752b45e80
--- /dev/null
+++ b/src/fe/controllerIop.h
@@ -0,0 +1,28 @@
+#ifndef LIGO_CONTROLLER_IOP_H
+#define LIGO_CONTROLLER_IOP_H
+
+#include "drv/cdsHardware.h"
+#include "cds_types.h" 
+
+#include "commData3.h" //TIMING_SIGNAL
+
+#if defined( XMIT_DOLPHIN_TIME ) || defined( USE_DOLPHIN_TIMING )
+extern volatile TIMING_SIGNAL* pcieTimer;
+#endif
+
+extern int ioClockDac;
+extern int ioMemCntrDac;
+
+extern int dacEnable;
+extern int dacWriteEnable;
+
+extern int dacTimingErrorPending[ MAX_DAC_MODULES ];
+
+extern int dacTimingError;
+
+extern int pBits[ 9 ];
+
+extern duotone_diag_t dt_diag; 
+
+
+#endif //LIGO_CONTROLLER_IOP_H
diff --git a/src/fe/controllerIopUser.c b/src/fe/controllerIopUser.c
index d59d25d1deda20455f7b4de07398bcf9e7429f58..51a0ef29276e5984bde0003efdc9c2872e3cb0a9 100644
--- a/src/fe/controllerIopUser.c
+++ b/src/fe/controllerIopUser.c
@@ -30,38 +30,41 @@
 ///<    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 <stdint.h>
-#include <drv/cdsHardware.h>
-#include "inlineMath.h"
-
+#include "drv/cdsHardware.h"
+#include "util/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 "cds_types.h"
 #include "controller.h"
+#include "controllerko.h" //tdsControl, tdsCount, etc
+#include "util/printl.h"
 
 #ifndef NO_DAQ
 #include "drv/fb.h"
-#include "drv/daqLib.c" // DAQ/GDS connection software
+#include "drv/daqLib.h" // DAQ/GDS connection software
 #endif
-
-#include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function
+#include "drv/epicsXfer.h" // User defined EPICS to/from FE data transfer function
 #include "drv/mapuser.h"
-#include "timing_common.h" // timing module / IRIG-B  functions
-
 #include "drv/inputFilterModule.h"
 #include "drv/inputFilterModule1.h"
-#include <drv/dac_info.c>
+#include "drv/dac_info.h"
+
+#include "../fe/timing_common.h" // timing module / IRIG-B  functions
+
 
 #ifdef DOLPHIN_TEST
 #include "dolphin.c"
 #endif
 
+#include <linux/version.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
 #ifdef USE_GPSCLOCK
 #include "drv/gpsclock.h"
 #else
@@ -72,8 +75,8 @@ gpsclock_timestring(char* line, int size)
     timef = fopen( "/sys/kernel/gpstime/time", "r" );
     if ( !timef )
     {
-        printf( "Cannot find GPS time \n" );
-        return ( 0 );
+        printl( "Cannot find GPS time \n" );
+        return;
     }
     fgets( line, 100, timef );
     fclose(timef);
@@ -82,37 +85,8 @@ gpsclock_timestring(char* line, int size)
 
 #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 control 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;
-
-int startGpsTime;
-int cycleOffset = 0;
-
-struct timespec myTimer[ 3 ]; ///< Used in code cycle timing
-int             getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec );
-
-// Include C code modules
-#include "rcguserIop.c"
+static int startGpsTime;
+static struct timespec myTimer[ 3 ]; ///< Used in code cycle timing
 
 unsigned int
 getGpsTimeProc( )
@@ -122,7 +96,7 @@ getGpsTimeProc( )
 
     gpsclock_timestring(line, 100);
     mytime = atoi( line );
-    printf( "GPS TIME is %d\n", mytime );
+    printl( "GPS TIME is %d\n", mytime );
     return ( mytime );
 }
 void
@@ -137,7 +111,7 @@ initAdcModules( adcInfo_t* adcinfo )
         pLocalEpics->epicsOutput.statAdc[ jj ] = 1;
         adcinfo->adcRdTimeErr[ jj ] = 0;
     }
-    printf( "ADC setup complete \n" );
+    printl( "ADC setup complete \n" );
 }
 void
 initDacModules( void )
@@ -149,7 +123,7 @@ initDacModules( void )
     {
         pLocalEpics->epicsOutput.statDac[ jj ] = DAC_FOUND_BIT;
     }
-    printf( "DAC setup complete \n" );
+    printl( "DAC setup complete \n" );
 }
 
 //***********************************************************************
@@ -180,11 +154,11 @@ fe_start_iop_user( )
 
     int adcData[ MAX_ADC_MODULES ]
                [ MAX_ADC_CHN_PER_MOD ]; /// @param adcData[][]  ADC raw data
-    int adcChanErr[ MAX_ADC_MODULES ];
+    int adcChanErr[ MAX_ADC_MODULES ] = {0,};
     // int adcWait = 0;
     adcInfo_t adcInfo;
     dacInfo_t dacinfo;
-    int adcOF[ MAX_ADC_MODULES ]; /// @param adcOF[]  ADC overrange counters
+    int adcOF[ MAX_ADC_MODULES ] = {0,}; /// @param adcOF[]  ADC overrange counters
 
     static int dacWriteEnable =
         0; /// @param dacWriteEnable  No DAC outputs until >4 times through code
@@ -285,7 +259,7 @@ fe_start_iop_user( )
     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
+    // printl("Epics at 0x%x and DAQ at 0x%x  size = %d
     // \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN));
 
     /// \> Zero out DAC outputs
@@ -297,6 +271,7 @@ fe_start_iop_user( )
             dacOut[ ii ][ jj ] = 0.0;
             dacOutUsed[ ii ][ jj ] = 0;
             dacinfo.dacOutBufSize[ ii ] = 0;
+            dacinfo.dacOF[ ii ] = 0;
             // Zero out DAC channel map in the shared memory
             // to be used to check on control models' channel allocation
             ioMemData->dacOutUsed[ ii ][ jj ] = 0;
@@ -328,22 +303,22 @@ fe_start_iop_user( )
     // if Contec 1616 BIO present, TDS receiver will be used for timing.
     syncSource = SYNC_SRC_TIMER;
 
-    printf( "Sync source = %d\n", syncSource );
+    printl( "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",
+    printl( "Waiting for EPICS BURT Restore = %d\n",
             pLocalEpics->epicsInput.burtRestore );
     cnt = 0;
     do
     {
         usleep( 80000 );
-        printf( "Waiting for EPICS BURT %d\n", cnt++ );
+        printl( "Waiting for EPICS BURT %d\n", cnt++ );
     } while ( !pLocalEpics->epicsInput.burtRestore );
 
-    printf( "BURT Restore Complete\n" );
+    printl( "BURT Restore Complete\n" );
 
     // BURT has completed
     // *******************************************************************
@@ -394,11 +369,11 @@ fe_start_iop_user( )
     /// \> Initialize IIR filter bank values
     if ( initVars( pDsp[ 0 ], pDsp[ 0 ], dspCoeff, MAX_MODULES, pCoeff[ 0 ] ) )
     {
-        printf( "Filter module init failed, exiting\n" );
+        printl( "Filter module init failed, exiting\n" );
         return 0;
     }
 
-    printf( "Initialized servo control parameters.\n" );
+    printl( "Initialized servo control parameters.\n" );
 
     usleep( 1000 );
 
@@ -421,10 +396,10 @@ fe_start_iop_user( )
     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 );
+    printl( "DAQ Ex Min/Max = %d %d\n", daq.filtExMin, daq.filtExMax );
+    printl( "DAQ XEx Min/Max = %d %d\n", daq.xExMin, daq.xExMax );
+    printl( "DAQ Tp Min/Max = %d %d\n", daq.filtTpMin, daq.filtTpMax );
+    printl( "DAQ XTp Min/Max = %d %d\n", daq.xTpMin, daq.xTpMax );
 
     /// - ---- Assign DAC testpoint pointers
     for ( ii = 0; ii < cdsPciModules.dacCount; ii++ )
@@ -455,7 +430,7 @@ fe_start_iop_user( )
                        pEpicsDaq );
     if ( status == -1 )
     {
-        printf( "DAQ init failed -- exiting\n" );
+        printl( "DAQ init failed -- exiting\n" );
         vmeDone = 1;
         return ( 0 );
     }
@@ -465,7 +440,7 @@ fe_start_iop_user( )
     vmeDone = 0;
 
     /// \> Call user application software initialization routine.
-    printf( "Calling feCode() to initialize\n" );
+    printl( "Calling feCode() to initialize\n" );
     iopDacEnable = feCode( cycleNum,
                            dWord,
                            dacOut,
@@ -488,9 +463,9 @@ fe_start_iop_user( )
     initDacModules( );
 
     pLocalEpics->epicsOutput.fe_status = INIT_SYNC;
-    printf( "*******************************\n" );
-    printf( "*     Running on timer!       *\n" );
-    printf( "*******************************\n" );
+    printl( "*******************************\n" );
+    printl( "*     Running on timer!       *\n" );
+    printl( "*******************************\n" );
     long timeoff = 0;
     /// Sync up to the 1Hz boundary
     do
@@ -846,7 +821,7 @@ fe_start_iop_user( )
                 }
             }
             if ( ( pLocalEpics->epicsInput.overflowReset ) ||
-                 ( adcInfo.overflowAdc > OVERFLOW_CNTR_LIMIT ) )
+                 ( overflowAcc > OVERFLOW_CNTR_LIMIT ) )
             {
                 pLocalEpics->epicsInput.overflowReset = 0;
                 pLocalEpics->epicsOutput.ovAccum = 0;
@@ -919,11 +894,11 @@ fe_start_iop_user( )
                 pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC;
                 stop_working_threads = 1;
                 vmeDone = 1;
-                printf( "Channel Hopping Detected on one or more ADC modules "
+                printl( "Channel Hopping Detected on one or more ADC modules "
                         "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
-                printf( "Check GDSTP screen ADC status bits to id affected ADC "
+                printl( "Check GDSTP screen ADC status bits to id affected ADC "
                         "modules\n" );
-                printf( "Code is exiting ..............\n" );
+                printl( "Code is exiting ..............\n" );
                 continue;
             }
             feStatus |= dac_status_update( &dacinfo );
@@ -985,9 +960,9 @@ fe_start_iop_user( )
         /// \> If not exit request, then continue INFINITE LOOP  *******
     }
 
-    printf( "exiting from fe_code()\n" );
+    printl( "exiting from fe_code()\n" );
     pLocalEpics->epicsOutput.cpuMeter = 0;
 
     /* System reset command received */
-    return (void*)-1;
+    return 0;
 }
diff --git a/src/fe/dolphin.c b/src/fe/dolphin.c
index a7db9a5d58019d22b5a71764322381153adad61c..3e11c7f8777a43bc7c3cb42f8e8b234b83450d58 100644
--- a/src/fe/dolphin.c
+++ b/src/fe/dolphin.c
@@ -4,8 +4,15 @@
 ///     module code.
 /// @author R.Bork
 
-#include <genif.h>
+#include "../fe/dolphin.h"
 #include "commData3.h"
+#include "controller.h" //MAX_UDELAY, cdsPciModules
+#include "util/printl.h"
+
+#include "../drv/mbuf/mbuf_kernel.h"
+
+#include <genif.h>
+
 
 sci_l_segment_handle_t segment[ 4 ];
 sci_map_handle_t       client_map_handle[ 4 ];
@@ -24,7 +31,7 @@ R_OK,
        SR_HEARTBEAT_RECEIVED
       } session_cb_reason_t;
 */
-int32_t
+static int32_t
 session_callback( session_cb_arg_t IN arg,
                   session_cb_reason_t IN reason,
                   session_cb_status_t IN status,
@@ -32,9 +39,9 @@ session_callback( session_cb_arg_t IN arg,
                   uint32_t 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,
+    // printl("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 )
+    if ( reason == SR_OK || status == SS_NONE ) //TODO: This does not seem like a good check, we could pass if reason has an error and status is SR_NONE
         iop_rfm_valid = 1;
     else
         iop_rfm_valid = 0;
@@ -45,13 +52,13 @@ session_callback( session_cb_arg_t IN arg,
 }
 
 /// Function for Dolphin connection callback
-int32_t
+static int32_t
 connect_callback( void IN*               arg,
                   sci_r_segment_handle_t IN remote_segment_handle,
                   uint32_t IN reason,
                   uint32_t IN status )
 {
-    // printkl("Connect callback reason=%d status=%d\n", reason, status);
+    // printl("Connect callback reason=%d status=%d\n", reason, status);
     if ( reason == 1 )
         iop_rfm_valid = 1;
     if ( reason == 3 )
@@ -61,14 +68,14 @@ connect_callback( void IN*               arg,
     return 0;
 }
 
-int32_t
+static int32_t
 create_segment_callback( void IN*               arg,
                          sci_l_segment_handle_t IN local_segment_handle,
                          uint32_t IN reason,
                          uint32_t IN source_node,
                          uint32_t IN local_adapter_number )
 {
-    // printkl("Create segment callback reason=%d source_node=%d\n", reason,
+    // printl("Create segment callback reason=%d source_node=%d\n", reason,
     // source_node);
     return 0;
 }
@@ -91,12 +98,12 @@ init_dolphin( int modules )
                                   create_segment_callback,
                                   0,
                                   &segment[ ii ] );
-        printk("DIS segment alloc status %d\n", err);
+        printl("DIS segment alloc status %d\n", err);
         if ( err )
             return -1;
 
         err = sci_set_local_segment_available( segment[ ii ], 0 );
-        printk("DIS segment making available status %d\n", err);
+        printl("DIS segment making available status %d\n", err);
         if ( err )
         {
             sci_remove_segment( &segment[ ii ], 0 );
@@ -104,7 +111,7 @@ init_dolphin( int modules )
         }
 
         err = sci_export_segment( segment[ ii ], 0, DIS_BROADCAST );
-        printk("DIS segment export status 0x%x\n", err);
+        printl("DIS segment export status 0x%x\n", err);
         if ( err )
         {
             sci_remove_segment( &segment[ ii ], 0 );
@@ -114,14 +121,14 @@ init_dolphin( int modules )
         read_addr = sci_local_kernel_virtual_address( segment[ ii ] );
         if ( read_addr == 0 )
         {
-            printk("DIS sci_local_kernel_virtual_address returned 0\n");
+            printl("DIS sci_local_kernel_virtual_address returned 0\n");
             sci_unexport_segment( segment[ ii ], 0, 0);
             sci_remove_segment( &segment[ ii ], 0 );
             return -4;
         }
         else
         {
-            printk("Dolphin memory read at 0x%p\n", read_addr);
+            printl("Dolphin memory read at 0x%p\n", read_addr);
             cdsPciModules.dolphinRead[ ii ] =
                 (volatile unsigned long*)read_addr;
         }
@@ -139,7 +146,7 @@ init_dolphin( int modules )
                                    connect_callback,
                                    0,
                                    &remote_segment_handle[ ii ] );
-        printk("DIS connect segment status %d\n", err);
+        printl("DIS connect segment status %d\n", err);
         if ( err )
         {
             sci_unexport_segment( segment[ ii ], 0, 0);
@@ -154,7 +161,7 @@ init_dolphin( int modules )
                                0,
                                IPC_TOTAL_ALLOC_SIZE,
                                &client_map_handle[ ii ] );
-        printk("DIS segment mapping status 0x%x\n", err);
+        printl("DIS segment mapping status 0x%x\n", err);
         if ( err )
         {
             sci_disconnect_segment( &remote_segment_handle[ ii ], 0 );
@@ -166,7 +173,7 @@ init_dolphin( int modules )
         addr = sci_kernel_virtual_address_of_mapping( client_map_handle[ ii ] );
         if ( addr == 0 )
         {
-            // printk ("Got zero pointer from
+            // printl ("Got zero pointer from
             // sci_kernel_virtual_address_of_mapping\n");
             sci_disconnect_segment( &remote_segment_handle[ ii ], 0 );
             sci_unexport_segment( segment[ ii ], 0, 0);
@@ -175,7 +182,7 @@ init_dolphin( int modules )
         }
         else
         {
-            printk ("Dolphin memory write at 0x%p\n", addr);
+            printl ("Dolphin memory write at 0x%p\n", addr);
             cdsPciModules.dolphinWrite[ ii ] = (volatile unsigned long*)addr;
         }
 
diff --git a/src/fe/dolphin.h b/src/fe/dolphin.h
new file mode 100644
index 0000000000000000000000000000000000000000..77d1241522bf613229d1f7fcb7a751d573b2d717
--- /dev/null
+++ b/src/fe/dolphin.h
@@ -0,0 +1,17 @@
+#ifndef LIGO_DOLPHIN_H
+#define LIGO_DOLPHIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int init_dolphin( int modules );
+void finish_dolphin( void );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_DOLPHIN_H
diff --git a/src/fe/map.c b/src/fe/map.c
index b721b6483efaf9756534c4694ddb8e699a322df6..790e981b447e87db33a2b57b2b320849e4c93374 100644
--- a/src/fe/map.c
+++ b/src/fe/map.c
@@ -1,39 +1,64 @@
 ///	\file map.c
 ///	\brief This file contains the software to find PCIe devices on the bus.
+//
+/// The header for this file is at include/drv/map.h
+
+#include "drv/map.h"
+
+
+
+#include "drv/cdsHardware.h"
+#include "drv/plx_9056.h"
+#include "commData3.h"
+#include "../drv/mbuf/mbuf_kernel.h"
+#include "map_cards_2_slots.h"
+#include "util/printl.h"
+
+// Include driver code for all supported I/O cards
+#include "drv/gsc16ai64.h"
+#include "drv/gsc18ai32.h"
+#include "drv/gsc18ai64.h"
+#include "drv/gsc_adc_common.h"
+#include "drv/gsc16ao16.h"
+#include "drv/gsc18ao8.h"
+#include "drv/gsc20ao8.h"
+#include "drv/gsc_dac_common.h"
+#include "drv/accesIIRO8.h"
+#include "drv/accesIIRO16.h"
+#include "drv/accesDio24.h"
+#include "drv/contec6464.h"
+#include "drv/contec1616.h"
+#include "drv/contec32o.h"
+#include "drv/vmic5565.h"
+#include "drv/symmetricomGps.h"
+#include "drv/spectracomGPS.h"
+#include "drv/ligoPcieTiming.h"
+#include "drv/spectracomGPS.h" //spectracomGpsInit()
+#include "controller.h"
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#undef printf
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
-#define printf printk
-#include <drv/cdsHardware.h>
-#include <drv/plx_9056.c>
-#include <drv/map.h>
-#include <commData3.h>
 
-// Include driver code for all supported I/O cards
-#include <drv/gsc16ai64.c>
-#include <drv/gsc18ai32.c>
-#include <drv/gsc18ai64.c>
-#include <drv/gsc_adc_common.c>
-#include <drv/gsc16ao16.c>
-#include <drv/gsc18ao8.c>
-#include <drv/gsc20ao8.c>
-#include <drv/gsc_dac_common.c>
-#include <drv/accesIIRO8.c>
-#include <drv/accesIIRO16.c>
-#include <drv/accesDio24.c>
-#include <drv/contec6464.c>
-#include <drv/contec1616.c>
-#include <drv/contec32o.c>
-#include <drv/vmic5565.c>
-#include <drv/symmetricomGps.c>
-#include <drv/spectracomGPS.c>
-#include <drv/ligoPcieTiming.c>
-#include "map_cards_2_slots.c"
+
+//
+// Global Data
+//
+dma_addr_t rfm_dma_handle[ MAX_DAC_MODULES ];
+//TODO: only vmic5565.c uses this, might be able to make parameter
+
+//
+// Local functions
+//
+#if defined( RUN_WO_IO_MODULES ) || defined( USE_DOLPHIN_TIMING ) || !defined(IOP_MODEL)
+static int mapPciModulesVirtual( CDS_HARDWARE* pCds );
+#else
+static int mapPciModulesRealCards( CDS_HARDWARE* pCds );
+#endif
+
 
 // *****************************************************************************
 /// \brief Patch to properly handle PEX PCIe chip for newer (PCIe) General
@@ -46,7 +71,7 @@ set_8111_prefetch( struct pci_dev* dacdev )
 {
     struct pci_dev* dev = dacdev->bus->self;
 
-    printk( "set_8111_prefetch: subsys=0x%x; vendor=0x%x\n",
+    printl( "set_8111_prefetch: subsys=0x%x; vendor=0x%x\n",
             dev->device,
             dev->vendor );
     if ( ( dev->device == 0x8111 ) && ( dev->vendor == PLX_VID ) )
@@ -74,7 +99,7 @@ set_8111_prefetch( struct pci_dev* dacdev )
 int 
 find_card_slot( CDS_HARDWARE* pCds, int ctype, int cinstance )
 {
-    int ii,jj;
+    int ii;
     for (ii=0;ii<pCds->ioc_cards;ii++)
     {
         if(pCds->ioc_config[ ii ] == ctype && pCds->ioc_instance[ ii ] == cinstance)
@@ -82,25 +107,155 @@ find_card_slot( CDS_HARDWARE* pCds, int ctype, int cinstance )
     }
     return -1;
 }
+
+
+int
+mapPciModules( CDS_HARDWARE* pCds )
+{
+#if defined( RUN_WO_IO_MODULES ) || defined( USE_DOLPHIN_TIMING ) || !defined(IOP_MODEL)
+    return mapPciModulesVirtual(pCds);
+#else
+    return mapPciModulesRealCards(pCds);
+#endif
+}
+
+
+// *****************************************************************************
+/// Routine to setup shared memory for virtual IO
+// *****************************************************************************
+#if defined( RUN_WO_IO_MODULES ) || defined( USE_DOLPHIN_TIMING ) || !defined(IOP_MODEL)
+static int
+mapPciModulesVirtual( CDS_HARDWARE* pCds )
+{
+    static struct pci_dev* dacdev;
+    int                    status;
+    int                    i,ii;
+    int                    ret;
+    int                    modCount = 0;
+//This does not build if CONTROL_MODEL is defined because the use of adc_cnt
+//is not blocked out below
+//#ifndef CONTROL_MODEL
+    int            adc_cnt = 0;
+//#endif
+    int            dac_cnt = 0;
+    char           fname[ 128 ];
+    volatile unsigned char* _device_shm;
+    volatile int*           data;
+    char err_msg[MBUF_ERROR_MSG_ALLOC_LEN];
+
+
+    dacdev = NULL;
+    status = 0;
+
+    // Initialize CDS_HARDWARE Structure
+    pCds->adcCount = 0;
+    pCds->dacCount = 0;
+    pCds->dioCount = 0;
+    pCds->doCount = 0;
+
+    for ( i = 0; i < pCds->cards; i++ )
+    {
+        if ( pCds->cards_used[ i ].type == GSC_18AO8 )
+        {
+            sprintf( fname, "%s_%d\n", "IO_DEV_", i );
+            ret = mbuf_allocate_area( fname, 8 * 4 * 65536, (volatile void **)&_device_shm );
+            if ( ret != MBUF_KERNEL_CODE_OK )
+            {
+                mbuf_lookup_error_msg(ret, err_msg);
+                printl( "mbuf_allocate_area() failed, error msg: %s\n", err_msg );
+                return -1;
+            }
+            pCds->pci_dac[ dac_cnt ] = (volatile int *)_device_shm;
+            pCds->dacType[ dac_cnt ] = GSC_18AO8;
+            pCds->dacInstance[ dac_cnt ] =  pCds->card_count[ GSC_18AO8 ];
+            pCds->dacCount++;
+            pCds->card_count[ GSC_18AO8 ] ++;
+            dac_cnt++;
+        }
+        if ( pCds->cards_used[ i ].type == GSC_16AO16 )
+        {
+            sprintf( fname, "%s_%d\n", "IO_DEV_", i );
+            ret = mbuf_allocate_area( fname, 16 * 4 * 65536, (volatile void **)&_device_shm );
+            if ( ret != MBUF_KERNEL_CODE_OK )
+            {
+                mbuf_lookup_error_msg(ret, err_msg);
+                printl( "mbuf_allocate_area() failed, error msg: %s\n", err_msg );
+                return -1;
+            }
+            pCds->pci_dac[ dac_cnt ] = (volatile int *)_device_shm;
+            pCds->dacType[ dac_cnt ] = GSC_16AO16;
+            pCds->dacInstance[ dac_cnt ] =  pCds->card_count[ GSC_16AO16 ];
+            pCds->dacCount++;
+            pCds->card_count[ GSC_16AO16 ] ++;
+            dac_cnt++;
+        }
+        if ( pCds->cards_used[ i ].type == GSC_20AO8 )
+        {
+            sprintf( fname, "%s_%d\n", "IO_DEV_", i );
+            ret = mbuf_allocate_area( fname, 8 * 4 * 65536, (volatile void **)&_device_shm );
+            if ( ret != MBUF_KERNEL_CODE_OK )
+            {
+                mbuf_lookup_error_msg(ret, err_msg);
+                printl( "mbuf_allocate_area() failed, error msg: %s\n", err_msg );
+                return -1;
+            }
+            pCds->pci_dac[ dac_cnt ] = (volatile int *)_device_shm;
+            pCds->dacType[ dac_cnt ] = GSC_20AO8;
+            pCds->dacInstance[ dac_cnt ] =  pCds->card_count[ GSC_20AO8 ];
+            pCds->dacCount++;
+            dac_cnt++;
+            pCds->card_count[ GSC_20AO8 ] ++;
+        }
+        if ( pCds->cards_used[ i ].type == GSC_16AI64SSA )
+        {
+            sprintf( fname, "%s_%d\n", "IO_DEV_", i );
+            ret = mbuf_allocate_area( fname, 32 * 4 * 128, (volatile void **)&_device_shm );
+            if ( ret != MBUF_KERNEL_CODE_OK )
+            {
+                mbuf_lookup_error_msg(ret, err_msg);
+                printl( "mbuf_allocate_area() failed, error msg: %s\n", err_msg );
+                return -1;
+            }
+            pCds->pci_adc[ adc_cnt ] = (volatile int *)_device_shm;
+            pCds->adcType[ adc_cnt ] = GSC_16AI64SSA;
+            pCds->adcInstance[ adc_cnt ] =  pCds->card_count[ GSC_16AI64SSA ];
+            pCds->card_count[ GSC_16AI64SSA ] ++;
+            pCds->adcChannels[ adc_cnt ] = 32;
+            pCds->adcCount++;
+            data = (volatile int *) pCds->pci_adc[ adc_cnt ];
+            for(ii=0;ii<64;ii++) {
+                *data = ii;
+                data ++;
+            }
+            adc_cnt++;
+        }
+        modCount++;
+    }
+    return ( modCount );
+}
+
+
+#else
+
 // *****************************************************************************
 /// Routine to find PCI modules and call the appropriate driver initialization
 /// software.
 // *****************************************************************************
-int
-mapPciModules( CDS_HARDWARE* pCds )
+static int
+mapPciModulesRealCards( CDS_HARDWARE* pCds )
 {
     static struct pci_dev* dacdev;
     int                    status;
     int                    i;
     int                    modCount = 0;
-    int fast_adc_cnt = 0;
     int adc_750_cnt = 0;
     int adc_cnt = 0;
     int dac_cnt = 0;
     int dac_18bit_cnt = 0;
     int dac_20bit_cnt = 0;
-    int bo_cnt = 0;
-    int use_it;
+    int            use_it;
+    int            bo_cnt = 0;
+    int            fast_adc_cnt = 0;
 
     dacdev = NULL;
     status = 0;
@@ -130,13 +285,13 @@ mapPciModules( CDS_HARDWARE* pCds )
                     pCds->adcSlot[ pCds->adcCount] = find_card_slot( pCds, GSC_16AI64SSA, adc_cnt );
                     status = gsc16ai64Init( pCds, dacdev );
                     pCds->adcTimeShift[ adc_cnt ] = pCds->cards_used[i].time_shift;
-                    printk( "adc card on bus %x; device %x status %d\n",
+                    printl( "adc card on bus %x; device %x status %d\n",
                             dacdev->bus->number,
                             PCI_SLOT( dacdev->devfn ),
                             status );
                     if(status != 0)
                     {
-                        printk( "Map fault GSC16AI64 ADC number %d slot %d\n",
+                        printl( "Map fault GSC16AI64 ADC number %d slot %d\n",
                             adc_cnt,pCds->adcSlot[ pCds->adcCount]);
                         return IO_CARD_MAP_ERROR;
                     } 
@@ -153,12 +308,12 @@ mapPciModules( CDS_HARDWARE* pCds )
                     pCds->adcSlot[ pCds->adcCount] = find_card_slot( pCds, GSC_18AI32SSC1M, fast_adc_cnt );
                     status = gsc18ai32Init( pCds, dacdev );
                     pCds->adcTimeShift[ adc_cnt ] = pCds->cards_used[i].time_shift;
-                    printk( "fast adc card on bus %x; device %x\n",
+                    printl( "fast adc card on bus %x; device %x\n",
                             dacdev->bus->number,
                             PCI_SLOT( dacdev->devfn ) );
                     if(status != 0)
                     {
-                        printk( "Map fault GSC18AI32 ADC number %d slot %d\n",
+                        printl( "Map fault GSC18AI32 ADC number %d slot %d\n",
                             fast_adc_cnt,pCds->adcSlot[ pCds->adcCount]);
                         return IO_CARD_MAP_ERROR;
                     } 
@@ -176,12 +331,12 @@ mapPciModules( CDS_HARDWARE* pCds )
                     pCds->adcSlot[ pCds->adcCount] = find_card_slot( pCds, GSC_18AI64SSC, adc_750_cnt );
                     status = gsc18ai64Init( pCds, dacdev );
                     pCds->adcTimeShift[ adc_cnt ] = pCds->cards_used[i].time_shift;
-                    printk( "750KHz adc card on bus %x; device %x\n",
+                    printl( "750KHz adc card on bus %x; device %x\n",
                             dacdev->bus->number,
                             PCI_SLOT( dacdev->devfn ) );
                     if(status != 0)
                     {
-                        printk( "Map fault GSC18AI64 ADC number %d slot %d\n",
+                        printl( "Map fault GSC18AI64 ADC number %d slot %d\n",
                             adc_750_cnt,pCds->adcSlot[ pCds->adcCount]);
                         return IO_CARD_MAP_ERROR;
                     } 
@@ -201,13 +356,13 @@ mapPciModules( CDS_HARDWARE* pCds )
                 {
                     pCds->dacSlot[ pCds->dacCount] = find_card_slot( pCds, GSC_16AO16, dac_cnt );
                     status = gsc16ao16Init( pCds, dacdev );
-                    printk( "16 bit dac card on bus %x; device %x status %d\n",
+                    printl( "16 bit dac card on bus %x; device %x status %d\n",
                             dacdev->bus->number,
                             PCI_SLOT( dacdev->devfn ),
                             status );
                     if(status != 0)
                     {
-                        printk( "Map fault GSC16AO16 DAC number %d slot %d\n",
+                        printl( "Map fault GSC16AO16 DAC number %d slot %d\n",
                             dac_cnt,pCds->dacSlot[ pCds->dacCount]);
                         return IO_CARD_MAP_ERROR;
                     } 
@@ -225,13 +380,13 @@ mapPciModules( CDS_HARDWARE* pCds )
                 {
                     pCds->dacSlot[ pCds->dacCount] = find_card_slot( pCds, GSC_18AO8, dac_18bit_cnt );
                     status = gsc18ao8Init( pCds, dacdev );
-                    printk( "18-bit dac card on bus %x; device %x status %d\n",
+                    printl( "18-bit dac card on bus %x; device %x status %d\n",
                             dacdev->bus->number,
                             PCI_SLOT( dacdev->devfn ),
                             status );
                     if(status != 0)
                     {
-                        printk( "Map fault GSC18AO8 DAC number %d slot %d\n",
+                        printl( "Map fault GSC18AO8 DAC number %d slot %d\n",
                             dac_18bit_cnt,pCds->dacSlot[ pCds->dacCount]);
                         return IO_CARD_MAP_ERROR;
                     }
@@ -248,13 +403,13 @@ mapPciModules( CDS_HARDWARE* pCds )
                 {
                     pCds->dacSlot[ pCds->dacCount] = find_card_slot( pCds, GSC_20AO8, dac_20bit_cnt );
                     status = gsc20ao8Init( pCds, dacdev );
-                    printk( "20-bit dac card on bus %x; device %x status %d\n",
+                    printl( "20-bit dac card on bus %x; device %x status %d\n",
                             dacdev->bus->number,
                             PCI_SLOT( dacdev->devfn ),
                             status );
                     if(status != 0)
                     {
-                        printk( "Map fault GSC18AO8 DAC number %d slot %d\n",
+                        printl( "Map fault GSC18AO8 DAC number %d slot %d\n",
                             dac_20bit_cnt,pCds->dacSlot[ pCds->dacCount]);
                         return IO_CARD_MAP_ERROR;
                     } 
@@ -262,7 +417,7 @@ mapPciModules( CDS_HARDWARE* pCds )
                 dac_20bit_cnt++;
             }
         } // end of while
-    } // end of pci_cards used
+    } // end of pci_cards useddrv/map.h
 
     dacdev = NULL;
     status = 0;
@@ -287,7 +442,7 @@ mapPciModules( CDS_HARDWARE* pCds )
         }
         if ( use_it )
         {
-            printk( "Access 24 BIO card on bus %x; device %x vendor 0x%x\n",
+            printl( "Access 24 BIO card on bus %x; device %x vendor 0x%x\n",
                     dacdev->bus->number,
                     PCI_SLOT( dacdev->devfn ),
                     dacdev->device );
@@ -323,7 +478,7 @@ mapPciModules( CDS_HARDWARE* pCds )
         }
         if ( use_it )
         {
-            printk( "Access 8 BIO card on bus %x; device %x vendor 0x%x\n",
+            printl( "Access 8 BIO card on bus %x; device %x vendor 0x%x\n",
                     dacdev->bus->number,
                     PCI_SLOT( dacdev->devfn ),
                     dacdev->device );
@@ -360,7 +515,7 @@ mapPciModules( CDS_HARDWARE* pCds )
         }
         if ( use_it )
         {
-            printk( "Access BIO-16 card on bus %x; device %x\n",
+            printl( "Access BIO-16 card on bus %x; device %x\n",
                     dacdev->bus->number,
                     PCI_SLOT( dacdev->devfn ) );
             status = accesIiro16Init( pCds, dacdev );
@@ -393,7 +548,7 @@ mapPciModules( CDS_HARDWARE* pCds )
         }
         if ( use_it )
         {
-            printk( "Contec 6464 DIO card on bus %x; device %x\n",
+            printl( "Contec 6464 DIO card on bus %x; device %x\n",
                     dacdev->bus->number,
                     PCI_SLOT( dacdev->devfn ) );
             status = contec6464Init( pCds, dacdev );
@@ -413,7 +568,7 @@ mapPciModules( CDS_HARDWARE* pCds )
     // setting LIGO timing card (non-PCIe version) settings
     while ( ( dacdev = pci_get_device( CONTEC_VID, C_DIO_1616L_PE, dacdev ) ) )
     {
-        printk( "Contec 1616 DIO card on bus %x; device %x\n",
+        printl( "Contec 1616 DIO card on bus %x; device %x\n",
                 dacdev->bus->number,
                 PCI_SLOT( dacdev->devfn ) );
         status = contec1616Init( pCds, dacdev );
@@ -445,7 +600,7 @@ mapPciModules( CDS_HARDWARE* pCds )
         }
         if ( use_it )
         {
-            printk( "Contec BO card on bus %x; device %x\n",
+            printl( "Contec BO card on bus %x; device %x\n",
                     dacdev->bus->number,
                     PCI_SLOT( dacdev->devfn ) );
             status = contec32OutInit( pCds, dacdev );
@@ -471,7 +626,7 @@ mapPciModules( CDS_HARDWARE* pCds )
     // Look for TSYNC GPS board
     if ( ( dacdev = pci_get_device( TSYNC_VID, TSYNC_TID, dacdev ) ) )
     {
-        printk( "TSYNC GPS card on bus %x; device %x\n",
+        printl( "TSYNC GPS card on bus %x; device %x\n",
                 dacdev->bus->number,
                 PCI_SLOT( dacdev->devfn ) );
         status = spectracomGpsInit( pCds, dacdev );
@@ -483,7 +638,7 @@ mapPciModules( CDS_HARDWARE* pCds )
     while ( ( dacdev = pci_get_device( 0x10ee, PCI_ANY_ID, dacdev ) ) )
     {
 	if(dacdev != NULL) {
-            printk( "Xilinx card on bus %x; device %x vendor 0x%x\n",
+            printl( "Xilinx card on bus %x; device %x vendor 0x%x\n",
                     dacdev->bus->number,
                     PCI_SLOT( dacdev->devfn ),
                     dacdev->device );
@@ -494,3 +649,5 @@ mapPciModules( CDS_HARDWARE* pCds )
 
     return ( modCount );
 }
+
+#endif
diff --git a/src/fe/mapApp.c b/src/fe/mapApp.c
index 90852cb77800d629a85349b92ec31ae14e16c780..92447742bebb6ebd1ed9d921970e6e67727f5fa0 100644
--- a/src/fe/mapApp.c
+++ b/src/fe/mapApp.c
@@ -2,19 +2,19 @@
 /// \brief This file contains the software to find PCIe card mapping from IOP in
 /// mbuf..
 
+#include "mapApp.h"
+#include "controller.h"
+#include FE_HEADER //SYSTEM_NAME_STRING_LOWER
 
-int mapPciModules( CDS_HARDWARE* );
-void initmap(CDS_HARDWARE* );
-
+#include "util/printl.h"
 
 int
 mapPciModules( CDS_HARDWARE* pCds )
 {
     int status = 0;
     int ii, jj, kk; /// @param ii,jj,kk default loop counters
-    int cards; /// @param cards Number of PCIe cards found on bus
 
-    printf( "" SYSTEM_NAME_STRING_LOWER ":IOP clock %u\n", ioMemData->mem_data_rate );
+    printl( SYSTEM_NAME_STRING_LOWER ":IOP clock %u\n", ioMemData->mem_data_rate );
 
     // Have to search thru all cards and find desired instance for application
     // IOP will map ADC cards first, then DAC and finally DIO
@@ -64,7 +64,7 @@ mapPciModules( CDS_HARDWARE* pCds )
                 {
                     kk = pCds->dacMap[ jj ];
                     pCds->dacConfig[ kk ] = ioMemData->ipc[ ii ];
-                    pCds->pci_dac[ kk ] = (long)( ioMemData->iodata[ ii ] );
+                    pCds->pci_dac[ kk ] = (volatile int *)( ioMemData->iodata[ ii ] );
                     pCds->card_count[ GSC_16AO16 ] ++;
                     status++;
                 }
@@ -76,7 +76,7 @@ mapPciModules( CDS_HARDWARE* pCds )
                 {
                     kk = pCds->dacMap[ jj ];
                     pCds->dacConfig[ kk ] = ioMemData->ipc[ ii ];
-                    pCds->pci_dac[ kk ] = (long)( ioMemData->iodata[ ii ] );
+                    pCds->pci_dac[ kk ] = (volatile int *)( ioMemData->iodata[ ii ] );
                     pCds->card_count[ GSC_18AO8 ] ++;
                     status++;
                 }
@@ -88,7 +88,7 @@ mapPciModules( CDS_HARDWARE* pCds )
                 {
                     kk = pCds->dacMap[ jj ];
                     pCds->dacConfig[ kk ] = ioMemData->ipc[ ii ];
-                    pCds->pci_dac[ kk ] = (long)( ioMemData->iodata[ ii ] );
+                    pCds->pci_dac[ kk ] = (volatile int *)( ioMemData->iodata[ ii ] );
                     pCds->card_count[ GSC_20AO8 ] ++;
                     status++;
                 }
@@ -203,9 +203,9 @@ mapPciModules( CDS_HARDWARE* pCds )
 
 void initmap(CDS_HARDWARE* pCds)
 {
-int i;
-int dac_cnt = 0;
-int adc_cnt = 0;
+    int i;
+    int dac_cnt = 0;
+    int adc_cnt = 0;
     pCds->adcCount = 0;
     pCds->dacCount = 0;
     pCds->dioCount = 0;
diff --git a/src/fe/mapApp.h b/src/fe/mapApp.h
new file mode 100644
index 0000000000000000000000000000000000000000..2bc8b6132fad66d75930305f9c39fe3b312649b0
--- /dev/null
+++ b/src/fe/mapApp.h
@@ -0,0 +1,19 @@
+#ifndef LIGO_MAPAPP_H
+#define LIGO_MAPAPP_H
+
+#include "controllerko.h" //ioMemData
+#include "drv/cdsHardware.h" //CDS_HARDWARE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int mapPciModules( CDS_HARDWARE* );
+void initmap(CDS_HARDWARE* );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_MAPAPP_H
diff --git a/src/fe/mapVirtual.c b/src/fe/mapVirtual.c
deleted file mode 100644
index ef4a766f6181226ef591f41c4e71fb1aabd8ed24..0000000000000000000000000000000000000000
--- a/src/fe/mapVirtual.c
+++ /dev/null
@@ -1,183 +0,0 @@
-///	\file map.c
-///	\brief This file contains the software to find PCIe devices on the bus.
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#undef printf
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#define printf printk
-#include <drv/cdsHardware.h>
-#include <drv/plx_9056.c>
-#include <drv/map.h>
-#include <commData3.h>
-
-
-// Include driver code for all supported I/O cards
-#include <drv/gsc16ai64.c>
-#include <drv/gsc18ai32.c>
-#include <drv/gsc18ai64.c>
-#include <drv/gsc_adc_common.c>
-#include <drv/gsc16ao16.c>
-#include <drv/gsc18ao8.c>
-#include <drv/gsc20ao8.c>
-#include <drv/gsc_dac_common.c>
-#include <drv/accesIIRO8.c>
-#include <drv/accesIIRO16.c>
-#include <drv/accesDio24.c>
-#include <drv/contec6464.c>
-#include <drv/contec1616.c>
-#include <drv/contec32o.c>
-#include <drv/vmic5565.c>
-#include <drv/symmetricomGps.c>
-#include <drv/spectracomGPS.c>
-#include <drv/ligoPcieTiming.c>
-#include "map_cards_2_slots.c"
-
-// *****************************************************************************
-/// \brief Patch to properly handle PEX PCIe chip for newer (PCIe) General
-/// Standards
-///< DAC modules ie those that are integrated PCIe boards vs. earlier versions
-///< built with carrier boards. \n This is extracted from code provided by GSC..
-// *****************************************************************************
-void
-set_8111_prefetch( struct pci_dev* dacdev )
-{
-    struct pci_dev* dev = dacdev->bus->self;
-
-    printk( "set_8111_prefetch: subsys=0x%x; vendor=0x%x\n",
-            dev->device,
-            dev->vendor );
-    if ( ( dev->device == 0x8111 ) && ( dev->vendor == PLX_VID ) )
-    {
-        unsigned int reg;
-        // Handle PEX 8111 setup, enable prefetch, set pref size to 64
-        // These numbers come from reverse engineering the GSC pxe8111 driver
-        // and using their prefetch program to enable the prefetch and set pref
-        // size to 64
-        pci_write_config_dword( dev, 132, 72 );
-        pci_read_config_dword( dev, 136, &reg );
-        pci_write_config_dword( dev, 136, reg );
-        pci_write_config_dword( dev, 132, 72 );
-        pci_read_config_dword( dev, 136, &reg );
-        pci_write_config_dword( dev, 136, reg | 1 );
-        pci_write_config_dword( dev, 132, 12 );
-        pci_read_config_dword( dev, 136, &reg );
-        pci_write_config_dword( dev, 136, reg | 0x8000000 );
-    }
-}
-
-// *****************************************************************************
-/// Routine to find PCI modules and call the appropriate driver initialization
-/// software.
-// *****************************************************************************
-int
-mapPciModules( CDS_HARDWARE* pCds )
-{
-    static struct pci_dev* dacdev;
-    int                    status;
-    int                    i,ii;
-    int                    ret;
-    int                    modCount = 0;
-#ifndef CONTROL_MODEL
-    int            adc_cnt = 0;
-#endif
-    int            dac_cnt = 0;
-    int            fast_adc_cnt = 0;
-    int            bo_cnt = 0;
-    int            use_it;
-    char           fname[ 128 ];
-    unsigned char* _device_shm;
-    int*           data;
-
-    dacdev = NULL;
-    status = 0;
-
-    // Initialize CDS_HARDWARE Structure
-    pCds->adcCount = 0;
-    pCds->dacCount = 0;
-    pCds->dioCount = 0;
-    pCds->doCount = 0;
-
-    for ( i = 0; i < pCds->cards; i++ )
-    {
-        if ( pCds->cards_used[ i ].type == GSC_18AO8 )
-        {
-            sprintf( fname, "%s_%d\n", "IO_DEV_", i );
-            ret = mbuf_allocate_area( fname, 8 * 4 * 65536, 0 );
-            if ( ret < 0 )
-            {
-                printf( "mbuf_allocate_area() failed; ret = %d\n", ret );
-                return -1;
-            }
-            _device_shm = (unsigned char*)( kmalloc_area[ ret ] );
-            pCds->pci_dac[ dac_cnt ] = (long)_device_shm;
-            pCds->dacType[ dac_cnt ] = GSC_18AO8;
-            pCds->dacInstance[ dac_cnt ] =  pCds->card_count[ GSC_18AO8 ];
-            pCds->dacCount++;
-            pCds->card_count[ GSC_18AO8 ] ++;
-            dac_cnt++;
-        }
-        if ( pCds->cards_used[ i ].type == GSC_16AO16 )
-        {
-            sprintf( fname, "%s_%d\n", "IO_DEV_", i );
-            ret = mbuf_allocate_area( fname, 16 * 4 * 65536, 0 );
-            if ( ret < 0 )
-            {
-                printf( "mbuf_allocate_area() failed; ret = %d\n", ret );
-                return -1;
-            }
-            _device_shm = (unsigned char*)( kmalloc_area[ ret ] );
-            pCds->pci_dac[ dac_cnt ] = (long)_device_shm;
-            pCds->dacType[ dac_cnt ] = GSC_16AO16;
-            pCds->dacInstance[ dac_cnt ] =  pCds->card_count[ GSC_16AO16 ];
-            pCds->dacCount++;
-            pCds->card_count[ GSC_16AO16 ] ++;
-            dac_cnt++;
-        }
-        if ( pCds->cards_used[ i ].type == GSC_20AO8 )
-        {
-            sprintf( fname, "%s_%d\n", "IO_DEV_", i );
-            ret = mbuf_allocate_area( fname, 8 * 4 * 65536, 0 );
-            if ( ret < 0 )
-            {
-                printf( "mbuf_allocate_area() failed; ret = %d\n", ret );
-                return -1;
-            }
-            _device_shm = (unsigned char*)( kmalloc_area[ ret ] );
-            pCds->pci_dac[ dac_cnt ] = (long)_device_shm;
-            pCds->dacType[ dac_cnt ] = GSC_20AO8;
-            pCds->dacInstance[ dac_cnt ] =  pCds->card_count[ GSC_20AO8 ];
-            pCds->dacCount++;
-            dac_cnt++;
-            pCds->card_count[ GSC_20AO8 ] ++;
-        }
-        if ( pCds->cards_used[ i ].type == GSC_16AI64SSA )
-        {
-            sprintf( fname, "%s_%d\n", "IO_DEV_", i );
-            ret = mbuf_allocate_area( fname, 32 * 4 * 128, 0 );
-            if ( ret < 0 )
-            {
-                printf( "mbuf_allocate_area() failed; ret = %d\n", ret );
-                return -1;
-            }
-            _device_shm = (unsigned char*)( kmalloc_area[ ret ] );
-            pCds->pci_adc[ adc_cnt ] = (long)_device_shm;
-            pCds->adcType[ adc_cnt ] = GSC_16AI64SSA;
-            pCds->adcInstance[ adc_cnt ] =  pCds->card_count[ GSC_16AI64SSA ];
-            pCds->card_count[ GSC_16AI64SSA ] ++;
-            pCds->adcChannels[ adc_cnt ] = 32;
-            pCds->adcCount++;
-            data = (int *) pCds->pci_adc[ adc_cnt ];
-            for(ii=0;ii<64;ii++) {
-                *data = ii;
-                data ++;
-            }
-            adc_cnt++;
-        }
-        modCount++;
-    }
-    return ( modCount );
-}
diff --git a/src/fe/map_cards_2_slots.c b/src/fe/map_cards_2_slots.c
index 92c3afd2e6b84ba3e512cb1145b5b5b11006d2ba..bdbd7dd4a2304a30a3d403b326d69b255e08c031 100644
--- a/src/fe/map_cards_2_slots.c
+++ b/src/fe/map_cards_2_slots.c
@@ -1,3 +1,17 @@
+#include "../fe/map_cards_2_slots.h"
+
+#include "controller.h"
+#include "drv/plx_9056.h" //PLX_VID
+#include "drv/gsc16ai64.h" //ADC_SS_ID
+#include "drv/gsc18ai32.h" //ADC_18AI32_SS_ID
+#include "drv/gsc16ao16.h" //DAC_SS_ID
+#include "drv/gsc18ai64.h" //ADC_18AI64_SS_ID
+#include "drv/gsc18ao8.h" //DAC_18BIT_SS_ID
+#include "drv/gsc20ao8.h" //DAC_20BIT_SS_ID
+
+#include <linux/types.h> //NULL
+#include <linux/pci.h>
+
 int
 map_cards_2_slots (CDS_HARDWARE* pCds )
 {
diff --git a/src/fe/map_cards_2_slots.h b/src/fe/map_cards_2_slots.h
new file mode 100644
index 0000000000000000000000000000000000000000..cd867031552aed388f14e178acc5555a374ce5dc
--- /dev/null
+++ b/src/fe/map_cards_2_slots.h
@@ -0,0 +1,17 @@
+#ifndef LIGO_MAP_CARDS_2_SLOTS_H
+#define LIGO_MAP_CARDS_2_SLOTS_H
+
+#include "drv/cdsHardware.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int map_cards_2_slots (CDS_HARDWARE* pCds );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_MAP_CARDS_2_SLOTS_H
diff --git a/src/fe/moduleLoad.c b/src/fe/moduleLoad.c
index f8561493a8ea60e13a35343d594577e473b2bad2..573c7dfca2b229f5c74fdd4a71724508f28a0bd8 100644
--- a/src/fe/moduleLoad.c
+++ b/src/fe/moduleLoad.c
@@ -1,20 +1,37 @@
 ///	@file moduleLoad.c
 ///	@brief File contains startup routines for real-time IOP and App code.
 
+#include "moduleLoadCommon.h"
+
+#include "controller.h" //daqArea
+#include "rts-cpu-isolator/rts-cpu-isolator.h"
+#include "verify_card_count.h"
+#include "print_io_info.h"
+#include "util/printl.h"
+#include "drv/map.h" //mapPciModules()
+#include "drv/ligoPcieTiming.h"
+#include "../fe/verify_slots.h"
+#include "../fe/mapApp.h" //initmap()
+#include "../fe/dolphin.h"
+
+
+#include <linux/uaccess.h>
 #include <asm/uaccess.h>
 #include <linux/ctype.h>
 #include <linux/spinlock_types.h>
+#include <linux/delay.h> //msleep
+#include <linux/module.h>
+#include <linux/init.h>
 
-#include "rts-cpu-isolator/rts-cpu-isolator.h"
 
-// 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_controller( void );
-extern char  daqArea[ DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers
-struct task_struct* sthread;
 
-extern void msleep( unsigned int );
+//
+// File function prototypes
+//
+void rt_fe_cleanup( void );
+int rt_fe_init( void );
+
 
 #ifdef IOP_MODEL
 int need_to_load_IOP_first;
@@ -23,9 +40,10 @@ EXPORT_SYMBOL( need_to_load_IOP_first );
 extern int need_to_load_IOP_first;
 #endif
 
-#include "moduleLoadCommon.c"
-#include "verify_card_count.c"
-#include "print_io_info.c"
+
+#ifdef NO_CPU_SHUTDOWN
+
+static struct task_struct* sthread;
 
 /// @breif Wrapper function so kthread_create()
 ///        can have a function with the expected
@@ -38,24 +56,23 @@ static int  fe_start_controller_kthread( void * arg )
     return 0;
 }
 
+#endif //NO_CPU_SHUTDOWN
+
 // MAIN routine: Code starting point
 // ****************************************************************
 /// Startup function for initialization of kernel module.
 int
 rt_fe_init( void )
 {
-    int status;
-    int ii, jj, kk; /// @param ii,jj,kk default loop counters
+    int jj, kk; /// @param ii,jj,kk default loop counters
     int cards; /// @param cards Number of PCIe cards found on bus
     int ret; /// @param ret Return value from various Malloc calls to allocate
              /// memory.
     int        cnt;
-    int        adcCount = 0;
-    int        dacCount = 0;
-    int        dioCount = 0;
-    int        doCount = 0;
     int        cardsfound = 0;
+#if (defined(IOP_MODEL) && !defined(USE_DOLPHIN_TIMING) && !defined(TEST_1PPS) ) || defined (REQUIRE_IO_CNT)
     int        io_config_stat = 0;
+#endif
     int        io_count_stat = 0;
     int model_cards[MAX_IO_MODULES];
 
@@ -70,21 +87,23 @@ rt_fe_init( void )
     /// Verify requested core is free.
     if ( is_cpu_taken_by_rcg_model( CPUID ) )
     {
-        printk( KERN_ALERT "Error: CPU %d already taken\n", CPUID );
+        printl( KERN_ALERT "Error: CPU %d already taken\n", CPUID );
         return -1;
     }
 #endif
 
 #ifdef DOLPHIN_TEST
-    /// Initialize the Dolphin interface
-    status = init_dolphin( 2 );
-    if ( status != 0 )
     {
-        printk( "" SYSTEM_NAME_STRING_LOWER
-                ": ERROR: Dolphin Network initialization failed; status = %d\n",
-                status );
-        rt_fe_cleanup( );
-        return -6;
+        /// Initialize the Dolphin interface
+        int status = init_dolphin( 2 );
+        if ( status != 0 )
+        {
+            printl( "" SYSTEM_NAME_STRING_LOWER
+                    ": ERROR: Dolphin Network initialization failed; status = %d\n",
+                    status );
+            rt_fe_cleanup( );
+            return -6;
+        }
     }
 #endif
 
@@ -96,7 +115,7 @@ rt_fe_init( void )
     ret = attach_shared_memory( );
     if ( ret < 0 )
     {
-        printk( "" SYSTEM_NAME_STRING_LOWER
+        printl( "" SYSTEM_NAME_STRING_LOWER
                 ": ERROR: mbuf_allocate_area failed; ret = %d\n",
                 ret );
         rt_fe_cleanup( );
@@ -122,20 +141,22 @@ rt_fe_init( void )
     {
         pLocalEpics->epicsOutput.fe_status = IO_CARD_MAP_ERROR;
         rt_fe_cleanup( );
+        detach_shared_memory();
         return -5;
     }
 
     // If no ADC cards were found, then cannot run
     if ( !cdsPciModules.adcCount )
     {
-        printk( "" SYSTEM_NAME_STRING_LOWER
+        printl( "" SYSTEM_NAME_STRING_LOWER
                 ": ERROR: No ADC cards found - exiting\n" );
         rt_fe_cleanup( );
+        detach_shared_memory();
         return -5;
     }
 
     // Verify all IO cards specified in model have been found on bus
-    io_count_stat = verify_card_count( &cdsPciModules, &model_cards );
+    io_count_stat = verify_card_count( &cdsPciModules, (int*) &model_cards, SYSTEM_NAME_STRING_LOWER );
 
 #ifdef IOP_MODEL
 #ifndef USE_DOLPHIN_TIMING
@@ -171,7 +192,7 @@ rt_fe_init( void )
     // wait to ensure EPICS is running before proceeding
     pLocalEpics->epicsOutput.fe_status = WAIT_BURT;
     msleep( 5000 );
-    printk( "" SYSTEM_NAME_STRING_LOWER
+    printl( "" SYSTEM_NAME_STRING_LOWER
             ": Waiting for EPICS BURT Restore = %d\n",
             pLocalEpics->epicsInput.burtRestore );
     /// Ensure EPICS running else exit
@@ -181,7 +202,7 @@ rt_fe_init( void )
     }
     if ( cnt == 10 )
     {
-        printk( "" SYSTEM_NAME_STRING_LOWER
+        printl( "" SYSTEM_NAME_STRING_LOWER
                 ": ERROR: EPICS restore not set - exiting\n" );
         pLocalEpics->epicsOutput.fe_status = BURT_RESTORE_ERROR;
         // Cleanup
@@ -195,28 +216,29 @@ rt_fe_init( void )
     // Print out all the I/O information
     // Following routine is in moduleLoadCommon.c
 #ifdef IOP_MODEL
-    print_io_info( &cdsPciModules, 1 );
+    print_io_info(SYSTEM_NAME_STRING_LOWER, &cdsPciModules, 1 );
 #else
-    print_io_info( &cdsPciModules, 0 );
+    print_io_info(SYSTEM_NAME_STRING_LOWER, &cdsPciModules, 0 );
 #endif
 #ifdef REQUIRE_IO_CNT
-    printk( "IO stat = %d\n", io_config_stat );
+    printl( "IO stat = %d\n", io_config_stat );
     if ( io_config_stat == IO_CONFIG_ERROR || io_count_stat == IO_CONFIG_ERROR)
     {
 #ifdef DOLPHIN_TEST
         finish_dolphin( );
 #endif
         pLocalEpics->epicsOutput.fe_status = IO_CONFIG_ERROR;
-        printk( "" SYSTEM_NAME_STRING_LOWER
+        printl( "" SYSTEM_NAME_STRING_LOWER
                 ": ERROR: Exit on incorrect card count \n" );
         rt_fe_cleanup( );
+        detach_shared_memory();
         return -5;
     }
 #endif
 
-    printk("model rate (Hz) = %d\n", MODEL_RATE_CPS);
-    printk("clock_div = %d\n", UNDERSAMPLE);
-    printk("usec_per_cycle = %d\n", USEC_PER_CYCLE);
+    printl("model rate (Hz) = %d\n", MODEL_RATE_CPS);
+    printl("clock_div = %d\n", UNDERSAMPLE);
+    printl("usec_per_cycle = %d\n", USEC_PER_CYCLE);
 
     pLocalEpics->epicsInput.vmeReset = 0;
     udelay( 2000 );
@@ -227,7 +249,8 @@ rt_fe_init( void )
         fe_start_controller_kthread, 0, "fe_start_controller_kthread/%d", CPUID );
     if ( IS_ERR( sthread ) )
     {
-        printk( "Failed to kthread_create()\n" );
+        printl( "Failed to kthread_create()\n" );
+        detach_shared_memory();
         return -1;
     }
     kthread_bind( sthread, CPUID );
@@ -236,7 +259,7 @@ rt_fe_init( void )
 
 #ifndef NO_CPU_SHUTDOWN
     pLocalEpics->epicsOutput.fe_status = LOCKING_CORE;
-    printk( "" SYSTEM_NAME_STRING_LOWER ": Locking CPU core %d\n", CPUID );
+    printl( "" SYSTEM_NAME_STRING_LOWER ": Locking CPU core %d\n", CPUID );
 
     // The code runs on the disabled CPU
     set_fe_code_idle( fe_start_controller, CPUID );
@@ -251,17 +274,15 @@ rt_fe_init( void )
 void
 rt_fe_cleanup( void )
 {
-    int ret;
 #ifndef NO_CPU_SHUTDOWN
     /// Unset the code callback
     set_fe_code_idle( 0, CPUID );
 #endif
 
-    // printk("Setting stop_working_threads to 1\n");
+    // printl("Setting stop_working_threads to 1\n");
     // Stop the code and wait
 #ifdef NO_CPU_SHUTDOWN
-    // int ret;
-    ret = kthread_stop( sthread );
+    kthread_stop( sthread );
 #endif
     stop_working_threads = 1;
     msleep( 1000 );
@@ -276,7 +297,7 @@ rt_fe_cleanup( void )
     /// 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);
+    // printll("Will bring back CPU %d\n", CPUID);
     msleep( 1000 );
     // Bring the CPU back up
     rts_isolator_cleanup( CPUID );
@@ -284,8 +305,8 @@ rt_fe_cleanup( void )
 #endif
 
     // Print out any error messages from FE code on exit
-    print_exit_messages( fe_status_return, fe_status_return_subcode );
-    ret = detach_shared_memory( );
+    print_exit_messages( fe_status_return, fe_status_return_subcode, SYSTEM_NAME_STRING_LOWER );
+    detach_shared_memory( );
 }
 
 module_init( rt_fe_init );
diff --git a/src/fe/moduleLoadCommon.c b/src/fe/moduleLoadCommon.c
index f97782455db2a7385cb211c9db115e54a5a5efe3..1c21c8225ae83a35ec13847cbc676b986854b46c 100644
--- a/src/fe/moduleLoadCommon.c
+++ b/src/fe/moduleLoadCommon.c
@@ -2,43 +2,50 @@
 ///     @brief File contains common routines for moduleLoad.c
 ///     for both IOP and User apps.`
 
+#include "moduleLoadCommon.h"
+#include "controller.h" //FILT_INIT_ERROR, etc
+#include "feComms.h" //RFM_FE_COMMS
+#include "controllerko.h" //tdsControl, tdsCount
+#include "mbuf/mbuf_kernel.h" //MBUF_ERROR_MSG_ALLOC_LEN, MBUF_KERNEL_CODE_OK
+#include "util/printl.h"
+
 void
-print_exit_messages( int error_type, int error_sub )
+print_exit_messages( int error_type, int error_sub, const char * sysname)
 {
-    printf( "" SYSTEM_NAME_STRING_LOWER " : Brought the CPU back up\n" );
+    printl( "%s : Brought the CPU back up\n", sysname );
     switch ( error_type )
     {
     case FILT_INIT_ERROR:
-        printf( "" SYSTEM_NAME_STRING_LOWER " FE error: %s\n",
-                "exited on filter initiialization error" );
+        printl( "%s FE error: %s\n",
+                sysname, "exited on filter initiialization error" );
         break;
     case DAQ_INIT_ERROR:
-        printf( "" SYSTEM_NAME_STRING_LOWER " FE error: %s\n",
-                "exited on DAQ initiialization error" );
+        printl( "%s FE error: %s\n",
+                sysname, "exited on DAQ initiialization error");
         break;
     case CHAN_HOP_ERROR:
-        printf( "" SYSTEM_NAME_STRING_LOWER " FE error: %s\n",
-                "exited on ADC Channel Hopping error" );
-        printf( "" SYSTEM_NAME_STRING_LOWER " : Error detected on ADC %d\n",
-                error_sub );
+        printl( "%s FE error: %s\n",
+                sysname, "exited on ADC Channel Hopping error");
+        printl( "%s : Error detected on ADC %d\n",
+                sysname, error_sub );
         break;
     case BURT_RESTORE_ERROR:
-        printf( "" SYSTEM_NAME_STRING_LOWER " FE error: %s\n",
-                "exited on BURT restore error" );
+        printl( "%s FE error: %s\n",
+                sysname, "exited on BURT restore error");
         break;
     case DAC_INIT_ERROR:
-        printf( "" SYSTEM_NAME_STRING_LOWER " FE error: %s\n",
-                "exited on DAC module initialization error" );
+        printl( "%s FE error: %s\n",
+                sysname, "exited on DAC module initialization error" );
         break;
     case ADC_TO_ERROR:
-        printf( "" SYSTEM_NAME_STRING_LOWER " FE error: %s\n",
-                "exited on ADC module timeout error" );
-        printf( "" SYSTEM_NAME_STRING_LOWER " : Error detected on ADC %d\n",
-                error_sub );
+        printl( "%s FE error: %s\n",
+                sysname, "exited on ADC module timeout error");
+        printl( "%s : Error detected on ADC %d\n",
+                sysname, error_sub );
         break;
     default:
-        printf( "Returning from cleanup_module "
-                "for " SYSTEM_NAME_STRING_LOWER "\n" );
+        printl( "Returning from cleanup_module "
+                "for %s\n", sysname );
         break;
     }
 }
@@ -47,110 +54,80 @@ print_exit_messages( int error_type, int error_sub )
 int
 detach_shared_memory( )
 {
-    int  ret;
-    char fname[ 128 ];
-
-    ret = mbuf_release_area( SYSTEM_NAME_STRING_LOWER, _epics_shm );
-    sprintf( fname, "%s%s", SYSTEM_NAME_STRING_LOWER, SHMEM_TESTPOINT_SUFFIX);
-    ret = mbuf_release_area( fname, _tp_shm );
-    sprintf( fname, "%s%s", SYSTEM_NAME_STRING_LOWER, SHMEM_AWG_SUFFIX);
-    ret = mbuf_release_area( fname, _awg_shm );
-    ret = mbuf_release_area( "ipc", _ipc_shm );
-    ret = mbuf_release_area( "shmipc", _shmipc_shm );
-    sprintf( fname, "%s_daq", SYSTEM_NAME_STRING_LOWER );
-    ret = mbuf_release_area( fname, _daq_shm );
-    return ret;
+    mbuf_release_area( SYSTEM_NAME_STRING_LOWER);
+    mbuf_release_area( SYSTEM_NAME_STRING_LOWER SHMEM_TESTPOINT_SUFFIX);
+    mbuf_release_area( SYSTEM_NAME_STRING_LOWER SHMEM_AWG_SUFFIX );
+    mbuf_release_area( "ipc" );
+    mbuf_release_area( "shmipc" );
+    mbuf_release_area( SYSTEM_NAME_STRING_LOWER "_daq");
+    return 0;
 }
+
+
 int
 attach_shared_memory( )
 {
-    int  ret;
+    enum MBUF_KERNEL_CODE  ret;
     char fname[ 128 ];
+    char err_msg[MBUF_ERROR_MSG_ALLOC_LEN];
 
     /// Allocate EPICS memory area
-    ret = mbuf_allocate_area( SYSTEM_NAME_STRING_LOWER, 64 * 1024 * 1024, 0 );
-    if ( ret < 0 )
-    {
-        printk( "" SYSTEM_NAME_STRING_LOWER
-                ": ERROR: mbuf_allocate_area(epics) failed; ret = %d\n",
-                ret );
-        return -12;
-    }
-    _epics_shm = (unsigned char*)( kmalloc_area[ ret ] );
+    sprintf( fname, "%s", SYSTEM_NAME_STRING_LOWER );
+    ret = mbuf_allocate_area( fname, SHMEM_EPICS_SIZE, (volatile void **)&_epics_shm );
+    if ( ret != MBUF_KERNEL_CODE_OK ) goto attach_shared_memory_error;
+
     // Set pointer to EPICS area
     pLocalEpics = (CDS_EPICS*)&( (RFM_FE_COMMS*)_epics_shm )->epicsSpace;
     pLocalEpics->epicsOutput.fe_status = 0;
 
     /// Allocate TP config memory area
-    ret = mbuf_allocate_area("" SYSTEM_NAME_STRING_LOWER SHMEM_TESTPOINT_SUFFIX, SHMEM_TESTPOINT_SIZE, 0 );
-    if ( ret < 0 )
-    {
-        printk( "" SYSTEM_NAME_STRING_LOWER
-        ": ERROR: mbuf_allocate_area(tp) failed; ret = %d\n",
-            ret );
-        return -12;
-    }
-    // Set pointer to TP area
-    _tp_shm = (volatile TESTPOINT_CFG *)( kmalloc_area[ ret ] );
+    sprintf( fname, "%s", SYSTEM_NAME_STRING_LOWER SHMEM_TESTPOINT_SUFFIX );
+    ret = mbuf_allocate_area(fname, SHMEM_TESTPOINT_SIZE, (volatile void **)&_tp_shm );
+    if ( ret != MBUF_KERNEL_CODE_OK ) goto attach_shared_memory_error;
 
-    /// Allocate AWG data memory area
-    ret = mbuf_allocate_area("" SYSTEM_NAME_STRING_LOWER SHMEM_AWG_SUFFIX, SHMEM_AWG_SIZE, 0 );
-    if ( ret < 0 )
-    {
-        printk( "" SYSTEM_NAME_STRING_LOWER
-                ": ERROR: mbuf_allocate_area(awg) failed; ret = %d\n",
-                ret );
-        return -12;
-    }
-    // Set pointer to AWG area
-    _awg_shm = (volatile AWG_DATA *)( kmalloc_area[ ret ] );
 
-    /// Allocate IPC memory area
-    ret = mbuf_allocate_area( "ipc", 32 * 1024 * 1024, 0 );
-    if ( ret < 0 )
-    {
-        printk( "" SYSTEM_NAME_STRING_LOWER
-                ": ERROR: mbuf_allocate_area(ipc) failed; ret = %d\n",
-                ret );
-        return -12;
-    }
-    _ipc_shm = (unsigned char*)( kmalloc_area[ ret ] );
+    /// Allocate AWG data memory area, and set pointer to AWG area
+    sprintf( fname, "%s", SYSTEM_NAME_STRING_LOWER SHMEM_AWG_SUFFIX);
+    ret = mbuf_allocate_area(fname, SHMEM_AWG_SIZE, (volatile void **)&_awg_shm );
+    if ( ret != MBUF_KERNEL_CODE_OK ) goto attach_shared_memory_error;
+
+
+    /// Allocate IPC memory area, ans assign pointer
+    sprintf( fname, "%s", "ipc");
+    ret = mbuf_allocate_area( fname, SHMEM_IOMEM_SIZE, (volatile void **) &_ipc_shm );
+    if ( ret != MBUF_KERNEL_CODE_OK ) goto attach_shared_memory_error;
 
     // Assign pointer to IOP/USER app comms space
     ioMemData = (IO_MEM_DATA*)( _ipc_shm + 0x4000 );
 
     /// Allocate Shared memory IPC comms memory area
-    ret = mbuf_allocate_area( "shmipc", 16 * 1024 * 1024, 0 );
-    if ( ret < 0 )
-    {
-        printk( "" SYSTEM_NAME_STRING_LOWER
-                ": ERROR: mbuf_allocate_area(shmipc) failed; ret = %d\n",
-                ret );
-        return -12;
-    }
-    _shmipc_shm = (unsigned char*)( kmalloc_area[ ret ] );
+    sprintf( fname, "%s", "shmipc");
+    ret = mbuf_allocate_area( fname, 16 * 1024 * 1024, (volatile void **)&_shmipc_shm );
+    if ( ret != MBUF_KERNEL_CODE_OK ) goto attach_shared_memory_error;
 
     /// Allocate DAQ memory area
     sprintf( fname, "%s_daq", SYSTEM_NAME_STRING_LOWER );
-    ret = mbuf_allocate_area( fname, 64 * 1024 * 1024, 0 );
-    if ( ret < 0 )
-    {
-        printk( "" SYSTEM_NAME_STRING_LOWER
-                ": ERROR:mbuf_allocate_area(daq) failed; ret = %d\n",
-                ret );
-        return -12;
-    }
-    _daq_shm = (unsigned char*)( kmalloc_area[ ret ] );
+    ret = mbuf_allocate_area( fname, 64 * 1024 * 1024, (volatile void **)&_daq_shm );
+    if ( ret != MBUF_KERNEL_CODE_OK ) goto attach_shared_memory_error;
+
     daqPtr = (struct rmIpcStr*)_daq_shm;
 
-    return 0;
+    return 0; //No error return
+
+    attach_shared_memory_error:
+    mbuf_lookup_error_msg(ret, err_msg);
+    printl( SYSTEM_NAME_STRING_LOWER
+            ": ERROR: mbuf_allocate_area(%s) failed - %s ",
+            fname, err_msg );
+    return -12;
+
 }
 
 #ifdef IOP_MODEL
 void
 send_io_info_to_mbuf( int totalcards, CDS_HARDWARE* pCds )
 {
-    int ii, jj, kk;
+    int ii, kk;
 
     // Write IOP data copy rate.  Needed by awgtpman
     ioMemData->mem_data_rate = IOP_IO_RATE;
@@ -246,5 +223,5 @@ send_io_info_to_mbuf( int totalcards, CDS_HARDWARE* pCds )
     ioMemData->dolphinWrite[ 1 ] = 0;
 #endif
 }
-#endif
-#endif
+#endif //IOP_MODEL
+#endif //ndef USER_SPACE
diff --git a/src/fe/moduleLoadCommon.h b/src/fe/moduleLoadCommon.h
new file mode 100644
index 0000000000000000000000000000000000000000..cd59a534367714343c4784995b0fe2a739cc62cc
--- /dev/null
+++ b/src/fe/moduleLoadCommon.h
@@ -0,0 +1,25 @@
+#ifndef LIGO_MODULELOADCOMMON_H
+#define LIGO_MODULELOADCOMMON_H
+
+#include "drv/cdsHardware.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void print_exit_messages( int error_type, int error_sub, const char* sysname );
+
+#ifndef USER_SPACE
+int detach_shared_memory( void );
+int attach_shared_memory( void );
+#ifdef IOP_MODEL
+void send_io_info_to_mbuf( int totalcards, CDS_HARDWARE* pCds );
+#endif //IOP_MODEL
+#endif //USER_SPACE
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_MODULELOADCOMMON_H
diff --git a/src/fe/print_io_info.c b/src/fe/print_io_info.c
index d6f323455100af3043da9e9563f830159c579644..9ddb5c1d03ccd2aa3f2b42c91cc09516a0fb4065 100644
--- a/src/fe/print_io_info.c
+++ b/src/fe/print_io_info.c
@@ -1,144 +1,149 @@
 /// @file print_io_info.c
 /// @brief File contains routine to print IO info on code startup.
 
-void print_io_info( CDS_HARDWARE*, int );
+#include "print_io_info.h"
+#include "controller.h" //_epics_shm, _tp_shm, _awg_shm, _ipc_shm
+
+#ifndef USER_SPACE
+#include "../fe/timing_kernel.h" //current_time_fe
+#endif
+#include "util/printl.h"
 
 void
-print_io_info( CDS_HARDWARE* cdsp, int iopmodel )
+print_io_info(const char* model_name, CDS_HARDWARE* cdsp, int iopmodel )
 {
     int ii, jj, kk;
     int channels = 0;
     jj = 0;
 
 #ifndef USER_SPACE
-    printf( "" SYSTEM_NAME_STRING_LOWER ":startup time is %ld\n",
-            current_time_fe( ) );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":cpu clock %u\n", cpu_khz );
+    printl( "%s:startup time is %ld\n",
+            model_name, current_time_fe( ) );
+    printl( "%s:cpu clock %u\n", model_name, cpu_khz );
 #endif
-    printf( "" SYSTEM_NAME_STRING_LOWER ":EPICSM at 0x%lx\n",
-            (unsigned long)_epics_shm );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":TPSM at 0x%lx\n",
-            (unsigned long)_tp_shm );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":AWGSM at 0x%lx\n",
-            (unsigned long)_awg_shm );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":IPC    at 0x%lx\n",
-            (unsigned long)_ipc_shm );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":IOMEM  at 0x%lx size 0x%lx\n",
-            ( (unsigned long)_ipc_shm + 0x4000 ),
+    printl( "%s:EPICSM at %p\n",
+            model_name, _epics_shm );
+    printl( "%s:TPSM at %p\n",
+            model_name, _tp_shm );
+    printl( "%s:AWGSM at %p\n",
+            model_name, _awg_shm );
+    printl( "%s:IPC    at %p\n",
+            model_name, _ipc_shm );
+    printl( "%s:IOMEM  at 0x%lx size 0x%lx\n",
+            model_name, ( (unsigned long)_ipc_shm + 0x4000 ),
             sizeof( IO_MEM_DATA ) );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":DAQSM at 0x%lx\n",
-            (unsigned long)_daq_shm );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":configured to use %d cards\n",
-            cdsp->cards );
+    printl( "%s:DAQSM at %p\n",
+            model_name, _daq_shm );
+    printl( "%s:configured to use %d cards\n",
+            model_name, cdsp->cards );
     kk = 0;
-    printf( "******************************************************************"
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d ADC cards found\n",
-            cdsp->adcCount );
+    printl( "%s:%d ADC cards found\n",
+            model_name, cdsp->adcCount );
     for ( ii = 0; ii < cdsp->adcCount; ii++ )
     {
         kk++;
-        printf( "" SYSTEM_NAME_STRING_LOWER ":\tADC %d is a %s module\n",
-                ii,
+        printl( "%s:\tADC %d is a %s module\n",
+                model_name, ii,
                 _cdscardtypename[ cdsp->adcType[ ii ] ] );
         if ( iopmodel )
         {
-            printf( "" SYSTEM_NAME_STRING_LOWER ":\t\tChannels = %d \n",
-                    cdsp->adcChannels[ ii ] );
-            printf( "" SYSTEM_NAME_STRING_LOWER ":\t\tFirmware Rev = %d \n\n",
+            printl( "%s:\t\tChannels = %d \n",
+                    model_name, cdsp->adcChannels[ ii ] );
+            printl( "%s:\t\tFirmware Rev = %d \n\n",
+                    model_name, 
                     ( cdsp->adcConfig[ ii ] & 0xfff ) );
         }
         else
         {
-            printf( "" SYSTEM_NAME_STRING_LOWER ":\tMemory at block %d\n",
-                    cdsp->adcConfig[ ii ] );
+            printl( "%s:\tMemory at block %d\n",
+                    model_name, cdsp->adcConfig[ ii ] );
         }
     }
-    printf( "******************************************************************"
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d DAC cards found\n",
-            cdsp->dacCount );
+    printl( "%s:%d DAC cards found\n",
+            model_name, cdsp->dacCount );
     for ( ii = 0; ii < cdsp->dacCount; ii++ )
     {
         kk++;
-        printf( "" SYSTEM_NAME_STRING_LOWER ":\tDAC %d is a %s module\n",
-                ii,
+        printl( "%s:\tDAC %d is a %s module\n",
+                model_name, ii,
                 _cdscardtypename[ cdsp->dacType[ ii ] ] );
-        printf( "" SYSTEM_NAME_STRING_LOWER ":\tCard number is %d\n",
-                cdsp->dacInstance[ ii ] );
-        printf( "" SYSTEM_NAME_STRING_LOWER ":\tMemory at block %d\n",
-                cdsp->dacConfig[ ii ] );
+        printl( "%s:\tCard number is %d\n",
+                model_name, cdsp->dacInstance[ ii ] );
+        printl( "%s:\tMemory at block %d\n",
+                model_name, cdsp->dacConfig[ ii ] );
         if ( iopmodel )
         {
             if ( cdsp->dacType[ ii ] == GSC_16AO16 )
                 channels = 16;
             else
                 channels = 8;
-            printf( "" SYSTEM_NAME_STRING_LOWER ":\tChannels = %d \n",
-                    channels );
-            printf( "" SYSTEM_NAME_STRING_LOWER ":\tFirmware Rev = %d \n\n",
-                    ( cdsp->dacAcr[ ii ] & 0xfff ) );
+            printl( "%s:\tChannels = %d \n",
+                    model_name, channels );
+            printl( "%s:\tFirmware Rev = %d \n\n",
+                    model_name, ( cdsp->dacAcr[ ii ] & 0xfff ) );
         }
     }
     kk += cdsp->doCount;
-    printf( "******************************************************************"
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d DIO cards found\n",
-            cdsp->dioCount );
-    printf( "******************************************************************"
+    printl( "%s:%d DIO cards found\n",
+            model_name, cdsp->dioCount );
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d IIRO-8 Isolated DIO cards found\n",
-            cdsp->card_count[ ACS_8DIO ] );
-    printf( "******************************************************************"
+    printl( "%s:%d IIRO-8 Isolated DIO cards found\n",
+            model_name, cdsp->card_count[ ACS_8DIO ] );
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "" SYSTEM_NAME_STRING_LOWER
-            ":%d IIRO-16 Isolated DIO cards found\n",
-            cdsp->card_count[ ACS_16DIO ] );
-    printf( "******************************************************************"
+    printl( "%s:%d IIRO-16 Isolated DIO cards found\n",
+            model_name, cdsp->card_count[ ACS_16DIO ] );
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d Contec 32ch PCIe DO cards found\n",
-            cdsp->card_count[ CON_32DO ] );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d Contec PCIe DIO1616 cards found\n",
-            cdsp->card_count[ CON_1616DIO ] );
+    printl( "%s:%d Contec 32ch PCIe DO cards found\n",
+            model_name, cdsp->card_count[ CON_32DO ] );
+    printl( "%s:%d Contec PCIe DIO1616 cards found\n",
+            model_name, cdsp->card_count[ CON_1616DIO ] );
     pLocalEpics->epicsOutput.bioMon[ 2 ] = cdsp->card_count[ CON_1616DIO ];
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d Contec PCIe DIO6464 cards found\n",
-            cdsp->card_count[ CON_6464DIO ] );
+    printl( "%s:%d Contec PCIe DIO6464 cards found\n",
+            model_name, cdsp->card_count[ CON_6464DIO ] );
     pLocalEpics->epicsOutput.bioMon[ 3 ] = cdsp->card_count[ CON_6464DIO ];
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d Contec PCIe CDO64 cards found\n",
-            cdsp->card_count[ CDO64 ] );
+    printl( "%s:%d Contec PCIe CDO64 cards found\n",
+            model_name, cdsp->card_count[ CDO64 ] );
     pLocalEpics->epicsOutput.bioMon[ 1 ] = cdsp->card_count[ CDO64 ];
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d Contec PCIe CDI64 cards found\n",
-            cdsp->card_count[ CDI64 ] );
+    printl( "%s:%d Contec PCIe CDI64 cards found\n",
+            model_name, cdsp->card_count[ CDI64 ] );
     pLocalEpics->epicsOutput.bioMon[ 0 ] = cdsp->card_count[ CDI64 ];
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d DO cards found\n", cdsp->doCount );
-    printf( "" SYSTEM_NAME_STRING_LOWER
-            ":Total of %d I/O modules found and mapped\n",
-            kk );
-    printf( "******************************************************************"
+    printl( "%s:%d DO cards found\n", model_name, cdsp->doCount );
+    printl( "%s:Total of %d I/O modules found and mapped\n",
+            model_name, kk );
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "" SYSTEM_NAME_STRING_LOWER ":%d RFM cards found\n",
-            cdsp->rfmCount );
+    printl( "%s:%d RFM cards found\n",
+            model_name, cdsp->rfmCount );
     for ( ii = 0; ii < cdsp->rfmCount; ii++ )
     {
-        printf( "\tRFM %d is a VMIC_%x module with Node ID %d\n",
+        printl( "\tRFM %d is a VMIC_%x module with Node ID %d\n",
                 ii,
                 cdsp->rfmType[ ii ],
                 cdsp->rfmConfig[ ii ] );
-        printf( "address is 0x%lx\n", cdsp->pci_rfm[ ii ] );
+        printl( "address is 0x%lx\n", cdsp->pci_rfm[ ii ] );
     }
-    printf( "******************************************************************"
+    printl( "******************************************************************"
             "*********\n" );
     if ( cdsp->gps )
     {
-        printf( "" SYSTEM_NAME_STRING_LOWER ":IRIG-B card found %d\n",
-                cdsp->gpsType );
-        printf( "**************************************************************"
+        printl( "%s:IRIG-B card found %d\n",
+                model_name, cdsp->gpsType );
+        printl( "**************************************************************"
                 "*************\n" );
     }
     for ( ii = 0; ii < cdsp->dolphinCount; ii++ )
     {
-        printf( "\tDolphin found %d\n", ii );
-        printf( "Read address is 0x%lx\n", cdsp->dolphinRead[ ii ] );
-        printf( "Write address is 0x%lx\n", cdsp->dolphinWrite[ ii ] );
+        printl( "\tDolphin found %d\n", ii );
+        printl( "Read address is %p\n", cdsp->dolphinRead[ ii ] );
+        printl( "Write address is %p\n", cdsp->dolphinWrite[ ii ] );
     }
 }
diff --git a/src/fe/print_io_info.h b/src/fe/print_io_info.h
new file mode 100644
index 0000000000000000000000000000000000000000..883fdaf150aa0b4563cc16280cbef2449cfc8b5e
--- /dev/null
+++ b/src/fe/print_io_info.h
@@ -0,0 +1,20 @@
+/// @file print_io_info.h
+/// @brief File contains routine to print IO info on code startup.
+#ifndef LIGO_PRINT_IO_INFO_H
+#define LIGO_PRINT_IO_INFO_H
+
+#include "drv/cdsHardware.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void print_io_info(const char* model_name, CDS_HARDWARE* cdsp, int iopmodel );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif //LIGO_PRINT_IO_INFO_H
diff --git a/src/fe/rcguser.c b/src/fe/rcguser.c
index ecf8e3c6e5f6ef2cd3ce53d7e2d86fa8f93f30ec..b25d8594a514ab72d01afb2e926a21faf5ce51b6 100644
--- a/src/fe/rcguser.c
+++ b/src/fe/rcguser.c
@@ -23,12 +23,15 @@
 #include <signal.h>
 #include <stdbool.h>
 
-#include "rcguserCommon.c"
-#include "mapApp.c"
+#include "rcguserCommon.h"
+#include "mapApp.h"
+#include "controller.h"
+#include "feComms.h"
+#include "print_io_info.h"
+#include "util/printl.h"
 
 // These externs and "16" need to go to a header file (mbuf.h)
 extern int   fe_start_app_user( );
-extern char  daqArea[ DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers
 
 /// Startup function for initialization of user space module.
 int
@@ -72,11 +75,11 @@ main( int argc, char** argv )
     // ******************************************************* Following I/O
     // card info is from feCode
     cards = sizeof( cards_used ) / sizeof( cards_used[ 0 ] );
-    printf( "configured to use %d cards\n", cards );
+    printl( "configured to use %d cards\n", cards );
     cdsPciModules.cards = cards;
     cdsPciModules.cards_used = cards_used;
     // return -1;
-    printf( "Initializing PCI Modules\n" );
+    printl( "Initializing PCI Modules\n" );
     cdsPciModules.adcCount = 0;
     cdsPciModules.dacCount = 0;
     cdsPciModules.dioCount = 0;
@@ -86,7 +89,7 @@ main( int argc, char** argv )
 
     // If running as a control process, I/O card information is via ipc shared
     // memory
-    printf( "%d PCI cards found\n", ioMemData->totalCards );
+    printl( "%d PCI cards found\n", ioMemData->totalCards );
 
     initmap( &cdsPciModules );
     /// Call PCI initialization routine in map.c file.
@@ -95,13 +98,13 @@ main( int argc, char** argv )
     // If no ADC cards were found, then control cannot run
     if ( !cdsPciModules.adcCount )
     {
-        printf( "No ADC cards found - exiting\n" );
+        printl( "No ADC cards found - exiting\n" );
         return -1;
     }
-    printf( "%d PCI cards found \n", status );
+    printl( "%d PCI cards found \n", status );
     if ( status < cards )
     {
-        printf( " ERROR **** Did not find correct number of cards! Expected %d "
+        printl( " ERROR **** Did not find correct number of cards! Expected %d "
                 "and Found %d\n",
                 cards,
                 status );
@@ -118,15 +121,15 @@ main( int argc, char** argv )
     }
 #endif
     // Print out all the I/O information
-    print_io_info( &cdsPciModules, 0 );
+    print_io_info(SYSTEM_NAME_STRING_LOWER, &cdsPciModules, 0 );
 
     // Initialize buffer for daqLib.c code
-    printf( "Initializing space for daqLib buffers\n" );
+    printl( "Initializing space for daqLib buffers\n" );
     daqBuffer = (long)&daqArea[ 0 ];
 
     for ( cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++ )
     {
-        printf( "Epics burt restore is %d\n",
+        printl( "Epics burt restore is %d\n",
                 pLocalEpics->epicsInput.burtRestore );
         usleep( 1000000 );
     }
diff --git a/src/fe/rcguserCommon.c b/src/fe/rcguserCommon.c
index 0aeaefe6de38b9d2fee5504e695cc60804a2b890..d02fdf309b4006362cf4498079281f70a2e89e86 100644
--- a/src/fe/rcguserCommon.c
+++ b/src/fe/rcguserCommon.c
@@ -1,19 +1,27 @@
 /// @file rcguserCommon.c
 /// @brief File contains routines for user app startup
 
-#include "print_io_info.c"
+#include "print_io_info.h"
+#include "controller.h"
+#include "findSharedMemory.h"
+#include "util/printl.h"
+
+#include <stddef.h>
+#include <stdio.h>
 
 // **********************************************************************************************
 // Capture SIGHALT from ControlC
 void
-intHandler( int dummy )
+intHandler( int signal)
 {
+    (void) signal;
     pLocalEpics->epicsInput.vmeReset = 1;
+    printl( "Received exit signal, exiting...\n" );
 }
 
 // **********************************************************************************************
 
-void
+int
 attach_shared_memory( char* sysname )
 {
 
@@ -21,63 +29,62 @@ attach_shared_memory( char* sysname )
 
     // epics shm used to communicate with model's EPICS process
     sprintf( shm_name, "%s", sysname );
-    _epics_shm = (char*) findSharedMemory( sysname );
+    _epics_shm = (volatile char*) findSharedMemory( sysname );
     if ( _epics_shm == NULL )
     {
-        printf( "mbuf_allocate_area() failed; ret = %d\n", _epics_shm );
+        printl( "mbuf_allocate_area() failed; ret = %p\n", _epics_shm );
         return -1;
     }
-    printf( "EPICSM at 0x%lx\n", (long)_epics_shm );
+    printl( "EPICSM at %p\n", _epics_shm );
 
     // testpoint config shm used to control testpoints from awgtpman
     sprintf( shm_name, "%s%s", sysname, SHMEM_TESTPOINT_SUFFIX );
     _tp_shm = (volatile TESTPOINT_CFG *) findSharedMemory( sysname );
     if ( _tp_shm == NULL )
     {
-        printf( "mbuf_allocate_area(tp) failed; ret = %d\n", _tp_shm );
+        printl( "mbuf_allocate_area(tp) failed; ret = %p\n", _tp_shm );
         return -1;
     }
-    printf( "TPSM at 0x%lx\n", (long)_tp_shm );
+    printl( "TPSM at %p\n", _tp_shm );
     
     // awg data shm used to stream data from awgtpman
     sprintf( shm_name, "%s%s", sysname, SHMEM_AWG_SUFFIX );
     _awg_shm = (volatile AWG_DATA *) findSharedMemory( sysname );
     if ( _awg_shm == NULL )
     {
-        printf( "mbuf_allocate_area(awg) failed; ret = %d\n", _awg_shm );
+        printl( "mbuf_allocate_area(awg) failed; ret = %p\n", _awg_shm );
         return -1;
     }
-    printf( "AWGSM at 0x%lx\n", (long)_awg_shm );
+    printl( "AWGSM at %p\n", _awg_shm );
     
     // ipc_shm used to communicate with IOP
     _ipc_shm = (char*)findSharedMemory( "ipc" );
     if ( _ipc_shm == NULL )
     {
-        printf( "mbuf_allocate_area(ipc) failed; ret = %d\n", _ipc_shm );
+        printl( "mbuf_allocate_area(ipc) failed; ret = %p\n", _ipc_shm );
         return -1;
     }
-    printf( "IPC    at 0x%lx\n", (long)_ipc_shm );
+    printl( "IPC    at %p\n", _ipc_shm );
     ioMemData = (volatile IO_MEM_DATA*)( ( (char*)_ipc_shm ) + 0x4000 );
-    printf(
-        "IOMEM  at 0x%lx size 0x%x\n", (long)ioMemData, sizeof( IO_MEM_DATA ) );
-    printf( "%d PCI cards found\n", ioMemData->totalCards );
+    printl("IOMEM  at %p size 0x%lx\n", ioMemData, sizeof( IO_MEM_DATA ) );
+    printl( "%d PCI cards found\n", ioMemData->totalCards );
 
     // DAQ is via shared memory
     sprintf( shm_name, "%s_daq", sysname );
     _daq_shm = (char*) findSharedMemory( shm_name );
     if ( _daq_shm == NULL )
     {
-        printf( "mbuf_allocate_area() failed; ret = %d\n", _daq_shm );
+        printl( "mbuf_allocate_area() failed; ret = %p\n", _daq_shm );
         return -1;
     }
-    printf( "DAQSM at 0x%lx\n", _daq_shm );
+    printl( "DAQSM at %p\n", _daq_shm );
     daqPtr = (struct rmIpcStr*)_daq_shm;
 
     // shmipc is used to send SHMEM IPC data between processes on same computer
     _shmipc_shm = (char*) findSharedMemory( "shmipc" );
     if ( _shmipc_shm == NULL )
     {
-        printf( "mbuf_allocate_area() failed; ret = %d\n", _shmipc_shm );
+        printl( "mbuf_allocate_area() failed; ret = %p\n", _shmipc_shm );
         return -1;
     }
 
@@ -85,9 +92,11 @@ attach_shared_memory( char* sysname )
     _io_shm = (char*) findSharedMemory( "virtual_io_space" );
     if ( _io_shm == NULL )
     {
-        printf( "mbuf_allocate_area() failed; ret = %d\n", _io_shm );
+        printl( "mbuf_allocate_area() failed; ret = %p\n", _io_shm );
         return -1;
     }
     ioMemDataIop = (volatile IO_MEM_DATA_IOP*)( ( (char*)_io_shm ) );
+
+    return 0;
 }
 
diff --git a/src/fe/rcguserCommon.h b/src/fe/rcguserCommon.h
new file mode 100644
index 0000000000000000000000000000000000000000..a96b62aa093bf0852db792f3893e4c914e9813d4
--- /dev/null
+++ b/src/fe/rcguserCommon.h
@@ -0,0 +1,16 @@
+#ifndef LIGO_RCG_COMMON_H
+#define LIGO_RCG_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void intHandler( int dummy );
+int attach_shared_memory( char* sysname );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_RCG_COMMON_H
diff --git a/src/fe/rcguserIop.c b/src/fe/rcguserIop.c
index 84913bc10619c38e15b159729f2c560a4b0d713c..fa8e1345893a3fec6cd9829ae28f1109214b4897 100644
--- a/src/fe/rcguserIop.c
+++ b/src/fe/rcguserIop.c
@@ -17,12 +17,17 @@
 #include <string.h>
 #include <signal.h>
 
-#include "rcguserCommon.c"
+#include "rcguserCommon.h"
+#include "controllerko.h" //tdsControl, tdsCount, etc
+#include "findSharedMemory.h"
+#include "controller.h" //daqArea
+#include "feComms.h" //RFM_FE_COMMS
+#include "util/printl.h"
+#include "../fe/print_io_info.h"
+
 
 // These externs and "16" need to go to a header file (mbuf.h)
 extern int   fe_start_iop_user( );
-extern char  daqArea[ DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers
-extern int   cycleOffset;
 
 // Scan a double
 #if 0
@@ -77,7 +82,6 @@ main( int argc, char** argv )
     int   c;
     char* modelname;
 
-    cycleOffset = 0;
 
 #if 0
     while ( ( c = getopt( argc, argv, "m:t:help" ) ) != EOF )
@@ -85,11 +89,11 @@ main( int argc, char** argv )
         {
         case 'm':
             sysname = optarg;
-            printf( "sysname = %s\n", sysname );
+            printl( "sysname = %s\n", sysname );
             break;
         case 't':
             cycleOffset = atoi( optarg );
-            printf( "cycle offset = %d\n", cycleOffset );
+            printl( "cycle offset = %d\n", cycleOffset );
             break;
         case 'help':
         default:
@@ -109,13 +113,13 @@ main( int argc, char** argv )
     // ******************************************************* Following I/O
     // card info is from feCode
     cards = sizeof( cards_used ) / sizeof( cards_used[ 0 ] );
-    printf( "configured to use %d cards\n", cards );
+    printl( "configured to use %d cards\n", cards );
     cdsPciModules.cards = cards;
     cdsPciModules.cards_used = cards_used;
     // return -1;
-    printf( "Initializing PCI Modules for IOP\n" );
+    printl( "Initializing PCI Modules for IOP\n" );
     for ( jj = 0; jj < cards; jj++ )
-        printf(
+        printl(
             "Card %d type = %d\n", jj, cdsPciModules.cards_used[ jj ].type );
     cdsPciModules.adcCount = 0;
     cdsPciModules.dacCount = 0;
@@ -126,7 +130,7 @@ main( int argc, char** argv )
 
     // If running as a control process, I/O card information is via ipc shared
     // memory
-    printf( "%d PCI cards found\n", cards );
+    printl( "%d PCI cards found\n", cards );
     status = 0;
 
     ioMemData->totalCards = cards;
@@ -136,7 +140,7 @@ main( int argc, char** argv )
     for ( jj = 0; jj < cards; jj++ )
     {
         /*
-        printf("Model %d = %d, type = %d, instance = %d, dacCnt = %d \n",
+        printl("Model %d = %d, type = %d, instance = %d, dacCnt = %d \n",
                 ii,ioMemData->model[ii],
                 cdsPciModules.cards_used[jj].type,
                 cdsPciModules.cards_used[jj].instance,
@@ -204,17 +208,17 @@ main( int argc, char** argv )
     // If no ADC cards were found, then control models cannot run
     if ( !cdsPciModules.adcCount )
     {
-        printf( "No ADC cards found - exiting\n" );
+        printl( "No ADC cards found - exiting\n" );
         return -1;
     }
     // This did not quite work for some reason
     // Need to find a way to handle skipped DAC cards in controllers
     // cdsPciModules.dacCount = ioMemData->dacCount;
 
-    printf( "%d PCI cards found \n", status );
+    printl( "%d PCI cards found \n", status );
     if ( status < cards )
     {
-        printf( " ERROR **** Did not find correct number of cards! Expected %d "
+        printl( " ERROR **** Did not find correct number of cards! Expected %d "
                 "and Found %d\n",
                 cards,
                 status );
@@ -222,7 +226,7 @@ main( int argc, char** argv )
     }
 
     // Print out all the I/O information
-    printf( "******************************************************************"
+    printl( "******************************************************************"
             "*********\n" );
     // Master send module counds to control models via ipc shm
     ioMemData->totalCards = status;
@@ -231,7 +235,7 @@ main( int argc, char** argv )
     ioMemData->bioCount = cdsPciModules.doCount;
     // kk will act as ioMem location counter for mapping modules
     kk = cdsPciModules.adcCount;
-    printf( "%d ADC cards found\n", cdsPciModules.adcCount );
+    printl( "%d ADC cards found\n", cdsPciModules.adcCount );
     for ( ii = 0; ii < cdsPciModules.adcCount; ii++ )
     {
         // MASTER maps ADC modules first in ipc shm for control models
@@ -250,52 +254,52 @@ main( int argc, char** argv )
         }
         if ( cdsPciModules.adcType[ ii ] == GSC_16AI64SSA )
         {
-            printf( "\tADC %d is a GSC_16AI64SSA module\n", ii );
+            printl( "\tADC %d is a GSC_16AI64SSA module\n", ii );
             if ( ( cdsPciModules.adcConfig[ ii ] & 0x10000 ) > 0 )
                 jj = 32;
             else
                 jj = 64;
-            printf( "\t\tChannels = %d \n", jj );
-            printf( "\t\tFirmware Rev = %d \n\n",
+            printl( "\t\tChannels = %d \n", jj );
+            printl( "\t\tFirmware Rev = %d \n\n",
                     ( cdsPciModules.adcConfig[ ii ] & 0xfff ) );
         }
     }
-    printf( "******************************************************************"
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "%d DAC cards found\n", cdsPciModules.dacCount );
+    printl( "%d DAC cards found\n", cdsPciModules.dacCount );
     for ( ii = 0; ii < cdsPciModules.dacCount; ii++ )
     {
         if ( cdsPciModules.dacType[ ii ] == GSC_18AO8 )
         {
-            printf( "\tDAC %d is a GSC_18AO8 module\n", ii );
+            printl( "\tDAC %d is a GSC_18AO8 module\n", ii );
         }
         if ( cdsPciModules.dacType[ ii ] == GSC_16AO16 )
         {
-            printf( "\tDAC %d is a GSC_16AO16 module\n", ii );
+            printl( "\tDAC %d is a GSC_16AO16 module\n", ii );
             if ( ( cdsPciModules.dacConfig[ ii ] & 0x10000 ) == 0x10000 )
                 jj = 8;
             if ( ( cdsPciModules.dacConfig[ ii ] & 0x20000 ) == 0x20000 )
                 jj = 12;
             if ( ( cdsPciModules.dacConfig[ ii ] & 0x30000 ) == 0x30000 )
                 jj = 16;
-            printf( "\t\tChannels = %d \n", jj );
+            printl( "\t\tChannels = %d \n", jj );
             if ( ( cdsPciModules.dacConfig[ ii ] & 0xC0000 ) == 0x0000 )
             {
-                printf( "\t\tFilters = None\n" );
+                printl( "\t\tFilters = None\n" );
             }
             if ( ( cdsPciModules.dacConfig[ ii ] & 0xC0000 ) == 0x40000 )
             {
-                printf( "\t\tFilters = 10kHz\n" );
+                printl( "\t\tFilters = 10kHz\n" );
             }
             if ( ( cdsPciModules.dacConfig[ ii ] & 0xC0000 ) == 0x80000 )
             {
-                printf( "\t\tFilters = 100kHz\n" );
+                printl( "\t\tFilters = 100kHz\n" );
             }
             if ( ( cdsPciModules.dacConfig[ ii ] & 0x100000 ) == 0x100000 )
             {
-                printf( "\t\tOutput Type = Differential\n" );
+                printl( "\t\tOutput Type = Differential\n" );
             }
-            printf( "\t\tFirmware Rev = %d \n\n",
+            printl( "\t\tFirmware Rev = %d \n\n",
                     ( cdsPciModules.dacConfig[ ii ] & 0xfff ) );
         }
         // Pass DAC info to control processes
@@ -304,28 +308,28 @@ main( int argc, char** argv )
         // Following used by IOP to point to ipc memory for inputting DAC
         // data from control models
         cdsPciModules.dacConfig[ ii ] = kk;
-        printf( "MASTER DAC SLOT %d %d\n", ii, cdsPciModules.dacConfig[ ii ] );
+        printl( "MASTER DAC SLOT %d %d\n", ii, cdsPciModules.dacConfig[ ii ] );
         kk++;
     }
-    printf( "******************************************************************"
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "%d DIO cards found\n", cdsPciModules.dioCount );
-    printf( "******************************************************************"
+    printl( "%d DIO cards found\n", cdsPciModules.dioCount );
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "%d IIRO-8 Isolated DIO cards found\n",
+    printl( "%d IIRO-8 Isolated DIO cards found\n",
             cdsPciModules.card_count[ ACS_8DIO ] );
-    printf( "******************************************************************"
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "%d IIRO-16 Isolated DIO cards found\n",
+    printl( "%d IIRO-16 Isolated DIO cards found\n",
             cdsPciModules.card_count[ ACS_16DIO ] );
-    printf( "******************************************************************"
+    printl( "******************************************************************"
             "*********\n" );
-    printf( "%d Contec 32ch PCIe DO cards found\n", cdsPciModules.card_count[ CON_32DO ] );
-    printf( "%d Contec PCIe DIO1616 cards found\n",
+    printl( "%d Contec 32ch PCIe DO cards found\n", cdsPciModules.card_count[ CON_32DO ] );
+    printl( "%d Contec PCIe DIO1616 cards found\n",
             cdsPciModules.card_count[ CON_1616DIO ] );
-    printf( "%d Contec PCIe DIO6464 cards found\n",
+    printl( "%d Contec PCIe DIO6464 cards found\n",
             cdsPciModules.card_count[ CON_6464DIO ] );
-    printf( "%d DO cards found\n", cdsPciModules.doCount );
+    printl( "%d DO cards found\n", cdsPciModules.doCount );
     // IOP sends DIO module information to control models
     // Note that for DIO, control modules will perform the I/O directly and
     // therefore need to know the PCIe address of these modules.
@@ -336,7 +340,7 @@ main( int argc, char** argv )
         if ( cdsPciModules.doType[ ii ] == CON_1616DIO )
         {
             tdsControl[ tdsCount ] = ii;
-            printf( "TDS controller %d is at %d\n", tdsCount, ii );
+            printl( "TDS controller %d is at %d\n", tdsCount, ii );
             tdsCount++;
         }
         ioMemData->model[ kk ] = cdsPciModules.doType[ ii ];
@@ -345,10 +349,10 @@ main( int argc, char** argv )
         ioMemData->ipc[ kk ] = kk;
         kk++;
     }
-    printf( "Total of %d I/O modules found and mapped\n", kk );
-    printf( "******************************************************************"
+    printl( "Total of %d I/O modules found and mapped\n", kk );
+    printl( "******************************************************************"
             "*********\n" );
-    print_io_info(&cdsPciModules,1);
+    print_io_info(SYSTEM_NAME_STRING_LOWER, &cdsPciModules, 1);
     // Following section maps Reflected Memory, both VMIC hardware style and
     // Dolphin PCIe network style. Control units will perform I/O transactions
     // with RFM directly ie IOP does not do RFM I/O. Master unit only maps
@@ -368,13 +372,13 @@ main( int argc, char** argv )
 #endif
 
     // Initialize buffer for daqLib.c code
-    printf( "Initializing space for daqLib buffers\n" );
+    printl( "Initializing space for daqLib buffers\n" );
     daqBuffer = (long)&daqArea[ 0 ];
 
     // Wait for SDF restore
     for ( cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++ )
     {
-        printf( "Epics burt restore is %d\n",
+        printl( "Epics burt restore is %d\n",
                 pLocalEpics->epicsInput.burtRestore );
         usleep( 1000000 );
     }
diff --git a/src/fe/sync21pps.c b/src/fe/sync21pps.c
index 3430de99594b049c66ff61630066573f6c57379e..d6f70230b22906b5f13f37d9e3e372a236281b23 100644
--- a/src/fe/sync21pps.c
+++ b/src/fe/sync21pps.c
@@ -1,3 +1,13 @@
+
+#include "../fe/sync21pps.h"
+
+#include "controller.h"
+#include "drv/gsc_adc_common.h" //GSAI_ALL_CARDS
+#include "drv/gsc_dac_common.h" //DAC_CLK_ENABLE
+#include "../fe/timing_kernel.h" //current_nanosecond
+#include "drv/plx_9056.h"
+#include "drv/iop_adc_functions.h"
+
 // Code to synch FE startup with 1PPS signal on last channel
 // of first ADC module.
 // Clocks are already running, so can't enable all ADC cards
@@ -10,7 +20,6 @@ int
 sync2pps_signal( one_pps_sync_t* p1pps, adcInfo_t* padcinfo, int cpuClock[] )
 {
     int           status;
-    int           onePps;
     int           pps_wait = 0;
     int           sync = SYNC_SRC_1PPS;
     unsigned long nanotime = 100000;
@@ -68,7 +77,6 @@ sync2pps_signal( one_pps_sync_t* p1pps, adcInfo_t* padcinfo, int cpuClock[] )
 int
 sync21pps_check( one_pps_sync_t* p1pps, adcInfo_t* padcinfo )
 {
-    // Assign chan 32 to onePps
     p1pps->value = adcinfo.adcData[ ADC_ONEPPS_BRD ][ ADC_DUOTONE_CHAN ];
     if ( ( p1pps->value > ONE_PPS_THRESH ) && ( p1pps->signalHi == 0 ) )
     {
@@ -77,4 +85,5 @@ sync21pps_check( one_pps_sync_t* p1pps, adcInfo_t* padcinfo )
     }
     if ( p1pps->value < ONE_PPS_THRESH )
         p1pps->signalHi = 0;
+    return 0;
 }
diff --git a/src/fe/sync21pps.h b/src/fe/sync21pps.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ab899ea3df81bccbc317fb65cf455c10530e223
--- /dev/null
+++ b/src/fe/sync21pps.h
@@ -0,0 +1,21 @@
+#ifndef LIGO_SYNC21PPS_H
+#define LIGO_SYNC21PPS_H
+
+#include "cds_types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int sync2pps_signal( one_pps_sync_t* p1pps, adcInfo_t* padcinfo, int cpuClock[] );
+
+int sync21pps_check( one_pps_sync_t* p1pps, adcInfo_t* padcinfo );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // LIGO_SYNC21PPS_H
diff --git a/src/fe/timing_common.h b/src/fe/timing_common.h
index 3fadee3b62d447585d0a4ad9762f35b30f01170d..8dbf6f511b02886733f576c6fd08fc9a666dc741 100644
--- a/src/fe/timing_common.h
+++ b/src/fe/timing_common.h
@@ -1,13 +1,16 @@
-
 #ifndef LIGO_TIMING_COMMON_H
 #define LIGO_TIMING_COMMON_H
 
+#include "portableInline.h"
+#include "cds_types.h"
+
 //***********************************************************************
 /// \brief Calculate ADC/DAC duotone offset for diagnostics. \n
 ///< Code should only run on IOP
 //***********************************************************************
 #ifdef IOP_MODEL
-inline float
+
+LIGO_INLINE float
 duotime( int count, float meanVal, float data[] )
 {
     float x, y, sumX, sumY, sumXX, sumXY, msumX;
@@ -48,7 +51,8 @@ duotime( int count, float meanVal, float data[] )
     answer = meanVal / slope - 91.552;
     return ( answer );
 }
-inline void
+
+LIGO_INLINE void
 initializeDuotoneDiags( duotone_diag_t* dt_diag )
 {
     int ii;
@@ -65,7 +69,7 @@ initializeDuotoneDiags( duotone_diag_t* dt_diag )
 }
 #endif
 
-inline void
+LIGO_INLINE void
 initializeTimingDiags( timing_diag_t* timeinfo )
 {
     timeinfo->cpuTimeEverMax = 0;
@@ -79,7 +83,8 @@ initializeTimingDiags( timing_diag_t* timeinfo )
     timeinfo->usrTime = 0;
     timeinfo->cycleTime = 0;
 }
-inline void
+
+LIGO_INLINE void
 sendTimingDiags2Epics( volatile CDS_EPICS* pLocalEpics,
                        timing_diag_t*      timeinfo,
                        adcInfo_t*          adcinfo )
@@ -106,7 +111,8 @@ sendTimingDiags2Epics( volatile CDS_EPICS* pLocalEpics,
     adcinfo->adcHoldTimeMin = 0xffff;
     adcinfo->adcHoldTimeAvg = 0;
 }
-inline void
+
+LIGO_INLINE void
 captureEocTiming( int            cycle,
                   unsigned int   cycle_gps,
                   timing_diag_t* timeinfo,
diff --git a/src/fe/timing_kernel.h b/src/fe/timing_kernel.h
index c8eb54f3e214f3fa5e299e4d3ce4c6fc5b0d771a..ab2c1c96036d1540b778c1a1bf04af82fb8f32f9 100644
--- a/src/fe/timing_kernel.h
+++ b/src/fe/timing_kernel.h
@@ -2,6 +2,8 @@
 #define LIGO_TIMING_KERNEL_H
 
 #include "../drv/gpstime/gpstime_kernel.h"
+#include "portableInline.h"
+
 /// \file timing_kernel.h
 /// \brief File contains some timing diagnostics previously imbedded
 ///<        into the controller.c code.
@@ -9,7 +11,7 @@
 /// \brief Get current kernel time (in GPS)
 /// @return Current time in form of GPS Seconds.
 //***********************************************************************
-inline unsigned long
+LIGO_INLINE unsigned long
 current_time_fe( void )
 {
 
@@ -17,7 +19,7 @@ current_time_fe( void )
     ligo_gpstime_get_ts(&t);
     return  t.tv_sec;
 }
-inline unsigned long
+LIGO_INLINE unsigned long
 current_nanosecond( void )
 {
     LIGO_TIMESPEC t;
diff --git a/src/fe/verify_card_count.c b/src/fe/verify_card_count.c
index 80f83a75b0ad93f80cb44e2af12720ed6f9c51ab..4f8a7045103efd8d32a0414cedd9021af8f0ebf6 100644
--- a/src/fe/verify_card_count.c
+++ b/src/fe/verify_card_count.c
@@ -1,8 +1,9 @@
 /// @file verify_card_count.c
 /// @brief Helper file for moduleLoad.c to check prior IO card counts/types.
 
-void initialize_card_counts( CDS_HARDWARE*, int[] );
-int  verify_card_count( CDS_HARDWARE*, int[] );
+#include "verify_card_count.h"
+#include "controller.h" //CDS_CARD_TYPES, IO_CONFIG_ERROR, 
+#include "util/printl.h"
 
 void
 initialize_card_counts( CDS_HARDWARE* pCds, int cards_per_model[] )
@@ -30,11 +31,10 @@ initialize_card_counts( CDS_HARDWARE* pCds, int cards_per_model[] )
 }
 
 int
-verify_card_count( CDS_HARDWARE* pCds, int model_cards[] )
+verify_card_count( CDS_HARDWARE* pCds, int model_cards[], const char* sysname )
 {
     int  ii;
     int  errStat = 0;
-    int  cardsFound = 0;
 
     for ( ii = 0; ii < CDS_CARD_TYPES; ii++ )
     {
@@ -43,20 +43,17 @@ verify_card_count( CDS_HARDWARE* pCds, int model_cards[] )
         {
             errStat = IO_CONFIG_ERROR;
 #ifdef REQUIRE_IO_CNT
-            printk( "" SYSTEM_NAME_STRING_LOWER
-                    ": ERROR: Did not find correct number of %s cards \n",
-                    _cdscardtypename[ ii ] );
-            printk( "" SYSTEM_NAME_STRING_LOWER
-                    ": ERROR: Expected %d and found %d - exiting\n",
+            printl( "%s: ERROR: Did not find correct number of %s cards \n",
+                    sysname, _cdscardtypename[ ii ] );
+            printl( "%s: ERROR: Expected %d and found %d - exiting\n",
+                    sysname,
                     model_cards[ ii ],
                     pCds->card_count[ ii ] );
 #else
-            printk( "" SYSTEM_NAME_STRING_LOWER
-                    ": WARNING: Did not find correct number of %s cards \n",
-                    _cdscardtypename[ ii ] );
-            printk( "" SYSTEM_NAME_STRING_LOWER
-                    ": WARNING: Expected %d and found %d \n",
-                    model_cards[ ii ],
+            printl( "%s: WARNING: Did not find correct number of %s cards \n",
+                    sysname, _cdscardtypename[ ii ] );
+            printl( "%s: WARNING: Expected %d and found %d \n",
+                    sysname, model_cards[ ii ],
                     pCds->card_count[ ii ] );
 #endif
         }
diff --git a/src/fe/verify_card_count.h b/src/fe/verify_card_count.h
new file mode 100644
index 0000000000000000000000000000000000000000..88f33690757dbd231f2c5df34e1efc47d0639657
--- /dev/null
+++ b/src/fe/verify_card_count.h
@@ -0,0 +1,20 @@
+/// @file verify_card_count.h
+/// @brief Helper file for moduleLoad.c to check prior IO card counts/types.
+#ifndef LIGO_VERIFY_CARD_COUNT_H
+#define LIGO_VERIFY_CARD_COUNT_H
+
+#include "drv/cdsHardware.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void initialize_card_counts( CDS_HARDWARE*, int[] );
+int  verify_card_count( CDS_HARDWARE*, int[], const char* sysname );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_VERIFY_CARD_COUNT_H
diff --git a/src/fe/verify_slots.c b/src/fe/verify_slots.c
index 80f0bdd52c107d083cec4ca448849eebfe8a78da..f41fe547b028a34dabb508b3a8a55696f9176fee 100644
--- a/src/fe/verify_slots.c
+++ b/src/fe/verify_slots.c
@@ -2,9 +2,19 @@
 /// @brief Software used to verify PCIe cards match up to
 ///< backplane slots in IOC Gen 2.
 
-int verify_cards2slots( CDS_HARDWARE* );
-int adc_cards2slots( CDS_HARDWARE*, int );
-int dac_cards2slots( CDS_HARDWARE*, int );
+#include "../fe/verify_slots.h"
+#include "controller.h"//IO_CONFIG_ERROR, pLocalEpics, etc
+#include "drv/gsc_adc_common.h" //GSAI_ALL_CARDS
+#include "drv/gsc_dac_common.h" //DAC_FIFO_EMPTY_TEST
+#include "drv/ligoPcieTiming.h" //LPTC_SLOT_ENABLE
+
+#if defined( RUN_WO_IO_MODULES ) || defined( USE_DOLPHIN_TIMING )
+#include "drv/no_ioc_dac_preload.h"
+#else
+#include "drv/iop_dac_functions.h"
+#endif
+
+#include <linux/delay.h> //udelay()
 
 //***********************************************************************
 // Sub: verify_cards2slots()
@@ -51,7 +61,6 @@ dac_cards2slots( CDS_HARDWARE* pCds, int card )
     int status;
     int max_wait = 20;
     int timer = 0;
-    int adcbufsize = 0;
     int err_return = 0;
     int cardslot = pCds->dacSlot[ card ];
 
diff --git a/src/fe/verify_slots.h b/src/fe/verify_slots.h
new file mode 100644
index 0000000000000000000000000000000000000000..d08b445e205c1a1a362517128688bee0ec4d4737
--- /dev/null
+++ b/src/fe/verify_slots.h
@@ -0,0 +1,21 @@
+#ifndef LIGO_VERIFY_SLOTS_H
+#define LIGO_VERIFY_SLOTS_H
+
+#include "drv/cdsHardware.h" //CDS_HARDWARE
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int verify_cards2slots( CDS_HARDWARE* );
+int adc_cards2slots( CDS_HARDWARE*, int );
+int dac_cards2slots( CDS_HARDWARE*, int );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_VERIFY_SLOTS_H
diff --git a/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/admin_interface.go b/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/admin_interface.go
index 637f8a809d0d11e381643f38b2cba733c0caa8eb..80ded8f478ed58449163492b51a110357d520aaf 100644
--- a/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/admin_interface.go
+++ b/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/admin_interface.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"encoding/json"
 	"git.ligo.org/cds/advligorts/src/fe_stream_test/fe_simulation"
+	"git.ligo.org/cds/advligorts/src/fe_stream_test/fe_simulation/gps"
 	"git.ligo.org/cds/advligorts/src/fe_stream_test/fe_simulation/middleware"
 	"log"
 	"net/http"
@@ -22,11 +23,13 @@ func gotoIndex(w http.ResponseWriter, r *http.Request) {
 	http.Redirect(w, r, "/", http.StatusSeeOther)
 }
 
-func indexHandler(w http.ResponseWriter, r *http.Request, sim *fe_simulation.SimulationLoop) {
+func indexHandler(w http.ResponseWriter, r *http.Request, sim *fe_simulation.SimulationLoop, clock *gps.Clock) {
 	data := struct {
 		DcuStatus []fe_simulation.SimulationDcuStatus
+		Clock     *gps.Clock
 	}{
 		DcuStatus: sim.Status(),
+		Clock:     clock,
 	}
 	if err := indexHandlerTemplate.Execute(w, &data); err != nil {
 		log.Print(err)
@@ -97,14 +100,14 @@ func mutateDcuApiHandler(w http.ResponseWriter, r *http.Request, sim *fe_simulat
 func timingGlitchHandler(w http.ResponseWriter, r *http.Request, sim *fe_simulation.SimulationLoop, onSuccess http.HandlerFunc) {
 	var rawRequest struct {
 		DeltaCycles int
-		Dcus string
+		Dcus        string
 	}
 	if middleware.ParseInput(&rawRequest, r) != nil {
 		http.Error(w, "Bad request", http.StatusBadRequest)
 		return
 	}
 	dcuStrings := strings.Split(rawRequest.Dcus, ",")
-	dcus := make([]int,0,len(dcuStrings))
+	dcus := make([]int, 0, len(dcuStrings))
 	for _, input := range dcuStrings {
 		if id, err := strconv.ParseInt(input, 10, 32); err == nil {
 			dcus = append(dcus, int(id))
@@ -117,7 +120,22 @@ func timingGlitchHandler(w http.ResponseWriter, r *http.Request, sim *fe_simulat
 	onSuccess(w, r)
 }
 
-func runAdminInterface(sim *fe_simulation.SimulationLoop, address string) {
+func clockStopHandler(w http.ResponseWriter, r *http.Request, clock *gps.Clock, onSuccess http.HandlerFunc) {
+	clock.Pause()
+	onSuccess(w, r)
+}
+
+func clockResumeHandler(w http.ResponseWriter, r *http.Request, clock *gps.Clock, onSuccess http.HandlerFunc) {
+	clock.Resume()
+	onSuccess(w, r)
+}
+
+func clockStepHandler(w http.ResponseWriter, r *http.Request, clock *gps.Clock, onSuccess http.HandlerFunc) {
+	clock.Step()
+	onSuccess(w, r)
+}
+
+func runAdminInterface(sim *fe_simulation.SimulationLoop, address string, clock *gps.Clock) {
 	for sim.State() == fe_simulation.SimulationNotStarted {
 		time.Sleep(time.Microsecond * 20)
 	}
@@ -130,7 +148,7 @@ func runAdminInterface(sim *fe_simulation.SimulationLoop, address string) {
 	srv.Handler = mux
 
 	mux.HandleFunc("/", middle.Apply(func(w http.ResponseWriter, r *http.Request) {
-		indexHandler(w, r, sim)
+		indexHandler(w, r, sim, clock)
 	}))
 	mux.HandleFunc("/simple_mutate/", middle.Apply(func(w http.ResponseWriter, r *http.Request) {
 		mutateDcuApiHandler(w, r, sim, nil, gotoIndex)
@@ -141,9 +159,18 @@ func runAdminInterface(sim *fe_simulation.SimulationLoop, address string) {
 	mux.HandleFunc("/simple_start_dcu/(?P<dcuid>[0-9]+)/", middle.Apply(func(w http.ResponseWriter, r *http.Request) {
 		startDcuApiHandler(w, r, sim, gotoIndex)
 	})).Methods("POST")
-	mux.HandleFunc("/simple_timing_glitch/", middle.Apply(func (w http.ResponseWriter, r *http.Request) {
+	mux.HandleFunc("/simple_timing_glitch/", middle.Apply(func(w http.ResponseWriter, r *http.Request) {
 		timingGlitchHandler(w, r, sim, gotoIndex)
 	})).Methods("POST")
+	mux.HandleFunc("/clock/stop/", middle.Apply(func(w http.ResponseWriter, r *http.Request) {
+		clockStopHandler(w, r, clock, gotoIndex)
+	})).Methods("POST")
+	mux.HandleFunc("/clock/resume/", middle.Apply(func(w http.ResponseWriter, r *http.Request) {
+		clockResumeHandler(w, r, clock, gotoIndex)
+	})).Methods("POST")
+	mux.HandleFunc("/clock/step/", middle.Apply(func(w http.ResponseWriter, r *http.Request) {
+		clockStepHandler(w, r, clock, gotoIndex)
+	})).Methods("POST")
 
 	mux.HandleFunc("/api/v1/system/status/", middle.Apply(func(w http.ResponseWriter, r *http.Request) {
 		systemStatusApiHandler(w, r, sim)
@@ -161,7 +188,7 @@ func runAdminInterface(sim *fe_simulation.SimulationLoop, address string) {
 		dcuId, _ := getDcuId(r)
 		mutateDcuApiHandler(w, r, sim, &dcuId, apiOk)
 	})).Methods("POST")
-	mux.HandleFunc("/api/v1/system/timing_glitch/", middle.Apply(func (w http.ResponseWriter, r *http.Request) {
+	mux.HandleFunc("/api/v1/system/timing_glitch/", middle.Apply(func(w http.ResponseWriter, r *http.Request) {
 		timingGlitchHandler(w, r, sim, apiOk)
 	})).Methods("POST")
 
diff --git a/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/fe_simulated_streams.go b/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/fe_simulated_streams.go
index cdfbe74657d325bd50febae0687baefc88b7c6f5..65cd53d891be183f01c17f9cc979b86f39359fa9 100644
--- a/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/fe_simulated_streams.go
+++ b/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/fe_simulated_streams.go
@@ -4,6 +4,7 @@ import (
 	"flag"
 	"fmt"
 	"git.ligo.org/cds/advligorts/src/fe_stream_test/fe_simulation"
+	"git.ligo.org/cds/advligorts/src/fe_stream_test/fe_simulation/gps"
 	"log"
 )
 
@@ -84,7 +85,7 @@ func parseArgs() fe_simulation.InitialOptions {
 		MBufSizeMB:  *mbufSize,
 		Concentrate: !*individualMbufs,
 		AdminIface:  *adminIface,
-		UseAWG: *useAWG,
+		UseAWG:      *useAWG,
 	}
 
 	return opts
@@ -103,8 +104,13 @@ func main() {
 	if err != nil {
 		log.Fatalf("Unable to create simulation loop %v", err)
 	}
+	clock, err := gps.NewClock()
+	if err != nil {
+		log.Fatalf("Unable to create clock, error %v", err)
+	}
+	defer clock.Close()
 	if opts.AdminIface != "" {
-		go runAdminInterface(simLoop, opts.AdminIface)
+		go runAdminInterface(simLoop, opts.AdminIface, clock)
 	}
-	simLoop.Run()
+	simLoop.Run(clock)
 }
diff --git a/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/templates.go b/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/templates.go
index bd4c995978fbabee7fe70afe07151f28657d478f..f656ffafe0feb9cb4d2d37808ad5e5024cc9ea0e 100644
--- a/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/templates.go
+++ b/src/fe_stream_test/fe_simulation/cmd/fe_simulated_streams/templates.go
@@ -72,7 +72,24 @@ func init() {
 				<label>Dcus<label><input type="text" name="Dcus"/><br/>
 				
 				<input type="submit" value="Request Glitch" />
-			</from>
+			</form>
+		</li>
+		<li>
+			<p>Time</p>
+			<p>Current time {{.Clock.String}}</p>
+			{{if .Clock.Paused }}
+			<form method="POST" action="/clock/resume/">
+				<input type="submit" value="Resume" />
+			</form>
+			<br/>
+			<form method="POST" action="/clock/step/">
+				<input type="submit" value="Single step" />
+			</form>
+			{{else}}
+			<form method="POST" action="/clock/stop/">
+				<input type="submit" value="Stop" />
+			</form>
+			{{end}}
 		</li>
 	</ul>
 </body>
diff --git a/src/fe_stream_test/fe_simulation/gps/gps.go b/src/fe_stream_test/fe_simulation/gps/gps.go
index 4e6e42c2adae2147fa2745cd9664c0477b8bb5f1..eb4393299b0cf67a3e085259a611d07b4c517538 100644
--- a/src/fe_stream_test/fe_simulation/gps/gps.go
+++ b/src/fe_stream_test/fe_simulation/gps/gps.go
@@ -4,20 +4,41 @@ package gps
 #include <stdint.h>
 #include <sys/ioctl.h>
 
-#define SYMMETRICOM_TIME 1
+#define IOCTL_GPSTIME_TIME 1
+#define IOCTL_GPSTIME_PAUSE _IO('x', 2)
+#define IOCTL_GPSTIME_RESUME _IO('x', 3)
+#define IOCTL_GPSTIME_RESET _IO('x', 4)
+#define IOCTL_GPSTIME_STEP _IO('x', 5)
 
 static void gps_now(int fd, int64_t *dest_sec, int32_t *dest_nano) {
 	unsigned long t[3];
-	ioctl( fd, SYMMETRICOM_TIME, &t);
+	ioctl( fd, IOCTL_GPSTIME_TIME, &t);
 	t[1] *= 1000;
 	t[1] += t[2];
 	*dest_sec = t[0];
 	*dest_nano = t[1];
 }
 
+static void gps_action(int fd, int action) {
+	ioctl( fd, action );
+}
+
+static void gps_pause(int fd) {
+	gps_action(fd, IOCTL_GPSTIME_PAUSE);
+}
+
+static void gps_resume(int fd) {
+	gps_action(fd, IOCTL_GPSTIME_RESUME);
+}
+
+static void gps_step(int fd) {
+	gps_action(fd, IOCTL_GPSTIME_STEP);
+}
+
 */
 import "C"
 import (
+	"fmt"
 	"os"
 	"time"
 )
@@ -31,7 +52,7 @@ type Clock struct {
 	offset  int64
 }
 
-func NewClock(offset int64) (*Clock, error) {
+func NewClock() (*Clock, error) {
 	gpsFile, err := os.Open("/dev/gpstime")
 	if err != nil {
 		return nil, err
@@ -39,7 +60,7 @@ func NewClock(offset int64) (*Clock, error) {
 	return &Clock{
 		gpsFile: gpsFile,
 		gpsFd:   gpsFile.Fd(),
-		offset:  offset,
+		offset:  0,
 	}, nil
 }
 
@@ -57,3 +78,34 @@ func (c *Clock) Now() time.Time {
 	C.gps_now(C.int(c.gpsFd), &gpsSec, &gpsNano)
 	return time.Unix(int64(gpsSec+C.int64_t(c.offset)), int64(gpsNano))
 }
+
+func (c *Clock) String() string {
+	t := c.Now()
+	return fmt.Sprintf("%d:%d", t.Unix(), t.Nanosecond())
+}
+
+func (c *Clock) Paused() bool {
+	f, err := os.Open("/sys/kernel/gpstime/debug_pause_status")
+	if err != nil {
+		return false
+	}
+	defer f.Close()
+	var buffer [1]byte
+	n, err := f.Read(buffer[:])
+	if n == 0 || err != nil {
+		return false
+	}
+	return buffer[0] == '1'
+}
+
+func (c *Clock) Pause() {
+	C.gps_pause(C.int(c.gpsFd))
+}
+
+func (c *Clock) Resume() {
+	C.gps_resume(C.int(c.gpsFd))
+}
+
+func (c *Clock) Step() {
+	C.gps_step(C.int(c.gpsFd))
+}
diff --git a/src/fe_stream_test/fe_simulation/simulation.go b/src/fe_stream_test/fe_simulation/simulation.go
index d9e8faf2282794d79cec9a7d6cc3e684de3a94a3..fae53eb0a54776aeb13729121789b0b83b1a36b0 100644
--- a/src/fe_stream_test/fe_simulation/simulation.go
+++ b/src/fe_stream_test/fe_simulation/simulation.go
@@ -90,7 +90,7 @@ type InitialOptions struct {
 	MBufSizeMB  int
 	Concentrate bool
 	AdminIface  string
-	UseAWG		bool
+	UseAWG      bool
 }
 
 type MutationRequest struct {
@@ -119,7 +119,7 @@ const (
 	commandSimulationStopDcu        = iota
 	commandSimulationStartDcu       = iota
 	commandSimulationMutateChannels = iota
-	commandSimulationTimeGlitch	    = iota
+	commandSimulationTimeGlitch     = iota
 )
 
 // simulationMessages are used to send request to a running simulation.
@@ -168,11 +168,10 @@ type timingGlitchCommand struct {
 	params TimingGlitchRequest
 }
 
-func (t* timingGlitchCommand) Command() int {
+func (t *timingGlitchCommand) Command() int {
 	return commandSimulationTimeGlitch
 }
 
-
 func NewSimulationLoop(opts InitialOptions) (*SimulationLoop, error) {
 	return &SimulationLoop{opts: opts, queue: make(chan simulationMessage, 10)}, nil
 }
@@ -198,7 +197,7 @@ func (s *SimulationLoop) RequestTimingGlitch(req TimingGlitchRequest) {
 
 // Run is the main simluation loop.  It takes the configuration, creates models, and ensures
 // that the models output data.
-func (s *SimulationLoop) Run() error {
+func (s *SimulationLoop) Run(clock *gps.Clock) error {
 	var err error
 	iniManager := NewIniManager(s.opts.IniRoot, s.opts.MasterPath)
 	models := make([]*Model, len(s.opts.Models))
@@ -225,19 +224,19 @@ func (s *SimulationLoop) Run() error {
 	var dataSize uintptr
 
 	if s.opts.UseAWG {
-	    // open AWG ipcs
-	    for _, m := range models {
-		    err = m.OpenTPShmem()
-		    if err != nil {
-			    log.Printf("Unable to open testpoint buffer %s_tp %v", m.Name, err)
-			    return err
-		    }
-		    err = m.OpenAWGShmem()
-		    if err != nil {
-			    log.Printf("Unable to open awg buffer %s_awg %v", m.Name, err)
-			    return err
-		    }
-	    }
+		// open AWG ipcs
+		for _, m := range models {
+			err = m.OpenTPShmem()
+			if err != nil {
+				log.Printf("Unable to open testpoint buffer %s_tp %v", m.Name, err)
+				return err
+			}
+			err = m.OpenAWGShmem()
+			if err != nil {
+				log.Printf("Unable to open awg buffer %s_awg %v", m.Name, err)
+				return err
+			}
+		}
 	}
 
 	if s.opts.Concentrate {
@@ -272,10 +271,6 @@ func (s *SimulationLoop) Run() error {
 
 	timeStep := time.Nanosecond * 1000000000 / 16
 	// start transmission at the start of the next second
-	clock, err := gps.NewClock(0)
-	if err != nil {
-		return err
-	}
 	transmitTime := time.Unix(clock.Now().Unix()+1, 0)
 
 	delayMultiplier := time.Duration(0)
@@ -295,6 +290,11 @@ func (s *SimulationLoop) Run() error {
 		now := clock.Now()
 		for ; now.Before(transmitTime); now = clock.Now() {
 			time.Sleep(2 * time.Millisecond)
+			select {
+			case msg := <-s.queue:
+				s.handleMessage(msg, &done, models, &iniManager)
+			default:
+			}
 		}
 
 		time.Sleep(time.Millisecond * delayMultiplier)
@@ -433,7 +433,7 @@ func generateConcentrated(models []*Model, destPtr, maxDatasize uintptr, cycle i
 			headerGps--
 		}
 		if glitchCycle > 15 {
-			headerGps += glitchCycle/16
+			headerGps += glitchCycle / 16
 			glitchCycle %= 16
 		}
 		headerNano = glitchCycle
@@ -546,7 +546,7 @@ func generateIndividual(models []*Model, cycle int, transmitTime time.Time) erro
 			headerGps--
 		}
 		if headerCycle > 15 {
-			headerGps += headerCycle/16
+			headerGps += headerCycle / 16
 			headerCycle %= 16
 		}
 		headerNano = headerCycle
diff --git a/src/gds/awgtpman/awgtpman.c b/src/gds/awgtpman/awgtpman.c
index 6c53d387f77cea37ea988dd33425c48a8851d8a4..8a1d33caa8b311d18dfe49dcf8d995013c77fbd5 100644
--- a/src/gds/awgtpman/awgtpman.c
+++ b/src/gds/awgtpman/awgtpman.c
@@ -341,14 +341,15 @@ CDS_HARDWARE cdsPciModules;
 
       if(!use_gps_time)
       {
-          if ( ioMemData->totalCards == 0 )
+          if ( ioMemData->totalCards <= 0 )
           {
               // Wait for the master to come up
               printf( "Waiting for the IOP to start\n" );
-              while ( ioMemData->totalCards == 0 )
+              while ( ioMemData->totalCards <= 0 )
               {
                   sleep( 2 );
               }
+              sleep(1);
           }
           printf( "Total PCI cards from the master: %d\n",
                   ioMemData->totalCards );
@@ -400,15 +401,19 @@ CDS_HARDWARE cdsPciModules;
 	   printf ("Error: Unable to spawn testpoint manager\n");
            return 1;
         }
-        sleep (5);
-     
-	{
-          extern int testpoint_manager_node;
-          if (testpoint_manager_node < 0) {
-	    printf("Test point manager startup failed; %d\n", testpoint_manager_node);
-	    return 1;
-          }
-	}
+        extern int testpoint_manager_node;
+        int tm_count=0;
+        while( testpoint_manager_node < 0)
+        {
+            if(tm_count > 60)
+            {
+                printf("Test point manager startup failed; %d\n", testpoint_manager_node);
+                return 1;
+            }
+            sleep( 1 );
+            tm_count++;
+        }
+
       }
 
       if (run_awg) {
@@ -420,11 +425,19 @@ CDS_HARDWARE cdsPciModules;
 	   printf ("Error: Unable to spawn arbitrary waveform generator\n");
            return 1;
         }
-        sleep (5);
+
+        int awg_init_count = 0;
         while(!isAwgInit())
         {
+            // wait a whole minute to quit
+            if(awg_init_count > 60)
+            {
+                printf("AWG startup failed.\n");
+                return 1;
+            }
             printf("Waiting for AWG to initialize.\n");
             sleep(1);
+            awg_init_count++;
         }
 
         /* Load AWG parameters here */
diff --git a/src/gds/awgtpman/gdschannel.c b/src/gds/awgtpman/gdschannel.c
index 39e359298cccf9316a6345ac99310ab990d84049..ca8f4614c4ef2bc024c6c4577208b7bea81e8bd4 100644
--- a/src/gds/awgtpman/gdschannel.c
+++ b/src/gds/awgtpman/gdschannel.c
@@ -605,6 +605,10 @@ static char *versionId = "Version $Id$" ;
          loadParamSectionEntry (PRM_RMID, sec, nentry, &cursor, 
                               5, &chninfo[chninfonum].rmId);
 
+         // unify DCUID location between awgtpman and DAQ reports
+         // (other functions read dcuids from the daq into chGroup)
+         chninfo[chninfonum].chGroup = chninfo[chninfonum].rmId;
+
 	 printf("%s rmid %d\n", chninfo[chninfonum].chName, chninfo[chninfonum].rmId);
          chninfo[chninfonum].dcuId = -1;
          loadParamSectionEntry (PRM_DCUID, sec, nentry, &cursor, 
diff --git a/src/gds/awgtpman/gdsheartbeat.c b/src/gds/awgtpman/gdsheartbeat.c
index a53129b8d1ba6479f00e7c9a81bfb21a6b457f22..756294db2054f65fac514d363b60cfc30a32e60d 100644
--- a/src/gds/awgtpman/gdsheartbeat.c
+++ b/src/gds/awgtpman/gdsheartbeat.c
@@ -516,7 +516,7 @@ unsigned int curDaqBlockSize;
       if (0 == noreturn) {
          return NULL;
       }
-      signalHandlerStatus = 1;
+
       pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 
       // Sync up to the master clock
@@ -524,11 +524,23 @@ unsigned int curDaqBlockSize;
       printf("waiting to sync %d\n", *ioMemDataCycle);
       // Spin until cycle 0 detected in first ADC buffer location.
       int spin_cnt = 0;
-      struct timespec cycle_wait={0, 1000000}; //1 msec
+      struct timespec cycle_wait={0, 10000000}; //10 msec
+
+      //first wait for non-zero then zero.  If no change, we never sync.
+
+      while (*ioMemDataCycle == 0) {
+          nanosleep(&cycle_wait, 0);
+          spin_cnt++;
+          if (spin_cnt >= 6000) {
+              fprintf(stderr, "Timed out waiting for cycle counter to change from zero.\n");
+              _exit(3);
+          }
+      }
+
       while (*ioMemDataCycle != 0) {
           nanosleep(&cycle_wait, 0);
 	spin_cnt++;
-	if (spin_cnt >= 10000) {
+	if (spin_cnt >= 6000) {
 	  fprintf(stderr, "Timed out waiting for cycle counter to return to zero.\n");
           _exit(3);
 	}
@@ -557,6 +569,8 @@ unsigned int curDaqBlockSize;
 
       int samples_per_cycle = samples_per_second / DAQ_NUM_DATA_BLOCKS_PER_SECOND;
 
+      signalHandlerStatus = 1;
+
       while (1) {
 
          /* check if finished */
@@ -609,7 +623,7 @@ unsigned int curDaqBlockSize;
       {
          static int	once = 0;
          int		attr;
-         struct timespec tick = {0, 1000000};	/* tick */	
+         struct timespec tick = {0, 100000000};	/* tick */
       
       #if !defined(AVOID_SIGNALS)
          sigset_t	set;
diff --git a/src/gds/awgtpman/shared_memory.c b/src/gds/awgtpman/shared_memory.c
index 5d6a35a3d980cada023cdf9e27f22eec0bbad1e2..fc0b5615d28e71a9eba9684c9b50867e8e7ca38a 100644
--- a/src/gds/awgtpman/shared_memory.c
+++ b/src/gds/awgtpman/shared_memory.c
@@ -147,7 +147,7 @@ OpenIoFrontEndData(const char *model_name)
     buff[sizeof(buff)-1] = 0;
     strncat( buff, model_name, sizeof( buff) - strlen(buff) - 1);
 
-    handle = shmem_open(buff,  64 );
+    handle = shmem_open(buff, SHMEM_EPICS_SIZE_MB );
     ioFrontEndData = (volatile uint32_t *) shmem_mapping( handle );
     io_frontend_shmem_handle = handle;
     atexit(closeIOFrontEndData);
@@ -170,4 +170,4 @@ SetSharedMemoryPrefix(const char *prefix)
         return 0;
     }
     return 1;
-}
\ No newline at end of file
+}
diff --git a/src/gds/awgtpman/testpoint.c b/src/gds/awgtpman/testpoint.c
index b081d2ff458af539fd62a497c4a5ea8be93a1e04..487ffd267f4357ad696b583d70b0af6f23263545 100644
--- a/src/gds/awgtpman/testpoint.c
+++ b/src/gds/awgtpman/testpoint.c
@@ -10,6 +10,11 @@
 #include "dtt/gdserr.h"
 #include "dtt/gdserrmsg.h"
 #include "tconv.h"
+#include "testpoint_interface_v3.h"
+
+#if defined (_CONFIG_DYNAMIC)
+#include "confinfo.h"
+#endif
 
 /*----------------------------------------------------------------------*/
 /*                                                         		*/
@@ -39,6 +44,7 @@ static int			tp_init = 0;
 static tpNode_t		tpNode[TP_MAX_NODE];
 static int			tpNum = 0;
 
+
 /*----------------------------------------------------------------------*/
 /*                                                         		*/
 /* Internal Procedure Name: tpSetHostAddress				*/
@@ -82,9 +88,9 @@ static int			tpNum = 0;
       if (tpNode[node].duplicate) {
          tpNode[node].id = k;
       }
-      printf ("TP: node = %i, host = %s, dup = %i, prog = 0x%x, vers = %i\n",
-              node, tpNode[node].hostname, tpNode[node].duplicate,
-              (int)tpNode[node].prognum, (int)tpNode[node].progver);
+//      printf ("TP: node = %i, host = %s, dup = %i, prog = 0x%x, vers = %i\n",
+//              node, tpNode[node].hostname, tpNode[node].duplicate,
+//              (int)tpNode[node].prognum, (int)tpNode[node].progver);
       return 0;
    }
 
@@ -147,6 +153,11 @@ int testpoint_client (void)
     int		status;		/* rpc status */
 
 
+#if defined (_CONFIG_DYNAMIC)
+    const char* const* cinfo;		/* configuration info */
+    confinfo_t	crec;		/* conf. info record */
+#endif
+
     /* already initialized */
     if (tp_init == 2) {
         return tpNum;
@@ -165,7 +176,19 @@ int testpoint_client (void)
         printf("testpoint_client %s\n", _TP_CLIENT_VERSION) ;
     }
 
+#if defined (_CONFIG_DYNAMIC)
+    for (cinfo = getConfInfo (0, 0); cinfo && *cinfo; cinfo++) {
+        if ((parseConfInfo (*cinfo, &crec) == 0) &&
+             (gds_strcasecmp (crec.interface,
+                               CONFIG_SERVICE_TP) == 0) &&
+             (crec.ifo >= 0) && (crec.ifo < TP_MAX_NODE) &&
+             (crec.port_prognum > 0) && (crec.progver > 0)) {
 
+            tpSetHostAddress (crec.ifo, crec.host,
+                              crec.port_prognum, crec.progver);
+        }
+    }
+#endif
 
     timeout.tv_sec = RPC_PROBE_WAIT;
     timeout.tv_usec = 0;
@@ -248,6 +271,7 @@ int tpClear (int node, const testpoint_t tp[], int tplen)
     TP_r		testpoints;	/* test point list */
     int		result;		/* result of rpc call */
     CLIENT*		clnt;		/* client rpc handle */
+    const testpoint_t *target;
 
     gdsDebug ("clear test point");
 
@@ -259,19 +283,33 @@ int tpClear (int node, const testpoint_t tp[], int tplen)
     /* make test point list */
     if (tp == NULL) {
         testpoints.TP_r_len = 1;
-        testpoints.TP_r_val = (ushort *)&all;
+        target = &all;
     }
     else if (tplen == 0) {
         return 0;
     }
     else {
         testpoints.TP_r_len = tplen;
-        testpoints.TP_r_val = (ushort *) tp;
+        target = tp;
+    }
+
+    testpoints.TP_r_val = malloc(testpoints.TP_r_len * sizeof(testpoints.TP_r_val[0]));
+    if(testpoints.TP_r_val == NULL)
+    {
+        gdsError(GDS_ERR_MEM, "unable to allocate memory for RPC struct");
+        return -5;
+    }
+
+    int i;
+    for(i=0; i < testpoints.TP_r_len; ++i)
+    {
+        testpoints.TP_r_val[i] = target[i];
     }
 
     /* make client handle */
     clnt = tpMakeHandle (node);
     if (clnt == NULL) {
+        free(testpoints.TP_r_val);
         return -3;
     }
 
@@ -284,6 +322,7 @@ int tpClear (int node, const testpoint_t tp[], int tplen)
 
     /* free handle */
     clnt_destroy (clnt);
+    free(testpoints.TP_r_val);
     return result;
 }
 
@@ -380,11 +419,23 @@ int tpRequest (int node, const testpoint_t tp[], int tplen,
 
     /* make test point list */
     testpoints.TP_r_len = tplen;
-    testpoints.TP_r_val = (ushort *) tp;
+    testpoints.TP_r_val = malloc(tplen * sizeof( testpoints.TP_r_val[0] ));
+    if(testpoints.TP_r_val == NULL)
+    {
+        gdsError(GDS_ERR_MEM, "could not allocate buffer for testpoints");
+        return -5;
+    }
+
+    int i;
+    for(i=0; i < tplen; ++i)
+    {
+        testpoints.TP_r_val[i] = tp[i];
+    }
 
     /* make client handle */
     clnt = tpMakeHandle (node);
     if (clnt == NULL) {
+        free(testpoints.TP_r_val);
         return -3;
     }
 
@@ -409,6 +460,7 @@ int tpRequest (int node, const testpoint_t tp[], int tplen,
     /* free handle and memory of return argument */
     xdr_free ((xdrproc_t)xdr_resultRequestTP_r, (char*) &result);
     clnt_destroy (clnt);
+    free(testpoints.TP_r_val);
     return retval;
 }
 
@@ -547,8 +599,11 @@ int tpQuery (int node, int tpinterface, testpoint_t tp[], int tplen,
         return -2;
     }
 
+    int max_interface = (testAwgTpInterfaceVersion(node) > 3)
+        ? TP_MAX_INTERFACE : TP_MAX_INTERFACE_V3;
+
     /* check interface */
-    if ((tpinterface < 0) || (tpinterface >= TP_MAX_INTERFACE)) {
+    if ((tpinterface < 0) || (tpinterface >= max_interface)) {
         return -2;
     }
 
@@ -628,7 +683,77 @@ static char* cmdreply (const char* m)
 /* Procedure Returns: void						*/
 /*                                                         		*/
 /*----------------------------------------------------------------------*/
-static void queryCmd (char* buf, int node)
+static void queryCmd_v3 (char* buf, int node)
+{
+    int		i;
+    char*		p;
+    testpoint_t	tp[TP_MAX_INDEX]; /* test points */
+    int		num;	/* number of test points */
+
+    sprintf (buf, "Test points for node %i\n", node);
+    /* query lsc exc */
+    num = tpQuery (node, TP_LSC_EX_INTERFACE, tp,
+                   TP_MAX_INDEX, 0, 0);
+    p = strend (buf);
+    sprintf (p, "LSC EX:");
+    p = strend (p);
+    if (num < 0) {
+        sprintf (p, " invalid\n");
+        return;
+    }
+    for (i = 0; i < num; i++) {
+        sprintf (p, " %i", tp[i]);
+        p = strend (p);
+    }
+    sprintf (p++, "\n");
+    /* query lsc tp */
+    num = tpQuery (node, TP_LSC_TP_INTERFACE, tp,
+                   TP_MAX_INDEX, 0, 0);
+    p = strend (buf);
+    sprintf (p, "LSC TP:");
+    p = strend (p);
+    if (num < 0) {
+        sprintf (p, " invalid\n");
+        return;
+    }
+    for (i = 0; i < num; i++) {
+        sprintf (p, " %i", tp[i]);
+        p = strend (p);
+    }
+    sprintf (p++, "\n");
+    /* query asc exc */
+    num = tpQuery (node, TP_ASC_EX_INTERFACE, tp,
+                   TP_MAX_INDEX, 0, 0);
+    p = strend (buf);
+    sprintf (p, "ASC EX:");
+    p = strend (p);
+    if (num < 0) {
+        sprintf (p, " invalid\n");
+        return;
+    }
+    for (i = 0; i < num; i++) {
+        sprintf (p, " %i", tp[i]);
+        p = strend (p);
+    }
+    sprintf (p++, "\n");
+    /* query asc tp */
+    num = tpQuery (node, TP_ASC_TP_INTERFACE, tp,
+                   TP_MAX_INDEX, 0, 0);
+    p = strend (buf);
+    sprintf (p, "ASC TP:");
+    p = strend (p);
+    if (num < 0) {
+        sprintf (p, " invalid\n");
+        return;
+    }
+    for (i = 0; i < num; i++) {
+        sprintf (p, " %i", tp[i]);
+        p = strend (p);
+    }
+    sprintf (p++, "\n");
+}
+
+static void queryCmd_v4 (char* buf, int node)
 {
     int		i;
     char*		p;
@@ -668,6 +793,24 @@ static void queryCmd (char* buf, int node)
     sprintf (p++, "\n");
 }
 
+static void queryCmd (char* buf, int node)
+{
+    int interface_version = testAwgTpInterfaceVersion(node);
+    switch (interface_version)
+    {
+    case 3:
+        queryCmd_v3(buf, node);
+        break;
+    case 4:
+        queryCmd_v4(buf, node);
+        break;
+    default:
+        printf("unrecognized awgtp interface version %d\n", interface_version);
+        break;
+    }
+}
+
+
 /*----------------------------------------------------------------------*/
 /*                                                         		*/
 /* External Procedure Name: tpCommand					*/
@@ -691,7 +834,7 @@ char* tpCommand (const char* cmd)
     if (gds_strncasecmp (cmd, "help", 4) == 0) {
         return cmdreply (_HELP_TEXT);
     }
-        /* show */
+    /* show */
     else if (gds_strncasecmp (cmd, "show", 4) == 0) {
         p = (char*) (cmd + 4);
         while (*p == ' ') {
@@ -713,10 +856,13 @@ char* tpCommand (const char* cmd)
             }
         }
         else {
-            node = *p - (int) '0';
-            if ((node < 0) || (node >= TP_MAX_NODE) ||
-                (!tpNode[node].valid)) {
-                return cmdreply ("error: invalid node number");
+            node = atoi(p);
+            if ((node < 0) || (node >= TP_MAX_NODE)) {
+                printf("invalid node number: 0 < node <= %d\n", TP_MAX_NODE);
+                return cmdreply ("error: node number out of range");
+            }
+            if ((!tpNode[node].valid)) {
+                return cmdreply ("error: node number invalid");
             }
             buf = malloc (2000);
             if (!buf) /* JCB */
@@ -729,16 +875,18 @@ char* tpCommand (const char* cmd)
         buf = realloc (buf, strlen (buf) + 1);
         return buf;
     }
-        /* set */
+    /* set */
     else if (gds_strncasecmp (cmd, "set", 3) == 0) {
         p = (char*) (cmd + 3);
         while (*p == ' ') {
             p++;
         }
-        node = *p - (int) '0';
-        if ((node < 0) || (node >= TP_MAX_NODE)) {
+        char *endptr;
+        node = strtol(p, &endptr, 10);
+
+        if (endptr == p) {
             /* assume channel names are specified */
-            if (tpRequestName (p, -1, NULL, NULL) < 0) {
+            if (tpRequestName (endptr, -1, NULL, NULL) < 0) {
                 return cmdreply ("error: unable to set test point");
             }
             else {
@@ -746,6 +894,11 @@ char* tpCommand (const char* cmd)
             }
         }
         else {
+            p = endptr;
+            if ((node < 0) || (node >= TP_MAX_NODE)) {
+                printf("invalid node number: 0 < node <= %d\n", TP_MAX_NODE);
+                return cmdreply ("error: node number out of range");
+            }
             /* assume test point numbers are specified */
             if (!tpNode[node].valid) {
                 return cmdreply ("error: invalid node number");
@@ -768,7 +921,7 @@ char* tpCommand (const char* cmd)
             }
         }
     }
-        /* clear */
+    /* clear */
     else if (gds_strncasecmp (cmd, "clear", 5) == 0) {
         p = (char*) (cmd + 5);
         while (*p == ' ') {
@@ -776,16 +929,22 @@ char* tpCommand (const char* cmd)
         }
         /* read node */
         if (*p == '*') {
+#ifdef CLEAR_ALL_TP_ALLOWED
             for (node = 0; node < TP_MAX_NODE; node++) {
                 if (tpNode[node].valid) {
                     tpClear (node, NULL, 0);
                 }
             }
             return cmdreply ("test point cleared");
+#else
+            return cmdreply ("Clearing all test points on all nodes is not allowed") ;
+#endif
         }
         /* try reading node */
-        node = *p - (int) '0';
-        if ((node < 0) || (node >= TP_MAX_NODE)) {
+        char *endptr;
+        node = strtol(p, &endptr, 10);
+
+        if (endptr == p) {
             /* assume channel names are specified */
             if (tpClearName (p) < 0) {
                 return cmdreply ("error: unable to clear test point");
@@ -795,6 +954,11 @@ char* tpCommand (const char* cmd)
             }
         }
         else {
+            p = endptr;
+            if ((node < 0) || (node >= TP_MAX_NODE)) {
+                printf("invalid node number: 0 < node <= %d\n", TP_MAX_NODE);
+                return cmdreply ("error: node number out of range");
+            }
             /* assume test point numbers are specified */
             if (!tpNode[node].valid) {
                 return cmdreply ("error: invalid node number");
@@ -828,7 +992,6 @@ char* tpCommand (const char* cmd)
     }
 }
 
-
 /*----------------------------------------------------------------------*/
 /*                                                         		*/
 /* External Procedure Name: tpcmdline					*/
@@ -892,3 +1055,57 @@ int keepAlive (int node)
     clnt_destroy (clnt);
     return ret;
 }
+
+
+/// Find RPC interface version used by awgtpman
+/// version 4 was introduced about RCG version 4.1.0
+/// all previous interface versions, including for RCG 4.0.1,
+/// are considered version 3.
+/// Version 4 has only two testpoint interfaces: one for excitations and one for
+/// other test points.
+/// Version 3 has 4 testpoint interfaces: the two interfaces of version 4 are
+/// divided between LSC and ASC test points.
+///
+/// \param node the node number to identify
+/// \return the version number, 0 on error
+int testAwgTpInterfaceVersion(int node)
+{
+    // memoize
+    static int node_version[ TP_MAX_NODE ];
+
+    if ( node_version[ node ] )
+    {
+        return node_version[ node ];
+    }
+
+    testpoint_t     tp[ 128 ];
+    resultQueryTP_r result;
+    memset (&result, 0, sizeof (resultQueryTP_r));
+
+    int chk = testpoint_client( );
+
+    if (chk < 0) {
+        printf("testAwgTpInterfaceVersion: testpoint_client() failed with return code %d\n", chk);
+        return 0;
+    }
+
+    CLIENT * clnt = tpMakeHandle (node);
+    if(clnt == NULL)
+    {
+        return 0;
+    }
+
+    if ((querytp_1 (tpNode[node].id, node, TP_ASC_TP_INTERFACE, 128, 0,
+                    0, &result, clnt) == RPC_SUCCESS) && (result.status >= 0)) {
+        printf("found version 3 or older test point interface\n");
+        node_version[node] = 3;
+    }
+    else
+    {
+        printf("found version 4 or newer test point interface\n");
+        node_version[node] = 4;
+    }
+
+    clnt_destroy (clnt);
+    return node_version[node];
+}
\ No newline at end of file
diff --git a/src/gds/awgtpman/testpoint.h b/src/gds/awgtpman/testpoint.h
index 92fedc295c0d419c93ba95d2bb25b4740a4f3c9f..cd7f0072120892651d09f4c6fe2321950ab5e219 100644
--- a/src/gds/awgtpman/testpoint.h
+++ b/src/gds/awgtpman/testpoint.h
@@ -8,6 +8,11 @@
 #include "testpoint_structs.h"
 #include "tconv.h"
 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /** Sets the test point manager address. This function is only
     available when compiling with the _TP_DAQD flag. It will disable
     the default parameter file and set the host address and rpc program
@@ -23,9 +28,10 @@
     @return 0 if successful, <0 otherwise
     @author DS, June 98
 ************************************************************************/
-int tpSetHostAddress (int node, const char* hostname,
-                      unsigned long prognum, unsigned long progver);
-
+int tpSetHostAddress( int           node,
+                      const char*   hostname,
+                      unsigned long prognum,
+                      unsigned long progver );
 
 /** Installs a test point client interface. This function should be
     called prior of using the test point interface. If not, the first
@@ -37,8 +43,7 @@ int tpSetHostAddress (int node, const char* hostname,
     @return 0 if successful, <0 otherwise
     @author DS, June 98
 ************************************************************************/
-int testpoint_client (void);
-
+int testpoint_client( void );
 
 /** Clear test points. This routine clears test points from the
     reflective memory. Test points are cleared in the 6th epoch only.
@@ -51,8 +56,7 @@ int testpoint_client (void);
     @return 0 if successful, <0 otherwise
     @author DS, June 98
 ************************************************************************/
-int tpClear (int node, const testpoint_t tp[], int tplen);
-
+int tpClear( int node, const testpoint_t tp[], int tplen );
 
 /** Terminates a test point client interface.
 
@@ -60,10 +64,7 @@ int tpClear (int node, const testpoint_t tp[], int tplen);
     @return void
     @author DS, June 98
 ************************************************************************/
-void testpoint_cleanup (void);
-
-
-
+void testpoint_cleanup( void );
 
 /** Request test points. The requested test points are made available
     in the reflective memory if enough test point slots are free.
@@ -87,9 +88,12 @@ void testpoint_cleanup (void);
     @return 0 if successful, <0 otherwise
     @author DS, June 98
 ************************************************************************/
-int tpRequest (int node, const testpoint_t tp[], int tplen,
-               tainsec_t timeout, taisec_t* time, int* epoch);
-
+int tpRequest( int               node,
+               const testpoint_t tp[],
+               int               tplen,
+               tainsec_t         timeout,
+               taisec_t*         time,
+               int*              epoch );
 
 /** Request test points by name. This routine is similar to
     tpRequest but accepts channel names of test points. The tpNames
@@ -105,12 +109,10 @@ int tpRequest (int node, const testpoint_t tp[], int tplen,
     @return 0 if successful, <0 otherwise
     @author DS, June 98
 ************************************************************************/
-int tpRequestName (const char* tpNames,
-                   tainsec_t timeout, taisec_t* time, int* epoch);
-
-
-
-
+int tpRequestName( const char* tpNames,
+                   tainsec_t   timeout,
+                   taisec_t*   time,
+                   int*        epoch );
 
 /** Clear test points by names. This routine is similar to tpClear but
     accepts channel names of test points. The tpNames
@@ -123,8 +125,7 @@ int tpRequestName (const char* tpNames,
     @return 0 if successful, <0 otherwise
     @author DS, June 98
 ************************************************************************/
-int tpClearName (const char* tpNames);
-
+int tpClearName( const char* tpNames );
 
 /** Query the test point interface. This routine returns a list of
     all assigned test points in the reflective memory belonging to the
@@ -157,9 +158,12 @@ int tpClearName (const char* tpNames);
     @return Number of read test points if successful, <0 otherwise
     @author DS, June 98
 ************************************************************************/
-int tpQuery (int node, int tpinterface, testpoint_t tp[], int tplen,
-             taisec_t time, int epoch);
-
+int tpQuery( int         node,
+             int         tpinterface,
+             testpoint_t tp[],
+             int         tplen,
+             taisec_t    time,
+             int         epoch );
 
 /** ASCII interface to a test point interface.
 
@@ -170,7 +174,7 @@ int tpQuery (int node, int tpinterface, testpoint_t tp[], int tplen,
     @return reply string
     @author DS, June 98
 ************************************************************************/
-char* tpCommand (const char* cmd);
+char* tpCommand( const char* cmd );
 
 /** ASCII interface to a test point interface.
 
@@ -181,7 +185,7 @@ char* tpCommand (const char* cmd);
     @return 0 if successful, <0 otherwise
     @author DS, June 98
 ************************************************************************/
-int tpcmdline (const char* cmd);
+int tpcmdline( const char* cmd );
 
 /*----------------------------------------------------------------------*/
 /*                                                         		*/
@@ -194,6 +198,24 @@ int tpcmdline (const char* cmd);
 /* Procedure Returns: 0 if successful, <0 if not			*/
 /*                                                         		*/
 /*----------------------------------------------------------------------*/
-int keepAlive (int node);
+int keepAlive( int node );
+
+
+/// Find RPC interface version used by awgtpman
+/// version 4 was introduced about RCG version 4.1.0
+/// all previous interface versions, including for RCG 4.0.1,
+/// are considered version 3.
+/// Version 4 has only two testpoint interfaces: one for excitations and one for
+/// other test points.
+/// Version 3 has 4 testpoint interfaces: the two interfaces of version 4 are
+/// divided between LSC and ASC test points.
+///
+/// \param node the node number to identify
+/// \return the version number, 0 on error
+int testAwgTpInterfaceVersion(int node);
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif // DAQD_TRUNK_TESTPOINT_H
diff --git a/src/gds/awgtpman/testpoint_interface_v3.h b/src/gds/awgtpman/testpoint_interface_v3.h
new file mode 100644
index 0000000000000000000000000000000000000000..bcbe1e79c34d360411968f19b763d71e6410bb10
--- /dev/null
+++ b/src/gds/awgtpman/testpoint_interface_v3.h
@@ -0,0 +1,60 @@
+//
+// Created by erik.vonreis on 5/4/22.
+//
+// defines needed for older version 3 RPC interface, stolen from
+// version 4.0.1
+//
+
+#ifndef DAQD_TRUNK_TESTPOINT_INTERFACE_V3_H
+#define DAQD_TRUNK_TESTPOINT_INTERFACE_V3_H
+
+/** Test point interface id of LSC excitation.
+
+@author DS, September 98
+    @see Testpoint Definition
+        ************************************************************************/
+#define TP_LSC_EX_INTERFACE	0
+
+/** Test point interface id of ASC excitation.
+
+    @author DS, September 98
+    @see Testpoint Definition
+************************************************************************/
+#define TP_ASC_EX_INTERFACE	1
+
+/** Test point interface id of LSC readout.
+
+    @author DS, September 98
+    @see Testpoint Definition
+************************************************************************/
+#define TP_LSC_TP_INTERFACE	2
+
+/** Test point interface id of ASC readout.
+
+    @author DS, September 98
+    @see Testpoint Definition
+************************************************************************/
+#define TP_ASC_TP_INTERFACE	3
+
+
+#define TP_MAX_INTERFACE_V3     4
+
+#define TP_ID_TO_INTERFACE_V3(A) ( \
+	((A) == 0 ? -1 :	    \
+	((A) < TP_ID_LSC_TP_OFS ? TP_LSC_EX_INTERFACE :	    \
+	((A) < TP_ID_ASC_EX_OFS ? TP_LSC_TP_INTERFACE :	    \
+	((A) < TP_ID_ASC_TP_OFS ? TP_ASC_EX_INTERFACE :	    \
+	((A) < TP_ID_DAC_OFS ? TP_ASC_TP_INTERFACE :	    \
+	((A) < TP_ID_DS340_OFS ? TP_DAC_INTERFACE :	    \
+        ((A) < TP_ID_END_OFS ? TP_DS340_INTERFACE :         \
+         -1))))))))
+
+/** Maximum number of entries in the test point index. This number must
+    be greater or equal than any of the individual test point indexes.
+
+@author DS, September 98
+    @see Testpoint Definition
+        ************************************************************************/
+#define TP_MAX_INDEX		64
+
+#endif // DAQD_TRUNK_TESTPOINT_INTERFACE_V3_H
diff --git a/src/gds/awgtpman/testpoint_server.c b/src/gds/awgtpman/testpoint_server.c
index bb469478308b5cb661dcb0cd6246019cd6642bdb..330f689de1f72be4fbfcb25f7c86819888e6b7ab 100644
--- a/src/gds/awgtpman/testpoint_server.c
+++ b/src/gds/awgtpman/testpoint_server.c
@@ -458,7 +458,7 @@ static char *versionId = "Version $Id$" ;
          int		ret;
          TP_r		tpcln;
          tpcln.TP_r_len = -result->status;
-         tpcln.TP_r_val = malloc (tpcln.TP_r_len * sizeof(testpoint_t));
+         tpcln.TP_r_val = malloc (tpcln.TP_r_len * sizeof(tpcln.TP_r_val[0]));
          if (tpcln.TP_r_val != 0) {
             for (i = 0; i < tpcln.TP_r_len; i++) {
                tpcln.TP_r_val[i] = tp.TP_r_val[i];
@@ -728,15 +728,24 @@ static char *versionId = "Version $Id$" ;
          result->status = -2;
          return TRUE;
       }
+
+      testpoint_t *testpoints;
    
       /* allocate memory for result array */
-      result->tp.TP_r_val = malloc (tplen * sizeof (testpoint_t));
+      result->tp.TP_r_val = malloc (tplen * sizeof (result->tp.TP_r_val[0]));
       if (result->tp.TP_r_val == NULL) {
-         gdsDebug("querytp_1_svc malloc(tplen * sizeof(testpoint_t)) failed.") ; /* JCB */
+         gdsDebug("querytp_1_svc malloc(tplen * sizeof(testpoint_t)) [1] failed.") ; /* JCB */
          result->status = -2;
          return FALSE;
       }
+      testpoints = malloc(tplen * sizeof(testpoint_t));
+      if (testpoints == NULL) {
+          gdsDebug("querytp_1_svc malloc(tplen * sizeof(testpoint_t)) [1] failed.") ; /* JCB */
+          result->status = -2;
+          return FALSE;
+      }
       result->tp.TP_r_len = tplen;
+
    
       /* fix time if needed */
       if (time == 0) {
@@ -747,10 +756,16 @@ static char *versionId = "Version $Id$" ;
    
       /* get index directly from test point client interface */
       result->status = 
-         tpGetIndexDirect (node, tpinterface, (testpoint_t *)result->tp.TP_r_val,
+         tpGetIndexDirect (node, tpinterface, testpoints,
                           result->tp.TP_r_len, time, epoch);
       if (result->status >= 0) {
          result->tp.TP_r_len = result->status;
+
+         // copy over resutls to RPC structure
+         for(int i=0; i<result->tp.TP_r_len; ++i)
+         {
+             result->tp.TP_r_val[i] = testpoints[i];
+         }
       }
       else {
          free (result->tp.TP_r_val);
@@ -777,7 +792,7 @@ static char *versionId = "Version $Id$" ;
          }
       }
    #endif
-   
+      free(testpoints);
       return TRUE;
    #endif
    }
@@ -962,21 +977,28 @@ static char *versionId = "Version $Id$" ;
       gdsChnInfo_t	chn;		/* channel info structure */
       int		tp_node;	/* node of test point name */
       char *		saveptr;
+      testpoint_t *     testpoints;
    
       /* allocate memory */
       buf = malloc (strlen (tpNames) + 2);
-      if (!buf) /* JCB */
+      if (NULL == buf) /* JCB */
       {
         gdsDebug("tpName2Index malloc(strlen(tpNames)+2) failed.") ;
         return -1 ;
       }
-      tp->TP_r_val = malloc (_MAX_TPNAMES * sizeof (testpoint_t));
-      if ((tp->TP_r_val == NULL) || (buf == NULL)) {
-         gdsDebug("tpName2Index malloc(_MAX_TPNAMES...) failed") ; /* JCB */
+      tp->TP_r_val = malloc (_MAX_TPNAMES * sizeof tp->TP_r_val[0]);
+      if (tp->TP_r_val == NULL) {
+         gdsDebug("tpName2Index malloc(_MAX_TPNAMES...) [1] failed") ; /* JCB */
          free (buf);
-         free (tp->TP_r_val);
          return -1;
       }
+      testpoints = malloc(_MAX_TPNAMES * sizeof(testpoint_t));
+      if (testpoints == NULL) {
+          gdsDebug("tpName2Index malloc(_MAX_TPNAMES...) [2] failed") ; /* JCB */
+          free (buf);
+          free (tp->TP_r_val);
+          return -1;
+      }
       tp->TP_r_len = 0;
       strcpy (buf, tpNames);
    
@@ -985,17 +1007,24 @@ static char *versionId = "Version $Id$" ;
       while ((p != NULL) && (tp->TP_r_len < _MAX_TPNAMES)) {
 	 printf("tpName2Index checking %s\n", p);
          if ((gdsChannelInfo (p, &chn) == 0) &&
-            (tpIsValid (&chn, &tp_node, (testpoint_t *)tp->TP_r_val + tp->TP_r_len)) &&
+            (tpIsValid (&chn, &tp_node, testpoints + tp->TP_r_len)) &&
             (node == tp_node)) {
             printf ("%s is tp %i (node %i)\n", p, 
-                   tp->TP_r_val[tp->TP_r_len], 
+                   testpoints[tp->TP_r_len],
                    tp_node);
             tp->TP_r_len++;
          }
 	 printf("node=%d; tp_node=%d\n", node, tp_node);
          p = strtok_r (NULL, " \t\n", &saveptr);
-      } 
-   
+      }
+
+      /* copy back into rpc structure */
+      for(int i=0; i < tp->TP_r_len; ++i)
+      {
+          tp->TP_r_val[i] = testpoints[i];
+      }
+
+      free(testpoints);
       free (buf);
       return 0;
    }
diff --git a/src/gds/awgtpman/testpointinfo.c b/src/gds/awgtpman/testpointinfo.c
index 3d7a6f6f8e86ab0c0525732e0520a1fd880be91c..8c456a24aba2d3b4ea0d266e843271c4612e9e96 100644
--- a/src/gds/awgtpman/testpointinfo.c
+++ b/src/gds/awgtpman/testpointinfo.c
@@ -52,7 +52,7 @@ static char *versionId = "Version $Id$" ;
          (TP_ID_TO_INTERFACE (chn->chNum) >= 0)) {
          /* copy return arguments */
          if (node != NULL) {
-            *node = chn->rmId;
+            *node = chn->chGroup;
          }
          if (tp != NULL) {
             *tp = chn->chNum;
diff --git a/src/gds/rpc/rtestpoint.x b/src/gds/rpc/rtestpoint.x
index 788ae3e039104cfd7ef18d3661194326a05e517c..af139f688749f995b54627bd684b9e9e702487d3 100644
--- a/src/gds/rpc/rtestpoint.x
+++ b/src/gds/rpc/rtestpoint.x
@@ -18,11 +18,7 @@
 %#include "dtt/rpcinc.h"
 
 /* list of test point */
-#if defined(_ADVANCED_LIGO) && !defined(COMPAT_INITIAL_LIGO)
 typedef unsigned int TP_r<>;
-#else
-typedef unsigned short TP_r<>;
-#endif
 
 /* request result */
 struct resultRequestTP_r {
diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt
index eb0cb1d95468c5ac881280a33ed468cbd81d314b..ddca6375f54af1428a309f9e292cfa2b5ce38b06 100644
--- a/src/include/CMakeLists.txt
+++ b/src/include/CMakeLists.txt
@@ -3,6 +3,7 @@ install(FILES
             daq_core.h
             daq_core_defs.h
             daq_data_types.h
+            portableInline.h
         DESTINATION
             include/advligorts
         )
diff --git a/src/include/cds_types.h b/src/include/cds_types.h
index e5848f3cc8d4d04ef0f56c0fd7c277b8123219ee..cef335697b5c4cd2a143a5ad9bff551317d8a2e0 100644
--- a/src/include/cds_types.h
+++ b/src/include/cds_types.h
@@ -1,6 +1,8 @@
 #ifndef LIGO_CDS_TYPES_H
 #define LIGO_CDS_TYPES_H
 
+#include "drv/cdsHardware.h"
+
 typedef struct adcInfo_t
 {
     int adcWait;
diff --git a/src/include/commData3.h b/src/include/commData3.h
index 68614dfcaf092850df5e4ec968f10cf741eeb16e..7a414da96cc02ab1973121b5fbb4b4e956979cf9 100644
--- a/src/include/commData3.h
+++ b/src/include/commData3.h
@@ -112,21 +112,17 @@ typedef struct CDS_DOLPHIN_INFO
 #define IPC_RFM_BLOCK_SIZE ( sizeof( struct CDS_IPC_XMIT ) * MAX_IPC )
 #define IPC_RFM_XFER_SIZE ( sizeof( struct CDS_IPC_XMIT ) * MAX_IPC_RFM )
 
-// decide between inline or not for commData functions
-  // initialize the CommDataState struct
-  // send data
-  //   the cycle counter is included in the checksum,
-  //   and is used to index the ring buffer
-#ifdef COMMDATA_INLINE
-#  include "../fe/commData3.c"
+#ifdef __cplusplus
+extern "C" {
 #endif
-#ifdef COMMDATA_USP
-#  include "../fe/commDataUsp.c"
+
+void commData3Init(int connects, int rate, CDS_IPC_INFO ipcInfo[] );
+void commData3Send(int connects, CDS_IPC_INFO ipcInfo[], int timeSec, int cycle);
+void commData3Receive(int connects, CDS_IPC_INFO ipcInfo[], int timeSec, int cycle);
+
+#ifdef __cplusplus
+}
 #endif
 
-// void commData3Init(int connects, int rate, CDS_IPC_INFO ipcInfo[], long
-// rfmAddress[]); void commData3Send(int connects, CDS_IPC_INFO ipcInfo[], int
-// timeSec, int cycle); void commData3Receive(int connects, CDS_IPC_INFO
-// ipcInfo[], int timeSec, int cycle);
 
 #endif // __COMMDATA3_H__
diff --git a/src/include/controller.c b/src/include/controller.c
new file mode 100644
index 0000000000000000000000000000000000000000..e2fd98dfde268b249c62b9578ac3a6db7630c2e6
--- /dev/null
+++ b/src/include/controller.c
@@ -0,0 +1,234 @@
+
+#include "controller.h"
+
+adcInfo_t     adcinfo;
+dacInfo_t     dacinfo;
+timing_diag_t timeinfo;
+
+/// 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;
+unsigned int     ipcErrBits = 0;
+int              cardCountErr = 0;
+struct rmIpcStr* daqPtr;
+int dacOF[ MAX_DAC_MODULES ]; /// @param dacOF[]  DAC overrange counters
+
+char daqArea[ DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers
+int  cpuId = 1;
+
+// 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 ];
+
+
+
+char*          build_date = __DATE__ " " __TIME__;
+volatile char* _epics_shm; ///< Ptr to EPICS shared memory area
+volatile TESTPOINT_CFG  *_tp_shm;
+volatile AWG_DATA *_awg_shm;
+volatile char*          _ipc_shm; ///< Ptr to inter-process communication area
+volatile char*          _daq_shm; ///< Ptr to frame builder comm shared mem area
+// char*          _gds_shm; ///< Ptr to frame builder comm shared mem area
+volatile char*          _shmipc_shm; ///< Ptr to IOP I/O data to/from User app shared mem area
+volatile char*          _io_shm; ///< Ptr to user space I/O area
+int            daq_fd; ///< File descriptor to share memory file
+
+long                      daqBuffer; // Address for daq dual buffers in daqLib.c
+CDS_HARDWARE              cdsPciModules; // Structure of PCI hardware addresses
+volatile IO_MEM_DATA*     ioMemData;
+volatile IO_MEM_DATA_IOP* ioMemDataIop;
+volatile int              vmeDone = 0; // Code kill command
+volatile int              fe_status_return = 0; // fe code status return to module_exit
+volatile int              fe_status_return_subcode = 0; // fe code status return to module_exit
+volatile int              stop_working_threads = 0;
+
+
+// Following define string names of above modules
+// Used to print info to syslog
+#define CDS_CARD_TYPES  16
+char _cdscardtypename[ CDS_CARD_TYPES ][ 40 ] = {
+        "GSC_16AI64SSA", "GSC_18AISS6C", "GSC_16AO16",  "GSC_20AO8",
+        "CON_32DO",      "ACS_16DIO",    "ACS_8DIO",    "GSC_18AI32SSC1M",
+        "GSC_18AO8",     "ACS_24DIO",    "CON_1616DIO", "CON_6464DIO",
+        "CDO64",         "CDI64",        "LPTC",        "GSC_18AI64SSC"
+};
+
+/// Testpoints which are not part of filter modules
+double* testpoint[ GDS_MAX_NFM_TP ];
+#ifndef NO_DAQ
+DAQ_RANGE daq; // Range settings for daqLib.c
+int       numFb = 0;
+int       fbStat[ 2 ] = { 0, 0 }; // Status of DAQ backend computer
+/// Excitation points which are not part of filter modules
+double xExc[ GDS_MAX_NFM_EXC ]; // GDS EXC not associated with filter modules
+#endif
+/// 1/16 sec cycle counters for DAQS
+int subcycle = 0; // Internal cycle counter
+/// DAQ cycle counter (0-15)
+unsigned int daqCycle; // DAQS cycle counter
+
+// Sharded memory discriptors
+int                 wfd, ipc_fd;
+volatile CDS_EPICS* pLocalEpics; // Local mem ptr to EPICS control data
+volatile char*      pEpicsDaq; // Local mem ptr to EPICS daq data
+
+
+// Filter module variables
+/// Standard Filter Module Structure
+FILT_MOD dsp[ NUM_SYSTEMS ]; // SFM structure.
+/// Pointer to local memory SFM Structure
+FILT_MOD* dspPtr[ NUM_SYSTEMS ]; // SFM structure pointer.
+/// Pointer to SFM in shared memory.
+FILT_MOD* pDsp[ NUM_SYSTEMS ]; // Ptr to SFM in shmem.
+/// Pointer to filter coeffs local memory.
+COEF dspCoeff[ NUM_SYSTEMS ]; // Local mem for SFM coeffs.
+/// Pointer to filter coeffs shared memory.
+VME_COEF* pCoeff[ NUM_SYSTEMS ]; // Ptr to SFM coeffs in shmem
+
+
+// ADC Variables
+/// Array of ADC values
+#ifdef IOP_MODEL
+double dWord[ MAX_ADC_MODULES ][ MAX_ADC_CHN_PER_MOD ][ 16 ]; // ADC read values
+#else
+double dWord[ MAX_ADC_MODULES ][ MAX_ADC_CHN_PER_MOD ]; // ADC read values
+#endif
+/// List of ADC channels used by this app. Used to determine if downsampling
+/// required.
+unsigned int dWordUsed[ MAX_ADC_MODULES ]
+                      [ MAX_ADC_CHN_PER_MOD ]; // ADC chans used by app code
+
+// DAC Variables
+/// Enables writing of DAC values; Used with DACKILL parts..
+int iopDacEnable; // Returned by feCode to allow writing values or zeros to DAC
+                  // modules
+int dacChanErr[ MAX_DAC_MODULES ];
+#ifdef IOP_MODEL
+int dacOutBufSize[ MAX_DAC_MODULES ];
+#endif
+/// Array of DAC output values.
+double dacOut[ MAX_DAC_MODULES ][ MAX_DAC_CHN_PER_MOD ]; // DAC output values
+/// DAC output values returned to EPICS
+int dacOutEpics[ MAX_DAC_MODULES ]
+               [ MAX_DAC_CHN_PER_MOD ]; // DAC outputs reported back to EPICS
+/// DAC channels used by an app.; determines up sampling required.
+unsigned int dacOutUsed[ MAX_DAC_MODULES ]
+                       [ MAX_DAC_CHN_PER_MOD ]; // DAC chans used by app code
+/// Array of DAC overflow (overrange) counters.
+int overflowDac[ MAX_DAC_MODULES ]
+               [ MAX_DAC_CHN_PER_MOD ]; // DAC overflow diagnostics
+/// DAC outputs stored as floats, to be picked up as test points
+double floatDacOut[ 160 ]; // DAC outputs stored as floats, to be picked up as
+                           // test points
+
+/// Counter for total ADC/DAC overflows
+int overflowAcc = 0; // Total ADC/DAC overflow counter
+
+
+#ifndef IOP_MODEL
+// Variables for Digital I/O board values
+// DIO board I/O is handled in control (user) applications for timing reasons
+// (longer I/O access times)
+/// Read value from Acces I/O 24bit module
+int dioInput[ MAX_DIO_MODULES ];
+/// Write value to Acces I/O 24bit module
+int dioOutput[ MAX_DIO_MODULES ];
+/// Last value written to Acces I/O 24bit module
+int dioOutputHold[ MAX_DIO_MODULES ];
+
+int rioInput1[ MAX_DIO_MODULES ];
+int rioInputInput[ MAX_DIO_MODULES ];
+int rioInputOutput[ MAX_DIO_MODULES ];
+int rioOutput[ MAX_DIO_MODULES ];
+int rioOutputHold[ MAX_DIO_MODULES ];
+int rioOutput1[ MAX_DIO_MODULES ];
+int rioOutputHold1[ MAX_DIO_MODULES ];
+
+// Contec 32 bit output modules
+/// Read value from Contec 32bit I/O module
+unsigned int CDO32Input[ MAX_DIO_MODULES ];
+/// Write value to Contec 32bit I/O module
+unsigned int CDO32Output[ MAX_DIO_MODULES ];
+
+#endif
+
+// Up/Down Sampling Filter Coeffs
+// 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
+/* Recalculated filters in biquad form */
+
+/* Oversamping base rate is 64K */
+/* Coeffs for the 2x downsampling (32K system) filter */
+double feCoeff2x[ 9 ] = {
+    0.053628649721183,   0.2568759660371100, -0.3225906481359000,
+    1.2568801238621801,  1.6774135096891700, -0.2061764045745400,
+    -1.0941543149527400, 2.0846376586498803, 2.1966597482716801
+};
+
+/*
+ * DCC docs of note
+ * T1600066 - New RCG 3.0 Decimation (IOP Upsampling / Downsampling) Filter for 16 kHz models
+ * T1500075 - A Note on the RCG Decimation (IOP Upsampling / Downsampling) Filters (Prior to RCG 3.0)
+ */
+
+/* RCG V3.0 Coeffs for the 4x downsampling (16K system) filter */
+double 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
+double 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) */
+/* 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};
+
+
+/* Coeffs for the 32x downsampling filter (2K system) per Brian Lantz May 5,
+ * 2009 */
+double feCoeff32x[ 9 ] = {
+     0.010581064947739,      0.90444302586137004,  -0.0063413204375699639,
+    -0.056459743474659874,  0.032075154877300172, 0.92390910024681006,
+    -0.0097523655540199261, 0.077383808424050127, 0.14238741130302013
+};
+
+// 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 //OVERSAMPLE
+
diff --git a/src/include/controller.h b/src/include/controller.h
index 7bd2375440f32012317491e900452cdfb239e295..64ac95800d60e3c5bd676d935ca206ae7044d08a 100644
--- a/src/include/controller.h
+++ b/src/include/controller.h
@@ -1,40 +1,48 @@
 #ifndef LIGO_CONTROLLER_H
 #define LIGO_CONTROLLER_H
 
-adcInfo_t     adcinfo;
-dacInfo_t     dacinfo;
-timing_diag_t timeinfo;
+#include "cds_types.h" //adcInfo_t, dacInfo_t, timing_diag_t
+#include "fm10Gen_types.h" //FILT_MOD 
+#include "daq_core_defs.h" //DAQ_DCU_SIZE
+
+#include "../shmem/shmem_all.h" //TESTPOINT_CFG, AWG_DATA
+
+
+extern adcInfo_t     adcinfo;
+extern dacInfo_t     dacinfo;
+extern timing_diag_t timeinfo;
 
 /// Maintains present cycle count within a one second period.
-int          cycleNum = 0;
-unsigned int odcStateWord = 0xffff;
+extern int          cycleNum;
+extern unsigned int odcStateWord;
 /// 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
+extern int          out_buf_size; // test checking DAC buffer size
+extern unsigned int cycle_gps_time; // Time at which ADCs triggered
+extern unsigned int cycle_gps_event_time; // Time at which ADCs triggered
+extern unsigned int cycle_gps_ns;
+extern unsigned int cycle_gps_event_ns;
+extern unsigned int gps_receiver_locked; // Lock/unlock flag for GPS time card
 /// GPS time in GPS seconds
-unsigned int     timeSec = 0;
-unsigned int     timeSecDiag = 0;
-unsigned int     ipcErrBits = 0;
-int              cardCountErr = 0;
-struct rmIpcStr* daqPtr;
-int dacOF[ MAX_DAC_MODULES ]; /// @param dacOF[]  DAC overrange counters
+extern unsigned int     timeSec;
+extern unsigned int     timeSecDiag;
+extern unsigned int     ipcErrBits;
+extern int              cardCountErr;
+extern struct rmIpcStr* daqPtr;
+extern int dacOF[ MAX_DAC_MODULES ]; /// @param dacOF[]  DAC overrange counters
 
-char daqArea[ DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers
-int  cpuId = 1;
-
-#define MX_OK 3
+extern char daqArea[ DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers
+extern int  cpuId;
 
 // Initial diag reset flag
-int initialDiagReset = 1;
+extern int initialDiagReset;
 
 // Cache flushing mumbo jumbo suggested by Thomas Gleixner, it is probably
 // useless Did not see any effect
-char fp[ 64 * 1024 ];
+extern char fp[ 64 * 1024 ];
+
+#define MX_OK 3
+
 
 // The following bits define the EPICS STATE_WORD
 #define FE_ERROR_TIMING 0x2 // bit 1
@@ -264,135 +272,132 @@ char fp[ 64 * 1024 ];
 #define PERIOD_COUNT 1
 #define MAX_UDELAY 19999
 
-#include "../shmem/shmem_all.h"
-
-char*          build_date = __DATE__ " " __TIME__;
-extern int     iop_rfm_valid;
-volatile char* _epics_shm; ///< Ptr to EPICS shared memory area
-volatile TESTPOINT_CFG  *_tp_shm;
-volatile AWG_DATA *_awg_shm;
-char*          _ipc_shm; ///< Ptr to inter-process communication area
-char*          _daq_shm; ///< Ptr to frame builder comm shared mem area
-// char*          _gds_shm; ///< Ptr to frame builder comm shared mem area
-char*          _shmipc_shm; ///< Ptr to IOP I/O data to/from User app shared mem area
-char*          _io_shm; ///< Ptr to user space I/O area
-int            daq_fd; ///< File descriptor to share memory file
-
-long                      daqBuffer; // Address for daq dual buffers in daqLib.c
-CDS_HARDWARE              cdsPciModules; // Structure of PCI hardware addresses
-volatile IO_MEM_DATA*     ioMemData;
-volatile IO_MEM_DATA_IOP* ioMemDataIop;
-volatile int              vmeDone = 0; // Code kill command
-volatile int              fe_status_return = 0; // fe code status return to module_exit
-volatile int              fe_status_return_subcode = 0; // fe code status return to module_exit
-volatile int              stop_working_threads = 0;
-
-extern unsigned int cpu_khz;
+
+extern char*          build_date ;
+extern volatile char* _epics_shm; ///< Ptr to EPICS shared memory area
+extern volatile TESTPOINT_CFG  *_tp_shm;
+extern volatile AWG_DATA *_awg_shm;
+extern volatile char*          _ipc_shm; ///< Ptr to inter-process communication area
+extern volatile char*          _daq_shm; ///< Ptr to frame builder comm shared mem area
+//extern  char*          _gds_shm; ///< Ptr to frame builder comm shared mem area
+extern volatile char*          _shmipc_shm; ///< Ptr to IOP I/O data to/from User app shared mem area
+extern volatile char*          _io_shm; ///< Ptr to user space I/O area
+extern int            daq_fd; ///< File descriptor to share memory file
+
+extern long                      daqBuffer; // Address for daq dual buffers in daqLib.c
+extern CDS_HARDWARE              cdsPciModules; // Structure of PCI hardware addresses
+extern volatile IO_MEM_DATA*     ioMemData;
+extern volatile IO_MEM_DATA_IOP* ioMemDataIop;
+extern volatile int              vmeDone ; // Code kill command
+extern volatile int              fe_status_return; // fe code status return to module_exit
+extern volatile int              fe_status_return_subcode; // fe code status return to module_exit
+extern volatile int              stop_working_threads;
+
+extern int     iop_rfm_valid; //From mbuf kernel module
+extern unsigned int cpu_khz; //From linux kernel tsc.c
 
 // Following define string names of above modules
 // Used to print info to syslog
 #define CDS_CARD_TYPES  16
-char _cdscardtypename[ CDS_CARD_TYPES ][ 40 ] = {
-        "GSC_16AI64SSA", "GSC_18AISS6C", "GSC_16AO16",  "GSC_20AO8",
-        "CON_32DO",      "ACS_16DIO",    "ACS_8DIO",    "GSC_18AI32SSC1M",
-        "GSC_18AO8",     "ACS_24DIO",    "CON_1616DIO", "CON_6464DIO",
-        "CDO64",         "CDI64",        "LPTC",        "GSC_18AI64SSC"
-};
+extern char _cdscardtypename[ CDS_CARD_TYPES ][ 40 ];
 
 
 /// Testpoints which are not part of filter modules
-double* testpoint[ GDS_MAX_NFM_TP ];
+extern double* testpoint[ GDS_MAX_NFM_TP ];
 #ifndef NO_DAQ
-DAQ_RANGE daq; // Range settings for daqLib.c
-int       numFb = 0;
-int       fbStat[ 2 ] = { 0, 0 }; // Status of DAQ backend computer
+extern DAQ_RANGE daq; // Range settings for daqLib.c
+extern int       numFb;
+extern int       fbStat[ 2 ]; // Status of DAQ backend computer
 /// Excitation points which are not part of filter modules
-double xExc[ GDS_MAX_NFM_EXC ]; // GDS EXC not associated with filter modules
+extern double xExc[ GDS_MAX_NFM_EXC ]; // GDS EXC not associated with filter modules
 #endif
 /// 1/16 sec cycle counters for DAQS
-int subcycle = 0; // Internal cycle counter
+extern int subcycle; // Internal cycle counter
 /// DAQ cycle counter (0-15)
-unsigned int daqCycle; // DAQS cycle counter
+extern unsigned int daqCycle; // DAQS cycle counter
 
 // Sharded memory discriptors
-int                 wfd, ipc_fd;
-volatile CDS_EPICS* pLocalEpics; // Local mem ptr to EPICS control data
-volatile char*      pEpicsDaq; // Local mem ptr to EPICS daq data
+extern int wfd;
+extern int ipc_fd;
+extern volatile CDS_EPICS* pLocalEpics; // Local mem ptr to EPICS control data
+extern volatile char*      pEpicsDaq; // Local mem ptr to EPICS daq data
 
 // Filter module variables
 /// Standard Filter Module Structure
-FILT_MOD dsp[ NUM_SYSTEMS ]; // SFM structure.
+extern FILT_MOD dsp[ NUM_SYSTEMS ]; // SFM structure.
 /// Pointer to local memory SFM Structure
-FILT_MOD* dspPtr[ NUM_SYSTEMS ]; // SFM structure pointer.
+extern FILT_MOD* dspPtr[ NUM_SYSTEMS ]; // SFM structure pointer.
 /// Pointer to SFM in shared memory.
-FILT_MOD* pDsp[ NUM_SYSTEMS ]; // Ptr to SFM in shmem.
+extern FILT_MOD* pDsp[ NUM_SYSTEMS ]; // Ptr to SFM in shmem.
 /// Pointer to filter coeffs local memory.
-COEF dspCoeff[ NUM_SYSTEMS ]; // Local mem for SFM coeffs.
+extern COEF dspCoeff[ NUM_SYSTEMS ]; // Local mem for SFM coeffs.
 /// Pointer to filter coeffs shared memory.
-VME_COEF* pCoeff[ NUM_SYSTEMS ]; // Ptr to SFM coeffs in shmem
+extern VME_COEF* pCoeff[ NUM_SYSTEMS ]; // Ptr to SFM coeffs in shmem
 
 // ADC Variables
 /// Array of ADC values
 #ifdef IOP_MODEL
-double dWord[ MAX_ADC_MODULES ][ MAX_ADC_CHN_PER_MOD ][ 16 ]; // ADC read values
+extern double dWord[ MAX_ADC_MODULES ][ MAX_ADC_CHN_PER_MOD ][ 16 ]; // ADC read values
 #else
-double dWord[ MAX_ADC_MODULES ][ MAX_ADC_CHN_PER_MOD ]; // ADC read values
+extern double dWord[ MAX_ADC_MODULES ][ MAX_ADC_CHN_PER_MOD ]; // ADC read values
 #endif
 /// List of ADC channels used by this app. Used to determine if downsampling
 /// required.
-unsigned int dWordUsed[ MAX_ADC_MODULES ]
-                      [ MAX_ADC_CHN_PER_MOD ]; // ADC chans used by app code
+extern unsigned int dWordUsed[ MAX_ADC_MODULES ]
+                             [ MAX_ADC_CHN_PER_MOD ]; // ADC chans used by app code
 
 // DAC Variables
 /// Enables writing of DAC values; Used with DACKILL parts..
-int iopDacEnable; // Returned by feCode to allow writing values or zeros to DAC
+extern int iopDacEnable; // Returned by feCode to allow writing values or zeros to DAC
                   // modules
-int dacChanErr[ MAX_DAC_MODULES ];
+extern int dacChanErr[ MAX_DAC_MODULES ];
 #ifdef IOP_MODEL
-int dacOutBufSize[ MAX_DAC_MODULES ];
+extern int dacOutBufSize[ MAX_DAC_MODULES ];
 #endif
 /// Array of DAC output values.
-double dacOut[ MAX_DAC_MODULES ][ MAX_DAC_CHN_PER_MOD ]; // DAC output values
+extern double dacOut[ MAX_DAC_MODULES ][ MAX_DAC_CHN_PER_MOD ]; // DAC output values
 /// DAC output values returned to EPICS
-int dacOutEpics[ MAX_DAC_MODULES ]
-               [ MAX_DAC_CHN_PER_MOD ]; // DAC outputs reported back to EPICS
+extern int dacOutEpics[ MAX_DAC_MODULES ]
+                      [ MAX_DAC_CHN_PER_MOD ]; // DAC outputs reported back to EPICS
 /// DAC channels used by an app.; determines up sampling required.
-unsigned int dacOutUsed[ MAX_DAC_MODULES ]
-                       [ MAX_DAC_CHN_PER_MOD ]; // DAC chans used by app code
+extern unsigned int dacOutUsed[ MAX_DAC_MODULES ]
+                              [ MAX_DAC_CHN_PER_MOD ]; // DAC chans used by app code
 /// Array of DAC overflow (overrange) counters.
-int overflowDac[ MAX_DAC_MODULES ]
-               [ MAX_DAC_CHN_PER_MOD ]; // DAC overflow diagnostics
+extern int overflowDac[ MAX_DAC_MODULES ]
+                      [ MAX_DAC_CHN_PER_MOD ]; // DAC overflow diagnostics
 /// DAC outputs stored as floats, to be picked up as test points
-double floatDacOut[ 160 ]; // DAC outputs stored as floats, to be picked up as
+extern double floatDacOut[ 160 ]; // DAC outputs stored as floats, to be picked up as
                            // test points
 
 /// Counter for total ADC/DAC overflows
-int overflowAcc = 0; // Total ADC/DAC overflow counter
+extern int overflowAcc; // Total ADC/DAC overflow counter
 
 #ifndef IOP_MODEL
 // Variables for Digital I/O board values
 // DIO board I/O is handled in control (user) applications for timing reasons
 // (longer I/O access times)
 /// Read value from Acces I/O 24bit module
-int dioInput[ MAX_DIO_MODULES ];
+extern int dioInput[ MAX_DIO_MODULES ];
 /// Write value to Acces I/O 24bit module
-int dioOutput[ MAX_DIO_MODULES ];
+extern int dioOutput[ MAX_DIO_MODULES ];
 /// Last value written to Acces I/O 24bit module
-int dioOutputHold[ MAX_DIO_MODULES ];
+extern int dioOutputHold[ MAX_DIO_MODULES ];
 
-int rioInputOutput[ MAX_DIO_MODULES ];
-int rioOutput[ MAX_DIO_MODULES ];
-int rioOutputHold[ MAX_DIO_MODULES ];
+extern int rioInputOutput[ MAX_DIO_MODULES ];
+extern int rioOutput[ MAX_DIO_MODULES ];
+extern int rioOutputHold[ MAX_DIO_MODULES ];
+
+extern int rioInput1[ MAX_DIO_MODULES ];
+extern int rioOutput1[ MAX_DIO_MODULES ];
+extern int rioOutputHold1[ MAX_DIO_MODULES ];
+extern int rioInputInput[ MAX_DIO_MODULES ];
 
-int rioInput1[ MAX_DIO_MODULES ];
-int rioOutput1[ MAX_DIO_MODULES ];
-int rioOutputHold1[ MAX_DIO_MODULES ];
 
 // Contec 32 bit output modules
 /// Read value from Contec 32bit I/O module
-unsigned int CDO32Input[ MAX_DIO_MODULES ];
+extern unsigned int CDO32Input[ MAX_DIO_MODULES ];
 /// Write value to Contec 32bit I/O module
-unsigned int CDO32Output[ MAX_DIO_MODULES ];
+extern unsigned int CDO32Output[ MAX_DIO_MODULES ];
 
 #endif
 
@@ -405,57 +410,23 @@ unsigned int CDO32Output[ MAX_DIO_MODULES ];
 
 /* 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
-};
-
-/*
- * DCC docs of note
- * T1600066 - New RCG 3.0 Decimation (IOP Upsampling / Downsampling) Filter for 16 kHz models
- * T1500075 - A Note on the RCG Decimation (IOP Upsampling / Downsampling) Filters (Prior to RCG 3.0)
- */
+extern double __attribute__( ( unused ) ) feCoeff2x[ 9 ];
 
 /* 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};
+extern double __attribute__( ( unused ) ) feCoeff4x[ 9 ];
 
 //
 // 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) */
-/* 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};
+extern double __attribute__( ( unused ) ) feCoeff16x[ 9 ];
 
 
 /* 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
-};
+extern double __attribute__( ( unused ) ) feCoeff32x[ 9 ];
 
 // History buffers for oversampling filters
-double dHistory[ ( MAX_ADC_MODULES * 32 ) ][ MAX_HISTRY ];
-double dDacHistory[ ( MAX_DAC_MODULES * 16 ) ][ MAX_HISTRY ];
+extern double dHistory[ ( MAX_ADC_MODULES * 32 ) ][ MAX_HISTRY ];
+extern double dDacHistory[ ( MAX_DAC_MODULES * 16 ) ][ MAX_HISTRY ];
 
 #else
 
diff --git a/src/include/controllerko.c b/src/include/controllerko.c
new file mode 100644
index 0000000000000000000000000000000000000000..e341d795a5839c90da6ed0e6488e132aa355cf61
--- /dev/null
+++ b/src/include/controllerko.c
@@ -0,0 +1,25 @@
+#include "controllerko.h"
+
+// 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 receiver 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;
+
diff --git a/src/include/controllerko.h b/src/include/controllerko.h
index a4c8a249dea3b9db066b991788608a6dd8b5af9c..2b6900b3d4027fff875e0fe4031c69229f519132 100644
--- a/src/include/controllerko.h
+++ b/src/include/controllerko.h
@@ -1,69 +1,30 @@
 #ifndef LIGO_CONTROLLERKO_H
-#define LIGO_CONTROLLERKO_H_
+#define LIGO_CONTROLLERKO_H
 
-#include <linux/version.h>
-#include <linux/init.h>
-#undef printf
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <asm/delay.h>
-#include <asm/cacheflush.h>
-
-#include <linux/slab.h>
-/// Can't use printf in kernel module so redefine to use Linux printk function
-#define printf printk
-#include <drv/cdsHardware.h>
-#include "inlineMath.h"
-
-#include <asm/processor.h>
-#include <asm/cacheflush.h>
-
-// Code can be run without shutting down CPU by changing this compile flag
-#ifndef NO_CPU_SHUTDOWN
-// extern long ligo_get_gps_driver_offset(void);
-#endif
-
-#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 "cds_types.h"
-#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 "../fe/timing_kernel.h" // timing module / IRIG-B  functions
-#include "../fe/timing_common.h"
-
-#include "drv/inputFilterModule.h"
-#include "drv/inputFilterModule1.h"
+#include "drv/cdsHardware.h" //MAX_DIO_MODULES
 
 // Contec 64 input bits plus 64 output bits (Standard for aLIGO)
 /// Contec6464 input register values
-unsigned int CDIO6464InputInput[ MAX_DIO_MODULES ]; // Binary input bits
+extern 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
+extern 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
+extern unsigned int CDIO6464Output[ MAX_DIO_MODULES ]; // Binary output bits
 
 // This Contect 16 input / 16 output DIO card is used to control timing receiver by
 // IOP
 /// Contec1616 input register values
-unsigned int CDIO1616InputInput[ MAX_DIO_MODULES ]; // Binary input bits
+extern 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
+extern 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
+extern 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
+extern 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;
+extern int tdsCount;
 
 
 #endif //LIGO_CONTROLLERKO_H
diff --git a/src/include/crc.h b/src/include/crc.h
index f5d186a8085b6c53ea5863fb0ed5f46b0c486ebf..d5a107ed0d2184c2d7cda3ae28d2512f046a87fc 100644
--- a/src/include/crc.h
+++ b/src/include/crc.h
@@ -1,10 +1,22 @@
 #ifndef LIGO_CRC_H
 #define LIGO_CRC_H
+/// @file crc.h
+/// @brief Contains prototype defs for CRC checking functions 
+//         found in drv/crc.c
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 
-///	@file crc.h
-///	@brief Contains prototype defs for CRC checking functions found in
-////drv/crc.c
 unsigned int crc_ptr( char* cp, unsigned int bytes, unsigned int crc );
 unsigned int crc_len( unsigned int bytes, unsigned int crc );
 
+extern const unsigned int crctab[256];
+
+#ifdef __cplusplus
+}
 #endif
+
+#endif //LIGO_CRC_H
diff --git a/src/include/daq_core.h b/src/include/daq_core.h
index 84f2d5dc9f5c20ffd5a7d4a17ba5390599398cec..5253591d66653200634d46c984b23055aa7a726f 100644
--- a/src/include/daq_core.h
+++ b/src/include/daq_core.h
@@ -1,10 +1,6 @@
 #ifndef DAQ_GENERAL_TRANSIT_CORE_H
 #define DAQ_GENERAL_TRANSIT_CORE_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "daq_core_defs.h"
 
 /*
@@ -17,7 +13,6 @@ extern "C" {
 #define CDS_DAQ_NET_DATA_OFFSET 0x2000
 
 #define DAQ_GDS_MAX_TP_NUM 0x100
-#define MMAP_SIZE 1024 * 1024 * 64 - 5000
 
 //
 #define DAQ_TRANSIT_MAX_DC_BYTE_SEC 0x6000000 // 100MB per sec
@@ -98,8 +93,4 @@ typedef struct daq_multi_cycle_data_t
                     DAQ_NUM_DATA_BLOCKS_PER_SECOND ];
 } daq_multi_cycle_data_t;
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* DAQ_GENERAL_TRANSIT_CORE_H */
diff --git a/src/include/daq_data_types.h b/src/include/daq_data_types.h
index 00d30813c42555bf552dd8ee523ee49567f5c32b..60ffbf60ffbd89c739e9d45e90ad397199037222 100644
--- a/src/include/daq_data_types.h
+++ b/src/include/daq_data_types.h
@@ -1,6 +1,8 @@
 #ifndef DAQD_DATA_TYPES_H
 #define DAQD_DATA_TYPES_H
 
+#include "portableInline.h"
+
 /* numbering must be contiguous */
 typedef enum
 {
@@ -14,7 +16,7 @@ typedef enum
     _32bit_uint = 7
 } daq_data_t;
 
-inline static int
+LIGO_INLINE int
 data_type_size( short dtype )
 {
     switch ( dtype )
@@ -35,4 +37,4 @@ data_type_size( short dtype )
     }
 }
 
-#endif
\ No newline at end of file
+#endif
diff --git a/src/include/daqmap.h b/src/include/daqmap.h
index 0118fe122f001c22b69a3b63a1e029a1a7d5c01f..d32afed7d86eea3458fb45ec86a8374a80579286 100644
--- a/src/include/daqmap.h
+++ b/src/include/daqmap.h
@@ -410,7 +410,8 @@ typedef struct tp_channel_t
 #define GDS_DATA_OFFSET 0x200000
 #define GDS_BUFF_SIZE 0x80000
 
-#endif
-
 #define MAX_DEC 128
 #define DEC_FILT_LENGTH 21
+
+#endif //MAP_5565_H
+
diff --git a/src/include/drv/accesDio24.c b/src/include/drv/accesDio24.c
index eba345f16e70f90c1646b2dc31725c323c9a791b..1113eecf161f9f1086172fd9d8e2024f90836652 100644
--- a/src/include/drv/accesDio24.c
+++ b/src/include/drv/accesDio24.c
@@ -11,8 +11,10 @@
 ///map.c
 // *****************************************************************************
 
+#include "accesDio24.h"
+#include "util/printl.h"
+
 // Vendor defined card model number
-#define ACC_TID     0x0C51
 #define DIO_A_OUTPUT    0x8B
 #define DIO_C_OUTPUT    0x92
 #define DIO_A_REG   0x0
@@ -37,10 +39,10 @@ accesDio24Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev )
     pedStatus = pci_enable_device( diodev );
     /// Find the I/O address space for this module.
     pci_read_config_dword( diodev, PCI_BASE_ADDRESS_2, &pci_io_addr );
-    printk( "dio pci2 = 0x%x\n", pci_io_addr );
+    printl( "dio pci2 = 0x%x\n", pci_io_addr );
     /// Write I/O address info into the CDS_HARDWARE structure.
     pHardware->pci_do[ devNum ] = ( pci_io_addr - 1 );
-    printk( "diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
+    printl( "diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
     outb_p( DIO_C_OUTPUT, pHardware->pci_do[ devNum ] + DIO_CTRL_REG );
     /// Clear the present output from the module.
     outb( 0x00, pHardware->pci_do[ devNum ] + DIO_C_REG );
diff --git a/src/include/drv/accesDio24.h b/src/include/drv/accesDio24.h
new file mode 100644
index 0000000000000000000000000000000000000000..470fc019cf4f59fc5b2dbb9462e7489c7103cef5
--- /dev/null
+++ b/src/include/drv/accesDio24.h
@@ -0,0 +1,21 @@
+#ifndef LIGO_ACCESDIO24_H
+#define LIGO_ACCESDIO24_H
+
+#include "drv/cdsHardware.h"
+#include <linux/pci.h>
+
+#define ACC_TID     0x0C51
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int accesDio24Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev );
+unsigned int accesDio24ReadInputRegister( CDS_HARDWARE* pHardware, int modNum );
+void accesDio24WriteOutputRegister( CDS_HARDWARE* pHardware, int modNum, int data );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIGO_ACCESDIO24_H
diff --git a/src/include/drv/accesIIRO16.c b/src/include/drv/accesIIRO16.c
index 2a4c308d49125f9482839114fa35cb291a3d94ff..6805af0b491a7ea57fc9daddcbba009c242754a3 100644
--- a/src/include/drv/accesIIRO16.c
+++ b/src/include/drv/accesIIRO16.c
@@ -6,6 +6,7 @@
 ///< Manual</a>
 
 #include "accesIIRO16.h"
+#include "util/printl.h"
 
 // *****************************************************************************
 /// \brief Routine to initialize ACCESS IIRO-16 Isolated DIO modules
@@ -32,13 +33,13 @@ accesIiro16Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev )
     pedStatus = pci_enable_device( diodev );
     /// Find the I/O address space for this module.
     pci_read_config_dword( diodev, PCI_BASE_ADDRESS_2, &pci_io_addr );
-    printk( "iiro-16 dio pci2 = 0x%x\n", pci_io_addr );
+    printl( "iiro-16 dio pci2 = 0x%x\n", pci_io_addr );
     /// Fill module data into the CDS_HARDWARE structure.
     pHardware->pci_do[ devNum ] = pci_io_addr - 1;
     pHardware->doType[ devNum ] = ACS_16DIO;
     pHardware->doInstance[ devNum ] = pHardware->card_count[ ACS_16DIO ];
     pHardware->card_count[ ACS_16DIO ] ++;
-    printk( "iiro-16 diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
+    printl( "iiro-16 diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
 
     pHardware->doCount++;
     /// Return device enable status.
diff --git a/src/include/drv/accesIIRO16.h b/src/include/drv/accesIIRO16.h
index 990b4b919377ea16129d097af79fa5aed0689011..00dd30448bcc9b7c6768e9f7eebafb63c1284cd2 100644
--- a/src/include/drv/accesIIRO16.h
+++ b/src/include/drv/accesIIRO16.h
@@ -1,3 +1,10 @@
+#ifndef LIGO_ACCESIIRO16_H
+#define LIGO_ACCESIIRO16_H
+
+#include "cdsHardware.h"
+
+#include <linux/pci.h>
+
 /* ACCESS PCI-IIRO-16 isolated digital input and output (16 channels) */
 #define ACC_IIRO_TID16 0x0f09
 #define ACC_IIRO_TID16_OLD 0x0f08
@@ -5,4 +12,17 @@
 #define IIRO_DIO16_INPUT  0x1
 #define IIRO_DIO16_OUTPUT 0x0
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int accesIiro16Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev );
+unsigned int accesIiro16ReadInputRegister( CDS_HARDWARE* pHardware, int modNum );
+void accesIiro16WriteOutputRegister( CDS_HARDWARE* pHardware, int modNum, int data );
+
+#ifdef __cplusplus
+}
+#endif
+
 
+#endif //LIGO_ACCESIIRO16_H
diff --git a/src/include/drv/accesIIRO8.c b/src/include/drv/accesIIRO8.c
index 0952f0bde38e69e106c450bde894a68cbe76a10b..fc50338ffbe2ed533b89ac5b5532bb3174c14671 100644
--- a/src/include/drv/accesIIRO8.c
+++ b/src/include/drv/accesIIRO8.c
@@ -6,6 +6,7 @@
 ///< Manual</a>
 
 #include "accesIIRO8.h"
+#include "util/printl.h"
 
 // *****************************************************************************
 /// \brief Routine to initialize ACCESS IIRO-8 Isolated DIO modules
@@ -32,14 +33,14 @@ accesIiro8Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev )
     pedStatus = pci_enable_device( diodev );
     /// Find the I/O address space for this module.
     pci_read_config_dword( diodev, PCI_BASE_ADDRESS_2, &pci_io_addr );
-    printk( "iiro-8 dio pci2 = 0x%x\n", pci_io_addr );
+    printl( "iiro-8 dio pci2 = 0x%x\n", pci_io_addr );
     /// Write I/O address info into the CDS_HARDWARE structure.
     pHardware->pci_do[ devNum ] = pci_io_addr - 1;
     /// Fill in remaining info into CDS_HARDWARE structure.
     pHardware->doType[ devNum ] = ACS_8DIO;
     pHardware->doInstance[ devNum ] = pHardware->card_count[ ACS_8DIO ];
     pHardware->card_count[ ACS_8DIO ] ++;
-    printk( "iiro-8 diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
+    printl( "iiro-8 diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
     pHardware->doCount++;
     /// Return device enable status.
     return ( pedStatus );
diff --git a/src/include/drv/accesIIRO8.h b/src/include/drv/accesIIRO8.h
index 6320a79ba57bf03bc9e789fa0bcbcd726162ed32..cc19ad051411cc6d71abb382be73633a43d5e3c1 100644
--- a/src/include/drv/accesIIRO8.h
+++ b/src/include/drv/accesIIRO8.h
@@ -2,6 +2,14 @@
 ///	\brief ACCESS PCI-IIRO-8 relay digital input and output defs. See 
 ///<	<a href="http://accesio.com/go.cgi?p=../pcie/pcie-iiro-8.html">PCIe-IIRO-8 Manual</a>
 ///< for more info on board registers.
+#ifndef LIGO_ACCESIIRO8_H
+#define LIGO_ACCESIIRO8_H
+
+
+#include "drv/cdsHardware.h" //CDS_HARDWARE
+
+#include <linux/pci.h> // struct pci_dev 
+
 
 #define ACC_IIRO_TID_OLD 0x0f00
 #define ACC_IIRO_TID 0x0f02
@@ -9,3 +17,18 @@
 #define IIRO_DIO8_INPUT  0x1
 #define IIRO_DIO8_OUTPUT 0x0
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int accesIiro8Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev );
+unsigned int accesIiro8ReadInputRegister( CDS_HARDWARE* pHardware, int modNum );
+unsigned int accesIiro8ReadOutputRegister( CDS_HARDWARE* pHardware, int modNum );
+void accesIiro8WriteOutputRegister( CDS_HARDWARE* pHardware, int modNum, int data );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_ACCESIIRO8_H
diff --git a/src/include/drv/adc_info.c b/src/include/drv/adc_info.h
similarity index 86%
rename from src/include/drv/adc_info.c
rename to src/include/drv/adc_info.h
index 8b19d20bb4a24232a8a634ab487add8b1883a968..ad8de8c57c612da0073e6f15300657b8b20eeb6d 100644
--- a/src/include/drv/adc_info.c
+++ b/src/include/drv/adc_info.h
@@ -1,6 +1,17 @@
-inline int adc_status_update( adcInfo_t* );
+#ifndef LIGO_ADC_INFO_H
+#define LIGO_ADC_INFO_H
 
-inline int
+#include "portableInline.h"
+
+#include "cds_types.h" //acdInfo_t
+#include "controller.h" //cdsPciModules
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIGO_INLINE int
 adc_status_update( adcInfo_t* adcinfo )
 {
     int ii, jj;
@@ -51,3 +62,10 @@ adc_status_update( adcInfo_t* adcinfo )
     }
     return status;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_ADC_INFO_H
diff --git a/src/include/drv/adc_info_ioc2.c b/src/include/drv/adc_info_ioc2.h
similarity index 90%
rename from src/include/drv/adc_info_ioc2.c
rename to src/include/drv/adc_info_ioc2.h
index 6310f56047a28d8b67366518f2ad46fe5bcf2c58..1b25c3af7d2589a8ca9093ea1babcb3ace1f0820 100644
--- a/src/include/drv/adc_info_ioc2.c
+++ b/src/include/drv/adc_info_ioc2.h
@@ -1,6 +1,17 @@
-inline int adc_status_update( adcInfo_t* );
+#ifndef LIGO_ADC_INFO_IOC2_H
+#define LIGO_ADC_INFO_IOC2_H
 
-inline int
+#include "portableInline.h"
+
+#include "cds_types.h" //acdInfo_t
+#include "controller.h" //cdsPciModules
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIGO_INLINE int
 adc_status_update( adcInfo_t* adcinfo )
 {
     int ii = 0;
@@ -73,3 +84,9 @@ adc_status_update( adcInfo_t* adcinfo )
     }
     return status;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIGO_ADC_INFO_IOC2_H
diff --git a/src/include/drv/app_adc_read.c b/src/include/drv/app_adc_read.h
similarity index 87%
rename from src/include/drv/app_adc_read.c
rename to src/include/drv/app_adc_read.h
index dbfdf73bffb64fadef502a238011f9ec5a45a750..5877ac4f1938e74e347c15ab6d02bdb17bd72b33 100644
--- a/src/include/drv/app_adc_read.c
+++ b/src/include/drv/app_adc_read.h
@@ -1,10 +1,24 @@
-inline int app_adc_read( int, int, adcInfo_t*, int[] );
-inline int app_adc_status_update( adcInfo_t* );
+#ifndef LIGO_APP_ADC_READ_H 
+#define LIGO_APP_ADC_READ_H
 
-inline int
-app_adc_read( int ioMemCtr, int ioClk, adcInfo_t* adcinfo, int cpuClk[] )
+#include "portableInline.h"
+#include "cds_types.h"
+#include "controller.h" //cdsPciModules
+#include "fm10Gen.h"
+
+#include <asm/msr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//This function is forced static because the rdtsc_ordered() function is static
+static inline int
+app_adc_read( int ioMemCtr, int ioClk, adcInfo_t* adcinfo, int cpuClk[], int* startGpsTime_ptr  )
 {
+#ifdef OVERSAMPLE
     int limit = OVERFLOW_LIMIT_16BIT;
+#endif
     int mm;
     int card = 0;
     int chan = 0;
@@ -30,8 +44,8 @@ app_adc_read( int ioMemCtr, int ioClk, adcInfo_t* adcinfo, int cpuClk[] )
         timeSec = ioMemData->iodata[ mm ][ ioMemCtr ].timeSec;
         if ( cycle_gps_time == 0 )
         {
-            startGpsTime = timeSec;
-            pLocalEpics->epicsOutput.startgpstime = startGpsTime;
+            *startGpsTime_ptr = timeSec;
+            pLocalEpics->epicsOutput.startgpstime = *startGpsTime_ptr;
         }
         cycle_gps_time = timeSec;
 
@@ -75,7 +89,7 @@ app_adc_read( int ioMemCtr, int ioClk, adcInfo_t* adcinfo, int cpuClk[] )
     return 0;
 }
 
-inline int
+LIGO_INLINE int
 app_adc_status_update( adcInfo_t* adcinfo )
 {
     int status = 0;
@@ -119,3 +133,10 @@ app_adc_status_update( adcInfo_t* adcinfo )
     }
     return status;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_APP_ADC_READ_H
diff --git a/src/include/drv/app_dac_functions.c b/src/include/drv/app_dac_functions.h
similarity index 92%
rename from src/include/drv/app_dac_functions.c
rename to src/include/drv/app_dac_functions.h
index ab01bf0c401dce3219553cb29b11cfa9c61e058d..d1b0bc782b58af4bde3ed0327c47712b7f5410c8 100644
--- a/src/include/drv/app_dac_functions.c
+++ b/src/include/drv/app_dac_functions.h
@@ -1,12 +1,20 @@
 #ifndef LIGO_APP_DAC_FUNCTIONS_H
 #define LIGO_APP_DAC_FUNCTIONS_H
 
+#include "portableInline.h"
 #include "cds_types.h"
+#include "controller.h" //cdsPciModules
+#include "fm10Gen.h"
+#include "drv/gsc16ao16.h" //GSAO_16BIT_MASK
+#include "drv/gsc18ao8.h" //GSAO_18BIT_MASK
+#include "drv/gsc20ao8.h" //GSAO_20BIT_MASK
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-
-static inline int
-app_dac_init( )
+LIGO_INLINE int
+app_dac_init( void )
 {
     int ii, jj;
     int pd;
@@ -25,8 +33,8 @@ app_dac_init( )
                 {
                     if ( ioMemData->dacOutUsed[ pd ][ jj ] )
                     {
-                        // printf("Failed to allocate DAC channel.\n");
-                        // printf("DAC local %d global %d channel %d is already
+                        // printl("Failed to allocate DAC channel.\n");
+                        // printl("DAC local %d global %d channel %d is already
                         // allocated.\n", ii, pd, jj);
                         return 1;
                     }
@@ -52,10 +60,11 @@ app_dac_init( )
     }
     return 0;
 }
+
 // Clear DAC channel shared memory map,
 // used to keep track of non-overlapping DAC channels among control models
 //
-static inline void
+LIGO_INLINE void
 deallocate_dac_channels( void )
 {
     int ii, jj;
@@ -71,8 +80,8 @@ deallocate_dac_channels( void )
     }
 }
 
-static inline int
-app_dac_write( int ioMemCtrDac, int ioClkDac, dacInfo_t* dacinfo )
+//LIGO_INLINE int
+LIGO_INLINE int app_dac_write( int ioMemCtrDac, int ioClkDac, dacInfo_t* dacinfo )
 {
     int    ii, jj, mm, kk;
     int    limit, mask, num_outs;
@@ -203,5 +212,9 @@ app_dac_write( int ioMemCtrDac, int ioClkDac, dacInfo_t* dacinfo )
     return 0;
 }
 
+#ifdef __cplusplus
+}
+#endif
+
 
 #endif
diff --git a/src/include/drv/app_dio_routines.c b/src/include/drv/app_dio_routines.h
similarity index 88%
rename from src/include/drv/app_dio_routines.c
rename to src/include/drv/app_dio_routines.h
index 5bf48eb5ee2efe03f3dcb6588eae237ed52bd621..0a78874e81690721cb2ecc462c96d877635ee920 100644
--- a/src/include/drv/app_dio_routines.c
+++ b/src/include/drv/app_dio_routines.h
@@ -1,8 +1,22 @@
-inline int app_dio_init( void );
-inline int app_dio_read_write( void );
+#ifndef LIGO_APP_DIO_ROUTINES_H 
+#define LIGO_APP_DIO_ROUTINES_H
 
-inline int
-app_dio_init( )
+#include "portableInline.h"
+#include "controller.h" //cdsPciModules
+#include "controllerko.h" //CDIO6464InputInput, CDIO6464LastOutState, 
+#include "drv/accesIIRO8.h"
+#include "drv/accesIIRO16.h"
+#include "contec32o.h"
+#include "contec6464.h"
+#include "accesDio24.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIGO_INLINE int
+app_dio_init( void )
 {
 
     int ii, kk;
@@ -35,14 +49,14 @@ app_dio_init( )
         {
             CDIO6464LastOutState[ ii ] =
                 contec6464ReadOutputRegister( &cdsPciModules, kk );
-            // printf ("Initial state of contec6464 number %d = 0x%x
+            // printl ("Initial state of contec6464 number %d = 0x%x
             // \n",ii,CDIO6464LastOutState[ii]);
         }
         else if ( cdsPciModules.doType[ kk ] == CDI64 )
         {
             CDIO6464LastOutState[ ii ] =
                 contec6464ReadOutputRegister( &cdsPciModules, kk );
-            // printf ("Initial state of contec6464 number %d = 0x%x
+            // printl ("Initial state of contec6464 number %d = 0x%x
             // \n",ii,CDIO6464LastOutState[ii]);
         }
         else if ( cdsPciModules.doType[ kk ] == ACS_24DIO )
@@ -52,8 +66,9 @@ app_dio_init( )
     }
     return 0;
 }
-inline int
-app_dio_read_write( )
+
+LIGO_INLINE int
+app_dio_read_write( void )
 {
 
     int ii, kk;
@@ -151,3 +166,9 @@ app_dio_read_write( )
     }
     return 0;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIGO_APP_DIO_ROUTINES_H
diff --git a/src/include/drv/cdsHardware.h b/src/include/drv/cdsHardware.h
index 0adea57f0418f95c837e97ac7b9e1a966be40553..4ff90069dcae843b7a221a7f4836edbf56925aa6 100644
--- a/src/include/drv/cdsHardware.h
+++ b/src/include/drv/cdsHardware.h
@@ -67,7 +67,7 @@
 typedef struct CDS_CARDS {
 	int type;
 	int instance;
-        int time_shift;
+	int time_shift;
 } CDS_CARDS;
 
 /* Remote IPC nodes configuration */
@@ -158,7 +158,7 @@ typedef struct IO_MEM_DATA{
 	int rfmCount;
 	long pci_rfm[MAX_RFM_MODULES];	/* Remapped addresses of RFM modules	*/
 	long pci_rfm_dma[MAX_RFM_MODULES];	/* Remapped addresses of RFM modules	*/
-    int dolphinCount;
+	int dolphinCount;
 	volatile unsigned long *dolphinRead[4]; /* read and write Dolphin memory */
 	volatile unsigned long *dolphinWrite[4]; /* read and write Dolphin memory */
 	MEM_DATA_BLOCK iodata[MAX_IO_MODULES][IO_MEMORY_SLOTS];
@@ -166,7 +166,7 @@ typedef struct IO_MEM_DATA{
 	unsigned int dacOutUsed[MAX_DAC_MODULES][16];
 	unsigned int ipcDetect[2][8];
 	int card[MAX_IO_MODULES];
-    int mem_data_rate;;
+	int mem_data_rate;;
 }IO_MEM_DATA;
 
 // Interface structure between user space IOP and user space control models
@@ -182,7 +182,7 @@ typedef struct IO_MEM_DATA_IOP{
 	int rfmCount;
 	long pci_rfm[MAX_RFM_MODULES];	/* Remapped addresses of RFM modules	*/
 	long pci_rfm_dma[MAX_RFM_MODULES];	/* Remapped addresses of RFM modules	*/
-        int dolphinCount;
+	int dolphinCount;
 	volatile unsigned long *dolphinRead[4]; /* read and write Dolphin memory */
 	volatile unsigned long *dolphinWrite[4]; /* read and write Dolphin memory */
 	MEM_DATA_BLOCK iodata[6][65536];
@@ -207,22 +207,22 @@ typedef struct IO_MEM_DATA_IOP{
 /* Standard structure to maintain PCI module information.			*/
 typedef struct CDS_HARDWARE{
 	int dacCount;			/* Number of DAC modules found 		*/
-	long pci_dac[MAX_DAC_MODULES];	/* Remapped addresses of DAC modules	*/
+	volatile int * pci_dac[MAX_DAC_MODULES];	/* Remapped addresses of DAC modules	*/
 	int dacType[MAX_DAC_MODULES];
 	int dacInstance[MAX_DAC_MODULES];
 	int dacSlot[MAX_DAC_MODULES];
 	int dacConfig[MAX_DAC_MODULES];
 	int dacMap[MAX_DAC_MODULES];
-    int dacAcr[MAX_DAC_MODULES];
+	int dacAcr[MAX_DAC_MODULES];
 	int adcCount;			/* Number of ADC modules found		*/
-	long pci_adc[MAX_ADC_MODULES];	/* Remapped addresses of ADC modules	*/
+	volatile int *pci_adc[MAX_ADC_MODULES];	/* Remapped addresses of ADC modules	*/
 	int adcType[MAX_ADC_MODULES];
 	int adcInstance[MAX_ADC_MODULES];
 	int adcSlot[MAX_ADC_MODULES];
-    int adcChannels[MAX_ADC_MODULES];
+	int adcChannels[MAX_ADC_MODULES];
 	int adcConfig[MAX_ADC_MODULES];
 	int adcMap[MAX_ADC_MODULES];
-        int adcTimeShift[MAX_ADC_MODULES];
+	int adcTimeShift[MAX_ADC_MODULES];
 	int doCount;			/* Number of DIO modules found		*/
 	unsigned short pci_do[MAX_DIO_MODULES];	/* io registers of DIO	*/
 	int doType[MAX_DIO_MODULES];
diff --git a/src/include/drv/contec1616.c b/src/include/drv/contec1616.c
index a03edb9e885f2871eb219ac372912aec454fc597..a2dd246fa245607fa497c2a49db06b8db6736560 100644
--- a/src/include/drv/contec1616.c
+++ b/src/include/drv/contec1616.c
@@ -8,6 +8,11 @@
 ///< href="http://www.contec.com/product.php?id=1611">DIO-1616L-PE Manual</a>
 
 #include "contec1616.h"
+#include "controller.h"
+#include "controllerko.h" //CDIO*
+#include "util/printl.h"
+
+#include <linux/delay.h> //udelay()
 
 // *****************************************************************************
 /// \brief Routine to initialize CONTEC PCIe 1616 DIO modules
@@ -35,13 +40,13 @@ contec1616Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev )
     pedStatus = pci_enable_device( diodev );
     /// Find the I/O address space for this module.
     pci_read_config_dword( diodev, PCI_BASE_ADDRESS_0, &pci_io_addr );
-    printk( "contec 1616 dio pci2 = 0x%x\n", pci_io_addr );
+    printl( "contec 1616 dio pci2 = 0x%x\n", pci_io_addr );
     /// Write I/O address info into the CDS_HARDWARE structure.
     pHardware->pci_do[ devNum ] = pci_io_addr - 1;
-    printk( "contec 1616 diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
+    printl( "contec 1616 diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
     /// Read board number switch setting on module
     pci_read_config_dword( diodev, PCI_REVISION_ID, &id );
-    printk( "contec dio pci2 card number= 0x%x\n", ( id & 0xf ) );
+    printl( "contec dio pci2 card number= 0x%x\n", ( id & 0xf ) );
     /// Fill in remaining info into CDS_HARDWARE structure.
     pHardware->doType[ devNum ] = CON_1616DIO;
     pHardware->doCount++;
diff --git a/src/include/drv/contec1616.h b/src/include/drv/contec1616.h
index aaa58f05a4f07a0b7c5c69686c1d2d345e82b1b9..ae8352265f89b114e134d85983f0b5fe77864a65 100644
--- a/src/include/drv/contec1616.h
+++ b/src/include/drv/contec1616.h
@@ -1,5 +1,16 @@
+#ifndef LGO_CONTEC1616_H 
+#define LGO_CONTEC1616_H
+
+#include "drv/cdsHardware.h"
+
+#include <linux/pci.h>
+
 #define C_DIO_1616L_PE  0x8632
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int contec1616Init( CDS_HARDWARE* , struct pci_dev* );
 unsigned int contec1616WriteOutputRegister( CDS_HARDWARE* , int , unsigned int );
 unsigned int contec1616ReadOutputRegister( CDS_HARDWARE* , int );
@@ -7,4 +18,9 @@ unsigned int contec1616ReadInputRegister( CDS_HARDWARE* , int );
 void start_tds_clocks ( int );
 void stop_tds_clocks ( int );
 
+#ifdef __cplusplus
+}
+#endif
+
 
+#endif // LGO_CONTEC1616_H
diff --git a/src/include/drv/contec32o.c b/src/include/drv/contec32o.c
index 2211138ec0bb362b8b4f890725da33582511bf4c..da339ab0b4ebc14a08abb2942761189f7211857f 100644
--- a/src/include/drv/contec32o.c
+++ b/src/include/drv/contec32o.c
@@ -7,8 +7,8 @@
 /// Routine to Initialize CONTEC PCIe-32 Isolated DO modules
 // *****************************************************************************
 
-// Contec card model ID
-#define C_DO_32L_PE 0x86E2
+#include "contec32o.h"
+#include "util/printl.h"
 
 int
 contec32OutInit( CDS_HARDWARE* pHardware, struct pci_dev* diodev )
@@ -21,11 +21,11 @@ contec32OutInit( CDS_HARDWARE* pHardware, struct pci_dev* diodev )
     devNum = pHardware->doCount;
     pedStatus = pci_enable_device( diodev );
     pci_read_config_dword( diodev, PCI_BASE_ADDRESS_0, &pci_io_addr );
-    printk( "contec dio pci2 = 0x%x\n", pci_io_addr );
+    printl( "contec dio pci2 = 0x%x\n", pci_io_addr );
     pHardware->pci_do[ devNum ] = pci_io_addr - 1;
-    printk( "contec32L diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
+    printl( "contec32L diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
     pci_read_config_dword( diodev, PCI_REVISION_ID, &id );
-    printk( "contec dio pci2 card number= 0x%x\n", ( id & 0xf ) );
+    printl( "contec dio pci2 card number= 0x%x\n", ( id & 0xf ) );
     pHardware->doType[ devNum ] = CON_32DO;
     pHardware->doCount++;
     pHardware->doInstance[ devNum ] = pHardware->card_count[ CON_32DO ];
@@ -41,8 +41,8 @@ contec32WriteOutputRegister( CDS_HARDWARE* pHardware,
                              int           modNum,
                              unsigned int  data )
 {
-    // printk("writeCDO32l modNum = %d\n",modNum);
-    // printk("writeCDO32l data = %d\n",data);
+    // printl("writeCDO32l modNum = %d\n",modNum);
+    // printl("writeCDO32l data = %d\n",data);
     outl( data, pHardware->pci_do[ modNum ] );
     return ( inl( pHardware->pci_do[ modNum ] ) );
 }
diff --git a/src/include/drv/contec32o.h b/src/include/drv/contec32o.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd7a3bea9a95968679810224ae88e174f6aaac8a
--- /dev/null
+++ b/src/include/drv/contec32o.h
@@ -0,0 +1,27 @@
+#ifndef LIGO_CONTEC32O_H
+#define LIGO_CONTEC32O_H
+
+#include "cdsHardware.h"
+
+#include <linux/pci.h>
+
+// Contec card model ID
+#define C_DO_32L_PE 0x86E2
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int contec32OutInit( CDS_HARDWARE* pHardware, struct pci_dev* diodev );
+unsigned int contec32WriteOutputRegister( CDS_HARDWARE* pHardware, int modNum, unsigned int data );
+unsigned int contec32ReadOutputRegister( CDS_HARDWARE* pHardware, int modNum );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+#endif //LIGO_CONTEC32O_H
diff --git a/src/include/drv/contec6464.c b/src/include/drv/contec6464.c
index 946b2a6b93718eff5ac89738670f30c06ee11b3e..62bbf7f0a89833bef55edccb41d3700a26cd08e4 100644
--- a/src/include/drv/contec6464.c
+++ b/src/include/drv/contec6464.c
@@ -5,6 +5,7 @@
 ///< href="http://www.contec.com/product.php?id=1710">DIO-6464L-PE Manual</a>
 
 #include "contec6464.h"
+#include "util/printl.h"
 
 // *****************************************************************************
 /// \brief Routine to initialize CONTEC PCIe 6464 DIO module
@@ -33,14 +34,14 @@ contec6464Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev )
     pedStatus = pci_enable_device( diodev );
     /// Find the I/O address space for this module.
     pci_read_config_dword( diodev, PCI_BASE_ADDRESS_0, &pci_io_addr );
-    printk( "contec 6464 dio pci2 = 0x%x\n", pci_io_addr );
+    printl( "contec 6464 dio pci2 = 0x%x\n", pci_io_addr );
     pHardware->pci_do[ devNum ] = pci_io_addr - 1;
-    printk( "contec32L diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
+    printl( "contec32L diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
     /// Read board number switch setting on module
     pci_read_config_dword( diodev, PCI_REVISION_ID, &id );
-    printk( "contec dio pci2 card number= 0x%x\n", ( id & 0xf ) );
+    printl( "contec dio pci2 card number= 0x%x\n", ( id & 0xf ) );
     test = contec6464ReadInputRegister( pHardware,devNum);
-    printk("Contec6464 %d read = 0x%x\n",devNum,test);
+    printl("Contec6464 %d read = 0x%x\n",devNum,test);
     /// Break the module into two, 32bit devices ie 64bits will not carry thru
     /// read/write and
     ///< maintain all of the bit information.
@@ -56,9 +57,9 @@ contec6464Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev )
     pHardware->doCount++;
     pHardware->doInstance[ devNum ] = pHardware->card_count[ CON_6464DIO ];
     pHardware->card_count[ CON_6464DIO ] ++;
-    printk( "contec32H diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
+    printl( "contec32H diospace = 0x%x\n", pHardware->pci_do[ devNum ] );
     test = contec6464ReadInputRegister( pHardware,devNum);
-    printk("Contec6464 %d read = 0x%x\n",devNum,test);
+    printl("Contec6464 %d read = 0x%x\n",devNum,test);
     /// Return board ID number.
     return ( id );
 }
diff --git a/src/include/drv/contec6464.h b/src/include/drv/contec6464.h
index 0765ef4b3ab9d18b9014434d237aacfc27b393ea..c288d4d7140e78be565c17dfa8bba6fb7c061be3 100644
--- a/src/include/drv/contec6464.h
+++ b/src/include/drv/contec6464.h
@@ -1,7 +1,25 @@
+#ifndef LIGO_CONTEC6464_H
+#define LIGO_CONTEC6464_H
+
+#include "drv/cdsHardware.h"
+
+#include <linux/pci.h>
+
 #define C_DIO_6464L_PE  0x8682
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int contec6464Init( CDS_HARDWARE* , struct pci_dev* );
 unsigned int contec6464WriteOutputRegister( CDS_HARDWARE* , int, unsigned int );
 unsigned int contec6464ReadOutputRegister( CDS_HARDWARE* , int );
 unsigned int contec6464ReadInputRegister( CDS_HARDWARE*,  int );
 
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_CONTEC6464_H
+
diff --git a/src/include/drv/dac_info.c b/src/include/drv/dac_info.h
similarity index 79%
rename from src/include/drv/dac_info.c
rename to src/include/drv/dac_info.h
index d8ab39aeaa2e221a714fa7d831a3bbbcce2e8e46..4aee41a352815eecbb3b284ea10f0d5998d48e42 100644
--- a/src/include/drv/dac_info.c
+++ b/src/include/drv/dac_info.h
@@ -1,6 +1,16 @@
-inline int dac_status_update( dacInfo_t* );
+#ifndef LIGO_DAC_INFO_H
+#define LIGO_DAC_INFO_H
 
-inline int
+#include "portableInline.h"
+#include "drv/cdsHardware.h" //CDS_HARDWARE
+#include "cds_types.h" //dacInfo_t
+#include "controller.h" //cdsPciModules
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIGO_INLINE int
 dac_status_update( dacInfo_t* dacinfo )
 {
     int ii, jj;
@@ -39,3 +49,11 @@ dac_status_update( dacInfo_t* dacinfo )
     }
     return status;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif //LIGO_DAC_INFO_H
diff --git a/src/include/drv/dac_info_ioc2.c b/src/include/drv/dac_info_ioc2.h
similarity index 92%
rename from src/include/drv/dac_info_ioc2.c
rename to src/include/drv/dac_info_ioc2.h
index e2c5c23d81eba9095d8eacc500b1c4699cef198f..a28486b45a8087936c63628147e13b237e642b2f 100644
--- a/src/include/drv/dac_info_ioc2.c
+++ b/src/include/drv/dac_info_ioc2.h
@@ -1,6 +1,18 @@
-inline int dac_status_update( dacInfo_t* );
+#ifndef LIGO_DAC_INFO_IOC2_H
+#define LIGO_DAC_INFO_IOC2_H
 
-inline int
+#include "portableInline.h"
+
+#include "cds_types.h" //dacInfo_t
+#include "controller.h" //cdsPciModules
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+LIGO_INLINE int
 dac_status_update( dacInfo_t* dacinfo )
 {
     int ii = 0;
@@ -98,3 +110,10 @@ dac_status_update( dacInfo_t* dacinfo )
     }
     return status;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_DAC_INFO_IOC2_H
diff --git a/src/include/drv/daqLib.c b/src/include/drv/daqLib.c
index b1ff64f95746d483fa1b9e17a7c260cf07800f37..89f4afd578a70e7c04b94855d98d98650dc540b4 100644
--- a/src/include/drv/daqLib.c
+++ b/src/include/drv/daqLib.c
@@ -2,63 +2,85 @@
  *	\brief File contains routines to support DAQ on realtime systems. \n
  *	\author R.Bork, A. Ivanov
  */
- 
+
+#include "daqLib.h"
+#include "daq_core.h"
 #include "../../shmem/shmem_all.h"
 
-volatile DAQ_INFO_BLOCK* pInfo; ///< Ptr to DAQ config in shmem.
-extern volatile char*    _epics_shm; ///< Ptr to EPICS shmem block
-extern volatile AWG_DATA *_awg_shm;
-extern volatile TESTPOINT_CFG *_tp_shm;
-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.
+//TODO: If we don't have this we get a undefined refrence iir_filter_biquad
+//Can't figure out why when this is gone we don't have an unknown function during compile time
+#include "fm10Gen.h" 
+#include "controller.h" //cycle_gps_time, FE_ERROR_EXC_SET, _daq_shm, etc
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+//
+// Exported Globals
+//
 struct cdsDaqNetGdsTpNum* tpPtr; ///< Pointer to TP table in shared memory.
-char*                     daqShmPtr; ///< Pointer to DAQ data in shared memory.
-volatile char*
-    pEpicsIntData; ///< Pointer to EPICS integer type data in shared memory.
-volatile char*
-             pEpicsDblData; ///< Pointer to EPICS double type data in shared memory.
-unsigned int curDaqBlockSize; ///< Total DAQ data rate diag
+unsigned int    curDaqBlockSize; ///< Total DAQ data rate diag
+
+
+//
+// Local Globals
+//
+static volatile DAQ_INFO_BLOCK* pInfo; ///< Ptr to DAQ config in shmem.
+static struct   rmIpcStr* dipc; ///< Pointer to DAQ IPC data in shared memory.
+static volatile char*    daqShmPtr; ///< Pointer to DAQ data in shared memory.
+static volatile char*  pEpicsIntData; ///< Pointer to EPICS integer type data in shared memory.
+static volatile char*  pEpicsDblData; ///< Pointer to EPICS double type data in shared memory.
+//static unsigned int    curDaqBlockSize; ///< Total DAQ data rate diag
 // Added to get EPICS data for RCG V2.8
-volatile char*   pEpicsInt; // Pointer to current DAQ data in shared memory.
-volatile char*   pEpicsInt1;
-volatile float*  pEpicsFloat; // Pointer to current DAQ data in shared memory.
-volatile double* pEpicsDblData1;
+static volatile char*   pEpicsInt; // Pointer to current DAQ data in shared memory.
+static volatile char*   pEpicsInt1;
+static volatile float*  pEpicsFloat; // Pointer to current DAQ data in shared memory.
+static volatile double* pEpicsDblData1;
 
-int
-    daqConfig( volatile DAQ_INFO_BLOCK*, volatile DAQ_INFO_BLOCK*, volatile 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[],
-              volatile char* );
-
-inline double
-htond( double in )
+
+
+// Helper function to search the lists
+// Clears the found number from the lists
+// tpnum and excnum lists of numbers do not intersect
+static inline int in_the_lists( unsigned int tp, 
+                                unsigned int slot, 
+                                unsigned int tpnum[ DAQ_GDS_MAX_TP_ALLOWED ],
+                                unsigned int excnum[ DAQ_GDS_MAX_TP_ALLOWED ],
+                                DAQ_LKUP_TABLE excTable[ DCU_MAX_CHANNELS ] )
 {
-    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 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
+static inline int empty_slot( int tpNum[ DAQ_GDS_MAX_TP_ALLOWED ] )
+{
+    int i;
+    for ( i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++ )
+    {
+        if ( tpNum[ i ] == 0 )
+            return i;
+    }
+    return -1;
+}
+
+
+
 /* ******************************************************************** */
 /* Routine to connect and write to LIGO DAQ system       		*/
 /* ******************************************************************** */
@@ -126,9 +148,6 @@ daqWrite( int            flag,
                                                       FB.	*/
     static int      totalChans; /* DAQ + TP + EXC chans selected.	*/
 
-    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;
@@ -138,6 +157,8 @@ daqWrite( int            flag,
     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             page_index;
+    volatile AWG_DATA_PAGE *awg_page;
 
 #ifdef CORE_BIQUAD
     // BIQUAD Decimation filter coefficient definitions.
@@ -442,7 +463,7 @@ daqWrite( int            flag,
         validTp = 0;
         validTpNet = 0;
 
-        // printf("at connect TPnum[0]=%d\n", tpNum[0]);
+        // printl("at connect TPnum[0]=%d\n", tpNum[0]);
     } ///  End DAQ CONNECT INITIALIZATION ******************************
 
     /* ********************************************************************************
@@ -646,7 +667,7 @@ daqWrite( int            flag,
             {
                 kk = jj + DAQ_XFER_FMD_PER_CYCLE;
             }
-            // printf("Cycle = %d jj = %d kk = %d\n",daqSlot,jj,kk);
+            // printl("Cycle = %d jj = %d kk = %d\n",daqSlot,jj,kk);
             for ( ii = jj; ii < kk; ii++ )
             {
                 *pEpicsFloat = (float)dspPtr->inputs[ ii ].offset;
@@ -690,8 +711,8 @@ daqWrite( int            flag,
                     continue;
 
                 //find right page for the excitation
-                int page_index = FIND_PAGE_INDEX(localTable[ ii ].sigNum, excBlockNum);
-                AWG_DATA_PAGE *awg_page = _awg_shm->page + page_index;
+                page_index = FIND_PAGE_INDEX(localTable[ ii ].sigNum, excBlockNum);
+                awg_page = _awg_shm->page + page_index;
 
                 if ( awg_page->status == 0 )
                 {
@@ -773,7 +794,7 @@ daqWrite( int            flag,
             //  - -- Check for reconfig request at start of each second
             if ( ( pInfo->reconfig == 1 ) && ( daqBlockNum == 0 ) )
             {
-                // printf("New daq config\n");
+                // printl("New daq config\n");
                 pInfo->reconfig = 0;
                 // Configure EPICS data channels
                 xferInfo.crcLength = daqConfig( &dataInfo, pInfo, pEpics );
@@ -800,40 +821,7 @@ daqWrite( int            flag,
             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;
-                }
+                //unsigned int _2k_sys_offs = sysRate < DAQ_16K_SAMPLE_SIZE;
 
                 // Copy TP/EXC tables into my local memory
                 // Had to change from memcpy to for loop for Debian 10.
@@ -847,7 +835,7 @@ daqWrite( int            flag,
                 {
                     if ( tpNum[ i ] == 0 )
                         continue;
-                    if ( !in_the_lists( tpNum[ i ], i ) )
+                    if ( !in_the_lists( tpNum[ i ], i, tpnum, excnum, excTable ) )
                     {
                         tpNum[ i ] = 0; // Removed test point is cleared now
                         ltSlot = dataInfo.numChans + i;
@@ -897,8 +885,8 @@ daqWrite( int            flag,
                         ii = i - DAQ_GDS_MAX_TP_ALLOWED;
                     }
 
-                    // printf("tpn=%d at %d\n", tpn, i);
-                    slot = empty_slot( );
+                    // printl("tpn=%d at %d\n", tpn, i);
+                    slot = empty_slot( tpNum );
                     if ( slot < 0 )
                     {
                         // No more slots left, table's full
@@ -1077,7 +1065,7 @@ daqConfig( volatile DAQ_INFO_BLOCK* dataInfo,
     // if((status < 1) || (status > DCU_MAX_CHANNELS))
     if ( status > DCU_MAX_CHANNELS )
     {
-        // printf("Invalid num daq chans = %d\n",status);
+        // printl("Invalid num daq chans = %d\n",status);
         return ( -1 );
     }
 
@@ -1111,7 +1099,7 @@ daqConfig( volatile DAQ_INFO_BLOCK* dataInfo,
 
     ii = ( sizeof( CDS_EPICS_OUT ) / 4 );
     jj = dataInfo->numEpicsInts - ii;
-    // printf("Have %d CDS epics integer and %d USR epics integer
+    // printl("Have %d CDS epics integer and %d USR epics integer
     // channels\n",ii,jj);
     ii *= 4;
     jj *= 4;
@@ -1123,12 +1111,12 @@ daqConfig( volatile DAQ_INFO_BLOCK* dataInfo,
     /// before the double type data in shared memory.
     if ( ii % 8 )
     {
-        // printf("Have int mem hole after CDS %d %d \n",ii,jj);
+        // printl("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);
+        // printl("Have int mem hole after user %d %d \n",ii,jj);
         dataInfo->epicsdblDataOffset += 4;
     }
     if ( ( ii % 8 ) && ( jj > 0 ) )
@@ -1141,7 +1129,7 @@ daqConfig( volatile DAQ_INFO_BLOCK* dataInfo,
         dataInfo->cpyIntSize[ 1 ] = jj;
         dataInfo->cpyepics2times = 1;
         // dataInfo->epicsdblDataOffset += 4;
-        // printf("Have mem holes after CDS  %d %d \nNeed to cpy ints twice -
+        // printl("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]);
     }
@@ -1154,17 +1142,17 @@ daqConfig( volatile DAQ_INFO_BLOCK* dataInfo,
         ( pEpicsIntData + epicsIntXferSize + dataInfo->epicsdblDataOffset );
 
     // Send EPICS data diags to dmesg
-    // printf("DAQ EPICS INT DATA is at 0x%lx with size
+    // printl("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 =
+    // printl("DAQ EPICS FLT DATA is at 0x%lx\n",(long)pEpicsDblData);
+    // printl("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 =
+    // printl("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);
+    // printl("crc length epics = %d\n",dataLength);
 
     /// \>  Get the DAQ configuration information for all fast DAQ channels and
     /// calc a crc checksum length
@@ -1176,7 +1164,7 @@ daqConfig( volatile DAQ_INFO_BLOCK* dataInfo,
         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
+        // if(mydatatype == 5) printl("Found double
         // %d\n",DAQ_DATA_TYPE_SIZE(mydatatype));
     }
     /// \> Set DAQ bytes/sec global, which is output to EPICS by controller.c
@@ -1232,7 +1220,7 @@ loadLocalTable( DAQ_XFER_INFO*  pDxi,
         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,
+            // printl("Channels %d has bad data rate %d\n", ii,
             // dataInfo->tp[ii].dataRate);
             return ( -1 );
         }
@@ -1299,11 +1287,11 @@ loadLocalTable( DAQ_XFER_INFO*  pDxi,
         }
         else
         {
-            // printf("Invalid chan num found %d =
+            // printl("Invalid chan num found %d =
             // %d\n",ii,dataInfo->tp[ii].tpnum);
             return ( -1 );
         }
-        // printf("Table %d Offset = %d  Type =
+        // printl("Table %d Offset = %d  Type =
         // %d\n",ii,localTable[ii].offset,dataInfo->tp[ii].dataType);
     }
     return ( 0 );
diff --git a/src/include/drv/daqLib.h b/src/include/drv/daqLib.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f7718cd140b9dc7421a1551552302523ceaa3bd
--- /dev/null
+++ b/src/include/drv/daqLib.h
@@ -0,0 +1,36 @@
+#ifndef LIGO_DAQLIB_H
+#define LIGO_DAQLIB_H
+
+#include "daqmap.h" //DAQ_*
+
+#include "fm10Gen_types.h"//FILT_MOD
+
+//
+// Global Variables 
+//
+extern struct cdsDaqNetGdsTpNum* tpPtr; //Used by fe/controller*.c files
+extern unsigned int    curDaqBlockSize;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int daqConfig( volatile DAQ_INFO_BLOCK*, volatile DAQ_INFO_BLOCK*, volatile 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[],
+              volatile char* );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_DAQLIB_H
diff --git a/src/include/drv/dtoal.c b/src/include/drv/dtoa.c
similarity index 100%
rename from src/include/drv/dtoal.c
rename to src/include/drv/dtoa.c
diff --git a/src/include/drv/epicsXfer.c b/src/include/drv/epicsXfer.c
index 492e956dec86fa143bd4fc723c2ae8ea522c91e4..5adbc53c4167c7cbdf40efb7455c06382e1b68ea 100644
--- a/src/include/drv/epicsXfer.c
+++ b/src/include/drv/epicsXfer.c
@@ -1,119 +1,9 @@
-///	@file epicsXfer.c
-///	@brief File contains routines for:
-///<		- Exchanging filter module data with EPICS shared memory
-///<		- Checking for process kill command from EPICS
-///<		- Ramping algorithm, used by Product.pm part.
-/************************************************************************/
-///	Function to exchange filter module data with EPICS via shared memory.
-///	@param[in] subcycle		Filter Module ID for data transfer.
-///	@param[in] *dsp			Pointer to process memory fm data.
-///	@param[in] *pDsp		Pointer to shared memory fm data.
-///	@param[in] *dspCoeff		Pointer to process memory fm coeff data.
-///	@param[in] *pCoeff		Pointer to shared memory fm coeff data.
-/************************************************************************/
-inline void
-updateEpics( int       subcycle,
-             FILT_MOD* dsp,
-             FILT_MOD* pDsp,
-             COEF*     dspCoeff,
-             VME_COEF* pCoeff )
-{
-    int ii;
-
-    ii = subcycle;
-    if ( ( ii >= 0 ) && ( ii < MAX_MODULES ) )
-    {
-        checkFiltReset( ii, dsp, pDsp, dspCoeff, MAX_MODULES, pCoeff );
-        // dsp->inputs[ii].opSwitchE = pDsp->inputs[ii].opSwitchE;
-        pDsp->data[ ii ].filterInput = dsp->data[ ii ].filterInput;
-        pDsp->data[ ii ].exciteInput = dsp->data[ ii ].exciteInput;
-        pDsp->data[ ii ].output16Hz = dsp->data[ ii ].output16Hz;
-        pDsp->data[ ii ].output = dsp->data[ ii ].output;
-        pDsp->data[ ii ].testpoint = dsp->data[ ii ].testpoint;
-        pDsp->data[ ii ].swStatus = dsp->data[ ii ].swStatus;
-        pDsp->inputs[ ii ].opSwitchP = dsp->inputs[ ii ].opSwitchP;
-        // dsp->inputs[ii].limiter = pDsp->inputs[ii].limiter;
-        pDsp->inputs[ ii ].mask = dsp->inputs[ ii ].mask;
-        pDsp->inputs[ ii ].control = dsp->inputs[ ii ].control;
-#if 0
-	if (dsp->inputs[ii].mask & 0x20000000) { /* Offset controlled by the FE */
-        	pDsp->inputs[ii].offset = dsp->inputs[ii].offset;
-	} else {
-        	dsp->inputs[ii].offset = pDsp->inputs[ii].offset;
-	}
-	if (dsp->inputs[ii].mask & 0x40000000) { /* Gain controlled by the FE */
-        	pDsp->inputs[ii].outgain = dsp->inputs[ii].outgain;
-	} else {
-        	dsp->inputs[ii].outgain = pDsp->inputs[ii].outgain;
-	}
-	if (dsp->inputs[ii].mask & 0x80000000) { /* Ramp time controlled by the FE */
-        	pDsp->inputs[ii].gain_ramp_time = dsp->inputs[ii].gain_ramp_time;
-	} else {
-        	dsp->inputs[ii].gain_ramp_time = pDsp->inputs[ii].gain_ramp_time;
-	}
-#endif
-    }
-}
-inline void
-updateFmSetpoints( FILT_MOD* dsp,
-                   FILT_MOD* pDsp,
-                   COEF*     dspCoeff,
-                   VME_COEF* pCoeff )
-{
-    int ii;
-
-    for ( ii = 0; ii < MAX_MODULES; ii++ )
-    {
-        dsp->inputs[ ii ].opSwitchE = pDsp->inputs[ ii ].opSwitchE;
-        dsp->inputs[ ii ].limiter = pDsp->inputs[ ii ].limiter;
-        if ( dsp->inputs[ ii ].mask & 0x20000000 )
-        { /* Offset controlled by the FE */
-            pDsp->inputs[ ii ].offset = dsp->inputs[ ii ].offset;
-        }
-        else
-        {
-            dsp->inputs[ ii ].offset = pDsp->inputs[ ii ].offset;
-        }
-        if ( dsp->inputs[ ii ].mask & 0x40000000 )
-        { /* Gain controlled by the FE */
-            pDsp->inputs[ ii ].outgain = dsp->inputs[ ii ].outgain;
-        }
-        else
-        {
-            dsp->inputs[ ii ].outgain = pDsp->inputs[ ii ].outgain;
-        }
-        if ( dsp->inputs[ ii ].mask & 0x80000000 )
-        { /* Ramp time controlled by the FE */
-            pDsp->inputs[ ii ].gain_ramp_time =
-                dsp->inputs[ ii ].gain_ramp_time;
-        }
-        else
-        {
-            dsp->inputs[ ii ].gain_ramp_time =
-                pDsp->inputs[ ii ].gain_ramp_time;
-        }
-    }
-}
-
-/// Check for process stop command from EPICS
-///	@param[in] subcycle	Present code cycle
-///	@param[in] *plocalEpics	Pointer to EPICS data in shared memory
-inline int
-checkEpicsReset( int subcycle, CDS_EPICS* plocalEpics )
-{
-    int ii;
+#include "tRamp.h"
 
-    ii = subcycle;
+//#define LIGO_INLINE
+#include "epicsXfer.h"
 
-    if ( ( ii == MAX_MODULES ) && ( plocalEpics->epicsInput.vmeReset ) )
-    {
-        return ( 1 );
-    }
-
-    return ( 0 );
-}
-
-///	Perform gain ramping
+/// Perform gain ramping
 int
 gainRamp( float gainReq, int rampTime, int id, float* gain, int gainRate )
 {
@@ -149,3 +39,5 @@ gainRamp( float gainReq, int rampTime, int id, float* gain, int gainRate )
     *gain = gainOut[ id ];
     return ( 1 );
 }
+
+
diff --git a/src/include/drv/epicsXfer.h b/src/include/drv/epicsXfer.h
new file mode 100644
index 0000000000000000000000000000000000000000..f922f8246974fb5865c8685478e0c58892b83c19
--- /dev/null
+++ b/src/include/drv/epicsXfer.h
@@ -0,0 +1,127 @@
+#ifndef LIGO_EPICS_XFER_H
+#define LIGO_EPICS_XFER_H
+
+/// @file epicsXfer.h
+/// @brief File contains routines for:
+///<        - Exchanging filter module data with EPICS shared memory
+///<        - Checking for process kill command from EPICS
+///<        - Ramping algorithm, used by Product.pm part.
+/************************************************************************/
+
+
+#include "portableInline.h" //LIGO_INLINE
+#include "fm10Gen_types.h" 
+#include "fm10Gen.h" //checkFiltReset()
+//
+// Start function declarations
+//
+int gainRamp( float gainReq, int rampTime, int id, float* gain, int gainRate);
+
+
+
+
+
+
+//
+// Start Inline functions
+//
+
+
+
+///	Function to exchange filter module data with EPICS via shared memory.
+///	@param[in] subcycle		Filter Module ID for data transfer.
+///	@param[in] *dsp			Pointer to process memory fm data.
+///	@param[in] *pDsp		Pointer to shared memory fm data.
+///	@param[in] *dspCoeff		Pointer to process memory fm coeff data.
+///	@param[in] *pCoeff		Pointer to shared memory fm coeff data.
+/************************************************************************/
+LIGO_INLINE void
+updateEpics( int       subcycle,
+             FILT_MOD* dsp,
+             FILT_MOD* pDsp,
+             COEF*     dspCoeff,
+             VME_COEF* pCoeff )
+{
+    int ii;
+
+    ii = subcycle;
+    if ( ( ii >= 0 ) && ( ii < MAX_MODULES ) )
+    {
+        checkFiltReset( ii, dsp, pDsp, dspCoeff, MAX_MODULES, pCoeff );
+        // dsp->inputs[ii].opSwitchE = pDsp->inputs[ii].opSwitchE;
+        pDsp->data[ ii ].filterInput = dsp->data[ ii ].filterInput;
+        pDsp->data[ ii ].exciteInput = dsp->data[ ii ].exciteInput;
+        pDsp->data[ ii ].output16Hz = dsp->data[ ii ].output16Hz;
+        pDsp->data[ ii ].output = dsp->data[ ii ].output;
+        pDsp->data[ ii ].testpoint = dsp->data[ ii ].testpoint;
+        pDsp->data[ ii ].swStatus = dsp->data[ ii ].swStatus;
+        pDsp->inputs[ ii ].opSwitchP = dsp->inputs[ ii ].opSwitchP;
+        // dsp->inputs[ii].limiter = pDsp->inputs[ii].limiter;
+        pDsp->inputs[ ii ].mask = dsp->inputs[ ii ].mask;
+        pDsp->inputs[ ii ].control = dsp->inputs[ ii ].control;
+    }
+}
+
+
+LIGO_INLINE void
+updateFmSetpoints( FILT_MOD* dsp,
+                   FILT_MOD* pDsp,
+                   COEF*     dspCoeff,
+                   VME_COEF* pCoeff )
+{
+    int ii;
+
+    for ( ii = 0; ii < MAX_MODULES; ii++ )
+    {
+        dsp->inputs[ ii ].opSwitchE = pDsp->inputs[ ii ].opSwitchE;
+        dsp->inputs[ ii ].limiter = pDsp->inputs[ ii ].limiter;
+        if ( dsp->inputs[ ii ].mask & 0x20000000 )
+        { /* Offset controlled by the FE */
+            pDsp->inputs[ ii ].offset = dsp->inputs[ ii ].offset;
+        }
+        else
+        {
+            dsp->inputs[ ii ].offset = pDsp->inputs[ ii ].offset;
+        }
+        if ( dsp->inputs[ ii ].mask & 0x40000000 )
+        { /* Gain controlled by the FE */
+            pDsp->inputs[ ii ].outgain = dsp->inputs[ ii ].outgain;
+        }
+        else
+        {
+            dsp->inputs[ ii ].outgain = pDsp->inputs[ ii ].outgain;
+        }
+        if ( dsp->inputs[ ii ].mask & 0x80000000 )
+        { /* Ramp time controlled by the FE */
+            pDsp->inputs[ ii ].gain_ramp_time =
+                dsp->inputs[ ii ].gain_ramp_time;
+        }
+        else
+        {
+            dsp->inputs[ ii ].gain_ramp_time =
+                pDsp->inputs[ ii ].gain_ramp_time;
+        }
+    }
+}
+
+/// Check for process stop command from EPICS
+///	@param[in] subcycle	Present code cycle
+///	@param[in] *plocalEpics	Pointer to EPICS data in shared memory
+LIGO_INLINE int
+checkEpicsReset( int subcycle, CDS_EPICS* plocalEpics )
+{
+    int ii;
+
+    ii = subcycle;
+
+    if ( ( ii == MAX_MODULES ) && ( plocalEpics->epicsInput.vmeReset ) )
+    {
+        return ( 1 );
+    }
+
+    return ( 0 );
+}
+
+
+#endif //LIGO_EPICS_XFER_H
+
diff --git a/src/include/drv/fb.h b/src/include/drv/fb.h
index 30386166cf98b106f7dc6a41a7f881c905b3db49..3d05887ecd2b9db60693799af5902da5105384c0 100644
--- a/src/include/drv/fb.h
+++ b/src/include/drv/fb.h
@@ -1,6 +1,11 @@
 #ifndef FB_H_INCLUDED
 #define FB_H_INCLUDED
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 int cdsDaqNetInit(int);	  /* Initialize DAQ network		*/
 int cdsDaqNetClose(void);  /* Close CDS network connection	*/
 int cdsDaqNetCheckCallback(void);/* Check for messages on 	*/
@@ -18,6 +23,11 @@ int cdsDaqNetDaqSend(   int dcuId,
                         int xferSize,
                         char *dataBuffer);
 
+#ifdef __cplusplus
+}
+#endif
+
+
 /* Offset in the shared memory to the beginning of data buffer */
 #define CDS_DAQ_NET_DATA_OFFSET 0x2000
 /* Offset to GDS test point table (struct cdsDaqNetGdsTpNum, defined in daqmap.h) */
diff --git a/src/include/drv/fm10Gen.c b/src/include/drv/fm10Gen.c
index cc3dc6221163932b881ac4ed56afa653e3c27cf9..c99a47c51c72918830615113051d8496215a0e9c 100644
--- a/src/include/drv/fm10Gen.c
+++ b/src/include/drv/fm10Gen.c
@@ -1,70 +1,20 @@
-/*-----------------------------------------------------------------------------
- */
-/*                                                                              */
-/*                      ------------------- */
-/*                                                                              */
-/*                             LIGO */
-/*                                                                              */
-/*        THE LASER INTERFEROMETER GRAVITATIONAL WAVE OBSERVATORY. */
-/*                                                                              */
-/*                     (C) The LIGO Project, 2005. */
-/*                                                                              */
-/*                                                                              */
-/* File: fm10Gen.c */
-/* Description: */
-/*      CDS generic code for calculating IIR filters. */
-/*                                                                              */
-/* California Institute of Technology */
-/* LIGO Project MS 18-34 */
-/* Pasadena CA 91125 */
-/*                                                                              */
-/* Massachusetts Institute of Technology */
-/* LIGO Project MS 20B-145 */
-/* Cambridge MA 01239 */
-/*                                                                              */
-/*-----------------------------------------------------------------------------
- */
-
-///	@file fm10Gen.c
-///	@brief This file contains the routines for performing the real-time
-///		IIR/FIR filter calculations. \n
-///	Further information is provided in the LIGO DCC
-///	<a
-///href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7687">T0900606
-///CDS Standard IIR Filter Module Software</a>
-
+//#define LIGO_INLINE
 #include "fm10Gen.h"
-
-/* Switching register bits */
-#define OPSWITCH_INPUT_ENABLE 0x4
-#define OPSWITCH_OFFSET_ENABLE 0x8
-#define OPSWITCH_LIMITER_ENABLE 0x1000000
-#define OPSWITCH_DECIMATE_ENABLE 0x2000000
-#define OPSWITCH_OUTPUT_ENABLE 0x4000000
-#define OPSWITCH_HOLD_ENABLE 0x8000000
-
-#define OPSWITCH_LIMITER_RAMPING 0x20000000
-#define OPSWITCH_GAIN_RAMPING    0x10000000
+#include "crc.h" //crc_ptr()
+#include "util/inlineMath.h"
 
 /// Quick look up table for power of 2 calcs
-const UINT32 pow2_in[ 10 ] = { 0x10,   0x40,    0x100,   0x400,    0x1000,
+static const UINT32 pow2_in[ 10 ] = { 0x10,   0x40,    0x100,   0x400,    0x1000,
                                0x4000, 0x10000, 0x40000, 0x100000, 0x400000 };
+
 /// Quick look up table for power of 2 calcs
-const UINT32 pow2_out[ 10 ] = { 0x20,   0x80,    0x200,   0x800,    0x2000,
+static const UINT32 pow2_out[ 10 ] = { 0x20,   0x80,    0x200,   0x800,    0x2000,
                                 0x8000, 0x20000, 0x80000, 0x200000, 0x800000 };
 
-/// Quick look up table for filter module switch decoding
-const UINT32
-    fltrConst[ 17 ] = { 16,        64,        256,     1024,    4096, 16384,
-                        65536,     262144,    1048576, 4194304, 0x4,  0x8,
-                        0x4000000, 0x1000000, 0x1, /* in sw, off sw, out sw ,
-                                                      limit sw*/
-                        0x2000000, 0x8000000 };
-
 #if defined( SERVO16K ) || defined( SERVO512K ) || defined( SERVO32K ) ||      \
     defined( SERVO64K ) || defined( SERVO128K ) || defined( SERVO256K ) ||     \
     defined( SERVO1024K )
-double sixteenKAvgCoeff[ 9 ] = { 1.9084759e-12,    -1.99708675982420,
+static double sixteenKAvgCoeff[ 9 ] = { 1.9084759e-12,    -1.99708675982420,
                                  0.99709029700517, 2.00000005830747,
                                  1.00000000739582, -1.99878510620232,
                                  0.99879373895648, 1.99999994169253,
@@ -72,13 +22,14 @@ double sixteenKAvgCoeff[ 9 ] = { 1.9084759e-12,    -1.99708675982420,
 #endif
 
 #if defined( SERVO2K ) || defined( SERVO4K )
-double twoKAvgCoeff[ 9 ] = { 7.705446e-9,      -1.97673337437048,
+static double twoKAvgCoeff[ 9 ] = { 7.705446e-9,      -1.97673337437048,
                              0.97695747524900, 2.00000006227141,
                              1.00000000659235, -1.98984125831661,
                              0.99039139954634, 1.99999993772859,
                              0.99999999340765 };
 #endif
 
+
 #ifdef SERVO16K
 #define avgCoeff sixteenKAvgCoeff
 #elif defined( SERVO32K ) || defined( SERVO64K ) || defined( SERVO128K ) ||    \
@@ -97,192 +48,74 @@ double twoKAvgCoeff[ 9 ] = { 7.705446e-9,      -1.97673337437048,
 #error need to define 2k or 16k or mixed
 #endif
 
-#ifdef SERVO1024K
-#define FE_RATE 1048576
-#endif
-#ifdef SERVO512K
-#define FE_RATE 524288
-#endif
-#ifdef SERVO256K
-#define FE_RATE 262144
-#endif
-#ifdef SERVO128K
-#define FE_RATE 131072
-#endif
-#ifdef SERVO64K
-#define FE_RATE 65536
-#endif
-#ifdef SERVO32K
-#define FE_RATE 32768
-#endif
-#ifdef SERVO16K
-#define FE_RATE 16384
-#endif
-#ifdef SERVO4K
-#define FE_RATE 4096
-#endif
-#ifdef SERVO2K
-#define FE_RATE 2048
-#endif
-
-/// New tRamp.c gain ramping strcuture
-RampParamState gain_ramp[ MAX_MODULES ][ 10 ];
-
-/// New tRamp.c gain offset strcuture
-RampParamState offset_ramp[ MAX_MODULES ][ 10 ];
-
-/// @brief Perform IIR filtering sample by sample on doubles.
-/// Implements cascaded direct form II second order sections.
-///	@param[in] input New input sample
-///	@param[in] *coef Pointer to filter coefficient data with size 4*n + 1
-///(gain)
-///	@param[in] n Number of second order sections in filter definition
-///	@param[in,out] *history Pointer to filter history data of size 2*n
-///	@return Result of filter calculation
-inline double
-iir_filter( double input, double* coef, int n, double* history )
-{
-
-    int     i;
-    double* coef_ptr;
-    double *hist1_ptr, *hist2_ptr;
-    double  output, new_hist, history1, history2;
-
-    coef_ptr = coef; /* coefficient pointer */
-
-    hist1_ptr = history; /* first history */
-    hist2_ptr = hist1_ptr + 1; /* next history */
-
-    output = input * ( *coef_ptr++ ); /* overall input scale factor */
 
-    for ( i = 0; i < n; i++ )
-    {
-
-        history1 = *hist1_ptr; /* history values */
-        history2 = *hist2_ptr;
-
-        output = output - history1 * ( *coef_ptr++ );
-        new_hist = output - history2 * ( *coef_ptr++ ); /* poles */
-
-        output = new_hist + history1 * ( *coef_ptr++ );
-        output = output + history2 * ( *coef_ptr++ ); /* zeros */
-
-        *hist2_ptr++ = *hist1_ptr;
-        *hist1_ptr++ = new_hist;
-        hist1_ptr++;
-        hist2_ptr++;
-    }
-
-    return ( output );
-}
-
-/* Biquad form IIR */
-/// @brief Perform IIR filtering sample by sample on doubles.
-/// Implements Biquad form calculations.
-///	@param[in] input New input sample
-///	@param[in] *coef Pointer to filter coefficient data with size 4*n + 1
-///(gain)
-///	@param[in] n Number of second order sections in filter definition
-///	@param[in,out] *history Pointer to filter history data of size 2*n
-///	@return Result of filter calculation
-inline double
-iir_filter_biquad( double input, double* coef, int n, double* history )
-{
-
-    int     i;
-    double* coef_ptr;
-    double *hist1_ptr, *hist2_ptr;
-    double  output, new_w, new_u, w, u, a11, a12, c1, c2;
-
-    coef_ptr = coef; /* coefficient pointer */
-
-    hist1_ptr = history; /* first history */
-    hist2_ptr = hist1_ptr + 1; /* next history */
-
-    output = input * ( *coef_ptr++ ); /* overall input scale factor */
-
-    for ( i = 0; i < n; i++ )
-    {
-
-        w = *hist1_ptr;
-        u = *hist2_ptr;
-
-        a11 = *coef_ptr++;
-        a12 = *coef_ptr++;
-        c1 = *coef_ptr++;
-        c2 = *coef_ptr++;
-
-        new_w = output + a11 * w + a12 * u;
-        output = output + w * c1 + u * c2;
-        new_u = w + u;
 
-        *hist1_ptr++ = new_w;
-        *hist2_ptr++ = new_u;
-        hist1_ptr++;
-        hist2_ptr++;
-    }
-
-    // if((output < 1e-28) && (output > -1e-28)) output = 0.0;
-    return ( output );
-}
 
-#ifdef FIR_FILTERS
-// *************************************************************************/
-///	@brief Perform FIR filter calculations.
-///	@param[in] input New input sample
-///	@param[in] *coef Pointer to filter coefficients
-///	@param[in] n Number of taps
-///	@param[in,out] *history Pointer to filter history data
-///	@return Result of FIR filter calculation
-inline double
-fir_filter( double input, double* coef, int n, double* history )
-{
-    int     i;
-    double *hist_ptr, *hist1_ptr, *coef_ptr;
-    double  output;
-
-    hist_ptr = history;
-    hist1_ptr = hist_ptr; /* use for history update */
-    coef_ptr = coef + n - 1; /* point to last coef */
-
-    /* form output accumulation */
-    output = *hist_ptr++ * ( *coef_ptr-- );
-    for ( i = 2; i < n; i++ )
-    {
-        *hist1_ptr++ = *hist_ptr; /* update history array */
-        output += ( *hist_ptr++ ) * ( *coef_ptr-- );
-    }
-    output += input * ( *coef_ptr ); /* input tap */
-    *hist1_ptr = input; /* last history */
+/// Quick look up table for filter module switch decoding
+static const UINT32
+    fltrConst[ 17 ] = { 16,        64,        256,     1024,    4096, 16384,
+                        65536,     262144,    1048576, 4194304, 0x4,  0x8,
+                        0x4000000, 0x1000000, 0x1, /* in sw, off sw, out sw ,
+                                                      limit sw*/
+                        0x2000000, 0x8000000 };
 
-    return ( output );
-}
-#endif
 
 #ifdef SERVO16K
-const int rate = 16384;
+static const int rate = 16384;
 #elif defined( SERVO5HZ )
-const int rate = 5;
+static const int rate = 5;
 #elif defined( SERVO2K )
-const int rate = 2048;
+static const int rate = 2048;
 #elif defined( SERVO4K )
-const int rate = 4096;
+static const int rate = 4096;
 #elif defined( SERVO32K )
-const int rate = 32768;
+static const int rate = 32768;
 #elif defined( SERVO64K )
-const int rate = ( 2 * 32768 );
+static const int rate = ( 2 * 32768 );
 #elif defined( SERVO128K )
-const int rate = ( 4 * 32768 );
+static const int rate = ( 4 * 32768 );
 #elif defined( SERVO256K )
-const int rate = ( 8 * 32768 );
+static const int rate = ( 8 * 32768 );
 #elif defined( SERVO512K )
-const int rate = ( 16 * 32768 );
+static const int rate = ( 16 * 32768 );
 #elif defined( SERVO1024K )
-const int rate = ( 32 * 32768 );
+static const int rate = ( 32 * 32768 );
 #endif
 
+/// New tRamp.h gain ramping strcuture
+static RampParamState gain_ramp[ MAX_MODULES ][ 10 ];
+
+/// New tRamp.h gain offset strcuture
+static RampParamState offset_ramp[ MAX_MODULES ][ 10 ];
+
+
+/// Filter module update globals
+typedef struct filtResetId_t
+{
+    int       fmResetCoeff;
+    int       fmResetCounter;
+    int       fmSubCounter;
+    FILT_MOD* fmResetDsp;
+    int       changed[ FILTERS ];
+} filtResetId_t;
+
+static filtResetId_t filtResetId[ FILTERS ] = 
+              { { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+              { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+              { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+              { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+              { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+              { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+              { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+              { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+              { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+              { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } };
+
+
+
+
 /* Convert opSwitchE bits into the 16-bit FiltCtrl2 Ctrl output format */
-inline unsigned int
+unsigned int
 filtCtrlBitConvert( unsigned int v )
 {
     unsigned int val = 0;
@@ -295,96 +128,21 @@ filtCtrlBitConvert( unsigned int v )
     return val;
 }
 
-/************************************************************************/
-/************************************************************************/
-/// @brief Read in filter coeffs from shared memory on code initialization.
-///	@param[in,out] *filtC Pointer to coeffs in local memory
-///	@param[in] *fmt Pointer to filter data in local memory
-///	@param[in] bF	Start filter number
-///	@param[in] sF	End filter number
-///	@param[in] *pRfmCoeff Pointer to coeffs in shared memory
-inline int
-readCoefVme(
-    COEF* filtC, FILT_MOD* fmt, int bF, int sF, volatile VME_COEF* pRfmCoeff )
-{
-    int ii, jj, kk;
-
-#ifdef FIR_FILTERS
-    int l;
-    for ( jj = 0; jj < MAX_FIR_MODULES; jj++ )
-        for ( kk = 0; kk < FILTERS; kk++ )
-            for ( l = 0; l < MAX_FIR_COEFFS; l++ )
-                filtC->firFiltCoeff[ jj ][ kk ][ l ] =
-                    pRfmCoeff->firFiltCoeff[ jj ][ kk ][ l ];
-#endif
-    for ( ii = bF; ii < sF; ii++ )
-    {
-        filtC->coeffs[ ii ].biquad = pRfmCoeff->vmeCoeffs[ ii ].biquad;
-        // if(filtC->coeffs[ii].biquad) printf("Found a BQF filter %d\n",ii);
-        for ( jj = 0; jj < FILTERS; jj++ )
-        {
-            if ( pRfmCoeff->vmeCoeffs[ ii ].filtSections[ jj ] )
-            {
-                filtC->coeffs[ ii ].filterType[ jj ] =
-                    pRfmCoeff->vmeCoeffs[ ii ].filterType[ jj ];
-#ifdef FIR_FILTERS
-                if ( filtC->coeffs[ ii ].filterType[ jj ] < 0 ||
-                     filtC->coeffs[ ii ].filterType[ jj ] > MAX_FIR_MODULES )
-                {
-                    filtC->coeffs[ ii ].filterType[ jj ] = 0;
-                    // printk("Corrupted data coming from Epics: module=%d
-                    // filter=%d filterType=%d\n",
-                    //	ii, jj, pRfmCoeff->vmeCoeffs[ii].filterType[jj]);
-                    return 1;
-                }
-#endif
-                filtC->coeffs[ ii ].filtSections[ jj ] =
-                    pRfmCoeff->vmeCoeffs[ ii ].filtSections[ jj ];
-                filtC->coeffs[ ii ].sType[ jj ] =
-                    pRfmCoeff->vmeCoeffs[ ii ].sType[ jj ];
-                fmt->inputs[ ii ].rmpcmp[ jj ] =
-                    pRfmCoeff->vmeCoeffs[ ii ].ramp[ jj ];
-                fmt->inputs[ ii ].timeout[ jj ] =
-                    pRfmCoeff->vmeCoeffs[ ii ].timout[ jj ];
-
-                if ( filtC->coeffs[ ii ].filterType[ jj ] == 0 )
-                {
-                    if ( filtC->coeffs[ ii ].filtSections[ jj ] > 10 )
-                    {
-                        // printk("Corrupted Epics data:  module=%d filter=%d
-                        // filterType=%d filtSections=%d\n", ii, jj,
-                        // pRfmCoeff->vmeCoeffs[ii].filterType[jj],
-                        // filtC->coeffs[ii].filtSections[jj]);
-                        return 1;
-                    }
-                    for ( kk = 0;
-                          kk < filtC->coeffs[ ii ].filtSections[ jj ] * 4 + 1;
-                          kk++ )
-                    {
-                        filtC->coeffs[ ii ].filtCoeff[ jj ][ kk ] =
-                            pRfmCoeff->vmeCoeffs[ ii ].filtCoeff[ jj ][ kk ];
-                    }
-                }
-            }
-        }
-    }
-    return 0;
-}
 
 /**************************************************/
 /* Read in new coeffs while running
         - One filter bank at a time.
-        - One SOS at a time.			  */
+        - One SOS at a time.                      */
 /**************************************************/
 /// @brief Read in filter coeffs from shared memory while code is running ie
 /// filter reload initiated.
-///	@param[in,out] *filtC Pointer to coeffs in local memory
-///	@param[in] *fmt Pointer to filter data in local memory
-///	@param[in] modNum1	ID number of the filter module
-///	@param[in] filtNum	ID number of the filter within the module
-///	@param[in] cycle	Code cycle number
-///	@param[in] *pRfmCoeff 	Pointer to coeffs in shared memory
-///	@param[in] *changed	Pointer to filter coef change flag memory.
+///     @param[in,out] *filtC Pointer to coeffs in local memory
+///     @param[in] *fmt Pointer to filter data in local memory
+///     @param[in] modNum1      ID number of the filter module
+///     @param[in] filtNum      ID number of the filter within the module
+///     @param[in] cycle        Code cycle number
+///     @param[in] *pRfmCoeff   Pointer to coeffs in shared memory
+///     @param[in] *changed     Pointer to filter coef change flag memory.
 int
 readCoefVme2( COEF*              filtC,
               FILT_MOD*          fmt,
@@ -413,12 +171,12 @@ readCoefVme2( COEF*              filtC,
 #ifdef FIR_FILTERS
     if ( type < 0 || type > MAX_FIR_MODULES )
     {
-        // printk("Vme2 bad Epics filter type: module=%d filter=%d
+        // printl("Vme2 bad Epics filter type: module=%d filter=%d
         // filterType=%d\n", modNum1, filtNum, type);
     }
 #endif
 
-    // printf("readCoefVme2: module=%d filter=%d filterType=%d\n", modNum1,
+    // printl("readCoefVme2: module=%d filter=%d filterType=%d\n", modNum1,
     // filtNum, type);
 
     ii = 0;
@@ -432,7 +190,7 @@ readCoefVme2( COEF*              filtC,
         localCoeff.crc = crc_ptr( (char*)&ii, sizeof( int ), localCoeff.crc );
         if ( ( ( ii > 0 ) && ( ii < 11 ) ) || ( ( ii > 10 ) && ( type > 0 ) ) )
         {
-            // printf("vme2: module=%d filter=%d type=%d\n", modNum1, filtNum,
+            // printl("vme2: module=%d filter=%d type=%d\n", modNum1, filtNum,
             // type);
             localCoeff.filtSections[ filtNum ] = ii;
             localCoeff.filterType[ filtNum ] = type;
@@ -455,7 +213,7 @@ readCoefVme2( COEF*              filtC,
         }
         else
         {
-            // printf("vme2:off  module=%d filter=%d type=%d\n", modNum1,
+            // printl("vme2:off  module=%d filter=%d type=%d\n", modNum1,
             // filtNum, type);
             /* Turn filter status readback off */
             fmt->inputs[ modNum1 ].opSwitchP &= ~pow2_out[ filtNum ];
@@ -481,7 +239,7 @@ readCoefVme2( COEF*              filtC,
                 localFirFiltCoeff[ filtNum ][ 0 ] = temp;
                 localCoeff.crc =
                     crc_ptr( (char*)&temp, sizeof( double ), localCoeff.crc );
-                // printf("gain = %f\n", temp);
+                // printl("gain = %f\n", temp);
 #endif
             }
             else
@@ -517,7 +275,7 @@ readCoefVme2( COEF*              filtC,
                     localFirFiltCoeff[ filtNum ][ kk ] = temp;
                     localCoeff.crc = crc_ptr(
                         (char*)&temp, sizeof( double ), localCoeff.crc );
-                    // printf("%f ", temp);
+                    // printl("%f ", temp);
 #endif
                 }
                 else
@@ -536,7 +294,7 @@ readCoefVme2( COEF*              filtC,
                         localCoeff.crc );
                 }
             }
-            // if (type > 0) printf("\n");
+            // if (type > 0) printl("\n");
             if ( localCoeff.filtSections[ filtNum ] > cycle )
                 ii = cycle + 1;
             else
@@ -551,7 +309,7 @@ readCoefVme2( COEF*              filtC,
             unsigned int vme_crc = pRfmCoeff->vmeCoeffs[ modNum1 ].crc;
             if ( localCoeff.crc != vme_crc )
             {
-                // printk("vme_crc = 0x%x; local crc = 0x%x\n", vme_crc,
+                // printl("vme_crc = 0x%x; local crc = 0x%x\n", vme_crc,
                 // localCoeff.crc); return -1;
             }
         }
@@ -583,9 +341,9 @@ readCoefVme2( COEF*              filtC,
 
             /* Do not clear decimation history when filters are reloaded */
 #if 0
-	  /* Clear decimation history */
-	  for(jj = 0; jj < 8; jj++)
-	    filtC->coeffs[modNum1].decHist[jj] = 0;
+          /* Clear decimation history */
+          for(jj = 0; jj < 8; jj++)
+            filtC->coeffs[modNum1].decHist[jj] = 0;
 #endif
 
             filtC->coeffs[ modNum1 ].filtSections[ filtNum ] =
@@ -628,37 +386,18 @@ readCoefVme2( COEF*              filtC,
 #undef MAX_UPDATE_CYCLE
 }
 
-/// Filter module update globals
-struct filtResetId
-{
-    int       fmResetCoeff;
-    int       fmResetCounter;
-    int       fmSubCounter;
-    FILT_MOD* fmResetDsp;
-    int       changed[ FILTERS ];
-} filtResetId[ FILTERS ] = { { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
-                             { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
-                             { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
-                             { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
-                             { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
-                             { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
-                             { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
-                             { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
-                             { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
-                             { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } };
-
 /***************************************/
 /* Check for history resets or new coeffs for filter banks */
 /***************************************/
-///	@brief Checks for history resets or new coefs for filter modules.
-///	@param[in] bankNum	Filter module ID number
-///	@param[in,out] *pL	Pointer to filter module data in local memory.
-///	@param[in] *dspVme	Pointer to filter module data in shared memory.
-///	@param[in,out] *pC	Pointer to filter coefs in local memory.
-///	@param[in] totMod	Total number of filter modules
-///	@param[in] *pRfmCoeff	Pointer to filter coefs in shared memory.
-///	@param[in] id		System ID number (old HEPI only).
-static inline void
+///     @brief Checks for history resets or new coefs for filter modules.
+///     @param[in] bankNum      Filter module ID number
+///     @param[in,out] *pL      Pointer to filter module data in local memory.
+///     @param[in] *dspVme      Pointer to filter module data in shared memory.
+///     @param[in,out] *pC      Pointer to filter coefs in local memory.
+///     @param[in] totMod       Total number of filter modules
+///     @param[in] *pRfmCoeff   Pointer to filter coefs in shared memory.
+///     @param[in] id           System ID number (old HEPI only).
+void
 checkFiltResetId( int                bankNum,
                   FILT_MOD*          pL,
                   volatile FILT_MOD* dspVme,
@@ -681,7 +420,7 @@ checkFiltResetId( int                bankNum,
         /* Coeff reset in progress */
         if ( filtResetId[ id ].fmResetDsp == pL )
         { /* Coeff reset is done for this subsystem */
-            /* printf("Coeff reset done\n"); */
+            /* printl("Coeff reset done\n"); */
             filtResetId[ id ].fmSubCounter =
                 readCoefVme2( pC,
                               pL,
@@ -703,7 +442,7 @@ checkFiltResetId( int                bankNum,
                 {
                     filtResetId[ id ].fmResetCounter = 0;
                     dspVme->coef_load_error = filtResetId[ id ].fmResetCoeff;
-                    /* printf("dspVme->coef_load_error = %d\n",
+                    /* printl("dspVme->coef_load_error = %d\n",
                      * dspVme->coef_load_error ); */
                     filtResetId[ id ].fmResetCoeff = 0;
                 }
@@ -750,7 +489,7 @@ checkFiltResetId( int                bankNum,
         /* Check if new coeffs */
         if ( status & 1 )
         {
-            /* printf("New coeff request; bank=%d \n", bankNum); */
+            /* printl("New coeff request; bank=%d \n", bankNum); */
             filtResetId[ id ].fmResetCoeff = bankNum + 1;
             filtResetId[ id ].fmResetDsp = pL;
         }
@@ -759,37 +498,20 @@ checkFiltResetId( int                bankNum,
     }
 }
 
-///	@brief Calls checkFiltResetId with dummy sys id of 0
-///	@param[in] bankNum	Filter module ID number
-///	@param[in,out] *pL	Pointer to filter module data in local memory.
-///	@param[in] *dspVme	Pointer to filter module data in shared memory.
-///	@param[in,out] *pC	Pointer to filter coefs in local memory.
-///	@param[in] totMod	Total number of filter modules
-///	@param[in] *pRfmCoeff	Pointer to filter coefs in shared memory.
-inline void
-checkFiltReset( int                bankNum,
-                FILT_MOD*          pL,
-                volatile FILT_MOD* dspVme,
+
+///     @brief Initialize filter module variables on code startup
+///     @param[in,out] *pL      Pointer to filter module data in local memory
+///     @param[in] *pV          Pointer to filter module data in shared memory
+///     @param[in,out] *pC      Pointer to filter coeffs in local memory
+///     @param[in] totMod       Total number of filter modules
+///     @param[in] *pRfmCoeff   Pointer to filter coeffs in shared memory
+///     @param[in] id           System id (old HEPI only)
+int initVarsId( FILT_MOD*          pL,
+                volatile FILT_MOD* pV,
                 COEF*              pC,
                 int                totMod,
-                volatile VME_COEF* pRfmCoeff )
-{
-    checkFiltResetId( bankNum, pL, dspVme, pC, totMod, pRfmCoeff, 0 );
-}
-
-///	@brief Initialize filter module variables on code startup
-///	@param[in,out] *pL	Pointer to filter module data in local memory
-///	@param[in] *pV		Pointer to filter module data in shared memory
-///	@param[in,out] *pC	Pointer to filter coeffs in local memory
-///	@param[in] totMod	Total number of filter modules
-///	@param[in] *pRfmCoeff	Pointer to filter coeffs in shared memory
-///	@param[in] id		System id (old HEPI only)
-inline int initVarsId( FILT_MOD*          pL,
-                       volatile FILT_MOD* pV,
-                       COEF*              pC,
-                       int                totMod,
-                       volatile VME_COEF* pRfmCoeff,
-                       int                id ) /* System id (HEPI) */
+                volatile VME_COEF* pRfmCoeff,
+                int                id ) /* System id (HEPI) */
 {
     int ii, kk, hh;
 
@@ -845,25 +567,7 @@ inline int initVarsId( FILT_MOD*          pL,
     return readCoefVme( pC, pL, 0, totMod, pRfmCoeff );
 }
 
-///	@brief Calls initVarsId with dummy sys id of 0
-///	@param[in,out] *pL	Pointer to filter module data in local memory
-///	@param[in] *pV		Pointer to filter module data in shared memory
-///	@param[in,out] *pC	Pointer to filter coeffs in local memory
-///	@param[in] totMod	Total number of filter modules
-///	@param[in] *pRfmCoeff	Pointer to filter coeffs in shared memory
-inline int
-initVars( FILT_MOD*          pL,
-          volatile FILT_MOD* pV,
-          COEF*              pC,
-          int                totMod,
-          volatile VME_COEF* pRfmCoeff )
-{
-    return initVarsId( pL, pV, pC, totMod, pRfmCoeff, 0 );
-}
 
-/* This module added to hanle all input, calculations and outputs as doubles.
-   This module also incorporates the input module, done separately above for
-   older systems. */
 
 /* Mask logic table:
  * M-mask; C-control input; S0-current bit state; S1-new bit state
@@ -878,19 +582,19 @@ initVars( FILT_MOD*          pL,
                1  0  1  0
                1  1  1  1
       */
-/// 	@brief This function is called by filterModuleD, or, in the case of FMC2
+///     @brief This function is called by filterModuleD, or, in the case of FMC2
 /// parts, user code directly to
 ///< perform CDS standard filter module calculations.
-///	@param[in,out] *pFilt Filter Module Data
-///	@param[in] *pC Filter module coefficients
-///	@param[in] modNum Filter module ID number
-///	@param[in] filterInput Input data sample
-///	@param[in] fltrCtrlVal Filter control value
-///	@param[in] mask Control mask
-///	@param[in] offset_in Filter module DC offset value from user model.
-///	@param[in] gain_in Filter module gain value from user model.
-///	@param[in] ramp_in Ramping time from user model.
-///	@return Output of IIR/FIR filter calculations.
+///     @param[in,out] *pFilt Filter Module Data
+///     @param[in] *pC Filter module coefficients
+///     @param[in] modNum Filter module ID number
+///     @param[in] filterInput Input data sample
+///     @param[in] fltrCtrlVal Filter control value
+///     @param[in] mask Control mask
+///     @param[in] offset_in Filter module DC offset value from user model.
+///     @param[in] gain_in Filter module gain value from user model.
+///     @param[in] ramp_in Ramping time from user model.
+///     @return Output of IIR/FIR filter calculations.
 double
 filterModuleD2( FILT_MOD* pFilt, /* Filter module data  */
                 COEF*     pC, /* Filter coefficients */
@@ -912,7 +616,6 @@ filterModuleD2( FILT_MOD* pFilt, /* Filter module data  */
     double     output;
     double     fmInput;
     int        id = 0; /* System number (HEPI) */
-    extern int cycleNum;
     unsigned int swstat = 0;
 
     /* Do the shift to match the bits in the the opSwitchE variable so I can do
@@ -1056,7 +759,7 @@ filterModuleD2( FILT_MOD* pFilt, /* Filter module data  */
             int firNum = ( cycleNum / 32 ) % 64;
 #endif
             // int firNum = cycleNum % 32;
-            // printf("cycleNum=%d; firNum=%d\n", cycleNum, firNum);
+            // printl("cycleNum=%d; firNum=%d\n", cycleNum, firNum);
 
             /* FIR filter */
             --filterType;
@@ -1080,7 +783,7 @@ filterModuleD2( FILT_MOD* pFilt, /* Filter module data  */
                 else
                 {
                     filtData = filterType;
-                    // printk("module %d; filter %d; filterType = %d\n", modNum,
+                    // printl("module %d; filter %d; filterType = %d\n", modNum,
                     // ii, filterType);
                 }
             }
@@ -1122,7 +825,7 @@ filterModuleD2( FILT_MOD* pFilt, /* Filter module data  */
                 ramp = pFilt->inputs[ modNum ]
                            .rmpcmp[ ii ]; /* Ramp slope coefficient */
                 kk = pFilt->inputs[ modNum ].cnt[ ii ]; /* Ramp count */
-                /* printf("kk=%d; ramp=%d; sw=%d; sw_out=%d\n", kk, ramp, sw,
+                /* printl("kk=%d; ramp=%d; sw=%d; sw_out=%d\n", kk, ramp, sw,
                  * sw_out); */
 
                 if ( kk == ramp )
@@ -1300,34 +1003,3 @@ filterModuleD2( FILT_MOD* pFilt, /* Filter module data  */
     return output;
 }
 
-/// 	@brief This function is called by user apps using standard IIR/FIR
-/// filters..
-///< This function in turn calls filterModuleD2 to actually perform the calcs,
-///< with dummy vars added.
-///	@param[in,out] *pFilt Filter Module Data
-///	@param[in] *pC Filter module coefficients
-///	@param[in] modNum Filter module ID number
-///	@param[in] filterInput Input data sample
-///	@param[in] fltrCtrlVal Filter control value
-///	@param[in] mask Control mask
-///	@return Output of IIR/FIR filter calculations.
-inline double
-filterModuleD( FILT_MOD* pFilt, /* Filter module data  */
-               COEF*     pC, /* Filter coefficients */
-               int       modNum, /* Filter module number */
-               double    filterInput, /* Input data sample (output from funtcion
-                                         inputModule()) */
-               int fltrCtrlVal, /* Filter control value */
-               int mask ) /* Mask of bits to act upon */
-{
-    /* Limit control to the 10 bits */
-    return filterModuleD2( pFilt,
-                           pC,
-                           modNum,
-                           filterInput,
-                           fltrCtrlVal & 0x3ff,
-                           mask & 0x3ff,
-                           0.,
-                           0.,
-                           0. );
-}
diff --git a/src/include/drv/gsc16ai64.c b/src/include/drv/gsc16ai64.c
index 9dbb37bd840a037c2210315509627ecf997adc09..569ea0ec578926074dff9f119f77e30163dbd0d3 100644
--- a/src/include/drv/gsc16ai64.c
+++ b/src/include/drv/gsc16ai64.c
@@ -8,9 +8,15 @@
 ///<    href="http://www.generalstandards.com/view-products2.php?BD_family=16ai64ssc">GSC
 ///<    16AI64SSC Manual</a>
 
-#include "gsc_adc_common.h"
 #include "gsc16ai64.h"
+#include "gsc_adc_common.h"
 #include "ioremap_selection.h"
+#include "drv/plx_9056.h" //adcDma
+#include "util/printl.h"
+
+#include <linux/pci.h> //PCI_BASE_ADDRESS_0
+#include <linux/delay.h> //udelay()
+
 
 // *****************************************************************************
 /// \brief Routine to initialize GSC 16bit, 32 channel ADC modules
@@ -48,7 +54,7 @@ gsc16ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
 #endif
     if(pedStatus != 0)
         return -1;
-    printk( "pci0 = 0x%x\n", pci_io_addr );
+    printl( "pci0 = 0x%x\n", pci_io_addr );
     /// Map module DMA space directly to computer memory space.
     _adc_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
     /// Map the module DMA control registers via PLX chip registers
@@ -58,14 +64,14 @@ gsc16ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     pedStatus = pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_2, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "pci2 = 0x%x\n", pci_io_addr );
+    printl( "pci2 = 0x%x\n", pci_io_addr );
     /// Map the module control register so local memory space.
     _adc_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
-    printk( "ADC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_adc_add );
+    printl( "ADC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_adc_add );
     /// Set global ptr to control register memory space.
     _adcPtr[ devNum ] = (GSA_ADC_REG*)_adc_add;
 
-    printk( "BCR = 0x%x\n", _adcPtr[ devNum ]->BCR );
+    printl( "BCR = 0x%x\n", _adcPtr[ devNum ]->BCR );
     /// Reset the ADC board
     _adcPtr[ devNum ]->BCR |= GSAI_RESET;
     do
@@ -88,8 +94,8 @@ gsc16ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     /// This is used for Cymac using ADC internal clock
     _adcPtr[ devNum ]->RAG =
         (unsigned int)( GSC16AI64_OSC_FREQ / ( UNDERSAMPLE * IOP_IO_RATE ) );
-    printk( "RAG = %d \n", _adcPtr[ devNum ]->RAG );
-    printk( "BCR = 0x%x\n", _adcPtr[ devNum ]->BCR );
+    printl( "RAG = %d \n", _adcPtr[ devNum ]->RAG );
+    printl( "BCR = 0x%x\n", _adcPtr[ devNum ]->BCR );
     _adcPtr[ devNum ]->RAG &= ~( GSAI_SAMPLE_START );
     /// Initiate board calibration
     _adcPtr[ devNum ]->BCR |= GSAI_AUTO_CAL;
@@ -101,12 +107,12 @@ gsc16ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     } while ( ( _adcPtr[ devNum ]->BCR & GSAI_AUTO_CAL ) != 0 );
     if ( ( _adcPtr[ devNum ]->BCR & GSAI_AUTO_CAL_PASS ) == 0 )
     {
-        printk( "ADC AUTOCAL FAIL %d\n", autocal );
+        printl( "ADC AUTOCAL FAIL %d\n", autocal );
         autocal = 0;
     }
     else
     {
-        printk( "ADC AUTOCAL PASS %d\n", autocal );
+        printl( "ADC AUTOCAL PASS %d\n", autocal );
         autocal = GSAI_AUTO_CAL_PASS;
     }
     _adcPtr[ devNum ]->RAG |= GSAI_SAMPLE_START;
@@ -116,11 +122,11 @@ gsc16ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
 #else
     _adcPtr[ devNum ]->SSC = ( GSAI_64_CHANNEL | GSAI_EXTERNAL_SYNC );
 #endif
-    printk( "SSC = 0x%x\n", _adcPtr[ devNum ]->SSC );
-    printk( "IDBC = 0x%x\n", _adcPtr[ devNum ]->IDBC );
+    printl( "SSC = 0x%x\n", _adcPtr[ devNum ]->SSC );
+    printl( "IDBC = 0x%x\n", _adcPtr[ devNum ]->IDBC );
     /// Fill in CDS_HARDWARE structure with ADC information.
     pHardware->pci_adc[ devNum ] =
-        (long)pci_alloc_consistent( adcdev, 0x2000, &adc_dma_handle[ devNum ] );
+        (volatile int *)pci_alloc_consistent( adcdev, 0x2000, &adc_dma_handle[ devNum ] );
     pHardware->adcType[ devNum ] = GSC_16AI64SSA;
     pHardware->adcInstance[ devNum ] = pHardware->card_count[ GSC_16AI64SSA ];
     pHardware->card_count[ GSC_16AI64SSA ] ++;
@@ -135,7 +141,7 @@ gsc16ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
 // *****************************************************************************
 /// \brief Function stops ADC acquisition by removing the clocking signal.
 // *****************************************************************************
-void gsc16ai64AdcStop( modNum )
+void gsc16ai64AdcStop( int modNum )
 {
     _adcPtr[ modNum ]->BCR &= ~( GSAI_ENABLE_X_SYNC );
 }
diff --git a/src/include/drv/gsc16ai64.h b/src/include/drv/gsc16ai64.h
index 81df978ac5eb4e9f9cfdd61e408d8740c5ec98a5..e9f4f8819722bfafe2316545eabc55088461642e 100644
--- a/src/include/drv/gsc16ai64.h
+++ b/src/include/drv/gsc16ai64.h
@@ -4,10 +4,20 @@
 ///<href="http://www.generalstandards.com/view-products2.php?BD_family=16ai64ssc">GSC
 ///<16AI64SSC Manual</a>
 ///< for more info on board registers.
+#ifndef LIGO_GSC16AI64_H
+#define LIGO_GSC16AI64_H
+
+#include "drv/cdsHardware.h"
+
+#include <linux/pci.h> //struct pci_dev
 
 #define ADC_SS_ID                                                              \
     0x3101 ///< Subsystem ID to identify and locate module on PCI bus
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Function Prototypes
 int gsc16ai64Init( CDS_HARDWARE*, struct pci_dev* );
 void gsc16ai64AdcStop( int );
@@ -15,6 +25,11 @@ void gsc16ai64AdcStop( int );
 void gsc16ai64DmaBump( int, int );
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
+
 #define GSAI_FULL_DIFFERENTIAL 0x200
 #define GSAI_64_CHANNEL 0x6
 #define GSAI_32_CHANNEL 0x5
@@ -36,3 +51,6 @@ void gsc16ai64DmaBump( int, int );
 #define GSAI_DATA_CODE_OFFSET 0x8000
 #define GSAI_DATA_MASK 0xffff
 #define GSC16AI64_OSC_FREQ 50000000
+
+
+#endif //LIGO_GSC16AI64_H
diff --git a/src/include/drv/gsc16ao16.c b/src/include/drv/gsc16ao16.c
index 91ffa997bd7f20f8b3d52be0a692d1a0c97992b0..a3540ecf00f18566d548f0093f65cb7bdbe9721c 100644
--- a/src/include/drv/gsc16ao16.c
+++ b/src/include/drv/gsc16ao16.c
@@ -11,6 +11,9 @@
 #include "gsc_dac_common.h"
 #include "gsc16ao16.h"
 #include "ioremap_selection.h"
+#include "drv/plx_9056.h"
+#include "drv/map.h"
+#include "util/printl.h"
 
 // *****************************************************************************
 /// \brief Routine to initialize GSC 16AO16 DAC modules.
@@ -43,7 +46,7 @@ gsc16ao16Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     pedStatus = pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_0, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "pci0 = 0x%x\n", pci_io_addr );
+    printl( "pci0 = 0x%x\n", pci_io_addr );
     _dac_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
     /// Set up a pointer to DMA registers on PLX chip
     dacDma[ devNum ] = (PLX_9056_DMA*)_dac_add;
@@ -52,12 +55,12 @@ gsc16ao16Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     pedStatus = pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_2, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "dac pci2 = 0x%x\n", pci_io_addr );
+    printl( "dac pci2 = 0x%x\n", pci_io_addr );
     _dac_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
-    printk( "DAC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_dac_add );
+    printl( "DAC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_dac_add );
     _dacPtr[ devNum ] = (GSC_DAC_REG*)_dac_add;
 
-    printk( "DAC BCR = 0x%x\n", _dacPtr[ devNum ]->BCR );
+    printl( "DAC BCR = 0x%x\n", _dacPtr[ devNum ]->BCR );
     /// Reset the DAC board and wait for it to finish (3msec)
     _dacPtr[ devNum ]->BCR |= GSAO_RESET;
 
@@ -67,18 +70,18 @@ gsc16ao16Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
 
     /// Enable 2s complement by clearing offset binary bit
     _dacPtr[ devNum ]->BCR = ( GSAO_OUT_RANGE_10 | GSAO_SIMULT_OUT );
-    printk( "DAC BCR after init = 0x%x\n", _dacPtr[ devNum ]->BCR );
-    printk( "DAC CSR = 0x%x\n", _dacPtr[ devNum ]->CSR_DIO );
-    printk( "DAC SRR = 0x%x\n", _dacPtr[ devNum ]->SAMPLE_RATE );
+    printl( "DAC BCR after init = 0x%x\n", _dacPtr[ devNum ]->BCR );
+    printl( "DAC CSR = 0x%x\n", _dacPtr[ devNum ]->CSR_DIO );
+    printl( "DAC SRR = 0x%x\n", _dacPtr[ devNum ]->SAMPLE_RATE );
 
     /// Set DAC FIFO buffer size. Set to match DAC timing diagnostics.
     _dacPtr[ devNum ]->BOR = GSAO_FIFO_SIZE;
 #ifndef USE_ADC_CLOCK
     _dacPtr[ devNum ]->BOR |= GSAO_EXTERN_CLK;
 #endif
-    printk( "DAC BOR = 0x%x\n", _dacPtr[ devNum ]->BOR );
+    printl( "DAC BOR = 0x%x\n", _dacPtr[ devNum ]->BOR );
     pHardware->pci_dac[ devNum ] =
-        (long)pci_alloc_consistent( dacdev, 0x200, &dac_dma_handle[ devNum ] );
+        (volatile int *)pci_alloc_consistent( dacdev, 0x200, &dac_dma_handle[ devNum ] );
     pHardware->dacAcr[ devNum ] = (int)( _dacPtr[ devNum ]->ASSC );
     pHardware->dacType[ devNum ] = GSC_16AO16;
     pHardware->dacCount++;
diff --git a/src/include/drv/gsc16ao16.h b/src/include/drv/gsc16ao16.h
index d3aabb7edd2d3bb9bbaf438ecf24ef3d4404819f..bc75f75c00006802121d097730ddb7549b40c54e 100644
--- a/src/include/drv/gsc16ao16.h
+++ b/src/include/drv/gsc16ao16.h
@@ -1,9 +1,22 @@
+#ifndef LIGO_GSC16AO16_H
+#define LIGO_GSC16AO16_H
 /* GSA 16AO16 DAC Module Definitions ********************************************************* */
 
+#include <linux/pci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int gsc16ao16Init( CDS_HARDWARE* , struct pci_dev* );
 int gsc16ao16CheckDacBuffer( int );
 void gsc16ao16ClearDacBuffer( int );
 
+#ifdef __cplusplus
+}
+#endif
+
+
 #define DAC_SS_ID               0x3120  /* Subsystem ID to find module on PCI bus       */
 #define GSAO_RESET              0x8000
 #define GSAO_OUT_RANGE_25       0x10000
@@ -30,4 +43,4 @@ void gsc16ao16ClearDacBuffer( int );
 #define GSAO_FIFO_SIZE      GSAO_FIFO_256
 #define GSAO_BOR_SW_CLOCK      ( GSAO_SFT_TRIG | GSAO_ISOLATE_EXT_CLK | GSAO_EXTERN_CLK | GSAO_ENABLE_CLK | GSAO_FIFO_SIZE )
 
-
+#endif //LIGO_GSC16AO16_H
diff --git a/src/include/drv/gsc18ai32.c b/src/include/drv/gsc18ai32.c
index 740c20e43c755ed117d5e56470232f377971729d..46ebd212e4f54911409b6c22c41e314e3c1c4953 100644
--- a/src/include/drv/gsc18ai32.c
+++ b/src/include/drv/gsc18ai32.c
@@ -7,6 +7,11 @@
 #include "gsc_adc_common.h"
 #include "gsc18ai32.h"
 #include "ioremap_selection.h"
+#include "drv/plx_9056.h"
+#include "util/printl.h"
+
+#include <linux/delay.h> //udelay()
+
 
 // *****************************************************************************
 /// \brief Routine to initialize GSC 18bit, 32 channel ADC modules
@@ -42,7 +47,7 @@ gsc18ai32Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     pedStatus = pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_0, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "pci0 = 0x%x\n", pci_io_addr );
+    printl( "pci0 = 0x%x\n", pci_io_addr );
     /// Map module DMA space directly to computer memory space.
     _adc_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
     /// Map the module DMA control registers via PLX chip registers
@@ -52,16 +57,16 @@ gsc18ai32Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     pedStatus = pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_2, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "pci2 = 0x%x\n", pci_io_addr );
+    printl( "pci2 = 0x%x\n", pci_io_addr );
     /// Map the module control register so local memory space.
     _adc_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
-    printk( "ADC 18 I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_adc_add );
+    printl( "ADC 18 I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_adc_add );
     /// Set global ptr to control register memory space.
     adc18Ptr = (GSA_ADC_REG*)_adc_add;
     _adcPtr[ devNum ] = (GSA_ADC_REG*)_adc_add;
-    printk( "ADC  pointer init  at 0x%lx\n", (long)_adcPtr[ devNum ] );
+    printl( "ADC  pointer init  at 0x%lx\n", (long)_adcPtr[ devNum ] );
 
-    printk( "BCR = 0x%x\n", adc18Ptr->BCR );
+    printl( "BCR = 0x%x\n", adc18Ptr->BCR );
     /// Reset the ADC board
     adc18Ptr->BCR |= GSAF_RESET;
     do
@@ -76,8 +81,8 @@ gsc18ai32Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     /// Unit runs with external clock, so this probably not necessary
     adc18Ptr->RAG =
         (unsigned int)( GSC18AI32_OSC_FREQ / ( UNDERSAMPLE * IOP_IO_RATE ) );
-    printk( "RAG = %d \n", adc18Ptr->RAG );
-    printk( "BCR = 0x%x\n", adc18Ptr->BCR );
+    printl( "RAG = %d \n", adc18Ptr->RAG );
+    printl( "BCR = 0x%x\n", adc18Ptr->BCR );
     adc18Ptr->RAG &= ~( GSAF_SAMPLE_START ); //  0x10000
 
     /// Initiate board calibration
@@ -90,12 +95,12 @@ gsc18ai32Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     } while ( ( adc18Ptr->BCR & GSAF_AUTO_CAL ) != 0 ); // 0x2000
     if ( ( adc18Ptr->BCR & GSAF_AUTO_CAL_PASS ) == 0 )
     {
-        printk( "ADC AUTOCAL FAIL %d\n", autocal );
+        printl( "ADC AUTOCAL FAIL %d\n", autocal );
         autocal = 0;
     }
     else
     {
-        printk( "ADC AUTOCAL PASS %d\n", autocal );
+        printl( "ADC AUTOCAL PASS %d\n", autocal );
         autocal = GSAF_AUTO_CAL_PASS;
     }
     // End AutoCal
@@ -130,11 +135,11 @@ gsc18ai32Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     // Only for Cymacs using ADC internal clock as clock source
     adc18Ptr->SSC |= GSAF_USE_RAG_CLK;
 #endif
-    printk( "SSC = 0x%x\n", adc18Ptr->SSC );
-    printk( "IDBC = 0x%x\n", adc18Ptr->IDBC );
+    printl( "SSC = 0x%x\n", adc18Ptr->SSC );
+    printl( "IDBC = 0x%x\n", adc18Ptr->IDBC );
     /// Fill in CDS_HARDWARE structure with ADC information.
     pHardware->pci_adc[ devNum ] =
-        (long)pci_alloc_consistent( adcdev, 0x2000, &adc_dma_handle[ devNum ] );
+        (volatile int *)pci_alloc_consistent( adcdev, 0x2000, &adc_dma_handle[ devNum ] );
     pHardware->adcType[ devNum ] = GSC_18AI32SSC1M;
     pHardware->adcInstance[ devNum ] = pHardware->card_count[ GSC_18AI32SSC1M ];
     pHardware->card_count[ GSC_18AI32SSC1M ] ++;
diff --git a/src/include/drv/gsc18ai32.h b/src/include/drv/gsc18ai32.h
index 977fc780399da839365c8627ff23c8b6ec7f8ba8..e5647a8901cabebdc5b714728edd59ef98837f81 100644
--- a/src/include/drv/gsc18ai32.h
+++ b/src/include/drv/gsc18ai32.h
@@ -1,13 +1,26 @@
-//	\file gsc16ai64.h 
-///	\brief GSC 16bit, 32 channel ADC Module Definitions. See  
-///<	<a href="http://www.generalstandards.com/view-products2.php?BD_family=16ai64ssc">GSC 16AI64SSC Manual</a>
+//	\file gsc18ai32.h 
+///	\brief GSC 18bit, 32 channel ADC Module Definitions. See  
+///<	<a href="http://www.generalstandards.com/view-products2.php?BD_family=18ai32ssc">GSC 16AI64SSC Manual</a>
 ///< for more info on board registers.
+#ifndef LIGO_GSC18AI32_H
+#define LIGO_GSC18AI32_H
+
+#include <linux/pci.h>
 
 #define ADC_18AI32_SS_ID       0x3431  ///< Subsystem ID to identify and locate module on PCI bus
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Function Prototypes
 int gsc18ai32Init(CDS_HARDWARE *, struct pci_dev *);
 
+#ifdef __cplusplus
+}
+#endif
+
+
 // Board Control Register (BCR) bits
 #define GSAF_FULL_DIFFERENTIAL  0x200
 #define GSAF_AUTO_CAL           0x2000
@@ -32,3 +45,5 @@ int gsc18ai32Init(CDS_HARDWARE *, struct pci_dev *);
 #define GSAF_FIRST_SAMPLE_MARK      0x80000000
 
 #define GSC18AI32_OSC_FREQ      36000000
+
+#endif //LIGO_GSC18AI32_H
diff --git a/src/include/drv/gsc18ai64.c b/src/include/drv/gsc18ai64.c
index 4206418e82bb1e065ea7622670b61912fed6c85c..75cc05296dd585631d1dabba3f5f87af00549e98 100644
--- a/src/include/drv/gsc18ai64.c
+++ b/src/include/drv/gsc18ai64.c
@@ -7,6 +7,11 @@
 #include "gsc_adc_common.h"
 #include "gsc18ai64.h"
 #include "ioremap_selection.h"
+#include "drv/plx_9056.h"
+#include "util/printl.h"
+
+#include <linux/delay.h> //udelay()
+
 
 // *****************************************************************************
 /// \brief Routine to initialize GSC 18bit, 64 channel ADC modules
@@ -42,7 +47,7 @@ gsc18ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     pedStatus = pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_0, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "pci0 = 0x%x\n", pci_io_addr );
+    printl( "pci0 = 0x%x\n", pci_io_addr );
     /// Map module DMA space directly to computer memory space.
     _adc_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
     /// Map the module DMA control registers via PLX chip registers
@@ -52,15 +57,15 @@ gsc18ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     pedStatus = pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_2, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "pci2 = 0x%x\n", pci_io_addr );
+    printl( "pci2 = 0x%x\n", pci_io_addr );
     /// Map the module control register so local memory space.
     _adc_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
-    printk( "ADC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_adc_add );
+    printl( "ADC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_adc_add );
     /// Set global ptr to control register memory space.
     adc18Ptr = (GSA_ADC_REG*)_adc_add;
     _adcPtr[ devNum ] = (GSA_ADC_REG*)_adc_add;
 
-    printk( "BCR = 0x%x\n", _adcPtr[ devNum ]->BCR );
+    printl( "BCR = 0x%x\n", _adcPtr[ devNum ]->BCR );
     /// Reset the ADC board
     adc18Ptr->BCR |= GSA7_RESET;
     do
@@ -78,8 +83,8 @@ gsc18ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     /// Unit runs with external clock, so this probably not necessary
     adc18Ptr->RAG =
         (unsigned int)( GSC18AI64_OSC_FREQ / ( UNDERSAMPLE * IOP_IO_RATE ) );
-    printk( "RAG = 0x%x\n", adc18Ptr->RAG );
-    printk( "BCR = 0x%x\n", adc18Ptr->BCR );
+    printl( "RAG = 0x%x\n", adc18Ptr->RAG );
+    printl( "BCR = 0x%x\n", adc18Ptr->BCR );
     adc18Ptr->RAG &= ~( GSA7_SAMPLE_START );
     /// Initiate board calibration
     adc18Ptr->BCR |= GSA7_AUTO_CAL;
@@ -91,12 +96,12 @@ gsc18ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     } while ( ( adc18Ptr->BCR & GSA7_AUTO_CAL ) != 0 );
     if ( ( adc18Ptr->BCR & GSA7_AUTO_CAL_PASS ) == 0 )
     {
-        printk( "ADC AUTOCAL FAIL %d\n", autocal );
+        printl( "ADC AUTOCAL FAIL %d\n", autocal );
         autocal = 0;
     }
     else
     {
-        printk( "ADC AUTOCAL PASS %d\n", autocal );
+        printl( "ADC AUTOCAL PASS %d\n", autocal );
         autocal = GSA7_AUTO_CAL_PASS;
     }
     adc18Ptr->IDBC = ( GSAI_CLEAR_BUFFER | GSAI_THRESHOLD );
@@ -119,13 +124,13 @@ gsc18ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev )
     }
 
     // print diags to dmesg
-    printk( "750K SSC = 0x%x\n", adc18Ptr->SSC );
-    printk( "750K IDBC = 0x%x\n", adc18Ptr->IDBC );
-    printk( "750K PCR = 0x%x \n", adc18Ptr->ASSC );
+    printl( "750K SSC = 0x%x\n", adc18Ptr->SSC );
+    printl( "750K IDBC = 0x%x\n", adc18Ptr->IDBC );
+    printl( "750K PCR = 0x%x \n", adc18Ptr->ASSC );
 
     /// Fill in CDS_HARDWARE structure with ADC information.
     pHardware->pci_adc[ devNum ] =
-        (long)pci_alloc_consistent( adcdev, 0x2000, &adc_dma_handle[ devNum ] );
+        (volatile int *)pci_alloc_consistent( adcdev, 0x2000, &adc_dma_handle[ devNum ] );
     pHardware->adcType[ devNum ] = GSC_18AI64SSC;
     pHardware->adcInstance[ devNum ] = pHardware->card_count[ GSC_18AI64SSC ];
     pHardware->card_count[ GSC_18AI64SSC ] ++;
@@ -153,6 +158,7 @@ gsc18ai64Clock( CDS_HARDWARE* pHardware, int modnum )
     adc18Ptr->IDBC = ( GSAI_CLEAR_BUFFER | GSAI_THRESHOLD );
     /// Enable sync via external clock input.
     adc18Ptr->SSC |= GSA7_CLOCK_ENABLE;
+    return 0;
 }
 
 // *****************************************************************************
@@ -168,37 +174,37 @@ gsc18ai64ReadRegisters( CDS_HARDWARE* pHardware, int modnum )
     adc18Ptr = (volatile GSA_ADC_REG*)_adcPtr[ modnum ];
     bcr_value = adc18Ptr->BCR;
     ii = bcr_value & 7;
-    printk( "750KHz BCR AIM = %d\n", ii );
+    printl( "750KHz BCR AIM = %d\n", ii );
     ii = ( bcr_value >> 3 );
-    printk( "750KHz BCR Unipolar = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Unipolar = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 4 );
-    printk( "750KHz BCR Range = %d\n", ( ii & 3 ) );
+    printl( "750KHz BCR Range = %d\n", ( ii & 3 ) );
     ii = ( bcr_value >> 6 );
-    printk( "750KHz BCR Offset Binary = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Offset Binary = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 7 );
-    printk( "750KHz BCR 16 Bit = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR 16 Bit = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 8 );
-    printk( "750KHz BCR Differential Processing  = %d\n", ( ii & 3 ) );
+    printl( "750KHz BCR Differential Processing  = %d\n", ( ii & 3 ) );
     ii = ( bcr_value >> 10 );
-    printk( "750KHz BCR Data on Hold = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Data on Hold = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 11 );
-    printk( "750KHz BCR Disable Scan Marker = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Disable Scan Marker = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 12 );
-    printk( "750KHz BCR Burst Trigger = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Burst Trigger = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 13 );
-    printk( "750KHz BCR Autocal = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Autocal = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 14 );
-    printk( "750KHz BCR Autocal Pass = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Autocal Pass = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 15 );
-    printk( "750KHz BCR Initialize = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Initialize = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 16 );
-    printk( "750KHz BCR Buffer Underflow = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Buffer Underflow = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 17 );
-    printk( "750KHz BCR Buffer Overflow = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Buffer Overflow = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 18 );
-    printk( "750KHz BCR Data Packing = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Data Packing = %d\n", ( ii & 1 ) );
     ii = ( bcr_value >> 19 );
-    printk( "750KHz BCR Input Clock = %d\n", ( ii & 1 ) );
+    printl( "750KHz BCR Input Clock = %d\n", ( ii & 1 ) );
 }
 
 // *****************************************************************************
diff --git a/src/include/drv/gsc18ai64.h b/src/include/drv/gsc18ai64.h
index f5a19cb5c576fd9f5705ed907313081968294672..5102803681f104c13074a26d5ea2a691cd92c5b7 100644
--- a/src/include/drv/gsc18ai64.h
+++ b/src/include/drv/gsc18ai64.h
@@ -1,15 +1,28 @@
 ///	\file gsc18ai64.h
 ///	\brief GSC 16bit, 64 channel 750KS/sec ADC Module Definitions.
+#ifndef LIGO_GSC18AI64_H
+#define LIGO_GSC18AI64_H
+
+#include <linux/pci.h>
 
 ///< Subsystem ID to identify and locate module on PCI bus
 #define ADC_18AI64_SS_ID  0x3570 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Function prototypes
 int  gsc18ai64Init( CDS_HARDWARE*, struct pci_dev* );
 int  gsc18ai64Clock( CDS_HARDWARE*, int );
 void gsc18ai64ReadRegisters( CDS_HARDWARE*, int );
 void gsc18ai64AdcStop( int );
 
+#ifdef __cplusplus
+}
+#endif
+
+
 // Board Control Register (BCR) bits
 #define GSA7_RESET 0x8000
 #define GSA7_FULL_DIFFERENTIAL 0x200
@@ -41,3 +54,5 @@ void gsc18ai64AdcStop( int );
 #define GSA7_DATA_CODE_OFFSET 0x20000
 #define GSA7_DATA_MASK 0x3ffff
 #define GSA7_FIRST_SAMPLE_MARK 0x40000
+
+#endif //LIGO_GSC18AI64_H
diff --git a/src/include/drv/gsc18ao8.c b/src/include/drv/gsc18ao8.c
index 350e29f1f7c3ebcf63163c8cac97c28a13d6df19..f3e70d5e90054d838c7fbf988c4e7c0ac1373957 100644
--- a/src/include/drv/gsc18ao8.c
+++ b/src/include/drv/gsc18ao8.c
@@ -8,9 +8,15 @@
 ///<    href="http://www.generalstandards.com/view-products2.php?BD_family=18ao8">GSC
 ///<    18AO8 Manual</a>
 
-#include "gsc_dac_common.h"
-#include "gsc18ao8.h"
+#include "drv/gsc_dac_common.h"
+#include "drv/gsc18ao8.h"
 #include "ioremap_selection.h"
+#include "util/printl.h"
+#include "drv/map.h"
+#include "drv/plx_9056.h"
+
+#include <linux/delay.h> //udelay()
+
 
 // *****************************************************************************
 /// \brief Routine to initialize GSC 18AO8 DAC modules.
@@ -48,7 +54,7 @@ gsc18ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     pedStatus = pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_0, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "pci0 = 0x%x\n", pci_io_addr );
+    printl( "pci0 = 0x%x\n", pci_io_addr );
     _dac_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
     /// Set up a pointer to DMA registers on PLX chip
     dacDma[ devNum ] = (PLX_9056_DMA*)_dac_add;
@@ -57,14 +63,14 @@ gsc18ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     pedStatus = pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_2, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "dac pci2 = 0x%x\n", pci_io_addr );
+    printl( "dac pci2 = 0x%x\n", pci_io_addr );
     _dac_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
-    printk( "DAC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_dac_add );
+    printl( "DAC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_dac_add );
 
     dac18bitPtr = (GSC_DAC_REG*)_dac_add;
     _dacPtr[ devNum ] = (GSC_DAC_REG*)_dac_add;
 
-    printk( "DAC BCR = 0x%x\n", dac18bitPtr->BCR );
+    printl( "DAC BCR = 0x%x\n", dac18bitPtr->BCR );
     /// Reset the DAC board and wait for it to finish (3msec)
 
     dac18bitPtr->BCR |= GSAO_18BIT_RESET;
@@ -76,8 +82,8 @@ gsc18ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     /// Enable 2s complement by clearing offset binary bit
     dac18bitPtr->BCR &= ~GSAO_18BIT_OFFSET_BINARY;
     dac18bitPtr->BCR |= GSAO_18BIT_SIMULT_OUT;
-    printk( "DAC BCR after init = 0x%x\n", dac18bitPtr->BCR );
-    printk( "DAC OUTPUT CONFIG = 0x%x\n", dac18bitPtr->OUTPUT_CONFIG );
+    printl( "DAC BCR after init = 0x%x\n", dac18bitPtr->BCR );
+    printl( "DAC OUTPUT CONFIG = 0x%x\n", dac18bitPtr->OUTPUT_CONFIG );
 
     /// Enable 10 volt output range
     dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_10VOLT_RANGE;
@@ -99,21 +105,21 @@ gsc18ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
 
     if ( dac18bitPtr->BCR & GSAO_18BIT_AUTOCAL_PASS )
     {
-        printk( "DAC AUTOCAL SUCCESS in %d milliseconds \n", timer );
+        printl( "DAC AUTOCAL SUCCESS in %d milliseconds \n", timer );
         pHardware->dacAcr[ devNum ] = DAC_CAL_PASS;
     } else {
-        printk( "DAC AUTOCAL FAILED in %d milliseconds \n", timer );
+        printl( "DAC AUTOCAL FAILED in %d milliseconds \n", timer );
     }
-    printk( "DAC OUTPUT CONFIG after init = 0x%x with BCR = 0x%x\n",
+    printl( "DAC OUTPUT CONFIG after init = 0x%x with BCR = 0x%x\n",
             dac18bitPtr->OUTPUT_CONFIG,
             dac18bitPtr->BCR );
 #else
-    printk( "DAC OUTPUT CONFIG after init = 0x%x\n",
+    printl( "DAC OUTPUT CONFIG after init = 0x%x\n",
             dac18bitPtr->OUTPUT_CONFIG );
 #endif
 
     pHardware->pci_dac[ devNum ] =
-        (long)pci_alloc_consistent( dacdev, 0x200, &dac_dma_handle[ devNum ] );
+        (volatile int *)pci_alloc_consistent( dacdev, 0x200, &dac_dma_handle[ devNum ] );
     pHardware->dacAcr[ devNum ] |= ((int)( dac18bitPtr->ASY_CONFIG ) & DAC_ACR_MASK);
     pHardware->dacType[ devNum ] = GSC_18AO8;
     pHardware->dacCount++;
diff --git a/src/include/drv/gsc18ao8.h b/src/include/drv/gsc18ao8.h
index f8f89c1f168e2b74e1dc31477029e5e97e2b984a..4b87001410b146830da20f359c54c06bf2c0f9a0 100644
--- a/src/include/drv/gsc18ao8.h
+++ b/src/include/drv/gsc18ao8.h
@@ -1,7 +1,19 @@
-/* GSC 18-bit DAC Module Defs ********************************************************* */
+#ifndef LIGO_GSC18AO8_H
+#define LIGO_GSC18AO8_H
+// GSC 18-bit DAC Module Defs
+
+#include <linux/pci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 int gsc18ao8Init( CDS_HARDWARE*, struct pci_dev* );
 
+#ifdef __cplusplus
+}
+#endif
+
 
 
 #define DAC_18BIT_SS_ID         0x3357  /* Subsystem ID to find module on PCI bus       */
@@ -22,3 +34,5 @@ int gsc18ao8Init( CDS_HARDWARE*, struct pci_dev* );
 #define GSAO_18BIT_AUTOCAL_PASS		(1 << 29)
 #define GSAO_18BIT_SW_CLOCK 		(1 << 7)
 #define GSAO_18BIT_BOO_SW_CLOCK     (GSAO_18BIT_SW_CLOCK | GSAO_18BIT_ENABLE_CLOCK)
+
+#endif //LIGO_GSC18AO8_H
diff --git a/src/include/drv/gsc20ao8.c b/src/include/drv/gsc20ao8.c
index e0ec9e1ddf63484370adaa4afe45d9472954aa1b..4b1e8cda8d5e60e2aa01061107b734d099dbebf5 100644
--- a/src/include/drv/gsc20ao8.c
+++ b/src/include/drv/gsc20ao8.c
@@ -11,6 +11,12 @@
 #include "gsc_dac_common.h"
 #include "gsc20ao8.h"
 #include "ioremap_selection.h"
+#include "util/printl.h"
+#include "drv/plx_9056.h"
+#include "drv/map.h"
+
+#include <linux/delay.h> //udelay()
+
 
 // *****************************************************************************
 /// \brief Routine to initialize GSC 20AO8 DAC modules.
@@ -46,7 +52,7 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     pedStatus = pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_0, &pci_io_addr );
     if(pedStatus != 0)
         return -1;
-    printk( "pci0 = 0x%x\n", pci_io_addr );
+    printl( "pci0 = 0x%x\n", pci_io_addr );
     _dac_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
     /// Set up a pointer to DMA registers on PLX chip
     dacDma[ devNum ] = (PLX_9056_DMA*)_dac_add;
@@ -56,16 +62,16 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     if(pedStatus != 0)
         return -1;
     // Send some info to dmesg
-    printk( "dac pci2 = 0x%x\n", pci_io_addr );
+    printl( "dac pci2 = 0x%x\n", pci_io_addr );
     _dac_add = IOREMAP( (unsigned long)pci_io_addr, 0x200 );
     // Send some info to dmesg
-    printk( "DAC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_dac_add );
+    printl( "DAC I/O address=0x%x  0x%lx\n", pci_io_addr, (long)_dac_add );
 
     dac20bitPtr = (GSC_DAC_REG*)_dac_add;
     _dacPtr[ devNum ] = (GSC_DAC_REG*)_dac_add;
 
     // Send some info to dmesg
-    printk( "DAC BCR = 0x%x\n", dac20bitPtr->BCR );
+    printl( "DAC BCR = 0x%x\n", dac20bitPtr->BCR );
     /// Reset the DAC board and wait for it to finish (3msec)
 
     dac20bitPtr->BCR |= GSAO_20BIT_RESET;
@@ -78,7 +84,7 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     } while ( ( dac20bitPtr->BCR & GSAO_20BIT_RESET ) != 0 && timer > 0 &&
               dac20bitPtr->PRIMARY_STATUS == 1 );
 
-    // printk("DAC PSR after init = 0x%x and timer =
+    // printl("DAC PSR after init = 0x%x and timer =
     // %d\n",dac20bitPtr->PRIMARY_STATUS,timer);
 
     /// Enable 2s complement by clearing offset binary bit
@@ -86,8 +92,8 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     // Set simultaneous outputs
     dac20bitPtr->BCR |= GSAO_20BIT_SIMULT_OUT;
     // Send some info to dmesg
-    // printk("DAC BCR after init = 0x%x\n",dac20bitPtr->BCR);
-    // printk("DAC OUTPUT CONFIG = 0x%x\n",dac20bitPtr->OUTPUT_CONFIG);
+    // printl("DAC BCR after init = 0x%x\n",dac20bitPtr->BCR);
+    // printl("DAC OUTPUT CONFIG = 0x%x\n",dac20bitPtr->OUTPUT_CONFIG);
 
     /// Enable 10 volt output range
     dac20bitPtr->OUTPUT_CONFIG |= GSAO_20BIT_10VOLT_RANGE;
@@ -97,10 +103,10 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     dac20bitPtr->BCR |= GSAO_20BIT_OUTPUT_ENABLE;
     udelay( 1000 );
     // Set primary status to detect autocal
-    printk( "DAC PSR = 0x%x\n", dac20bitPtr->PRIMARY_STATUS );
+    printl( "DAC PSR = 0x%x\n", dac20bitPtr->PRIMARY_STATUS );
     dac20bitPtr->PRIMARY_STATUS = 2;
     udelay( 1000 );
-    printk( "DAC PSR after reset = 0x%x\n", dac20bitPtr->PRIMARY_STATUS );
+    printl( "DAC PSR after reset = 0x%x\n", dac20bitPtr->PRIMARY_STATUS );
 
     // Start Calibration
     dac20bitPtr->BCR |= GSAO_20BIT_AUTOCAL_SET;
@@ -110,28 +116,28 @@ gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev )
     do
     {
         udelay( 1000 );
-        // printk("DAC PSR in autocal = 0x%x\n",dac20bitPtr->PRIMARY_STATUS);
+        // printl("DAC PSR in autocal = 0x%x\n",dac20bitPtr->PRIMARY_STATUS);
         timer += 1;
     } while ( ( dac20bitPtr->BCR & GSAO_20BIT_AUTOCAL_SET ) != 0 );
 
-    printk( "DAC after autocal PSR = 0x%x\n", dac20bitPtr->PRIMARY_STATUS );
+    printl( "DAC after autocal PSR = 0x%x\n", dac20bitPtr->PRIMARY_STATUS );
     if ( dac20bitPtr->BCR & GSAO_20BIT_AUTOCAL_PASS )
     {
-        printk( "DAC AUTOCAL SUCCESS in %d milliseconds \n", timer );
+        printl( "DAC AUTOCAL SUCCESS in %d milliseconds \n", timer );
         pHardware->dacAcr[ devNum ] = DAC_CAL_PASS;
     } else {
-        printk( "DAC AUTOCAL FAILED in %d milliseconds \n", timer );
+        printl( "DAC AUTOCAL FAILED in %d milliseconds \n", timer );
     }
-    printk( "DAC PSR = 0x%x\n", dac20bitPtr->PRIMARY_STATUS );
+    printl( "DAC PSR = 0x%x\n", dac20bitPtr->PRIMARY_STATUS );
 
     // If 20bit DAC, need to enable outputs.
     dac20bitPtr->BCR |= GSAO_20BIT_OUTPUT_ENABLE;
-    printk( "DAC OUTPUT CONFIG after init = 0x%x with BCR = 0x%x\n",
+    printl( "DAC OUTPUT CONFIG after init = 0x%x with BCR = 0x%x\n",
             dac20bitPtr->OUTPUT_CONFIG,
             dac20bitPtr->BCR );
 
     pHardware->pci_dac[ devNum ] =
-        (long)pci_alloc_consistent( dacdev, 0x200, &dac_dma_handle[ devNum ] );
+        (volatile int *)pci_alloc_consistent( dacdev, 0x200, &dac_dma_handle[ devNum ] );
     pHardware->dacAcr[ devNum ] |= ((int)( dac20bitPtr->ASY_CONFIG )  & DAC_ACR_MASK);
 
     // Return the device type to main code.
diff --git a/src/include/drv/gsc20ao8.h b/src/include/drv/gsc20ao8.h
index ece52903efbf321effaacd2fb857dbb0b05d27a6..9aa6353fca935ce7fffd28767720e6bd3ea3304a 100644
--- a/src/include/drv/gsc20ao8.h
+++ b/src/include/drv/gsc20ao8.h
@@ -1,7 +1,20 @@
+#ifndef LIGO_GSC20AO8_H
+#define LIGO_GSC20AO8_H
 /* GSC 20-bit DAC Module Defs ********************************************************* */
 
+#include <linux/pci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int gsc20ao8Init( CDS_HARDWARE* , struct pci_dev* );
 
+#ifdef __cplusplus
+}
+#endif
+
+
 #define DAC_20BIT_SS_ID         0x3574  /* Subsystem ID to find module on PCI bus       */
 #define GSAO_20BIT_RESET        (1 << 31)
 #define GSAO_20BIT_OFFSET_BINARY        (1 << 25)
@@ -19,3 +32,5 @@ int gsc20ao8Init( CDS_HARDWARE* , struct pci_dev* );
 #define GSAO_20BIT_AUTOCAL_SET		(1 << 28)
 #define GSAO_20BIT_AUTOCAL_PASS		(1 << 29)
 #define GSAO_20BIT_OUTPUT_ENABLE       0x80    // Enable DAC Outputs
+
+#endif //LIGO_GSC20AO8_H
diff --git a/src/include/drv/gsc_adc_common.c b/src/include/drv/gsc_adc_common.c
index 26296ccf081989404bc60fd2c4c8880ead5fd2e6..cdeb0e5545a1a6033b83576acd002a7387b8ac23 100644
--- a/src/include/drv/gsc_adc_common.c
+++ b/src/include/drv/gsc_adc_common.c
@@ -2,6 +2,14 @@
 /// @brief File contains routines common to all ADC modules
 
 #include "gsc_adc_common.h"
+#include "drv/plx_9056.h"
+
+//
+// Global Data
+// This is used by common ADC code (gsc_adc_common.c) and a lot 
+// of specific drivers. (gsc18ai64.c, gsc16ai64.c etc...) 
+//
+volatile GSA_ADC_REG* _adcPtr[ MAX_ADC_MODULES ]; ///< Ptr to ADC registers */
 
 // *****************************************************************************
 /// \brief Routine reads number of samples in ADC FIFO.
diff --git a/src/include/drv/gsc_adc_common.h b/src/include/drv/gsc_adc_common.h
index f8d4b654836ed20145465bb4c1af7ae28c318ca4..485f1bd87d694bd8728c44029d43ad54f7f71bf2 100644
--- a/src/include/drv/gsc_adc_common.h
+++ b/src/include/drv/gsc_adc_common.h
@@ -4,11 +4,21 @@
 /// @file gsc_adc_common.h
 /// @brief Defines standard ADC card register map and defines.
 
+#include "drv/cdsHardware.h" //CDS_HARDWARE
+#include "util/fixed_width_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Prototypes for routines found in gsc_adc_common.c
 int gscCheckAdcBuffer( int );
 void gscDisableAdcClk( CDS_HARDWARE* , int );
 void gscEnableAdcModule( CDS_HARDWARE* , int , int );
 
+#ifdef __cplusplus
+}
+#endif
 
 
 // Standard ADC register map
@@ -32,7 +42,7 @@ typedef struct GSA_ADC_REG{
 }GSA_ADC_REG;
 
 // Global pointer to ADC register map
-volatile GSA_ADC_REG* _adcPtr[ MAX_ADC_MODULES ]; ///< Ptr to ADC registers */
+extern volatile GSA_ADC_REG* _adcPtr[ MAX_ADC_MODULES ]; ///< Ptr to ADC registers */
 
 #define GSAI_CLEAR_BUFFER   0x40000
 #define GSAI_THRESHOLD      0x001f
diff --git a/src/include/drv/gsc_dac_common.c b/src/include/drv/gsc_dac_common.c
index e07bb1f721ad5244c825d232f11f321881662930..a3fdde1af845747836dcccec5dc1fddcdd636018 100644
--- a/src/include/drv/gsc_dac_common.c
+++ b/src/include/drv/gsc_dac_common.c
@@ -1,8 +1,22 @@
 /// @file gsc_dac_common.c
 /// @brief File contains routines common to all DAC modules
-#include "gsc_dac_common.h"
+#include "drv/gsc_adc_common.h" //GSAI_ALL_CARDS
+#include "drv/gsc_dac_common.h"
+#include "drv/gsc16ao16.h" //GSAO_ENABLE_CLK
+#include "drv/gsc18ao8.h" //GSAO_18BIT_EXT_CLOCK_SRC
+#include "drv/gsc20ao8.h" //GSAO_20BIT_EXT_CLOCK_SRC
+#include "controller.h" //MAX_UDELAY, cdsPciModules
+#include "controllerko.h" //CDIO1616Output , TODO This looks like it is defined multiple places
 
-void 
+#include <asm/delay.h>
+
+//
+// Global Variables
+//
+volatile GSC_DAC_REG *_dacPtr[MAX_DAC_MODULES];  /* Ptr to DAC registers */
+
+
+static void 
 gscdacfirstlast(int card, int total_cards, int* first, int* last)
 { 
     if ( card == GSAI_ALL_CARDS )
diff --git a/src/include/drv/gsc_dac_common.h b/src/include/drv/gsc_dac_common.h
index 86c827ac6acf5e48b706bf8d50e251d21d2a9863..763c6b2255606d190a06ea481ca42df7c18f28b5 100644
--- a/src/include/drv/gsc_dac_common.h
+++ b/src/include/drv/gsc_dac_common.h
@@ -4,10 +4,25 @@
 /// @file gsc_dac_common.h
 /// @brief Provides DAC register map and common defs
 
+#include "drv/cdsHardware.h" //CDS_HARDWARE
+
+#include <linux/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 // Prototypes for routines found in gsc_dac_common.c
 void gscEnableDacModule( CDS_HARDWARE* , int , int );
 int gscDacFifoCheck( CDS_HARDWARE* pHardware, int , int );
 void gscDacFifoClear( CDS_HARDWARE* , int );
+void gscDacSoftClock( CDS_HARDWARE* pHardware, int card );
+
+#ifdef __cplusplus
+}
+#endif
+
 
 // Standard DAC module register map
 typedef struct GSC_DAC_REG {
@@ -36,7 +51,7 @@ typedef struct GSC_DAC_REG {
         u32 OUTPUT_CONFIG;     /* 0x54 */
 } GSC_DAC_REG;
 
-volatile GSC_DAC_REG *_dacPtr[MAX_DAC_MODULES];  /* Ptr to DAC registers */
+extern volatile GSC_DAC_REG *_dacPtr[MAX_DAC_MODULES];  /* Ptr to DAC registers */
 
 #define DAC_FIFO_EMPTY_TEST      1
 #define DAC_FIFO_NOT_EMPTY_TEST  0
diff --git a/src/include/drv/inputFilterModule.h b/src/include/drv/inputFilterModule.h
index 26cee7b3afd88c468b4ca41d11403548c7b99069..209e4bfd8f615c0d00a222be46342544faea6ce4 100644
--- a/src/include/drv/inputFilterModule.h
+++ b/src/include/drv/inputFilterModule.h
@@ -2,8 +2,11 @@
 ///	@brief File contains routines for running single pole/single zero filter modules
 ///		with settings from EPICS.
 
+#include "portableInline.h"
+
 /// Control ramping of filter parameters
-static double inputFilterModuleRamp(
+LIGO_INLINE 
+double inputFilterModuleRamp(
 	double *v, 	/* current value in/out */
 	double nv,	/* new value from Epics */
 	double tramp,	/* Ramping time in seconds */
@@ -50,6 +53,7 @@ static double inputFilterModuleRamp(
 ///	@param[in,out] *ks		Gain ramping steps
 ///	@param[in,out] *ps		Pole ramping steps
 ///	@param[in,out] *zs		Zero ramping steps
+LIGO_INLINE 
 void inputFilterModule(
 	double in,						/* input IN0 */
 	double *old_out,					/* input IN1_PREV, output IN1 */
diff --git a/src/include/drv/inputFilterModule1.h b/src/include/drv/inputFilterModule1.h
index 0749115631c012fc129ee5bdfe4efaf98d3afe8d..ce6c546f305226536fffb8e090f560cd4640bd5c 100644
--- a/src/include/drv/inputFilterModule1.h
+++ b/src/include/drv/inputFilterModule1.h
@@ -2,7 +2,9 @@
 ///	@brief File contains routines to support single pole/ single zero filter modules
 ///<		with EPICS inputs.
 
-static double inputFilterModuleRamp1(
+#include "portableInline.h"
+
+LIGO_INLINE double inputFilterModuleRamp1(
 	double *v, 	/* current value in/out */
 	double nv,	/* new value from Epics */
 	double tramp,	/* Ramping time in seconds */
@@ -35,7 +37,7 @@ static double inputFilterModuleRamp1(
     return *v;
 }
 
-void inputFilterModule1(
+LIGO_INLINE void inputFilterModule1(
 	double in,						/* input IN0 */
 	double *old_out,					/* input IN1_PREV, output IN1 */
 	double *old_val,					/* input VAL_PREV, output VAL */
diff --git a/src/include/drv/iop_adc_functions.c b/src/include/drv/iop_adc_functions.c
index e1ec814a05e5fea78a2c60b4b285f27e6f98abc1..c664729fc25fc3ebbaf5d369ec191c9721824a79 100644
--- a/src/include/drv/iop_adc_functions.c
+++ b/src/include/drv/iop_adc_functions.c
@@ -1,12 +1,37 @@
-inline int iop_adc_init( adcInfo_t* );
-inline int iop_adc_read( adcInfo_t*, int[] );
+#include "drv/iop_adc_functions.h"
+
+
+#include "drv/gsc16ai64.h"
+#include "drv/gsc18ai32.h"
+#include "drv/gsc18ai64.h"
+#include "drv/gsc_adc_common.h"
+#include "drv/symmetricomGps.h"
+#include "drv/spectracomGPS.h"
+#include "drv/ligoPcieTiming.h"
+#include "drv/gsc18ao8.h"
+#include "drv/plx_9056.h"
+#include "fm10Gen.h"//iir_filter_biquad()
+#include "controller.h" //cdsPciModules, etc
+
+#ifdef XMIT_DOLPHIN_TIME
+#include "../fe/controllerIop.h" //pcieTimer
+#endif
+
+#ifdef XMIT_DOLPHIN_TIME
+#include <asm/cacheflush.h>
+#endif
+
+//
+// Global Functions
+//
+static int first_adc_read = 1;
+
 
 // Routine for initializing ADC modules on startup
-inline int
+int
 iop_adc_init( adcInfo_t* adcinfo )
 {
     volatile int* adcDummyData;
-    int           status;
     int           ii, jj;
     int           dma_bytes = 32;
     int           card = 0;
@@ -44,7 +69,7 @@ iop_adc_init( adcInfo_t* adcinfo )
         // should always have an upper bit set indicating channel 0.
         // Write a number into the last channel which the ADC should never write
         // ie no upper bits should be set in channel 31.
-        adcDummyData = (int*)cdsPciModules.pci_adc[ jj ];
+        adcDummyData = cdsPciModules.pci_adc[ jj ];
         switch ( cdsPciModules.adcType[ jj ] )
         {
         case GSC_18AI32SSC1M:
@@ -97,11 +122,10 @@ iop_adc_init( adcInfo_t* adcinfo )
     return 0;
 }
 
-int first_adc_read = 1;
 
 // ADC Read *****************************************************************
 // Routine for reading data from ADC modules.
-inline int
+int
 iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
 {
     int           ii, jj, kk;
@@ -116,8 +140,6 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
     int           max_loops = UNDERSAMPLE;  //number of samples typically processed from an A2D per cycle.
     int           loops = max_loops;     //can be less than max_loops on the first cycle when time_shift parameter is used.
     int           iocycle = 0;
-    unsigned int  nsec = 0;
-    int           gps_status = 0;
     int           first_chan_marker = 0;
     int           adc_wait_limit = 0;
     double        val2dec = 0;
@@ -151,7 +173,7 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
         /// - ---- ADC DATA RDY is detected when last channel in memory no
         /// longer contains the dummy variable written during initialization and
         /// reset after each read.
-        packedData = (int*)cdsPciModules.pci_adc[ card ];
+        packedData = cdsPciModules.pci_adc[ card ];
 
         /// Where last channel is is dependent on adcDummyDatanumber of channels a
         /// particular card type has.
@@ -226,6 +248,9 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
                                            cpuClk[ CPU_TIME_CYCLE_START ] ) /
                 CPURATE;
 #ifdef XMIT_DOLPHIN_TIME
+            // TODO: This version of iop_adc_init() does not appear to be used when we 
+            // are configured for XMIT_DOLPHIN_TIME, so can we even hit this ?
+            //
             // Send time on Dolphin net if this is the time xmitter.
             pcieTimer->gps_time = timeSec;
             pcieTimer->cycle = cycleNum/UNDERSAMPLE;
@@ -273,14 +298,14 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
                 switch ( cdsPciModules.gpsType )
                 {
                 case SYMCOM_RCVR:
-                    lockGpsTime( );
+                    lockGpsTime( &cdsPciModules );
                     break;
                 case 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( );
+                    timeSec = getGpsSecTsync( &cdsPciModules );
                     break;
                 case LIGO_RCVR:
                     // Read GPS second from LIGO Pcie timing card.
@@ -294,7 +319,7 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
 
         /// \> Read adc data
         // Set pointer to first channel
-        packedData = (int*)cdsPciModules.pci_adc[ card ];
+        packedData = cdsPciModules.pci_adc[ card ];
         /// - ---- First, and only first, channel should have upper bit marker
         /// set. If not, have a channel hopping error.
         if ( !( *packedData & first_chan_marker ) )
@@ -323,10 +348,15 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
 
         // loops and max_loops are usually equal to UNDERSAMPLE, but on the first cycle
         // they loops may be less.
+        max_loops = UNDERSAMPLE;
         if(first_adc_read)
         {
             loops = UNDERSAMPLE - cdsPciModules.adcTimeShift[card];
         }
+        else
+        {
+            loops = UNDERSAMPLE;
+        }
 
 
         // GSC_16AI64SSA can't support rate > 128KS/sec
@@ -430,7 +460,7 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
         /// next cycle
         /// - ---- First channel should never be zero ie should have channel
         /// marker bit
-        packedData = (int*)cdsPciModules.pci_adc[ card ];
+        packedData = cdsPciModules.pci_adc[ card ];
         *packedData = 0x0;
 
         // Enable the ADC Demand DMA for next read
diff --git a/src/include/drv/iop_adc_functions.h b/src/include/drv/iop_adc_functions.h
new file mode 100644
index 0000000000000000000000000000000000000000..f374a0f8421145ab6818dca2e1b50cfa3666b860
--- /dev/null
+++ b/src/include/drv/iop_adc_functions.h
@@ -0,0 +1,19 @@
+#ifndef LIGO_IOP_ADC_FUNCTIONS_H
+#define LIGO_IOP_ADC_FUNCTIONS_H
+
+#include "cds_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iop_adc_init( adcInfo_t* );
+int iop_adc_read( adcInfo_t*, int[] );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif //LIGO_IOP_ADC_FUNCTIONS_H
diff --git a/src/include/drv/iop_dac_functions.c b/src/include/drv/iop_dac_functions.c
index e6537656b665699a4f3429ffd9861f4bcc4fa16a..a219399201cb793f059106e9d66cf8a7cd2646fb 100644
--- a/src/include/drv/iop_dac_functions.c
+++ b/src/include/drv/iop_dac_functions.c
@@ -1,6 +1,13 @@
-int iop_dac_init( int[] );
-void iop_dac_preload( int );
-inline int iop_dac_write( );
+#include "drv/iop_dac_functions.h" 
+#include "drv/gsc_adc_common.h"
+#include "gsc_dac_common.h" //_dacPtr
+#include "drv/gsc20ao8.h" //GSAO_20BIT_PRELOAD
+#include "drv/gsc16ao16.h" //GSAO_16BIT_PRELOAD
+#include "drv/gsc18ao8.h" //GSAO_18BIT_PRELOAD
+#include "controller.h"
+#include "drv/plx_9056.h"
+
+#include "../fe/controllerIop.h"//dacWriteEnable
 
 int
 iop_dac_init( int errorPend[] )
@@ -80,10 +87,10 @@ iop_dac_preload( int card )
     }
 }
 
-inline int
+int
 iop_dac_write(  )
 {
-    unsigned int* pDacData;
+    volatile unsigned int* pDacData;
     int           mm;
     int           limit;
     int           mask;
@@ -103,7 +110,7 @@ iop_dac_write(  )
         for ( card = 0; card < cdsPciModules.dacCount; card++ )
         {
             /// - -- Point to DAC memory buffer
-            pDacData = (unsigned int*)( cdsPciModules.pci_dac[ card ] );
+            pDacData = (volatile unsigned int*)( cdsPciModules.pci_dac[ card ] );
             /// - -- locate the proper DAC memory block
             mm = cdsPciModules.dacConfig[ card ];
             /// - -- Determine if memory block has been set with the correct
@@ -222,7 +229,7 @@ iop_dac_write(  )
     return status;
 }
 
-inline int
+int
 check_dac_buffers( int cardNum, int report_all_faults )
 {
     // if report_all_faults not set, then will only set
diff --git a/src/include/drv/iop_dac_functions.h b/src/include/drv/iop_dac_functions.h
new file mode 100644
index 0000000000000000000000000000000000000000..b70aa08f008dd680560202141d91ffca315f023b
--- /dev/null
+++ b/src/include/drv/iop_dac_functions.h
@@ -0,0 +1,18 @@
+#ifndef LIGO_IOP_DAC_FUNCTIONS_H
+#define LIGO_IOP_DAC_FUNCTIONS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iop_dac_init( int[] );
+void iop_dac_preload( int );
+int iop_dac_write( void  );
+int check_dac_buffers( int cardNum, int report_all_faults );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_IOP_DAC_FUNCTIONS_H
diff --git a/src/include/drv/ioremap_selection.h b/src/include/drv/ioremap_selection.h
index fdc27e3c0fa8e9395177c585a2b81c942dcd6a1f..972ca22369b867f60612c1921db7379a16a38746 100644
--- a/src/include/drv/ioremap_selection.h
+++ b/src/include/drv/ioremap_selection.h
@@ -8,6 +8,8 @@
 #ifndef IOREMAP_SELECTION_H
 #define IOREMAP_SELECTION_H
 
+#include <linux/version.h> //KERNEL_VERSION
+
 /* Keeping IOREMAP as a macro instead of a static inline function as
  * the kernel has a few similar but different definitions of the argument
  * types, and I will not wade into that here.
diff --git a/src/include/drv/ligoPcieTiming.c b/src/include/drv/ligoPcieTiming.c
index 10e848844f30e10545f42d2093826ae6ed8daef7..d672c9b8fc3f9fbdf1ce67eddb864b2dd5e29a29 100644
--- a/src/include/drv/ligoPcieTiming.c
+++ b/src/include/drv/ligoPcieTiming.c
@@ -1,8 +1,10 @@
 /// 	\file ligoPcieTiming64.c
 
 #include "ligoPcieTiming.h"
+#include "controller.h" //IOC_CLK_SLOW, MAX_UDELAY
+
+#include <linux/delay.h> //udelay()
 
-#include "ligoPcieTiming_core.c"
 
 void
 lptc_enable_all_slots( CDS_HARDWARE* pCds )
@@ -59,6 +61,8 @@ lptc_start_clock( CDS_HARDWARE* pCds )
     int            ii, jj;
     volatile LPTC_REGISTER* lptcPtr;
 
+    if(pCds->card_count[ LPTC ] < 1) return -1;
+
     for ( jj = 0; jj < pCds->card_count[ LPTC ]; jj++ )
     {
         lptcPtr = (LPTC_REGISTER*)pCds->lptc[ jj ];
@@ -86,7 +90,6 @@ lptc_status_update( CDS_HARDWARE* pCds )
 {
     int ii;
 
-    volatile LPTC_REGISTER* lptcPtr = (LPTC_REGISTER*)pCds->lptc[ 0 ];
     // Update lptc status to epics
     for ( ii = 0; ii < LPTC_IOC_SLOTS; ii++ )
         pLocalEpics->epicsOutput.lptMon[ ii ] =
@@ -108,6 +111,8 @@ lptc_stop_clock( CDS_HARDWARE* pCds )
     int            jj;
     volatile LPTC_REGISTER* lptcPtr;
 
+    if(pCds->card_count[ LPTC ] < 1) return -1;
+
     for ( jj = 0; jj < pCds->card_count[ LPTC ]; jj++ )
     {
         lptcPtr = (LPTC_REGISTER*)pCds->lptc[ jj ];
diff --git a/src/include/drv/ligoPcieTiming.h b/src/include/drv/ligoPcieTiming.h
index 8cb27c5fdfd6a91a745b2e914d4c0f99d8e2958a..6d34f88c205e31148cc19797f2047f35a1661228 100644
--- a/src/include/drv/ligoPcieTiming.h
+++ b/src/include/drv/ligoPcieTiming.h
@@ -5,14 +5,25 @@
 #define LPTC_VID	0x10ee
 #define LPTC_TID	0xd8c6
 
+#include "drv/cdsHardware.h"
+
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Prototypes for routines in ligoPcieTiming_core.c
-static int lptcInit( CDS_HARDWARE* , struct pci_dev* );
+int lptcInit( CDS_HARDWARE* , struct pci_dev* );
 int lptc_get_gps_time( CDS_HARDWARE* , u32* , u32* );
 unsigned int lptc_get_gps_usec( CDS_HARDWARE* );
 unsigned int lptc_get_gps_sec( CDS_HARDWARE* );
 int lptc_get_lptc_status( CDS_HARDWARE* );
 int lptc_get_bp_status( CDS_HARDWARE* );
 int lptc_get_bp_config( CDS_HARDWARE* );
+int lptc_get_slot_phase( CDS_HARDWARE* pCds, int slot );
+
 
 // slot functions in ligoPcieTiming_core.c
 int lptc_get_slot_config( CDS_HARDWARE* , int );
@@ -60,6 +71,10 @@ void lptc_slot_clk_set( CDS_HARDWARE* , int, int );
 void lptc_slot_clk_disable_all( CDS_HARDWARE* );
 void lptc_slot_clk_enable_all( CDS_HARDWARE* );
 
+#ifdef __cplusplus
+}
+#endif
+
 
 
 
diff --git a/src/include/drv/ligoPcieTiming_core.c b/src/include/drv/ligoPcieTiming_core.c
index 7566af6be488f1c0ab450e7599953c91e35fe1d5..a72c02bef0686a3e22abc2f018eeffda6081cb20 100644
--- a/src/include/drv/ligoPcieTiming_core.c
+++ b/src/include/drv/ligoPcieTiming_core.c
@@ -1,9 +1,11 @@
 /// \file ligoPcieTiming_core.c
 /// \brief core functions for the LIGO timing card, init and read time
-#ifndef LIGO_PCIE_TIMING_CORE_IMPL
-#define LIGO_PCIE_TIMING_CORE_IMPL
-#include "ligoPcieTiming.h"
-#include "ioremap_selection.h"
+#include "drv/ligoPcieTiming.h"
+#include "drv/ioremap_selection.h"
+#include "util/printl.h"
+
+#include <linux/delay.h> //udelay()
+
 
 /// Convert fractional part of 2^32 Hz LPTC timing counter to microseconds 
 /// \param clock_ticks_2_32_hz fractional time as reported by LPTC
@@ -14,7 +16,7 @@ lptc_usec_convert_int(uint32_t clock_ticks_2_32_hz)
     return ((uint64_t)clock_ticks_2_32_hz * 1000000) >> 32;
 }
 
-static int
+int
 lptcInit( CDS_HARDWARE* pCds, struct pci_dev* lptcdev )
 {
     static unsigned int pci_io_addr;
@@ -28,11 +30,11 @@ lptcInit( CDS_HARDWARE* pCds, struct pci_dev* lptcdev )
 
     card = pCds->card_count[ LPTC ];
     status = pci_enable_device( lptcdev );
-    printk( "Xilinx enabled status = %d\n", status );
+    printl( "Xilinx enabled status = %d\n", status );
     pci_read_config_dword( lptcdev, PCI_BASE_ADDRESS_0, &pci_io_addr );
     pci_io_addr &= 0xfffffff0;
     addr = (char*)IOREMAP( (unsigned long)pci_io_addr, 0x2000 );
-    printk( "Xilinx mapped  = 0x%x   0x%p\n", pci_io_addr, addr );
+    printl( "Xilinx mapped  = 0x%x   0x%p\n", pci_io_addr, addr );
     pCds->lptc[ card ] = (unsigned int*)addr;
 
     if ( card == 0 )
@@ -47,40 +49,40 @@ lptcInit( CDS_HARDWARE* pCds, struct pci_dev* lptcdev )
     //usec = (gpstime & 0xffffffff) * LPTC_USEC_CONVERT;
     usec = lptc_usec_convert_int((uint32_t)(gpstime & 0xffffffff));
     sec = (gpstime >> 32) & 0xffffffff;
-    printk( "Xilinx time1  = %u   %u\n", sec, usec );
+    printl( "Xilinx time1  = %u   %u\n", sec, usec );
     udelay(1000);
     gpstime = lptcPtr->gps_time;
     //usec = (gpstime & 0xffffffff) * LPTC_USEC_CONVERT;
     usec = lptc_usec_convert_int((int32_t)(gpstime & 0xffffffff));
     sec = (gpstime >> 32) & 0xffffffff;
-    printk( "Xilinx time2  = %u   %u\n", sec, usec );
+    printl( "Xilinx time2  = %u   %u\n", sec, usec );
 
-    printk( "Xilinx status  = 0x%x  \n", lptcPtr->status );
-    printk( "Xilinx sw revision  = 0x%x  \n", lptcPtr->revision );
-    printk( "Xilinx bp config  = 0x%x  \n", lptcPtr->bp_config );
-    printk( "Xilinx bp status  = 0x%x  \n", lptcPtr->bp_status );
+    printl( "Xilinx status  = 0x%x  \n", lptcPtr->status );
+    printl( "Xilinx sw revision  = 0x%x  \n", lptcPtr->revision );
+    printl( "Xilinx bp config  = 0x%x  \n", lptcPtr->bp_config );
+    printl( "Xilinx bp status  = 0x%x  \n", lptcPtr->bp_status );
 
     regval = lptcPtr->status;
     if ( regval & LPTC_STATUS_OK )
-        printk( "LPTC Status = OK\n" );
+        printl( "LPTC Status = OK\n" );
     else
-        printk( "LPTC Status = BAD \n" );
+        printl( "LPTC Status = BAD \n" );
     if ( regval & LPTC_STATUS_UPLINK_OK )
-        printk( "LPTC Uplink = OK\n" );
+        printl( "LPTC Uplink = OK\n" );
     else
-        printk( "LPTC Uplink = BAD \n" );
-    printk( "LPTC Leap Seconds = %d\n",
+        printl( "LPTC Uplink = BAD \n" );
+    printl( "LPTC Leap Seconds = %d\n",
             ( ( regval & LPTC_STATUS_LEAP_SEC ) >> 8 ) );
-    printk( "LPTC Leap Seconds = 0x%x\n",
+    printl( "LPTC Leap Seconds = 0x%x\n",
             ( ( regval & LPTC_STATUS_LEAP_SEC ) ) );
 
     lptcPtr->bp_config = LPTC_CMD_STOP_CLK_ALL;
     msleep( 10 );
     regval = lptcPtr->bp_status;
     if ( regval & LPTC_BPS_BP_PRESENT )
-        printk( "LPTC backplane present = OK\n" );
+        printl( "LPTC backplane present = OK\n" );
     else
-        printk( "LPTC BACKPLANE IS NOT PRESENT \n" );
+        printl( "LPTC BACKPLANE IS NOT PRESENT \n" );
     pCds->card_count[ LPTC ]++;
     return 0;
 }
@@ -343,5 +345,3 @@ void lptc_get_external_pwr( CDS_HARDWARE* pCds, u32 *output)
     }
 }
 
-
-#endif /* LIGO_PCIE_TIMING_CORE_IMPL */
diff --git a/src/include/drv/map.h b/src/include/drv/map.h
index 9e9d606ae29b7dc9c9bdbe066f2955c2de32a8be..00649035e9ddbd0ab1b719ffb6a57ab40bebc82c 100644
--- a/src/include/drv/map.h
+++ b/src/include/drv/map.h
@@ -1,11 +1,26 @@
 #ifndef MAP_H_INCLUDED
 #define MAP_H_INCLUDED
 
+#include "drv/cdsHardware.h"
+
+#include <linux/types.h> //dma_addr_t
+#include <linux/pci.h> 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 void set_8111_prefetch( struct pci_dev* );
+int find_card_slot( CDS_HARDWARE* pCds, int ctype, int cinstance );
 int  mapPciModules( CDS_HARDWARE* ); /* Init routine to map adc/dac cards*/
 
+#ifdef __cplusplus
+}
+#endif
+
 // PCI Device variables
 // volatile PLX_9056_INTCTRL* plxIcr; /* Ptr to interrupt cntrl reg on PLX chip */
-dma_addr_t rfm_dma_handle[ MAX_DAC_MODULES ]; /* PCI add of RFM DMA memory */
+extern dma_addr_t rfm_dma_handle[ MAX_DAC_MODULES ]; /* PCI add of RFM DMA memory */
 
 #endif
diff --git a/src/include/drv/mapVirtual.h b/src/include/drv/mapVirtual.h
index 44816495adb933f72e2444f97dba552d57d0df50..51aa7616a68adcc88c16dad5f64c6514e0ea3905 100644
--- a/src/include/drv/mapVirtual.h
+++ b/src/include/drv/mapVirtual.h
@@ -1,33 +1,34 @@
 ///	\file mapVirtual.h
 ///	\brief This file contains the software to find PCIe devices on the bus.
 
+
+#include "commData3.h"
+
+#include "drv/cdsHardware.h"
+#include "drv/map.h"
+// Include driver code for all supported I/O cards
+#include "drv/plx_9056.h"
+#include "drv/gsc16ai64.h"
+#include "drv/gsc16ao16.h"
+#include "drv/gsc18ao8.h"
+#include "drv/gsc20ao8.h"
+#include "drv/accesIIRO8.h"
+#include "drv/accesIIRO16.h"
+#include "drv/accesDio24.h"
+#include "drv/contec6464.h"
+#include "drv/contec1616.h"
+#include "drv/contec32o.h"
+#include "drv/vmic5565.h"
+#include "drv/symmetricomGps.h"
+#include "drv/spectracomGPS.h"
+#include "drv/gsc18ai32.h"
+#include "drv/ligoPcieTiming.h"
+
+
 #include <linux/types.h>
 #include <linux/kernel.h>
-#undef printf
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
-#define printf printk
-#include <drv/cdsHardware.h>
-#include <drv/map.h>
-#include <commData3.h>
-
-// Include driver code for all supported I/O cards
-#include <drv/plx_9056.h>
-#include <drv/gsc16ai64.h>
-#include <drv/gsc16ao16.h>
-#include <drv/gsc18ao8.h>
-#include <drv/gsc20ao8.h>
-#include <drv/accesIIRO8.c>
-#include <drv/accesIIRO16.c>
-#include <drv/accesDio24.c>
-#include <drv/contec6464.c>
-#include <drv/contec1616.c>
-#include <drv/contec32o.c>
-#include <drv/vmic5565.c>
-#include <drv/symmetricomGps.c>
-#include <drv/spectracomGPS.c>
-#include <drv/gsc18ai32.h>
-#include <drv/ligoPcieTiming.h>
 
diff --git a/src/include/drv/mapuser.h b/src/include/drv/mapuser.h
index ccb9f0434fa96cc56b9a93a5fb251fb71ca39bf2..964f12dc8917b67893cb8724f83c2991846a9015 100644
--- a/src/include/drv/mapuser.h
+++ b/src/include/drv/mapuser.h
@@ -4,6 +4,11 @@
 #include <drv/cdsHardware.h>
 #include <commData3.h>
 
+//In userspace the linux/pci.h header does not have
+//the pci_dev struct defined, so we forward declare it
+//here, so we can include these headers without a warning
+struct pci_dev;
+
 #include "gsc16ai64.h"
 #include "gsc16ao16.h"
 #include "gsc18ao8.h"
diff --git a/src/include/drv/myri.h b/src/include/drv/myri.h
index 1d50b438bf968f29d0e60efd216359f452f03e3b..52b2aeb503de8fdfaaa5b573fab2dcf242b31134 100644
--- a/src/include/drv/myri.h
+++ b/src/include/drv/myri.h
@@ -1,3 +1,10 @@
+#ifndef LIGO_MYRI_H
+#define LIGO_MYRI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int myriNetInit(int);	  /* Initialize myrinet card.		*/
 int myriNetClose(void);	  /* Clean up myrinet on exit.		*/
 int myriNetCheckCallback(void);/* Check for messages on myrinet.	*/
@@ -14,3 +21,9 @@ int myriNetDaqSend(     int dcuId,
                         int tpNum[],
                         int xferSize,
                         char *dataBuffer);
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_MYRI_H
diff --git a/src/include/drv/no_ioc_dac_preload.h b/src/include/drv/no_ioc_dac_preload.h
new file mode 100644
index 0000000000000000000000000000000000000000..dce7c0506f9fbec9eeeb1e49513633c47ca7eef0
--- /dev/null
+++ b/src/include/drv/no_ioc_dac_preload.h
@@ -0,0 +1,32 @@
+#ifndef LIGO_NO_IOC_DAC_PRELOAD_H
+#define LIGO_NO_IOC_DAC_PRELOAD_H
+
+#include "portableInline.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// When we have no IO cards (virtual IO) this version
+// of iop_dac_preload() is called, it does nothing 
+// but it is put in its own header for now because controllerIop.c
+// and verify_slots.c both call it.
+//
+// The original comment was: dummy placeholder function that should never be called when there's no IOC
+//
+// But it has the possibility of being called or we wouldn't need to define it...
+
+LIGO_INLINE int iop_dac_preload( int card ) 
+{
+    return 0;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif // LIGO_NO_IOC_DAC_PRELOAD_H
diff --git a/src/include/drv/no_ioc_timing.c b/src/include/drv/no_ioc_timing.h
similarity index 90%
rename from src/include/drv/no_ioc_timing.c
rename to src/include/drv/no_ioc_timing.h
index ac80c408d2168bb9b80f090b9e8f2f5e4d643063..083f095de57f4a95635d164e838bc409a1000318 100644
--- a/src/include/drv/no_ioc_timing.c
+++ b/src/include/drv/no_ioc_timing.h
@@ -1,4 +1,27 @@
-inline int
+#ifndef LIGO_NO_IOC_TIMING_H
+#define LIGO_NO_IOC_TIMING_H
+
+#include "portableInline.h"
+#include "../drv/gpstime/gpstime_kernel.h" //LIGO_TIMESPEC
+#include "cds_types.h" //acdInfo_t
+#include "controller.h" //cdsPciModules
+#include "drv/symmetricomGps.h" //SYMCOM_RCVR
+#include "drv/spectracomGPS.h" //TSYNC_RCVR
+#include "drv/gsc16ai64.h" //GSAI_DATA_CODE_OFFSET
+#include "drv/gsc16ao16.h" //GSAO_16BIT_CHAN_COUNT
+#include "drv/gsc18ao8.h" //GSAO_18BIT_CHAN_COUNT
+#include "drv/gsc20ao8.h" //GSAO_20BIT_CHAN_COUNT
+#include "../fe/controllerIop.h" //dacTimingError, ioMemCntrDac, dacEnable, pBits
+#include "commData3.h" //TIMING_SIGNAL
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+LIGO_INLINE int
 waitPcieTimingSignal( volatile TIMING_SIGNAL* timePtr, int cycle )
 {
     int loop = 0;
@@ -13,15 +36,15 @@ waitPcieTimingSignal( volatile TIMING_SIGNAL* timePtr, int cycle )
     else
         return ( 0 );
 }
-inline int
+
+LIGO_INLINE int
 waitInternalTimingSignal( int cycle )
 {
-    int loop = 0;
-
     udelay( 14 );
     return ( 0 );
 }
-inline unsigned int
+
+LIGO_INLINE unsigned int
 sync2master( volatile TIMING_SIGNAL* timePtr )
 {
     int loop = 0;
@@ -41,19 +64,18 @@ sync2master( volatile TIMING_SIGNAL* timePtr )
         return ( timePtr->gps_time );
     }
 }
-inline unsigned int
-sync2cpuclock( )
+
+LIGO_INLINE unsigned int
+sync2cpuclock( void )
 {
     LIGO_TIMESPEC t;
     ligo_gpstime_get_ts(&t);
     return t.tv_sec;
 }
 
-inline int
+LIGO_INLINE int
 iop_adc_init( adcInfo_t* adcinfo )
 {
-    volatile int* adcDummyData;
-    int           status;
     int           ii, jj;
 
     /// \> If IOP,  Initialize the ADC modules
@@ -79,7 +101,10 @@ iop_adc_init( adcInfo_t* adcinfo )
     return 0;
 }
 
-inline int
+//
+//rdtsc_ordered() is a static function so this function won't be inlined
+//
+static int
 iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
 {
     int           kk = 0;
@@ -108,7 +133,7 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
         /// - ---- 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[ card ];
+        packedData = cdsPciModules.pci_adc[ card ];
 
         cpuClk[ CPU_TIME_RDY_ADC ] = rdtsc_ordered( );
         cpuClk[ CPU_TIME_ADC_WAIT ] = rdtsc_ordered( );
@@ -168,20 +193,20 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
                 // 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( );
+                    lockGpsTime( &cdsPciModules );
                 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( );
+                    timeSec = getGpsSecTsync( &cdsPciModules );
                 }
             }
         }
 
         /// \> Read adc data
-        packedData = (int*)cdsPciModules.pci_adc[ card ];
+        packedData = cdsPciModules.pci_adc[ card ];
 
         limit = OVERFLOW_LIMIT_16BIT;
         // Various ADC models have different number of channels/data bits
@@ -231,11 +256,10 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] )
     return adcStat;
 }
 
-inline int
+LIGO_INLINE int
 iop_dac_init( int errorPend[] )
 {
     int ii, jj;
-    int status;
 
     /// \> Zero out DAC outputs
     for ( ii = 0; ii < MAX_DAC_MODULES; ii++ )
@@ -260,10 +284,10 @@ iop_dac_init( int errorPend[] )
     return 0;
 }
 
-inline int
-iop_dac_write(  )
+LIGO_INLINE int
+iop_dac_write( void )
 {
-    unsigned int* pDacData;
+    volatile unsigned int* pDacData;
     int           ii, jj, mm;
     int           limit;
     int           num_outs;
@@ -316,7 +340,7 @@ iop_dac_write(  )
             num_outs = GSAO_20BIT_CHAN_COUNT;
         }
         /// - -- Point to DAC memory buffer
-        pDacData = (unsigned int*)( cdsPciModules.pci_dac[ jj ] );
+        pDacData = (volatile unsigned int*)( cdsPciModules.pci_dac[ jj ] );
         // Advance to the correct point in the one second memory buffer
         //pDacData += num_outs * cycleNum;
         /// - -- For each DAC channel
@@ -380,3 +404,10 @@ iop_dac_write(  )
 
     return status;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //LIGO_NO_IOC_TIMING_H
diff --git a/src/include/drv/plx_9056.c b/src/include/drv/plx_9056.c
index 0e3c648fb623e1d24b30de7c8c32fa5b09ec35b1..d1d5366f717e5b16f8182413bd59acc2666689fb 100644
--- a/src/include/drv/plx_9056.c
+++ b/src/include/drv/plx_9056.c
@@ -1,19 +1,23 @@
 /// \file plx_9056.c
 /// \brief File contains common PLX chip DMA routines for ADC and DAC modules
 
-#include "plx_9056.h"
+#include "drv/plx_9056.h"
 
-// ADC DMA Functions
-int plx9056_check_dma_done( int );
-int plx9056_wait_dma_done( int, int, int );
-void plx9056_adc_dma_setup( int, int );
-void plx9056_adc_dma_enable( int );
-void plx9056_adc_dma_start( int );
+#include <linux/delay.h> //udelay()
+
+
+//
+// Globals
+// Used by: include/drv/gsc18ai64.c, include/drv/gsc18ai32.c, include/drv/gsc20ao8, include/drv/gsc18ao8
+//
+#ifndef USER_SPACE
+volatile PLX_9056_DMA* adcDma[ MAX_ADC_MODULES ]; ///< DMA struct for GSA ADC
+dma_addr_t adc_dma_handle[ MAX_ADC_MODULES ]; ///< PCI add of ADC DMA memory
+
+volatile PLX_9056_DMA *dacDma[MAX_DAC_MODULES]; /* DMA struct for GSA DAC */
+dma_addr_t dac_dma_handle[MAX_DAC_MODULES];     /* PCI add of DAC DMA memory */
+#endif
 
-// DAC DMA Functions
-void plx9056_dac_1820_dma_setup( int );
-void plx9056_dac_16_dma_setup( int );
-void plx9056_dac_dma_start( int );
 
 
 // *****************************************************************************
@@ -50,7 +54,7 @@ plx9056_wait_dma_done( int module, int timeinterval, int time2wait)
     {
         ii++;
         udelay( timeinterval );
-    } while ( ( adcDma[ module ]->DMA_CSR & PLX_DMA_DONE == 0 ) &&
+    } while ( ( (adcDma[ module ]->DMA_CSR & PLX_DMA_DONE) == 0 ) &&
               ( ii < time2wait ) );
     // If DMA did not complete, return error
     if ( ii >= time2wait )
diff --git a/src/include/drv/plx_9056.h b/src/include/drv/plx_9056.h
index dcd327621443ec4dc310815e8dd5691520b0226d..fdc31f7f11b0774f3462b4cf5710629a25d3bd3b 100644
--- a/src/include/drv/plx_9056.h
+++ b/src/include/drv/plx_9056.h
@@ -1,3 +1,11 @@
+#ifndef LIGO_PLX_9056_H
+#define LIGO_PLX_9056_H
+
+
+#include "drv/cdsHardware.h" //MAX_ADC_MODULES, MAX_DAC_MODULES
+
+#include <linux/types.h>
+
 
 /* PLX Chip Definitions for GSA ADC/DAC Modules ******************************* */
 /* Common DMA register definition       */
@@ -42,12 +50,35 @@ typedef struct PLX_9056_INTCTRL{
 #define GSAO16_BTC        64      // num chans (16) * 4 bytes
 #define GSAO1820_BTC      32      // num chans (8) * 4 bytes
 
-#ifndef USER_SPACE
-volatile PLX_9056_DMA* adcDma[ MAX_ADC_MODULES ]; ///< DMA struct for GSA ADC
-dma_addr_t adc_dma_handle[ MAX_ADC_MODULES ]; ///< PCI add of ADC DMA memory
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-volatile PLX_9056_DMA *dacDma[MAX_DAC_MODULES]; /* DMA struct for GSA DAC */
-dma_addr_t dac_dma_handle[MAX_DAC_MODULES];     /* PCI add of DAC DMA memory */
+// ADC DMA Functions
+int plx9056_check_dma_done( int );
+int plx9056_wait_dma_done( int, int, int );
+void plx9056_adc_dma_setup( int module, int dma_bytes );
+void plx9056_adc_dma_set_size( int module, int dma_bytes );
+void plx9056_adc_dma_setup( int, int );
+void plx9056_adc_dma_enable( int );
+void plx9056_adc_dma_start( int );
+
+// DAC DMA Functions
+void plx9056_dac_1820_dma_setup( int );
+void plx9056_dac_16_dma_setup( int );
+void plx9056_dac_dma_start( int );
+
+#ifdef __cplusplus
+}
 #endif
 
 
+#ifndef USER_SPACE
+extern volatile PLX_9056_DMA* adcDma[ MAX_ADC_MODULES ]; ///< DMA struct for GSA ADC
+extern dma_addr_t adc_dma_handle[ MAX_ADC_MODULES ]; ///< PCI add of ADC DMA memory
+
+extern volatile PLX_9056_DMA *dacDma[MAX_DAC_MODULES]; /* DMA struct for GSA DAC */
+extern dma_addr_t dac_dma_handle[MAX_DAC_MODULES];     /* PCI add of DAC DMA memory */
+#endif
+
+#endif //LIGO_PLX_9056_H
diff --git a/src/include/drv/spectracomGPS.c b/src/include/drv/spectracomGPS.c
index d8226a096a315560528b945524058682c36945be..be44186165633bed55f1e2b01cbcd9389f953c4b 100644
--- a/src/include/drv/spectracomGPS.c
+++ b/src/include/drv/spectracomGPS.c
@@ -7,18 +7,28 @@
 ///<    href="http://www.spectracomcorp.com/ProductsServices/TimingSynchronization/BuslevelTiming/PCIexpressslotcards/tabid/1296/Default.aspx">Spectracom
 ///<    TSync-PCIe Manual</a>
 
-#include "spectracomGPS.h"
-#include "ioremap_selection.h"
+//#define LIGO_INLINE
+#include "drv/spectracomGPS.h"
+#include "drv/ioremap_selection.h"
+#include "drv/cdsHardware.h" //CDS_HARDWARE
+//#include "controller.h" //cdsPciModules //TODO: this should be a parameter
+#include "util/printl.h"
+
+#include <linux/pci.h> // PCI_BASE_ADDRESS_0
+#include <linux/delay.h> //udelay()
+
 
 // *****************************************************************************
-/// \brief Initialize TSYNC GPS card (model BC635PCI-U)
+/// \brief Initialize TSYNC GPS card (model BC635PCI-U). This is also used by
+//         the gpstime module.
+//
 ///     @param[in,out] *pHardware Pointer to global data structure for storing
-///     I/O
-///<            register mapping information.
+///     I/O register mapping information.
+//
 ///	@param *gpsdev PCI address information passed by the mapping code in
 ///map.c
 // *****************************************************************************
-static int
+int
 spectracomGpsInitCheckSync( CDS_HARDWARE*   pHardware,
                             struct pci_dev* gpsdev,
                             int*            need_sync )
@@ -39,10 +49,10 @@ spectracomGpsInitCheckSync( CDS_HARDWARE*   pHardware,
     pedStatus = pci_enable_device( gpsdev );
     pci_read_config_dword( gpsdev, PCI_BASE_ADDRESS_0, &pci_io_addr );
     pci_io_addr &= 0xfffffff0;
-    printk( "TSYNC PIC BASE 0 address = %x\n", pci_io_addr );
+    printl( "TSYNC PIC BASE 0 address = %x\n", pci_io_addr );
 
     addr1 = (unsigned char*)IOREMAP( (unsigned long)pci_io_addr, 0x30 );
-    printk( "Remapped 0x%p\n", addr1 );
+    printl( "Remapped 0x%p\n", addr1 );
     pHardware->gps = (unsigned int*)addr1;
     pHardware->gpsType = TSYNC_RCVR;
 
@@ -101,7 +111,7 @@ spectracomGpsInitCheckSync( CDS_HARDWARE*   pHardware,
         i = myTime->BCD_SEC;
         if ( i < 1000000000 )
         {
-            printk( "TSYNC NOT receiving YEAR info, defaulting to by year "
+            printl( "TSYNC NOT receiving YEAR info, defaulting to by year "
                     "patch\n" );
             *need_sync = 1;
             /* Historically we would hardwire a offset here.
@@ -141,23 +151,23 @@ spectracomGpsInitCheckSync( CDS_HARDWARE*   pHardware,
         else
         {
             *need_sync = 0;
-            printk( "TSYNC receiving YEAR info\n" );
+            printl( "TSYNC receiving YEAR info\n" );
             pHardware->gpsOffset = -315964800;
         }
         sec = i + pHardware->gpsOffset;
         i = myTime->BCD_SUB_SEC;
-        printk( "date = %d days %2d:%2d:%2d\n", days, hours, min, sec );
+        printl( "date = %d days %2d:%2d:%2d\n", days, hours, min, sec );
         usec = ( i & 0xf ) + ( ( i >> 4 ) & 0xf ) * 10 +
             ( ( i >> 8 ) & 0xf ) * 100;
         msec = ( ( i >> 16 ) & 0xf ) + ( ( i >> 20 ) & 0xf ) * 10 +
             ( ( i >> 24 ) & 0xf ) * 100;
-        printk(
+        printl(
             "bcd time = %d sec  %d milliseconds %d microseconds  %d nanosec\n",
             sec,
             msec,
             usec,
             nanosec );
-        printk( "Board sync = %d\n", tsync );
+        printl( "Board sync = %d\n", tsync );
     }
     return ( 0 );
 }
@@ -177,69 +187,3 @@ spectracomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev )
     return spectracomGpsInitCheckSync( pHardware, gpsdev, &need_sync_dummy );
 }
 
-//***********************************************************************
-/// \brief  Get current GPS time from TSYNC IRIG-B Rcvr
-/// @param[out] *tsyncSec Pointer to register with seconds information.
-/// @param[out] *tsyncUsec Pointer to register with microsecond information.
-/// @return GPS Sync bit (0=No sync 1=Sync)
-//***********************************************************************
-inline int
-getGpsTimeTsync( unsigned int* tsyncSec, unsigned int* tsyncUsec )
-{
-    volatile TSYNC_REGISTER* timeRead;
-    unsigned int    timeSec, timeNsec, sync;
-
-    if ( cdsPciModules.gps )
-    {
-        timeRead = (TSYNC_REGISTER*)cdsPciModules.gps;
-        timeSec = timeRead->BCD_SEC;
-        timeSec += cdsPciModules.gpsOffset;
-        *tsyncSec = timeSec;
-        timeNsec = timeRead->SUB_SEC;
-        *tsyncUsec = ( ( timeNsec & 0xfffffff ) * 5 ) / 1000;
-        sync = ( ( timeNsec >> 31 ) & 0x1 ) + 1;
-        return ( sync );
-    }
-    return ( 0 );
-}
-
-//***********************************************************************
-/// \brief Get current GPS seconds from TSYNC IRIG-B Rcvr
-//***********************************************************************
-inline unsigned int
-getGpsSecTsync( void )
-{
-    volatile TSYNC_REGISTER* timeRead;
-    unsigned int    timeSec;
-
-    if ( cdsPciModules.gps )
-    {
-        timeRead = (TSYNC_REGISTER*)cdsPciModules.gps;
-        timeSec = timeRead->BCD_SEC;
-        timeSec += cdsPciModules.gpsOffset;
-        return ( timeSec );
-    }
-    return ( 0 );
-}
-
-//***********************************************************************
-/// \brief Get current GPS useconds from TSYNC IRIG-B Rcvr
-/// @param[out] *tsyncUsec Pointer to register with microsecond information.
-/// @return GPS Sync bit (0=No sync 1=Sync)
-//***********************************************************************
-inline int
-getGpsuSecTsync( unsigned int* tsyncUsec )
-{
-    volatile TSYNC_REGISTER* timeRead;
-    unsigned int    timeNsec, sync;
-
-    if ( cdsPciModules.gps )
-    {
-        timeRead = (TSYNC_REGISTER*)cdsPciModules.gps;
-        timeNsec = timeRead->SUB_SEC;
-        *tsyncUsec = ( ( timeNsec & 0xfffffff ) * 5 ) / 1000;
-        sync = ( ( timeNsec >> 31 ) & 0x1 ) + 1;
-        return ( sync );
-    }
-    return ( 0 );
-}
diff --git a/src/include/drv/spectracomGPS.h b/src/include/drv/spectracomGPS.h
index 1b51a5a6fca6868a4e9fcc909769384ad312b467..000317b89dbd0a007b23b96907481079297b8a18 100644
--- a/src/include/drv/spectracomGPS.h
+++ b/src/include/drv/spectracomGPS.h
@@ -1,5 +1,12 @@
+#ifndef LIGO_SPECTRACOM_GPS_H
+#define LIGO_SPECTRACOM_GPS_H
 // Spectracom GPS input card
 
+#include "portableInline.h"
+#include "drv/cdsHardware.h"
+//#include "controller.h" //cdsPciModules
+
+#include <linux/pci.h>
 
 #define TSYNC_VID               0x1ad7
 #define TSYNC_TID               0x8000
@@ -14,4 +21,96 @@ typedef struct TSYNC_REGISTER{
         unsigned int BCD_SUB_SEC;       // Sub Second binary time
 }TSYNC_REGISTER;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// Function Prototypes
+//
+int spectracomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev );
+int spectracomGpsInitCheckSync( CDS_HARDWARE*   pHardware,
+                                struct pci_dev* gpsdev,
+                                int*            need_sync );
+
+
+//
+// Inline Functions
+//
+
+//***********************************************************************
+/// \brief  Get current GPS time from TSYNC IRIG-B Rcvr
+/// @param[out] *tsyncSec Pointer to register with seconds information.
+/// @param[out] *tsyncUsec Pointer to register with microsecond information.
+/// @return GPS Sync bit (0=No sync 1=Sync)
+//***********************************************************************
+LIGO_INLINE int
+getGpsTimeTsync(CDS_HARDWARE* pHardware, unsigned int* tsyncSec, unsigned int* tsyncUsec )
+{
+    volatile TSYNC_REGISTER* timeRead;
+    unsigned int    timeSec, timeNsec, sync;
+
+    if (  pHardware->gps )
+    {
+        timeRead = (TSYNC_REGISTER*)pHardware->gps;
+        timeSec = timeRead->BCD_SEC;
+        timeSec += pHardware->gpsOffset;
+        *tsyncSec = timeSec;
+        timeNsec = timeRead->SUB_SEC;
+        *tsyncUsec = ( ( timeNsec & 0xfffffff ) * 5 ) / 1000;
+        sync = ( ( timeNsec >> 31 ) & 0x1 ) + 1;
+        return ( sync );
+    }
+    return ( 0 );
+}
+
+//***********************************************************************
+/// \brief Get current GPS seconds from TSYNC IRIG-B Rcvr
+/// @param[in] pHardware Pointer to PCI hardware map
+//***********************************************************************
+LIGO_INLINE unsigned int
+getGpsSecTsync( CDS_HARDWARE* pHardware )
+{
+    volatile TSYNC_REGISTER* timeRead;
+    unsigned int    timeSec;
+
+    if ( pHardware->gps )
+    {
+        timeRead = (TSYNC_REGISTER*)pHardware->gps;
+        timeSec = timeRead->BCD_SEC;
+        timeSec += pHardware->gpsOffset;
+        return ( timeSec );
+    }
+    return ( 0 );
+}
+
+//***********************************************************************
+/// \brief Get current GPS useconds from TSYNC IRIG-B Rcvr
+/// @param[in] pHardware Pointer to PCI hardware map
+/// @param[out] *tsyncUsec Pointer to register with microsecond information.
+/// @return GPS Sync bit (0=No sync 1=Sync)
+//***********************************************************************
+LIGO_INLINE int
+getGpsuSecTsync( CDS_HARDWARE* pHardware, unsigned int* tsyncUsec )
+{
+    volatile TSYNC_REGISTER* timeRead;
+    unsigned int    timeNsec, sync;
+
+    if (  pHardware->gps )
+    {
+        timeRead = (TSYNC_REGISTER*)pHardware->gps;
+        timeNsec = timeRead->SUB_SEC;
+        *tsyncUsec = ( ( timeNsec & 0xfffffff ) * 5 ) / 1000;
+        sync = ( ( timeNsec >> 31 ) & 0x1 ) + 1;
+        return ( sync );
+    }
+    return ( 0 );
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
 
+#endif //LIGO_SPECTRACOM_GPS_H
diff --git a/src/include/drv/symmetricomGps.c b/src/include/drv/symmetricomGps.c
index 345b94b06d22e793289ba091feb208e9f30a8f63..0f3eda407cf60838f1bdbf8c843f8a65ed5402bc 100644
--- a/src/include/drv/symmetricomGps.c
+++ b/src/include/drv/symmetricomGps.c
@@ -1,5 +1,9 @@
-#include "symmetricomGps.h"
-#include "ioremap_selection.h"
+#include "drv/symmetricomGps.h"
+#include "drv/ioremap_selection.h"
+#include "util/printl.h"
+
+#include <asm/delay.h>
+
 
 // *****************************************************************************
 /// Initialize Symmetricom GPS card (model BC635PCI-U)
@@ -20,10 +24,10 @@ symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev )
     pedStatus = pci_enable_device( gpsdev );
     pci_read_config_dword( gpsdev, PCI_BASE_ADDRESS_2, &pci_io_addr );
     pci_io_addr &= 0xfffffff0;
-    printk( "PIC BASE 2 address = %x\n", pci_io_addr );
+    printl( "PIC BASE 2 address = %x\n", pci_io_addr );
 
     addr1 = (unsigned char*)IOREMAP( (unsigned long)pci_io_addr, 0x40 );
-    printk( "Remapped 0x%p\n", addr1 );
+    printl( "Remapped 0x%p\n", addr1 );
     pHardware->gps = (unsigned int*)addr1;
     pHardware->gpsType = SYMCOM_RCVR;
     timeReg = (SYMCOM_REGISTER*)addr1;
@@ -33,8 +37,8 @@ symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev )
     pci_io_addr &= 0xfffffff0;
     addr3 =
         (unsigned char*)IOREMAP( (unsigned long)pci_io_addr, 0x200 );
-    printk( "PIC BASE 3 address = 0x%x\n", pci_io_addr );
-    printk( "PIC BASE 3 address = 0x%p\n", addr3 );
+    printl( "PIC BASE 3 address = 0x%x\n", pci_io_addr );
+    printl( "PIC BASE 3 address = 0x%p\n", addr3 );
     dramRead = (unsigned int*)( addr3 + 0x82 );
     cmd = (unsigned int*)( addr3 + 0x102 );
     //
@@ -50,8 +54,8 @@ symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev )
         i++;
     } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) );
     if ( timeReg->ACK )
-        printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
-    printk( "Model = 0x%x\n", *dramRead );
+        printl( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
+    printl( "Model = 0x%x\n", *dramRead );
     // End Wait ****************************************
     //
     // Set write and wait *****************************
@@ -66,8 +70,8 @@ symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev )
         i++;
     } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) );
     if ( timeReg->ACK )
-        printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
-    printk( "Model = 0x%x\n", *dramRead );
+        printl( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
+    printl( "Model = 0x%x\n", *dramRead );
     // End Wait ****************************************
     //
     // Set write and wait *****************************
@@ -82,8 +86,8 @@ symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev )
         i++;
     } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) );
     if ( timeReg->ACK )
-        printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
-    printk( "Model = 0x%x\n", *dramRead );
+        printl( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
+    printl( "Model = 0x%x\n", *dramRead );
     // End Wait ****************************************
     //
     // Set write and wait *****************************
@@ -98,8 +102,8 @@ symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev )
         i++;
     } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) );
     if ( timeReg->ACK )
-        printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
-    printk( "New Time COde Format = 0x%x\n", *dramRead );
+        printl( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
+    printl( "New Time COde Format = 0x%x\n", *dramRead );
     // End Wait ****************************************
     //
     // Set write and wait *****************************
@@ -114,14 +118,14 @@ symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev )
         i++;
     } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) );
     if ( timeReg->ACK )
-        printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
-    printk( "New TC Modulation = 0x%x\n", *dramRead );
+        printl( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i );
+    printl( "New TC Modulation = 0x%x\n", *dramRead );
     // End Wait ****************************************
 
     for ( i = 0; i < 10; i++ )
     {
         pHardware->gps[ 0 ] = 1;
-        printk( "Current time %ds %dus %dns \n",
+        printl( "Current time %ds %dus %dns \n",
                 ( pHardware->gps[ 0x34 / 4 ] - 252806386 ),
                 0xfffff & pHardware->gps[ 0x30 / 4 ],
                 100 * ( ( pHardware->gps[ 0x30 / 4 ] >> 20 ) & 0xf ) );
@@ -129,39 +133,9 @@ symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev )
     pHardware->gps[ 0 ] = 1;
     time0 = pHardware->gps[ 0x30 / 4 ];
     if ( time0 & ( 1 << 24 ) )
-        printk( "Flywheeling, unlocked...\n" );
+        printl( "Flywheeling, unlocked...\n" );
     else
-        printk( "Locked!\n" );
+        printl( "Locked!\n" );
     return ( 0 );
 }
 
-inline void
-lockGpsTime( void )
-{
-    volatile SYMCOM_REGISTER* timeRead;
-    timeRead = (SYMCOM_REGISTER*)cdsPciModules.gps;
-    timeRead->TIMEREQ = 1; // Trigger module to capture time
-}
-
-//***********************************************************************
-// Function to read time from Symmetricom IRIG-B Module ***********************
-//***********************************************************************
-inline int
-getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec )
-{
-    volatile SYMCOM_REGISTER* timeRead;
-    unsigned int     timeSec, timeNsec, sync;
-
-    if ( cdsPciModules.gps )
-    {
-        timeRead = (SYMCOM_REGISTER*)cdsPciModules.gps;
-        timeSec = timeRead->TIME1;
-        timeNsec = timeRead->TIME0;
-        *tsyncSec = timeSec - 315964800;
-        *tsyncUsec = ( timeNsec & 0xfffff );
-        // Read seconds, microseconds, nanoseconds
-        sync = !( timeNsec & ( 1 << 24 ) );
-        return sync;
-    }
-    return ( 0 );
-}
diff --git a/src/include/drv/symmetricomGps.h b/src/include/drv/symmetricomGps.h
index 5f23f6a95470b3a408dc598eb4ab4025a0addd0d..232d663b04f5e350d219e9b4bfe7ea167a985d8f 100644
--- a/src/include/drv/symmetricomGps.h
+++ b/src/include/drv/symmetricomGps.h
@@ -1,3 +1,12 @@
+#ifndef LIGO_SYMMETRICOM_GPS_H
+#define LIGO_SYMMETRICOM_GPS_H
+
+#include "portableInline.h"
+#include "drv/cdsHardware.h"
+//#include "controller.h" //cdsPciModules
+
+#include <linux/pci.h>
+
 // Symmertricom GPS input card
 // model BC635PCI-U
 typedef struct SYMCOM_REGISTER{
@@ -34,3 +43,55 @@ typedef struct SYMCOM_REGISTER{
 #define SYMCOM_BC635_EVENT1     0x3C
 #define SYMCOM_RCVR             0x1
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// Declarations for c file
+//
+
+int symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev );
+
+//
+// Inline functions
+//
+
+LIGO_INLINE void
+lockGpsTime( CDS_HARDWARE* pHardware )
+{
+    volatile SYMCOM_REGISTER* timeRead;
+    timeRead = (SYMCOM_REGISTER*)pHardware->gps;
+    timeRead->TIMEREQ = 1; // Trigger module to capture time
+}
+
+//***********************************************************************
+// Function to read time from Symmetricom IRIG-B Module ***********************
+//***********************************************************************
+LIGO_INLINE int
+getGpsTime( CDS_HARDWARE* pHardware, unsigned int* tsyncSec, unsigned int* tsyncUsec )
+{
+    volatile SYMCOM_REGISTER* timeRead;
+    unsigned int     timeSec, timeNsec, sync;
+
+    if ( pHardware->gps )
+    {
+        timeRead = (SYMCOM_REGISTER*)pHardware->gps;
+        timeSec = timeRead->TIME1;
+        timeNsec = timeRead->TIME0;
+        *tsyncSec = timeSec - 315964800;
+        *tsyncUsec = ( timeNsec & 0xfffff );
+        // Read seconds, microseconds, nanoseconds
+        sync = !( timeNsec & ( 1 << 24 ) );
+        return sync;
+    }
+    return ( 0 );
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif //LIGO_SYMMETRICOM_GPS_H
diff --git a/src/include/drv/tRamp.c b/src/include/drv/tRamp.c
deleted file mode 100644
index 72597bf786fc4410afeefb7b0f8756b94650da0e..0000000000000000000000000000000000000000
--- a/src/include/drv/tRamp.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/************************************************/
-/* Time ramp function */
-/* Takes in a ramping state */
-
-inline double
-RampParamGetVal( RampParamState* state )
-{
-    return state->val;
-}
-
-inline int
-RampParamGetIsRamping( RampParamState* state )
-{
-    return state->isRamping;
-}
-
-inline void
-RampParamInit( RampParamState* state, double xInit, const int fe_rate )
-{
-    state->isRamping = 0;
-    state->val = xInit;
-    state->dxPrev = 0.0;
-
-    state->req = xInit;
-    state->dxMax = 0.0;
-    state->ddxMax = 0.0;
-
-    state->softRatio = 4.0;
-    state->softVel = 1.36; // how to compute this from softRatio?
-    state->minAccCycles = 0.05 * fe_rate;
-}
-
-inline void
-RampParamLoad( RampParamState* state,
-               double          req,
-               double          tRamp,
-               const int       fe_rate )
-{
-    double inv_nRamp; // 1 / number of ramp cycles
-
-    if ( tRamp <= 0.0 )
-    {
-        // no ramp
-        state->isRamping = 0;
-        state->val = req;
-        state->dxPrev = 0.0;
-
-        state->req = req;
-        state->dxMax = 0.0;
-        state->ddxMax = 0.0;
-    }
-    else if ( state->isRamping || req != state->val )
-    {
-        // setup ramp parameters
-        inv_nRamp = 1.0 / ( fe_rate * tRamp );
-        state->req = req;
-        state->dxMax = state->softVel * lfabs( req - state->val ) * inv_nRamp;
-        state->ddxMax = state->softRatio * state->dxMax * inv_nRamp;
-
-        // if currently ramping, allow high accelleration
-        if ( state->isRamping )
-            state->ddxMax =
-                lfabs( state->dxMax + state->dxPrev ) / state->minAccCycles;
-
-        // start the ramp
-        state->isRamping = 1;
-    }
-}
-
-inline double
-RampParamUpdate( RampParamState* state )
-{
-    double dxReq; // distance to requested value
-    double dxNow; // current step size
-    double dxNowAbs; // lfabs(dxNow)
-    double ddxNow; // current change in step size
-    double nStop; // steps required to stop (may be non-integer)
-    double dxStop; // shortest distance required to stop
-    double dxLand; // current step size to achieve "soft landing"
-
-    // if not ramping, just return
-    if ( !state->isRamping )
-        return state->val;
-
-    // requested change
-    dxReq = state->req - state->val;
-
-    // apply slew limit
-    if ( dxReq > state->dxMax )
-        dxNow = state->dxMax;
-    else if ( dxReq < -state->dxMax )
-        dxNow = -state->dxMax;
-    else
-        dxNow = dxReq;
-
-    // apply accelleration limit
-    ddxNow = dxNow - state->dxPrev;
-    if ( ddxNow > state->ddxMax )
-        dxNow = state->dxPrev + state->ddxMax;
-    else if ( ddxNow < -state->ddxMax )
-        dxNow = state->dxPrev - state->ddxMax;
-
-    // enforce "soft landing"
-    dxNowAbs = lfabs( dxNow );
-    if ( dxNowAbs > state->ddxMax && dxNow * dxReq > 0.0 )
-    {
-        // number of decellerations required to stop
-        nStop = dxNowAbs / state->ddxMax;
-
-        // distance traveled before stopping
-        // assuming max decelleration in all subsequent steps
-        dxStop = dxNow * ( 1.5 + 0.5 * nStop );
-
-        // dxNow required to make stopping distance = dxReq
-        // (approximation for dxReq ~ dxStop)
-        dxLand = dxNow + ( dxReq - dxStop ) / ( 1.5 + nStop );
-
-        // if dxLand is slower than dxNow, use it
-        if ( lfabs( dxLand ) < dxNowAbs )
-            dxNow = dxLand;
-    }
-
-
-    //approx. minimum fraction of a double precision value that when added, changes that value
-    const double minprecision = 1.1103e-16;
-
-    //minimum change that will affect the current value (this is approximate, and can be bigger than the minimum change).
-    double minchange = lfabs(state->val)*minprecision;
-
-    if(dxNow != 0.0)
-    {
-        //handle the case where dxReq is smaller than our approx. minimum
-        if(minchange > lfabs(dxReq))
-        {
-            dxNow = dxReq;
-        }
-        else
-        {
-            //otherwise, use the approx. minimum as a lower limit for our change.
-            if(minchange > lfabs(dxNow))
-            {
-                dxNow = dxNow > 0 ? minchange : -minchange;
-            }
-        }
-    }
-
-
-    // update state
-    state->isRamping = !( dxNow == 0.0 && state->dxPrev == 0.0 );
-
-    //if close enough, just jump to the end
-    if ( lfabs(dxNow) >= lfabs(dxReq))
-    {
-        state->val = state->req;
-        dxNow = dxReq;
-    }
-    else
-    {
-        state->val += dxNow;
-    }
-
-    state->dxPrev = dxNow;
-
-    return state->val;
-}
diff --git a/src/include/drv/vmic5565.c b/src/include/drv/vmic5565.c
index de1635de6dbe407501173b94445d4290aaf177a7..3d0008cf86795edbe6d21c35c39b6a75f68a8f85 100644
--- a/src/include/drv/vmic5565.c
+++ b/src/include/drv/vmic5565.c
@@ -10,6 +10,17 @@
 
 #include "vmic5565.h"
 #include "ioremap_selection.h"
+#include "drv/cdsHardware.h"
+#include "commData3.h" // IPC_BUFFER_SIZE
+#include "map.h" //rfm_dma_handle
+#include "util/printl.h"
+
+#include <linux/pci.h>
+
+
+static volatile VMIC5565_CSR *p5565Csr[MAX_RFM_MODULES];                // VMIC5565 Control/Status Registers
+static volatile VMIC5565DMA *p5565Dma[MAX_RFM_MODULES];              // VMIC5565 DMA Engine
+
 
 // *****************************************************************************
 /// \brief Routine to initialize VMIC RFM modules. \n
@@ -39,11 +50,11 @@ vmic5565Init( CDS_HARDWARE* pHardware, struct pci_dev* rfmdev )
     // Allocate local memory for IPC DMA xfers from RFM module
     pHardware->pci_rfm_dma[ devNum ] = (long)pci_alloc_consistent(
         rfmdev, IPC_BUFFER_SIZE, &rfm_dma_handle[ devNum ] );
-    printk( "RFM address is 0x%ux\n", pci_io_addr );
+    printl( "RFM address is 0x%ux\n", pci_io_addr );
 
     // Find the RFM control/status register
     pci_read_config_dword( rfmdev, PCI_BASE_ADDRESS_2, &csrAddress );
-    printk( "CSR address is 0x%x\n", csrAddress );
+    printl( "CSR address is 0x%x\n", csrAddress );
     csrAddr = IOREMAP( (unsigned long)csrAddress, 0x40 );
 
     p5565Csr[ devNum ] = (VMIC5565_CSR*)csrAddr;
@@ -51,39 +62,39 @@ vmic5565Init( CDS_HARDWARE* pHardware, struct pci_dev* rfmdev )
     p5565Csr[ devNum ]->LCSR1 &= ~TURN_OFF_5565_FAIL;
     p5565Csr[ devNum ]->LCSR1 &= !1; // Turn off own data light
 
-    printk( "Board id = 0x%x\n", p5565Csr[ devNum ]->BID );
+    printl( "Board id = 0x%x\n", p5565Csr[ devNum ]->BID );
     pHardware->rfmConfig[ devNum ] = p5565Csr[ devNum ]->NID;
 
     // Check switches and such
     if ( p5565Csr[ devNum ]->LCSR1 & VMIC_5565_REDUNDANT_MODE )
-        printk( "VMIC5565 set to redundant transfers\n" );
+        printl( "VMIC5565 set to redundant transfers\n" );
     else
-        printk( "VMIC5565 set to single transfers\n" );
+        printl( "VMIC5565 set to single transfers\n" );
     if ( p5565Csr[ devNum ]->LCSR1 & VMIC_5565_ROGUE_MASTER1 )
-        printk( "VMIC5565 ROGUE MASTER 1 = ON\n" );
+        printl( "VMIC5565 ROGUE MASTER 1 = ON\n" );
     else
-        printk( "VMIC5565 ROGUE MASTER 1 = OFF\n" );
+        printl( "VMIC5565 ROGUE MASTER 1 = OFF\n" );
     if ( p5565Csr[ devNum ]->LCSR1 & VMIC_5565_ROGUE_MASTER0 )
-        printk( "VMIC5565 ROGUE MASTER 0 = ON\n" );
+        printl( "VMIC5565 ROGUE MASTER 0 = ON\n" );
     else
-        printk( "VMIC5565 ROGUE MASTER 0 = OFF\n" );
+        printl( "VMIC5565 ROGUE MASTER 0 = OFF\n" );
     if ( p5565Csr[ devNum ]->LCSR1 & VMIC_5565_MEM_SIZE )
-        printk( "VMIC5565 Memory size = 128MBytes\n" );
+        printl( "VMIC5565 Memory size = 128MBytes\n" );
     else
-        printk( "VMIC5565 Memory size = 64MBytes\n" );
+        printl( "VMIC5565 Memory size = 64MBytes\n" );
     //
     // Find DMA Engine controls in RFM Local Configuration Table
     pci_read_config_dword( rfmdev, PCI_BASE_ADDRESS_0, &dmaAddress );
-    printk( "DMA address is 0x%ux\n", dmaAddress );
+    printl( "DMA address is 0x%ux\n", dmaAddress );
     dmaAddr = IOREMAP( dmaAddress, 0x200 );
     p5565Dma[ devNum ] = (VMIC5565DMA*)dmaAddr;
     // pHardware->rfm_dma[devNum] = p5565Dma[devNum];
-    printk( "5565DMA at 0x%lx\n", (unsigned long int)p5565Dma[ devNum ] );
-    printk( "5565 INTCR = 0x%ux\n", p5565Dma[ devNum ]->INTCSR );
+    printl( "5565DMA at 0x%lx\n", (unsigned long int)p5565Dma[ devNum ] );
+    printl( "5565 INTCR = 0x%ux\n", p5565Dma[ devNum ]->INTCSR );
     p5565Dma[ devNum ]->INTCSR = 0; // Disable interrupts from this card
-    printk( "5565 INTCR = 0x%ux\n", p5565Dma[ devNum ]->INTCSR );
-    printk( "5565 MODE = 0x%ux\n", p5565Dma[ devNum ]->DMA0_MODE );
-    printk( "5565 DESC = 0x%ux\n", p5565Dma[ devNum ]->DMA0_DESC );
+    printl( "5565 INTCR = 0x%ux\n", p5565Dma[ devNum ]->INTCSR );
+    printl( "5565 MODE = 0x%ux\n", p5565Dma[ devNum ]->DMA0_MODE );
+    printl( "5565 DESC = 0x%ux\n", p5565Dma[ devNum ]->DMA0_DESC );
     // Preload some DMA settings
     // Only important items here are BTC and DESC fields, which are used
     // later by DMA routine.
diff --git a/src/include/drv/vmic5565.h b/src/include/drv/vmic5565.h
index 28b0c6737a8904699ff2cd294d5c241a8e757e4a..502176b420e5a83636a8c9168e7cf71b06de720b 100644
--- a/src/include/drv/vmic5565.h
+++ b/src/include/drv/vmic5565.h
@@ -1,3 +1,6 @@
+#ifndef LIGO_VMIC5565_H
+#define LIGO_VMIC5565_H
+
 #define TURN_OFF_5565_FAIL	0x80000000
 #define UINT32 unsigned int
 
@@ -87,6 +90,7 @@ typedef struct VMIC5565RTR{
         unsigned int INTCSR;
 }VMIC5565RTR;
 
-volatile VMIC5565_CSR *p5565Csr[MAX_RFM_MODULES];                // VMIC5565 Control/Status Registers
-volatile VMIC5565DMA *p5565Dma[MAX_RFM_MODULES];              // VMIC5565 DMA Engine
+//volatile VMIC5565_CSR *p5565Csr[MAX_RFM_MODULES];                // VMIC5565 Control/Status Registers
+//volatile VMIC5565DMA *p5565Dma[MAX_RFM_MODULES];              // VMIC5565 DMA Engine
 
+#endif //LIGO_VMIC5565_H
diff --git a/src/include/fe.h b/src/include/fe.h
index 58dc3909822e50a2d8cf26109639641d805ac9e3..a6df4d44d10d338684b1955e2d8396f74fd3588e 100644
--- a/src/include/fe.h
+++ b/src/include/fe.h
@@ -1,63 +1,30 @@
 #ifndef LIGO_FE_H
 #define LIGO_FE_H
 
-#include "linux/types.h"
-#include "linux/kernel.h"
-#include "asm/delay.h"
-#include "asm/processor.h"
-// extern int printf(const char *, ...) __attribute__((format(printf, 1, 2)));
-// extern int printf(const char *, ...);
-#define printf printk
-#include "inlineMath.h"
+#include "controller.h" //This has most globals externed
+#include "controllerko.h" //CDIO* Globals and tdsControl/tdsCount
+
+#include "modelRateInfo.h" ////CYCLE_PER_SECOND, FE_RATE
+#include "util/inlineMath.h"
+#include "util/timing.h"
+#include "fm10Gen.h"
+#include "tRamp.h"
+#include "isnan.h"
+#include "commData3.h"
+
+#include "drv/inputFilterModule.h" //inputFilterModule()
 #include "drv/cdsHardware.h"
+#include "drv/epicsXfer.h"
+
 #include FE_HEADER
-#include "tRamp.h"
-extern int          cycleNum;
-extern unsigned int odcStateWord;
-extern unsigned int cycle_gps_time;
-#include "fm10Gen.h"
-#include "drv/dtoal.c"
-extern unsigned int dWordUsed[ MAX_ADC_MODULES ][ 32 ];
-extern unsigned int dacOutUsed[ MAX_DAC_MODULES ][ 16 ];
-extern int          dacChanErr[ MAX_DAC_MODULES ];
-extern unsigned int CDIO6464Output[ MAX_DIO_MODULES ];
-extern unsigned int CDIO1616Output[ MAX_DIO_MODULES ];
-extern unsigned int CDIO1616InputInput[ MAX_DIO_MODULES ];
-extern unsigned int CDIO6464InputInput[ MAX_DIO_MODULES ];
-extern double*      testpoint[ 500 ];
-extern double       xExc[ 50 ];
-extern char*        _shmipc_shm;
-extern int          startGpsTime;
-extern CDS_HARDWARE cdsPciModules;
-extern unsigned int ipcErrBits;
-extern unsigned int timeSec;
-extern unsigned int curDaqBlockSize;
-int                 rioOutput[ MAX_DIO_MODULES ];
-int                 rioInputOutput[ MAX_DIO_MODULES ];
-int                 rioOutput1[ MAX_DIO_MODULES ];
-int                 rioInput1[ MAX_DIO_MODULES ];
-int                 rioInputInput[ MAX_DIO_MODULES ];
-int gainRamp( float gainReq, int rampTime, int id, float* gain, int gainRate );
-unsigned int CDO32Output[ MAX_DIO_MODULES ];
 
-#if defined( SERVO1024K )
-#define CYCLE_PER_SECOND ( 1024 * 1024 )
-#elif defined( SERVO512K )
-#define CYCLE_PER_SECOND ( 512 * 1024 )
-#elif defined( SERVO256K )
-#define CYCLE_PER_SECOND ( 256 * 1024 )
-#elif defined( SERVO128K )
-#define CYCLE_PER_SECOND ( 128 * 1024 )
-#elif defined( SERVO64K )
-#define CYCLE_PER_SECOND ( 64 * 1024 )
-#elif defined( SERVO32K )
-#define CYCLE_PER_SECOND ( 32 * 1024 )
-#elif defined( SERVO16K )
-#define CYCLE_PER_SECOND ( 16 * 1024 )
-#elif defined( SERVO4K )
-#define CYCLE_PER_SECOND ( 4 * 1024 )
-#elif defined( SERVO2K )
-#define CYCLE_PER_SECOND ( 2 * 1024 )
-#endif
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <asm/delay.h>
+#include <asm/processor.h>
+#else
+#include <stdbool.h>
+#endif //__KERNEL__
 
 #endif //LIGO_FE_H
diff --git a/src/include/feComms.h b/src/include/feComms.h
index 21fdbe15fe744986e75de73dd5db87ef571aea1c..db3331477c095cff80e132194a34e74a638a3eff 100644
--- a/src/include/feComms.h
+++ b/src/include/feComms.h
@@ -5,7 +5,9 @@
 #ifndef LIGO_FECOMMS_H
 #define LIGO_FECOMMS_H
 
-#include FE_HEADER
+#include "fm10Gen_types.h"
+
+#include FE_HEADER //CDS_EPICS
 
 /// Structure for passing data between EPICS and Real-time Code. \n
 /// Original use was via RFM network, but now used in shared memory.
@@ -48,4 +50,4 @@ typedef struct RFM_FE_COMMS
         ;
 } RFM_FE_COMMS;
 
-#endif
+#endif //LIGO_FECOMMS_H
diff --git a/src/include/feuser.h b/src/include/feuser.h
deleted file mode 100644
index 3a47b60daa45e425c1ab2ebf1c4654c2faf943a7..0000000000000000000000000000000000000000
--- a/src/include/feuser.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef LIGO_FEUSER_H
-#define LIGO_FEUSER_H
-
-#include "linux/types.h"
-// #include "math.h"
-#include "inlineMath.h"
-#include "drv/cdsHardware.h"
-#include FE_HEADER
-#include "tRamp.h"
-extern int          cycleNum;
-extern unsigned int odcStateWord;
-extern unsigned int cycle_gps_time;
-#include "fm10Gen.h"
-#include "drv/dtoal.c"
-extern unsigned int dWordUsed[ MAX_ADC_MODULES ][ 32 ];
-extern unsigned int dacOutUsed[ MAX_DAC_MODULES ][ 16 ];
-extern int          dacChanErr[ MAX_DAC_MODULES ];
-extern unsigned int CDIO6464Output[ MAX_DIO_MODULES ];
-extern unsigned int CDIO1616Output[ MAX_DIO_MODULES ];
-extern unsigned int CDIO1616InputInput[ MAX_DIO_MODULES ];
-extern unsigned int CDIO6464InputInput[ MAX_DIO_MODULES ];
-extern double*      testpoint[ 500 ];
-extern double       xExc[ 50 ];
-extern char*        _shmipc_shm;
-extern int          startGpsTime;
-extern CDS_HARDWARE cdsPciModules;
-extern unsigned int ipcErrBits;
-extern unsigned int timeSec;
-extern unsigned int curDaqBlockSize;
-int                 rioOutput[ MAX_DIO_MODULES ];
-int                 rioInputOutput[ MAX_DIO_MODULES ];
-int                 rioOutput1[ MAX_DIO_MODULES ];
-int                 rioInput1[ MAX_DIO_MODULES ];
-int                 rioInputInput[ MAX_DIO_MODULES ];
-int gainRamp( float gainReq, int rampTime, int id, float* gain, int gainRate );
-unsigned int CDO32Output[ MAX_DIO_MODULES ];
-extern void RampParamInit( RampParamState* , double , const int  );
-extern double RampParamGetVal( RampParamState*  );
-extern int RampParamGetIsRamping( RampParamState*  );
-extern void RampParamLoad( RampParamState*,double,double,const int);
-extern double RampParamUpdate( RampParamState*);
-
-#if defined( SERVO256K )
-#define CYCLE_PER_SECOND ( 256 * 1024 )
-#elif defined( SERVO128K )
-#define CYCLE_PER_SECOND ( 128 * 1024 )
-#elif defined( SERVO64K )
-#define CYCLE_PER_SECOND ( 64 * 1024 )
-#elif defined( SERVO32K )
-#define CYCLE_PER_SECOND ( 32 * 1024 )
-#elif defined( SERVO16K )
-#define CYCLE_PER_SECOND ( 16 * 1024 )
-#elif defined( SERVO4K )
-#define CYCLE_PER_SECOND ( 4 * 1024 )
-#elif defined( SERVO2K )
-#define CYCLE_PER_SECOND ( 2 * 1024 )
-#endif
-
-#endif //LIGO_FEUSER_H
diff --git a/src/include/findSharedMemory.h b/src/include/findSharedMemory.h
index f4ae974a4364252b64630c3609aefdcc37bba274..b03777685fc9dd1238d1d35b7988d931fa0c3a71 100644
--- a/src/include/findSharedMemory.h
+++ b/src/include/findSharedMemory.h
@@ -1,7 +1,17 @@
 #ifndef LIGO_FINDSHAREDMEMORY_H 
 #define LIGO_FINDSHAREDMEMORY_H
 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 volatile void* findSharedMemory( char* );
 volatile void* findSharedMemorySize( char*, int size_mb );
 
+#ifdef __cplusplus
+}
+#endif
+
+
 #endif
diff --git a/src/include/fm10Gen.h b/src/include/fm10Gen.h
index edbfcb15ce1b5fdac2f66d80f646fadfbeebc6a0..34bf6bd3108be2e5de8cdfdb32215ebee3296543 100644
--- a/src/include/fm10Gen.h
+++ b/src/include/fm10Gen.h
@@ -1,235 +1,378 @@
-#ifndef FM10GEN_H
-#define FM10GEN_H
+/*-----------------------------------------------------------------------------
+ */
+/*                                                                              */
+/*                      ------------------- */
+/*                                                                              */
+/*                             LIGO */
+/*                                                                              */
+/*        THE LASER INTERFEROMETER GRAVITATIONAL WAVE OBSERVATORY. */
+/*                                                                              */
+/*                     (C) The LIGO Project, 2005. */
+/*                                                                              */
+/*                                                                              */
+/* File: fm10Gen.h */
+/* Description: */
+/*      CDS generic code for calculating IIR filters. */
+/*                                                                              */
+/* California Institute of Technology */
+/* LIGO Project MS 18-34 */
+/* Pasadena CA 91125 */
+/*                                                                              */
+/* Massachusetts Institute of Technology */
+/* LIGO Project MS 20B-145 */
+/* Cambridge MA 01239 */
+/*                                                                              */
+/*-----------------------------------------------------------------------------
+ */
 
 ///	@file fm10Gen.h
-///	@brief This file contains the basic defines and structures required to
-///<		process IIR/FIR filter calculations and pass filter module data.
+///	@brief This file contains the routines for performing the real-time
+///		IIR/FIR filter calculations. \n
+///	Further information is provided in the LIGO DCC
+///	<a
+///href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7687">T0900606
+///CDS Standard IIR Filter Module Software</a>
 
-/*****************************************************************************/
-/* #include <sysLib.h> */
+#ifndef LIGO_FM10GEN_H
+#define LIGO_FM10GEN_H
 
-#ifndef UINT32
-#define UINT32 unsigned int
-#endif
+#include "modelRateInfo.h"
+#include "fm10Gen_types.h"
+#include "tRamp.h"
+#include "portableInline.h" //LIGO_INLINE
 
-/*DEFINITIONS*/
+/* Switching register bits */
+#define OPSWITCH_INPUT_ENABLE 0x4
+#define OPSWITCH_OFFSET_ENABLE 0x8
+#define OPSWITCH_LIMITER_ENABLE 0x1000000
+#define OPSWITCH_DECIMATE_ENABLE 0x2000000
+#define OPSWITCH_OUTPUT_ENABLE 0x4000000
+#define OPSWITCH_HOLD_ENABLE 0x8000000
 
-#define FILTERS 10 ///< Num filters per Filter Module
-#define TP_PER_FM   3 ///< Num TP per file modules
-#define MAX_COEFFS 41 ///< Max coeff per filter, including gain
-#define MAX_HISTRY 20 ///< Max num filter history elements
-#define MAX_SO_SECTIONS                                                        \
-    10 ///< Maximum number of second order sections supported
+#define OPSWITCH_LIMITER_RAMPING 0x20000000
+#define OPSWITCH_GAIN_RAMPING    0x10000000
 
-#ifdef FIR_FILTERS
-#define MAX_FIR_MODULES                                                        \
-    6 ///< Maximum total number of FIR filters allowed per system
-#include "fmFir.h"
-#define MAX_FIR_SO_SECTIONS                                                    \
-    ( FIR_TAPS / 4 ) ///< Maximum SOS supported for FIR filters
-#define MAX_FIR_COEFFS ( FIR_TAPS + 1 )
-// #ifdef SERVO2K
-#define FIR_POLYPHASE_SIZE 32 ///< The number of parallel polyphase filters
-// #endif
-
-// #ifdef SERVO4K
-// #define FIR_POLYPHASE_SIZE	64		///< The number of parallel
-// polyphase filters #endif
+
+
+#ifdef __cplusplus
+extern "C" {
 #endif
 
-/*masks*/
-#define COEF_MASK 0xFFFFFFFE
-#define HIST_MASK 0xFFFFFFFD
 
-/*****************************************************************************/
+//
+// Function Prototypes for c file implementation
+//
+int
+readCoefVme2( COEF* filtC, FILT_MOD* fmt, int modNum1, int filtNum,
+              int cycle, volatile VME_COEF* pRfmCoeff, int* changed );
+double
+filterModuleD2( FILT_MOD* pFilt, COEF* pC, int modNum, double filterInput, 
+                int fltrCtrlVal, int mask, double offset_in, double gain_in,
+                double ramp_in );
 
-/*STRUCTURES*/
+/* Convert opSwitchE bits into the 16-bit FiltCtrl2 Ctrl output format */
+unsigned int filtCtrlBitConvert( unsigned int v );
 
-///  Struct of operator input to each filter module
-typedef struct FM_OP_IN
-{
-    /// EPICS Switch Control Register - 28/32 bits used. \n
-    ///   ORGANIZATION OF THE SWITCH CONTROL REGISTER \n
-    ///   bit          0 = reset coefficients.  Momentary: When hit, rereads and
-    ///   loads
-    ///<                   new filter coefficients from file. \n
-    ///   bit          1 = master reset.  Momentary: When hit, clears out filt
-    ///   history \n bit          2 = input enable switch. Enables/Disables
-    ///   input into filter. \n bit          3 = offset switch. Enables/Disables
-    ///   offset calculation. \n even bits 4-22 = Filter stage On/Off readback.
-    ///   When on/off this will show
-    ///<                   that a filter has been requested to turn on/off. \n
-    ///   odd bits  5-23 = Filter output Switch On/Off readback. This will show
-    ///   that
-    ///<                   a filter has been engaged or shut off after a
-    ///<                   request. \n
-    ///   bit         24 = limiter switch. Enables/Disables limiter calculation.
-    ///   \n bit         25 = Decimation filter switch.  Enables/Disables the
-    ///   dec filter.\n bit         26 = Output enable switch. Enables/Disables
-    ///   output from filter. \n bit         27 = Hold Output switch.  if(!bit26
-    ///   && bit27) will hold outputs
-    ///                   at last value. if(!bit26 && !bit27) will zero outputs.
-    ///                   else, nothing.
-    UINT32 opSwitchE;
-    UINT32 opSwitchP; ///< Local Switch Control Register; 28/32 bits used.\n
-                      ///< Bits defined same as opSwitchE.
-    UINT32 rset; ///< reset switches
-    float  offset; ///< Signal DC Offset
-    float  outgain; ///<  Filter module gain
-    float  limiter; ///<  Used to limit the filter output to +/- limit val
-    int    rmpcmp[ FILTERS ]; ///< Ramp counts: \n
-                           ///< Ramps on a filter for type 2 output \n
-                           ///< Comparison limit: compare limit for type 3
-                           ///< output \n Not used for type 1 output filter
-    int timeout[ FILTERS ]; ///< used to timeout wait in type 3 output filter
-    int cnt[ FILTERS ]; ///< used to keep track of up and down cnt of rmpcmp;
-                        ///< should be initialized to zero
-    float  gain_ramp_time; ///< Gain change ramping time in seconds
-    UINT32 mask; ///< mask indicating which filters are controlled by FE
-    UINT32 control; ///< ten control bits to turn on or off filters
-    UINT32 swReq; ///< Switch settings requested by Guardian
-    UINT32 swMask; ///< Guardian switch setting mask
-} FM_OP_IN;
-
-/// Structure for holding filter module ramping information.
-typedef struct FM_GAIN_RAMP
-{
-    float prev_outgain; ///< Normally the same as outgain.
-                        ///< When gain is changed it holds old gain value
-    unsigned int gain_ramp_cycles; ///< Overall cycles to ramp gain
-    unsigned int ramp_cycles_left; ///< Cycles left to ramp gain
-} FM_GAIN_RAMP;
-
-/// Struct of data output for each filter module
-typedef struct FM_OP_DATA
-{
-    double filterInput; ///< Input to the filter bank module
-    double exciteInput; ///< an Excitation point/bypasses input switch
-    double inputTestpoint; ///< Filter Bank switched input plus excitation
-    double testpoint; ///< Filter Bank output;always enabled
-    double output; ///< Filter Bank Output;ENABLE/DISABLE/HOLD
-    double output16Hz; ///< 16hz Output; ENABLE/DISABLE/HOLD
-    UINT32 swStatus; ///< Status of fm switch settings
-} FM_OP_DATA;
-
-/// Struct of local memory filter module coefficients
-typedef struct FM_OP_COEF
+
+void checkFiltResetId( int bankNum, FILT_MOD* pL, volatile FILT_MOD* dspVme,
+                       COEF* pC, int totMod, volatile VME_COEF* pRfmCoeff,
+                       int id );
+
+int initVarsId( FILT_MOD* pL, volatile FILT_MOD* pV, COEF* pC, int totMod,
+                volatile VME_COEF* pRfmCoeff, int id );
+
+
+//
+// Inline functions provided by this header
+//
+
+
+
+/// @brief Perform IIR filtering sample by sample on doubles.
+/// Implements cascaded direct form II second order sections.
+///	@param[in] input New input sample
+///	@param[in] *coef Pointer to filter coefficient data with size 4*n + 1
+///(gain)
+///	@param[in] n Number of second order sections in filter definition
+///	@param[in,out] *history Pointer to filter history data of size 2*n
+///	@return Result of filter calculation
+LIGO_INLINE double
+iir_filter( double input, double* coef, int n, double* history )
 {
-    double filtCoeff[ FILTERS ]
-                    [ MAX_COEFFS ]; /* coefficients for filter string */
-    double filtHist[ FILTERS ]
-                   [ MAX_HISTRY ]; /* history buffer for filter string */
-    int filtSections[ FILTERS ]; /* number of sections in each filter */
-    /// FILTER TYPE DEFINITIONS \n
-    ///  There are two types of Filter Stage input on/off switch types: \n
-    ///  Type 1:  When turned off/on, filter input remains on and filter output
-    ///  switch
-    ///           turned off/on according to filter output type. \n
-    ///  Type 2:  When turned off/on, filter input and output turned off/on
-    ///  according
-    ///           to filter output type. \n
-    ///  There are three types of filter stage output on/off switch types. \n
-    ///  Type 1:  This will simply enable or disable the output of the filter
-    ///  block
-    ///           instantaniously. This type does not use the rmpcmp structure
-    ///           element. \n
-    ///  Type 2:  This will ramp in/out a filter output slowly according to the
-    ///  number
-    ///           set by the rmpcmp structure element when the servo block is
-    ///           enabled. \n
-    ///  Type 3:  This will compare filter output with the straight-through
-    ///  input. Once
-    ///           the difference comes within the number set in the rmpcmp
-    ///           structure
-    ///	   element, the filter output will turn on/off in the system.\n
-    ///  The system will recognize the total filter type by a numbered system of
-    ///  input/output types.  ie, they will be represented as type
-    ///  11,12,13,21,... etc.\n These will be determined in the coefficient
-    ///  file.
-    int sType[ FILTERS ]; //< indicates the filter switch in/out type
-    /* float decHist[1024];   history for the decimation filter */
-    double decHist[ 8 ]; ///< Decimation history buffer for 16Hz out filter
-    /// 0 - IIR; N - FIR, where 0 > N < MAX_FIR_MODULES \n
-    /// N-1 shows where coeffictients are. COEF.firFiltCoeff[N-1]
-    int filterType[ FILTERS ];
-    int biquad; ///< Set to one if the code needs to be in biquad form
-} FM_OP_COEF;
-
-/// Structure for filter module coefficients.
-typedef struct COEF
+
+    int     i;
+    double* coef_ptr;
+    double *hist1_ptr, *hist2_ptr;
+    double  output, new_hist, history1, history2;
+
+    coef_ptr = coef; /* coefficient pointer */
+
+    hist1_ptr = history; /* first history */
+    hist2_ptr = hist1_ptr + 1; /* next history */
+
+    output = input * ( *coef_ptr++ ); /* overall input scale factor */
+
+    for ( i = 0; i < n; i++ )
+    {
+
+        history1 = *hist1_ptr; /* history values */
+        history2 = *hist2_ptr;
+
+        output = output - history1 * ( *coef_ptr++ );
+        new_hist = output - history2 * ( *coef_ptr++ ); /* poles */
+
+        output = new_hist + history1 * ( *coef_ptr++ );
+        output = output + history2 * ( *coef_ptr++ ); /* zeros */
+
+        *hist2_ptr++ = *hist1_ptr;
+        *hist1_ptr++ = new_hist;
+        hist1_ptr++;
+        hist2_ptr++;
+    }
+
+    return ( output );
+}
+
+/* Biquad form IIR */
+/// @brief Perform IIR filtering sample by sample on doubles.
+/// Implements Biquad form calculations.
+///	@param[in] input New input sample
+///	@param[in] *coef Pointer to filter coefficient data with size 4*n + 1
+///(gain)
+///	@param[in] n Number of second order sections in filter definition
+///	@param[in,out] *history Pointer to filter history data of size 2*n
+///	@return Result of filter calculation
+LIGO_INLINE double
+iir_filter_biquad( double input, double* coef, int n, double* history )
 {
-    FM_OP_COEF coeffs[ MAX_MODULES ];
+
+    int     i;
+    double* coef_ptr;
+    double *hist1_ptr, *hist2_ptr;
+    double  output, new_w, new_u, w, u, a11, a12, c1, c2;
+
+    coef_ptr = coef; /* coefficient pointer */
+
+    hist1_ptr = history; /* first history */
+    hist2_ptr = hist1_ptr + 1; /* next history */
+
+    output = input * ( *coef_ptr++ ); /* overall input scale factor */
+
+    for ( i = 0; i < n; i++ )
+    {
+
+        w = *hist1_ptr;
+        u = *hist2_ptr;
+
+        a11 = *coef_ptr++;
+        a12 = *coef_ptr++;
+        c1 = *coef_ptr++;
+        c2 = *coef_ptr++;
+
+        new_w = output + a11 * w + a12 * u;
+        output = output + w * c1 + u * c2;
+        new_u = w + u;
+
+        *hist1_ptr++ = new_w;
+        *hist2_ptr++ = new_u;
+        hist1_ptr++;
+        hist2_ptr++;
+    }
+
+    // if((output < 1e-28) && (output > -1e-28)) output = 0.0;
+    return ( output );
+}
 
 #ifdef FIR_FILTERS
-#if defined( FIR_POLYPHASE_SIZE )
-    double firFiltCoeff[ MAX_FIR_MODULES ][ FILTERS ][ MAX_FIR_COEFFS ];
-    /* firHistory is huge, 5 megabytes. may need to get rid of FILTERS dimension
-     */
-    double firHistory[ MAX_FIR_MODULES ][ FILTERS ][ FIR_POLYPHASE_SIZE ]
-                     [ FIR_TAPS ];
-    double prevFirOutput[ MAX_FIR_MODULES ];
-#endif
+// *************************************************************************/
+///	@brief Perform FIR filter calculations.
+///	@param[in] input New input sample
+///	@param[in] *coef Pointer to filter coefficients
+///	@param[in] n Number of taps
+///	@param[in,out] *history Pointer to filter history data
+///	@return Result of FIR filter calculation
+LIGO_INLINE double
+fir_filter( double input, double* coef, int n, double* history )
+{
+    int     i;
+    double *hist_ptr, *hist1_ptr, *coef_ptr;
+    double  output;
+
+    hist_ptr = history;
+    hist1_ptr = hist_ptr; /* use for history update */
+    coef_ptr = coef + n - 1; /* point to last coef */
+
+    /* form output accumulation */
+    output = *hist_ptr++ * ( *coef_ptr-- );
+    for ( i = 2; i < n; i++ )
+    {
+        *hist1_ptr++ = *hist_ptr; /* update history array */
+        output += ( *hist_ptr++ ) * ( *coef_ptr-- );
+    }
+    output += input * ( *coef_ptr ); /* input tap */
+    *hist1_ptr = input; /* last history */
+
+    return ( output );
+}
 #endif
 
-} COEF;
 
-/// Structure for shared memory passing of FM coeff info for a single filter
-/// module.
-typedef struct VME_FM_OP_COEF
-{
-    double       filtCoeff[ FILTERS ][ MAX_COEFFS ]; ///< Filter coeffs.
-    char         filtName[ FILTERS ][ 32 ]; ///< Filter Name.
-    int          bankNum; ///< Filter module ID number.
-    int          filtSections[ FILTERS ]; ///< number of sections in each filter
-    int          sType[ FILTERS ]; ///< indicates the filter switch in/out type
-    int          ramp[ FILTERS ]; ///< Ramp time in seconds.
-    int          timout[ FILTERS ]; ///< Switching timeout value.
-    unsigned int crc; ///< Epics-calculated data checksum
-    int          filterType[ FILTERS ]; ///< 0 - IIR; N - FIR, where 0 > N <
-                               ///< MAX_FIR_MODULES
-    int biquad; ///< Set to 1 if this filter needs to use a biquad form
-                ///< calculations
-} VME_FM_OP_COEF;
-
-/// Structure definition for passing FM coeff data for all filter modules in
-/// shared memory.
-///< This uses an array of VME_FM_OP_COEF structures.
-typedef struct VME_COEF
+
+/************************************************************************/
+/************************************************************************/
+/// @brief Read in filter coeffs from shared memory on code initialization.
+///	@param[in,out] *filtC Pointer to coeffs in local memory
+///	@param[in] *fmt Pointer to filter data in local memory
+///	@param[in] bF	Start filter number
+///	@param[in] sF	End filter number
+///	@param[in] *pRfmCoeff Pointer to coeffs in shared memory
+LIGO_INLINE int
+readCoefVme(
+    COEF* filtC, FILT_MOD* fmt, int bF, int sF, volatile VME_COEF* pRfmCoeff )
 {
+    int ii, jj, kk;
 
 #ifdef FIR_FILTERS
-    double firFiltCoeff[ MAX_FIR_MODULES ][ FILTERS ][ MAX_FIR_COEFFS ];
+    int l;
+    for ( jj = 0; jj < MAX_FIR_MODULES; jj++ )
+        for ( kk = 0; kk < FILTERS; kk++ )
+            for ( l = 0; l < MAX_FIR_COEFFS; l++ )
+                filtC->firFiltCoeff[ jj ][ kk ][ l ] =
+                    pRfmCoeff->firFiltCoeff[ jj ][ kk ][ l ];
 #endif
+    for ( ii = bF; ii < sF; ii++ )
+    {
+        filtC->coeffs[ ii ].biquad = pRfmCoeff->vmeCoeffs[ ii ].biquad;
+        // if(filtC->coeffs[ii].biquad) printl("Found a BQF filter %d\n",ii);
+        for ( jj = 0; jj < FILTERS; jj++ )
+        {
+            if ( pRfmCoeff->vmeCoeffs[ ii ].filtSections[ jj ] )
+            {
+                filtC->coeffs[ ii ].filterType[ jj ] =
+                    pRfmCoeff->vmeCoeffs[ ii ].filterType[ jj ];
+#ifdef FIR_FILTERS
+                if ( filtC->coeffs[ ii ].filterType[ jj ] < 0 ||
+                     filtC->coeffs[ ii ].filterType[ jj ] > MAX_FIR_MODULES )
+                {
+                    filtC->coeffs[ ii ].filterType[ jj ] = 0;
+                    // printl("Corrupted data coming from Epics: module=%d
+                    // filter=%d filterType=%d\n",
+                    //	ii, jj, pRfmCoeff->vmeCoeffs[ii].filterType[jj]);
+                    return 1;
+                }
+#endif
+                filtC->coeffs[ ii ].filtSections[ jj ] =
+                    pRfmCoeff->vmeCoeffs[ ii ].filtSections[ jj ];
+                filtC->coeffs[ ii ].sType[ jj ] =
+                    pRfmCoeff->vmeCoeffs[ ii ].sType[ jj ];
+                fmt->inputs[ ii ].rmpcmp[ jj ] =
+                    pRfmCoeff->vmeCoeffs[ ii ].ramp[ jj ];
+                fmt->inputs[ ii ].timeout[ jj ] =
+                    pRfmCoeff->vmeCoeffs[ ii ].timout[ jj ];
+
+                if ( filtC->coeffs[ ii ].filterType[ jj ] == 0 )
+                {
+                    if ( filtC->coeffs[ ii ].filtSections[ jj ] > 10 )
+                    {
+                        // printl("Corrupted Epics data:  module=%d filter=%d
+                        // filterType=%d filtSections=%d\n", ii, jj,
+                        // pRfmCoeff->vmeCoeffs[ii].filterType[jj],
+                        // filtC->coeffs[ii].filtSections[jj]);
+                        return 1;
+                    }
+                    for ( kk = 0;
+                          kk < filtC->coeffs[ ii ].filtSections[ jj ] * 4 + 1;
+                          kk++ )
+                    {
+                        filtC->coeffs[ ii ].filtCoeff[ jj ][ kk ] =
+                            pRfmCoeff->vmeCoeffs[ ii ].filtCoeff[ jj ][ kk ];
+                    }
+                }
+            }
+        }
+    }
+    return 0;
+}
 
-    VME_FM_OP_COEF vmeCoeffs[ MAX_MODULES ];
 
-    /* Do not put anything at the end of this structure */
-    /* fmReadCoeff code gets compiled with MAX_MODULES == 0 */
-} VME_COEF;
 
-/// Struct of filter names for use in epics screens
-typedef struct FILT_NAME
+///	@brief Calls checkFiltResetId with dummy sys id of 0
+///	@param[in] bankNum	Filter module ID number
+///	@param[in,out] *pL	Pointer to filter module data in local memory.
+///	@param[in] *dspVme	Pointer to filter module data in shared memory.
+///	@param[in,out] *pC	Pointer to filter coefs in local memory.
+///	@param[in] totMod	Total number of filter modules
+///	@param[in] *pRfmCoeff	Pointer to filter coefs in shared memory.
+LIGO_INLINE void
+checkFiltReset( int                bankNum,
+                FILT_MOD*          pL,
+                volatile FILT_MOD* dspVme,
+                COEF*              pC,
+                int                totMod,
+                volatile VME_COEF* pRfmCoeff )
 {
-    char filtName[ FILTERS ]
-                 [ 32 ]; /* holds filter names for each filter bank */
-} FILT_NAME;
+    checkFiltResetId( bankNum, pL, dspVme, pC, totMod, pRfmCoeff, 0 );
+}
 
-/// Filter modules all in one structure
-typedef struct FILT_MOD
+
+///	@brief Calls initVarsId with dummy sys id of 0
+///	@param[in,out] *pL	Pointer to filter module data in local memory
+///	@param[in] *pV		Pointer to filter module data in shared memory
+///	@param[in,out] *pC	Pointer to filter coeffs in local memory
+///	@param[in] totMod	Total number of filter modules
+///	@param[in] *pRfmCoeff	Pointer to filter coeffs in shared memory
+LIGO_INLINE int
+initVars( FILT_MOD*          pL,
+          volatile FILT_MOD* pV,
+          COEF*              pC,
+          int                totMod,
+          volatile VME_COEF* pRfmCoeff )
 {
+    return initVarsId( pL, pV, pC, totMod, pRfmCoeff, 0 );
+}
+
+/* This module added to hanle all input, calculations and outputs as doubles.
+   This module also incorporates the input module, done separately above for
+   older systems. */
+
 
-    FM_OP_IN   inputs[ MAX_MODULES ]; ///< operator inputs to each filter module
-    FM_OP_DATA data[ MAX_MODULES ]; ///< data output for each filter module
-    int        cycle;
-    int coef_load_error; ///< Error flag inidicating problems loading coeffs by
-                         ///< a front-end
 
-} FILT_MOD;
 
-#if ( defined( __i386__ ) || defined( __amd64__ ) ) &&                         \
-    !defined( NO_FM10GEN_C_CODE )
-#include "../drv/crc.c"
-#include "drv/fm10Gen.c"
+/// 	@brief This function is called by user apps using standard IIR/FIR
+/// filters..
+///< This function in turn calls filterModuleD2 to actually perform the calcs,
+///< with dummy vars added.
+///	@param[in,out] *pFilt Filter Module Data
+///	@param[in] *pC Filter module coefficients
+///	@param[in] modNum Filter module ID number
+///	@param[in] filterInput Input data sample
+///	@param[in] fltrCtrlVal Filter control value
+///	@param[in] mask Control mask
+///	@return Output of IIR/FIR filter calculations.
+LIGO_INLINE double
+filterModuleD( FILT_MOD* pFilt, /* Filter module data  */
+               COEF*     pC, /* Filter coefficients */
+               int       modNum, /* Filter module number */
+               double    filterInput, /* Input data sample (output from funtcion
+                                         inputModule()) */
+               int fltrCtrlVal, /* Filter control value */
+               int mask ) /* Mask of bits to act upon */
+{
+    /* Limit control to the 10 bits */
+    return filterModuleD2( pFilt,
+                           pC,
+                           modNum,
+                           filterInput,
+                           fltrCtrlVal & 0x3ff,
+                           mask & 0x3ff,
+                           0.,
+                           0.,
+                           0. );
+}
+
+#ifdef __cplusplus
+}
 #endif
 
-#endif //FM10GEN_H
+
+#endif //LIGO_FM10GEN_H
diff --git a/src/include/fm10Gen_types.h b/src/include/fm10Gen_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..26429fc2e703ff9f9ca983e86ba614366487d3eb
--- /dev/null
+++ b/src/include/fm10Gen_types.h
@@ -0,0 +1,239 @@
+#ifndef FM10GEN_TYPES_H
+#define FM10GEN_TYPES_H
+
+///	@file fm10Gen_types.h
+///	@brief This file contains the basic defines and structures required to
+///<		process IIR/FIR filter calculations and pass filter module data.
+
+/*****************************************************************************/
+
+// For the EPICS process fmReadCoeff.c wants to define MAX_MODULES
+// as 0, while the model needs to use the actual number of modules.
+// This var might be a candidate for macro definition "-D", or needs 
+// a better solution that supports both cases better.
+#ifndef MAX_MODULES
+#include FE_HEADER //MAX_MODULES
+//TODO:MAX_MODULES Should probably be defined in another generated header, because we 
+//have a circular dependency here
+#endif
+
+#ifndef UINT32
+#define UINT32 unsigned int
+#endif
+
+/*DEFINITIONS*/
+
+#define FILTERS 10 ///< Num filters per Filter Module
+#define TP_PER_FM   3 ///< Num TP per file modules
+#define MAX_COEFFS 41 ///< Max coeff per filter, including gain
+#define MAX_HISTRY 20 ///< Max num filter history elements
+#define MAX_SO_SECTIONS                                                        \
+    10 ///< Maximum number of second order sections supported
+
+#ifdef FIR_FILTERS
+#define MAX_FIR_MODULES                                                        \
+    6 ///< Maximum total number of FIR filters allowed per system
+#include "fmFir.h"
+#define MAX_FIR_SO_SECTIONS                                                    \
+    ( FIR_TAPS / 4 ) ///< Maximum SOS supported for FIR filters
+#define MAX_FIR_COEFFS ( FIR_TAPS + 1 )
+// #ifdef SERVO2K
+#define FIR_POLYPHASE_SIZE 32 ///< The number of parallel polyphase filters
+// #endif
+
+// #ifdef SERVO4K
+// #define FIR_POLYPHASE_SIZE	64		///< The number of parallel
+// polyphase filters #endif
+#endif
+
+/*masks*/
+#define COEF_MASK 0xFFFFFFFE
+#define HIST_MASK 0xFFFFFFFD
+
+/*****************************************************************************/
+
+/*STRUCTURES*/
+
+///  Struct of operator input to each filter module
+typedef struct FM_OP_IN
+{
+    /// EPICS Switch Control Register - 28/32 bits used. \n
+    ///   ORGANIZATION OF THE SWITCH CONTROL REGISTER \n
+    ///   bit          0 = reset coefficients.  Momentary: When hit, rereads and
+    ///   loads
+    ///<                   new filter coefficients from file. \n
+    ///   bit          1 = master reset.  Momentary: When hit, clears out filt
+    ///   history \n bit          2 = input enable switch. Enables/Disables
+    ///   input into filter. \n bit          3 = offset switch. Enables/Disables
+    ///   offset calculation. \n even bits 4-22 = Filter stage On/Off readback.
+    ///   When on/off this will show
+    ///<                   that a filter has been requested to turn on/off. \n
+    ///   odd bits  5-23 = Filter output Switch On/Off readback. This will show
+    ///   that
+    ///<                   a filter has been engaged or shut off after a
+    ///<                   request. \n
+    ///   bit         24 = limiter switch. Enables/Disables limiter calculation.
+    ///   \n bit         25 = Decimation filter switch.  Enables/Disables the
+    ///   dec filter.\n bit         26 = Output enable switch. Enables/Disables
+    ///   output from filter. \n bit         27 = Hold Output switch.  if(!bit26
+    ///   && bit27) will hold outputs
+    ///                   at last value. if(!bit26 && !bit27) will zero outputs.
+    ///                   else, nothing.
+    UINT32 opSwitchE;
+    UINT32 opSwitchP; ///< Local Switch Control Register; 28/32 bits used.\n
+                      ///< Bits defined same as opSwitchE.
+    UINT32 rset; ///< reset switches
+    float  offset; ///< Signal DC Offset
+    float  outgain; ///<  Filter module gain
+    float  limiter; ///<  Used to limit the filter output to +/- limit val
+    int    rmpcmp[ FILTERS ]; ///< Ramp counts: \n
+                           ///< Ramps on a filter for type 2 output \n
+                           ///< Comparison limit: compare limit for type 3
+                           ///< output \n Not used for type 1 output filter
+    int timeout[ FILTERS ]; ///< used to timeout wait in type 3 output filter
+    int cnt[ FILTERS ]; ///< used to keep track of up and down cnt of rmpcmp;
+                        ///< should be initialized to zero
+    float  gain_ramp_time; ///< Gain change ramping time in seconds
+    UINT32 mask; ///< mask indicating which filters are controlled by FE
+    UINT32 control; ///< ten control bits to turn on or off filters
+    UINT32 swReq; ///< Switch settings requested by Guardian
+    UINT32 swMask; ///< Guardian switch setting mask
+} FM_OP_IN;
+
+/// Structure for holding filter module ramping information.
+typedef struct FM_GAIN_RAMP
+{
+    float prev_outgain; ///< Normally the same as outgain.
+                        ///< When gain is changed it holds old gain value
+    unsigned int gain_ramp_cycles; ///< Overall cycles to ramp gain
+    unsigned int ramp_cycles_left; ///< Cycles left to ramp gain
+} FM_GAIN_RAMP;
+
+/// Struct of data output for each filter module
+typedef struct FM_OP_DATA
+{
+    double filterInput; ///< Input to the filter bank module
+    double exciteInput; ///< an Excitation point/bypasses input switch
+    double inputTestpoint; ///< Filter Bank switched input plus excitation
+    double testpoint; ///< Filter Bank output;always enabled
+    double output; ///< Filter Bank Output;ENABLE/DISABLE/HOLD
+    double output16Hz; ///< 16hz Output; ENABLE/DISABLE/HOLD
+    UINT32 swStatus; ///< Status of fm switch settings
+} FM_OP_DATA;
+
+/// Struct of local memory filter module coefficients
+typedef struct FM_OP_COEF
+{
+    double filtCoeff[ FILTERS ]
+                    [ MAX_COEFFS ]; /* coefficients for filter string */
+    double filtHist[ FILTERS ]
+                   [ MAX_HISTRY ]; /* history buffer for filter string */
+    int filtSections[ FILTERS ]; /* number of sections in each filter */
+    /// FILTER TYPE DEFINITIONS \n
+    ///  There are two types of Filter Stage input on/off switch types: \n
+    ///  Type 1:  When turned off/on, filter input remains on and filter output
+    ///  switch
+    ///           turned off/on according to filter output type. \n
+    ///  Type 2:  When turned off/on, filter input and output turned off/on
+    ///  according
+    ///           to filter output type. \n
+    ///  There are three types of filter stage output on/off switch types. \n
+    ///  Type 1:  This will simply enable or disable the output of the filter
+    ///  block
+    ///           instantaniously. This type does not use the rmpcmp structure
+    ///           element. \n
+    ///  Type 2:  This will ramp in/out a filter output slowly according to the
+    ///  number
+    ///           set by the rmpcmp structure element when the servo block is
+    ///           enabled. \n
+    ///  Type 3:  This will compare filter output with the straight-through
+    ///  input. Once
+    ///           the difference comes within the number set in the rmpcmp
+    ///           structure
+    ///	   element, the filter output will turn on/off in the system.\n
+    ///  The system will recognize the total filter type by a numbered system of
+    ///  input/output types.  ie, they will be represented as type
+    ///  11,12,13,21,... etc.\n These will be determined in the coefficient
+    ///  file.
+    int sType[ FILTERS ]; //< indicates the filter switch in/out type
+    /* float decHist[1024];   history for the decimation filter */
+    double decHist[ 8 ]; ///< Decimation history buffer for 16Hz out filter
+    /// 0 - IIR; N - FIR, where 0 > N < MAX_FIR_MODULES \n
+    /// N-1 shows where coeffictients are. COEF.firFiltCoeff[N-1]
+    int filterType[ FILTERS ];
+    int biquad; ///< Set to one if the code needs to be in biquad form
+} FM_OP_COEF;
+
+/// Structure for filter module coefficients.
+typedef struct COEF
+{
+    FM_OP_COEF coeffs[ MAX_MODULES ];
+
+#ifdef FIR_FILTERS
+#if defined( FIR_POLYPHASE_SIZE )
+    double firFiltCoeff[ MAX_FIR_MODULES ][ FILTERS ][ MAX_FIR_COEFFS ];
+    /* firHistory is huge, 5 megabytes. may need to get rid of FILTERS dimension
+     */
+    double firHistory[ MAX_FIR_MODULES ][ FILTERS ][ FIR_POLYPHASE_SIZE ]
+                     [ FIR_TAPS ];
+    double prevFirOutput[ MAX_FIR_MODULES ];
+#endif
+#endif
+
+} COEF;
+
+/// Structure for shared memory passing of FM coeff info for a single filter
+/// module.
+typedef struct VME_FM_OP_COEF
+{
+    double       filtCoeff[ FILTERS ][ MAX_COEFFS ]; ///< Filter coeffs.
+    char         filtName[ FILTERS ][ 32 ]; ///< Filter Name.
+    int          bankNum; ///< Filter module ID number.
+    int          filtSections[ FILTERS ]; ///< number of sections in each filter
+    int          sType[ FILTERS ]; ///< indicates the filter switch in/out type
+    int          ramp[ FILTERS ]; ///< Ramp time in seconds.
+    int          timout[ FILTERS ]; ///< Switching timeout value.
+    unsigned int crc; ///< Epics-calculated data checksum
+    int          filterType[ FILTERS ]; ///< 0 - IIR; N - FIR, where 0 > N <
+                               ///< MAX_FIR_MODULES
+    int biquad; ///< Set to 1 if this filter needs to use a biquad form
+                ///< calculations
+} VME_FM_OP_COEF;
+
+/// Structure definition for passing FM coeff data for all filter modules in
+/// shared memory.
+///< This uses an array of VME_FM_OP_COEF structures.
+typedef struct VME_COEF
+{
+
+#ifdef FIR_FILTERS
+    double firFiltCoeff[ MAX_FIR_MODULES ][ FILTERS ][ MAX_FIR_COEFFS ];
+#endif
+
+    VME_FM_OP_COEF vmeCoeffs[ MAX_MODULES ];
+
+    /* Do not put anything at the end of this structure */
+    /* fmReadCoeff code gets compiled with MAX_MODULES == 0 */
+} VME_COEF;
+
+/// Struct of filter names for use in epics screens
+typedef struct FILT_NAME
+{
+    char filtName[ FILTERS ]
+                 [ 32 ]; /* holds filter names for each filter bank */
+} FILT_NAME;
+
+/// Filter modules all in one structure
+typedef struct FILT_MOD
+{
+
+    FM_OP_IN   inputs[ MAX_MODULES ]; ///< operator inputs to each filter module
+    FM_OP_DATA data[ MAX_MODULES ]; ///< data output for each filter module
+    int        cycle;
+    int coef_load_error; ///< Error flag inidicating problems loading coeffs by
+                         ///< a front-end
+
+} FILT_MOD;
+
+
+#endif //FM10GEN_TYPES_H
diff --git a/src/include/fmReadCoeff.h b/src/include/fmReadCoeff.h
index faa2c5372db886fe368457e2731fb45e73ffa848..0378f9eebffcaffd7a1f5919e5ebe3a656794642 100644
--- a/src/include/fmReadCoeff.h
+++ b/src/include/fmReadCoeff.h
@@ -56,10 +56,6 @@ typedef struct fmReadCoeff
 #define TF_THRESHOLDS_NOT_FOUND 2 /* MA */
 #define TF_PARSE_ERROR 3 /* MA */
 
-int   fmReadCoeffFile( fmReadCoeff*, int, unsigned long );
-char* fmReadErrMsg( );
-char* fmReadShortErrMsg( );
-
 #undef CVL
 
 /* Error codes */
@@ -79,4 +75,20 @@ char* fmReadShortErrMsg( );
 #define FIR_LOAD 4
 #define FIR_TMP 5
 
+//
+// Function declarations for definitions in fmReadCoeff.c 
+//
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int   fmReadCoeffFile( fmReadCoeff*, int, unsigned long );
+char* fmReadErrMsg( );
+char* fmReadShortErrMsg( );
+
+#ifdef __cplusplus
+}
+#endif
+
+
 #endif //FM_READ_COEFF_H
diff --git a/src/include/isnan.h b/src/include/isnan.h
index e2de7285eb8b7cc66ff05a8dae8d5c4f71f146ab..1a9e55dccc6a88ab1846535cf0e5e26cd530c210 100644
--- a/src/include/isnan.h
+++ b/src/include/isnan.h
@@ -1,6 +1,8 @@
 #ifndef ISNAN_H
 #define ISNAN_H 
 
+#include "util/fixed_width_types.h"
+
 /* A union which permits us to convert between a long double and
    three 32 bit ints.  */
 
@@ -9,8 +11,8 @@ typedef union
     long double value;
     struct
     {
-        u_int32_t    lsw;
-        u_int32_t    msw;
+        uint32_t    lsw;
+        uint32_t    msw;
         int          sign_exponent : 16;
         unsigned int empty1 : 16;
         unsigned int empty0 : 32;
@@ -114,8 +116,8 @@ isnan( long double x )
        extended format has the normally implicit 1 explicit
        present.  Sigh!  */
     lx |= hx & 0x7fffffff;
-    se |= ( u_int32_t )( lx | ( -lx ) ) >> 31;
+    se |= ( uint32_t )( lx | ( -lx ) ) >> 31;
     se = 0xfffe - se;
-    return (int)( ( u_int32_t )( se ) ) >> 16;
+    return (int)( ( uint32_t )( se ) ) >> 16;
 }
 #endif //ISNAN_H
diff --git a/src/include/modelRateInfo.h b/src/include/modelRateInfo.h
new file mode 100644
index 0000000000000000000000000000000000000000..c2f808f019dfa454925521e6a281842b4537e9ba
--- /dev/null
+++ b/src/include/modelRateInfo.h
@@ -0,0 +1,37 @@
+#ifndef LIGO_MODEL_RATE_INFO_H
+#define LIGO_MODEL_RATE_INFO_H
+
+
+//TODO:CYCLE_PER_SECOND and FE_RATE seem to refer to the same quantity,
+//consider consolidating.
+//TODO: FE_RATE is also defined in the model generated code
+#if defined( SERVO1024K )
+#define CYCLE_PER_SECOND ( 1024 * 1024 ) //From fe.h
+#define FE_RATE 1048576 //From fmGen10.h
+#elif defined( SERVO512K )
+#define CYCLE_PER_SECOND ( 512 * 1024 )
+#define FE_RATE 524288
+#elif defined( SERVO256K )
+#define CYCLE_PER_SECOND ( 256 * 1024 )
+#define FE_RATE 262144
+#elif defined( SERVO128K )
+#define CYCLE_PER_SECOND ( 128 * 1024 )
+#define FE_RATE 131072
+#elif defined( SERVO64K )
+#define CYCLE_PER_SECOND ( 64 * 1024 )
+#define FE_RATE 65536
+#elif defined( SERVO32K )
+#define CYCLE_PER_SECOND ( 32 * 1024 )
+#define FE_RATE 32768
+#elif defined( SERVO16K )
+#define CYCLE_PER_SECOND ( 16 * 1024 )
+#define FE_RATE 16384
+#elif defined( SERVO4K )
+#define CYCLE_PER_SECOND ( 4 * 1024 )
+#define FE_RATE 4096
+#elif defined( SERVO2K )
+#define CYCLE_PER_SECOND ( 2 * 1024 )
+#define FE_RATE 2048
+#endif
+
+#endif
diff --git a/src/include/param.h b/src/include/param.h
index 4a996eebc361cb5e3dab343ca5a2ce62df39ee62..496083a544929ab2fa4712f9efbc1cf9dbc96af1 100644
--- a/src/include/param.h
+++ b/src/include/param.h
@@ -1,6 +1,8 @@
 #ifndef PARAM_H
 #define PARAM_H
 
+#include "daqmap.h" //DAQ_INFO_BLOCK, GDS_INFO_BLOCK
+
 typedef struct CHAN_PARAM
 {
     int   dcuid;
@@ -18,6 +20,10 @@ typedef struct CHAN_PARAM
     char  system[ 40 ];
 } CHAN_PARAM;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int parseConfigFile( char*,
                      unsigned long*,
                      int ( *callback )( char*, struct CHAN_PARAM*, void* ),
@@ -27,4 +33,9 @@ int parseConfigFile( char*,
 
 int loadDaqConfigFile( DAQ_INFO_BLOCK*, GDS_INFO_BLOCK*, char*, char*, char* );
 
+#ifdef __cplusplus
+}
 #endif
+
+
+#endif //PARAM_H
diff --git a/src/include/portableInline.h b/src/include/portableInline.h
new file mode 100644
index 0000000000000000000000000000000000000000..52b6048cf744f17d9bdb4b240ce2b43e5ce1585c
--- /dev/null
+++ b/src/include/portableInline.h
@@ -0,0 +1,13 @@
+#ifndef LIGO_PORTABLE_INLINE_H
+#define LIGO_PORTABLE_INLINE_H
+
+#ifndef LIGO_INLINE
+# if (defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__)) || __KERNEL__
+#  define LIGO_INLINE extern inline
+# else
+#  define LIGO_INLINE inline 
+# endif
+#endif //INC_FROM_SOURCE
+
+
+#endif //LIGO_PORTABLE_INLINE_H
diff --git a/src/include/qnorm.h b/src/include/qnorm.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3700d1ce30d699cd9ec38e7d076b62b7f698f44
--- /dev/null
+++ b/src/include/qnorm.h
@@ -0,0 +1,253 @@
+/* -------- This header applies to the qnorm function ------------
+ *  Mathlib : A C Library of Special Functions
+ *  Copyright (C) 2000--2020 The R Core Team
+ *  Copyright (C) 1998       Ross Ihaka
+ *  based on AS 111 (C) 1977 Royal Statistical Society
+ *  and   on AS 241 (C) 1988 Royal Statistical Society
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, a copy is available at
+ *  https://www.R-project.org/Licenses/
+ *
+ *  SYNOPSIS
+ *
+ *      double qnorm5(double p, double mu, double sigma,
+ *                    int lower_tail, int log_p)
+ *            {qnorm (..) is synonymous and preferred inside R}
+ *
+ *  DESCRIPTION
+ *
+ *      Compute the quantile function for the normal distribution.
+ *
+ *      For small to moderate probabilities, algorithm referenced
+ *      below is used to obtain an initial approximation which is
+ *      polished with a final Newton step.
+ *
+ *      For very large arguments, an algorithm of Wichura is used.
+ *
+ *  REFERENCE
+ *
+ *      Beasley, J. D. and S. G. Springer (1977).
+ *      Algorithm AS 111: The percentage points of the normal distribution,
+ *      Applied Statistics, 26, 118-121.
+ *
+ *      Wichura, M.J. (1988).
+ *      Algorithm AS 241: The Percentage Points of the Normal Distribution.
+ *      Applied Statistics, 37, 477-484.
+ *
+ * -------------- End qnorm function header -----------------------------
+ *
+ * -------- This header applies to the fastlog2 and fastlog functions ---
+ * =====================================================================*
+ *                   Copyright (C) 2011 Paul Mineiro                   *
+ * All rights reserved.                                                *
+ *                                                                     *
+ * Redistribution and use in source and binary forms, with             *
+ * or without modification, are permitted provided that the            *
+ * following conditions are met:                                       *
+ *                                                                     *
+ *     * Redistributions of source code must retain the                *
+ *     above copyright notice, this list of conditions and             *
+ *     the following disclaimer.                                       *
+ *                                                                     *
+ *     * Redistributions in binary form must reproduce the             *
+ *     above copyright notice, this list of conditions and             *
+ *     the following disclaimer in the documentation and/or            *
+ *     other materials provided with the distribution.                 *
+ *                                                                     *
+ *     * Neither the name of Paul Mineiro nor the names                *
+ *     of other contributors may be used to endorse or promote         *
+ *     products derived from this software without specific            *
+ *     prior written permission.                                       *
+ *                                                                     *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND              *
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,         *
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES               *
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE             *
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER               *
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,                 *
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES            *
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE           *
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR                *
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF          *
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           *
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY              *
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE             *
+ * POSSIBILITY OF SUCH DAMAGE.                                         *
+ *                                                                     *
+ * Contact: Paul Mineiro <paul@mineiro.com>                            *
+ * =====================================================================
+ *
+ * ---------- End of fastlog2 and fastlog functions --------------------
+ *
+ */
+
+/**
+ * LIGO Header
+ *
+ * This code was taken from : https://svn.r-project.org/R/trunk/src/nmath/qnorm.c
+ * LIGO versions of math functions were swapped in. (sqrt -> lsqrt, etc)
+ *
+ * The fastlog2 and fastlog functions where taken from :
+ * https://github.com/romeric/fastapprox/blob/master/fastapprox/src/fastlog.h
+ *
+ */
+
+#ifndef LIGO_QNORM_H
+#define LIGO_QNORM_H
+
+#include "inlineMath.h"
+
+
+#define ML_POSINF   (1.0 / 0.0)
+#define ML_NEGINF   ((-1.0) / 0.0)
+#define ML_NAN      (0.0 / 0.0)
+
+/* Use 0.5 - p + 0.5 to perhaps gain 1 bit of accuracy */
+#define R_D_Lval(p) (lower_tail ? (p) : (0.5 - (p) + 0.5))  /*  p  */
+#define R_D_Cval(p) (lower_tail ? (0.5 - (p) + 0.5) : (p))  /*  1 - p */
+
+
+#define R_DT_qIv(p) (log_p ? (lower_tail ? taylor_9th_exp(p) : - expm1(p)) \
+                   : R_D_Lval(p))
+
+#define R_DT_CIv(p) (log_p ? (lower_tail ? -expm1(p) : taylor_9th_exp(p)) \
+                   : R_D_Cval(p))
+
+// This is a simplified 9th order Taylor polynomial for e^x
+//
+// This has a maximum percent error of 0.000011% over the (0,1)
+// range, which is where we use it here
+//
+static inline double taylor_9th_exp(double x)
+{
+    return (362880+x*(362880+x*(181440+x*(60480+x*
+               (15120+x*(3024+x*(504+x*(72+x*(9+x)))))))))*2.75573192e-6;
+}
+
+static inline double expm1( double x)
+{
+    return taylor_9th_exp(x) - 1.0;
+}
+
+
+static inline float
+fastlog2 (float x)
+{
+  union { float f; uint32_t i; } vx = { x };
+  union { uint32_t i; float f; } mx = { (vx.i & 0x007FFFFF) | 0x3f000000 };
+  float y = vx.i;
+  y *= 1.1920928955078125e-7f;
+
+  return y - 124.22551499f
+           - 1.498030302f * mx.f
+           - 1.72587999f / (0.3520887068f + mx.f);
+}
+
+// The maximum error over the (0,1] range is a percent error of
+// 0.000773% with the use of this acceleration 
+static inline float
+fastlog (float x)
+{
+  return 0.69314718f * fastlog2 (x);
+}
+
+
+static inline double qnorm5_s(double p, int lower_tail, int log_p)
+{
+    double p_, q, r, val;
+
+    p_ = R_DT_qIv(p);/* real lower_tail prob. p */
+    q = p_ - 0.5;
+
+    /*-- use AS 241 --- */
+    /* double ppnd16_(double *p, long *ifault)*/
+    /*      ALGORITHM AS241  APPL. STATIST. (1988) VOL. 37, NO. 3
+
+            Produces the normal deviate Z corresponding to a given lower
+            tail area of P; Z is accurate to about 1 part in 10**16.
+
+            (original fortran code used PARAMETER(..) for the coefficients
+             and provided hash codes for checking them...)
+    */
+    if (lfabs(q) <= .425) {/* |p~ - 0.5| <= .425  <==> 0.075 <= p~ <= 0.925 */
+        r = .180625 - q * q; // = .425^2 - q^2  >= 0
+        val =
+            q * (((((((r * 2509.0809287301226727 +
+                       33430.575583588128105) * r + 67265.770927008700853) * r +
+                     45921.953931549871457) * r + 13731.693765509461125) * r +
+                   1971.5909503065514427) * r + 133.14166789178437745) * r +
+                 3.387132872796366608)
+            / (((((((r * 5226.495278852854561 +
+                     28729.085735721942674) * r + 39307.89580009271061) * r +
+                   21213.794301586595867) * r + 5394.1960214247511077) * r +
+                 687.1870074920579083) * r + 42.313330701600911252) * r + 1.);
+    }
+    else { /* closer than 0.075 from {0,1} boundary :
+            *  r := log(p~);  p~ = min(p, 1-p) < 0.075 :  */
+        if(log_p && ((lower_tail && q <= 0) || (!lower_tail && q > 0))) {
+            p_ = R_DT_qIv(p);/* real lower_tail prob. p */
+            r = p;
+        } else {
+            r = fastlog( (q > 0) ? R_DT_CIv(p) /* 1-p */ : p_ /* = R_DT_Iv(p) ^=  p */);
+        }
+
+        // r = sqrt( - log(min(p,1-p)) )  <==>  min(p, 1-p) = exp( - r^2 ) :
+        r = lsqrt(-r);
+        if (r <= 5.) { /* <==> min(p,1-p) >= exp(-25) ~= 1.3888e-11 */
+            r += -1.6;
+            val = (((((((r * 7.7454501427834140764e-4 +
+                           .0227238449892691845833) * r + .24178072517745061177) *
+                         r + 1.27045825245236838258) * r +
+                        3.64784832476320460504) * r + 5.7694972214606914055) *
+                      r + 4.6303378461565452959) * r +
+                     1.42343711074968357734)
+                    / (((((((r *
+                             1.05075007164441684324e-9 + 5.475938084995344946e-4) *
+                            r + .0151986665636164571966) * r +
+                           .14810397642748007459) * r + .68976733498510000455) *
+                         r + 1.6763848301838038494) * r +
+                        2.05319162663775882187) * r + 1.);
+        }
+        else if(r >= 816) { // p is *extremly* close to 0 or 1 - only possibly when log_p =TRUE
+            // Using the asymptotical formula -- is *not* optimal but uniformly better than branch below
+            val = r * M_SQRT2;
+        }
+            else { // p is very close to  0 or 1:  r > 5 <==> min(p,1-p) < exp(-25) = 1.3888..e-11
+            // Wichura, p.478: minimax rational approx R_3(t) is for 5 <= t <= 27  (t :== r)
+            r += -5.;
+            val = (((((((r * 2.01033439929228813265e-7 +
+                       2.71155556874348757815e-5) * r +
+                      .0012426609473880784386) * r + .026532189526576123093) *
+                    r + .29656057182850489123) * r +
+                   1.7848265399172913358) * r + 5.4637849111641143699) *
+                 r + 6.6579046435011037772)
+                / (((((((r *
+                         2.04426310338993978564e-15 + 1.4215117583164458887e-7)*
+                        r + 1.8463183175100546818e-5) * r +
+                       7.868691311456132591e-4) * r + .0148753612908506148525)
+                     * r + .13692988092273580531) * r +
+                    .59983220655588793769) * r + 1.);
+        }
+
+        if(q < 0.0)
+            val = -val;
+    }
+    return val;
+}
+
+
+
+
+
+#endif //LIGO_QNORM_H
diff --git a/src/include/sdf_file_loaded.h b/src/include/sdf_file_loaded.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f3a09025e37b1e7eda8a2498ede52b3d582b805
--- /dev/null
+++ b/src/include/sdf_file_loaded.h
@@ -0,0 +1,20 @@
+#ifndef DAQD_TRUNK_SDF_FILE_LOADED_H
+#define DAQD_TRUNK_SDF_FILE_LOADED_H
+
+// set or clear and sdf file loaded flag
+// this flag is used to trigger BURT_RESTORE
+// when the safe.snap or other sdf file is completely loaded
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int  get_sdf_file_loaded( void );
+extern void set_sdf_file_loaded( int );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // DAQD_TRUNK_SDF_FILE_LOADED_H
diff --git a/src/include/tRamp.h b/src/include/tRamp.h
index 95247ec7ad3792ac0ddf7e2bfd76d563cb4ddfcb..a1ba5bca3f57a9773f7d8f214a3e972d9d6bd235 100644
--- a/src/include/tRamp.h
+++ b/src/include/tRamp.h
@@ -1,6 +1,9 @@
 #ifndef TRAMP_H
 #define TRAMP_H
 
+#include "util/inlineMath.h"
+#include "portableInline.h"
+
 /*******************************************************/
 /* Header file for the Ramping over Time functions (tRamp) */
 
@@ -23,6 +26,179 @@ typedef struct RampParamState
 
 } RampParamState;
 
-#include <drv/tRamp.c>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*******************************************************/
+/* Start Ramping functions     */
+LIGO_INLINE double
+RampParamGetVal( RampParamState* state )
+{
+    return state->val;
+}
+
+LIGO_INLINE int
+RampParamGetIsRamping( RampParamState* state )
+{
+    return state->isRamping;
+}
+
+LIGO_INLINE void
+RampParamInit( RampParamState* state, double xInit, const int fe_rate )
+{
+    state->isRamping = 0;
+    state->val = xInit;
+    state->dxPrev = 0.0;
+
+    state->req = xInit;
+    state->dxMax = 0.0;
+    state->ddxMax = 0.0;
+
+    state->softRatio = 4.0;
+    state->softVel = 1.36; // how to compute this from softRatio?
+    state->minAccCycles = 0.05 * fe_rate;
+}
+
+LIGO_INLINE void
+RampParamLoad( RampParamState* state,
+               double          req,
+               double          tRamp,
+               const int       fe_rate )
+{
+    double inv_nRamp; // 1 / number of ramp cycles
+
+    if ( tRamp <= 0.0 )
+    {
+        // no ramp
+        state->isRamping = 0;
+        state->val = req;
+        state->dxPrev = 0.0;
+
+        state->req = req;
+        state->dxMax = 0.0;
+        state->ddxMax = 0.0;
+    }
+    else if ( state->isRamping || req != state->val )
+    {
+        // setup ramp parameters
+        inv_nRamp = 1.0 / ( fe_rate * tRamp );
+        state->req = req;
+        state->dxMax = state->softVel * lfabs( req - state->val ) * inv_nRamp;
+        state->ddxMax = state->softRatio * state->dxMax * inv_nRamp;
+
+        // if currently ramping, allow high accelleration
+        if ( state->isRamping )
+            state->ddxMax =
+                lfabs( state->dxMax + state->dxPrev ) / state->minAccCycles;
+
+        // start the ramp
+        state->isRamping = 1;
+    }
+}
+
+LIGO_INLINE double
+RampParamUpdate( RampParamState* state )
+{
+    double dxReq; // distance to requested value
+    double dxNow; // current step size
+    double dxNowAbs; // lfabs(dxNow)
+    double ddxNow; // current change in step size
+    double nStop; // steps required to stop (may be non-integer)
+    double dxStop; // shortest distance required to stop
+    double dxLand; // current step size to achieve "soft landing"
+    double minchange;
+    //approx. minimum fraction of a double precision value that when added, changes that value
+    const double minprecision = 1.1103e-16;
 
+
+    // if not ramping, just return
+    if ( !state->isRamping )
+        return state->val;
+
+    // requested change
+    dxReq = state->req - state->val;
+
+    // apply slew limit
+    if ( dxReq > state->dxMax )
+        dxNow = state->dxMax;
+    else if ( dxReq < -state->dxMax )
+        dxNow = -state->dxMax;
+    else
+        dxNow = dxReq;
+
+    // apply accelleration limit
+    ddxNow = dxNow - state->dxPrev;
+    if ( ddxNow > state->ddxMax )
+        dxNow = state->dxPrev + state->ddxMax;
+    else if ( ddxNow < -state->ddxMax )
+        dxNow = state->dxPrev - state->ddxMax;
+
+    // enforce "soft landing"
+    dxNowAbs = lfabs( dxNow );
+    if ( dxNowAbs > state->ddxMax && dxNow * dxReq > 0.0 )
+    {
+        // number of decellerations required to stop
+        nStop = dxNowAbs / state->ddxMax;
+
+        // distance traveled before stopping
+        // assuming max decelleration in all subsequent steps
+        dxStop = dxNow * ( 1.5 + 0.5 * nStop );
+
+        // dxNow required to make stopping distance = dxReq
+        // (approximation for dxReq ~ dxStop)
+        dxLand = dxNow + ( dxReq - dxStop ) / ( 1.5 + nStop );
+
+        // if dxLand is slower than dxNow, use it
+        if ( lfabs( dxLand ) < dxNowAbs )
+            dxNow = dxLand;
+    }
+
+
+    //minimum change that will affect the current value (this is approximate, and can be bigger than the minimum change).
+    minchange = lfabs(state->val)*minprecision;
+
+    if(dxNow != 0.0)
+    {
+        //handle the case where dxReq is smaller than our approx. minimum
+        if(minchange > lfabs(dxReq))
+        {
+            dxNow = dxReq;
+        }
+        else
+        {
+            //otherwise, use the approx. minimum as a lower limit for our change.
+            if(minchange > lfabs(dxNow))
+            {
+                dxNow = dxNow > 0 ? minchange : -minchange;
+            }
+        }
+    }
+
+
+    // update state
+    state->isRamping = !( dxNow == 0.0 && state->dxPrev == 0.0 );
+
+    //if close enough, just jump to the end
+    if ( lfabs(dxNow) >= lfabs(dxReq))
+    {
+        state->val = state->req;
+        dxNow = dxReq;
+    }
+    else
+    {
+        state->val += dxNow;
+    }
+
+    state->dxPrev = dxNow;
+
+    return state->val;
+}
+
+#ifdef __cplusplus
+}
 #endif
+
+
+#endif //TRAMP_H
diff --git a/src/include/util/fixed_width_types.h b/src/include/util/fixed_width_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b0f300135ec6e69e4bbd45d18382c760123366d
--- /dev/null
+++ b/src/include/util/fixed_width_types.h
@@ -0,0 +1,14 @@
+#ifndef LIGO_FIXED_WIDTH_TYPES_H
+#define LIGO_FIXED_WIDTH_TYPES_H
+
+#if __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+typedef uint64_t    u64;
+typedef int64_t     s64;
+typedef uint32_t    u32;
+typedef int32_t     s32;
+#endif
+
+#endif //LIGO_FIXED_WIDTH_TYPES_H
diff --git a/src/include/util/inlineMath.h b/src/include/util/inlineMath.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d56aa438984181d8f30f140cb1a9e24ae39fcfb
--- /dev/null
+++ b/src/include/util/inlineMath.h
@@ -0,0 +1,24 @@
+/* CVS VERSION: $Id: inlineMath.h,v 1.4 2009/08/18 16:25:21 aivanov Exp $ */
+
+#ifndef LIGO_INLINE_MATH_H
+#define LIGO_INLINE_MATH_H
+
+#define M_PI 3.14159265358979323846
+#define M_TWO_PI 6.28318530717958647692
+
+#if defined(USE_STDLIB_MATH) 
+
+#if defined(__KERNEL__) //Make sure we aren't trying to use the stdlib in kernelspace
+#error "USE_STDLIB_MATH is defined, but the standard lib CANNOT be used in a kernel module. Invalid build options."
+#endif
+
+#include "util/user/inlineMath_stdlib.h"
+#else
+
+//The inlineMath_x86_asm version can be used in kernel and user space, 
+//but the inline assembly makes it dependent on system architecture
+#include "util/inlineMath_x86_asm.h"
+#endif
+
+
+#endif //LIGO_INLINE_MATH_H
diff --git a/src/include/inlineMath.h b/src/include/util/inlineMath_x86_asm.h
similarity index 80%
rename from src/include/inlineMath.h
rename to src/include/util/inlineMath_x86_asm.h
index 36e97dea6f92337cdae5615adb3ea39d55151b74..35c62ecf0e23e6a5150e955899e083fdfb54a387 100644
--- a/src/include/inlineMath.h
+++ b/src/include/util/inlineMath_x86_asm.h
@@ -1,18 +1,12 @@
-/* CVS VERSION: $Id: inlineMath.h,v 1.4 2009/08/18 16:25:21 aivanov Exp $ */
+#ifndef LIGO_INLINE_MATH_X86_ASM
+#define LIGO_INLINE_MATH_X86_ASM
 
-#ifndef INLINE_MATH
-#define INLINE_MATH
+#include "portableInline.h"
 
 #define M_PI 3.14159265358979323846
 #define M_TWO_PI 6.28318530717958647692
+#define M_SQRT2 1.41421356237309504880
 
-#include <asm/msr.h>
-#define rdtscl( low ) __asm__ __volatile__( "rdtsc" : "=a"( low ) : : "edx" )
-
-// These are already defined in kernel's msr.h
-#if 0
-#define rdtscll( val ) __asm__ __volatile__( "rdtsc" : "=A"( val ) )
-#endif
 
 #define __lrint_code                                                           \
     long int __lrintres;                                                       \
@@ -22,18 +16,25 @@
                           : "st" );                                            \
     return __lrintres
 
-inline int
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+LIGO_INLINE int
 _rintf( float __x )
 {
     __lrint_code;
 }
-inline int
+
+LIGO_INLINE int
 _rint( double __x )
 {
     __lrint_code;
 }
 
-inline void
+LIGO_INLINE void
 sincos( double __x, double* __sinx, double* __cosx )
 {
     register long double __cosr;
@@ -59,7 +60,7 @@ sincos( double __x, double* __sinx, double* __cosx )
 }
 
 /* Fast Pentium FPU SQRT command */
-inline double
+LIGO_INLINE double
 lsqrt( double __x )
 {
     register double __result;
@@ -68,7 +69,7 @@ lsqrt( double __x )
 }
 
 /* Fast Pentium FPU 2^x command for -1<=x<=1*/
-inline double
+LIGO_INLINE double
 l2xr( double __x )
 {
     register double __result;
@@ -79,7 +80,7 @@ l2xr( double __x )
 }
 
 /* Fast Pentium FPU round to nearest integer command */
-inline double
+LIGO_INLINE double
 lrndint( double __x )
 {
     register double __result;
@@ -88,7 +89,7 @@ lrndint( double __x )
 }
 
 /* Fast Pentium FPU to multiply with log2(10) */
-inline double
+LIGO_INLINE double
 lmullog210( double __x )
 {
     register double __result;
@@ -97,7 +98,7 @@ lmullog210( double __x )
 }
 
 /* Fast Pentium FPU log10(x) command */
-inline double
+LIGO_INLINE double
 llog10( double __x )
 {
     register double __result;
@@ -108,7 +109,7 @@ llog10( double __x )
 }
 
 /* Fast Pentium absolute value */
-inline double
+LIGO_INLINE double
 lfabs( double __x )
 {
     register double __result;
@@ -117,7 +118,7 @@ lfabs( double __x )
 }
 
 /* Fast Pentium ATAN2 */
-inline double
+LIGO_INLINE double
 latan2( double __y, double __x )
 {
     register long double __atanr;
@@ -132,25 +133,25 @@ The MXCSR register is a 32-bit register containing flags for control and status
 information regarding SSE instructions. As of SSE3, only bits 0-15 have been
 defined.
 
-Pnemonic	Bit Location	Description
-FZ	bit 15	Flush To Zero
-R+	bit 14	Round Positive
-R-	bit 13	Round Negative
-RZ	bits 13 and 14	Round To Zero
-RN	bits 13 and 14 are 0	Round To Nearest
-PM	bit 12	Precision Mask
-UM	bit 11	Underflow Mask
-OM	bit 10	Overflow Mask
-ZM	bit 9	Divide By Zero Mask
-DM	bit 8	Denormal Mask
-IM	bit 7	Invalid Operation Mask
-DAZ	bit 6	Denormals Are Zero
-PE	bit 5	Precision Flag
-UE	bit 4	Underflow Flag
-OE	bit 3	Overflow Flag
-ZE	bit 2	Divide By Zero Flag
-DE	bit 1	Denormal Flag
-IE	bit 0	Invalid Operation Flag
+Pnemonic        Bit Location    Description
+FZ      bit 15  Flush To Zero
+R+      bit 14  Round Positive
+R-      bit 13  Round Negative
+RZ      bits 13 and 14  Round To Zero
+RN      bits 13 and 14 are 0    Round To Nearest
+PM      bit 12  Precision Mask
+UM      bit 11  Underflow Mask
+OM      bit 10  Overflow Mask
+ZM      bit 9   Divide By Zero Mask
+DM      bit 8   Denormal Mask
+IM      bit 7   Invalid Operation Mask
+DAZ     bit 6   Denormals Are Zero
+PE      bit 5   Precision Flag
+UE      bit 4   Underflow Flag
+OE      bit 3   Overflow Flag
+ZE      bit 2   Divide By Zero Flag
+DE      bit 1   Denormal Flag
+IE      bit 0   Invalid Operation Flag
 
 
 FZ mode causes all underflowing operations to simply go to zero. This saves some
@@ -183,7 +184,7 @@ then one needs to inspect bytes 28 through 31 for the MXCSR_MASK value. If bit 6
 is set, DAZ is supported, otherwise, it isn't.
 */
 
-static inline unsigned long long
+LIGO_INLINE unsigned long long
 read_mxcsr( void )
 {
     unsigned long long mxcsr;
@@ -191,22 +192,26 @@ read_mxcsr( void )
     return mxcsr;
 }
 
-static inline void
+LIGO_INLINE void
 write_mxcsr( unsigned long long val )
 {
     asm( "ldmxcsr %0" ::"m"( val ) );
 }
 
 /* Set FZ and DAZ bits, disabling underflows and denorms
- * This fixes long execution times caused by 0.0 inputs to filter modules */
-void
+ * This fixes long execution times caused by 0.0 inputs to filter modules.
+ * See the inlineMath.h header file for more information on the bits we are
+ * setting
+ * */
+LIGO_INLINE void
 fz_daz( void )
 {
-    // unsigned long long mxcsr = read_mxcsr();
-    // printk("mxcsr=%p\n", mxcsr);
-    // mxcsr |= 1 | 1 << 15;
-    // write_mxcsr(mxcsr);
     write_mxcsr( read_mxcsr( ) | 1 | 1 << 15 );
 }
 
-#endif //INLINE_MATH
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //LIGO_INLINE_MATH_X86_ASM
diff --git a/src/include/util/printl.h b/src/include/util/printl.h
new file mode 100644
index 0000000000000000000000000000000000000000..d342f49b3a12718541f85413f91ad70112c9092e
--- /dev/null
+++ b/src/include/util/printl.h
@@ -0,0 +1,17 @@
+#ifndef LIGO_PRINTL_H
+#define LIGO_PRINTL_H
+
+
+#ifdef __KERNEL__
+#include <linux/kernel.h> //snprintf, etc
+#include <linux/printk.h>
+#define printl printk
+
+#else //__KERNEL__
+
+#include <stdio.h>
+#define printl printf
+#endif //!__KERNEL__
+
+
+#endif //LIGO_PRINT_H
diff --git a/src/include/util/prng_xoroshiroPP.h b/src/include/util/prng_xoroshiroPP.h
new file mode 100644
index 0000000000000000000000000000000000000000..dad441a7d387dddb68fa0ba091803ab9080599ab
--- /dev/null
+++ b/src/include/util/prng_xoroshiroPP.h
@@ -0,0 +1,46 @@
+/*  Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org)
+
+To the extent possible under law, the author has dedicated all copyright
+and related and neighboring rights to this software to the public domain
+worldwide. This software is distributed without any warranty.
+
+See <http://creativecommons.org/publicdomain/zero/1.0/>. */
+
+
+/* This is xoroshiro128++ 1.0, one of our all-purpose, rock-solid,
+ * small-state generators. It is extremely (sub-ns) fast and it passes all
+ * tests we are aware of, but its state space is large enough only for
+ * mild parallelism.
+ *
+ * For generating just floating-point numbers, xoroshiro128+ is even
+ * faster (but it has a very mild bias, see notes in the comments).
+ *
+ * The state must be seeded so that it is not everywhere zero. If you have
+ * a 64-bit seed, we suggest to seed a splitmix64 generator and use its
+ * output to fill s.
+ *
+ * This has a 2^(128)-1 period
+ */
+
+#ifndef LIGO_PRNG_XOROSHIRO_PLUS_PLUS_H
+#define LIGO_PRNG_XOROSHIRO_PLUS_PLUS_H
+
+static inline uint64_t rotl(const uint64_t x, int k) {
+    return (x << k) | (x >> (64 - k));
+}
+
+
+static uint64_t xoroshiroPP_next( uint64_t s[2] ) {
+    const uint64_t s0 = s[0];
+    uint64_t s1 = s[1];
+    const uint64_t result = rotl(s0 + s1, 17) + s0;
+
+    s1 ^= s0;
+    s[0] = rotl(s0, 49) ^ s1 ^ (s1 << 21); // a, b
+    s[1] = rotl(s1, 28); // c
+
+    return result;
+}
+
+
+#endif //LIGO_PRNG_XOROSHIRO_PLUS_H
diff --git a/src/include/util/random_bytes.h b/src/include/util/random_bytes.h
new file mode 100644
index 0000000000000000000000000000000000000000..ebc7f89bb6389376090d93a8c29660b56e054079
--- /dev/null
+++ b/src/include/util/random_bytes.h
@@ -0,0 +1,45 @@
+#ifndef LIGO_RAMDOM_BYTES_H
+#define LIGO_RAMDOM_BYTES_H
+
+/****************************************************************************
+ *
+ * This header provides a kernel/usp compatible compatible call for
+ * retrieving cryptographically secure random bytes.
+ *
+ * NOTE: These calls are SLOW and should not be used in performance sensitive
+ *       loops. .5-1us measured on a Intel(R) Xeon(R) CPU E5-1660 v4 @ 3.20GHz
+ *
+ * You will see these used to seed faster PRNGs that will be used to
+ * generate random numbers during critical loops.
+ *
+ * @author EJ Dohmen
+ * @date 13 April 2022
+ *
+ ****************************************************************************/
+
+#ifdef __KERNEL__
+
+#include <linux/random.h>
+
+static inline void ligo_get_random_bytes(void *buf, int nbytes)
+{
+    get_random_bytes(buf, nbytes);
+    return;
+}
+
+#else
+
+#include <sys/random.h>
+
+static inline void ligo_get_random_bytes(void *buf, int nbytes)
+{
+    getrandom(buf, nbytes, GRND_NONBLOCK);
+    return;
+}
+
+
+#endif
+
+
+
+#endif //LIGO_RAMDOM_BYTES_H
diff --git a/src/include/util/timing.h b/src/include/util/timing.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd090970d9fc4079fa2fced782ba3db16e7d7d05
--- /dev/null
+++ b/src/include/util/timing.h
@@ -0,0 +1,54 @@
+#ifndef LIGO_TIMING_H
+#define LIGO_TIMING_H
+
+#include "util/fixed_width_types.h"
+
+#if defined(__KERNEL__)
+
+#include <asm/msr.h> //rdtsc_ordered()
+#include <asm/tsc.h> //tsc_khz
+
+//
+// We are making these functions statix inline bacause rdtsc_ordered()
+// is a static function, and the compiler will complain if we aren't
+//
+
+/** @brief Returns a monotonic count of nanoseconds from an unspecified
+ *         starting point.
+ *
+ *  This is the kernelspace implementation and uses the TSC register, which 
+ *  counts the number of CPU cycles since it was laster reset. We multiply 
+ *  by 1e6 first so we can keep the math fixed point, and factor in the CPU
+ *  frequency with tsc_khz. 
+ *
+ *  TODO: How do we end up with ns?
+ *
+ *  @return uint64_t A number of ns
+ */
+static inline uint64_t getMonotonic_ns_utin64( void ) 
+{
+    return (rdtsc_ordered() * 1000000ULL) / tsc_khz ; 
+}
+
+#else //
+
+#include <time.h>
+
+/** @brief Returns a monotonic count of nanoseconds from an unspecified
+ *         starting point.
+ *         
+ *  This is the userspace implementation and simply uses the clock_gettime()
+ *  function provided by the standard library.
+ *
+ *  @return uint64_t A number of ns
+ */
+static inline uint64_t getMonotonic_ns_utin64( void ) 
+{
+    struct timespec monotime;
+    clock_gettime(CLOCK_MONOTONIC_RAW, &monotime);
+    return (monotime.tv_sec * 1000000000ULL) + monotime.tv_nsec; 
+}
+
+#endif
+
+#endif //LIGO_TIMING_H
diff --git a/src/include/util/user/check_file_crc.h b/src/include/util/user/check_file_crc.h
new file mode 100644
index 0000000000000000000000000000000000000000..f756df0f4a579d03330fd6e59346585ca3cedec1
--- /dev/null
+++ b/src/include/util/user/check_file_crc.h
@@ -0,0 +1,56 @@
+//
+// Created by jonathan.hanks on 3/30/22.
+//
+
+#ifndef DAQD_TRUNK_CHECK_FILE_CRC_H
+#define DAQD_TRUNK_CHECK_FILE_CRC_H
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "crc.h"
+
+
+/// Common routine to check file CRC.
+///	@param[in] *fName	Name of file to check.
+///	@return File CRC or -1 if file not found.
+static inline int
+checkFileCrc( const char* fName )
+{
+    char         cbuf[ 128 ];
+    char*        cp = 0;
+    int          flen = 0;
+    int          clen = 0;
+    unsigned int crc = 0;
+    FILE*        fp = NULL;
+
+    if ( !fName )
+    {
+        return -1;
+    }
+    fp = fopen( fName, "r" );
+    if ( fp == NULL )
+    {
+        return -1;
+    }
+
+    while ( ( cp = fgets( cbuf, 128, fp ) ) != NULL )
+    {
+        clen = strlen( cbuf );
+        flen += clen;
+        crc = crc_ptr( cbuf, clen, crc );
+    }
+    crc = crc_len( flen, crc );
+    fclose( fp );
+    return crc;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // DAQD_TRUNK_CHECK_FILE_CRC_H
diff --git a/src/include/util/user/inlineMath_stdlib.h b/src/include/util/user/inlineMath_stdlib.h
new file mode 100644
index 0000000000000000000000000000000000000000..e8efb20f17edb37a0feb088ddfb82584a00d2d7c
--- /dev/null
+++ b/src/include/util/user/inlineMath_stdlib.h
@@ -0,0 +1,30 @@
+#ifndef LIGO_INLINE_MATH_STDLIB_H
+#define LIGO_INLINE_MATH_STDLIB_H
+
+#include "portableInline.h"
+
+#define _GNU_SOURCE
+#include <math.h>
+#undef _GNU_SOURCE
+
+#include <pmmintrin.h>
+#include <xmmintrin.h>
+
+
+#define lsqrt sqrt
+#define l2xr exp2
+#define lrndint round
+#define lmullog210(x) ((x)*log2(10))
+#define llog10 log10
+#define lfabs fabs
+#define latan2 atan2
+
+LIGO_INLINE void
+fz_daz( void )
+{
+    _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
+    _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
+}
+
+
+#endif //LIGO_INLINE_MATH_STDLIB_H
diff --git a/src/nds/CMakeLists.txt b/src/nds/CMakeLists.txt
index 0582b564321c0acdb5bd758dc4c71f51f390cb68..85e17caf8714f9de69284561bc56f73126f8c39a 100644
--- a/src/nds/CMakeLists.txt
+++ b/src/nds/CMakeLists.txt
@@ -40,6 +40,57 @@ configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
 
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../gds)
 
+add_executable(extracttrend extracttrend.cc)
+target_compile_definitions(extracttrend PRIVATE -D_REENTRANT -DDAQD_CPP11)
+target_compile_definitions(extracttrend PRIVATE ${NDS_COMMON_DEFINES})
+target_compile_definitions(extracttrend PRIVATE -DDAQD_CPP11)
+target_include_directories(extracttrend PRIVATE
+    ${CMAKE_CURRENT_BINARY_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/client
+    ${CMAKE_CURRENT_SOURCE_DIR}/framelib/src
+    ${CMAKE_CURRENT_SOURCE_DIR}/framelib/src/zlib
+    ${CMAKE_CURRENT_SOURCE_DIR}/../include
+    ${Boost_INCLUDE_DIRS}
+)
+target_link_libraries(extracttrend PRIVATE
+        args
+        ldastools::framecpp
+        ${Boost_LIBRARIES})
+add_executable(mergetrend mergetrend.cc)
+target_compile_definitions(mergetrend PRIVATE -D_REENTRANT -DDAQD_CPP11)
+target_compile_definitions(mergetrend PRIVATE ${NDS_COMMON_DEFINES})
+target_compile_definitions(mergetrend PRIVATE -DDAQD_CPP11)
+target_include_directories(mergetrend PRIVATE
+    ${CMAKE_CURRENT_BINARY_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/client
+    ${CMAKE_CURRENT_SOURCE_DIR}/framelib/src
+    ${CMAKE_CURRENT_SOURCE_DIR}/framelib/src/zlib
+    ${CMAKE_CURRENT_SOURCE_DIR}/../include
+    ${Boost_INCLUDE_DIRS}
+)
+target_link_libraries(mergetrend PRIVATE
+        args
+        ldastools::framecpp
+        ${Boost_LIBRARIES})
+add_executable(validaterawtrend validaterawtrend.cc)
+target_compile_definitions(validaterawtrend PRIVATE -D_REENTRANT -DDAQD_CPP11)
+target_compile_definitions(validaterawtrend PRIVATE ${NDS_COMMON_DEFINES})
+target_compile_definitions(validaterawtrend PRIVATE -DDAQD_CPP11)
+target_include_directories(validaterawtrend PRIVATE
+    ${CMAKE_CURRENT_BINARY_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/client
+    ${CMAKE_CURRENT_SOURCE_DIR}/framelib/src
+    ${CMAKE_CURRENT_SOURCE_DIR}/framelib/src/zlib
+    ${CMAKE_CURRENT_SOURCE_DIR}/../include
+    ${Boost_INCLUDE_DIRS}
+)
+target_link_libraries(validaterawtrend PRIVATE
+        args
+        ldastools::framecpp
+        ${Boost_LIBRARIES})
 add_executable(nds ${NDS_SRC})
 target_compile_definitions(nds PRIVATE -D_REENTRANT -DDAQD_CPP11)
 target_compile_definitions(nds PRIVATE ${NDS_COMMON_DEFINES})
@@ -60,4 +111,4 @@ target_link_libraries(nds PRIVATE
 
 install(TARGETS nds DESTINATION bin)
 
-# -L/opt/ldas-tools-al-2.5.5/lib -L/opt/ldas-tools-framecpp-2.5.2/lib -lframecpp -lframecpp8 -lframecpp7 -lframecpp6 -lframecpp4 -lframecpp3 -lframecppcmn -lldastoolsal -lz -lbz2 -ldl -lnsl
\ No newline at end of file
+# -L/opt/ldas-tools-al-2.5.5/lib -L/opt/ldas-tools-framecpp-2.5.2/lib -lframecpp -lframecpp8 -lframecpp7 -lframecpp6 -lframecpp4 -lframecpp3 -lframecppcmn -lldastoolsal -lz -lbz2 -ldl -lnsl
diff --git a/src/nds/extracttrend.cc b/src/nds/extracttrend.cc
new file mode 100644
index 0000000000000000000000000000000000000000..00dd05779fb47d465cdad4f800c7c1542531dfe0
--- /dev/null
+++ b/src/nds/extracttrend.cc
@@ -0,0 +1,237 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+
+#include <iostream>
+#include <fstream>
+#include <list>
+#include <set>
+#include <map>
+#include <string>
+#include <memory>
+
+#include "nds.hh"
+#include "io.h"
+#include "daqd_net.hh"
+#include "../daqd/crc8.cc"
+
+using namespace CDS_NDS;
+using namespace std;
+
+int nds_log_level=4; // Controls volume of log messages
+int _debug = 4;
+
+typedef struct  trend_block_on_disk_t {
+/// These two ints represent a double
+  unsigned int min;
+  unsigned int min2;
+/// These two ints represent a double
+  unsigned int max;
+  unsigned int max2;
+  unsigned int n;
+/// These two ints represent a double
+  unsigned int rms;
+  unsigned int rms2;
+/// These two ints represent a double
+  unsigned int mean;
+  unsigned int mean2;
+
+/// Assign with the in-memory trend structure
+  void operator=(const trend_block_t& t) {
+	memcpy(&min, &t.min, 2*sizeof(unsigned int));
+	memcpy(&max, &t.max, 2*sizeof(unsigned int));
+	n = t.n;
+	memcpy(&rms, &t.rms, 2*sizeof(unsigned int));
+	memcpy(&mean, &t.mean, 2*sizeof(unsigned int));
+  }
+} trend_block_on_disk_t;
+
+typedef struct raw_trend_disk_record_struct {
+  unsigned int gps;
+  trend_block_on_disk_t tb;
+} raw_trend_disk_record_struct;
+
+// Fixed record size to be independent of 32/64 bit difference
+// struct raw_trend_record_struct does not represent the layout of data on disk
+// only in memory.
+#define RAW_TREND_REC_SIZE 40
+
+
+static unsigned long
+find_offs (unsigned int gps, int fd, unsigned long start, unsigned long structs)
+{
+        lseek (fd, RAW_TREND_REC_SIZE * (start + structs/2), SEEK_SET);
+        raw_trend_record_struct ss;
+        int nread = read (fd, &ss, RAW_TREND_REC_SIZE);
+	//if (sizeof(raw_trend_record_struct) == 48) {
+	// we must be on the 64-bit computer
+	//}
+	// Do not need to shuffle the data since ss.gps is the first 4 bytes always
+        if (1 == structs) {
+                if (gps < ss.gps + 30)
+                        return start;
+                else
+                        return start + 1;
+        }
+
+        int begin;
+        if (gps > ss.gps)
+                begin = start + structs/2;
+        else
+                begin = start;
+        DEBUG1(cerr << "recursion: " << gps << " " << ss.gps << " " << begin << " " <<  (structs+1)/2 << endl);
+        return find_offs (gps, fd, begin, (structs+1)/2);
+}
+
+inline void
+byteswap(char *image_ptr, int chb)
+{
+	char a[8];
+	switch(chb) {
+		case 2:
+			a[0] = *image_ptr;
+			*image_ptr = image_ptr[1];
+			image_ptr[1] = a[0];
+			break;
+		case 4:
+			a[0] = image_ptr[0];
+			a[1] = image_ptr[1];
+			a[2] = image_ptr[2];
+			a[3] = image_ptr[3];
+			image_ptr[0] = a[3];
+			image_ptr[1] = a[2];
+			image_ptr[2] = a[1];
+			image_ptr[3] = a[0];
+			break;
+		case 8:
+			a[0] = image_ptr[0];
+			a[1] = image_ptr[1];
+			a[2] = image_ptr[2];
+			a[3] = image_ptr[3];
+			a[4] = image_ptr[4];
+			a[5] = image_ptr[5];
+			a[6] = image_ptr[6];
+			a[7] = image_ptr[7];
+			image_ptr[0] = a[7];
+			image_ptr[1] = a[6];
+			image_ptr[2] = a[5];
+			image_ptr[3] = a[4];
+			image_ptr[4] = a[3];
+			image_ptr[5] = a[2];
+			image_ptr[6] = a[1];
+			image_ptr[7] = a[0];
+			break;
+	}
+}
+
+int printUntil(int fd, int gpsEnd, int lastReadGPS, raw_trend_disk_record_struct *sd) {
+  int nread = 0;
+
+  do {
+    if (sd->gps <= lastReadGPS) {
+	fprintf(stderr, "Skipping record: time goes backwards: %d -> %d\n", sd->gps, lastReadGPS);
+    } else if ((lastReadGPS - sd->gps) %60 != 0) {
+	fprintf(stderr, "Skipping record: time increased by an interval != 60seconds: %d\n", lastReadGPS - sd->gps);
+    } else {
+	//fprintf(stderr, "Wrote data at %d\n", sd->gps);
+	fwrite(sd, RAW_TREND_REC_SIZE, 1, stdout);
+	lastReadGPS = sd->gps;
+    }
+
+    nread = read (fd, sd, RAW_TREND_REC_SIZE);
+  } while (sd->gps < gpsEnd && nread != 0);
+
+  return nread;
+}
+
+int main (int argc, char **argv) {
+  multimap<string, int> fname_channel_mmap; // file_name -> index of the signal in the user request
+  typedef multimap<string, int>::const_iterator FCMI;
+  set<string> file_set; // to keep file names
+  map<string, list<data_span> > data_span_map; // file_name -> list of data spans
+  typedef map<string, list<data_span> >::const_iterator DSMI;
+  typedef map<string, list<data_span> >::iterator NCDSMI;
+  typedef list<data_span>::const_iterator DSI;
+  typedef list<data_span>::iterator NCDSI;
+  typedef list<mapping_data_span>::const_iterator MDSI;
+  typedef list<mapping_data_span>::iterator NCMDSI;
+  typedef set<string>::const_iterator SSI;
+
+
+  if (argc != 5) {
+    fprintf(stderr, "Usage:  %s <infile> <gpsStart> <gpsEnd> <outfile>\n", argv[0]);
+    exit(1);
+  }
+
+  string infile = argv[1];
+  int gpsstart = atoi(argv[2]);
+  int gpsend = atoi(argv[3]);
+  string outfile = argv[4];
+
+  // For every file construct a list of data spans (index, gps, length), `data_span_map'
+  // Each file contains data with gaps. This we end up with the list of data spans.
+  int fd = open (infile.c_str(), O_RDONLY);
+
+  int fdout = open (outfile.c_str(), O_WRONLY|O_TRUNC|O_CREAT);
+
+  if (fd < 0) {
+    system_log(1, "Couldn't open raw minute trend file `%s' for reading; errno %d", infile.c_str(), errno);
+  } else if (fdout < 0) {
+    system_log(1, "Couldn't open raw minute trend file `%s' for writing; errno %d", outfile.c_str(), errno);
+  } else {
+    struct stat st;
+    struct stat st_out;
+    int res = fstat (fd, &st);
+    int resout = fstat (fdout, &st_out);
+    if (res) {
+      system_log(1, "Couldn't stat raw minute trend file `%s'; errno %d", infile.c_str(), errno);
+    } else if (resout) {
+      system_log(1, "Couldn't stat raw minute trend file `%s'; errno %d", outfile.c_str(), errno);
+    } else {
+      int structs = st.st_size / RAW_TREND_REC_SIZE;
+      int structsout = st_out.st_size / RAW_TREND_REC_SIZE;
+      raw_trend_disk_record_struct sd;
+      DEBUG1(cerr << infile << ": length " << st.st_size << "; structs " <<  structs << endl);
+      if (st.st_size%RAW_TREND_REC_SIZE) {
+	system_log (1, "WARNING: filesize of %s isn't multiple of %d (record size)\n", infile.c_str(), RAW_TREND_REC_SIZE);
+	exit(1);
+      } else {
+	int nread = 0;
+	int nwrite = 0;
+	int endFound = 0;
+	int lastReadGPS = 0;
+
+	nread = read (fd, &sd, RAW_TREND_REC_SIZE);
+
+	while (sd.gps <= gpsend && !endFound) {
+	  if (nread == 0) {
+	    fprintf(stderr, "EOF on input file at %d.\n", sd.gps);
+	    endFound = 1;
+	  } else if (sd.gps > gpsend) {
+	    fprintf(stderr, "GPS End reached on src file at %d.\n", sd.gps);
+	    endFound = 1;
+	  } else if (sd.gps+60 >= gpsstart && sd.gps <= gpsend ) {
+	    nwrite = write (fdout, &sd, RAW_TREND_REC_SIZE);
+	    fprintf(stdout, "Wrote GPS record %ld\n", sd.gps);
+	  } else {
+	    fprintf(stdout, "Skipping GPS record %ld\n", sd.gps);
+	  }
+	  nread = read (fd, &sd, RAW_TREND_REC_SIZE);
+	}
+      }
+    }
+    close (fd);
+    close (fdout);
+  } 
+
+  exit(0);
+}
+
diff --git a/src/nds/mergetrend.cc b/src/nds/mergetrend.cc
new file mode 100644
index 0000000000000000000000000000000000000000..71cb2e241b35c5fd2d8093a245282cea3708abfe
--- /dev/null
+++ b/src/nds/mergetrend.cc
@@ -0,0 +1,301 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+
+#include <iostream>
+#include <fstream>
+#include <list>
+#include <set>
+#include <map>
+#include <string>
+#include <memory>
+
+#include "nds.hh"
+#include "io.h"
+#include "daqd_net.hh"
+#include "../daqd/crc8.cc"
+
+using namespace CDS_NDS;
+using namespace std;
+
+int nds_log_level=4; // Controls volume of log messages
+int _debug = 4;
+
+typedef struct  trend_block_on_disk_t {
+/// These two ints represent a double
+  unsigned int min;
+  unsigned int min2;
+/// These two ints represent a double
+  unsigned int max;
+  unsigned int max2;
+  unsigned int n;
+/// These two ints represent a double
+  unsigned int rms;
+  unsigned int rms2;
+/// These two ints represent a double
+  unsigned int mean;
+  unsigned int mean2;
+
+/// Assign with the in-memory trend structure
+  void operator=(const trend_block_t& t) {
+	memcpy(&min, &t.min, 2*sizeof(unsigned int));
+	memcpy(&max, &t.max, 2*sizeof(unsigned int));
+	n = t.n;
+	memcpy(&rms, &t.rms, 2*sizeof(unsigned int));
+	memcpy(&mean, &t.mean, 2*sizeof(unsigned int));
+  }
+} trend_block_on_disk_t;
+
+typedef struct raw_trend_disk_record_struct {
+  unsigned int gps;
+  trend_block_on_disk_t tb;
+} raw_trend_disk_record_struct;
+
+// Fixed record size to be independent of 32/64 bit difference
+// struct raw_trend_record_struct does not represent the layout of data on disk
+// only in memory.
+#define RAW_TREND_REC_SIZE 40
+
+
+static unsigned long
+find_offs (unsigned int gps, int fd, unsigned long start, unsigned long structs)
+{
+        lseek (fd, RAW_TREND_REC_SIZE * (start + structs/2), SEEK_SET);
+        raw_trend_record_struct ss;
+        int nread = read (fd, &ss, RAW_TREND_REC_SIZE);
+	//if (sizeof(raw_trend_record_struct) == 48) {
+	// we must be on the 64-bit computer
+	//}
+	// Do not need to shuffle the data since ss.gps is the first 4 bytes always
+        if (1 == structs) {
+                if (gps < ss.gps + 30)
+                        return start;
+                else
+                        return start + 1;
+        }
+
+        int begin;
+        if (gps > ss.gps)
+                begin = start + structs/2;
+        else
+                begin = start;
+        DEBUG1(cerr << "recursion: " << gps << " " << ss.gps << " " << begin << " " <<  (structs+1)/2 << endl);
+        return find_offs (gps, fd, begin, (structs+1)/2);
+}
+
+inline void
+byteswap(char *image_ptr, int chb)
+{
+	char a[8];
+	switch(chb) {
+		case 2:
+			a[0] = *image_ptr;
+			*image_ptr = image_ptr[1];
+			image_ptr[1] = a[0];
+			break;
+		case 4:
+			a[0] = image_ptr[0];
+			a[1] = image_ptr[1];
+			a[2] = image_ptr[2];
+			a[3] = image_ptr[3];
+			image_ptr[0] = a[3];
+			image_ptr[1] = a[2];
+			image_ptr[2] = a[1];
+			image_ptr[3] = a[0];
+			break;
+		case 8:
+			a[0] = image_ptr[0];
+			a[1] = image_ptr[1];
+			a[2] = image_ptr[2];
+			a[3] = image_ptr[3];
+			a[4] = image_ptr[4];
+			a[5] = image_ptr[5];
+			a[6] = image_ptr[6];
+			a[7] = image_ptr[7];
+			image_ptr[0] = a[7];
+			image_ptr[1] = a[6];
+			image_ptr[2] = a[5];
+			image_ptr[3] = a[4];
+			image_ptr[4] = a[3];
+			image_ptr[5] = a[2];
+			image_ptr[6] = a[1];
+			image_ptr[7] = a[0];
+			break;
+	}
+}
+
+int printUntil(int fd, int gpsEnd, int lastReadGPS, raw_trend_disk_record_struct *sd) {
+  int nread = 0;
+
+  do {
+    if (sd->gps <= lastReadGPS) {
+	fprintf(stderr, "Skipping record: time goes backwards: %d -> %d\n", sd->gps, lastReadGPS);
+    } else if ((lastReadGPS - sd->gps) %60 != 0) {
+	fprintf(stderr, "Skipping record: time increased by an interval != 60seconds: %d\n", lastReadGPS - sd->gps);
+    } else {
+	//fprintf(stderr, "Wrote data at %d\n", sd->gps);
+	fwrite(sd, RAW_TREND_REC_SIZE, 1, stdout);
+	lastReadGPS = sd->gps;
+    }
+
+    nread = read (fd, sd, RAW_TREND_REC_SIZE);
+  } while (sd->gps < gpsEnd && nread != 0);
+
+  return nread;
+}
+
+int main (int argc, char **argv) {
+  multimap<string, int> fname_channel_mmap; // file_name -> index of the signal in the user request
+  typedef multimap<string, int>::const_iterator FCMI;
+  set<string> file_set; // to keep file names
+  map<string, list<data_span> > data_span_map; // file_name -> list of data spans
+  typedef map<string, list<data_span> >::const_iterator DSMI;
+  typedef map<string, list<data_span> >::iterator NCDSMI;
+  typedef list<data_span>::const_iterator DSI;
+  typedef list<data_span>::iterator NCDSI;
+  typedef list<mapping_data_span>::const_iterator MDSI;
+  typedef list<mapping_data_span>::iterator NCMDSI;
+  typedef set<string>::const_iterator SSI;
+
+
+  if (argc != 6) {
+    fprintf(stderr, "Usage:  %s <channel> <path1> <path2> <gpsStart> <gpsEnd>\n", argv[0]);
+    exit(1);
+  }
+
+  string channel = argv[1];
+  string path = argv[2];
+  string pathfiller = argv[3];
+  int gpsstart = atoi(argv[4]);
+  int gpsend = atoi(argv[5]);
+
+  file_set.insert(channel);
+
+  // For every file construct a list of data spans (index, gps, length), `data_span_map'
+  // Each file contains data with gaps. This we end up with the list of data spans.
+  for (SSI p = file_set.begin (); p != file_set.end (); p++) {
+    //string fname_str = path + "/" + crc8_str(p->c_str()) + "/" +*p;
+    string fname_str = path + "/" + *p;
+    const char *fname = fname_str.c_str ();
+    int fd = open (fname, O_RDONLY);
+
+    string fillername_str = pathfiller + "/" + crc8_str(p->c_str()) + "/" +*p;
+    const char *fillername = fillername_str.c_str ();
+    int fdfiller = open (fillername, O_RDONLY);
+
+    if (fd < 0) {
+      system_log(1, "Couldn't open raw minute trend file `%s' for reading; errno %d", fname, errno);
+    } else if (fdfiller < 0) {
+      system_log(1, "Couldn't open raw minute trend file `%s' for reading; errno %d", fillername, errno);
+    } else {
+      struct stat st;
+      struct stat stfiller;
+      int res = fstat (fd, &st);
+      int resfiller = fstat (fdfiller, &stfiller);
+      if (res) {
+	system_log(1, "Couldn't stat raw minute trend file `%s'; errno %d", fname, errno);
+      } else if (resfiller) {
+	system_log(1, "Couldn't stat raw minute trend file `%s'; errno %d", fillername, errno);
+      } else {
+	int structs = st.st_size / RAW_TREND_REC_SIZE;
+	int structsfiller = stfiller.st_size / RAW_TREND_REC_SIZE;
+        raw_trend_disk_record_struct sd;
+        raw_trend_disk_record_struct sdfiller;
+        DEBUG1(cerr << fname << ": length " << st.st_size << "; structs " <<  structs << endl);
+        if (st.st_size%RAW_TREND_REC_SIZE) {
+	  system_log (1, "WARNING: filesize of %s isn't multiple of %d (record size)\n", fname, RAW_TREND_REC_SIZE);
+	  exit(1);
+	} else if (stfiller.st_size%RAW_TREND_REC_SIZE) {
+	  system_log (1, "WARNING: filesize of %s isn't multiple of %d (record size)\n", fillername, RAW_TREND_REC_SIZE);
+	  exit(1);
+	} else {
+	  int nread = 0;
+	  int nreadfiller = 0;
+	  int endFound = 0;
+	  int lastReadGPS = 0;
+	  nread = read (fd, &sd, RAW_TREND_REC_SIZE);
+	  nreadfiller = read (fdfiller, &sdfiller, RAW_TREND_REC_SIZE);
+
+	  fprintf(stderr, "Start of src: %d\n", sd.gps);
+	  fprintf(stderr, "Start of filler: %d\n", sdfiller.gps);
+
+	  while (!endFound) {
+	    if (nread == 0) {
+	      /*
+	       * EOF on source file.  Continue filling in data from 
+	       * the filler file.
+	       */
+	      fprintf(stderr, "EOF on input file at %d.  Completing with filler file.\n", sd.gps);
+	      nreadfiller = printUntil(fdfiller, gpsend, lastReadGPS, &sdfiller);
+	      lastReadGPS = sdfiller.gps;
+	    } else if (nreadfiller == 0) {
+	      /*
+	       * EOF on filler file.  Continue filling in data from 
+	       * the source file.
+	       */
+	      fprintf(stderr, "EOF on filler file at %d.  Completing with input file.\n", sdfiller.gps);
+	      nread = printUntil(fd, gpsend, lastReadGPS, &sd);
+	      lastReadGPS = sd.gps;
+	    } else if (sd.gps == sdfiller.gps) {
+	      if (sd.gps - lastReadGPS > 60) {
+		fprintf(stderr, "Unfillable gap from %d to %d (%d s)\n", lastReadGPS, sd.gps, sd.gps - lastReadGPS);
+	      }
+	      if (sd.tb.n > sdfiller.tb.n) {
+		fprintf(stderr, "Filled partial trend from src (%d vs. %d) at %d\n", sd.tb.n, sdfiller.tb.n, sdfiller.gps);
+		fwrite(&sd, RAW_TREND_REC_SIZE, 1, stdout);
+		lastReadGPS = sd.gps;
+	      } else if (sd.tb.n < sdfiller.tb.n) {
+		fprintf(stderr, "Filled partial trend from filler (%d vs. %d) at %d\n", sd.tb.n, sdfiller.tb.n, sdfiller.gps);
+		fwrite(&sdfiller, RAW_TREND_REC_SIZE, 1, stdout);
+		lastReadGPS = sdfiller.gps;
+	      } else {
+		//fprintf(stderr, "Wrote data at %d\n", sd.gps);
+		fwrite(&sd, RAW_TREND_REC_SIZE, 1, stdout);
+		lastReadGPS = sd.gps;
+	      }
+	      nread = read (fd, &sd, RAW_TREND_REC_SIZE);
+	      nreadfiller = read (fdfiller, &sdfiller, RAW_TREND_REC_SIZE);
+	    } else if (sd.gps < sdfiller.gps) {
+	      fprintf(stderr, "Filling reverse gap from %d to %d (%d s)\n", sd.gps, sdfiller.gps, sdfiller.gps - sd.gps);
+	      nread = printUntil(fd, sdfiller.gps, lastReadGPS, &sd);
+	      lastReadGPS = sd.gps;
+	    } else {
+	      fprintf(stderr, "Filling gap from %d to %d (%d s)\n", sdfiller.gps, sd.gps, sd.gps - sdfiller.gps);
+	      nreadfiller = printUntil(fdfiller, sd.gps, lastReadGPS, &sdfiller);
+	      lastReadGPS = sdfiller.gps;
+	    }
+
+	    if ((nread == 0 || sd.gps > gpsend) && (nreadfiller == 0 || sdfiller.gps > gpsend)) {
+	      if (nread == 0) {
+		fprintf(stderr, "EOF on input file at %d.\n", sd.gps);
+	      }
+	      if (nreadfiller == 0) {
+		fprintf(stderr, "EOF on filler file at %d.\n", sdfiller.gps);
+	      }
+	      if (sd.gps > gpsend) {
+		fprintf(stderr, "GPS End reached on src file at %d.\n", sd.gps);
+	      }
+	      if (sdfiller.gps > gpsend) {
+		fprintf(stderr, "GPS End reached on filler file at %d.\n", sdfiller.gps);
+	      }
+	      endFound = 1;
+	    }
+	  }
+	}
+      }
+      close (fd);
+      close (fdfiller);
+    } 
+  }
+
+  exit(0);
+}
+
diff --git a/src/nds/validaterawtrend.cc b/src/nds/validaterawtrend.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2132697570b49b3a26f8556fab56e8eaf7dd6aa7
--- /dev/null
+++ b/src/nds/validaterawtrend.cc
@@ -0,0 +1,337 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <fstream>
+#include <list>
+#include <set>
+#include <map>
+#include <string>
+#include <memory>
+
+#include "nds.hh"
+#include "io.h"
+#include "daqd_net.hh"
+#include "../daqd/crc8.cc"
+
+using namespace CDS_NDS;
+using namespace std;
+
+int nds_log_level=4; // Controls volume of log messages
+int _debug = 4;
+
+typedef struct  trend_block_on_disk_t {
+/// These two ints represent a double
+  unsigned int min;
+  unsigned int min2;
+/// These two ints represent a double
+  unsigned int max;
+  unsigned int max2;
+  unsigned int n;
+/// These two ints represent a double
+  unsigned int rms;
+  unsigned int rms2;
+/// These two ints represent a double
+  unsigned int mean;
+  unsigned int mean2;
+
+/// Assign with the in-memory trend structure
+  void operator=(const trend_block_t& t) {
+	memcpy(&min, &t.min, 2*sizeof(unsigned int));
+	memcpy(&max, &t.max, 2*sizeof(unsigned int));
+	n = t.n;
+	memcpy(&rms, &t.rms, 2*sizeof(unsigned int));
+	memcpy(&mean, &t.mean, 2*sizeof(unsigned int));
+  }
+} trend_block_on_disk_t;
+
+typedef struct raw_trend_disk_record_struct {
+  unsigned int gps;
+  trend_block_on_disk_t tb;
+} raw_trend_disk_record_struct;
+
+// Fixed record size to be independent of 32/64 bit difference
+// struct raw_trend_record_struct does not represent the layout of data on disk
+// only in memory.
+#define RAW_TREND_REC_SIZE 40
+
+
+static unsigned long
+find_offs (unsigned int gps, int fd, unsigned long start, unsigned long structs)
+{
+        lseek (fd, RAW_TREND_REC_SIZE * (start + structs/2), SEEK_SET);
+        raw_trend_record_struct ss;
+        int nread = read (fd, &ss, RAW_TREND_REC_SIZE);
+	//if (sizeof(raw_trend_record_struct) == 48) {
+	// we must be on the 64-bit computer
+	//}
+	// Do not need to shuffle the data since ss.gps is the first 4 bytes always
+        if (1 == structs) {
+                if (gps < ss.gps + 30)
+                        return start;
+                else
+                        return start + 1;
+        }
+
+        int begin;
+        if (gps > ss.gps)
+                begin = start + structs/2;
+        else
+                begin = start;
+        DEBUG1(cerr << "recursion: " << gps << " " << ss.gps << " " << begin << " " <<  (structs+1)/2 << endl);
+        return find_offs (gps, fd, begin, (structs+1)/2);
+}
+
+inline void
+byteswap(char *image_ptr, int chb)
+{
+	char a[8];
+	switch(chb) {
+		case 2:
+			a[0] = *image_ptr;
+			*image_ptr = image_ptr[1];
+			image_ptr[1] = a[0];
+			break;
+		case 4:
+			a[0] = image_ptr[0];
+			a[1] = image_ptr[1];
+			a[2] = image_ptr[2];
+			a[3] = image_ptr[3];
+			image_ptr[0] = a[3];
+			image_ptr[1] = a[2];
+			image_ptr[2] = a[1];
+			image_ptr[3] = a[0];
+			break;
+		case 8:
+			a[0] = image_ptr[0];
+			a[1] = image_ptr[1];
+			a[2] = image_ptr[2];
+			a[3] = image_ptr[3];
+			a[4] = image_ptr[4];
+			a[5] = image_ptr[5];
+			a[6] = image_ptr[6];
+			a[7] = image_ptr[7];
+			image_ptr[0] = a[7];
+			image_ptr[1] = a[6];
+			image_ptr[2] = a[5];
+			image_ptr[3] = a[4];
+			image_ptr[4] = a[3];
+			image_ptr[5] = a[2];
+			image_ptr[6] = a[1];
+			image_ptr[7] = a[0];
+			break;
+	}
+}
+
+void print_usage(const char *progname) {
+    fprintf(stderr, "Usage:  %s [-g] [-v] [-e] [-s] [-f] [-G maxgap] <filename>\n", progname);
+    fprintf(stderr, "        -g  Print each gap\n");
+    fprintf(stderr, "        -v  Print each data record\n");
+    fprintf(stderr, "        -e  Exit the first time an error is found\n");
+    fprintf(stderr, "        -s  Do not print the summary of gaps and time spans\n");
+    fprintf(stderr, "        -f  Purge invalid data and write the result to stdout\n");
+    fprintf(stderr, "        -G  maxgap Maximum allowed size of a gap.\n");
+    fprintf(stderr, "        -m  minGPS Minimum allowed GPS timestamp on data records.\n");
+    fprintf(stderr, "                   Defaults to timestamp on first data record\n");
+    fprintf(stderr, "        -M  maxGPS Maximum allowed GPS timestamp on data records.\n");
+    fprintf(stderr, "                   Defaults to timestamp on final data record\n");
+}
+
+int main (int argc, char **argv) {
+  multimap<string, int> fname_channel_mmap; // file_name -> index of the signal in the user request
+  typedef multimap<string, int>::const_iterator FCMI;
+  set<string> file_set; // to keep file names
+  map<string, list<data_span> > data_span_map; // file_name -> list of data spans
+  typedef map<string, list<data_span> >::const_iterator DSMI;
+  typedef map<string, list<data_span> >::iterator NCDSMI;
+  typedef list<data_span>::const_iterator DSI;
+  typedef list<data_span>::iterator NCDSI;
+  typedef list<mapping_data_span>::const_iterator MDSI;
+  typedef list<mapping_data_span>::iterator NCMDSI;
+  typedef set<string>::const_iterator SSI;
+
+  int opt;
+  int verbose = 0;
+  int exit_on_error = 0;
+  int print_gaps = 0;
+  int print_summary = 1;
+  int fix_file = 0;
+  int max_gap = 0;
+  int lastRecordGPS = 0;
+  int startGPS = 0;
+
+  while ((opt = getopt(argc, argv, "sgvefG:m:M:")) != -1) {
+    switch (opt) {
+      case 'v':
+	verbose++;
+	break;
+      case 'g':
+	print_gaps++;
+	break;
+      case 's':
+	print_summary = 0;
+	break;
+      case 'e':
+	exit_on_error++;
+	break;
+      case 'f':
+	fix_file++;
+	break;
+      case 'G':
+	max_gap=atoi(optarg);
+	break;
+      case 'm':
+	startGPS=atoi(optarg);
+	break;
+      case 'M':
+	lastRecordGPS=atoi(optarg);
+	break;
+      default:
+	print_usage(argv[0]);
+	exit(1);
+    }
+  }
+
+  if (optind >= argc) {
+    print_usage(argv[0]);
+    exit(1);
+  }
+
+  int errorFound = 0;
+  string channel = argv[optind];
+  file_set.insert(channel);
+
+  // For every file construct a list of data spans (index, gps, length), `data_span_map'
+  // Each file contains data with gaps. This we end up with the list of data spans.
+  for (SSI p = file_set.begin (); p != file_set.end (); p++) {
+    string fname_str = *p;
+    const char *fname = fname_str.c_str ();
+    int fd = open (fname, O_RDONLY);
+    if (fd < 0) {
+      system_log(1, "Couldn't open raw minute trend file `%s' for reading; errno %d", fname, errno);
+    } else {
+      struct stat st;
+      int res = fstat (fd, &st);
+      if (res) {
+	system_log(1, "Couldn't stat raw minute trend file `%s'; errno %d", fname, errno);
+      } else {
+	int structs = st.st_size / RAW_TREND_REC_SIZE;
+        raw_trend_disk_record_struct sd;
+        DEBUG1(cerr << fname << ": length " << st.st_size << "; structs " <<  structs << endl);
+        if (st.st_size%RAW_TREND_REC_SIZE) {
+	  system_log (1, "WARNING: filesize of %s isn't multiple of %d (record size)\n", fname, RAW_TREND_REC_SIZE);
+	}
+
+	int nread = 0;
+	if (lastRecordGPS == 0) {
+	    lseek (fd, -RAW_TREND_REC_SIZE, SEEK_END);
+	    nread = read (fd, &sd, RAW_TREND_REC_SIZE);
+	    if (nread != 0) {
+		lastRecordGPS = sd.gps;
+	    }
+	    lseek (fd, 0, SEEK_SET);
+	}
+
+	int numRecords = 0;
+	int numGaps = 0;
+	int gapSpan = 0;
+	int prevGPS = 0;
+	int longestGap = 0;
+	nread = read (fd, &sd, RAW_TREND_REC_SIZE);
+	while (nread != 0) {
+	  numRecords++;
+	  if (startGPS == 0) {
+	    startGPS = sd.gps;
+	    if (startGPS > lastRecordGPS) {
+		fprintf(stderr, "Timestamp of final record is less than timestamp of first record: %d vs. %d\n", startGPS, lastRecordGPS);
+		if (exit_on_error) {
+		    exit (1);
+		}
+	    }
+	  }
+
+	  if (sd.gps % 60 != 0) {
+	    fprintf(stderr, "Record %d does not start at a 60-second boundary: %d (off by %d)\n", numRecords, sd.gps, sd.gps%60);
+	    errorFound++;
+	    if (exit_on_error) {
+	      exit (1);
+	    }
+	  } else if (sd.gps < startGPS || sd.gps > lastRecordGPS) {
+	    fprintf(stderr, "Record %d has a timestamp outside the bounds of the file: %d not within %d -> %d\n", numRecords, sd.gps, startGPS, lastRecordGPS);
+	    errorFound++;
+	    if (exit_on_error) {
+	      exit (1);
+	    }
+	  } else if (prevGPS > 0 && sd.gps < prevGPS) {
+	    fprintf(stderr, "Time goes backwards at record %d: %d -> %d\n", numRecords, prevGPS, sd.gps);
+	    errorFound++;
+	    if (exit_on_error) {
+	      exit (1);
+	    }
+	  } else if (prevGPS > 0 && max_gap > 0 && sd.gps - prevGPS > max_gap) {
+	    fprintf(stderr, "Gap found between %d and %d lasting %d s, exceeded max allowed gap size of %d.\n", prevGPS, sd.gps, sd.gps - prevGPS, max_gap);
+	    if (sd.gps - prevGPS > longestGap) {
+		longestGap = sd.gps - prevGPS;
+	    }
+	    errorFound++;
+	    if (exit_on_error) {
+		exit (1);
+	    }
+	  } else if (prevGPS > 0 && sd.gps - prevGPS > 60) {
+	    if (print_gaps >= 1) {
+		fprintf(stderr, "Gap found between %d and %d lasting %d s\n", prevGPS, sd.gps, sd.gps - prevGPS);
+	    }
+	    if (sd.gps - prevGPS > longestGap) {
+		longestGap = sd.gps - prevGPS;
+	    }
+	    numGaps++;
+	    gapSpan += sd.gps - prevGPS;
+	    prevGPS = sd.gps;
+	    if (fix_file && sd.gps - prevGPS <= max_gap) {
+		fwrite(&sd, RAW_TREND_REC_SIZE, 1, stdout);
+	    }
+	  } else if (prevGPS > 0 && sd.gps - prevGPS != 60) {
+	    fprintf(stderr, "Bad gap size found at record %d between %d and %d lasting %d s\n", numRecords, prevGPS, sd.gps, sd.gps - prevGPS);
+	    errorFound++;
+	    if (exit_on_error) {
+	      exit (1);
+	    }
+	    prevGPS = sd.gps;
+	  } else {
+	    if (fix_file) {
+		fwrite(&sd, RAW_TREND_REC_SIZE, 1, stdout);
+	    }
+	    prevGPS = sd.gps;
+	  }
+
+	  if (verbose) {
+	    fprintf(stderr, "%d: %d min:%d+%d max:%d+%d rms:%d+%d mean:%d+%d n:%d\n", numRecords, sd.gps, sd.tb.min, sd.tb.min2, sd.tb.max, sd.tb.max2, sd.tb.rms, sd.tb.rms2, sd.tb.mean, sd.tb.mean2, sd.tb.n);
+	  }
+	  nread = read (fd, &sd, RAW_TREND_REC_SIZE);
+	}
+	if (print_summary) {
+	  fprintf(stderr, "%d records with %d gaps spanning %d seconds found\n", numRecords, numGaps, gapSpan);
+	  fprintf(stderr, "Max gap length is %d\n", longestGap);
+	  fprintf(stderr, "GPS time range: %d to %d\n", startGPS, prevGPS);
+	}
+      }
+      close (fd);
+    } 
+  }
+
+  if (errorFound) {
+    exit(1);
+  }
+  exit(0);
+}
+
diff --git a/src/pcie_switch/kmod/Makefile b/src/pcie_switch/kmod/Makefile
index 27aa07e527e52b248b8efd808cb29e593bb36efa..4df22c60867813a9a2b539c92e41afa4f1bfca46 100644
--- a/src/pcie_switch/kmod/Makefile
+++ b/src/pcie_switch/kmod/Makefile
@@ -1,9 +1,15 @@
-MBUFSYM="$(shell ../../epics/util/find_module_symvers mbuf)"
-GPSSYM="$(shell ../../epics/util/find_module_symvers gpstime)"
-CPUISOSYM="$(shell ../../epics/util/find_module_symvers -q rts-cpu-isolator)"
-KBUILD_EXTRA_SYMBOLS=$MBUFSYM
-KBUILD_EXTRA_SYMBOLS += $GPSSYM
-KBUILD_EXTRA_SYMBOLS += $CPUISOSYM
+ifndef MBUF_SYM
+MBUF_SYM = $(shell ../../epics/util/find_module_symvers -q mbuf)
+endif
+ifndef GPSTIME_SYM
+GPSTIME_SYM = $(shell ../../epics/util/find_module_symvers -q gpstime)
+endif
+ifndef RTS_CPU_ISOLATOR_SYM
+RTS_CPU_ISOLATOR_SYM = $(shell ../../epics/util/find_module_symvers -q rts-cpu-isolator)
+endif
+KBUILD_EXTRA_SYMBOLS = $MBUF_SYM
+KBUILD_EXTRA_SYMBOLS += $GPSTIME_SYM
+KBUILD_EXTRA_SYMBOLS += $RTS_CPU_ISOLATOR_SYM
 
 EXTRA_CFLAGS += -O3
 DISDIR = /opt/srcdis
diff --git a/src/perldaq/daq.pm b/src/perldaq/daq.pm
new file mode 100755
index 0000000000000000000000000000000000000000..7468b93a2d3a1c6a97157d863006ea5ac4aede3e
--- /dev/null
+++ b/src/perldaq/daq.pm
@@ -0,0 +1,183 @@
+package DAQ;
+use Exporter;
+@ISA = ('Exporter');
+
+use IO::Socket;
+
+%channels = ();
+$host = "";
+$port = 8088;
+
+
+# get the channel list from the server, store in %channels
+sub connect {
+my ($host, $port) = @_;
+
+if (! defined $host) {
+	$host = 'localhost';
+}
+if (! defined $port) {
+	$port = 8088;
+}
+$DAQ::host = $host;
+$DAQ::port = $port;
+
+$remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $host, PeerPort => $port);
+unless ($remote) { die "cannot connect to daqd on $host:$port" }
+$remote->autoflush(1);
+
+# Get the channel list and store the values
+#
+
+print $remote "status channels 3;\n";
+$len = 0 + <$remote>;
+#print "$len channels configured\n";
+for my $i (1 .. $len) {
+	#print $i, "\n";
+	my $name = <$remote>;
+	my $rate = 0 + <$remote>;
+	my $type = 0 + <$remote>;
+	my $tpnum = 0 + <$remote>;
+	my $grpnum = 0 + <$remote>;
+	my $units = <$remote>;
+	my $gain = .0 + <$remote>;
+	my $slope = .0 + <$remote>;
+	my $offset = .0 + <$remote>;
+	chomp $name;
+	chomp $units;
+	$channels{$name} = {rate => $rate,
+				type => $type,
+				tpnum => $tpnum,
+				grpnum => $grpnum,
+				units => $units,
+				gain => $gain,
+				slope => $slope,
+				offset => $offset};
+	#print $channels{$name};
+} 
+close $remote;
+return 0;
+}
+
+# print the while channel list or just a single channel, given an argument (channel name)
+sub print_channel {
+my ($cn) = @_;
+
+if (!defined $cn) {
+for my $chname (keys %channels) {
+	print $chname, "\n";
+	for (keys %{$channels{$chname}}) {
+		print $_, "=", ${$channels{$chname}}{$_}, "\n";
+	}
+}
+} else {
+	print $cn, "\n";
+	for (keys %{$channels{$cn}}) {
+		print $_, "=", ${$channels{$cn}}{$_}, "\n";
+	}
+}
+}
+
+# get current time
+sub gps {
+my $remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $DAQ::host, PeerPort => $DAQ::port);
+unless ($remote) { die "cannot connect to daqd on $DAQ::host:$DAQ::port" }
+$remote->autoflush(1);
+my $gps = 0;
+
+# This loop here is to fix a frame builder bug
+# sometimes "gps" commands returns strange number (0 or a number much less than the current GPS time)
+# TODO: need to fix this in the frame builder
+do {
+print $remote "gps;\n";
+read($remote, $resp, 24);
+read($remote, $gps, 4);
+$gps = unpack( 'N', $gps );
+#print "gps=$gps\n";
+} while ($gps <= 986074331);
+close $remote;
+return $gps;
+}
+
+# get data starting at (optional) $gps for $req_seconds (default 1 second)
+# for the channel $chname
+sub acquire {
+my ($chname, $req_seconds, $gps, $dtype) = @_;
+$dtype ||= "f";
+die "Need to connect first\n" unless defined $remote;
+die "Unspecified channel name\n" unless defined $chname;
+die "Bad channel name\n" unless defined $channels{$chname};
+$req_seconds = 1 if ! defined $req_seconds;
+
+#print "Acquiring $chname for $req_seconds from $gps\n";
+my $remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $DAQ::host, PeerPort => $DAQ::port);
+unless ($remote) { die "cannot connect to daqd on $DAQ::host:$DAQ::port" }
+$remote->autoflush(1);
+
+if (defined $gps && $gps > 0) {
+	print $remote "start net-writer $gps $req_seconds {\"$chname\"};\n";
+} else {
+	print $remote "start net-writer {\"$chname\"};\n";
+}
+#while ( <$remote> ) { print }
+#close $remote;
+
+#read($remote, $length. 4);
+#read($new_sock, $data, $length);
+
+
+# Initial responses "0000"
+read($remote, $resp, 4);
+#print $resp. "\n\n";
+read($remote, $resp, 4);
+#print $resp. "\n";
+read($remote, $resp, 4);
+#print $resp. "\n\n";
+
+my $len = 0;
+read($remote, $len, 4);
+$len = unpack( 'N', $len );
+#if ($len) { 
+#print "Getting offline data\n";
+#} else {
+#print "received 0 response (online data)\n";
+#}
+
+my $accum_seconds = 0;
+
+undef @result_array;
+while(read($remote, $len, 4)) {
+
+  $len = unpack( 'N', $len );
+  #print "$len\n";
+  read($remote, $seconds, 4);
+  $seconds = unpack( 'N', $seconds );
+  read($remote, $gps, 4);
+  $gps = unpack( 'N', $gps );
+  read($remote, $gps_n, 4);
+  $gps_n = unpack( 'N', $gps_n );
+  read($remote, $seq, 4);
+  $seq = unpack( 'N', $seq );
+  $len -= 16;
+  read($remote, $data, $len);
+  if ($gps == 0xffffffff) {
+	#reconfig block
+  } else {
+  	#print "gps=$gps; seconds=$seconds; gps_n=$gps_n; seq=$seq\n";
+  	#print "data length=$len\n";
+	@data_array = unpack( '(a4)*', $data );
+	my $as = @data_array;
+	#print $as, "\n";
+	for (@data_array) { $_ = unpack $dtype, reverse; }
+	#for (@data_array) { printf "%.1f ", $_; }
+	#print "\n";
+	push (@result_array, @data_array);
+	$accum_seconds += $seconds;
+	if ($accum_seconds >= $req_seconds) {last};
+  }
+}
+close $remote;
+return @result_array;
+}
+
+return 1;
diff --git a/src/perldaq/test.pl b/src/perldaq/test.pl
new file mode 100755
index 0000000000000000000000000000000000000000..9bbcfc55b22e9fc24c2a54ab00d5a6a79e9b80b0
--- /dev/null
+++ b/src/perldaq/test.pl
@@ -0,0 +1,37 @@
+#!/usr/bin/perl -w -I.
+
+# This script claculates an average of $mychan starting 5 seconds ago up till now
+
+require "daq.pm";
+
+#$mychan = "G1:ACO-TCE_SEIS_FF_X_OUT";
+#$mychan = "G1:GCO-FILTERSB1POS_OUT";
+#$mychan = "G1:GCO-AFTERMAT1X_IN1_DAQ";
+#$mychan = "G1:GCO-DELAYDDMOD1R_OUT_DAQ";
+$mychan = "H1:FE3-TIM32_T1_ADC_FILTER_5_OUT_DQ";
+# get the channel list
+DAQ::connect("x1nds0", 8088);
+#DAQ::print_channel();
+#DAQ::print_channel("C1:SUS-ETMY_OPLEV_SUM");
+
+# get current time
+$gps = DAQ::gps();
+
+#$gps -= 300;
+
+@data = DAQ::acquire($mychan, 3, 0, 'L');
+
+# calculate average on the data and print
+$avg = 0.0;
+$min = 0xffffffff + 0.0;
+$max = -0xffffffff + 0.0;
+$cnt = 0;
+for (@data) {
+	$cnt++;
+	printf "%.1f ", $_;
+	$avg += $_;
+	if ($_ < $min) { $min = $_; }
+	if ($_ > $max) { $max = $_; }
+}
+$avg /= $cnt;
+printf "at gps=$gps $mychan averaged %.5f for 3 seconds; min=%.5f; max=%.5f\n", $avg, $min, $max;
diff --git a/src/pub_sub_stream/plugins/sub_plugin_rmipc.cc b/src/pub_sub_stream/plugins/sub_plugin_rmipc.cc
index 9fe4bf54800953ffdb541300e58912d9cf66ff90..3e4bf2b930cb79b519c815585f9e868069b38b5b 100644
--- a/src/pub_sub_stream/plugins/sub_plugin_rmipc.cc
+++ b/src/pub_sub_stream/plugins/sub_plugin_rmipc.cc
@@ -27,9 +27,7 @@
 #include "drv/shmem.h"
 #include "modelrate.h"
 
-//#include "../../drv/crc.c"
-extern unsigned int crc_ptr( char*, unsigned int, unsigned int );
-extern unsigned int crc_len( unsigned int, unsigned int );
+#include "crc.h"
 
 namespace cps_plugins
 {
@@ -456,4 +454,4 @@ namespace cps_plugins
                                                      std::move( handler ) );
     }
 
-} // namespace cps_plugins
\ No newline at end of file
+} // namespace cps_plugins
diff --git a/src/rtcds/__init__.py b/src/rtcds/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/rtcds/__main__.py b/src/rtcds/__main__.py
deleted file mode 100644
index 329cc3ff2f700ae3d215cb5ead88122e1622a660..0000000000000000000000000000000000000000
--- a/src/rtcds/__main__.py
+++ /dev/null
@@ -1,61 +0,0 @@
-import os
-import logging
-
-
-ENV_FILE = os.getenv('RTS_ENV', '/etc/advligorts/env')
-
-USER_VARS = ['SITE', 'IFO', 'RCG_LIB_PATH']
-LIST_VARS = ['RTS_VERSION'] + USER_VARS + ['RCG_SRC', 'RCG_BUILD_ROOT', 'RCG_BUILDD', 'RCG_TARGET']
-EXPORT_VARS = USER_VARS + ['site', 'ifo', 'CDS_SRC', 'CDS_IFO_SRC']
-
-
-
-def check_env():
-    for var in USER_VARS:
-	if not os.getenv(var):
-	    raise ValueError(f"variable '{var}' not set.")
-    for var in LIST_VARS:
-	logging.info(f"{var}=${!var}")
-    for var in EXPORT_VARS:
-	#export $var
-        pass
-
-
-def prep_buildd():
-    if os.path.exists(RCG_BUILDD):
-        return
-    logging.info(f"creating RCG_BUILDD {RCG_BUILDD}...")
-    if ! mkdir -p "$RCG_BUILDD" 2>/dev/null ; then
-        log "Could not create build directory '$RCG_BUILDD'."
-        log "Please create manually (with correct permissions) and try again."
-        exit 1
-    fi
-    log "configuring RCG_BUILDD $RCG_BUILDD..."
-    cd "$RCG_BUILDD"
-    "$RCG_SRC"/configure
-
-
-def prep_target():
-    if os.path.exists(RCG_TARGET):
-        return
-    logging.info(f"creating RCG_TARGET {RCG_TARGET}...")
-    if ! mkdir -p "$RCG_TARGET" 2>/dev/null ; then
-        log "Could not create target directory '$RCG_TARGET'."
-        log "Please create manually (with correct permissions) and try again."
-        exit 1
-    fi
-    mkdir -p ${RCG_TARGET}/{target,chans/tmp}
-
-
-
-
-
-def main():
-
-
-
-    if error:
-	logging.error(f"The following environment variables must be set (in e.g. {ENV_FILE}:")
-	for var in USER_VARS:
-	    logging.error(f"  {var}")
-	    raise ValueError
diff --git a/src/rtcds/fe_generator/README.md b/src/rtcds/fe_generator/README.md
deleted file mode 100644
index 3b653b3497541286287de541a5bef54559ef2315..0000000000000000000000000000000000000000
--- a/src/rtcds/fe_generator/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Systemd generator that creates units at server boot for automatically starting models and other front end services.
diff --git a/src/rtcds/fe_generator/__init__.py b/src/rtcds/fe_generator/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/rtcds/fe_generator/__main__.py b/src/rtcds/fe_generator/__main__.py
deleted file mode 100755
index a5529d7fc61275cdf4d6abb718e77b69202fba79..0000000000000000000000000000000000000000
--- a/src/rtcds/fe_generator/__main__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python3
-
-# Generate systemd unit files needed for LIGO CDS front-end
-# server startup sequences
-
-from rtcds.fe_generator.sequencer import Sequencer
-from rtcds.fe_generator.options import get_options
-import sys
-from rtcds.fe_generator.log import klog
-
-
-if __name__ == '__main__':
-    klog(f"in python with args {sys.argv}")
-    seq = Sequencer(get_options(), sys.argv[2])
-    klog(f"Sequencer created")
-    seq.create_start_sequence()
-    klog(f"sequence complete")
diff --git a/src/rtcds/fe_generator/cdsrfm.py b/src/rtcds/fe_generator/cdsrfm.py
deleted file mode 100644
index 99aeaf7f4ec128ddb3c981e420cc434f93defc03..0000000000000000000000000000000000000000
--- a/src/rtcds/fe_generator/cdsrfm.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from .front_end import Process
-
-
-class CDSRFMProcesses(object):
-    def __init__(self, target_dir):
-        self.target_dir = target_dir
-
-    @staticmethod
-    def epics():
-        return Process("rts-cdsrfm-epics.service", "rts-cdsrfm-epics.service")
-
-    @staticmethod
-    def module():
-        return Process("rts-cdsrfm-module.service", "rts-cdsrfm-module.service")
diff --git a/src/rtcds/fe_generator/fe_generator b/src/rtcds/fe_generator/fe_generator
deleted file mode 100755
index 87c808a5af665da21e3a1cbc2d21dfb3d68bbea2..0000000000000000000000000000000000000000
--- a/src/rtcds/fe_generator/fe_generator
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-source /etc/advligorts/env
-
-# export all variables in between set -a and set +a
-set -a
-source /etc/advligorts/systemd_env
-source /etc/advligorts/systemd_env_`hostname`
-set +a
-
-python3 -m rtcds.fe_generator $@
diff --git a/src/rtcds/fe_generator/front_end.py b/src/rtcds/fe_generator/front_end.py
deleted file mode 100644
index 044df7b4dd11b074f9b4f8eeb7bfbb9e1f981a1f..0000000000000000000000000000000000000000
--- a/src/rtcds/fe_generator/front_end.py
+++ /dev/null
@@ -1,281 +0,0 @@
-# Setup the various processes for the front end startup
-
-import os
-import os.path as path
-
-gen_disclaimer = "# Created by systemd cds_frontend 'fe_generator'\n"
-
-
-class Process(object):
-    def __init__(self, start, end, first_service=None):
-        self.start = start
-        self.end = end
-        if first_service is None:
-            self.first_service = start
-        else:
-            self.first_service = first_service
-
-
-class FrontEndProcesses(object):
-    def __init__(self, target_dir):
-        self.target_dir = target_dir
-
-    def models(self):
-        target_name = path.join(self.target_dir, "rts-models.target")
-        with open(target_name, "wt") as f:
-            f.write(gen_disclaimer)
-            f.write("""[Unit]
-Description=All models            
-""")
-
-    @staticmethod
-    def dolphin_port():
-        return Process('rts-dolphin-port.service', 'rts-dolphin-port.service')
-
-    def dolphin_drivers(self):
-        # link up from one to the next
-        targ_name = "rts-dolphin-driver.target"
-        targ_path = path.join(self.target_dir, targ_name)
-        services = ['dis_kosif.service', 'dis_ix.service', 'dis_irm.service', 'dis_sisci.service',
-                    'dis_nodemgr.service']
-
-        with open(targ_path, "wt") as f:
-            f.write(gen_disclaimer)
-            f.write(f"""[Unit]
-Description=Dolphin IX drivers
-Wants={" ".join(services)}""")
-
-        self.serialize_units(services)
-        self.bind_units(services)
-
-        for service in services:
-            self.part_of(service, targ_name)
-
-        return Process(targ_name, 'dis_nodemgr.service', 'dis_kosif.service',)
-
-    def epics_only_models(self, models):
-        services = [f"rts-epics@{model}.service" for model in models]
-
-        target_name = "rts-epics-only-models.target"
-        target_path = path.join(self.target_dir, target_name)
-        with open(target_path, "wt") as f:
-            f.write(gen_disclaimer)
-            f.write(f"""[Unit]
-Description=All epics only models
-Wants={" ".join(services)}            
-""")
-
-        self.serialize_units(services)
-        for service in services:
-            self.part_of(service, target_name)
-
-        self.link_to(target_name, "rts-models.target")
-        self.part_of(target_name, "rts-models.target")
-
-        return Process(target_name, services[-1], services[0])
-
-    def iop_model(self, model, bind_to_dolphin=True):
-        """
-        Link up various services for the IOP model.
-        If bind_to_dolphin is true, link the iop to the appropriate dolphin service
-        """
-        target_path = path.join(self.target_dir, "rts-iop-model.target")
-        with open(target_path, "wt") as f:
-            f.write(gen_disclaimer)
-            f.write(f"""[Unit]
-Description=The IPO model.    
-Wants=rts@{model}.target                    
-""")
-
-        self.part_of(f"rts@{model}.target", "rts-iop-model.target")
-
-        self.link_to("rts-iop-model.target", "rts-models.target")
-        self.part_of("rts-iop-model.target", "rts-models.target")
-
-        if bind_to_dolphin:
-            self.after(f"rts-module@{model}.service", "dis_nodemgr.service")
-            self.requires(f"rts-module@{model}.service", "dis_nodemgr.service")
-
-        return Process(f"rts-iop-model.target", f"rts-awgtpman@{model}.service",
-                       f"rts-epics@{model}.service")
-
-    def user_models(self, models, iop_model):
-        target_name = "rts-user-models.target"
-        target_path = path.join(self.target_dir, target_name)
-        with open(target_path, "wt") as f:
-            f.write(gen_disclaimer)
-            f.write("""[Unit]
-Description=All user models            
-""")
-
-        services = []
-        for model in models:
-            services += [f"rts-epics@{model}.service", f"rts-module@{model}.service",
-                         f"rts-awgtpman@{model}.service"]
-
-        self.serialize_units(services)
-
-        for model in models:
-            self.link_to(f"rts@{model}.target", target_name)
-            self.part_of(f"rts@{model}.target", target_name)
-
-            #make sure iop is running before running any user models
-            self.requires(f"rts-epics@{model}.service", f"rts-module@{iop_model}.service")
-            self.after(f"rts-epics@{model}.service", f"rts-module@{iop_model}.service")
-            self.binds_to(f"rts-module@{model}.service", f"rts-module@{iop_model}.service")
-            self.after(f"rts-module@{model}.service", f"rts-module@{iop_model}.service")
-
-        self.link_to(target_name, "rts-models.target")
-        self.part_of(target_name, "rts-models.target")
-
-        return Process(f"rts-user-models.target", services[-1],
-                       services[0])
-
-    def edcs(self, edcs):
-        """
-        Takes a list of edc names and returns a Process object that can be used to start them all.
-        """
-        services = [f"rts-edc_{edc}.service" for edc in edcs]
-        self.serialize_units(services)
-        return Process(services[0], services[-1])
-
-    def streaming(self, options):
-        # check transport specifier exists
-        ts = 'transport_specifier'
-        if not (ts in options and options[ts]):
-            raise Exception(f"option '{ts}' must be determined when reading options")
-
-        # set up port
-        network_dir = "/run/systemd/network"
-        os.makedirs(network_dir, exist_ok=True)
-        fpath = path.join(network_dir, "rts-daq.network")
-        with open(fpath, "wt") as f:
-            f.write(gen_disclaimer)
-            f.write(f"""[Match]
-Name={options['DAQ_ETH_DEV']}
-
-[Link]
-MTUBytes=9000
-
-[Network]
-Description=Interface for streaming data to the DAQ
-Address={options['DAQ_ETH_IP']}
-""")
-
-        # setup services
-        services = ["rts-local_dc.service", f"rts-transport@{options[ts]}.service"]
-        self.serialize_units(services)
-
-        # setup target
-        targ_unit_name = "rts-transport.target"
-        targ_path = path.join(self.target_dir, targ_unit_name)
-        with open(targ_path, "wt") as f:
-            f.write(gen_disclaimer)
-            f.write(f"""[Unit]
-Description=Start transport of data to DAQ
-Wants={" ".join(services)} 
-""")
-
-        for service in services:
-            self.link_to(service, targ_unit_name)
-            self.part_of(service, targ_unit_name)
-
-        return Process(targ_unit_name, services[-1], services[0])
-
-    def serialize_units(self, services):
-        """
-        Take a list of systemd unit names and put one after the other.
-        """
-        for i in range(1, len(services)):
-            self.after(services[i], services[i-1])
-
-    def bind_units(self, services):
-        """
-        Take a list of systemd units and bind them together, with second
-        bound to the first, third bound to the second etc.
-        """
-        for i in range(1, len(services)):
-            self.binds_to(services[i], services[i-1])
-
-    def serialize_processes(self, processes):
-        """
-        Take a list of processes and put one after the other
-        """
-        for i in range(1, len(processes)):
-            self.after(processes[i].first_service, processes[i-1].end)
-
-    def create_world_target(self):
-        with open(path.join(self.target_dir, "rts-world.target"), "wt") as world:
-            world.write(gen_disclaimer)
-            world.write("""[Unit]
-Description=All model and streaming services for Front End servers
-
-[Install]
-WantedBy=multi-user.target
-""")
-
-    def link_to(self, unit_name, target_name):
-        """
-        Makes systemd unit unit_name wanted by target_name
-
-        :return:
-        """
-        override_path = path.join(self.target_dir, f"{target_name}.d")
-        os.makedirs(override_path, exist_ok=True)
-        conf_path = path.join(override_path, f"wants_{unit_name}.conf")
-        with open(conf_path, "wt") as f:
-            f.write(gen_disclaimer)
-            f.write(f"""[Unit]
-Wants={unit_name}""")
-
-    def part_of(self, unit_name, parent_name):
-        """
-        Make unit_name a part of parent_name, so that when parent_name is stopped, unit_name is as well.
-        """
-        unit_d = path.join(self.target_dir, f"{unit_name}.d")
-        os.makedirs(unit_d, exist_ok=True)
-        fname = path.join(unit_d, f"part_of_{parent_name}.conf")
-        with open(fname, "wt") as conf:
-            conf.write(gen_disclaimer)
-            conf.write(f"""[Unit]
-PartOf={parent_name}
-""")
-
-    def after(self, after_name, before_name):
-        """
-        Make the systemd unit after_name start after before_name is finished
-        """
-        after_d = path.join(self.target_dir, f"{after_name}.d")
-        os.makedirs(after_d, exist_ok=True)
-        fname = path.join(after_d, f"after_{before_name}.conf")
-        with open(fname, "wt") as conf:
-            conf.write(gen_disclaimer)
-            conf.write(f"""[Unit]
-After={before_name}
-""")
-
-    def requires(self, after_name, before_name):
-        """
-        Make the systemd unit after_name require before_name is finished
-        """
-        after_d = path.join(self.target_dir, f"{after_name}.d")
-        os.makedirs(after_d, exist_ok=True)
-        fname = path.join(after_d, f"require_{before_name}.conf")
-        with open(fname, "wt") as conf:
-            conf.write(gen_disclaimer)
-            conf.write(f"""[Unit]
-Requires={before_name}
-""")
-
-    def binds_to(self, after_name, before_name):
-        """
-        Make the systemd unit after_name require before_name is finished
-        """
-        after_d = path.join(self.target_dir, f"{after_name}.d")
-        os.makedirs(after_d, exist_ok=True)
-        fname = path.join(after_d, f"bindsto_{before_name}.conf")
-        with open(fname, "wt") as conf:
-            conf.write(gen_disclaimer)
-            conf.write(f"""[Unit]
-BindsTo={before_name}
-""")
diff --git a/src/rtcds/fe_generator/log.py b/src/rtcds/fe_generator/log.py
deleted file mode 100644
index 80d772959c2ddf1c1d5a89dcd43eaab8e8fbb20b..0000000000000000000000000000000000000000
--- a/src/rtcds/fe_generator/log.py
+++ /dev/null
@@ -1,3 +0,0 @@
-def klog(line):
-    with open("/dev/kmsg","wt") as f:
-        f.write(f"fe_generator: {line}\n")
diff --git a/src/rtcds/fe_generator/options.py b/src/rtcds/fe_generator/options.py
deleted file mode 100644
index d5ff111589cd3a474910679e858daeb33e94b110..0000000000000000000000000000000000000000
--- a/src/rtcds/fe_generator/options.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# gather options for generating systemd units
-import os
-import os.path as path
-
-
-def split(s):
-    """Split a string on whitespace"""
-    return s.split()
-
-
-def boolean(s):
-    """Convert a string into True or False.
-    Return true only if first character is a 'T' of either case"""
-    return s[0] == "t" or s[0] == "T"
-
-
-class Variable(object):
-    def __init__(self, convert, default=None):
-        self.convert = convert
-        self.default = default
-
-
-# net every expected variable is set up here, only those that need translation from a string
-# or need a default value
-variables = {
-    'IOP_MODEL': Variable(str, None),
-    'USER_MODELS': Variable(split, default=[]),
-    'EPICS_ONLY_MODELS': Variable(split, default=[]),
-    'EDC': Variable(split, default=[]),
-    'IS_DOLPHIN_NODE': Variable(boolean, False),
-    'DAQ_STREAMING': Variable(boolean, False),
-    'CDSRFM': Variable(boolean, False),
-    'START_MODELS': Variable(boolean, False),
-}
-
-
-def get_options():
-    # first check /etc/advligorts/systemd_env.. files
-    options = {key: value for key,value in os.environ.items()}
-    host_name = os.uname()[1]
-
-
-    # also if rtsystab is available, prefer its unit list
-
-    read_rtsystab(f"/etc/rtsystab", options, host_name)
-
-    # process the options into right type, etc, and create a few that aren't to be found in the files
-    for name,var in variables.items():
-        if name in options:
-            options[name] = var.convert(options[name])
-        else:
-            options[name] = var.default
-
-    if options['IOP_MODEL'] in options['EPICS_ONLY_MODELS']:
-        options['IOP_MODEL'] = None
-
-    options['USER_MODELS'] = [m for m in options['USER_MODELS']
-                              if m not in options['EPICS_ONLY_MODELS']]
-
-    options['HAS_DOLPHIN_PORT'] = path.exists('/etc/dolphin_ix_port_ctl.sh')
-    options['HAS_EPICS_ONLY_MODELS'] = len(options['EPICS_ONLY_MODELS']) > 0
-    options['HAS_IOP_MODEL'] = options['IOP_MODEL'] is not None
-    options['HAS_USER_MODELS'] = len(options['USER_MODELS']) > 0
-
-    options['HAS_EDC'] = "EDC" in options and len(options["EDC"]) > 0
-
-    if 'cps_xmit_args' in options:
-        options['transport_specifier'] = 'cps_xmit'
-
-    return options
-
-
-def read_rtsystab(fname, options, host_name):
-    try:
-        with open(fname, "rt") as f:
-            for line_raw in f.readlines():
-                line = line_raw.strip()
-                if len(line) <= 0:
-                    continue
-                line = line.split('#')[0].strip()
-                if len(line) <= 0:
-                    continue
-                words = [word.strip() for word in line.split()]
-                if len(words) > 1 and words[0] == host_name:
-                    options["IOP_MODEL"] = words[1]
-                    options["USER_MODELS"] = " ".join(words[2:])
-                    return
-    except IOError:
-        pass
diff --git a/src/rtcds/fe_generator/sequencer.py b/src/rtcds/fe_generator/sequencer.py
deleted file mode 100644
index 0a80c990f2d96b2b8b8fd2b3aec4aeb1672edc1b..0000000000000000000000000000000000000000
--- a/src/rtcds/fe_generator/sequencer.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# Set the start sequence for front ends and other diskless systems
-
-from .front_end import FrontEndProcesses
-from .cdsrfm import CDSRFMProcesses
-import os.path as path
-from .log import klog
-
-
-class Sequencer(object):
-
-    def __init__(self, options, target_dir):
-        """options is a dictionary of host-specific key/value pairs that will determine what
-        elements are added to the start sequence
-
-        target_dir is the target directory for unit files
-        """
-        self.options = options
-        self.target_dir = target_dir
-        self.processes = FrontEndProcesses(target_dir)
-
-    def create_start_sequence(self):
-        if self.options["CDSRFM"]:
-            klog("is CDSRFM host")
-            before_world, world = self.create_cdsrfm_start_sequence(self.processes,
-                                                         CDSRFMProcesses(self.target_dir))
-        else:
-            klog("is standard front end host")
-            before_world, world = self.create_frontend_start_sequence()
-        self.link_sequence(before_world, world, self.options["START_MODELS"])
-
-    def create_frontend_start_sequence(self):
-        before_world = []
-        world = []
-        models = False
-        if self.options["IS_DOLPHIN_NODE"]:
-            dolphin_drivers = self.processes.dolphin_drivers()
-            if self.options["HAS_DOLPHIN_PORT"]:
-                dolphin_port = self.processes.dolphin_port()
-
-                # bind drivers to port control so that drivers automatically get disabled
-                # when port is closed
-                self.processes.binds_to(dolphin_drivers.first_service, dolphin_port.start)
-
-                before_world.append(dolphin_port)
-                before_world.append(self.delay(15, "dolphin_port"))
-            before_world.append(dolphin_drivers)
-            klog("dolphin drivers added")
-        before_world.append(self.delay(30, "startup"))
-        if self.options["HAS_EPICS_ONLY_MODELS"]:
-            world.append(self.processes.epics_only_models(self.options["EPICS_ONLY_MODELS"]))
-            models = True
-        if self.options["HAS_IOP_MODEL"]:
-            world.append(self.processes.iop_model(self.options["IOP_MODEL"],
-                                                  self.options["IS_DOLPHIN_NODE"]))
-            models = True
-        if self.options["HAS_EDC"]:
-            world.append(self.processes.edcs(self.options["EDC"]))
-        if self.options["DAQ_STREAMING"]:
-            world.append(self.processes.streaming(self.options))
-        if self.options["HAS_USER_MODELS"]:
-            if self.options["HAS_IOP_MODEL"]:
-                world.append(self.processes.user_models(self.options["USER_MODELS"],
-                                                        self.options["IOP_MODEL"]))
-                models = True
-            else:
-                klog("Can't have user models without an IOP model")
-        if models:
-            self.processes.models()
-        return before_world, world
-
-    def create_cdsrfm_start_sequence(self, front_end_processes, cdsrfm_processes):
-        before_world = [
-            front_end_processes.dolphin_port(),
-            self.delay(15, "dolphin_port"),
-            front_end_processes.dolphin_drivers(),
-            self.delay(30, "startup"),]
-        world = [
-            cdsrfm_processes.module(),
-            cdsrfm_processes.epics(),
-            ]
-        return before_world, world
-
-    def link_sequence(self, before_world, world, start_models):
-        self.processes.create_world_target()
-
-        # link the first of each process to multi-user or to the world target
-        for process in before_world:
-            self.processes.link_to(process.start, "multi-user.target")
-        for process in world:
-            self.processes.link_to(process.start, "rts-world.target")
-            self.processes.part_of(process.start, "rts-world.target")
-        if len(before_world) > 0:
-            self.processes.after("rts-world.target", before_world[-1].end)
-        if start_models:
-            self.processes.link_to("rts-world.target", "multi-user.target")
-        else:
-            klog("START_MODELS is false.  Skipping model start.")
-        self.processes.serialize_processes(before_world + world)
-
-    class Delay(object):
-        def __init__(self, unit_name):
-            self.start = unit_name
-            self.end = unit_name
-            self.first_service = unit_name
-
-    def delay(self, time_s, name):
-        file_name = f"rts-delay-{name}.service"
-        file_path = path.join(self.target_dir, file_name)
-        with open(file_path, "wt") as f:
-            f.write(f"""[Unit]
-Description=Delay for {time_s} seconds
-
-[Service]
-ExecStartPre=/bin/sleep {time_s}
-ExecStart=/bin/echo 'finished waiting for {name}'
-""")
-        return self.Delay(file_name)
diff --git a/src/shmem/shmem_all.h b/src/shmem/shmem_all.h
index 6c12bef8a899378bdc9c844f96fed657b62d6b6f..812244a048c7291674ef97e88eeeb2916b6a7759 100644
--- a/src/shmem/shmem_all.h
+++ b/src/shmem/shmem_all.h
@@ -5,6 +5,7 @@
 #ifndef DAQD_TRUNK_SHMEM_ALL_H
 #define DAQD_TRUNK_SHMEM_ALL_H
 
+#include "shmem_epics.h"
 #include "shmem_awg.h"
 #include "shmem_iomem.h"
 #include "shmem_testpoint.h"
diff --git a/src/shmem/shmem_epics.h b/src/shmem/shmem_epics.h
new file mode 100644
index 0000000000000000000000000000000000000000..045b12cfca728238c0683613c33dfa4ab8f7772b
--- /dev/null
+++ b/src/shmem/shmem_epics.h
@@ -0,0 +1,9 @@
+#ifndef SHMEM_EPICS_H
+#define SHMEM_EPICS_H
+
+#define SHMEM_EPICS_SUFFIX ""
+#define SHMEM_EPICS_SIZE_MB 64
+#define SHMEM_EPICS_SIZE ( SHMEM_EPICS_SIZE_MB * ( 1024 ) * ( 1024 ) )
+
+#endif // SHMEM_EPICS_H
+
diff --git a/src/shmem/shmem_header.h b/src/shmem/shmem_header.h
index 5a220ad0352dddeaca8a3baad966f119867f119f..d3dd8a433b96a1427d2e0e27b8a1884c123295ba 100644
--- a/src/shmem/shmem_header.h
+++ b/src/shmem/shmem_header.h
@@ -5,6 +5,12 @@
 #ifndef DAQD_TRUNK_SHMEM_HEADER_H
 #define DAQD_TRUNK_SHMEM_HEADER_H
 
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+
 // header to suppport version control for shared memory structures.
 typedef struct SHMEM_HEADER
 {
diff --git a/src/shmem/shmem_testpoint.h b/src/shmem/shmem_testpoint.h
index 73c22e6832a824dddbde7f3655497271c1124422..5b3c19531b5e37ca5913e3711c54a07c478bf213 100644
--- a/src/shmem/shmem_testpoint.h
+++ b/src/shmem/shmem_testpoint.h
@@ -11,7 +11,7 @@
 // it's overloaded with some other uses, such as controlling awg slots.
 #define SHMEM_TESTPOINT_SUFFIX "_tp"
 #define SHMEM_TESTPOINT_SIZE_MB 1
-#define SHMEM_TESTPOINT_SIZE (SHMEM_AWG_SIZE_MB * 1024 * 1024 )
+#define SHMEM_TESTPOINT_SIZE (SHMEM_TESTPOINT_SIZE_MB * 1024 * 1024 )
 
 #define SHMEM_TESTPOINT_STRUCT TESTPOINT_CFG
 
diff --git a/src/simple_pv/CMakeLists.txt b/src/simple_pv/CMakeLists.txt
index 4a52fdc520d5df5f690f05e67a585550ee757137..130418a7c1176116cb0a67283e78f1b4a4c0e28c 100644
--- a/src/simple_pv/CMakeLists.txt
+++ b/src/simple_pv/CMakeLists.txt
@@ -1,7 +1,8 @@
 add_library(simple_pv simple_pv.cc
         simple_epics.cc
-        simple_epics_internal.cc)
+        simple_pv_internal.cc)
 target_include_directories(simple_pv PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+target_include_directories(simple_pv PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/private)
 target_link_libraries(simple_pv PUBLIC epics::cas epics::gdd /usr/lib/epics/lib/linux-x86_64/libCom.so)
 target_requires_cpp11(simple_pv PUBLIC)
 add_library(pv::simple_pv ALIAS simple_pv)
@@ -9,3 +10,6 @@ add_library(pv::simple_pv ALIAS simple_pv)
 add_executable(test_simple_pv tests/test_simple_pv.cc)
 target_link_libraries(test_simple_pv PUBLIC simple_pv)
 target_include_directories(test_simple_pv PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+
+add_executable(test_rw_ioc tests/test_rw_cas.cc)
+target_link_libraries(test_rw_ioc PUBLIC simple_pv)
\ No newline at end of file
diff --git a/src/simple_pv/private/simple_pv_int.hh b/src/simple_pv/private/simple_pv_int.hh
new file mode 100644
index 0000000000000000000000000000000000000000..ef7df71519162b4811b8fc4b051e307e3a74a85c
--- /dev/null
+++ b/src/simple_pv/private/simple_pv_int.hh
@@ -0,0 +1,286 @@
+//
+// Created by jonathan.hanks on 3/16/22.
+//
+
+#ifndef DAQD_TRUNK_SIMPLE_EPICS_INTERNAL_INT_HH
+#define DAQD_TRUNK_SIMPLE_EPICS_INTERNAL_INT_HH
+
+#include "simple_pv_types.hh"
+#include "simple_pv_internal.hh"
+#include <mutex>
+#include <type_traits>
+
+#include <iostream>
+
+namespace simple_epics
+{
+
+    namespace detail
+    {
+
+        /*!
+         * @brief A representation of a R/O integer in a PV
+         */
+        template < typename IntType >
+        class simpleBasicIntPV : public simplePVBase
+        {
+            static_assert( std::is_integral< IntType >::value,
+                           "Must use an interger type" );
+
+        public:
+            simpleBasicIntPV( caServer&                       server,
+                              pvBasicIntAttributes< IntType > attr )
+                : simplePVBase( ), server_{ server }, attr_{ std::move(
+                                                          attr ) },
+                  val_( ), monitored_{ false }
+            {
+                std::once_flag initted{ };
+                std::call_once(
+                    initted, []( ) { simpleBasicIntPV::setup_func_table( ); } );
+
+                val_ = new gddScalar( gddAppType_value,
+                                      ait_data_type< IntType >::value );
+                val_->unreference( );
+                set_value( *attr_.src( ) );
+            }
+            ~simpleBasicIntPV( ) override = default;
+
+            caStatus
+            read( const casCtx& ctx, gdd& prototype ) override
+            {
+                return get_func_table( ).read( *this, prototype );
+            }
+            caStatus
+            write( const casCtx& ctx, const gdd& value ) override
+            {
+                if ( attr_.mode( ) != PVMode::ReadWrite )
+                {
+                    return S_casApp_noSupport;
+                }
+                aitType newValue;
+                value.get( &newValue, ait_data_type< IntType >::value );
+                set_value( newValue );
+                *const_cast< IntType* >( attr_.src( ) ) = newValue;
+                return S_casApp_success;
+            }
+
+            void destroy( ) override{ };
+
+            aitEnum
+            bestExternalType( ) const override
+            {
+                return val_->primitiveType( );
+            }
+
+            const char*
+            getName( ) const override
+            {
+                return attr_.name( ).c_str( );
+            }
+
+            caStatus
+            interestRegister( ) override
+            {
+                monitored_ = true;
+                return S_casApp_success;
+            }
+
+            void
+            interestDelete( ) override
+            {
+                monitored_ = false;
+            }
+
+            void
+            update( ) override
+            {
+                set_value( *attr_.src( ) );
+            }
+
+        private:
+            using aitType = typename ait_data_type< IntType >::ait_type;
+
+            void
+            set_value( aitType value )
+            {
+                aitType current_value = 0;
+
+                val_->getConvert( current_value );
+                if ( current_value == value )
+                {
+                    return;
+                }
+
+                val_->putConvert( value );
+                aitTimeStamp ts = aitTimeStamp( epicsTime::getCurrent( ) );
+                val_->setTimeStamp( &ts );
+
+                aitUint16 stat = epicsAlarmNone;
+                aitUint16 sevr = epicsSevNone;
+                if ( value >= attr_.alarm_high( ) )
+                {
+                    stat = epicsAlarmHiHi;
+                    sevr = epicsSevMajor;
+                }
+                else if ( value <= attr_.alarm_low( ) )
+                {
+                    stat = epicsAlarmLoLo;
+                    sevr = epicsSevMajor;
+                }
+                else if ( value >= attr_.warn_high( ) )
+                {
+                    stat = epicsAlarmHigh;
+                    sevr = epicsSevMinor;
+                }
+                else if ( value <= attr_.warn_low( ) )
+                {
+                    stat = epicsAlarmLow;
+                    sevr = epicsSevMinor;
+                }
+                val_->setSevr( sevr );
+                val_->setStat( stat );
+
+                if ( monitored_ )
+                {
+                    casEventMask mask =
+                        casEventMask( server_.valueEventMask( ) );
+                    bool alarm_changed = ( stat != val_->getStat( ) ||
+                                           sevr != val_->getSevr( ) );
+                    if ( alarm_changed )
+                    {
+                        mask |= server_.alarmEventMask( );
+                    }
+                    postEvent( mask, *val_ );
+                }
+            }
+
+            static void
+            setup_func_table( )
+            {
+                auto install = []( const char* name,
+                                   gddAppFuncTableStatus (
+                                       simpleBasicIntPV::*handler )( gdd& ) ) {
+                    gddAppFuncTableStatus status;
+
+                    //           char error_string[100];
+
+                    status = get_func_table( ).installReadFunc( name, handler );
+                    if ( status != S_gddAppFuncTable_Success )
+                    {
+                        //                errSymLookup(status, error_string,
+                        //                sizeof(error_string));
+                        //               throw std::runtime_error(error_string);
+                        throw std::runtime_error(
+                            "Unable to initialize pv lookup table" );
+                    }
+                };
+
+                install( "units", &simpleBasicIntPV::read_attr_not_handled );
+                install( "status", &simpleBasicIntPV::read_status );
+                install( "severity", &simpleBasicIntPV::read_severity );
+                install( "maxElements",
+                         &simpleBasicIntPV::read_attr_not_handled );
+                install( "precision", &simpleBasicIntPV::read_precision );
+                install( "alarmHigh", &simpleBasicIntPV::read_alarm_high );
+                install( "alarmLow", &simpleBasicIntPV::read_alarm_low );
+                install( "alarmHighWarning",
+                         &simpleBasicIntPV::read_warn_high );
+                install( "alarmLowWarning", &simpleBasicIntPV::read_warn_low );
+                install( "maxElements",
+                         &simpleBasicIntPV::read_attr_not_handled );
+                install( "graphicHigh",
+                         &simpleBasicIntPV::read_attr_not_handled );
+                install( "graphicLow",
+                         &simpleBasicIntPV::read_attr_not_handled );
+                install( "controlHigh",
+                         &simpleBasicIntPV::read_attr_not_handled );
+                install( "controlLow",
+                         &simpleBasicIntPV::read_attr_not_handled );
+                install( "enums", &simpleBasicIntPV::read_attr_not_handled );
+                install( "menuitem", &simpleBasicIntPV::read_attr_not_handled );
+                install( "timestamp",
+                         &simpleBasicIntPV::read_attr_not_handled );
+                install( "value", &simpleBasicIntPV::read_value );
+            }
+            static gddAppFuncTable< simpleBasicIntPV >&
+            get_func_table( )
+            {
+                static gddAppFuncTable< simpleBasicIntPV > func_table;
+                return func_table;
+            }
+
+            gddAppFuncTableStatus
+            read_attr_not_handled( gdd& g )
+            {
+                return S_casApp_success;
+            }
+
+            gddAppFuncTableStatus
+            read_status( gdd& g )
+            {
+                g.putConvert( val_->getStat( ) );
+                return S_casApp_success;
+            }
+
+            gddAppFuncTableStatus
+            read_severity( gdd& g )
+            {
+                g.putConvert( val_->getSevr( ) );
+                return S_casApp_success;
+            }
+
+            gddAppFuncTableStatus
+            read_precision( gdd& g )
+            {
+                g.putConvert( 0 );
+                return S_casApp_success;
+            }
+
+            gddAppFuncTableStatus
+            read_alarm_high( gdd& g )
+            {
+                g.putConvert( attr_.alarm_high( ) );
+                return S_casApp_success;
+            }
+
+            gddAppFuncTableStatus
+            read_alarm_low( gdd& g )
+            {
+                g.putConvert( attr_.alarm_low( ) );
+                return S_casApp_success;
+            }
+
+            gddAppFuncTableStatus
+            read_warn_high( gdd& g )
+            {
+                g.putConvert( attr_.warn_high( ) );
+                return S_casApp_success;
+            }
+
+            gddAppFuncTableStatus
+            read_warn_low( gdd& g )
+            {
+                g.putConvert( attr_.warn_low( ) );
+                return S_casApp_success;
+            }
+
+            gddAppFuncTableStatus
+            read_value( gdd& g )
+            {
+                auto status = gddApplicationTypeTable::app_table.smartCopy(
+                    &g, val_.get( ) );
+                return ( status ? S_cas_noConvert : S_casApp_success );
+            }
+
+            caServer&                       server_;
+            pvBasicIntAttributes< IntType > attr_;
+            smartGDDPointer                 val_;
+            bool                            monitored_;
+        };
+        using simpleIntPV = simpleBasicIntPV< std::int32_t >;
+        using simpleUIntPV = simpleBasicIntPV< std::uint32_t >;
+        using simpleUShortPV = simpleBasicIntPV< std::uint16_t >;
+    } // namespace detail
+} // namespace simple_epics
+
+#endif // DAQD_TRUNK_SIMPLE_EPICS_INTERNAL_INT_HH
diff --git a/src/simple_pv/simple_epics_internal.hh b/src/simple_pv/private/simple_pv_internal.hh
similarity index 69%
rename from src/simple_pv/simple_epics_internal.hh
rename to src/simple_pv/private/simple_pv_internal.hh
index f3adeb4eedfa9b400918c8788f349c35e45a1e29..0ad59337988cd104096b721f69a9e70c4e3401ee 100644
--- a/src/simple_pv/simple_epics_internal.hh
+++ b/src/simple_pv/private/simple_pv_internal.hh
@@ -1,19 +1,20 @@
 //
-// Created by jonathan.hanks on 1/6/20.
+// Created by jonathan.hanks on 3/16/22.
 //
 
 #ifndef DAQD_TRUNK_SIMPLE_PV_INTERNAL_HH
 #define DAQD_TRUNK_SIMPLE_PV_INTERNAL_HH
 
-#include "simple_epics.hh"
 #include <memory>
 
+#include "simple_epics.hh"
+#include "simple_pv_int.hh"
+
 namespace simple_epics
 {
 
     namespace detail
     {
-
         // std::make_unique didn't make it into C++11, so
         // to allow this to work in a pre C++14 world, we
         // provide a simple replacement.
@@ -36,80 +37,6 @@ namespace simple_epics
                 new T( std::forward< Ts >( params )... ) );
         }
 
-        class setup_int_pv_table;
-
-        /*!
-         * @brief A representation of a R/O integer in a PV
-         */
-        class simpleIntPV : public simplePVBase
-        {
-            friend class setup_int_pv_table;
-
-        public:
-            simpleIntPV( caServer& server, pvIntAttributes attr )
-                : simplePVBase( ), server_{ server }, attr_{ std::move(
-                                                          attr ) },
-                  val_( ), monitored_{ false }
-            {
-                val_ = new gddScalar( gddAppType_value, aitEnumInt32 );
-                val_->unreference( );
-                set_value( *attr_.src( ) );
-            }
-            ~simpleIntPV( ) override;
-
-            caStatus read( const casCtx& ctx, gdd& prototype ) override;
-            caStatus write( const casCtx& ctx, const gdd& value ) override;
-
-            void destroy( ) override{};
-
-            aitEnum bestExternalType( ) const override;
-
-            const char*
-            getName( ) const override
-            {
-                return attr_.name( ).c_str( );
-            }
-
-            caStatus interestRegister( ) override;
-
-            void interestDelete( ) override;
-
-            void update( ) override;
-
-        private:
-            void set_value( int value );
-
-            static void                            setup_func_table( );
-            static gddAppFuncTable< simpleIntPV >& get_func_table( );
-
-            gddAppFuncTableStatus
-            read_attr_not_handled( gdd& g )
-            {
-                return S_casApp_success;
-            }
-
-            gddAppFuncTableStatus read_status( gdd& g );
-
-            gddAppFuncTableStatus read_severity( gdd& g );
-
-            gddAppFuncTableStatus read_precision( gdd& g );
-
-            gddAppFuncTableStatus read_alarm_high( gdd& g );
-
-            gddAppFuncTableStatus read_alarm_low( gdd& g );
-
-            gddAppFuncTableStatus read_warn_high( gdd& g );
-
-            gddAppFuncTableStatus read_warn_low( gdd& g );
-
-            gddAppFuncTableStatus read_value( gdd& g );
-
-            caServer&       server_;
-            pvIntAttributes attr_;
-            smartGDDPointer val_;
-            bool            monitored_;
-        };
-
         class setup_string_pv_table;
         /*!
          * @brief A representation of a R/O integer in a PV
@@ -133,7 +60,7 @@ namespace simple_epics
             caStatus read( const casCtx& ctx, gdd& prototype ) override;
             caStatus write( const casCtx& ctx, const gdd& value ) override;
 
-            void destroy( ) override{};
+            void destroy( ) override{ };
 
             aitEnum bestExternalType( ) const override;
 
@@ -199,7 +126,7 @@ namespace simple_epics
             caStatus read( const casCtx& ctx, gdd& prototype ) override;
             caStatus write( const casCtx& ctx, const gdd& value ) override;
 
-            void destroy( ) override{};
+            void destroy( ) override{ };
 
             aitEnum bestExternalType( ) const override;
 
@@ -248,9 +175,7 @@ namespace simple_epics
             smartGDDPointer    val_;
             bool               monitored_;
         };
-
     } // namespace detail
-
 } // namespace simple_epics
 
 #endif // DAQD_TRUNK_SIMPLE_PV_INTERNAL_HH
diff --git a/src/simple_pv/private/simple_pv_types.hh b/src/simple_pv/private/simple_pv_types.hh
new file mode 100644
index 0000000000000000000000000000000000000000..4e698ab7cfd01e3b9320c3a31746f1730e90adf3
--- /dev/null
+++ b/src/simple_pv/private/simple_pv_types.hh
@@ -0,0 +1,97 @@
+//
+// Created by jonathan.hanks on 3/16/22.
+//
+
+#ifndef DAQD_TRUNK_SIMPLE_PV_TYPES_HH
+#define DAQD_TRUNK_SIMPLE_PV_TYPES_HH
+
+#include <cstdint>
+#include <string>
+#include <type_traits>
+#include "aitTypes.h"
+
+namespace simple_epics
+{
+    namespace detail
+    {
+        /**
+         * @brief ait_data_type is used to map between C++ types and the
+         * CAS ait (architecture independent) data types.
+         * @tparam T The type to map
+         */
+        template < typename T >
+        struct ait_data_type
+        {
+            static const aitEnum value = aitEnumInvalid;
+            using ait_type = void;
+        };
+
+        template <>
+        struct ait_data_type< std::int16_t >
+        {
+            static const aitEnum value = aitEnumInt16;
+            using ait_type = aitInt16;
+            static_assert( std::is_same< std::int16_t, ait_type >::value,
+                           "aitType and C++ types must match" );
+        };
+
+        template <>
+        struct ait_data_type< std::uint16_t >
+        {
+            static const aitEnum value = aitEnumUint16;
+            using ait_type = aitUint16;
+            static_assert( std::is_same< std::uint16_t, ait_type >::value,
+                           "aitType and C++ types must match" );
+        };
+
+        template <>
+        struct ait_data_type< std::int32_t >
+        {
+            static const aitEnum value = aitEnumInt32;
+            using ait_type = aitInt32;
+            static_assert( std::is_same< std::int32_t, ait_type >::value,
+                           "aitType and C++ types must match" );
+        };
+
+        template <>
+        struct ait_data_type< std::uint32_t >
+        {
+            static const aitEnum value = aitEnumUint32;
+            using ait_type = aitUint32;
+            static_assert( std::is_same< std::uint32_t, ait_type >::value,
+                           "aitType and C++ types must match" );
+        };
+
+        template <>
+        struct ait_data_type< float >
+        {
+            static const aitEnum value = aitEnumFloat32;
+            using ait_type = aitFloat32;
+            static_assert( std::is_same< float, ait_type >::value,
+                           "aitType and C++ types must match" );
+        };
+
+        template <>
+        struct ait_data_type< double >
+        {
+            static const aitEnum value = aitEnumFloat64;
+            using ait_type = aitFloat64;
+            static_assert( std::is_same< double, ait_type >::value,
+                           "aitType and C++ types must match" );
+        };
+
+        template <>
+        struct ait_data_type< const char* >
+        {
+            static const aitEnum value = aitEnumString;
+        };
+
+        template <>
+        struct ait_data_type< std::string >
+        {
+            static const aitEnum value = aitEnumString;
+        };
+    } // namespace detail
+} // namespace simple_epics
+
+#endif // DAQD_TRUNK_SIMPLE_PV_TYPES_HH
diff --git a/src/simple_pv/simple_epics.cc b/src/simple_pv/simple_epics.cc
index dbce6e75f4b5656c6a30e09c8e66f607983f9ec0..3f6de43397f4144c42949deeb3248adf4f77d508 100644
--- a/src/simple_pv/simple_epics.cc
+++ b/src/simple_pv/simple_epics.cc
@@ -2,7 +2,7 @@
 // Created by jonathan.hanks on 12/20/19.
 //
 #include "simple_epics.hh"
-#include "simple_epics_internal.hh"
+#include "simple_pv_internal.hh"
 
 #include <stdexcept>
 #include <algorithm>
@@ -11,6 +11,24 @@ namespace simple_epics
 {
     Server::~Server( ) = default;
 
+    void
+    Server::addPV( pvUShortAttributes attr )
+    {
+        std::lock_guard< std::mutex > l_( m_ );
+
+        auto it = pvs_.find( attr.name( ) );
+        if ( it != pvs_.end( ) )
+        {
+            throw std::runtime_error(
+                "Duplicate key insertion to the epics db" );
+        }
+        std::string name{ attr.name( ) };
+        pvs_.insert(
+            std::make_pair( std::move( name ),
+                            detail::make_unique_ptr< detail::simpleUShortPV >(
+                                *this, std::move( attr ) ) ) );
+    }
+
     void
     Server::addPV( pvIntAttributes attr )
     {
@@ -29,6 +47,24 @@ namespace simple_epics
                                 *this, std::move( attr ) ) ) );
     }
 
+    void
+    Server::addPV( pvUIntAttributes attr )
+    {
+        std::lock_guard< std::mutex > l_( m_ );
+
+        auto it = pvs_.find( attr.name( ) );
+        if ( it != pvs_.end( ) )
+        {
+            throw std::runtime_error(
+                "Duplicate key insertion to the epics db" );
+        }
+        std::string name{ attr.name( ) };
+        pvs_.insert(
+            std::make_pair( std::move( name ),
+                            detail::make_unique_ptr< detail::simpleUIntPV >(
+                                *this, std::move( attr ) ) ) );
+    }
+
     void
     Server::addPV( pvStringAttributes attr )
     {
diff --git a/src/simple_pv/simple_epics.hh b/src/simple_pv/simple_epics.hh
index 2830457d85ade894cf65bac4b3b1f28325f528ac..c6a70ede3e8a3d824156a200a4636a33c91b1883 100644
--- a/src/simple_pv/simple_epics.hh
+++ b/src/simple_pv/simple_epics.hh
@@ -9,6 +9,7 @@
 #include <memory>
 #include <mutex>
 #include <string>
+#include <type_traits>
 #include <gddAppFuncTable.h>
 #include <epicsTimer.h>
 
@@ -36,69 +37,94 @@ namespace simple_epics
 
     class Server;
 
+    enum class PVMode
+    {
+        ReadOnly = 0,
+        ReadWrite = 1,
+    };
+
     /*!
      * @brief A description of a PV, used to describe an int PV to the server.
      * @note this is given a pointer to the data.  This value is only read
      * when a Server object is told to update its data.
      */
-    class pvIntAttributes
+    template < typename IntType >
+    class pvBasicIntAttributes
     {
+        static_assert( std::is_integral< IntType >::value,
+                       "integer type required" );
+
     public:
-        pvIntAttributes( std::string           pv_name,
-                         int*                  value,
-                         std::pair< int, int > alarm_range,
-                         std::pair< int, int > warn_range )
+        using value_type = IntType;
+
+        pvBasicIntAttributes( std::string                   pv_name,
+                              IntType*                      value,
+                              std::pair< IntType, IntType > alarm_range,
+                              std::pair< IntType, IntType > warn_range,
+                              PVMode mode = PVMode::ReadOnly )
             : name_{ std::move( pv_name ) },
 
               alarm_low_{ alarm_range.first },
               alarm_high_{ alarm_range.second }, warn_low_{ warn_range.first },
-              warn_high_{ warn_range.second }, src_{ value }
+              warn_high_{ warn_range.second }, mode_{ mode }, src_{ value }
         {
         }
 
         const std::string&
-        name( ) const
+        name( ) const noexcept
         {
             return name_;
         }
 
-        int
-        alarm_high( ) const
+        IntType
+        alarm_high( ) const noexcept
         {
             return alarm_high_;
         }
-        int
-        alarm_low( ) const
+        IntType
+        alarm_low( ) const noexcept
         {
             return alarm_low_;
         }
-        int
-        warn_high( ) const
+        IntType
+        warn_high( ) const noexcept
         {
             return warn_high_;
         }
-        int
-        warn_low( ) const
+        IntType
+        warn_low( ) const noexcept
         {
             return warn_low_;
         }
 
-        const int*
-        src( ) const
+        const IntType*
+        src( ) const noexcept
         {
             return src_;
         }
 
+        PVMode
+        mode( ) const noexcept
+        {
+            return mode_;
+        }
+
     private:
         std::string name_;
 
-        int alarm_high_;
-        int alarm_low_;
-        int warn_high_;
-        int warn_low_;
+        IntType alarm_high_;
+        IntType alarm_low_;
+        IntType warn_high_;
+        IntType warn_low_;
 
-        int* src_;
+        PVMode   mode_;
+        IntType* src_{ nullptr };
     };
+    using pvIntAttributes = pvBasicIntAttributes< std::int32_t >;
+    using pvUIntAttributes = pvBasicIntAttributes< std::uint32_t >;
+    using pvUShortAttributes = pvBasicIntAttributes< std::uint16_t >;
+    static_assert( sizeof( std::int32_t ) == sizeof( int ),
+                   "int must be 32 bit" );
 
     /*!
      * @brief A description of a PV, used to describe a string PV to the server.
@@ -108,27 +134,50 @@ namespace simple_epics
     class pvStringAttributes
     {
     public:
-        pvStringAttributes( std::string pv_name, const char* value )
-            : name_{ std::move( pv_name ) }, src_{ value }
+        pvStringAttributes( std::string pv_name,
+                            const char* value,
+                            PVMode      mode = PVMode::ReadOnly,
+                            std::size_t buffer_size = 0 )
+            : name_{ std::move( pv_name ) }, mode_{ mode }, src_{ value },
+              src_size_{ buffer_size }
         {
         }
 
         const std::string&
-        name( ) const
+        name( ) const noexcept
         {
             return name_;
         }
 
         const char*
-        src( ) const
+        src( ) const noexcept
         {
             return src_;
         }
 
+        char*
+        src( ) noexcept
+        {
+            return (char*)src_;
+        }
+
+        std::size_t
+        src_size( ) const noexcept
+        {
+            return src_size_;
+        }
+
+        PVMode
+        mode( ) const noexcept
+        {
+            return mode_;
+        }
+
     private:
         std::string name_;
-
+        PVMode      mode_;
         const char* src_;
+        std::size_t src_size_;
     };
 
     /*!
@@ -142,48 +191,55 @@ namespace simple_epics
         pvDoubleAttributes( std::string                 pv_name,
                             double*                     value,
                             std::pair< double, double > alarm_range,
-                            std::pair< double, double > warn_range )
+                            std::pair< double, double > warn_range,
+                            PVMode mode = PVMode::ReadOnly )
             : name_{ std::move( pv_name ) },
 
               alarm_low_{ alarm_range.first },
               alarm_high_{ alarm_range.second }, warn_low_{ warn_range.first },
-              warn_high_{ warn_range.second }, src_{ value }
+              warn_high_{ warn_range.second }, mode_{ mode }, src_{ value }
         {
         }
 
         const std::string&
-        name( ) const
+        name( ) const noexcept
         {
             return name_;
         }
 
         double
-        alarm_high( ) const
+        alarm_high( ) const noexcept
         {
             return alarm_high_;
         }
         double
-        alarm_low( ) const
+        alarm_low( ) const noexcept
         {
             return alarm_low_;
         }
         double
-        warn_high( ) const
+        warn_high( ) const noexcept
         {
             return warn_high_;
         }
         double
-        warn_low( ) const
+        warn_low( ) const noexcept
         {
             return warn_low_;
         }
 
         const double*
-        src( ) const
+        src( ) const noexcept
         {
             return src_;
         }
 
+        PVMode
+        mode( ) const noexcept
+        {
+            return mode_;
+        }
+
     private:
         std::string name_;
 
@@ -192,7 +248,9 @@ namespace simple_epics
         double warn_high_;
         double warn_low_;
 
-        double* src_;
+        PVMode mode_;
+
+        double* src_{ nullptr };
     };
 
     /*!
@@ -201,7 +259,7 @@ namespace simple_epics
     class Server : public caServer
     {
     public:
-        Server( ) : caServer( ), pvs_{}
+        Server( ) : caServer( ), pvs_{ }
         {
         }
         ~Server( ) override;
@@ -209,7 +267,9 @@ namespace simple_epics
         /*!
          * @brief Add a PV to the server.
          */
+        void addPV( pvUShortAttributes attr );
         void addPV( pvIntAttributes attr );
+        void addPV( pvUIntAttributes attr );
         void addPV( pvStringAttributes attr );
         void addPV( pvDoubleAttributes attr );
 
diff --git a/src/simple_pv/simple_pv.cc b/src/simple_pv/simple_pv.cc
index 7ab5c2b729a59dea61e94a3d77846938063c3d15..bffe8c2a2c90e37e4131b6d4d6fcdac3327221fa 100644
--- a/src/simple_pv/simple_pv.cc
+++ b/src/simple_pv/simple_pv.cc
@@ -3,7 +3,7 @@
 //
 #include "simple_pv.h"
 #include "simple_epics.hh"
-#include "simple_epics_internal.hh"
+#include "simple_pv_internal.hh"
 
 #include <algorithm>
 #include <memory>
@@ -29,15 +29,14 @@ simple_pv_server_create( const char* prefix, SimplePV* pvs, int pv_count )
     std::for_each(
         pvs,
         pvs + pv_count,
-        [&prefix_, pv_server]( const SimplePV& pv ) -> void {
+        [ &prefix_, pv_server ]( const SimplePV& pv ) -> void {
             if ( !pv.name || !pv.data )
             {
                 return;
             }
             switch ( pv.pv_type )
             {
-            case SIMPLE_PV_INT:
-            {
+            case SIMPLE_PV_INT: {
                 pv_server->addPV( simple_epics::pvIntAttributes(
                     prefix_ + pv.name,
                     reinterpret_cast< int* >( pv.data ),
@@ -45,14 +44,12 @@ simple_pv_server_create( const char* prefix, SimplePV* pvs, int pv_count )
                     std::make_pair< int, int >( pv.warn_low, pv.warn_high ) ) );
             }
             break;
-            case SIMPLE_PV_STRING:
-            {
+            case SIMPLE_PV_STRING: {
                 pv_server->addPV( simple_epics::pvStringAttributes(
                     prefix_ + pv.name, reinterpret_cast< char* >( pv.data ) ) );
             }
             break;
-            case SIMPLE_PV_DOUBLE:
-            {
+            case SIMPLE_PV_DOUBLE: {
                 pv_server->addPV( simple_epics::pvDoubleAttributes(
                     prefix_ + pv.name,
                     reinterpret_cast< double* >( pv.data ),
diff --git a/src/simple_pv/simple_epics_internal.cc b/src/simple_pv/simple_pv_internal.cc
similarity index 64%
rename from src/simple_pv/simple_epics_internal.cc
rename to src/simple_pv/simple_pv_internal.cc
index 2bf9c4a17636319d2df670ce52d9c6d346dbe474..adf5909f8e30c7e9ecc3a0336f765a7726378ddf 100644
--- a/src/simple_pv/simple_epics_internal.cc
+++ b/src/simple_pv/simple_pv_internal.cc
@@ -1,24 +1,13 @@
 //
 // Created by jonathan.hanks on 1/6/20.
 //
-#include "simple_epics_internal.hh"
+#include "simple_pv_internal.hh"
 #include <cstring>
 
 namespace simple_epics
 {
     namespace detail
     {
-        class setup_int_pv_table
-        {
-        public:
-            setup_int_pv_table( )
-            {
-                simpleIntPV::setup_func_table( );
-            }
-        };
-
-        setup_int_pv_table pv_int_table_setup_;
-
         class setup_string_pv_table
         {
         public:
@@ -41,206 +30,6 @@ namespace simple_epics
 
         setup_double_pv_table pv_double_table_setup_;
 
-        /*
-         * Start of int PV
-         */
-
-        gddAppFuncTable< simpleIntPV >&
-        simpleIntPV::get_func_table( )
-        {
-            static gddAppFuncTable< simpleIntPV > func_table;
-            return func_table;
-        }
-
-        simpleIntPV::~simpleIntPV( ) = default;
-
-        gddAppFuncTableStatus
-        simpleIntPV::read_status( gdd& g )
-        {
-            g.putConvert( val_->getStat( ) );
-            return S_casApp_success;
-        }
-
-        gddAppFuncTableStatus
-        simpleIntPV::read_severity( gdd& g )
-        {
-            g.putConvert( val_->getSevr( ) );
-            return S_casApp_success;
-        }
-
-        gddAppFuncTableStatus
-        simpleIntPV::read_precision( gdd& g )
-        {
-            g.putConvert( 0 );
-            return S_casApp_success;
-        }
-
-        gddAppFuncTableStatus
-        simpleIntPV::read_alarm_high( gdd& g )
-        {
-            g.putConvert( attr_.alarm_high( ) );
-            return S_casApp_success;
-        }
-
-        gddAppFuncTableStatus
-        simpleIntPV::read_alarm_low( gdd& g )
-        {
-            g.putConvert( attr_.alarm_low( ) );
-            return S_casApp_success;
-        }
-
-        gddAppFuncTableStatus
-        simpleIntPV::read_warn_high( gdd& g )
-        {
-            g.putConvert( attr_.warn_high( ) );
-            return S_casApp_success;
-        }
-
-        gddAppFuncTableStatus
-        simpleIntPV::read_warn_low( gdd& g )
-        {
-            g.putConvert( attr_.warn_low( ) );
-            return S_casApp_success;
-        }
-
-        gddAppFuncTableStatus
-        simpleIntPV::read_value( gdd& g )
-        {
-            auto status =
-                gddApplicationTypeTable::app_table.smartCopy( &g, val_.get( ) );
-            return ( status ? S_cas_noConvert : S_casApp_success );
-        }
-
-        void
-        simpleIntPV::setup_func_table( )
-        {
-            auto install =
-                []( const char* name,
-                    gddAppFuncTableStatus ( simpleIntPV::*handler )( gdd& ) ) {
-                    gddAppFuncTableStatus status;
-
-                    //           char error_string[100];
-
-                    status = get_func_table( ).installReadFunc( name, handler );
-                    if ( status != S_gddAppFuncTable_Success )
-                    {
-                        //                errSymLookup(status, error_string,
-                        //                sizeof(error_string));
-                        //               throw std::runtime_error(error_string);
-                        throw std::runtime_error(
-                            "Unable to initialize pv lookup table" );
-                    }
-                };
-
-            install( "units", &simpleIntPV::read_attr_not_handled );
-            install( "status", &simpleIntPV::read_status );
-            install( "severity", &simpleIntPV::read_severity );
-            install( "maxElements", &simpleIntPV::read_attr_not_handled );
-            install( "precision", &simpleIntPV::read_precision );
-            install( "alarmHigh", &simpleIntPV::read_alarm_high );
-            install( "alarmLow", &simpleIntPV::read_alarm_low );
-            install( "alarmHighWarning", &simpleIntPV::read_warn_high );
-            install( "alarmLowWarning", &simpleIntPV::read_warn_low );
-            install( "maxElements", &simpleIntPV::read_attr_not_handled );
-            install( "graphicHigh", &simpleIntPV::read_attr_not_handled );
-            install( "graphicLow", &simpleIntPV::read_attr_not_handled );
-            install( "controlHigh", &simpleIntPV::read_attr_not_handled );
-            install( "controlLow", &simpleIntPV::read_attr_not_handled );
-            install( "enums", &simpleIntPV::read_attr_not_handled );
-            install( "menuitem", &simpleIntPV::read_attr_not_handled );
-            install( "timestamp", &simpleIntPV::read_attr_not_handled );
-            install( "value", &simpleIntPV::read_value );
-        }
-
-        caStatus
-        simpleIntPV::read( const casCtx& ctx, gdd& prototype )
-        {
-            return get_func_table( ).read( *this, prototype );
-        }
-        caStatus
-        simpleIntPV::write( const casCtx& ctx, const gdd& value )
-        {
-            return S_casApp_noSupport;
-        }
-
-        aitEnum
-        simpleIntPV::bestExternalType( ) const
-        {
-            return val_->primitiveType( );
-        }
-
-        caStatus
-        simpleIntPV::interestRegister( )
-        {
-            monitored_ = true;
-            return S_casApp_success;
-        }
-
-        void
-        simpleIntPV::interestDelete( )
-        {
-            monitored_ = false;
-        }
-
-        void
-        simpleIntPV::update( )
-        {
-            set_value( *attr_.src( ) );
-        }
-
-        void
-        simpleIntPV::set_value( int value )
-        {
-            int current_value = 0;
-
-            val_->getConvert( current_value );
-            if ( current_value == value )
-            {
-                return;
-            }
-
-            val_->putConvert( value );
-            aitTimeStamp ts = aitTimeStamp( epicsTime::getCurrent( ) );
-            val_->setTimeStamp( &ts );
-
-            aitUint16 stat = epicsAlarmNone;
-            aitUint16 sevr = epicsSevNone;
-            if ( value >= attr_.alarm_high( ) )
-            {
-                stat = epicsAlarmHiHi;
-                sevr = epicsSevMajor;
-            }
-            else if ( value <= attr_.alarm_low( ) )
-            {
-                stat = epicsAlarmLoLo;
-                sevr = epicsSevMajor;
-            }
-            else if ( value >= attr_.warn_high( ) )
-            {
-                stat = epicsAlarmHigh;
-                sevr = epicsSevMinor;
-            }
-            else if ( value <= attr_.warn_low( ) )
-            {
-                stat = epicsAlarmLow;
-                sevr = epicsSevMinor;
-            }
-            val_->setSevr( sevr );
-            val_->setStat( stat );
-
-            if ( monitored_ )
-            {
-                casEventMask mask = casEventMask( server_.valueEventMask( ) );
-                bool         alarm_changed =
-                    ( stat != val_->getStat( ) || sevr != val_->getSevr( ) );
-                if ( alarm_changed )
-                {
-                    mask |= server_.alarmEventMask( );
-                }
-                postEvent( mask, *val_ );
-            }
-        }
-
         /*
          * Start of string PV
          */
@@ -334,7 +123,20 @@ namespace simple_epics
         caStatus
         simpleStringPV::write( const casCtx& ctx, const gdd& value )
         {
-            return S_casApp_noSupport;
+            if ( attr_.mode( ) != PVMode::ReadWrite || attr_.src_size( ) < 1 )
+            {
+                return S_casApp_noSupport;
+            }
+            aitString newValue;
+            value.get( &newValue, aitEnumString );
+            if ( newValue.string( ) == nullptr )
+            {
+                return S_casApp_noSupport;
+            }
+            set_value( newValue.string( ) );
+            std::strncpy( attr_.src( ), newValue.string( ), attr_.src_size( ) );
+            attr_.src( )[ attr_.src_size( ) - 1 ] == '\0';
+            return S_casApp_success;
         }
 
         aitEnum
@@ -505,7 +307,15 @@ namespace simple_epics
         caStatus
         simpleDoublePV::write( const casCtx& ctx, const gdd& value )
         {
-            return S_casApp_noSupport;
+            if ( attr_.mode( ) != PVMode::ReadWrite )
+            {
+                return S_casApp_noSupport;
+            }
+            aitFloat64 newValue;
+            value.get( &newValue, aitEnumFloat64 );
+            set_value( newValue );
+            *const_cast< double* >( attr_.src( ) ) = newValue;
+            return S_casApp_success;
         }
 
         aitEnum
diff --git a/src/simple_pv/tests/test_rw_cas.cc b/src/simple_pv/tests/test_rw_cas.cc
new file mode 100644
index 0000000000000000000000000000000000000000..260eb80bcbb04f278be7f89c46d48a8571278c1e
--- /dev/null
+++ b/src/simple_pv/tests/test_rw_cas.cc
@@ -0,0 +1,52 @@
+//
+// Created by jonathan.hanks on 3/14/22.
+//
+#include "simple_epics.hh"
+#include <atomic>
+#include <csignal>
+
+#include "fdManager.h"
+
+std::atomic< bool > done{ false };
+
+void
+signal_handler( int dummy )
+{
+    done = true;
+}
+
+int
+main( int argc, char* argv[] )
+{
+    using pvInt = simple_epics::pvIntAttributes;
+    simple_epics::Server server{ };
+
+    int                              int1val = 0;
+    pvInt                            int1{ "int1",
+                &int1val,
+                std::make_pair( -1, 100 ),
+                std::make_pair( -1, 100 ),
+                simple_epics::PVMode::ReadWrite };
+    double                           float1val = 0.0;
+    simple_epics::pvDoubleAttributes float1{ "float1",
+                                             &float1val,
+                                             std::make_pair( -1, 100 ),
+                                             std::make_pair( -1, 100 ),
+                                             simple_epics::PVMode::ReadWrite };
+
+    server.addPV( int1 );
+    server.addPV( float1 );
+
+    std::signal( SIGINT, signal_handler );
+    server.update( );
+    while ( !done )
+    {
+        if ( int1val == 42 )
+        {
+            done = true;
+        }
+        server.update( );
+        fileDescriptorManager.process( 0. );
+    }
+    return 0;
+}
\ No newline at end of file
diff --git a/support/bin/rtcds.in b/support/bin/rtcds.in
index c656cfad0a17759c5da9fdc86861640de3462117..e61464684d1b39eb1b0fde3668333c625fb55e0d 100755
--- a/support/bin/rtcds.in
+++ b/support/bin/rtcds.in
@@ -35,7 +35,7 @@ RCG_BUILD_ROOT=${RCG_BUILD_ROOT:-/var/cache/advligorts}
 RCG_BUILDD=${RCG_BUILDD:-$RCG_BUILD_ROOT/rcg-$RTS_VERSION}
 # FIXME: the RCG hard-codes /opt/rtcds as the root, you can use a custom
 # RCG_TARGET for building only
-RCG_TARGET=${RCG_TARGET-"/opt/rtcds/${site}/${ifo}"}
+RCG_TARGET=${RCG_TARGET:-"/opt/rtcds/${site}/${ifo}"}
 
 # search paths for C source code
 CDS_SRC=${CDS_SRC:-$RCG_LIB_PATH}
diff --git a/support/bin/rts_awgtpman_exec b/support/bin/rts_awgtpman_exec
index 7e7753eee7b9ed78800ac77c6ae08a6c2e70e0a9..87428fe04918dfe6332d3654ea60328fae5c550b 100755
--- a/support/bin/rts_awgtpman_exec
+++ b/support/bin/rts_awgtpman_exec
@@ -1,5 +1,6 @@
 #!/bin/bash -e
-. /etc/advligorts/env
+rts_env=${RTS_ENV:-/etc/advligorts/env}
+. $rts_env
 sys="$1"
 if [ -z "$sys" ] ; then
     echo "usage: $(basename $0) <sys>" >&2
diff --git a/support/bin/rts_epics_exec b/support/bin/rts_epics_exec
index 8d65432a1d7eebd84cb1d3506db080d70fa6c015..657db2b31e329fedd19bd329ef96bec7b9a4bd06 100755
--- a/support/bin/rts_epics_exec
+++ b/support/bin/rts_epics_exec
@@ -1,5 +1,6 @@
 #!/bin/bash -e
-. /etc/advligorts/env
+rts_env=${RTS_ENV:-/etc/advligorts/env}
+. $rts_env
 sys="$1"
 if [ -z "$sys" ] ; then
     echo "usage: $(basename $0) <sys>" >&2
diff --git a/support/bin/rts_module_ctrl b/support/bin/rts_module_ctrl
index 53b36df955d494da74701f3ec600ac180f06028d..ca3508f350acf41114a1378360f1b38312bb16c5 100755
--- a/support/bin/rts_module_ctrl
+++ b/support/bin/rts_module_ctrl
@@ -1,5 +1,6 @@
 #!/bin/bash -e
-. /etc/advligorts/env
+rts_env=${RTS_ENV:-/etc/advligorts/env}
+. $rts_env
 cmd="$1"
 sys="$2"
 if [ -z "$sys" ] ; then
diff --git a/support/symvers/ModuleIOP.symvers b/support/symvers/ModuleIOP.symvers
new file mode 100644
index 0000000000000000000000000000000000000000..814919e9fee2858e70ce53e6b0679b848e17a643
--- /dev/null
+++ b/support/symvers/ModuleIOP.symvers
@@ -0,0 +1 @@
+0x1f66a720	need_to_load_IOP_first	/	EXPORT_SYMBOL	
diff --git a/support/symvers/README.md b/support/symvers/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ae2c0736a8afbf465e44aaf314dd3fbd20b48146
--- /dev/null
+++ b/support/symvers/README.md
@@ -0,0 +1,2 @@
+# ModuleIOP.symvers
+As a verification of proper configuration the IOP model on each front end exports a variable with the name `need_to_load_IOP_first`. This allows us to fail non-IOP modules when loading if the IOP model has not been loaded first. The `ModuleIOP.symvers` file in this directory allows us to build modules in any order, instead of always building an IOP model first and then copying that generated ModuleIOP.symvers around. If the prototype of the exported symbol ever changed, you would need to replace this file with a new one, otherwise don't touch this file unless you know what you are doing.