Low-Energy Muon (LEM) Experiment  0.5.1
hv_fug.c
Go to the documentation of this file.
1 /********************************************************************\
2 
3  Name: hv_fug.c
4  Created by: Andreas Suter 2001/07/20
5  based on Stefan Ritt's nitronic device driver
6 
7  Contents: Description of the Slow Control device driver for the FUG high voltage
8  devices which are used in the transport system of the low energy
9  muSR experiment at PSI.
10 
11  The FUG high voltage devices are used for the muon transport system in the
12  low energy muon experiment (LEM) at PSI. Since the high voltage devices
13  themselfs only have analog input controls, analog input/output cards of
14  National Instruments (FP-AI-110 / FP-AO-210) are used to connect to the digital
15  world. To control them via a computer a special interface card (FP1000) and bus
16  is used (again National Instrument stuff).
17 
18  The hard wiring looks like this:
19 
20  |- FP-RLY-420,bus address 8 (set polarity of FUG HCL devices 8-12)
21  |- FP-AI-110, bus address 5 (read polarity of FUG HCL devices 8-12)
22  |- FP-AI-110, bus address 7 (Lense_1, Sample_G1, Sample_G2, Sample)
23  |- FP-AI-110, bus address 3 (Moderator, Mod_Guard, Mod_Grid, Mirror)
24  |- FP-AI-110, bus address 2 (Lense_2, Lense_3, RA-L, RA-R)
25  PC <-- Lantronix/RS232 --> FP1000 -|
26  |- FP-AO-210, bus address 6 (Lense_1, Sample_G1, Sample_G2, Sample)
27  |- FP-AO-210, bus address 4 (Moderator, Mod_Guard, Mod_Grid, Mirror)
28  |- FP-AO-210, bus address 1 (Lense_2, Lense_3, RA-L, RA-R)
29  i.e. we use
30 
31  3 analog input cards (FP-AI-110) with each 8 channels to read the HV and the current
32  3 analog output cards (FP-AO-210) with each 8 channels to write the HV and the current
33  1 anlog input card (FP-AI-110) with 8 channels to read the polarity of HCL devices
34  (5 devices (8-12) connected in control box)
35  1 relay module (FP-RLY-420) with 8 channels to set the polarity of HCL devices
36  (5 devices (8-12) connected in control box)
37 
38  for 12 FUG high voltage devices. Each FUG HV device needs 2 input and
39  2 output channels (in/out voltage/current).
40 
41  The new HCL devices (we will use four of them for Grid_1, Sample_G1, Sample_G2, Sample)
42  have the option to change the polarity remotely. This is done by using the
43  relay module FP-RLY-420. The polarity of these devices is monitored by
44  an additional FP-AI-110:
45  +polarity gives ~15V, i.e. overrange at the FP-AI-110 (10.4V max. measurable voltage)
46  -polarity gives ~0V.
47 
48  RS232 settings of the FP1000:
49  baud rate: 9600
50  parity: none
51  data bits: 8
52  stop bits: 1
53  synchronization: Xon/Xoff (Software)
54  terminator: "\r"
55 
56  For a detailed description of the command language of the field point bus of
57  National Instruments see:
58  Field Point -- FP-1000/FP-1001 Programmer Reference Manual.
59 
60 -------------------------------------------------------------------------------------------
61 
62  The ODB equipment definition of the different FUG HV devices is organized as follows:
63  key : /Equipment/HV/Settings/Devices/FUG/DD
64 
65  With the following entries:
66 
67  No of FP-IO Modules -> total number of field point modules
68  Modules -> list of all the modules 'x1:name1; x2:name2; ...' with
69  x_i the number of the field point module and
70  name_i the type of the field point module, i.e. FP-1000 for the RS232 communication module
71  FUG fp mapping input -> coded array of all the input channels.
72  The coding is as follows:
73  name u_module u_ch i_module i_ch switch_tag module u_ch
74  with
75  name : name of the fug
76  u_module : voltage readback module (bus address)
77  u_ch : voltage readback channel (channel address)
78  i_module : current readback module (bus address)
79  i_ch : current readback channel (channel address)
80  switch_tag : (Y/N) Y: polarity of the FUG is remote switchable, otherwise N
81  module : if switch_tag = Y, the module of the relais readback (bus address)
82  u_ch : relais readback channel (channel address)
83 
84  e.g. Moderator 02 0x0001 02 0x0002 N 00 0x0000
85  FUG fp mapping output -> dito to 'FUG fp mapping input' except for the output channels
86  Properties -> specification of the FUG's coded as e.g.
87  Moderator @20.0kV #0.6mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA
88  ^ ^ ^ ^ ^ ^ ^
89  name max hv | upramp downramp default hv |
90  max current default current limit
91 
92  Moderator Group -> on/off, xkV -> on : i.e. Moderator, Mod_Guard, Mod_Grid form a group where the
93  maximal difference in the HV is x kV, e.g.
94  on, 5kV
95  if 'off' you can do whatever you want
96  Sample Group -> dito, where Sample, Sample_G1, Sample_G2 form a group
97  RA Group -> dito, where RA-R and RA-L form a group
98 
99 \********************************************************************/
100 
101 #include <stdio.h>
102 #include <stdlib.h>
103 #include <math.h>
104 #include <string.h>
105 #include <stdarg.h>
106 #include "midas.h"
107 #include "msystem.h"
108 
109 #include "hv_fug.h"
110 
111 #include "ets_logout.h"
112 #include "lemSCWatchdog.h"
113 
114 /********************************************************************
115  identifier for the different field point modules
116  see "FieldPoint Programmer Reference Manual" p.5-4f
117 ********************************************************************/
118 
119 #define FP_1000 0x0001
120 #define FP_1001 0x0002
121 #define FP_AI_110 0x0101
122 #define FP_AO_200 0x0102
123 #define FP_DI_330 0x0103
124 #define FP_DO_400 0x0104
125 #define FP_DI_301 0x0105
126 #define FP_DO_401 0x0106
127 #define FP_TC_120 0x0107
128 #define FP_RLY_420 0x0108
129 #define FP_DI_300 0x0109
130 #define FP_AI_100 0x010A
131 #define FP_RTD_122 0x010B
132 #define FP_AI_111 0x010C
133 #define FP_AO_210 0x010F
134 
135 /*******************************************************************
136  Default settings for the FP-AI-110 and FP-AO-210
137  FP-AI-110: Range=04(0-10.4V) Filter=00(60Hz)
138  FP-AO-210: Range=04(0-10.2V)
139  FP_IO_RESOL: = 2^16. This is only for the SW. The real devices
140  might be different (Resolution FP-AI-110 = 2^16,
141  Resolution FP-AO-200 = 2^12)
142  FP_AO_NORM: The HV FUG devices reach their maximum voltage at
143  an analog input programming voltage of 10 V =: HV_FUG_MAX,
144  whereas the FP-AO-210 delivers a maximum of FP_AO_MAX=10.2V.
145  FP_AO_NORM = HV_FUG_MAX / FP_AO_MAX = 10/10.2
146  FP_AI_NORM: Analog FP_AO_NORM:
147  FP_AI_NORM = FP_AI_MAX / HV_FUG_MAX = 10.4/10
148 
149 ********************************************************************/
150 
151 #define FP_IO_NUM_CH 8
152 #define FP_AI_110_RANGE 0x04
153 #define FP_AI_110_FILTER 0x00
154 #define FP_AO_210_RANGE 0x04
155 #define FP_RLY_SETTING 0x10
156 #define FP_IO_RESOL 65536
157 #define FP_AO_NORM 0.9804
158 #define FP_AI_NORM 1.04
159 
160 /********************************************************************
161  Possible Field Point Module Error Codes
162 ********************************************************************/
166 #define FP_ERR_PUCLR_EXP 0x00
167 #ifndef DOXYGEN_SHOULD_SKIP_THIS
168 #define FP_ERR_INVALID_CMD 0x01
169 #define FP_ERR_BAD_CHECKSUM 0x02
170 #define FP_ERR_INBUF_OVERFLO 0x03
171 #define FP_ERR_ILLEGAL_CHAR 0x04
172 #define FP_ERR_INSUFF_CHARS 0x05
173 #define FP_ERR_WATCHDOG_TMO 0x06
174 #define FP_ERR_INV_LIMS_GOT 0x07
175 #define FP_ERR_ILLEGAL_DIGIT 0x80
176 #define FP_ERR_BAD_ADDRESS 0x81
177 #define FP_ERR_INBUF_FRMERR 0x82
178 #define FP_ERR_NO_MODULE 0x83
179 #define FP_ERR_INV_CHNL 0x84
180 #define FP_ERR_INV_RANGE 0x85
181 #define FP_ERR_INV_ATTR 0x86
182 #define FP_ERR_HOTSWAP 0x88
183 #define FP_ERR_ADDR_NOT_SAME 0x89
184 #define FP_ERR_NO_RESEND_BUF 0x8A
185 #define FP_ERR_HW_FAILURE 0x8B
186 #define FP_ERR_UNKNOWN 0x8C
187 #endif // DOXYGEN_SHOULD_SKIP_THIS
188 
190 #define HV_FUG_TIME_OUT 3000
191 
192 /* --------- to handle errors ---------------------------------------*/
193 #define HV_FUG_MAX_ERROR 5
194 #define HV_FUG_DELTA_TIME_ERROR 3600
195 
196 #define HV_FUG_MAX_READBACK_FAILURE 5
198 #define HV_FUG_RECONNECTION_TIMEOUT 10
200 #define HV_FUG_READ_ERROR -99
202 
204 #define HV_FUG_ETS_LOGOUT_SLEEP 10000
205 
206 //---- globals -----------------------------------------------------
207 
209 typedef struct {
215  char fp_io_modules[128];
216  char map_fp_fug_input[12][64];
217  char map_fp_fug_output[12][64];
218  char fug_properties[12][64];
220 
225 #define HV_FUG_SETTINGS_INTERNAL_STR "\
226 Detailed Messages = INT : 0\n\
227 ETS_IN_USE = INT : 1\n\
228 SCW_IN_USE = INT : 1\n\
229 "
230 
235 #define HV_FUG_SETTINGS_ODB_OFFSET_STR "\
236 ODB Channel Offset = INT : 0\n\
237 "
238 
243 #define HV_FUG_SETTINGS_NO_STR "\
244 No of FP-IO Modules = INT : 9\n\
245 "
246 
251 #define HV_FUG_SETTINGS_MODULE_STR "\
252 Modules = STRING : [128] 0:FP-1000; 1:FP-AO-210; 2:FP-AI-110; 3:FP-AI-110; 4:FP-AO-210; 5:FP-AI-110; 6:FP-AO-210; 7:FP-AI-110; 8:FP-RLY-420;\n\
253 "
254 
259 /*
260 #define HV_FUG_SETTINGS_OUT_STR "\
261 FUG fp mapping output = STRING[12] : \n\
262 [64] Moderator 04 0x0004 04 0x0008 N 00 0x0000 \n\
263 [64] Mod_Guard 04 0x0010 04 0x0020 N 00 0x0000 \n\
264 [64] Mod_Grid 04 0x0040 04 0x0080 N 00 0x0000 \n\
265 [64] Lense_1 06 0x0001 06 0x0002 N 00 0x0000 \n\
266 [64] Mirror 04 0x0001 04 0x0002 N 00 0x0000 \n\
267 [64] Lense_2 01 0x0040 01 0x0080 N 00 0x0000 \n\
268 [64] Lense_3 01 0x0010 01 0x0020 N 00 0x0000 \n\
269 [64] RA-L 01 0x0004 01 0x0008 N 00 0x0000 \n\
270 [64] RA-R 01 0x0001 01 0x0002 N 00 0x0000 \n\
271 [64] Sample_G1 06 0x0004 06 0x0008 Y 08 0x0004 \n\
272 [64] Sample_G2 06 0x0010 06 0x0020 Y 08 0x0008 \n\
273 [64] Sample 06 0x0040 06 0x0080 Y 08 0x0010 \n\
274 "
275 */
276 /*
277 #define HV_FUG_SETTINGS_OUT_STR "\
278 FUG fp mapping output = STRING[12] : \n\
279 [64] Moderator 04 0x0004 04 0x0008 N 00 0x0000 \n\
280 [64] Mod_Guard 04 0x0010 04 0x0020 N 00 0x0000 \n\
281 [64] Mod_Grid 06 0x0004 06 0x0008 N 08 0x0004 \n\
282 [64] Lense_1 06 0x0010 06 0x0020 N 08 0x0008 \n\
283 [64] Mirror 04 0x0001 04 0x0002 N 00 0x0000 \n\
284 [64] Lense_2 01 0x0040 01 0x0080 N 00 0x0000 \n\
285 [64] Lense_3 01 0x0010 01 0x0020 N 00 0x0000 \n\
286 [64] RA-L 01 0x0004 01 0x0008 N 00 0x0000 \n\
287 [64] RA-R 01 0x0001 01 0x0002 N 00 0x0000 \n\
288 [64] RA-T 06 0x0001 06 0x0002 N 00 0x0000 \n\
289 [64] RA-B 04 0x0040 04 0x0080 N 00 0x0000 \n\
290 [64] Sample 06 0x0040 06 0x0080 Y 08 0x0010 \n\
291 "
292 */
293 
294 /* channel assignments for bipolar RA */
295 #define HV_FUG_SETTINGS_OUT_STR "\
296 FUG fp mapping output = STRING[12] : \n\
297 [64] Moderator 04 0x0004 04 0x0008 N 00 0x0000 \n\
298 [64] Mod_Guard 04 0x0010 04 0x0020 N 00 0x0000 \n\
299 [64] Mod_Grid 01 0x0001 01 0x0002 N 00 0x0000 \n\
300 [64] Lense_1 01 0x0004 01 0x0008 N 00 0x0000 \n\
301 [64] Mirror 04 0x0001 04 0x0002 N 00 0x0000 \n\
302 [64] Lense_2 01 0x0040 01 0x0080 N 00 0x0000 \n\
303 [64] Lense_3 01 0x0010 01 0x0020 N 00 0x0000 \n\
304 [64] RA-L 06 0x0010 06 0x0020 Y 08 0x0008 \n\
305 [64] RA-R 06 0x0004 06 0x0008 Y 08 0x0004 \n\
306 [64] RA-T 06 0x0001 06 0x0002 Y 08 0x0002 \n\
307 [64] RA-B 04 0x0040 04 0x0080 Y 08 0x0001 \n\
308 [64] Sample 06 0x0040 06 0x0080 Y 08 0x0010 \n\
309 "
310 
314 /*
315 #define HV_FUG_SETTINGS_IN_STR "\
316 FUG fp mapping input = STRING[12] : \n\
317 [64] Moderator 03 0x0004 03 0x0008 N 00 0x0000 \n\
318 [64] Mod_Guard 03 0x0010 03 0x0020 N 00 0x0000 \n\
319 [64] Mod_Grid 03 0x0040 03 0x0080 N 00 0x0000 \n\
320 [64] Lense_1 07 0x0001 07 0x0002 N 00 0x0000 \n\
321 [64] Mirror 03 0x0001 03 0x0002 N 00 0x0000 \n\
322 [64] Lense_2 02 0x0040 02 0x0080 N 00 0x0000 \n\
323 [64] Lense_3 02 0x0010 02 0x0020 N 00 0x0000 \n\
324 [64] RA-L 02 0x0004 02 0x0008 N 00 0x0000 \n\
325 [64] RA-R 02 0x0001 02 0x0002 N 00 0x0000 \n\
326 [64] Sample_G1 07 0x0004 07 0x0008 Y 05 0x0004 \n\
327 [64] Sample_G2 07 0x0010 07 0x0020 Y 05 0x0008 \n\
328 [64] Sample 07 0x0040 07 0x0080 Y 05 0x0010 \n\
329 "
330 */
331 /*
332 #define HV_FUG_SETTINGS_IN_STR "\
333 FUG fp mapping input = STRING[12] : \n\
334 [64] Moderator 03 0x0004 03 0x0008 N 00 0x0000 \n\
335 [64] Mod_Guard 03 0x0010 03 0x0020 N 00 0x0000 \n\
336 [64] Mod_Grid 07 0x0004 07 0x0008 N 05 0x0004 \n\
337 [64] Lense_1 07 0x0010 07 0x0020 N 05 0x0008 \n\
338 [64] Mirror 03 0x0001 03 0x0002 N 00 0x0000 \n\
339 [64] Lense_2 02 0x0040 02 0x0080 N 00 0x0000 \n\
340 [64] Lense_3 02 0x0010 02 0x0020 N 00 0x0000 \n\
341 [64] RA-L 02 0x0004 02 0x0008 N 00 0x0000 \n\
342 [64] RA-R 02 0x0001 02 0x0002 N 00 0x0000 \n\
343 [64] RA-T 07 0x0001 07 0x0002 N 00 0x0000 \n\
344 [64] RA-B 03 0x0040 03 0x0080 N 00 0x0000 \n\
345 [64] Sample 07 0x0040 07 0x0080 Y 05 0x0010 \n\
346 "
347 */
348 
349 /* channel assignments for bipolar RA */
350 #define HV_FUG_SETTINGS_IN_STR "\
351 FUG fp mapping input = STRING[12] : \n\
352 [64] Moderator 03 0x0004 03 0x0008 N 00 0x0000 \n\
353 [64] Mod_Guard 03 0x0010 03 0x0020 N 00 0x0000 \n\
354 [64] Mod_Grid 02 0x0001 02 0x0002 N 00 0x0000 \n\
355 [64] Lense_1 02 0x0004 02 0x0008 N 00 0x0000 \n\
356 [64] Mirror 03 0x0001 03 0x0002 N 00 0x0000 \n\
357 [64] Lense_2 02 0x0040 02 0x0080 N 00 0x0000 \n\
358 [64] Lense_3 02 0x0010 02 0x0020 N 00 0x0000 \n\
359 [64] RA-L 07 0x0010 07 0x0020 Y 05 0x0008 \n\
360 [64] RA-R 07 0x0004 07 0x0008 Y 05 0x0004 \n\
361 [64] RA-T 07 0x0001 07 0x0002 Y 05 0x0002 \n\
362 [64] RA-B 03 0x0040 03 0x0080 Y 05 0x0001 \n\
363 [64] Sample 07 0x0040 07 0x0080 Y 05 0x0010 \n\
364 "
365 
369 /*
370 #define HV_FUG_SETTINGS_PROPERTIES_STR "\
371 Properties = STRING[12] : \n\
372 [64] Moderator @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
373 [64] Mod_Guard @20.0kV #0.6mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
374 [64] Mod_Grid @20.0kV #0.6mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
375 [64] Lense_1 @20.0kV #0.6mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
376 [64] Mirror @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
377 [64] Lense_2 @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
378 [64] Lense_3 @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
379 [64] RA-L @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
380 [64] RA-R @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
381 [64] Sample_G1 @12.5kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
382 [64] Sample_G2 @12.5kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
383 [64] Sample @12.5kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
384 "
385 */
386 #define HV_FUG_SETTINGS_PROPERTIES_STR "\
387 Properties = STRING[12] : \n\
388 [64] Moderator @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
389 [64] Mod_Guard @20.0kV #0.6mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
390 [64] Mod_Grid @12.5kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
391 [64] Lense_1 @12.5kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
392 [64] Mirror @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
393 [64] Lense_2 @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
394 [64] Lense_3 @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
395 [64] RA-L @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
396 [64] RA-R @35.0kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
397 [64] RA-T @20.0kV #0.6mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
398 [64] RA-B @20.0kV #0.6mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
399 [64] Sample @12.5kV #1.0mA up0.1kV/s down0.0kV/s $0.00kV !0.001mA \n\
400 "
401 
403 #define HV_FUG_SCW_STR "\
404 Proc Name = STRING : [32]\n\
405 PID = INT : -1\n\
406 Log Name = STRING : [64]\n\
407 DD Name = STRING : [32] FUG\n\
408 Last Updated = DWORD : 0\n\
409 Timeout = DWORD : 180\n\
410 "
411 
415 typedef struct {
417  LEM_SC_WATCHDOG scw;
419  INT (*bd)(INT cmd, ...);
420  void *bd_info;
421  HNDLE hDB;
422  HNDLE hkey;
423  HNDLE hDDkey;
424  float last_valid_hv[25];
425  float last_valid_current[25];
428  DWORD lasterrtime;
434 } HV_FUG_INFO;
435 
439 typedef struct {
440  char name[80];
449  float max_volt;
450  float max_curr;
453  float init_volt;
454  float init_curr;
460 } HV_FUG_FP;
461 
463 
465 // prototype declaration
466 INT hv_fug_get(HV_FUG_INFO *info, INT channel, float *pvalue);
467 
468 /*--------------------------------------------------------------------
469  hv specific routines in connection with field point interface
470  and the default settings for the data base.
471 --------------------------------------------------------------------*/
472 
473 // error filter routine ------------------------------------------------
484 INT fp_error_msg(HV_FUG_INFO *info, char *where, char *error)
485 {
486  int err_num=0;
487  char err_msg[512];
488 
489  if (strlen(error)<3) {
490  if (info->errorcount < HV_FUG_MAX_ERROR) {
491  if (info->hv_settings.detailed_msg)
492  cm_msg(MERROR, where, "Unrecognized Error (%d,%s). Possibly a communication problem.",
493  strlen(error), error);
494  info->errorcount++;
495  }
496  } else {
497  sscanf(error, "N%i", &err_num);
498  switch (err_num) {
499  case FP_ERR_PUCLR_EXP:
500  sprintf(err_msg, "FP ERROR %d: Power Up Clear expected.", err_num);
501  break;
502  case FP_ERR_INVALID_CMD:
503  sprintf(err_msg, "FP ERROR %d: Undefined command.", err_num);
504  break;
505  case FP_ERR_BAD_CHECKSUM:
506  sprintf(err_msg, "FP ERROR %d: Checksum error.", err_num);
507  break;
508  case FP_ERR_INBUF_OVERFLO:
509  sprintf(err_msg, "FP ERROR %d: Input buffer overrun.", err_num);
510  break;
511  case FP_ERR_ILLEGAL_CHAR:
512  sprintf(err_msg, "FP ERROR %d: Non-printable ASCII character received.", err_num);
513  break;
514  case FP_ERR_INSUFF_CHARS:
515  sprintf(err_msg, "FP ERROR %d: Data field error. Insufficient or incorrect number of characters were received.", err_num);
516  break;
517  case FP_ERR_WATCHDOG_TMO:
518  sprintf(err_msg, "FP ERROR %d: Communication link network watchdog timed out.", err_num);
519  break;
520  case FP_ERR_INV_LIMS_GOT:
521  sprintf(err_msg, "FP ERROR %d: Specified limits invalid for the command.", err_num);
522  break;
523  case FP_ERR_ILLEGAL_DIGIT:
524  sprintf(err_msg, "FP ERROR %d: One or more characters sent in the command could not be correctely converted to a digit.", err_num);
525  break;
526  case FP_ERR_BAD_ADDRESS:
527  sprintf(err_msg, "FP ERROR %d: Addressed module does not support the sent command.", err_num);
528  break;
529  case FP_ERR_INBUF_FRMERR:
530  sprintf(err_msg, "FP ERROR %d: Serial framing error.", err_num);
531  break;
532  case FP_ERR_NO_MODULE:
533  sprintf(err_msg, "FP ERROR %d: Addressed module does not exist.", err_num);
534  break;
535  case FP_ERR_INV_CHNL:
536  sprintf(err_msg, "FP ERROR %d: Channel command error.", err_num);
537  break;
538  case FP_ERR_INV_RANGE:
539  sprintf(err_msg, "FP ERROR %d: Channel command error.", err_num);
540  break;
541  case FP_ERR_INV_ATTR:
542  sprintf(err_msg, "FP ERROR %d: Channel command error.", err_num);
543  break;
544  case FP_ERR_HOTSWAP:
545  sprintf(err_msg, "FP ERROR %d: The module has been hot-swapped since the last sent command.", err_num);
546  break;
547  case FP_ERR_ADDR_NOT_SAME:
548  sprintf(err_msg, "FP ERROR %d: Module switched.", err_num);
549  break;
550  case FP_ERR_NO_RESEND_BUF:
551  sprintf(err_msg, "FP ERROR %d: Response to the last command is unavailable.", err_num);
552  break;
553  case FP_ERR_HW_FAILURE:
554  sprintf(err_msg, "FP ERROR %d: An irrecoverable fault has occured.", err_num);
555  break;
556  case FP_ERR_UNKNOWN:
557  sprintf(err_msg, "FP ERROR %d: An unidentifiable error condition has occured.", err_num);
558  break;
559  default:
560  strcpy(err_msg,"Unrecognized Error. Possibly a communication problem.");
561  }
562  if (info->errorcount < HV_FUG_MAX_ERROR) {
563  if (info->hv_settings.detailed_msg)
564  cm_msg(MERROR, where, err_msg);
565  info->errorcount++;
566  }
567  }
568 
569  return FE_ERR_HW;
570 }
571 
572 /*------ copies substring from line starting with start, stoping with stop ---*/
582 void mid_str(char *start, char *stop, char *line, char *result)
583 {
584  char *s, *e;
585 
586  s=strstr(line, start);
587  strcpy(result, s+strlen(start));
588  e=strstr(result, stop);
589  *e='\0';
590 }
591 
592 /*------ copies substring from line starting with start, stoping with stop ---*/
604 void sub_str(int start, int stop, char *line, char *result, int size_line, int size_result)
605 {
606  int i, j=0;
607 
608  if (stop > size_line)
609  stop = size_line;
610 
611  for (i=start; i<stop; i++){
612  if (j < size_result) {
613  result[j] = line[i];
614  j++;
615  }
616  }
617  result[j] = '\0';
618 }
619 
631 char *filter_sub_str(char *str, char *start, char *stop, char *result)
632 {
633  char *pstart, *pstop;
634 
635  if ((pstart=strstr(str, start))==NULL) return NULL;
636  pstart++;
637  strcpy(result, pstart);
638  if ((pstop=strstr(result, stop))==NULL) return NULL;
639  *pstop='\0';
640  return result;
641 }
642 
643 /*------ Checksum check ------------------------------------------------------*/
654 int chksumchk(char *line, char *chksum)
655 {
656  int i, sum=0, checksum=0;
657 
658  sscanf(chksum, "%X", &checksum); // %X since chksum is in HEX
659 
660  for (i=0; i<strlen(line); i++)
661  sum += line[i];
662 
663  sum %= 256;
664 
665  if (sum!=checksum)
666  return 0;
667  else
668  return 1;
669 }
670 
671 /*----- check attribute/range string for input module -------------------------*/
684 int chk_attrib_in(HV_FUG_INFO *info, int module, char *line)
685 {
686  int i;
687  char str[3];
688  int value;
689 
690  for (i=0; i<FP_IO_NUM_CH; i++) {
691  strncpy(str, line+(i<<2), 2);
692  sscanf(str, "%X", &value);
693  if (value != FP_AI_110_FILTER) {
694  if (info->errorcount < HV_FUG_MAX_ERROR) {
695  cm_msg(MERROR, "hv_fug_init", "Input Module %d, Module-Channel %d, wrong filter setting.", module, i+1);
696  info->errorcount++;
697  }
698  return FE_ERR_HW;
699  }
700  strncpy(str, line+((i<<2)+2), 2);
701  sscanf(str, "%X", &value);
702  if (value != FP_AI_110_RANGE) {
703  if (info->errorcount < HV_FUG_MAX_ERROR) {
704  cm_msg(MERROR, "hv_fug_init", "Input Module %d, Module-Channel %d, wrong range setting.", module, i+1);
705  info->errorcount++;
706  }
707  return FE_ERR_HW;
708  }
709  }
710  return 0;
711 }
712 
713 /*----- check attribute/range string for output module -------------------------*/
726 int chk_attrib_out(HV_FUG_INFO *info, int module, char *line)
727 {
728  int i;
729  char str[3];
730  int value;
731 
732  for (i=0; i<FP_IO_NUM_CH; i++) {
733  strncpy(str, line+(i<<1), 2);
734  sscanf(str, "%X", &value);
735  if (value != FP_AO_210_RANGE) {
736  if (info->errorcount < HV_FUG_MAX_ERROR) {
737  cm_msg(MERROR, "hv_fug_init", "Output Module %d, Module-Channel %d, wrong range setting.", module, i+1);
738  info->errorcount++;
739  }
740  return FE_ERR_HW;
741  }
742  }
743  return 0;
744 }
745 
746 /*----- check attribute/range string for relais module -------------------------*/
759 int chk_attrib_rly(HV_FUG_INFO *info, int module, char *line)
760 {
761  int i;
762  char str[3];
763  int value;
764 
765  for (i=0; i<FP_IO_NUM_CH; i++) {
766  strncpy(str, line+(i<<1), 2);
767  sscanf(str, "%X", &value);
768  if (value != FP_RLY_SETTING) {
769  if (info->errorcount < HV_FUG_MAX_ERROR) {
770  cm_msg(MERROR, "hv_fug_init", "Relais Module %d, Module-Channel %d, wrong range setting.", module, i+1);
771  info->errorcount++;
772  }
773  return FE_ERR_HW;
774  }
775  }
776  return 0;
777 }
778 
779 /*----------------------------------------------------------------------------*/
788 void err_bad_channels(char *line, int module, HV_FUG_INFO *info)
789 {
790  int i, j;
791  int code;
792  char msg[128];
793  char substr[128];
794 
795  sscanf(line, "%X", &code);
796  sprintf(msg,"hv_fug_init: module %d, channel(s) ( ", module);
797  for (i=0; i<16; i++) {
798  if ((1<<i) & code) {
799  sprintf(substr, "%d ", i);
800  strcat(msg, substr);
801  for (j=0; j<info->num_channels; j++) {
802  if ((hv_fug_fp_set[j].module_cdc_out==module) && (hv_fug_fp_set[j].channel_cdc_out==1<<i)) {
803  sprintf(substr, "(%s) ", hv_fug_fp_set[j].name);
804  strcat(msg, substr);
805  }
806  }
807  }
808  }
809  strcat(msg, " ) are bad.");
810  if (info->errorcount < HV_FUG_MAX_ERROR) {
811  cm_msg(MERROR, "hv_fug_init", msg);
812  info->errorcount++;
813  }
814 }
815 
816 /*----------------------------------------------------------------------------*/
828 static INT hv_fug_update_db_settings(HNDLE hDB, HV_FUG_INFO *info, INT channels)
829 {
830  int i;
831  int status, err, size;
832  float dummy;
833  char name[128], str[10];
834  HNDLE hkey;
835 
836 
837  // filter fug device settings from string
838  for (i=0; i<channels; i++){ // input channels
839  sscanf(info->hv_settings.map_fp_fug_input[i], "%s %X %X %X %X %s %X %X",
840  hv_fug_fp_set[i].name, &hv_fug_fp_set[i].module_vdc_in, &hv_fug_fp_set[i].channel_vdc_in,
841  &hv_fug_fp_set[i].module_cdc_in, &hv_fug_fp_set[i].channel_cdc_in,
842  str, &hv_fug_fp_set[i].module_relais_in, &hv_fug_fp_set[i].channel_relais_in);
843  if (strstr(str, "Y")) // decode flag
844  hv_fug_fp_set[i].hv_switchable = TRUE;
845  else
846  hv_fug_fp_set[i].hv_switchable = FALSE;
847  }
848  for (i=0; i<channels; i++){ // ouput channels
849  sscanf(info->hv_settings.map_fp_fug_output[i], "%s %X %X %X %X %s %X %X",
850  name, &hv_fug_fp_set[i].module_vdc_out, &hv_fug_fp_set[i].channel_vdc_out,
851  &hv_fug_fp_set[i].module_cdc_out, &hv_fug_fp_set[i].channel_cdc_out,
852  str, &hv_fug_fp_set[i].module_relais_out, &hv_fug_fp_set[i].channel_relais_out);
853  }
854  for (i=0; i<channels; i++){ // properties
855  sscanf(info->hv_settings.fug_properties[i], "%s @%fkV #%fmA up%fkV/s down%fkV/s $%fkV !%fmA",
856  name, &hv_fug_fp_set[i].max_volt, &hv_fug_fp_set[i].max_curr,
857  &hv_fug_fp_set[i].ramping_speed_up, &hv_fug_fp_set[i].ramping_speed_down,
858  &hv_fug_fp_set[i].init_volt, &hv_fug_fp_set[i].init_curr);
859  }
860 
861  // update voltage limits if needed
862  if ((err=db_find_key(hDB, 0, "/Equipment/HV/Settings/Voltage Limit", &hkey))!=DB_SUCCESS)
863  return err;
864  size=sizeof(float);
865  if ((err=db_get_data_index(hDB, hkey, &dummy, &size, 0+info->hv_settings.odb_offset, TID_FLOAT))!=DB_SUCCESS)
866  return err;
867  if ((dummy==3000.f) || (dummy==0.f)) {
868  for (i=0; i<channels; i++){
869  if ((err=db_set_data_index(hDB, hkey, &hv_fug_fp_set[i].max_volt, sizeof(float), i+info->hv_settings.odb_offset, TID_FLOAT))!=DB_SUCCESS)
870  return err;
871  }
872  }
873 
874  // update current limits if needed
875  if ((err=db_find_key(hDB, 0, "/Equipment/HV/Settings/Current Limit", &hkey))!=DB_SUCCESS)
876  return err;
877  size=sizeof(float);
878  if ((err=db_get_data_index(hDB, hkey, &dummy, &size, 0+info->hv_settings.odb_offset, TID_FLOAT))!=DB_SUCCESS)
879  return err;
880  if ((dummy==3000.f) || (dummy==0.f)) {
881  for (i=0; i<channels; i++){
882  if ((err=db_set_data_index(hDB, hkey, &hv_fug_fp_set[i].init_curr, sizeof(float), i+info->hv_settings.odb_offset, TID_FLOAT))!=DB_SUCCESS)
883  return err;
884  }
885  }
886 
887  // update ramping speed up if needed
888  if ((err=db_find_key(hDB, 0, "/Equipment/HV/Settings/Ramp Up Speed", &hkey))!=DB_SUCCESS)
889  return err ;
890  size=sizeof(float);
891  if ((err=db_get_data_index(hDB, hkey, &dummy, &size, 0+info->hv_settings.odb_offset, TID_FLOAT))!=DB_SUCCESS)
892  return err;
893  if (dummy==0.f) {
894  for (i=0; i<channels; i++){
895  if ((err=db_set_data_index(hDB, hkey, &hv_fug_fp_set[i].ramping_speed_up, sizeof(float), i+info->hv_settings.odb_offset, TID_FLOAT))!=DB_SUCCESS)
896  return err;
897  }
898  }
899 
900  // update ramping speed down if needed
901  if ((err=db_find_key(hDB, 0, "/Equipment/HV/Settings/Ramp Down Speed", &hkey))!=DB_SUCCESS)
902  return err ;
903  size=sizeof(float);
904  if ((err=db_get_data_index(hDB, hkey, &dummy, &size, 0+info->hv_settings.odb_offset, TID_FLOAT))!=DB_SUCCESS)
905  return err;
906  if (dummy==0.f) {
907  for (i=0; i<channels; i++){
908  if ((err=db_set_data_index(hDB, hkey, &hv_fug_fp_set[i].ramping_speed_down, sizeof(float), i+info->hv_settings.odb_offset, TID_FLOAT))!=DB_SUCCESS)
909  return err;
910  }
911  }
912 
913  // update Update Threshold Measured table if necessary
914  status = db_find_key(hDB, 0, "/Equipment/HV/Settings/Update Threshold Measured", &hkey);
915  if (status != DB_SUCCESS) return FE_ERR_ODB;
916  for (i=0; i<channels; i++) {
917  size = sizeof(float);
918  db_get_data_index(hDB, hkey, &dummy, &size, i+info->hv_settings.odb_offset, TID_FLOAT);
919  if (dummy!=2) break;
920  dummy = 50/1e3;
921  db_set_data_index(hDB, hkey, &dummy, size, i+info->hv_settings.odb_offset, TID_FLOAT);
922  }
923 
924  // update Update Threshold Current table if necessary
925  status = db_find_key(hDB, 0, "/Equipment/HV/Settings/Update Threshold Current", &hkey);
926  if (status != DB_SUCCESS) return FE_ERR_ODB;
927  for (i=0; i<channels; i++) {
928  size = sizeof(float);
929  db_get_data_index(hDB, hkey, &dummy, &size, i+info->hv_settings.odb_offset, TID_FLOAT);
930  if (dummy!=2) break;
931  dummy = 1/1e3;
932  db_set_data_index(hDB, hkey, &dummy, size, i+info->hv_settings.odb_offset, TID_FLOAT);
933  }
934 
935  return 0;
936 }
937 
938 /*----------------------------------------------------------------------------*/
951 {
952  int status=0;
953  int i;
954  char str[128];
955 
956  // ==0 is the RS232 interface itself!
957  for (i=0; i<info->hv_settings.no_fp_modules; i++) {
958  sprintf(str,">0%dA??\r",i); // Power Up Clear (FieldPoint Programmer Reference Manual p.4-2)
959  BD_PUTS(str);
960  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
961  if (str[0]!='A') {
962  if (info->errorcount < HV_FUG_MAX_ERROR) {
963  cm_msg(MERROR, "fp_power_up_clear", "Field point module %d does not respond. Check power/RS232 conection.", i);
964  info->errorcount++;
965  }
966  return FE_ERR_HW;
967  }
968  }
969  return 0;
970 }
971 
972 /*----------------------------------------------------------------------------*/
985 {
986  int status=0;
987  char str[128];
988  char sub[3];
989  int tot_num_modules=0;
990  int i;
991  char db_str[512];
992  char parse[128];
993  char module_name[128];
994  char type_str[512];
995 
996  strcpy(str,">00!B??\r"); // Read All Module IDs (FieldPoint Programmer Reference Manual p.5-4)
997  BD_PUTS(str);
998  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
999  if (str[0]!='A') return fp_error_msg(info, "fp_check_modules in hv_fug_init", str);
1000 
1001  // isolate # modules from recived string
1002  strncpy(sub, &str[1], 2);
1003  sub[2]='\0';
1004  sscanf(sub, "%d", &tot_num_modules);
1005 
1006  // check if DB setting corresponds to actual configuration
1007  if (info->hv_settings.no_fp_modules != tot_num_modules) {
1008  sprintf(str, "# Modules according DB = %d, # Modules according FP = %d. They have to be equal!",
1009  info->hv_settings.no_fp_modules, tot_num_modules-1);
1010  if (info->errorcount < HV_FUG_MAX_ERROR) {
1011  cm_msg(MERROR, "hv_fug_init", str);
1012  info->errorcount++;
1013  }
1014  return FE_ERR_HW;
1015  }
1016  // check that recived string is long enough
1017  if (strlen(str)!=tot_num_modules*4+6) {
1018  if (info->errorcount < HV_FUG_MAX_ERROR) {
1019  cm_msg(MERROR, "hv_fug_init", "Recieved data from FP1000 are corrupted.");
1020  info->errorcount++;
1021  }
1022  return FE_ERR_HW;
1023  }
1024  // check if the module-types are correct
1025  strcpy(db_str, info->hv_settings.fp_io_modules);
1026  strcpy(type_str,"");
1027  for (i=0; i<tot_num_modules; i++) {
1028  sprintf(parse, "%d:", i);
1029  mid_str(parse, ";", db_str, module_name);
1030  if (!strcmp(module_name, "FP-1000"))
1031  strcat(type_str, "0001");
1032  else if (!strcmp(module_name, "FP-AI-110"))
1033  strcat(type_str, "0101");
1034  else if (!strcmp(module_name, "FP-AO-210"))
1035  strcat(type_str, "010F");
1036  else if (!strcmp(module_name, "FP-RLY-420"))
1037  strcat(type_str, "0108");
1038  else {
1039  if (info->errorcount < HV_FUG_MAX_ERROR) {
1040  cm_msg(MERROR, "hv_fug_init", "Wrong FP-Module entry in DB.");
1041  info->errorcount++;
1042  }
1043  return FE_ERR_HW;
1044  }
1045  }
1046  if (!strstr(str, type_str)) {
1047  if (info->errorcount < HV_FUG_MAX_ERROR) {
1048  cm_msg(MERROR, "hv_fug_init", "FP-Module order differs between DB and FP.");
1049  info->errorcount++;
1050  }
1051  return FE_ERR_HW;
1052  }
1053 
1054  return 0;
1055 }
1056 
1057 /*----------------------------------------------------------------------------*/
1085 {
1086  int status=0;
1087  int i, err;
1088  char str[512], substr[512], chksumstr[4];
1089 
1090  for (i=1; i<info->hv_settings.no_fp_modules; i++) {
1091  sprintf(str, ">%02X!A??\r", i); // get module id command
1092  BD_PUTS(str);
1093  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1094  if (info->hv_settings.detailed_msg > 1) // debug info
1095  cm_msg(MINFO, "fp_check_attrib_settings", "debug> (0) fp_check_attrib_settings: str=%s", str);
1096  if (strstr(str, "0101")) { // input module FP-AI-110
1097  /* --------------------------------------------------------------------
1098  gets ALL the attributes and ranges of ALL the channels per input module
1099  at once.
1100  see FieldPoint Programmer Reference Manual, p.5-14
1101  0xFF = 11111111, i.e. for every channel (8 for the FP-AI-110) there
1102  is a character (bit) set = 1.
1103  for each channel 'bit' set there is an attribute mask and a range mask.
1104  The attribute mask is 4 byte (e.g. 0x0001) and the range mask 1 byte
1105  (e.g. 1).
1106  return structure: A0004...000420 with the meaning
1107  for each channel 4 characters, the first two are the attributes 0x00=60Hz
1108  the second two are the range 0x04=0-10.4V
1109  the very last two characters of the string are the checksum.
1110  (for checksum see subroutine chksumchk above and Manual P.1-3)
1111  -------------------------------------------------------------------- */
1112  sprintf(str, ">%02X!E00FF0001100011000110001100011000110001100011??\r", i);
1113  BD_PUTS(str);
1114  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1115  if (info->hv_settings.detailed_msg > 1) // debug info
1116  cm_msg(MINFO, "fp_check_attrib_settings", "debug> (1) fp_check_attrib_settings, str=%s", str);
1117  if (str[0]!='A')
1118  return fp_error_msg(info, "fp_check_attrib_settings in hv_fug_init", str);
1119  sub_str(1, 2*2*FP_IO_NUM_CH+1, str, substr, sizeof(str), sizeof(substr)); // attribute and range
1120  sub_str(strlen(str)-3, strlen(str), str, chksumstr, sizeof(str), sizeof(chksumstr)); // checksum
1121  if (!chksumchk(substr, chksumstr))
1122  return fp_error_msg(info, "fp_check_attrib_settings in hv_fug_init (FP-AI-110)", "N02");
1123  if ((err=chk_attrib_in(info, i, substr)))
1124  return err; // analysis response string
1125  }
1126  if (strstr(str, "010F")) { // output module FP-AO-210
1127  sprintf(str, ">%02X!E00FF0000100001000010000100001000010000100001??\r", i);
1128  BD_PUTS(str);
1129  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1130  if (info->hv_settings.detailed_msg > 1) // debug info
1131  cm_msg(MINFO, "fp_check_attrib_settings", "debug> (2) fp_check_attrib_settings, str='%s'", str);
1132  if (str[0]!='A')
1133  return fp_error_msg(info, "fp_check_attrib_settings in hv_fug_init", str);
1134  sub_str(1, 2*FP_IO_NUM_CH+1, str, substr, sizeof(str), sizeof(substr)); // attribute and range
1135  sub_str(strlen(str)-3, strlen(str), str, chksumstr, sizeof(str), sizeof(chksumstr)); // checksum
1136  if (!chksumchk(substr, chksumstr))
1137  return fp_error_msg(info, "fp_check_attrib_settings in hv_fug_init (FP-AO-210)", "N02");
1138  if ((err=chk_attrib_out(info, i, substr)))
1139  return err; // analysis response string
1140  }
1141  if (strstr(str, "0108")) { // relay module FP-RLY-420
1142  sprintf(str, ">%02X!E00FF0000100001000010000100001000010000100001??\r", i);
1143  BD_PUTS(str);
1144  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1145  if (info->hv_settings.detailed_msg > 1) // debug info
1146  cm_msg(MINFO, "fp_check_attrib_settings", "debug> (3) fp_check_attrib_settings, str=%s", str);
1147  if (str[0]!='A')
1148  return fp_error_msg(info, "fp_check_attrib_settings in hv_fug_init (FP-RLY-420)", str);
1149  sub_str(1, 2*FP_IO_NUM_CH+1, str, substr, sizeof(str), sizeof(substr)); // attribute and range
1150  sub_str(strlen(str)-3, strlen(str), str, chksumstr, sizeof(str), sizeof(chksumstr)); // checksum
1151  if (!chksumchk(substr, chksumstr))
1152  return fp_error_msg(info, "fp_check_attrib_settings in hv_fug_init", "N02");
1153  if ((err=chk_attrib_rly(info, i, substr)))
1154  return err; // analysis response string
1155  }
1156  }
1157 
1158  return 0;
1159 }
1160 
1161 
1162 /*----------------------------------------------------------------------------*/
1174 {
1175  int status=0;
1176  int i, j;
1177  struct {
1178  int mask;
1179  int hits;
1180  float curr_ratio[8];
1181  } mod[32];
1182  char *cmd[32]; // pointer array to fill current masks
1183  char str[128], substr[5], res[128];
1184 
1185  // set current limits for all modules ---------------------------------------
1186  for (i=1; i<info->hv_settings.no_fp_modules; i++) { // allocate memory for available modules
1187  cmd[i] = (char *) malloc(512*sizeof(char));
1188  mod[i].mask = 0;
1189  mod[i].hits = 0;
1190  }
1191  // generate current mask
1192  for (i=0; i<info->num_channels; i++) {
1193  mod[hv_fug_fp_set[i].module_cdc_out].mask |= hv_fug_fp_set[i].channel_cdc_out;
1194  mod[hv_fug_fp_set[i].module_cdc_out].curr_ratio[mod[hv_fug_fp_set[i].module_cdc_out].hits] = hv_fug_fp_set[i].init_curr/hv_fug_fp_set[i].max_curr;
1195  mod[hv_fug_fp_set[i].module_cdc_out].hits += 1;
1196  }
1197  // generate FP send commands
1198  for (i=1; i<info->hv_settings.no_fp_modules; i++) {
1199  if (mod[i].mask != 0) { // output module
1200  sprintf(cmd[i], ">%02X!I%04X", i, mod[i].mask);
1201  for (j=mod[i].hits-1; j>=0; j--) { // data filling starts with most significant 'bit'!!!
1202  sprintf(str, "%04X", (int)(mod[i].curr_ratio[j]*FP_IO_RESOL*FP_AO_NORM));
1203  strcat(cmd[i], str);
1204  }
1205  strcat(cmd[i], "??\r");
1206  } else { // input module
1207  strcpy(cmd[i],"");
1208  }
1209  }
1210  // send command
1211  for (i=1; i<info->hv_settings.no_fp_modules; i++) {
1212  if (mod[i].mask != 0) { // output module
1213  BD_PUTS(cmd[i]);
1214  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1215  if (str[0]!='A') return fp_error_msg(info, "fp_write_defaults in hv_fug_init", str);
1216  sub_str(1, 5, str, substr, sizeof(str), sizeof(substr));
1217  if (strcmp(substr,"0000")) {
1218  err_bad_channels(substr, i, info);
1219  return FE_ERR_HW;
1220  }
1221  }
1222  }
1223 
1224  // read back current settings of modules ---------------------------------------
1225  for (i=1; i<info->hv_settings.no_fp_modules; i++) {
1226  if (mod[i].mask != 0) { // output module
1227  sprintf(cmd[i], ">%02X!F%04X??\r", i, mod[i].mask); // reads, from module i, 8 channels back
1228  BD_PUTS(cmd[i]);
1229  status = BD_GETS(res, sizeof(res), "\r", HV_FUG_TIME_OUT);
1230  if (res[0]!='A') return fp_error_msg(info, "fp_write_defaults in hv_fug_init", res);
1231  // check if readback values are equal to set values
1232  sub_str(1, strlen(res)-3, res, res, sizeof(res), sizeof(res)); // cut out current coding
1233  // construct current code line
1234  strcpy(str,"");
1235  for (j=mod[i].hits-1; j>=0; j--) { // data filling starts with most significant 'bit'!!!
1236  sprintf(substr, "%04X", (int)(mod[i].curr_ratio[j]*FP_IO_RESOL*FP_AO_NORM));
1237  strcat(str, substr);
1238  }
1239  if (strcmp(res, str)) {
1240  if (info->errorcount < HV_FUG_MAX_ERROR) {
1241  cm_msg(MERROR, "hv_fug_init", "current limit readback error in module %d.", i);
1242  info->errorcount++;
1243  }
1244  }
1245  }
1246  }
1247 
1248  for (i=1; i<info->hv_settings.no_fp_modules; i++) { // free memory for available modules
1249  free(cmd[i]);
1250  }
1251  return 0;
1252 }
1253 
1254 /*----------------------------------------------------------------------------*/
1255 /*---- device driver routines ------------------------------------------------*/
1256 /*----------------------------------------------------------------------------*/
1271 INT hv_fug_init(HNDLE hKey, void **pinfo, INT channels, INT (*bd)(INT cmd, ...))
1272 {
1273  int status, size;
1274  HNDLE hDB, hDDKey;
1275  HV_FUG_INFO *info;
1276  char str[4096];
1277 
1278  // allocate info structure
1279  info = (HV_FUG_INFO *) calloc(1, sizeof(HV_FUG_INFO));
1280  *pinfo = info;
1281 
1282  cm_get_experiment_database(&hDB, NULL);
1283 
1284  // create device driver settings records
1285  strcpy(str, HV_FUG_SETTINGS_INTERNAL_STR);
1286  strcat(str, HV_FUG_SETTINGS_ODB_OFFSET_STR);
1287  strcat(str, HV_FUG_SETTINGS_NO_STR);
1288  strcat(str, HV_FUG_SETTINGS_MODULE_STR);
1289  strcat(str, HV_FUG_SETTINGS_IN_STR);
1290  strcat(str, HV_FUG_SETTINGS_OUT_STR);
1291  strcat(str, HV_FUG_SETTINGS_PROPERTIES_STR);
1292  status = db_create_record(hDB, hKey, "DD/FUG", str);
1293  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1294  info->startup_error = TRUE;
1295  cm_msg(MERROR, "hv_fug_init", "hv_fug_init: Couldn't create DD/FUG in ODB: status=%d", status);
1296  cm_yield(0);
1297  return FE_ERR_ODB;
1298  }
1299 
1300  // create slowcontrol watchdog info structure
1301  status = db_create_record(hDB, hKey, "DD/SCW", HV_FUG_SCW_STR);
1302  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1303  info->startup_error = TRUE;
1304  cm_msg(MERROR, "hv_fug_init", "hv_fug_init: Couldn't create DD/SCW in ODB: status=%d", status);
1305  cm_yield(0);
1306  return FE_ERR_ODB;
1307  }
1308 
1309  // get device driver ODB key
1310  status = db_find_key(hDB, hKey, "DD/FUG", &hDDKey);
1311  if (status != DB_SUCCESS) {
1312  info->startup_error = TRUE;
1313  return FE_ERR_ODB;
1314  }
1315 
1316  // establish hot-link
1317  size = sizeof(info->hv_settings);
1318  db_get_record(hDB, hDDKey, &info->hv_settings, &size, 0);
1319 
1320  // initialize driver
1321  info->num_channels = channels; // # of channels
1322  info->bd = bd;
1323  info->hDDkey = hDDKey;
1324  info->hDB = hDB;
1325  info->hkey = hKey;
1326  info->startup_error = FALSE;
1327  info->errorcount = 0;
1328  info->lasterrtime = ss_time();
1329  info->last_reconnect = ss_time();
1330  info->readback_failure = 0;
1331  info->reconnection_failures = 0;
1332  info->first_bd_error = 1;
1333 
1334  // initialize bus driver
1335  status = info->bd(CMD_INIT, hKey, &info->bd_info);
1336  if (status != SUCCESS) {
1337  info->startup_error = TRUE;
1338  info->bd_connected = FALSE;
1339  return status;
1340  }
1341  info->bd_connected = TRUE;
1342 
1343  // update settings
1344  if (hv_fug_update_db_settings(hDB, info, channels))
1345  return FE_ERR_DRIVER;
1346 
1347  // initialize and check hv devices
1348  cm_msg(MINFO, "hv_fug_init", "HV FUG INIT: Power Up Clear.");
1349  if (fp_power_up_clear(hDB, info)) {
1350  info->startup_error = TRUE;
1351  cm_msg(MERROR, "hv_fug_init", "**ERROR** HV FUG INIT: Power Up Clear failed.");
1352  cm_yield(0);
1353  return FE_ERR_HW;
1354  }
1355 
1356  cm_msg(MINFO, "hv_fug_init", "HV FUG INIT: Check Modules and DB Settings.");
1357  if (fp_check_modules(hDB, info)) {
1358  info->startup_error = TRUE;
1359  cm_msg(MERROR, "hv_fug_init", "**ERROR** HV FUG INIT: Check Modules and DB Settings failed.");
1360  cm_yield(0);
1361  return FE_ERR_HW;
1362  }
1363 
1364  cm_msg(MINFO, "hv_fug_init", "HV FUG INIT: Check Module Attributes and Range Settings.");
1365  cm_yield(0);
1366  if (fp_check_attrib_settings(hDB, info)) {
1367  info->startup_error = TRUE;
1368  cm_msg(MERROR, "hv_fug_init", "**ERROR** HV FUG INIT: Check Module Attributes and Range Settings failed.");
1369  cm_yield(0);
1370  return FE_ERR_HW;
1371  }
1372 
1373  cm_msg(MINFO, "hv_fug_init", "HV FUG INIT: Write Defaults for HV and Current Limits.");
1374  cm_yield(0);
1375  if (fp_write_defaults(hDB, info)) {
1376  info->startup_error = TRUE;
1377  cm_msg(MERROR, "hv_fug_init", "**ERROR** HV FUG INIT: Write Defaults for HV and Current Limits failed.");
1378  cm_yield(0);
1379  return FE_ERR_HW;
1380  }
1381 
1382  if (info->hv_settings.scw_in_use) { // slowcontrol watchdog shall be used
1383  // register with the slowcontrol watchdog -------------------------------------
1384  // find scw record in DD
1385  db_find_key(hDB, hKey, "DD/SCW", &hDDKey);
1386  // get record
1387  size = sizeof(info->scw);
1388  db_get_record(hDB, hDDKey, &info->scw, &size, 0);
1389  // fill watchdog structure
1390  info->scw.pid = ss_getpid();
1391  info->scw.last_updated = ss_time();
1392  // write info back into ODB
1393  db_set_record(hDB, hDDKey, &info->scw, sizeof(info->scw), 0);
1394 
1395  // register with slowcontrol watchdog
1396  status = lem_scw_init(&info->scw);
1397  if (status != LEM_SCW_SUCCESS) {
1398  cm_msg(MINFO, "hv_fug_init", "Couldn't register with lem watchdog");
1399  cm_yield(0);
1400  }
1401  }
1402 
1403  return FE_SUCCESS;
1404 }
1405 
1406 /*----------------------------------------------------------------------------*/
1416 {
1417  if (info->startup_error) return FE_SUCCESS;
1418 
1419  // call EXIT function of bus driver, usually closes device
1420  if (info->bd_connected)
1421  info->bd(CMD_EXIT, info->bd_info);
1422 
1423  if (info->hv_settings.scw_in_use && !info->startup_error) { // slowcontrol watchdog in use
1424  // deregister from the slowcontrol watchdog
1425  lem_scw_exit(&info->scw);
1426  }
1427 
1428  free(info);
1429 
1430  return FE_SUCCESS;
1431 }
1432 
1433 /*----------------------------------------------------------------------------*/
1443 INT hv_fug_set(HV_FUG_INFO *info, INT channel, float value)
1444 {
1445  int status, val, ch;
1446  float sign;
1447  char str[512], err[512], dat[512], substr[5];
1448 
1449  if (info->startup_error) return FE_SUCCESS;
1450 
1451  // bus driver not connect at the moment
1452  if (!info->bd_connected) {
1453  if (info->first_bd_error) {
1454  info->first_bd_error = 0;
1455  cm_msg(MERROR, "hv_fug_set",
1456  "set HV not possible at the moment, since the bus driver is not available!");
1457  }
1458  return FE_SUCCESS;
1459  }
1460 
1461  if (hv_fug_fp_set[channel].hv_switchable) { // hv polarity switchable fug
1462  // read relais state
1463  sprintf(str, ">%02X!G%04X??\r", hv_fug_fp_set[channel].module_relais_in,
1464  hv_fug_fp_set[channel].channel_relais_in);
1465  BD_PUTS(str);
1466  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1467  // All the different checks to see if data are OK
1468  if ((str[0]!='A') || (strlen(str)!=12)) { // return value total garbage
1469  ch = (int)(log(hv_fug_fp_set[channel].channel_vdc_out)/log(2))+1;
1470  sprintf(err, "hv_fug_set, module %d, channel %d", hv_fug_fp_set[channel].module_vdc_out, ch);
1471  return fp_error_msg(info, err, str);
1472  }
1473  if (strstr(str, "FFFF")) { // positive fug polarity
1474  sign = 1.0;
1475  } else { // negative fug polarity
1476  sign = -1.0;
1477  }
1478  // check the sign of the value
1479  if (sign != value/fabs(value)) { // sign of value and fug settings do not coincide
1480  // switch fug polarity
1481  if (sign == 1) {
1482  strcpy(dat, "FFFF");
1483  } else {
1484  strcpy(dat, "0000");
1485  }
1486  sprintf(str, ">%02X!M%04X%s??\r", hv_fug_fp_set[channel].module_relais_out,
1487  hv_fug_fp_set[channel].channel_relais_out, dat);
1488  BD_PUTS(str);
1489  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1490  // All the different checks to see if data are OK
1491  if ((str[0]!='A') || (strlen(str)!=8)) { // return value total garbage
1492  ch = (int)(log(hv_fug_fp_set[channel].channel_vdc_out)/log(2))+1;
1493  sprintf(err, "hv_fug_set, module %d, channel %d", hv_fug_fp_set[channel].module_vdc_out, ch);
1494  return fp_error_msg(info, err, str);
1495  }
1496  }
1497  }
1498 
1499  // calculate VDC set value
1500  val = (int)(fabs(value)/hv_fug_fp_set[channel].max_volt*FP_IO_RESOL*FP_AO_NORM);
1501  // construct command, 16-bit read with status
1502  sprintf(str, ">%02X!I%04X%04X??\r", hv_fug_fp_set[channel].module_vdc_out,
1503  hv_fug_fp_set[channel].channel_vdc_out,
1504  val);
1505 
1506  BD_PUTS(str);
1507  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1508 
1509  // All the different checks to see if data are OK
1510  if ((str[0]!='A') || (strlen(str)!=8)) { // return value total garbage
1511  ch = (int)(log(hv_fug_fp_set[channel].channel_vdc_out)/log(2))+1;
1512  sprintf(err, "hv_fug_set, module %d, channel %d", hv_fug_fp_set[channel].module_vdc_out, ch);
1513  return fp_error_msg(info, err, str);
1514  }
1515 
1516  sub_str(strlen(str)-3, strlen(str)-1, str, substr, sizeof(str), sizeof(substr));
1517  sub_str(1, strlen(str)-3, str, dat, sizeof(str), sizeof(dat));
1518  if (!chksumchk(dat, substr)) { // checksum error
1519  ch = (int)(log(hv_fug_fp_set[channel].channel_vdc_out)/log(2))+1;
1520  if (info->errorcount < HV_FUG_MAX_ERROR) {
1521  cm_msg(MERROR, "hv_fug_set", "Checksum Error Response, Module %d, Channel %d", hv_fug_fp_set[channel].module_vdc_out, ch);
1522  info->errorcount++;
1523  }
1524  return FE_ERR_HW;
1525  }
1526  return FE_SUCCESS;
1527 }
1528 
1529 /*----------------------------------------------------------------------------*/
1539 INT hv_fug_get(HV_FUG_INFO *info, INT channel, float *pvalue)
1540 {
1541  int status, value, ch;
1542  char str[512], err[512], dat[512], substr[5];
1543  float sign;
1544  DWORD nowtime, difftime;
1545 
1546  sign = 1.0f;
1547 
1548  if (info->startup_error) {
1549  ss_sleep(10); // to keep CPU load low when Run active
1550  return FE_SUCCESS;
1551  }
1552 
1553  // error limiter handling
1554  nowtime = ss_time();
1555  difftime = nowtime - info->lasterrtime;
1556  if ( difftime > HV_FUG_DELTA_TIME_ERROR ) {
1557  info->errorcount = 0;
1558  info->lasterrtime = nowtime;
1559  }
1560 
1561  if (info->reconnection_failures > 5) {
1562  *pvalue = (float) HV_FUG_READ_ERROR;
1563  if (info->reconnection_failures == 6) {
1564  cm_msg(MERROR, "hv_fug_get", "too many reconnection failures, bailing out :-(");
1565  info->reconnection_failures++;
1566  }
1567  return FE_SUCCESS;
1568  }
1569 
1570  if (info->hv_settings.scw_in_use) { // slowcontrol watchdog in use
1571  // feed slowcontrol watchdog
1572  info->scw.last_updated = ss_time();
1573  lem_scw_update(&info->scw);
1574  }
1575 
1576  // if disconnected, try to reconnect after a timeout of a timeout
1577  if (!info->bd_connected) {
1578  if (ss_time()-info->last_reconnect > HV_FUG_RECONNECTION_TIMEOUT) { // timeout expired
1579  if (info->hv_settings.detailed_msg)
1580  cm_msg(MINFO, "hv_fug_get", "HV FUG: reconnection trial ...");
1581  status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
1582  if (status != FE_SUCCESS) {
1583  info->reconnection_failures++;
1584  *pvalue = (float) HV_FUG_READ_ERROR;
1585  if (info->hv_settings.detailed_msg)
1586  cm_msg(MINFO, "hv_fug_get", "HV FUG: reconnection attempted failed");
1587  ss_sleep(3000);
1588  return FE_ERR_HW;
1589  } else {
1590  info->bd_connected = 1; // bus driver is connected again
1591  info->last_reconnect = ss_time();
1592  info->reconnection_failures = 0;
1593  info->first_bd_error = 1;
1594  if (info->hv_settings.detailed_msg)
1595  cm_msg(MINFO, "hv_fug_get", "HV FUG: successfully reconnected");
1596  }
1597  } else { // timeout still running
1598  *pvalue = info->last_valid_hv[channel];
1599  return FE_SUCCESS;
1600  }
1601  }
1602 
1603  if (hv_fug_fp_set[channel].hv_switchable) {
1604  // read relais state in order to get the sign
1605  sprintf(str, ">%02X!G%04X??\r", hv_fug_fp_set[channel].module_relais_in,
1606  hv_fug_fp_set[channel].channel_relais_in);
1607  BD_PUTS(str);
1608  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1609  if (strstr(str, "FFFF"))
1610  sign = 1.0f;
1611  else
1612  sign = -1.0f;
1613  }
1614 
1615  // construct command, 16-bit read with status
1616  sprintf(str, ">%02X!G%04X??\r", hv_fug_fp_set[channel].module_vdc_in,
1617  hv_fug_fp_set[channel].channel_vdc_in);
1618 
1619  BD_PUTS(str);
1620  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1621  // All the different checks to see if data are OK
1622  if ((str[0]!='A') || (strlen(str)!=12)) { // return value total garbage
1623 
1624  info->readback_failure++;
1625 
1627  info->readback_failure = 0;
1628  // try to disconnect and reconnect the bus driver
1629  if ((ss_time()-info->last_reconnect > HV_FUG_RECONNECTION_TIMEOUT) && info->bd_connected) {
1630  info->bd(CMD_EXIT, info->bd_info); // disconnect bus driver
1631  if (info->hv_settings.detailed_msg)
1632  cm_msg(MINFO, "hv_fug_get", "HV FUG: try to disconnect and reconnect the bus driver");
1633  info->last_reconnect = ss_time();
1634  info->bd_connected = 0;
1635  if (info->hv_settings.ets_in_use)
1637  }
1638  }
1639 
1640  ch = (int)(log(hv_fug_fp_set[channel].channel_vdc_in)/log(2))+1;
1641  sprintf(err, "hv_fug_get, module %d, channel %d",
1642  hv_fug_fp_set[channel].module_vdc_in, ch);
1643  return fp_error_msg(info, err, str);
1644  }
1645  sub_str(strlen(str)-3, strlen(str)-1, str, substr, sizeof(str), sizeof(substr));
1646  sub_str(1, strlen(str)-3, str, dat, sizeof(str), sizeof(dat));
1647  if (!chksumchk(dat, substr)) { // checksum error
1648  ch = (int)(log(hv_fug_fp_set[channel].channel_vdc_in)/log(2))+1;
1649  if (info->errorcount < HV_FUG_MAX_ERROR) {
1650  cm_msg(MERROR, "hv_fug_get", "Checksum Error Read, Module %d, Channel %d",
1651  hv_fug_fp_set[channel].module_vdc_in, ch);
1652  info->errorcount++;
1653  }
1654  return FE_ERR_HW;
1655  }
1656  // decode data
1657  sub_str(5, 9, str, substr, sizeof(str), sizeof(substr));
1658  sscanf(substr, "%04X", &value);
1659  *pvalue = sign*(float)value/(float)FP_IO_RESOL*FP_AI_NORM*hv_fug_fp_set[channel].max_volt;
1660 
1661  info->last_valid_hv[channel] = *pvalue; // keep last valid measured HV
1662  info->last_reconnect = 0;
1663  info->readback_failure = 0; // no readback error occured
1664 
1665  return FE_SUCCESS;
1666 }
1667 
1668 /*----------------------------------------------------------------------------*/
1678 INT hv_fug_get_label(INT channel, char *name)
1679 {
1680  sprintf(name, "FUG%%%s", hv_fug_fp_set[channel].name);
1681  return FE_SUCCESS;
1682 }
1683 
1684 /*----------------------------------------------------------------------------*/
1694 INT hv_fug_get_current(HV_FUG_INFO *info, INT channel, float *pvalue)
1695 {
1696  int status, value, ch;
1697  char str[512], err[512], dat[512], substr[5];
1698  DWORD nowtime, difftime;
1699 
1700  if (info->startup_error) return FE_SUCCESS;
1701 
1702  // error limiter handling
1703  nowtime = ss_time();
1704  difftime = nowtime - info->lasterrtime;
1705  if ( difftime > HV_FUG_DELTA_TIME_ERROR ) {
1706  info->errorcount = 0;
1707  info->lasterrtime = nowtime;
1708  }
1709 
1710  // bus driver not connect at the moment
1711  if (!info->bd_connected) {
1712  *pvalue = info->last_valid_current[channel];
1713  return FE_SUCCESS;
1714  }
1715 
1716  // construct command, 16-bit read with status
1717  sprintf(str, ">%02X!G%04X??\r", hv_fug_fp_set[channel].module_cdc_in,
1718  hv_fug_fp_set[channel].channel_cdc_in);
1719 
1720  BD_PUTS(str);
1721  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1722  // All the different checks to see if data are OK
1723  if ((str[0]!='A') || (strlen(str)!=12)) { // return value total garbage
1724  ch = (int)(log(hv_fug_fp_set[channel].channel_cdc_in)/log(2))+1;
1725  sprintf(err, "hv_fug_get_current, module %d, channel %d", hv_fug_fp_set[channel].module_cdc_in, ch);
1726  return fp_error_msg(info, err, str);
1727  }
1728  sub_str(strlen(str)-3, strlen(str)-1, str, substr, sizeof(str), sizeof(substr));
1729  sub_str(1, strlen(str)-3, str, dat, sizeof(str), sizeof(dat));
1730  if (!chksumchk(dat, substr)) { // checksum error
1731  ch = (int)(log(hv_fug_fp_set[channel].channel_cdc_in)/log(2))+1;
1732  if (info->errorcount < HV_FUG_MAX_ERROR) {
1733  cm_msg(MERROR, "hv_fug_get_current", "Checksum Error Read, Module %d, Channel %d", hv_fug_fp_set[channel].module_cdc_in, ch);
1734  info->errorcount++;
1735  }
1736  return FE_ERR_HW;
1737  }
1738  // decode data
1739  sub_str(5, 9, str, substr, sizeof(str), sizeof(substr));
1740  sscanf(substr, "%04X", &value);
1741  *pvalue = (float)value/(float)FP_IO_RESOL*FP_AI_NORM*hv_fug_fp_set[channel].max_curr;
1742 
1743  info->last_valid_current[channel] = *pvalue; // keep last valid measured current
1744 
1745  return FE_SUCCESS;
1746 }
1747 
1748 /*----------------------------------------------------------------------------*/
1758 INT hv_fug_set_current_limit(HV_FUG_INFO *info, INT channel, float limit)
1759 {
1760  int status, ch;
1761  char str[512], err[512];
1762 
1763  if (info->startup_error) return FE_SUCCESS;
1764 
1765  // bus driver not connect at the moment
1766  if (!info->bd_connected) {
1767  cm_msg(MERROR, "hv_fug_set_current_limit",
1768  "set current limit cannot be executed at the moment, since the bus driver is not available!");
1769  return FE_SUCCESS;
1770  }
1771 
1772  // construct command
1773  sprintf(str, ">%02X!I%04X%04X??\r", hv_fug_fp_set[channel].module_cdc_out,
1774  hv_fug_fp_set[channel].channel_cdc_out,
1775  (int)(limit/hv_fug_fp_set[channel].max_curr*FP_IO_RESOL*FP_AO_NORM));
1776 
1777  BD_PUTS(str);
1778  status = BD_GETS(str, sizeof(str), "\r", HV_FUG_TIME_OUT);
1779  if (str[0]!='A') {
1780  ch = (int)(log(hv_fug_fp_set[channel].channel_cdc_in)/log(2))+1;
1781  sprintf(err, "hv_fug_set_current_limit, module %X, channel %X", hv_fug_fp_set[channel].module_cdc_out, ch);
1782  return fp_error_msg(info, err, str);
1783  }
1784 
1785  return FE_SUCCESS;
1786 }
1787 
1788 /*---- device driver entry point -----------------------------------*/
1789 
1790 INT hv_fug(INT cmd, ...)
1791 {
1792 va_list argptr;
1793 HNDLE hKey;
1794 INT channel, status;
1795 float value, *pvalue;
1796 void *info, *bd;
1797 char *name;
1798 DWORD flags;
1799 
1800  va_start(argptr, cmd);
1801  status = FE_SUCCESS;
1802 
1803  switch (cmd) {
1804  case CMD_INIT:
1805  hKey = va_arg(argptr, HNDLE);
1806  info = va_arg(argptr, void *);
1807  channel = va_arg(argptr, INT);
1808  flags = va_arg(argptr, DWORD);
1809  bd = va_arg(argptr, void *);
1810  status = hv_fug_init(hKey, info, channel, bd);
1811  break;
1812 
1813  case CMD_EXIT:
1814  info = va_arg(argptr, void *);
1815  status = hv_fug_exit(info);
1816  break;
1817 
1818  case CMD_SET:
1819  info = va_arg(argptr, void *);
1820  channel = va_arg(argptr, INT);
1821  value = (float) va_arg(argptr, double);
1822  status = hv_fug_set(info, channel, value);
1823  break;
1824 
1825  case CMD_GET:
1826  info = va_arg(argptr, void *);
1827  channel = va_arg(argptr, INT);
1828  pvalue = va_arg(argptr, float*);
1829  status = hv_fug_get(info, channel, pvalue);
1830  break;
1831 
1832  case CMD_GET_LABEL:
1833  info = va_arg(argptr, void *);
1834  channel = va_arg(argptr, INT);
1835  name = va_arg(argptr, char *);
1836  status = hv_fug_get_label(channel, name);
1837  break;
1838 
1839  case CMD_GET_CURRENT:
1840  info = va_arg(argptr, void *);
1841  channel = va_arg(argptr, INT);
1842  pvalue = va_arg(argptr, float*);
1843  status = hv_fug_get_current(info, channel, pvalue);
1844  break;
1845 
1846  case CMD_SET_CURRENT_LIMIT:
1847  info = va_arg(argptr, void *);
1848  channel = va_arg(argptr, INT);
1849  value = (float) va_arg(argptr, double);
1850  status = hv_fug_set_current_limit(info, channel, value);
1851  break;
1852 
1853  // this are known commands of the class driver but not implmented yet or not needed
1854  case CMD_SET_TRIP_TIME:
1855  case CMD_SET_RAMPUP:
1856  case CMD_SET_RAMPDOWN:
1857  case CMD_SET_VOLTAGE_LIMIT:
1858  case CMD_SET_LABEL:
1859  case CMD_GET_DEMAND:
1860  case CMD_GET_THRESHOLD:
1861  case CMD_GET_THRESHOLD_CURRENT:
1862  case CMD_GET_THRESHOLD_ZERO:
1863  case CMD_GET_CURRENT_LIMIT:
1864  case CMD_GET_TRIP_TIME:
1865  case CMD_GET_RAMPUP:
1866  case CMD_GET_RAMPDOWN:
1867  case CMD_STOP:
1868  break;
1869 
1870  default:
1871  break;
1872  } // end case
1873 
1874  va_end(argptr);
1875 
1876  return status;
1877 }
1878 
1879 //----------------------------------------------------------------------------------
static INT fp_write_defaults(HNDLE hDB, HV_FUG_INFO *info)
Definition: hv_fug.c:1173
int chk_attrib_rly(HV_FUG_INFO *info, int module, char *line)
Definition: hv_fug.c:759
INT startup_error
startup error tag
Definition: hv_fug.c:426
char * filter_sub_str(char *str, char *start, char *stop, char *result)
Definition: hv_fug.c:631
INT hv_fug(INT cmd,...)
Definition: hv_fug.c:1790
int num_channels
number of channels in the DD
Definition: hv_fug.c:418
int module_cdc_in
FP module address for current measured.
Definition: hv_fug.c:447
DWORD last_reconnect
timer for bus driver reconnect error handling
Definition: hv_fug.c:432
int module_vdc_out
FP module address for HV demand.
Definition: hv_fug.c:441
float ramping_speed_up
ramping speed up (kV/s)
Definition: hv_fug.c:451
HNDLE hDDkey
ODB key to the device driver info.
Definition: hv_fug.c:423
static INT fp_power_up_clear(HNDLE hDB, HV_FUG_INFO *info)
Definition: hv_fug.c:950
INFO info
Definition: vme_fe.c:206
#define FP_AI_110_RANGE
0 - 10.4 V
Definition: hv_fug.c:152
#define FP_ERR_PUCLR_EXP
Definition: hv_fug.c:166
HNDLE hDB
main handle to the ODB
Definition: hv_fug.c:421
#define HV_FUG_SETTINGS_INTERNAL_STR
Definition: hv_fug.c:225
#define HV_FUG_READ_ERROR
return value in case a read back error occured
Definition: hv_fug.c:201
#define HV_FUG_SETTINGS_PROPERTIES_STR
Definition: hv_fug.c:386
static HV_FUG_FP hv_fug_fp_set[12]
Definition: hv_fug.c:462
char map_fp_fug_output[12][64]
mapping field point&lt;-&gt;FUG of the output channels
Definition: hv_fug.c:217
#define HV_FUG_TIME_OUT
time out for read rs232 communication in (ms).
Definition: hv_fug.c:190
float max_volt
maximal high voltage for this FUG device (kV)
Definition: hv_fug.c:449
#define FP_RLY_SETTING
default reply
Definition: hv_fug.c:155
LEM_SC_WATCHDOG scw
slowcontrol watchdog info structure
Definition: hv_fug.c:417
#define FP_AO_210_RANGE
0 - 10.2 V
Definition: hv_fug.c:154
#define FP_AO_NORM
Max FUG prog / Max AO.
Definition: hv_fug.c:157
float ramping_speed_down
ramping speed down (kV/s)
Definition: hv_fug.c:452
#define HV_FUG_DELTA_TIME_ERROR
reset error counter after HV_FUG_DELTA_TIME_ERROR seconds
Definition: hv_fug.c:194
INT hv_fug_get(HV_FUG_INFO *info, INT channel, float *pvalue)
Definition: hv_fug.c:1539
INT hv_fug_get_current(HV_FUG_INFO *info, INT channel, float *pvalue)
Definition: hv_fug.c:1694
void * bd_info
private info of bus driver
Definition: hv_fug.c:420
#define HV_FUG_SETTINGS_OUT_STR
Definition: hv_fug.c:295
#define HV_FUG_SETTINGS_ODB_OFFSET_STR
Definition: hv_fug.c:235
void err_bad_channels(char *line, int module, HV_FUG_INFO *info)
Definition: hv_fug.c:788
int channel_cdc_in
FP module channel for current measured.
Definition: hv_fug.c:448
void mid_str(char *start, char *stop, char *line, char *result)
Definition: hv_fug.c:582
float last_valid_hv[25]
last valid measured hv
Definition: hv_fug.c:424
char fp_io_modules[128]
list of the field point modules
Definition: hv_fug.c:215
#define HV_FUG_SCW_STR
defines the slowcontrol default watchdog info structure
Definition: hv_fug.c:403
static INT fp_check_modules(HNDLE hDB, HV_FUG_INFO *info)
Definition: hv_fug.c:984
BOOL hv_switchable
flag: FUG device for which polarity is remote switchable
Definition: hv_fug.c:455
INT scw_in_use
flag indicating if the slowcontrol watchdog shall be used
Definition: hv_fug.c:212
int ets_logout(void *info, int wait, int detailed_msg)
Definition: ets_logout.c:113
#define FP_IO_NUM_CH
channels per module
Definition: hv_fug.c:151
HNDLE hKey
Definition: write_summary.c:97
INT readback_failure
counts the number of readback failures
Definition: hv_fug.c:431
int bd_connected
flag showing if the bus driver is connected
Definition: hv_fug.c:429
char line[MAXLINE]
Definition: write_summary.c:96
INT ets_in_use
flag indicating if the rs232 terminal server is in use
Definition: hv_fug.c:211
#define HV_FUG_MAX_READBACK_FAILURE
maximum number of readback failures before a reconnect will take place
Definition: hv_fug.c:197
int no_fp_modules
number of field point modules
Definition: hv_fug.c:214
static INT fp_check_attrib_settings(HNDLE hDB, HV_FUG_INFO *info)
Definition: hv_fug.c:1084
int chksumchk(char *line, char *chksum)
Definition: hv_fug.c:654
INT hv_fug_set_current_limit(HV_FUG_INFO *info, INT channel, float limit)
Definition: hv_fug.c:1758
HNDLE hDB
Definition: write_summary.c:97
float last_valid_current[25]
last valid measured current
Definition: hv_fug.c:425
void sub_str(int start, int stop, char *line, char *result, int size_line, int size_result)
Definition: hv_fug.c:604
#define HV_FUG_RECONNECTION_TIMEOUT
timeout in (sec) for before trying to reconnect again (after a communication breakdown) ...
Definition: hv_fug.c:199
float init_curr
initial current limit (mA)
Definition: hv_fug.c:454
char name[80]
name of the FUG device
Definition: hv_fug.c:440
#define FP_IO_RESOL
resolution of the i/o commands 2^16
Definition: hv_fug.c:156
HNDLE hkey
ODB equipment key.
Definition: hv_fug.c:422
int channel_relais_in
FP relay module channel for the measured polarity.
Definition: hv_fug.c:459
int channel_relais_out
FP relay module channel for the demand polarity.
Definition: hv_fug.c:457
#define HV_FUG_SETTINGS_IN_STR
Definition: hv_fug.c:350
char fug_properties[12][64]
property list of the FUG HV devices
Definition: hv_fug.c:218
int module_relais_in
FP relay module address for the measured polarity.
Definition: hv_fug.c:458
float init_volt
initial HV demand (kV)
Definition: hv_fug.c:453
INT hv_fug_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
Definition: hv_fug.c:1271
#define HV_FUG_ETS_LOGOUT_SLEEP
sleep time (us) between the telnet commands of the ets_logout
Definition: hv_fug.c:204
INT errorcount
error limiter
Definition: hv_fug.c:427
#define FP_AI_NORM
Max AI / Max FUG prog.
Definition: hv_fug.c:158
int module_cdc_out
FP module address for current demand.
Definition: hv_fug.c:443
int chk_attrib_in(HV_FUG_INFO *info, int module, char *line)
Definition: hv_fug.c:684
INT hv_fug_set(HV_FUG_INFO *info, INT channel, float value)
Definition: hv_fug.c:1443
int reconnection_failures
how often reconnection failed
Definition: hv_fug.c:433
int channel_vdc_in
FP module channel for HV measured.
Definition: hv_fug.c:446
#define HV_FUG_SETTINGS_MODULE_STR
Definition: hv_fug.c:251
char map_fp_fug_input[12][64]
mapping field point&lt;-&gt;FUG of the input channels
Definition: hv_fug.c:216
int odb_offset
channel offset within ODB
Definition: hv_fug.c:213
INT hv_fug_get_label(INT channel, char *name)
Definition: hv_fug.c:1678
HV_FUG_SETTINGS hv_settings
ODB hot-link data for the DD.
Definition: hv_fug.c:416
INT detailed_msg
flag indicating if detailed status/error messages are wanted
Definition: hv_fug.c:210
float max_curr
maximal current for this FUG device (mA)
Definition: hv_fug.c:450
int module_vdc_in
FP module address for HV measured.
Definition: hv_fug.c:445
INT(* bd)(INT cmd,...)
bus driver entry function
Definition: hv_fug.c:419
#define HV_FUG_MAX_ERROR
maximum number of error messages
Definition: hv_fug.c:193
INT fp_error_msg(HV_FUG_INFO *info, char *where, char *error)
Definition: hv_fug.c:484
#define HV_FUG_SETTINGS_NO_STR
Definition: hv_fug.c:243
INT hv_fug_exit(HV_FUG_INFO *info)
Definition: hv_fug.c:1415
int channel_vdc_out
FP module channel for HV demand.
Definition: hv_fug.c:442
#define FP_AI_110_FILTER
60 Hz
Definition: hv_fug.c:153
INT first_bd_error
flag showing if the bus driver error message is already given
Definition: hv_fug.c:430
static INT hv_fug_update_db_settings(HNDLE hDB, HV_FUG_INFO *info, INT channels)
Definition: hv_fug.c:828
int chk_attrib_out(HV_FUG_INFO *info, int module, char *line)
Definition: hv_fug.c:726
stores internal informations within the DD.
Definition: hv_fug.c:209
DWORD lasterrtime
timer for error limiter
Definition: hv_fug.c:428
int channel_cdc_out
FP module channel for current demand.
Definition: hv_fug.c:444
int module_relais_out
FP relay module address for the demand polarity.
Definition: hv_fug.c:456