mirror of
https://github.com/eddyem/apogee_control.git
synced 2025-12-06 10:45:20 +03:00
763 lines
25 KiB
C
763 lines
25 KiB
C
/*
|
||
* takepic.c
|
||
*
|
||
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program; if not, write to the Free Software
|
||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
* MA 02110-1301, USA.
|
||
*/
|
||
|
||
#include <dirent.h>
|
||
#include <float.h>
|
||
#include <linux/usbdevice_fs.h>
|
||
#include <locale.h>
|
||
#include <signal.h>
|
||
#include <sys/ioctl.h>
|
||
#include <usb.h>
|
||
|
||
#ifdef USE_BTA
|
||
#include "bta_print.h"
|
||
#endif
|
||
#include "camtools.h"
|
||
#include "defhdrs.h"
|
||
#ifdef IMAGEVIEW
|
||
#include "imageview.h"
|
||
#endif
|
||
#include "macros.h"
|
||
#include "takepic.h"
|
||
#include "usage.h"
|
||
|
||
|
||
#define BUFF_SIZ 4096
|
||
#define PROC_BASE "/proc"
|
||
|
||
#define TMBUFSIZ 40 // time string buffer length
|
||
|
||
static char *pidfilename = "/tmp/apogee_control.pid"; // pidfile
|
||
|
||
static char tm_buf[TMBUFSIZ]; // time string buffer
|
||
|
||
char *camera = NULL, *sensor = NULL, viewfield[80];
|
||
double pixX, pixY; // pixel size
|
||
|
||
int test_headers = 0; // don't even try to open camera device, just show FITS keys
|
||
|
||
double t_ext, t_int; // hot & cold side temperatures
|
||
time_t expStartsAt; // time of exposition start (time_t)
|
||
|
||
static int itime(){ // time in seconds to count intervals
|
||
struct timeval ct;
|
||
gettimeofday(&ct, NULL);
|
||
return (ct.tv_sec);
|
||
}
|
||
static int time0;
|
||
static int ltime(){ // time since last time0 reinitialising
|
||
return(itime()-time0);
|
||
}
|
||
|
||
// return string with current date/time
|
||
static size_t curtime(char *s_time){
|
||
time_t tm = time(NULL);
|
||
size_t s = strftime(s_time, TMBUFSIZ, "%d/%m/%Y,%H:%M:%S", localtime(&tm));
|
||
if(!s) info("curtime() error");
|
||
return s;
|
||
}
|
||
|
||
// find the first non-exists filename & put it into buff
|
||
static int check_filename(char *buff, char *outfile, char *ext){
|
||
struct stat filestat;
|
||
int num;
|
||
for(num = 1; num < 10000; num++){
|
||
if(snprintf(buff, BUFF_SIZ, "%s_%04d.%s", outfile, num, ext) < 1)
|
||
return 0;
|
||
if(stat(buff, &filestat)) // OK, file not exists
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static void reset_usb_port(int pid, int vid){
|
||
int fd, rc;
|
||
char buf[FILENAME_MAX*3], *d = NULL, *f = NULL;
|
||
struct usb_bus *bus;
|
||
struct usb_device *dev;
|
||
int found = 0;
|
||
usb_init();
|
||
usb_find_busses();
|
||
usb_find_devices();
|
||
for(bus = usb_busses; bus && !found; bus = bus->next) {
|
||
for(dev = bus->devices; dev && !found; dev = dev->next) {
|
||
if (dev->descriptor.idVendor == vid && dev->descriptor.idProduct == pid){
|
||
found = 1;
|
||
d = bus->dirname;
|
||
f = dev->filename;
|
||
}
|
||
}
|
||
}
|
||
if(!found){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
ERR(_("Device not found"));
|
||
return;
|
||
}
|
||
DBG("found camera device, reseting");
|
||
snprintf(buf, sizeof(buf), "/dev/bus/usb/%s/%s", d,f);
|
||
fd = open(buf, O_WRONLY);
|
||
if (fd < 0){
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %s: %s"
|
||
ERR(_("Can't open device file %s: %s"), buf, strerror(errno));
|
||
return;
|
||
}
|
||
info("Resetting USB device %s", buf);
|
||
rc = ioctl(fd, USBDEVFS_RESET, 0);
|
||
if (rc < 0) {
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ioctl"
|
||
perror(_("Error in ioctl"));
|
||
return;
|
||
}
|
||
close(fd);
|
||
}
|
||
|
||
// quit by signal
|
||
static void signals(int sig){
|
||
int u;
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.\n"
|
||
if(sig){
|
||
signal(sig, signals);
|
||
printf(_("Get signal %d, quit.\n"), sig);
|
||
}
|
||
u = unlink(pidfilename);
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PID-<2D><><EFBFBD><EFBFBD>"
|
||
if(u == -1) perror(_("Can't delete PIDfile"));
|
||
ApnGlueWheelClose();
|
||
DBG("wheel closed");
|
||
ApnGlueExpAbort(); // this function stubs all!
|
||
DBG("exp aborted");
|
||
ApnGlueClose();
|
||
DBG("device closed");
|
||
#ifdef IMAGEVIEW
|
||
clear_GL_context();
|
||
#endif
|
||
exit(sig);
|
||
}
|
||
|
||
static int sigcounter = 3;
|
||
static void cnt_signals(int sig){
|
||
--sigcounter;
|
||
if(sigcounter){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ctrl+C <20><><EFBFBD> %d <20><><EFBFBD>[<5B>], <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n"
|
||
printf(_("Press Ctrl+C %d time[s] more to interrupt reading\n"), sigcounter);
|
||
signal(SIGINT, cnt_signals);
|
||
}else{
|
||
signals(sig);
|
||
}
|
||
}
|
||
|
||
// Try to ignore all signals exept SIGINT, which is counted
|
||
static void ignore_signals(){
|
||
sigcounter = 3;
|
||
for(int _=0; _<256; _++)
|
||
signal(_, SIG_IGN);
|
||
signal(SIGINT, cnt_signals);
|
||
}
|
||
// We must take care about signals to avoid ctrl+C problems
|
||
static void catch_signals(){
|
||
for(int _=0; _<256; _++)
|
||
signal(_, SIG_IGN);
|
||
signal(SIGTERM, signals); // kill (-15) - quit
|
||
signal(SIGHUP, signals); // hup - quit
|
||
signal(SIGINT, signals); // ctrl+C - quit
|
||
signal(SIGQUIT, signals); // ctrl+\ - quit
|
||
//signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
|
||
}
|
||
/*
|
||
void restore_signals(){
|
||
sigcounter = 3;
|
||
for(int _=0; _<256; _++)
|
||
signal(_, SIG_DFL);
|
||
unlink(pidfilename);
|
||
}*/
|
||
|
||
// check for running process
|
||
static void check4running(){
|
||
// get process name from /proc
|
||
int readname(char *name, pid_t pid){
|
||
char *pp = name, byte, path[256];
|
||
int cntr = 0, file;
|
||
snprintf (path, 255, PROC_BASE "/%d/cmdline", pid);
|
||
file = open(path, O_RDONLY);
|
||
if(file == -1) return 0;
|
||
do{
|
||
if(read(file, &byte, 1) != 1) break;
|
||
if (byte != '/') *pp++ = byte;
|
||
else pp = name;
|
||
}
|
||
while(byte != EOF && byte != 0 && cntr++ < 255);
|
||
name[255] = 0;
|
||
close(file);
|
||
return 1;
|
||
}
|
||
DIR *dir;
|
||
FILE* pidfile;
|
||
struct dirent *de;
|
||
struct stat s_buf;
|
||
pid_t pid, self, run = 0;
|
||
char name[256], myname[256];
|
||
if (!(dir = opendir(PROC_BASE))){ // open /proc dir
|
||
perror(PROC_BASE);
|
||
exit(1);
|
||
}
|
||
self = getpid(); // self PID
|
||
if(stat(pidfilename, &s_buf) == 0){ // PID file exists
|
||
pidfile = fopen(pidfilename, "r");
|
||
if(1 == fscanf(pidfile, "%d", &run)){ // get PID of (possibly) running process
|
||
if(readname(name, run) && strncmp(name, myname, 255) == 0){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (pid=%d), <20><><EFBFBD><EFBFBD><EFBFBD>.\n"
|
||
ERR(_("\nFound running process (pid=%d), exit.\n"), run);
|
||
exit(7);
|
||
}
|
||
}
|
||
fclose(pidfile);
|
||
}
|
||
// there's no PID file or it's old
|
||
readname(myname, self); // self name
|
||
while ((de = readdir (dir)) != NULL){ // scan /proc
|
||
if (!(pid = (pid_t) atoi (de->d_name)) || pid == self)
|
||
continue;
|
||
readname(name, pid); // get process name
|
||
if(strncmp(name, myname, 255) == 0){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (pid=%d), <20><><EFBFBD><EFBFBD><EFBFBD>.\n"
|
||
ERR(_("\nFound running process (pid=%d), exit.\n"), pid);
|
||
exit(7);
|
||
}
|
||
}
|
||
closedir(dir);
|
||
unlink(pidfilename); // try to remove pidfilename
|
||
DBG("my PID: %d\n", self);
|
||
pidfile = fopen(pidfilename, "w");
|
||
fprintf(pidfile, "%d\n", self); // write into pidfilename the pid
|
||
fclose(pidfile);
|
||
}
|
||
|
||
// Work with turret
|
||
static void parse_turret_args(){
|
||
int maxPos, curPos;
|
||
if(ApnGlueWheelOpen(Nwheel, Apn_Filter_FW50_7S)){
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
ERR(_("Can't open turret"));
|
||
return;
|
||
}
|
||
DBG("get max pos");
|
||
maxPos = ApnGlueWheelGetMaxPos();
|
||
curPos = ApnGlueWheelGetPos();
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (MAX) <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (CUR) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:\n"
|
||
printf(_("Turret MAXimum position and CURrent position:\n"));
|
||
printf("MAX=%d, CUR=%d\n", maxPos, curPos);
|
||
if(wheelPos == 0) goto wheelret;
|
||
if(wheelPos > maxPos){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
ERR(_("Required position greater then max"));
|
||
goto wheelret;
|
||
}
|
||
if(ApnGlueWheelSetPos(wheelPos)){
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
ERR(_("Can't move turret"));
|
||
goto wheelret;
|
||
}
|
||
if(ApnGlueWheelGetStatus()){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "
|
||
printf(_("Wait, while turret is moving "));
|
||
while(ApnGlueWheelGetStatus()){
|
||
printf("."); fflush(NULL);
|
||
sleep(1);
|
||
}
|
||
}
|
||
printf("\n");
|
||
wheelret:
|
||
ApnGlueWheelClose();
|
||
}
|
||
|
||
#ifdef IMAGEVIEW
|
||
static void change_displayed_image(unsigned short *buf, windowData *win){
|
||
FNAME();
|
||
if(!win) return;
|
||
pthread_mutex_lock(&win->mutex);
|
||
int w = win->image->w, h = win->image->h;
|
||
static GLubyte i = 0;
|
||
GLubyte *raw = win->image->rawdata;
|
||
DBG("image size: %dx%d",w,h);
|
||
convert_grayimage(buf, raw, w, h);
|
||
win->image->changed = 1;
|
||
pthread_mutex_unlock(&win->mutex);
|
||
i++;
|
||
}
|
||
#endif
|
||
|
||
int main(int argc, char **argv){
|
||
int i; //cycles
|
||
int pid = -1, vid = -1; // device pid/vid
|
||
FILE *f_tlog = NULL; // temperature logging file
|
||
FILE *f_statlog = NULL; // stat file
|
||
int roih=0, roiw=0, osh=0, osw=0, binh=0, binw=0, shtr=0; // camera parameters
|
||
char whynot[BUFF_SIZ]; // temporary buffer for error texts
|
||
int imW=1024, imH=1024; // real (with binning) image size
|
||
unsigned short *buf = NULL; // image buffer
|
||
double mintemp=0.;
|
||
#ifdef IMAGEVIEW
|
||
windowData *mainwin = NULL;
|
||
rawimage im;
|
||
#endif
|
||
|
||
initial_setup(); // setup for macros.c
|
||
parse_args(argc, argv);
|
||
|
||
catch_signals();
|
||
// Check whether there's no concurrents
|
||
check4running();
|
||
|
||
if(test_headers){
|
||
writefits(NULL, imW, imH, NULL);
|
||
return(0);
|
||
}
|
||
if(fake) test_headers = 1;
|
||
// Begin of non-fake block ------->
|
||
if(!fake){
|
||
// Turret block
|
||
if(open_turret) parse_turret_args();
|
||
if(only_turret){
|
||
// "<22><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
info(_("Expose parameters aren't specified, exit"));
|
||
goto returning;
|
||
}
|
||
|
||
// And camera block
|
||
// First - open camera devise
|
||
if(subnet) ApnGlueSetSubnet(subnet); // set subnet name if there's an ethernet camera
|
||
if(cammsgid) ApnGlueSetMsgId(cammsgid); // set msgid given by user
|
||
if(ApnGlueOpen(Ncam)){
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
ERR(_("Can't open camera device, exit"));
|
||
if(ApnGlueIsEthernet()){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
info(_("Try to reboot camera from web-interface"));
|
||
}
|
||
exit(9);
|
||
}
|
||
DBG("open %d", Ncam);
|
||
// ApnGlueGetName(&sensor, &camera);
|
||
// camera = strdup(camera); sensor = strdup(sensor); - bug. it shows a shit!
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '%s' <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '%s'"
|
||
|
||
char *msg = NULL;
|
||
char *findnm(const char *nm){
|
||
char *f = strstr(msg, nm);
|
||
if(!f) return NULL;
|
||
f += strlen(nm);
|
||
char *e = strchr(f, '\n');
|
||
size_t l = (e) ? (size_t)(e-f) : strlen(f);
|
||
char *r = MALLOC(char, l+1);
|
||
snprintf(r, l, f);
|
||
return r;
|
||
}
|
||
msg = ApnGlueGetInfo(&pid, &vid);
|
||
if(msg){
|
||
//printf("\n Camera info:\n%s\n", msg);
|
||
camera = findnm("Model: ");
|
||
sensor = findnm("Sensor: ");
|
||
info(_("Camera '%s' with sensor '%s' detected"), camera, sensor);
|
||
free(msg);
|
||
}
|
||
|
||
// Second - check whether we want do a simple power operations
|
||
if(StopRes){
|
||
switch(StopRes){
|
||
case Reset:
|
||
ApnGlueReset();
|
||
if(pid > 0 && vid > 0)
|
||
reset_usb_port(pid, vid);
|
||
break;
|
||
case Sleep:
|
||
if(ApnGluePowerDown())
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>!"
|
||
ERR(_("Error: sleepless night!"));
|
||
break;
|
||
default:
|
||
ApnGluePowerResume();
|
||
}
|
||
goto returning;
|
||
}
|
||
|
||
// And then we can do other work
|
||
if(save_Tlog){
|
||
struct stat s;
|
||
char print_hdr = 1;
|
||
if(stat("temp_log", &s) == 0) print_hdr = 0;
|
||
f_tlog = fopen("temp_log", "a");
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
if(!f_tlog) err(1, _("Can't open temperature log file"));
|
||
if(print_hdr)
|
||
fprintf(f_tlog, "Time\t\t\tUnix time\tTint\tText\tStatus (eXp, Idle)\n");
|
||
//fprintf(f_tlog, "\n\n\n");
|
||
}
|
||
// Shutter
|
||
if(Shtr != -1)
|
||
ApnGlueOpenShutter(Shtr);
|
||
if(stat_logging){
|
||
struct stat s;
|
||
char print_hdr = 1;
|
||
if(stat("stat_log", &s) == 0) print_hdr = 0;
|
||
f_statlog = fopen("stat_log", "a");
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
if(!f_statlog) err(1, _("Can't open statistics log file"));
|
||
if(print_hdr)
|
||
fprintf(f_statlog, "Time\t\t\tUnix time\tTexp\tTint\tText\tImax\tImin\tIavr\tIstd\tNover\tN>3std\tIavr3\t\tIstd3\n");
|
||
}
|
||
ApnGlueGetMaxValues(NULL, &roiw, &roih, &osw, &osh, &binw, &binh,
|
||
&shtr, &mintemp);
|
||
info(_("Max binning: %dx%d\n"), binw, binh);
|
||
DBG("Shtr = %d, mintemp = %g", shtr, mintemp);
|
||
ApnGlueGetGeom(&pixX, &pixY);
|
||
// "\n<><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "
|
||
printf(_("\nThe shutter is "));
|
||
if(ApnGlueReadShutter())
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n"
|
||
printf(_("open\n"));
|
||
else
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n"
|
||
printf(_("closed\n"));
|
||
printCoolerStat(NULL);
|
||
|
||
if(set_T){
|
||
if(cooler_off){
|
||
ApnGlueSetTemp(0);
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
info(_("Switch cooler off"));
|
||
}else{
|
||
if(temperature >= mintemp){
|
||
if(temperature == 0.) temperature += 2.*DBL_EPSILON; // remove problem of zero temperature
|
||
ApnGlueSetTemp(temperature);
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
info(_("Changing of cooler setpoint"));
|
||
}else
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
info(_("The temperature setpoint is too low"));
|
||
}
|
||
}
|
||
|
||
if(fanspd > -1){
|
||
ApnGlueSetFan(fanspd);
|
||
if(ApnGlueGetFan() == fanspd)
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> %d\n"
|
||
info(_("Set fan speed %d\n"), fanspd);
|
||
else
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!\n"
|
||
ERR("Can't set fan speed\n");
|
||
}
|
||
|
||
if(only_T || exptime < 0) goto returning;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %g x %g
|
||
//info(_("Pixel size: %g x %g"), pixX, pixY);
|
||
--roiw;
|
||
--roih;
|
||
snprintf(viewfield, 79, "(0, %d)(0, %d)", roiw-osw, roih-osh);
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: %s"
|
||
info(_("Field of view: %s"), viewfield);
|
||
// "<22><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: (0, %d)(0, %d)"
|
||
info(_("Array field: (0, %d)(0, %d)"), roiw, roih);
|
||
|
||
if(X0 == -1) X0 = 0; // default parameters
|
||
if(Y0 == -1) Y0 = 0;
|
||
if(X1 == -1 || X1 > roiw) X1 = roiw;
|
||
if(Y1 == -1 || Y1 > roih) Y1 = roih;
|
||
// check overskan
|
||
if(X0 != 0 || X1 != roiw){
|
||
if(X1 == roiw) X1 -= osw;
|
||
osw = 0;
|
||
}
|
||
if(Y0 != 0 || Y1 != roih){
|
||
if(Y1 == roih) Y1 -= osh;
|
||
osh = 0;
|
||
}
|
||
if(hbin > binw) hbin = binw;
|
||
if(vbin > binh) vbin = binh;
|
||
|
||
//AutoadjustFanSpeed(FALSE);
|
||
if(noflash) ApnGluePreFlash(0);
|
||
if(noclean) ApnGlueDisablePostExpFlushing(1);
|
||
if(twelveBit)
|
||
ApnGlueSetDatabits(Apn_Resolution_TwelveBit);
|
||
else
|
||
ApnGlueSetDatabits(Apn_Resolution_SixteenBit);
|
||
|
||
if(ROspeed) ApnGlueSetSpeed(ROspeed);
|
||
|
||
if(pre_exp){// pre-expose
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
info(_("Pre-expose"));
|
||
double E = 0.;
|
||
if(!twelveBit)
|
||
ApnGlueSetDatabits(Apn_Resolution_TwelveBit);
|
||
if(ApnGlueSetExpGeom(8, 8, 0, 0, 8, 8, 0, 0, &imW, &imH, whynot)){
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %s"
|
||
ERR("Can't set readout parameters: %s", whynot);
|
||
goto returning;
|
||
}
|
||
int L = imW*imH;
|
||
buf = (unsigned short*) calloc(L, sizeof(unsigned short));
|
||
if(!buf){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"
|
||
ERR(_("malloc() failed!"));
|
||
}
|
||
if(ApnGlueStartExp(&E, 0)){
|
||
if(pid > 0 && vid > 0)
|
||
reset_usb_port(pid, vid);
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"
|
||
if(ApnGlueStartExp(&E, 0)) ERR("Error exposing pre-exp frame!");
|
||
}
|
||
ignore_signals();
|
||
if(ApnGlueReadPixels(buf, L, whynot)){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %s\n"
|
||
ERR(_("Readout error: %s\n"), whynot);
|
||
}
|
||
free(buf);
|
||
// restore signals
|
||
catch_signals();
|
||
if(!twelveBit)
|
||
ApnGlueSetDatabits(Apn_Resolution_SixteenBit);
|
||
}
|
||
if(ApnGlueSetExpGeom(X1-X0-1, Y1-Y0+1, osw, osh, hbin, vbin,
|
||
X0, Y0, &imW, &imH, whynot)){
|
||
DBG("ApnGlueSetExpGeom(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s)", X1-X0+1, Y1-Y0+1, osw, osh, hbin, vbin,
|
||
X0, Y0, imW, imH, whynot);
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %s"
|
||
ERR("Can't set readout parameters: %s", whynot);
|
||
goto returning;
|
||
}
|
||
DBG("ApnGlueSetExpGeom(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s)", X1-X0+1, Y1-Y0+1, osw, osh, hbin, vbin,
|
||
X0, Y0, imW, imH, whynot);
|
||
} // <------ end of non-fake block
|
||
DBG("geomery: %dx%d", imW, imH);
|
||
int L = imW*imH;
|
||
buf = (unsigned short*) calloc(L, sizeof(unsigned short));
|
||
if(!buf){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"
|
||
ERR(_("malloc() failed!"));
|
||
}
|
||
#ifdef IMAGEVIEW
|
||
// start image view module if not need to save image or manually defined displaying
|
||
if(fake || !save_image || show_image){
|
||
imageview_init();
|
||
im.protected = 1;
|
||
im.rawdata = MALLOC(GLubyte, imW*imH*3);
|
||
if(!im.rawdata) ERR("Can't allocate memory");
|
||
im.w = imW; im.h = imH;
|
||
}
|
||
#endif
|
||
if(fake) pics = 0;
|
||
DBG("start %d expositions", pics);
|
||
for (i = 0; i < pics; i++){
|
||
/*DBG("spd");
|
||
AutoadjustFanSpeed(FALSE);
|
||
DBG("cooler");*/
|
||
temperature = printCoolerStat(NULL);
|
||
double E;
|
||
int I;
|
||
if(exptime > -1){ // do expositions only if there is -x key
|
||
E = (double) exptime / 1000.;
|
||
I = (int) E;
|
||
ignore_signals();
|
||
DBG("start exp");
|
||
if(ApnGlueStartExp(&E, shutter)){
|
||
DBG("pid=%d, vid=%d", pid, vid);
|
||
if(pid > 0 && vid > 0)
|
||
reset_usb_port(pid, vid);
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"
|
||
if(ApnGlueStartExp(&E, shutter)) ERR("Error exposing frame!");
|
||
}
|
||
DBG("Exposing");
|
||
#ifdef USE_BTA
|
||
if(histry) push_param();
|
||
#endif
|
||
//exptime = (int)(E*1000.);
|
||
printf("\n\n");
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> %d, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - %g <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n"
|
||
printf(_("Capture frame %d, exp time - %g sec\n"), i, E);
|
||
expStartsAt = time(NULL); // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/*if(save_Tlog) if(curtime(tm_buf))
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d-<2D><> <20><><EFBFBD><EFBFBD><EFBFBD>; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %g<>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %s, <20><><EFBFBD><EFBFBD>: %s\n"
|
||
fprintf(f_tlog, _("Begin exposition of %dth frame; exp length: %gs, start time: %s, filename: %s\n"),
|
||
i, E, tm_buf, outfile);*/
|
||
time0 = itime();
|
||
do{
|
||
// %.3f <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n
|
||
//printf(_("%.3f seconds till exposition ends\n"), ((float)ltmp) / 1000.);
|
||
t_int = printCoolerStat(&t_ext);
|
||
if(save_Tlog && curtime(tm_buf)){
|
||
fprintf(f_tlog, "%s\t%ld\t%.2f\t%.2f\tX\n", tm_buf, time(NULL), t_int, t_ext);
|
||
}
|
||
//AutoadjustFanSpeed(FALSE);
|
||
int tt = ltime();
|
||
printf("%d sec\n", tt);
|
||
if(I - tt > time_interval){
|
||
sleep(time_interval);
|
||
#ifdef USE_BTA
|
||
if(histry) push_param();
|
||
#endif
|
||
}else while(!ApnGlueExpDone()) usleep(100000); // make 100ms error
|
||
}while(!ApnGlueExpDone());
|
||
DBG("exp done");
|
||
#ifdef USE_BTA
|
||
if(histry) push_param();
|
||
#endif
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:"
|
||
printf(_("Read image: "));
|
||
fflush(stdout);
|
||
// try to ignore signals for this long operation
|
||
ignore_signals();
|
||
if(ApnGlueReadPixels(buf, L, whynot)){
|
||
// "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %s\n"
|
||
ERR(_("Readout error: %s\n"), whynot);
|
||
catch_signals();
|
||
continue;
|
||
}
|
||
// mirror image if needed
|
||
if(flipX){ // mirror vertically (around X axe)
|
||
unsigned short *newbuf = MALLOC(unsigned short, imW*imH);
|
||
OMP_FOR()
|
||
for(int _row = 0; _row < imH; _row++){
|
||
unsigned short *optr = &newbuf[_row*imW], *iptr = &buf[(imH-1-_row)*imW];
|
||
for(int _pix = 0; _pix < imW; _pix++)
|
||
*optr++ = *iptr++;
|
||
}
|
||
FREE(buf);
|
||
buf = newbuf;
|
||
}
|
||
if(flipY){ // mirror horizontally (around Y axe)
|
||
unsigned short *newbuf = MALLOC(unsigned short, imW*imH);
|
||
OMP_FOR()
|
||
for(int _row = 0; _row < imH; _row++){
|
||
unsigned short *optr = &newbuf[_row*imW], *iptr = &buf[(_row+1)*imW-1];
|
||
for(int _pix = 0; _pix < imW; _pix++)
|
||
*optr++ = *iptr--;
|
||
}
|
||
FREE(buf);
|
||
buf = newbuf;
|
||
}
|
||
// restore signals
|
||
catch_signals();
|
||
t_int = printCoolerStat(&t_ext);
|
||
if(f_statlog && curtime(tm_buf))
|
||
fprintf(f_statlog, "%s\t%ld\t%g\t%.2f\t%.2f\t", tm_buf,
|
||
time(NULL), E, t_int, t_ext);
|
||
print_stat(buf, L, f_statlog);
|
||
#ifdef IMAGEVIEW
|
||
if(!save_image || show_image){
|
||
// build FITS headers tree for viewer
|
||
#ifdef USE_BTA
|
||
write_bta_data(NULL);
|
||
#endif
|
||
check_wcs();
|
||
if(!get_windows_amount() || !mainwin){
|
||
mainwin = createGLwin("Sample window", 400, 400, &im);
|
||
if(!mainwin){
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> OpenGL, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"
|
||
info(_("Can't open OpenGL window, image preview will be inaccessible"));
|
||
}else{
|
||
mainwin->killthread = 1;
|
||
}
|
||
}
|
||
}
|
||
if(get_windows_amount() && mainwin){
|
||
DBG("change image");
|
||
change_displayed_image(buf, mainwin);
|
||
}
|
||
#endif
|
||
inline void WRITEIMG(int (*writefn)(char*,int,int,void*), char *ext){
|
||
if(!check_filename(whynot, outfile, ext))
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>"
|
||
err(1, _("Can't save file"));
|
||
else{
|
||
int r = writefn(whynot, imW, imH, buf);
|
||
// "<22><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> '%s'"
|
||
if (r == 0) info(_("File saved as '%s'"), whynot);
|
||
}
|
||
}
|
||
if(save_image){
|
||
DBG("save image");
|
||
#ifdef USERAW
|
||
WRITEIMG(writeraw, "raw");
|
||
#endif // USERAW
|
||
WRITEIMG(writefits, "fit");
|
||
#ifdef USEPNG
|
||
WRITEIMG(writepng, "png");
|
||
#endif /* USEPNG */
|
||
}
|
||
}
|
||
if(pause_len){
|
||
int delta;
|
||
time0 = itime();
|
||
while((delta = pause_len - ltime()) > 0){
|
||
// "%d <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>\n"
|
||
printf(_("%d seconds till pause ends\n"), delta);
|
||
temperature = printCoolerStat(&t_ext);
|
||
if(save_Tlog && curtime(tm_buf)){
|
||
fprintf(f_tlog, "%s\t%ld\t%.2f\t%.2f\tI\n", tm_buf, time(NULL), temperature, t_ext);
|
||
}
|
||
//AutoadjustFanSpeed(FALSE);
|
||
if(delta > 10) sleep(10);
|
||
else sleep(delta);
|
||
}
|
||
}
|
||
fflush(NULL);
|
||
}
|
||
#ifdef IMAGEVIEW
|
||
if(fake){
|
||
writefits(NULL, imW, imH, NULL);
|
||
if(!get_windows_amount() || !mainwin){
|
||
mainwin = createGLwin("Sample window", 400, 400, &im);
|
||
if(!mainwin){
|
||
// "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> OpenGL, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"
|
||
info(_("Can't open OpenGL window, image preview will be inaccessible"));
|
||
}else{
|
||
mainwin->killthread = 1;
|
||
}
|
||
}
|
||
if(get_windows_amount() && mainwin){
|
||
DBG("change image");
|
||
change_displayed_image(buf, mainwin);
|
||
}
|
||
}
|
||
#endif
|
||
returning:
|
||
if(!only_turret){
|
||
#ifdef IMAGEVIEW
|
||
DBG("test for GL window");
|
||
if(mainwin){ //window was created - wait for manual close
|
||
DBG("wait for window closing");
|
||
while(get_windows_amount()){
|
||
usleep(50000);
|
||
}
|
||
FREE(im.rawdata);
|
||
}
|
||
#endif
|
||
if(!fake){
|
||
if(f_tlog) fclose(f_tlog);
|
||
if(f_statlog) fclose(f_statlog);
|
||
signals(0);
|
||
}
|
||
}
|
||
return 0;
|
||
}
|