diff --git a/debian/indi-mi/changelog b/debian/indi-mi/changelog index 413356ab0..22f2148f6 100644 --- a/debian/indi-mi/changelog +++ b/debian/indi-mi/changelog @@ -1,3 +1,9 @@ +indi-mi (2.0) buster; urgency=medium + + * Add MI Standalone Filter Wheel driver + + -- Jakub Smutny Tue, 05 Mar 2024 10:00:00 +0100 + indi-mi (1.8) buster; urgency=medium * Using MI Libraries again. diff --git a/debian/indi-mi/indi-mi.links b/debian/indi-mi/indi-mi.links index 8abb05ae0..2c1db862a 100644 --- a/debian/indi-mi/indi-mi.links +++ b/debian/indi-mi/indi-mi.links @@ -1,2 +1,4 @@ usr/bin/indi_mi_ccd usr/bin/indi_mi_ccd_usb usr/bin/indi_mi_ccd usr/bin/indi_mi_ccd_eth +usr/bin/indi_mi_sfw usr/bin/indi_mi_sfw_usb +usr/bin/indi_mi_sfw usr/bin/indi_mi_sfw_eth diff --git a/debian/libmicam/changelog b/debian/libmicam/changelog index cd733b62d..d3d934996 100644 --- a/debian/libmicam/changelog +++ b/debian/libmicam/changelog @@ -1,3 +1,9 @@ +libmicam (1.2) buster; urgency=low + + * Updated MI library to version 0.10.0/0.9.0 + + -- Jakub Smutny Tue, 05 Mar 2024 10:00:00 +0100 + libmicam (1.1) buster; urgency=low * Updated MI library to version 0.9.0/0.8.0 diff --git a/indi-mi/CMakeLists.txt b/indi-mi/CMakeLists.txt index 599cdd3f5..476bfe1a0 100644 --- a/indi-mi/CMakeLists.txt +++ b/indi-mi/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.16) -PROJECT(indi_miccd CXX C) +PROJECT(indi_mi CXX C) LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/") LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake_modules/") @@ -13,8 +13,8 @@ find_package(USB1 REQUIRED) find_package(Threads REQUIRED) find_package(CFITSIO REQUIRED) -set(INDI_MI_VERSION_MAJOR 1) -set(INDI_MI_VERSION_MINOR 9) +set(INDI_MI_VERSION_MAJOR 2) +set(INDI_MI_VERSION_MINOR 0) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/indi_miccd.xml.cmake ${CMAKE_CURRENT_BINARY_DIR}/indi_miccd.xml) @@ -22,8 +22,8 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/indi_miccd.xml.cmake ${CMAKE_CURRENT_ include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${INDI_INCLUDE_DIR}) -include_directories( ${CFITSIO_INCLUDE_DIR}) -include_directories( ${MICAM_INCLUDE_DIR}) +include_directories(${CFITSIO_INCLUDE_DIR}) +include_directories(${MICAM_INCLUDE_DIR}) ########### MI CCD ########### set(indi_miccd_SRCS @@ -37,13 +37,6 @@ else (APPLE) target_link_libraries(indi_mi_ccd ${INDI_LIBRARIES} ${CFITSIO_LIBRARIES} ${MICAM_LIBRARIES} ${USB1_LIBRARIES} Threads::Threads rt) endif(APPLE) -#if(THREADS_HAVE_PTHREAD_ARG) -# target_compile_options(indi_mi_ccd "-pthread") -#endif() -#if(CMAKE_THREAD_LIBS_INIT) -# target_link_libraries(indi_mi_ccd "${CMAKE_THREAD_LIBS_INIT}") -#endif() - install(TARGETS indi_mi_ccd RUNTIME DESTINATION bin) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/make_mi_ccd_symlink.cmake @@ -52,4 +45,26 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/make_mi_ccd_symlink.cmake set_target_properties(indi_mi_ccd PROPERTIES POST_INSTALL_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/make_mi_ccd_symlink.cmake) +########### MI SFW ########### +set(indi_misfw_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/mi_sfw.cpp + ) + +add_executable(indi_mi_sfw ${indi_misfw_SRCS}) +if (APPLE) + target_link_libraries(indi_mi_sfw ${INDI_LIBRARIES} ${CFITSIO_LIBRARIES} ${MICAM_LIBRARIES} ${USB1_LIBRARIES} Threads::Threads) +else (APPLE) + target_link_libraries(indi_mi_sfw ${INDI_LIBRARIES} ${CFITSIO_LIBRARIES} ${MICAM_LIBRARIES} ${USB1_LIBRARIES} Threads::Threads rt) +endif(APPLE) + +install(TARGETS indi_mi_sfw RUNTIME DESTINATION bin) + +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/make_mi_sfw_symlink.cmake +"exec_program(\"${CMAKE_COMMAND}\" ARGS -E create_symlink indi_mi_sfw \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/indi_mi_sfw_usb)\n + exec_program(\"${CMAKE_COMMAND}\" ARGS -E create_symlink indi_mi_sfw \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/indi_mi_sfw_eth)\n") + +set_target_properties(indi_mi_sfw PROPERTIES POST_INSTALL_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/make_mi_sfw_symlink.cmake) + +############################## + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/indi_miccd.xml DESTINATION ${INDI_DATA_DIR}) diff --git a/indi-mi/INSTALL b/indi-mi/INSTALL index 32bfc9a4c..e6a332df3 100644 --- a/indi-mi/INSTALL +++ b/indi-mi/INSTALL @@ -1,4 +1,4 @@ -MI CCD INSTALL +MI DRIVERS INSTALL ============== You must have CMake >= 2.8.0 in order to build this package. diff --git a/indi-mi/README b/indi-mi/README index 68d56fd6c..57c178e7b 100644 --- a/indi-mi/README +++ b/indi-mi/README @@ -1,7 +1,7 @@ -Moravian Instruments CCD Driver +Moravian Instruments INDI Driver =============================== -This package provides Moravian Instruments CCD INDI driver for MI CCD cameras. +This package provides Moravian Instruments INDI driver for MI cameras and standalone filter wheels. Requirements ============ @@ -29,14 +29,22 @@ How to Use To run the driver from the command line: - USB variant: + Cameras (USB variant): $ indiserver indi_mi_ccd_usb - ETH variant: + Cameras (ETH variant): $ indiserver indi_mi_ccd_eth + SFW (USB variant): + + $ indiserver indi_mi_sfw_usb + + SFW (ETH variant): + + $ indiserver indi_mi_sfw_eth + You can then connect to the driver from any client, the default port is 7624. If you're using KStars, the driver will be automatically listed in KStars' Device Manager, no further configuration is necessary. diff --git a/indi-mi/indi_miccd.xml.cmake b/indi-mi/indi_miccd.xml.cmake index bace8951e..f06babd4f 100644 --- a/indi-mi/indi_miccd.xml.cmake +++ b/indi-mi/indi_miccd.xml.cmake @@ -10,4 +10,14 @@ @INDI_MI_VERSION_MAJOR@.@INDI_MI_VERSION_MINOR@ + + + indi_mi_sfw_usb + @INDI_MI_VERSION_MAJOR@.@INDI_MI_VERSION_MINOR@ + + + indi_mi_sfw_eth + @INDI_MI_VERSION_MAJOR@.@INDI_MI_VERSION_MINOR@ + + diff --git a/indi-mi/mi_ccd.cpp b/indi-mi/mi_ccd.cpp index 1379d3815..584ef3a65 100644 --- a/indi-mi/mi_ccd.cpp +++ b/indi-mi/mi_ccd.cpp @@ -116,7 +116,8 @@ MICCD::MICCD(int camId, bool eth) : FilterInterface(this) else { rtrim(sp); - snprintf(name, MAXINDINAME, "MI %s", sp); + strncpy(name, "MI ", MAXINDINAME); + strncat(name, sp, MAXINDINAME - 3); IDLog("Detected camera: %s.\n", name); } diff --git a/indi-mi/mi_sfw.cpp b/indi-mi/mi_sfw.cpp new file mode 100644 index 000000000..788ab3e01 --- /dev/null +++ b/indi-mi/mi_sfw.cpp @@ -0,0 +1,302 @@ +/* + Moravian Instruments INDI Driver + + Copyright (C) 2024 Moravian Instruments (info@gxccd.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "mi_sfw.h" + +#include "config.h" + +#include +#include +#include +#include + +#define MAX_DEVICES 4 /* Max device cameraCount */ +#define MAX_ERROR_LEN 64 /* Max length of error buffer */ + +// There is _one_ binary for USB and ETH driver, but each binary is renamed +// to its variant (indi_mi_sfw_usb and indi_mi_sfw_eth). The main function will +// fetch from std args the binary name and ISInit will create the appropriate +// driver afterwards. +extern char *__progname; + +static class Loader +{ + std::deque> wheels; + + public: + Loader(); + + public: + std::deque> initWheels; + +} loader; + +Loader::Loader() +{ + if (strstr(__progname, "indi_mi_sfw_eth")) + { + gxfw_enumerate_eth([](int id) + { + loader.initWheels.emplace_back(id, true); + }); + } + else + { + // "__progname" shoud be indi_mi_sfw_usb, however accept all names as USB + gxfw_enumerate_usb([](int id) + { + loader.initWheels.emplace_back(id, false); + }); + } + + for (const auto &args : initWheels) + { + wheels.push_back(std::unique_ptr(new MISFW(args.first, args.second))); + } + + initWheels.clear(); +} + +MISFW::MISFW(int _wheelId, bool eth) +{ + if (isSimulation()) + { + numFilters = 9; + strncpy(name, "MI SFW Simulator", MAXINDINAME); + } + else + { + wheelId = _wheelId; + isEth = eth; + + if (isEth) + wheelHandle = gxfw_initialize_eth(wheelId); + else + wheelHandle = gxfw_initialize_usb(wheelId); + if (!wheelHandle) + { + IDLog("Error connecting MI SFW!\n"); + return; + } + + char sp[MAXINDINAME]; + if (gxfw_get_string_parameter(wheelHandle, FW_GSP_DESCRIPTION, sp, sizeof(sp)) < 0) + { + strncpy(name, "MI SFW", MAXINDIDEVICE); + gxfw_get_last_error(wheelHandle, sp, sizeof(sp)); + IDLog("Error getting MI SFW info: %s.\n", sp); + } + else + { + strncpy(name, "MI ", MAXINDINAME); + strncat(name, sp, MAXINDINAME - 3); + IDLog("Detected SFW: %s.\n", name); + } + + gxfw_get_integer_parameter(wheelHandle, FW_GIP_FILTERS, &numFilters); + + gxfw_release(wheelHandle); + wheelHandle = nullptr; + } + + setDeviceName(name); + setVersion(INDI_MI_VERSION_MAJOR, INDI_MI_VERSION_MINOR); +} + +MISFW::~MISFW() +{ + if (wheelHandle) + gxfw_release(wheelHandle); +} + +const char *MISFW::getDefaultName() +{ + return name; +} + +bool MISFW::initProperties() +{ + INDI::FilterWheel::initProperties(); + + FilterSlotN[0].min = 1; + FilterSlotN[0].max = numFilters; + + // Reinit FW + IUFillSwitch(&ReinitS[0], "REINIT", "Reinit Filter Wheel", ISS_OFF); + IUFillSwitchVector(&ReinitSP, ReinitS, 1, getDeviceName(), "SFW_REINIT", "Commands", MAIN_CONTROL_TAB, IP_WO, ISR_ATMOST1, 0, IPS_IDLE); + + addAuxControls(); + + return true; +} + +bool MISFW::updateProperties() +{ + INDI::FilterWheel::updateProperties(); + + if (isConnected()) + { + defineProperty(&ReinitSP); + } + else + { + deleteProperty(ReinitSP.name); + } + + return true; +} + +bool MISFW::Connect() +{ + if (isSimulation()) + { + LOGF_INFO("Connected to %s", name); + return true; + } + + if (!wheelHandle) + { + if (isEth) + wheelHandle = gxfw_initialize_eth(wheelId); + else + wheelHandle = gxfw_initialize_usb(wheelId); + } + if (!wheelHandle) + { + LOGF_ERROR("Error connecting to %s.", name); + return false; + } + + LOGF_INFO("Connected to %s.", name); + return true; +} + +bool MISFW::Disconnect() +{ + LOGF_INFO("Disconnected from %s.", name); + if (!isSimulation()) { + gxfw_release(wheelHandle); + wheelHandle = nullptr; + } + return true; +} + +bool MISFW::SelectFilter(int position) +{ + if (!isSimulation() && gxfw_set_filter(wheelHandle, position - 1) < 0) + { + char errorStr[MAX_ERROR_LEN]; + gxfw_get_last_error(wheelHandle, errorStr, sizeof(errorStr)); + LOGF_ERROR("Setting filter failed: %s.", errorStr); + return false; + } + + CurrentFilter = position; + SelectFilterDone(position); + LOGF_DEBUG("Filter changed to %d", position); + return true; +} + +int MISFW::QueryFilter() +{ + return CurrentFilter; +} + +bool MISFW::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) +{ + if (strcmp(dev, getDeviceName()) == 0) + { + if (!strcmp(name, ReinitSP.name)) + { + IUUpdateSwitch(&ReinitSP, states, names, n); + IUResetSwitch(&ReinitSP); + + if (!isSimulation()) + { + LOG_INFO("Reinitializing filter wheel..."); + if (gxfw_reinit_filter_wheel(wheelHandle, &numFilters) < 0) + { + char errorStr[MAX_ERROR_LEN]; + gxfw_get_last_error(wheelHandle, errorStr, sizeof(errorStr)); + LOGF_ERROR("Wheel reinit failed: %s.", errorStr); + ReinitSP.s = IPS_ALERT; + } else { + LOG_INFO("Done."); + ReinitSP.s = IPS_OK; + FilterSlotN[0].value = 1; + IDSetNumber(&FilterSlotNP, nullptr); + updateFilterProperties(); + } + } + + IDSetSwitch(&ReinitSP, nullptr); + return true; + } + } + + return INDI::FilterWheel::ISNewSwitch(dev, name, states, names, n); +} + +bool MISFW::updateFilterProperties() +{ + if (FilterNameTP->ntp != numFilters) + { + FilterSlotN[0].max = numFilters; + IUUpdateMinMax(&FilterSlotNP); + + m_defaultDevice->deleteProperty("FILTER_NAME"); + + char filterName[MAXINDINAME]; + char filterLabel[MAXINDILABEL]; + + if (FilterNameT != nullptr) + { + for (int i = 0; i < FilterNameTP->ntp; i++) + free(FilterNameT[i].text); + delete [] FilterNameT; + } + + FilterNameT = new IText[numFilters]; + memset(FilterNameT, 0, sizeof(IText) * numFilters); + + for (int i = 0; i < numFilters; i++) + { + snprintf(filterName, MAXINDINAME, "FILTER_SLOT_NAME_%d", i + 1); + snprintf(filterLabel, MAXINDILABEL, "Filter#%d", i + 1); + IUFillText(&FilterNameT[i], filterName, filterLabel, filterLabel); + } + + IUFillTextVector(FilterNameTP, FilterNameT, numFilters, m_defaultDevice->getDeviceName(), "FILTER_NAME", "Filter", + FilterSlotNP.group, IP_RW, 0, IPS_IDLE); + m_defaultDevice->defineProperty(FilterNameTP); + + // Try to load config filter labels + for (int i = 0; i < numFilters; i++) + { + char oneFilter[MAXINDINAME] = {0}; + if (IUGetConfigText(m_defaultDevice->getDeviceName(), FilterNameTP->name, FilterNameT[i].name, oneFilter, MAXINDINAME) == 0) + IUSaveText(&FilterNameT[i], oneFilter); + } + + return true; + } + + return false; +} diff --git a/indi-mi/mi_sfw.h b/indi-mi/mi_sfw.h new file mode 100644 index 000000000..2675186c7 --- /dev/null +++ b/indi-mi/mi_sfw.h @@ -0,0 +1,60 @@ +/* + Moravian INDI Driver + + Copyright (C) 2024 Moravian Instruments (info@gxccd.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include + +#include + +class MISFW : public INDI::FilterWheel +{ + public: + MISFW(int wheelId, bool eth = false); + virtual ~MISFW(); + + virtual const char *getDefaultName() override; + + virtual bool initProperties() override; + virtual bool updateProperties() override; + + virtual bool Connect() override; + virtual bool Disconnect() override; + + virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; + + protected: + virtual bool SelectFilter(int position) override; + virtual int QueryFilter() override; + + ISwitch ReinitS[1]; + ISwitchVectorProperty ReinitSP; + + private: + char name[MAXINDIDEVICE]; + + int wheelId; + fwheel_t *wheelHandle; + bool isEth; + + int numFilters; + + bool updateFilterProperties(); +}; diff --git a/libmicam/CMakeLists.txt b/libmicam/CMakeLists.txt index 6660cf665..7e09fc7a4 100644 --- a/libmicam/CMakeLists.txt +++ b/libmicam/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.16) project (libmicam) -set (MICAM_VERSION "0.9.0") -set (MICAM_VERSION_MAC "0.8.0") +set (MICAM_VERSION "0.10.0") +set (MICAM_VERSION_MAC "0.9.0") set (MICAM_SOVERSION "0") list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/") diff --git a/libmicam/gxccd.h b/libmicam/gxccd.h index 8fec476a3..c939871c4 100644 --- a/libmicam/gxccd.h +++ b/libmicam/gxccd.h @@ -1,7 +1,7 @@ /* * The Moravian Instruments (MI) camera library. * - * Copyright (c) 2016-2023, Moravian Instruments + * Copyright (c) 2016-2024, Moravian Instruments * All rights reserved. * * Redistribution. Redistribution and use in binary form, without @@ -60,11 +60,14 @@ extern "C" { */ /* Typedef for prototype of enumeration function. */ -typedef void (*enum_callback_t)(int /*camera_id*/); +typedef void (*enum_callback_t)(int /*device_id*/); /* Typedef for prototype of anonymous camera structure. */ typedef struct camera camera_t; +/* Typedef for prototype of anonymous filter wheel structure. */ +typedef struct fwheel fwheel_t; + /* ============================================================================= * Structure of .ini configuration file. @@ -154,6 +157,8 @@ typedef struct camera camera_t; * "camera_id" is 1111) in .config directory located in current user's home * directory (e.g. /home/username/.config/gxccd.ini) or in directory with * application executable binary. + * In the case of the filter wheel, the filename is "gxfw.ini" or + * "gxfw.wheel_id.ini". * If none of these files is found, default values (mentioned above) are used. */ @@ -437,6 +442,16 @@ int gxccd_read_image(camera_t *camera, void *buf, size_t size); */ int gxccd_read_image_exposure(camera_t *camera, void *buf, size_t size); +/* + * Open camera shutter. + */ +int gxccd_open_shutter(camera_t *camera); + +/* + * Close camera shutter. + */ +int gxccd_close_shutter(camera_t *camera); + /* * Enumerates all read modes provided by the camera. * This enumeration does not use any callback, the caller passes index @@ -495,7 +510,7 @@ int gxccd_set_filter(camera_t *camera, int index); /* * Reinitializes camera filter wheel. - * If parameter "num_filter" is not NULL, it will contain the number of detected + * If parameter "num_filters" is not NULL, it will contain the number of detected * filters or 0 in case of error (or camera without filter wheel). */ int gxccd_reinit_filter_wheel(camera_t *camera, int *num_filters); @@ -567,6 +582,128 @@ int gxccd_get_gps_data(camera_t *camera, double *lat, double *lon, double *msl, */ void gxccd_get_last_error(camera_t *camera, char *buf, size_t size); +/*============================================================================== + * External Filter Wheels + *============================================================================*/ + +/* + * Enumerates all filter wheels currently connected to your computer (_usb) or + * the ethernet adapter (_eth). + * You have to provide callback function, which is called for each connected + * wheel and the filter wheel identifier (filter wheel ID) is passed as + * an argument to this callback function. + * If your application is designed to work with one wheel only or the filter + * wheel identifier is known, gxfw_enumerate_*() needs not to be called at all. + */ +/* USB variant */ +void gxfw_enumerate_usb(enum_callback_t callback); +/* Ethernet variant */ +void gxfw_enumerate_eth(enum_callback_t callback); + +/* + * Driver is designed to handle multiple filter wheels at once. It distinguishes + * individual wheels using pointer to individual instances. + * This function returns pointer to initialized structure or NULL in case of + * error. + * "wheel_id" is camera indentifier (e.g. obtained by gxfw_enumerate_*() + * function) and is required. If you have one filter wheel connected, you can + * pass -1 as "wheel_id". + */ +/* USB variant */ +fwheel_t *gxfw_initialize_usb(int wheel_id); +/* Ethernet variant */ +fwheel_t *gxfw_initialize_eth(int wheel_id); + +/* + * Disconnects from filter wheel and releases other resources. The memory + * pointed by "wheel" becomes invalid and you must not pass it to any of the + * following functions! + */ +void gxfw_release(fwheel_t *wheel); + +/*============================================================================== + * RULES FOR THE FOLLOWING FUNCTIONS: + * 1. Each function works with initialized fwheel_t structure. + * 2. Every parameter is required. + * 3. On success returns 0, on error the value -1 is returned and application + * can obtain error explanation by calling gxfw_get_last_error(). + *============================================================================*/ + +/* Standard gxfw_get_boolean_parameter() indexes */ +enum { + FW_GBP_CONNECTED = 0, /* true if wheel is connected */ + FW_GBP_INITIALIZED, /* true if wheel is initialized */ + FW_GBP_MICROMETER_FILTER_OFFSETS, /* true if filter focusing offsets are + expressed in micrometers */ + FW_GBP_CONFIGURED = 127, /* true if wheel is configured */ +}; + +/* Returns true or false in "value" depending on the "index". */ +int gxfw_get_boolean_parameter(fwheel_t *wheel, int index, bool *value); + +/* Standard gxfw_get_integer_parameter() indexes */ +enum { + FW_GIP_VERSION_1 = 0, /* Wheel firmware version (optional) */ + FW_GIP_VERSION_2, /* -//- */ + FW_GIP_VERSION_3, /* -//- */ + FW_GIP_VERSION_4, /* -//- */ + FW_GIP_WHEEL_ID, /* Identifier of the current filter wheel */ + FW_GIP_FILTERS, /* Number of filters offered by the filter wheel */ +}; + +/* Returns integer in "value" depending on the "index". */ +int gxfw_get_integer_parameter(fwheel_t *wheel, int index, int *value); + +/* Standard gxfw_get_string_parameter() indexes */ +enum { + FW_GSP_DESCRIPTION = 0, /* Filter wheel description */ + FW_GSP_MANUFACTURER, /* Manufacturer name */ + FW_GSP_SERIAL_NUMBER, /* Filter wheel serial number */ +}; + +/* + * Returns string in "buf" depending on the "index". + * The caller must specify the size of the buffer in "size". + */ +int gxfw_get_string_parameter(fwheel_t *wheel, int index, char *buf, + size_t size); + +/* + * Enumerates all filters provided by the filter wheel. + * This enumeration does not use any callback, by the caller passes index + * beginning with 0 and repeats the call with incremented index until the call + * returns -1. + * Returns filter name in "buf". The caller must specify the size of the buffer + * in parameter size. + * "color" parameter hints the RGB color (e.g. cyan color is 0x00ffff), which + * can be used to draw the filter name in the application. + * "offset" indicates the focuser shift when the particular filter is selected. + * Units of the "offset" can be micrometers or arbitrary focuser specific units + * (steps). If the units used are micrometers, driver returns true from + * gxfw_get_boolean_parameter() with FW_GBP_MICROMETER_FILTER_OFFSETS "index". + */ +int gxfw_enumerate_filters(fwheel_t *wheel, int index, char *buf, size_t size, + uint32_t *color, int *offset); + +/* + * Sets the required filter. + */ +int gxfw_set_filter(fwheel_t *wheel, int index); + +/* + * Reinitializes the filter wheel. + * If parameter "num_filters" is not NULL, it will contain the number of detected + * filters or 0 in case of error. + */ +int gxfw_reinit_filter_wheel(fwheel_t *wheel, int *num_filters); + +/* + * If any call fails (returns -1), this function returns failure description + * in parameter buf. + * The caller must specify the size of the buffer in parameter "size". + */ +void gxfw_get_last_error(fwheel_t *wheel, char *buf, size_t size); + /*============================================================================== * ADVANCED USB FUNCTIONS * diff --git a/libmicam/libgxccd32.bin b/libmicam/libgxccd32.bin index c8669ac30..71b221f41 100644 Binary files a/libmicam/libgxccd32.bin and b/libmicam/libgxccd32.bin differ diff --git a/libmicam/libgxccd64.bin b/libmicam/libgxccd64.bin index 2ab68475b..4001f6529 100644 Binary files a/libmicam/libgxccd64.bin and b/libmicam/libgxccd64.bin differ diff --git a/libmicam/libgxccdarmv7.bin b/libmicam/libgxccdarmv7.bin index 1127f8375..e2f1eaf07 100644 Binary files a/libmicam/libgxccdarmv7.bin and b/libmicam/libgxccdarmv7.bin differ diff --git a/libmicam/libgxccdarmv8.bin b/libmicam/libgxccdarmv8.bin index 82158ab09..cbf77739b 100644 Binary files a/libmicam/libgxccdarmv8.bin and b/libmicam/libgxccdarmv8.bin differ diff --git a/libmicam/libgxccdmac.bin b/libmicam/libgxccdmac.bin index ad78079ed..cbe731384 100644 Binary files a/libmicam/libgxccdmac.bin and b/libmicam/libgxccdmac.bin differ