Line data Source code
1 : /********************************************************************\
2 :
3 : Name: hv.c
4 : Created by: Stefan Ritt
5 :
6 : Contents: High Voltage Class Driver
7 :
8 : $Id: hv.c 5126 2011-07-07 12:32:53Z ritt $
9 :
10 : \********************************************************************/
11 :
12 : #include <stdio.h>
13 : #include <math.h>
14 : #include <assert.h>
15 : #include <stdlib.h>
16 : #include <string.h>
17 : #include "midas.h"
18 : #include "mstrlcpy.h"
19 :
20 : // minimal ramping increment to reduce calls to (potential slow) SET function
21 : #define HV_MIN_RAMP_STEP 0.05
22 :
23 : typedef struct {
24 :
25 : /* ODB keys */
26 : HNDLE hKeyRoot, hKeyDemand, hKeyMeasured, hKeyCurrent, hKeyChStatus, hKeyTemperature;
27 :
28 : /* globals */
29 : INT num_channels;
30 : INT format;
31 : DWORD last_update;
32 : INT last_channel;
33 : INT last_channel_updated;
34 :
35 : /* items in /Variables record */
36 : char *names;
37 : float *demand;
38 : float *measured;
39 : float *current;
40 : DWORD *chStatus;
41 : float *temperature;
42 :
43 : /* items in /Settings */
44 : float *update_threshold;
45 : float *update_threshold_current;
46 : float *zero_threshold;
47 : float *voltage_limit;
48 : float *current_limit;
49 : float *rampup_speed;
50 : float *rampdown_speed;
51 : float *trip_time;
52 : DWORD *chState;
53 : INT *crateMap;
54 :
55 : /* mirror arrays */
56 : float *demand_mirror;
57 : float *measured_mirror;
58 : float *current_mirror;
59 : DWORD *chStatus_mirror;
60 : float *temperature_mirror;
61 : DWORD *last_change;
62 :
63 : DEVICE_DRIVER **driver;
64 : INT *channel_offset;
65 : void **dd_info;
66 :
67 : } HV_INFO;
68 :
69 : #ifndef ABS
70 : #define ABS(a) (((a) < 0) ? -(a) : (a))
71 : #endif
72 :
73 : /*------------------------------------------------------------------*/
74 :
75 0 : static void free_mem(HV_INFO * hv_info)
76 : {
77 0 : free(hv_info->names);
78 0 : free(hv_info->demand);
79 0 : free(hv_info->measured);
80 0 : free(hv_info->current);
81 0 : free(hv_info->chStatus);
82 0 : free(hv_info->temperature);
83 :
84 0 : free(hv_info->update_threshold);
85 0 : free(hv_info->update_threshold_current);
86 0 : free(hv_info->zero_threshold);
87 0 : free(hv_info->voltage_limit);
88 0 : free(hv_info->current_limit);
89 0 : free(hv_info->rampup_speed);
90 0 : free(hv_info->rampdown_speed);
91 0 : free(hv_info->trip_time);
92 0 : free(hv_info->chState);
93 0 : free(hv_info->crateMap);
94 :
95 0 : free(hv_info->demand_mirror);
96 0 : free(hv_info->measured_mirror);
97 0 : free(hv_info->current_mirror);
98 0 : free(hv_info->chStatus_mirror);
99 0 : free(hv_info->temperature_mirror);
100 0 : free(hv_info->last_change);
101 :
102 0 : free(hv_info->dd_info);
103 0 : free(hv_info->channel_offset);
104 0 : free(hv_info->driver);
105 :
106 0 : free(hv_info);
107 0 : }
108 :
109 : /*----------------------------------------------------------------------------*/
110 :
111 0 : INT hv_start(EQUIPMENT * pequipment)
112 : {
113 : INT i;
114 :
115 : /* call start method of device drivers */
116 0 : for (i = 0; pequipment->driver[i].dd != NULL ; i++)
117 0 : if (pequipment->driver[i].flags & DF_MULTITHREAD) {
118 0 : pequipment->driver[i].pequipment = &pequipment->info;
119 0 : device_driver(&pequipment->driver[i], CMD_START);
120 : }
121 :
122 0 : return FE_SUCCESS;
123 : }
124 :
125 : /*----------------------------------------------------------------------------*/
126 :
127 0 : INT hv_stop(EQUIPMENT * pequipment)
128 : {
129 : INT i;
130 :
131 : /* call close method of device drivers */
132 0 : for (i = 0; pequipment->driver[i].dd != NULL ; i++)
133 0 : if (pequipment->driver[i].flags & DF_MULTITHREAD)
134 0 : device_driver(&pequipment->driver[i], CMD_CLOSE);
135 :
136 : /* call stop method of device drivers */
137 0 : for (i = 0; pequipment->driver[i].dd != NULL ; i++)
138 0 : if (pequipment->driver[i].flags & DF_MULTITHREAD)
139 0 : device_driver(&pequipment->driver[i], CMD_STOP);
140 :
141 0 : return FE_SUCCESS;
142 : }
143 :
144 : /*------------------------------------------------------------------*/
145 :
146 0 : INT hv_read(EQUIPMENT * pequipment, int channel)
147 : {
148 0 : int i, status = 0;
149 : float max_diff;
150 : DWORD act_time, min_time;
151 : BOOL changed;
152 : HV_INFO *hv_info;
153 : HNDLE hDB;
154 :
155 0 : hv_info = (HV_INFO *) pequipment->cd_info;
156 0 : cm_get_experiment_database(&hDB, NULL);
157 :
158 : /* if driver is multi-threaded, read all channels at once */
159 0 : for (i=0 ; i < hv_info->num_channels ; i++) {
160 0 : if (hv_info->driver[i]->flags & DF_MULTITHREAD) {
161 0 : status = device_driver(hv_info->driver[i], CMD_GET,
162 0 : i - hv_info->channel_offset[i],
163 0 : &hv_info->measured[i]);
164 0 : status = device_driver(hv_info->driver[i], CMD_GET_CURRENT,
165 0 : i - hv_info->channel_offset[i],
166 0 : &hv_info->current[i]);
167 0 : if (hv_info->driver[i]->flags & DF_REPORT_STATUS)
168 0 : status = device_driver(hv_info->driver[i], CMD_GET_STATUS,
169 0 : i - hv_info->channel_offset[i],
170 0 : &hv_info->chStatus[i]);
171 0 : if (hv_info->driver[i]->flags & DF_REPORT_TEMP)
172 0 : status = device_driver(hv_info->driver[i], CMD_GET_TEMPERATURE,
173 0 : i - hv_info->channel_offset[i],
174 0 : &hv_info->temperature[i]);
175 0 : if (hv_info->driver[i]->flags & DF_POLL_DEMAND)
176 0 : status = device_driver(hv_info->driver[i], CMD_GET_DEMAND,
177 0 : i - hv_info->channel_offset[i],
178 0 : &hv_info->demand[i]);
179 : }
180 : }
181 :
182 : /* else read only single channel */
183 0 : if (!(hv_info->driver[channel]->flags & DF_MULTITHREAD)) {
184 0 : status = device_driver(hv_info->driver[channel], CMD_GET,
185 0 : channel - hv_info->channel_offset[channel],
186 0 : &hv_info->measured[channel]);
187 0 : status = device_driver(hv_info->driver[channel], CMD_GET_CURRENT,
188 0 : channel - hv_info->channel_offset[channel],
189 0 : &hv_info->current[channel]);
190 0 : if (hv_info->driver[channel]->flags & DF_REPORT_STATUS)
191 0 : status = device_driver(hv_info->driver[channel], CMD_GET_STATUS,
192 0 : channel - hv_info->channel_offset[channel],
193 0 : &hv_info->chStatus[channel]);
194 0 : if (hv_info->driver[channel]->flags & DF_REPORT_TEMP)
195 0 : status = device_driver(hv_info->driver[channel], CMD_GET_TEMPERATURE,
196 0 : channel - hv_info->channel_offset[channel],
197 0 : &hv_info->temperature[channel]);
198 0 : if (hv_info->driver[channel]->flags & DF_POLL_DEMAND)
199 0 : status = device_driver(hv_info->driver[channel], CMD_GET_DEMAND,
200 0 : channel - hv_info->channel_offset[channel],
201 0 : &hv_info->demand[channel]);
202 : }
203 :
204 : // check how much channels have changed since last ODB update
205 0 : act_time = ss_millitime();
206 :
207 : // check for update measured
208 0 : max_diff = 0.f;
209 0 : min_time = 60000;
210 0 : changed = FALSE;
211 0 : for (i = 0; i < hv_info->num_channels; i++) {
212 0 : if (ABS(hv_info->measured[i] - hv_info->measured_mirror[i]) > max_diff)
213 0 : max_diff = ABS(hv_info->measured[i] - hv_info->measured_mirror[i]);
214 :
215 : /* indicate change if variation more than the threshold */
216 0 : if (ABS(hv_info->measured[i] - hv_info->measured_mirror[i]) >
217 0 : hv_info->update_threshold[i] && (ABS(hv_info->measured[i]) > hv_info->zero_threshold[i]))
218 0 : changed = TRUE;
219 :
220 0 : if (!ss_isnan(hv_info->measured[i]) && ss_isnan(hv_info->measured_mirror[i]))
221 0 : changed = TRUE;
222 :
223 0 : if (act_time - hv_info->last_change[i] < min_time)
224 0 : min_time = act_time - hv_info->last_change[i];
225 : }
226 :
227 : /* update if change is more than update_sensitivity or less than 20 seconds ago
228 : or last update is older than a minute */
229 0 : if (changed || (min_time < 20000 && max_diff > 0) ||
230 0 : act_time - hv_info->last_update > 60000) {
231 0 : hv_info->last_update = act_time;
232 :
233 0 : for (i = 0; i < hv_info->num_channels; i++)
234 0 : hv_info->measured_mirror[i] = hv_info->measured[i];
235 :
236 0 : db_set_data(hDB, hv_info->hKeyMeasured, hv_info->measured,
237 0 : sizeof(float) * hv_info->num_channels, hv_info->num_channels,
238 : TID_FLOAT);
239 :
240 0 : pequipment->odb_out++;
241 : }
242 :
243 : // check for update current
244 0 : max_diff = 0.f;
245 0 : min_time = 10000;
246 0 : changed = FALSE;
247 0 : for (i = 0; i < hv_info->num_channels; i++) {
248 0 : if (ABS(hv_info->current[i] - hv_info->current_mirror[i]) > max_diff)
249 0 : max_diff = ABS(hv_info->current[i] - hv_info->current_mirror[i]);
250 :
251 0 : if (ABS(hv_info->current[i] - hv_info->current_mirror[i]) >
252 0 : hv_info->update_threshold_current[i])
253 0 : changed = TRUE;
254 :
255 0 : if (act_time - hv_info->last_change[i] < min_time)
256 0 : min_time = act_time - hv_info->last_change[i];
257 : }
258 :
259 : // update if change is more than update_sensitivity or less than 5sec ago
260 0 : if (changed || (min_time < 5000 && max_diff > 0)) {
261 0 : for (i = 0; i < hv_info->num_channels; i++)
262 0 : hv_info->current_mirror[i] = hv_info->current[i];
263 :
264 0 : db_set_data(hDB, hv_info->hKeyCurrent, hv_info->current,
265 0 : sizeof(float) * hv_info->num_channels, hv_info->num_channels,
266 : TID_FLOAT);
267 :
268 0 : pequipment->odb_out++;
269 : }
270 :
271 : // check for update demand
272 0 : for (i = 0; i < hv_info->num_channels; i++) {
273 0 : if (hv_info->driver[i]->flags & DF_POLL_DEMAND) {
274 0 : if (hv_info->demand[i] != hv_info->demand_mirror[i]) {
275 0 : db_set_data_index(hDB, hv_info->hKeyDemand, &hv_info->demand[i],
276 : sizeof(float), i, TID_FLOAT);
277 0 : hv_info->demand_mirror[i] = hv_info->demand[i];
278 : }
279 :
280 0 : pequipment->odb_out++;
281 : }
282 : }
283 :
284 : // check for updated chStatus
285 0 : max_diff = 0.f;
286 0 : min_time = 60000;
287 0 : changed = FALSE;
288 0 : for (i = 0; i < hv_info->num_channels; i++) {
289 0 : if (hv_info->driver[i]->flags & DF_REPORT_STATUS){
290 0 : if(hv_info->chStatus[i] != hv_info->chStatus_mirror[i])
291 0 : changed = TRUE;
292 :
293 0 : if (act_time - hv_info->last_change[i] < min_time)
294 0 : min_time = act_time - hv_info->last_change[i];
295 : }
296 : }
297 :
298 : // update if change is more than update_sensitivity or less than 20 seconds ago or last update is older than a minute
299 0 : if (changed || (min_time < 20000 && max_diff > 0) ||
300 0 : act_time - hv_info->last_update > 60000) {
301 0 : hv_info->last_update = act_time;
302 :
303 0 : for (i = 0; i < hv_info->num_channels; i++)
304 0 : hv_info->chStatus_mirror[i] = hv_info->chStatus[i];
305 :
306 0 : db_set_data(hDB, hv_info->hKeyChStatus, hv_info->chStatus,
307 0 : sizeof(DWORD) * hv_info->num_channels, hv_info->num_channels,
308 : TID_DWORD);
309 :
310 0 : pequipment->odb_out++;
311 : }
312 :
313 : // check for temperature update
314 0 : max_diff = 0.f;
315 0 : min_time = 60000;
316 0 : changed = FALSE;
317 0 : for (i = 0; i < hv_info->num_channels; i++) {
318 0 : if (hv_info->driver[i]->flags & DF_REPORT_TEMP){
319 0 : if (ABS(hv_info->temperature[i] - hv_info->temperature_mirror[i]) > max_diff)
320 0 : max_diff = ABS(hv_info->temperature[i] - hv_info->temperature_mirror[i]);
321 :
322 : // indicate change if variation more than the threshold
323 0 : if(hv_info->temperature[i] != hv_info->temperature_mirror[i])
324 0 : changed = TRUE;
325 :
326 0 : if (act_time - hv_info->last_change[i] < min_time)
327 0 : min_time = act_time - hv_info->last_change[i];
328 : }
329 : }
330 :
331 : // update if change is more than update_sensitivity or less than 20 seconds ago or last update is older than a minute
332 0 : if (changed || (min_time < 20000 && max_diff > 0) ||
333 0 : act_time - hv_info->last_update > 60000) {
334 0 : hv_info->last_update = act_time;
335 :
336 0 : for (i = 0; i < hv_info->num_channels; i++)
337 0 : hv_info->temperature_mirror[i] = hv_info->temperature[i];
338 :
339 0 : db_set_data(hDB, hv_info->hKeyTemperature, hv_info->temperature,
340 0 : sizeof(float) * hv_info->num_channels, hv_info->num_channels,
341 : TID_FLOAT);
342 :
343 0 : pequipment->odb_out++;
344 : }
345 :
346 0 : return status;
347 : }
348 :
349 : /*------------------------------------------------------------------*/
350 :
351 0 : INT hv_ramp(HV_INFO * hv_info)
352 : {
353 0 : INT i, status = 0, switch_tag = FALSE;
354 0 : float delta, ramp_speed = 0;
355 :
356 0 : for (i = 0; i < hv_info->num_channels; i++) {
357 :
358 0 : if (!ss_isnan(hv_info->demand[i]) &&
359 0 : (hv_info->demand[i] != hv_info->demand_mirror[i])) {
360 :
361 : /* check if to ramp up or down */
362 0 : if ((hv_info->demand[i] >= 0.f) && (hv_info->demand_mirror[i] > 0.f)) {
363 0 : switch_tag = FALSE;
364 0 : if (hv_info->demand[i] > hv_info->demand_mirror[i])
365 0 : ramp_speed = hv_info->rampup_speed[i];
366 : else
367 0 : ramp_speed = hv_info->rampdown_speed[i];
368 : }
369 0 : if ((hv_info->demand[i] >= 0.f) && (hv_info->demand_mirror[i] < 0.f)) {
370 0 : switch_tag = TRUE;
371 0 : ramp_speed = hv_info->rampdown_speed[i];
372 : }
373 0 : if ((hv_info->demand[i] < 0.f) && (hv_info->demand_mirror[i] > 0.f)) {
374 0 : switch_tag = TRUE;
375 0 : ramp_speed = hv_info->rampdown_speed[i];
376 : }
377 0 : if ((hv_info->demand[i] < 0.f) && (hv_info->demand_mirror[i] < 0.f)) {
378 0 : switch_tag = FALSE;
379 0 : if (hv_info->demand[i] > hv_info->demand_mirror[i])
380 0 : ramp_speed = hv_info->rampdown_speed[i];
381 : else
382 0 : ramp_speed = hv_info->rampup_speed[i];
383 : }
384 0 : if (hv_info->demand_mirror[i] == 0.f) {
385 0 : switch_tag = FALSE;
386 0 : ramp_speed = hv_info->rampup_speed[i];
387 : }
388 :
389 0 : if (ramp_speed == 0.f)
390 0 : if (switch_tag)
391 0 : hv_info->demand_mirror[i] = 0.f; /* go to zero */
392 : else
393 0 : hv_info->demand_mirror[i] = hv_info->demand[i]; /* step directly to the new high voltage */
394 : else {
395 0 : delta = (float) ((ss_millitime() -
396 0 : hv_info->last_change[i]) / 1000.0 * ramp_speed);
397 0 : if (delta < HV_MIN_RAMP_STEP)
398 0 : return FE_SUCCESS;
399 :
400 0 : if (hv_info->demand[i] > hv_info->demand_mirror[i])
401 0 : hv_info->demand_mirror[i] =
402 0 : MIN(hv_info->demand[i], hv_info->demand_mirror[i] + delta);
403 : else
404 0 : hv_info->demand_mirror[i] =
405 0 : MAX(hv_info->demand[i], hv_info->demand_mirror[i] - delta);
406 : }
407 0 : status = device_driver(hv_info->driver[i], CMD_SET,
408 0 : i - hv_info->channel_offset[i], hv_info->demand_mirror[i]);
409 0 : hv_info->last_change[i] = ss_millitime();
410 : }
411 : }
412 :
413 0 : return status;
414 : }
415 :
416 :
417 : /*------------------------------------------------------------------*/
418 :
419 0 : void hv_demand(INT hDB, INT hKey, void *info)
420 : {
421 : INT i;
422 : HV_INFO *hv_info;
423 : EQUIPMENT *pequipment;
424 :
425 0 : pequipment = (EQUIPMENT *) info;
426 0 : hv_info = (HV_INFO *) pequipment->cd_info;
427 :
428 : /* check for voltage limit */
429 0 : for (i = 0; i < hv_info->num_channels; i++)
430 0 : if (fabs(hv_info->demand[i]) > fabs(hv_info->voltage_limit[i])) {
431 0 : hv_info->demand[i] = hv_info->voltage_limit[i];
432 :
433 : /* correct value in ODB */
434 0 : db_set_data_index(hDB, hv_info->hKeyDemand, &hv_info->demand[i],
435 : sizeof(float), i, TID_FLOAT);
436 : }
437 :
438 : /* set individual channels only if demand value differs */
439 0 : for (i = 0; i < hv_info->num_channels; i++)
440 0 : if (hv_info->demand[i] != hv_info->demand_mirror[i])
441 0 : hv_info->last_change[i] = ss_millitime();
442 :
443 0 : pequipment->odb_in++;
444 :
445 0 : for (i = 0; i < hv_info->num_channels; i++) {
446 : /* if device can do hardware ramping, just set value */
447 0 : if (hv_info->driver[i]->flags & DF_HW_RAMP) {
448 0 : if (!ss_isnan(hv_info->demand[i]) &&
449 0 : (hv_info->demand[i] != hv_info->demand_mirror[i])) {
450 0 : device_driver(hv_info->driver[i], CMD_SET,
451 0 : i - hv_info->channel_offset[i], hv_info->demand[i]);
452 0 : hv_info->last_change[i] = ss_millitime();
453 0 : hv_info->demand_mirror[i] = hv_info->demand[i];
454 : }
455 : }
456 : }
457 :
458 : /* execute one ramping for devices which have not hardware ramping */
459 0 : hv_ramp(hv_info);
460 0 : }
461 :
462 : /*------------------------------------------------------------------*/
463 :
464 0 : void hv_set_trip_time(INT hDB, INT hKey, void *info)
465 : {
466 : INT i;
467 : HV_INFO *hv_info;
468 : EQUIPMENT *pequipment;
469 :
470 0 : pequipment = (EQUIPMENT *) info;
471 0 : hv_info = (HV_INFO *) pequipment->cd_info;
472 :
473 : /* check for voltage limit */
474 0 : for (i = 0; i < hv_info->num_channels; i++)
475 0 : device_driver(hv_info->driver[i], CMD_SET_TRIP_TIME,
476 0 : i - hv_info->channel_offset[i], hv_info->trip_time[i]);
477 :
478 0 : pequipment->odb_in++;
479 0 : }
480 :
481 : /*------------------------------------------------------------------*/
482 :
483 0 : void hv_set_current_limit(INT hDB, INT hKey, void *info)
484 : {
485 : INT i;
486 : HV_INFO *hv_info;
487 : EQUIPMENT *pequipment;
488 :
489 0 : pequipment = (EQUIPMENT *) info;
490 0 : hv_info = (HV_INFO *) pequipment->cd_info;
491 :
492 : /* check for voltage limit */
493 0 : for (i = 0; i < hv_info->num_channels; i++)
494 0 : device_driver(hv_info->driver[i], CMD_SET_CURRENT_LIMIT,
495 0 : i - hv_info->channel_offset[i], hv_info->current_limit[i]);
496 :
497 0 : pequipment->odb_in++;
498 0 : }
499 :
500 : /*------------------------------------------------------------------*/
501 :
502 0 : void hv_set_rampup(INT hDB, INT hKey, void *info)
503 : {
504 : INT i;
505 : HV_INFO *hv_info;
506 : EQUIPMENT *pequipment;
507 :
508 0 : pequipment = (EQUIPMENT *) info;
509 0 : hv_info = (HV_INFO *) pequipment->cd_info;
510 :
511 : /* check for voltage limit */
512 0 : for (i = 0; i < hv_info->num_channels; i++)
513 0 : device_driver(hv_info->driver[i], CMD_SET_RAMPUP,
514 0 : i - hv_info->channel_offset[i], hv_info->rampup_speed[i]);
515 :
516 0 : pequipment->odb_in++;
517 0 : }
518 :
519 : /*------------------------------------------------------------------*/
520 :
521 0 : void hv_set_rampdown(INT hDB, INT hKey, void *info)
522 : {
523 : INT i;
524 : HV_INFO *hv_info;
525 : EQUIPMENT *pequipment;
526 :
527 0 : pequipment = (EQUIPMENT *) info;
528 0 : hv_info = (HV_INFO *) pequipment->cd_info;
529 :
530 : /* check for voltage limit */
531 0 : for (i = 0; i < hv_info->num_channels; i++)
532 0 : device_driver(hv_info->driver[i], CMD_SET_RAMPDOWN,
533 0 : i - hv_info->channel_offset[i], hv_info->rampdown_speed[i]);
534 :
535 0 : pequipment->odb_in++;
536 0 : }
537 :
538 : /*------------------------------------------------------------------*/
539 :
540 0 : void hv_set_voltage_limit(INT hDB, INT hKey, void *info)
541 : {
542 : INT i;
543 : HV_INFO *hv_info;
544 : EQUIPMENT *pequipment;
545 :
546 0 : pequipment = (EQUIPMENT *) info;
547 0 : hv_info = (HV_INFO *) pequipment->cd_info;
548 :
549 : /* check for voltage limit */
550 0 : for (i = 0; i < hv_info->num_channels; i++)
551 0 : device_driver(hv_info->driver[i], CMD_SET_VOLTAGE_LIMIT,
552 0 : i - hv_info->channel_offset[i], hv_info->voltage_limit[i]);
553 :
554 0 : pequipment->odb_in++;
555 0 : }
556 :
557 : /*------------------------------------------------------------------*/
558 :
559 0 : void hv_update_label(INT hDB, INT hKey, void *info)
560 : {
561 :
562 : INT i;
563 : HV_INFO *hv_info;
564 : EQUIPMENT *pequipment;
565 :
566 0 : pequipment = (EQUIPMENT *) info;
567 0 : hv_info = (HV_INFO *) pequipment->cd_info;
568 :
569 : //update channel labels based on the midas channel names
570 0 : for (i = 0; i < hv_info->num_channels; i++) {
571 0 : device_driver(hv_info->driver[i], CMD_SET_LABEL, i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
572 : }
573 0 : }
574 :
575 : /*------------------------------------------------------------------*/
576 :
577 0 : void hv_set_chState(INT hDB, INT hKey, void *info)
578 : {
579 : INT i;
580 : HV_INFO *hv_info;
581 : EQUIPMENT *pequipment;
582 :
583 0 : pequipment = (EQUIPMENT *) info;
584 0 : hv_info = (HV_INFO *) pequipment->cd_info;
585 :
586 0 : for (i = 0; i < hv_info->num_channels; i++){
587 0 : device_driver(hv_info->driver[i], CMD_SET_CHSTATE, i - hv_info->channel_offset[i], (double)hv_info->chState[i] );
588 : }
589 :
590 0 : pequipment->odb_in++;
591 0 : }
592 :
593 : /*------------------------------------------------------------------*/
594 :
595 0 : void validate_odb_array(HNDLE hDB, HV_INFO *hv_info, const char *path, double default_value, int cmd,
596 : float *array, void (*callback)(INT,INT,void *) ,EQUIPMENT *pequipment)
597 : {
598 : int i;
599 : HNDLE hKey;
600 :
601 0 : for (i = 0; i < hv_info->num_channels; i++)
602 0 : array[i] = (float)default_value;
603 0 : if (db_find_key(hDB, hv_info->hKeyRoot, path, &hKey) != DB_SUCCESS)
604 0 : for (i = 0; i < hv_info->num_channels; i++)
605 0 : device_driver(hv_info->driver[i], cmd,
606 0 : i - hv_info->channel_offset[i], array + i);
607 0 : db_merge_data(hDB, hv_info->hKeyRoot, path, array, sizeof(float) * hv_info->num_channels,
608 : hv_info->num_channels, TID_FLOAT);
609 0 : db_find_key(hDB, hv_info->hKeyRoot, path, &hKey);
610 0 : assert(hKey);
611 0 : db_open_record(hDB, hKey, array, sizeof(float) * hv_info->num_channels, MODE_READ,
612 : callback, pequipment);
613 0 : }
614 :
615 0 : void validate_odb_array_bool(HNDLE hDB, HV_INFO *hv_info, const char *path, double default_value, int cmd,
616 : DWORD *array, void (*callback)(INT,INT,void *) ,EQUIPMENT *pequipment)
617 : {
618 : int i;
619 : HNDLE hKey;
620 :
621 0 : for (i = 0; i < hv_info->num_channels; i++)
622 0 : array[i] = (DWORD)default_value;
623 0 : if (db_find_key(hDB, hv_info->hKeyRoot, path, &hKey) != DB_SUCCESS)
624 0 : for (i = 0; i < hv_info->num_channels; i++){
625 0 : device_driver(hv_info->driver[i], cmd, i - hv_info->channel_offset[i], array + i);
626 0 : array[i] = 0;
627 : }
628 0 : db_merge_data(hDB, hv_info->hKeyRoot, path, array, sizeof(DWORD) * hv_info->num_channels, hv_info->num_channels, TID_DWORD);
629 0 : db_find_key(hDB, hv_info->hKeyRoot, path, &hKey);
630 0 : assert(hKey);
631 0 : db_open_record(hDB, hKey, array, sizeof(DWORD) * hv_info->num_channels, MODE_READ,
632 : callback, pequipment);
633 0 : }
634 :
635 0 : void validate_odb_int(HNDLE hDB, HV_INFO *hv_info, const char *path, double default_value, int cmd,
636 : int *target, void (*callback)(INT,INT,void *) ,EQUIPMENT *pequipment)
637 : {
638 : int i;
639 : HNDLE hKey;
640 :
641 0 : for (i = 0; i < 1; i++)
642 0 : target[i] = (INT)default_value;
643 0 : if (db_find_key(hDB, hv_info->hKeyRoot, path, &hKey) != DB_SUCCESS)
644 0 : for (i = 0; i < 1; i++){
645 0 : device_driver(hv_info->driver[i], cmd, i - hv_info->channel_offset[i], target + i);
646 : }
647 0 : db_merge_data(hDB, hv_info->hKeyRoot, path, target, sizeof(INT), 1, TID_INT);
648 0 : db_find_key(hDB, hv_info->hKeyRoot, path, &hKey);
649 0 : assert(hKey);
650 0 : db_open_record(hDB, hKey, target, sizeof(INT), MODE_READ,callback, pequipment);
651 0 : }
652 :
653 : /*------------------------------------------------------------------*/
654 :
655 0 : INT hv_init(EQUIPMENT * pequipment)
656 : {
657 : int status, size, i, j, index, offset;
658 : char str[256];
659 : HNDLE hDB, hKey;
660 : HV_INFO *hv_info;
661 : BOOL partially_disabled;
662 :
663 : /* allocate private data */
664 0 : pequipment->cd_info = calloc(1, sizeof(HV_INFO));
665 0 : hv_info = (HV_INFO *) pequipment->cd_info;
666 :
667 : /* get class driver root key */
668 0 : cm_get_experiment_database(&hDB, NULL);
669 0 : sprintf(str, "/Equipment/%s", pequipment->name);
670 0 : db_create_key(hDB, 0, str, TID_KEY);
671 0 : db_find_key(hDB, 0, str, &hv_info->hKeyRoot);
672 :
673 : /* save event format */
674 0 : size = sizeof(str);
675 0 : db_get_value(hDB, hv_info->hKeyRoot, "Common/Format", str, &size, TID_STRING, TRUE);
676 :
677 0 : if (equal_ustring(str, "Fixed"))
678 0 : hv_info->format = FORMAT_FIXED;
679 0 : else if (equal_ustring(str, "MIDAS"))
680 0 : hv_info->format = FORMAT_MIDAS;
681 : else {
682 0 : hv_info->format = 0;
683 0 : cm_msg(MERROR, "hv_init", "Unknown Common/Format \"%s\", should be FIXED or MIDAS", str);
684 0 : return FE_ERR_ODB;
685 : }
686 :
687 : /* count total number of channels */
688 0 : for (i = 0, hv_info->num_channels = 0; pequipment->driver[i].name[0]; i++) {
689 0 : if (pequipment->driver[i].channels == 0) {
690 0 : cm_msg(MERROR, "hv_init", "Driver with zero channels not allowed");
691 0 : return FE_ERR_ODB;
692 : }
693 :
694 0 : hv_info->num_channels += pequipment->driver[i].channels;
695 : }
696 :
697 0 : if (hv_info->num_channels == 0) {
698 0 : cm_msg(MERROR, "hv_init", "No channels found in device driver list");
699 0 : return FE_ERR_ODB;
700 : }
701 :
702 : /* Allocate memory for buffers */
703 0 : hv_info->names = (char *) calloc(hv_info->num_channels, NAME_LENGTH);
704 :
705 0 : hv_info->demand = (float *) calloc(hv_info->num_channels, sizeof(float));
706 0 : hv_info->measured = (float *) calloc(hv_info->num_channels, sizeof(float));
707 0 : hv_info->current = (float *) calloc(hv_info->num_channels, sizeof(float));
708 0 : hv_info->chStatus = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
709 0 : hv_info->temperature = (float *) calloc(hv_info->num_channels, sizeof(float));
710 :
711 0 : hv_info->update_threshold = (float *) calloc(hv_info->num_channels, sizeof(float));
712 0 : hv_info->update_threshold_current = (float *) calloc(hv_info->num_channels, sizeof(float));
713 0 : hv_info->zero_threshold = (float *) calloc(hv_info->num_channels, sizeof(float));
714 0 : hv_info->voltage_limit = (float *) calloc(hv_info->num_channels, sizeof(float));
715 0 : hv_info->current_limit = (float *) calloc(hv_info->num_channels, sizeof(float));
716 0 : hv_info->rampup_speed = (float *) calloc(hv_info->num_channels, sizeof(float));
717 0 : hv_info->rampdown_speed = (float *) calloc(hv_info->num_channels, sizeof(float));
718 0 : hv_info->trip_time = (float *) calloc(hv_info->num_channels, sizeof(float));
719 0 : hv_info->chState = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
720 0 : hv_info->crateMap = (INT *) calloc(hv_info->num_channels, sizeof(INT));
721 :
722 0 : hv_info->demand_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
723 0 : hv_info->measured_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
724 0 : hv_info->current_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
725 0 : hv_info->chStatus_mirror = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
726 0 : hv_info->temperature_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
727 0 : hv_info->last_change = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
728 :
729 0 : hv_info->dd_info = (void **) calloc(hv_info->num_channels, sizeof(void *));
730 0 : hv_info->channel_offset = (INT *) calloc(hv_info->num_channels, sizeof(INT));
731 0 : hv_info->driver = (DEVICE_DRIVER **) calloc(hv_info->num_channels, sizeof(void *));
732 :
733 0 : if (!hv_info->driver) {
734 0 : cm_msg(MERROR, "hv_init", "Not enough memory");
735 0 : return FE_ERR_ODB;
736 : }
737 :
738 : /*---- Initialize device drivers ----*/
739 :
740 : /* call init method */
741 0 : partially_disabled = FALSE;
742 0 : for (i = 0; pequipment->driver[i].name[0]; i++) {
743 0 : sprintf(str, "Settings/Devices/%s", pequipment->driver[i].name);
744 0 : status = db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
745 0 : if (status != DB_SUCCESS) {
746 0 : db_create_key(hDB, hv_info->hKeyRoot, str, TID_KEY);
747 0 : status = db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
748 0 : if (status != DB_SUCCESS) {
749 0 : cm_msg(MERROR, "hv_init", "Cannot create %s entry in online database", str);
750 0 : free_mem(hv_info);
751 0 : return FE_ERR_ODB;
752 : }
753 : }
754 :
755 : /* check enabled flag */
756 0 : size = sizeof(pequipment->driver[i].enabled);
757 0 : pequipment->driver[i].enabled = 1;
758 0 : sprintf(str, "Settings/Devices/%s/Enabled", pequipment->driver[i].name);
759 0 : status = db_get_value(hDB, hv_info->hKeyRoot, str, &pequipment->driver[i].enabled, &size, TID_BOOL, TRUE);
760 0 : if (status != DB_SUCCESS)
761 0 : return FE_ERR_ODB;
762 :
763 0 : if (pequipment->driver[i].enabled) {
764 0 : printf("Connecting %s...", pequipment->driver[i].name);
765 0 : fflush(stdout);
766 0 : status = device_driver(&pequipment->driver[i], CMD_INIT, hKey);
767 0 : if (status != FE_SUCCESS) {
768 0 : free_mem(hv_info);
769 0 : return status;
770 : }
771 0 : printf("OK\n");
772 : } else
773 0 : partially_disabled = TRUE;
774 : }
775 :
776 : /* compose device driver channel assignment */
777 0 : for (i = 0, j = 0, index = 0, offset = 0; i < hv_info->num_channels; i++, j++) {
778 0 : while (j >= pequipment->driver[index].channels && pequipment->driver[index].name[0]) {
779 0 : offset += j;
780 0 : index++;
781 0 : j = 0;
782 : }
783 :
784 0 : hv_info->driver[i] = &pequipment->driver[index];
785 0 : hv_info->channel_offset[i] = offset;
786 : }
787 :
788 : /*---- Create/Read settings ----*/
789 :
790 0 : db_create_key(hDB, hv_info->hKeyRoot, "Settings/Editable", TID_STRING);
791 0 : status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Editable", &hKey);
792 0 : if (status == DB_SUCCESS) {
793 0 : const int kSize = 10;
794 : char editable[kSize][NAME_LENGTH];
795 : int count;
796 0 : for (i = 0; i < kSize; i++)
797 0 : editable[i][0] = 0;
798 0 : count = 0;
799 0 : strcpy(editable[count++], "Demand");
800 0 : if (hv_info->driver[0]->flags & DF_REPORT_CHSTATE)
801 0 : strcpy(editable[count++], "ChState");
802 0 : db_set_data(hDB, hKey, editable, count * NAME_LENGTH, count, TID_STRING);
803 : }
804 :
805 : // Names
806 0 : for (i = 0; i < hv_info->num_channels; i++){
807 0 : if((hv_info->driver[i]->flags & DF_LABELS_FROM_DEVICE) == 0)
808 0 : sprintf(hv_info->names + NAME_LENGTH * i, "Default%%CH %d", i);
809 : }
810 :
811 0 : if (db_find_key(hDB, hv_info->hKeyRoot, "Settings/Names", &hKey) != DB_SUCCESS)
812 0 : for (i = 0; i < hv_info->num_channels; i++)
813 0 : device_driver(hv_info->driver[i], CMD_GET_LABEL, i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
814 :
815 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Settings/Names", hv_info->names, NAME_LENGTH * hv_info->num_channels, hv_info->num_channels, TID_STRING);
816 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Names", &hKey);
817 0 : assert(hKey);
818 0 : db_open_record(hDB, hKey, hv_info->names, NAME_LENGTH * hv_info->num_channels, MODE_READ, NULL, pequipment);
819 :
820 : /* Unit */
821 0 : status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Demand", &hKey);
822 0 : if (status == DB_NO_KEY) {
823 0 : int n = hv_info->num_channels;
824 0 : char *unit = (char *)calloc(n, 32);
825 0 : for (int ii=0 ; ii<n ; ii++)
826 0 : mstrlcpy(unit + ii*32, "V", 32);
827 0 : db_create_key(hDB, hv_info->hKeyRoot, "Settings/Unit Demand", TID_STRING);
828 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Demand", &hKey);
829 0 : db_set_data(hDB, hKey, unit, n*32, n, TID_STRING);
830 0 : free(unit);
831 : }
832 0 : status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Measured", &hKey);
833 0 : if (status == DB_NO_KEY) {
834 0 : int n = hv_info->num_channels;
835 0 : char *unit = (char *)calloc(n, 32);
836 0 : for (int ii=0 ; ii<n ; ii++)
837 0 : mstrlcpy(unit + ii*32, "V", 32);
838 0 : db_create_key(hDB, hv_info->hKeyRoot, "Settings/Unit Measured", TID_STRING);
839 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Measured", &hKey);
840 0 : db_set_data(hDB, hKey, unit, n*32, n, TID_STRING);
841 0 : free(unit);
842 : }
843 0 : status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Current", &hKey);
844 0 : if (status == DB_NO_KEY) {
845 0 : int n = hv_info->num_channels;
846 0 : char *unit = (char *)calloc(n, 32);
847 0 : for (int ii=0 ; ii<n ; ii++)
848 0 : mstrlcpy(unit + ii*32, "uA", 32);
849 0 : db_create_key(hDB, hv_info->hKeyRoot, "Settings/Unit Current", TID_STRING);
850 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Current", &hKey);
851 0 : db_set_data(hDB, hKey, unit, n*32, n, TID_STRING);
852 0 : free(unit);
853 : }
854 :
855 : /* Format */
856 0 : status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Demand", &hKey);
857 0 : if (status == DB_NO_KEY) {
858 0 : int n = hv_info->num_channels;
859 0 : char *format = (char *)calloc(n, 32);
860 0 : for (int ii=0 ; ii<n ; ii++)
861 0 : mstrlcpy(format + ii*32, "%f2", 32);
862 0 : db_create_key(hDB, hv_info->hKeyRoot, "Settings/Format Demand", TID_STRING);
863 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Demand", &hKey);
864 0 : db_set_data(hDB, hKey, format, n*32, n, TID_STRING);
865 0 : free(format);
866 : }
867 0 : status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Measured", &hKey);
868 0 : if (status == DB_NO_KEY) {
869 0 : int n = hv_info->num_channels;
870 0 : char *format = (char *)calloc(n, 32);
871 0 : for (int ii=0 ; ii<n ; ii++)
872 0 : mstrlcpy(format + ii*32, "%f2", 32);
873 0 : db_create_key(hDB, hv_info->hKeyRoot, "Settings/Format Measured", TID_STRING);
874 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Measured", &hKey);
875 0 : db_set_data(hDB, hKey, format, n*32, n, TID_STRING);
876 0 : free(format);
877 : }
878 0 : status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Current", &hKey);
879 0 : if (status == DB_NO_KEY) {
880 0 : int n = hv_info->num_channels;
881 0 : char *format = (char *)calloc(n, 32);
882 0 : for (int ii=0 ; ii<n ; ii++)
883 0 : mstrlcpy(format + ii*32, "%f2", 32);
884 0 : db_create_key(hDB, hv_info->hKeyRoot, "Settings/Format Current", TID_STRING);
885 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Current", &hKey);
886 0 : db_set_data(hDB, hKey, format, n*32, n, TID_STRING);
887 0 : free(format);
888 : }
889 :
890 : /* Update threshold */
891 0 : validate_odb_array(hDB, hv_info, "Settings/Update Threshold Measured", 0.5, CMD_GET_THRESHOLD,
892 : hv_info->update_threshold, NULL, NULL);
893 :
894 : /* Update threshold current */
895 0 : validate_odb_array(hDB, hv_info, "Settings/Update Threshold Current", 1, CMD_GET_THRESHOLD_CURRENT,
896 : hv_info->update_threshold_current, NULL, NULL);
897 :
898 : /* Zero threshold */
899 0 : validate_odb_array(hDB, hv_info, "Settings/Zero Threshold", 20, CMD_GET_THRESHOLD_ZERO,
900 : hv_info->zero_threshold, NULL, NULL);
901 :
902 : /* Voltage limit */
903 0 : validate_odb_array(hDB, hv_info, "Settings/Voltage Limit", 3000, CMD_GET_VOLTAGE_LIMIT,
904 : hv_info->voltage_limit, hv_set_voltage_limit, pequipment);
905 :
906 : /* Current limit */
907 0 : validate_odb_array(hDB, hv_info, "Settings/Current Limit", 3000, CMD_GET_CURRENT_LIMIT,
908 : hv_info->current_limit, hv_set_current_limit, pequipment);
909 :
910 : /* Trip Time */
911 0 : validate_odb_array(hDB, hv_info, "Settings/Trip Time", 10, CMD_GET_TRIP_TIME,
912 : hv_info->trip_time, hv_set_trip_time, pequipment);
913 :
914 : /* Ramp up */
915 0 : validate_odb_array(hDB, hv_info, "Settings/Ramp Up Speed", 0, CMD_GET_RAMPUP,
916 : hv_info->rampup_speed, hv_set_rampup, pequipment);
917 :
918 : /* Ramp down */
919 0 : validate_odb_array(hDB, hv_info, "Settings/Ramp Down Speed", 0, CMD_GET_RAMPDOWN,
920 : hv_info->rampdown_speed, hv_set_rampdown, pequipment);
921 :
922 : /* Crate Map */
923 0 : if (hv_info->driver[0]->flags & DF_REPORT_CRATEMAP) {
924 0 : sprintf(str, "Settings/Devices/%s/DD/crateMap", pequipment->driver[0].name);
925 0 : validate_odb_int(hDB, hv_info, str, 'n', CMD_GET_CRATEMAP,
926 : hv_info->crateMap, NULL, pequipment);
927 : }
928 :
929 : /*---- Create/Read variables ----*/
930 :
931 : /* Demand */
932 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Demand",
933 0 : hv_info->demand, sizeof(float) * hv_info->num_channels,
934 : hv_info->num_channels, TID_FLOAT);
935 0 : db_find_key(hDB, hv_info->hKeyRoot, "Variables/Demand", &hv_info->hKeyDemand);
936 :
937 : /* Measured */
938 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Measured",
939 0 : hv_info->measured, sizeof(float) * hv_info->num_channels,
940 : hv_info->num_channels, TID_FLOAT);
941 0 : db_find_key(hDB, hv_info->hKeyRoot, "Variables/Measured", &hv_info->hKeyMeasured);
942 0 : memcpy(hv_info->measured_mirror, hv_info->measured,
943 0 : hv_info->num_channels * sizeof(float));
944 :
945 : /* Current */
946 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Current",
947 0 : hv_info->current, sizeof(float) * hv_info->num_channels,
948 : hv_info->num_channels, TID_FLOAT);
949 0 : db_find_key(hDB, hv_info->hKeyRoot, "Variables/Current", &hv_info->hKeyCurrent);
950 0 : memcpy(hv_info->current_mirror, hv_info->current,
951 0 : hv_info->num_channels * sizeof(float));
952 :
953 : /* Channel State */
954 0 : if (hv_info->driver[0]->flags & DF_REPORT_CHSTATE)
955 0 : validate_odb_array_bool(hDB, hv_info, "Variables/ChState", 'n', CMD_GET_CHSTATE,
956 : hv_info->chState, hv_set_chState, pequipment);
957 :
958 : /* Status */
959 0 : if (hv_info->driver[0]->flags & DF_REPORT_STATUS){
960 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Variables/ChStatus",
961 0 : hv_info->chStatus, sizeof(DWORD) * hv_info->num_channels,
962 : hv_info->num_channels, TID_DWORD);
963 0 : db_find_key(hDB, hv_info->hKeyRoot, "Variables/ChStatus", &hv_info->hKeyChStatus);
964 0 : memcpy(hv_info->chStatus_mirror, hv_info->chStatus,
965 0 : hv_info->num_channels * sizeof(DWORD));
966 : }
967 :
968 : /* Temperature */
969 0 : if (hv_info->driver[0]->flags & DF_REPORT_TEMP){
970 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Temperature",
971 0 : hv_info->temperature, sizeof(float) * hv_info->num_channels,
972 : hv_info->num_channels, TID_FLOAT);
973 0 : db_find_key(hDB, hv_info->hKeyRoot, "Variables/Temperature", &hv_info->hKeyTemperature);
974 0 : memcpy(hv_info->temperature_mirror, hv_info->temperature,
975 0 : hv_info->num_channels * sizeof(float));
976 : }
977 :
978 : /*---- set labels from midas SC names ----*/
979 0 : for (i = 0; i < hv_info->num_channels; i++) {
980 0 : if ((hv_info->driver[i]->flags & DF_LABELS_FROM_DEVICE) == 0)
981 0 : status = device_driver(hv_info->driver[i], CMD_SET_LABEL,
982 0 : i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
983 : }
984 :
985 : /*---- set/get values ----*/
986 0 : for (i = 0; i < hv_info->num_channels; i++) {
987 0 : if ((hv_info->driver[i]->flags & DF_PRIO_DEVICE) == 0) {
988 0 : hv_info->demand_mirror[i] = MIN(hv_info->demand[i], hv_info->voltage_limit[i]);
989 0 : status = device_driver(hv_info->driver[i], CMD_SET,
990 0 : i - hv_info->channel_offset[i], hv_info->demand_mirror[i]);
991 0 : status = device_driver(hv_info->driver[i], CMD_SET_TRIP_TIME,
992 0 : i - hv_info->channel_offset[i], hv_info->trip_time[i]);
993 0 : status = device_driver(hv_info->driver[i], CMD_SET_CURRENT_LIMIT,
994 0 : i - hv_info->channel_offset[i], hv_info->current_limit[i]);
995 0 : status = device_driver(hv_info->driver[i], CMD_SET_VOLTAGE_LIMIT,
996 0 : i - hv_info->channel_offset[i], hv_info->voltage_limit[i]);
997 0 : if(hv_info->driver[i]->flags & DF_HW_RAMP){
998 0 : status = device_driver(hv_info->driver[i], CMD_SET_RAMPUP,
999 0 : i - hv_info->channel_offset[i], hv_info->rampup_speed[i]);
1000 0 : status = device_driver(hv_info->driver[i], CMD_SET_RAMPDOWN,
1001 0 : i - hv_info->channel_offset[i], hv_info->rampdown_speed[i]);
1002 : }
1003 0 : if (hv_info->driver[i]->flags & DF_REPORT_CHSTATE)
1004 0 : status = device_driver(hv_info->driver[i], CMD_SET_CHSTATE,
1005 0 : i - hv_info->channel_offset[i], (double)hv_info->chState[i]);
1006 : } else {
1007 0 : if (hv_info->driver[i]->flags & DF_POLL_DEMAND) {
1008 0 : hv_info->demand[i] = ss_nan();
1009 0 : hv_info->demand_mirror[i] = ss_nan();
1010 : } else {
1011 : // use CMD_GET_DEMAND_DIRECT, since demand value coming from thread has not yet
1012 : // been placed in buffer
1013 0 : status = device_driver(hv_info->driver[i], CMD_GET_DEMAND_DIRECT,
1014 0 : i - hv_info->channel_offset[i], hv_info->demand + i);
1015 0 : hv_info->demand_mirror[i] = hv_info->demand[i];
1016 : }
1017 :
1018 0 : status = device_driver(hv_info->driver[i], CMD_GET_TRIP_TIME,
1019 0 : i - hv_info->channel_offset[i], &hv_info->trip_time[i]);
1020 0 : status = device_driver(hv_info->driver[i], CMD_GET_CURRENT_LIMIT,
1021 0 : i - hv_info->channel_offset[i], &hv_info->current_limit[i]);
1022 0 : status = device_driver(hv_info->driver[i], CMD_GET_VOLTAGE_LIMIT,
1023 0 : i - hv_info->channel_offset[i], &hv_info->voltage_limit[i]);
1024 0 : if (hv_info->driver[i]->flags & DF_HW_RAMP) {
1025 0 : status = device_driver(hv_info->driver[i], CMD_GET_RAMPUP,
1026 0 : i - hv_info->channel_offset[i], &hv_info->rampup_speed[i]);
1027 0 : status = device_driver(hv_info->driver[i], CMD_GET_RAMPDOWN,
1028 0 : i - hv_info->channel_offset[i], &hv_info->rampdown_speed[i]);
1029 : }
1030 0 : if (hv_info->driver[i]->flags & DF_REPORT_CHSTATE)
1031 0 : status = device_driver(hv_info->driver[i], CMD_GET_CHSTATE,
1032 0 : i - hv_info->channel_offset[i], &hv_info->chState[i]);
1033 0 : if (hv_info->driver[i]->flags & DF_REPORT_CRATEMAP)
1034 0 : status = device_driver(hv_info->driver[i], CMD_GET_CRATEMAP,
1035 0 : i - hv_info->channel_offset[i], &hv_info->crateMap[i]);
1036 : }
1037 : }
1038 :
1039 0 : db_set_record(hDB, hv_info->hKeyDemand, hv_info->demand,
1040 0 : hv_info->num_channels * sizeof(float), 0);
1041 :
1042 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Trip Time", &hKey);
1043 0 : db_set_record(hDB, hKey, hv_info->trip_time, hv_info->num_channels * sizeof(float), 0);
1044 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Current Limit", &hKey);
1045 0 : db_set_record(hDB, hKey, hv_info->current_limit, hv_info->num_channels * sizeof(float), 0);
1046 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Voltage Limit", &hKey);
1047 0 : db_set_record(hDB, hKey, hv_info->voltage_limit, hv_info->num_channels * sizeof(float), 0);
1048 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Ramp Up Speed", &hKey);
1049 0 : db_set_record(hDB, hKey, hv_info->rampup_speed, hv_info->num_channels * sizeof(float), 0);
1050 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Ramp Down Speed", &hKey);
1051 0 : db_set_record(hDB, hKey, hv_info->rampdown_speed, hv_info->num_channels * sizeof(float), 0);
1052 0 : if (hv_info->driver[0]->flags & DF_REPORT_CHSTATE){
1053 0 : db_find_key(hDB, hv_info->hKeyRoot, "Variables/ChState", &hKey);
1054 0 : db_set_record(hDB, hKey, hv_info->chState, hv_info->num_channels * sizeof(DWORD), 'n');
1055 : }
1056 0 : if (hv_info->driver[0]->flags & DF_REPORT_CRATEMAP){
1057 0 : sprintf(str, "Settings/Devices/%s/DD/crateMap", pequipment->driver[0].name);
1058 0 : db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
1059 0 : db_set_record(hDB, hKey, hv_info->crateMap, sizeof(INT), 'n');
1060 : }
1061 :
1062 : /*--- open hotlink to HV demand values ----*/
1063 0 : db_open_record(hDB, hv_info->hKeyDemand, hv_info->demand,
1064 0 : hv_info->num_channels * sizeof(float), MODE_READ, hv_demand,
1065 : pequipment);
1066 :
1067 : /* initially read all channels */
1068 0 : for (i=0 ; i<hv_info->num_channels ; i++) {
1069 0 : if ((hv_info->driver[i]->flags & DF_QUICKSTART) == 0) {
1070 0 : if (hv_info->driver[i]->enabled) {
1071 0 : hv_info->driver[i]->dd(CMD_GET, hv_info->driver[i]->dd_info,
1072 0 : i - hv_info->channel_offset[i], &hv_info->measured[i]);
1073 0 : hv_info->driver[i]->dd(CMD_GET_CURRENT, hv_info->driver[i]->dd_info,
1074 0 : i - hv_info->channel_offset[i], &hv_info->current[i]);
1075 0 : if (hv_info->driver[i]->flags & DF_REPORT_STATUS)
1076 0 : hv_info->driver[i]->dd(CMD_GET_STATUS, hv_info->driver[i]->dd_info,
1077 0 : i - hv_info->channel_offset[i], &hv_info->chStatus[i]);
1078 0 : if (hv_info->driver[i]->flags & DF_REPORT_TEMP)
1079 0 : hv_info->driver[i]->dd(CMD_GET_TEMPERATURE, hv_info->driver[i]->dd_info,
1080 0 : i - hv_info->channel_offset[i], &hv_info->temperature[i]);
1081 :
1082 0 : hv_info->measured_mirror[i] = hv_info->measured[i];
1083 0 : hv_info->current_mirror[i] = hv_info->current[i];
1084 0 : hv_info->chStatus_mirror[i] = hv_info->chStatus[i];
1085 0 : hv_info->temperature_mirror[i] = hv_info->temperature[i];
1086 :
1087 0 : db_set_data_index(hDB, hv_info->hKeyCurrent, &hv_info->current[i], sizeof(float), i, TID_FLOAT);
1088 :
1089 0 : if (hv_info->driver[0]->flags & DF_REPORT_STATUS)
1090 0 : db_set_data_index(hDB, hv_info->hKeyChStatus, &hv_info->chStatus[i],
1091 : sizeof(DWORD), i, TID_DWORD);
1092 :
1093 0 : if (hv_info->driver[0]->flags & DF_REPORT_TEMP)
1094 0 : db_set_data_index(hDB, hv_info->hKeyTemperature, &hv_info->temperature[i],
1095 0 : sizeof(float) * hv_info->num_channels, hv_info->num_channels,
1096 : TID_FLOAT);
1097 :
1098 : }
1099 : }
1100 : }
1101 :
1102 0 : pequipment->odb_out++;
1103 :
1104 0 : if (partially_disabled)
1105 0 : return FE_PARTIALLY_DISABLED;
1106 :
1107 0 : return FE_SUCCESS;
1108 : }
1109 :
1110 : /*------------------------------------------------------------------*/
1111 :
1112 0 : INT hv_exit(EQUIPMENT * pequipment)
1113 : {
1114 : INT i;
1115 :
1116 0 : free_mem((HV_INFO *) pequipment->cd_info);
1117 :
1118 : /* call exit method of device drivers */
1119 0 : for (i = 0; pequipment->driver[i].dd != NULL; i++)
1120 0 : device_driver(&pequipment->driver[i], CMD_EXIT);
1121 :
1122 0 : return FE_SUCCESS;
1123 : }
1124 :
1125 : /*------------------------------------------------------------------*/
1126 :
1127 0 : INT hv_idle(EQUIPMENT * pequipment)
1128 : {
1129 0 : INT act, status = 0;
1130 : DWORD act_time;
1131 : HV_INFO *hv_info;
1132 :
1133 0 : hv_info = (HV_INFO *) pequipment->cd_info;
1134 :
1135 : /* do ramping */
1136 0 : hv_ramp(hv_info);
1137 :
1138 0 : if (hv_info->driver[0]->flags & DF_MULTITHREAD) {
1139 : // hv_read reads all channels
1140 0 : status = hv_read(pequipment, 0);
1141 : } else {
1142 : /* select next measurement channel */
1143 0 : hv_info->last_channel = (hv_info->last_channel + 1) % hv_info->num_channels;
1144 :
1145 : /* measure channel */
1146 0 : status = hv_read(pequipment, hv_info->last_channel);
1147 : }
1148 :
1149 : /* additionally read channel recently updated if not multithreaded */
1150 0 : if (!(hv_info->driver[hv_info->last_channel]->flags & DF_MULTITHREAD)) {
1151 :
1152 0 : act_time = ss_millitime();
1153 :
1154 0 : act = (hv_info->last_channel_updated + 1) % hv_info->num_channels;
1155 0 : while (!(act_time - hv_info->last_change[act] < 10000)) {
1156 0 : act = (act + 1) % hv_info->num_channels;
1157 0 : if (act == hv_info->last_channel_updated) {
1158 : /* non found, so return */
1159 0 : return status;
1160 : }
1161 : }
1162 :
1163 : /* updated channel found, so read it additionally */
1164 0 : status = hv_read(pequipment, act);
1165 0 : hv_info->last_channel_updated = act;
1166 : }
1167 :
1168 0 : return status;
1169 : }
1170 :
1171 : /*------------------------------------------------------------------*/
1172 :
1173 0 : INT cd_hv_read(char *pevent, int offset)
1174 : {
1175 : float *pdata;
1176 :
1177 0 : EQUIPMENT* pequipment = *((EQUIPMENT **) pevent);
1178 0 : HV_INFO* hv_info = (HV_INFO *) pequipment->cd_info;
1179 :
1180 0 : if (hv_info->format == FORMAT_FIXED) {
1181 0 : memcpy(pevent, hv_info->demand, sizeof(float) * hv_info->num_channels);
1182 0 : pevent += sizeof(float) * hv_info->num_channels;
1183 :
1184 0 : memcpy(pevent, hv_info->measured, sizeof(float) * hv_info->num_channels);
1185 0 : pevent += sizeof(float) * hv_info->num_channels;
1186 :
1187 0 : memcpy(pevent, hv_info->current, sizeof(float) * hv_info->num_channels);
1188 0 : pevent += sizeof(float) * hv_info->num_channels;
1189 :
1190 0 : memcpy(pevent, hv_info->chStatus, sizeof(DWORD) * hv_info->num_channels);
1191 0 : pevent += sizeof(DWORD) * hv_info->num_channels;
1192 :
1193 0 : memcpy(pevent, hv_info->temperature, sizeof(float) * hv_info->num_channels);
1194 0 : pevent += sizeof(float) * hv_info->num_channels;
1195 :
1196 0 : return ( 4 * sizeof(float) + sizeof(DWORD) )* hv_info->num_channels;
1197 0 : } else if (hv_info->format == FORMAT_MIDAS) {
1198 0 : bk_init32(pevent);
1199 :
1200 : /* create DMND bank */
1201 0 : bk_create(pevent, "DMND", TID_FLOAT, (void **)&pdata);
1202 0 : memcpy(pdata, hv_info->demand, sizeof(float) * hv_info->num_channels);
1203 0 : pdata += hv_info->num_channels;
1204 0 : bk_close(pevent, pdata);
1205 :
1206 : /* create MSRD bank */
1207 0 : bk_create(pevent, "MSRD", TID_FLOAT, (void **)&pdata);
1208 0 : memcpy(pdata, hv_info->measured, sizeof(float) * hv_info->num_channels);
1209 0 : pdata += hv_info->num_channels;
1210 0 : bk_close(pevent, pdata);
1211 :
1212 : /* create CRNT bank */
1213 0 : bk_create(pevent, "CRNT", TID_FLOAT, (void **)&pdata);
1214 0 : memcpy(pdata, hv_info->current, sizeof(float) * hv_info->num_channels);
1215 0 : pdata += hv_info->num_channels;
1216 0 : bk_close(pevent, pdata);
1217 :
1218 : /* create STAT bank */
1219 0 : bk_create(pevent, "STAT", TID_DWORD, (void **)&pdata);
1220 0 : memcpy(pdata, hv_info->chStatus, sizeof(DWORD) * hv_info->num_channels);
1221 0 : pdata += hv_info->num_channels;
1222 0 : bk_close(pevent, pdata);
1223 :
1224 : /* create TPTR bank */
1225 0 : bk_create(pevent, "TPTR", TID_FLOAT, (void **)&pdata);
1226 0 : memcpy(pdata, hv_info->temperature, sizeof(float) * hv_info->num_channels);
1227 0 : pdata += hv_info->num_channels;
1228 0 : bk_close(pevent, pdata);
1229 :
1230 0 : return bk_size(pevent);
1231 : } else {
1232 0 : assert(!"unsupported hv_info->format");
1233 : }
1234 :
1235 : return 0;
1236 : }
1237 :
1238 : /*------------------------------------------------------------------*/
1239 :
1240 0 : INT cd_hv(INT cmd, PEQUIPMENT pequipment)
1241 : {
1242 : INT status;
1243 :
1244 0 : switch (cmd) {
1245 0 : case CMD_INIT:
1246 0 : status = hv_init(pequipment);
1247 0 : break;
1248 :
1249 0 : case CMD_EXIT:
1250 0 : status = hv_exit(pequipment);
1251 0 : break;
1252 :
1253 0 : case CMD_START:
1254 0 : status = hv_start(pequipment);
1255 0 : break;
1256 :
1257 0 : case CMD_STOP:
1258 0 : status = hv_stop(pequipment);
1259 0 : break;
1260 :
1261 0 : case CMD_IDLE:
1262 0 : status = hv_idle(pequipment);
1263 0 : break;
1264 :
1265 0 : default:
1266 0 : cm_msg(MERROR, "HV class driver", "Received unknown command %d", cmd);
1267 0 : status = FE_ERR_DRIVER;
1268 0 : break;
1269 : }
1270 :
1271 0 : return status;
1272 : }
|