This is Unofficial EPICS BASE Doxygen Site
dfanoutRecord.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 Southeastern Universities Research Association, as
3 * Operator of Thomas Jefferson National Accelerator Facility.
4 * EPICS BASE is distributed subject to a Software License Agreement found
5 * in file LICENSE that is included with this distribution.
6 \*************************************************************************/
7 
8 /* recDfanout.c - Record Support Routines for Dfanout records */
9 /*
10  * Original Author: Matt Bickley (Sometime in 1994)
11  *
12  * Modification Log:
13  * -----------------
14  * .01 1994 mhb Started with longout record to make the data fanout
15  * .02 May 10, 96 jt Bug Fix
16  * .03 11SEP2000 mrk LONG=>DOUBLE, add SELL,SELN,SELM
17  */
18 
19 
20 #include <stddef.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "dbDefs.h"
27 #include "epicsPrint.h"
28 #include "epicsMath.h"
29 #include "alarm.h"
30 #include "dbAccess.h"
31 #include "dbEvent.h"
32 #include "dbFldTypes.h"
33 #include "devSup.h"
34 #include "errMdef.h"
35 #include "recSup.h"
36 #include "recGbl.h"
37 #include "special.h"
38 #include "menuOmsl.h"
39 
40 #define GEN_SIZE_OFFSET
41 #include "dfanoutRecord.h"
42 #undef GEN_SIZE_OFFSET
43 #include "epicsExport.h"
44 
45 /* Create RSET - Record Support Entry Table*/
46 #define report NULL
47 #define initialize NULL
48 static long init_record(struct dbCommon *, int);
49 static long process(struct dbCommon *);
50 #define special NULL
51 #define get_value NULL
52 #define cvt_dbaddr NULL
53 #define get_array_info NULL
54 #define put_array_info NULL
55 static long get_units(DBADDR *, char *);
56 static long get_precision(const DBADDR *, long *);
57 #define get_enum_str NULL
58 #define get_enum_strs NULL
59 #define put_enum_str NULL
60 static long get_graphic_double(DBADDR *,struct dbr_grDouble *);
61 static long get_control_double(DBADDR *,struct dbr_ctrlDouble *);
62 static long get_alarm_double(DBADDR *,struct dbr_alDouble *);
63 
65  RSETNUMBER,
66  report,
67  initialize,
69  process,
70  special,
71  get_value,
72  cvt_dbaddr,
75  get_units,
83 };
84 epicsExportAddress(rset,dfanoutRSET);
85 
86 
87 static void checkAlarms(dfanoutRecord *);
88 static void monitor(dfanoutRecord *);
89 static void push_values(dfanoutRecord *);
90 
91 #define OUT_ARG_MAX 8
92 
93 
94 static long init_record(struct dbCommon *pcommon, int pass)
95 {
96  struct dfanoutRecord *prec = (struct dfanoutRecord *)pcommon;
97  if (pass==0)
98  return 0;
99 
100  recGblInitConstantLink(&prec->sell, DBF_USHORT, &prec->seln);
101 
102  /* get the initial value dol is a constant*/
103  if (recGblInitConstantLink(&prec->dol, DBF_DOUBLE, &prec->val))
104  prec->udf = isnan(prec->val);
105 
106  return 0;
107 }
108 
109 static long process(struct dbCommon *pcommon)
110 {
111  struct dfanoutRecord *prec = (struct dfanoutRecord *)pcommon;
112  long status=0;
113 
114  if (!prec->pact &&
115  !dbLinkIsConstant(&prec->dol) &&
116  prec->omsl == menuOmslclosed_loop) {
117  status = dbGetLink(&prec->dol, DBR_DOUBLE, &prec->val, 0, 0);
118  if (!dbLinkIsConstant(&prec->dol) && !status)
119  prec->udf = isnan(prec->val);
120  }
121  prec->pact = TRUE;
122  recGblGetTimeStamp(prec);
123  /* Push out the data to all the forward links */
124  dbGetLink(&(prec->sell),DBR_USHORT,&(prec->seln),0,0);
125  checkAlarms(prec);
126  push_values(prec);
127  monitor(prec);
128  recGblFwdLink(prec);
129  prec->pact=FALSE;
130  return(status);
131 }
132 
133 #define indexof(field) dfanoutRecord##field
134 
135 static long get_units(DBADDR *paddr,char *units)
136 {
137  dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
138 
139  if(paddr->pfldDes->field_type == DBF_DOUBLE) {
140  strncpy(units,prec->egu,DB_UNITS_SIZE);
141  }
142  return(0);
143 }
144 
145 static long get_precision(const DBADDR *paddr,long *precision)
146 {
147  dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
148 
149  *precision = prec->prec;
150  if (dbGetFieldIndex(paddr) == indexof(VAL)) return(0);
151  recGblGetPrec(paddr,precision);
152  return(0);
153 }
154 
155 static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
156 {
157  dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
158 
159  switch (dbGetFieldIndex(paddr)) {
160  case indexof(VAL):
161  case indexof(HIHI):
162  case indexof(HIGH):
163  case indexof(LOW):
164  case indexof(LOLO):
165  case indexof(LALM):
166  case indexof(ALST):
167  case indexof(MLST):
168  pgd->upper_disp_limit = prec->hopr;
169  pgd->lower_disp_limit = prec->lopr;
170  break;
171  default:
172  recGblGetGraphicDouble(paddr,pgd);
173  }
174  return(0);
175 }
176 
177 static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
178 {
179  dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
180 
181  switch (dbGetFieldIndex(paddr)) {
182  case indexof(VAL):
183  case indexof(LALM):
184  case indexof(ALST):
185  case indexof(MLST):
186  pcd->upper_ctrl_limit = prec->hopr;
187  pcd->lower_ctrl_limit = prec->lopr;
188  break;
189  default:
190  recGblGetControlDouble(paddr,pcd);
191  }
192  return(0);
193 }
194 static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
195 {
196  dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
197 
198  if(dbGetFieldIndex(paddr) == indexof(VAL)) {
199  pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
200  pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
201  pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
202  pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN;
203  } else recGblGetAlarmDouble(paddr,pad);
204  return(0);
205 }
206 
207 static void checkAlarms(dfanoutRecord *prec)
208 {
209  double val, hyst, lalm;
210  double alev;
211  epicsEnum16 asev;
212 
213  if (prec->udf) {
214  recGblSetSevr(prec, UDF_ALARM, prec->udfs);
215  return;
216  }
217 
218  val = prec->val;
219  hyst = prec->hyst;
220  lalm = prec->lalm;
221 
222  /* alarm condition hihi */
223  asev = prec->hhsv;
224  alev = prec->hihi;
225  if (asev && (val >= alev || ((lalm == alev) && (val >= alev - hyst)))) {
226  if (recGblSetSevr(prec, HIHI_ALARM, asev))
227  prec->lalm = alev;
228  return;
229  }
230 
231  /* alarm condition lolo */
232  asev = prec->llsv;
233  alev = prec->lolo;
234  if (asev && (val <= alev || ((lalm == alev) && (val <= alev + hyst)))) {
235  if (recGblSetSevr(prec, LOLO_ALARM, asev))
236  prec->lalm = alev;
237  return;
238  }
239 
240  /* alarm condition high */
241  asev = prec->hsv;
242  alev = prec->high;
243  if (asev && (val >= alev || ((lalm == alev) && (val >= alev - hyst)))) {
244  if (recGblSetSevr(prec, HIGH_ALARM, asev))
245  prec->lalm = alev;
246  return;
247  }
248 
249  /* alarm condition low */
250  asev = prec->lsv;
251  alev = prec->low;
252  if (asev && (val <= alev || ((lalm == alev) && (val <= alev + hyst)))) {
253  if (recGblSetSevr(prec, LOW_ALARM, asev))
254  prec->lalm = alev;
255  return;
256  }
257 
258  /* we get here only if val is out of alarm by at least hyst */
259  prec->lalm = val;
260  return;
261 }
262 
263 static void monitor(dfanoutRecord *prec)
264 {
265  unsigned monitor_mask = recGblResetAlarms(prec);
266 
267  /* check for value change */
268  recGblCheckDeadband(&prec->mlst, prec->val, prec->mdel, &monitor_mask, DBE_VALUE);
269 
270  /* check for archive change */
271  recGblCheckDeadband(&prec->alst, prec->val, prec->adel, &monitor_mask, DBE_ARCHIVE);
272 
273  /* send out monitors connected to the value field */
274  if (monitor_mask){
275  db_post_events(prec,&prec->val,monitor_mask);
276  }
277 
278  return;
279 }
280 
281 static void push_values(dfanoutRecord *prec)
282 {
283  struct link *plink; /* structure of the link field */
284  int i;
285  long status;
286  unsigned short state;
287 
288  switch (prec->selm){
289  case (dfanoutSELM_All):
290  for(i=0, plink=&(prec->outa); i<OUT_ARG_MAX; i++, plink++) {
291  status=dbPutLink(plink,DBR_DOUBLE,&(prec->val),1);
292  if(status) recGblSetSevr(prec,LINK_ALARM,MAJOR_ALARM);
293  }
294  break;
295  case (dfanoutSELM_Specified):
296  if(prec->seln>OUT_ARG_MAX) {
297  recGblSetSevr(prec,SOFT_ALARM,INVALID_ALARM);
298  break;
299  }
300  if(prec->seln==0) break;
301  plink=&(prec->outa);
302  plink += (prec->seln -1);
303  status=dbPutLink(plink,DBR_DOUBLE,&(prec->val),1);
304  if(status) recGblSetSevr(prec,LINK_ALARM,MAJOR_ALARM);
305  break;
306  case (dfanoutSELM_Mask):
307  if(prec->seln==0) break;
308  for(i=0, plink=&(prec->outa), state=prec->seln;
309  i<OUT_ARG_MAX;
310  i++, plink++, state>>=1) {
311  if(state&1) {
312  status=dbPutLink(plink,DBR_DOUBLE,&(prec->val),1);
313  if(status) recGblSetSevr(prec,LINK_ALARM,MAJOR_ALARM);
314  }
315  }
316  break;
317  default:
318  recGblSetSevr(prec,SOFT_ALARM,INVALID_ALARM);
319  }
320 
321 }
#define HIHI_ALARM
Definition: alarm.h:94
#define RSETNUMBER
Definition: recSup.h:92
#define report
Definition: dfanoutRecord.c:46
#define FALSE
Definition: dbDefs.h:32
pvd::Status status
#define MAJOR_ALARM
Definition: alarm.h:52
int i
Definition: scan.c:967
#define DBR_USHORT
Definition: dbFldTypes.h:80
#define init_record
#define SOFT_ALARM
Definition: alarm.h:106
rset dfanoutRSET
Definition: dfanoutRecord.c:64
#define indexof(field)
Miscellaneous macro definitions.
#define DBE_ARCHIVE
Definition: caeventmask.h:39
#define OUT_ARG_MAX
Definition: dfanoutRecord.c:91
#define get_control_double
Definition: biRecord.c:58
#define DBE_VALUE
Definition: caeventmask.h:38
#define HIGH_ALARM
Definition: alarm.h:95
Device support routines.
#define isnan(x)
Definition: epicsMath.h:21
#define get_units
Definition: biRecord.c:52
#define DBR_DOUBLE
Definition: db_access.h:76
#define get_value
Definition: dfanoutRecord.c:51
#define LINK_ALARM
Definition: alarm.h:105
#define initialize
Definition: dfanoutRecord.c:47
float epicsNAN
Definition: epicsMath.cpp:35
epicsUInt16 epicsEnum16
Definition: epicsTypes.h:47
#define get_precision
Definition: biRecord.c:53
#define put_array_info
Definition: dfanoutRecord.c:54
#define TRUE
Definition: dbDefs.h:27
epicsExportAddress(rset, dfanoutRSET)
#define put_enum_str
Definition: dfanoutRecord.c:59
#define cvt_dbaddr
Definition: dfanoutRecord.c:52
if(yy_init)
Definition: scan.c:972
Definition: recSup.h:67
#define get_array_info
Definition: dfanoutRecord.c:53
int prec
Definition: reader.c:29
#define INVALID_ALARM
Definition: alarm.h:53
#define LOLO_ALARM
Definition: alarm.h:96
#define LOW_ALARM
Definition: alarm.h:97
#define get_graphic_double
Definition: biRecord.c:57
#define special
Definition: dfanoutRecord.c:50
#define get_enum_str
Definition: dfanoutRecord.c:57
#define get_alarm_double
Definition: aaiRecord.c:69
#define UDF_ALARM
Definition: alarm.h:108
Exporting IOC objects.
#define get_enum_strs
Definition: dfanoutRecord.c:58