Merge 7.0.10 into PSI-7.0
This commit is contained in:
@@ -90,7 +90,7 @@ int asSetFilename(const char *acf)
|
||||
|
||||
int asSetSubstitutions(const char *substitutions)
|
||||
{
|
||||
if(psubstitutions) free ((void *)psubstitutions);
|
||||
if(psubstitutions) free (psubstitutions);
|
||||
if(substitutions) {
|
||||
psubstitutions = calloc(1,strlen(substitutions)+1);
|
||||
if(!psubstitutions) {
|
||||
@@ -123,7 +123,7 @@ static long asInitCommon(void)
|
||||
static epicsThreadOnceId asInitCommonOnceFlag = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
|
||||
epicsThreadOnce(&asInitCommonOnceFlag,asInitCommonOnce,(void *)&firstTime);
|
||||
epicsThreadOnce(&asInitCommonOnceFlag, asInitCommonOnce, &firstTime);
|
||||
if(wasFirstTime) {
|
||||
if(!pacf) return(0); /*access security will NEVER be turned on*/
|
||||
} else {
|
||||
@@ -174,7 +174,7 @@ static void asInitTask(ASDBCALLBACK *pcallback)
|
||||
{
|
||||
long status;
|
||||
|
||||
taskwdInsert(epicsThreadGetIdSelf(), wdCallback, (void *)pcallback);
|
||||
taskwdInsert(epicsThreadGetIdSelf(), wdCallback, pcallback);
|
||||
status = asInitCommon();
|
||||
taskwdRemove(epicsThreadGetIdSelf());
|
||||
asInitTheadId = 0;
|
||||
@@ -198,7 +198,7 @@ int asInitAsyn(ASDBCALLBACK *pcallback)
|
||||
asInitTheadId = epicsThreadCreate("asInitTask",
|
||||
(epicsThreadPriorityCAServerHigh + 1),
|
||||
epicsThreadGetStackSize(epicsThreadStackBig),
|
||||
(EPICSTHREADFUNC)asInitTask,(void *)pcallback);
|
||||
(EPICSTHREADFUNC)asInitTask, pcallback);
|
||||
if(asInitTheadId==0) {
|
||||
errMessage(0,"asInit: epicsThreadCreate Error");
|
||||
if(pcallback) {
|
||||
@@ -264,7 +264,7 @@ int astac(const char *pname,const char *user,const char *location)
|
||||
errMessage(status,"asAddClient error");
|
||||
return(1);
|
||||
} else {
|
||||
asPutClientPvt(*pasclientpvt,(void *)precord->name);
|
||||
asPutClientPvt(*pasclientpvt, precord->name);
|
||||
asRegisterClientCallback(*pasclientpvt,astacCallback);
|
||||
}
|
||||
return(0);
|
||||
|
||||
@@ -33,7 +33,7 @@ static const iocshArg asSetSubstitutionsArg0 = { "substitutions",iocshArgString}
|
||||
static const iocshArg * const asSetSubstitutionsArgs[] = {&asSetSubstitutionsArg0};
|
||||
static const iocshFuncDef asSetSubstitutionsFuncDef =
|
||||
{"asSetSubstitutions",1,asSetSubstitutionsArgs,
|
||||
"Set subtitutions used when reading ACF file.\n"
|
||||
"Set substitutions used when reading ACF file.\n"
|
||||
"No immediate effect. Run asInit to (re)load.\n"
|
||||
"Example: asSetSubstitutions var1=5,var2=hello\n"};
|
||||
static void asSetSubstitutionsCallFunc(const iocshArgBuf *args)
|
||||
|
||||
@@ -53,5 +53,6 @@ int main(int argc,char **argv)
|
||||
status = -1;
|
||||
}
|
||||
errlogFlush();
|
||||
asFreeAll((ASBASE*)pasbase);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ got_header:
|
||||
pdata[n] = pnext->value;
|
||||
pdataList = pnext;
|
||||
pnext = pnext->next;
|
||||
free((void *)pdataList);
|
||||
free(pdataList);
|
||||
}
|
||||
brkCreateInfo.pTable = pdata;
|
||||
if(create_break(&brkCreateInfo,&brkint[0],MAX_BREAKS,&nBreak))
|
||||
@@ -360,7 +360,7 @@ static int create_break( struct brkCreateInfo *pbci, brkInt *pabrkInt,
|
||||
if (inc < 1)
|
||||
inc = 1;
|
||||
valid = TRUE;
|
||||
/* keep trying intervals until cant do better */
|
||||
/* keep trying intervals until can't do better */
|
||||
expanding = TRUE; /* originally we are trying larger and larger
|
||||
* intervals */
|
||||
while (valid) {
|
||||
|
||||
@@ -100,6 +100,10 @@ static int priorityValue[NUM_CALLBACK_PRIORITIES] = {0, 1, 2};
|
||||
|
||||
int callbackSetQueueSize(int size)
|
||||
{
|
||||
if (size<=0) {
|
||||
fprintf(stderr, "Queue size must be positive\n");
|
||||
return -1;
|
||||
}
|
||||
if (epicsAtomicGetIntT(&cbState)!=cbInit) {
|
||||
fprintf(stderr, "Callback system already initialized\n");
|
||||
return -1;
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
#include "dbCoreAPI.h"
|
||||
|
||||
/** @file callback.h
|
||||
* @brief Process database deferred execution utility
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -38,53 +42,176 @@ extern "C" {
|
||||
#define priorityMedium 1
|
||||
#define priorityHigh 2
|
||||
|
||||
/** Handle for delayed work.
|
||||
*
|
||||
* @pre Must be zero initialized prior to first use.
|
||||
*
|
||||
* @since 3.15.6 epicsCallback typedef added. CALLBACK typedef deprecated.
|
||||
*/
|
||||
typedef struct callbackPvt {
|
||||
/** Callback function */
|
||||
void (*callback)(struct callbackPvt*);
|
||||
/** One of priorityLow, priorityMedium, or priorityHigh */
|
||||
int priority;
|
||||
void *user; /*for use by callback user*/
|
||||
void *timer; /*for use by callback itself*/
|
||||
/** for use by callback API user*/
|
||||
void *user;
|
||||
/** Must be zero initialized. Used by callback internals. */
|
||||
void *timer;
|
||||
}epicsCallback;
|
||||
|
||||
#if !defined(EPICS_NO_CALLBACK)
|
||||
/** Deprecated alias for epicsCallback
|
||||
*
|
||||
* Name conflicts with definition from windows.h.
|
||||
* Portable applications should prefer epicsCallback
|
||||
* and define the EPICS_NO_CALLBACK pre-processor macro to hide this typedef.
|
||||
*
|
||||
* @since 3.15.6 Deprecated in favor of epicsCallback typedef
|
||||
*/
|
||||
typedef epicsCallback CALLBACK;
|
||||
#endif
|
||||
|
||||
typedef void (*CALLBACKFUNC)(struct callbackPvt*);
|
||||
|
||||
/** See callbackQueueStatus() */
|
||||
typedef struct callbackQueueStats {
|
||||
/** Maxiumum depth of queues */
|
||||
int size;
|
||||
/** Current number of elements on each queue */
|
||||
int numUsed[NUM_CALLBACK_PRIORITIES];
|
||||
/** Maximum numUsed seen so far (from init or reset) */
|
||||
int maxUsed[NUM_CALLBACK_PRIORITIES];
|
||||
/** Number of overflow events */
|
||||
int numOverflow[NUM_CALLBACK_PRIORITIES];
|
||||
} callbackQueueStats;
|
||||
|
||||
/** Assigns callbackPvt::callback */
|
||||
#define callbackSetCallback(PFUN, PCALLBACK) \
|
||||
( (PCALLBACK)->callback = (PFUN) )
|
||||
/** Assigns callbackPvt::priority */
|
||||
#define callbackSetPriority(PRIORITY, PCALLBACK) \
|
||||
( (PCALLBACK)->priority = (PRIORITY) )
|
||||
/** Assigns callbackPvt::priority */
|
||||
#define callbackGetPriority(PRIORITY, PCALLBACK) \
|
||||
( (PRIORITY) = (PCALLBACK)->priority )
|
||||
/** Assigns callbackPvt::user */
|
||||
#define callbackSetUser(USER, PCALLBACK) \
|
||||
( (PCALLBACK)->user = (void *) (USER) )
|
||||
( (PCALLBACK)->user = (USER) )
|
||||
/** Read and return callbackPvt::user */
|
||||
#define callbackGetUser(USER, PCALLBACK) \
|
||||
( (USER) = (PCALLBACK)->user )
|
||||
|
||||
DBCORE_API void callbackInit(void);
|
||||
DBCORE_API void callbackStop(void);
|
||||
DBCORE_API void callbackCleanup(void);
|
||||
/** Queue immediate callback request.
|
||||
*
|
||||
* Each epicsCallback may be queued multiple times.
|
||||
* epicsCallback object must not be modified while queued,
|
||||
* and must remain valid while queued or executing.
|
||||
*
|
||||
* @param pCallback Caller expected to initialize or zero all members before first call.
|
||||
* @return Zero on success.
|
||||
* Errors if callback members not initialized correctly, or if queue is full.
|
||||
*/
|
||||
DBCORE_API int callbackRequest(epicsCallback *pCallback);
|
||||
/** Setup callback to process a record
|
||||
* @pre Callback must be zero initialized.
|
||||
*
|
||||
* @param pcallback Callback to initialize.
|
||||
* @param Priority priorityLow, priorityMedium, or priorityHigh
|
||||
* @param pRec A record pointer (dbCommon or specific recordType)
|
||||
*/
|
||||
DBCORE_API void callbackSetProcess(
|
||||
epicsCallback *pcallback, int Priority, void *pRec);
|
||||
/** (Re)Initialize callback object and queue
|
||||
*
|
||||
* Shorthand for callbackSetProcess() followed by callbackRequest()
|
||||
*
|
||||
* @pre Callback object must be zero initialized before first call.
|
||||
*/
|
||||
DBCORE_API int callbackRequestProcessCallback(
|
||||
epicsCallback *pCallback,int Priority, void *pRec);
|
||||
/** Queue delayed callback request
|
||||
*
|
||||
* Each epicsCallback has a single timer.
|
||||
* Repeated calls before expiration will cancel and reschedule timer.
|
||||
* epicsCallback object must not be modified while queued,
|
||||
* and must remain valid while queued or executing.
|
||||
*
|
||||
* epicsCallback::timer must be zeroed before the first call,
|
||||
* and left unmodified for subsequent calls.
|
||||
* Each epicsCallback is allocated a timer on first call.
|
||||
* There is no way to free this allocation.
|
||||
* Reuse of epicsCallback is strongly recommended.
|
||||
*
|
||||
* @param pCallback Callback object.
|
||||
* Caller expected to initialize or zero all members prior to first call.
|
||||
* @param seconds Relative to call time. Expected to be >= 0.
|
||||
* @return Zero on success.
|
||||
* Errors if callback members not initialized correctly, or if queue is full.
|
||||
*/
|
||||
DBCORE_API void callbackRequestDelayed(
|
||||
epicsCallback *pCallback,double seconds);
|
||||
/** Cancel delayed callback.
|
||||
*
|
||||
* Usage not recommended. Caller can not distinguish between successful
|
||||
* cancellation, or expiration. In the later case the callback may still be
|
||||
* queued or executing.
|
||||
*
|
||||
* @param pcallback Callback object previously passed to callbackRequestDelayed()
|
||||
*
|
||||
* @post Timer is cancelled. However, callback may be queued or executing.
|
||||
*/
|
||||
DBCORE_API void callbackCancelDelayed(epicsCallback *pcallback);
|
||||
/** (Re)Initialize callback object and queue
|
||||
*
|
||||
* Shorthand for callbackSetProcess() followed by callbackRequestDelayed()
|
||||
*
|
||||
* @pre Callback object must be zero initialized before first call.
|
||||
*/
|
||||
DBCORE_API void callbackRequestProcessCallbackDelayed(
|
||||
epicsCallback *pCallback, int Priority, void *pRec, double seconds);
|
||||
/** Set callback queue depth
|
||||
*
|
||||
* @param size A positive integer
|
||||
* @return -1 if too late to change depth
|
||||
*
|
||||
* @pre Must be called before iocInit()
|
||||
*/
|
||||
DBCORE_API int callbackSetQueueSize(int size);
|
||||
/** Query configuration and statistics from callback system
|
||||
* @param reset If non-zero, reset maxUsed after reading.
|
||||
* @param result NULL, or location for results
|
||||
* @return -2 if result is NULL. reset happens anyway.
|
||||
*
|
||||
* @since 7.0.2. Also present in 3.16.2
|
||||
*/
|
||||
DBCORE_API int callbackQueueStatus(const int reset, callbackQueueStats *result);
|
||||
DBCORE_API void callbackQueueShow(const int reset);
|
||||
/** Setup multiple worker threads for specified priority
|
||||
*
|
||||
* By default, only one thread is run for each priority (3 in total).
|
||||
*
|
||||
* Calling with count==0 will take the count from the callbackParallelThreadsDefault
|
||||
* global variable (default default is 2).
|
||||
* Calling with count>0 sets the number of worker threads directly.
|
||||
* Calling with count<0 computes the count based on the number of CPU cores on the host.
|
||||
* eg. Passing -2 on an 8 core system will start 6 worker threads.
|
||||
* In all cases, at least one worker thread will always run.
|
||||
*
|
||||
* A special prio name of "*" will modify all priorities.
|
||||
* Otherwise, only the named priority is modified.
|
||||
*
|
||||
* @param count If zero, reset to default (callbackParallelThreadsDefault global/iocsh variable).
|
||||
* If positive, exact number of worker threads to create.
|
||||
* If negative, number of worker threads less than core count.
|
||||
* @param prio Priority name. eg. "*", "LOW", "MEDIUM" or "HIGH".
|
||||
* @return zero on success, non-zero if called after iocInit() or with invalid arguments.
|
||||
*
|
||||
* @pre Must be called before iocInit()
|
||||
*
|
||||
* @since 3.15.0.2
|
||||
*/
|
||||
DBCORE_API int callbackParallelThreads(int count, const char *prio);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -339,7 +339,7 @@ static parse_result parse_start(chFilter *filter)
|
||||
}
|
||||
}
|
||||
|
||||
filter->puser = (void*) f;
|
||||
filter->puser = f;
|
||||
|
||||
return parse_continue;
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ long cvtRawToEngBpt(double *pval, short linr, short init,
|
||||
if (!pbrkTable)
|
||||
return S_dbLib_badField;
|
||||
|
||||
*ppbrk = (void *)pbrkTable;
|
||||
*ppbrk = pbrkTable;
|
||||
*plbrk = 0;
|
||||
} else
|
||||
pbrkTable = (brkTable *)*ppbrk;
|
||||
@@ -138,7 +138,7 @@ long cvtEngToRawBpt(double *pval, short linr, short init,
|
||||
if (!pbrkTable)
|
||||
return S_dbLib_badField;
|
||||
|
||||
*ppbrk = (void *)pbrkTable;
|
||||
*ppbrk = pbrkTable;
|
||||
/* start at the beginning */
|
||||
*plbrk = 0;
|
||||
} else
|
||||
|
||||
@@ -183,7 +183,7 @@ static void get_enum_strs(DBADDR *paddr, char **ppbuffer,
|
||||
}
|
||||
|
||||
if(nchoices > NELEMENTS(penum->strs))
|
||||
nchoices = NELEMENTS(penum->strs); /* availible > capacity, truncated list */
|
||||
nchoices = NELEMENTS(penum->strs); /* available > capacity, truncated list */
|
||||
|
||||
penum->no_str = nchoices;
|
||||
|
||||
@@ -550,7 +550,7 @@ long dbProcess(dbCommon *precord)
|
||||
monitor_mask |= DBE_VALUE|DBE_LOG;
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
|
||||
db_post_events(precord,
|
||||
(void *)(((char *)precord) + pdbFldDes->offset),
|
||||
((char *)precord) + pdbFldDes->offset,
|
||||
monitor_mask);
|
||||
goto all_done;
|
||||
}
|
||||
@@ -587,7 +587,7 @@ long dbProcess(dbCommon *precord)
|
||||
db_post_events(precord, &precord->sevr, DBE_VALUE);
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
|
||||
db_post_events(precord,
|
||||
(void *)(((char *)precord) + pdbFldDes->offset),
|
||||
((char *)precord) + pdbFldDes->offset,
|
||||
DBE_VALUE|DBE_ALARM);
|
||||
goto all_done;
|
||||
}
|
||||
@@ -597,7 +597,7 @@ long dbProcess(dbCommon *precord)
|
||||
if (!prset || !prset->process) {
|
||||
callNotifyCompletion = TRUE;
|
||||
precord->pact = 1;/*set pact so error is issued only once*/
|
||||
recGblRecordError(S_db_noRSET, (void *)precord, "dbProcess");
|
||||
recGblRecordError(S_db_noRSET, precord, "dbProcess");
|
||||
status = S_db_noRSET;
|
||||
if (*ptrace)
|
||||
printf("%s: No RSET for %s\n", context, precord->name);
|
||||
@@ -709,7 +709,7 @@ void dbInitEntryFromAddr(struct dbAddr *paddr, DBENTRY *pdbentry)
|
||||
struct dbCommon *prec = paddr->precord;
|
||||
dbCommonPvt *ppvt = dbRec2Pvt(prec);
|
||||
|
||||
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
|
||||
memset(pdbentry, '\0', sizeof(DBENTRY));
|
||||
|
||||
pdbentry->pdbbase = pdbbase;
|
||||
pdbentry->precordType = prec->rdes;
|
||||
@@ -723,7 +723,7 @@ void dbInitEntryFromRecord(struct dbCommon *prec, DBENTRY *pdbentry)
|
||||
{
|
||||
dbCommonPvt *ppvt = dbRec2Pvt(prec);
|
||||
|
||||
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
|
||||
memset(pdbentry, '\0', sizeof(DBENTRY));
|
||||
|
||||
pdbentry->pdbbase = pdbbase;
|
||||
pdbentry->precordType = prec->rdes;
|
||||
@@ -805,7 +805,7 @@ int dbLoadRecords(const char* file, const char* subs)
|
||||
if(dbLoadRecordsHook)
|
||||
dbLoadRecordsHook(file, subs);
|
||||
} else {
|
||||
fprintf(stderr, ERL_ERROR " failed to load '%s'\n", file);
|
||||
fprintf(stderr, ERL_ERROR ": Failed to load '%s'\n", file);
|
||||
if(status==-2)
|
||||
fprintf(stderr, " Records cannot be loaded after iocInit!\n");
|
||||
}
|
||||
@@ -1070,7 +1070,7 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
dbFldDes *pfldDes = paddr->pfldDes;
|
||||
long special = paddr->special;
|
||||
struct link *plink = (struct link *)paddr->pfield;
|
||||
const char *pstring = (const char *)pbuffer;
|
||||
const char *pstring = pbuffer;
|
||||
struct dsxt *old_dsxt = NULL;
|
||||
dset *new_dset = NULL;
|
||||
struct dsxt *new_dsxt = NULL;
|
||||
@@ -1095,7 +1095,7 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
return S_db_badDbrtype;
|
||||
}
|
||||
|
||||
status = dbParseLink(pstring, pfldDes->field_type, &link_info);
|
||||
status = dbParseLink(pstring, pfldDes->field_type, &link_info, precord->name, pfldDes->name);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@@ -1130,7 +1130,7 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
}
|
||||
|
||||
if (dbCanSetLink(plink, &link_info, new_devsup)) {
|
||||
/* link type mis-match prevents assignment */
|
||||
/* link type mismatch prevents assignment */
|
||||
status = S_dbLib_badField;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
@@ -207,6 +207,7 @@ private:
|
||||
cacChannel::priLev );
|
||||
void flush (
|
||||
epicsGuard < epicsMutex > & );
|
||||
void sync ();
|
||||
unsigned circuitCount (
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
void selfTest (
|
||||
|
||||
@@ -120,7 +120,7 @@ static int dbca_chan_count;
|
||||
* The libca callbacks take no action if pca->plink==NULL.
|
||||
*
|
||||
* dbCaPutLinkCallback causes an additional complication because
|
||||
* when dbCaRemoveLink is called the callback may not have occured.
|
||||
* when dbCaRemoveLink is called the callback may not have occurred.
|
||||
* If putComplete sees plink==0 it will not call the user's code.
|
||||
* If pca->putCallback is non-zero, dbCaTask will call the
|
||||
* user's callback AFTER it has called ca_clear_channel.
|
||||
@@ -209,9 +209,9 @@ void testdbCaWaitForEventCB(void *raw)
|
||||
{
|
||||
struct waitPvt *pvt = raw;
|
||||
|
||||
epicsMutexMustLock(pvt->pca->lock);
|
||||
epicsMutexMustLock(workListLock);
|
||||
epicsEventMustTrigger(pvt->evt);
|
||||
epicsMutexUnlock(pvt->pca->lock);
|
||||
epicsMutexUnlock(workListLock);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -239,8 +239,6 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
|
||||
dbScanUnlock(plink->precord);
|
||||
|
||||
epicsEventMustWait(evt);
|
||||
/* ensure worker has finished executing */
|
||||
dbCaSync();
|
||||
|
||||
dbScanLock(plink->precord);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
@@ -250,8 +248,15 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
|
||||
pca->userPvt = NULL;
|
||||
}
|
||||
|
||||
epicsEventDestroy(evt);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
|
||||
/* ensure worker has finished executing */
|
||||
dbCaSync();
|
||||
|
||||
epicsMutexMustLock(workListLock); /* lock to ensure that epicsEventMustTrigger() has returned */
|
||||
epicsEventDestroy(evt);
|
||||
epicsMutexUnlock(workListLock);
|
||||
|
||||
caLinkDec(pca);
|
||||
dbScanUnlock(plink->precord);
|
||||
}
|
||||
@@ -266,6 +271,10 @@ void testdbCaWaitForUpdateCount(DBLINK *plink, unsigned long cnt)
|
||||
testdbCaWaitForEvent(plink, cnt, testEventCount);
|
||||
}
|
||||
|
||||
// private access to access.cpp
|
||||
LIBCA_API
|
||||
void dbCaSyncLocal(void);
|
||||
|
||||
/* Block until worker thread has processed all previously queued actions.
|
||||
* Does not prevent additional actions from being queued.
|
||||
*/
|
||||
@@ -274,6 +283,8 @@ void dbCaSync(void)
|
||||
epicsEventId wake;
|
||||
caLink templink;
|
||||
|
||||
dbCaSyncLocal();
|
||||
|
||||
/* we only partially initialize templink.
|
||||
* It has no link field and no subscription
|
||||
* so the worker must handle it early
|
||||
@@ -487,7 +498,7 @@ long dbCaGetLink(struct link *plink, short dbrType, void *pdest,
|
||||
ntoget = pca->usedelements;
|
||||
*nelements = ntoget;
|
||||
|
||||
memset((void *)&dbAddr, 0, sizeof(dbAddr));
|
||||
memset(&dbAddr, 0, sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pgetNative;
|
||||
/*Following will only be used for pca->dbrType == DBR_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
@@ -568,7 +579,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
|
||||
long (*aConvert)(struct dbAddr *paddr, const void *from, long nreq, long nfrom, long off);
|
||||
|
||||
aConvert = dbPutConvertRoutine[dbrType][newType];
|
||||
memset((void *)&dbAddr, 0, sizeof(dbAddr));
|
||||
memset(&dbAddr, 0, sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pputNative;
|
||||
/*Following only used for DBF_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
@@ -1139,7 +1150,7 @@ static void dbCaTask(void *arg)
|
||||
}
|
||||
if (link_action & CA_CONNECT) {
|
||||
status = ca_create_channel(
|
||||
pca->pvname,connectionCallback,(void *)pca,
|
||||
pca->pvname, connectionCallback, pca,
|
||||
CA_PRIORITY_DB_LINKS, &(pca->chid));
|
||||
if (status != ECA_NORMAL) {
|
||||
errlogPrintf("dbCaTask ca_create_channel %s\n",
|
||||
|
||||
@@ -346,7 +346,7 @@ DBCORE_API void dbChannelInit(void);
|
||||
/** \brief Cleanup the dbChannel subsystem. */
|
||||
DBCORE_API void dbChannelExit(void);
|
||||
|
||||
/** \brief Test the given PV name for existance.
|
||||
/** \brief Test the given PV name for existence.
|
||||
*
|
||||
* This routine looks up the given record and field name, but does not check
|
||||
* whether any field modifiers given after the field name are correct.
|
||||
@@ -512,7 +512,7 @@ DBCORE_API long dbChannelGet(dbChannel *chan, short type,
|
||||
* \param[in] pfl Pointer to a db_field_log or NULL.
|
||||
* \returns 0, or an error status value.
|
||||
*
|
||||
* \since UNRELEASED If pfl is NULL and chan has filters, db_create_read_log() will be called
|
||||
* \since 7.0.10 If pfl is NULL and chan has filters, db_create_read_log() will be called
|
||||
* internally to create a temporary db_field_log which is passed to dbChannelGet()
|
||||
* then deallocated.
|
||||
*/
|
||||
|
||||
@@ -522,7 +522,7 @@ hardware.
|
||||
|
||||
=item *
|
||||
|
||||
Positive values (normally between 1-255) get the time of the last occurance of
|
||||
Positive values (normally between 1-255) get the time of the last occurrence of
|
||||
the numbered generalTime event.
|
||||
|
||||
=back
|
||||
|
||||
@@ -399,6 +399,23 @@ void dbContext::flush (
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void dbContextDummyExtraLabor(void *) {}
|
||||
|
||||
void dbContext::sync()
|
||||
{
|
||||
// ctx created lazily on first subscription
|
||||
{
|
||||
epicsGuard<epicsMutex> G(mutex);
|
||||
if(!ctx)
|
||||
return;
|
||||
}
|
||||
// assumes dbContext makes no other use of extra labor
|
||||
db_add_extra_labor_event(ctx, dbContextDummyExtraLabor, NULL);
|
||||
db_post_extra_labor(ctx);
|
||||
db_flush_extra_labor_event(ctx);
|
||||
}
|
||||
|
||||
unsigned dbContext::circuitCount (
|
||||
epicsGuard < epicsMutex > & guard ) const
|
||||
{
|
||||
|
||||
@@ -384,7 +384,7 @@ static long dbDbPutValue(struct link *plink, short dbrType,
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (dbChannelField(chan) == (void *) &pdest->proc ||
|
||||
if (dbChannelField(chan) == &pdest->proc ||
|
||||
(ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
|
||||
status = processTarget(psrce, pdest);
|
||||
}
|
||||
|
||||
@@ -200,19 +200,19 @@ int dbel ( const char *pname, unsigned level )
|
||||
const void * taskId;
|
||||
LOCKEVQUE(pevent->ev_que);
|
||||
nEntriesFree = ringSpace ( pevent->ev_que );
|
||||
taskId = ( void * ) pevent->ev_que->evUser->taskid;
|
||||
taskId = pevent->ev_que->evUser->taskid;
|
||||
UNLOCKEVQUE(pevent->ev_que);
|
||||
if ( nEntriesFree == 0u ) {
|
||||
printf ( ", thread=%p, queue full",
|
||||
(void *) taskId );
|
||||
taskId );
|
||||
}
|
||||
else if ( nEntriesFree == EVENTQUESIZE ) {
|
||||
printf ( ", thread=%p, queue empty",
|
||||
(void *) taskId );
|
||||
taskId );
|
||||
}
|
||||
else {
|
||||
printf ( ", thread=%p, unused entries=%u",
|
||||
(void *) taskId, nEntriesFree );
|
||||
taskId, nEntriesFree );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,9 +234,9 @@ int dbel ( const char *pname, unsigned level )
|
||||
|
||||
if ( level > 3 ) {
|
||||
printf ( ", ev %p, ev que %p, ev user %p",
|
||||
( void * ) pevent,
|
||||
( void * ) pevent->ev_que,
|
||||
( void * ) pevent->ev_que->evUser );
|
||||
pevent,
|
||||
pevent->ev_que,
|
||||
pevent->ev_que->evUser );
|
||||
}
|
||||
|
||||
printf( "\n" );
|
||||
@@ -557,6 +557,40 @@ static void event_remove ( struct event_que *ev_que,
|
||||
pevent->npend--;
|
||||
}
|
||||
|
||||
/* synchronize with worker thread.
|
||||
*
|
||||
* On return, any previously pending events or extra labor have been handled.
|
||||
*
|
||||
* caller must lock evUser->lock
|
||||
*/
|
||||
static
|
||||
void db_sync_event (struct event_user * const evUser)
|
||||
{
|
||||
/* grab current cycle counter, then wait for it to change */
|
||||
epicsUInt32 curSeq = evUser->pflush_seq;
|
||||
event_waiter wait;
|
||||
wait.wake = epicsEventCreate(epicsEventEmpty); /* failure allowed */
|
||||
|
||||
ellAdd(&evUser->waiters, &wait.node);
|
||||
do {
|
||||
epicsMutexUnlock( evUser->lock );
|
||||
/* ensure worker will cycle at least once */
|
||||
epicsEventMustTrigger(evUser->ppendsem);
|
||||
|
||||
if(wait.wake) {
|
||||
epicsEventMustWait(wait.wake);
|
||||
} else {
|
||||
epicsThreadSleep(0.01); /* ick. but better than cantProceed() */
|
||||
}
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
} while(curSeq == evUser->pflush_seq);
|
||||
ellDelete(&evUser->waiters, &wait.node);
|
||||
/* destroy under lock to ensure epicsEventMustTrigger() has returned */
|
||||
if(wait.wake)
|
||||
epicsEventDestroy(wait.wake);
|
||||
}
|
||||
|
||||
/*
|
||||
* DB_CANCEL_EVENT()
|
||||
*
|
||||
@@ -594,34 +628,9 @@ void db_cancel_event (dbEventSubscription event)
|
||||
UNLOCKEVQUE (que);
|
||||
|
||||
if(sync) {
|
||||
/* cycle through worker */
|
||||
struct event_user *evUser = que->evUser;
|
||||
epicsUInt32 curSeq;
|
||||
event_waiter wait;
|
||||
wait.wake = epicsEventCreate(epicsEventEmpty); /* may fail */
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
ellAdd(&evUser->waiters, &wait.node);
|
||||
/* grab current cycle counter, then wait for it to change */
|
||||
curSeq = evUser->pflush_seq;
|
||||
do {
|
||||
epicsMutexUnlock( evUser->lock );
|
||||
/* ensure worker will cycle at least once */
|
||||
epicsEventMustTrigger(evUser->ppendsem);
|
||||
|
||||
if(wait.wake) {
|
||||
epicsEventMustWait(wait.wake);
|
||||
} else {
|
||||
epicsThreadSleep(0.01); /* ick. but better than cantProceed() */
|
||||
}
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
} while(curSeq == evUser->pflush_seq);
|
||||
ellDelete(&evUser->waiters, &wait.node);
|
||||
/* destroy under lock to ensure epicsEventMustTrigger() has returned */
|
||||
if(wait.wake)
|
||||
epicsEventDestroy(wait.wake);
|
||||
epicsMutexUnlock( evUser->lock );
|
||||
epicsMutexMustLock ( que->evUser->lock );
|
||||
db_sync_event(que->evUser);
|
||||
epicsMutexUnlock( que->evUser->lock );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,10 +644,10 @@ void db_flush_extra_labor_event (dbEventCtx ctx)
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
while ( evUser->extraLaborBusy ) {
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
epicsThreadSleep(0.1);
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
if ( evUser->extraLaborBusy || (evUser->extra_labor && evUser->extralabor_sub) ) {
|
||||
db_sync_event(evUser);
|
||||
// At this point, original labor completed.
|
||||
// Do not wait for any additional labor queued afterwards.
|
||||
}
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
}
|
||||
@@ -884,7 +893,7 @@ unsigned int caEventMask
|
||||
* Only send event msg if they are waiting on the field which
|
||||
* changed or pval==NULL, and are waiting on matching event
|
||||
*/
|
||||
if ( (dbChannelField(pevent->chan) == (void *)pField || pField==NULL) &&
|
||||
if ( (dbChannelField(pevent->chan) == pField || pField==NULL) &&
|
||||
(caEventMask & pevent->select)) {
|
||||
db_field_log *pLog = db_create_event_log(pevent);
|
||||
if(pLog)
|
||||
@@ -1027,9 +1036,7 @@ static void event_task (void *pParm)
|
||||
* labor to this task
|
||||
*/
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
evUser->extraLaborBusy = TRUE;
|
||||
if ( evUser->extra_labor && evUser->extralabor_sub ) {
|
||||
evUser->extra_labor = FALSE;
|
||||
pExtraLaborSub = evUser->extralabor_sub;
|
||||
pExtraLaborArg = evUser->extralabor_arg;
|
||||
}
|
||||
@@ -1037,12 +1044,14 @@ static void event_task (void *pParm)
|
||||
pExtraLaborSub = NULL;
|
||||
pExtraLaborArg = NULL;
|
||||
}
|
||||
evUser->extra_labor = FALSE;
|
||||
if ( pExtraLaborSub ) {
|
||||
evUser->extraLaborBusy = TRUE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
(*pExtraLaborSub)(pExtraLaborArg);
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
evUser->extraLaborBusy = FALSE;
|
||||
}
|
||||
evUser->extraLaborBusy = FALSE;
|
||||
|
||||
for ( ev_que = &evUser->firstque; ev_que; ev_que = ev_que->nextque ) {
|
||||
/* unlock during iteration is safe as event_que will not be free'd */
|
||||
@@ -1126,7 +1135,7 @@ int db_start_events (
|
||||
taskname = EVENT_PEND_NAME;
|
||||
}
|
||||
evUser->taskid = epicsThreadCreateOpt (
|
||||
taskname, event_task, (void *)evUser, &opts);
|
||||
taskname, event_task, evUser, &opts);
|
||||
if (!evUser->taskid) {
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
return DB_EVENT_ERROR;
|
||||
|
||||
@@ -199,7 +199,7 @@ static const iocshFuncDef dblFuncDef = {"dbl",2,dblArgs,
|
||||
"Database list.\n"
|
||||
"List record/field names.\n"
|
||||
"With no arguments, lists all record names.\n"
|
||||
"If record type is given, then only the names of records maching the type are printed\n"
|
||||
"If record type is given, then only the names of records matching the type are printed\n"
|
||||
"If a field list is given, then their values are also printed\n\n"
|
||||
"Example: dbl(\"\")\n"
|
||||
" dbl(\"ai\")\n"
|
||||
@@ -440,7 +440,7 @@ static const iocshArg scanOnceQueueShowArg0 = { "reset",iocshArgInt};
|
||||
static const iocshArg * const scanOnceQueueShowArgs[1] =
|
||||
{&scanOnceQueueShowArg0};
|
||||
static const iocshFuncDef scanOnceQueueShowFuncDef = {"scanOnceQueueShow",1,scanOnceQueueShowArgs,
|
||||
"Show details and statitics of scan once queue processing.\n"};
|
||||
"Show details and statistics of scan once queue processing.\n"};
|
||||
static void scanOnceQueueShowCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
scanOnceQueueShow(args[0].ival);
|
||||
|
||||
@@ -233,7 +233,7 @@ static void processNotifyCommon(processNotify *ppn, dbCommon *precord, int first
|
||||
if (ppn->requestType == putProcessRequest ||
|
||||
ppn->requestType == putProcessGetRequest) {
|
||||
/* Check if puts disabled */
|
||||
if (precord->disp && (dbChannelField(ppn->chan) != (void *) &precord->disp)) {
|
||||
if (precord->disp && (dbChannelField(ppn->chan) != &precord->disp)) {
|
||||
ppn->putCallback(ppn, putDisabledType);
|
||||
} else {
|
||||
didPut = ppn->putCallback(ppn, putType);
|
||||
@@ -241,7 +241,7 @@ static void processNotifyCommon(processNotify *ppn, dbCommon *precord, int first
|
||||
}
|
||||
/* Check if dbProcess should be called */
|
||||
if (didPut &&
|
||||
((dbChannelField(ppn->chan) == (void *) &precord->proc) ||
|
||||
((dbChannelField(ppn->chan) == &precord->proc) ||
|
||||
(dbChannelFldDes(ppn->chan)->process_passive && precord->scan == 0)))
|
||||
doProcess = 1;
|
||||
else
|
||||
@@ -338,7 +338,7 @@ void dbProcessNotify(processNotify *ppn)
|
||||
if (ppn->requestType == putProcessRequest ||
|
||||
ppn->requestType == putProcessGetRequest) {
|
||||
/* Check if puts disabled */
|
||||
if (precord->disp && (dbChannelField(ppn->chan) != (void *) &precord->disp)) {
|
||||
if (precord->disp && (dbChannelField(ppn->chan) != &precord->disp)) {
|
||||
ppn->putCallback(ppn, putDisabledType);
|
||||
} else {
|
||||
ppn->putCallback(ppn, putFieldType);
|
||||
@@ -661,7 +661,7 @@ int dbNotifyDump(void)
|
||||
|
||||
pnotifyPvt = (notifyPvt *) ppn->pnotifyPvt;
|
||||
printf("%s state %d ppn %p\n waitList\n",
|
||||
precord->name, pnotifyPvt->state, (void*) ppn);
|
||||
precord->name, pnotifyPvt->state, ppn);
|
||||
ppnr = (processNotifyRecord *) ellFirst(&pnotifyPvt->waitList);
|
||||
while (ppnr) {
|
||||
printf(" %s pact %d\n",
|
||||
|
||||
@@ -245,7 +245,7 @@ void scanAdd(struct dbCommon *precord)
|
||||
scan = precord->scan;
|
||||
if (scan == menuScanPassive) return;
|
||||
if (scan < 0 || scan >= nPeriodic + SCAN_1ST_PERIODIC) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd detected illegal SCAN value");
|
||||
} else if (scan == menuScanEvent) {
|
||||
char* eventname;
|
||||
@@ -255,7 +255,7 @@ void scanAdd(struct dbCommon *precord)
|
||||
eventname = precord->evnt;
|
||||
prio = precord->prio;
|
||||
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: illegal prio field");
|
||||
return;
|
||||
}
|
||||
@@ -267,14 +267,14 @@ void scanAdd(struct dbCommon *precord)
|
||||
long (*get_ioint_info)(int, struct dbCommon *, IOSCANPVT*);
|
||||
|
||||
if (precord->dset == NULL){
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: I/O Intr not valid (no DSET) ");
|
||||
precord->scan = menuScanPassive;
|
||||
return;
|
||||
}
|
||||
get_ioint_info = precord->dset->get_ioint_info;
|
||||
if (get_ioint_info == NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: I/O Intr not valid (no get_ioint_info)");
|
||||
precord->scan = menuScanPassive;
|
||||
return;
|
||||
@@ -284,14 +284,14 @@ void scanAdd(struct dbCommon *precord)
|
||||
return;
|
||||
}
|
||||
if (piosh == NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: I/O Intr not valid");
|
||||
precord->scan = menuScanPassive;
|
||||
return;
|
||||
}
|
||||
prio = precord->prio;
|
||||
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: illegal prio field");
|
||||
precord->scan = menuScanPassive;
|
||||
return;
|
||||
@@ -313,7 +313,7 @@ void scanDelete(struct dbCommon *precord)
|
||||
scan = precord->scan;
|
||||
if (scan == menuScanPassive) return;
|
||||
if (scan < 0 || scan >= nPeriodic + SCAN_1ST_PERIODIC) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete detected illegal SCAN value");
|
||||
} else if (scan == menuScanEvent) {
|
||||
int prio;
|
||||
@@ -322,7 +322,7 @@ void scanDelete(struct dbCommon *precord)
|
||||
|
||||
prio = precord->prio;
|
||||
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete detected illegal PRIO field");
|
||||
return;
|
||||
}
|
||||
@@ -335,25 +335,25 @@ void scanDelete(struct dbCommon *precord)
|
||||
long (*get_ioint_info)(int, struct dbCommon *, IOSCANPVT*);
|
||||
|
||||
if (precord->dset==NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete: I/O Intr not valid (no DSET)");
|
||||
return;
|
||||
}
|
||||
get_ioint_info=precord->dset->get_ioint_info;
|
||||
if (get_ioint_info == NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete: I/O Intr not valid (no get_ioint_info)");
|
||||
return;
|
||||
}
|
||||
if (get_ioint_info(1, precord, &piosh)) return;
|
||||
if (piosh == NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete: I/O Intr not valid");
|
||||
return;
|
||||
}
|
||||
prio = precord->prio;
|
||||
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete: get_ioint_info returned illegal priority");
|
||||
return;
|
||||
}
|
||||
@@ -949,7 +949,7 @@ static void spawnPeriodic(int ind)
|
||||
|
||||
sprintf(taskName, "scan-%g", ppsl->period);
|
||||
periodicTaskId[ind] = epicsThreadCreateOpt(
|
||||
taskName, periodicTask, (void *)ppsl, &opts);
|
||||
taskName, periodicTask, ppsl, &opts);
|
||||
|
||||
epicsEventWait(startStopEvent);
|
||||
}
|
||||
@@ -1103,14 +1103,14 @@ static void deleteFromList(struct dbCommon *precord, scan_list *psl)
|
||||
epicsMutexUnlock(psl->lock);
|
||||
errlogPrintf("dbScan: Tried to delete record from wrong scan list!\n"
|
||||
"\t%s.SPVT = NULL, but psl = %p\n",
|
||||
precord->name, (void *)psl);
|
||||
precord->name, psl);
|
||||
return;
|
||||
}
|
||||
if (pse->pscan_list != psl) {
|
||||
epicsMutexUnlock(psl->lock);
|
||||
errlogPrintf("dbScan: Tried to delete record from wrong scan list!\n"
|
||||
"\t%s.SPVT->pscan_list = %p but psl = %p\n",
|
||||
precord->name, (void *)pse, (void *)psl);
|
||||
precord->name, pse, psl);
|
||||
return;
|
||||
}
|
||||
pse->pscan_list = NULL;
|
||||
|
||||
@@ -112,7 +112,7 @@ DBCORE_API void scanIoInit(IOSCANPVT *ppios);
|
||||
* @return
|
||||
*/
|
||||
DBCORE_API unsigned int scanIoRequest(IOSCANPVT pios);
|
||||
/** @brief Process all records on the scan list for the specificed priority.
|
||||
/** @brief Process all records on the scan list for the specified priority.
|
||||
*
|
||||
* Also executes the callback set by scanIoSetComplete()
|
||||
*
|
||||
|
||||
@@ -143,7 +143,7 @@ DBCORE_API void dbsr(unsigned level);
|
||||
DBCORE_API int dbServerClient(char *pBuf, size_t bufSize);
|
||||
|
||||
/** @brief CPP Macro indicating the dbServerStats() routine exists.
|
||||
* @since UNRELEASED
|
||||
* @since 7.0.10
|
||||
*/
|
||||
#define HAS_DBSERVER_STATS
|
||||
|
||||
@@ -161,7 +161,7 @@ DBCORE_API int dbServerClient(char *pBuf, size_t bufSize);
|
||||
* variables and returns the number of dbServer::stats() methods called,
|
||||
* 0 if a named server wasn't found or doesn't have a stats() method.
|
||||
*
|
||||
* @since UNRELEASED
|
||||
* @since 7.0.10
|
||||
*/
|
||||
DBCORE_API int dbServerStats(const char *name, unsigned *channels,
|
||||
unsigned *clients);
|
||||
|
||||
@@ -45,7 +45,7 @@ dbSubscriptionIO::dbSubscriptionIO (
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
this->es = db_add_event ( ctx, dbch,
|
||||
dbSubscriptionEventCallback, (void *) this, maskIn );
|
||||
dbSubscriptionEventCallback, this, maskIn );
|
||||
if ( this->es == 0 ) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
@@ -192,8 +192,8 @@ long dbl(const char *precordTypename, const char *fields)
|
||||
status = dbNextRecordType(pdbentry);
|
||||
}
|
||||
if (nfields > 0) {
|
||||
free((void *)papfields);
|
||||
free((void *)fieldnames);
|
||||
free(papfields);
|
||||
free(fieldnames);
|
||||
}
|
||||
dbFinishEntry(pdbentry);
|
||||
return 0;
|
||||
@@ -334,8 +334,8 @@ long dbglob(const char *pmask,const char *fields)
|
||||
status = dbNextRecordType(pdbentry);
|
||||
}
|
||||
if (nfields > 0) {
|
||||
free((void *)papfields);
|
||||
free((void *)fieldnames);
|
||||
free(papfields);
|
||||
free(fieldnames);
|
||||
}
|
||||
dbFinishEntry(pdbentry);
|
||||
return 0;
|
||||
@@ -826,7 +826,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_STATUS) {
|
||||
if (retOptions & DBR_STATUS) {
|
||||
struct dbr_status *pdbr_status = (void *)pbuffer;
|
||||
struct dbr_status *pdbr_status = pbuffer;
|
||||
|
||||
printf("status = %u, severity = %u\n",
|
||||
pdbr_status->status,
|
||||
@@ -840,7 +840,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_UNITS) {
|
||||
if (retOptions & DBR_UNITS) {
|
||||
struct dbr_units *pdbr_units = (void *)pbuffer;
|
||||
struct dbr_units *pdbr_units = pbuffer;
|
||||
|
||||
printf("units = \"%s\"\n",
|
||||
pdbr_units->units);
|
||||
@@ -853,7 +853,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_PRECISION) {
|
||||
if (retOptions & DBR_PRECISION){
|
||||
struct dbr_precision *pdbr_precision = (void *)pbuffer;
|
||||
struct dbr_precision *pdbr_precision = pbuffer;
|
||||
|
||||
printf("precision = %ld\n",
|
||||
pdbr_precision->precision.dp);
|
||||
@@ -866,7 +866,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_TIME) {
|
||||
if (retOptions & DBR_TIME) {
|
||||
struct dbr_time *pdbr_time = (void *)pbuffer;
|
||||
struct dbr_time *pdbr_time = pbuffer;
|
||||
char time_buf[40];
|
||||
epicsTimeToStrftime(time_buf, 40, "%Y-%m-%d %H:%M:%S.%09f",
|
||||
&pdbr_time->time);
|
||||
@@ -880,7 +880,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_ENUM_STRS) {
|
||||
if (retOptions & DBR_ENUM_STRS) {
|
||||
struct dbr_enumStrs *pdbr_enumStrs = (void *)pbuffer;
|
||||
struct dbr_enumStrs *pdbr_enumStrs = pbuffer;
|
||||
|
||||
printf("no_strs = %u:\n",
|
||||
pdbr_enumStrs->no_str);
|
||||
@@ -895,7 +895,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_GR_LONG) {
|
||||
if (retOptions & DBR_GR_LONG) {
|
||||
struct dbr_grLong *pdbr_grLong = (void *)pbuffer;
|
||||
struct dbr_grLong *pdbr_grLong = pbuffer;
|
||||
|
||||
printf("grLong: %d .. %d\n",
|
||||
pdbr_grLong->lower_disp_limit,
|
||||
@@ -909,7 +909,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_GR_DOUBLE) {
|
||||
if (retOptions & DBR_GR_DOUBLE) {
|
||||
struct dbr_grDouble *pdbr_grDouble = (void *)pbuffer;
|
||||
struct dbr_grDouble *pdbr_grDouble = pbuffer;
|
||||
|
||||
printf("grDouble: %g .. %g\n",
|
||||
pdbr_grDouble->lower_disp_limit,
|
||||
@@ -923,7 +923,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_CTRL_LONG) {
|
||||
if (retOptions & DBR_CTRL_LONG){
|
||||
struct dbr_ctrlLong *pdbr_ctrlLong = (void *)pbuffer;
|
||||
struct dbr_ctrlLong *pdbr_ctrlLong = pbuffer;
|
||||
|
||||
printf("ctrlLong: %d .. %d\n",
|
||||
pdbr_ctrlLong->lower_ctrl_limit,
|
||||
@@ -937,7 +937,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_CTRL_DOUBLE) {
|
||||
if (retOptions & DBR_CTRL_DOUBLE) {
|
||||
struct dbr_ctrlDouble *pdbr_ctrlDouble = (void *)pbuffer;
|
||||
struct dbr_ctrlDouble *pdbr_ctrlDouble = pbuffer;
|
||||
|
||||
printf("ctrlDouble: %g .. %g\n",
|
||||
pdbr_ctrlDouble->lower_ctrl_limit,
|
||||
@@ -951,7 +951,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_AL_LONG) {
|
||||
if (retOptions & DBR_AL_LONG) {
|
||||
struct dbr_alLong *pdbr_alLong = (void *)pbuffer;
|
||||
struct dbr_alLong *pdbr_alLong = pbuffer;
|
||||
|
||||
printf("alLong: %d < %d .. %d < %d\n",
|
||||
pdbr_alLong->lower_alarm_limit,
|
||||
@@ -967,7 +967,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_AL_DOUBLE) {
|
||||
if (retOptions & DBR_AL_DOUBLE) {
|
||||
struct dbr_alDouble *pdbr_alDouble = (void *)pbuffer;
|
||||
struct dbr_alDouble *pdbr_alDouble = pbuffer;
|
||||
|
||||
printf("alDouble: %g < %g .. %g < %g\n",
|
||||
pdbr_alDouble->lower_alarm_limit,
|
||||
@@ -1224,7 +1224,7 @@ static int dbpr_report(
|
||||
break;
|
||||
|
||||
case DBF_NOACCESS:
|
||||
if (pfield == (void *)&paddr->precord->time) {
|
||||
if (pfield == &paddr->precord->time) {
|
||||
/* Special for the TIME field, make it human-readable */
|
||||
char time_buf[40];
|
||||
epicsTimeToStrftime(time_buf, 40, "%Y-%m-%d %H:%M:%S.%09f",
|
||||
|
||||
@@ -27,7 +27,7 @@ DBCORE_API long dbnr(int verbose);
|
||||
/* list aliases */
|
||||
DBCORE_API long dbla(const char *pmask);
|
||||
/* list infos */
|
||||
DBCORE_API long dbli(const char *patern);
|
||||
DBCORE_API long dbli(const char *pattern);
|
||||
/*list records filtered by glob pattern*/
|
||||
DBCORE_API long dbglob(const char *ppattern,const char *fields);
|
||||
/*list records filtered by glob pattern; alias for dbglob*/
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "errSymTbl.h"
|
||||
#include "iocshRegisterCommon.h"
|
||||
|
||||
#define DBR_NAME(dbrType) (VALID_DB_REQ(dbrType) ? pamapdbfType[dbrType].strvalue+3 : "???")
|
||||
|
||||
static dbEventCtx testEvtCtx;
|
||||
static epicsMutexId testEvtLock;
|
||||
static ELLLIST testEvtList; /* holds testMonitor::node */
|
||||
@@ -153,8 +155,8 @@ long testdbVPutField(const char* pv, short dbrType, va_list ap)
|
||||
OP(DBR_ENUM, int, enum16);
|
||||
#undef OP
|
||||
default:
|
||||
testFail("invalid DBR: dbPutField(\"%s\", %d, ...)",
|
||||
dbChannelName(chan), dbrType);
|
||||
testFail("invalid DBR: dbPutField(\"%s\", DBR%s, ...)",
|
||||
dbChannelName(chan), DBR_NAME(dbrType));
|
||||
ret = S_db_badDbrtype;
|
||||
break;
|
||||
}
|
||||
@@ -174,7 +176,8 @@ void testdbPutFieldOk(const char* pv, int dbrType, ...)
|
||||
ret = testdbVPutField(pv, dbrType, ap);
|
||||
va_end(ap);
|
||||
|
||||
testOk(ret==0, "dbPutField(\"%s\", %d, ...) -> %#lx (%s)", pv, dbrType, ret, errSymMsg(ret));
|
||||
testOk(ret==0, "dbPutField(\"%s\", DBR%s, ...) -> %#lx (%s)",
|
||||
pv, DBR_NAME(dbrType), ret, errSymMsg(ret));
|
||||
}
|
||||
|
||||
void testdbPutFieldFail(long status, const char* pv, int dbrType, ...)
|
||||
@@ -186,8 +189,8 @@ void testdbPutFieldFail(long status, const char* pv, int dbrType, ...)
|
||||
ret = testdbVPutField(pv, dbrType, ap);
|
||||
va_end(ap);
|
||||
|
||||
testOk(ret==status, "dbPutField(\"%s\", %d, ...) -> %#lx (%s) == %#lx (%s)",
|
||||
pv, dbrType, status, errSymMsg(status), ret, errSymMsg(ret));
|
||||
testOk(ret==status, "dbPutField(\"%s\", DBR%s, ...) -> %#lx (%s) == %#lx (%s)",
|
||||
pv, DBR_NAME(dbrType), status, errSymMsg(status), ret, errSymMsg(ret));
|
||||
}
|
||||
|
||||
void testdbGetFieldEqual(const char* pv, int dbrType, ...)
|
||||
@@ -213,10 +216,12 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
|
||||
|
||||
status = dbChannelGetField(chan, dbrType, pod.bytes, NULL, &nReq, NULL);
|
||||
if (status) {
|
||||
testFail("dbGetField(\"%s\", %d, ...) -> %#lx (%s)", pv, dbrType, status, errSymMsg(status));
|
||||
testFail("dbGetField(\"%s\", DBR%s, ...) -> %#lx (%s)",
|
||||
pv, DBR_NAME(dbrType), status, errSymMsg(status));
|
||||
goto done;
|
||||
} else if(nReq==0) {
|
||||
testFail("dbGetField(\"%s\", %d, ...) -> zero length", pv, dbrType);
|
||||
testFail("dbGetField(\"%s\", DBR%s, ...) -> zero length",
|
||||
pv, DBR_NAME(dbrType));
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -224,13 +229,14 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
|
||||
case DBR_STRING: {
|
||||
const char *expect = va_arg(ap, char*);
|
||||
testOk(strcmp(expect, pod.valStr)==0,
|
||||
"dbGetField(\"%s\", %d) -> \"%s\" == \"%s\"",
|
||||
pv, dbrType, expect, pod.valStr);
|
||||
"dbGetField(\"%s\", DBR%s) -> \"%s\" == \"%s\"",
|
||||
pv, DBR_NAME(dbrType), expect, pod.valStr);
|
||||
break;
|
||||
}
|
||||
#define OP(DBR,Type,mem,pat) case DBR: {Type expect = va_arg(ap,Type); \
|
||||
testOk(expect==pod.val.mem, "dbGetField(\"%s\", %d) -> " pat " == " pat, \
|
||||
pv, dbrType, expect, (Type)pod.val.mem); break;}
|
||||
testOk(expect==pod.val.mem||((expect!=expect)&&(pod.val.mem!=pod.val.mem)), \
|
||||
"dbGetField(\"%s\", DBR%s) -> " pat " == " pat, \
|
||||
pv, DBR_NAME(dbrType), expect, (Type)pod.val.mem); break;}
|
||||
|
||||
OP(DBR_CHAR, int, int8, "%d");
|
||||
OP(DBR_UCHAR, int, uInt8, "%d");
|
||||
@@ -240,12 +246,12 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
|
||||
OP(DBR_ULONG, unsigned int, uInt32, "%u");
|
||||
OP(DBR_INT64, long long, int64, "%lld");
|
||||
OP(DBR_UINT64, unsigned long long, uInt64, "%llu");
|
||||
OP(DBR_FLOAT, double, float32, "%e");
|
||||
OP(DBR_DOUBLE, double, float64, "%e");
|
||||
OP(DBR_ENUM, int, enum16, "%d");
|
||||
OP(DBR_FLOAT, double, float32, "%g");
|
||||
OP(DBR_DOUBLE, double, float64, "%g");
|
||||
#undef OP
|
||||
default:
|
||||
testFail("dbGetField(\"%s\", %d) -> unsupported dbf", pv, dbrType);
|
||||
testFail("dbGetField(\"%s\", DBR%s) -> unsupported dbf", pv, DBR_NAME(dbrType));
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -265,7 +271,7 @@ void testdbPutArrFieldOk(const char* pv, short dbrType, unsigned long count, con
|
||||
|
||||
status = dbChannelPutField(chan, dbrType, pbuf, count);
|
||||
|
||||
testOk(status==0, "dbPutField(\"%s\", dbr=%d, count=%lu, ...) -> %ld", pv, dbrType, count, status);
|
||||
testOk(status==0, "dbPutField(\"%s\", DBR%s, count=%lu, ...) -> %ld", pv, DBR_NAME(dbrType), count, status);
|
||||
|
||||
done:
|
||||
if(chan)
|
||||
@@ -294,14 +300,14 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign
|
||||
|
||||
status = dbChannelGetField(chan, dbfType, gbuf, NULL, &nRequest, NULL);
|
||||
if (status) {
|
||||
testFail("dbGetField(\"%s\", %d, ...) -> %#lx", pv, dbfType, status);
|
||||
testFail("dbGetField(\"%s\", DBR%s, ...) -> %#lx", pv, DBR_NAME(dbfType), status);
|
||||
|
||||
} else {
|
||||
unsigned match = nRequest==cnt;
|
||||
long n, N = nRequest < cnt ? nRequest : cnt;
|
||||
|
||||
if(!match)
|
||||
testDiag("Length mis-match. expected=%lu actual=%lu", cnt, nRequest);
|
||||
testDiag("Length mismatch. expected=%lu actual=%lu", cnt, nRequest);
|
||||
|
||||
for(n=0; n<N; n++, gbuf+=vSize, pbuf+=vSize) {
|
||||
|
||||
@@ -327,14 +333,14 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign
|
||||
OP(DBR_ULONG, unsigned int, "%u");
|
||||
OP(DBR_INT64, long long, "%lld");
|
||||
OP(DBR_UINT64, unsigned long long, "%llu");
|
||||
OP(DBR_FLOAT, float, "%e");
|
||||
OP(DBR_DOUBLE, double, "%e");
|
||||
OP(DBR_FLOAT, float, "%g");
|
||||
OP(DBR_DOUBLE, double, "%g");
|
||||
OP(DBR_ENUM, int, "%d");
|
||||
#undef OP
|
||||
}
|
||||
}
|
||||
|
||||
testOk(match, "dbGetField(\"%s\", dbrType=%d, nRequest=%ld ...) match", pv, dbfType, nRequest);
|
||||
testOk(match, "dbGetField(\"%s\", DBR%s, nRequest=%ld ...) match", pv, DBR_NAME(dbfType), nRequest);
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -428,6 +434,17 @@ void testMonitorWait(testMonitor *mon)
|
||||
}
|
||||
}
|
||||
|
||||
static void dummylabor(void* unused) {(void)unused;}
|
||||
|
||||
void testMonitorSync(testMonitor *mon)
|
||||
{
|
||||
// db_flush_extra_labor_event() only blocks if there is actual labor pending
|
||||
(void)db_add_extra_labor_event(testEvtCtx, dummylabor, NULL);
|
||||
(void)db_post_extra_labor(testEvtCtx);
|
||||
db_flush_extra_labor_event(testEvtCtx);
|
||||
(void)db_add_extra_labor_event(testEvtCtx, NULL, NULL);
|
||||
}
|
||||
|
||||
unsigned testMonitorCount(testMonitor *mon, unsigned reset)
|
||||
{
|
||||
unsigned count;
|
||||
|
||||
@@ -139,21 +139,45 @@ DBCORE_API dbCommon* testdbRecordPtr(const char* pv);
|
||||
|
||||
typedef struct testMonitor testMonitor;
|
||||
|
||||
/** Setup monitoring the named PV for changes */
|
||||
/** Setup monitoring the named PV for changes
|
||||
*
|
||||
* @param[in] pvname Requested PV name. Must be valid for dbChannelCreate().
|
||||
* @param[in] dbe_mask A bitwise or of DBE_VALUE and friends.
|
||||
* @param[in] opt Currently unused. Set to zero.
|
||||
* @returns Newly allocated testMonitor object, which caller must testMonitorDestroy()
|
||||
*
|
||||
* Calls testAbort() on failure. Will never return NULL.
|
||||
*
|
||||
* @since 3.16.0.1
|
||||
*/
|
||||
DBCORE_API testMonitor* testMonitorCreate(const char* pvname, unsigned dbe_mask, unsigned opt);
|
||||
/** Stop monitoring */
|
||||
/** Stop monitoring
|
||||
*
|
||||
* @since 3.16.0.1
|
||||
*/
|
||||
DBCORE_API void testMonitorDestroy(testMonitor*);
|
||||
/** Return immediately if it has been updated since create, last wait,
|
||||
* or reset (count w/ reset=1).
|
||||
* Otherwise, block until the value of the target PV is updated.
|
||||
*
|
||||
* @since 3.16.0.1
|
||||
*/
|
||||
DBCORE_API void testMonitorWait(testMonitor*);
|
||||
/** Return the number of monitor events which have occured since create,
|
||||
/** Synchronize with dbEvent working for subscription.
|
||||
*
|
||||
* On return, any updates previously posted for this subscriptions have been delivered.
|
||||
*
|
||||
* @since 7.0.10
|
||||
*/
|
||||
DBCORE_API void testMonitorSync(testMonitor*);
|
||||
/** Return the number of monitor events which have occurred since create,
|
||||
* or a previous reset (called reset=1).
|
||||
* Calling w/ reset=0 only returns the count.
|
||||
* Calling w/ reset=1 resets the count to zero and ensures that the next
|
||||
* wait will block unless subsequent events occur. Returns the previous
|
||||
* count.
|
||||
*
|
||||
* @since 3.16.0.1
|
||||
*/
|
||||
DBCORE_API unsigned testMonitorCount(testMonitor*, unsigned reset);
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ typedef struct dbRecordNode {
|
||||
struct dbRecordNode *aliasedRecnode; /* NULL unless flags|DBRN_FLAGS_ISALIAS */
|
||||
}dbRecordNode;
|
||||
|
||||
/*dbRecordAttribute is for "psuedo" fields */
|
||||
/*dbRecordAttribute is for "pseudo" fields */
|
||||
/*pdbFldDes is so that other access routines work correctly*/
|
||||
/*Until base supports char * value MUST be fixed length string*/
|
||||
typedef struct dbRecordAttribute {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "dbStaticLib.h"
|
||||
#include "dbStaticPvt.h"
|
||||
#include "epicsExport.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "link.h"
|
||||
#include "special.h"
|
||||
#include "iocInit.h"
|
||||
@@ -187,7 +188,7 @@ const char *dbOpenFile(DBBASE *pdbbase,const char *filename,FILE **fp)
|
||||
*fp = fopen(fullfilename, "r");
|
||||
if (*fp && makeDbdDepends)
|
||||
fprintf(stdout, "%s:%s \n", makeDbdDepends, fullfilename);
|
||||
free((void *)fullfilename);
|
||||
free(fullfilename);
|
||||
if (*fp) return pdbPathNode->directory;
|
||||
pdbPathNode = (dbPathNode *)ellNext(&pdbPathNode->node);
|
||||
}
|
||||
@@ -206,7 +207,7 @@ static void freeInputFileList(void)
|
||||
pinputFileNow->filename, strerror(errno));
|
||||
free((void *)pinputFileNow->filename);
|
||||
ellDelete(&inputFileList,(ELLNODE *)pinputFileNow);
|
||||
free((void *)pinputFileNow);
|
||||
free(pinputFileNow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +238,8 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
errlogInit(0); /* Initialize the errSymTable */
|
||||
|
||||
if(*ppdbbase == 0) *ppdbbase = dbAllocBase();
|
||||
savedPdbbase = *ppdbbase;
|
||||
if(path && strlen(path)>0) {
|
||||
@@ -339,11 +342,11 @@ cleanup:
|
||||
}
|
||||
if(macHandle) macDeleteHandle(macHandle);
|
||||
macHandle = NULL;
|
||||
if(mac_input_buffer) free((void *)mac_input_buffer);
|
||||
if(mac_input_buffer) free(mac_input_buffer);
|
||||
mac_input_buffer = NULL;
|
||||
if(freeListPvt) freeListCleanup(freeListPvt);
|
||||
freeListPvt = NULL;
|
||||
if(my_buffer) free((void *)my_buffer);
|
||||
if(my_buffer) free(my_buffer);
|
||||
my_buffer = NULL;
|
||||
freeInputFileList();
|
||||
if(fp)
|
||||
@@ -351,14 +354,18 @@ cleanup:
|
||||
return(status);
|
||||
}
|
||||
|
||||
long dbReadDatabase(DBBASE **ppdbbase,const char *filename,
|
||||
const char *path,const char *substitutions)
|
||||
{return (dbReadCOM(ppdbbase,filename,0,path,substitutions));}
|
||||
long dbReadDatabase(DBBASE **ppdbbase, const char *filename,
|
||||
const char *path, const char *substitutions)
|
||||
{
|
||||
return dbReadCOM(ppdbbase, filename, 0, path, substitutions);
|
||||
}
|
||||
|
||||
long dbReadDatabaseFP(DBBASE **ppdbbase, FILE *fp,
|
||||
const char *path, const char *substitutions)
|
||||
{
|
||||
return dbReadCOM(ppdbbase, 0, fp, path, substitutions);
|
||||
}
|
||||
|
||||
long dbReadDatabaseFP(DBBASE **ppdbbase,FILE *fp,
|
||||
const char *path,const char *substitutions)
|
||||
{return (dbReadCOM(ppdbbase,0,fp,path,substitutions));}
|
||||
|
||||
static int db_yyinput(char *buf, int max_size)
|
||||
{
|
||||
size_t l,n;
|
||||
@@ -389,7 +396,7 @@ static int db_yyinput(char *buf, int max_size)
|
||||
pinputFileNow->filename, strerror(errno));
|
||||
free((void *)pinputFileNow->filename);
|
||||
ellDelete(&inputFileList,(ELLNODE *)pinputFileNow);
|
||||
free((void *)pinputFileNow);
|
||||
free(pinputFileNow);
|
||||
pinputFileNow = (inputFile *)ellLast(&inputFileList);
|
||||
if(!pinputFileNow) return(0);
|
||||
}
|
||||
@@ -445,7 +452,7 @@ static void dbIncludeNew(char *filename)
|
||||
fprintf(stderr, ERL_ERROR ": Can't open include file '%s'\n", filename);
|
||||
yyerror(NULL);
|
||||
free((void *)pinputFile->filename);
|
||||
free((void *)pinputFile);
|
||||
free(pinputFile);
|
||||
return;
|
||||
}
|
||||
pinputFile->fp = fp;
|
||||
@@ -705,7 +712,7 @@ static void dbRecordtypeEmpty(void)
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbRecordType = ptempListNode->item;
|
||||
fprintf(stderr, ERL_ERROR
|
||||
": Declaration of recordtype(%s) preceeded full definition.\n",
|
||||
": Declaration of recordtype(%s) preceded full definition.\n",
|
||||
pdbRecordType->name);
|
||||
yyerrorAbort(NULL);
|
||||
}
|
||||
@@ -1190,6 +1197,37 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
dbVisibleRecord(pdbentry);
|
||||
}
|
||||
|
||||
/* For better suggestions for wrong field names
|
||||
the following array contains pairs of often
|
||||
confused fields. Thus, the number of elements
|
||||
must be even.
|
||||
For the last character, ranges like A-F are
|
||||
allowed as a shortcut. Pairs must have matching
|
||||
range size.
|
||||
If extending this map, please add only field names
|
||||
found in record types from base.
|
||||
Each array element (i.e. both sides of a pair)
|
||||
is tested against the faulty field name.
|
||||
The first match (considering ranges) where the
|
||||
other side of the pair is an existing field name
|
||||
(after adjusting for ranges) will be suggested
|
||||
as a replacement.
|
||||
If no such match is found, the suggestion falls
|
||||
back to weighted lexical similarity with existing
|
||||
field names.
|
||||
*/
|
||||
|
||||
static const char* const dbFieldConfusionMap [] = {
|
||||
"INP","OUT",
|
||||
"DOL","INP",
|
||||
"ZNAM","ZRST",
|
||||
"ONAM","ONST",
|
||||
"INPA-J","DOL0-9",
|
||||
"INPK-P","DOLA-F",
|
||||
"INP0-9","INPA-J"
|
||||
};
|
||||
STATIC_ASSERT(NELEMENTS(dbFieldConfusionMap)%2==0);
|
||||
|
||||
static void dbRecordField(char *name,char *value)
|
||||
{
|
||||
DBENTRY *pdbentry;
|
||||
@@ -1206,18 +1244,140 @@ static void dbRecordField(char *name,char *value)
|
||||
dbGetRecordTypeName(pdbentry), dbGetRecordName(pdbentry), name);
|
||||
if(dbGetRecordName(pdbentry)) {
|
||||
DBENTRY temp;
|
||||
double bestSim = -1.0;
|
||||
const dbFldDes *bestFld = NULL;
|
||||
int i;
|
||||
dbCopyEntryContents(pdbentry, &temp);
|
||||
for(status = dbFirstField(&temp, 0); !status; status = dbNextField(&temp, 0)) {
|
||||
double sim = epicsStrSimilarity(name, temp.pflddes->name);
|
||||
if(!bestFld || sim > bestSim) {
|
||||
bestSim = sim;
|
||||
for(i = 0; i < NELEMENTS(dbFieldConfusionMap); i++) {
|
||||
const char* fieldname = dbFieldConfusionMap[i];
|
||||
const char* replacement = dbFieldConfusionMap[i^1]; /* swap even with odd indices */
|
||||
const char* guess = NULL;
|
||||
char buf[8]; /* no field name is so long */
|
||||
size_t l = strlen(fieldname);
|
||||
if (l >= 3 && fieldname[l-2] == '-' &&
|
||||
strncmp(name, fieldname, l-3) == 0 &&
|
||||
name[l-3] >= fieldname[l-3] &&
|
||||
name[l-3] <= fieldname[l-1])
|
||||
{
|
||||
/* range map (like XXXA-Z) */
|
||||
size_t l2 = strlen(replacement);
|
||||
strncpy(buf, replacement, sizeof(buf)-1);
|
||||
buf[l2-3] += name[l-3] - fieldname[l-3];
|
||||
buf[l2-2] = 0;
|
||||
guess = buf;
|
||||
} else if (strcmp(name, fieldname) == 0) {
|
||||
/* simple map */
|
||||
guess = replacement;
|
||||
}
|
||||
if (guess && dbFindFieldPart(&temp, &guess) == 0) {
|
||||
/* guessed field exists */
|
||||
bestFld = temp.pflddes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bestFld) {
|
||||
/* no map found, use weighted lexical similarity
|
||||
the weights are a bit arbitrary */
|
||||
double bestSim = -1.0;
|
||||
char quote = 0;
|
||||
if (*value == '"' || *value == '\'')
|
||||
quote = *value++;
|
||||
for (status = dbFirstField(&temp, 0); !status; status = dbNextField(&temp, 0)) {
|
||||
if (temp.pflddes->special == SPC_NOMOD ||
|
||||
temp.pflddes->special == SPC_DBADDR) /* cannot be configured */
|
||||
continue;
|
||||
double sim = epicsStrSimilarity(name, temp.pflddes->name);
|
||||
if (!temp.pflddes->promptgroup)
|
||||
sim *= 0.5; /* no prompt: unlikely */
|
||||
if (temp.pflddes->interest)
|
||||
sim *= 1.0 - 0.1 * temp.pflddes->interest; /* 10% less likely per interest level */
|
||||
if (sim == 0)
|
||||
continue;
|
||||
if (*value != quote) {
|
||||
/* value given, check match to field type */
|
||||
long status = 0;
|
||||
char* end = "e;
|
||||
|
||||
switch (temp.pflddes->field_type) {
|
||||
epicsAny dummy;
|
||||
case DBF_CHAR:
|
||||
status = epicsParseInt8(value, &dummy.int8, 0, &end);
|
||||
break;
|
||||
case DBF_UCHAR:
|
||||
status = epicsParseUInt8(value, &dummy.uInt8, 0, &end);
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
status = epicsParseInt16(value, &dummy.int16, 0, &end);
|
||||
break;
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
status = epicsParseUInt16(value, &dummy.uInt16, 0, &end);
|
||||
break;
|
||||
case DBF_LONG:
|
||||
status = epicsParseInt32(value, &dummy.int32, 0, &end);
|
||||
break;
|
||||
case DBF_ULONG:
|
||||
status = epicsParseUInt32(value, &dummy.uInt32, 0, &end);
|
||||
break;
|
||||
case DBF_INT64:
|
||||
status = epicsParseInt64(value, &dummy.int64, 0, &end);
|
||||
break;
|
||||
case DBF_UINT64:
|
||||
status = epicsParseUInt64(value, &dummy.uInt64, 0, &end);
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
status = epicsParseFloat(value, &dummy.float32, &end);
|
||||
break;
|
||||
case DBF_DOUBLE:
|
||||
status = epicsParseDouble(value, &dummy.float64, &end);
|
||||
break;
|
||||
case DBF_MENU:
|
||||
case DBF_DEVICE: {
|
||||
char** choices;
|
||||
int nChoice;
|
||||
int choice;
|
||||
|
||||
if (temp.pflddes->field_type == DBF_MENU) {
|
||||
dbMenu* menu = (dbMenu*)temp.pflddes->ftPvt;
|
||||
choices = menu->papChoiceValue;
|
||||
nChoice = menu->nChoice;
|
||||
} else {
|
||||
dbDeviceMenu* menu = (dbDeviceMenu*)temp.pflddes->ftPvt;
|
||||
choices = menu->papChoice;
|
||||
nChoice = menu->nChoice;
|
||||
}
|
||||
status = epicsParseUInt16(value, &dummy.uInt16, 0, &end);
|
||||
if (!status && *end == quote && dummy.uInt16 < nChoice) {
|
||||
if (temp.pflddes->field_type == DBF_DEVICE)
|
||||
sim *= 0.5; /* numeric device type index is uncommon */
|
||||
break;
|
||||
}
|
||||
for (choice = 0; choice < nChoice; choice++) {
|
||||
size_t len = strlen(choices[choice]);
|
||||
end = value + len;
|
||||
if (strncmp(value, choices[choice], len) == 0 && *end == quote) {
|
||||
sim *= 1.5; /* boost for matching choice string */
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (choice == nChoice)
|
||||
status = S_stdlib_noConversion;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (status || *end != quote)
|
||||
sim *= 0.1; /* value type does not match field type: unlikely */
|
||||
}
|
||||
if (sim > bestSim) {
|
||||
bestSim = sim;
|
||||
bestFld = temp.pflddes;
|
||||
}
|
||||
}
|
||||
}
|
||||
dbFinishEntry(&temp);
|
||||
if(bestSim>0.0) {
|
||||
if (bestFld) {
|
||||
fprintf(stderr, " Did you mean \"%s\"?", bestFld->name);
|
||||
if(bestFld->prompt)
|
||||
fprintf(stderr, " (%s)", bestFld->prompt);
|
||||
|
||||
@@ -50,7 +50,7 @@ static const iocshArg dbDumpMenuArg1 = { "menuName",iocshArgString};
|
||||
static const iocshArg * const dbDumpMenuArgs[] = {
|
||||
&argPdbbase, &dbDumpMenuArg1};
|
||||
static const iocshFuncDef dbDumpMenuFuncDef = {"dbDumpMenu",2,dbDumpMenuArgs,
|
||||
"Dump information about the available menuNames and choices defined withing each menuName.\n"
|
||||
"Dump information about the available menuNames and choices defined within each menuName.\n"
|
||||
"Example: dbDumpMenu pdbbase menuAlarmStat \n"
|
||||
"If last argument(s) are missing, dump all menuNames information in the database.\n"};
|
||||
static void dbDumpMenuCallFunc(const iocshArgBuf *args)
|
||||
|
||||
@@ -109,9 +109,9 @@ void dbFreeLinkContents(struct link *plink)
|
||||
char *parm = NULL;
|
||||
|
||||
switch(plink->type) {
|
||||
case CONSTANT: free((void *)plink->value.constantStr); break;
|
||||
case MACRO_LINK: free((void *)plink->value.macro_link.macroStr); break;
|
||||
case PV_LINK: free((void *)plink->value.pv_link.pvname); break;
|
||||
case CONSTANT: free(plink->value.constantStr); break;
|
||||
case MACRO_LINK: free(plink->value.macro_link.macroStr); break;
|
||||
case PV_LINK: free(plink->value.pv_link.pvname); break;
|
||||
case JSON_LINK:
|
||||
dbJLinkFree(plink->value.json.jlink);
|
||||
parm = plink->value.json.string;
|
||||
@@ -128,7 +128,7 @@ void dbFreeLinkContents(struct link *plink)
|
||||
default:
|
||||
epicsPrintf("dbFreeLink called but link type %d unknown\n", plink->type);
|
||||
}
|
||||
if(parm && (parm != pNullString)) free((void *)parm);
|
||||
if(parm && (parm != pNullString)) free(parm);
|
||||
if(plink->text) free(plink->text);
|
||||
plink->lset = NULL;
|
||||
plink->text = NULL;
|
||||
@@ -145,10 +145,10 @@ void dbFreePath(DBBASE *pdbbase)
|
||||
if(!ppathList) return;
|
||||
while((pdbPathNode = (dbPathNode *)ellFirst(ppathList))) {
|
||||
ellDelete(ppathList,&pdbPathNode->node);
|
||||
free((void *)pdbPathNode->directory);
|
||||
free((void *)pdbPathNode);
|
||||
free(pdbPathNode->directory);
|
||||
free(pdbPathNode);
|
||||
}
|
||||
free((void *)ppathList);
|
||||
free(ppathList);
|
||||
pdbbase->pathPvt = 0;
|
||||
return;
|
||||
}
|
||||
@@ -346,8 +346,8 @@ dbDeviceMenu *dbGetDeviceMenu(DBENTRY *pdbentry)
|
||||
pdbDeviceMenu = (dbDeviceMenu *)pflddes->ftPvt;
|
||||
if(pdbDeviceMenu->nChoice == ellCount(&precordType->devList))
|
||||
return(pdbDeviceMenu);
|
||||
free((void *)pdbDeviceMenu->papChoice);
|
||||
free((void *)pdbDeviceMenu);
|
||||
free(pdbDeviceMenu->papChoice);
|
||||
free(pdbDeviceMenu);
|
||||
pflddes->ftPvt = NULL;
|
||||
}
|
||||
nChoice = ellCount(&precordType->devList);
|
||||
@@ -383,7 +383,7 @@ void dbCatString(char **string,int *stringLength,char *src,char *separator)
|
||||
newString = dbCalloc(size,sizeof(char));
|
||||
if(*string) {
|
||||
strcpy(newString,*string);
|
||||
free((void *)(*string));
|
||||
free(*string);
|
||||
}
|
||||
*string = newString;
|
||||
}
|
||||
@@ -463,35 +463,35 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
while(pdbRecordType) {
|
||||
for(i=0; i<pdbRecordType->no_fields; i++) {
|
||||
pdbFldDes = pdbRecordType->papFldDes[i];
|
||||
free((void *)pdbFldDes->prompt);
|
||||
free((void *)pdbFldDes->name);
|
||||
free((void *)pdbFldDes->extra);
|
||||
free((void *)pdbFldDes->initial);
|
||||
free(pdbFldDes->prompt);
|
||||
free(pdbFldDes->name);
|
||||
free(pdbFldDes->extra);
|
||||
free(pdbFldDes->initial);
|
||||
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
|
||||
dbDeviceMenu *pdbDeviceMenu;
|
||||
|
||||
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
|
||||
free((void *)pdbDeviceMenu->papChoice);
|
||||
free((void *)pdbDeviceMenu);
|
||||
free(pdbDeviceMenu->papChoice);
|
||||
free(pdbDeviceMenu);
|
||||
pdbFldDes->ftPvt=0;
|
||||
}
|
||||
free((void *)pdbFldDes);
|
||||
free(pdbFldDes);
|
||||
}
|
||||
pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||||
while(pdevSup) {
|
||||
pdevSupNext = (devSup *)ellNext(&pdevSup->node);
|
||||
ellDelete(&pdbRecordType->devList,&pdevSup->node);
|
||||
free((void *)pdevSup->name);
|
||||
free((void *)pdevSup->choice);
|
||||
free((void *)pdevSup);
|
||||
free(pdevSup->name);
|
||||
free(pdevSup->choice);
|
||||
free(pdevSup);
|
||||
pdevSup = pdevSupNext;
|
||||
}
|
||||
ptext = (dbText *)ellFirst(&pdbRecordType->cdefList);
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbRecordType->cdefList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
free(ptext->text);
|
||||
free(ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
pAttribute =
|
||||
@@ -499,20 +499,20 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
while(pAttribute) {
|
||||
pAttributeNext = (dbRecordAttribute *)ellNext(&pAttribute->node);
|
||||
ellDelete(&pdbRecordType->attributeList,&pAttribute->node);
|
||||
free((void *)pAttribute->name);
|
||||
free((void *)pAttribute->pdbFldDes);
|
||||
free(pAttribute->name);
|
||||
free(pAttribute->pdbFldDes);
|
||||
free(pAttribute);
|
||||
pAttribute = pAttributeNext;
|
||||
}
|
||||
pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node);
|
||||
gphDelete(pdbbase->pgpHash,pdbRecordType->name,&pdbbase->recordTypeList);
|
||||
ellDelete(&pdbbase->recordTypeList,&pdbRecordType->node);
|
||||
free((void *)pdbRecordType->name);
|
||||
free((void *)pdbRecordType->link_ind);
|
||||
free((void *)pdbRecordType->papsortFldName);
|
||||
free((void *)pdbRecordType->sortFldInd);
|
||||
free((void *)pdbRecordType->papFldDes);
|
||||
free((void *)pdbRecordType);
|
||||
free(pdbRecordType->name);
|
||||
free(pdbRecordType->link_ind);
|
||||
free(pdbRecordType->papsortFldName);
|
||||
free(pdbRecordType->sortFldInd);
|
||||
free(pdbRecordType->papFldDes);
|
||||
free(pdbRecordType);
|
||||
pdbRecordType = pdbRecordTypeNext;
|
||||
}
|
||||
pdbMenu = (dbMenu *)ellFirst(&pdbbase->menuList);
|
||||
@@ -521,21 +521,21 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
gphDelete(pdbbase->pgpHash,pdbMenu->name,&pdbbase->menuList);
|
||||
ellDelete(&pdbbase->menuList,&pdbMenu->node);
|
||||
for(i=0; i< pdbMenu->nChoice; i++) {
|
||||
free((void *)pdbMenu->papChoiceName[i]);
|
||||
free((void *)pdbMenu->papChoiceValue[i]);
|
||||
free(pdbMenu->papChoiceName[i]);
|
||||
free(pdbMenu->papChoiceValue[i]);
|
||||
}
|
||||
free((void *)pdbMenu->papChoiceName);
|
||||
free((void *)pdbMenu->papChoiceValue);
|
||||
free((void *)pdbMenu ->name);
|
||||
free((void *)pdbMenu);
|
||||
free(pdbMenu->papChoiceName);
|
||||
free(pdbMenu->papChoiceValue);
|
||||
free(pdbMenu ->name);
|
||||
free(pdbMenu);
|
||||
pdbMenu = pdbMenuNext;
|
||||
}
|
||||
pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList);
|
||||
while(pdrvSup) {
|
||||
pdrvSupNext = (drvSup *)ellNext(&pdrvSup->node);
|
||||
ellDelete(&pdbbase->drvList,&pdrvSup->node);
|
||||
free((void *)pdrvSup->name);
|
||||
free((void *)pdrvSup);
|
||||
free(pdrvSup->name);
|
||||
free(pdrvSup);
|
||||
pdrvSup = pdrvSupNext;
|
||||
}
|
||||
while ((plinkSup = (linkSup *) ellGet(&pdbbase->linkList))) {
|
||||
@@ -547,25 +547,25 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbbase->registrarList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
free(ptext->text);
|
||||
free(ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
ptext = (dbText *)ellFirst(&pdbbase->functionList);
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbbase->functionList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
free(ptext->text);
|
||||
free(ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
pvar = (dbVariableDef *)ellFirst(&pdbbase->variableList);
|
||||
while(pvar) {
|
||||
pvarNext = (dbVariableDef *)ellNext(&pvar->node);
|
||||
ellDelete(&pdbbase->variableList,&pvar->node);
|
||||
free((void *)pvar->name);
|
||||
free((void *)pvar->type);
|
||||
free((void *)pvar);
|
||||
free(pvar->name);
|
||||
free(pvar->type);
|
||||
free(pvar);
|
||||
pvar = pvarNext;
|
||||
}
|
||||
pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
|
||||
@@ -574,8 +574,8 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
|
||||
ellDelete(&pdbbase->bptList,&pbrkTable->node);
|
||||
free(pbrkTable->name);
|
||||
free((void *)pbrkTable->paBrkInt);
|
||||
free((void *)pbrkTable);
|
||||
free(pbrkTable->paBrkInt);
|
||||
free(pbrkTable);
|
||||
pbrkTable = pbrkTableNext;
|
||||
}
|
||||
pfilt = (chFilterPlugin *)ellFirst(&pdbbase->filterList);
|
||||
@@ -593,13 +593,13 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
gphDelete(pdbbase->pgpHash, pguiGroup->name, &pdbbase->guiGroupList);
|
||||
ellDelete(&pdbbase->guiGroupList, &pguiGroup->node);
|
||||
free(pguiGroup->name);
|
||||
free((void *)pguiGroup);
|
||||
free(pguiGroup);
|
||||
pguiGroup = pguiGroupNext;
|
||||
}
|
||||
gphFreeMem(pdbbase->pgpHash);
|
||||
dbPvdFreeMem(pdbbase);
|
||||
dbFreePath(pdbbase);
|
||||
free((void *)pdbbase);
|
||||
free(pdbbase);
|
||||
pdbbase = NULL;
|
||||
return;
|
||||
}
|
||||
@@ -619,20 +619,20 @@ void dbFreeEntry(DBENTRY *pdbentry)
|
||||
if (!pdbentry)
|
||||
return;
|
||||
if (pdbentry->message)
|
||||
free((void *)pdbentry->message);
|
||||
free(pdbentry->message);
|
||||
dbmfFree(pdbentry);
|
||||
}
|
||||
|
||||
void dbInitEntry(dbBase *pdbbase,DBENTRY *pdbentry)
|
||||
{
|
||||
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
|
||||
memset(pdbentry, '\0', sizeof(DBENTRY));
|
||||
pdbentry->pdbbase = pdbbase;
|
||||
}
|
||||
|
||||
void dbFinishEntry(DBENTRY *pdbentry)
|
||||
{
|
||||
if(pdbentry->message) {
|
||||
free((void *)pdbentry->message);
|
||||
free(pdbentry->message);
|
||||
pdbentry->message = NULL;
|
||||
}
|
||||
}
|
||||
@@ -675,7 +675,7 @@ long dbAddPath(DBBASE *pdbbase,const char *path)
|
||||
if(!ppathList) {
|
||||
ppathList = dbCalloc(1,sizeof(ELLLIST));
|
||||
ellInit(ppathList);
|
||||
pdbbase->pathPvt = (void *)ppathList;
|
||||
pdbbase->pathPvt = ppathList;
|
||||
}
|
||||
if (!path) return(0); /* Empty path strings are ignored */
|
||||
/* care is taken to properly deal with white space
|
||||
@@ -1886,7 +1886,7 @@ char * dbGetString(DBENTRY *pdbentry)
|
||||
switch (pflddes->field_type) {
|
||||
case DBF_STRING:
|
||||
/* Protect against a missing nil-terminator */
|
||||
dbMsgNCpy(pdbentry, (char *)pfield, pflddes->size);
|
||||
dbMsgNCpy(pdbentry, pfield, pflddes->size);
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
case DBF_UCHAR:
|
||||
@@ -2212,7 +2212,7 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec)
|
||||
if(!plink->text)
|
||||
continue;
|
||||
|
||||
if(dbParseLink(plink->text, pflddes->field_type, &link_info)!=0) {
|
||||
if(dbParseLink(plink->text, pflddes->field_type, &link_info, prec->name, pflddes->name)!=0) {
|
||||
/* This was already parsed once when ->text was set.
|
||||
* Any syntax error messages were printed at that time.
|
||||
*/
|
||||
@@ -2241,7 +2241,7 @@ void dbFreeLinkInfo(dbLinkInfo *pinfo)
|
||||
pinfo->target = NULL;
|
||||
}
|
||||
|
||||
long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo)
|
||||
long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, const char *recname, const char *fieldname)
|
||||
{
|
||||
char *pstr;
|
||||
size_t len;
|
||||
@@ -2378,7 +2378,13 @@ long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo)
|
||||
/* filter modifiers based on link type */
|
||||
switch(ftype) {
|
||||
case DBF_INLINK: /* accept all */ break;
|
||||
case DBF_OUTLINK: pinfo->modifiers &= ~pvlOptCPP; break;
|
||||
case DBF_OUTLINK:
|
||||
if(pinfo->modifiers & (pvlOptCPP|pvlOptCP)){
|
||||
errlogPrintf(ERL_WARNING ": Discarding CP/CPP modifier in CA output link from %s.%s to %s.\n",
|
||||
recname, fieldname, pinfo->target);
|
||||
}
|
||||
pinfo->modifiers &= ~(pvlOptCPP|pvlOptCP);
|
||||
break;
|
||||
case DBF_FWDLINK: pinfo->modifiers &= pvlOptCA; break;
|
||||
}
|
||||
}
|
||||
@@ -2579,7 +2585,7 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring)
|
||||
case DBF_STRING:
|
||||
if(!pfield) return(S_dbLib_fieldNotFound);
|
||||
if(strlen(pstring) >= (size_t)pflddes->size) return S_dbLib_strLen;
|
||||
strncpy((char *)pfield, pstring, pflddes->size-1);
|
||||
strncpy(pfield, pstring, pflddes->size-1);
|
||||
((char *)pfield)[pflddes->size-1] = 0;
|
||||
|
||||
if((pflddes->special == SPC_CALC) && !stringHasMacro) {
|
||||
@@ -2616,7 +2622,7 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring)
|
||||
dbLinkInfo link_info;
|
||||
DBLINK *plink = (DBLINK *)pfield;
|
||||
|
||||
status = dbParseLink(pstring, pflddes->field_type, &link_info);
|
||||
status = dbParseLink(pstring, pflddes->field_type, &link_info, dbGetRecordName(pdbentry), dbGetFieldName(pdbentry));
|
||||
if (status) break;
|
||||
|
||||
if (plink->type==CONSTANT && plink->value.constantStr==NULL) {
|
||||
@@ -3045,7 +3051,7 @@ brkTable * dbFindBrkTable(dbBase *pdbbase,const char *name)
|
||||
{
|
||||
GPHENTRY *pgph;
|
||||
|
||||
pgph = gphFind(pdbbase->pgpHash,name,(void *)&pdbbase->bptList);
|
||||
pgph = gphFind(pdbbase->pgpHash, name, &pdbbase->bptList);
|
||||
if(!pgph) return(NULL);
|
||||
return((brkTable *)pgph->userPvt);
|
||||
}
|
||||
@@ -3078,7 +3084,7 @@ dbMenu * dbFindMenu(dbBase *pdbbase,const char *name)
|
||||
{
|
||||
GPHENTRY *pgph;
|
||||
|
||||
pgph = gphFind(pdbbase->pgpHash,name,(void *)&pdbbase->menuList);
|
||||
pgph = gphFind(pdbbase->pgpHash, name, &pdbbase->menuList);
|
||||
if(!pgph) return(NULL);
|
||||
return((dbMenu *)pgph->userPvt);
|
||||
}
|
||||
@@ -3330,7 +3336,7 @@ void dbDumpRecordType(DBBASE *pdbbase,const char *recordTypeName)
|
||||
printf("indvalFlddes %d name %s\n",pdbRecordType->indvalFlddes,
|
||||
pdbRecordType->pvalFldDes->name);
|
||||
printf("rset * %p rec_size %d\n",
|
||||
(void *)pdbRecordType->prset,pdbRecordType->rec_size);
|
||||
pdbRecordType->prset,pdbRecordType->rec_size);
|
||||
if(recordTypeName) break;
|
||||
}
|
||||
}
|
||||
@@ -3447,7 +3453,7 @@ void dbDumpDevice(DBBASE *pdbbase,const char *recordTypeName)
|
||||
printf(" device name: %s\n",pdevSup->name);
|
||||
printf("\tchoice: %s\n",pdevSup->choice);
|
||||
printf("\tlink_type: %d\n",pdevSup->link_type);
|
||||
printf("\tpdset: %p\n",(void *)pdevSup->pdset);
|
||||
printf("\tpdset: %p\n",pdevSup->pdset);
|
||||
if (pdevSup->pdset) {
|
||||
static const char *names[] = {
|
||||
" - report()",
|
||||
@@ -3462,15 +3468,15 @@ void dbDumpDevice(DBBASE *pdbbase,const char *recordTypeName)
|
||||
for (i = 0; i < n; ++i, ++pfunc) {
|
||||
const char *name = (i < NELEMENTS(names)) ? names[i] : "";
|
||||
|
||||
printf("\t func %d: %p%s\n", i, (void *)*pfunc, name);
|
||||
printf("\t func %d: %p%s\n", i, *pfunc, name);
|
||||
}
|
||||
}
|
||||
printf("\tpdsxt: %p\n",(void *)pdevSup->pdsxt);
|
||||
printf("\tpdsxt: %p\n", pdevSup->pdsxt);
|
||||
if (pdevSup->pdsxt) {
|
||||
printf("\t add_record: %p\n",
|
||||
(void *)pdevSup->pdsxt->add_record);
|
||||
pdevSup->pdsxt->add_record);
|
||||
printf("\t del_record: %p\n",
|
||||
(void *)pdevSup->pdsxt->del_record);
|
||||
pdevSup->pdsxt->del_record);
|
||||
}
|
||||
}
|
||||
if(recordTypeName) break;
|
||||
@@ -3600,7 +3606,7 @@ void dbReportDeviceConfig(dbBase *pdbbase, FILE *report)
|
||||
if (plink->text) { /* Not yet parsed */
|
||||
dbLinkInfo linfo;
|
||||
|
||||
if (dbParseLink(plink->text, pdbentry->pflddes->field_type, &linfo))
|
||||
if (dbParseLink(plink->text, pdbentry->pflddes->field_type, &linfo, dbGetRecordName(pdbentry), dbGetFieldName(pdbentry)))
|
||||
continue;
|
||||
|
||||
linkType = linfo.ltype;
|
||||
|
||||
@@ -74,7 +74,7 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec);
|
||||
/* Parse link string. no record locks needed.
|
||||
* on success caller must free pinfo->target
|
||||
*/
|
||||
DBCORE_API long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo);
|
||||
DBCORE_API long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, const char *recordname, const char *fieldname);
|
||||
/* Check if link type allow the parsed link value pinfo
|
||||
* to be assigned to the given link.
|
||||
* Record containing plink must be locked.
|
||||
|
||||
@@ -122,7 +122,7 @@ long dbAllocRecord(DBENTRY *pdbentry,const char *precordName)
|
||||
pflddes = pdbRecordType->papFldDes[i];
|
||||
if(!pflddes) continue;
|
||||
pfield = (char*)precord + pflddes->offset;
|
||||
pdbentry->pfield = (void *)pfield;
|
||||
pdbentry->pfield = pfield;
|
||||
pdbentry->pflddes = pflddes;
|
||||
pdbentry->indfield = i;
|
||||
switch(pflddes->field_type) {
|
||||
|
||||
@@ -26,7 +26,7 @@ static const iocshFuncDef dbLoadTemplateFuncDef = {
|
||||
"for each template in the substitution file, and load them using 'dbLoadRecords'.\n\n"
|
||||
"The second argument provides extra variables to substitute in the\n"
|
||||
"template files (not the substitution file). The third argument provides\n"
|
||||
"a list of paths to search through for the subsitution and template files.\n\n"
|
||||
"a list of paths to search through for the substitution and template files.\n\n"
|
||||
"See 'help dbLoadRecords' for more information.\n\n"
|
||||
"Example: dbLoadTemplate db/my.substitutions 'user=myself,host=myhost' 'path/to/subst:path2/to2/subst2'\n",
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ discouraged.
|
||||
:::
|
||||
|
||||
::: {option} -o <file>
|
||||
Output will be written to the specifed \<file\> rather than to the
|
||||
Output will be written to the specified \<file\> rather than to the
|
||||
standard output.
|
||||
:::
|
||||
|
||||
@@ -166,7 +166,7 @@ expanded properly.
|
||||
However neither back-slash characters nor quotes of either variety are
|
||||
removed when generating the output file, so depending on what is being
|
||||
output the single quote behaviour may not be useful and may even be a
|
||||
hinderance. It cannot be disabled in the current version of msi.
|
||||
hindrance. It cannot be disabled in the current version of msi.
|
||||
|
||||
|
||||
### Template file commands
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "epicsPrint.h"
|
||||
#include "epicsSignal.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsString.h"
|
||||
#include "errMdef.h"
|
||||
#include "iocsh.h"
|
||||
#include "taskwd.h"
|
||||
@@ -132,10 +133,10 @@ static int iocBuild_1(void)
|
||||
}
|
||||
|
||||
{
|
||||
/* fall back to "old" decimal-only conversion if EPICS_DB_CONVERT_DECIMAL_ONLY
|
||||
is set and does not look like meaning no/false/0 */
|
||||
/* fall back to "old" decimal-only conversion if
|
||||
EPICS_DB_CONVERT_DECIMAL_ONLY is YES (case insensitive). */
|
||||
const char* dec_only = getenv("EPICS_DB_CONVERT_DECIMAL_ONLY");
|
||||
if (dec_only && *dec_only && !strchr("nNfF0", *dec_only)) {
|
||||
if (dec_only && epicsStrCaseCmp(dec_only, "YES") == 0) {
|
||||
dbConvertBase = 10;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,14 @@
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#if defined(vxWorks) && \
|
||||
(_WRS_VXWORKS_MAJOR+0 <= 6) && (_WRS_VXWORKS_MINOR+0 < 9)
|
||||
typedef int intptr_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ static const iocshFuncDef registryRecordTypeFindFuncDef = {
|
||||
"Example: registryRecordTypeFind ai\n",
|
||||
};
|
||||
static void registryRecordTypeFindCallFunc(const iocshArgBuf *args) {
|
||||
printf("%p\n", (void*) registryRecordTypeFind(args[0].sval));
|
||||
printf("%p\n", registryRecordTypeFind(args[0].sval));
|
||||
}
|
||||
|
||||
/* registryDeviceSupportFind */
|
||||
@@ -40,7 +40,7 @@ static const iocshFuncDef registryDeviceSupportFindFuncDef = {
|
||||
"Example: registryDeviceSupportFind devAaiSoft\n",
|
||||
};
|
||||
static void registryDeviceSupportFindCallFunc(const iocshArgBuf *args) {
|
||||
printf("%p\n", (void*) registryDeviceSupportFind(args[0].sval));
|
||||
printf("%p\n", registryDeviceSupportFind(args[0].sval));
|
||||
}
|
||||
|
||||
/* registryDriverSupportFind */
|
||||
@@ -52,7 +52,7 @@ static const iocshFuncDef registryDriverSupportFindFuncDef = {
|
||||
"Example: registryDriverSupportFind stream\n",
|
||||
};
|
||||
static void registryDriverSupportFindCallFunc(const iocshArgBuf *args) {
|
||||
printf("%p\n", (void*) registryDriverSupportFind(args[0].sval));
|
||||
printf("%p\n", registryDriverSupportFind(args[0].sval));
|
||||
}
|
||||
|
||||
/* registryFunctionFind */
|
||||
@@ -64,7 +64,7 @@ static const iocshFuncDef registryFunctionFindFuncDef = {
|
||||
"Example: registryFunctionFind registryFunctionFind\n",
|
||||
};
|
||||
static void registryFunctionFindCallFunc(const iocshArgBuf *args) {
|
||||
printf("%p\n", (void*) registryFunctionFind(args[0].sval));
|
||||
printf("%p\n", registryFunctionFind(args[0].sval));
|
||||
}
|
||||
|
||||
void registryIocRegister(void)
|
||||
|
||||
@@ -326,7 +326,7 @@ static void log_header (
|
||||
mp->m_cid, mp->m_dataType, mp->m_count, mp->m_postsize, client->minor_version_number);
|
||||
|
||||
epicsPrintf ( "CAS: Request from %s => available=0x%x \tN=%u paddr=%p\n",
|
||||
hostName, mp->m_available, mnum, (pciu ? (void *)&pciu->dbch : NULL));
|
||||
hostName, mp->m_available, mnum, (pciu ? &pciu->dbch : NULL));
|
||||
|
||||
if (mp->m_cmmd==CA_PROTO_WRITE && mp->m_dataType==DBF_STRING && pPayLoad ) {
|
||||
epicsPrintf ( "CAS: Request from %s => Wrote string \"%s\"\n",
|
||||
@@ -1500,7 +1500,7 @@ static void sendAllUpdateAS ( struct client *client )
|
||||
}
|
||||
else {
|
||||
errlogPrintf (
|
||||
"%s at %d: corrupt channel state detected durring AR update\n",
|
||||
"%s at %d: corrupt channel state detected during AR update\n",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
pciu->state = rsrvCS_inService;
|
||||
@@ -1541,7 +1541,7 @@ static void putNotifyErrorReply ( struct client *client, caHdrLargeArray *mp, in
|
||||
mp->m_available, 0 );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
SEND_UNLOCK ( client );
|
||||
errlogPrintf ("%s at %d: should always get sufficent space for put notify error reply\n",
|
||||
errlogPrintf ("%s at %d: should always get sufficient space for put notify error reply\n",
|
||||
__FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
@@ -1883,7 +1883,7 @@ static int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client
|
||||
* the monitors and I could get deadlocked.
|
||||
* The client is blocked sending and the server
|
||||
* task for the client is blocked sending in
|
||||
* this case. I cant check the recv part of the
|
||||
* this case. I can't check the recv part of the
|
||||
* socket in the client since I am still handling an
|
||||
* outstanding recv ( they must be processed in order).
|
||||
* I handle this problem in the server by using
|
||||
@@ -2128,7 +2128,7 @@ static void search_fail_reply ( caHdrLargeArray *mp, void *pPayload, struct clie
|
||||
0u, mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, NULL );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
SEND_UNLOCK ( client );
|
||||
errlogPrintf ( "%s at %d: should always get sufficent space for search fail reply?\n",
|
||||
errlogPrintf ( "%s at %d: should always get sufficient space for search fail reply?\n",
|
||||
__FILE__, __LINE__ );
|
||||
return;
|
||||
}
|
||||
@@ -2472,11 +2472,11 @@ int camessage ( struct client *client )
|
||||
msg.m_postsize = ntohl ( pLW[0] );
|
||||
msg.m_count = ntohl ( pLW[1] );
|
||||
msgsize = msg.m_postsize + sizeof(*mp) + 2 * sizeof ( *pLW );
|
||||
pBody = ( void * ) ( pLW + 2 );
|
||||
pBody = pLW + 2;
|
||||
}
|
||||
else {
|
||||
msgsize = msg.m_postsize + sizeof(*mp);
|
||||
pBody = ( void * ) ( mp + 1 );
|
||||
pBody = mp + 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -303,7 +303,7 @@ int cas_copy_in_header (
|
||||
pMsg->m_postsize = htons(((ca_uint16_t) alignedPayloadSize));
|
||||
pMsg->m_count = htons(((ca_uint16_t) nElem));
|
||||
if (ppPayload)
|
||||
*ppPayload = (void *) (pMsg + 1);
|
||||
*ppPayload = pMsg + 1;
|
||||
}
|
||||
else {
|
||||
ca_uint32_t *pW32 = (ca_uint32_t *) (pMsg + 1);
|
||||
@@ -312,7 +312,7 @@ int cas_copy_in_header (
|
||||
pW32[0] = htonl(alignedPayloadSize);
|
||||
pW32[1] = htonl(nElem);
|
||||
if (ppPayload)
|
||||
*ppPayload = (void *) (pW32 + 2);
|
||||
*ppPayload = pW32 + 2;
|
||||
}
|
||||
|
||||
/* zero out pad bytes */
|
||||
@@ -367,7 +367,7 @@ void cas_commit_msg ( struct client *pClient, ca_uint32_t size )
|
||||
|
||||
/*
|
||||
* this assumes that we have already checked to see
|
||||
* if sufficent bytes are available
|
||||
* if sufficient bytes are available
|
||||
*/
|
||||
ca_uint16_t rsrvGetUInt16 ( struct message_buffer *recv )
|
||||
{
|
||||
@@ -375,7 +375,7 @@ ca_uint16_t rsrvGetUInt16 ( struct message_buffer *recv )
|
||||
ca_uint16_t result;
|
||||
/*
|
||||
* this assumes that we have already checked to see
|
||||
* if sufficent bytes are available
|
||||
* if sufficient bytes are available
|
||||
*/
|
||||
assert ( recv->cnt - recv->stk >= 2u );
|
||||
result = pBuf[recv->stk++] << 8u;
|
||||
@@ -385,7 +385,7 @@ ca_uint16_t rsrvGetUInt16 ( struct message_buffer *recv )
|
||||
|
||||
/*
|
||||
* this assumes that we have already checked to see
|
||||
* if sufficent bytes are available
|
||||
* if sufficient bytes are available
|
||||
*/
|
||||
ca_uint32_t rsrvGetUInt32 ( struct message_buffer *recv )
|
||||
{
|
||||
@@ -393,7 +393,7 @@ ca_uint32_t rsrvGetUInt32 ( struct message_buffer *recv )
|
||||
ca_uint32_t result;
|
||||
/*
|
||||
* this assumes that we have already checked to see
|
||||
* if sufficent bytes are available
|
||||
* if sufficient bytes are available
|
||||
*/
|
||||
assert ( recv->cnt - recv->stk >= 4u );
|
||||
result = pBuf[recv->stk++] << 24u;
|
||||
|
||||
@@ -860,7 +860,7 @@ static void log_one_client (struct client *client, unsigned level)
|
||||
recv_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_recv);
|
||||
|
||||
printf ("\tTask Id = %p, Socket FD = %d\n",
|
||||
(void *) client->tid, (int)client->sock);
|
||||
client->tid, (int)client->sock);
|
||||
printf(
|
||||
"\t%.2f secs since last send, %.2f secs since last receive\n",
|
||||
send_delay, recv_delay);
|
||||
@@ -1276,7 +1276,7 @@ struct client * create_client ( SOCKET sock, int proto )
|
||||
ellInit ( & client->chanList );
|
||||
ellInit ( & client->chanPendingUpdateARList );
|
||||
ellInit ( & client->putNotifyQue );
|
||||
memset ( (char *)&client->addr, 0, sizeof (client->addr) );
|
||||
memset ( &client->addr, 0, sizeof (client->addr) );
|
||||
client->tid = 0;
|
||||
|
||||
if ( proto == IPPROTO_TCP ) {
|
||||
|
||||
@@ -66,7 +66,7 @@ void rsrv_online_notify_task(void *pParm)
|
||||
delay = 0.02; /* initial beacon period in sec */
|
||||
maxdelay = maxPeriod;
|
||||
|
||||
memset((char *)&msg, 0, sizeof msg);
|
||||
memset(&msg, 0, sizeof msg);
|
||||
msg.m_cmmd = htons (CA_PROTO_RSRV_IS_UP);
|
||||
msg.m_count = htons (ca_server_port);
|
||||
msg.m_dataType = htons (CA_MINOR_PROTOCOL_REVISION);
|
||||
|
||||
@@ -14,9 +14,9 @@ documentation is now being published.
|
||||
|
||||
=over
|
||||
|
||||
=item * L<Introduction to EPICS|https://docs.epics-controls.org/en/latest/guides/EPICS_Intro.html>
|
||||
=item * L<Introduction to EPICS|https://docs.epics-controls.org/en/latest/getting-started/EPICS_Intro.html>
|
||||
|
||||
=item * L<Process Database Concepts|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html>
|
||||
=item * L<Process Database Concepts|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html>
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ long asSubInit(subRecord *precord,void *process)
|
||||
|
||||
pcallback = (ASDBCALLBACK *)callocMustSucceed(
|
||||
1,sizeof(ASDBCALLBACK),"asSubInit");
|
||||
precord->dpvt = (void *)pcallback;
|
||||
precord->dpvt = pcallback;
|
||||
callbackSetCallback(myCallback,&pcallback->callback);
|
||||
callbackSetUser(precord,&pcallback->callback);
|
||||
return(0);
|
||||
|
||||
@@ -87,7 +87,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (plink->type != PV_LINK) {
|
||||
long status = S_db_badField;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devAiSoftCallback (add_record) Illegal INP field");
|
||||
return status;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!chan) {
|
||||
long status = S_db_notFound;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devAiSoftCallback (add_record) link target not found");
|
||||
return status;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!pdevPvt) {
|
||||
long status = S_db_noMemory;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devAiSoftCallback (add_record) out of memory, calloc() failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ static long add_record (struct dbCommon *pdbc)
|
||||
biRecord *prec = (biRecord *) pdbc;
|
||||
|
||||
if (INST_IO != prec->inp.type) {
|
||||
recGblRecordError(S_db_badField, (void *) prec, DEVSUPNAME ": Illegal INP field");
|
||||
recGblRecordError(S_db_badField, prec, DEVSUPNAME ": Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (plink->type != PV_LINK) {
|
||||
long status = S_db_badField;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devBiSoftCallback (add_record) Illegal INP field");
|
||||
return status;
|
||||
}
|
||||
@@ -94,7 +94,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!chan) {
|
||||
long status = S_db_notFound;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devBiSoftCallback (add_record) link target not found");
|
||||
return status;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!pdevPvt) {
|
||||
long status = S_db_noMemory;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devBiSoftCallback (add_record) out of memory, calloc() failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ static long add_record (struct dbCommon *pdbc)
|
||||
boRecord *prec = (boRecord *) pdbc;
|
||||
|
||||
if (INST_IO != prec->out.type) {
|
||||
recGblRecordError(S_db_badField, (void *) prec, DEVSUPNAME ": Illegal OUT field");
|
||||
recGblRecordError(S_db_badField, prec, DEVSUPNAME ": Illegal OUT field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ static long init_ai(dbCommon *pcommon)
|
||||
int i;
|
||||
|
||||
if (prec->inp.type != INST_IO) {
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"devAiGeneralTime::init_ai: Illegal INP field");
|
||||
prec->pact = TRUE;
|
||||
return S_db_badField;
|
||||
@@ -71,7 +71,7 @@ static long init_ai(dbCommon *pcommon)
|
||||
}
|
||||
}
|
||||
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"devAiGeneralTime::init_ai: Bad parm");
|
||||
prec->pact = TRUE;
|
||||
prec->dpvt = NULL;
|
||||
@@ -119,7 +119,7 @@ static long init_bo(dbCommon *pcommon)
|
||||
int i;
|
||||
|
||||
if (prec->out.type != INST_IO) {
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"devAiGeneralTime::init_ai: Illegal INP field");
|
||||
prec->pact = TRUE;
|
||||
return S_db_badField;
|
||||
@@ -134,7 +134,7 @@ static long init_bo(dbCommon *pcommon)
|
||||
}
|
||||
}
|
||||
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"devBoGeneralTime::init_bo: Bad parm");
|
||||
prec->pact = TRUE;
|
||||
prec->dpvt = NULL;
|
||||
@@ -178,7 +178,7 @@ static long init_li(dbCommon *pcommon)
|
||||
int i;
|
||||
|
||||
if (prec->inp.type != INST_IO) {
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"devLiGeneralTime::init_li: Illegal INP field");
|
||||
prec->pact = TRUE;
|
||||
return S_db_badField;
|
||||
@@ -192,7 +192,7 @@ static long init_li(dbCommon *pcommon)
|
||||
}
|
||||
}
|
||||
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"devLiGeneralTime::init_li: Bad parm");
|
||||
prec->pact = TRUE;
|
||||
prec->dpvt = NULL;
|
||||
@@ -247,7 +247,7 @@ static long init_si(dbCommon *pcommon)
|
||||
int i;
|
||||
|
||||
if (prec->inp.type != INST_IO) {
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"devSiGeneralTime::init_si: Illegal INP field");
|
||||
prec->pact = TRUE;
|
||||
return S_db_badField;
|
||||
@@ -261,7 +261,7 @@ static long init_si(dbCommon *pcommon)
|
||||
}
|
||||
}
|
||||
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"devSiGeneralTime::init_si: Bad parm");
|
||||
prec->pact = TRUE;
|
||||
prec->dpvt = NULL;
|
||||
|
||||
@@ -85,7 +85,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (plink->type != PV_LINK) {
|
||||
long status = S_db_badField;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devI64inSoftCallback (add_record) Illegal INP field");
|
||||
return status;
|
||||
}
|
||||
@@ -94,7 +94,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!chan) {
|
||||
long status = S_db_notFound;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devI64inSoftCallback (init_record) linked record not found");
|
||||
return status;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!pdevPvt) {
|
||||
long status = S_db_noMemory;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devI64inSoftCallback (add_record) out of memory, calloc() failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (plink->type != PV_LINK) {
|
||||
long status = S_db_badField;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devLiSoftCallback (add_record) Illegal INP field");
|
||||
return status;
|
||||
}
|
||||
@@ -94,7 +94,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!chan) {
|
||||
long status = S_db_notFound;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devLiSoftCallback (init_record) linked record not found");
|
||||
return status;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!pdevPvt) {
|
||||
long status = S_db_noMemory;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devLiSoftCallback (add_record) out of memory, calloc() failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (plink->type != PV_LINK) {
|
||||
long status = S_db_badField;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devMbbiDirectSoftCallback (add_record) Illegal INP field");
|
||||
return status;
|
||||
}
|
||||
@@ -94,7 +94,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!chan) {
|
||||
long status = S_db_notFound;
|
||||
|
||||
recGblRecordError(status,(void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devMbbiDirectSoftCallback (add_record) linked record not found");
|
||||
return status;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!pdevPvt) {
|
||||
long status = S_db_noMemory;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devMbbiDirectSoftCallback (add_record) out of memory, calloc() failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (plink->type != PV_LINK) {
|
||||
long status = S_db_badField;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devMbbiSoftCallback (add_record) Illegal INP field");
|
||||
return status;
|
||||
}
|
||||
@@ -94,7 +94,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!chan) {
|
||||
long status = S_db_notFound;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devMbbiSoftCallback (add_record) linked record not found");
|
||||
return status;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!pdevPvt) {
|
||||
long status = S_db_noMemory;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devMbbiSoftCallback (add_record) out of memory, calloc() failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (plink->type != PV_LINK) {
|
||||
long status = S_db_badField;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devSiSoftCallback (add_record) Illegal INP field");
|
||||
return status;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!pdevPvt) {
|
||||
long status = S_db_noMemory;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devSiSoftCallback (add_record) out of memory, calloc() failed");
|
||||
return status;
|
||||
}
|
||||
@@ -106,7 +106,7 @@ static long add_record(dbCommon *pcommon)
|
||||
if (!chan) {
|
||||
long status = S_db_notFound;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
recGblRecordError(status, prec,
|
||||
"devSiSoftCallback (add_record) linked record not found");
|
||||
free(pdevPvt);
|
||||
return status;
|
||||
|
||||
@@ -48,7 +48,7 @@ static void * allocPvt(void)
|
||||
my->start = 0;
|
||||
my->incr = 1;
|
||||
my->end = -1;
|
||||
return (void *) my;
|
||||
return my;
|
||||
}
|
||||
|
||||
static void freePvt(void *pvt)
|
||||
|
||||
@@ -77,9 +77,9 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) {
|
||||
localAddr.field_type = pfl->field_type;
|
||||
localAddr.field_size = pfl->field_size;
|
||||
localAddr.no_elements = pfl->no_elements;
|
||||
localAddr.pfield = (char *) &pfl->u.v.field;
|
||||
localAddr.pfield = &pfl->u.v.field;
|
||||
status = dbFastGetConvertRoutine[pfl->field_type][DBR_DOUBLE]
|
||||
(localAddr.pfield, (void*) &val, &localAddr);
|
||||
(localAddr.pfield, &val, &localAddr);
|
||||
if (!status) {
|
||||
send = pfl->mask & ~(DBE_VALUE|DBE_LOG);
|
||||
recGblCheckDeadband(&my->last, val, my->hyst, &send, pfl->mask & (DBE_VALUE|DBE_LOG));
|
||||
|
||||
@@ -38,7 +38,7 @@ chfPluginArgDef opts[] = {
|
||||
static void * allocPvt(void)
|
||||
{
|
||||
myStruct *my = (myStruct*) freeListCalloc(myStructFreeList);
|
||||
return (void *) my;
|
||||
return my;
|
||||
}
|
||||
|
||||
static void freePvt(void *pvt)
|
||||
|
||||
@@ -70,7 +70,7 @@ chfPluginArgDef opts[] = {
|
||||
static void * allocPvt(void)
|
||||
{
|
||||
myStruct *my = (myStruct*) freeListCalloc(myStructFreeList);
|
||||
return (void *) my;
|
||||
return my;
|
||||
}
|
||||
|
||||
static void freePvt(void *pvt)
|
||||
|
||||
@@ -40,7 +40,7 @@ link(const, lnkConstIf)
|
||||
|
||||
=head3 Constant Link C<"const">
|
||||
|
||||
Constant links are input links that provide literal values at link initalization
|
||||
Constant links are input links that provide literal values at link initialization
|
||||
time, but do not return any data when their C<getValue()> routine is called.
|
||||
Most record types support the use of constant links on their input links by
|
||||
calling C<recGblInitConstantLink()> at record initialization, which results in
|
||||
@@ -86,6 +86,8 @@ input links, and returns a double-precision floating-point result. The
|
||||
expression is evaluated by the EPICS Calc engine, and the result is returned as
|
||||
the value of the link.
|
||||
|
||||
Since 7.0.10 the number of inputs has been increased from 12 to 21.
|
||||
|
||||
Two additional expressions may also be provided and are evaluated to determine
|
||||
whether the record owning the link should be placed in alarm state. In both
|
||||
cases the result of the main calculation is available to these expressions as
|
||||
@@ -126,9 +128,11 @@ An optional expression that returns non-zero to raise a minor alarm.
|
||||
|
||||
=item args
|
||||
|
||||
A JSON list of up to 12 input arguments for the expression, which are assigned
|
||||
A JSON list of up to 24 input arguments for the expression, which are assigned
|
||||
to the inputs C<A>, C<B>, C<C>, ... C<U>. Each input argument may be either a
|
||||
numeric literal or an embedded JSON link inside C<{}> braces. The same input
|
||||
numeric literal or an embedded JSON link inside C<{}> braces. A C<pva> link
|
||||
could provide values from another record in this or other IOCs if built in, but
|
||||
the built-in non-JSON CA or DB link types are not supported. The same input
|
||||
values are provided to the two alarm expressions as to the primary expression.
|
||||
|
||||
=item out
|
||||
|
||||
@@ -563,7 +563,7 @@ static long special(DBADDR *paddr, int after)
|
||||
pfunc = (GENFUNCPTR)registryFunctionFind(prec->snam);
|
||||
if (!pfunc) {
|
||||
status = S_db_BadSub;
|
||||
recGblRecordError(status, (void *)prec, prec->snam);
|
||||
recGblRecordError(status, prec, prec->snam);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ Except when it doesn't.
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
|
||||
=head3 Output Event Flag
|
||||
@@ -338,7 +338,7 @@ during record processing.
|
||||
|
||||
=head3 Input Value Fields
|
||||
|
||||
Thse fields hold the scalar or array values fetched through the input links
|
||||
These fields hold the scalar or array values fetched through the input links
|
||||
INPA,...,INPU.
|
||||
|
||||
=fields A - U
|
||||
@@ -353,7 +353,7 @@ INPA,...,INPU.
|
||||
extra("void *a")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTA
|
||||
#=type Set by FTA[NOA]
|
||||
}
|
||||
field(B,DBF_NOACCESS) {
|
||||
prompt("Input value B")
|
||||
@@ -363,7 +363,7 @@ INPA,...,INPU.
|
||||
extra("void *b")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTB
|
||||
#=type Set by FTB[NOB]
|
||||
}
|
||||
field(C,DBF_NOACCESS) {
|
||||
prompt("Input value C")
|
||||
@@ -373,7 +373,7 @@ INPA,...,INPU.
|
||||
extra("void *c")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTC
|
||||
#=type Set by FTC[NOC]
|
||||
}
|
||||
field(D,DBF_NOACCESS) {
|
||||
prompt("Input value D")
|
||||
@@ -383,7 +383,7 @@ INPA,...,INPU.
|
||||
extra("void *d")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTD
|
||||
#=type Set by FTD[NOD]
|
||||
}
|
||||
field(E,DBF_NOACCESS) {
|
||||
prompt("Input value E")
|
||||
@@ -393,7 +393,7 @@ INPA,...,INPU.
|
||||
extra("void *e")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTE
|
||||
#=type Set by FTE[NOE]
|
||||
}
|
||||
field(F,DBF_NOACCESS) {
|
||||
prompt("Input value F")
|
||||
@@ -403,7 +403,7 @@ INPA,...,INPU.
|
||||
extra("void *f")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTF
|
||||
#=type Set by FTF[NOF]
|
||||
}
|
||||
field(G,DBF_NOACCESS) {
|
||||
prompt("Input value G")
|
||||
@@ -413,7 +413,7 @@ INPA,...,INPU.
|
||||
extra("void *g")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTG
|
||||
#=type Set by FTG[NOG]
|
||||
}
|
||||
field(H,DBF_NOACCESS) {
|
||||
prompt("Input value H")
|
||||
@@ -423,7 +423,7 @@ INPA,...,INPU.
|
||||
extra("void *h")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTH
|
||||
#=type Set by FTH[NOH]
|
||||
}
|
||||
field(I,DBF_NOACCESS) {
|
||||
prompt("Input value I")
|
||||
@@ -433,7 +433,7 @@ INPA,...,INPU.
|
||||
extra("void *i")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTI
|
||||
#=type Set by FTI[NOI]
|
||||
}
|
||||
field(J,DBF_NOACCESS) {
|
||||
prompt("Input value J")
|
||||
@@ -443,7 +443,7 @@ INPA,...,INPU.
|
||||
extra("void *j")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTJ
|
||||
#=type Set by FTJ[NOJ]
|
||||
}
|
||||
field(K,DBF_NOACCESS) {
|
||||
prompt("Input value K")
|
||||
@@ -453,7 +453,7 @@ INPA,...,INPU.
|
||||
extra("void *k")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTK
|
||||
#=type Set by FTK[NOK]
|
||||
}
|
||||
field(L,DBF_NOACCESS) {
|
||||
prompt("Input value L")
|
||||
@@ -463,7 +463,7 @@ INPA,...,INPU.
|
||||
extra("void *l")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTL
|
||||
#=type Set by FTL[NOL]
|
||||
}
|
||||
field(M,DBF_NOACCESS) {
|
||||
prompt("Input value M")
|
||||
@@ -473,7 +473,7 @@ INPA,...,INPU.
|
||||
extra("void *m")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTM
|
||||
#=type Set by FTM[NOM]
|
||||
}
|
||||
field(N,DBF_NOACCESS) {
|
||||
prompt("Input value N")
|
||||
@@ -483,7 +483,7 @@ INPA,...,INPU.
|
||||
extra("void *n")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTN
|
||||
#=type Set by FTN[NON]
|
||||
}
|
||||
field(O,DBF_NOACCESS) {
|
||||
prompt("Input value O")
|
||||
@@ -493,7 +493,7 @@ INPA,...,INPU.
|
||||
extra("void *o")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTO
|
||||
#=type Set by FTO[NOO]
|
||||
}
|
||||
field(P,DBF_NOACCESS) {
|
||||
prompt("Input value P")
|
||||
@@ -503,7 +503,7 @@ INPA,...,INPU.
|
||||
extra("void *p")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTP
|
||||
#=type Set by FTP[NOP]
|
||||
}
|
||||
field(Q,DBF_NOACCESS) {
|
||||
prompt("Input value Q")
|
||||
@@ -513,7 +513,7 @@ INPA,...,INPU.
|
||||
extra("void *q")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTQ
|
||||
#=type Set by FTQ[NOQ]
|
||||
}
|
||||
field(R,DBF_NOACCESS) {
|
||||
prompt("Input value R")
|
||||
@@ -523,7 +523,7 @@ INPA,...,INPU.
|
||||
extra("void *r")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTR
|
||||
#=type Set by FTR[NOR]
|
||||
}
|
||||
field(S,DBF_NOACCESS) {
|
||||
prompt("Input value S")
|
||||
@@ -533,7 +533,7 @@ INPA,...,INPU.
|
||||
extra("void *s")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTS
|
||||
#=type Set by FTS[NOS]
|
||||
}
|
||||
field(T,DBF_NOACCESS) {
|
||||
prompt("Input value T")
|
||||
@@ -543,7 +543,7 @@ INPA,...,INPU.
|
||||
extra("void *t")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTT
|
||||
#=type Set by FTT[NOT]
|
||||
}
|
||||
field(U,DBF_NOACCESS) {
|
||||
prompt("Input value U")
|
||||
@@ -553,7 +553,7 @@ INPA,...,INPU.
|
||||
extra("void *u")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTU
|
||||
#=type Set by FTU[NOU]
|
||||
}
|
||||
|
||||
=head3 Input Value Data Types
|
||||
@@ -1161,7 +1161,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *vala")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVA
|
||||
#=type Set by FTVA[NOVA]
|
||||
}
|
||||
field(VALB,DBF_NOACCESS) {
|
||||
prompt("Output value B")
|
||||
@@ -1171,7 +1171,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valb")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVB
|
||||
#=type Set by FTVB[NOVB]
|
||||
}
|
||||
field(VALC,DBF_NOACCESS) {
|
||||
prompt("Output value C")
|
||||
@@ -1181,7 +1181,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valc")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVC
|
||||
#=type Set by FTVC[NOVC]
|
||||
}
|
||||
field(VALD,DBF_NOACCESS) {
|
||||
prompt("Output value D")
|
||||
@@ -1191,7 +1191,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *vald")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVD
|
||||
#=type Set by FTVD[NOVD]
|
||||
}
|
||||
field(VALE,DBF_NOACCESS) {
|
||||
prompt("Output value E")
|
||||
@@ -1201,7 +1201,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *vale")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVE
|
||||
#=type Set by FTVE[NOVE]
|
||||
}
|
||||
field(VALF,DBF_NOACCESS) {
|
||||
prompt("Output value F")
|
||||
@@ -1211,7 +1211,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valf")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVF
|
||||
#=type Set by FTVF[NOVF]
|
||||
}
|
||||
field(VALG,DBF_NOACCESS) {
|
||||
prompt("Output value G")
|
||||
@@ -1221,7 +1221,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valg")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVG
|
||||
#=type Set by FTVG[NOVG]
|
||||
}
|
||||
field(VALH,DBF_NOACCESS) {
|
||||
prompt("Output value H")
|
||||
@@ -1231,7 +1231,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valh")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVH
|
||||
#=type Set by FTVH[NOVH]
|
||||
}
|
||||
field(VALI,DBF_NOACCESS) {
|
||||
prompt("Output value I")
|
||||
@@ -1241,7 +1241,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *vali")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVI
|
||||
#=type Set by FTVI[NOVI]
|
||||
}
|
||||
field(VALJ,DBF_NOACCESS) {
|
||||
prompt("Output value J")
|
||||
@@ -1251,7 +1251,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valj")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVJ
|
||||
#=type Set by FTVJ[NOVJ]
|
||||
}
|
||||
field(VALK,DBF_NOACCESS) {
|
||||
prompt("Output value K")
|
||||
@@ -1261,7 +1261,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valk")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVK
|
||||
#=type Set by FTVK[NOVK]
|
||||
}
|
||||
field(VALL,DBF_NOACCESS) {
|
||||
prompt("Output value L")
|
||||
@@ -1271,7 +1271,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *vall")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVL
|
||||
#=type Set by FTVL[NOVL]
|
||||
}
|
||||
field(VALM,DBF_NOACCESS) {
|
||||
prompt("Output value M")
|
||||
@@ -1281,7 +1281,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valm")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVM
|
||||
#=type Set by FTVM[NOVM]
|
||||
}
|
||||
field(VALN,DBF_NOACCESS) {
|
||||
prompt("Output value N")
|
||||
@@ -1291,7 +1291,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valn")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVN
|
||||
#=type Set by FTVN[NOVN]
|
||||
}
|
||||
field(VALO,DBF_NOACCESS) {
|
||||
prompt("Output value O")
|
||||
@@ -1301,7 +1301,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valo")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVO
|
||||
#=type Set by FTVO[NOVO]
|
||||
}
|
||||
field(VALP,DBF_NOACCESS) {
|
||||
prompt("Output value P")
|
||||
@@ -1311,7 +1311,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valp")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVP
|
||||
#=type Set by FTVP[NOVP]
|
||||
}
|
||||
field(VALQ,DBF_NOACCESS) {
|
||||
prompt("Output value Q")
|
||||
@@ -1321,7 +1321,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valq")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVQ
|
||||
#=type Set by FTVQ[NOVQ]
|
||||
}
|
||||
field(VALR,DBF_NOACCESS) {
|
||||
prompt("Output value R")
|
||||
@@ -1331,7 +1331,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valr")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVR
|
||||
#=type Set by FTVR[NOVR]
|
||||
}
|
||||
field(VALS,DBF_NOACCESS) {
|
||||
prompt("Output value S")
|
||||
@@ -1341,7 +1341,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *vals")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVS
|
||||
#=type Set by FTVS[NOVS]
|
||||
}
|
||||
field(VALT,DBF_NOACCESS) {
|
||||
prompt("Output value T")
|
||||
@@ -1351,7 +1351,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valt")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVT
|
||||
#=type Set by FTVT[NOVT]
|
||||
}
|
||||
field(VALU,DBF_NOACCESS) {
|
||||
prompt("Output value U")
|
||||
@@ -1361,7 +1361,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
extra("void *valu")
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
#=type Set by FTVU
|
||||
#=type Set by FTVU[NOVU]
|
||||
}
|
||||
|
||||
=head3 Old Value Fields
|
||||
@@ -2378,7 +2378,7 @@ record can locate them. The simplest way is as follows:
|
||||
|
||||
#include <registryFunction.h>
|
||||
#include <epicsExport.h>
|
||||
|
||||
|
||||
static long my_asub_routine(aSubRecord *prec) {
|
||||
...
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=title Array Analog Input (aai)
|
||||
=title Array Input (aai)
|
||||
|
||||
The array analog input record type is used to read array data. The array data can
|
||||
The array input record type is used to read array data. The array data can
|
||||
contain any of the supported data types. The record is in many ways similar to the
|
||||
waveform record. It allows, however, the device support to allocate the array
|
||||
storage.
|
||||
@@ -31,14 +31,14 @@ The record-specific fields are described below, grouped by functionality.
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The array analog input record has the standard fields for specifying under what
|
||||
The array input record has the standard fields for specifying under what
|
||||
circumstances the record will be processed.
|
||||
These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
|
||||
=head3 Read Parameters
|
||||
|
||||
These fields are configurable by the user to specify how and from where the record
|
||||
reads its data. The INP field determines from where the array analog input gets
|
||||
reads its data. The INP field determines from where the array input gets
|
||||
its input. It can be a hardware address, a channel access or database link, or a
|
||||
constant. Only in records that use soft device support can the INP field be a
|
||||
channel access link, a database link, or a constant. Otherwise, the INP field must
|
||||
@@ -83,7 +83,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The array analog input record has the alarm parameters common to all record types.
|
||||
The array input record has the alarm parameters common to all record types.
|
||||
|
||||
=head3 Monitor Parameters
|
||||
|
||||
@@ -108,11 +108,11 @@ These are the possible choices for the C<APST> and C<MPST> fields:
|
||||
|
||||
=head3 Run-time Parameters
|
||||
|
||||
These parameters are used by the run-time code for processing the array analog
|
||||
These parameters are used by the run-time code for processing the array
|
||||
input record. They are not configured using a configuration tool. Only the VAL
|
||||
field is modifiable at run-time.
|
||||
|
||||
VAL references the array where the array analog input record stores its data. The
|
||||
VAL references the array where the array input record stores its data. The
|
||||
BPTR field holds the address of the array.
|
||||
|
||||
The NORD field holds a counter of the number of elements that have been read
|
||||
@@ -294,7 +294,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
include "dbCommon.dbd"
|
||||
%
|
||||
%/* Declare Device Support Entry Table */
|
||||
%struct aaiRecord;
|
||||
@@ -311,7 +311,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
special(SPC_DBADDR)
|
||||
pp(TRUE)
|
||||
extra("void * val")
|
||||
#=type DOUBLE[NELM]
|
||||
#=type Set by FTVL[NELM]
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
}
|
||||
@@ -319,7 +319,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
@@ -331,19 +331,19 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(HOPR,DBF_DOUBLE) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_DOUBLE) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(NELM,DBF_ULONG) {
|
||||
prompt("Number of Elements")
|
||||
@@ -351,6 +351,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
initial("1")
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(FTVL,DBF_MENU) {
|
||||
prompt("Field Type of Value")
|
||||
@@ -438,7 +439,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=head3 Fields Of Interest To Device Support
|
||||
|
||||
Each array analog input record record must have an associated set of device
|
||||
Each array input record record must have an associated set of device
|
||||
support routines. The primary responsibility of the device support routines is to
|
||||
obtain a new array value whenever C<read_aai()> is called. The device support
|
||||
routines are primarily interested in the following fields:
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=title Array Analog Output (aao)
|
||||
=title Array Output (aao)
|
||||
|
||||
The array analog output record type is used to write array data. The array data
|
||||
The array output record type is used to write array data. The array data
|
||||
can contain any of the supported data types. The record is in many ways similar
|
||||
to the waveform record but outputs arrays instead of reading them. It also
|
||||
allows the device support to allocate the array storage.
|
||||
@@ -31,7 +31,7 @@ The record-specific fields are described below, grouped by functionality.
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The array analog output record has the standard fields for specifying under what
|
||||
The array output record has the standard fields for specifying under what
|
||||
circumstances the record will be processed.
|
||||
These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
|
||||
@@ -40,12 +40,12 @@ These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
=head3 Write Parameters
|
||||
|
||||
These fields are configurable by the user to specify how and where to the record
|
||||
writes its data. The OUT field determines where the array analog output writes
|
||||
writes its data. The OUT field determines where the array output writes
|
||||
its output. It can be a hardware address, a channel access or database link, or
|
||||
a constant. Only in records that use soft device support can the OUT field be a
|
||||
channel access link, a database link, or a constant. Otherwise, the OUT field
|
||||
must be a hardware address. See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on the format of hardware addresses and database links.
|
||||
|
||||
=head4 Fields related to array writing
|
||||
@@ -87,7 +87,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The array analog output record has the alarm parameters common to all record
|
||||
The array output record has the alarm parameters common to all record
|
||||
types.
|
||||
|
||||
=head3 Monitor Parameters
|
||||
@@ -115,11 +115,11 @@ These are the choices available for the C<APST> and C<MPST> fields
|
||||
|
||||
=head3 Run-time Parameters
|
||||
|
||||
These parameters are used by the run-time code for processing the array analog
|
||||
These parameters are used by the run-time code for processing the array
|
||||
output record. They are not configured using a configuration tool. Only the VAL
|
||||
field is modifiable at run-time.
|
||||
|
||||
VAL references the array where the array analog output record stores its data.
|
||||
VAL references the array where the array output record stores its data.
|
||||
The BPTR field holds the address of the array.
|
||||
|
||||
The NORD field holds a counter of the number of elements that have been written
|
||||
@@ -317,7 +317,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
include "dbCommon.dbd"
|
||||
%
|
||||
%/* Declare Device Support Entry Table */
|
||||
%struct aaoRecord;
|
||||
@@ -333,7 +333,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
special(SPC_DBADDR)
|
||||
pp(TRUE)
|
||||
extra("void * val")
|
||||
#=type DOUBLE[]
|
||||
#=type Set by FTVL[NELM]
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
}
|
||||
@@ -341,7 +341,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(OUT,DBF_OUTLINK) {
|
||||
prompt("Output Specification")
|
||||
@@ -364,19 +364,19 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(HOPR,DBF_DOUBLE) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_DOUBLE) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(NELM,DBF_ULONG) {
|
||||
prompt("Number of Elements")
|
||||
@@ -384,6 +384,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
initial("1")
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(FTVL,DBF_MENU) {
|
||||
prompt("Field Type of Value")
|
||||
@@ -471,7 +472,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=head3 Fields Of Interest To Device Support
|
||||
|
||||
Each array analog output record record must have an associated set of device
|
||||
Each array output record record must have an associated set of device
|
||||
support routines. The primary responsibility of the device support routines is
|
||||
to write the array data value whenever C<write_aao()> is called. The device
|
||||
support routines are primarily interested in the following fields:
|
||||
|
||||
@@ -104,16 +104,16 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
recGblInitConstantLink(&prec->siol, DBF_DOUBLE, &prec->sval);
|
||||
|
||||
if(!(pdset = (aidset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"ai: init_record");
|
||||
recGblRecordError(S_dev_noDSET, prec, "ai: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* must have read_ai function defined */
|
||||
if ((pdset->common.number < 6) || (pdset->read_ai == NULL)) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"ai: init_record");
|
||||
recGblRecordError(S_dev_missingSup, prec, "ai: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
prec->init = TRUE;
|
||||
/*The following is for old device support that doesnt know about eoff*/
|
||||
/*The following is for old device support that doesn't know about eoff*/
|
||||
if ((prec->eslo==1.0) && (prec->eoff==0.0)) {
|
||||
prec->eoff = prec->egul;
|
||||
}
|
||||
@@ -143,7 +143,7 @@ static long process(struct dbCommon *pcommon)
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_ai==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"read_ai");
|
||||
recGblRecordError(S_dev_missingSup, prec, "read_ai");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
timeLast = prec->time;
|
||||
@@ -431,7 +431,7 @@ static void convert(aiRecord *prec)
|
||||
break;
|
||||
|
||||
default: /* must use breakpoint table */
|
||||
if (cvtRawToEngBpt(&val,prec->linr,prec->init,(void *)&prec->pbrk,&prec->lbrk)!=0) {
|
||||
if (cvtRawToEngBpt(&val, prec->linr, prec->init, &prec->pbrk, &prec->lbrk)!=0) {
|
||||
recGblSetSevrMsg(prec,SOFT_ALARM,MAJOR_ALARM, "BPT Error");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ input data should come from.
|
||||
The format for the INP field value depends on the device support layer that is
|
||||
selected by the DTYP field.
|
||||
See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for a description of the various hardware address formats supported.
|
||||
|
||||
=head3 Units Conversion
|
||||
@@ -212,7 +212,7 @@ positive number of seconds will delay the record going into or out of a minor
|
||||
alarm severity or from minor to major severity until the input signal has been
|
||||
in the alarm range for that number of seconds.
|
||||
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
for a complete explanation of record alarms and of the standard fields.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
||||
to alarms that are common to all record types.
|
||||
@@ -265,7 +265,7 @@ monitoring functionality.
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(LINR,DBF_MENU) {
|
||||
prompt("Linearization")
|
||||
@@ -294,19 +294,19 @@ monitoring functionality.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(HOPR,DBF_DOUBLE) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_DOUBLE) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(AOFF,DBF_DOUBLE) {
|
||||
prompt("Adjustment Offset")
|
||||
@@ -331,35 +331,35 @@ monitoring functionality.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_DOUBLE) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_DOUBLE) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_DOUBLE) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
@@ -367,7 +367,7 @@ monitoring functionality.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
@@ -375,7 +375,7 @@ monitoring functionality.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
@@ -383,7 +383,7 @@ monitoring functionality.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_DOUBLE) {
|
||||
|
||||
@@ -105,7 +105,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
|
||||
|
||||
if(!(pdset = (aodset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"ao: init_record");
|
||||
recGblRecordError(S_dev_noDSET, prec, "ao: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* get the initial value if dol is a constant*/
|
||||
@@ -114,11 +114,11 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
|
||||
/* must have write_ao function defined */
|
||||
if ((pdset->common.number < 6) || (pdset->write_ao ==NULL)) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"ao: init_record");
|
||||
recGblRecordError(S_dev_missingSup, prec, "ao: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
prec->init = TRUE;
|
||||
/*The following is for old device support that doesnt know about eoff*/
|
||||
/*The following is for old device support that doesn't know about eoff*/
|
||||
if ((prec->eslo==1.0) && (prec->eoff==0.0)) {
|
||||
prec->eoff = prec->egul;
|
||||
}
|
||||
@@ -141,7 +141,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
value = value*prec->eslo + prec->eoff;
|
||||
}else{
|
||||
if(cvtRawToEngBpt(&value,prec->linr,prec->init,
|
||||
(void *)&prec->pbrk,&prec->lbrk)!=0) break;
|
||||
&prec->pbrk, &prec->lbrk)!=0) break;
|
||||
}
|
||||
prec->val = value;
|
||||
prec->udf = isnan(value);
|
||||
@@ -149,7 +149,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
case(2): /* no convert */
|
||||
break;
|
||||
default:
|
||||
recGblRecordError(S_dev_badInitRet,(void *)prec,"ao: init_record");
|
||||
recGblRecordError(S_dev_badInitRet, prec, "ao: init_record");
|
||||
return(S_dev_badInitRet);
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ static long process(struct dbCommon *pcommon)
|
||||
|
||||
if ((pdset==NULL) || (pdset->write_ao==NULL)) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"write_ao");
|
||||
recGblRecordError(S_dev_missingSup, prec, "write_ao");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ static long process(struct dbCommon *pcommon)
|
||||
break;
|
||||
default :
|
||||
status=-1;
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"ao:process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
@@ -493,7 +493,7 @@ static void convert(aoRecord *prec, double value)
|
||||
break;
|
||||
default:
|
||||
if (cvtEngToRawBpt(&value, prec->linr, prec->init,
|
||||
(void *)&prec->pbrk, &prec->lbrk) != 0) {
|
||||
&prec->pbrk, &prec->lbrk) != 0) {
|
||||
recGblSetSevr(prec, SOFT_ALARM, MAJOR_ALARM);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -69,9 +69,13 @@ output value PVAL is added to it.
|
||||
|
||||
=head4 Drive Limits
|
||||
|
||||
The output value is now clipped to the range DRVL to DRVH inclusive, provided
|
||||
that DRVH E<gt> DRVL.
|
||||
The result is copied into both the VAL and PVAL fields.
|
||||
The VAL field's value will be clipped within limits specified in the fields DRVH
|
||||
and DRVL if these have been configured by the database designer:
|
||||
|
||||
DRVL <= VAL <= DRVH
|
||||
|
||||
Note: These limits are only enforced as long as DRVH E<gt> DRVL. If they are not
|
||||
set or DRVH E<lt>= DRVL they will not be used.
|
||||
|
||||
=head4 Limit Rate of Change
|
||||
|
||||
@@ -162,7 +166,7 @@ OUT field. For analog outputs that write their values to devices, the
|
||||
OUT field must specify the address of the I/O card. In addition, the
|
||||
DTYP field must contain the name of the device support module. Be aware
|
||||
that the address format differs according to the I/O bus used. See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on the format of hardware addresses.
|
||||
|
||||
For soft records the output link can be a database link, a channel
|
||||
@@ -220,8 +224,8 @@ alarms that are common to all record types.
|
||||
These parameters are used to specify deadbands for monitors on the VAL
|
||||
field. The monitors are sent when the value field exceeds the last
|
||||
monitored field by the specified deadband. 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 processed, monitors
|
||||
of zero, every time the value changes, a monitor will be triggered; if
|
||||
they have a value of -1, every time the record is processed, monitors
|
||||
are triggered. ADEL is the deadband for archive monitors, and MDEL the
|
||||
deadband for all other types of monitors. See Monitor Specification for
|
||||
a complete explanation of monitors.
|
||||
@@ -328,7 +332,7 @@ for more information on simulation mode and its fields.
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(LINR,DBF_MENU) {
|
||||
prompt("Linearization")
|
||||
@@ -357,7 +361,7 @@ for more information on simulation mode and its fields.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(ROFF,DBF_ULONG) {
|
||||
prompt("Raw Offset")
|
||||
@@ -382,26 +386,26 @@ for more information on simulation mode and its fields.
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_control_double
|
||||
}
|
||||
field(DRVL,DBF_DOUBLE) {
|
||||
prompt("Drive Low Limit")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_control_double
|
||||
}
|
||||
field(HOPR,DBF_DOUBLE) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double
|
||||
}
|
||||
field(LOPR,DBF_DOUBLE) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double
|
||||
}
|
||||
field(AOFF,DBF_DOUBLE) {
|
||||
prompt("Adjustment Offset")
|
||||
@@ -420,35 +424,35 @@ for more information on simulation mode and its fields.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) #get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_DOUBLE) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) #get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_DOUBLE) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) #get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_DOUBLE) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) #get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) #get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
@@ -456,7 +460,7 @@ for more information on simulation mode and its fields.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) #get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
@@ -464,7 +468,7 @@ for more information on simulation mode and its fields.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) #get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
@@ -472,7 +476,7 @@ for more information on simulation mode and its fields.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) #get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_DOUBLE) {
|
||||
@@ -689,7 +693,7 @@ Routine process implements the following algorithm:
|
||||
|
||||
=over
|
||||
|
||||
=item 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
|
||||
@@ -697,7 +701,7 @@ terminated with the PACT field set to TRUE. This ensures that processes
|
||||
will no longer be called for this record. Thus error storms will not
|
||||
occur.
|
||||
|
||||
=item 2.
|
||||
=item 2.
|
||||
|
||||
Check PACT: If PACT is FALSE call fetch_values and convert
|
||||
which perform the following steps:
|
||||
@@ -746,7 +750,7 @@ calculated in, using the formula RVAL = (RVAL -AOFF) / ASLO - ROFF.
|
||||
|
||||
=back
|
||||
|
||||
=item 3.
|
||||
=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 y are
|
||||
@@ -754,18 +758,18 @@ set. It also honors the alarm hysteresis factor (HYST). Thus the value
|
||||
must change by at least HYST before the alarm status and severity is
|
||||
reduced.
|
||||
|
||||
=item 4.
|
||||
=item 4.
|
||||
|
||||
Check severity and write the new value. See Invalid Alarm
|
||||
Output Action for details on how invalid alarms affect output records.
|
||||
|
||||
=item 5.
|
||||
=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.
|
||||
=item 6.
|
||||
|
||||
Check to see if monitors should be invoked:
|
||||
|
||||
@@ -784,7 +788,7 @@ monitors are invoked.
|
||||
|
||||
=back
|
||||
|
||||
=item 7.
|
||||
=item 7.
|
||||
|
||||
Scan forward link if necessary, set PACT and INIT FALSE, and
|
||||
return.
|
||||
|
||||
@@ -96,12 +96,12 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
recGblInitConstantLink(&prec->siol, DBF_USHORT, &prec->sval);
|
||||
|
||||
if(!(pdset = (bidset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"bi: init_record");
|
||||
recGblRecordError(S_dev_noDSET, prec, "bi: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* must have read_bi function defined */
|
||||
if( (pdset->common.number < 5) || (pdset->read_bi == NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"bi: init_record");
|
||||
recGblRecordError(S_dev_missingSup, prec, "bi: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if( pdset->common.init_record ) {
|
||||
@@ -122,7 +122,7 @@ static long process(struct dbCommon *pcommon)
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_bi==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"read_bi");
|
||||
recGblRecordError(S_dev_missingSup, prec, "read_bi");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,13 +47,13 @@ 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<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on the format of the hardware address.
|
||||
|
||||
For records that specify C<Soft Channel> or C<Raw Soft Channel> 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<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on the format of database and
|
||||
channel access addresses. Also, see L<Device Support for Soft Records> in
|
||||
this chapter for information on soft device support.
|
||||
@@ -99,7 +99,7 @@ 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.
|
||||
support routines.
|
||||
|
||||
The user can choose the severity of each state in the ZSV and OSV fields.
|
||||
The possible values for these fields are C<NO_ALARM>, C<MINOR>, and
|
||||
@@ -107,7 +107,7 @@ C<MAJOR>. 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<Alarm Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
for a complete explanation of record alarms and of the standard fields.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
||||
to alarms that are common to all record types.
|
||||
@@ -126,7 +126,7 @@ 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
|
||||
The LALM fields 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 MAJOR or MINOR.
|
||||
|
||||
@@ -186,7 +186,7 @@ is not equal to VAL.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(ONAM,DBF_STRING) {
|
||||
prompt("One Name")
|
||||
@@ -194,7 +194,7 @@ is not equal to VAL.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_Str
|
||||
}
|
||||
field(RVAL,DBF_ULONG) {
|
||||
prompt("Raw Value")
|
||||
@@ -407,7 +407,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
=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
|
||||
routines. The primary responsibility of the device support routines is to
|
||||
obtain a new raw input value whenever C<read_bi()> is called. The device
|
||||
support routines are primarily interested in the following fields:
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ static long process(struct dbCommon *pcommon)
|
||||
|
||||
if( (pdset==NULL) || (pdset->write_bo==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"write_bo");
|
||||
recGblRecordError(S_dev_missingSup, prec, "write_bo");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if (!prec->pact) {
|
||||
@@ -240,7 +240,7 @@ static long process(struct dbCommon *pcommon)
|
||||
break;
|
||||
default :
|
||||
status=-1;
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"bo:process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ continuous control, a database link to a control algorithm record should be
|
||||
entered in the DOL field.
|
||||
|
||||
See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on hardware addresses and links.
|
||||
|
||||
=fields DOL, OMSL
|
||||
@@ -105,13 +105,13 @@ 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<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on the format of hardware addresses.
|
||||
|
||||
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<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on the format of the database and channel access addresses.
|
||||
Also, see L<Device Support For Soft Records> in this chapter for more on output
|
||||
to other records.
|
||||
@@ -239,7 +239,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(ONAM,DBF_STRING) {
|
||||
prompt("One Name")
|
||||
@@ -247,7 +247,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(RVAL,DBF_ULONG) {
|
||||
prompt("Raw Value")
|
||||
@@ -391,7 +391,7 @@ 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.
|
||||
or initialized to 0 if DOL is zero, and UDF is set to FALSE.
|
||||
|
||||
If device support includes C<init_record()>, it is called. VAL is set using
|
||||
RVAL, and UDF is set to FALSE.
|
||||
|
||||
@@ -103,7 +103,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
recGblInitConstantLink(plink, DBF_DOUBLE, pvalue);
|
||||
}
|
||||
if (postfix(prec->calc, prec->rpcl, &error_number)) {
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"calc: init_record: Illegal CALC field");
|
||||
errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->calc);
|
||||
@@ -144,7 +144,7 @@ static long special(DBADDR *paddr, int after)
|
||||
if (!after) return 0;
|
||||
if (paddr->special == SPC_CALC) {
|
||||
if (postfix(prec->calc, prec->rpcl, &error_number)) {
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"calc: Illegal CALC field");
|
||||
errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->calc);
|
||||
|
||||
@@ -14,6 +14,8 @@ 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.
|
||||
|
||||
Since 7.0.10 the number of inputs has been increased from 12 to 21.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
@@ -35,45 +37,49 @@ These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
=head3 Read Parameters
|
||||
|
||||
The read parameters for the Calc record consist of 21 input links INPA -
|
||||
INPU. The fields can be database links, channel access links, or
|
||||
constants. If they are links, they must specify another record's field or a
|
||||
INPU. 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<dbPuts>. They
|
||||
cannot be hardware addresses.
|
||||
|
||||
See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on how to specify database links.
|
||||
|
||||
=fields INPA - INPU
|
||||
|
||||
=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.
|
||||
At the core of the Calc record lies the CALC and RPCL fields.
|
||||
The CALC field holds an infix expression to be evaluated whenever the record is
|
||||
processed.
|
||||
The calculated value is placed in the VAL field and can be accessed from there.
|
||||
|
||||
The CALC expression gets compiled into a stream of Reverse Polish Notation (RPN)
|
||||
opcodes for a stack-based machine, and stored in the RPCL field.
|
||||
The RPN opcodes are used to calculate VAL at run-time, and are more efficient
|
||||
than evaluating the infix expression.
|
||||
The CALC expression can be replaced at run-time, triggering a special record
|
||||
routine to compile the new expression into 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.
|
||||
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 C<;>, any one of which may provide the calculation result.
|
||||
All other expressions included in the string 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.
|
||||
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 colon or C<?:> operator.
|
||||
|
||||
=fields CALC, RPCL
|
||||
|
||||
@@ -85,10 +91,10 @@ parentheses and commas, and the question mark or '?:' operator.
|
||||
Standard double precision floating point numbers
|
||||
|
||||
=item *
|
||||
Inf: Infinity
|
||||
C<Inf>: Infinity
|
||||
|
||||
=item *
|
||||
Nan: Not a Number
|
||||
C<NaN>: Not a Number
|
||||
|
||||
=back
|
||||
|
||||
@@ -97,14 +103,14 @@ Nan: Not a Number
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
PI: returns the mathematical constant E<pi>
|
||||
C<PI>: returns the mathematical constant E<pi>
|
||||
|
||||
=item *
|
||||
D2R: evaluates to E<pi>/180 which, when used as a multiplier, converts an
|
||||
C<D2R>: evaluates to E<pi>/180 which, when used as a multiplier, converts an
|
||||
angle from degrees to radians
|
||||
|
||||
=item *
|
||||
R2D: evaluates to 180/E<pi> which as a multiplier converts an angle from
|
||||
C<R2D>: evaluates to 180/E<pi> which as a multiplier converts an angle from
|
||||
radians to degrees
|
||||
|
||||
=back
|
||||
@@ -127,112 +133,205 @@ The keyword VAL returns the current contents of the VAL field (which can be
|
||||
written to by a CA put, so it might I<not> be the result from the last time
|
||||
the expression was evaluated).
|
||||
|
||||
=head3 Algebraic Operators
|
||||
=head3 Arithmetic Operators
|
||||
|
||||
Except for unary minus these are infix binary operators.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
ABS: Absolute value (unary)
|
||||
C<+> : Addition
|
||||
|
||||
=item *
|
||||
SQR: Square root (unary)
|
||||
C<-> : Subtraction
|
||||
|
||||
=item *
|
||||
MIN: Minimum (any number of args)
|
||||
C<-> : Minus (unary)
|
||||
|
||||
=item *
|
||||
MAX: Maximum (any number of args)
|
||||
C<*> : Multiplication
|
||||
|
||||
=item *
|
||||
FINITE: returns non-zero if none of the arguments are NaN or Inf (any
|
||||
number of args)
|
||||
C</> : Division
|
||||
|
||||
=item *
|
||||
ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number
|
||||
of args)
|
||||
C<%> : Modulo
|
||||
|
||||
=item *
|
||||
CEIL: Ceiling (unary)
|
||||
C<^> : Exponential
|
||||
|
||||
=item *
|
||||
FLOOR: Floor (unary)
|
||||
|
||||
=item *
|
||||
FMOD: Floating point modulo (binary) Added in 7.0.8
|
||||
|
||||
=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)
|
||||
C<**> : Exponential
|
||||
|
||||
=back
|
||||
|
||||
=head3 Trigonometric Operators
|
||||
=head3 Algebraic Functions
|
||||
|
||||
When functions take more than one argument, a comma separator must appear
|
||||
between them.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
SIN: Sine
|
||||
C<ABS (arg)> : Absolute value
|
||||
|
||||
=item *
|
||||
SINH: Hyperbolic sine
|
||||
C<EXP (arg)> : Exponential function
|
||||
|
||||
=item *
|
||||
ASIN: Arc sine
|
||||
C<FMOD (num, den)> : Floating point modulo. Added in 7.0.8
|
||||
|
||||
=item *
|
||||
COS: Cosine
|
||||
C<LN (arg)> : Natural log
|
||||
|
||||
=item *
|
||||
COSH: Hyperbolic cosine
|
||||
C<LOG (arg)> : Log base 10
|
||||
|
||||
=item *
|
||||
ACOS: Arc cosine
|
||||
C<LOGE (arg)> : Natural log
|
||||
|
||||
=item *
|
||||
TAN: Tangent
|
||||
C<MIN (any number of args)> : Minimum
|
||||
|
||||
=item *
|
||||
TANH: Hyperbolic tangent
|
||||
C<MAX (any number of args)> : Maximum
|
||||
|
||||
=item *
|
||||
ATAN: Arc tangent
|
||||
C<SQR (arg)> : Square root
|
||||
|
||||
=item *
|
||||
C<SQRT (arg)> : Square root
|
||||
|
||||
=back
|
||||
|
||||
=head3 Trigonometric Functions
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<SIN (arg)> : Sine
|
||||
|
||||
=item *
|
||||
C<ASIN (arg)> : Arc sine
|
||||
|
||||
=item *
|
||||
C<COS (arg)> : Cosine
|
||||
|
||||
=item *
|
||||
C<ACOS (arg)> : Arc cosine
|
||||
|
||||
=item *
|
||||
C<TAN (arg)> : Tangent
|
||||
|
||||
=item *
|
||||
C<ATAN (arg)> : Arc tangent
|
||||
|
||||
=item *
|
||||
C<ATAN2 (den, num)> : 2-parameter Arc tangent. Arg's are reversed to ANSI C
|
||||
|
||||
=back
|
||||
|
||||
=head3 Hyperbolic Trigonometry Functions
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<SINH (arg)> : Hyperbolic sine
|
||||
|
||||
=item *
|
||||
C<COSH (arg)> : Hyperbolic cosine
|
||||
|
||||
=item *
|
||||
C<TANH (arg)> : Hyperbolic tangent
|
||||
|
||||
=back
|
||||
|
||||
=head3 Numeric Functions
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<CEIL (arg)> : Ceiling
|
||||
|
||||
=item *
|
||||
C<FLOOR (arg)> : Floor
|
||||
|
||||
=item *
|
||||
C<NINT (arg)> : Round to nearest integer
|
||||
|
||||
=item *
|
||||
C<ISINF (arg)> : returns non-zero if any argument is Inf
|
||||
|
||||
=item *
|
||||
C<ISNAN (any number of args)> : returns non-zero (true) if any argument is NaN
|
||||
or Inf
|
||||
|
||||
=item *
|
||||
C<FINITE (any number of args)> : returns non-zero (true) if none of the
|
||||
arguments are NaN or Inf
|
||||
|
||||
=back
|
||||
|
||||
=head3 Boolean/Logical Operators
|
||||
|
||||
These operators use their arguments as a true (non-zero) or false (zero) value.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<&&> : And, infix binary
|
||||
|
||||
=item *
|
||||
C<||> : Or, infix binary
|
||||
|
||||
=item *
|
||||
C<!> : Not, unary prefix
|
||||
|
||||
=back
|
||||
|
||||
=head3 Bitwise Operators
|
||||
|
||||
Mostly infix binary, the arguments are converted to a 32-bit integer, the
|
||||
operator is applied, and the result converted back into a double.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<&> : Bitwise and
|
||||
|
||||
=item *
|
||||
C<|> : Bitwise or
|
||||
|
||||
=item *
|
||||
C<~> : Bitwise not or one's complement, unary prefix
|
||||
|
||||
=item *
|
||||
C<<< << >>> : Arithmetic shift left
|
||||
|
||||
=item *
|
||||
C<<< >> >>> : Arithmetic shift right
|
||||
|
||||
=item *
|
||||
C<<<< >>> >>>> : Logical shift right
|
||||
|
||||
=item *
|
||||
C<AND> : Bitwise and
|
||||
|
||||
=item *
|
||||
C<OR> : Bitwise or
|
||||
|
||||
=item *
|
||||
C<XOR> : Bitwise exclusive or
|
||||
|
||||
=item *
|
||||
C<NOT> : Bitwise not or one's complement, unary prefix
|
||||
|
||||
=back
|
||||
|
||||
=head3 Relational Operators
|
||||
|
||||
These are all infix binary operators.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
@@ -247,59 +346,17 @@ C<<< <= >>> : Less than or equal to
|
||||
=item *
|
||||
C<<< < >>> : Less than
|
||||
|
||||
=item *
|
||||
C<<< != >>> : Not equal to
|
||||
|
||||
=item *
|
||||
C<<< # >>> : Not equal to
|
||||
|
||||
=item *
|
||||
C<<< = >>> : Equal to
|
||||
|
||||
=back
|
||||
|
||||
=head3 Logical Operators
|
||||
|
||||
=over 1
|
||||
C<<< == >>> : Equal to
|
||||
|
||||
=item *
|
||||
C<&&> : And
|
||||
|
||||
=item *
|
||||
C<||> : Or
|
||||
|
||||
=item *
|
||||
C<!> : Not
|
||||
|
||||
=back
|
||||
|
||||
=head3 Bitwise Operators
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<|> : Bitwise Or
|
||||
|
||||
=item *
|
||||
C<&> : Bitwise And
|
||||
|
||||
=item *
|
||||
OR : Bitwise Or
|
||||
|
||||
=item *
|
||||
AND : Bitwise And
|
||||
|
||||
=item *
|
||||
XOR : Bitwise Exclusive Or
|
||||
|
||||
=item *
|
||||
C<~> : One's Complement
|
||||
|
||||
=item *
|
||||
C<<< << >>> : Arithmetic Left Shift
|
||||
|
||||
=item *
|
||||
C<<< >> >>> : Arithmetic Right Shift
|
||||
|
||||
=item *
|
||||
C<<<< >>> >>>> : Logical Right Shift
|
||||
C<<< = >>> : Equal to (not assignment)
|
||||
|
||||
=back
|
||||
|
||||
@@ -312,24 +369,26 @@ C<:=> : assigns a value (right hand side) to a variable (i.e. field)
|
||||
|
||||
=back
|
||||
|
||||
=head3 Parantheses, Comma, and Semicolon
|
||||
=head3 Parentheses, Comma, and Semicolon
|
||||
|
||||
The open and close parentheses are supported. Nested parentheses are
|
||||
supported.
|
||||
The open C<(> and close parentheses C<)> are supported to override precedence
|
||||
rules in a sub-expression.
|
||||
Nested parentheses are supported to significant depth.
|
||||
|
||||
The comma is supported when used to separate the arguments of a binary
|
||||
function.
|
||||
The comma C<,> is required to separate the arguments of a function.
|
||||
|
||||
The semicolon is used to separate expressions. Although only one
|
||||
traditional calculation expression is allowed, multiple assignment
|
||||
expressions are allowed.
|
||||
The semicolon C<;> is used to value separate expressions.
|
||||
Exactly one value expression must be present, but multiple assignment
|
||||
expressions may be included before and/or after the value expression.
|
||||
|
||||
=head3 Conditional Expression
|
||||
=head3 Conditional Operator
|
||||
|
||||
The C language's question mark operator is supported. The format is:
|
||||
C<condition ? True result : False result>
|
||||
The C language's question mark colon C<?:> ternary operator is supported.
|
||||
The format is:
|
||||
|
||||
=head3 Expression Examples
|
||||
I<condition> C<?> I<true-expression> C<:> I<false-expression>
|
||||
|
||||
=head2 Expression Examples
|
||||
|
||||
=head3 Algebraic
|
||||
|
||||
@@ -370,21 +429,21 @@ Result is C<F + L + 10> if C<<< (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:
|
||||
Prior to Base 3.14.9 it was legal to omit the colon C<:> and the second (else)
|
||||
part of the conditional, like this:
|
||||
|
||||
C<(A + B)<(C + D) ? E>
|
||||
C<<< (A + B)<(C + D) ? E >>>
|
||||
|
||||
=over 1
|
||||
|
||||
=item
|
||||
Result is E if (A + B)<(C + D)
|
||||
=item *
|
||||
Result is C<E> if C<<< (A + B)<(C + D) >>>
|
||||
|
||||
=item
|
||||
Result is unchanged if (A + B)>=(C + D)
|
||||
=item *
|
||||
Result is unchanged if C<<< (A + B)>=(C + D) >>>
|
||||
|
||||
From 3.14.9 onwards, this expresion must be written as
|
||||
C<(A + B) < (C + D) ? E : VAL>
|
||||
From 3.14.9 onwards, this expression must be written as
|
||||
C<<< (A + B) < (C + D) ? E : VAL >>>
|
||||
|
||||
=back
|
||||
|
||||
@@ -406,7 +465,7 @@ Convert A to integer
|
||||
Convert B to integer
|
||||
|
||||
=item *
|
||||
Bitwise And A and B
|
||||
Bitwise A C<and> B
|
||||
|
||||
=item *
|
||||
Convert result to floating point
|
||||
@@ -465,7 +524,7 @@ reporting of limit alarms until the signal has been within the alarm range for
|
||||
that number of seconds (the default AFTC value of zero retains the previous
|
||||
behavior).
|
||||
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
for a complete explanation of record alarms and of the standard fields.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
||||
to alarms that are common to all record types.
|
||||
@@ -478,8 +537,8 @@ 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
|
||||
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<Monitor Specification> for a complete explanation of monitors.
|
||||
|
||||
=fields ADEL, MDEL
|
||||
@@ -634,60 +693,60 @@ manner for the VAL field.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(PREC,DBF_SHORT) {
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(HOPR,DBF_DOUBLE) {
|
||||
prompt("High Operating Rng")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_dpuble, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_DOUBLE) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_dpuble, get_control_double
|
||||
}
|
||||
field(HIHI,DBF_DOUBLE) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_DOUBLE) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_DOUBLE) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_DOUBLE) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
@@ -695,7 +754,7 @@ manner for the VAL field.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
@@ -703,7 +762,7 @@ manner for the VAL field.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
@@ -711,7 +770,7 @@ manner for the VAL field.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(AFTC, DBF_DOUBLE) {
|
||||
@@ -1018,23 +1077,25 @@ Routine process implements the following algorithm:
|
||||
=over 1
|
||||
|
||||
=item 1.
|
||||
|
||||
Fetch all arguments.
|
||||
|
||||
=item 2.
|
||||
|
||||
Call routine C<calcPerform>, which calculates VAL from the postfix version of
|
||||
the expression given in CALC. If C<calcPerform> 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
|
||||
Check to see if monitors should be invoked.
|
||||
|
||||
=over 1
|
||||
|
||||
@@ -1053,9 +1114,8 @@ NSEV and NSTA are reset to 0.
|
||||
|
||||
=back
|
||||
|
||||
=over
|
||||
|
||||
=item 5.
|
||||
|
||||
Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=back
|
||||
|
||||
@@ -142,13 +142,13 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
}
|
||||
|
||||
if (!(pcalcoutDSET = (calcoutdset *)prec->dset)) {
|
||||
recGblRecordError(S_dev_noDSET, (void *)prec, "calcout:init_record");
|
||||
recGblRecordError(S_dev_noDSET, prec, "calcout:init_record");
|
||||
return S_dev_noDSET;
|
||||
}
|
||||
|
||||
/* must have write defined */
|
||||
if ((pcalcoutDSET->common.number < 5) || (pcalcoutDSET->write ==NULL)) {
|
||||
recGblRecordError(S_dev_missingSup, (void *)prec, "calcout:init_record");
|
||||
recGblRecordError(S_dev_missingSup, prec, "calcout:init_record");
|
||||
return S_dev_missingSup;
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
|
||||
prec->clcv = postfix(prec->calc, prec->rpcl, &error_number);
|
||||
if (prec->clcv){
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"calcout: init_record: Illegal CALC field");
|
||||
errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->calc);
|
||||
@@ -198,7 +198,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
|
||||
prec->oclv = postfix(prec->ocal, prec->orpc, &error_number);
|
||||
if (prec->dopt == calcoutDOPT_Use_OVAL && prec->oclv){
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"calcout: init_record: Illegal OCAL field");
|
||||
errlogPrintf("%s.OCAL: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->ocal);
|
||||
@@ -325,7 +325,7 @@ static long special(DBADDR *paddr, int after)
|
||||
case(calcoutRecordCALC):
|
||||
prec->clcv = postfix(prec->calc, prec->rpcl, &error_number);
|
||||
if (prec->clcv){
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"calcout: special(): Illegal CALC field");
|
||||
errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->calc);
|
||||
@@ -336,7 +336,7 @@ static long special(DBADDR *paddr, int after)
|
||||
case(calcoutRecordOCAL):
|
||||
prec->oclv = postfix(prec->ocal, prec->orpc, &error_number);
|
||||
if (prec->dopt == calcoutDOPT_Use_OVAL && prec->oclv){
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"calcout: special(): Illegal OCAL field");
|
||||
errlogPrintf("%s.OCAL: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->ocal);
|
||||
@@ -650,7 +650,7 @@ static void execOutput(calcoutRecord *prec)
|
||||
if (prec->epvt) postEvent(prec->epvt);
|
||||
break;
|
||||
default:
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"calcout:process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ 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.
|
||||
|
||||
Since 7.0.10 the number of inputs has been increased from 12 to 21.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
@@ -58,8 +60,8 @@ These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
=head3 Read Parameters
|
||||
|
||||
The read parameters for the Calcout record consists of 21 input links INPA -
|
||||
INPU. The fields can be database links, channel access links, or
|
||||
constants. If they are links, they must specify another record's field. If
|
||||
INPU. 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<dbPuts>. These fields cannot be
|
||||
hardware addresses. In addition, the Calcout record contains the INAV -
|
||||
@@ -70,38 +72,45 @@ fields.
|
||||
|
||||
=fields INPA - INPU
|
||||
|
||||
=head3 Expression
|
||||
=head3 Expressions
|
||||
|
||||
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<Output Parameters>) 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.
|
||||
Like the Calc record, the Calcout record's CALC field holds an infix expression
|
||||
to be evaluated whenever the record is processed.
|
||||
The resulting value is placed in the VAL field.
|
||||
|
||||
The OOPT field condition is applied to VAL (see L<Output Parameters>) and
|
||||
controls whether to write to the output link (or post a named event), and the
|
||||
DOPT field selects whether VAL should be written, or another expression from
|
||||
the OCAL field should be evaluated and used instead.
|
||||
|
||||
The CALC and OCAL expressions get compiled into streams of Reverse Polish
|
||||
Notation (RPN) opcodes for a stack-based machine, and stored in the RPCL and
|
||||
ORPC fields respectively.
|
||||
|
||||
The RPN opcodes are used to calculate VAL at run-time, and are more efficient
|
||||
than evaluating the infix expression.
|
||||
The CALC and OCAL expressions can be replaced at run-time, triggering a special
|
||||
record routine to compile the new expression into 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.
|
||||
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 C<;>, any one of which may provide the calculation result.
|
||||
All other expressions included in the string 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 operator, the assignment operator,
|
||||
parentheses and commas, and the question mark or '?:' operator.
|
||||
relational operators, logical operators, the assignment operator, parentheses
|
||||
and commas, and the question mark colon or C<?:> operator.
|
||||
|
||||
=fields CALC, VAL, RPCL
|
||||
=fields CALC, VAL, OVAL, RPCL, ORPC
|
||||
|
||||
=head3 Literals
|
||||
|
||||
@@ -111,10 +120,10 @@ parentheses and commas, and the question mark or '?:' operator.
|
||||
Standard double precision floating point numbers
|
||||
|
||||
=item *
|
||||
Inf: Infinity
|
||||
C<Inf>: Infinity
|
||||
|
||||
=item *
|
||||
Nan: Not a Number
|
||||
C<NaN>: Not a Number
|
||||
|
||||
=back
|
||||
|
||||
@@ -123,14 +132,14 @@ Nan: Not a Number
|
||||
=over
|
||||
|
||||
=item *
|
||||
PI: returns the mathematical constant E<pi>
|
||||
C<PI>: returns the mathematical constant E<pi>
|
||||
|
||||
=item *
|
||||
D2R: evaluates to E<pi>/180 which, when used as a multiplier, converts an
|
||||
C<D2R>: evaluates to E<pi>/180 which, when used as a multiplier, converts an
|
||||
angle from degrees to radians
|
||||
|
||||
=item *
|
||||
R2D: evaluates to 180/E<pi> which, when used as a multiplier, converts an
|
||||
C<R2D>: evaluates to 180/E<pi> which, when used as a multiplier, converts an
|
||||
angle from radians to degrees
|
||||
|
||||
=back
|
||||
@@ -153,112 +162,205 @@ 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<not> be the result from the last time the expression was evaluated).
|
||||
|
||||
=head3 Algebraic Operations
|
||||
=head3 Arithmetic Operators
|
||||
|
||||
Except for unary minus these are infix binary operators.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
ABS: Absolute value (unary)
|
||||
C<+> : Addition
|
||||
|
||||
=item *
|
||||
SQR: Square root (unary)
|
||||
C<-> : Subtraction
|
||||
|
||||
=item *
|
||||
MIN: Minimum (any number of args)
|
||||
C<-> : Minus (unary)
|
||||
|
||||
=item *
|
||||
MAX: Maximum (any number of args)
|
||||
C<*> : Multiplication
|
||||
|
||||
=item *
|
||||
FINITE: returns non-zero if none of the arguments are NaN or Inf (any
|
||||
number of args)
|
||||
C</> : Division
|
||||
|
||||
=item *
|
||||
ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number
|
||||
of args)
|
||||
C<%> : Modulo
|
||||
|
||||
=item *
|
||||
CEIL: Ceiling (unary)
|
||||
C<^> : Exponential
|
||||
|
||||
=item *
|
||||
FLOOR: Floor (unary)
|
||||
|
||||
=item *
|
||||
FMOD: Floating point modulo (binary) Added in 7.0.8
|
||||
|
||||
=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)
|
||||
C<**> : Exponential
|
||||
|
||||
=back
|
||||
|
||||
=head3 Trigonometric Operators
|
||||
=head3 Algebraic Functions
|
||||
|
||||
When functions take more than one argument, a comma separator must appear
|
||||
between them.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
SIN: Sine
|
||||
C<ABS (arg)> : Absolute value
|
||||
|
||||
=item *
|
||||
SINH: Hyperbolic sine
|
||||
C<EXP (arg)> : Exponential function
|
||||
|
||||
=item *
|
||||
ASIN: Arc sine
|
||||
C<FMOD (num, den)> : Floating point modulo. Added in 7.0.8
|
||||
|
||||
=item *
|
||||
COS: Cosine
|
||||
C<LN (arg)> : Natural log
|
||||
|
||||
=item *
|
||||
COSH: Hyperbolic cosine
|
||||
C<LOG (arg)> : Log base 10
|
||||
|
||||
=item *
|
||||
ACOS: Arc cosine
|
||||
C<LOGE (arg)> : Natural log
|
||||
|
||||
=item *
|
||||
TAN: Tangent
|
||||
C<MIN (any number of args)> : Minimum
|
||||
|
||||
=item *
|
||||
TANH: Hyperbolic tangent
|
||||
C<MAX (any number of args)> : Maximum
|
||||
|
||||
=item *
|
||||
ATAN: Arc tangent
|
||||
C<SQR (arg)> : Square root
|
||||
|
||||
=item *
|
||||
C<SQRT (arg)> : Square root
|
||||
|
||||
=back
|
||||
|
||||
=head3 Trigonometric Functions
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<SIN (arg)> : Sine
|
||||
|
||||
=item *
|
||||
C<ASIN (arg)> : Arc sine
|
||||
|
||||
=item *
|
||||
C<COS (arg)> : Cosine
|
||||
|
||||
=item *
|
||||
C<ACOS (arg)> : Arc cosine
|
||||
|
||||
=item *
|
||||
C<TAN (arg)> : Tangent
|
||||
|
||||
=item *
|
||||
C<ATAN (arg)> : Arc tangent
|
||||
|
||||
=item *
|
||||
C<ATAN2 (den, num)> : 2-parameter Arc tangent. Arg's are reversed to ANSI C
|
||||
|
||||
=back
|
||||
|
||||
=head3 Hyperbolic Trigonometry Functions
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<SINH (arg)> : Hyperbolic sine
|
||||
|
||||
=item *
|
||||
C<COSH (arg)> : Hyperbolic cosine
|
||||
|
||||
=item *
|
||||
C<TANH (arg)> : Hyperbolic tangent
|
||||
|
||||
=back
|
||||
|
||||
=head3 Numeric Functions
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<CEIL (arg)> : Ceiling
|
||||
|
||||
=item *
|
||||
C<FLOOR (arg)> : Floor
|
||||
|
||||
=item *
|
||||
C<NINT (arg)> : Round to nearest integer
|
||||
|
||||
=item *
|
||||
C<ISINF (arg)> : returns non-zero if any argument is Inf
|
||||
|
||||
=item *
|
||||
C<ISNAN (any number of args)> : returns non-zero (true) if any argument is NaN
|
||||
or Inf
|
||||
|
||||
=item *
|
||||
C<FINITE (any number of args)> : returns non-zero (true) if none of the
|
||||
arguments are NaN or Inf
|
||||
|
||||
=back
|
||||
|
||||
=head3 Boolean/Logical Operators
|
||||
|
||||
These operators use their arguments as a true (non-zero) or false (zero) value.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<&&> : And, infix binary
|
||||
|
||||
=item *
|
||||
C<||> : Or, infix binary
|
||||
|
||||
=item *
|
||||
C<!> : Not, unary prefix
|
||||
|
||||
=back
|
||||
|
||||
=head3 Bitwise Operators
|
||||
|
||||
Mostly infix binary, the arguments are converted to a 32-bit integer, the
|
||||
operator is applied, and the result converted back into a double.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<&> : Bitwise and
|
||||
|
||||
=item *
|
||||
C<|> : Bitwise or
|
||||
|
||||
=item *
|
||||
C<~> : Bitwise not or one's complement, unary prefix
|
||||
|
||||
=item *
|
||||
C<<< << >>> : Arithmetic shift left
|
||||
|
||||
=item *
|
||||
C<<< >> >>> : Arithmetic shift right
|
||||
|
||||
=item *
|
||||
C<<<< >>> >>>> : Logical shift right
|
||||
|
||||
=item *
|
||||
C<AND> : Bitwise and
|
||||
|
||||
=item *
|
||||
C<OR> : Bitwise or
|
||||
|
||||
=item *
|
||||
C<XOR> : Bitwise exclusive or
|
||||
|
||||
=item *
|
||||
C<NOT> : Bitwise not or one's complement, unary prefix
|
||||
|
||||
=back
|
||||
|
||||
=head3 Relational Operators
|
||||
|
||||
These are all infix binary operators.
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
@@ -273,59 +375,17 @@ C<<< <= >>> : Less than or equal to
|
||||
=item *
|
||||
C<<< < >>> : Less than
|
||||
|
||||
=item *
|
||||
C<<< != >>> : Not equal to
|
||||
|
||||
=item *
|
||||
C<<< # >>> : Not equal to
|
||||
|
||||
=item *
|
||||
C<<< = >>> : Equal to
|
||||
|
||||
=back
|
||||
|
||||
=head3 Logical Operators
|
||||
|
||||
=over 1
|
||||
C<<< == >>> : Equal to
|
||||
|
||||
=item *
|
||||
&& : And
|
||||
|
||||
=item *
|
||||
|| : Or
|
||||
|
||||
=item *
|
||||
! : Not
|
||||
|
||||
=back
|
||||
|
||||
=head3 Bitwise Operators
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
C<|> : Bitwise Or
|
||||
|
||||
=item *
|
||||
C<&> : Bitwise And
|
||||
|
||||
=item *
|
||||
OR : Bitwise Or
|
||||
|
||||
=item *
|
||||
AND : Bitwise And
|
||||
|
||||
=item *
|
||||
XOR : Bitwise Exclusive Or
|
||||
|
||||
=item *
|
||||
C<~> : One's Complement
|
||||
|
||||
=item *
|
||||
C<<< << >>> : Arithmetic Left Shift
|
||||
|
||||
=item *
|
||||
C<<< >> >>> : Arithmetic Right Shift
|
||||
|
||||
=item *
|
||||
C<<<< >>> >>>> : Logical Right Shift
|
||||
C<<< = >>> : Equal to (not assignment)
|
||||
|
||||
=back
|
||||
|
||||
@@ -340,22 +400,24 @@ C<:=> : assigns a value (right hand side) to a variable (i.e. field)
|
||||
|
||||
=head3 Parentheses, Comma, and Semicolon
|
||||
|
||||
The open and close parentheses are supported. Nested parentheses are
|
||||
supported.
|
||||
The open C<(> and close parentheses C<)> are supported to override precedence
|
||||
rules in a sub-expression.
|
||||
Nested parentheses are supported to significant depth.
|
||||
|
||||
The comma is supported when used to separate the arguments of a binary
|
||||
function.
|
||||
The comma C<,> is required to separate the arguments of a function.
|
||||
|
||||
The semicolon is used to separate expressions. Although only one
|
||||
traditional calculation expression is allowed, multiple assignment
|
||||
expressions are allowed.
|
||||
The semicolon C<;> is used to value separate expressions.
|
||||
Exactly one value expression must be present, but multiple assignment
|
||||
expressions may be included before and/or after the value expression.
|
||||
|
||||
=head3 Conditional Expression
|
||||
=head3 Conditional Operator
|
||||
|
||||
The C language's question mark operator is supported. The format is:
|
||||
C<condition ? True result : False result>
|
||||
The C language's question mark colon C<?:> ternary operator is supported.
|
||||
The format is:
|
||||
|
||||
=head3 Expression Examples
|
||||
I<condition> C<?> I<true-expression> C<:> I<false-expression>
|
||||
|
||||
=head2 Expression Examples
|
||||
|
||||
=head3 Algebraic
|
||||
|
||||
@@ -396,21 +458,21 @@ Result is C<F + L + 10> if C<<< (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:
|
||||
Prior to Base 3.14.9 it was legal to omit the colon C<:> and the second (else)
|
||||
part of the conditional, like this:
|
||||
|
||||
C<(A + B)<(C + D) ? E>
|
||||
C<<< (A + B)<(C + D) ? E >>>
|
||||
|
||||
=over 1
|
||||
|
||||
=item
|
||||
Result is E if (A + B)<(C + D)
|
||||
=item *
|
||||
Result is E if C<<< (A + B)<(C + D) >>>
|
||||
|
||||
=item
|
||||
Result is unchanged if (A + B)>=(C + D)
|
||||
=item *
|
||||
Result is unchanged if C<<< (A + B)>=(C + D) >>>
|
||||
|
||||
From 3.14.9 onwards, this expression must be written as
|
||||
C<(A + B) < (C + D) ? E : VAL>
|
||||
C<<< (A + B) < (C + D) ? E : VAL >>>
|
||||
|
||||
=back
|
||||
|
||||
@@ -432,7 +494,7 @@ Convert A to integer
|
||||
Convert B to integer
|
||||
|
||||
=item *
|
||||
Bitwise And A and B
|
||||
Bitwise A C<and> B
|
||||
|
||||
=item *
|
||||
Convert result to floating point
|
||||
@@ -511,13 +573,14 @@ 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.
|
||||
If the OEVT field isn't empty and the condition in the OOPT field is met, the
|
||||
record will post the corresponding named 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 enters an INVALID alarm status. The options are
|
||||
@@ -595,7 +658,7 @@ conditions.
|
||||
|
||||
The HYST field defines an alarm deadband for each limit.
|
||||
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
for a complete explanation of record alarms and of the standard fields.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
||||
to alarms that are common to all record types.
|
||||
@@ -1017,60 +1080,60 @@ manner for the VAL field.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(PREC,DBF_SHORT) {
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(HOPR,DBF_DOUBLE) {
|
||||
prompt("High Operating Rng")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_DOUBLE) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(HIHI,DBF_DOUBLE) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_DOUBLE) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_DOUBLE) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_DOUBLE) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
@@ -1078,7 +1141,7 @@ manner for the VAL field.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
@@ -1086,7 +1149,7 @@ manner for the VAL field.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
@@ -1094,7 +1157,7 @@ manner for the VAL field.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_DOUBLE) {
|
||||
@@ -1407,26 +1470,31 @@ The C<process()> routine implements the following algorithm:
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
Fetch all arguments.
|
||||
|
||||
=item 2.
|
||||
|
||||
Call routine C<calcPerform()>, which calculates VAL from the prefix version
|
||||
of the expression given in CALC. If C<calcPerform()> 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.
|
||||
|
||||
Determine if the Output Execution Option (OOPT) is met. If 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<execOutput()> routine below.
|
||||
|
||||
=item 5.
|
||||
|
||||
Check to see if monitors should be invoked.
|
||||
|
||||
=over
|
||||
@@ -1447,6 +1515,7 @@ NSEV and NSTA are reset to 0
|
||||
=back
|
||||
|
||||
=item 6.
|
||||
|
||||
If no output delay was specified, scan forward link if necessary, set PACT
|
||||
FALSE, and return.
|
||||
|
||||
@@ -1457,19 +1526,23 @@ FALSE, and return.
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
If DOPT field specifies the use of OCAL, call the routine C<calcPerform()>
|
||||
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).
|
||||
put the value of OVAL to the OUT link and post the event named in OEVT (if
|
||||
not empty).
|
||||
|
||||
=item 4.
|
||||
|
||||
If an output delay was implemented, process the forward link.
|
||||
|
||||
=back
|
||||
|
||||
@@ -107,7 +107,7 @@ static void monitor(compressRecord *prec)
|
||||
db_post_events(prec, &prec->nuse, monitor_mask);
|
||||
prec->ouse = prec->nuse;
|
||||
}
|
||||
db_post_events(prec, (void*)&prec->val, monitor_mask);
|
||||
db_post_events(prec, &prec->val, monitor_mask);
|
||||
}
|
||||
|
||||
static void put_value(compressRecord *prec, double *psource, int n)
|
||||
|
||||
@@ -88,7 +88,7 @@ As stated above, the ALG field specifies which algorithm to be performed on the
|
||||
The INP should be a database or channel access link. Though INP can be a
|
||||
constant, the data compression algorithms are supported only when INP is a
|
||||
database link. See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on specifying links.
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ holds the average of the first element of INP over N samples, VAL[1] holds the
|
||||
average of the next element of INP over N samples, and so on. The following
|
||||
shows the equation:
|
||||
|
||||
=for comment Latex form of equation bellow : VAL[i] \leftarrow \frac{1}{N}\sum_{n=1}^NINP_{n}[i]
|
||||
=for comment Latex form of equation below : VAL[i] \leftarrow \frac{1}{N}\sum_{n=1}^NINP_{n}[i]
|
||||
|
||||
=begin html
|
||||
|
||||
@@ -449,26 +449,26 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_DOUBLE) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(PREC,DBF_SHORT) {
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(EGU,DBF_STRING) {
|
||||
prompt("Engineering Units")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(OFF,DBF_ULONG) {
|
||||
prompt("Offset")
|
||||
|
||||
@@ -140,7 +140,7 @@ static long process(struct dbCommon *pcommon)
|
||||
break;
|
||||
default :
|
||||
status=-1;
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"dfanout:process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,12 @@
|
||||
|
||||
The Data Fanout or "dfanout" record is used to forward data to up to
|
||||
16 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
|
||||
capability to forward data has been added to it. It has no associated
|
||||
device support.
|
||||
|
||||
Since 7.0.10 the number of output links has been increased
|
||||
from 8 to 16 and IVOA and IVOV fields have been added.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
@@ -39,7 +42,7 @@ These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
=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
|
||||
originates, i.e., the data which is to be forwarded 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<closed_loop>, the desired output is retrieved from the link
|
||||
@@ -60,7 +63,7 @@ undergoes no conversions before it is sent out to the output links.
|
||||
|
||||
The OUTA-OUTP fields specify where VAL is to be sent. Each field that is to
|
||||
forward data must specify an address to another record. See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on specifying links.
|
||||
|
||||
The SELL, SELM, and SELN fields specify which output links are to be
|
||||
@@ -140,7 +143,7 @@ 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<Alarm Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
for a complete explanation of record alarms and of the standard fields.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
||||
to alarms that are common to all record types.
|
||||
@@ -153,8 +156,8 @@ 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
|
||||
every time the value changes, a monitor will be triggered; if they have a
|
||||
value of -1, every time the record is scanned, monitors are triggered. See
|
||||
L<Monitor Specification> for a complete explanation of monitors.
|
||||
|
||||
=fields ADEL, MDEL
|
||||
@@ -162,7 +165,7 @@ L<Monitor Specification> for a complete explanation of monitors.
|
||||
=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
|
||||
fanout record. They are not configurable. They are used to implement the
|
||||
hysteresis factors for monitor callbacks.
|
||||
|
||||
=fields LALM, ALST, MLST
|
||||
@@ -194,82 +197,82 @@ hysteresis factors for monitor callbacks.
|
||||
}
|
||||
field(OUTA,DBF_OUTLINK) {
|
||||
prompt("Output Spec A")
|
||||
promptgroup("50 - Outputs A-H")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTB,DBF_OUTLINK) {
|
||||
prompt("Output Spec B")
|
||||
promptgroup("50 - Outputs A-H")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTC,DBF_OUTLINK) {
|
||||
prompt("Output Spec C")
|
||||
promptgroup("50 - Outputs A-H")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTD,DBF_OUTLINK) {
|
||||
prompt("Output Spec D")
|
||||
promptgroup("50 - Outputs A-H")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTE,DBF_OUTLINK) {
|
||||
prompt("Output Spec E")
|
||||
promptgroup("50 - Outputs A-H")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTF,DBF_OUTLINK) {
|
||||
prompt("Output Spec F")
|
||||
promptgroup("50 - Outputs A-H")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTG,DBF_OUTLINK) {
|
||||
prompt("Output Spec G")
|
||||
promptgroup("50 - Outputs A-H")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTH,DBF_OUTLINK) {
|
||||
prompt("Output Spec H")
|
||||
promptgroup("50 - Outputs A-H")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTI,DBF_OUTLINK) {
|
||||
prompt("Output Spec I")
|
||||
promptgroup("51 - Outputs I-P")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTJ,DBF_OUTLINK) {
|
||||
prompt("Output Spec J")
|
||||
promptgroup("51 - Outputs I-P")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTK,DBF_OUTLINK) {
|
||||
prompt("Output Spec K")
|
||||
promptgroup("51 - Outputs I-P")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTL,DBF_OUTLINK) {
|
||||
prompt("Output Spec L")
|
||||
promptgroup("51 - Outputs I-P")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTM,DBF_OUTLINK) {
|
||||
prompt("Output Spec M")
|
||||
promptgroup("51 - Outputs I-P")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTN,DBF_OUTLINK) {
|
||||
prompt("Output Spec N")
|
||||
promptgroup("51 - Outputs I-P")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTO,DBF_OUTLINK) {
|
||||
prompt("Output Spec O")
|
||||
promptgroup("51 - Outputs I-P")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(OUTP,DBF_OUTLINK) {
|
||||
prompt("Output Spec P")
|
||||
promptgroup("51 - Outputs I-P")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(DOL,DBF_INLINK) {
|
||||
@@ -288,60 +291,60 @@ hysteresis factors for monitor callbacks.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(PREC,DBF_SHORT) {
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(HOPR,DBF_DOUBLE) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_DOUBLE) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(HIHI,DBF_DOUBLE) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_DOUBLE) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_DOUBLE) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_DOUBLE) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
@@ -349,7 +352,7 @@ hysteresis factors for monitor callbacks.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
@@ -357,7 +360,7 @@ hysteresis factors for monitor callbacks.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
@@ -365,7 +368,7 @@ hysteresis factors for monitor callbacks.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_DOUBLE) {
|
||||
@@ -404,7 +407,7 @@ hysteresis factors for monitor callbacks.
|
||||
interest(2)
|
||||
menu(menuIvoa)
|
||||
}
|
||||
field(IVOV,DBF_LONG) {
|
||||
field(IVOV,DBF_DOUBLE) {
|
||||
prompt("INVALID output value")
|
||||
promptgroup("50 - Output")
|
||||
interest(2)
|
||||
@@ -487,6 +490,7 @@ Alarms ranges are checked against the contents of the VAL field.
|
||||
|
||||
Check severity and then send the value through the OUTA-OUTP links, depending
|
||||
on the setting of SELM and the value in SELN.
|
||||
|
||||
See L<Invalid Output Action Fields|dbCommonOutput/Invalid Output Action Fields>
|
||||
for information on how INVALID alarms affect output records.
|
||||
|
||||
|
||||
@@ -9,9 +9,12 @@
|
||||
|
||||
=title Event Record (event)
|
||||
|
||||
The normal use for this record type is to post an event and/or process a
|
||||
forward link. Device support for this record can provide a hardware interrupt
|
||||
handler routine for I/O Event-scanned records.
|
||||
The normal use for this record type is to post a soft-event and/or process a
|
||||
forward link.
|
||||
C<Soft Channel> device support is provided to allow the soft-event name to be
|
||||
read from an input link.
|
||||
Hardware device support for this record can provide an interrupt handler routine
|
||||
to trigger processing of the record when an I/O Intr event occurs.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
@@ -37,18 +40,31 @@ recordtype(event) {
|
||||
=head3 Scan Parameters
|
||||
|
||||
The event record has the standard fields for specifying under what circumstances
|
||||
it will be processed.
|
||||
it should be processed.
|
||||
These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
|
||||
=fields SCAN, PHAS, EVNT, PRIO, PINI
|
||||
|
||||
=head3 Event Number Parameters
|
||||
=head3 Event Name Parameters
|
||||
|
||||
The VAL field contains the event number read by the device support routines. It
|
||||
is this number which is posted. For records that use C<Soft Channel> device
|
||||
support, it can be configured before run-time or set via dbPuts.
|
||||
The VAL field is a string (prior to the Base-3.15.1 release it was a short
|
||||
integer) providing the name of an IOC soft-event.
|
||||
This named soft-event gets posted whenever the record is processed.
|
||||
|
||||
=fields VAL
|
||||
When the soft-event name is known at design time, the VAL field should be set to
|
||||
the name in a loaded database file.
|
||||
Soft-event names do not have to be registered before use, a handle for the name
|
||||
is automatically created and stored when a name is first seen and the same
|
||||
handle returned later if the same name is re-used.
|
||||
|
||||
The EPVT field holds the handle for the soft-event named in the VAL field.
|
||||
Looking up the handle for a soft-event name is fast and uses a hash table.
|
||||
|
||||
For records that use the default C<Soft Channel> device support, the soft-event
|
||||
name can be fetched through the INP field link, written to the VAL field and the
|
||||
handle looked up during record processing.
|
||||
|
||||
=fields VAL, EPVT
|
||||
|
||||
=cut
|
||||
|
||||
@@ -69,16 +85,18 @@ support, it can be configured before run-time or set via dbPuts.
|
||||
|
||||
=head3 Input Specification
|
||||
|
||||
The device support routines use the address in this record to obtain input. For
|
||||
records that provide an interrupt handler, the INP field should specify the
|
||||
The device support routines use the address in this record to obtain input.
|
||||
For records that provide an interrupt handler, the INP field should specify the
|
||||
address of the I/O card, and the DTYP field should specify a valid device
|
||||
support module. Be aware that the address format differs according to the card
|
||||
type used. See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
support module.
|
||||
|
||||
The address format differs according to the card type used. See
|
||||
L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on the format of hardware addresses and specifying links.
|
||||
|
||||
For soft records, the INP field can be a constant, a database link, or a channel
|
||||
access link. For soft records, the DTYP field should specify C<Soft Channel>.
|
||||
access link, and the DTYP field should be empty or set to C<Soft Channel>.
|
||||
|
||||
=fields INP, DTYP
|
||||
|
||||
@@ -93,24 +111,27 @@ access link. For soft records, the DTYP field should specify C<Soft Channel>.
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
|
||||
Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
|
||||
Parameters>
|
||||
for more on the record name (NAME) and description (DESC) fields.
|
||||
|
||||
=fields NAME, DESC
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The Event record has the alarm parameters common to all record types. L<Alarm
|
||||
Fields> lists other fields related to alarms that are common to all record
|
||||
types.
|
||||
The Event record has the alarm parameters common to all record types.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related to alarms
|
||||
that are common to all record types.
|
||||
|
||||
=fields STAT, SEVR, AMSG, NSTA, NSEV, NAMSG, ACKS, ACKT, UDF
|
||||
|
||||
=head3 Simulation Mode Parameters
|
||||
|
||||
The following fields are used to operate the event record in the simulation
|
||||
mode. See L<Fields Common to Many Record Types> for more information on these
|
||||
fields.
|
||||
mode.
|
||||
See L<Fields Common to Input Record Types|dbCommonInput/Input Simulation Fields>
|
||||
for more information on these fields.
|
||||
|
||||
=fields SIOL, SVAL, SIML, SIMM, SIMS
|
||||
=fields SIOL, SVAL, SIML, SIMM, SIMS, SSCN, SDLY
|
||||
|
||||
=cut
|
||||
|
||||
@@ -179,38 +200,50 @@ initialized if SIOL is CONSTANT or PV_LINK.
|
||||
|
||||
If device support includes C<init_record()>, it is called.
|
||||
|
||||
The string in VAL is converted to a soft-event handle in EPVT.
|
||||
|
||||
=head4 process
|
||||
|
||||
See next section.
|
||||
|
||||
=head4 special
|
||||
|
||||
When the VAL field is set, the new string is converted to a soft-event handle in
|
||||
EPVT.
|
||||
|
||||
=head3 Record Processing
|
||||
|
||||
Routine process implements the following algorithm:
|
||||
Routine C<process()> implements the following algorithm:
|
||||
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
readValue is called. See L<Input Records> for more information.
|
||||
C<readValue()> is called.
|
||||
See L<Input Records|dbCommonInput/Input Records> for more information.
|
||||
|
||||
=item 2.
|
||||
|
||||
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.
|
||||
If PACT has changed to TRUE, the device support read routine has started
|
||||
but has not completed reading a new soft-event name.
|
||||
In this case, the processing routine returns immediately, leaving PACT TRUE.
|
||||
|
||||
=item 3.
|
||||
|
||||
If VAL E<gt> 0, post event number VAL.
|
||||
Set PACT to TRUE.
|
||||
|
||||
=item 4.
|
||||
|
||||
Check to see if monitors should be invoked. Alarm monitors are invoked if the
|
||||
alarm status or severity has chanet to 0.
|
||||
Post the soft-event whose handle is in EPVT.
|
||||
|
||||
=item 5.
|
||||
|
||||
Scan forward link if necessary, set PACT FALSE, and return.
|
||||
Check to see if monitors should be invoked.
|
||||
Alarm monitors are invoked if the new alarm status or severity are non-zero.
|
||||
|
||||
=item 6.
|
||||
|
||||
Scan forward link if set, set PACT to FALSE, and return.
|
||||
|
||||
=back
|
||||
|
||||
@@ -221,13 +254,15 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
Each record must have an associated set of device support routines. The device
|
||||
support routines are primarily interested in the following fields:
|
||||
|
||||
=fields PACT, DPVT, UDF, NSEV, NSTA, INP, PRIO
|
||||
=fields PACT, DPVT, UDF, NSEV, NSTA, INP, PRIO, VAL, EPVT
|
||||
|
||||
=head3 Device Support Routines
|
||||
|
||||
Device support consists of the following routines:
|
||||
|
||||
=head4 long report(int level)
|
||||
=head4 report
|
||||
|
||||
long report(int level)
|
||||
|
||||
This optional routine is called by the IOC command C<dbior> and is passed the
|
||||
report level that was requested by the user.
|
||||
@@ -235,9 +270,11 @@ It should print a report on the state of the device support to stdout.
|
||||
The C<level> parameter may be used to output increasingly more detailed
|
||||
information at higher levels, or to select different types of information with
|
||||
different levels.
|
||||
Level zero should print no more than a small summary.
|
||||
Level zero should print only a 1-line summary.
|
||||
|
||||
=head4 long init(int after)
|
||||
=head4 init
|
||||
|
||||
long init(int after)
|
||||
|
||||
This optional routine is called twice at IOC initialization time.
|
||||
The first call happens before any of the C<init_record()> calls are made, with
|
||||
@@ -247,23 +284,25 @@ with C<after> set to 1.
|
||||
|
||||
=head4 init_record
|
||||
|
||||
init_record(precord)
|
||||
long init_record(precord)
|
||||
|
||||
This routine is optional. If provided, it is called by the record support
|
||||
C<init_record()> routine.
|
||||
|
||||
=head4 get_ioint_info
|
||||
|
||||
get_ioint_info(int cmd, struct dbCommon *precord, IOSCANPVT *ppvt)
|
||||
long get_ioint_info(int cmd, struct dbCommon *precord, IOSCANPVT *ppvt)
|
||||
|
||||
This routine is called by the ioEventScan system each time the record is added
|
||||
or deleted from an I/O event scan list. C<cmd> 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.
|
||||
This routine is called by the dbScan system each time the record is added
|
||||
or deleted from an I/O event scan list.
|
||||
C<cmd> has the value (0, 1) if the record is being (added to, deleted from) an
|
||||
I/O event list.
|
||||
The C<get_ioint_info> routine is optional, but must be provided by any device
|
||||
support that implements C<I/O Intr> scanning for the event record type.
|
||||
|
||||
=head4 read_event
|
||||
|
||||
read_event(precord)
|
||||
long read_event(precord)
|
||||
|
||||
This routine returns the following values:
|
||||
|
||||
@@ -281,15 +320,13 @@ Other: Error.
|
||||
|
||||
=head3 Device Support For Soft Records
|
||||
|
||||
The C<Soft Channel> device support module is available. The INP link type must
|
||||
be either CONSTANT, DB_LINK, or CA_LINK.
|
||||
A C<Soft Channel> device support module is available.
|
||||
The INP link field is used to fetch the soft-event name.
|
||||
|
||||
If the INP link type is CONSTANT, then the constant value is stored into VAL by
|
||||
C<init_record()>, and UDF is set to FALSE. If the INP link type is PV_LINK, then
|
||||
dbCaAddInlink is called by C<init_record()>.
|
||||
The C<read_event()> routine reads a string through INP and stores it in VAL,
|
||||
then looks up the named soft-event handle and sets EPVT.
|
||||
|
||||
C<read_event> calls recGblGetLinkValue to read the current value of VAL. See
|
||||
L<Input Records> for details on soft input.
|
||||
See L<Input Records|dbCommonInput/Input Records> for details on soft input.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ static void wdogCallback(epicsCallback *arg)
|
||||
if (prec->mcnt > 0){
|
||||
dbScanLock((struct dbCommon *)prec);
|
||||
recGblGetTimeStamp(prec);
|
||||
db_post_events(prec, (void*)&prec->val, DBE_VALUE | DBE_LOG);
|
||||
db_post_events(prec, &prec->val, DBE_VALUE | DBE_LOG);
|
||||
prec->mcnt = 0;
|
||||
dbScanUnlock((struct dbCommon *)prec);
|
||||
}
|
||||
@@ -291,7 +291,7 @@ static void monitor(histogramRecord *prec)
|
||||
}
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask)
|
||||
db_post_events(prec, (void*)&prec->val, monitor_mask);
|
||||
db_post_events(prec, &prec->val, monitor_mask);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ alarms that are common to all record types.
|
||||
|
||||
The MDEL field implements the monitor count deadband. Only when MCNT is greater
|
||||
than the value given to MDEL are monitors triggered, MCNT being the number of
|
||||
counts since the last time the record was processed. If MDEL is -1, everytime
|
||||
counts since the last time the record was processed. If MDEL is -1, every time
|
||||
the record is processed, a monitor is triggered regardless.
|
||||
|
||||
If SDEL is greater than 0, it causes a callback routine to be called. The number
|
||||
|
||||
@@ -102,12 +102,12 @@ static long init_record(dbCommon *pcommon, int pass)
|
||||
recGblInitConstantLink(&prec->siol, DBF_INT64, &prec->sval);
|
||||
|
||||
if(!(pdset = (int64indset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"int64in: init_record");
|
||||
recGblRecordError(S_dev_noDSET, prec, "int64in: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* must have read_int64in function defined */
|
||||
if ((pdset->common.number < 5) || (pdset->read_int64in == NULL)) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"int64in: init_record");
|
||||
recGblRecordError(S_dev_missingSup, prec, "int64in: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if (pdset->common.init_record) {
|
||||
@@ -129,7 +129,7 @@ static long process(dbCommon *pcommon)
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_int64in==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"read_int64in");
|
||||
recGblRecordError(S_dev_missingSup, prec, "read_int64in");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
timeLast = prec->time;
|
||||
|
||||
@@ -135,47 +135,47 @@ monitoring deadband functionality.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(HOPR,DBF_INT64) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_INT64) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(HIHI,DBF_INT64) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_INT64) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_INT64) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_INT64) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
|
||||
@@ -98,12 +98,12 @@ static long init_record(dbCommon *pcommon, int pass)
|
||||
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
|
||||
|
||||
if(!(pdset = (int64outdset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"int64out: init_record");
|
||||
recGblRecordError(S_dev_noDSET, prec, "int64out: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* must have write_int64out functions defined */
|
||||
if ((pdset->common.number < 5) || (pdset->write_int64out == NULL)) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"int64out: init_record");
|
||||
recGblRecordError(S_dev_missingSup, prec, "int64out: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if (prec->dol.type == CONSTANT) {
|
||||
@@ -129,7 +129,7 @@ static long process(dbCommon *pcommon)
|
||||
|
||||
if( (pdset==NULL) || (pdset->write_int64out==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"write_int64out");
|
||||
recGblRecordError(S_dev_missingSup, prec, "write_int64out");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if (!prec->pact) {
|
||||
@@ -170,7 +170,7 @@ static long process(dbCommon *pcommon)
|
||||
break;
|
||||
default :
|
||||
status=-1;
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"int64out:process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,61 +171,61 @@ monitoring deadband functionality.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(DRVH,DBF_INT64) {
|
||||
prompt("Drive High Limit")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_control_double
|
||||
}
|
||||
field(DRVL,DBF_INT64) {
|
||||
prompt("Drive Low Limit")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_control_double
|
||||
}
|
||||
field(HOPR,DBF_INT64) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_INT64) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(HIHI,DBF_INT64) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_INT64) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_INT64) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_INT64) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
|
||||
@@ -133,7 +133,7 @@ static long process(struct dbCommon *pcommon)
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_longin==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"read_longin");
|
||||
recGblRecordError(S_dev_missingSup, prec, "read_longin");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
timeLast = prec->time;
|
||||
|
||||
@@ -93,8 +93,8 @@ alarms that are common to all record types.
|
||||
These parameters are used to determine when to send monitors placed on the value
|
||||
field. The monitors are sent when the value field exceeds the last monitored
|
||||
field (see the next section) by the appropriate deadband. 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. The
|
||||
value of zero, every time the value changes, a monitor will be triggered; if they
|
||||
have a value of -1, every time the record is scanned, monitors are triggered. The
|
||||
ADEL field is used by archive monitors and the MDEL field for all other types of
|
||||
monitors.
|
||||
|
||||
@@ -345,53 +345,54 @@ sets UDF to FALSE. read_longin returns the status of C<recGblGetLinkValue>.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(HOPR,DBF_LONG) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_LONG) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(HIHI,DBF_LONG) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_LONG) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_LONG) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_LONG) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
@@ -399,6 +400,7 @@ sets UDF to FALSE. read_longin returns the status of C<recGblGetLinkValue>.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
@@ -406,6 +408,7 @@ sets UDF to FALSE. read_longin returns the status of C<recGblGetLinkValue>.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
@@ -413,6 +416,7 @@ sets UDF to FALSE. read_longin returns the status of C<recGblGetLinkValue>.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_LONG) {
|
||||
|
||||
@@ -139,7 +139,7 @@ static long process(struct dbCommon *pcommon)
|
||||
|
||||
if( (pdset==NULL) || (pdset->write_longout==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"write_longout");
|
||||
recGblRecordError(S_dev_missingSup, prec, "write_longout");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if (!prec->pact) {
|
||||
@@ -179,7 +179,7 @@ static long process(struct dbCommon *pcommon)
|
||||
break;
|
||||
default :
|
||||
status=-1;
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"longout:process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ channel access link. If the link is a constant, the result is no output. The
|
||||
DTYP field must then specify the C<<< Soft Channel >>> device support routine.
|
||||
|
||||
See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on the format of hardware addresses and database links.
|
||||
|
||||
=fields OUT, DTYP, OOPT, OOCH
|
||||
@@ -187,33 +187,33 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(DRVH,DBF_LONG) {
|
||||
prompt("Drive High Limit")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_control_double
|
||||
}
|
||||
field(DRVL,DBF_LONG) {
|
||||
prompt("Drive Low Limit")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_control_double
|
||||
}
|
||||
field(HOPR,DBF_LONG) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_LONG) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
|
||||
=head3 Alarm Parameters
|
||||
@@ -233,7 +233,7 @@ The HYST field sets an alarm deadband around each limit alarm.
|
||||
For an explanation of the IVOA and IVOV fields, see
|
||||
L<Invalid Output Action Fields|dbCommonOutput/Invalid Output Action Fields>.
|
||||
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
for a complete explanation of record alarms and of the standard fields.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
||||
to alarms that are common to all record types.
|
||||
@@ -247,34 +247,35 @@ to alarms that are common to all record types.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_LONG) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_LONG) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_LONG) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
@@ -282,6 +283,7 @@ to alarms that are common to all record types.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
@@ -289,6 +291,7 @@ to alarms that are common to all record types.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
@@ -296,6 +299,7 @@ to alarms that are common to all record types.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_LONG) {
|
||||
@@ -308,9 +312,9 @@ to alarms that are common to all record types.
|
||||
|
||||
These parameters are used to determine when to send monitors placed on the value
|
||||
field. The monitors are sent when the value field exceeds the last monitored
|
||||
field by the appropriate delta. If these fields have a value of zero, everytime
|
||||
field by the appropriate delta. If these fields have a value of zero, every time
|
||||
the value changes, a monitor will be triggered; if they have a value of -1,
|
||||
everytime the record is scanned, monitors are triggered. The ADEL field is the
|
||||
every time the record is scanned, monitors are triggered. The ADEL field is the
|
||||
delta for archive monitors, and the MDEL field is the delta for all other types
|
||||
of monitors. See L<Monitor Specification> for a complete explanation of
|
||||
monitors.
|
||||
|
||||
@@ -102,6 +102,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
promptgroup("40 - Input")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
|
||||
@@ -276,7 +276,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(ONST,DBF_STRING) {
|
||||
prompt("One String")
|
||||
@@ -285,7 +285,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(TWST,DBF_STRING) {
|
||||
prompt("Two String")
|
||||
@@ -294,7 +294,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(THST,DBF_STRING) {
|
||||
prompt("Three String")
|
||||
@@ -303,7 +303,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(FRST,DBF_STRING) {
|
||||
prompt("Four String")
|
||||
@@ -312,7 +312,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(FVST,DBF_STRING) {
|
||||
prompt("Five String")
|
||||
@@ -321,7 +321,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(SXST,DBF_STRING) {
|
||||
prompt("Six String")
|
||||
@@ -330,7 +330,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(SVST,DBF_STRING) {
|
||||
prompt("Seven String")
|
||||
@@ -339,7 +339,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(EIST,DBF_STRING) {
|
||||
prompt("Eight String")
|
||||
@@ -348,7 +348,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(NIST,DBF_STRING) {
|
||||
prompt("Nine String")
|
||||
@@ -357,7 +357,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(TEST,DBF_STRING) {
|
||||
prompt("Ten String")
|
||||
@@ -366,7 +366,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(ELST,DBF_STRING) {
|
||||
prompt("Eleven String")
|
||||
@@ -375,7 +375,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(TVST,DBF_STRING) {
|
||||
prompt("Twelve String")
|
||||
@@ -384,7 +384,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(TTST,DBF_STRING) {
|
||||
prompt("Thirteen String")
|
||||
@@ -393,7 +393,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(FTST,DBF_STRING) {
|
||||
prompt("Fourteen String")
|
||||
@@ -402,7 +402,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(FFST,DBF_STRING) {
|
||||
prompt("Fifteen String")
|
||||
@@ -411,7 +411,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
|
||||
=head3 Alarm Parameters
|
||||
@@ -436,7 +436,7 @@ state occurs, if set to MAJOR or MINOR.
|
||||
The other fields, when set to MAJOR or MINOR, trigger an alarm when VAL equals
|
||||
the corresponding state.
|
||||
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
for a complete explanation of record alarms and of the standard fields.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
||||
to alarms that are common to all record types.
|
||||
|
||||
@@ -16,7 +16,7 @@ It can accept boolean values in its 32 bit fields (B0-B9, BA-BF, B10-B19 and
|
||||
B1A-B1F), and converts them to a 32-bit signed integer in VAL which is provided
|
||||
to the device support. A zero value in a bit field becomes a zero bit in VAL, a
|
||||
non-zero value in a bit field becomes a one bit in VAL, with B0 being the least
|
||||
signficant bit and B1F the MSB/sign bit.
|
||||
significant bit and B1F the MSB/sign bit.
|
||||
|
||||
=recordtype mbboDirect
|
||||
|
||||
@@ -47,7 +47,7 @@ placed into the VAL field.
|
||||
|
||||
When OMSL is set to C<<< supervisory >>>, the DOL field is ignored during
|
||||
processing and the contents of VAL are used. A value to be output may thus be
|
||||
written direcly into the VAL field from elsewhere as long as the record is in
|
||||
written directly into the VAL field from elsewhere as long as the record is in
|
||||
C<<< supervisory >>> mode.
|
||||
|
||||
=fields OMSL, DOL, VAL
|
||||
@@ -89,7 +89,7 @@ For records that are to write values to hardware devices, the OUT output link
|
||||
must contain the address of the I/O card, and the DTYP field must specify
|
||||
the proper device support module. Be aware that the address format differs
|
||||
according to the I/O bus used. See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on the format of hardware addresses.
|
||||
|
||||
During record processing VAL is converted into RVAL, which is the actual 32-bit
|
||||
@@ -153,6 +153,7 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
promptgroup("50 - Output")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(DOL,DBF_INLINK) {
|
||||
prompt("Desired Output Link")
|
||||
@@ -299,7 +300,7 @@ the IVOV field to the output.
|
||||
See L<Invalid Output Action Fields|dbCommonOutput/Invalid Output Action Fields>
|
||||
for more information about IVOA and IVOV.
|
||||
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
for a complete explanation of record alarms and of the standard fields.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
||||
to alarms that are common to all record types.
|
||||
|
||||
@@ -354,7 +354,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(ONST,DBF_STRING) {
|
||||
prompt("One String")
|
||||
@@ -363,7 +363,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(TWST,DBF_STRING) {
|
||||
prompt("Two String")
|
||||
@@ -372,7 +372,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(THST,DBF_STRING) {
|
||||
prompt("Three String")
|
||||
@@ -381,7 +381,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(FRST,DBF_STRING) {
|
||||
prompt("Four String")
|
||||
@@ -390,7 +390,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(FVST,DBF_STRING) {
|
||||
prompt("Five String")
|
||||
@@ -399,7 +399,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(SXST,DBF_STRING) {
|
||||
prompt("Six String")
|
||||
@@ -408,7 +408,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(SVST,DBF_STRING) {
|
||||
prompt("Seven String")
|
||||
@@ -417,7 +417,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(EIST,DBF_STRING) {
|
||||
prompt("Eight String")
|
||||
@@ -426,7 +426,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(NIST,DBF_STRING) {
|
||||
prompt("Nine String")
|
||||
@@ -435,7 +435,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(TEST,DBF_STRING) {
|
||||
prompt("Ten String")
|
||||
@@ -444,7 +444,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(ELST,DBF_STRING) {
|
||||
prompt("Eleven String")
|
||||
@@ -453,7 +453,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(TVST,DBF_STRING) {
|
||||
prompt("Twelve String")
|
||||
@@ -462,7 +462,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(TTST,DBF_STRING) {
|
||||
prompt("Thirteen String")
|
||||
@@ -471,7 +471,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(FTST,DBF_STRING) {
|
||||
prompt("Fourteen String")
|
||||
@@ -480,7 +480,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(FFST,DBF_STRING) {
|
||||
prompt("Fifteen String")
|
||||
@@ -489,7 +489,7 @@ for more information on simulation mode and its fields.
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
size(26)
|
||||
prop(YES)
|
||||
prop(YES) # get_enum_str, get_enum_strs, put_enum_str
|
||||
}
|
||||
field(ZRSV,DBF_MENU) {
|
||||
prompt("State Zero Severity")
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
else \
|
||||
flags |= F_BADLNK
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ >= 5 || defined(__clang__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wformat-security"
|
||||
/* Intentionally passing non-const format string to epicsSnprintf() below.
|
||||
@@ -322,7 +322,7 @@ static void doPrintf(printfRecord *prec)
|
||||
prec->len = pval - prec->val;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ >= 5 || defined(__clang__)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
The printf record must specify the desired output string with embedded format
|
||||
specifiers in the FMT field. Plain characters are copied directly to the output
|
||||
string. A pair of percent characters 'C<%%>' are converted into a single percent
|
||||
character in the output string. A single precent character 'C<%>' introduces a
|
||||
character in the output string. A single percent character 'C<%>' introduces a
|
||||
format specifier and is followed by zero or more of the standard C<printf()>
|
||||
format flags and modifiers:
|
||||
|
||||
@@ -148,7 +148,7 @@ which type of the data is requested through the appropriate input link. As with
|
||||
C<printf()> a C<*> character may be used in the format to specify width and/or
|
||||
precision instead of numeric literals, in which case additional input links are
|
||||
used to provide the necessary integer parameter or parameters. See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on specifying links.
|
||||
|
||||
The formatted string is written to the VAL field. The maximum number of
|
||||
|
||||
@@ -150,14 +150,14 @@ static long get_precision(const DBADDR *paddr, long *precision)
|
||||
int i;
|
||||
|
||||
*precision = prec->prec;
|
||||
if(paddr->pfield==(void *)&prec->val){
|
||||
if(paddr->pfield==&prec->val){
|
||||
return(0);
|
||||
}
|
||||
pvalue = &prec->a;
|
||||
plvalue = &prec->la;
|
||||
for(i=0; i<SEL_MAX; i++, pvalue++, plvalue++) {
|
||||
if(paddr->pfield==(void *)&pvalue
|
||||
|| paddr->pfield==(void *)&plvalue){
|
||||
if(paddr->pfield==&pvalue
|
||||
|| paddr->pfield==&plvalue){
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,8 +133,8 @@ alarms that are common to all record types.
|
||||
These fields are configurable by the user. They are used as deadbands for the
|
||||
archiver and monitor calls for the VAL field. Unless, VAL changes by more than
|
||||
the value specified by each, then the respective monitors will not be called. If
|
||||
these fields have a value of zero, everytime the VAL changes, monitors are
|
||||
triggered; if they have a value of -1, everytime the record is processed,
|
||||
these fields have a value of zero, every time the VAL changes, monitors are
|
||||
triggered; if they have a value of -1, every time the record is processed,
|
||||
monitors are triggered.
|
||||
|
||||
=fields ADEL, MDEL
|
||||
@@ -299,6 +299,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
prompt("Display Precision")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES) # get_precision
|
||||
}
|
||||
field(NVL,DBF_INLINK) {
|
||||
prompt("Index Value Location")
|
||||
@@ -370,54 +371,54 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
prop(YES) # get_units
|
||||
}
|
||||
field(HOPR,DBF_DOUBLE) {
|
||||
prompt("High Operating Rng")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(LOPR,DBF_DOUBLE) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_graphic_double, get_control_double
|
||||
}
|
||||
field(HIHI,DBF_DOUBLE) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOLO,DBF_DOUBLE) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HIGH,DBF_DOUBLE) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(LOW,DBF_DOUBLE) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
@@ -425,7 +426,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
@@ -433,7 +434,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
@@ -441,7 +442,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
prop(YES) # get_alarm_double
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_DOUBLE) {
|
||||
|
||||
@@ -129,7 +129,7 @@ static long process(struct dbCommon *pcommon)
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_stringin==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"read_stringin");
|
||||
recGblRecordError(S_dev_missingSup, prec, "read_stringin");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ static long process(struct dbCommon *pcommon)
|
||||
|
||||
if( (pdset==NULL) || (pdset->write_stringout==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"write_stringout");
|
||||
recGblRecordError(S_dev_missingSup, prec, "write_stringout");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if (!prec->pact &&
|
||||
@@ -168,7 +168,7 @@ static long process(struct dbCommon *pcommon)
|
||||
break;
|
||||
default :
|
||||
status=-1;
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"stringout:process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,13 +107,13 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
|
||||
/* must have dset defined */
|
||||
if (!(pdset = (sadset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"sa: init_record");
|
||||
recGblRecordError(S_dev_noDSET, prec, "sa: init_record");
|
||||
return S_dev_noDSET;
|
||||
}
|
||||
|
||||
/* must have read_sa function defined */
|
||||
if ( (pdset->common.number < 5) || (pdset->read_sa == NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"sa: init_record");
|
||||
recGblRecordError(S_dev_missingSup, prec, "sa: init_record");
|
||||
return S_dev_missingSup;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ static long process(struct dbCommon *pcommon)
|
||||
|
||||
if ((pdset==NULL) || (pdset->read_sa==NULL)) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup, (void *)prec, "read_sa");
|
||||
recGblRecordError(S_dev_missingSup, prec, "read_sa");
|
||||
return S_dev_missingSup;
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ static void monitor(subArrayRecord *prec)
|
||||
monitor_mask = recGblResetAlarms(prec);
|
||||
monitor_mask |= (DBE_LOG|DBE_VALUE);
|
||||
|
||||
db_post_events(prec, (void*)&prec->val, monitor_mask);
|
||||
db_post_events(prec, &prec->val, monitor_mask);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user