diff --git a/configure/CONFIG_COMMON b/configure/CONFIG_COMMON
index eef4d6745..d3a66968f 100644
--- a/configure/CONFIG_COMMON
+++ b/configure/CONFIG_COMMON
@@ -76,11 +76,14 @@ COMMON_DIR = ../O.Common
IOCS_APPL_TOP = $(shell $(FULLPATHNAME) $(INSTALL_LOCATION))
#-------------------------------------------------------
-# Make echo output - suppress echoing if make's '-s' flag is set
+# Silencing the build - suppress messages during 'make -s'
NOP = :
-ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo)
-QUIET_FLAG := $(if $(findstring s,$(MAKEFLAGS)),-q,)
-QUESTION_FLAG := $(if $(findstring q,$(MAKEFLAGS)),-i,)
+ECHO = @$(if $(findstring s,$(MFLAGS)),$(NOP),echo)
+QUIET_FLAG := $(if $(findstring s,$(MFLAGS)),-q,)
+
+#-------------------------------------------------------
+# Convert 'make -q' flag into '-i' for genVersionHeader.pl
+QUESTION_FLAG := $(if $(findstring q,$(MFLAGS)),-i,)
#-------------------------------------------------------
ifdef T_A
@@ -90,7 +93,7 @@ INSTALL_SHRLIB = $(INSTALL_LOCATION_LIB)/$(T_A)
INSTALL_TCLLIB = $(INSTALL_LOCATION_LIB)/$(T_A)
INSTALL_BIN = $(INSTALL_LOCATION_BIN)/$(T_A)
-#Directories for libraries
+# Directories for libraries
SHRLIB_SEARCH_DIRS = $(INSTALL_LIB)
#-------------------------------------------------------
diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD
index 21a838790..2dc9dd501 100644
--- a/configure/RULES_BUILD
+++ b/configure/RULES_BUILD
@@ -43,6 +43,7 @@ LOADABLE_LIBRARY += $(LOADABLE_LIBRARY_HOST)
OBJS += $(OBJS_HOST)
PROD += $(PROD_HOST)
SCRIPTS += $(SCRIPTS_HOST)
+TARGETS += $(TARGETS_HOST)
TESTLIBRARY += $(TESTLIBRARY_HOST)
TESTSCRIPTS += $(TESTSCRIPTS_HOST)
TESTPROD += $(TESTPROD_HOST)
@@ -54,6 +55,7 @@ LOADABLE_LIBRARY += $(LOADABLE_LIBRARY_IOC)
OBJS += $(OBJS_IOC)
PROD += $(PROD_IOC)
SCRIPTS += $(SCRIPTS_IOC)
+TARGETS += $(TARGETS_IOC)
TESTLIBRARY += $(TESTLIBRARY_IOC)
TESTSCRIPTS += $(TESTSCRIPTS_IOC)
TESTPROD += $(TESTPROD_IOC)
@@ -360,14 +362,17 @@ ifneq ($(TAPFILES),)
ifdef RUNTESTS_ENABLED
prove --failures --ext .tap --exec "$(CAT)" --color $(TAPFILES)
endif
+
+CURRENT_TAPFILES := $(wildcard $(TAPFILES))
+CURRENT_JUNITFILES := $(wildcard $(JUNITFILES))
endif
clean-tests:
-ifneq ($(TAPFILES),)
- $(RM) $(TAPFILES)
+ifneq ($(CURRENT_TAPFILES),)
+ $(RM) $(CURRENT_TAPFILES)
endif
-ifneq ($(JUNITFILES),)
- $(RM) $(JUNITFILES)
+ifneq ($(CURRENT_JUNITFILES),)
+ $(RM) $(CURRENT_JUNITFILES)
endif
tapfiles: $(TESTSCRIPTS) $(TAPFILES)
diff --git a/configure/os/CONFIG.Common.RTEMS b/configure/os/CONFIG.Common.RTEMS
index 214ba794d..8425e6ef9 100644
--- a/configure/os/CONFIG.Common.RTEMS
+++ b/configure/os/CONFIG.Common.RTEMS
@@ -76,7 +76,7 @@ CPPFLAGS += $($(BUILD_CLASS)_CPPFLAGS) $(POSIX_CPPFLAGS) $(OPT_CPPFLAGS)\
$(USR_CPPFLAGS) $(CMD_CPPFLAGS) $(ARCH_DEP_CPPFLAGS) $(OP_SYS_CPPFLAGS)\
$(OP_SYS_INCLUDE_CPPFLAGS) $(CODE_CPPFLAGS)
-ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo)
+ECHO = @$(if $(findstring s,$(MFLAGS)),$(NOP),echo)
#--------------------------------------------------
# Although RTEMS uses gcc, it wants to use gcc its own way
diff --git a/configure/os/CONFIG.Common.vxWorksCommon b/configure/os/CONFIG.Common.vxWorksCommon
index 50f626959..f28f0e327 100644
--- a/configure/os/CONFIG.Common.vxWorksCommon
+++ b/configure/os/CONFIG.Common.vxWorksCommon
@@ -146,8 +146,10 @@ SHRLIB_CFLAGS =
SHRLIB_LDFLAGS =
#--------------------------------------------------
-# Earlier versions of gcc don't understand -MF
-HDEPENDS_COMPFLAGS = -MM > $@
+# Don't use gcc 2.x for dependency generation
+
+HDEPENDS_METHOD_2 = MKMF
+HDEPENDS_METHOD = $(firstword $(HDEPENDS_METHOD_$(VX_GNU_MAJOR_VERSION)) COMP)
#--------------------------------------------------
# osithead use default stack, YES or NO override
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 63f8880a7..a61d5218e 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -112,6 +112,25 @@ be happy to try and answer them!
+Status reporting for the callback and scanOnce task queues
+
+Two new iocsh commands and some associated underlying APIs have been added to
+show the state of the queues that feed the three callback tasks and the scanOnce
+task, including a high-water mark which can optionally be reset. The new iocsh
+commands are callbackQueueShow and scanOnceQueueShow ; both
+take an optional integer argument which must be non-zero to reset the
+high-water mark.
+
+Support for event codes greater than or equal to NUM_TIME_EVENTS
+
+Event numbers greater than or equal to NUM_TIME_EVENTS are now allowed if
+supported by the registered event time provider, which must provide its own
+advancing timestamp validation for such events.
+
+Time events numbered 0 through (NUM_TIME_EVENTS-1) are still validated by
+code in epicsGeneralTime.c that checks for advancing timestamps and enforces
+that restriction.
+
Type-safe Device and Driver Support Tables
Type-safe versions of the device and driver support structures dset
diff --git a/modules/ca/src/tools/caget.c b/modules/ca/src/tools/caget.c
index 00056709e..75225d07f 100644
--- a/modules/ca/src/tools/caget.c
+++ b/modules/ca/src/tools/caget.c
@@ -34,6 +34,7 @@
#include
#include
#include
+#include "epicsVersion.h"
#include "tool_lib.h"
@@ -55,6 +56,7 @@ static void usage (void)
{
fprintf (stderr, "\nUsage: caget [options] ...\n\n"
" -h: Help: Print this message\n"
+ " -V: Version: Show EPICS and CA versions\n"
"Channel Access options:\n"
" -w : Wait time, specifies CA timeout, default is %f second(s)\n"
" -c: Asynchronous get (use ca_get_callback and wait for completion)\n"
@@ -389,11 +391,14 @@ int main (int argc, char *argv[])
LINE_BUFFER(stdout); /* Configure stdout buffering */
- while ((opt = getopt(argc, argv, ":taicnhsSe:f:g:l:#:d:0:w:p:F:")) != -1) {
+ while ((opt = getopt(argc, argv, ":taicnhsSVe:f:g:l:#:d:0:w:p:F:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
return 0;
+ case 'V':
+ printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
+ return 0;
case 't': /* Terse output mode */
complainIfNotPlainAndSet(&format, terse);
break;
diff --git a/modules/ca/src/tools/cainfo.c b/modules/ca/src/tools/cainfo.c
index ad580f473..fc18ccd3f 100644
--- a/modules/ca/src/tools/cainfo.c
+++ b/modules/ca/src/tools/cainfo.c
@@ -23,6 +23,7 @@
#include
#include
+#include "epicsVersion.h"
#include
#include
@@ -36,12 +37,14 @@ void usage (void)
{
fprintf (stderr, "\nUsage: cainfo [options] ...\n\n"
" -h: Help: Print this message\n"
+ " -V: Version: Show EPICS and CA versions\n"
"Channel Access options:\n"
" -w : Wait time, specifies CA timeout, default is %f second(s)\n"
" -s : Call ca_client_status with the specified interest level\n"
" -p : CA priority (0-%u, default 0=lowest)\n"
"\nExample: cainfo my_channel another_channel\n\n"
, DEFAULT_TIMEOUT, CA_PRIORITY_MAX);
+ fprintf (stderr, "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
}
@@ -137,11 +140,14 @@ int main (int argc, char *argv[])
LINE_BUFFER(stdout); /* Configure stdout buffering */
- while ((opt = getopt(argc, argv, ":nhw:s:p:")) != -1) {
+ while ((opt = getopt(argc, argv, ":nhVw:s:p:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
return 0;
+ case 'V':
+ printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
+ return 0;
case 'w': /* Set CA timeout value */
if(epicsScanDouble(optarg, &caTimeout) != 1)
{
diff --git a/modules/ca/src/tools/camonitor.c b/modules/ca/src/tools/camonitor.c
index 307dad8d6..a3fdecd55 100644
--- a/modules/ca/src/tools/camonitor.c
+++ b/modules/ca/src/tools/camonitor.c
@@ -26,6 +26,7 @@
#include
#include
#include
+#include "epicsVersion.h"
#include
#include
@@ -44,7 +45,8 @@ void usage (void)
{
fprintf (stderr, "\nUsage: camonitor [options] ...\n"
"\n"
- " -h: Help; Print this message\n"
+ " -h: Help: Print this message\n"
+ " -V: Version: Show EPICS and CA versions\n"
"Channel Access options:\n"
" -w : Wait time, specifies CA timeout, default is %f second(s)\n"
" -m : Specify CA event mask to use. is any combination of\n"
@@ -209,11 +211,14 @@ int main (int argc, char *argv[])
LINE_BUFFER(stdout); /* Configure stdout buffering */
- while ((opt = getopt(argc, argv, ":nhm:sSe:f:g:l:#:0:w:t:p:F:")) != -1) {
+ while ((opt = getopt(argc, argv, ":nhVm:sSe:f:g:l:#:0:w:t:p:F:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
return 0;
+ case 'V':
+ printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
+ return 0;
case 'n': /* Print ENUM as index numbers */
enumAsNr=1;
break;
diff --git a/modules/ca/src/tools/caput.c b/modules/ca/src/tools/caput.c
index 5e4d10e23..79ffef8c3 100644
--- a/modules/ca/src/tools/caput.c
+++ b/modules/ca/src/tools/caput.c
@@ -37,6 +37,7 @@
#include
#include
#include
+#include "epicsVersion.h"
#include "tool_lib.h"
@@ -59,6 +60,7 @@ void usage (void)
fprintf (stderr, "\nUsage: caput [options] ...\n"
" caput -a [options] ...\n\n"
" -h: Help: Print this message\n"
+ " -V: Version: Show EPICS and CA versions\n"
"Channel Access options:\n"
" -w : Wait time, specifies CA timeout, default is %f second(s)\n"
" -c: Asynchronous put (use ca_put_callback and wait for completion)\n"
@@ -281,11 +283,14 @@ int main (int argc, char *argv[])
LINE_BUFFER(stdout); /* Configure stdout buffering */
putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */
- while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:F:")) != -1) {
+ while ((opt = getopt(argc, argv, ":cnlhatsVS#:w:p:F:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
return 0;
+ case 'V':
+ printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
+ return 0;
case 'n': /* Force interpret ENUM as index number */
enumAsNr = 1;
enumAsString = 0;
diff --git a/modules/database/src/ioc/db/Makefile b/modules/database/src/ioc/db/Makefile
index c6f33556a..2dc4fec0d 100644
--- a/modules/database/src/ioc/db/Makefile
+++ b/modules/database/src/ioc/db/Makefile
@@ -61,7 +61,7 @@ DBDINC += menuScan
DBDINC += dbCommon
dbMenusPod = $(notdir $(wildcard ../db/menu*.dbd.pod))
-HTMLS += $(patsubst %.dbd.pod,%.html,$(menusPod))
+HTMLS += $(patsubst %.dbd.pod,%.html,$(dbMenusPod))
dbCore_SRCS += dbLock.c
dbCore_SRCS += dbAccess.c
diff --git a/modules/database/src/ioc/db/callback.c b/modules/database/src/ioc/db/callback.c
index ae074141c..fe6db815b 100644
--- a/modules/database/src/ioc/db/callback.c
+++ b/modules/database/src/ioc/db/callback.c
@@ -54,6 +54,7 @@ typedef struct cbQueueSet {
epicsEventId semWakeUp;
epicsRingPointerId queue;
int queueOverflow;
+ int queueOverflows;
int shutdown;
int threadsConfigured;
int threadsRunning;
@@ -103,6 +104,51 @@ int callbackSetQueueSize(int size)
return 0;
}
+int callbackQueueStatus(const int reset, callbackQueueStats *result)
+{
+ int ret;
+ if (!callbackIsInit) return -1;
+ if (result) {
+ int prio;
+ result->size = callbackQueueSize;
+ for(prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
+ epicsRingPointerId qId = callbackQueue[prio].queue;
+ result->numUsed[prio] = epicsRingPointerGetUsed(qId);
+ result->maxUsed[prio] = epicsRingPointerGetHighWaterMark(qId);
+ result->numOverflow[prio] = epicsAtomicGetIntT(&callbackQueue[prio].queueOverflows);
+ }
+ ret = 0;
+ } else {
+ ret = -2;
+ }
+ if (reset) {
+ int prio;
+ for(prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
+ epicsRingPointerResetHighWaterMark(callbackQueue[prio].queue);
+ }
+ }
+ return ret;
+}
+
+void callbackQueueShow(const int reset)
+{
+ callbackQueueStats stats;
+ if (callbackQueueStatus(reset, &stats) == -1) {
+ fprintf(stderr, "Callback system not initialized, yet. Please run "
+ "iocInit before using this command.\n");
+ } else {
+ int prio;
+ printf("PRIORITY HIGH-WATER MARK ITEMS IN Q Q SIZE %% USED Q OVERFLOWS\n");
+ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
+ double qusage = 100.0 * stats.numUsed[prio] / stats.size;
+ printf("%8s %15d %10d %6d %6.1f %11d\n",
+ threadNamePrefix[prio], stats.maxUsed[prio],
+ stats.numUsed[prio], stats.size, qusage,
+ stats.numOverflow[prio]);
+ }
+ }
+}
+
int callbackParallelThreads(int count, const char *prio)
{
if (callbackIsInit) {
@@ -290,6 +336,7 @@ int callbackRequest(CALLBACK *pcallback)
if (!pushOK) {
epicsInterruptContextMessage(fullMessage[priority]);
mySet->queueOverflow = TRUE;
+ epicsAtomicIncrIntT(&mySet->queueOverflows);
return S_db_bufFull;
}
epicsEventSignal(mySet->semWakeUp);
diff --git a/modules/database/src/ioc/db/callback.h b/modules/database/src/ioc/db/callback.h
index fa626d1d0..720cf337d 100644
--- a/modules/database/src/ioc/db/callback.h
+++ b/modules/database/src/ioc/db/callback.h
@@ -48,6 +48,13 @@ typedef epicsCallback CALLBACK;
typedef void (*CALLBACKFUNC)(struct callbackPvt*);
+typedef struct callbackQueueStats {
+ int size;
+ int numUsed[NUM_CALLBACK_PRIORITIES];
+ int maxUsed[NUM_CALLBACK_PRIORITIES];
+ int numOverflow[NUM_CALLBACK_PRIORITIES];
+} callbackQueueStats;
+
#define callbackSetCallback(PFUN, PCALLBACK) \
( (PCALLBACK)->callback = (PFUN) )
#define callbackSetPriority(PRIORITY, PCALLBACK) \
@@ -73,6 +80,8 @@ epicsShareFunc void callbackCancelDelayed(CALLBACK *pcallback);
epicsShareFunc void callbackRequestProcessCallbackDelayed(
CALLBACK *pCallback, int Priority, void *pRec, double seconds);
epicsShareFunc int callbackSetQueueSize(int size);
+epicsShareFunc int callbackQueueStatus(const int reset, callbackQueueStats *result);
+epicsShareFunc void callbackQueueShow(const int reset);
epicsShareFunc int callbackParallelThreads(int count, const char *prio);
#ifdef __cplusplus
diff --git a/modules/database/src/ioc/db/dbCa.c b/modules/database/src/ioc/db/dbCa.c
index 65a8327cf..843fbfc0c 100644
--- a/modules/database/src/ioc/db/dbCa.c
+++ b/modules/database/src/ioc/db/dbCa.c
@@ -703,7 +703,12 @@ static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
caLink *pca;
long status;
- pcaGetCheck
+ assert(plink);
+ if (plink->type != CA_LINK) return -1;
+ pca = (caLink *)plink->value.pv_link.pvt;
+ assert(pca);
+ epicsMutexMustLock(pca->lock);
+ assert(pca->plink);
status = rtn(plink, priv);
epicsMutexUnlock(pca->lock);
return status;
diff --git a/modules/database/src/ioc/db/dbChannel.c b/modules/database/src/ioc/db/dbChannel.c
index 92be08c77..9792708cb 100644
--- a/modules/database/src/ioc/db/dbChannel.c
+++ b/modules/database/src/ioc/db/dbChannel.c
@@ -20,6 +20,7 @@
#include "cantProceed.h"
#include "epicsAssert.h"
#include "epicsString.h"
+#include "epicsStdio.h"
#include "errlog.h"
#include "freeList.h"
#include "gpHash.h"
diff --git a/modules/database/src/ioc/db/dbIocRegister.c b/modules/database/src/ioc/db/dbIocRegister.c
index 4d0b88cd9..c40af92c1 100644
--- a/modules/database/src/ioc/db/dbIocRegister.c
+++ b/modules/database/src/ioc/db/dbIocRegister.c
@@ -296,6 +296,17 @@ static void scanOnceSetQueueSizeCallFunc(const iocshArgBuf *args)
scanOnceSetQueueSize(args[0].ival);
}
+/* scanOnceQueueShow */
+static const iocshArg scanOnceQueueShowArg0 = { "reset",iocshArgInt};
+static const iocshArg * const scanOnceQueueShowArgs[1] =
+ {&scanOnceQueueShowArg0};
+static const iocshFuncDef scanOnceQueueShowFuncDef =
+ {"scanOnceQueueShow",1,scanOnceQueueShowArgs};
+static void scanOnceQueueShowCallFunc(const iocshArgBuf *args)
+{
+ scanOnceQueueShow(args[0].ival);
+}
+
/* scanppl */
static const iocshArg scanpplArg0 = { "rate",iocshArgDouble};
static const iocshArg * const scanpplArgs[1] = {&scanpplArg0};
@@ -335,6 +346,17 @@ static void callbackSetQueueSizeCallFunc(const iocshArgBuf *args)
callbackSetQueueSize(args[0].ival);
}
+/* callbackQueueShow */
+static const iocshArg callbackQueueShowArg0 = { "reset", iocshArgInt};
+static const iocshArg * const callbackQueueShowArgs[1] =
+ {&callbackQueueShowArg0};
+static const iocshFuncDef callbackQueueShowFuncDef =
+ {"callbackQueueShow",1,callbackQueueShowArgs};
+static void callbackQueueShowCallFunc(const iocshArgBuf *args)
+{
+ callbackQueueShow(args[0].ival);
+}
+
/* callbackParallelThreads */
static const iocshArg callbackParallelThreadsArg0 = { "no of threads", iocshArgInt};
static const iocshArg callbackParallelThreadsArg1 = { "priority", iocshArgString};
@@ -441,12 +463,14 @@ void dbIocRegister(void)
iocshRegister(&dbLockShowLockedFuncDef,dbLockShowLockedCallFunc);
iocshRegister(&scanOnceSetQueueSizeFuncDef,scanOnceSetQueueSizeCallFunc);
+ iocshRegister(&scanOnceQueueShowFuncDef,scanOnceQueueShowCallFunc);
iocshRegister(&scanpplFuncDef,scanpplCallFunc);
iocshRegister(&scanpelFuncDef,scanpelCallFunc);
iocshRegister(&postEventFuncDef,postEventCallFunc);
iocshRegister(&scanpiolFuncDef,scanpiolCallFunc);
iocshRegister(&callbackSetQueueSizeFuncDef,callbackSetQueueSizeCallFunc);
+ iocshRegister(&callbackQueueShowFuncDef,callbackQueueShowCallFunc);
iocshRegister(&callbackParallelThreadsFuncDef,callbackParallelThreadsCallFunc);
/* Needed before callback system is initialized */
diff --git a/modules/database/src/ioc/db/dbScan.c b/modules/database/src/ioc/db/dbScan.c
index e5c78fea1..9224ed504 100644
--- a/modules/database/src/ioc/db/dbScan.c
+++ b/modules/database/src/ioc/db/dbScan.c
@@ -24,6 +24,7 @@
#include "cantProceed.h"
#include "dbDefs.h"
#include "ellLib.h"
+#include "epicsAtomic.h"
#include "epicsEvent.h"
#include "epicsMutex.h"
#include "epicsPrint.h"
@@ -63,6 +64,7 @@ static volatile enum ctl scanCtl;
static int onceQueueSize = 1000;
static epicsEventId onceSem;
static epicsRingBytesId onceQ;
+static int onceQOverruns = 0;
static epicsThreadId onceTaskId;
static void *exitOnce;
@@ -676,6 +678,7 @@ int scanOnceCallback(struct dbCommon *precord, once_complete cb, void *usr)
if (!pushOK) {
if (newOverflow) errlogPrintf("scanOnce: Ring buffer overflow\n");
newOverflow = FALSE;
+ epicsAtomicIncrIntT(&onceQOverruns);
} else {
newOverflow = TRUE;
}
@@ -722,6 +725,40 @@ int scanOnceSetQueueSize(int size)
return 0;
}
+int scanOnceQueueStatus(const int reset, scanOnceQueueStats *result)
+{
+ int ret;
+ if (!onceQ) return -1;
+ if (result) {
+ result->size = epicsRingBytesSize(onceQ) / sizeof(onceEntry);
+ result->numUsed = epicsRingBytesUsedBytes(onceQ) / sizeof(onceEntry);
+ result->maxUsed = epicsRingBytesHighWaterMark(onceQ) / sizeof(onceEntry);
+ result->numOverflow = epicsAtomicGetIntT(&onceQOverruns);
+ ret = 0;
+ } else {
+ ret = -2;
+ }
+ if (reset) {
+ epicsRingBytesResetHighWaterMark(onceQ);
+ }
+ return ret;
+}
+
+void scanOnceQueueShow(const int reset)
+{
+ scanOnceQueueStats stats;
+ if (scanOnceQueueStatus(reset, &stats) == -1) {
+ fprintf(stderr, "scanOnce system not initialized, yet. Please run "
+ "iocInit before using this command.\n");
+ } else {
+ double qusage = 100.0 * stats.numUsed / stats.size;
+ printf("PRIORITY HIGH-WATER MARK ITEMS IN Q Q SIZE %% USED Q OVERFLOWS\n");
+ printf("%8s %15d %10d %6d %6.1f %11d\n", "scanOnce", stats.maxUsed,
+ stats.numUsed, stats.size, qusage,
+ epicsAtomicGetIntT(&onceQOverruns));
+ }
+}
+
static void initOnce(void)
{
if ((onceQ = epicsRingBytesLockedCreate(sizeof(onceEntry)*onceQueueSize)) == NULL) {
diff --git a/modules/database/src/ioc/db/dbScan.h b/modules/database/src/ioc/db/dbScan.h
index d483a0c30..622103c3b 100644
--- a/modules/database/src/ioc/db/dbScan.h
+++ b/modules/database/src/ioc/db/dbScan.h
@@ -42,6 +42,13 @@ struct dbCommon;
typedef void (*io_scan_complete)(void *usr, IOSCANPVT, int prio);
typedef void (*once_complete)(void *usr, struct dbCommon*);
+typedef struct scanOnceQueueStats {
+ int size;
+ int numUsed;
+ int maxUsed;
+ int numOverflow;
+} scanOnceQueueStats;
+
epicsShareFunc long scanInit(void);
epicsShareFunc void scanRun(void);
epicsShareFunc void scanPause(void);
@@ -57,6 +64,8 @@ epicsShareFunc double scanPeriod(int scan);
epicsShareFunc int scanOnce(struct dbCommon *);
epicsShareFunc int scanOnceCallback(struct dbCommon *, once_complete cb, void *usr);
epicsShareFunc int scanOnceSetQueueSize(int size);
+epicsShareFunc int scanOnceQueueStatus(const int reset, scanOnceQueueStats *result);
+epicsShareFunc void scanOnceQueueShow(const int reset);
/*print periodic lists*/
epicsShareFunc int scanppl(double rate);
diff --git a/modules/database/src/ioc/db/menuScan.dbd b/modules/database/src/ioc/db/menuScan.dbd.pod
similarity index 50%
rename from modules/database/src/ioc/db/menuScan.dbd
rename to modules/database/src/ioc/db/menuScan.dbd.pod
index 17fedd59b..e716e79da 100644
--- a/modules/database/src/ioc/db/menuScan.dbd
+++ b/modules/database/src/ioc/db/menuScan.dbd.pod
@@ -1,11 +1,48 @@
#*************************************************************************
-# Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
+# Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
+
+=head1 Menu menuScan
+
+This menu is used for the C field of all record types.
+
+The set of periodic scan rates may be modified for an individual IOC by
+copying the F file from Base into the IOC's source
+directory and changing it to contain the desired scan rates.
+
+The scan periods are extracted from the choice strings at runtime, which
+must be expressed as a number with any of the following units appended:
+
+=over 4
+
+ second
+ seconds
+ minute
+ minutes
+ hour
+ hours
+ Hertz
+ Hz
+
+=back
+
+At IOC start-up a separate scan thread will be created for each period,
+with thread priority increasing further down the list, so faster periods
+should appear after slower ones.
+
+Scan rates that cannot be achieved will generate a warning message from
+the C command.
+
+
+=menu menuScan
+
+=cut
+
menu(menuScan) {
choice(menuScanPassive,"Passive")
choice(menuScanEvent,"Event")
diff --git a/modules/database/src/std/rec/biRecord.dbd b/modules/database/src/std/rec/biRecord.dbd
deleted file mode 100644
index 1646d5df1..000000000
--- a/modules/database/src/std/rec/biRecord.dbd
+++ /dev/null
@@ -1,134 +0,0 @@
-#*************************************************************************
-# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-# National Laboratory.
-# Copyright (c) 2002 The Regents of the University of California, as
-# Operator of Los Alamos National Laboratory.
-# EPICS BASE is distributed subject to a Software License Agreement found
-# in file LICENSE that is included with this distribution.
-#*************************************************************************
-recordtype(bi) {
- include "dbCommon.dbd"
- field(INP,DBF_INLINK) {
- prompt("Input Specification")
- promptgroup("40 - Input")
- interest(1)
- }
- field(VAL,DBF_ENUM) {
- prompt("Current Value")
- promptgroup("40 - Input")
- asl(ASL0)
- pp(TRUE)
- }
- field(ZSV,DBF_MENU) {
- prompt("Zero Error Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- menu(menuAlarmSevr)
- }
- field(OSV,DBF_MENU) {
- prompt("One Error Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- menu(menuAlarmSevr)
- }
- field(COSV,DBF_MENU) {
- prompt("Change of State Svr")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- menu(menuAlarmSevr)
- }
- field(ZNAM,DBF_STRING) {
- prompt("Zero Name")
- promptgroup("80 - Display")
- pp(TRUE)
- interest(1)
- size(26)
- prop(YES)
- }
- field(ONAM,DBF_STRING) {
- prompt("One Name")
- promptgroup("80 - Display")
- pp(TRUE)
- interest(1)
- size(26)
- prop(YES)
- }
- field(RVAL,DBF_ULONG) {
- prompt("Raw Value")
- pp(TRUE)
- }
- field(ORAW,DBF_ULONG) {
- prompt("prev Raw Value")
- special(SPC_NOMOD)
- interest(3)
- }
- field(MASK,DBF_ULONG) {
- prompt("Hardware Mask")
- special(SPC_NOMOD)
- interest(1)
- }
- field(LALM,DBF_USHORT) {
- prompt("Last Value Alarmed")
- special(SPC_NOMOD)
- interest(3)
- }
- field(MLST,DBF_USHORT) {
- prompt("Last Value Monitored")
- special(SPC_NOMOD)
- interest(3)
- }
- field(SIOL,DBF_INLINK) {
- prompt("Simulation Input Link")
- promptgroup("90 - Simulate")
- interest(1)
- }
- field(SVAL,DBF_ULONG) {
- prompt("Simulation Value")
- }
- field(SIML,DBF_INLINK) {
- prompt("Simulation Mode Link")
- promptgroup("90 - Simulate")
- interest(1)
- }
- field(SIMM,DBF_MENU) {
- prompt("Simulation Mode")
- special(SPC_MOD)
- interest(1)
- menu(menuSimm)
- }
- field(SIMS,DBF_MENU) {
- prompt("Simulation Mode Severity")
- promptgroup("90 - Simulate")
- interest(2)
- menu(menuAlarmSevr)
- }
- field(OLDSIMM,DBF_MENU) {
- prompt("Prev. Simulation Mode")
- special(SPC_NOMOD)
- interest(4)
- menu(menuSimm)
- }
- field(SSCN,DBF_MENU) {
- prompt("Sim. Mode Scan")
- promptgroup("90 - Simulate")
- interest(1)
- menu(menuScan)
- initial("65535")
- }
- field(SDLY,DBF_DOUBLE) {
- prompt("Sim. Mode Async Delay")
- promptgroup("90 - Simulate")
- interest(2)
- initial("-1.0")
- }
- %#include "callback.h"
- field(SIMPVT,DBF_NOACCESS) {
- prompt("Sim. Mode Private")
- special(SPC_NOMOD)
- interest(4)
- extra("CALLBACK *simpvt")
- }
-}
diff --git a/modules/database/src/std/rec/biRecord.dbd.pod b/modules/database/src/std/rec/biRecord.dbd.pod
new file mode 100644
index 000000000..fbf343ad4
--- /dev/null
+++ b/modules/database/src/std/rec/biRecord.dbd.pod
@@ -0,0 +1,491 @@
+#*************************************************************************
+# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+# National Laboratory.
+# Copyright (c) 2002 The Regents of the University of California, as
+# Operator of Los Alamos National Laboratory.
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
+
+=title Binary Input Record (bi)
+
+This record type is normally used to obtain a binary value of 0 or 1. Most
+device support modules obtain values from hardware and place the value in
+RVAL. For these devices, record processing sets VAL = (0,1) if RVAL is (0,
+not 0). Device support modules may optionally read a value directly from
+VAL.
+
+Soft device modules are provided to obtain input via database or channel
+access links via dbPutField or dbPutLink requests. Two soft device support
+modules are provided: C and C. The first
+allows VAL to be an arbitrary unsigned short integer. The second reads the
+value into RVAL just like normal hardware modules.
+
+=head2 Parameter Fields
+
+The binary input's fields fall into the following categories:
+
+=over
+
+=item *
+scan Parameters
+
+=item *
+read and convert parameters
+
+=item *
+operator display parameters
+
+=item *
+alarm parameters
+
+=item *
+run-time parameters
+
+=back
+
+=recordtype bi
+
+=cut
+
+recordtype(bi) {
+
+=head3 Scan Parameters
+
+The binary input record has the standard fields for specifying under what
+circumstances the record will be processed. These fields are listed in
+L. In addition, L explains how these
+fields are used. Note that I/O event scanning is only supported for those
+card types that interrupt.
+
+=fields SCAN
+
+=head3 Read and Convert Parameters
+
+The read and convert fields determine where the binary input gets its
+input from and how to convert the raw signal to engineering units. The INP
+field contains the address from where device support retrieves the value.
+If the binary input record gets its value from hardware, the address of the
+card must be entered in the INP field, and the name of the device support
+module must be entered in the DTYP field. See L for
+information on the format of the hardware address. Be aware that the format
+differs between types of cards. You can see a list of device support
+modules currently supported at the user's local site by using C
+utility (R3.13).
+
+For records that specify C or C device
+support routines, the INP field can be a channel or a database link, or a
+constant. If a constant, VAL can be changed directly by dbPuts. See
+L for information on the format of database and
+channel access addresses. Also, see L in
+this chapter for information on soft device support.
+
+If the record gets its values from hardware or uses the C
+device support, the device support routines place the value in the RVAL
+field which is then converted using the process described in the next
+section.
+
+=fields INP, DTYP, ZNAM, ONAM, RVAL, VAL
+
+=head3 Conversion Fields
+
+The VAL field is set equal to (0,1) if the RVAL field is (0, not 0), unless
+the device support module reads a value directly into VAL or the
+C device support is used. The value can also be fetched as one of
+the strings specified in the ZNAM or ONAM fields. The ZNAM field has a
+string that corresponds to the 0 state, so when the value is fetched as
+this string, C will return a 0. The ONAM field hold the
+string that corresponds to the 1 state, so when the value is fetched as
+this string, C returns a 1.
+
+=fields ZNAM, ONAM
+
+=head3 Operator Display Parameters
+
+These parameters are used to present meaningful data to the operator. The
+C record support routine can retrieve the state string
+corresponding to the VAL's state. If the value is 1, C will
+return the string in the ONAM field; and if 0, C will return
+the ZNAM string.
+
+See L for more on the record name (NAME)
+and description (DESC) fields.
+
+=fields ZNAM, ONAM, NAME, DESC
+
+=head3 Alarm Parameters
+
+These parameters are used to determine if the binary input is in alarm
+condition and to determine the severity of that condition. The possible
+alarm conditions for binary inputs are the SCAN, READ state alarms, and the
+change of state alarm. The SCAN and READ alarms are called by the device
+supprt routines.
+
+The user can choose the severity of each state in the ZSV and OSV fields.
+The possible values for these fields are C, C, and
+C. The ZSV field holds the severity for the zero state; OSV, for
+the one state. COSV causes an alarm whenever the state changes between
+0 and 1 and the severity is configured as MINOR or MAJOR.
+
+See L for a complete explanation of the discrete alarm
+states. L lists other fields related to alarms that are
+common to all record types.
+
+=fields ZSV, OSV, COSV
+
+=head3 Run-time Parameters and Simulation Mode Parameters
+
+These parameters are used by the run-time code for processing the binary
+input. They are not configured using a database configuration tool.
+
+ORAW is used to determine if monitors should be triggered for RVAL at the same
+time they are triggered for VAL.
+
+MASK is given a value by ithe device support routines. This value is used to
+manipulate the record's value, but is only the concern of the hardware device
+support routines.
+
+The LALM fields holds the value of the last occurence of the change of
+state alarm. It is used to implement the change of state alarm, and thus
+only has meaning if COSV is MAJOR or MINOR.
+
+The MSLT field is used by the C record support routine to
+determine if archive and value change monitors are invoked. They are if MSLT
+is not equal to VAL.
+
+=fields ORAW, MASK, LALM, MLST
+
+The following fields are used to operate the binary input in simulation
+mode. See L for more information on
+these fields.
+
+=fields SIOL, SVAL, SIML, SIMM, SIMS
+
+
+=cut
+
+ include "dbCommon.dbd"
+ field(INP,DBF_INLINK) {
+ prompt("Input Specification")
+ promptgroup("40 - Input")
+ interest(1)
+ }
+ field(VAL,DBF_ENUM) {
+ prompt("Current Value")
+ promptgroup("40 - Input")
+ asl(ASL0)
+ pp(TRUE)
+ }
+ field(ZSV,DBF_MENU) {
+ prompt("Zero Error Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ menu(menuAlarmSevr)
+ }
+ field(OSV,DBF_MENU) {
+ prompt("One Error Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ menu(menuAlarmSevr)
+ }
+ field(COSV,DBF_MENU) {
+ prompt("Change of State Svr")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ menu(menuAlarmSevr)
+ }
+ field(ZNAM,DBF_STRING) {
+ prompt("Zero Name")
+ promptgroup("80 - Display")
+ pp(TRUE)
+ interest(1)
+ size(26)
+ prop(YES)
+ }
+ field(ONAM,DBF_STRING) {
+ prompt("One Name")
+ promptgroup("80 - Display")
+ pp(TRUE)
+ interest(1)
+ size(26)
+ prop(YES)
+ }
+ field(RVAL,DBF_ULONG) {
+ prompt("Raw Value")
+ pp(TRUE)
+ }
+ field(ORAW,DBF_ULONG) {
+ prompt("prev Raw Value")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(MASK,DBF_ULONG) {
+ prompt("Hardware Mask")
+ special(SPC_NOMOD)
+ interest(1)
+ }
+ field(LALM,DBF_USHORT) {
+ prompt("Last Value Alarmed")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(MLST,DBF_USHORT) {
+ prompt("Last Value Monitored")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(SIOL,DBF_INLINK) {
+ prompt("Simulation Input Link")
+ promptgroup("90 - Simulate")
+ interest(1)
+ }
+ field(SVAL,DBF_ULONG) {
+ prompt("Simulation Value")
+ }
+ field(SIML,DBF_INLINK) {
+ prompt("Simulation Mode Link")
+ promptgroup("90 - Simulate")
+ interest(1)
+ }
+ field(SIMM,DBF_MENU) {
+ prompt("Simulation Mode")
+ special(SPC_MOD)
+ interest(1)
+ menu(menuSimm)
+ }
+ field(SIMS,DBF_MENU) {
+ prompt("Simulation Mode Severity")
+ promptgroup("90 - Simulate")
+ interest(2)
+ menu(menuAlarmSevr)
+ }
+ field(OLDSIMM,DBF_MENU) {
+ prompt("Prev. Simulation Mode")
+ special(SPC_NOMOD)
+ interest(4)
+ menu(menuSimm)
+ }
+ field(SSCN,DBF_MENU) {
+ prompt("Sim. Mode Scan")
+ promptgroup("90 - Simulate")
+ interest(1)
+ menu(menuScan)
+ initial("65535")
+ }
+ field(SDLY,DBF_DOUBLE) {
+ prompt("Sim. Mode Async Delay")
+ promptgroup("90 - Simulate")
+ interest(2)
+ initial("-1.0")
+ }
+ %#include "callback.h"
+ field(SIMPVT,DBF_NOACCESS) {
+ prompt("Sim. Mode Private")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("CALLBACK *simpvt")
+ }
+
+=head2 Record Support
+
+=head3 Record Support Routines
+
+=head2 C
+
+This routine initializes SIMM with the value of SIML if SIML type is a
+CONSTANT link or creates a channel access link if SIML type is PV_LINK.
+SVAL is likewise initialized if SIOL is a CONSTANT or PV_LINK.
+
+This routine next checks to see that device support is available and a
+device support routine is defined. If neither exist, an error is issued and
+processing is terminated.
+
+If device support includes C, it is called.
+
+=head2 C
+
+See next section.
+
+=head2 C
+
+Fills in the values of struct valueDes so that they refer to VAL.
+
+=head2 C
+
+Retrieves ASCII string corresponding to VAL.
+
+=head2 C
+
+Retrieves ASCII strings for ZNAM and ONAM.
+
+=head2 C
+
+Check if string matches ZNAM or ONAM, and if it does, sets VAL.
+
+=head2 Record Processing
+
+Routine process implements the following algorithm:
+
+=over 1
+
+=item 1.
+Check to see that the appropriate device support module exists. If it
+doesn't, an error message is issued and processing is terminated with
+the PACT field still set to TRUE. This ensures that processes will no
+longer be called for this record. Thus error storms will not occur.
+
+=item 2.
+C is called. See L for details.
+
+=item 3.
+If PACT has been changed to TRUE, the device support read routine has
+started but has not completed reading a new input value. In this case, the
+processing routine merely returns, leaving PACT TRUE.
+
+=item 4.
+Convert.
+
+=back
+
+=over 1
+
+=item *
+status = read_bi
+
+=item *
+PACT = TRUE
+
+=item *
+TIME = tslocaltime
+
+=item *
+if status is 0, then set VAL=(0,1) if RVAL is (0, not 0) and UDF = False.
+
+=item *
+if status is 2, set status = 0
+
+=back
+
+=over 1
+
+=item 5.
+Check alarms: This routine checks to see if the new VAL causes the alarm
+status and severity to change. If so, NSEV, NSTA and LALM are set. Note
+that if VAL is greater than 1, no checking is performed.
+
+=item 6.
+Check if monitors should be invoked:
+
+=back
+
+=over 1
+
+=item *
+Alarm monitors are invoked if the alarm status or severity has changed.
+
+=item *
+Archive and value change monitors are invoked if MSLT is not equal to VAL.
+
+=item *
+Monitors for RVAL are checked whenever other monitors are invoked.
+
+=item *
+NSEV and NSTA are reset to 0.
+
+=back
+
+=over 1
+
+=item 7.
+Scan forward link if necessary, set PACT FALSE, and return.
+
+=back
+
+=head2 Device Support
+
+=head3 Fields of Interest to Device Support
+
+Each binary input record must have an associated set of device support
+routines. The primary resposibility of the device support routines is to
+obtain a new raw input value whenever C is called. The device
+support routines are primarily interested in the following fields:
+
+=fields PACT, DPVT, UDF, NSEV, NSTA, VAL, INP, RVAL, MASK
+
+=head3 Device Support routines
+
+Device support consists of the following routines:
+
+=head2 C
+
+Not currently used.
+
+=head2 C
+
+This routine is called once during IOC initialization.
+
+=head2 C
+
+This routine is optional. If provided, it is called by the record support
+C routine.
+
+=head2 C
+
+This routine is called by the C system each time the record is
+added or deleted from an I/O event scan list. C has the value (0,1) if
+the record is being (added to, deleted from) and I/O event list. It must be
+provided for any device type that can use the ioEvent scanner.
+
+=head2 C
+
+This routine must provide a new input value. It returns the following
+values:
+
+=over
+
+=item 0:
+Success. A new raw value is placed in RVAL. The record support module
+forces VAL to be (0,1) if RVAL is (0, not 0).
+
+=item 2:
+Success, but don't modify VAL.
+
+=item Other:
+Error.
+
+=back
+
+=head3 Device Support for Soft Records
+
+Two soft device support modules, Soft Channel and Raw Soft Channel, are
+provided for input records not related to actual hardware devices. The INP
+link type must be either CONSTANT, DB_LINK, or CA_LINK.
+
+=head3 Soft Channel
+
+C always returns a value of 2, which means that no conversion is
+performed.
+
+If the INP link type is CONSTANT, then the constant value is stored in VAL
+by C, and the UDF is set to FALSE. VAL can be changed via
+C requests. If the INP link type is PV_LINK, the C is
+called by C.
+
+C calls C to read the current value of VAL.
+See L for details.
+
+If the return status of C is zero, then C sets
+UDF to FALSE. The status of C is returned.
+
+=head3 Raw Soft Channel
+
+This module is like the previous except that values are read into RVAL.
+
+C returns a value of 0. Thus the record processing routine will
+force VAL to be 0 or 1.
+
+=cut
+}
diff --git a/modules/database/src/std/rec/boRecord.dbd b/modules/database/src/std/rec/boRecord.dbd
deleted file mode 100644
index 346f0f22c..000000000
--- a/modules/database/src/std/rec/boRecord.dbd
+++ /dev/null
@@ -1,182 +0,0 @@
-#*************************************************************************
-# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-# National Laboratory.
-# Copyright (c) 2002 The Regents of the University of California, as
-# Operator of Los Alamos National Laboratory.
-# EPICS BASE is distributed subject to a Software License Agreement found
-# in file LICENSE that is included with this distribution.
-#*************************************************************************
-recordtype(bo) {
- include "dbCommon.dbd"
- field(VAL,DBF_ENUM) {
- prompt("Current Value")
- promptgroup("50 - Output")
- asl(ASL0)
- pp(TRUE)
- }
- field(OMSL,DBF_MENU) {
- prompt("Output Mode Select")
- promptgroup("50 - Output")
- interest(1)
- menu(menuOmsl)
- }
- field(DOL,DBF_INLINK) {
- prompt("Desired Output Loc")
- promptgroup("40 - Input")
- interest(1)
- }
- field(OUT,DBF_OUTLINK) {
- prompt("Output Specification")
- promptgroup("50 - Output")
- interest(1)
- }
- field(HIGH,DBF_DOUBLE) {
- prompt("Seconds to Hold High")
- promptgroup("30 - Action")
- interest(1)
- }
- field(ZNAM,DBF_STRING) {
- prompt("Zero Name")
- promptgroup("80 - Display")
- pp(TRUE)
- interest(1)
- size(26)
- prop(YES)
- }
- field(ONAM,DBF_STRING) {
- prompt("One Name")
- promptgroup("80 - Display")
- pp(TRUE)
- interest(1)
- size(26)
- prop(YES)
- }
- field(RVAL,DBF_ULONG) {
- prompt("Raw Value")
- pp(TRUE)
- }
- field(ORAW,DBF_ULONG) {
- prompt("prev Raw Value")
- special(SPC_NOMOD)
- interest(3)
- }
- field(MASK,DBF_ULONG) {
- prompt("Hardware Mask")
- special(SPC_NOMOD)
- interest(1)
- }
- field(RPVT,DBF_NOACCESS) {
- prompt("Record Private")
- special(SPC_NOMOD)
- interest(4)
- extra("void * rpvt")
- }
- field(WDPT,DBF_NOACCESS) {
- prompt("Watch Dog Timer ID")
- special(SPC_NOMOD)
- interest(4)
- extra("void * wdpt")
- }
- field(ZSV,DBF_MENU) {
- prompt("Zero Error Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- menu(menuAlarmSevr)
- }
- field(OSV,DBF_MENU) {
- prompt("One Error Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- menu(menuAlarmSevr)
- }
- field(COSV,DBF_MENU) {
- prompt("Change of State Sevr")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- menu(menuAlarmSevr)
- }
- field(RBV,DBF_ULONG) {
- prompt("Readback Value")
- special(SPC_NOMOD)
- }
- field(ORBV,DBF_ULONG) {
- prompt("Prev Readback Value")
- special(SPC_NOMOD)
- interest(3)
- }
- field(MLST,DBF_USHORT) {
- prompt("Last Value Monitored")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LALM,DBF_USHORT) {
- prompt("Last Value Alarmed")
- special(SPC_NOMOD)
- interest(3)
- }
- field(SIOL,DBF_OUTLINK) {
- prompt("Simulation Output Link")
- promptgroup("90 - Simulate")
- interest(1)
- }
- field(SIML,DBF_INLINK) {
- prompt("Simulation Mode Link")
- promptgroup("90 - Simulate")
- interest(1)
- }
- field(SIMM,DBF_MENU) {
- prompt("Simulation Mode")
- special(SPC_MOD)
- interest(1)
- menu(menuYesNo)
- }
- field(SIMS,DBF_MENU) {
- prompt("Simulation Mode Severity")
- promptgroup("90 - Simulate")
- interest(2)
- menu(menuAlarmSevr)
- }
- field(OLDSIMM,DBF_MENU) {
- prompt("Prev. Simulation Mode")
- special(SPC_NOMOD)
- interest(4)
- menu(menuSimm)
- }
- field(SSCN,DBF_MENU) {
- prompt("Sim. Mode Scan")
- promptgroup("90 - Simulate")
- interest(1)
- menu(menuScan)
- initial("65535")
- }
- field(SDLY,DBF_DOUBLE) {
- prompt("Sim. Mode Async Delay")
- promptgroup("90 - Simulate")
- interest(2)
- initial("-1.0")
- }
- %#include "callback.h"
- field(SIMPVT,DBF_NOACCESS) {
- prompt("Sim. Mode Private")
- special(SPC_NOMOD)
- interest(4)
- extra("CALLBACK *simpvt")
- }
- field(IVOA,DBF_MENU) {
- prompt("INVALID outpt action")
- promptgroup("50 - Output")
- interest(2)
- menu(menuIvoa)
- }
- field(IVOV,DBF_USHORT) {
- prompt("INVALID output value")
- promptgroup("50 - Output")
- interest(2)
- }
-}
-
-variable(boHIGHprecision, int)
-variable(boHIGHlimit, double)
diff --git a/modules/database/src/std/rec/boRecord.dbd.pod b/modules/database/src/std/rec/boRecord.dbd.pod
new file mode 100644
index 000000000..fe0a98e6e
--- /dev/null
+++ b/modules/database/src/std/rec/boRecord.dbd.pod
@@ -0,0 +1,611 @@
+#*************************************************************************
+# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+# National Laboratory.
+# Copyright (c) 2002 The Regents of the University of California, as
+# Operator of Los Alamos National Laboratory.
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
+
+=title Binary Output Record (bo)
+
+The normal use for this record type is to store a simple bit (0 or 1) value
+to be sent to a Digital Output module. It can also be used to write binary
+values into other records via database or channel access links. This record
+can implement both latched and momentary binary outputs depending on how
+the HIGH field is configured.
+
+=head2 Parameter Fields
+
+The binary output's fields fall into the following categories:
+
+=over 1
+
+=item *
+scan parameters
+
+=item *
+convert and write parameters
+
+=item *
+operator display parameters
+
+=item *
+alarm parameters
+
+=item *
+run-time parameters
+
+=back
+
+=recordtype bo
+
+=cut
+
+recordtype(bo) {
+
+=head3 Scan Parameters
+
+The binary output record has the standard fields for specifying under what
+circumstances the record will be processed. The fields are listed in
+L. In addition, L explains how these
+fields are used. Note that I/O event scanning is only supported for those card
+types that interrupt.
+
+=fields SCAN
+
+=head3 Desired Output Parameters
+
+The binary output record must specify where its desired output originates.
+The desired output needs to be in engineering units.
+
+The first field that determines where the desired output originates is the
+output mode select (OMSL) field, which can have two possible values:
+C or C. If C is specified, the value
+in the VAL field can be set externally via dbPuts at run-time. If
+C is specified, the VAL field's value is obtained from the
+address specified in the desired output location (DOL) field which can be a
+database link, a channel access link, or a constant. To achieve continuous
+control, a database link to a control algorithm record should be entered in
+the DOL field.
+
+L presents more information on database addresses
+and links. L explaines the effect of database
+linkage on scanning.
+
+=fields DOL, OMSL
+
+=head3 Convert and Write Parameters
+
+These parameters are used to determine where the binary output writes to
+and how to convert the engineering units to a raw signal. After VAL is set
+and forced to be either 1 or 0, as the result of either a dbPut or a new
+value being retrieved from the link in the DOL field, then what happens
+next depends on which device support routine is used and how the HIGH field
+is configured.
+
+If the C device support routine is specified, then the device
+support routine writes the VAL field's value to the address specified in
+the OUT field. Otherwise, RVAL is the value written by the device support
+routines after being converted.
+
+If VAL is equal to 0, then the record processing routine sets RVAL equal to
+zero. When VAL is not equal to 0, then RVAL is set equal to the value
+contained in the MASK field. (MASK is set by the device support routines
+and is of no concern to the user.) Also, when VAL is not 0 and after RVAL is
+set equal to MASK, the record processing routine checks to see if the HIGH
+field is greater than 0. If it is, then the routine will process the record
+again with VAL set to 0 after the number of seconds specified by HIGH.
+Thus, HIGH implements a momentary output which changes the state of the
+device back to 0 after I number of seconds.
+
+=fields DTYP, OUT, VAL, RVAL, HIGH, ZNAM, ONAM
+
+=head3 Conversion Parameters
+
+The ZNAM field has the string that corresponds to the 0 state, and the ONAM
+field holds the string that corresponds to the 1 state. These fields, other
+than being used to tell the operator what each state represents, are used
+to perform conversions if the value fetched by DOL is a string. If it is,
+VAL is set to the state which corresponds to that string. For instance, if the
+value fetched is the string "Off" and the ZNAM string is "Off," then VAL is
+set to 0.
+
+After VAL is set, if VAL is equal to 0, then the record processing routine
+sets RVAL equal to zero. When VAL is not equal to 0, then RVAL is set equal
+to the value contained in the MASK field. (Mask is set by the device
+support routines and is of no concern to the user.) Also when VAL is equal
+to 1 and after RVAL is set equal to MASK, the record processing routine checks
+to see if the HIGH field is greater than 0. If it is, then the routine
+processes the record again with VAL=0 after the number of seconds specified
+by HIGH. Thus, HIGH implements a latched output which changes the state of
+the device or link to 1, then changes it back to 0 after I number of seconds.
+
+=fields ZNAM, ONAM, HIGH
+
+=head3 Output Specification
+
+The OUT field specifies where the binary output record writes its output.
+It must specify the address of an I/O card if the record sends its output
+to hardware, and the DTYP field must contain the corresponding device
+support module. Be aware that the address format differs according to the
+I/O bus used. See L for information on the format of
+hardware addresses. You can see a list of device support modules currently
+supported at the user's local site by using the C utility in R3.13.
+
+Otherwise, if the record is configured to use the soft device support
+modules, then it can be either a database link, a channel access link, or a
+constant. Be aware that nothing will be written when OUT is a constant. See
+L for information on the format of the database and
+channel access addresses. Also, see L in
+this chapter for more on output to other records.
+
+=head3 Operator Display Parameters
+
+These parameters are used to present meaningful data to the operator, The
+C record support routine can retrieve the state string
+corresponding to the VAL's state. So, if the value is 1, C
+will return the string in the ONAM field: and if 0, C will
+return the ZNAM string.
+
+See L for more on the record name (NAME)
+and description (DESC) fields.
+
+=fields ZNAM, ONAM, NAME, DESC
+
+=head3 Alarm Parameters
+
+These parameters are used to determine the binary output's alarm condition
+and to determine the severity of that condition. The possible alarm
+conditions for binary outputs are the SCAN, READ, INVALID and state alarms.
+The user can configure the state alarm conditions using these fields.
+
+The possible values for these fields are C, C, and
+C. The ZSV holds the severity for the zero state; OSV for the one
+state. COSV is used to cause an alarm whenever the state changes between
+states (0-1, 1-0) and its severity is configured as MINOR or MAJOR.
+
+See L for more information on the IVOA and
+IVOV fields. L lists other fields related to alarms that are
+common to all record types.
+
+=fields ZSV, OSV, COSV, IVOA, IVOV
+
+=head3 Run-Time and Simulation Mode Parameters
+
+These parameters are used by the run-time code for processiong the binary
+output. They are not configurable using a configuration tool. They
+represent the current state of the binary output.
+
+ORAW is used to determine if monitors should be triggered for RVAL at the
+same time they are triggered for VAL.
+
+MASK is given a value by the device support routines and should not concern
+the user.
+
+The RBV field is also set by device support. It is the actual read back
+value obtained from the hardware itself or from the associated device
+driver.
+
+The ORBV field is used to decide if monitors should be triggered
+for RBV at the same time monitors are triggered for changes in VAL.
+
+The LALM field holds the value of the last occurrence of the change of
+state alarm. It is used to implement the change of state alarm, and thus
+only has meaning if COSV is MINOR or MAJOR.
+
+The MLST is used by the C record support routine to determine if
+archive and value change monitors are invoked. They are if MLST is not
+equal to VAL.
+
+The WPDT field is a private field for honoring seconds to hold HIGH.
+
+=fields ORAW, MASK, RBV, ORBV, LALM, MLST, RPVT, WDPT
+
+The following fields are used to operate the binary output in the
+simulation mode. See L for more
+information on these fields.
+
+=fields SIOL, SIML, SIMM, SIMS
+
+=cut
+
+ include "dbCommon.dbd"
+ field(VAL,DBF_ENUM) {
+ prompt("Current Value")
+ promptgroup("50 - Output")
+ asl(ASL0)
+ pp(TRUE)
+ }
+ field(OMSL,DBF_MENU) {
+ prompt("Output Mode Select")
+ promptgroup("50 - Output")
+ interest(1)
+ menu(menuOmsl)
+ }
+ field(DOL,DBF_INLINK) {
+ prompt("Desired Output Loc")
+ promptgroup("40 - Input")
+ interest(1)
+ }
+ field(OUT,DBF_OUTLINK) {
+ prompt("Output Specification")
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(HIGH,DBF_DOUBLE) {
+ prompt("Seconds to Hold High")
+ promptgroup("30 - Action")
+ interest(1)
+ }
+ field(ZNAM,DBF_STRING) {
+ prompt("Zero Name")
+ promptgroup("80 - Display")
+ pp(TRUE)
+ interest(1)
+ size(26)
+ prop(YES)
+ }
+ field(ONAM,DBF_STRING) {
+ prompt("One Name")
+ promptgroup("80 - Display")
+ pp(TRUE)
+ interest(1)
+ size(26)
+ prop(YES)
+ }
+ field(RVAL,DBF_ULONG) {
+ prompt("Raw Value")
+ pp(TRUE)
+ }
+ field(ORAW,DBF_ULONG) {
+ prompt("prev Raw Value")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(MASK,DBF_ULONG) {
+ prompt("Hardware Mask")
+ special(SPC_NOMOD)
+ interest(1)
+ }
+ field(RPVT,DBF_NOACCESS) {
+ prompt("Record Private")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("void * rpvt")
+ }
+ field(WDPT,DBF_NOACCESS) {
+ prompt("Watch Dog Timer ID")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("void * wdpt")
+ }
+ field(ZSV,DBF_MENU) {
+ prompt("Zero Error Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ menu(menuAlarmSevr)
+ }
+ field(OSV,DBF_MENU) {
+ prompt("One Error Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ menu(menuAlarmSevr)
+ }
+ field(COSV,DBF_MENU) {
+ prompt("Change of State Sevr")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ menu(menuAlarmSevr)
+ }
+ field(RBV,DBF_ULONG) {
+ prompt("Readback Value")
+ special(SPC_NOMOD)
+ }
+ field(ORBV,DBF_ULONG) {
+ prompt("Prev Readback Value")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(MLST,DBF_USHORT) {
+ prompt("Last Value Monitored")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LALM,DBF_USHORT) {
+ prompt("Last Value Alarmed")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(SIOL,DBF_OUTLINK) {
+ prompt("Simulation Output Link")
+ promptgroup("90 - Simulate")
+ interest(1)
+ }
+ field(SIML,DBF_INLINK) {
+ prompt("Simulation Mode Link")
+ promptgroup("90 - Simulate")
+ interest(1)
+ }
+ field(SIMM,DBF_MENU) {
+ prompt("Simulation Mode")
+ special(SPC_MOD)
+ interest(1)
+ menu(menuYesNo)
+ }
+ field(SIMS,DBF_MENU) {
+ prompt("Simulation Mode Severity")
+ promptgroup("90 - Simulate")
+ interest(2)
+ menu(menuAlarmSevr)
+ }
+ field(OLDSIMM,DBF_MENU) {
+ prompt("Prev. Simulation Mode")
+ special(SPC_NOMOD)
+ interest(4)
+ menu(menuSimm)
+ }
+ field(SSCN,DBF_MENU) {
+ prompt("Sim. Mode Scan")
+ promptgroup("90 - Simulate")
+ interest(1)
+ menu(menuScan)
+ initial("65535")
+ }
+ field(SDLY,DBF_DOUBLE) {
+ prompt("Sim. Mode Async Delay")
+ promptgroup("90 - Simulate")
+ interest(2)
+ initial("-1.0")
+ }
+ %#include "callback.h"
+ field(SIMPVT,DBF_NOACCESS) {
+ prompt("Sim. Mode Private")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("CALLBACK *simpvt")
+ }
+ field(IVOA,DBF_MENU) {
+ prompt("INVALID outpt action")
+ promptgroup("50 - Output")
+ interest(2)
+ menu(menuIvoa)
+ }
+ field(IVOV,DBF_USHORT) {
+ prompt("INVALID output value")
+ promptgroup("50 - Output")
+ interest(2)
+ }
+
+
+=head2 Record Support
+
+=head3 Record Support Routines
+
+=head2 C
+
+This routine initializes SIMM if SIML is a constant or creates a channel
+access link if SIML is PV_LINK. If SIOL is a PV_LINK a channel access link
+is created.
+
+This routine next checks to see that device support is available. The
+routine next checks to see if the device support write routine is defined.
+
+If either device support or the device support write routine does not
+exist, and error message is issued and processing is terminated.
+
+If DOL is a constant, then VAL is initialized to 1 if its value is nonzero
+or initialzed to 0 if DOL is zero, and UDF is set to FALSE.
+
+If device support includes C, it is called. VAL is set using
+RVAL, and UDF is set to FALSE.
+
+=head2 C
+
+See next section.
+
+=head2 C
+
+Fills in the values of struct valueDes so that they refer to VAL.
+
+=head2 C
+
+Retrieves ASCII string corresponding to VAL.
+
+=head2 C
+
+Retrieves ASCII strings for ZNAM and ONAM.
+
+=head2 C
+
+Checks if string matches ZNAM or ONAM, and if it does, sets VAL.
+
+=head2 Record Processing
+
+Routine process implements the following algorithm:
+
+=over 1
+
+=item 1.
+Check to see that the appropriate device support module exists. If it
+doesn't, an error message is issued and processing is terminated with
+the PACT field still set to TRUE. This ensures that processes will no
+longer be called for this record. Thus error storms will not occur.
+
+=item 2.
+If PACT is FALSE
+
+=back
+
+=over
+
+=item *
+If DOL is DB_LINK and OMSL is CLOSED_LOOP
+
+=over
+
+=item *
+get values from DOL
+
+=item *
+check for link alarm
+
+=item *
+force VAL to be 0 or 1
+
+=item *
+if MASK is defined
+
+=over
+
+=item *
+if VAL is 0 set RVAL = 0
+
+=back
+
+=item *
+else set RVAL = MASK
+
+=back
+
+=back
+
+=over
+
+=item 3.
+Check alarms: This routine checks to see if the new VAL causes the alarm
+status and severity to change. If so, NSEV, NSTA, and LALM are set.
+
+=item 4.
+Check severity and write the new value. See L
+for more information on how INVALID alarms affect output.
+
+=item 5.
+If PACT has been changed to TRUE, the device support write output routine
+has started but has not completed writing the new value. in this case, the
+processing routine merely returns, leaving PACT TRUE.
+
+=item 6.
+Check WAIT. If VAL is 1 and WAIT is greater than 0, process again with a
+VAL=0 after WAIT seconds.
+
+=item 7.
+Check to see if monitors should be invoked.
+
+=back
+
+=over 1
+
+=item *
+Alarm monitors are invoked if the alarm status or severity has changed.
+
+=item *
+Archive and value change monitors are invoked if MLST is not equal to VAL.
+
+=item *
+Monitors for RVAL and for RBV are checked whenever other monitors are
+invoked.
+
+=item *
+NSEV and NSTA are reset to 0.
+
+=back
+
+=over
+
+=item 8
+Scan forward link if necessary, set PACT FALSE, and return
+
+=back
+
+=head2 Device support
+
+=head3 Fields Of Interest To Device Support
+
+Each binary output record must have an associated set of device support
+routines. The primary responsibility of the device support routines is to
+write a new value whenever C is called. The device support routines
+are primarily interested in the following fields:
+
+=fields PACT, DPVT, NSEV, NSTA, VAL, OUT, RVAL, MASK, RBV
+
+=head3 Decive Support Routines
+
+Device support consists of the following routines:
+
+=head2 C
+
+Not currently used.
+
+=head2 C
+
+This routine is called once during IOC initialization.
+
+=head2 C
+
+This routine is optional. If provided, it is called by record support
+C routine. It should determine MASK if it is needed.
+
+=over
+
+=item *
+0: Success. RVAL modified (VAL will be set accordingly)
+
+=item *
+2: Success. VAL modified
+
+=item *
+other: Error
+
+=back
+
+=head2 C
+
+This routine is called by the ioEventScan system each time the record is
+added or deleted from an I/O event scan list. C has the value (0,1) if
+the record is being (added to, deleted from) an I/O event list. It must be
+provided for any device type that can use the ioEvent scanner.
+
+=head2 C
+
+This routine must output a new value. It returns the following values:
+
+=over
+
+=item *
+0: Success
+
+=item *
+other: Error.
+
+=back
+
+=head2 Device Support For Soft Records
+
+Two soft device support modules C and C are
+provided for output records not related to actual hardware devices. The OUT
+link type must be either CONSTANT, DB_LINK, or CA_LINK.
+
+=head3 Soft Channel
+
+This module writes the current value of VAL.
+
+If the OUT link type is PV_LINK, then C is called by
+C. C always returns a value of 2, which means
+that no conversion will ever be attempted. C calls
+C to write the current value of VAL. See L
+for details.
+
+=head3 Raw Soft Channel
+
+This module is like the previous except that it writes the current value of
+RVAL
+
+=cut
+}
+
+variable(boHIGHprecision, int)
+variable(boHIGHlimit, double)
diff --git a/modules/database/src/std/rec/calcRecord.dbd b/modules/database/src/std/rec/calcRecord.dbd
deleted file mode 100644
index e7eb0eee3..000000000
--- a/modules/database/src/std/rec/calcRecord.dbd
+++ /dev/null
@@ -1,324 +0,0 @@
-#*************************************************************************
-# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
-# National Laboratory.
-# Copyright (c) 2002 The Regents of the University of California, as
-# Operator of Los Alamos National Laboratory.
-# EPICS BASE is distributed subject to a Software License Agreement found
-# in file LICENSE that is included with this distribution.
-#*************************************************************************
-recordtype(calc) {
- include "dbCommon.dbd"
- field(VAL,DBF_DOUBLE) {
- prompt("Result")
- promptgroup("50 - Output")
- asl(ASL0)
- }
- field(CALC,DBF_STRING) {
- prompt("Calculation")
- promptgroup("30 - Action")
- special(SPC_CALC)
- pp(TRUE)
- size(80)
- initial("0")
- }
- field(INPA,DBF_INLINK) {
- prompt("Input A")
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPB,DBF_INLINK) {
- prompt("Input B")
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPC,DBF_INLINK) {
- prompt("Input C")
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPD,DBF_INLINK) {
- prompt("Input D")
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPE,DBF_INLINK) {
- prompt("Input E")
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPF,DBF_INLINK) {
- prompt("Input F")
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPG,DBF_INLINK) {
- prompt("Input G")
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPH,DBF_INLINK) {
- prompt("Input H")
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPI,DBF_INLINK) {
- prompt("Input I")
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPJ,DBF_INLINK) {
- prompt("Input J")
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPK,DBF_INLINK) {
- prompt("Input K")
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPL,DBF_INLINK) {
- prompt("Input L")
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(EGU,DBF_STRING) {
- prompt("Engineering Units")
- promptgroup("80 - Display")
- interest(1)
- size(16)
- prop(YES)
- }
- field(PREC,DBF_SHORT) {
- prompt("Display Precision")
- promptgroup("80 - Display")
- interest(1)
- prop(YES)
- }
- field(HOPR,DBF_DOUBLE) {
- prompt("High Operating Rng")
- promptgroup("80 - Display")
- interest(1)
- prop(YES)
- }
- field(LOPR,DBF_DOUBLE) {
- prompt("Low Operating Range")
- promptgroup("80 - Display")
- interest(1)
- prop(YES)
- }
- field(HIHI,DBF_DOUBLE) {
- prompt("Hihi Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(LOLO,DBF_DOUBLE) {
- prompt("Lolo Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(HIGH,DBF_DOUBLE) {
- prompt("High Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(LOW,DBF_DOUBLE) {
- prompt("Low Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(HHSV,DBF_MENU) {
- prompt("Hihi Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(LLSV,DBF_MENU) {
- prompt("Lolo Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(HSV,DBF_MENU) {
- prompt("High Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(LSV,DBF_MENU) {
- prompt("Low Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(AFTC, DBF_DOUBLE) {
- prompt("Alarm Filter Time Constant")
- promptgroup("70 - Alarm")
- interest(1)
- }
- field(AFVL, DBF_DOUBLE) {
- prompt("Alarm Filter Value")
- special(SPC_NOMOD)
- interest(3)
- }
- field(HYST,DBF_DOUBLE) {
- prompt("Alarm Deadband")
- promptgroup("70 - Alarm")
- interest(1)
- }
- field(ADEL,DBF_DOUBLE) {
- prompt("Archive Deadband")
- promptgroup("80 - Display")
- interest(1)
- }
- field(MDEL,DBF_DOUBLE) {
- prompt("Monitor Deadband")
- promptgroup("80 - Display")
- interest(1)
- }
- field(A,DBF_DOUBLE) {
- prompt("Value of Input A")
- pp(TRUE)
- }
- field(B,DBF_DOUBLE) {
- prompt("Value of Input B")
- pp(TRUE)
- }
- field(C,DBF_DOUBLE) {
- prompt("Value of Input C")
- pp(TRUE)
- }
- field(D,DBF_DOUBLE) {
- prompt("Value of Input D")
- pp(TRUE)
- }
- field(E,DBF_DOUBLE) {
- prompt("Value of Input E")
- pp(TRUE)
- }
- field(F,DBF_DOUBLE) {
- prompt("Value of Input F")
- pp(TRUE)
- }
- field(G,DBF_DOUBLE) {
- prompt("Value of Input G")
- pp(TRUE)
- }
- field(H,DBF_DOUBLE) {
- prompt("Value of Input H")
- pp(TRUE)
- }
- field(I,DBF_DOUBLE) {
- prompt("Value of Input I")
- pp(TRUE)
- }
- field(J,DBF_DOUBLE) {
- prompt("Value of Input J")
- pp(TRUE)
- }
- field(K,DBF_DOUBLE) {
- prompt("Value of Input K")
- pp(TRUE)
- }
- field(L,DBF_DOUBLE) {
- prompt("Value of Input L")
- pp(TRUE)
- }
- field(LA,DBF_DOUBLE) {
- prompt("Prev Value of A")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LB,DBF_DOUBLE) {
- prompt("Prev Value of B")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LC,DBF_DOUBLE) {
- prompt("Prev Value of C")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LD,DBF_DOUBLE) {
- prompt("Prev Value of D")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LE,DBF_DOUBLE) {
- prompt("Prev Value of E")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LF,DBF_DOUBLE) {
- prompt("Prev Value of F")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LG,DBF_DOUBLE) {
- prompt("Prev Value of G")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LH,DBF_DOUBLE) {
- prompt("Prev Value of H")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LI,DBF_DOUBLE) {
- prompt("Prev Value of I")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LJ,DBF_DOUBLE) {
- prompt("Prev Value of J")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LK,DBF_DOUBLE) {
- prompt("Prev Value of K")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LL,DBF_DOUBLE) {
- prompt("Prev Value of L")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LALM,DBF_DOUBLE) {
- prompt("Last Value Alarmed")
- special(SPC_NOMOD)
- interest(3)
- }
- field(ALST,DBF_DOUBLE) {
- prompt("Last Value Archived")
- special(SPC_NOMOD)
- interest(3)
- }
- field(MLST,DBF_DOUBLE) {
- prompt("Last Val Monitored")
- special(SPC_NOMOD)
- interest(3)
- }
- %#include "postfix.h"
- field(RPCL,DBF_NOACCESS) {
- prompt("Reverse Polish Calc")
- special(SPC_NOMOD)
- interest(4)
- extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
- }
-}
diff --git a/modules/database/src/std/rec/calcRecord.dbd.pod b/modules/database/src/std/rec/calcRecord.dbd.pod
new file mode 100644
index 000000000..c50667fb3
--- /dev/null
+++ b/modules/database/src/std/rec/calcRecord.dbd.pod
@@ -0,0 +1,948 @@
+#*************************************************************************
+# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
+# National Laboratory.
+# Copyright (c) 2002 The Regents of the University of California, as
+# Operator of Los Alamos National Laboratory.
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
+
+=title Calculation Record (calc)
+
+The calculation or "Calc" record is used to perform algebraic, relational,
+and logical operations on values retrieved from other records. The result
+of its operations can then be accessed by another record so that it can
+then be used.
+
+=head2 Parameter Fields
+
+The fields in the record fall into the following categories:
+
+=over 1
+
+=item *
+scan parameters
+
+=item *
+read parameters
+
+=item *
+expression parameters
+
+=item *
+operator display parameters
+
+=item *
+alarm parameters
+
+=item *
+monitor parameters
+
+=item *
+run-time parameters
+
+=back
+
+=recordtype calc
+
+=cut
+
+recordtype(calc) {
+
+=head3 Scan Parameters
+
+The Calc record has the standard fields for specifying under what
+circumstances the record will be processed. These fields are listed in
+L. In addition, L explains how these
+fields are used. Since the Calc record supports no direct interfaces to
+hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot
+be C.
+
+=fields SCAN
+
+
+=head3 Read Parameters
+
+The read parameters for the Calc record consist of 12 input links INPA,
+INPB, ... INPL. The fields can be database links, channel access links, or
+constants. If they are links, they must specify another record's field or a
+channel access link. If they are constants, they will be initialized with
+the value they are configured with and can be changed via C. They
+cannot be hardware addresses.
+
+See L for information on how to specify database
+links.
+
+=fields INPA, INPB, INPC, INPD, INPE, INPF, INPG, INPH, INPI, INPJ, INPK, INPL
+
+=head3 Expression
+
+At the core of the Calc record lies the CALC and RPCL fields. The CALC field
+contains the infix expresion which the record routine will use when it
+processes the record. The resulting value is placed in the VAL field and
+can be accessed from there. The CALC expression is actually converted to
+opcode and stored as Reverse Polish Notation in the RPCL field. It is this
+expression which is actually used to calculate VAL. The Reverse Polish
+expression is evaluated more efficiently during run-time than an infix
+expression. CALC can be changed at run-time, and a special record routine
+calls a function to convert it to Reverse Polish Notation.
+
+The infix expressions that can be used are very similar to the C expression
+syntax, but with some additions and subtle differences in operator meaning
+and precedence. The string may contain a series of expressions separated by
+a semi-colon character ";" any one of which may actually provide the
+calculation result; however, all of the other expressions included must
+assign their result to a variable. All alphabetic elements described below
+are case independent, so upper and lower case letters may be used and mixed
+in the variable and function names as desired. Spaces may be used anywhere
+within an expression except between characters that make up a single
+expression element.
+
+The range of expressions supported by the calculation record are separated
+into literals, constants, operands, algebraic operators, trigonometric operators,
+relational operators, logical operators, the assignment operator,
+parentheses and commas, and the question mark or '?:' operator.
+
+=fields CALC, RPCL
+
+=head3 Literals
+
+=over 1
+
+=item *
+Standard double precision floating point numbers
+
+=item *
+Inf: Infinity
+
+=item *
+Nan: Not a Number
+
+=back
+
+=head3 Constants
+
+=over 1
+
+=item *
+PI: returns the mathematical constant E
+
+=item *
+D2R: evaluates to E/180 which, when used as a multiplier, converts an
+angle from degrees to radians
+
+=item *
+R2D: evaluates to 180/E which as a multiplier converts an angle from
+radians to degrees
+
+=back
+
+=head3 Operands
+
+The expression uses the values retrieved from the INPx links as operands,
+though constants can be used as operands too. These values retrieved from
+the input links are stored in the A-L fields. The values to be used in the
+expression are simply referenced by the field letter. For instance, the
+value obtained from INPA link is stored in the field A, and the value
+obtained from INPB is stored in field B. The field names can be included in
+the expression which will operate on their respective values, as in A+B.
+Also, the RNDM nullary function can be included as an operand in the
+expression in order to generate a random number between 0 and 1.
+
+=fields A, B, C, D, E, F, G, H, I, J, K, L
+
+The keyword VAL returns the current contents of the VAL field (which can be
+written to by a CA put, so it might I be the result from the last time
+the expression was evaluated).
+
+=head3 Algebraic Operators
+
+=over 1
+
+=item *
+ABS: Absolute value (unary)
+
+=item *
+SQR: Square root (unary)
+
+=item *
+MIN: Minimum (any number of args)
+
+=item *
+MAX: Maximum (any number of args)
+
+=item *
+FINITE: returns non-zero if none of the arguments are NaN or Inf (any
+number of args)
+
+=item *
+ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number
+of args)
+
+=item *
+CEIL: Ceiling (unary)
+
+=item *
+FLOOR: Floor (unary)
+
+=item *
+LOG: Log base 10 (unary)
+
+=item *
+LOGE: Natural log (unary)
+
+=item *
+LN: Natural log (unary)
+
+=item *
+EXP: Exponential function (unary)
+
+=item *
+^ : Exponential (binary)
+
+=item *
+** : Exponential (binary)
+
+=item *
++ : Addition (binary)
+
+=item *
+- : Subtraction (binary)
+
+=item *
+* : Multiplication (binary)
+
+=item *
+/ : Division (binary)
+
+=item *
+% : Modulo (binary)
+
+=item *
+NOT: Negate (unary)
+
+=back
+
+=head3 Trigonometric Operators
+
+=over 1
+
+=item *
+SIN: Sine
+
+=item *
+SINH: Hyperbolic sine
+
+=item *
+ASIN: Arc sine
+
+=item *
+COS: Cosine
+
+=item *
+COSH: Hyperbolic cosine
+
+=item *
+ACOS: Arc cosine
+
+=item *
+TAN: Tangent
+
+=item *
+TANH: Hyperbolic tangent
+
+=item *
+ATAN: Arc tangent
+
+=back
+
+=head3 Relational Operators
+
+=over 1
+
+=item *
+>= : Greater than or equal to
+
+=item *
+> : Greater than
+
+=item *
+<= : Less than or equal to
+
+=item *
+< : Less than
+
+=item *
+# : Not equal to
+
+=item *
+= : Equal to
+
+=back
+
+=head3 Logical Operators
+
+=over 1
+
+=item *
+&& : And
+
+=item *
+|| : Or
+
+=item *
+! : Not
+
+=back
+
+=head3 Bitwise Operators
+
+=over 1
+
+=item *
+| : Bitwise Or
+
+=item *
+& : Bitwise And
+
+=item *
+OR : Bitwise Or
+
+=item *
+AND : Bitwise And
+
+=item *
+XOR : Bitwise Exclusive Or
+
+=item *
+~ : One's Complement
+
+=item *
+<< : Left shift
+
+=item *
+>> : Right shift
+
+=back
+
+=head3 Assignment Operator
+
+=over 1
+
+=item *
+:= : assigns a value (right hand side) to a variable (i.e. field)
+
+=back
+
+=head3 Parantheses, Comma, and Semicolon
+
+The open and close parentheses are supported. Nested parentheses are
+supported.
+
+The comma is supported when used to separate the arguments of a binary
+function.
+
+The semicolon is used to separate expressions. Although only one
+traditional calculation expression is allowed, multiple assignment
+expressions are allowed.
+
+=head3 Conditional Expression
+
+The C language's question mark operator is supported. The format is:
+C
+
+=head3 Expression Examples
+
+=head3 Algebraic
+
+C
+
+=over 1
+
+=item *
+Result is A + B + 10
+
+=back
+
+=head3 Relational
+
+C<(A + B) < (C + D)>
+
+=over 1
+
+=item *
+Result is 1 if (A + B) < (C + D)
+
+=item *
+Result is 0 if (A + B) >= (C + D)
+
+=back
+
+=head3 Question Mark
+
+C<(A + B) < (C + D) ? E : F + L + 10>
+
+=over 1
+
+=item *
+Result is E if (A + B) < (C + D)
+
+=item *
+Result is F + L + 10 if (A + B) >= (C + D)
+
+=back
+
+Prior to Base 3.14.9 it was legal to omit the : and the second (else) part
+of the conditional, like this:
+
+C<(A + B)<(C + D) ? E>
+
+=over 1
+
+=item
+Result is E if (A + B)<(C + D)
+
+=item
+Result is unchanged if (A + B)>=(C + D)
+
+From 3.14.9 onwards, this expresion must be written as
+C<(A + B) < (C + D) ? E : VAL>
+
+=back
+
+=head3 Logical
+
+C
+
+=over 1
+
+=item *
+Causes the following to occur:
+
+=over 1
+
+=item *
+Convert A to integer
+
+=item *
+Convert B to integer
+
+=item *
+Bitwise And A and B
+
+=item *
+Convert result to floating point
+
+=back
+
+=back
+
+=head3 Assignment
+
+C
+
+=over 1
+
+=item *
+Causes the Calc record to output the successive values of a sine curve in
+1 degree intervals.
+
+=back
+
+=head3 Operator Display Parameters
+
+These parameters are used to present meaningful data to the operator. These
+fields are used to display VAL and other parameters of the calculation
+record either textually or graphically.
+
+The EGU field contains a string of up to 16 characters which is supplied by
+the user and which describes the values being operated upon. The string is
+retrieved whenever the routine C is called. The EGU string is
+solely for an operator's sake and does not have to be used.
+
+The HOPR and LOPR fields only refer to the limits of the VAL, HIHI, HIGH,
+LOW and LOLO fields. PREC controls the precision of the VAL field.
+
+See L for more on the record name (NAME)
+and description (DESC) fields.
+
+=fields EGU, PREC, HOPR, LOPR, NAME, DESC
+
+=head3 Alarm Parameters
+
+The possible alarm conditions for the Calc record are the SCAN, READ,
+Calculation, and limit alarms. The SCAN and READ alarms are called by the
+record support routines. The Calculation alarm is called by the record
+processing routine when the CALC expression is an invalid one, upon which
+an error message is generated.
+
+The following alarm parameters which are configured by the user, define the
+limit alarms for the VAL field and the severity corresponding to those
+conditions.
+
+The HYST field defines an alarm deadband for each limit. See L
+for a complete explanation of alarms of these fields. L
+lists other fields related to alarms that are common to all record types.
+
+=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
+
+=head3 Monitor Parameters
+
+These paramaeters are used to determine when to send monitors for the value
+fields. These monitors are sent when the value field exceeds the last
+monitored field by the appropriate deadband, the ADEL for archiver monitors
+and the MDEL field for all other types of monitors. If these fields have a
+value of zero, everytime the value changes, monitors are triggered; if they have a
+value of -1, everytime the record is scanned, monitors are triggered. See
+L for a complete explanation of monitors.
+
+=fields ADEL, MDEL
+
+=head3 Run-time Parameters
+
+These fields are not configurable using a configuration tool and none are
+modifiable at run-time. They are used to process the record.
+
+The LALM field is used to implement the hysteresis factor for the alarm
+limits.
+
+The LA-LL fields are used to decide when to trigger monitors for the
+corresponding fields. For instance, if LA does not equal the value A,
+monitors for A are triggered. The MLST and ALST fields are used in the same
+manner for the VAL field.
+
+=fields LALM, ALST, MLST, LA, LB, LC, LD, LE, LF, LG, LH, LI, LJ, LK, LL
+
+=cut
+
+ include "dbCommon.dbd"
+ field(VAL,DBF_DOUBLE) {
+ prompt("Result")
+ promptgroup("50 - Output")
+ asl(ASL0)
+ }
+ field(CALC,DBF_STRING) {
+ prompt("Calculation")
+ promptgroup("30 - Action")
+ special(SPC_CALC)
+ pp(TRUE)
+ size(80)
+ initial("0")
+ }
+ field(INPA,DBF_INLINK) {
+ prompt("Input A")
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPB,DBF_INLINK) {
+ prompt("Input B")
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPC,DBF_INLINK) {
+ prompt("Input C")
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPD,DBF_INLINK) {
+ prompt("Input D")
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPE,DBF_INLINK) {
+ prompt("Input E")
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPF,DBF_INLINK) {
+ prompt("Input F")
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPG,DBF_INLINK) {
+ prompt("Input G")
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPH,DBF_INLINK) {
+ prompt("Input H")
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPI,DBF_INLINK) {
+ prompt("Input I")
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPJ,DBF_INLINK) {
+ prompt("Input J")
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPK,DBF_INLINK) {
+ prompt("Input K")
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPL,DBF_INLINK) {
+ prompt("Input L")
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(EGU,DBF_STRING) {
+ prompt("Engineering Units")
+ promptgroup("80 - Display")
+ interest(1)
+ size(16)
+ prop(YES)
+ }
+ field(PREC,DBF_SHORT) {
+ prompt("Display Precision")
+ promptgroup("80 - Display")
+ interest(1)
+ prop(YES)
+ }
+ field(HOPR,DBF_DOUBLE) {
+ prompt("High Operating Rng")
+ promptgroup("80 - Display")
+ interest(1)
+ prop(YES)
+ }
+ field(LOPR,DBF_DOUBLE) {
+ prompt("Low Operating Range")
+ promptgroup("80 - Display")
+ interest(1)
+ prop(YES)
+ }
+ field(HIHI,DBF_DOUBLE) {
+ prompt("Hihi Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(LOLO,DBF_DOUBLE) {
+ prompt("Lolo Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(HIGH,DBF_DOUBLE) {
+ prompt("High Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(LOW,DBF_DOUBLE) {
+ prompt("Low Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(HHSV,DBF_MENU) {
+ prompt("Hihi Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(LLSV,DBF_MENU) {
+ prompt("Lolo Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(HSV,DBF_MENU) {
+ prompt("High Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(LSV,DBF_MENU) {
+ prompt("Low Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(AFTC, DBF_DOUBLE) {
+ prompt("Alarm Filter Time Constant")
+ promptgroup("70 - Alarm")
+ interest(1)
+ }
+ field(AFVL, DBF_DOUBLE) {
+ prompt("Alarm Filter Value")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(HYST,DBF_DOUBLE) {
+ prompt("Alarm Deadband")
+ promptgroup("70 - Alarm")
+ interest(1)
+ }
+ field(ADEL,DBF_DOUBLE) {
+ prompt("Archive Deadband")
+ promptgroup("80 - Display")
+ interest(1)
+ }
+ field(MDEL,DBF_DOUBLE) {
+ prompt("Monitor Deadband")
+ promptgroup("80 - Display")
+ interest(1)
+ }
+ field(A,DBF_DOUBLE) {
+ prompt("Value of Input A")
+ pp(TRUE)
+ }
+ field(B,DBF_DOUBLE) {
+ prompt("Value of Input B")
+ pp(TRUE)
+ }
+ field(C,DBF_DOUBLE) {
+ prompt("Value of Input C")
+ pp(TRUE)
+ }
+ field(D,DBF_DOUBLE) {
+ prompt("Value of Input D")
+ pp(TRUE)
+ }
+ field(E,DBF_DOUBLE) {
+ prompt("Value of Input E")
+ pp(TRUE)
+ }
+ field(F,DBF_DOUBLE) {
+ prompt("Value of Input F")
+ pp(TRUE)
+ }
+ field(G,DBF_DOUBLE) {
+ prompt("Value of Input G")
+ pp(TRUE)
+ }
+ field(H,DBF_DOUBLE) {
+ prompt("Value of Input H")
+ pp(TRUE)
+ }
+ field(I,DBF_DOUBLE) {
+ prompt("Value of Input I")
+ pp(TRUE)
+ }
+ field(J,DBF_DOUBLE) {
+ prompt("Value of Input J")
+ pp(TRUE)
+ }
+ field(K,DBF_DOUBLE) {
+ prompt("Value of Input K")
+ pp(TRUE)
+ }
+ field(L,DBF_DOUBLE) {
+ prompt("Value of Input L")
+ pp(TRUE)
+ }
+ field(LA,DBF_DOUBLE) {
+ prompt("Prev Value of A")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LB,DBF_DOUBLE) {
+ prompt("Prev Value of B")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LC,DBF_DOUBLE) {
+ prompt("Prev Value of C")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LD,DBF_DOUBLE) {
+ prompt("Prev Value of D")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LE,DBF_DOUBLE) {
+ prompt("Prev Value of E")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LF,DBF_DOUBLE) {
+ prompt("Prev Value of F")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LG,DBF_DOUBLE) {
+ prompt("Prev Value of G")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LH,DBF_DOUBLE) {
+ prompt("Prev Value of H")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LI,DBF_DOUBLE) {
+ prompt("Prev Value of I")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LJ,DBF_DOUBLE) {
+ prompt("Prev Value of J")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LK,DBF_DOUBLE) {
+ prompt("Prev Value of K")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LL,DBF_DOUBLE) {
+ prompt("Prev Value of L")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LALM,DBF_DOUBLE) {
+ prompt("Last Value Alarmed")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(ALST,DBF_DOUBLE) {
+ prompt("Last Value Archived")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(MLST,DBF_DOUBLE) {
+ prompt("Last Val Monitored")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ %#include "postfix.h"
+ field(RPCL,DBF_NOACCESS) {
+ prompt("Reverse Polish Calc")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
+ }
+
+=head2 Record Support
+
+=head3 Record Support Routines
+
+=head2 C
+
+For each constant input link, the corresponding value field is initialized
+with the constant value if the input link is CONSTANT or a channel access
+link is created if the input link is a PV_LINK.
+
+A routine postfix is called to convert the infix expression in CALC to
+Reverse Polish Notation. The result is stored in RPCL.
+
+=head2 C
+
+See next section.
+
+=head2 C
+
+This is called if CALC is changed. C calls postfix.
+
+=head2 C
+
+Fills in the values of struct valueDes so that the refer to VAL.
+
+=head2 C
+
+Retrieves EGU.
+
+=head2 C
+
+Retrieves PREC.
+
+=head2 C
+
+Sets the upper display and lower display limits for a field. If the field
+is VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else
+if the field has upper and lower limits defined they will be used, else the
+upper and lower maximum values for the field will be used.
+
+=head2 C
+
+Sets the upper control and the lower control limits for a field. If the
+field is VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and
+LOPR, else if the field has upper and lower limits defined they will be
+used, else the upper and lower maximum values for the field type will be
+used.
+
+=head2 C
+
+Sets the following values:
+
+=over 1
+
+upper_alarm_limit = HIHI
+
+upper_warning_limit = HIGH
+
+lower_warning_limit = LOW
+
+lower_alarm_limit = LOLO
+
+=back
+
+=head3 Record Processing
+
+Routine process implements the following algorithm:
+
+=over 1
+
+=item 1.
+Fetch all arguments.
+
+=item 2.
+Call routine C, which calculates VAL from the postfix version of
+the expression given in CALC. If C returns success UDF is set to
+FALSE.
+
+=item 3.
+Check alarms. This routine checks to see if the new VAL causes the alarm
+status and severity to change. If so, NSEV, NSTA, and LALM are set. It also
+honors the alarm hysteresis factor (HYST). Thus the value must change by
+at least HYST before the alarm status and severity changes.
+
+=item 4.
+Check to see if monitors should be invoked.
+
+=back
+
+=over 1
+
+=item *
+Alarm monitors are invoked if the alarm status or severity has changed.
+
+=item *
+Archive and values change monitors are invoked if ADEL and MDEL conditions
+are met.
+
+=item *
+Monitors for A-L are checked whenever other monitors are invoked.
+
+=item *
+NSEV and NSTA are reset to 0.
+
+=back
+
+=over
+
+=item 5.
+Scan forward link if necessary, set PACT FALSE, and return.
+
+=back
+
+=cut
+
+}
diff --git a/modules/database/src/std/rec/calcoutRecord.dbd b/modules/database/src/std/rec/calcoutRecord.dbd
deleted file mode 100644
index 5bf2e54de..000000000
--- a/modules/database/src/std/rec/calcoutRecord.dbd
+++ /dev/null
@@ -1,530 +0,0 @@
-#*************************************************************************
-# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
-# National Laboratory.
-# Copyright (c) 2002 The Regents of the University of California, as
-# Operator of Los Alamos National Laboratory.
-# EPICS BASE is distributed subject to a Software License Agreement found
-# in file LICENSE that is included with this distribution.
-#*************************************************************************
-menu(calcoutOOPT) {
- choice(calcoutOOPT_Every_Time,"Every Time")
- choice(calcoutOOPT_On_Change,"On Change")
- choice(calcoutOOPT_When_Zero,"When Zero")
- choice(calcoutOOPT_When_Non_zero,"When Non-zero")
- choice(calcoutOOPT_Transition_To_Zero,"Transition To Zero")
- choice(calcoutOOPT_Transition_To_Non_zero,"Transition To Non-zero")
-}
-menu(calcoutDOPT) {
- choice(calcoutDOPT_Use_VAL,"Use CALC")
- choice(calcoutDOPT_Use_OVAL,"Use OCAL")
-}
-menu(calcoutINAV) {
- choice(calcoutINAV_EXT_NC,"Ext PV NC")
- choice(calcoutINAV_EXT,"Ext PV OK")
- choice(calcoutINAV_LOC,"Local PV")
- choice(calcoutINAV_CON,"Constant")
-}
-recordtype(calcout) {
- include "dbCommon.dbd"
- field(RPVT,DBF_NOACCESS) {
- prompt("Record Private")
- special(SPC_NOMOD)
- interest(4)
- extra("struct rpvtStruct *rpvt")
- }
- field(VAL,DBF_DOUBLE) {
- prompt("Result")
- promptgroup("50 - Output")
- asl(ASL0)
- }
- field(PVAL,DBF_DOUBLE) {
- prompt("Previous Value")
- }
- field(CALC,DBF_STRING) {
- prompt("Calculation")
- promptgroup("30 - Action")
- special(SPC_CALC)
- pp(TRUE)
- size(80)
- initial("0")
- }
- field(CLCV,DBF_LONG) {
- prompt("CALC Valid")
- interest(1)
- }
- field(INPA,DBF_INLINK) {
- prompt("Input A")
- special(SPC_MOD)
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPB,DBF_INLINK) {
- prompt("Input B")
- special(SPC_MOD)
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPC,DBF_INLINK) {
- prompt("Input C")
- special(SPC_MOD)
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPD,DBF_INLINK) {
- prompt("Input D")
- special(SPC_MOD)
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPE,DBF_INLINK) {
- prompt("Input E")
- special(SPC_MOD)
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPF,DBF_INLINK) {
- prompt("Input F")
- special(SPC_MOD)
- promptgroup("41 - Input A-F")
- interest(1)
- }
- field(INPG,DBF_INLINK) {
- prompt("Input G")
- special(SPC_MOD)
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPH,DBF_INLINK) {
- prompt("Input H")
- special(SPC_MOD)
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPI,DBF_INLINK) {
- prompt("Input I")
- special(SPC_MOD)
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPJ,DBF_INLINK) {
- prompt("Input J")
- special(SPC_MOD)
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPK,DBF_INLINK) {
- prompt("Input K")
- special(SPC_MOD)
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(INPL,DBF_INLINK) {
- prompt("Input L")
- special(SPC_MOD)
- promptgroup("42 - Input G-L")
- interest(1)
- }
- field(OUT,DBF_OUTLINK) {
- prompt("Output Specification")
- special(SPC_MOD)
- promptgroup("50 - Output")
- interest(1)
- }
- field(INAV,DBF_MENU) {
- prompt("INPA PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INBV,DBF_MENU) {
- prompt("INPB PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INCV,DBF_MENU) {
- prompt("INPC PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INDV,DBF_MENU) {
- prompt("INPD PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INEV,DBF_MENU) {
- prompt("INPE PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INFV,DBF_MENU) {
- prompt("INPF PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INGV,DBF_MENU) {
- prompt("INPG PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INHV,DBF_MENU) {
- prompt("INPH PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INIV,DBF_MENU) {
- prompt("INPI PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INJV,DBF_MENU) {
- prompt("INPJ PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INKV,DBF_MENU) {
- prompt("INPK PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(INLV,DBF_MENU) {
- prompt("INPL PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- initial("1")
- }
- field(OUTV,DBF_MENU) {
- prompt("OUT PV Status")
- special(SPC_NOMOD)
- interest(1)
- menu(calcoutINAV)
- }
- field(OOPT,DBF_MENU) {
- prompt("Output Execute Opt")
- promptgroup("50 - Output")
- interest(1)
- menu(calcoutOOPT)
- }
- field(ODLY,DBF_DOUBLE) {
- prompt("Output Execute Delay")
- promptgroup("50 - Output")
- asl(ASL0)
- interest(1)
- }
- field(DLYA,DBF_USHORT) {
- prompt("Output Delay Active")
- special(SPC_NOMOD)
- asl(ASL0)
- }
- field(DOPT,DBF_MENU) {
- prompt("Output Data Opt")
- promptgroup("30 - Action")
- interest(1)
- menu(calcoutDOPT)
- }
- field(OCAL,DBF_STRING) {
- prompt("Output Calculation")
- promptgroup("30 - Action")
- special(SPC_CALC)
- pp(TRUE)
- size(80)
- initial("0")
- }
- field(OCLV,DBF_LONG) {
- prompt("OCAL Valid")
- interest(1)
- }
- field(OEVT,DBF_STRING) {
- prompt("Event To Issue")
- promptgroup("30 - Action")
- special(SPC_MOD)
- asl(ASL0)
- size(40)
- }
- %#include "dbScan.h"
- field(EPVT, DBF_NOACCESS) {
- prompt("Event private")
- special(SPC_NOMOD)
- interest(4)
- extra("EVENTPVT epvt")
- }
- field(IVOA,DBF_MENU) {
- prompt("INVALID output action")
- promptgroup("50 - Output")
- interest(2)
- menu(menuIvoa)
- }
- field(IVOV,DBF_DOUBLE) {
- prompt("INVALID output value")
- promptgroup("50 - Output")
- interest(2)
- }
- field(EGU,DBF_STRING) {
- prompt("Engineering Units")
- promptgroup("80 - Display")
- interest(1)
- size(16)
- prop(YES)
- }
- field(PREC,DBF_SHORT) {
- prompt("Display Precision")
- promptgroup("80 - Display")
- interest(1)
- prop(YES)
- }
- field(HOPR,DBF_DOUBLE) {
- prompt("High Operating Rng")
- promptgroup("80 - Display")
- interest(1)
- prop(YES)
- }
- field(LOPR,DBF_DOUBLE) {
- prompt("Low Operating Range")
- promptgroup("80 - Display")
- interest(1)
- prop(YES)
- }
- field(HIHI,DBF_DOUBLE) {
- prompt("Hihi Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(LOLO,DBF_DOUBLE) {
- prompt("Lolo Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(HIGH,DBF_DOUBLE) {
- prompt("High Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(LOW,DBF_DOUBLE) {
- prompt("Low Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(HHSV,DBF_MENU) {
- prompt("Hihi Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(LLSV,DBF_MENU) {
- prompt("Lolo Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(HSV,DBF_MENU) {
- prompt("High Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(LSV,DBF_MENU) {
- prompt("Low Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(HYST,DBF_DOUBLE) {
- prompt("Alarm Deadband")
- promptgroup("70 - Alarm")
- interest(1)
- }
- field(ADEL,DBF_DOUBLE) {
- prompt("Archive Deadband")
- promptgroup("80 - Display")
- interest(1)
- }
- field(MDEL,DBF_DOUBLE) {
- prompt("Monitor Deadband")
- promptgroup("80 - Display")
- interest(1)
- }
- field(A,DBF_DOUBLE) {
- prompt("Value of Input A")
- pp(TRUE)
- }
- field(B,DBF_DOUBLE) {
- prompt("Value of Input B")
- pp(TRUE)
- }
- field(C,DBF_DOUBLE) {
- prompt("Value of Input C")
- pp(TRUE)
- }
- field(D,DBF_DOUBLE) {
- prompt("Value of Input D")
- pp(TRUE)
- }
- field(E,DBF_DOUBLE) {
- prompt("Value of Input E")
- pp(TRUE)
- }
- field(F,DBF_DOUBLE) {
- prompt("Value of Input F")
- pp(TRUE)
- }
- field(G,DBF_DOUBLE) {
- prompt("Value of Input G")
- pp(TRUE)
- }
- field(H,DBF_DOUBLE) {
- prompt("Value of Input H")
- pp(TRUE)
- }
- field(I,DBF_DOUBLE) {
- prompt("Value of Input I")
- pp(TRUE)
- }
- field(J,DBF_DOUBLE) {
- prompt("Value of Input J")
- pp(TRUE)
- }
- field(K,DBF_DOUBLE) {
- prompt("Value of Input K")
- pp(TRUE)
- }
- field(L,DBF_DOUBLE) {
- prompt("Value of Input L")
- pp(TRUE)
- }
- field(OVAL,DBF_DOUBLE) {
- prompt("Output Value")
- asl(ASL0)
- }
- field(LA,DBF_DOUBLE) {
- prompt("Prev Value of A")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LB,DBF_DOUBLE) {
- prompt("Prev Value of B")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LC,DBF_DOUBLE) {
- prompt("Prev Value of C")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LD,DBF_DOUBLE) {
- prompt("Prev Value of D")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LE,DBF_DOUBLE) {
- prompt("Prev Value of E")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LF,DBF_DOUBLE) {
- prompt("Prev Value of F")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LG,DBF_DOUBLE) {
- prompt("Prev Value of G")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LH,DBF_DOUBLE) {
- prompt("Prev Value of H")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LI,DBF_DOUBLE) {
- prompt("Prev Value of I")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LJ,DBF_DOUBLE) {
- prompt("Prev Value of J")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LK,DBF_DOUBLE) {
- prompt("Prev Value of K")
- special(SPC_NOMOD)
- interest(3)
- }
- field(LL,DBF_DOUBLE) {
- prompt("Prev Value of L")
- special(SPC_NOMOD)
- interest(3)
- }
- field(POVL,DBF_DOUBLE) {
- prompt("Prev Value of OVAL")
- asl(ASL0)
- }
- field(LALM,DBF_DOUBLE) {
- prompt("Last Value Alarmed")
- special(SPC_NOMOD)
- interest(3)
- }
- field(ALST,DBF_DOUBLE) {
- prompt("Last Value Archived")
- special(SPC_NOMOD)
- interest(3)
- }
- field(MLST,DBF_DOUBLE) {
- prompt("Last Val Monitored")
- special(SPC_NOMOD)
- interest(3)
- }
- %#include "postfix.h"
- field(RPCL,DBF_NOACCESS) {
- prompt("Reverse Polish Calc")
- special(SPC_NOMOD)
- interest(4)
- extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
- }
- field(ORPC,DBF_NOACCESS) {
- prompt("Reverse Polish OCalc")
- special(SPC_NOMOD)
- interest(4)
- extra("char orpc[INFIX_TO_POSTFIX_SIZE(80)]")
- }
-}
-
-variable(calcoutODLYprecision, int)
-variable(calcoutODLYlimit, double)
diff --git a/modules/database/src/std/rec/calcoutRecord.dbd.pod b/modules/database/src/std/rec/calcoutRecord.dbd.pod
new file mode 100644
index 000000000..6289f9043
--- /dev/null
+++ b/modules/database/src/std/rec/calcoutRecord.dbd.pod
@@ -0,0 +1,1271 @@
+#*************************************************************************
+# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
+# National Laboratory.
+# Copyright (c) 2002 The Regents of the University of California, as
+# Operator of Los Alamos National Laboratory.
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
+
+=title Calculation Output Record (calcout)
+
+The Calculation Output or "Calcout" record is similar to the Calc record
+with the added feature of having outputs (an "output link" and an "output
+event") which are conditionally executed based on the result of the
+calculation. This feature allows conditional branching to be implemented
+within an EPICS database (e.g. process Record_A only if Record_B has a
+value of 0). The Calcout record is also similar to the Wait record (with
+additional features) but uses EPICS standard INLINK and OUTLINK fields
+rather than the DBF_STRING fields used in the Wait record. For new
+databases, it is recommended that the Calcout record be used instead of the
+Wait record.
+
+=head2 Parameter Fields
+
+The fields in this record fall into these categories:
+
+=over 1
+
+=item *
+scan parameters
+
+=item *
+read parameters
+
+=item *
+expression parameters
+
+=item *
+output parameters
+
+=item *
+operator display parameters
+
+=item *
+alarm parameters
+
+=item *
+monitor parameters
+
+=item *
+run-time parameters
+
+=back
+
+=recordtype calcout
+
+=cut
+
+menu(calcoutOOPT) {
+ choice(calcoutOOPT_Every_Time,"Every Time")
+ choice(calcoutOOPT_On_Change,"On Change")
+ choice(calcoutOOPT_When_Zero,"When Zero")
+ choice(calcoutOOPT_When_Non_zero,"When Non-zero")
+ choice(calcoutOOPT_Transition_To_Zero,"Transition To Zero")
+ choice(calcoutOOPT_Transition_To_Non_zero,"Transition To Non-zero")
+}
+menu(calcoutDOPT) {
+ choice(calcoutDOPT_Use_VAL,"Use CALC")
+ choice(calcoutDOPT_Use_OVAL,"Use OCAL")
+}
+menu(calcoutINAV) {
+ choice(calcoutINAV_EXT_NC,"Ext PV NC")
+ choice(calcoutINAV_EXT,"Ext PV OK")
+ choice(calcoutINAV_LOC,"Local PV")
+ choice(calcoutINAV_CON,"Constant")
+}
+
+recordtype(calcout) {
+
+=head3 Scan Parameters
+
+The Calcout record has the standard fields for specifying under what
+circumstances the record will be processed. The fields are listed in
+L. In addition, L explains how these
+fields are used. Since the Calcout record supports no direct interfaces to
+hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot
+be C.
+
+=head3 Read Parameters
+
+The read parameters for the Calcout record consists of 12 input links INPA,
+INPB, ... INPL. The fields can be database links, channel access links, or
+constants. If they are links, they must specify another record's field. If
+they are constants, they will be initialized with the value they are
+configured with and can be changed via C. These fields cannot be
+hardware addresses. In addition, the Calcout record contains the INAV,
+INBV, ... INLV fields which indicate the status of the link fields, for
+example, whether or not the specified PV was found and a link to it
+established. See L for an explanation of these
+fields.
+
+See L for information on how to specify database
+links.
+
+=fields INPA, INPB, INPC, INPD, INPE, INPF, INPG, INPH, INPI, INPJ, INPK, INPL
+
+=head3 Expression
+
+Like the Calc record, the Calcout record has a CALC field in which the
+developer can enter an infix expression which the record routine will
+evaluate when it processes the record. The resulting value is placed in the
+VAL field. This value can then be used by the OOPT field (see
+L) to determine whether or not to write to the output
+link or post an output event. It can also be the value that is written to
+the output link. The CALC expression is actually converted to opcode and
+stored in Reverse Polish Notation in the RPCL field. It is this expression
+which is actually used to calculate VAL. The Reverse Polish expression is
+evaluated more efficiently during run-time than an infix expression. CALC
+can be changes at run-time, and a special record routine will call a
+function to convert it to Reverse Polish Notation.
+
+The infix expressions that can be used are very similar to the C expression
+syntax, but with some additions and subtle differences in operator meaning
+and precedence. The string may contain a series of expressions separated by
+a semi-colon character ';' any one of which may actually provide the
+calculation result; however all of the other expressions included must
+assign their result to a variable. All alphabetic elements described below
+are case independent, so upper and lower case letters may be used and mixed
+in the variable and function names as desired. Spaces may be used anywhere
+within an expression except between the characters that make up a single
+expression element.
+
+The range of expressions supported by the calculation record are separated into
+literals, constants, operands, algebraic operators, trigonometric operators,
+relational operators, logical operator, the assignment operator,
+parentheses and commas, and the question mark or '?:' operator.
+
+=fields CALC, VAL, RPCL
+
+=head3 Literals
+
+=over 1
+
+=item *
+Standard double precision floating point numbers
+
+=item *
+Inf: Infinity
+
+=item *
+Nan: Not a Number
+
+=back
+
+=head3 Constants
+
+=over
+
+=item *
+PI: returns the mathematical constant E
+
+=item *
+D2R: evaluates to E/180 which, when used as a multiplier, converts an
+angle from degrees to radians
+
+=item *
+R2D: evaluates to 180/E which, when used as a multiplier, converts an
+angle from radians to degrees
+
+=back
+
+=head3 Operands
+
+The expression can use the values retrieved from the INPx links as
+operands, though constants can be used as operands too. These values
+retrieved from the input links are stored in the A-L fields. The values to
+be used in the expression are simple references by the field letter. For
+instance, the value obtained from the INPA link is stored in field A, and
+the values obtained from the INPB link is stored in the field B. The names
+can be included in the expression will operate on their respective values,
+as in A+B.
+
+=fields A, B, C, D, E, F, G, H, I, J, K, L
+
+The keyword VAL returns the current contents of the expression's result
+field, i.e. the VAL field for the CALC expression and the OVAL field for
+the OCAL expression. (These fields can be written to by CA put, so it might
+I be the result from the last time the expression was evaluated).
+
+=head3 Algebraic Operations
+
+=over 1
+
+=item *
+ABS: Absolute value (unary)
+
+=item *
+SQR: Square root (unary)
+
+=item *
+MIN: Minimum (any number of args)
+
+=item *
+MAX: Maximum (any number of args)
+
+=item *
+FINITE: returns non-zero if none of the arguments are NaN or Inf (any
+number of args)
+
+=item *
+ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number
+of args)
+
+=item *
+CEIL: Ceiling (unary)
+
+=item *
+FLOOR: Floor (unary)
+
+=item *
+LOG: Log base 10 (unary)
+
+=item *
+LOGE: Natural log (unary)
+
+=item *
+LN: Natural log (unary)
+
+=item *
+EXP: Exponential function (unary)
+
+=item *
+^ : Exponential (binary)
+
+=item *
+** : Exponential (binary)
+
+=item *
++ : Addition (binary)
+
+=item *
+- : Subtraction (binary)
+
+=item *
+* : Multiplication (binary)
+
+=item *
+/ : Division (binary)
+
+=item *
+% : Modulo (binary)
+
+=item *
+NOT: Negate (unary)
+
+=back
+
+=head3 Trigonometric Operators
+
+=over 1
+
+=item *
+SIN: Sine
+
+=item *
+SINH: Hyperbolic sine
+
+=item *
+ASIN: Arc sine
+
+=item *
+COS: Cosine
+
+=item *
+COSH: Hyperbolic cosine
+
+=item *
+ACOS: Arc cosine
+
+=item *
+TAN: Tangent
+
+=item *
+TANH: Hyperbolic tangent
+
+=item *
+ATAN: Arc tangent
+
+=back
+
+=head3 Relational Operators
+
+=over 1
+
+=item *
+>= : Greater than or equal to
+
+=item *
+> : Greater than
+
+=item *
+<= : Less than or equal to
+
+=item *
+< : Less than
+
+=item *
+# : Not equal to
+
+=item *
+= : Equal to
+
+=back
+
+=head3 Logical Operators
+
+=over 1
+
+=item *
+&& : And
+
+=item *
+|| : Or
+
+=item *
+! : Not
+
+=back
+
+=head3 Bitwise Operators
+
+=over 1
+
+=item *
+| : Bitwise Or
+
+=item *
+& : Bitwise And
+
+=item *
+OR : Bitwise Or
+
+=item *
+AND : Bitwise And
+
+=item *
+XOR : Bitwise Exclusive Or
+
+=item *
+~ : One's Complement
+
+=item *
+<< : Left shift
+
+=item *
+>> : Right shift
+
+=back
+
+=head3 Assignment Operator
+
+=over 1
+
+=item *
+:= : assigns a value (right hand side) to a variable (i.e. field)
+
+=back
+
+=head3 Parentheses and Comma
+
+The open and close parentheses are supported. Nested parentheses are
+supported.
+
+The comma is supported when used to separate the arguments of a binary
+function.
+
+=head3 Conditional Expression
+
+The C language's question mark operator is supported. The format is:
+C
+
+=head3 Expression Examples
+
+=head3 Algebraic
+
+C
+
+=over 1
+
+=item *
+Result is A + B + 10
+
+=back
+
+=head3 Relational
+
+C<(A + B) < (C + D)>
+
+=over 1
+
+=item *
+Result is 1 if (A + B) < (C + D)
+
+=item *
+Result is 0 if (A + B) >= (C + D)
+
+=back
+
+=head3 Question Mark
+
+C<(A + B) < (C + D) ? E : F + L + 10>
+
+=over 1
+
+=item *
+Result is E if (A + B) < (C + D)
+
+=item *
+Result is F + L + 10 if (A + B) >= (C + D)
+
+=back
+
+=head3 Logical
+
+C
+
+=over 1
+
+=item *
+Causes the following to occur:
+
+=over 1
+
+=item *
+Convert A to integer
+
+=item *
+Convert B to integer
+
+=item *
+Bitwise And A and B
+
+=item *
+Convert result to floating point
+
+=back
+
+=back
+
+=head3 Output Parameters
+
+These parameters specify and control the output capabilities of the Calcout
+record. They determine when to write the output, where to write it, and what
+the output will be. The OUT link specifies the Process Variable to which
+the result will be written.
+
+=head4 Menu calcoutOOPT
+
+The OOPT field determines the condition that causes the output link to be
+written to. It's a menu field that has six choices:
+
+=menu calcoutOOPT
+
+=over
+
+=item *
+C -- write output every time record is processed.
+
+=item *
+C -- write output every time VAL changes, i.e., every time the
+result of the expression changes.
+
+=item *
+C -- when record is preocessed, write output if VAL is zero.
+
+=item *
+C -- when record is processed, write output if VAL is
+non-zero.
+
+=item *
+C -- when record is processed, write output only if VAL
+is zero and the last value was non-zero.
+
+=item *
+C -- when record is processed, write output only if
+VAL is non-zero and last value was zero.
+
+=back
+
+=head4 Menu calcoutDOPT
+
+The DOPT field determines what data is written to the output link when the
+output is executed. The field is a menu field with two options:
+
+=menu calcoutDOPT
+
+If C is specified, when the record writes its
+output it will write the result of the expression in the CALC field, that
+is, it will write the value of the VAL field. If C is specified,
+the record will instead write the result of the expresion in the OCAL
+field, which is contained in the OVAL field. The OCAL field is exactly like
+the CALC field and has the same fuctionality it can contain the string
+representation of an expression which is evaluated at run-time. Thus, if
+necessary, the record can use the result of the CALC expression to
+determine if data should be written and can use the result of the OCAL
+expression as the data to write.
+
+If the OEVT field specifies a non-zero integer and the condition in the
+OOPT field is met, the record will post a corresponding event. If the ODLY
+field is non-zero, the record pauses for the specified number of seconds
+before executing the OUT link or posting the output event. During this
+waiting period the record is "active" and will not be processed again until
+the wait is over. The field DLYA is equal to 1 during the delay period. The
+resolution of the delay entry system dependent.
+
+The IVOA field specifies what action to take with the OUT link if the
+Calcout record eneters an INVALID alarm status. The options are
+C, C, and C.
+If the IVOA field is C, the data entered into the
+IVOV field is written to the OUT link if the record alarm severity is
+INVALID.
+
+=fields OUT, OOPT, DOPT, OCAL, OVAL, OEVT, ODLY, IVOA, IVOV
+
+=head3 Operator Display Parameter
+
+These parameters are used to present meaningful data to the operator. Some
+are also meant to represent the status of the record at run-time.
+
+The EGU field contains a string of up to 16 characters which is supplied by
+the user and which describes the values being operated upon. The string is
+retrieved whenever the routine C is called. The EGU string is
+solely for an operator's sake and does not have to be used.
+
+The HOPR and LOPR fields on;y refer to the limits if the VAL, HIHI, HIGH,
+LOW, and LOLO fields. PREC controls the precision of the VAL field.
+
+=head4 Menu calcoutINAV
+
+The INAV-INLV fields indicate the status of the link to the PVs specified
+in the INPA-INPL fields, respectfully. These field can have four possible
+values:
+
+=menu calcoutINAV
+
+=over 1
+
+=item *
+C -- the PV wasn't found on this IOC and a Channel Access link
+hasn't been established.
+
+=item *
+C -- the PV wasn't found on this IOC and a Channel Access link
+has been established.
+
+=item *
+C -- the PV was found on this IOC.
+
+=item *
+C -- the corresponding link field is a constant.
+
+=back
+
+The OUTV field indicates the status of the OUT link. If has the same
+possible values as the INAV-INLV fields.
+
+The CLCV and OLCV fields indicate the validity of the expression in the
+CALC and OCAL fields respectfully. If the expression in invalid, the field
+is set to one.
+
+The DYLA field is set to one during the delay specified in ODLY.
+
+See L for more information on the record
+name (NAME) and description (DESC) fields.
+
+=fields EGU, PREC, HOPR, LOPR, INAV, INBV, INCV, INDV, INEV, INFV, INGV, INHV, INIV, INJV, INKV, INLV, OUTV, CLCV, OCLV, DLYA, NAME, DESC
+
+=head3 Alarm Parameters
+
+The possible alarm conditions for the Calcout record are the SCAN, READ,
+Calculation, and limit alarms. The SCAN and READ alarms are called by the
+record support routines. The Calculation alarm is called by the record
+processing routine when the CALC expression is an invalid one, upon which
+an error message is generated.
+
+The following alarm parametersi, which are configured by the user, define the
+limit alarms for the VAL field and the severity corresponding to those
+conditions.
+
+The HYST field defines an alarm deadband for each limit. See
+L for a complete explanation of alarms and these
+fields. C lists other fields related to alarms that are
+common to all record types.
+
+=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
+
+=head3 Monitor Parameters
+
+These parameters are used to determine when to send monitors for the value
+fields. These monitors are sent when the value field exceeds the last
+monitored field by the appropriate deadband, the ADEL for archiver monitors
+and the MDEL field for all aother types of monitors. If these fields have a
+value of zero, every time the value changes, monitors are triggered; if
+they have a value of -1, every time the record is scanned, monitors are
+triggered. See L for a complete explanation of
+monitors.
+
+=fields ADEL, MDEL
+
+=head3 Run-time Parameters
+
+These fields are not configurable using a configuration tool and none are
+modifiable at run-time. They are used to process the record.
+
+The LALM field is used to implement the hysteresis factor for the alarm
+limits.
+
+The LA-LL fields are used to decide when to trigger monitors for the
+corresponding fields. For instance, if LA does not equal the value for A,
+monitors for A are triggered. The MLST and ALST fields are used in the same
+manner for the VAL field.
+
+=fields LALM, ALST, MLST, LA, LB, LC, LD, LE, LF, LG, LH, LI, LJ, LK, LL
+
+=cut
+
+ include "dbCommon.dbd"
+ field(RPVT,DBF_NOACCESS) {
+ prompt("Record Private")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("struct rpvtStruct *rpvt")
+ }
+ field(VAL,DBF_DOUBLE) {
+ prompt("Result")
+ promptgroup("50 - Output")
+ asl(ASL0)
+ }
+ field(PVAL,DBF_DOUBLE) {
+ prompt("Previous Value")
+ }
+ field(CALC,DBF_STRING) {
+ prompt("Calculation")
+ promptgroup("30 - Action")
+ special(SPC_CALC)
+ pp(TRUE)
+ size(80)
+ initial("0")
+ }
+ field(CLCV,DBF_LONG) {
+ prompt("CALC Valid")
+ interest(1)
+ }
+ field(INPA,DBF_INLINK) {
+ prompt("Input A")
+ special(SPC_MOD)
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPB,DBF_INLINK) {
+ prompt("Input B")
+ special(SPC_MOD)
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPC,DBF_INLINK) {
+ prompt("Input C")
+ special(SPC_MOD)
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPD,DBF_INLINK) {
+ prompt("Input D")
+ special(SPC_MOD)
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPE,DBF_INLINK) {
+ prompt("Input E")
+ special(SPC_MOD)
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPF,DBF_INLINK) {
+ prompt("Input F")
+ special(SPC_MOD)
+ promptgroup("41 - Input A-F")
+ interest(1)
+ }
+ field(INPG,DBF_INLINK) {
+ prompt("Input G")
+ special(SPC_MOD)
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPH,DBF_INLINK) {
+ prompt("Input H")
+ special(SPC_MOD)
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPI,DBF_INLINK) {
+ prompt("Input I")
+ special(SPC_MOD)
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPJ,DBF_INLINK) {
+ prompt("Input J")
+ special(SPC_MOD)
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPK,DBF_INLINK) {
+ prompt("Input K")
+ special(SPC_MOD)
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(INPL,DBF_INLINK) {
+ prompt("Input L")
+ special(SPC_MOD)
+ promptgroup("42 - Input G-L")
+ interest(1)
+ }
+ field(OUT,DBF_OUTLINK) {
+ prompt("Output Specification")
+ special(SPC_MOD)
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(INAV,DBF_MENU) {
+ prompt("INPA PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INBV,DBF_MENU) {
+ prompt("INPB PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INCV,DBF_MENU) {
+ prompt("INPC PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INDV,DBF_MENU) {
+ prompt("INPD PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INEV,DBF_MENU) {
+ prompt("INPE PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INFV,DBF_MENU) {
+ prompt("INPF PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INGV,DBF_MENU) {
+ prompt("INPG PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INHV,DBF_MENU) {
+ prompt("INPH PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INIV,DBF_MENU) {
+ prompt("INPI PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INJV,DBF_MENU) {
+ prompt("INPJ PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INKV,DBF_MENU) {
+ prompt("INPK PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(INLV,DBF_MENU) {
+ prompt("INPL PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ initial("1")
+ }
+ field(OUTV,DBF_MENU) {
+ prompt("OUT PV Status")
+ special(SPC_NOMOD)
+ interest(1)
+ menu(calcoutINAV)
+ }
+ field(OOPT,DBF_MENU) {
+ prompt("Output Execute Opt")
+ promptgroup("50 - Output")
+ interest(1)
+ menu(calcoutOOPT)
+ }
+ field(ODLY,DBF_DOUBLE) {
+ prompt("Output Execute Delay")
+ promptgroup("50 - Output")
+ asl(ASL0)
+ interest(1)
+ }
+ field(DLYA,DBF_USHORT) {
+ prompt("Output Delay Active")
+ special(SPC_NOMOD)
+ asl(ASL0)
+ }
+ field(DOPT,DBF_MENU) {
+ prompt("Output Data Opt")
+ promptgroup("30 - Action")
+ interest(1)
+ menu(calcoutDOPT)
+ }
+ field(OCAL,DBF_STRING) {
+ prompt("Output Calculation")
+ promptgroup("30 - Action")
+ special(SPC_CALC)
+ pp(TRUE)
+ size(80)
+ initial("0")
+ }
+ field(OCLV,DBF_LONG) {
+ prompt("OCAL Valid")
+ interest(1)
+ }
+ field(OEVT,DBF_STRING) {
+ prompt("Event To Issue")
+ promptgroup("30 - Action")
+ special(SPC_MOD)
+ asl(ASL0)
+ size(40)
+ }
+ %#include "dbScan.h"
+ field(EPVT, DBF_NOACCESS) {
+ prompt("Event private")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("EVENTPVT epvt")
+ }
+ field(IVOA,DBF_MENU) {
+ prompt("INVALID output action")
+ promptgroup("50 - Output")
+ interest(2)
+ menu(menuIvoa)
+ }
+ field(IVOV,DBF_DOUBLE) {
+ prompt("INVALID output value")
+ promptgroup("50 - Output")
+ interest(2)
+ }
+ field(EGU,DBF_STRING) {
+ prompt("Engineering Units")
+ promptgroup("80 - Display")
+ interest(1)
+ size(16)
+ prop(YES)
+ }
+ field(PREC,DBF_SHORT) {
+ prompt("Display Precision")
+ promptgroup("80 - Display")
+ interest(1)
+ prop(YES)
+ }
+ field(HOPR,DBF_DOUBLE) {
+ prompt("High Operating Rng")
+ promptgroup("80 - Display")
+ interest(1)
+ prop(YES)
+ }
+ field(LOPR,DBF_DOUBLE) {
+ prompt("Low Operating Range")
+ promptgroup("80 - Display")
+ interest(1)
+ prop(YES)
+ }
+ field(HIHI,DBF_DOUBLE) {
+ prompt("Hihi Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(LOLO,DBF_DOUBLE) {
+ prompt("Lolo Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(HIGH,DBF_DOUBLE) {
+ prompt("High Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(LOW,DBF_DOUBLE) {
+ prompt("Low Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(HHSV,DBF_MENU) {
+ prompt("Hihi Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(LLSV,DBF_MENU) {
+ prompt("Lolo Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(HSV,DBF_MENU) {
+ prompt("High Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(LSV,DBF_MENU) {
+ prompt("Low Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(HYST,DBF_DOUBLE) {
+ prompt("Alarm Deadband")
+ promptgroup("70 - Alarm")
+ interest(1)
+ }
+ field(ADEL,DBF_DOUBLE) {
+ prompt("Archive Deadband")
+ promptgroup("80 - Display")
+ interest(1)
+ }
+ field(MDEL,DBF_DOUBLE) {
+ prompt("Monitor Deadband")
+ promptgroup("80 - Display")
+ interest(1)
+ }
+ field(A,DBF_DOUBLE) {
+ prompt("Value of Input A")
+ pp(TRUE)
+ }
+ field(B,DBF_DOUBLE) {
+ prompt("Value of Input B")
+ pp(TRUE)
+ }
+ field(C,DBF_DOUBLE) {
+ prompt("Value of Input C")
+ pp(TRUE)
+ }
+ field(D,DBF_DOUBLE) {
+ prompt("Value of Input D")
+ pp(TRUE)
+ }
+ field(E,DBF_DOUBLE) {
+ prompt("Value of Input E")
+ pp(TRUE)
+ }
+ field(F,DBF_DOUBLE) {
+ prompt("Value of Input F")
+ pp(TRUE)
+ }
+ field(G,DBF_DOUBLE) {
+ prompt("Value of Input G")
+ pp(TRUE)
+ }
+ field(H,DBF_DOUBLE) {
+ prompt("Value of Input H")
+ pp(TRUE)
+ }
+ field(I,DBF_DOUBLE) {
+ prompt("Value of Input I")
+ pp(TRUE)
+ }
+ field(J,DBF_DOUBLE) {
+ prompt("Value of Input J")
+ pp(TRUE)
+ }
+ field(K,DBF_DOUBLE) {
+ prompt("Value of Input K")
+ pp(TRUE)
+ }
+ field(L,DBF_DOUBLE) {
+ prompt("Value of Input L")
+ pp(TRUE)
+ }
+ field(OVAL,DBF_DOUBLE) {
+ prompt("Output Value")
+ asl(ASL0)
+ }
+ field(LA,DBF_DOUBLE) {
+ prompt("Prev Value of A")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LB,DBF_DOUBLE) {
+ prompt("Prev Value of B")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LC,DBF_DOUBLE) {
+ prompt("Prev Value of C")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LD,DBF_DOUBLE) {
+ prompt("Prev Value of D")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LE,DBF_DOUBLE) {
+ prompt("Prev Value of E")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LF,DBF_DOUBLE) {
+ prompt("Prev Value of F")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LG,DBF_DOUBLE) {
+ prompt("Prev Value of G")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LH,DBF_DOUBLE) {
+ prompt("Prev Value of H")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LI,DBF_DOUBLE) {
+ prompt("Prev Value of I")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LJ,DBF_DOUBLE) {
+ prompt("Prev Value of J")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LK,DBF_DOUBLE) {
+ prompt("Prev Value of K")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(LL,DBF_DOUBLE) {
+ prompt("Prev Value of L")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(POVL,DBF_DOUBLE) {
+ prompt("Prev Value of OVAL")
+ asl(ASL0)
+ }
+ field(LALM,DBF_DOUBLE) {
+ prompt("Last Value Alarmed")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(ALST,DBF_DOUBLE) {
+ prompt("Last Value Archived")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(MLST,DBF_DOUBLE) {
+ prompt("Last Val Monitored")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ %#include "postfix.h"
+ field(RPCL,DBF_NOACCESS) {
+ prompt("Reverse Polish Calc")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
+ }
+ field(ORPC,DBF_NOACCESS) {
+ prompt("Reverse Polish OCalc")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("char orpc[INFIX_TO_POSTFIX_SIZE(80)]")
+ }
+
+=head2 Record Support
+
+=head3 Record Support Routines
+
+=head2 C
+
+For each constant input link, the corresponding value field is initialized
+with the constant value if the input link is CONSTANT or a channel access
+link is created if the input link is PV_LINK.
+
+A routine postfix is called to convert the infix expression in CALC and
+OCAL to Reverse Polish Notation. The result is stored in RPCL and ORPC,
+respectively.
+
+=head2 C
+
+See next section.
+
+=head2 C
+
+This is called id CALC or OCAL is changed. C calls postfix.
+
+=head2 C
+
+Fills in the values of struct valueDes so that they refer to VAL.
+
+=head2 C
+
+Retrieves EGU.
+
+=head2 C
+
+Retrieves PREC.
+
+=head2 C
+
+Sets the upper display and lower display limits for a field. If the field
+is VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else
+if the field has upper and lower limits defined they will be used, else the
+upper and lower macimum values for the field type will be used.
+
+=head2 C
+
+Sets the upper control and lower control limits for a field. If the VAL,
+HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else if the
+field has upper and lower limits defimed they will be used, else the upper
+and lower maximum values for the field will be used.
+
+=head2 C
+
+Sets the following values:
+
+=over
+
+upper_alarm_limit = HIHI
+
+upper_warning_limit = HIGH
+
+lower warning_limit = LOW
+
+lower_alarm_limit = LOLO
+
+=back
+
+=head3 Record Processing
+
+=head2 C
+
+The C routine implements the following algorithm:
+
+=over
+
+=item 1.
+Fetch all arguments.
+
+=item 2.
+Call routine C, which calculates VAL from the prefix version
+of the expression given in CALC. If C returns success, UDF
+is set to FALSE.
+
+=item 3.
+Check alarms. This routine checks to see if the new VAL causes the alarm
+status and severity to change. If so, NSEV, NSTA and LALM are set. If also
+honors the alarm hysteresis factor (HYST). Thus the value must change by at
+least HYST before the alarm status and severity changes.
+
+=item 4.
+Determin if the Output Execution Option (OOPT) is met. If it met, either
+execute the output link (and output event) immediately (if ODLY = 0), or
+schedule a callback after the specified interval. See the explanation for
+the C routine below.
+
+=item 5.
+Check to see if monitors should be invoked.
+
+=over
+
+=item *
+Alarm monitors are invoked if the alarm status or severity has changed.
+
+=item *
+Archive and value change monitors are invoked if ADEL and MDEL conditions
+are met.
+
+=item *
+Monitors for A-L are checked whenever other monitors are invoked.
+
+=item *
+NSEV and NSTA are reset to 0
+
+=back
+
+=item 6.
+If no output delay was specified, scan forwark link if necessaru, set PACT
+FALSE, and return.
+
+=back
+
+=head2 C
+
+=over
+
+=item 1.
+If DOPT field specifies the use of OCAL, call the routine C
+for the postfix version of the expression in OCAL. Otherwise, use VAL.
+
+=item 2.
+If the Alarm Severity is INVALID, follow the option as designated by the
+field IVOA.
+
+=item 3.
+The Alarm Severity is not INVALID or IVOA specifies "Continue Normally",
+put the value of OVAL to the OUT link and post the event in OEVT (if
+non-zero).
+
+=item 4.
+If an output delay was implemented, process the forwark link.
+
+=back
+
+=cut
+}
+
+variable(calcoutODLYprecision, int)
+variable(calcoutODLYlimit, double)
diff --git a/modules/database/src/std/rec/dfanoutRecord.dbd b/modules/database/src/std/rec/dfanoutRecord.dbd
deleted file mode 100644
index c2eb42a75..000000000
--- a/modules/database/src/std/rec/dfanoutRecord.dbd
+++ /dev/null
@@ -1,204 +0,0 @@
-#*************************************************************************
-# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-# National Laboratory.
-# Copyright (c) 2002 The Regents of the University of California, as
-# Operator of Los Alamos National Laboratory.
-# EPICS BASE is distributed subject to a Software License Agreement found
-# in file LICENSE that is included with this distribution.
-#*************************************************************************
-menu(dfanoutSELM) {
- choice(dfanoutSELM_All,"All")
- choice(dfanoutSELM_Specified,"Specified")
- choice(dfanoutSELM_Mask,"Mask")
-}
-recordtype(dfanout) {
- include "dbCommon.dbd"
- field(VAL,DBF_DOUBLE) {
- prompt("Desired Output")
- promptgroup("40 - Input")
- asl(ASL0)
- pp(TRUE)
- }
- field(SELM,DBF_MENU) {
- prompt("Select Mechanism")
- promptgroup("30 - Action")
- interest(1)
- menu(dfanoutSELM)
- }
- field(SELN,DBF_USHORT) {
- prompt("Link Selection")
- interest(1)
- initial("1")
- }
- field(SELL,DBF_INLINK) {
- prompt("Link Selection Loc")
- promptgroup("30 - Action")
- interest(1)
- }
- field(OUTA,DBF_OUTLINK) {
- prompt("Output Spec A")
- promptgroup("50 - Output")
- interest(1)
- }
- field(OUTB,DBF_OUTLINK) {
- prompt("Output Spec B")
- promptgroup("50 - Output")
- interest(1)
- }
- field(OUTC,DBF_OUTLINK) {
- prompt("Output Spec C")
- promptgroup("50 - Output")
- interest(1)
- }
- field(OUTD,DBF_OUTLINK) {
- prompt("Output Spec D")
- promptgroup("50 - Output")
- interest(1)
- }
- field(OUTE,DBF_OUTLINK) {
- prompt("Output Spec E")
- promptgroup("50 - Output")
- interest(1)
- }
- field(OUTF,DBF_OUTLINK) {
- prompt("Output Spec F")
- promptgroup("50 - Output")
- interest(1)
- }
- field(OUTG,DBF_OUTLINK) {
- prompt("Output Spec G")
- promptgroup("50 - Output")
- interest(1)
- }
- field(OUTH,DBF_OUTLINK) {
- prompt("Output Spec H")
- promptgroup("50 - Output")
- interest(1)
- }
- field(DOL,DBF_INLINK) {
- prompt("Desired Output Loc")
- promptgroup("40 - Input")
- interest(1)
- }
- field(OMSL,DBF_MENU) {
- prompt("Output Mode Select")
- promptgroup("50 - Output")
- interest(1)
- menu(menuOmsl)
- }
- field(EGU,DBF_STRING) {
- prompt("Engineering Units")
- promptgroup("80 - Display")
- interest(1)
- size(16)
- prop(YES)
- }
- field(PREC,DBF_SHORT) {
- prompt("Display Precision")
- promptgroup("80 - Display")
- interest(1)
- prop(YES)
- }
- field(HOPR,DBF_DOUBLE) {
- prompt("High Operating Range")
- promptgroup("80 - Display")
- interest(1)
- prop(YES)
- }
- field(LOPR,DBF_DOUBLE) {
- prompt("Low Operating Range")
- promptgroup("80 - Display")
- interest(1)
- prop(YES)
- }
- field(HIHI,DBF_DOUBLE) {
- prompt("Hihi Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(LOLO,DBF_DOUBLE) {
- prompt("Lolo Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(HIGH,DBF_DOUBLE) {
- prompt("High Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(LOW,DBF_DOUBLE) {
- prompt("Low Alarm Limit")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- }
- field(HHSV,DBF_MENU) {
- prompt("Hihi Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(LLSV,DBF_MENU) {
- prompt("Lolo Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(HSV,DBF_MENU) {
- prompt("High Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(LSV,DBF_MENU) {
- prompt("Low Severity")
- promptgroup("70 - Alarm")
- pp(TRUE)
- interest(1)
- prop(YES)
- menu(menuAlarmSevr)
- }
- field(HYST,DBF_DOUBLE) {
- prompt("Alarm Deadband")
- promptgroup("70 - Alarm")
- interest(1)
- }
- field(ADEL,DBF_DOUBLE) {
- prompt("Archive Deadband")
- promptgroup("80 - Display")
- interest(1)
- }
- field(MDEL,DBF_DOUBLE) {
- prompt("Monitor Deadband")
- promptgroup("80 - Display")
- interest(1)
- }
- field(LALM,DBF_DOUBLE) {
- prompt("Last Value Alarmed")
- special(SPC_NOMOD)
- interest(3)
- }
- field(ALST,DBF_DOUBLE) {
- prompt("Last Value Archived")
- special(SPC_NOMOD)
- interest(3)
- }
- field(MLST,DBF_DOUBLE) {
- prompt("Last Val Monitored")
- special(SPC_NOMOD)
- interest(3)
- }
-}
diff --git a/modules/database/src/std/rec/dfanoutRecord.dbd.pod b/modules/database/src/std/rec/dfanoutRecord.dbd.pod
new file mode 100644
index 000000000..0d0487666
--- /dev/null
+++ b/modules/database/src/std/rec/dfanoutRecord.dbd.pod
@@ -0,0 +1,454 @@
+#*************************************************************************
+# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+# National Laboratory.
+# Copyright (c) 2002 The Regents of the University of California, as
+# Operator of Los Alamos National Laboratory.
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
+
+=title Data Fanout Record (dfanout)
+
+The Data Fanout or "dfanout" record is used to forward data to up to
+eight other records. It's similar to the fanout record except that the
+capability to forward data has been added to it. If has no associated
+device support.
+
+=head2 Parameter Fields
+
+The fields in this record can be classified into the following categories:
+
+=over
+
+=item *
+scan parameters
+
+=item *
+desired output parameters
+
+=item *
+write parameters
+
+=item *
+operator display parameters
+
+=item *
+alarm parameters
+
+=item *
+monitor parameters
+
+=item *
+run-time and simulation mode parameters
+
+=back
+
+=recordtype dfanout
+
+=cut
+
+menu(dfanoutSELM) {
+ choice(dfanoutSELM_All,"All")
+ choice(dfanoutSELM_Specified,"Specified")
+ choice(dfanoutSELM_Mask,"Mask")
+}
+
+recordtype(dfanout) {
+
+=head3 Scan Parameters
+
+The data fanout record has the standard fields for specifying under what
+circumstances it will be processed. These fields are listed in
+L. In addition, L explains how these
+fields are used. Since the data fanout record supports no direct interfaces
+to hardware, it cannot be scanned on I/O interrupt, so its SCAN field
+cannot be C.
+
+=head3 Desired Output Parameters
+
+The data fanout record must specify where the desired output value
+originates, i.e., the data which is to be fowarded to the records in its
+output links. The output mode select (OMSL) field determines whether the
+output originates from another record or from run-time database access.
+When set to C, the desired output is retrieved from the link
+specified in the desired output (DOL) field, which can specify either a
+database or a channel access link, and placed into the VAL field. When set
+to C, the desired output can be written to the VAL field via
+dbPuts at run-time.
+
+The DOL field can also be a constant in which case the VAL field is
+initialized to the constant value.
+
+Note that there are no conversion parameters, so the desired output value
+undergoes no conversions before it is sent out to the output links.
+
+=fields DOL, OMSL, VAL
+
+=head3 Write Parameters
+
+The OUTA-OUTH fields specify where VAL is to be sent. Each field that is to
+forward data must specify an address to another record. See
+L for information on specifying links.
+
+The SELL, SELM, and SELN fields specify which output links are to be
+used.
+
+=head4 Menu dfanoutSELM
+
+SELM is a menu, with three choices:
+
+=menu dfanoutSELM
+
+If SELM=="All", then all output links are used, and the values of
+SELL and SELN are ignored.
+
+If SELM=="Specified", then the value of SELN is used to specify a single
+link which will be used. If SELN==0, then no link will be used; if SELN==1,
+then OUTA will be used, and so on.
+
+SELN can either have its value set directly, or have its values retrieved
+from another EPICS PV. If SELL is a valid PV link, then SELN will be set to
+the values of the linked PV.
+
+If SELM=="Mask", then SELN will be treated as a bit mask. If bit one of
+SELN is set, then OUTA will be used, if bit two is set, OUTB will be used.
+Thus if SELN==5, OUTC and OUTA will be used.
+
+=fields OUTA, OUTB, OUTC, OUTD, OUTE, OUTF, OUTG, OUTH
+
+=head3 Operator Display Parameters
+
+These parameters are used to present meaningful data to the operator. They
+display the value and other parameters of the data fanout record either
+textually or graphically.
+
+The EGU field can contain a string of up to 16 characters describing the
+value on the VAL field.
+
+The HOPR and LOPR fields determine the upper and lower display limits for
+graphic displays and the upper and lower control limits for control
+displays. They apply to the VAL, HIHI, HIGH, LOW, and LOLO fields. The
+record support routines C or C
+retrieve HOPR and LOPR.
+
+See L for more on the record name (NAME)
+and description (DESC) fields.
+
+=fields EGU, HOPR, LOPR, NAME, DESC
+
+=head3 Alarm Parameters
+
+The possible alarm conditions for data fanouts are the SCAN, READ, INVALID,
+and limit alarms. The SCAN and READ alarms are called by the record
+routines. The limit alarms are configured by the user in the HIHI, LOLO,
+HIGH, and LOW fields using floating point values. The limit alarms apply
+only to the VAL field. The severity for each of these limits is specified
+in the corresponding field (HHSV, LLSV, HSV, LSV) and can be either
+NO_ALARM, MINOR, or MAJOR. In the hysteresis field (HYST) can be entered a
+number which serves as the deadband on the limit alarms.
+
+See L for a complete explanation of alarms and these
+fields. L lists other fields related to alarms that are
+common to all record types.
+
+=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
+
+=head3 Monitor Parameters
+
+These parameters are used to determine when to send monitors placed on the
+VAL field. These monitors are sent when the value field exceeds the last
+monitored fields by the specified deadband, ADEL for archivers monitors and
+MDEL for all other types of monitors. If these fields have a value of zero,
+everytime the value changes, a monitor will be triggered; if they have a
+value of -1, everytime the record is scanned, monitors are triggered. See
+L for a complete explanation of monitors.
+
+=fields ADEL, MDEL
+
+=head3 Run-Time Parameters and Simulation Mode Parameters
+
+These parameters are used by the run-time code for processing the data
+fanout record. Ther are not configurable. They are used to implement the
+hysteresis factors for monitor callbacks.
+
+=fields LALM, ALST, MLST
+
+=cut
+
+ include "dbCommon.dbd"
+ field(VAL,DBF_DOUBLE) {
+ prompt("Desired Output")
+ promptgroup("40 - Input")
+ asl(ASL0)
+ pp(TRUE)
+ }
+ field(SELM,DBF_MENU) {
+ prompt("Select Mechanism")
+ promptgroup("30 - Action")
+ interest(1)
+ menu(dfanoutSELM)
+ }
+ field(SELN,DBF_USHORT) {
+ prompt("Link Selection")
+ interest(1)
+ initial("1")
+ }
+ field(SELL,DBF_INLINK) {
+ prompt("Link Selection Loc")
+ promptgroup("30 - Action")
+ interest(1)
+ }
+ field(OUTA,DBF_OUTLINK) {
+ prompt("Output Spec A")
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(OUTB,DBF_OUTLINK) {
+ prompt("Output Spec B")
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(OUTC,DBF_OUTLINK) {
+ prompt("Output Spec C")
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(OUTD,DBF_OUTLINK) {
+ prompt("Output Spec D")
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(OUTE,DBF_OUTLINK) {
+ prompt("Output Spec E")
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(OUTF,DBF_OUTLINK) {
+ prompt("Output Spec F")
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(OUTG,DBF_OUTLINK) {
+ prompt("Output Spec G")
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(OUTH,DBF_OUTLINK) {
+ prompt("Output Spec H")
+ promptgroup("50 - Output")
+ interest(1)
+ }
+ field(DOL,DBF_INLINK) {
+ prompt("Desired Output Loc")
+ promptgroup("40 - Input")
+ interest(1)
+ }
+ field(OMSL,DBF_MENU) {
+ prompt("Output Mode Select")
+ promptgroup("50 - Output")
+ interest(1)
+ menu(menuOmsl)
+ }
+ field(EGU,DBF_STRING) {
+ prompt("Engineering Units")
+ promptgroup("80 - Display")
+ interest(1)
+ size(16)
+ prop(YES)
+ }
+ field(PREC,DBF_SHORT) {
+ prompt("Display Precision")
+ promptgroup("80 - Display")
+ interest(1)
+ prop(YES)
+ }
+ field(HOPR,DBF_DOUBLE) {
+ prompt("High Operating Range")
+ promptgroup("80 - Display")
+ interest(1)
+ prop(YES)
+ }
+ field(LOPR,DBF_DOUBLE) {
+ prompt("Low Operating Range")
+ promptgroup("80 - Display")
+ interest(1)
+ prop(YES)
+ }
+ field(HIHI,DBF_DOUBLE) {
+ prompt("Hihi Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(LOLO,DBF_DOUBLE) {
+ prompt("Lolo Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(HIGH,DBF_DOUBLE) {
+ prompt("High Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(LOW,DBF_DOUBLE) {
+ prompt("Low Alarm Limit")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ }
+ field(HHSV,DBF_MENU) {
+ prompt("Hihi Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(LLSV,DBF_MENU) {
+ prompt("Lolo Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(HSV,DBF_MENU) {
+ prompt("High Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(LSV,DBF_MENU) {
+ prompt("Low Severity")
+ promptgroup("70 - Alarm")
+ pp(TRUE)
+ interest(1)
+ prop(YES)
+ menu(menuAlarmSevr)
+ }
+ field(HYST,DBF_DOUBLE) {
+ prompt("Alarm Deadband")
+ promptgroup("70 - Alarm")
+ interest(1)
+ }
+ field(ADEL,DBF_DOUBLE) {
+ prompt("Archive Deadband")
+ promptgroup("80 - Display")
+ interest(1)
+ }
+ field(MDEL,DBF_DOUBLE) {
+ prompt("Monitor Deadband")
+ promptgroup("80 - Display")
+ interest(1)
+ }
+ field(LALM,DBF_DOUBLE) {
+ prompt("Last Value Alarmed")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(ALST,DBF_DOUBLE) {
+ prompt("Last Value Archived")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+ field(MLST,DBF_DOUBLE) {
+ prompt("Last Val Monitored")
+ special(SPC_NOMOD)
+ interest(3)
+ }
+
+=head2 Record Support
+
+=head3 Record Support Routines
+
+=head2 C
+
+This routine initializes all output links that are defined. Then it initializes
+DOL if DOL is a constant or a PV_LINK. When initializing the output links
+and the DOL link, a non-zero value is returned if an error occurs.
+
+=head2 C
+
+See next section.
+
+=head2 C
+
+This routine fills in the members of C with the VAL fields
+value and characteristics.
+
+=head2 C
+
+The routine copies the string specified in the EGU field to the location
+specified by a pointer which is passed to the routine.
+
+=head2 C
+
+If the referenced field is VAL, HIHI, HIGH, LOW, or LOLO, this routine sets
+the C member of the C structure to the
+HOPR and the C member to the LOPR. If the referenced
+field is not one of the above fields, then C
+routine is called.
+
+=head2 C
+
+Same as the C routine except that it uses the
+C structure.
+
+=head2 C
+
+This sets the members of the C structure to the specified
+alarm limits if the referenced field is VAL:
+
+=over
+
+upper_alarm_limit = HIHI
+
+upper_warning_limit = HIGH
+
+lower_warning_limit = LOW
+
+lower_alarm_limit = LOLO
+
+=back
+
+If the referenced field is not VAL, the C routine
+is called.
+
+=head3 Record Processing
+
+=over
+
+=item 1.
+The C routine first retrieves a value for DOL and places it in
+VAL if OMSL is set to colsed loop mode. If an error occurs, then UDF is set
+to FALSE.
+
+=item 2.
+PACT is set TRUE
+
+=item 3.
+VAL is then sent to all the records specified in the OUTA-OUTH fields by
+calling C for each link.
+
+=item 4.
+Alarms are checked and monitors are called if conditions apply.
+
+=item 5.
+The data fanout's own forward link is then processed.
+
+=item 6.
+PACT is set FALSE, and the C routine returns. A -1 is returned
+if there was an error writing values to one of the output links.
+
+=back
+
+=cut
+}
diff --git a/modules/database/src/tools/DBD/Parser.pm b/modules/database/src/tools/DBD/Parser.pm
index 6065486c8..4b845b0d1 100644
--- a/modules/database/src/tools/DBD/Parser.pm
+++ b/modules/database/src/tools/DBD/Parser.pm
@@ -97,7 +97,7 @@ sub ParseDBD {
my $rtyp = $dbd->recordtype($record_type);
if (!defined $rtyp) {
$rtyp = DBD::Recordtype->new($record_type);
- warn "Device using undefined record type '$record_type', place-holder created\n";
+ warn "Device using unknown record type '$record_type', declaration created\n";
$dbd->add($rtyp);
}
$rtyp->add_device(DBD::Device->new($link_type, $dset, $choice));
@@ -218,7 +218,12 @@ sub parse_breaktable {
sub parse_recordtype {
my ($dbd, $record_type) = @_;
pushContext("recordtype($record_type)");
- my $rtyp = DBD::Recordtype->new($record_type);
+ # Re-use a matching declaration record type if one exists
+ my $rtyp = $dbd->recordtype($record_type);
+ if (!defined($rtyp) || $rtyp->fields) {
+ # Earlier record type is not a declaration, don't re-use it
+ $rtyp = DBD::Recordtype->new($record_type);
+ }
while(1) {
parseCommon($rtyp);
if (m/\G field \s* \( \s* $RXstr \s* , \s* $RXstr \s* \) \s* \{/xgc) {
diff --git a/modules/database/src/tools/DBD/Recfield.pm b/modules/database/src/tools/DBD/Recfield.pm
index f7bfbae46..3e109d2d1 100644
--- a/modules/database/src/tools/DBD/Recfield.pm
+++ b/modules/database/src/tools/DBD/Recfield.pm
@@ -130,7 +130,18 @@ sub attribute {
}
sub equals {
- dieContext("Record field objects are not comparable");
+ my ($l, $r) = @_;
+ return 1 if $l eq $r;
+ return 0 if
+ $l->{NAME} ne $r->{NAME} ||
+ $l->{DBF_TYPE} ne $r->{DBF_TYPE};
+ my ($la, $ra) = ($l->{ATTR_INDEX}, $r->{ATTR_INDEX});
+ my @keys = sort keys %$la;
+ return 0 if join(',', @keys) ne join(',', sort keys %$ra);
+ foreach my $k (@keys) {
+ return 0 if $la->{$k} ne $ra->{$k};
+ }
+ return 1;
}
sub check_valid {
diff --git a/modules/database/src/tools/DBD/Recordtype.pm b/modules/database/src/tools/DBD/Recordtype.pm
index e4b0d5481..649c6a21b 100644
--- a/modules/database/src/tools/DBD/Recordtype.pm
+++ b/modules/database/src/tools/DBD/Recordtype.pm
@@ -104,9 +104,19 @@ sub pod {
sub equals {
my ($new, $known) = @_;
- return 0 if ! $known->fields;
- return 1 if ! $new->fields;
- dieContext("Duplicate definition of record type '$known->{NAME}'");
+ return 1 if $new eq $known;
+ return 0 if $new->{NAME} ne $known->{NAME};
+ return 1 if ! $new->fields; # Later declarations always match
+ # NB: Definition after declaration is handled in parse_recordtype()
+ my @nf = @{$new->{FIELD_LIST}};
+ my @kf = @{$known->{FIELD_LIST}};
+ return 0 if scalar @nf != scalar @kf;
+ while (@nf) {
+ my $nf = shift @nf;
+ my $kf = shift @kf;
+ return 0 if ! $nf->equals($kf);
+ }
+ return 1;
}
sub toDeclaration {
diff --git a/modules/database/src/tools/dbdToHtml.pl b/modules/database/src/tools/dbdToHtml.pl
index c51c793b5..e9711f757 100644
--- a/modules/database/src/tools/dbdToHtml.pl
+++ b/modules/database/src/tools/dbdToHtml.pl
@@ -127,6 +127,33 @@ if ($opt_D) { # Output dependencies only
open my $out, '>', $opt_o or
die "Can't create $opt_o: $!\n";
+my $podHtml;
+my $idify;
+
+if ($::XHTML) {
+ $podHtml = Pod::Simple::XHTML->new();
+ $podHtml->html_doctype(<< '__END_DOCTYPE');
+
+
+__END_DOCTYPE
+ $podHtml->html_header_tags($podHtml->html_header_tags .
+ "\n ");
+
+ $idify = sub {
+ my $title = shift;
+ return $podHtml->idify($title, 1);
+ }
+} else { # Fall back to HTML
+ $podHtml = Pod::Simple::HTML->new();
+ $podHtml->html_css('style.css');
+
+ $idify = sub {
+ my $title = shift;
+ return Pod::Simple::HTML::esc($podHtml->section_escape($title));
+ }
+}
+
# Parse the Pod text from the root DBD object
my $pod = join "\n", '=for html ', '',
map {
@@ -156,22 +183,6 @@ my $pod = join "\n", '=for html
', '',
} $dbd->pod,
'=for html
', '';
-my $podHtml;
-
-if ($::XHTML) {
- $podHtml = Pod::Simple::XHTML->new();
- $podHtml->html_doctype(<< '__END_DOCTYPE');
-
-
-__END_DOCTYPE
- $podHtml->html_header_tags($podHtml->html_header_tags .
- "\n
");
-} else { # Fall back to HTML
- $podHtml = Pod::Simple::HTML->new();
- $podHtml->html_css('style.css');
-}
-
$podHtml->force_title(encode_entities($title));
$podHtml->perldoc_url_prefix('');
$podHtml->perldoc_url_postfix('.html');
@@ -249,7 +260,7 @@ sub fieldTableRow {
if ($type eq 'MENU') {
my $mn = $fld->attribute('menu');
my $menu = $dbd->menu($mn);
- my $url = $menu ? "#Menu_$mn" : "${mn}.html";
+ my $url = $menu ? '#' . &$idify("Menu $mn") : "${mn}.html";
$html .= " (
$mn )";
}
$html .= '
';
@@ -377,6 +388,8 @@ can be found in the aai and aSub record types.
If you look at the L file you'll see that the POD there starts
by documenting a record-specific menu definition. The "menu" keyword generates a
-table that lists all the choices found in the named menu.
+table that lists all the choices found in the named menu. Any MENU fields in the
+field tables that refer to a locally-defined menu will generate a link to a
+document section which must be titled "Menu [menuName]".
=cut
diff --git a/modules/database/test/std/rec/Makefile b/modules/database/test/std/rec/Makefile
index 6b468e106..185c2c0c1 100644
--- a/modules/database/test/std/rec/Makefile
+++ b/modules/database/test/std/rec/Makefile
@@ -114,6 +114,7 @@ TESTPROD_HOST += regressTest
regressTest_SRCS += regressTest.c
regressTest_SRCS += regressTest_registerRecordDeviceDriver.cpp
TESTFILES += $(COMMON_DIR)/regressTest.dbd ../regressArray1.db ../regressHex.db ../regressLinkMS.db
+TESTFILES += ../badCaLink.db
TESTS += regressTest
TARGETS += $(COMMON_DIR)/simmTest.dbd
diff --git a/modules/database/test/std/rec/badCaLink.db b/modules/database/test/std/rec/badCaLink.db
new file mode 100644
index 000000000..c71bc9d2f
--- /dev/null
+++ b/modules/database/test/std/rec/badCaLink.db
@@ -0,0 +1,4 @@
+record(ai, "ai:disconn") {
+ field(INP , "invalid CA")
+ field(UDF , "0")
+}
diff --git a/modules/database/test/std/rec/regressTest.c b/modules/database/test/std/rec/regressTest.c
index 15010cebf..661463984 100644
--- a/modules/database/test/std/rec/regressTest.c
+++ b/modules/database/test/std/rec/regressTest.c
@@ -8,6 +8,7 @@
#include