mirror of
https://github.com/eddyem/CCD_Capture.git
synced 2026-03-21 09:11:00 +03:00
rebuild all cameras as .so-modules; add 16-bit monochrome ZWO-ASI support (not fully tested yet)
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
set(CCDLIB zwo_module)
|
||||
set(ZWOLIB ${CCDLIB} PARENT_SCOPE)
|
||||
set(CCDLIB devzwo)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(${CCDLIB} REQUIRED usefull_macros)
|
||||
|
||||
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})
|
||||
|
||||
add_library(${CCDLIB} SHARED ${SRC})
|
||||
target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES} -lASICamera2)
|
||||
|
||||
@@ -16,8 +16,495 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "zwofunc.h"
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <usefull_macros.h>
|
||||
#include <ASICamera2.h>
|
||||
|
||||
Camera ZWOcam;
|
||||
Focuser ZWOfocus;
|
||||
Wheel ZWOwheel;
|
||||
#include "ccdfunc.h"
|
||||
|
||||
extern Camera camera;
|
||||
extern Focuser focuser;
|
||||
extern Wheel wheel;
|
||||
|
||||
// remove all these after removing stubs!
|
||||
// VVV
|
||||
static const int filtermax = 5;
|
||||
static const float focmaxpos = 10.;
|
||||
static int filterpos = 0;
|
||||
static float focuserpos = 1.;
|
||||
// AAA
|
||||
|
||||
static int curbin = 1;
|
||||
static ASI_BOOL isdark = ASI_FALSE;
|
||||
static struct{
|
||||
float maxgain;
|
||||
float mingain;
|
||||
float maxbright;
|
||||
float minbright;
|
||||
} extrvalues = {0}; // extremal values
|
||||
|
||||
static double starttime = 0.; // time when exposure started
|
||||
static float exptime = 0.; // exposition time
|
||||
|
||||
static ASI_CAMERA_INFO caminfo = {0};
|
||||
|
||||
// setters and getters of some parameters
|
||||
static int zwo_setfloat(float f, ASI_CONTROL_TYPE t){
|
||||
DBG("Try to set float %f, type %d", f, t);
|
||||
long val = (long) f;
|
||||
if(ASI_SUCCESS != ASISetControlValue(caminfo.CameraID, t, val, ASI_FALSE)){
|
||||
DBG("FAILED");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
static int zwo_getfloat(float *f, ASI_CONTROL_TYPE t){
|
||||
if(!f) return FALSE;
|
||||
long val; ASI_BOOL aut = ASI_FALSE;
|
||||
if(ASI_SUCCESS != ASIGetControlValue(caminfo.CameraID, t, &val, &aut))
|
||||
return FALSE;
|
||||
*f = (float) val;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int asi_checkcam(){
|
||||
camera.Ndevices = ASIGetNumOfConnectedCameras();
|
||||
DBG("found %d ZWO's", camera.Ndevices);
|
||||
if(camera.Ndevices) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int campoll(capture_status *st, float *remain){
|
||||
if(!st) return FALSE;
|
||||
ASI_EXPOSURE_STATUS s;
|
||||
if(ASI_SUCCESS != ASIGetExpStatus(caminfo.CameraID, &s)) return FALSE;
|
||||
switch(s){
|
||||
case ASI_EXP_IDLE:
|
||||
*st = CAPTURE_NO;
|
||||
break;
|
||||
case ASI_EXP_WORKING:
|
||||
*st = CAPTURE_PROCESS;
|
||||
break;
|
||||
case ASI_EXP_SUCCESS:
|
||||
*st = CAPTURE_READY;
|
||||
break;
|
||||
default: // failed
|
||||
*st = CAPTURE_ABORTED;
|
||||
}
|
||||
if(remain){
|
||||
float diff = exptime - (dtime() - starttime);
|
||||
if(diff < 0.) diff = 0.;
|
||||
*remain = diff;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int camcapt(IMG *ima){
|
||||
if(!ima || !ima->data) return FALSE;
|
||||
unsigned char *d = (unsigned char *)ima->data;
|
||||
long image_size = ima->h * ima->w * 2;
|
||||
if(ASI_SUCCESS != ASIGetDataAfterExp(caminfo.CameraID, d, image_size)){
|
||||
printf("Couldn't read exposure data\n");
|
||||
return 1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void camcancel(){
|
||||
ASI_EXPOSURE_STATUS s;
|
||||
if(ASI_SUCCESS == ASIGetExpStatus(caminfo.CameraID, &s) && s == ASI_EXP_WORKING){
|
||||
ASIStopExposure(caminfo.CameraID);
|
||||
}
|
||||
}
|
||||
|
||||
static int setframetype(int l){
|
||||
if(l) isdark = ASI_FALSE;
|
||||
else isdark = ASI_TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int startcapt(){
|
||||
camcancel();
|
||||
//red("ISDARK = %s\n", isdark ? "true" : "false");
|
||||
if(ASI_SUCCESS == ASIStartExposure(caminfo.CameraID, isdark)){
|
||||
starttime = dtime();
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void asi_closecam(){
|
||||
FNAME();
|
||||
if(caminfo.CameraID){
|
||||
ASICloseCamera(caminfo.CameraID);
|
||||
caminfo.CameraID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int setdevno(int n){
|
||||
if(n > camera.Ndevices - 1 || n < 0) return FALSE;
|
||||
asi_closecam();
|
||||
if(ASI_SUCCESS != ASIGetCameraProperty(&caminfo, n)) return FALSE;
|
||||
DBG("Camera #%d, name: %s, ID: %d", n, caminfo.Name, caminfo.CameraID);
|
||||
DBG("WxH: %ldx%ld, %s", caminfo.MaxWidth, caminfo.MaxHeight, caminfo.IsColorCam == ASI_TRUE ? "color" : "monochrome");
|
||||
DBG("Pixel size: %1.1f mkm; gain: %1.2f e/ADU", caminfo.PixelSize, caminfo.ElecPerADU);
|
||||
#ifdef EBUG
|
||||
int *sup = caminfo.SupportedBins;
|
||||
while(*sup){
|
||||
green("Supported bin: %d\n", *sup++);
|
||||
}
|
||||
#endif
|
||||
camera.pixX = camera.pixY = (float)caminfo.PixelSize / 1e6; // um -> m
|
||||
camera.array = (frameformat){.w = caminfo.MaxWidth, .h = caminfo.MaxHeight, .xoff = 0, .yoff = 0};
|
||||
camera.field = camera.array; // initial setup (will update later)
|
||||
if(ASI_SUCCESS != ASIOpenCamera(caminfo.CameraID)){
|
||||
WARNX("Can't open device for camera %s", caminfo.Name);
|
||||
return FALSE;
|
||||
}
|
||||
if(ASI_SUCCESS != ASIInitCamera(caminfo.CameraID)){
|
||||
WARNX("Can't init device for camera %s", caminfo.Name);
|
||||
asi_closecam();
|
||||
return FALSE;
|
||||
}
|
||||
// get binning
|
||||
int imtype;
|
||||
if(ASI_SUCCESS == ASIGetROIFormat(caminfo.CameraID, &camera.field.w, &camera.field.h, &curbin, &imtype)){
|
||||
ASIGetStartPos(caminfo.CameraID, &camera.field.xoff, &camera.field.yoff);
|
||||
DBG("FIELD: %dx%d, offset %dx%d, binning %d", camera.field.w, camera.field.h, camera.field.xoff, camera.field.yoff, curbin);
|
||||
}
|
||||
int ncontrols = 0;
|
||||
if(ASI_SUCCESS == ASIGetNumOfControls(caminfo.CameraID, &ncontrols)){
|
||||
ASI_CONTROL_CAPS asicon;
|
||||
for(int i = 0; i < ncontrols; ++i){
|
||||
if(ASI_SUCCESS == ASIGetControlCaps(caminfo.CameraID, i, &asicon)){
|
||||
#ifdef EBUG
|
||||
green("Control #%d: '%s' ", i, asicon.Name);
|
||||
#endif
|
||||
long val;
|
||||
ASI_BOOL aut;
|
||||
if(ASI_SUCCESS == ASIGetControlValue(caminfo.CameraID, asicon.ControlType, &val, &aut)){
|
||||
#ifdef EBUG
|
||||
printf("curval: %ld%s, ", val, aut ? " (auto)": "");
|
||||
#endif
|
||||
switch(asicon.ControlType){ // get extremal values of brightness and gain
|
||||
case ASI_GAIN:
|
||||
extrvalues.maxgain = (float) asicon.MaxValue;
|
||||
extrvalues.mingain = (float) asicon.MinValue;
|
||||
break;
|
||||
case ASI_BRIGHTNESS:
|
||||
extrvalues.maxbright = (float) asicon.MaxValue;
|
||||
extrvalues.minbright = (float) asicon.MinValue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef EBUG
|
||||
printf("min/max: %ld/%ld; def: %ld, writeable: %d, descr: %s\n",
|
||||
asicon.MinValue, asicon.MaxValue, asicon.DefaultValue, asicon.IsWritable,
|
||||
asicon.Description);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int camsetbrig(float b){
|
||||
if(b < extrvalues.minbright || b > extrvalues.maxbright) return FALSE;
|
||||
return zwo_setfloat(b, ASI_BRIGHTNESS);
|
||||
}
|
||||
|
||||
static int camgetbrig(float *b){
|
||||
if(!b) return FALSE;
|
||||
return zwo_getfloat(b, ASI_BRIGHTNESS);
|
||||
}
|
||||
|
||||
static int camsetexp(float t){
|
||||
if(!zwo_setfloat(t*1e6, ASI_EXPOSURE)) return FALSE;
|
||||
exptime = t;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int camsetgain(float g){
|
||||
if(g < extrvalues.mingain || g > extrvalues.maxgain) return FALSE;
|
||||
return zwo_setfloat(g, ASI_GAIN);
|
||||
}
|
||||
|
||||
static int camgetgain(float *g){
|
||||
if(!g) return FALSE;
|
||||
return zwo_getfloat(g, ASI_GAIN);
|
||||
}
|
||||
|
||||
static int camsett(float t){
|
||||
if(!zwo_setfloat(1., ASI_FAN_ON)){
|
||||
DBG("Can't set fan on");
|
||||
return FALSE;
|
||||
}
|
||||
float f;
|
||||
if(zwo_getfloat(&f, ASI_FAN_ON)){
|
||||
DBG("FAN: %g", f);
|
||||
}
|
||||
if(!zwo_setfloat(t, ASI_TARGET_TEMP)){
|
||||
DBG("Can't set target temperature");
|
||||
return FALSE;
|
||||
}
|
||||
if(zwo_getfloat(&f, ASI_TARGET_TEMP)){
|
||||
DBG("Ttarg = %g", f);
|
||||
}
|
||||
if(!zwo_setfloat(1., ASI_COOLER_ON)){
|
||||
DBG("Can't set cooler on");
|
||||
return FALSE;
|
||||
}
|
||||
if(!zwo_getfloat(&f, ASI_COOLER_ON)) return FALSE;
|
||||
DBG("COOLERON = %g", f);
|
||||
usleep(100000);
|
||||
double t0 = dtime();
|
||||
float c, p, tn;
|
||||
while(dtime() - t0 < 10.){
|
||||
green("%.1f", dtime()-t0);
|
||||
zwo_getfloat(&f, ASI_FAN_ON);
|
||||
zwo_getfloat(&t, ASI_TARGET_TEMP);
|
||||
zwo_getfloat(&c, ASI_COOLER_ON);
|
||||
zwo_getfloat(&tn, ASI_TEMPERATURE);
|
||||
zwo_getfloat(&p, ASI_COOLER_POWER_PERC);
|
||||
printf("fan: %g, t: %g, cooler: %g, perc: %g, tnow: %g\n", f, t, c, p, tn/10.);
|
||||
if(f > 0.) break;
|
||||
usleep(100000);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static int camgett(float *t){
|
||||
if(!t) return FALSE;
|
||||
float curt;
|
||||
if(!zwo_getfloat(&curt, ASI_TEMPERATURE)) return FALSE;
|
||||
*t = curt / 10.;
|
||||
return TRUE;
|
||||
}
|
||||
// get Tbody & Thot unsupported
|
||||
static int gett(_U_ float *t){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int camsetbin(int h, int v){
|
||||
if(h != v) return FALSE;
|
||||
if(zwo_setfloat(1., ASI_HARDWARE_BIN)){
|
||||
curbin = h;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// unsupported, but return TRUE if have mechanical shutter
|
||||
static int camshutter(_U_ shutter_op s){
|
||||
if(!caminfo.MechanicalShutter) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// set ROI
|
||||
static int camsetgeom(frameformat *f){ // w,h, xoff, yoff
|
||||
if(!f) return FALSE;
|
||||
int imtype;
|
||||
DBG("w: %g, h: %g, bin: %d", (double)f->w / curbin, (double)f->h / curbin, curbin);
|
||||
if(ASI_SUCCESS != ASISetROIFormat(caminfo.CameraID, f->w/curbin, f->h/curbin, curbin, ASI_IMG_RAW16)){
|
||||
DBG(_("Can't set geometry"));
|
||||
return FALSE;
|
||||
}
|
||||
if(ASI_SUCCESS != ASIGetROIFormat(caminfo.CameraID, &f->w, &f->h, &curbin, &imtype)){
|
||||
DBG(_("Can't get geometry"));
|
||||
return FALSE;
|
||||
}
|
||||
DBG("w=%d, h=%d, bin=%d", f->w, f->h, curbin);
|
||||
if(ASI_SUCCESS != ASISetStartPos(caminfo.CameraID, f->xoff, f->yoff)){
|
||||
DBG("Can't set start pos");
|
||||
return FALSE;
|
||||
}
|
||||
if(ASI_SUCCESS != ASIGetStartPos(caminfo.CameraID, &f->xoff, &f->yoff)){
|
||||
DBG("Can't get start pos");
|
||||
return FALSE;
|
||||
}
|
||||
camera.geometry = *f;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int camgetnam(char *n, int l){
|
||||
strncpy(n, caminfo.Name, l);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int camgmg(float *mg){ // get max gain
|
||||
if(mg) *mg = extrvalues.maxgain;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int camggl(frameformat *max, frameformat *step){ // get geometry limits
|
||||
if(max) *max = camera.array;
|
||||
if(step) *step = (frameformat){1,1,1,1};
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int camgetbin(int *binh, int *binv){
|
||||
if(binh) *binh = curbin;
|
||||
if(binv) *binv = curbin;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int setfspd(int spd){ // set fast speed (0..3): 0 - 40% bandwidthovrl, 3 - 100%
|
||||
float bw = 40.;
|
||||
if(spd > 2) bw = 100.;
|
||||
else if(spd > 0) bw += 20. * spd;
|
||||
DBG("set BANDWIDTH to %g", bw);
|
||||
if(ASI_SUCCESS != zwo_setfloat(bw, ASI_BANDWIDTHOVERLOAD)){
|
||||
DBG("Can't set");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int camgetio(_U_ int *io){ // not supported
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int camfan(_U_ fan_speed spd){ // not supported
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* --------------- FOCUSER --------------- */
|
||||
static int focsetpos(_U_ int a, float n){
|
||||
if(n < 0. || n > focmaxpos) return FALSE;
|
||||
focuserpos = n;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int fochome(_U_ int a){
|
||||
focuserpos = 0.;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int focgetnam(char *n, int l){
|
||||
strncpy(n, "Dummy focuser", l);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int focpos(float *p){
|
||||
if(p) *p = focuserpos;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int focMp(float *p){
|
||||
if(p) *p = focmaxpos;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int focmp(float *p){
|
||||
if(p) *p = 0.;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* --------------- WHEEL --------------- */
|
||||
static int whlsetpos(int n){
|
||||
if(n > filtermax || n < 0) return FALSE;
|
||||
filterpos = n;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int whlgetpos(int *n){
|
||||
if(n) *n = filterpos;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int whlgmp(int *n){
|
||||
if(n) *n = filtermax;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int whlgetnam(char *n, int l){
|
||||
strncpy(n, "Dummy filter wheel", l);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int stub(){
|
||||
return FALSE;
|
||||
}
|
||||
static void vstub(){
|
||||
FNAME();
|
||||
return;
|
||||
}
|
||||
static int istub(_U_ int N){
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global objects: camera, focuser and wheel
|
||||
*/
|
||||
__attribute__ ((visibility("default"))) Camera camera = {
|
||||
.check = asi_checkcam,
|
||||
.close = asi_closecam,
|
||||
.pollcapture = campoll,
|
||||
.capture = camcapt,
|
||||
.cancel = camcancel,
|
||||
.startexposition = startcapt,
|
||||
// setters:
|
||||
.setDevNo = setdevno,
|
||||
.setbrightness = camsetbrig,
|
||||
.setexp = camsetexp,
|
||||
.setgain = camsetgain,
|
||||
.setT = camsett,
|
||||
.setbin = camsetbin,
|
||||
.setnflushes = istub,
|
||||
.shuttercmd = camshutter,
|
||||
.confio = istub,
|
||||
.setio = istub,
|
||||
.setframetype = setframetype,
|
||||
.setbitdepth = istub,
|
||||
.setfastspeed = setfspd,
|
||||
.setgeometry = camsetgeom,
|
||||
.setfanspeed = camfan,
|
||||
// getters:
|
||||
.getbrightness = camgetbrig,
|
||||
.getModelName = camgetnam,
|
||||
.getgain = camgetgain,
|
||||
.getmaxgain = camgmg,
|
||||
.getgeomlimits = camggl,
|
||||
.getTcold = camgett,
|
||||
.getThot = gett,
|
||||
.getTbody = gett,
|
||||
.getbin = camgetbin,
|
||||
.getio = camgetio,
|
||||
};
|
||||
|
||||
__attribute__ ((visibility("default"))) Focuser focuser = {
|
||||
.check = stub,
|
||||
.close = vstub,
|
||||
// setters:
|
||||
.setDevNo = setdevno,
|
||||
.setAbsPos = focsetpos,
|
||||
.home = fochome,
|
||||
// getters:
|
||||
.getModelName = focgetnam,
|
||||
.getTbody = gett,
|
||||
.getPos = focpos,
|
||||
.getMaxPos = focMp,
|
||||
.getMinPos = focmp,
|
||||
};
|
||||
|
||||
__attribute__ ((visibility("default"))) Wheel wheel = {
|
||||
.check = stub,
|
||||
.close = vstub,
|
||||
// setters
|
||||
.setDevNo = setdevno,
|
||||
.setPos = whlsetpos,
|
||||
// getters
|
||||
.getModelName = whlgetnam,
|
||||
.getTbody = gett,
|
||||
.getPos = whlgetpos,
|
||||
.getMaxPos = whlgmp,
|
||||
};
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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__
|
||||
Reference in New Issue
Block a user