Low-Energy Muon (LEM) Experiment  0.5.1
lemvac.c
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------
2 
3  Name: lemvac.c
4  Created by: Andreas Suter 2004/08/30
5  Rewritten by: Andreas Suter 2016/01/25 (new Siemens SPS communication modules)
6 
7  Contents: device driver for the lem vacuum SPS control unit
8 
9 ----------------------------------------------------------------------------*/
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <math.h>
17 #include "midas.h"
18 #include "lemvac.h"
19 
20 #define LV_HV_NO_INTERLOCK_FLAG 128
21 #define LV_GAS_INLET_FLAG 128
22 
23 // bits as encoded in the SPS words
24 #define LV_BIT0 0x0100
25 #define LV_BIT1 0x0200
26 #define LV_BIT2 0x0400
27 #define LV_BIT3 0x0800
28 #define LV_BIT4 0x1000
29 #define LV_BIT5 0x2000
30 #define LV_BIT6 0x4000
31 #define LV_BIT7 0x8000
32 #define LV_BIT8 0x0001
33 #define LV_BIT9 0x0002
34 #define LV_BIT10 0x0004
35 #define LV_BIT11 0x0008
36 #define LV_BIT12 0x0010
37 #define LV_BIT13 0x0020
38 #define LV_BIT14 0x0040
39 #define LV_BIT15 0x0080
40 
41 // channels of the SPS input variables
42 #define LV_LIFESIGN 0
43 #define LV_MCGR 1
44 #define LV_MCGT 2
45 #define LV_MCGJ 3
46 #define LV_MCGJ2 4
47 #define LV_TCGR 5
48 #define LV_TCGT 6
49 #define LV_TCGJ 7
50 #define LV_TCGJ2 8
51 #define LV_SCGR 9
52 #define LV_SCGT 10
53 #define LV_SCGJ 11
54 #define LV_SCGJ2 12
55 #define LV_PZGR 13
56 #define LV_MCSTAT1 14
57 #define LV_MCSTAT2 15
58 #define LV_MCSTAT3 16
59 #define LV_TCSTAT1 17
60 #define LV_TCSTAT2 18
61 #define LV_TCSTAT3 19
62 #define LV_SCSTAT1 20
63 #define LV_SCSTAT2 21
64 #define LV_SCSTAT3 22
65 #define LV_PZSTAT1 23
66 #define LV_PZSTAT2 24
67 #define LV_BPVX 25
68 #define LV_BPVY 26
69 
70 // channels of the SPS output variables
71 #define LV_BPVX_ENABLED 0
72 #define LV_BPVX_CMD 1
73 #define LV_BPVY_ENABLED 2
74 #define LV_BPVY_CMD 3
75 #define LV_SC_PUMP_CMD_ENABLED 4
76 #define LV_SC_PUMP_CMD 5
77 #define LV_SC_VENT_CMD_ENABLED 6
78 #define LV_SC_VENT_CMD 7
79 
80 // BPVX/Y commands
81 #define LV_BPV_CMD_IDLE 0.0
82 #define LV_BPV_CMD_TOGGLE 1.0
83 #define LV_BPV_CMD_OPEN 2.0
84 #define LV_BPV_CMD_CLOSE 3.0
85 
86 #define SPS_MAX_BYTES 680
87 #define LEMVAC_TIME_CONST 0
88 #define LEMVAC_TIMEOUT_ERROR 3600
89 
90 // flags needed the more complex commands like start/stop the pump and/or venting the SC
91 #define LEMVAC_SC_PENDING_CMD_IDLE 0
92 #define LEMVAC_SC_PENDING_CMD_STOP 1
93 #define LEMVAC_SC_PENDING_CMD_VENT 2
94 
95 #define VENT_STATE_HV_BIT 0
96 #define VENT_STATE_TEMP_BIT 1
97 #define VENT_STATE_BPVY_BIT 2
98 #define VENT_STATE_PUMP_BIT 3
99 
100 #define VENT_CMD_STOP 0
101 #define VENT_CMD_START 1
102 
103 // ODB indices for the FUG's in the SC region
104 #define FUG_SC_RAL_IDX 11
105 #define FUG_SC_RAR_IDX 12
106 #define FUG_SC_RAT_IDX 13
107 #define FUG_SC_RAB_IDX 14
108 #define FUG_SC_SAMPLE_IDX 15
109 
110 // ODB indices for the sample cryo relevant for venting
111 #define SAMPLE_IN_CF1_IDX 0
112 #define SAMPLE_OUT_SET_POINT_IDX 1
113 #define SAMPLE_OUT_LS_RAMP 7
114 #define SAMPLE_OUT_BH1_FLOW_IDX 8
115 #define SAMPLE_OUT_BH2_FLOW_IDX 10
116 
118 typedef struct {
120 } LEMVAC_INTERN;
121 
123 #define LAMVAC_INTERN_STR "\
124 Detailed Messages = INT : 0\n\
125 "
126 
128 typedef struct {
129 char in_name[LEMVAC_IN_VARS][NAME_LENGTH];
130 char out_name[LEMVAC_OUT_VARS][NAME_LENGTH];
131 } LEMVAC_NAMES;
132 
134 #define LEMVAC_NAMES_STR "\
135 Input Names = STRING[27] : \n\
136 [32] Life Sign\n\
137 [32] MC_GR Pirani\n\
138 [32] MC_GT Pirani\n\
139 [32] MC_GJ Penning\n\
140 [32] MC_GJ2 Penning\n\
141 [32] TC_GR Pirani\n\
142 [32] TC_GT Pirani\n\
143 [32] TC_GJ Penning\n\
144 [32] TC_GJ2 Penning\n\
145 [32] SC_GR Pirani\n\
146 [32] SC_GT Pirani\n\
147 [32] SC_GJ Penning\n\
148 [32] SC_GJ2 Penning\n\
149 [32] PZ_GR Pirani\n\
150 [32] MC Status Word 1\n\
151 [32] MC Status Word 2\n\
152 [32] MC Status Word 3\n\
153 [32] TC Status Word 1\n\
154 [32] TC Status Word 2\n\
155 [32] TC Status Word 3\n\
156 [32] SC Status Word 1\n\
157 [32] SC Status Word 2\n\
158 [32] SC Status Word 3\n\
159 [32] PZ Status Word 1\n\
160 [32] PZ Status Word 2\n\
161 [32] BPVX Status Word\n\
162 [32] BPVY Status Word\n\
163 Output Names = STRING[8] : \n\
164 [32] BPVX enabled\n\
165 [32] BPVX toggle cmd\n\
166 [32] BPVY enabled\n\
167 [32] BPVY toggle cmd\n\
168 [32] SC pump cmd enabled\n\
169 [32] SC pump cmd\n\
170 [32] SC vent enabled\n\
171 [32] SC vent cmd\n\
172 "
173 
175 typedef struct {
178  char lemvac_buffer[SPS_MAX_BYTES];
179  float lemvac_data[LEMVAC_IN_VARS];
180  INT (*bd)(INT cmd, ...);
181  void *bd_info;
182  int bpv_enabled[2];
185  char handshake_cmd[32];
186  int handshake_err_count[4];
187  HNDLE hDB;
188  HNDLE hKey_in;
189  HNDLE hKey_out;
191  DWORD time;
192  DWORD errTime;
197  DWORD last_success;
198 } LEMVAC_INFO;
199 
201 
202 // lemvac_sc_vent_state keeps the current state of the sample chamber. It is
203 // encoded the following way:
204 // XXX0 : HV on (HV's in the sample chamber)
205 // XXX1 : HV off
206 // XX0X : T<90K (CF1 of the sample cryo)
207 // XX1X : T>=90K
208 // X0XX : BPVY open
209 // X1XX : BPVY closed
210 // 0XXX : sample chamber pumping station is off
211 // 1XXX : sample chamber pumping station is on
212 //
213 // this means lemvac_sc_vent_state = 15 (1111 binary) is needed that the sample chamber can be vented.
215 
216 // 0: idle
217 // 1: stop SC pump
218 // 2: vent SC
220 
223 void lemvac_vent_sc(LEMVAC_INFO *info, INT cmd);
224 void lemvac_set_sliding_valve(LEMVAC_INFO *info, INT valve, float value);
225 
226 //------------------------------------------------------------------------
234 {
235  INT state = 0;
236  INT status, i;
237  HNDLE hDB, hKey;
238  INT size;
239  float fval;
240 
241  // get main ODB handle
242  cm_get_experiment_database(&hDB, NULL);
243 
244  // get FUG frontend key
245  status = db_find_key(hDB, 0, "/Equipment/HV/Variables/Demand", &hKey);
246  if (status != DB_SUCCESS) {
247  cm_msg(MERROR, "lemvac_check_sample_hv", "lemvac_check_sample_hv: lemvac_scfe: **ERROR** couldn't get FUG key from the ODB to check the sample HV.");
248  return 1; // like HV on since I do not know
249  }
250 
251  // check if any sample chamber HV demand value is not equal to zero
252  size = sizeof(float);
253  fval = -1.0;
254  for (i=FUG_SC_RAL_IDX; i<=FUG_SC_SAMPLE_IDX; i++) {
255  db_get_data_index(hDB, hKey, &fval, &size, i, TID_FLOAT);
256  if (fval != 0.0) {
257  state = 1;
258  break;
259  }
260  }
261 
262  return state;
263 }
264 
265 //--------------------------------------------------------------------
272 {
273  INT state = 0;
274  INT status;
275  HNDLE hDB, hKey;
276  INT size;
277  float fval;
278 
279  // get main ODB handle
280  cm_get_experiment_database(&hDB, NULL);
281 
282  // get SampleCryo frontend key
283  status = db_find_key(hDB, 0, "/Equipment/SampleCryo/Variables/Input", &hKey);
284  if (status != DB_SUCCESS) {
285  cm_msg(MERROR, "lemvac_check_sample_temp", "lemvac_check_sample_temp: lemvac_scfe: **ERROR** couldn't get SampleCryo key from the ODB to check the sample CF1 temp.");
286  return 1; // like T<90K since I do not know
287  }
288 
289  size = sizeof(float);
290  fval = 0.0;
291  db_get_data_index(hDB, hKey, &fval, &size, SAMPLE_IN_CF1_IDX, TID_FLOAT);
292  if (fval < 90.0)
293  state = 1;
294 
295  return state;
296 }
297 
298 //----------------------------------------------------------------------------
305 {
306  HNDLE hKey;
307  INT size, i;
308  float fval;
309 
310  // get the handle
311  db_find_key(info->hDB, 0, "/Equipment/HV/Variables/Demand", &hKey);
312 
313  cm_msg(MINFO, "lemvac_shutdown_sc_hv", "lemvac_shutdown_sc_hv: shut down sample chamber HVs.");
314 
315  // shutdown the SC HVs
316  size = sizeof(float);
317  fval = 0.0;
318  for (i=FUG_SC_RAL_IDX; i<=FUG_SC_SAMPLE_IDX; i++) {
319  db_set_data_index(info->hDB, hKey, &fval, size, i, TID_FLOAT);
320  }
321 }
322 
323 //----------------------------------------------------------------------------
331 {
332  HNDLE hKey;
333  INT size;
334  float fval;
335 
336  // get the handle to the SampleCryo Output variable
337  db_find_key(info->hDB, 0, "/Equipment/SampleCryo/Variables/Output", &hKey);
338 
339  cm_msg(MINFO, "lemvac_forced_warmup", "lemvac_forced_warmup: initiate forced warmup of the sample cryo.");
340 
341  // set LakeShore 340 ramping to zero
342  size = sizeof(float);
343  fval = 0.0;
344  db_set_data_index(info->hDB, hKey, &fval, size, SAMPLE_OUT_LS_RAMP, TID_FLOAT);
345  ss_sleep(2000); // wait 2 sec before proceeding
346 
347  // set the set-point to 300K
348  size = sizeof(float);
349  fval = 300.0;
350  db_set_data_index(info->hDB, hKey, &fval, size, SAMPLE_OUT_SET_POINT_IDX, TID_FLOAT);
351 
352  // set BH1, BH2 flow to 0
353  fval = 0.0;
354  db_set_data_index(info->hDB, hKey, &fval, size, SAMPLE_OUT_BH1_FLOW_IDX, TID_FLOAT);
355  fval = 0.0;
356  db_set_data_index(info->hDB, hKey, &fval, size, SAMPLE_OUT_BH2_FLOW_IDX, TID_FLOAT);
357 }
358 
359 //----------------------------------------------------------------------------
366 {
367  ss_sleep(200); //as currently needed since SPS is too slow
368  cm_yield(0); //as
369 
371  if ((lemvac_sc_vent_state == 7) ||
372  (lemvac_sc_vent_state == 15)) { // i.e. SC HVs down, T>=90K, and BPVY closed
373  lemvac_stop_sc_pump(info);
375  }
377  if (lemvac_sc_vent_state == 15) { // i.e. SC HVs down, T>=90K, BPVY closed, and SC pump off
380  } else if (lemvac_sc_vent_state == 7) { // i.e. i.e. SC HVs down, T>=90K, BPVY closed, but SC pump still on
381  lemvac_stop_sc_pump(info);
382  }
383  }
384 }
385 
386 //----------------------------------------------------------------------------
394 short spsToNumber(unsigned char *buffer)
395 {
396  int val = 0;
397 
398  if (buffer[0] & 0x80)
399  val = (buffer[0] &0x7f) << 8;
400  else
401  val = buffer[0] << 8;
402 
403  if (buffer[1] & 0x80) // sign bit set
404  val += (buffer[1] &0x7f) + 128;
405  else
406  val += buffer[1];
407 
408  return val;
409 }
410 
411 //----------------------------------------------------------------------------
419 int spsToWord(unsigned char *buffer)
420 {
421  short val = buffer[0];
422  val = val << 8;
423  val += buffer[1];
424  return val;
425 }
426 
427 //----------------------------------------------------------------------------
437 double penning_ikr070(int analog)
438 {
439  return exp(log(10.f)*(-11.f+0.8571*analog/100.f));
440 }
441 
442 //----------------------------------------------------------------------------
451 double pirani_tpr018(int analog)
452 {
453  double volt[30] = {0.0, 0.1, 0.201, 0.4523, 0.7035, 0.9146, 1.1055,
454  2.0653, 2.5377, 2.9045, 3.2111, 3.4623, 4.1106,
455  4.6583, 5.0251, 5.3618, 5.5879, 6.1457, 6.6181,
456  7.0553, 7.3970, 7.6935, 8.6683, 9.2462, 9.4975,
457  9.6080, 9.7085, 9.8543, 9.9497, 10.0};
458 
459  double p[30] = {1.0e-4, 1.0e-3, 0.002, 0.004, 0.006, 0.008, 0.01,
460  0.02, 0.04, 0.06, 0.08, 0.1, 0.2, 0.4, 0.6, 0.8,
461  1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 20.0, 40.0, 60.0,
462  80.0, 100.0, 200.0, 400.0, 1000.0};
463 
464  if (analog > 32512) { // underrange
465  return 1.0e-6;
466  }
467 
468  double u = analog/100.f;
469  double pressure;
470  int i;
471 
472  // find closest voltage
473  for (i=0; i<30; i++) {
474  if (volt[i] > u)
475  break;
476  }
477 
478  if (i==0)
479  pressure = 1.0e-4;
480  else
481  pressure = p[i-1]+(p[i]-p[i-1])*(u-volt[i-1])/(volt[i]-volt[i-1]);
482 
483  return pressure;
484 }
485 
486 //----------------------------------------------------------------------------
496 BOOL lemvac_decode_data(LEMVAC_INFO *info, const char *buffer)
497 {
498  if ((buffer[4] != 65) || (buffer[5] != 66)) // check if buffer has the right 'AB' signature
499  return FALSE;
500 
501  info->lemvac_data[LV_LIFESIGN] = spsToNumber((unsigned char*)&buffer[10]); // lifesign counter
502  info->lemvac_data[LV_MCGR] = pirani_tpr018(spsToNumber((unsigned char*)&buffer[368])); // MC_GR Pirani
503  info->lemvac_data[LV_MCGT] = pirani_tpr018(spsToNumber((unsigned char*)&buffer[370])); // MC_GT Pirani
504  info->lemvac_data[LV_MCGJ] = penning_ikr070(spsToNumber((unsigned char*)&buffer[372])); // MC_GJ Penning
505  info->lemvac_data[LV_MCGJ2] = penning_ikr070(spsToNumber((unsigned char*)&buffer[374])); // MC_GJ2 Penning
506  info->lemvac_data[LV_TCGR] = pirani_tpr018(spsToNumber((unsigned char*)&buffer[388])); // TC_GR Pirani
507  info->lemvac_data[LV_TCGT] = pirani_tpr018(spsToNumber((unsigned char*)&buffer[390])); // TC_GT Pirani
508  info->lemvac_data[LV_TCGJ] = penning_ikr070(spsToNumber((unsigned char*)&buffer[392])); // TC_GJ Penning
509  info->lemvac_data[LV_TCGJ2] = penning_ikr070(spsToNumber((unsigned char*)&buffer[394])); // TC_GJ2 Penning
510  info->lemvac_data[LV_SCGR] = pirani_tpr018(spsToNumber((unsigned char*)&buffer[408])); // SC_GR Pirani
511  info->lemvac_data[LV_SCGT] = pirani_tpr018(spsToNumber((unsigned char*)&buffer[410])); // SC_GT Pirani
512  info->lemvac_data[LV_SCGJ] = penning_ikr070(spsToNumber((unsigned char*)&buffer[412])); // SC_GJ Penning
513  info->lemvac_data[LV_SCGJ2] = penning_ikr070(spsToNumber((unsigned char*)&buffer[414])); // SC_GJ2 Penning
514  info->lemvac_data[LV_PZGR] = pirani_tpr018(spsToNumber((unsigned char*)&buffer[508])); // PZ_GR Pirani
515  info->lemvac_data[LV_MCSTAT1] = spsToWord((unsigned char*)&buffer[360]); // MC Status Word 1
516  info->lemvac_data[LV_MCSTAT2] = spsToWord((unsigned char*)&buffer[362]); // MC Status Word 2
517  info->lemvac_data[LV_MCSTAT3] = spsToWord((unsigned char*)&buffer[364]); // MC Status Word 3
518  info->lemvac_data[LV_TCSTAT1] = spsToWord((unsigned char*)&buffer[380]); // TC Status Word 1
519  info->lemvac_data[LV_TCSTAT2] = spsToWord((unsigned char*)&buffer[382]); // TC Status Word 2
520  info->lemvac_data[LV_TCSTAT3] = spsToWord((unsigned char*)&buffer[384]); // TC Status Word 3
521  info->lemvac_data[LV_SCSTAT1] = spsToWord((unsigned char*)&buffer[400]); // SC Status Word 1
522  info->lemvac_data[LV_SCSTAT2] = spsToWord((unsigned char*)&buffer[402]); // SC Status Word 2
523  info->lemvac_data[LV_SCSTAT3] = spsToWord((unsigned char*)&buffer[404]); // SC Status Word 3
524  info->lemvac_data[LV_PZSTAT1] = spsToWord((unsigned char*)&buffer[500]); // PZ Status Word 1
525  info->lemvac_data[LV_PZSTAT2] = spsToWord((unsigned char*)&buffer[502]); // PZ Status Word 2
526  info->lemvac_data[LV_BPVX] = spsToWord((unsigned char*)&buffer[600]); // BPVX Status Word
527  info->lemvac_data[LV_BPVY] = spsToWord((unsigned char*)&buffer[610]); // BPVY Status Word
528 
529  return TRUE;
530 }
531 
532 //----------------------------------------------------------------------------
542 {
543  int status, cmd, cmd_tag;
544  // the handshake string has the following structure d0;d1
545  // where d0 is the command : 1 = BPVX toggle, 3 = BPVY toggle, 5 = SC pump, 7 = SC vent
546  // and d1 ist the command tag: 1,2,3 for BPVX/Y; 0 (stop), or 1 (start) for SC pump/vent
547 
548  // tokenize handshake command
549  status = sscanf(info->handshake_cmd, "%d;%d", &cmd, &cmd_tag);
550  if (status != 2) {
551  cm_msg(MINFO, "lemvac_deal_with_handshake", "lemvac_deal_with_handshake: **ERROR** when tokenize handshake command ('%s').", info->handshake_cmd);
552  return;
553  }
554 
555  // check cmd
556  switch (cmd) {
557  case 1: // BPVX
558  if (cmd_tag != 0) {
559  if (((int)info->lemvac_data[LV_BPVX] & LV_BIT3) ||
560  ((int)info->lemvac_data[LV_BPVX] & LV_BIT4)) { // BPVX open or closed present -> cmd OK hence reset
561  info->handshake_err_count[0] = 0;
562  info->lemvac_buffer[604] = (char)0;
563  lemvac_write_cmd(info);
564  } else {
565  info->handshake_err_count[0]++;
566  if ((info->handshake_err_count[0] + 5) % 10 == 0)
567  cm_msg(MINFO, "lemvac_deal_with_handshake", "lemvac_deal_with_handshake: **WARNING** toggle BPVX failed.");
568  return;
569  }
570  }
571  break;
572  case 3: // BPVY
573  if (cmd_tag != 0) {
574  if (((int)info->lemvac_data[LV_BPVY] & LV_BIT3) ||
575  ((int)info->lemvac_data[LV_BPVY] & LV_BIT4)) { // BPVY open or closed present -> cmd OK hence reset
576  info->handshake_err_count[1] = 0;
577  info->lemvac_buffer[614] = (char)0;
578  lemvac_write_cmd(info);
579  } else {
580  info->handshake_err_count[1]++;
581  if ((info->handshake_err_count[1] + 5) % 10 == 0)
582  cm_msg(MINFO, "lemvac_deal_with_handshake", "lemvac_deal_with_handshake: **WARNING** toggle BPVY failed.");
583  return;
584  }
585  }
586  break;
587  case 5: // SC pump start/stop cmd
588  if ((cmd_tag == 1) &&
589  (((int)info->lemvac_data[LV_SCSTAT1] & LV_BIT0) ||
590  ((int)info->lemvac_data[LV_SCSTAT1] & LV_BIT2) ||
591  ((int)info->lemvac_data[LV_SCSTAT1] & LV_BIT3))) { // start pump
592  info->handshake_err_count[2] = 0;
593  info->lemvac_buffer[416] = (char)0;
594  lemvac_write_cmd(info);
595  } else if ((cmd_tag == 0) && ((int)info->lemvac_data[LV_SCSTAT1] & LV_BIT1)) { // stop pump
596  info->handshake_err_count[2] = 0;
597  info->lemvac_buffer[416] = (char)0;
598  lemvac_write_cmd(info);
599  } else {
600  info->handshake_err_count[2]++;
601  if ((info->handshake_err_count[2] + 5) % 10 == 0)
602  cm_msg(MINFO, "lemvac_deal_with_handshake", "lemvac_deal_with_handshake: **WARNING** pump cmd failed.");
603  return;
604  }
605  break;
606  case 7: // SC vent start/stop cmd
607  if ((cmd_tag == 1) && ((int)info->lemvac_buffer[416] != 0)) { // vent on
608  info->handshake_err_count[3] = 0;
609  info->lemvac_buffer[416] = (char)0;
610  lemvac_write_cmd(info);
611  } else if ((cmd_tag == 0) && (int)info->lemvac_data[LV_SCSTAT1] & LV_BIT9) { // vent off
612  info->handshake_err_count[3] = 0;
613  info->lemvac_buffer[416] = (char)0;
614  lemvac_write_cmd(info);
615  } else {
616  info->handshake_err_count[3]++;
617  if ((info->handshake_err_count[3] + 5) % 10 == 0)
618  cm_msg(MINFO, "lemvac_deal_with_handshake", "lemvac_deal_with_handshake: **WARNING** pump/vent cmd failed.");
619  return;
620  }
621  break;
622  default:
623  cm_msg(MINFO, "lemvac_deal_with_handshake", "lemvac_deal_with_handshake: **ERROR** you never should have reached this point.");
624  return;
625  break;
626  }
627 
628  // reset handshake_cmd
629  strncpy(info->handshake_cmd, "", sizeof(info->handshake_cmd));
630 }
631 
632 //----------------------------------------------------------------------------
643 {
644  INT status;
645  char data[SPS_MAX_BYTES];
646 
647  float delta = ss_time()-info->time;
648  // check timer, if smaller then time constant do nothing
649  if (delta < LEMVAC_TIME_CONST)
650  return;
651 
652  // communication error report handling
653  delta = ss_time()-info->errTime;
654  if (delta > LEMVAC_TIMEOUT_ERROR) {
655  if ((info->tcpip_open_error != 0) || (info->read_error != 0)) {
656  if (info->intern.detailed_msg) {
657  cm_msg(MINFO, "lemvac_get_all",
658  "lemvac_get_all: No of tcpip open errors = %d, tcpip read errors =%d of %d readings in the last %d secs.",
660  cm_yield(0);
661  }
662  // reset error counters
663  info->tcpip_open_error = 0;
664  info->read_error = 0;
665  info->read_counts = 0;
666  // restart timer
667  info->errTime = ss_time();
668  }
669  }
670 
671  // get data
672  status = info->bd(CMD_READ, info->bd_info, &data[0], sizeof(data), 3000); // read data
673  if (info->intern.detailed_msg) {
674  cm_msg(MDEBUG, "lemvac_get_all", "lemvac_get_all: get data (status=%d)", status);
675  cm_yield(0);
676  }
677  if (status == SPS_MAX_BYTES) {
678  memcpy(info->lemvac_buffer, data, SPS_MAX_BYTES);
679  } else {
680  if (info->intern.detailed_msg) {
681  cm_msg(MINFO, "lemvac_get_all", "lemvac_get_all: get.data.status=%d", status);
682  cm_yield(0);
683  }
684  info->read_counts++;
685  }
686 
687  // check for errors
688  // (error byte set) or (haven't gotten all the data)
689  if (status != SPS_MAX_BYTES) {
690  info->read_error++;
691  return;
692  } else {
693  info->read_counts = 0;
694  if (!lemvac_decode_data(info, data)) {
695  info->read_error++;
696  } else { // only check potential handshake if decoding is ok
697  // check if handshake command is pending
698  if (strlen(info->handshake_cmd) > 0) {
700  }
701  }
702  }
703 
704  info->time = ss_time(); // restart timer
705 
706  // update lemvac_sc_vent_state: check BPVY
707  if (info->lemvac_data[LV_BPVY] == 3072.f) // BPVY closed
708  lemvac_sc_vent_state |= 1 << VENT_STATE_BPVY_BIT; // set BPVY state bit, i.e. BPVY closed
709  else
710  lemvac_sc_vent_state &= ~(1 << VENT_STATE_BPVY_BIT); // clear BPVY state bit, i.e. BPVY is open
711 
712  // update lemvac_sc_vent_state: check SC pump state
713  if (info->lemvac_data[LV_SCSTAT1] == 18827) // SC pump state: pumping
714  lemvac_sc_vent_state &= ~(1 << VENT_STATE_PUMP_BIT); // clear pump state bit, i.e. sample chamber is pumping
715  else
716  lemvac_sc_vent_state |= 1 << VENT_STATE_PUMP_BIT; // set pump state bit, i.e. sample chamber pumping is stopped
717 
718  // update lemvac_sc_vent_state: check sample HV's
719  if (lemvac_check_sample_hv() == 1) // HV on
720  lemvac_sc_vent_state &= ~(1 << VENT_STATE_HV_BIT); // clear HV bit, i.e. HV on
721  else // HV off
722  lemvac_sc_vent_state |= 1 << VENT_STATE_HV_BIT; // set HV bit
723 
724  // update lemvac_sc_vent_state: check sample temperature T<90 or T>=90
725  if (lemvac_check_sample_temp() == 1) // CF1 temp < 90K
726  lemvac_sc_vent_state &= ~(1 << VENT_STATE_TEMP_BIT); // clear sample temperature bit, i.e. T<90K
727  else // CF1 temp >= 90K
728  lemvac_sc_vent_state |= 1 << VENT_STATE_TEMP_BIT; // set sample temperature bit
729 
730  // check for pending commands
732 
733  // ------------------------------------------------------------------------------------
734  // check the HV interlock setting for the various chambers.
735  // The HV interlock fires if the pressure > 1e-6, i.e. if the corresponding pressure
736  // decade bit is NOT set (see DB50, e.g. byte 352).
737  // If a gas inlet action is going on, no alarm is given, since it is assumed that the
738  // user knows what he is doing!
739 
740  // check if MC HV interlock fired and there was not a gas inlet action
741  if (!(info->lemvac_buffer[361] & LV_HV_NO_INTERLOCK_FLAG) &&
742  !(info->lemvac_buffer[363] & LV_GAS_INLET_FLAG)) {
743  al_trigger_alarm( "lemvac_get_all", "MC High Voltage Interlock Activated", "Alarm",
744  "Manual Reset Needed", AT_INTERNAL);
746  }
747 
748  // check if TC HV interlock fired and there was not a gas inlet action
749  if (!(info->lemvac_buffer[381] & LV_HV_NO_INTERLOCK_FLAG) &&
750  !(info->lemvac_buffer[383] & LV_GAS_INLET_FLAG)) {
751  al_trigger_alarm( "lemvac_get_all", "TC High Voltage Interlock Activated", "Alarm",
752  "Manual Reset Needed", AT_INTERNAL);
755  }
756 
757  // check if SC HV interlock fired and there was not a gas inlet action
758  if (!(info->lemvac_buffer[401] & LV_HV_NO_INTERLOCK_FLAG) &&
759  !(info->lemvac_buffer[403] & LV_GAS_INLET_FLAG)) {
760  al_trigger_alarm( "lemvac_get_all", "SC High Voltage Interlock Activated", "Alarm",
761  "Manual Reset Needed", AT_INTERNAL);
763  }
764 
765  // end HV interlock checks
766  // ------------------------------------------------------------------------------------
767 }
768 
769 //----------------------------------------------------------------------------
776 {
777  int status;
778 
779  info->tcpip_open_error = 0;
780 
781  // write stuff
782  status = info->bd(CMD_WRITE, info->bd_info, &info->lemvac_buffer[0], sizeof(info->lemvac_buffer)); // write data
783  if (info->intern.detailed_msg) {
784  cm_msg(MDEBUG, "lemvac_write_cmd", "lemvac_write_cmd: write data (status=%d)", status);
785  cm_yield(0);
786  }
787 }
788 
789 //----------------------------------------------------------------------------
798 void lemvac_set_sliding_valve(LEMVAC_INFO *info, INT valve, float value)
799 {
800  BOOL open;
801  int status, size, odb_idx;
802  int bpv_state, idx;
803  float fval;
804  HNDLE hKey;
805  char cmd[32];
806 
807  if (value == 0.0)
808  return;
809 
810  // get the handle to the output variables
811  status = db_find_key(info->hDB, 0, "/Equipment/LEMVAC/Variables/Output", &hKey);
812  if (status != DB_SUCCESS) {
813  cm_msg(MINFO, "lemvac_set_sliding_valve", "lemvac_set_sliding_valve: couldn't get the output variable key.");
814  return;
815  }
816 
817  // get the BPV state (open or closed) and reset the toggle command
818  if (valve == 1) { // BPVX
819  idx = 600; // lemvac_buffer index
820  } else if (valve == 3) { // BPVY
821  idx = 610; // lemvac_buffer index
822  }
823  bpv_state = spsToWord((unsigned char*)&info->lemvac_buffer[idx]);
824 
825  // check the current BPVX/Y state
826  if ((bpv_state & LV_BIT4) && (bpv_state & LV_BIT2) && !(bpv_state & LV_BIT3)) {
827  open = TRUE;
828  } else {
829  open = FALSE;
830  }
831 
832  // set command back to idle
833  size = sizeof(float);
834  fval = 0.0;
835  if (idx == 600)
836  odb_idx = 1; // ODB index
837  else
838  odb_idx = 3; // ODB index
839  status = db_set_data_index(info->hDB, hKey, &fval, size, odb_idx, TID_FLOAT);
840 
841  // check if the current state and the given command correspond in which case nothing has to be done
842  if ((open == TRUE) && (value == 2.0)) // current state 'open', command 'open', hence nothing to be done
843  return;
844  if ((open == FALSE) && (value == 3.0)) // current state 'closed', command 'closed', hence nothing to be done
845  return;
846 
847  // write the command to the SPS
848  if (open == TRUE) { // currently open, hence close
849  info->lemvac_buffer[idx+4] = (char)2;
850  } else { // currently closed, hence open
851  info->lemvac_buffer[idx+4] = (char)1;
852  }
853  lemvac_write_cmd(info);
854 
855  // set handshake command string
856  sprintf(cmd, "%d;%d", valve, (int)value);
857  strncpy(info->handshake_cmd, cmd, sizeof(info->handshake_cmd));
858 }
859 
860 //----------------------------------------------------------------------------
867 {
868  HNDLE hKey;
869  INT size;
870  float fval;
871  char cmd[32];
872 
873  cm_msg(MDEBUG, "lemvac_start_sc_pump", "lemvac_start_sc_pump: will start SC pump.");
874  cm_yield(0);
875 
876  if ((int)info->lemvac_data[LV_SCSTAT1] & LV_BIT0 ||
877  (int)info->lemvac_data[LV_SCSTAT1] & LV_BIT2 ||
878  (int)info->lemvac_data[LV_SCSTAT1] & LV_BIT3) {
879  cm_msg(MDEBUG, "lemvac_start_sc_pump", "lemvac_start_sc_pump: SC pump already running. Will do nothing.");
880  cm_yield(0);
881  } else { // pump != running, hence send start command
882  info->lemvac_buffer[416] = (char)1; // SC PS_On command
883  lemvac_write_cmd(info);
884 
885  // set handshake command string
886  sprintf(cmd, "%d;%d", 5, 1);
887  strncpy(info->handshake_cmd, cmd, sizeof(info->handshake_cmd));
888  }
889 
890  // reset cmd tag, i.e. set it to idle
891  db_find_key(info->hDB, 0, "/Equipment/LEMVAC/Variables/Output", &hKey);
892  size = sizeof(float);
893  fval = 0.0;
894  db_set_data_index(info->hDB, hKey, &fval, size, LV_SC_PUMP_CMD, TID_FLOAT);
895 
896  // disable SC pump cmd enabled
897  fval = 0.0;
898  db_set_data_index(info->hDB, hKey, &fval, size, LV_SC_PUMP_CMD_ENABLED, TID_FLOAT);
899 }
900 
901 //----------------------------------------------------------------------------
908 {
909  HNDLE hKey;
910  INT size;
911  float fval;
912  char cmd[32];
913 
914  cm_msg(MDEBUG, "lemvac_stop_sc_pump", "lemvac_stop_sc_pump: will stop SC pump.");
915  cm_yield(0);
916 
917  // get current SC pump state
918  if ((int)info->lemvac_data[LV_SCSTAT1] & LV_BIT1) {
919  cm_msg(MDEBUG, "lemvac_stop_sc_pump", "lemvac_stop_sc_pump: SC pump already stopped. Will do nothing.");
920  cm_yield(0);
921  } else { // pump != stopped, hence send stop command
922  info->lemvac_buffer[416] = (char)2; // SC PS_Off command
923  lemvac_write_cmd(info);
924 
925  // set handshake command string
926  sprintf(cmd, "%d;%d", 5, 0);
927  strncpy(info->handshake_cmd, cmd, sizeof(info->handshake_cmd));
928  }
929 
930 
931  // reset cmd tag, i.e. set it to idle
932  db_find_key(info->hDB, 0, "/Equipment/LEMVAC/Variables/Output", &hKey);
933  size = sizeof(float);
934  fval = 0.0;
935  db_set_data_index(info->hDB, hKey, &fval, size, LV_SC_PUMP_CMD, TID_FLOAT);
936 
937  // disable SC pump cmd
938  fval = 0.0;
939  db_set_data_index(info->hDB, hKey, &fval, size, LV_SC_PUMP_CMD_ENABLED, TID_FLOAT);
940 }
941 
942 //----------------------------------------------------------------------------
952 {
953  if (lemvac_sc_vent_state == 7) { // all necessary conditions fulfilled, i.e. HV SC down, T>=90K, and BPVY closed
954  lemvac_stop_sc_pump(info);
955  return;
956  }
957 
958  if (!(lemvac_sc_vent_state & (1 << VENT_STATE_HV_BIT))) { // HV FUG SC still on
959  lemvac_shutdown_sc_hv(info);
960  }
961  if (!(lemvac_sc_vent_state & (1 << VENT_STATE_BPVY_BIT))) { // BPVY still open
963  }
964  if (!(lemvac_sc_vent_state & (1 << VENT_STATE_TEMP_BIT))) { // sample CF1 T<90K
965  if (forced == TRUE) {
966  lemvac_forced_warmup(info);
967  } else {
968  cm_msg(MINFO, "lemvac_prepare_stop_sc_pump", "lemvac_prepare_stop_sc_pump: CF1 T<90K, will stop the SC pump as soon as T>=90K. But you need to initiate it.");
969  cm_yield(0);
970  }
971  }
972 
974 }
975 
976 //----------------------------------------------------------------------------
986 {
987  if (lemvac_sc_vent_state == 15) { // all necessary conditions fulfilled, i.e. HV SC down, BPVY closed, T>=90K, SC turbo pump stopped
989  return;
990  }
991 
992  if (!(lemvac_sc_vent_state & (1 << VENT_STATE_HV_BIT))) { // HV FUG still on
993  lemvac_shutdown_sc_hv(info);
994  }
995  if (!(lemvac_sc_vent_state & (1 << VENT_STATE_BPVY_BIT))) { // BPVY still open
997  }
998  if (!(lemvac_sc_vent_state & (1 << VENT_STATE_TEMP_BIT))) { // sample CF1 T<90K
999  if (forced == TRUE) {
1000  lemvac_forced_warmup(info);
1001  } else {
1002  cm_msg(MINFO, "lemvac_prepare_venting_sc", "lemvac_prepare_venting_sc: CF1 T<90K, will start venting the SC as soon as T>=90K. But you need to initiate it.");
1003  }
1004  }
1005 
1007 }
1008 
1009 //----------------------------------------------------------------------------
1017 {
1018  HNDLE hKey;
1019  INT status, size;
1020  float fval;
1021  char cmdStr[32];
1022 
1023  // vent
1024  if (cmd == VENT_CMD_STOP) { // stop venting command requested
1025  info->lemvac_buffer[416] = (char)64; // vent off command
1026  lemvac_write_cmd(info);
1027 
1028  // set handshake command string
1029  sprintf(cmdStr, "%d;%d", 7, cmd);
1030  strncpy(info->handshake_cmd, cmdStr, sizeof(info->handshake_cmd));
1031  } else if (cmd == VENT_CMD_START) { // start venting command requested
1032  info->lemvac_buffer[416] = (char)32; // vent on command
1033  lemvac_write_cmd(info);
1034 
1035  // set handshake command string
1036  sprintf(cmdStr, "%d;%d", 7, cmd);
1037  strncpy(info->handshake_cmd, cmdStr, sizeof(info->handshake_cmd));
1038  } else {
1039  cm_msg(MDEBUG, "lemvac_vent_sc", "lemvac_vent_sc: **ERROR** recived unkown vent command.");
1040  cm_yield(0);
1041  }
1042 
1043  // update ODB vent state
1044  status = db_find_key(info->hDB, 0, "/Equipment/LEMVAC/Variables/Output", &hKey);
1045  if (status != DB_SUCCESS) {
1046  cm_msg(MERROR, "lemvac_vent_sc", "lemvac_vent_sc: **ERROR** couldn't get lemvac output variable key.");
1047  return;
1048  }
1049 
1050  // disable venting
1051  size = sizeof(float);
1052  fval = 0.0;
1053  db_set_data_index(info->hDB, hKey, &fval, size, LV_SC_VENT_CMD, TID_FLOAT);
1054  fval = 0.0;
1055  db_set_data_index(info->hDB, hKey, &fval, size, LV_SC_VENT_CMD_ENABLED, TID_FLOAT);
1056 
1057  // status message
1058  if (cmd == VENT_CMD_START) {
1059  cm_msg(MINFO, "lemvac_vent_sc", "lemvac_vent_sc: sample chamber vented.");
1060  } else {
1061  cm_msg(MINFO, "lemvac_vent_sc", "lemvac_vent_sc: stop venting the sample chamber.");
1062  }
1063  cm_yield(0);
1064 }
1065 
1066 /*---- device driver routines ------------------------------------------------*/
1067 
1068 /*----------------------------------------------------------------------------*/
1082 INT lemvac_in_init(HNDLE hKey, void **pinfo, INT channels, INT (*bd)(INT cmd, ...))
1083 {
1084  INT status, size, i;
1085  char str[512];
1086  HNDLE hDB, hkeydd;
1087 
1088  // allocate info structure
1089  gInfo = (LEMVAC_INFO *)calloc(1, sizeof(LEMVAC_INFO));
1090  *pinfo = gInfo;
1091 
1092  // get ODB handle
1093  cm_get_experiment_database(&hDB, NULL);
1094  // store handles (ODB and DD key) in local structure to keep it for latter use
1095  gInfo->hDB = hDB;
1096  gInfo->hKey_in = hKey;
1097 
1098  // create lemvac DD intern structure if not already exists
1099  status = db_find_key(hDB, hKey, "DD/intern", &hkeydd);
1100  if (status != DB_SUCCESS) { // key doesn't exist yet
1101  // create lemvac DD intern
1102  status = db_create_record(hDB, hKey, "DD/intern", LAMVAC_INTERN_STR);
1103  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1104  cm_msg(MERROR, "lemvac_init", "lemvac_init: Error creating lemvac intern record in ODB, status=%d", status);
1105  cm_yield(0);
1106  return FE_ERR_ODB;
1107  }
1108  }
1109  db_find_key(hDB, hKey, "DD/intern", &hkeydd);
1110  size = sizeof(gInfo->intern);
1111  status = db_get_record(hDB, hkeydd, &gInfo->intern, &size, 0);
1112  // open hotlink
1113  status = db_open_record(hDB, hkeydd, &gInfo->intern, size, MODE_READ, NULL, NULL);
1114 
1115  // create lemvac DD names record
1116  status = db_create_record(hDB, hKey, "DD/Names", LEMVAC_NAMES_STR);
1117  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1118  cm_msg(MERROR, "lemvac_init", "lemvac_init: Error creating lemvac Names record in ODB, status=%d", status);
1119  cm_yield(0);
1120  return FE_ERR_ODB;
1121  }
1122  db_find_key(hDB, hKey, "DD/Names", &hkeydd);
1123  size = sizeof(gInfo->lemvac_names);
1124  db_get_record(hDB, hkeydd, &gInfo->lemvac_names, &size, 0);
1125 
1126 
1127  // check if lemvac DD SPS-DB buffer record already exists
1128  status = db_find_key(hDB, hKey, "DD/DB_Buffer", &hkeydd);
1129  if (status != DB_SUCCESS) { // key doesn't exist yet
1130  // create lemvac DD DB buffer
1131  strcpy(str, "DB_Buffer = BYTE[680] : \n");
1132  for (i=0; i<SPS_MAX_BYTES; i++)
1133  strcat(str, " \n");
1134  status = db_create_record(hDB, hKey, "DD/DB_Buffer", str);
1135  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1136  cm_msg(MERROR, "lemvac_init", "lemvac_init: Error creating lemvac DB_Buffer record in ODB, status=%d", status);
1137  cm_yield(0);
1138  return FE_ERR_ODB;
1139  }
1140  }
1141 
1142  db_find_key(hDB, hKey, "DD/DB_Buffer", &hkeydd);
1143  size = sizeof(gInfo->lemvac_buffer);
1144  status = db_get_record(hDB, hkeydd, &gInfo->lemvac_buffer, &size, 0);
1145  // open hotlink
1146  status = db_open_record(hDB, hkeydd, &gInfo->lemvac_buffer, size, MODE_WRITE, NULL, NULL);
1147  gInfo->hKey_DB_Buffer = hkeydd;
1148 
1149  // initialize driver
1150  gInfo->bd = bd; // keep the bus driver entry function
1151  gInfo->bd_info = 0; // initialize the pointer to the BD info structure
1152  gInfo->bpv_enabled[0] = 0; // initialize BPVX enable flag
1153  gInfo->bpv_enabled[1] = 0; // initialize BPVY enable flag
1154  gInfo->sc_pump_cmd_enabled = 0; // initialize SC pump cmd enable flag
1155  gInfo->sc_vent_cmd_enabled = 0; // initialize SC vent cmd enable flag
1156  strncpy(gInfo->handshake_cmd, "", sizeof(gInfo->handshake_cmd)); // initialize handshake cmd
1157  for (i=0; i<4; i++)
1158  gInfo->handshake_err_count[i] = 0;
1159  gInfo->time = ss_time(); // timer for error handling
1160  gInfo->errTime = ss_time(); // timer for error handling
1161  gInfo->read_error = 0; // read error counter
1162  gInfo->tcpip_open_error = 0; // open tcpip error counter
1163  gInfo->read_counts = 0; // counter how often tcpip reading has benn attempt
1164  gInfo->last_success = 0;
1165 
1166  // initialize vent state variable
1168 
1169  // initialize pending command variable
1171 
1172  // open tcpip connection
1173  status = gInfo->bd(CMD_INIT, gInfo->hKey_in, &gInfo->bd_info);
1174  if (gInfo->intern.detailed_msg) {
1175  cm_msg(MDEBUG, "lemvac_init", "lemvac_init: open tcpip connection (status=%d)", status);
1176  cm_yield(0);
1177  }
1178  if (status != SUCCESS) {
1179  gInfo->tcpip_open_error++;
1180  if (gInfo->intern.detailed_msg) {
1181  cm_msg(MINFO, "lemvac_init", "lemvac_init: open bounced off");
1182  cm_yield(0);
1183  }
1184  return FE_ERR_DRIVER;
1185  }
1186 
1187  // initialize lemvac status message
1188  cm_msg(MINFO, "lemvac_init", "lemvac initialized ...");
1189  cm_yield(0);
1190 
1191  return FE_SUCCESS;
1192 }
1193 
1194 /*----------------------------------------------------------------------------*/
1206 INT lemvac_out_init(HNDLE hKey, void **pinfo, INT channels, INT (*bd)(INT cmd, ...))
1207 {
1208  *pinfo = gInfo; // since gInfo has been allocated in lemvac_in_init, it is enough to pass the pointer
1209 
1210  // initialize driver
1211  gInfo->hKey_out = hKey; // keep the DD entry key
1212 
1213  return FE_SUCCESS;
1214 }
1215 
1216 /*----------------------------------------------------------------------------*/
1226 {
1227  // close all hotlinks
1228  db_close_record(info->hDB, info->hKey_DB_Buffer);
1229 
1230  // close connection
1231  info->bd(CMD_EXIT, info->bd_info);
1232 
1233  free(info);
1234  return FE_SUCCESS;
1235 }
1236 
1237 /*----------------------------------------------------------------------------*/
1255 INT lemvac_set(LEMVAC_INFO *info, INT channel, float value)
1256 {
1257  switch (channel) {
1258  case LV_BPVX_ENABLED: // enable/disable flag BPVX
1259  info->bpv_enabled[0] = (int)value;
1260  break;
1261  case LV_BPVY_ENABLED: // enable/disable flag BPVY
1262  info->bpv_enabled[1] = (int)value;
1263  break;
1264  case LV_BPVX_CMD: // BPVX open/close command
1265  if (info->bpv_enabled[0]) {
1266  lemvac_set_sliding_valve(info, channel, value);
1267  }
1268  break;
1269  case LV_BPVY_CMD: // BPVY open/close command
1270  if (info->bpv_enabled[1]) {
1271  lemvac_set_sliding_valve(info, channel, value);
1272  }
1273  break;
1275  info->sc_pump_cmd_enabled = (int)value;
1276  break;
1277  case LV_SC_PUMP_CMD:
1278  if (!info->sc_pump_cmd_enabled && (value > 0.0)) {
1279  cm_msg(MERROR, "lemvac_set", "lemvac_set: **WARNING** pump cmd not enabled! Will do nothing!");
1280  return FE_SUCCESS;
1281  }
1282  if (value == 0.0) {
1284  } else if (value == 1.0) {
1285  lemvac_vent_sc(info, VENT_CMD_STOP); // make sure venting is stopped
1286  ss_sleep(200); //as currently needed since the SPS is too slow
1287  cm_yield(0); //as
1288  lemvac_start_sc_pump(info);
1289  } else if (value == 2.0) {
1290  lemvac_prepare_stop_sc_pump(info, FALSE); // stop pump if T>90K, do nothing on the SC temperature controller
1291  } else if (value == 3.0) {
1292  lemvac_prepare_stop_sc_pump(info, TRUE); // stop pump if T>90K, if T<90K initiate warmup
1293  } else {
1294  cm_msg(MERROR, "lemvac_set", "lemvac_set: **ERROR** found unsupported SC pump cmd %d. Will do nothing.", (int)value);
1295  cm_yield(0);
1296  }
1297  break;
1299  info->sc_vent_cmd_enabled = (int)value;
1300  break;
1301  case LV_SC_VENT_CMD:
1302  if (!info->sc_vent_cmd_enabled && (value > 0.0)) {
1303  cm_msg(MERROR, "lemvac_set", "lemvac_set: **WARNING** vent cmd not enabled! Will do nothing!");
1304  return FE_SUCCESS;
1305  }
1306  if (value == 0.0) {
1308  } else if (value == 1.0) {
1310  } else if (value == 2.0) {
1311  lemvac_prepare_venting_sc(info, FALSE); // vent as soon as T>90K, but do nothing on the SC temperature controller, BH flow, etc.
1312  } else if (value == 3.0) {
1313  lemvac_prepare_venting_sc(info, TRUE); // vent as soon as T>90K, if T<90K initiate warmup
1314  } else {
1315  cm_msg(MERROR, "lemvac_set", "lemvac_set: **ERROR** found unsupported SC vent cmd %d. Will do nothing.", (int)value);
1316  cm_yield(0);
1317  }
1318  break;
1319  default:
1320  break;
1321  }
1322 
1323  return FE_SUCCESS;
1324 }
1325 
1326 //----------------------------------------------------------------------------
1337 INT lemvac_in_get_label(LEMVAC_INFO *info, INT channel, char *name)
1338 {
1339  strcpy(name, info->lemvac_names.in_name[channel]);
1340  return FE_SUCCESS;
1341 }
1342 
1343 //----------------------------------------------------------------------------
1354 INT lemvac_out_get_label(LEMVAC_INFO *info, INT channel, char *name)
1355 {
1356  strcpy(name, info->lemvac_names.out_name[channel]);
1357  return FE_SUCCESS;
1358 }
1359 
1360 //-----------------------------------------------------------------------------
1370 INT lemvac_get(LEMVAC_INFO *info, INT channel, float *pvalue)
1371 {
1372  if (info->intern.detailed_msg > 1) {
1373  cm_msg(MDEBUG, "lemvac_get", "in lemvac_get ...");
1374  cm_yield(0);
1375  }
1376 
1377  if (channel % (LEMVAC_IN_VARS / 2) == 0) { // only read if channel is 0 or (LEMVAC_IN_VARS / 2) since all data are read at once
1378  if (info->intern.detailed_msg) {
1379  cm_msg(MDEBUG, "lemvac_get", "in lemvac_get and will call lemvac_get_all(info)");
1380  cm_yield(0);
1381  }
1382  lemvac_get_all(info);
1383  }
1384 
1385  *pvalue = info->lemvac_data[channel];
1386 
1387  ss_sleep(10);
1388  return FE_SUCCESS;
1389 }
1390 
1391 //---- device driver entry point -----------------------------------
1392 INT lemvac_in(INT cmd, ...)
1393 {
1394 va_list argptr;
1395 HNDLE hKey;
1396 INT channel, status;
1397 float *pvalue;
1398 void *info, *bd;
1399 char *name;
1400 DWORD flags;
1401 
1402  va_start(argptr, cmd);
1403  status = FE_SUCCESS;
1404 
1405  switch (cmd) {
1406  case CMD_INIT:
1407  hKey = va_arg(argptr, HNDLE);
1408  info = va_arg(argptr, void *);
1409  channel = va_arg(argptr, INT);
1410  flags = va_arg(argptr, DWORD);
1411  bd = va_arg(argptr, void *);
1412  status = lemvac_in_init(hKey, info, channel, bd);
1413  break;
1414 
1415  case CMD_EXIT:
1416  info = va_arg(argptr, void *);
1417  status = lemvac_exit(info);
1418  break;
1419 
1420  case CMD_GET:
1421  info = va_arg(argptr, void *);
1422  channel = va_arg(argptr, INT);
1423  pvalue = va_arg(argptr, float*);
1424  status = lemvac_get(info, channel, pvalue);
1425  break;
1426 
1427  case CMD_GET_LABEL:
1428  info = va_arg(argptr, void *);
1429  channel = va_arg(argptr, INT);
1430  name = va_arg(argptr, char *);
1431  status = lemvac_in_get_label(info, channel, name);
1432  break;
1433 
1434  default:
1435  break;
1436  }
1437 
1438  va_end(argptr);
1439 
1440  return status;
1441 }
1442 
1443 //---- device driver entry point -----------------------------------
1444 INT lemvac_out(INT cmd, ...)
1445 {
1446 va_list argptr;
1447 HNDLE hKey;
1448 INT channel, status;
1449 float value;
1450 void *info, *bd;
1451 char *name;
1452 DWORD flags;
1453 
1454  va_start(argptr, cmd);
1455  status = FE_SUCCESS;
1456 
1457  switch (cmd) {
1458  case CMD_INIT:
1459  hKey = va_arg(argptr, HNDLE);
1460  info = va_arg(argptr, void *);
1461  channel = va_arg(argptr, INT);
1462  flags = va_arg(argptr, DWORD);
1463  bd = va_arg(argptr, void *);
1464  status = lemvac_out_init(hKey, info, channel, bd);
1465  break;
1466 
1467  case CMD_GET_LABEL:
1468  info = va_arg(argptr, void *);
1469  channel = va_arg(argptr, INT);
1470  name = va_arg(argptr, char *);
1471  status = lemvac_out_get_label(info, channel, name);
1472  break;
1473 
1474  case CMD_SET:
1475  info = va_arg(argptr, void *);
1476  channel = va_arg(argptr, INT);
1477  value = (float) va_arg(argptr, double);
1478  status = lemvac_set(info, channel, value);
1479  break;
1480 
1481  default:
1482  break;
1483  }
1484 
1485  va_end(argptr);
1486 
1487  return status;
1488 }
1489 //---- end --------------------------------------------------------------
INT(* bd)(INT cmd,...)
bus driver entry function for reading
Definition: lemvac.c:180
int handshake_err_count[4]
handshake command error counters
Definition: lemvac.c:186
#define LV_SCSTAT1
Definition: lemvac.c:62
INT read_error
how often there has been a read error
Definition: lemvac.c:195
#define SAMPLE_IN_CF1_IDX
Definition: lemvac.c:111
INFO info
Definition: vme_fe.c:206
void lemvac_shutdown_sc_hv(LEMVAC_INFO *info)
Definition: lemvac.c:304
void lemvac_forced_warmup(LEMVAC_INFO *info)
Definition: lemvac.c:330
#define LV_BPVY_ENABLED
Definition: lemvac.c:73
#define LV_MCSTAT2
Definition: lemvac.c:57
#define LV_BPVY_CMD
Definition: lemvac.c:74
INT lemvac_out_get_label(LEMVAC_INFO *info, INT channel, char *name)
Definition: lemvac.c:1354
#define LV_PZSTAT1
Definition: lemvac.c:65
void lemvac_deal_with_handshake(LEMVAC_INFO *info)
Definition: lemvac.c:541
#define LV_TCGJ2
Definition: lemvac.c:50
void lemvac_write_cmd(LEMVAC_INFO *info)
Definition: lemvac.c:775
INT lemvac_check_sample_temp()
Definition: lemvac.c:271
void * bd_info
pointer to the BD info structure of the input channels
Definition: lemvac.c:181
#define LV_BIT1
Definition: lemvac.c:25
#define LEMVAC_NAMES_STR
Initializing string for the struct LEMVAC_NAMES.
Definition: lemvac.c:134
#define LV_MCSTAT3
Definition: lemvac.c:58
INT lemvac_in_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
Definition: lemvac.c:1082
#define LV_BIT3
Definition: lemvac.c:27
int sc_vent_cmd_enabled
holds enable flag for SC vent command
Definition: lemvac.c:184
void lemvac_get_all(LEMVAC_INFO *info)
Definition: lemvac.c:642
INT lemvac_in_get_label(LEMVAC_INFO *info, INT channel, char *name)
Definition: lemvac.c:1337
#define LV_TCGT
Definition: lemvac.c:48
#define LV_SC_VENT_CMD
Definition: lemvac.c:78
#define LV_BIT2
Definition: lemvac.c:26
LEMVAC_NAMES lemvac_names
stores the internal DD settings
Definition: lemvac.c:177
#define FUG_SC_SAMPLE_IDX
Definition: lemvac.c:108
#define VENT_CMD_STOP
Definition: lemvac.c:100
char out_name[LEMVAC_OUT_VARS][NAME_LENGTH]
Names of the output variable names as found in the ODB.
Definition: lemvac.c:130
#define LV_BPVX_CMD
Definition: lemvac.c:72
int bpv_enabled[2]
holds enable flag for BPVX and BPVY
Definition: lemvac.c:182
#define LV_SCSTAT2
Definition: lemvac.c:63
#define LV_SCGT
Definition: lemvac.c:52
double penning_ikr070(int analog)
Definition: lemvac.c:437
float lemvac_data[LEMVAC_IN_VARS]
stores decoded values from SPS-DB
Definition: lemvac.c:179
#define LV_BPVX_ENABLED
Definition: lemvac.c:71
#define LV_SC_VENT_CMD_ENABLED
Definition: lemvac.c:77
#define LEMVAC_TIMEOUT_ERROR
after what time (sec.) read errors should be reported
Definition: lemvac.c:88
INT lemvac_get(LEMVAC_INFO *info, INT channel, float *pvalue)
Definition: lemvac.c:1370
#define LV_TCSTAT1
Definition: lemvac.c:59
void lemvac_vent_sc(LEMVAC_INFO *info, INT cmd)
Definition: lemvac.c:1016
Stores DD specific internal information.
Definition: lemvac.c:118
#define LV_LIFESIGN
Definition: lemvac.c:42
HNDLE hKey
Definition: write_summary.c:97
#define SAMPLE_OUT_BH2_FLOW_IDX
Definition: lemvac.c:115
#define FUG_SC_RAL_IDX
Definition: lemvac.c:104
void lemvac_start_sc_pump(LEMVAC_INFO *info)
Definition: lemvac.c:866
INT lemvac_pending_sc_cmd
Definition: lemvac.c:219
INT lemvac_set(LEMVAC_INFO *info, INT channel, float value)
Definition: lemvac.c:1255
INT lemvac_sc_vent_state
Definition: lemvac.c:214
HNDLE hKey_DB_Buffer
handle to the raw SPS-DB data
Definition: lemvac.c:190
LEMVAC_INFO * gInfo
global info structure, in/out-init routines need the same structure
Definition: lemvac.c:200
#define LV_SC_PUMP_CMD_ENABLED
Definition: lemvac.c:75
#define LEMVAC_OUT_VARS
number of variables in the set list
Definition: lemvac.h:11
#define VENT_STATE_HV_BIT
Definition: lemvac.c:95
#define LEMVAC_TIME_CONST
trigger time constant for read out of the SPS
Definition: lemvac.c:87
#define VENT_STATE_TEMP_BIT
Definition: lemvac.c:96
INT lemvac_out(INT cmd,...)
Definition: lemvac.c:1444
#define LV_TCSTAT3
Definition: lemvac.c:61
HNDLE hKey_in
main device driver handle for input channels
Definition: lemvac.c:188
HNDLE hDB
Definition: write_summary.c:97
int spsToWord(unsigned char *buffer)
Definition: lemvac.c:419
double pirani_tpr018(int analog)
Definition: lemvac.c:451
INT startup_error
tag if there has been an error at startup
Definition: lemvac.c:193
int sc_pump_cmd_enabled
holds enable flag for SC pump command
Definition: lemvac.c:183
#define LV_SCGJ2
Definition: lemvac.c:54
#define LV_MCGJ
Definition: lemvac.c:45
#define VENT_STATE_PUMP_BIT
Definition: lemvac.c:98
DWORD time
trigger timer
Definition: lemvac.c:191
HNDLE hKey_out
main device driver handle for output channels
Definition: lemvac.c:189
#define LV_BPV_CMD_CLOSE
Definition: lemvac.c:84
#define LV_GAS_INLET_FLAG
Definition: lemvac.c:21
INT lemvac_check_sample_hv()
Definition: lemvac.c:233
#define LEMVAC_SC_PENDING_CMD_VENT
Definition: lemvac.c:93
#define SPS_MAX_BYTES
length of the data structure exchanged between SPS and midas
Definition: lemvac.c:86
void lemvac_stop_sc_pump(LEMVAC_INFO *info)
Definition: lemvac.c:907
void lemvac_check_pending_cmd(LEMVAC_INFO *info)
Definition: lemvac.c:365
HNDLE hDB
main ODB handle
Definition: lemvac.c:187
#define LV_BPVX
Definition: lemvac.c:67
#define LV_BIT0
Definition: lemvac.c:24
#define LV_PZGR
Definition: lemvac.c:55
#define LV_MCSTAT1
Definition: lemvac.c:56
#define VENT_STATE_BPVY_BIT
Definition: lemvac.c:97
#define LV_MCGR
Definition: lemvac.c:43
char in_name[LEMVAC_IN_VARS][NAME_LENGTH]
Names of the input variable names as found in the ODB.
Definition: lemvac.c:129
#define SAMPLE_OUT_BH1_FLOW_IDX
Definition: lemvac.c:114
#define LV_SC_PUMP_CMD
Definition: lemvac.c:76
INT detailed_msg
flag indicating if detailed status/error messages are wanted
Definition: lemvac.c:119
This structure contains private variables for the device driver.
Definition: lemvac.c:175
short spsToNumber(unsigned char *buffer)
Definition: lemvac.c:394
INT read_counts
total no of tcpip reading attempts
Definition: lemvac.c:196
float lemvac_in[27]
holds the lemvac input variables
Definition: hv_fug_scfe.c:94
#define LV_SCGJ
Definition: lemvac.c:53
#define LV_SCSTAT3
Definition: lemvac.c:64
#define LV_TCGR
Definition: lemvac.c:47
void lemvac_prepare_venting_sc(LEMVAC_INFO *info, BOOL forced)
Definition: lemvac.c:985
BOOL lemvac_decode_data(LEMVAC_INFO *info, const char *buffer)
Definition: lemvac.c:496
void lemvac_prepare_stop_sc_pump(LEMVAC_INFO *info, BOOL forced)
Definition: lemvac.c:951
#define LV_MCGJ2
Definition: lemvac.c:46
#define LEMVAC_SC_PENDING_CMD_STOP
Definition: lemvac.c:92
#define LV_BIT9
Definition: lemvac.c:33
#define LEMVAC_IN_VARS
number of variables in the get list
Definition: lemvac.h:10
#define SAMPLE_OUT_LS_RAMP
Definition: lemvac.c:113
void lemvac_set_sliding_valve(LEMVAC_INFO *info, INT valve, float value)
Definition: lemvac.c:798
#define LV_HV_NO_INTERLOCK_FLAG
Definition: lemvac.c:20
char handshake_cmd[32]
handshake command
Definition: lemvac.c:185
LEMVAC_INTERN intern
stores DD specific internal settings
Definition: lemvac.c:176
DWORD errTime
timer for error handling concerning tcpip communication
Definition: lemvac.c:192
#define VENT_CMD_START
Definition: lemvac.c:101
INT lemvac_out_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
Definition: lemvac.c:1206
#define LV_TCSTAT2
Definition: lemvac.c:60
#define LAMVAC_INTERN_STR
Initializing string for the struct LEMVAC_INTERN.
Definition: lemvac.c:123
DWORD last_success
timer of last read success
Definition: lemvac.c:197
INT tcpip_open_error
how often the attempt to open the tcpip communication failed
Definition: lemvac.c:194
#define LV_MCGT
Definition: lemvac.c:44
#define LV_TCGJ
Definition: lemvac.c:49
#define LV_BPVY
Definition: lemvac.c:68
#define SAMPLE_OUT_SET_POINT_IDX
Definition: lemvac.c:112
#define LV_PZSTAT2
Definition: lemvac.c:66
char lemvac_buffer[SPS_MAX_BYTES]
SPS-DB byte buffer.
Definition: lemvac.c:178
#define LEMVAC_SC_PENDING_CMD_IDLE
Definition: lemvac.c:91
INT lemvac_exit(LEMVAC_INFO *info)
Definition: lemvac.c:1225
#define LV_SCGR
Definition: lemvac.c:51
#define LV_BIT4
Definition: lemvac.c:28
Stores the names of the various channels which are than transferred form the DD to the variable names...
Definition: lemvac.c:128