24 #include "epicsMath.h" 37 #define GEN_SIZE_OFFSET 38 #include "subRecord.h" 39 #undef GEN_SIZE_OFFSET 44 #define initialize NULL 46 static long process(
struct dbCommon *);
47 static long special(DBADDR *,
int);
48 #define get_value NULL 49 #define cvt_dbaddr NULL 50 #define get_array_info NULL 51 #define put_array_info NULL 54 #define get_enum_str NULL 55 #define get_enum_strs NULL 56 #define put_enum_str NULL 83 static void checkAlarms(subRecord *);
84 static long do_sub(subRecord *);
85 static long fetch_values(subRecord *);
86 static void monitor(subRecord *);
88 #define INP_ARG_MAX 12 90 static long init_record(
struct dbCommon *pcommon,
int pass)
92 struct subRecord *
prec = (
struct subRecord *)pcommon;
93 SUBFUNCPTR psubroutine;
98 if (pass==0)
return(0);
102 for (i = 0; i <
INP_ARG_MAX; i++, plink++, pvalue++) {
103 recGblInitConstantLink(plink,
DBF_DOUBLE, pvalue);
109 if (psubroutine == 0) {
110 recGblRecordError(S_db_BadSub, (
void *)prec,
"Init subroutine (INAM)");
114 (*psubroutine)(
prec);
117 if (prec->snam[0] == 0) {
123 if (prec->sadr ==
NULL) {
124 recGblRecordError(S_db_BadSub, (
void *)prec,
"Proc subroutine (SNAM)");
127 prec->mlst = prec->val;
128 prec->alst = prec->val;
129 prec->lalm = prec->val;
133 static long process(
struct dbCommon *pcommon)
135 struct subRecord *
prec = (
struct subRecord *)pcommon;
137 int pact = prec->pact;
141 status = fetch_values(prec);
144 if (status == 0) status = do_sub(prec);
147 if (!pact && prec->pact)
return 0;
151 if (status == 1)
return 0;
153 recGblGetTimeStamp(prec);
167 static long special(DBADDR *paddr,
int after)
169 subRecord *
prec = (subRecord *)paddr->precord;
172 if (prec->snam[0] == 0 && prec->pact) {
179 if (prec->snam[0] == 0) {
186 if (prec->sadr)
return 0;
188 recGblRecordError(S_db_BadSub, (
void *)prec,
189 "subRecord(special) registryFunctionFind failed");
193 #define indexof(field) subRecord##field 195 static long get_linkNumber(
int fieldIndex) {
197 return fieldIndex -
indexof(A);
203 static long get_units(DBADDR *paddr,
char *units)
205 subRecord *
prec = (subRecord *)paddr->precord;
208 if(paddr->pfldDes->field_type ==
DBF_DOUBLE) {
209 linkNumber = get_linkNumber(dbGetFieldIndex(paddr));
211 dbGetUnits(&prec->inpa + linkNumber, units, DB_UNITS_SIZE);
213 strncpy(units,prec->egu,DB_UNITS_SIZE);
218 static long get_precision(
const DBADDR *paddr,
long *pprecision)
220 subRecord *
prec = (subRecord *)paddr->precord;
221 int fieldIndex = dbGetFieldIndex(paddr);
224 *pprecision = prec->prec;
225 if (fieldIndex ==
indexof(VAL))
228 linkNumber = get_linkNumber(fieldIndex);
229 if (linkNumber >= 0) {
232 if (dbGetPrecision(&prec->inpa + linkNumber, &precision) == 0)
233 *pprecision = precision;
235 recGblGetPrec(paddr, pprecision);
241 subRecord *
prec = (subRecord *)paddr->precord;
242 int fieldIndex = dbGetFieldIndex(paddr);
245 switch (fieldIndex) {
254 pgd->lower_disp_limit = prec->lopr;
255 pgd->upper_disp_limit = prec->hopr;
258 linkNumber = get_linkNumber(fieldIndex);
259 if (linkNumber >= 0) {
260 dbGetGraphicLimits(&prec->inpa + linkNumber,
261 &pgd->lower_disp_limit,
262 &pgd->upper_disp_limit);
264 recGblGetGraphicDouble(paddr,pgd);
271 subRecord *
prec = (subRecord *)paddr->precord;
273 switch (dbGetFieldIndex(paddr)) {
282 pcd->lower_ctrl_limit = prec->lopr;
283 pcd->upper_ctrl_limit = prec->hopr;
286 recGblGetControlDouble(paddr,pcd);
293 subRecord *
prec = (subRecord *)paddr->precord;
294 int fieldIndex = dbGetFieldIndex(paddr);
297 if (fieldIndex == subRecordVAL) {
298 pad->upper_alarm_limit = prec->hhsv ? prec->hihi :
epicsNAN;
299 pad->upper_warning_limit = prec->hsv ? prec->high :
epicsNAN;
300 pad->lower_warning_limit = prec->lsv ? prec->low :
epicsNAN;
301 pad->lower_alarm_limit = prec->llsv ? prec->lolo :
epicsNAN;
303 linkNumber = get_linkNumber(fieldIndex);
304 if (linkNumber >= 0) {
305 dbGetAlarmLimits(&prec->inpa + linkNumber,
306 &pad->lower_alarm_limit,
307 &pad->lower_warning_limit,
308 &pad->upper_warning_limit,
309 &pad->upper_alarm_limit);
311 recGblGetAlarmDouble(paddr, pad);
316 static void checkAlarms(subRecord *
prec)
318 double val, hyst, lalm;
323 recGblSetSevr(prec,
UDF_ALARM, prec->udfs);
334 if (asev && (val >= alev || ((lalm == alev) && (val >= alev - hyst)))) {
343 if (asev && (val <= alev || ((lalm == alev) && (val <= alev + hyst)))) {
352 if (asev && (val >= alev || ((lalm == alev) && (val >= alev - hyst)))) {
361 if (asev && (val <= alev || ((lalm == alev) && (val <= alev + hyst)))) {
362 if (recGblSetSevr(prec,
LOW_ALARM, asev))
372 static void monitor(subRecord *
prec)
374 unsigned monitor_mask;
380 monitor_mask = recGblResetAlarms(prec);
383 recGblCheckDeadband(&prec->mlst, prec->val, prec->mdel, &monitor_mask,
DBE_VALUE);
386 recGblCheckDeadband(&prec->alst, prec->val, prec->adel, &monitor_mask,
DBE_ARCHIVE);
390 db_post_events(prec, &prec->val, monitor_mask);
394 for (i = 0, pnew = &prec->a, pold = &prec->la;
396 if (*pnew != *pold) {
404 static long fetch_values(subRecord *
prec)
406 struct link *plink = &prec->inpa;
407 double *pvalue = &prec->a;
410 for (i = 0; i <
INP_ARG_MAX; i++, plink++, pvalue++) {
411 if (dbGetLink(plink,
DBR_DOUBLE, pvalue, 0, 0))
417 static long do_sub(subRecord *
prec)
419 SUBFUNCPTR psubroutine = prec->sadr;
422 if (psubroutine ==
NULL) {
427 status = (*psubroutine)(
prec);
431 prec->udf =
isnan(prec->val);
Miscellaneous macro definitions.
#define get_control_double
epicsExportAddress(rset, subRSET)
epicsShareFunc REGISTRYFUNCTION registryFunctionFind(const char *name)
Routines for code that can't continue or return after an error.
#define get_graphic_double