mrfioc2  2.3.0
asub.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * Copyright (c) 2015 Paul Scherrer Institute (PSI), Villigen, Switzerland
5 * mrfioc2 is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 /*
9  * Author: Michael Davidsaver <mdavidsaver@gmail.com>
10  */
11 
12 #include <math.h>
13 #include <string.h>
14 
15 #include <dbDefs.h>
16 #include <errlog.h>
17 #include <recGbl.h>
18 #include <alarm.h>
19 #include <dbAccess.h>
20 
21 #include <registryFunction.h>
22 
23 #include <menuFtype.h>
24 #include <aSubRecord.h>
25 #include <epicsExport.h>
26 
27 #define NINPUTS (aSubRecordU - aSubRecordA)
28 
29 static
30 long select_string(aSubRecord *prec)
31 {
32  unsigned i;
33  char *out = prec->vala;
34  DBLINK *L = &prec->inpa;
35  const char **I = (const char**)&prec->a;
36 
37  /* find the first input w/o an active alarm */
38  for(i=0; i<NINPUTS; i++) {
39  epicsEnum16 sevr, stat;
40  if(L[i].type==CONSTANT)
41  continue;
42  if(dbGetAlarm(&L[i], &stat, &sevr))
43  continue;
44  if(sevr!=NO_ALARM)
45  continue;
46  memcpy(out, I[i], MAX_STRING_SIZE);
47  return 0;
48  }
49 
50  out[0] = '\0';
51  (void)recGblSetSevr(prec, READ_ALARM, INVALID_ALARM);
52  return 0;
53 }
54 
67 static
68 long gen_timeline(aSubRecord *prec)
69 {
70  double x0, dx;
71  epicsUInt32 count, i;
72  double *result;
73 
74  if (prec->fta != menuFtypeDOUBLE
75  || prec->ftb != menuFtypeDOUBLE
76  || prec->ftc != menuFtypeLONG
77  ) {
78  errlogPrintf("%s incorrect input type. A,B (DOUBLE), C (LONG)",
79  prec->name);
80  return -1;
81  }
82 
83  if (prec->ftva != menuFtypeDOUBLE
84  ) {
85  errlogPrintf("%s incorrect output type. OUTA (DOUBLE)",
86  prec->name);
87  return -1;
88  }
89 
90  if (prec->nova < 1)
91  {
92  errlogPrintf("%s output size too small. OUTA (>=1)",
93  prec->name);
94  return -1;
95  }
96 
97  x0=*(double*)prec->a;
98  dx=*(double*)prec->b;
99  count=*(epicsUInt32*)prec->c;
100  result=prec->vala;
101 
102  if (count>prec->nova)
103  count=prec->nova;
104 
105  result[0]=x0;
106  for (i=1; i<count; i++) {
107  result[i]=result[i-1]+dx;
108  }
109 
110  prec->neva = count;
111 
112  return 0;
113 }
114 
130 static
131 long gen_delaygen(aSubRecord *prec)
132 {
133  double delay, width, egupertick;
134  epicsUInt32 count, i, mult;
135  unsigned char *result;
136  epicsUInt32 idelay, iwidth;
137 
138  if (prec->fta != menuFtypeDOUBLE
139  || prec->ftb != menuFtypeDOUBLE
140  || prec->ftc != menuFtypeDOUBLE
141  || prec->ftd != menuFtypeLONG
142  ) {
143  errlogPrintf("%s incorrect input type. A,B,C (DOUBLE) D (LONG)",
144  prec->name);
145  return -1;
146  }
147 
148  if (prec->ftva != menuFtypeUCHAR
149  ) {
150  errlogPrintf("%s incorrect output type. OUTA (DOUBLE)",
151  prec->name);
152  return -1;
153  }
154 
155  delay=*(double*)prec->a;
156  width=*(double*)prec->b;
157  egupertick=*(double*)prec->c;
158  mult=*(epicsUInt32*)prec->d;
159  result=prec->vala;
160  count=prec->nova;
161 
162  if(mult==0)
163  mult=1;
164 
165  idelay=(epicsInt32)(0.5 + delay/egupertick);
166  iwidth=(epicsInt32)(0.5 + width/egupertick);
167 
168  if(idelay>=count) {
169  errlogPrintf("%s : invalid delay %d check units\n",prec->name,idelay);
170  return -1;
171  } else if(iwidth>=count) {
172  errlogPrintf("%s : invalid delay %d check units\n",prec->name,iwidth);
173  return -1;
174  } else if(idelay+iwidth>=count) {
175  errlogPrintf("%s : delay+width is too long\n",prec->name);
176  return -1;
177  }
178 
179  for (i=0; i<count; i++) {
180  if(i<idelay) {
181  result[i]=0;
182  } else if(i<idelay+iwidth) {
183  result[i]=1;
184  } else {
185  /* ensure last element is 0 */
186  result[i]=0;
187  if (i%mult==mult-1) {
188  i++;
189  break;
190  }
191  }
192  }
193 
194  prec->neva = i;
195 
196  return 0;
197 }
198 
215 static
216 long gen_bitarraygen(aSubRecord *prec)
217 {
218  epicsEnum16 *intype=&prec->fta;
219  epicsUInt16 **indata=(epicsUInt16 **)&prec->a;
220  epicsUInt32 *inlen=&prec->noa;
221 
222  epicsUInt32 outlen=prec->nova, curlen;
223 
224  epicsUInt8 *result=prec->vala;
225  epicsUInt32 numinputs = outlen/16;
226 
227  if(prec->ftva!=menuFtypeUCHAR) {
228  errlogPrintf("%s incorrect output type. A (UCHAR))\n",
229  prec->name);
230  return -1;
231  }
232  if(outlen%16)
233  numinputs++;
234  if(numinputs>NINPUTS)
235  numinputs=NINPUTS;
236 
237  for(curlen=0; curlen<numinputs; curlen++) {
238  if(intype[curlen]!=menuFtypeUSHORT) {
239  errlogPrintf("%s incorrect input type. %c (UCHAR))\n",
240  prec->name, 'A'+curlen);
241  return -1;
242  } else if(inlen[curlen]!=1){
243  errlogPrintf("%s incorrect input length. %c (1))\n",
244  prec->name, 'A'+curlen);
245  return -1;
246  }
247  }
248 
249  for(curlen=0; curlen<outlen; curlen++) {
250  epicsUInt32 I=curlen/16;
251  epicsUInt32 B=15-(curlen%16);
252  if(I>NINPUTS)
253  break;
254 
255  result[curlen]=!!(*indata[I]&(1<<B));
256  }
257 
258  return 0;
259 }
260 
261 static
262 long gun_bunchTrain(aSubRecord *prec)
263 {
264  int bunchPerTrain;
265  unsigned char *result;
266  epicsUInt32 count;
267  int i, j;
268 
269 
270  if (prec->fta != menuFtypeULONG) {
271  errlogPrintf("%s incorrect input type. A(ULONG)",
272  prec->name);
273  return -1;
274  }
275 
276  if (prec->ftva != menuFtypeUCHAR) {
277  errlogPrintf("%s incorrect output type. OUTA (DOUBLE)",
278  prec->name);
279  return -1;
280  }
281 
282  bunchPerTrain = *(int*)prec->a;
283  result = prec->vala;
284 
285  if(bunchPerTrain<1 || bunchPerTrain>150) {
286  errlogPrintf("%s : invalid number of bunches per train %d.\n",prec->name,bunchPerTrain);
287  return -1;
288  }
289 
290  count = 0;
291 
292  for(i = 0; i < bunchPerTrain; i++) {
293  for(j = 0; j < 10; j++) {
294  count++;
295  if(j < 5)
296  result[i*10 + j] = 1;
297  else
298  result[i*10 + j] = 0;
299  }
300  }
301  for(i = 0; i <10; i++, count++) {
302  result[count] = 0;
303  }
304 
305  prec->neva = count;
306  return 0;
307 }
308 
309 static registryFunctionRef asub_seq[] = {
310  {"Select String", (REGISTRYFUNCTION) select_string},
311  {"Timeline", (REGISTRYFUNCTION) gen_timeline},
312  {"Bit Array Gen", (REGISTRYFUNCTION) gen_bitarraygen},
313  {"Delay Gen", (REGISTRYFUNCTION) gen_delaygen},
314  {"Bunch Train", (REGISTRYFUNCTION) gun_bunchTrain}
315 };
316 
317 static
318 void asub_evr(void) {
319  registryFunctionRefAdd(asub_seq, NELEMENTS(asub_seq));
320 }
321 
322 #include <epicsExport.h>
323 
324 epicsExportRegistrar(asub_evr);
325 
#define NINPUTS
Definition: asub.c:27
epicsExportRegistrar(asub_evr)