Low-Energy Muon (LEM) Experiment  0.5.1
danfysik.c
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------
2 
3  Name: danfysik.c
4  Created by: Andreas Suter 2005/02/28
5 
6  Contents: device driver for danfysik magnet power supply.
7 
8  RS232: 9600 baud, 8 data bits, 1 stop bit, no parity,
9  protocol: CTS (hardware), termination \r (CR)
10 
11 ----------------------------------------------------------------------------*/
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <math.h>
18 #include "midas.h"
19 #include "danfysik.h"
20 
21 #include "ets_logout.h"
22 
24 #define DANFYSIK_INIT_ERROR -2
25 #define DANFYSIK_READ_ERROR -1
27 #define DANFYSIK_TIME_OUT 2000
29 #define DANFYSIK_RECONNECTION_TIMEOUT 10
31 
33 #define DANFYSIK_IN_CH 5
34 #define DANFYSIK_OUT_CH 4
36 
38 #define DANFYSIK_ETS_LOGOUT_SLEEP 10000
39 
40 /* --------- to handle error messages ------------------------------*/
42 #define DANFYSIK_MAX_READBACK_FAILURE 5
43 #define DANFYSIK_MAX_EMPTY_READBACK_ERR 10
45 #define DELTA_TIME_ERROR 3600
47 
48 /*---- danfysik status decoding tags ---------------------------------*/
49 #define DANFYSIK_STATUS_OFF 0x800000
50 #define DANFYSIK_STATUS_LOCAL 0x400000
51 #define DANFYSIK_INTERLOCK_EXT_4 0x200000
52 #define DANFYSIK_SPARE_1 0x100000
53 #define DANFYSIK_SPARE_2 0x080000
54 #define DANFYSIK_SPARE_3 0x040000
55 #define DANFYSIK_PERCENTAGE 0x020000
56 #define DANFYSIK_INTERLOCK_EXT_1 0x010000
57 #define DANFYSIK_STATUS_STANDBY 0x008000
58 #define DANFYSIK_INTERLOCK_SUM 0x004000
59 #define DANFYSIK_INTERLOCK_DC_OVER_CURRENT 0x002000
60 #define DANFYSIK_INTERLOCK_OVER_VOLTAGE_PROTECTION 0x001000
61 #define DANFYSIK_STATUS_ON 0x000800
62 #define DANFYSIK_INTERLOCK_EXT_2 0x000400
63 #define DANFYSIK_INTERLOCK_MAINS_FAILURE 0x000200
64 #define DANFYSIK_STATUS_CURRENT_LIMIT 0x000100
65 #define DANFYSIK_INTERLOCK_EARTH_LEAKAGE_FAILURE 0x000080
66 #define DANFYSIK_INTERLOCK_CONVERTER_OVER_VOLTAGE 0x000040
67 #define DANFYSIK_INTERLOCK_MPS_OVERTEMPERATURE 0x000020
68 #define DANFYSIK_SPARE_4 0x000010
69 #define DANFYSIK_SPARE_5 0x000008
70 #define DANFYSIK_INTERLOCK_EXT_3 0x000004
71 #define DANFYSIK_STATUS_MPS_NOT_READY 0x000002
72 #define DANFYSIK_INTERLOCK_MPS_FAN_FAULT 0x000001
73 
75 typedef struct {
77  INT ets_in_use;
78  char in_names[DANFYSIK_IN_CH][NAME_LENGTH];
79  char out_names[DANFYSIK_OUT_CH][NAME_LENGTH];
80  float max_current;
81  float max_voltage;
82  DWORD next_read;
84 
86 #define DANFYSIK_SETTINGS_STR "\
87 Detailed Messages = INT : 0\n\
88 ETS_IN_USE = INT : 1\n\
89 Input Names = STRING[5] : \n\
90 [32] Remote (read back)\n\
91 [32] Current Set Value (A) (readback)\n\
92 [32] Output Voltage (V)\n\
93 [32] Output Current (A)\n\
94 [32] Status\n\
95 Output Names = STRING[4] : \n\
96 [32] Remote\n\
97 [32] State (0 off, 1 on, 2 reset)\n\
98 [32] Set Current (A)\n\
99 [32] Current Limit (A)\n\
100 Max. Current = FLOAT : 20.f\n\
101 Max. Voltage = FLOAT : 75.f\n\
102 Next Read Attempt (ms) = DWORD : 75\n\
103 "
104 
107 typedef struct {
110  INT (*bd)(INT cmd, ...);
111  void *bd_info;
114  HNDLE hDB;
115  HNDLE hkey;
118  INT errcount;
122  DWORD lasterrtime;
123  float last_valid_value[DANFYSIK_IN_CH];
127  DWORD time_to_read;
128 } DANFYSIK_INFO;
129 
131 
132 /*---- support routines --------------------------------------------*/
141 void danfysik_strip_rubbish(char *str_in, char *str_clean)
142 {
143  int i;
144 
145  for (i=0; i<strlen(str_in); i++)
146  if ((str_in[i]>=32) && (str_in[i]<=126))
147  break;
148 
149  strcpy(str_clean, str_in+i);
150 }
151 
152 /*------------------------------------------------------------------*/
164 INT danfysik_error_read(int channel, char *str)
165 {
166  int error;
167  char err_msg[128];
168 
169  // because sometimes not the whole string is given
170  error = 0;
171  if (channel == 0) { // CMD
172  if (strlen(str) != 6)
173  error = 1;
174  } else if (channel == 1) { // RA
175  if (strlen(str) != 8)
176  error = 1;
177  } else if ((channel > 1) && (channel < 4)) { // AD 2, AD 8
178  if (((str[0] != '+') && (str[0] != '-')) || strlen(str) != 8) // read back error
179  error = 1;
180  } else { // S1H
181  if (strlen(str) != 8)
182  error = 1;
183  }
184 
185  if (error) {
186  info->empty_readback_error++;
187  return 1;
188  }
189 
190  error = 0;
191  if (str[0]=='?') { // error
192  strcpy(err_msg, "Communication/Command Error");
193  info->errcount++;
195  cm_msg(MERROR, "danfysik_error_read", err_msg);
196  return 1;
197  } else
198  return 0;
199 }
200 
201 /*------------------------------------------------------------------*/
208 void danfysik_decode_status(DANFYSIK_INFO *info, char *str)
209 {
210  int status;
211 
212  if (strlen(str)==0) {
213  info->empty_readback_error++;
214  return;
215  }
216 
217  sscanf(str, "%x", &status);
218 
219  // for debugging only, needs to be removed asap
220  if ((str[0] == '-') || (str[0] == '+')) {
221  return;
222  }
223 
224  // for debugging only, needs to be removed asap
225 /*
226  if (status & 0x21F7FF)
227  cm_msg(MDEBUG, "danfysik_decode_status", "debug> str='%s', status=%d", str, status);
228 */
229 
230  if (status & DANFYSIK_STATUS_OFF) {
231  if (!(info->danfysik_status & DANFYSIK_STATUS_OFF)) // previous status != DANFYSIK_STATUS_OFF
232  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Status changed to Off.");
233  }
234 
235  if (status & DANFYSIK_STATUS_LOCAL) {
236  if (!(info->danfysik_status & DANFYSIK_STATUS_LOCAL)) // previous status != DANFYSIK_STATUS_LOCAL
237  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Status changed to Local.");
238  }
239 
240  if (status & DANFYSIK_INTERLOCK_EXT_4) {
241  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_EXT_4)) // previous status != DANFYSIK_INTERLOCK_EXT_4
242  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Ext Interlock 4 fired.");
243  }
244 
245  if (status & DANFYSIK_PERCENTAGE) {
246  if (!(info->danfysik_status & DANFYSIK_PERCENTAGE)) // previous status != DANFYSIK_PERCENTAGE
247  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Shows Percentage instead of A/V.");
248  }
249 
250  if (status & DANFYSIK_INTERLOCK_EXT_1) {
251  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_EXT_1)) // previous status != DANFYSIK_INTERLOCK_EXT_1
252  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Ext Interlock 1 (Magnet Thermo Switch) fired.");
253  }
254 
255  if (status & DANFYSIK_STATUS_STANDBY) {
256  if (!(info->danfysik_status & DANFYSIK_STATUS_STANDBY)) // previous status != DANFYSIK_STATUS_STANDBY
257  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Status changed to Standby Mode.");
258  }
259 
260  if (status & DANFYSIK_INTERLOCK_DC_OVER_CURRENT) {
261  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_DC_OVER_CURRENT)) // previous status != DANFYSIK_INTERLOCK_DC_OVER_CURRENT
262  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: DC Over Current Interlock fired.");
263  }
264 
266  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_OVER_VOLTAGE_PROTECTION)) // previous status != DANFYSIK_INTERLOCK_OVER_VOLTAGE_PROTECTION
267  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Over Voltage Protection Interlock fired.");
268  }
269 
270  if (status & DANFYSIK_STATUS_ON) {
271  if (!(info->danfysik_status & DANFYSIK_STATUS_ON)) // previous status != DANFYSIK_STATUS_ON
272  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Status changed to On.");
273  }
274 
275  if (status & DANFYSIK_INTERLOCK_EXT_2) {
276  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_EXT_2)) // previous status != DANFYSIK_INTERLOCK_EXT_2
277  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Ext Interlock 2 fired.");
278  }
279 
280  if (status & DANFYSIK_INTERLOCK_MAINS_FAILURE) {
281  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_MAINS_FAILURE)) // previous status != DANFYSIK_INTERLOCK_MAINS_FAILURE
282  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Mains Failure Interlock fired.");
283  }
284 
285  if (status & DANFYSIK_STATUS_CURRENT_LIMIT) {
286  if (!(info->danfysik_status & DANFYSIK_STATUS_CURRENT_LIMIT)) // previous status != DANFYSIK_STATUS_CURRENT_LIMIT
287  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: At Current Limit.");
288  }
289 
291  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_EARTH_LEAKAGE_FAILURE)) // previous status != DANFYSIK_INTERLOCK_EARTH_LEAKAGE_FAILURE
292  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Earth Leakage Failure Interlock fired.");
293  }
294 
296  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_CONVERTER_OVER_VOLTAGE)) // previous status != DANFYSIK_INTERLOCK_CONVERTER_OVER_VOLTAGE
297  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Converter Over Voltage Interlock fired.");
298  }
299 
301  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_MPS_OVERTEMPERATURE)) // previous status != DANFYSIK_INTERLOCK_MPS_OVERTEMPERATURE
302  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: MPS Overtemperature Interlock fired.");
303  }
304 
305  if (status & DANFYSIK_INTERLOCK_EXT_3) {
306  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_EXT_3)) // previous status != DANFYSIK_INTERLOCK_EXT_3
307  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Ext Interlock 3 fired.");
308  }
309 
310  if (status & DANFYSIK_STATUS_MPS_NOT_READY) {
311  if (!(info->danfysik_status & DANFYSIK_STATUS_MPS_NOT_READY)) // previous status != DANFYSIK_STATUS_MPS_NOT_READY
312  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: Status changed to MPS not ready.");
313  }
314 
315  if (status & DANFYSIK_INTERLOCK_MPS_FAN_FAULT) {
316  if (!(info->danfysik_status & DANFYSIK_INTERLOCK_MPS_FAN_FAULT)) // previous status != DANFYSIK_INTERLOCK_MPS_FAN_FAULT
317  cm_msg(MINFO, "danfysik_decode_status", "Danfysik Power Supply: MPS Fan Fault Interlock fired.");
318  }
319 
320  info->danfysik_status = status;
321 }
322 
323 /*---- device driver routines --------------------------------------*/
337 INT danfysik_in_init(HNDLE hKey, void **pinfo, INT channels, INT (*bd)(INT cmd, ...))
338 {
339  INT status, size;
340  char str[256], str2[256], str3[256], str_clean[256];
341  HNDLE hDB, hkeydd;
342 
343  // allocate info structure
344  info = calloc(1, sizeof(DANFYSIK_INFO));
345  *pinfo = info;
346 
347  cm_get_experiment_database(&hDB, NULL);
348 
349  // create Danfysik settings record
350  status = db_create_record(hDB, hKey, "DD", DANFYSIK_SETTINGS_STR);
351  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
352  cm_msg(MERROR, "danfysik_init", "danfysik_init: Error creating Danfysik DD record in ODB, status=%d", status);
353  cm_yield(0);
354  return FE_ERR_ODB;
355  }
356 
357  db_find_key(hDB, hKey, "DD", &hkeydd);
358  size = sizeof(info->danfysik_settings);
359  db_get_record(hDB, hkeydd, &info->danfysik_settings, &size, 0);
360 
361  // initialize driver
362  info->num_channels = channels;
363  info->bd = bd;
364  info->hDB = hDB;
365  info->hkey = hKey;
366  info->errcount = 0;
367  info->startup_error = 0;
368  info->lasterrtime = ss_time();
369  info->danfysik_status = 0;
370  info->empty_readback_error = 0;
371  info->readback_failure = 0;
372  info->last_reconnect = ss_time();
373  info->reconnection_failures = 0;
374  info->first_bd_error = 1;
375  info->soft_current_limit = +999.0;
376  info->time_to_read = ss_millitime();
377 
378  if (!bd)
379  return FE_ERR_ODB;
380 
381  // initialize bus driver
382  status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
383  if (status != SUCCESS) {
384  info->startup_error = 1;
385  info->bd_connected = FALSE;
386  return status;
387  }
388  info->bd_connected = TRUE;
389 
390  // initialize Danfysik
391  cm_msg(MINFO, "danfysik_init", "initialize danfysik.");
392  cm_yield(0);
393  BD_PUTS("VER\r");
394  status = BD_GETS(str, sizeof(str), "\r", DANFYSIK_TIME_OUT);
395  status = BD_GETS(str2, sizeof(str), "\r", DANFYSIK_TIME_OUT);
396  status = BD_GETS(str3, sizeof(str), "\r", DANFYSIK_TIME_OUT);
397  if (status < 0) {
398  info->startup_error = 1;
399  return FE_SUCCESS;
400  }
401  cm_msg(MINFO, "danfysik_init", "danfysik sw version:\r %s %s %s", str, str2, str3);
402  cm_yield(0);
403 
404  // check if local or remote
405  BD_PUTS("CMD\r");
406  status = BD_GETS(str, sizeof(str), "\r", DANFYSIK_TIME_OUT);
407  danfysik_strip_rubbish(str, str_clean);
408  if (strstr(str_clean, "LOC")) { // in local mode
409  info->danfysik_remote = 0;
410  cm_msg(MINFO, "danfysik_init", "danfysik power supply not in remote mode.");
411  cm_yield(0);
412  } else if (strstr(str_clean, "REM")) { // in remote mode
413  info->danfysik_remote = 1;
414  } else { // error
415  info->startup_error = 1;
416  if (info->danfysik_settings.detailed_msg) {
417  cm_msg(MINFO, "danfysik_init", "danfysik read problem: %s", str_clean);
418  cm_yield(0);
419  }
420  return FE_SUCCESS;
421  }
422 
423  if (info->danfysik_settings.detailed_msg) {
424  cm_msg(MINFO, "danfysik_init", "danfysik set to %s", str_clean);
425  cm_yield(0);
426  }
427 
428  // check status
429  memset(str, 0, sizeof(str));
430  BD_PUTS("S1H\r");
431  status = BD_GETS(str, sizeof(str), "\r", DANFYSIK_TIME_OUT);
432  danfysik_strip_rubbish(str, str_clean);
433  danfysik_decode_status(info, str_clean);
434 
435  if (info->danfysik_settings.detailed_msg) {
436  cm_msg(MINFO, "danfysik_init", "danfysik startup status to %s", str);
437  cm_yield(0);
438  }
439 
440  return FE_SUCCESS;
441 }
442 
443 /*----------------------------------------------------------------------------*/
455 INT danfysik_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  return FE_SUCCESS;
478 }
479 
480 /*----------------------------------------------------------------------------*/
490 INT danfysik_set(DANFYSIK_INFO *info, INT channel, float value)
491 {
492  char str[128], str_clean[128];
493  INT ivalue;
494  INT status;
495 
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, "danfysik_set",
504  "set values not possible at the moment, since the bus driver is not available!");
505  }
506  }
507 
508  switch (channel) {
509  case 0: // local/remote
510  if (value == 0) { // switch to local
511  if (info->danfysik_remote != 0) // not already in local mode
512  strcpy(str, "LOC\r");
513  else // nothing to be done
514  return FE_SUCCESS;
515  } else if (value == 1) { // switch to remote
516  if (info->danfysik_remote != 1) // not already in remote mode
517  strcpy(str, "REM\r");
518  else // nothing to be done
519  return FE_SUCCESS;
520  } else { // value out of range, hence ignore it
521  return FE_SUCCESS;
522  }
523  BD_PUTS(str); // send command
524  info->danfysik_remote = value; // keep value
525  break;
526  case 1: // on/off/reset
527  switch ((int)value) {
528  case 0: // off
529  strcpy(str, "F\r");
530  break;
531  case 1: // on
532  strcpy(str, "N\r");
533  break;
534  case 2: // reset
535  strcpy(str, "RS\r");
536  break;
537  default: // value out of range, hence ignore it
538  return FE_SUCCESS;
539  }
540  BD_PUTS(str);
541  break;
542  case 2: // set current
543  if (value > info->soft_current_limit) {
544  cm_msg(MERROR, "danfysik_set", "Set current value %f > soft current limit %f! Will set soft current limit.",
545  value, info->soft_current_limit);
546  ivalue = (INT)(info->soft_current_limit*1.0e3);
547  } else {
548  ivalue = (INT)(value*1.0e3);
549  }
550  if (ivalue > 0)
551  sprintf(str, "DA 0,+0%d\r", ivalue);
552  else
553  sprintf(str, "DA 0,-0%d\r", abs(ivalue));
554 
555  BD_PUTS(str);
556  status = BD_GETS(str, sizeof(str), "\r", 200);
557  danfysik_strip_rubbish(str, str_clean);
558  if (strstr(str_clean, "?")) { // wrong command mode
560  cm_msg(MERROR, "danfysik_set", "set current: Wrong command mode (local/remote)!");
561  }
562  break;
563  case 3: // set soft-current limit
564  info->soft_current_limit = value; // keep soft current limit
565  break;
566  default:
567  return FE_SUCCESS;
568  }
569 
570  return FE_SUCCESS;
571 }
572 
573 /*----------------------------------------------------------------------------*/
584 INT danfysik_in_get_label(DANFYSIK_INFO *info, INT channel, char *name)
585 {
586  strcpy(name, info->danfysik_settings.in_names[channel]);
587  return FE_SUCCESS;
588 }
589 
590 /*----------------------------------------------------------------------------*/
601 INT danfysik_out_get_label(DANFYSIK_INFO *info, INT channel, char *name)
602 {
603  strcpy(name, info->danfysik_settings.out_names[channel]);
604  return FE_SUCCESS;
605 }
606 
607 /*-----------------------------------------------------------------------------*/
617 INT danfysik_get(DANFYSIK_INFO *info, INT channel, float *pvalue)
618 {
619  char str[128], cmd[128], str_clean[128];
620  INT status, size;
621  INT value;
622  DWORD now, nowtime, difftime;
623  HNDLE hkey;
624 
625  now = ss_millitime();
626  if (now - info->time_to_read < info->danfysik_settings.next_read) {
627  ss_sleep(10);
628  return FE_SUCCESS;
629  }
630  info->time_to_read = now;
631 
632  // error timeout facility
633  nowtime = ss_time();
634  difftime = nowtime - info->lasterrtime;
635  if ( difftime > DELTA_TIME_ERROR ) {
636  info->errcount = 0;
637  info->lasterrtime = ss_time();
638  }
639 
640  // check if there was a startup error
641  if ( info->startup_error ) {
642  *pvalue = (float) DANFYSIK_INIT_ERROR;
643  ss_sleep(10); // to keep CPU load low when Run active
644  return FE_SUCCESS;
645  }
646 
647  if (info->reconnection_failures > 5) {
648  *pvalue = (float) DANFYSIK_READ_ERROR;
649  if (info->reconnection_failures == 6) {
651  cm_msg(MERROR, "danfysik_get", "too many reconnection failures, bailing out :-(");
652  info->reconnection_failures++;
653  }
654  return FE_SUCCESS;
655  }
656 
657  // if disconnected, try to reconnect after a timeout of a timeout
658  if (!info->bd_connected) {
659  if (ss_time()-info->last_reconnect > DANFYSIK_RECONNECTION_TIMEOUT) { // timeout expired
661  cm_msg(MINFO, "danfysik_get", "Danfysik: reconnection trial ...");
662  status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
663  if (status != FE_SUCCESS) {
664  info->reconnection_failures++;
665  *pvalue = (float) DANFYSIK_READ_ERROR;
667  cm_msg(MINFO, "danfysik_get", "Danfysik: reconnection attempted failed");
668  return FE_ERR_HW;
669  } else {
670  info->bd_connected = 1; // bus driver is connected again
671  info->last_reconnect = ss_time();
672  info->reconnection_failures = 0;
673  info->first_bd_error = 1;
675  cm_msg(MINFO, "danfysik_get", "Danfysik: successfully reconnected");
676  }
677  } else { // timeout still running
678  *pvalue = (float) info->last_valid_value[channel];
679  return FE_SUCCESS;
680  }
681  }
682 
683  if (info->soft_current_limit == +999.0) { // soft current limit not set so far
684  // get soft current limit from ODB
685  db_find_key(info->hDB, 0, "/Equipment/Danfysik/Variables/Output", &hkey);
686  size = sizeof(info->soft_current_limit);
687  status = db_get_data_index(info->hDB, hkey, &info->soft_current_limit, &size, 3, TID_FLOAT);
688  if (status != DB_SUCCESS) {
689  cm_msg(MERROR, "danfysik_init", "danfysik_init: Error reading Danfysik soft current limit, status=%d", status);
690  info->soft_current_limit = 20.0;
691  }
692  }
693 
694  // get command
695  switch (channel) {
696  case 0: // read if local or remote
697  strcpy(cmd, "CMD\r");
698  break;
699  case 1: // read set value
700  strcpy(cmd, "RA\r");
701  break;
702  case 2: // read output voltage
703  strcpy(cmd, "AD 2\r");
704  break;
705  case 3: // read output current
706  strcpy(cmd, "AD 8\r");
707  break;
708  case 4: // read status
709  strcpy(cmd, "S1H\r");
710  break;
711  default:
712  *pvalue = (float) DANFYSIK_READ_ERROR;
713  return FE_SUCCESS;
714  }
715 
716  memset(str, 0, sizeof(str));
717  BD_PUTS(cmd);
718  status = BD_GETS(str, sizeof(str), "\r", DANFYSIK_TIME_OUT);
719  danfysik_strip_rubbish(str, str_clean);
720 
721  if (danfysik_error_read(channel, str_clean)) {
722  *pvalue = info->last_valid_value[channel];
724  cm_msg(MERROR, "danfysik_get", "danfysik_get: cannot get any readback anymore! Check device!");
725  *pvalue = (float) DANFYSIK_READ_ERROR;
726  }
727 
728  info->readback_failure++;
729 
731  info->readback_failure = 0; // reset counter
732  // try to disconnect and reconnect the bus driver
733  if ((ss_time()-info->last_reconnect > DANFYSIK_RECONNECTION_TIMEOUT) && info->bd_connected) {
734  info->bd(CMD_EXIT, info->bd_info); // disconnect bus driver
736  cm_msg(MINFO, "danfysik_get", "Danfysik: try to disconnect and reconnect the bus driver");
737  info->last_reconnect = ss_time();
738  info->bd_connected = 0;
739  if (info->danfysik_settings.ets_in_use)
741  }
742  }
743  return FE_SUCCESS;
744  }
745 
746  // decode readback
747  switch (channel) {
748  case 0: // local or remote
749  if (strstr(str_clean, "LOC"))
750  *pvalue = 0.f;
751  else if (strstr(str_clean, "REM"))
752  *pvalue = 1.f;
753  else
754  *pvalue = (float) DANFYSIK_READ_ERROR;
755  info->danfysik_remote = *pvalue;
756  break;
757  case 1: // read set value
758  sscanf(str_clean, "%d", &value);
759  // read polarity
760  strcpy(cmd, "PO\r");
761  BD_PUTS(cmd);
762  status = BD_GETS(str, sizeof(str), "\r", DANFYSIK_TIME_OUT);
763  danfysik_strip_rubbish(str, str_clean);
764  if (strstr(str_clean, "+"))
765  *pvalue = (float)value/1.0e3;
766  else
767  *pvalue = -1.0*(float)value/1.0e3;
768  break;
769  case 2: // read output voltage
770  sscanf(str_clean, "%d", &value);
771  *pvalue = (float)value/1.0e2;
772  break;
773  case 3: // read output current
774  sscanf(str_clean, "%d", &value);
775  *pvalue = (float)value/1.0e3;
776  break;
777  case 4: // read status
778  sscanf(str_clean, "%d", &value);
779  *pvalue = (float)value;
780  break;
781  default:
782  *pvalue = (float) DANFYSIK_READ_ERROR;
783  return FE_SUCCESS;
784  }
785  info->last_valid_value[channel] = *pvalue; // keep the last valid value
786  info->empty_readback_error = 0; // reset empty readback error counter
787  info->readback_failure = 0; // reset readback failure error counter
788 
789  // read and decode status at each cycle
790  memset(str, 0, sizeof(str));
791  BD_PUTS("S1H\r");
792  status = BD_GETS(str, sizeof(str), "\r", DANFYSIK_TIME_OUT);
793  danfysik_strip_rubbish(str, str_clean);
794  if (danfysik_error_read(4, str_clean)) {
795  return FE_SUCCESS;
796  } else {
797  danfysik_decode_status(info, str_clean);
798  }
799 
800  return FE_SUCCESS;
801 }
802 
803 /*---- device driver entry point -----------------------------------*/
804 INT danfysik_in(INT cmd, ...)
805 {
806 va_list argptr;
807 HNDLE hKey;
808 INT channel, status;
809 float *pvalue;
810 void *info, *bd;
811 char *name;
812 DWORD flags;
813 
814  va_start(argptr, cmd);
815  status = FE_SUCCESS;
816 
817  switch (cmd) {
818  case CMD_INIT:
819  hKey = va_arg(argptr, HNDLE);
820  info = va_arg(argptr, void *);
821  channel = va_arg(argptr, INT);
822  flags = va_arg(argptr, DWORD);
823  bd = va_arg(argptr, void *);
824  status = danfysik_in_init(hKey, info, channel, bd);
825  break;
826 
827  case CMD_EXIT:
828  info = va_arg(argptr, void *);
829  status = danfysik_exit(info);
830  break;
831 
832  case CMD_GET:
833  info = va_arg(argptr, void *);
834  channel = va_arg(argptr, INT);
835  pvalue = va_arg(argptr, float*);
836  status = danfysik_get(info, channel, pvalue);
837  break;
838 
839  case CMD_GET_LABEL:
840  info = va_arg(argptr, void *);
841  channel = va_arg(argptr, INT);
842  name = va_arg(argptr, char *);
843  status = danfysik_in_get_label(info, channel, name);
844  break;
845 
846  default:
847  break;
848  }
849 
850  va_end(argptr);
851 
852  return status;
853 }
854 /*------------------------------------------------------------------*/
855 INT danfysik_out(INT cmd, ...)
856 {
857 va_list argptr;
858 HNDLE hKey;
859 INT channel, status;
860 float value;
861 void *info, *bd;
862 char *name;
863 DWORD flags;
864 
865  va_start(argptr, cmd);
866  status = FE_SUCCESS;
867 
868  switch (cmd) {
869  case CMD_INIT:
870  hKey = va_arg(argptr, HNDLE);
871  info = va_arg(argptr, void *);
872  channel = va_arg(argptr, INT);
873  flags = va_arg(argptr, DWORD);
874  bd = va_arg(argptr, void *);
875  status = danfysik_out_init(hKey, info, channel, bd);
876  break;
877 
878  case CMD_GET_LABEL:
879  info = va_arg(argptr, void *);
880  channel = va_arg(argptr, INT);
881  name = va_arg(argptr, char *);
882  status = danfysik_out_get_label(info, channel, name);
883  break;
884 
885  case CMD_SET:
886  info = va_arg(argptr, void *);
887  channel = va_arg(argptr, INT);
888  value = (float) va_arg(argptr, double);
889  status = danfysik_set(info, channel, value);
890  break;
891 
892  default:
893  break;
894  }
895 
896  va_end(argptr);
897 
898  return status;
899 }
900 /*------------------------------------------------------------------*/
INT danfysik_remote
1=remote, 0=local
Definition: danfysik.c:116
#define DANFYSIK_INTERLOCK_EXT_4
Definition: danfysik.c:51
DANFYSIK_SETTINGS danfysik_settings
stores the internal DD settings
Definition: danfysik.c:108
#define DANFYSIK_ETS_LOGOUT_SLEEP
sleep time (us) between the telnet commands of the ets_logout
Definition: danfysik.c:38
HNDLE hkey
ODB key for device driver info.
Definition: danfysik.c:115
INFO info
Definition: vme_fe.c:206
HNDLE hDB
main handle to the ODB
Definition: danfysik.c:114
#define DANFYSIK_INTERLOCK_DC_OVER_CURRENT
Definition: danfysik.c:59
INT danfysik_exit(DANFYSIK_INFO *info)
Definition: danfysik.c:471
INT num_channels
number of channels for this device
Definition: danfysik.c:109
#define DANFYSIK_OUT_CH
number of output channels
Definition: danfysik.c:35
INT danfysik_status
keeps the old danfysik status
Definition: danfysik.c:117
INT danfysik_set(DANFYSIK_INFO *info, INT channel, float value)
Definition: danfysik.c:490
int reconnection_failures
how often reconnection failed
Definition: danfysik.c:125
INT danfysik_out_get_label(DANFYSIK_INFO *info, INT channel, char *name)
Definition: danfysik.c:601
#define DANFYSIK_STATUS_ON
Definition: danfysik.c:61
DWORD next_read
timeout in (ms) before trying to attempt to read new data from the danfysik pwr supply ...
Definition: danfysik.c:82
#define DANFYSIK_STATUS_LOCAL
Definition: danfysik.c:50
void danfysik_strip_rubbish(char *str_in, char *str_clean)
Definition: danfysik.c:141
#define DANFYSIK_STATUS_CURRENT_LIMIT
Definition: danfysik.c:64
#define DANFYSIK_MAX_EMPTY_READBACK_ERR
maximum number of empty readback errors
Definition: danfysik.c:44
#define DANFYSIK_INTERLOCK_EARTH_LEAKAGE_FAILURE
Definition: danfysik.c:65
INT readback_failure
counts the number of readback failures
Definition: danfysik.c:121
int ets_logout(void *info, int wait, int detailed_msg)
Definition: ets_logout.c:113
#define DANFYSIK_STATUS_OFF
Definition: danfysik.c:49
Stores all the parameters the device driver needs.
Definition: experim.h:8491
DWORD time_to_read
timer which allows to slow down the reading a bit (get routine)
Definition: danfysik.c:127
INT empty_readback_error
counts the number of empty readbacks
Definition: danfysik.c:120
HNDLE hKey
Definition: write_summary.c:97
#define DANFYSIK_RECONNECTION_TIMEOUT
timeout in (sec) for before trying to reconnect again (after a communication breakdown) ...
Definition: danfysik.c:30
INT ets_in_use
flag indicating if the rs232 terminal server is in use
Definition: experim.h:8502
INT detailed_msg
flag indicating if detailed status/error messages are wanted
Definition: danfysik.c:76
INT danfysik_in(INT cmd,...)
Definition: danfysik.c:804
HNDLE hDB
Definition: write_summary.c:97
INT danfysik_out_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
Definition: danfysik.c:455
#define DANFYSIK_INTERLOCK_MAINS_FAILURE
Definition: danfysik.c:63
DWORD last_reconnect
timer for bus driver reconnect error handling
Definition: danfysik.c:124
#define DELTA_TIME_ERROR
reset error counter after DELTA_TIME_ERROR seconds
Definition: danfysik.c:46
float last_valid_value[DANFYSIK_IN_CH]
stores the last valid value
Definition: danfysik.c:123
#define DANFYSIK_INTERLOCK_EXT_3
Definition: danfysik.c:70
INT danfysik_error_read(int channel, char *str)
Definition: danfysik.c:164
INT danfysik_get(DANFYSIK_INFO *info, INT channel, float *pvalue)
Definition: danfysik.c:617
float soft_current_limit
keeps the soft current limit, i.e. the current set value needs to be &lt; than the soft current limit ...
Definition: danfysik.c:126
#define DANFYSIK_INTERLOCK_CONVERTER_OVER_VOLTAGE
Definition: danfysik.c:66
char out_names[DANFYSIK_OUT_CH][NAME_LENGTH]
Names of the DD output channels.
Definition: danfysik.c:79
void * bd_info
private info of bus driver
Definition: danfysik.c:111
INT danfysik_in_get_label(DANFYSIK_INFO *info, INT channel, char *name)
Definition: danfysik.c:584
#define DANFYSIK_STATUS_STANDBY
Definition: danfysik.c:57
float max_voltage
Max. voltage of the danfysik power supply.
Definition: danfysik.c:81
INT startup_error
initializer error tag, if set, danfysik_get and danfysik_set won&#39;t do anything
Definition: danfysik.c:119
int first_bd_error
flag showing if the bus driver error message is already given
Definition: danfysik.c:113
INT(* bd)(INT cmd,...)
bus driver entry function
Definition: danfysik.c:110
#define DANFYSIK_PERCENTAGE
Definition: danfysik.c:55
#define DANFYSIK_INTERLOCK_MPS_FAN_FAULT
Definition: danfysik.c:72
int bd_connected
flag showing if bus driver is connected
Definition: danfysik.c:112
char in_names[DANFYSIK_IN_CH][NAME_LENGTH]
Names of the DD input channels.
Definition: danfysik.c:78
#define DANFYSIK_MAX_READBACK_FAILURE
maximum number of readback failures before a reconnect will take place
Definition: danfysik.c:42
DWORD lasterrtime
last error time stamp
Definition: danfysik.c:122
#define DANFYSIK_INTERLOCK_MPS_OVERTEMPERATURE
Definition: danfysik.c:67
INT danfysik_in_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
Definition: danfysik.c:337
#define DANFYSIK_INTERLOCK_EXT_2
Definition: danfysik.c:62
float max_current
Max. current of the danfysik power supply.
Definition: danfysik.c:80
#define DANFYSIK_READ_ERROR
tag: read error
Definition: danfysik.c:26
#define DANFYSIK_IN_CH
number of input channels
Definition: danfysik.c:33
#define DANFYSIK_SETTINGS_STR
Initializing string for the struct DANFYSIK_SETTINGS.
Definition: danfysik.c:86
INT errcount
error counter in order not to flood the message queue
Definition: danfysik.c:118
#define DANFYSIK_INTERLOCK_EXT_1
Definition: danfysik.c:56
#define DANFYSIK_STATUS_MPS_NOT_READY
Definition: danfysik.c:71
#define DANFYSIK_INTERLOCK_OVER_VOLTAGE_PROTECTION
Definition: danfysik.c:60
#define DANFYSIK_INIT_ERROR
tag: initializing error
Definition: danfysik.c:24
#define DANFYSIK_TIME_OUT
timeout in (ms) for the communication between pc and danfysik
Definition: danfysik.c:28
void danfysik_decode_status(DANFYSIK_INFO *info, char *str)
Definition: danfysik.c:208
INT danfysik_out(INT cmd,...)
Definition: danfysik.c:855