source: BAORadio/libindi/v1.0.1/drivers/ccd/fli_ccd.c @ 614

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

import libindi (JEC)

File size: 37.3 KB
Line 
1#if 0
2    FLI CCD
3    INDI Interface for Finger Lakes Instruments CCDs
4    Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
20#endif
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <stdarg.h>
26#include <math.h>
27#include <unistd.h>
28#include <time.h>
29#include <fcntl.h>
30#include <errno.h>
31#include <sys/stat.h>
32#include <sys/time.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <netinet/in.h>
36#include <netdb.h>
37#include <zlib.h>
38
39#include <fitsio.h>
40
41#include <libfli.h>
42#include "indidevapi.h"
43#include "eventloop.h"
44#include "indicom.h"
45
46void ISInit(void);
47void getBasicData(void);
48void ISPoll(void *);
49void handleExposure(void *);
50void connectCCD(void);
51void getBasicData(void);
52void uploadFile(const char* filename);
53int  writeFITS(const char* filename, char errmsg[]);
54int  findcam(flidomain_t domain);
55int  setImageArea(char errmsg[]);
56int  manageDefaults(char errmsg[]);
57int  grabImage(void);
58int  checkPowerS(ISwitchVectorProperty *sp);
59int  checkPowerN(INumberVectorProperty *np);
60int  checkPowerT(ITextVectorProperty *tp);
61int  getOnSwitch(ISwitchVectorProperty *sp);
62int  isCCDConnected(void);
63void addFITSKeywords(fitsfile *fptr);
64
65double min(void);
66double max(void);
67
68extern char* me;
69extern int errno;
70
71#define mydev           "FLI CCD"
72
73#define COMM_GROUP      "Communication"
74#define EXPOSE_GROUP    "Expose"
75#define IMAGE_GROUP     "Image Settings"
76#define DATA_GROUP      "Data Channel"
77
78#define MAX_CCD_TEMP    45              /* Max CCD temperature */
79#define MIN_CCD_TEMP    -55             /* Min CCD temperature */
80#define MAX_X_BIN       16.             /* Max Horizontal binning */
81#define MAX_Y_BIN       16.             /* Max Vertical binning */
82#define MAX_PIXELS      4096            /* Max number of pixels in one dimension */
83#define POLLMS          1000            /* Polling time (ms) */
84#define TEMP_THRESHOLD  .25             /* Differential temperature threshold (C)*/
85#define NFLUSHES        1               /* Number of times a CCD array is flushed before an exposure */
86
87#define FILENAMESIZ     2048
88#define LIBVERSIZ       1024
89#define PREFIXSIZ       64
90#define PIPEBUFSIZ      8192
91#define FRAME_ILEN      64
92#define TEMPFILE_LEN    16
93
94enum FLIFrames { LIGHT_FRAME = 0, BIAS_FRAME, DARK_FRAME, FLAT_FRAME };
95
96
97typedef struct {
98  flidomain_t domain;
99  char *dname;
100  char *name;
101  char *model;
102  long HWRevision;
103  long FWRevision;
104  double x_pixel_size;
105  double y_pixel_size;
106  long Array_Area[4];
107  long Visible_Area[4];
108  int width, height;
109  double temperature;
110} cam_t;
111
112typedef struct {
113int  width;
114int  height;
115int  frameType;
116int  expose;
117unsigned short  *img;
118} img_t;
119
120/*static int streamTimerID;              Stream ID */
121
122static flidev_t fli_dev;
123static cam_t *FLICam;
124static img_t *FLIImg;
125static int portSwitchIndex;
126
127long int Domains[] = { FLIDOMAIN_USB, FLIDOMAIN_SERIAL, FLIDOMAIN_PARALLEL_PORT,  FLIDOMAIN_INET };
128
129/*INDI controls */
130
131/* Connect/Disconnect */
132static ISwitch ConnectS[]               = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}};
133static ISwitchVectorProperty ConnectSP  = { mydev, "CONNECTION" , "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE, ConnectS, NARRAY(ConnectS), "", 0};
134
135/* Types of Ports */
136static ISwitch PortS[]                  = {{"USB", "", ISS_ON, 0, 0}, {"Serial", "", ISS_OFF, 0, 0}, {"Parallel", "", ISS_OFF, 0, 0}, {"INet", "", ISS_OFF, 0, 0}};
137static ISwitchVectorProperty PortSP     = { mydev, "Port Type", "", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, PortS, NARRAY(PortS), "", 0};
138
139/* Types of Frames */
140static ISwitch FrameTypeS[]             = { {"FRAME_LIGHT", "Light", ISS_ON, 0, 0}, {"FRAME_BIAS", "Bias", ISS_OFF, 0, 0}, {"FRAME_DARK", "Dark", ISS_OFF, 0, 0}, {"FRAME_FLAT", "Flat Field", ISS_OFF, 0, 0}};
141static ISwitchVectorProperty FrameTypeSP = { mydev, "CCD_FRAME_TYPE", "Frame Type", EXPOSE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, FrameTypeS, NARRAY(FrameTypeS), "", 0};
142
143/* Frame coordinates. Full frame is default */
144static INumber FrameN[]                 = {
145 { "X", "X", "%.0f", 0.,     MAX_PIXELS, 1., 0., 0, 0, 0},
146 { "Y", "Y", "%.0f", 0.,     MAX_PIXELS, 1., 0., 0, 0, 0},
147 { "WIDTH", "Width", "%.0f", 0., MAX_PIXELS, 1., 0., 0, 0, 0},
148 { "HEIGHT", "Height", "%.0f",0., MAX_PIXELS, 1., 0., 0, 0, 0}};
149 static INumberVectorProperty FrameNP = { mydev, "CCD_FRAME", "Frame", IMAGE_GROUP, IP_RW, 60, IPS_IDLE, FrameN, NARRAY(FrameN), "", 0};
150 
151 /* Binning */ 
152 static INumber BinningN[]       = {
153 { "HOR_BIN", "X", "%0.f", 1., MAX_X_BIN, 1., 1., 0, 0, 0},
154 { "VER_BIN", "Y", "%0.f", 1., MAX_Y_BIN, 1., 1., 0, 0, 0}};
155 static INumberVectorProperty BinningNP = { mydev, "CCD_BINNING", "Binning", IMAGE_GROUP, IP_RW, 60, IPS_IDLE, BinningN, NARRAY(BinningN), "", 0};
156 
157 /* Exposure time */
158  static INumber ExposeTimeWN[]    = {{ "CCD_EXPOSURE_VALUE", "Duration (s)", "%5.2f", 0., 36000., .5, 1., 0, 0, 0}};
159  static INumberVectorProperty ExposeTimeWNP = { mydev, "CCD_EXPOSURE_REQUEST", "Expose", EXPOSE_GROUP, IP_WO, 36000, IPS_IDLE, ExposeTimeWN, NARRAY(ExposeTimeWN), "", 0};
160
161  static INumber ExposeTimeRN[]    = {{ "CCD_EXPOSURE_VALUE", "Duration (s)", "%5.2f", 0., 36000., .5, 1., 0, 0, 0}};
162  static INumberVectorProperty ExposeTimeRNP = { mydev, "CCD_EXPOSURE", "Expose", EXPOSE_GROUP, IP_RO, 36000, IPS_IDLE, ExposeTimeRN, NARRAY(ExposeTimeRN), "", 0};
163 
164  /* Temperature control */
165 static INumber TemperatureN[]    = { {"CCD_TEMPERATURE_VALUE", "Temperature", "%+06.2f", MIN_CCD_TEMP, MAX_CCD_TEMP, .2, 0., 0, 0, 0}};
166 static INumberVectorProperty TemperatureNP = { mydev, "CCD_TEMPERATURE", "Temperature (C)", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE, TemperatureN, NARRAY(TemperatureN), "", 0};
167 
168  /* Pixel size (µm) */
169static INumber PixelSizeN[]     = {
170        { "Width", "", "%.0f", 0. , 0., 0., 0., 0, 0, 0},
171        { "Height", "", "%.0f", 0. , 0., 0., 0., 0, 0, 0}};
172static INumberVectorProperty PixelSizeNP = { mydev, "Pixel Size (µm)", "", DATA_GROUP, IP_RO, 0, IPS_IDLE, PixelSizeN, NARRAY(PixelSizeN), "", 0};
173
174/* BLOB for sending image */
175static IBLOB imageB = {"FITS_BLOB", "FITS", "", 0, 0, 0, 0, 0, 0, 0};
176static IBLOBVectorProperty imageBP = {mydev, "CCD_FITS_BLOB", "BLOB", COMM_GROUP,
177  IP_RO, 0, IPS_IDLE, &imageB, 1, "", 0};
178
179/* send client definitions of all properties */
180void ISInit()
181{
182  static int isInit=0;
183
184 if (isInit)
185  return;
186 
187 /* USB by default {USB, SERIAL, PARALLEL, INET} */
188 portSwitchIndex = 0;
189 
190 FLIImg = malloc (sizeof(img_t));
191 
192 if (FLIImg == NULL)
193 {
194   IDMessage(mydev, "Error: unable to initialize driver. Low memory.");
195   IDLog("Error: unable to initialize driver. Low memory.");
196   return;
197 }
198 
199 IEAddTimer (POLLMS, ISPoll, NULL);
200
201 isInit = 1;
202 
203}
204
205void ISGetProperties (const char *dev)
206{ 
207
208   ISInit();
209 
210  if (dev && strcmp (mydev, dev))
211    return;
212
213  /* COMM_GROUP */
214  IDDefSwitch(&ConnectSP, NULL);
215  IDDefSwitch(&PortSP, NULL);
216  IDDefBLOB(&imageBP, NULL);
217 
218  /* Expose */
219  IDDefSwitch(&FrameTypeSP, NULL); 
220  IDDefNumber(&ExposeTimeWNP, NULL);
221  IDDefNumber(&ExposeTimeRNP, NULL);
222  IDDefNumber(&TemperatureNP, NULL);
223 
224  /* Image Group */
225  IDDefNumber(&FrameNP, NULL);
226  IDDefNumber(&BinningNP, NULL);
227 
228}
229
230void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) {}
231void ISSnoopDevice (XMLEle *root) {}
232 
233void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
234{
235        long err;
236        int i;
237        ISwitch *sp;
238       
239        /* ignore if not ours */
240        if (dev && strcmp (dev, mydev))
241            return;
242           
243        ISInit();
244
245        /* Port type */
246        if (!strcmp (name, PortSP.name))
247        {
248          PortSP.s = IPS_IDLE; 
249          IUResetSwitch(&PortSP);
250          IUUpdateSwitch(&PortSP, states, names, n);
251          portSwitchIndex = getOnSwitch(&PortSP);
252         
253          PortSP.s = IPS_OK; 
254          IDSetSwitch(&PortSP, NULL);
255          return;
256        }
257       
258        /* Connection */
259        if (!strcmp (name, ConnectSP.name))
260        {
261          if (IUUpdateSwitch(&ConnectSP, states, names, n) < 0)
262                return;
263          connectCCD();
264          return;
265        }
266       
267     /* Frame Type */
268     if (!strcmp(FrameTypeSP.name, name))
269     {
270       if (checkPowerS(&FrameTypeSP))
271         return;
272         
273       for (i = 0; i < n ; i++)
274       {
275         sp = IUFindSwitch(&FrameTypeSP, names[i]);
276         
277         if (!sp)
278         {
279              FrameTypeSP.s = IPS_ALERT;
280              IDSetSwitch(&FrameTypeSP, "Unknown error. %s is not a member of %s property.", names[0], name);
281              return;
282         }
283         
284         /* NORMAL, BIAS, or FLAT */
285         if ( (sp == &FrameTypeS[LIGHT_FRAME] || sp == &FrameTypeS[FLAT_FRAME]) && states[i] == ISS_ON)
286         {
287           if (sp == &FrameTypeS[LIGHT_FRAME])
288             FLIImg->frameType = LIGHT_FRAME;
289           else
290             FLIImg->frameType = FLAT_FRAME;
291           
292           if ((err = FLISetFrameType(fli_dev, FLI_FRAME_TYPE_NORMAL) ))
293           {
294            IUResetSwitch(&FrameTypeSP);
295            FrameTypeS[LIGHT_FRAME].s = ISS_ON;
296            FrameTypeSP.s = IPS_ALERT;
297            IDSetSwitch(&FrameTypeSP, "FLISetFrameType() failed. %s.\n", strerror((int)-err));
298            IDLog("FLISetFrameType() failed. %s.\n", strerror((int)-err));
299            return;
300           }
301         
302           IUResetSwitch(&FrameTypeSP);
303           sp->s = ISS_ON; 
304           FrameTypeSP.s = IPS_OK;
305           IDSetSwitch(&FrameTypeSP, NULL);
306           break;
307         }
308         /* DARK AND BIAS */
309         else if ( (sp == &FrameTypeS[DARK_FRAME] || sp == &FrameTypeS[BIAS_FRAME]) && states[i] == ISS_ON)
310         {
311           
312          if (sp == &FrameTypeS[DARK_FRAME])
313             FLIImg->frameType = DARK_FRAME;
314          else
315             FLIImg->frameType = BIAS_FRAME;
316           
317           if ((err = FLISetFrameType(fli_dev, FLI_FRAME_TYPE_DARK) ))
318           {
319            IUResetSwitch(&FrameTypeSP);
320            FrameTypeS[LIGHT_FRAME].s = ISS_ON;
321            FrameTypeSP.s = IPS_ALERT;
322            IDSetSwitch(&FrameTypeSP, "FLISetFrameType() failed. %s.\n", strerror((int)-err));
323            IDLog("FLISetFrameType() failed. %s.\n", strerror((int)-err));
324            return;
325           }
326           
327           IUResetSwitch(&FrameTypeSP);
328           sp->s = ISS_ON;
329           FrameTypeSP.s = IPS_OK;
330           IDSetSwitch(&FrameTypeSP, NULL);
331           break;
332         }
333           
334        } /* For loop */
335       
336        return;
337     }
338     
339}
340
341void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
342{
343        ISInit();
344 
345       /* ignore if not ours */ 
346       if (dev && strcmp (mydev, dev))
347         return;
348
349        /* suppress warning */
350        n=n; dev=dev; name=name; names=names; texts=texts;
351       
352}
353
354
355void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
356{
357      long err;
358      int i;
359      INumber *np;
360      char errmsg[ERRMSG_SIZE];
361
362        /* ignore if not ours */
363        if (dev && strcmp (dev, mydev))
364            return;
365           
366        ISInit();
367       
368    /* Exposure time */
369    if (!strcmp (ExposeTimeWNP.name, name))
370    {
371       if (checkPowerN(&ExposeTimeWNP))
372         return;
373
374       if (ExposeTimeWNP.s == IPS_BUSY)
375       {
376          if ( (err = FLICancelExposure(fli_dev)))
377          {
378                ExposeTimeWNP.s = IPS_ALERT;
379                IDSetNumber(&ExposeTimeWNP, "FLICancelExposure() failed. %s.", strerror((int)-err));
380                IDLog("FLICancelExposure() failed. %s.\n", strerror((int)-err));
381                return;
382          }
383       
384          ExposeTimeWNP.s = IPS_IDLE;
385          ExposeTimeRNP.s = IPS_IDLE;
386          ExposeTimeRN[0].value = 0;
387
388          IDSetNumber(&ExposeTimeWNP, "Exposure cancelled.");
389          IDSetNumber(&ExposeTimeRNP, NULL);
390          IDLog("Exposure Cancelled.\n");
391          return;
392        }
393   
394       np = IUFindNumber(&ExposeTimeWNP, names[0]);
395         
396       if (!np)
397       {
398           ExposeTimeWNP.s = IPS_ALERT;
399           IDSetNumber(&ExposeTimeWNP, "Error: %s is not a member of %s property.", names[0], name);
400           return;
401       }
402         
403        np->value = values[0];
404        FLIImg->expose = (int) (values[0] * 1000.);
405       
406      /* Set duration */ 
407     if ( (err = FLISetExposureTime(fli_dev, np->value * 1000.) ))
408     {
409       ExposeTimeWNP.s = IPS_ALERT;
410       IDSetNumber(&ExposeTimeWNP, "FLISetExposureTime() failed. %s.\n", strerror((int)-err));
411       IDLog("FLISetExposureTime() failed. %s.\n", strerror((int)-err));
412       return;
413     }
414     
415      IDLog("Exposure Time (ms) is: %g\n", np->value * 1000.);
416     
417      handleExposure(NULL);
418      return;
419    } 
420   
421   
422  if (!strcmp(TemperatureNP.name, name))
423  {
424    if (checkPowerN(&TemperatureNP))
425      return;
426     
427    TemperatureNP.s = IPS_IDLE;
428   
429    np = IUFindNumber(&TemperatureNP, names[0]);
430   
431    if (!np)
432    {
433    IDSetNumber(&TemperatureNP, "Unknown error. %s is not a member of %s property.", names[0], name);
434    return;
435    }
436   
437    if (values[0] < MIN_CCD_TEMP || values[0] > MAX_CCD_TEMP)
438    {
439      IDSetNumber(&TemperatureNP, "Error: valid range of temperature is from %d to %d", MIN_CCD_TEMP, MAX_CCD_TEMP);
440      return;
441    }
442   
443    if ( (err = FLISetTemperature(fli_dev, values[0])))
444    {
445      IDSetNumber(&TemperatureNP, "FLISetTemperature() failed. %s.", strerror((int)-err));
446      IDLog("FLISetTemperature() failed. %s.", strerror((int)-err));
447      return;
448    }
449   
450    FLICam->temperature = values[0];
451    TemperatureNP.s = IPS_BUSY;
452   
453    IDSetNumber(&TemperatureNP, "Setting CCD temperature to %+06.2f C", values[0]);
454    IDLog("Setting CCD temperature to %+06.2f C\n", values[0]);
455    return;
456   }
457   
458   if (!strcmp(FrameNP.name, name))
459   {
460     int nset=0;
461     
462     if (checkPowerN(&FrameNP))
463      return;
464     
465     FrameNP.s = IPS_IDLE;
466     
467     for (i=0; i < n ; i++)
468     {
469       np = IUFindNumber(&FrameNP, names[i]);
470       
471      if (!np)
472      {
473       IDSetNumber(&FrameNP, "Unknown error. %s is not a member of %s property.", names[0], name);
474       return;
475      }
476     
477      /* X or Width */
478      if (np == &FrameN[0] || np==&FrameN[2])
479      {
480        if (values[i] < 0 || values[i] > FLICam->width)
481         break;
482         
483        nset++;
484        np->value = values[i];
485      }
486      /* Y or height */
487      else if (np == &FrameN[1] || np==&FrameN[3])
488      {
489       if (values[i] < 0 || values[i] > FLICam->height)
490         break;
491         
492        nset++;
493        np->value = values[i];
494      }
495     }
496     
497      if (nset < 4)
498      {
499        IDSetNumber(&FrameNP, "Invalid range. Valid range is (0,0) - (%0d,%0d)", FLICam->width, FLICam->height);
500        IDLog("Invalid range. Valid range is (0,0) - (%0d,%0d)", FLICam->width, FLICam->height);
501        return; 
502      }
503     
504      if (setImageArea(errmsg))
505      {
506        IDSetNumber(&FrameNP, "%s", errmsg);
507        return;
508      }
509           
510      FrameNP.s = IPS_OK;
511     
512      /* Adjusting image width and height */ 
513      FLIImg->width  = FrameN[2].value;
514      FLIImg->height = FrameN[3].value;
515     
516      IDSetNumber(&FrameNP, NULL);
517     
518   } /* end FrameNP */
519     
520   
521   if (!strcmp(BinningNP.name, name))
522   {
523     if (checkPowerN(&BinningNP))
524       return;
525       
526     BinningNP.s = IPS_IDLE;
527     
528     for (i=0 ; i < n ; i++)
529     {
530       np = IUFindNumber(&BinningNP, names[i]);
531       
532      if (!np)
533      {
534       IDSetNumber(&BinningNP, "Unknown error. %s is not a member of %s property.", names[0], name);
535       return;
536      }
537     
538      /* X binning */
539      if (np == &BinningN[0])
540      {
541        if (values[i] < 1 || values[i] > MAX_X_BIN)
542        {
543          IDSetNumber(&BinningNP, "Error: Valid X bin values are from 1 to %g", MAX_X_BIN);
544          IDLog("Error: Valid X bin values are from 1 to %g", MAX_X_BIN);
545          return;
546        }
547       
548        if ( (err = FLISetHBin(fli_dev, values[i])))
549        {
550          IDSetNumber(&BinningNP, "FLISetHBin() failed. %s.", strerror((int)-err));
551          IDLog("FLISetHBin() failed. %s.", strerror((int)-err));
552          return;
553        }
554       
555        np->value = values[i];
556      }
557      else if (np == &BinningN[1])
558      {
559        if (values[i] < 1 || values[i] > MAX_Y_BIN)
560        {
561          IDSetNumber(&BinningNP, "Error: Valid Y bin values are from 1 to %g", MAX_Y_BIN);
562          IDLog("Error: Valid X bin values are from 1 to %g", MAX_Y_BIN);
563          return;
564        }
565       
566        if ( (err = FLISetVBin(fli_dev, values[i])))
567        {
568          IDSetNumber(&BinningNP, "FLISetVBin() failed. %s.", strerror((int)-err));
569          IDLog("FLISetVBin() failed. %s.", strerror((int)-err));
570          return;
571        }
572       
573        np->value = values[i];
574      }
575     } /* end for */
576     
577     if (setImageArea(errmsg))
578     {
579       IDSetNumber(&BinningNP, errmsg, NULL);
580       IDLog("%s", errmsg);
581       return;
582     }
583     
584     BinningNP.s = IPS_OK;
585     
586     IDLog("Binning is: %.0f x %.0f\n", BinningN[0].value, BinningN[1].value);
587     
588     IDSetNumber(&BinningNP, NULL);
589     return;
590   }
591       
592}
593
594
595void ISPoll(void *p)
596{
597        long err;
598        long timeleft;
599        double ccdTemp;
600       
601        if (!isCCDConnected())
602        {
603         IEAddTimer (POLLMS, ISPoll, NULL);
604         return;
605        }
606         
607        /*IDLog("In Poll.\n");*/
608       
609        switch (ExposeTimeWNP.s)
610        {
611          case IPS_IDLE:
612            break;
613           
614          case IPS_OK:
615            break;
616           
617          case IPS_BUSY:
618            if ( (err = FLIGetExposureStatus(fli_dev, &timeleft)))
619            { 
620              ExposeTimeWNP.s = IPS_ALERT; 
621              ExposeTimeRN[0].value = 0;
622             
623              IDSetNumber(&ExposeTimeWNP, "FLIGetExposureStatus() failed. %s.", strerror((int)-err));
624              IDSetNumber(&ExposeTimeRNP, NULL);
625              IDLog("FLIGetExposureStatus() failed. %s.\n", strerror((int)-err));
626              break;
627            }
628           
629            if (timeleft > 0)
630            {
631              ExposeTimeRN[0].value = timeleft / 1000.;
632              IDSetNumber(&ExposeTimeRNP, NULL); 
633              break;
634            }
635
636            /* We're done exposing */
637            /*ExposeTimeWNP.s = IPS_OK;*/
638            ExposeTimeRNP.s = IPS_OK; 
639            ExposeTimeRN[0].value = 0;
640            IDSetNumber(&ExposeTimeWNP, "Exposure done, downloading image...");
641            IDSetNumber(&ExposeTimeRNP, NULL);
642            IDLog("Exposure done, downloading image...\n");
643
644            /* grab and save image */
645             grabImage();
646
647            break;
648           
649          case IPS_ALERT:
650            break;
651         }
652         
653         switch (TemperatureNP.s)
654         {
655           case IPS_IDLE:
656           case IPS_OK:
657             if ( (err = FLIGetTemperature(fli_dev, &ccdTemp)))
658             {
659               TemperatureNP.s = IPS_IDLE;
660               IDSetNumber(&TemperatureNP, "FLIGetTemperature() failed. %s.", strerror((int)-err));
661               IDLog("FLIGetTemperature() failed. %s.", strerror((int)-err));
662               return;
663             }
664             
665             if (fabs(TemperatureN[0].value - ccdTemp) >= TEMP_THRESHOLD)
666             {
667               TemperatureN[0].value = ccdTemp;
668               IDSetNumber(&TemperatureNP, NULL);
669             }
670             break;
671             
672           case IPS_BUSY:
673           if ((err = FLIGetTemperature(fli_dev, &ccdTemp)))
674             {
675               TemperatureNP.s = IPS_ALERT;
676               IDSetNumber(&TemperatureNP, "FLIGetTemperature() failed. %s.", strerror((int)-err));
677               IDLog("FLIGetTemperature() failed. %s.", strerror((int)-err));
678               return;
679             }
680             
681             if (fabs(FLICam->temperature - ccdTemp) <= TEMP_THRESHOLD)
682               TemperatureNP.s = IPS_OK;
683                       
684              TemperatureN[0].value = ccdTemp;
685              IDSetNumber(&TemperatureNP, NULL);
686              break;
687             
688            case IPS_ALERT:
689             break;
690          }
691         
692         p=p; 
693       
694         IEAddTimer (POLLMS, ISPoll, NULL);
695}
696
697/* Sets the Image area that the CCD will scan and download.
698   We compensate for binning. */
699int setImageArea(char errmsg[])
700{
701 
702   long x_1, y_1, x_2, y_2;
703   long err;
704   
705   /* Add the X and Y offsets */
706   x_1 = FrameN[0].value + FLICam->Visible_Area[0];
707   y_1 = FrameN[1].value + FLICam->Visible_Area[1];
708   
709   x_2 = x_1 + (FrameN[2].value / BinningN[0].value);
710   y_2 = y_1 + (FrameN[3].value / BinningN[1].value);
711   
712   if (x_2 > FLICam->Visible_Area[2])
713     x_2 = FLICam->Visible_Area[2];
714   
715   if (y_2 > FLICam->Visible_Area[3])
716     y_2 = FLICam->Visible_Area[3];
717     
718   IDLog("The Final image area is (%ld, %ld), (%ld, %ld)\n", x_1, y_1, x_2, y_2);
719   
720   FLIImg->width  = x_2 - x_1;
721   FLIImg->height = y_2 - y_1;
722   
723   if ( (err = FLISetImageArea(fli_dev, x_1, y_1, x_2, y_2) ))
724   {
725     snprintf(errmsg, ERRMSG_SIZE, "FLISetImageArea() failed. %s.\n", strerror((int)-err));
726     IDLog("%s", errmsg);
727     return -1;
728   }
729   
730   return 0;
731}
732
733/* Downloads the image from the CCD row by row and store them
734   in a raw file.
735 N.B. No processing is done on the image */
736int grabImage()
737{
738        long err;
739        int img_size,i, fd;
740        char errmsg[ERRMSG_SIZE];
741        char filename[TEMPFILE_LEN] = "/tmp/fitsXXXXXX";
742 
743        if ((fd = mkstemp(filename)) < 0)
744        { 
745                IDMessage(mydev, "Error making temporary filename.");
746                IDLog("Error making temporary filename.\n");
747                return -1;
748        }
749        close(fd);
750     
751        img_size = FLIImg->width * FLIImg->height * sizeof(unsigned short);
752       
753        FLIImg->img = malloc (img_size);
754 
755        if (FLIImg->img == NULL)
756        {
757                IDMessage(mydev, "Not enough memory to store image.");
758                IDLog("Not enough memory to store image.\n");
759                return -1;
760        }
761 
762        for (i=0; i < FLIImg->height ; i++)
763        {
764                if ( (err = FLIGrabRow(fli_dev, &FLIImg->img[i * FLIImg->width], FLIImg->width)))
765                {
766                        free(FLIImg->img);
767                        IDMessage(mydev, "FLIGrabRow() failed at row %d. %s.", i, strerror((int)-err));
768                        IDLog("FLIGrabRow() failed at row %d. %s.\n", i, strerror((int)-err));
769                        return -1;
770                }
771        }
772 
773        IDMessage(mydev, "Download complete.\n");
774       
775        /*err = (ImageFormatS[0].s == ISS_ON) ? writeFITS(FileNameT[0].text, errmsg) : writeRAW(FileNameT[0].text, errmsg);*/
776        err = writeFITS(filename, errmsg);
777   
778        if (err)
779        {
780                free(FLIImg->img);
781                IDMessage(mydev, errmsg, NULL);
782                return -1;
783        }
784
785        free(FLIImg->img);
786        return 0;
787 
788}
789
790int writeFITS(const char* filename, char errmsg[])
791{
792  fitsfile *fptr;       /* pointer to the FITS file; defined in fitsio.h */
793  int status;
794  long  fpixel = 1, naxis = 2, nelements;
795  long naxes[2];
796  char filename_rw[TEMPFILE_LEN+1];
797
798  naxes[0] = FLIImg->width;
799  naxes[1] = FLIImg->height;
800
801  /* Append ! to file name to over write it.*/
802  snprintf(filename_rw, TEMPFILE_LEN+1, "!%s", filename);
803
804  status = 0;         /* initialize status before calling fitsio routines */
805  fits_create_file(&fptr, filename_rw, &status);   /* create new file */
806
807  /* Create the primary array image (16-bit short integer pixels */
808  fits_create_img(fptr, USHORT_IMG, naxis, naxes, &status);
809
810  addFITSKeywords(fptr);
811
812  nelements = naxes[0] * naxes[1];          /* number of pixels to write */
813
814  /* Write the array of integers to the image */
815  fits_write_img(fptr, TUSHORT, fpixel, nelements, FLIImg->img, &status);
816
817  fits_close_file(fptr, &status);            /* close the file */
818
819  fits_report_error(stderr, status);  /* print out any error messages */
820
821  /* Success */
822  ExposeTimeWNP.s = IPS_OK;
823  IDSetNumber(&ExposeTimeWNP, NULL);
824  uploadFile(filename);
825  unlink(filename);
826 
827  return status;
828}
829
830void addFITSKeywords(fitsfile *fptr)
831{
832  int status=0; 
833  char binning_s[32];
834  char frame_s[32];
835  double min_val, max_val;
836 
837  /*pixel_size = (float) PixelSizeN[0].value;
838  min_val = min();
839  max_val = max();
840  temp    = (float) TemperatureN[0].value;
841  expose  = (float) FLIImg->expose;*/
842
843  snprintf(binning_s, 32, "(%g x %g)", BinningN[0].value, BinningN[1].value);
844
845  switch (FLIImg->frameType)
846  {
847    case LIGHT_FRAME:
848        strcpy(frame_s, "Light");
849        break;
850    case BIAS_FRAME:
851        strcpy(frame_s, "Bias");
852        break;
853    case FLAT_FRAME:
854        strcpy(frame_s, "Flat Field");
855        break;
856    case DARK_FRAME:
857        strcpy(frame_s, "Dark");
858        break;
859  }
860
861  fits_update_key(fptr, TDOUBLE, "CCD-TEMP", &(TemperatureN[0].value), "CCD Temperature (Celcius)", &status);
862  fits_update_key(fptr, TDOUBLE, "EXPOSURE", &(FLIImg->expose), "Total Exposure Time (ms)", &status); 
863  fits_update_key(fptr, TDOUBLE, "PIX-SIZ", &(PixelSizeN[0].value), "Pixel Size (microns)", &status);
864  fits_update_key(fptr, TSTRING, "BINNING", binning_s, "Binning HOR x VER", &status);
865  fits_update_key(fptr, TSTRING, "FRAME", frame_s, "Frame Type", &status);
866  fits_update_key(fptr, TDOUBLE, "DATAMIN", &min_val, "Minimum value", &status);
867  fits_update_key(fptr, TDOUBLE, "DATAMAX", &max_val, "Maximum value", &status);
868  fits_update_key(fptr, TSTRING, "INSTRUME", "Finger Lakes Instruments", "CCD Name", &status);
869  fits_write_date(fptr, &status);
870
871}
872
873void uploadFile(const char* filename)
874{
875   FILE * fitsFile;
876   unsigned char *fitsData, *compressedData;
877   int r=0;
878   unsigned int i =0, nr = 0;
879   uLongf compressedBytes=0;
880   uLong  totalBytes;
881   struct stat stat_p; 
882 
883   if ( -1 ==  stat (filename, &stat_p))
884   { 
885     IDLog(" Error occurred attempting to stat file.\n"); 
886     return; 
887   }
888   
889   totalBytes     = stat_p.st_size;
890   fitsData       = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes);
891   compressedData = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
892   
893   if (fitsData == NULL || compressedData == NULL)
894   {
895     if (fitsData) free(fitsData);
896     if (compressedData) free(compressedData);
897     IDLog("Error! low memory. Unable to initialize fits buffers.\n");
898     return;
899   }
900   
901   fitsFile = fopen(filename, "r");
902   
903   if (fitsFile == NULL)
904    return;
905   
906   /* #1 Read file from disk */ 
907   for (i=0; i < totalBytes; i+= nr)
908   {
909      nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
910     
911     if (nr <= 0)
912     {
913        IDLog("Error reading temporary FITS file.\n");
914        return;
915     }
916   }
917   fclose(fitsFile);
918   
919   compressedBytes = sizeof(char) * totalBytes + totalBytes / 64 + 16 + 3;
920   
921   /* #2 Compress it */ 
922   r = compress2(compressedData, &compressedBytes, fitsData, totalBytes, 9);
923   if (r != Z_OK)
924   {
925        /* this should NEVER happen */
926        IDLog("internal error - compression failed: %d\n", r);
927        return;
928   }
929   
930   /* #3 Send it */
931   imageB.blob = compressedData;
932   imageB.bloblen = compressedBytes;
933   imageB.size = totalBytes;
934   strcpy(imageB.format, ".fits.z");
935   imageBP.s = IPS_OK;
936   IDSetBLOB (&imageBP, NULL);
937   
938   free (fitsData);   
939   free (compressedData);
940   
941}
942
943/* Initiates the exposure procedure */
944void handleExposure(void *p)
945{
946  long err;
947 
948  /* no warning */
949  p=p;
950 
951  /* BIAS frame is the same as DARK but with minimum period. i.e. readout from camera electronics.
952  */
953  if (FLIImg->frameType == BIAS_FRAME)
954  {
955     if ((err = FLISetExposureTime(fli_dev, 50)))
956     {
957       ExposeTimeWNP.s = IPS_ALERT;
958       IDSetNumber(&ExposeTimeWNP, "FLISetExposureTime() failed. %s.\n", strerror((int)-err));
959       IDLog("FLISetExposureTime() failed. %s.\n", strerror((int)-err));
960       return;
961     }
962   }
963   
964  if ((err = FLIExposeFrame(fli_dev)))
965  {
966        ExposeTimeWNP.s = IPS_ALERT;
967        IDSetNumber(&ExposeTimeWNP, "FLIExposeFrame() failed. %s.", strerror((int)-err));
968        IDLog("FLIExposeFrame() failed. %s.\n", strerror((int)-err));
969        return;
970  }
971 
972   ExposeTimeWNP.s = IPS_BUSY;
973                 
974   IDSetNumber(&ExposeTimeWNP, "Taking a %g seconds frame...", FLIImg->expose / 1000.);
975   
976   IDLog("Taking a frame...\n");
977}
978
979/* Retrieves basic data from the CCD upon connection like temperature, array size, firmware..etc */
980void getBasicData()
981{
982
983  char buff[2048];
984  long err;
985
986  IDLog("In getBasicData()\n");
987 
988  if ((err = FLIGetModel (fli_dev, buff, 2048)))
989  {
990    IDMessage(mydev, "FLIGetModel() failed. %s.", strerror((int)-err));
991    IDLog("FLIGetModel() failed. %s.\n", strerror((int)-err));
992    return;
993  }
994  else
995  {
996    if ( (FLICam->model = malloc (sizeof(char) * 2048)) == NULL)
997    {
998      IDMessage(mydev, "malloc() failed.");
999      IDLog("malloc() failed.");
1000      return;
1001    }
1002   
1003    strcpy(FLICam->model, buff);
1004  }
1005 
1006  if (( err = FLIGetHWRevision(fli_dev, &FLICam->HWRevision)))
1007  {
1008    IDMessage(mydev, "FLIGetHWRevision() failed. %s.", strerror((int)-err));
1009    IDLog("FLIGetHWRevision() failed. %s.\n", strerror((int)-err));
1010   
1011    return;
1012  }
1013 
1014  if (( err = FLIGetFWRevision(fli_dev, &FLICam->FWRevision)))
1015  {
1016    IDMessage(mydev, "FLIGetFWRevision() failed. %s.", strerror((int)-err));
1017    IDLog("FLIGetFWRevision() failed. %s.\n", strerror((int)-err));
1018    return;
1019  }
1020
1021  if (( err = FLIGetPixelSize(fli_dev, &FLICam->x_pixel_size, &FLICam->y_pixel_size)))
1022  {
1023    IDMessage(mydev, "FLIGetPixelSize() failed. %s.", strerror((int)-err));
1024    IDLog("FLIGetPixelSize() failed. %s.\n", strerror((int)-err));
1025    return;
1026  }
1027 
1028  FLICam->x_pixel_size *= 1e6;
1029  FLICam->y_pixel_size *= 1e6; 
1030 
1031  if (( err = FLIGetArrayArea(fli_dev, &FLICam->Array_Area[0], &FLICam->Array_Area[1], &FLICam->Array_Area[2], &FLICam->Array_Area[3])))
1032  {
1033    IDMessage(mydev, "FLIGetArrayArea() failed. %s.", strerror((int)-err));
1034    IDLog("FLIGetArrayArea() failed. %s.\n", strerror((int)-err));
1035    return;
1036  }
1037 
1038  if (( err = FLIGetVisibleArea( fli_dev, &FLICam->Visible_Area[0], &FLICam->Visible_Area[1], &FLICam->Visible_Area[2], &FLICam->Visible_Area[3])))
1039  {
1040    IDMessage(mydev, "FLIGetVisibleArea() failed. %s.", strerror((int)-err));
1041    IDLog("FLIGetVisibleArea() failed. %s.\n", strerror((int)-err));
1042  }
1043 
1044  if (( err = FLIGetTemperature(fli_dev, &FLICam->temperature)))
1045  {
1046    IDMessage(mydev, "FLIGetTemperature() failed. %s.", strerror((int)-err));
1047    IDLog("FLIGetTemperature() failed. %s.\n", strerror((int)-err));
1048    return;
1049  }
1050 
1051  IDLog("The CCD Temperature is %f.\n", FLICam->temperature);
1052 
1053  PixelSizeN[0].value  = FLICam->x_pixel_size;                          /* Pixel width (um) */
1054  PixelSizeN[1].value  = FLICam->y_pixel_size;                          /* Pixel height (um) */
1055  TemperatureN[0].value = FLICam->temperature;                          /* CCD chip temperatre (degrees C) */
1056  FrameN[0].value = 0;                                                  /* X */
1057  FrameN[1].value = 0;                                                  /* Y */
1058  FrameN[2].value = FLICam->Visible_Area[2] - FLICam->Visible_Area[0];  /* Frame Width */
1059  FrameN[3].value = FLICam->Visible_Area[3] - FLICam->Visible_Area[1];  /* Frame Height */
1060 
1061  FLICam->width  = FLIImg->width = FrameN[2].value;
1062  FLICam->height = FLIImg->width = FrameN[3].value;
1063 
1064  BinningN[0].value = BinningN[1].value = 1;
1065 
1066  IDLog("The Camera Width is %d ---- %d\n", (int) FLICam->width, (int) FrameN[2].value);
1067  IDLog("The Camera Height is %d ---- %d\n", (int) FLICam->height, (int) FrameN[3].value);
1068 
1069  IDSetNumber(&PixelSizeNP, NULL);
1070  IDSetNumber(&TemperatureNP, NULL);
1071  IDSetNumber(&FrameNP, NULL);
1072  IDSetNumber(&BinningNP, NULL);
1073 
1074  IDLog("Exiting getBasicData()\n");
1075 
1076}
1077
1078int manageDefaults(char errmsg[])
1079{
1080  long err;
1081  /*int exposeTimeMS;
1082 
1083  exposeTimeMS = (int) (ExposeTimeWN[0].value * 1000.);
1084 
1085  IDLog("Setting default exposure time of %d ms.\n", exposeTimeMS);
1086  if ( (err = FLISetExposureTime(fli_dev, exposeTimeMS) ))
1087  {
1088    snprintf(errmsg, ERRMSG_SIZE, "FLISetExposureTime() failed. %s.\n", strerror((int)-err));
1089    IDLog(errmsg, NULL);
1090    return -1;
1091  }*/
1092 
1093  /* Default frame type is NORMAL */
1094  if ( (err = FLISetFrameType(fli_dev, FLI_FRAME_TYPE_NORMAL) ))
1095  {
1096    snprintf(errmsg, ERRMSG_SIZE, "FLISetFrameType() failed. %s.\n", strerror((int)-err));
1097    IDLog(errmsg, NULL);
1098    return -1;
1099  }
1100 
1101  /* X horizontal binning */
1102  if ( (err = FLISetHBin(fli_dev, BinningN[0].value) ))
1103  {
1104    snprintf(errmsg, ERRMSG_SIZE, "FLISetBin() failed. %s.\n", strerror((int)-err));
1105    IDLog(errmsg, NULL);
1106    return -1;
1107  }
1108 
1109  /* Y vertical binning */
1110  if ( (err = FLISetVBin(fli_dev, BinningN[1].value) ))
1111  {
1112    snprintf(errmsg, ERRMSG_SIZE, "FLISetVBin() failed. %s.\n", strerror((int)-err));
1113    IDLog(errmsg, NULL);
1114    return -1;
1115  }
1116 
1117  IDLog("Setting default binning %f x %f.\n", BinningN[0].value, BinningN[1].value);
1118 
1119  FLISetNFlushes(fli_dev, NFLUSHES);
1120 
1121  /* Set image area */
1122  if (setImageArea(errmsg))
1123    return -1;
1124 
1125  /* Success */
1126  return 0;
1127   
1128}
1129
1130int getOnSwitch(ISwitchVectorProperty *sp)
1131{
1132  int i=0;
1133 for (i=0; i < sp->nsp ; i++)
1134 {
1135   /*IDLog("Switch %s is %s\n", sp->sp[i].name, sp->sp[i].s == ISS_ON ? "On" : "Off");*/
1136     if (sp->sp[i].s == ISS_ON)
1137      return i;
1138 }
1139
1140 return -1;
1141}
1142
1143int checkPowerS(ISwitchVectorProperty *sp)
1144{
1145  if (ConnectSP.s != IPS_OK)
1146  {
1147    if (!strcmp(sp->label, ""))
1148        IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->name);
1149    else
1150        IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->label);
1151       
1152    sp->s = IPS_IDLE;
1153    IDSetSwitch(sp, NULL);
1154    return -1;
1155  }
1156
1157  return 0;
1158}
1159
1160int checkPowerN(INumberVectorProperty *np)
1161{
1162  if (ConnectSP.s != IPS_OK)
1163  {
1164     if (!strcmp(np->label, ""))
1165        IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->name);
1166    else
1167        IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->label);
1168   
1169    np->s = IPS_IDLE;
1170    IDSetNumber(np, NULL);
1171    return -1;
1172  }
1173
1174  return 0;
1175}
1176
1177int checkPowerT(ITextVectorProperty *tp)
1178{
1179
1180  if (ConnectSP.s != IPS_OK)
1181  {
1182    if (!strcmp(tp->label, ""))
1183        IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->name);
1184    else
1185        IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->label);
1186       
1187    tp->s = IPS_IDLE;
1188    IDSetText(tp, NULL);
1189    return -1;
1190  }
1191
1192  return 0;
1193
1194}
1195
1196void connectCCD()
1197{
1198        long err;
1199        char errmsg[ERRMSG_SIZE];
1200       
1201        IDLog ("In ConnectCCD\n");
1202   
1203  /* USB by default {USB, SERIAL, PARALLEL, INET} */
1204        switch (ConnectS[0].s)
1205        {
1206                case ISS_ON:
1207                IDLog("Current portSwitch is %d\n", portSwitchIndex);
1208                IDLog("Attempting to find the camera in domain %ld\n", Domains[portSwitchIndex]);
1209                if (findcam(Domains[portSwitchIndex])) {
1210                        ConnectSP.s = IPS_IDLE;
1211                        ConnectS[0].s = ISS_OFF;
1212                        ConnectS[1].s = ISS_ON;
1213                        IDSetSwitch(&ConnectSP, "Error: no cameras were detected.");
1214                        IDLog("Error: no cameras were detected.\n");
1215                        return;
1216                }
1217
1218                if ((err = FLIOpen(&fli_dev, FLICam->name, FLIDEVICE_CAMERA | FLICam->domain)))
1219                {
1220                        ConnectSP.s = IPS_IDLE;
1221                        ConnectS[0].s = ISS_OFF;
1222                        ConnectS[1].s = ISS_ON;
1223                        IDSetSwitch(&ConnectSP, "Error: FLIOpen() failed. %s.", strerror( (int) -err));
1224                        IDLog("Error: FLIOpen() failed. %s.\n", strerror( (int) -err));
1225                        return;
1226                }
1227     
1228                /* Sucess! */
1229                ConnectS[0].s = ISS_ON;
1230                ConnectS[1].s = ISS_OFF;
1231                ConnectSP.s = IPS_OK;
1232                IDSetSwitch(&ConnectSP, "CCD is online. Retrieving basic data.");
1233                IDLog("CCD is online. Retrieving basic data.\n");
1234                getBasicData();
1235                if (manageDefaults(errmsg))
1236                {
1237                        IDMessage(mydev, errmsg, NULL);
1238                        IDLog("%s", errmsg);
1239                        return;
1240                }
1241
1242                break;
1243     
1244                case ISS_OFF:
1245                        ConnectS[0].s = ISS_OFF;
1246                        ConnectS[1].s = ISS_ON;
1247                        ConnectSP.s = IPS_IDLE;
1248                        if ((err = FLIClose(fli_dev))) {
1249                                ConnectSP.s = IPS_IDLE;
1250                                ConnectS[0].s = ISS_OFF;
1251                                ConnectS[1].s = ISS_ON;
1252                                IDSetSwitch(&ConnectSP, "Error: FLIClose() failed. %s.", strerror( (int) -err));
1253                                IDLog("Error: FLIClose() failed. %s.\n", strerror( (int) -err));
1254                                return;
1255                        }
1256                        IDSetSwitch(&ConnectSP, "CCD is offline.");
1257                        break;
1258     }
1259}
1260
1261/* isCCDConnected: return 1 if we have a connection, 0 otherwise */
1262int isCCDConnected(void)
1263{
1264  return ((ConnectS[0].s == ISS_ON) ? 1 : 0);
1265}
1266
1267int findcam(flidomain_t domain)
1268{
1269  char **tmplist;
1270  long err;
1271 
1272  IDLog("In find Camera, the domain is %ld\n", domain);
1273
1274  if (( err = FLIList(domain | FLIDEVICE_CAMERA, &tmplist)))
1275  {
1276    IDLog("FLIList() failed. %s\n", strerror((int)-err));
1277    return -1;
1278  }
1279 
1280  if (tmplist != NULL && tmplist[0] != NULL)
1281  {
1282    int i;
1283
1284    IDLog("Trying to allocate memory to FLICam\n");
1285    if ((FLICam = malloc (sizeof (cam_t))) == NULL)
1286    {
1287        IDLog("malloc() failed.\n");
1288        return -1;
1289    }
1290
1291    for (i = 0; tmplist[i] != NULL; i++)
1292    {
1293      int j;
1294
1295      for (j = 0; tmplist[i][j] != '\0'; j++)
1296        if (tmplist[i][j] == ';')
1297        {
1298          tmplist[i][j] = '\0';
1299          break;
1300        }
1301    }
1302   
1303     FLICam->domain = domain;
1304     
1305        switch (domain)
1306        {
1307                case FLIDOMAIN_PARALLEL_PORT:
1308                        FLICam->dname = strdup("parallel port");
1309                        break;
1310
1311                case FLIDOMAIN_USB:
1312                        FLICam->dname = strdup("USB");
1313                        break;
1314
1315                case FLIDOMAIN_SERIAL:
1316                        FLICam->dname = strdup("serial");
1317                        break;
1318
1319                case FLIDOMAIN_INET:
1320                        FLICam->dname = strdup("inet");
1321                        break;
1322
1323                default:
1324                        FLICam->dname = strdup("Unknown domain");
1325        }
1326     
1327      FLICam->name = strdup(tmplist[0]);
1328     
1329     if ((err = FLIFreeList(tmplist)))
1330     {
1331       IDLog("FLIFreeList() failed. %s.\n", strerror((int)-err));
1332       return -1;
1333     }
1334     
1335   } /* end if */
1336   else
1337   {
1338     if ((err = FLIFreeList(tmplist)))
1339     {
1340       IDLog("FLIFreeList() failed. %s.\n", strerror((int)-err));
1341       return -1;
1342     }
1343     
1344     return -1;
1345   }
1346
1347  IDLog("Findcam() finished successfully.\n");
1348  return 0;
1349}
1350
1351double min()
1352{
1353  double lmin = FLIImg->img[0];
1354  int ind=0, i, j;
1355 
1356  for (i= 0; i < FLIImg->height ; i++)
1357    for (j= 0; j < FLIImg->width; j++)
1358    {
1359       ind = (i * FLIImg->width) + j;
1360       if (FLIImg->img[ind] < lmin) lmin = FLIImg->img[ind];
1361    }
1362   
1363    return lmin;
1364}
1365
1366double max()
1367{
1368  double lmax = FLIImg->img[0];
1369  int ind=0, i, j;
1370 
1371   for (i= 0; i < FLIImg->height ; i++)
1372    for (j= 0; j < FLIImg->width; j++)
1373    {
1374      ind = (i * FLIImg->width) + j;
1375       if (FLIImg->img[ind] > lmax) lmax = FLIImg->img[ind];
1376    }
1377   
1378    return lmax;
1379}
Note: See TracBrowser for help on using the repository browser.