Low-Energy Muon (LEM) Experiment  0.5.2
mirror.c
Go to the documentation of this file.
1 /********************************************************************\
2 
3  Name: mirror.c
4  Created by: Andreas Suter 2003/02/19
5 
6  Contents: device driver for the bloody mirror controller
7 
8  RS232: 9600 baud, 8 data bits, 1 stop bit, no parity bit
9 
10  Comments: angle () = (adc_value - 2048) * 5 / 1024
11  1 step of the stepper motor = 0.01
12 
13  02-Sep-2005: 45 degree position corresponds to -2.0 degree at controller
14  this corresponds to 294.8 degree at nonius (this info is
15  from the old VMS DCL script nemu_mirror.com)
16 
17  The mirror controller software is written in basic (stamp2 from parallax,
18  see http://www.parallax.com/). The actual basic controller version
19  is 'mor5.bs2' and can be found in the CVS as well. Since the basic
20  controller software is strictly sequential AND slow, some ugly routines
21  are included in this in this C driver.
22 
23 \********************************************************************/
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <math.h>
29 
30 #include "midas.h"
31 
32 #include "mirror.h"
33 
34 #include "ets_logout.h"
35 
37 #define MIRROR_ETS_LOGOUT_SLEEP 10000
38 
39 /*---- globals -----------------------------------------------------*/
40 
42 typedef struct {
43  INT ets_in_use;
44  int time_out;
45  int adc_45;
46  char names[2][32];
48 
50 #define MIRROR_SETTINGS_DD_STR "\
51 ETS_IN_USE = INT : 1\n\
52 TCPIPTimeOut = INT : 500\n\
53 MirrorADC45 = INT : 1976\n\
54 Names = STRING[2] :\n\
55 [32] Reset\n\
56 [32] Angle\n\
57 "
58 
60 typedef struct {
62  INT (*bd)(INT cmd, ...);
63  void *bd_info;
64  HNDLE hDB;
65  HNDLE hkey;
66  HNDLE hKeyDemand;
67  HNDLE hKeyInfo;
68  INT errorcount;
70  DWORD lasterrtime;
73  float last_value;
75 } MIRROR_INFO;
76 
77 // FOR DEBUG ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
78 int histo[MIRROR_MAX_TRY]; // histo in order to see how many attempts to read were necessary
79 
80 /*---- device driver routines --------------------------------------*/
81 /*----------------------------------------------------------------------------------*/
95 INT mirror_init(HNDLE hKey, void **pinfo, INT channels, INT (*bd)(INT cmd, ...))
96 {
97 
98  INT status;
99  HNDLE hDB, hKeyDD;
100  MIRROR_INFO *info;
101 
102  if (MIRROR_DEBUG) { // init read histo
103  int i;
104  for (i=0; i<MIRROR_MAX_TRY; i++) histo[i]=0;
105  }
106 
107  cm_get_experiment_database(&hDB, NULL);
108 
109  // allocate info structure
110  info = calloc(1, sizeof(MIRROR_INFO));
111  *pinfo = info;
112 
113  // create MIRROR settings record
114  status = db_create_record(hDB, hKey, "DD", MIRROR_SETTINGS_DD_STR);
115  if (status != DB_SUCCESS)
116  return FE_ERR_ODB;
117 
118  // get key to DD structure
119  status = db_find_key(hDB, hKey, "DD", &hKeyDD);
120  if (status != DB_SUCCESS)
121  return FE_ERR_ODB;
122 
123  // create hot-link onto 'DD' structure
124  status = db_open_record(hDB, hKeyDD, &info->mirror_dd_settings, sizeof(info->mirror_dd_settings),
125  MODE_READ, NULL, NULL);
126  if (status != DB_SUCCESS)
127  return FE_ERR_ODB;
128 
129  // initialize driver
130  info->bd = bd;
131  info->hDB = hDB;
132  info->hkey = hKey;
133  info->errorcount = 0;
134  info->startup_error = 0;
135  info->lasterrtime = ss_time();
136  info->bd_connected = 0;
137  info->last_reconnect = ss_time();
138  info->reconnection_failures = 0;
139 
140  // get and store some handles needed
141  if (db_find_key(info->hDB, 0, "/Equipment/Mirror/Variables/Demand", &info->hKeyDemand) != DB_SUCCESS) {
142  cm_msg(MINFO, "mirror_init", "WARNING: Couldn't get Key '/Equipment/Mirror/Variables/Demand' wasn't found in OBD.");
143  cm_yield(0);
144  return FE_SUCCESS;
145  }
146  if (db_find_key(info->hDB, 0, "/Info/Mirror/Angle horizontal", &info->hKeyInfo) != DB_SUCCESS) {
147  cm_msg(MINFO, "mirror_init", "WARNING: Couldn't get Key '/Info/Mirror/Angle horizontal' wasn't found in OBD.");
148  cm_yield(0);
149  return FE_SUCCESS;
150  }
151 
152  // pointer to bus driver available?
153  if (!bd)
154  return FE_ERR_ODB;
155 
156  // initialize bus driver
157  status = info->bd(CMD_INIT, hKey, &info->bd_info);
158  if (status != SUCCESS) {
159  info->startup_error = 1;
160  return status;
161  }
162  cm_msg(MINFO,"mirror_init","MIRROR driver initialized.");
163  cm_yield(0);
164  info->bd_connected = 1;
165 
166  return FE_SUCCESS;
167 }
168 
169 /*----------------------------------------------------------------------------------*/
179 {
180 
181  // call EXIT function of bus driver, usually closes device
182  info->bd(CMD_EXIT, info->bd_info);
183 
184  free(info);
185 
186  return FE_SUCCESS;
187 }
188 
189 /*----------------------------------------------------------------------------------*/
203 {
204  char cmd[MIRROR_MAX_STR];
205  int i, status;
206 
207  // read back reached value command
208  strcpy(cmd, "M+0\r");
209 
210  if (MIRROR_DEBUG)
211  printf("\n>>gcp: cmd = %s", cmd);
212 
213  i=0;
214  do { // loop
215  BD_PUTS(cmd);
216  status = BD_GETS(str, MIRROR_MAX_STR*sizeof(char), "\r", info->mirror_dd_settings.time_out);
217  i++;
218  if (strstr(str, "HS") || strstr(str, "ES")) { // mirror controller glitch
219  i--;
220  status = 0;
221  }
222  ss_sleep(MIRROR_WAIT);
223  } while (i<MIRROR_MAX_TRY && !status);
224 
225  if (MIRROR_DEBUG)
226  printf("\n>>gcp: str = %s", str);
227 
228  return i;
229 }
230 
231 /*----------------------------------------------------------------------------------*/
244 INT mirror_move_to_position(MIRROR_INFO *info, char *cmd, char *str, int max_try)
245 {
246  int i, status;
247 
248  i=0;
249  do { // till new position reached
250  BD_PUTS(cmd);
251  status = BD_GETS(str, MIRROR_MAX_STR*sizeof(char), "\r", info->mirror_dd_settings.time_out);
252  i++;
253  ss_sleep(MIRROR_WAIT);
254  } while (i<max_try && !strstr(str, "HS") && !strstr(str, "ES"));
255 
256  return i;
257 }
258 
259 /*----------------------------------------------------------------------------------*/
272 {
273  char cmd[MIRROR_MAX_STR], str[MIRROR_MAX_STR];
274  BOOL done;
275  int i, j, pos, step;
276 
277  cm_msg(MINFO,"mirror_set","INFO: reset process start. This is going to take some time!");
278 
279  // drive anticlock wise (negative angles) up to the limit switch
280  done = FALSE;
281  strcpy(cmd, "M-999\r");
282  j = 0;
283  do { // till end switch reached
284  if (MIRROR_DEBUG)
285  printf("\n>>mirror reset: cmd = %s", cmd);
286 
287  i=mirror_move_to_position(info, cmd, str, 5*MIRROR_MAX_TRY);
288 
289  if (MIRROR_DEBUG)
290  printf("\n>>mirror reset: i=%d, str=%s", i, str);
291 
292  if (i==5*MIRROR_MAX_TRY) // didn't get anything at all!!!
293  return FALSE;
294 
295  if (strstr(str, "ES")) // end switch reached
296  done = TRUE;
297 
298  j++;
299  } while(!done && j<5);
300  cm_msg(MINFO,"mirror_set","INFO: reset process: End switch reached. Start to move back.");
301 
302  // read the current position
303  mirror_get_current_position(info, str);
304  // decode str
305  pos = atoi(str);
306  // calculate angle to move (in 0.01 units)
307  step = abs(100*(info->mirror_dd_settings.adc_45-pos)*5/512);
308 
309  // first in steps of 999
310  for (j=0; j<step/999; j++) {
311  strcpy(cmd, "M+999\r");
312  if (MIRROR_DEBUG)
313  printf("\n>>mirror reset: cmd = %s", cmd);
314  i=mirror_move_to_position(info, cmd, str, 5*MIRROR_MAX_TRY);
315 
316  if (MIRROR_DEBUG)
317  printf("\n>>mirror reset: i=%d, str=%s", i, str);
318 
319  if (i==5*MIRROR_MAX_TRY) // didn't get anything at all!!!
320  return FALSE;
321  }
322 
323  // final step
324  step = step % 999; // remaining angle to move
325  sprintf(cmd, "M+%d\r", step);
326  if (MIRROR_DEBUG)
327  printf("\n>>mirror reset: cmd = %s", cmd);
328 
329  i=mirror_move_to_position(info, cmd, str, 5*MIRROR_MAX_TRY);
330 
331  if (MIRROR_DEBUG)
332  printf("\n>>mirror reset: i=%d, str=%s", i, str);
333 
334  if (i==5*MIRROR_MAX_TRY) // didn't get anything at all!!!
335  return FALSE;
336 
337  // check position
338  if (mirror_get_current_position(info, str) == MIRROR_MAX_TRY) {
339  return FALSE;
340  }
341 
342  cm_msg(MINFO,"mirror_set","INFO: reset process completed.");
343 
344  if (MIRROR_DEBUG)
345  printf("\n>>mirror reset: str=%d, adc_45=%d", atoi(str), info->mirror_dd_settings.adc_45);
346 
347  if (abs(atoi(str) - info->mirror_dd_settings.adc_45) > 10)
348  return FALSE;
349 
350  return TRUE;
351 }
352 
353 /*----------------------------------------------------------------------------------*/
354 
366 BOOL mirror_position_reached(MIRROR_INFO *info, char *cmd, float value)
367 {
368  int i=0;
369  char str[MIRROR_MAX_STR];
370 
371  if (MIRROR_DEBUG)
372  printf("\n\n\n\n\n>>mpr: cmd = %s", cmd);
373 
374  i=mirror_move_to_position(info, cmd, str, 5*MIRROR_MAX_TRY);
375 
376  if (MIRROR_DEBUG)
377  printf("\n>>mpr: i=%d, str=%s", i, str);
378 
379  if (i==5*MIRROR_MAX_TRY)
380  return FALSE;
381 
382  // wait a bit so that the controller is back
383  ss_sleep(7000);
384 
385  // read back reached value
387  return FALSE;
388 
389  // check the value
390  if (fabs(value-(atof(str)-2048.f)*5.f/512.f)>0.1)
391  return FALSE;
392 
393  return TRUE;
394 }
395 
396 /*----------------------------------------------------------------------------------*/
411 INT mirror_set(MIRROR_INFO *info, INT channel, float value)
412 {
413  int status, i, j;
414  float measured;
415  char cmd[MIRROR_MAX_STR], str[MIRROR_MAX_STR];
416  float dummy;
417 
418  if (channel == 0) { // reset channel
419  if (value != 0) { // reset mirror position
420  // set demand value
421  dummy = (info->mirror_dd_settings.adc_45-2048.f)*5.f/512.f;
422  db_set_data_index(info->hDB, info->hKeyDemand, &dummy, sizeof(float), channel+1, TID_FLOAT);
423  if (!reset_mirror_position(info)) {
424  cm_msg(MINFO, "mirror_set", "ERROR: Mirror reset couldn't be performed properly.");
425  }
426  // set reset value to zero again
427  dummy = 0.f;
428  db_set_data_index(info->hDB, info->hKeyDemand, &dummy, sizeof(float), channel, TID_FLOAT);
429  }
430  return FE_SUCCESS;
431  }
432 
433  if (value > 15.f) { // check if value is =< 15
434  value = 0.f;
435  status = db_set_data_index(info->hDB, info->hKeyDemand, &value, sizeof(float), channel, TID_FLOAT);
436  cm_msg(MINFO,"mirror_set","ERROR: MIRROR out of range +-15. Set it to 0.");
437  }
438  if (value < -15.f) { // check if value is >= -15
439  value = 0.f;
440  status = db_set_data_index(info->hDB, info->hKeyDemand, &value, sizeof(float), channel, TID_FLOAT);
441  cm_msg(MINFO,"mirror_set","ERROR: MIRROR out of range +-15. Set it to 0.");
442  }
443 
444  // get current position
445  mirror_get_current_position(info, str);
446 
447  measured = (atof(str)-2048.f)*5.f/512.f;
448 
449  if (fabs(measured-value)<0.1) { // do nothing
450  return FE_SUCCESS;
451  }
452 
453  i = (100*fabs(measured-value) / 999);
454 
455  if (measured - value > 0) { // current position > demanded position
456  // loop down in steps of 999 if necessary
457  strcpy(cmd, "M-999\r"); // move a defined amount backwards
458  for (j=0; j<i+1; j++) {
459  cm_msg(MINFO,"mirror_set","INFO: moving mirror, this is going to take a while.");
460  mirror_position_reached(info, cmd, value);
461  }
462  // final step
463  cm_msg(MINFO,"mirror_set","INFO: moving mirror, this is going to take a while.");
464  // get current position
465  mirror_get_current_position(info, str);
466  measured = (atof(str)-2048.f)*5.f/512.f;
467  if (value-measured > 0) { // end switch has never been reached
468  sprintf(cmd, "M+%d\r", abs(100*(value-measured))); // move back to the correct position
469  if (!mirror_position_reached(info, cmd, value)) {
470  cm_msg(MINFO,"mirror_set","ERROR: haven't reached demand value.");
471  return FE_ERR_HW;
472  }
473  } else { // end switch has been reached
474  strcpy(cmd, "M-999\r"); // move a defined amount backwards
475  mirror_position_reached(info, cmd, value);
476  sprintf(cmd, "M+%d\r", abs(100*(value-measured))); // move back to the correct position
477  if (!mirror_position_reached(info, cmd, value)) {
478  cm_msg(MINFO,"mirror_set","ERROR: haven't reached demand value.");
479  return FE_ERR_HW;
480  }
481  }
482  } else { // current position < demanded position
483  // loop up in steps of 999 if necessary
484  strcpy(cmd, "M+999\r");
485  for (j=0; j<i; j++) {
486  cm_msg(MINFO,"mirror_set","INFO: moving mirror, this is going to take a while.");
487  mirror_position_reached(info, cmd, value);
488  }
489  // final step
490  cm_msg(MINFO,"mirror_set","INFO: moving mirror, this is going to take a while.");
491  // read back current value
492  mirror_get_current_position(info, str);
493  measured = (atof(str)-2048.f)*5.f/512.f;
494  sprintf(cmd, "M+%d\r", abs(100*(value-measured)));
495  if (!mirror_position_reached(info, cmd, value)) {
496  cm_msg(MINFO,"mirror_set","ERROR: haven't reached demand value.");
497  return FE_ERR_HW;
498  }
499  }
500  cm_msg(MINFO,"mirror_set","INFO: mirror at new position.");
501 
502  return FE_SUCCESS;
503 }
504 
505 /*----------------------------------------------------------------------------------*/
506 
519 INT mirror_get(MIRROR_INFO *info, INT channel, float *pvalue)
520 {
521  char str[MIRROR_MAX_STR];
522  INT i, status;
523  DWORD nowtime, difftime;
524 
525  ss_sleep(10); // sleep 10ms to keep CPU load small during run active
526 
527  if (channel == 0) { // reset
528  *pvalue = 0;
529  return FE_SUCCESS;
530  }
531 
532  if (!info->bd_connected) { // lost connection
533  *pvalue = info->last_value;
534 
535  if (info->reconnection_failures > 5) {
536  if (info->reconnection_failures == 6) {
537  cm_msg(MERROR, "mirror_get", "too many reconnection failures, bailing out :-(");
538  info->reconnection_failures++;
539  }
540  return FE_SUCCESS;
541  }
542 
543  // try to disconnect and reconnect the bus driver
544  if ((ss_time()-info->last_reconnect > 10) && info->bd_connected) { // disconnect bus driver
545  info->bd(CMD_EXIT, info->bd_info);
546  cm_msg(MINFO, "mirror_get", "mirror_get: try to disconnect and reconnect the bus driver");
547  info->last_reconnect = ss_time();
548  info->bd_connected = 0;
549  if (info->mirror_dd_settings.ets_in_use)
551  }
552 
553  // try to reconnect after a timeout of 10 sec
554  if ((ss_time()-info->last_reconnect > 10) && !info->bd_connected) {
555  cm_msg(MINFO, "mirror_get", "mirror_get: reconnection trial ...");
556  status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
557  if (status != FE_SUCCESS) {
558  cm_msg(MINFO, "mirror_get", "mirror_get: reconnection attempted failed");
559  info->reconnection_failures++;
560  return FE_ERR_HW;
561  } else {
562  info->bd_connected = 1; // bus driver is connected again
563  info->reconnection_failures = 0;
564  info->last_reconnect = ss_time();
565  cm_msg(MINFO, "mirror_get", "mirror_get: successfully reconnected");
566  }
567  }
568  }
569 
570  nowtime = ss_time();
571  difftime = nowtime - info->lasterrtime;
572  if ( difftime > MIRROR_DELTA_TIME_ERROR ) {
573  info->errorcount = 0;
574  info->lasterrtime = nowtime;
575  }
576 
577  if ( info->startup_error == 1 ) { // error during CMD_INIT, return -2
578  *pvalue = (float) -2;
579  ss_sleep(10); // to keep CPU load low when Run active
580  return FE_SUCCESS;
581  }
582 
583  strcpy(str, ""); // initialize str
584  i = mirror_get_current_position(info, str);
585 
586  if (i == MIRROR_MAX_TRY) { // lost connection
587  info->bd_connected = 0;
588  *pvalue = -111; // haven't gotten anything
589  return FE_SUCCESS;
590  }
591 
592  if (MIRROR_DEBUG) {
593  histo[i-1]++;
594  printf("\n>> ");
595  for (i=0; i<MIRROR_MAX_TRY; i++)
596  printf("%5d", i+1);
597  printf("\n>> ");
598  for (i=0; i<MIRROR_MAX_TRY; i++)
599  printf("%5d", histo[i]);
600  }
601 
602  // decode return string
603  if (!strstr(str,"HS") && !strstr(str,"ES")) { // stepper motor is not moving, i.e. a value is returned
604  *pvalue = (atof(str) - 2048)*5.f/512.f; // ADC Range 0..4096, Mirror Angle Range +- 20
605  info->last_value = *pvalue; // keep last valid value
606  // write value also back into /Info/Mirror/Angle horizontal
607  db_set_data_index(info->hDB, info->hKeyInfo, pvalue, sizeof(float), 0, TID_FLOAT);
608  } else {
609  *pvalue = -222; // stepper motor moving
610  }
611 
612  ss_sleep(1000); // sleep for a second that the mirror controller is not too stressed!!
613 
614  return FE_SUCCESS;
615 }
616 
617 /*----------------------------------------------------------------------------------*/
628 INT mirror_get_label(MIRROR_INFO *info, INT channel, char *name)
629 {
630  strcpy(name, info->mirror_dd_settings.names[channel]);
631  return FE_SUCCESS;
632 }
633 
634 /*---- device driver entry point ---------------------------------------------------*/
635 INT mirror(INT cmd, ...)
636 {
637 va_list argptr;
638 HNDLE hKey;
639 INT channel, status;
640 DWORD flags;
641 void *info, *bd;
642 float value, *pvalue;
643 char *name;
644 
645  va_start(argptr, cmd);
646  status = FE_SUCCESS;
647 
648  switch (cmd) {
649  case CMD_INIT:
650  hKey = va_arg(argptr, HNDLE);
651  info = va_arg(argptr, void *);
652  channel = va_arg(argptr, INT);
653  flags = va_arg(argptr, DWORD);
654  bd = va_arg(argptr, void *);
655  status = mirror_init(hKey, info, channel, bd);
656  break;
657 
658  case CMD_EXIT:
659  info = va_arg(argptr, void *);
660  status = mirror_exit(info);
661  break;
662 
663  case CMD_GET:
664  info = va_arg(argptr, void *);
665  channel = va_arg(argptr, INT);
666  pvalue = va_arg(argptr, float *);
667  status = mirror_get(info, channel, pvalue);
668  break;
669 
670  case CMD_SET:
671  info = va_arg(argptr, void *);
672  channel = va_arg(argptr, INT);
673  value = (float) va_arg(argptr, double);
674  status = mirror_set(info, channel, value);
675  break;
676 
677  case CMD_GET_LABEL:
678  info = va_arg(argptr, void *);
679  channel = va_arg(argptr, INT);
680  name = va_arg(argptr, char *);
681  status = mirror_get_label(info, channel, name);
682  break;
683 
684  default:
685  break;
686  }
687  va_end(argptr);
688  return status;
689 }
690 /*------------------------------------------------------------------*/
691 
#define MIRROR_ETS_LOGOUT_SLEEP
sleep time (us) between the telnet commands of the ets_logout
Definition: mirror.c:37
float last_value
stores the last valid value
Definition: mirror.c:73
INT ets_in_use
flag indicating if the rs232 terminal server is in use
Definition: mirror.c:43
int adc_45
45 position of the mirror ADC
Definition: mirror.c:45
This structure contains private variables for the device driver.
Definition: mirror.c:60
#define MIRROR_MAX_TRY
maximal no of attempts to read
Definition: mirror.h:11
char names[2][32]
where to find mirror init data
Definition: mirror.c:46
INT mirror_move_to_position(MIRROR_INFO *info, char *cmd, char *str, int max_try)
Definition: mirror.c:244
HNDLE hDB
main ODB handle
Definition: mirror.c:64
INT(* bd)(INT cmd,...)
bus driver entry function
Definition: mirror.c:62
INT mirror_set(MIRROR_INFO *info, INT channel, float value)
Definition: mirror.c:411
int ets_logout(void *info, int wait, int detailed_msg)
INT errorcount
error coutner
Definition: mirror.c:68
#define MIRROR_DEBUG
debug tag, if set to TRUE, additional messages will be displayed at execution time ...
Definition: mirror.h:23
DWORD last_reconnect
timer for bus driver reconnect error handling
Definition: mirror.c:72
MIRROR_DD_SETTINGS mirror_dd_settings
ODB hot-link data for the DD.
Definition: mirror.c:61
INT mirror_get_current_position(MIRROR_INFO *info, char *str)
Definition: mirror.c:202
INFO info
Definition: analyzer.cxx:94
#define MIRROR_SETTINGS_DD_STR
initializing string for MIRROR_DD_SETTINGS
Definition: mirror.c:50
int histo[MIRROR_MAX_TRY]
Definition: mirror.c:78
HNDLE hKeyInfo
handle to /Info/Mirror/Angle horizontal
Definition: mirror.c:67
void * bd_info
private info of bus driver
Definition: mirror.c:63
INT startup_error
startup error tag; if set, the get and BH_set and BH_get routines wont do anything ...
Definition: mirror.c:69
HNDLE hKey
INT mirror_get(MIRROR_INFO *info, INT channel, float *pvalue)
Definition: mirror.c:519
#define MIRROR_MAX_STR
maximum string length for rs232 communication
Definition: mirror.h:20
HNDLE hkey
ODB key for bus driver info.
Definition: mirror.c:65
int bd_connected
flag showing if bus driver is connected
Definition: mirror.c:71
INT mirror(INT cmd,...)
Definition: mirror.c:635
int time_out
tcpip time out in msec
Definition: mirror.c:44
#define MIRROR_WAIT
time (ms) to wait between commands
Definition: mirror.h:17
BOOL reset_mirror_position(MIRROR_INFO *info)
Definition: mirror.c:271
stores internal informations within the DD.
Definition: mirror.c:42
HNDLE hDB
INT mirror_exit(MIRROR_INFO *info)
Definition: mirror.c:178
INT mirror_get_label(MIRROR_INFO *info, INT channel, char *name)
Definition: mirror.c:628
#define MIRROR_DELTA_TIME_ERROR
reset error counter after DELTA_TIME_ERROR seconds
Definition: mirror.h:14
int reconnection_failures
how often reconnection failed
Definition: mirror.c:74
INT mirror_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
Definition: mirror.c:95
HNDLE hKeyDemand
handle to /Equipment/Mirror/Variables/Demand
Definition: mirror.c:66
BOOL mirror_position_reached(MIRROR_INFO *info, char *cmd, float value)
Definition: mirror.c:366
DWORD lasterrtime
timer for error handling
Definition: mirror.c:70