source: BAORadio/libindi/v1.0.1/drivers/filter_wheel/fli_wheel.c @ 614

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

import libindi (JEC)

File size: 16.7 KB
Line 
1#if 0
2    FLI WHEEL
3    INDI Interface for Finger Lakes Instruments Filter Wheels
4    Copyright (C) 2005 Gaetano Vocca (yagvoc-web AT yahoo DOT it)
5        Based on fli_ccd by Jasem Mutlaq (mutlaqja AT ikarustech DOT com)
6
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with this library; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <stdarg.h>
27#include <math.h>
28#include <unistd.h>
29#include <time.h>
30#include <fcntl.h>
31#include <errno.h>
32#include <sys/stat.h>
33#include <sys/time.h>
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <netdb.h>
38
39#include "libfli.h"
40#include "indidevapi.h"
41#include "eventloop.h"
42#include "indicom.h"
43
44void ISInit(void);
45void getBasicData(void);
46void ISPoll(void *);
47void handleExposure(void *);
48void connectFilter(void);
49int  findwheel(flidomain_t domain);
50int  manageDefaults(char errmsg[]);
51int  checkPowerS(ISwitchVectorProperty *sp);
52int  checkPowerN(INumberVectorProperty *np);
53int  checkPowerT(ITextVectorProperty *tp);
54int  getOnSwitch(ISwitchVectorProperty *sp);
55int  isFilterConnected(void);
56
57double min(void);
58double max(void);
59
60extern char* me;
61extern int errno;
62
63#define mydev           "FLI Wheel"
64
65#define MAIN_GROUP      "Main Control"
66
67#define LAST_FILTER  14         /* Max slot index */
68#define FIRST_FILTER 0          /* Min slot index */
69
70#define currentFilter   FilterN[0].value
71
72#define POLLMS          1000
73#define LIBVERSIZ       1024
74#define PREFIXSIZ       64
75#define PIPEBUFSIZ      8192
76#define FRAME_ILEN      64
77
78typedef struct {
79  flidomain_t domain;
80  char *dname;
81  char *name;
82  char *model;
83  long HWRevision;
84  long FWRevision;
85  long current_filter;
86  long filter_count;
87  long home;
88} cam_t;
89
90
91static flidev_t fli_dev;
92static cam_t *FLIWheel;
93static int portSwitchIndex;
94static int simulation;
95static int targetFilter;
96
97long int Domains[] = { FLIDOMAIN_USB, FLIDOMAIN_SERIAL, FLIDOMAIN_PARALLEL_PORT,  FLIDOMAIN_INET };
98
99/*INDI controls */
100
101/* Connect/Disconnect */
102static ISwitch PowerS[]                 = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}};
103static ISwitchVectorProperty PowerSP    = { mydev, "CONNECTION" , "Connection", MAIN_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0};
104
105/* Types of Ports */
106static ISwitch PortS[]                  = {{"USB", "", ISS_ON, 0, 0}, {"Serial", "", ISS_OFF, 0, 0}, {"Parallel", "", ISS_OFF, 0, 0}, {"INet", "", ISS_OFF, 0, 0}};
107static ISwitchVectorProperty PortSP     = { mydev, "Port Type", "", MAIN_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, PortS, NARRAY(PortS), "", 0};
108 
109/* Filter control */
110static INumber FilterN[]          = { {"FILTER_SLOT_VALUE", "Active Filter", "%2.0f", FIRST_FILTER, LAST_FILTER, 1, 0, 0, 0, 0}};
111static INumberVectorProperty FilterNP = { mydev, "FILTER_SLOT", "Filter", MAIN_GROUP, IP_RW, 0, IPS_IDLE, FilterN, NARRAY(FilterN), "", 0};
112 
113/* send client definitions of all properties */
114void ISInit()
115{
116        static int isInit=0;
117       
118        if (isInit)
119                return;
120       
121        /* USB by default {USB, SERIAL, PARALLEL, INET} */
122        portSwitchIndex = 0;
123
124        targetFilter = 0;
125
126        /* No Simulation by default */
127        simulation = 0;
128
129        /* Enable the following for simulation mode */
130        /*simulation = 1;
131        IDLog("WARNING: Simulation is on\n");*/
132       
133        IEAddTimer (POLLMS, ISPoll, NULL);
134       
135        isInit = 1; 
136}
137
138void ISGetProperties (const char *dev)
139{ 
140
141        ISInit();
142       
143        if (dev && strcmp (mydev, dev))
144                return;
145       
146        /* Main Control */
147        IDDefSwitch(&PowerSP, NULL);
148        IDDefSwitch(&PortSP, NULL);
149        IDDefNumber(&FilterNP, NULL);
150       
151}
152
153void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) 
154{
155  INDI_UNUSED(dev);
156  INDI_UNUSED(name);
157  INDI_UNUSED(sizes);
158  INDI_UNUSED(blobsizes);
159  INDI_UNUSED(blobs);
160  INDI_UNUSED(formats);
161  INDI_UNUSED(names);
162  INDI_UNUSED(n);
163}
164void ISSnoopDevice (XMLEle *root) 
165{
166  INDI_UNUSED(root);
167}
168
169void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
170{
171        /* ignore if not ours */
172        if (dev && strcmp (dev, mydev))
173                return;
174           
175        ISInit();
176           
177        /* Port type */
178        if (!strcmp (name, PortSP.name))
179        {
180                PortSP.s = IPS_IDLE; 
181                IUResetSwitch(&PortSP);
182                IUUpdateSwitch(&PortSP, states, names, n);
183                portSwitchIndex = getOnSwitch(&PortSP);
184               
185                PortSP.s = IPS_OK; 
186                IDSetSwitch(&PortSP, NULL);
187                return;
188        }
189       
190        /* Connection */
191        if (!strcmp (name, PowerSP.name))
192        {
193                IUResetSwitch(&PowerSP);
194                IUUpdateSwitch(&PowerSP, states, names, n);
195                connectFilter();
196                return;
197        }
198       
199     
200}
201
202void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
203{
204        ISInit();
205       
206        /* ignore if not ours */ 
207        if (dev && strcmp (mydev, dev))
208                return;
209
210        /* suppress warning */
211        n=n; dev=dev; name=name; names=names; texts=texts;
212}
213
214
215void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
216{
217        long err;
218        INumber *np;
219        long newFilter;
220
221        n = n;
222       
223        /* ignore if not ours */
224        if (dev && strcmp (dev, mydev))
225            return;
226           
227        ISInit();
228       
229       
230if (!strcmp(FilterNP.name, name)) {
231                if (simulation) {
232                        targetFilter = values[0];
233                        FilterNP.s = IPS_BUSY;
234                        IDSetNumber(&FilterNP, "Setting current filter to slot %d", targetFilter);
235                        IDLog("Setting current filter to slot %d\n", targetFilter);
236                        return;
237                }
238
239
240                if (!isFilterConnected()) {
241                        IDMessage(mydev, "Device not connected.");
242                        FilterNP.s = IPS_IDLE;
243                        IDSetNumber(&FilterNP, NULL);
244                        return;
245                }
246               
247                targetFilter = values[0];
248               
249                np = IUFindNumber(&FilterNP, names[0]);
250               
251                if (!np)
252                {
253                        FilterNP.s = IPS_ALERT;
254                        IDSetNumber(&FilterNP, "Unknown error. %s is not a member of %s property.", names[0], name);
255                        return;
256                }
257               
258                if (targetFilter < FIRST_FILTER || targetFilter > FLIWheel->filter_count - 1)
259                {
260                        FilterNP.s = IPS_ALERT;
261                        IDSetNumber(&FilterNP, "Error: valid range of filter is from %d to %d", FIRST_FILTER, LAST_FILTER);
262                        return;
263                }
264
265                FilterNP.s = IPS_BUSY;
266                IDSetNumber(&FilterNP, "Setting current filter to slot %d", targetFilter);
267                IDLog("Setting current filter to slot %d\n", targetFilter);
268               
269                if ( (err = FLISetFilterPos(fli_dev, targetFilter)))
270                {
271                        FilterNP.s = IPS_ALERT;
272                        IDSetNumber(&FilterNP, "FLISetFilterPos() failed. %s.", strerror((int)-err));
273                        IDLog("FLISetFilterPos() failed. %s.", strerror((int)-err));
274                        return;
275                }
276               
277                /* Check current filter position */
278                if (( err = FLIGetFilterPos(fli_dev, &newFilter))) {
279                        FilterNP.s = IPS_ALERT;
280                        IDSetNumber(&FilterNP, "FLIGetFilterPos() failed. %s.", strerror((int)-err));
281                        IDLog("FLIGetFilterPos() failed. %s.\n", strerror((int)-err));
282                        return;
283                }
284               
285                if (newFilter == targetFilter) {
286                        FLIWheel->current_filter = targetFilter;
287                        FilterN[0].value = FLIWheel->current_filter;
288                        FilterNP.s = IPS_OK;
289                        IDSetNumber(&FilterNP, "Filter set to slot #%d", targetFilter);
290                        return;
291                }
292
293                return;
294        }
295}
296
297
298/* Retrieves basic data from the Wheel upon connection like temperature, array size, firmware..etc */
299void getBasicData()
300{
301
302        char buff[2048];
303        long err;
304       
305        if ((err = FLIGetModel (fli_dev, buff, 2048)))
306        {
307                IDMessage(mydev, "FLIGetModel() failed. %s.", strerror((int)-err));
308                IDLog("FLIGetModel() failed. %s.\n", strerror((int)-err));
309                return;
310        }
311        else
312        {
313                if ( (FLIWheel->model = malloc (sizeof(char) * 2048)) == NULL)
314                {
315                IDMessage(mydev, "malloc() failed.");
316                IDLog("malloc() failed.");
317                return;
318                }
319               
320                strcpy(FLIWheel->model, buff);
321        }
322 
323        if (( err = FLIGetHWRevision(fli_dev, &FLIWheel->HWRevision)))
324        {
325                IDMessage(mydev, "FLIGetHWRevision() failed. %s.", strerror((int)-err));
326                IDLog("FLIGetHWRevision() failed. %s.\n", strerror((int)-err));
327               
328                return;
329        }
330       
331        if (( err = FLIGetFWRevision(fli_dev, &FLIWheel->FWRevision)))
332        {
333                IDMessage(mydev, "FLIGetFWRevision() failed. %s.", strerror((int)-err));
334                IDLog("FLIGetFWRevision() failed. %s.\n", strerror((int)-err));
335                return;
336        }
337       
338        if (( err = FLIGetFilterCount(fli_dev, &FLIWheel->filter_count)))
339        {
340                IDMessage(mydev, "FLIGetFilterCount() failed. %s.", strerror((int)-err));
341                IDLog("FLIGetFilterCount() failed. %s.\n", strerror((int)-err));
342                return;
343        }
344 
345        IDLog("The filter count is %ld\n", FLIWheel->filter_count);
346       
347        FilterN[0].max = FLIWheel->filter_count - 1;
348        FilterNP.s = IPS_OK;
349       
350        IUUpdateMinMax(&FilterNP);
351        IDSetNumber(&FilterNP, "Setting basic data");
352       
353        IDLog("Exiting getBasicData()\n");
354 
355}
356
357int manageDefaults(char errmsg[])
358{
359        long err;
360       
361        /*IDLog("Resetting filter wheel to slot %d\n", 0);
362        FLIWheel->home = 0;
363        if (( err = FLISetFilterPos(fli_dev, 0)))
364        {
365                IDMessage(mydev, "FLISetFilterPos() failed. %s.", strerror((int)-err));
366                IDLog("FLISetFilterPos() failed. %s.\n", strerror((int)-err));
367                return (int)-err;
368        }*/
369
370       
371        if (( err = FLIGetFilterPos(fli_dev, &FLIWheel->current_filter)))
372        {
373                IDMessage(mydev, "FLIGetFilterPos() failed. %s.", strerror((int)-err));
374                IDLog("FLIGetFilterPos() failed. %s.\n", strerror((int)-err));
375                return (int)-err;
376        }
377 
378        IDLog("The current filter is %ld\n", FLIWheel->current_filter);
379
380        FilterN[0].value = FLIWheel->current_filter;
381        IDSetNumber(&FilterNP, "Storing defaults");
382       
383        /* Success */
384        return 0;
385   
386}
387
388void ISPoll(void *p)
389{
390  static int simMTC = 5;
391
392  if (!isFilterConnected())
393  {
394      IEAddTimer (POLLMS, ISPoll, NULL);
395      return;
396  }
397
398
399  switch (FilterNP.s)
400  {
401    case IPS_IDLE:
402    case IPS_OK:
403       break;
404 
405   
406   case IPS_BUSY:
407    /* Simulate that it takes 5 seconds to change slot */
408    if (simulation)
409    {
410        simMTC--;
411        if (simMTC == 0)
412        {
413           simMTC = 5;
414           currentFilter = targetFilter;
415           FilterNP.s = IPS_OK;
416           IDSetNumber(&FilterNP, "Filter set to slot #%2.0f", currentFilter);
417           break;
418        }
419        IDSetNumber(&FilterNP, NULL);
420        break;
421    }
422
423
424    /*if (( err = FLIGetFilterPos(fli_dev, &currentFilter)))
425        {
426                FilterNP.s = IPS_ALERT;
427                IDSetNumber(&FilterNP, "FLIGetFilterPos() failed. %s.", strerror((int)-err));
428                IDLog("FLIGetFilterPos() failed. %s.\n", strerror((int)-err));
429                return;
430        }
431
432        if (targetFilter == currentFilter)
433        {
434                FLIWheel->current_filter = currentFilter;
435                FilterNP.s = IPS_OK;
436                IDSetNumber(&FilterNP, "Filter set to slot #%2.0f", currentFilter);
437                return;
438        }
439       
440        IDSetNumber(&FilterNP, NULL);*/
441        break;
442
443   case IPS_ALERT:
444    break;
445 }
446
447   IEAddTimer (POLLMS, ISPoll, NULL);
448
449}
450
451
452
453int getOnSwitch(ISwitchVectorProperty *sp)
454{
455  int i=0;
456 for (i=0; i < sp->nsp ; i++)
457 {
458   /*IDLog("Switch %s is %s\n", sp->sp[i].name, sp->sp[i].s == ISS_ON ? "On" : "Off");*/
459     if (sp->sp[i].s == ISS_ON)
460      return i;
461 }
462
463 return -1;
464}
465
466int checkPowerS(ISwitchVectorProperty *sp)
467{
468
469  if (simulation)
470   return 0;
471
472  if (PowerSP.s != IPS_OK)
473  {
474    if (!strcmp(sp->label, ""))
475        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", sp->name);
476    else
477        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", sp->label);
478       
479    sp->s = IPS_IDLE;
480    IDSetSwitch(sp, NULL);
481    return -1;
482  }
483
484  return 0;
485}
486
487int checkPowerN(INumberVectorProperty *np)
488{
489  if (simulation)
490   return 0;
491
492  if (PowerSP.s != IPS_OK)
493  {
494     if (!strcmp(np->label, ""))
495        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", np->name);
496    else
497        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", np->label);
498   
499    np->s = IPS_IDLE;
500    IDSetNumber(np, NULL);
501    return -1;
502  }
503
504  return 0;
505}
506
507int checkPowerT(ITextVectorProperty *tp)
508{
509   if (simulation)
510    return 0;
511
512  if (PowerSP.s != IPS_OK)
513  {
514    if (!strcmp(tp->label, ""))
515        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", tp->name);
516    else
517        IDMessage (mydev, "Cannot change property %s while the wheel is offline.", tp->label);
518       
519    tp->s = IPS_IDLE;
520    IDSetText(tp, NULL);
521    return -1;
522  }
523
524  return 0;
525
526}
527
528void connectFilter()
529{
530        long err;
531        char errmsg[ERRMSG_SIZE];
532 
533 
534        /* USB by default {USB, SERIAL, PARALLEL, INET} */
535        switch (PowerS[0].s)
536        {
537                case ISS_ON:
538                       
539                        if (simulation)
540                        {
541                                /* Success! */
542                                PowerS[0].s = ISS_ON;
543                                PowerS[1].s = ISS_OFF;
544                                PowerSP.s = IPS_OK;
545                                IDSetSwitch(&PowerSP, "Simulation Wheel is online.");
546                                IDLog("Simulation Wheel is online.\n");
547                                return;
548                        }
549
550                        IDLog("Current portSwitch is %d\n", portSwitchIndex);
551                        IDLog("Attempting to find the device in domain %ld\n", Domains[portSwitchIndex]);
552
553                        if (findwheel(Domains[portSwitchIndex]))
554                        {
555                                PowerSP.s = IPS_IDLE;
556                                PowerS[0].s = ISS_OFF;
557                                PowerS[1].s = ISS_ON;
558                                IDSetSwitch(&PowerSP, "Error: no wheels were detected.");
559                                IDLog("Error: no wheels were detected.\n");
560                                return;
561                        }
562                       
563                        if ((err = FLIOpen(&fli_dev, FLIWheel->name, FLIWheel->domain | FLIDEVICE_FILTERWHEEL)))
564                        {
565                                PowerSP.s = IPS_IDLE;
566                                PowerS[0].s = ISS_OFF;
567                                PowerS[1].s = ISS_ON;
568                                IDSetSwitch(&PowerSP, "Error: FLIOpen() failed. %s.", strerror( (int) -err));
569                                IDLog("Error: FLIOpen() failed. %s.\n", strerror( (int) -err));
570                                return;
571                        }
572
573                        /* Success! */
574                        PowerS[0].s = ISS_ON;
575                        PowerS[1].s = ISS_OFF;
576                        PowerSP.s = IPS_OK;
577                        IDSetSwitch(&PowerSP, "Wheel is online. Retrieving basic data.");
578                        IDLog("Wheel is online. Retrieving basic data.\n");
579                        getBasicData();
580                       
581
582                        if (manageDefaults(errmsg))
583                        {
584                                IDMessage(mydev, errmsg, NULL);
585                                IDLog("%s", errmsg);
586                                return;
587                        }
588
589                        break;
590               
591                case ISS_OFF:
592
593                        if (simulation)
594                        {
595                                PowerS[0].s = ISS_OFF;
596                                PowerS[1].s = ISS_ON;
597                                PowerSP.s = IPS_IDLE;
598                                IDSetSwitch(&PowerSP, "Wheel is offline.");
599                                return;
600                        }
601
602                        PowerS[0].s = ISS_OFF;
603                        PowerS[1].s = ISS_ON;
604                        PowerSP.s = IPS_IDLE;
605                        if ((err = FLIClose(fli_dev))) {
606                                PowerSP.s = IPS_ALERT;
607                                IDSetSwitch(&PowerSP, "Error: FLIClose() failed. %s.", strerror( (int) -err));
608                                IDLog("Error: FLIClose() failed. %s.\n", strerror( (int) -err));
609                                return;
610                        }
611                        IDSetSwitch(&PowerSP, "Wheel is offline.");
612                        break;
613        }
614}
615
616/* isFilterConnected: return 1 if we have a connection, 0 otherwise */
617int isFilterConnected(void)
618{
619   if (simulation)
620     return 1;
621
622   return ((PowerS[0].s == ISS_ON) ? 1 : 0);
623}
624
625int findwheel(flidomain_t domain)
626{
627        char **devlist;
628        long err;
629       
630        IDLog("In find Camera, the domain is %ld\n", domain);
631       
632        if (( err = FLIList(domain | FLIDEVICE_FILTERWHEEL, &devlist)))
633        {
634                IDLog("FLIList() failed. %s\n", strerror((int)-err));
635                return -1;
636        }
637       
638        if (devlist != NULL && devlist[0] != NULL)
639        {
640                int i;
641
642                IDLog("Trying to allocate memory to FLIWheel\n");
643                if ((FLIWheel = malloc (sizeof (cam_t))) == NULL)
644                {
645                        IDLog("malloc() failed.\n");
646                        return -1;
647                }
648               
649                for (i = 0; devlist[i] != NULL; i++)
650                {
651                        int j;
652       
653                        for (j = 0; devlist[i][j] != '\0'; j++)
654                                if (devlist[i][j] == ';')
655                                {
656                                        devlist[i][j] = '\0';
657                                        break;
658                                }
659                }
660
661                FLIWheel->domain = domain;
662               
663                /* Each driver handles _only_ one camera for now */
664                switch (domain)
665                {
666                        case FLIDOMAIN_PARALLEL_PORT:
667                                FLIWheel->dname = strdup("parallel port");
668                                break;
669       
670                        case FLIDOMAIN_USB:
671                                FLIWheel->dname = strdup("USB");
672                                break;
673       
674                        case FLIDOMAIN_SERIAL:
675                                FLIWheel->dname = strdup("serial");
676                                break;
677       
678                        case FLIDOMAIN_INET:
679                                FLIWheel->dname = strdup("inet");
680                                break;
681       
682                        default:
683                                FLIWheel->dname = strdup("Unknown domain");
684                }
685               
686                IDLog("Domain set OK\n");
687               
688                FLIWheel->name = strdup(devlist[0]);
689                               
690                if ((err = FLIFreeList(devlist)))
691                {
692                        IDLog("FLIFreeList() failed. %s.\n", strerror((int)-err));
693                        return -1;
694                }
695     
696        } /* end if */
697        else
698        {
699                if ((err = FLIFreeList(devlist)))
700                {
701                        IDLog("FLIFreeList() failed. %s.\n", strerror((int)-err));
702                        return -1;
703                }
704               
705                return -1;
706        }
707
708        IDLog("Findcam() finished successfully.\n");
709        return 0;
710}
Note: See TracBrowser for help on using the repository browser.