25 #include "epicsMath.h" 38 #include "menuConvert.h" 40 #define GEN_SIZE_OFFSET 42 #undef GEN_SIZE_OFFSET 46 #define THRESHOLD 0.6321 50 #define initialize NULL 52 static long process(
struct dbCommon *);
53 static long special(DBADDR *,
int);
54 #define get_value NULL 55 #define cvt_dbaddr NULL 56 #define get_array_info NULL 57 #define put_array_info NULL 60 #define get_enum_str NULL 61 #define get_enum_strs NULL 62 #define put_enum_str NULL 90 static void convert(aiRecord *
prec);
91 static void monitor(aiRecord *
prec);
92 static long readValue(aiRecord *
prec);
94 static long init_record(
struct dbCommon *pcommon,
int pass)
96 struct aiRecord *
prec = (
struct aiRecord *)pcommon;
98 double eoff = prec->eoff, eslo = prec->eslo;
100 if (pass == 0)
return 0;
102 recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
103 recGblInitConstantLink(&prec->siol,
DBF_DOUBLE, &prec->sval);
105 if(!(pdset = (aidset *)(prec->dset))) {
106 recGblRecordError(
S_dev_noDSET,(
void *)prec,
"ai: init_record");
110 if ((pdset->common.number < 6) || (pdset->read_ai ==
NULL)) {
116 if ((prec->eslo==1.0) && (prec->eoff==0.0)) {
117 prec->eoff = prec->egul;
120 if (pdset->common.init_record) {
121 long status = pdset->common.init_record(pcommon);
122 if (prec->linr == menuConvertSLOPE) {
128 prec->mlst = prec->val;
129 prec->alst = prec->val;
130 prec->lalm = prec->val;
131 prec->oraw = prec->rval;
135 static long process(
struct dbCommon *pcommon)
137 struct aiRecord *
prec = (
struct aiRecord *)pcommon;
138 aidset *pdset = (aidset *)(prec->dset);
140 unsigned char pact=prec->pact;
143 if( (pdset==
NULL) || (pdset->read_ai==
NULL) ) {
148 timeLast = prec->time;
150 status=readValue(prec);
152 if ( !pact && prec->pact )
return(0);
155 recGblGetTimeStampSimm(prec, prec->simm, &prec->siol);
157 if (status==0) convert(prec);
158 else if (status==2) status=0;
160 if (status == 0) prec->udf =
isnan(prec->val);
163 checkAlarms(prec,&timeLast);
174 static long special(DBADDR *paddr,
int after)
176 aiRecord *
prec = (aiRecord *)(paddr->precord);
177 aidset *pdset = (aidset *) (prec->dset);
178 int special_type = paddr->special;
180 switch(special_type) {
182 if (pdset->common.number < 6) {
183 recGblDbaddrError(S_db_noMod,paddr,
"ai: special");
187 if ((prec->linr == menuConvertLINEAR) && pdset->special_linconv) {
188 double eoff = prec->eoff;
189 double eslo = prec->eslo;
191 prec->eoff = prec->egul;
192 status = (*pdset->special_linconv)(prec,after);
193 if (eoff != prec->eoff)
195 if (eslo != prec->eslo)
201 if (dbGetFieldIndex(paddr) == aiRecordSIMM) {
203 recGblSaveSimm(prec->sscn, &prec->oldsimm, prec->simm);
205 recGblCheckSimm((dbCommon *)prec, &prec->sscn, prec->oldsimm, prec->simm);
209 recGblDbaddrError(S_db_badChoice,paddr,
"ai: special");
210 return(S_db_badChoice);
214 #define indexof(field) aiRecord##field 216 static long get_units(DBADDR *paddr,
char *units)
218 aiRecord *
prec=(aiRecord *)paddr->precord;
220 if(paddr->pfldDes->field_type ==
DBF_DOUBLE) {
221 switch (dbGetFieldIndex(paddr)) {
227 strncpy(units,prec->egu,DB_UNITS_SIZE);
233 static long get_precision(
const DBADDR *paddr,
long *precision)
235 aiRecord *
prec=(aiRecord *)paddr->precord;
237 *precision = prec->prec;
238 if (dbGetFieldIndex(paddr) ==
indexof(VAL))
return(0);
239 recGblGetPrec(paddr,precision);
245 aiRecord *
prec=(aiRecord *)paddr->precord;
247 switch (dbGetFieldIndex(paddr)) {
257 pgd->upper_disp_limit = prec->hopr;
258 pgd->lower_disp_limit = prec->lopr;
261 recGblGetGraphicDouble(paddr,pgd);
268 aiRecord *
prec=(aiRecord *)paddr->precord;
270 switch (dbGetFieldIndex(paddr)) {
280 pcd->upper_ctrl_limit = prec->hopr;
281 pcd->lower_ctrl_limit = prec->lopr;
284 recGblGetControlDouble(paddr,pcd);
291 aiRecord *
prec=(aiRecord *)paddr->precord;
293 if (dbGetFieldIndex(paddr) ==
indexof(VAL)) {
294 pad->upper_alarm_limit = prec->hhsv ? prec->hihi :
epicsNAN;
295 pad->upper_warning_limit = prec->hsv ? prec->high :
epicsNAN;
296 pad->lower_warning_limit = prec->lsv ? prec->low :
epicsNAN;
297 pad->lower_alarm_limit = prec->llsv ? prec->lolo :
epicsNAN;
298 }
else recGblGetAlarmDouble(paddr,pad);
315 double val, hyst, lalm, alev, aftc, afvl;
329 if ((asev =
prec->hhsv) &&
330 (val >= (alev =
prec->hihi) ||
331 ((lalm == alev) && (val >= alev - hyst))))
332 alarmRange = range_Hihi;
334 if ((asev =
prec->llsv) &&
335 (val <= (alev =
prec->lolo) ||
336 ((lalm == alev) && (val <= alev + hyst))))
337 alarmRange = range_Lolo;
339 if ((asev =
prec->hsv) &&
340 (val >= (alev =
prec->high) ||
341 ((lalm == alev) && (val >= alev - hyst))))
342 alarmRange = range_High;
344 if ((asev =
prec->lsv) &&
345 (val <= (alev =
prec->low) ||
346 ((lalm == alev) && (val <= alev + hyst))))
347 alarmRange = range_Low;
351 alarmRange = range_Normal;
361 afvl = (double)alarmRange;
364 double alpha = aftc / (t + aftc);
371 afvl = alpha * afvl +
372 ((afvl > 0) ? (1 - alpha) : (alpha - 1)) * alarmRange;
376 alarmRange = abs((
int)floor(afvl));
377 switch (alarmRange) {
404 if (recGblSetSevr(
prec, range_stat[alarmRange], asev))
412 static void convert(aiRecord *
prec)
417 val = (double)prec->rval + (
double)prec->roff;
419 if(prec->aslo!=0.0) val*=prec->aslo;
423 switch (prec->linr) {
424 case menuConvertNO_CONVERSION:
427 case menuConvertLINEAR:
428 case menuConvertSLOPE:
429 val = (val * prec->eslo) + prec->eoff;
433 if (
cvtRawToEngBpt(&val,prec->linr,prec->init,(
void *)&prec->pbrk,&prec->lbrk)!=0) {
439 if (prec->smoo != 0.0 &&
finite(prec->val)){
440 if (prec->init) prec->val = val;
441 prec->val = val * (1.00 - prec->smoo) + (prec->val * prec->smoo);
448 static void monitor(aiRecord *
prec)
450 unsigned monitor_mask = recGblResetAlarms(prec);
453 recGblCheckDeadband(&prec->mlst, prec->val, prec->mdel, &monitor_mask,
DBE_VALUE);
456 recGblCheckDeadband(&prec->alst, prec->val, prec->adel, &monitor_mask,
DBE_ARCHIVE);
460 db_post_events(prec,&prec->val,monitor_mask);
461 if(prec->oraw != prec->rval) {
462 db_post_events(prec,&prec->rval,monitor_mask);
463 prec->oraw = prec->rval;
469 static long readValue(aiRecord *
prec)
471 aidset *pdset = (aidset *)prec->dset;
475 status = recGblGetSimm((dbCommon *)prec, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
479 switch (prec->simm) {
481 status = pdset->read_ai(prec);
487 if (prec->pact || (prec->sdly < 0.)) {
490 if (prec->simm == menuSimmYES) {
491 prec->val = prec->sval;
494 prec->rval = (long)floor(prec->sval);
500 epicsCallback *pvt = prec->simpvt;
502 pvt = calloc(1,
sizeof(epicsCallback));
505 if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
Miscellaneous macro definitions.
#define get_control_double
#define NO_ALARM
The NO_ALARM value can be used as both a severity and a status.
epicsShareFunc long cvtRawToEngBpt(double *pval, short linr, short init, void **ppbrk, short *plbrk)
EPICS time stamp, for use from C code.
LIBCOM_API double epicsStdCall epicsTimeDiffInSeconds(const epicsTimeStamp *pLeft, const epicsTimeStamp *pRight)
Time difference between left and right in seconds.
epicsExportAddress(rset, aiRSET)
#define get_graphic_double