This is Unofficial EPICS BASE Doxygen Site
devAiSoftCallback.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /* devAiSoftCallback.c */
10 /*
11  * Authors: Marty Kraimer & Andrew Johnson
12  */
13 
14 #include <stdlib.h>
15 #include <stdio.h>
16 
17 #include "alarm.h"
18 #include "callback.h"
19 #include "cantProceed.h"
20 #include "dbCommon.h"
21 #include "dbDefs.h"
22 #include "dbAccess.h"
23 #include "dbChannel.h"
24 #include "dbNotify.h"
25 #include "epicsAssert.h"
26 #include "epicsMath.h"
27 #include "recGbl.h"
28 #include "recSup.h"
29 #include "devSup.h"
30 #include "link.h"
31 #include "aiRecord.h"
32 #include "epicsExport.h"
33 
34 
35 #define GET_OPTIONS (DBR_STATUS | DBR_TIME)
36 
37 typedef struct devPvt {
38  processNotify pn;
39  epicsCallback callback;
40  long options;
41  int status;
42  int smooth;
43  struct {
44  DBRstatus
45  DBRtime
47  } buffer;
48 } devPvt;
49 
50 
51 static void getCallback(processNotify *ppn, notifyGetType type)
52 {
53  aiRecord *prec = (aiRecord *)ppn->usrPvt;
54  devPvt *pdevPvt = (devPvt *)prec->dpvt;
55  long no_elements = 1;
56 
57  if (ppn->status == notifyCanceled) {
58  printf("devAiSoftCallback::getCallback notifyCanceled\n");
59  return;
60  }
61 
62  assert(type == getFieldType);
63  pdevPvt->status = dbChannelGetField(ppn->chan, DBR_DOUBLE,
64  &pdevPvt->buffer, &pdevPvt->options, &no_elements, 0);
65 }
66 
67 static void doneCallback(processNotify *ppn)
68 {
69  aiRecord *prec = (aiRecord *)ppn->usrPvt;
70  devPvt *pdevPvt = (devPvt *)prec->dpvt;
71 
72  callbackRequestProcessCallback(&pdevPvt->callback, prec->prio, prec);
73 }
74 
75 static long add_record(dbCommon *pcommon)
76 {
77  aiRecord *prec = (aiRecord *)pcommon;
78  DBLINK *plink = &prec->inp;
79  dbChannel *chan;
80  devPvt *pdevPvt;
81  processNotify *ppn;
82 
83  if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
84  return 0;
85 
86  if (plink->type != PV_LINK) {
87  long status = S_db_badField;
88 
89  recGblRecordError(status, (void *)prec,
90  "devAiSoftCallback (add_record) Illegal INP field");
91  return status;
92  }
93 
94  chan = dbChannelCreate(plink->value.pv_link.pvname);
95  if (!chan) {
96  long status = S_db_notFound;
97 
98  recGblRecordError(status, (void *)prec,
99  "devAiSoftCallback (add_record) link target not found");
100  return status;
101  }
102 
103  pdevPvt = calloc(1, sizeof(*pdevPvt));
104  if (!pdevPvt) {
105  long status = S_db_noMemory;
106 
107  recGblRecordError(status, (void *)prec,
108  "devAiSoftCallback (add_record) out of memory, calloc() failed");
109  return status;
110  }
111  ppn = &pdevPvt->pn;
112 
113  plink->type = PN_LINK;
114  plink->value.pv_link.pvlMask &= pvlOptMsMode; /* Severity flags only */
115 
116  ppn->usrPvt = prec;
117  ppn->chan = chan;
118  ppn->getCallback = getCallback;
119  ppn->doneCallback = doneCallback;
120  ppn->requestType = processGetRequest;
121 
122  pdevPvt->options = GET_OPTIONS;
123 
124  prec->dpvt = pdevPvt;
125  return 0;
126 }
127 
128 static long del_record(dbCommon *pcommon) {
129  aiRecord *prec = (aiRecord *)pcommon;
130  DBLINK *plink = &prec->inp;
131  devPvt *pdevPvt = (devPvt *)prec->dpvt;
132 
133  if (dbLinkIsDefined(plink) && dbLinkIsConstant(plink))
134  return 0;
135 
136  assert(plink->type == PN_LINK);
137 
138  dbNotifyCancel(&pdevPvt->pn);
139  dbChannelDelete(pdevPvt->pn.chan);
140  free(pdevPvt);
141 
142  plink->type = PV_LINK;
143  return 0;
144 }
145 
146 static struct dsxt dsxtSoftCallback = {
148 };
149 
150 static long init(int pass)
151 {
152  if (pass == 0) devExtend(&dsxtSoftCallback);
153  return 0;
154 }
155 
156 static long init_record(dbCommon *pcommon)
157 {
158  aiRecord *prec = (aiRecord *)pcommon;
159 
160  if (recGblInitConstantLink(&prec->inp, DBF_DOUBLE, &prec->val))
161  prec->udf = FALSE;
162 
163  return 0;
164 }
165 
166 static long read_ai(aiRecord *prec)
167 {
168  devPvt *pdevPvt = (devPvt *)prec->dpvt;
169 
170  if (!prec->dpvt)
171  return 2;
172 
173  if (!prec->pact) {
174  dbProcessNotify(&pdevPvt->pn);
175  prec->pact = TRUE;
176  return 0;
177  }
178 
179  if (pdevPvt->status) {
180  recGblSetSevr(prec, READ_ALARM, INVALID_ALARM);
181  pdevPvt->smooth = FALSE;
182  return 2;
183  }
184 
185  /* Apply smoothing algorithm */
186  if (prec->smoo != 0.0 && pdevPvt->smooth && finite(prec->val))
187  prec->val = prec->val * prec->smoo +
188  pdevPvt->buffer.value * (1.0 - prec->smoo);
189  else
190  prec->val = pdevPvt->buffer.value;
191 
192  prec->udf = FALSE;
193  pdevPvt->smooth = TRUE;
194 
195  switch (prec->inp.value.pv_link.pvlMask & pvlOptMsMode) {
196  case pvlOptNMS:
197  break;
198  case pvlOptMSI:
199  if (pdevPvt->buffer.severity < INVALID_ALARM)
200  break;
201  /* else fall through */
202  case pvlOptMS:
203  recGblSetSevr(prec, LINK_ALARM, pdevPvt->buffer.severity);
204  break;
205  case pvlOptMSS:
206  recGblSetSevr(prec, pdevPvt->buffer.status,
207  pdevPvt->buffer.severity);
208  break;
209  }
210 
211  if (dbLinkIsConstant(&prec->tsel) &&
212  prec->tse == epicsTimeEventDeviceTime)
213  prec->time = pdevPvt->buffer.time;
214 
215  return 2;
216 }
217 
219  {6, NULL, init, init_record, NULL},
220  read_ai, NULL
221 };
Definition: devSup.h:117
epicsCallback callback
struct devPvt devPvt
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
#define FALSE
Definition: dbDefs.h:32
#define GET_OPTIONS
double epicsFloat64
Definition: epicsTypes.h:49
#define READ_ALARM
Definition: alarm.h:92
An EPICS-specific replacement for ANSI C&#39;s assert.
void devExtend(dsxt *pdsxt)
Definition: dbStaticRun.c:60
aidset devAiSoftCallback
#define init_record
#define printf
Definition: epicsStdio.h:41
pvd::StructureConstPtr type
#define NULL
Definition: catime.c:38
Miscellaneous macro definitions.
epicsExportAddress(dset, devAiSoftCallback)
struct devPvt::@2 buffer
Device support routines.
Definition: devSup.h:140
#define epicsTimeEventDeviceTime
Definition: epicsTime.h:362
long(* add_record)(struct dbCommon *precord)
Definition: devSup.h:122
#define DBR_DOUBLE
Definition: db_access.h:76
#define LINK_ALARM
Definition: alarm.h:105
processNotify pn
DBRstatus DBRtime epicsFloat64 value
long(* del_record)(struct dbCommon *precord)
Definition: devSup.h:127
#define TRUE
Definition: dbDefs.h:27
if(yy_init)
Definition: scan.c:972
Routines for code that can&#39;t continue or return after an error.
#define finite(x)
Definition: epicsMath.h:16
int prec
Definition: reader.c:29
struct pv_link pv_link
Definition: link.h:178
#define INVALID_ALARM
Definition: alarm.h:53
Exporting IOC objects.