• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kstars

sbigccd.cpp

Go to the documentation of this file.
00001 #if 0
00002     INDI driver for SBIG CCD
00003     Copyright (C) 2005 Chris Curran (ccurran AT planetcurran DOT com)
00004 
00005     Based on Apogee PPI driver by Jasem Mutlaq (mutlaqja AT ikarustech DOT com)
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2.1 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 #endif
00022  
00023 #include <ctype.h>
00024 #include <sys/stat.h>
00025 #include <sys/time.h>
00026 #include <sys/types.h>
00027 #include <sys/socket.h>
00028 #include <netinet/in.h>
00029 #include <netdb.h>
00030 #include <zlib.h>
00031 
00032 #include "sbigccd.h"
00033 #include "lilxml.h"
00034 #include "base64.h"
00035 
00036 extern char* me;            /* argv[0] */
00037 SBIGCam *MainCam = NULL;        /* Main and only camera */
00038 
00039 /* send client definitions of all properties */
00040 void ISInit()
00041 {
00042   if (MainCam == NULL)
00043     MainCam = new SBIGCam();
00044 }
00045     
00046 void ISGetProperties (const char *dev)
00047 { 
00048   if (dev && strcmp (mydev, dev))
00049     return;
00050   
00051    ISInit();
00052   
00053   MainCam->ISGetProperties(dev);
00054 }
00055 
00056 
00057 void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
00058 {
00059     
00060   /* ignore if not ours */
00061   if (dev && strcmp (dev, mydev))
00062     return;
00063         
00064   ISInit();
00065   
00066   MainCam->ISNewSwitch(dev, name, states, names, n);
00067 }
00068 
00069 void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
00070 {
00071   /* ignore if not ours */ 
00072   if (dev && strcmp (mydev, dev))
00073     return;
00074 
00075    ISInit();
00076    
00077    MainCam->ISNewText(dev, name, texts, names, n);
00078 }
00079 
00080 
00081 void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
00082 {
00083       
00084   /* ignore if not ours */
00085   if (dev && strcmp (dev, mydev))
00086     return;
00087         
00088   ISInit();
00089   
00090   MainCam->ISNewNumber(dev, name, values, names, n);
00091 }
00092 
00093 void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
00094 {
00095 
00096   // We use this if we're receving binary data from the client. Most likely we won't for this driver.
00097 
00098 }
00099 
00100 SBIGCam::SBIGCam()
00101 {
00102   initProperties();
00103   IEAddTimer (POLLMS, SBIGCam::ISStaticPoll, this);
00104 }
00105 
00106 SBIGCam::~SBIGCam()
00107 {
00108   
00109 }
00110 
00111 void SBIGCam::initProperties()
00112 {
00113   fillSwitch(&PowerS[0], "CONNECT", "Connect", ISS_OFF);
00114   fillSwitch(&PowerS[1], "DISCONNECT", "Disconnect", ISS_ON);
00115   fillSwitchVector(&PowerSP, PowerS, NARRAY(PowerS), mydev, "CONNECTION", "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
00116   
00117   fillSwitch(&FrameTypeS[0], "FRAME_LIGHT", "Light", ISS_ON);
00118   fillSwitch(&FrameTypeS[1], "FRAME_BIAS", "Bias", ISS_OFF);
00119   fillSwitch(&FrameTypeS[2], "FRAME_DARK", "Dark", ISS_OFF);
00120   fillSwitch(&FrameTypeS[3], "FRAME_FLAT", "Flat Field", ISS_OFF);
00121   fillSwitchVector(&FrameTypeSP, FrameTypeS, NARRAY(FrameTypeS), mydev, "CCD_FRAME_TYPE", "Frame Type", EXPOSE_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
00122 
00123   fillNumber(&FrameN[0], "X", "X", "%.0f", 0., MAX_PIXELS, 1., 0.);
00124   fillNumber(&FrameN[1], "Y", "Y", "%.0f", 0., MAX_PIXELS, 1., 0.);
00125   fillNumber(&FrameN[2], "WIDTH", "Width", "%.0f", 0., MAX_PIXELS, 1., 0.);
00126   fillNumber(&FrameN[3], "HEIGHT", "Height", "%.0f", 0., MAX_PIXELS, 1., 0.);
00127   fillNumberVector(&FrameNP, FrameN, NARRAY(FrameN), mydev, "CCD_FRAME", "Frame", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
00128   
00129   fillNumber(&BinningN[0], "HOR_BIN", "X", "%0.f", 1., MAXHBIN, 1., 1.);
00130   fillNumber(&BinningN[1], "VER_BIN", "Y", "%0.f", 1., MAXVBIN, 1., 1.);
00131   fillNumberVector(&BinningNP, BinningN, NARRAY(BinningN), mydev, "CCD_BINNING", "Binning", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
00132     
00133   fillNumber(&ExposeTimeN[0], "EXPOSE_DURATION", "Duration (s)", "%5.2f", 0., 36000., 0.5, 1.);
00134   fillNumberVector(&ExposeTimeNP, ExposeTimeN, NARRAY(ExposeTimeN), mydev, "CCD_EXPOSE_DURATION", "Expose", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE);
00135   
00136   fillNumber(&TemperatureN[0], "TEMPERATURE", "Temperature", "%+06.2f", MIN_CCD_TEMP, MAX_CCD_TEMP, 0.2, 0.);
00137   fillNumberVector(&TemperatureNP, TemperatureN, NARRAY(TemperatureN), mydev, "CCD_TEMPERATURE", "Expose", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE);
00138 
00139   // We need to setup the BLOB (Binary Large Object) below. Using this property, we can send FITS to our client
00140   strcpy(imageB.name, "CCD1");
00141   strcpy(imageB.label, "Feed");
00142   strcpy(imageB.format, "");
00143   imageB.blob    = 0;
00144   imageB.bloblen = 0;
00145   imageB.size    = 0;
00146   imageB.bvp     = 0;
00147   imageB.aux0    = 0;
00148   imageB.aux1    = 0;
00149   imageB.aux2    = 0;
00150   
00151   strcpy(imageBP.device, mydev);
00152   strcpy(imageBP.name, "Video");
00153   strcpy(imageBP.label, "Video");
00154   strcpy(imageBP.group, COMM_GROUP);
00155   strcpy(imageBP.timestamp, "");
00156   imageBP.p       = IP_RO;
00157   imageBP.timeout = 0;
00158   imageBP.s       = IPS_IDLE;
00159   imageBP.bp      = &imageB;
00160   imageBP.nbp     = 1;
00161   imageBP.aux     = 0;
00162   
00163 }
00164 
00165 void SBIGCam::ISGetProperties(const char */*dev*/)
00166 {
00167   
00168   /* COMM_GROUP */
00169   IDDefSwitch(&PowerSP, NULL);
00170   IDDefBLOB(&imageBP, NULL);
00171 
00172   /* Expose */
00173   IDDefSwitch(&FrameTypeSP, NULL);  
00174   IDDefNumber(&ExposeTimeNP, NULL);
00175   IDDefNumber(&TemperatureNP, NULL);
00176   
00177   /* Image Group */
00178   IDDefNumber(&FrameNP, NULL);
00179   IDDefNumber(&BinningNP, NULL);
00180   
00181 }
00182 
00183 void SBIGCam::ISNewSwitch (const char */*dev*/, const char *name, ISState *states, char *names[], int n)
00184 {
00185   
00186     /* Connection */
00187     if (!strcmp (name, PowerSP.name))
00188     {
00189         IUResetSwitches(&PowerSP);
00190         IUUpdateSwitches(&PowerSP, states, names, n);
00191         connectCCD();
00192         return;
00193     }
00194     
00195         /* Frame Type */
00196         if (!strcmp(FrameTypeSP.name, name))
00197     {
00198         if (checkPowerS(&FrameTypeSP))
00199             return;
00200         
00201         IUResetSwitches(&FrameTypeSP);
00202         IUUpdateSwitches(&FrameTypeSP, states, names, n);
00203         FrameTypeSP.s = IPS_OK;
00204         IDSetSwitch(&FrameTypeSP, NULL);
00205         
00206         return;
00207     }
00208      
00209 }
00210 
00211 void SBIGCam::ISNewText (const char */*dev*/, const char */*name*/, char **/*texts[]*/, char **/*names[]*/, int /*n*/)
00212 {
00213   
00214 }
00215 
00216 void SBIGCam::ISNewNumber (const char */*dev*/, const char *name, double values[], char *names[], int n)
00217 {
00218     /* Exposure time */
00219     if (!strcmp (ExposeTimeNP.name, name))
00220     {
00221        if (checkPowerN(&ExposeTimeNP))
00222          return;
00223 
00224        if (ExposeTimeNP.s == IPS_BUSY)
00225        {
00226       ExposeTimeNP.s = IPS_IDLE;
00227       ExposeTimeN[0].value = 0;
00228 
00229       IDSetNumber(&ExposeTimeNP, "Exposure cancelled.");
00230       IDLog("Exposure Cancelled.\n");
00231       return;
00232         }
00233     
00234        ExposeTimeNP.s = IPS_IDLE;
00235        
00236        IUUpdateNumbers(&ExposeTimeNP, values, names, n);
00237        
00238       IDLog("Exposure Time (ms) is: %g\n", ExposeTimeN[0].value);
00239       
00240       handleExposure(NULL);
00241       return;
00242     } 
00243     
00244   if (!strcmp(TemperatureNP.name, name))
00245   {
00246     if (checkPowerN(&TemperatureNP))
00247       return;
00248       
00249     TemperatureNP.s = IPS_IDLE;
00250     
00251     if (values[0] < MIN_CCD_TEMP || values[0] > MAX_CCD_TEMP)
00252     {
00253       IDSetNumber(&TemperatureNP, "Error: valid range of temperature is from %d to %d", MIN_CCD_TEMP, MAX_CCD_TEMP);
00254       return;
00255     }
00256     
00257     targetTemp = values[0];
00258 
00259     // JM: Below, tell SBIG to update to temperature to targetTemp
00260     // e.g. cam->setTemp(targetTemp);
00261     
00262 
00263     // Now we set property to busy and poll in ISPoll for CCD temp
00264     TemperatureNP.s = IPS_BUSY;
00265     
00266     IDSetNumber(&TemperatureNP, "Setting CCD temperature to %+06.2f C", values[0]);
00267     IDLog("Setting CCD temperature to %+06.2f C\n", values[0]);
00268     return;
00269    }
00270    
00271    // Subframing
00272    if (!strcmp(FrameNP.name, name))
00273    {
00274      if (checkPowerN(&FrameNP))
00275       return;
00276       
00277      FrameNP.s = IPS_OK;
00278      IUUpdateNumbers(&FrameNP, values, names, n);
00279      
00280      // JM: Below, we setup the frame size we want to take exposure of
00281      // The way it is done depends on the camera API. Example below
00282      //cam->m_StartX = (int) FrameN[0].value;
00283      //cam->m_StartY = (int) FrameN[1].value;
00284      //cam->m_Width   = (int) FrameN[2].value;
00285      //cam->m_Height  = (int) FrameN[3].value;
00286 
00287      IDSetNumber(&FrameNP, NULL);
00288       
00289    } /* end FrameNP */
00290       
00291 
00292    // Binning     
00293    if (!strcmp(BinningNP.name, name))
00294    {
00295      if (checkPowerN(&BinningNP))
00296        return;
00297        
00298      
00299      BinningNP.s = IPS_OK;
00300      IUUpdateNumbers(&BinningNP, values, names, n);
00301      
00302      // JM: Below we set the camera binning.
00303      // eg:
00304      //cam->m_BinX = (int) BinningN[0].value;
00305      //cam->m_BinY = (int) BinningN[1].value;
00306      
00307      IDLog("Binning is: %.0f x %.0f\n", BinningN[0].value, BinningN[1].value);
00308      return;
00309    }
00310 }
00311 
00312 
00313 void SBIGCam::ISStaticPoll(void *p)
00314 {
00315     if (!((SBIGCam *)p)->isCCDConnected())
00316     {
00317       IEAddTimer (POLLMS, SBIGCam::ISStaticPoll, p);
00318       return;
00319     }
00320     
00321     ((SBIGCam *) p)->ISPoll();
00322     
00323     IEAddTimer (POLLMS, SBIGCam::ISStaticPoll, p);
00324 }
00325 
00326 void SBIGCam::ISPoll()
00327 {
00328   static int mtc=5;
00329   int readStatus=0;
00330   double ccdTemp (0);
00331     
00332   switch (ExposeTimeNP.s)
00333   {
00334     case IPS_IDLE:
00335     case IPS_OK:
00336       break;
00337         
00338     case IPS_BUSY:
00339       
00340       // JM: Here we check the status of the camera (whether it's still capturing an image or has finished that)
00341       // ISPoll is called once per second. e.g. below for how we do this for Apogee Cameras
00342       /*
00343       readStatus = cam->read_Status();
00344       if (readStatus < 0)
00345       {
00346     IDLog("Error in exposure!\n");
00347     ExposeTimeNP.s = IPS_IDLE;
00348     ExposeTimeN[0].value = 0;
00349     IDSetNumber(&ExposeTimeNP, "Error in exposure procedure.");
00350     return;
00351       }
00352       else if (readStatus == Camera_Status_ImageReady)
00353       {
00354     ExposeTimeN[0].value = 0;
00355     ExposeTimeNP.s = IPS_OK;
00356     IDSetNumber(&ExposeTimeNP, "Exposure done, downloading image...");
00357     IDLog("Exposure done, downloading image...\n");
00358     // grab and save image. Don't forget to call this!
00359     grabImage();
00360     return;
00361       } */
00362       
00363       ExposeTimeN[0].value --;
00364       IDSetNumber(&ExposeTimeNP, NULL);
00365       break;
00366         
00367     case IPS_ALERT:
00368         break;
00369     }
00370      
00371      
00372      switch (TemperatureNP.s)
00373      {
00374            // JM: If we're not setting a new temperature (i.e. state is either ok or idle)
00375            // We simply check for the temp every 5 seconds (this is why mtc = 5 and then decremented).
00376        case IPS_IDLE:
00377        case IPS_OK:
00378          mtc--;
00379          
00380          if (mtc == 0)
00381          {
00382            //TemperatureN[0].value = cam->read_Temperature();
00383            IDSetNumber(&TemperatureNP, NULL);
00384            mtc = 5;
00385          }
00386          break;
00387          
00388            // JM: If we're setting a new temperature, we continously check for it here untill we get
00389            // a "close enough" value. This close enough value as seen below is the TEMP_THRESHOLD (0.25 C)
00390        case IPS_BUSY:
00391        
00392              // Read in current CCD temp
00393          //ccdTemp = cam->read_Temperature();
00394          
00395          if (fabs(targetTemp - ccdTemp) <= TEMP_THRESHOLD)
00396            TemperatureNP.s = IPS_OK;
00397                    
00398           mtc = 1;
00399               TemperatureN[0].value = ccdTemp;
00400           IDSetNumber(&TemperatureNP, NULL);
00401           break;
00402           
00403         case IPS_ALERT:
00404          break;
00405       }
00406       
00407 }
00408 
00409 /* Downloads the image from the CCD row by row and store them
00410    in a raw file.
00411  N.B. No processing is done on the image */
00412 void SBIGCam::grabImage()
00413 {
00414   
00415   long err;
00416   int img_size, fd;
00417   char errmsg[1024];
00418   char filename[] = "/tmp/fitsXXXXXX";
00419   
00420    if ((fd = mkstemp(filename)) < 0)
00421    { 
00422     IDMessage(mydev, "Error making temporary filename.");
00423     IDLog("Error making temporary filename.\n");
00424     return;
00425    }
00426    close(fd);
00427      
00428    // JM: allocate memory for buffer. In most cameras, the bit depth is 16 bit and so we use unsigned short
00429    // But change if the bit depth is different
00430    img_size = SBIGFrame.width * SBIGFrame.height * sizeof(unsigned short);
00431   
00432    SBIGFrame.img = (unsigned short *) malloc (img_size);
00433    
00434   if (SBIGFrame.img == NULL)
00435   {
00436     IDMessage(mydev, "Not enough memory to store image.");
00437     IDLog("Not enough memory to store image.\n");
00438     return;
00439   }
00440   
00441   // JM: Here we fetch the image from the camera
00442   // 
00443   /*if (!cam->GetImage( SBIGFrame.img , SBIGFrame.width, SBIGFrame.height ))
00444   {
00445        free(SBIGFrame.img);
00446        IDMessage(mydev, "GetImage() failed.");
00447        IDLog("GetImage() failed.");
00448        return;
00449   }*/
00450   
00451    err = writeFITS(filename, errmsg);
00452    
00453    if (err)
00454    {
00455        free(SBIGFrame.img);
00456        IDMessage(mydev, errmsg, NULL);
00457        return;
00458    }
00459    
00460   free(SBIGFrame.img);
00461    
00462 }
00463 
00464 int SBIGCam::writeFITS(char *filename, char errmsg[])
00465 {
00466   
00467   FITS_FILE* ofp;
00468   int bpp, bpsl, width, height;
00469   long nbytes;
00470   FITS_HDU_LIST *hdu;
00471   
00472   ofp = fits_open (filename, "w");
00473   if (!ofp)
00474   {
00475     sprintf(errmsg, "Error: cannot open file for writing.");
00476     return (-1);
00477   }
00478   
00479   // We're assuming bit depth is 16 (unsigned short). Change as desired.
00480   width  = SBIGFrame.width;
00481   height = SBIGFrame.height;
00482   bpp    = sizeof(unsigned short);   /* Bytes per Pixel */
00483   bpsl   = bpp * SBIGFrame.width;    /* Bytes per Line */
00484   nbytes = 0;
00485   
00486   hdu = create_fits_header (ofp, width, height, bpp);
00487   if (hdu == NULL)
00488   {
00489      sprintf(errmsg, "Error: creating FITS header failed.");
00490      return (-1);
00491   }
00492   if (fits_write_header (ofp, hdu) < 0)
00493   {
00494     sprintf(errmsg, "Error: writing to FITS header failed.");
00495     return (-1);
00496   }
00497   
00498   // JM: Here we're performing little endian to big endian (network order) conversion
00499   // Since FITS is stored in big endian. If the camera provides the image buffer in big endian
00500   // then there is no need for this conversion
00501   for (int i=0; i < height; i++)
00502     for (int j=0 ; j < width; j++)
00503       SBIGFrame.img[width * i + j] = getBigEndian( (SBIGFrame.img[width * i + j]) );
00504   
00505   // The "2" below is for two bytes (16 bit or unsigned short). Again, change as desired.
00506   for (int i= 0; i < height  ; i++)
00507   {
00508     fwrite(SBIGFrame.img + (i * width), 2, width, ofp->fp);
00509     nbytes += bpsl;
00510   }
00511   
00512   nbytes = nbytes % FITS_RECORD_SIZE;
00513   if (nbytes)
00514   {
00515     while (nbytes++ < FITS_RECORD_SIZE)
00516       putc (0, ofp->fp);
00517   }
00518   
00519   if (ferror (ofp->fp))
00520   {
00521     sprintf(errmsg, "Error: write error occured");
00522     return (-1);
00523   }
00524  
00525  fits_close (ofp);      
00526  
00527   /* Success */
00528  ExposeTimeNP.s = IPS_OK;
00529  IDSetNumber(&ExposeTimeNP, NULL);
00530  IDLog("Loading FITS image...\n");
00531  
00532  uploadFile(filename);
00533 
00534  return 0;
00535 
00536 }
00537 
00538 void SBIGCam::uploadFile(char * filename)
00539 {
00540 
00541    FILE * fitsFile;
00542    unsigned char *fitsData, *compressedData;
00543    int r=0;
00544    unsigned int i =0, nr = 0;
00545    uLongf compressedBytes=0;
00546    uLong  totalBytes;
00547    struct stat stat_p; 
00548  
00549    if ( -1 ==  stat (filename, &stat_p))
00550    { 
00551      IDLog(" Error occoured attempting to stat %s\n", filename); 
00552      return; 
00553    }
00554    
00555    totalBytes     = stat_p.st_size;
00556    fitsData       = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes);
00557    compressedData = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
00558    
00559    if (fitsData == NULL || compressedData == NULL)
00560    {
00561      IDLog("Error! low memory. Unable to initialize fits buffers.\n");
00562      return;
00563    }
00564    
00565    fitsFile = fopen(filename, "r");
00566    
00567    if (fitsFile == NULL)
00568     return;
00569    
00570    /* #1 Read file from disk */ 
00571    for (i=0; i < totalBytes; i+= nr)
00572    {
00573       nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
00574      
00575      if (nr <= 0)
00576      {
00577         IDLog("Error reading temporary FITS file.\n");
00578         return;
00579      }
00580    }
00581    
00582    compressedBytes = sizeof(char) * totalBytes + totalBytes / 64 + 16 + 3;
00583      
00584    /* #2 Compress it */
00585    r = compress2(compressedData, &compressedBytes, fitsData, totalBytes, 9);
00586    if (r != Z_OK)
00587    {
00588     /* this should NEVER happen */
00589     IDLog("internal error - compression failed: %d\n", r);
00590     return;
00591    }
00592    
00593    /* #3 Send it */
00594    imageB.blob = compressedData;
00595    imageB.bloblen = compressedBytes;
00596    imageB.size = totalBytes;
00597    strcpy(imageB.format, ".fits.z");
00598    imageBP.s = IPS_OK;
00599    IDSetBLOB (&imageBP, NULL);
00600    
00601    free (fitsData);   
00602    free (compressedData);
00603    
00604 }
00605 
00606 /* Initiates the exposure procedure */
00607 void SBIGCam::handleExposure(void */*p*/)
00608 {
00609   
00610   int curFrame = getOnSwitch(&FrameTypeSP);
00611   
00612   switch (curFrame)
00613   {
00614     /* Light frame */ 
00615    case LIGHT_FRAME:
00616    
00617    /*if (!cam->Expose( (int) ExposeTimeN[0].value, true ))
00618    {  
00619      ExposeTimeNP.s = IPS_IDLE;
00620      IDSetNumber(&ExposeTimeNP, "Light Camera exposure failed.");
00621      IDLog("Light Camera exposure failed.\n");
00622      return;
00623    }*/
00624    break;
00625    
00626    /* BIAS frame is the same as DARK but with minimum period. i.e. readout from camera electronics.
00627    */
00628     case BIAS_FRAME:
00629       
00630       /*if (!cam->Expose( 0.05 , false ))
00631       {  
00632     ExposeTimeNP.s = IPS_IDLE;
00633     IDSetNumber(&ExposeTimeNP, "Bias Camera exposure failed.");
00634     IDLog("Bias Camera exposure failed.\n");
00635     return;
00636       }*/
00637       break;
00638       
00639       /* Dark frame */
00640     case DARK_FRAME:
00641       
00642       /*if (!cam->Expose( (int) ExposeTimeN[0].value , false ))
00643       {  
00644     ExposeTimeNP.s = IPS_IDLE;
00645     IDSetNumber(&ExposeTimeNP, "Dark Camera exposure failed.");
00646     IDLog("Dark Camera exposure failed.\n");
00647     return;
00648       }*/
00649       break;
00650       
00651     case FLAT_FRAME:
00652       
00653       /*if (!cam->Expose( (int) ExposeTimeN[0].value , true ))
00654       {  
00655     ExposeTimeNP.s = IPS_IDLE;
00656     IDSetNumber(&ExposeTimeNP, "Flat Camera exposure failed.");
00657     IDLog("Flat Camera exposure failed.\n");
00658     return;
00659       }*/
00660       break;
00661   }
00662       
00663   SBIGFrame.frameType   = curFrame;
00664   SBIGFrame.width   = (int) FrameN[2].value;
00665   SBIGFrame.height  = (int) FrameN[3].value;
00666   SBIGFrame.expose  = (int) ExposeTimeN[0].value;
00667   SBIGFrame.temperature =       TemperatureN[0].value;
00668   SBIGFrame.binX        = (int) BinningN[0].value;
00669   SBIGFrame.binY        = (int) BinningN[1].value;
00670   
00671   ExposeTimeNP.s = IPS_BUSY;
00672           
00673   IDSetNumber(&ExposeTimeNP, "Taking a %g seconds frame...", ExposeTimeN[0].value);
00674   IDLog("Taking a frame...\n");
00675    
00676 }
00677 
00678 /* Retrieves basic data from the CCD upon connection like temperature, array size, firmware..etc */
00679 void SBIGCam::getBasicData()
00680 {
00681 
00682 
00683   // Maximum resolution
00684 
00685   // JM: Update here basic variables upon connection. 
00686 
00687   /*
00688   FrameN[2].max = cam->m_NumX;
00689   FrameN[3].max = cam->m_NumY;
00690   IUUpdateMinMax(&FrameNP);
00691   
00692   // Maximum Bin
00693   BinningN[0].max = cam->m_MaxBinX;
00694   BinningN[1].max = cam->m_MaxBinX;
00695   IUUpdateMinMax(&BinningNP);
00696   
00697   // Current Temperature
00698   TemperatureN[0].value = cam->read_Temperature();
00699   IDSetNumber(&TemperatureNP, NULL);*/
00700   
00701 }
00702 
00703 int SBIGCam::getOnSwitch(ISwitchVectorProperty *sp)
00704 {
00705  for (int i=0; i < sp->nsp ; i++)
00706  {
00707      if (sp->sp[i].s == ISS_ON)
00708       return i;
00709  }
00710 
00711  return -1;
00712 }
00713 
00714 int SBIGCam::checkPowerS(ISwitchVectorProperty *sp)
00715 {
00716   if (PowerSP.s != IPS_OK)
00717   {
00718     if (!strcmp(sp->label, ""))
00719         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->name);
00720     else
00721         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->label);
00722     
00723     sp->s = IPS_IDLE;
00724     IDSetSwitch(sp, NULL);
00725     return -1;
00726   }
00727 
00728   return 0;
00729 }
00730 
00731 int SBIGCam::checkPowerN(INumberVectorProperty *np)
00732 {
00733   if (PowerSP.s != IPS_OK)
00734   {
00735      if (!strcmp(np->label, ""))
00736         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->name);
00737     else
00738         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->label);
00739     
00740     np->s = IPS_IDLE;
00741     IDSetNumber(np, NULL);
00742     return -1;
00743   }
00744 
00745   return 0;
00746 }
00747 
00748 int SBIGCam::checkPowerT(ITextVectorProperty *tp)
00749 {
00750 
00751   if (PowerSP.s != IPS_OK)
00752   {
00753     if (!strcmp(tp->label, ""))
00754         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->name);
00755     else
00756         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->label);
00757     
00758     tp->s = IPS_IDLE;
00759     IDSetText(tp, NULL);
00760     return -1;
00761   }
00762 
00763   return 0;
00764 
00765 }
00766 
00767 void SBIGCam::connectCCD()
00768 {
00769   
00770   switch (PowerS[0].s)
00771   {
00772     case ISS_ON:
00773       if (initCamera())
00774       {
00775     /* Sucess! */
00776     PowerS[0].s = ISS_ON;
00777     PowerS[1].s = ISS_OFF;
00778     PowerSP.s = IPS_OK;
00779     IDSetSwitch(&PowerSP, "CCD is online. Retrieving basic data.");
00780     IDLog("CCD is online. Retrieving basic data.\n");
00781     getBasicData();
00782     
00783       }
00784       else
00785       {
00786         PowerSP.s = IPS_IDLE;
00787         PowerS[0].s = ISS_OFF;
00788         PowerS[1].s = ISS_ON;
00789         IDSetSwitch(&PowerSP, "Error: no cameras were detected.");
00790         IDLog("Error: no cameras were detected.\n");
00791         return;
00792       }
00793       
00794       break;
00795       
00796     case ISS_OFF:
00797       PowerS[0].s = ISS_OFF;
00798       PowerS[1].s = ISS_ON;
00799       PowerSP.s = IPS_IDLE;
00800       IDSetSwitch(&PowerSP, "CCD is offline.");
00801 
00802       // JM: Disconnect cam and clean up
00803       // e.g. disConnectSBIG();
00804       break;
00805      }
00806 
00807 }
00808 
00809 bool SBIGCam::initCamera()
00810 {
00811   // JM: Here, we do all camera initilization stuff and we establish a connection to the camera
00812   // If everything goes well, we return true, otherwise false
00813   // Please use IDLog(...) to report errors.
00814 
00815   return false;
00816 }
00817 
00818 /* isCCDConnected: return 1 if we have a connection, 0 otherwise */
00819 int SBIGCam::isCCDConnected(void)
00820 {
00821   return ((PowerS[0].s == ISS_ON) ? 1 : 0);
00822 }
00823 
00824 FITS_HDU_LIST * SBIGCam::create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp)
00825 {
00826  
00827  FITS_HDU_LIST *hdulist;
00828  
00829  char temp_s[FITS_CARD_SIZE], expose_s[FITS_CARD_SIZE], binning_s[FITS_CARD_SIZE], pixel_s[FITS_CARD_SIZE], frame_s[FITS_CARD_SIZE];
00830  char obsDate[FITS_CARD_SIZE];
00831  
00832  snprintf(obsDate, FITS_CARD_SIZE, "DATE-OBS= '%s' /Observation Date UTC", timestamp());
00833  
00834  hdulist = fits_add_hdu (ofp);
00835  if (hdulist == NULL) return (NULL);
00836 
00837  hdulist->used.simple = 1;
00838  hdulist->bitpix = 16;
00839  hdulist->naxis = 2;
00840  hdulist->naxisn[0] = width;
00841  hdulist->naxisn[1] = height;
00842  hdulist->naxisn[2] = bpp;
00843  // JM: Record here the minimum and maximum pixel values
00844  /*hdulist->used.datamin = min();
00845  hdulist->datamin = min();
00846  hdulist->used.datamax = max();
00847  hdulist->datamax = max();*/
00848  hdulist->used.bzero = 1;
00849  hdulist->bzero = 0.0;
00850  hdulist->used.bscale = 1;
00851  hdulist->bscale = 1.0;
00852  
00853  snprintf(temp_s, FITS_CARD_SIZE, "CCD-TEMP= %g / degrees celcius", SBIGFrame.temperature);
00854  snprintf(expose_s, FITS_CARD_SIZE, "EXPOSURE= %d / milliseconds", SBIGFrame.expose);
00855  snprintf(binning_s, FITS_CARD_SIZE, "BINNING = '(%d x %d)'", SBIGFrame.binX, SBIGFrame.binY);
00856  //sprintf(pixel_s, "PIX-SIZ = '%.0f microns square'", PixelSizeN[0].value);
00857  switch (SBIGFrame.frameType)
00858   {
00859     case LIGHT_FRAME:
00860         strcpy(frame_s, "FRAME   = 'Light'");
00861     break;
00862     case BIAS_FRAME:
00863         strcpy(frame_s, "FRAME   = 'Bias'");
00864     break;
00865     case FLAT_FRAME:
00866         strcpy(frame_s, "FRAME   = 'Flat Field'");
00867     break;
00868     case DARK_FRAME:
00869         strcpy(frame_s, "FRAME   = 'Dark'");
00870     break;
00871   }
00872  
00873  fits_add_card (hdulist, frame_s);   
00874  fits_add_card (hdulist, temp_s);
00875  fits_add_card (hdulist, expose_s);
00876  //fits_add_card (hdulist, pixel_s);
00877 
00878  // JM: If there is a way to get the specific model of the camera, use that.
00879  fits_add_card (hdulist, "INSTRUME= 'SBIG CCD'");
00880  fits_add_card (hdulist, obsDate);
00881   
00882  return (hdulist);
00883 }
00884 

kstars

Skip menu "kstars"
  • Main Page
  • Modules
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • keduca
  • kstars
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal