28 #include "epicsMath.h" 34 #define GEN_SIZE_OFFSET 35 #include "calcRecord.h" 36 #undef GEN_SIZE_OFFSET 40 #define THRESHOLD 0.6321 45 #define initialize NULL 46 static long init_record(
struct dbCommon *pcommon,
int pass);
47 static long process(
struct dbCommon *
prec);
48 static long special(DBADDR *paddr,
int after);
49 #define get_value NULL 50 #define cvt_dbaddr NULL 51 #define get_array_info NULL 52 #define put_array_info NULL 53 static long get_units(DBADDR *paddr,
char *units);
54 static long get_precision(
const DBADDR *paddr,
long *precision);
55 #define get_enum_str NULL 56 #define get_enum_strs NULL 57 #define put_enum_str NULL 85 static void monitor(calcRecord *
prec);
86 static int fetch_values(calcRecord *
prec);
89 static long init_record(
struct dbCommon *pcommon,
int pass)
91 struct calcRecord *
prec = (
struct calcRecord *)pcommon;
97 if (pass==0)
return(0);
102 recGblInitConstantLink(plink,
DBF_DOUBLE, pvalue);
104 if (
postfix(prec->calc, prec->rpcl, &error_number)) {
105 recGblRecordError(S_db_badField, (
void *)prec,
106 "calc: init_record: Illegal CALC field");
113 static long process(
struct dbCommon *pcommon)
115 struct calcRecord *
prec = (
struct calcRecord *)pcommon;
119 if (fetch_values(prec) == 0) {
120 if (
calcPerform(&prec->a, &prec->val, prec->rpcl)) {
123 prec->udf =
isnan(prec->val);
126 timeLast = prec->time;
127 recGblGetTimeStamp(prec);
129 checkAlarms(prec, &timeLast);
138 static long special(DBADDR *paddr,
int after)
140 calcRecord *
prec = (calcRecord *)paddr->precord;
143 if (!after)
return 0;
145 if (
postfix(prec->calc, prec->rpcl, &error_number)) {
146 recGblRecordError(S_db_badField, (
void *)prec,
147 "calc: Illegal CALC field");
150 return S_db_badField;
154 recGblDbaddrError(S_db_badChoice, paddr,
"calc::special - bad special value!");
155 return S_db_badChoice;
158 #define indexof(field) calcRecord##field 160 static long get_linkNumber(
int fieldIndex) {
162 return fieldIndex -
indexof(A);
168 static long get_units(DBADDR *paddr,
char *units)
170 calcRecord *
prec = (calcRecord *)paddr->precord;
173 if(paddr->pfldDes->field_type ==
DBF_DOUBLE) {
174 linkNumber = get_linkNumber(dbGetFieldIndex(paddr));
176 dbGetUnits(&prec->inpa + linkNumber, units, DB_UNITS_SIZE);
178 strncpy(units,prec->egu,DB_UNITS_SIZE);
183 static long get_precision(
const DBADDR *paddr,
long *pprecision)
185 calcRecord *
prec = (calcRecord *)paddr->precord;
186 int fieldIndex = dbGetFieldIndex(paddr);
189 *pprecision = prec->prec;
190 if (fieldIndex ==
indexof(VAL))
193 linkNumber = get_linkNumber(fieldIndex);
194 if (linkNumber >= 0) {
197 if (dbGetPrecision(&prec->inpa + linkNumber, &precision) == 0)
198 *pprecision = precision;
200 recGblGetPrec(paddr, pprecision);
206 calcRecord *
prec = (calcRecord *)paddr->precord;
207 int fieldIndex = dbGetFieldIndex(paddr);
210 switch (fieldIndex) {
219 pgd->lower_disp_limit = prec->lopr;
220 pgd->upper_disp_limit = prec->hopr;
223 linkNumber = get_linkNumber(fieldIndex);
224 if (linkNumber >= 0) {
225 dbGetGraphicLimits(&prec->inpa + linkNumber,
226 &pgd->lower_disp_limit,
227 &pgd->upper_disp_limit);
229 recGblGetGraphicDouble(paddr,pgd);
236 calcRecord *
prec = (calcRecord *)paddr->precord;
238 switch (dbGetFieldIndex(paddr)) {
247 pcd->lower_ctrl_limit = prec->lopr;
248 pcd->upper_ctrl_limit = prec->hopr;
251 recGblGetControlDouble(paddr,pcd);
258 calcRecord *
prec = (calcRecord *)paddr->precord;
259 int fieldIndex = dbGetFieldIndex(paddr);
262 if (fieldIndex ==
indexof(VAL)) {
263 pad->lower_alarm_limit = prec->llsv ? prec->lolo :
epicsNAN;
264 pad->lower_warning_limit = prec->lsv ? prec->low :
epicsNAN;
265 pad->upper_warning_limit = prec->hsv ? prec->high :
epicsNAN;
266 pad->upper_alarm_limit = prec->hhsv ? prec->hihi :
epicsNAN;
268 linkNumber = get_linkNumber(fieldIndex);
269 if (linkNumber >= 0) {
270 dbGetAlarmLimits(&prec->inpa + linkNumber,
271 &pad->lower_alarm_limit,
272 &pad->lower_warning_limit,
273 &pad->upper_warning_limit,
274 &pad->upper_alarm_limit);
276 recGblGetAlarmDouble(paddr, pad);
296 double val, hyst, lalm, alev, aftc, afvl;
310 if ((asev =
prec->hhsv) &&
311 (val >= (alev =
prec->hihi) ||
312 ((lalm == alev) && (val >= alev - hyst))))
313 alarmRange = range_Hihi;
315 if ((asev =
prec->llsv) &&
316 (val <= (alev =
prec->lolo) ||
317 ((lalm == alev) && (val <= alev + hyst))))
318 alarmRange = range_Lolo;
320 if ((asev =
prec->hsv) &&
321 (val >= (alev =
prec->high) ||
322 ((lalm == alev) && (val >= alev - hyst))))
323 alarmRange = range_High;
325 if ((asev =
prec->lsv) &&
326 (val <= (alev =
prec->low) ||
327 ((lalm == alev) && (val <= alev + hyst))))
328 alarmRange = range_Low;
332 alarmRange = range_Normal;
342 afvl = (double)alarmRange;
345 double alpha = aftc / (t + aftc);
352 afvl = alpha * afvl +
353 ((afvl > 0) ? (1 - alpha) : (alpha - 1)) * alarmRange;
357 alarmRange = abs((
int)floor(afvl));
358 switch (alarmRange) {
385 if (recGblSetSevr(
prec, range_stat[alarmRange], asev))
394 static void monitor(calcRecord *
prec)
396 unsigned monitor_mask;
397 double *pnew, *pprev;
400 monitor_mask = recGblResetAlarms(prec);
403 recGblCheckDeadband(&prec->mlst, prec->val, prec->mdel, &monitor_mask,
DBE_VALUE);
406 recGblCheckDeadband(&prec->alst, prec->val, prec->adel, &monitor_mask,
DBE_ARCHIVE);
410 db_post_events(prec, &prec->val, monitor_mask);
417 if (*pnew != *pprev ||
426 static int fetch_values(calcRecord *
prec)
438 newStatus = dbGetLink(plink,
DBR_DOUBLE, pvalue, 0, 0);
439 if (status == 0) status = newStatus;
LIBCOM_API const char * calcErrorStr(short error)
Convert an error code to a string.
#define CALCPERFORM_NARGS
Number of input arguments to a calc expression (A-L)
Miscellaneous macro definitions.
#define get_control_double
#define NO_ALARM
The NO_ALARM value can be used as both a severity and a status.
int errlogPrintf(const char *pFormat,...)
EPICS time stamp, for use from C code.
epicsExportAddress(rset, calcRSET)
LIBCOM_API double epicsStdCall epicsTimeDiffInSeconds(const epicsTimeStamp *pLeft, const epicsTimeStamp *pRight)
Time difference between left and right in seconds.
LIBCOM_API long postfix(const char *psrc, char *pout, short *perror)
Compile an infix expression into postfix byte-code.
#define get_graphic_double