MIDAS
Loading...
Searching...
No Matches
device_driver.cxx File Reference
#include <stdio.h>
#include <assert.h>
#include "midas.h"
#include "msystem.h"
Include dependency graph for device_driver.cxx:

Go to the source code of this file.

Functions

static int sc_thread (void *info)
 
INT device_driver (DEVICE_DRIVER *device_drv, INT cmd,...)
 

Function Documentation

◆ device_driver()

INT device_driver ( DEVICE_DRIVER device_drv,
INT  cmd,
  ... 
)

Definition at line 153 of file device_driver.cxx.

154{
156 HNDLE hKey;
157 INT channel, status, i, j;
158 float value, *pvalue;
159 char *name, *label;
160
161 va_start(argptr, cmd);
163
164 /* don't execute command if driver is disabled */
165 if (!device_drv->enabled)
167
168 switch (cmd) {
169 case CMD_INIT:
171
172 if (device_drv->flags & DF_MULTITHREAD) {
173 status = device_drv->dd(CMD_INIT, hKey, &device_drv->dd_info,
174 device_drv->channels, device_drv->flags,
175 device_drv->bd);
176
177 if (status == FE_SUCCESS && (device_drv->flags & DF_MULTITHREAD)) {
178 /* create inter-thread data exchange buffers */
179 device_drv->mt_buffer = (DD_MT_BUFFER *) calloc(1, sizeof(DD_MT_BUFFER));
180 device_drv->mt_buffer->n_channels = device_drv->channels;
181 device_drv->mt_buffer->channel = (DD_MT_CHANNEL *) calloc(device_drv->channels, sizeof(DD_MT_CHANNEL));
182 assert(device_drv->mt_buffer->channel);
183
184 /* initialize n_read for all channels */
185 for (i=0 ; i<device_drv->channels ; i++)
186 device_drv->mt_buffer->channel[i].n_read = 0;
187
188 /* set all get values to NaN */
189 for (i=0 ; i<device_drv->channels ; i++)
190 for (j=CMD_GET_FIRST ; j<=CMD_GET_LAST ; j++)
191 device_drv->mt_buffer->channel[i].variable[j] = (float) ss_nan();
192
193 /* set all set values to NaN */
194 for (i=0 ; i<device_drv->channels ; i++)
195 for (j=CMD_SET_FIRST ; j<=CMD_SET_LAST ; j++)
196 device_drv->mt_buffer->channel[i].variable[j] = (float)ss_nan();
197
198 /* get default names for this driver already now */
199 for (i = 0; i < device_drv->channels; i++) {
200 device_drv->dd(CMD_GET_LABEL, device_drv->dd_info, i,
201 device_drv->mt_buffer->channel[i].label);
202 }
203 /* create semaphore */
205 if (status != SS_CREATED && status != SS_SUCCESS)
206 return FE_ERR_DRIVER;
208 }
209 } else {
210 status = device_drv->dd(CMD_INIT, hKey, &device_drv->dd_info,
211 device_drv->channels, device_drv->flags,
212 device_drv->bd);
213 }
214 break;
215
216 case CMD_START:
217 if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL) {
218 /* create dedicated thread for this device */
219 device_drv->mt_buffer->thread_id = ss_thread_create(sc_thread, device_drv);
220 }
221 break;
222
223 case CMD_CLOSE:
224 /* signal all threads to stop */
225 if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL)
226 device_drv->stop_thread = 1;
227 break;
228
229 case CMD_STOP:
230 if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL) {
231 if (device_drv->stop_thread == 0)
232 device_drv->stop_thread = 1;
233
234 /* wait for max. 10 seconds until thread has gracefully stopped */
235 for (i = 0; i < 1000; i++) {
236 if (device_drv->stop_thread == 2)
237 break;
238 ss_sleep(10);
239 }
240
241 /* if timeout expired, kill thread */
242 if (i == 1000)
243 ss_thread_kill(device_drv->mt_buffer->thread_id);
244
246 free(device_drv->mt_buffer->channel);
247 free(device_drv->mt_buffer);
248 }
249 break;
250
251 case CMD_EXIT:
252 status = device_drv->dd(CMD_EXIT, device_drv->dd_info);
253 break;
254
255 case CMD_SET_LABEL:
257 label = va_arg(argptr, char *);
258 status = device_drv->dd(CMD_SET_LABEL, device_drv->dd_info, channel, label);
259 break;
260
261 case CMD_GET_LABEL:
263 name = va_arg(argptr, char *);
265 break;
266
267 default:
268
269 if (cmd >= CMD_SET_FIRST && cmd <= CMD_SET_LAST) {
270
271 /* transfer data to sc_thread for SET commands */
273 value = (float) va_arg(argptr, double); // floats are passed as double
274 if (device_drv->flags & DF_MULTITHREAD) {
275 ss_mutex_wait_for(device_drv->mutex, 1000);
276 device_drv->mt_buffer->channel[channel].variable[cmd] = value;
277 status = device_drv->mt_buffer->status;
279 } else {
280 status = device_drv->dd(cmd, device_drv->dd_info, channel, value);
281 }
282
283 } else if (cmd >= CMD_GET_FIRST && cmd <= CMD_GET_LAST) {
284
285 /* transfer data from sc_thread for GET commands */
287 pvalue = va_arg(argptr, float *);
288 if (device_drv->flags & DF_MULTITHREAD) {
289 ss_mutex_wait_for(device_drv->mutex, 1000);
290 *pvalue = device_drv->mt_buffer->channel[channel].variable[cmd];
291 status = device_drv->mt_buffer->status;
292 if (device_drv->mt_buffer->channel[channel].n_read < 1)
295 } else
296 status = device_drv->dd(cmd, device_drv->dd_info, channel, pvalue);
297
298 } else {
299
300 /* all remaining commands which are passed directly to the device driver */
302 pvalue = va_arg(argptr, float *);
303 status = device_drv->dd(cmd, device_drv->dd_info, channel, pvalue);
304 }
305
306 break;
307 }
308
309 va_end(argptr);
310 return status;
311}
#define FALSE
Definition cfortran.h:309
static int sc_thread(void *info)
#define SS_SUCCESS
Definition midas.h:663
#define SS_CREATED
Definition midas.h:664
#define CMD_CLOSE
Definition midas.h:773
#define FE_SUCCESS
Definition midas.h:717
#define CMD_INIT
Definition midas.h:762
#define CMD_SET_LAST
Definition midas.h:784
#define CMD_SET_FIRST
Definition midas.h:776
#define CMD_STOP
Definition midas.h:765
#define FE_NOT_YET_READ
Definition midas.h:723
#define CMD_GET_LAST
Definition midas.h:793
#define CMD_SET_LABEL
Definition midas.h:770
#define FE_PARTIALLY_DISABLED
Definition midas.h:722
#define CMD_START
Definition midas.h:764
#define FE_ERR_DRIVER
Definition midas.h:721
#define CMD_GET_LABEL
Definition midas.h:771
#define CMD_EXIT
Definition midas.h:763
#define CMD_GET_FIRST
Definition midas.h:786
INT ss_mutex_release(MUTEX_T *mutex)
Definition system.cxx:3157
INT ss_thread_kill(midas_thread_t thread_id)
Definition system.cxx:2383
INT ss_mutex_delete(MUTEX_T *mutex)
Definition system.cxx:3211
INT ss_mutex_create(MUTEX_T **mutex, BOOL recursive)
Definition system.cxx:2941
midas_thread_t ss_thread_create(INT(*thread_func)(void *), void *param)
Definition system.cxx:2310
INT ss_sleep(INT millisec)
Definition system.cxx:3628
double ss_nan()
Definition system.cxx:7940
INT ss_mutex_wait_for(MUTEX_T *mutex, INT timeout)
Definition system.cxx:3037
INT channel
HNDLE hKey
INT i
Definition mdump.cxx:32
INT HNDLE
Definition midas.h:132
#define DF_MULTITHREAD
Definition midas.h:1054
int INT
Definition midas.h:129
#define name(x)
Definition midas_macro.h:24
INT j
Definition odbhist.cxx:40
double value[100]
Definition odbhist.cxx:42
DWORD status
Definition odbhist.cxx:39
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
Here is the call graph for this function:

◆ sc_thread()

static int sc_thread ( void info)
static

Definition at line 15 of file device_driver.cxx.

16{
18 int i, status, cmd;
19 int current_channel = 0;
21 float value;
22 int *last_update;
23 unsigned int current_time;
25
26 ss_thread_set_name(std::string("SC:")+ *device_drv->pequipment_name);
27
28 last_update = (int*)calloc(device_drv->channels, sizeof(int));
29 for (i=0 ; i<device_drv->channels ; i++)
30 last_update[i] = ss_millitime() - 20000;
32
33 // call CMD_START of device driver
34 device_drv->dd(CMD_START, device_drv->dd_info, 0, NULL);
35
36 // initialize setting to NAN in order not to trigger an immediate write
37 for (i = 0; i < device_drv->channels; i++)
38 device_drv->mt_buffer->channel[i].variable[CMD_SET] = (float) ss_nan();
39
40 int skip = 0;
41 do {
42
43 // only operate if enabled
44 if (device_drv->pequipment->enabled) {
45
46 /* read one channel from device, skip if time limit is set */
47
48 /* limit data rate if defined in equipment list */
49 if (device_drv->pequipment && device_drv->pequipment->event_limit && current_channel == 0) {
50 if (ss_millitime() - last_time < (DWORD) device_drv->pequipment->event_limit) {
51 skip = 1;
52 } else {
53 skip = 0;
55 }
56 }
57
58 if (!skip) {
59 for (cmd = CMD_GET_FIRST; cmd <= CMD_GET_LAST; cmd++) {
60 value = (float) ss_nan();
61 status = device_drv->dd(cmd, device_drv->dd_info, current_channel, &value);
62
63 ss_mutex_wait_for(device_drv->mutex, 1000);
64 device_drv->mt_buffer->channel[current_channel].variable[cmd] = value;
65 device_drv->mt_buffer->status = status;
67 }
68 device_drv->mt_buffer->channel[current_channel].n_read++;
69 }
70
71 /* switch to next channel in next loop */
72 current_channel = (current_channel + 1) % device_drv->channels;
73
74 /* check for priority channel */
75 if (device_drv->flags & DF_PRIORITY_READ) {
77 i = (current_priority_channel + 1) % device_drv->channels;
78 while (!(current_time - last_update[i] < 10000)) {
79 i = (i + 1) % device_drv->channels;
81 /* non found, so finish */
82 break;
83 }
84 }
85
86 /* updated channel found, so read it additionally */
87 if (current_time - last_update[i] < 10000) {
89
90 for (cmd = CMD_GET_FIRST; cmd <= CMD_GET_LAST; cmd++) {
91 status = device_drv->dd(cmd, device_drv->dd_info, i, &value);
92
93 ss_mutex_wait_for(device_drv->mutex, 1000);
94 device_drv->mt_buffer->channel[i].variable[cmd] = value;
95 device_drv->mt_buffer->status = status;
97 }
98 }
99 }
100
101 // copy potential set value to get/get_demand buffers to avoid old value there to be copied to ODB
102 for (i = 0; i < device_drv->channels; i++) {
103
104 for (cmd = CMD_SET_FIRST; cmd <= CMD_SET_LAST; cmd++) {
105 if (!ss_isnan(device_drv->mt_buffer->channel[i].variable[cmd])) {
106 ss_mutex_wait_for(device_drv->mutex, 1000);
107 value = device_drv->mt_buffer->channel[i].variable[cmd];
109
110 if (cmd == CMD_SET) {
111 ss_mutex_wait_for(device_drv->mutex, 1000);
112 device_drv->mt_buffer->channel[i].variable[CMD_GET] = value;
113 device_drv->mt_buffer->channel[i].variable[CMD_GET_DEMAND] = value;
115 }
116 }
117 }
118 }
119
120 /* check if anything to write to device */
121 for (i = 0; i < device_drv->channels; i++) {
122
123 for (cmd = CMD_SET_FIRST; cmd <= CMD_SET_LAST; cmd++) {
124 if (!ss_isnan(device_drv->mt_buffer->channel[i].variable[cmd])) {
125 ss_mutex_wait_for(device_drv->mutex, 1000);
126 value = device_drv->mt_buffer->channel[i].variable[cmd];
127 device_drv->mt_buffer->channel[i].variable[cmd] = (float) ss_nan();
129
130 status = device_drv->dd(cmd, device_drv->dd_info, i, value);
131 device_drv->mt_buffer->status = status;
132 if (cmd == CMD_SET)
134 }
135 }
136 }
137 } // enabled
138
139 ss_sleep(10); // don't eat all CPU
140
141 } while (device_drv->stop_thread == 0);
142
143 free(last_update);
144
145 /* signal stopped thread */
146 device_drv->stop_thread = 2;
147
148 return SUCCESS;
149}
#define CMD_GET_DEMAND
Definition midas.h:792
#define CMD_GET
Definition midas.h:787
#define CMD_SET
Definition midas.h:777
unsigned int DWORD
Definition mcstd.h:51
#define SUCCESS
Definition mcstd.h:54
int ss_isnan(double x)
Definition system.cxx:7961
DWORD ss_millitime()
Definition system.cxx:3393
INT EXPRT ss_thread_set_name(std::string name)
Definition system.cxx:2426
void ** info
Definition fesimdaq.cxx:41
DWORD last_time
Definition mana.cxx:3070
#define DF_PRIORITY_READ
Definition midas.h:1063
static char * skip(char **buf, const char *delimiters)
Here is the call graph for this function:
Here is the caller graph for this function: