From 89e23066e26f572c1ebc2fab9e0f539cd5d51912 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Thu, 12 Feb 2026 17:53:15 +0300 Subject: [PATCH] toupcam ready (without GPIO); also fixed some bugs --- TOUPCAM_cameras/toupcam.c | 228 +++++++++++++++++++++++++++----------- ccdcapture.h | 2 +- ccdfunc.c | 3 +- locale/ru/messages.po | 26 ++--- locale/ru/ru.po | 26 ++--- server.c | 12 +- 6 files changed, 202 insertions(+), 95 deletions(-) diff --git a/TOUPCAM_cameras/toupcam.c b/TOUPCAM_cameras/toupcam.c index 7819866..c299cc1 100644 --- a/TOUPCAM_cameras/toupcam.c +++ b/TOUPCAM_cameras/toupcam.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -38,11 +39,17 @@ typedef enum{ // devices static ToupcamDeviceV2 g_dev[TOUPCAM_MAX] = {0}; static struct{ - ToupcamDeviceV2* dev; - HToupcam hcam; - unsigned long long flags; - void* data; - imstate_t state; + ToupcamDeviceV2* dev; // device + HToupcam hcam; // hcam for all functions + unsigned long long flags; // flags (read on connect) + pthread_mutex_t mutex; // lock mutex for `data` writing/reading + void* data; // image data + size_t imsz; // size of current image in bytes + imstate_t state; // current state + uint64_t imseqno; // number of image from connection + uint64_t lastcapno; // last captured image number + uint8_t bytepix; // bytes per pixel + int curbin; // current binning } toupcam = {0}; static int camgetbp(uint8_t *bp); @@ -52,13 +59,38 @@ static double exptime = 0., starttime = 0.; #define TCHECK() do{if(!toupcam.hcam) return FALSE;}while(0) +// return constant string with error code description +static const char *errcode(int ecode){ + switch(ecode){ + case 0: return "S_OK"; + case 1: return "S_FALSE"; + case 0x8000ffff: return "E_UNEXPECTED"; + case 0x80004001: return "E_NOTIMPL"; + case 0x80004002: return "E_NOINTERFACE"; + case 0x80070005: return "E_ACCESSDENIED"; + case 0x8007000e: return "E_OUTOFMEMORY"; + case 0x80070057: return "E_INVALIDARG"; + case 0x80004003: return "E_POINTER"; + case 0x80004005: return "E_FAIL"; + case 0x8001010e: return "E_WRONG_THREAD"; + case 0x8007001f: return "E_GEN_FAILURE"; + case 0x800700aa: return "E_BUSY"; + case 0x8000000a: return "E_PENDING"; + case 0x8001011f: return "E_TIMEOUT"; + case 0x80072743: return "E_UNREACH"; + default: return "Unknown error"; + } +} + /** * @brief camcancel - camera.cancel - cancel exposition */ static void camcancel(){ if(!toupcam.hcam) return; - Toupcam_Trigger(toupcam.hcam, 0); // stop triggering - Toupcam_Stop(toupcam.hcam); + int e = Toupcam_Trigger(toupcam.hcam, 0); // stop triggering + if(e < 0) WARNX("Can't trigger 0: %s", errcode(e)); + e = Toupcam_Stop(toupcam.hcam); + if(e < 0) WARNX("Can't stop: %s", errcode(e)); toupcam.state = IM_SLEEP; } @@ -92,23 +124,6 @@ static int initcam(){ 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 @@ -143,15 +158,20 @@ static int setdevno(int n){ 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); + DBG("Allocate data (%d bytes: 2*%d*%d)", 2 * camera.array.w * camera.array.h, 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) + // 12 frames/sec 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; + toupcam.imseqno = toupcam.lastcapno = 0; + uint8_t bp; + if(!camera.getbitpix(&bp)) toupcam.bytepix = 2; + else toupcam.bytepix = (bp+7)/8; + if(!camera.getbin(NULL, NULL)) toupcam.curbin = 1; + pthread_mutex_init(&toupcam.mutex, NULL); return TRUE; } @@ -193,6 +213,35 @@ static int campoll(cc_capture_status *st, float *remain){ return ret; } +// 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}; + //DBG("LOCK"); + pthread_mutex_lock(&toupcam.mutex); + if(Toupcam_PullImageV4(toupcam.hcam, toupcam.data, 0, 0, 0, &info) < 0){ + DBG("Error pulling image"); + toupcam.state = IM_ERROR; + }else{ + ++toupcam.imseqno; + DBG("Image %lu (%dx%d) ready!", toupcam.imseqno, info.v3.width, info.v3.height); + toupcam.state = IM_READY; + toupcam.imsz = info.v3.height * info.v3.width * toupcam.bytepix; + // geometry.h/w WITHOUT binning! + camera.geometry.h = info.v3.height * toupcam.curbin; + camera.geometry.w = info.v3.width * toupcam.curbin; + if(toupcam.imseqno - toupcam.lastcapno > 5){ + WARNX("5 uncaptured images -> cancel"); + camera.cancel(); + toupcam.imseqno = toupcam.lastcapno; + } + } + pthread_mutex_unlock(&toupcam.mutex); + //DBG("UNLOCK"); +} + /** * @brief startexp - camera.startexposition - start exp if can * @return FALSE if failed @@ -205,7 +254,16 @@ static int startexp(){ return FALSE; } } - if(Toupcam_Trigger(toupcam.hcam, 1) < 0) return FALSE; + // Ask to trigger for several images (maximal speed available) + int e = Toupcam_Trigger(toupcam.hcam, 100); + if(e < 0){ + DBG("Can't ask for images stream: %s; try 1", errcode(e)); + e = Toupcam_Trigger(toupcam.hcam, 1); + if(e < 0){ + WARNX("Can't ask for next image: %s", errcode(e)); + return FALSE; + } + } toupcam.state = IM_STARTED; starttime = sl_dtime(); return TRUE; @@ -219,14 +277,22 @@ static int startexp(){ 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); + //DBG("LOCK"); + pthread_mutex_lock(&toupcam.mutex); + size_t fullsz = ima->w * ima->h * toupcam.bytepix; + if(toupcam.imsz != fullsz){ + if(toupcam.imsz < fullsz) fullsz = toupcam.imsz; + int realw = camera.geometry.w / toupcam.curbin; + if(ima->w != realw) ima->w = realw; + ima->h = fullsz / realw / toupcam.bytepix; + WARNX("Asked image size (%zd) not equal real (%zd); set w=%d, h=%d!", + ima->w * ima->h * toupcam.bytepix, toupcam.imsz, ima->w, ima->h); + } memcpy(ima->data, toupcam.data, fullsz); - ima->bitpix = bp; - ima->h = camera.geometry.h; - ima->w = camera.geometry.w; - ima->bytelen = fullsz; + ima->bitpix = toupcam.bytepix * 8; + toupcam.lastcapno = toupcam.imseqno; + pthread_mutex_unlock(&toupcam.mutex); + //DBG("UNLOCK"); return TRUE; } @@ -239,9 +305,12 @@ static int camsetbit(int b){ TCHECK(); DBG("set bitdepth %d", b); if(Toupcam_put_Option(toupcam.hcam, TOUPCAM_OPTION_BITDEPTH, b) < 0) return FALSE; + DBG("OK"); 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; + DBG("OK"); + toupcam.bytepix = (b) ? 2 : 1; return TRUE; } @@ -275,10 +344,17 @@ static int camgetbp(uint8_t *bp){ */ static int camsetbrig(float b){ TCHECK(); - if(b < 0.f) return FALSE; + if(b < -255.f || b > 255.f){ + WARNX("Available brightness: -255..255"); + return FALSE; + } int br = (int) b; DBG("Try to set brightness to %d", br); - if(Toupcam_put_Brightness(toupcam.hcam, br)) return FALSE; + int e = Toupcam_put_Brightness(toupcam.hcam, br); + if(e < 0){ + WARNX("Can't set brightness: %s", errcode(e)); + return FALSE; + } DBG("OK"); return TRUE; } @@ -308,7 +384,11 @@ static int camsetexp(float t){ 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; + int e = Toupcam_put_ExpoTime(toupcam.hcam, microseconds); + if(e < 0){ + WARNX("Can't set exp: %s", errcode(e)); + return FALSE; + } DBG("OK"); exptime = (double) t; return TRUE; @@ -376,7 +456,11 @@ static int camgettc(float *t){ 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; + int g = Toupcam_get_Temperature(toupcam.hcam, &T); + if(g < 0){ + WARNX("Can't get T: %s", errcode(g)); + return FALSE; + } DBG("got %u", T); if(t) *t = ((float)T) / 10.f; return TRUE; @@ -412,6 +496,14 @@ static int camsetbin(int h, int v){ 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; + if(Toupcam_get_Option(toupcam.hcam, TOUPCAM_OPTION_BINNING, &toupcam.curbin) < 0){ + DBG("CANT get binning"); + return FALSE; + } + if(h != toupcam.curbin){ + DBG("Wrong binning: %d instead of %d!", toupcam.curbin, h); + return FALSE; + } DBG("OK"); return TRUE; } @@ -423,12 +515,11 @@ static int camsetbin(int h, int v){ */ 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; + if(Toupcam_get_Option(toupcam.hcam, TOUPCAM_OPTION_BINNING, &toupcam.curbin) < 0) return FALSE; + DBG("Got: %d", toupcam.curbin); + if(binh) *binh = toupcam.curbin; + if(binv) *binv = toupcam.curbin; return TRUE; } @@ -437,10 +528,17 @@ static int camgetbin(int *binh, int *binv){ * @param s - new command for shutter (open/close etc) * @return FALSE if failed or can't */ -static int camshutter(cc_shutter_op _U_ s){ +static int camshutter(cc_shutter_op s){ TCHECK(); if(!(toupcam.flags & TOUPCAM_FLAG_GLOBALSHUTTER)) return FALSE; - return FALSE; + if(s != SHUTTER_OPEN && s != SHUTTER_CLOSE) return FALSE; + int val = (s == SHUTTER_OPEN) ? 0 : 1; + int e = Toupcam_put_Option(toupcam.hcam, TOUPCAM_OPTION_MECHANICALSHUTTER, val); + if(e < 0){ + WARNX("Can't run shutter command: %s", errcode(e)); + return FALSE; + } + return TRUE; } /** @@ -474,8 +572,11 @@ static int camgetnam(char *n, int l){ * @param mg (o) - max gain * @return FALSE if can't change gain */ -static int camgmg(float _U_ *mg){ +static int camgmg(float *mg){ TCHECK(); + unsigned short gmin, gmax, gdef; + if(Toupcam_get_ExpoAGainRange(toupcam.hcam, &gmin, &gmax, &gdef) < 0) return FALSE; + if(mg) *mg = gmax; return FALSE; } @@ -485,18 +586,10 @@ static int camgmg(float _U_ *mg){ * @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){ +static int camggl(cc_frameformat *max, cc_frameformat _U_ *step){ TCHECK(); + if(max) *max = camera.array; + if(step) *step = (cc_frameformat){.w = 1, .h = 1, .xoff = 1, .yoff = 1}; return FALSE; } @@ -509,8 +602,11 @@ 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; + if(Toupcam_put_Option(toupcam.hcam, TOUPCAM_OPTION_FAN, (int)spd) < 0){ + DBG("Can't put this option"); + return FALSE; + } + return TRUE; } static cc_hresult setopt(const char *str, cc_charbuff *ans){ @@ -572,18 +668,18 @@ 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; -} +#if 0 // stub for void nonexistant functions static void vstub(){ FNAME(); return; } #endif +// stub for nonexistant properties +static int stubi(int _U_ *N){ + return FALSE; +} // stub for nonexistant integer setters static int istub(int _U_ N){ return FALSE; @@ -628,7 +724,7 @@ __attribute__ ((visibility("default"))) cc_Camera camera = { .getThot = camgetth, .getTbody = gettb, .getbin = camgetbin, - .getio = camgetio, + .getio = stubi, // these parameters could be filled after initialization .pixX = 10., .pixY = 10., diff --git a/ccdcapture.h b/ccdcapture.h index e92253c..a07492a 100644 --- a/ccdcapture.h +++ b/ccdcapture.h @@ -145,7 +145,7 @@ typedef struct{ float pixX, pixY; // pixel size in um cc_frameformat field; // max field of view (full CCD field without overscans) cc_frameformat array; // array format (with overscans) - cc_frameformat geometry; // current geometry settings (as in setgeometry) + cc_frameformat geometry; // current geometry settings (as in setgeometry) WITHOUT BINNING!!! } cc_Camera; // focuser diff --git a/ccdfunc.c b/ccdfunc.c index 6cf5dad..5f2aa05 100644 --- a/ccdfunc.c +++ b/ccdfunc.c @@ -680,7 +680,7 @@ int prepare_ccds(){ if(GP->hbin < 1) GP->hbin = 1; if(GP->vbin < 1) GP->vbin = 1; if(!camera->setbin || !camera->setbin(GP->hbin, GP->vbin)){ - ERRX(_("Can't set binning %dx%d"), GP->hbin, GP->vbin); + WARNX(_("Can't set binning %dx%d"), GP->hbin, GP->vbin); if(camera->getbin) camera->getbin(&GP->hbin, &GP->vbin); } if(GP->X0 < 0) GP->X0 = x0; // default values @@ -734,6 +734,7 @@ DBG("w=%d, h=%d", raw_width, raw_height); uint16_t *img = MALLOC(uint16_t, raw_width * raw_height); DBG("\n\nAllocated image 2x%dx%d=%d", raw_width, raw_height, 2 * raw_width * raw_height); cc_IMG ima = {.data = img, .w = raw_width, .h = raw_height}; + if(!camera->getbitpix || !camera->getbitpix(&ima.bitpix)) ima.bitpix = 16; if(GP->nframes < 1) GP->nframes = 1; for(int j = 0; j < GP->nframes; ++j){ TIMEINIT(); diff --git a/locale/ru/messages.po b/locale/ru/messages.po index 17ba715..48461b4 100644 --- a/locale/ru/messages.po +++ b/locale/ru/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-11 17:12+0300\n" +"POT-Creation-Date: 2026-02-12 17:40+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -495,12 +495,12 @@ msgstr "" msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:683 server.c:280 +#: ccdfunc.c:683 server.c:284 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:695 server.c:281 +#: ccdfunc.c:695 server.c:285 msgid "Can't set given geometry" msgstr "" @@ -543,45 +543,45 @@ msgstr "" msgid "Can't get current binning" msgstr "" -#: ccdfunc.c:741 +#: ccdfunc.c:742 #, c-format msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:742 ccdfunc.c:819 server.c:149 server.c:150 +#: ccdfunc.c:743 ccdfunc.c:820 server.c:153 server.c:154 msgid "Camera plugin have no function `start exposition`" msgstr "" -#: ccdfunc.c:744 ccdfunc.c:821 server.c:155 server.c:156 +#: ccdfunc.c:745 ccdfunc.c:822 server.c:159 server.c:160 msgid "Can't start exposition" msgstr "" -#: ccdfunc.c:749 +#: ccdfunc.c:750 msgid "Can't capture image" msgstr "" -#: ccdfunc.c:752 +#: ccdfunc.c:753 msgid "Read grabbed image" msgstr "" -#: ccdfunc.c:754 ccdfunc.c:834 server.c:173 server.c:174 +#: ccdfunc.c:755 ccdfunc.c:835 server.c:177 server.c:178 msgid "Camera plugin have no function `capture`" msgstr "" -#: ccdfunc.c:756 ccdfunc.c:835 +#: ccdfunc.c:757 ccdfunc.c:836 msgid "Can't grab image" msgstr "" -#: ccdfunc.c:770 client.c:289 +#: ccdfunc.c:771 client.c:289 #, c-format msgid "%d seconds till pause ends\n" msgstr "" -#: ccdfunc.c:832 +#: ccdfunc.c:833 msgid "Some error when capture" msgstr "" -#: server.c:201 +#: server.c:205 msgid "No camera device" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index bd9b009..ad61e76 100644 --- a/locale/ru/ru.po +++ b/locale/ru/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" - "POT-Creation-Date: 2026-02-11 17:12+0300\n" + "POT-Creation-Date: 2026-02-12 17:25+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -21,7 +21,7 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n" msgid "%.1f seconds till exposition ends" msgstr "%.1f секунд до окончания экспозиции" -#: ccdfunc.c:770 client.c:289 +#: ccdfunc.c:771 client.c:289 #, c-format msgid "%d seconds till pause ends\n" msgstr "%d секунд до окончания паузы\n" @@ -70,12 +70,12 @@ msgstr " msgid "Camera plugin have no fun speed setter" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:754 ccdfunc.c:834 server.c:173 server.c:174 +#: ccdfunc.c:755 ccdfunc.c:835 server.c:177 server.c:178 #, fuzzy msgid "Camera plugin have no function `capture`" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:742 ccdfunc.c:819 server.c:149 server.c:150 +#: ccdfunc.c:743 ccdfunc.c:820 server.c:153 server.c:154 #, fuzzy msgid "Camera plugin have no function `start exposition`" msgstr "У плагина камеры нет особых команд" @@ -90,7 +90,7 @@ msgstr " msgid "Camera plugin have no temperature setter" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:749 +#: ccdfunc.c:750 msgid "Can't capture image" msgstr "Не могу захватить изображение" @@ -122,7 +122,7 @@ msgstr " msgid "Can't get max wheel position" msgstr "Не могу определить предельную позицию колеса" -#: ccdfunc.c:756 ccdfunc.c:835 +#: ccdfunc.c:757 ccdfunc.c:836 msgid "Can't grab image" msgstr "Не могу захватить изображение" @@ -178,7 +178,7 @@ msgstr " msgid "Can't set active wheel number" msgstr "Не могу установить номер активного колеса" -#: ccdfunc.c:683 server.c:280 +#: ccdfunc.c:683 server.c:284 #, c-format msgid "Can't set binning %dx%d" msgstr "Не могу установить биннинг %dx%d" @@ -206,7 +206,7 @@ msgstr " msgid "Can't set gain to %g" msgstr "Не могу установить Gain в %g" -#: ccdfunc.c:695 server.c:281 +#: ccdfunc.c:695 server.c:285 msgid "Can't set given geometry" msgstr "Не могу установить геометрию" @@ -229,11 +229,11 @@ msgstr " msgid "Can't set wheel position %d" msgstr "Не могу установить положение колеса %d" -#: ccdfunc.c:744 ccdfunc.c:821 server.c:155 server.c:156 +#: ccdfunc.c:745 ccdfunc.c:822 server.c:159 server.c:160 msgid "Can't start exposition" msgstr "Не могу начать экспозицию" -#: ccdfunc.c:741 +#: ccdfunc.c:742 #, c-format msgid "Capture frame %d" msgstr "Захват кадра %d" @@ -308,7 +308,7 @@ msgstr " msgid "N flushes before exposing (default: 1)" msgstr "N засвечиваний перед экспозицией (по умолчанию: 1)" -#: server.c:201 +#: server.c:205 msgid "No camera device" msgstr "Не указано устройство камеры" @@ -333,7 +333,7 @@ msgstr " msgid "Pixel size: %g x %g" msgstr "Размер пикселя: %g x %g" -#: ccdfunc.c:752 +#: ccdfunc.c:753 msgid "Read grabbed image" msgstr "Считывание изображения" @@ -366,7 +366,7 @@ msgstr " msgid "Shutter command: %s\n" msgstr "Команда затвора: %s\n" -#: ccdfunc.c:832 +#: ccdfunc.c:833 msgid "Some error when capture" msgstr "Ошибка при захвате" diff --git a/server.c b/server.c index 3b294ee..364163d 100644 --- a/server.c +++ b/server.c @@ -63,7 +63,8 @@ strpair allcommands[] = { { CC_CMD_CAMFANSPD, "fan speed of camera" }, { CC_CMD_CONFIO, "camera IO configuration" }, { CC_CMD_DARK, "don't open shutter @ exposure" }, - { CC_CMD_EXPSTATE, "get exposition state" }, + { CC_CMD_EXPSTATE, "get exposition state (0: cancel, 1: capturing, 2: frame ready, 3: error) " + "or set (0: cancel, 1: start exp)\n also get camflags (bits: 0-start capture, 1-cancel, 2-restart server" }, { CC_CMD_EXPOSITION, "exposition time" }, { CC_CMD_FASTSPD, "fast readout speed" }, { CC_CMD_FILENAME, "save file with this name, like file.fits" }, @@ -134,6 +135,9 @@ static void fixima(){ ima->w = raw_width; if(!camera->getbitpix || !camera->getbitpix(&ima->bitpix)) ima->bitpix = 16; if(ima->bitpix < 8 || ima->bitpix > 16) ima->bitpix = 16; // use maximum in any strange cases + DBG("bitpix=%d", ima->bitpix); + GP->_8bit = (ima->bitpix < 9) ? 1 : 0; + DBG("GP->_8bit=%d", GP->_8bit); ima->bytelen = raw_height * raw_width * cc_getNbytes(ima); DBG("new image: %dx%d", raw_width, raw_height); } @@ -641,6 +645,11 @@ static cc_hresult expstatehandler(_U_ int fd, _U_ const char *key, _U_ const cha return CC_RESULT_OK; } else if(n == CAMERA_CAPTURE){ // start exposition + if(GP->exptime < 1e-9){ + snprintf(buf, 63, CC_CMD_EXPOSITION "=%g", GP->exptime); + cc_sendstrmessage(fd, buf); + return CC_RESULT_FAIL; + } TIMESTAMP("Get FLAG_STARTCAPTURE"); TIMEINIT(); camflags |= FLAG_STARTCAPTURE; @@ -987,6 +996,7 @@ static cc_hresult inftyhandler(int fd, _U_ const char *key, const char *val){ if(val){ int i = atoi(val); infty = (i) ? 1 : 0; + if(!infty) camflags |= FLAG_CANCEL; } snprintf(buf, 63, CC_CMD_INFTY "=%d", infty); if(!cc_sendstrmessage(fd, buf)) return CC_RESULT_DISCONNECTED;