Merge remote-tracking branch 'origin' into PSI-7.0
Conflicts: configure/os/CONFIG_SITE.Common.linuxCommon modules/libcom/src/log/iocLog.c modules/libcom/src/log/logClient.c modules/pvAccess modules/pvData modules/pvDatabase
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
TOP = ..
|
||||
TOP = ../../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
# PDB Tools
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
TOP=../..
|
||||
IOCDIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
|
||||
TOP = ../../../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
SRC = $(TOP)/src
|
||||
IOCDIR = $(SRC)/ioc
|
||||
USR_CPPFLAGS += -DUSE_TYPED_RSET
|
||||
|
||||
SHRLIB_VERSION = 3.17.0
|
||||
|
||||
LIBRARY_IOC += dbCore
|
||||
dbCore_LIBS += ca Com
|
||||
@@ -34,6 +36,9 @@ include $(IOCDIR)/misc/Makefile
|
||||
include $(IOCDIR)/registry/Makefile
|
||||
include $(IOCDIR)/rsrv/Makefile
|
||||
|
||||
GENVERSION = epicsVCS.h
|
||||
GENVERSIONMACRO = EPICS_VCS_VERSION
|
||||
|
||||
EXPANDVARS += EPICS_DATABASE_MAJOR_VERSION
|
||||
EXPANDVARS += EPICS_DATABASE_MINOR_VERSION
|
||||
EXPANDVARS += EPICS_DATABASE_MAINTENANCE_VERSION
|
||||
@@ -53,3 +58,5 @@ include $(IOCDIR)/dbtemplate/RULES
|
||||
../O.Common/databaseVersionNum.h: ../databaseVersionNum.h@
|
||||
$(MKDIR) $(COMMON_DIR)
|
||||
$(EXPAND_TOOL) $(EXPANDFLAGS) $($@_EXPANDFLAGS) $< $@
|
||||
|
||||
epicsRelease$(DEP): $(COMMON_DIR)/$(GENVERSION)
|
||||
|
||||
@@ -229,20 +229,23 @@ static void asCaTask(void)
|
||||
|
||||
void asCaStart(void)
|
||||
{
|
||||
epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT;
|
||||
|
||||
opts.stackSize = epicsThreadGetStackSize(epicsThreadStackBig);
|
||||
opts.priority = epicsThreadPriorityScanLow - 3;
|
||||
opts.joinable = 1;
|
||||
|
||||
if(asCaDebug) printf("asCaStart called\n");
|
||||
if(firstTime) {
|
||||
firstTime = FALSE;
|
||||
firstTime = FALSE;
|
||||
asCaTaskLock=epicsMutexMustCreate();
|
||||
asCaTaskWait=epicsEventMustCreate(epicsEventEmpty);
|
||||
asCaTaskAddChannels=epicsEventMustCreate(epicsEventEmpty);
|
||||
asCaTaskClearChannels=epicsEventMustCreate(epicsEventEmpty);
|
||||
threadid = epicsThreadCreate("asCaTask",
|
||||
(epicsThreadPriorityScanLow - 3),
|
||||
epicsThreadGetStackSize(epicsThreadStackBig),
|
||||
(EPICSTHREADFUNC)asCaTask,0);
|
||||
if(threadid==0) {
|
||||
errMessage(0,"asCaStart: taskSpawn Failure\n");
|
||||
}
|
||||
threadid = epicsThreadCreateOpt("asCaTask", (EPICSTHREADFUNC)asCaTask, 0, &opts);
|
||||
if(threadid==0) {
|
||||
errMessage(0,"asCaStart: taskSpawn Failure\n");
|
||||
}
|
||||
}
|
||||
epicsMutexMustLock(asCaTaskLock);
|
||||
epicsEventSignal(asCaTaskAddChannels);
|
||||
@@ -260,6 +263,8 @@ void asCaStop(void)
|
||||
epicsEventMustWait(asCaTaskWait);
|
||||
if(asCaDebug) printf("asCaStop done\n");
|
||||
epicsMutexUnlock(asCaTaskLock);
|
||||
epicsThreadMustJoin(threadid);
|
||||
threadid = 0;
|
||||
}
|
||||
|
||||
int ascar(int level) { return ascarFP(stdout,level);}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#ifndef INCasCah
|
||||
#define INCasCah
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -12,11 +12,13 @@
|
||||
#ifndef INCdbAsLibh
|
||||
#define INCdbAsLibh
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "callback.h"
|
||||
#include "shareLib.h"
|
||||
|
||||
typedef struct {
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
long status;
|
||||
} ASDBCALLBACK;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ static void asSetSubstitutionsCallFunc(const iocshArgBuf *args)
|
||||
static const iocshFuncDef asInitFuncDef = {"asInit",0};
|
||||
static void asInitCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
asInit();
|
||||
iocshSetError(asInit());
|
||||
}
|
||||
|
||||
/* asdbdump */
|
||||
|
||||
@@ -216,7 +216,7 @@ static void callbackTask(void *arg)
|
||||
epicsEventMustWait(mySet->semWakeUp);
|
||||
|
||||
while ((ptr = epicsRingPointerPop(mySet->queue))) {
|
||||
CALLBACK *pcallback = (CALLBACK *)ptr;
|
||||
epicsCallback *pcallback = (epicsCallback *)ptr;
|
||||
if(!epicsRingPointerIsEmpty(mySet->queue))
|
||||
epicsEventMustTrigger(mySet->semWakeUp);
|
||||
mySet->queueOverflow = FALSE;
|
||||
@@ -317,7 +317,7 @@ void callbackInit(void)
|
||||
}
|
||||
|
||||
/* This routine can be called from interrupt context */
|
||||
int callbackRequest(CALLBACK *pcallback)
|
||||
int callbackRequest(epicsCallback *pcallback)
|
||||
{
|
||||
int priority;
|
||||
int pushOK;
|
||||
@@ -347,7 +347,7 @@ int callbackRequest(CALLBACK *pcallback)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ProcessCallback(CALLBACK *pcallback)
|
||||
static void ProcessCallback(epicsCallback *pcallback)
|
||||
{
|
||||
dbCommon *pRec;
|
||||
|
||||
@@ -358,14 +358,14 @@ static void ProcessCallback(CALLBACK *pcallback)
|
||||
dbScanUnlock(pRec);
|
||||
}
|
||||
|
||||
void callbackSetProcess(CALLBACK *pcallback, int Priority, void *pRec)
|
||||
void callbackSetProcess(epicsCallback *pcallback, int Priority, void *pRec)
|
||||
{
|
||||
callbackSetCallback(ProcessCallback, pcallback);
|
||||
callbackSetPriority(Priority, pcallback);
|
||||
callbackSetUser(pRec, pcallback);
|
||||
}
|
||||
|
||||
int callbackRequestProcessCallback(CALLBACK *pcallback,
|
||||
int callbackRequestProcessCallback(epicsCallback *pcallback,
|
||||
int Priority, void *pRec)
|
||||
{
|
||||
callbackSetProcess(pcallback, Priority, pRec);
|
||||
@@ -374,11 +374,11 @@ int callbackRequestProcessCallback(CALLBACK *pcallback,
|
||||
|
||||
static void notify(void *pPrivate)
|
||||
{
|
||||
CALLBACK *pcallback = (CALLBACK *)pPrivate;
|
||||
epicsCallback *pcallback = (epicsCallback *)pPrivate;
|
||||
callbackRequest(pcallback);
|
||||
}
|
||||
|
||||
void callbackRequestDelayed(CALLBACK *pcallback, double seconds)
|
||||
void callbackRequestDelayed(epicsCallback *pcallback, double seconds)
|
||||
{
|
||||
epicsTimerId timer = (epicsTimerId)pcallback->timer;
|
||||
|
||||
@@ -389,7 +389,7 @@ void callbackRequestDelayed(CALLBACK *pcallback, double seconds)
|
||||
epicsTimerStartDelay(timer, seconds);
|
||||
}
|
||||
|
||||
void callbackCancelDelayed(CALLBACK *pcallback)
|
||||
void callbackCancelDelayed(epicsCallback *pcallback)
|
||||
{
|
||||
epicsTimerId timer = (epicsTimerId)pcallback->timer;
|
||||
|
||||
@@ -398,7 +398,7 @@ void callbackCancelDelayed(CALLBACK *pcallback)
|
||||
}
|
||||
}
|
||||
|
||||
void callbackRequestProcessCallbackDelayed(CALLBACK *pcallback,
|
||||
void callbackRequestProcessCallbackDelayed(epicsCallback *pcallback,
|
||||
int Priority, void *pRec, double seconds)
|
||||
{
|
||||
callbackSetProcess(pcallback, Priority, pRec);
|
||||
|
||||
@@ -26,7 +26,7 @@ extern "C" {
|
||||
/*
|
||||
* WINDOWS also has a "CALLBACK" type def
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(EPICS_NO_CALLBACK)
|
||||
# ifdef CALLBACK
|
||||
# undef CALLBACK
|
||||
# endif /*CALLBACK*/
|
||||
@@ -44,7 +44,9 @@ typedef struct callbackPvt {
|
||||
void *timer; /*for use by callback itself*/
|
||||
}epicsCallback;
|
||||
|
||||
#if !defined(EPICS_NO_CALLBACK)
|
||||
typedef epicsCallback CALLBACK;
|
||||
#endif
|
||||
|
||||
typedef void (*CALLBACKFUNC)(struct callbackPvt*);
|
||||
|
||||
@@ -69,16 +71,16 @@ typedef struct callbackQueueStats {
|
||||
epicsShareFunc void callbackInit(void);
|
||||
epicsShareFunc void callbackStop(void);
|
||||
epicsShareFunc void callbackCleanup(void);
|
||||
epicsShareFunc int callbackRequest(CALLBACK *pCallback);
|
||||
epicsShareFunc int callbackRequest(epicsCallback *pCallback);
|
||||
epicsShareFunc void callbackSetProcess(
|
||||
CALLBACK *pcallback, int Priority, void *pRec);
|
||||
epicsCallback *pcallback, int Priority, void *pRec);
|
||||
epicsShareFunc int callbackRequestProcessCallback(
|
||||
CALLBACK *pCallback,int Priority, void *pRec);
|
||||
epicsCallback *pCallback,int Priority, void *pRec);
|
||||
epicsShareFunc void callbackRequestDelayed(
|
||||
CALLBACK *pCallback,double seconds);
|
||||
epicsShareFunc void callbackCancelDelayed(CALLBACK *pcallback);
|
||||
epicsCallback *pCallback,double seconds);
|
||||
epicsShareFunc void callbackCancelDelayed(epicsCallback *pcallback);
|
||||
epicsShareFunc void callbackRequestProcessCallbackDelayed(
|
||||
CALLBACK *pCallback, int Priority, void *pRec, double seconds);
|
||||
epicsCallback *pCallback, int Priority, void *pRec, double seconds);
|
||||
epicsShareFunc int callbackSetQueueSize(int size);
|
||||
epicsShareFunc int callbackQueueStatus(const int reset, callbackQueueStats *result);
|
||||
epicsShareFunc void callbackQueueShow(const int reset);
|
||||
|
||||
@@ -1010,7 +1010,7 @@ devSup* dbDTYPtoDevSup(dbRecordType *prdes, int dtyp) {
|
||||
return (devSup *)ellNth(&prdes->devList, dtyp+1);
|
||||
}
|
||||
|
||||
devSup* dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset) {
|
||||
devSup* dbDSETtoDevSup(dbRecordType *prdes, dset *pdset) {
|
||||
devSup *pdevSup = (devSup *)ellFirst(&prdes->devList);
|
||||
while (pdevSup) {
|
||||
if (pdset == pdevSup->pdset) return pdevSup;
|
||||
@@ -1032,7 +1032,7 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
struct link *plink = (struct link *)paddr->pfield;
|
||||
const char *pstring = (const char *)pbuffer;
|
||||
struct dsxt *old_dsxt = NULL;
|
||||
struct dset *new_dset = NULL;
|
||||
dset *new_dset = NULL;
|
||||
struct dsxt *new_dsxt = NULL;
|
||||
devSup *new_devsup = NULL;
|
||||
long status;
|
||||
|
||||
@@ -18,15 +18,16 @@
|
||||
|
||||
#include "epicsTypes.h"
|
||||
#include "epicsTime.h"
|
||||
#include "dbBase.h"
|
||||
#include "dbAddr.h"
|
||||
#include "recSup.h"
|
||||
|
||||
#ifdef INCLdb_accessh_epicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
#include "dbBase.h"
|
||||
#include "dbAddr.h"
|
||||
#include "recSup.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -239,7 +240,7 @@ epicsShareFunc void dbInitEntryFromRecord(struct dbCommon *prec,
|
||||
struct dbEntry *pdbentry);
|
||||
|
||||
epicsShareFunc devSup* dbDTYPtoDevSup(dbRecordType *prdes, int dtyp);
|
||||
epicsShareFunc devSup* dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset);
|
||||
epicsShareFunc devSup* dbDSETtoDevSup(dbRecordType *prdes, dset *pdset);
|
||||
epicsShareFunc long dbGetField(
|
||||
struct dbAddr *,short dbrType,void *pbuffer,long *options,
|
||||
long *nRequest,void *pfl);
|
||||
|
||||
@@ -68,6 +68,7 @@ static volatile enum dbCaCtl_t {
|
||||
ctlInit, ctlRun, ctlPause, ctlExit
|
||||
} dbCaCtl;
|
||||
static epicsEventId startStopEvent;
|
||||
static epicsThreadId dbCaWorker;
|
||||
|
||||
struct ca_client_context * dbCaClientContext;
|
||||
|
||||
@@ -258,10 +259,18 @@ void dbCaShutdown(void)
|
||||
dbCaCtl = ctlExit;
|
||||
epicsEventSignal(workListEvent);
|
||||
epicsEventMustWait(startStopEvent);
|
||||
if(dbCaWorker)
|
||||
epicsThreadMustJoin(dbCaWorker);
|
||||
}
|
||||
|
||||
static void dbCaLinkInitImpl(int isolate)
|
||||
{
|
||||
epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT;
|
||||
|
||||
opts.stackSize = epicsThreadGetStackSize(epicsThreadStackBig);
|
||||
opts.priority = epicsThreadPriorityMedium;
|
||||
opts.joinable = 1;
|
||||
|
||||
dbServiceIsolate = isolate;
|
||||
dbServiceIOInit();
|
||||
|
||||
@@ -274,9 +283,8 @@ static void dbCaLinkInitImpl(int isolate)
|
||||
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
|
||||
dbCaCtl = ctlPause;
|
||||
|
||||
epicsThreadCreate("dbCaLink", epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackBig),
|
||||
dbCaTask, NULL);
|
||||
dbCaWorker = epicsThreadCreateOpt("dbCaLink", dbCaTask, NULL, &opts);
|
||||
/* wait for worker to startup and initialize dbCaClientContext */
|
||||
epicsEventMustWait(startStopEvent);
|
||||
}
|
||||
|
||||
|
||||
@@ -199,11 +199,12 @@
|
||||
interest(4)
|
||||
extra("struct typed_rset *rset")
|
||||
}
|
||||
%#include "devSup.h"
|
||||
field(DSET,DBF_NOACCESS) {
|
||||
prompt("DSET address")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct dset *dset")
|
||||
extra("unambiguous_dset *dset")
|
||||
}
|
||||
field(DPVT,DBF_NOACCESS) {
|
||||
prompt("Device Private")
|
||||
|
||||
@@ -384,7 +384,7 @@ void dbContext::show (
|
||||
this->mutex.show ( level - 2u );
|
||||
}
|
||||
if ( this->pNetContext.get() ) {
|
||||
this->pNetContext.get()->show ( guard, level );
|
||||
this->pNetContext->show ( guard, level );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,7 +393,7 @@ void dbContext::flush (
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
if ( this->pNetContext.get() ) {
|
||||
this->pNetContext.get()->flush ( guard );
|
||||
this->pNetContext->flush ( guard );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ unsigned dbContext::circuitCount (
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
if ( this->pNetContext.get() ) {
|
||||
return this->pNetContext.get()->circuitCount ( guard );
|
||||
return this->pNetContext->circuitCount ( guard );
|
||||
}
|
||||
else {
|
||||
return 0u;
|
||||
@@ -416,7 +416,7 @@ void dbContext::selfTest (
|
||||
this->ioTable.verify ();
|
||||
|
||||
if ( this->pNetContext.get() ) {
|
||||
this->pNetContext.get()->selfTest ( guard );
|
||||
this->pNetContext->selfTest ( guard );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +425,7 @@ unsigned dbContext::beaconAnomaliesSinceProgramStart (
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
if ( this->pNetContext.get() ) {
|
||||
return this->pNetContext.get()->beaconAnomaliesSinceProgramStart ( guard );
|
||||
return this->pNetContext->beaconAnomaliesSinceProgramStart ( guard );
|
||||
}
|
||||
else {
|
||||
return 0u;
|
||||
|
||||
@@ -84,7 +84,6 @@ struct event_user {
|
||||
epicsMutexId lock;
|
||||
epicsEventId ppendsem; /* Wait while empty */
|
||||
epicsEventId pflush_sem; /* wait for flush */
|
||||
epicsEventId pexitsem; /* wait for event task to join */
|
||||
|
||||
EXTRALABORFUNC *extralabor_sub;/* off load to event task */
|
||||
void *extralabor_arg;/* parameter to above */
|
||||
@@ -123,8 +122,6 @@ static char *EVENT_PEND_NAME = "eventTask";
|
||||
|
||||
static struct evSubscrip canceledEvent;
|
||||
|
||||
static epicsMutexId stopSync;
|
||||
|
||||
static unsigned short ringSpace ( const struct event_que *pevq )
|
||||
{
|
||||
if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) {
|
||||
@@ -266,10 +263,6 @@ dbEventCtx db_init_events (void)
|
||||
{
|
||||
struct event_user * evUser;
|
||||
|
||||
if (!stopSync) {
|
||||
stopSync = epicsMutexMustCreate();
|
||||
}
|
||||
|
||||
if (!dbevEventUserFreeList) {
|
||||
freeListInitPvt(&dbevEventUserFreeList,
|
||||
sizeof(struct event_user),8);
|
||||
@@ -293,9 +286,6 @@ dbEventCtx db_init_events (void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Flag will be cleared when event task starts */
|
||||
evUser->pendexit = TRUE;
|
||||
|
||||
evUser->firstque.evUser = evUser;
|
||||
evUser->firstque.writelock = epicsMutexCreate();
|
||||
if (!evUser->firstque.writelock)
|
||||
@@ -310,9 +300,6 @@ dbEventCtx db_init_events (void)
|
||||
evUser->lock = epicsMutexCreate();
|
||||
if (!evUser->lock)
|
||||
goto fail;
|
||||
evUser->pexitsem = epicsEventCreate(epicsEventEmpty);
|
||||
if (!evUser->pexitsem)
|
||||
goto fail;
|
||||
|
||||
evUser->flowCtrlMode = FALSE;
|
||||
evUser->extraLaborBusy = FALSE;
|
||||
@@ -327,8 +314,6 @@ fail:
|
||||
epicsEventDestroy (evUser->ppendsem);
|
||||
if(evUser->pflush_sem)
|
||||
epicsEventDestroy (evUser->pflush_sem);
|
||||
if(evUser->pexitsem)
|
||||
epicsEventDestroy (evUser->pexitsem);
|
||||
freeListFree(dbevEventUserFreeList,evUser);
|
||||
return NULL;
|
||||
}
|
||||
@@ -349,7 +334,6 @@ epicsShareFunc void db_cleanup_events(void)
|
||||
dbevFieldLogFreeList = NULL;
|
||||
}
|
||||
|
||||
/* intentionally leak stopSync to avoid possible shutdown races */
|
||||
/*
|
||||
* DB_CLOSE_EVENTS()
|
||||
*
|
||||
@@ -371,30 +355,15 @@ void db_close_events (dbEventCtx ctx)
|
||||
* hazardous to the system's health.
|
||||
*/
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
if(!evUser->pendexit) { /* event task running */
|
||||
evUser->pendexit = TRUE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
|
||||
/* notify the waiting task */
|
||||
epicsEventSignal(evUser->ppendsem);
|
||||
/* wait for task to exit */
|
||||
epicsEventMustWait(evUser->pexitsem);
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
}
|
||||
|
||||
evUser->pendexit = TRUE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
|
||||
epicsMutexMustLock (stopSync);
|
||||
/* notify the waiting task */
|
||||
epicsEventSignal(evUser->ppendsem);
|
||||
|
||||
epicsEventDestroy(evUser->pexitsem);
|
||||
epicsEventDestroy(evUser->ppendsem);
|
||||
epicsEventDestroy(evUser->pflush_sem);
|
||||
epicsMutexDestroy(evUser->lock);
|
||||
|
||||
epicsMutexUnlock (stopSync);
|
||||
|
||||
freeListFree(dbevEventUserFreeList, evUser);
|
||||
if(evUser->taskid)
|
||||
epicsThreadMustJoin(evUser->taskid);
|
||||
/* evUser has been deleted by the worker */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1074,17 +1043,14 @@ static void event_task (void *pParm)
|
||||
}
|
||||
}
|
||||
|
||||
epicsEventDestroy(evUser->ppendsem);
|
||||
epicsEventDestroy(evUser->pflush_sem);
|
||||
epicsMutexDestroy(evUser->lock);
|
||||
|
||||
freeListFree(dbevEventUserFreeList, evUser);
|
||||
|
||||
taskwdRemove(epicsThreadGetIdSelf());
|
||||
|
||||
/* use stopSync to ensure pexitsem is not destroy'd
|
||||
* until epicsEventSignal() has returned.
|
||||
*/
|
||||
epicsMutexMustLock (stopSync);
|
||||
|
||||
epicsEventSignal(evUser->pexitsem);
|
||||
|
||||
epicsMutexUnlock(stopSync);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1096,6 +1062,11 @@ int db_start_events (
|
||||
void *init_func_arg, unsigned osiPriority )
|
||||
{
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT;
|
||||
|
||||
opts.stackSize = epicsThreadGetStackSize(epicsThreadStackMedium);
|
||||
opts.priority = osiPriority;
|
||||
opts.joinable = 1;
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
|
||||
@@ -1113,15 +1084,12 @@ int db_start_events (
|
||||
if (!taskname) {
|
||||
taskname = EVENT_PEND_NAME;
|
||||
}
|
||||
evUser->taskid = epicsThreadCreate (
|
||||
taskname, osiPriority,
|
||||
epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||
event_task, (void *)evUser);
|
||||
evUser->taskid = epicsThreadCreateOpt (
|
||||
taskname, event_task, (void *)evUser, &opts);
|
||||
if (!evUser->taskid) {
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
return DB_EVENT_ERROR;
|
||||
}
|
||||
evUser->pendexit = FALSE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
return DB_EVENT_OK;
|
||||
}
|
||||
@@ -1186,3 +1154,8 @@ void db_delete_field_log (db_field_log *pfl)
|
||||
freeListFree(dbevFieldLogFreeList, pfl);
|
||||
}
|
||||
}
|
||||
|
||||
int db_available_logs(void)
|
||||
{
|
||||
return (int) freeListItemsAvail(dbevFieldLogFreeList);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ epicsShareFunc void db_event_disable (dbEventSubscription es);
|
||||
epicsShareFunc struct db_field_log* db_create_event_log (struct evSubscrip *pevent);
|
||||
epicsShareFunc struct db_field_log* db_create_read_log (struct dbChannel *chan);
|
||||
epicsShareFunc void db_delete_field_log (struct db_field_log *pfl);
|
||||
epicsShareFunc int db_available_logs(void);
|
||||
|
||||
#define DB_EVENT_OK 0
|
||||
#define DB_EVENT_ERROR (-1)
|
||||
@@ -91,4 +92,3 @@ epicsShareFunc void db_delete_field_log (struct db_field_log *pfl);
|
||||
#endif
|
||||
|
||||
#endif /*INCLdbEventh*/
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ static const iocshFuncDef dbLoadDatabaseFuncDef =
|
||||
{"dbLoadDatabase",3,dbLoadDatabaseArgs};
|
||||
static void dbLoadDatabaseCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dbLoadDatabase(args[0].sval,args[1].sval,args[2].sval);
|
||||
iocshSetError(dbLoadDatabase(args[0].sval,args[1].sval,args[2].sval));
|
||||
}
|
||||
|
||||
/* dbLoadRecords */
|
||||
@@ -49,7 +49,7 @@ static const iocshArg * const dbLoadRecordsArgs[2] = {&dbLoadRecordsArg0,&dbLoad
|
||||
static const iocshFuncDef dbLoadRecordsFuncDef = {"dbLoadRecords",2,dbLoadRecordsArgs};
|
||||
static void dbLoadRecordsCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dbLoadRecords(args[0].sval,args[1].sval);
|
||||
iocshSetError(dbLoadRecords(args[0].sval,args[1].sval));
|
||||
}
|
||||
|
||||
/* dbb */
|
||||
|
||||
@@ -69,7 +69,7 @@ typedef struct notifyPvt {
|
||||
ELLNODE node; /*For free list*/
|
||||
long magic;
|
||||
short state;
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
ELLLIST waitList; /*list of records for current processNotify*/
|
||||
short cancelWait;
|
||||
short userCallbackWait;
|
||||
@@ -86,7 +86,7 @@ typedef struct notifyGlobal {
|
||||
|
||||
static notifyGlobal *pnotifyGlobal = 0;
|
||||
|
||||
static void notifyCallback(CALLBACK *pcallback);
|
||||
static void notifyCallback(epicsCallback *pcallback);
|
||||
|
||||
#define ellSafeAdd(list,listnode) \
|
||||
{ \
|
||||
@@ -270,7 +270,7 @@ static void processNotifyCommon(processNotify *ppn, dbCommon *precord, int first
|
||||
callDone(precord, ppn);
|
||||
}
|
||||
|
||||
static void notifyCallback(CALLBACK *pcallback)
|
||||
static void notifyCallback(epicsCallback *pcallback)
|
||||
{
|
||||
processNotify *ppn = NULL;
|
||||
dbCommon *precord;
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
|
||||
#include "shareLib.h"
|
||||
#include "ellLib.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "callback.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -144,12 +144,12 @@ void dbPutNotifyBlocker::initiatePutNotify (
|
||||
break;
|
||||
}
|
||||
if ( beginTimeInit ) {
|
||||
if ( epicsTime::getCurrent () - begin > 30.0 ) {
|
||||
if ( epicsTime::getMonotonic () - begin > 30.0 ) {
|
||||
throw cacChannel::requestTimedOut ();
|
||||
}
|
||||
}
|
||||
else {
|
||||
begin = epicsTime::getCurrent ();
|
||||
begin = epicsTime::getMonotonic ();
|
||||
beginTimeInit = true;
|
||||
}
|
||||
{
|
||||
|
||||
@@ -109,7 +109,7 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = {
|
||||
/* EVENT */
|
||||
|
||||
typedef struct event_list {
|
||||
CALLBACK callback[NUM_CALLBACK_PRIORITIES];
|
||||
epicsCallback callback[NUM_CALLBACK_PRIORITIES];
|
||||
scan_list scan_list[NUM_CALLBACK_PRIORITIES];
|
||||
struct event_list *next;
|
||||
char eventname[1]; /* actually arbitrary size */
|
||||
@@ -120,7 +120,7 @@ static epicsMutexId event_lock;
|
||||
/* IO_EVENT*/
|
||||
|
||||
typedef struct io_scan_list {
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
scan_list scan_list;
|
||||
} io_scan_list;
|
||||
|
||||
@@ -141,9 +141,9 @@ static void periodicTask(void *arg);
|
||||
static void initPeriodic(void);
|
||||
static void deletePeriodic(void);
|
||||
static void spawnPeriodic(int ind);
|
||||
static void eventCallback(CALLBACK *pcallback);
|
||||
static void eventCallback(epicsCallback *pcallback);
|
||||
static void ioscanInit(void);
|
||||
static void ioscanCallback(CALLBACK *pcallback);
|
||||
static void ioscanCallback(epicsCallback *pcallback);
|
||||
static void ioscanDestroy(void);
|
||||
static void printList(scan_list *psl, char *message);
|
||||
static void scanList(scan_list *psl);
|
||||
@@ -448,7 +448,7 @@ int scanpiol(void) /* print pioscan_list */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void eventCallback(CALLBACK *pcallback)
|
||||
static void eventCallback(epicsCallback *pcallback)
|
||||
{
|
||||
scan_list *psl;
|
||||
|
||||
@@ -787,7 +787,7 @@ static void periodicTask(void *arg)
|
||||
taskwdInsert(0, NULL, NULL);
|
||||
epicsEventSignal(startStopEvent);
|
||||
|
||||
epicsTimeGetCurrent(&next);
|
||||
epicsTimeGetMonotonic(&next);
|
||||
reported = next;
|
||||
|
||||
while (ppsl->scanCtl != ctlExit) {
|
||||
@@ -798,7 +798,7 @@ static void periodicTask(void *arg)
|
||||
scanList(&ppsl->scan_list);
|
||||
|
||||
epicsTimeAddSeconds(&next, ppsl->period);
|
||||
epicsTimeGetCurrent(&now);
|
||||
epicsTimeGetMonotonic(&now);
|
||||
delay = epicsTimeDiffInSeconds(&next, &now);
|
||||
if (delay <= 0.0) {
|
||||
if (overtime == 0.0) {
|
||||
@@ -944,7 +944,7 @@ static void spawnPeriodic(int ind)
|
||||
epicsEventWait(startStopEvent);
|
||||
}
|
||||
|
||||
static void ioscanCallback(CALLBACK *pcallback)
|
||||
static void ioscanCallback(epicsCallback *pcallback)
|
||||
{
|
||||
ioscan_head *piosh;
|
||||
int prio;
|
||||
|
||||
@@ -56,7 +56,7 @@ typedef struct msgBuff TAB_BUFFER;
|
||||
# define MIN(x,y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
# define MAX(x,y) (((x) < (y)) ? (x) : (y))
|
||||
# define MAX(x,y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
/* Local Routines */
|
||||
@@ -712,7 +712,7 @@ long dbior(const char *pdrvName,int interest_level)
|
||||
for (pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||||
pdevSup;
|
||||
pdevSup = (devSup *)ellNext(&pdevSup->node)) {
|
||||
struct dset *pdset = pdevSup->pdset;
|
||||
dset *pdset = pdevSup->pdset;
|
||||
const char *pname = pdevSup->name;
|
||||
|
||||
if (!pdset || !pname)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "epicsStdlib.h"
|
||||
#include "epicsString.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsEvent.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "db_access_routines.h"
|
||||
|
||||
+11
@@ -7,6 +7,17 @@
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuAlarmStat
|
||||
|
||||
This menu defines the possible alarm statuses that EPICS records can exhibit
|
||||
which is used for C<STAT> and C<NSTA> fields of all record types.
|
||||
See L<Alarm Status> for more information.
|
||||
|
||||
=menu menuAlarmStat
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuAlarmStat) {
|
||||
choice(menuAlarmStatNO_ALARM,"NO_ALARM")
|
||||
choice(menuAlarmStatREAD,"READ")
|
||||
+9
@@ -6,6 +6,15 @@
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuFtype
|
||||
|
||||
This menu is used for the C<FTVL> and similar fields of many record types.
|
||||
|
||||
=menu menuFtype
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuFtype) {
|
||||
choice(menuFtypeSTRING,"STRING")
|
||||
choice(menuFtypeCHAR,"CHAR")
|
||||
+12
-3
@@ -3,10 +3,19 @@
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuIvoa
|
||||
|
||||
This menu specifies the possibile actions to take when the INVALID alarm is
|
||||
triggered. See individual record types for more information.
|
||||
|
||||
=menu menuIvoa
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuIvoa) {
|
||||
choice(menuIvoaContinue_normally,"Continue normally")
|
||||
choice(menuIvoaDon_t_drive_outputs,"Don't drive outputs")
|
||||
@@ -1,13 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
menu(menuOmsl) {
|
||||
choice(menuOmslsupervisory,"supervisory")
|
||||
choice(menuOmslclosed_loop,"closed_loop")
|
||||
}
|
||||
+16
-15
@@ -6,19 +6,20 @@
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(state) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_STRING) {
|
||||
prompt("Value")
|
||||
promptgroup("40 - Input")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
size(20)
|
||||
}
|
||||
field(OVAL,DBF_STRING) {
|
||||
prompt("Prev Value")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
size(20)
|
||||
}
|
||||
|
||||
=head1 Menu menuOmsl
|
||||
|
||||
This menu is used for the C<OMSL> field of many output record types. It controls
|
||||
whether the record will fetch an input value from its C<DOL> input link when
|
||||
processed, which is useful when it is part of a closed loop control algorithm.
|
||||
The C<supervisory> state means the input link will not be used, C<closed_loop>
|
||||
enables the input link.
|
||||
|
||||
=menu menuOmsl
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuOmsl) {
|
||||
choice(menuOmslsupervisory,"supervisory")
|
||||
choice(menuOmslclosed_loop,"closed_loop")
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
menu(menuYesNo) {
|
||||
choice(menuYesNoNO,"NO")
|
||||
choice(menuYesNoYES,"YES")
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuYesNo
|
||||
|
||||
This menu is used by many record types to specify simple C<NO> or C<YES>
|
||||
options for record-specific purposes.
|
||||
|
||||
Note that no other values for a field that uses menuYesNo are possible, e.g.
|
||||
C<MAYBE> or C<NO WAY> would not be accepted as choices for the field.
|
||||
Also, the choices C<yes>, C<No>, and C<Yes> are not valid choices since they
|
||||
don't match the case of C<NO> or C<YES>.
|
||||
The integer values C<0> and C<1> may often be used instead however, they are
|
||||
used as an index into the choices so C<0> becomes C<NO> and C<1> becomes <YES>.
|
||||
|
||||
=menu menuYesNo
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuYesNo) {
|
||||
choice(menuYesNoNO,"NO")
|
||||
choice(menuYesNoYES,"YES")
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "ellLib.h"
|
||||
#include "dbDefs.h"
|
||||
#include "recSup.h"
|
||||
#include "devSup.h"
|
||||
|
||||
typedef struct dbMenu {
|
||||
ELLNODE node;
|
||||
@@ -40,7 +41,7 @@ typedef struct devSup {
|
||||
char *choice;
|
||||
int link_type;
|
||||
/*Following only available on run time system*/
|
||||
struct dset *pdset;
|
||||
dset *pdset;
|
||||
struct dsxt *pdsxt; /* Extended device support */
|
||||
}devSup;
|
||||
|
||||
|
||||
@@ -153,6 +153,9 @@ typedef struct dset { /* device support entry table */
|
||||
typedef typed_dset dset;
|
||||
#endif /* USE_TYPED_DSET */
|
||||
|
||||
/* exists only to disambiguate dset dbCommon::dset */
|
||||
typedef dset unambiguous_dset;
|
||||
|
||||
/** Fetch INP or OUT link (or NULL if record type has neither).
|
||||
*
|
||||
* Recommended for use in device support init_record()
|
||||
|
||||
@@ -12,7 +12,16 @@
|
||||
#define INCdbLoadTemplateh
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
epicsShareFunc int dbLoadTemplate(
|
||||
const char *sub_file, const char *cmd_collect);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*INCdbLoadTemplateh*/
|
||||
|
||||
@@ -22,7 +22,7 @@ static const iocshFuncDef dbLoadTemplateFuncDef =
|
||||
{"dbLoadTemplate", 2, dbLoadTemplateArgs};
|
||||
static void dbLoadTemplateCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dbLoadTemplate(args[0].sval, args[1].sval);
|
||||
iocshSetError(dbLoadTemplate(args[0].sval, args[1].sval));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,3 +33,6 @@ variable(callbackParallelThreadsDefault,int)
|
||||
|
||||
# Real-time operation
|
||||
variable(dbThreadRealtimeLock,int)
|
||||
|
||||
# show logClient network activity
|
||||
variable(logClientDebug,int)
|
||||
|
||||
@@ -16,12 +16,13 @@
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsRelease.h"
|
||||
#include "epicsVCS.h"
|
||||
|
||||
epicsShareFunc int coreRelease(void)
|
||||
{
|
||||
printf ( "############################################################################\n" );
|
||||
printf ( "## %s\n", epicsReleaseVersion );
|
||||
printf ( "## %s\n", "EPICS Base built " __DATE__ );
|
||||
printf ( "## %s\n", "Rev. " EPICS_VCS_VERSION );
|
||||
printf ( "############################################################################\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ static void initDevSup(void)
|
||||
for (pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||||
pdevSup;
|
||||
pdevSup = (devSup *)ellNext(&pdevSup->node)) {
|
||||
struct dset *pdset = registryDeviceSupportFind(pdevSup->name);
|
||||
dset *pdset = registryDeviceSupportFind(pdevSup->name);
|
||||
|
||||
if (!pdset) {
|
||||
errlogPrintf("device support %s not found\n",pdevSup->name);
|
||||
@@ -456,7 +456,7 @@ static void finishDevSup(void)
|
||||
for (pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||||
pdevSup;
|
||||
pdevSup = (devSup *)ellNext(&pdevSup->node)) {
|
||||
struct dset *pdset = pdevSup->pdset;
|
||||
dset *pdset = pdevSup->pdset;
|
||||
|
||||
if (pdset && pdset->init)
|
||||
pdset->init(1);
|
||||
|
||||
@@ -22,28 +22,28 @@
|
||||
static const iocshFuncDef iocInitFuncDef = {"iocInit",0,NULL};
|
||||
static void iocInitCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocInit();
|
||||
iocshSetError(iocInit());
|
||||
}
|
||||
|
||||
/* iocBuild */
|
||||
static const iocshFuncDef iocBuildFuncDef = {"iocBuild",0,NULL};
|
||||
static void iocBuildCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocBuild();
|
||||
iocshSetError(iocBuild());
|
||||
}
|
||||
|
||||
/* iocRun */
|
||||
static const iocshFuncDef iocRunFuncDef = {"iocRun",0,NULL};
|
||||
static void iocRunCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocRun();
|
||||
iocshSetError(iocRun());
|
||||
}
|
||||
|
||||
/* iocPause */
|
||||
static const iocshFuncDef iocPauseFuncDef = {"iocPause",0,NULL};
|
||||
static void iocPauseCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocPause();
|
||||
iocshSetError(iocPause());
|
||||
}
|
||||
|
||||
/* coreRelease */
|
||||
@@ -77,7 +77,7 @@ static const iocshArg * const systemArgs[] = {&systemArg0};
|
||||
static const iocshFuncDef systemFuncDef = {"system",1,systemArgs};
|
||||
static void systemCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
system(args[0].sval);
|
||||
iocshSetError(system(args[0].sval));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ void registerRecordTypes(DBBASE *pbase, int nRecordTypes,
|
||||
} else {
|
||||
sizeOffset(dbEntry.precordType);
|
||||
}
|
||||
dbFinishEntry(&dbEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,12 @@ static void *registryID = "device support";
|
||||
|
||||
|
||||
epicsShareFunc int registryDeviceSupportAdd(
|
||||
const char *name, const struct dset *pdset)
|
||||
const char *name, const dset *pdset)
|
||||
{
|
||||
return registryAdd(registryID, name, (void *)pdset);
|
||||
}
|
||||
|
||||
epicsShareFunc struct dset * registryDeviceSupportFind(
|
||||
epicsShareFunc dset * registryDeviceSupportFind(
|
||||
const char *name)
|
||||
{
|
||||
return registryFind(registryID, name);
|
||||
|
||||
@@ -18,8 +18,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
epicsShareFunc int registryDeviceSupportAdd(
|
||||
const char *name, const struct dset *pdset);
|
||||
epicsShareFunc struct dset * registryDeviceSupportFind(
|
||||
const char *name, const dset *pdset);
|
||||
epicsShareFunc dset * registryDeviceSupportFind(
|
||||
const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -861,6 +861,14 @@ static int host_name_action ( caHdrLargeArray *mp, void *pPayload,
|
||||
return RSRV_ERROR;
|
||||
}
|
||||
|
||||
/* after all validation */
|
||||
if(asCheckClientIP) {
|
||||
|
||||
DLOG (2, ( "CAS: host_name_action for \"%s\" ignores client provided host name\n",
|
||||
client->pHostName ) );
|
||||
return RSRV_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* user name will not change if there isnt enough memory
|
||||
*/
|
||||
|
||||
@@ -56,7 +56,7 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed )
|
||||
if ( pclient->disconnect ) {
|
||||
if ( CASDEBUG > 2 ) {
|
||||
errlogPrintf ( "CAS: msg Discard for sock %d addr %x\n",
|
||||
pclient->sock, (unsigned) pclient->addr.sin_addr.s_addr );
|
||||
(int)pclient->sock, (unsigned) pclient->addr.sin_addr.s_addr );
|
||||
}
|
||||
pclient->send.stk = 0u;
|
||||
if(lock_needed)
|
||||
|
||||
@@ -335,7 +335,7 @@ void rsrv_build_addr_lists(void)
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf("rsrv: failed to set mcast ttl %d\n", ttl);
|
||||
errlogPrintf("rsrv: failed to set mcast ttl %d\n", (int)ttl);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1343,10 +1343,13 @@ void casExpandBuffer ( struct message_buffer *buf, ca_uint32_t size, int sendbuf
|
||||
// round up to multiple of 4K
|
||||
size = ((size-1)|0xfff)+1;
|
||||
|
||||
if (buf->type==mbtLargeTCP)
|
||||
if (buf->type==mbtLargeTCP) {
|
||||
newbuf = realloc (buf->buf, size);
|
||||
else
|
||||
if(newbuf)
|
||||
buf->buf = newbuf;
|
||||
} else {
|
||||
newbuf = malloc (size);
|
||||
}
|
||||
newtype = mbtLargeTCP;
|
||||
newsize = size;
|
||||
|
||||
@@ -1421,6 +1424,20 @@ struct client *create_tcp_client (SOCKET sock , const osiSockAddr *peerAddr)
|
||||
}
|
||||
|
||||
client->addr = peerAddr->ia;
|
||||
if(asCheckClientIP) {
|
||||
epicsUInt32 ip = ntohl(client->addr.sin_addr.s_addr);
|
||||
client->pHostName = malloc(24);
|
||||
if(!client->pHostName) {
|
||||
destroy_client ( client );
|
||||
return NULL;
|
||||
}
|
||||
epicsSnprintf(client->pHostName, 24,
|
||||
"%u.%u.%u.%u",
|
||||
(ip>>24)&0xff,
|
||||
(ip>>16)&0xff,
|
||||
(ip>>8)&0xff,
|
||||
(ip>>0)&0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* see TCP(4P) this seems to make unsolicited single events much
|
||||
|
||||
@@ -86,7 +86,7 @@ typedef struct client {
|
||||
ELLLIST chanList;
|
||||
ELLLIST chanPendingUpdateARList;
|
||||
ELLLIST putNotifyQue;
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr_in addr; /* peer address, TCP only */
|
||||
epicsTimeStamp time_at_last_send;
|
||||
epicsTimeStamp time_at_last_recv;
|
||||
void *evuser;
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
STDDIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
|
||||
TOP = ../../../..
|
||||
|
||||
TOP = ../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
STDDIR=$(TOP)/src/std
|
||||
USR_CPPFLAGS += -DUSE_TYPED_RSET
|
||||
|
||||
SHRLIB_VERSION = 3.17.0
|
||||
|
||||
LIBRARY_IOC += dbRecStd
|
||||
dbRecStd_LIBS = dbCore ca Com
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
/* The following is provided for access security*/
|
||||
/*It allows a CA client to force access security initialization*/
|
||||
|
||||
static void myCallback(CALLBACK *pcallback)
|
||||
static void myCallback(epicsCallback *pcallback)
|
||||
{
|
||||
ASDBCALLBACK *pasdbcallback = (ASDBCALLBACK *)pcallback;
|
||||
subRecord *precord;
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
typedef struct devPvt {
|
||||
processNotify pn;
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
long options;
|
||||
int status;
|
||||
int smooth;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
typedef struct devPvt {
|
||||
processNotify pn;
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
long options;
|
||||
int status;
|
||||
struct {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
typedef struct devPvt {
|
||||
processNotify pn;
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
long options;
|
||||
int status;
|
||||
struct {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
typedef struct devPvt {
|
||||
processNotify pn;
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
long options;
|
||||
int status;
|
||||
struct {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
typedef struct devPvt {
|
||||
processNotify pn;
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
long options;
|
||||
int status;
|
||||
struct {
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
typedef struct devPvt {
|
||||
DBADDR dbaddr;
|
||||
processNotify pn;
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
long options;
|
||||
int status;
|
||||
struct {
|
||||
|
||||
@@ -15,6 +15,7 @@ dbRecStd_SRCS += ts.c
|
||||
dbRecStd_SRCS += dbnd.c
|
||||
dbRecStd_SRCS += arr.c
|
||||
dbRecStd_SRCS += sync.c
|
||||
dbRecStd_SRCS += decimate.c
|
||||
|
||||
HTMLS += filters.html
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2019 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2010 Brookhaven National Laboratory.
|
||||
* Copyright (c) 2010 Helmholtz-Zentrum Berlin
|
||||
* fuer Materialien und Energie GmbH.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors: Ralph Lange <Ralph.Lange@bessy.de>,
|
||||
* Andrew Johnson <anj@anl.gov>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "freeList.h"
|
||||
#include "db_field_log.h"
|
||||
#include "chfPlugin.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
typedef struct myStruct {
|
||||
epicsInt32 n, i;
|
||||
} myStruct;
|
||||
|
||||
static void *myStructFreeList;
|
||||
|
||||
static const
|
||||
chfPluginArgDef opts[] = {
|
||||
chfInt32(myStruct, n, "n", 1, 0),
|
||||
chfPluginArgEnd
|
||||
};
|
||||
|
||||
static void * allocPvt(void)
|
||||
{
|
||||
myStruct *my = (myStruct*) freeListCalloc(myStructFreeList);
|
||||
return (void *) my;
|
||||
}
|
||||
|
||||
static void freePvt(void *pvt)
|
||||
{
|
||||
freeListFree(myStructFreeList, pvt);
|
||||
}
|
||||
|
||||
static int parse_ok(void *pvt)
|
||||
{
|
||||
myStruct *my = (myStruct*) pvt;
|
||||
|
||||
if (my->n < 1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) {
|
||||
db_field_log *passfl = NULL;
|
||||
myStruct *my = (myStruct*) pvt;
|
||||
epicsInt32 i = my->i;
|
||||
|
||||
if (pfl->ctx == dbfl_context_read)
|
||||
return pfl;
|
||||
|
||||
if (i++ == 0)
|
||||
passfl = pfl;
|
||||
else
|
||||
db_delete_field_log(pfl);
|
||||
|
||||
if (i >= my->n)
|
||||
i = 0;
|
||||
|
||||
my->i = i;
|
||||
return passfl;
|
||||
}
|
||||
|
||||
static void channelRegisterPre(dbChannel *chan, void *pvt,
|
||||
chPostEventFunc **cb_out, void **arg_out, db_field_log *probe)
|
||||
{
|
||||
*cb_out = filter;
|
||||
*arg_out = pvt;
|
||||
}
|
||||
|
||||
static void channel_report(dbChannel *chan, void *pvt, int level, const unsigned short indent)
|
||||
{
|
||||
myStruct *my = (myStruct*) pvt;
|
||||
printf("%*sDecimate (dec): n=%d, i=%d\n", indent, "",
|
||||
my->n, my->i);
|
||||
}
|
||||
|
||||
static chfPluginIf pif = {
|
||||
allocPvt,
|
||||
freePvt,
|
||||
|
||||
NULL, /* parse_error, */
|
||||
parse_ok,
|
||||
|
||||
NULL, /* channel_open, */
|
||||
channelRegisterPre,
|
||||
NULL, /* channelRegisterPost, */
|
||||
channel_report,
|
||||
NULL /* channel_close */
|
||||
};
|
||||
|
||||
static void decInitialize(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
|
||||
if (!firstTime) return;
|
||||
firstTime = 0;
|
||||
|
||||
if (!myStructFreeList)
|
||||
freeListInitPvt(&myStructFreeList, sizeof(myStruct), 64);
|
||||
|
||||
chfPluginRegister("dec", &pif, opts);
|
||||
}
|
||||
|
||||
epicsExportRegistrar(decInitialize);
|
||||
@@ -14,6 +14,8 @@ The following filters are available in this release:
|
||||
|
||||
=item * L<Synchronize|/"Synchronize Filter sync">
|
||||
|
||||
=item * L<Decimation|/"Decimation Filter dec">
|
||||
|
||||
=back
|
||||
|
||||
=head2 Using Filters
|
||||
@@ -245,3 +247,41 @@ periods only when "blue" is true by using
|
||||
...
|
||||
|
||||
=cut
|
||||
|
||||
registrar(decInitialize)
|
||||
|
||||
=head3 Decimation Filter C<"dec">
|
||||
|
||||
This filter is used to reduce the number or rate of monitor updates from a
|
||||
channel by an integer factor C<n> that is provided as a filter argument,
|
||||
discarding the other updates. A true decimation following the original meaning
|
||||
of the word would be achieved by giving C<n> as 10, to only allow every tenth
|
||||
update through.
|
||||
|
||||
=head4 Parameters
|
||||
|
||||
=over
|
||||
|
||||
=item Number C<"n">
|
||||
|
||||
The decimation factor, a positive integer. Giving n=1 is equivalent to a no-op
|
||||
that allows all updates to be passed to the client.
|
||||
|
||||
=back
|
||||
|
||||
This filter is intentionally very simplistic. It passes on the first monitor
|
||||
event that it sees after the channel connects, then discards the next N-1 events
|
||||
before sending the next event. If several clients connect to a channel using the
|
||||
same filter settings they may see completely different data streams since each
|
||||
client gets its own instance of the filter whose event counter starts when that
|
||||
client connects.
|
||||
|
||||
=head4 Example
|
||||
|
||||
To sample a 60Hz channel at 1Hz, a 10Hz channel every 6 seconds or a 1Hz channel
|
||||
once every minute:
|
||||
|
||||
Hal$ camonitor 'test:channel' 'test:channel.{"dec":{"n":60}}'
|
||||
...
|
||||
|
||||
=cut
|
||||
|
||||
@@ -110,7 +110,9 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) {
|
||||
passfl = pfl;
|
||||
pfl = NULL;
|
||||
}
|
||||
break;
|
||||
else
|
||||
db_delete_field_log(pfl);
|
||||
goto save_state;
|
||||
case syncModeLast:
|
||||
if (!actstate && my->laststate) {
|
||||
passfl = my->lastfl;
|
||||
@@ -122,28 +124,34 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) {
|
||||
passfl = pfl;
|
||||
pfl = NULL;
|
||||
}
|
||||
break;
|
||||
else
|
||||
db_delete_field_log(pfl);
|
||||
goto save_state;
|
||||
case syncModeWhile:
|
||||
if (actstate) {
|
||||
if (actstate)
|
||||
passfl = pfl;
|
||||
}
|
||||
else
|
||||
db_delete_field_log(pfl);
|
||||
goto no_shift;
|
||||
case syncModeUnless:
|
||||
if (!actstate) {
|
||||
if (!actstate)
|
||||
passfl = pfl;
|
||||
}
|
||||
else
|
||||
db_delete_field_log(pfl);
|
||||
goto no_shift;
|
||||
}
|
||||
|
||||
if (my->lastfl)
|
||||
db_delete_field_log(my->lastfl);
|
||||
my->lastfl = pfl;
|
||||
my->laststate = actstate;
|
||||
|
||||
/* since no copy is made we can't keep a reference to the returned fl */
|
||||
assert(my->lastfl != passfl);
|
||||
|
||||
no_shift:
|
||||
save_state:
|
||||
my->laststate = actstate;
|
||||
|
||||
no_shift:
|
||||
return passfl;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,3 +55,7 @@ stdRecords_DBD = $(patsubst %,%.dbd,$(stdRecords))
|
||||
dbRecStd_SRCS += $(patsubst %,%.c,$(stdRecords))
|
||||
|
||||
HTMLS += $(patsubst %.dbd.pod,%.html,$(notdir $(wildcard ../rec/*Record.dbd.pod)))
|
||||
|
||||
vpath %.png $(SRC_DIRS)
|
||||
HTMLS += image/compress-1.png
|
||||
HTMLS += image/compress-2.png
|
||||
|
||||
@@ -356,10 +356,10 @@ static long readValue(aaiRecord *prec)
|
||||
recGblSetSevr(prec, SIMM_ALARM, prec->sims);
|
||||
|
||||
if (prec->sdly >= 0) {
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
|
||||
if (!pvt) { /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(CALLBACK));
|
||||
pvt = calloc(1, sizeof(epicsCallback));
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt)
|
||||
|
||||
@@ -122,7 +122,7 @@ recordtype(aai) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
field(MPST,DBF_MENU) {
|
||||
prompt("Post Value Monitors")
|
||||
|
||||
@@ -367,9 +367,9 @@ static long writeValue(aaoRecord *prec)
|
||||
status = pdset->write_aao(prec);
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -122,7 +122,7 @@ recordtype(aao) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
field(MPST,DBF_MENU) {
|
||||
prompt("Post Value Monitors")
|
||||
|
||||
@@ -508,9 +508,9 @@ static long readValue(aiRecord *prec)
|
||||
}
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=title Analog Input Record (ai)
|
||||
@@ -214,7 +214,7 @@ monitoring functionality.
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_DOUBLE) {
|
||||
prompt("Current EGU Value")
|
||||
promptgroup("40 - Input")
|
||||
@@ -516,7 +516,7 @@ simulation mode.
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -547,7 +547,7 @@ The individual routines are described below.
|
||||
|
||||
=head3 Device Support Routines
|
||||
|
||||
=head4 long report(int level)
|
||||
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.
|
||||
@@ -557,7 +557,7 @@ information at higher levels, or to select different types of information with
|
||||
different levels.
|
||||
Level zero should print no more than a small summary.
|
||||
|
||||
=head4 long init(int after)
|
||||
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
|
||||
@@ -565,7 +565,7 @@ the integer parameter C<after> set to 0.
|
||||
The second call happens after all of the C<init_record()> calls have been made,
|
||||
with C<after> set to 1.
|
||||
|
||||
=head4 long init_record(aiRecord *prec)
|
||||
long init_record(aiRecord *prec)
|
||||
|
||||
This optional routine is called by the record initialization code for each ai
|
||||
record instance that has its DTYP field set to use this device support.
|
||||
@@ -582,7 +582,7 @@ C<LINEAR>, but it is not necessary to check that condition first.
|
||||
This same calculation takes place in the C<special_linconv()> routine, so the
|
||||
implementation can usually just call that routine to perform the task.
|
||||
|
||||
=head4 long get_ioint_info(int cmd, aiRecord *prec, IOSCANPVT *piosl)
|
||||
long get_ioint_info(int cmd, aiRecord *prec, IOSCANPVT *piosl)
|
||||
|
||||
This optional routine is called whenever the record's SCAN field is being
|
||||
changed to or from the value C<I/O Intr> to find out which I/O Interrupt Scan
|
||||
@@ -611,7 +611,7 @@ thread.
|
||||
The C<scanIoRequest()> routine is safe to call from an interrupt service routine
|
||||
on embedded architectures (vxWorks and RTEMS).
|
||||
|
||||
=head4 long read_ai(aiRecord *prec)
|
||||
long read_ai(aiRecord *prec)
|
||||
|
||||
This essential routine is called when the record wants a new value from the
|
||||
addressed device.
|
||||
@@ -622,7 +622,7 @@ It is responsible for performing (or at least initiating) a read operation, and
|
||||
|
||||
... return value ...
|
||||
|
||||
=head4 long special_linconv(aiRecord *prec, int after)
|
||||
long special_linconv(aiRecord *prec, int after)
|
||||
|
||||
This optional routine should be provided if the record type's unit conversion
|
||||
features are used by the device support's C<read_ai()> routine returning a
|
||||
|
||||
@@ -574,9 +574,9 @@ static long writeValue(aoRecord *prec)
|
||||
status = dbPutLink(&prec->siol, DBR_DOUBLE, &prec->oval, 1);
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -70,7 +70,7 @@ 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 > DRVL.
|
||||
that DRVH E<gt> DRVL.
|
||||
The result is copied into both the VAL and PVAL fields.
|
||||
|
||||
=head4 Limit Rate of Change
|
||||
@@ -164,9 +164,7 @@ 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
|
||||
Address Specification for information on the format of hardware
|
||||
addresses. The user can see a list of the device support modules
|
||||
currently supported at the user's local site by using the dbst utility
|
||||
in R3.13.
|
||||
addresses.
|
||||
|
||||
For soft records the output link can be a database link, a channel
|
||||
access link, or a constant value. If the link is a constant, no output
|
||||
@@ -573,7 +571,7 @@ information on these fields.
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
field(IVOA,DBF_MENU) {
|
||||
prompt("INVALID output action")
|
||||
@@ -620,7 +618,7 @@ terminated.
|
||||
For compatibility with old device supports that don't know EOFF, if
|
||||
both EOFF and ESLO have their default value, EOFF is set to EGUL.
|
||||
|
||||
If device support includes init_record, it is called.
|
||||
If device support includes C<init_record()>, it is called.
|
||||
|
||||
INIT is set TRUE. This causes PBRK, LBRK, and smoothing to be
|
||||
re-initialized. If "backwards" linear conversion is requested, then VAL
|
||||
@@ -647,10 +645,6 @@ called.
|
||||
INIT is set TRUE. This causes PBRK, LBRK, and smoothing to be
|
||||
re-initialized.
|
||||
|
||||
=item get_value
|
||||
|
||||
Fills in the values of struct valueDes so that they refer to VAL.
|
||||
|
||||
=item get_alarm_double
|
||||
|
||||
Sets the following values:
|
||||
@@ -930,7 +924,7 @@ OUT link type must be either a CONSTANT, DB_LINK, or CA_LINK.
|
||||
This module writes the current value of OVAL.
|
||||
|
||||
If the OUT link type is PV_LINK, then dbCaAddInlink is called by
|
||||
init_record. init_record always returns a value of 2, which means that
|
||||
C<init_record()>. C<init_record()> always returns a value of 2, which means that
|
||||
no conversion will ever be attempted.
|
||||
|
||||
write_ao calls recGblPutLinkValue to write the current value of VAL.
|
||||
|
||||
@@ -304,9 +304,9 @@ static long readValue(biRecord *prec)
|
||||
}
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -69,9 +69,7 @@ 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> for
|
||||
information on the format of the hardware address. Be aware that the format
|
||||
differs between types of cards. You can see a list of device support
|
||||
modules currently supported at the user's local site by using C<dbst>
|
||||
utility (R3.13).
|
||||
differs between types of cards.
|
||||
|
||||
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
|
||||
@@ -94,18 +92,18 @@ the device support module reads a value directly into VAL or the
|
||||
C<Soft Channel> device support is used. The value can also be fetched as one of
|
||||
the strings specified in the ZNAM or ONAM fields. The ZNAM field has a
|
||||
string that corresponds to the 0 state, so when the value is fetched as
|
||||
this string, C<put_enum_str> will return a 0. The ONAM field hold the
|
||||
this string, C<put_enum_str()> will return a 0. The ONAM field hold the
|
||||
string that corresponds to the 1 state, so when the value is fetched as
|
||||
this string, C<put_enum_str> returns a 1.
|
||||
this string, C<put_enum_str()> returns a 1.
|
||||
|
||||
=fields ZNAM, ONAM
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
These parameters are used to present meaningful data to the operator. The
|
||||
C<get_enum_str> record support routine can retrieve the state string
|
||||
corresponding to the VAL's state. If the value is 1, C<get_enum_str> will
|
||||
return the string in the ONAM field; and if 0, C<get_enum_str> will return
|
||||
C<get_enum_str()> record support routine can retrieve the state string
|
||||
corresponding to the VAL's state. If the value is 1, C<get_enum_str()> will
|
||||
return the string in the ONAM field; and if 0, C<get_enum_str()> will return
|
||||
the ZNAM string.
|
||||
|
||||
See L<Fields Common to All Record Types> for more on the record name (NAME)
|
||||
@@ -149,7 +147,7 @@ The LALM fields holds the value of the last occurence of the change of
|
||||
state alarm. It is used to implement the change of state alarm, and thus
|
||||
only has meaning if COSV is MAJOR or MINOR.
|
||||
|
||||
The MSLT field is used by the C<process> record support routine to
|
||||
The MSLT field is used by the C<process()> record support routine to
|
||||
determine if archive and value change monitors are invoked. They are if MSLT
|
||||
is not equal to VAL.
|
||||
|
||||
@@ -164,7 +162,7 @@ these fields.
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
include "dbCommon.dbd"
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup("40 - Input")
|
||||
@@ -286,14 +284,14 @@ these fields.
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
|
||||
=head2 Record Support
|
||||
|
||||
=head3 Record Support Routines
|
||||
|
||||
=head2 C<init_record>
|
||||
long init_record(struct dbCommon *precord, int pass);
|
||||
|
||||
This routine initializes SIMM with the value of SIML if SIML type is a
|
||||
CONSTANT link or creates a channel access link if SIML type is PV_LINK.
|
||||
@@ -303,25 +301,21 @@ This routine next checks to see that device support is available and a
|
||||
device support routine is defined. If neither exist, an error is issued and
|
||||
processing is terminated.
|
||||
|
||||
If device support includes C<init_record>, it is called.
|
||||
If device support includes C<init_record()>, it is called.
|
||||
|
||||
=head2 C<process>
|
||||
long process(struct dbCommon *precord);
|
||||
|
||||
See next section.
|
||||
See L<Record Processing> below.
|
||||
|
||||
=head2 C<get_value>
|
||||
|
||||
Fills in the values of struct valueDes so that they refer to VAL.
|
||||
|
||||
=head2 C<get_enum_str>
|
||||
long get_enum_str(const struct dbAddr *paddr, char *pbuffer);
|
||||
|
||||
Retrieves ASCII string corresponding to VAL.
|
||||
|
||||
=head2 C<get_enum_strs>
|
||||
long get_enum_strs(const struct dbAddr *paddr, struct dbr_enumStrs *p);
|
||||
|
||||
Retrieves ASCII strings for ZNAM and ONAM.
|
||||
|
||||
=head2 C<put_enum_str>
|
||||
long put_enum_str(const struct dbAddr *paddr, const char *pbuffer);
|
||||
|
||||
Check if string matches ZNAM or ONAM, and if it does, sets VAL.
|
||||
|
||||
@@ -329,7 +323,7 @@ Check if string matches ZNAM or ONAM, and if it does, sets VAL.
|
||||
|
||||
Routine process implements the following algorithm:
|
||||
|
||||
=over 1
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
Check to see that the appropriate device support module exists. If it
|
||||
@@ -338,7 +332,7 @@ the PACT field still set to TRUE. This ensures that processes will no
|
||||
longer be called for this record. Thus error storms will not occur.
|
||||
|
||||
=item 2.
|
||||
C<readValue> is called. See L<Input Records> for details.
|
||||
C<readValue()> is called. See L<Input Records> for details.
|
||||
|
||||
=item 3.
|
||||
If PACT has been changed to TRUE, the device support read routine has
|
||||
@@ -350,7 +344,7 @@ Convert.
|
||||
|
||||
=back
|
||||
|
||||
=over 1
|
||||
=over
|
||||
|
||||
=item *
|
||||
status = read_bi
|
||||
@@ -359,7 +353,7 @@ status = read_bi
|
||||
PACT = TRUE
|
||||
|
||||
=item *
|
||||
TIME = tslocaltime
|
||||
C<recGblGetTimeStamp()> is called.
|
||||
|
||||
=item *
|
||||
if status is 0, then set VAL=(0,1) if RVAL is (0, not 0) and UDF = False.
|
||||
@@ -369,7 +363,7 @@ if status is 2, set status = 0
|
||||
|
||||
=back
|
||||
|
||||
=over 1
|
||||
=over
|
||||
|
||||
=item 5.
|
||||
Check alarms: This routine checks to see if the new VAL causes the alarm
|
||||
@@ -381,7 +375,7 @@ Check if monitors should be invoked:
|
||||
|
||||
=back
|
||||
|
||||
=over 1
|
||||
=over
|
||||
|
||||
=item *
|
||||
Alarm monitors are invoked if the alarm status or severity has changed.
|
||||
@@ -397,7 +391,7 @@ NSEV and NSTA are reset to 0.
|
||||
|
||||
=back
|
||||
|
||||
=over 1
|
||||
=over
|
||||
|
||||
=item 7.
|
||||
Scan forward link if necessary, set PACT FALSE, and return.
|
||||
@@ -410,7 +404,7 @@ Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
Each binary input record must have an associated set of device support
|
||||
routines. The primary resposibility of the device support routines is to
|
||||
obtain a new raw input value whenever C<read_bi> is called. The device
|
||||
obtain a new raw input value whenever C<read_bi()> is called. The device
|
||||
support routines are primarily interested in the following fields:
|
||||
|
||||
=fields PACT, DPVT, UDF, NSEV, NSTA, VAL, INP, RVAL, MASK
|
||||
@@ -419,27 +413,37 @@ support routines are primarily interested in the following fields:
|
||||
|
||||
Device support consists of the following routines:
|
||||
|
||||
=head2 C<report(FILE fp, paddr)>
|
||||
long report(int level);
|
||||
|
||||
Not currently used.
|
||||
This optional routine is called by the IOC command C<dbior> and is passed the
|
||||
report level that was requested by the user.
|
||||
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.
|
||||
|
||||
=head2 C<init()>
|
||||
long init(int after);
|
||||
|
||||
This routine is called once during IOC initialization.
|
||||
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
|
||||
the integer parameter C<after> set to 0.
|
||||
The second call happens after all of the C<init_record()> calls have been made,
|
||||
with C<after> set to 1.
|
||||
|
||||
=head2 C<init_record(precord)>
|
||||
long init_record(struct dbCommon *precord);
|
||||
|
||||
This routine is optional. If provided, it is called by the record support
|
||||
C<init_record> routine.
|
||||
C<init_record()> routine.
|
||||
|
||||
=head2 C<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 C<ioEventScan> system each time the record is
|
||||
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) and I/O event list. It must be
|
||||
provided for any device type that can use the ioEvent scanner.
|
||||
|
||||
=head2 C<read_bi(precord)>
|
||||
long read_bi(struct dbCommon *precord);
|
||||
|
||||
This routine must provide a new input value. It returns the following
|
||||
values:
|
||||
@@ -466,25 +470,25 @@ link type must be either CONSTANT, DB_LINK, or CA_LINK.
|
||||
|
||||
=head3 Soft Channel
|
||||
|
||||
C<read_bi> always returns a value of 2, which means that no conversion is
|
||||
C<read_bi()> always returns a value of 2, which means that no conversion is
|
||||
performed.
|
||||
|
||||
If the INP link type is CONSTANT, then the constant value is stored in VAL
|
||||
by C<init_record>, and the UDF is set to FALSE. VAL can be changed via
|
||||
C<dbPut> requests. If the INP link type is PV_LINK, the C<dbCaAddInlink> is
|
||||
called by C<init_record>.
|
||||
by C<init_record()>, and the UDF is set to FALSE. VAL can be changed via
|
||||
C<dbPut()> requests. If the INP link type is PV_LINK, the C<dbCaAddInlink()> is
|
||||
called by C<init_record()>.
|
||||
|
||||
C<read_bi> calls C<recGbleGetLinkValue> to read the current value of VAL.
|
||||
C<read_bi()> calls C<dbGetLinkValue> to read the current value of VAL.
|
||||
See L<Soft Input> for details.
|
||||
|
||||
If the return status of C<recGblGetLinkValue> is zero, then C<read_bi> sets
|
||||
UDF to FALSE. The status of C<recGblGetLinkValue> is returned.
|
||||
If the return status of C<dbGetLinkValue()> is zero, then C<read_bi()> sets
|
||||
UDF to FALSE. The status of C<dbGetLinkValue()> is returned.
|
||||
|
||||
=head3 Raw Soft Channel
|
||||
|
||||
This module is like the previous except that values are read into RVAL.
|
||||
|
||||
C<read_bi> returns a value of 0. Thus the record processing routine will
|
||||
C<read_bi()> returns a value of 0. Thus the record processing routine will
|
||||
force VAL to be 0 or 1.
|
||||
|
||||
=cut
|
||||
|
||||
@@ -98,7 +98,7 @@ struct bodset { /* binary output dset */
|
||||
|
||||
/* control block for callback*/
|
||||
typedef struct myCallback {
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
struct dbCommon *precord;
|
||||
}myCallback;
|
||||
|
||||
@@ -106,7 +106,7 @@ static void checkAlarms(boRecord *);
|
||||
static void monitor(boRecord *);
|
||||
static long writeValue(boRecord *);
|
||||
|
||||
static void myCallbackFunc(CALLBACK *arg)
|
||||
static void myCallbackFunc(epicsCallback *arg)
|
||||
{
|
||||
myCallback *pcallback;
|
||||
boRecord *prec;
|
||||
@@ -439,9 +439,9 @@ static long writeValue(boRecord *prec)
|
||||
status = dbPutLink(&prec->siol, DBR_USHORT, &prec->val, 1);
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -65,9 +65,9 @@ C<losed_loop> or C<supervisory>. If C<supervisory> is specified, the value
|
||||
in the VAL field can be set externally via dbPuts at run-time. If
|
||||
C<closed_loop> is specified, the VAL field's value is obtained from the
|
||||
address specified in the desired output location (DOL) field which can be a
|
||||
database link, a channel access link, or a constant. To achieve continuous
|
||||
control, a database link to a control algorithm record should be entered in
|
||||
the DOL field.
|
||||
database link or a channel access link, but not a constant. To achieve
|
||||
continuous control, a database link to a control algorithm record should be
|
||||
entered in the DOL field.
|
||||
|
||||
L<Address Specification> presents more information on database addresses
|
||||
and links. L<Scanning Specification> explaines the effect of database
|
||||
@@ -130,8 +130,7 @@ 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> for information on the format of
|
||||
hardware addresses. You can see a list of device support modules currently
|
||||
supported at the user's local site by using the C<dbst> utility in R3.13.
|
||||
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
|
||||
@@ -143,9 +142,9 @@ this chapter for more on output to other records.
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
These parameters are used to present meaningful data to the operator, The
|
||||
C<get_enum_str> record support routine can retrieve the state string
|
||||
corresponding to the VAL's state. So, if the value is 1, C<get_enum_str>
|
||||
will return the string in the ONAM field: and if 0, C<get_enum_str> will
|
||||
C<get_enum_str()> record support routine can retrieve the state string
|
||||
corresponding to the VAL's state. So, if the value is 1, C<get_enum_str()>
|
||||
will return the string in the ONAM field: and if 0, C<get_enum_str()> will
|
||||
return the ZNAM string.
|
||||
|
||||
See L<Fields Common to All Record Types> for more on the record name (NAME)
|
||||
@@ -194,7 +193,7 @@ The LALM field holds the value of the last occurrence of the change of
|
||||
state alarm. It is used to implement the change of state alarm, and thus
|
||||
only has meaning if COSV is MINOR or MAJOR.
|
||||
|
||||
The MLST is used by the C<process> record support routine to determine if
|
||||
The MLST is used by the C<process()> record support routine to determine if
|
||||
archive and value change monitors are invoked. They are if MLST is not
|
||||
equal to VAL.
|
||||
|
||||
@@ -366,7 +365,7 @@ information on these fields.
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
field(IVOA,DBF_MENU) {
|
||||
prompt("INVALID outpt action")
|
||||
@@ -400,17 +399,13 @@ exist, and error message is issued and processing is terminated.
|
||||
If DOL is a constant, then VAL is initialized to 1 if its value is nonzero
|
||||
or initialzed to 0 if DOL is zero, and UDF is set to FALSE.
|
||||
|
||||
If device support includes C<init_record>, it is called. VAL is set using
|
||||
If device support includes C<init_record()>, it is called. VAL is set using
|
||||
RVAL, and UDF is set to FALSE.
|
||||
|
||||
=head2 C<process>
|
||||
|
||||
See next section.
|
||||
|
||||
=head2 C<get_value>
|
||||
|
||||
Fills in the values of struct valueDes so that they refer to VAL.
|
||||
|
||||
=head2 C<get_enum_str>
|
||||
|
||||
Retrieves ASCII string corresponding to VAL.
|
||||
@@ -443,7 +438,7 @@ If PACT is FALSE
|
||||
=over
|
||||
|
||||
=item *
|
||||
If DOL is DB_LINK and OMSL is CLOSED_LOOP
|
||||
If DOL holds a link and OMSL is C<closed_loop>
|
||||
|
||||
=over
|
||||
|
||||
@@ -527,27 +522,37 @@ Scan forward link if necessary, set PACT FALSE, and return
|
||||
|
||||
Each binary output record must have an associated set of device support
|
||||
routines. The primary responsibility of the device support routines is to
|
||||
write a new value whenever C<write_bo> is called. The device support routines
|
||||
write a new value whenever C<write_bo()> is called. The device support routines
|
||||
are primarily interested in the following fields:
|
||||
|
||||
=fields PACT, DPVT, NSEV, NSTA, VAL, OUT, RVAL, MASK, RBV
|
||||
|
||||
=head3 Decive Support Routines
|
||||
=head3 Device Support Routines
|
||||
|
||||
Device support consists of the following routines:
|
||||
|
||||
=head2 C<report(FILE fp, paddr)>
|
||||
=head4 long report(int level)
|
||||
|
||||
Not currently used.
|
||||
This optional routine is called by the IOC command C<dbior> and is passed the
|
||||
report level that was requested by the user.
|
||||
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.
|
||||
|
||||
=head2 C<init()>
|
||||
=head4 long init(int after)
|
||||
|
||||
This routine is called once during IOC initialization.
|
||||
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
|
||||
the integer parameter C<after> set to 0.
|
||||
The second call happens after all of the C<init_record()> calls have been made,
|
||||
with C<after> set to 1.
|
||||
|
||||
=head2 C<init_record(precord)>
|
||||
|
||||
This routine is optional. If provided, it is called by record support
|
||||
C<init_record> routine. It should determine MASK if it is needed.
|
||||
C<init_record()> routine. It should determine MASK if it is needed.
|
||||
|
||||
=over
|
||||
|
||||
@@ -593,10 +598,10 @@ link type must be either CONSTANT, DB_LINK, or CA_LINK.
|
||||
|
||||
This module writes the current value of VAL.
|
||||
|
||||
If the OUT link type is PV_LINK, then C<dbCaAddInlink> is called by
|
||||
C<init_record>. C<init_record> always returns a value of 2, which means
|
||||
that no conversion will ever be attempted. C<write_bo> calls
|
||||
C<recGblPutLinkValue> to write the current value of VAL. See L<Soft Output>
|
||||
If the OUT link type is PV_LINK, then C<dbCaAddInlink()> is called by
|
||||
C<init_record()>. C<init_record()> always returns a value of 2, which means
|
||||
that no conversion will ever be attempted. C<write_bo()> calls
|
||||
C<recGblPutLinkValue()> to write the current value of VAL. See L<Soft Output>
|
||||
for details.
|
||||
|
||||
=head3 Raw Soft Channel
|
||||
|
||||
@@ -261,22 +261,22 @@ ATAN: Arc tangent
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
>= : Greater than or equal to
|
||||
C<<< >= >>> : Greater than or equal to
|
||||
|
||||
=item *
|
||||
> : Greater than
|
||||
C<<< > >>> : Greater than
|
||||
|
||||
=item *
|
||||
<= : Less than or equal to
|
||||
C<<< <= >>> : Less than or equal to
|
||||
|
||||
=item *
|
||||
< : Less than
|
||||
C<<< < >>> : Less than
|
||||
|
||||
=item *
|
||||
# : Not equal to
|
||||
C<<< # >>> : Not equal to
|
||||
|
||||
=item *
|
||||
= : Equal to
|
||||
C<<< = >>> : Equal to
|
||||
|
||||
=back
|
||||
|
||||
@@ -285,13 +285,13 @@ ATAN: Arc tangent
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
&& : And
|
||||
C<&&> : And
|
||||
|
||||
=item *
|
||||
|| : Or
|
||||
C<||> : Or
|
||||
|
||||
=item *
|
||||
! : Not
|
||||
C<!> : Not
|
||||
|
||||
=back
|
||||
|
||||
@@ -300,10 +300,10 @@ ATAN: Arc tangent
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
| : Bitwise Or
|
||||
C<|> : Bitwise Or
|
||||
|
||||
=item *
|
||||
& : Bitwise And
|
||||
C<&> : Bitwise And
|
||||
|
||||
=item *
|
||||
OR : Bitwise Or
|
||||
@@ -315,13 +315,13 @@ AND : Bitwise And
|
||||
XOR : Bitwise Exclusive Or
|
||||
|
||||
=item *
|
||||
~ : One's Complement
|
||||
C<~> : One's Complement
|
||||
|
||||
=item *
|
||||
<< : Left shift
|
||||
C<<< << >>> : Left shift
|
||||
|
||||
=item *
|
||||
>> : Right shift
|
||||
C<<< >> >>> : Right shift
|
||||
|
||||
=back
|
||||
|
||||
@@ -330,7 +330,7 @@ XOR : Bitwise Exclusive Or
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
:= : assigns a value (right hand side) to a variable (i.e. field)
|
||||
C<:=> : assigns a value (right hand side) to a variable (i.e. field)
|
||||
|
||||
=back
|
||||
|
||||
@@ -360,35 +360,35 @@ C<A + B + 10>
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
Result is A + B + 10
|
||||
Result is C<A + B + 10>
|
||||
|
||||
=back
|
||||
|
||||
=head3 Relational
|
||||
|
||||
C<(A + B) < (C + D)>
|
||||
C<<< (A + B) < (C + D) >>>
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
Result is 1 if (A + B) < (C + D)
|
||||
Result is 1 if C<<< (A + B) < (C + D) >>>
|
||||
|
||||
=item *
|
||||
Result is 0 if (A + B) >= (C + D)
|
||||
Result is 0 if C<<< (A + B) >= (C + D) >>>
|
||||
|
||||
=back
|
||||
|
||||
=head3 Question Mark
|
||||
|
||||
C<(A + B) < (C + D) ? E : F + L + 10>
|
||||
C<<< (A + B) < (C + D) ? E : F + L + 10 >>>
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
Result is E if (A + B) < (C + D)
|
||||
Result is C<E> if C<<< (A + B) < (C + D) >>>
|
||||
|
||||
=item *
|
||||
Result is F + L + 10 if (A + B) >= (C + D)
|
||||
Result is C<F + L + 10> if C<<< (A + B) >= (C + D) >>>
|
||||
|
||||
=back
|
||||
|
||||
@@ -412,7 +412,7 @@ C<(A + B) < (C + D) ? E : VAL>
|
||||
|
||||
=head3 Logical
|
||||
|
||||
C<A&B>
|
||||
C<A & B>
|
||||
|
||||
=over 1
|
||||
|
||||
@@ -851,10 +851,6 @@ See next section.
|
||||
|
||||
This is called if CALC is changed. C<special> calls postfix.
|
||||
|
||||
=head2 C<get_value>
|
||||
|
||||
Fills in the values of struct valueDes so that the refer to VAL.
|
||||
|
||||
=head2 C<get_units>
|
||||
|
||||
Retrieves EGU.
|
||||
|
||||
@@ -117,8 +117,8 @@ typedef struct calcoutDSET {
|
||||
#define CA_LINKS_NOT_OK 2
|
||||
|
||||
typedef struct rpvtStruct {
|
||||
CALLBACK doOutCb;
|
||||
CALLBACK checkLinkCb;
|
||||
epicsCallback doOutCb;
|
||||
epicsCallback checkLinkCb;
|
||||
short cbScheduled;
|
||||
short caLinkStat; /* NO_CA_LINKS, CA_LINKS_ALL_OK, CA_LINKS_NOT_OK */
|
||||
} rpvtStruct;
|
||||
@@ -128,7 +128,7 @@ static void monitor(calcoutRecord *prec);
|
||||
static int fetch_values(calcoutRecord *prec);
|
||||
static void execOutput(calcoutRecord *prec);
|
||||
static void checkLinks(calcoutRecord *prec);
|
||||
static void checkLinksCallback(CALLBACK *arg);
|
||||
static void checkLinksCallback(epicsCallback *arg);
|
||||
static long writeValue(calcoutRecord *prec);
|
||||
|
||||
int calcoutRecDebug;
|
||||
@@ -702,7 +702,7 @@ static int fetch_values(calcoutRecord *prec)
|
||||
return(status);
|
||||
}
|
||||
|
||||
static void checkLinksCallback(CALLBACK *arg)
|
||||
static void checkLinksCallback(epicsCallback *arg)
|
||||
{
|
||||
|
||||
calcoutRecord *prec;
|
||||
@@ -760,7 +760,7 @@ static void checkLinks(calcoutRecord *prec)
|
||||
prpvt->caLinkStat = NO_CA_LINKS;
|
||||
|
||||
if (!prpvt->cbScheduled && caLinkNc) {
|
||||
/* Schedule another CALLBACK */
|
||||
/* Schedule another epicsCallback */
|
||||
prpvt->cbScheduled = 1;
|
||||
callbackRequestDelayed(&prpvt->checkLinkCb, .5);
|
||||
}
|
||||
|
||||
@@ -293,22 +293,22 @@ ATAN: Arc tangent
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
>= : Greater than or equal to
|
||||
C<<< >= >>> : Greater than or equal to
|
||||
|
||||
=item *
|
||||
> : Greater than
|
||||
C<<< > >>> : Greater than
|
||||
|
||||
=item *
|
||||
<= : Less than or equal to
|
||||
C<<< <= >>> : Less than or equal to
|
||||
|
||||
=item *
|
||||
< : Less than
|
||||
C<<< < >>> : Less than
|
||||
|
||||
=item *
|
||||
# : Not equal to
|
||||
C<<< # >>> : Not equal to
|
||||
|
||||
=item *
|
||||
= : Equal to
|
||||
C<<< = >>> : Equal to
|
||||
|
||||
=back
|
||||
|
||||
@@ -332,10 +332,10 @@ ATAN: Arc tangent
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
| : Bitwise Or
|
||||
C<|> : Bitwise Or
|
||||
|
||||
=item *
|
||||
& : Bitwise And
|
||||
C<&> : Bitwise And
|
||||
|
||||
=item *
|
||||
OR : Bitwise Or
|
||||
@@ -347,13 +347,13 @@ AND : Bitwise And
|
||||
XOR : Bitwise Exclusive Or
|
||||
|
||||
=item *
|
||||
~ : One's Complement
|
||||
C<~> : One's Complement
|
||||
|
||||
=item *
|
||||
<< : Left shift
|
||||
C<<< << >>> : Left shift
|
||||
|
||||
=item *
|
||||
>> : Right shift
|
||||
C<<< >> >>> : Right shift
|
||||
|
||||
=back
|
||||
|
||||
@@ -362,11 +362,11 @@ XOR : Bitwise Exclusive Or
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
:= : assigns a value (right hand side) to a variable (i.e. field)
|
||||
C<:=> : assigns a value (right hand side) to a variable (i.e. field)
|
||||
|
||||
=back
|
||||
|
||||
=head3 Parentheses and Comma
|
||||
=head3 Parentheses, Comma, and Semicolon
|
||||
|
||||
The open and close parentheses are supported. Nested parentheses are
|
||||
supported.
|
||||
@@ -374,6 +374,10 @@ supported.
|
||||
The comma is supported when used to separate the arguments of a binary
|
||||
function.
|
||||
|
||||
The semicolon is used to separate expressions. Although only one
|
||||
traditional calculation expression is allowed, multiple assignment
|
||||
expressions are allowed.
|
||||
|
||||
=head3 Conditional Expression
|
||||
|
||||
The C language's question mark operator is supported. The format is:
|
||||
@@ -388,41 +392,59 @@ C<A + B + 10>
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
Result is A + B + 10
|
||||
Result is C<A + B + 10>
|
||||
|
||||
=back
|
||||
|
||||
=head3 Relational
|
||||
|
||||
C<(A + B) < (C + D)>
|
||||
C<<< (A + B) < (C + D) >>>
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
Result is 1 if (A + B) < (C + D)
|
||||
Result is 1 if C<<< (A + B) < (C + D) >>>
|
||||
|
||||
=item *
|
||||
Result is 0 if (A + B) >= (C + D)
|
||||
Result is 0 if C<<< (A + B) >= (C + D) >>>
|
||||
|
||||
=back
|
||||
|
||||
=head3 Question Mark
|
||||
|
||||
C<(A + B) < (C + D) ? E : F + L + 10>
|
||||
C<<< (A + B) < (C + D) ? E : F + L + 10 >>>
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
Result is E if (A + B) < (C + D)
|
||||
Result is C<E> if C<<< (A + B) < (C + D) >>>
|
||||
|
||||
=item *
|
||||
Result is F + L + 10 if (A + B) >= (C + D)
|
||||
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:
|
||||
|
||||
C<(A + B)<(C + D) ? E>
|
||||
|
||||
=over 1
|
||||
|
||||
=item
|
||||
Result is E if (A + B)<(C + D)
|
||||
|
||||
=item
|
||||
Result is unchanged if (A + B)>=(C + D)
|
||||
|
||||
From 3.14.9 onwards, this expression must be written as
|
||||
C<(A + B) < (C + D) ? E : VAL>
|
||||
|
||||
=back
|
||||
|
||||
=head3 Logical
|
||||
|
||||
C<A&B>
|
||||
C<A & B>
|
||||
|
||||
=over 1
|
||||
|
||||
@@ -447,6 +469,18 @@ Convert result to floating point
|
||||
|
||||
=back
|
||||
|
||||
=head3 Assignment
|
||||
|
||||
C<sin(a); a:=a+D2R>
|
||||
|
||||
=over 1
|
||||
|
||||
=item *
|
||||
Causes the Calc record to output the successive values of a sine curve in
|
||||
1 degree intervals.
|
||||
|
||||
=back
|
||||
|
||||
=head3 Output Parameters
|
||||
|
||||
These parameters specify and control the output capabilities of the Calcout
|
||||
@@ -471,7 +505,7 @@ C<On Change> -- write output every time VAL changes, i.e., every time the
|
||||
result of the expression changes.
|
||||
|
||||
=item *
|
||||
C<When Zero> -- when record is preocessed, write output if VAL is zero.
|
||||
C<When Zero> -- when record is processed, write output if VAL is zero.
|
||||
|
||||
=item *
|
||||
C<When Non-zero> -- when record is processed, write output if VAL is
|
||||
@@ -497,9 +531,9 @@ output is executed. The field is a menu field with two options:
|
||||
If C<Use CALC> is specified, when the record writes its
|
||||
output it will write the result of the expression in the CALC field, that
|
||||
is, it will write the value of the VAL field. If C<Use OCAL> is specified,
|
||||
the record will instead write the result of the expresion in the OCAL
|
||||
the record will instead write the result of the expression in the OCAL
|
||||
field, which is contained in the OVAL field. The OCAL field is exactly like
|
||||
the CALC field and has the same fuctionality it can contain the string
|
||||
the CALC field and has the same functionality it can contain the string
|
||||
representation of an expression which is evaluated at run-time. Thus, if
|
||||
necessary, the record can use the result of the CALC expression to
|
||||
determine if data should be written and can use the result of the OCAL
|
||||
@@ -514,7 +548,7 @@ the wait is over. The field DLYA is equal to 1 during the delay period. The
|
||||
resolution of the delay entry system dependent.
|
||||
|
||||
The IVOA field specifies what action to take with the OUT link if the
|
||||
Calcout record eneters an INVALID alarm status. The options are
|
||||
Calcout record enters an INVALID alarm status. The options are
|
||||
C<Continue normally>, C<Don't drive outputs>, and C<Set output to IVOV>.
|
||||
If the IVOA field is C<Set output to IVOV>, the data entered into the
|
||||
IVOV field is written to the OUT link if the record alarm severity is
|
||||
@@ -529,7 +563,7 @@ are also meant to represent the status of the record at run-time.
|
||||
|
||||
The EGU field contains a string of up to 16 characters which is supplied by
|
||||
the user and which describes the values being operated upon. The string is
|
||||
retrieved whenever the routine C<get_units> is called. The EGU string is
|
||||
retrieved whenever the routine C<get_units()> is called. The EGU string is
|
||||
solely for an operator's sake and does not have to be used.
|
||||
|
||||
The HOPR and LOPR fields on;y refer to the limits if the VAL, HIHI, HIGH,
|
||||
@@ -568,7 +602,7 @@ The CLCV and OLCV fields indicate the validity of the expression in the
|
||||
CALC and OCAL fields respectfully. If the expression in invalid, the field
|
||||
is set to one.
|
||||
|
||||
The DYLA field is set to one during the delay specified in ODLY.
|
||||
The DLYA field is set to one during the delay specified in ODLY.
|
||||
|
||||
See L<Fields Common to All Record Types> for more information on the record
|
||||
name (NAME) and description (DESC) fields.
|
||||
@@ -583,7 +617,7 @@ record support routines. The Calculation alarm is called by the record
|
||||
processing routine when the CALC expression is an invalid one, upon which
|
||||
an error message is generated.
|
||||
|
||||
The following alarm parametersi, which are configured by the user, define the
|
||||
The following alarm parameters, which are configured by the user, define the
|
||||
limit alarms for the VAL field and the severity corresponding to those
|
||||
conditions.
|
||||
|
||||
@@ -599,7 +633,7 @@ common to all record types.
|
||||
These parameters are used to determine when to send monitors for the value
|
||||
fields. These monitors are sent when the value field exceeds the last
|
||||
monitored field by the appropriate deadband, the ADEL for archiver monitors
|
||||
and the MDEL field for all aother types of monitors. If these fields have a
|
||||
and the MDEL field for all other types of monitors. If these fields have a
|
||||
value of zero, every time the value changes, monitors are triggered; if
|
||||
they have a value of -1, every time the record is scanned, monitors are
|
||||
triggered. See L<Monitor Specification> for a complete explanation of
|
||||
@@ -1146,10 +1180,6 @@ See next section.
|
||||
|
||||
This is called id CALC or OCAL is changed. C<special> calls postfix.
|
||||
|
||||
=head2 C<get_value>
|
||||
|
||||
Fills in the values of struct valueDes so that they refer to VAL.
|
||||
|
||||
=head2 C<get_units>
|
||||
|
||||
Retrieves EGU.
|
||||
@@ -1163,13 +1193,13 @@ Retrieves PREC.
|
||||
Sets the upper display and lower display limits for a field. If the field
|
||||
is VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else
|
||||
if the field has upper and lower limits defined they will be used, else the
|
||||
upper and lower macimum values for the field type will be used.
|
||||
upper and lower maximum values for the field type will be used.
|
||||
|
||||
=head2 C<get_control_double>
|
||||
|
||||
Sets the upper control and lower control limits for a field. If the VAL,
|
||||
HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else if the
|
||||
field has upper and lower limits defimed they will be used, else the upper
|
||||
field has upper and lower limits defined they will be used, else the upper
|
||||
and lower maximum values for the field will be used.
|
||||
|
||||
=head2 C<get_alarm_double>
|
||||
@@ -1211,7 +1241,7 @@ honors the alarm hysteresis factor (HYST). Thus the value must change by at
|
||||
least HYST before the alarm status and severity changes.
|
||||
|
||||
=item 4.
|
||||
Determin if the Output Execution Option (OOPT) is met. If it met, either
|
||||
Determine if the Output Execution Option (OOPT) is met. If it met, either
|
||||
execute the output link (and output event) immediately (if ODLY = 0), or
|
||||
schedule a callback after the specified interval. See the explanation for
|
||||
the C<execOutput()> routine below.
|
||||
@@ -1237,7 +1267,7 @@ NSEV and NSTA are reset to 0
|
||||
=back
|
||||
|
||||
=item 6.
|
||||
If no output delay was specified, scan forwark link if necessaru, set PACT
|
||||
If no output delay was specified, scan forward link if necessary, set PACT
|
||||
FALSE, and return.
|
||||
|
||||
=back
|
||||
@@ -1260,7 +1290,7 @@ put the value of OVAL to the OUT link and post the event in OEVT (if
|
||||
non-zero).
|
||||
|
||||
=item 4.
|
||||
If an output delay was implemented, process the forwark link.
|
||||
If an output delay was implemented, process the forward link.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=title Compress Record (compress)
|
||||
=title Compression Record (compress)
|
||||
|
||||
The data compression record is used to collect and compress data from arrays.
|
||||
When the INP field references a data array field, it immediately compresses the
|
||||
@@ -62,11 +62,299 @@ menu(bufferingALG) {
|
||||
}
|
||||
recordtype(compress) {
|
||||
|
||||
=fields VAL
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
|
||||
=head3 Scanning Parameters
|
||||
|
||||
The compression record has the standard fields for specifying under what
|
||||
circumstances the record will be processed. These fields are listed in
|
||||
L<Scan Fields>. In addition, L<Scanning Specification>
|
||||
explains how these fields are used. Since the compression record supports no
|
||||
direct interfaces to hardware, its SCAN field cannot specify C<<< I/O Intr >>>.
|
||||
|
||||
=head3 Algorithms and Related Parameters
|
||||
|
||||
The user specifies the algorithm to be used in the ALG field. There are six possible
|
||||
algorithms which can be specified as follows:
|
||||
|
||||
=head4 Menu compressALG
|
||||
|
||||
=menu compressALG
|
||||
|
||||
The following fields determine what channel to read and how to compress the data:
|
||||
|
||||
=fields ALG, INP, NSAM, N, ILIL, IHIL, OFF, RES
|
||||
|
||||
As stated above, the ALG field specifies which algorithm to be performed on the data.
|
||||
|
||||
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> for information on specifying links.
|
||||
|
||||
|
||||
IHIL and ILIL can be set to provide an initial value filter on the input array.
|
||||
If ILIL E<lt> IHIL, the input elements will be skipped until a value is found
|
||||
that is in the range of ILIL to IHIL. Note that ILIL and IHIL are used only in
|
||||
C<<< N to 1 >>> algorithms.
|
||||
|
||||
OFF provides the offset to the current beginning of the array data.
|
||||
Note that OFF is used only in C<<< N to 1 >>> algorithms.
|
||||
|
||||
The RES field can be accessed at run time to cause the algorithm to reset
|
||||
itself before the maximum number of samples are reached.
|
||||
|
||||
=head4 Algorithms
|
||||
|
||||
B<Circular Buffer> algorithm keeps a circular buffer of length NSAM.
|
||||
Each time the record is processed, it gets the data referenced by INP and puts
|
||||
it into the circular buffer referenced by VAL. The INP can refer to both scalar or
|
||||
array data and VAL is just a time ordered circular buffer of values obtained
|
||||
from INP.
|
||||
Note that N, ILIL, IHIL and OFF are not used in C<<< Circular Buffer >>> algorithm.
|
||||
|
||||
B<Average> takes an average of every element of the array obtained from
|
||||
INP over time; that is, the entire array referenced by INP is retrieved, and for
|
||||
each element, the new average is calculated and placed in the corresponding
|
||||
element of the value buffer. The retrieved array is truncated to be of length
|
||||
NSAM. N successive arrays are averaged and placed in the buffer. Thus, VAL[0]
|
||||
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]
|
||||
|
||||
=begin html
|
||||
|
||||
<img src="image/compress-1.png">
|
||||
|
||||
=end html
|
||||
|
||||
B<N to 1> If any of the C<<< N to 1 >>> algorithms are chosen, then VAL is a circular
|
||||
buffer of NSAM samples.
|
||||
The actual algorithm depends on whether INP references a scalar or an array.
|
||||
|
||||
If INP refers to a scalar, then N successive time ordered samples of INP are taken.
|
||||
After the Nth sample is obtained, a new value determined by the algorithm
|
||||
(Lowest, Highest, or Average), is written to the circular buffer referenced by
|
||||
VAL. If C<<< Low Value >>> the lowest value of all the samples is written; if
|
||||
C<<< High Value >>> the highest value is written; and if C<<< Average >>>, the
|
||||
average of all the samples are written. The C<<< Median >>> setting behaves
|
||||
like C<<< Average >>> with scalar input data.
|
||||
|
||||
If INP refers to an array, then the following applies:
|
||||
|
||||
=over
|
||||
|
||||
=item C<<< N to 1 Low Value >>>
|
||||
|
||||
Compress N to 1 samples, keeping the lowest value.
|
||||
|
||||
=item C<<< N to 1 High Value >>>
|
||||
|
||||
Compress N to 1 samples, keeping the highest value.
|
||||
|
||||
=item C<<< N to 1 Average >>>
|
||||
|
||||
Compress N to 1 samples, taking the average value.
|
||||
|
||||
=item C<<< N to 1 Median >>>
|
||||
|
||||
Compress N to 1 samples, taking the median value.
|
||||
|
||||
=back
|
||||
|
||||
The compression record keeps NSAM data samples.
|
||||
|
||||
The field N determines the number of elements to compress into each result.
|
||||
|
||||
Thus, if NSAM was 3, and N was also equal to 3, then the algorithms would work
|
||||
as in the following diagram:
|
||||
|
||||
=begin html
|
||||
|
||||
<img src="image/compress-2.png">
|
||||
|
||||
=end html
|
||||
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
These parameters are used to present meaningful data to the operator. They
|
||||
display the value and other parameters of the record either textually or
|
||||
graphically.
|
||||
|
||||
=fields EGU, HOPR, LOPR, PREC, NAME, DESC
|
||||
|
||||
The EGU field should be given a string that describes the value of VAL, but is
|
||||
used whenever the C<<< get_units >>> record support routine is called.
|
||||
|
||||
The HOPR and LOPR fields only specify the upper and lower display limits for
|
||||
VAL, HIHI, HIGH, LOLO and LOW fields.
|
||||
|
||||
PREC controls the floating-point precision whenever C<<< get_precision >>> is
|
||||
called, and the field being referenced is the VAL field (i.e., one of the values
|
||||
contained in the circular buffer).
|
||||
|
||||
See L<Fields Common to All Record Types>
|
||||
for more on the record name (NAME) and description (DESC) fields.
|
||||
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The compression record has the alarm parameters common to all record types
|
||||
described in L<Alarm Fields>.
|
||||
|
||||
=head3 Run-time Parameters
|
||||
|
||||
These parameters are used by the run-time code for processing the data
|
||||
compression algorithm. They are not configurable by the user, though some are
|
||||
accessible at run-time. They can represent the current state of the waveform or
|
||||
of the record whose field is referenced by the INP field.
|
||||
|
||||
=fields NUSE, OUSE, BPTR, SPTR, WPTR, CVB, INPN, INX
|
||||
|
||||
NUSE and OUSE hold the current and previous number of elements stored in VAL.
|
||||
|
||||
BPTR is a pointer that refers to the buffer referenced by VAL.
|
||||
|
||||
SPTR points to an array that is used for array averages.
|
||||
|
||||
WPTR is used by the dbGetlinks routines.
|
||||
|
||||
=head2 Record Support
|
||||
|
||||
=head3 Record Support Routines
|
||||
|
||||
long init_record(struct dbCommon *precord, int pass)
|
||||
|
||||
Space for all necessary arrays is allocated. The addresses are stored in the
|
||||
appropriate fields in the record.
|
||||
|
||||
long process(struct dbCommon *precord)
|
||||
|
||||
See L<Record Processing> below.
|
||||
|
||||
long special(struct dbAddr *paddr, int after)
|
||||
|
||||
This routine is called when RSET, ALG, or N are set. It performs a reset.
|
||||
|
||||
long cvt_dbaddr(struct dbAddr *paddr)
|
||||
|
||||
This is called by dbNameToAddr. It makes the dbAddr structure refer to the
|
||||
actual buffer holding the result.
|
||||
|
||||
long get_array_info(struct dbAddr *paddr, long *no_elements, long *offset)
|
||||
|
||||
Obtains values from the circular buffer referenced by VAL.
|
||||
|
||||
long put_array_info(struct dbAddr *paddr, long nNew);
|
||||
|
||||
Writes values into the circular buffer referenced by VAL.
|
||||
|
||||
long get_units(struct dbAddr *paddr, char *units);
|
||||
|
||||
Retrieves EGU.
|
||||
|
||||
long get_precision(const struct dbAddr *paddr, long *precision);
|
||||
|
||||
Retrieves PREC.
|
||||
|
||||
long get_graphic_double(struct dbAddr *paddr, struct dbr_grDouble *p);
|
||||
|
||||
Sets the upper display and lower display limits for a field. If the field is
|
||||
VAL, the limits are set to HOPR and LOPR, else if the field has upper and lower
|
||||
limits defined they will be used, else the upper and lower maximum values for
|
||||
the field type will be used.
|
||||
|
||||
long get_control_double(struct dbAddr *paddr, struct dbr_ctrlDouble *p);
|
||||
|
||||
Sets the upper control and the lower control limits for a field. If the field is
|
||||
VAL, the limits are set to HOPR and LOPR, else if the field has upper and lower
|
||||
limits defined they will be used, else the upper and lower maximum values for
|
||||
the field type will be used.
|
||||
|
||||
=head3 Record Processing
|
||||
|
||||
Routine process implements the following algorithm:
|
||||
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
If INP is not a database link, check monitors and the forward link and return.
|
||||
|
||||
=item 2.
|
||||
|
||||
Get the current data referenced by INP.
|
||||
|
||||
=item 3.
|
||||
|
||||
Perform the appropriate algorithm:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
Average: Read N successive instances of INP and perform an element by element
|
||||
average. Until N instances have been obtained it just return without checking
|
||||
monitors or the forward link. When N instances have been obtained complete the
|
||||
algorithm, store the result in the VAL array, check monitors and the forward
|
||||
link, and return.
|
||||
|
||||
=item *
|
||||
|
||||
Circular Buffer: Write the values obtained from INP into the VAL array as a
|
||||
circular buffer, check monitors and the forward link, and return.
|
||||
|
||||
=item *
|
||||
|
||||
N to 1 xxx when INP refers to a scalar: Obtain N successive values from INP and
|
||||
apply the N to 1 xxx algorithm to these values. Until N values are obtained
|
||||
monitors and forward links are not triggered. When N successive values have been
|
||||
obtained, complete the algorithm, check monitors and trigger the forward link,
|
||||
and return.
|
||||
|
||||
=item *
|
||||
|
||||
N to 1 xxx when INP refers to an array: The ILIL and IHIL are honored if ILIL
|
||||
E<lt> IHIL. The input array is divided into subarrays of length N. The specified
|
||||
N to 1 xxx compression algorithm is applied to each sub-array and the result
|
||||
stored in the array referenced by VAL. The monitors and forward link are
|
||||
checked.
|
||||
|
||||
=back
|
||||
|
||||
=item 4.
|
||||
|
||||
If success, set UDF to FALSE.
|
||||
|
||||
=item 5.
|
||||
|
||||
Check to see if monitors should be invoked:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
Alarm monitors are invoked if the alarm status or severity has changed.
|
||||
|
||||
=item *
|
||||
|
||||
NSEV and NSTA are reset to 0.
|
||||
|
||||
=back
|
||||
|
||||
=item 6.
|
||||
|
||||
Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_NOACCESS) {
|
||||
prompt("Value")
|
||||
asl(ASL0)
|
||||
|
||||
@@ -128,7 +128,7 @@ value on the VAL field.
|
||||
The HOPR and LOPR fields determine the upper and lower display limits for
|
||||
graphic displays and the upper and lower control limits for control
|
||||
displays. They apply to the VAL, HIHI, HIGH, LOW, and LOLO fields. The
|
||||
record support routines C<get_graphic_double> or C<get_control_double>
|
||||
record support routines C<get_graphic_double()> and C<get_control_double()>
|
||||
retrieve HOPR and LOPR.
|
||||
|
||||
See L<Fields Common to All Record Types> for more on the record name (NAME)
|
||||
@@ -379,11 +379,6 @@ and the DOL link, a non-zero value is returned if an error occurs.
|
||||
|
||||
See next section.
|
||||
|
||||
=head2 C<get_value()>
|
||||
|
||||
This routine fills in the members of C<struct valueDes> with the VAL fields
|
||||
value and characteristics.
|
||||
|
||||
=head2 C<get_units()>
|
||||
|
||||
The routine copies the string specified in the EGU field to the location
|
||||
@@ -399,13 +394,13 @@ routine is called.
|
||||
|
||||
=head2 C<get_control_double()>
|
||||
|
||||
Same as the C<get_graphic_double> routine except that it uses the
|
||||
Same as the C<get_graphic_double()> routine except that it uses the
|
||||
C<dbr_ctrlDouble> structure.
|
||||
|
||||
=head2 C<get_alarm_double()>
|
||||
|
||||
This sets the members of the C<dbr_alDouble> structure to the specified
|
||||
alarm limits if the referenced field is VAL:
|
||||
alarm limits when the referenced field is VAL:
|
||||
|
||||
=over
|
||||
|
||||
@@ -427,26 +422,32 @@ is called.
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
The C<process()> routine first retrieves a value for DOL and places it in
|
||||
VAL if OMSL is set to colsed loop mode. If an error occurs, then UDF is set
|
||||
to FALSE.
|
||||
The C<process()> routine first checks that DOL is not a constant link and
|
||||
that OMSL is set to "closed_loop". If so, it retrieves a value through DOL
|
||||
and places it into VAL. If no errors occur, UDF is set to FALSE.
|
||||
|
||||
=item 2.
|
||||
PACT is set TRUE
|
||||
PACT is set TRUE, and the record's timestamp is set.
|
||||
|
||||
=item 3.
|
||||
VAL is then sent to all the records specified in the OUTA-OUTH fields by
|
||||
calling C<recGblePutLinkValue()> for each link.
|
||||
A value is fetched from SELL and placed into SELN.
|
||||
|
||||
=item 4.
|
||||
Alarms are checked and monitors are called if conditions apply.
|
||||
Alarms ranges are checked against the contents of the VAL field.
|
||||
|
||||
=item 5.
|
||||
The data fanout's own forward link is then processed.
|
||||
VAL is then sent through the OUTA-OUTH links by calling C<dbPutLink()> for
|
||||
each link, conditional on the setting of SELM and the value in SELN.
|
||||
|
||||
=item 6.
|
||||
PACT is set FALSE, and the C<process()> routine returns. A -1 is returned
|
||||
if there was an error writing values to one of the output links.
|
||||
Value and archive monitors are posted on the VAL field if appropriate based on
|
||||
the settings of MDEL and ADEL respectively.
|
||||
|
||||
=item 7.
|
||||
The data fanout's forward link FLNK is processed.
|
||||
|
||||
=item 6.
|
||||
PACT is set FALSE, and the C<process()> routine returns.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -199,9 +199,9 @@ static long readValue(eventRecord *prec)
|
||||
}
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(event) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_STRING) {
|
||||
prompt("Event Name To Post")
|
||||
promptgroup("40 - Input")
|
||||
special(SPC_MOD)
|
||||
asl(ASL0)
|
||||
size(40)
|
||||
}
|
||||
%#include "dbScan.h"
|
||||
field(EPVT, DBF_NOACCESS) {
|
||||
prompt("Event private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("EVENTPVT epvt")
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(SIOL,DBF_INLINK) {
|
||||
prompt("Simulation Input Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SVAL,DBF_STRING) {
|
||||
prompt("Simulation Value")
|
||||
size(40)
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Simulation Mode Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
special(SPC_MOD)
|
||||
interest(1)
|
||||
menu(menuYesNo)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Simulation Mode Severity")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(OLDSIMM,DBF_MENU) {
|
||||
prompt("Prev. Simulation Mode")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SSCN,DBF_MENU) {
|
||||
prompt("Sim. Mode Scan")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
initial("65535")
|
||||
}
|
||||
field(SDLY,DBF_DOUBLE) {
|
||||
prompt("Sim. Mode Async Delay")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
initial("-1.0")
|
||||
}
|
||||
%#include "callback.h"
|
||||
field(SIMPVT,DBF_NOACCESS) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=title 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.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The records in this field fall into the following groups of parameters:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
scan parameters
|
||||
|
||||
=item *
|
||||
|
||||
read parameters
|
||||
|
||||
=item *
|
||||
|
||||
event number parameters
|
||||
|
||||
=item *
|
||||
|
||||
simulation mode parameters
|
||||
|
||||
=back
|
||||
|
||||
=recordtype event
|
||||
|
||||
=cut
|
||||
|
||||
recordtype(event) {
|
||||
include "dbCommon.dbd"
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The event record has the standard fields for specifying under what circumstances
|
||||
it will be processed. If the SCAN field specifies C<I/O Intr>, then device
|
||||
support will provide an interrupt handler, posting an event number when an I/O
|
||||
interrupt occurs. These fields are listed in L<Scan Fields>. In addition,
|
||||
L<Scanning Specification> explains how the scanning fields work. Note that I/O
|
||||
event scanning is only supported for those card types that interrupt.
|
||||
|
||||
=head3 Event Number 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.
|
||||
|
||||
=fields VAL
|
||||
|
||||
=cut
|
||||
|
||||
field(VAL,DBF_STRING) {
|
||||
prompt("Event Name To Post")
|
||||
promptgroup("40 - Input")
|
||||
special(SPC_MOD)
|
||||
asl(ASL0)
|
||||
size(40)
|
||||
}
|
||||
%#include "dbScan.h"
|
||||
field(EPVT, DBF_NOACCESS) {
|
||||
prompt("Event private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("EVENTPVT epvt")
|
||||
}
|
||||
|
||||
=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
|
||||
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> 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>.
|
||||
|
||||
=fields INP, DTYP
|
||||
|
||||
=cut
|
||||
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
See L<Fields Common to All Record Types> 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.
|
||||
|
||||
=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.
|
||||
|
||||
=fields SIOL, SVAL, SIML, SIMM, SIMS
|
||||
|
||||
=cut
|
||||
|
||||
field(SIOL,DBF_INLINK) {
|
||||
prompt("Sim Input Specifctn")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SVAL,DBF_STRING) {
|
||||
prompt("Simulation Value")
|
||||
size(40)
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Sim Mode Location")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
special(SPC_MOD)
|
||||
interest(1)
|
||||
menu(menuYesNo)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Sim mode Alarm Svrty")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(OLDSIMM,DBF_MENU) {
|
||||
prompt("Prev. Simulation Mode")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SSCN,DBF_MENU) {
|
||||
prompt("Sim. Mode Scan")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
initial("65535")
|
||||
}
|
||||
field(SDLY,DBF_DOUBLE) {
|
||||
prompt("Sim. Mode Async Delay")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
initial("-1.0")
|
||||
}
|
||||
%#include "callback.h"
|
||||
field(SIMPVT,DBF_NOACCESS) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
|
||||
=head2 Record Support
|
||||
|
||||
=head3 Record Support Routines
|
||||
|
||||
=head4 init_record
|
||||
|
||||
This routine initializes SIMM with the value of SIML if SIML type is a CONSTANT
|
||||
link or creates a channel access link if SIML type is PV_LINK. SVAL is likewise
|
||||
initialized if SIOL is CONSTANT or PV_LINK.
|
||||
|
||||
If device support includes C<init_record()>, it is called.
|
||||
|
||||
=head4 process
|
||||
|
||||
See next section.
|
||||
|
||||
=head3 Record Processing
|
||||
|
||||
Routine process implements the following algorithm:
|
||||
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
readValue is called. See L<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.
|
||||
|
||||
=item 3.
|
||||
|
||||
If VAL E<gt> 0, post event number VAL.
|
||||
|
||||
=item 4.
|
||||
|
||||
Check to see if monitors should be invoked. Alarm monitors are invoked if the
|
||||
alarm status or severity has chanet to 0.
|
||||
|
||||
=item 5.
|
||||
|
||||
Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Device Support
|
||||
|
||||
=head3 Fields of Interest To Device Support
|
||||
|
||||
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
|
||||
|
||||
=head3 Device Support Routines
|
||||
|
||||
Device support consists of the following routines:
|
||||
|
||||
=head4 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.
|
||||
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.
|
||||
|
||||
=head4 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
|
||||
the integer parameter C<after> set to 0.
|
||||
The second call happens after all of the C<init_record()> calls have been made,
|
||||
with C<after> set to 1.
|
||||
|
||||
=head4 init_record
|
||||
|
||||
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)
|
||||
|
||||
This routine is called by the ioEventScan system each time the record is added
|
||||
or deleted from an I/O event scan list. 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.
|
||||
|
||||
=head4 read_event
|
||||
|
||||
read_event(precord)
|
||||
|
||||
This routine returns the following values:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
0: Success.
|
||||
|
||||
=item *
|
||||
|
||||
Other: Error.
|
||||
|
||||
=back
|
||||
|
||||
=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.
|
||||
|
||||
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()>.
|
||||
|
||||
C<read_event> calls recGblGetLinkValue to read the current value of VAL. See
|
||||
L<Input Records> for details on soft input.
|
||||
|
||||
=cut
|
||||
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
menu(fanoutSELM) {
|
||||
choice(fanoutSELM_All,"All")
|
||||
choice(fanoutSELM_Specified,"Specified")
|
||||
choice(fanoutSELM_Mask,"Mask")
|
||||
}
|
||||
recordtype(fanout) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_LONG) {
|
||||
prompt("Used to trigger")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(SELM,DBF_MENU) {
|
||||
prompt("Select Mechanism")
|
||||
promptgroup("30 - Action")
|
||||
interest(1)
|
||||
menu(fanoutSELM)
|
||||
}
|
||||
field(SELN,DBF_USHORT) {
|
||||
prompt("Link Selection")
|
||||
interest(1)
|
||||
initial("1")
|
||||
}
|
||||
field(SELL,DBF_INLINK) {
|
||||
prompt("Link Selection Loc")
|
||||
promptgroup("30 - Action")
|
||||
interest(1)
|
||||
}
|
||||
field(OFFS,DBF_SHORT) {
|
||||
prompt("Offset for Specified")
|
||||
promptgroup("30 - Action")
|
||||
interest(1)
|
||||
initial("0")
|
||||
}
|
||||
field(SHFT,DBF_SHORT) {
|
||||
prompt("Shift for Mask mode")
|
||||
promptgroup("30 - Action")
|
||||
interest(1)
|
||||
initial("-1")
|
||||
}
|
||||
field(LNK0,DBF_FWDLINK) {
|
||||
prompt("Forward Link 0")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK1,DBF_FWDLINK) {
|
||||
prompt("Forward Link 1")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK2,DBF_FWDLINK) {
|
||||
prompt("Forward Link 2")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK3,DBF_FWDLINK) {
|
||||
prompt("Forward Link 3")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK4,DBF_FWDLINK) {
|
||||
prompt("Forward Link 4")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK5,DBF_FWDLINK) {
|
||||
prompt("Forward Link 5")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK6,DBF_FWDLINK) {
|
||||
prompt("Forward Link 6")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK7,DBF_FWDLINK) {
|
||||
prompt("Forward Link 7")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK8,DBF_FWDLINK) {
|
||||
prompt("Forward Link 8")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK9,DBF_FWDLINK) {
|
||||
prompt("Forward Link 9")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKA,DBF_FWDLINK) {
|
||||
prompt("Forward Link 10")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKB,DBF_FWDLINK) {
|
||||
prompt("Forward Link 11")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKC,DBF_FWDLINK) {
|
||||
prompt("Forward Link 12")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKD,DBF_FWDLINK) {
|
||||
prompt("Forward Link 13")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKE,DBF_FWDLINK) {
|
||||
prompt("Forward Link 14")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKF,DBF_FWDLINK) {
|
||||
prompt("Forward Link 15")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=title Fanout Record (fanout)
|
||||
|
||||
The fanout record uses several forward processing links to force multiple
|
||||
passive records to scan. When more than one record needs to be scanned as the
|
||||
result of a record being processed, the forward link of that record can specify
|
||||
a fanout record. The fanout record can specify up to sixteen other records to
|
||||
process. If more than sixteen are needed, one of the forward links in the fanout
|
||||
record (or its FLNK field) can point to another fanout record.
|
||||
|
||||
B<NOTE: Fanout records only propagate processing, not data.> The dfanout or
|
||||
data fanout record can, on the other hand, send data to other records.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The fanout record's fields fall into the following categories:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
scan parameters
|
||||
|
||||
=item *
|
||||
|
||||
operator display parameters
|
||||
|
||||
=item *
|
||||
|
||||
run-time parameters.
|
||||
|
||||
=back
|
||||
|
||||
=recordtype fanout
|
||||
|
||||
=cut
|
||||
|
||||
menu(fanoutSELM) {
|
||||
choice(fanoutSELM_All,"All")
|
||||
choice(fanoutSELM_Specified,"Specified")
|
||||
choice(fanoutSELM_Mask,"Mask")
|
||||
}
|
||||
|
||||
recordtype(fanout) {
|
||||
include "dbCommon.dbd"
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The forward link fields of the fanout record (LNK0-LNK9, LNKA-LNKF) specify
|
||||
records to be scanned. The records to be processed must specify C<Passive> in
|
||||
their SCAN fields; otherwise the forward link will not cause them to process.
|
||||
Also when specifying database links for the fanout record, the user needs only
|
||||
to specify the record name. As no value is being sent or retrieved, a field name
|
||||
is only required when the link will be over Channel Access, in which case the
|
||||
field PROC must be named.
|
||||
|
||||
The SELM, SELN, and SELL fields specify the order of processing for the forward
|
||||
links. The select mechanism menu field (SELM) has three choices:
|
||||
|
||||
=menu fanoutSELM
|
||||
|
||||
How the SELM value affects which links to process and in which order is as
|
||||
follows:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
B<All>
|
||||
Links are processed in numerical order - LNK0, LNK1, etc.
|
||||
|
||||
=item *
|
||||
|
||||
B<Specified> The sum of the values in the SELN and OFFS fields is used as the
|
||||
specifier of which link to process. For instance, with OFFS=0 and SELN=1, the
|
||||
record targeted by LNK1 will be processed.
|
||||
|
||||
=item *
|
||||
|
||||
B<Mask> The individual bits in SELN are shifted by SHFT bits (negative means
|
||||
shift left) and the result used to select which links to process as follows:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If bit 0 (LSB) is set, LNK0 is processed.
|
||||
|
||||
=item *
|
||||
|
||||
If bit 1 is set, LNK2 is processed.
|
||||
|
||||
=item *
|
||||
|
||||
If bit 2 is set, LNK3 is processed, etc.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
SELN reads its value from SELL. SELL can be a constant, a database link, or a
|
||||
channel access link. If a constant, SELN is initialized with the constant value
|
||||
and can be changed via dbPuts. For database/channel access links, SELN is
|
||||
retrieved from SELL each time the record is processed and can also be changed
|
||||
via dbPuts.
|
||||
|
||||
The Fanout record also has the standard scanning fields common to all records.
|
||||
These fields are listed in L<Scan Fields>. In addition,
|
||||
L<Scanning Specification> explains in more detail how forward links and the
|
||||
scanning algorithms work.
|
||||
|
||||
=fields SELM, SELN, SELL, OFFS, SHFT, LNK0, LNK1, LNK2, LNK3, LNK4, LNK5, LNK6, LNK7, LNK8, LNK9, LNKA, LNKB, LNKC, LNKD, LNKE, LNKF
|
||||
|
||||
=cut
|
||||
|
||||
field(VAL,DBF_LONG) {
|
||||
prompt("Used to trigger")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(SELM,DBF_MENU) {
|
||||
prompt("Select Mechanism")
|
||||
promptgroup("30 - Action")
|
||||
interest(1)
|
||||
menu(fanoutSELM)
|
||||
}
|
||||
field(SELN,DBF_USHORT) {
|
||||
prompt("Link Selection")
|
||||
interest(1)
|
||||
initial("1")
|
||||
}
|
||||
field(SELL,DBF_INLINK) {
|
||||
prompt("Link Selection Loc")
|
||||
promptgroup("30 - Action")
|
||||
interest(1)
|
||||
}
|
||||
field(OFFS,DBF_SHORT) {
|
||||
prompt("Offset for Specified")
|
||||
promptgroup("30 - Action")
|
||||
interest(1)
|
||||
initial("0")
|
||||
}
|
||||
field(SHFT,DBF_SHORT) {
|
||||
prompt("Shift for Mask mode")
|
||||
promptgroup("30 - Action")
|
||||
interest(1)
|
||||
initial("-1")
|
||||
}
|
||||
field(LNK0,DBF_FWDLINK) {
|
||||
prompt("Forward Link 0")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK1,DBF_FWDLINK) {
|
||||
prompt("Forward Link 1")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK2,DBF_FWDLINK) {
|
||||
prompt("Forward Link 2")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK3,DBF_FWDLINK) {
|
||||
prompt("Forward Link 3")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK4,DBF_FWDLINK) {
|
||||
prompt("Forward Link 4")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK5,DBF_FWDLINK) {
|
||||
prompt("Forward Link 5")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK6,DBF_FWDLINK) {
|
||||
prompt("Forward Link 6")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK7,DBF_FWDLINK) {
|
||||
prompt("Forward Link 7")
|
||||
promptgroup("51 - Output 0-7")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK8,DBF_FWDLINK) {
|
||||
prompt("Forward Link 8")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNK9,DBF_FWDLINK) {
|
||||
prompt("Forward Link 9")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKA,DBF_FWDLINK) {
|
||||
prompt("Forward Link 10")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKB,DBF_FWDLINK) {
|
||||
prompt("Forward Link 11")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKC,DBF_FWDLINK) {
|
||||
prompt("Forward Link 12")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKD,DBF_FWDLINK) {
|
||||
prompt("Forward Link 13")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKE,DBF_FWDLINK) {
|
||||
prompt("Forward Link 14")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
field(LNKF,DBF_FWDLINK) {
|
||||
prompt("Forward Link 15")
|
||||
promptgroup("52 - Output 8-F")
|
||||
interest(1)
|
||||
}
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
These parameters are used to present meaningful data to the operator. See
|
||||
L<Fields Common to All Record Types> for more on these fields.
|
||||
|
||||
=fields NAME, DESC
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The Fanout record has the alarm parameters common to all record types.
|
||||
L<Alarm Fields> lists other fields related to a alarms that are common to all
|
||||
record types.
|
||||
|
||||
=head3 Run-time Parameters
|
||||
|
||||
The VAL field performs no specific function, but a Channel Access put to it will
|
||||
cause the record to process.
|
||||
|
||||
=fields VAL
|
||||
|
||||
=head2 Record Support
|
||||
|
||||
=head3 Record Support Routines
|
||||
|
||||
=head4 init_record
|
||||
|
||||
This routine initializes SELN with the value of SELL, if SELL type is CONSTANT
|
||||
link, or creates a channel access link if SELL type is PV_LINK.
|
||||
|
||||
=head4 process
|
||||
|
||||
See next section.
|
||||
|
||||
=head3 Record Processing
|
||||
|
||||
Routine process implements the following algorithm:
|
||||
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
PACT is set to TRUE.
|
||||
|
||||
=item 2.
|
||||
|
||||
The link selection SELN is fetched.
|
||||
|
||||
=item 3.
|
||||
|
||||
Depending on the selection mechanism, the link selection forward links are
|
||||
processed, and UDF is set to FALSE.
|
||||
|
||||
=item 4.
|
||||
|
||||
Check to see if monitors should be invoked:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
Alarm monitors are invoked if the alarm status or severity has changed.
|
||||
|
||||
=item *
|
||||
|
||||
NSEV and NSTA are reset to 0.
|
||||
|
||||
=back
|
||||
|
||||
=item 5.
|
||||
|
||||
Scan forward link field FLNK if used, set PACT FALSE, and return.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
}
|
||||
@@ -100,7 +100,7 @@ struct histogramdset { /* histogram input dset */
|
||||
|
||||
/* control block for callback*/
|
||||
typedef struct myCallback {
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
histogramRecord *prec;
|
||||
} myCallback;
|
||||
|
||||
@@ -110,7 +110,7 @@ static void monitor(histogramRecord *);
|
||||
static long readValue(histogramRecord *);
|
||||
|
||||
|
||||
static void wdogCallback(CALLBACK *arg)
|
||||
static void wdogCallback(epicsCallback *arg)
|
||||
{
|
||||
myCallback *pcallback;
|
||||
histogramRecord *prec;
|
||||
@@ -403,9 +403,9 @@ static long readValue(histogramRecord *prec)
|
||||
}
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -154,7 +154,7 @@ recordtype(histogram) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
field(HOPR,DBF_ULONG) {
|
||||
prompt("High Operating Range")
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
@@ -420,9 +420,9 @@ static long readValue(int64inRecord *prec)
|
||||
}
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -313,7 +313,7 @@ simulation mode.
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -396,9 +396,9 @@ static long writeValue(int64outRecord *prec)
|
||||
status = dbPutLink(&prec->siol, DBR_INT64, &prec->val, 1);
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -350,7 +350,7 @@ simulation mode.
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
|
||||
=head3 Invalid Alarm Output Action
|
||||
|
||||
@@ -428,9 +428,9 @@ static long readValue(longinRecord *prec)
|
||||
}
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(longin) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_LONG) {
|
||||
prompt("Current value")
|
||||
promptgroup("40 - Input")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(EGU,DBF_STRING) {
|
||||
prompt("Engineering Units")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
}
|
||||
field(HOPR,DBF_LONG) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOPR,DBF_LONG) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIHI,DBF_LONG) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOLO,DBF_LONG) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIGH,DBF_LONG) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOW,DBF_LONG) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
prompt("Lolo Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
prompt("High Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
prompt("Low Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_LONG) {
|
||||
prompt("Alarm Deadband")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
}
|
||||
field(AFTC, DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Time Constant")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
}
|
||||
field(AFVL, DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Value")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ADEL,DBF_LONG) {
|
||||
prompt("Archive Deadband")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
}
|
||||
field(MDEL,DBF_LONG) {
|
||||
prompt("Monitor Deadband")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
}
|
||||
field(LALM,DBF_LONG) {
|
||||
prompt("Last Value Alarmed")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ALST,DBF_LONG) {
|
||||
prompt("Last Value Archived")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(MLST,DBF_LONG) {
|
||||
prompt("Last Val Monitored")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(SIOL,DBF_INLINK) {
|
||||
prompt("Simulation Input Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SVAL,DBF_LONG) {
|
||||
prompt("Simulation Value")
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Simulation Mode Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
special(SPC_MOD)
|
||||
interest(1)
|
||||
menu(menuYesNo)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Simulation Mode Severity")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(OLDSIMM,DBF_MENU) {
|
||||
prompt("Prev. Simulation Mode")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SSCN,DBF_MENU) {
|
||||
prompt("Sim. Mode Scan")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
initial("65535")
|
||||
}
|
||||
field(SDLY,DBF_DOUBLE) {
|
||||
prompt("Sim. Mode Async Delay")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
initial("-1.0")
|
||||
}
|
||||
%#include "callback.h"
|
||||
field(SIMPVT,DBF_NOACCESS) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,485 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=title Long Input Record (longin)
|
||||
|
||||
The normal use for the long input record or "longin" record is to retrieve a
|
||||
long integer value of up to 32 bits. Device support routines are provided to
|
||||
support direct interfaces to hardware. In addition, the C<<< Soft Channel >>>
|
||||
device module is provided to obtain input via database or channel access links
|
||||
or via dbPutField or dbPutLink requests.
|
||||
|
||||
=recordtype longin
|
||||
|
||||
=cut
|
||||
|
||||
recordtype(longin) {
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The long input record has the standard fields for specifying under what
|
||||
circumstances the record will be processed. These fields are listed in L<Scan
|
||||
Fields>. In addition, L<Scanning Specification> explains how these fields are
|
||||
used. Note that I/O event scanning is only supported for those card types
|
||||
that interrupt.
|
||||
|
||||
=head3 Read Parameters
|
||||
|
||||
The device support routines use the INP field to obtain the record's input. For
|
||||
records that obtain their input from devices, the INP field 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.
|
||||
|
||||
For soft records, the INP can be a constant, a database link, or a channel
|
||||
access link. The value is read directly into VAL. The C<<< Soft Channel >>>
|
||||
device support module is available for longin records. See L<Address
|
||||
Specification> for information on the format of hardware addresses and a
|
||||
database links.
|
||||
|
||||
=fields VAL, INP, DTYP
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
These parameters are used to present meaningful data to the operator. These
|
||||
fields are used to display the value and other parameters of the long input
|
||||
either textually or graphically.
|
||||
|
||||
EGU is a string of up to 16 characters describing the units that the long input
|
||||
measures. It is retrieved by the C<<< get_units >>> record support routine.
|
||||
|
||||
The HOPR and LOPR fields set the upper and lower display limits for the VAL,
|
||||
HIHI, HIGH, LOW, and LOLO fields. Both the C<<< get_graphic_double >>> and C<<<
|
||||
get_control_double >>> record support routines retrieve these fields.
|
||||
|
||||
See L<Fields Common to All Record Types> for more on the record name (NAME) and
|
||||
description (DESC) fields.
|
||||
|
||||
=fields EGU, HOPR, LOPR, NAME, DESC
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The possible alarm conditions for long inputs are the SCAN, READ, and limit
|
||||
alarms. The SCAN and READ alarms are called by the record or device support
|
||||
routines.
|
||||
|
||||
The limit alarms are configured by the user in the HIHI, LOLO, HIGH, and LOW
|
||||
fields using numerical values. For each of these fields, there is a
|
||||
corresponding severity field which can be either NO_ALARM, MINOR, or MAJOR. The
|
||||
HYST field can be used to specify a deadband around each limit. See L<Alarm
|
||||
Specification> for a complete explanation of alarms and these fields. L<Alarm
|
||||
Fields> lists other fields related to a alarms that are common to all record
|
||||
types.
|
||||
|
||||
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
|
||||
|
||||
=head3 Monitor Parameters
|
||||
|
||||
These parameters are used to determine when to send monitors placed on the 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
|
||||
ADEL field is used by archive monitors and the MDEL field for all other types of
|
||||
monitors. See L<Monitor Specification> for a complete explanation of monitors.
|
||||
|
||||
=fields ADEL, MDEL
|
||||
|
||||
=head3 Run-time and Simulation Mode Parameters
|
||||
|
||||
The LALM, MLST, and ALST fields are used to implement the hysteresis factors for
|
||||
monitor callbacks. Only if the difference between these fields and the
|
||||
corresponding value field is greater than the appropriate delta (MDEL, ADEL,
|
||||
HYST)--only then are monitors triggered. For instance, only if the difference
|
||||
between VAL and MLST is greater than MDEL are the monitors triggered for VAL.
|
||||
|
||||
=fields LALM, ALST, MLST
|
||||
|
||||
The following fields are used to operate the long input in the simulation mode.
|
||||
See L<Fields Common to Many Record Types> for more information on these fields.
|
||||
|
||||
=fields SIOL, SVAL, SIML, SIMM, SIMS
|
||||
|
||||
=head2 Record Support
|
||||
|
||||
=head3 Record Support Routines
|
||||
|
||||
=head4 init_record
|
||||
|
||||
This routine initializes SIMM with the value of SIML if SIML type is CONSTANT
|
||||
link or creates a channel access link if SIML type is PV_LINK. SVAL is likewise
|
||||
initialized if SIOL is CONSTANT or PV_LINK.
|
||||
|
||||
This routine next checks to see that device support is available and a device
|
||||
support read routine is defined. If either does not exist, an error message is
|
||||
issued and processing is terminated.
|
||||
|
||||
If device support includes C<init_record()>, it is called.
|
||||
|
||||
=head4 process
|
||||
|
||||
See next section.
|
||||
|
||||
=head4 get_units
|
||||
|
||||
Retrieves EGU.
|
||||
|
||||
=head4 get_graphic_double
|
||||
|
||||
Sets the upper display and lower display limits for a field. If the field is
|
||||
VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else if the
|
||||
field has upper and lower limits defined they will be used, else the upper and
|
||||
lower maximum values for the field type will be used.
|
||||
|
||||
=head4 get_control_double
|
||||
|
||||
Sets the upper control and the lower control limits for a field. If the field is
|
||||
VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else if the
|
||||
field has upper and lower limits defined they will be used, else the upper and
|
||||
lower maximum values for the field type will be used.
|
||||
|
||||
=head4 get_alarm_double
|
||||
|
||||
Sets the following values:
|
||||
|
||||
upper_alarm_limit = HIHI
|
||||
upper_warning_limit = HIGH
|
||||
lower_warning_limit = LOW
|
||||
lower_alarm_limit = LOLO
|
||||
|
||||
=head3 Record Processing
|
||||
|
||||
Routine process implements the following algorithm:
|
||||
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
Check to see that the appropriate device support module exists. If it doesn't,
|
||||
an error message is issued and processing is terminated with the PACT field
|
||||
still set to TRUE. This ensures that processes will no longer be called for this
|
||||
record. Thus error storms will not occur.
|
||||
|
||||
=item 2.
|
||||
|
||||
readValue is called. See L<Input Records> for more information.
|
||||
|
||||
=item 3.
|
||||
|
||||
If PACT has been changed to TRUE, the device support read routine has started
|
||||
but has not completed reading a new input value. In this case, the processing
|
||||
routine merely returns, leaving PACT TRUE.
|
||||
|
||||
=item 4.
|
||||
|
||||
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 more than HYST
|
||||
before the alarm status and severity is lowered.
|
||||
|
||||
=item 5.
|
||||
|
||||
Check to see if monitors should be invoked:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
Alarm monitors are invoked if the alarm status or severity has changed.
|
||||
|
||||
=item *
|
||||
|
||||
Archive and value change monitors are invoked if ADEL and MDEL conditions are
|
||||
met.
|
||||
|
||||
=item *
|
||||
|
||||
NSEV and NSTA are reset to 0.
|
||||
|
||||
=back
|
||||
|
||||
=item 6.
|
||||
|
||||
Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=back
|
||||
|
||||
=begin html
|
||||
|
||||
<br><hr><br>
|
||||
|
||||
=end html
|
||||
|
||||
=head2 Device Support
|
||||
|
||||
=head3 Fields Of Interest To Device Support
|
||||
|
||||
Each long input record must have an associated set of device support routines.
|
||||
The primary responsibility of the device support routines is to obtain a new
|
||||
input value whenever read_longin is called. The device support routines are
|
||||
primarily interested in the following fields:
|
||||
|
||||
=fields PACT, DPVT, UDF, NSEV, NSTA, VAL, INP
|
||||
|
||||
=head3 Device Support Routines
|
||||
|
||||
Device support consists of the following routines:
|
||||
|
||||
=head4 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.
|
||||
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.
|
||||
|
||||
=head4 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
|
||||
the integer parameter C<after> set to 0.
|
||||
The second call happens after all of the C<init_record()> calls have been made,
|
||||
with C<after> set to 1.
|
||||
|
||||
=head4 init_record
|
||||
|
||||
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)
|
||||
|
||||
This routine is called by the ioEventScan system each time the record is added
|
||||
or deleted from an I/O event scan list. 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.
|
||||
|
||||
=head4 read_longin
|
||||
|
||||
read_longin(precord)
|
||||
|
||||
This routine must provide a new input value. It returns the following values:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
0: Success. A new value is placed in VAL.
|
||||
|
||||
=item *
|
||||
|
||||
Other: Error.
|
||||
|
||||
=back
|
||||
|
||||
=head3 Device Support For Soft Records
|
||||
|
||||
The C<<< Soft Channel >>> device support module places a value directly in VAL.
|
||||
|
||||
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()>.
|
||||
|
||||
C<<< read_longin >>> calls recGblGetLinkValue to read the current value of VAL.
|
||||
See L<Soft Input> for more information
|
||||
|
||||
If the return status of C<<< recGblGetLinkValue >>> is zero then read_longin
|
||||
sets UDF to FALSE. read_longin returns the status of C<recGblGetLinkValue>.
|
||||
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_LONG) {
|
||||
prompt("Current value")
|
||||
promptgroup("40 - Input")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(EGU,DBF_STRING) {
|
||||
prompt("Engineering Units")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
}
|
||||
field(HOPR,DBF_LONG) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOPR,DBF_LONG) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIHI,DBF_LONG) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOLO,DBF_LONG) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIGH,DBF_LONG) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOW,DBF_LONG) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
prompt("Lolo Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
prompt("High Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
prompt("Low Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_LONG) {
|
||||
prompt("Alarm Deadband")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
}
|
||||
field(AFTC, DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Time Constant")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
}
|
||||
field(AFVL, DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Value")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ADEL,DBF_LONG) {
|
||||
prompt("Archive Deadband")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
}
|
||||
field(MDEL,DBF_LONG) {
|
||||
prompt("Monitor Deadband")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
}
|
||||
field(LALM,DBF_LONG) {
|
||||
prompt("Last Value Alarmed")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ALST,DBF_LONG) {
|
||||
prompt("Last Value Archived")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(MLST,DBF_LONG) {
|
||||
prompt("Last Val Monitored")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(SIOL,DBF_INLINK) {
|
||||
prompt("Sim Input Specifctn")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SVAL,DBF_LONG) {
|
||||
prompt("Simulation Value")
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Sim Mode Location")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
special(SPC_MOD)
|
||||
interest(1)
|
||||
menu(menuYesNo)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Sim mode Alarm Svrty")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(OLDSIMM,DBF_MENU) {
|
||||
prompt("Prev. Simulation Mode")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SSCN,DBF_MENU) {
|
||||
prompt("Sim. Mode Scan")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
initial("65535")
|
||||
}
|
||||
field(SDLY,DBF_DOUBLE) {
|
||||
prompt("Sim. Mode Async Delay")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
initial("-1.0")
|
||||
}
|
||||
%#include "callback.h"
|
||||
field(SIMPVT,DBF_NOACCESS) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
}
|
||||
@@ -401,9 +401,9 @@ static long writeValue(longoutRecord *prec)
|
||||
status = dbPutLink(&prec->siol, DBR_LONG, &prec->val, 1);
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(longout) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_LONG) {
|
||||
prompt("Desired Output")
|
||||
promptgroup("50 - Output")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(OUT,DBF_OUTLINK) {
|
||||
prompt("Output Specification")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(DOL,DBF_INLINK) {
|
||||
prompt("Desired Output Loc")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(OMSL,DBF_MENU) {
|
||||
prompt("Output Mode Select")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
menu(menuOmsl)
|
||||
}
|
||||
field(EGU,DBF_STRING) {
|
||||
prompt("Engineering Units")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
}
|
||||
field(DRVH,DBF_LONG) {
|
||||
prompt("Drive High Limit")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(DRVL,DBF_LONG) {
|
||||
prompt("Drive Low Limit")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HOPR,DBF_LONG) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOPR,DBF_LONG) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIHI,DBF_LONG) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOLO,DBF_LONG) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIGH,DBF_LONG) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOW,DBF_LONG) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
prompt("Lolo Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
prompt("High Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
prompt("Low Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_LONG) {
|
||||
prompt("Alarm Deadband")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
}
|
||||
field(ADEL,DBF_LONG) {
|
||||
prompt("Archive Deadband")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
}
|
||||
field(MDEL,DBF_LONG) {
|
||||
prompt("Monitor Deadband")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
}
|
||||
field(LALM,DBF_LONG) {
|
||||
prompt("Last Value Alarmed")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ALST,DBF_LONG) {
|
||||
prompt("Last Value Archived")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(MLST,DBF_LONG) {
|
||||
prompt("Last Val Monitored")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(SIOL,DBF_OUTLINK) {
|
||||
prompt("Simulation Output Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Simulation Mode Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
special(SPC_MOD)
|
||||
interest(1)
|
||||
menu(menuYesNo)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Simulation Mode Severity")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(OLDSIMM,DBF_MENU) {
|
||||
prompt("Prev. Simulation Mode")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SSCN,DBF_MENU) {
|
||||
prompt("Sim. Mode Scan")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
initial("65535")
|
||||
}
|
||||
field(SDLY,DBF_DOUBLE) {
|
||||
prompt("Sim. Mode Async Delay")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
initial("-1.0")
|
||||
}
|
||||
%#include "callback.h"
|
||||
field(SIMPVT,DBF_NOACCESS) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
}
|
||||
field(IVOA,DBF_MENU) {
|
||||
prompt("INVALID output action")
|
||||
promptgroup("50 - Output")
|
||||
interest(2)
|
||||
menu(menuIvoa)
|
||||
}
|
||||
field(IVOV,DBF_LONG) {
|
||||
prompt("INVALID output value")
|
||||
promptgroup("50 - Output")
|
||||
interest(2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,589 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=title Long Output Record (longout)
|
||||
|
||||
The normal use for the long output or "longout" record type is to store long
|
||||
integer values of up to 32 bits and write them to hardware devices. The C<<<
|
||||
Soft Channel >>> device support layer can also be used to write values to
|
||||
other records via database or channel access links. The OUT field determines how
|
||||
the record is used. The record supports alarm limits and graphics and control
|
||||
limits.
|
||||
|
||||
=recordtype longout
|
||||
|
||||
=cut
|
||||
|
||||
recordtype(longout) {
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The fields in this record fall into the following categories:
|
||||
|
||||
=over
|
||||
|
||||
=item * L<Scan Parameters>
|
||||
|
||||
=item * L<Desired Output Parameters>
|
||||
|
||||
=item * L<Write Parameters>
|
||||
|
||||
=item * L<Operator Display Parameters>
|
||||
|
||||
=item * L<Alarm Parameters>
|
||||
|
||||
=item * L<Monitor Parameters>
|
||||
|
||||
=item * L<Simulation Mode Parameters>
|
||||
|
||||
=back
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The longout record has the standard fields for specifying under what
|
||||
circumstances it will be processed. These fields are listed in L<Scan Fields>.
|
||||
In addition, L<Scanning Specification> explains how these fields are used. Note
|
||||
that I/O event scanning is only supported for those card types that
|
||||
interrupt.
|
||||
|
||||
=head3 Desired Output Parameters
|
||||
|
||||
The record must specify where the desired output originates, i.e., the 32 bit
|
||||
integer value it is to write. The output mode select (OMSL) field determines
|
||||
whether the output originates from another record or from database access. When
|
||||
set to C<<< closed_loop >>>, the desired output is retrieved from the link
|
||||
specified in the desired output (DOL) field (which can specify either a database
|
||||
or channel access link) and placed into the VAL field. When set to C<<<
|
||||
supervisory >>>, the desired output can be written into the VAL field via dpPuts
|
||||
at run-time.
|
||||
|
||||
A third type of value for the DOL field is a constant in which case, when the
|
||||
record is initialized, the VAL field will be initialized with this constant
|
||||
value.
|
||||
|
||||
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.
|
||||
|
||||
=fields DOL, OMSL, DRVH, DRVL, VAL
|
||||
|
||||
=head3 Write Parameters
|
||||
|
||||
The OUT link field determines where the record is to send its output. For
|
||||
records that write values to hardware devices, the OUT output link field must
|
||||
specify the address of the I/O card, and the DTYP field must specify the
|
||||
name of the corresponding device support module.
|
||||
|
||||
For soft records, the OUT output link can be a constant, a database link, or a
|
||||
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> for information on the format of hardware addresses
|
||||
and database links.
|
||||
|
||||
=fields OUT, DTYP
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_LONG) {
|
||||
prompt("Desired Output")
|
||||
promptgroup("50 - Output")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(OUT,DBF_OUTLINK) {
|
||||
prompt("Output Specification")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(DOL,DBF_INLINK) {
|
||||
prompt("Desired Output Loc")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(OMSL,DBF_MENU) {
|
||||
prompt("Output Mode Select")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
menu(menuOmsl)
|
||||
}
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
These parameters are used to present meaningful data to the operator. They
|
||||
display the value and other parameters of the long output either textually or
|
||||
graphically.
|
||||
|
||||
EGU is a string of up to 16 characters describing the units that the long output
|
||||
measures. It is retrieved by the C<<< get_units >>> record support routine.
|
||||
|
||||
The HOPR and LOPR fields set the upper and lower display limits for the VAL,
|
||||
HIHI, HIGH, LOW, and LOLO fields. Both the C<<< get_graphic_double >>> and C<<<
|
||||
get_control_double >>> record support routines retrieve these fields.
|
||||
|
||||
See L<Fields Common to All Record Types> for more on the record name (NAME) and
|
||||
description (DESC) fields.
|
||||
|
||||
=fields EGU, HOPR, LOPR, NAME, DESC
|
||||
|
||||
=cut
|
||||
|
||||
field(EGU,DBF_STRING) {
|
||||
prompt("Engineering Units")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
}
|
||||
field(DRVH,DBF_LONG) {
|
||||
prompt("Drive High Limit")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(DRVL,DBF_LONG) {
|
||||
prompt("Drive Low Limit")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HOPR,DBF_LONG) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOPR,DBF_LONG) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The possible alarm conditions for long inputs are the SCAN, READ, INVALID, and
|
||||
limit alarms. The SCAN and READ alarms are not configurable by the user because
|
||||
their severity is always MAJOR. The INVALID alarm is called by the record
|
||||
support routine when the record or device support routines cannot write the
|
||||
record's output. The IVOA field specifies the action to take in this case.
|
||||
|
||||
The limit alarms are configured by the user in the HIHI, LOLO, HIGH, and LOW
|
||||
fields using floating-point values. For each of these fields, there is a
|
||||
corresponding severity field which can be either NO_ALARM, MINOR, or MAJOR. The
|
||||
HYST field contains the alarm deadband around each limit alarm.
|
||||
|
||||
See the See L<Alarm Specification> for a complete explanation of alarms and
|
||||
these fields. For an explanation of the IVOA and IVOV fields, see L<Output
|
||||
Records>. L<Alarm Fields> lists other fields related to a alarms that are common
|
||||
to all record types.
|
||||
|
||||
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST, IVOA, IVOV
|
||||
|
||||
=cut
|
||||
|
||||
field(HIHI,DBF_LONG) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOLO,DBF_LONG) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIGH,DBF_LONG) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOW,DBF_LONG) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
prompt("Lolo Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
prompt("High Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
prompt("Low Severity")
|
||||
promptgroup("70 - Alarm")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_LONG) {
|
||||
prompt("Alarm Deadband")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
}
|
||||
|
||||
=head3 Monitor Parameters
|
||||
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
=fields ADEL, MDEL
|
||||
|
||||
=cut
|
||||
|
||||
field(ADEL,DBF_LONG) {
|
||||
prompt("Archive Deadband")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
}
|
||||
field(MDEL,DBF_LONG) {
|
||||
prompt("Monitor Deadband")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
}
|
||||
field(LALM,DBF_LONG) {
|
||||
prompt("Last Value Alarmed")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ALST,DBF_LONG) {
|
||||
prompt("Last Value Archived")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(MLST,DBF_LONG) {
|
||||
prompt("Last Val Monitored")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
|
||||
=head3 Run-time and Simulation Mode Parameters
|
||||
|
||||
The LALM, MLST, and ALST fields are used to implement the hysteresis factors for
|
||||
monitor callbacks. Only if the difference between these fields and the
|
||||
corresponding value field is greater than the appropriate delta (MDEL, ADEL,
|
||||
HYST)--only then are monitors triggered. For instance, only if the difference
|
||||
between VAL and MLST is greater than MDEL are the monitors triggered for VAL.
|
||||
|
||||
=fields LALM, ALST, MLST
|
||||
|
||||
The following fields are used to operate the long output in the simulation mode.
|
||||
See L<Fields Common to Many Record Types> for more information on the simulation
|
||||
mode fields
|
||||
|
||||
=fields SIOL, SIML, SIMM, SIMS
|
||||
|
||||
=cut
|
||||
|
||||
field(SIOL,DBF_OUTLINK) {
|
||||
prompt("Sim Output Specifctn")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Sim Mode Location")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
special(SPC_MOD)
|
||||
interest(1)
|
||||
menu(menuYesNo)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Sim mode Alarm Svrty")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(OLDSIMM,DBF_MENU) {
|
||||
prompt("Prev. Simulation Mode")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SSCN,DBF_MENU) {
|
||||
prompt("Sim. Mode Scan")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
initial("65535")
|
||||
}
|
||||
field(SDLY,DBF_DOUBLE) {
|
||||
prompt("Sim. Mode Async Delay")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
initial("-1.0")
|
||||
}
|
||||
%#include "callback.h"
|
||||
field(SIMPVT,DBF_NOACCESS) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
field(IVOA,DBF_MENU) {
|
||||
prompt("INVALID output action")
|
||||
promptgroup("50 - Output")
|
||||
interest(2)
|
||||
menu(menuIvoa)
|
||||
}
|
||||
field(IVOV,DBF_LONG) {
|
||||
prompt("INVALID output value")
|
||||
promptgroup("50 - Output")
|
||||
interest(2)
|
||||
}
|
||||
|
||||
|
||||
=begin html
|
||||
|
||||
<br><hr><br>
|
||||
|
||||
=end html
|
||||
|
||||
=head2 Record Support
|
||||
|
||||
=head3 Record Support Routines
|
||||
|
||||
=head4 init_record
|
||||
|
||||
This routine initializes SIMM if SIML is a constant or creates a channel access
|
||||
link if SIML is PV_LINK. If SIOL is PV_LINK a channel access link is created.
|
||||
|
||||
This routine next checks to see that device support is available. The routine
|
||||
next checks to see if the device support write routine is defined.
|
||||
|
||||
If either device support or the device support write routine does not exist, an
|
||||
error message is issued and processing is terminated.
|
||||
|
||||
If DOL is a constant, then VAL is initialized to its value and UDF is set to
|
||||
FALSE. If DOL type is a PV_LINK then dbCaAddInlink is called to create a channel
|
||||
access link.
|
||||
|
||||
If device support includes C<init_record()>, it is called.
|
||||
|
||||
=head4 process
|
||||
|
||||
See next section.
|
||||
|
||||
=head4 get_units
|
||||
|
||||
Retrieves EGU.
|
||||
|
||||
=head4 get_graphic_double
|
||||
|
||||
Sets the upper display and lower display limits for a field. If the field is
|
||||
VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else if the
|
||||
field has upper and lower limits defined they will be used, else the upper and
|
||||
lower maximum values for the field type will be used.
|
||||
|
||||
=head4 get_control_double
|
||||
|
||||
Sets the upper control and the lower control limits for a field. If the field is
|
||||
VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else if the
|
||||
field has upper and lower limits defined they will be used, else the upper and
|
||||
lower maximum values for the field type will be used.
|
||||
|
||||
=head4 get_alarm_double
|
||||
|
||||
Sets the following values:
|
||||
|
||||
upper_alarm_limit = HIHI
|
||||
upper_warning_limit = HIGH
|
||||
lower_warning_limit = LOW
|
||||
lower_alarm_limit = LOLO
|
||||
|
||||
|
||||
=head3 Record Processing
|
||||
|
||||
Routine process implements the following algorithm:
|
||||
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
Check to see that the appropriate device support module exists. If it doesn't,
|
||||
an error message is issued and processing is terminated with the PACT field
|
||||
still set to TRUE. This ensures that processes will no longer be called for this
|
||||
record. Thus error storms will not occur.
|
||||
|
||||
=item 2.
|
||||
|
||||
If PACT is FALSE and OMSL is CLOSED_LOOP recGblGetLinkValue is called to read
|
||||
the current value of VAL. See L<Output Records> for more information. If the
|
||||
return status of recGblGetLinkValue is zero then 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 more than HYST
|
||||
before the alarm status and severity is lowered.
|
||||
|
||||
=item 4.
|
||||
|
||||
Check severity and write the new value. See L<Invalid Alarm Output Action> for
|
||||
information on how INVALID alarms affect output records.
|
||||
|
||||
=item 5.
|
||||
|
||||
If PACT has been changed to TRUE, the device support write output routine has
|
||||
started but has not completed writing the new value. In this case, the
|
||||
processing routine merely returns, leaving PACT TRUE.
|
||||
|
||||
=item 6.
|
||||
|
||||
Check to see if monitors should be invoked:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
Alarm monitors are invoked if the alarm status or severity has changed.
|
||||
|
||||
=item *
|
||||
|
||||
Archive and value change monitors are invoked if ADEL and MDEL conditions are
|
||||
met.
|
||||
|
||||
=item *
|
||||
|
||||
NSEV and NSTA are reset to 0.
|
||||
|
||||
=back
|
||||
|
||||
=item 7.
|
||||
|
||||
Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=back
|
||||
|
||||
=begin html
|
||||
|
||||
<br><hr><br>
|
||||
|
||||
=end html
|
||||
|
||||
=head2 Device Support
|
||||
|
||||
=head3 Fields Of Interest To Device Support
|
||||
|
||||
Each long output record must have an associated set of device support routines.
|
||||
The primary responsibility of the device support routines is to output a new
|
||||
value whenever write_longout is called. The device support routines are
|
||||
primarily interested in the following fields:
|
||||
|
||||
=fields PACT, DPVT, NSEV, NSTA, OUT
|
||||
|
||||
=head3 Device Support Routines
|
||||
|
||||
Device support consists of the following routines:
|
||||
|
||||
=head4 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.
|
||||
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.
|
||||
|
||||
=head4 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
|
||||
the integer parameter C<after> set to 0.
|
||||
The second call happens after all of the C<init_record()> calls have been made,
|
||||
with C<after> set to 1.
|
||||
|
||||
=head4 init_record
|
||||
|
||||
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)
|
||||
|
||||
This routine is called by the ioEventScan system each time the record is added
|
||||
or deleted from an I/O event scan list. 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.
|
||||
|
||||
=head4 write_longout
|
||||
|
||||
write_longout(precord)
|
||||
|
||||
This routine must output a new value. It returns the following values:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
0: Success.
|
||||
|
||||
=item *
|
||||
|
||||
Other: Error.
|
||||
|
||||
=back
|
||||
|
||||
=head3 Device Support For Soft Records
|
||||
|
||||
The C<<< Soft Channel >>> module writes the current value of VAL.
|
||||
|
||||
If the OUT link type is PV_LINK, then dbCaAddInlink is called by
|
||||
C<init_record()>.
|
||||
|
||||
write_longout calls recGblPutLinkValue to write the current value of VAL.
|
||||
|
||||
See L<Soft Output> for a further explanation.
|
||||
|
||||
=cut
|
||||
|
||||
} #end of the DBD file
|
||||
@@ -241,9 +241,9 @@ static long readValue(lsiRecord *prec)
|
||||
if (status == 0) prec->udf = FALSE;
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -110,6 +110,6 @@ recordtype(lsi) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,9 +282,9 @@ static long writeValue(lsoRecord *prec)
|
||||
status = dbPutLinkLS(&prec->siol, prec->val, prec->len);
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -134,6 +134,6 @@ recordtype(lso) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,9 +277,9 @@ static long readValue(mbbiDirectRecord *prec)
|
||||
}
|
||||
prec->pact = FALSE;
|
||||
} else { /* !prec->pact && delay >= 0. */
|
||||
CALLBACK *pvt = prec->simpvt;
|
||||
epicsCallback *pvt = prec->simpvt;
|
||||
if (!pvt) {
|
||||
pvt = calloc(1, sizeof(CALLBACK)); /* very lazy allocation of callback structure */
|
||||
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
|
||||
prec->simpvt = pvt;
|
||||
}
|
||||
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(mbbiDirect) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_LONG) {
|
||||
prompt("Current Value")
|
||||
promptgroup("40 - Input")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(NOBT,DBF_SHORT) {
|
||||
prompt("Number of Bits")
|
||||
promptgroup("40 - Input")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(RVAL,DBF_ULONG) {
|
||||
prompt("Raw Value")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(ORAW,DBF_ULONG) {
|
||||
prompt("Prev Raw Value")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(MASK,DBF_ULONG) {
|
||||
prompt("Hardware Mask")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(MLST,DBF_LONG) {
|
||||
prompt("Last Value Monitored")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(SHFT,DBF_USHORT) {
|
||||
prompt("Shift")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(SIOL,DBF_INLINK) {
|
||||
prompt("Simulation Input Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SVAL,DBF_LONG) {
|
||||
prompt("Simulation Value")
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Simulation Mode Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
special(SPC_MOD)
|
||||
interest(1)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Simulation Mode Severity")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(OLDSIMM,DBF_MENU) {
|
||||
prompt("Prev. Simulation Mode")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SSCN,DBF_MENU) {
|
||||
prompt("Sim. Mode Scan")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
initial("65535")
|
||||
}
|
||||
field(SDLY,DBF_DOUBLE) {
|
||||
prompt("Sim. Mode Async Delay")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
initial("-1.0")
|
||||
}
|
||||
%#include "callback.h"
|
||||
field(SIMPVT,DBF_NOACCESS) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("CALLBACK *simpvt")
|
||||
}
|
||||
field(B0,DBF_UCHAR) {
|
||||
prompt("Bit 0")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1,DBF_UCHAR) {
|
||||
prompt("Bit 1")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B2,DBF_UCHAR) {
|
||||
prompt("Bit 2")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B3,DBF_UCHAR) {
|
||||
prompt("Bit 3")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B4,DBF_UCHAR) {
|
||||
prompt("Bit 4")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B5,DBF_UCHAR) {
|
||||
prompt("Bit 5")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B6,DBF_UCHAR) {
|
||||
prompt("Bit 6")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B7,DBF_UCHAR) {
|
||||
prompt("Bit 7")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B8,DBF_UCHAR) {
|
||||
prompt("Bit 8")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B9,DBF_UCHAR) {
|
||||
prompt("Bit 9")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BA,DBF_UCHAR) {
|
||||
prompt("Bit 10")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BB,DBF_UCHAR) {
|
||||
prompt("Bit 11")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BC,DBF_UCHAR) {
|
||||
prompt("Bit 12")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BD,DBF_UCHAR) {
|
||||
prompt("Bit 13")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BE,DBF_UCHAR) {
|
||||
prompt("Bit 14")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BF,DBF_UCHAR) {
|
||||
prompt("Bit 15")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B10,DBF_UCHAR) {
|
||||
prompt("Bit 16")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B11,DBF_UCHAR) {
|
||||
prompt("Bit 17")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B12,DBF_UCHAR) {
|
||||
prompt("Bit 18")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B13,DBF_UCHAR) {
|
||||
prompt("Bit 19")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B14,DBF_UCHAR) {
|
||||
prompt("Bit 20")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B15,DBF_UCHAR) {
|
||||
prompt("Bit 21")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B16,DBF_UCHAR) {
|
||||
prompt("Bit 22")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B17,DBF_UCHAR) {
|
||||
prompt("Bit 23")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B18,DBF_UCHAR) {
|
||||
prompt("Bit 24")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B19,DBF_UCHAR) {
|
||||
prompt("Bit 25")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1A,DBF_UCHAR) {
|
||||
prompt("Bit 26")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1B,DBF_UCHAR) {
|
||||
prompt("Bit 27")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1C,DBF_UCHAR) {
|
||||
prompt("Bit 28")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1D,DBF_UCHAR) {
|
||||
prompt("Bit 29")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1E,DBF_UCHAR) {
|
||||
prompt("Bit 30")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1F,DBF_UCHAR) {
|
||||
prompt("Bit 31")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,588 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=title Multi-Bit Binary Input Direct Record (mbbiDirect)
|
||||
|
||||
The mbbiDirect record retrieves a 32-bit hardware value and converts it to
|
||||
an array of 32 unsigned characters, each representing a bit of the word.
|
||||
These fields (B0-B9, BA-BF, B10-B19, B1A-B1F) are set to 1 if the corresponding
|
||||
bit is set, and 0 if not.
|
||||
|
||||
This record's operation is similar to that of the multi-bit binary input record,
|
||||
and it has many fields in common with it. This record also has two available
|
||||
soft device support modules: C<Soft Channel> and C<Raw Soft Channel>.
|
||||
|
||||
=recordtype mbbiDirect
|
||||
|
||||
=cut
|
||||
|
||||
recordtype(mbbiDirect) {
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The mbbiDirect record has the standard fields for specifying under what
|
||||
circumstances the record will be processed. These fields are listed in L<Scan
|
||||
Fields>. In addition, L<Scanning Specification> explains how these fields are
|
||||
used. Note that I/O event scanning is only supported for those card types
|
||||
that interrupt.
|
||||
|
||||
=head3 Read and Convert Parameters
|
||||
|
||||
The device support routines obtain the record's input from the device or link
|
||||
specified in the INP field. For records that obtain their input from devices,
|
||||
the INP field 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> for
|
||||
information on the format of hardware addresses.
|
||||
|
||||
Two soft device support modules can be specified in DTYP C<Soft Channel> and
|
||||
C<<< Raw Soft Channel >>>.
|
||||
|
||||
C<<< Raw Soft Channel >>> reads the value into RVAL,
|
||||
upon which the normal conversion process is undergone. C<<< Soft Channel >>>
|
||||
reads any unsigned integer directly into VAL. For a soft mbbiDirect record, the
|
||||
INP field can be a constant, a database, or a channel access link. If INP is a
|
||||
constant, then the VAL is initialized to the INP value but can be changed at
|
||||
run-time via dbPutField or dbPutLink. See L<Address Specification> for
|
||||
information on how to database links.
|
||||
|
||||
For records that don't use C<<< Soft Channel >>> device support, RVAL is used to
|
||||
determine VAL as follows:
|
||||
|
||||
=over
|
||||
|
||||
=item 1. RVAL is assigned to a temporary variable I<rval> = RVAL
|
||||
|
||||
=item 2. I<rval> is shifted right SHFT number of bits.
|
||||
|
||||
=item 3. VAL is set equal to I<rval>.
|
||||
|
||||
=back
|
||||
|
||||
Each of the fields, B0-BF and B10-B1F, represents one bit of the word.
|
||||
|
||||
=fields VAL, INP, RVAL, SHFT, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, BA, BB, BC, BD, BE, BF, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19, B1A, B1B, B1C, B1D, B1E, B1F
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
These parameters are used to present meaningful data to the operator.
|
||||
|
||||
See L<Fields Common to All Record Types> for more on the record name (NAME) and
|
||||
description (DESC) fields.
|
||||
|
||||
=fields NAME, DESC
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_LONG) {
|
||||
prompt("Current Value")
|
||||
promptgroup("40 - Input")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(NOBT,DBF_SHORT) {
|
||||
prompt("Number of Bits")
|
||||
promptgroup("40 - Input")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(RVAL,DBF_ULONG) {
|
||||
prompt("Raw Value")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(ORAW,DBF_ULONG) {
|
||||
prompt("Prev Raw Value")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(MASK,DBF_ULONG) {
|
||||
prompt("Hardware Mask")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(MLST,DBF_LONG) {
|
||||
prompt("Last Value Monitored")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(SHFT,DBF_USHORT) {
|
||||
prompt("Shift")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
|
||||
=head3 Run-time and Simulation Mode Parameters
|
||||
|
||||
These parameters are used by the run-time code for processing the mbbi direct
|
||||
record. They are not configurable prior to run-time.
|
||||
|
||||
MASK is used by device support routine to read hardware register. Record support
|
||||
sets low order NOBT bits in MASK. Device support can shift this value.
|
||||
|
||||
MLST holds the value when the last monitor for value change was triggered.
|
||||
|
||||
=fields NOBT, ORAW, MASK, MLST
|
||||
|
||||
The following fields are used to operate the mbbiDirect record in the simulation
|
||||
mode. See L<Fields Common to Many Record Types> for more information on these
|
||||
fields.
|
||||
|
||||
=fields SIOL, SVAL, SIML, SIMM, SIMS, SSCN, SDLY
|
||||
|
||||
=cut
|
||||
|
||||
field(SIOL,DBF_INLINK) {
|
||||
prompt("Simulation Input Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SVAL,DBF_LONG) {
|
||||
prompt("Simulation Value")
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Simulation Mode Link")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
special(SPC_MOD)
|
||||
interest(1)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Simulation Mode Severity")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(OLDSIMM,DBF_MENU) {
|
||||
prompt("Prev. Simulation Mode")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
menu(menuSimm)
|
||||
}
|
||||
field(SSCN,DBF_MENU) {
|
||||
prompt("Sim. Mode Scan")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
initial("65535")
|
||||
}
|
||||
field(SDLY,DBF_DOUBLE) {
|
||||
prompt("Sim. Mode Async Delay")
|
||||
promptgroup("90 - Simulate")
|
||||
interest(2)
|
||||
initial("-1.0")
|
||||
}
|
||||
%#include "callback.h"
|
||||
field(SIMPVT,DBF_NOACCESS) {
|
||||
prompt("Sim. Mode Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("epicsCallback *simpvt")
|
||||
}
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The possible alarm conditions for multi-bit binary input direct records are the
|
||||
SCAN and READ alarms. These alarms are not configurable by the user since they
|
||||
are always of MAJOR severity. See L<Alarm Specification> for a complete
|
||||
explanation of Scan and Read alarms. No fields exist for the mbbi direct record
|
||||
to have state alarms.
|
||||
|
||||
L<Alarm Fields> lists other fields related to a alarms that are common to all
|
||||
record types.
|
||||
|
||||
=cut
|
||||
|
||||
field(B0,DBF_UCHAR) {
|
||||
prompt("Bit 0")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1,DBF_UCHAR) {
|
||||
prompt("Bit 1")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B2,DBF_UCHAR) {
|
||||
prompt("Bit 2")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B3,DBF_UCHAR) {
|
||||
prompt("Bit 3")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B4,DBF_UCHAR) {
|
||||
prompt("Bit 4")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B5,DBF_UCHAR) {
|
||||
prompt("Bit 5")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B6,DBF_UCHAR) {
|
||||
prompt("Bit 6")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B7,DBF_UCHAR) {
|
||||
prompt("Bit 7")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B8,DBF_UCHAR) {
|
||||
prompt("Bit 8")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B9,DBF_UCHAR) {
|
||||
prompt("Bit 9")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BA,DBF_UCHAR) {
|
||||
prompt("Bit 10")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BB,DBF_UCHAR) {
|
||||
prompt("Bit 11")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BC,DBF_UCHAR) {
|
||||
prompt("Bit 12")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BD,DBF_UCHAR) {
|
||||
prompt("Bit 13")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BE,DBF_UCHAR) {
|
||||
prompt("Bit 14")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(BF,DBF_UCHAR) {
|
||||
prompt("Bit 15")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B10,DBF_UCHAR) {
|
||||
prompt("Bit 16")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B11,DBF_UCHAR) {
|
||||
prompt("Bit 17")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B12,DBF_UCHAR) {
|
||||
prompt("Bit 18")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B13,DBF_UCHAR) {
|
||||
prompt("Bit 19")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B14,DBF_UCHAR) {
|
||||
prompt("Bit 20")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B15,DBF_UCHAR) {
|
||||
prompt("Bit 21")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B16,DBF_UCHAR) {
|
||||
prompt("Bit 22")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B17,DBF_UCHAR) {
|
||||
prompt("Bit 23")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B18,DBF_UCHAR) {
|
||||
prompt("Bit 24")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B19,DBF_UCHAR) {
|
||||
prompt("Bit 25")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1A,DBF_UCHAR) {
|
||||
prompt("Bit 26")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1B,DBF_UCHAR) {
|
||||
prompt("Bit 27")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1C,DBF_UCHAR) {
|
||||
prompt("Bit 28")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1D,DBF_UCHAR) {
|
||||
prompt("Bit 29")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1E,DBF_UCHAR) {
|
||||
prompt("Bit 30")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
field(B1F,DBF_UCHAR) {
|
||||
prompt("Bit 31")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
}
|
||||
|
||||
=head2 Record Support
|
||||
|
||||
=head3 Record Support Routines
|
||||
|
||||
=head4 init_record
|
||||
|
||||
This routine initializes SIMM with the value of SIML if SIML type is CONSTANT
|
||||
link or creates a channel access link if SIML type is PV_LINK. SVAL is likewise
|
||||
initialized if SIOL is CONSTANT or PV_LINK.
|
||||
|
||||
This routine next checks to see that device support is available and a device
|
||||
support read routine is defined. If either does not exist, an error message is
|
||||
issued and processing is terminated.
|
||||
|
||||
Clears MASK and then sets the NOBT low order bits.
|
||||
|
||||
If device support includes C<init_record()>, it is called.
|
||||
|
||||
refresh_bits is then called to refresh all the bit fields based on a hardware
|
||||
value.
|
||||
|
||||
=head4 process
|
||||
|
||||
See next section.
|
||||
|
||||
=head3 Record Processing
|
||||
|
||||
Routine process implements the following algorithm:
|
||||
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
Check to see that the appropriate device support module exists. If it doesn't,
|
||||
an error message is issued and processing is terminated with the PACT field
|
||||
still set to TRUE. This ensures that processes will no longer be called for this
|
||||
record. Thus error storms will not occur.
|
||||
|
||||
=item 2.
|
||||
|
||||
readValue is called. See L<Output Records> for information.
|
||||
|
||||
=item 3.
|
||||
|
||||
If PACT has been changed to TRUE, the device support read routine has started
|
||||
but has not completed reading a new input value. In this case, the processing
|
||||
routine merely returns, leaving PACT TRUE.
|
||||
|
||||
=item 4.
|
||||
|
||||
Convert.
|
||||
|
||||
=over
|
||||
|
||||
=item * status = read_mbbiDirect
|
||||
|
||||
=item * PACT = TRUE
|
||||
|
||||
=item * C<recGblGetTimeStamp()> is called.
|
||||
|
||||
=item * If status is 0, then determine VAL
|
||||
|
||||
=over
|
||||
|
||||
=item * Set rval = RVAL
|
||||
|
||||
=item * Shift rval right SHFT bits
|
||||
|
||||
=item * Set VAL = RVAL
|
||||
|
||||
=back
|
||||
|
||||
=item * If status is 1, return 0
|
||||
|
||||
=item * If status is 2, set status = 0
|
||||
|
||||
=back
|
||||
|
||||
=item 5.
|
||||
|
||||
Check to see if monitors should be invoked.
|
||||
|
||||
=over
|
||||
|
||||
=item * Alarm monitors are invoked if the alarm status or severity has changed.
|
||||
|
||||
=item * Archive and value change monitors are invoked if MLST is not equal to VAL.
|
||||
|
||||
=item * Monitors for RVAL are checked whenever other monitors are invoked.
|
||||
|
||||
=item * NSEV and NSTA are reset to 0.
|
||||
|
||||
=back
|
||||
|
||||
=item 6.
|
||||
|
||||
Scan forward link if necessary, set PACT FALSE, and return.
|
||||
|
||||
=back
|
||||
|
||||
=begin html
|
||||
|
||||
<br><hr><br>
|
||||
|
||||
=end html
|
||||
|
||||
=head2 Device Support
|
||||
|
||||
=head3 Fields Of Interest To Device Support
|
||||
|
||||
Each input record must have an associated set of device support routines.
|
||||
|
||||
The primary responsibility of the device support routines is to obtain a new raw
|
||||
input value whenever read_mbbiDirect is called. The device support routines are
|
||||
primarily interested in the following fields:
|
||||
|
||||
=fields PACT, DPVT, UDF, NSEV, NSTA, NOBT, VAL, INP, RVAL, MASK, SHFT
|
||||
|
||||
=head3 Device Support Routines
|
||||
|
||||
Device support consists of the following routines:
|
||||
|
||||
=head4 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.
|
||||
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.
|
||||
|
||||
=head4 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
|
||||
the integer parameter C<after> set to 0.
|
||||
The second call happens after all of the C<init_record()> calls have been made,
|
||||
with C<after> set to 1.
|
||||
|
||||
=head4 init_record
|
||||
|
||||
init_record(precord)
|
||||
|
||||
This routine is optional. If provided, it is called by the record support
|
||||
C<init_record()> routine. If it uses MASK, it should shift it as necessary and
|
||||
also give SHFT a value.
|
||||
|
||||
=head4 get_ioint_info
|
||||
|
||||
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 IE<sol>O event scan list. cmd has the value (0,1) if the
|
||||
record is being (added to, deleted from) an IE<sol>O event list. It must be
|
||||
provided for any device type that can use the ioEvent scanner.
|
||||
|
||||
=head4 read_mbbiDirect
|
||||
|
||||
read_mbbiDirect(precord)
|
||||
|
||||
This routine must provide a new input value. It returns the following values:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
0: Success. A new raw value is placed in RVAL. The record support module
|
||||
determines VAL from RVAL and SHFT.
|
||||
|
||||
=item *
|
||||
|
||||
2: Success, but don't modify VAL.
|
||||
|
||||
=item *
|
||||
|
||||
Other: Error.
|
||||
|
||||
=back
|
||||
|
||||
=head3 Device Support For Soft Records
|
||||
|
||||
Two soft device support modules, C<<< Soft Channel >>> and C<<< Raw Soft Channel
|
||||
>>>, are provided for multi-bit binary input direct records not related to
|
||||
actual hardware devices. The INP link type must be either CONSTANT, DB_LINK, or
|
||||
CA_LINK.
|
||||
|
||||
=head4 Soft Channel
|
||||
|
||||
For this module, read_mbbiDirect always returns a value of 2, which means that
|
||||
no conversion is performed.
|
||||
|
||||
If the INP link type is constant, then the constant value is stored into VAL by
|
||||
C<init_record()>, and UDF is set to FALSE. VAL can be changed via dbPut
|
||||
requests. If the INP link type is PV_LINK, then dbCaAddInlink is called by
|
||||
C<init_record()>.
|
||||
|
||||
read_mbbiDirect calls recGblGetLinkValue to read the current value of VAL.
|
||||
|
||||
See L<Input Records> for a further explanation.
|
||||
|
||||
If the return status of recGblGetLinkValue is zero, then read_mbbi sets UDF to
|
||||
FALSE. The status of recGblGetLinkValue is returned.
|
||||
|
||||
=head4 Raw Soft Channel
|
||||
|
||||
This module is like the previous except that values are read into RVAL, VAL is
|
||||
computed from RVAL, and read_mbbiDirect returns a value of 0. Thus the record
|
||||
processing routine will determine VAL in the normal way.
|
||||
|
||||
=cut
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user