merged record-updates branch
This commit is contained in:
@@ -15,6 +15,40 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.</p>
|
||||
<h2 align="center">Changes between 3.14.x and 3.15.0.x</h2>
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>Alarm filtering added to input record types</h3>
|
||||
|
||||
<p>The record types ai, calc, longin and mbbi have a new alarm filter added to
|
||||
them. This provides a low-pass filter that can be used to delay the reporting of
|
||||
alarms caused by the input level passing the HIGH, HIHI, LOW or LOLO values. The
|
||||
filter is controlled with a new AFTC field that sets the filter's time constant.
|
||||
The default value for this field is zero, which keeps the record's original
|
||||
alarm behaviour.</p>
|
||||
|
||||
<p>The record must be scanned often enough for the filtering action to work
|
||||
effectively and the alarm severity can only change when the record is processed,
|
||||
but that processing does not have to be regular; the filter uses the time since
|
||||
the record last processed in its calculation. Setting AFTC to a positive number
|
||||
of seconds will delay the record going into or out of a minor alarm severity or
|
||||
from minor to major severity until the input signal has been in that range for
|
||||
that number of seconds.</p>
|
||||
|
||||
<h3>Post events on Waveform record's NORD field</h3>
|
||||
|
||||
<p>When the record type or soft device support modify the NORD field of a
|
||||
waveform record they now also post a DBE_VALUE and DBE_LOG event, signalling the
|
||||
array length change to any clients monitoring the NORD field. Input device
|
||||
support routines should be modified to do this as well.</p>
|
||||
|
||||
<h3>Attributes of Non-VAL Fields</h3>
|
||||
|
||||
<p>Non-VAL fields now report meaningful information for precision, units,
|
||||
graphic limits, control limits, and alarm limits instead of simply using
|
||||
PREC, EGU, HOPR, LOPR, DRVL, DRVH, HIHI, HIGH, LOW, and LOLO. All delay
|
||||
fields have a default precision of 2 digits, units "s" and control limits
|
||||
of 0 to 100,000 seconds (these precision and limit values can be changed
|
||||
for each record type as a whole at runtime by updating a registered global
|
||||
variable). Input fields like A-L of the calc record read their metadata
|
||||
from the corresponding INPn link if possible.</p>
|
||||
<h4>epicsStdioRedirect.h merged into epicsStdio.h</h4>
|
||||
|
||||
<p>The definitions from the header file epicsStdioRedirect.h have been moved
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "alarm.h"
|
||||
#include "dbDefs.h"
|
||||
#include "dbAccess.h"
|
||||
#include "dbEvent.h"
|
||||
#include "recGbl.h"
|
||||
#include "devSup.h"
|
||||
#include "waveformRecord.h"
|
||||
@@ -75,6 +76,7 @@ static long read_wf(waveformRecord *prec)
|
||||
if (prec->tsel.type == CONSTANT &&
|
||||
prec->tse == epicsTimeEventDeviceTime)
|
||||
dbGetTimeStamp(&prec->inp, &prec->time);
|
||||
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -53,14 +53,14 @@ static long special(DBADDR *, int);
|
||||
static long cvt_dbaddr(DBADDR *);
|
||||
static long get_array_info(DBADDR *, long *, long *);
|
||||
static long put_array_info(DBADDR *, long );
|
||||
#define get_units NULL
|
||||
static long get_units(DBADDR *, char *);
|
||||
static long get_precision(DBADDR *, long *);
|
||||
#define get_enum_str NULL
|
||||
#define get_enum_strs NULL
|
||||
#define put_enum_str NULL
|
||||
#define get_graphic_double NULL
|
||||
#define get_control_double NULL
|
||||
#define get_alarm_double 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 aSubRSET = {
|
||||
RSETNUMBER,
|
||||
@@ -330,15 +330,116 @@ static long fetch_values(aSubRecord *prec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_precision(DBADDR *paddr, long *precision)
|
||||
#define indexof(field) aSubRecord##field
|
||||
|
||||
static long get_inlinkNumber(int fieldIndex) {
|
||||
if (fieldIndex >= indexof(A) && fieldIndex <= indexof(U))
|
||||
return fieldIndex - indexof(A);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long get_outlinkNumber(int fieldIndex) {
|
||||
if (fieldIndex >= indexof(VALA) && fieldIndex <= indexof(VALU))
|
||||
return fieldIndex - indexof(VALA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
aSubRecord *prec = (aSubRecord *)paddr->precord;
|
||||
int linkNumber;
|
||||
|
||||
*precision = prec->prec;
|
||||
recGblGetPrec(paddr, precision);
|
||||
linkNumber = get_inlinkNumber(dbGetFieldIndex(paddr));
|
||||
if (linkNumber >= 0) {
|
||||
dbGetUnits(&prec->inpa + linkNumber, units, DB_UNITS_SIZE);
|
||||
return 0;
|
||||
}
|
||||
linkNumber = get_outlinkNumber(dbGetFieldIndex(paddr));
|
||||
if (linkNumber >= 0) {
|
||||
dbGetUnits(&prec->outa + linkNumber, units, DB_UNITS_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_precision(DBADDR *paddr, long *pprecision)
|
||||
{
|
||||
aSubRecord *prec = (aSubRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
short precision;
|
||||
|
||||
*pprecision = prec->prec;
|
||||
linkNumber = get_inlinkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
if (dbGetPrecision(&prec->inpa + linkNumber, &precision) == 0)
|
||||
*pprecision = precision;
|
||||
return 0;
|
||||
}
|
||||
linkNumber = get_outlinkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
if (dbGetPrecision(&prec->outa + linkNumber, &precision) == 0)
|
||||
*pprecision = precision;
|
||||
return 0;
|
||||
}
|
||||
recGblGetPrec(paddr, pprecision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
aSubRecord *prec = (aSubRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
linkNumber = get_inlinkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetGraphicLimits(&prec->inpa + linkNumber,
|
||||
&pgd->lower_disp_limit,
|
||||
&pgd->upper_disp_limit);
|
||||
return 0;
|
||||
}
|
||||
linkNumber = get_outlinkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetGraphicLimits(&prec->outa + linkNumber,
|
||||
&pgd->lower_disp_limit,
|
||||
&pgd->upper_disp_limit);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
{
|
||||
aSubRecord *prec = (aSubRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
linkNumber = get_inlinkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetAlarmLimits(&prec->inpa + linkNumber,
|
||||
&pad->lower_alarm_limit,
|
||||
&pad->lower_warning_limit,
|
||||
&pad->upper_warning_limit,
|
||||
&pad->upper_alarm_limit);
|
||||
return 0;
|
||||
}
|
||||
linkNumber = get_outlinkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetAlarmLimits(&prec->outa + linkNumber,
|
||||
&pad->lower_alarm_limit,
|
||||
&pad->lower_warning_limit,
|
||||
&pad->upper_warning_limit,
|
||||
&pad->upper_alarm_limit);
|
||||
return 0;
|
||||
}
|
||||
recGblGetAlarmDouble(paddr, pad);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void monitor(aSubRecord *prec)
|
||||
{
|
||||
|
||||
@@ -109,7 +109,7 @@ static long init_record(aaiRecord *prec, int pass)
|
||||
recGblRecordError(S_dev_noDSET, prec, "aai: init_record");
|
||||
return S_dev_noDSET;
|
||||
}
|
||||
|
||||
|
||||
if (pass == 0) {
|
||||
if (prec->nelm <= 0)
|
||||
prec->nelm = 1;
|
||||
@@ -120,12 +120,12 @@ static long init_record(aaiRecord *prec, int pass)
|
||||
} else {
|
||||
prec->nord = 0;
|
||||
}
|
||||
|
||||
|
||||
/* we must call pdset->init_record in pass 0
|
||||
because it may set prec->bptr which must
|
||||
not change after links are established before pass 1
|
||||
*/
|
||||
|
||||
|
||||
if (pdset->init_record) {
|
||||
/* init_record may set the bptr to point to the data */
|
||||
if ((status = pdset->init_record(prec)))
|
||||
@@ -141,7 +141,7 @@ static long init_record(aaiRecord *prec, int pass)
|
||||
|
||||
/* 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);
|
||||
recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
|
||||
}
|
||||
|
||||
/* must have read_aai function defined */
|
||||
@@ -210,11 +210,20 @@ static long put_array_info(DBADDR *paddr, long nNew)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define indexof(field) aaiRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
aaiRecord *prec = (aaiRecord *)paddr->precord;
|
||||
|
||||
strncpy(units, prec->egu, DB_UNITS_SIZE);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
|
||||
break;
|
||||
case indexof(HOPR):
|
||||
case indexof(LOPR):
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -223,8 +232,8 @@ static long get_precision(DBADDR *paddr, long *precision)
|
||||
aaiRecord *prec = (aaiRecord *)paddr->precord;
|
||||
|
||||
*precision = prec->prec;
|
||||
if (paddr->pfield == prec->bptr) return 0;
|
||||
recGblGetPrec(paddr, precision);
|
||||
if (dbGetFieldIndex(paddr) != indexof(VAL))
|
||||
recGblGetPrec(paddr, precision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -232,10 +241,18 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
aaiRecord *prec = (aaiRecord *)paddr->precord;
|
||||
|
||||
if (paddr->pfield == prec->bptr) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else recGblGetGraphicDouble(paddr, pgd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(NORD):
|
||||
pgd->upper_disp_limit = prec->nelm;
|
||||
pgd->lower_disp_limit = 0;
|
||||
break;
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr, pgd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -243,10 +260,18 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
aaiRecord *prec = (aaiRecord *)paddr->precord;
|
||||
|
||||
if (paddr->pfield == prec->bptr) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
} else recGblGetControlDouble(paddr, pcd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(NORD):
|
||||
pcd->upper_ctrl_limit = prec->nelm;
|
||||
pcd->lower_ctrl_limit = 0;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr, pcd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ static long init_record(aaoRecord *prec, int pass)
|
||||
recGblRecordError(S_dev_noDSET, prec, "aao: init_record");
|
||||
return S_dev_noDSET;
|
||||
}
|
||||
|
||||
|
||||
if (pass == 0) {
|
||||
if (prec->nelm <= 0)
|
||||
prec->nelm = 1;
|
||||
@@ -120,12 +120,12 @@ static long init_record(aaoRecord *prec, int pass)
|
||||
} else {
|
||||
prec->nord = 0;
|
||||
}
|
||||
|
||||
|
||||
/* we must call pdset->init_record in pass 0
|
||||
because it may set prec->bptr which must
|
||||
not change after links are established before pass 1
|
||||
*/
|
||||
|
||||
|
||||
if (pdset->init_record) {
|
||||
/* init_record may set the bptr to point to the data */
|
||||
if ((status = pdset->init_record(prec)))
|
||||
@@ -138,12 +138,12 @@ static long init_record(aaoRecord *prec, int pass)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
|
||||
}
|
||||
|
||||
|
||||
/* must have write_aao function defined */
|
||||
if (pdset->number < 5 || pdset->write_aao == NULL) {
|
||||
recGblRecordError(S_dev_missingSup, prec, "aao: init_record");
|
||||
@@ -210,11 +210,20 @@ static long put_array_info(DBADDR *paddr, long nNew)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define indexof(field) aaoRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
aaoRecord *prec = (aaoRecord *)paddr->precord;
|
||||
|
||||
strncpy(units, prec->egu, DB_UNITS_SIZE);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
|
||||
break;
|
||||
case indexof(HOPR):
|
||||
case indexof(LOPR):
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -223,8 +232,8 @@ static long get_precision(DBADDR *paddr, long *precision)
|
||||
aaoRecord *prec = (aaoRecord *)paddr->precord;
|
||||
|
||||
*precision = prec->prec;
|
||||
if (paddr->pfield == (void *)prec->bptr) return 0;
|
||||
recGblGetPrec(paddr, precision);
|
||||
if (dbGetFieldIndex(paddr) != indexof(VAL))
|
||||
recGblGetPrec(paddr, precision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -232,10 +241,18 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
aaoRecord *prec = (aaoRecord *)paddr->precord;
|
||||
|
||||
if (paddr->pfield == prec->bptr) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else recGblGetGraphicDouble(paddr,pgd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(NORD):
|
||||
pgd->upper_disp_limit = prec->nelm;
|
||||
pgd->lower_disp_limit = 0;
|
||||
break;
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr, pgd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -243,10 +260,18 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
aaoRecord *prec = (aaoRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield == prec->bptr){
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
} else recGblGetControlDouble(paddr,pcd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(NORD):
|
||||
pcd->upper_ctrl_limit = prec->nelm;
|
||||
pcd->lower_ctrl_limit = 0;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr, pcd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
#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
|
||||
@@ -94,12 +97,7 @@ typedef struct aidset { /* analog input dset */
|
||||
}aidset;
|
||||
|
||||
|
||||
/*Following from timing system */
|
||||
/*
|
||||
extern unsigned int gts_trigger_counter;
|
||||
*/
|
||||
|
||||
static void checkAlarms(aiRecord *prec);
|
||||
static void checkAlarms(aiRecord *prec, epicsTimeStamp *lastTime);
|
||||
static void convert(aiRecord *prec);
|
||||
static void monitor(aiRecord *prec);
|
||||
static long readValue(aiRecord *prec);
|
||||
@@ -158,12 +156,15 @@ static long process(void *precord)
|
||||
aidset *pdset = (aidset *)(prec->dset);
|
||||
long status;
|
||||
unsigned char pact=prec->pact;
|
||||
epicsTimeStamp timeLast;
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_ai==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"read_ai");
|
||||
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);
|
||||
@@ -174,7 +175,7 @@ static long process(void *precord)
|
||||
else if (status==2) status=0;
|
||||
|
||||
/* check for alarms */
|
||||
checkAlarms(prec);
|
||||
checkAlarms(prec,&timeLast);
|
||||
/* check event list */
|
||||
monitor(prec);
|
||||
/* process the forward scan link record */
|
||||
@@ -217,11 +218,22 @@ static long special(DBADDR *paddr,int after)
|
||||
}
|
||||
}
|
||||
|
||||
#define indexof(field) aiRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
aiRecord *prec=(aiRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
if(paddr->pfldDes->field_type == DBF_DOUBLE) {
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(ASLO):
|
||||
case indexof(AOFF):
|
||||
case indexof(SMOO):
|
||||
break;
|
||||
default:
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -230,7 +242,7 @@ static long get_precision(DBADDR *paddr, long *precision)
|
||||
aiRecord *prec=(aiRecord *)paddr->precord;
|
||||
|
||||
*precision = prec->prec;
|
||||
if(paddr->pfield == (void *)&prec->val) return(0);
|
||||
if (dbGetFieldIndex(paddr) == indexof(VAL)) return(0);
|
||||
recGblGetPrec(paddr,precision);
|
||||
return(0);
|
||||
}
|
||||
@@ -238,43 +250,54 @@ static long get_precision(DBADDR *paddr, long *precision)
|
||||
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
|
||||
{
|
||||
aiRecord *prec=(aiRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == aiRecordVAL
|
||||
|| fieldIndex == aiRecordHIHI
|
||||
|| fieldIndex == aiRecordHIGH
|
||||
|| fieldIndex == aiRecordLOW
|
||||
|| fieldIndex == aiRecordLOLO
|
||||
|| fieldIndex == aiRecordHOPR
|
||||
|| fieldIndex == aiRecordLOPR) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else recGblGetGraphicDouble(paddr,pgd);
|
||||
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)
|
||||
{
|
||||
aiRecord *prec=(aiRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == aiRecordVAL
|
||||
|| fieldIndex == aiRecordHIHI
|
||||
|| fieldIndex == aiRecordHIGH
|
||||
|| fieldIndex == aiRecordLOW
|
||||
|| fieldIndex == aiRecordLOLO) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
} else recGblGetControlDouble(paddr,pcd);
|
||||
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)
|
||||
{
|
||||
aiRecord *prec=(aiRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == aiRecordVAL) {
|
||||
if (dbGetFieldIndex(paddr) == indexof(VAL)) {
|
||||
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
|
||||
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
|
||||
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
|
||||
@@ -283,60 +306,114 @@ static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void checkAlarms(aiRecord *prec)
|
||||
static void checkAlarms(aiRecord *prec, epicsTimeStamp *lastTime)
|
||||
{
|
||||
double val, hyst, lalm;
|
||||
double alev;
|
||||
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 val, hyst, lalm, alev, aftc, afvl;
|
||||
epicsEnum16 asev;
|
||||
|
||||
if (prec->udf) {
|
||||
recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM);
|
||||
prec->afvl = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
val = prec->val;
|
||||
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;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
aftc = prec->aftc;
|
||||
afvl = 0;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
if (aftc > 0) {
|
||||
/* Apply level filtering */
|
||||
afvl = prec->afvl;
|
||||
if (afvl == 0) {
|
||||
afvl = (double)alarmRange;
|
||||
} else {
|
||||
double t = epicsTimeDiffInSeconds(&prec->time, lastTime);
|
||||
double alpha = aftc / (t + aftc);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* 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 */
|
||||
|
||||
/* we get here only if val is out of alarm by at least hyst */
|
||||
prec->lalm = val;
|
||||
return;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static void convert(aiRecord *prec)
|
||||
|
||||
@@ -138,6 +138,11 @@ recordtype(ai) {
|
||||
promptgroup(GUI_ALARMS)
|
||||
interest(1)
|
||||
}
|
||||
field(AFTC,DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Time Constant")
|
||||
promptgroup(GUI_ALARMS)
|
||||
interest(1)
|
||||
}
|
||||
field(ADEL,DBF_DOUBLE) {
|
||||
prompt("Archive Deadband")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
@@ -153,6 +158,11 @@ recordtype(ai) {
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(AFVL,DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Value")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(ALST,DBF_DOUBLE) {
|
||||
prompt("Last Value Archived")
|
||||
special(SPC_NOMOD)
|
||||
|
||||
@@ -276,11 +276,21 @@ static long special(DBADDR *paddr, int after)
|
||||
}
|
||||
}
|
||||
|
||||
#define indexof(field) aoRecord##field
|
||||
|
||||
static long get_units(DBADDR * paddr,char *units)
|
||||
{
|
||||
aoRecord *prec=(aoRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
if(paddr->pfldDes->field_type == DBF_DOUBLE) {
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(ASLO):
|
||||
case indexof(AOFF):
|
||||
break;
|
||||
default:
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -289,10 +299,14 @@ static long get_precision(DBADDR *paddr,long *precision)
|
||||
aoRecord *prec=(aoRecord *)paddr->precord;
|
||||
|
||||
*precision = prec->prec;
|
||||
if(paddr->pfield == (void *)&prec->val
|
||||
|| paddr->pfield == (void *)&prec->oval
|
||||
|| paddr->pfield == (void *)&prec->pval) return(0);
|
||||
recGblGetPrec(paddr,precision);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
case indexof(OVAL):
|
||||
case indexof(PVAL):
|
||||
break;
|
||||
default:
|
||||
recGblGetPrec(paddr,precision);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -300,16 +314,24 @@ static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
|
||||
{
|
||||
aoRecord *prec=(aoRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)&prec->val
|
||||
|| paddr->pfield==(void *)&prec->hihi
|
||||
|| paddr->pfield==(void *)&prec->high
|
||||
|| paddr->pfield==(void *)&prec->low
|
||||
|| paddr->pfield==(void *)&prec->lolo
|
||||
|| paddr->pfield==(void *)&prec->oval
|
||||
|| paddr->pfield==(void *)&prec->pval){
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else recGblGetGraphicDouble(paddr,pgd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
case indexof(OVAL):
|
||||
case indexof(PVAL):
|
||||
case indexof(HIHI):
|
||||
case indexof(HIGH):
|
||||
case indexof(LOW):
|
||||
case indexof(LOLO):
|
||||
case indexof(LALM):
|
||||
case indexof(ALST):
|
||||
case indexof(MLST):
|
||||
case indexof(IVOV):
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -317,23 +339,30 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
aoRecord *prec=(aoRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)&prec->val
|
||||
|| paddr->pfield==(void *)&prec->hihi
|
||||
|| paddr->pfield==(void *)&prec->high
|
||||
|| paddr->pfield==(void *)&prec->low
|
||||
|| paddr->pfield==(void *)&prec->lolo
|
||||
|| paddr->pfield==(void *)&prec->oval
|
||||
|| paddr->pfield==(void *)&prec->pval){
|
||||
pcd->upper_ctrl_limit = prec->drvh;
|
||||
pcd->lower_ctrl_limit = prec->drvl;
|
||||
} else recGblGetControlDouble(paddr,pcd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
case indexof(OVAL):
|
||||
case indexof(PVAL):
|
||||
case indexof(HIHI):
|
||||
case indexof(HIGH):
|
||||
case indexof(LOW):
|
||||
case indexof(LOLO):
|
||||
case indexof(LALM):
|
||||
case indexof(ALST):
|
||||
case indexof(MLST):
|
||||
pcd->upper_ctrl_limit = prec->drvh;
|
||||
pcd->lower_ctrl_limit = prec->drvl;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
{
|
||||
aoRecord *prec=(aoRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)&prec->val){
|
||||
if(dbGetFieldIndex(paddr) == indexof(VAL)){
|
||||
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
|
||||
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
|
||||
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
|
||||
|
||||
@@ -51,13 +51,13 @@ static long process(boRecord *);
|
||||
#define cvt_dbaddr NULL
|
||||
#define get_array_info NULL
|
||||
#define put_array_info NULL
|
||||
#define get_units NULL
|
||||
static long get_units(DBADDR *, char *);
|
||||
static long get_precision(DBADDR *, long *);
|
||||
static long get_enum_str(DBADDR *, char *);
|
||||
static long get_enum_strs(DBADDR *, struct dbr_enumStrs *);
|
||||
static long put_enum_str(DBADDR *, char *);
|
||||
#define get_graphic_double NULL
|
||||
#define get_control_double NULL
|
||||
static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
|
||||
#define get_alarm_double NULL
|
||||
|
||||
rset boRSET={
|
||||
@@ -82,6 +82,11 @@ rset boRSET={
|
||||
};
|
||||
epicsExportAddress(rset,boRSET);
|
||||
|
||||
int boHIGHprecision = 2;
|
||||
epicsExportAddress(int, boHIGHprecision);
|
||||
double boHIGHlimit = 100000;
|
||||
epicsExportAddress(double, boHIGHlimit);
|
||||
|
||||
struct bodset { /* binary output dset */
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
@@ -268,12 +273,31 @@ static long process(boRecord *prec)
|
||||
return(status);
|
||||
}
|
||||
|
||||
#define indexof(field) boRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
if(dbGetFieldIndex(paddr) == indexof(HIGH))
|
||||
strcpy(units, "s");
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_precision(DBADDR *paddr, long *precision)
|
||||
{
|
||||
boRecord *prec=(boRecord *)paddr->precord;
|
||||
if(dbGetFieldIndex(paddr) == indexof(HIGH))
|
||||
*precision = boHIGHprecision;
|
||||
else
|
||||
recGblGetPrec(paddr,precision);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(paddr->pfield == (void *)&prec->high) *precision=2;
|
||||
else recGblGetPrec(paddr,precision);
|
||||
static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
if(dbGetFieldIndex(paddr) == indexof(HIGH)) {
|
||||
pcd->lower_ctrl_limit = 0.0;
|
||||
pcd->upper_ctrl_limit = boHIGHlimit;
|
||||
} else
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -285,7 +309,7 @@ static long get_enum_str(DBADDR *paddr, char *pstring)
|
||||
|
||||
|
||||
index = dbGetFieldIndex(paddr);
|
||||
if(index!=boRecordVAL) {
|
||||
if(index!=indexof(VAL)) {
|
||||
strcpy(pstring,"Illegal_Value");
|
||||
} else if(*pfield==0) {
|
||||
strncpy(pstring,prec->znam,sizeof(prec->znam));
|
||||
|
||||
@@ -149,3 +149,6 @@ recordtype(bo) {
|
||||
interest(2)
|
||||
}
|
||||
}
|
||||
|
||||
variable(boHIGHprecision, int)
|
||||
variable(boHIGHlimit, double)
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
#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
|
||||
@@ -54,32 +57,32 @@ static long get_precision(DBADDR *paddr, long *precision);
|
||||
#define get_enum_strs NULL
|
||||
#define put_enum_str NULL
|
||||
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd);
|
||||
static long get_ctrl_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd);
|
||||
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd);
|
||||
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad);
|
||||
|
||||
rset calcRSET={
|
||||
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_ctrl_double,
|
||||
get_alarm_double
|
||||
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, calcRSET);
|
||||
|
||||
static void checkAlarms(calcRecord *prec);
|
||||
static void checkAlarms(calcRecord *prec, epicsTimeStamp *timeLast);
|
||||
static void monitor(calcRecord *prec);
|
||||
static int fetch_values(calcRecord *prec);
|
||||
|
||||
@@ -96,30 +99,35 @@ static long init_record(calcRecord *prec, int pass)
|
||||
plink = &prec->inpa;
|
||||
pvalue = &prec->a;
|
||||
for (i = 0; i < CALCPERFORM_NARGS; i++, plink++, pvalue++) {
|
||||
if (plink->type == CONSTANT) {
|
||||
recGblInitConstantLink(plink, DBF_DOUBLE, pvalue);
|
||||
}
|
||||
if (plink->type == CONSTANT) {
|
||||
recGblInitConstantLink(plink, DBF_DOUBLE, pvalue);
|
||||
}
|
||||
}
|
||||
if (postfix(prec->calc, prec->rpcl, &error_number)) {
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
"calc: init_record: Illegal CALC field");
|
||||
errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->calc);
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
"calc: init_record: Illegal CALC field");
|
||||
errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->calc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long process(calcRecord *prec)
|
||||
{
|
||||
epicsTimeStamp timeLast;
|
||||
|
||||
prec->pact = TRUE;
|
||||
if (fetch_values(prec)==0) {
|
||||
if (calcPerform(&prec->a, &prec->val, prec->rpcl)) {
|
||||
recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM);
|
||||
} else prec->udf = isnan(prec->val);
|
||||
if (fetch_values(prec) == 0) {
|
||||
if (calcPerform(&prec->a, &prec->val, prec->rpcl)) {
|
||||
recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM);
|
||||
} else
|
||||
prec->udf = isnan(prec->val);
|
||||
}
|
||||
|
||||
timeLast = prec->time;
|
||||
recGblGetTimeStamp(prec);
|
||||
/* check for alarms */
|
||||
checkAlarms(prec);
|
||||
checkAlarms(prec, &timeLast);
|
||||
/* check event list */
|
||||
monitor(prec);
|
||||
/* process the forward scan link record */
|
||||
@@ -135,24 +143,41 @@ static long special(DBADDR *paddr, int after)
|
||||
|
||||
if (!after) return 0;
|
||||
if (paddr->special == SPC_CALC) {
|
||||
if (postfix(prec->calc, prec->rpcl, &error_number)) {
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
"calc: Illegal CALC field");
|
||||
errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->calc);
|
||||
return S_db_badField;
|
||||
}
|
||||
return 0;
|
||||
if (postfix(prec->calc, prec->rpcl, &error_number)) {
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
"calc: Illegal CALC field");
|
||||
errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
|
||||
prec->name, calcErrorStr(error_number), prec->calc);
|
||||
return S_db_badField;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
recGblDbaddrError(S_db_badChoice, paddr, "calc::special - bad special value!");
|
||||
return S_db_badChoice;
|
||||
}
|
||||
|
||||
#define indexof(field) calcRecord##field
|
||||
|
||||
static long get_linkNumber(int fieldIndex) {
|
||||
if (fieldIndex >= indexof(A) && fieldIndex <= indexof(L))
|
||||
return fieldIndex - indexof(A);
|
||||
if (fieldIndex >= indexof(LA) && fieldIndex <= indexof(LL))
|
||||
return fieldIndex - indexof(LA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
calcRecord *prec = (calcRecord *)paddr->precord;
|
||||
int linkNumber;
|
||||
|
||||
strncpy(units, prec->egu, DB_UNITS_SIZE);
|
||||
if(paddr->pfldDes->field_type == DBF_DOUBLE) {
|
||||
linkNumber = get_linkNumber(dbGetFieldIndex(paddr));
|
||||
if (linkNumber >= 0)
|
||||
dbGetUnits(&prec->inpa + linkNumber, units, DB_UNITS_SIZE);
|
||||
else
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -160,98 +185,122 @@ static long get_precision(DBADDR *paddr, long *pprecision)
|
||||
{
|
||||
calcRecord *prec = (calcRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
*pprecision = prec->prec;
|
||||
|
||||
if (fieldIndex != calcRecordVAL)
|
||||
recGblGetPrec(paddr, pprecision);
|
||||
|
||||
if (fieldIndex == indexof(VAL)) {
|
||||
return 0;
|
||||
}
|
||||
linkNumber = get_linkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
short precision;
|
||||
if (dbGetPrecision(&prec->inpa + linkNumber, &precision) == 0)
|
||||
*pprecision = precision;
|
||||
else
|
||||
*pprecision = 15;
|
||||
} else
|
||||
recGblGetPrec(paddr, pprecision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
calcRecord *prec = (calcRecord *)paddr->precord;
|
||||
|
||||
if (paddr->pfield == (void *)&prec->val ||
|
||||
paddr->pfield == (void *)&prec->hihi ||
|
||||
paddr->pfield == (void *)&prec->high ||
|
||||
paddr->pfield == (void *)&prec->low ||
|
||||
paddr->pfield == (void *)&prec->lolo) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return 0;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
switch (fieldIndex) {
|
||||
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->lower_disp_limit = prec->lopr;
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
break;
|
||||
default:
|
||||
linkNumber = get_linkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetGraphicLimits(&prec->inpa + linkNumber,
|
||||
&pgd->lower_disp_limit,
|
||||
&pgd->upper_disp_limit);
|
||||
} else
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
}
|
||||
|
||||
if (paddr->pfield >= (void *)&prec->a &&
|
||||
paddr->pfield <= (void *)&prec->l) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return 0;
|
||||
}
|
||||
if (paddr->pfield >= (void *)&prec->la &&
|
||||
paddr->pfield <= (void *)&prec->ll) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return 0;
|
||||
}
|
||||
recGblGetGraphicDouble(paddr, pgd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_ctrl_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
calcRecord *prec = (calcRecord *)paddr->precord;
|
||||
|
||||
if (paddr->pfield == (void *)&prec->val ||
|
||||
paddr->pfield == (void *)&prec->hihi ||
|
||||
paddr->pfield == (void *)&prec->high ||
|
||||
paddr->pfield == (void *)&prec->low ||
|
||||
paddr->pfield == (void *)&prec->lolo) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return 0;
|
||||
|
||||
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):
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
}
|
||||
|
||||
if (paddr->pfield >= (void *)&prec->a &&
|
||||
paddr->pfield <= (void *)&prec->l) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return 0;
|
||||
}
|
||||
if (paddr->pfield >= (void *)&prec->la &&
|
||||
paddr->pfield <= (void *)&prec->ll) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return 0;
|
||||
}
|
||||
recGblGetControlDouble(paddr, pcd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
{
|
||||
calcRecord *prec = (calcRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
if (paddr->pfield == (void *)&prec->val) {
|
||||
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
|
||||
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
|
||||
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
|
||||
if (fieldIndex == indexof(VAL)) {
|
||||
pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN;
|
||||
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
|
||||
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
|
||||
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
|
||||
} else {
|
||||
recGblGetAlarmDouble(paddr, pad);
|
||||
linkNumber = get_linkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetAlarmLimits(&prec->inpa + linkNumber,
|
||||
&pad->lower_alarm_limit,
|
||||
&pad->lower_warning_limit,
|
||||
&pad->upper_warning_limit,
|
||||
&pad->upper_alarm_limit);
|
||||
} else
|
||||
recGblGetAlarmDouble(paddr, pad);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void checkAlarms(calcRecord *prec)
|
||||
static void checkAlarms(calcRecord *prec, epicsTimeStamp *timeLast)
|
||||
{
|
||||
double val, hyst, lalm;
|
||||
double alev;
|
||||
|
||||
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 val, hyst, lalm, alev, aftc, afvl;
|
||||
epicsEnum16 asev;
|
||||
|
||||
if (prec->udf) {
|
||||
recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM);
|
||||
prec->afvl = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -259,45 +308,89 @@ static void checkAlarms(calcRecord *prec)
|
||||
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;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
asev = prec->llsv;
|
||||
alev = prec->lolo;
|
||||
if (asev && (val <= alev || ((lalm == alev) && (val <= alev + hyst)))) {
|
||||
if (recGblSetSevr(prec, LOLO_ALARM, asev))
|
||||
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;
|
||||
return;
|
||||
} else {
|
||||
/* No alarm condition, reset LALM */
|
||||
prec->lalm = val;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static void monitor(calcRecord *prec)
|
||||
@@ -311,34 +404,34 @@ static void monitor(calcRecord *prec)
|
||||
delta = prec->mlst - prec->val;
|
||||
if (delta < 0.0) delta = -delta;
|
||||
if (delta > prec->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
prec->mlst = prec->val;
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
prec->mlst = prec->val;
|
||||
}
|
||||
/* check for archive change */
|
||||
delta = prec->alst - prec->val;
|
||||
if (delta < 0.0) delta = -delta;
|
||||
if (delta > prec->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
/* update last archive value monitored */
|
||||
prec->alst = prec->val;
|
||||
/* post events on value field for archive 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);
|
||||
db_post_events(prec, &prec->val, monitor_mask);
|
||||
}
|
||||
/* check all input fields for changes*/
|
||||
pnew = &prec->a;
|
||||
pprev = &prec->la;
|
||||
for (i = 0; i < CALCPERFORM_NARGS; i++, pnew++, pprev++) {
|
||||
if (*pnew != *pprev ||
|
||||
monitor_mask & DBE_ALARM) {
|
||||
db_post_events(prec, pnew, monitor_mask | DBE_VALUE | DBE_LOG);
|
||||
*pprev = *pnew;
|
||||
}
|
||||
if (*pnew != *pprev ||
|
||||
monitor_mask & DBE_ALARM) {
|
||||
db_post_events(prec, pnew, monitor_mask | DBE_VALUE | DBE_LOG);
|
||||
*pprev = *pnew;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -353,10 +446,10 @@ static int fetch_values(calcRecord *prec)
|
||||
plink = &prec->inpa;
|
||||
pvalue = &prec->a;
|
||||
for(i = 0; i < CALCPERFORM_NARGS; i++, plink++, pvalue++) {
|
||||
int newStatus;
|
||||
int newStatus;
|
||||
|
||||
newStatus = dbGetLink(plink, DBR_DOUBLE, pvalue, 0, 0);
|
||||
if (status == 0) status = newStatus;
|
||||
newStatus = dbGetLink(plink, DBR_DOUBLE, pvalue, 0, 0);
|
||||
if (status == 0) status = newStatus;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,16 @@ recordtype(calc) {
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
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(HYST,DBF_DOUBLE) {
|
||||
prompt("Alarm Deadband")
|
||||
promptgroup(GUI_ALARMS)
|
||||
|
||||
@@ -59,7 +59,7 @@ static long get_precision(DBADDR *, long *);
|
||||
#define get_enum_strs NULL
|
||||
#define put_enum_str NULL
|
||||
static long get_graphic_double(DBADDR *, struct dbr_grDouble *);
|
||||
static long get_ctrl_double(DBADDR *, struct dbr_ctrlDouble *);
|
||||
static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
|
||||
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
|
||||
|
||||
rset calcoutRSET = {
|
||||
@@ -79,11 +79,16 @@ rset calcoutRSET = {
|
||||
get_enum_strs,
|
||||
put_enum_str,
|
||||
get_graphic_double,
|
||||
get_ctrl_double,
|
||||
get_control_double,
|
||||
get_alarm_double
|
||||
};
|
||||
epicsExportAddress(rset, calcoutRSET);
|
||||
|
||||
|
||||
int calcoutODLYprecision = 2;
|
||||
epicsExportAddress(int, calcoutODLYprecision);
|
||||
double calcoutODLYlimit = 100000;
|
||||
epicsExportAddress(double, calcoutODLYlimit);
|
||||
|
||||
typedef struct calcoutDSET {
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
@@ -371,11 +376,34 @@ static long special(DBADDR *paddr, int after)
|
||||
}
|
||||
}
|
||||
|
||||
#define indexof(field) calcoutRecord##field
|
||||
|
||||
static long get_linkNumber(int fieldIndex) {
|
||||
if (fieldIndex >= indexof(A) && fieldIndex <= indexof(L))
|
||||
return fieldIndex - indexof(A);
|
||||
if (fieldIndex >= indexof(LA) && fieldIndex <= indexof(LL))
|
||||
return fieldIndex - indexof(LA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
calcoutRecord *prec = (calcoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
strncpy(units, prec->egu, DB_UNITS_SIZE);
|
||||
if(fieldIndex == indexof(ODLY)) {
|
||||
strcpy(units, "s");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(paddr->pfldDes->field_type == DBF_DOUBLE) {
|
||||
linkNumber = get_linkNumber(dbGetFieldIndex(paddr));
|
||||
if (linkNumber >= 0)
|
||||
dbGetUnits(&prec->inpa + linkNumber, units, DB_UNITS_SIZE);
|
||||
else
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -383,86 +411,109 @@ static long get_precision(DBADDR *paddr, long *pprecision)
|
||||
{
|
||||
calcoutRecord *prec = (calcoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
if(fieldIndex == indexof(ODLY)) {
|
||||
*pprecision = calcoutODLYprecision;
|
||||
return 0;
|
||||
}
|
||||
*pprecision = prec->prec;
|
||||
|
||||
if (fieldIndex != calcoutRecordVAL)
|
||||
if (fieldIndex == indexof(VAL)) {
|
||||
return 0;
|
||||
}
|
||||
linkNumber = get_linkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
short precision;
|
||||
if (dbGetPrecision(&prec->inpa + linkNumber, &precision) == 0)
|
||||
*pprecision = precision;
|
||||
else
|
||||
*pprecision = 15;
|
||||
} else
|
||||
recGblGetPrec(paddr, pprecision);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
calcoutRecord *prec = (calcoutRecord *)paddr->precord;
|
||||
|
||||
if (paddr->pfield == (void *)&prec->val ||
|
||||
paddr->pfield == (void *)&prec->hihi ||
|
||||
paddr->pfield == (void *)&prec->high ||
|
||||
paddr->pfield == (void *)&prec->low ||
|
||||
paddr->pfield == (void *)&prec->lolo) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return 0;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
switch (fieldIndex) {
|
||||
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->lower_disp_limit = prec->lopr;
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
break;
|
||||
case indexof(ODLY):
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
pgd->lower_disp_limit = 0.0;
|
||||
break;
|
||||
default:
|
||||
linkNumber = get_linkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetGraphicLimits(&prec->inpa + linkNumber,
|
||||
&pgd->lower_disp_limit,
|
||||
&pgd->upper_disp_limit);
|
||||
} else
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
}
|
||||
|
||||
if (paddr->pfield >= (void *)&prec->a &&
|
||||
paddr->pfield <= (void *)&prec->l) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return 0;
|
||||
}
|
||||
if (paddr->pfield >= (void *)&prec->la &&
|
||||
paddr->pfield <= (void *)&prec->ll) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return 0;
|
||||
}
|
||||
recGblGetGraphicDouble(paddr, pgd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_ctrl_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
calcoutRecord *prec = (calcoutRecord *)paddr->precord;
|
||||
|
||||
if (paddr->pfield == (void *)&prec->val ||
|
||||
paddr->pfield == (void *)&prec->hihi ||
|
||||
paddr->pfield == (void *)&prec->high ||
|
||||
paddr->pfield == (void *)&prec->low ||
|
||||
paddr->pfield == (void *)&prec->lolo) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return 0;
|
||||
|
||||
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):
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
break;
|
||||
case indexof(ODLY):
|
||||
pcd->lower_ctrl_limit = 0.0;
|
||||
pcd->upper_ctrl_limit = calcoutODLYlimit;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
}
|
||||
|
||||
if (paddr->pfield >= (void *)&prec->a &&
|
||||
paddr->pfield <= (void *)&prec->l) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return 0;
|
||||
}
|
||||
if (paddr->pfield >= (void *)&prec->la &&
|
||||
paddr->pfield <= (void *)&prec->ll) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return 0;
|
||||
}
|
||||
recGblGetControlDouble(paddr, pcd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
{
|
||||
calcoutRecord *prec = (calcoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
if (paddr->pfield == (void *)&prec->val) {
|
||||
if (fieldIndex == indexof(VAL)) {
|
||||
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
|
||||
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
|
||||
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
|
||||
pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN;
|
||||
} else {
|
||||
recGblGetAlarmDouble(paddr, pad);
|
||||
linkNumber = get_linkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetAlarmLimits(&prec->inpa + linkNumber,
|
||||
&pad->lower_alarm_limit,
|
||||
&pad->lower_warning_limit,
|
||||
&pad->upper_warning_limit,
|
||||
&pad->upper_alarm_limit);
|
||||
} else
|
||||
recGblGetAlarmDouble(paddr, pad);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -513,3 +513,6 @@ recordtype(calcout) {
|
||||
extra("char orpc[INFIX_TO_POSTFIX_SIZE(80)]")
|
||||
}
|
||||
}
|
||||
|
||||
variable(calcoutODLYprecision, int)
|
||||
variable(calcoutODLYlimit, double)
|
||||
|
||||
@@ -400,11 +400,16 @@ static long put_array_info(DBADDR *paddr, long nNew)
|
||||
return(0);
|
||||
}
|
||||
|
||||
#define indexof(field) compressRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr,char *units)
|
||||
{
|
||||
compressRecord *prec=(compressRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
if(paddr->pfldDes->field_type == DBF_DOUBLE
|
||||
|| dbGetFieldIndex(paddr) == indexof(VAL)) {
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -413,7 +418,7 @@ static long get_precision(DBADDR *paddr, long *precision)
|
||||
compressRecord *prec=(compressRecord *)paddr->precord;
|
||||
|
||||
*precision = prec->prec;
|
||||
if(paddr->pfield == (void *)prec->bptr) return(0);
|
||||
if(dbGetFieldIndex(paddr) == indexof(BPTR)) return(0);
|
||||
recGblGetPrec(paddr,precision);
|
||||
return(0);
|
||||
}
|
||||
@@ -422,12 +427,16 @@ static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
|
||||
{
|
||||
compressRecord *prec=(compressRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)prec->bptr
|
||||
|| paddr->pfield==(void *)&prec->ihil
|
||||
|| paddr->pfield==(void *)&prec->ilil){
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else recGblGetGraphicDouble(paddr,pgd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(BPTR):
|
||||
case indexof(IHIL):
|
||||
case indexof(ILIL):
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -435,11 +444,15 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
compressRecord *prec=(compressRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)prec->bptr
|
||||
|| paddr->pfield==(void *)&prec->ihil
|
||||
|| paddr->pfield==(void *)&prec->ilil){
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
} else recGblGetControlDouble(paddr,pcd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(BPTR):
|
||||
case indexof(IHIL):
|
||||
case indexof(ILIL):
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -126,73 +126,72 @@ static long process(dfanoutRecord *prec)
|
||||
return(status);
|
||||
}
|
||||
|
||||
#define indexof(field) dfanoutRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr,char *units)
|
||||
{
|
||||
dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
if(paddr->pfldDes->field_type == DBF_DOUBLE) {
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_precision(DBADDR *paddr,long *precision)
|
||||
{
|
||||
dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == dfanoutRecordVAL
|
||||
|| fieldIndex == dfanoutRecordHIHI
|
||||
|| fieldIndex == dfanoutRecordHIGH
|
||||
|| fieldIndex == dfanoutRecordLOW
|
||||
|| fieldIndex == dfanoutRecordLOLO
|
||||
|| fieldIndex == dfanoutRecordHOPR
|
||||
|| fieldIndex == dfanoutRecordLOPR) {
|
||||
*precision = prec->prec;
|
||||
} else {
|
||||
recGblGetPrec(paddr,precision);
|
||||
}
|
||||
*precision = prec->prec;
|
||||
if (dbGetFieldIndex(paddr) == indexof(VAL)) return(0);
|
||||
recGblGetPrec(paddr,precision);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
|
||||
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
|
||||
{
|
||||
dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == dfanoutRecordVAL
|
||||
|| fieldIndex == dfanoutRecordHIHI
|
||||
|| fieldIndex == dfanoutRecordHIGH
|
||||
|| fieldIndex == dfanoutRecordLOW
|
||||
|| fieldIndex == dfanoutRecordLOLO
|
||||
|| fieldIndex == dfanoutRecordHOPR
|
||||
|| fieldIndex == dfanoutRecordLOPR) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else recGblGetGraphicDouble(paddr,pgd);
|
||||
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)
|
||||
{
|
||||
dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == dfanoutRecordVAL
|
||||
|| fieldIndex == dfanoutRecordHIHI
|
||||
|| fieldIndex == dfanoutRecordHIGH
|
||||
|| fieldIndex == dfanoutRecordLOW
|
||||
|| fieldIndex == dfanoutRecordLOLO) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
} else recGblGetControlDouble(paddr,pcd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
case indexof(LALM):
|
||||
case indexof(ALST):
|
||||
case indexof(MLST):
|
||||
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)
|
||||
{
|
||||
dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
|
||||
if(fieldIndex == dfanoutRecordVAL) {
|
||||
if(dbGetFieldIndex(paddr) == indexof(VAL)) {
|
||||
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
|
||||
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
|
||||
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
|
||||
|
||||
@@ -52,7 +52,7 @@ static long special(DBADDR *, int);
|
||||
static long cvt_dbaddr(DBADDR *);
|
||||
static long get_array_info(DBADDR *, long *, long *);
|
||||
#define put_array_info NULL
|
||||
#define get_units NULL
|
||||
static long get_units(DBADDR *, char *);
|
||||
static long get_precision(DBADDR *paddr,long *precision);
|
||||
#define get_enum_str NULL
|
||||
#define get_enum_strs NULL
|
||||
@@ -83,6 +83,9 @@ rset histogramRSET={
|
||||
};
|
||||
epicsExportAddress(rset,histogramRSET);
|
||||
|
||||
int histogramSDELprecision = 2;
|
||||
epicsExportAddress(int, histogramSDELprecision);
|
||||
|
||||
struct histogramdset { /* histogram input dset */
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
@@ -386,42 +389,71 @@ static long readValue(histogramRecord *prec)
|
||||
return(status);
|
||||
}
|
||||
|
||||
#define indexof(field) histogramRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
if (dbGetFieldIndex(paddr) == indexof(SDEL)) {
|
||||
strcpy(units,"s");
|
||||
}
|
||||
/* We should have EGU for other DOUBLE values or probably get it from input link SVL */
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_precision(DBADDR *paddr,long *precision)
|
||||
{
|
||||
histogramRecord *prec=(histogramRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
*precision = prec->prec;
|
||||
if(fieldIndex == histogramRecordULIM
|
||||
|| fieldIndex == histogramRecordLLIM
|
||||
|| fieldIndex == histogramRecordSDEL
|
||||
|| fieldIndex == histogramRecordSGNL
|
||||
|| fieldIndex == histogramRecordSVAL
|
||||
|| fieldIndex == histogramRecordWDTH) {
|
||||
*precision = prec->prec;
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(ULIM):
|
||||
case indexof(LLIM):
|
||||
case indexof(SGNL):
|
||||
case indexof(SVAL):
|
||||
case indexof(WDTH):
|
||||
*precision = prec->prec;
|
||||
break;
|
||||
case indexof(SDEL):
|
||||
*precision = histogramSDELprecision;
|
||||
break;
|
||||
default:
|
||||
recGblGetPrec(paddr,precision);
|
||||
}
|
||||
recGblGetPrec(paddr,precision);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
|
||||
{
|
||||
histogramRecord *prec=(histogramRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == histogramRecordBPTR){
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else recGblGetGraphicDouble(paddr,pgd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(BPTR):
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(WDTH):
|
||||
pgd->upper_disp_limit = prec->ulim-prec->llim;
|
||||
pgd->lower_disp_limit = 0.0;
|
||||
break;
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
histogramRecord *prec=(histogramRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == histogramRecordBPTR){
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
} else recGblGetControlDouble(paddr,pcd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(BPTR):
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(WDTH):
|
||||
pcd->upper_ctrl_limit = prec->ulim-prec->llim;
|
||||
pcd->lower_ctrl_limit = 0.0;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -135,3 +135,5 @@ recordtype(histogram) {
|
||||
interest(1)
|
||||
}
|
||||
}
|
||||
|
||||
variable(histogramSDELprecision, int)
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#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
|
||||
@@ -87,7 +89,7 @@ struct longindset { /* longin input dset */
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_longin; /*returns: (-1,0)=>(failure,success)*/
|
||||
};
|
||||
static void checkAlarms(longinRecord *prec);
|
||||
static void checkAlarms(longinRecord *prec, epicsTimeStamp *timeLast);
|
||||
static void monitor(longinRecord *prec);
|
||||
static long readValue(longinRecord *prec);
|
||||
|
||||
@@ -132,12 +134,14 @@ static long process(longinRecord *prec)
|
||||
struct longindset *pdset = (struct longindset *)(prec->dset);
|
||||
long status;
|
||||
unsigned char pact=prec->pact;
|
||||
epicsTimeStamp timeLast;
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_longin==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"read_longin");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
timeLast = prec->time;
|
||||
|
||||
status=readValue(prec); /* read the new value */
|
||||
/* check if device support set pact */
|
||||
@@ -148,7 +152,7 @@ static long process(longinRecord *prec)
|
||||
if (status==0) prec->udf = FALSE;
|
||||
|
||||
/* check for alarms */
|
||||
checkAlarms(prec);
|
||||
checkAlarms(prec, &timeLast);
|
||||
/* check event list */
|
||||
monitor(prec);
|
||||
/* process the forward scan link record */
|
||||
@@ -158,11 +162,15 @@ static long process(longinRecord *prec)
|
||||
return(status);
|
||||
}
|
||||
|
||||
#define indexof(field) longinRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr,char *units)
|
||||
{
|
||||
longinRecord *prec=(longinRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
if(paddr->pfldDes->field_type == DBF_LONG) {
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -171,14 +179,22 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
longinRecord *prec=(longinRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)&prec->val
|
||||
|| paddr->pfield==(void *)&prec->hihi
|
||||
|| paddr->pfield==(void *)&prec->high
|
||||
|| paddr->pfield==(void *)&prec->low
|
||||
|| paddr->pfield==(void *)&prec->lolo){
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else recGblGetGraphicDouble(paddr,pgd);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -186,14 +202,22 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
longinRecord *prec=(longinRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)&prec->val
|
||||
|| paddr->pfield==(void *)&prec->hihi
|
||||
|| paddr->pfield==(void *)&prec->high
|
||||
|| paddr->pfield==(void *)&prec->low
|
||||
|| paddr->pfield==(void *)&prec->lolo){
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
} else recGblGetControlDouble(paddr,pcd);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -201,7 +225,7 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
{
|
||||
longinRecord *prec=(longinRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)&prec->val){
|
||||
if(dbGetFieldIndex(paddr) == indexof(VAL)){
|
||||
pad->upper_alarm_limit = prec->hihi;
|
||||
pad->upper_warning_limit = prec->high;
|
||||
pad->lower_warning_limit = prec->low;
|
||||
@@ -210,14 +234,28 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void checkAlarms(longinRecord *prec)
|
||||
static void checkAlarms(longinRecord *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;
|
||||
epicsInt32 val, hyst, lalm;
|
||||
epicsInt32 alev;
|
||||
epicsEnum16 asev;
|
||||
|
||||
if (prec->udf) {
|
||||
recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM);
|
||||
prec->afvl = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -225,45 +263,88 @@ static void checkAlarms(longinRecord *prec)
|
||||
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;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
aftc = prec->aftc;
|
||||
afvl = 0;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* 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 */
|
||||
|
||||
/* we get here only if val is out of alarm by at least hyst */
|
||||
prec->lalm = val;
|
||||
return;
|
||||
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
|
||||
|
||||
@@ -93,6 +93,16 @@ recordtype(longin) {
|
||||
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_LONG) {
|
||||
prompt("Archive Deadband")
|
||||
promptgroup(GUI_DISPLAY)
|
||||
|
||||
@@ -190,58 +190,73 @@ static long process(longoutRecord *prec)
|
||||
return(status);
|
||||
}
|
||||
|
||||
#define indexof(field) longoutRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr,char *units)
|
||||
{
|
||||
longoutRecord *prec=(longoutRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
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)
|
||||
{
|
||||
longoutRecord *prec=(longoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == longoutRecordVAL
|
||||
|| fieldIndex == longoutRecordHIHI
|
||||
|| fieldIndex == longoutRecordHIGH
|
||||
|| fieldIndex == longoutRecordLOW
|
||||
|| fieldIndex == longoutRecordLOLO) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else recGblGetGraphicDouble(paddr,pgd);
|
||||
|
||||
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)
|
||||
{
|
||||
longoutRecord *prec=(longoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == longoutRecordVAL
|
||||
|| fieldIndex == longoutRecordHIHI
|
||||
|| fieldIndex == longoutRecordHIGH
|
||||
|| fieldIndex == longoutRecordLOW
|
||||
|| fieldIndex == longoutRecordLOLO) {
|
||||
/* 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;
|
||||
}
|
||||
} else recGblGetControlDouble(paddr,pcd);
|
||||
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)
|
||||
{
|
||||
longoutRecord *prec=(longoutRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(fieldIndex == longoutRecordVAL) {
|
||||
if(dbGetFieldIndex(paddr) == indexof(VAL)) {
|
||||
pad->upper_alarm_limit = prec->hihi;
|
||||
pad->upper_warning_limit = prec->high;
|
||||
pad->lower_warning_limit = prec->low;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie.
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* 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.
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "dbEvent.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "devSup.h"
|
||||
#include "epicsMath.h"
|
||||
#include "errMdef.h"
|
||||
#include "menuSimm.h"
|
||||
#include "recSup.h"
|
||||
@@ -36,6 +37,10 @@
|
||||
#include "mbbiRecord.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
|
||||
@@ -54,56 +59,56 @@ static long put_enum_str(DBADDR *, char *);
|
||||
#define get_graphic_double NULL
|
||||
#define get_control_double NULL
|
||||
#define get_alarm_double NULL
|
||||
rset mbbiRSET={
|
||||
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
|
||||
|
||||
rset mbbiRSET = {
|
||||
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,mbbiRSET);
|
||||
|
||||
struct mbbidset { /* multi bit binary input dset */
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_mbbi;/*(0,2)=>(success, success no convert)*/
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /* returns: (-1,0) => (failure, success)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_mbbi;/* (0, 2) => (success, success no convert)*/
|
||||
};
|
||||
static void checkAlarms(mbbiRecord *);
|
||||
|
||||
static void checkAlarms(mbbiRecord *, epicsTimeStamp *);
|
||||
static void monitor(mbbiRecord *);
|
||||
static long readValue(mbbiRecord *);
|
||||
|
||||
static void init_common(mbbiRecord *prec)
|
||||
{
|
||||
epicsUInt32 *pstate_values;
|
||||
char *pstate_string;
|
||||
short i;
|
||||
epicsUInt32 *pstate_values = &prec->zrvl;
|
||||
char *pstate_string = prec->zrst;
|
||||
int i;
|
||||
|
||||
/* determine if any states are defined */
|
||||
pstate_values = &(prec->zrvl); pstate_string = prec->zrst;
|
||||
prec->sdef = FALSE;
|
||||
for (i=0; i<16; i++, pstate_string += sizeof(prec->zrst)) {
|
||||
if((*(pstate_values+i) != 0) || (*pstate_string !='\0')) {
|
||||
prec->sdef = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
/* Check if any states are defined */
|
||||
for (i = 0; i < 16; i++, pstate_string += sizeof(prec->zrst)) {
|
||||
if ((pstate_values[i] != 0) || (*pstate_string != '\0')) {
|
||||
prec->sdef = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
prec->sdef = FALSE;
|
||||
}
|
||||
|
||||
static long init_record(mbbiRecord *prec, int pass)
|
||||
@@ -111,258 +116,312 @@ static long init_record(mbbiRecord *prec, int pass)
|
||||
struct mbbidset *pdset;
|
||||
long status;
|
||||
|
||||
if (pass==0) return(0);
|
||||
if (pass == 0)
|
||||
return 0;
|
||||
|
||||
if (prec->siml.type == CONSTANT) {
|
||||
recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
|
||||
recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
|
||||
}
|
||||
if (prec->siol.type == CONSTANT) {
|
||||
recGblInitConstantLink(&prec->siol,DBF_USHORT,&prec->sval);
|
||||
recGblInitConstantLink(&prec->siol, DBF_USHORT, &prec->sval);
|
||||
}
|
||||
if(!(pdset = (struct mbbidset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"mbbi: init_record");
|
||||
return(S_dev_noDSET);
|
||||
|
||||
pdset = (struct mbbidset *) prec->dset;
|
||||
if (!pdset) {
|
||||
recGblRecordError(S_dev_noDSET, prec, "mbbi: init_record");
|
||||
return S_dev_noDSET;
|
||||
}
|
||||
/* must have read_mbbi function defined */
|
||||
if( (pdset->number < 5) || (pdset->read_mbbi == NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"mbbi: init_record");
|
||||
return(S_dev_missingSup);
|
||||
if ((pdset->number < 5) || (pdset->read_mbbi == NULL)) {
|
||||
recGblRecordError(S_dev_missingSup, prec, "mbbi: init_record");
|
||||
return S_dev_missingSup;
|
||||
}
|
||||
/* initialize mask*/
|
||||
prec->mask = (1 << prec->nobt) - 1;
|
||||
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(prec))) return(status);
|
||||
/* initialize mask if the user didn't */
|
||||
if (prec->mask == 0)
|
||||
prec->mask = (1 << prec->nobt) - 1;
|
||||
|
||||
if (pdset->init_record) {
|
||||
status = pdset->init_record(prec);
|
||||
}
|
||||
else
|
||||
status = 0;
|
||||
|
||||
init_common(prec);
|
||||
prec->mlst = prec->val;
|
||||
prec->lalm = prec->val;
|
||||
prec->oraw = prec->rval;
|
||||
return(0);
|
||||
return status;
|
||||
}
|
||||
|
||||
static long process(mbbiRecord *prec)
|
||||
{
|
||||
struct mbbidset *pdset = (struct mbbidset *)(prec->dset);
|
||||
long status;
|
||||
unsigned char pact=prec->pact;
|
||||
struct mbbidset *pdset = (struct mbbidset *) prec->dset;
|
||||
long status;
|
||||
int pact = prec->pact;
|
||||
epicsTimeStamp timeLast;
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_mbbi==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"read_mbbi");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if ((pdset == NULL) || (pdset->read_mbbi == NULL)) {
|
||||
prec->pact = TRUE;
|
||||
recGblRecordError(S_dev_missingSup, prec, "read_mbbi");
|
||||
return S_dev_missingSup;
|
||||
}
|
||||
|
||||
status=readValue(prec); /* read the new value */
|
||||
/* check if device support set pact */
|
||||
if ( !pact && prec->pact ) return(0);
|
||||
prec->pact = TRUE;
|
||||
timeLast = prec->time;
|
||||
|
||||
recGblGetTimeStamp(prec);
|
||||
if(status==0) { /* convert the value */
|
||||
epicsUInt32 *pstate_values;
|
||||
short i;
|
||||
epicsUInt32 rval = prec->rval;
|
||||
status = readValue(prec); /* read the new value */
|
||||
/* check if device support set pact */
|
||||
if (!pact && prec->pact)
|
||||
return 0;
|
||||
prec->pact = TRUE;
|
||||
|
||||
prec->udf = FALSE;
|
||||
if(prec->shft>0) rval >>= prec->shft;
|
||||
if (prec->sdef){
|
||||
pstate_values = &(prec->zrvl);
|
||||
prec->val = 65535; /* initalize to unknown state*/
|
||||
for (i = 0; i < 16; i++){
|
||||
if (*pstate_values == rval){
|
||||
prec->val = i;
|
||||
break;
|
||||
}
|
||||
pstate_values++;
|
||||
}
|
||||
}else{
|
||||
/* the raw value is the desired value */
|
||||
prec->val = (unsigned short)rval;
|
||||
}
|
||||
}
|
||||
else if(status == 2) status = 0;
|
||||
recGblGetTimeStamp(prec);
|
||||
if (status == 0) { /* convert the value */
|
||||
epicsUInt32 *pstate_values;
|
||||
short i;
|
||||
epicsUInt32 rval = prec->rval;
|
||||
|
||||
/* check for alarms */
|
||||
checkAlarms(prec);
|
||||
prec->udf = FALSE;
|
||||
if (prec->shft > 0)
|
||||
rval >>= prec->shft;
|
||||
if (prec->sdef) {
|
||||
pstate_values = &(prec->zrvl);
|
||||
prec->val = 65535; /* initalize to unknown state*/
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (*pstate_values == rval) {
|
||||
prec->val = i;
|
||||
break;
|
||||
}
|
||||
pstate_values++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* the raw value is the desired value */
|
||||
prec->val = rval;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (status == 2) {
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* check event list */
|
||||
monitor(prec);
|
||||
/* check for alarms */
|
||||
checkAlarms(prec, &timeLast);
|
||||
|
||||
/* process the forward scan link record */
|
||||
recGblFwdLink(prec);
|
||||
/* check event list */
|
||||
monitor(prec);
|
||||
|
||||
prec->pact=FALSE;
|
||||
return(status);
|
||||
/* process the forward scan link record */
|
||||
recGblFwdLink(prec);
|
||||
|
||||
prec->pact=FALSE;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static long special(DBADDR *paddr,int after)
|
||||
static long special(DBADDR *paddr, int after)
|
||||
{
|
||||
mbbiRecord *prec = (mbbiRecord *)(paddr->precord);
|
||||
int special_type = paddr->special;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
mbbiRecord *prec = (mbbiRecord *) paddr->precord;
|
||||
int special_type = paddr->special;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(!after) return(0);
|
||||
switch(special_type) {
|
||||
case(SPC_MOD):
|
||||
init_common(prec);
|
||||
if (fieldIndex >= mbbiRecordZRST && fieldIndex <= mbbiRecordFFST)
|
||||
db_post_events(prec,&prec->val,DBE_PROPERTY);
|
||||
return(0);
|
||||
if (!after) return 0;
|
||||
switch (special_type) {
|
||||
case SPC_MOD:
|
||||
init_common(prec);
|
||||
if (fieldIndex >= mbbiRecordZRST && fieldIndex <= mbbiRecordFFST) {
|
||||
int event = DBE_PROPERTY;
|
||||
|
||||
if (prec->val == fieldIndex - mbbiRecordZRST)
|
||||
event |= DBE_VALUE | DBE_LOG;
|
||||
db_post_events(prec, &prec->val, event);
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
recGblDbaddrError(S_db_badChoice,paddr,"mbbi: special");
|
||||
return(S_db_badChoice);
|
||||
recGblDbaddrError(S_db_badChoice, paddr, "mbbi: special");
|
||||
return S_db_badChoice;
|
||||
}
|
||||
}
|
||||
|
||||
static long get_enum_str(DBADDR *paddr,char* pstring)
|
||||
static long get_enum_str(DBADDR *paddr, char *pstring)
|
||||
{
|
||||
mbbiRecord *prec=(mbbiRecord *)paddr->precord;
|
||||
char *psource;
|
||||
int index;
|
||||
unsigned short *pfield = (unsigned short *)paddr->pfield;
|
||||
unsigned short val=*pfield;
|
||||
mbbiRecord *prec = (mbbiRecord *) paddr->precord;
|
||||
int index;
|
||||
unsigned short *pfield = paddr->pfield;
|
||||
epicsEnum16 val = *pfield;
|
||||
|
||||
index = dbGetFieldIndex(paddr);
|
||||
if(index!=mbbiRecordVAL) {
|
||||
strcpy(pstring,"Illegal_Value");
|
||||
} else if(val<= 15) {
|
||||
psource = (prec->zrst);
|
||||
psource += (val * sizeof(prec->zrst));
|
||||
strncpy(pstring,psource,sizeof(prec->zrst));
|
||||
} else {
|
||||
strcpy(pstring,"Illegal Value");
|
||||
if (index != mbbiRecordVAL) {
|
||||
strcpy(pstring, "Illegal_Value");
|
||||
}
|
||||
return(0);
|
||||
else if (val <= 15) {
|
||||
char *pstate = prec->zrst + val * sizeof(prec->zrst);
|
||||
|
||||
strncpy(pstring, pstate, sizeof(prec->zrst));
|
||||
}
|
||||
else {
|
||||
strcpy(pstring, "Illegal Value");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_enum_strs(DBADDR *paddr, struct dbr_enumStrs *pes)
|
||||
{
|
||||
mbbiRecord *prec=(mbbiRecord *)paddr->precord;
|
||||
char *psource;
|
||||
int i;
|
||||
short no_str;
|
||||
mbbiRecord *prec = (mbbiRecord *) paddr->precord;
|
||||
char *pstate = prec->zrst;
|
||||
int i;
|
||||
short states = 0;
|
||||
|
||||
no_str = 0;
|
||||
memset(pes->strs,'\0',sizeof(pes->strs));
|
||||
for(i=0,psource=(prec->zrst); i<16; i++, psource += sizeof(prec->zrst) ) {
|
||||
strncpy(pes->strs[i],psource,sizeof(prec->zrst));
|
||||
if(*psource!=0) no_str=i+1;
|
||||
memset(pes->strs, '\0', sizeof(pes->strs));
|
||||
for (i = 0; i < 16; i++, pstate += sizeof(prec->zrst) ) {
|
||||
strncpy(pes->strs[i], pstate, sizeof(prec->zrst));
|
||||
if (*pstate!=0) states = i+1;
|
||||
}
|
||||
pes->no_str=no_str;
|
||||
return(0);
|
||||
pes->no_str = states;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long put_enum_str(DBADDR *paddr, char *pstring)
|
||||
{
|
||||
mbbiRecord *prec=(mbbiRecord *)paddr->precord;
|
||||
char *pstate_name;
|
||||
short i;
|
||||
mbbiRecord *prec = (mbbiRecord *) paddr->precord;
|
||||
char *pstate;
|
||||
short i;
|
||||
|
||||
if (prec->sdef){
|
||||
pstate_name = prec->zrst;
|
||||
for (i = 0; i < 16; i++){
|
||||
if(strncmp(pstate_name,pstring,sizeof(prec->zrst))==0){
|
||||
prec->val = i;
|
||||
prec->udf = FALSE;
|
||||
return(0);
|
||||
}
|
||||
pstate_name += sizeof(prec->zrst);
|
||||
}
|
||||
if (prec->sdef) {
|
||||
pstate = prec->zrst;
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (strncmp(pstate, pstring, sizeof(prec->zrst)) == 0) {
|
||||
prec->val = i;
|
||||
prec->udf = FALSE;
|
||||
return 0;
|
||||
}
|
||||
pstate += sizeof(prec->zrst);
|
||||
}
|
||||
return(S_db_badChoice);
|
||||
}
|
||||
return S_db_badChoice;
|
||||
}
|
||||
|
||||
static void checkAlarms(mbbiRecord *prec)
|
||||
static void checkAlarms(mbbiRecord *prec, epicsTimeStamp *timeLast)
|
||||
{
|
||||
unsigned short *severities;
|
||||
unsigned short val=prec->val;
|
||||
double aftc, afvl;
|
||||
unsigned short alarm;
|
||||
epicsEnum16 asev;
|
||||
epicsEnum16 val = prec->val;
|
||||
|
||||
/* check for udf alarm */
|
||||
if(prec->udf == TRUE ){
|
||||
recGblSetSevr(prec,UDF_ALARM,INVALID_ALARM);
|
||||
/* check for udf alarm */
|
||||
if (prec->udf) {
|
||||
recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM);
|
||||
prec->afvl = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* check for state alarm */
|
||||
if (val > 15) {
|
||||
/* Unknown state */
|
||||
alarm = prec->unsv;
|
||||
}
|
||||
else {
|
||||
/* State has a severity field */
|
||||
epicsEnum16 *severities = &prec->zrsv;
|
||||
|
||||
alarm = severities[prec->val];
|
||||
}
|
||||
|
||||
aftc = prec->aftc;
|
||||
afvl = 0;
|
||||
|
||||
if (aftc > 0) {
|
||||
afvl = prec->afvl;
|
||||
if (afvl == 0) {
|
||||
afvl = (double) alarm;
|
||||
}
|
||||
else {
|
||||
double t = epicsTimeDiffInSeconds(&prec->time, timeLast);
|
||||
double alpha = aftc / (t + aftc);
|
||||
|
||||
/* check for state alarm */
|
||||
/* unknown state */
|
||||
if (val > 15){
|
||||
recGblSetSevr(prec,STATE_ALARM,prec->unsv);
|
||||
} else {
|
||||
/* in a state which is an error */
|
||||
severities = (unsigned short *)&(prec->zrsv);
|
||||
recGblSetSevr(prec,STATE_ALARM,severities[prec->val]);
|
||||
}
|
||||
afvl = alpha * afvl +
|
||||
((afvl > 0) ? (1.0 - alpha) : (alpha - 1.0)) * alarm;
|
||||
if (afvl - floor(afvl) > THRESHOLD)
|
||||
afvl = -afvl;
|
||||
|
||||
/* check for cos alarm */
|
||||
if(val == prec->lalm) return;
|
||||
recGblSetSevr(prec,COS_ALARM,prec->cosv);
|
||||
prec->lalm = val;
|
||||
return;
|
||||
alarm = abs((int)floor(afvl));
|
||||
}
|
||||
}
|
||||
|
||||
asev = alarm;
|
||||
recGblSetSevr(prec, STATE_ALARM, asev);
|
||||
|
||||
/* check for cos alarm */
|
||||
if (val == prec->lalm)
|
||||
return;
|
||||
|
||||
recGblSetSevr(prec, COS_ALARM, prec->cosv);
|
||||
prec->lalm = val;
|
||||
}
|
||||
|
||||
static void monitor(mbbiRecord *prec)
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
unsigned short monitor_mask;
|
||||
|
||||
monitor_mask = recGblResetAlarms(prec);
|
||||
/* check for value change */
|
||||
if (prec->mlst != prec->val){
|
||||
/* post events for value change and archive change */
|
||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||
/* update last value monitored */
|
||||
prec->mlst = prec->val;
|
||||
}
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(prec,&prec->val,monitor_mask);
|
||||
}
|
||||
if(prec->oraw!=prec->rval) {
|
||||
db_post_events(prec,&prec->rval,monitor_mask|DBE_VALUE);
|
||||
prec->oraw = prec->rval;
|
||||
}
|
||||
return;
|
||||
monitor_mask = recGblResetAlarms(prec);
|
||||
/* check for value change */
|
||||
if (prec->mlst != prec->val) {
|
||||
/* post events for value change and archive change */
|
||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||
/* update last value monitored */
|
||||
prec->mlst = prec->val;
|
||||
}
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask) {
|
||||
db_post_events(prec, &prec->val, monitor_mask);
|
||||
}
|
||||
if (prec->oraw != prec->rval) {
|
||||
db_post_events(prec, &prec->rval, monitor_mask | DBE_VALUE);
|
||||
prec->oraw = prec->rval;
|
||||
}
|
||||
}
|
||||
|
||||
static long readValue(mbbiRecord *prec)
|
||||
{
|
||||
long status;
|
||||
struct mbbidset *pdset = (struct mbbidset *) (prec->dset);
|
||||
struct mbbidset *pdset = (struct mbbidset *) prec->dset;
|
||||
long status;
|
||||
|
||||
if (prec->pact == TRUE){
|
||||
status=(*pdset->read_mbbi)(prec);
|
||||
return(status);
|
||||
}
|
||||
if (prec->pact) {
|
||||
status = pdset->read_mbbi(prec);
|
||||
return status;
|
||||
}
|
||||
|
||||
status=dbGetLink(&(prec->siml),DBR_USHORT,&(prec->simm),0,0);
|
||||
if (status)
|
||||
return(status);
|
||||
status = dbGetLink(&prec->siml, DBR_USHORT, &prec->simm, 0, 0);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (prec->simm == menuSimmNO){
|
||||
status=(*pdset->read_mbbi)(prec);
|
||||
return(status);
|
||||
}
|
||||
if (prec->simm == menuSimmYES){
|
||||
status=dbGetLink(&(prec->siol),DBR_ULONG,&(prec->sval),0,0);
|
||||
if (status==0){
|
||||
prec->val=(unsigned short)prec->sval;
|
||||
prec->udf=FALSE;
|
||||
}
|
||||
status=2; /* dont convert */
|
||||
}
|
||||
else if (prec->simm == menuSimmRAW){
|
||||
status=dbGetLink(&(prec->siol),DBR_ULONG,&(prec->sval),0,0);
|
||||
if (status==0){
|
||||
prec->rval=prec->sval;
|
||||
prec->udf=FALSE;
|
||||
}
|
||||
status=0; /* convert since we've written RVAL */
|
||||
} else {
|
||||
status=-1;
|
||||
recGblSetSevr(prec,SOFT_ALARM,INVALID_ALARM);
|
||||
return(status);
|
||||
}
|
||||
recGblSetSevr(prec,SIMM_ALARM,prec->sims);
|
||||
if (prec->simm == menuSimmNO) {
|
||||
status = pdset->read_mbbi(prec);
|
||||
return status;
|
||||
}
|
||||
if (prec->simm == menuSimmYES) {
|
||||
status=dbGetLink(&prec->siol, DBR_ULONG, &prec->sval, 0, 0);
|
||||
if (status == 0) {
|
||||
prec->val = prec->sval;
|
||||
prec->udf = FALSE;
|
||||
}
|
||||
status = 2; /* dont convert */
|
||||
}
|
||||
else if (prec->simm == menuSimmRAW) {
|
||||
status = dbGetLink(&prec->siol, DBR_ULONG, &prec->sval, 0, 0);
|
||||
if (status == 0) {
|
||||
prec->rval = prec->sval;
|
||||
prec->udf = FALSE;
|
||||
}
|
||||
status = 0; /* convert since we've written RVAL */
|
||||
}
|
||||
else {
|
||||
status = -1;
|
||||
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
|
||||
return status;
|
||||
}
|
||||
recGblSetSevr(prec, SIMM_ALARM, prec->sims);
|
||||
|
||||
return(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -394,6 +394,16 @@ recordtype(mbbi) {
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
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(UNSV,DBF_MENU) {
|
||||
prompt("Unknown State Severity")
|
||||
promptgroup(GUI_MBB)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie.
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* 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.
|
||||
@@ -60,35 +60,35 @@ static long put_enum_str(DBADDR *, char *);
|
||||
#define get_control_double NULL
|
||||
#define get_alarm_double NULL
|
||||
|
||||
rset mbboRSET={
|
||||
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
|
||||
rset mbboRSET = {
|
||||
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,mbboRSET);
|
||||
|
||||
struct mbbodset { /* multi bit binary output dset */
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /*returns: (0,2)=>(success,success no convert)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN write_mbbo; /*returns: (0,2)=>(success,success no convert)*/
|
||||
long number;
|
||||
DEVSUPFUN dev_report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /*returns: (0, 2) => (success, success no convert)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN write_mbbo; /*returns: (0, 2) => (success, success no convert)*/
|
||||
};
|
||||
|
||||
|
||||
@@ -100,360 +100,370 @@ static long writeValue(mbboRecord *);
|
||||
|
||||
static void init_common(mbboRecord *prec)
|
||||
{
|
||||
epicsUInt32 *pstate_values;
|
||||
char *pstate_string;
|
||||
short i;
|
||||
epicsUInt32 *pstate_values = &prec->zrvl;
|
||||
char *pstate_string = prec->zrst;
|
||||
int i;
|
||||
|
||||
/* determine if any states are defined */
|
||||
pstate_values = &(prec->zrvl); pstate_string = prec->zrst;
|
||||
prec->sdef = FALSE;
|
||||
for (i=0; i<16; i++, pstate_string += sizeof(prec->zrst)) {
|
||||
if((*(pstate_values+i)!= 0) || (*pstate_string !='\0')) {
|
||||
prec->sdef = TRUE;
|
||||
return;
|
||||
}
|
||||
/* Check if any states are defined */
|
||||
for (i = 0; i < 16; i++, pstate_string += sizeof(prec->zrst)) {
|
||||
if ((pstate_values[i] != 0) || (*pstate_string != '\0')) {
|
||||
prec->sdef = TRUE;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
prec->sdef = FALSE;
|
||||
}
|
||||
|
||||
static long init_record(mbboRecord *prec, int pass)
|
||||
{
|
||||
struct mbbodset *pdset;
|
||||
long status;
|
||||
int i;
|
||||
|
||||
if (pass==0) {
|
||||
if (pass == 0) {
|
||||
init_common(prec);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mbbo.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);
|
||||
recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
|
||||
}
|
||||
|
||||
if(!(pdset = (struct mbbodset *)(prec->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,(void *)prec,"mbbo: init_record");
|
||||
return(S_dev_noDSET);
|
||||
pdset = (struct mbbodset *) prec->dset;
|
||||
if (!pdset) {
|
||||
recGblRecordError(S_dev_noDSET, prec, "mbbo: init_record");
|
||||
return S_dev_noDSET;
|
||||
}
|
||||
/* must have write_mbbo function defined */
|
||||
if( (pdset->number < 5) || (pdset->write_mbbo == NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"mbbo: init_record");
|
||||
return(S_dev_missingSup);
|
||||
if ((pdset->number < 5) || (pdset->write_mbbo == NULL)) {
|
||||
recGblRecordError(S_dev_missingSup, prec, "mbbo: init_record");
|
||||
return S_dev_missingSup;
|
||||
}
|
||||
if (prec->dol.type == CONSTANT){
|
||||
if(recGblInitConstantLink(&prec->dol,DBF_USHORT,&prec->val))
|
||||
prec->udf = FALSE;
|
||||
if (prec->dol.type == CONSTANT) {
|
||||
if (recGblInitConstantLink(&prec->dol, DBF_USHORT, &prec->val))
|
||||
prec->udf = FALSE;
|
||||
}
|
||||
|
||||
/* initialize mask*/
|
||||
prec->mask = 0;
|
||||
for (i=0; i<prec->nobt; i++) {
|
||||
prec->mask <<= 1; /* shift left 1 bit*/
|
||||
prec->mask |= 1; /* set low order bit*/
|
||||
}
|
||||
if( pdset->init_record ) {
|
||||
epicsUInt32 rval;
|
||||
/* initialize mask if the user didn't */
|
||||
if (prec->mask == 0)
|
||||
prec->mask = (1 << prec->nobt) - 1;
|
||||
|
||||
status=(*pdset->init_record)(prec);
|
||||
/* init_record might set status */
|
||||
init_common(prec);
|
||||
if(status==0){
|
||||
rval = prec->rval;
|
||||
if(prec->shft>0) rval >>= prec->shft;
|
||||
if (prec->sdef){
|
||||
epicsUInt32 *pstate_values;
|
||||
short i;
|
||||
if (pdset->init_record) {
|
||||
status = pdset->init_record(prec);
|
||||
init_common(prec);
|
||||
if (status == 0) {
|
||||
/* convert initial read-back */
|
||||
epicsUInt32 rval = prec->rval;
|
||||
|
||||
pstate_values = &(prec->zrvl);
|
||||
prec->val = 65535; /* initalize to unknown state*/
|
||||
for (i = 0; i < 16; i++){
|
||||
if (*pstate_values == rval){
|
||||
prec->val = i;
|
||||
break;
|
||||
}
|
||||
pstate_values++;
|
||||
}
|
||||
}else{
|
||||
/* the raw is the desired val */
|
||||
prec->val = (unsigned short)rval;
|
||||
}
|
||||
prec->udf = FALSE;
|
||||
} else if (status==2) status=0;
|
||||
if (prec->shft > 0)
|
||||
rval >>= prec->shft;
|
||||
|
||||
if (prec->sdef) {
|
||||
epicsUInt32 *pstate_values = &prec->zrvl;
|
||||
int i;
|
||||
|
||||
prec->val = 65535; /* initalize to unknown state */
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (*pstate_values == rval) {
|
||||
prec->val = i;
|
||||
break;
|
||||
}
|
||||
pstate_values++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* No defined states, punt */
|
||||
prec->val = rval;
|
||||
}
|
||||
prec->udf = FALSE;
|
||||
}
|
||||
else if (status == 2)
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
init_common(prec);
|
||||
status = 0;
|
||||
}
|
||||
init_common(prec);
|
||||
/* convert val to rval */
|
||||
convert(prec);
|
||||
prec->mlst = prec->val;
|
||||
prec->lalm = prec->val;
|
||||
prec->oraw = prec->rval;
|
||||
prec->orbv = prec->rbv;
|
||||
return(0);
|
||||
return status;
|
||||
}
|
||||
|
||||
static long process(mbboRecord *prec)
|
||||
{
|
||||
struct mbbodset *pdset = (struct mbbodset *)(prec->dset);
|
||||
long status=0;
|
||||
unsigned char pact=prec->pact;
|
||||
struct mbbodset *pdset = (struct mbbodset *) prec->dset;
|
||||
long status = 0;
|
||||
int pact = prec->pact;
|
||||
|
||||
if( (pdset==NULL) || (pdset->write_mbbo==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,(void *)prec,"write_mbbo");
|
||||
return(S_dev_missingSup);
|
||||
if ((pdset == NULL) || (pdset->write_mbbo == NULL)) {
|
||||
prec->pact = TRUE;
|
||||
recGblRecordError(S_dev_missingSup, prec, "write_mbbo");
|
||||
return S_dev_missingSup;
|
||||
}
|
||||
|
||||
if (!prec->pact) {
|
||||
if (prec->dol.type != CONSTANT && prec->omsl == menuOmslclosed_loop) {
|
||||
long status;
|
||||
unsigned short val;
|
||||
if (!pact) {
|
||||
if (prec->dol.type != CONSTANT && prec->omsl == menuOmslclosed_loop) {
|
||||
long status;
|
||||
unsigned short val;
|
||||
|
||||
status = dbGetLink(&prec->dol,DBR_USHORT, &val,0,0);
|
||||
if(status==0) {
|
||||
prec->val= val;
|
||||
prec->udf= FALSE;
|
||||
} else {
|
||||
recGblSetSevr(prec,LINK_ALARM,INVALID_ALARM);
|
||||
goto CONTINUE;
|
||||
}
|
||||
}
|
||||
if(prec->udf==TRUE) {
|
||||
recGblSetSevr(prec,UDF_ALARM,INVALID_ALARM);
|
||||
goto CONTINUE;
|
||||
}
|
||||
/* convert val to rval */
|
||||
convert(prec);
|
||||
status = dbGetLink(&prec->dol, DBR_USHORT, &val, 0, 0);
|
||||
if (status == 0) {
|
||||
prec->val = val;
|
||||
prec->udf = FALSE;
|
||||
} else {
|
||||
recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM);
|
||||
goto CONTINUE;
|
||||
}
|
||||
}
|
||||
if (prec->udf==TRUE) {
|
||||
recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM);
|
||||
goto CONTINUE;
|
||||
}
|
||||
/* convert val to rval */
|
||||
convert(prec);
|
||||
}
|
||||
|
||||
CONTINUE:
|
||||
/* check for alarms */
|
||||
checkAlarms(prec);
|
||||
|
||||
if (prec->nsev < INVALID_ALARM )
|
||||
status=writeValue(prec); /* write the new value */
|
||||
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;
|
||||
convert(prec);
|
||||
}
|
||||
status=writeValue(prec); /* write the new value */
|
||||
break;
|
||||
default :
|
||||
status=-1;
|
||||
recGblRecordError(S_db_badField,(void *)prec,
|
||||
"mbbo:process Illegal IVOA field");
|
||||
switch (prec->ivoa) {
|
||||
case menuIvoaSet_output_to_IVOV:
|
||||
if (!prec->pact) {
|
||||
prec->val = prec->ivov;
|
||||
convert(prec);
|
||||
}
|
||||
/* no break, fall through... */
|
||||
case menuIvoaContinue_normally:
|
||||
status = writeValue(prec); /* write the new value */
|
||||
break;
|
||||
case menuIvoaDon_t_drive_outputs:
|
||||
break;
|
||||
default :
|
||||
status = -1;
|
||||
recGblRecordError(S_db_badField, prec,
|
||||
"mbbo::process Illegal IVOA field");
|
||||
}
|
||||
}
|
||||
|
||||
/* check if device support set pact */
|
||||
if ( !pact && prec->pact ) return(0);
|
||||
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);
|
||||
prec->pact = FALSE;
|
||||
return status;
|
||||
}
|
||||
|
||||
static long special(DBADDR *paddr, int after)
|
||||
{
|
||||
mbboRecord *prec = (mbboRecord *)(paddr->precord);
|
||||
int special_type = paddr->special;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
mbboRecord *prec = (mbboRecord *) paddr->precord;
|
||||
int special_type = paddr->special;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if(!after) return(0);
|
||||
switch(special_type) {
|
||||
case(SPC_MOD):
|
||||
if (!after)
|
||||
return 0;
|
||||
|
||||
switch (special_type) {
|
||||
case SPC_MOD:
|
||||
init_common(prec);
|
||||
if (fieldIndex >= mbboRecordZRST && fieldIndex <= mbboRecordFFST)
|
||||
db_post_events(prec,&prec->val,DBE_PROPERTY);
|
||||
return(0);
|
||||
if (fieldIndex >= mbboRecordZRST && fieldIndex <= mbboRecordFFST) {
|
||||
int event = DBE_PROPERTY;
|
||||
|
||||
if (prec->val == fieldIndex - mbboRecordZRST)
|
||||
event |= DBE_VALUE | DBE_LOG;
|
||||
db_post_events(prec, &prec->val, event);
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
recGblDbaddrError(S_db_badChoice,paddr,"mbbo: special");
|
||||
return(S_db_badChoice);
|
||||
recGblDbaddrError(S_db_badChoice, paddr, "mbbo: special");
|
||||
return S_db_badChoice;
|
||||
}
|
||||
}
|
||||
|
||||
static long cvt_dbaddr(DBADDR *paddr)
|
||||
{
|
||||
mbboRecord *prec=(mbboRecord *)paddr->precord;
|
||||
int index;
|
||||
mbboRecord *prec = (mbboRecord *) paddr->precord;
|
||||
|
||||
index = dbGetFieldIndex(paddr);
|
||||
if(index!=mbboRecordVAL) {
|
||||
recGblDbaddrError(S_db_badField,paddr,"mbbo: cvt_dbaddr");
|
||||
return(0);
|
||||
if (dbGetFieldIndex(paddr) != mbboRecordVAL) {
|
||||
recGblDbaddrError(S_db_badField, paddr, "mbbo: cvt_dbaddr");
|
||||
return 0;
|
||||
}
|
||||
if(!prec->sdef) {
|
||||
if (!prec->sdef) {
|
||||
paddr->field_type = DBF_USHORT;
|
||||
paddr->dbr_field_type = DBF_USHORT;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_enum_str(DBADDR *paddr, char *pstring)
|
||||
{
|
||||
mbboRecord *prec=(mbboRecord *)paddr->precord;
|
||||
char *psource;
|
||||
int index;
|
||||
unsigned short *pfield = (unsigned short *)paddr->pfield;
|
||||
unsigned short val=*pfield;
|
||||
mbboRecord *prec = (mbboRecord *) paddr->precord;
|
||||
unsigned short *pfield = paddr->pfield;
|
||||
int val = *pfield;
|
||||
|
||||
index = dbGetFieldIndex(paddr);
|
||||
if(index!=mbboRecordVAL) {
|
||||
strcpy(pstring,"Illegal_Value");
|
||||
} else if(val<= 15) {
|
||||
psource = (prec->zrst);
|
||||
psource += (val * sizeof(prec->zrst));
|
||||
strncpy(pstring,psource,sizeof(prec->zrst));
|
||||
} else {
|
||||
strcpy(pstring,"Illegal Value");
|
||||
if (dbGetFieldIndex(paddr) != mbboRecordVAL) {
|
||||
strcpy(pstring, "Bad Field");
|
||||
}
|
||||
return(0);
|
||||
else if (val <= 15) {
|
||||
const char *pstate = prec->zrst + val * sizeof(prec->zrst);
|
||||
|
||||
strncpy(pstring, pstate, sizeof(prec->zrst));
|
||||
}
|
||||
else {
|
||||
strcpy(pstring, "Illegal Value");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_enum_strs(DBADDR *paddr, struct dbr_enumStrs *pes)
|
||||
{
|
||||
mbboRecord *prec=(mbboRecord *)paddr->precord;
|
||||
char *psource;
|
||||
int i;
|
||||
short no_str;
|
||||
mbboRecord *prec = (mbboRecord *) paddr->precord;
|
||||
const char *pstate;
|
||||
int i, states = 0;
|
||||
|
||||
no_str=0;
|
||||
memset(pes->strs,'\0',sizeof(pes->strs));
|
||||
for(i=0,psource=(prec->zrst); i<16; i++, psource += sizeof(prec->zrst) ) {
|
||||
strncpy(pes->strs[i],psource,sizeof(prec->zrst));
|
||||
if(*psource!=0)no_str=i+1;
|
||||
memset(pes->strs, '\0', sizeof(pes->strs));
|
||||
pstate = prec->zrst;
|
||||
for (i = 0; i < 16; i++) {
|
||||
strncpy(pes->strs[i], pstate, sizeof(prec->zrst));
|
||||
if (*pstate) states = i + 1;
|
||||
pstate += sizeof(prec->zrst);
|
||||
}
|
||||
pes->no_str = no_str;
|
||||
pes->no_str = states;
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
static long put_enum_str(DBADDR *paddr,char *pstring)
|
||||
{
|
||||
mbboRecord *prec=(mbboRecord *)paddr->precord;
|
||||
char *pstate_name;
|
||||
short i;
|
||||
mbboRecord *prec = (mbboRecord *) paddr->precord;
|
||||
const char *pstate;
|
||||
short i;
|
||||
|
||||
if (prec->sdef){
|
||||
pstate_name = prec->zrst;
|
||||
for (i = 0; i < 16; i++){
|
||||
if(strncmp(pstate_name,pstring,sizeof(prec->zrst))==0){
|
||||
prec->val = i;
|
||||
return(0);
|
||||
}
|
||||
pstate_name += sizeof(prec->zrst);
|
||||
}
|
||||
if (prec->sdef) {
|
||||
pstate = prec->zrst;
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (strncmp(pstate, pstring, sizeof(prec->zrst)) == 0) {
|
||||
prec->val = i;
|
||||
return 0;
|
||||
}
|
||||
pstate += sizeof(prec->zrst);
|
||||
}
|
||||
return(S_db_badChoice);
|
||||
}
|
||||
return S_db_badChoice;
|
||||
}
|
||||
|
||||
static void checkAlarms(mbboRecord *prec)
|
||||
{
|
||||
unsigned short *severities;
|
||||
unsigned short val=prec->val;
|
||||
epicsEnum16 val = prec->val;
|
||||
|
||||
/* check for state alarm */
|
||||
if (val > 15) {
|
||||
/* Unknown state */
|
||||
recGblSetSevr(prec, STATE_ALARM, prec->unsv);
|
||||
}
|
||||
else {
|
||||
/* State has a severity field */
|
||||
epicsEnum16 *severities = &prec->zrsv;
|
||||
recGblSetSevr(prec, STATE_ALARM, severities[prec->val]);
|
||||
}
|
||||
|
||||
/* check for state alarm */
|
||||
/* unknown state */
|
||||
if (val > 15){
|
||||
recGblSetSevr(prec,STATE_ALARM,prec->unsv);
|
||||
} else {
|
||||
/* in a state which is an error */
|
||||
severities = (unsigned short *)&(prec->zrsv);
|
||||
recGblSetSevr(prec,STATE_ALARM,severities[prec->val]);
|
||||
}
|
||||
|
||||
/* check for cos alarm */
|
||||
if(val == prec->lalm) return;
|
||||
if(recGblSetSevr(prec,COS_ALARM,prec->cosv)) return;
|
||||
prec->lalm = val;
|
||||
return;
|
||||
/* check for cos alarm */
|
||||
if (val == prec->lalm) return;
|
||||
if (recGblSetSevr(prec,COS_ALARM,prec->cosv)) return;
|
||||
prec->lalm = val;
|
||||
return;
|
||||
}
|
||||
|
||||
static void monitor(mbboRecord *prec)
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
unsigned short monitor_mask;
|
||||
|
||||
monitor_mask = recGblResetAlarms(prec);
|
||||
/* check for value change */
|
||||
if (prec->mlst != prec->val){
|
||||
/* post events for value change and archive change */
|
||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||
/* update last value monitored */
|
||||
prec->mlst = prec->val;
|
||||
}
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(prec,&prec->val,monitor_mask);
|
||||
}
|
||||
if(prec->oraw!=prec->rval) {
|
||||
db_post_events(prec,&prec->rval,monitor_mask|DBE_VALUE);
|
||||
prec->oraw = prec->rval;
|
||||
}
|
||||
if(prec->orbv!=prec->rbv) {
|
||||
db_post_events(prec,&prec->rbv,monitor_mask|DBE_VALUE);
|
||||
prec->orbv = prec->rbv;
|
||||
}
|
||||
return;
|
||||
monitor_mask = recGblResetAlarms(prec);
|
||||
/* check for value change */
|
||||
if (prec->mlst != prec->val) {
|
||||
/* post events for value change and archive change */
|
||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||
/* update last value monitored */
|
||||
prec->mlst = prec->val;
|
||||
}
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask) {
|
||||
db_post_events(prec, &prec->val, monitor_mask);
|
||||
}
|
||||
if (prec->oraw != prec->rval) {
|
||||
db_post_events(prec, &prec->rval, monitor_mask | DBE_VALUE);
|
||||
prec->oraw = prec->rval;
|
||||
}
|
||||
if (prec->orbv != prec->rbv) {
|
||||
db_post_events(prec, &prec->rbv, monitor_mask | DBE_VALUE);
|
||||
prec->orbv = prec->rbv;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void convert(mbboRecord *prec)
|
||||
{
|
||||
epicsUInt32 *pvalues = &(prec->zrvl);
|
||||
epicsUInt32 *pvalues = &prec->zrvl;
|
||||
|
||||
/* convert val to rval */
|
||||
if(prec->sdef) {
|
||||
/* convert val to rval */
|
||||
if (prec->sdef) {
|
||||
if (prec->val > 15) {
|
||||
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
|
||||
return;
|
||||
}
|
||||
prec->rval = pvalues[prec->val];
|
||||
}
|
||||
else
|
||||
prec->rval = prec->val;
|
||||
|
||||
if(prec->val>15) {
|
||||
recGblSetSevr(prec,SOFT_ALARM,INVALID_ALARM);
|
||||
return;
|
||||
}
|
||||
prec->rval = pvalues[prec->val];
|
||||
} else prec->rval = (epicsUInt32)(prec->val);
|
||||
if(prec->shft>0) prec->rval <<= prec->shft;
|
||||
if (prec->shft > 0)
|
||||
prec->rval <<= prec->shft;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long writeValue(mbboRecord *prec)
|
||||
{
|
||||
long status;
|
||||
struct mbbodset *pdset = (struct mbbodset *) (prec->dset);
|
||||
long status;
|
||||
struct mbbodset *pdset = (struct mbbodset *) prec->dset;
|
||||
|
||||
if (prec->pact == TRUE){
|
||||
status=(*pdset->write_mbbo)(prec);
|
||||
return(status);
|
||||
}
|
||||
if (prec->pact) {
|
||||
status = pdset->write_mbbo(prec);
|
||||
return status;
|
||||
}
|
||||
|
||||
status=dbGetLink(&(prec->siml),DBR_USHORT, &(prec->simm),0,0);
|
||||
if (status)
|
||||
return(status);
|
||||
status = dbGetLink(&prec->siml, DBR_USHORT, &prec->simm, 0, 0);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (prec->simm == menuYesNoNO){
|
||||
status=(*pdset->write_mbbo)(prec);
|
||||
return(status);
|
||||
}
|
||||
if (prec->simm == menuYesNoYES){
|
||||
status=dbPutLink(&prec->siol,DBR_USHORT, &prec->val,1);
|
||||
} else {
|
||||
status=-1;
|
||||
recGblSetSevr(prec,SOFT_ALARM,INVALID_ALARM);
|
||||
return(status);
|
||||
}
|
||||
recGblSetSevr(prec,SIMM_ALARM,prec->sims);
|
||||
if (prec->simm == menuYesNoNO) {
|
||||
status = pdset->write_mbbo(prec);
|
||||
return status;
|
||||
}
|
||||
if (prec->simm == menuYesNoYES) {
|
||||
status = dbPutLink(&prec->siol, DBR_USHORT, &prec->val, 1);
|
||||
}
|
||||
else {
|
||||
status=-1;
|
||||
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
|
||||
return status;
|
||||
}
|
||||
recGblSetSevr(prec, SIMM_ALARM, prec->sims);
|
||||
|
||||
return(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -132,11 +132,15 @@ static long process(selRecord *prec)
|
||||
}
|
||||
|
||||
|
||||
#define indexof(field) selRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
selRecord *prec=(selRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
if(paddr->pfldDes->field_type == DBF_DOUBLE) {
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -166,56 +170,68 @@ static long get_precision(DBADDR *paddr, long *precision)
|
||||
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
selRecord *prec=(selRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)&prec->val
|
||||
|| paddr->pfield==(void *)&prec->hihi
|
||||
|| paddr->pfield==(void *)&prec->high
|
||||
|| paddr->pfield==(void *)&prec->low
|
||||
|| paddr->pfield==(void *)&prec->lolo){
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return(0);
|
||||
int index = dbGetFieldIndex(paddr);
|
||||
|
||||
switch (index) {
|
||||
case indexof(VAL):
|
||||
case indexof(HIHI):
|
||||
case indexof(HIGH):
|
||||
case indexof(LOW):
|
||||
case indexof(LOLO):
|
||||
case indexof(LALM):
|
||||
case indexof(ALST):
|
||||
case indexof(MLST):
|
||||
#ifdef __GNUC__
|
||||
case indexof(A) ... indexof(L):
|
||||
case indexof(LA) ... indexof(LL):
|
||||
break;
|
||||
default:
|
||||
#else
|
||||
break;
|
||||
default:
|
||||
if((index >= indexof(A) && index <= indexof(L))
|
||||
|| (index >= indexof(LA) && index <= indexof(LL)))
|
||||
break;
|
||||
#endif
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(paddr->pfield>=(void *)&prec->a && paddr->pfield<=(void *)&prec->l){
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return(0);
|
||||
}
|
||||
if(paddr->pfield>=(void *)&prec->la && paddr->pfield<=(void *)&prec->ll){
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return(0);
|
||||
}
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_control_double(struct dbAddr *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
selRecord *prec=(selRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)&prec->val
|
||||
|| paddr->pfield==(void *)&prec->hihi
|
||||
|| paddr->pfield==(void *)&prec->high
|
||||
|| paddr->pfield==(void *)&prec->low
|
||||
|| paddr->pfield==(void *)&prec->lolo){
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return(0);
|
||||
int index = dbGetFieldIndex(paddr);
|
||||
|
||||
switch (index) {
|
||||
case indexof(VAL):
|
||||
case indexof(HIHI):
|
||||
case indexof(HIGH):
|
||||
case indexof(LOW):
|
||||
case indexof(LOLO):
|
||||
case indexof(LALM):
|
||||
case indexof(ALST):
|
||||
case indexof(MLST):
|
||||
#ifdef __GNUC__
|
||||
case indexof(A) ... indexof(L):
|
||||
case indexof(LA) ... indexof(LL):
|
||||
break;
|
||||
default:
|
||||
#else
|
||||
break;
|
||||
default:
|
||||
if((index >= indexof(A) && index <= indexof(L))
|
||||
|| (index >= indexof(LA) && index <= indexof(LL)))
|
||||
break;
|
||||
#endif
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(paddr->pfield>=(void *)&prec->a && paddr->pfield<=(void *)&prec->l){
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return(0);
|
||||
}
|
||||
if(paddr->pfield>=(void *)&prec->la && paddr->pfield<=(void *)&prec->ll){
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return(0);
|
||||
}
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -223,7 +239,7 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
{
|
||||
selRecord *prec=(selRecord *)paddr->precord;
|
||||
|
||||
if(paddr->pfield==(void *)&prec->val ){
|
||||
if(dbGetFieldIndex(paddr) == indexof(VAL)) {
|
||||
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
|
||||
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
|
||||
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* $Revision-Id$
|
||||
*
|
||||
@@ -39,37 +39,56 @@
|
||||
|
||||
int seqRecDebug = 0;
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
static long init_record(seqRecord *prec, int pass);
|
||||
static long process(seqRecord *prec);
|
||||
static int processNextLink(seqRecord *prec);
|
||||
static long asyncFinish(seqRecord *prec);
|
||||
static void processCallback(CALLBACK *arg);
|
||||
static long get_precision(dbAddr *paddr, long *pprecision);
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
#define report NULL
|
||||
#define initialize NULL
|
||||
static long init_record(seqRecord *prec, int pass);
|
||||
static long process(seqRecord *prec);
|
||||
#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 *);
|
||||
static long get_precision(dbAddr *paddr, long *);
|
||||
#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 seqRSET={
|
||||
RSETNUMBER,
|
||||
NULL, /* report */
|
||||
NULL, /* initialize */
|
||||
report, /* report */
|
||||
initialize, /* initialize */
|
||||
init_record, /* init_record */
|
||||
process, /* process */
|
||||
NULL, /* special */
|
||||
NULL, /* get_value */
|
||||
NULL, /* cvt_dbaddr */
|
||||
NULL, /* get_array_info */
|
||||
NULL, /* put_array_info */
|
||||
NULL, /* get_units */
|
||||
special, /* special */
|
||||
get_value, /* get_value */
|
||||
cvt_dbaddr, /* cvt_dbaddr */
|
||||
get_array_info, /* get_array_info */
|
||||
put_array_info, /* put_array_info */
|
||||
get_units, /* get_units */
|
||||
get_precision, /* get_precision */
|
||||
NULL, /* get_enum_str */
|
||||
NULL, /* get_enum_strs */
|
||||
NULL, /* put_enum_str */
|
||||
NULL, /* get_graphic_double */
|
||||
NULL, /* get_control_double */
|
||||
NULL /* get_alarm_double */
|
||||
|
||||
get_enum_str, /* get_enum_str */
|
||||
get_enum_strs, /* get_enum_strs */
|
||||
put_enum_str, /* put_enum_str */
|
||||
get_graphic_double, /* get_graphic_double */
|
||||
get_control_double, /* get_control_double */
|
||||
get_alarm_double /* get_alarm_double */
|
||||
};
|
||||
epicsExportAddress(rset,seqRSET);
|
||||
|
||||
int seqDLYprecision = 2;
|
||||
epicsExportAddress(int, seqDLYprecision);
|
||||
double seqDLYlimit = 100000;
|
||||
epicsExportAddress(double, seqDLYlimit);
|
||||
|
||||
/* Total number of link-groups in a sequence record */
|
||||
#define NUM_LINKS 10
|
||||
#define SELN_BIT_MASK ~(0xffff << NUM_LINKS)
|
||||
@@ -406,15 +425,93 @@ static void processCallback(CALLBACK *arg)
|
||||
* Return the precision value from PREC
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define indexof(field) seqRecord##field
|
||||
#define get_dol(prec, fieldOffset) \
|
||||
&((linkDesc*)&prec->dly1)[fieldOffset>>2].dol
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
seqRecord *prec = (seqRecord *) paddr->precord;
|
||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
||||
|
||||
if (fieldOffset >= 0) switch (fieldOffset & 2) {
|
||||
case 0: /* DLYn */
|
||||
strcpy(units, "s");
|
||||
break;
|
||||
case 2: /* DOn */
|
||||
dbGetUnits(get_dol(prec, fieldOffset),
|
||||
units, DB_UNITS_SIZE);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_precision(dbAddr *paddr, long *pprecision)
|
||||
{
|
||||
seqRecord *prec = (seqRecord *) paddr->precord;
|
||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
||||
short precision;
|
||||
|
||||
if (fieldOffset >= 0) switch (fieldOffset & 2) {
|
||||
case 0: /* DLYn */
|
||||
*pprecision = seqDLYprecision;
|
||||
return 0;
|
||||
case 2: /* DOn */
|
||||
if (dbGetPrecision(get_dol(prec, fieldOffset),
|
||||
&precision) == 0) {
|
||||
*pprecision = precision;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*pprecision = prec->prec;
|
||||
|
||||
if(paddr->pfield < (void *)&prec->val)
|
||||
return 0; /* Field is NOT in dbCommon */
|
||||
|
||||
recGblGetPrec(paddr, pprecision); /* Field is in dbCommon */
|
||||
recGblGetPrec(paddr, pprecision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
seqRecord *prec = (seqRecord *) paddr->precord;
|
||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
||||
|
||||
if (fieldOffset >= 0) switch (fieldOffset & 2) {
|
||||
case 0: /* DLYn */
|
||||
pgd->lower_disp_limit = 0.0;
|
||||
pgd->lower_disp_limit = 10.0;
|
||||
return 0;
|
||||
case 2: /* DOn */
|
||||
dbGetGraphicLimits(get_dol(prec, fieldOffset),
|
||||
&pgd->lower_disp_limit,
|
||||
&pgd->upper_disp_limit);
|
||||
return 0;
|
||||
}
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
||||
|
||||
if (fieldOffset >= 0 && (fieldOffset & 2) == 0) { /* DLYn */
|
||||
pcd->lower_ctrl_limit = 0.0;
|
||||
pcd->upper_ctrl_limit = seqDLYlimit;
|
||||
} else
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
{
|
||||
seqRecord *prec = (seqRecord *) paddr->precord;
|
||||
int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1);
|
||||
|
||||
if (fieldOffset >= 0 && (fieldOffset & 2) == 2) /* DOn */
|
||||
dbGetAlarmLimits(get_dol(prec, fieldOffset),
|
||||
&pad->lower_alarm_limit,
|
||||
&pad->lower_warning_limit,
|
||||
&pad->upper_warning_limit,
|
||||
&pad->upper_alarm_limit);
|
||||
else
|
||||
recGblGetAlarmDouble(paddr, pad);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,3 +231,6 @@ recordtype(seq) {
|
||||
interest(1)
|
||||
}
|
||||
}
|
||||
|
||||
variable(seqDLYprecision, int)
|
||||
variable(seqDLYlimit, double)
|
||||
|
||||
@@ -200,25 +200,30 @@ static long put_array_info(DBADDR *paddr, long nNew)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define indexof(field) subArrayRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
subArrayRecord *prec = (subArrayRecord *) paddr->precord;
|
||||
|
||||
strncpy(units, prec->egu, DB_UNITS_SIZE);
|
||||
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
|
||||
break;
|
||||
case indexof(HOPR):
|
||||
case indexof(LOPR):
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_precision(DBADDR *paddr, long *precision)
|
||||
{
|
||||
subArrayRecord *prec = (subArrayRecord *) paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
*precision = prec->prec;
|
||||
|
||||
if (fieldIndex != subArrayRecordVAL)
|
||||
if (dbGetFieldIndex(paddr) != indexof(VAL))
|
||||
recGblGetPrec(paddr, precision);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -227,25 +232,29 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
subArrayRecord *prec = (subArrayRecord *) paddr->precord;
|
||||
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case subArrayRecordVAL:
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
|
||||
case subArrayRecordINDX:
|
||||
pgd->upper_disp_limit = prec->malm - 1;
|
||||
pgd->lower_disp_limit = 0;
|
||||
break;
|
||||
|
||||
case subArrayRecordNELM:
|
||||
pgd->upper_disp_limit = prec->malm;
|
||||
pgd->lower_disp_limit = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr, pgd);
|
||||
case indexof(VAL):
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(INDX):
|
||||
pgd->upper_disp_limit = prec->malm - 1;
|
||||
pgd->lower_disp_limit = 0;
|
||||
break;
|
||||
case indexof(NELM):
|
||||
pgd->upper_disp_limit = prec->malm;
|
||||
pgd->lower_disp_limit = 0;
|
||||
break;
|
||||
case indexof(NORD):
|
||||
pgd->upper_disp_limit = prec->malm;
|
||||
pgd->lower_disp_limit = 0;
|
||||
break;
|
||||
case indexof(BUSY):
|
||||
pgd->upper_disp_limit = 1;
|
||||
pgd->lower_disp_limit = 0;
|
||||
break;
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr, pgd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -254,25 +263,29 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
subArrayRecord *prec = (subArrayRecord *) paddr->precord;
|
||||
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case subArrayRecordVAL:
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
break;
|
||||
|
||||
case subArrayRecordINDX:
|
||||
pcd->upper_ctrl_limit = prec->malm - 1;
|
||||
pcd->lower_ctrl_limit = 0;
|
||||
break;
|
||||
|
||||
case subArrayRecordNELM:
|
||||
pcd->upper_ctrl_limit = prec->malm;
|
||||
pcd->lower_ctrl_limit = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
recGblGetControlDouble(paddr, pcd);
|
||||
case indexof(VAL):
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(INDX):
|
||||
pcd->upper_ctrl_limit = prec->malm - 1;
|
||||
pcd->lower_ctrl_limit = 0;
|
||||
break;
|
||||
case indexof(NELM):
|
||||
pcd->upper_ctrl_limit = prec->malm;
|
||||
pcd->lower_ctrl_limit = 1;
|
||||
break;
|
||||
case indexof(NORD):
|
||||
pcd->upper_ctrl_limit = prec->malm;
|
||||
pcd->lower_ctrl_limit = 0;
|
||||
break;
|
||||
case indexof(BUSY):
|
||||
pcd->upper_ctrl_limit = 1;
|
||||
pcd->lower_ctrl_limit = 0;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr, pcd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -191,54 +191,79 @@ static long special(DBADDR *paddr, int after)
|
||||
return S_db_BadSub;
|
||||
}
|
||||
|
||||
#define indexof(field) subRecord##field
|
||||
|
||||
static long get_linkNumber(int fieldIndex) {
|
||||
if (fieldIndex >= indexof(A) && fieldIndex <= indexof(L))
|
||||
return fieldIndex - indexof(A);
|
||||
if (fieldIndex >= indexof(LA) && fieldIndex <= indexof(LL))
|
||||
return fieldIndex - indexof(LA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
subRecord *prec = (subRecord *)paddr->precord;
|
||||
int linkNumber;
|
||||
|
||||
strncpy(units, prec->egu, DB_UNITS_SIZE);
|
||||
if(paddr->pfldDes->field_type == DBF_DOUBLE) {
|
||||
linkNumber = get_linkNumber(dbGetFieldIndex(paddr));
|
||||
if (linkNumber >= 0)
|
||||
dbGetUnits(&prec->inpa + linkNumber, units, DB_UNITS_SIZE);
|
||||
else
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_precision(DBADDR *paddr, long *precision)
|
||||
static long get_precision(DBADDR *paddr, long *pprecision)
|
||||
{
|
||||
subRecord *prec = (subRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
*precision = prec->prec;
|
||||
if (fieldIndex != subRecordVAL)
|
||||
recGblGetPrec(paddr, precision);
|
||||
|
||||
*pprecision = prec->prec;
|
||||
if (fieldIndex == indexof(VAL)) {
|
||||
return 0;
|
||||
}
|
||||
linkNumber = get_linkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
short precision;
|
||||
if (dbGetPrecision(&prec->inpa + linkNumber, &precision) == 0)
|
||||
*pprecision = precision;
|
||||
else
|
||||
*pprecision = 15;
|
||||
} else
|
||||
recGblGetPrec(paddr, pprecision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
subRecord *prec = (subRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
int linkNumber;
|
||||
|
||||
switch (fieldIndex) {
|
||||
case subRecordVAL:
|
||||
case subRecordHIHI: case subRecordHIGH:
|
||||
case subRecordLOW: case subRecordLOLO:
|
||||
case subRecordA: case subRecordB:
|
||||
case subRecordC: case subRecordD:
|
||||
case subRecordE: case subRecordF:
|
||||
case subRecordG: case subRecordH:
|
||||
case subRecordI: case subRecordJ:
|
||||
case subRecordK: case subRecordL:
|
||||
case subRecordLA: case subRecordLB:
|
||||
case subRecordLC: case subRecordLD:
|
||||
case subRecordLE: case subRecordLF:
|
||||
case subRecordLG: case subRecordLH:
|
||||
case subRecordLI: case subRecordLJ:
|
||||
case subRecordLK: case subRecordLL:
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr, pgd);
|
||||
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->lower_disp_limit = prec->lopr;
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
break;
|
||||
default:
|
||||
linkNumber = get_linkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetGraphicLimits(&prec->inpa + linkNumber,
|
||||
&pgd->lower_disp_limit,
|
||||
&pgd->upper_disp_limit);
|
||||
} else
|
||||
recGblGetGraphicDouble(paddr,pgd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -246,24 +271,21 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
subRecord *prec = (subRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
switch (fieldIndex) {
|
||||
case subRecordVAL:
|
||||
case subRecordHIHI: case subRecordHIGH:
|
||||
case subRecordLOW: case subRecordLOLO:
|
||||
case subRecordA: case subRecordB:
|
||||
case subRecordC: case subRecordD:
|
||||
case subRecordE: case subRecordF:
|
||||
case subRecordG: case subRecordH:
|
||||
case subRecordI: case subRecordJ:
|
||||
case subRecordK: case subRecordL:
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
break;
|
||||
|
||||
default:
|
||||
recGblGetControlDouble(paddr, pcd);
|
||||
|
||||
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):
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr,pcd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -272,6 +294,7 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
{
|
||||
subRecord *prec = (subRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
int linkNumber;
|
||||
|
||||
if (fieldIndex == subRecordVAL) {
|
||||
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
|
||||
@@ -279,7 +302,15 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
|
||||
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
|
||||
pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN;
|
||||
} else {
|
||||
recGblGetAlarmDouble(paddr, pad);
|
||||
linkNumber = get_linkNumber(fieldIndex);
|
||||
if (linkNumber >= 0) {
|
||||
dbGetAlarmLimits(&prec->inpa + linkNumber,
|
||||
&pad->lower_alarm_limit,
|
||||
&pad->lower_warning_limit,
|
||||
&pad->upper_warning_limit,
|
||||
&pad->upper_alarm_limit);
|
||||
} else
|
||||
recGblGetAlarmDouble(paddr, pad);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
|
||||
{
|
||||
waveformRecord *prec = (waveformRecord *) paddr->precord;
|
||||
|
||||
*no_elements = prec->nord;
|
||||
*no_elements = prec->nord;
|
||||
*offset = 0;
|
||||
|
||||
return 0;
|
||||
@@ -191,28 +191,34 @@ static long put_array_info(DBADDR *paddr, long nNew)
|
||||
if (prec->nord > prec->nelm)
|
||||
prec->nord = prec->nelm;
|
||||
|
||||
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define indexof(field) waveformRecord##field
|
||||
|
||||
static long get_units(DBADDR *paddr, char *units)
|
||||
{
|
||||
waveformRecord *prec = (waveformRecord *) paddr->precord;
|
||||
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
|
||||
break;
|
||||
case indexof(HOPR):
|
||||
case indexof(LOPR):
|
||||
strncpy(units,prec->egu,DB_UNITS_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_precision(DBADDR *paddr, long *precision)
|
||||
{
|
||||
waveformRecord *prec = (waveformRecord *) paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
*precision = prec->prec;
|
||||
|
||||
if (fieldIndex != waveformRecordVAL)
|
||||
if (dbGetFieldIndex(paddr) != indexof(VAL))
|
||||
recGblGetPrec(paddr, precision);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -220,11 +226,22 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
|
||||
{
|
||||
waveformRecord *prec = (waveformRecord *) paddr->precord;
|
||||
|
||||
if (dbGetFieldIndex(paddr) == waveformRecordVAL) {
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
} else
|
||||
recGblGetGraphicDouble(paddr, pgd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
pgd->upper_disp_limit = prec->hopr;
|
||||
pgd->lower_disp_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(BUSY):
|
||||
pgd->upper_disp_limit = 1;
|
||||
pgd->lower_disp_limit = 0;
|
||||
break;
|
||||
case indexof(NORD):
|
||||
pgd->upper_disp_limit = prec->nelm;
|
||||
pgd->lower_disp_limit = 0;
|
||||
break;
|
||||
default:
|
||||
recGblGetGraphicDouble(paddr, pgd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -232,11 +249,22 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
|
||||
{
|
||||
waveformRecord *prec = (waveformRecord *) paddr->precord;
|
||||
|
||||
if (dbGetFieldIndex(paddr) == waveformRecordVAL) {
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
} else
|
||||
recGblGetControlDouble(paddr, pcd);
|
||||
switch (dbGetFieldIndex(paddr)) {
|
||||
case indexof(VAL):
|
||||
pcd->upper_ctrl_limit = prec->hopr;
|
||||
pcd->lower_ctrl_limit = prec->lopr;
|
||||
break;
|
||||
case indexof(BUSY):
|
||||
pcd->upper_ctrl_limit = 1;
|
||||
pcd->lower_ctrl_limit = 0;
|
||||
break;
|
||||
case indexof(NORD):
|
||||
pcd->upper_ctrl_limit = prec->nelm;
|
||||
pcd->lower_ctrl_limit = 0;
|
||||
break;
|
||||
default:
|
||||
recGblGetControlDouble(paddr, pcd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -300,6 +328,7 @@ static long readValue(waveformRecord *prec)
|
||||
/* nord set only for db links: needed for old db_access */
|
||||
if (prec->siol.type != CONSTANT) {
|
||||
prec->nord = nRequest;
|
||||
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
|
||||
if (status == 0)
|
||||
prec->udf=FALSE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user