Add int64 record types and device support, from long
This commit is contained in:
@@ -28,6 +28,8 @@ dbRecStd_SRCS += devBoDbState.c
|
||||
dbRecStd_SRCS += devCalcoutSoft.c
|
||||
dbRecStd_SRCS += devEventSoft.c
|
||||
dbRecStd_SRCS += devHistogramSoft.c
|
||||
dbRecStd_SRCS += devI64inSoft.c
|
||||
dbRecStd_SRCS += devI64outSoft.c
|
||||
dbRecStd_SRCS += devLiSoft.c
|
||||
dbRecStd_SRCS += devLoSoft.c
|
||||
dbRecStd_SRCS += devLsiSoft.c
|
||||
@@ -49,6 +51,7 @@ dbRecStd_SRCS += devGeneralTime.c
|
||||
|
||||
dbRecStd_SRCS += devAiSoftCallback.c
|
||||
dbRecStd_SRCS += devBiSoftCallback.c
|
||||
dbRecStd_SRCS += devI64inSoftCallback.c
|
||||
dbRecStd_SRCS += devLiSoftCallback.c
|
||||
dbRecStd_SRCS += devMbbiDirectSoftCallback.c
|
||||
dbRecStd_SRCS += devMbbiSoftCallback.c
|
||||
@@ -57,6 +60,7 @@ dbRecStd_SRCS += devSiSoftCallback.c
|
||||
dbRecStd_SRCS += devAoSoftCallback.c
|
||||
dbRecStd_SRCS += devBoSoftCallback.c
|
||||
dbRecStd_SRCS += devCalcoutSoftCallback.c
|
||||
dbRecStd_SRCS += devI64outSoftCallback.c
|
||||
dbRecStd_SRCS += devLoSoftCallback.c
|
||||
dbRecStd_SRCS += devLsoSoftCallback.c
|
||||
dbRecStd_SRCS += devMbboSoftCallback.c
|
||||
|
||||
79
src/std/dev/devI64inSoft.c
Normal file
79
src/std/dev/devI64inSoft.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 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.
|
||||
\*************************************************************************/
|
||||
|
||||
/* $Revision-Id$
|
||||
*
|
||||
* Original Author: Janet Anderson
|
||||
* Date: 09-23-91
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alarm.h"
|
||||
#include "dbDefs.h"
|
||||
#include "dbAccess.h"
|
||||
#include "recGbl.h"
|
||||
#include "devSup.h"
|
||||
#include "int64inRecord.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
/* Create the dset for devI64inSoft */
|
||||
static long init_record(int64inRecord *prec);
|
||||
static long read_int64in(int64inRecord *prec);
|
||||
|
||||
struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_int64in;
|
||||
} devI64inSoft = {
|
||||
5,
|
||||
NULL,
|
||||
NULL,
|
||||
init_record,
|
||||
NULL,
|
||||
read_int64in
|
||||
};
|
||||
epicsExportAddress(dset, devI64inSoft);
|
||||
|
||||
static long init_record(int64inRecord *prec)
|
||||
{
|
||||
/* INP must be CONSTANT, PV_LINK, DB_LINK or CA_LINK*/
|
||||
switch (prec->inp.type) {
|
||||
case CONSTANT:
|
||||
if (recGblInitConstantLink(&prec->inp, DBF_INT64, &prec->val))
|
||||
prec->udf = FALSE;
|
||||
break;
|
||||
case PV_LINK:
|
||||
case DB_LINK:
|
||||
case CA_LINK:
|
||||
break;
|
||||
default:
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
"devI64inSoft (init_record) Illegal INP field");
|
||||
return S_db_badField;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long read_int64in(int64inRecord *prec)
|
||||
{
|
||||
long status;
|
||||
|
||||
status = dbGetLink(&prec->inp, DBR_INT64, &prec->val, 0, 0);
|
||||
if (!status &&
|
||||
prec->tsel.type == CONSTANT &&
|
||||
prec->tse == epicsTimeEventDeviceTime)
|
||||
dbGetTimeStamp(&prec->inp, &prec->time);
|
||||
return status;
|
||||
}
|
||||
222
src/std/dev/devI64inSoftCallback.c
Normal file
222
src/std/dev/devI64inSoftCallback.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 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.
|
||||
\*************************************************************************/
|
||||
/* devI64inSoftCallback.c */
|
||||
/*
|
||||
* Authors: Marty Kraimer & Andrew Johnson
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alarm.h"
|
||||
#include "callback.h"
|
||||
#include "cantProceed.h"
|
||||
#include "dbCommon.h"
|
||||
#include "dbDefs.h"
|
||||
#include "dbAccess.h"
|
||||
#include "dbChannel.h"
|
||||
#include "dbNotify.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "recGbl.h"
|
||||
#include "recSup.h"
|
||||
#include "devSup.h"
|
||||
#include "link.h"
|
||||
#include "int64inRecord.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
|
||||
#define GET_OPTIONS (DBR_STATUS | DBR_TIME)
|
||||
|
||||
typedef struct devPvt {
|
||||
processNotify pn;
|
||||
CALLBACK callback;
|
||||
long options;
|
||||
int status;
|
||||
struct {
|
||||
DBRstatus
|
||||
DBRtime
|
||||
epicsInt32 value;
|
||||
} buffer;
|
||||
} devPvt;
|
||||
|
||||
|
||||
static void getCallback(processNotify *ppn, notifyGetType type)
|
||||
{
|
||||
int64inRecord *prec = (int64inRecord *)ppn->usrPvt;
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
long no_elements = 1;
|
||||
|
||||
if (ppn->status == notifyCanceled) {
|
||||
printf("devI64inSoftCallback::getCallback notifyCanceled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(type == getFieldType);
|
||||
pdevPvt->status = dbChannelGetField(ppn->chan, DBR_INT64,
|
||||
&pdevPvt->buffer, &pdevPvt->options, &no_elements, 0);
|
||||
}
|
||||
|
||||
static void doneCallback(processNotify *ppn)
|
||||
{
|
||||
int64inRecord *prec = (int64inRecord *)ppn->usrPvt;
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
|
||||
callbackRequestProcessCallback(&pdevPvt->callback, prec->prio, prec);
|
||||
}
|
||||
|
||||
static long add_record(dbCommon *pcommon)
|
||||
{
|
||||
int64inRecord *prec = (int64inRecord *)pcommon;
|
||||
DBLINK *plink = &prec->inp;
|
||||
dbChannel *chan;
|
||||
devPvt *pdevPvt;
|
||||
processNotify *ppn;
|
||||
|
||||
if (plink->type == CONSTANT) return 0;
|
||||
|
||||
if (plink->type != PV_LINK) {
|
||||
long status = S_db_badField;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
"devI64inSoftCallback (add_record) Illegal INP field");
|
||||
return status;
|
||||
}
|
||||
|
||||
chan = dbChannelCreate(plink->value.pv_link.pvname);
|
||||
if (!chan) {
|
||||
long status = S_db_notFound;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
"devI64inSoftCallback (init_record) linked record not found");
|
||||
return status;
|
||||
}
|
||||
|
||||
pdevPvt = calloc(1, sizeof(*pdevPvt));
|
||||
if (!pdevPvt) {
|
||||
long status = S_db_noMemory;
|
||||
|
||||
recGblRecordError(status, (void *)prec,
|
||||
"devI64inSoftCallback (add_record) out of memory, calloc() failed");
|
||||
return status;
|
||||
}
|
||||
ppn = &pdevPvt->pn;
|
||||
|
||||
plink->type = PN_LINK;
|
||||
plink->value.pv_link.pvlMask &= pvlOptMsMode; /* Severity flags only */
|
||||
|
||||
ppn->usrPvt = prec;
|
||||
ppn->chan = chan;
|
||||
ppn->getCallback = getCallback;
|
||||
ppn->doneCallback = doneCallback;
|
||||
ppn->requestType = processGetRequest;
|
||||
|
||||
pdevPvt->options = GET_OPTIONS;
|
||||
|
||||
prec->dpvt = pdevPvt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long del_record(dbCommon *pcommon) {
|
||||
int64inRecord *prec = (int64inRecord *)pcommon;
|
||||
DBLINK *plink = &prec->inp;
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
|
||||
if (plink->type == CONSTANT) return 0;
|
||||
assert(plink->type == PN_LINK);
|
||||
|
||||
dbNotifyCancel(&pdevPvt->pn);
|
||||
dbChannelDelete(pdevPvt->pn.chan);
|
||||
free(pdevPvt);
|
||||
|
||||
plink->type = PV_LINK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dsxt dsxtSoftCallback = {
|
||||
add_record, del_record
|
||||
};
|
||||
|
||||
static long init(int pass)
|
||||
{
|
||||
if (pass == 0) devExtend(&dsxtSoftCallback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long init_record(int64inRecord *prec)
|
||||
{
|
||||
/* INP must be CONSTANT or PN_LINK */
|
||||
switch (prec->inp.type) {
|
||||
case CONSTANT:
|
||||
if (recGblInitConstantLink(&prec->inp, DBR_INT64, &prec->val))
|
||||
prec->udf = FALSE;
|
||||
break;
|
||||
case PN_LINK:
|
||||
/* Handled by add_record */
|
||||
break;
|
||||
default:
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
"devI64inSoftCallback (init_record) Illegal INP field");
|
||||
prec->pact = TRUE;
|
||||
return S_db_badField;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long read_int64in(int64inRecord *prec)
|
||||
{
|
||||
devPvt *pdevPvt = (devPvt *)prec->dpvt;
|
||||
|
||||
if (!prec->dpvt)
|
||||
return 0;
|
||||
|
||||
if (!prec->pact) {
|
||||
dbProcessNotify(&pdevPvt->pn);
|
||||
prec->pact = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pdevPvt->status) {
|
||||
recGblSetSevr(prec, READ_ALARM, INVALID_ALARM);
|
||||
return pdevPvt->status;
|
||||
}
|
||||
|
||||
prec->val = pdevPvt->buffer.value;
|
||||
prec->udf = FALSE;
|
||||
|
||||
switch (prec->inp.value.pv_link.pvlMask & pvlOptMsMode) {
|
||||
case pvlOptNMS:
|
||||
break;
|
||||
case pvlOptMSI:
|
||||
if (pdevPvt->buffer.severity < INVALID_ALARM)
|
||||
break;
|
||||
/* else fall through */
|
||||
case pvlOptMS:
|
||||
recGblSetSevr(prec, LINK_ALARM, pdevPvt->buffer.severity);
|
||||
break;
|
||||
case pvlOptMSS:
|
||||
recGblSetSevr(prec, pdevPvt->buffer.status,
|
||||
pdevPvt->buffer.severity);
|
||||
break;
|
||||
}
|
||||
|
||||
if (prec->tsel.type == CONSTANT &&
|
||||
prec->tse == epicsTimeEventDeviceTime)
|
||||
prec->time = pdevPvt->buffer.time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create the dset for devI64inSoftCallback */
|
||||
struct {
|
||||
dset common;
|
||||
DEVSUPFUN read_int64in;
|
||||
} devI64inSoftCallback = {
|
||||
{5, NULL, init, init_record, NULL},
|
||||
read_int64in
|
||||
};
|
||||
epicsExportAddress(dset, devI64inSoftCallback);
|
||||
58
src/std/dev/devI64outSoft.c
Normal file
58
src/std/dev/devI64outSoft.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 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.
|
||||
\*************************************************************************/
|
||||
|
||||
/* $Revision-Id$ */
|
||||
/*
|
||||
* Original Author: Janet Anderson
|
||||
* Date: 09-23-91
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alarm.h"
|
||||
#include "dbDefs.h"
|
||||
#include "dbAccess.h"
|
||||
#include "recGbl.h"
|
||||
#include "recSup.h"
|
||||
#include "devSup.h"
|
||||
#include "int64outRecord.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
/* Create the dset for devI64outSoft */
|
||||
static long init_record(int64outRecord *prec);
|
||||
static long write_int64out(int64outRecord *prec);
|
||||
struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN write_int64out;
|
||||
} devI64outSoft = {
|
||||
5,
|
||||
NULL,
|
||||
NULL,
|
||||
init_record,
|
||||
NULL,
|
||||
write_int64out
|
||||
};
|
||||
epicsExportAddress(dset, devI64outSoft);
|
||||
|
||||
static long init_record(int64outRecord *prec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long write_int64out(int64outRecord *prec)
|
||||
{
|
||||
dbPutLink(&prec->out, DBR_INT64, &prec->val,1);
|
||||
return 0;
|
||||
}
|
||||
69
src/std/dev/devI64outSoftCallback.c
Normal file
69
src/std/dev/devI64outSoftCallback.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 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.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Original Author: Marty Kraimer
|
||||
* Date: 04NOV2003
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alarm.h"
|
||||
#include "dbDefs.h"
|
||||
#include "dbAccess.h"
|
||||
#include "recGbl.h"
|
||||
#include "recSup.h"
|
||||
#include "devSup.h"
|
||||
#include "int64outRecord.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
/* Create the dset for devI64outSoftCallback */
|
||||
static long write_int64out(int64outRecord *prec);
|
||||
struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN write_int64out;
|
||||
} devI64outSoftCallback = {
|
||||
5,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
write_int64out
|
||||
};
|
||||
epicsExportAddress(dset, devI64outSoftCallback);
|
||||
|
||||
static long write_int64out(int64outRecord *prec)
|
||||
{
|
||||
struct link *plink = &prec->out;
|
||||
long status;
|
||||
|
||||
if (prec->pact)
|
||||
return 0;
|
||||
|
||||
if (plink->type != CA_LINK) {
|
||||
status = dbPutLink(plink, DBR_INT64, &prec->val, 1);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = dbCaPutLinkCallback(plink, DBR_INT64, &prec->val, 1,
|
||||
dbCaCallbackProcess, plink);
|
||||
if (status) {
|
||||
recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM);
|
||||
return status;
|
||||
}
|
||||
|
||||
prec->pact = TRUE;
|
||||
return 0;
|
||||
}
|
||||
@@ -9,6 +9,8 @@ device(bo,CONSTANT,devBoSoft,"Soft Channel")
|
||||
device(calcout,CONSTANT,devCalcoutSoft,"Soft Channel")
|
||||
device(event,CONSTANT,devEventSoft,"Soft Channel")
|
||||
device(histogram,CONSTANT,devHistogramSoft,"Soft Channel")
|
||||
device(int64in,CONSTANT,devI64inSoft,"Soft Channel")
|
||||
device(int64out,CONSTANT,devI64outSoft,"Soft Channel")
|
||||
device(longin,CONSTANT,devLiSoft,"Soft Channel")
|
||||
device(longout,CONSTANT,devLoSoft,"Soft Channel")
|
||||
device(lsi,CONSTANT,devLsiSoft,"Soft Channel")
|
||||
@@ -37,6 +39,8 @@ device(ao,CONSTANT,devAoSoftCallback,"Async Soft Channel")
|
||||
device(bi,CONSTANT,devBiSoftCallback,"Async Soft Channel")
|
||||
device(bo,CONSTANT,devBoSoftCallback,"Async Soft Channel")
|
||||
device(calcout,CONSTANT,devCalcoutSoftCallback,"Async Soft Channel")
|
||||
device(int64in,CONSTANT,devI64inSoftCallback,"Async Soft Channel")
|
||||
device(int64out,CONSTANT,devI64outSoftCallback,"Async Soft Channel")
|
||||
device(longin,CONSTANT,devLiSoftCallback,"Async Soft Channel")
|
||||
device(longout,CONSTANT,devLoSoftCallback,"Async Soft Channel")
|
||||
device(lso,CONSTANT,devLsoSoftCallback,"Async Soft Channel")
|
||||
|
||||
@@ -25,6 +25,8 @@ stdRecords += dfanoutRecord
|
||||
stdRecords += eventRecord
|
||||
stdRecords += fanoutRecord
|
||||
stdRecords += histogramRecord
|
||||
stdRecords += int64inRecord
|
||||
stdRecords += int64outRecord
|
||||
stdRecords += longinRecord
|
||||
stdRecords += longoutRecord
|
||||
stdRecords += lsiRecord
|
||||
|
||||
416
src/std/rec/int64inRecord.c
Normal file
416
src/std/rec/int64inRecord.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2008 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.
|
||||
\*************************************************************************/
|
||||
|
||||
/* $Revision-Id$ */
|
||||
|
||||
/* int64inRecord.c - Record Support Routines for int64in records */
|
||||
/*
|
||||
* Original Author: Janet Anderson
|
||||
* Date: 9/23/91
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsPrint.h"
|
||||
#include "alarm.h"
|
||||
#include "dbAccess.h"
|
||||
#include "dbEvent.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "devSup.h"
|
||||
#include "errMdef.h"
|
||||
#include "recSup.h"
|
||||
#include "recGbl.h"
|
||||
#include "menuYesNo.h"
|
||||
|
||||
#define GEN_SIZE_OFFSET
|
||||
#include "int64inRecord.h"
|
||||
#undef GEN_SIZE_OFFSET
|
||||
#include "epicsExport.h"
|
||||
|
||||
/* Hysterisis for alarm filtering: 1-1/e */
|
||||
#define THRESHOLD 0.6321
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
#define report NULL
|
||||
#define initialize NULL
|
||||
static long init_record(int64inRecord *, int);
|
||||
static long process(int64inRecord *);
|
||||
#define special NULL
|
||||
#define get_value NULL
|
||||
#define cvt_dbaddr NULL
|
||||
#define get_array_info NULL
|
||||
#define put_array_info NULL
|
||||
static long get_units(DBADDR *, char *);
|
||||
#define get_precision NULL
|
||||
#define get_enum_str NULL
|
||||
#define get_enum_strs NULL
|
||||
#define put_enum_str NULL
|
||||
static long get_graphic_double(DBADDR *, struct dbr_grDouble *);
|
||||
static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
|
||||
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
|
||||
|
||||
rset int64inRSET={
|
||||
RSETNUMBER,
|
||||
report,
|
||||
initialize,
|
||||
init_record,
|
||||
process,
|
||||
special,
|
||||
get_value,
|
||||
cvt_dbaddr,
|
||||
get_array_info,
|
||||
put_array_info,
|
||||
get_units,
|
||||
get_precision,
|
||||
get_enum_str,
|
||||
get_enum_strs,
|
||||
put_enum_str,
|
||||
get_graphic_double,
|
||||
get_control_double,
|
||||
get_alarm_double
|
||||
};
|
||||
epicsExportAddress(rset,int64inRSET);
|
||||
|
||||
|
||||
struct int64indset { /* int64in input dset */
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_int64in; /*returns: (-1,0)=>(failure,success)*/
|
||||
};
|
||||
static void checkAlarms(int64inRecord *prec, epicsTimeStamp *timeLast);
|
||||
static void monitor(int64inRecord *prec);
|
||||
static long readValue(int64inRecord *prec);
|
||||
|
||||
|
||||
static long init_record(int64inRecord *prec, int pass)
|
||||
{
|
||||
struct int64indset *pdset;
|
||||
long status;
|
||||
|
||||
if (pass==0) return(0);
|
||||
|
||||
/* int64in.siml must be a CONSTANT or a PV_LINK or a DB_LINK */
|
||||
if (prec->siml.type == CONSTANT) {
|
||||
recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
|
||||
}
|
||||
|
||||
/* int64in.siol must be a CONSTANT or a PV_LINK or a DB_LINK */
|
||||
if (prec->siol.type == CONSTANT) {
|
||||
recGblInitConstantLink(&prec->siol,DBF_LONG,&prec->sval);
|
||||
}
|
||||
|
||||
if(!(pdset = (struct int64indset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"int64in: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* must have read_int64in function defined */
|
||||
if( (pdset->number < 5) || (pdset->read_int64in == NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"int64in: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(prec))) return(status);
|
||||
}
|
||||
prec->mlst = prec->val;
|
||||
prec->alst = prec->val;
|
||||
prec->lalm = prec->val;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(int64inRecord *prec)
|
||||
{
|
||||
struct int64indset *pdset = (struct int64indset *)(prec->dset);
|
||||
long status;
|
||||
unsigned char pact=prec->pact;
|
||||
epicsTimeStamp timeLast;
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_int64in==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"read_int64in");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
timeLast = prec->time;
|
||||
|
||||
status=readValue(prec); /* read the new value */
|
||||
/* check if device support set pact */
|
||||
if ( !pact && prec->pact ) return(0);
|
||||
prec->pact = TRUE;
|
||||
|
||||
recGblGetTimeStamp(prec);
|
||||
if (status==0) prec->udf = FALSE;
|
||||
|
||||
/* check for alarms */
|
||||
checkAlarms(prec, &timeLast);
|
||||
/* check event list */
|
||||
monitor(prec);
|
||||
/* process the forward scan link record */
|
||||
recGblFwdLink(prec);
|
||||
|
||||
prec->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
#define indexof(field) int64inRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr,char *units)
|
||||
{
|
||||
int64inRecord *prec=(int64inRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfldDes->field_type == DBF_LONG) {
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
int64inRecord *prec=(int64inRecord *)paddr->precord;
|
||||
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
case indexof(HIHI):
|
||||
case indexof(HIGH):
|
||||
case indexof(LOW):
|
||||
case indexof(LOLO):
|
||||
case indexof(LALM):
|
||||
case indexof(ALST):
|
||||
case indexof(MLST):
|
||||
case indexof(SVAL):
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
int64inRecord *prec=(int64inRecord *)paddr->precord;
|
||||
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
case indexof(HIHI):
|
||||
case indexof(HIGH):
|
||||
case indexof(LOW):
|
||||
case indexof(LOLO):
|
||||
case indexof(LALM):
|
||||
case indexof(ALST):
|
||||
case indexof(MLST):
|
||||
case indexof(SVAL):
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
{
|
||||
int64inRecord *prec=(int64inRecord *)paddr->precord;
|
||||
|
||||
if(dbGetFieldIndex(paddr) == indexof(VAL)){
|
||||
pad->upper_alarm_limit = prec->hihi;
|
||||
pad->upper_warning_limit = prec->high;
|
||||
pad->lower_warning_limit = prec->low;
|
||||
pad->lower_alarm_limit = prec->lolo;
|
||||
} else recGblGetAlarmDouble(paddr,pad);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void checkAlarms(int64inRecord *prec, epicsTimeStamp *timeLast)
|
||||
{
|
||||
enum {
|
||||
range_Lolo = 1,
|
||||
range_Low,
|
||||
range_Normal,
|
||||
range_High,
|
||||
range_Hihi
|
||||
} alarmRange;
|
||||
static const epicsEnum16 range_stat[] = {
|
||||
SOFT_ALARM, LOLO_ALARM, LOW_ALARM,
|
||||
NO_ALARM, HIGH_ALARM, HIHI_ALARM
|
||||
};
|
||||
|
||||
double aftc, afvl;
|
||||
epicsInt64 val, hyst, lalm;
|
||||
epicsInt64 alev;
|
||||
epicsEnum16 asev;
|
||||
|
||||
if (prec->udf) {
|
||||
recGblSetSevr(prec, UDF_ALARM, prec->udfs);
|
||||
prec->afvl = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
val = prec->val;
|
||||
hyst = prec->hyst;
|
||||
lalm = prec->lalm;
|
||||
|
||||
/* check VAL against alarm limits */
|
||||
if ((asev = prec->hhsv) &&
|
||||
(val >= (alev = prec->hihi) ||
|
||||
((lalm == alev) && (val >= alev - hyst))))
|
||||
alarmRange = range_Hihi;
|
||||
else
|
||||
if ((asev = prec->llsv) &&
|
||||
(val <= (alev = prec->lolo) ||
|
||||
((lalm == alev) && (val <= alev + hyst))))
|
||||
alarmRange = range_Lolo;
|
||||
else
|
||||
if ((asev = prec->hsv) &&
|
||||
(val >= (alev = prec->high) ||
|
||||
((lalm == alev) && (val >= alev - hyst))))
|
||||
alarmRange = range_High;
|
||||
else
|
||||
if ((asev = prec->lsv) &&
|
||||
(val <= (alev = prec->low) ||
|
||||
((lalm == alev) && (val <= alev + hyst))))
|
||||
alarmRange = range_Low;
|
||||
else {
|
||||
alev = val;
|
||||
asev = NO_ALARM;
|
||||
alarmRange = range_Normal;
|
||||
}
|
||||
|
||||
aftc = prec->aftc;
|
||||
afvl = 0;
|
||||
|
||||
if (aftc > 0) {
|
||||
/* Apply level filtering */
|
||||
afvl = prec->afvl;
|
||||
if (afvl == 0) {
|
||||
afvl = (double)alarmRange;
|
||||
} else {
|
||||
double t = epicsTimeDiffInSeconds(&prec->time, timeLast);
|
||||
double alpha = aftc / (t + aftc);
|
||||
|
||||
/* The sign of afvl indicates whether the result should be
|
||||
* rounded up or down. This gives the filter hysteresis.
|
||||
* If afvl > 0 the floor() function rounds to a lower alarm
|
||||
* level, otherwise to a higher.
|
||||
*/
|
||||
afvl = alpha * afvl +
|
||||
((afvl > 0) ? (1 - alpha) : (alpha - 1)) * alarmRange;
|
||||
if (afvl - floor(afvl) > THRESHOLD)
|
||||
afvl = -afvl; /* reverse rounding */
|
||||
|
||||
alarmRange = abs((int)floor(afvl));
|
||||
switch (alarmRange) {
|
||||
case range_Hihi:
|
||||
asev = prec->hhsv;
|
||||
alev = prec->hihi;
|
||||
break;
|
||||
case range_High:
|
||||
asev = prec->hsv;
|
||||
alev = prec->high;
|
||||
break;
|
||||
case range_Normal:
|
||||
asev = NO_ALARM;
|
||||
break;
|
||||
case range_Low:
|
||||
asev = prec->lsv;
|
||||
alev = prec->low;
|
||||
break;
|
||||
case range_Lolo:
|
||||
asev = prec->llsv;
|
||||
alev = prec->lolo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
prec->afvl = afvl;
|
||||
|
||||
if (asev) {
|
||||
/* Report alarm condition, store LALM for future HYST calculations */
|
||||
if (recGblSetSevr(prec, range_stat[alarmRange], asev))
|
||||
prec->lalm = alev;
|
||||
} else {
|
||||
/* No alarm condition, reset LALM */
|
||||
prec->lalm = val;
|
||||
}
|
||||
}
|
||||
|
||||
/* DELTA calculates the absolute difference between its arguments
|
||||
* expressed as an unsigned 32-bit integer */
|
||||
#define DELTA(last, val) \
|
||||
((epicsUInt32) ((last) > (val) ? (last) - (val) : (val) - (last)))
|
||||
|
||||
static void monitor(int64inRecord *prec)
|
||||
{
|
||||
unsigned short monitor_mask = recGblResetAlarms(prec);
|
||||
|
||||
if (prec->mdel < 0 ||
|
||||
DELTA(prec->mlst, prec->val) > (epicsUInt32) prec->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
prec->mlst = prec->val;
|
||||
}
|
||||
|
||||
if (prec->adel < 0 ||
|
||||
DELTA(prec->alst, prec->val) > (epicsUInt32) prec->adel) {
|
||||
/* post events for archive value change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
/* update last archive value monitored */
|
||||
prec->alst = prec->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask)
|
||||
db_post_events(prec, &prec->val, monitor_mask);
|
||||
}
|
||||
|
||||
static long readValue(int64inRecord *prec)
|
||||
{
|
||||
long status;
|
||||
struct int64indset *pdset = (struct int64indset *) (prec->dset);
|
||||
|
||||
if (prec->pact == TRUE){
|
||||
status=(*pdset->read_int64in)(prec);
|
||||
return(status);
|
||||
}
|
||||
|
||||
status=dbGetLink(&(prec->siml),DBR_USHORT, &(prec->simm),0,0);
|
||||
if (status)
|
||||
return(status);
|
||||
|
||||
if (prec->simm == menuYesNoNO){
|
||||
status=(*pdset->read_int64in)(prec);
|
||||
return(status);
|
||||
}
|
||||
if (prec->simm == menuYesNoYES){
|
||||
status=dbGetLink(&(prec->siol),DBR_LONG,
|
||||
&(prec->sval),0,0);
|
||||
|
||||
if (status==0) {
|
||||
prec->val=prec->sval;
|
||||
prec->udf=FALSE;
|
||||
}
|
||||
} else {
|
||||
status=-1;
|
||||
recGblSetSevr(prec,SOFT_ALARM,INVALID_ALARM);
|
||||
return(status);
|
||||
}
|
||||
recGblSetSevr(prec,SIMM_ALARM,prec->sims);
|
||||
|
||||
return(status);
|
||||
}
|
||||
161
src/std/rec/int64inRecord.dbd
Normal file
161
src/std/rec/int64inRecord.dbd
Normal file
@@ -0,0 +1,161 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(int64in) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_INT64) {
|
||||
prompt("Current value")
|
||||
promptgroup(GUI_INPUTS)
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup(GUI_INPUTS)
|
||||
interest(1)
|
||||
}
|
||||
field(EGU,DBF_STRING) {
|
||||
prompt("Units name")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
}
|
||||
field(HOPR,DBF_INT64) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOPR,DBF_INT64) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIHI,DBF_INT64) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOLO,DBF_INT64) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIGH,DBF_INT64) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOW,DBF_INT64) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
prompt("Lolo Severity")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
prompt("High Severity")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
prompt("Low Severity")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_INT64) {
|
||||
prompt("Alarm Deadband")
|
||||
promptgroup(GUI_ALARMS)
|
||||
interest(1)
|
||||
}
|
||||
field(AFTC, DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Time Constant")
|
||||
promptgroup(GUI_ALARMS)
|
||||
interest(1)
|
||||
}
|
||||
field(AFVL, DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Value")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ADEL,DBF_INT64) {
|
||||
prompt("Archive Deadband")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
}
|
||||
field(MDEL,DBF_INT64) {
|
||||
prompt("Monitor Deadband")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
}
|
||||
field(LALM,DBF_INT64) {
|
||||
prompt("Last Value Alarmed")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ALST,DBF_INT64) {
|
||||
prompt("Last Value Archived")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(MLST,DBF_INT64) {
|
||||
prompt("Last Val Monitored")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(SIOL,DBF_INLINK) {
|
||||
prompt("Sim Input Specifctn")
|
||||
promptgroup(GUI_INPUTS)
|
||||
interest(1)
|
||||
}
|
||||
field(SVAL,DBF_INT64) {
|
||||
prompt("Simulation Value")
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Sim Mode Location")
|
||||
promptgroup(GUI_INPUTS)
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
interest(1)
|
||||
menu(menuYesNo)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Sim mode Alarm Svrty")
|
||||
promptgroup(GUI_INPUTS)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
}
|
||||
393
src/std/rec/int64outRecord.c
Normal file
393
src/std/rec/int64outRecord.c
Normal file
@@ -0,0 +1,393 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 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.
|
||||
\*************************************************************************/
|
||||
|
||||
/* $Revision-Id$ */
|
||||
/*
|
||||
* Original Author: Janet Anderson
|
||||
* Date: 9/23/91
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsPrint.h"
|
||||
#include "alarm.h"
|
||||
#include "dbAccess.h"
|
||||
#include "dbEvent.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "devSup.h"
|
||||
#include "errMdef.h"
|
||||
#include "recSup.h"
|
||||
#include "recGbl.h"
|
||||
#include "menuYesNo.h"
|
||||
#include "menuIvoa.h"
|
||||
#include "menuOmsl.h"
|
||||
|
||||
#define GEN_SIZE_OFFSET
|
||||
#include "int64outRecord.h"
|
||||
#undef GEN_SIZE_OFFSET
|
||||
#include "epicsExport.h"
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
#define report NULL
|
||||
#define initialize NULL
|
||||
static long init_record(int64outRecord *, int);
|
||||
static long process(int64outRecord *);
|
||||
#define special NULL
|
||||
#define get_value NULL
|
||||
#define cvt_dbaddr NULL
|
||||
#define get_array_info NULL
|
||||
#define put_array_info NULL
|
||||
static long get_units(DBADDR *, char *);
|
||||
#define get_precision NULL
|
||||
#define get_enum_str NULL
|
||||
#define get_enum_strs NULL
|
||||
#define put_enum_str NULL
|
||||
static long get_graphic_double(DBADDR *, struct dbr_grDouble *);
|
||||
static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
|
||||
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
|
||||
|
||||
rset int64outRSET={
|
||||
RSETNUMBER,
|
||||
report,
|
||||
initialize,
|
||||
init_record,
|
||||
process,
|
||||
special,
|
||||
get_value,
|
||||
cvt_dbaddr,
|
||||
get_array_info,
|
||||
put_array_info,
|
||||
get_units,
|
||||
get_precision,
|
||||
get_enum_str,
|
||||
get_enum_strs,
|
||||
put_enum_str,
|
||||
get_graphic_double,
|
||||
get_control_double,
|
||||
get_alarm_double
|
||||
};
|
||||
epicsExportAddress(rset,int64outRSET);
|
||||
|
||||
|
||||
struct int64outdset { /* int64out input dset */
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN write_int64out;/*(-1,0)=>(failure,success*/
|
||||
};
|
||||
static void checkAlarms(int64outRecord *prec);
|
||||
static void monitor(int64outRecord *prec);
|
||||
static long writeValue(int64outRecord *prec);
|
||||
static void convert(int64outRecord *prec, epicsInt64 value);
|
||||
|
||||
|
||||
static long init_record(int64outRecord *prec, int pass)
|
||||
{
|
||||
struct int64outdset *pdset;
|
||||
long status=0;
|
||||
|
||||
if (pass==0) return(0);
|
||||
if (prec->siml.type == CONSTANT) {
|
||||
recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
|
||||
}
|
||||
if(!(pdset = (struct int64outdset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"int64out: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* must have write_int64out functions defined */
|
||||
if( (pdset->number < 5) || (pdset->write_int64out == NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"int64out: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if (prec->dol.type == CONSTANT) {
|
||||
if(recGblInitConstantLink(&prec->dol,DBF_INT64,&prec->val))
|
||||
prec->udf=FALSE;
|
||||
}
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(prec))) return(status);
|
||||
}
|
||||
prec->mlst = prec->val;
|
||||
prec->alst = prec->val;
|
||||
prec->lalm = prec->val;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(int64outRecord *prec)
|
||||
{
|
||||
struct int64outdset *pdset = (struct int64outdset *)(prec->dset);
|
||||
long status=0;
|
||||
epicsInt64 value;
|
||||
unsigned char pact=prec->pact;
|
||||
|
||||
if( (pdset==NULL) || (pdset->write_int64out==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"write_int64out");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if (!prec->pact) {
|
||||
if((prec->dol.type != CONSTANT)
|
||||
&& (prec->omsl == menuOmslclosed_loop)) {
|
||||
status = dbGetLink(&(prec->dol),DBR_INT64,
|
||||
&value,0,0);
|
||||
if (prec->dol.type!=CONSTANT && RTN_SUCCESS(status))
|
||||
prec->udf=FALSE;
|
||||
}
|
||||
else {
|
||||
value = prec->val;
|
||||
}
|
||||
if (!status) convert(prec,value);
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
checkAlarms(prec);
|
||||
|
||||
if (prec->nsev < INVALID_ALARM )
|
||||
status=writeValue(prec); /* write the new value */
|
||||
else {
|
||||
switch (prec->ivoa) {
|
||||
case (menuIvoaContinue_normally) :
|
||||
status=writeValue(prec); /* write the new value */
|
||||
break;
|
||||
case (menuIvoaDon_t_drive_outputs) :
|
||||
break;
|
||||
case (menuIvoaSet_output_to_IVOV) :
|
||||
if(prec->pact == FALSE){
|
||||
prec->val=prec->ivov;
|
||||
}
|
||||
status=writeValue(prec); /* write the new value */
|
||||
break;
|
||||
default :
|
||||
status=-1;
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"int64out:process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
|
||||
/* check if device support set pact */
|
||||
if ( !pact && prec->pact ) return(0);
|
||||
prec->pact = TRUE;
|
||||
|
||||
recGblGetTimeStamp(prec);
|
||||
|
||||
/* check event list */
|
||||
monitor(prec);
|
||||
|
||||
/* process the forward scan link record */
|
||||
recGblFwdLink(prec);
|
||||
|
||||
prec->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
#define indexof(field) int64outRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr,char *units)
|
||||
{
|
||||
int64outRecord *prec=(int64outRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfldDes->field_type == DBF_INT64) {
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
|
||||
{
|
||||
int64outRecord *prec=(int64outRecord *)paddr->precord;
|
||||
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
case indexof(HIHI):
|
||||
case indexof(HIGH):
|
||||
case indexof(LOW):
|
||||
case indexof(LOLO):
|
||||
case indexof(LALM):
|
||||
case indexof(ALST):
|
||||
case indexof(MLST):
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
int64outRecord *prec=(int64outRecord *)paddr->precord;
|
||||
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
case indexof(HIHI):
|
||||
case indexof(HIGH):
|
||||
case indexof(LOW):
|
||||
case indexof(LOLO):
|
||||
case indexof(LALM):
|
||||
case indexof(ALST):
|
||||
case indexof(MLST):
|
||||
/* do not change pre drvh/drvl behavior */
|
||||
if(prec->drvh > prec->drvl) {
|
||||
pcd->upper_ctrl_limit = prec->drvh;
|
||||
pcd->lower_ctrl_limit = prec->drvl;
|
||||
} else {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
|
||||
{
|
||||
int64outRecord *prec=(int64outRecord *)paddr->precord;
|
||||
|
||||
if(dbGetFieldIndex(paddr) == indexof(VAL)) {
|
||||
pad->upper_alarm_limit = prec->hihi;
|
||||
pad->upper_warning_limit = prec->high;
|
||||
pad->lower_warning_limit = prec->low;
|
||||
pad->lower_alarm_limit = prec->lolo;
|
||||
} else recGblGetAlarmDouble(paddr,pad);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void checkAlarms(int64outRecord *prec)
|
||||
{
|
||||
epicsInt64 val, hyst, lalm;
|
||||
epicsInt64 alev;
|
||||
epicsEnum16 asev;
|
||||
|
||||
if (prec->udf) {
|
||||
recGblSetSevr(prec, UDF_ALARM, prec->udfs);
|
||||
return;
|
||||
}
|
||||
|
||||
val = prec->val;
|
||||
hyst = prec->hyst;
|
||||
lalm = prec->lalm;
|
||||
|
||||
/* alarm condition hihi */
|
||||
asev = prec->hhsv;
|
||||
alev = prec->hihi;
|
||||
if (asev && (val >= alev || ((lalm == alev) && (val >= alev - hyst)))) {
|
||||
if (recGblSetSevr(prec, HIHI_ALARM, asev))
|
||||
prec->lalm = alev;
|
||||
return;
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
asev = prec->llsv;
|
||||
alev = prec->lolo;
|
||||
if (asev && (val <= alev || ((lalm == alev) && (val <= alev + hyst)))) {
|
||||
if (recGblSetSevr(prec, LOLO_ALARM, asev))
|
||||
prec->lalm = alev;
|
||||
return;
|
||||
}
|
||||
|
||||
/* alarm condition high */
|
||||
asev = prec->hsv;
|
||||
alev = prec->high;
|
||||
if (asev && (val >= alev || ((lalm == alev) && (val >= alev - hyst)))) {
|
||||
if (recGblSetSevr(prec, HIGH_ALARM, asev))
|
||||
prec->lalm = alev;
|
||||
return;
|
||||
}
|
||||
|
||||
/* alarm condition low */
|
||||
asev = prec->lsv;
|
||||
alev = prec->low;
|
||||
if (asev && (val <= alev || ((lalm == alev) && (val <= alev + hyst)))) {
|
||||
if (recGblSetSevr(prec, LOW_ALARM, asev))
|
||||
prec->lalm = alev;
|
||||
return;
|
||||
}
|
||||
|
||||
/* we get here only if val is out of alarm by at least hyst */
|
||||
prec->lalm = val;
|
||||
return;
|
||||
}
|
||||
|
||||
/* DELTA calculates the absolute difference between its arguments
|
||||
* expressed as an unsigned 64-bit integer */
|
||||
#define DELTA(last, val) \
|
||||
((epicsUInt64) ((last) > (val) ? (last) - (val) : (val) - (last)))
|
||||
|
||||
static void monitor(int64outRecord *prec)
|
||||
{
|
||||
unsigned short monitor_mask = recGblResetAlarms(prec);
|
||||
|
||||
if (prec->mdel < 0 ||
|
||||
DELTA(prec->mlst, prec->val) > (epicsUInt64) prec->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
prec->mlst = prec->val;
|
||||
}
|
||||
|
||||
if (prec->adel < 0 ||
|
||||
DELTA(prec->alst, prec->val) > (epicsUInt64) prec->adel) {
|
||||
/* post events for archive value change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
/* update last archive value monitored */
|
||||
prec->alst = prec->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask)
|
||||
db_post_events(prec, &prec->val, monitor_mask);
|
||||
}
|
||||
|
||||
static long writeValue(int64outRecord *prec)
|
||||
{
|
||||
long status;
|
||||
struct int64outdset *pdset = (struct int64outdset *) (prec->dset);
|
||||
|
||||
if (prec->pact == TRUE){
|
||||
status=(*pdset->write_int64out)(prec);
|
||||
return(status);
|
||||
}
|
||||
|
||||
status=dbGetLink(&(prec->siml),DBR_USHORT,&(prec->simm),0,0);
|
||||
if (!RTN_SUCCESS(status))
|
||||
return(status);
|
||||
|
||||
if (prec->simm == menuYesNoNO){
|
||||
status=(*pdset->write_int64out)(prec);
|
||||
return(status);
|
||||
}
|
||||
if (prec->simm == menuYesNoYES){
|
||||
status=dbPutLink(&prec->siol,DBR_INT64,&prec->val,1);
|
||||
} else {
|
||||
status=-1;
|
||||
recGblSetSevr(prec,SOFT_ALARM,INVALID_ALARM);
|
||||
return(status);
|
||||
}
|
||||
recGblSetSevr(prec,SIMM_ALARM,prec->sims);
|
||||
|
||||
return(status);
|
||||
}
|
||||
|
||||
static void convert(int64outRecord *prec, epicsInt64 value)
|
||||
{
|
||||
/* check drive limits */
|
||||
if(prec->drvh > prec->drvl) {
|
||||
if (value > prec->drvh) value = prec->drvh;
|
||||
else if (value < prec->drvl) value = prec->drvl;
|
||||
}
|
||||
prec->val = value;
|
||||
}
|
||||
184
src/std/rec/int64outRecord.dbd
Normal file
184
src/std/rec/int64outRecord.dbd
Normal file
@@ -0,0 +1,184 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(int64out) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_INT64) {
|
||||
prompt("Desired Output")
|
||||
promptgroup(GUI_OUTPUT)
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
}
|
||||
field(OUT,DBF_OUTLINK) {
|
||||
prompt("Output Specification")
|
||||
promptgroup(GUI_OUTPUT)
|
||||
interest(1)
|
||||
}
|
||||
field(DOL,DBF_INLINK) {
|
||||
prompt("Desired Output Loc")
|
||||
promptgroup(GUI_OUTPUT)
|
||||
interest(1)
|
||||
}
|
||||
field(OMSL,DBF_MENU) {
|
||||
prompt("Output Mode Select")
|
||||
promptgroup(GUI_OUTPUT)
|
||||
interest(1)
|
||||
menu(menuOmsl)
|
||||
}
|
||||
field(EGU,DBF_STRING) {
|
||||
prompt("Units name")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
size(16)
|
||||
prop(YES)
|
||||
}
|
||||
field(DRVH,DBF_INT64) {
|
||||
prompt("Drive High Limit")
|
||||
promptgroup(GUI_OUTPUT)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(DRVL,DBF_INT64) {
|
||||
prompt("Drive Low Limit")
|
||||
promptgroup(GUI_OUTPUT)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HOPR,DBF_INT64) {
|
||||
prompt("High Operating Range")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOPR,DBF_INT64) {
|
||||
prompt("Low Operating Range")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIHI,DBF_INT64) {
|
||||
prompt("Hihi Alarm Limit")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOLO,DBF_INT64) {
|
||||
prompt("Lolo Alarm Limit")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HIGH,DBF_INT64) {
|
||||
prompt("High Alarm Limit")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(LOW,DBF_INT64) {
|
||||
prompt("Low Alarm Limit")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
prop(YES)
|
||||
}
|
||||
field(HHSV,DBF_MENU) {
|
||||
prompt("Hihi Severity")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LLSV,DBF_MENU) {
|
||||
prompt("Lolo Severity")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HSV,DBF_MENU) {
|
||||
prompt("High Severity")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LSV,DBF_MENU) {
|
||||
prompt("Low Severity")
|
||||
promptgroup(GUI_ALARMS)
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(HYST,DBF_INT64) {
|
||||
prompt("Alarm Deadband")
|
||||
promptgroup(GUI_ALARMS)
|
||||
interest(1)
|
||||
}
|
||||
field(ADEL,DBF_INT64) {
|
||||
prompt("Archive Deadband")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
}
|
||||
field(MDEL,DBF_INT64) {
|
||||
prompt("Monitor Deadband")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
interest(1)
|
||||
}
|
||||
field(LALM,DBF_INT64) {
|
||||
prompt("Last Value Alarmed")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ALST,DBF_INT64) {
|
||||
prompt("Last Value Archived")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(MLST,DBF_INT64) {
|
||||
prompt("Last Val Monitored")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(SIOL,DBF_OUTLINK) {
|
||||
prompt("Sim Output Specifctn")
|
||||
promptgroup(GUI_INPUTS)
|
||||
interest(1)
|
||||
}
|
||||
field(SIML,DBF_INLINK) {
|
||||
prompt("Sim Mode Location")
|
||||
promptgroup(GUI_INPUTS)
|
||||
interest(1)
|
||||
}
|
||||
field(SIMM,DBF_MENU) {
|
||||
prompt("Simulation Mode")
|
||||
interest(1)
|
||||
menu(menuYesNo)
|
||||
}
|
||||
field(SIMS,DBF_MENU) {
|
||||
prompt("Sim mode Alarm Svrty")
|
||||
promptgroup(GUI_INPUTS)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(IVOA,DBF_MENU) {
|
||||
prompt("INVALID output action")
|
||||
promptgroup(GUI_OUTPUT)
|
||||
interest(2)
|
||||
menu(menuIvoa)
|
||||
}
|
||||
field(IVOV,DBF_INT64) {
|
||||
prompt("INVALID output value")
|
||||
promptgroup(GUI_OUTPUT)
|
||||
interest(2)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user