Line data Source code
1 : /********************************************************************\
2 :
3 : Name: generic.c
4 : Created by: Stefan Ritt
5 :
6 : Contents: Generic Class Driver
7 :
8 : $Id$
9 :
10 : \********************************************************************/
11 :
12 : #include <stdio.h>
13 : #include <assert.h>
14 : #include <stdlib.h>
15 : #include <string.h>
16 : #include "midas.h"
17 :
18 : typedef struct {
19 :
20 : /* ODB keys */
21 : HNDLE hKeyRoot, hKeyDemand, hKeyMeasured;
22 :
23 : /* globals */
24 : INT num_channels;
25 : INT format;
26 : INT last_channel;
27 :
28 : /* items in /Variables record */
29 : float *demand;
30 : float *measured;
31 :
32 : /* items in /Settings */
33 : char *names;
34 : float *update_threshold;
35 :
36 : /* mirror arrays */
37 : float *demand_mirror;
38 : float *measured_mirror;
39 :
40 : DEVICE_DRIVER **driver;
41 : INT *channel_offset;
42 :
43 : } GEN_INFO;
44 :
45 : #ifndef abs
46 : #define abs(a) (((a) < 0) ? -(a) : (a))
47 : #endif
48 :
49 : /*------------------------------------------------------------------*/
50 :
51 0 : static void free_mem(GEN_INFO * gen_info)
52 : {
53 0 : free(gen_info->names);
54 0 : free(gen_info->demand);
55 0 : free(gen_info->measured);
56 :
57 0 : free(gen_info->update_threshold);
58 :
59 0 : free(gen_info->demand_mirror);
60 0 : free(gen_info->measured_mirror);
61 :
62 0 : free(gen_info->channel_offset);
63 0 : free(gen_info->driver);
64 :
65 0 : free(gen_info);
66 0 : }
67 :
68 : /*------------------------------------------------------------------*/
69 :
70 0 : INT gen_read(EQUIPMENT * pequipment, int channel)
71 : {
72 : int i, status;
73 : GEN_INFO *gen_info;
74 : HNDLE hDB;
75 0 : gen_info = (GEN_INFO *) pequipment->cd_info;
76 0 : cm_get_experiment_database(&hDB, NULL);
77 : /* if driver is multi-threaded, read all channels at once */
78 0 : for (i=0 ; i < gen_info->num_channels ; i++) {
79 :
80 0 : if (gen_info->driver[i]->flags & DF_MULTITHREAD) {
81 0 : status = device_driver(gen_info->driver[i], CMD_GET,
82 0 : i - gen_info->channel_offset[i],
83 0 : &gen_info->measured[i]);
84 : }
85 : }
86 :
87 : /* else read only single channel */
88 0 : if (!(gen_info->driver[channel]->flags & DF_MULTITHREAD)) {
89 0 : status = device_driver(gen_info->driver[channel], CMD_GET,
90 0 : channel - gen_info->channel_offset[channel],
91 0 : &gen_info->measured[channel]);
92 : }
93 : /* check for update measured */
94 0 : for (i = 0; i < gen_info->num_channels; i++) {
95 : /* update if change is more than update_threshold */
96 0 : if ((ss_isnan(gen_info->measured[i]) && !ss_isnan(gen_info->measured_mirror[i])) ||
97 0 : (!ss_isnan(gen_info->measured[i]) && ss_isnan(gen_info->measured_mirror[i])) ||
98 0 : (!ss_isnan(gen_info->measured[i]) && !ss_isnan(gen_info->measured_mirror[i]) &&
99 0 : abs(gen_info->measured[i] - gen_info->measured_mirror[i]) >
100 0 : gen_info->update_threshold[i])) {
101 0 : for (i = 0; i < gen_info->num_channels; i++)
102 0 : gen_info->measured_mirror[i] = gen_info->measured[i];
103 :
104 0 : db_set_data(hDB, gen_info->hKeyMeasured, gen_info->measured,
105 0 : sizeof(float) * gen_info->num_channels, gen_info->num_channels,
106 : TID_FLOAT);
107 :
108 0 : pequipment->odb_out++;
109 :
110 0 : break;
111 : }
112 : }
113 :
114 : /*---- read demand value ----*/
115 :
116 0 : status = device_driver(gen_info->driver[channel], CMD_GET_DEMAND,
117 0 : channel - gen_info->channel_offset[channel],
118 0 : &gen_info->demand[channel]);
119 :
120 0 : if ((gen_info->demand[channel] != gen_info->demand_mirror[channel] && !ss_isnan(gen_info->demand[channel])) ||
121 0 : (ss_isnan(gen_info->demand[channel]) && !ss_isnan(gen_info->demand_mirror[channel])) ||
122 0 : (!ss_isnan(gen_info->demand[channel]) && ss_isnan(gen_info->demand_mirror[channel]))) {
123 0 : gen_info->demand_mirror[channel] = gen_info->demand[channel];
124 0 : db_set_data(hDB, gen_info->hKeyDemand, gen_info->demand,
125 0 : sizeof(float) * gen_info->num_channels, gen_info->num_channels,
126 : TID_FLOAT);
127 : }
128 :
129 0 : return status;
130 : }
131 :
132 : /*------------------------------------------------------------------*/
133 :
134 0 : INT gen_read_direct(EQUIPMENT * pequipment) {
135 0 : int i, status = 0;
136 : GEN_INFO *gen_info;
137 : HNDLE hDB;
138 0 : gen_info = (GEN_INFO *) pequipment->cd_info;
139 0 : cm_get_experiment_database(&hDB, NULL);
140 :
141 0 : for (i = 0; i < gen_info->num_channels; i++)
142 0 : status = device_driver(gen_info->driver[i], CMD_GET_DIRECT,
143 0 : i - gen_info->channel_offset[i],
144 0 : &gen_info->measured[i]);
145 :
146 0 : return status;
147 : }
148 :
149 : /*------------------------------------------------------------------*/
150 :
151 0 : void gen_demand(INT hDB, INT hKey, void *info)
152 : {
153 : INT i;
154 : GEN_INFO *gen_info;
155 : EQUIPMENT *pequipment;
156 :
157 0 : pequipment = (EQUIPMENT *) info;
158 0 : gen_info = (GEN_INFO *) pequipment->cd_info;
159 :
160 : /* set individual channels only if demand value differs */
161 0 : for (i = 0; i < gen_info->num_channels; i++)
162 0 : if (gen_info->demand[i] != gen_info->demand_mirror[i]) {
163 0 : if ((gen_info->driver[i]->flags & DF_READ_ONLY) == 0) {
164 0 : device_driver(gen_info->driver[i], CMD_SET,
165 0 : i - gen_info->channel_offset[i], gen_info->demand[i]);
166 : }
167 0 : gen_info->demand_mirror[i] = gen_info->demand[i];
168 : }
169 :
170 0 : pequipment->odb_in++;
171 0 : }
172 :
173 : /*------------------------------------------------------------------*/
174 :
175 0 : void gen_update_label(INT hDB, INT hKey, void *info)
176 : {
177 : INT i;
178 : GEN_INFO *gen_info;
179 : EQUIPMENT *pequipment;
180 :
181 0 : pequipment = (EQUIPMENT *) info;
182 0 : gen_info = (GEN_INFO *) pequipment->cd_info;
183 :
184 : /* update channel labels based on the midas channel names */
185 0 : for (i = 0; i < gen_info->num_channels; i++)
186 0 : device_driver(gen_info->driver[i], CMD_SET_LABEL,
187 0 : i - gen_info->channel_offset[i],
188 0 : gen_info->names + NAME_LENGTH * i);
189 0 : }
190 :
191 : /*------------------------------------------------------------------*/
192 :
193 0 : INT gen_init(EQUIPMENT * pequipment)
194 : {
195 : int status, size, i, j, index, offset;
196 : char str[256];
197 : HNDLE hDB, hKey, hNames, hThreshold;
198 : GEN_INFO *gen_info;
199 :
200 : /* allocate private data */
201 0 : pequipment->cd_info = calloc(1, sizeof(GEN_INFO));
202 0 : gen_info = (GEN_INFO *) pequipment->cd_info;
203 :
204 : /* get class driver root key */
205 0 : cm_get_experiment_database(&hDB, NULL);
206 0 : snprintf(str, sizeof(str), "/Equipment/%s", pequipment->name);
207 0 : db_create_key(hDB, 0, str, TID_KEY);
208 0 : db_find_key(hDB, 0, str, &gen_info->hKeyRoot);
209 :
210 : /* save event format */
211 0 : size = sizeof(str);
212 0 : db_get_value(hDB, gen_info->hKeyRoot, "Common/Format", str, &size, TID_STRING, TRUE);
213 :
214 0 : if (equal_ustring(str, "Fixed"))
215 0 : gen_info->format = FORMAT_FIXED;
216 0 : else if (equal_ustring(str, "MIDAS"))
217 0 : gen_info->format = FORMAT_MIDAS;
218 : else
219 0 : assert(!"unknown ODM Common/Format");
220 :
221 : /* count total number of channels */
222 0 : for (i = 0, gen_info->num_channels = 0; pequipment->driver[i].name[0]; i++) {
223 0 : if (pequipment->driver[i].channels == 0) {
224 0 : cm_msg(MERROR, "gen_init", "Driver with zero channels not allowed");
225 0 : return FE_ERR_ODB;
226 : }
227 :
228 0 : gen_info->num_channels += pequipment->driver[i].channels;
229 : }
230 :
231 0 : if (gen_info->num_channels == 0) {
232 0 : cm_msg(MERROR, "gen_init", "No channels found in device driver list");
233 0 : return FE_ERR_ODB;
234 : }
235 :
236 : /* Allocate memory for buffers */
237 0 : gen_info->names = (char *) calloc(gen_info->num_channels, NAME_LENGTH);
238 :
239 0 : gen_info->demand = (float *) calloc(gen_info->num_channels, sizeof(float));
240 0 : gen_info->measured = (float *) calloc(gen_info->num_channels, sizeof(float));
241 :
242 0 : gen_info->update_threshold = (float *) calloc(gen_info->num_channels, sizeof(float));
243 :
244 0 : gen_info->demand_mirror = (float *) calloc(gen_info->num_channels, sizeof(float));
245 0 : gen_info->measured_mirror = (float *) calloc(gen_info->num_channels, sizeof(float));
246 :
247 0 : gen_info->channel_offset = (INT *) calloc(gen_info->num_channels, sizeof(INT));
248 0 : gen_info->driver = (DEVICE_DRIVER **) calloc(gen_info->num_channels, sizeof(void *));
249 :
250 0 : if (!gen_info->driver) {
251 0 : cm_msg(MERROR, "hv_init", "Not enough memory");
252 0 : return FE_ERR_ODB;
253 : }
254 :
255 : /*---- Initialize device drivers ----*/
256 :
257 : /* call init method */
258 0 : for (i = 0; pequipment->driver[i].name[0]; i++) {
259 0 : snprintf(str, sizeof(str), "Settings/Devices/%s", pequipment->driver[i].name);
260 0 : status = db_find_key(hDB, gen_info->hKeyRoot, str, &hKey);
261 0 : if (status != DB_SUCCESS) {
262 0 : db_create_key(hDB, gen_info->hKeyRoot, str, TID_KEY);
263 0 : status = db_find_key(hDB, gen_info->hKeyRoot, str, &hKey);
264 0 : if (status != DB_SUCCESS) {
265 0 : cm_msg(MERROR, "hv_init", "Cannot create %s entry in online database", str);
266 0 : free_mem(gen_info);
267 0 : return FE_ERR_ODB;
268 : }
269 : }
270 :
271 : /* check enabled flag */
272 0 : size = sizeof(pequipment->driver[i].enabled);
273 0 : pequipment->driver[i].enabled = 1;
274 0 : snprintf(str, sizeof(str), "Settings/Devices/%s/Enabled", pequipment->driver[i].name);
275 0 : status = db_get_value(hDB, gen_info->hKeyRoot, str, &pequipment->driver[i].enabled
276 : , &size, TID_BOOL, TRUE);
277 0 : if (status != DB_SUCCESS)
278 0 : return FE_ERR_ODB;
279 :
280 0 : if (pequipment->driver[i].enabled) {
281 0 : printf("Connecting %s:%s...", pequipment->name, pequipment->driver[i].name);
282 0 : fflush(stdout);
283 0 : status = device_driver(&pequipment->driver[i], CMD_INIT, hKey);
284 0 : if (status != FE_SUCCESS) {
285 0 : free_mem(gen_info);
286 0 : return status;
287 : }
288 0 : printf("OK\n");
289 : }
290 : }
291 :
292 : /* compose device driver channel assignment */
293 0 : for (i = 0, j = 0, index = 0, offset = 0; i < gen_info->num_channels; i++, j++) {
294 0 : while (j >= pequipment->driver[index].channels && pequipment->driver[index].name[0]) {
295 0 : offset += j;
296 0 : index++;
297 0 : j = 0;
298 : }
299 :
300 0 : gen_info->driver[i] = &pequipment->driver[index];
301 0 : gen_info->channel_offset[i] = offset;
302 : }
303 :
304 : /*---- create demand variables ----*/
305 :
306 : /* get demand from ODB */
307 : status =
308 0 : db_find_key(hDB, gen_info->hKeyRoot, "Variables/Demand", &gen_info->hKeyDemand);
309 0 : if (status == DB_SUCCESS) {
310 0 : size = sizeof(float) * gen_info->num_channels;
311 0 : db_get_data(hDB, gen_info->hKeyDemand, gen_info->demand, &size, TID_FLOAT);
312 : }
313 : /* let device driver overwrite demand values, if it supports it */
314 0 : for (i = 0; i < gen_info->num_channels; i++) {
315 0 : if ((gen_info->driver[i]->flags & DF_PRIO_DEVICE) &&
316 0 : !(gen_info->driver[i]->flags & DF_QUICKSTART)) {
317 0 : device_driver(gen_info->driver[i], CMD_GET_DEMAND_DIRECT,
318 0 : i - gen_info->channel_offset[i], &gen_info->demand[i]);
319 0 : gen_info->demand_mirror[i] = gen_info->demand[i];
320 :
321 0 : if (gen_info->driver[i]->flags &DF_MULTITHREAD)
322 0 : gen_info->driver[i]->mt_buffer->channel[i].variable[CMD_GET_DEMAND] = gen_info->demand[i];
323 :
324 : } else
325 0 : gen_info->demand_mirror[i] = ss_nan();
326 : }
327 : /* write back demand values */
328 : status =
329 0 : db_find_key(hDB, gen_info->hKeyRoot, "Variables/Demand", &gen_info->hKeyDemand);
330 0 : if (status != DB_SUCCESS) {
331 0 : db_create_key(hDB, gen_info->hKeyRoot, "Variables/Demand", TID_FLOAT);
332 0 : db_find_key(hDB, gen_info->hKeyRoot, "Variables/Demand", &gen_info->hKeyDemand);
333 : }
334 0 : size = sizeof(float) * gen_info->num_channels;
335 0 : db_set_data(hDB, gen_info->hKeyDemand, gen_info->demand, size,
336 : gen_info->num_channels, TID_FLOAT);
337 0 : db_open_record(hDB, gen_info->hKeyDemand, gen_info->demand,
338 0 : gen_info->num_channels * sizeof(float), MODE_READ, gen_demand,
339 : pequipment);
340 :
341 : /*---- create measured variables ----*/
342 0 : db_merge_data(hDB, gen_info->hKeyRoot, "Variables/Measured",
343 0 : gen_info->measured, sizeof(float) * gen_info->num_channels,
344 : gen_info->num_channels, TID_FLOAT);
345 0 : db_find_key(hDB, gen_info->hKeyRoot, "Variables/Measured", &gen_info->hKeyMeasured);
346 0 : for (i=0 ; i<gen_info->num_channels ; i++)
347 0 : gen_info->measured[i] = (float)ss_nan();
348 :
349 : /*---- get default names from device driver ----*/
350 0 : for (i = 0; i < gen_info->num_channels; i++) {
351 0 : snprintf(gen_info->names + NAME_LENGTH * i, NAME_LENGTH, "Default%%CH %d", i);
352 0 : device_driver(gen_info->driver[i], CMD_GET_LABEL,
353 0 : i - gen_info->channel_offset[i], gen_info->names + NAME_LENGTH * i);
354 : }
355 0 : db_merge_data(hDB, gen_info->hKeyRoot, "Settings/Names",
356 0 : gen_info->names, NAME_LENGTH * gen_info->num_channels,
357 : gen_info->num_channels, TID_STRING);
358 :
359 : /*---- set labels form midas SC names ----*/
360 0 : for (i = 0; i < gen_info->num_channels; i++) {
361 0 : gen_info = (GEN_INFO *) pequipment->cd_info;
362 0 : device_driver(gen_info->driver[i], CMD_SET_LABEL,
363 0 : i - gen_info->channel_offset[i], gen_info->names + NAME_LENGTH * i);
364 : }
365 :
366 : /* open hotlink on channel names */
367 0 : if (db_find_key(hDB, gen_info->hKeyRoot, "Settings/Names", &hNames) == DB_SUCCESS)
368 0 : db_open_record(hDB, hNames, gen_info->names, NAME_LENGTH*gen_info->num_channels,
369 : MODE_READ, gen_update_label, pequipment);
370 :
371 : /*---- get default update threshold from device driver ----*/
372 0 : for (i = 0; i < gen_info->num_channels; i++) {
373 0 : gen_info->update_threshold[i] = 1.f; /* default 1 unit */
374 0 : device_driver(gen_info->driver[i], CMD_GET_THRESHOLD,
375 0 : i - gen_info->channel_offset[i], &gen_info->update_threshold[i]);
376 : }
377 0 : db_merge_data(hDB, gen_info->hKeyRoot, "Settings/Update Threshold Measured",
378 0 : gen_info->update_threshold, sizeof(float)*gen_info->num_channels,
379 : gen_info->num_channels, TID_FLOAT);
380 :
381 : /* open hotlink on update threshold */
382 0 : if (db_find_key(hDB, gen_info->hKeyRoot, "Settings/Update Threshold Measured", &hThreshold) == DB_SUCCESS)
383 0 : db_open_record(hDB, hThreshold, gen_info->update_threshold, sizeof(float)*gen_info->num_channels,
384 : MODE_READ, NULL, NULL);
385 :
386 : /*---- set initial demand values ----*/
387 0 : gen_demand(hDB, gen_info->hKeyDemand, pequipment);
388 :
389 : /* initially read all channels */
390 0 : if (!(gen_info->driver[0]->flags & DF_QUICKSTART)) {
391 0 : gen_read_direct(pequipment);
392 :
393 0 : if (gen_info->driver[0]->flags & DF_MULTITHREAD) {
394 0 : for (i = 0; i < gen_info->num_channels; i++)
395 0 : gen_info->driver[i]->mt_buffer->channel[i].variable[CMD_GET] = gen_info->measured[i];
396 : }
397 : }
398 :
399 0 : return FE_SUCCESS;
400 : }
401 :
402 : /*----------------------------------------------------------------------------*/
403 :
404 0 : INT gen_start(EQUIPMENT * pequipment)
405 : {
406 : INT i;
407 :
408 : /* call start method of device drivers */
409 0 : for (i = 0; pequipment->driver[i].dd != NULL ; i++)
410 0 : if (pequipment->driver[i].flags & DF_MULTITHREAD) {
411 0 : pequipment->driver[i].pequipment = &pequipment->info;
412 0 : device_driver(&pequipment->driver[i], CMD_START);
413 : }
414 :
415 0 : return FE_SUCCESS;
416 : }
417 :
418 : /*----------------------------------------------------------------------------*/
419 :
420 0 : INT gen_stop(EQUIPMENT * pequipment)
421 : {
422 : INT i;
423 :
424 : /* call stop method of device drivers */
425 0 : for (i = 0; pequipment->driver[i].dd != NULL && pequipment->driver[i].flags & DF_MULTITHREAD ; i++)
426 0 : device_driver(&pequipment->driver[i], CMD_STOP);
427 :
428 0 : return FE_SUCCESS;
429 : }
430 :
431 : /*------------------------------------------------------------------*/
432 :
433 0 : INT gen_exit(EQUIPMENT * pequipment)
434 : {
435 : INT i;
436 :
437 0 : free_mem((GEN_INFO *) pequipment->cd_info);
438 :
439 : /* call exit method of device drivers */
440 0 : for (i = 0; pequipment->driver[i].dd != NULL; i++)
441 0 : device_driver(&pequipment->driver[i], CMD_EXIT);
442 :
443 0 : return FE_SUCCESS;
444 : }
445 :
446 : /*------------------------------------------------------------------*/
447 :
448 0 : INT gen_idle(EQUIPMENT * pequipment)
449 : {
450 : INT act, status;
451 : GEN_INFO *gen_info;
452 :
453 0 : gen_info = (GEN_INFO *) pequipment->cd_info;
454 :
455 : /* select next measurement channel */
456 0 : act = (gen_info->last_channel + 1) % gen_info->num_channels;
457 :
458 : /* measure channel */
459 0 : status = gen_read(pequipment, act);
460 0 : gen_info->last_channel = act;
461 :
462 0 : return status;
463 : }
464 :
465 : /*------------------------------------------------------------------*/
466 :
467 0 : INT cd_gen_read(char *pevent, int offset)
468 : {
469 : float *pdata;
470 : GEN_INFO *gen_info;
471 : EQUIPMENT *pequipment;
472 : #ifdef HAVE_YBOS
473 : DWORD *pdw;
474 : #endif
475 :
476 0 : pequipment = *((EQUIPMENT **) pevent);
477 0 : gen_info = (GEN_INFO *) pequipment->cd_info;
478 :
479 0 : if (gen_info->format == FORMAT_FIXED) {
480 0 : memcpy(pevent, gen_info->demand, sizeof(float) * gen_info->num_channels);
481 0 : pevent += sizeof(float) * gen_info->num_channels;
482 :
483 0 : memcpy(pevent, gen_info->measured, sizeof(float) * gen_info->num_channels);
484 0 : pevent += sizeof(float) * gen_info->num_channels;
485 :
486 0 : return 2 * sizeof(float) * gen_info->num_channels;
487 0 : } else if (gen_info->format == FORMAT_MIDAS) {
488 0 : bk_init32(pevent);
489 :
490 : /* create DMND bank */
491 0 : bk_create(pevent, "DMND", TID_FLOAT, (void **)&pdata);
492 0 : memcpy(pdata, gen_info->demand, sizeof(float) * gen_info->num_channels);
493 0 : pdata += gen_info->num_channels;
494 0 : bk_close(pevent, pdata);
495 :
496 : /* create MSRD bank */
497 0 : bk_create(pevent, "MSRD", TID_FLOAT, (void **)&pdata);
498 0 : memcpy(pdata, gen_info->measured, sizeof(float) * gen_info->num_channels);
499 0 : pdata += gen_info->num_channels;
500 0 : bk_close(pevent, pdata);
501 :
502 0 : return bk_size(pevent);
503 : } else {
504 0 : assert(!"unknown gen_info->format");
505 : }
506 :
507 : return 0;
508 : }
509 :
510 : /*------------------------------------------------------------------*/
511 :
512 0 : INT cd_gen(INT cmd, EQUIPMENT * pequipment)
513 : {
514 : INT status;
515 :
516 0 : switch (cmd) {
517 0 : case CMD_INIT:
518 0 : status = gen_init(pequipment);
519 0 : break;
520 :
521 0 : case CMD_START:
522 0 : status = gen_start(pequipment);
523 0 : break;
524 :
525 0 : case CMD_STOP:
526 0 : status = gen_stop(pequipment);
527 0 : break;
528 :
529 0 : case CMD_EXIT:
530 0 : status = gen_exit(pequipment);
531 0 : break;
532 :
533 0 : case CMD_IDLE:
534 0 : status = gen_idle(pequipment);
535 0 : break;
536 :
537 0 : default:
538 0 : cm_msg(MERROR, "Generic class driver", "Received unknown command %d", cmd);
539 0 : status = FE_ERR_DRIVER;
540 0 : break;
541 : }
542 :
543 0 : return status;
544 : }
|