Line data Source code
1 : /********************************************************************\
2 :
3 : Name: cd_ivc32.c
4 : Created by: Pierre-Andre Amaudruz
5 :
6 : Contents: MSCB IVC32 for the LiXe Intermediate HV control
7 : Refer for documentation to:
8 : http://daq-plone.triumf.ca/HR/PERIPHERALS/IVC32.pdf
9 :
10 : $Id$
11 : \********************************************************************/
12 :
13 : #include <stdio.h>
14 : #include <math.h>
15 : #include <string.h> // memcpy()
16 : #include <assert.h>
17 : #include "midas.h"
18 :
19 : typedef struct {
20 :
21 : /* ODB keys */
22 : HNDLE hKeyRoot, hKeyDemand, hKeyMeasured, hKeyCurrent;
23 :
24 : /* globals */
25 : INT num_channels;
26 : INT format;
27 : DWORD last_update;
28 : INT last_channel;
29 : INT last_channel_updated;
30 :
31 : /* items in /Variables record */
32 : char *names;
33 : float *demand;
34 : float *measured;
35 : float *current;
36 :
37 : /* items in /Settings */
38 : float *update_threshold;
39 : float *update_threshold_current;
40 : float *voltage_limit;
41 : float *current_limit;
42 : float *ramp_step; //Ramp Step in Volts WORD
43 : float *step_time; // Step Time in millisecond WORD
44 : float *trip_time;
45 :
46 : /* mirror arrays */
47 : float *demand_mirror;
48 : float *measured_mirror;
49 : float *current_mirror;
50 : DWORD *last_change;
51 :
52 : DEVICE_DRIVER **driver;
53 : INT *channel_offset;
54 : void **dd_info;
55 :
56 : } HV_INFO;
57 :
58 : #ifndef abs
59 : #define abs(a) (((a) < 0) ? -(a) : (a))
60 : #endif
61 :
62 : /*------------------------------------------------------------------*/
63 :
64 0 : static void free_mem(HV_INFO * hv_info)
65 : {
66 0 : free(hv_info->names);
67 0 : free(hv_info->demand);
68 0 : free(hv_info->measured);
69 0 : free(hv_info->current);
70 :
71 0 : free(hv_info->update_threshold);
72 0 : free(hv_info->update_threshold_current);
73 0 : free(hv_info->voltage_limit);
74 0 : free(hv_info->current_limit);
75 0 : free(hv_info->ramp_step);
76 0 : free(hv_info->step_time);
77 0 : free(hv_info->trip_time);
78 :
79 0 : free(hv_info->demand_mirror);
80 0 : free(hv_info->measured_mirror);
81 0 : free(hv_info->current_mirror);
82 0 : free(hv_info->last_change);
83 :
84 0 : free(hv_info->dd_info);
85 0 : free(hv_info->channel_offset);
86 0 : free(hv_info->driver);
87 :
88 0 : free(hv_info);
89 0 : }
90 :
91 : /*----------------------------------------------------------------------------*/
92 :
93 0 : INT ivc32_start(EQUIPMENT * pequipment)
94 : {
95 : INT i;
96 :
97 : /* call start method of device drivers */
98 0 : for (i = 0; pequipment->driver[i].dd != NULL ; i++)
99 0 : if (pequipment->driver[i].flags & DF_MULTITHREAD) {
100 0 : pequipment->driver[i].pequipment = &pequipment->info;
101 0 : device_driver(&pequipment->driver[i], CMD_START);
102 : }
103 :
104 0 : return FE_SUCCESS;
105 : }
106 :
107 : /*----------------------------------------------------------------------------*/
108 :
109 0 : INT ivc32_stop(EQUIPMENT * pequipment)
110 : {
111 : INT i;
112 :
113 : /* call close method of device drivers */
114 0 : for (i = 0; pequipment->driver[i].dd != NULL ; i++)
115 0 : if (pequipment->driver[i].flags & DF_MULTITHREAD)
116 0 : device_driver(&pequipment->driver[i], CMD_STOP);
117 :
118 0 : return FE_SUCCESS;
119 : }
120 :
121 : /*------------------------------------------------------------------*/
122 :
123 0 : INT ivc32_read(EQUIPMENT * pequipment, int channel)
124 : {
125 : int i;
126 0 : int status = 0;
127 : float max_diff;
128 : DWORD act_time, min_time;
129 : BOOL changed;
130 : HV_INFO *hv_info;
131 : HNDLE hDB;
132 :
133 0 : hv_info = (HV_INFO *) pequipment->cd_info;
134 0 : cm_get_experiment_database(&hDB, NULL);
135 :
136 : /* if driver is multi-threaded, read all channels at once */
137 0 : for (i=0 ; i < hv_info->num_channels ; i++) {
138 0 : if (hv_info->driver[i]->flags & DF_MULTITHREAD) {
139 0 : status = device_driver(hv_info->driver[i], CMD_GET,
140 0 : i - hv_info->channel_offset[i],
141 0 : &hv_info->measured[i]);
142 0 : status = device_driver(hv_info->driver[i], CMD_GET_CURRENT,
143 0 : i - hv_info->channel_offset[i],
144 0 : &hv_info->current[i]);
145 : }
146 : }
147 :
148 : /* else read only single channel */
149 0 : if (!(hv_info->driver[channel]->flags & DF_MULTITHREAD)) {
150 0 : status = device_driver(hv_info->driver[channel], CMD_GET,
151 0 : channel - hv_info->channel_offset[channel],
152 0 : &hv_info->measured[channel]);
153 0 : status = device_driver(hv_info->driver[channel], CMD_GET_CURRENT,
154 0 : channel - hv_info->channel_offset[channel],
155 0 : &hv_info->current[channel]);
156 : }
157 :
158 : /* check how much channels have changed since last ODB update */
159 0 : act_time = ss_millitime();
160 :
161 : /* check for update measured */
162 0 : max_diff = 0.f;
163 0 : min_time = 10000;
164 0 : changed = FALSE;
165 0 : for (i = 0; i < hv_info->num_channels; i++) {
166 0 : if (abs(hv_info->measured[i] - hv_info->measured_mirror[i]) > max_diff)
167 0 : max_diff = abs(hv_info->measured[i] - hv_info->measured_mirror[i]);
168 :
169 : /* indicate change if variation more than the threshold */
170 0 : if (abs(hv_info->measured[i] - hv_info->measured_mirror[i]) >
171 0 : hv_info->update_threshold[i] && hv_info->measured[i] > 10)
172 0 : changed = TRUE;
173 :
174 0 : if (act_time - hv_info->last_change[i] < min_time)
175 0 : min_time = act_time - hv_info->last_change[i];
176 : }
177 :
178 : /* update if change is more than update_sensitivity or less than 5sec ago
179 : or last update is older than a minute */
180 0 : if (changed || (min_time < 5000 && max_diff > 0) ||
181 0 : act_time - hv_info->last_update > 60000) {
182 0 : hv_info->last_update = act_time;
183 :
184 0 : for (i = 0; i < hv_info->num_channels; i++)
185 0 : hv_info->measured_mirror[i] = hv_info->measured[i];
186 :
187 0 : db_set_data(hDB, hv_info->hKeyMeasured, hv_info->measured,
188 0 : sizeof(float) * hv_info->num_channels, hv_info->num_channels,
189 : TID_FLOAT);
190 :
191 0 : pequipment->odb_out++;
192 : }
193 :
194 : /* check for update current */
195 0 : max_diff = 0.f;
196 0 : min_time = 10000;
197 0 : changed = FALSE;
198 0 : for (i = 0; i < hv_info->num_channels; i++) {
199 0 : if (abs(hv_info->current[i] - hv_info->current_mirror[i]) > max_diff)
200 0 : max_diff = abs(hv_info->current[i] - hv_info->current_mirror[i]);
201 :
202 0 : if (abs(hv_info->current[i] - hv_info->current_mirror[i]) >
203 0 : hv_info->update_threshold_current[i])
204 0 : changed = TRUE;
205 :
206 0 : if (act_time - hv_info->last_change[i] < min_time)
207 0 : min_time = act_time - hv_info->last_change[i];
208 : }
209 :
210 : /* update if change is more than update_sensitivity or less than 5sec ago */
211 0 : if (changed || (min_time < 5000 && max_diff > 0)) {
212 0 : for (i = 0; i < hv_info->num_channels; i++)
213 0 : hv_info->current_mirror[i] = hv_info->current[i];
214 :
215 0 : db_set_data(hDB, hv_info->hKeyCurrent, hv_info->current,
216 0 : sizeof(float) * hv_info->num_channels, hv_info->num_channels,
217 : TID_FLOAT);
218 :
219 0 : pequipment->odb_out++;
220 : }
221 :
222 0 : return status;
223 : }
224 :
225 : /*------------------------------------------------------------------*/
226 :
227 0 : INT ivc32_ramp(HV_INFO * hv_info)
228 : {
229 0 : INT i, status = 0, switch_tag = FALSE;
230 0 : float delta, ramp_speed = 0;
231 :
232 0 : for (i = 0; i < hv_info->num_channels; i++) {
233 0 : if (hv_info->demand[i] != hv_info->demand_mirror[i]) {
234 : /* check if to ramp up or down */
235 0 : if ((hv_info->demand[i] >= 0.f) && (hv_info->demand_mirror[i] > 0.f)) {
236 0 : switch_tag = FALSE;
237 0 : if (hv_info->demand[i] > hv_info->demand_mirror[i])
238 0 : ramp_speed = hv_info->ramp_step[i];
239 : else
240 0 : ramp_speed = hv_info->step_time[i];
241 : }
242 0 : if ((hv_info->demand[i] >= 0.f) && (hv_info->demand_mirror[i] < 0.f)) {
243 0 : switch_tag = TRUE;
244 0 : ramp_speed = hv_info->step_time[i];
245 : }
246 0 : if ((hv_info->demand[i] < 0.f) && (hv_info->demand_mirror[i] > 0.f)) {
247 0 : switch_tag = TRUE;
248 0 : ramp_speed = hv_info->step_time[i];
249 : }
250 0 : if ((hv_info->demand[i] < 0.f) && (hv_info->demand_mirror[i] < 0.f)) {
251 0 : switch_tag = FALSE;
252 0 : if (hv_info->demand[i] > hv_info->demand_mirror[i])
253 0 : ramp_speed = hv_info->step_time[i];
254 : else
255 0 : ramp_speed = hv_info->ramp_step[i];
256 : }
257 0 : if (hv_info->demand_mirror[i] == 0.f) {
258 0 : switch_tag = FALSE;
259 0 : ramp_speed = hv_info->ramp_step[i];
260 : }
261 :
262 0 : if (ramp_speed == 0.f)
263 0 : if (switch_tag)
264 0 : hv_info->demand_mirror[i] = 0.f; /* go to zero */
265 : else
266 0 : hv_info->demand_mirror[i] = hv_info->demand[i]; /* step directly to the new high voltage */
267 : else {
268 0 : delta = (float) ((ss_millitime() -
269 0 : hv_info->last_change[i]) / 1000.0 * ramp_speed);
270 0 : if (hv_info->demand[i] > hv_info->demand_mirror[i])
271 0 : hv_info->demand_mirror[i] =
272 0 : MIN(hv_info->demand[i], hv_info->demand_mirror[i] + delta);
273 : else
274 0 : hv_info->demand_mirror[i] =
275 0 : MAX(hv_info->demand[i], hv_info->demand_mirror[i] - delta);
276 : }
277 0 : status = device_driver(hv_info->driver[i], CMD_SET,
278 0 : i - hv_info->channel_offset[i], hv_info->demand_mirror[i]);
279 0 : hv_info->last_change[i] = ss_millitime();
280 : }
281 : }
282 :
283 0 : return status;
284 : }
285 :
286 :
287 : /*------------------------------------------------------------------*/
288 :
289 0 : void ivc32_demand(INT hDB, INT hKey, void *info)
290 : {
291 : INT i;
292 : HV_INFO *hv_info;
293 : EQUIPMENT *pequipment;
294 :
295 0 : pequipment = (EQUIPMENT *) info;
296 0 : hv_info = (HV_INFO *) pequipment->cd_info;
297 :
298 : /* check for voltage limit */
299 0 : for (i = 0; i < hv_info->num_channels; i++)
300 0 : if (hv_info->demand[i] > hv_info->voltage_limit[i])
301 0 : hv_info->demand[i] = hv_info->voltage_limit[i];
302 :
303 : /* set individual channels only if demand value differs */
304 0 : for (i = 0; i < hv_info->num_channels; i++)
305 0 : if (hv_info->demand[i] != hv_info->demand_mirror[i])
306 0 : hv_info->last_change[i] = ss_millitime();
307 :
308 0 : pequipment->odb_in++;
309 :
310 0 : for (i = 0; i < hv_info->num_channels; i++) {
311 : /* if device can do hardware ramping, just set value */
312 0 : if (hv_info->driver[i]->flags & DF_HW_RAMP) {
313 0 : if (hv_info->demand[i] != hv_info->demand_mirror[i]) {
314 0 : device_driver(hv_info->driver[i], CMD_SET,
315 0 : i - hv_info->channel_offset[i], hv_info->demand[i]);
316 0 : hv_info->last_change[i] = ss_millitime();
317 0 : hv_info->demand_mirror[i] = hv_info->demand[i];
318 : }
319 : }
320 : }
321 0 : }
322 :
323 : /*------------------------------------------------------------------*/
324 : // in WORD
325 0 : void ivc32_set_trip_time(INT hDB, INT hKey, void *info)
326 : {
327 : INT i;
328 : HV_INFO *hv_info;
329 : EQUIPMENT *pequipment;
330 :
331 0 : pequipment = (EQUIPMENT *) info;
332 0 : hv_info = (HV_INFO *) pequipment->cd_info;
333 :
334 : /* check for voltage limit */
335 0 : for (i = 0; i < hv_info->num_channels; i++)
336 0 : device_driver(hv_info->driver[i], CMD_SET_TRIP_TIME,
337 0 : i - hv_info->channel_offset[i], hv_info->trip_time[i]);
338 :
339 0 : pequipment->odb_in++;
340 0 : }
341 :
342 : /*------------------------------------------------------------------*/
343 :
344 0 : void ivc32_set_current_limit(INT hDB, INT hKey, void *info)
345 : {
346 : INT i;
347 : HV_INFO *hv_info;
348 : EQUIPMENT *pequipment;
349 :
350 0 : pequipment = (EQUIPMENT *) info;
351 0 : hv_info = (HV_INFO *) pequipment->cd_info;
352 :
353 : /* check for voltage limit */
354 0 : for (i = 0; i < hv_info->num_channels; i++)
355 0 : device_driver(hv_info->driver[i], CMD_SET_CURRENT_LIMIT,
356 0 : i - hv_info->channel_offset[i], hv_info->current_limit[i]);
357 :
358 0 : pequipment->odb_in++;
359 0 : }
360 :
361 : /*------------------------------------------------------------------*/
362 : // Actually Ramp step in WORD
363 0 : void ivc32_set_rampstep(INT hDB, INT hKey, void *info)
364 : {
365 : INT i;
366 : HV_INFO *hv_info;
367 : EQUIPMENT *pequipment;
368 :
369 0 : pequipment = (EQUIPMENT *) info;
370 0 : hv_info = (HV_INFO *) pequipment->cd_info;
371 :
372 : /* check for voltage limit */
373 0 : for (i = 0; i < hv_info->num_channels; i++)
374 0 : device_driver(hv_info->driver[i], CMD_SET_RAMPUP,
375 0 : i - hv_info->channel_offset[i], hv_info->ramp_step[i]);
376 :
377 0 : pequipment->odb_in++;
378 0 : }
379 :
380 : /*------------------------------------------------------------------*/
381 : // Actually Step Time in WORD
382 0 : void ivc32_set_steptime(INT hDB, INT hKey, void *info)
383 : {
384 : INT i;
385 : HV_INFO *hv_info;
386 : EQUIPMENT *pequipment;
387 :
388 0 : pequipment = (EQUIPMENT *) info;
389 0 : hv_info = (HV_INFO *) pequipment->cd_info;
390 :
391 : /* check for voltage limit */
392 0 : for (i = 0; i < hv_info->num_channels; i++)
393 0 : device_driver(hv_info->driver[i], CMD_SET_RAMPDOWN,
394 0 : i - hv_info->channel_offset[i], hv_info->step_time[i]);
395 :
396 0 : pequipment->odb_in++;
397 0 : }
398 :
399 : /*------------------------------------------------------------------*/
400 : // Not implemented for IVC32 use as software limit
401 0 : void ivc32_set_voltage_limit(INT hDB, INT hKey, void *info)
402 : {
403 : //HV_INFO *hv_info;
404 : //EQUIPMENT *pequipment;
405 :
406 : //pequipment = (EQUIPMENT *) info;
407 : //hv_info = (HV_INFO *) pequipment->cd_info;
408 :
409 : // voltage_limit has been updated by open_record
410 :
411 : /* check for voltage limit */
412 : //for (i = 0; i < hv_info->num_channels; i++)
413 : // device_driver(hv_info->driver[i], CMD_SET_VOLTAGE_LIMIT,
414 : // i - hv_info->channel_offset[i], hv_info->voltage_limit[i]);
415 :
416 : //pequipment->odb_in++;
417 0 : }
418 :
419 : /*------------------------------------------------------------------*/
420 :
421 0 : void ivc32_update_label(INT hDB, INT hKey, void *info)
422 : {
423 : INT i, status;
424 : HV_INFO *hv_info;
425 : EQUIPMENT *pequipment;
426 :
427 0 : pequipment = (EQUIPMENT *) info;
428 0 : hv_info = (HV_INFO *) pequipment->cd_info;
429 :
430 : /* update channel labels based on the midas channel names */
431 0 : for (i = 0; i < hv_info->num_channels; i++)
432 0 : status = device_driver(hv_info->driver[i], CMD_SET_LABEL,
433 0 : i - hv_info->channel_offset[i],
434 0 : hv_info->names + NAME_LENGTH * i);
435 :
436 : (void)status; // defeat "set but unused" warning
437 0 : }
438 :
439 : /*------------------------------------------------------------------*/
440 :
441 0 : void validate_odb_array(HNDLE hDB, HV_INFO *hv_info, const char *path, double default_value, int cmd,
442 : float *array, void (*callback)(INT,INT,void *) ,EQUIPMENT *pequipment)
443 : {
444 : int i;
445 : HNDLE hKey;
446 :
447 0 : for (i = 0; i < hv_info->num_channels; i++)
448 0 : array[i] = (float)default_value;
449 0 : if (db_find_key(hDB, hv_info->hKeyRoot, path, &hKey) != DB_SUCCESS)
450 0 : for (i = 0; i < hv_info->num_channels; i++)
451 0 : device_driver(hv_info->driver[i], cmd,
452 0 : i - hv_info->channel_offset[i], array + i);
453 0 : db_merge_data(hDB, hv_info->hKeyRoot, path, array, sizeof(float) * hv_info->num_channels,
454 : hv_info->num_channels, TID_FLOAT);
455 0 : db_find_key(hDB, hv_info->hKeyRoot, path, &hKey);
456 0 : assert(hKey);
457 0 : db_open_record(hDB, hKey, array, sizeof(float) * hv_info->num_channels, MODE_READ,
458 : callback, pequipment);
459 0 : }
460 :
461 : /*------------------------------------------------------------------*/
462 :
463 0 : INT ivc32_init(EQUIPMENT * pequipment)
464 : {
465 : int status, size, i, j, index, offset;
466 : char str[256];
467 : HNDLE hDB, hKey;
468 : HV_INFO *hv_info;
469 :
470 : /* allocate private data */
471 0 : pequipment->cd_info = calloc(1, sizeof(HV_INFO));
472 0 : hv_info = (HV_INFO *) pequipment->cd_info;
473 :
474 : /* get class driver root key */
475 0 : cm_get_experiment_database(&hDB, NULL);
476 0 : sprintf(str, "/Equipment/%s", pequipment->name);
477 0 : db_create_key(hDB, 0, str, TID_KEY);
478 0 : db_find_key(hDB, 0, str, &hv_info->hKeyRoot);
479 :
480 : /* save event format */
481 0 : size = sizeof(str);
482 0 : db_get_value(hDB, hv_info->hKeyRoot, "Common/Format", str, &size, TID_STRING, TRUE);
483 :
484 0 : if (equal_ustring(str, "Fixed"))
485 0 : hv_info->format = FORMAT_FIXED;
486 0 : else if (equal_ustring(str, "MIDAS"))
487 0 : hv_info->format = FORMAT_MIDAS;
488 : else
489 0 : assert(!"unknown ODB Common/Format");
490 :
491 : /* count total number of channels */
492 0 : for (i = 0, hv_info->num_channels = 0; pequipment->driver[i].name[0]; i++) {
493 0 : if (pequipment->driver[i].channels == 0) {
494 0 : cm_msg(MERROR, "hv_init", "Driver with zero channels not allowed");
495 0 : return FE_ERR_ODB;
496 : }
497 :
498 0 : hv_info->num_channels += pequipment->driver[i].channels;
499 : }
500 :
501 0 : if (hv_info->num_channels == 0) {
502 0 : cm_msg(MERROR, "hv_init", "No channels found in device driver list");
503 0 : return FE_ERR_ODB;
504 : }
505 :
506 : /* Allocate memory for buffers */
507 0 : hv_info->names = (char *) calloc(hv_info->num_channels, NAME_LENGTH);
508 :
509 0 : hv_info->demand = (float *) calloc(hv_info->num_channels, sizeof(float));
510 0 : hv_info->measured = (float *) calloc(hv_info->num_channels, sizeof(float));
511 0 : hv_info->current = (float *) calloc(hv_info->num_channels, sizeof(float));
512 :
513 0 : hv_info->update_threshold = (float *) calloc(hv_info->num_channels, sizeof(float));
514 0 : hv_info->update_threshold_current = (float *) calloc(hv_info->num_channels, sizeof(float));
515 0 : hv_info->voltage_limit = (float *) calloc(hv_info->num_channels, sizeof(float));
516 0 : hv_info->current_limit = (float *) calloc(hv_info->num_channels, sizeof(float));
517 0 : hv_info->ramp_step = (float *) calloc(hv_info->num_channels, sizeof(float));
518 0 : hv_info->step_time = (float *) calloc(hv_info->num_channels, sizeof(float));
519 0 : hv_info->trip_time = (float *) calloc(hv_info->num_channels, sizeof(float));
520 :
521 0 : hv_info->demand_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
522 0 : hv_info->measured_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
523 0 : hv_info->current_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
524 0 : hv_info->last_change = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
525 :
526 0 : hv_info->dd_info = (void**) calloc(hv_info->num_channels, sizeof(void *));
527 0 : hv_info->channel_offset = (INT *) calloc(hv_info->num_channels, sizeof(INT));
528 0 : hv_info->driver = (DEVICE_DRIVER**) calloc(hv_info->num_channels, sizeof(void *));
529 :
530 0 : if (!hv_info->driver) {
531 0 : cm_msg(MERROR, "hv_init", "Not enough memory");
532 0 : return FE_ERR_ODB;
533 : }
534 :
535 : /*---- Initialize device drivers ----*/
536 :
537 : /* call init method */
538 0 : for (i = 0; pequipment->driver[i].name[0]; i++) {
539 0 : sprintf(str, "Settings/Devices/%s", pequipment->driver[i].name);
540 0 : status = db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
541 0 : if (status != DB_SUCCESS) {
542 0 : db_create_key(hDB, hv_info->hKeyRoot, str, TID_KEY);
543 0 : status = db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
544 0 : if (status != DB_SUCCESS) {
545 0 : cm_msg(MERROR, "hv_init", "Cannot create %s entry in online database", str);
546 0 : free_mem(hv_info);
547 0 : return FE_ERR_ODB;
548 : }
549 : }
550 :
551 0 : status = device_driver(&pequipment->driver[i], CMD_INIT, hKey);
552 0 : if (status != FE_SUCCESS) {
553 0 : free_mem(hv_info);
554 0 : return status;
555 : }
556 : }
557 :
558 : /* compose device driver channel assignment */
559 0 : for (i = 0, j = 0, index = 0, offset = 0; i < hv_info->num_channels; i++, j++) {
560 0 : while (j >= pequipment->driver[index].channels && pequipment->driver[index].name[0]) {
561 0 : offset += j;
562 0 : index++;
563 0 : j = 0;
564 : }
565 :
566 0 : hv_info->driver[i] = &pequipment->driver[index];
567 0 : hv_info->channel_offset[i] = offset;
568 : }
569 :
570 : /*---- Create/Read settings ----*/
571 : /* Names */
572 0 : for (i = 0; i < hv_info->num_channels; i++) {
573 0 : if ((i>=0) && (i<8)) sprintf(hv_info->names + NAME_LENGTH * i, "Front%%CH %d", i);
574 0 : if ((i>=8) && (i<16)) sprintf(hv_info->names + NAME_LENGTH * i, "Back%%CH %d", i);
575 0 : if ((i>=16) && (i<24)) sprintf(hv_info->names + NAME_LENGTH * i, "Left%%CH %d", i);
576 0 : if ((i>=24) && (i<32)) sprintf(hv_info->names + NAME_LENGTH * i, "Right%%CH %d", i);
577 : }
578 0 : if (db_find_key(hDB, hv_info->hKeyRoot, "Settings/Names", &hKey) != DB_SUCCESS)
579 0 : for (i = 0; i < hv_info->num_channels; i++)
580 0 : device_driver(hv_info->driver[i], CMD_GET_LABEL,
581 0 : i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
582 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Settings/Names",
583 0 : hv_info->names, NAME_LENGTH * hv_info->num_channels,
584 : hv_info->num_channels, TID_STRING);
585 0 : db_find_key(hDB, hv_info->hKeyRoot, "Settings/Names", &hKey);
586 0 : assert(hKey);
587 0 : db_open_record(hDB, hKey, hv_info->names, NAME_LENGTH * hv_info->num_channels,
588 : MODE_READ, ivc32_update_label, pequipment);
589 :
590 : /* Update threshold */
591 0 : validate_odb_array(hDB, hv_info, "Settings/Update Threshold Measured", 0.5, CMD_GET_THRESHOLD,
592 : hv_info->update_threshold, NULL, NULL);
593 :
594 : /* Update threshold current */
595 0 : validate_odb_array(hDB, hv_info, "Settings/Update Threshold Current", 0.5, CMD_GET_THRESHOLD_CURRENT,
596 : hv_info->update_threshold_current, NULL, NULL);
597 :
598 : /* Voltage limit */
599 0 : validate_odb_array(hDB, hv_info, "Settings/Voltage Limit", 100, CMD_GET_VOLTAGE_LIMIT,
600 : hv_info->voltage_limit, ivc32_set_voltage_limit, pequipment);
601 : /* Current limit */
602 0 : validate_odb_array(hDB, hv_info, "Settings/Current Limit", 50, CMD_GET_CURRENT_LIMIT,
603 : hv_info->current_limit, ivc32_set_current_limit, pequipment);
604 :
605 : /* Trip Time */
606 0 : validate_odb_array(hDB, hv_info, "Settings/Trip Time", 1000, CMD_GET_TRIP_TIME,
607 : hv_info->trip_time, ivc32_set_trip_time, pequipment);
608 :
609 : /* Ramp Step */
610 0 : validate_odb_array(hDB, hv_info, "Settings/Ramp Step", 5, CMD_GET_RAMPUP,
611 : hv_info->ramp_step, ivc32_set_rampstep, pequipment);
612 :
613 : /* Step Time */
614 0 : validate_odb_array(hDB, hv_info, "Settings/Step Time", 50, CMD_GET_RAMPDOWN,
615 : hv_info->step_time, ivc32_set_steptime, pequipment);
616 :
617 : /*---- Create/Read variables ----*/
618 :
619 : /* Demand */
620 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Demand",
621 0 : hv_info->demand, sizeof(float) * hv_info->num_channels,
622 : hv_info->num_channels, TID_FLOAT);
623 0 : db_find_key(hDB, hv_info->hKeyRoot, "Variables/Demand", &hv_info->hKeyDemand);
624 :
625 : /* Measured */
626 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Measured",
627 0 : hv_info->measured, sizeof(float) * hv_info->num_channels,
628 : hv_info->num_channels, TID_FLOAT);
629 0 : db_find_key(hDB, hv_info->hKeyRoot, "Variables/Measured", &hv_info->hKeyMeasured);
630 0 : memcpy(hv_info->measured_mirror, hv_info->measured,
631 0 : hv_info->num_channels * sizeof(float));
632 :
633 : /* Current */
634 0 : db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Current",
635 0 : hv_info->current, sizeof(float) * hv_info->num_channels,
636 : hv_info->num_channels, TID_FLOAT);
637 0 : db_find_key(hDB, hv_info->hKeyRoot, "Variables/Current", &hv_info->hKeyCurrent);
638 0 : memcpy(hv_info->current_mirror, hv_info->current,
639 0 : hv_info->num_channels * sizeof(float));
640 :
641 : /*---- set labels form midas SC names ----*/
642 0 : for (i = 0; i < hv_info->num_channels; i++) {
643 0 : status = device_driver(hv_info->driver[i], CMD_SET_LABEL,
644 0 : i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
645 : }
646 :
647 : /*---- set/get values ----*/
648 0 : for (i = 0; i < hv_info->num_channels; i++) {
649 0 : if ((hv_info->driver[i]->flags & DF_PRIO_DEVICE) == 0) {
650 0 : hv_info->demand_mirror[i] = MIN(hv_info->demand[i], hv_info->voltage_limit[i]);
651 0 : status = device_driver(hv_info->driver[i], CMD_SET,
652 0 : i - hv_info->channel_offset[i], hv_info->demand_mirror[i]);
653 0 : status = device_driver(hv_info->driver[i], CMD_SET_TRIP_TIME,
654 0 : i - hv_info->channel_offset[i], hv_info->trip_time[i]);
655 0 : status = device_driver(hv_info->driver[i], CMD_SET_CURRENT_LIMIT,
656 0 : i - hv_info->channel_offset[i], hv_info->current_limit[i]);
657 0 : status = device_driver(hv_info->driver[i], CMD_SET_VOLTAGE_LIMIT,
658 0 : i - hv_info->channel_offset[i], hv_info->voltage_limit[i]);
659 0 : status = device_driver(hv_info->driver[i], CMD_SET_RAMPUP,
660 0 : i - hv_info->channel_offset[i], hv_info->ramp_step[i]);
661 0 : status = device_driver(hv_info->driver[i], CMD_SET_RAMPDOWN,
662 0 : i - hv_info->channel_offset[i], hv_info->step_time[i]);
663 : } else {
664 0 : status = device_driver(hv_info->driver[i], CMD_GET_DEMAND,
665 0 : i - hv_info->channel_offset[i], hv_info->demand + i);
666 0 : hv_info->demand_mirror[i] = hv_info->demand[i];
667 :
668 0 : status = device_driver(hv_info->driver[i], CMD_GET_CURRENT_LIMIT,
669 0 : i - hv_info->channel_offset[i], &hv_info->current_limit[i]);
670 0 : status = device_driver(hv_info->driver[i], CMD_GET_VOLTAGE_LIMIT,
671 0 : i - hv_info->channel_offset[i], &hv_info->voltage_limit[i]);
672 0 : status = device_driver(hv_info->driver[i], CMD_GET_RAMPUP,
673 0 : i - hv_info->channel_offset[i], &hv_info->ramp_step[i]);
674 0 : status = device_driver(hv_info->driver[i], CMD_GET_RAMPDOWN,
675 0 : i - hv_info->channel_offset[i], &hv_info->step_time[i]);
676 0 : status = device_driver(hv_info->driver[i], CMD_GET_TRIP_TIME,
677 0 : i - hv_info->channel_offset[i], &hv_info->trip_time[i]);
678 : }
679 : }
680 0 : db_set_record(hDB, hv_info->hKeyDemand, hv_info->demand,
681 0 : hv_info->num_channels * sizeof(float), 0);
682 :
683 : /*--- open hotlink to HV demand values ----*/
684 0 : db_open_record(hDB, hv_info->hKeyDemand, hv_info->demand,
685 0 : hv_info->num_channels * sizeof(float), MODE_READ, ivc32_demand,
686 : pequipment);
687 :
688 : /* initially read all channels */
689 0 : for (i=0 ; i<hv_info->num_channels ; i++) {
690 :
691 0 : hv_info->driver[i]->dd(CMD_GET, hv_info->driver[i]->dd_info,
692 0 : i - hv_info->channel_offset[i], &hv_info->measured[i]);
693 0 : hv_info->driver[i]->dd(CMD_GET_CURRENT, hv_info->driver[i]->dd_info,
694 0 : i - hv_info->channel_offset[i], &hv_info->current[i]);
695 :
696 0 : hv_info->measured_mirror[i] = hv_info->measured[i];
697 0 : hv_info->current_mirror[i] = hv_info->current[i];
698 : }
699 0 : db_set_data(hDB, hv_info->hKeyCurrent, hv_info->current,
700 0 : sizeof(float) * hv_info->num_channels, hv_info->num_channels,
701 : TID_FLOAT);
702 0 : pequipment->odb_out++;
703 :
704 0 : return FE_SUCCESS;
705 : }
706 :
707 : /*------------------------------------------------------------------*/
708 :
709 0 : INT ivc32_exit(EQUIPMENT * pequipment)
710 : {
711 : INT i;
712 :
713 0 : free_mem((HV_INFO *) pequipment->cd_info);
714 :
715 : /* call exit method of device drivers */
716 0 : for (i = 0; pequipment->driver[i].dd != NULL; i++)
717 0 : device_driver(&pequipment->driver[i], CMD_EXIT);
718 :
719 0 : return FE_SUCCESS;
720 : }
721 :
722 : /*------------------------------------------------------------------*/
723 :
724 0 : INT ivc32_idle(EQUIPMENT * pequipment)
725 : {
726 : INT act, status;
727 : DWORD act_time;
728 : HV_INFO *hv_info;
729 :
730 0 : hv_info = (HV_INFO *) pequipment->cd_info;
731 :
732 : /* do ramping */
733 : // ivc32_ramp(hv_info);
734 :
735 : /* select next measurement channel */
736 0 : hv_info->last_channel = (hv_info->last_channel + 1) % hv_info->num_channels;
737 :
738 : /* measure channel */
739 0 : status = ivc32_read(pequipment, hv_info->last_channel);
740 :
741 : /* additionally read channel recently updated if not multithreaded */
742 0 : if (!(hv_info->driver[hv_info->last_channel]->flags & DF_MULTITHREAD)) {
743 :
744 0 : act_time = ss_millitime();
745 :
746 0 : act = (hv_info->last_channel_updated + 1) % hv_info->num_channels;
747 0 : while (!(act_time - hv_info->last_change[act] < 10000)) {
748 0 : act = (act + 1) % hv_info->num_channels;
749 0 : if (act == hv_info->last_channel_updated) {
750 : /* non found, so return */
751 0 : return status;
752 : }
753 : }
754 :
755 : /* updated channel found, so read it additionally */
756 0 : status = ivc32_read(pequipment, act);
757 0 : hv_info->last_channel_updated = act;
758 : }
759 :
760 0 : return status;
761 : }
762 :
763 : /*------------------------------------------------------------------*/
764 :
765 0 : INT cd_ivc32_read(char *pevent, int offset)
766 : {
767 : float *pdata;
768 : HV_INFO *hv_info;
769 : EQUIPMENT *pequipment;
770 :
771 0 : pequipment = *((EQUIPMENT **) pevent);
772 0 : hv_info = (HV_INFO *) pequipment->cd_info;
773 :
774 0 : if (hv_info->format == FORMAT_FIXED) {
775 0 : memcpy(pevent, hv_info->demand, sizeof(float) * hv_info->num_channels);
776 0 : pevent += sizeof(float) * hv_info->num_channels;
777 :
778 0 : memcpy(pevent, hv_info->measured, sizeof(float) * hv_info->num_channels);
779 0 : pevent += sizeof(float) * hv_info->num_channels;
780 :
781 0 : memcpy(pevent, hv_info->current, sizeof(float) * hv_info->num_channels);
782 0 : pevent += sizeof(float) * hv_info->num_channels;
783 :
784 0 : return 3 * sizeof(float) * hv_info->num_channels;
785 0 : } else if (hv_info->format == FORMAT_MIDAS) {
786 0 : bk_init(pevent);
787 :
788 : /* create DMND bank */
789 0 : bk_create(pevent, "DMND", TID_FLOAT, (void**) &pdata);
790 0 : memcpy(pdata, hv_info->demand, sizeof(float) * hv_info->num_channels);
791 0 : pdata += hv_info->num_channels;
792 0 : bk_close(pevent, pdata);
793 :
794 : /* create MSRD bank */
795 0 : bk_create(pevent, "MSRD", TID_FLOAT, (void**) &pdata);
796 0 : memcpy(pdata, hv_info->measured, sizeof(float) * hv_info->num_channels);
797 0 : pdata += hv_info->num_channels;
798 0 : bk_close(pevent, pdata);
799 :
800 : /* create CRNT bank */
801 0 : bk_create(pevent, "CRNT", TID_FLOAT, (void**) &pdata);
802 0 : memcpy(pdata, hv_info->current, sizeof(float) * hv_info->num_channels);
803 0 : pdata += hv_info->num_channels;
804 0 : bk_close(pevent, pdata);
805 :
806 0 : return bk_size(pevent);
807 : } else {
808 0 : assert(!"unknown hv_info->format");
809 : return 0;
810 : }
811 : }
812 :
813 : /*------------------------------------------------------------------*/
814 :
815 0 : INT cd_ivc32(INT cmd, PEQUIPMENT pequipment)
816 : {
817 : INT status;
818 :
819 0 : switch (cmd) {
820 0 : case CMD_INIT:
821 0 : status = ivc32_init(pequipment);
822 0 : break;
823 :
824 0 : case CMD_EXIT:
825 0 : status = ivc32_exit(pequipment);
826 0 : break;
827 :
828 0 : case CMD_START:
829 0 : status = ivc32_start(pequipment);
830 0 : break;
831 :
832 0 : case CMD_STOP:
833 0 : status = ivc32_stop(pequipment);
834 0 : break;
835 :
836 0 : case CMD_IDLE:
837 0 : status = ivc32_idle(pequipment);
838 0 : break;
839 :
840 0 : default:
841 0 : cm_msg(MERROR, "HV class driver", "Received unknown command %d", cmd);
842 0 : status = FE_ERR_DRIVER;
843 0 : break;
844 : }
845 :
846 0 : return status;
847 : }
|