pre-alpha (works only with FLI)

This commit is contained in:
Edward Emelianov 2022-01-13 12:32:11 +03:00
parent 2def67923b
commit 838c9567c3
21 changed files with 3843 additions and 35 deletions

46
.gitignore vendored
View File

@ -1,52 +1,28 @@
# Temporary files
*~
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# QT-creator files
*.cflags
*.config
*.creator
*.user
*.cxxflags
*.files
*.includes

129
CMakeLists.txt Normal file
View File

@ -0,0 +1,129 @@
cmake_minimum_required(VERSION 3.20)
set(PROJ ccd_capture)
project(${PROJ})
set(MINOR_VERSION "0")
set(MID_VERSION "0")
set(MAJOR_VERSION "1")
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
message("VER: ${VERSION}")
# default flags
set(CFLAGS ${CFLAGS} -Wall -W -Wextra -O3 -std=gnu99)
add_definitions(-D_XOPEN_SOURCE=1234 -D_DEFAULT_SOURCE -D_GNU_SOURCE)
set(CMAKE_COLOR_MAKEFILE ON)
set(SOURCES main.c cmdlnopts.c ccdfunc.c)
# cmake -DDEBUG=yes -> debugging
if(DEFINED DEBUG AND DEBUG STREQUAL "yes")
set(CFLAGS ${CFLAGS} -Werror)
add_definitions(-DEBUG)
set(CMAKE_VERBOSE_MAKEFILE "ON")
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
find_package(CFITSIO REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(${PROJ} REQUIRED usefull_macros)
if(DEFINED IMAGEVIEW AND IMAGEVIEW STREQUAL "yes")
list(APPEND SOURCES events.c imageview.c)
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
find_package(X11 REQUIRED)
find_package(Threads REQUIRED)
list(APPEND ${PROJ}_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
add_definitions(-DIMAGEVIEW)
endif()
# additional modules with CCD/CMOS support
if(DEFINED ZWO AND ZWO STREQUAL "yes")
add_subdirectory(ZWO_cameras)
list(APPEND ${PROJ}_INCLUDE_DIRS ZWO_cameras)
add_definitions(-DUSEZWO)
list(APPEND ${PROJ}_LIBRARIES ${ZWOLIB})
include_directories(ZWO_cameras)
endif()
# additional modules with CCD/CMOS support
if(DEFINED FLI AND FLI STREQUAL "yes")
add_subdirectory(FLI_cameras)
list(APPEND ${PROJ}_INCLUDE_DIRS FLI_cameras)
add_definitions(-DUSEFLI)
list(APPEND ${PROJ}_LIBRARIES ${FLILIB})
include_directories(FLI_cameras)
endif()
# change wrong behaviour with install prefix
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND CMAKE_INSTALL_PREFIX MATCHES "/usr/local")
message("Change default install path to /usr")
set(CMAKE_INSTALL_PREFIX "/usr")
endif()
message("Install dir prefix: ${CMAKE_INSTALL_PREFIX}")
# directory should contain dir locale/ru for gettext translations
set(LCPATH ${CMAKE_SOURCE_DIR}/locale/ru)
if(NOT DEFINED LOCALEDIR)
if(DEFINED DEBUG AND DEBUG STREQUAL "yes")
set(LOCALEDIR ${CMAKE_CURRENT_SOURCE_DIR}/locale)
else()
set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale)
endif()
endif()
# gettext files
set(PO_FILE ${LCPATH}/messages.po)
set(MO_FILE ${LCPATH}/LC_MESSAGES/${PROJ}.mo)
set(RU_FILE ${LCPATH}/ru.po)
# exe file
add_executable(${PROJ} ${SOURCES} ${PO_FILE} ${MO_FILE})
target_link_libraries(${PROJ} ${CFITSIO_LIBRARIES} ${X11_LIBRARIES} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${${PROJ}_LIBRARIES} -lm)
include_directories(${${PROJ}_INCLUDE_DIRS} .)
link_directories(${${PROJ}_LIBRARY_DIRS} )
add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\"
-DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\"
-DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\"
-DMAJOR_VERSION=\"${MAJOR_VESION}\")
# Installation of the program
INSTALL(FILES ${MO_FILE} DESTINATION "share/locale/ru/LC_MESSAGES")
INSTALL(TARGETS ${PROJ} DESTINATION "bin")
find_package(Gettext REQUIRED)
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
if(NOT GETTEXT_XGETTEXT_EXECUTABLE OR NOT GETTEXT_MSGFMT_EXECUTABLE)
message(FATAL_ERROR "xgettext not found")
endif()
file(MAKE_DIRECTORY ${LCPATH})
file(MAKE_DIRECTORY ${LCPATH}/LC_MESSAGES)
add_custom_command(
OUTPUT ${PO_FILE}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --from-code=koi8-r ${SOURCES} -c -k_ -kN_ -o ${PO_FILE}
COMMAND sed -i 's/charset=.*\\\\n/charset=koi8-r\\\\n/' ${PO_FILE}
# COMMAND enconv ${PO_FILE}
DEPENDS ${SOURCES}
)
# we need this to prewent ru.po & .mo from deleting by make clean
add_custom_command(
OUTPUT ${MO_FILE}
COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} ${RU_FILE} -o ${MO_FILE}
DEPENDS ${RU_FILE} ru_file_updated
)
add_custom_command(
OUTPUT ru_file_updated
COMMAND [ -f ${RU_FILE} ] && ${GETTEXT_MSGMERGE_EXECUTABLE} -Uis ${RU_FILE} ${PO_FILE} || cp ${PO_FILE} ${RU_FILE}
COMMAND ${CMAKE_COMMAND} -E touch ru_file_updated
BYPRODUCTS ${RU_FILE}
DEPENDS ${PO_FILE}
)
add_custom_target(MO_FILE ALL DEPENDS ${MO_FILE})

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.20)
set(CCDLIB fli_module)
set(FLILIB ${CCDLIB} PARENT_SCOPE)
find_package(PkgConfig REQUIRED)
pkg_check_modules(${CCDLIB} REQUIRED fli>=1.71 usefull_macros)
set(CFLAGS -O3 -Wextra -Wall -W -std=gnu99)
set(CMAKE_COLOR_MAKEFILE ON)
if(DEFINED DEBUG AND DEBUG STREQUAL "yes")
set(CFLAGS ${CFLAGS} -Werror)
message ("DBG = ${DEBUG}, CFLAGS=${CFLAGS}")
add_definitions(-DEBUG)
set(CMAKE_VERBOSE_MAKEFILE "ON")
endif()
add_definitions(${CFLAGS})
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC)
add_library(${CCDLIB} ${SRC})
target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES})
include_directories(${${CCDLIB}_INCLUDE_DIRS} ..)
link_directories(${${CCDLIB}_LIBRARY_DIRS})

712
FLI_cameras/flifunc.c Normal file
View File

