25 #include "epicsMath.h" 37 #include "menuConvert.h" 39 #include "menuYesNo.h" 42 #define GEN_SIZE_OFFSET 44 #undef GEN_SIZE_OFFSET 49 #define initialize NULL 51 static long process(
struct dbCommon *);
52 static long special(DBADDR *,
int);
53 #define get_value NULL 54 #define cvt_dbaddr NULL 55 #define get_array_info NULL 56 #define put_array_info NULL 59 #define get_enum_str NULL 60 #define get_enum_strs NULL 61 #define put_enum_str NULL 88 static void checkAlarms(aoRecord *);
89 static long fetch_value(aoRecord *,
double *);
90 static void convert(aoRecord *,
double);
91 static void monitor(aoRecord *);
92 static long writeValue(aoRecord *);
94 static long init_record(
struct dbCommon *pcommon,
int pass)
96 struct aoRecord *
prec = (
struct aoRecord *)pcommon;
98 double eoff = prec->eoff, eslo = prec->eslo;
102 if (pass == 0)
return 0;
104 recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
106 if(!(pdset = (aodset *)(prec->dset))) {
107 recGblRecordError(
S_dev_noDSET,(
void *)prec,
"ao: init_record");
111 if (recGblInitConstantLink(&prec->dol,
DBF_DOUBLE,&prec->val))
112 prec->udf =
isnan(prec->val);
115 if ((pdset->common.number < 6) || (pdset->write_ao ==
NULL)) {
121 if ((prec->eslo==1.0) && (prec->eoff==0.0)) {
122 prec->eoff = prec->egul;
125 if (pdset->common.init_record) {
126 status = pdset->common.init_record(pcommon);
127 if (prec->linr == menuConvertSLOPE) {
133 value = (double)prec->rval + (
double)prec->roff;
134 if(prec->aslo!=0.0) value *= prec->aslo;
136 if (prec->linr == menuConvertNO_CONVERSION){
138 }
else if ((prec->linr == menuConvertLINEAR) ||
139 (prec->linr == menuConvertSLOPE)) {
140 value = value*prec->eslo + prec->eoff;
143 (
void *)&prec->pbrk,&prec->lbrk)!=0)
break;
146 prec->udf =
isnan(value);
155 prec->oval = prec->pval = prec->val;
156 prec->mlst = prec->val;
157 prec->alst = prec->val;
158 prec->lalm = prec->val;
159 prec->oraw = prec->rval;
160 prec->orbv = prec->rbv;
164 static long process(
struct dbCommon *pcommon)
166 struct aoRecord *
prec = (
struct aoRecord *)pcommon;
167 aodset *pdset = (aodset *)(prec->dset);
169 unsigned char pact=prec->pact;
172 if ((pdset==
NULL) || (pdset->write_ao==
NULL)) {
179 if (prec->pact ==
FALSE) {
180 if (!dbLinkIsConstant(&prec->dol) &&
181 prec->omsl == menuOmslclosed_loop) {
182 status = fetch_value(prec, &value);
187 if(!status) convert(prec, value);
188 prec->udf =
isnan(prec->val);
195 status=writeValue(prec);
197 switch (prec->ivoa) {
198 case (menuIvoaContinue_normally) :
199 status=writeValue(prec);
201 case (menuIvoaDon_t_drive_outputs) :
203 case (menuIvoaSet_output_to_IVOV) :
204 if(prec->pact ==
FALSE){
205 prec->val=prec->ivov;
209 status=writeValue(prec);
213 recGblRecordError(S_db_badField,(
void *)prec,
214 "ao:process Illegal IVOA field");
219 if ( !pact && prec->pact )
return(0);
222 recGblGetTimeStampSimm(prec, prec->simm,
NULL);
235 static long special(DBADDR *paddr,
int after)
237 aoRecord *
prec = (aoRecord *)(paddr->precord);
238 aodset *pdset = (aodset *) (prec->dset);
239 int special_type = paddr->special;
241 switch(special_type) {
243 if(pdset->common.number<6 ) {
244 recGblDbaddrError(S_db_noMod,paddr,
"ao: special");
248 if ((prec->linr == menuConvertLINEAR) && pdset->special_linconv) {
249 double eoff = prec->eoff;
250 double eslo = prec->eslo;
252 prec->eoff = prec->egul;
253 status = (*pdset->special_linconv)(prec,after);
254 if (eoff != prec->eoff)
256 if (eslo != prec->eslo)
262 if (dbGetFieldIndex(paddr) == aoRecordSIMM) {
264 recGblSaveSimm(prec->sscn, &prec->oldsimm, prec->simm);
266 recGblCheckSimm((dbCommon *)prec, &prec->sscn, prec->oldsimm, prec->simm);
270 recGblDbaddrError(S_db_badChoice,paddr,
"ao: special");
271 return(S_db_badChoice);
275 #define indexof(field) aoRecord##field 277 static long get_units(DBADDR * paddr,
char *units)
279 aoRecord *
prec=(aoRecord *)paddr->precord;
281 if(paddr->pfldDes->field_type ==
DBF_DOUBLE) {
282 switch (dbGetFieldIndex(paddr)) {
287 strncpy(units,prec->egu,DB_UNITS_SIZE);
293 static long get_precision(
const DBADDR *paddr,
long *precision)
295 aoRecord *
prec=(aoRecord *)paddr->precord;
297 *precision = prec->prec;
298 switch (dbGetFieldIndex(paddr)) {
304 recGblGetPrec(paddr,precision);
311 aoRecord *
prec=(aoRecord *)paddr->precord;
313 switch (dbGetFieldIndex(paddr)) {
325 pgd->upper_disp_limit = prec->hopr;
326 pgd->lower_disp_limit = prec->lopr;
329 recGblGetGraphicDouble(paddr,pgd);
336 aoRecord *
prec=(aoRecord *)paddr->precord;
338 switch (dbGetFieldIndex(paddr)) {
349 pcd->upper_ctrl_limit = prec->drvh;
350 pcd->lower_ctrl_limit = prec->drvl;
353 recGblGetControlDouble(paddr,pcd);
359 aoRecord *
prec=(aoRecord *)paddr->precord;
361 if(dbGetFieldIndex(paddr) ==
indexof(VAL)){
362 pad->upper_alarm_limit = prec->hhsv ? prec->hihi :
epicsNAN;
363 pad->upper_warning_limit = prec->hsv ? prec->high :
epicsNAN;
364 pad->lower_warning_limit = prec->lsv ? prec->low :
epicsNAN;
365 pad->lower_alarm_limit = prec->llsv ? prec->lolo :
epicsNAN;
366 }
else recGblGetAlarmDouble(paddr,pad);
370 static void checkAlarms(aoRecord *
prec)
372 double val, hyst, lalm;
377 recGblSetSevr(prec,
UDF_ALARM, prec->udfs);
388 if (asev && (val >= alev || ((lalm == alev) && (val >= alev - hyst)))) {
397 if (asev && (val <= alev || ((lalm == alev) && (val <= alev + hyst)))) {
406 if (asev && (val >= alev || ((lalm == alev) && (val >= alev - hyst)))) {
415 if (asev && (val <= alev || ((lalm == alev) && (val <= alev + hyst)))) {
416 if (recGblSetSevr(prec,
LOW_ALARM, asev))
426 static long fetch_value(aoRecord *
prec,
double *pvalue)
431 save_pact =
prec->pact;
438 prec->pact = save_pact;
445 if (
prec->oif == aoOIF_Incremental)
446 *pvalue +=
prec->val;
451 static void convert(aoRecord *
prec,
double value)
455 if (value >
prec->drvh)
465 if (
prec->oroc != 0){
468 diff = value -
prec->oval;
470 if (
prec->oroc < -diff)
472 }
else if (
prec->oroc < diff)
479 switch (
prec->linr) {
480 case menuConvertNO_CONVERSION:
482 case menuConvertLINEAR:
483 case menuConvertSLOPE:
484 if (
prec->eslo == 0.0) value = 0;
485 else value = (value -
prec->eoff) /
prec->eslo;
489 (
void *)&
prec->pbrk, &
prec->lbrk) != 0) {
495 if (
prec->aslo != 0) value /=
prec->aslo;
500 if (value >= (0x7fffffff - 0.5))
501 prec->rval = 0x7fffffff;
505 if (value > (0.5 - 0x80000000))
508 prec->rval = 0x80000000;
513 static void monitor(aoRecord *
prec)
515 unsigned monitor_mask = recGblResetAlarms(prec);
518 recGblCheckDeadband(&prec->mlst, prec->val, prec->mdel, &monitor_mask,
DBE_VALUE);
521 recGblCheckDeadband(&prec->alst, prec->val, prec->adel, &monitor_mask,
DBE_ARCHIVE);
525 db_post_events(prec,&prec->val,monitor_mask);
531 db_post_events(prec,&prec->oval,monitor_mask);
532 if(prec->oraw != prec->rval) {
533 db_post_events(prec,&prec->rval,
535 prec->oraw = prec->rval;
537 if(prec->orbv != prec->rbv) {
538 db_post_events(prec,&prec->rbv,
540 prec->orbv = prec->rbv;
546 static long writeValue(aoRecord *
prec)
548 aodset *pdset = (aodset *) prec->dset;
552 status = recGblGetSimm((dbCommon *)prec, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
556 switch (prec->simm) {
558 status = pdset->write_ao(prec);
563 if (prec->pact || (prec->sdly < 0.)) {
567 epicsCallback *pvt = prec->simpvt;
569 pvt = calloc(1,
sizeof(epicsCallback));
572 if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
Miscellaneous macro definitions.
#define get_control_double
epicsShareFunc long cvtEngToRawBpt(double *pval, short linr, short init, void **ppbrk, short *plbrk)
epicsShareFunc long cvtRawToEngBpt(double *pval, short linr, short init, void **ppbrk, short *plbrk)
#define get_graphic_double
epicsExportAddress(rset, aoRSET)