This is Unofficial EPICS BASE Doxygen Site
devGeneralTime.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * EPICS BASE is distributed subject to a Software License Agreement found
3 * in file LICENSE that is included with this distribution.
4 \*************************************************************************/
5 
6 /*
7  * Original Author: Sheng Peng, ORNL / SNS Project
8  * Date: 07/2004
9  *
10  * EPICS device support for general timestamp support
11  *
12  * Integrated into base by Peter Denison, Diamond Light Source
13  */
14 
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 
19 #include "alarm.h"
20 #include "dbDefs.h"
21 #include "dbAccess.h"
22 #include "recGbl.h"
23 #include "devSup.h"
24 #include "epicsString.h"
25 #include "epicsGeneralTime.h"
26 
27 #include "aiRecord.h"
28 #include "boRecord.h"
29 #include "longinRecord.h"
30 #include "stringinRecord.h"
31 #include "epicsExport.h"
32 
33 
34 /********* ai record **********/
35 static int getCurrentTime(double * pseconds)
36 {
37  epicsTimeStamp ts;
38 
39  if (epicsTimeOK == epicsTimeGetCurrent(&ts)) {
40  *pseconds = ts.secPastEpoch + ((double)(ts.nsec)) * 1e-9;
41  return 0;
42  }
43  return -1;
44 }
45 
46 static struct ai_channel {
47  char *name;
48  int (*get)(double *);
49 } ai_channels[] = {
50  {"TIME", getCurrentTime},
51 };
52 
53 static long init_ai(dbCommon *pcommon)
54 {
55  aiRecord *prec = (aiRecord *)pcommon;
56  int i;
57 
58  if (prec->inp.type != INST_IO) {
59  recGblRecordError(S_db_badField, (void *)prec,
60  "devAiGeneralTime::init_ai: Illegal INP field");
61  prec->pact = TRUE;
62  return S_db_badField;
63  }
64 
65  for (i = 0; i < NELEMENTS(ai_channels); i++) {
66  struct ai_channel *pchan = &ai_channels[i];
67  if (!epicsStrCaseCmp(prec->inp.value.instio.string, pchan->name)) {
68  prec->dpvt = pchan;
69  return 0;
70  }
71  }
72 
73  recGblRecordError(S_db_badField, (void *)prec,
74  "devAiGeneralTime::init_ai: Bad parm");
75  prec->pact = TRUE;
76  prec->dpvt = NULL;
77  return S_db_badField;
78 }
79 
80 static long read_ai(aiRecord *prec)
81 {
82  struct ai_channel *pchan = (struct ai_channel *)prec->dpvt;
83 
84  if (!pchan) return -1;
85 
86  if (pchan->get(&prec->val) == 0) {
87  prec->udf = FALSE;
88  return 2;
89  }
90  prec->udf = TRUE;
91  recGblSetSevr(prec, READ_ALARM, INVALID_ALARM);
92  return -1;
93 }
94 
95 aidset devAiGeneralTime = {
96  {6, NULL, NULL, init_ai, NULL},
97  read_ai, NULL
98 };
99 epicsExportAddress(dset, devAiGeneralTime);
100 
101 
102 /********* bo record **********/
103 static void resetErrors(void)
104 {
106 }
107 
108 static struct bo_channel {
109  char *name;
110  void (*put)(void);
111 } bo_channels[] = {
112  {"RSTERRCNT", resetErrors},
113 };
114 
115 static long init_bo(dbCommon *pcommon)
116 {
117  boRecord *prec = (boRecord *)pcommon;
118  int i;
119 
120  if (prec->out.type != INST_IO) {
121  recGblRecordError(S_db_badField, (void *)prec,
122  "devAiGeneralTime::init_ai: Illegal INP field");
123  prec->pact = TRUE;
124  return S_db_badField;
125  }
126 
127  for (i = 0; i < NELEMENTS(bo_channels); i++) {
128  struct bo_channel *pchan = &bo_channels[i];
129  if (!epicsStrCaseCmp(prec->out.value.instio.string, pchan->name)) {
130  prec->dpvt = pchan;
131  prec->mask = 0;
132  return 2;
133  }
134  }
135 
136  recGblRecordError(S_db_badField, (void *)prec,
137  "devBoGeneralTime::init_bo: Bad parm");
138  prec->pact = TRUE;
139  prec->dpvt = NULL;
140  return S_db_badField;
141 }
142 
143 static long write_bo(boRecord *prec)
144 {
145  struct bo_channel *pchan = (struct bo_channel *)prec->dpvt;
146 
147  if (!pchan) return -1;
148 
149  pchan->put();
150  return 0;
151 }
152 
154  {5, NULL, NULL, init_bo, NULL},
155  write_bo
156 };
157 epicsExportAddress(dset, devBoGeneralTime);
158 
159 
160 
161 /******* longin record *************/
162 static int errorCount(void)
163 {
164  return generalTimeGetErrorCounts();
165 }
166 
167 static struct li_channel {
168  char *name;
169  int (*get)(void);
170 } li_channels[] = {
171  {"GETERRCNT", errorCount},
172 };
173 
174 static long init_li(dbCommon *pcommon)
175 {
176  longinRecord *prec = (longinRecord *)pcommon;
177  int i;
178 
179  if (prec->inp.type != INST_IO) {
180  recGblRecordError(S_db_badField, (void *)prec,
181  "devLiGeneralTime::init_li: Illegal INP field");
182  prec->pact = TRUE;
183  return S_db_badField;
184  }
185 
186  for (i = 0; i < NELEMENTS(li_channels); i++) {
187  struct li_channel *pchan = &li_channels[i];
188  if (!epicsStrCaseCmp(prec->inp.value.instio.string, pchan->name)) {
189  prec->dpvt = pchan;
190  return 0;
191  }
192  }
193 
194  recGblRecordError(S_db_badField, (void *)prec,
195  "devLiGeneralTime::init_li: Bad parm");
196  prec->pact = TRUE;
197  prec->dpvt = NULL;
198  return S_db_badField;
199 }
200 
201 static long read_li(longinRecord *prec)
202 {
203  struct li_channel *pchan = (struct li_channel *)prec->dpvt;
204 
205  if (!pchan) return -1;
206 
207  prec->val = pchan->get();
208  return 0;
209 }
210 
211 longindset devLiGeneralTime = {
212  {5, NULL, NULL, init_li, NULL},
213  read_li
214 };
215 epicsExportAddress(dset, devLiGeneralTime);
216 
217 
218 /********** stringin record **********/
219 static const char * timeProvider(void)
220 {
222 }
223 
224 static const char * highestProvider(void)
225 {
227 }
228 
229 static const char * eventProvider(void)
230 {
232 }
233 
234 static struct si_channel {
235  char *name;
236  const char * (*get)(void);
237 } si_channels[] = {
238  {"BESTTCP", timeProvider},
239  {"TOPTCP", highestProvider},
240  {"BESTTEP", eventProvider},
241 };
242 
243 static long init_si(dbCommon *pcommon)
244 {
245  stringinRecord *prec = (stringinRecord *)pcommon;
246  int i;
247 
248  if (prec->inp.type != INST_IO) {
249  recGblRecordError(S_db_badField, (void *)prec,
250  "devSiGeneralTime::init_si: Illegal INP field");
251  prec->pact = TRUE;
252  return S_db_badField;
253  }
254 
255  for (i = 0; i < NELEMENTS(si_channels); i++) {
256  struct si_channel *pchan = &si_channels[i];
257  if (!epicsStrCaseCmp(prec->inp.value.instio.string, pchan->name)) {
258  prec->dpvt = pchan;
259  return 0;
260  }
261  }
262 
263  recGblRecordError(S_db_badField, (void *)prec,
264  "devSiGeneralTime::init_si: Bad parm");
265  prec->pact = TRUE;
266  prec->dpvt = NULL;
267  return S_db_badField;
268 }
269 
270 static long read_si(stringinRecord *prec)
271 {
272  struct si_channel *pchan = (struct si_channel *)prec->dpvt;
273  const char *name;
274 
275  if (!pchan) return -1;
276 
277  name = pchan->get();
278  if (name) {
279  strncpy(prec->val, name, sizeof(prec->val));
280  prec->val[sizeof(prec->val) - 1] = '\0';
281  } else {
282  strcpy(prec->val, "No working providers");
283  recGblSetSevr(prec, READ_ALARM, MAJOR_ALARM);
284  }
285  prec->udf = FALSE;
286  return 0;
287 }
288 
289 stringindset devSiGeneralTime = {
290  {5, NULL, NULL, init_si, NULL},
291  read_si
292 };
293 epicsExportAddress(dset, devSiGeneralTime);
The generalTime framework provides a mechanism for several time providers to be present within the sy...
const char * generalTimeCurrentProviderName(void)
Return the nume of the provider that last returned a valid current time, or NULL if none...
#define FALSE
Definition: dbDefs.h:32
std::tr1::shared_ptr< detail::SharedPut > put
#define READ_ALARM
Definition: alarm.h:92
const char * generalTimeHighestCurrentName(void)
Return the name of the registered current time provider that has the highest priority.
#define MAJOR_ALARM
Definition: alarm.h:52
int i
Definition: scan.c:967
stringindset devSiGeneralTime
#define NULL
Definition: catime.c:38
#define epicsTimeOK
Success.
Definition: epicsTime.h:339
Miscellaneous macro definitions.
int epicsStrCaseCmp(const char *s1, const char *s2)
Definition: epicsString.c:191
bodset devBoGeneralTime
epicsUInt32 secPastEpoch
seconds since 0000 Jan 1, 1990
Definition: epicsTime.h:34
epicsExportAddress(dset, devAiGeneralTime)
Device support routines.
Definition: devSup.h:140
longindset devLiGeneralTime
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
const char * generalTimeEventProviderName(void)
Return the name of the provider that last returned a valid Time Event time, or NULL of none...
#define NELEMENTS(A)
Definition: aToIPAddr.c:21
void generalTimeResetErrorCounts(void)
Reset the internal counter of the number of times the time returned was earlier than when previously ...
EPICS time stamp, for use from C code.
Definition: epicsTime.h:33
#define TRUE
Definition: dbDefs.h:27
aidset devAiGeneralTime
if(yy_init)
Definition: scan.c:972
int prec
Definition: reader.c:29
#define INVALID_ALARM
Definition: alarm.h:53
int generalTimeGetErrorCounts(void)
Return the internal counter of the number of times the time returned was earlier than when previously...
epicsUInt32 nsec
nanoseconds within second
Definition: epicsTime.h:35
Exporting IOC objects.