Low-Energy Muon (LEM) Experiment  0.5.1
bruker.c
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------
2 
3  Name: bruker.c
4  Created by: Andreas Suter 2001/08/29
5 
6  Contents: device driver for bruker B-EC 1 magnet power supply.
7  Revised for Midas' new bus driver conept.
8 
9  RS232: 9600 baud, 8 data bits, 1 stop bit, no parity,
10  protocol: CTS (hardware), termination \r\n (CR\LF)
11 
12 ----------------------------------------------------------------------------*/
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <string.h>
18 #include <math.h>
19 #include "midas.h"
20 #include "bruker.h"
21 
22 #include "ets_logout.h"
23 
24 #define BRUKER_INIT_ERROR -2
25 #define BRUKER_READ_ERROR -1
26 
27 #define BRUKER_MAX_READ 5
28 
29 #define BRUKER_TIME_OUT 2000
31 
33 #define BRUKER_MAX_READBACK_FAILURE 5
34 
36 #define BRUKER_RECONNECTION_TIMEOUT 5
37 
39 #define BRUKER_ETS_LOGOUT_SLEEP 10000
40 
41 //---- bruker status decoding tags ----------------------------------
43 #define BRUKER_ERR_WATER 0x001
44 #define BRUKER_ERR_PHASE 0x002
46 #define BRUKER_ERR_TEMP 0x004
48 #define BRUKER_ERR_EXT1 0x008
50 #define BRUKER_ERR_DOOR 0x010
52 #define BRUKER_ERR_GND 0x020
54 #define BRUKER_ERR_EXT2 0x040
56 #define BRUKER_ERR_CURR 0x100
58 
60 #define BRUKER_STATUS_REMOTE 0x010000
61 #define BRUKER_STATUS_EXTREF 0x040000
63 #define BRUKER_STATUS_CYCLE 0x080000
65 #define BRUKER_STATUS_POLNORM 0x200000
67 #define BRUKER_STATUS_DCPWRON 0x400000
69 
70 //--------- to handle error messages ------------------------------
71 
73 #define BRUKER_MAX_ERROR 10
74 #define BRUKER_DELTA_TIME_ERROR 1800
76 
77 //--------- number of channels -------------------------------------
79 #define BRUKER_IN_CHS 5
80 #define BRUKER_OUT_CHS 2
82 
84 typedef struct {
86  INT ets_in_use;
87  char names_in[BRUKER_IN_CHS][NAME_LENGTH];
88  char names_out[BRUKER_OUT_CHS][NAME_LENGTH];
90 
92 #define BRUKER_SETTINGS_STR "\
93 Detailed Messages = INT : 0\n\
94 ETS_IN_USE = INT : 1\n\
95 Input Names = STRING[5] :\n\
96 [32] Polarity, 1=pos, 2=neg, 3=switch\n\
97 [32] Status\n\
98 [32] Demand Current (Readback)\n\
99 [32] Output Current\n\
100 [32] Output Voltage\n\
101 Output Names = STRING[2] :\n\
102 [32] Power On=1/Off=0\n\
103 [32] Demand Current\n\
104 "
105 
107 typedef struct {
109  INT (*bd)(INT cmd, ...);
110  void *bd_info;
113  HNDLE hkey;
120  INT errcount;
122  DWORD lasterrtime;
126 } BRUKER_INFO;
127 
129 
130 //---- support routines --------------------------------------------
139 INT bruker_send_rcv(BRUKER_INFO *info, char *cmd, char *str, int size)
140 {
141  int i, status = 0;
142  char reply[128], *lp;
143 
144  BD_PUTS(cmd);
145 
146  for (i=0; i<BRUKER_MAX_READ; i++) {
147  // get the reply
148  status = BD_GETS(reply, sizeof(reply), "\r", BRUKER_TIME_OUT);
149  if (status) { // got something -> happy
150  lp = strstr(reply, "/"); // find end of the cmd string echo
151  if (lp) {
152  lp++;
153  strncpy(str, lp, size);
154  break;
155  }
156 /*
157  cm_msg(MDEBUG, "bruker_send_rcv", "bruker_send_rcv i=%d, status=%d, str=%s", i, status, str);
158  cm_yield(0);
159 */
160  }
161  ss_sleep(500);
162  }
163 
164  return status;
165 }
166 
167 //-------------------------------------------------------------------
178 INT bruker_decode_status(BRUKER_INFO *info, char *str)
179 {
180  INT status;
181  char *lp;
182 
183  // in case str is empty, do nothing
184  if ((strlen(str) == 0) || (strlen(str) == 1)) {
185  return FE_SUCCESS;
186  }
187 
188  // first check if the STA/ command potentially makes any sense
189  lp = strstr(str, "E");
190  if (lp) { // something went wrong, just ignore it for now
191  if (strstr(str, "E01") || strstr(str, "E03"))
192  return FE_SUCCESS;
193  cm_msg(MDEBUG, "bruker_decode_status", "bruker_decode_status: str=%s", str);
194  cm_yield(0);
195  return FE_SUCCESS;
196  }
197 
198  // extract status bits
199  sscanf(str, "%x", &status);
200 
201  // error checks
202  if (status & BRUKER_ERR_WATER) {
203  if (info->errcount < BRUKER_MAX_ERROR ) {
204  al_trigger_alarm("Bruker", "NO WATER FLOW", "Alarm", "no water flow", AT_INTERNAL);
205  cm_msg(MERROR, "bruker", "ERROR - NO WATER FLOW");
206  cm_yield(0);
207  info->errcount++;
208  return FE_ERR_HW;
209  }
210  }
211 
212  if (status & BRUKER_ERR_PHASE) {
213  if (info->errcount < BRUKER_MAX_ERROR) {
214  al_trigger_alarm("Bruker", "PHASE ERROR", "Alarm", "phase error", AT_INTERNAL);
215  cm_msg(MERROR, "bruker", "ERROR - PHASE ERROR");
216  cm_yield(0);
217  info->errcount++;
218  return FE_ERR_HW;
219  }
220  }
221 
222  if (status & BRUKER_ERR_TEMP) {
223  if (info->errcount < BRUKER_MAX_ERROR) {
224  al_trigger_alarm("Bruker", "OVERHEATED", "Alarm", "overheated", AT_INTERNAL);
225  cm_msg(MERROR, "bruker", "ERROR - OVERHEATED");
226  cm_yield(0);
227  info->errcount++;
228  return FE_ERR_HW;
229  }
230  }
231 
232  if (status & BRUKER_ERR_EXT1) {
233  if (info->errcount < BRUKER_MAX_ERROR) {
234  al_trigger_alarm("Bruker", "EXTERNAL 1 ERROR", "Alarm", "ext. 1", AT_INTERNAL);
235  cm_msg(MERROR, "bruker", "ERROR - EXTERNAL 1 ERROR");
236  cm_yield(0);
237  info->errcount++;
238  return FE_ERR_HW;
239  }
240  }
241 
242  if (status & BRUKER_ERR_DOOR) {
243  if (info->errcount < BRUKER_MAX_ERROR) {
244  al_trigger_alarm("Bruker", "EXTERNAL 1 ERROR", "Alarm", "door open", AT_INTERNAL);
245  cm_msg(MERROR, "bruker", "ERROR - DOOR OPEN");
246  cm_yield(0);
247  info->errcount++;
248  return FE_ERR_HW;
249  }
250  }
251 
252  if (status & BRUKER_ERR_GND) {
253  if (info->errcount < BRUKER_MAX_ERROR) {
254  al_trigger_alarm("Bruker", "GROUND FAULT or HV SPARKING", "Alarm", "ground fault", AT_INTERNAL);
255  cm_msg(MERROR, "bruker", "ERROR - GROUND FAULT");
256  cm_yield(0);
257  info->errcount++;
258  return FE_ERR_HW;
259  }
260  }
261 
262  if (status & BRUKER_ERR_EXT2) {
263  if (info->errcount < BRUKER_MAX_ERROR) {
264  al_trigger_alarm("Bruker", "EXTERNAL 2 ERROR", "Alarm", "ext. 2", AT_INTERNAL);
265  cm_msg(MERROR, "bruker", "ERROR - EXTERNAL 2 ERROR");
266  cm_yield(0);
267  info->errcount++;
268  return FE_ERR_HW;
269  }
270  }
271 
272  if (status & BRUKER_ERR_CURR) {
273  if (info->errcount < BRUKER_MAX_ERROR) {
274  al_trigger_alarm("Bruker", "OVERCURRENT", "Alarm", "overcurrent", AT_INTERNAL);
275  cm_msg(MERROR, "bruker", "ERROR - OVERCURRENT");
276  cm_yield(0);
277  info->errcount++;
278  return FE_ERR_HW;
279  }
280  }
281 
282  // status checks
283  if (!(status & BRUKER_STATUS_DCPWRON)) {
284  if (info->errcount < BRUKER_MAX_ERROR) {
285  al_trigger_alarm("Bruker", "DC POWER OFF", "Warning", "DC Power Off", AT_INTERNAL);
286  cm_msg(MINFO, "bruker", "BRUKER - WARNING - DC POWER OFF");
287  cm_msg(MDEBUG, "bruker_decode_status", "debug> str='%s', strlen(str)=%d", str, (int)strlen(str));
288  cm_yield(0);
289  info->errcount++;
290  return FE_SUCCESS;
291  }
292  }
293 
294  if (status & BRUKER_STATUS_REMOTE) {
295  if (info->bruker_remote == 0) {
296  cm_msg(MINFO, "bruker", "BRUKER - WARNING - SWITCHED LOCAL->REMOTE");
297  cm_yield(0);
298  }
299  info->bruker_remote = 1;
300  } else {
301  if (info->bruker_remote == 1) {
302  cm_msg(MINFO, "bruker", "BRUKER - WARNING - SWITCHED REMOTE->LOCAL");
303  cm_yield(0);
304  }
305  info->bruker_remote = 0;
306  }
307 
308  //info->errcount = 0;
309 
310  return FE_SUCCESS;
311 }
312 
313 
314 /*---- device driver routines --------------------------------------*/
315 
327 INT bruker_in_init(HNDLE hKey, void **pinfo, INT channels, INT (*bd)(INT cmd, ...))
328 {
329  INT status, size;
330  char cmd[64], str[64];
331  HNDLE hDB, hkeydd;
332 
333  // allocate info structure
334  info = calloc(1, sizeof(BRUKER_INFO));
335  *pinfo = info;
336 
337  cm_get_experiment_database(&hDB, NULL);
338 
339  // create Bruker settings record
340  status = db_create_record(hDB, hKey, "DD", BRUKER_SETTINGS_STR);
341  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
342  cm_msg(MERROR, "bruker_init", "bruker_init: Error creating Bruker DD record in ODB, status=%d", status);
343  cm_yield(0);
344  return FE_ERR_ODB;
345  }
346 
347  db_find_key(hDB, hKey, "DD", &hkeydd);
348  size = sizeof(info->bruker_settings);
349  db_get_record(hDB, hkeydd, &info->bruker_settings, &size, 0);
350 
351  // initialize driver
352  info->bd = bd;
353  info->hkey = hKey;
354  info->errcount = 0;
355  info->startup_error = 0;
356  info->check_setpoint = FALSE;
357  info->lasterrtime = ss_time();
358  info->readback_failure = 0;
359  info->last_reconnect = ss_time();
360  info->reconnection_failures = 0;
361  info->first_bd_error = 1;
362 
363  if (!bd)
364  return FE_ERR_ODB;
365 
366  // initialize bus driver
367  status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
368  if (status != SUCCESS) {
369  cm_msg(MERROR, "bruker_init", "Couldn't initialize the bus driver :-(");
370  cm_yield(0);
371  info->startup_error = 1;
372  info->bd_connected = FALSE;
373  return FE_SUCCESS;
374  }
375  info->bd_connected = TRUE;
376 
377  // initialize Bruker B-EC 1
378  cm_msg(MINFO, "bruker_init", "initialize bruker, takes a while ...");
379  cm_yield(0);
380  strcpy(cmd, "REM/\r");
381  status = bruker_send_rcv(info, cmd, str, sizeof(str));
382  if (info->bruker_settings.detailed_msg) {
383  cm_msg(MINFO,"bruker_init","REM status = %d, received string = %s", status, str);
384  cm_yield(0);
385  }
386  if (!strstr(str, "1")) { // not in remote mode
387  info->bruker_remote = 0;
388  cm_msg(MINFO, "bruker_init", "bruker power supply not in remote mode.");
389  cm_yield(0);
390  return FE_SUCCESS;
391  } else
392  info->bruker_remote = 1;
393 
394  // try to reset pending errors
395  strcpy(cmd, "RST=0\r");
396  status = bruker_send_rcv(info, cmd, str, sizeof(str));
397 
398 
399  // check status
400  strcpy(cmd, "STA/\r");
401  status = bruker_send_rcv(info, cmd, str, sizeof(str));
402  if (info->bruker_settings.detailed_msg) {
403  cm_msg(MINFO,"bruker_init","STA status = %d, received string = %s", status, str);
404  cm_yield(0);
405  }
406  if (!status) {
407  cm_msg(MINFO, "bruker_init", "STA: bruker does not respond. Check power and RS232 conection, further check Lantronix.");
408  cm_yield(0);
409  info->startup_error = 1;
410  return FE_SUCCESS;
411  }
412  if ((status = bruker_decode_status(info, str)) != FE_SUCCESS) {
413  info->startup_error = 1;
414  return FE_SUCCESS;
415  }
416 
417  // read current state of the polarity unit
418  strcpy(cmd, "POL/\r");
419  status = bruker_send_rcv(info, cmd, str, sizeof(str));
420  if (!status) {
421  cm_msg(MINFO, "bruker_init", "POL: bruker does not respond. Check power and RS232 conection, further check Lantronix.");
422  cm_yield(0);
423  info->startup_error = 1;
424  return FE_SUCCESS;
425  }
426  // extract polarity
427  status = sscanf(str, "%f", &info->bruker_polarity);
428  if (status != 1) {
429  info->startup_error = 1;
430  return FE_SUCCESS;
431  }
432  info->readback_failure = 0;
433  if (info->bruker_settings.detailed_msg) {
434  cm_msg(MINFO, "bruker_init", "POL: str='%s', polarity=%f", str, info->bruker_polarity);
435  cm_yield(0);
436  }
437 
438  cm_msg(MINFO, "bruker_init", "bruker initialized");
439  cm_yield(0);
440 
441  return FE_SUCCESS;
442 }
443 
444 //---------------------------------------------------------------------------------
455 INT bruker_out_init(HNDLE hKey, void **pinfo, INT channels, INT (*bd)(INT cmd, ...))
456 {
457  *pinfo = info;
458 
459  return FE_SUCCESS;
460 }
461 
462 //---------------------------------------------------------------------------------
472 {
473  // call EXIT function of bus driver, usually closes device
474  info->bd(CMD_EXIT, info->bd_info);
475 
476  free(info);
477 
478  return FE_SUCCESS;
479 }
480 
481 //---------------------------------------------------------------------------------
491 INT bruker_set(BRUKER_INFO *info, INT channel, float value)
492 {
493  char cmd[64], str[64];
494  INT status;
495  INT pol_tag;
496 
497  if (info->startup_error)
498  return FE_SUCCESS;
499 
500  if (!info->bd_connected) {
501  if (info->first_bd_error) {
502  info->first_bd_error = 0;
503  cm_msg(MINFO, "bruker_set",
504  "set values not possible at the moment, since the bus driver is not available!");
505  cm_yield(0);
506  }
507  }
508 
509  if (channel == BRUKER_POWER) {
510  if (value == 0.0) { // switch power off
511  strcpy(cmd, "DCP=0\r");
512  } else if (value == 1.0) { // switch power on
513  strcpy(cmd, "DCP=1\r");
514  } else {
515  cm_msg(MINFO, "bruker_set", "bruker_set: Power On=1, Power Off=0, everything else will be ignored!");
516  cm_yield(0);
517  return FE_SUCCESS;
518  }
519  status = bruker_send_rcv(info, cmd, str, sizeof(str));
520  }
521 
522  if (channel == BRUKER_DEMAND_CURRENT) {
523  // set check setpoint flag which makes sure that the setpoint is reached.
524  info->check_setpoint = TRUE;
525 
526  // keep target demand current value
527  info->bruker_target_demand = value;
528  cm_msg(MDEBUG, "bruker_set", "bruker_set: demand current = %f", value);
529 
530  // check if new demand current value has the same sign as the setting of the polarity unit
531  if (((value > 0.0) && (info->bruker_polarity == 2.0)) ||
532  ((value < 0.0) && (info->bruker_polarity == 1.0))) { // polarity switching needed
533  // set polarity switching flag
534  info->bruker_pol_switching = 1;
535  // check what polarity switching tag is needed
536  if (value > 0.0) { // positive
537  pol_tag = 0; // see Bruker manual p.34
538  } else { // negative
539  pol_tag = 1; // see Bruker manual p.34
540  }
541  // start the polarity switching
542  sprintf(cmd, "POL=%d\r", pol_tag); // polarity switching command
543  status = bruker_send_rcv(info, cmd, str, sizeof(str));
544  if (info->bruker_settings.detailed_msg) {
545  cm_msg(MINFO, "bruker_set", "bruker_set: polarity switching needed. cmd=%s", cmd);
546  cm_yield(0);
547  }
548  } else { // same polarity as before
549  // since the CUR command is only taking the absolut value, the following if is needed
550  if (value > 0.0)
551  sprintf(cmd, "CUR=%f\r", value); // set current command
552  else
553  sprintf(cmd, "CUR=%f\r", -value); // set current command
554  if (info->bruker_settings.detailed_msg) {
555  cm_msg(MINFO, "bruker_set", "bruker_set: cmd=%s", cmd);
556  cm_yield(0);
557  }
558  status = bruker_send_rcv(info, cmd, str, sizeof(str));
559  }
560  }
561 
562  return FE_SUCCESS;
563 }
564 
565 //---------------------------------------------------------------------------------
576 INT bruker_get_label_in(BRUKER_INFO *info, INT channel, char *name)
577 {
578  strcpy(name, info->bruker_settings.names_in[channel]);
579  return FE_SUCCESS;
580 }
581 
582 //---------------------------------------------------------------------------------
593 INT bruker_get_label_out(BRUKER_INFO *info, INT channel, char *name)
594 {
595  strcpy(name, info->bruker_settings.names_out[channel]);
596  return FE_SUCCESS;
597 }
598 
599 //---------------------------------------------------------------------------------
609 INT bruker_get(BRUKER_INFO *info, INT channel, float *pvalue)
610 {
611  char cmd[64], str[64];
612  INT status;
613  float fvalue, sign;
614  DWORD nowtime, difftime;
615 
616  // check if there was a startup error
617  if ( info->startup_error ) {
618  *pvalue = (float) BRUKER_INIT_ERROR;
619  ss_sleep(10); // to keep CPU load low when Run active
620  return FE_SUCCESS;
621  }
622 
623  // error timeout facility
624  nowtime = ss_time();
625  difftime = nowtime - info->lasterrtime;
626  if ( difftime > BRUKER_DELTA_TIME_ERROR ) {
627  info->errcount = 0;
628  info->lasterrtime = nowtime;
629  }
630 
631  // check if they where too many reconnection failures
632  if (info->reconnection_failures > 5) {
633  *pvalue = (float) BRUKER_READ_ERROR;
634  if (info->reconnection_failures == 6) {
635  cm_msg(MERROR, "bruker_get", "too many reconnection failures, bailing out :-(");
636  cm_yield(0);
637  info->reconnection_failures++;
638  }
639  return FE_SUCCESS;
640  }
641 
642  // if disconnected, try to reconnect after a timeout of a timeout
643  if (!info->bd_connected) {
644  if (ss_time()-info->last_reconnect > BRUKER_RECONNECTION_TIMEOUT) { // timeout expired
645  if (info->bruker_settings.detailed_msg) {
646  cm_msg(MINFO, "bruker_get", "Bruker: reconnection trial ...");
647  cm_yield(0);
648  }
649  status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
650  if (status != FE_SUCCESS) {
651  info->reconnection_failures++;
652  *pvalue = (float) BRUKER_READ_ERROR;
653  if (info->bruker_settings.detailed_msg) {
654  cm_msg(MINFO, "bruker_get", "Bruker: reconnection attempted failed");
655  cm_yield(0);
656  }
657  return FE_SUCCESS;
658  } else {
659  info->bd_connected = 1; // bus driver is connected again
660  info->last_reconnect = ss_time();
661  info->reconnection_failures = 0;
662  info->first_bd_error = 1;
663  if (info->bruker_settings.detailed_msg) {
664  cm_msg(MINFO, "bruker_get", "Bruker: successfully reconnected");
665  cm_yield(0);
666  }
667  }
668  } else { // timeout still running
669  ss_sleep(10); // in order to keep the CPU happy
670  return FE_SUCCESS;
671  }
672  }
673 
674  // check if the polarity switching is underway
675  if (info->bruker_pol_switching) {
676  // check if needed polarity is reached
677  if (((info->bruker_polarity == 1.0) && (info->bruker_target_demand >= 0.0)) ||
678  ((info->bruker_polarity == 2.0) && (info->bruker_target_demand <= 0.0))) {
679  ss_sleep(1000);
680  // since the CUR command is only taking the absolut value, the following if is needed
681  if (info->bruker_target_demand >= 0.0)
682  sprintf(cmd, "CUR=%f\r", info->bruker_target_demand); // set current command
683  else
684  sprintf(cmd, "CUR=%f\r", -info->bruker_target_demand); // set current command
685  BD_PUTS(cmd);
686  status = bruker_send_rcv(info, cmd, str, sizeof(str));
687 
688  // reset to polarity switching flag
689  info->bruker_pol_switching = 0;
690  }
691  }
692 
693  // generate read command ------------------------------------------
694  switch (channel) {
696  strcpy(cmd, "POL/\r");
697  break;
698  case BRUKER_STATUS:
699  strcpy(cmd, "STA/\r");
700  break;
702  strcpy(cmd, "CHN/\r"); // **WARNING** this is different than what the manual suggests!!
703  break;
705  strcpy(cmd, "CUR/\r"); // **WARNING** this is different than what the manual suggests!!
706  break;
708  strcpy(cmd, "VLT/\r");
709  break;
710  default:
711  return FE_SUCCESS;
712  }
713 
714  // send<->recieve -------------------------------------------------
715  status = bruker_send_rcv(info, cmd, str, sizeof(str));
716 
717  if (info->bruker_settings.detailed_msg) {
718  cm_msg(MINFO,"bruker_get","%s status = %d, received string = %s", cmd, status, str);
719  cm_yield(0);
720  }
721  if (!status) {
722  if (info->errcount < BRUKER_MAX_ERROR) {
723 /* as, 2016/07/26
724  cm_msg(MERROR, "bruker_get",
725  "CHN bruker does not respond. Check power and RS232 connection, further check Lantronix.");
726  cm_yield(0);
727 */
728  info->errcount++;
729  }
730 
731  info->readback_failure++;
732 
734  info->readback_failure = 0;
735  // try to disconnect and reconnect the bus driver
736  if ((ss_time()-info->last_reconnect > BRUKER_RECONNECTION_TIMEOUT) && info->bd_connected) {
737  info->bd(CMD_EXIT, info->bd_info); // disconnect bus driver
738  if (info->bruker_settings.detailed_msg) {
739  cm_msg(MINFO, "bruker_get", "Bruker: try to disconnect and reconnect the bus driver");
740  cm_yield(0);
741  }
742  info->last_reconnect = ss_time();
743  info->bd_connected = 0;
744  if (info->bruker_settings.ets_in_use)
746  }
747  }
748  return FE_SUCCESS;
749  } else {
750  info->errcount = 0;
751  }
752 
753  // decode reply string ---------------------------------------------------------------
754  // handle status messages
755  if (channel == BRUKER_STATUS)
756  bruker_decode_status(info, str);
757 
758  if (info->bruker_settings.detailed_msg) {
759  cm_msg(MINFO, "bruker_get", "bruker_get: channel=%d, str=%s", channel, str);
760  cm_yield(0);
761  }
762 
763  switch (channel) {
765  case BRUKER_STATUS:
766  status = sscanf(str, "%f", &fvalue);
767  if (!status) {
768  info->readback_failure++;
769  return FE_SUCCESS;
770  }
771  break;
775  // reply string has the form "+ 3.45", hence ...
776  if (str[0] == '+')
777  sign = 1.0;
778  else if (str[0] == '-')
779  sign = -1.0;
780  else
781  return FE_SUCCESS;
782  status = sscanf(&str[1], "%f", &fvalue);
783  if (!status) {
784  info->readback_failure++;
785  return FE_SUCCESS;
786  }
787  fvalue *= sign;
788  break;
789  default:
790  return FE_SUCCESS;
791  }
792 
793  // keep the current polarity
794  if (channel == BRUKER_POLARITY_READBACK)
795  info->bruker_polarity = fvalue;
796 
797  // new valid value
798  *pvalue = fvalue;
799 
800  // reset readback error counter
801  info->readback_failure = 0;
802 
803  // check new setpoint
804  if (info->check_setpoint) {
805  info->check_setpoint_timer = ss_time(); // start timer for checking
806  info->check_setpoint = FALSE;
807  } else {
808  if (nowtime - info->check_setpoint_timer > 120) {
809  if (channel == BRUKER_OUTPUT_CURRENT) {
810  if (fabs(info->bruker_target_demand - *pvalue) > 1.0) {
811  cm_msg(MDEBUG, "bruker_get", "need to call bruker_set: demand=%f, measured=%f", info->bruker_target_demand, *pvalue);
813  }
814  }
815  }
816  }
817 
818  return FE_SUCCESS;
819 }
820 
821 /*---- device driver entry point -----------------------------------*/
822 INT bruker_in(INT cmd, ...)
823 {
824 va_list argptr;
825 HNDLE hKey;
826 INT channel, status;
827 float *pvalue;
828 void *info, *bd;
829 char *name;
830 DWORD flags;
831 
832  va_start(argptr, cmd);
833  status = FE_SUCCESS;
834 
835  switch (cmd) {
836  case CMD_INIT:
837  hKey = va_arg(argptr, HNDLE);
838  info = va_arg(argptr, void *);
839  channel = va_arg(argptr, INT);
840  flags = va_arg(argptr, DWORD);
841  bd = va_arg(argptr, void *);
842  status = bruker_in_init(hKey, info, channel, bd);
843  break;
844 
845  case CMD_EXIT:
846  info = va_arg(argptr, void *);
847  status = bruker_exit(info);
848  break;
849 
850  case CMD_GET:
851  info = va_arg(argptr, void *);
852  channel = va_arg(argptr, INT);
853  pvalue = va_arg(argptr, float*);
854  status = bruker_get(info, channel, pvalue);
855  break;
856 
857  case CMD_GET_LABEL:
858  info = va_arg(argptr, void *);
859  channel = va_arg(argptr, INT);
860  name = va_arg(argptr, char *);
861  status = bruker_get_label_in(info, channel, name);
862  break;
863 
864  default:
865  break;
866  }
867 
868  va_end(argptr);
869 
870  return status;
871 }
872 
873 //---------------------------------------------------------------------------------
874 INT bruker_out(INT cmd, ...)
875 {
876 va_list argptr;
877 HNDLE hKey;
878 INT channel, status;
879 float value;
880 void *info, *bd;
881 char *name;
882 DWORD flags;
883 
884  va_start(argptr, cmd);
885  status = FE_SUCCESS;
886 
887  switch (cmd) {
888  case CMD_INIT:
889  hKey = va_arg(argptr, HNDLE);
890  info = va_arg(argptr, void *);
891  channel = va_arg(argptr, INT);
892  flags = va_arg(argptr, DWORD);
893  bd = va_arg(argptr, void *);
894  status = bruker_out_init(hKey, info, channel, bd);
895  break;
896 
897  case CMD_GET_LABEL:
898  info = va_arg(argptr, void *);
899  channel = va_arg(argptr, INT);
900  name = va_arg(argptr, char *);
901  status = bruker_get_label_out(info, channel, name);
902  break;
903 
904  case CMD_SET:
905  info = va_arg(argptr, void *);
906  channel = va_arg(argptr, INT);
907  value = (float) va_arg(argptr, double);
908  status = bruker_set(info, channel, value);
909  break;
910 
911  default:
912  break;
913  }
914 
915  va_end(argptr);
916 
917  return status;
918 }
919 //---------------------------------------------------------------------------------
DWORD last_reconnect
timer for bus driver reconnect error handling
Definition: bruker.c:124
float bruker_polarity
keeps the current polarity tag: 1=pos, 2=neg
Definition: bruker.c:115
#define BRUKER_ERR_PHASE
tag: on off the line phases might be missing (see Bruker &quot;Description of B-EC 1&quot;, p...
Definition: bruker.c:45
INT bruker_in_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
Definition: bruker.c:327
INT bruker_out_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
Definition: bruker.c:455
INFO info
Definition: vme_fe.c:206
HNDLE hkey
ODB key for bus driver info.
Definition: bruker.c:113
#define BRUKER_ETS_LOGOUT_SLEEP
sleep time (us) between the telnet commands of the ets_logout
Definition: bruker.c:39
DWORD lasterrtime
last error time stamp
Definition: bruker.c:122
INT bruker_pol_switching
flag showing that the polarity is switching
Definition: bruker.c:116
#define BRUKER_DELTA_TIME_ERROR
reset error counter after BRUKER_DELTA_TIME_ERROR seconds
Definition: bruker.c:75
DWORD check_setpoint_timer
timer needed to check the setpoint current
Definition: bruker.c:118
float bruker_target_demand
keeps the target demand current value: needed if polarity switching is needed
Definition: bruker.c:117
#define BRUKER_STATUS
Definition: bruker.h:13
INT errcount
error counter in order not to flood the message queue
Definition: bruker.c:120
#define BRUKER_MAX_ERROR
maximum number of error messages
Definition: bruker.c:73
#define BRUKER_ERR_TEMP
tag: internal overheating protection for the bruker (see Bruker &quot;Description of B-EC 1&quot;...
Definition: bruker.c:47
#define BRUKER_ERR_CURR
tag: overcurrent protection
Definition: bruker.c:57
#define BRUKER_DEMAND_CURRENT
Definition: bruker.h:20
INT bruker_get_label_in(BRUKER_INFO *info, INT channel, char *name)
Definition: bruker.c:576
#define BRUKER_IN_CHS
number of input channels
Definition: bruker.c:79
INT bruker_send_rcv(BRUKER_INFO *info, char *cmd, char *str, int size)
Definition: bruker.c:139
#define BRUKER_MAX_READBACK_FAILURE
maximum number of readback failures before a reconnect will take place
Definition: bruker.c:33
#define BRUKER_OUTPUT_VOLTAGE
Definition: bruker.h:16
int bd_connected
flag showing if bus driver is connected
Definition: bruker.c:111
INT(* bd)(INT cmd,...)
bus driver entry function
Definition: bruker.c:109
#define BRUKER_POWER
Definition: bruker.h:19
#define BRUKER_POLARITY_READBACK
Definition: bruker.h:12
BRUKER_SETTINGS bruker_settings
stores the internal DD settings
Definition: bruker.c:108
char names_out[BRUKER_OUT_CHS][NAME_LENGTH]
Names of the output channels as found in the ODB.
Definition: bruker.c:88
INT readback_failure
counts the number of readback failures
Definition: bruker.c:123
int ets_logout(void *info, int wait, int detailed_msg)
Definition: ets_logout.c:113
INT detailed_msg
flag indicating if detailed status/error messages are wanted
Definition: bruker.c:85
HNDLE hKey
Definition: write_summary.c:97
This structure contains private variables for the device driver.
Definition: bruker.c:107
#define BRUKER_OUTPUT_CURRENT
Definition: bruker.h:15
INT bruker_in(INT cmd,...)
Definition: bruker.c:822
char names_in[BRUKER_IN_CHS][NAME_LENGTH]
Names of the input channels as found in the ODB.
Definition: bruker.c:87
#define BRUKER_SETTINGS_STR
Initializing string for the struct BRUKER_SETTINGS.
Definition: bruker.c:92
#define BRUKER_MAX_READ
maximal number for reading retries
Definition: bruker.c:27
HNDLE hDB
Definition: write_summary.c:97
INT bruker_get(BRUKER_INFO *info, INT channel, float *pvalue)
Definition: bruker.c:609
INT ets_in_use
flag indicating if the rs232 terminal server is in use
Definition: bruker.c:86
#define BRUKER_ERR_GND
tag: ground relay has tripped due to a ground voltage exeeding about 10 volt (see Bruker &quot;Description...
Definition: bruker.c:53
#define BRUKER_STATUS_DCPWRON
tag: ??
Definition: bruker.c:68
void * bd_info
private info of bus driver
Definition: bruker.c:110
#define BRUKER_RECONNECTION_TIMEOUT
timeout in (sec) between logout terminal server an reconnection trial
Definition: bruker.c:36
#define BRUKER_ERR_WATER
tag: cooling water for the bruker is missing (see Bruker &quot;Description of B-EC 1&quot;, p...
Definition: bruker.c:43
#define BRUKER_OUT_CHS
number of output channels
Definition: bruker.c:81
#define BRUKER_DEMAND_CURRENT_READBACK
Definition: bruker.h:14
int reconnection_failures
how often reconnection failed
Definition: bruker.c:125
INT bruker_set(BRUKER_INFO *info, INT channel, float value)
Definition: bruker.c:491
#define BRUKER_ERR_EXT1
tag: monitoring tag of the water guard of the magnet hooked up to the bruker
Definition: bruker.c:49
INT bruker_out(INT cmd,...)
Definition: bruker.c:874
#define BRUKER_TIME_OUT
timeout in (ms) for the communication between pc and bruker
Definition: bruker.c:30
#define BRUKER_ERR_EXT2
tag: unused
Definition: bruker.c:55
#define BRUKER_READ_ERROR
tag: read error
Definition: bruker.c:25
INT bruker_exit(BRUKER_INFO *info)
Definition: bruker.c:471
INT bruker_get_label_out(BRUKER_INFO *info, INT channel, char *name)
Definition: bruker.c:593
BOOL check_setpoint
flag needed to check the setpoint
Definition: bruker.c:119
INT bruker_decode_status(BRUKER_INFO *info, char *str)
Definition: bruker.c:178
int first_bd_error
flag showing if the bus driver error message is already given
Definition: bruker.c:112
INT bruker_remote
1=remote, 0=local
Definition: bruker.c:114
Stores all the parameters the device driver needs.
Definition: bruker.c:84
#define BRUKER_STATUS_REMOTE
tag: bruker on remote
Definition: bruker.c:60
#define BRUKER_INIT_ERROR
tag: initializing error
Definition: bruker.c:24
INT startup_error
initializer error tag, if set, bruker_get and bruker_set won&#39;t do anything
Definition: bruker.c:121
#define BRUKER_ERR_DOOR
tag: door at the back of the bruker is open
Definition: bruker.c:51