diff --git a/iocBoot/iocwfdemo/Makefile b/iocBoot/iocwfdemo/Makefile
new file mode 100644
index 0000000..89d66d0
--- /dev/null
+++ b/iocBoot/iocwfdemo/Makefile
@@ -0,0 +1,5 @@
+TOP = ../..
+include $(TOP)/configure/CONFIG
+ARCH = linux-x86_64-debug
+TARGETS = envPaths
+include $(TOP)/configure/RULES.ioc
diff --git a/iocBoot/iocwfdemo/iq.db b/iocBoot/iocwfdemo/iq.db
new file mode 100644
index 0000000..8e7df87
--- /dev/null
+++ b/iocBoot/iocwfdemo/iq.db
@@ -0,0 +1,56 @@
+record(ao, "$(N)Rate") {
+ field(VAL, "1.0")
+ field(PINI, "YES")
+ field(PREC, "3")
+ field( OUT, "$(N)dly_.ODLY NPP")
+}
+
+record(ao, "$(N)Delta") {
+ field(VAL, "0.0")
+ field(PINI, "YES")
+}
+
+record(calc, "$(N)Phase:I") {
+ field(PINI, "RUNNING")
+ field(INPA, "$(N)Phase:I")
+ field(CALC, "A+1")
+ field( EGU, "rad")
+ field(PREC, "3")
+ field(FLNK, "$(N)Phase:Q")
+ info(pdbGroup0, "$(N)iq|phas_i=VAL")
+ #field(TPRO, "1")
+}
+
+record(calc, "$(N)Phase:Q") {
+ field(INPA, "$(N)Phase:I")
+ field(INPB, "$(N)Delta NPP")
+ field(CALC, "A+B")
+ field( EGU, "rad")
+ field(PREC, "3")
+ field(FLNK, "$(N)I")
+ info(pdbGroup0, "$(N)iq|phas_q=VAL")
+}
+
+record(waveform, "$(N)I") {
+ field(DTYP, "PDB Demo")
+ field( INP, "$(N)Phase:I")
+ field(FTVL, "DOUBLE")
+ field(NELM, "500")
+ field(FLNK, "$(N)Q")
+ info(pdbGroup0, "$(N)iq|I=VAL")
+}
+
+record(waveform, "$(N)Q") {
+ field(DTYP, "PDB Demo")
+ field( INP, "$(N)Phase:Q")
+ field(FTVL, "DOUBLE")
+ field(NELM, "500")
+ field(FLNK, "$(N)dly_")
+ info(pdbGroup0, "$(N)iq|Q=VAL")
+ info(pdbTrigger,"$(N)iq|Q>*")
+}
+
+record(calcout, "$(N)dly_") {
+ field(ODLY, "1.0")
+ field(OUT , "$(N)Phase:I.PROC CA")
+}
diff --git a/iocBoot/iocwfdemo/qwfdemo.opi b/iocBoot/iocwfdemo/qwfdemo.opi
new file mode 100644
index 0000000..1b3c35f
--- /dev/null
+++ b/iocBoot/iocwfdemo/qwfdemo.opi
@@ -0,0 +1,1205 @@
+
+
+
+
+ false
+ -1
+ -1
+
+ false
+
+
+
+ 5.1.0.201605121837
+
+
+
+ 6
+ 1200
+
+ true
+ TST:
+
+
+
+
+ true
+ true
+ true
+ true
+ true
+ Display
+ 800
+ 19ff4908:15deb215829:-7d48
+ -1
+ -1
+
+
+ false
+ false
+ false
+
+
+
+ true
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+ false
+
+
+
+ 0
+ 20
+ 0
+ Text Update
+ 0
+ true
+ $(N)Phase:I
+
+ 0.0
+
+
+ true
+ true
+ false
+
+
+ true
+ ######
+ $(pv_name)
+$(pv_value)
+ false
+ 1
+ true
+ Text Update
+ 100
+ false
+ 19ff4908:15deb215829:-7d43
+ 204
+ 37
+
+
+
+ false
+ false
+ false
+
+
+
+ true
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+ false
+
+
+
+ 0
+ 20
+ 0
+ Text Update_1
+ 0
+ true
+ $(N)Phase:Q
+
+ 0.0
+
+
+ true
+ true
+ false
+
+
+ true
+ ######
+ $(pv_name)
+$(pv_value)
+ false
+ 1
+ true
+ Text Update
+ 100
+ false
+ 19ff4908:15deb215829:-7d3b
+ 204
+ 65
+
+
+
+ false
+ false
+ false
+
+
+
+ true
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+ false
+
+
+
+ 0
+ 20
+ 0
+ Text Update_2
+ 0
+ true
+ =field("phas_i", 'pva://$(N)iq')
+
+ 0.0
+
+
+ true
+ true
+ false
+
+
+ true
+ ######
+ $(pv_name)
+$(pv_value)
+ false
+ 1
+ true
+ Text Update
+ 100
+ false
+ 19ff4908:15deb215829:-7d02
+ 436
+ 37
+
+
+
+ false
+ false
+ false
+
+
+
+ true
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+ false
+
+
+
+ 0
+ 20
+ 0
+ Text Update_3
+ 0
+ true
+ pva://$(N)Phase:I
+
+ 0.0
+
+
+ true
+ true
+ false
+
+
+ true
+ ######
+ $(pv_name)
+$(pv_value)
+ false
+ 1
+ true
+ Text Update
+ 100
+ false
+ 19ff4908:15deb215829:-7ced
+ 316
+ 37
+
+
+
+ false
+ false
+ false
+
+
+
+ true
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+ false
+
+
+
+ 0
+ 20
+ 0
+ Text Update_4
+ 0
+ true
+ pva://$(N)Phase:Q
+
+ 0.0
+
+
+ true
+ true
+ false
+
+
+ true
+ ######
+ $(pv_name)
+$(pv_value)
+ false
+ 1
+ true
+ Text Update
+ 100
+ false
+ 19ff4908:15deb215829:-7cec
+ 316
+ 65
+
+
+
+ false
+ false
+ false
+
+
+
+ true
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+ false
+
+
+
+ 0
+ 20
+ 0
+ Text Update_5
+ 0
+ true
+ =field("phas_q", 'pva://$(N)iq')
+
+ 0.0
+
+
+ true
+ true
+ false
+
+
+ true
+ ######
+ $(pv_name)
+$(pv_value)
+ false
+ 1
+ true
+ Text Update
+ 100
+ false
+ 19ff4908:15deb215829:-7cc6
+ 436
+ 65
+
+
+
+ false
+
+
+
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+
+
+
+ 20
+ 1
+ Label
+
+
+ true
+ true
+ false
+
+
+ CA
+
+ true
+ 1
+ true
+ Label
+ 100
+ false
+ 19ff4908:15deb215829:-7cb9
+ 204
+ 18
+
+
+
+ false
+
+
+
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+
+
+
+ 20
+ 1
+ Label_1
+
+
+ true
+ true
+ false
+
+
+ PVA single
+
+ true
+ 1
+ true
+ Label
+ 100
+ false
+ 19ff4908:15deb215829:-7caf
+ 316
+ 18
+
+
+
+ false
+
+
+
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+
+
+
+ 20
+ 1
+ Label_2
+
+
+ true
+ true
+ false
+
+
+ PVA group
+
+ true
+ 1
+ true
+ Label
+ 100
+ false
+ 19ff4908:15deb215829:-7ca5
+ 436
+ 18
+
+
+
+ false
+
+
+
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+
+
+
+ 20
+ 1
+ Label_3
+
+
+ true
+ true
+ false
+
+
+ I
+
+ true
+ 1
+ true
+ Label
+ 27
+ false
+ 19ff4908:15deb215829:-7c00
+ 178
+ 37
+
+
+
+ false
+
+
+
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+
+
+
+ 20
+ 1
+ Label_4
+
+
+ true
+ true
+ false
+
+
+ Q
+
+ true
+ 1
+ true
+ Label
+ 27
+ false
+ 19ff4908:15deb215829:-7bf6
+ 178
+ 65
+
+
+
+ false
+ true
+ 0.0
+
+
+
+ Primary X Axis (0)
+ true
+
+
+
+ false
+ 100.0
+ 0.0
+
+ Default
+
+
+ true
+ 0
+
+ Default Bold
+
+ true
+ true
+ 0.0
+
+
+
+ Primary Y Axis (1)
+ true
+
+
+
+ false
+ 100.0
+ 0.0
+
+ Default
+
+
+ true
+ 0
+
+ Default Bold
+
+ true
+ 2
+ false
+
+
+
+ true
+
+
+
+ 0
+ 1
+ true
+ false
+
+
+
+ 283
+ XY Graph
+
+
+
+ $(N)I
+
+
+
+ true
+ true
+ false
+
+
+ true
+ false
+ true
+ CA
+
+ Default Bold
+
+ $(trace_0_y_pv)
+$(trace_0_y_pv_value)
+ true
+ 1000
+ false
+ 1
+ $(trace_0_y_pv)
+ 0
+ 4
+ 0
+
+
+
+ 0
+ 100
+ 0
+ true
+ 0
+
+
+ 1
+ $(pv_name)
+
+ true
+ 1000
+ false
+ 1
+ $(trace_1_y_pv)
+ 0
+ 4
+ 0
+
+
+
+ 0
+ 100
+ 0
+ true
+ 0
+
+
+ 1
+ $(N)Q
+
+ 2
+ false
+
+
+ true
+ XY Graph
+ 725
+ 19ff4908:15deb215829:-7bb4
+ 38
+ 132
+
+
+
+ false
+ true
+ 0.0
+
+
+
+ Primary X Axis (0)
+ true
+
+
+
+ false
+ 100.0
+ 0.0
+
+ Default
+
+
+ true
+ 0
+
+ Default Bold
+
+ true
+ true
+ 0.0
+
+
+
+ Primary Y Axis (1)
+ true
+
+
+
+ false
+ 100.0
+ 0.0
+
+ Default
+
+
+ true
+ 0
+
+ Default Bold
+
+ true
+ 2
+ false
+
+
+
+ true
+
+
+
+ 0
+ 1
+ true
+ false
+
+
+
+ 283
+ XY Graph_1
+
+
+
+ pva://$(N)I
+
+
+
+ true
+ true
+ false
+
+
+ true
+ false
+ true
+ PVA Single
+
+ Default Bold
+
+ $(trace_0_y_pv)
+$(trace_0_y_pv_value)
+ true
+ 1000
+ false
+ 1
+ $(trace_0_y_pv)
+ 0
+ 4
+ 0
+
+
+
+ 0
+ 100
+ 0
+ true
+ 0
+
+
+ 1
+ $(pv_name)
+
+ true
+ 1000
+ false
+ 1
+ $(trace_1_y_pv)
+ 0
+ 4
+ 0
+
+
+
+ 0
+ 100
+ 0
+ true
+ 0
+
+
+ 1
+ pva://$(N)Q
+
+ 2
+ false
+
+
+ true
+ XY Graph
+ 725
+ 19ff4908:15deb215829:-7b3e
+ 38
+ 426
+
+
+
+ false
+ true
+ 0.0
+
+
+
+ Primary X Axis (0)
+ true
+
+
+
+ false
+ 100.0
+ 0.0
+
+ Default
+
+
+ true
+ 0
+
+ Default Bold
+
+ true
+ true
+ 0.0
+
+
+
+ Primary Y Axis (1)
+ true
+
+
+
+ false
+ 100.0
+ 0.0
+
+ Default
+
+
+ true
+ 0
+
+ Default Bold
+
+ true
+ 2
+ false
+
+
+
+ true
+
+
+
+ 0
+ 1
+ true
+ false
+
+
+
+ 283
+ XY Graph_2
+
+
+
+ =field("I", 'pva://$(N)iq')
+
+
+
+ true
+ true
+ false
+
+
+ true
+ false
+ true
+ PVA Group
+
+ Default Bold
+
+ $(trace_0_y_pv)
+$(trace_0_y_pv_value)
+ true
+ 1000
+ false
+ 1
+ $(trace_0_y_pv)
+ 0
+ 4
+ 0
+
+
+
+ 0
+ 100
+ 0
+ true
+ 0
+
+
+ 1
+ $(pv_name)
+
+ true
+ 1000
+ false
+ 1
+ $(trace_1_y_pv)
+ 0
+ 4
+ 0
+
+
+
+ 0
+ 100
+ 0
+ true
+ 0
+
+
+ 1
+ =field("Q", 'pva://$(N)iq')
+
+ 2
+ false
+
+
+ true
+ XY Graph
+ 725
+ 19ff4908:15deb215829:-7b09
+ 38
+ 720
+
+
+
+ false
+ false
+ false
+
+
+
+ false
+
+
+
+ 3
+ 1
+
+ true
+
+ Default
+
+ false
+
+
+
+ 0
+ 25
+ 0
+ false
+ 1.7976931348623157E308
+ -1.7976931348623157E308
+ false
+ Text Input
+ 0
+ true
+ $(N)Rate
+
+ 0.0
+
+
+ true
+ true
+ false
+
+
+ 0
+ true
+
+
+ $(pv_name)
+$(pv_value)
+ false
+ true
+ Text Input
+ 142
+ 19ff4908:15deb215829:-7ac8
+ 30
+ 34
+
+
+
+ false
+ false
+ false
+
+
+
+ false
+
+
+
+ 3
+ 1
+
+ true
+
+ Default
+
+ false
+
+
+
+ 0
+ 25
+ 0
+ false
+ 1.7976931348623157E308
+ -1.7976931348623157E308
+ false
+ Text Input_1
+ 0
+ true
+ $(N)Delta
+
+ 0.0
+
+
+ true
+ true
+ false
+
+
+ 0
+ true
+
+
+ $(pv_name)
+$(pv_value)
+ false
+ true
+ Text Input
+ 142
+ 19ff4908:15deb215829:-7aaf
+ 30
+ 84
+
+
+
+ false
+
+
+
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+
+
+
+ 20
+ 1
+ Label_5
+
+
+ true
+ true
+ false
+
+
+ Update Period(sec)
+
+ true
+ 1
+ true
+ Label
+ 142
+ false
+ 19ff4908:15deb215829:-7a94
+ 30
+ 15
+
+
+
+ false
+
+
+
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+
+
+
+ 20
+ 1
+ Label_6
+
+
+ true
+ true
+ false
+
+
+ Phase Diff (rad)
+
+ true
+ 1
+ true
+ Label
+ 142
+ false
+ 19ff4908:15deb215829:-7a8a
+ 30
+ 65
+
+
+
+ false
+
+
+
+
+
+
+ 0
+ 1
+ true
+
+ Default
+
+
+
+
+ 20
+ 1
+ Label_7
+
+
+ true
+ true
+ false
+
+
+ freq = 360 deg / 100 samples
+
+ true
+ 1
+ true
+ Label
+ 211
+ false
+ 19ff4908:15deb215829:-7a30
+ 552
+ 108
+
+
\ No newline at end of file
diff --git a/iocBoot/iocwfdemo/st.cmd b/iocBoot/iocwfdemo/st.cmd
new file mode 100755
index 0000000..8b5b7b1
--- /dev/null
+++ b/iocBoot/iocwfdemo/st.cmd
@@ -0,0 +1,5 @@
+#!../../bin/linux-x86_64-debug/softIocPVA
+
+dbLoadRecords("iq.db","N=TST:")
+
+iocInit()
diff --git a/pdbApp/Makefile b/pdbApp/Makefile
index 4b8ed99..63d4bff 100644
--- a/pdbApp/Makefile
+++ b/pdbApp/Makefile
@@ -15,6 +15,7 @@ pdbcore_SRCS += pdb.cpp
pdbcore_SRCS += pdbsingle.cpp
pdbcore_SRCS += pdbgroup.cpp
#pdbcore_SRCS += pvalink.cpp
+pdbcore_SRCS += demo.cpp
pdbcore_LIBS += pvAccess pvData Com
diff --git a/pdbApp/demo.cpp b/pdbApp/demo.cpp
new file mode 100644
index 0000000..59d852b
--- /dev/null
+++ b/pdbApp/demo.cpp
@@ -0,0 +1,66 @@
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+namespace {
+
+// pi/180
+static const double pi_180 = 0.017453292519943295;
+
+int dummy;
+
+long init_spin(waveformRecord *prec)
+{
+ if(prec->ftvl==menuFtypeDOUBLE)
+ prec->dpvt = &dummy;
+ return 0;
+}
+
+long process_spin(waveformRecord *prec)
+{
+ const double freq = 360.0*pi_180/100; // rad/sample
+ double phase = 0;
+ double *val = static_cast(prec->bptr);
+
+ long ret = dbGetLink(&prec->inp, DBF_DOUBLE, &phase, 0, 0);
+ if(ret) {
+ (void)recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM);
+ return ret;
+ }
+
+ phase *= pi_180; // deg -> rad
+
+ for(size_t i=0; inelm; i++)
+ val[i] = sin(freq*i+phase);
+
+ prec->nord = prec->nelm;
+
+ return 0;
+}
+
+template
+struct dset5
+{
+ long count;
+ long (*report)(int);
+ long (*init)(int);
+ long (*init_record)(REC *);
+ long (*get_ioint_info)(int, REC *, IOSCANPVT*);
+ long (*process)(REC *);
+};
+
+dset5 devWfPDBDemo = {5,0,0,&init_spin,0,&process_spin};
+
+} // namespace
+
+extern "C" {
+epicsExportAddress(dset, devWfPDBDemo);
+}
diff --git a/pdbApp/qsrv.dbd b/pdbApp/qsrv.dbd
index 5eaa2b4..58329a5 100644
--- a/pdbApp/qsrv.dbd
+++ b/pdbApp/qsrv.dbd
@@ -1,3 +1,6 @@
registrar(QSRVRegistrar)
#registrar(installPVAAddLinkHook)
#link("pva", "lsetPVA")
+
+# from demo.cpp
+device(waveform, CONSTANT, devWfPDBDemo, "PDB Demo")