This is Unofficial EPICS BASE Doxygen Site
subArrayRecord.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 Lawrence Berkeley Laboratory,The Control Systems
3 * Group, Systems Engineering Department
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 /* recSubArray.c - Record Support Routines for SubArray records
9  *
10  *
11  * Author: Carl Lionberger
12  * Date: 090293
13  *
14  * NOTES:
15  * Derived from waveform record.
16  * Modification Log:
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 "alarm.h"
29 #include "dbAccess.h"
30 #include "dbEvent.h"
31 #include "dbFldTypes.h"
32 #include "dbScan.h"
33 #include "devSup.h"
34 #include "errMdef.h"
35 #include "recSup.h"
36 #include "recGbl.h"
37 #include "cantProceed.h"
38 
39 #define GEN_SIZE_OFFSET
40 #include "subArrayRecord.h"
41 #undef GEN_SIZE_OFFSET
42 #include "epicsExport.h"
43 
44 /* Create RSET - Record Support Entry Table*/
45 #define report NULL
46 #define initialize NULL
47 static long init_record(struct dbCommon *prec, int pass);
48 static long process(struct dbCommon *prec);
49 #define special NULL
50 #define get_value NULL
51 static long cvt_dbaddr(DBADDR *paddr);
52 static long get_array_info(DBADDR *paddr, long *no_elements, long *offset);
53 static long put_array_info(DBADDR *paddr, long nNew);
54 static long get_units(DBADDR *paddr, char *units);
55 static long get_precision(const DBADDR *paddr, long *precision);
56 #define get_enum_str NULL
57 #define get_enum_strs NULL
58 #define put_enum_str NULL
59 static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd);
60 static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd);
61 #define get_alarm_double NULL
62 
64  RSETNUMBER,
65  report,
66  initialize,
68  process,
69  special,
70  get_value,
71  cvt_dbaddr,
74  get_units,
82 };
83 epicsExportAddress(rset,subArrayRSET);
84 
85 static void monitor(subArrayRecord *prec);
86 static long readValue(subArrayRecord *prec);
87 
88 
89 static long init_record(struct dbCommon *pcommon, int pass)
90 {
91  struct subArrayRecord *prec = (struct subArrayRecord *)pcommon;
92  sadset *pdset;
93 
94  if (pass==0){
95  if (prec->malm <= 0)
96  prec->malm = 1;
97  if (prec->ftvl > DBF_ENUM)
98  prec->ftvl = DBF_UCHAR;
99  prec->bptr = callocMustSucceed(prec->malm, dbValueSize(prec->ftvl),
100  "subArrayRecord calloc failed");
101  prec->nord = 0;
102  if (prec->nelm > prec->malm)
103  prec->nelm = prec->malm;
104  return 0;
105  }
106 
107  /* must have dset defined */
108  if (!(pdset = (sadset *)(prec->dset))) {
109  recGblRecordError(S_dev_noDSET,(void *)prec,"sa: init_record");
110  return S_dev_noDSET;
111  }
112 
113  /* must have read_sa function defined */
114  if ( (pdset->common.number < 5) || (pdset->read_sa == NULL) ) {
115  recGblRecordError(S_dev_missingSup,(void *)prec,"sa: init_record");
116  return S_dev_missingSup;
117  }
118 
119  if (pdset->common.init_record)
120  return pdset->common.init_record(pcommon);
121 
122  return 0;
123 }
124 
125 static long process(struct dbCommon *pcommon)
126 {
127  struct subArrayRecord *prec = (struct subArrayRecord *)pcommon;
128  sadset *pdset = (sadset *)(prec->dset);
129  long status;
130  unsigned char pact=prec->pact;
131 
132  if ((pdset==NULL) || (pdset->read_sa==NULL)) {
133  prec->pact=TRUE;
134  recGblRecordError(S_dev_missingSup, (void *)prec, "read_sa");
135  return S_dev_missingSup;
136  }
137 
138  if (pact && prec->busy) return 0;
139 
140  status=readValue(prec); /* read the new value */
141  if (!pact && prec->pact) return 0;
142  prec->pact = TRUE;
143 
144  recGblGetTimeStamp(prec);
145 
146  prec->udf = !!status; /* 0 or 1 */
147  if (status)
148  recGblSetSevr(prec, UDF_ALARM, prec->udfs);
149 
150  monitor(prec);
151 
152  /* process the forward scan link record */
153  recGblFwdLink(prec);
154 
155  prec->pact=FALSE;
156  return 0;
157 }
158 
159 static long cvt_dbaddr(DBADDR *paddr)
160 {
161  subArrayRecord *prec = (subArrayRecord *) paddr->precord;
162 
163  paddr->pfield = prec->bptr;
164  paddr->no_elements = prec->malm;
165  paddr->field_type = prec->ftvl;
166  paddr->field_size = dbValueSize(prec->ftvl);
167  paddr->dbr_field_type = prec->ftvl;
168 
169  return 0;
170 }
171 
172 static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
173 {
174  subArrayRecord *prec = (subArrayRecord *) paddr->precord;
175 
176  if (prec->udf)
177  *no_elements = 0;
178  else
179  *no_elements = prec->nord;
180  *offset = 0;
181 
182  return 0;
183 }
184 
185 static long put_array_info(DBADDR *paddr, long nNew)
186 {
187  subArrayRecord *prec = (subArrayRecord *) paddr->precord;
188  epicsUInt32 nord = prec->nord;
189 
190  prec->nord = nNew;
191  if (prec->nord > prec->malm)
192  prec->nord = prec->malm;
193 
194  if (nord != prec->nord)
195  db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
196  return 0;
197 }
198 
199 #define indexof(field) subArrayRecord##field
200 
201 static long get_units(DBADDR *paddr, char *units)
202 {
203  subArrayRecord *prec = (subArrayRecord *) paddr->precord;
204 
205  switch (dbGetFieldIndex(paddr)) {
206  case indexof(VAL):
207  if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
208  break;
209  case indexof(HOPR):
210  case indexof(LOPR):
211  strncpy(units,prec->egu,DB_UNITS_SIZE);
212  }
213  return 0;
214 }
215 
216 static long get_precision(const DBADDR *paddr, long *precision)
217 {
218  subArrayRecord *prec = (subArrayRecord *) paddr->precord;
219 
220  *precision = prec->prec;
221  if (dbGetFieldIndex(paddr) != indexof(VAL))
222  recGblGetPrec(paddr, precision);
223  return 0;
224 }
225 
226 static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
227 {
228  subArrayRecord *prec = (subArrayRecord *) paddr->precord;
229 
230  switch (dbGetFieldIndex(paddr)) {
231  case indexof(VAL):
232  pgd->upper_disp_limit = prec->hopr;
233  pgd->lower_disp_limit = prec->lopr;
234  break;
235  case indexof(INDX):
236  pgd->upper_disp_limit = prec->malm - 1;
237  pgd->lower_disp_limit = 0;
238  break;
239  case indexof(NELM):
240  pgd->upper_disp_limit = prec->malm;
241  pgd->lower_disp_limit = 0;
242  break;
243  case indexof(NORD):
244  pgd->upper_disp_limit = prec->malm;
245  pgd->lower_disp_limit = 0;
246  break;
247  case indexof(BUSY):
248  pgd->upper_disp_limit = 1;
249  pgd->lower_disp_limit = 0;
250  break;
251  default:
252  recGblGetGraphicDouble(paddr, pgd);
253  }
254  return 0;
255 }
256 
257 static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
258 {
259  subArrayRecord *prec = (subArrayRecord *) paddr->precord;
260 
261  switch (dbGetFieldIndex(paddr)) {
262  case indexof(VAL):
263  pcd->upper_ctrl_limit = prec->hopr;
264  pcd->lower_ctrl_limit = prec->lopr;
265  break;
266  case indexof(INDX):
267  pcd->upper_ctrl_limit = prec->malm - 1;
268  pcd->lower_ctrl_limit = 0;
269  break;
270  case indexof(NELM):
271  pcd->upper_ctrl_limit = prec->malm;
272  pcd->lower_ctrl_limit = 1;
273  break;
274  case indexof(NORD):
275  pcd->upper_ctrl_limit = prec->malm;
276  pcd->lower_ctrl_limit = 0;
277  break;
278  case indexof(BUSY):
279  pcd->upper_ctrl_limit = 1;
280  pcd->lower_ctrl_limit = 0;
281  break;
282  default:
283  recGblGetControlDouble(paddr, pcd);
284  }
285  return 0;
286 }
287 
288 static void monitor(subArrayRecord *prec)
289 {
290  unsigned short monitor_mask;
291 
292  monitor_mask = recGblResetAlarms(prec);
293  monitor_mask |= (DBE_LOG|DBE_VALUE);
294 
295  db_post_events(prec, prec->bptr, monitor_mask);
296 
297  return;
298 }
299 
300 static long readValue(subArrayRecord *prec)
301 {
302  long status;
303  sadset *pdset = (sadset *) (prec->dset);
304 
305  if (prec->nelm > prec->malm)
306  prec->nelm = prec->malm;
307 
308  if (prec->indx >= prec->malm)
309  prec->indx = prec->malm - 1;
310 
311  status = (*pdset->read_sa)(prec);
312 
313  if (prec->nord <= 0)
314  status = -1;
315 
316  return status;
317 }
#define RSETNUMBER
Definition: recSup.h:92
#define get_alarm_double
#define FALSE
Definition: dbDefs.h:32
pvd::Status status
#define init_record
#define S_dev_missingSup
Definition: devSup.h:170
#define NULL
Definition: catime.c:38
unsigned int epicsUInt32
Definition: epicsTypes.h:43
Miscellaneous macro definitions.
rset subArrayRSET
#define indexof(field)
#define get_control_double
Definition: biRecord.c:58
epicsExportAddress(rset, subArrayRSET)
#define DBE_VALUE
Definition: caeventmask.h:38
#define get_array_info
Definition: aiRecord.c:56
Device support routines.
#define DBE_LOG
Definition: caeventmask.h:40
#define get_units
Definition: biRecord.c:52
#define get_enum_str
LIBCOM_API void * callocMustSucceed(size_t count, size_t size, const char *msg)
A calloc() that never returns NULL.
Definition: cantProceed.c:22
#define get_precision
Definition: biRecord.c:53
#define put_array_info
Definition: aiRecord.c:57
#define get_value
#define TRUE
Definition: dbDefs.h:27
if(yy_init)
Definition: scan.c:972
Definition: recSup.h:67
Routines for code that can&#39;t continue or return after an error.
#define initialize
int prec
Definition: reader.c:29
#define report
#define get_graphic_double
Definition: biRecord.c:57
#define cvt_dbaddr
Definition: aiRecord.c:55
#define special
#define put_enum_str
#define get_enum_strs
#define S_dev_noDSET
Definition: devSup.h:169
#define UDF_ALARM
Definition: alarm.h:108
Exporting IOC objects.