diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e12707a --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*~ +*.bak +*.bck +*.o +.hg* +.dropbox.attr diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..48318d0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 2.6) +set(PROJ takepic) +project(${PROJ}) +set(VERSION "0.2.0") +set(CMAKE_COLOR_MAKEFILE ON) +if(DEFINED DEBUG) + add_definitions(-DEBUG) +endif() +if(DEFINED CMAKE_INSTALL_PREFIX AND CMAKE_INSTALL_PREFIX MATCHES "/usr/local") + set(CMAKE_INSTALL_PREFIX "/usr") +endif() +message("Install dir prefix: ${CMAKE_INSTALL_PREFIX}") +#aux_source_directory(. SOURCES) +set(SOURCES takepic.c usage.c) +if(NOT DEFINED NOBTA) + set(SOURCES ${SOURCES} bta_print.c) + add_definitions(-DUSE_BTA) +endif() +set(LCPATH locale/ru) +set(CFLAGS -O3 -Wall -Werror -W -std=c99) +set(PO_FILE ${LCPATH}/messages.po) +set(MO_FILE ${LCPATH}/LC_MESSAGES/${PROJ}.mo) +set(RU_FILE ${LCPATH}/ru.po) +find_package(PkgConfig REQUIRED) +set(MODULES cfitsio>=3.0 fli>=1.71) +if(DEFINED USEPNG) + set(MODULES ${MODULES} libpng>=1.2) + add_definitions(-DUSEPNG) +endif() +pkg_check_modules(${PROJ} REQUIRED ${MODULES}) +if(DEFINED USERAW) + add_definitions(-DUSERAW) +endif() +add_executable(${PROJ} ${SOURCES} ${PO_FILE} ${MO_FILE}) +target_link_libraries(${PROJ} ${${PROJ}_LIBRARIES}) +include_directories(${${PROJ}_INCLUDE_DIRS}) +link_directories(${${PROJ}_LIBRARY_DIRS}) +add_definitions(${CFLAGS} -DLOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/share/locale\" + -DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\") + +# Installation of the program +INSTALL(FILES ${MO_FILE} DESTINATION "share/locale/ru/LC_MESSAGES") + #PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +INSTALL(TARGETS ${PROJ} DESTINATION "bin") + #PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +# Script to be executed at installation time (kind of post-intallation script) to +# change the right accesses on the installed files +#INSTALL(SCRIPT inst.cmake) + +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() +add_custom_command( + OUTPUT ${PO_FILE} + COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --from-code=koi8-r ${SOURCES} -c -k_ -kN_ -o ${PO_FILE} + COMMAND sed 's/charset=UTF-8/charset=koi8-r/' ${PO_FILE} | enconv > tmp && mv -f tmp ${PO_FILE} + COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} -Uis ${RU_FILE} ${PO_FILE} + DEPENDS ${SOURCES}) +add_custom_command( + OUTPUT ${MO_FILE} + COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} ${RU_FILE} -o ${MO_FILE} + DEPENDS ${RU_FILE}) diff --git a/README b/README new file mode 100644 index 0000000..e59b8d6 --- /dev/null +++ b/README @@ -0,0 +1,16 @@ +1. cmake . +2. make +3. [make install] or just copy file takepic wherever you want + +File bta_print.c needed to fill specific FITS keys for BTA telescope +If your want use this outside SAO RAS localnet, write: +1. cmake -DNOBTA=1 . +2. make ... + + +If you wish to save not only FITS, define: +* -DUSERAW=1 to save raw data +* -DUSEPNG=1 to save png data + +define +* -DEBUG=1 for debug info diff --git a/README-func b/README-func new file mode 100644 index 0000000..ac69b6f --- /dev/null +++ b/README-func @@ -0,0 +1,157 @@ +// переменные, типы + flidomain_t = METHOD | DEVICE; + // METHOD: FLIDOMAIN_PARALLEL_PORT, FLIDOMAIN_USB, FLIDOMAIN_SERIAL, FLIDOMAIN_INET; + // DEVICE: FLIDEVICE_CAMERA, FLIDOMAIN_FILTERWHEEL, FLIDOMAIN_FOCUSER. + + fliframe_t = FLI_FRAME_TYPE_NORMAL или FLI_FRAME_TYPE_DARK. + + flibitdepth_t = FLI_MODE_8BIT или FLI_MODE_16BIT. + + flishutter_t = FLI_SHUTTER_CLOSE, FLI_SHUTTER_OPEN, FLI_SHUTTER_EXTERNAL_TRIGGER, + FLI_SHUTTER_EXTERNAL_TRIGGER_LOW, and FLI_SHUTTER_EXTERNAL_TRIGGER HIGH. + + flibgflush_t = FLI_BGFLUSH_STOP and FLI_BGFLUSH_START. + + flichannel_t = FLI_TEMPERATURE_INTERNAL and FLI_TEMPERATURE_EXTERNAL. + + flidebug_t = FLIDEBUG_NONE, FLIDEBUG_INFO, FLIDEBUG_WARN, and FLIDEBUG_FAIL. + +// функции + + LIBFLIAPI FLICancelExposure(flidev_t dev); // отмена экспозиции + // return: 0 - успех, !0 - неудача + + LIBFLIAPI FLIClose(flidev_t dev); // закрыть устройство + + LIBFLIAPI FLIGetArrayArea(flidev_t dev, + long* ul_x, long* ul_y, long* lr_x, long* lr_y); // получить размер фрейма + // ul_x, ul_y - координаты верхнего левого угла + // lr_x, lr_y - к-ты правого нижнего угла + + LIBFLIAPI FLIFlushRow(flidev_t dev, long rows, long repeat); // сброс рядов + // rows - кол-во рядов для сброса, repeat - сколько раз подряд сбросить + + LIBFLIAPI FLIGetFWRevision(flidev_t dev, long* fwrev); // версия прошивки + LIBFLIAPI FLIGetHWRevision(flidev_t dev, long* hwrev); // версия железа + // fwrev - версия прошивки, hwrev - версия железа + + LIBFLIAPI FLIGetLibVersion(char* ver, size_t len); // версия библиотеки + // ver - буфер для версии, len - его длина + + LIBFLIAPI FLIGetModel(flidev_t dev, char* model, size_t len); // имя модели + // model - буфер, len - его длина + + LIBFLIAPI FLIGetPixelSize(flidev_t dev, + double* pixel x, double* pixel y); // размер пикселя в мкм + + LIBFLIAPI FLIGetVisibleArea(flidev_t dev, + long* ul_x, long* ul_y, long* lr_x, long* lr_y); // р-р видимой области + // к-ты аналогично FLIGetArrayArea + + LIBFLIAPI FLIOpen(flidev_t* dev, char* name, flidomain_t domain); // открыть + // name - имя ищ FLIList() + + LIBFLIAPI FLISetDebugLevel(char* host, flidebug_t level); // уровень отладки + // host игнорируется + + LIBFLIAPI FLISetExposureTime(flidev_t dev, long exptime); // время экспозиции + // exptime - в миллисекундах + + LIBFLIAPI FLISetHBin(flidev_t dev, long hbin); // гориз. биннинг + LIBFLIAPI FLISetVBin(flidev_t dev, long vbin); // верт. биннинг + // hbin = 1..16, vbin = 1..16 + + LIBFLIAPI FLISetFrameType(flidev_t dev, fliframe_t frametype); // темновой или обычный + + LIBFLIAPI FLISetImageArea(flidev_t dev, + long ul_x, long ul_y, long lr_x, long lr_y); // установить область к-т + // lr_x = ul_x+(lrx-ul_x)/hbin; + // lr_y = ul_y+(lry-ul_y)/vbin; + // lrx, lry - абс. координаты в желаемой области + + LIBFLIAPI FLIGetExposureStatus(flidev_t dev, long* timeleft); + // время до окончания экспозиции + + LIBFLIAPI FLISetTemperature(flidev_t dev, double temperature); // задать Т + // temperature - в градусах Цельсия, от -55 до +45 + + LIBFLIAPI FLIGetTemperature(flidev_t dev, double* temperature); // узнать Т + + LIBFLIAPI FLIGrabRow(flidev_t dev, void* buff, size_t width); // считать ряд + // buff - буфер, width - макс. ширина ряда (размер буфера) + // считывает очередной ряд с камеры + + LIBFLIAPI FLIExposeFrame(flidev_t dev); // начать накопление + + LIBFLIAPI FLISetBitDepth(flidev_t dev, flibitdepth_t bitdepth); // задать разрядность + + LIBFLIAPI FLISetNFlushes(flidev_t dev, long nflushes); // задать кол-во сбросов + // перед экспозицией + + LIBFLIAPI FLIReadIOPort(flidev_t dev, long* ioportset); // считать порт io + // ioportset - считанные данные + + LIBFLIAPI FLIWriteIOPort(flidev_t dev, long ioportset); // записать в io + + LIBFLIAPI FLIConfigureIOPort(flidev_t dev, long ioportset); // настройка + // функционал каждого контакта порта io зависит от значения ioportset + // 1 - выход, 0 - вход + + LIBFLIAPI FLILockDevice(flidev_t dev); // блокировка устройства + // для обеспечения монопольного доступа + LIBFLIAPI FLIUnlockDevice(flidev_t dev); + + LIBFLIAPI FLIControlShutter(flidev_t dev, flishutter_t shutter); // затвор + // FLI_SHUTTER_EXTERNAL_TRIGGER_LOW и FLI_SHUTTER_EXTERNAL_TRIGGER + // запускают экспозицию при наличии лог. нуля на io0 + // FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH - запуск эксп. на лог1 на io0 + + LIBFLIAPI FLIControlBackgroundFlush(flidev_t dev, flibgflush_t bgflush); + // фоновый сброс + + LIBFLIAPI FLIList(flidomain_t domain, char*** names); + // список устройств из домена domain + LIBFLIAPI FLIFreeList(char** names); // очистить список names + + LIBFLIAPI FLISetFilterPos(flidev_t dev, long filter); + // установить фильтр в позицию filter + + LIBFLIAPI FLIGetFilterPos(flidev_t dev, long* filter); + // текущее положение фильтра + + LIBFLIAPI FLIGetStepsRemaining(flidev_t dev, long* steps); + // количество шагов, оставшихся до назначенной позиции + + LIBFLIAPI FLIGetFilterCount(flidev_t dev, long* filter); + // узнать кол-во фильтров + + LIBFLIAPI FLIStepMotorAsync(flidev_t dev, long steps); + LIBFLIAPI FLIStepMotor(flidev_t dev, long steps); + // передвинуть турель на заданное кол-во шагов + + LIBFLIAPI FLIGetStepperPosition(flidev_t dev, long* position); + // текущее положение ШД + +// функции для работы с фокусирующим устройством + LIBFLIAPI FLIHomeFocuser(flidev_t dev); + LIBFLIAPI FLIGetFocuserExtent(flidev_t dev, long* extent); + LIBFLIAPI FLIReadTemperature(flidev_t dev, flichannel_t channel, + double* temperature); + + LIBFLIAPI FLICreateList(flidomain_t domain); // создать список + LIBFLIAPI FLIDeleteList(void); // удалить список + LIBFLIAPI FLIListFirst(flidomain_t* domain, char* filename, + size_t fnlen, char* name, size_t namelen); // получить первое устройство из списка + // domain - домен устр-ва; + // filename - имя файла устр-ва; + // fnlen - длина буфера имени файла; + // name - название устр-ва; + // namelen - длина буфера названия + + LIBFLIAPI FLIListNext(flidomain_t* domain, char* filename, + size_t fnlen, char* name, size_t namelen); // получить следующее устр-во + + + + + diff --git a/bta_print.c b/bta_print.c new file mode 100644 index 0000000..8e2dc89 --- /dev/null +++ b/bta_print.c @@ -0,0 +1,138 @@ +/* Print some BTA NewACS data (or write to file) + * Usage: + * bta_print [time_step] [file_name] + * Where: + * time_step - writing period in sec., >=1.0 + * <1.0 - once and exit (default) + * file_name - name of file to write to, + * "-" - stdout (default) + */ +#include "bta_print.h" +#include "bta_shdata.h" + + +static char buf[1024]; +char *time_asc(double t){ + int h, m; + double s; + h = (int)(t/3600.); + m = (int)((t - (double)h*3600.)/60.); + s = t - (double)h*3600. - (double)m*60.; + h %= 24; + if(s>59) s=59; + sprintf(buf, "%dh:%02dm:%04.1fs", h,m,s); + return buf; +} + +char *angle_asc(double a){ + char s; + int d, min; + double sec; + if (a >= 0.) + s = '+'; + else{ + s = '-'; a = -a; + } + d = (int)(a/3600.); + min = (int)((a - (double)d*3600.)/60.); + sec = a - (double)d*3600. - (double)min*60.; + d %= 360; + if(sec>59.9) sec=59.9; + sprintf(buf, "%c%d:%02d':%04.1f''", s,d,min,sec); + return buf; +} + +#define CMNTSZ 79 +#define CMNT(...) snprintf(comment, CMNTSZ, __VA_ARGS__) +#define FTKEY(...) WRITEKEY(fp, __VA_ARGS__, comment) + +void write_bta_data(fitsfile *fp){ + char comment[CMNTSZ + 1]; + char *val; + double dtmp; + int i; + get_shm_block(&sdat, ClientSide); + if(!check_shm_block(&sdat)) return; + // TELESCOP / Telescope name + CMNT("Telescope name"); + FTKEY(TSTRING, "TELESCOP", "BTA 6m telescope"); + dtmp = S_time-EE_time; + // ST / sidereal time (hh:mm:ss.ms) + CMNT("Sidereal time: %s", time_asc(dtmp)); + FTKEY(TDOUBLE, "ST", &dtmp); + // UT / universal time (hh:mm:ss.ms) + CMNT("Universal time: %s", time_asc(M_time)); + FTKEY(TDOUBLE, "UT", &M_time); + CMNT("Julian date"); + FTKEY(TDOUBLE, "JD", &JDate); + + switch(Tel_Focus){ + default: + case Prime : + val = "Prime"; + // FOCUS / Focus of telescope (mm) + CMNT("Focus of telescope (mm)"); + FTKEY(TDOUBLE, "VAL_F", &val_F); + break; + case Nasmyth1 : val = "Nasmyth1"; break; + case Nasmyth2 : val = "Nasmyth2"; break; + } + CMNT("Observation focus"); + FTKEY(TSTRING, "FOCUS", val); + // EPOCH / Epoch of RA & DEC + time_t epoch = time(NULL); + strftime(comment, CMNTSZ, "%Y", gmtime(&epoch)); + i = atoi(comment); + CMNT("Epoch of RA & DEC"); + FTKEY(TINT, "EPOCH", &i); + CMNT("Current object R.A.: %s", time_asc(CurAlpha)); + // RA / Right ascention (HH MM SS) + FTKEY(TDOUBLE, "RA", &CurAlpha); + // DEC / Declination (DD MM SS) + CMNT("Current object Decl.: %s", angle_asc(CurDelta)); + FTKEY(TDOUBLE, "DEC", &CurDelta); + CMNT("Source R.A.: %s", time_asc(SrcAlpha)); + FTKEY(TDOUBLE, "S_RA", &SrcAlpha); + CMNT("Source Decl.: %s", angle_asc(SrcDelta)); + FTKEY(TDOUBLE, "S_DEC", &SrcDelta); + CMNT("Telescope R.A: %s", time_asc(val_Alp)); + FTKEY(TDOUBLE, "T_RA", &val_Alp); + CMNT("Telescope Decl.: %s", angle_asc(val_Del)); + FTKEY(TDOUBLE, "T_DEC", &val_Del); + // A / Azimuth + CMNT("Current object Azimuth: %s", angle_asc(tag_A)); + FTKEY(TDOUBLE, "A", &tag_A); + // Z / Zenith distance + CMNT("Current object Zenith: %s", angle_asc(tag_Z)); + FTKEY(TDOUBLE, "Z", &tag_Z); + // ROTANGLE / Field rotation angle + CMNT("Field rotation angle: %s", angle_asc(tag_P)); + FTKEY(TDOUBLE, "ROTANGLE", &tag_P); + + CMNT("Telescope A: %s", angle_asc(val_A)); + FTKEY(TDOUBLE, "VAL_A", &val_A); + CMNT("Telescope Z: %s", angle_asc(val_Z)); + FTKEY(TDOUBLE, "VAL_Z", &val_Z); + CMNT("Current P: %s", angle_asc(val_P)); + FTKEY(TDOUBLE, "VAL_P", &val_P); + + CMNT("Dome A: %s", angle_asc(val_D)); + FTKEY(TDOUBLE, "VAL_D", &val_D); + // OUTTEMP / Out temperature (C) + CMNT("Outern temperature, degC"); + FTKEY(TDOUBLE, "OUTTEMP", &val_T1); + // DOMETEMP / Dome temperature (C) + CMNT("In-dome temperature, degC"); + FTKEY(TDOUBLE, "DOMETEMP", &val_T2); + // MIRRTEMP / Mirror temperature (C) + CMNT("Mirror temperature, degC"); + // PRESSURE / Pressure (mmHg) + FTKEY(TDOUBLE, "MIRRTEMP", &val_T3); + CMNT("Pressure, mmHg"); + FTKEY(TDOUBLE, "PRESSURE", &val_B); + // WIND / Wind speed (m/s) + CMNT("Wind speed, m/s"); + FTKEY(TDOUBLE, "WIND", &val_Wnd); + CMNT("Humidity, %%"); + FTKEY(TDOUBLE, "HUM", &val_Hmd); +} diff --git a/bta_print.h b/bta_print.h new file mode 100644 index 0000000..6ddb506 --- /dev/null +++ b/bta_print.h @@ -0,0 +1,8 @@ +#ifndef __BTA_PRINT_H__ +#define __BTA_PRINT_H__ + +#include "takepic.h" + +void write_bta_data(fitsfile *fp); + +#endif // __BTA_PRINT_H__ diff --git a/bta_shdata.h b/bta_shdata.h new file mode 100644 index 0000000..2aec738 --- /dev/null +++ b/bta_shdata.h @@ -0,0 +1,1159 @@ +#pragma once +#ifndef __BTA_SHDATA_H__ +#define __BTA_SHDATA_H__ + +#define _XOPEN_SOURCE 501 +/* Основные определения и функции поддержки межпрограммного интерфейса */ +/* Возможные внешние определения: */ +/* BTA_MODULE - при исп-и в доп. C-модулях (не в главн.программе) */ +/* SHM_OLD_SIZE - для генерации предыдущей весии структуры БТА-данных */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __GNUC_PREREQ(4,2) +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-braces" +#pragma GCC diagnostic ignored "-Wsequence-point" +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +#pragma GCC diagnostic ignored "-Wimplicit-function-declaration" +#endif + +#define uint __uint32_t + +struct SHM_Block { /* описание блока разделяемой памяти */ + union { + char name[5]; /* ключ идентефикации сегмента памяти */ + key_t code; + } key; + int size; /* размер используемой части в байтах */ + int maxsize; /* размер при создании ("с запасом" для будущих версий) */ + int mode; /* режим доступа (rwxrwxrwx) */ + int atflag; /* режим подсоединения (SHM_RDONLY или 0) */ + void (*init)(); /* процедура инициализации */ + int (*check)(); /* процедура проверки */ + void (*close)(); /* процедура отсоединения */ + int side; /* тип подсоединения: Клиент/Сервер */ + int id; /* дескриптор подсоединения */ + unsigned char *addr; /* адрес подсоединения */ +}; + +struct CMD_Queue { /* описание очереди (канала) команд */ + union { + char name[5]; /* ключ идентефикации очереди */ + key_t code; + } key; + int mode; /* режим доступа (rwxrwxrwx) */ + int side; /* тип подсоединения: Клиент/Сервер (Sender/Receiver)*/ + int id; /* дескриптор подсоединения */ + uint acckey; /* ключ доступа (для передачи Клиент->Сервер) */ +}; + +#ifndef BTA_MODULE +/* канал команд главного операторского интерфейса (Level5)*/ +struct CMD_Queue mcmd = {{'M','c','m','d',0},0200,0,-1,0}; +/* канал передачи операторских (привелегированных) команд (Level4)*/ +struct CMD_Queue ocmd = {{'O','c','m','d',0},0200,0,-1,0}; +/* канал передачи пользовательских (непривелегированных) команд (Level2/3)*/ +struct CMD_Queue ucmd = {{'U','c','m','d',0},0200,0,-1,0}; +#else +extern struct CMD_Queue mcmd; +extern struct CMD_Queue ocmd; +extern struct CMD_Queue ucmd; +#endif + +static void send_cmd_noarg(int); +static void send_cmd_str(int, char *); +static void send_cmd_i1(int, int); +static void send_cmd_i2(int, int, int); +static void send_cmd_i3(int, int, int, int); +static void send_cmd_i4(int, int, int, int, int); +static void send_cmd_d1(int, double); +static void send_cmd_d2(int, double, double); +static void send_cmd_i1d1(int, int, double); +static void send_cmd_i2d1(int, int, int, double); +static void send_cmd_i3d1(int, int, int, int, double); + +/* список команд */ +/* имя код аргументы тип */ +#define StopTel 1 /* останов телескопа */ +#define StopTeleskope() send_cmd_noarg( 1 ) /* опер. */ +#define StartHS 2 /* старт привода наведения */ +#define StartHightSpeed() send_cmd_noarg( 2 ) /* опер/тст*/ +#define StartLS 3 /* старт привода ведения */ +#define StartLowSpeed() send_cmd_noarg( 3 ) /* опер/тст*/ +#define SetTmr 4 /* уст. Ch7_15 или SysTimer */ +#define SetTimerMode(T) send_cmd_i1 ( 4, (int)(T)) /* М.опер. */ +#define SetModMod 5 /* уст. режим моделирования */ +#define SetModelMode(M) send_cmd_i1 ( 5, (int)(M)) /* М.опер. */ +#define SetCodA 6 /* код скорости по A */ +#define SetPKN_A(iA,sA) send_cmd_i2 ( 6, (int)(iA),(int)(sA)) /* опер/тст*/ +#define SetCodZ 7 /* код скорости по Z */ +#define SetPKN_Z(iZ) send_cmd_i1 ( 7, (int)(iZ)) /* опер/тст*/ +#define SetCodP 8 /* код скорости по P */ +#define SetPKN_P(iP) send_cmd_i1 ( 8, (int)(iP)) /* опер/тст*/ +#define SetVA 9 /* уст. скорость по A */ +#define SetSpeedA(vA) send_cmd_d1 ( 9, (double)(vA)) /* опер/тст*/ +#define SetVZ 10 /* уст. скорость по Z */ +#define SetSpeedZ(vZ) send_cmd_d1 (10, (double)(vZ)) /* опер/тст*/ +#define SetVP 11 /* уст. скорость по P */ +#define SetSpeedP(vP) send_cmd_d1 (11, (double)(vP)) /* опер/тст*/ +#define SetAD 12 /* зап.новые координаты R.A.и Decl */ +#define SetRADec(Alp,Del) send_cmd_d2 (12, (double)(Alp),(double)(Del))/* польз.*/ +#define SetAZ 13 /* зап.координаты азимут и зен.расст.*/ +#define SetAzimZ(A,Z) send_cmd_d2 (13, (double)(A),(double)(Z))/* польз.*/ +#define GoToAD 14 /* старт наведения на объект (по R.A.и Decl)*/ +#define GoToObject() send_cmd_noarg(14 ) /* опер. */ +#define MoveToAD 15 /* переезд на объект (по R.A.и Decl)*/ +#define MoveToObject() send_cmd_noarg(15 ) /* польз.*/ +#define GoToAZ 16 /* наведение по положению (по A Z)*/ +#define GoToAzimZ() send_cmd_noarg(16 ) /* опер. */ +#define WriteAZ 17 /* установка A и Z для FullModel*/ +#define WriteModelAZ() send_cmd_noarg(17 ) /* опер. */ +#define SetModP 18 /* уст. режим использования P2 */ +#define SetPMode(pmod) send_cmd_i1 (18, (int)(pmod)) /* польз.*/ +#define P2Move 19 /* вкл./выкл. (+-1,0) движение P2 */ +#define MoveP2(dir) send_cmd_i1 (19, (int)(dir)) /* польз.*/ +#define FocMove 20 /* вкл./выкл. (+-2,+-1,0) движение фокуса */ +#define MoveFocus(speed,time) send_cmd_i1d1(20,(int)(speed),(double)(time)) /* польз.*/ +#define UsePCorr 21 /* режим учета поправок положения (СКН) */ +#define SwitchPosCorr(pc_flag) send_cmd_i1 (21, (int)(pc_flag)) /* опер. */ +#define SetTrkFlags 22 /* уст. флагов режима слежения */ +#define SetTrkOkMode(trk_flags) send_cmd_i1 (22, (int)(trk_flags)) /* опер.*/ +#define SetTFoc 23 /* уст.фокуса: 0-ПФ, 1-Н1, 2-Н2 */ +#define SetTelFocus(N) send_cmd_i1 ( 23, (int)(N)) /* опер. */ +#define SetVAD 24 /* уст.ск.собсв.дв-я объекта по R.A.и Decl */ +#define SetVelAD(VAlp,VDel) send_cmd_d2 (24, (double)(VAlp),(double)(VDel))/* опер.*/ +#define SetRevA 25 /* уст. режим "обхода" азимута */ +#define SetAzRevers(amod) send_cmd_i1 (25, (int)(amod)) /* польз.*/ +#define SetVP2 26 /* уст.скор..дв-я P2 (для ДБУ) */ +#define SetVelP2(vP2) send_cmd_d1 (26, (double)(vP2)) /* польз.*/ +#define SetTarg 27 /* уст. цели наведения */ +#define SetSysTarg(Targ) send_cmd_i1 (27, (int)(Targ)) /* опер.*/ +#define SendMsg 28 /* размещение сообщения (всем клиентам и в протокол) */ +#define SendMessage(Mesg) send_cmd_str (28, (char *)(Mesg)) /* польз.*/ +#define CorrAD 29 /* коррекция координат R.A.и Decl */ +#define DoADcorr(dAlp,dDel) send_cmd_d2 (29, (double)(dAlp),(double)(dDel))/* польз.*/ +#define CorrAZ 30 /* коррекция координат A и Z*/ +#define DoAZcorr(dA,dZ) send_cmd_d2 (30, (double)(dA),(double)(dZ))/* польз.*/ +#define SetVCAZ 31 /* уст.скор.коррекции по A и Z*/ +#define SetVCorr(vA,vZ) send_cmd_d2 (31, (double)(vA),(double)(vZ))/* польз.*/ +#define P2MoveTo 32 /* переезд P2 по времени */ +#define MoveP2To(vP2,time) send_cmd_d2 (32, (double)(vP2),(double)(time))/* польз.*/ +#define GoToTD 33 /* старт наведения на стационар (по t и Decl)*/ +#define GoToSat() send_cmd_noarg (33 ) /* опер..*/ +#define MoveToTD 34 /* переезд на стационар (по t и Decl)*/ +#define MoveToSat() send_cmd_noarg (34 ) /* польз.*/ +#define NullCom 35 /* пустая команда (для синхронизаций?) */ +#define SyncCom() send_cmd_noarg (35 ) /* опер. */ +#define StartTel 36 /* кнопка "Пуск" телескопа */ +#define StartTeleskope() send_cmd_noarg(36 ) /* опер. */ +#define SetTMod 37 /* уст. режимы работы телескопа */ +#define SetTelMode(M) send_cmd_i1 ( 37, (int)(M)) /* М.опер. */ +#define TelOn 38 /* кнопка Вкл. Масло, ЭМУ и т.д.*/ +#define TeleskopeOn() send_cmd_noarg(38 ) /* М.опер. */ +#define SetModD 39 /* уст. режим использования купола */ +#define SetDomeMode(dmod) send_cmd_i1 (39, (int)(dmod)) /* М.опер.*/ +#define DomeMove 40 /* вкл./выкл. (+-1+-2,+-3,0) движение купола */ +#define MoveDome(speed,time) send_cmd_i1d1(40,(int)(speed),(double)(time)) /* опер.*/ +#define SetPass 41 /* уст. пароль уровня доступа */ +#define SetPasswd(LPass) send_cmd_str (41, (char *)(LPass)) /* М.опер.*/ +#define SetLevC 42 /* уст. код уровня доступа */ +#define SetLevCode(Nlev,Cod) send_cmd_i2(42, (int)(Nlev),(int)(Cod)) /* М.опер.*/ +#define SetLevK 43 /* уст. ключ уровня доступа */ +#define SetLevKey(Nlev,Key) send_cmd_i2(43, (int)(Nlev),(int)(Key)) /* М.опер.*/ +#define SetNet 44 /* уст. маску и адрес подсети */ +#define SetNetAcc(Mask,Addr) send_cmd_i2(44, (int)(Mask),(int)(Addr)) /* М.опер.*/ +#define SetMet 45 /* ввод метео данных */ +#define SetMeteo(m_id,m_val) send_cmd_i1d1(45,(int)(m_id),(double)(m_val)) /* опер.*/ +#define TurnMetOff 46 /* отмена исп. метео данных */ +#define TurnMeteoOff(m_id) send_cmd_i1 (46, (int)(m_id)) /* опер.*/ +#define SetDUT1 47 /* уст.попр.времени(IERS DUT1=UT1-UTC) */ +#define SetDtime(dT) send_cmd_d1 (47, (double)(dT)) /* М.опер.*/ +#define SetPM 48 /* уст.полож.полюса(IERS polar motion)*/ +#define SetPolMot(Xp,Yp) send_cmd_d2 (48, (double)(Xp),(double)(Yp)) /* М.опер.*/ +#define GetSEW 49 /* прочитать SEW параметр */ +#define GetSEWparam(Ndrv,Indx,Cnt) send_cmd_i3(49,(int)(Ndrv),(int)(Indx),(int)(Cnt)) /* M.опер.*/ +#define PutSEW 50 /* записать SEW параметр */ +#define PutSEWparam(Ndrv,Indx,Key,Val) send_cmd_i4(50,(int)(Ndrv),(int)(Indx),(int)(Key),(int)(Val)) /* M.опер.*/ +#define SetLocks 51 /* установка блокировок управления узлами */ +#define SetLockFlags(f) send_cmd_i1 (SetLocks, (int)(f)) /* M.опер.*/ +#define ClearLocks 52 /* отмена блокировок управления узлами */ +#define ClearLockFlags(f) send_cmd_i1 (ClearLocks, (int)(f)) /* M.опер.*/ +#define SetRKbits 53 /* Установка доп.битов PEP-RK */ +#define AddRKbits(f) send_cmd_i1 (SetRKbits, (int)(f)) /* M.опер.*/ +#define ClrRKbits 54 /* Очистка доп.битов PEP-RK */ +#define ClearRKbits(f) send_cmd_i1 (ClrRKbits, (int)(f)) /* M.опер.*/ +#define SetSEWnd 55 /* уст.номер SEW-движка купола (для индикации)*/ +#define SetDomeDrive(ND) send_cmd_i1 (SetSEWnd, (int)(ND)) /* М.опер.*/ +#define SEWsDome 56 /* Вкл./Выкл. SEW-движков купола */ +#define DomeSEW(OnOff) send_cmd_i1 (SEWsDome, (int)(OnOff)) /* М.опер.*/ + + +/* структура данных алгоритма управления (распределение "глобальной области") */ +#define BTA_Data_Ver 2 +#pragma pack(4) +//struct __attribute__((packed)) BTA_Data { +struct BTA_Data { + int magic; /* код опознания структуры */ + int version; /* номер версии структуры = BTA_Data_Ver*/ + int size; /* размер структуры = sizeof(struct BTA_Data)*/ + int pid; +#define ServPID (sdt->pid) /*номер процесса гл.упр.программы */ + + /* режимы работы */ + int model; +#define UseModel (sdt->model) /* вариант использования моделирования */ +#define NoModel 0 /* отключено */ +#define CheckModel 1 /* привода контролируются по модели */ +#define DriveModel 2 /* моделирование приводов и "слепое" управление без реальных датчиков */ +#define FullModel 3 /* полное моделирование без телескопа */ + int timer; +#define ClockType (sdt->timer) /* какие часы используются */ +#define Ch7_15 0 /* Внутр.часы упр.программы с синхронизацией по Ч7-15 */ +#define SysTimer 1 /* Таймер системы (неизвестно синхронизированный или нет) */ +#define ExtSynchro 2 /* Работает синхронизация таймера системы внешней программой (bta_time или xntpd)*/ + int system; +#define Sys_Mode (sdt->system) /* режим работы системы */ +#define SysStop 0 /* Останов */ +#define SysWait 1 /* Ожидание старта (наведения) */ +#define SysPointAZ 2 /* Наведение по положению (по A Z)*/ +#define SysPointAD 3 /* Наведение на объект (по R.A.и Decl)*/ +#define SysTrkStop 4 /* Ведение: ожидание старта */ +#define SysTrkStart 5 /* Ведение: разгон до номин.скорости (объекта)*/ +#define SysTrkMove 6 /* Ведение: переезд на объект */ +#define SysTrkSeek 7 /* Ведение: слежение за объектом */ +#define SysTrkOk 8 /* Ведение: рассогласования в допуске */ +#define SysTrkCorr 9 /* Ведение: коррекция положения */ +#define SysTest 10 /* Тестирование */ + int sys_target; +#define Sys_Target (sdt->sys_target) /* цель наведения */ +#define TagPosition 0 /* Положение A/Z */ +#define TagObject 1 /* Объект Alpha/Delta */ +#define TagNest 2 /* Положение "Гнездо" */ +#define TagZenith 3 /* Положение "Зенит" */ +#define TagHorizon 4 /* Положение "Горизонт" */ +#define TagStatObj 5 /* "Стационар" t/Delta */ + + int tel_focus; +#define Tel_Focus (sdt->tel_focus) /* тип фокуса телескопа: 0-ПФ, 1-Н1, 2-Н2 */ +#define Prime 0 +#define Nasmyth1 1 +#define Nasmyth2 2 + double pc_coeff[8]; +#define PosCor_Coeff (sdt->pc_coeff) /* коэф-ты СКН для тек.фокуса */ + + /* состояние телескопа */ +#define Stopping 0 /* Останов */ +#define Pointing 1 /* Наведение */ +#define Tracking 2 /* Ведение */ + int tel_state; +#define Tel_State (sdt->tel_state) /* реально отрабатываемое */ + int req_state; +#define Req_State (sdt->req_state) /* затребованное программой */ + int tel_hard_state; +#define Tel_Hardware (sdt->tel_hard_state) /* состояние УСО */ +#define Hard_Off 0 /* питание выключено */ +#define Hard_On 1 /* включено */ + + /* режимы работы телескопа */ + int tel_mode; +#define Tel_Mode (sdt->tel_mode) +#define Automatic 0 /* "Автомат" - нормальный режим*/ +#define Manual 1 /* "П/авт.упр." - пультовой режим и в нем:*/ +#define ZenHor 2 /* "Зенит-Горизонт" - работа при Z<5 и Z>80*/ +#define A_Move 4 /* ручное движение A */ +#define Z_Move 8 /* --- "" --- Z */ +#define Balance 0x10 /* балансировка трубы */ + + /* вкл./выкл. режим "обхода" азимута */ + int az_mode; +#define Az_Mode (sdt->az_mode) +#define Rev_Off 0 /* нормальное наведение на ближайшее положение по азимуту */ +#define Rev_On 1 /* наведение с перегоном на 360град. */ + + /* работа P2 */ + int p2_state; +#define P2_State (sdt->p2_state) /* реальное состояние привода P2 */ +#define P2_Off 0 /* Стоит */ +#define P2_On 1 /* Ведет */ +#define P2_Plus 2 /* быстро едет в + */ +#define P2_Minus -2 /* быстро едет в - */ + int p2_req_mode; +#define P2_Mode (sdt->p2_req_mode) /* режим использования P2 (пока: Вкл/Выкл)*/ + + /* состояние привода фокуса */ + int focus_state; +#define Foc_State (sdt->focus_state) +#define Foc_Off 0 /* Стоит */ +#define Foc_Lplus 1 /* медл. едет в + */ +#define Foc_Lminus -1 /* медл. едет в - */ +#define Foc_Hplus 2 /* быстро едет в + */ +#define Foc_Hminus -2 /* быстро едет в - */ + + /* состояние привода купола */ + int dome_state; +#define Dome_State (sdt->dome_state) +#define D_On 7 /* Автоматическое согласование с телескопом */ +#define D_Off 0 /* Стоит */ +#define D_Lplus 1 /* медл. едет в + */ +#define D_Lminus -1 /* медл. едет в - */ +#define D_Mplus 2 /* сред.скор. в + */ +#define D_Mminus -2 /* сред.скор. в - */ +#define D_Hplus 3 /* быстро едет в + */ +#define D_Hminus -3 /* быстро едет в - */ + +/* учет поправок положения (СКН) */ + int pcor_mode; +#define Pos_Corr (sdt->pcor_mode) /* коррекция положения объекта по A/Z: Вкл/Выкл*/ +#define PC_Off 0 /* Выкл. */ +#define PC_On 1 /* Вкл. */ + +/* флаги вкл/выкл. вариантов режима слежения */ + int trkok_mode; +#define TrkOk_Mode (sdt->trkok_mode) +#define UseDiffVel 1 /* определение&учет поправок реальной скорости приводов (~изодором)*/ +#define UseDiffAZ 2 /* слежение по рассогласованию (иначе уст.рассчетн.скоростей) */ +#define UseDFlt 4 /* вкл. цифрового фильтра рассогласований */ + + /* введенные значения */ + double i_alpha, i_delta; +#define InpAlpha (sdt->i_alpha) /* введенная координата R.A. (sec) */ +#define InpDelta (sdt->i_delta) /* -- " -- Decl. (") */ + double s_alpha, s_delta; +#define SrcAlpha (sdt->s_alpha) /* исходная координата R.A. (sec) */ +#define SrcDelta (sdt->s_delta) /* -- " -- Decl. (") */ + double v_alpha, v_delta; +#define VelAlpha (sdt->v_alpha) /* ск.собсв.дв-я объекта по R.A. (sec/сек) */ +#define VelDelta (sdt->v_delta) /* -- " -- Decl. ("/сек) */ + double i_azim, i_zdist; +#define InpAzim (sdt->i_azim) /* для наведения по азимуту (") */ +#define InpZdist (sdt->i_zdist) /* -- " -- зен.расст. (") */ + + /* рассчетные значения */ + double c_alpha, c_delta; +#define CurAlpha (sdt->c_alpha) /* текущая координата R.A. (sec) */ +#define CurDelta (sdt->c_delta) /* -- " -- Decl. (") */ + double tag_a, tag_z, tag_p; +#define tag_A (sdt->tag_a) /* текущий A (") объекта */ +#define tag_Z (sdt->tag_z) /* - " - Z (") - " - */ +#define tag_P (sdt->tag_p) /* - " - P (") - " - */ + double pcor_a, pcor_z, refr_z; +#define pos_cor_A (sdt->pcor_a) /* поправка положения объекта по A (") */ +#define pos_cor_Z (sdt->pcor_z) /* - " - - " - по Z (") */ +#define refract_Z (sdt->refr_z) /* поправка за рефракцию для объекта (") */ + double tcor_a, tcor_z, tref_z; +#define tel_cor_A (sdt->tcor_a) /* поправка обр.пересчета положения телескопа по A (") */ +#define tel_cor_Z (sdt->tcor_z) /* - " - - " - - " - по Z (") */ +#define tel_ref_Z (sdt->tref_z) /* поправка обр.пересчета за рефракцию (") */ + double diff_a, diff_z, diff_p; +#define Diff_A (sdt->diff_a) /* рассогл-е(осталось ехать) по A (") */ +#define Diff_Z (sdt->diff_z) /* - " - - " - Z (") */ +#define Diff_P (sdt->diff_p) /* - " - - " - P (") */ + double vbasea,vbasez,vbasep; +#define vel_objA (sdt->vbasea) /* базовая скорость объекта по A ("/сек) */ +#define vel_objZ (sdt->vbasez) /* - " - - " - Z - " - */ +#define vel_objP (sdt->vbasep) /* - " - - " - P - " - */ + double diffva,diffvz,diffvp; +#define diff_vA (sdt->diffva) /* поправка реальной скорости привода по азимуту */ +#define diff_vZ (sdt->diffvz) /* -- "" -- -- "" -- по Z */ +#define diff_vP (sdt->diffvp) /* -- "" -- -- "" -- по P */ + double speeda,speedz,speedp; +#define speedA (sdt->speeda) /* скорость по A ("/сек) для управления приводом */ +#define speedZ (sdt->speedz) /* - " - Z - " - */ +#define speedP (sdt->speedp) /* - " - P - " - */ + double m_time_precip; +#define Precip_time (sdt->m_time_precip)/* момент времени появления осадков (precipitations)*/ + unsigned char reserve[16]; +#define Reserve (sdt->reserve) /* свободное место */ + double rspeeda, rspeedz, rspeedp; +#define req_speedA (sdt->rspeeda) /* скорость ("/сек) выданная на привод A */ +#define req_speedZ (sdt->rspeedz) /* - " - Z */ +#define req_speedP (sdt->rspeedp) /* - " - P */ + double simvela, simvelz, simvelp, simvelf, simveld; +#define mod_vel_A (sdt->simvela) /* скорость по A ("/сек) модельная */ +#define mod_vel_Z (sdt->simvelz) /* - " - Z - " - */ +#define mod_vel_P (sdt->simvelp) /* - " - P - " - */ +#define mod_vel_F (sdt->simvelf) /* - " - F - " - */ +#define mod_vel_D (sdt->simvelf) /* - " - D - " - */ + + + /* результаты измерения датчиков и рассчитанные по ним значения */ + uint kost; +#define code_KOST (sdt->kost) /* сост. телескопа и ручной коррекции */ + /* 0x8000 - азимут положительный */ + /* 0x4000 - отработка вкл. */ + /* 0x2000 - режим ведения */ + /* 0x1000 - отработка P2 вкл.*/ + /* 0x01F0 - ск.корр. 0.2 0.4 1.0 2.0 5.0("/сек) */ + /* 0x000F - напр.корр. +Z -Z +A -A */ + double m_time, s_time, l_time; +#define M_time (sdt->m_time) /* текущее московское время (теперь UTC!)*/ +#define S_time (sdt->s_time) /* текущее звездное время */ +#define L_time (sdt->l_time) /* время работы программы */ + uint ppndd_a, ppndd_z, ppndd_p, ppndd_b; +#define ppndd_A (sdt->ppndd_a) /* код датчика ППНДД (грубого отсчета) A */ +#define ppndd_Z (sdt->ppndd_z) /* - "" - Z */ +#define ppndd_P (sdt->ppndd_p) /* - "" - P */ +#define ppndd_B (sdt->ppndd_b) /* код датчика ППНДД давления */ + uint dup_a, dup_z, dup_p, dup_f, dup_d; +#define dup_A (sdt->dup_a) /* код Грея датчика ДУП (точного отсчета) A */ +#define dup_Z (sdt->dup_z) /* - "" - Z */ +#define dup_P (sdt->dup_p) /* - "" - P */ +#define dup_F (sdt->dup_f) /* код Грея датчика ДУП фокуса телескопа */ +#define dup_D (sdt->dup_d) /* код Грея датчика ДУП положения купола */ + uint low_a, low_z, low_p, low_f, low_d; +#define low_A (sdt->low_a) /* 14р-в дв.кода точного отсчета A */ +#define low_Z (sdt->low_z) /* - "" - Z */ +#define low_P (sdt->low_p) /* - "" - P */ +#define low_F (sdt->low_f) /* код отсчета фокуса телескопа */ +#define low_D (sdt->low_d) /* код отсчета положения купола */ + uint code_a, code_z, code_p, code_b, code_f, code_d; +#define code_A (sdt->code_a) /* 23р-в дв.кода отсчета A */ +#define code_Z (sdt->code_z) /* - "" - Z */ +#define code_P (sdt->code_p) /* - "" - P */ +#define code_B (sdt->code_b) /* код давления */ +#define code_F (sdt->code_f) /* код отсчета фокуса телескопа */ +#define code_D (sdt->code_d) /* код отсчета положения купола */ + uint adc[8]; +#define ADC(N) (sdt->adc[(N)]) /* коды 8-ми каналов АЦП PCL818 */ +#define code_T1 ADC(0) /* код датчика наруж. температуры*/ +#define code_T2 ADC(1) /* код датчика температуры под куп.*/ +#define code_T3 ADC(2) /* код датчика температуры зеркала */ +#define code_Wnd ADC(3) /* код датчика ветра */ + double val_a, val_z, val_p, val_b, val_f, val_d; + double val_t1, val_t2, val_t3, val_wnd; +#define val_A (sdt->val_a) /* отсчет A (") */ +#define val_Z (sdt->val_z) /* - " - Z (") */ +#define val_P (sdt->val_p) /* - " - P (") */ +#define val_B (sdt->val_b) /* давлениe (мм.рт.ст.)*/ +#define val_F (sdt->val_f) /* фокус телескопа (мм) */ +#define val_D (sdt->val_d) /* положение купола (") */ +#define val_T1 (sdt->val_t1) /* наруж. температура (гр.)*/ +#define val_T2 (sdt->val_t2) /* температура под куп.(гр.)*/ +#define val_T3 (sdt->val_t3) /* температура зеркала (гр.)*/ +#define val_Wnd (sdt->val_wnd) /* ветер (м/сек)*/ + double val_alp, val_del; +#define val_Alp (sdt->val_alp) /* обратный пересчет R.A. (sec) */ +#define val_Del (sdt->val_del) /* -- " -- Decl. (") */ + + double vel_a, vel_z, vel_p, vel_f, vel_d; +#define vel_A (sdt->vel_a) /* скорость по A ("/сек) измеренная */ +#define vel_Z (sdt->vel_z) /* - " - Z - " - */ +#define vel_P (sdt->vel_p) /* - " - P - " - */ +#define vel_F (sdt->vel_f) /* - " - F - " - */ +#define vel_D (sdt->vel_d) /* - " - D - " - */ + + /* очередь последних системных сообщений */ +#define MesgNum 3 +#define MesgLen 39 + //struct __attribute__((packed)) SysMesg { + struct SysMesg { + int seq_num; + char type; +#define MesgEmpty 0 +#define MesgInfor 1 +#define MesgWarn 2 +#define MesgFault 3 +#define MesgLog 4 + char text[MesgLen]; + } sys_msg_buf[MesgNum]; +#define Sys_Mesg(N) (sdt->sys_msg_buf[N]) + + /* управление доступом */ + /* коды установки уровней доступа для клиентов */ + uint code_lev1,code_lev2,code_lev3,code_lev4,code_lev5; +#define code_Lev1 (sdt->code_lev1) /* "удаленный наблюдатель" - только информация */ +#define code_Lev2 (sdt->code_lev2) /* "местный наблюдатель" - + ввод координат */ +#define code_Lev3 (sdt->code_lev3) /* "главный наблюдатель" - + A/Z-корр-я, упр.P2/F */ +#define code_Lev4 (sdt->code_lev4) /* "оператор" - + пуск/стоп телеск., тестирование */ +#define code_Lev5 (sdt->code_lev5) /* "главный оператор" - все операции */ + /* ограничение сетевого доступа */ + uint netmask, netaddr, acsmask, acsaddr; +#define NetMask (sdt->netmask) /* маска подсети (обычно: 255.255.255.0) */ +#define NetWork (sdt->netaddr) /* адрес подсети (например: 192.168.3.0) */ +#define ACSMask (sdt->acsmask) /* маска АСУ-сети (например: 255.255.255.0) */ +#define ACSNet (sdt->acsaddr) /* адрес АСУ-сети (например: 192.168.13.0) */ + + /* ввод метео-данных */ + int meteo_stat; +#define MeteoMode (sdt->meteo_stat) /* флаги датчиков и ввода данных*/ +#define INPUT_B 1 /* давление *//* флаги ручного ввода метео данных */ +#define INPUT_T1 2 /* T-наружная */ +#define INPUT_T2 4 /* T-подкупольная */ +#define INPUT_T3 8 /* T-зеркала */ +#define INPUT_WND 0x10 /* ветер */ +#define INPUT_HMD 0x20 /* влажность */ +#define SENSOR_B (INPUT_B <<8) /* флаги внешних метео-датчиков (e.g.по CAN-шине)*/ +#define SENSOR_T1 (INPUT_T1 <<8) +#define SENSOR_T2 (INPUT_T2 <<8) +#define SENSOR_T3 (INPUT_T3 <<8) +#define SENSOR_WND (INPUT_WND<<8) +#define SENSOR_HMD (INPUT_HMD<<8) +#define ADC_B (INPUT_B <<16) /* флаги считывания с АЦП упр.компутера */ +#define ADC_T1 (INPUT_T1 <<16) +#define ADC_T2 (INPUT_T2 <<16) +#define ADC_T3 (INPUT_T3 <<16) +#define ADC_WND (INPUT_WND<<16) +#define ADC_HMD (INPUT_HMD<<16) +#define NET_B (INPUT_B <<24) /* флаги получения данных с метеостанции по сети */ +#define NET_T1 (INPUT_T1 <<24) +#define NET_WND (INPUT_WND<<24) +#define NET_HMD (INPUT_HMD<<24) + double inp_b, inp_t1, inp_t2, inp_t3, inp_wnd; +#define inp_B (sdt->inp_b) /* давлениe (мм.рт.ст.)*/ +#define inp_T1 (sdt->inp_t1) /* наруж. температура (гр.)*/ +#define inp_T2 (sdt->inp_t2) /* температура под куп.(гр.)*/ +#define inp_T3 (sdt->inp_t3) /* температура зеркала (гр.)*/ +#define inp_Wnd (sdt->inp_wnd) /* ветер (м/сек)*/ + + double temper, press; +#define Temper (sdt->temper) /* темрература используемая для рефракции */ +#define Pressure (sdt->press) /* давление используемое для рефракции */ + double m_time10, m_time15; +#define Wnd10_time (sdt->m_time10) /* момент времени порыва >=10м/сек*/ +#define Wnd15_time (sdt->m_time15) /* - " - - " - - " - >=15м/сек*/ + + /* IERS DUT1 (источник: ftp://maia.usno.navy.mil/ser7/ser7.dat) */ + double dut1; +#define DUT1 (sdt->dut1) /* поправка ср.солнечного времени: DUT1 = UT1-UTC */ + + double a_time, z_time, p_time; +#define A_time (sdt->a_time) /* момент считывания датчика A */ +#define Z_time (sdt->z_time) /* - " - - " - - " - Z */ +#define P_time (sdt->p_time) /* - " - - " - - " - P */ + + double speedain, speedzin, speedpin; +#define speedAin (sdt->speedain) /* постоянная скорость уст-я по A */ +#define speedZin (sdt->speedzin) /* постоянная скорость уст-я по Z */ +#define speedPin (sdt->speedpin) /* постоянная скорость уст-я по P2*/ + + double acc_a, acc_z, acc_p, acc_f, acc_d; +#define acc_A (sdt->acc_a) /* ускорение по A ("/сек^2) */ +#define acc_Z (sdt->acc_z) /* - " - Z - " - */ +#define acc_P (sdt->acc_p) /* - " - P - " - */ +#define acc_F (sdt->acc_f) /* - " - F - " - */ +#define acc_D (sdt->acc_d) /* - " - D - " - */ + + uint code_sew; +#define code_SEW (sdt->code_sew) /* код спец.доступа к SEW-контроллерам */ + +/* параметры SEW-контроллеров */ +//struct __attribute__((packed)) SEWdata { +struct SEWdata { + int status; + double set_speed; + double mes_speed; + double current; + int index; + union { + unsigned char b[4]; + __uint32_t l; + } value; +} sewdrv[3]; +#define statusSEW(Drv) (sdt->sewdrv[(Drv)-1].status) /*состояние контроллера*/ +#define statusSEW1 (sdt->sewdrv[0].status) +#define statusSEW2 (sdt->sewdrv[1].status) +#define statusSEW3 (sdt->sewdrv[2].status) +#define speedSEW(Drv) (sdt->sewdrv[(Drv)-1].set_speed) /*установленная скорость*/ +#define speedSEW1 (sdt->sewdrv[0].set_speed) /* об/мин (rpm)*/ +#define speedSEW2 (sdt->sewdrv[1].set_speed) +#define speedSEW3 (sdt->sewdrv[2].set_speed) +#define vel_SEW(Drv) (sdt->sewdrv[(Drv)-1].mes_speed) /*измеренная скорость */ +#define vel_SEW1 (sdt->sewdrv[0].mes_speed) /* об/мин (rpm)*/ +#define vel_SEW2 (sdt->sewdrv[1].mes_speed) +#define vel_SEW3 (sdt->sewdrv[2].mes_speed) +#define currentSEW(Drv) (sdt->sewdrv[(Drv)-1].current) /*ток (А)*/ +#define currentSEW1 (sdt->sewdrv[0].current) +#define currentSEW2 (sdt->sewdrv[1].current) +#define currentSEW3 (sdt->sewdrv[2].current) +#define indexSEW(Drv) (sdt->sewdrv[(Drv)-1].index) /*номер параметра*/ +#define indexSEW1 (sdt->sewdrv[0].index) +#define indexSEW2 (sdt->sewdrv[1].index) +#define indexSEW3 (sdt->sewdrv[2].index) +#define valueSEW(Drv) (sdt->sewdrv[(Drv)-1].value.l) /*код значения параметра*/ +#define valueSEW1 (sdt->sewdrv[0].value.l) +#define valueSEW2 (sdt->sewdrv[1].value.l) +#define valueSEW3 (sdt->sewdrv[2].value.l) +#define bvalSEW(Drv,Nb) (sdt->sewdrv[(Drv)-1].value.b[Nb]) /*байт кода значения параметра*/ + +/* информация от PEP-контроллеров */ + uint pep_code_a, pep_code_z, pep_code_p; +#define PEP_code_A (sdt->pep_code_a) /* 23р-в дв.кода отсчета A */ +#define PEP_code_Z (sdt->pep_code_z) /* - "" - Z */ +#define PEP_code_P (sdt->pep_code_p) /* - "" - P */ + uint pep_sw_a, pep_sw_z, pep_sw_p; +#define switch_A (sdt->pep_sw_a) /* код концевиков азимута */ +#define Sw_minus_A 1 /* азимут отрицательный (см. code_KOST&0x8000)*/ +#define Sw_plus240_A 2 /* концевик "+240град" */ +#define Sw_minus240_A 4 /* концевик "-240град" */ +#define Sw_minus45_A 8 /* положение "в горизонт" (~-46град)*/ +#define switch_Z (sdt->pep_sw_z) /* код концевиков Z */ +#define Sw_0_Z 0x01 /* концевик "0град" */ +#define Sw_5_Z 0x02 /* концевик "5град" */ +#define Sw_20_Z 0x04 /* концевик "20град" */ +#define Sw_60_Z 0x08 /* концевик "60град" */ +#define Sw_80_Z 0x10 /* концевик "80град" */ +#define Sw_90_Z 0x20 /* концевик "90град" */ +#define switch_P (sdt->pep_sw_p) /* - "" - СПФ */ +#define Sw_No_P 0x00 /* "Нет концевиков" */ +#define Sw_22_P 0x01 /* концевик "22град" */ +#define Sw_89_P 0x02 /* концевик "89град" */ +#define Sw_Sm_P 0x80 /* датчик дыма СПФ */ + uint pep_code_f, pep_code_d, pep_code_ri, pep_code_ro; +#define PEP_code_F (sdt->pep_code_f) /* код отсчета фокуса телескопа */ +#define PEP_code_D (sdt->pep_code_d) /* код отсчета положения купола */ +#define PEP_code_Rin (sdt->pep_code_ri)/* код принятый из РК */ +#define PEP_code_Rout (sdt->pep_code_ro)/* код выдаваемый в РК */ + unsigned char pep_on[10]; /* флаги работы PEP-контроллеров */ +#define PEP_A_On (sdt->pep_on[0]) +#define PEP_A_Off (PEP_A_On==0) +#define PEP_Z_On (sdt->pep_on[1]) +#define PEP_Z_Off (PEP_Z_On==0) +#define PEP_P_On (sdt->pep_on[2]) +#define PEP_P_Off (PEP_P_On==0) +#define PEP_F_On (sdt->pep_on[3]) +#define PEP_F_Off (PEP_F_On==0) +#define PEP_D_On (sdt->pep_on[4]) +#define PEP_D_Off (PEP_D_On==0) +#define PEP_R_On (sdt->pep_on[5]) +#define PEP_R_Off ((PEP_R_On&1)==0) +#define PEP_R_Inp ((PEP_R_On&2)!=0) +#define PEP_K_On (sdt->pep_on[6]) +#define PEP_K_Off ((PEP_K_On&1)==0) +#define PEP_K_Inp ((PEP_K_On&2)!=0) + + /* IERS polar motion (источник: ftp://maia.usno.navy.mil/ser7/ser7.dat) */ + double xpol, ypol; +#define polarX (sdt->xpol) /* X-поправкa полож.полюса */ +#define polarY (sdt->ypol) /* Y-поправкa полож.полюса */ + + double jdate, eetime; +#define JDate (sdt->jdate) /* текущая юлианская дата */ +#define EE_time (sdt->eetime) /* поправ.зв.вр. за "Equation of the Equinoxes" */ + + /* еще ввод метео-данных */ + double val_hmd, inp_hmd; +#define val_Hmd (sdt->val_hmd) /* значение влажности (%) */ +#define inp_Hmd (sdt->val_hmd) /* ручной ввод */ + + /* положение червяка (подвеска) */ + double worm_a, worm_z; +#define worm_A (sdt->worm_a) /* положение подвески A (мкм) */ +#define worm_Z (sdt->worm_z) /* положение подвески Z (мкм) */ + + /* флаги блокировки управления узлами */ + __uint32_t lock_flags; +#define LockFlags (sdt->lock_flags) +#define Lock_A 0x01 +#define Lock_Z 0x02 +#define Lock_P 0x04 +#define Lock_F 0x08 +#define Lock_D 0x10 +#define A_Locked (LockFlags&Lock_A) +#define Z_Locked (LockFlags&Lock_Z) +#define P_Locked (LockFlags&Lock_P) +#define F_Locked (LockFlags&Lock_F) +#define D_Locked (LockFlags&Lock_D) + + /* требуемая скорость привода купола (для упр-я SEW-приводами)*/ + int sew_dome_speed; /* пока тоже что и Dome_State */ +#define Dome_Speed (sdt->sew_dome_speed) /* т.е. D_Lplus,D_Lminus,.... */ + +/* номер SEW-движка купола (для индикации)*/ + int sew_dome_num; +#define DomeSEW_N (sdt->sew_dome_num) + +/* параметры выбранного(DomeSEW_N) SEW-контроллера купола*/ +struct SEWdata sewdomedrv; +#define statusSEWD (sdt->sewdomedrv.status) /*состояние контроллера*/ +#define speedSEWD (sdt->sewdomedrv.set_speed) /*установленная скорость об/мин (rpm)*/ +#define vel_SEWD (sdt->sewdomedrv.mes_speed) /*измеренная скорость об/мин (rpm)*/ +#define currentSEWD (sdt->sewdomedrv.current) /*ток (А)*/ +#define indexSEWD (sdt->sewdomedrv.index) /*номер параметра*/ +#define valueSEWD (sdt->sewdomedrv.value.l) /*код значения параметра*/ + +/* информация PEP-контроллера купола */ + uint pep_code_di, pep_code_do; +#define PEP_code_Din (sdt->pep_code_di) /* код принятый из PEP-купола */ +#define PEP_Dome_SEW_Ok 0x200 +#define PEP_Dome_Cable_Ok 0x100 +#define PEP_code_Dout (sdt->pep_code_do) /* код выдаваемый в PEP-купола */ +#define PEP_Dome_SEW_On 0x10 +#define PEP_Dome_SEW_Off 0x20 + +}; + +#ifndef BTA_MODULE +struct BTA_Data *sdt; +#else +extern struct BTA_Data *sdt; +#endif + +struct BTA_Local { /* структура локальных данных */ + unsigned char reserve[120]; /* свободное место для расширения глобальной области */ + /* (на глобальную область резервируем 1500 байт) */ + double pr_oil_a,pr_oil_z,pr_oil_t; +#define PressOilA (sdtl->pr_oil_a) /* Давление в маслопроводе A (МПа) */ +#define PressOilZ (sdtl->pr_oil_z) /* Давление в маслопроводе Z (МПа) */ +#define PressOilTank (sdtl->pr_oil_t) /* Датчик уровня масла в баке(КПа) */ + double t_oil_1,t_oil_2; +#define OilTemper1 (sdtl->t_oil_1) /* Температура масла */ +#define OilTemper2 (sdtl->t_oil_2) /* Температура охлаждающей воды */ +}; + +#ifndef BTA_MODULE +struct BTA_Local *sdtl; /* конец глобальных, начало локальных данных */ +#else +extern struct BTA_Local *sdtl; +#endif + +#define ClientSide 0 +#define ServerSide 1 + +#ifndef BTA_MODULE +static void bta_data_init(); +static int bta_data_check(); +static void bta_data_close(); + +/* описание блока данных алгоритма управления ("глобальная область") */ +struct SHM_Block sdat = { +{'S','d','a','t',0},sizeof(struct BTA_Data),2048,0444,SHM_RDONLY,bta_data_init,bta_data_check,bta_data_close,0,-1,NULL +}; +#else +extern struct SHM_Block sdat; +#endif + +#ifndef BTA_MODULE +/* инициализация данных алгоритма управления (обнуление "глобальной области") */ +static void bta_data_init() { + int i; + sdt = (struct BTA_Data *)sdat.addr; + sdtl = (struct BTA_Local *)(sdat.addr+sizeof(struct BTA_Data)); + if(sdat.side == ClientSide) { + if(sdt->magic != sdat.key.code) { + fprintf(stderr,"Wrong shared data (maybe server turned off)\n"); + /*exit(1);*/ + } + if(sdt->version == 0) { + fprintf(stderr,"Null shared data version (maybe server turned off)\n"); + /*exit(1);*/ + } + else if(sdt->version != BTA_Data_Ver) { + fprintf(stderr,"Wrong shared data version: I'am - %d, but server - %d ...\n", + BTA_Data_Ver, sdt->version ); + /*exit(1);*/ + } + if(sdt->size != sdat.size) { + if(sdt->size > sdat.size) { + /* но клиент имеет право использовать начальную часть данных */ + fprintf(stderr,"Wrong shared area size: I needs - %d, but server - %d ...\n", + sdat.size, sdt->size ); + } else { + /* "залезание" в пустую резервную часть теперь тоже */ + /* будем оставлять на совести автора клиента! */ + fprintf(stderr,"Attention! Too little shared data structure!\n"); + sleep(1); + fprintf(stderr,"I needs - %d, but server gives only %d ...\n", + sdat.size, sdt->size ); + sleep(1); + fprintf(stderr,"May be server's version too old!?\n"); + /* exit(1); */ + + } + } + return; + } + /* ServerSide */ + if(sdt->magic != sdat.key.code || + sdt->version != BTA_Data_Ver || + sdt->size != sdat.size) { + + for(i=0; imagic = sdat.key.code; + sdt->version = BTA_Data_Ver; + sdt->size = sdat.size; + ServPID = 0; + UseModel = NoModel; + ClockType = Ch7_15; + Sys_Mode = SysStop; + Sys_Target = TagPosition; + Tel_Focus = Prime; + Tel_Hardware = Hard_On; + Tel_Mode = Automatic; + Az_Mode = Rev_Off; + P2_State = P2_Mode = P2_Off; + Foc_State = Foc_Off; + Dome_State = D_Off; + Pos_Corr = PC_On; + TrkOk_Mode = UseDiffVel | UseDiffAZ ; + InpAlpha=InpDelta= 0.; + SrcAlpha=SrcDelta= 0.; + VelAlpha=VelDelta= 0.; + CurAlpha=CurDelta= 0.; + InpAzim=InpZdist = 0.; + Diff_A=Diff_Z=Diff_P=0.0; + pos_cor_A=pos_cor_Z=refract_Z = 0.; + tel_cor_A=tel_cor_Z=tel_ref_Z = 0.; + vel_objA=vel_objZ=vel_objP = 0.; + diff_vA=diff_vZ=diff_vP=0.; + speedA = speedZ = speedP = 0.; + req_speedA = req_speedZ = req_speedP = 0.; + mod_vel_A=mod_vel_Z=mod_vel_P=mod_vel_F=mod_vel_D=0.; + code_KOST = 0; + M_time = S_time = L_time = 0.; + ppndd_A=ppndd_Z=ppndd_P=ppndd_B=0; + dup_A=dup_Z=dup_P=dup_F=dup_D=0; + low_A=low_Z=low_P=low_F=low_D=0; + code_A=code_Z=code_P=code_B=code_F=code_D=code_T1=code_T2=code_T3=code_Wnd=0; + val_A=val_Z=val_P=val_B=val_F=val_D=val_T1=val_T2=val_T3=val_Wnd=val_Alp=val_Del=0.; + vel_A=vel_Z=vel_P=vel_F=vel_D=0.; + for(i=0; imagic == sdat.key.code) && (sdt->version == BTA_Data_Ver) ); +} +static void bta_data_close() { + if(sdat.side == ServerSide) { + sdt->magic = 0; + sdt->version = 0; + } +} + +/* блок информационных сообщений ??? */ +/*struct SHM_Block info = {{'I','n','f','o',0},1024,1024,0444,SHM_RDONLY,NULL,NULL,NULL,0,-1,NULL};*/ + +/* Allocate shared memory segment */ +static void get_shm_block( struct SHM_Block *sb, int server) { + int getsize = (server)? sb->maxsize : sb->size; + + /* first try to find existing one */ + sb->id = shmget(sb->key.code, getsize, sb->mode); + + if (sb->id<0 && errno==ENOENT && server) { + /* if no - try to create a new one */ + int cresize = sb->maxsize; + if(sb->size > cresize) { + fprintf(stderr,"Wrong shm maxsize(%d) < realsize(%d)\n",sb->maxsize,sb->size); + cresize = sb->size; + } + sb->id = shmget(sb->key.code, cresize, IPC_CREAT|IPC_EXCL|sb->mode); + } + if (sb->id<0) { + char msg[80]; + if(server) + sprintf(msg,"Can't create shared memory segment '%s'",sb->key.name); + else + sprintf(msg,"Can't find shared segment '%s' (maybe no server process) ",sb->key.name); + perror(msg); + exit(errno); + } + /* attach it to our memory space */ + sb->addr = (unsigned char *)shmat ( sb->id, NULL, sb->atflag ); + + if ((int)(sb->addr) == -1) { + char msg[80]; + sprintf(msg,"Can't attach shared memory segment '%s'",sb->key.name); + perror(msg); + exit(errno); + } + if(server) { + if((shmctl(sb->id, SHM_LOCK, NULL) < 0) < 0) { + char msg[80]; + sprintf(msg,"Can't prevents swapping of shared memory segment '%s'",sb->key.name); + perror(msg); + exit(errno); + } + } + fprintf(stderr,"Create&attach shared memory segment '%s' %dbytes at %x \n", + sb->key.name, sb->size, (uint)sb->addr); + + sb->side = server; + + if(sb->init!=NULL) + sb->init(); +} +static int close_shm_block( struct SHM_Block *sb) { + int ret; + if(sb->close != NULL) + sb->close(); + if(sb->side == ServerSide) { +// ret = shmctl(sb->id, SHM_UNLOCK, NULL); + ret = shmctl(sb->id, IPC_RMID, NULL); + } + ret = shmdt (sb->addr); + return(ret); +} +#endif + +static int check_shm_block( struct SHM_Block *sb) { + if(sb->check != NULL) + return(sb->check()); + else return(1); +} + +#ifndef BTA_MODULE +int snd_id=-1; /* текущий (и единственный?) канал отсылки команд клиента */ +int cmd_src_pid=0; /* номер процесса источника для ОДНОЙ след.команды */ +__uint32_t cmd_src_ip=0; /* IP-адр. источника для ОДНОЙ след.команды */ +#else +extern int snd_id; +extern int cmd_src_pid; +extern __uint32_t cmd_src_ip; +#endif + +#ifndef BTA_MODULE +/* Create|Find command queue */ +static void get_cmd_queue( struct CMD_Queue *cq, int server) { + if (!server && cq->id>=0) { /* if already in use */ + snd_id = cq->id; /* set current... */ + return; + } + /* first try to find existing one */ + cq->id = msgget(cq->key.code, cq->mode); + if (cq->id<0 && errno==ENOENT && server) + /* if no - try to create a new one */ + cq->id = msgget(cq->key.code, IPC_CREAT|IPC_EXCL|cq->mode); + if (cq->id<0) { + char msg[80]; + if(server) + sprintf(msg,"Can't create comand queue '%s'",cq->key.name); + else + sprintf(msg,"Can't find comand queue '%s' (maybe no server process) ",cq->key.name); + perror(msg); + exit(errno); + } + cq->side = server; + if (server) { + char buf[120]; /* выбросить все команды из очереди */ + while(msgrcv(cq->id, (struct msgbuf *)buf, 112, 0, IPC_NOWAIT)>0); + } else + snd_id = cq->id; + cq->acckey = 0; +} +#endif + +/* установка ключа доступа в тек. канале */ +static void set_acckey(uint newkey) { + if (snd_id<0) return; + if(ucmd.id==snd_id) ucmd.acckey=newkey; + else if(ocmd.id==snd_id) ocmd.acckey=newkey; + else if(mcmd.id==snd_id) mcmd.acckey=newkey; +} + +/* установка данных источника для ОДНОЙ след.команды */ +/* если не подходят умолчания: IP=0(локальная команда) и PID текущ.процесса */ +static void set_cmd_src(__uint32_t ip, int pid) { + cmd_src_pid = pid; + cmd_src_ip = ip; +} + +/* структура сообщения */ +struct my_msgbuf { + __int32_t mtype; /* type of message */ + __uint32_t acckey; /* ключ доступа клиента */ + __uint32_t src_pid; /* номер процесса источника */ + __uint32_t src_ip; /* IP-адр. источника, =0 - локальная команда */ + char mtext[100]; /* message text */ +}; +/* отсылка команд клиента к серверу */ +static void send_cmd(int cmd_code, char *buf, int size) { + struct my_msgbuf mbuf; + + if (snd_id<0) return; + if (size>100) size=100; + if (cmd_code>0) + mbuf.mtype = cmd_code; + else + return; + if(ucmd.id==snd_id) mbuf.acckey=ucmd.acckey; + else if(ocmd.id==snd_id) mbuf.acckey=ocmd.acckey; + else if(mcmd.id==snd_id) mbuf.acckey=mcmd.acckey; + + mbuf.src_pid = cmd_src_pid? cmd_src_pid : getpid(); + mbuf.src_ip = cmd_src_ip; + cmd_src_pid = cmd_src_ip = 0; + + if(size>0) + memcpy( mbuf.mtext, buf, size); + else { + mbuf.mtext[0] = 0; + size = 1; + } + msgsnd( snd_id, (struct msgbuf *)&mbuf, size+12, IPC_NOWAIT); +} +static void send_cmd_noarg(int cmd_code) { + send_cmd(cmd_code, NULL, 0); +} +static void send_cmd_str(int cmd_code, char *arg) { + send_cmd(cmd_code, arg, strlen(arg)+1); +} +static void send_cmd_i1(int cmd_code, int arg1) { + send_cmd(cmd_code, (char *)&arg1, sizeof(int)); +} +static void send_cmd_i2(int cmd_code, int arg1, int arg2) { + int ibuf[2]; + ibuf[0] = arg1; + ibuf[1] = arg2; + send_cmd(cmd_code, (char *)ibuf, 2*sizeof(int)); +} +static void send_cmd_i3(int cmd_code, int arg1, int arg2, int arg3) { + int ibuf[3]; + ibuf[0] = arg1; + ibuf[1] = arg2; + ibuf[2] = arg3; + send_cmd(cmd_code, (char *)ibuf, 3*sizeof(int)); +} +static void send_cmd_i4(int cmd_code, int arg1, int arg2, int arg3, int arg4) { + int ibuf[4]; + ibuf[0] = arg1; + ibuf[1] = arg2; + ibuf[2] = arg3; + ibuf[3] = arg4; + send_cmd(cmd_code, (char *)ibuf, 4*sizeof(int)); +} +static void send_cmd_d1(int cmd_code, double arg1) { + send_cmd(cmd_code, (char *)&arg1, sizeof(double)); +} +static void send_cmd_d2(int cmd_code, double arg1, double arg2) { + double dbuf[2]; + dbuf[0] = arg1; + dbuf[1] = arg2; + send_cmd(cmd_code, (char *)dbuf, 2*sizeof(double)); +} +static void send_cmd_i1d1(int cmd_code, int arg1, double arg2) { + struct { + int ival; + double dval; + } buf; + buf.ival = arg1; + buf.dval = arg2; + send_cmd(cmd_code, (char *)&buf, sizeof(buf)); +} +static void send_cmd_i2d1(int cmd_code, int arg1, int arg2, double arg3) { + struct { + int ival[2]; + double dval; + } buf; + buf.ival[0] = arg1; + buf.ival[1] = arg2; + buf.dval = arg3; + send_cmd(cmd_code, (char *)&buf, sizeof(buf)); +} +static void send_cmd_i3d1(int cmd_code, int arg1, int arg2, int arg3, double arg4) { + struct { + int ival[3]; + double dval; + } buf; + buf.ival[0] = arg1; + buf.ival[1] = arg2; + buf.ival[2] = arg3; + buf.dval = arg4; + send_cmd(cmd_code, (char *)&buf, sizeof(buf)); +} + +static void encode_lev_passwd(char *passwd, int nlev, uint *keylev, uint *codlev) { + char salt[4]; + char *encr; + union { + uint ui; + char c[4]; + } key,cod; + sprintf(salt,"L%1d",nlev); + encr = (char *)crypt(passwd, salt); + cod.c[0] = encr[2]; + key.c[0] = encr[3]; + cod.c[1] = encr[4]; + key.c[1] = encr[5]; + cod.c[2] = encr[6]; + key.c[2] = encr[7]; + cod.c[3] = encr[8]; + key.c[3] = encr[9]; + *keylev = key.ui; + *codlev = cod.ui; +} + +static int find_lev_passwd(char *passwd, uint *keylev, uint *codlev) { + int nlev; + for(nlev=5; nlev>0; nlev--) { + encode_lev_passwd(passwd, nlev, keylev, codlev); + if(nlev == 1 && code_Lev1 == *codlev) break; + if(nlev == 2 && code_Lev2 == *codlev) break; + if(nlev == 3 && code_Lev3 == *codlev) break; + if(nlev == 4 && code_Lev4 == *codlev) break; + if(nlev == 5 && code_Lev5 == *codlev) break; + } + return(nlev); +} + +static int check_lev_passwd(char *passwd) { + uint keylev,codlev; + int nlev; + nlev = find_lev_passwd(passwd, &keylev, &codlev); + if(nlev>0) set_acckey(keylev); + return(nlev); +} + +#pragma GCC diagnostic pop + +#endif // __BTA_SHDATA_H__ diff --git a/extern/fliusb-1.3.tgz b/extern/fliusb-1.3.tgz new file mode 100644 index 0000000..0c6b727 Binary files /dev/null and b/extern/fliusb-1.3.tgz differ diff --git a/extern/libfli-1.104.tgz b/extern/libfli-1.104.tgz new file mode 100644 index 0000000..7c9c389 Binary files /dev/null and b/extern/libfli-1.104.tgz differ diff --git a/locale/ru/LC_MESSAGES/takepic.mo b/locale/ru/LC_MESSAGES/takepic.mo new file mode 100644 index 0000000..af6abc7 Binary files /dev/null and b/locale/ru/LC_MESSAGES/takepic.mo differ diff --git a/locale/ru/ru.po b/locale/ru/ru.po new file mode 100644 index 0000000..0c31dcb --- /dev/null +++ b/locale/ru/ru.po @@ -0,0 +1,401 @@ +# 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 , YEAR. +# +msgid "" +msgstr "Project-Id-Version: PACKAGE VERSION\n" + "Report-Msgid-Bugs-To: \n" + "POT-Creation-Date: 2011-06-28 09:54+0400\n" + "PO-Revision-Date: 2011-06-28 09:22+0300\n" + "Last-Translator: Edward V. Emelianov \n" + "Language-Team: LANGUAGE \n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=koi8-r\n" + "Content-Transfer-Encoding: 8bit\n" + +#. "\tОпции:\n" +#: usage.c:78 +#, c-format +msgid "\tOptions:\n" +msgstr "\tОпции:\n" + +#. %.3f секунд до окончания экспозиции\n +#: takepic.c:166 +#, c-format +msgid "%.3f seconds till exposition ends\n" +msgstr "%.3f секунд до окончания экспозиции\n" + +#. %d секунд до окончания паузы\n +#: takepic.c:220 +#, c-format +msgid "%d seconds till pause ends\n" +msgstr "%d секунд до окончания паузы\n" + +#. Поле изображения: (%ld, %ld)(%ld, %ld) +#: takepic.c:125 +#, c-format +msgid "Array field: (%ld, %ld)(%ld, %ld)" +msgstr "Поле изображения: (%ld, %ld)(%ld, %ld)" + +#. Начинаю экспозицию %dмс, время: %s, файл: %s.%d.%d\n +#: takepic.c:160 +#, c-format +msgid "Begin exposition %dms, exptime: %s, filename: %s.%d.%d\n" +msgstr "Начинаю экспозицию %dмс, время: %s, файл: %s.%d.%d\n" + +#. Камера '%s' из домена %s +#: takepic.c:101 +#, c-format +msgid "Camera '%s', domain %s" +msgstr "Камера '%s' из домена %s" + +#. Не могу открыть файл журнала статистики +#: takepic.c:89 +msgid "Can't open statistics log file" +msgstr "Не могу открыть журнал статистики" + +#. Не могу открыть файл журнала температур +#: takepic.c:80 +msgid "Can't open temperature log file" +msgstr "Не могу открыть журнал температур" + +#. Не могу сохранить файл +#: takepic.c:199 +msgid "Can't save file" +msgstr "Не могу сохранить файл" + +#. Захват кадра %d\n +#: takepic.c:155 +#, c-format +msgid "Capture frame %d\n" +msgstr "Захват кадра %d\n" + +#. "Съемка темновых" +#: usage.c:193 +msgid "Dark frames" +msgstr "Съемка темновых" + +#. "Время экспозиции: %dмс" +#: usage.c:296 +#, c-format +msgid "Exposure time: %dms" +msgstr "Время экспозиции: %dмс" + +#. Видимое поле: %s +#: takepic.c:120 +#, c-format +msgid "Field of view: %s" +msgstr "Видимое поле: %s" + +#. Файл записан в '%s' +#: takepic.c:203 +#, c-format +msgid "File saved as '%s'" +msgstr "Файл записан в '%s'" + +#. Полное журналирование статистики без сохранения изображений +#: usage.c:225 +msgid "Full statistics logging without saving images" +msgstr "Полное журналирование статистики без сохранения изображений" + +#. Апп. версия: %ld +#: takepic.c:110 +#, c-format +msgid "HW revision: %ld" +msgstr "Апп. версия: %ld" + +#. "Гор. биннинг: %d" +#: usage.c:209 +#, c-format +msgid "Horisontal binning: %d" +msgstr "Гор. биннинг: %d" + +#. "Игнорирую аргумент[ы]:\n" +#: usage.c:327 +#, c-format +msgid "Ignore argument[s]:\n" +msgstr "Игнорирую аргумент[ы]:\n" + +#. Статистика по изображению\n +#: takepic.c:470 +#, c-format +msgid "Image stat:\n" +msgstr "Статистика по изображению\n" + +#. "Тип изображения - %s" +#: usage.c:214 +#, c-format +msgid "Image type - %s" +msgstr "Тип изображения - %s" + +#. Температура (внутр.): %f +#: takepic.c:141 +#, c-format +msgid "Inner temperature: %f" +msgstr "Температура (внутр.): %f" + +#. "Название прибора - %s" +#: usage.c:219 +#, c-format +msgid "Instrument name - %s" +msgstr "Название прибора - %s" + +#. Версия библиотеки '%s' +#: takepic.c:75 +#, c-format +msgid "Library version '%s'" +msgstr "Версия библиотеки '%s'" + +#. Модель:\t\t%s +#: takepic.c:106 +#, c-format +msgid "Model:\t\t%s" +msgstr "Модель:\t\t%s" + +#. "N сбросов перед экспозицией" +#: usage.c:87 +msgid "N flushes before exposing" +msgstr "N сбросов перед экспозицией" + +#. Камеры не найдены!\n +#: takepic.c:286 +msgid "No cameras found!\n" +msgstr "Камеры не найдены!\n" + +#. "Имя объекта - %s" +#: usage.c:243 +#, c-format +msgid "Object name - %s" +msgstr "Имя объекта - %s" + +#. "Наблюдатели: %s" +#: usage.c:248 +#, c-format +msgid "Observers: %s" +msgstr "Наблюдатели: %s" + +#. Температура (внешн.): %f +#: takepic.c:144 +#, c-format +msgid "Outern temperature: %f" +msgstr "Температура (внешн.): %f" + +#. "Нет префикса имени выходных файлов" +#: usage.c:316 +msgid "Output file names prefix is absent" +msgstr "Нет префикса имени выходных файлов" + +#. "Пауза: %dс" +#: usage.c:261 +#, c-format +msgid "Pause: %ds" +msgstr "Пауза: %dс" + +#. Размер пикселя: %g x %g +#: takepic.c:116 +#, c-format +msgid "Pixel size: %g x %g" +msgstr "Размер пикселя: %g x %g" + +#. "Автор программы: %s" +#: usage.c:188 +#, c-format +msgid "Program author: %s" +msgstr "Автор программы: %s" + +#. "Название программы: %s" +#: usage.c:253 +#, c-format +msgid "Program name: %s" +msgstr "Название программы: %s" + +#. Считывание изображения: +#: takepic.c:179 +#, c-format +msgid "Read image: " +msgstr "Считывание изображения: " + +#. Прогр. версия: %ld +#: takepic.c:113 +#, c-format +msgid "SW revision: %ld" +msgstr "Прогр. версия: %ld" + +#. "Сохранение журнала температур" +#: usage.c:230 +msgid "Save temperature log" +msgstr "Сохранение журнала температур" + +#. "Серия из %d кадров" +#: usage.c:238 +#, c-format +msgid "Series of %d frames" +msgstr "Серия из %d кадров" + +#. "Установить температуру: %.3f" +#: usage.c:280 +#, c-format +msgid "Set temperature: %.3f" +msgstr "Установить температуру: %.3f" + +#. "Использование:\t%s [опции] <префикс выходных файлов>\n" +#: usage.c:75 +#, c-format +msgid "Usage:\t%s [options] \n" +msgstr "Использование:\t%s [опции] <префикс выходных файлов>\n" + +#. "Верт. биннинг: %d" +#: usage.c:288 +#, c-format +msgid "Vertical binning: %d" +msgstr "Верт. биннинг: %d" + +#. "Неверный" +#: usage.c:206 usage.c:285 +msgid "Wrong" +msgstr "Неверный" + +#. "Неверное время экспозиции: %s" +#: usage.c:293 +#, c-format +msgid "Wrong exposure time: %s" +msgstr "Неверное время экспозиции: %s" + +#. "Неверное кол-во кадров: %s" +#: usage.c:235 +#, c-format +msgid "Wrong frames number in series: %s" +msgstr "Неверное кол-во кадров: %s" + +#. "Неверная нижняя граница: %s" +#: usage.c:54 +#, c-format +msgid "Wrong lower border: %s" +msgstr "Неверная нижняя граница: %s" + +#. "Неверная пауза: %s" +#: usage.c:258 +#, c-format +msgid "Wrong pause length: %s" +msgstr "Неверная пауза: %s" + +#. "Неверное значение температуры: %s (должно быть от -55 до 30)" +#: usage.c:276 +#, c-format +msgid "Wrong temperature: %s (must be from -55 to 30)" +msgstr "Неверное значение температуры: %s (должно быть от -55 до 30)" + +#. "Неверная верхняя граница: %s" +#: usage.c:59 +#, c-format +msgid "Wrong upper border: %s" +msgstr "Неверная верхняя граница: %s" + +#. "Диапазон по X: [%d, %d]" +#: usage.c:301 +#, c-format +msgid "X range: [%d, %d]" +msgstr "Диапазон по X: [%d, %d]" + +#. "Диапазон по Y: [%d, %d]" +#: usage.c:306 +#, c-format +msgid "Y range: [%d, %d]" +msgstr "Диапазон по Y: [%d, %d]" + +#. дата/время +#: takepic.c:171 takepic.c:225 +msgid "date/time" +msgstr "дата/время" + +#. "не сохранять изображения, лишь вести запись статистки" +#: usage.c:99 +msgid "don't save images, only make all-stat log" +msgstr "не сохранять изображения, лишь вести запись статистки" + +#. "биннинг N пикселей по горизонтали" +#: usage.c:90 +msgid "horizontal binning to N pixels" +msgstr "биннинг N пикселей по горизонтали" + +#. "тип изображения" +#: usage.c:93 +msgid "image type" +msgstr "тип изображения" + +#. "название прибора" +#: usage.c:96 +msgid "instrument name" +msgstr "название прибора" + +#. "выдержать ptime секунд между экспозициями" +#: usage.c:117 +msgid "make pause for ptime seconds between expositions" +msgstr "выдержать ptime секунд между экспозициями" + +#. "N кадров в серии" +#: usage.c:105 +msgid "make series of N frames" +msgstr "N кадров в серии" + +#. "вести запись рабочих температур в файл temp_log" +#: usage.c:102 +msgid "make temperatures logging to file temp_log" +msgstr "вести запись рабочих температур в файл temp_log" + +#. "не открывать затвор при экспозиции (\"темновые\")" +#: usage.c:84 +msgid "not open shutter, when exposing (\"dark frames\")" +msgstr "не открывать затвор при экспозиции (\"темновые\")" + +#. "не сохранять изображение, а только отобразить статистику" +#: usage.c:120 +msgid "not save image, just show statistics" +msgstr "не сохранять изображение, а только отобразить статистику" + +#. "название объекта" +#: usage.c:108 +msgid "object name" +msgstr "название объекта" + +#. "имена наблюдателей" +#: usage.c:111 +msgid "observers' names" +msgstr "имена наблюдателей" + +#. "название программы наблюдений" +#: usage.c:114 +msgid "observing program name" +msgstr "название программы наблюдений" + +#. "только задать/получить температуру" +#. "только отобразить/задать температуру" +#: usage.c:123 usage.c:270 +msgid "only set/get temperature" +msgstr "только задать/получить температуру" + +#. "автор программы" +#: usage.c:81 +msgid "program author" +msgstr "автор программы" + +#. "выбрать диапазон для считывания" +#: usage.c:135 usage.c:138 +msgid "select clip region" +msgstr "выбрать диапазон для считывания" + +#. "время экспозиции exptime мс" +#: usage.c:132 +msgid "set exposure time to exptime ms" +msgstr "время экспозиции exptime мс" + +#. "задать рабочую температуру degr градусов" +#: usage.c:126 +msgid "set work temperature to degr C" +msgstr "задать рабочую температуру degr градусов" + +#. "биннинг N пикселей по вертикали" +#: usage.c:129 +msgid "vertical binning to N pixels" +msgstr "биннинг N пикселей по вертикали" diff --git a/takepic.c b/takepic.c new file mode 100644 index 0000000..9748c97 --- /dev/null +++ b/takepic.c @@ -0,0 +1,503 @@ +#include "takepic.h" +#include "usage.h" +#ifdef USE_BTA +#include "bta_print.h" +#endif +#include +#include +#include +#include + +#ifdef USEPNG +int writepng(char *filename, int width, int height, void *data); +#endif /* USEPNG */ + +#define BUFF_SIZ 4096 + +#define TMBUFSIZ 40 // длина буфера для строки с временем +char tm_buf[TMBUFSIZ]; // буфер для строки с временем + +u_int16_t max=0, min=65535; // экстремальные значения текущего изображения +double avr, std; // среднее значение и среднеквадратическое отклонение текущего изобр. +char *camera = NULL, viewfield[80]; +double pixX, pixY; // размер пикселя + +int numcams = 0; + +void print_stat(u_int16_t *img, long size, FILE* f); + +int itime(){ // усл. время в секундах + struct timeval ct; + gettimeofday(&ct, NULL); + return (ct.tv_sec); +} +int time0; +int ltime(){ // время, прошедшее с момента запуска программы + return(itime()-time0); +} + +size_t curtime(char *s_time){ // строка - текущее время/дата + time_t tm = time(NULL); + return strftime(s_time, TMBUFSIZ, "%d/%m/%Y,%H:%M:%S", localtime(&tm)); +} + +double t_ext, t_int; // внешняя т., т. камеры (+ на конец экспозиции) +time_t expStartsAt; // время начала экспозиции (time_t) + +int check_filename(char *buff, char *outfile, char *ext){ + struct stat filestat; + int num; + for(num = 1; num < 10000; num++){ + if(snprintf(buff, BUFF_SIZ, "%s_%04d.%s", outfile, num, ext) < 1) + return 0; + if(stat(buff, &filestat)) // файла не существует + return 1; + } + return 0; +} + +int main(int argc, char **argv){ + int i; // для циклов + FILE *f_tlog = NULL;// файл, в который будет записываться журнал температур + FILE *f_statlog = NULL; // файл для статистики в режиме "только статистика" + char libver[LIBVERSIZ]; // буфер для версии библиотеки fli + cam_t *cam = NULL; // список камер + setlocale(LC_ALL, getenv("LC_ALL")); + setlocale(LC_NUMERIC, "C"); + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + //bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); + parse_args(argc, argv); + //TRYFUNC(FLISetDebugLevel, NULL /* "NO HOST" */, FLIDEBUG_ALL); + TRYFUNC(FLISetDebugLevel, NULL, FLIDEBUG_NONE); + TRYFUNC(FLIGetLibVersion, libver, LIBVERSIZ); + // Версия библиотеки '%s' + info(_("Library version '%s'"), libver); + findcams(FLIDOMAIN_USB, &cam); + if(save_Tlog){ + f_tlog = fopen("temp_log", "a"); + // Не могу открыть файл журнала температур + if(!f_tlog) err(1, _("Can't open temperature log file")); + fprintf(f_tlog, "\n\n\n"); + } + if(stat_logging){ + struct stat s; + char print_hdr = 1; + if(stat("stat_log", &s) == 0) print_hdr = 0; + f_statlog = fopen("stat_log", "a"); + // Не могу открыть файл журнала статистики + if(!f_statlog) err(1, _("Can't open statistics log file")); + if(print_hdr) + fprintf(f_statlog, "Time\t\t\tUnix time\tTexp\tTint\tText\tImax\tImin\tIavr\tIstd\tNover\tN>3std\tIavr3\t\tIstd3\n"); + } + i = 0; + for (i = 0; i < numcams; i++){ + long x0,x1, y0,y1, row, img_rows, row_width, ltmp, img_size; + flidev_t dev; + char buff[BUFF_SIZ]; + u_int16_t *img; + int j; + // Камера '%s' из домена %s + info(_("Camera '%s', domain %s"), cam[i].name, cam[i].dname); + TRYFUNC(FLIOpen, &dev, cam[i].name, FLIDEVICE_CAMERA | cam[i].domain); + if(r) continue; + TRYFUNC(FLIGetModel, dev, buff, BUFF_SIZ); + // Модель:\t\t%s + info(_("Model:\t\t%s"), buff); + camera = strdup(buff); + TRYFUNC(FLIGetHWRevision, dev, <mp); + // Апп. версия: %ld + info(_("HW revision: %ld"), ltmp); + TRYFUNC(FLIGetFWRevision, dev, <mp); + // Прогр. версия: %ld + info(_("SW revision: %ld"), ltmp); + TRYFUNC(FLIGetPixelSize, dev, &pixX, &pixY); + // Размер пикселя: %g x %g + info(_("Pixel size: %g x %g"), pixX, pixY); + TRYFUNC(FLIGetVisibleArea, dev, &x0, &y0, &x1, &y1); + snprintf(viewfield, 79, "(%ld, %ld)(%ld, %ld)", x0, y0, x1, y1); + // Видимое поле: %s + info(_("Field of view: %s"), viewfield); + if(X1 > x1) X1 = x1; + if(Y1 > y1) Y1 = y1; + TRYFUNC(FLIGetArrayArea, dev, &x0, &y0, &x1, &y1); + // Поле изображения: (%ld, %ld)(%ld, %ld) + info(_("Array field: (%ld, %ld)(%ld, %ld)"), x0, y0, x1, y1); + TRYFUNC(FLISetHBin, dev, hbin); + TRYFUNC(FLISetVBin, dev, vbin); + if(X0 == -1) X0 = x0; // задаем значения по умолчанию + if(Y0 == -1) Y0 = y0; + if(X1 == -1) X1 = x1; + if(Y1 == -1) Y1 = y1; + row_width = (X1 - X0) / hbin; + img_rows = (Y1 - Y0) / vbin; + //TRYFUNC(FLISetImageArea, dev, ltmp, tmp2, tmp3, tmp4); + TRYFUNC(FLISetImageArea, dev, X0, Y0, + X0 + (X1 - X0) / hbin, Y0 + (Y1 - Y0) / vbin); + TRYFUNC(FLISetNFlushes, dev, flushes); + if(set_T) TRYFUNC(FLISetTemperature, dev, temperature); + TRYFUNC(FLIGetTemperature, dev, &t_int); + // Температура (внутр.): %f + info(_("Inner temperature: %f"), t_int); + TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_EXTERNAL, &t_ext); + // Температура (внешн.): %f + info(_("Outern temperature: %f"), t_ext); + if(only_T) continue; + TRYFUNC(FLISetExposureTime, dev, exptime); + TRYFUNC(FLISetFrameType, dev, frametype); + //TRYFUNC(FLISetBitDepth, dev, FLI_MODE_16BIT); + img_size = img_rows * row_width * sizeof(u_int16_t); + if((img = malloc(img_size)) == NULL) err(1, "malloc() failed"); + for (j = 0; j < pics; j ++){ + TRYFUNC(FLIGetTemperature, dev, &temperature); // температура до начала экспозиции + printf("\n\n"); + // Захват кадра %d\n + printf(_("Capture frame %d\n"), j); + TRYFUNC(FLIExposeFrame, dev); + expStartsAt = time(NULL); // время начала экспозиции + if(save_Tlog) if(curtime(tm_buf)) + // Начинаю экспозицию %dмс, время: %s, файл: %s.%d.%d\n + fprintf(f_tlog, _("Begin exposition %dms, exptime: %s, filename: %s.%d.%d\n"), + exptime, tm_buf, outfile, i, j); + do{ + TRYFUNC(FLIGetExposureStatus, dev, <mp); + if(r) break; + // %.3f секунд до окончания экспозиции\n + printf(_("%.3f seconds till exposition ends\n"), ((float)ltmp) / 1000.); + TRYFUNC(FLIGetTemperature, dev, &t_int); + TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_EXTERNAL, &t_ext); + if(curtime(tm_buf)){ + // дата/время + printf("%s: %s\tText=%.2f\tTint=%.2f\n", _("date/time"), tm_buf, t_ext, t_int); + if(save_Tlog) fprintf(f_tlog, "%s\t\t%.5f\t\t%.5f\n", tm_buf, t_ext, t_int); + } + else info("curtime() error"); + if(ltmp > 10000) sleep(10); + else usleep(ltmp * 1000); + }while(ltmp); + // Считывание изображения: + printf(_("Read image: ")); + int portion = 0; + for (row = 0; row < img_rows; row++){ + TRYFUNC(FLIGrabRow, dev, &img[row * row_width], row_width); + if(r) break; + int progress = (int)(((float)row / (float)img_rows) * 100.); + if(progress/5 > portion){ + if((++portion)%2) printf(".."); + else printf("%d%%", portion*5); + fflush(stdout); + } + } + printf("100%%\n"); + curtime(tm_buf); + if(f_statlog) + fprintf(f_statlog, "%s\t%ld\t%g\t%.2f\t%.2f\t", tm_buf, time(NULL), exptime/1000., t_int, t_ext); + print_stat(img, row_width * img_rows, f_statlog); + inline void WRITEIMG(int (*writefn)(char*,int,int,void*), char *ext){ + if(!check_filename(buff, outfile, ext)) + // Не могу сохранить файл + err(1, _("Can't save file")); + else{ + TRYFUNC(writefn, buff, row_width, img_rows, img); + // Файл записан в '%s' + if (r == 0) info(_("File saved as '%s'"), buff); + } + } + if(save_image){ + #ifdef USERAW + WRITEIMG(writeraw, "raw"); + #endif // USERAW + WRITEIMG(writefits, "fit"); + #ifdef USEPNG + WRITEIMG(writepng, "png"); + #endif /* USEPNG */ + } + if(pause_len){ + int delta; + time0 = itime(); + while((delta = pause_len - ltime()) > 0){ + // %d секунд до окончания паузы\n + printf(_("%d seconds till pause ends\n"), delta); + TRYFUNC(FLIGetTemperature, dev, &t_int); + TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_EXTERNAL, &t_ext); + if(curtime(tm_buf)){ + // дата/время + printf("%s: %s\tText=%.2f\tTint=%.2f\n", _("date/time"), tm_buf, t_ext, t_int); + if(save_Tlog) fprintf(f_tlog, "%s\t\t%.5f\t\t%.5f\n", tm_buf, t_ext, t_int); + } + else info("curtime() error"); + if(delta > 10) sleep(10); + else sleep(delta); + } + } + } + free(camera); + free(img); + TRYFUNC(FLIClose, dev); + } + for (i = 0; i < numcams; i++) + free(cam[i].name); + free(cam); + if(f_tlog) fclose(f_tlog); + if(f_statlog) fclose(f_statlog); + exit(0); +} + +void findcams(flidomain_t domain, cam_t **cam){ + long r; + char **tmplist; + TRYFUNC(FLIList, domain | FLIDEVICE_CAMERA, &tmplist); + if (tmplist != NULL && tmplist[0] != NULL){ + int i, cams = 0; + for (i = 0; tmplist[i] != NULL; i++) cams++; + if ((*cam = realloc(*cam, (numcams + cams) * sizeof(cam_t))) == NULL) + err(1, "realloc() failed"); + for (i = 0; tmplist[i] != NULL; 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; + switch (domain){ + 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; + } + tmpcam->name = strdup(tmplist[i]); + } + numcams += cams; + } + // Камеры не найдены!\n + else info(_("No cameras found!\n")); + TRYFUNC(FLIFreeList, tmplist); + return; +} + +#ifdef USERAW +int writeraw(char *filename, int width, int height, void *data){ + int fd, size, err; + if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) == -1){ + warn("open(%s) failed", filename); + return -errno; + } + size = width * height * sizeof(u_int16_t); + if ((err = write(fd, data, size)) != size){ + warn("write() failed"); + err = -errno; + } + else err = 0; + close(fd); + return err; +} +#endif // USERAW + +/* + * В шапке должны быть: + * RATE / Readout rate (KPix/sec) + * GAIN / gain, e/ADU + * SEEING / Seeing ('') + * IMSCALE / Image scale (''/pix x ''/pix) + * CLOUDS / Clouds (%) + */ + + +int writefits(char *filename, int width, int height, void *data){ + long naxes[2] = {width, height}, startTime; + double tmp = 0.0; + struct tm *tm_starttime; + char buf[80]; + time_t savetime = time(NULL); + fitsfile *fp; + TRYFITS(fits_create_file, &fp, filename); + TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes); + // 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){ + WRITEKEY(fp, TSTRING, "DETECTOR", camera, "Detector model"); + } + // INSTRUME / Instrument + if(instrument){ + WRITEKEY(fp, TSTRING, "INSTRUME", instrument, "Instrument"); + }else + WRITEKEY(fp, TSTRING, "INSTRUME", "direct imaging", "Instrument"); + // BZERO / zero point in scaling equation + //WRITEKEY(fp, TDOUBLE, "BZERO", &tmp, "zero point in scaling equation"); + // BSCALE / linear factor in scaling equation + //tmp = 1.0; WRITEKEY(fp, TDOUBLE, "BSCALE", &tmp, "linear factor in scaling equation"); + snprintf(buf, 79, "%.g x %.g", pixX, pixY); + // PXSIZE / pixel size + WRITEKEY(fp, TSTRING, "PXSIZE", buf, "Pixel size in m"); + WRITEKEY(fp, TSTRING, "VIEW_FIELD", viewfield, "Camera field of view"); + // CRVAL1, CRVAL2 / Offset in X, Y + if(X0) WRITEKEY(fp, TINT, "CRVAL1", &X0, "Offset in X"); + if(Y0) WRITEKEY(fp, TINT, "CRVAL2", &Y0, "Offset in Y"); + if(exptime == 0) sprintf(buf, "bias"); + else if(frametype == FLI_FRAME_TYPE_DARK) sprintf(buf, "dark"); + else if(objtype) strncpy(buf, objtype, 79); + else sprintf(buf, "object"); + // IMAGETYP / object, flat, dark, bias, scan, eta, neon, push + WRITEKEY(fp, TSTRING, "IMAGETYP", buf, "Image type"); + // DATAMAX, DATAMIN / Max,min pixel value + WRITEKEY(fp, TUSHORT, "DATAMAX", &max, "Max pixel value"); + WRITEKEY(fp, TUSHORT, "DATAMIN", &min, "Min pixel value"); + WRITEKEY(fp, TDOUBLE, "DATAAVR", &avr, "Average pixel value"); + WRITEKEY(fp, TDOUBLE, "DATASTD", &std, "Standart deviation of pixel value"); + WRITEKEY(fp, TDOUBLE, "TEMP0", &temperature, "Camera temperature at exp. start (degr C)"); + WRITEKEY(fp, TDOUBLE, "TEMP1", &t_int, "Camera temperature at exp. end (degr C)"); + WRITEKEY(fp, TDOUBLE, "TEMPBODY", &t_ext, "Camera body temperature at exp. end (degr C)"); + tmp = (temperature + t_int) / 2. + 273.15; + // CAMTEMP / Camera temperature (K) + WRITEKEY(fp, TDOUBLE, "CAMTEMP", &tmp, "Camera temperature (K)"); + tmp = (double)exptime / 1000.; + // EXPTIME / actual exposition time (sec) + WRITEKEY(fp, TDOUBLE, "EXPTIME", &tmp, "actual exposition time (sec)"); + // DATE / Creation date (YYYY-MM-DDThh:mm:ss, UTC) + strftime(buf, 79, "%Y-%m-%dT%H:%M:%S", gmtime(&savetime)); + WRITEKEY(fp, TSTRING, "DATE", buf, "Creation date (YYYY-MM-DDThh:mm:ss, UTC)"); + startTime = (long)expStartsAt; + tm_starttime = localtime(&expStartsAt); + strftime(buf, 79, "exposition starts at %d/%m/%Y, %H:%M:%S (local)", tm_starttime); + WRITEKEY(fp, TLONG, "UNIXTIME", &startTime, buf); + strftime(buf, 79, "%Y/%m/%d", tm_starttime); + // DATE-OBS / DATE (YYYY/MM/DD) OF OBS. + WRITEKEY(fp, TSTRING, "DATE-OBS", buf, "DATE OF OBS. (YYYY/MM/DD, local)"); + strftime(buf, 79, "%H:%M:%S", tm_starttime); + // START / Measurement start time (local) (hh:mm:ss) + WRITEKEY(fp, TSTRING, "START", buf, "Measurement start time (hh:mm:ss, local)"); + // OBJECT / Object name + if(objname){ + WRITEKEY(fp, TSTRING, "OBJECT", objname, "Object name"); + } + // BINNING / Binning + if(hbin != 1 || vbin != 1){ + snprintf(buf, 79, "%d x %d", hbin, vbin); + WRITEKEY(fp, TSTRING, "BINNING", buf, "Binning (hbin x vbin)"); + } + // OBSERVER / Observers + if(observers){ + WRITEKEY(fp, TSTRING, "OBSERVER", observers, "Observers"); + } + // PROG-ID / Observation program identifier + if(prog_id){ + WRITEKEY(fp, TSTRING, "PROG-ID", prog_id, "Observation program identifier"); + } + // AUTHOR / Author of the program + if(author){ + WRITEKEY(fp, TSTRING, "AUTHOR", author, "Author of the program"); + } +#ifdef USE_BTA + write_bta_data(fp); +#endif + TRYFITS(fits_write_img, fp, TUSHORT, 1, width * height, data); + TRYFITS(fits_close_file, fp); + return 0; +} + +#ifdef USEPNG +int writepng(char *filename, int width, int height, void *data){ + int err; + FILE *fp = NULL; + png_structp pngptr = NULL; + png_infop infoptr = NULL; + void *row; + if ((fp = fopen(filename, "wb")) == NULL){ + err = -errno; + goto done; + } + if ((pngptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL)) == NULL){ + err = -ENOMEM; + goto done; + } + if ((infoptr = png_create_info_struct(pngptr)) == NULL){ + err = -ENOMEM; + goto done; + } + png_init_io(pngptr, fp); + png_set_compression_level(pngptr, Z_BEST_COMPRESSION); + png_set_IHDR(pngptr, infoptr, width, height, 16, PNG_COLOR_TYPE_GRAY, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + png_write_info(pngptr, infoptr); + png_set_swap(pngptr); + for(row = data; height > 0; row += width * sizeof(u_int16_t), height--) + png_write_row(pngptr, row); + png_write_end(pngptr, infoptr); + err = 0; + done: + if(fp) fclose(fp); + if(pngptr) png_destroy_write_struct(&pngptr, &infoptr); + return err; +} +#endif /* USEPNG */ + +void print_stat(u_int16_t *img, long size, FILE *f){ + long i, Noverld = 0L, N = 0L; + double pv, sum=0., sum2=0., sz = (double)size, tres; + u_int16_t *ptr = img, val; + max = 0; min = 65535; + for(i = 0; i < size; i++, ptr++){ + val = *ptr; + pv = (double) 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")); + avr = sum/sz; + printf("avr = %.1f, std = %.1f, Noverload = %ld\n", avr, + std = sqrt(fabs(sum2/sz - avr*avr)), Noverld); + printf("max = %u, min = %u, size = %ld\n", max, min, size); + // полная статистика, если у нас режим сохранения статистики: + if(!f) return; + // Iсреднее, Iсигма, Nперекоп + fprintf(f, "%d\t%d\t%.3f\t%.3f\t%ld\t", max, min, avr, std, Noverld); + Noverld = 0L; + ptr = img; sum = 0.; sum2 = 0.; + tres = avr + 3. * std; // порог по максимуму - 3 сигмы + for(i = 0; i < size; i++, ptr++){ + val = *ptr; + pv = (double) val; + if(pv > tres){ + Noverld++; // теперь это - кол-во слишком ярких пикселей + continue; + } + sum += pv; + sum2 += (pv * pv); + N++; + } + if(N == 0L){ + fprintf(f, "err\n"); + return; + } + sz = (double)N; + avr = sum/sz; std = sqrt(fabs(sum2/sz - avr*avr)); + // Nбольше3сигм, Iсреднее в пределах 3сигм, Iсигма в пределах 3сигм + fprintf(f, "%ld\t%.3f\t%.3f\n", Noverld, avr, std); + fflush(f); + printf("Novr3 = %ld\n", Noverld); +} diff --git a/takepic.h b/takepic.h new file mode 100644 index 0000000..189f881 --- /dev/null +++ b/takepic.h @@ -0,0 +1,95 @@ +#ifndef __TAKEPIC_H__ +#define __TAKEPIC_H__ +#define _XOPEN_SOURCE 501 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USEPNG +#include +#endif /* USEPNG */ + +#include "libfli.h" + +#ifndef GETTEXT_PACKAGE +#define GETTEXT_PACKAGE "takepic" +#endif +#ifndef LOCALEDIR +#define LOCALEDIR "./locale" +#endif + +#define _(String) gettext(String) +#define gettext_noop(String) String +#define N_(String) gettext_noop(String) + +// режим отладки, -DEBUG +#ifdef EBUG + #define RED "\033[1;32;41m" + #define GREEN "\033[5;30;42m" + #define OLDCOLOR "\033[0;0;0m" + #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) + #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n");} while(0) +#else + #define FNAME() do{}while(0) + #define DBG(...) do{}while(0) +#endif //EBUG + +extern const char *__progname; +#define info(format, args...) do{ \ + printf("%s: ", __progname); \ + printf(format, ## args); \ + printf("\n");}while(0) + +#define warnc(c, format, args...) \ + warnx(format ": %s", ## args, strerror(c)) + +long r; +#define TRYFUNC(f, ...) \ +do{ if((r = f(__VA_ARGS__))) \ + warnc(-r, #f "() failed"); \ +}while(0) + +#define LIBVERSIZ 1024 + +typedef struct{ + flidomain_t domain; + char *dname; + char *name; +}cam_t; + +void findcams(flidomain_t domain, cam_t **cam); +#ifdef USERAW +int writeraw(char *filename, int width, int height, void *data); +#endif // USERAW + +#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) +int writefits(char *filename, int width, int height, void *data); + + +#endif // __TAKEPIC_H__ diff --git a/usage.c b/usage.c new file mode 100644 index 0000000..1cc7200 --- /dev/null +++ b/usage.c @@ -0,0 +1,331 @@ +#include "usage.h" + +char + *objname = NULL // имя объекта + ,*outfile = NULL // префикс имени файла для записи raw/fits + ,*objtype = NULL // тип кадра (по умолчанию - object, при -d - dark) + ,*instrument = NULL // название прибора (по умолчанию - "direct imaging") + ,*observers = NULL // наблюдатели + ,*prog_id = NULL // имя программы + ,*author = NULL // автор +; +int + exptime = 500 // время экспозиции (в мс) + ,pics = 1 // кол-во снимаемых кадров + ,hbin = 1 // горизонтальный биннинг + ,vbin = 1 // вертикальный биннинг + ,X0=-1,Y0=-1 // координаты верхнего левого угла считываемого изображения + // -1 - вся область, в т.ч. "оверскан" + ,X1=-1,Y1=-1 // координаты правого нижнего угла считываемого изображения + ,flushes = 1 // кол-во сбросов + ,pause_len = 0 // продолжительность паузы (в с) между кадрами +; +double temperature = -20.; // температура (которую задать, потом - на начало эксп.) + +fliframe_t frametype = FLI_FRAME_TYPE_NORMAL; // тип фрейма (обычный или темновой) + +bool + only_T = FALSE // только отобразить температуру - и выйти + ,set_T = FALSE // задать нужную температуру + ,save_Tlog = FALSE // сохранять журнал температур + ,save_image = TRUE // сохранять изображение + ,stat_logging = FALSE // полное логгирование статистики +; +int myatoi(int *num, const char *str){ // "аккуратный" atoi + long tmp; + char *endptr; + tmp = strtol(str, &endptr, 0); + if (*str == '\0' || *endptr != '\0' || tmp < INT_MIN || tmp > INT_MAX){ + return -1; + } + *num = (int)tmp; + return 0; +} + +void getrange(int *X0, int *X1, char *arg){ + char *a = NULL, *pair; + pair = strdup(arg); + if((a = strchr(pair, ','))){ + *a = 0; + a++; + } + if(myatoi(X0, pair) || *X0 < 0){ + // "Неверная нижняя граница: %s" + usage(_("Wrong lower border: %s"), pair); + } + if(a){ + if(myatoi(X1, a) || *X1 < 0 || *X1 <= *X0){ + // "Неверная верхняя граница: %s" + usage(_("Wrong upper border: %s"), pair); + } + } + free(pair); +} + +void usage(char *fmt, ...){ + va_list ap; + va_start(ap, fmt); + printf("\n"); + if (fmt != NULL){ + vprintf(fmt, ap); + printf("\n\n"); + } + va_end(ap); + // "Использование:\t%s [опции] <префикс выходных файлов>\n" + printf(_("Usage:\t%s [options] \n"), + __progname); + // "\tОпции:\n" + printf(_("\tOptions:\n")); + printf("\t-A,\t--author=author\t\t%s\n", + // "автор программы" + _("program author")); + printf("\t-d,\t--dark\t\t\t%s\n", + // "не открывать затвор при экспозиции (\"темновые\")" + _("not open shutter, when exposing (\"dark frames\")")); + printf("\t-f,\t--flushes=N\t\t%s\n", + // "N сбросов перед экспозицией" + _("N flushes before exposing")); + printf("\t-h,\t--hbin=N\t\t%s\n", + // "биннинг N пикселей по горизонтали" + _("horizontal binning to N pixels")); + printf("\t-I,\t--image-type=type\t%s\n", + // "тип изображения" + _("image type")); + printf("\t-i,\t--instrument=instr\t%s\n", + // "название прибора" + _("instrument name")); + printf("\t-L,\t--log-only\t\t%s\n", + // "не сохранять изображения, лишь вести запись статистки" + _("don't save images, only make all-stat log")); + printf("\t-l,\t--tlog\t\t\t%s\n", + // "вести запись рабочих температур в файл temp_log" + _("make temperatures logging to file temp_log")); + printf("\t-n,\t--nframes=N\t\t%s\n", + // "N кадров в серии" + _("make series of N frames")); + printf("\t-O,\t--object=obj\t\t%s\n", + // "название объекта" + _("object name")); + printf("\t-o,\t--observer=obs\t\t%s\n", + // "имена наблюдателей" + _("observers' names")); + printf("\t-P,\t--prog-id=prname\t%s\n", + // "название программы наблюдений" + _("observing program name")); + printf("\t-p,\t--pause-len=ptime\t%s\n", + // "выдержать ptime секунд между экспозициями" + _("make pause for ptime seconds between expositions")); + printf("\t-s,\t--only-stat\t\t%s\n", + // "не сохранять изображение, а только отобразить статистику" + _("not save image, just show statistics")); + printf("\t-T,\t--only-temp\t\t%s\n", + // "только задать/получить температуру" + _("only set/get temperature")); + printf("\t-t,\t--set-temp=degr\t\t%s\n", + // "задать рабочую температуру degr градусов" + _("set work temperature to degr C")); + printf("\t-v,\t--vbin=N\t\t%s\n", + // "биннинг N пикселей по вертикали" + _("vertical binning to N pixels")); + printf("\t-x,\t--exp=exptime\t\t%s\n", + // "время экспозиции exptime мс" + _("set exposure time to exptime ms")); + printf("\t-X,\t--xclip=X0[,X1]\t\t%s [X0:X1]\n", + // "выбрать диапазон для считывания" + _("select clip region")); + printf("\t-Y,\t--xclip=Y0[,Y1]\t\t%s [Y0:Y1]\n", + // "выбрать диапазон для считывания" + _("select clip region")); + exit(0); +} + +void parse_args(int argc, char **argv){ + int i; + char short_options[] = "A:df:h:I:i:Lln:O:o:P:p:sTt:v:x:X:Y:"; + struct option long_options[] = { +/* { name, has_arg, flag, val }, где: + * name - имя "длинного" параметра + * has_arg = 0 - нет аргумента, 1 - обязательный аргумент, 2 - необязательный аргумент + * flag = NULL для возврата val, указатель на переменную int - для присвоения ей + * значения val (в этом случае функция возвращает 0) + * val - возвращаемое значение getopt_long или значение, присваемое указателю flag + * !!! последняя строка - четыре нуля + */ + {"author", 1, 0, 'A'}, + {"dark", 0, 0, 'd'}, + {"flushes", 1, 0, 'f'}, + {"hbin", 1, 0, 'h'}, + {"image-type", 1, 0, 'I'}, + {"instrument", 1, 0, 'i'}, + {"log-only", 0, 0, 'L'}, + {"tlog", 0, 0, 'l'}, + {"nframes", 1, 0, 'n'}, + {"object", 1, 0, 'O'}, + {"observers", 1, 0, 'o'}, + {"prog-id", 1, 0, 'P'}, + {"pause-len", 1, 0, 'p'}, + {"only-stat", 0, 0, 's'}, + {"only-temp", 0, 0, 'T'}, + {"set-temp", 1, 0, 't'}, + {"vbin", 1, 0, 'v'}, + {"exp", 1, 0, 'x'}, + {"xclip", 1, 0, 'X'}, + {"yclip", 1, 0, 'Y'}, + { 0, 0, 0, 0 } + }; +/* "длинные" и "короткие" параметры getopt_long не должны совпадать + * (лишь если "длинный" должен значить то же, что "короткий", для него + * должно быть flag = NULL, val = значение короткого + */ + while (1){ + int opt; + if((opt = getopt_long(argc, argv, short_options, + long_options, NULL)) == -1) break; + switch(opt){ + case 'A': + author = strdup(optarg); + // "Автор программы: %s" + info(_("Program author: %s"), author); + break; + case 'd': + frametype = FLI_FRAME_TYPE_DARK; + // "Съемка темновых" + info(_("Dark frames")); + break; + case 'f': + if (myatoi(&flushes, optarg) || flushes < 0){ + // "Неверное кол-во сбросов: %s" + usage("Wrong flushes number: %s", optarg); + } + // "Кол-во сбросов: %d" + info("Flushes number: %d", flushes); + break; + case 'h': + if (myatoi(&hbin, optarg) || hbin < 1 || hbin > 16){ + // "Неверный" + usage("%s hbin: %s", _("Wrong"), optarg); + } + // "Гор. биннинг: %d" + info(_("Horisontal binning: %d"), hbin); + break; + case 'I': + objtype = strdup(optarg); + // "Тип изображения - %s" + info(_("Image type - %s"), objtype); + break; + case 'i': + instrument = strdup(optarg); + // "Название прибора - %s" + info(_("Instrument name - %s"), instrument); + break; + case 'L': + stat_logging = TRUE; + save_image = FALSE; + // Полное журналирование статистики без сохранения изображений + info(_("Full statistics logging without saving images")); + break; + case 'l': + save_Tlog = TRUE; + // "Сохранение журнала температур" + info(_("Save temperature log")); + break; + case 'n': + if (myatoi(&pics, optarg) || pics <= 0){ + // "Неверное кол-во кадров: %s" + usage(_("Wrong frames number in series: %s"), optarg); + } + // "Серия из %d кадров" + info(_("Series of %d frames"), pics); + break; + case 'O': + objname = strdup(optarg); + // "Имя объекта - %s" + info(_("Object name - %s"), objname); + break; + case 'o': + observers = strdup(optarg); + // "Наблюдатели: %s" + info(_("Observers: %s"), observers); + break; + case 'P': + prog_id = strdup(optarg); + // "Название программы: %s" + info(_("Program name: %s"), prog_id); + break; + case 'p': + if (myatoi(&pause_len, optarg) || pause_len < 0){ + // "Неверная пауза: %s" + usage(_("Wrong pause length: %s"), optarg); + } + // "Пауза: %dс" + info(_("Pause: %ds"), pause_len); + break; + case 's': + save_image = FALSE; + break; + case 'T': + only_T = TRUE; + save_image = FALSE; + // "только отобразить/задать температуру" + info(_("only set/get temperature")); + break; + case 't': + temperature = atof(optarg); + if(temperature < -55. || temperature > 30.){ + // "Неверное значение температуры: %s (должно быть от -55 до 30)" + usage(_("Wrong temperature: %s (must be from -55 to 30)"), optarg); + } + set_T = TRUE; + // "Установить температуру: %.3f" + info(_("Set temperature: %.3f"), temperature); + break; + case 'v': + if (myatoi(&vbin, optarg) || vbin < 1 || vbin > 16){ + // "Неверный" + usage("%s vbin: %s", _("Wrong"), optarg); + } + // "Верт. биннинг: %d" + info(_("Vertical binning: %d"), vbin); + break; + case 'x': + if (myatoi(&exptime, optarg) || exptime < 0){ + // "Неверное время экспозиции: %s" + usage(_("Wrong exposure time: %s"), optarg); + } + // "Время экспозиции: %dмс" + info(_("Exposure time: %dms"), exptime); + break; + case 'X': + getrange(&X0, &X1, optarg); + // "Диапазон по X: [%d, %d]" + info(_("X range: [%d, %d]"), X0, X1); + break; + case 'Y': + getrange(&Y0, &Y1, optarg); + // "Диапазон по Y: [%d, %d]" + info(_("Y range: [%d, %d]"), Y0, Y1); + break; + default: + usage(NULL); + } + } + argc -= optind; + argv += optind; + if(argc == 0 && save_image){ + // "Нет префикса имени выходных файлов" + usage(_("Output file names prefix is absent")); + } + else{ if(argc != 0){ + outfile = argv[0]; + argc--; + argv++; + } + else outfile = strdup("nofile"); + } + if(argc > 0){ + // "Игнорирую аргумент[ы]:\n" + printf(_("Ignore argument[s]:\n")); + } + for (i = 0; i < argc; i++) + warnx("%s ", argv[i]); +} diff --git a/usage.h b/usage.h new file mode 100644 index 0000000..2f0afd0 --- /dev/null +++ b/usage.h @@ -0,0 +1,39 @@ +#ifndef __USAGE_H__ +#define __USAGE_H__ + +#include "takepic.h" +#include +#include + +extern int + exptime // время экспозиции (в мс) + ,pics // кол-во снимаемых кадров + ,hbin // горизонтальный биннинг + ,vbin // вертикальный биннинг + ,X0, X1, Y0, Y1 // координаты выбранного окна + ,flushes // кол-во сбросов + ,pause_len // продолжительность паузы (в с) между кадрами +; +extern double temperature; // температура (которую задать, потом - на начало эксп.) + +extern fliframe_t frametype; // тип фрейма (обычный или темновой) + +extern bool + only_T // только отобразить температуру - и выйти + ,set_T // задать нужную температуру + ,save_Tlog // сохранять журнал температур + ,save_image // сохранять изображение + ,stat_logging // полное логгирование статистики +; +extern char *objname // имя объекта + ,*outfile // префикс имени файла для записи raw/fits + ,*objtype // тип изображения + ,*instrument // название прибора (по умолчанию - "direct imaging") + ,*observers // наблюдатели + ,*prog_id // имя программы + ,*author // автор +; +void usage(char *fmt, ...); +void parse_args(int argc, char **argv); + +#endif // __USAGE_H__