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

Last change on this file since 689 was 490, checked in by campagne, 15 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.