@ -0,0 +1,712 @@
/*
* This file is part of the FLI_control project.
* Copyright 2020 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <fcntl.h>
#include <fitsio.h>
#include <libfli.h>
#include <limits.h>
#include <math.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <usefull_macros.h>
#include "flifunc.h"
#define LIBVERSIZ 1024
#ifndef FLIUSB_VENDORID
#define FLIUSB_VENDORID 0xf18
#endif
#ifndef FLIUSB_PROLINE_ID
#define FLIUSB_PROLINE_ID 0x0a
#endif
#ifndef FLIUSB_FILTER_ID
#define FLIUSB_FILTER_ID 0x07
#endif
#ifndef FLIUSB_FOCUSER_ID
#define FLIUSB_FOCUSER_ID 0x06
#endif
// wheel position in steps = WHEEL_POS0STPS + WHEEL_STEPPOS*N
#define WHEEL_POS0STPS (239)
#define WHEEL_STEPPOS (48)
// 1mm == FOCSCALE steps of focuser
#define FOCSCALE (10000.)
#define TRYFUNC(f, ...) \
do{ if((fli_err = f(__VA_ARGS__))) \
WARNX(#f "() failed"); \
}while(0)
#define TRYFITS(f, ...) \
do{ int status = 0; \
f(__VA_ARGS__, &status); \
if (status){ \
fits_report_error(stderr, status); \
return -1;} \
}while(0)
#define WRITEKEY(...) \
do{ int status = 0; \
fits_write_key(__VA_ARGS__, &status); \
if(status) fits_report_error(stderr, status);\
}while(0)
typedef struct{
flidomain_t domain;
char *dname;
char *name;
}cam_t;
static char camname[BUFSIZ] = {0}, whlname[BUFSIZ], focname[BUFSIZ];
static long fli_err, tmpl;
static cam_t *camz = NULL, *whlz = NULL, *focz = NULL;
static flidev_t camdev, whldev, focdev;
static capture_status capStatus = CAPTURE_NO;
static int curhbin = 1, curvbin = 1;
static long filterpos = -1, filtermax = -1; // filter position
static long focuserpos = -1, focmaxpos = -1; // focuser position
static int fli_init(){
char libver[LIBVERSIZ]; // FLI library version
TRYFUNC(FLISetDebugLevel, NULL /* "NO HOST" */, FLIDEBUG_NONE);
if(fli_err) return FALSE;
TRYFUNC(FLIGetLibVersion, libver, LIBVERSIZ);
if(!fli_err) DBG("Library version '%s'", libver);
return TRUE;
}
static int findcams(flidomain_t domain, cam_t **cam){
char **tmplist;
int numcams = 0;
TRYFUNC(FLIList, domain, &tmplist);
if(tmplist && tmplist[0]){
int i, cams = 0;
for(i = 0; tmplist[i]; i++) cams++;
if((*cam = realloc(*cam, (numcams + cams) * sizeof(cam_t))) == NULL)
ERR("realloc() failed");
for(i = 0; tmplist[i]; i++){
int j;
cam_t *tmpcam = *cam + i;
for (j = 0; tmplist[i][j] != '\0'; j++)
if (tmplist[i][j] == ';'){
tmplist[i][j] = '\0';
break;
}
tmpcam->domain = domain;
tmpcam->name = strdup(tmplist[i]);
switch (domain & 0xff){
case FLIDOMAIN_PARALLEL_PORT:
tmpcam->dname = "parallel port";
break;
case FLIDOMAIN_USB:
tmpcam->dname = "USB";
break;
case FLIDOMAIN_SERIAL:
tmpcam->dname = "serial";
break;
case FLIDOMAIN_INET:
tmpcam->dname = "inet";
break;
default:
tmpcam->dname = "Unknown domain";
break;
}
DBG("found: %s @ %s", tmpcam->name, tmpcam->dname);
}
numcams += cams;
}
TRYFUNC(FLIFreeList, tmplist);
return numcams;
}
static int fli_findCCD(){
DBG("Try to find FLI cameras .. ");
if(!fli_init()){
DBG("FLI not found");
return FALSE;
}
if(!camz){ // build cameras list
FLIcam.Ndevices = findcams(FLIDOMAIN_USB | FLIDEVICE_CAMERA, &camz);
if(!FLIcam.Ndevices){
DBG("No cameras");
return FALSE;
}
for(int i = 0; i < FLIcam.Ndevices; i++){
DBG("Camera '%s', domain %s", camz[i].name, camz[i].dname);
}
}
return TRUE;
}
static int fli_setActiceCam(int n){
if(!camz && !fli_findCCD()) return FALSE;
if(n >= FLIcam.Ndevices){
return FALSE;
}
FLIClose(camdev);
TRYFUNC(FLIOpen, &camdev, camz[n].name, camz[n].domain);
if(fli_err){
return FALSE;
}
TRYFUNC(FLIGetModel, camdev, camname, BUFSIZ);
#ifdef EBUG
if(!fli_err) DBG("Model: %s", camname);
TRYFUNC(FLIGetHWRevision, camdev, &tmpl);
if(!fli_err) DBG("HW revision: %ld", tmpl);
TRYFUNC(FLIGetFWRevision, camdev, &tmpl);
if(!fli_err) DBG("SW revision: %ld", tmpl);
#endif
double x,y;
TRYFUNC(FLIGetPixelSize, camdev, &x, &y);
if(!fli_err){
DBG("Pixel size: %g x %g", x,y);
FLIcam.pixX = (float)x;
FLIcam.pixY = (float)y;
}
long x0, x1, y0, y1;
TRYFUNC(FLIGetVisibleArea, camdev, &x0, &y0, &x1, &y1);
if(!fli_err){
DBG("Field of view: (%ld, %ld)(%ld, %ld)", x0, y0, x1, y1);
FLIcam.field = (frameformat){.w = x1 - x0, .h = y1 - y0, .xoff = x0, .yoff = y0};
}
TRYFUNC(FLIGetArrayArea, camdev, &x0, &y0, &x1, &y1);
if(!fli_err){
DBG("Array field: (%ld, %ld)(%ld, %ld)", x0, y0, x1, y1);
FLIcam.array = (frameformat){.w = x1 - x0, .h = y1 - y0, .xoff = x0, .yoff = y0};
}
return TRUE;
}
static int fli_geomlimits(frameformat *l, frameformat *s){
if(l) *l = FLIcam.array;
if(s) *s = (frameformat){.w = 1, .h = 1, .xoff = 1, .yoff = 1};
return TRUE;
}
static int fli_findFocuser(){
DBG("Try to find FLI focusers .. ");
if(!fli_init()){
DBG("FLI not found");
return FALSE;
}
if(!focz){
FLIfocus.Ndevices = findcams(FLIDOMAIN_USB | FLIDEVICE_FOCUSER, &focz);
if(!FLIfocus.Ndevices){
DBG("No focusers");
return FALSE;
}
for(int i = 0; i < FLIfocus.Ndevices; i++){
DBG("Focuser '%s', domain %s", focz[i].name, focz[i].dname);
}
}
return TRUE;
}
static int fli_setActiceFocuser(int n){
if(!focz && !fli_findFocuser()) return FALSE;
if(n >= FLIfocus.Ndevices) return FALSE;
FLIClose(focdev);
int OK = FALSE;
for(int i = 0; i < FLIfocus.Ndevices; ++i){
DBG("Try %s", focz[i].name);
TRYFUNC(FLIOpen, &focdev, focz[i].name, focz[i].domain);
if(fli_err) continue;
TRYFUNC(FLIGetModel, focdev, focname, BUFSIZ);
DBG("MODEL '%s'", focname);
if(fli_err) continue;
if(!strcasestr(focname, "focuser")){ // not a focuser?
DBG("Not a focuser");
TRYFUNC(FLIClose, focdev);
continue;
}
if(n-- == 0){
OK = TRUE; break;
}
}
if(!OK){
DBG("Not found");
return FALSE;
}
DBG("Focuser: %s", focname);
#ifdef EBUG
TRYFUNC(FLIGetHWRevision, focdev, &tmpl);
if(!fli_err) DBG("HW revision: %ld", tmpl);
TRYFUNC(FLIGetFWRevision, focdev, &tmpl);
if(!fli_err) DBG("SW revision: %ld", tmpl);
#endif
TRYFUNC(FLIGetStepperPosition, focdev, &focuserpos);
TRYFUNC(FLIGetFocuserExtent, focdev, &focmaxpos);
DBG("Curpos: %ld, maxpos: %ld", focuserpos, focmaxpos);
return TRUE;
}
static int fli_fgetmodel(char *model, int l){
strncpy(model, focname, l);
return TRUE;
}
static int fli_fgett(float *t){
if(!t) return FALSE;
double d;
if(FLIReadTemperature(focdev, FLI_TEMPERATURE_INTERNAL, &d)) return FALSE;
*t = (float) d;
return TRUE;
}
static int fli_fgetpos(float *p){
if(!p) return FALSE;
TRYFUNC(FLIGetStepperPosition, focdev, &focuserpos);
if(fli_err) return FALSE;
*p = focuserpos / FOCSCALE;
return TRUE;
}
static int fli_fgetmaxpos(float *p){
if(!p) return FALSE;
*p = focmaxpos / FOCSCALE;
return TRUE;
}
static int fli_fgetminpos(float *p){
if(!p) return FALSE;
*p = 0.;
return TRUE;
}
static int fli_fhome(int async){
if(async) TRYFUNC(FLIHomeDevice, focdev);
else TRYFUNC(FLIHomeFocuser, focdev);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_fgoto(int async, float pos){
long tagpos = pos * FOCSCALE;
if(tagpos > focmaxpos) return FALSE;
DBG("tagpos: %ld, focuserpos: %ld", tagpos, focuserpos);
tagpos -= focuserpos;
if(labs(tagpos) < 2) return TRUE;
DBG("tagpos: %ld", tagpos);
if(async) TRYFUNC(FLIStepMotorAsync, focdev, tagpos);
else TRYFUNC(FLIStepMotor, focdev, tagpos);
return TRUE;
}
static int fli_findWheel(){
if(whlz) return TRUE;
DBG("Try to find FLI filter wheels .. ");
if(!fli_init()){
DBG("FLI not found");
return FALSE;
}
FLIwheel.Ndevices = findcams(FLIDOMAIN_USB | FLIDEVICE_FILTERWHEEL, &whlz);
if(!FLIwheel.Ndevices){
DBG("No wheels");
return FALSE;
}
for(int i = 0; i < FLIwheel.Ndevices; i++){
DBG("Wheel '%s', domain %s", whlz[i].name, whlz[i].dname);
}
return TRUE;
}
static int fli_wgetpos(int *p);
static int fli_setActiceWheel(int n){
if(!whlz && !fli_findWheel()) return FALSE;
if(n >= FLIwheel.Ndevices) return FALSE;
FLIClose(whldev);
int OK = FALSE;
for(int i = 0; i < FLIfocus.Ndevices; ++i){
DBG("Try %s", whlz[i].name);
TRYFUNC(FLIOpen, &whldev, whlz[i].name, whlz[i].domain);
if(fli_err) continue;
TRYFUNC(FLIGetFilterCount, whldev, &filtermax);
if(fli_err || filtermax < 2){ // not a wheel
DBG("Not a wheel");
TRYFUNC(FLIClose, whldev);
continue;
}
if(n-- == 0){
OK = TRUE; break;
}
}
if(!OK){
DBG("Not found");
return FALSE;
}
TRYFUNC(FLIGetModel, whldev, whlname, BUFSIZ);
DBG("Wheel: %s", whlname);
#ifdef EBUG
TRYFUNC(FLIGetHWRevision, whldev, &tmpl);
if(!fli_err) DBG("HW revision: %ld", tmpl);
TRYFUNC(FLIGetFWRevision, whldev, &tmpl);
if(!fli_err) DBG("SW revision: %ld", tmpl);
#endif
--filtermax; // max position number
int tmp;
fli_wgetpos(&tmp);
DBG("Cur position: %ld, max position: %ld", filterpos, filtermax);
return TRUE;
}
static int fli_wgetname(char *x, int n){
strncpy(x, whlname, n);
return TRUE;
}
static int fli_wgetmaxpos(int *p){
if(!p) return FALSE;
*p = filtermax;
return TRUE;
}
static int fli_wgetpos(int *p){
if(!p) return FALSE;
//TRYFUNC(FLIGetFilterPos, whldev, &filterpos); - wrong position!
//if(fli_err){
// DBG("FLIGetFilterPos - ERROR!");
TRYFUNC(FLIGetStepperPosition, whldev, &tmpl);
if(fli_err) return FALSE;
if(tmpl < 0) tmpl = -tmpl;
int pos = (tmpl - WHEEL_POS0STPS+WHEEL_STEPPOS/2)/WHEEL_STEPPOS;
DBG("pos = %d", pos);
if(pos > -1 && pos <= filtermax) filterpos = pos;
else return FALSE;
//}
*p = filterpos;
return TRUE;
}
static int fli_wsetpos(int p){
if(p == filterpos) return TRUE;
if(p > filtermax || p < 0) return FALSE;
TRYFUNC(FLISetFilterPos, whldev, (long)p);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_wgett(float *t){
if(!t) return FALSE;
double d;
if(FLIReadTemperature(whldev, FLI_TEMPERATURE_INTERNAL, &d)) return FALSE;
*t = (float) d;
return TRUE;
}
static int fli_pollcapt(capture_status *st, float *remain){
static int errctr = 0;
if(capStatus == CAPTURE_READY){
DBG("Capture ends");
goto retn;
}
if(capStatus == CAPTURE_NO){ // start capture
errctr = 0;
DBG("Start exposition");
TRYFUNC(FLIExposeFrame, camdev);
if(fli_err){
TRYFUNC(FLICancelExposure, camdev);
if(st) *st = CAPTURE_CANTSTART;
return FALSE;
}
capStatus = CAPTURE_PROCESS;
}
if(capStatus == CAPTURE_PROCESS){
TRYFUNC(FLIGetExposureStatus, camdev, &tmpl);
if(fli_err){
if(++errctr > 3){
if(st) *st = CAPTURE_ABORTED;
TRYFUNC(FLICancelExposure, camdev);
capStatus = CAPTURE_NO;
return FALSE;
}
goto retn;
}
if(remain) *remain = tmpl/1000.;
DBG("remained: %g", tmpl/1000.);
if(tmpl == 0){
if(st) *st = CAPTURE_READY;
capStatus = CAPTURE_NO;
return TRUE;
}
}else{ // some error
if(st) *st = CAPTURE_ABORTED;
capStatus = CAPTURE_NO;
}
retn:
if(st) *st = capStatus;
return TRUE;
}
static int fli_capt(IMG *ima){
if(!ima || !ima->data) return FALSE;
for(int row = 0; row < ima->h; row++){
TRYFUNC(FLIGrabRow, camdev, &ima->data[row * ima->w], ima->w);
if(fli_err) return FALSE;
}
return TRUE;
}
static int fli_modelname(char *buf, int bufsz){
strncpy(buf, camname, bufsz);
return TRUE;
}
static int fli_setbin(int binh, int binv){
TRYFUNC(FLISetHBin, camdev, binh);
if(fli_err) return FALSE;
curhbin = binh;
TRYFUNC(FLISetVBin, camdev, binv);
if(fli_err) return FALSE;
curvbin = binv;
return TRUE;
}
static int fli_getbin(int *h, int *v){
if(h) *h = curhbin;
if(v) *v = curvbin;
return TRUE;
}
static int fli_setgeometry(frameformat *f){
if(!f) return FALSE;
TRYFUNC(FLISetImageArea, camdev, f->xoff, f->yoff,
f->xoff + f->w/curhbin, f->yoff + f->h/curvbin);
if(fli_err) return FALSE;
FLIcam.geometry = *f;
return TRUE;
}
static int fli_setnflushes(int n){
if(n < 0) return FALSE;
if(n){
TRYFUNC(FLIControlBackgroundFlush, camdev, FLI_BGFLUSH_START);
TRYFUNC(FLISetNFlushes, camdev, n);
}
else TRYFUNC(FLIControlBackgroundFlush, camdev, FLI_BGFLUSH_STOP);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_settemp(float t){
TRYFUNC(FLISetTemperature, camdev, t);
if(fli_err) return FALSE;
return TRUE;
}
typedef enum{
T_COLD,
T_BODY,
T_HOT
} temptype;
static int fli_gettemp(temptype type, float *t){
double d;
switch(type){
case T_COLD:
TRYFUNC(FLIGetTemperature, camdev, &d);
break;
case T_BODY:
TRYFUNC(FLIReadTemperature, camdev, FLI_TEMPERATURE_EXTERNAL, &d);
break;
default:
TRYFUNC(FLIReadTemperature, camdev, FLI_TEMPERATURE_INTERNAL, &d);
}
if(fli_err) return FALSE;
*t = d;
return TRUE;
}
static int fli_getTcold(float *t){
return fli_gettemp(T_COLD, t);
}
static int fli_getTbody(float *t){
return fli_gettemp(T_BODY, t);
}
static int fli_getThot(float *t){
return fli_gettemp(T_HOT, t);
}
static void fli_cancel(){
TRYFUNC(FLICancelExposure, camdev);
TRYFUNC(FLIEndExposure, camdev);
}
static int fli_shutter(shutter_op cmd){
flishutter_t shtr = FLI_SHUTTER_CLOSE;
switch(cmd){
case SHUTTER_OPEN:
shtr = FLI_SHUTTER_OPEN;
break;
case SHUTTER_CLOSE:
break;
case SHUTTER_OPENATHIGH:
shtr = FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH;
break;
case SHUTTER_OPENATLOW:
shtr = FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH;
break;
default:
return FALSE;
}
TRYFUNC(FLIControlShutter, camdev, shtr);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_confio(int io){
TRYFUNC(FLIConfigureIOPort, camdev, io);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_getio(int *io){
if(!io) return FALSE;
long lio = (long)*io;
TRYFUNC(FLIReadIOPort, camdev, &lio);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_setio(int io){
TRYFUNC(FLIWriteIOPort, camdev, (long)io);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_setexp(float t){
long e = (long)(t*1000.);
TRYFUNC(FLISetExposureTime, camdev, e);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_setframetype(int t){
fliframe_t frametype = t ? FLI_FRAME_TYPE_NORMAL : FLI_FRAME_TYPE_DARK;
TRYFUNC(FLISetFrameType, camdev, frametype);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_setbitdepth(int i){
flibitdepth_t depth = i ? FLI_MODE_16BIT : FLI_MODE_8BIT;
TRYFUNC(FLISetBitDepth, camdev, depth);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_setfastspeed(int fast){
flimode_t mode = fast ? 0 : 1;
TRYFUNC(FLISetCameraMode, camdev, mode);
if(fli_err) return FALSE;
return TRUE;
}
static int fli_setfanspd(fan_speed s){
long sp = (s == FAN_OFF) ? FLI_FAN_SPEED_OFF : FLI_FAN_SPEED_ON;
TRYFUNC(FLISetFanSpeed, camdev, sp);
if(fli_err) return FALSE;
return TRUE;
}
static void camt_free(cam_t **c, int n, flidev_t dev){
if(!c || !*c) return;
TRYFUNC(FLIClose, dev);
for(int i = 0; i < n; ++i)
FREE((*c)[i].name);
FREE(*c);
}
static void fli_closecam(){
DBG("CAMERA CLOSE");
camt_free(&camz, FLIcam.Ndevices, camdev);
}
static void fli_closefocuser(){
DBG("FOCUSER CLOSE");
camt_free(&focz, FLIfocus.Ndevices, focdev);
}
static void fli_closewheel(){
DBG("WHEEL CLOSE");
camt_free(&whlz, FLIwheel.Ndevices, whldev);
}
static int fli_ffalse(_U_ float f){ return FALSE; }
static int fli_fpfalse(_U_ float *f){ return FALSE; }
/*
* Global objects: camera, focuser and wheel
*/
Camera FLIcam = {
.check = fli_findCCD,
.setDevNo = fli_setActiceCam,
.close = fli_closecam,
.pollcapture = fli_pollcapt,
.capture = fli_capt,
.cancel = fli_cancel,
.setbin = fli_setbin,
.setgeometry = fli_setgeometry,
.setnflushes = fli_setnflushes,
.setT = fli_settemp,
.setio = fli_setio,
.setexp = fli_setexp,
.setframetype = fli_setframetype,
.setbitdepth = fli_setbitdepth,
.setfastspeed = fli_setfastspeed,
.setfanspeed = fli_setfanspd,
.shuttercmd = fli_shutter,
.confio = fli_confio,
.getModelName = fli_modelname,
.getbin = fli_getbin,
.getTcold = fli_getTcold,
.getThot = fli_getThot,
.getTbody = fli_getTbody,
.getio = fli_getio,
.getgeomlimits = fli_geomlimits,
.setbrightness = fli_ffalse,
.setgain = fli_ffalse,
.getmaxgain = fli_fpfalse,
};
Focuser FLIfocus = {
.check = fli_findFocuser,
.setDevNo = fli_setActiceFocuser,
.close = fli_closefocuser,
.getModelName = fli_fgetmodel,
.getTbody = fli_fgett,
.getPos = fli_fgetpos,
.getMaxPos = fli_fgetmaxpos,
.getMinPos = fli_fgetminpos,
.home = fli_fhome,
.setAbsPos = fli_fgoto,
};
Wheel FLIwheel = {
.check = fli_findWheel,
.setDevNo = fli_setActiceWheel,
.close = fli_closewheel,
.getModelName = fli_wgetname,
.getMaxPos = fli_wgetmaxpos,
.getPos = fli_wgetpos,
.setPos = fli_wsetpos,
.getTbody = fli_wgett,
};

29
FLI_cameras/flifunc.h Normal file
View File

@ -0,0 +1,29 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef FLIFUNC_H__
#define FLIFUNC_H__
#include "ccdfunc.h"
extern Camera FLIcam;
extern Focuser FLIfocus;
extern Wheel FLIwheel;
#endif // FLIFUNC_H__

67
FindCFITSIO.cmake Normal file
View File

@ -0,0 +1,67 @@
# - Try to find CFITSIO
# Once done this will define
#
# CFITSIO_FOUND - system has CFITSIO
# CFITSIO_INCLUDE_DIR - the CFITSIO include directory
# CFITSIO_LIBRARIES - Link these to use CFITSIO
# CFITSIO_VERSION_STRING - Human readable version number of cfitsio
# CFITSIO_VERSION_MAJOR - Major version number of cfitsio
# CFITSIO_VERSION_MINOR - Minor version number of cfitsio
# Copyright (c) 2006, Jasem Mutlaq <mutlaqja@ikarustech.com>
# Based on FindLibfacile by Carsten Niehaus, <cniehaus@gmx.de>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
# in cache already, be quiet
set(CFITSIO_FIND_QUIETLY TRUE)
else (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
# JM: Packages from different distributions have different suffixes
find_path(CFITSIO_INCLUDE_DIR fitsio.h
PATH_SUFFIXES libcfitsio3 libcfitsio0 cfitsio
PATHS
$ENV{CFITSIO}
${_obIncDir}
${GNUWIN32_DIR}/include
)
find_library(CFITSIO_LIBRARIES NAMES cfitsio
PATHS
$ENV{CFITSIO}
${_obLinkDir}
${GNUWIN32_DIR}/lib
)
if(CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
set(CFITSIO_FOUND TRUE)
else (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
set(CFITSIO_FOUND FALSE)
endif(CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
if (CFITSIO_FOUND)
# Find the version of the cfitsio header
FILE(READ "${CFITSIO_INCLUDE_DIR}/fitsio.h" FITSIO_H)
STRING(REGEX REPLACE ".*#define CFITSIO_VERSION[^0-9]*([0-9]+)\\.([0-9]+).*" "\\1.\\2" CFITSIO_VERSION_STRING "${FITSIO_H}")
STRING(REGEX REPLACE "^([0-9]+)[.]([0-9]+)" "\\1" CFITSIO_VERSION_MAJOR ${CFITSIO_VERSION_STRING})
STRING(REGEX REPLACE "^([0-9]+)[.]([0-9]+)" "\\2" CFITSIO_VERSION_MINOR ${CFITSIO_VERSION_STRING})
message(STATUS "found version string ${CFITSIO_VERSION_STRING}")
if (NOT CFITSIO_FIND_QUIETLY)
message(STATUS "Found CFITSIO ${CFITSIO_VERSION_MAJOR}.${CFITSIO_VERSION_MINOR}: ${CFITSIO_LIBRARIES}")
endif (NOT CFITSIO_FIND_QUIETLY)
else (CFITSIO_FOUND)
if (CFITSIO_FIND_REQUIRED)
message(STATUS "CFITSIO not found.")
endif (CFITSIO_FIND_REQUIRED)
endif (CFITSIO_FOUND)
mark_as_advanced(CFITSIO_INCLUDE_DIR CFITSIO_LIBRARIES)
endif (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)

View File

@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.20)
set(CCDLIB zwo_module)
set(ZWOLIB ${CCDLIB} PARENT_SCOPE)
find_package(PkgConfig REQUIRED)
pkg_check_modules(${CCDLIB} REQUIRED usefull_macros)
set(CFLAGS -O3 -Wextra -Wall -W -std=gnu99)
set(CMAKE_COLOR_MAKEFILE ON)
if(DEFINED DEBUG AND DEBUG STREQUAL "yes")
set(CFLAGS ${CFLAGS} -Werror)
add_definitions(-DEBUG)
set(CMAKE_VERBOSE_MAKEFILE "ON")
endif()
add_definitions(${CFLAGS})
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC)
add_library(${CCDLIB} ${SRC})
target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES} -lASICamera2)
include_directories(${${CCDLIB}_INCLUDE_DIRS} ..)
link_directories(${${CCDLIB}_LIBRARY_DIRS})

23
ZWO_cameras/zwofunc.c Normal file
View File

@ -0,0 +1,23 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "zwofunc.h"
Camera ZWOcam;
Focuser ZWOfocus;
Wheel ZWOwheel;

29
ZWO_cameras/zwofunc.h Normal file
View File

@ -0,0 +1,29 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef ZWOFUNC_H__
#define ZWOFUNC_H__
#include "ccdfunc.h"
extern Camera ZWOcam;
extern Focuser ZWOfocus;
extern Wheel ZWOwheel;
#endif // ZWOFUNC_H__

657
ccdfunc.c Normal file
View File

@ -0,0 +1,657 @@
/*
* This file is part of the FLI_control project.
* Copyright 2020 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <fcntl.h>
#include <fitsio.h>
#include <limits.h>
#include <math.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "ccdfunc.h"
#include "cmdlnopts.h"
#ifdef USEFLI
#include "flifunc.h"
#endif
#ifdef USEZWO
#include "zwofunc.h"
#endif
#ifdef IMAGEVIEW
#include "imageview.h"
#endif
Camera *camera = NULL;
Focuser *focuser = NULL;
Wheel *wheel = NULL;
static int fitserror = 0;
#define TRYFITS(f, ...) \
do{ int status = 0; \
f(__VA_ARGS__, &status); \
if(status){ \
fits_report_error(stderr, status); \
fitserror = status;} \
}while(0)
#define WRITEKEY(...) \
do{ int status = 0; \
fits_write_key(__VA_ARGS__, &status); \
if(status) fits_report_error(stderr, status);\
}while(0)
#define TMBUFSIZ 40
/*
static size_t curtime(char *s_time){ // current date/time
time_t tm = time(NULL);
return strftime(s_time, TMBUFSIZ, "%d/%m/%Y,%H:%M:%S", localtime(&tm));
}*/
static int check_filename(char *buff, char *outfile, char *ext){
struct stat filestat;
int num;
for(num = 1; num < 10000; num++){
if(snprintf(buff, PATH_MAX, "%s_%04d.%s", outfile, num, ext) < 1)
return 0;
if(stat(buff, &filestat)) // no such file or can't stat()
return 1;
}
return 0;
}
/**
* @brief addrec - add FITS records from file
* @param f (i) - FITS filename
* @param filename (i) - name of file
*/
static void addrec(fitsfile *f, char *filename){
FILE *fp = fopen(filename, "r");
if(!fp) return;
char buf[2*FLEN_CARD];
while(fgets(buf, 2*FLEN_CARD, fp)){
//DBG("check record _%s_", buf);
int keytype, status = 0;
char newcard[FLEN_CARD], keyname[FLEN_CARD];
fits_parse_template(buf, newcard, &keytype, &status);
if(status){
fits_report_error(stderr, status);
continue;
}
//DBG("reformatted to _%s_", newcard);
strncpy(keyname, newcard, FLEN_CARD);
char *eq = strchr(keyname, '='); if(eq) *eq = 0;
eq = strchr(keyname, ' '); if(eq) *eq = 0;
//DBG("keyname: %s", keyname);
fits_update_card(f, keyname, newcard, &status);
}
}
void saveFITS(IMG *img, char *filename){
char buff[PATH_MAX];
if(filename == NULL) return;
fitserror = 0;
if(!check_filename(buff, filename, "fits") && !GP->rewrite){
// îÅ ÍÏÇÕ ÓÏÈÒÁÎÉÔØ ÆÁÊÌ
WARNX(_("Can't save file"));
}else{
if(GP->rewrite){
DBG("REW");
snprintf(buff, PATH_MAX, "!%s.fits", filename);
}
}
int width = img->w, height = img->h;
void *data = (void*) img->data;
long naxes[2] = {width, height}, tmpl;
double tmpd = 0.0;
float tmpf = 0.0;
int tmpi = 0;
struct tm *tm_time;
char bufc[FLEN_CARD];
time_t savetime = time(NULL);
fitsfile *fp;
TRYFITS(fits_create_file, &fp, buff);
if(fitserror) goto cloerr;
TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes);
if(fitserror) goto cloerr;
// FILE / Input file original name
WRITEKEY(fp, TSTRING, "FILE", filename, "Input file original name");
// ORIGIN / organization responsible for the data
WRITEKEY(fp, TSTRING, "ORIGIN", "SAO RAS", "organization responsible for the data");
// OBSERVAT / Observatory name
WRITEKEY(fp, TSTRING, "OBSERVAT", "Special Astrophysical Observatory, Russia", "Observatory name");
// DETECTOR / detector
if(camera->getModelName(buff, PATH_MAX)){
WRITEKEY(fp, TSTRING, "DETECTOR", buff, "Detector model");
}
// INSTRUME / Instrument
if(GP->instrument){
WRITEKEY(fp, TSTRING, "INSTRUME", GP->instrument, "Instrument");
}else
WRITEKEY(fp, TSTRING, "INSTRUME", "direct imaging", "Instrument");
snprintf(bufc, FLEN_VALUE, "%.g x %.g", camera->pixX, camera->pixY);
// PXSIZE / pixel size
WRITEKEY(fp, TSTRING, "PXSIZE", bufc, "Pixel size in m");
snprintf(bufc, FLEN_VALUE, "(%d, %d)(%d, %d)", camera->field.xoff, camera->field.yoff,
camera->field.xoff + camera->field.w, camera->field.yoff + camera->field.h);
WRITEKEY(fp, TSTRING, "VIEWFLD", bufc, "Camera field of view");
snprintf(bufc, FLEN_VALUE, "(%d, %d)(%d, %d)", camera->array.xoff, camera->array.yoff,
camera->array.xoff + camera->array.w, camera->array.yoff + camera->array.h);
WRITEKEY(fp, TSTRING, "ARRAYFLD", bufc, "Camera full array size");
// CRVAL1, CRVAL2 / Offset in X, Y
if(GP->X0 > -1) WRITEKEY(fp, TINT, "X0", &GP->X0, "Subframe left border");
if(GP->Y0 > -1) WRITEKEY(fp, TINT, "Y0", &GP->Y0, "Subframe upper border");
if(GP->objtype) strncpy(bufc, GP->objtype, FLEN_CARD-1);
else sprintf(bufc, "object");
// IMAGETYP / object, flat, dark, bias, scan, eta, neon, push
WRITEKEY(fp, TSTRING, "IMAGETYP", bufc, "Image type");
// DATAMAX, DATAMIN / Max, min pixel value
tmpi = 0;
WRITEKEY(fp, TINT, "DATAMIN", &tmpi, "Min pixel value");
//itmp = GP->fast ? 255 : 65535;
tmpi = 65535;
WRITEKEY(fp, TINT, "DATAMAX", &tmpi, "Max pixel value");
tmpi = img->min;
WRITEKEY(fp, TUSHORT, "STATMIN", &tmpi, "Min data value");
tmpi = img->max;
WRITEKEY(fp, TUSHORT, "STATMAX", &tmpi, "Max data value");
tmpf = img->avr;
WRITEKEY(fp, TFLOAT, "STATAVR", &tmpf, "Average data value");
tmpf = img->std;
WRITEKEY(fp, TFLOAT, "STATSTD", &tmpf, "Std. of data value");
WRITEKEY(fp, TFLOAT, "CAMTEMP0", &GP->temperature, "Camera temperature at exp. start, degr C");
if(camera->getTcold(&tmpf))
WRITEKEY(fp, TFLOAT, "CAMTEMP", &tmpf, "Camera temperature at exp. end, degr C");
if(camera->getTbody(&tmpf))
WRITEKEY(fp, TFLOAT, "BODYTEMP", &tmpf, "Camera body temperature at exp. end, degr C");
if(camera->getThot(&tmpf))
WRITEKEY(fp, TFLOAT, "HOTTEMP", &tmpf, "Camera peltier hot side temperature at exp. end, degr C");
// EXPTIME / actual exposition time (sec)
tmpd = GP->exptime;
WRITEKEY(fp, TDOUBLE, "EXPTIME", &tmpd, "Actual exposition time (sec)");
// DATE / Creation date (YYYY-MM-DDThh:mm:ss, UTC)
strftime(bufc, FLEN_VALUE, "%Y-%m-%dT%H:%M:%S", gmtime(&savetime));
WRITEKEY(fp, TSTRING, "DATE", bufc, "Creation date (YYYY-MM-DDThh:mm:ss, UTC)");
tmpl = (long) savetime;
tm_time = localtime(&savetime);
strftime(bufc, FLEN_VALUE, "File creation time (UNIX)", tm_time);
WRITEKEY(fp, TLONG, "UNIXTIME", &tmpl, bufc);
strftime(bufc, 80, "%Y/%m/%d", tm_time);
// DATE-OBS / DATE (YYYY/MM/DD) OF OBS.
WRITEKEY(fp, TSTRING, "DATE-OBS", bufc, "DATE OF OBS. (YYYY/MM/DD, local)");
strftime(bufc, 80, "%H:%M:%S", tm_time);
WRITEKEY(fp, TSTRING, "TIME", bufc, "Creation time (hh:mm:ss, local)");
// OBJECT / Object name
if(GP->objname){
WRITEKEY(fp, TSTRING, "OBJECT", GP->objname, "Object name");
}
// BINNING / Binning
if(GP->hbin != 1 || GP->vbin != 1){
snprintf(bufc, 80, "%d x %d", GP->hbin, GP->vbin);
WRITEKEY(fp, TSTRING, "BINNING", bufc, "Binning (hbin x vbin)");
}
// OBSERVER / Observers
if(GP->observers){
WRITEKEY(fp, TSTRING, "OBSERVER", GP->observers, "Observers");
}
// PROG-ID / Observation program identifier
if(GP->prog_id){
WRITEKEY(fp, TSTRING, "PROG-ID", GP->prog_id, "Observation program identifier");
}
// AUTHOR / Author of the program
if(GP->author){
WRITEKEY(fp, TSTRING, "AUTHOR", GP->author, "Author of the program");
}
if(focuser){ // there is a focuser device - add info
if(focuser->getModelName(buff, PATH_MAX))
WRITEKEY(fp, TSTRING, "FOCUSER", buff, "Focuser model");
if(focuser->getPos(&tmpf))
WRITEKEY(fp, TFLOAT, "FOCUS", &tmpf, "Current focuser position, mm");
if(focuser->getMinPos(&tmpf))
WRITEKEY(fp, TFLOAT, "FOCMIN", &tmpf, "Minimal focuser position, mm");
if(focuser->getMaxPos(&tmpf))
WRITEKEY(fp, TFLOAT, "FOCMAX", &tmpf, "Maximal focuser position, mm");
if(focuser->getTbody(&tmpf))
WRITEKEY(fp, TFLOAT, "FOCTEMP", &tmpf, "Focuser body temperature, degr C");
}
if(wheel){ // there is a filter wheel device - add info
if(wheel->getModelName(buff, PATH_MAX))
WRITEKEY(fp, TSTRING, "WHEEL", buff, "Filter wheel model");
if(wheel->getPos(&tmpi))
WRITEKEY(fp, TINT, "FILTER", &tmpi, "Current filter number");
if(wheel->getMaxPos(&tmpi))
WRITEKEY(fp, TINT, "FILTMAX", &tmpi, "Amount of filter positions");
if(wheel->getTbody(&tmpf))
WRITEKEY(fp, TFLOAT, "FILTTEMP", &tmpf, "Filter wheel body temperature, degr C");
}
if(GP->addhdr){ // add records from files
char **nxtfile = GP->addhdr;
while(*nxtfile){
addrec(fp, *nxtfile++);
}
}
TRYFITS(fits_write_img, fp, TUSHORT, 1, width * height, data);
if(fitserror) goto cloerr;
TRYFITS(fits_close_file, fp);
cloerr:
if(fitserror == 0){
verbose(1, _("File saved as '%s'"), buff);
}else{
WARNX(_("Error saving file"));
fitserror = 0;
}
}
static void print_stat(IMG *image){
long i, Noverld = 0L, size = image->h*image->w;
float pv, sum=0., sum2=0., sz = (float)size;
uint16_t *ptr = image->data, val;
uint16_t max = 0, min = 65535;
for(i = 0; i < size; i++, ptr++){
val = *ptr;
pv = (float) val;
sum += pv;
sum2 += (pv * pv);
if(max < val) max = val;
if(min > val) min = val;
if(val >= 65530) Noverld++;
}
// óÔÁÔÉÓÔÉËÁ ÐÏ ÉÚÏÂÒÁÖÅÎÉÀ:\n
printf(_("Image stat:\n"));
float avr = sum/sz;
printf("avr = %.1f, std = %.1f, Noverload = %ld\n", image->avr = avr,
image->std = sqrt(fabs(sum2/sz - avr*avr)), Noverld);
printf("max = %u, min = %u, size = %ld\n", max, min, size);
}
/*
* Find focusers and work with each of them
*/
void focusers(){
if(!GP->focuserdev){
verbose(3, _("Focuser device not pointed, try to guess"));
#ifdef USEFLI
if(FLIfocus.check()) focuser = &FLIfocus;
#endif
#ifdef USEZWO
if(ZWOfocus.check()) focuser = &ZWOfocus;
#endif
}else{
#ifdef USEFLI
if(strcasecmp(GP->focuserdev, "fli") == 0) focuser = &FLIfocus;
#endif
#ifdef USEZWO
if(strcasecmp(GP->focuserdev, "zwo") == 0) focuser = &ZWOfocus;
#endif
}
if(!focuser){
WARNX(_("Focuser not found"));
return;
}
int num = GP->focdevno;
if(num > focuser->Ndevices - 1){
WARNX(_("Found %d focusers, you point number %d"), focuser->Ndevices, num);
goto retn;
}
if(!focuser->setDevNo(num)){
WARNX(_("Can't set active focuser number"));
goto retn;
}
char buf[BUFSIZ];
if(focuser->getModelName(buf, BUFSIZ)){
verbose(2, "Focuser model: %s", buf);
}
float t;
if(focuser->getTbody(&t)){
verbose(1, "FOCTEMP=%.1f", t);
DBG("FOCTEMP=%.1f", t);
}
float minpos, maxpos, curpos;
if(!focuser->getMinPos(&minpos) || !focuser->getMaxPos(&maxpos)){
WARNX(_("Can't get focuser limit positions"));
goto retn;
}
verbose(1, "FOCMINPOS=%g", minpos);
verbose(1, "FOCMAXPOS=%g", maxpos);
DBG("FOCMINPOS=%g, FOCMAXPOS=%g", minpos, maxpos);
if(!focuser->getPos(&curpos)){
WARNX(_("Can't get current focuser position"));
goto retn;
}
verbose(1, "FOCPOS=%g", curpos);
DBG("Curpos = %g", curpos);
if(isnan(GP->gotopos) && isnan(GP->addsteps)) goto retn; // no focuser commands
float tagpos = 0.;
if(!isnan(GP->gotopos)){ // set absolute position
tagpos = GP->gotopos;
}else{ // relative
tagpos = curpos + GP->addsteps;
}
DBG("tagpos: %g", tagpos);
if(tagpos < minpos || tagpos > maxpos){
WARNX(_("Can't set position %g: out of limits [%g, %g]"), tagpos, minpos, maxpos);
goto retn;
}
if(tagpos - minpos < __FLT_EPSILON__){
if(!focuser->home(GP->async)) WARNX(_("Can't home focuser"));
}else{
if(!focuser->setAbsPos(GP->async, tagpos)) WARNX(_("Can't set position %g"), tagpos);
}
retn:
focuser->close();
focuser = NULL;
}
/*
* Find wheels and work with each of them
*/
void wheels(){
if(!GP->wheeldev){
verbose(3, _("Wheel device not pointed, try to guess"));
#ifdef USEFLI
if(FLIwheel.check()) wheel = &FLIwheel;
#endif
#ifdef USEZWO
if(ZWOwheel.check()) wheel = &ZWOwheel;
#endif
}else{
#ifdef USEFLI
if(strcasecmp(GP->wheeldev, "fli") == 0) wheel = &FLIwheel;
#endif
#ifdef USEZWO
if(strcasecmp(GP->wheeldev, "zwo") == 0) wheel = &ZWOwheel;
#endif
}
if(!wheel){
WARNX(_("Wheel not found"));
return;
}
int num = GP->whldevno;
if(num > wheel->Ndevices - 1){
WARNX(_("Found %d wheels, you point number %d"), wheel->Ndevices, num);
goto retn;
}
if(!wheel->setDevNo(num)){
WARNX(_("Can't set active wheel number"));
goto retn;
}
float t;
if(wheel->getTbody(&t)){
verbose(1, "WHEELTEMP=%.1f", t);
}
int pos, maxpos;
if(wheel->getPos(&pos)){
verbose(1, "WHEELPOS=%d", pos);
}else WARNX("Can't get current wheel position");
if(!wheel->getMaxPos(&maxpos)){
WARNX(_("Can't get max wheel position"));
goto retn;
}
verbose(1, "WHEELMAXPOS=%d", maxpos);
pos = GP->setwheel;
if(pos == -1) goto retn; // no wheel commands
if(pos < 0 || pos > maxpos){
WARNX(_("Wheel position should be from 0 to %d"), maxpos);
goto retn;
}
if(!wheel->setPos(pos))
WARNX(_("Can't set wheel position %d"), pos);
retn:
wheel->close();
wheel = NULL;
}
static void closeall(){
if(camera){camera->close(); camera = NULL;}
if(focuser){focuser->close(); focuser = NULL;}
if(wheel){wheel->close(); wheel = NULL;}
}
/*
* Find CCDs and work with each of them
*/
void ccds(){
float tmpf;
int tmpi;
if(!GP->cameradev){
verbose(3, _("Camera device not pointed, try to guess"));
#ifdef USEFLI
if(FLIcam.check()) camera = &FLIcam;
#endif
#ifdef USEZWO
if(ZWOcam.check()) camera = &ZWOcam;
#endif
}else{
#ifdef USEFLI
if(strcasecmp(GP->cameradev, "fli") == 0) camera = &FLIcam;
#endif
#ifdef USEZWO
if(strcasecmp(GP->cameradev, "zwo") == 0) camera = &ZWOcam;
#endif
}
if(!camera){
WARNX(_("Camera device not found"));
goto retn;
}
int num = GP->camdevno;
if(num > camera->Ndevices - 1){
WARNX(_("Found %d cameras, you point number %d"), camera->Ndevices, num);
goto retn;
}
if(!camera->setDevNo(num)){
WARNX(_("Can't set active camera number"));
goto retn;
}
if(GP->fanspeed > -1){
if(GP->fanspeed > FAN_HIGH) GP->fanspeed = FAN_HIGH;
if(!camera->setfanspeed((fan_speed)GP->fanspeed))
WARNX(_("Can't set fan speed"));
}
int x0,x1, y0,y1;
char buf[BUFSIZ];
if(camera->getModelName(buf, BUFSIZ))
verbose(2, _("Camera model: %s"), buf);
verbose(2, _("Pixel size: %g x %g"), camera->pixX, camera->pixY);
x0 = camera->array.xoff;
y0 = camera->array.yoff;
x1 = camera->array.xoff + camera->array.w;
y1 = camera->array.yoff + camera->array.h;
snprintf(buf, BUFSIZ, "(%d, %d)(%d, %d)", x0, y0, x1, y1);
verbose(2, _("Full array: %s"), buf);
snprintf(buf, BUFSIZ, "(%d, %d)(%d, %d)", camera->field.xoff, camera->field.yoff,
camera->field.xoff + camera->field.w, camera->field.yoff + camera->field.h);
verbose(2, _("Field of view: %s"), buf);
if(GP->temperature < 40.){
if(!camera->setT((float)GP->temperature))
WARNX(_("Can't set T to %g degC"), GP->temperature);
verbose(3, "SetT=%.1f", GP->temperature);
}
if(camera->getTcold(&tmpf)) verbose(1, "CCDTEMP=%.1f", tmpf);
if(camera->getTbody(&tmpf)) verbose(1, "BODYTEMP=%.1f", tmpf);
if(GP->shtr_cmd > -1 && GP->shtr_cmd < SHUTTER_AMOUNT){
const char *str[] = {"open", "close", "expose @high", "expose @low"};
verbose(1, _("Shutter command: %s\n"), str[GP->shtr_cmd]);
if(!camera->shuttercmd((shutter_op)GP->shtr_cmd))
WARNX(_("Can't run shutter command %s (unsupported?)"), str[GP->shtr_cmd]);
}
if(GP->confio > -1){
// "ðÏÐÙÔËÁ ÓËÏÎÆÉÇÕÒÉÒÏ×ÁÔØ ÐÏÒÔ I/O ËÁË %d\n"
verbose(1, _("Try to convfigure I/O port as %d"), GP->confio);
if(!camera->confio(GP->confio))
WARNX(_("Can't configure (unsupported?)"));
}
if(GP->getio){
if(camera->getio(&tmpi))
verbose(1, "CCDIOPORT=9x%02x\n", tmpi);
else
WARNX(_("Can't get IOport state (unsupported?)"));
}
if(GP->setio > -1){
// "ðÏÐÙÔËÁ ÚÁÐÉÓÉ %d × ÐÏÒÔ I/O\n"
verbose(1, _("Try to write %d to I/O port"), GP->setio);
if(!camera->setio(GP->setio))
WARNX(_("Can't set IOport"));
}
if(GP->exptime < 0.) goto retn;
/*********************** expose control ***********************/
#ifdef IMAGEVIEW
windowData *mainwin = NULL;
if(GP->showimage) imageview_init();
#endif
// cancel previous exp
camera->cancel();
int binh = 1, binv = 1;
if(!camera->setbin(GP->hbin, GP->vbin))
WARNX(_("Can't set binning %dx%d"), GP->hbin, GP->vbin);
if(!camera->getbin(&binh, &binv))
WARNX(_("Can't get current binning"));
verbose(2, "Binning: %d x %d", binh, binv);
if(GP->fullframe){
DBG("FULLFRAME");
GP->X0 = x0; GP->Y0 = y0; GP->X1 = x1; GP->Y1 = y1;
}
if(GP->X0 == -1) GP->X0 = x0; // default values
if(GP->Y0 == -1) GP->Y0 = y0;
if(GP->X1 == -1) GP->X1 = x1;
else if(GP->X1 > x1) GP->X1 = x1;
if(GP->Y1 == -1) GP->Y1 = y1;
else if(GP->Y1 > y1) GP->Y1 = y1;
frameformat fmt = {.w = GP->X1 - GP->X0, .h = GP->Y1 - GP->Y0, .xoff = GP->X0, .yoff = GP->Y0};
int raw_width = fmt.w / binh, raw_height = fmt.h / binv;
if(!camera->setgeometry(&fmt))
WARNX(_("Can't set given geometry"));
verbose(3, "Geometry: off=%d/%d, wh=%d/%d", fmt.xoff, fmt.yoff, fmt.w, fmt.h);
if(!camera->setnflushes(GP->nflushes))
WARNX(_("Can't set %d flushes"), GP->nflushes);
verbose(3, "Nflushes=%d", GP->nflushes);
if(!camera->setexp(GP->exptime))
WARNX(_("Can't set exposure time to %f seconds"), GP->exptime);
tmpi = (GP->dark) ? 0 : 1;
if(!camera->setframetype(tmpi))
WARNX(_("Can't change frame type"));
tmpi = (GP->_8bit) ? 0 : 1;
if(!camera->setbitdepth(tmpi))
WARNX(_("Can't set bit depth"));
tmpi = (GP->fast) ? 1 : 0;
if(!camera->setfastspeed(tmpi))
WARNX(_("Can't set readout speed"));
else if(GP->fast) verbose(1, _("Fast readout mode"));
if(!GP->outfile) verbose(1, _("Only show statistics"));
uint16_t *img = MALLOC(uint16_t, raw_width * raw_height);
IMG ima = {.data = img, .w = raw_width, .h = raw_height};
for(int j = 0; j < GP->nframes; ++j){
verbose(1, "\n\n");
// úÁÈ×ÁÔ ËÁÄÒÁ %d\n
verbose(1, _("Capture frame %d\n"), j);
capture_status cs;
float tleave = 1.;
while(camera->pollcapture(&cs, &tleave)){
if(cs != CAPTURE_PROCESS) break;
verbose(2, _("%.1f seconds till exposition ends"), tleave);
if(camera->getTcold(&tmpf)) verbose(1, "CCDTEMP=%.1f", tmpf);
if(camera->getTbody(&tmpf)) verbose(1, "BODYTEMP=%.1f", tmpf);
if(tleave > 6.) sleep(5);
else if(tleave > 0.9) sleep((int)(tleave+0.99));
else usleep((int)(1e6*tleave) + 99999);
}
if(cs != CAPTURE_READY){
WARNX(_("Can't capture image"));
break;
}
verbose(2, _("Read grabbed image"));
if(!camera->capture(&ima)){
WARNX(_("Can't grab image"));
break;
}
print_stat(&ima);
saveFITS(&ima, GP->outfile);
#ifdef IMAGEVIEW
if(GP->showimage){ // display image
if(!(mainwin = getWin())){
DBG("Create new win");
mainwin = createGLwin("Sample window", raw_width, raw_height, NULL);
if(!mainwin){
WARNX(_("Can't open OpenGL window, image preview will be inaccessible"));
}else
pthread_create(&mainwin->thread, NULL, &image_thread, (void*)&ima);
}
if((mainwin = getWin())){
DBG("change image");
change_displayed_image(mainwin, &ima);
while((mainwin = getWin())){ // test paused state & grabbing custom frames
if((mainwin->winevt & WINEVT_PAUSE) == 0) break;
if(mainwin->winevt & WINEVT_GETIMAGE){
mainwin->winevt &= ~WINEVT_GETIMAGE;
if(!camera->capture(&ima)){
WARNX(_("Can't grab image"));
}
change_displayed_image(mainwin, &ima);
}
usleep(10000);
}
}
}
#endif
if(GP->pause_len && j != (GP->nframes - 1)){
double delta, time1 = dtime() + GP->pause_len;
while((delta = time1 - dtime()) > 0.){
// %d ÓÅËÕÎÄ ÄÏ ÏËÏÎÞÁÎÉÑ ÐÁÕÚÙ\n
verbose(1, _("%d seconds till pause ends\n"), (int)delta);
if(camera->getTcold(&tmpf)) verbose(1, "CCDTEMP=%.1f\n", tmpf);
if(camera->getTbody(&tmpf)) verbose(1, "BODYTEMP=%.1f\n", tmpf);
if(delta > 10) sleep(10);
else usleep((int)(delta*1e6 + 1));
}
}
}
#ifdef IMAGEVIEW
if(GP->showimage){
mainwin->winevt |= WINEVT_PAUSE;
DBG("Waiting");
while((mainwin = getWin())){
if(mainwin->killthread) break;
if(mainwin->winevt & WINEVT_GETIMAGE){
DBG("GRAB");
mainwin->winevt &= ~WINEVT_GETIMAGE;
if(!camera->capture(&ima)){
WARNX(_("Can't grab image"));
}
change_displayed_image(mainwin, &ima);
}
}
DBG("Close window");
usleep(10000);
}
#endif
FREE(img);
retn:
camera->close();
camera = NULL;
}
void cancel(){
if(camera){
camera->cancel();
}
closeall();
}

140
ccdfunc.h Normal file
View File

@ -0,0 +1,140 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef CCDFUNC_H__
#define CCDFUNC_H__
#include <stdint.h>
typedef struct{
uint16_t *data; // image data
int w, h; // image size
uint16_t max, min; // min/max values
float avr, std; // statistics
} IMG;
// format of single frame
typedef struct{
int w; int h; // width & height
int xoff; int yoff; // X and Y offset
} frameformat;
typedef enum{
SHUTTER_OPEN, // open shutter now
SHUTTER_CLOSE, // close shutter now
SHUTTER_OPENATLOW, // ext. expose control @low
SHUTTER_OPENATHIGH, // -//- @high
SHUTTER_AMOUNT, // amount of entries
} shutter_op;
typedef enum{
CAPTURE_NO, // no capture initiated
CAPTURE_PROCESS, // in progress
CAPTURE_CANTSTART, // can't start
CAPTURE_ABORTED, // some error - aborted
CAPTURE_READY, // ready - user can read image
} capture_status;
typedef enum{
FAN_OFF,
FAN_LOW,
FAN_HIGH,
} fan_speed;
// all setters and getters of Camera, Focuser and Wheel should return TRUE if success or FALSE if failed or unsupported
// camera
typedef struct{
int (*check)(); // check if the device is available, connect and init
int Ndevices; // amount of devices found
void (*close)(); // disconnect & close device
int (*pollcapture)(capture_status *st, float *remain);// start or poll capture process, `remain` - time remain (s)
int (*capture)(IMG *ima); // capture an image, struct `ima` should be prepared before
void (*cancel)(); // cancel exposition
// setters:
int (*setDevNo)(int n); // set active device number
int (*setbrightness)(float b);
int (*setexp)(float e);
int (*setgain)(float g);
int (*setT)(float t);
int (*setbin)(int binh, int binv); // binning
int (*setnflushes)(int N); // flushes amount
int (*shuttercmd)(shutter_op s); // work with shutter
int (*confio)(int s); // configure IO-port
int (*setio)(int s); // set IO-port to given state
int (*setframetype)(int l); // set frametype: 1 - light, 0 - dark
int (*setbitdepth)(int h); // set bit depth: 1 - high, 0 - low
int (*setfastspeed)(int s); // set readout speed: 1 - fast, 0 - low
// geometry (if TRUE, all args are changed to suitable values)
int (*setgeometry)(frameformat *fmt); // set geometry in UNBINNED coordinates
int (*setfanspeed)(fan_speed spd); // set fan speed
// getters:
int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes)
int (*getmaxgain)(float *g);// get max available gain value
// get limits of geometry: maximal values and steps
int (*getgeomlimits)(frameformat *max, frameformat *step);
int (*getTcold)(float *t); // cold-side T
int (*getThot)(float *t); // hot-side T
int (*getTbody)(float *t); // body T
int (*getbin)(int *binh, int *binv);
int (*getio)(int *s); // get IO-port state
float pixX, pixY; // pixel size in um
frameformat field; // max field of view
frameformat array; // array format
frameformat geometry; // current geometry settings (as in setgeometry)
} Camera;
// focuser
typedef struct{
int (*check)(); // check if the device is available
int Ndevices;
void (*close)();
// setters:
int (*setDevNo)(int n); // set active device number
int (*setAbsPos)(int async, float n);// set absolute position (in millimeters!!!)
int (*home)(int async); // home device
// getters:
int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes)
int (*getTbody)(float *t); // body T
int (*getPos)(float *p); // current position number (starting from zero)
int (*getMaxPos)(float *p); // max position
int (*getMinPos)(float *p); // min position
} Focuser;
// wheel
typedef struct{
int (*check)(); // check if the device is available
int Ndevices;
void (*close)();
// setters:
int (*setDevNo)(int n); // set active device number
int (*setPos)(int n); // set absolute position (starting from 0)
// getters:
int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes)
int (*getTbody)(float *t); // body T
int (*getPos)(int *p); // current position number (starting from zero)
int (*getMaxPos)(int *p); // amount of positions
} Wheel;
void saveFITS(IMG *img, char *filename); // for imageview module
void focusers();
void wheels();
void ccds();
void cancel();
#endif // CCDFUNC_H__

167
cmdlnopts.c Normal file
View File

@ -0,0 +1,167 @@
/*
* cmdlnopts.c - the only function that parse cmdln args and returns glob parameters
*
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
*
* 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 <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <math.h>
#include <limits.h>
#include <libfli.h>
#include "cmdlnopts.h"
#include "usefull_macros.h"
#define RAD 57.2957795130823
#define D2R(x) ((x) / RAD)
#define R2D(x) ((x) * RAD)
/*
* here are global parameters initialisation
*/
static int help;
static glob_pars G;
glob_pars *GP = NULL;
// DEFAULTS
// default global parameters
glob_pars const Gdefault = {
.objtype = "object",
.instrument = "direct imaging",
.exptime = -1,
.nframes = 1,
.hbin = 1, .vbin = 1,
.X0 = -1, .Y0 = -1,
.X1 = -1, .Y1 = -1,
.temperature = 1e6,
.shtr_cmd = -1,
.confio = -1, .setio = -1,
.gotopos = NAN, .addsteps = NAN,
.setwheel = -1,
.fanspeed = -1,
.nflushes = 1
};
/*
* Define command line options by filling structure:
* name has_arg flag val type argptr help
*/
myoption cmdlnopts[] = {
{"cameradev", NEED_ARG, NULL, 'C', arg_string, APTR(&G.cameradev), N_("camera device type (fli/zwo/etc)")},
{"focuserdev", NEED_ARG,NULL, 'F', arg_string, APTR(&G.focuserdev),N_("focuser device type (fli/zwo/etc)")},
{"wheeldev", NEED_ARG, NULL, 'W', arg_string, APTR(&G.wheeldev), N_("wheel device type (fli/zwo/etc)")},
{"camdevno",NEED_ARG, NULL, 0, arg_int, APTR(&G.camdevno), N_("camera device number (if many: 0, 1, 2 etc)")},
{"wheeldevno",NEED_ARG, NULL, 0, arg_int, APTR(&G.whldevno), N_("filter wheel device number (if many: 0, 1, 2 etc)")},
{"focdevno",NEED_ARG, NULL, 0, arg_int, APTR(&G.focdevno), N_("focuser device number (if many: 0, 1, 2 etc)")},
{"help", NO_ARGS, &help, 1, arg_none, NULL, N_("show this help")},
{"rewrite", NO_ARGS, &G.rewrite,1, arg_none, NULL, N_("rewrite output file if exists")},
{"verbose", NO_ARGS, NULL, 'V', arg_none, APTR(&G.verbose), N_("verbose level (each -v increase it)")},
{"dark", NO_ARGS, NULL, 'd', arg_int, APTR(&G.dark), N_("not open shutter, when exposing (\"dark frames\")")},
{"8bit", NO_ARGS, NULL, '8', arg_int, APTR(&G._8bit), N_("run in 8-bit mode")},
{"fast", NO_ARGS, NULL, 'f', arg_int, APTR(&G.fast), N_("fast (8MHz) readout mode")},
{"set-temp",NEED_ARG, NULL, 't', arg_double, APTR(&G.temperature),N_("set CCD temperature to given value (degr C)")},
{"set-fan", NEED_ARG, NULL, 0, arg_int, APTR(&G.fanspeed), N_("set fan speed (0 - off, 1 - low, 2 - high)")},
{"author", NEED_ARG, NULL, 'A', arg_string, APTR(&G.author), N_("program author")},
{"objtype", NEED_ARG, NULL, 'Y', arg_string, APTR(&G.objtype), N_("object type (neon, object, flat etc)")},
{"instrument",NEED_ARG, NULL, 'I', arg_string, APTR(&G.instrument),N_("instrument name")},
{"object", NEED_ARG, NULL, 'O', arg_string, APTR(&G.objname), N_("object name")},
{"obsname", NEED_ARG, NULL, 'N', arg_string, APTR(&G.observers), N_("observers' names")},
{"prog-id", NEED_ARG, NULL, 'P', arg_string, APTR(&G.prog_id), N_("observing program name")},
{"addrec", MULT_PAR, NULL, 'r', arg_string, APTR(&G.addhdr), N_("add records to header from given file[s]")},
{"nflushes",NEED_ARG, NULL, 'l', arg_int, APTR(&G.nflushes), N_("N flushes before exposing (default: 1)")},
{"hbin", NEED_ARG, NULL, 'h', arg_int, APTR(&G.hbin), N_("horizontal binning to N pixels")},
{"vbin", NEED_ARG, NULL, 'v', arg_int, APTR(&G.vbin), N_("vertical binning to N pixels")},
{"nframes", NEED_ARG, NULL, 'n', arg_int, APTR(&G.nframes), N_("make series of N frames")},
{"pause", NEED_ARG, NULL, 'p', arg_int, APTR(&G.pause_len), N_("make pause for N seconds between expositions")},
{"exptime", NEED_ARG, NULL, 'x', arg_float, APTR(&G.exptime), N_("set exposure time to given value (ms)")},
{"X0", NEED_ARG, NULL, 0, arg_int, APTR(&G.X0), N_("frame X0 coordinate (-1 - all with overscan)")},
{"Y0", NEED_ARG, NULL, 0, arg_int, APTR(&G.Y0), N_("frame Y0 coordinate (-1 - all with overscan)")},
{"X1", NEED_ARG, NULL, 0, arg_int, APTR(&G.X1), N_("frame X1 coordinate (-1 - all with overscan)")},
{"Y1", NEED_ARG, NULL, 0, arg_int, APTR(&G.Y1), N_("frame Y1 coordinate (-1 - all with overscan)")},
{"fullframe",NO_ARGS, NULL, 0, arg_int, APTR(&G.fullframe), N_("grab full frame (with overscans)")},
{"open-shutter",NO_ARGS,&G.shtr_cmd, SHUTTER_OPEN,arg_none,NULL, N_("open shutter")},
{"close-shutter",NO_ARGS,&G.shtr_cmd, SHUTTER_CLOSE,arg_none,NULL, N_("close shutter")},
{"shutter-on-low",NO_ARGS,&G.shtr_cmd, SHUTTER_OPENATLOW,arg_none,NULL, N_("run exposition on LOW @ pin5 I/O port")},
{"shutter-on-high",NO_ARGS,&G.shtr_cmd,SHUTTER_OPENATHIGH,arg_none,NULL,N_("run exposition on HIGH @ pin5 I/O port")},
{"get-ioport",NO_ARGS, NULL, 'i', arg_int, APTR(&G.getio), N_("get value of I/O port pins")},
{"async", NO_ARGS, &G.async,1, arg_none, NULL, N_("move stepper motor asynchronous")},
{"set-ioport",NEED_ARG, NULL, 's', arg_int, APTR(&G.setio), N_("set I/O port pins to given value (decimal number, pin1 is LSB)")},
{"conf-ioport",NEED_ARG,NULL, 'c', arg_int, APTR(&G.confio), N_("configure I/O port pins to given value (decimal number, pin1 is LSB, 1 == output, 0 == input)")},
{"goto", NEED_ARG, NULL, 'g', arg_double, APTR(&G.gotopos), N_("move focuser to absolute position, mm")},
{"addsteps",NEED_ARG, NULL, 'a', arg_double, APTR(&G.addsteps), N_("move focuser to relative position, mm")},
{"wheel-set",NEED_ARG, NULL, 'w', arg_int, APTR(&G.setwheel), N_("set wheel position")},
#ifdef IMAGEVIEW
{"display", NO_ARGS, NULL, 'D', arg_int, APTR(&G.showimage), N_("Display image in OpenGL window")},
#endif
//{"", NEED_ARG, NULL, '', arg_double, APTR(&G.), N_("")},
end_option
};
/**
* Parse command line options and return dynamically allocated structure
* to global parameters
* @param argc - copy of argc from main
* @param argv - copy of argv from main
* @return allocated structure with global parameters
*/
glob_pars *parse_args(int argc, char **argv){
void *ptr;
ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr);
// format of help: "Usage: progname [args]\n"
change_helpstring("Usage: %s [args] <output file prefix>\n\n\tWhere args are:\n");
// parse arguments
parseargs(&argc, &argv, cmdlnopts);
if(help) showhelp(-1, cmdlnopts);
if(argc > 0){
G.outfile = strdup(argv[0]);
if(argc > 1){
WARNX("%d unused parameters:\n", argc - 1);
for(int i = 1; i < argc; ++i)
printf("\t%4d: %s\n", i, argv[i]);
}
}
GP = &G;
return GP;
}
/**
* @brief verbose - print additional messages depending of G.verbose
* @param levl - message level
* @param fmt - message
*/
void verbose(int levl, const char *fmt, ...){
va_list ar;
if(levl > G.verbose) return;
printf("%s: ", __progname);
va_start(ar, fmt);
vprintf(fmt, ar);
va_end(ar);
printf("\n");
}

81
cmdlnopts.h Normal file
View File

@ -0,0 +1,81 @@
/*
* cmdlnopts.h - comand line options for parceargs
*
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
*
* 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.
*/
#pragma once
#ifndef __CMDLNOPTS_H__
#define __CMDLNOPTS_H__
#include "ccdfunc.h"
#include <usefull_macros.h>
/*
* here are some typedef's for global data
*/
typedef struct{
char *cameradev; // camera device ("fli", "zwo" etc)
char *focuserdev; // focuser ...
char *wheeldev; // wheel ...
char *objname; // object's name
char *outfile; // output filename prefix
char *objtype; // type of object (dark/obj/bias)
char *instrument; // instrument's name
char *observers; // observers' names
char *prog_id; // programm identificator
char *author; // programm author
int fanspeed; // fan speed: 0-2
int noflush; // turn off bg flushing
int camdevno; // camera number (0, 1, 2 etc)
int focdevno;
int whldevno;
int dark; // dark frame
int nframes; // amount of frames to take
int hbin; int vbin; // binning
int X0; int Y0; // top left corner coordinate (-1 - all, including overscan)
int X1; int Y1; // bottom right corner coordinate
int fullframe; // grab full frame (with overscans)
int nflushes; // amount of flushes
int pause_len; // pause (in seconds) between expositions
int shtr_cmd; // shutter command (flishutter_t)
int _8bit; // 8bit mode
int fast; // fast (8MHz) readout mode
int getio; // get value of ioport
int setio; // set value of ioport
int confio; // configure ioport
float exptime; // time of exposition in seconds
double temperature; // temperature of CCD
double gotopos; // move stepper motor of focuser to absolute position
double addsteps; // move stepper motor of focuser to relative position
int setwheel; // set wheel position
int async; // asynchronous moving
int verbose; // each '-V' increases it
int rewrite; // rewrite file
int showimage; // show image preview
char **addhdr; // list of files from which to add header records
} glob_pars;
// default & global parameters
extern glob_pars const Gdefault;
extern glob_pars *GP;
glob_pars *parse_args(int argc, char **argv);
void verbose(int levl, const char *fmt, ...);
#endif // __CMDLNOPTS_H__

199
events.c Normal file
View File

@ -0,0 +1,199 @@
/*
* events.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 <usefull_macros.h>
#include "events.h"
#include "imageview.h"
/**
* manage pressed keys & menu items
*/
static void processKeybrd(unsigned char key, int mod, _U_ int x, _U_ int y){
windowData *win = getWin();
if(!win) return;
DBG("key=%d (%c), mod=%d", key, key, mod);
if(mod == GLUT_ACTIVE_CTRL){ // 'a' == 1, 'b' == 2...
key += 'a'-1;
DBG("CTRL+%c", key);
switch(key){
case 'r': // roll colorfun
win->winevt |= WINEVT_ROLLCOLORFUN;
break;
case 's': // save image
win->winevt |= WINEVT_SAVEIMAGE;
break;
case 'q': // exit case 17:
win->killthread = 1;
break;
}
}else if(mod == GLUT_ACTIVE_ALT){
; // ALT
}else switch(key){
case '0': // return zoom to 1 & image to 0
win->zoom = 1;
win->x = 0; win->y = 0;
break;
case 27: // esc - kill
win->killthread = 1;
break;
case 'c': // capture in pause mode
DBG("winevt = %d", win->winevt);
if(win->winevt & WINEVT_PAUSE)
win->winevt |= WINEVT_GETIMAGE;
break;
case 'l': // flip left-right
win->flip ^= WIN_FLIP_LR;
break;
case 'p': // pause capturing
win->winevt ^= WINEVT_PAUSE;
break;
case 'u': // flip up-down
win->flip ^= WIN_FLIP_UD;
break;
case 'Z': // zoom+
win->zoom *= 1.1f;
calc_win_props(NULL, NULL);
break;
case 'z': // zoom-
win->zoom /= 1.1f;
calc_win_props(NULL, NULL);
break;
}
}
/*
* Process keyboard
*/
void keyPressed(unsigned char key, int x, int y){
int mod = glutGetModifiers();
//mod: GLUT_ACTIVE_SHIFT, GLUT_ACTIVE_CTRL, GLUT_ACTIVE_ALT; result is their sum
DBG("Key pressed. mod=%d, keycode=%d (%c), point=(%d,%d)\n", mod, key, key, x,y);
processKeybrd(key, mod, x, y);
}
/*
void keySpPressed(_U_ int key, _U_ int x, _U_ int y){
// int mod = glutGetModifiers();
DBG("Sp. key pressed. mod=%d, keycode=%d, point=(%d,%d)\n", glutGetModifiers(), key, x,y);
}*/
static int oldx, oldy; // coordinates when mouse was pressed
static int movingwin = 0; // ==1 when user moves image by middle button
void mousePressed(int key, int state, int x, int y){
// key: GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON
// state: GLUT_UP, GLUT_DOWN
int mod = glutGetModifiers();
windowData *win = getWin();
if(!win) return;
if(state == GLUT_DOWN){
oldx = x; oldy = y;
float X,Y, Zoom = win->zoom;
conv_mouse_to_image_coords(x,y,&X,&Y,win);
DBG("press in (%d, %d) == (%f, %f) on image; mod == %d", x,y,X,Y, mod);
if(key == GLUT_LEFT_BUTTON){
DBG("win->x=%g, win->y=%g", win->x, win->y);
win->x += Zoom * (win->w/2.f - (float)x);
win->y -= Zoom * (win->h/2.f - (float)y);
}else if(key == GLUT_MIDDLE_BUTTON) movingwin = 1;
else if(key == 3){ // wheel UP
if(mod == 0) win->y += 10.f*win->zoom; // nothing pressed - scroll up
else if(mod == GLUT_ACTIVE_SHIFT) win->x -= 10.f*Zoom; // shift pressed - scroll left
else if(mod == GLUT_ACTIVE_CTRL) win->zoom *= 1.1f; // ctrl+wheel up == zoom+
}else if(key == 4){ // wheel DOWN
if(mod == 0) win->y -= 10.f*win->zoom; // nothing pressed - scroll down
else if(mod == GLUT_ACTIVE_SHIFT) win->x += 10.f*Zoom; // shift pressed - scroll right
else if(mod == GLUT_ACTIVE_CTRL) win->zoom /= 1.1f; // ctrl+wheel down == zoom-
}
calc_win_props(NULL, NULL);
}else{
movingwin = 0;
}
}
void mouseMove(int x, int y){
windowData *win = getWin();
if(!win) return;
if(movingwin){
float X, Y, nx, ny, w2, h2;
float a = win->Daspect;
X = (x - oldx) * a; Y = (y - oldy) * a;
nx = win->x + X;
ny = win->y - Y;
w2 = win->image->w / 2.f * win->zoom;
h2 = win->image->h / 2.f * win->zoom;
if(nx < w2 && nx > -w2)
win->x = nx;
if(ny < h2 && ny > -h2)
win->y = ny;
oldx = x;
oldy = y;
calc_win_props(NULL, NULL);
}
}
void menuEvents(int opt){
DBG("opt: %d, key: %d (%c), mod: %d", opt, opt&0xff, opt&0xff, opt>>8);
// just work as shortcut pressed
processKeybrd((unsigned char)(opt&0xff), opt>>8, 0, 0);
} // GLUT_ACTIVE_CTRL
typedef struct{
char *name; // menu entry name
int symbol; // shortcut symbol + rolled modifier
} menuentry;
#define CTRL_K(key) ((key-'a'+1) | (GLUT_ACTIVE_CTRL<<8))
#define SHIFT_K(key) (key | (GLUT_ACTIVE_SHIFT<<8))
#define ALT_K(key) (key | (GLUT_ACTIVE_ALT<<8))
static const menuentry entries[] = {
{"Capture in pause mode (c)", 'c'},
{"Flip image LR (l)", 'l'},
{"Flip image UD (u)", 'u'},
{"Make a pause/continue (p)", 'p'},
{"Restore zoom (0)", '0'},
{"Roll colorfun (ctrl+r)", CTRL_K('r')},
{"Save image (ctrl+s)", CTRL_K('s')},
{"Close this window (ESC)", 27},
{"Quit (ctrl+q)", CTRL_K('q')},
{NULL, 0}
};
#undef CTRL_K
#undef SHIFT_K
#undef ALT_K
void createMenu(){
FNAME();
windowData *win = getWin();
if(!win) return;
DBG("menu for win ID %d", win->ID);
glutSetWindow(win->ID);
if(win->menu) glutDestroyMenu(win->menu);
win->menu = glutCreateMenu(menuEvents);
const menuentry *ptr = entries;
while(ptr->name){
glutAddMenuEntry(ptr->name, ptr->symbol);
++ptr;
}
DBG("created menu %d\n", win->menu);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}

42
events.h Normal file
View File

@ -0,0 +1,42 @@
/*
* events.h
*
* 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.
*/
#pragma once
#ifndef __EVENTS_H__
#define __EVENTS_H__
#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
#include <GL/glext.h>
#include <GL/freeglut.h>
extern float Z; // ËÏÏÒÄÉÎÁÔÁ Z (zoom)
void keyPressed(unsigned char key, int x, int y);
//void keySpPressed(int key, int x, int y);
void mousePressed(int key, int state, int x, int y);
void mouseMove(int x, int y);
void createMenu();
void menuEvents(int opt);
//void mouseWheel(int button, int dir, int x, int y);
#endif // __EVENTS_H__

463
imageview.c Normal file
View File

@ -0,0 +1,463 @@
/*
* This file is part of the FLI_control project.
* Copyright 2020 Edward V. Emelianov <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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <X11/Xlib.h> // XInitThreads();
#include <math.h> // roundf(), log(), sqrt()
#include <pthread.h>
#include <unistd.h>
#include <usefull_macros.h>
#include "cmdlnopts.h"
#include "imageview.h"
static windowData *win = NULL; // main window
static pthread_t GLUTthread = 0; // main GLUT thread
static int initialized = 0; // ==1 if GLUT is initialized; ==0 after clear_GL_context
static void *Redraw(_U_ void *p);
static void createWindow();
static void RedrawWindow();
static void Resize(int width, int height);
/**
* calculate window properties on creating & resizing
*/
void calc_win_props(GLfloat *Wortho, GLfloat *Hortho){
if(!win || ! win->image) return;
float a, A, w, h, W, H;
float Zoom = win->zoom;
w = (float)win->image->w / 2.f;
h = (float)win->image->h / 2.f;
W = (float)win->w;
H =(float) win->h;
A = W / H;
a = w / h;
if(A > a){ // now W & H are parameters for glOrtho
win->Daspect = (float)h / H * 2.f;
W = h * A; H = h;
}else{
win->Daspect = (float)w / W * 2.f;
H = w / A; W = w;
}
if(Wortho) *Wortho = W;
if(Hortho) *Hortho = H;
// calculate coordinates of center
win->x0 = W/Zoom - w + win->x / Zoom;
win->y0 = H/Zoom + h - win->y / Zoom;
}
/**
* create window & run main loop
*/
static void createWindow(){
DBG("ini=%d, win %s", initialized, win ? "yes" : "no");
if(!initialized) return;
if(!win) return;
int w = win->w, h = win->h;
DBG("create window with title %s", win->title);
glutInitWindowSize(w, h);
win->ID = glutCreateWindow(win->title);
DBG("created GL_ID=%d", win->ID);
glutReshapeFunc(Resize);
glutDisplayFunc(RedrawWindow);
glutKeyboardFunc(keyPressed);
//glutSpecialFunc(keySpPressed);
//glutMouseWheelFunc(mouseWheel);
glutMouseFunc(mousePressed);
glutMotionFunc(mouseMove);
//glutIdleFunc(glutPostRedisplay);
glutIdleFunc(RedrawWindow);
DBG("init textures");
glGenTextures(1, &(win->Tex));
calc_win_props(NULL, NULL);
win->zoom = 1. / win->Daspect;
glEnable(GL_TEXTURE_2D);
// the hext 4 lines need to unaligned storage
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glBindTexture(GL_TEXTURE_2D, win->Tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, win->image->w, win->image->h, 0,
GL_RGB, GL_UNSIGNED_BYTE, win->image->rawdata);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glDisable(GL_TEXTURE_2D);
createMenu();
DBG("Window opened");
}
int killwindow(){
if(!win) return 0;
if(!win->killthread){
// say threads to die
win->killthread = 1;
}
pthread_mutex_lock(&win->mutex);
//pthread_join(win->thread, NULL); // wait while thread dies
if(win->menu) glutDestroyMenu(win->menu);
glutDestroyWindow(win->ID);
DBG("destroy menu, wundow & texture %d", win->Tex);
glDeleteTextures(1, &(win->Tex));
glutLeaveMainLoop();
DBG("Cancel");
windowData *old = win;
win = NULL;
DBG("free(rawdata)");
FREE(old->image->rawdata);
DBG("free(image)");
FREE(old->image);
pthread_mutex_unlock(&old->mutex);
DBG("free(win)");
FREE(old);
DBG("return");
return 1;
}
void renderBitmapString(float x, float y, void *font, char *string, GLubyte *color){
if(!initialized) return;
char *c;
int x1=x, W=0;
for(c = string; *c; c++){
W += glutBitmapWidth(font,*c);// + 1;
}
x1 -= W/2;
glColor3ubv(color);
glLoadIdentity();
glTranslatef(0.,0., -150);
//glTranslatef(x,y, -4000.);
for (c = string; *c != '\0'; c++){
glColor3ubv(color);
glRasterPos2f(x1,y);
glutBitmapCharacter(font, *c);
//glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);
x1 = x1 + glutBitmapWidth(font,*c);// + 1;
}
}
static void RedrawWindow(){
//DBG("ini=%d, win=%s", initialized, win ? "yes" : "no");
if(!initialized || !win || win->killthread) return;
if(pthread_mutex_trylock(&win->mutex)) return;
GLfloat w = win->image->w, h = win->image->h;
glutSetWindow(win->ID);
glClearColor(0.0, 0.0, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(win->x, win->y, 0.);
glScalef(-win->zoom, -win->zoom, 1.);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, win->Tex);
if(win->image->changed){
DBG("Image changed!");
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, win->image->w, win->image->h, 0,
GL_RGB, GL_UNSIGNED_BYTE, win->image->rawdata);
/* glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, win->image->w, win->image->h,
GL_RGB, GL_UNSIGNED_BYTE, win->image->rawdata);*/
win->image->changed = 0;
}
w /= 2.f; h /= 2.f;
float lr = 1., ud = 1.; // flipping coefficients
if(win->flip & WIN_FLIP_LR) lr = -1.;
if(win->flip & WIN_FLIP_UD) ud = -1.;
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f); glVertex2f( -1.f*lr*w, ud*h ); // top right
glTexCoord2f(1.0f, 0.0f); glVertex2f( -1.f*lr*w, -1.f*ud*h ); // bottom right
glTexCoord2f(0.0f, 0.0f); glVertex2f(lr*w, -1.f*ud*h ); // bottom left
glTexCoord2f(0.0f, 1.0f); glVertex2f(lr*w, ud*h ); // top left
glEnd();
glDisable(GL_TEXTURE_2D);
glFinish();
glutSwapBuffers();
pthread_mutex_unlock(&win->mutex);
usleep(10000);
}
/**
* main freeGLUT loop
* waits for global signals to create windows & make other actions
*/
static void *Redraw(_U_ void *arg){
FNAME();
createWindow();
glutMainLoop();
return NULL;
}
static void Resize(int width, int height){
FNAME();
if(!initialized || !win || win->killthread) return;
glutReshapeWindow(width, height);
win->w = width;
win->h = height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat W, H;
calc_win_props(&W, &H);
glOrtho(-W,W, -H,H, -1., 1.);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/**
* create new window, run thread & return pointer to its structure or NULL
* asynchroneous call from outside
* wait for window creating & return its data
* @param title - header (copyed inside this function)
* @param w,h - image size
* @param rawdata - NULL (then the memory will be allocated here with size w x h)
* or allocated outside data
*/
windowData *createGLwin(char *title, int w, int h, rawimage *rawdata){
FNAME();
if(!initialized) imageview_init();
if(win) killwindow();
win = MALLOC(windowData, 1);
rawimage *raw;
if(rawdata){
raw = rawdata;
}else{
raw = MALLOC(rawimage, 1);
if(raw){
raw->rawdata = MALLOC(GLubyte, w*h*3);
raw->w = w;
raw->h = h;
raw->changed = 1;
// raw->protected is zero automatically
}
}
if(!raw || !raw->rawdata){
free(raw);
return NULL;
}
win->title = strdup(title);
win->image = raw;
if(pthread_mutex_init(&win->mutex, NULL)){
WARN(_("Can't init mutex!"));
killwindow();
return NULL;
}
win->w = w;
win->h = h;
pthread_create(&GLUTthread, NULL, &Redraw, NULL);
return win;
}
/**
* Init freeGLUT
*/
void imageview_init(){
FNAME();
char *v[] = {"Image view window", NULL};
int c = 1;
if(initialized){
WARNX(_("Already initialized!"));
return;
}
XInitThreads(); // we need it for threaded windows
glutInit(&c, v);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
initialized = 1;
}
/**
* Close all opened windows and terminate main GLUT thread
*/
void clear_GL_context(){
FNAME();
if(!initialized) return;
initialized = 0;
DBG("kill");
killwindow();
DBG("join");
if(GLUTthread) pthread_join(GLUTthread, NULL); // wait while main thread exits
DBG("main GL thread cancelled");
}
/*
* Coordinates transformation from CS of drawingArea into CS of picture
* x,y - pointer coordinates
* X,Y - coordinates of appropriate point at picture
*/
void conv_mouse_to_image_coords(int x, int y,
float *X, float *Y,
windowData *window){
float a = window->Daspect / window->zoom;
*X = (float)x * a - window->x0;
*Y = window->y0 - (float)y * a;
}
void conv_image_to_mouse_coords(float X, float Y,
int *x, int *y,
windowData *window){
float a = window->zoom / window->Daspect;
*x = (int)roundf((X + window->x0) * a);
*y = (int)roundf((window->y0 - Y) * a);
}
windowData *getWin(){
return win;
}
/**
* Convert gray (unsigned short) into RGB components (GLubyte)
* @argument L - gray level (0..1)
* @argument rgb - rgb array (GLubyte [3])
*/
static void gray2rgb(double gray, GLubyte *rgb){
int i = gray * 4.;
double x = (gray - (double)i * .25) * 4.;
GLubyte r = 0, g = 0, b = 0;
//r = g = b = (gray < 1) ? gray * 256 : 255;
switch(i){
case 0:
g = (GLubyte)(255. * x);
b = 255;
break;
case 1:
g = 255;
b = (GLubyte)(255. * (1. - x));
break;
case 2:
r = (GLubyte)(255. * x);
g = 255;
break;
case 3:
r = 255;
g = (GLubyte)(255. * (1. - x));
break;
default:
r = 255;
}
*rgb++ = r;
*rgb++ = g;
*rgb = b;
}
typedef enum{
COLORFN_LINEAR, // linear
COLORFN_LOG, // ln
COLORFN_SQRT, // sqrt
COLORFN_MAX // end of list
} colorfn_type;
static colorfn_type ft = COLORFN_LINEAR;
// all colorfun's should get argument in [0, 1] and return in [0, 1]
static double linfun(double arg){ return arg; } // bung for PREVIEW_LINEAR
static double logfun(double arg){ return log(1.+arg) / 0.6931472; } // for PREVIEW_LOG [log_2(x+1)]
static double (*colorfun)(double) = linfun; // default function to convert color
static void change_colorfun(colorfn_type f){
DBG("New colorfn: %d", f);
switch (f){
case COLORFN_LOG:
colorfun = logfun;
ft = COLORFN_LOG;
break;
case COLORFN_SQRT:
colorfun = sqrt;
ft = COLORFN_SQRT;
break;
default: // linear
colorfun = linfun;
ft = COLORFN_LINEAR;
}
}
// cycle switch between palettes
static void roll_colorfun(){
colorfn_type t = ++ft;
if(t == COLORFN_MAX) t = COLORFN_LINEAR;
change_colorfun(t);
}
/**
* @brief equalize - hystogram equalization
* @param ori (io) - input/output data
* @param w,h - image width and height
* @return data allocated here
*/
static uint8_t *equalize(uint16_t *ori, int w, int h){
uint8_t *retn = MALLOC(uint8_t, w*h);
double orig_hysto[0x10000] = {0.}; // original hystogram
uint8_t eq_levls[0x10000] = {0}; // levels to convert: newpix = eq_levls[oldpix]
int s = w*h;
for(int i = 0; i < s; ++i) ++orig_hysto[ori[i]];
double part = (double)(s + 1) / 0x100, N = 0.;
for(int i = 0; i <= 0xffff; ++i){
N += orig_hysto[i];
eq_levls[i] = (uint8_t)(N/part);
}
for(int i = 0; i < s; ++i){
retn[i] = eq_levls[ori[i]];
}
return retn;
}
void change_displayed_image(windowData *win, IMG *img){
if(!win || !win->image) return;
rawimage *im = win->image;
DBG("imh=%d, imw=%d, ch=%u, cw=%u", im->h, im->w, img->w, img->h);
pthread_mutex_lock(&win->mutex);
int w = img->w, h = img->h, s = w*h;
uint8_t *newima = equalize(img->data, w, h);
GLubyte *dst = im->rawdata;
for(int i = 0; i < s; ++i, dst += 3){
gray2rgb(colorfun(newima[i] / 256.), dst);
}
FREE(newima);
win->image->changed = 1;
pthread_mutex_unlock(&win->mutex);
}
void* image_thread(_U_ void *data){
FNAME();
IMG *img = (IMG*) data;
while(1){
windowData *win = getWin();
if(!win || win->killthread){
DBG("got killthread");
clear_GL_context();
pthread_exit(NULL);
}
if(win && win->winevt){
if(win->winevt & WINEVT_SAVEIMAGE){ // save image
verbose(2, "Make screenshot\n");
saveFITS(img, "ScreenShot");
win->winevt &= ~WINEVT_SAVEIMAGE;
}
if(win->winevt & WINEVT_ROLLCOLORFUN){
roll_colorfun();
win->winevt &= ~WINEVT_ROLLCOLORFUN;
change_displayed_image(win, img);
}
}
usleep(10000);
}
}

91
imageview.h Normal file
View File

@ -0,0 +1,91 @@
/*
* imageview.h
*
* 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.
*/
#pragma once
#ifndef __BMPVIEW_H__
#define __BMPVIEW_H__
#include <math.h>
#include <pthread.h>
#include <stdbool.h>
#include <string.h>
#include "ccdfunc.h"
#include "events.h"
typedef struct{
GLubyte *rawdata; // raw image data
int w; // size of image
int h;
int changed; // == 1 if data was changed outside (to redraw)
} rawimage;
// events from menu:
// temporaly stop capture of regular sequence
#define WINEVT_PAUSE (1<<0)
// capture one image in pause mode
#define WINEVT_GETIMAGE (1<<1)
// save current image
#define WINEVT_SAVEIMAGE (1<<2)
// change color palette function
#define WINEVT_ROLLCOLORFUN (1<<3)
// flip image
#define WIN_FLIP_LR (1<<0)
#define WIN_FLIP_UD (1<<1)
typedef struct{
int ID; // identificator of OpenGL window
char *title; // title of window
GLuint Tex; // texture for image inside window
rawimage *image; // raw image data
int w; int h; // window size
float x; float y; // image offset coordinates
float x0; float y0; // center of window for coords conversion
float zoom; // zoom aspect
float Daspect; // aspect ratio between image & window sizes
int menu; // window menu identifier
uint32_t winevt; // window menu events
uint8_t flip; // flipping settings
pthread_t thread; // identificator of thread that changes window data
pthread_mutex_t mutex;// mutex for operations with image
int killthread; // flag for killing data changing thread & also signal that there's no threads
} windowData;
typedef enum{
INNER,
OPENGL
} winIdType;
void imageview_init();
windowData *createGLwin(char *title, int w, int h, rawimage *rawdata);
windowData *getWin();
int killwindow();
void renderBitmapString(float x, float y, void *font, char *string, GLubyte *color);
void clear_GL_context();
void calc_win_props(GLfloat *Wortho, GLfloat *Hortho);
void conv_mouse_to_image_coords(int x, int y, float *X, float *Y, windowData *window);
void conv_image_to_mouse_coords(float X, float Y, int *x, int *y, windowData *window);
void* image_thread(void *data);
void change_displayed_image(windowData *win, IMG *img);
#endif // __BMPVIEW_H__

Binary file not shown.

450
locale/ru/messages.po Normal file
View File

@ -0,0 +1,450 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-01-13 12:16+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=koi8-r\n"
"Content-Transfer-Encoding: 8bit\n"
#: cmdlnopts.c:68
msgid "camera device type (fli/zwo/etc)"
msgstr ""
#: cmdlnopts.c:69
msgid "focuser device type (fli/zwo/etc)"
msgstr ""
#: cmdlnopts.c:70
msgid "wheel device type (fli/zwo/etc)"
msgstr ""
#: cmdlnopts.c:71
msgid "camera device number (if many: 0, 1, 2 etc)"
msgstr ""
#: cmdlnopts.c:72
msgid "filter wheel device number (if many: 0, 1, 2 etc)"
msgstr ""
#: cmdlnopts.c:73
msgid "focuser device number (if many: 0, 1, 2 etc)"
msgstr ""
#: cmdlnopts.c:74
msgid "show this help"
msgstr ""
#: cmdlnopts.c:75
msgid "rewrite output file if exists"
msgstr ""
#: cmdlnopts.c:76
msgid "verbose level (each -v increase it)"
msgstr ""
#: cmdlnopts.c:77
msgid "not open shutter, when exposing (\"dark frames\")"
msgstr ""
#: cmdlnopts.c:78
msgid "run in 8-bit mode"
msgstr ""
#: cmdlnopts.c:79
msgid "fast (8MHz) readout mode"
msgstr ""
#: cmdlnopts.c:80
msgid "set CCD temperature to given value (degr C)"
msgstr ""
#: cmdlnopts.c:81
msgid "set fan speed (0 - off, 1 - low, 2 - high)"
msgstr ""
#: cmdlnopts.c:83
msgid "program author"
msgstr ""
#: cmdlnopts.c:84
msgid "object type (neon, object, flat etc)"
msgstr ""
#: cmdlnopts.c:85
msgid "instrument name"
msgstr ""
#: cmdlnopts.c:86
msgid "object name"
msgstr ""
#: cmdlnopts.c:87
msgid "observers' names"
msgstr ""
#: cmdlnopts.c:88
msgid "observing program name"
msgstr ""
#: cmdlnopts.c:89
msgid "add records to header from given file[s]"
msgstr ""
#: cmdlnopts.c:91
msgid "N flushes before exposing (default: 1)"
msgstr ""
#: cmdlnopts.c:92
msgid "horizontal binning to N pixels"
msgstr ""
#: cmdlnopts.c:93
msgid "vertical binning to N pixels"
msgstr ""
#: cmdlnopts.c:94
msgid "make series of N frames"
msgstr ""
#: cmdlnopts.c:95
msgid "make pause for N seconds between expositions"
msgstr ""
#: cmdlnopts.c:96
msgid "set exposure time to given value (ms)"
msgstr ""
#: cmdlnopts.c:97
msgid "frame X0 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:98
msgid "frame Y0 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:99
msgid "frame X1 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:100
msgid "frame Y1 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:101
msgid "grab full frame (with overscans)"
msgstr ""
#: cmdlnopts.c:103
msgid "open shutter"
msgstr ""
#: cmdlnopts.c:104
msgid "close shutter"
msgstr ""
#: cmdlnopts.c:105
msgid "run exposition on LOW @ pin5 I/O port"
msgstr ""
#: cmdlnopts.c:106
msgid "run exposition on HIGH @ pin5 I/O port"
msgstr ""
#: cmdlnopts.c:107
msgid "get value of I/O port pins"
msgstr ""
#: cmdlnopts.c:108
msgid "move stepper motor asynchronous"
msgstr ""
#: cmdlnopts.c:110
msgid "set I/O port pins to given value (decimal number, pin1 is LSB)"
msgstr ""
#: cmdlnopts.c:111
msgid ""
"configure I/O port pins to given value (decimal number, pin1 is LSB, 1 == "
"output, 0 == input)"
msgstr ""
#: cmdlnopts.c:113
msgid "move focuser to absolute position, mm"
msgstr ""
#: cmdlnopts.c:114
msgid "move focuser to relative position, mm"
msgstr ""
#: cmdlnopts.c:116
msgid "set wheel position"
msgstr ""
#: cmdlnopts.c:119
msgid "Display image in OpenGL window"
msgstr ""
#. Не могу сохранить файл
#: ccdfunc.c:115
msgid "Can't save file"
msgstr ""
#: ccdfunc.c:257
#, c-format
msgid "File saved as '%s'"
msgstr ""
#: ccdfunc.c:259
msgid "Error saving file"
msgstr ""
#. Статистика по изображению:\n
#: ccdfunc.c:279
#, c-format
msgid "Image stat:\n"
msgstr ""
#: ccdfunc.c:291
msgid "Focuser device not pointed, try to guess"
msgstr ""
#: ccdfunc.c:307
msgid "Focuser not found"
msgstr ""
#: ccdfunc.c:312
#, c-format
msgid "Found %d focusers, you point number %d"
msgstr ""
#: ccdfunc.c:316
msgid "Can't set active focuser number"
msgstr ""
#: ccdfunc.c:330
msgid "Can't get focuser limit positions"
msgstr ""
#: ccdfunc.c:337
msgid "Can't get current focuser position"
msgstr ""
#: ccdfunc.c:351
#, c-format
msgid "Can't set position %g: out of limits [%g, %g]"
msgstr ""
#: ccdfunc.c:355
msgid "Can't home focuser"
msgstr ""
#: ccdfunc.c:357
#, c-format
msgid "Can't set position %g"
msgstr ""
#: ccdfunc.c:369
msgid "Wheel device not pointed, try to guess"
msgstr ""
#: ccdfunc.c:385
msgid "Wheel not found"
msgstr ""
#: ccdfunc.c:390
#, c-format
msgid "Found %d wheels, you point number %d"
msgstr ""
#: ccdfunc.c:394
msgid "Can't set active wheel number"
msgstr ""
#: ccdfunc.c:406
msgid "Can't get max wheel position"
msgstr ""
#: ccdfunc.c:413
#, c-format
msgid "Wheel position should be from 0 to %d"
msgstr ""
#: ccdfunc.c:417
#, c-format
msgid "Can't set wheel position %d"
msgstr ""
#: ccdfunc.c:436
msgid "Camera device not pointed, try to guess"
msgstr ""
#: ccdfunc.c:452
msgid "Camera device not found"
msgstr ""
#: ccdfunc.c:457
#, c-format
msgid "Found %d cameras, you point number %d"
msgstr ""
#: ccdfunc.c:461
msgid "Can't set active camera number"
msgstr ""
#: ccdfunc.c:467
msgid "Can't set fan speed"
msgstr ""
#: ccdfunc.c:472
#, c-format
msgid "Camera model: %s"
msgstr ""
#: ccdfunc.c:473
#, c-format
msgid "Pixel size: %g x %g"
msgstr ""
#: ccdfunc.c:479
#, c-format
msgid "Full array: %s"
msgstr ""
#: ccdfunc.c:482
#, c-format
msgid "Field of view: %s"
msgstr ""
#: ccdfunc.c:485
#, c-format
msgid "Can't set T to %g degC"
msgstr ""
#: ccdfunc.c:492
#, c-format
msgid "Shutter command: %s\n"
msgstr ""
#: ccdfunc.c:494
#, c-format
msgid "Can't run shutter command %s (unsupported?)"
msgstr ""
#. "Попытка сконфигурировать порт I/O как %d\n"
#: ccdfunc.c:498
#, c-format
msgid "Try to convfigure I/O port as %d"
msgstr ""
#: ccdfunc.c:500
msgid "Can't configure (unsupported?)"
msgstr ""
#: ccdfunc.c:506
msgid "Can't get IOport state (unsupported?)"
msgstr ""
#. "Попытка записи %d в порт I/O\n"
#: ccdfunc.c:510
#, c-format
msgid "Try to write %d to I/O port"
msgstr ""
#: ccdfunc.c:512
msgid "Can't set IOport"
msgstr ""
#: ccdfunc.c:524
#, c-format
msgid "Can't set binning %dx%d"
msgstr ""
#: ccdfunc.c:526
msgid "Can't get current binning"
msgstr ""
#: ccdfunc.c:541
msgid "Can't set given geometry"
msgstr ""
#: ccdfunc.c:544
#, c-format
msgid "Can't set %d flushes"
msgstr ""
#: ccdfunc.c:547
#, c-format
msgid "Can't set exposure time to %f seconds"
msgstr ""
#: ccdfunc.c:550
msgid "Can't change frame type"
msgstr ""
#: ccdfunc.c:553
msgid "Can't set bit depth"
msgstr ""
#: ccdfunc.c:556
msgid "Can't set readout speed"
msgstr ""
#: ccdfunc.c:557
msgid "Fast readout mode"
msgstr ""
#: ccdfunc.c:558
msgid "Only show statistics"
msgstr ""
#. Захват кадра %d\n
#: ccdfunc.c:565
#, c-format
msgid "Capture frame %d\n"
msgstr ""
#: ccdfunc.c:570
#, c-format
msgid "%.1f seconds till exposition ends"
msgstr ""
#: ccdfunc.c:578
msgid "Can't capture image"
msgstr ""
#: ccdfunc.c:581
msgid "Read grabbed image"
msgstr ""
#: ccdfunc.c:583 ccdfunc.c:606 ccdfunc.c:637
msgid "Can't grab image"
msgstr ""
#: ccdfunc.c:594
msgid "Can't open OpenGL window, image preview will be inaccessible"
msgstr ""
#. %d секунд до окончания паузы\n
#: ccdfunc.c:619
#, c-format
msgid "%d seconds till pause ends\n"
msgstr ""
#: imageview.c:257
msgid "Can't init mutex!"
msgstr ""
#: imageview.c:275
msgid "Already initialized!"
msgstr ""

448
locale/ru/ru.po Normal file
View File

@ -0,0 +1,448 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-01-13 12:15+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=koi8-r\n"
"Content-Transfer-Encoding: 8bit\n"
#: ccdfunc.c:570
#, c-format
msgid "%.1f seconds till exposition ends"
msgstr ""
#. %d секунд до окончания паузы\n
#: ccdfunc.c:619
#, c-format
msgid "%d seconds till pause ends\n"
msgstr ""
#: imageview.c:275
msgid "Already initialized!"
msgstr ""
#: ccdfunc.c:452
msgid "Camera device not found"
msgstr ""
#: ccdfunc.c:436
msgid "Camera device not pointed, try to guess"
msgstr ""
#: ccdfunc.c:472
#, c-format
msgid "Camera model: %s"
msgstr ""
#: ccdfunc.c:578
msgid "Can't capture image"
msgstr ""
#: ccdfunc.c:550
msgid "Can't change frame type"
msgstr ""
#: ccdfunc.c:500
msgid "Can't configure (unsupported?)"
msgstr ""
#: ccdfunc.c:506
msgid "Can't get IOport state (unsupported?)"
msgstr ""
#: ccdfunc.c:526
msgid "Can't get current binning"
msgstr ""
#: ccdfunc.c:337
msgid "Can't get current focuser position"
msgstr ""
#: ccdfunc.c:330
msgid "Can't get focuser limit positions"
msgstr ""
#: ccdfunc.c:406
msgid "Can't get max wheel position"
msgstr ""
#: ccdfunc.c:583 ccdfunc.c:606 ccdfunc.c:637
msgid "Can't grab image"
msgstr ""
#: ccdfunc.c:355
msgid "Can't home focuser"
msgstr ""
#: imageview.c:257
msgid "Can't init mutex!"
msgstr ""
#: ccdfunc.c:594
msgid "Can't open OpenGL window, image preview will be inaccessible"
msgstr ""
#: ccdfunc.c:494
#, c-format
msgid "Can't run shutter command %s (unsupported?)"
msgstr ""
#. Не могу сохранить файл
#: ccdfunc.c:115
msgid "Can't save file"
msgstr ""
#: ccdfunc.c:544
#, c-format
msgid "Can't set %d flushes"
msgstr ""
#: ccdfunc.c:512
msgid "Can't set IOport"
msgstr ""
#: ccdfunc.c:485
#, c-format
msgid "Can't set T to %g degC"
msgstr ""
#: ccdfunc.c:461
msgid "Can't set active camera number"
msgstr ""
#: ccdfunc.c:316
msgid "Can't set active focuser number"
msgstr ""
#: ccdfunc.c:394
msgid "Can't set active wheel number"
msgstr ""
#: ccdfunc.c:524
#, c-format
msgid "Can't set binning %dx%d"
msgstr ""
#: ccdfunc.c:553
msgid "Can't set bit depth"
msgstr ""
#: ccdfunc.c:547
#, c-format
msgid "Can't set exposure time to %f seconds"
msgstr ""
#: ccdfunc.c:467
msgid "Can't set fan speed"
msgstr ""
#: ccdfunc.c:541
msgid "Can't set given geometry"
msgstr ""
#: ccdfunc.c:357
#, c-format
msgid "Can't set position %g"
msgstr ""
#: ccdfunc.c:351
#, c-format
msgid "Can't set position %g: out of limits [%g, %g]"
msgstr ""
#: ccdfunc.c:556
msgid "Can't set readout speed"
msgstr ""
#: ccdfunc.c:417
#, c-format
msgid "Can't set wheel position %d"
msgstr ""
#. Захват кадра %d\n
#: ccdfunc.c:565
#, c-format
msgid "Capture frame %d\n"
msgstr ""
#: cmdlnopts.c:119
msgid "Display image in OpenGL window"
msgstr ""
#: ccdfunc.c:259
msgid "Error saving file"
msgstr ""
#: ccdfunc.c:557
msgid "Fast readout mode"
msgstr ""
#: ccdfunc.c:482
#, c-format
msgid "Field of view: %s"
msgstr ""
#: ccdfunc.c:257
#, c-format
msgid "File saved as '%s'"
msgstr ""
#: ccdfunc.c:291
msgid "Focuser device not pointed, try to guess"
msgstr ""
#: ccdfunc.c:307
msgid "Focuser not found"
msgstr ""
#: ccdfunc.c:457
#, c-format
msgid "Found %d cameras, you point number %d"
msgstr ""
#: ccdfunc.c:312
#, c-format
msgid "Found %d focusers, you point number %d"
msgstr ""
#: ccdfunc.c:390
#, c-format
msgid "Found %d wheels, you point number %d"
msgstr ""
#: ccdfunc.c:479
#, c-format
msgid "Full array: %s"
msgstr ""
#. Статистика по изображению:\n
#: ccdfunc.c:279
#, c-format
msgid "Image stat:\n"
msgstr ""
#: cmdlnopts.c:91
msgid "N flushes before exposing (default: 1)"
msgstr ""
#: ccdfunc.c:558
msgid "Only show statistics"
msgstr ""
#: ccdfunc.c:473
#, c-format
msgid "Pixel size: %g x %g"
msgstr ""
#: ccdfunc.c:581
msgid "Read grabbed image"
msgstr ""
#: ccdfunc.c:492
#, c-format
msgid "Shutter command: %s\n"
msgstr ""
#. "Попытка сконфигурировать порт I/O как %d\n"
#: ccdfunc.c:498
#, c-format
msgid "Try to convfigure I/O port as %d"
msgstr ""
#. "Попытка записи %d в порт I/O\n"
#: ccdfunc.c:510
#, c-format
msgid "Try to write %d to I/O port"
msgstr ""
#: ccdfunc.c:369
msgid "Wheel device not pointed, try to guess"
msgstr ""
#: ccdfunc.c:385
msgid "Wheel not found"
msgstr ""
#: ccdfunc.c:413
#, c-format
msgid "Wheel position should be from 0 to %d"
msgstr ""
#: cmdlnopts.c:89
msgid "add records to header from given file[s]"
msgstr ""
#: cmdlnopts.c:71
msgid "camera device number (if many: 0, 1, 2 etc)"
msgstr ""
#: cmdlnopts.c:68
msgid "camera device type (fli/zwo/etc)"
msgstr ""
#: cmdlnopts.c:104
msgid "close shutter"
msgstr ""
#: cmdlnopts.c:111
msgid "configure I/O port pins to given value (decimal number, pin1 is LSB, "
"1 == output, 0 == input)"
msgstr ""
#: cmdlnopts.c:79
msgid "fast (8MHz) readout mode"
msgstr ""
#: cmdlnopts.c:72
msgid "filter wheel device number (if many: 0, 1, 2 etc)"
msgstr ""
#: cmdlnopts.c:73
msgid "focuser device number (if many: 0, 1, 2 etc)"
msgstr ""
#: cmdlnopts.c:69
msgid "focuser device type (fli/zwo/etc)"
msgstr ""
#: cmdlnopts.c:97
msgid "frame X0 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:99
msgid "frame X1 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:98
msgid "frame Y0 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:100
msgid "frame Y1 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:107
msgid "get value of I/O port pins"
msgstr ""
#: cmdlnopts.c:101
msgid "grab full frame (with overscans)"
msgstr ""
#: cmdlnopts.c:92
msgid "horizontal binning to N pixels"
msgstr ""
#: cmdlnopts.c:85
msgid "instrument name"
msgstr ""
#: cmdlnopts.c:95
msgid "make pause for N seconds between expositions"
msgstr ""
#: cmdlnopts.c:94
msgid "make series of N frames"
msgstr ""
#: cmdlnopts.c:113
msgid "move focuser to absolute position, mm"
msgstr ""
#: cmdlnopts.c:114
msgid "move focuser to relative position, mm"
msgstr ""
#: cmdlnopts.c:108
msgid "move stepper motor asynchronous"
msgstr ""
#: cmdlnopts.c:77
msgid "not open shutter, when exposing (\"dark frames\")"
msgstr ""
#: cmdlnopts.c:86
msgid "object name"
msgstr ""
#: cmdlnopts.c:84
msgid "object type (neon, object, flat etc)"
msgstr ""
#: cmdlnopts.c:87
msgid "observers' names"
msgstr ""
#: cmdlnopts.c:88
msgid "observing program name"
msgstr ""
#: cmdlnopts.c:103
msgid "open shutter"
msgstr ""
#: cmdlnopts.c:83
msgid "program author"
msgstr ""
#: cmdlnopts.c:75
msgid "rewrite output file if exists"
msgstr ""
#: cmdlnopts.c:106
msgid "run exposition on HIGH @ pin5 I/O port"
msgstr ""
#: cmdlnopts.c:105
msgid "run exposition on LOW @ pin5 I/O port"
msgstr ""
#: cmdlnopts.c:78
msgid "run in 8-bit mode"
msgstr ""
#: cmdlnopts.c:80
msgid "set CCD temperature to given value (degr C)"
msgstr ""
#: cmdlnopts.c:110
msgid "set I/O port pins to given value (decimal number, pin1 is LSB)"
msgstr ""
#: cmdlnopts.c:96
msgid "set exposure time to given value (ms)"
msgstr ""
#: cmdlnopts.c:81
msgid "set fan speed (0 - off, 1 - low, 2 - high)"
msgstr ""
#: cmdlnopts.c:116
msgid "set wheel position"
msgstr ""
#: cmdlnopts.c:74
msgid "show this help"
msgstr ""
#: cmdlnopts.c:76
msgid "verbose level (each -v increase it)"
msgstr ""
#: cmdlnopts.c:93
msgid "vertical binning to N pixels"
msgstr ""
#: cmdlnopts.c:70
msgid "wheel device type (fli/zwo/etc)"
msgstr ""

58
main.c Normal file
View File

@ -0,0 +1,58 @@
/*
* geany_encoding=koi8-r
* main.c
*
* Copyright 2017 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 <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <usefull_macros.h>
#include "cmdlnopts.h"
#include "ccdfunc.h"
#ifdef IMAGEVIEW
#include "imageview.h"
#endif
void signals(int signo){
cancel();
exit(signo);
}
extern const char *__progname;
int main(int argc, char **argv){
initial_setup();
parse_args(argc, argv);
signal(SIGINT, signals);
signal(SIGQUIT, signals);
signal(SIGABRT, signals);
signal(SIGTERM, signals);
focusers();
wheels();
ccds();
return 0;
}