/* Heavily modified from 'camtest' -- 30.8.98, C. Titus Brown */ /* apsunkx4k **TEMPORARY** solar observation program using Apogee camera. This version for Apogee KX-4 for H-alpha full disk */ /* Modifications: 25-Aug-1999 JRV Modified from 'moonglow' by C. Titus Brown 21-Sep-1999 JRV Got timed mode to work. Still no LBC. 22-Sep-1999 JRV Add LBC, change FITS routines to BBSO standard. Change file naming to new standard (like SOHO). 24-Sep-1999 JRV Copied from apsun.c (version for KX-260 camera). Added synoptic commands and continuous mode. 08-Nov-1999 JRV Remove serial, LBC (not needed for H-alpha). 22-Nov-1999 JRV Modify image size for KX-4. 07-Dec-1999 JRV Some bug fixes. Really do need continuous mode. Change synoptic commands. 08-Dec-1999 JRV Debug CCD temperature control. Change synoptic dir. 12-Jan-2000 JRV Invert camera image before saving. 13-Jan-2000 JRV Small modifications to control logic. 18-Jan-2000 JRV Bug fixes to keyboard buffer. 11-Apr-2000 JRV Allow eight positions for flat field sequence. 11-May-2000 JRV Modify file names, FITS header information. 09-Jun-2000 JRV apsunkx4k slightly modified version for Kanzelhoehe. 27-Jul-2000 JRV Slight change to file names. */ #define BASE_SAVE_DIR "/data/daytime" #define SYNOP_SAVE_DIR "/data/daytime/synoptic" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* POSIX terminal control definitions */ #include "telenv.h" #include "ccdcamera.h" #include "fitsionew.h" static char *months[12] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; /* A static variable for holding the line. */ static char *line_read = (char *)NULL; char * rl_gets(); /* TELHOME driver path */ static char dev[] = "dev/ccdcamera"; static CCDExpoParams cep; /* persistent exposure info */ void do_command(char *buf); static void perrno (char *lbl); static void ax_writeFits (char * name, CCDExpoParams *cep, char *pix, int camtemp, int filter, int exptype, struct tm *snaptime); static void take_image(int length, int camfd, char * filename, int filter, int camtemp, int exptype, int savimg, int tstimg); static void take_data(int filter, int type, int close_shutter); void countdown(int); int report_temperature(char * status); void turn_off_cooler(); void set_cooler(); void handle_ctrlc(int); static int interrupt_recd = 0; /* this is based on OSL CCD code */ typedef struct { char observer[4]; char objcom[48]; char wavlen[9]; char telescope[9]; char fnprefix[6]; char sitenam[5]; int runflag; int seeing; int intervaltime; /* interval time */ int exptime; /* exposure time, milliseconds */ int telpos[2]; /* X,Y telescope position */ int objint; /* integer version of region number */ float ccdtemp; /* temperature of CCD camera (C) */ } param_st; void pixel_fiddle(unsigned short *pix, CCDExpoParams *cep); void invert_cam_image(unsigned short *pix, CCDExpoParams *cep); /* camera FD */ int camfd; /* A few global variables (ick!) for the image numbering/naming stuff */ param_st obsparams; char dirname[180]; char syndirname[180]; char datestring[20]; int itel; int exitflag = 0; /* Exposure times */ int exposure_time = 30; /* milliseconds */ int interval_time = 60; /* seconds */ int runflag = 0; /* save pictures in timed mode */ int contflag = 0; /* run continuous mode */ int syncounter = 0; /* synoptic file counter */ int cont_interval = 6; /* interval time for continuous mode */ #define BS 1 #define FD 2 #define BF 4 #define FF 5 #define OPEN 0 #define CLOSED 1 int main (int ac, char *av[]) { char buf2[1024]; char *imagebuf; int nbytes; int pid; time_t thetime; time_t interval_start; struct tm * snaptime; char * basedir = BASE_SAVE_DIR; char * synbase = SYNOP_SAVE_DIR; char cwd[180]; char name[64]; int test, short_year; fd_set watchset; fd_set inset; /* updated by select() */ struct timeval tv; /* used for read timeout */ /* Initialize dirname & datestring */ thetime = time(0L); interval_start = thetime; snaptime = gmtime(&thetime); short_year = snaptime->tm_year; short_year = short_year % 100; sprintf(datestring, "%02d%s%02d", short_year, months[snaptime->tm_mon], snaptime->tm_mday); sprintf(dirname, "%s/%s", basedir, datestring); /* sprintf(syndirname, "%s/%s", synbase, datestring); */ strcpy(syndirname, synbase); /* don't use date with synoptic dir. */ /* set defaults for H alpha line on Singer telescope */ strcpy(obsparams.fnprefix, "halph"); strcpy(obsparams.observer, "XXX"); obsparams.telpos[0] = 0; obsparams.telpos[1] = 0; strcpy(obsparams.sitenam, "kanz"); strcpy(obsparams.telescope, "PATROL"); strcpy(obsparams.wavlen, "HALPHA"); strcpy(obsparams.objcom, ""); itel = 10; obsparams.objint = 0; /* Other stuff */ signal(SIGINT, handle_ctrlc); rl_bind_key ('\t', rl_insert); /* open the driver */ camfd = telopen (dev, O_RDWR); if (camfd < 0) { perror (dev); printf("(Running in \"test\" mode.)\n"); } else { /* print the ID string */ if (ioctl (camfd, CCD_GET_ID, buf2) < 0) { printf ("Can not get ID: %s\n", strerror (errno)); exit(1); } printf ("ID: %s\n", buf2); /* set default exposure info */ if (ioctl (camfd, CCD_GET_SIZE, &cep) < 0) { printf ("Can not get chip size: %s\n", strerror (errno)); exit(1); } /* set defaults for KX-4 camera */ cep.sw = 2032; cep.sh = 2032; cep.bx = cep.by = 1; cep.sx = cep.sy = 0; cep.duration = 30; cep.shutter = 1; exposure_time = cep.duration; /* get max image buffer */ nbytes = cep.sw * cep.sh * 2; imagebuf = malloc (nbytes); if (!imagebuf) { printf ("No memory for %dx%d array\n", cep.sw, cep.sh); exit(1); } printf ("Max size: %d W x %d H\n", cep.sw, cep.sh); } getcwd(cwd, sizeof(cwd)); test = chdir(dirname); if (test != 0) { printf("Directory does not exist -- creating %s.\n", dirname); test = mkdir(dirname, 0777); if (test != 0) { printf("Couldn't create %s - exiting.\n", dirname); exit(-1); } } chdir(cwd); printf("Starting 'camera' program...\n"); pid = fork(); if (pid == 0) { char *args[] = { "/usr/local/telescope/GUI/camera/camera", 0 }; setpgrp(); chdir("/tmp"); execvp("/usr/local/telescope/GUI/camera/camera", args); } /* set up fd structure for select() */ FD_ZERO(&watchset); FD_SET(STDIN_FILENO, &watchset); /* this sets up readline for input */ rl_callback_handler_install("> ", &do_command); /* this starts the event loop */ while (1) { /* sleep some time here */ /* now check for incoming characters from the keyboard */ tv.tv_sec = 0; tv.tv_usec = 20000; /* 20 millisecond timeout */ inset = watchset; if (select((int) STDIN_FILENO + 1, &inset, NULL, NULL, &tv) < 0) { perror("select error"); return 1; } /* if there is a character, use the readline callback function */ if (FD_ISSET(STDIN_FILENO, &inset)) rl_callback_read_char(); /* check for time for exposure */ if (runflag) { /* if it's time, take an exposure */ if ((int) difftime( time(NULL), interval_start) >= interval_time) { /* take picture */ if (interval_time < 7) { printf("Interval time too short.\n"); runflag = 0; } else { interval_start = time(NULL); take_data(0,1,OPEN); } } } else if (contflag) { /* if not running in timed mode, and continuous flag is on */ /* if it's time, take an exposure */ if ((int) difftime( time(NULL), interval_start) >= cont_interval) { sprintf(name, "/tmp/apsun-cont-image.fts"); interval_start = time(NULL); take_image(exposure_time, camfd, name, -1, report_temperature(NULL),-1, 1, 1); } } if (exitflag == 1) { rl_callback_handler_remove(); kill(pid, 9); system("/bin/rm -f /tmp/apsun-cont-image*"); system("/bin/rm -f /tmp/apsuntmp-test*"); return (0); } } } /* function to process user input string */ void do_command(char *buf) { char name[64]; char synfn[64]; char synstr[5]; char ccd_status[40]; char cwd[180]; int test; char newchar = 'X'; time_t thetime; struct tm * snaptime; static int test_name_n = 1; /* test image number */ time_t interval_start; int i, j, ll, mm; static int space = 0; /* process user input */ while(isspace(buf[strlen(buf) - 1])) { buf[strlen(buf) - 1] = 0; } /* clean up the input: lower case, replace whitespace with ' '. */ for(i = 0; i < strlen(buf); i++) { if (isspace(buf[i])) { if (space) { /* do nothing if we're going through ws */ ; } else { space = 1; buf[i] = ' '; } } else { space = 0; /* reset */ buf[i] = tolower(buf[i]); } } /* printf("Input is: \"%s\"\n", buf); */ if (!strncmp(buf, "do_run", strlen("do_run"))) { /* run camera (interval) */ /* take_data(0,1,OPEN); */ interval_start = time(NULL); contflag = 0; runflag = 1; } else if (!strncmp(buf, "do_cont", strlen("do_cont"))) { contflag = 1; runflag = 0; interval_start = time(NULL); } else if (!strncmp(buf, "exit", strlen("exit"))) { /* quit the program */ exitflag = 1; } else if (!strncmp(buf, "stop_run", strlen("stop_run"))) { /* stop the camera now */ runflag = 0; } else if (!strncmp(buf,"q", strlen("q"))) { contflag = 0; } else if (!strncmp(buf, "test", strlen("test"))) { i = strlen("test"); if (i == strlen(buf)) { printf("Please specify exposure length (ms)!\n"); } else { int length; i++; length = atoi(buf + i); if (length < 10 || length > 120000) { printf("%d ms is an invalid time. Choose again!\n", length); } else { sprintf (name, "/tmp/apsuntmp-test-image%03d.fts", test_name_n++); take_image(length, camfd, name, -1, report_temperature(NULL), -1, 1, 1); } } } else if (!strncmp(buf, "synoptic", strlen("synoptic"))) { /* take synoptic frames, file names like: hb08d, hb08l, hb08l01, hb08l02, etc. */ /* make sure correct synoptic directory exists */ getcwd(cwd, sizeof(cwd)); test = chdir(syndirname); if (test != 0) { printf("Directory does not exist -- creating %s.\n", syndirname); test = mkdir(syndirname, 0777); if (test != 0) { printf("Couldn't create %s - exiting.\n", syndirname); exit(-1); } } chdir(cwd); /* set up base file name for synoptic images */ thetime = time(0L); snaptime = gmtime(&thetime); sprintf(synstr,"h%1x%02d",snaptime->tm_mon + 1, snaptime->tm_mday); fseek(stdin, 0L, SEEK_END); /* flush standard input */ strcpy(buf,""); /* flush readline's buffer too */ printf("Type 'e' to not take the image and return to the prompt.\n"); if (syncounter == 0) { /* take center frame */ sprintf(synfn,"%s/%sl.fts",syndirname,synstr); printf("ready to take %s: ", synfn); newchar = getchar(); if (newchar != 'E' && newchar != 'e') { take_image(exposure_time,camfd,synfn,-1, report_temperature(ccd_status),-1,1,1); } else { syncounter--; goto synbreak; } fseek(stdin, 0L, SEEK_END); /* flush standard input */ strcpy(buf,""); /* flush readline's buffer too */ printf("image OK? "); newchar = getchar(); if (newchar == 'N' || newchar == 'n') { printf("Image rejected, retake\n"); syncounter--; goto synbreak; } else { printf("Image accepted\n"); } } else if (syncounter == 1) { /* take dark frame */ sprintf(synfn,"%s/%sd.fts",syndirname,synstr); printf("ready to take %s: ", synfn); getchar(); if (newchar != 'E' && newchar != 'e') { cep.shutter = 0; take_image(exposure_time,camfd,synfn,-1, report_temperature(ccd_status),3,1,1); cep.shutter = 1; } else { syncounter--; goto synbreak; } } else if (syncounter > 1 && syncounter < 10) { /* take off-center frames for flat field */ sprintf(synfn,"%s/%sl%02d.fts",syndirname,synstr, syncounter - 1); printf("ready to take %s: ", synfn); getchar(); if (newchar != 'E' && newchar != 'e') { take_image(exposure_time,camfd,synfn,-1, report_temperature(ccd_status),-1,1,1); } else { syncounter--; goto synbreak; } fseek(stdin, 0L, SEEK_END); /* flush standard input */ strcpy(buf,""); /* flush readline's buffer too */ printf("image OK? "); newchar = getchar(); if (newchar == 'N' || newchar == 'n') { printf("Image rejected, retake\n"); syncounter--; goto synbreak; } else { printf("Image accepted\n"); } } else if (syncounter >= 10) { printf("I think the synoptic data have already been taken.\n"); printf("Do you want to retake the synoptic data, overwriting\n"); printf("the old data?"); newchar = getchar(); if (newchar != 'n' && newchar != 'N') { syncounter = -1; printf("Ready to retake synoptic data.\n"); } else { printf("Nothing happens.\n"); goto synbreak; } } synbreak: printf("\n"); syncounter++; } else if (!strncmp(buf, "retake", strlen("retake"))) { fseek(stdin, 0L, SEEK_END); /* flush standard input */ strcpy(buf,""); /* flush readline's buffer too */ printf("Do you want to retake the synoptic data, overwriting\n"); printf("the old data?"); newchar = getchar(); if (newchar != 'n' && newchar != 'N') { syncounter = 0; printf("Ready to retake synoptic data.\n"); } else { printf("Nothing happens.\n"); } } else if (!strncmp(buf, "flat", strlen("flat"))) { take_data(0, 1, OPEN); take_data(0, 1, CLOSED); } else if (!strncmp(buf, "dc", strlen("dc"))) { take_data(0, 1, CLOSED); } else if (!strncmp(buf, "single", strlen("single"))) { take_data(0,1, OPEN); } else if (!strncmp(buf, "temp", strlen("temp"))) { int temp; int old_temp; char ccd_status[40]; old_temp = report_temperature(ccd_status); i = strlen("temp") + 1; temp = atoi(buf + i); if (strlen(buf) <= i) { printf("Please specify a temperature between -10 and 20.\n"); } else if ((temp < -10 || temp > 20) && temp != -1000 ) { printf("Invalid temperature! (%d)\n", temp); } else if (((temp - old_temp) > 6 || (old_temp -temp) > 6) && temp != -1000) { printf("Temperature step too high - <= 5 degree once!\n"); } else if (temp != -1000) { printf("setting temperature to %d\n", temp); set_cooler(temp); } else { /* temp == -1000 */ turn_off_cooler(); printf("CCD cooler off.\n"); } } else if (!strncmp(buf, "auto_temp", strlen("auto_temp"))) { int temp; int old_temp; int del_temp; int new_temp; char ccd_status[40]; del_temp=5; printf("Starting auto_temp mode\n"); old_temp = report_temperature(ccd_status); printf("The temperature now is %d\n", old_temp); i = strlen("auto_temp") + 1; temp = atoi(buf + i); if (strlen(buf) <= i) { printf("Please specify a temperature between -10 and 20.\n"); } else if ((temp < -10 || temp > 20) && temp != -1000 ) { printf("Invalid temperature! (%d)\n", temp); } else if (temp != -1000) { printf("Setting CCD temperature automatically.\n"); printf("Please wait until new temperature is reached.\n"); printf("Press Ctrl-C to interrupt.\n"); if ((temp - old_temp) > 0 ) {del_temp = 4; } if ((temp - old_temp) < 0 ) {del_temp = -4; } for (j = 1; j <= (temp - old_temp)/del_temp && !interrupt_recd; j++) { new_temp = old_temp + del_temp*j; printf("setting temperature to %d\n", new_temp); set_cooler(new_temp); sleep(300); new_temp=report_temperature(ccd_status); printf("\tCCD temperature & status: %d Celsius (%s)\n", new_temp, ccd_status); } } else { /* temp == -1000 */ turn_off_cooler(); printf("CCD cooler off.\n"); } } else if (!strncmp(buf, "set", strlen("set"))) { i = strlen("set") + 1; if (!strncmp(buf + i, "exp", strlen("exp"))) { int tmp; tmp = atoi(buf + i + strlen("exp") + 1); if (tmp > 20) { printf("setting exposure time to %d\n", tmp); exposure_time = tmp; } else { printf("invalid number: got %d\n", tmp); } } else if (!strncmp(buf + i, "interval", strlen("interval"))) { int tmp; tmp = atoi(buf + i + strlen("interval") + 1); if (tmp > 1) { printf("setting interval time to %d\n", tmp); interval_time = tmp; } else { printf("invalid number: got %d\n", tmp); } } else if (!strncmp(buf + i, "lambda", strlen("lambda"))) { /* set wavelength */ ll = i + strlen("lambda") + 1; for (mm = ll; mm < ll + 6; mm++) { if (buf[mm] == '\0') break; buf[mm] = toupper(buf[mm]); } strncpy(obsparams.wavlen, buf + i + strlen("lambda") + 1, 6); } else if (!strncmp(buf + i, "fnprefix", strlen("fnprefix"))) { /* set file name prefix */ strncpy(obsparams.fnprefix, buf + i + strlen("fnprefix") + 1, 5); } else if (!strncmp(buf + i, "observer", strlen("observer"))) { /* set observer name */ ll = i + strlen("observer") + 1; for (mm = ll; mm < ll + 3; mm++) { if (buf[mm] == '\0') break; buf[mm] = toupper(buf[mm]); } strncpy(obsparams.observer, buf + i + strlen("observer") + 1, 3); } else if (!strncmp(buf + i, "seeing", strlen("seeing"))) { /* set seeing value */ int tmp; tmp = atoi(buf + i + strlen("seeing") + 1); if (tmp < 0 || tmp > 4) { printf("invalid seeing value: got %d\n", tmp); } else { obsparams.seeing = tmp; } } } else if (!strncmp(buf, "status", strlen("status"))) { char ccd_status[40]; int temp; printf("Info:\n\n\texp = %d\n\tinterval = %d\n", exposure_time, interval_time); printf("\tdirname = %s\n", dirname); printf("\tdatestring = %s\n\n", datestring); printf("\trun state %d (1 = on, 0 = off)\n", runflag); printf("\tcontinuous state %d (1 = on, 0 = off)\n", contflag); temp = report_temperature(ccd_status); printf("\tCCD temperature: %d C Cooler: %s\n", temp, ccd_status); printf("\ttelescope: %s\n", obsparams.telescope); /* printf("\tX: %d Y: %d\n", obsparams.telpos[0], obsparams.telpos[1]); */ printf("\tObserver: %s Wavelength: %s Prefix: %s\n", obsparams.observer, obsparams.wavlen, obsparams.fnprefix); } else if (!strncmp(buf, "?", strlen("?")) || strlen(buf) < 1) { printf("\nList of commands: \n\n"); printf("\texit\t stop program \t\tstatus\t print status info\n"); printf("\tset\texp ee\t\t set exposure time to ee (msec)\n"); printf("\t\tinterval ii\t set interval time to ii(sec)\n"); printf("\t\tlambda wwwww\t set wavelength to wwwww\n"); printf("\t\tobserver ooo\t set observer name to ooo\n"); printf("\t\tseeing n\t set seeing to n\n"); printf("\t\tfnprefix ppppp\t set file name prefix to ppppp\n"); printf("\ttest ee\t\t take a test (unsaved) image, exp time ee\n"); printf("\tauto_temp tt\t start auto cooler temp control to tt\n"); printf("\ttemp tt\t\t set cooler temperature to tt (-1000 == off)\n"); printf("\tsingle\t\t take single picture\n"); printf("\tsynoptic\t take a synoptic image\n"); printf("\tretake\t prepare to retake synoptic data\n"); printf("\tdc\t\t take picture with shutter closed\n"); printf("\tdo_run \t\t run camera (interval)\n"); printf("\tstop_run \t stop running camera\n"); printf("\tdo_cont \t run camera continuously\n"); printf("\tq \t\t stop continuous mode\n"); printf("\n"); } else if (!strncmp(buf, "cooler", strlen("cooler"))) { printf("cooler command does nothing!\n"); } } static void take_image(int length, int camfd, char * filename, int filter, int camtemp, int exptype, int savimg, int tstimg) { struct timeval tv, tv2, select_tv; time_t thetime; struct tm * snaptime; fd_set rfd; int nbytes; int n; char *imagebuf; char name[80]; double dt; nbytes = cep.sw * cep.sh * 2; imagebuf = malloc (nbytes); if (length < 20 || length > 120000) { printf("%d ms is an invalid time. Choose again!\n", length); } else { cep.duration = length; if (ioctl(camfd, CCD_SET_EXPO, &cep) < 0) { perrno("d"); } else { int r; fcntl (camfd, F_SETFL, O_NONBLOCK); nbytes = cep.sw * cep.sh * 2; /* tell the camera to take a picture: */ if (cep.duration / 1000 > 1) { printf("\n*click*\nWaiting for camera: %3d", cep.duration / 1000); fflush(stdout); } else { printf("\n*click*"); fflush(stdout); } thetime = time(0L); snaptime = gmtime(&thetime); read (camfd, imagebuf, nbytes); gettimeofday (&tv, NULL); while(1) { FD_ZERO (&rfd); FD_SET (camfd, &rfd); select_tv.tv_sec = 1; select_tv.tv_usec = 0; r = select (camfd+1, &rfd, NULL, NULL, &select_tv); if (r < 0) { perror("S"); } else { int t; gettimeofday (&tv2, NULL); t = cep.duration / 1000 - (int)(tv2.tv_sec - tv.tv_sec); if (t > 0) { printf("%c%c%c%3d", 8, 8, 8, t); fflush(stdout); } else { printf("%c%c%c\nCamera done.\n", 8, 8, 8); fflush(stdout); } } if (FD_ISSET(camfd, &rfd)) { printf("\nReading image... please wait.\n"); break; } } gettimeofday (&tv, NULL); n = read (camfd, imagebuf, nbytes); gettimeofday (&tv2, NULL); if (n < 0) perrno ("R"); else if (n != nbytes) printf ("Expected %d bytes but read %d\n", nbytes, n); else { if (savimg) { if (!tstimg) { /* generate file name here */ sprintf(name, "%s/%s_%s_fi_%04d%02d%02d_%02d%02d%02d.fts", dirname, obsparams.sitenam, obsparams.fnprefix, snaptime->tm_year + 1900, snaptime->tm_mon + 1, snaptime->tm_mday, snaptime->tm_hour, snaptime->tm_min, snaptime->tm_sec); } else { strcpy(name, filename); } ax_writeFits (name, &cep, imagebuf, camtemp, filter, exptype, snaptime); } dt = tv2.tv_sec - tv.tv_sec + (tv2.tv_usec - tv.tv_usec)/1e6 - cep.duration/1e3; printf ("%d pixels in %g secs <=> %g pix/sec\n", nbytes/2, dt, nbytes/2/dt); } } } free(imagebuf); } static void perrno(char *lbl) { printf (" %3.3s: %2d: %s\n", lbl, errno, strerror(errno)); } static void ax_writeFits (char * name, CCDExpoParams *cep, char *pix, int camtemp, int filter, int moontype, struct tm * snaptime) { int fd; char (*headbuf)[81] = NULL; int bitpix, nax, naxes[2], ltype, iline; char object[9], obscom[48], timecom[48]; char sfname[34]; char *slashpos; ltype = 1; nax = 2; bitpix = 16; naxes[0] = cep->sw; naxes[1] = cep->sh; strcpy(obscom, ""); /* set up FITS header information */ headbuf = (char (*)[81]) malloc (36 * 81); /* note this allows only a one block (36 line) FITS header */ iline = fits_head_encode(headbuf, ltype, bitpix, nax, naxes, 32768.0, 1.0, ""); /* sprintf(object,"%-5d",obsparams.objint); */ sprintf(object,"SUN"); sprintf(timecom, "START OF %d MS EXPOSURE", cep->duration); iline = fits_head_kanz(headbuf, iline, object, obsparams.objcom, 'H', obscom, obsparams.seeing, obsparams.telpos, *snaptime, timecom, obsparams.telescope, obsparams.wavlen, "", obsparams.observer); /* CCD-specific header information */ flini0(headbuf[iline++], "EXPTIME", (cep->duration * 0.001), "SECONDS"); flini0(headbuf[iline++], "TEC_TEMP", camtemp, "DEGREES C"); /* use file name only, not directory name */ slashpos = strrchr(name, '/'); if (slashpos != NULL) { strcpy(sfname, (slashpos + 1)); } else { strcpy(sfname, name); } sprintf (headbuf[iline++], "COMMENT ORIGIN FILE NAME %-53s", sfname); sprintf (headbuf[iline++], "%-80s", "END"); /* write FITS file */ invert_cam_image((unsigned short *) pix, cep); pixel_fiddle((unsigned short *) pix, cep); if (fits_write(name, headbuf, iline, (void *) pix, naxes, bitpix) < 0) { printf("Error in fits_write\n"); } /* send to camera, if he's listening */ fd = telopen ("comm/CameraFilename", O_WRONLY|O_NONBLOCK); if (fd >= 0) { struct stat st; if (fstat (fd, &st) == 0 && S_ISFIFO(st.st_mode)) { char fullpath[1024]; if (name[0] != '/') { getcwd (fullpath, sizeof(fullpath)); strcat (fullpath, "/"); strcat (fullpath, name); write (fd, fullpath, strlen(fullpath)); } else { write (fd, name, strlen(name)); } } close (fd); } } /* take_data sets up some parameters for the FITS header then takes an image and saves it to disk */ static void take_data(int filter, int type, int close_shutter) { /* type = 1 for single frame, 2 for frame selection (not enabled yet) */ char name[64]; int exposure = -1; char descriptor[3]; int exptype = -1; int ccd_temp; signal(SIGINT, SIG_IGN); ccd_temp = report_temperature(NULL); strcpy(descriptor, "EX"); if (type == 1) { exposure = exposure_time; exptype = 1; } else if (type == 2) { printf("frame selection not operating yet\n"); exposure = exposure_time; exptype = 2; } if (close_shutter) { strcpy(descriptor, "DC"); exposure = exposure_time; exptype = 3; cep.shutter = 0; } /* sprintf(name, "%s/%s%03d.fts", dirname, datestring, data_image_n); printf("\ntaking image #%d, exposure time %d (%s)\n", data_image_n, exposure, descriptor); */ sprintf(name, "junk.fts"); printf("\ntaking image, exposure time %d\n", exposure); take_image(exposure, camfd, name, filter, ccd_temp, exptype, 1, 0); /* data_image_n++; */ cep.shutter = 1; signal(SIGINT, handle_ctrlc); } void handle_ctrlc(int sig) { interrupt_recd = 1; printf("\n\nCTRL-C received - sending interrupt.\n\n"); signal(SIGINT, handle_ctrlc); } /* Stolen straight from the Readline man pages. --CTB */ /* Read a string, and return a pointer to it. Returns NULL on EOF. */ char * rl_gets () { /* If the buffer has already been allocated, return the memory to the free pool. */ if (line_read) { free (line_read); line_read = (char *)NULL; } /* Get a line from the user. */ line_read = readline ("> "); /* If the line has any text in it, save it on the history. */ if (line_read && *line_read) { add_history (line_read); } return (line_read); } void countdown(int n) { int i; for (i = 0; i < n && !interrupt_recd; i++) { printf("%c%c%c%3d", 8, 8, 8, n - i); fflush(stdout); sleep(1); } printf("%c%c%c \n", 8, 8, 8); } void set_cooler(int celsius) { CCDTempInfo tinfo; tinfo.s = CCDTS_SET; tinfo.t = celsius; if (ioctl(camfd, CCD_SET_TEMP, &tinfo) < 0) { printf("Error setting temperature.\n"); } } void turn_off_cooler() { CCDTempInfo tinfo; tinfo.s = CCDTS_OFF; if (ioctl(camfd, CCD_SET_TEMP, &tinfo) < 0) { printf("Error turning cooler off.\n"); } } int report_temperature(char * status) { CCDTempInfo tinfo; if (ioctl(camfd, CCD_GET_TEMP, &tinfo) < 0) { printf("Error getting temperature.\n"); return -1000; } if (status != NULL) { switch (tinfo.s) { case CCDTS_AT: strcpy(status, "AtTarg"); break; case CCDTS_UNDER: strcpy(status, "Targ"); break; case CCDTS_OFF: strcpy(status, "Off"); break; case CCDTS_RDN: strcpy(status, "Ramping"); break; case CCDTS_RUP: strcpy(status, "ToAmb"); break; case CCDTS_STUCK: strcpy(status, "Floor"); break; case CCDTS_MAX: strcpy(status, "Ceiling"); break; case CCDTS_AMB: strcpy(status, "AtAmb"); break; default: strcpy(status, "Error"); break; } } return tinfo.t; } void pixel_fiddle(unsigned short *pix, CCDExpoParams *cep) { unsigned short *thispix; int npix; unsigned short *tmppix; int bigpix; thispix = pix; npix = cep->sh * cep->sw; while (--npix >= 0) { tmppix = thispix++; bigpix = (int) (*tmppix) - 32768; *tmppix = bigpix; } } void invert_cam_image(unsigned short *pix, CCDExpoParams *cep) { int halfrows; int i, j; int nrows, ncols, rowmax; unsigned short tmppix; nrows = cep->sh; ncols = cep->sw; rowmax = nrows - 1; halfrows = nrows / 2; for (i = 0; i < halfrows; i++) { /* read row[i] to tmprow */ for (j = 0; j < ncols; j++) { tmppix = pix[(i * ncols) + j]; /* read row[cep->sh - i] to row[i] */ pix[(i * ncols) + j] = pix[((rowmax - i) * ncols) + j]; /* read tmprow to row[cep->sh - i] */ pix[((rowmax - i) * ncols) + j] = tmppix; } } }