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

kstars

apogee_ppi.cpp

Go to the documentation of this file.
00001 #if 0
00002     FLI CCD
00003     INDI Interface for Apogee PPI
00004     Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public
00017     License along with this library; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 
00020 #endif
00021  
00022 #include <ctype.h>
00023 #include <sys/stat.h>
00024 #include <sys/time.h>
00025 #include <sys/types.h>
00026 #include <sys/socket.h>
00027 #include <netinet/in.h>
00028 #include <netdb.h>
00029 #include <zlib.h>
00030 
00031 #include "apogee_ppi.h"
00032 #include "lilxml.h"
00033 #include "base64.h"
00034 
00035 static void ISPoll(void *);
00036 
00037 extern char* me;            /* argv[0] */
00038 ApogeeCam *MainCam = NULL;      /* Main and only camera */
00039 
00040 /* send client definitions of all properties */
00041 void ISInit()
00042 {
00043   if (MainCam == NULL)
00044   {
00045     MainCam = new ApogeeCam();
00046     IEAddTimer (POLLMS, ISPoll, NULL);
00047   }
00048 }
00049     
00050 void ISGetProperties (const char *dev)
00051 { 
00052   if (dev && strcmp (mydev, dev))
00053     return;
00054   
00055    ISInit();
00056   
00057   MainCam->ISGetProperties(dev);
00058 }
00059 
00060 
00061 void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
00062 {
00063     
00064   /* ignore if not ours */
00065   if (dev && strcmp (dev, mydev))
00066     return;
00067         
00068   ISInit();
00069   
00070   MainCam->ISNewSwitch(dev, name, states, names, n);
00071 }
00072 
00073 void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
00074 {
00075   /* ignore if not ours */ 
00076   if (dev && strcmp (mydev, dev))
00077     return;
00078 
00079    ISInit();
00080    
00081    MainCam->ISNewText(dev, name, texts, names, n);
00082 }
00083 
00084 
00085 void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
00086 {
00087       
00088   /* ignore if not ours */
00089   if (dev && strcmp (dev, mydev))
00090     return;
00091         
00092   ISInit();
00093   
00094   MainCam->ISNewNumber(dev, name, values, names, n);
00095 }
00096 
00097 void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
00098 {
00099 
00100 }
00101 
00102 void ISPoll(void *)
00103 {
00104  MainCam->ISPoll(); 
00105  IEAddTimer (POLLMS, ISPoll, NULL);
00106 }
00107 
00108 
00109 ApogeeCam::ApogeeCam()
00110 {
00111   ApogeeModelS = NULL;
00112   
00113   initProperties();
00114   
00115 }
00116 
00117 ApogeeCam::~ApogeeCam()
00118 {
00119   
00120 }
00121 
00122 void ApogeeCam::initProperties()
00123 {
00124   fillSwitch(&PowerS[0], "CONNECT", "Connect", ISS_OFF);
00125   fillSwitch(&PowerS[1], "DISCONNECT", "Disconnect", ISS_ON);
00126   fillSwitchVector(&PowerSP, PowerS, NARRAY(PowerS), mydev, "CONNECTION", "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
00127   
00128   fillSwitch(&FrameTypeS[0], "FRAME_LIGHT", "Light", ISS_ON);
00129   fillSwitch(&FrameTypeS[1], "FRAME_BIAS", "Bias", ISS_OFF);
00130   fillSwitch(&FrameTypeS[2], "FRAME_DARK", "Dark", ISS_OFF);
00131   fillSwitch(&FrameTypeS[3], "FRAME_FLAT", "Flat Field", ISS_OFF);
00132   fillSwitchVector(&FrameTypeSP, FrameTypeS, NARRAY(FrameTypeS), mydev, "CCD_FRAME_TYPE", "Frame Type", EXPOSE_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
00133 
00134   fillNumber(&FrameN[0], "X", "X", "%.0f", 0., MAX_PIXELS, 1., 0.);
00135   fillNumber(&FrameN[1], "Y", "Y", "%.0f", 0., MAX_PIXELS, 1., 0.);
00136   fillNumber(&FrameN[2], "WIDTH", "Width", "%.0f", 0., MAX_PIXELS, 1., 0.);
00137   fillNumber(&FrameN[3], "HEIGHT", "Height", "%.0f", 0., MAX_PIXELS, 1., 0.);
00138   fillNumberVector(&FrameNP, FrameN, NARRAY(FrameN), mydev, "CCD_FRAME", "Frame", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
00139   
00140   fillNumber(&BinningN[0], "HOR_BIN", "X", "%0.f", 1., MAXHBIN, 1., 1.);
00141   fillNumber(&BinningN[1], "VER_BIN", "Y", "%0.f", 1., MAXVBIN, 1., 1.);
00142   fillNumberVector(&BinningNP, BinningN, NARRAY(BinningN), mydev, "CCD_BINNING", "Binning", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
00143     
00144   fillNumber(&ExposeTimeN[0], "DURATION", "Duration (s)", "%5.2f", 0., 36000., 0.5, 1.);
00145   fillNumberVector(&ExposeTimeNP, ExposeTimeN, NARRAY(ExposeTimeN), mydev, "CCD_EXPOSE_DURATION", "Expose", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE);
00146   
00147   fillNumber(&TemperatureN[0], "TEMPERATURE", "Temperature", "%+06.2f", MIN_CCD_TEMP, MAX_CCD_TEMP, 0.2, 0.);
00148   fillNumberVector(&TemperatureNP, TemperatureN, NARRAY(TemperatureN), mydev, "CCD_TEMPERATURE", "Expose", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE);
00149   
00150   strcpy(imageB.name, "CCD1");
00151   strcpy(imageB.label, "Feed");
00152   strcpy(imageB.format, "");
00153   imageB.blob    = 0;
00154   imageB.bloblen = 0;
00155   imageB.size    = 0;
00156   imageB.bvp     = 0;
00157   imageB.aux0    = 0;
00158   imageB.aux1    = 0;
00159   imageB.aux2    = 0;
00160   
00161   strcpy(imageBP.device, mydev);
00162   strcpy(imageBP.name, "Video");
00163   strcpy(imageBP.label, "Video");
00164   strcpy(imageBP.group, COMM_GROUP);
00165   strcpy(imageBP.timestamp, "");
00166   imageBP.p       = IP_RO;
00167   imageBP.timeout = 0;
00168   imageBP.s       = IPS_IDLE;
00169   imageBP.bp      = &imageB;
00170   imageBP.nbp     = 1;
00171   imageBP.aux     = 0;
00172   
00173   //loadXMLModel();
00174 }
00175 
00176 bool ApogeeCam::loadXMLModel()
00177 {
00178   LilXML *XMLParser = newLilXML();
00179   XMLEle *root = NULL, *camera = NULL;
00180   XMLAtt *modelName;
00181   FILE *modelSpecFile = NULL;
00182   char errmsg[1024];
00183   int ncams = 0;
00184   
00185   //IDLog("Top dir is "TOP_DATADIR, NULL);
00186   modelSpecFile = fopen(TOP_DATADIR"/apogee_caminfo.xml", "r");
00187   //modelSpecFile = fopen("/opt/kde3/share/apps/kstars/apogee_caminfo.xml", "r");
00188   if (modelSpecFile == NULL) 
00189   {
00190     IDLog("Error: Unable to open file apogee_caminfo.xml\n");
00191     IDMessage(mydev, "Error: Unable to open file apogee_caminfo.xml");
00192     return false;
00193   }
00194   
00195   root = readXMLFile(modelSpecFile, XMLParser, errmsg);
00196   if (root == NULL)
00197   {
00198     IDLog("Error: Unable to process apogee_caminfo.xml. %s\n", errmsg);
00199     IDMessage(mydev, "Error: Unable to process apogee_caminfo.xml. %s\n", errmsg);
00200     fclose(modelSpecFile);
00201     delLilXML(XMLParser);
00202     return false;
00203   }
00204     
00205   for (camera = nextXMLEle (root, 1); camera != NULL; camera = nextXMLEle (root, 0))
00206   {
00207     modelName = findXMLAtt(camera, "model");
00208     if (modelName == NULL) 
00209       continue;
00210     
00211     ApogeeModelS = (ApogeeModelS == NULL) ? (ISwitch *) malloc (sizeof(ISwitch))
00212                                           : (ISwitch *) realloc(ApogeeModelS, sizeof(ISwitch) * (ncams + 1));
00213     
00214     snprintf(ApogeeModelS[ncams].name, MAXINDINAME, "Model%d", ncams);
00215     strcpy(ApogeeModelS[ncams].label, valuXMLAtt(modelName));
00216     ApogeeModelS[ncams].s = (ncams == 0) ? ISS_ON : ISS_OFF;
00217     ApogeeModelS[ncams].svp = NULL;
00218     ApogeeModelS[ncams].aux = NULL;
00219     
00220     ncams++;
00221   }
00222   
00223   fclose(modelSpecFile);
00224   delLilXML(XMLParser);
00225   
00226   if (ncams > 0)
00227   {
00228     fillSwitchVector(&ApogeeModelSP, ApogeeModelS, ncams, mydev, "Model", "", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
00229     return true;
00230   }
00231   
00232   return false;
00233   
00234 }
00235 
00236 void ApogeeCam::ISGetProperties(const char */*dev*/)
00237 {
00238   
00239 
00240   /* COMM_GROUP */
00241   IDDefSwitch(&PowerSP, NULL);
00242   if (loadXMLModel())
00243     IDDefSwitch(&ApogeeModelSP, NULL);
00244   else
00245     IDMessage(mydev, "Error: Unable to read camera specifications. Driver is disabled.");
00246   IDDefBLOB(&imageBP, NULL);
00247 
00248   /* Expose */
00249   IDDefSwitch(&FrameTypeSP, NULL);  
00250   IDDefNumber(&ExposeTimeNP, NULL);
00251   IDDefNumber(&TemperatureNP, NULL);
00252   
00253   /* Image Group */
00254   IDDefNumber(&FrameNP, NULL);
00255   IDDefNumber(&BinningNP, NULL);
00256 
00257   IDLog("Apogee Driver Debug Enabled\n");
00258   
00259 }
00260 
00261 void ApogeeCam::ISNewSwitch (const char */*dev*/, const char *name, ISState *states, char *names[], int n)
00262 {
00263   
00264     /* Connection */
00265     if (!strcmp (name, PowerSP.name))
00266     {
00267         IUResetSwitches(&PowerSP);
00268         IUUpdateSwitches(&PowerSP, states, names, n);
00269         connectCCD();
00270         return;
00271     }
00272     
00273         /* Frame Type */
00274         if (!strcmp(FrameTypeSP.name, name))
00275     {
00276         if (checkPowerS(&FrameTypeSP))
00277             return;
00278         
00279         IUResetSwitches(&FrameTypeSP);
00280         IUUpdateSwitches(&FrameTypeSP, states, names, n);
00281         FrameTypeSP.s = IPS_OK;
00282         IDSetSwitch(&FrameTypeSP, NULL);
00283         
00284         return;
00285     }
00286      
00287         /* Apogee Model */
00288         if (!strcmp(ApogeeModelSP.name, name))
00289     {
00290         IUResetSwitches(&ApogeeModelSP);
00291         IUUpdateSwitches(&ApogeeModelSP, states, names, n);
00292         ApogeeModelSP.s = IPS_OK;
00293         IDSetSwitch(&ApogeeModelSP, NULL);
00294         return;
00295     }
00296     
00297 }
00298 
00299 void ApogeeCam::ISNewText (const char */*dev*/, const char */*name*/, char **/*texts[]*/, char **/*names[]*/, int /*n*/)
00300 {
00301   
00302 }
00303 
00304 void ApogeeCam::ISNewNumber (const char */*dev*/, const char *name, double values[], char *names[], int n)
00305 {
00306     /* Exposure time */
00307     if (!strcmp (ExposeTimeNP.name, name))
00308     {
00309        if (checkPowerN(&ExposeTimeNP))
00310          return;
00311 
00312        if (ExposeTimeNP.s == IPS_BUSY)
00313        {
00314       cam->Reset();
00315       ExposeTimeNP.s = IPS_IDLE;
00316       ExposeTimeN[0].value = 0;
00317 
00318       IDSetNumber(&ExposeTimeNP, "Exposure cancelled.");
00319       IDLog("Exposure Cancelled.\n");
00320       return;
00321         }
00322     
00323        ExposeTimeNP.s = IPS_IDLE;
00324        
00325        IUUpdateNumbers(&ExposeTimeNP, values, names, n);
00326        
00327       IDLog("Exposure Time is: %g\n", ExposeTimeN[0].value);
00328       
00329       handleExposure(NULL);
00330       return;
00331     } 
00332     
00333   if (!strcmp(TemperatureNP.name, name))
00334   {
00335     if (checkPowerN(&TemperatureNP))
00336       return;
00337       
00338     TemperatureNP.s = IPS_IDLE;
00339     
00340     if (values[0] < MIN_CCD_TEMP || values[0] > MAX_CCD_TEMP)
00341     {
00342       IDSetNumber(&TemperatureNP, "Error: valid range of temperature is from %d to %d", MIN_CCD_TEMP, MAX_CCD_TEMP);
00343       return;
00344     }
00345     
00346     targetTemp = values[0];
00347     cam->write_CoolerMode(0);
00348     cam->write_CoolerMode(1);
00349     cam->write_CoolerSetPoint(targetTemp);
00350     
00351     TemperatureNP.s = IPS_BUSY;
00352     
00353     IDSetNumber(&TemperatureNP, "Setting CCD temperature to %+06.2f C", values[0]);
00354     IDLog("Setting CCD temperature to %+06.2f C\n", values[0]);
00355     return;
00356    }
00357    
00358    if (!strcmp(FrameNP.name, name))
00359    {
00360      if (checkPowerN(&FrameNP))
00361       return;
00362       
00363      FrameNP.s = IPS_OK;
00364      IUUpdateNumbers(&FrameNP, values, names, n);
00365      
00366      cam->m_StartX = (int) FrameN[0].value;
00367      cam->m_StartY = (int) FrameN[1].value;
00368      cam->m_NumX   = (int) FrameN[2].value;
00369      cam->m_NumY   = (int) FrameN[3].value;
00370      IDSetNumber(&FrameNP, NULL);
00371       
00372    } /* end FrameNP */
00373       
00374     
00375    if (!strcmp(BinningNP.name, name))
00376    {
00377      if (checkPowerN(&BinningNP))
00378        return;
00379        
00380      
00381      BinningNP.s = IPS_OK;
00382      IUUpdateNumbers(&BinningNP, values, names, n);
00383      
00384      cam->m_BinX = (int) BinningN[0].value;
00385      cam->m_BinY = (int) BinningN[1].value;
00386      
00387      IDLog("Binning is: %.0f x %.0f\n", BinningN[0].value, BinningN[1].value);
00388      return;
00389    }
00390 }
00391 
00392 
00393 void ApogeeCam::ISPoll()
00394 {
00395   static int mtc=5;
00396   int readStatus=0;
00397   double ccdTemp;
00398 
00399   if (!isCCDConnected())
00400    return;
00401 
00402   switch (ExposeTimeNP.s)
00403   {
00404     case IPS_IDLE:
00405     case IPS_OK:
00406       break;
00407         
00408     case IPS_BUSY:
00409       
00410       readStatus = cam->read_Status();
00411       if (readStatus < 0)
00412       {
00413     IDLog("Error in exposure! Read status: %d\n", readStatus);
00414     ExposeTimeNP.s = IPS_ALERT;
00415     ExposeTimeN[0].value = 0;
00416     IDSetNumber(&ExposeTimeNP, "Error in exposure procedure. Read states: %d", readStatus);
00417     return;
00418       }
00419       else if (readStatus == Camera_Status_ImageReady)
00420       {
00421     ExposeTimeN[0].value = 0;
00422     ExposeTimeNP.s = IPS_OK;
00423     IDSetNumber(&ExposeTimeNP, "Exposure done, downloading image...");
00424     IDLog("Exposure done, downloading image...\n");
00425     /* grab and save image */
00426     grabImage();
00427     return;
00428       }
00429       
00430       ExposeTimeN[0].value --;
00431       IDSetNumber(&ExposeTimeNP, NULL);
00432       break;
00433         
00434     case IPS_ALERT:
00435         break;
00436     }
00437      
00438     switch (TemperatureNP.s)
00439     {
00440        case IPS_IDLE:
00441        case IPS_OK:
00442          mtc--;
00443          
00444          if (mtc == 0)
00445          {
00446            TemperatureN[0].value = cam->read_Temperature();
00447            IDSetNumber(&TemperatureNP, NULL);
00448            mtc = 5;
00449          }
00450          break;
00451          
00452        case IPS_BUSY:
00453        
00454          ccdTemp = cam->read_Temperature();
00455          
00456          if (fabs(targetTemp - ccdTemp) <= TEMP_THRESHOLD)
00457            TemperatureNP.s = IPS_OK;
00458                    
00459           mtc = 1;
00460               TemperatureN[0].value = ccdTemp;
00461           IDSetNumber(&TemperatureNP, NULL);
00462           break;
00463           
00464         case IPS_ALERT:
00465          break;
00466       }
00467       
00468 }
00469 
00470 /* Downloads the image from the CCD row by row and store them
00471    in a raw file.
00472  N.B. No processing is done on the image */
00473 void ApogeeCam::grabImage()
00474 {
00475   
00476   long err;
00477   int img_size, fd;
00478   char errmsg[1024];
00479   char filename[] = "/tmp/fitsXXXXXX";
00480 
00481    IDLog("In grab Image\n");
00482   
00483    if ((fd = mkstemp(filename)) < 0)
00484    { 
00485     IDMessage(mydev, "Error making temporary filename.");
00486     IDLog("Error making temporary filename.\n");
00487     return;
00488    }
00489    close(fd);
00490      
00491    img_size = APGFrame.width * APGFrame.height * sizeof(unsigned short);
00492    
00493    IDLog("Allocating memory buffer. Width: %d - Height: %d\n", APGFrame.width, APGFrame.height);
00494 
00495    APGFrame.img = (unsigned short *) malloc (img_size);
00496    
00497   if (APGFrame.img == NULL)
00498   {
00499     IDMessage(mydev, "Not enough memory to store image.");
00500     IDLog("Not enough memory to store image.\n");
00501     return;
00502   }
00503   
00504   IDLog("Getting frame buffer from camera...\n");
00505   if (!cam->GetImage( APGFrame.img , APGFrame.width, APGFrame.height ))
00506   {
00507        free(APGFrame.img);
00508        IDMessage(mydev, "GetImage() failed.");
00509        IDLog("GetImage() failed.");
00510        return;
00511   }
00512 
00513   IDLog("Done with getting frame buffer, writing FITS file\n");
00514   
00515    err = writeFITS(filename, errmsg);
00516    
00517    if (err)
00518    {
00519        free(APGFrame.img);
00520        IDMessage(mydev, errmsg, NULL);
00521        return;
00522    }
00523    
00524   free(APGFrame.img);
00525 
00526   IDLog("All good, returning\n");
00527    
00528 }
00529 
00530 int ApogeeCam::writeFITS(char *filename, char errmsg[])
00531 {
00532   
00533   FITS_FILE* ofp;
00534   int bpp, bpsl, width, height;
00535   long nbytes;
00536   FITS_HDU_LIST *hdu;
00537   
00538   IDLog("in write FITS, opening filename %s\n", filename);
00539 
00540   ofp = fits_open (filename, "w");
00541   if (!ofp)
00542   {
00543     sprintf(errmsg, "Error: cannot open file for writing.");
00544     return (-1);
00545   }
00546   
00547   width  = APGFrame.width;
00548   height = APGFrame.height;
00549   bpp    = sizeof(unsigned short); /* Bytes per Pixel */
00550   bpsl   = bpp * APGFrame.width;    /* Bytes per Line */
00551   nbytes = 0;
00552   
00553   IDLog("Creating FITS header\n");
00554   hdu = create_fits_header (ofp, width, height, bpp);
00555   if (hdu == NULL)
00556   {
00557      sprintf(errmsg, "Error: creating FITS header failed.");
00558      return (-1);
00559   }
00560   if (fits_write_header (ofp, hdu) < 0)
00561   {
00562     sprintf(errmsg, "Error: writing to FITS header failed.");
00563     return (-1);
00564   }
00565   
00566   IDLog("Converting to BIG Endian\n");
00567   for (int i=0; i < height; i++)
00568     for (int j=0 ; j < width; j++)
00569       APGFrame.img[width * i + j] = getBigEndian( (APGFrame.img[width * i + j]) );
00570   
00571   IDLog("Writing frame to disk\n");
00572   for (int i= 0; i < height  ; i++)
00573   {
00574     fwrite(APGFrame.img + (i * width), 2, width, ofp->fp);
00575     nbytes += bpsl;
00576   }
00577   
00578   IDLog("Calculating nbytes\n");
00579   nbytes = nbytes % FITS_RECORD_SIZE;
00580   if (nbytes)
00581   {
00582     while (nbytes++ < FITS_RECORD_SIZE)
00583       putc (0, ofp->fp);
00584   }
00585   
00586   if (ferror (ofp->fp))
00587   {
00588     sprintf(errmsg, "Error: write error occured");
00589     return (-1);
00590   }
00591  
00592  IDLog("Closing ofp\n");
00593  fits_close (ofp);      
00594  
00595   /* Success */
00596  ExposeTimeNP.s = IPS_OK;
00597  IDSetNumber(&ExposeTimeNP, NULL);
00598  IDLog("Loading FITS image...\n");
00599  
00600  IDLog("Uploading filename\n");
00601  uploadFile(filename);
00602  IDLog("Uploading done, returning\n");
00603 
00604  return 0;
00605 
00606 }
00607 
00608 void ApogeeCam::uploadFile(char * filename)
00609 {
00610 
00611    FILE * fitsFile;
00612    unsigned char *fitsData, *compressedData;
00613    int r=0;
00614    unsigned int i =0, nr = 0;
00615    uLongf compressedBytes=0;
00616    uLong  totalBytes;
00617    struct stat stat_p; 
00618 
00619    IDLog("in upload file, will stat file now\n");
00620  
00621    if ( -1 ==  stat (filename, &stat_p))
00622    { 
00623      IDLog(" Error occoured attempting to stat %s\n", filename); 
00624      return; 
00625    }
00626    
00627    totalBytes     = stat_p.st_size;
00628    fitsData       = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes);
00629    compressedData = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
00630    
00631    if (fitsData == NULL || compressedData == NULL)
00632    {
00633      IDLog("Error! low memory. Unable to initialize fits buffers.\n");
00634      return;
00635    }
00636    
00637    IDLog("opening file\n");
00638    fitsFile = fopen(filename, "r");
00639    
00640    if (fitsFile == NULL)
00641     return;
00642    
00643    IDLog("Reading file from disk\n");
00644    /* #1 Read file from disk */ 
00645    for (i=0; i < totalBytes; i+= nr)
00646    {
00647       nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
00648      
00649      if (nr <= 0)
00650      {
00651         IDLog("Error reading temporary FITS file.\n");
00652         return;
00653      }
00654    }
00655    
00656    compressedBytes = sizeof(char) * totalBytes + totalBytes / 64 + 16 + 3;
00657      
00658    IDLog("Compressing data\n");
00659    /* #2 Compress it */
00660    r = compress2(compressedData, &compressedBytes, fitsData, totalBytes, 9);
00661    if (r != Z_OK)
00662    {
00663     /* this should NEVER happen */
00664     IDLog("internal error - compression failed: %d\n", r);
00665     return;
00666    }
00667    
00668    IDLog("Sending blob. bloblen %ld - size %ld\n", compressedBytes, totalBytes);
00669 
00670    /* #3 Send it */
00671    imageB.blob = compressedData;
00672    imageB.bloblen = compressedBytes;
00673    imageB.size = totalBytes;
00674    strcpy(imageB.format, ".fits.z");
00675    imageBP.s = IPS_OK;
00676    IDSetBLOB (&imageBP, NULL);
00677    
00678    free (fitsData);   
00679    free (compressedData);
00680    
00681 }
00682 
00683 /* Initiates the exposure procedure */
00684 void ApogeeCam::handleExposure(void */*p*/)
00685 {
00686   
00687   int curFrame = getOnSwitch(&FrameTypeSP);
00688   
00689   switch (curFrame)
00690   {
00691     /* Light frame */ 
00692    case LIGHT_FRAME:
00693    if (!cam->Expose( (int) ExposeTimeN[0].value, true ))
00694    {  
00695      ExposeTimeNP.s = IPS_IDLE;
00696      IDSetNumber(&ExposeTimeNP, "Light Camera exposure failed.");
00697      IDLog("Light Camera exposure failed.\n");
00698      return;
00699    }
00700    break;
00701    
00702    /* BIAS frame is the same as DARK but with minimum period. i.e. readout from camera electronics.
00703    */
00704     case BIAS_FRAME:
00705       if (!cam->Expose( 0.05 , false ))
00706       {  
00707     ExposeTimeNP.s = IPS_IDLE;
00708     IDSetNumber(&ExposeTimeNP, "Bias Camera exposure failed.");
00709     IDLog("Bias Camera exposure failed.\n");
00710     return;
00711       }
00712       break;
00713       
00714       /* Dark frame */
00715     case DARK_FRAME:
00716       if (!cam->Expose( (int) ExposeTimeN[0].value , false ))
00717       {  
00718     ExposeTimeNP.s = IPS_IDLE;
00719     IDSetNumber(&ExposeTimeNP, "Dark Camera exposure failed.");
00720     IDLog("Dark Camera exposure failed.\n");
00721     return;
00722       }
00723       break;
00724       
00725     case FLAT_FRAME:
00726       if (!cam->Expose( (int) ExposeTimeN[0].value , true ))
00727       {  
00728     ExposeTimeNP.s = IPS_IDLE;
00729     IDSetNumber(&ExposeTimeNP, "Flat Camera exposure failed.");
00730     IDLog("Flat Camera exposure failed.\n");
00731     return;
00732       }
00733       break;
00734   }
00735       
00736   APGFrame.frameType    = curFrame;
00737   APGFrame.width    = (int) FrameN[2].value;
00738   APGFrame.height   = (int) FrameN[3].value;
00739   APGFrame.expose   = (int) ExposeTimeN[0].value;
00740   APGFrame.temperature  =       TemperatureN[0].value;
00741   APGFrame.binX         = (int) BinningN[0].value;
00742   APGFrame.binY         = (int) BinningN[1].value;
00743   
00744   ExposeTimeNP.s = IPS_BUSY;
00745           
00746   IDSetNumber(&ExposeTimeNP, "Taking a %g seconds frame...", ExposeTimeN[0].value);
00747   IDLog("Taking a frame. Width: %d - Height: %d - expose %d - temperature %g - binX %d - binY %d\n", APGFrame.width, APGFrame.height, APGFrame.expose, APGFrame.temperature, APGFrame.binX, APGFrame.binY);
00748    
00749 }
00750 
00751 /* Retrieves basic data from the CCD upon connection like temperature, array size, firmware..etc */
00752 void ApogeeCam::getBasicData()
00753 {
00754 
00755 
00756   // Maximum resolution
00757   FrameN[2].max = cam->m_NumX;
00758   FrameN[3].max = cam->m_NumY;
00759   IUUpdateMinMax(&FrameNP);
00760   
00761   // Maximum Bin
00762   BinningN[0].max = cam->m_MaxBinX;
00763   BinningN[1].max = cam->m_MaxBinX;
00764   IUUpdateMinMax(&BinningNP);
00765 
00766   FrameN[0].value = 0;
00767   FrameN[1].value = 0;
00768   FrameN[2].min   = 0;
00769   FrameN[2].max   = cam->m_ImgColumns;
00770   FrameN[2].value = cam->m_ImgColumns;
00771   FrameN[3].min   = 0;
00772   FrameN[3].max   = cam->m_ImgRows;
00773   FrameN[3].value = cam->m_ImgRows;
00774 
00775   IUUpdateMinMax(&FrameNP);
00776   IDSetNumber(&FrameNP, NULL);
00777   
00778   // Current Temperature
00779   TemperatureN[0].value = cam->read_Temperature();
00780   IDSetNumber(&TemperatureNP, NULL);
00781   
00782 }
00783 
00784 int ApogeeCam::getOnSwitch(ISwitchVectorProperty *sp)
00785 {
00786   int i=0;
00787  for (i=0; i < sp->nsp ; i++)
00788  {
00789    /*IDLog("Switch %s is %s\n", sp->sp[i].name, sp->sp[i].s == ISS_ON ? "On" : "Off");*/
00790      if (sp->sp[i].s == ISS_ON)
00791       return i;
00792  }
00793 
00794  return -1;
00795 }
00796 
00797 int ApogeeCam::checkPowerS(ISwitchVectorProperty *sp)
00798 {
00799   if (PowerSP.s != IPS_OK)
00800   {
00801     if (!strcmp(sp->label, ""))
00802         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->name);
00803     else
00804         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->label);
00805     
00806     sp->s = IPS_IDLE;
00807     IDSetSwitch(sp, NULL);
00808     return -1;
00809   }
00810 
00811   return 0;
00812 }
00813 
00814 int ApogeeCam::checkPowerN(INumberVectorProperty *np)
00815 {
00816   if (PowerSP.s != IPS_OK)
00817   {
00818      if (!strcmp(np->label, ""))
00819         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->name);
00820     else
00821         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->label);
00822     
00823     np->s = IPS_IDLE;
00824     IDSetNumber(np, NULL);
00825     return -1;
00826   }
00827 
00828   return 0;
00829 }
00830 
00831 int ApogeeCam::checkPowerT(ITextVectorProperty *tp)
00832 {
00833 
00834   if (PowerSP.s != IPS_OK)
00835   {
00836     if (!strcmp(tp->label, ""))
00837         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->name);
00838     else
00839         IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->label);
00840     
00841     tp->s = IPS_IDLE;
00842     IDSetText(tp, NULL);
00843     return -1;
00844   }
00845 
00846   return 0;
00847 
00848 }
00849 
00850 void ApogeeCam::connectCCD()
00851 {
00852   
00853   /* USB by default {USB, SERIAL, PARALLEL, INET} */
00854   switch (PowerS[0].s)
00855   {
00856     case ISS_ON:
00857       if (initCamera())
00858       {
00859     /* Sucess! */
00860     PowerS[0].s = ISS_ON;
00861     PowerS[1].s = ISS_OFF;
00862     PowerSP.s = IPS_OK;
00863     IDSetSwitch(&PowerSP, "CCD is online. Retrieving basic data.");
00864     IDLog("CCD is online. Retrieving basic data.\n");
00865     getBasicData();
00866     
00867       }
00868       else
00869       {
00870         PowerSP.s = IPS_IDLE;
00871         PowerS[0].s = ISS_OFF;
00872         PowerS[1].s = ISS_ON;
00873         IDSetSwitch(&PowerSP, "Error: no cameras were detected.");
00874         IDLog("Error: no cameras were detected.\n");
00875         return;
00876       }
00877       
00878       break;
00879       
00880     case ISS_OFF:
00881       PowerS[0].s = ISS_OFF;
00882       PowerS[1].s = ISS_ON;
00883       PowerSP.s = IPS_IDLE;
00884       IDSetSwitch(&PowerSP, "CCD is offline.");
00885       break;
00886      }
00887 
00888 }
00889 
00890 bool ApogeeCam::initCamera()
00891 {
00892   LilXML *XMLParser = newLilXML();
00893   XMLEle *root = NULL, *camera = NULL, *ele = NULL;
00894   XMLEle *system = NULL, *geometry = NULL, *temp = NULL, *ccd = NULL;
00895   XMLAtt *ap;
00896   FILE *spFile = NULL;
00897   char errmsg[1024];
00898   
00899   spFile = fopen(TOP_DATADIR"/apogee_caminfo.xml", "r");
00900   //spFile = fopen("/opt/kde3/share/apps/kstars/apogee_caminfo.xml", "r");
00901   if (spFile == NULL) 
00902   {
00903     IDLog("Error: Unable to open file apogee_caminfo.xml\n");
00904     IDMessage(mydev, "Error: Unable to open file apogee_caminfo.xml");
00905     return false;
00906   }
00907   
00908   root = readXMLFile(spFile, XMLParser, errmsg);
00909   if (root == NULL)
00910   {
00911     IDLog("Error: Unable to process apogee_caminfo.xml. %s\n", errmsg);
00912     IDMessage(mydev, "Error: Unable to process apogee_caminfo.xml. %s\n", errmsg);
00913     fclose(spFile);
00914     delLilXML(XMLParser);
00915     return false;
00916   }
00917   
00918   fclose(spFile);
00919   
00920   // Let's locate which camera to load the configuration for  
00921   camera = findXMLEle(root, "Apogee_Camera");
00922   
00923   if (camera == NULL)
00924   {
00925     IDLog("Error: Unable to find Apogee_Camera element.\n");
00926     IDMessage(mydev, "Error: Unable to find Apogee_Camera element.");
00927     delLilXML(XMLParser);
00928     return false;
00929   }
00930    
00931   IDLog("Looking for %s - len %d\n", ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label, strlen(ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label));
00932   
00933   ap = findXMLAtt(camera, "model");
00934   if (!ap)
00935   {
00936     IDLog("Error: Unable to find attribute model.\n");
00937     IDMessage(mydev, "Error: Unable to find attribute model.");
00938     return false;
00939   }
00940   
00941   if (strcmp(valuXMLAtt(ap), ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label))
00942   {
00943     IDLog("Camera %s not found in XML file\n", ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label);
00944     IDMessage(mydev, "Camera %s not found in XML file\n", ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label);
00945     delLilXML(XMLParser);
00946     return false;
00947   }
00948   
00949   // Let's get the subsections now
00950   system   = findXMLEle(camera, "System");
00951   geometry = findXMLEle(camera, "Geometry");
00952   temp     = findXMLEle(camera, "Temp");
00953   ccd      = findXMLEle(camera, "CCD");
00954   
00955   if (system == NULL)
00956   {
00957     IDLog("Error: Unable to find System element in camera.\n");
00958     IDMessage(mydev, "Error: Unable to find System element in camera.");
00959     delLilXML(XMLParser);
00960     return false;
00961   }
00962   
00963   if (geometry == NULL)
00964   {
00965     IDLog("Error: Unable to find Geometry element in camera.\n");
00966     IDMessage(mydev, "Error: Unable to find Geometry element in camera.");
00967     delLilXML(XMLParser);
00968     return false;
00969   }
00970   
00971   if (temp == NULL)
00972   {
00973     IDLog("Error: Unable to find Temp element in camera.\n");
00974     IDMessage(mydev, "Error: Unable to find Temp element in camera.");
00975     delLilXML(XMLParser);
00976     return false;
00977   }
00978   
00979   if (ccd == NULL)
00980   {
00981     IDLog("Error: Unable to find CCD element in camera.\n");
00982     IDMessage(mydev, "Error: Unable to find CCD element in camera.");
00983     delLilXML(XMLParser);
00984     return false;
00985   }
00986   
00987   cam = new CCameraIO();
00988   
00989   if (cam == NULL)
00990   {
00991     IDLog("Error: Failed to create CCameraIO object.\n");
00992     IDMessage(mydev, "Error: Failed to create CCameraIO object.");
00993     delLilXML(XMLParser);
00994     return false; 
00995   }
00996   
00997   int bAddr = 0x378;
00998   int val   = 0;
00999   
01000   bAddr = hextoi(valuXMLAtt(findXMLAtt(system, "Base"))) & 0xFFF;
01001   
01002   // Rows
01003   ap = findXMLAtt(geometry, "Rows");
01004   if (!ap)
01005   {
01006     IDLog("Error: Unable to find attribute Rows.\n");
01007     IDMessage(mydev, "Error: Unable to find attribute Rows.");
01008     delLilXML(XMLParser);
01009     return false;
01010   }
01011   
01012   cam->m_Rows = hextoi(valuXMLAtt(ap));
01013   
01014   // Columns
01015   ap = findXMLAtt(geometry, "Columns");
01016   if (!ap)
01017   {
01018     IDLog("Error: Unable to find attribute Columns.\n");
01019     IDMessage(mydev, "Error: Unable to find attribute Columns.");
01020     delLilXML(XMLParser);
01021     return false;
01022   }
01023   
01024   cam->m_Columns = hextoi(valuXMLAtt(ap));
01025   
01026   // pp_repeat
01027   ele = findXMLEle(system, "PP_Repeat");
01028   if (!ele)
01029   {
01030     IDLog("Error: Unable to find element PP_Repeat.\n");
01031     IDMessage(mydev, "Error: Unable to find element PP_Repeat.");
01032     delLilXML(XMLParser);
01033     return false;
01034   }
01035   
01036   val = hextoi(pcdataXMLEle(ele));
01037   if (val > 0 && val <= 1000)
01038       cam->m_PPRepeat = val;
01039 
01040   // Initiate driver
01041   if (!cam->InitDriver(0))
01042   {
01043     IDLog("Error: Failed to Init Driver.\n");
01044     IDMessage(mydev, "Error: Failed to Init Driver.");
01045     delLilXML(XMLParser);
01046     return false;
01047   }
01048 
01049   cam->Reset();
01050   
01051   // Cable length
01052   ele = findXMLEle(system, "Cable");
01053   if (!ele)
01054   {
01055     IDLog("Error: Unable to find element Cable.\n");
01056     IDMessage(mydev, "Error: Unable to find element Cable.");
01057     delLilXML(XMLParser);
01058     return false;
01059  }
01060  
01061  if (!strcmp("Long", pcdataXMLEle(ele)))
01062  {
01063    cam->write_LongCable( true );
01064    IDLog("Cable is long\n");
01065  }
01066  else
01067  {
01068    cam->write_LongCable( false );
01069    IDLog("Cable is short\n");
01070  }
01071  
01072  
01073  if (!cam->read_Present())
01074  {
01075    IDLog("Error: read_Present() failed.\n");
01076    IDMessage(mydev, "Error: read_Present() failed.");
01077    delLilXML(XMLParser);
01078    return false;
01079 }
01080  
01081  // Default settings
01082  cam->write_UseTrigger( false );
01083  cam->write_ForceShutterOpen( false );
01084  
01085  // High priority
01086  ele = findXMLEle(system, "High_Priority");
01087  if (ele)
01088  {
01089    if (!strcmp(pcdataXMLEle(ele), "True"))
01090      cam->m_HighPriority = true;
01091    else
01092      cam->m_HighPriority = false;
01093  }
01094  
01095  // Data bits
01096  ele = findXMLEle(system, "Data_Bits");
01097  if (ele)
01098  {
01099    val = hextoi(pcdataXMLEle(ele));
01100    if (val >= 8 && val <= 18) cam->m_DataBits = val;
01101  }
01102  
01103  // Sensor
01104  ele = findXMLEle(system, "Sensor");
01105  if (ele)
01106  {
01107    if (!strcmp(pcdataXMLEle(ele), "CCD"))
01108      cam->m_SensorType = Camera_SensorType_CCD;
01109    else
01110      cam->m_SensorType = Camera_SensorType_CMOS;
01111  }
01112  
01113  // Mode
01114  ele = findXMLEle(system, "Mode");
01115  if (ele)
01116  {
01117    val = hextoi(pcdataXMLEle(ele)) & 0xF;
01118    cam->write_Mode( val );
01119    IDLog("Mode %d\n", val);
01120  }
01121  else
01122    cam->write_Mode( 0 );
01123  
01124  // Test
01125  ele = findXMLEle(system, "Test");
01126  if (ele)
01127  {
01128    val = hextoi(pcdataXMLEle(ele)) & 0xF;
01129    cam->write_TestBits( val );
01130    IDLog("Test bits %d\n", val);
01131  }
01132  else
01133    cam->write_TestBits( 0 );
01134  
01135  // Test2
01136  ele = findXMLEle(system, "Test2");
01137  if (ele)
01138  {
01139    val = hextoi(pcdataXMLEle(ele)) & 0xF;
01140    cam->write_Test2Bits( val );
01141    IDLog("Test 2 bits %d\n", val);
01142  }
01143  else
01144    cam->write_Test2Bits( 0 );
01145  
01146  // Shutter Speed
01147  ele = findXMLEle(system, "Shutter_Speed");
01148  if (ele)
01149  {
01150    cam->m_MaxExposure = 10485.75;
01151    
01152    if (!strcmp(pcdataXMLEle(ele), "Normal"))
01153    {
01154      cam->m_FastShutter = false;
01155      cam->m_MinExposure = 0.01;
01156      IDLog("Shutter speed normal\n");
01157    }
01158    else if ( (!strcmp(pcdataXMLEle(ele), "Fast")) || (!strcmp(pcdataXMLEle(ele), "Dual")) )
01159    {
01160      cam->m_FastShutter = true;
01161      cam->m_MinExposure = 0.001;
01162      IDLog("Shutter speed fast\n");
01163    }
01164  }
01165  
01166  // Shutter Bits
01167  ele = findXMLEle(system, "Shutter_Bits");
01168  if (ele)
01169  {
01170    val = hextoi(pcdataXMLEle(ele));
01171    cam->m_FastShutterBits_Mode = val & 0x0F;
01172    cam->m_FastShutterBits_Test = ( val & 0xF0 ) >> 4;
01173    IDLog("Shutter bits %d\n", val);
01174  }
01175  
01176  // Max X Bin
01177  ele = findXMLEle(system, "MaxBinX");
01178  if (ele)
01179  {
01180    val = hextoi(pcdataXMLEle(ele));
01181    if (val >= 1 && val <= MAXHBIN) 
01182      cam->m_MaxBinX = val;
01183  }
01184  
01185  // Max Y Bin
01186  ele = findXMLEle(system, "MaxBinY");
01187  if (ele)
01188  {
01189    val = hextoi(pcdataXMLEle(ele));
01190    if (val >= 1 && val <= MAXVBIN) 
01191      cam->m_MaxBinY = val;
01192  }
01193  
01194  // Guider Relays
01195  ele = findXMLEle(system, "Guider_Relays");
01196  if (ele)
01197  {
01198    if (!strcmp(pcdataXMLEle(ele), "True"))
01199      cam->m_GuiderRelays = true;
01200    else
01201      cam->m_GuiderRelays = false;
01202  }
01203  
01204  // Timeout
01205  ele = findXMLEle(system, "Timeout");
01206  if (ele)
01207  {
01208    double dval = atof(pcdataXMLEle(ele));
01209    if (dval >= 0.0 && dval <= 10000.0) cam->m_Timeout = dval;
01210  }
01211  
01212  // BIC
01213   ele = findXMLEle(geometry, "BIC");
01214   if (ele)
01215   {
01216     val = hextoi(pcdataXMLEle(ele));
01217     if (val >= 1 && val <= MAXCOLUMNS)
01218       cam->m_BIC = val;
01219   }
01220   
01221    // BIR
01222   ele = findXMLEle(geometry, "BIR");
01223   if (ele)
01224   {
01225     val = hextoi(pcdataXMLEle(ele));
01226     if (val >= 1 && val <= MAXROWS)
01227       cam->m_BIR = val;
01228   }
01229   
01230   // SKIPC
01231   ele = findXMLEle(geometry, "SKIPC");
01232   if (ele)
01233   {
01234     val = hextoi(pcdataXMLEle(ele));
01235     if (val >= 1 && val <= MAXCOLUMNS)
01236       cam->m_SkipC = val;
01237   }
01238   
01239   // SKIPR
01240   ele = findXMLEle(geometry, "SKIPR");
01241   if (ele)
01242   {
01243     val = hextoi(pcdataXMLEle(ele));
01244     if (val >= 1 && val <= MAXROWS)
01245       cam->m_SkipR = val;
01246   }
01247   
01248   // IMG COlS
01249   ele = findXMLEle(geometry, "ImgCols");
01250   if (ele)
01251   {
01252     val = hextoi(pcdataXMLEle(ele));
01253     if (val >= 1 && val <= MAXTOTALCOLUMNS)
01254       cam->m_ImgColumns = val;
01255   }
01256   else
01257     cam->m_ImgColumns = cam->m_Columns - cam->m_BIC - cam->m_SkipC;
01258   
01259   // IMG ROWS
01260   ele = findXMLEle(geometry, "ImgRows");
01261   if (ele)
01262   {
01263     val = hextoi(pcdataXMLEle(ele));
01264     if (val >= 1 && val <= MAXTOTALROWS)
01265       cam->m_ImgRows = val;
01266   }
01267   else
01268     cam->m_ImgRows = cam->m_Rows - cam->m_BIR - cam->m_SkipR;
01269   
01270   // Hor Flush
01271   ele = findXMLEle(geometry, "HFlush");
01272   if (ele)
01273   {
01274     val = hextoi(pcdataXMLEle(ele));
01275     if (val >= 1 && val <= MAXHBIN) 
01276       cam->m_HFlush = val;
01277   }
01278   
01279   // Ver Flush
01280   ele = findXMLEle(geometry, "VFlush");
01281   if (ele)
01282   {
01283     val = hextoi(pcdataXMLEle(ele));
01284     if (val >= 1 && val <= MAXVBIN) 
01285       cam->m_VFlush = val;
01286   }
01287 
01288   // Default to full frame
01289   cam->m_NumX = cam->m_ImgColumns;
01290   cam->m_NumY = cam->m_ImgRows;
01291   
01292   // Temp Control 
01293   ap = findXMLAtt(temp, "Control");
01294   if (ap)
01295   {
01296     if (!strcmp(valuXMLAtt(ap), "True"))
01297       cam->m_TempControl = true;
01298     else
01299       cam->m_TempControl = false;
01300   }
01301   
01302   // Calibration
01303   ap = findXMLAtt(temp, "Cal");
01304   if (ap)
01305   {
01306     val = hextoi(valuXMLAtt(ap));
01307     if (val >= 1 && val <= 255) 
01308       cam->m_TempCalibration = val;
01309   }
01310   
01311   // Scale
01312   ap = findXMLAtt(temp, "Scale");
01313   if (ap)
01314   {
01315     double dval = atof(valuXMLAtt(ap));
01316     if (dval >= 1.0 && dval <= 10.0) 
01317       cam->m_TempScale = dval;
01318   }
01319   
01320   // Target
01321   ap = findXMLAtt(temp, "Target");
01322   if (ap)
01323   {
01324     double dval = atof(valuXMLAtt(ap));
01325     if (dval >= -60.0 && dval <= 40.0) 
01326       cam->write_CoolerSetPoint( dval );
01327     else
01328       cam->write_CoolerSetPoint( -10.0 );       // Default   
01329     
01330     IDLog("Target: %g\n", dval);
01331   }
01332   
01333   // Sensor
01334   ap = findXMLAtt(ccd, "Sensor");
01335   if (ap)
01336   {
01337     strncpy (cam->m_Sensor, valuXMLAtt(ap), 255);
01338     IDLog("Sensor: %s\n", cam->m_Sensor);
01339   }
01340   
01341   // Color
01342   ele = findXMLEle(ccd, "Color");
01343   if (ele)
01344   {
01345     if (!strcmp(pcdataXMLEle(ele), "True"))
01346     {
01347       cam->m_Color = true;
01348       IDLog("Color: true\n");
01349     }
01350     else
01351     { 
01352       cam->m_Color = false;
01353       IDLog("Color: false\n");
01354     }
01355   }
01356   
01357   // Noise
01358   ele = findXMLEle(ccd, "Noise");
01359   if (ele)
01360     cam->m_Noise = atof( pcdataXMLEle(ele) );
01361   
01362   // Noise
01363   ele = findXMLEle(ccd, "Gain");
01364   if (ele)
01365     cam->m_Gain = atof( pcdataXMLEle(ele) );
01366   
01367   // Pixel X Size
01368   ele = findXMLEle(ccd, "PixelXSize");
01369   if (ele)
01370   {
01371     cam->m_PixelXSize = atof( pcdataXMLEle(ele) );
01372     IDLog("Pixel X Size: %g\n", cam->m_PixelXSize);
01373   }
01374   
01375   // Pixel Y Size
01376   ele = findXMLEle(ccd, "PixelYSize");
01377   if (ele)
01378   {
01379     cam->m_PixelYSize = atof( pcdataXMLEle(ele) );
01380     IDLog("Pixel Y Size: %g\n", cam->m_PixelYSize);
01381   }
01382   
01383   // Log all values
01384   IDLog("Cam Row: %d - Cam Cols: %d - PP_Repeat %d\n",cam->m_Rows,  cam->m_Columns, cam->m_PPRepeat);
01385   IDLog("High_Priority %s - Data_Bits %d - Sensor %s\n", cam->m_HighPriority ? "true" : "false", cam->m_DataBits, (cam->m_SensorType == Camera_SensorType_CCD) ? "CCD" : "CMOS");
01386   IDLog("Max X Bin: %d - Max Y Bin: %d - Guider Relays: %s\n", cam->m_MaxBinX, cam->m_MaxBinY, cam->m_GuiderRelays ? "true" : "false");
01387   IDLog("BIC: %d - BIR: %d - SKIPC: %d - SKIPR: %d - ImgRows: %d - ImgCols %d\n", cam->m_BIC, cam->m_BIR, cam->m_SkipC, cam->m_SkipR, cam->m_ImgRows, cam->m_ImgColumns);
01388   IDLog("HFlush: %d - VFlush: %d - Control: %s - Cal: %d - Scale: %g\n", cam->m_HFlush, cam->m_VFlush, cam->m_TempControl ? "true" : "false", cam->m_TempCalibration, cam->m_TempScale); 
01389   
01390   delLilXML(XMLParser);
01391   
01392   return true;
01393 }
01394 
01395 /* isCCDConnected: return 1 if we have a connection, 0 otherwise */
01396 int ApogeeCam::isCCDConnected(void)
01397 {
01398   return ((PowerS[0].s == ISS_ON) ? 1 : 0);
01399 }
01400 
01401 FITS_HDU_LIST * ApogeeCam::create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp)
01402 {
01403  
01404  FITS_HDU_LIST *hdulist;
01405  
01406  char temp_s[FITS_CARD_SIZE], expose_s[FITS_CARD_SIZE], binning_s[FITS_CARD_SIZE], frame_s[FITS_CARD_SIZE], pixel_s[FITS_CARD_SIZE];
01407  char obsDate[FITS_CARD_SIZE];
01408  
01409  snprintf(obsDate, FITS_CARD_SIZE, "DATE-OBS= '%s' /Observation Date UTC", timestamp());
01410  
01411  hdulist = fits_add_hdu (ofp);
01412  if (hdulist == NULL) return (NULL);
01413 
01414  hdulist->used.simple = 1;
01415  hdulist->bitpix = 16;
01416  hdulist->naxis = 2;
01417  hdulist->naxisn[0] = width;
01418  hdulist->naxisn[1] = height;
01419  hdulist->naxisn[2] = bpp;
01420  hdulist->used.datamin = 1;
01421  hdulist->datamin = min();
01422  hdulist->used.datamax = 1;
01423  hdulist->datamax = max();
01424  hdulist->used.bzero = 1;
01425  hdulist->bzero = 0.0;
01426  hdulist->used.bscale = 1;
01427  hdulist->bscale = 1.0;
01428  
01429  snprintf(temp_s, FITS_CARD_SIZE, "CCD-TEMP= %g / degrees celcius", APGFrame.temperature);
01430  snprintf(expose_s, FITS_CARD_SIZE, "EXPOSURE= %d / milliseconds", APGFrame.expose);
01431  snprintf(binning_s, FITS_CARD_SIZE, "BINNING = '(%d x %d)'", APGFrame.binX, APGFrame.binY);
01432  snprintf(pixel_s, FITS_CARD_SIZE, "PIX-SIZ = '%0.f x %0.f microns square'", cam->m_PixelXSize, cam->m_PixelYSize);
01433  switch (APGFrame.frameType)
01434   {
01435     case LIGHT_FRAME:
01436         strcpy(frame_s, "FRAME   = 'Light'");
01437     break;
01438     case BIAS_FRAME:
01439         strcpy(frame_s, "FRAME   = 'Bias'");
01440     break;
01441     case FLAT_FRAME:
01442         strcpy(frame_s, "FRAME   = 'Flat Field'");
01443     break;
01444     case DARK_FRAME:
01445         strcpy(frame_s, "FRAME   = 'Dark'");
01446     break;
01447   }
01448  
01449  fits_add_card (hdulist, frame_s);   
01450  fits_add_card (hdulist, temp_s);
01451  fits_add_card (hdulist, expose_s);
01452  fits_add_card (hdulist, pixel_s);
01453  fits_add_card (hdulist, "INSTRUME= 'Apogee CCD'");
01454  fits_add_card (hdulist, obsDate);
01455   
01456  return (hdulist);
01457 }
01458 
01459 // Convert a string to a decimal or hexadecimal integer
01460 // Code taken from Dave Mills Apogee driver
01461 unsigned short ApogeeCam::hextoi(char *instr)
01462 {
01463   unsigned short val, tot = 0;
01464   bool IsHEX = false;
01465 
01466   long n = strlen( instr );
01467   if ( n > 1 )
01468   { // Look for hex format e.g. 8Fh, A3H or 0x5D
01469     if ( instr[ n - 1 ] == 'h' || instr[ n - 1 ] == 'H' )
01470       IsHEX = true;
01471     else if ( *instr == '0' && *(instr+1) == 'x' )
01472     {
01473       IsHEX = true;
01474       instr += 2;
01475     }
01476   }
01477 
01478   if ( IsHEX )
01479   {
01480     while (instr && *instr && isxdigit(*instr))
01481     {
01482       val = *instr++ - '0';
01483       if (9 < val)
01484     val -= 7;
01485       tot <<= 4;
01486       tot |= (val & 0x0f);
01487     }
01488   }
01489   else
01490     tot = atoi( instr );
01491 
01492   return tot;
01493 }
01494 
01495 double ApogeeCam::min()
01496 {
01497   double lmin = APGFrame.img[0];
01498   int ind=0, i, j;
01499   
01500   for (i= 0; i < APGFrame.height ; i++)
01501     for (j= 0; j < APGFrame.width; j++)
01502     {
01503        ind = (i * APGFrame.width) + j;
01504        if (APGFrame.img[ind] < lmin) lmin = APGFrame.img[ind];
01505     }
01506     
01507     return lmin;
01508 }
01509 
01510 double ApogeeCam::max()
01511 {
01512   double lmax = APGFrame.img[0];
01513   int ind=0, i, j;
01514   
01515    for (i= 0; i < APGFrame.height ; i++)
01516     for (j= 0; j < APGFrame.width; j++)
01517     {
01518       ind = (i * APGFrame.width) + j;
01519        if (APGFrame.img[ind] > lmax) lmax = APGFrame.img[ind];
01520     }
01521     
01522     return lmax;
01523 }
01524 

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