source: BAORadio/libindi/v1.0.1/drivers/focuser/robofocus.c @ 614

Last change on this file since 614 was 490, checked in by campagne, 14 years ago

import libindi (JEC)

File size: 32.8 KB
Line 
1 #if 0
2    Robofocus driver
3    Copyright (C) 2006 Markus Wildi, markus.wildi@datacomm.ch
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
19#endif
20
21/* Standard headers */
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26/* INDI Core headers */
27/* indidevapi.h contains API declerations */
28#include "indidevapi.h"
29
30/* INDI Eventloop mechanism */
31#include "eventloop.h"
32
33/* INDI Common Routines/RS232 */
34#include "indicom.h"
35
36#include "robofocusdriver.h"
37
38/* Definitions */
39
40#define mydev              "Robofocus"     /* Device name */
41#define CONNECTION_GROUP   "Connection"  /* Group name */
42#define MOTION_GROUP       "Motion"
43 
44#define currentSpeed            SpeedN[0].value
45#define currentPosition         PositionN[0].value
46#define currentTemperature      TemperatureN[0].value
47#define currentBacklash         SetBacklashN[0].value
48#define currentDuty             SettingsN[0].value
49#define currentDelay            SettingsN[1].value
50#define currentTicks            SettingsN[2].value
51#define currentRelativeMovement RelMovementN[0].value
52#define currentAbsoluteMovement AbsMovementN[0].value
53#define currentSetBacklash      SetBacklashN[0].value
54#define currentMinPosition      MinMaxPositionN[0].value
55#define currentMaxPosition      MinMaxPositionN[1].value
56#define currentMaxTravel        MaxTravelN[0].value
57
58int fd; /* Rs 232 file handle */
59int wp ;  /* Work proc ID */
60
61
62/* Function protptypes */
63
64void connectRobofocus(void);
65
66static void ISInit() ;
67void ISWorkProc (void) ;
68int updateRFPosition(int fd, double *value) ;
69int updateRFTemperature(int fd, double *value) ;
70int updateRFBacklash(int fd, double *value) ;
71int updateRFFirmware(int fd, char *rf_cmd) ;
72int updateRFMotorSettings(int fd, double *duty, double *delay, double *ticks) ;
73int updateRFPositionRelativeInward(int fd, double *value) ;
74int updateRFPositionRelativeOutward(int fd, double *value) ;
75int updateRFPositionAbsolute(int fd, double *value) ;
76int updateRFPowerSwitches(int fd, int s, int  i, int *cur_s1LL, int *cur_s2LR, int *cur_s3RL, int *cur_s4RR) ;
77int updateRFMaxPosition(int fd, double *value) ;
78int updateRFSetPosition(int fd, double *value) ;
79
80/* operational info */
81
82
83/* RS 232 Connection */
84
85static ISwitch PowerS[] = {
86  {"CONNECT", "Connect", ISS_OFF, 0, 0},                         
87  {"DISCONNECT", "Disconnect", ISS_OFF, 0, 0},
88};
89
90static ISwitchVectorProperty PowerSP    = { 
91  mydev                 /* Device name */
92  , "CONNECTION"        /* Property name */
93  , "Connection"        /* Property label */
94  , CONNECTION_GROUP    /* Property group */
95  , IP_RW               /* Property premission, it's both read and write */
96  , ISR_1OFMANY         /* Switch behavior. Only 1 of many switches are allowed to be on at the same time */
97  , 0                   /* Timeout, 0 seconds */
98  , IPS_IDLE            /* Initial state is idle */
99  , PowerS              /* Switches comprimising this vector that we defined above */
100  , NARRAY(PowerS)      /* Number of Switches. NARRAY is defined in indiapi.h */
101  , ""                  /* Timestamp, set to 0 */
102  , 0};                 /* auxiluary, set to 0 for now */
103
104/* Serial */
105
106static IText PortT[]= {{"PORT", "Port", 0, 0, 0, 0}}; /* Attention malloc */
107
108static ITextVectorProperty PortTP= { 
109  mydev, 
110  "DEVICE_PORT", 
111  "Ports", 
112  CONNECTION_GROUP, 
113  IP_RW, 
114  0, 
115  IPS_IDLE, 
116  PortT, 
117  NARRAY(PortT), 
118  "", 
119  0
120} ;
121
122/* Focuser temperature */
123
124static INumber TemperatureN[] = {
125
126  { "TEMPERATURE", "Celsius", "%6.2f", 0, 65000., 0., 10000., 0, 0, 0},                         
127} ;
128
129static INumberVectorProperty TemperatureNP = { 
130  mydev, 
131  "FOCUS_TEMPERATURE", 
132  "Temperature", 
133  CONNECTION_GROUP, 
134  IP_RO, 
135  0, 
136  IPS_IDLE, 
137  TemperatureN, 
138  NARRAY(TemperatureN), 
139  "", 
140  0
141} ;
142
143/* Settings of the Robofocus */
144
145static INumber SettingsN[] = {
146
147  { "Duty cycle", "Duty cycle", "%6.0f", 0., 255., 0., 1., 0, 0, 0},
148  { "Step delay", "Step delay", "%6.0f", 0., 255., 0., 1., 0, 0, 0},
149  { "Motor Steps", "Motor steps per tick", "%6.0f", 0, 255., 0., 1., 0, 0, 0},
150};
151
152static INumberVectorProperty SettingsNP = { 
153  mydev, 
154  "FOCUS_SETTINGS", 
155  "Settings", 
156  CONNECTION_GROUP, 
157  IP_RW, 
158  0, 
159  IPS_IDLE, 
160  SettingsN, 
161  NARRAY(SettingsN), 
162  "", 
163  0
164} ;
165
166/* Power Switches of the Robofocus */
167static ISwitch PowerSwitchesS[]= {
168
169  {"1", "Switch 1", ISS_OFF, 0, 0}, 
170  {"2", "Switch 2", ISS_OFF, 0, 0}, 
171  {"3", "Switch 3", ISS_OFF, 0, 0}, 
172  {"4", "Switch 4", ISS_ON , 0, 0}
173};
174
175static ISwitchVectorProperty PowerSwitchesSP      = { 
176  mydev, 
177  "SWITCHES", 
178  "Power", 
179  CONNECTION_GROUP, 
180  IP_RW,
181  ISR_1OFMANY, 
182  0, 
183  IPS_IDLE, 
184  PowerSwitchesS, 
185  NARRAY(PowerSwitchesS), 
186  "", 
187  0 
188} ;
189
190/* Direction of the focuser movement - or IGNORE */
191
192static ISwitch DirectionS[] = {
193
194  {"FOCUSIN", "inward", ISS_OFF, 0, 0}, 
195  {"FOCUSOUT", "outward", ISS_OFF, 0, 0},       
196  {"FOCUSIGNORE", "IGNORE", ISS_ON, 0, 0},
197} ;
198
199static ISwitchVectorProperty DirectionSP    = { 
200 
201  mydev, 
202  "DIRECTION", 
203  "Movement",
204  MOTION_GROUP,   
205  IP_RW,       
206  ISR_ATMOST1,
207  0,
208  IPS_IDLE,
209  DirectionS,
210  NARRAY(DirectionS),
211  "",   
212  0
213} ;     
214
215/* Robofocus should stay within these limits */
216
217static INumber MinMaxPositionN[] = {
218
219  { "MINPOS", "Minimum Tick", "%6.0f", 1., 65000., 0., 100., 0, 0, 0},
220  { "MAXPOS", "Maximum Tick", "%6.0f", 1., 65000., 0., 55000., 0, 0, 0},
221};
222
223static INumberVectorProperty MinMaxPositionNP = { 
224  mydev, 
225  "FOCUS_MINMXPOSITION", 
226  "Extrema", 
227  MOTION_GROUP, 
228  IP_RW, 
229  0, 
230  IPS_IDLE, 
231  MinMaxPositionN, 
232  NARRAY(MinMaxPositionN), 
233  "", 
234  0
235};
236
237static INumber MaxTravelN[] = {
238
239  { "MAXTRAVEL", "Maximum travel", "%6.0f", 1., 64000., 0., 10000., 0, 0, 0},
240};
241
242static INumberVectorProperty MaxTravelNP = { 
243  mydev, 
244  "FOCUS_MAXTRAVEL", 
245  "Max. travel", 
246  MOTION_GROUP, 
247  IP_RW, 
248  0, 
249  IPS_IDLE, 
250  MaxTravelN, 
251  NARRAY(MaxTravelN), 
252  "", 
253  0
254};
255
256/* Set Robofocus position register to the this position */
257
258static INumber SetRegisterPositionN[] = {
259
260  /* 64000: see Robofocus manual */
261  { "SETPOS", "Position", "%6.0f", 0, 64000., 0., 0., 0, 0, 0}, 
262};
263
264static INumberVectorProperty SetRegisterPositionNP = { 
265  mydev, 
266  "FOCUS_REGISTERPOSITION", 
267  "Set register", 
268  MOTION_GROUP, 
269  IP_RW, 
270  0, 
271  IPS_IDLE, 
272  SetRegisterPositionN, 
273  NARRAY(SetRegisterPositionN), 
274  "", 
275  0
276};
277/* Set Robofocus' backlash behaviour */
278
279static INumber SetBacklashN[] = {
280
281  { "SETBACKLASH", "Backlash", "%6.0f", -255., 255., 0., 0., 0, 0, 0},
282};
283
284static INumberVectorProperty SetBacklashNP = { 
285  mydev, 
286  "FOCUS_Backlash", 
287  "Set register", 
288  MOTION_GROUP, 
289  IP_RW, 
290  0, 
291  IPS_IDLE, 
292  SetBacklashN, 
293  NARRAY(SetBacklashN), 
294  "", 
295  0
296};
297
298/* Speed */
299static INumber SpeedN[] = {
300
301  {"SPEED", "Ticks/sec", "%6.0f",0., 999., 0., 50., 0, 0, 0},
302} ;
303
304static INumberVectorProperty SpeedNP = { 
305  mydev, 
306  "FOCUS_SPEED", 
307  "Speed", 
308  MOTION_GROUP, 
309  IP_RW, 
310  0, 
311  IPS_IDLE, 
312  SpeedN, 
313  NARRAY(SpeedN), 
314  "", 
315  0
316} ;
317
318
319/*  Timer */
320static INumber TimerN[] = {
321
322  {"TIMER","sec", "%6.0f",0., 999., 0., 0., 0, 0, 0},
323} ;
324
325static INumberVectorProperty TimerNP = { 
326
327  mydev, 
328  "FOCUS_TIMER", 
329  "Timer", 
330  MOTION_GROUP, 
331  IP_RW, 
332  0, 
333  IPS_IDLE, 
334  TimerN, 
335  NARRAY(TimerN), 
336  "", 
337  0
338} ;
339
340/* Robofocus` position (RO) */
341
342static INumber PositionN[] = {
343
344  { "POSITION", "Tick", "%6.0f", 0, 65000., 0., 10000., 0, 0, 0},                               
345} ;
346
347static INumberVectorProperty PositionNP = { 
348  mydev, 
349  "FOCUS_POSITION", 
350  "Position", 
351  MOTION_GROUP, 
352  IP_RO, 
353  0, 
354  IPS_IDLE, 
355  PositionN, 
356  NARRAY(PositionN), 
357  "", 
358  0
359} ;
360
361/* Relative and absolute movement */
362static INumber RelMovementN[] = {
363
364  { "RELMOVEMENT", "Ticks", "%6.0f", -65000., 65000., 0., 100., 0, 0, 0},
365                               
366};
367
368static INumberVectorProperty RelMovementNP = { 
369
370  mydev, 
371  "FOCUS_RELMOVEMENT", 
372  "Relative goto", 
373  MOTION_GROUP, 
374  IP_RW, 
375  0, 
376  IPS_IDLE, 
377  RelMovementN, 
378  NARRAY(RelMovementN), 
379  "", 
380  0
381} ;
382
383
384static INumber AbsMovementN[] = {
385
386  { "ABSMOVEMENT", "Tick", "%6.0f", 0, 65000., 0., 10000., 0, 0, 0},                           
387} ;
388
389static INumberVectorProperty AbsMovementNP = { 
390  mydev, 
391  "FOCUS_ABSMOVEMENT", 
392  "Absolute goto", 
393  MOTION_GROUP, 
394  IP_RW, 
395  0, 
396  IPS_IDLE, 
397  AbsMovementN, 
398  NARRAY(AbsMovementN), 
399  "", 
400  0
401} ;
402
403
404/* Initlization routine */
405static void ISInit() {
406
407  static int isInit=0;          /* set once mountInit is called */
408  /*fprintf(stderr, "ISInit\n") ;*/
409
410  if (isInit)
411    return;
412
413  /* stolen from temmadriver.c :-)*/
414
415  PortT[0].text = malloc( 13);
416  if (!PortT[0].text ){
417    fprintf(stderr,"Memory allocation error");
418    return;
419  }
420  IUSaveText( &PortT[0],  "/dev/ttyUSB0");
421
422  /* fprintf(stderr, "PORT:%s<\n", PortT->text) ; */
423  IDSetText( &PortTP, NULL) ;
424
425  fd=-1;
426  isInit = 1;
427}
428
429
430void ISWorkProc () {
431
432  char firmeware[]="FV0000000" ;
433  int ret = -1 ;
434  int cur_s1LL=0 ;
435  int cur_s2LR=0 ;
436  int cur_s3RL=0 ;
437  int cur_s4RR=0 ;
438
439  /* fprintf(stderr, "ISWorkProc\n") ; */
440
441  if (PowerS[0].s == ISS_ON) {
442    switch (PowerSP.s) {
443
444    case IPS_IDLE:
445    case IPS_OK:
446
447      if((ret= updateRFFirmware(fd, firmeware)) < 0) {
448        /* This would be the end*/
449        IDMessage( mydev, "Unknown error while reading Robofocus firmware\n");
450        break;
451      }
452      PowerSP.s = IPS_OK;
453      IDSetSwitch(&PowerSP, NULL);
454
455
456      if((ret= updateRFPosition(fd, &currentPosition)) < 0) {
457        PositionNP.s = IPS_ALERT;
458        IDSetNumber(&PositionNP, "Unknown error while reading  Robofocus position: %d", ret);
459        break;
460      }
461      PositionNP.s = IPS_OK;
462      IDSetNumber(&PositionNP, NULL); 
463
464      if(( ret= updateRFTemperature(fd, &currentTemperature)) < 0) {
465        TemperatureNP.s = IPS_ALERT;
466        IDSetNumber(&TemperatureNP, "Unknown error while reading  Robofocus temperature");
467        break;
468      }
469      TemperatureNP.s = IPS_OK;
470      IDSetNumber(&TemperatureNP, NULL);
471
472
473      currentBacklash= BACKLASH_READOUT ;
474      if(( ret= updateRFBacklash(fd, &currentBacklash)) < 0) {
475        SetBacklashNP.s = IPS_ALERT;
476        IDSetNumber(&SetBacklashNP, "Unknown error while reading  Robofocus backlash");
477        break;
478      }
479      SetBacklashNP.s = IPS_OK;
480      IDSetNumber(&SetBacklashNP, NULL);
481
482      currentDuty= currentDelay= currentTicks=0 ;
483
484      if(( ret= updateRFMotorSettings(fd, &currentDuty, &currentDelay, &currentTicks )) < 0) {
485        SettingsNP.s = IPS_ALERT;
486        IDSetNumber(&SettingsNP, "Unknown error while reading  Robofocus motor settings");
487        break;
488      }
489      SettingsNP.s = IPS_OK;
490      IDSetNumber(&SettingsNP, NULL);
491
492      if(( ret= updateRFPowerSwitches(fd,  -1, -1,  &cur_s1LL, &cur_s2LR, &cur_s3RL, &cur_s4RR)) < 0) {
493        PowerSwitchesSP.s = IPS_ALERT;
494        IDSetSwitch(&PowerSwitchesSP, "Unknown error while reading  Robofocus power swicht settings");
495        break;
496      }
497
498      PowerSwitchesS[0].s= PowerSwitchesS[1].s= PowerSwitchesS[2].s= PowerSwitchesS[3].s= ISS_OFF ;
499
500      if(cur_s1LL== ISS_ON) {
501
502        PowerSwitchesS[0].s= ISS_ON ;
503      } 
504      if(cur_s2LR== ISS_ON) {
505 
506        PowerSwitchesS[1].s= ISS_ON ;
507      }
508      if(cur_s3RL== ISS_ON) {
509
510        PowerSwitchesS[2].s= ISS_ON ;
511      } 
512      if(cur_s4RR== ISS_ON) {
513
514        PowerSwitchesS[3].s= ISS_ON ;
515      }
516      PowerSwitchesSP.s = IPS_OK ; 
517      IDSetSwitch(&PowerSwitchesSP, NULL);     
518
519
520      currentMaxTravel= MAXTRAVEL_READOUT ;
521      if(( ret= updateRFMaxPosition(fd, &currentMaxTravel)) < 0) {
522        MaxTravelNP.s = IPS_ALERT;
523        IDSetNumber(&MaxTravelNP, "Unknown error while reading  Robofocus maximum travel");
524        break;
525      }
526      MaxTravelNP.s = IPS_OK;
527      IDSetNumber(&MaxTravelNP, NULL);
528
529    case IPS_BUSY:
530
531      break;
532               
533    case IPS_ALERT:
534      break;
535    }
536  }     
537}
538
539/* void ISGetProperties (const char *dev)
540*  INDI will call this function when the client inquires about the device properties.
541*  Here we will use IDxxx functions to define new properties to the client */
542void ISGetProperties (const char *dev)
543{ 
544  /* fprintf(stderr, "ISGetProperties\n") ; */
545
546   /* #1 Let's make sure everything has been initialized properly */
547   ISInit();
548 
549  /* #2 Let's make sure that the client is asking for the properties of our device, otherwise ignore */
550  if (dev && strcmp (mydev, dev))
551    return;
552   
553  /* #3 Tell the client to create a new Switch property PowerSP */
554  IDDefSwitch(&PowerSP, NULL);
555  IDDefText(&PortTP, NULL);
556  IDDefSwitch(&PowerSwitchesSP, NULL);
557  IDDefNumber(&TemperatureNP, NULL);
558  IDDefNumber(&SettingsNP, NULL);
559
560  IDDefNumber(&MinMaxPositionNP, NULL);
561  IDDefNumber(&MaxTravelNP, NULL);
562  IDDefNumber(&SetRegisterPositionNP, NULL);
563  IDDefNumber(&SetBacklashNP, NULL);
564  IDDefSwitch(&DirectionSP, NULL);
565
566  IDDefNumber(&PositionNP, NULL);
567  IDDefNumber(&SpeedNP, NULL);
568  IDDefNumber(&TimerNP, NULL);
569  IDDefNumber(&AbsMovementNP, NULL);
570  IDDefNumber(&RelMovementNP, NULL);
571}
572 
573/* void ISNewSwitch(...)
574 * INDI will call this function when the client wants to set a new state of existing switches
575 ** Parameters **
576 * dev: the device name
577 * name: the property name the client wants to update
578 * states: an array of states of members switches (ISS_ON and ISS_OFF)
579 * names: names of the switches. The names are parallel to the states. That is, member names[0] has a state states[0], and so on...
580 * n: number of switches to update, which is also the dimension of *states and names[]
581*/
582void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n) {
583
584  /* fprintf(stderr, "ISNewSwitch\n") ; */
585
586  /* #1 Let's make sure everything has been initialized properly */
587  ISInit();
588       
589  /* #2 Let's make sure that the client is asking to update the properties of our device, otherwise ignore */
590  if (dev && strcmp (dev, mydev))
591    return;
592           
593  /* #3 Now let's check if the property the client wants to change is the PowerSP (name: CONNECTION) property*/
594  if (!strcmp (name, PowerSP.name)) {
595
596
597    /* If the clients wants to update this property, let's perform the following */
598         
599    /* A. We reset all switches (in this case CONNECT and DISCONNECT) to ISS_OFF */
600    IUResetSwitch(&PowerSP);
601
602    /* B. We update the switches by sending their names and updated states IUUpdateSwitch function */
603    IUUpdateSwitch(&PowerSP, states, names, n);
604         
605    /* C. We try to establish a connection to our device */
606    connectRobofocus();
607    return ;
608  }
609
610  if (!strcmp (name, PowerSwitchesSP.name)) {
611    int ret= -1 ;
612    int nset= 0 ;
613    int i= 0 ;
614    int new_s= -1 ;
615    int new_sn= -1 ;
616    int cur_s1LL=0 ;
617    int cur_s2LR=0 ;
618    int cur_s3RL=0 ;
619    int cur_s4RR=0 ;
620
621    ISwitch *sp ;
622
623    PowerSwitchesSP.s = IPS_BUSY ;
624    IDSetSwitch(&PowerSwitchesSP, NULL) ;
625
626
627    for( nset = i = 0; i < n; i++) {
628      /* Find numbers with the passed names in the SettingsNP property */
629      sp = IUFindSwitch (&PowerSwitchesSP, names[i]) ;
630     
631      /* If the state found is  (PowerSwitchesS[0]) then process it */
632
633      if( sp == &PowerSwitchesS[0]){
634             
635
636        new_s = (states[i]) ;
637        new_sn= 0; 
638        nset++ ;
639      } else if( sp == &PowerSwitchesS[1]){
640
641        new_s = (states[i]) ;
642        new_sn= 1; 
643        nset++ ;
644      } else if( sp == &PowerSwitchesS[2]){
645
646        new_s = (states[i]) ;
647        new_sn= 2; 
648        nset++ ;
649      } else if( sp == &PowerSwitchesS[3]){
650
651        new_s = (states[i]) ;
652        new_sn= 3; 
653        nset++ ;
654      }
655    }
656    if (nset == 1) {
657      cur_s1LL= cur_s2LR= cur_s3RL= cur_s4RR= 0 ;
658
659      if(( ret= updateRFPowerSwitches(fd, new_s, new_sn, &cur_s1LL, &cur_s2LR, &cur_s3RL, &cur_s4RR)) < 0) {
660
661        PowerSwitchesSP.s = IPS_ALERT;
662        IDSetSwitch(&PowerSwitchesSP, "Unknown error while reading  Robofocus power swicht settings");
663        return ;
664      }
665    } else {
666      /* Set property state to idle */
667      PowerSwitchesSP.s = IPS_IDLE ;
668               
669      IDSetNumber(&SettingsNP, "Power switch settings absent or bogus.");
670      return ;
671    }
672
673   
674    PowerSwitchesS[0].s= PowerSwitchesS[1].s= PowerSwitchesS[2].s= PowerSwitchesS[3].s= ISS_OFF ;
675 
676    if(cur_s1LL== ISS_ON) {
677
678
679      PowerSwitchesS[0].s= ISS_ON ;
680    } 
681    if(cur_s2LR== ISS_ON) {
682
683      PowerSwitchesS[1].s= ISS_ON ;
684    }
685    if(cur_s3RL== ISS_ON) {
686
687      PowerSwitchesS[2].s= ISS_ON ;
688    } 
689    if(cur_s4RR== ISS_ON) {
690
691      PowerSwitchesS[3].s= ISS_ON ;
692    }
693    PowerSwitchesSP.s = IPS_OK ; 
694    IDSetSwitch(&PowerSwitchesSP, "Setting power switches");
695
696   
697  }
698}
699
700
701/* void ISNewText(...)
702 * INDI will call this function when the client wants to update an existing text.
703 ** Parameters **
704 
705 * dev: the device name
706 * name: the property name the client wants to update
707 * texts: an array of texts.
708 * names: names of the members. The names are parallel to the texts.
709 * n: number of texts to update, which is also the dimension of *texts and names[]
710*/
711void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n) {
712
713  /* fprintf(stderr, "ISNewText\n") ; */
714
715  /* #1 Let's make sure everything has been initialized properly */
716  ISInit();
717
718  /* #2 Let's make sure that the client is asking to update the properties of our device, otherwise ignore */
719  if (dev && strcmp (dev, mydev))
720    return;
721 
722
723  dev=dev; names=names; n=n;
724
725  if (!strcmp(name, PortTP.name)) {
726    IUSaveText(&PortT[0], texts[0]);
727    PortTP.s = IPS_OK;
728    IDSetText(&PortTP, NULL);
729    return;
730  }
731
732  return;       
733}
734
735/* void ISNewNumber(...)
736 * INDI will call this function when the client wants to update an existing number.
737 ** Parameters **
738 
739 * dev: the device name
740 * name: the property name the client wants to update
741 * values: an array of values.
742 * names: names of the members. The names are parallel to the values.
743 * n: number of numbers to update, which is the dimension of *numbers and names[]
744*/
745void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n) {
746 
747  int i, nset;
748 
749  /* fprintf(stderr, "ISNewNumber\n") ; */
750
751  /* Make sure to initialize */
752  ISInit();
753
754  /* ignore if not ours */
755  if (strcmp (dev, mydev))
756    return;
757
758
759  if (!strcmp (name, SettingsNP.name)) {
760    /* new speed */
761    double new_duty = 0 ;
762    double new_delay = 0 ;
763    double new_ticks = 0 ;
764    int ret = -1 ;
765           
766    /* Check power, if it is off, then return */
767    if (PowerS[0].s != ISS_ON){
768      SettingsNP.s = IPS_IDLE;
769      IDSetNumber(&SettingsNP, "Power is off");
770      return;
771    }
772           
773    for (nset = i = 0; i < n; i++){
774      /* Find numbers with the passed names in the SettingsNP property */
775      INumber *eqp = IUFindNumber (&SettingsNP, names[i]);
776     
777      /* If the number found is  (SettingsN[0]) then process it */
778      if (eqp == &SettingsN[0]){
779             
780        new_duty = (values[i]);
781        nset += new_duty >= 0 && new_duty <= 255;
782      } else if  (eqp == &SettingsN[1]){
783
784        new_delay = (values[i]);
785        nset += new_delay >= 0 && new_delay <= 255;
786      } else if  (eqp == &SettingsN[2]){
787
788        new_ticks = (values[i]);
789        nset += new_ticks >= 0 && new_ticks <= 255;
790      }
791    }
792           
793    /* Did we process the three numbers? */
794    if (nset == 3) {
795               
796      /* Set the robofocus state to BUSY */
797      SettingsNP.s = IPS_BUSY;
798               
799               
800      IDSetNumber(&SettingsNP, NULL);
801
802      if(( ret= updateRFMotorSettings(fd,  &new_duty, &new_delay, &new_ticks))< 0) {
803       
804        IDSetNumber(&SettingsNP, "Changing to new settings failed");
805        return ;
806      } ; 
807
808      currentDuty = new_duty ;
809      currentDelay= new_delay ;
810      currentTicks= new_ticks ;
811
812      SettingsNP.s = IPS_OK;
813      IDSetNumber(&SettingsNP, "Motor settings are now  %3.0f %3.0f %3.0f", currentDuty, currentDelay, currentTicks);
814
815    } else {
816      /* Set property state to idle */
817      SettingsNP.s = IPS_IDLE;
818               
819      IDSetNumber(&SettingsNP, "Settings absent or bogus.");
820      return ;
821    }
822  }
823
824  if (!strcmp (name, RelMovementNP.name)) {
825
826    double cur_rpos=0 ;
827    double new_rpos = 0 ;
828    int nset = 0;
829    int ret= -1 ;
830
831    if (PowerS[0].s != ISS_ON){
832      RelMovementNP.s = IPS_IDLE;
833      IDSetNumber(&RelMovementNP, "Power is off");
834      return;
835    }
836    for (nset = i = 0; i < n; i++) {
837      /* Find numbers with the passed names in the RelMovementNP property */
838      INumber *eqp = IUFindNumber (&RelMovementNP, names[i]);
839               
840      /* If the number found is RelMovement (RelMovementN[0]) then process it */
841      if (eqp == &RelMovementN[0]){
842             
843        cur_rpos= new_rpos = (values[i]);
844       
845        /* CHECK 2006-01-26, limmits are relative to the actual position */
846        nset += new_rpos >= -0xffff && new_rpos <= 0xffff;
847      }
848
849      if (nset == 1) {
850
851        /* Set the robofocus state to BUSY */
852        RelMovementNP.s = IPS_BUSY;
853        IDSetNumber(&RelMovementNP, NULL);
854
855        if((currentPosition + new_rpos < currentMinPosition) || (currentPosition + new_rpos > currentMaxPosition)) {
856
857          RelMovementNP.s = IPS_ALERT ;
858          IDSetNumber(&RelMovementNP, "Value out of limits %5.0f", currentPosition +  new_rpos);
859          return ;
860        }
861
862        if( new_rpos > 0) {
863
864          ret= updateRFPositionRelativeOutward(fd, &new_rpos) ;
865
866        } else {
867
868          new_rpos= -new_rpos ;
869          ret= updateRFPositionRelativeInward(fd, &new_rpos) ;
870        }
871       
872        if( ret < 0) {
873
874          RelMovementNP.s = IPS_IDLE;
875          IDSetNumber(&RelMovementNP, "Read out of the relative movement failed, trying to recover position.");
876          if((ret= updateRFPosition(fd, &currentPosition)) < 0) {
877         
878
879            PositionNP.s = IPS_ALERT;
880            IDSetNumber(&PositionNP, "Unknown error while reading  Robofocus position: %d", ret);
881            return ;
882          }
883          PositionNP.s = IPS_ALERT;
884          IDSetNumber(&PositionNP, "Robofocus position recovered %5.0f", currentPosition); 
885
886          IDMessage( mydev, "Robofocus position recovered resuming normal operation");
887
888          /* We have to leave here, because new_rpos is not set */
889          return ;
890        }
891
892        RelMovementNP.s = IPS_OK;
893        currentRelativeMovement= cur_rpos ;
894        IDSetNumber(&RelMovementNP, NULL) ;
895
896        AbsMovementNP.s = IPS_OK;
897        currentAbsoluteMovement=  new_rpos - cur_rpos ;
898        IDSetNumber(&AbsMovementNP, NULL) ;
899
900        PositionNP.s = IPS_OK;
901        currentPosition= new_rpos ;
902        IDSetNumber(&PositionNP,  "Last position was %5.0f", currentAbsoluteMovement);
903
904     } else {
905
906        RelMovementNP.s = IPS_IDLE;
907        IDSetNumber(&RelMovementNP, "Need exactly one parameter.");
908
909        return ;
910      }
911    }
912  }
913
914  if (!strcmp (name, AbsMovementNP.name)) {
915
916    double new_apos = 0 ;
917    int nset = 0;
918    int ret= -1 ;
919
920    if (PowerS[0].s != ISS_ON){
921      AbsMovementNP.s = IPS_IDLE;
922      IDSetNumber(&AbsMovementNP, "Power is off");
923      return;
924    }
925    for (nset = i = 0; i < n; i++) {
926      /* Find numbers with the passed names in the AbsMovementNP property */
927      INumber *eqp = IUFindNumber (&AbsMovementNP, names[i]);
928     
929      /* If the number found is AbsMovement (AbsMovementN[0]) then process it */
930      if (eqp == &AbsMovementN[0]){
931       
932        new_apos = (values[i]);
933       
934        /* limits are absolute to the actual position */
935        nset += new_apos >= 0 && new_apos <= 0xffff;
936      }
937
938      if (nset == 1) {
939
940        /* Set the robofocus state to BUSY */
941        AbsMovementNP.s = IPS_BUSY;
942        IDSetNumber(&AbsMovementNP, NULL);
943
944        if((new_apos < currentMinPosition) || (new_apos > currentMaxPosition)) {
945
946          AbsMovementNP.s = IPS_ALERT ;
947          IDSetNumber(&AbsMovementNP, "Value out of limits  %5.0f", new_apos);
948          return ;
949        }
950       
951        if(( ret= updateRFPositionAbsolute(fd, &new_apos)) < 0) {
952
953          AbsMovementNP.s = IPS_IDLE;
954          IDSetNumber(&AbsMovementNP, "Read out of the absolute movement failed %3d, trying to recover position.", ret);
955
956          if((ret= updateRFPosition(fd, &currentPosition)) < 0) {
957 
958            PositionNP.s = IPS_ALERT;
959            IDSetNumber(&PositionNP, "Unknown error while reading  Robofocus position: %d.", ret);
960
961            return ;
962          }
963
964          PositionNP.s = IPS_OK;
965          IDSetNumber(&PositionNP, "Robofocus position recovered %5.0f", currentPosition); 
966          IDMessage( mydev, "Robofocus position recovered resuming normal operation");
967          /* We have to leave here, because new_apos is not set */
968          return ;
969        }
970
971        currentAbsoluteMovement=  currentPosition ;
972        AbsMovementNP.s = IPS_OK;
973        IDSetNumber(&AbsMovementNP, NULL) ;
974
975        PositionNP.s = IPS_OK;
976        currentPosition= new_apos ;
977        IDSetNumber(&PositionNP,  "Absolute position was  %5.0f", currentAbsoluteMovement);
978
979      } else {
980       
981        AbsMovementNP.s = IPS_IDLE;
982        IDSetNumber(&RelMovementNP, "Need exactly one parameter.");
983 
984        return ;
985      }
986    }
987  }
988
989  if (!strcmp (name, SetBacklashNP.name)) {
990
991    double new_back = 0 ;
992    int nset = 0;
993    int ret= -1 ;
994
995    if (PowerS[0].s != ISS_ON){
996      SetBacklashNP.s = IPS_IDLE;
997      IDSetNumber(&SetBacklashNP, "Power is off");
998      return;
999    }
1000    for (nset = i = 0; i < n; i++) {
1001      /* Find numbers with the passed names in the SetBacklashNP property */
1002      INumber *eqp = IUFindNumber (&SetBacklashNP, names[i]);
1003     
1004      /* If the number found is SetBacklash (SetBacklashN[0]) then process it */
1005      if (eqp == &SetBacklashN[0]){
1006       
1007        new_back = (values[i]);
1008       
1009        /* limits */
1010        nset += new_back >= -0xff && new_back <= 0xff;
1011      }
1012
1013      if (nset == 1) {
1014
1015        /* Set the robofocus state to BUSY */
1016        SetBacklashNP.s = IPS_BUSY;
1017        IDSetNumber(&SetBacklashNP, NULL);
1018       
1019        if(( ret= updateRFBacklash(fd, &new_back)) < 0) {
1020
1021          SetBacklashNP.s = IPS_IDLE;
1022          IDSetNumber(&SetBacklashNP, "Setting new backlash failed.");
1023         
1024          return ;
1025        } 
1026       
1027        currentSetBacklash=  new_back ;
1028        SetBacklashNP.s = IPS_OK;
1029        IDSetNumber(&SetBacklashNP, "Backlash is now  %3.0f", currentSetBacklash) ;
1030      } else {
1031       
1032        SetBacklashNP.s = IPS_IDLE;
1033        IDSetNumber(&SetBacklashNP, "Need exactly one parameter.");
1034
1035        return ;
1036      }
1037    }
1038  }
1039 
1040  if (!strcmp (name, MinMaxPositionNP.name)) {
1041    /* new positions */
1042    double new_min = 0 ;
1043    double new_max = 0 ;
1044 
1045           
1046    /* Check power, if it is off, then return */
1047    if (PowerS[0].s != ISS_ON){
1048      MinMaxPositionNP.s = IPS_IDLE;
1049      IDSetNumber(&MinMaxPositionNP, "Power is off");
1050      return;
1051    }
1052           
1053    for (nset = i = 0; i < n; i++){
1054      /* Find numbers with the passed names in the MinMaxPositionNP property */
1055      INumber *mmpp = IUFindNumber (&MinMaxPositionNP, names[i]);
1056     
1057      /* If the number found is  (MinMaxPositionN[0]) then process it */
1058      if (mmpp == &MinMaxPositionN[0]){
1059             
1060        new_min = (values[i]);
1061        nset += new_min >= 1 && new_min <= 65000;
1062      } else if  (mmpp == &MinMaxPositionN[1]){
1063
1064        new_max = (values[i]);
1065        nset += new_max >= 1 && new_max <= 65000;
1066      }
1067    }
1068           
1069    /* Did we process the two numbers? */
1070    if (nset == 2) {
1071               
1072      /* Set the robofocus state to BUSY */
1073      MinMaxPositionNP.s = IPS_BUSY;
1074
1075      currentMinPosition = new_min ;
1076      currentMaxPosition= new_max ;
1077 
1078
1079      MinMaxPositionNP.s = IPS_OK;
1080      IDSetNumber(&MinMaxPositionNP, "Minimum and Maximum settings are now  %3.0f %3.0f", currentMinPosition, currentMaxPosition);
1081
1082    } else {
1083      /* Set property state to idle */
1084      MinMaxPositionNP.s = IPS_IDLE;
1085               
1086      IDSetNumber(&MinMaxPositionNP, "Minimum and maximum limits absent or bogus.");
1087     
1088      return ;
1089    }
1090  }
1091
1092  if (!strcmp (name, MaxTravelNP.name)) {
1093
1094    double new_maxt = 0 ;
1095    int ret = -1 ;
1096
1097    /* Check power, if it is off, then return */
1098    if (PowerS[0].s != ISS_ON){
1099      MaxTravelNP.s = IPS_IDLE;
1100      IDSetNumber(&MaxTravelNP, "Power is off");
1101      return;
1102    }
1103    for (nset = i = 0; i < n; i++){
1104      /* Find numbers with the passed names in the MinMaxPositionNP property */
1105      INumber *mmpp = IUFindNumber (&MaxTravelNP, names[i]);
1106     
1107      /* If the number found is  (MaxTravelN[0]) then process it */
1108      if (mmpp == &MaxTravelN[0]){
1109             
1110        new_maxt = (values[i]);
1111        nset += new_maxt >= 1 && new_maxt <= 64000;
1112      }
1113    }
1114    /* Did we process the one number? */
1115    if (nset == 1) {
1116
1117      IDSetNumber(&MinMaxPositionNP, NULL);
1118
1119      if(( ret= updateRFMaxPosition(fd,  &new_maxt))< 0 ) {
1120        MaxTravelNP.s = IPS_IDLE;
1121        IDSetNumber(&MaxTravelNP, "Changing to new maximum travel failed");
1122        return ;
1123      } ; 
1124
1125      currentMaxTravel=  new_maxt ;
1126      MaxTravelNP.s = IPS_OK;
1127      IDSetNumber(&MaxTravelNP, "Maximum travel is now  %3.0f", currentMaxTravel) ;
1128
1129    } else {
1130      /* Set property state to idle */
1131
1132      MaxTravelNP.s = IPS_IDLE;
1133      IDSetNumber(&MaxTravelNP, "Maximum travel absent or bogus.");
1134     
1135      return ;
1136    }
1137  }
1138
1139  if (!strcmp (name, SetRegisterPositionNP.name)) {
1140
1141    double new_apos = 0 ;
1142    int nset = 0;
1143    int ret= -1 ;
1144
1145    if (PowerS[0].s != ISS_ON){
1146      SetRegisterPositionNP.s = IPS_IDLE;
1147      IDSetNumber(&SetRegisterPositionNP, "Power is off");
1148      return;
1149    }
1150    for (nset = i = 0; i < n; i++)  {
1151      /* Find numbers with the passed names in the SetRegisterPositionNP property */
1152      INumber *srpp = IUFindNumber (&SetRegisterPositionNP, names[i]);
1153     
1154      /* If the number found is SetRegisterPosition (SetRegisterPositionN[0]) then process it */
1155      if (srpp == &SetRegisterPositionN[0]){
1156       
1157        new_apos = (values[i]);
1158       
1159        /* limits are absolute */
1160        nset += new_apos >= 0 && new_apos <= 64000;
1161      }
1162
1163      if (nset == 1) {
1164
1165        if((new_apos < currentMinPosition) || (new_apos > currentMaxPosition)) {
1166
1167          SetRegisterPositionNP.s = IPS_ALERT ;
1168          IDSetNumber(&SetRegisterPositionNP, "Value out of limits  %5.0f", new_apos);
1169          return ;
1170        }
1171
1172        /* Set the robofocus state to BUSY */
1173        SetRegisterPositionNP.s = IPS_BUSY;
1174        IDSetNumber(&SetRegisterPositionNP, NULL);
1175       
1176        if(( ret= updateRFSetPosition(fd, &new_apos)) < 0) {
1177
1178          SetRegisterPositionNP.s = IPS_OK;
1179          IDSetNumber(&SetRegisterPositionNP, "Read out of the set position to %3d failed. Trying to recover the position", ret);
1180
1181          if((ret= updateRFPosition(fd, &currentPosition)) < 0) {
1182 
1183            PositionNP.s = IPS_ALERT;
1184            IDSetNumber(&PositionNP, "Unknown error while reading  Robofocus position: %d", ret);
1185
1186            SetRegisterPositionNP.s = IPS_IDLE;
1187            IDSetNumber(&SetRegisterPositionNP, "Relative movement failed.");
1188          }
1189
1190          SetRegisterPositionNP.s = IPS_OK;
1191          IDSetNumber(&SetRegisterPositionNP, NULL); 
1192
1193
1194          PositionNP.s = IPS_OK;
1195          IDSetNumber(&PositionNP, "Robofocus position recovered %5.0f", currentPosition); 
1196          IDMessage( mydev, "Robofocus position recovered resuming normal operation");
1197          /* We have to leave here, because new_apos is not set */
1198          return ;
1199        }
1200        currentPosition= new_apos ;
1201        SetRegisterPositionNP.s = IPS_OK;
1202        IDSetNumber(&SetRegisterPositionNP, "Robofocus register set to %5.0f", currentPosition); 
1203
1204        PositionNP.s = IPS_OK;
1205        IDSetNumber(&PositionNP, "Robofocus position is now %5.0f", currentPosition); 
1206
1207        return ;
1208
1209      } else {
1210       
1211        SetRegisterPositionNP.s = IPS_IDLE;
1212        IDSetNumber(&SetRegisterPositionNP, "Need exactly one parameter.");
1213       
1214        return ;
1215      }
1216      if((ret= updateRFPosition(fd, &currentPosition)) < 0) {
1217 
1218        PositionNP.s = IPS_ALERT;
1219        IDSetNumber(&PositionNP, "Unknown error while reading  Robofocus position: %d", ret);
1220
1221        return ;
1222      }
1223      SetRegisterPositionNP.s = IPS_OK;
1224      IDSetNumber(&SetRegisterPositionNP, "Robofocus has accepted new register setting" ) ; 
1225
1226      PositionNP.s = IPS_OK;
1227      IDSetNumber(&PositionNP, "Robofocus new position %5.0f", currentPosition); 
1228    }
1229  } 
1230  return;
1231}
1232
1233void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) 
1234{
1235  INDI_UNUSED(dev);
1236  INDI_UNUSED(name);
1237  INDI_UNUSED(sizes);
1238  INDI_UNUSED(blobsizes);
1239  INDI_UNUSED(blobs);
1240  INDI_UNUSED(formats);
1241  INDI_UNUSED(names);
1242  INDI_UNUSED(n);
1243}
1244void ISSnoopDevice (XMLEle *root) 
1245{
1246  INDI_UNUSED(root);
1247}
1248
1249/* void connectRobofocus(void)
1250 * This function is called when the state of PowerSP is changed in the ISNewSwitch() function.
1251 * We check the state of CONNECT and DISCONNECT switches, and connect or disconnect our fake device accordingly */
1252
1253void connectRobofocus(void) {
1254
1255  /* fprintf(stderr, "connectRobofocus\n") ; */
1256
1257  switch (PowerS[0].s) {
1258  case ISS_ON:
1259   
1260   if (tty_connect(PortT[0].text, 9600, 8, 0, 1, &fd) != TTY_OK)
1261   {
1262
1263      PowerSP.s = IPS_ALERT;
1264      IUResetSwitch(&PowerSP);
1265      IDSetSwitch(&PowerSP, "Error connecting to port >%s<", PortT[0].text);
1266      return;
1267    }
1268
1269    PowerSP.s = IPS_OK;
1270    IDSetSwitch(&PowerSP, "Robofocus is online.");
1271    wp= IEAddWorkProc( (IE_WPF *)ISWorkProc, NULL) ;
1272    break;
1273
1274  case ISS_OFF:
1275
1276    IERmWorkProc ( wp) ;
1277    tty_disconnect(fd);
1278    IUResetSwitch(&PowerSP);   
1279    IUResetSwitch(&PowerSwitchesSP);
1280    IUResetSwitch(&DirectionSP);
1281    AbsMovementNP.s= RelMovementNP.s= TimerNP.s= SpeedNP.s= SetBacklashNP.s= SetRegisterPositionNP.s= MinMaxPositionNP.s= DirectionSP.s= PowerSwitchesSP.s= SettingsNP.s= TemperatureNP.s= PositionNP.s = PortTP.s = PowerSP.s = IPS_IDLE;
1282
1283    IDSetSwitch(&PowerSP, "Robofocus is offline.");
1284
1285    IDSetText(&PortTP, NULL);
1286   
1287    IDSetSwitch(&DirectionSP, NULL);
1288    IDSetSwitch(&PowerSwitchesSP, NULL);
1289
1290    /* Write the last status */
1291
1292    IDSetNumber(&PositionNP, NULL);
1293    IDSetNumber(&AbsMovementNP, NULL);
1294    IDSetNumber(&RelMovementNP, NULL);
1295    IDSetNumber(&TimerNP, NULL);
1296    IDSetNumber(&SpeedNP, NULL);
1297    IDSetNumber(&SetBacklashNP, NULL);
1298    IDSetNumber(&SetRegisterPositionNP, NULL);
1299    IDSetNumber(&MinMaxPositionNP, NULL);
1300    IDSetNumber(&MaxTravelNP, NULL);
1301    IDSetNumber(&SettingsNP, NULL);
1302    IDSetNumber(&TemperatureNP, NULL);
1303
1304    break;
1305  }
1306}
1307
Note: See TracBrowser for help on using the repository browser.