moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kstars / kstars / indi / fli / libfli-filter-focuser.c
blobef4afb8e9aedee8000434fae61cf0a9b76cd004a
1 /*
3 Copyright (c) 2002 Finger Lakes Instrumentation (FLI), L.L.C.
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
10 Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
13 Redistributions in binary form must reproduce the above
14 copyright notice, this list of conditions and the following
15 disclaimer in the documentation and/or other materials
16 provided with the distribution.
18 Neither the name of Finger Lakes Instrumentation (FLI), LLC
19 nor the names of its contributors may be used to endorse or
20 promote products derived from this software without specific
21 prior written permission.
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
36 ======================================================================
38 Finger Lakes Instrumentation, L.L.C. (FLI)
39 web: http://www.fli-cam.com
40 email: support@fli-cam.com
44 #ifdef WIN32
45 #include <winsock.h>
46 #else
47 #include <sys/param.h>
48 #include <netinet/in.h>
49 #endif
51 #include <stdio.h>
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <time.h>
55 #include <stdarg.h>
57 #include "libfli-libfli.h"
58 #include "libfli-mem.h"
59 #include "libfli-debug.h"
60 #include "libfli-filter-focuser.h"
63 Array of filterwheel info
64 Pos = # of filters
65 Off = Offset of 0 filter from magnetic stop,
66 X - y = number of steps from filter x to filter y
68 static const wheeldata_t wheeldata[] =
70 /* POS OFF 0-1 1-2 2-3 3-4 4-5 5-6 6-7 7-8 8-9 9-A A-B B-C C-D D-E F-F F-0 */
71 { 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
72 { 1, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
73 { 2, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
74 { 3, 48, { 80, 80, 80, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
75 { 4, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
76 { 5, 0, { 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
77 { 6, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
78 { 7, 14, { 34, 34, 35, 34, 34, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
79 { 8, 18, { 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0} },
80 { 9, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
81 {10, 0, { 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0} },
82 {11, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
83 {12, 6,{ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0} },
84 {13, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
85 {14, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
86 {15, 0, { 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48} },
89 static long fli_stepmotor(flidev_t dev, long steps);
90 static long fli_getsteppos(flidev_t dev, long *pos);
91 static long fli_setfilterpos(flidev_t dev, long pos);
94 long fli_filter_focuser_open(flidev_t dev)
96 #define FWSTRING "Filter Wheel (%ld position)"
97 #define FOCSTRING "Focuser"
98 #define MODEL_LEN (sizeof(FWSTRING) + 30)
99 int err = 0;
100 unsigned long ndev;
101 long rlen, wlen;
102 unsigned short buf[16];
103 flifilterdata_t *fdata = NULL;
105 CHKDEVICE(dev);
107 DEVICE->io_timeout = 1000;
109 wlen = 2;
110 rlen = 2;
111 buf[0] = htons(0x8000);
112 IO(dev, buf, &wlen, &rlen);
113 if (ntohs(buf[0]) != 0x8000)
115 debug(FLIDEBUG_WARN, "Invalid echo, device not recognized, got %04x instead of %04x.", ntohs(buf[0]), 0x8000);
116 err = -ENODEV;
117 goto done;
120 wlen = 2;
121 rlen = 2;
122 buf[0] = htons(0x8001);
123 IO(dev, buf, &wlen, &rlen);
124 DEVICE->devinfo.fwrev = ntohs(buf[0]);
125 if ((DEVICE->devinfo.fwrev & 0xff00) != 0x8000)
127 debug(FLIDEBUG_WARN, "Invalid echo, device not recognized.");
128 err = -ENODEV;
129 goto done;
132 if ((DEVICE->device_data = xmalloc(sizeof(flifilterdata_t))) == NULL)
134 err = -ENOMEM;
135 goto done;
137 fdata = DEVICE->device_data;
138 fdata->numslots = 0;
139 fdata->stepspersec = 100;
140 fdata->currentslot = -1;
142 if (DEVICE->devinfo.fwrev == 0x8001) /* Old level of firmware */
144 if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
146 err = -ENODEV;
147 goto done;
150 debug(FLIDEBUG_INFO, "Device is old fashioned filter wheel.");
151 fdata->numslots = 5;
153 /* FIX: should model info be set first? */
154 return 0;
157 debug(FLIDEBUG_INFO, "New version of hardware found.");
158 wlen = 2;
159 rlen = 2;
160 buf[0] = htons(0x8002);
161 IO(dev, buf, &wlen, &rlen);
162 ndev = ntohs(buf[0]);
164 if ((ndev & 0xff00) != 0x8000)
166 err = -ENODEV;
167 goto done;
170 if ((DEVICE->devinfo.model = (char *)xmalloc(MODEL_LEN)) == NULL)
172 debug(FLIDEBUG_FAIL, "Could not allocate memory for model information.");
173 err = -ENOMEM;
174 goto done;
177 ndev &= 0x00ff;
179 /* switch based on the jumper settings on the filter/focuser dongle, determines how many slots in the filter wheel */
180 switch (ndev)
182 case 0x00:
183 if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
185 err = -ENODEV;
186 goto done;
188 fdata->numslots = 5;
189 snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
190 break;
192 case 0x01:
193 if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
195 err = -ENODEV;
196 goto done;
198 fdata->numslots = 3;
199 snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
200 break;
202 case 0x02:
203 if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
205 err = -ENODEV;
206 goto done;
208 fdata->numslots = 7;
209 snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
210 break;
212 case 0x03:
213 fdata->numslots = 8;
214 if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
216 err = -ENODEV;
217 goto done;
219 snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
220 break;
222 case 0x04:
223 fdata->numslots = 15;
224 fdata->stepspersec= 16;/* // 1/.06 */
225 if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
227 err = -ENODEV;
228 goto done;
230 snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
231 break;
234 case 0x05:
235 if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
237 err = -ENODEV;
238 goto done;
240 fdata->numslots = 12;
241 fdata->stepspersec= 16; /*// 1/.06*/
243 snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
244 break;
246 case 0x06:
247 fdata->numslots = 10;
248 fdata->stepspersec= 16; /*// 1/.06*/
249 if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
251 err = -ENODEV;
252 goto done;
254 snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
255 break;
258 case 0x07:
259 if (DEVICE->devinfo.type != FLIDEVICE_FOCUSER)
261 err = -ENODEV;
262 goto done;
264 snprintf(DEVICE->devinfo.model, MODEL_LEN, FOCSTRING);
265 break;
267 default:
268 err = -ENODEV;
269 goto done;
272 done:
274 if (err)
276 if (DEVICE->devinfo.model != NULL)
278 xfree(DEVICE->devinfo.model);
279 DEVICE->devinfo.model = NULL;
282 if (DEVICE->device_data != NULL)
284 xfree(DEVICE->device_data);
285 DEVICE->device_data = NULL;
288 return err;
291 debug(FLIDEBUG_INFO, "Found a %ld slot filter wheel or a focuser.",
292 fdata->numslots);
294 #undef FWSTRING
295 #undef FOCSTRING
296 #undef MODEL_LEN
298 return 0;
301 long fli_filter_focuser_close(flidev_t dev)
303 CHKDEVICE(dev);
305 if (DEVICE->devinfo.model != NULL)
307 xfree(DEVICE->devinfo.model);
308 DEVICE->devinfo.model = NULL;
311 if (DEVICE->device_data != NULL)
313 xfree(DEVICE->device_data);
314 DEVICE->device_data = NULL;
317 return 0;
320 long fli_filter_command(flidev_t dev, int cmd, int argc, ...)
322 flifilterdata_t *fdata;
323 long r;
324 va_list ap;
326 va_start(ap, argc);
327 CHKDEVICE(dev);
328 fdata = DEVICE->device_data;
330 switch (cmd)
332 case FLI_SET_FILTER_POS:
333 if (argc != 1)
334 r = -EINVAL;
335 else
337 long pos;
339 pos = *va_arg(ap, long *);
340 r = fli_setfilterpos(dev, pos);
342 break;
344 case FLI_GET_FILTER_POS:
345 if (argc != 1)
346 r = -EINVAL;
347 else
349 long *cslot;
351 cslot = va_arg(ap, long *);
352 *cslot = fdata->currentslot;
353 r = 0;
355 break;
357 case FLI_GET_FILTER_COUNT:
358 if (argc != 1)
359 r = -EINVAL;
360 else
362 long *nslots;
364 nslots = va_arg(ap, long *);
365 *nslots = fdata->numslots;
366 r = 0;
368 break;
370 case FLI_STEP_MOTOR:
371 if (argc != 1)
372 r = -EINVAL;
373 else
375 long *steps;
377 steps = va_arg(ap, long *);
378 r = fli_stepmotor(dev, *steps);
380 break;
382 case FLI_GET_STEPPER_POS:
383 if (argc != 1)
384 r = -EINVAL;
385 else
387 long *pos;
389 pos = va_arg(ap, long *);
390 r = fli_getsteppos(dev, pos);
392 break;
394 default:
395 r = -EINVAL;
398 va_end(ap);
400 return r;
403 long fli_focuser_command(flidev_t dev, int cmd, int argc, ...)
405 long r;
406 va_list ap;
408 va_start(ap, argc);
409 CHKDEVICE(dev);
411 switch (cmd)
413 case FLI_STEP_MOTOR:
414 if (argc != 1)
415 r = -EINVAL;
416 else
418 long *steps;
420 steps = va_arg(ap, long *);
421 r = fli_stepmotor(dev, *steps);
423 break;
425 case FLI_GET_STEPPER_POS:
426 if (argc != 1)
427 r = -EINVAL;
428 else
430 long *pos;
432 pos = va_arg(ap, long *);
433 r = fli_getsteppos(dev, pos);
435 break;
437 case FLI_HOME_FOCUSER:
438 if (argc != 0)
439 r = -EINVAL;
440 else
441 r = fli_setfilterpos(dev, FLI_FILTERPOSITION_HOME);
442 break;
444 default:
445 r = -EINVAL;
448 va_end(ap);
450 return r;
453 static long fli_stepmotor(flidev_t dev, long steps)
455 flifilterdata_t *fdata;
456 long dir, timeout, move, stepsleft;
457 long rlen,wlen;
458 unsigned short buf[16];
459 clock_t begin;
461 if (steps == 0)
462 return 0;
464 fdata = DEVICE->device_data;
466 dir = steps;
467 steps = abs(steps);
468 while (steps > 0)
470 if (steps > 2048)
471 move = 2048;
472 else
473 move = steps;
475 debug(FLIDEBUG_INFO, "Stepping %d steps.", move);
477 steps -= move;
478 timeout = (move / fdata->stepspersec) + 2;
480 rlen = 2;
481 wlen = 2;
482 if (dir < 0)
484 buf[0] = htons((unsigned short) (0xa000 | (unsigned short) move));
485 IO(dev, buf, &wlen, &rlen);
486 if ((ntohs(buf[0]) & 0xf000) != 0xa000)
488 debug(FLIDEBUG_WARN, "Invalid echo.");
489 return -EIO;
492 else
494 buf[0] = htons((unsigned short) (0x9000 | (unsigned short) move));
495 IO(dev, buf, &wlen, &rlen);
496 if ((ntohs(buf[0]) & 0xf000) != 0x9000)
498 debug(FLIDEBUG_WARN, "Invalid echo.");
499 return -EIO;
503 begin = clock();
504 stepsleft = 0;
505 while (stepsleft != 0x7000)
507 buf[0] = htons(0x7000);
508 IO(dev, buf, &wlen, &rlen);
509 stepsleft = ntohs(buf[0]);
511 if (((clock() - begin) / CLOCKS_PER_SEC) > timeout)
513 debug(FLIDEBUG_WARN, "A device timeout has occurred.");
514 return -EIO;
519 return 0;
522 static long fli_getsteppos(flidev_t dev, long *pos)
524 long poslow, poshigh;
525 long rlen, wlen;
526 unsigned short buf[16];
528 rlen = 2; wlen = 2;
529 buf[0] = htons(0x6000);
530 IO(dev, buf, &wlen, &rlen);
531 poslow = ntohs(buf[0]);
532 if ((poslow & 0xf000) != 0x6000)
533 return -EIO;
535 buf[0] = htons(0x6001);
536 IO(dev, buf, &wlen, &rlen);
537 poshigh = ntohs(buf[0]);
538 if ((poshigh & 0xf000) != 0x6000)
539 return -EIO;
541 if ((poshigh & 0x0080) > 0)
543 *pos = ((~poslow) & 0xff) + 1;
544 *pos += (256 * ((~poshigh) & 0xff));
545 *pos = -(*pos);
547 else
549 *pos = (poslow & 0xff) + 256 * (poshigh & 0xff);
551 return 0;
555 static long fli_setfilterpos(flidev_t dev, long pos)
557 flifilterdata_t *fdata;
558 long rlen, wlen;
559 unsigned short buf[16];
560 long move, i, steps;
562 fdata = DEVICE->device_data;
564 if (pos == FLI_FILTERPOSITION_HOME)
565 fdata->currentslot = FLI_FILTERPOSITION_HOME;
567 if (fdata->currentslot < 0)
569 debug(FLIDEBUG_INFO, "Home filter wheel/focuser.");
570 /* //set the timeout*/
571 DEVICE->io_timeout = (DEVICE->devinfo.type == FLIDEVICE_FILTERWHEEL ? 5000 : 30000);
572 /*//10,12,15 pos filterwheel needs a longer timeout t*/
573 if(fdata->numslots == 12||fdata->numslots == 10)
575 DEVICE->io_timeout = 120000;
577 if(fdata->numslots == 15)
579 DEVICE->io_timeout = 200000;
582 wlen = 2;
583 rlen = 2;
584 buf[0] = htons(0xf000);
585 IO(dev, buf, &wlen, &rlen);
586 if (ntohs(buf[0]) != 0xf000)
587 return -EIO;
589 DEVICE->io_timeout = 1000;
591 debug(FLIDEBUG_INFO, "Moving %d steps to home position.",
592 wheeldata[fdata->numslots].n_offset);
594 COMMAND(fli_stepmotor(dev, - (wheeldata[fdata->numslots].n_offset)));
595 fdata->currentslot = 0;
598 if (pos == FLI_FILTERPOSITION_HOME)
599 return 0;
601 if (pos >= fdata->numslots)
603 debug(FLIDEBUG_WARN, "Requested slot (%d) exceeds number of slots.", pos);
604 return -EINVAL;
607 if (pos == fdata->currentslot)
608 return 0;
610 move = pos - fdata->currentslot;
612 if (move < 0)
613 move += fdata->numslots;
615 steps = 0;
616 for (i=0; i < move; i++)
617 steps += wheeldata[fdata->numslots].n_steps[i % fdata->numslots];
619 debug(FLIDEBUG_INFO, "Move filter wheel %d steps.", steps);
621 COMMAND(fli_stepmotor(dev, - (steps)));
622 fdata->currentslot = pos;
624 return 0;