mirror of
https://github.com/eddyem/CCD_Capture.git
synced 2026-03-20 08:40:56 +03:00
add Toupcam support; fix some bugs
This commit is contained in:
15
TOUPCAM_cameras/CMakeLists.txt
Normal file
15
TOUPCAM_cameras/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
set(CCDLIB devtoupcam)
|
||||
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(${CCDLIB} REQUIRED usefull_macros toupcam)
|
||||
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC)
|
||||
add_library(${CCDLIB} SHARED ${SRC})
|
||||
|
||||
target_include_directories(${CCDLIB} PRIVATE ${${CCDLIB}_INCLUDE_DIRS} ..)
|
||||
target_link_directories(${CCDLIB} PRIVATE ${${CCDLIB}_LIBRARY_DIRS})
|
||||
|
||||
target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES} -fPIC)
|
||||
install(TARGETS ${CCDLIB} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
639
TOUPCAM_cameras/toupcam.c
Normal file
639
TOUPCAM_cameras/toupcam.c
Normal file
@@ -0,0 +1,639 @@
|
||||
/*
|
||||
* This file is part of the CCD_Capture project.
|
||||
* Copyright 2026 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 <float.h>
|
||||
#include <string.h>
|
||||
#include <toupcam.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "ccdcapture.h"
|
||||
|
||||
extern cc_Camera camera;
|
||||
extern cc_Focuser focuser;
|
||||
extern cc_Wheel wheel;
|
||||
|
||||
// flags for image processing
|
||||
typedef enum{
|
||||
IM_SLEEP,
|
||||
IM_STARTED,
|
||||
IM_READY,
|
||||
IM_ERROR
|
||||
} imstate_t;
|
||||
|
||||
// devices
|
||||
static ToupcamDeviceV2 g_dev[TOUPCAM_MAX] = {0};
|
||||
static struct{
|
||||
ToupcamDeviceV2* dev;
|
||||
HToupcam hcam;
|
||||
unsigned long long flags;
|
||||
void* data;
|
||||
imstate_t state;
|
||||
} toupcam = {0};
|
||||
|
||||
static int camgetbp(uint8_t *bp);
|
||||
|
||||
// exptime and starting of exposition
|
||||
static double exptime = 0., starttime = 0.;
|
||||
|
||||
#define TCHECK() do{if(!toupcam.hcam) return FALSE;}while(0)
|
||||
|
||||
/**
|
||||
* @brief camcancel - camera.cancel - cancel exposition
|
||||
*/
|
||||
static void camcancel(){
|
||||
if(!toupcam.hcam) return;
|
||||
Toupcam_Trigger(toupcam.hcam, 0); // stop triggering
|
||||
Toupcam_Stop(toupcam.hcam);
|
||||
toupcam.state = IM_SLEEP;
|
||||
}
|
||||
|
||||
// close camera device
|
||||
static void camclose(){
|
||||
camcancel();
|
||||
if(toupcam.hcam){
|
||||
DBG("Close camera");
|
||||
Toupcam_Close(toupcam.hcam);
|
||||
toupcam.hcam = NULL;
|
||||
}
|
||||
if(toupcam.data){
|
||||
DBG("Free image data");
|
||||
free(toupcam.data);
|
||||
toupcam.data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initcam - init camera
|
||||
* @return FALSE if failed
|
||||
*/
|
||||
static int initcam(){
|
||||
camclose();
|
||||
unsigned N = Toupcam_EnumV2(g_dev);
|
||||
if(0 == N){
|
||||
DBG("Found 0 toupcams");
|
||||
return FALSE;
|
||||
}
|
||||
camera.Ndevices = (int) N;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// callback of image ready event
|
||||
static void EventCallback(unsigned nEvent, void _U_ *pCallbackCtx){
|
||||
DBG("CALLBACK with evt %d", nEvent);
|
||||
if(!toupcam.hcam || !toupcam.data){ DBG("NO data!"); return; }
|
||||
if(nEvent != TOUPCAM_EVENT_IMAGE){ DBG("Not image event"); return; }
|
||||
ToupcamFrameInfoV4 info = {0};
|
||||
if(Toupcam_PullImageV4(toupcam.hcam, toupcam.data, 0, 0, 0, &info) < 0){
|
||||
DBG("Error pulling image");
|
||||
toupcam.state = IM_ERROR;
|
||||
}else{
|
||||
DBG("Image ready!");
|
||||
toupcam.state = IM_READY;
|
||||
camera.geometry.h = info.v3.height;
|
||||
camera.geometry.w = info.v3.width;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setdevno - camera.setDevNo - set active device number
|
||||
* @param n - device no
|
||||
* @return FALSE if no such device or failed
|
||||
*/
|
||||
static int setdevno(int n){
|
||||
if(n < 0 || n >= camera.Ndevices) return FALSE;
|
||||
camclose(); // close if was opened
|
||||
toupcam.dev = &g_dev[n];
|
||||
toupcam.hcam = Toupcam_Open(g_dev[n].id);
|
||||
if(!toupcam.hcam){
|
||||
DBG("Can't open %dth camera", n);
|
||||
return FALSE;
|
||||
}
|
||||
DBG("Opened %s", toupcam.dev->displayname);
|
||||
DBG("Clear ROI");
|
||||
Toupcam_put_Roi(toupcam.hcam, 0, 0, 0, 0); // clear ROI
|
||||
// now fill camera geometry
|
||||
DBG("Get geometry");
|
||||
Toupcam_get_Size(toupcam.hcam, &camera.geometry.w, &camera.geometry.h);
|
||||
DBG("size (wxh): %dx%d", camera.geometry.w, camera.geometry.h);
|
||||
unsigned int xoff, yoff, h, w;
|
||||
DBG("Get ROI");
|
||||
Toupcam_get_Roi(toupcam.hcam, &xoff, &yoff, &w, &h);
|
||||
DBG("off (x/y): %d/%d; wxh: %dx%d", xoff, yoff, w, h);
|
||||
camera.array.xoff = camera.field.xoff = xoff;
|
||||
camera.array.yoff = camera.field.yoff = yoff;
|
||||
camera.array.w = camera.field.w = w;
|
||||
camera.array.h = camera.field.h = h;
|
||||
DBG("Get pixel size");
|
||||
Toupcam_get_PixelSize(toupcam.hcam, 0, &camera.pixX, &camera.pixY);
|
||||
DBG("pixsize (x/y): %g/%g", camera.pixX, camera.pixY);
|
||||
toupcam.flags = Toupcam_query_Model(toupcam.hcam)->flag;
|
||||
DBG("flags: 0x%llx", toupcam.flags);
|
||||
DBG("Allocate data (%d bytes)", 2 * camera.array.w * camera.array.h);
|
||||
toupcam.data = calloc(camera.array.w * camera.array.h, 2);
|
||||
#define OPT(opt, val, comment) do{DBG(comment); if(Toupcam_put_Option(toupcam.hcam, opt, val) < 0){ DBG("Can't put this option"); }}while(0)
|
||||
OPT(TOUPCAM_OPTION_TRIGGER, 1, "Software/simulated trigger mode");
|
||||
//OPT(TOUPCAM_OPTION_DFC, 0xff0000ff , "Enable dark field correction");
|
||||
//OPT(TOUPCAM_OPTION_FFC, 0xff0000ff, "Enable flatfield correction");
|
||||
OPT(TOUPCAM_OPTION_RAW, 1, "Put to RAW mode");
|
||||
#undef OPT
|
||||
toupcam.state = IM_SLEEP;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief campoll - camera.pollcapture - polling of capture process status
|
||||
* @param st (o) - status of capture process
|
||||
* @param remain (o) - time remain (s)
|
||||
* @return FALSE if error (exp aborted), TRUE while no errors
|
||||
*/
|
||||
static int campoll(cc_capture_status *st, float *remain){
|
||||
TCHECK();
|
||||
cc_capture_status curst;
|
||||
double tremain = 0.f;
|
||||
int ret = FALSE;
|
||||
switch(toupcam.state){
|
||||
case IM_SLEEP:
|
||||
curst = CAPTURE_NO;
|
||||
break;
|
||||
case IM_ERROR:
|
||||
curst = CAPTURE_ABORTED;
|
||||
break;
|
||||
case IM_READY:
|
||||
curst = CAPTURE_READY;
|
||||
ret = TRUE;
|
||||
break;
|
||||
default: // IM_PROCESS
|
||||
curst = CAPTURE_PROCESS;
|
||||
//DBG("exptime: %g, d-s: %g", exptime, sl_dtime() - starttime);
|
||||
tremain = exptime - (sl_dtime() - starttime);
|
||||
if(tremain < -2.0) curst = CAPTURE_ABORTED;
|
||||
else{
|
||||
if(tremain < 0.) tremain = 0.;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
//DBG("curst: %d, tremain: %g", curst, tremain);
|
||||
if(st) *st = curst;
|
||||
if(remain) *remain = (float)tremain;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief startexp - camera.startexposition - start exp if can
|
||||
* @return FALSE if failed
|
||||
*/
|
||||
static int startexp(){
|
||||
TCHECK();
|
||||
if(toupcam.state == IM_SLEEP){
|
||||
if(Toupcam_StartPullModeWithCallback(toupcam.hcam, EventCallback, NULL) < 0){
|
||||
WARNX("Can't run PullMode with Callback!");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if(Toupcam_Trigger(toupcam.hcam, 1) < 0) return FALSE;
|
||||
toupcam.state = IM_STARTED;
|
||||
starttime = sl_dtime();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camcapt - camera.capture - capture an image, struct `ima` should be prepared before
|
||||
* @param ima (o) - captured image
|
||||
* @return FALSE if failed or bad `ima`
|
||||
*/
|
||||
static int camcapt(cc_IMG *ima){
|
||||
TCHECK();
|
||||
if(!ima || !ima->data || !toupcam.data) return FALSE;
|
||||
uint8_t bp;
|
||||
if(!camgetbp(&bp)) bp = 16;
|
||||
size_t fullsz = camera.geometry.h * camera.geometry.w * (int)((bp+7)/8);
|
||||
memcpy(ima->data, toupcam.data, fullsz);
|
||||
ima->bitpix = bp;
|
||||
ima->h = camera.geometry.h;
|
||||
ima->w = camera.geometry.w;
|
||||
ima->bytelen = fullsz;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camsetbit - camera.setbitdepth
|
||||
* @param b - bit depth, 1 - high (16 bit), 0 - low (8 or other bit)
|
||||
* @return FALSE if failed
|
||||
*/
|
||||
static int camsetbit(int b){
|
||||
TCHECK();
|
||||
DBG("set bitdepth %d", b);
|
||||
if(Toupcam_put_Option(toupcam.hcam, TOUPCAM_OPTION_BITDEPTH, b) < 0) return FALSE;
|
||||
int opt = (b) ? TOUPCAM_PIXELFORMAT_RAW16 : TOUPCAM_PIXELFORMAT_RAW8;
|
||||
DBG("set pixel format %d", opt);
|
||||
if(Toupcam_put_Option(toupcam.hcam, TOUPCAM_OPTION_PIXEL_FORMAT, opt) < 0) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgetbp - camera.getbitpix - get bit depth in bits per pixel (8, 12, 16 etc)
|
||||
* @param bp (o) - bits per pixel
|
||||
* @return FALSE if failed
|
||||
*/
|
||||
static int camgetbp(uint8_t *bp){
|
||||
TCHECK();
|
||||
int b;
|
||||
DBG("Get bitdepth");
|
||||
if(Toupcam_get_Option(toupcam.hcam, TOUPCAM_OPTION_BITDEPTH, &b) < 0) return FALSE;
|
||||
DBG("bitdepth=%d", b);
|
||||
if(bp){
|
||||
if(b == 0) *bp = 8;
|
||||
else{
|
||||
DBG("Get pixformat");
|
||||
if(Toupcam_get_Option(toupcam.hcam, TOUPCAM_OPTION_PIXEL_FORMAT, &b) < 0) return FALSE;
|
||||
DBG("pixformat=%d", b);
|
||||
*bp = 8 + b*2;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camsetbrig - camera.setbrightness - set `brightness`
|
||||
* @param b - `brightness` value
|
||||
* @return FALSE if failed or no such property
|
||||
*/
|
||||
static int camsetbrig(float b){
|
||||
TCHECK();
|
||||
if(b < 0.f) return FALSE;
|
||||
int br = (int) b;
|
||||
DBG("Try to set brightness to %d", br);
|
||||
if(Toupcam_put_Brightness(toupcam.hcam, br)) return FALSE;
|
||||
DBG("OK");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgetbrig - camera.getbrightness - get `brightness` value
|
||||
* @param b (o) - brightness
|
||||
* @return FALSE if failed or no such property
|
||||
*/
|
||||
static int camgetbrig(float *b){
|
||||
TCHECK();
|
||||
int br;
|
||||
DBG("get brightness");
|
||||
if(Toupcam_get_Brightness(toupcam.hcam, &br) < 0) return FALSE;
|
||||
DBG("brightness=%d", br);
|
||||
if(b) *b = (float) br;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camsetexp - camera.setexp - set exposition time (s)
|
||||
* @param t - time (s)
|
||||
* @return FALSE if failed
|
||||
*/
|
||||
static int camsetexp(float t){
|
||||
TCHECK();
|
||||
if(t < FLT_EPSILON) return FALSE;
|
||||
unsigned int microseconds = (unsigned)(t * 1e6f);
|
||||
DBG("Set exptime to %dus", microseconds);
|
||||
if(Toupcam_put_ExpoTime(toupcam.hcam, microseconds) < 0) return FALSE;
|
||||
DBG("OK");
|
||||
exptime = (double) t;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camsetgain - camera.setgain - set gain
|
||||
* @param g - gain
|
||||
* @return FALSE if gain is wrong or no such property
|
||||
*/
|
||||
static int camsetgain(float g){
|
||||
TCHECK();
|
||||
unsigned short G = (unsigned short)(100.f * g);
|
||||
if(Toupcam_put_ExpoAGain(toupcam.hcam, G) < 0){
|
||||
unsigned short gmin, gmax, gdef;
|
||||
if(Toupcam_get_ExpoAGainRange(toupcam.hcam, &gmin, &gmax, &gdef) >= 0)
|
||||
WARNX("Gain out of range; min: %g, max: %g, default: %g",
|
||||
(float)gmin/100.f, (float)gmax/100.f, (float)gdef/100.f);
|
||||
return FALSE;
|
||||
}
|
||||
DBG("GAIN is %d", G);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgetgain - camera.getgain - getter
|
||||
* @param g (o) - gain
|
||||
* @return FALSE if have no such property
|
||||
*/
|
||||
static int camgetgain(float *g){
|
||||
TCHECK();
|
||||
unsigned short G;
|
||||
if(Toupcam_get_ExpoAGain(toupcam.hcam, &G) < 0) return FALSE;
|
||||
if(g) *g = (float)G / 100.f;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camsett - camera.setT - set cold side temperature
|
||||
* @param t - temperature (degC)
|
||||
* @return FALSE if failed
|
||||
*/
|
||||
static int camsett(float t){
|
||||
TCHECK();
|
||||
if(!(toupcam.flags & TOUPCAM_FLAG_TEC)) return FALSE; // cannot set temperature
|
||||
if(toupcam.flags & TOUPCAM_FLAG_TEC_ONOFF){
|
||||
int onoff = (t < 20.f) ? 1 : 0;
|
||||
if(Toupcam_put_Option(toupcam.hcam, TOUPCAM_OPTION_TEC, onoff) < 0) return FALSE;
|
||||
if(!onoff) return TRUE; // just turn off TEC if user wants >= 20degC
|
||||
}
|
||||
short T = (short) t * 10.f;
|
||||
DBG("Try to set T=%g", t);
|
||||
if(Toupcam_put_Temperature(toupcam.hcam, T) < 0) return FALSE;
|
||||
DBG("OK");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgett - camera.getTcold - get cold side T
|
||||
* @param t - temperature (degC)
|
||||
* @return FALSE if failed or no such property
|
||||
*/
|
||||
static int camgettc(float *t){
|
||||
TCHECK();
|
||||
if(!(toupcam.flags & TOUPCAM_FLAG_GETTEMPERATURE)) return FALSE; // cannot get T
|
||||
short T;
|
||||
DBG("Try to get T");
|
||||
if(Toupcam_get_Temperature(toupcam.hcam, &T) < 0) return FALSE;
|
||||
DBG("got %u", T);
|
||||
if(t) *t = ((float)T) / 10.f;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgett - camera.getThot - get hot side T
|
||||
* @param t - temperature (degC)
|
||||
* @return FALSE if failed or no such property
|
||||
*/
|
||||
static int camgetth(float _U_ *t){
|
||||
TCHECK();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgett - camera.getTbody - get body T
|
||||
* @param t - temperature (degC)
|
||||
* @return FALSE if failed or no such property
|
||||
*/
|
||||
static int gettb(float _U_ *t){
|
||||
TCHECK();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camsetbin - camera.setbin - binning setter
|
||||
* @param h, v - binning values (horiz/vert)
|
||||
* @return FALSE if failed or can't change binning
|
||||
*/
|
||||
static int camsetbin(int h, int v){
|
||||
TCHECK();
|
||||
if(h != v) return FALSE;
|
||||
DBG("Try to set binning %d/%d", h,v);
|
||||
if(Toupcam_put_Option(toupcam.hcam, TOUPCAM_OPTION_BINNING, h) < 0) return FALSE;
|
||||
DBG("OK");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgetbin - camera.getbin - binning getter
|
||||
* @param binh (o), binv (o) - current binning
|
||||
* @return FALSE if can't change binning
|
||||
*/
|
||||
static int camgetbin(int *binh, int *binv){
|
||||
TCHECK();
|
||||
int bin;
|
||||
DBG("Get binning");
|
||||
if(Toupcam_get_Option(toupcam.hcam, TOUPCAM_OPTION_BINNING, &bin) < 0) return FALSE;
|
||||
DBG("Got: %d", bin);
|
||||
if(binh) *binh = bin;
|
||||
if(binv) *binv = bin;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camshutter - camera.shuttercmd - work with shutter
|
||||
* @param s - new command for shutter (open/close etc)
|
||||
* @return FALSE if failed or can't
|
||||
*/
|
||||
static int camshutter(cc_shutter_op _U_ s){
|
||||
TCHECK();
|
||||
if(!(toupcam.flags & TOUPCAM_FLAG_GLOBALSHUTTER)) return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camsetgeom - camera.setgeometry - set geometry in UNBINNED coordinates
|
||||
* @param f (i) - new geometry
|
||||
* @return FALSE if can't change ROI or wrong geometry
|
||||
*/
|
||||
static int camsetgeom(cc_frameformat *f){
|
||||
TCHECK();
|
||||
if(Toupcam_put_Roi(toupcam.hcam, (unsigned) f->xoff, (unsigned) f->yoff, (unsigned) f->w, (unsigned) f->h) < 0) return FALSE;
|
||||
camera.geometry = *f;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgetnam - camera.getModelName - get model name
|
||||
* @param n (io) - prepared string for name
|
||||
* @param l - full length of n in bytes
|
||||
* @return FALSE if can't
|
||||
*/
|
||||
static int camgetnam(char *n, int l){
|
||||
TCHECK();
|
||||
if(!toupcam.dev) return FALSE;
|
||||
DBG("name: %s, strncpy to %d buf", toupcam.dev->displayname, l);
|
||||
strncpy(n, toupcam.dev->displayname, l);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgmg - camera.getmaxgain - get max available gain
|
||||
* @param mg (o) - max gain
|
||||
* @return FALSE if can't change gain
|
||||
*/
|
||||
static int camgmg(float _U_ *mg){
|
||||
TCHECK();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camggl - camera.getgeomlimits - get limits of ROI changing
|
||||
* @param max (o) - max ROI
|
||||
* @param step (o) - step for ROI change
|
||||
* @return
|
||||
*/
|
||||
static int camggl(cc_frameformat _U_ *max, cc_frameformat _U_ *step){
|
||||
TCHECK();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camgetio - camera.getio - get IO status
|
||||
* @param io (o) - GPIO status
|
||||
* @return FALSE if have no such property
|
||||
*/
|
||||
static int camgetio(int _U_ *io){
|
||||
TCHECK();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief camfan - camera.setfanspeed - set fan speed
|
||||
* @param spd - new speed
|
||||
* @return FALSE if can't
|
||||
*/
|
||||
static int camfan(cc_fan_speed spd){
|
||||
TCHECK();
|
||||
if(!(toupcam.flags & TOUPCAM_FLAG_FAN)) return FALSE; // don't have a fan
|
||||
DBG("Set fan to %d", spd);
|
||||
if(Toupcam_put_Option(toupcam.hcam, TOUPCAM_OPTION_FAN, (int)spd) < 0){ DBG("Can't put this option"); }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cc_hresult setopt(const char *str, cc_charbuff *ans){
|
||||
if(!str || !toupcam.hcam) return CC_RESULT_FAIL;
|
||||
char key[256], *kptr = key;
|
||||
snprintf(key, 255, "%s", str);
|
||||
char *val = cc_get_keyval(&kptr);
|
||||
if(!kptr || !val || strcmp(kptr, "opt")) return CC_RESULT_BADKEY;
|
||||
snprintf(key, 255, "%s", val); // now this is our opt[=val]
|
||||
kptr = key; val = cc_get_keyval(&kptr);
|
||||
int result = -1, par;
|
||||
int o;
|
||||
if(!sl_str2i(&o, kptr)){
|
||||
cc_charbufput(ans, "Wrong integer: ", 15);
|
||||
cc_charbufaddline(ans, kptr);
|
||||
}
|
||||
DBG("optD: %u", o);
|
||||
if(val){ // setter
|
||||
par = atoi(val);
|
||||
result = Toupcam_put_Option(toupcam.hcam, (unsigned) o, par);
|
||||
}else{ // getter
|
||||
result = Toupcam_get_Option(toupcam.hcam, (unsigned) o, &par);
|
||||
if(result >= 0){
|
||||
snprintf(key, 255, "Option %d have value %d", o, par);
|
||||
cc_charbufaddline(ans, key);
|
||||
}
|
||||
}
|
||||
if(result < 0 ) return CC_RESULT_FAIL;
|
||||
return CC_RESULT_OK;
|
||||
}
|
||||
|
||||
static cc_hresult getpf(const char *str, cc_charbuff *ans){
|
||||
if(!str || !toupcam.hcam) return CC_RESULT_FAIL;
|
||||
int N;
|
||||
if(Toupcam_get_PixelFormatSupport(toupcam.hcam, -1, &N) < 0) return CC_RESULT_FAIL;
|
||||
cc_charbufaddline(ans, "Supported formats:");
|
||||
for(int f = 0; f < N; ++f){
|
||||
int pf;
|
||||
if(Toupcam_get_PixelFormatSupport(toupcam.hcam, f, &pf) < 0) continue;
|
||||
cc_charbufaddline(ans, Toupcam_get_PixelFormatName(pf));
|
||||
}
|
||||
return CC_RESULT_SILENCE;
|
||||
}
|
||||
|
||||
// cmd, help, checker, pointer, min, max, type
|
||||
static cc_parhandler_t handlers[] = {
|
||||
{"opt", "set/get given option, like opt=0x08=1 (TOUPCAM_OPTION_TEC ON) or opt=0x08 (check)", setopt, NULL, NULL, NULL, 0},
|
||||
{"pixfmt", "get list of supported pixel formats", getpf, NULL, NULL, NULL, 0},
|
||||
CC_PARHANDLER_END
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief plugincmd - custom camera plugin command (get string as input, send string as output or NULL if failed)
|
||||
* @param str
|
||||
* @param buf
|
||||
* @return
|
||||
*/
|
||||
static cc_hresult plugincmd(const char _U_ *str, cc_charbuff _U_ *buf){
|
||||
return cc_plugin_customcmd(str, handlers, buf);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// stub for nonexistant properties
|
||||
static int stub(){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// stub for void nonexistant functions
|
||||
static void vstub(){
|
||||
FNAME();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// stub for nonexistant integer setters
|
||||
static int istub(int _U_ N){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global objects: camera, focuser and wheel
|
||||
*/
|
||||
__attribute__ ((visibility("default"))) cc_Camera camera = {
|
||||
.check = initcam,
|
||||
.Ndevices = 0,
|
||||
.close = camclose,
|
||||
.pollcapture = campoll,
|
||||
.capture = camcapt,
|
||||
.cancel = camcancel,
|
||||
.startexposition = startexp,
|
||||
.plugincmd = plugincmd,
|
||||
// setters:
|
||||
.setDevNo = setdevno,
|
||||
.setbrightness = camsetbrig,
|
||||
.setexp = camsetexp,
|
||||
.setgain = camsetgain,
|
||||
.setT = camsett,
|
||||
.setbin = camsetbin,
|
||||
.setnflushes = istub,
|
||||
.shuttercmd = camshutter,
|
||||
.confio = istub,
|
||||
.setio = istub,
|
||||
.setframetype = istub,
|
||||
.setbitdepth = camsetbit,
|
||||
.setfastspeed = istub,
|
||||
.setgeometry = camsetgeom,
|
||||
.setfanspeed = camfan,
|
||||
// getters:
|
||||
.getbitpix = camgetbp,
|
||||
.getbrightness = camgetbrig,
|
||||
.getModelName = camgetnam,
|
||||
.getgain = camgetgain,
|
||||
.getmaxgain = camgmg,
|
||||
.getgeomlimits = camggl,
|
||||
.getTcold = camgettc,
|
||||
.getThot = camgetth,
|
||||
.getTbody = gettb,
|
||||
.getbin = camgetbin,
|
||||
.getio = camgetio,
|
||||
// these parameters could be filled after initialization
|
||||
.pixX = 10.,
|
||||
.pixY = 10.,
|
||||
.field = (cc_frameformat){.h = 1024, .w = 1024, .xoff = 10, .yoff = 10},
|
||||
.array = (cc_frameformat){.h = 1050, .w = 1050, .xoff = 0, .yoff = 0},
|
||||
.geometry = {0},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user