~ubuntu-branches/ubuntu/quantal/libindi/quantal

« back to all changes in this revision

Viewing changes to drivers/ccd/fli_ccd.c

  • Committer: Bazaar Package Importer
  • Author(s): Rohan Garg, Rohan Garg, Jonathan Riddell, Jonathan Thomas
  • Date: 2011-07-14 18:18:04 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110714181804-3fybxiy3tpjnk9kq
Tags: 0.8-0ubuntu1
[ Rohan Garg ]
* New upstream release
  - Add boost to build deps
  - Bump soversion to 0.8

[ Jonathan Riddell ]
* Use source format 3.0
* Add kubuntu_01_link_pthreads.diff to fix linking with pthreads

[ Jonathan Thomas ]
* Change Maintainer from MOTU to Ubuntu Developers

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
46
 
void ISInit(void);
47
 
void getBasicData(void);
48
 
void ISPoll(void *);
49
 
void handleExposure(void *);
50
 
void connectCCD(void);
51
 
void getBasicData(void);
52
 
void uploadFile(const char* filename);
53
 
int  writeFITS(const char* filename, char errmsg[]);
54
 
int  findcam(flidomain_t domain);
55
 
int  setImageArea(char errmsg[]);
56
 
int  manageDefaults(char errmsg[]);
57
 
int  grabImage(void);
58
 
int  checkPowerS(ISwitchVectorProperty *sp);
59
 
int  checkPowerN(INumberVectorProperty *np);
60
 
int  checkPowerT(ITextVectorProperty *tp);
61
 
int  getOnSwitch(ISwitchVectorProperty *sp);
62
 
int  isCCDConnected(void);
63
 
void addFITSKeywords(fitsfile *fptr);
64
 
 
65
 
double min(void);
66
 
double max(void);
67
 
 
68
 
extern char* me;
69
 
extern 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
 
 
94
 
enum FLIFrames { LIGHT_FRAME = 0, BIAS_FRAME, DARK_FRAME, FLAT_FRAME };
95
 
 
96
 
 
97
 
typedef 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
 
 
112
 
typedef struct {
113
 
int  width;
114
 
int  height;
115
 
int  frameType;
116
 
int  expose;
117
 
unsigned short  *img;
118
 
} img_t;
119
 
 
120
 
/*static int streamTimerID;              Stream ID */
121
 
 
122
 
static flidev_t fli_dev;
123
 
static cam_t *FLICam;
124
 
static img_t *FLIImg;
125
 
static int portSwitchIndex;
126
 
 
127
 
long int Domains[] = { FLIDOMAIN_USB, FLIDOMAIN_SERIAL, FLIDOMAIN_PARALLEL_PORT,  FLIDOMAIN_INET };
128
 
 
129
 
/*INDI controls */
130
 
 
131
 
/* Connect/Disconnect */
132
 
static ISwitch ConnectS[]               = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}};
133
 
static ISwitchVectorProperty ConnectSP  = { mydev, "CONNECTION" , "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE, ConnectS, NARRAY(ConnectS), "", 0};
134
 
 
135
 
/* Types of Ports */
136
 
static ISwitch PortS[]                  = {{"USB", "", ISS_ON, 0, 0}, {"Serial", "", ISS_OFF, 0, 0}, {"Parallel", "", ISS_OFF, 0, 0}, {"INet", "", ISS_OFF, 0, 0}};
137
 
static ISwitchVectorProperty PortSP     = { mydev, "Port Type", "", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, PortS, NARRAY(PortS), "", 0};
138
 
 
139
 
/* Types of Frames */
140
 
static 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}};
141
 
static 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 */
144
 
static 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) */
169
 
static INumber PixelSizeN[]     = {
170
 
        { "Width", "", "%.0f", 0. , 0., 0., 0., 0, 0, 0},
171
 
        { "Height", "", "%.0f", 0. , 0., 0., 0., 0, 0, 0}};
172
 
static INumberVectorProperty PixelSizeNP = { mydev, "Pixel Size (µm)", "", DATA_GROUP, IP_RO, 0, IPS_IDLE, PixelSizeN, NARRAY(PixelSizeN), "", 0};
173
 
 
174
 
/* BLOB for sending image */
175
 
static IBLOB imageB = {"FITS_BLOB", "FITS", "", 0, 0, 0, 0, 0, 0, 0};
176
 
static 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 */
180
 
void 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
 
 
205
 
void 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
 
 
230
 
void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) {}
231
 
void ISSnoopDevice (XMLEle *root) {}
232
 
  
233
 
void 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
 
 
341
 
void 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
 
 
355
 
void 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
 
 
595
 
void 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. */
699
 
int 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 */
736
 
int 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
 
 
790
 
int 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
 
 
830
 
void 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
 
 
873
 
void 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 */
944
 
void 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 */
980
 
void 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
 
 
1078
 
int 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
 
 
1130
 
int 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
 
 
1143
 
int 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
 
 
1160
 
int 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
 
 
1177
 
int 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
 
 
1196
 
void 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 */
1262
 
int isCCDConnected(void)
1263
 
{
1264
 
  return ((ConnectS[0].s == ISS_ON) ? 1 : 0);
1265
 
}
1266
 
 
1267
 
int 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
 
 
1351
 
double 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
 
 
1366
 
double 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
 
}