From 2ba3c5bbf6f8c182c92bfaaf120a8b07937f53f7 Mon Sep 17 00:00:00 2001 From: James McKenzie Date: Sun, 27 Nov 2022 08:06:02 +0000 Subject: first --- .gitignore | 6 + cmake_modules/CMakeCommon.cmake | 128 + cmake_modules/CMakeParseArguments.cmake | 21 + cmake_modules/FindAHPXC.cmake | 50 + cmake_modules/FindAIOUSB.cmake | 61 + cmake_modules/FindALTAIRCAM.cmake | 49 + cmake_modules/FindALUT.cmake | 77 + cmake_modules/FindAPOGEE.cmake | 53 + cmake_modules/FindARAVIS.cmake | 43 + cmake_modules/FindASI.cmake | 74 + cmake_modules/FindATIK.cmake | 49 + cmake_modules/FindCFITSIO.cmake | 65 + cmake_modules/FindD2XX.cmake | 56 + cmake_modules/FindDC1394.cmake | 50 + cmake_modules/FindFFTW3.cmake | 52 + cmake_modules/FindFFmpeg.cmake | 213 ++ cmake_modules/FindFISHCAMP.cmake | 54 + cmake_modules/FindFLI.cmake | 53 + cmake_modules/FindFTDI.cmake | 54 + cmake_modules/FindFTDI1.cmake | 56 + cmake_modules/FindGLIB2.cmake | 218 ++ cmake_modules/FindGMock.cmake | 184 ++ cmake_modules/FindGPHOTO2.cmake | 66 + cmake_modules/FindGPSD.cmake | 19 + cmake_modules/FindGSL.cmake | 238 ++ cmake_modules/FindINDI.cmake | 320 +++ cmake_modules/FindINOVASDK.cmake | 50 + cmake_modules/FindIconv.cmake | 81 + cmake_modules/FindJPEG.cmake | 28 + cmake_modules/FindLIMESUITE.cmake | 52 + cmake_modules/FindLibRaw.cmake | 79 + cmake_modules/FindMALLINCAM.cmake | 49 + cmake_modules/FindMEADE.cmake | 47 + cmake_modules/FindMICAM.cmake | 49 + cmake_modules/FindMMAL.cmake | 45 + cmake_modules/FindMODBUS.cmake | 56 + cmake_modules/FindNNCAM.cmake | 49 + cmake_modules/FindNUTClient.cmake | 50 + cmake_modules/FindNova.cmake | 55 + cmake_modules/FindOMEGONPROCAM.cmake | 50 + cmake_modules/FindOggTheora.cmake | 47 + cmake_modules/FindOpenAL.cmake | 100 + cmake_modules/FindPENTAX.cmake | 86 + cmake_modules/FindPLAYERONE.cmake | 56 + cmake_modules/FindPackageHandleStandardArgs.cmake | 396 +++ cmake_modules/FindPackageMessage.cmake | 57 + cmake_modules/FindQHY.cmake | 50 + cmake_modules/FindQSI.cmake | 50 + cmake_modules/FindRT.cmake | 39 + cmake_modules/FindSBIG.cmake | 50 + cmake_modules/FindSTARSHOOTG.cmake | 49 + cmake_modules/FindSV305.cmake | 52 + cmake_modules/FindTIFFXX.cmake | 41 + cmake_modules/FindTOUPCAM.cmake | 50 + cmake_modules/FindUSB1.cmake | 83 + cmake_modules/FindVorbis.cmake | 32 + cmake_modules/InstallImported.cmake | 92 + cmake_modules/UnityBuild.cmake | 158 ++ indi-celestronaux/.gitignore | 1 + indi-celestronaux/CMakeLists.txt | 33 + indi-celestronaux/README.md | 102 + indi-celestronaux/auxproto.cpp | 467 ++++ indi-celestronaux/auxproto.h | 169 ++ indi-celestronaux/celestronaux.cpp | 2907 +++++++++++++++++++++ indi-celestronaux/celestronaux.h | 442 ++++ indi-celestronaux/config.h.cmake | 10 + indi-celestronaux/indi-celestronaux.spec | 79 + indi-celestronaux/indi_celestronaux.xml.cmake | 33 + indi-celestronaux/simulator/nse_simulator.py | 259 ++ indi-celestronaux/simulator/nse_telescope.py | 760 ++++++ 70 files changed, 9799 insertions(+) create mode 100644 .gitignore create mode 100644 cmake_modules/CMakeCommon.cmake create mode 100644 cmake_modules/CMakeParseArguments.cmake create mode 100644 cmake_modules/FindAHPXC.cmake create mode 100644 cmake_modules/FindAIOUSB.cmake create mode 100644 cmake_modules/FindALTAIRCAM.cmake create mode 100644 cmake_modules/FindALUT.cmake create mode 100644 cmake_modules/FindAPOGEE.cmake create mode 100644 cmake_modules/FindARAVIS.cmake create mode 100644 cmake_modules/FindASI.cmake create mode 100644 cmake_modules/FindATIK.cmake create mode 100644 cmake_modules/FindCFITSIO.cmake create mode 100644 cmake_modules/FindD2XX.cmake create mode 100644 cmake_modules/FindDC1394.cmake create mode 100644 cmake_modules/FindFFTW3.cmake create mode 100644 cmake_modules/FindFFmpeg.cmake create mode 100644 cmake_modules/FindFISHCAMP.cmake create mode 100644 cmake_modules/FindFLI.cmake create mode 100644 cmake_modules/FindFTDI.cmake create mode 100644 cmake_modules/FindFTDI1.cmake create mode 100644 cmake_modules/FindGLIB2.cmake create mode 100644 cmake_modules/FindGMock.cmake create mode 100644 cmake_modules/FindGPHOTO2.cmake create mode 100644 cmake_modules/FindGPSD.cmake create mode 100644 cmake_modules/FindGSL.cmake create mode 100644 cmake_modules/FindINDI.cmake create mode 100644 cmake_modules/FindINOVASDK.cmake create mode 100644 cmake_modules/FindIconv.cmake create mode 100644 cmake_modules/FindJPEG.cmake create mode 100644 cmake_modules/FindLIMESUITE.cmake create mode 100644 cmake_modules/FindLibRaw.cmake create mode 100644 cmake_modules/FindMALLINCAM.cmake create mode 100644 cmake_modules/FindMEADE.cmake create mode 100644 cmake_modules/FindMICAM.cmake create mode 100644 cmake_modules/FindMMAL.cmake create mode 100644 cmake_modules/FindMODBUS.cmake create mode 100644 cmake_modules/FindNNCAM.cmake create mode 100644 cmake_modules/FindNUTClient.cmake create mode 100644 cmake_modules/FindNova.cmake create mode 100644 cmake_modules/FindOMEGONPROCAM.cmake create mode 100644 cmake_modules/FindOggTheora.cmake create mode 100644 cmake_modules/FindOpenAL.cmake create mode 100644 cmake_modules/FindPENTAX.cmake create mode 100644 cmake_modules/FindPLAYERONE.cmake create mode 100644 cmake_modules/FindPackageHandleStandardArgs.cmake create mode 100644 cmake_modules/FindPackageMessage.cmake create mode 100644 cmake_modules/FindQHY.cmake create mode 100644 cmake_modules/FindQSI.cmake create mode 100644 cmake_modules/FindRT.cmake create mode 100644 cmake_modules/FindSBIG.cmake create mode 100644 cmake_modules/FindSTARSHOOTG.cmake create mode 100644 cmake_modules/FindSV305.cmake create mode 100644 cmake_modules/FindTIFFXX.cmake create mode 100644 cmake_modules/FindTOUPCAM.cmake create mode 100644 cmake_modules/FindUSB1.cmake create mode 100644 cmake_modules/FindVorbis.cmake create mode 100644 cmake_modules/InstallImported.cmake create mode 100644 cmake_modules/UnityBuild.cmake create mode 100644 indi-celestronaux/.gitignore create mode 100644 indi-celestronaux/CMakeLists.txt create mode 100644 indi-celestronaux/README.md create mode 100644 indi-celestronaux/auxproto.cpp create mode 100644 indi-celestronaux/auxproto.h create mode 100644 indi-celestronaux/celestronaux.cpp create mode 100644 indi-celestronaux/celestronaux.h create mode 100644 indi-celestronaux/config.h.cmake create mode 100644 indi-celestronaux/indi-celestronaux.spec create mode 100644 indi-celestronaux/indi_celestronaux.xml.cmake create mode 100644 indi-celestronaux/simulator/nse_simulator.py create mode 100644 indi-celestronaux/simulator/nse_telescope.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2206af6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +indi-celestronaux/CMakeCache.txt +indi-celestronaux/CMakeFiles/ +indi-celestronaux/Makefile +indi-celestronaux/cmake_install.cmake +indi-celestronaux/config.h +indi-celestronaux/indi_celestronaux.xml diff --git a/cmake_modules/CMakeCommon.cmake b/cmake_modules/CMakeCommon.cmake new file mode 100644 index 0000000..b7be23d --- /dev/null +++ b/cmake_modules/CMakeCommon.cmake @@ -0,0 +1,128 @@ + +include(CheckCCompilerFlag) + +#IF (NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") + #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") + #SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +#ENDIF () + +# C++14 Support +if (NOT ANDROID) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif(NOT ANDROID) + +# Position Independent Code +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# Ccache support +IF (ANDROID OR UNIX OR APPLE) + FIND_PROGRAM(CCACHE_FOUND ccache) + SET(CCACHE_SUPPORT OFF CACHE BOOL "Enable ccache support") + IF ((CCACHE_FOUND OR ANDROID) AND CCACHE_SUPPORT MATCHES ON) + SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + ENDIF () +ENDIF () + +# Add security (hardening flags) +IF (UNIX OR APPLE OR ANDROID) + # Older compilers are predefining _FORTIFY_SOURCE, so defining it causes a + # warning, which is then considered an error. Second issue is that for + # these compilers, _FORTIFY_SOURCE must be used while optimizing, else + # causes a warning, which also results in an error. And finally, CMake is + # not using optimization when testing for libraries, hence breaking the build. + CHECK_C_COMPILER_FLAG("-Werror -D_FORTIFY_SOURCE=2" COMPATIBLE_FORTIFY_SOURCE) + IF (${COMPATIBLE_FORTIFY_SOURCE}) + SET(SEC_COMP_FLAGS "-D_FORTIFY_SOURCE=2") + ENDIF () + SET(SEC_COMP_FLAGS "${SEC_COMP_FLAGS} -fstack-protector-all -fPIE") + # Make sure to add optimization flag. Some systems require this for _FORTIFY_SOURCE. + IF (NOT CMAKE_BUILD_TYPE MATCHES "MinSizeRel" AND NOT CMAKE_BUILD_TYPE MATCHES "Release" AND NOT CMAKE_BUILD_TYPE MATCHES "Debug") + SET(SEC_COMP_FLAGS "${SEC_COMP_FLAGS} -O1") + ENDIF () + IF (NOT ANDROID AND NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND NOT APPLE AND NOT CYGWIN) + SET(SEC_COMP_FLAGS "${SEC_COMP_FLAGS} -Wa,--noexecstack") + ENDIF () + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SEC_COMP_FLAGS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SEC_COMP_FLAGS}") + SET(SEC_LINK_FLAGS "") + IF (NOT APPLE AND NOT CYGWIN) + SET(SEC_LINK_FLAGS "${SEC_LINK_FLAGS} -Wl,-z,nodump -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now") + ENDIF () + IF (NOT ANDROID AND NOT APPLE) + SET(SEC_LINK_FLAGS "${SEC_LINK_FLAGS} -pie") + ENDIF () + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SEC_LINK_FLAGS}") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SEC_LINK_FLAGS}") +ENDIF () + +# Warning, debug and linker flags +SET(FIX_WARNINGS OFF CACHE BOOL "Enable strict compilation mode to turn compiler warnings to errors") +IF (UNIX OR APPLE) + SET(COMP_FLAGS "") + SET(LINKER_FLAGS "") + # Verbose warnings and turns all to errors + SET(COMP_FLAGS "${COMP_FLAGS} -Wall -Wextra") + IF (FIX_WARNINGS) + SET(COMP_FLAGS "${COMP_FLAGS} -Werror") + ENDIF () + # Omit problematic warnings + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + SET(COMP_FLAGS "${COMP_FLAGS} -Wno-unused-but-set-variable") + ENDIF () + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.9.9) + SET(COMP_FLAGS "${COMP_FLAGS} -Wno-format-truncation") + ENDIF () + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") + SET(COMP_FLAGS "${COMP_FLAGS} -Wno-nonnull -Wno-deprecated-declarations") + ENDIF () + + # Minimal debug info with Clang + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + SET(COMP_FLAGS "${COMP_FLAGS} -gline-tables-only") + ELSE () + SET(COMP_FLAGS "${COMP_FLAGS} -g") + ENDIF () + + # Note: The following flags are problematic on older systems with gcc 4.8 + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9.9)) + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") + SET(COMP_FLAGS "${COMP_FLAGS} -Wno-unused-command-line-argument") + ENDIF () + FIND_PROGRAM(LDGOLD_FOUND ld.gold) + SET(LDGOLD_SUPPORT OFF CACHE BOOL "Enable ld.gold support") + # Optional ld.gold is 2x faster than normal ld + IF (LDGOLD_FOUND AND LDGOLD_SUPPORT MATCHES ON AND NOT APPLE AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES arm) + SET(LINKER_FLAGS "${LINKER_FLAGS} -fuse-ld=gold") + # Use Identical Code Folding + SET(COMP_FLAGS "${COMP_FLAGS} -ffunction-sections") + SET(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--icf=safe") + # Compress the debug sections + # Note: Before valgrind 3.12.0, patch should be applied for valgrind (https://bugs.kde.org/show_bug.cgi?id=303877) + IF (NOT APPLE AND NOT ANDROID AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES arm AND NOT CMAKE_CXX_CLANG_TIDY) + SET(COMP_FLAGS "${COMP_FLAGS} -Wa,--compress-debug-sections") + SET(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--compress-debug-sections=zlib") + ENDIF () + ENDIF () + ENDIF () + + # Apply the flags + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMP_FLAGS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMP_FLAGS}") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}") +ENDIF () + +# Sanitizer support +SET(CLANG_SANITIZERS OFF CACHE BOOL "Clang's sanitizer support") +IF (CLANG_SANITIZERS AND + ((UNIX AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") OR (APPLE AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang"))) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") +ENDIF () + +# Unity Build support +include(UnityBuild) diff --git a/cmake_modules/CMakeParseArguments.cmake b/cmake_modules/CMakeParseArguments.cmake new file mode 100644 index 0000000..fc64ab9 --- /dev/null +++ b/cmake_modules/CMakeParseArguments.cmake @@ -0,0 +1,21 @@ +#.rst: +# CMakeParseArguments +# ------------------- +# +# This module once implemented the :command:`cmake_parse_arguments` command +# that is now implemented natively by CMake. It is now an empty placeholder +# for compatibility with projects that include it to get the command from +# CMake 3.4 and lower. + +#============================================================================= +# Copyright 2010 Alexander Neundorf +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) diff --git a/cmake_modules/FindAHPXC.cmake b/cmake_modules/FindAHPXC.cmake new file mode 100644 index 0000000..5da5692 --- /dev/null +++ b/cmake_modules/FindAHPXC.cmake @@ -0,0 +1,50 @@ +# - Try to find AHPXC Universal Library +# Once done this will define +# +# AHPXC_FOUND - system has AHPXC +# AHPXC_INCLUDE_DIR - the AHPXC include directory +# AHPXC_LIBRARIES - Link these to use AHPXC + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (AHPXC_INCLUDE_DIR AND AHPXC_LIBRARIES) + + # in cache already + set(AHPXC_FOUND TRUE) + message(STATUS "Found libahp_xc: ${AHPXC_LIBRARIES}") + +else (AHPXC_INCLUDE_DIR AND AHPXC_LIBRARIES) + + find_path(AHPXC_INCLUDE_DIR ahp_xc.h + PATH_SUFFIXES ahp + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(AHPXC_LIBRARIES NAMES ahp_xc + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(AHPXC_INCLUDE_DIR AND AHPXC_LIBRARIES) + set(AHPXC_FOUND TRUE) + else (AHPXC_INCLUDE_DIR AND AHPXC_LIBRARIES) + set(AHPXC_FOUND FALSE) + endif(AHPXC_INCLUDE_DIR AND AHPXC_LIBRARIES) + + + if (AHPXC_FOUND) + if (NOT AHPXC_FIND_QUIETLY) + message(STATUS "Found AHP XC: ${AHPXC_LIBRARIES}") + endif (NOT AHPXC_FIND_QUIETLY) + else (AHPXC_FOUND) + if (AHPXC_FIND_REQUIRED) + message(FATAL_ERROR "AHP XC not found. Please install libahp_xc http://www.indilib.org") + endif (AHPXC_FIND_REQUIRED) + endif (AHPXC_FOUND) + + mark_as_advanced(AHPXC_INCLUDE_DIR AHPXC_LIBRARIES) + +endif (AHPXC_INCLUDE_DIR AND AHPXC_LIBRARIES) diff --git a/cmake_modules/FindAIOUSB.cmake b/cmake_modules/FindAIOUSB.cmake new file mode 100644 index 0000000..4bc4469 --- /dev/null +++ b/cmake_modules/FindAIOUSB.cmake @@ -0,0 +1,61 @@ +# - Try to find libaiousb +# Once done this will define +# +# AIOUSB_FOUND - system has AIOUSB +# AIOUSB_INCLUDE_DIR - the AIOUSB include directory +# AIOUSB_LIBRARIES - Link these to use AIOUSB (C) +# AIOUSB_CPP_LIBRARIES - Link these to use AIOUSB (C++) + +# Copyright (c) 2006, Jasem Mutlaq +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES) + + # in cache already + set(AIOUSB_FOUND TRUE) + message(STATUS "Found libaiusb: ${AIOUSB_LIBRARIES}") + message(STATUS "Found libaiusbcpp: ${AIOUSB_CPP_LIBRARIES}") + +else (AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES) + + find_path(AIOUSB_INCLUDE_DIR aiousb.h + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(AIOUSB_LIBRARIES NAMES aiousb + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + find_library(AIOUSB_CPP_LIBRARIES NAMES aiousbcpp + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES) + set(AIOUSB_FOUND TRUE) + else (AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES) + set(AIOUSB_FOUND FALSE) + endif(AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES) + + if (AIOUSB_FOUND) + if (NOT AIOUSB_FIND_QUIETLY) + message(STATUS "Found libaiousb: ${AIOUSB_LIBRARIES}") + message(STATUS "Found libaiusbcpp: ${AIOUSB_CPP_LIBRARIES}") + endif (NOT AIOUSB_FIND_QUIETLY) + else (AIOUSB_FOUND) + if (AIOUSB_FIND_REQUIRED) + message(FATAL_ERROR "libaiousb not found. Please install libaiousb. https://www.accesio.com") + endif (AIOUSB_FIND_REQUIRED) + endif (AIOUSB_FOUND) + + mark_as_advanced(AIOUSB_INCLUDE_DIR AIOUSB_LIBRARIES AIOUSB_CPP_LIBRARIES) + +endif (AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES) + diff --git a/cmake_modules/FindALTAIRCAM.cmake b/cmake_modules/FindALTAIRCAM.cmake new file mode 100644 index 0000000..bffa78e --- /dev/null +++ b/cmake_modules/FindALTAIRCAM.cmake @@ -0,0 +1,49 @@ +# - Try to find Altair Camera Library +# Once done this will define +# +# ALTAIRCAM_FOUND - system has Altair +# ALTAIRCAM_INCLUDE_DIR - the Altair include directory +# ALTAIRCAM_LIBRARIES - Link these to use Altair + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (ALTAIRCAM_INCLUDE_DIR AND ALTAIRCAM_LIBRARIES) + + # in cache already + set(ALTAIRCAM_FOUND TRUE) + message(STATUS "Found libaltaircam: ${ALTAIRCAM_LIBRARIES}") + +else (ALTAIRCAM_INCLUDE_DIR AND ALTAIRCAM_LIBRARIES) + + find_path(ALTAIRCAM_INCLUDE_DIR altaircam.h + PATH_SUFFIXES libaltaircam + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(ALTAIRCAM_LIBRARIES NAMES altaircam + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(ALTAIRCAM_INCLUDE_DIR AND ALTAIRCAM_LIBRARIES) + set(ALTAIRCAM_FOUND TRUE) + else (ALTAIRCAM_INCLUDE_DIR AND ALTAIRCAM_LIBRARIES) + set(ALTAIRCAM_FOUND FALSE) + endif(ALTAIRCAM_INCLUDE_DIR AND ALTAIRCAM_LIBRARIES) + + if (ALTAIRCAM_FOUND) + if (NOT ALTAIRCAM_FIND_QUIETLY) + message(STATUS "Found Altaircam: ${ALTAIRCAM_LIBRARIES}") + endif (NOT ALTAIRCAM_FIND_QUIETLY) + else (ALTAIRCAM_FOUND) + if (ALTAIRCAM_FIND_REQUIRED) + message(FATAL_ERROR "Altaircam not found. Please install Altaircam Library http://www.indilib.org") + endif (ALTAIRCAM_FIND_REQUIRED) + endif (ALTAIRCAM_FOUND) + + mark_as_advanced(ALTAIRCAM_INCLUDE_DIR ALTAIRCAM_LIBRARIES) + +endif (ALTAIRCAM_INCLUDE_DIR AND ALTAIRCAM_LIBRARIES) diff --git a/cmake_modules/FindALUT.cmake b/cmake_modules/FindALUT.cmake new file mode 100644 index 0000000..44aa2b0 --- /dev/null +++ b/cmake_modules/FindALUT.cmake @@ -0,0 +1,77 @@ +# - Locate ALUT +# This module defines +# ALUT_LIBRARY +# ALUT_FOUND, if false, do not try to link to OpenAL +# ALUT_INCLUDE_DIR, where to find the headers +# +# $OPENALDIR is an environment variable that would +# correspond to the ./configure --prefix=$OPENALDIR +# used in building OpenAL. +# +# Created by Bryan Donlan, based on the FindOpenAL.cmake module by Eric Wang. + +FIND_PATH(ALUT_INCLUDE_DIR alut.h + $ENV{OPENALDIR}/include + ~/Library/Frameworks/OpenAL.framework/Headers + /Library/Frameworks/OpenAL.framework/Headers + /System/Library/Frameworks/OpenAL.framework/Headers # Tiger + /usr/local/include/AL + /usr/local/include/OpenAL + /usr/local/include + /usr/include/AL + /usr/include/OpenAL + /usr/include + /sw/include/AL # Fink + /sw/include/OpenAL + /sw/include + /opt/local/include/AL # DarwinPorts + /opt/local/include/OpenAL + /opt/local/include + /opt/csw/include/AL # Blastwave + /opt/csw/include/OpenAL + /opt/csw/include + /opt/include/AL + /opt/include/OpenAL + /opt/include + ) +# I'm not sure if I should do a special casing for Apple. It is +# unlikely that other Unix systems will find the framework path. +# But if they do ([Next|Open|GNU]Step?), +# do they want the -framework option also? +IF(${ALUT_INCLUDE_DIR} MATCHES ".framework") + STRING(REGEX REPLACE "(.*)/.*\\.framework/.*" "\\1" ALUT_FRAMEWORK_PATH_TMP ${ALUT_INCLUDE_DIR}) + IF("${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/Library/Frameworks" + OR "${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/System/Library/Frameworks" + ) + # String is in default search path, don't need to use -F + SET (ALUT_LIBRARY "-framework OpenAL" CACHE STRING "OpenAL framework for OSX") + ELSE("${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/Library/Frameworks" + OR "${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/System/Library/Frameworks" + ) + # String is not /Library/Frameworks, need to use -F + SET(ALUT_LIBRARY "-F${ALUT_FRAMEWORK_PATH_TMP} -framework OpenAL" CACHE STRING "OpenAL framework for OSX") + ENDIF("${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/Library/Frameworks" + OR "${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/System/Library/Frameworks" + ) + # Clear the temp variable so nobody can see it + SET(ALUT_FRAMEWORK_PATH_TMP "" CACHE INTERNAL "") + +ELSE(${ALUT_INCLUDE_DIR} MATCHES ".framework") + FIND_LIBRARY(ALUT_LIBRARY + NAMES alut + PATHS + $ENV{OPENALDIR}/lib + $ENV{OPENALDIR}/libs + /usr/local/lib + /usr/lib + /sw/lib + /opt/local/lib + /opt/csw/lib + /opt/lib + ) +ENDIF(${ALUT_INCLUDE_DIR} MATCHES ".framework") + +SET(ALUT_FOUND "NO") +IF(ALUT_LIBRARY) + SET(ALUT_FOUND "YES") +ENDIF(ALUT_LIBRARY) diff --git a/cmake_modules/FindAPOGEE.cmake b/cmake_modules/FindAPOGEE.cmake new file mode 100644 index 0000000..081fb7e --- /dev/null +++ b/cmake_modules/FindAPOGEE.cmake @@ -0,0 +1,53 @@ +# - Try to find Apogee Instruments Library +# Once done this will define +# +# APOGEE_FOUND - system has APOGEE +# APOGEE_INCLUDE_DIR - the APOGEE include directory +# APOGEE_LIBRARY - Link these to use APOGEE + +# Copyright (c) 2008, Jasem Mutlaq +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY) + + # in cache already + set(APOGEE_FOUND TRUE) + message(STATUS "Found libapogee: ${APOGEE_LIBRARY}") + +else (APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY) + + find_path(APOGEE_INCLUDE_DIR ApogeeCam.h + PATH_SUFFIXES libapogee + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + # Find Apogee Library + find_library(APOGEE_LIBRARY NAMES apogee + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY) + set(APOGEE_FOUND TRUE) + else (APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY) + set(APOGEE_FOUND FALSE) + endif(APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY) + + if (APOGEE_FOUND) + if (NOT APOGEE_FIND_QUIETLY) + message(STATUS "Found APOGEE: ${APOGEE_LIBRARY}") + endif (NOT APOGEE_FIND_QUIETLY) + else (APOGEE_FOUND) + if (APOGEE_FIND_REQUIRED) + message(FATAL_ERROR "libapogee not found. Cannot compile Apogee CCD Driver. Please install libapogee and try again. http://www.indilib.org") + endif (APOGEE_FIND_REQUIRED) + endif (APOGEE_FOUND) + + mark_as_advanced(APOGEE_INCLUDE_DIR APOGEE_LIBRARY) + +endif (APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY) diff --git a/cmake_modules/FindARAVIS.cmake b/cmake_modules/FindARAVIS.cmake new file mode 100644 index 0000000..5bd2d3c --- /dev/null +++ b/cmake_modules/FindARAVIS.cmake @@ -0,0 +1,43 @@ +# - Find the native sqlite3 includes and library +# +# This module defines +# ARV_INCLUDE_DIR, where to find libgphoto2 header files +# ARV_LIBRARIES, the libraries to link against to use libgphoto2 +# ARV_FOUND, If false, do not try to use libgphoto2. +# ARV_VERSION_STRING, e.g. 2.4.14 +# ARV_VERSION_MAJOR, e.g. 2 +# ARV_VERSION_MINOR, e.g. 4 +# ARV_VERSION_PATCH, e.g. 14 +# +# also defined, but not for general use are +# ARV_LIBRARY, where to find the sqlite3 library. + + +#============================================================================= +# Copyright 2010 henrik andersson +#============================================================================= + +SET(ARV_FIND_REQUIRED ${Arv_FIND_REQUIRED}) + +find_path(ARV_INCLUDE_DIR aravis-0.8/arv.h) +mark_as_advanced(ARV_INCLUDE_DIR) + +set(ARV_NAMES ${ARV_NAMES} aravis-0.8) +find_library(ARV_LIBRARY NAMES ${ARV_NAMES} ) +mark_as_advanced(ARV_LIBRARY) + +set(ARV_VERSION_MAJOR "0") +set(ARV_VERSION_MINOR "8") +set(ARV_VERSION_STRING "${ARV_VERSION_MAJOR}.${ARV_VERSION_MINOR}") + +# handle the QUIETLY and REQUIRED arguments and set ARV_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(ARV DEFAULT_MSG ARV_LIBRARY ARV_INCLUDE_DIR) + +IF(ARV_FOUND) + #SET(Arv_LIBRARIES ${ARV_LIBRARY}) + SET(Arv_LIBRARIES "aravis-0.8") + SET(Arv_INCLUDE_DIRS "${ARV_INCLUDE_DIR}/aravis-0.8") + MESSAGE (STATUS "Found aravis: ${Arv_LIBRARIES} ${Arv_INCLUDE_DIRS}") +ENDIF(ARV_FOUND) diff --git a/cmake_modules/FindASI.cmake b/cmake_modules/FindASI.cmake new file mode 100644 index 0000000..0df4577 --- /dev/null +++ b/cmake_modules/FindASI.cmake @@ -0,0 +1,74 @@ +# - Try to find ASI Library +# Once done this will define +# +# ASI_FOUND - system has ASI +# ASI_INCLUDE_DIR - the ASI include directory +# ASI_LIBRARIES - Link these to use ASI + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (ASI_INCLUDE_DIR AND ASI_LIBRARIES) + + # in cache already + set(ASI_FOUND TRUE) + message(STATUS "Found libasi: ${ASI_LIBRARIES}") + +else (ASI_INCLUDE_DIR AND ASI_LIBRARIES) + + find_path(ASI_INCLUDE_DIR ASICamera2.h + PATH_SUFFIXES libasi + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(ASICAM_LIBRARIES NAMES ASICamera2 + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + find_library(ASIEFW_LIBRARIES NAMES EFWFilter + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + find_library(ASIST4_LIBRARIES NAMES USB2ST4Conv + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + find_library(ASIEAF_LIBRARIES NAMES EAFFocuser + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + + if (ASICAM_LIBRARIES AND ASIEFW_LIBRARIES AND ASIST4_LIBRARIES AND ASIEAF_LIBRARIES) + set(ASI_LIBRARIES ${ASICAM_LIBRARIES} ${ASIEFW_LIBRARIES} ${ASIST4_LIBRARIES} ${ASIEAF_LIBRARIES}) + endif (ASICAM_LIBRARIES AND ASIEFW_LIBRARIES AND ASIST4_LIBRARIES AND ASIEAF_LIBRARIES) + + + if(ASI_INCLUDE_DIR AND ASI_LIBRARIES) + set(ASI_FOUND TRUE) + else (ASI_INCLUDE_DIR AND ASI_LIBRARIES) + set(ASI_FOUND FALSE) + endif(ASI_INCLUDE_DIR AND ASI_LIBRARIES) + + + if (ASI_FOUND) + if (NOT ASI_FIND_QUIETLY) + message(STATUS "Found ASI: ${ASI_LIBRARIES}") + endif (NOT ASI_FIND_QUIETLY) + else (ASI_FOUND) + if (ASI_FIND_REQUIRED) + message(FATAL_ERROR "ASI not found. Please install libasi http://www.indilib.org") + endif (ASI_FIND_REQUIRED) + endif (ASI_FOUND) + + mark_as_advanced(ASI_INCLUDE_DIR ASI_LIBRARIES) + +endif (ASI_INCLUDE_DIR AND ASI_LIBRARIES) diff --git a/cmake_modules/FindATIK.cmake b/cmake_modules/FindATIK.cmake new file mode 100644 index 0000000..d52f86e --- /dev/null +++ b/cmake_modules/FindATIK.cmake @@ -0,0 +1,49 @@ +# - Try to find Atik Camera Library +# Once done this will define +# +# ATIK_FOUND - system has ATIK +# ATIK_INCLUDE_DIR - the ATIK include directory +# ATIK_LIBRARIES - Link these to use ATIK + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (ATIK_INCLUDE_DIR AND ATIK_LIBRARIES) + + # in cache already + set(ATIK_FOUND TRUE) + message(STATUS "Found libatik: ${ATIK_LIBRARIES}") + +else (ATIK_INCLUDE_DIR AND ATIK_LIBRARIES) + + find_path(ATIK_INCLUDE_DIR AtikCameras.h + PATH_SUFFIXES libatik + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(ATIK_LIBRARIES NAMES atikcameras + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(ATIK_INCLUDE_DIR AND ATIK_LIBRARIES) + set(ATIK_FOUND TRUE) + else (ATIK_INCLUDE_DIR AND ATIK_LIBRARIES) + set(ATIK_FOUND FALSE) + endif(ATIK_INCLUDE_DIR AND ATIK_LIBRARIES) + + if (ATIK_FOUND) + if (NOT ATIK_FIND_QUIETLY) + message(STATUS "Found Atik Library: ${ATIK_LIBRARIES}") + endif (NOT ATIK_FIND_QUIETLY) + else (ATIK_FOUND) + if (ATIK_FIND_REQUIRED) + message(FATAL_ERROR "Atik Library not found. Please install Atik Library http://www.indilib.org") + endif (ATIK_FIND_REQUIRED) + endif (ATIK_FOUND) + + mark_as_advanced(ATIK_INCLUDE_DIR ATIK_LIBRARIES) + +endif (ATIK_INCLUDE_DIR AND ATIK_LIBRARIES) diff --git a/cmake_modules/FindCFITSIO.cmake b/cmake_modules/FindCFITSIO.cmake new file mode 100644 index 0000000..c994522 --- /dev/null +++ b/cmake_modules/FindCFITSIO.cmake @@ -0,0 +1,65 @@ +# - Try to find CFITSIO +# Once done this will define +# +# CFITSIO_FOUND - system has CFITSIO +# CFITSIO_INCLUDE_DIR - the CFITSIO include directory +# CFITSIO_LIBRARIES - Link these to use CFITSIO +# CFITSIO_VERSION_STRING - Human readable version number of cfitsio +# CFITSIO_VERSION_MAJOR - Major version number of cfitsio +# CFITSIO_VERSION_MINOR - Minor version number of cfitsio + +# Copyright (c) 2006, Jasem Mutlaq +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES) + + # in cache already + set(CFITSIO_FOUND TRUE) + message(STATUS "Found CFITSIO: ${CFITSIO_LIBRARIES}") + + +else (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES) + + # JM: Packages from different distributions have different suffixes + find_path(CFITSIO_INCLUDE_DIR fitsio.h + PATH_SUFFIXES libcfitsio3 libcfitsio0 cfitsio + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(CFITSIO_LIBRARIES NAMES cfitsio + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES) + set(CFITSIO_FOUND TRUE) + else (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES) + set(CFITSIO_FOUND FALSE) + endif(CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES) + + + if (CFITSIO_FOUND) + + # Find the version of the cfitsio header + file(STRINGS ${CFITSIO_INCLUDE_DIR}/fitsio.h CFITSIO_VERSION_STRING LIMIT_COUNT 1 REGEX "CFITSIO_VERSION") + STRING(REGEX REPLACE "[^0-9.]" "" CFITSIO_VERSION_STRING ${CFITSIO_VERSION_STRING}) + STRING(REGEX REPLACE "^([0-9]+)[.]([0-9]+)" "\\1" CFITSIO_VERSION_MAJOR ${CFITSIO_VERSION_STRING}) + STRING(REGEX REPLACE "^([0-9]+)[.]([0-9]+)" "\\2" CFITSIO_VERSION_MINOR ${CFITSIO_VERSION_STRING}) + + if (NOT CFITSIO_FIND_QUIETLY) + message(STATUS "Found CFITSIO ${CFITSIO_VERSION_STRING}: ${CFITSIO_LIBRARIES}") + endif (NOT CFITSIO_FIND_QUIETLY) + else (CFITSIO_FOUND) + if (CFITSIO_FIND_REQUIRED) + message(STATUS "CFITSIO not found.") + endif (CFITSIO_FIND_REQUIRED) + endif (CFITSIO_FOUND) + + mark_as_advanced(CFITSIO_INCLUDE_DIR CFITSIO_LIBRARIES) + +endif (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES) diff --git a/cmake_modules/FindD2XX.cmake b/cmake_modules/FindD2XX.cmake new file mode 100644 index 0000000..0dc9f80 --- /dev/null +++ b/cmake_modules/FindD2XX.cmake @@ -0,0 +1,56 @@ +# - Try to find D2XX +# Once done this will define +# +# D2XX_FOUND - system has FTDI +# D2XX_INCLUDE_DIR - the FTDI include directory +# D2XX_LIBRARIES - Link these to use FTDI +# +# N.B. You must include the file as following: +# +#include +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (D2XX_INCLUDE_DIR AND D2XX_LIBRARIES) + + # in cache already + set(D2XX_FOUND TRUE) + message(STATUS "Found libfd2xx: ${D2XX_LIBRARIES}") + +else (D2XX_INCLUDE_DIR AND D2XX_LIBRARIES) + + find_path(D2XX_INCLUDE_DIR ftd2xx.h + #PATH_SUFFIXES libD2XX + ${_obIncDir} + ${GNUWIN32_DIR}/include + /usr/local/include + ) + + find_library(D2XX_LIBRARIES NAMES ftd2xx + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + /usr/local/lib + ) + + if(D2XX_INCLUDE_DIR AND D2XX_LIBRARIES) + set(D2XX_FOUND TRUE) + else (D2XX_INCLUDE_DIR AND D2XX_LIBRARIES) + set(D2XX_FOUND FALSE) + endif(D2XX_INCLUDE_DIR AND D2XX_LIBRARIES) + + + if (D2XX_FOUND) + if (NOT D2XX_FIND_QUIETLY) + message(STATUS "Found D2XX: ${D2XX_LIBRARIES}") + endif (NOT D2XX_FIND_QUIETLY) + else (D2XX_FOUND) + if (D2XX_FIND_REQUIRED) + message(FATAL_ERROR "D2XX not found. Please install libd2xx") + endif (D2XX_FIND_REQUIRED) + endif (D2XX_FOUND) + + mark_as_advanced(D2XX_INCLUDE_DIR D2XX_LIBRARIES) + +endif (D2XX_INCLUDE_DIR AND D2XX_LIBRARIES) diff --git a/cmake_modules/FindDC1394.cmake b/cmake_modules/FindDC1394.cmake new file mode 100644 index 0000000..87d9609 --- /dev/null +++ b/cmake_modules/FindDC1394.cmake @@ -0,0 +1,50 @@ +# - Try to find dc1394 library (version 2) and include files +# Once done this will define +# +# DC1394_FOUND - system has DC1394 +# DC1394_INCLUDE_DIR - the DC1394 include directory +# DC1394_LIBRARIES - Link these to use DC1394 + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (DC1394_INCLUDE_DIR AND DC1394_LIBRARIES) + + # in cache already + set(DC1394_FOUND TRUE) + message(STATUS "Found libdc1394: ${DC1394_LIBRARIES}") + +else (DC1394_INCLUDE_DIR AND DC1394_LIBRARIES) + + find_path(DC1394_INCLUDE_DIR control.h + PATH_SUFFIXES dc1394 + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(DC1394_LIBRARIES NAMES dc1394 + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(DC1394_INCLUDE_DIR AND DC1394_LIBRARIES) + set(DC1394_FOUND TRUE) + else (DC1394_INCLUDE_DIR AND DC1394_LIBRARIES) + set(DC1394_FOUND FALSE) + endif(DC1394_INCLUDE_DIR AND DC1394_LIBRARIES) + + + if (DC1394_FOUND) + if (NOT DC1394_FIND_QUIETLY) + message(STATUS "Found DC1394: ${DC1394_LIBRARIES}") + endif (NOT DC1394_FIND_QUIETLY) + else (DC1394_FOUND) + if (DC1394_FIND_REQUIRED) + message(FATAL_ERROR "DC1394 not found. Please install libdc1394 development package.") + endif (DC1394_FIND_REQUIRED) + endif (DC1394_FOUND) + + mark_as_advanced(DC1394_INCLUDE_DIR DC1394_LIBRARIES) + +endif (DC1394_INCLUDE_DIR AND DC1394_LIBRARIES) diff --git a/cmake_modules/FindFFTW3.cmake b/cmake_modules/FindFFTW3.cmake new file mode 100644 index 0000000..289accc --- /dev/null +++ b/cmake_modules/FindFFTW3.cmake @@ -0,0 +1,52 @@ +# - Try to find FFTW3 +# Once done this will define +# +# FFTW3_FOUND - system has FFTW3 +# FFTW3_INCLUDE_DIR - the FFTW3 include directory +# FFTW3_LIBRARIES - Link these to use FFTW3 +# FFTW3_VERSION_STRING - Human readable version number of fftw3 +# FFTW3_VERSION_MAJOR - Major version number of fftw3 +# FFTW3_VERSION_MINOR - Minor version number of fftw3 + +# Copyright (c) 2017, Ilia Platone, +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (FFTW3_LIBRARIES) + + # in cache already + set(FFTW3_FOUND TRUE) + message(STATUS "Found FFTW3: ${FFTW3_LIBRARIES}") + + +else (FFTW3_LIBRARIES) + + find_library(FFTW3_LIBRARIES NAMES fftw3 + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + /usr/local/lib + ) + + if(FFTW3_LIBRARIES) + set(FFTW3_FOUND TRUE) + else (FFTW3_LIBRARIES) + set(FFTW3_FOUND FALSE) + endif(FFTW3_LIBRARIES) + + + if (FFTW3_FOUND) + if (NOT FFTW3_FIND_QUIETLY) + message(STATUS "Found FFTW3: ${FFTW3_LIBRARIES}") + endif (NOT FFTW3_FIND_QUIETLY) + else (FFTW3_FOUND) + if (FFTW3_FIND_REQUIRED) + message(FATAL_ERROR "FFTW3 not found. Please install libfftw3-dev") + endif (FFTW3_FIND_REQUIRED) + endif (FFTW3_FOUND) + + mark_as_advanced(FFTW3_LIBRARIES) + +endif (FFTW3_LIBRARIES) diff --git a/cmake_modules/FindFFmpeg.cmake b/cmake_modules/FindFFmpeg.cmake new file mode 100644 index 0000000..6d4b72f --- /dev/null +++ b/cmake_modules/FindFFmpeg.cmake @@ -0,0 +1,213 @@ +# - Try to find ffmpeg libraries (libavcodec, libavdevice, libavformat, libavutil, and libswscale) +# Once done this will define +# +# FFMPEG_FOUND - system has ffmpeg or libav +# FFMPEG_INCLUDE_DIR - the ffmpeg include directory +# FFMPEG_LIBRARIES - Link these to use ffmpeg +# FFMPEG_LIBAVCODEC +# FFMPEG_LIBAVDEVICE +# FFMPEG_LIBAVFORMAT +# FFMPEG_LIBAVUTIL +# FFMPEG_LIBSWSCALE +# +# Copyright (c) 2008 Andreas Schneider +# Modified for other libraries by Lasse Kärkkäinen +# Modified for Hedgewars by Stepik777 +# Modified for INDILIB by rlancaste +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# + +macro(_FFMPEG_PACKAGE_check_version) + if(EXISTS "${PACKAGE_INCLUDE_DIR}/version.h") + file(READ "${PACKAGE_INCLUDE_DIR}/version.h" _FFMPEG_PACKAGE_version_header) + + string(REGEX MATCH "#define ${PACKAGE_NAME}_VERSION_MAJOR[ \t]+([0-9]+)" _VERSION_MAJOR_match "${_FFMPEG_PACKAGE_version_header}") + set(FFMPEG_PACKAGE_VERSION_MAJOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "#define ${PACKAGE_NAME}_VERSION_MINOR[ \t]+([0-9]+)" _VERSION_MINOR_match "${_FFMPEG_PACKAGE_version_header}") + set(FFMPEG_PACKAGE_VERSION_MINOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "#define ${PACKAGE_NAME}_VERSION_MICRO[ \t]+([0-9]+)" _VERSION_MICRO_match "${_FFMPEG_PACKAGE_version_header}") + set(FFMPEG_PACKAGE_VERSION_MICRO "${CMAKE_MATCH_1}") + + set(FFMPEG_PACKAGE_VERSION ${FFMPEG_PACKAGE_VERSION_MAJOR}.${FFMPEG_PACKAGE_VERSION_MINOR}.${FFMPEG_PACKAGE_VERSION_MICRO}) + if(${FFMPEG_PACKAGE_VERSION} VERSION_LESS ${FFMPEG_PACKAGE_FIND_VERSION}) + set(FFMPEG_PACKAGE_VERSION_OK FALSE) + else(${FFMPEG_PACKAGE_VERSION} VERSION_LESS ${FFMPEG_PACKAGE_FIND_VERSION}) + set(FFMPEG_PACKAGE_VERSION_OK TRUE) + endif(${FFMPEG_PACKAGE_VERSION} VERSION_LESS ${FFMPEG_PACKAGE_FIND_VERSION}) + + if(NOT FFMPEG_PACKAGE_VERSION_OK) + message(STATUS "${PACKAGE_NAME} version ${FFMPEG_PACKAGE_VERSION} found in ${PACKAGE_INCLUDE_DIR}, " + "but at least version ${FFMPEG_PACKAGE_FIND_VERSION} is required") + else(NOT FFMPEG_PACKAGE_VERSION_OK) + mark_as_advanced(FFMPEG_PACKAGE_VERSION_MAJOR FFMPEG_PACKAGE_VERSION_MINOR FFMPEG_PACKAGE_VERSION_MICRO) + endif(NOT FFMPEG_PACKAGE_VERSION_OK) + else(EXISTS "${PACKAGE_INCLUDE_DIR}/version.h") + set(FFMPEG_PACKAGE_VERSION_OK FALSE) + message(STATUS "${PACKAGE_NAME}'s version.h file was not found in the include directory: ${PACKAGE_INCLUDE_DIR}, please install this program.") + endif(EXISTS "${PACKAGE_INCLUDE_DIR}/version.h") +endmacro(_FFMPEG_PACKAGE_check_version) + +# required ffmpeg library versions, Requiring at least FFMPEG 3.2.11, Hypatia +set(_avcodec_ver ">=57.64.101") +set(_avdevice_ver ">=57.1.100") +set(_avformat_ver ">=57.56.100") +set(_avutil_ver ">=55.34.100") +set(_swscale_ver ">=4.2.100") + +if (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) + + # in cache already + set(FFMPEG_FOUND TRUE) + +else (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) +# use pkg-config to get the directories and then use these values +# in the FIND_PATH() and FIND_LIBRARY() calls + +find_path(FFMPEG_INCLUDE_DIR +NAMES libavcodec/avcodec.h +PATHS ${FFMPEG_INCLUDE_DIRS} ${CMAKE_INSTALL_PREFIX}/include /usr/include /usr/local/include /opt/local/include /sw/include +PATH_SUFFIXES ffmpeg libav +) + +find_package(PkgConfig) +if (PKG_CONFIG_FOUND) + + pkg_check_modules(AVCODEC libavcodec${_avcodec_ver}) + pkg_check_modules(AVDEVICE libavdevice${_avdevice_ver}) + pkg_check_modules(AVFORMAT libavformat${_avformat_ver}) + pkg_check_modules(AVUTIL libavutil${_avutil_ver}) + pkg_check_modules(SWSCALE libswscale${_swscale_ver}) + +endif (PKG_CONFIG_FOUND) + +if (NOT PKG_CONFIG_FOUND OR + NOT FFMPEG_LIBAVCODEC OR + NOT FFMPEG_LIBAVDEVICE OR + NOT FFMPEG_LIBAVFORMAT OR + NOT FFMPEG_LIBAVUTIL OR + NOT FFMPEG_LIBSWSCALE) + +# LIBAVCODEC + set(PACKAGE_NAME "LIBAVCODEC") + set(PACKAGE_INCLUDE_DIR "${FFMPEG_INCLUDE_DIR}/libavcodec") + set(FFMPEG_PACKAGE_FIND_VERSION _avcodec_ver) + + _FFMPEG_PACKAGE_check_version() + + if(FFMPEG_PACKAGE_VERSION_OK) + set(AVCODEC_VERSION FFMPEG_PACKAGE_VERSION) + endif(FFMPEG_PACKAGE_VERSION_OK) + +# LIBAVDEVICE + set(PACKAGE_NAME "LIBAVDEVICE") + set(PACKAGE_INCLUDE_DIR "${FFMPEG_INCLUDE_DIR}/libavdevice") + set(FFMPEG_PACKAGE_FIND_VERSION _avdevice_ver) + + _FFMPEG_PACKAGE_check_version() + + if(FFMPEG_PACKAGE_VERSION_OK) + set(AVDEVICE_VERSION FFMPEG_PACKAGE_VERSION) + endif(FFMPEG_PACKAGE_VERSION_OK) + +# LIBAVFORMAT + set(PACKAGE_NAME "LIBAVFORMAT") + set(PACKAGE_INCLUDE_DIR "${FFMPEG_INCLUDE_DIR}/libavformat") + set(FFMPEG_PACKAGE_FIND_VERSION _avformat_ver) + + _FFMPEG_PACKAGE_check_version() + + if(FFMPEG_PACKAGE_VERSION_OK) + set(AVFORMAT_VERSION FFMPEG_PACKAGE_VERSION) + endif(FFMPEG_PACKAGE_VERSION_OK) + +# LIBAVUTIL + set(PACKAGE_NAME "LIBAVUTIL") + set(PACKAGE_INCLUDE_DIR "${FFMPEG_INCLUDE_DIR}/libavutil") + set(FFMPEG_PACKAGE_FIND_VERSION _avutil_ver) + + _FFMPEG_PACKAGE_check_version() + + if(FFMPEG_PACKAGE_VERSION_OK) + set(AVUTIL_VERSION FFMPEG_PACKAGE_VERSION) + endif(FFMPEG_PACKAGE_VERSION_OK) + +# LIBSWSCALE + set(PACKAGE_NAME "LIBSWSCALE") + set(PACKAGE_INCLUDE_DIR "${FFMPEG_INCLUDE_DIR}/libswscale") + set(FFMPEG_PACKAGE_FIND_VERSION _swscale_ver) + + _FFMPEG_PACKAGE_check_version() + + if(FFMPEG_PACKAGE_VERSION_OK) + set(SWSCALE_VERSION FFMPEG_PACKAGE_VERSION) + endif(FFMPEG_PACKAGE_VERSION_OK) + +endif () + +find_library(FFMPEG_LIBAVCODEC +NAMES avcodec libavcodec +PATHS ${AVCODEC_LIBRARY_DIRS} ${CMAKE_INSTALL_PREFIX}/lib /usr/lib /usr/local/lib /opt/local/lib /sw/lib +) + +find_library(FFMPEG_LIBAVDEVICE +NAMES avdevice libavdevice +PATHS ${AVDEVICE_LIBRARY_DIRS} ${CMAKE_INSTALL_PREFIX}/lib /usr/lib /usr/local/lib /opt/local/lib /sw/lib +) + +find_library(FFMPEG_LIBAVFORMAT +NAMES avformat libavformat +PATHS ${AVFORMAT_LIBRARY_DIRS} ${CMAKE_INSTALL_PREFIX}/lib /usr/lib /usr/local/lib /opt/local/lib /sw/lib +) + +find_library(FFMPEG_LIBAVUTIL +NAMES avutil libavutil +PATHS ${AVUTIL_LIBRARY_DIRS} ${CMAKE_INSTALL_PREFIX}/lib /usr/lib /usr/local/lib /opt/local/lib /sw/lib +) + +find_library(FFMPEG_LIBSWSCALE +NAMES swscale libswscale +PATHS ${SWSCALE_LIBRARY_DIRS} ${CMAKE_INSTALL_PREFIX}/lib /usr/lib /usr/local/lib /opt/local/lib /sw/lib +) + +#Only set FFMPEG to found if all the libraries are found in the right versions. +if(AVCODEC_VERSION AND + AVDEVICE_VERSION AND + AVFORMAT_VERSION AND + AVUTIL_VERSION AND + SWSCALE_VERSION AND + FFMPEG_LIBAVCODEC AND + FFMPEG_LIBAVDEVICE AND + FFMPEG_LIBAVFORMAT AND + FFMPEG_LIBAVUTIL AND + FFMPEG_LIBSWSCALE) +set(FFMPEG_FOUND TRUE) +endif() + +if (FFMPEG_FOUND) + + set(FFMPEG_LIBRARIES + ${FFMPEG_LIBAVCODEC} + ${FFMPEG_LIBAVDEVICE} + ${FFMPEG_LIBAVFORMAT} + ${FFMPEG_LIBAVUTIL} + ${FFMPEG_LIBSWSCALE} + ) + +endif (FFMPEG_FOUND) + +if (FFMPEG_FOUND) + if (NOT FFMPEG_FIND_QUIETLY) + message(STATUS "Found FFMPEG: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}") + endif (NOT FFMPEG_FIND_QUIETLY) + else (FFMPEG_FOUND) + message(STATUS "Could not find up to date FFMPEG for INDI Webcam. Up to date versions of these packages are required: libavcodec, libavdevice, libavformat, libavutil, and libswscale") + if (FFMPEG_FIND_REQUIRED) + message(FATAL_ERROR "Error: FFMPEG is required by this package!") + endif (FFMPEG_FIND_REQUIRED) +endif (FFMPEG_FOUND) + +endif (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) + + diff --git a/cmake_modules/FindFISHCAMP.cmake b/cmake_modules/FindFISHCAMP.cmake new file mode 100644 index 0000000..e023596 --- /dev/null +++ b/cmake_modules/FindFISHCAMP.cmake @@ -0,0 +1,54 @@ +# - Try to find FISHCAMP CCD +# Once done this will define +# +# FISHCAMP_FOUND - system has FISHCAMP +# FISHCAMP_LIBRARIES - Link these to use FISHCAMP +# FISHCAMP_INCLUDE_DIR - Fishcamp include directory + +# Copyright (c) 2006, Jasem Mutlaq +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR) + + # in cache already + set(FISHCAMP_FOUND TRUE) + message(STATUS "Found FISHCAMP: ${FISHCAMP_LIBRARIES}") + +else (FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR) + + find_library(FISHCAMP_LIBRARIES NAMES fishcamp + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + find_path(FISHCAMP_INCLUDE_DIR fishcamp.h + PATH_SUFFIXES libfishcamp + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + set(CMAKE_REQUIRED_LIBRARIES ${FISHCAMP_LIBRARIES}) + + if(FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR) + set(FISHCAMP_FOUND TRUE) + else (FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR) + set(FISHCAMP_FOUND FALSE) + endif(FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR) + + if (FISHCAMP_FOUND) + if (NOT FISHCAMP_FIND_QUIETLY) + message(STATUS "Found FISHCAMP: ${FISHCAMP_LIBRARIES}") + endif (NOT FISHCAMP_FIND_QUIETLY) + else (FISHCAMP_FOUND) + if (FISHCAMP_FIND_REQUIRED) + message(FATAL_ERROR "FISHCAMP not found. Please install FISHCAMP library. http://www.indilib.org") + endif (FISHCAMP_FIND_REQUIRED) + endif (FISHCAMP_FOUND) + + mark_as_advanced(FISHCAMP_LIBRARIES FISHCAMP_INCLUDE_DIR) + +endif (FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR) diff --git a/cmake_modules/FindFLI.cmake b/cmake_modules/FindFLI.cmake new file mode 100644 index 0000000..3881cf7 --- /dev/null +++ b/cmake_modules/FindFLI.cmake @@ -0,0 +1,53 @@ +# - Try to find Finger Lakes Instruments Library +# Once done this will define +# +# FLI_FOUND - system has FLI +# FLI_INCLUDE_DIR - the FLI include directory +# FLI_LIBRARIES - Link these to use FLI + +# Copyright (c) 2008, Jasem Mutlaq +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (FLI_INCLUDE_DIR AND FLI_LIBRARIES) + + # in cache already + set(FLI_FOUND TRUE) + message(STATUS "Found libfli: ${FLI_LIBRARIES}") + +else (FLI_INCLUDE_DIR AND FLI_LIBRARIES) + + find_path(FLI_INCLUDE_DIR libfli.h + PATH_SUFFIXES fli + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(FLI_LIBRARIES NAMES fli + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(FLI_INCLUDE_DIR AND FLI_LIBRARIES) + set(FLI_FOUND TRUE) + else (FLI_INCLUDE_DIR AND FLI_LIBRARIES) + set(FLI_FOUND FALSE) + endif(FLI_INCLUDE_DIR AND FLI_LIBRARIES) + + + if (FLI_FOUND) + if (NOT FLI_FIND_QUIETLY) + message(STATUS "Found FLI: ${FLI_LIBRARIES}") + endif (NOT FLI_FIND_QUIETLY) + else (FLI_FOUND) + if (FLI_FIND_REQUIRED) + message(FATAL_ERROR "FLI not found. Please install libfli-dev. http://www.indilib.org") + endif (FLI_FIND_REQUIRED) + endif (FLI_FOUND) + + mark_as_advanced(FLI_INCLUDE_DIR FLI_LIBRARIES) + +endif (FLI_INCLUDE_DIR AND FLI_LIBRARIES) diff --git a/cmake_modules/FindFTDI.cmake b/cmake_modules/FindFTDI.cmake new file mode 100644 index 0000000..35989ce --- /dev/null +++ b/cmake_modules/FindFTDI.cmake @@ -0,0 +1,54 @@ +# - Try to find FTDI +# This finds libFTDI that is compatible with old libusb v 0.1 +# For newer libusb > 1.0, use FindFTDI1.cmake +# Once done this will define +# +# FTDI_FOUND - system has FTDI +# FTDI_INCLUDE_DIR - the FTDI include directory +# FTDI_LIBRARIES - Link these to use FTDI + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (FTDI_INCLUDE_DIR AND FTDI_LIBRARIES) + + # in cache already + set(FTDI_FOUND TRUE) + message(STATUS "Found libftdi: ${FTDI_LIBRARIES}") + +else (FTDI_INCLUDE_DIR AND FTDI_LIBRARIES) + + find_path(FTDI_INCLUDE_DIR ftdi.h + PATH_SUFFIXES libftdi1 + ${_obIncDir} + ${GNUWIN32_DIR}/include + /usr/local/include + ) + + find_library(FTDI_LIBRARIES NAMES ftdi ftdi1 + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + /usr/local/lib + ) + + if(FTDI_INCLUDE_DIR AND FTDI_LIBRARIES) + set(FTDI_FOUND TRUE) + else (FTDI_INCLUDE_DIR AND FTDI_LIBRARIES) + set(FTDI_FOUND FALSE) + endif(FTDI_INCLUDE_DIR AND FTDI_LIBRARIES) + + + if (FTDI_FOUND) + if (NOT FTDI_FIND_QUIETLY) + message(STATUS "Found FTDI: ${FTDI_LIBRARIES}") + endif (NOT FTDI_FIND_QUIETLY) + else (FTDI_FOUND) + if (FTDI_FIND_REQUIRED) + message(FATAL_ERROR "FTDI not found. Please install libftdi-dev") + endif (FTDI_FIND_REQUIRED) + endif (FTDI_FOUND) + + mark_as_advanced(FTDI_INCLUDE_DIR FTDI_LIBRARIES) + +endif (FTDI_INCLUDE_DIR AND FTDI_LIBRARIES) diff --git a/cmake_modules/FindFTDI1.cmake b/cmake_modules/FindFTDI1.cmake new file mode 100644 index 0000000..2199159 --- /dev/null +++ b/cmake_modules/FindFTDI1.cmake @@ -0,0 +1,56 @@ +# - Try to find FTDI1 +# Once done this will define +# +# FTDI1_FOUND - system has FTDI +# FTDI1_INCLUDE_DIR - the FTDI include directory +# FTDI1_LIBRARIES - Link these to use FTDI +# +# N.B. You must include the file as following: +# +#include +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (FTDI1_INCLUDE_DIR AND FTDI1_LIBRARIES) + + # in cache already + set(FTDI1_FOUND TRUE) + message(STATUS "Found libftdi1: ${FTDI1_LIBRARIES}") + +else (FTDI1_INCLUDE_DIR AND FTDI1_LIBRARIES) + + find_path(FTDI1_INCLUDE_DIR ftdi.h + PATH_SUFFIXES libftdi1 + ${_obIncDir} + ${GNUWIN32_DIR}/include + /usr/local/include + ) + + find_library(FTDI1_LIBRARIES NAMES ftdi1 + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + /usr/local/lib + ) + + if(FTDI1_INCLUDE_DIR AND FTDI1_LIBRARIES) + set(FTDI1_FOUND TRUE) + else (FTDI1_INCLUDE_DIR AND FTDI1_LIBRARIES) + set(FTDI1_FOUND FALSE) + endif(FTDI1_INCLUDE_DIR AND FTDI1_LIBRARIES) + + + if (FTDI1_FOUND) + if (NOT FTDI1_FIND_QUIETLY) + message(STATUS "Found FTDI1: ${FTDI1_LIBRARIES}") + endif (NOT FTDI1_FIND_QUIETLY) + else (FTDI1_FOUND) + if (FTDI1_FIND_REQUIRED) + message(FATAL_ERROR "FTDI not found. Please install libftdi1-dev") + endif (FTDI1_FIND_REQUIRED) + endif (FTDI1_FOUND) + + mark_as_advanced(FTDI1_INCLUDE_DIR FTDI1_LIBRARIES) + +endif (FTDI1_INCLUDE_DIR AND FTDI1_LIBRARIES) diff --git a/cmake_modules/FindGLIB2.cmake b/cmake_modules/FindGLIB2.cmake new file mode 100644 index 0000000..976be36 --- /dev/null +++ b/cmake_modules/FindGLIB2.cmake @@ -0,0 +1,218 @@ +# - Try to find GLib2 +# Once done this will define +# +# GLIB2_FOUND - system has GLib2 +# GLIB2_INCLUDE_DIRS - the GLib2 include directory +# GLIB2_LIBRARIES - Link these to use GLib2 +# +# HAVE_GLIB_GREGEX_H glib has gregex.h header and +# supports g_regex_match_simple +# +# Copyright (c) 2006 Andreas Schneider +# Copyright (c) 2006 Philippe Bernery +# Copyright (c) 2007 Daniel Gollub +# Copyright (c) 2007 Alban Browaeys +# Copyright (c) 2008 Michael Bell +# Copyright (c) 2008 Bjoern Ricks +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + + +IF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS ) + # in cache already + SET(GLIB2_FOUND TRUE) +ELSE (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS ) + + INCLUDE(FindPkgConfig) + + ## Glib + IF ( GLIB2_FIND_REQUIRED ) + SET( _pkgconfig_REQUIRED "REQUIRED" ) + ELSE ( GLIB2_FIND_REQUIRED ) + SET( _pkgconfig_REQUIRED "" ) + ENDIF ( GLIB2_FIND_REQUIRED ) + + IF ( GLIB2_MIN_VERSION ) + PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0>=${GLIB2_MIN_VERSION} ) + ELSE ( GLIB2_MIN_VERSION ) + PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0 ) + ENDIF ( GLIB2_MIN_VERSION ) + IF ( PKG_CONFIG_FOUND ) + IF ( GLIB2_FOUND ) + SET ( GLIB2_CORE_FOUND TRUE ) + ELSE ( GLIB2_FOUND ) + SET ( GLIB2_CORE_FOUND FALSE ) + ENDIF ( GLIB2_FOUND ) + ENDIF ( PKG_CONFIG_FOUND ) + + # Look for glib2 include dir and libraries w/o pkgconfig + IF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND ) + FIND_PATH( + _glibconfig_include_DIR + NAMES + glibconfig.h + PATHS + /opt/gnome/lib64 + /opt/gnome/lib + /opt/lib/ + /opt/local/lib + /sw/lib/ + /usr/lib64 + /usr/lib + /usr/local/include + ${CMAKE_LIBRARY_PATH} + PATH_SUFFIXES + glib-2.0/include + ) + + FIND_PATH( + _glib2_include_DIR + NAMES + glib.h + PATHS + /opt/gnome/include + /opt/local/include + /sw/include + /usr/include + /usr/local/include + PATH_SUFFIXES + glib-2.0 + ) + + #MESSAGE(STATUS "Glib headers: ${_glib2_include_DIR}") + + FIND_LIBRARY( + _glib2_link_DIR + NAMES + glib-2.0 + glib + PATHS + /opt/gnome/lib + /opt/local/lib + /sw/lib + /usr/lib + /usr/local/lib + ) + IF ( _glib2_include_DIR AND _glib2_link_DIR ) + SET ( _glib2_FOUND TRUE ) + ENDIF ( _glib2_include_DIR AND _glib2_link_DIR ) + + + IF ( _glib2_FOUND ) + SET ( GLIB2_INCLUDE_DIRS ${_glib2_include_DIR} ${_glibconfig_include_DIR} ) + SET ( GLIB2_LIBRARIES ${_glib2_link_DIR} ) + SET ( GLIB2_CORE_FOUND TRUE ) + ELSE ( _glib2_FOUND ) + SET ( GLIB2_CORE_FOUND FALSE ) + ENDIF ( _glib2_FOUND ) + + # Handle dependencies + # libintl + IF ( NOT LIBINTL_FOUND ) + FIND_PATH(LIBINTL_INCLUDE_DIR + NAMES + libintl.h + PATHS + /opt/gnome/include + /opt/local/include + /sw/include + /usr/include + /usr/local/include + ) + + FIND_LIBRARY(LIBINTL_LIBRARY + NAMES + intl + PATHS + /opt/gnome/lib + /opt/local/lib + /sw/lib + /usr/local/lib + /usr/lib + ) + + IF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR) + SET (LIBINTL_FOUND TRUE) + ENDIF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR) + ENDIF ( NOT LIBINTL_FOUND ) + + # libiconv + IF ( NOT LIBICONV_FOUND ) + FIND_PATH(LIBICONV_INCLUDE_DIR + NAMES + iconv.h + PATHS + /opt/gnome/include + /opt/local/include + /opt/local/include + /sw/include + /sw/include + /usr/local/include + /usr/include + PATH_SUFFIXES + glib-2.0 + ) + + FIND_LIBRARY(LIBICONV_LIBRARY + NAMES + iconv + PATHS + /opt/gnome/lib + /opt/local/lib + /sw/lib + /usr/lib + /usr/local/lib + ) + + IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR) + SET (LIBICONV_FOUND TRUE) + ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR) + ENDIF ( NOT LIBICONV_FOUND ) + + IF (LIBINTL_FOUND) + SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBINTL_LIBRARY}) + SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBINTL_INCLUDE_DIR}) + ENDIF (LIBINTL_FOUND) + + IF (LIBICONV_FOUND) + SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY}) + SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR}) + ENDIF (LIBICONV_FOUND) + + ENDIF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND ) + ## + + IF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES) + SET (GLIB2_FOUND TRUE) + ENDIF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES) + + IF (GLIB2_FOUND) + IF (NOT GLIB2_FIND_QUIETLY) + MESSAGE (STATUS "Found GLib2: ${GLIB2_LIBRARIES} ${GLIB2_INCLUDE_DIRS}") + ENDIF (NOT GLIB2_FIND_QUIETLY) + ELSE (GLIB2_FOUND) + IF (GLIB2_FIND_REQUIRED) + MESSAGE (SEND_ERROR "Could not find GLib2") + ENDIF (GLIB2_FIND_REQUIRED) + ENDIF (GLIB2_FOUND) + + # show the GLIB2_INCLUDE_DIRS and GLIB2_LIBRARIES variables only in the advanced view + MARK_AS_ADVANCED(GLIB2_INCLUDE_DIRS GLIB2_LIBRARIES) + MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARY) + MARK_AS_ADVANCED(LIBINTL_INCLUDE_DIR LIBINTL_LIBRARY) + +ENDIF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS) + +IF ( GLIB2_FOUND ) + # Check if system has a newer version of glib + # which supports g_regex_match_simple + INCLUDE( CheckIncludeFiles ) + SET( CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS} ) + CHECK_INCLUDE_FILES ( glib/gregex.h HAVE_GLIB_GREGEX_H ) + # Reset CMAKE_REQUIRED_INCLUDES + SET( CMAKE_REQUIRED_INCLUDES "" ) +ENDIF( GLIB2_FOUND ) + diff --git a/cmake_modules/FindGMock.cmake b/cmake_modules/FindGMock.cmake new file mode 100644 index 0000000..3187d72 --- /dev/null +++ b/cmake_modules/FindGMock.cmake @@ -0,0 +1,184 @@ +#.rst: +# FindGMock +# --------- +# +# Locate the Google C++ Mocking Framework. +# +# Defines the following variables: +# +# :: +# +# GMOCK_FOUND - Found the Google Mocking framework +# GMOCK_INCLUDE_DIRS - Include directories +# +# +# +# Also defines the library variables below as normal variables. These +# contain debug/optimized keywords when a debugging library is found. +# +# :: +# +# GMOCK_LIBRARIES - libgmock +# +# +# +# Accepts the following variables as input: +# +# :: +# +# GMOCK_ROOT - (as a CMake or environment variable) +# The root directory of the gmock install prefix +# +# +# +# :: +# +# GMOCK_MSVC_SEARCH - If compiling with MSVC, this variable can be set to +# "MD" or "MT" to enable searching a GMock build tree +# (defaults: "MD") +# +# +# +# Example Usage: +# +# :: +# +# find_package(GMock REQUIRED) +# include_directories(${GMOCK_INCLUDE_DIRS}) +# +# +# +# :: +# +# add_executable(foo foo.cc) +# target_link_libraries(foo ${GMOCK_LIBRARIES}) +# +# +# +# :: +# +# add_test(AllMocksInFoo foo) +# +# +# +# +# +# If you would like each Google test to show up in CMock as a test you +# may use the following macro. NOTE: It will slow down your tests by +# running an executable for each test and test fixture. You will also +# have to rerun CMake after adding or removing tests or test fixtures. +# +# GMOCK_ADD_MOCKS(executable extra_args ARGN) +# +# :: +# +# executable = The path to the test executable +# extra_args = Pass a list of extra arguments to be passed to +# executable enclosed in quotes (or "" for none) +# ARGN = A list of source files to search for tests & test +# fixtures. +# +# +# +# :: +# +# Example: +# set(FooMockArgs --foo 1 --bar 2) +# add_executable(FooMock FooUnitMock.cc) +# GMOCK_ADD_MOCKS(FooMock "${FooMockArgs}" FooUnitMock.cc) + +#============================================================================= +# Copyright 2009 Kitware, Inc. +# Copyright 2009 Philip Lowman +# Copyright 2009 Daniel Blezek +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) +# +# Thanks to Daniel Blezek for the GMOCK_ADD_MOCKS code + +function(GMOCK_ADD_MOCKS executable extra_args) + if(NOT ARGN) + message(FATAL_ERROR "Missing ARGN: Read the documentation for GMOCK_ADD_MOCKS") + endif() + foreach(source ${ARGN}) + file(READ "${source}" contents) + string(REGEX MATCHALL "MOCK_?F?\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents}) + foreach(hit ${found_tests}) + string(REGEX REPLACE ".*\\( *([A-Za-z_0-9]+), *([A-Za-z_0-9]+) *\\).*" "\\1.\\2" test_name ${hit}) + add_test(${test_name} ${executable} --gmock_filter=${test_name} ${extra_args}) + endforeach() + endforeach() +endfunction() + +function(_gmock_append_debugs _endvar _library) + if(${_library} AND ${_library}_DEBUG) + set(_output optimized ${${_library}} debug ${${_library}_DEBUG}) + else() + set(_output ${${_library}}) + endif() + set(${_endvar} ${_output} PARENT_SCOPE) +endfunction() + +function(_gmock_find_library _name) + find_library(${_name} + NAMES ${ARGN} + HINTS + ENV GMOCK_ROOT + ${GMOCK_ROOT} + PATH_SUFFIXES ${_gmock_libpath_suffixes} + ) + mark_as_advanced(${_name}) +endfunction() + +# + +if(NOT DEFINED GMOCK_MSVC_SEARCH) + set(GMOCK_MSVC_SEARCH MD) +endif() + +set(_gmock_libpath_suffixes lib) +if(MSVC) + if(GMOCK_MSVC_SEARCH STREQUAL "MD") + list(APPEND _gmock_libpath_suffixes + msvc/gmock-md/Debug + msvc/gmock-md/Release) + elseif(GMOCK_MSVC_SEARCH STREQUAL "MT") + list(APPEND _gmock_libpath_suffixes + msvc/gmock/Debug + msvc/gmock/Release) + endif() +endif() + + +find_path(GMOCK_INCLUDE_DIR gmock/gmock.h + HINTS + $ENV{GMOCK_ROOT}/include + ${GMOCK_ROOT}/include +) +mark_as_advanced(GMOCK_INCLUDE_DIR) + +if(MSVC AND GMOCK_MSVC_SEARCH STREQUAL "MD") + # The provided /MD project files for Google Mock add -md suffixes to the + # library names. + _gmock_find_library(GMOCK_LIBRARY gmock-md gmock) + _gmock_find_library(GMOCK_LIBRARY_DEBUG gmock-mdd gmockd) +else() + _gmock_find_library(GMOCK_LIBRARY gmock) + _gmock_find_library(GMOCK_LIBRARY_DEBUG gmockd) +endif() + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMock DEFAULT_MSG GMOCK_LIBRARY GMOCK_INCLUDE_DIR) + +if(GMOCK_FOUND) + set(GMOCK_INCLUDE_DIRS ${GMOCK_INCLUDE_DIR}) + _gmock_append_debugs(GMOCK_LIBRARIES GMOCK_LIBRARY) +endif() + diff --git a/cmake_modules/FindGPHOTO2.cmake b/cmake_modules/FindGPHOTO2.cmake new file mode 100644 index 0000000..e5ffe29 --- /dev/null +++ b/cmake_modules/FindGPHOTO2.cmake @@ -0,0 +1,66 @@ +# - Find the native sqlite3 includes and library +# +# This module defines +# GPHOTO2_INCLUDE_DIR, where to find libgphoto2 header files +# GPHOTO2_LIBRARIES, the libraries to link against to use libgphoto2 +# GPHOTO2_FOUND, If false, do not try to use libgphoto2. +# GPHOTO2_VERSION_STRING, e.g. 2.4.14 +# GPHOTO2_VERSION_MAJOR, e.g. 2 +# GPHOTO2_VERSION_MINOR, e.g. 4 +# GPHOTO2_VERSION_PATCH, e.g. 14 +# +# also defined, but not for general use are +# GPHOTO2_LIBRARY, where to find the sqlite3 library. + + +#============================================================================= +# Copyright 2010 henrik andersson +#============================================================================= + +SET(GPHOTO2_FIND_REQUIRED ${Gphoto2_FIND_REQUIRED}) + +find_path(GPHOTO2_INCLUDE_DIR gphoto2/gphoto2.h) +mark_as_advanced(GPHOTO2_INCLUDE_DIR) + +set(GPHOTO2_NAMES ${GPHOTO2_NAMES} gphoto2 libgphoto2) +set(GPHOTO2_PORT_NAMES ${GPHOTO2_PORT_NAMES} gphoto2_port libgphoto2_port) +find_library(GPHOTO2_LIBRARY NAMES ${GPHOTO2_NAMES} ) +find_library(GPHOTO2_PORT_LIBRARY NAMES ${GPHOTO2_PORT_NAMES} ) +mark_as_advanced(GPHOTO2_LIBRARY) +mark_as_advanced(GPHOTO2_PORT_LIBRARY) + +# Detect libgphoto2 version +FIND_PROGRAM(GPHOTO2CONFIG_EXECUTABLE NAMES gphoto2-config) +IF(GPHOTO2CONFIG_EXECUTABLE) + EXEC_PROGRAM(${GPHOTO2CONFIG_EXECUTABLE} ARGS --version RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GPHOTO2_VERSION) + string(REGEX REPLACE "^.*libgphoto2 ([0-9]+).*$" "\\1" GPHOTO2_VERSION_MAJOR "${GPHOTO2_VERSION}") + string(REGEX REPLACE "^.*libgphoto2 [0-9]+\\.([0-9]+).*$" "\\1" GPHOTO2_VERSION_MINOR "${GPHOTO2_VERSION}") + string(REGEX REPLACE "^.*libgphoto2 [0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" GPHOTO2_VERSION_PATCH "${GPHOTO2_VERSION}") + + set(GPHOTO2_VERSION_STRING "${GPHOTO2_VERSION_MAJOR}.${GPHOTO2_VERSION_MINOR}.${GPHOTO2_VERSION_PATCH}") +ENDIF(GPHOTO2CONFIG_EXECUTABLE) + +# handle the QUIETLY and REQUIRED arguments and set GPHOTO2_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GPHOTO2 DEFAULT_MSG GPHOTO2_LIBRARY GPHOTO2_INCLUDE_DIR) + +IF(GPHOTO2_FOUND) + SET(Gphoto2_LIBRARIES ${GPHOTO2_LIBRARY} ${GPHOTO2_PORT_LIBRARY}) + SET(Gphoto2_INCLUDE_DIRS ${GPHOTO2_INCLUDE_DIR}) + + # libgphoto2 dynamically loads and unloads usb library + # without calling any cleanup functions (since they are absent from libusb-0.1). + # This leaves usb event handling threads running with invalid callback and return addresses, + # which causes a crash after any usb event is generated, at least in Mac OS X. + # libusb1 backend does correctly call exit function, but ATM it crashes anyway. + # Workaround is to link against libusb so that it wouldn't get unloaded. + IF(APPLE) + find_library(USB_LIBRARY NAMES usb-1.0 libusb-1.0) + mark_as_advanced(USB_LIBRARY) + IF(USB_LIBRARY) + SET(Gphoto2_LIBRARIES ${Gphoto2_LIBRARIES} ${USB_LIBRARY}) + ENDIF(USB_LIBRARY) + ENDIF(APPLE) + +ENDIF(GPHOTO2_FOUND) diff --git a/cmake_modules/FindGPSD.cmake b/cmake_modules/FindGPSD.cmake new file mode 100644 index 0000000..d5dc416 --- /dev/null +++ b/cmake_modules/FindGPSD.cmake @@ -0,0 +1,19 @@ +# - Find GPSD +# Find the native GPSD includes and library + +FIND_PATH(GPSD_INCLUDE_DIR libgpsmm.h gps.h) + +SET(GPSD_NAMES ${GPSD_NAMES} gps) +FIND_LIBRARY(GPSD_LIBRARY NAMES ${GPSD_NAMES} ) + +# handle the QUIETLY and REQUIRED arguments and set JPEG_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GPSD DEFAULT_MSG GPSD_LIBRARY GPSD_INCLUDE_DIR) + +IF(GPSD_FOUND) + SET(GPSD_LIBRARIES ${GPSD_LIBRARY}) + message(STATUS "Found libgps: ${GPSD_LIBRARIES}") +ENDIF(GPSD_FOUND) + + diff --git a/cmake_modules/FindGSL.cmake b/cmake_modules/FindGSL.cmake new file mode 100644 index 0000000..ef125c0 --- /dev/null +++ b/cmake_modules/FindGSL.cmake @@ -0,0 +1,238 @@ +#.rst: +# FindGSL +# -------- +# +# Find the native GSL includes and libraries. +# +# The GNU Scientific Library (GSL) is a numerical library for C and C++ +# programmers. It is free software under the GNU General Public +# License. +# +# Imported Targets +# ^^^^^^^^^^^^^^^^ +# +# If GSL is found, this module defines the following :prop_tgt:`IMPORTED` +# targets:: +# +# GSL::gsl - The main GSL library. +# GSL::gslcblas - The CBLAS support library used by GSL. +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# This module will set the following variables in your project:: +# +# GSL_FOUND - True if GSL found on the local system +# GSL_INCLUDE_DIRS - Location of GSL header files. +# GSL_LIBRARIES - The GSL libraries. +# GSL_VERSION - The version of the discovered GSL install. +# +# Hints +# ^^^^^ +# +# Set ``GSL_ROOT_DIR`` to a directory that contains a GSL installation. +# +# This script expects to find libraries at ``$GSL_ROOT_DIR/lib`` and the GSL +# headers at ``$GSL_ROOT_DIR/include/gsl``. The library directory may +# optionally provide Release and Debug folders. For Unix-like systems, this +# script will use ``$GSL_ROOT_DIR/bin/gsl-config`` (if found) to aid in the +# discovery GSL. +# +# Cache Variables +# ^^^^^^^^^^^^^^^ +# +# This module may set the following variables depending on platform and type +# of GSL installation discovered. These variables may optionally be set to +# help this module find the correct files:: +# +# GSL_CLBAS_LIBRARY - Location of the GSL CBLAS library. +# GSL_CBLAS_LIBRARY_DEBUG - Location of the debug GSL CBLAS library (if any). +# GSL_CONFIG_EXECUTABLE - Location of the ``gsl-config`` script (if any). +# GSL_LIBRARY - Location of the GSL library. +# GSL_LIBRARY_DEBUG - Location of the debug GSL library (if any). +# + +#============================================================================= +# Copyright 2014 Kelly Thompson +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# Include these modules to handle the QUIETLY and REQUIRED arguments. +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +#============================================================================= +# If the user has provided ``GSL_ROOT_DIR``, use it! Choose items found +# at this location over system locations. +if( EXISTS "$ENV{GSL_ROOT_DIR}" ) + file( TO_CMAKE_PATH "$ENV{GSL_ROOT_DIR}" GSL_ROOT_DIR ) + set( GSL_ROOT_DIR "${GSL_ROOT_DIR}" CACHE PATH "Prefix for GSL installation." ) +endif() +if( NOT EXISTS "${GSL_ROOT_DIR}" ) + set( GSL_USE_PKGCONFIG ON ) +endif() + +#============================================================================= +# As a first try, use the PkgConfig module. This will work on many +# *NIX systems. See :module:`findpkgconfig` +# This will return ``GSL_INCLUDEDIR`` and ``GSL_LIBDIR`` used below. +if( GSL_USE_PKGCONFIG ) + find_package(PkgConfig) + pkg_check_modules( GSL QUIET gsl ) + + if( EXISTS "${GSL_INCLUDEDIR}" ) + get_filename_component( GSL_ROOT_DIR "${GSL_INCLUDEDIR}" DIRECTORY CACHE) + endif() +endif() + +#============================================================================= +# Set GSL_INCLUDE_DIRS and GSL_LIBRARIES. If we skipped the PkgConfig step, try +# to find the libraries at $GSL_ROOT_DIR (if provided) or in standard system +# locations. These find_library and find_path calls will prefer custom +# locations over standard locations (HINTS). If the requested file is not found +# at the HINTS location, standard system locations will be still be searched +# (/usr/lib64 (Redhat), lib/i386-linux-gnu (Debian)). + +find_path( GSL_INCLUDE_DIR + NAMES gsl/gsl_sf.h + HINTS ${GSL_ROOT_DIR}/include ${GSL_INCLUDEDIR} +) +find_library( GSL_LIBRARY + NAMES gsl + HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} + PATH_SUFFIXES Release Debug +) +find_library( GSL_CBLAS_LIBRARY + NAMES gslcblas cblas + HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} + PATH_SUFFIXES Release Debug +) +# Do we also have debug versions? +find_library( GSL_LIBRARY_DEBUG + NAMES gsl + HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} + PATH_SUFFIXES Debug +) +find_library( GSL_CBLAS_LIBRARY_DEBUG + NAMES gslcblas cblas + HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} + PATH_SUFFIXES Debug +) +set( GSL_INCLUDE_DIRS ${GSL_INCLUDE_DIR} ) +set( GSL_LIBRARIES ${GSL_LIBRARY} ${GSL_CBLAS_LIBRARY} ) + +# If we didn't use PkgConfig, try to find the version via gsl-config or by +# reading gsl_version.h. +if( NOT GSL_VERSION ) + # 1. If gsl-config exists, query for the version. + find_program( GSL_CONFIG_EXECUTABLE + NAMES gsl-config + HINTS "${GSL_ROOT_DIR}/bin" + ) + if( EXISTS "${GSL_CONFIG_EXECUTABLE}" ) + execute_process( + COMMAND "${GSL_CONFIG_EXECUTABLE}" --version + OUTPUT_VARIABLE GSL_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE ) + endif() + + # 2. If gsl-config is not available, try looking in gsl/gsl_version.h + if( NOT GSL_VERSION AND EXISTS "${GSL_INCLUDE_DIRS}/gsl/gsl_version.h" ) + file( STRINGS "${GSL_INCLUDE_DIRS}/gsl/gsl_version.h" gsl_version_h_contents REGEX "define GSL_VERSION" ) + string( REGEX REPLACE ".*([0-9].[0-9][0-9]).*" "\\1" GSL_VERSION ${gsl_version_h_contents} ) + endif() + + # might also try scraping the directory name for a regex match "gsl-X.X" +endif() + +#============================================================================= +# handle the QUIETLY and REQUIRED arguments and set GSL_FOUND to TRUE if all +# listed variables are TRUE +find_package_handle_standard_args( GSL + FOUND_VAR + GSL_FOUND + REQUIRED_VARS + GSL_INCLUDE_DIR + GSL_LIBRARY + GSL_CBLAS_LIBRARY + VERSION_VAR + GSL_VERSION + ) + +mark_as_advanced( GSL_ROOT_DIR GSL_VERSION GSL_LIBRARY GSL_INCLUDE_DIR + GSL_CBLAS_LIBRARY GSL_LIBRARY_DEBUG GSL_CBLAS_LIBRARY_DEBUG + GSL_USE_PKGCONFIG GSL_CONFIG ) + +#============================================================================= +# Register imported libraries: +# 1. If we can find a Windows .dll file (or if we can find both Debug and +# Release libraries), we will set appropriate target properties for these. +# 2. However, for most systems, we will only register the import location and +# include directory. + +# Look for dlls, or Release and Debug libraries. +if(WIN32) + string( REPLACE ".lib" ".dll" GSL_LIBRARY_DLL "${GSL_LIBRARY}" ) + string( REPLACE ".lib" ".dll" GSL_CBLAS_LIBRARY_DLL "${GSL_CBLAS_LIBRARY}" ) + string( REPLACE ".lib" ".dll" GSL_LIBRARY_DEBUG_DLL "${GSL_LIBRARY_DEBUG}" ) + string( REPLACE ".lib" ".dll" GSL_CBLAS_LIBRARY_DEBUG_DLL "${GSL_CBLAS_LIBRARY_DEBUG}" ) +endif() + +if( GSL_FOUND AND NOT TARGET GSL::gsl ) + if( EXISTS "${GSL_LIBRARY_DLL}" AND EXISTS "${GSL_CBLAS_LIBRARY_DLL}") + + # Windows systems with dll libraries. + add_library( GSL::gsl SHARED IMPORTED ) + add_library( GSL::gslcblas SHARED IMPORTED ) + + # Windows with dlls, but only Release libraries. + set_target_properties( GSL::gslcblas PROPERTIES + IMPORTED_LOCATION_RELEASE "${GSL_CBLAS_LIBRARY_DLL}" + IMPORTED_IMPLIB "${GSL_CBLAS_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GSL_INCLUDE_DIRS}" + IMPORTED_CONFIGURATIONS Release + IMPORTED_LINK_INTERFACE_LANGUAGES "C" ) + set_target_properties( GSL::gsl PROPERTIES + IMPORTED_LOCATION_RELEASE "${GSL_LIBRARY_DLL}" + IMPORTED_IMPLIB "${GSL_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GSL_INCLUDE_DIRS}" + IMPORTED_CONFIGURATIONS Release + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + INTERFACE_LINK_LIBRARIES GSL::gslcblas ) + + # If we have both Debug and Release libraries + if( EXISTS "${GSL_LIBRARY_DEBUG_DLL}" AND EXISTS "${GSL_CBLAS_LIBRARY_DEBUG_DLL}") + set_property( TARGET GSL::gslcblas APPEND PROPERTY IMPORTED_CONFIGURATIONS Debug ) + set_target_properties( GSL::gslcblas PROPERTIES + IMPORTED_LOCATION_DEBUG "${GSL_CBLAS_LIBRARY_DEBUG_DLL}" + IMPORTED_IMPLIB_DEBUG "${GSL_CBLAS_LIBRARY_DEBUG}" ) + set_property( TARGET GSL::gsl APPEND PROPERTY IMPORTED_CONFIGURATIONS Debug ) + set_target_properties( GSL::gsl PROPERTIES + IMPORTED_LOCATION_DEBUG "${GSL_LIBRARY_DEBUG_DLL}" + IMPORTED_IMPLIB_DEBUG "${GSL_LIBRARY_DEBUG}" ) + endif() + + else() + + # For all other environments (ones without dll libraries), create + # the imported library targets. + add_library( GSL::gsl UNKNOWN IMPORTED ) + add_library( GSL::gslcblas UNKNOWN IMPORTED ) + set_target_properties( GSL::gslcblas PROPERTIES + IMPORTED_LOCATION "${GSL_CBLAS_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GSL_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" ) + set_target_properties( GSL::gsl PROPERTIES + IMPORTED_LOCATION "${GSL_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GSL_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + INTERFACE_LINK_LIBRARIES GSL::gslcblas ) + endif() +endif() diff --git a/cmake_modules/FindINDI.cmake b/cmake_modules/FindINDI.cmake new file mode 100644 index 0000000..b18991f --- /dev/null +++ b/cmake_modules/FindINDI.cmake @@ -0,0 +1,320 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This module can find INDI Library +# +# Requirements: +# - CMake >= 2.8.3 (for new version of find_package_handle_standard_args) +# +# The following variables will be defined for your use: +# - INDI_FOUND : were all of your specified components found (include dependencies)? +# - INDI_WEBSOCKET : was INDI compiled with websocket support? +# - INDI_INCLUDE_DIR : INDI include directory +# - INDI_DATA_DIR : INDI include directory +# - INDI_LIBRARIES : INDI libraries +# - INDI_DRIVER_LIBRARIES : Same as above maintained for backward compatibility +# - INDI_VERSION : complete version of INDI (x.y.z) +# - INDI_MAJOR_VERSION : major version of INDI +# - INDI_MINOR_VERSION : minor version of INDI +# - INDI_RELEASE_VERSION : release version of INDI +# - INDI__FOUND : were found? (FALSE for non specified component if it is not a dependency) +# +# For windows or non standard installation, define INDI_ROOT variable to point to the root installation of INDI. Two ways: +# - run cmake with -DINDI_ROOT= +# - define an environment variable with the same name before running cmake +# With cmake-gui, before pressing "Configure": +# 1) Press "Add Entry" button +# 2) Add a new entry defined as: +# - Name: INDI_ROOT +# - Type: choose PATH in the selection list +# - Press "..." button and select the root installation of INDI +# +# Example Usage: +# +# 1. Copy this file in the root of your project source directory +# 2. Then, tell CMake to search this non-standard module in your project directory by adding to your CMakeLists.txt: +# set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}) +# 3. Finally call find_package() once, here are some examples to pick from +# +# Require INDI 1.4 or later +# find_package(INDI 1.4 REQUIRED) +# +# if(INDI_FOUND) +# include_directories(${INDI_INCLUDE_DIR}) +# add_executable(myapp myapp.cpp) +# target_link_libraries(myapp ${INDI_LIBRARIES}) +# endif(INDI_FOUND) +# +# +# Using Components: +# +# You can search for specific components. Currently, the following components are available +# * driver: to build INDI hardware drivers. +# * align: to build drivers that use INDI Alignment Subsystem. +# * client: to build pure C++ INDI clients. +# * clientqt5: to build Qt5-based INDI clients. +# * lx200: To build LX200-based 3rd party drivers (you must link with driver above as well). +# +# By default, if you do not specify any components, driver and align components are searched. +# +# Example: +# +# To use INDI Qt5 Client library only in your application: +# +# find_package(INDI COMPONENTS clientqt5 REQUIRED) +# +# if(INDI_FOUND) +# include_directories(${INDI_INCLUDE_DIR}) +# add_executable(myapp myapp.cpp) +# target_link_libraries(myapp ${INDI_LIBRARIES}) +# endif(INDI_FOUND) +# +# To use INDI driver + lx200 component in your application: +# +# find_package(INDI COMPONENTS driver lx200 REQUIRED) +# +# if(INDI_FOUND) +# include_directories(${INDI_INCLUDE_DIR}) +# add_executable(myapp myapp.cpp) +# target_link_libraries(myapp ${INDI_LIBRARIES}) +# endif(INDI_FOUND) +# +# Notice we still use ${INDI_LIBRARIES} which now should contain both driver & lx200 libraries. +#============================================================================================== +# Copyright (c) 2011-2013, julp +# Copyright (c) 2017-2019 Jasem Mutlaq +# +# Distributed under the OSI-approved BSD License +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTINDILAR PURPOSE. +#============================================================================= + +find_package(PkgConfig QUIET) + +########## Private ########## +if(NOT DEFINED INDI_PUBLIC_VAR_NS) + set(INDI_PUBLIC_VAR_NS "INDI") # Prefix for all INDI relative public variables +endif(NOT DEFINED INDI_PUBLIC_VAR_NS) +if(NOT DEFINED INDI_PRIVATE_VAR_NS) + set(INDI_PRIVATE_VAR_NS "_${INDI_PUBLIC_VAR_NS}") # Prefix for all INDI relative internal variables +endif(NOT DEFINED INDI_PRIVATE_VAR_NS) +if(NOT DEFINED PC_INDI_PRIVATE_VAR_NS) + set(PC_INDI_PRIVATE_VAR_NS "_PC${INDI_PRIVATE_VAR_NS}") # Prefix for all pkg-config relative internal variables +endif(NOT DEFINED PC_INDI_PRIVATE_VAR_NS) + +function(indidebug _VARNAME) + if(${INDI_PUBLIC_VAR_NS}_DEBUG) + if(DEFINED ${INDI_PUBLIC_VAR_NS}_${_VARNAME}) + message("${INDI_PUBLIC_VAR_NS}_${_VARNAME} = ${${INDI_PUBLIC_VAR_NS}_${_VARNAME}}") + else(DEFINED ${INDI_PUBLIC_VAR_NS}_${_VARNAME}) + message("${INDI_PUBLIC_VAR_NS}_${_VARNAME} = ") + endif(DEFINED ${INDI_PUBLIC_VAR_NS}_${_VARNAME}) + endif(${INDI_PUBLIC_VAR_NS}_DEBUG) +endfunction(indidebug) + +set(${INDI_PRIVATE_VAR_NS}_ROOT "") +if(DEFINED ENV{INDI_ROOT}) + set(${INDI_PRIVATE_VAR_NS}_ROOT "$ENV{INDI_ROOT}") +endif(DEFINED ENV{INDI_ROOT}) +if (DEFINED INDI_ROOT) + set(${INDI_PRIVATE_VAR_NS}_ROOT "${INDI_ROOT}") +endif(DEFINED INDI_ROOT) + +set(${INDI_PRIVATE_VAR_NS}_BIN_SUFFIXES ) +set(${INDI_PRIVATE_VAR_NS}_LIB_SUFFIXES ) +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND ${INDI_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin64") + list(APPEND ${INDI_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib64") +endif(CMAKE_SIZEOF_VOID_P EQUAL 8) +list(APPEND ${INDI_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin") +list(APPEND ${INDI_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib") + +set(${INDI_PRIVATE_VAR_NS}_COMPONENTS ) +# ... +macro(INDI_declare_component _NAME) + list(APPEND ${INDI_PRIVATE_VAR_NS}_COMPONENTS ${_NAME}) + set("${INDI_PRIVATE_VAR_NS}_COMPONENTS_${_NAME}" ${ARGN}) +endmacro(INDI_declare_component) + +INDI_declare_component(driver indidriver) +INDI_declare_component(align indiAlignmentDriver) +INDI_declare_component(client indiclient) +INDI_declare_component(clientqt5 indiclientqt5) +INDI_declare_component(lx200 indilx200) + +########## Public ########## +set(${INDI_PUBLIC_VAR_NS}_FOUND TRUE) +set(${INDI_PUBLIC_VAR_NS}_LIBRARIES ) +set(${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR ) +foreach(${INDI_PRIVATE_VAR_NS}_COMPONENT ${${INDI_PRIVATE_VAR_NS}_COMPONENTS}) + string(TOUPPER "${${INDI_PRIVATE_VAR_NS}_COMPONENT}" ${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT) + set("${INDI_PUBLIC_VAR_NS}_${${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE) # may be done in the INDI_declare_component macro +endforeach(${INDI_PRIVATE_VAR_NS}_COMPONENT) + +# Check components +if(NOT ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS) # driver and posix client by default + set(${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS driver align) +else(NOT ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS) + #list(APPEND ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS uc) + list(REMOVE_DUPLICATES ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS) + foreach(${INDI_PRIVATE_VAR_NS}_COMPONENT ${${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS}) + if(NOT DEFINED ${INDI_PRIVATE_VAR_NS}_COMPONENTS_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) + message(FATAL_ERROR "Unknown INDI component: ${${INDI_PRIVATE_VAR_NS}_COMPONENT}") + endif(NOT DEFINED ${INDI_PRIVATE_VAR_NS}_COMPONENTS_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) + endforeach(${INDI_PRIVATE_VAR_NS}_COMPONENT) +endif(NOT ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS) + +# Includes +find_path( + ${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR + indidevapi.h + PATH_SUFFIXES libindi include/libindi + ${PC_INDI_INCLUDE_DIR} + ${_obIncDir} + ${GNUWIN32_DIR}/include + HINTS ${${INDI_PRIVATE_VAR_NS}_ROOT} + DOC "Include directory for INDI" +) + +find_path( + WEBSOCKET_HEADER + indiwsserver.h + PATH_SUFFIXES libindi + ${PC_INDI_INCLUDE_DIR} + ${_obIncDir} + ${GNUWIN32_DIR}/include +) + +if (WEBSOCKET_HEADER) + SET(INDI_WEBSOCKET TRUE) +else() + SET(INDI_WEBSOCKET FALSE) +endif() + +find_path(${INDI_PUBLIC_VAR_NS}_DATA_DIR + drivers.xml + PATH_SUFFIXES share/indi + DOC "Data directory for INDI" + ) + +if(${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR) + if(EXISTS "${${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR}/indiversion.h") # INDI >= 1.4 + file(READ "${${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR}/indiversion.h" ${INDI_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS) + else() + message(FATAL_ERROR "INDI version header not found") + endif() + + if(${INDI_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*INDI_VERSION ([0-9]+).([0-9]+).([0-9]+)") + set(${INDI_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}") + set(${INDI_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}") + set(${INDI_PUBLIC_VAR_NS}_RELEASE_VERSION "${CMAKE_MATCH_3}") + else() + message(FATAL_ERROR "failed to detect INDI version") + endif() + set(${INDI_PUBLIC_VAR_NS}_VERSION "${${INDI_PUBLIC_VAR_NS}_MAJOR_VERSION}.${${INDI_PUBLIC_VAR_NS}_MINOR_VERSION}.${${INDI_PUBLIC_VAR_NS}_RELEASE_VERSION}") + + # Check libraries + foreach(${INDI_PRIVATE_VAR_NS}_COMPONENT ${${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS}) + set(${INDI_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES ) + set(${INDI_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES ) + foreach(${INDI_PRIVATE_VAR_NS}_BASE_NAME ${${INDI_PRIVATE_VAR_NS}_COMPONENTS_${${INDI_PRIVATE_VAR_NS}_COMPONENT}}) + list(APPEND ${INDI_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${INDI_PRIVATE_VAR_NS}_BASE_NAME}") + list(APPEND ${INDI_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${INDI_PRIVATE_VAR_NS}_BASE_NAME}d") + list(APPEND ${INDI_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${INDI_PRIVATE_VAR_NS}_BASE_NAME}${INDI_MAJOR_VERSION}${INDI_MINOR_VERSION}") + list(APPEND ${INDI_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${INDI_PRIVATE_VAR_NS}_BASE_NAME}${INDI_MAJOR_VERSION}${INDI_MINOR_VERSION}d") + endforeach(${INDI_PRIVATE_VAR_NS}_BASE_NAME) + + find_library( + ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT} + NAMES ${${INDI_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES} + HINTS ${${INDI_PRIVATE_VAR_NS}_ROOT} + PATH_SUFFIXES ${_INDI_LIB_SUFFIXES} + DOC "Release libraries for INDI" + ) + find_library( + ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT} + NAMES ${${INDI_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES} + HINTS ${${INDI_PRIVATE_VAR_NS}_ROOT} + PATH_SUFFIXES ${_INDI_LIB_SUFFIXES} + DOC "Debug libraries for INDI" + ) + + string(TOUPPER "${${INDI_PRIVATE_VAR_NS}_COMPONENT}" ${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT) + if(NOT ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) # both not found + set("${INDI_PUBLIC_VAR_NS}_${${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE) + set("${INDI_PUBLIC_VAR_NS}_FOUND" FALSE) + else(NOT ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) # one or both found + set("${INDI_PUBLIC_VAR_NS}_${${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" TRUE) + if(NOT ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) # release not found => we are in debug + set(${INDI_PRIVATE_VAR_NS}_LIB_${${INDI_PRIVATE_VAR_NS}_COMPONENT} "${${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}}") + elseif(NOT ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) # debug not found => we are in release + set(${INDI_PRIVATE_VAR_NS}_LIB_${${INDI_PRIVATE_VAR_NS}_COMPONENT} "${${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT}}") + else() # both found + set( + ${INDI_PRIVATE_VAR_NS}_LIB_${${INDI_PRIVATE_VAR_NS}_COMPONENT} + optimized ${${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT}} + debug ${${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}} + ) + endif() + list(APPEND ${INDI_PUBLIC_VAR_NS}_LIBRARIES ${${INDI_PRIVATE_VAR_NS}_LIB_${${INDI_PRIVATE_VAR_NS}_COMPONENT}}) + endif(NOT ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) + endforeach(${INDI_PRIVATE_VAR_NS}_COMPONENT) + + # Check find_package arguments + include(FindPackageHandleStandardArgs) + if(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY) + find_package_handle_standard_args( + ${INDI_PUBLIC_VAR_NS} + REQUIRED_VARS ${INDI_PUBLIC_VAR_NS}_LIBRARIES ${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR + VERSION_VAR ${INDI_PUBLIC_VAR_NS}_VERSION + ) + else(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY) + find_package_handle_standard_args(${INDI_PUBLIC_VAR_NS} "INDI not found" ${INDI_PUBLIC_VAR_NS}_LIBRARIES ${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR) + endif(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY) +else(${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR) + set("${INDI_PUBLIC_VAR_NS}_FOUND" FALSE) + if(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY) + message(FATAL_ERROR "Could not find INDI include directory") + endif(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY) +endif(${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR) + +mark_as_advanced( + ${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR + ${INDI_PUBLIC_VAR_NS}_LIBRARIES + INDI_WEBSOCKET +) + +# IN (args) +indidebug("FIND_COMPONENTS") +indidebug("FIND_REQUIRED") +indidebug("FIND_QUIETLY") +indidebug("FIND_VERSION") +# OUT +# Found +indidebug("FOUND") +indidebug("SERVER_FOUND") +indidebug("DRIVERS_FOUND") +indidebug("CLIENT_FOUND") +indidebug("QT5CLIENT_FOUND") +indidebug("LX200_FOUND") + +# Linking +indidebug("INCLUDE_DIR") +indidebug("DATA_DIR") +indidebug("LIBRARIES") +# Backward compatibility +set(${INDI_PUBLIC_VAR_NS}_DRIVER_LIBRARIES ${${INDI_PUBLIC_VAR_NS}_LIBRARIES}) +indidebug("DRIVER_LIBRARIES") +# Version +indidebug("MAJOR_VERSION") +indidebug("MINOR_VERSION") +indidebug("RELEASE_VERSION") +indidebug("VERSION") diff --git a/cmake_modules/FindINOVASDK.cmake b/cmake_modules/FindINOVASDK.cmake new file mode 100644 index 0000000..75874e0 --- /dev/null +++ b/cmake_modules/FindINOVASDK.cmake @@ -0,0 +1,50 @@ +# - Try to find INOVASDK Universal Library +# Once done this will define +# +# INOVASDK_FOUND - system has INOVASDK +# INOVASDK_INCLUDE_DIR - the INOVASDK include directory +# INOVASDK_LIBRARIES - Link these to use INOVASDK + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (INOVASDK_INCLUDE_DIR AND INOVASDK_LIBRARIES) + + # in cache already + set(INOVASDK_FOUND TRUE) + message(STATUS "Found libinovasdk: ${INOVASDK_LIBRARIES}") + +else (INOVASDK_INCLUDE_DIR AND INOVASDK_LIBRARIES) + + find_path(INOVASDK_INCLUDE_DIR inovasdk.h + PATH_SUFFIXES inovasdk + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(INOVASDK_LIBRARIES NAMES inovasdk + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(INOVASDK_INCLUDE_DIR AND INOVASDK_LIBRARIES) + set(INOVASDK_FOUND TRUE) + else (INOVASDK_INCLUDE_DIR AND INOVASDK_LIBRARIES) + set(INOVASDK_FOUND FALSE) + endif(INOVASDK_INCLUDE_DIR AND INOVASDK_LIBRARIES) + + + if (INOVASDK_FOUND) + if (NOT INOVASDK_FIND_QUIETLY) + message(STATUS "Found INOVASDK: ${INOVASDK_LIBRARIES}") + endif (NOT INOVASDK_FIND_QUIETLY) + else (INOVASDK_FOUND) + if (INOVASDK_FIND_REQUIRED) + message(FATAL_ERROR "INOVASDK not found. Please install INOVASDK Library http://www.indilib.org") + endif (INOVASDK_FIND_REQUIRED) + endif (INOVASDK_FOUND) + + mark_as_advanced(INOVASDK_INCLUDE_DIR INOVASDK_LIBRARIES) + +endif (INOVASDK_INCLUDE_DIR AND INOVASDK_LIBRARIES) diff --git a/cmake_modules/FindIconv.cmake b/cmake_modules/FindIconv.cmake new file mode 100644 index 0000000..ea0e5f3 --- /dev/null +++ b/cmake_modules/FindIconv.cmake @@ -0,0 +1,81 @@ +# +# Copyright (C) 2010 Michael Bell +# 2015-2016 MariaDB Corporation AB +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the COPYING-CMAKE-SCRIPTS file. +# +# ICONV_EXTERNAL - Iconv is an external library (not libc) +# ICONV_FOUND - system has Iconv +# ICONV_INCLUDE_DIR - the Iconv include directory +# ICONV_LIBRARIES - Link these to use Iconv +# ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const +# ICONV_VERSION - Iconv version string + +if (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) + # Already in cache, be silent + set(ICONV_FIND_QUIETLY TRUE) +endif (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) + +find_path(ICONV_INCLUDE_DIR iconv.h) + +IF(CMAKE_SYSTEM_NAME MATCHES "SunOS") + # There is some libiconv.so in /usr/local that must + # be avoided, iconv routines are in libc +ELSEIF(APPLE) + find_library(ICONV_LIBRARIES NAMES iconv libiconv PATHS + /usr/lib/ + NO_CMAKE_SYSTEM_PATH) + SET(ICONV_EXTERNAL TRUE) +ELSE() + find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2) + IF(ICONV_LIBRARIES) + SET(ICONV_EXTERNAL TRUE) + ENDIF() +ENDIF() + +if (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) + set (ICONV_FOUND TRUE) +endif (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) + +set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) +IF(ICONV_EXTERNAL) + set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES}) +ENDIF() + +if (ICONV_FOUND) + include(CheckCSourceCompiles) + CHECK_C_SOURCE_COMPILES(" + #include + int main(){ + iconv_t conv = 0; + const char* in = 0; + size_t ilen = 0; + char* out = 0; + size_t olen = 0; + iconv(conv, &in, &ilen, &out, &olen); + return 0; + } +" ICONV_SECOND_ARGUMENT_IS_CONST ) +endif (ICONV_FOUND) + +set (CMAKE_REQUIRED_INCLUDES) +set (CMAKE_REQUIRED_LIBRARIES) + +if (ICONV_FOUND) + if (NOT ICONV_FIND_QUIETLY) + message (STATUS "Found Iconv: ${ICONV_LIBRARIES}") + endif (NOT ICONV_FIND_QUIETLY) +else (ICONV_FOUND) + if (Iconv_FIND_REQUIRED) + message (FATAL_ERROR "Could not find Iconv") + endif (Iconv_FIND_REQUIRED) +endif (ICONV_FOUND) + +MARK_AS_ADVANCED( + ICONV_INCLUDE_DIR + ICONV_LIBRARIES + ICONV_EXTERNAL + ICONV_SECOND_ARGUMENT_IS_CONST +) diff --git a/cmake_modules/FindJPEG.cmake b/cmake_modules/FindJPEG.cmake new file mode 100644 index 0000000..3692ee1 --- /dev/null +++ b/cmake_modules/FindJPEG.cmake @@ -0,0 +1,28 @@ +# - Find JPEG +# Find the native JPEG includes and library +# This module defines +# JPEG_INCLUDE_DIR, where to find jpeglib.h, etc. +# JPEG_LIBRARIES, the libraries needed to use JPEG. +# JPEG_FOUND, If false, do not try to use JPEG. +# also defined, but not for general use are +# JPEG_LIBRARY, where to find the JPEG library. + +FIND_PATH(JPEG_INCLUDE_DIR jpeglib.h) + +SET(JPEG_NAMES ${JPEG_NAMES} jpeg) +FIND_LIBRARY(JPEG_LIBRARY NAMES ${JPEG_NAMES} ) + +# handle the QUIETLY and REQUIRED arguments and set JPEG_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(JPEG DEFAULT_MSG JPEG_LIBRARY JPEG_INCLUDE_DIR) + +IF(JPEG_FOUND) + SET(JPEG_LIBRARIES ${JPEG_LIBRARY}) +ENDIF(JPEG_FOUND) + +# Deprecated declarations. +SET (NATIVE_JPEG_INCLUDE_PATH ${JPEG_INCLUDE_DIR} ) +GET_FILENAME_COMPONENT (NATIVE_JPEG_LIB_PATH ${JPEG_LIBRARY} PATH) + +MARK_AS_ADVANCED(JPEG_LIBRARY JPEG_INCLUDE_DIR ) diff --git a/cmake_modules/FindLIMESUITE.cmake b/cmake_modules/FindLIMESUITE.cmake new file mode 100644 index 0000000..3f1168b --- /dev/null +++ b/cmake_modules/FindLIMESUITE.cmake @@ -0,0 +1,52 @@ +# - Try to find LIMESUITE +# Once done this will define +# +# LIMESUITE_FOUND - system has LIMESUITE +# LIMESUITE_INCLUDE_DIR - the LIMESUITE include directory +# LIMESUITE_LIBRARIES - Link these to use LIMESUITE +# LIMESUITE_VERSION_STRING - Human readable version number of rtlsdr +# LIMESUITE_VERSION_MAJOR - Major version number of rtlsdr +# LIMESUITE_VERSION_MINOR - Minor version number of rtlsdr + +# Copyright (c) 2017, Ilia Platone, +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (LIMESUITE_LIBRARIES) + + # in cache already + set(LIMESUITE_FOUND TRUE) + message(STATUS "Found LIMESUITE: ${LIMESUITE_LIBRARIES}") + + +else (LIMESUITE_LIBRARIES) + + find_library(LIMESUITE_LIBRARIES NAMES LimeSuite + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + /usr/local/lib + ) + + if(LIMESUITE_LIBRARIES) + set(LIMESUITE_FOUND TRUE) + else (LIMESUITE_LIBRARIES) + set(LIMESUITE_FOUND FALSE) + endif(LIMESUITE_LIBRARIES) + + + if (LIMESUITE_FOUND) + if (NOT LIMESUITE_FIND_QUIETLY) + message(STATUS "Found LIMESUITE: ${LIMESUITE_LIBRARIES}") + endif (NOT LIMESUITE_FIND_QUIETLY) + else (LIMESUITE_FOUND) + if (LIMESUITE_FIND_REQUIRED) + message(FATAL_ERROR "LIMESUITE not found. Please install libLimeSuite-dev") + endif (LIMESUITE_FIND_REQUIRED) + endif (LIMESUITE_FOUND) + + mark_as_advanced(LIMESUITE_LIBRARIES) + +endif (LIMESUITE_LIBRARIES) diff --git a/cmake_modules/FindLibRaw.cmake b/cmake_modules/FindLibRaw.cmake new file mode 100644 index 0000000..e2dbe09 --- /dev/null +++ b/cmake_modules/FindLibRaw.cmake @@ -0,0 +1,79 @@ +# - Find LibRaw +# Find the LibRaw library +# This module defines +# LibRaw_VERSION_STRING, the version string of LibRaw +# LibRaw_INCLUDE_DIR, where to find libraw.h +# LibRaw_LIBRARIES, the libraries needed to use LibRaw (non-thread-safe) +# LibRaw_r_LIBRARIES, the libraries needed to use LibRaw (thread-safe) +# LibRaw_DEFINITIONS, the definitions needed to use LibRaw (non-thread-safe) +# LibRaw_r_DEFINITIONS, the definitions needed to use LibRaw (thread-safe) +# +# Copyright (c) 2013, Pino Toscano +# Copyright (c) 2013, Gilles Caulier +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +FIND_PACKAGE(PkgConfig) + +IF(PKG_CONFIG_FOUND) + PKG_CHECK_MODULES(PC_LIBRAW libraw) + SET(LibRaw_DEFINITIONS ${PC_LIBRAW_CFLAGS_OTHER}) + + PKG_CHECK_MODULES(PC_LIBRAW_R libraw_r) + SET(LibRaw_r_DEFINITIONS ${PC_LIBRAW_R_CFLAGS_OTHER}) +ENDIF() + +FIND_PATH(LibRaw_INCLUDE_DIR libraw.h + HINTS + ${PC_LIBRAW_INCLUDEDIR} + ${PC_LibRaw_INCLUDE_DIRS} + PATH_SUFFIXES libraw + ) + +FIND_LIBRARY(LibRaw_LIBRARIES NAMES raw + HINTS + ${PC_LIBRAW_LIBDIR} + ${PC_LIBRAW_LIBRARY_DIRS} + ) + +FIND_LIBRARY(LibRaw_r_LIBRARIES NAMES raw_r + HINTS + ${PC_LIBRAW_R_LIBDIR} + ${PC_LIBRAW_R_LIBRARY_DIRS} + ) + +IF(LibRaw_INCLUDE_DIR) + FILE(READ ${LibRaw_INCLUDE_DIR}/libraw_version.h _libraw_version_content) + + STRING(REGEX MATCH "#define LIBRAW_MAJOR_VERSION[ \t]*([0-9]*)\n" _version_major_match ${_libraw_version_content}) + SET(_libraw_version_major "${CMAKE_MATCH_1}") + + STRING(REGEX MATCH "#define LIBRAW_MINOR_VERSION[ \t]*([0-9]*)\n" _version_minor_match ${_libraw_version_content}) + SET(_libraw_version_minor "${CMAKE_MATCH_1}") + + STRING(REGEX MATCH "#define LIBRAW_PATCH_VERSION[ \t]*([0-9]*)\n" _version_patch_match ${_libraw_version_content}) + SET(_libraw_version_patch "${CMAKE_MATCH_1}") + + IF(_version_major_match AND _version_minor_match AND _version_patch_match) + SET(LibRaw_VERSION_STRING "${_libraw_version_major}.${_libraw_version_minor}.${_libraw_version_patch}") + ELSE() + IF(NOT LibRaw_FIND_QUIETLY) + MESSAGE(STATUS "Failed to get version information from ${LibRaw_INCLUDE_DIR}/libraw_version.h") + ENDIF() + ENDIF() +ENDIF() + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibRaw + REQUIRED_VARS LibRaw_LIBRARIES LibRaw_INCLUDE_DIR + VERSION_VAR LibRaw_VERSION_STRING + ) + +MARK_AS_ADVANCED(LibRaw_VERSION_STRING + LibRaw_INCLUDE_DIR + LibRaw_LIBRARIES + LibRaw_r_LIBRARIES + LibRaw_DEFINITIONS + LibRaw_r_DEFINITIONS + ) diff --git a/cmake_modules/FindMALLINCAM.cmake b/cmake_modules/FindMALLINCAM.cmake new file mode 100644 index 0000000..ce296b0 --- /dev/null +++ b/cmake_modules/FindMALLINCAM.cmake @@ -0,0 +1,49 @@ +# - Try to find MALLINCAM Camera Library +# Once done this will define +# +# MALLINCAM_FOUND - system has Levenhuk +# MALLINCAM_INCLUDE_DIR - the Levenhuk include directory +# MALLINCAM_LIBRARIES - Link these to use Levenhuk + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (MALLINCAM_INCLUDE_DIR AND MALLINCAM_LIBRARIES) + + # in cache already + set(MALLINCAM_FOUND TRUE) + message(STATUS "Found libnncam: ${MALLINCAM_LIBRARIES}") + +else (MALLINCAM_INCLUDE_DIR AND MALLINCAM_LIBRARIES) + + find_path(MALLINCAM_INCLUDE_DIR mallincam.h + PATH_SUFFIXES libmallincam + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(MALLINCAM_LIBRARIES NAMES mallincam + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(MALLINCAM_INCLUDE_DIR AND MALLINCAM_LIBRARIES) + set(MALLINCAM_FOUND TRUE) + else (MALLINCAM_INCLUDE_DIR AND MALLINCAM_LIBRARIES) + set(MALLINCAM_FOUND FALSE) + endif(MALLINCAM_INCLUDE_DIR AND MALLINCAM_LIBRARIES) + + if (MALLINCAM_FOUND) + if (NOT MALLINCAM_FIND_QUIETLY) + message(STATUS "Found MALLINCAM: ${MALLINCAM_LIBRARIES}") + endif (NOT MALLINCAM_FIND_QUIETLY) + else (MALLINCAM_FOUND) + if (MALLINCAM_FIND_REQUIRED) + message(FATAL_ERROR "MALLINCAM not found. Please install MALLINCAM Library http://www.indilib.org") + endif (MALLINCAM_FIND_REQUIRED) + endif (MALLINCAM_FOUND) + + mark_as_advanced(MALLINCAM_INCLUDE_DIR MALLINCAM_LIBRARIES) + +endif (MALLINCAM_INCLUDE_DIR AND MALLINCAM_LIBRARIES) diff --git a/cmake_modules/FindMEADE.cmake b/cmake_modules/FindMEADE.cmake new file mode 100644 index 0000000..59427aa --- /dev/null +++ b/cmake_modules/FindMEADE.cmake @@ -0,0 +1,47 @@ +# - Try to find Meade DSI Library. +# Once done this will define +# +# MEADEDSI_FOUND - system has Meade DSI +# MEADEDSI_LIBRARIES - Link these to use Meade DSI + +# Copyright (c) 2006, Jasem Mutlaq +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (MEADEDSI_LIBRARIES) + + # in cache already + set(MEADEDSI_FOUND TRUE) + message(STATUS "Found MEADEDSI: ${MEADEDSI_LIBRARIES}") + +else (MEADEDSI_LIBRARIES) + + find_library(MEADEDSI_LIBRARIES NAMES dsi + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + set(CMAKE_REQUIRED_LIBRARIES ${MEADEDSI_LIBRARIES}) + + if(MEADEDSI_LIBRARIES) + set(MEADEDSI_FOUND TRUE) + else (MEADEDSI_LIBRARIES) + set(MEADEDSI_FOUND FALSE) + endif(MEADEDSI_LIBRARIES) + + if (MEADEDSI_FOUND) + if (NOT MEADEDSI_FIND_QUIETLY) + message(STATUS "Found Meade DSI: ${MEADEDSI_LIBRARIES}") + endif (NOT MEADEDSI_FIND_QUIETLY) + else (MEADEDSI_FOUND) + if (MEADEDSI_FIND_REQUIRED) + message(FATAL_ERROR "Meade DSI not found. Please install Meade DSI library. http://linuxdsi.sourceforge.net") + endif (MEADEDSI_FIND_REQUIRED) + endif (MEADEDSI_FOUND) + + mark_as_advanced(MEADEDSI_LIBRARIES) + +endif (MEADEDSI_LIBRARIES) diff --git a/cmake_modules/FindMICAM.cmake b/cmake_modules/FindMICAM.cmake new file mode 100644 index 0000000..b62561b --- /dev/null +++ b/cmake_modules/FindMICAM.cmake @@ -0,0 +1,49 @@ +# - Try to find Moravian Instruments Camera Library +# Once done this will define +# +# MICAM_FOUND - system has MI +# MICAM_INCLUDE_DIR - the MI include directory +# MICAM_LIBRARIES - Link these to use MI + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (MICAM_INCLUDE_DIR AND MICAM_LIBRARIES) + + # in cache already + set(MICAM_FOUND TRUE) + message(STATUS "Found libmicam: ${MICAM_LIBRARIES}") + +else (MICAM_INCLUDE_DIR AND MICAM_LIBRARIES) + + find_path(MICAM_INCLUDE_DIR gxccd.h + PATH_SUFFIXES libmicam + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(MICAM_LIBRARIES NAMES gxccd + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(MICAM_INCLUDE_DIR AND MICAM_LIBRARIES) + set(MICAM_FOUND TRUE) + else (MICAM_INCLUDE_DIR AND MICAM_LIBRARIES) + set(MICAM_FOUND FALSE) + endif(MICAM_INCLUDE_DIR AND MICAM_LIBRARIES) + + if (MICAM_FOUND) + if (NOT MICAM_FIND_QUIETLY) + message(STATUS "Found MI Library: ${MICAM_LIBRARIES}") + endif (NOT MICAM_FIND_QUIETLY) + else (MICAM_FOUND) + if (MICAM_FIND_REQUIRED) + message(FATAL_ERROR "MI Library not found. Please install MI Library http://www.indilib.org") + endif (MICAM_FIND_REQUIRED) + endif (MICAM_FOUND) + + mark_as_advanced(MICAM_INCLUDE_DIR MICAM_LIBRARIES) + +endif (MICAM_INCLUDE_DIR AND MICAM_LIBRARIES) diff --git a/cmake_modules/FindMMAL.cmake b/cmake_modules/FindMMAL.cmake new file mode 100644 index 0000000..a537c51 --- /dev/null +++ b/cmake_modules/FindMMAL.cmake @@ -0,0 +1,45 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This module can find the MMAL camera libraries. +# +cmake_minimum_required(VERSION 3.0.0) + +set (MMAL_LIBS mmal_core mmal_util mmal_vc_client) +set (EGL_LIBS brcmGLESv2 brcmEGL) + +foreach(lib ${MMAL_LIBS} ${EGL_LIBS} vcos bcm_host m dl) + find_library(${lib}_LIBRARY + NAMES ${lib} + HINTS ${MMAL_DIR}/lib /opt/vc/lib + ) + if (DEFINED ${lib}_LIBRARY) + set(MMAL_LIBRARIES ${MMAL_LIBRARIES} ${${lib}_LIBRARY}) + else() + message(FATAL_ERROR "Failed to find ${${lib}_LIBRARY} library") + endif() +endforeach(lib) + +find_path(BCM_INCLUDE_DIR NAMES bcm_host.h + HINTS "/opt/vc/include" +) + +find_path(MMAL_BASE_INCLUDE_DIR NAMES mmal.h + HINTS "/opt/vc/include/interface/mmal" +) + +find_path(MMAL_UTIL_INCLUDE_DIR NAMES mmal_util.h + HINTS "/opt/vc/include/interface/mmal/util" +) + +if (MMAL_BASE_INCLUDE_DIR AND BCM_INCLUDE_DIR AND MMAL_UTIL_INCLUDE_DIR) + set(MMAL_INCLUDE_DIR ${MMAL_BASE_INCLUDE_DIR} ${BCM_INCLUDE_DIR} ${MMAL_UTIL_INCLUDE_DIR}) + set(MMAL_FOUND TRUE) +endif() diff --git a/cmake_modules/FindMODBUS.cmake b/cmake_modules/FindMODBUS.cmake new file mode 100644 index 0000000..42e8c47 --- /dev/null +++ b/cmake_modules/FindMODBUS.cmake @@ -0,0 +1,56 @@ +# - Try to find libmodbus +# Once done this will define +# +# MODBUS_FOUND - system has MODBUS +# MODBUS_INCLUDE_DIR - the MODBUS include directory +# MODBUS_LIBRARIES - Link these to use MODBUS + +# Copyright (c) 2006, Jasem Mutlaq +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES) + + # in cache already + set(MODBUS_FOUND TRUE) + message(STATUS "Found libmodbus: ${MODBUS_LIBRARIES}") + +else (MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES) + + find_path(MODBUS_INCLUDE_DIR modbus.h + PATH_SUFFIXES modbus + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(MODBUS_LIBRARIES NAMES modbus + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + set(CMAKE_REQUIRED_INCLUDES ${MODBUS_INCLUDE_DIR}) + set(CMAKE_REQUIRED_LIBRARIES ${MODBUS_LIBRARIES}) + + if(MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES) + set(MODBUS_FOUND TRUE) + else (MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES) + set(MODBUS_FOUND FALSE) + endif(MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES) + + if (MODBUS_FOUND) + if (NOT MODBUS_FIND_QUIETLY) + message(STATUS "Found libmodbus: ${MODBUS_LIBRARIES}") + endif (NOT MODBUS_FIND_QUIETLY) + else (MODBUS_FOUND) + if (MODBUS_FIND_REQUIRED) + message(FATAL_ERROR "libmodbus not found. Please install libmodbus-devel. https://launchpad.net/libmodbus/") + endif (MODBUS_FIND_REQUIRED) + endif (MODBUS_FOUND) + + mark_as_advanced(MODBUS_INCLUDE_DIR MODBUS_LIBRARIES) + +endif (MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES) + diff --git a/cmake_modules/FindNNCAM.cmake b/cmake_modules/FindNNCAM.cmake new file mode 100644 index 0000000..a9eabe1 --- /dev/null +++ b/cmake_modules/FindNNCAM.cmake @@ -0,0 +1,49 @@ +# - Try to find NNCAM Camera Library +# Once done this will define +# +# NNCAM_FOUND - system has Levenhuk +# NNCAM_INCLUDE_DIR - the Levenhuk include directory +# NNCAM_LIBRARIES - Link these to use Levenhuk + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (NNCAM_INCLUDE_DIR AND NNCAM_LIBRARIES) + + # in cache already + set(NNCAM_FOUND TRUE) + message(STATUS "Found libnncam: ${NNCAM_LIBRARIES}") + +else (NNCAM_INCLUDE_DIR AND NNCAM_LIBRARIES) + + find_path(NNCAM_INCLUDE_DIR nncam.h + PATH_SUFFIXES libnncam + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(NNCAM_LIBRARIES NAMES nncam + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(NNCAM_INCLUDE_DIR AND NNCAM_LIBRARIES) + set(NNCAM_FOUND TRUE) + else (NNCAM_INCLUDE_DIR AND NNCAM_LIBRARIES) + set(NNCAM_FOUND FALSE) + endif(NNCAM_INCLUDE_DIR AND NNCAM_LIBRARIES) + + if (NNCAM_FOUND) + if (NOT NNCAM_FIND_QUIETLY) + message(STATUS "Found NNCAM: ${NNCAM_LIBRARIES}") + endif (NOT NNCAM_FIND_QUIETLY) + else (NNCAM_FOUND) + if (NNCAM_FIND_REQUIRED) + message(FATAL_ERROR "NNCAM not found. Please install NNCAM Library http://www.indilib.org") + endif (NNCAM_FIND_REQUIRED) + endif (NNCAM_FOUND) + + mark_as_advanced(NNCAM_INCLUDE_DIR NNCAM_LIBRARIES) + +endif (NNCAM_INCLUDE_DIR AND NNCAM_LIBRARIES) diff --git a/cmake_modules/FindNUTClient.cmake b/cmake_modules/FindNUTClient.cmake new file mode 100644 index 0000000..bdac85d --- /dev/null +++ b/cmake_modules/FindNUTClient.cmake @@ -0,0 +1,50 @@ +# - Try to find nutclient library (version 2) and include files +# Once done this will define +# +# NUTCLIENT_FOUND - system has NUTCLIENT +# NUTCLIENT_INCLUDE_DIR - the NUTCLIENT include directory +# NUTCLIENT_LIBRARIES - Link these to use NUTCLIENT + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (NUTCLIENT_INCLUDE_DIR AND NUTCLIENT_LIBRARIES) + + # in cache already + set(NUTCLIENT_FOUND TRUE) + message(STATUS "Found libnutclient: ${NUTCLIENT_LIBRARIES}") + +else (NUTCLIENT_INCLUDE_DIR AND NUTCLIENT_LIBRARIES) + + find_path(NUTCLIENT_INCLUDE_DIR nutclient.h + PATH_SUFFIXES nutclient + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(NUTCLIENT_LIBRARIES NAMES nutclient + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(NUTCLIENT_INCLUDE_DIR AND NUTCLIENT_LIBRARIES) + set(NUTCLIENT_FOUND TRUE) + else (NUTCLIENT_INCLUDE_DIR AND NUTCLIENT_LIBRARIES) + set(NUTCLIENT_FOUND FALSE) + endif(NUTCLIENT_INCLUDE_DIR AND NUTCLIENT_LIBRARIES) + + + if (NUTCLIENT_FOUND) + if (NOT NUTCLIENT_FIND_QUIETLY) + message(STATUS "Found NUTCLIENT: ${NUTCLIENT_LIBRARIES}") + endif (NOT NUTCLIENT_FIND_QUIETLY) + else (NUTCLIENT_FOUND) + if (NUTCLIENT_FIND_REQUIRED) + message(FATAL_ERROR "NUTCLIENT not found. Please install libnutclient development package.") + endif (NUTCLIENT_FIND_REQUIRED) + endif (NUTCLIENT_FOUND) + + mark_as_advanced(NUTCLIENT_INCLUDE_DIR NUTCLIENT_LIBRARIES) + +endif (NUTCLIENT_INCLUDE_DIR AND NUTCLIENT_LIBRARIES) diff --git a/cmake_modules/FindNova.cmake b/cmake_modules/FindNova.cmake new file mode 100644 index 0000000..2d6761c --- /dev/null +++ b/cmake_modules/FindNova.cmake @@ -0,0 +1,55 @@ +# - Try to find NOVA +# Once done this will define +# +# NOVA_FOUND - system has NOVA +# NOVA_INCLUDE_DIR - the NOVA include directory +# NOVA_LIBRARIES - Link these to use NOVA + +# Copyright (c) 2006, Jasem Mutlaq +# Based on FindLibfacile by Carsten Niehaus, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (NOVA_INCLUDE_DIR AND NOVA_LIBRARIES) + + # in cache already + set(NOVA_FOUND TRUE) + message(STATUS "Found libnova: ${NOVA_LIBRARIES}") + +else (NOVA_INCLUDE_DIR AND NOVA_LIBRARIES) + + find_path(NOVA_INCLUDE_DIR libnova.h + PATH_SUFFIXES libnova + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(NOVA_LIBRARIES NAMES nova libnova libnovad + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + set(CMAKE_REQUIRED_INCLUDES ${NOVA_INCLUDE_DIR}) + set(CMAKE_REQUIRED_LIBRARIES ${NOVA_LIBRARIES}) + + if(NOVA_INCLUDE_DIR AND NOVA_LIBRARIES) + set(NOVA_FOUND TRUE) + else (NOVA_INCLUDE_DIR AND NOVA_LIBRARIES) + set(NOVA_FOUND FALSE) + endif(NOVA_INCLUDE_DIR AND NOVA_LIBRARIES) + + if (NOVA_FOUND) + if (NOT Nova_FIND_QUIETLY) + message(STATUS "Found NOVA: ${NOVA_LIBRARIES}") + endif (NOT Nova_FIND_QUIETLY) + else (NOVA_FOUND) + if (Nova_FIND_REQUIRED) + message(FATAL_ERROR "libnova not found. Please install libnova development package.") + endif (Nova_FIND_REQUIRED) + endif (NOVA_FOUND) + + mark_as_advanced(NOVA_INCLUDE_DIR NOVA_LIBRARIES) + +endif (NOVA_INCLUDE_DIR AND NOVA_LIBRARIES) diff --git a/cmake_modules/FindOMEGONPROCAM.cmake b/cmake_modules/FindOMEGONPROCAM.cmake new file mode 100644 index 0000000..6e04b37 --- /dev/null +++ b/cmake_modules/FindOMEGONPROCAM.cmake @@ -0,0 +1,50 @@ +# - Try to find Omegon Pro Cam Camera Library +# Once done this will define +# +# OMEGONPROCAM_FOUND - system has Omegon Pro Cam +# OMEGONPROCAM_INCLUDE_DIR - the Omegon Pro Cam include directory +# OMEGONPROCAM_LIBRARIES - Link these to use Omegon Pro Cam + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (OMEGONPROCAM_INCLUDE_DIR AND OMEGONPROCAM_LIBRARIES) + + # in cache already + set(OMEGONPROCAM_FOUND TRUE) + message(STATUS "Found libomegonprocam: ${OMEGONPROCAM_LIBRARIES}") + +else (OMEGONPROCAM_INCLUDE_DIR AND OMEGONPROCAM_LIBRARIES) + + find_path(OMEGONPROCAM_INCLUDE_DIR omegonprocam.h + PATH_SUFFIXES libomegonprocam + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(OMEGONPROCAM_LIBRARIES NAMES omegonprocam + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(OMEGONPROCAM_INCLUDE_DIR AND OMEGONPROCAM_LIBRARIES) + set(OMEGONPROCAM_FOUND TRUE) + else (OMEGONPROCAM_INCLUDE_DIR AND OMEGONPROCAM_LIBRARIES) + set(OMEGONPROCAM_FOUND FALSE) + endif(OMEGONPROCAM_INCLUDE_DIR AND OMEGONPROCAM_LIBRARIES) + + + if (OMEGONPROCAM_FOUND) + if (NOT OMEGONPROCAM_FIND_QUIETLY) + message(STATUS "Found OmegonProCam: ${OMEGONPROCAM_LIBRARIES}") + endif (NOT OMEGONPROCAM_FIND_QUIETLY) + else (OMEGONPROCAM_FOUND) + if (OMEGONPROCAM_FIND_REQUIRED) + message(FATAL_ERROR "OmegonProCam not found. Please install OmegonProCam Library http://www.indilib.org") + endif (OMEGONPROCAM_FIND_REQUIRED) + endif (OMEGONPROCAM_FOUND) + + mark_as_advanced(OMEGONPROCAM_INCLUDE_DIR OMEGONPROCAM_LIBRARIES) + +endif (OMEGONPROCAM_INCLUDE_DIR AND OMEGONPROCAM_LIBRARIES) diff --git a/cmake_modules/FindOggTheora.cmake b/cmake_modules/FindOggTheora.cmake new file mode 100644 index 0000000..a536fc1 --- /dev/null +++ b/cmake_modules/FindOggTheora.cmake @@ -0,0 +1,47 @@ +# +# Find the native Ogg/Theora includes and libraries +# +# This module defines +# OGGTHEORA_INCLUDE_DIR, where to find ogg/ogg.h and theora/theora.h +# OGGTHEORA_LIBRARIES, the libraries to link against to use Ogg/Theora. +# OGGTHEORA_FOUND, If false, do not try to use Ogg/Theora. + +FIND_PATH(OGGTHEORA_ogg_INCLUDE_DIR ogg/ogg.h) + +FIND_PATH(OGGTHEORA_theora_INCLUDE_DIR theora/theora.h) + +FIND_LIBRARY(OGGTHEORA_ogg_LIBRARY ogg) + +FIND_LIBRARY(OGGTHEORA_theoraenc_LIBRARY theoraenc) + +FIND_LIBRARY(OGGTHEORA_theoradec_LIBRARY theoradec) + +SET(OGGTHEORA_INCLUDE_DIRS + ${OGGTHEORA_ogg_INCLUDE_DIR} + ${OGGTHEORA_theora_INCLUDE_DIR} + ) +#HACK multiple directories +SET(OGGTHEORA_INCLUDE_DIR ${OGGTHEORA_INCLUDE_DIRS}) + +SET(OGGTHEORA_LIBRARIES + ${OGGTHEORA_theoraenc_LIBRARY} + ${OGGTHEORA_theoradec_LIBRARY} + ${OGGTHEORA_ogg_LIBRARY} + ) +#HACK multiple libraries +SET(OGGTHEORA_LIBRARY ${OGGTHEORA_LIBRARIES}) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(OGGTHEORA + "Could NOT find the ogg and theora libraries" + OGGTHEORA_ogg_LIBRARY + OGGTHEORA_theoraenc_LIBRARY + OGGTHEORA_theoradec_LIBRARY + OGGTHEORA_ogg_INCLUDE_DIR + OGGTHEORA_theora_INCLUDE_DIR + ) + +MARK_AS_ADVANCED(OGGTHEORA_ogg_INCLUDE_DIR OGGTHEORA_theora_INCLUDE_DIR + OGGTHEORA_ogg_LIBRARY OGGTHEORA_theoraenc_LIBRARY + OGGTHEORA_theoradec_LIBRARY + ) diff --git a/cmake_modules/FindOpenAL.cmake b/cmake_modules/FindOpenAL.cmake new file mode 100644 index 0000000..8d2933c --- /dev/null +++ b/cmake_modules/FindOpenAL.cmake @@ -0,0 +1,100 @@ +# Locate OpenAL +# This module defines +# OPENAL_LIBRARY +# OPENAL_FOUND, if false, do not try to link to OpenAL +# OPENAL_INCLUDE_DIR, where to find the headers +# +# $OPENALDIR is an environment variable that would +# correspond to the ./configure --prefix=$OPENALDIR +# used in building OpenAL. +# +# Created by Eric Wing. This was influenced by the FindSDL.cmake module. + +# This makes the presumption that you are include al.h like +# #include "al.h" +# and not +# #include +# The reason for this is that the latter is not entirely portable. +# Windows/Creative Labs does not by default put their headers in AL/ and +# OS X uses the convention . +# +# For Windows, Creative Labs seems to have added a registry key for their +# OpenAL 1.1 installer. I have added that key to the list of search paths, +# however, the key looks like it could be a little fragile depending on +# if they decide to change the 1.00.0000 number for bug fix releases. +# Also, they seem to have laid down groundwork for multiple library platforms +# which puts the library in an extra subdirectory. Currently there is only +# Win32 and I have hardcoded that here. This may need to be adjusted as +# platforms are introduced. +# The OpenAL 1.0 installer doesn't seem to have a useful key I can use. +# I do not know if the Nvidia OpenAL SDK has a registry key. +# +# For OS X, remember that OpenAL was added by Apple in 10.4 (Tiger). +# To support the framework, I originally wrote special framework detection +# code in this module which I have now removed with CMake's introduction +# of native support for frameworks. +# In addition, OpenAL is open source, and it is possible to compile on Panther. +# Furthermore, due to bugs in the initial OpenAL release, and the +# transition to OpenAL 1.1, it is common to need to override the built-in +# framework. +# Per my request, CMake should search for frameworks first in +# the following order: +# ~/Library/Frameworks/OpenAL.framework/Headers +# /Library/Frameworks/OpenAL.framework/Headers +# /System/Library/Frameworks/OpenAL.framework/Headers +# +# On OS X, this will prefer the Framework version (if found) over others. +# People will have to manually change the cache values of +# OPENAL_LIBRARY to override this selection or set the CMake environment +# CMAKE_INCLUDE_PATH to modify the search paths. + +FIND_PATH(OPENAL_INCLUDE_DIR al.h + PATHS + $ENV{OPENALDIR} + NO_DEFAULT_PATH + PATH_SUFFIXES include/AL include/OpenAL include +) + +FIND_PATH(OPENAL_INCLUDE_DIR al.h + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir] + PATH_SUFFIXES include/AL include/OpenAL include +) + +FIND_LIBRARY(OPENAL_LIBRARY + NAMES OpenAL al openal OpenAL32 + PATHS + $ENV{OPENALDIR} + NO_DEFAULT_PATH + PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 +) + +FIND_LIBRARY(OPENAL_LIBRARY + NAMES OpenAL al openal OpenAL32 + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw + /opt/local + /opt/csw + /opt + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir] + PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 +) + + +SET(OPENAL_FOUND "NO") +IF(OPENAL_LIBRARY AND OPENAL_INCLUDE_DIR) + SET(OPENAL_FOUND "YES") +ENDIF(OPENAL_LIBRARY AND OPENAL_INCLUDE_DIR) + diff --git a/cmake_modules/FindPENTAX.cmake b/cmake_modules/FindPENTAX.cmake new file mode 100644 index 0000000..5209c8a --- /dev/null +++ b/cmake_modules/FindPENTAX.cmake @@ -0,0 +1,86 @@ +# - Try to find PENTAX Universal Libraries +# Once done this will define +# +# PENTAX_FOUND - system has PENTAX +# PENTAX_INCLUDE_DIR - the PENTAX include directory +# PENTAX_LIBRARIES - Link these to use PENTAX + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (PENTAX_INCLUDE_DIR AND PENTAX_LIBRARIES) + + # in cache already + set(PENTAX_FOUND TRUE) + message(STATUS "Found PENTAX libraries: ${PENTAX_LIBRARIES}") + +else (PENTAX_INCLUDE_DIR AND PENTAX_LIBRARIES) + + find_path(PKTRIGGERCORD_INCLUDE_DIR libpktriggercord.h + PATH_SUFFIXES libpktriggercord + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(PKTRIGGERCORD_LIBRARIES NAMES pktriggercord + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + PATH_SUFFIXES indipentax + ) + +#if not armv8, then look for ricoh library; otherwise only use pktriggercord library + if(NOT (${CMAKE_SYSTEM_PROCESSOR} MATCHES "^aarch64")) + find_path(RICOH_INCLUDE_DIR ricoh_camera_sdk.hpp + PATH_SUFFIXES libpentax libricohcamerasdk + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + find_library(RICOH_LIBRARIES NAMES RicohCameraSDKCpp + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + find_library(RICOHMTP_LIBRARIES NAMES libmtpricoh.so.9.3.0 + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if (RICOH_INCLUDE_DIR AND PKTRIGGERCORD_INCLUDE_DIR) + set(PENTAX_INCLUDE_DIR ${RICOH_INCLUDE_DIR} ${PKTRIGGERCORD_INCLUDE_DIR}) + endif (RICOH_INCLUDE_DIR AND PKTRIGGERCORD_INCLUDE_DIR) + if (RICOH_LIBRARIES AND RICOHMTP_LIBRARIES AND PKTRIGGERCORD_LIBRARIES) + set(PENTAX_LIBRARIES ${RICOH_LIBRARIES} ${RICOHMTP_LIBRARIES} ${PKTRIGGERCORD_LIBRARIES}) + endif (RICOH_LIBRARIES AND RICOHMTP_LIBRARIES AND PKTRIGGERCORD_LIBRARIES) + + else() + if (PKTRIGGERCORD_INCLUDE_DIR) + set(PENTAX_INCLUDE_DIR ${PKTRIGGERCORD_INCLUDE_DIR}) + endif (PKTRIGGERCORD_INCLUDE_DIR) + if (PKTRIGGERCORD_LIBRARIES) + set(PENTAX_LIBRARIES ${PKTRIGGERCORD_LIBRARIES}) + endif (PKTRIGGERCORD_LIBRARIES) + endif() + + + if(PENTAX_INCLUDE_DIR AND PENTAX_LIBRARIES) + set(PENTAX_FOUND TRUE) + else (PENTAX_INCLUDE_DIR AND PENTAX_LIBRARIES) + set(PENTAX_FOUND FALSE) + endif(PENTAX_INCLUDE_DIR AND PENTAX_LIBRARIES) + + + if (PENTAX_FOUND) + if (NOT PENTAX_FIND_QUIETLY) + message(STATUS "Found PENTAX libraries: ${PENTAX_LIBRARIES}") + endif (NOT PENTAX_FIND_QUIETLY) + else (PENTAX_FOUND) + if (PENTAX_FIND_REQUIRED) + message(FATAL_ERROR "One or both of libricohcamersdk and libpktriggercord are not found. Please install them. See http://www.indilib.org.") + endif (PENTAX_FIND_REQUIRED) + endif (PENTAX_FOUND) + + mark_as_advanced(PENTAX_INCLUDE_DIR PENTAX_LIBRARIES) + +endif (PENTAX_INCLUDE_DIR AND PENTAX_LIBRARIES) diff --git a/cmake_modules/FindPLAYERONE.cmake b/cmake_modules/FindPLAYERONE.cmake new file mode 100644 index 0000000..9171a51 --- /dev/null +++ b/cmake_modules/FindPLAYERONE.cmake @@ -0,0 +1,56 @@ +# - Try to find PlayerOne Library +# Once done this will define +# +# PLAYERONE_FOUND - system has PLAYERONE +# PLAYERONE_INCLUDE_DIR - the PLAYERONE include directory +# PLAYERONE_LIBRARIES - Link these to use ASI + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (PLAYERONE_INCLUDE_DIR AND PLAYERONE_LIBRARIES) + + # in cache already + set(PLAYERONE_FOUND TRUE) + message(STATUS "Found libplayerone: ${PLAYERONE_LIBRARIES}") + +else (PLAYERONE_INCLUDE_DIR AND PLAYERONE_LIBRARIES) + + find_path(PLAYERONE_INCLUDE_DIR PlayerOneCamera.h + PATH_SUFFIXES libplayerone + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(PLAYERONECAM_LIBRARIES NAMES PlayerOneCamera + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + + if (PLAYERONECAM_LIBRARIES) + set(PLAYERONE_LIBRARIES ${PLAYERONECAM_LIBRARIES}) + endif (PLAYERONECAM_LIBRARIES) + + + if(PLAYERONE_INCLUDE_DIR AND PLAYERONE_LIBRARIES) + set(PLAYERONE_FOUND TRUE) + else (PLAYERONE_INCLUDE_DIR AND PLAYERONE_LIBRARIES) + set(PLAYERONE_FOUND FALSE) + endif(PLAYERONE_INCLUDE_DIR AND PLAYERONE_LIBRARIES) + + + if (PLAYERONE_FOUND) + if (NOT PLAYERONE_FIND_QUIETLY) + message(STATUS "Found PLAYERONE: ${PLAYERONE_LIBRARIES}") + endif (NOT PLAYERONE_FIND_QUIETLY) + else (PLAYERONE_FOUND) + if (PLAYERONE_FIND_REQUIRED) + message(FATAL_ERROR "PLAYERONE not found. Please install libPlayerOneCamera.3 http://www.indilib.org") + endif (PLAYERONE_FIND_REQUIRED) + endif (PLAYERONE_FOUND) + + mark_as_advanced(PLAYERONE_INCLUDE_DIR PLAYERONE_LIBRARIES) + +endif (PLAYERONE_INCLUDE_DIR AND PLAYERONE_LIBRARIES) diff --git a/cmake_modules/FindPackageHandleStandardArgs.cmake b/cmake_modules/FindPackageHandleStandardArgs.cmake new file mode 100644 index 0000000..fe2dbea --- /dev/null +++ b/cmake_modules/FindPackageHandleStandardArgs.cmake @@ -0,0 +1,396 @@ +#[=======================================================================[.rst: +FindPackageHandleStandardArgs +----------------------------- + +This module provides a function intended to be used in :ref:`Find Modules` +implementing :command:`find_package()` calls. It handles the +``REQUIRED``, ``QUIET`` and version-related arguments of ``find_package``. +It also sets the ``_FOUND`` variable. The package is +considered found if all variables listed contain valid results, e.g. +valid filepaths. + +.. command:: find_package_handle_standard_args + + There are two signatures:: + + find_package_handle_standard_args( + (DEFAULT_MSG|) + ... + ) + + find_package_handle_standard_args( + [FOUND_VAR ] + [REQUIRED_VARS ...] + [VERSION_VAR ] + [HANDLE_COMPONENTS] + [CONFIG_MODE] + [FAIL_MESSAGE ] + ) + + The ``_FOUND`` variable will be set to ``TRUE`` if all + the variables ``...`` are valid and any optional + constraints are satisfied, and ``FALSE`` otherwise. A success or + failure message may be displayed based on the results and on + whether the ``REQUIRED`` and/or ``QUIET`` option was given to + the :command:`find_package` call. + + The options are: + + ``(DEFAULT_MSG|)`` + In the simple signature this specifies the failure message. + Use ``DEFAULT_MSG`` to ask for a default message to be computed + (recommended). Not valid in the full signature. + + ``FOUND_VAR `` + Obsolete. Specifies either ``_FOUND`` or + ``_FOUND`` as the result variable. This exists only + for compatibility with older versions of CMake and is now ignored. + Result variables of both names are always set for compatibility. + + ``REQUIRED_VARS ...`` + Specify the variables which are required for this package. + These may be named in the generated failure message asking the + user to set the missing variable values. Therefore these should + typically be cache entries such as ``FOO_LIBRARY`` and not output + variables like ``FOO_LIBRARIES``. + + ``VERSION_VAR `` + Specify the name of a variable that holds the version of the package + that has been found. This version will be checked against the + (potentially) specified required version given to the + :command:`find_package` call, including its ``EXACT`` option. + The default messages include information about the required + version and the version which has been actually found, both + if the version is ok or not. + + ``HANDLE_COMPONENTS`` + Enable handling of package components. In this case, the command + will report which components have been found and which are missing, + and the ``_FOUND`` variable will be set to ``FALSE`` + if any of the required components (i.e. not the ones listed after + the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are + missing. + + ``CONFIG_MODE`` + Specify that the calling find module is a wrapper around a + call to ``find_package( NO_MODULE)``. This implies + a ``VERSION_VAR`` value of ``_VERSION``. The command + will automatically check whether the package configuration file + was found. + + ``FAIL_MESSAGE `` + Specify a custom failure message instead of using the default + generated message. Not recommended. + +Example for the simple signature: + +.. code-block:: cmake + + find_package_handle_standard_args(LibXml2 DEFAULT_MSG + LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR) + +The ``LibXml2`` package is considered to be found if both +``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid. +Then also ``LibXml2_FOUND`` is set to ``TRUE``. If it is not found +and ``REQUIRED`` was used, it fails with a +:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was +used or not. If it is found, success will be reported, including +the content of the first ````. On repeated CMake runs, +the same message will not be printed again. + +Example for the full signature: + +.. code-block:: cmake + + find_package_handle_standard_args(LibArchive + REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR + VERSION_VAR LibArchive_VERSION) + +In this case, the ``LibArchive`` package is considered to be found if +both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid. +Also the version of ``LibArchive`` will be checked by using the version +contained in ``LibArchive_VERSION``. Since no ``FAIL_MESSAGE`` is given, +the default messages will be printed. + +Another example for the full signature: + +.. code-block:: cmake + + find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4) + find_package_handle_standard_args(Automoc4 CONFIG_MODE) + +In this case, a ``FindAutmoc4.cmake`` module wraps a call to +``find_package(Automoc4 NO_MODULE)`` and adds an additional search +directory for ``automoc4``. Then the call to +``find_package_handle_standard_args`` produces a proper success/failure +message. +#]=======================================================================] + +#============================================================================= +# Copyright 2007-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) + +# internal helper macro +macro(_FPHSA_FAILURE_MESSAGE _msg) + if (${_NAME}_FIND_REQUIRED) + message(FATAL_ERROR "${_msg}") + else () + if (NOT ${_NAME}_FIND_QUIETLY) + message(STATUS "${_msg}") + endif () + endif () +endmacro() + + +# internal helper macro to generate the failure message when used in CONFIG_MODE: +macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) + # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: + if(${_NAME}_CONFIG) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + else() + # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. + # List them all in the error message: + if(${_NAME}_CONSIDERED_CONFIGS) + set(configsText "") + list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) + math(EXPR configsCount "${configsCount} - 1") + foreach(currentConfigIndex RANGE ${configsCount}) + list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) + list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) + set(configsText "${configsText} ${filename} (version ${version})\n") + endforeach() + if (${_NAME}_NOT_FOUND_MESSAGE) + set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n") + endif() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}") + + else() + # Simple case: No Config-file was found at all: + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") + endif() + endif() +endmacro() + + +function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) + +# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in +# new extended or in the "old" mode: + set(options CONFIG_MODE HANDLE_COMPONENTS) + set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR) + set(multiValueArgs REQUIRED_VARS) + set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) + list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) + + if(${INDEX} EQUAL -1) + set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) + set(FPHSA_REQUIRED_VARS ${ARGN}) + set(FPHSA_VERSION_VAR) + else() + + CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) + + if(FPHSA_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") + endif() + + if(NOT FPHSA_FAIL_MESSAGE) + set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") + endif() + endif() + +# now that we collected all arguments, process them + + if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG") + set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") + endif() + + # In config-mode, we rely on the variable _CONFIG, which is set by find_package() + # when it successfully found the config-file, including version checking: + if(FPHSA_CONFIG_MODE) + list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) + list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) + set(FPHSA_VERSION_VAR ${_NAME}_VERSION) + endif() + + if(NOT FPHSA_REQUIRED_VARS) + message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") + endif() + + list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) + + string(TOUPPER ${_NAME} _NAME_UPPER) + string(TOLOWER ${_NAME} _NAME_LOWER) + + if(FPHSA_FOUND_VAR) + if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$") + set(_FOUND_VAR ${FPHSA_FOUND_VAR}) + else() + message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.") + endif() + else() + set(_FOUND_VAR ${_NAME_UPPER}_FOUND) + endif() + + # collect all variables which were not found, so they can be printed, so the + # user knows better what went wrong (#6375) + set(MISSING_VARS "") + set(DETAILS "") + # check if all passed variables are valid + set(FPHSA_FOUND_${_NAME} TRUE) + foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) + if(NOT ${_CURRENT_VAR}) + set(FPHSA_FOUND_${_NAME} FALSE) + set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}") + else() + set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]") + endif() + endforeach() + if(FPHSA_FOUND_${_NAME}) + set(${_NAME}_FOUND TRUE) + set(${_NAME_UPPER}_FOUND TRUE) + else() + set(${_NAME}_FOUND FALSE) + set(${_NAME_UPPER}_FOUND FALSE) + endif() + + # component handling + unset(FOUND_COMPONENTS_MSG) + unset(MISSING_COMPONENTS_MSG) + + if(FPHSA_HANDLE_COMPONENTS) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(${_NAME}_${comp}_FOUND) + + if(NOT DEFINED FOUND_COMPONENTS_MSG) + set(FOUND_COMPONENTS_MSG "found components: ") + endif() + set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}") + + else() + + if(NOT DEFINED MISSING_COMPONENTS_MSG) + set(MISSING_COMPONENTS_MSG "missing components: ") + endif() + set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}") + + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + set(MISSING_VARS "${MISSING_VARS} ${comp}") + endif() + + endif() + endforeach() + set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}") + set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]") + endif() + + # version handling: + set(VERSION_MSG "") + set(VERSION_OK TRUE) + set(VERSION ${${FPHSA_VERSION_VAR}}) + + # check with DEFINED here as the requested or found version may be "0" + if (DEFINED ${_NAME}_FIND_VERSION) + if(DEFINED ${FPHSA_VERSION_VAR}) + + if(${_NAME}_FIND_VERSION_EXACT) # exact version required + # count the dots in the version string + string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${VERSION}") + # add one dot because there is one dot more than there are components + string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS) + if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT) + # Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT + # is at most 4 here. Therefore a simple lookup table is used. + if (${_NAME}_FIND_VERSION_COUNT EQUAL 1) + set(_VERSION_REGEX "[^.]*") + elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2) + set(_VERSION_REGEX "[^.]*\\.[^.]*") + elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3) + set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*") + else () + set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*") + endif () + string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${VERSION}") + unset(_VERSION_REGEX) + if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD) + set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable exact version \"${VERSION}\")") + endif () + unset(_VERSION_HEAD) + else () + if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL VERSION) + set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable exact version \"${VERSION}\")") + endif () + endif () + unset(_VERSION_DOTS) + + else() # minimum version specified: + if (${_NAME}_FIND_VERSION VERSION_GREATER VERSION) + set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")") + endif () + endif() + + else() + + # if the package was not found, but a version was given, add that to the output: + if(${_NAME}_FIND_VERSION_EXACT) + set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") + else() + set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") + endif() + + endif() + else () + if(VERSION) + set(VERSION_MSG "(found version \"${VERSION}\")") + endif() + endif () + + if(VERSION_OK) + set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]") + else() + set(${_NAME}_FOUND FALSE) + endif() + + + # print the result: + if (${_NAME}_FOUND) + FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}") + else () + + if(FPHSA_CONFIG_MODE) + _FPHSA_HANDLE_FAILURE_CONFIG_MODE() + else() + if(NOT VERSION_OK) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") + else() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}") + endif() + endif() + + endif () + + set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) + set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) +endfunction() diff --git a/cmake_modules/FindPackageMessage.cmake b/cmake_modules/FindPackageMessage.cmake new file mode 100644 index 0000000..a0349d3 --- /dev/null +++ b/cmake_modules/FindPackageMessage.cmake @@ -0,0 +1,57 @@ +#.rst: +# FindPackageMessage +# ------------------ +# +# +# +# FIND_PACKAGE_MESSAGE( "message for user" "find result details") +# +# This macro is intended to be used in FindXXX.cmake modules files. It +# will print a message once for each unique find result. This is useful +# for telling the user where a package was found. The first argument +# specifies the name (XXX) of the package. The second argument +# specifies the message to display. The third argument lists details +# about the find result so that if they change the message will be +# displayed again. The macro also obeys the QUIET argument to the +# find_package command. +# +# Example: +# +# :: +# +# if(X11_FOUND) +# FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}" +# "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]") +# else() +# ... +# endif() + +#============================================================================= +# Copyright 2008-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +function(FIND_PACKAGE_MESSAGE pkg msg details) + # Avoid printing a message repeatedly for the same find result. + if(NOT ${pkg}_FIND_QUIETLY) + string(REPLACE "\n" "" details "${details}") + set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg}) + if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}") + # The message has not yet been printed. + message(STATUS "${msg}") + + # Save the find details in the cache to avoid printing the same + # message again. + set("${DETAILS_VAR}" "${details}" + CACHE INTERNAL "Details about finding ${pkg}") + endif() + endif() +endfunction() diff --git a/cmake_modules/FindQHY.cmake b/cmake_modules/FindQHY.cmake new file mode 100644 index 0000000..9b41ac5 --- /dev/null +++ b/cmake_modules/FindQHY.cmake @@ -0,0 +1,50 @@ +# - Try to find QHY Library +# Once done this will define +# +# QHY_FOUND - system has QHY +# QHY_INCLUDE_DIR - the QHY include directory +# QHY_LIBRARIES - Link these to use QHY + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (QHY_INCLUDE_DIR AND QHY_LIBRARIES) + + # in cache already + set(QHY_FOUND TRUE) + message(STATUS "Found libqhyccd: ${QHY_LIBRARIES}") + +else (QHY_INCLUDE_DIR AND QHY_LIBRARIES) + + find_path(QHY_INCLUDE_DIR qhyccd.h + PATH_SUFFIXES libqhy + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(QHY_LIBRARIES NAMES qhyccd + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(QHY_INCLUDE_DIR AND QHY_LIBRARIES) + set(QHY_FOUND TRUE) + else (QHY_INCLUDE_DIR AND QHY_LIBRARIES) + set(QHY_FOUND FALSE) + endif(QHY_INCLUDE_DIR AND QHY_LIBRARIES) + + + if (QHY_FOUND) + if (NOT QHY_FIND_QUIETLY) + message(STATUS "Found QHY: ${QHY_LIBRARIES}") + endif (NOT QHY_FIND_QUIETLY) + else (QHY_FOUND) + if (QHY_FIND_REQUIRED) + message(FATAL_ERROR "QHY not found. Please install libqhy http://www.indilib.org") + endif (QHY_FIND_REQUIRED) + endif (QHY_FOUND) + + mark_as_advanced(QHY_INCLUDE_DIR QHY_LIBRARIES) + +endif (QHY_INCLUDE_DIR AND QHY_LIBRARIES) diff --git a/cmake_modules/FindQSI.cmake b/cmake_modules/FindQSI.cmake new file mode 100644 index 0000000..afaac6d --- /dev/null +++ b/cmake_modules/FindQSI.cmake @@ -0,0 +1,50 @@ +# - Try to find Quantum Scientific Imaging Library +# Once done this will define +# +# QSI_FOUND - system has QSI +# QSI_INCLUDE_DIR - the QSI include directory +# QSI_LIBRARIES - Link these to use QSI + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (QSI_INCLUDE_DIR AND QSI_LIBRARIES) + + # in cache already + set(QSI_FOUND TRUE) + message(STATUS "Found libqsiapi: ${QSI_LIBRARIES}") + +else (QSI_INCLUDE_DIR AND QSI_LIBRARIES) + + find_path(QSI_INCLUDE_DIR qsiapi.h + PATH_SUFFIXES qsiapi + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(QSI_LIBRARIES NAMES qsiapi + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(QSI_INCLUDE_DIR AND QSI_LIBRARIES) + set(QSI_FOUND TRUE) + else (QSI_INCLUDE_DIR AND QSI_LIBRARIES) + set(QSI_FOUND FALSE) + endif(QSI_INCLUDE_DIR AND QSI_LIBRARIES) + + + if (QSI_FOUND) + if (NOT QSI_FIND_QUIETLY) + message(STATUS "Found QSI: ${QSI_LIBRARIES}") + endif (NOT QSI_FIND_QUIETLY) + else (QSI_FOUND) + if (QSI_FIND_REQUIRED) + message(FATAL_ERROR "QSI not found. Please install libqsi http://www.indilib.org") + endif (QSI_FIND_REQUIRED) + endif (QSI_FOUND) + + mark_as_advanced(QSI_INCLUDE_DIR QSI_LIBRARIES) + +endif (QSI_INCLUDE_DIR AND QSI_LIBRARIES) diff --git a/cmake_modules/FindRT.cmake b/cmake_modules/FindRT.cmake new file mode 100644 index 0000000..db7c4de --- /dev/null +++ b/cmake_modules/FindRT.cmake @@ -0,0 +1,39 @@ +# FindRT.cmake - Try to find the RT library +# Once done this will define +# +# RT_FOUND - System has rt +# RT_INCLUDE_DIR - The rt include directory +# RT_LIBRARIES - The libraries needed to use rt +# RT_DEFINITIONS - Compiler switches required for using rt +# +# Also creates an import target called RT::RT + +find_path (RT_INCLUDE_DIR NAMES time.h + PATHS + /usr + /usr/local + /opt + PATH_SUFFIXES +) + +find_library(RT_LIBRARIES NAMES rt + PATHS + /usr + /usr/local + /opt +) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(rt DEFAULT_MSG RT_LIBRARIES RT_INCLUDE_DIR) + +mark_as_advanced(RT_INCLUDE_DIR RT_LIBRARIES) + +if (NOT TARGET RT::RT) + add_library(RT::RT INTERFACE IMPORTED) + + set_target_properties(RT::RT PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${RT_INCLUDE_DIR} + INTERFACE_LINK_LIBRARIES ${RT_LIBRARIES} + ) +endif() \ No newline at end of file diff --git a/cmake_modules/FindSBIG.cmake b/cmake_modules/FindSBIG.cmake new file mode 100644 index 0000000..db01e93 --- /dev/null +++ b/cmake_modules/FindSBIG.cmake @@ -0,0 +1,50 @@ +# - Try to find SBIG Universal Library +# Once done this will define +# +# SBIG_FOUND - system has SBIG +# SBIG_INCLUDE_DIR - the SBIG include directory +# SBIG_LIBRARIES - Link these to use SBIG + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (SBIG_INCLUDE_DIR AND SBIG_LIBRARIES) + + # in cache already + set(SBIG_FOUND TRUE) + message(STATUS "Found libsbig: ${SBIG_LIBRARIES}") + +else (SBIG_INCLUDE_DIR AND SBIG_LIBRARIES) + + find_path(SBIG_INCLUDE_DIR sbigudrv.h + PATH_SUFFIXES libsbig + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(SBIG_LIBRARIES NAMES sbig + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(SBIG_INCLUDE_DIR AND SBIG_LIBRARIES) + set(SBIG_FOUND TRUE) + else (SBIG_INCLUDE_DIR AND SBIG_LIBRARIES) + set(SBIG_FOUND FALSE) + endif(SBIG_INCLUDE_DIR AND SBIG_LIBRARIES) + + + if (SBIG_FOUND) + if (NOT SBIG_FIND_QUIETLY) + message(STATUS "Found SBIG: ${SBIG_LIBRARIES}") + endif (NOT SBIG_FIND_QUIETLY) + else (SBIG_FOUND) + if (SBIG_FIND_REQUIRED) + message(FATAL_ERROR "SBIG not found. Please install SBIG Library http://www.indilib.org") + endif (SBIG_FIND_REQUIRED) + endif (SBIG_FOUND) + + mark_as_advanced(SBIG_INCLUDE_DIR SBIG_LIBRARIES) + +endif (SBIG_INCLUDE_DIR AND SBIG_LIBRARIES) diff --git a/cmake_modules/FindSTARSHOOTG.cmake b/cmake_modules/FindSTARSHOOTG.cmake new file mode 100644 index 0000000..3551be8 --- /dev/null +++ b/cmake_modules/FindSTARSHOOTG.cmake @@ -0,0 +1,49 @@ +# - Try to find Starshoot Camera Library +# Once done this will define +# +# STARSHOOTG_FOUND - system has Starshoot +# STARSHOOTG_INCLUDE_DIR - the Starshoot include directory +# STARSHOOTG_LIBRARIES - Link these to use Starshoot + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (STARSHOOTG_INCLUDE_DIR AND STARSHOOTG_LIBRARIES) + + # in cache already + set(STARSHOOTG_FOUND TRUE) + message(STATUS "Found libstarshootg: ${STARSHOOTG_LIBRARIES}") + +else (STARSHOOTG_INCLUDE_DIR AND STARSHOOTG_LIBRARIES) + + find_path(STARSHOOTG_INCLUDE_DIR starshootg.h + PATH_SUFFIXES libstarshootg + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(STARSHOOTG_LIBRARIES NAMES starshootg + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(STARSHOOTG_INCLUDE_DIR AND STARSHOOTG_LIBRARIES) + set(STARSHOOTG_FOUND TRUE) + else (STARSHOOTG_INCLUDE_DIR AND STARSHOOTG_LIBRARIES) + set(STARSHOOTG_FOUND FALSE) + endif(STARSHOOTG_INCLUDE_DIR AND STARSHOOTG_LIBRARIES) + + if (STARSHOOTG_FOUND) + if (NOT STARSHOOTG_FIND_QUIETLY) + message(STATUS "Found StarshootG: ${STARSHOOTG_LIBRARIES}") + endif (NOT STARSHOOTG_FIND_QUIETLY) + else (STARSHOOTG_FOUND) + if (STARSHOOTG_FIND_REQUIRED) + message(FATAL_ERROR "StarshootG not found. Please install StarshootG Library http://www.indilib.org") + endif (STARSHOOTG_FIND_REQUIRED) + endif (STARSHOOTG_FOUND) + + mark_as_advanced(STARSHOOTG_INCLUDE_DIR STARSHOOTG_LIBRARIES) + +endif (STARSHOOTG_INCLUDE_DIR AND STARSHOOTG_LIBRARIES) diff --git a/cmake_modules/FindSV305.cmake b/cmake_modules/FindSV305.cmake new file mode 100644 index 0000000..e5ffcaa --- /dev/null +++ b/cmake_modules/FindSV305.cmake @@ -0,0 +1,52 @@ +# - Try to find SV305 Library +# Once done this will define +# +# SV305_FOUND - system has QHY +# SV305_INCLUDE_DIR - the QHY include directory +# SV305_LIBRARIES - Link these to use QHY + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (SV305_INCLUDE_DIR AND SV305_LIBRARIES) + + # in cache already + set(SV305_FOUND TRUE) + message(STATUS "Found libsv305: ${SV305_LIBRARIES}") + +else (SV305_INCLUDE_DIR AND SV305_LIBRARIES) + + # find headers + find_path(SV305_INCLUDE_DIR NAMES SVBCameraSDK.h + PATH_SUFFIXES libsv305 + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + # find libraries + find_library(SV305_LIBRARIES NAMES SVBCameraSDK + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(SV305_INCLUDE_DIR AND SV305_LIBRARIES) + set(SV305_FOUND TRUE) + else (SV305_INCLUDE_DIR AND SV305_LIBRARIES) + set(SV305_FOUND FALSE) + endif(SV305_INCLUDE_DIR AND SV305_LIBRARIES) + + + if (SV305_FOUND) + if (NOT SV305_FIND_QUIETLY) + message(STATUS "Found SV305 libraries : ${SV305_LIBRARIES}") + endif (NOT SV305_FIND_QUIETLY) + else (SV305_FOUND) + if (SV305_FIND_REQUIRED) + message(FATAL_ERROR "SV305 libraries not found. Please install libsv305 http://www.indilib.org") + endif (SV305_FIND_REQUIRED) + endif (SV305_FOUND) + + mark_as_advanced(SV305_INCLUDE_DIR SV305_LIBRARIES) + +endif (SV305_INCLUDE_DIR AND SV305_LIBRARIES) diff --git a/cmake_modules/FindTIFFXX.cmake b/cmake_modules/FindTIFFXX.cmake new file mode 100644 index 0000000..e478c05 --- /dev/null +++ b/cmake_modules/FindTIFFXX.cmake @@ -0,0 +1,41 @@ +# - Try to find TIFFXX Library +# Once done this will define +# +# TIFXX_LIBRARY - Link these to use TIFFXX + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (TIFFXX_LIBRARY) + + # in cache already + set(TIFFXX_FOUND TRUE) + message(STATUS "Found libtiffxx: ${TIFFXX_LIBRARY}") + +else (TIFFXX_LIBRARY) + + find_library(TIFFXX_LIBRARY NAMES tiffxx + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(TIFFXX_LIBRARY) + set(TIFFXX_FOUND TRUE) + else (TIFFXX_LIBRARY) + set(TIFFXX_FOUND FALSE) + endif(TIFFXX_LIBRARY) + + if (TIFFXX_FOUND) + if (NOT TIFFXX_FIND_QUIETLY) + message(STATUS "Found tiffxx: ${TIFFXX_LIBRARY}") + endif (NOT TIFFXX_FIND_QUIETLY) + else (TIFFXX_FOUND) + if (TIFFXX_FIND_REQUIRED) + message(FATAL_ERROR "tiffxx is not found. Please install it first.") + endif (TIFFXX_FIND_REQUIRED) + endif (TIFFXX_FOUND) + + mark_as_advanced(TIFFXX_LIBRARY) + +endif (TIFFXX_LIBRARY) diff --git a/cmake_modules/FindTOUPCAM.cmake b/cmake_modules/FindTOUPCAM.cmake new file mode 100644 index 0000000..626c3a5 --- /dev/null +++ b/cmake_modules/FindTOUPCAM.cmake @@ -0,0 +1,50 @@ +# - Try to find Toupcam Camera Library +# Once done this will define +# +# TOUPCAM_FOUND - system has Toupcam +# TOUPCAM_INCLUDE_DIR - the Toupcam include directory +# TOUPCAM_LIBRARIES - Link these to use Toupcam + +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (TOUPCAM_INCLUDE_DIR AND TOUPCAM_LIBRARIES) + + # in cache already + set(TOUPCAM_FOUND TRUE) + message(STATUS "Found libsbig: ${TOUPCAM_LIBRARIES}") + +else (TOUPCAM_INCLUDE_DIR AND TOUPCAM_LIBRARIES) + + find_path(TOUPCAM_INCLUDE_DIR toupcam.h + PATH_SUFFIXES libtoupcam + ${_obIncDir} + ${GNUWIN32_DIR}/include + ) + + find_library(TOUPCAM_LIBRARIES NAMES toupcam + PATHS + ${_obLinkDir} + ${GNUWIN32_DIR}/lib + ) + + if(TOUPCAM_INCLUDE_DIR AND TOUPCAM_LIBRARIES) + set(TOUPCAM_FOUND TRUE) + else (TOUPCAM_INCLUDE_DIR AND TOUPCAM_LIBRARIES) + set(TOUPCAM_FOUND FALSE) + endif(TOUPCAM_INCLUDE_DIR AND TOUPCAM_LIBRARIES) + + + if (TOUPCAM_FOUND) + if (NOT TOUPCAM_FIND_QUIETLY) + message(STATUS "Found Toupcam: ${TOUPCAM_LIBRARIES}") + endif (NOT TOUPCAM_FIND_QUIETLY) + else (TOUPCAM_FOUND) + if (TOUPCAM_FIND_REQUIRED) + message(FATAL_ERROR "Toupcam not found. Please install Toupcam Library http://www.indilib.org") + endif (TOUPCAM_FIND_REQUIRED) + endif (TOUPCAM_FOUND) + + mark_as_advanced(TOUPCAM_INCLUDE_DIR TOUPCAM_LIBRARIES) + +endif (TOUPCAM_INCLUDE_DIR AND TOUPCAM_LIBRARIES) diff --git a/cmake_modules/FindUSB1.cmake b/cmake_modules/FindUSB1.cmake new file mode 100644 index 0000000..0e155b4 --- /dev/null +++ b/cmake_modules/FindUSB1.cmake @@ -0,0 +1,83 @@ +# - Try to find libusb-1.0 +# Once done this will define +# +# USB1_FOUND - system has libusb-1.0 +# USB1_INCLUDE_DIRS - the libusb-1.0 include directories +# USB1_LIBRARIES - Link these to use libusb-1.0 +# USB1_DEFINITIONS - Compiler switches required for using libusb-1.0 +# +# USB1_HAS_LIBUSB_ERROR_NAME - defined when libusb-1.0 has libusb_error_name() + +#============================================================================= +# Copyright (c) 2017 Pino Toscano +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +find_package(PkgConfig) +pkg_check_modules(PC_LIBUSB1 QUIET libusb-1.0) + +find_path(USB1_INCLUDE_DIR + NAMES + libusb.h + HINTS + ${PC_LIBUSB1_INCLUDE_DIRS} + PATH_SUFFIXES + libusb-1.0 +) + +find_library(USB1_LIBRARY + NAMES + ${PC_LIBUSB1_LIBRARIES} + usb-1.0 + HINTS + ${PC_LIBUSB1_LIBRARY_DIRS} +) + +set(USB1_INCLUDE_DIRS ${USB1_INCLUDE_DIR}) +set(USB1_LIBRARIES ${USB1_LIBRARY}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(USB1 + FOUND_VAR + USB1_FOUND + REQUIRED_VARS + USB1_LIBRARY + USB1_INCLUDE_DIR + VERSION_VAR + PC_LIBUSB1_VERSION +) + +mark_as_advanced(USB1_INCLUDE_DIRS USB1_LIBRARIES) + +if(USB1_FOUND) + include(CheckCXXSourceCompiles) + include(CMakePushCheckState) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_INCLUDES ${USB1_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_LIBRARIES ${USB1_LIBRARIES}) + check_cxx_source_compiles("#include + int main() { libusb_error_name(0); return 0; }" USB1_HAS_LIBUSB_ERROR_NAME) + cmake_pop_check_state() +endif() diff --git a/cmake_modules/FindVorbis.cmake b/cmake_modules/FindVorbis.cmake new file mode 100644 index 0000000..d5e273e --- /dev/null +++ b/cmake_modules/FindVorbis.cmake @@ -0,0 +1,32 @@ +# - Find vorbis +# Find the native vorbis includes and libraries +# +# VORBIS_INCLUDE_DIR - where to find vorbis.h, etc. +# VORBIS_LIBRARIES - List of libraries when using vorbis(file). +# VORBIS_FOUND - True if vorbis found. + +if(VORBIS_INCLUDE_DIR) + # Already in cache, be silent + set(VORBIS_FIND_QUIETLY TRUE) +endif(VORBIS_INCLUDE_DIR) + +find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h) + +find_library(OGG_LIBRARY NAMES ogg) +find_library(VORBIS_LIBRARY NAMES vorbis) +find_library(VORBISFILE_LIBRARY NAMES vorbisfile) + +# Handle the QUIETLY and REQUIRED arguments and set VORBIS_FOUND to TRUE if +# all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(VORBIS DEFAULT_MSG + VORBIS_INCLUDE_DIR OGG_LIBRARY VORBIS_LIBRARY VORBIS_LIBRARY) + +if(VORBIS_FOUND) + set(VORBIS_LIBRARIES ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY}) +else(VORBIS_FOUND) + set(VORBIS_LIBRARIES) +endif(VORBIS_FOUND) + +mark_as_advanced(VORBIS_INCLUDE_DIR) +mark_as_advanced(OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY) diff --git a/cmake_modules/InstallImported.cmake b/cmake_modules/InstallImported.cmake new file mode 100644 index 0000000..740753c --- /dev/null +++ b/cmake_modules/InstallImported.cmake @@ -0,0 +1,92 @@ + +function (install_imported) + + cmake_parse_arguments (ARG "" "DESTINATION" "TARGETS" ${ARGN}) + + if (NOT DEFINED ARG_DESTINATION) + message (FATAL_ERROR "DESTINATION not defined") + endif () + + foreach (target ${ARG_TARGETS}) + + get_target_property (location ${target} LOCATION) + get_target_property (version ${target} VERSION) + get_target_property (soversion ${target} SOVERSION) + get_target_property (output_name ${target} OUTPUT_NAME) + get_target_property (suffix ${target} SUFFIX) + get_target_property (type ${target} TYPE) + + if (NOT ${type} STREQUAL "SHARED_LIBRARY") + message (FATAL_ERROR "install_imported: ${type} not supported") + endif () + + if (${location} STREQUAL "${target}-NOTFOUND") + return () + endif () + + if (NOT ${version} STREQUAL "version-NOTFOUND") + set (version ".${version}") + else () + set (version "") + endif () + + if (NOT ${soversion} STREQUAL "soversion-NOTFOUND") + set (soversion ".${soversion}") + else () + set (soversion "") + endif () + + if (${output_name} STREQUAL "output_name-NOTFOUND") + set (output_name ${target}) + endif () + + set (name_noversion "${CMAKE_SHARED_LIBRARY_PREFIX}${output_name}${CMAKE_SHARED_LIBRARY_SUFFIX}") + + if (APPLE) + set (name_version "${CMAKE_SHARED_LIBRARY_PREFIX}${output_name}${version}${CMAKE_SHARED_LIBRARY_SUFFIX}") + set (name_soversion "${CMAKE_SHARED_LIBRARY_PREFIX}${output_name}${soversion}${CMAKE_SHARED_LIBRARY_SUFFIX}") + else () + set (name_version "${CMAKE_SHARED_LIBRARY_PREFIX}${output_name}${CMAKE_SHARED_LIBRARY_SUFFIX}${version}") + set (name_soversion "${CMAKE_SHARED_LIBRARY_PREFIX}${output_name}${CMAKE_SHARED_LIBRARY_SUFFIX}${soversion}") + endif () + + if (NOT IS_ABSOLUTE ${location}) + set (location ${CMAKE_CURRENT_SOURCE_DIR}/${location}) + endif () + + if (NOT ${name_noversion} STREQUAL ${name_soversion}) + add_custom_command ( + OUTPUT ${name_noversion} + COMMAND ${CMAKE_COMMAND} -E create_symlink ${name_soversion} ${name_noversion} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + MAIN_DEPENDENCY ${name_soversion} + ) + + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${name_noversion} DESTINATION ${ARG_DESTINATION}) + endif () + + if (NOT ${name_soversion} STREQUAL ${name_version}) + add_custom_command ( + OUTPUT ${name_soversion} + COMMAND ${CMAKE_COMMAND} -E create_symlink ${name_version} ${name_soversion} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + MAIN_DEPENDENCY ${name_version} + ) + + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${name_soversion} DESTINATION ${ARG_DESTINATION}) + endif () + + add_custom_command ( + OUTPUT ${name_version} + COMMAND ${CMAKE_COMMAND} -E copy "${location}" "${CMAKE_CURRENT_BINARY_DIR}/${name_version}" + MAIN_DEPENDENCY ${location} + ) + + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${name_version} DESTINATION ${ARG_DESTINATION}) + + add_custom_target( + imported_${output_name} ALL + DEPENDS ${name_version} ${name_noversion} ${name_soversion} + ) + + endforeach () + +endfunction () diff --git a/cmake_modules/UnityBuild.cmake b/cmake_modules/UnityBuild.cmake new file mode 100644 index 0000000..7c133f1 --- /dev/null +++ b/cmake_modules/UnityBuild.cmake @@ -0,0 +1,158 @@ +# +# Copyright (c) 2009-2012 Christoph Heindl +# Copyright (c) 2015 Csaba Kertész (csaba.kertesz@gmail.com) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +MACRO (COMMIT_UNITY_FILE UNITY_FILE FILE_CONTENT) + SET(DIRTY FALSE) + # Check if the build file exists + SET(OLD_FILE_CONTENT "") + IF (NOT EXISTS ${${UNITY_FILE}} AND NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${${UNITY_FILE}}) + SET(DIRTY TRUE) + ELSE () + # Check the file content + FILE(STRINGS ${${UNITY_FILE}} OLD_FILE_CONTENT) + STRING(REPLACE ";" "" OLD_FILE_CONTENT "${OLD_FILE_CONTENT}") + STRING(REPLACE "\n" "" NEW_CONTENT "${${FILE_CONTENT}}") + STRING(COMPARE EQUAL "${OLD_FILE_CONTENT}" "${NEW_CONTENT}" EQUAL_CHECK) + IF (NOT EQUAL_CHECK EQUAL 1) + SET(DIRTY TRUE) + ENDIF () + ENDIF () + IF (DIRTY MATCHES TRUE) + MESSAGE(STATUS "Write Unity Build file: " ${${UNITY_FILE}}) + FILE(WRITE ${${UNITY_FILE}} "${${FILE_CONTENT}}") + ENDIF () + # Create a dummy copy of the unity file to trigger CMake reconfigure if it is deleted. + SET(UNITY_FILE_PATH "") + SET(UNITY_FILE_NAME "") + GET_FILENAME_COMPONENT(UNITY_FILE_PATH ${${UNITY_FILE}} PATH) + GET_FILENAME_COMPONENT(UNITY_FILE_NAME ${${UNITY_FILE}} NAME) + CONFIGURE_FILE(${${UNITY_FILE}} ${UNITY_FILE_PATH}/CMakeFiles/${UNITY_FILE_NAME}.dummy) +ENDMACRO () + +MACRO (ENABLE_UNITY_BUILD TARGET_NAME SOURCE_VARIABLE_NAME UNIT_SIZE EXTENSION) + # Limit is zero based conversion of unit_size + MATH(EXPR LIMIT ${UNIT_SIZE}-1) + SET(FILES ${SOURCE_VARIABLE_NAME}) + # Effectivly ignore the source files from the build, but keep track them for changes. + SET_SOURCE_FILES_PROPERTIES(${${FILES}} PROPERTIES HEADER_FILE_ONLY true) + # Counts the number of source files up to the threshold + SET(COUNTER ${LIMIT}) + # Have one or more unity build files + SET(FILE_NUMBER 0) + SET(BUILD_FILE "") + SET(BUILD_FILE_CONTENT "") + SET(UNITY_BUILD_FILES "") + SET(_DEPS "") + + FOREACH (SOURCE_FILE ${${FILES}}) + IF (COUNTER EQUAL LIMIT) + SET(_DEPS "") + # Write the actual Unity Build file + IF (NOT ${BUILD_FILE} STREQUAL "" AND NOT ${BUILD_FILE_CONTENT} STREQUAL "") + COMMIT_UNITY_FILE(BUILD_FILE BUILD_FILE_CONTENT) + ENDIF () + SET(UNITY_BUILD_FILES ${UNITY_BUILD_FILES} ${BUILD_FILE}) + # Set the variables for the current Unity Build file + SET(BUILD_FILE ${CMAKE_CURRENT_BINARY_DIR}/unitybuild_${FILE_NUMBER}_${TARGET_NAME}.${EXTENSION}) + SET(BUILD_FILE_CONTENT "// Unity Build file generated by CMake\n") + MATH(EXPR FILE_NUMBER ${FILE_NUMBER}+1) + SET(COUNTER 0) + ENDIF () + # Add source path to the file name if it is not there yet. + SET(FINAL_SOURCE_FILE "") + SET(SOURCE_PATH "") + GET_FILENAME_COMPONENT(SOURCE_PATH ${SOURCE_FILE} PATH) + IF (SOURCE_PATH STREQUAL "" OR NOT EXISTS ${SOURCE_FILE}) + SET(FINAL_SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE}) + ELSE () + SET(FINAL_SOURCE_FILE ${SOURCE_FILE}) + ENDIF () + # Treat only the existing files or moc_*.cpp files + STRING(FIND ${SOURCE_FILE} "moc_" MOC_POS) + IF (EXISTS ${FINAL_SOURCE_FILE} OR MOC_POS GREATER -1) + # Add md5 hash of the source file (except moc files) to the build file content + IF (MOC_POS LESS 0) + SET(MD5_HASH "") + FILE(MD5 ${FINAL_SOURCE_FILE} MD5_HASH) + SET(BUILD_FILE_CONTENT "${BUILD_FILE_CONTENT}// md5: ${MD5_HASH}\n") + ENDIF () + # Add the source file to the build file content + IF (MOC_POS GREATER -1) + SET(BUILD_FILE_CONTENT "${BUILD_FILE_CONTENT}#include <${SOURCE_FILE}>\n") + ELSE () + SET(BUILD_FILE_CONTENT "${BUILD_FILE_CONTENT}#include <${FINAL_SOURCE_FILE}>\n") + ENDIF () + # Add the source dependencies to the Unity Build file + GET_SOURCE_FILE_PROPERTY(_FILE_DEPS ${SOURCE_FILE} OBJECT_DEPENDS) + + IF (_FILE_DEPS) + SET(_DEPS ${_DEPS} ${_FILE_DEPS}) + SET_SOURCE_FILES_PROPERTIES(${BUILD_FILE} PROPERTIES OBJECT_DEPENDS "${_DEPS}") + ENDIF() + # Keep counting up to the threshold. Increment counter. + MATH(EXPR COUNTER ${COUNTER}+1) + ENDIF () + ENDFOREACH () + # Write out the last Unity Build file + IF (NOT ${BUILD_FILE} STREQUAL "" AND NOT ${BUILD_FILE_CONTENT} STREQUAL "") + COMMIT_UNITY_FILE(BUILD_FILE BUILD_FILE_CONTENT) + ENDIF () + SET(UNITY_BUILD_FILES ${UNITY_BUILD_FILES} ${BUILD_FILE}) + SET(${SOURCE_VARIABLE_NAME} ${${SOURCE_VARIABLE_NAME}} ${UNITY_BUILD_FILES}) +ENDMACRO () + +MACRO (UNITY_GENERATE_MOC TARGET_NAME SOURCES HEADERS) + SET(NEW_SOURCES "") + FOREACH (HEADER_FILE ${${HEADERS}}) + IF (NOT EXISTS ${HEADER_FILE}) + MESSAGE(FATAL_ERROR "Header file does not exist (mocing): ${HEADER_FILE}") + ENDIF () + FILE(READ ${HEADER_FILE} FILE_CONTENT) + STRING(FIND "${FILE_CONTENT}" "Q_OBJECT" QOBJECT_POS) + STRING(FIND "${FILE_CONTENT}" "Q_SLOTS" QSLOTS_POS) + STRING(FIND "${FILE_CONTENT}" "Q_SIGNALS" QSIGNALS_POS) + STRING(FIND "${FILE_CONTENT}" "QObject" OBJECT_POS) + STRING(FIND "${FILE_CONTENT}" "slots" SLOTS_POS) + STRING(FIND "${FILE_CONTENT}" "signals" SIGNALS_POS) + IF (QOBJECT_POS GREATER 0 OR OBJECT_POS GREATER 0 OR QSLOTS_POS GREATER 0 OR Q_SIGNALS GREATER 0 OR + SLOTS_POS GREATER 0 OR SIGNALS GREATER 0) + # Generate the moc filename + GET_FILENAME_COMPONENT(HEADER_BASENAME ${HEADER_FILE} NAME_WE) + SET(MOC_FILENAME "moc_${HEADER_BASENAME}.cpp") + SET(NEW_SOURCES ${NEW_SOURCES} ; "${CMAKE_CURRENT_BINARY_DIR}/${MOC_FILENAME}") + ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${MOC_FILENAME}" + DEPENDS ${HEADER_FILE} + COMMAND ${QT_MOC_EXECUTABLE} ${HEADER_FILE} -o "${CMAKE_CURRENT_BINARY_DIR}/${MOC_FILENAME}") + ENDIF () + ENDFOREACH () + IF (NEW_SOURCES) + SET_SOURCE_FILES_PROPERTIES(${NEW_SOURCES} PROPERTIES GENERATED TRUE) + SET(${SOURCES} ${${SOURCES}} ; ${NEW_SOURCES}) + ENDIF () +ENDMACRO () diff --git a/indi-celestronaux/.gitignore b/indi-celestronaux/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/indi-celestronaux/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/indi-celestronaux/CMakeLists.txt b/indi-celestronaux/CMakeLists.txt new file mode 100644 index 0000000..9a3cd27 --- /dev/null +++ b/indi-celestronaux/CMakeLists.txt @@ -0,0 +1,33 @@ +########### Celestron AUX INDI driver ############## +PROJECT(indi-celestronaux C CXX) +cmake_minimum_required(VERSION 3.0) + +include(GNUInstallDirs) + +LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/") +LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake_modules/") + +find_package(INDI REQUIRED) +find_package(Nova REQUIRED) +find_package(ZLIB REQUIRED) +find_package(GSL REQUIRED) + +set(CAUX_VERSION_MAJOR 1) +set(CAUX_VERSION_MINOR 2) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h ) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/indi_celestronaux.xml.cmake ${CMAKE_CURRENT_BINARY_DIR}/indi_celestronaux.xml ) + +include_directories( ${CMAKE_CURRENT_BINARY_DIR}) +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}) +include_directories( ${INDI_INCLUDE_DIR}) +include_directories( ${NOVA_INCLUDE_DIR}) +include_directories( ${EV_INCLUDE_DIR}) + +include(CMakeCommon) + +add_executable(indi_celestron_aux auxproto.cpp celestronaux.cpp) +target_link_libraries(indi_celestron_aux ${INDI_LIBRARIES} ${NOVA_LIBRARIES} ${GSL_LIBRARIES}) +install(TARGETS indi_celestron_aux RUNTIME DESTINATION bin) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/indi_celestronaux.xml DESTINATION ${INDI_DATA_DIR}) diff --git a/indi-celestronaux/README.md b/indi-celestronaux/README.md new file mode 100644 index 0000000..0b831d8 --- /dev/null +++ b/indi-celestronaux/README.md @@ -0,0 +1,102 @@ +Celestron AUX protocol driver +------------------------------------- + +Authors: Paweł T. Jochym + Fabrizio Pollastri + +*Do not use this driver unattended! This is BETA software! Always have your power switch ready! It is NOT SUITABLE for autonomous operation yet!* +*There are no slew limits implemented at this stage.* + +This is eqmod-style driver for the NexStar and other Celestron AUX-protocol +mounts. It works over serial link to PC/AUX ports or HC serial port +and over WiFi to the NexStar-Evolution or SkyFi-equipped mount. + +The driver is in the beta stage. +It is functional and should work as intended but it is not complete. +I am using it and will be happy to help any brave testers. +I of course welcome any feedback/contribution. + +What works: +- N-star alignment (with INDI alignment module) +- Basic tracking, slew, park/unpark +- GPS simulation. If you have HC connected and you have active gps driver + it can simulate Celestron GPS device and serve GPS data to HC. Works quite + nicely on RaspberryPi with a GPS module. You can actually use it as + a replacement for the Celestron GPS. +- Cordwrap control + +What does not work/is not implemented: +- Joystick control +- Slew limits +- HC interaction (tracking HC motor commands to function as joystick) +- Probably many other things + +Install +------- + +The driver is not included in the PPA distribution yet - due to its beta +state. So to use it you need to compile it from the source yourself. + +You can make a stand-alone compilation or build the debian packages for your +system. It should be fairly easy. Let me know if something in the following +guide is wrong or if you have problem with compiling the driver. + +Get the source +============== + +You can get the source from the SVN repository of the system on sourceforge +maintained by the INDI project (see the website of the project) or get it +from the github mirror of the sourceforge repository maintained by the author +of this driver. Both will do fine. The github repository lets you track the +development of the driver more closely in the nse branch of the repository, +since only master branch is uploaded back to the upstream SVN repository. + +- Make some working directory and change into it. +- Get the source from the github master branch - it takes a while + the repo is 64MB in size. + +Compiling on any linux system +============================= + +The compilation is simple. You will need indi libraries installed. The best way +is to install libindi-dev package from the PPA. You may also want to have +indi-gpsd and gpsd packages installed (not strictly required). If you cannot use +the PPA you need to install libindi-dev from your distribution or compile the +indi libraries yourself using instructions from the INDI website. I have not +tested the backward compatibility but the driver should compile and work at +least with the 1.8.4 version of the library. My recommendation: use PPA if you +can. To compile the driver you will need also: cmake, cdbs, libindi-dev, +libnova-dev, zlib1g-dev. Run following commands (you can select other install +prefix): + +```sh +mkdir -p ~/Projects/build/indi-caux +cd ~/Projects/build/indi-caux +cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Debug ~/Projects/indi-3rdparty/indi-celestronaux +make +``` +You can run `make install` optionally at the end if you like to have the driver +properly installed. + + +Building debian/ubuntu packages +=============================== + +To build the debian package you will need the debian packaging tools: +`build-essential, devscripts, debhelper, fakeroot` + +Create `package` directory at the same level as indilib directory with the +cloned source. Then execute: + +```sh +mkdir -p ~/Projects/build/deb-indi-caux +cd ~/Projects/build/deb-indi-caux +cp -r ~/Projects/indi-3rdparty/indi-celestronaux . +cp -r ~/Projects/indi-3rdparty/debian//indi-celestronaux debian +cp -r ~/Projects/indi-3rdparty/cmake_modules indi-celestronaux/ +fakeroot debian/rules binary +fakeroot debian/rules clean +``` +this should produce two packages in the main build directory (above `package`), +which you can install with `sudo dpkg -i indi-celestronaux_*.deb`. + diff --git a/indi-celestronaux/auxproto.cpp b/indi-celestronaux/auxproto.cpp new file mode 100644 index 0000000..9891e10 --- /dev/null +++ b/indi-celestronaux/auxproto.cpp @@ -0,0 +1,467 @@ +/* + Celestron Aux Command + + Copyright (C) 2020 Paweł T. Jochym + Copyright (C) 2020 Fabrizio Pollastri + Copyright (C) 2021 Jasem Mutlaq + + 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 "auxproto.h" + +#include +#include +#include +#include +#include + +#define READ_TIMEOUT 1 // s +#define CTS_TIMEOUT 100 // ms +#define RTS_DELAY 50 // ms + +#define BUFFER_SIZE 512 +int MAX_CMD_LEN = 32; + +uint8_t AUXCommand::DEBUG_LEVEL = 0; +char AUXCommand::DEVICE_NAME[64] = {0}; +////////////////////////////////////////////////// +/////// Utility functions +////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void logBytes(unsigned char *buf, int n, const char *deviceName, uint32_t debugLevel) +{ + char hex_buffer[BUFFER_SIZE] = {0}; + for (int i = 0; i < n; i++) + sprintf(hex_buffer + 3 * i, "%02X ", buf[i]); + + if (n > 0) + hex_buffer[3 * n - 1] = '\0'; + + DEBUGFDEVICE(deviceName, debugLevel, "[%s]", hex_buffer); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void AUXCommand::logResponse() +{ + char hex_buffer[BUFFER_SIZE] = {0}, part1[BUFFER_SIZE] = {0}, part2[BUFFER_SIZE] = {0}, part3[BUFFER_SIZE] = {0}; + for (size_t i = 0; i < m_Data.size(); i++) + sprintf(hex_buffer + 3 * i, "%02X ", m_Data[i]); + + if (m_Data.size() > 0) + hex_buffer[3 * m_Data.size() - 1] = '\0'; + + const char * c = commandName(m_Command); + const char * s = moduleName(m_Source); + const char * d = moduleName(m_Destination); + + if (c != nullptr) + snprintf(part1, BUFFER_SIZE, "<%12s>", c); + else + snprintf(part1, BUFFER_SIZE, "<%02x>", m_Command); + + if (s != nullptr) + snprintf(part2, BUFFER_SIZE, "%5s ->", s); + else + snprintf(part2, BUFFER_SIZE, "%02x ->", m_Source); + + if (s != nullptr) + snprintf(part3, BUFFER_SIZE, "%5s", d); + else + snprintf(part3, BUFFER_SIZE, "%02x", m_Destination); + + if (m_Data.size() > 0) + DEBUGFDEVICE(DEVICE_NAME, DEBUG_LEVEL, "RES %s%s%s [%s]", part1, part2, part3, hex_buffer); + else + DEBUGFDEVICE(DEVICE_NAME, DEBUG_LEVEL, "RES %s%s%s", part1, part2, part3); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void AUXCommand::logCommand() +{ + char hex_buffer[BUFFER_SIZE] = {0}, part1[BUFFER_SIZE] = {0}, part2[BUFFER_SIZE] = {0}, part3[BUFFER_SIZE] = {0}; + for (size_t i = 0; i < m_Data.size(); i++) + sprintf(hex_buffer + 3 * i, "%02X ", m_Data[i]); + + if (m_Data.size() > 0) + hex_buffer[3 * m_Data.size() - 1] = '\0'; + + const char * c = commandName(m_Command); + const char * s = moduleName(m_Source); + const char * d = moduleName(m_Destination); + + if (c != nullptr) + snprintf(part1, BUFFER_SIZE, "<%12s>", c); + else + snprintf(part1, BUFFER_SIZE, "<%02x>", m_Command); + + if (s != nullptr) + snprintf(part2, BUFFER_SIZE, "%5s ->", s); + else + snprintf(part2, BUFFER_SIZE, "%02x ->", m_Source); + + if (s != nullptr) + snprintf(part3, BUFFER_SIZE, "%5s", d); + else + snprintf(part3, BUFFER_SIZE, "%02x", m_Destination); + + if (m_Data.size() > 0) + DEBUGFDEVICE(DEVICE_NAME, DEBUG_LEVEL, "CMD %s%s%s [%s]", part1, part2, part3, hex_buffer); + else + DEBUGFDEVICE(DEVICE_NAME, DEBUG_LEVEL, "CMD %s%s%s", part1, part2, part3); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void AUXCommand::setDebugInfo(const char *deviceName, uint8_t debugLevel) +{ + strncpy(DEVICE_NAME, deviceName, 64); + DEBUG_LEVEL = debugLevel; +} +//////////////////////////////////////////////// +////// AUXCommand class +//////////////////////////////////////////////// + +AUXCommand::AUXCommand() +{ + m_Data.reserve(MAX_CMD_LEN); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +AUXCommand::AUXCommand(const AUXBuffer &buf) +{ + m_Data.reserve(MAX_CMD_LEN); + parseBuf(buf); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +AUXCommand::AUXCommand(AUXCommands command, AUXTargets source, AUXTargets destination, const AUXBuffer &data) +{ + m_Command = command; + m_Source = source; + m_Destination = destination; + m_Data.reserve(MAX_CMD_LEN); + m_Data = data; + len = 3 + m_Data.size(); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +AUXCommand::AUXCommand(AUXCommands command, AUXTargets source, AUXTargets destination) +{ + m_Command = command; + m_Source = source; + m_Destination = destination; + m_Data.reserve(MAX_CMD_LEN); + len = 3 + m_Data.size(); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +const char * AUXCommand::commandName(AUXCommands command) const +{ + if (m_Source == GPS || m_Destination == GPS) + { + switch (command) + { + case GPS_GET_LAT: + return "GPS_GET_LAT"; + case GPS_GET_LONG: + return "GPS_GET_LONG"; + case GPS_GET_DATE: + return "GPS_GET_DATE"; + case GPS_GET_YEAR: + return "GPS_GET_YEAR"; + case GPS_GET_TIME: + return "GPS_GET_TIME"; + case GPS_TIME_VALID: + return "GPS_TIME_VALID"; + case GPS_LINKED: + return "GPS_LINKED"; + case GET_VER: + return "GET_VER"; + default : + return nullptr; + } + } + else + { + switch (command) + { + case MC_GET_POSITION: + return "MC_GET_POSITION"; + case MC_GOTO_FAST: + return "MC_GOTO_FAST"; + case MC_SET_POSITION: + return "MC_SET_POSITION"; + case MC_SET_POS_GUIDERATE: + return "MC_SET_POS_GUIDERATE"; + case MC_SET_NEG_GUIDERATE: + return "MC_SET_NEG_GUIDERATE"; + case MC_LEVEL_START: + return "MC_LEVEL_START"; + case MC_SLEW_DONE: + return "MC_SLEW_DONE"; + case MC_GOTO_SLOW: + return "MC_GOTO_SLOW"; + case MC_SEEK_INDEX: + return "MC_SEEK_INDEX"; + case MC_MOVE_POS: + return "MC_MOVE_POS"; + case MC_MOVE_NEG: + return "MC_MOVE_NEG"; + case MC_ENABLE_CORDWRAP: + return "MC_ENABLE_CORDWRAP"; + case MC_DISABLE_CORDWRAP: + return "MC_DISABLE_CORDWRAP"; + case MC_SET_CORDWRAP_POS: + return "MC_SET_CORDWRAP_POS"; + case MC_POLL_CORDWRAP: + return "MC_POLL_CORDWRAP"; + case MC_GET_CORDWRAP_POS: + return "MC_GET_CORDWRAP_POS"; + case GET_VER: + return "GET_VER"; + default : + return nullptr; + } + } +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +int AUXCommand::responseDataSize() +{ + if (m_Source == GPS || m_Destination == GPS) + { + switch (m_Command) + { + case GPS_GET_LAT: + case GPS_GET_LONG: + case GPS_GET_TIME: + return 3; + case GPS_GET_DATE: + case GPS_GET_YEAR: + case GET_VER: + return 2; + case GPS_TIME_VALID: + case GPS_LINKED: + return 1; + default : + return -1; + } + } + else + { + switch (m_Command) + { + case MC_GET_POSITION: + case MC_GET_CORDWRAP_POS: + return 3; + case GET_VER: + return 4; + case MC_SLEW_DONE: + case MC_SEEK_DONE: + case MC_LEVEL_DONE: + case MC_POLL_CORDWRAP: + return 1; + case MC_GOTO_FAST: + case MC_SET_POSITION: + case MC_SET_POS_GUIDERATE: + case MC_SET_NEG_GUIDERATE: + case MC_LEVEL_START: + case MC_GOTO_SLOW: + case MC_MOVE_POS: + case MC_MOVE_NEG: + case MC_ENABLE_CORDWRAP: + case MC_DISABLE_CORDWRAP: + case MC_SET_CORDWRAP_POS: + return 0; + case MC_SEEK_INDEX: + return -1; + default : + return -1; + } + } +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +const char * AUXCommand::moduleName(AUXTargets n) +{ + switch (n) + { + case ANY : + return "ANY"; + case MB : + return "MB"; + case HC : + return "HC"; + case HCP : + return "HC+"; + case AZM : + return "AZM"; + case ALT : + return "ALT"; + case APP : + return "APP"; + case GPS : + return "GPS"; + case WiFi: + return "WiFi"; + case BAT : + return "BAT"; + case CHG : + return "CHG"; + case LIGHT : + return "LIGHT"; + default : + return nullptr; + } +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void AUXCommand::fillBuf(AUXBuffer &buf) +{ + buf.resize(len + 3); + + buf[0] = 0x3b; + buf[1] = len; + buf[2] = m_Source; + buf[3] = m_Destination; + buf[4] = m_Command; + for (uint32_t i = 0; i < m_Data.size(); i++) + { + buf[i + 5] = m_Data[i]; + } + buf.back() = checksum(buf); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void AUXCommand::parseBuf(AUXBuffer buf) +{ + len = buf[1]; + m_Source = (AUXTargets)buf[2]; + m_Destination = (AUXTargets)buf[3]; + m_Command = (AUXCommands)buf[4]; + m_Data = AUXBuffer(buf.begin() + 5, buf.end() - 1); + valid = (checksum(buf) == buf.back()); + if (valid == false) + { + DEBUGFDEVICE(DEVICE_NAME, DEBUG_LEVEL, "Checksum error: %02x vs. %02x", checksum(buf), buf.back()); + }; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void AUXCommand::parseBuf(AUXBuffer buf, bool do_checksum) +{ + (void)do_checksum; + + len = buf[1]; + m_Source = (AUXTargets)buf[2]; + m_Destination = (AUXTargets)buf[3]; + m_Command = (AUXCommands)buf[4]; + if (buf.size() > 5) + m_Data = AUXBuffer(buf.begin() + 5, buf.end()); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +unsigned char AUXCommand::checksum(AUXBuffer buf) +{ + int l = buf[1]; + int cs = 0; + for (int i = 1; i < l + 2; i++) + { + cs += buf[i]; + } + return (unsigned char)(((~cs) + 1) & 0xFF); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// Return 8, 16, or 24bit value as dictacted by the data response size. +///////////////////////////////////////////////////////////////////////////////////// +uint32_t AUXCommand::getData() +{ + uint32_t value = 0; + switch (m_Data.size()) + { + case 3: + value = (m_Data[0] << 16) | (m_Data[1] << 8) | m_Data[2]; + break; + + case 2: + value = (m_Data[0] << 8) | m_Data[1]; + break; + + case 1: + value = m_Data[0]; + break; + } + + return value; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// Set encoder position in steps. +///////////////////////////////////////////////////////////////////////////////////// +void AUXCommand::setData(uint32_t value, uint8_t bytes) +{ + m_Data.resize(bytes); + switch (bytes) + { + case 1: + len = 4; + m_Data[0] = static_cast(value >> 0 & 0xff); + break; + case 2: + len = 5; + m_Data[1] = static_cast(value >> 0 & 0xff); + m_Data[0] = static_cast(value >> 8 & 0xff); + break; + + case 3: + default: + len = 6; + m_Data[2] = static_cast(value >> 0 & 0xff); + m_Data[1] = static_cast(value >> 8 & 0xff); + m_Data[0] = static_cast(value >> 16 & 0xff); + break; + } +} diff --git a/indi-celestronaux/auxproto.h b/indi-celestronaux/auxproto.h new file mode 100644 index 0000000..3593eee --- /dev/null +++ b/indi-celestronaux/auxproto.h @@ -0,0 +1,169 @@ +/* + Celestron Aux Command + + Copyright (C) 2020 Paweł T. Jochym + Copyright (C) 2020 Fabrizio Pollastri + Copyright (C) 2021 Jasem Mutlaq + + 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 +#include + +typedef std::vector AUXBuffer; + +enum AUXCommands +{ + MC_GET_POSITION = 0x01, + MC_GOTO_FAST = 0x02, + MC_SET_POSITION = 0x04, + MC_SET_POS_GUIDERATE = 0x06, + MC_SET_NEG_GUIDERATE = 0x07, + MC_LEVEL_START = 0x0b, + MC_LEVEL_DONE = 0x12, + MC_SLEW_DONE = 0x13, + MC_GOTO_SLOW = 0x17, + MC_SEEK_DONE = 0x18, + MC_SEEK_INDEX = 0x19, + MC_MOVE_POS = 0x24, + MC_MOVE_NEG = 0x25, + MC_AUX_GUIDE = 0x26, + MC_AUX_GUIDE_ACTIVE = 0x27, + MC_ENABLE_CORDWRAP = 0x38, + MC_DISABLE_CORDWRAP = 0x39, + MC_SET_CORDWRAP_POS = 0x3a, + MC_POLL_CORDWRAP = 0x3b, + MC_GET_CORDWRAP_POS = 0x3c, + MC_SET_AUTOGUIDE_RATE = 0x46, + MC_GET_AUTOGUIDE_RATE = 0x47, + GET_VER = 0xfe, + GPS_GET_LAT = 0x01, + GPS_GET_LONG = 0x02, + GPS_GET_DATE = 0x03, + GPS_GET_YEAR = 0x04, + GPS_GET_TIME = 0x33, + GPS_TIME_VALID = 0x36, + GPS_LINKED = 0x37 +}; + +enum AUXTargets +{ + ANY = 0x00, + MB = 0x01, + HC = 0x04, + HCP = 0x0d, + AZM = 0x10, + ALT = 0x11, + APP = 0x20, + GPS = 0xb0, + WiFi = 0xb5, + BAT = 0xb6, + CHG = 0xb7, + LIGHT = 0xbf +}; + +#define CAUX_DEFAULT_IP "1.2.3.4" +#define CAUX_DEFAULT_PORT 2000 + +void logBytes(unsigned char *buf, int n, const char *deviceName, uint32_t debugLevel); + +class AUXCommand +{ + public: + AUXCommand(); + AUXCommand(const AUXBuffer &buf); + AUXCommand(AUXCommands command, AUXTargets source, AUXTargets destination, const AUXBuffer &data); + AUXCommand(AUXCommands command, AUXTargets source, AUXTargets destination); + + /////////////////////////////////////////////////////////////////////////////// + /// Buffer Management + /////////////////////////////////////////////////////////////////////////////// + void fillBuf(AUXBuffer &buf); + void parseBuf(AUXBuffer buf); + void parseBuf(AUXBuffer buf, bool do_checksum); + + /////////////////////////////////////////////////////////////////////////////// + /// Getters + /////////////////////////////////////////////////////////////////////////////// + const AUXTargets &source() const + { + return m_Source; + } + const AUXTargets &destination() const + { + return m_Destination; + } + const AUXBuffer &data() const + { + return m_Data; + } + AUXCommands command() const + { + return m_Command; + } + size_t dataSize() const + { + return m_Data.size(); + } + const char * commandName() const + { + return commandName(m_Command); + } + + /////////////////////////////////////////////////////////////////////////////// + /// Set and Get data + /////////////////////////////////////////////////////////////////////////////// + /** + * @brief getData Parses data packet and convert it to a 32bit unsigned integer + * @param bytes How many bytes to interpret the data. + * @return + */ + uint32_t getData(); + void setData(uint32_t value, uint8_t bytes = 3); + + /////////////////////////////////////////////////////////////////////////////// + /// Check sum + /////////////////////////////////////////////////////////////////////////////// + uint8_t checksum(AUXBuffer buf); + + /////////////////////////////////////////////////////////////////////////////// + /// Logging + /////////////////////////////////////////////////////////////////////////////// + const char * commandName(AUXCommands command) const; + const char * moduleName(AUXTargets n); + int responseDataSize(); + void logResponse(); + void logCommand(); + static void setDebugInfo(const char *deviceName, uint8_t debugLevel); + + static uint8_t DEBUG_LEVEL; + static char DEVICE_NAME[64]; + + private: + uint8_t len {0}; + bool valid {false}; + + AUXCommands m_Command; + AUXTargets m_Source, m_Destination; + AUXBuffer m_Data; + + + +}; diff --git a/indi-celestronaux/celestronaux.cpp b/indi-celestronaux/celestronaux.cpp new file mode 100644 index 0000000..ad8afe9 --- /dev/null +++ b/indi-celestronaux/celestronaux.cpp @@ -0,0 +1,2907 @@ +/* + Celestron Aux Mount Driver. + + Copyright (C) 2020 Paweł T. Jochym + Copyright (C) 2020 Fabrizio Pollastri + Copyright (C) 2020-2022 Jasem Mutlaq + + 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 + + JM 2022.07.07: Added Wedge support. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "celestronaux.h" +#include "config.h" + +#define DEBUG_PID + +using namespace INDI::AlignmentSubsystem; + +static std::unique_ptr telescope_caux(new CelestronAUX()); + +double anglediff(double a, double b) +{ + // Signed angle difference + double d; + b = fmod(b, 360.0); + a = fmod(a, 360.0); + d = fmod(a - b + 360.0, 360.0); + if (d > 180) + d = 360.0 - d; + return std::abs(d) * ((a - b >= 0 && a - b <= 180) || (a - b <= -180 && a - b >= -360) ? 1 : -1); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +CelestronAUX::CelestronAUX() + : ScopeStatus(IDLE), + DBG_CAUX(INDI::Logger::getInstance().addDebugLevel("AUX", "CAUX")), + DBG_SERIAL(INDI::Logger::getInstance().addDebugLevel("Serial", "CSER")) +{ + setVersion(CAUX_VERSION_MAJOR, CAUX_VERSION_MINOR); + SetTelescopeCapability(TELESCOPE_CAN_PARK | + TELESCOPE_CAN_SYNC | + TELESCOPE_CAN_GOTO | + TELESCOPE_CAN_ABORT | + TELESCOPE_HAS_TIME | + TELESCOPE_HAS_LOCATION | + TELESCOPE_CAN_CONTROL_TRACK | + TELESCOPE_HAS_TRACK_MODE | + TELESCOPE_HAS_TRACK_RATE + , 8); + + //Both communication available, Serial and network (tcp/ip). + setTelescopeConnection(CONNECTION_TCP | CONNECTION_SERIAL); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +CelestronAUX::~CelestronAUX() +{ +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::Handshake() +{ + LOGF_DEBUG("CAUX: connect %d (%s)", PortFD, (getActiveConnection() == serialConnection) ? "serial" : "net"); + if (PortFD > 0) + { + if (getActiveConnection() == serialConnection) + { + if (PortTypeSP[PORT_AUX_PC].getState() == ISS_ON) + { + serialConnection->setDefaultBaudRate(Connection::Serial::B_19200); + if (!tty_set_speed(B19200)) + return false; + m_IsRTSCTS = detectRTSCTS(); + } + else + { + serialConnection->setDefaultBaudRate(Connection::Serial::B_9600); + if (!tty_set_speed(B9600)) + { + LOG_ERROR("Cannot set serial speed to 9600 baud."); + return false; + } + + // wait for speed to settle + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + LOG_INFO("Setting serial speed to 9600 baud."); + + // detect if connectd to HC port or to mount USB port + // ask for HC version + char version[10]; + if ((m_isHandController = detectHC(version, 10))) + LOGF_INFO("Detected Hand Controller (v%s) serial connection.", version); + else + LOG_INFO("Detected Mount USB serial connection."); + } + } + else + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + // read firmware version, if read ok, detected scope + LOG_DEBUG("Communicating with mount motor controllers..."); + if (getVersion(AZM) && getVersion(ALT)) + { + LOG_INFO("Got response from target ALT or AZM."); + } + else + { + LOG_ERROR("Got no response from target ALT or AZM."); + LOG_ERROR("Cannot continue without connection to motor controllers."); + return false; + } + + LOG_DEBUG("Connection ready. Starting Processing."); + + // set mount type to alignment subsystem + //SetApproximateMountAlignmentFromMountType(static_cast(MountTypeSP.findOnSwitchIndex())); + // tell the alignment math plugin to reinitialise + Initialise(this); + + // update cordwrap position at each init of the alignment subsystem + if (isConnected()) + syncCoordWrapPosition(); + + return true; + } + else + { + return false ; + } + +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::Disconnect() +{ + Abort(); + return INDI::Telescope::Disconnect(); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +const char *CelestronAUX::getDefaultName() +{ + return "Celestron AUX"; +} + +///////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////// +void CelestronAUX::ISGetProperties(const char *dev) +{ + INDI::Telescope::ISGetProperties(dev); + defineProperty(&PortTypeSP); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::initProperties() +{ + INDI::Telescope::initProperties(); + setDriverInterface(getDriverInterface() | GUIDER_INTERFACE); + + ///////////////////////////////////////////////////////////////////////////////////// + /// Main Control Tab + ///////////////////////////////////////////////////////////////////////////////////// + // Mount type + int configMountType = ALTAZ; + IUGetConfigOnSwitchIndex(getDeviceName(), "MOUNT_TYPE", &configMountType); + + // Detect Equatorial Mounts + if (strstr(getDeviceName(), "CGX") || + strstr(getDeviceName(), "CGEM") || + strstr(getDeviceName(), "Advanced VX") || + strstr(getDeviceName(), "Wedge")) + { + // Force equatorial for such mounts + configMountType = EQUATORIAL; + m_IsWedge = (strstr(getDeviceName(), "Wedge") != nullptr); + } + + if (configMountType == EQUATORIAL) + SetApproximateMountAlignment(m_Location.latitude >= 0 ? NORTH_CELESTIAL_POLE : SOUTH_CELESTIAL_POLE); + else + SetApproximateMountAlignment(ZENITH); + + MountTypeSP[EQUATORIAL].fill("EQUATORIAL", "Equatorial", configMountType == EQUATORIAL ? ISS_ON : ISS_OFF); + MountTypeSP[ALTAZ].fill("ALTAZ", "AltAz", configMountType == ALTAZ ? ISS_ON : ISS_OFF); + MountTypeSP.fill(getDeviceName(), "MOUNT_TYPE", "Mount Type", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE); + + // Track Modes for Equatorial Mount + if (MountTypeSP[EQUATORIAL].getState() == ISS_ON) + { + AddTrackMode("TRACK_SIDEREAL", "Sidereal", true); + AddTrackMode("TRACK_SOLAR", "Solar"); + AddTrackMode("TRACK_LUNAR", "Lunar"); + AddTrackMode("TRACK_CUSTOM", "Custom"); + + SetTelescopeCapability(GetTelescopeCapability() | TELESCOPE_HAS_PIER_SIDE, 8); + } + + // Horizontal Coords + HorizontalCoordsNP[AXIS_AZ].fill("AZ", "Az D:M:S", "%10.6m", 0.0, 360.0, 0.0, 0); + HorizontalCoordsNP[AXIS_ALT].fill("ALT", "Alt D:M:S", "%10.6m", -90., 90.0, 0.0, 0); + HorizontalCoordsNP.fill(getDeviceName(), "HORIZONTAL_COORD", "Horizontal Coord", MAIN_CONTROL_TAB, IP_RW, 0, IPS_IDLE); + + // Homing + HomeSP[HOME_AXIS1].fill("AXIS1", "AZ/RA", ISS_OFF); + HomeSP[HOME_AXIS2].fill("AXIS2", "AL/DE", ISS_OFF); + HomeSP[HOME_ALL].fill("ALL", "All", ISS_OFF); + HomeSP.fill(getDeviceName(), "HOME", "Home", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1, 60, IPS_IDLE); + + ///////////////////////////////////////////////////////////////////////////////////// + /// Cord Wrap Tab + ///////////////////////////////////////////////////////////////////////////////////// + + // Cord wrap Toggle + CordWrapToggleSP[INDI_ENABLED].fill("INDI_ENABLED", "Enabled", ISS_OFF); + CordWrapToggleSP[INDI_DISABLED].fill("INDI_DISABLED", "Disabled", ISS_ON); + CordWrapToggleSP.fill(getDeviceName(), "CORDWRAP", "Cord Wrap", CORDWRAP_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE); + + // Cord Wrap Position + CordWrapPositionSP[CORDWRAP_N].fill("CORDWRAP_N", "North", ISS_ON); + CordWrapPositionSP[CORDWRAP_E].fill("CORDWRAP_E", "East", ISS_OFF); + CordWrapPositionSP[CORDWRAP_S].fill("CORDWRAP_S", "South", ISS_OFF); + CordWrapPositionSP[CORDWRAP_W].fill("CORDWRAP_W", "West", ISS_OFF); + CordWrapPositionSP.fill(getDeviceName(), "CORDWRAP_POS", "CW Position", CORDWRAP_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE); + + // Cord Wrap / Park Base + CordWrapBaseSP[CW_BASE_ENC].fill("CW_BASE_ENC", "Encoders", ISS_ON); + CordWrapBaseSP[CW_BASE_SKY].fill("CW_BASE_SKY", "Alignment positions", ISS_OFF); + CordWrapBaseSP.fill(getDeviceName(), "CW_BASE", "CW Position Base", CORDWRAP_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE); + + ///////////////////////////////////////////////////////////////////////////////////// + /// Options + ///////////////////////////////////////////////////////////////////////////////////// + // GPS Emulation + GPSEmuSP[GPSEMU_OFF].fill("GPSEMU_OFF", "OFF", ISS_OFF); + GPSEmuSP[GPSEMU_ON].fill("GPSEMU_ON", "ON", ISS_ON); + GPSEmuSP.fill(getDeviceName(), "GPSEMU", "GPS Emu", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE); + + ///////////////////////////////////////////////////////////////////////////////////// + /// Guide Tab + ///////////////////////////////////////////////////////////////////////////////////// + + // Guide Properties + initGuiderProperties(getDeviceName(), GUIDE_TAB); + // Rate rate + GuideRateNP[AXIS_AZ].fill("GUIDE_RATE_WE", "W/E Rate", "%.f", 0, 1, .1, 0.5); + GuideRateNP[AXIS_ALT].fill("GUIDE_RATE_NS", "N/S Rate", "%.f", 0, 1, .1, 0.5); + GuideRateNP.fill(getDeviceName(), "GUIDE_RATE", "Guiding Rate", GUIDE_TAB, IP_RW, 0, IPS_IDLE); + + setDriverInterface(getDriverInterface() | GUIDER_INTERFACE); + + ///////////////////////////////////////////////////////////////////////////////////// + /// Connection + ///////////////////////////////////////////////////////////////////////////////////// + IUGetConfigOnSwitchIndex(getDeviceName(), "PORT_TYPE", &m_ConfigPortType); + PortTypeSP[PORT_AUX_PC].fill("PORT_AUX_PC", "AUX/PC", m_ConfigPortType == PORT_AUX_PC ? ISS_ON : ISS_OFF); + PortTypeSP[PORT_HC_USB].fill("PORT_HC_USB", "USB/HC", m_ConfigPortType == PORT_AUX_PC ? ISS_OFF : ISS_ON); + PortTypeSP.fill(getDeviceName(), "PORT_TYPE", "Port Type", CONNECTION_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE); + ///////////////////////////////////////////////////////////////////////////////////// + /// Mount Information + ///////////////////////////////////////////////////////////////////////////////////// + + // Raw encoder values + EncoderNP[AXIS_AZ].fill("AXIS_AZ", "Axis 1", "%.f", 0, STEPS_PER_REVOLUTION, 0, 0); + EncoderNP[AXIS_ALT].fill("AXIS_ALT", "Axis 2", "%.f", 0, STEPS_PER_REVOLUTION, 0, 0); + EncoderNP.fill(getDeviceName(), "TELESCOPE_ENCODER_STEPS", "Encoders", MOUNTINFO_TAB, IP_RW, 60, IPS_IDLE); + + // Encoder -> Angle values + AngleNP[AXIS_AZ].fill("AXIS_AZ", "Axis 1", "%.2f", 0, 360, 0, 0); + AngleNP[AXIS_ALT].fill("AXIS_ALT", "Axis 2", "%.2f", -90, 90, 0, 0); + AngleNP.fill(getDeviceName(), "TELESCOPE_ENCODER_ANGLES", "Angles", MOUNTINFO_TAB, IP_RO, 60, IPS_IDLE); + + // PID Control + Axis1PIDNP[Propotional].fill("Propotional", "Propotional", "%.2f", 0, 500, 10, GAIN_STEPS); + Axis1PIDNP[Derivative].fill("Derivative", "Derivative", "%.2f", 0, 500, 10, 0); + Axis1PIDNP[Integral].fill("Integral", "Integral", "%.2f", 0, 500, 10, 0); + Axis1PIDNP.fill(getDeviceName(), "AXIS1_PID", "Axis1 PID", MOUNTINFO_TAB, IP_RW, 60, IPS_IDLE); + + Axis2PIDNP[Propotional].fill("Propotional", "Propotional", "%.2f", 0, 500, 10, GAIN_STEPS); + Axis2PIDNP[Derivative].fill("Derivative", "Derivative", "%.2f", 0, 100, 10, 0); + Axis2PIDNP[Integral].fill("Integral", "Integral", "%.2f", 0, 100, 10, 1); + Axis2PIDNP.fill(getDeviceName(), "AXIS2_PID", "Axis2 PID", MOUNTINFO_TAB, IP_RW, 60, IPS_IDLE); + + // Firmware Info + FirmwareTP[FW_HC].fill("HC version", "", nullptr); + FirmwareTP[FW_MB].fill("Mother Board version", "", nullptr); + FirmwareTP[FW_AZM].fill("Ra/AZM version", "", nullptr); + FirmwareTP[FW_ALT].fill("Dec/ALT version", "", nullptr); + FirmwareTP[FW_WiFi].fill("WiFi version", "", nullptr); + FirmwareTP[FW_BAT].fill("Battery version", "", nullptr); + FirmwareTP[FW_GPS].fill("GPS version", "", nullptr); + FirmwareTP.fill(getDeviceName(), "Firmware Info", "Firmware Info", MOUNTINFO_TAB, IP_RO, 0, IPS_IDLE); + + // Gain Rate + // GainNP[AXIS_AZ].fill("AXIS_AZ", "Axis1", "%.f", -10000, 10000, 500, 0); + // GainNP[AXIS_ALT].fill("AXIS_ALT", "Axis2", "%.f", -10000, 10000, 500, 0); + // GainNP.fill(getDeviceName(), "TRACK_GAIN", "Gain", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); + ///////////////////////////////////////////////////////////////////////////////////// + /// Initial Configuration + ///////////////////////////////////////////////////////////////////////////////////// + + // Set Debug Information for AUX Commands + AUXCommand::setDebugInfo(getDeviceName(), DBG_CAUX); + + // Add debug controls so we may debug driver if necessary + addDebugControl(); + + // Add alignment properties + InitAlignmentProperties(this); + + // set alignment system be on the first time by default + getSwitch("ALIGNMENT_SUBSYSTEM_ACTIVE")->sp[0].s = ISS_ON; + + // Default connection options + serialConnection->setDefaultBaudRate(Connection::Serial::B_19200); + tcpConnection->setDefaultHost(CAUX_DEFAULT_IP); + tcpConnection->setDefaultPort(CAUX_DEFAULT_PORT); + + SetParkDataType(PARK_AZ_ALT_ENCODER); + + // to update cordwrap pos at each init of alignment subsystem + IDSnoopDevice(getDeviceName(), "ALIGNMENT_SUBSYSTEM_MATH_PLUGIN_INITIALISE"); + + // JM 2020-09-23 Make it easier for users to connect by default via WiFi if they + // selected the Celestron WiFi labeled driver. + if (strstr(getDeviceName(), "WiFi")) + setActiveConnection(tcpConnection); + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::formatVersionString(char *s, int n, uint8_t *verBuf) +{ + if (verBuf[0] == 0 && verBuf[1] == 0 && verBuf[2] == 0 && verBuf[3] == 0) + snprintf(s, n, "Unknown"); + else + snprintf(s, n, "%d.%02d.%d", verBuf[0], verBuf[1], verBuf[2] * 256 + verBuf[3]); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::updateProperties() +{ + INDI::Telescope::updateProperties(); + + if (isConnected()) + { + // Main Control Panel + defineProperty(&MountTypeSP); + //defineProperty(&GainNP); + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + defineProperty(&HorizontalCoordsNP); + defineProperty(&HomeSP); + + // Guide + defineProperty(&GuideNSNP); + defineProperty(&GuideWENP); + defineProperty(&GuideRateNP); + + // Cord wrap Enabled? + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + { + getCordWrapEnabled(); + CordWrapToggleSP[INDI_ENABLED].s = m_CordWrapActive ? ISS_ON : ISS_OFF; + CordWrapToggleSP[INDI_DISABLED].s = m_CordWrapActive ? ISS_OFF : ISS_ON; + defineProperty(&CordWrapToggleSP); + + // Cord wrap Position? + getCordWrapPosition(); + double cordWrapAngle = range360(m_CordWrapPosition / STEPS_PER_DEGREE); + LOGF_INFO("Cord Wrap position angle %.2f", cordWrapAngle); + CordWrapPositionSP[static_cast(std::floor(cordWrapAngle / 90))].s = ISS_ON; + defineProperty(&CordWrapPositionSP); + defineProperty(&CordWrapBaseSP); + } + + defineProperty(&GPSEmuSP); + + // Encoders + defineProperty(&EncoderNP); + defineProperty(&AngleNP); + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + { + defineProperty(&Axis1PIDNP); + defineProperty(&Axis2PIDNP); + } + + getVersions(); + // display firmware versions + char fwText[16] = {0}; + formatVersionString(fwText, 10, m_HCVersion); + FirmwareTP[FW_HC].setText(fwText); + formatVersionString(fwText, 10, m_MainBoardVersion); + FirmwareTP[FW_MB].setText(fwText); + formatVersionString(fwText, 10, m_AzimuthVersion); + FirmwareTP[FW_AZM].setText(fwText); + formatVersionString(fwText, 10, m_AltitudeVersion); + FirmwareTP[FW_ALT].setText(fwText); + formatVersionString(fwText, 10, m_WiFiVersion); + FirmwareTP[FW_WiFi].setText(fwText); + formatVersionString(fwText, 10, m_BATVersion); + FirmwareTP[FW_BAT].setText(fwText); + formatVersionString(fwText, 10, m_GPSVersion); + FirmwareTP[FW_GPS].setText(fwText); + defineProperty(&FirmwareTP); + + if (InitPark()) + { + // If loading parking data is successful, we just set the default parking values. + SetAxis1ParkDefault(0); + SetAxis2ParkDefault(0); + } + else + { + // Otherwise, we set all parking data to default in case no parking data is found. + SetAxis1Park(0); + SetAxis2Park(0); + SetAxis1ParkDefault(0); + SetAxis2ParkDefault(0); + } + } + else + { + deleteProperty(MountTypeSP.getName()); + //deleteProperty(GainNP.getName()); + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + deleteProperty(HorizontalCoordsNP.getName()); + deleteProperty(HomeSP.getName()); + + deleteProperty(GuideNSNP.name); + deleteProperty(GuideWENP.name); + deleteProperty(GuideRateNP.getName()); + + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + { + deleteProperty(CordWrapToggleSP.getName()); + deleteProperty(CordWrapPositionSP.getName()); + deleteProperty(CordWrapBaseSP.getName()); + } + + deleteProperty(GPSEmuSP.getName()); + + deleteProperty(EncoderNP.getName()); + deleteProperty(AngleNP.getName()); + + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + { + deleteProperty(Axis1PIDNP.getName()); + deleteProperty(Axis2PIDNP.getName()); + } + + deleteProperty(FirmwareTP.getName()); + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::saveConfigItems(FILE *fp) +{ + INDI::Telescope::saveConfigItems(fp); + SaveAlignmentConfigProperties(fp); + + IUSaveConfigSwitch(fp, &MountTypeSP); + IUSaveConfigSwitch(fp, &PortTypeSP); + IUSaveConfigSwitch(fp, &CordWrapToggleSP); + IUSaveConfigSwitch(fp, &CordWrapPositionSP); + IUSaveConfigSwitch(fp, &CordWrapBaseSP); + IUSaveConfigSwitch(fp, &GPSEmuSP); + + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + { + IUSaveConfigNumber(fp, &Axis1PIDNP); + IUSaveConfigNumber(fp, &Axis2PIDNP); + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::ISSnoopDevice(XMLEle *root) +{ + const char *propName = findXMLAttValu(root, "name"); + + // update cordwrap position at each init of the alignment subsystem + if (!strcmp(propName, "ALIGNMENT_SUBSYSTEM_MATH_PLUGIN_INITIALISE") && telescope_caux->isConnected()) + telescope_caux->syncCoordWrapPosition(); + + return Telescope::ISSnoopDevice(root); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], + char *formats[], char *names[], int n) +{ + if (strcmp(dev, getDeviceName()) == 0) + { + // Process alignment properties + ProcessAlignmentBLOBProperties(this, name, sizes, blobsizes, blobs, formats, names, n); + } + // Pass it up the chain + return INDI::Telescope::ISNewBLOB(dev, name, sizes, blobsizes, blobs, formats, names, n); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) +{ + if (strcmp(dev, getDeviceName()) == 0) + { + // Gain + // if (GainNP.isNameMatch(name)) + // { + // GainNP.update(values, names, n); + // GainNP.setState(IPS_OK); + // GainNP.apply(); + // return true; + // } + + // Axis1 PID + if (Axis1PIDNP.isNameMatch(name)) + { + Axis1PIDNP.update(values, names, n); + Axis1PIDNP.setState(IPS_OK); + Axis1PIDNP.apply(); + saveConfig(true, Axis1PIDNP.getName()); + return true; + } + + // Axis2 PID + if (Axis2PIDNP.isNameMatch(name)) + { + Axis2PIDNP.update(values, names, n); + Axis2PIDNP.setState(IPS_OK); + Axis2PIDNP.apply(); + saveConfig(true, Axis2PIDNP.getName()); + return true; + } + + // Horizontal Coords + if (HorizontalCoordsNP.isNameMatch(name)) + { + double az = 0, alt = 0; + for (int i = 0; i < 2; i++) + { + if (HorizontalCoordsNP[AXIS_AZ].isNameMatch(names[i])) + az = values[i]; + else if (HorizontalCoordsNP[AXIS_ALT].isNameMatch(names[i])) + alt = values[i]; + } + + // Convert Celestial Alt-Az to Equatorial + INDI::IHorizontalCoordinates celestialAzAlt = {az, alt}; + INDI::IEquatorialCoordinates celestialEquatorial; + INDI::HorizontalToEquatorial(&celestialAzAlt, &m_Location, ln_get_julian_from_sys(), &celestialEquatorial); + + if (Goto(celestialEquatorial.rightascension, celestialEquatorial.declination)) + { + // State already set in Goto so no need to set state here + char azStr[32], alStr[32]; + fs_sexa(azStr, celestialAzAlt.azimuth, 2, 3600); + fs_sexa(alStr, celestialAzAlt.altitude, 2, 3600); + LOGF_INFO("Slewing to AZ: %s AL: %s", azStr, alStr); + } + else + { + HorizontalCoordsNP.setState(IPS_ALERT); + HorizontalCoordsNP.apply(); + } + + return true; + } + + // Guide Rate + if (GuideRateNP.isNameMatch(name)) + { + GuideRateNP.update(values, names, n); + GuideRateNP.setState(IPS_OK); + GuideRateNP.apply(); + return true; + } + + // Encoder Values + if (EncoderNP.isNameMatch(name)) + { + uint32_t axisSteps1 {0}, axisSteps2 {0}; + for (int i = 0; i < n; i++) + { + if (!strcmp(names[i], EncoderNP[AXIS_AZ].getName())) + axisSteps1 = values[i]; + else if (!strcmp(names[i], EncoderNP[AXIS_ALT].getName())) + axisSteps2 = values[i]; + } + + slewTo(AXIS_AZ, axisSteps1); + slewTo(AXIS_ALT, axisSteps2); + TrackState = SCOPE_SLEWING; + EncoderNP.setState(IPS_OK); + EncoderNP.apply(); + return true; + } + + // Process Guide Properties + processGuiderProperties(name, values, names, n); + + // Process Alignment Properties + ProcessAlignmentNumberProperties(this, name, values, names, n); + } + + return INDI::Telescope::ISNewNumber(dev, name, values, names, n); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) +{ + if (strcmp(dev, getDeviceName()) == 0) + { + // mount type + if (MountTypeSP.isNameMatch(name)) + { + // Get current type + MountType currentMountType = IUFindOnSwitchIndex(&MountTypeSP) ? ALTAZ : EQUATORIAL; + + MountTypeSP.update(states, names, n); + MountTypeSP.setState(IPS_OK); + MountTypeSP.apply(); + + // Get target type + MountType targetMountType = IUFindOnSwitchIndex(&MountTypeSP) ? ALTAZ : EQUATORIAL; + + // If different then update + if (currentMountType != targetMountType) + { + LOG_INFO("Mount type updated. You must restart the driver for changes to take effect."); + saveConfig(true, MountTypeSP.getName()); + } + + return true; + } + + // Port Type + if (PortTypeSP.isNameMatch(name)) + { + PortTypeSP.update(states, names, n); + PortTypeSP.setState(IPS_OK); + PortTypeSP.apply(); + if (m_ConfigPortType != IUFindOnSwitchIndex(&PortTypeSP)) + { + m_ConfigPortType = IUFindOnSwitchIndex(&PortTypeSP); + saveConfig(true, PortTypeSP.getName()); + } + return true; + } + + // Cord Wrap Toggle + if (CordWrapToggleSP.isNameMatch(name)) + { + CordWrapToggleSP.update(states, names, n); + const bool toEnable = CordWrapToggleSP[INDI_ENABLED].s == ISS_ON; + LOGF_INFO("Cord Wrap is %s.", toEnable ? "enabled" : "disabled"); + setCordWrapEnabled(toEnable); + getCordWrapEnabled(); + CordWrapToggleSP.setState(IPS_OK); + CordWrapToggleSP.apply(); + + return true; + } + + // Cord Wrap Position + if (CordWrapPositionSP.isNameMatch(name)) + { + CordWrapPositionSP.update(states, names, n); + LOGF_DEBUG("Cord Wrap Position is %s.", CordWrapPositionSP.findOnSwitch()->getLabel()); + CordWrapPositionSP.setState(IPS_OK); + CordWrapPositionSP.apply(); + switch (CordWrapPositionSP.findOnSwitchIndex()) + { + case CORDWRAP_N: + m_RequestedCordwrapPos = 0; + break; + case CORDWRAP_E: + m_RequestedCordwrapPos = 90; + break; + case CORDWRAP_S: + m_RequestedCordwrapPos = 180; + break; + case CORDWRAP_W: + m_RequestedCordwrapPos = 270; + break; + default: + m_RequestedCordwrapPos = 0; + break; + } + + syncCoordWrapPosition(); + return true; + } + + // Park position base + if (CordWrapBaseSP.isNameMatch(name)) + { + CordWrapBaseSP.update(states, names, n); + CordWrapBaseSP.setState(IPS_OK); + CordWrapBaseSP.apply(); + return true; + } + + // GPS Emulation + if (GPSEmuSP.isNameMatch(name)) + { + GPSEmuSP.update(states, names, n); + GPSEmuSP.setState(IPS_OK); + GPSEmuSP.apply(); + m_GPSEmulation = GPSEmuSP[GPSEMU_ON].s == ISS_ON; + return true; + } + + // Homing/Leveling + if (HomeSP.isNameMatch(name)) + { + HomeSP.update(states, names, n); + bool rc = false; + switch (HomeSP.findOnSwitchIndex()) + { + case HOME_AXIS1: + rc = goHome(AXIS_AZ); + break; + case HOME_AXIS2: + rc = goHome(AXIS_ALT); + break; + case HOME_ALL: + rc = goHome(AXIS_AZ) && goHome(AXIS_ALT); + break; + } + + if (rc) + { + HomeSP.setState(IPS_BUSY); + LOG_INFO("Homing in progress..."); + } + else + { + HomeSP.reset(); + HomeSP.setState(IPS_ALERT); + LOG_ERROR("Failed to start homing."); + } + + HomeSP.apply(); + return true; + } + + // Process alignment properties + ProcessAlignmentSwitchProperties(this, name, states, names, n); + } + + return INDI::Telescope::ISNewSwitch(dev, name, states, names, n); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) +{ + if (!strcmp(dev, getDeviceName())) + ProcessAlignmentTextProperties(this, name, texts, names, n); + + return INDI::Telescope::ISNewText(dev, name, texts, names, n); +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::Park() +{ + slewTo(AXIS_AZ, GetAxis1Park()); + slewTo(AXIS_ALT, GetAxis2Park()); + TrackState = SCOPE_PARKING; + LOG_INFO("Parking in progress..."); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::UnPark() +{ + SetParked(false); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +INDI::IHorizontalCoordinates CelestronAUX::AltAzFromRaDec(double ra, double dec, double ts) +{ + // Call the alignment subsystem to translate the celestial reference frame coordinate + // into a telescope reference frame coordinate + TelescopeDirectionVector TDV; + INDI::IHorizontalCoordinates AltAz; + + if (TransformCelestialToTelescope(ra, dec, ts, TDV)) + // The alignment subsystem has successfully transformed my coordinate + AltitudeAzimuthFromTelescopeDirectionVector(TDV, AltAz); + else + { + LOG_DEBUG("AltAzFromRaDec - TransformCelestialToTelescope failed"); + + INDI::IEquatorialCoordinates EquatorialCoordinates { ra, dec }; + INDI::EquatorialToHorizontal(&EquatorialCoordinates, &m_Location, ln_get_julian_from_sys(), &AltAz); + TDV = TelescopeDirectionVectorFromAltitudeAzimuth(AltAz); + switch (GetApproximateMountAlignment()) + { + case ZENITH: + break; + + case NORTH_CELESTIAL_POLE: + // Rotate the TDV coordinate system clockwise (negative) around the y axis by 90 minus + // the (positive)observatory latitude. The vector itself is rotated anticlockwise + TDV.RotateAroundY(m_Location.latitude - 90.0); + break; + + case SOUTH_CELESTIAL_POLE: + // Rotate the TDV coordinate system anticlockwise (positive) around the y axis by 90 plus + // the (negative)observatory latitude. The vector itself is rotated clockwise + TDV.RotateAroundY(m_Location.latitude + 90.0); + break; + } + AltitudeAzimuthFromTelescopeDirectionVector(TDV, AltAz); + } + + return AltAz; +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +double CelestronAUX::getNorthAz() +{ + INDI::IGeographicCoordinates location; + double northAz; + if (!GetDatabaseReferencePosition(location)) + northAz = 0.; + else + northAz = DegreesToAzimuth(AltAzFromRaDec(get_local_sidereal_time(m_Location.longitude), 0., 0.).azimuth); + LOGF_DEBUG("North Azimuth = %lf", northAz); + return northAz; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::syncCoordWrapPosition() +{ + // No coord wrap for equatorial mounts. + if (MountTypeSP[EQUATORIAL].getState() == ISS_ON) + return; + + uint32_t coordWrapPosition = 0; + if (CordWrapBaseSP[CW_BASE_SKY].s == ISS_ON) + coordWrapPosition = range360(m_RequestedCordwrapPos + getNorthAz()) * STEPS_PER_DEGREE; + else + coordWrapPosition = range360(m_RequestedCordwrapPos) * STEPS_PER_DEGREE; + setCordWrapPosition(coordWrapPosition); + getCordWrapPosition(); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) +{ + int rate = IUFindOnSwitchIndex(&SlewRateSP) + 1; + m_AxisDirection[AXIS_ALT] = (dir == DIRECTION_NORTH) ? FORWARD : REVERSE; + m_AxisStatus[AXIS_ALT] = (command == MOTION_START) ? SLEWING : STOPPED; + ScopeStatus = SLEWING_MANUAL; + TrackState = SCOPE_SLEWING; + if (command == MOTION_START) + { + return slewByRate(AXIS_ALT, ((m_AxisDirection[AXIS_ALT] == FORWARD) ? 1 : -1) * rate); + } + else + return stopAxis(AXIS_ALT); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) +{ + int rate = IUFindOnSwitchIndex(&SlewRateSP) + 1; + if (isNorthHemisphere()) + m_AxisDirection[AXIS_AZ] = (dir == DIRECTION_WEST) ? FORWARD : REVERSE; + else + m_AxisDirection[AXIS_AZ] = (dir == DIRECTION_WEST) ? REVERSE : FORWARD; + m_AxisStatus[AXIS_AZ] = (command == MOTION_START) ? SLEWING : STOPPED; + ScopeStatus = SLEWING_MANUAL; + TrackState = SCOPE_SLEWING; + if (command == MOTION_START) + { + return slewByRate(AXIS_AZ, ((m_AxisDirection[AXIS_AZ] == FORWARD) ? 1 : -1) * rate); + } + else + return stopAxis(AXIS_AZ); +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +IPState CelestronAUX::GuideNorth(uint32_t ms) +{ + int8_t rate = static_cast(GuideRateNP[AXIS_ALT].getValue() * 100); + guidePulse(AXIS_DE, ms, rate); + return IPS_BUSY; +} + +IPState CelestronAUX::GuideSouth(uint32_t ms) +{ + int8_t rate = static_cast(GuideRateNP[AXIS_ALT].getValue() * 100); + guidePulse(AXIS_DE, ms, -rate); + return IPS_BUSY; +} + +IPState CelestronAUX::GuideEast(uint32_t ms) +{ + int8_t rate = static_cast(GuideRateNP[AXIS_AZ].getValue() * 100); + guidePulse(AXIS_RA, ms, -rate); + return IPS_BUSY; +} + +IPState CelestronAUX::GuideWest(uint32_t ms) +{ + int8_t rate = static_cast(GuideRateNP[AXIS_AZ].getValue() * 100); + guidePulse(AXIS_RA, ms, rate); + return IPS_BUSY; +} + +bool CelestronAUX::guidePulse(INDI_EQ_AXIS axis, uint32_t ms, int8_t rate) +{ + // For Equatorial mounts, use regular guiding. + if (MountTypeSP[EQUATORIAL].getState() == ISS_ON) + { + uint8_t ticks = std::min(255u, ms / 10); + AUXBuffer data(2); + data[0] = rate; + data[1] = ticks; + AUXCommand cmd(MC_AUX_GUIDE, APP, axis == AXIS_DE ? ALT : AZM, data); + return sendAUXCommand(cmd); + } + // For Alt-Az mounts in tracking state, add to guide delta + else if (TrackState == SCOPE_TRACKING) + { + double arcsecs = TRACKRATE_SIDEREAL * ms / 1000.0 * rate / 100.; + double steps = arcsecs * STEPS_PER_ARCSEC; + m_GuideOffset[axis] += steps; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::resetTracking() +{ + // getEncoder(AXIS_AZ); + // getEncoder(AXIS_ALT); + // m_TrackStartSteps[AXIS_AZ] = EncoderNP[AXIS_AZ].getValue(); + // m_TrackStartSteps[AXIS_ALT] = EncoderNP[AXIS_ALT].getValue(); + + m_Controllers[AXIS_AZ].reset(new PID(1, 100000, -100000, Axis1PIDNP[Propotional].getValue(), + Axis1PIDNP[Derivative].getValue(), Axis1PIDNP[Integral].getValue())); + m_Controllers[AXIS_AZ]->setIntegratorLimits(-2000, 2000); + m_Controllers[AXIS_ALT].reset(new PID(1, 100000, -100000, Axis2PIDNP[Propotional].getValue(), + Axis2PIDNP[Derivative].getValue(), Axis2PIDNP[Integral].getValue())); + m_Controllers[AXIS_ALT]->setIntegratorLimits(-2000, 2000); + m_TrackingElapsedTimer.restart(); + m_GuideOffset[AXIS_AZ] = m_GuideOffset[AXIS_ALT] = 0; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::isTrackingRequested() +{ + return (ISS_ON == IUFindSwitch(&CoordSP, "TRACK")->s); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::ReadScopeStatus() +{ + if (!isConnected()) + return false; + + if (!getStatus(AXIS_AZ)) + return false; + if (!getStatus(AXIS_ALT)) + return false; + + double axis1 = EncoderNP[AXIS_AZ].getValue(); + double axis2 = EncoderNP[AXIS_ALT].getValue(); + + if (!getEncoder(AXIS_AZ)) + { + if (EncoderNP.getState() != IPS_ALERT) + { + EncoderNP.setState(IPS_ALERT); + AngleNP.setState(IPS_ALERT); + EncoderNP.apply(); + AngleNP.apply(); + } + return false; + } + if (!getEncoder(AXIS_ALT)) + { + if (EncoderNP.getState() != IPS_ALERT) + { + EncoderNP.setState(IPS_ALERT); + AngleNP.setState(IPS_ALERT); + EncoderNP.apply(); + AngleNP.apply(); + } + return false; + } + + // Mount Alt-Az Coords + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + { + EncodersToAltAz(m_MountCurrentAltAz); + } + // Mount RA/DE Coords. + else + { + TelescopePierSide pierSide = currentPierSide; + EncodersToRADE(m_MountCurrentRADE, pierSide); + setPierSide(pierSide); + } + + // Send to client if updated + if (std::abs(axis1 - EncoderNP[AXIS_AZ].getValue()) > 1 || std::abs(axis2 - EncoderNP[AXIS_ALT].getValue()) > 1) + { + EncoderNP.setState(IPS_OK); + EncoderNP.apply(); + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + { + AngleNP[AXIS_AZ].setValue(m_MountCurrentAltAz.azimuth); + AngleNP[AXIS_ALT].setValue(m_MountCurrentAltAz.altitude); + } + else + { + AngleNP[AXIS_RA].setValue(range360(range24(get_local_sidereal_time(m_Location.longitude) - + m_MountCurrentRADE.rightascension) * 15)); + AngleNP[AXIS_DE].setValue(rangeDec(m_MountCurrentRADE.declination)); + } + AngleNP.setState(IPS_OK); + AngleNP.apply(); + } + + // Get sky coordinates + mountToSkyCoords(); + char RAStr[32] = {0}, DecStr[32] = {0}; + fs_sexa(RAStr, m_SkyCurrentRADE.rightascension, 2, 3600); + fs_sexa(DecStr, m_SkyCurrentRADE.declination, 2, 3600); + + INDI::IHorizontalCoordinates celestialAzAlt; + INDI::EquatorialToHorizontal(&m_SkyCurrentRADE, &m_Location, ln_get_julian_from_sys(), &celestialAzAlt); + + char AzStr[32] = {0}, AltStr[32] = {0}, HAStr[32] = {0}; + fs_sexa(AzStr, celestialAzAlt.azimuth, 2, 3600); + fs_sexa(AltStr, celestialAzAlt.altitude, 2, 3600); + double HA = rangeHA(ln_get_julian_from_sys() - m_SkyCurrentRADE.rightascension); + fs_sexa(HAStr, HA, 2, 3600); + DEBUGF(INDI::AlignmentSubsystem::DBG_ALIGNMENT, "Mount -> Sky RA: %s DE: %s AZ: %s AL: %s HA: %s Pier: %s", + RAStr, + DecStr, + AzStr, + AltStr, + HAStr, + MountTypeSP[ALTAZ].getState() == ISS_ON ? "NA" : getPierSideStr(currentPierSide)); + + if (std::abs(celestialAzAlt.azimuth - HorizontalCoordsNP[AXIS_AZ].getValue()) > 0.1 || + std::abs(celestialAzAlt.altitude - HorizontalCoordsNP[AXIS_ALT].getValue()) > 0.1) + { + HorizontalCoordsNP[AXIS_AZ].setValue(celestialAzAlt.azimuth); + HorizontalCoordsNP[AXIS_ALT].setValue(celestialAzAlt.altitude); + HorizontalCoordsNP.apply(); + } + + if (TrackState == SCOPE_SLEWING) + { + if (isSlewing() == false) + { + // Stages are GOTO --> SLEWING FAST --> APPRAOCH --> SLEWING SLOW --> TRACKING + if (ScopeStatus == SLEWING_FAST) + { + ScopeStatus = APPROACH; + return Goto(m_SkyGOTOTarget.rightascension, m_SkyGOTOTarget.declination); + } + + // If tracking was engaged, start it. + if (isTrackingRequested()) + { + // Goto has finished start tracking + ScopeStatus = TRACKING; + if (HorizontalCoordsNP.getState() == IPS_BUSY) + { + HorizontalCoordsNP.setState(IPS_OK); + HorizontalCoordsNP.apply(); + } + TrackState = SCOPE_TRACKING; + resetTracking(); + + // For equatorial mounts, engage tracking. + if (MountTypeSP[EQUATORIAL].getState() == ISS_ON) + SetTrackMode(IUFindOnSwitchIndex(&TrackModeSP)); + LOG_INFO("Tracking started."); + } + else + { + TrackState = SCOPE_IDLE; + ScopeStatus = IDLE; + } + } + } + else if (TrackState == SCOPE_PARKING) + { + if (isSlewing() == false) + { + SetParked(true); + SetTrackEnabled(false); + } + } + + NewRaDec(m_SkyCurrentRADE.rightascension, m_SkyCurrentRADE.declination); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::EncodersToAltAz(INDI::IHorizontalCoordinates &coords) +{ + coords.azimuth = DegreesToAzimuth(EncodersToDegrees(EncoderNP[AXIS_AZ].getValue())); + coords.altitude = EncodersToDegrees(EncoderNP[AXIS_ALT].getValue()); + DEBUGF(INDI::AlignmentSubsystem::DBG_ALIGNMENT, "Axis1 encoder %10.f -> AZ %.4f°", EncoderNP[AXIS_AZ].getValue(), + coords.azimuth); + DEBUGF(INDI::AlignmentSubsystem::DBG_ALIGNMENT, "Axis2 encoder %10.f -> AL %.4f°", EncoderNP[AXIS_ALT].getValue(), + coords.altitude); +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::Goto(double ra, double dec) +{ + char RAStr[32] = {0}, DecStr[32] = {0}; + fs_sexa(RAStr, ra, 2, 3600); + fs_sexa(DecStr, dec, 2, 3600); + + // In case we have appaoch ongoing + if (ScopeStatus == APPROACH) + { + DEBUGF(INDI::AlignmentSubsystem::DBG_ALIGNMENT, "Slow Iterative GOTO RA %s DE %s", RAStr, DecStr); + } + // Fast GOTO + else + { + if (TrackState != SCOPE_IDLE) + Abort(); + + m_GuideOffset[AXIS_AZ] = m_GuideOffset[AXIS_ALT] = 0; + m_SkyGOTOTarget.rightascension = ra; + m_SkyGOTOTarget.declination = dec; + + DEBUGF(INDI::AlignmentSubsystem::DBG_ALIGNMENT, "Fast GOTO RA %s DE %s", RAStr, DecStr); + + if (isTrackingRequested()) + { + m_SkyTrackingTarget = m_SkyGOTOTarget; + } + } + + uint32_t axis1Steps {0}, axis2Steps {0}; + + TelescopeDirectionVector TDV; + INDI::IEquatorialCoordinates MountRADE { ra, dec }; + + // Transform Celestial to Telescope coordinates. + // We have no good way to estimate how long will the mount takes to reach target (with deceleration, + // and not just speed). So we will use iterative GOTO once the first GOTO is complete. + if (TransformCelestialToTelescope(ra, dec, 0.0, TDV)) + { + // For Alt-Az Mounts, we get the Mount AltAz coords + if (MountTypeSP[MOUNT_ALTAZ].getState() == ISS_ON) + { + INDI::IHorizontalCoordinates MountAltAz { 0, 0 }; + AltitudeAzimuthFromTelescopeDirectionVector(TDV, MountAltAz); + // Converts to steps and we're done. + axis1Steps = DegreesToEncoders(AzimuthToDegrees(MountAltAz.azimuth)); + axis2Steps = DegreesToEncoders(MountAltAz.altitude); + + // For logging purposes + INDI::HorizontalToEquatorial(&MountAltAz, &m_Location, ln_get_julian_from_sys(), &MountRADE); + } + // For Equatorial mounts + else + { + EquatorialCoordinatesFromTelescopeDirectionVector(TDV, MountRADE); + // Converts to steps and we're done. + RADEToEncoders(MountRADE, axis1Steps, axis2Steps); + } + } + // Conversion failed, use values as is + else + { + if (MountTypeSP[EQUATORIAL].getState() == ISS_ON) + { + RADEToEncoders(MountRADE, axis1Steps, axis2Steps); + } + else + { + INDI::IHorizontalCoordinates MountAltAz { 0, 0 }; + INDI::EquatorialToHorizontal(&MountRADE, &m_Location, ln_get_julian_from_sys(), &MountAltAz); + TDV = TelescopeDirectionVectorFromAltitudeAzimuth(MountAltAz); + switch (GetApproximateMountAlignment()) + { + case ZENITH: + break; + + case NORTH_CELESTIAL_POLE: + // Rotate the TDV coordinate system clockwise (negative) around the y axis by 90 minus + // the (positive)observatory latitude. The vector itself is rotated anticlockwise + TDV.RotateAroundY(m_Location.latitude - 90.0); + break; + + case SOUTH_CELESTIAL_POLE: + // Rotate the TDV coordinate system anticlockwise (positive) around the y axis by 90 plus + // the (negative)observatory latitude. The vector itself is rotated clockwise + TDV.RotateAroundY(m_Location.latitude + 90.0); + break; + } + AltitudeAzimuthFromTelescopeDirectionVector(TDV, MountAltAz); + + // Converts to steps and we're done. + axis1Steps = DegreesToEncoders(AzimuthToDegrees(MountAltAz.azimuth)); + axis2Steps = DegreesToEncoders(MountAltAz.altitude); + } + } + + fs_sexa(RAStr, MountRADE.rightascension, 2, 3600); + fs_sexa(DecStr, MountRADE.declination, 2, 3600); + DEBUGF(INDI::AlignmentSubsystem::DBG_ALIGNMENT, "Sky -> Mount RA %s (%ld) DE %s (%ld)", RAStr, axis1Steps, DecStr, + axis2Steps); + + // Slew to physical steps. + slewTo(AXIS_AZ, axis1Steps, ScopeStatus != APPROACH); + slewTo(AXIS_ALT, axis2Steps, ScopeStatus != APPROACH); + + ScopeStatus = (ScopeStatus == APPROACH) ? SLEWING_SLOW : SLEWING_FAST; + TrackState = SCOPE_SLEWING; + + if (MountTypeSP[ALTAZ].getState() == ISS_ON && HorizontalCoordsNP.getState() != IPS_BUSY) + { + HorizontalCoordsNP.setState(IPS_BUSY); + HorizontalCoordsNP.apply(); + + } + return true; +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::Sync(double ra, double dec) +{ + // Compute a telescope direction vector from the current encoders + if (!getEncoder(AXIS_AZ)) + return false; + if (!getEncoder(AXIS_ALT)) + return false; + + + AlignmentDatabaseEntry NewEntry; + NewEntry.ObservationJulianDate = ln_get_julian_from_sys(); + NewEntry.RightAscension = ra; + NewEntry.Declination = dec; + + + if (MountTypeSP[MOUNT_ALTAZ].getState() == ISS_ON) + { + INDI::IHorizontalCoordinates MountAltAz { 0, 0 }; + MountAltAz.azimuth = DegreesToAzimuth(EncodersToDegrees(EncoderNP[AXIS_AZ].getValue())); + MountAltAz.altitude = EncodersToDegrees(EncoderNP[AXIS_ALT].getValue()); + NewEntry.TelescopeDirection = TelescopeDirectionVectorFromAltitudeAzimuth(MountAltAz); + } + else + { + INDI::IEquatorialCoordinates MountRADE {0, 0}; + TelescopePierSide pierSide; + EncodersToRADE(MountRADE, pierSide); + NewEntry.TelescopeDirection = TelescopeDirectionVectorFromEquatorialCoordinates(MountRADE); + } + NewEntry.PrivateDataSize = 0; + + DEBUGF(INDI::AlignmentSubsystem::DBG_ALIGNMENT, "New sync point Date %lf RA %lf DEC %lf TDV(x %lf y %lf z %lf)", + NewEntry.ObservationJulianDate, NewEntry.RightAscension, NewEntry.Declination, NewEntry.TelescopeDirection.x, + NewEntry.TelescopeDirection.y, NewEntry.TelescopeDirection.z); + + if (!CheckForDuplicateSyncPoint(NewEntry)) + { + GetAlignmentDatabase().push_back(NewEntry); + + // Tell the client about size change + UpdateSize(); + + // Tell the math plugin to reinitialise + Initialise(this); + + // Force read before restarting + ReadScopeStatus(); + + // Sync cord wrap + syncCoordWrapPosition(); + + // The tracking seconds should be reset to restart the drift compensation + resetTracking(); + + return true; + } + return false; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +/// +////////////////////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::mountToSkyCoords() +{ + double RightAscension, Declination; + + // TODO for Alt-Az Mounts on a Wedge, we need a watch to set this. + if (MountTypeSP[ALTAZ].getState() == ISS_ON) + { + INDI::IHorizontalCoordinates AltAz = m_MountCurrentAltAz; + TelescopeDirectionVector TDV = TelescopeDirectionVectorFromAltitudeAzimuth(AltAz); + if (!TransformTelescopeToCelestial(TDV, RightAscension, Declination)) + { + TelescopeDirectionVector RotatedTDV(TDV); + switch (GetApproximateMountAlignment()) + { + case ZENITH: + break; + + case NORTH_CELESTIAL_POLE: + // Rotate the TDV coordinate system anticlockwise (positive) around the y axis by 90 minus + // the (positive)observatory latitude. The vector itself is rotated clockwise + RotatedTDV.RotateAroundY(90.0 - m_Location.latitude); + AltitudeAzimuthFromTelescopeDirectionVector(RotatedTDV, AltAz); + break; + + case SOUTH_CELESTIAL_POLE: + // Rotate the TDV coordinate system clockwise (negative) around the y axis by 90 plus + // the (negative)observatory latitude. The vector itself is rotated anticlockwise + RotatedTDV.RotateAroundY(-90.0 - m_Location.latitude); + AltitudeAzimuthFromTelescopeDirectionVector(RotatedTDV, AltAz); + break; + } + + INDI::IEquatorialCoordinates EquatorialCoordinates; + INDI::HorizontalToEquatorial(&AltAz, &m_Location, ln_get_julian_from_sys(), &EquatorialCoordinates); + RightAscension = EquatorialCoordinates.rightascension; + Declination = EquatorialCoordinates.declination; + } + } + else + { + INDI::IEquatorialCoordinates EquatorialCoordinates = m_MountCurrentRADE; + TelescopeDirectionVector TDV = TelescopeDirectionVectorFromEquatorialCoordinates(EquatorialCoordinates); + if (!TransformTelescopeToCelestial(TDV, RightAscension, Declination)) + { + RightAscension = EquatorialCoordinates.rightascension; + Declination = EquatorialCoordinates.declination; + } + } + + m_SkyCurrentRADE.rightascension = RightAscension; + m_SkyCurrentRADE.declination = Declination; + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::TimerHit() +{ + INDI::Telescope::TimerHit(); + + switch (TrackState) + { + case SCOPE_SLEWING: + break; + + case SCOPE_TRACKING: + { + // Check if manual motion in progress but we stopped + if (m_ManualMotionActive && isSlewing() == false) + { + m_ManualMotionActive = false; + // If we slewed manually using NSWE keys, then we need to restart tracking + // whatever point we are AT now. We need to update the SkyTrackingTarget accordingly. + m_SkyTrackingTarget.rightascension = EqN[AXIS_RA].value; + m_SkyTrackingTarget.declination = EqN[AXIS_DE].value; + resetTracking(); + } + // If we're manually moving by WESN controls, update the tracking coordinates. + if (m_ManualMotionActive) + { + break; + } + // We only engage ACTIVE tracking if the mount is Alt-Az. + // For Equatorial mount, we simply use user-selected tracking mode and let it passively track. + else if (MountTypeSP[MOUNT_ALTAZ].getState() == ISS_ON) + { + TelescopeDirectionVector TDV; + INDI::IHorizontalCoordinates targetMountAxisCoordinates { 0, 0 }; + + // Start by transforming tracking target celestial coordinates to telescope coordinates. + if (TransformCelestialToTelescope(m_SkyTrackingTarget.rightascension, m_SkyTrackingTarget.declination, + 0, TDV)) + { + // If mount is Alt-Az then that's all we need to do + AltitudeAzimuthFromTelescopeDirectionVector(TDV, targetMountAxisCoordinates); + } + // If transformation failed. + else + { + INDI::IEquatorialCoordinates EquatorialCoordinates { 0, 0 }; + EquatorialCoordinates.rightascension = m_SkyTrackingTarget.rightascension; + EquatorialCoordinates.declination = m_SkyTrackingTarget.declination; + INDI::EquatorialToHorizontal(&EquatorialCoordinates, &m_Location, ln_get_julian_from_sys(), &targetMountAxisCoordinates); + } + + // Now add the guiding offsets. + targetMountAxisCoordinates.azimuth += m_GuideOffset[AXIS_AZ]; + targetMountAxisCoordinates.altitude += m_GuideOffset[AXIS_ALT]; + + // If we had guiding pulses active, mark them as complete + if (GuideWENP.s == IPS_BUSY) + GuideComplete(AXIS_RA); + if (GuideNSNP.s == IPS_BUSY) + GuideComplete(AXIS_DE); + + // Next get current alt-az + INDI::IHorizontalCoordinates currentAltAz { 0, 0 }; + currentAltAz.azimuth = DegreesToAzimuth(EncodersToDegrees(EncoderNP[AXIS_AZ].getValue())); + currentAltAz.altitude = EncodersToDegrees(EncoderNP[AXIS_ALT].getValue()); + + // Offset in degrees + double offsetAngle[2] = {0, 0}; + offsetAngle[AXIS_AZ] = (targetMountAxisCoordinates.azimuth - currentAltAz.azimuth); + offsetAngle[AXIS_ALT] = (targetMountAxisCoordinates.altitude - currentAltAz.altitude); + + int32_t offsetSteps[2] = {0, 0}; + int32_t targetSteps[2] = {0, 0}; + double trackRates[2] = {0, 0}; + + offsetSteps[AXIS_AZ] = offsetAngle[AXIS_AZ] * STEPS_PER_DEGREE; + offsetSteps[AXIS_ALT] = offsetAngle[AXIS_ALT] * STEPS_PER_DEGREE; + + // Only apply trackinf IF we're still on the same side of the curve + // If we switch over, let's settle for a bit + if (m_LastOffset[AXIS_AZ] * offsetSteps[AXIS_AZ] >= 0 || m_OffsetSwitchSettle[AXIS_AZ]++ > 3) + { + m_OffsetSwitchSettle[AXIS_AZ] = 0; + m_LastOffset[AXIS_AZ] = offsetSteps[AXIS_AZ]; + targetSteps[AXIS_AZ] = DegreesToEncoders(AzimuthToDegrees(targetMountAxisCoordinates.azimuth)); + trackRates[AXIS_AZ] = m_Controllers[AXIS_AZ]->calculate(targetSteps[AXIS_AZ], EncoderNP[AXIS_AZ].getValue()); + + LOGF_DEBUG("Tracking AZ Now: %.f Target: %d Offset: %d Rate: %.2f", EncoderNP[AXIS_AZ].getValue(), targetSteps[AXIS_AZ], + offsetSteps[AXIS_AZ], trackRates[AXIS_AZ]); +#ifdef DEBUG_PID + LOGF_DEBUG("Tracking AZ P: %f I: %f D: %f", + m_Controllers[AXIS_AZ]->propotionalTerm(), + m_Controllers[AXIS_AZ]->integralTerm(), + m_Controllers[AXIS_AZ]->derivativeTerm()); +#endif + + // Use PID to determine appropiate tracking rate + trackByRate(AXIS_AZ, trackRates[AXIS_AZ]); + } + + // Only apply trackinf IF we're still on the same side of the curve + // If we switch over, let's settle for a bit + if (m_LastOffset[AXIS_ALT] * offsetSteps[AXIS_ALT] >= 0 || m_OffsetSwitchSettle[AXIS_ALT]++ > 3) + { + m_OffsetSwitchSettle[AXIS_ALT] = 0; + m_LastOffset[AXIS_ALT] = offsetSteps[AXIS_ALT]; + targetSteps[AXIS_ALT] = DegreesToEncoders(targetMountAxisCoordinates.altitude); + trackRates[AXIS_ALT] = m_Controllers[AXIS_ALT]->calculate(targetSteps[AXIS_ALT], EncoderNP[AXIS_ALT].getValue()); + + LOGF_DEBUG("Tracking AL Now: %.f Target: %d Offset: %d Rate: %.2f", EncoderNP[AXIS_ALT].getValue(), targetSteps[AXIS_ALT], + offsetSteps[AXIS_ALT], trackRates[AXIS_ALT]); +#ifdef DEBUG_PID + LOGF_DEBUG("Tracking AL P: %f I: %f D: %f", + m_Controllers[AXIS_ALT]->propotionalTerm(), + m_Controllers[AXIS_ALT]->integralTerm(), + m_Controllers[AXIS_ALT]->derivativeTerm()); +#endif + trackByRate(AXIS_ALT, trackRates[AXIS_ALT]); + } + break; + } + break; + + default: + break; + } + } + + // Check if seeking index or leveling is done + if (HomeSP.getState() == IPS_BUSY) + { + isHomingDone(AXIS_AZ); + isHomingDone(AXIS_ALT); + + if (!m_HomingProgress[AXIS_AZ] && !m_HomingProgress[AXIS_ALT]) + { + LOG_INFO("Homing complete."); + HomeSP.reset(); + HomeSP.setState(IPS_OK); + HomeSP.apply(); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::updateLocation(double latitude, double longitude, double elevation) +{ + // Update INDI Alignment Subsystem Location + UpdateLocation(latitude, longitude, elevation); + + // Do we really need this in update Location?? + // take care of latitude for north or south emisphere + //SetApproximateMountAlignmentFromMountType(static_cast(IUFindOnSwitchIndex(&MountTypeSP))); + // tell the alignment math plugin to reinitialise + //Initialise(this); + + // update cordwrap position at each init of the alignment subsystem + syncCoordWrapPosition(); + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// 0 to 360 degrees +///////////////////////////////////////////////////////////////////////////////////// +double CelestronAUX::EncodersToDegrees(uint32_t steps) +{ + return range360(steps * DEGREES_PER_STEP); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +uint32_t CelestronAUX::DegreesToEncoders(double degree) +{ + return round(range360(degree) * STEPS_PER_DEGREE); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +double CelestronAUX::DegreesToAzimuth(double degree) +{ + if (isNorthHemisphere()) + return degree; + else + return range360(degree + 180); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +double CelestronAUX::AzimuthToDegrees(double degree) +{ + if (isNorthHemisphere()) + return degree; + else + return range360(degree + 180); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// 0 to 24 hours +///////////////////////////////////////////////////////////////////////////////////// +double CelestronAUX::EncodersToHours(uint32_t steps) +{ + double value = steps * HOURS_PER_STEP; + // North hemisphere + if (isNorthHemisphere()) + return range24(value); + else + return range24(24 - value); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +uint32_t CelestronAUX::HoursToEncoders(double hour) +{ + return DegreesToEncoders(hour * 15); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::EncodersToRADE(INDI::IEquatorialCoordinates &coords, TelescopePierSide &pierSide) +{ + auto haEncoder = (EncoderNP[AXIS_RA].getValue() / STEPS_PER_REVOLUTION) * 360.0; + auto deEncoder = 360.0 - (EncoderNP[AXIS_DE].getValue() / STEPS_PER_REVOLUTION) * 360.0; + + double de = 0, ha = 0; + // Northern Hemisphere + if (LocationN[LOCATION_LATITUDE].value >= 0) + { + if (m_IsWedge) + { + pierSide = PIER_UNKNOWN; + if (deEncoder >= 270) + de = 360 - deEncoder; + else if (deEncoder >= 90) + de = deEncoder - 180; + else + de = -deEncoder; + + if (haEncoder >= 180) + ha = -((360 - haEncoder) / 360.0) * 24.0 ; + else + ha = (haEncoder / 360.0) * 24.0 ; + } + // "Normal" Pointing State (East, looking West) + else if (deEncoder >= 0) + { + de = std::min(90 - deEncoder, 90.0); + ha = -6.0 + (haEncoder / 360.0) * 24.0 ; + pierSide = PIER_EAST; + } + // "Reversed" Pointing State (West, looking East) + else + { + de = 90 + deEncoder; + ha = 6.0 + (haEncoder / 360.0) * 24.0 ; + pierSide = PIER_WEST; + } + } + else + { + if (m_IsWedge) + { + pierSide = PIER_UNKNOWN; + if (deEncoder >= 270) + de = deEncoder - 360; + else if (deEncoder >= 90) + de = 180 - deEncoder; + else + de = deEncoder; + + if (haEncoder >= 180) + ha = -((360 - haEncoder) / 360.0) * 24.0 ; + else + ha = (haEncoder / 360.0) * 24.0 ; + } + // East + else if (deEncoder <= 0) + { + de = std::max(-90 - deEncoder, -90.0); + ha = -6.0 - (haEncoder / 360.0) * 24.0 ; + pierSide = PIER_WEST; + } + // West + else + { + de = -90 + deEncoder; + ha = 6.0 - (haEncoder / 360.0) * 24.0 ; + pierSide = PIER_EAST; + } + } + + double lst = get_local_sidereal_time(LocationN[LOCATION_LONGITUDE].value); + double ra = range24(lst - ha); + + coords.rightascension = ra; + coords.declination = de; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// HA encoders at 0 (HA = LST). When going WEST, steps increase from 0 to STEPS_PER_REVOLUTION {16777216} +/// counter clock-wise. +/// HA 0 to 6 hours range: 0 to 4194304 +/// HA 0 to -6 hours range: 16777216 to 12582912 +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::RADEToEncoders(const INDI::IEquatorialCoordinates &coords, uint32_t &haEncoder, uint32_t &deEncoder) +{ + double lst = get_local_sidereal_time(LocationN[LOCATION_LONGITUDE].value); + double dHA = rangeHA(lst - coords.rightascension); + double de = 0, ha = 0; + // Northern Hemisphere + if (LocationN[LOCATION_LATITUDE].value >= 0) + { + if (m_IsWedge) + { + if (coords.declination < 0) + de = -coords.declination; + else + de = 360 - coords.declination; + + if (dHA < 0) + ha = 360 - ((dHA / -24.0) * 360.0); + else + ha = (dHA / 24.0) * 360.0; + + } + // "Normal" Pointing State (East, looking West) + else if (dHA <= 0) + { + de = -(coords.declination - 90.0); + ha = (dHA + 6.0) * 360.0 / 24.0; + } + // "Reversed" Pointing State (West, looking East) + else + { + de = coords.declination - 90.0; + ha = (dHA - 6.0) * 360.0 / 24.0; + } + } + else + { + if (m_IsWedge) + { + if (coords.declination >= 0) + de = coords.declination; + else + de = 360 + coords.declination; + + if (dHA < 0) + ha = 360 - ((dHA / -24.0) * 360.0); + else + ha = (dHA / 24.0) * 360.0; + + } + // "Normal" Pointing State (East, looking West) + else if (dHA <= 0) + { + de = -(coords.declination + 90.0); + ha = -(dHA + 6.0) * 360.0 / 24.0; + } + // "Reversed" Pointing State (West, looking East) + else + { + de = (coords.declination + 90.0); + ha = -(dHA - 6.0) * 360 / 24.0; + } + } + + haEncoder = (range360(ha) / 360.0) * STEPS_PER_REVOLUTION; + deEncoder = (360.0 - range360(de)) / 360.0 * STEPS_PER_REVOLUTION; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// -90 to +90 +///////////////////////////////////////////////////////////////////////////////////// +double CelestronAUX::EncodersToDE(uint32_t steps, TelescopePierSide pierSide) +{ + double degrees = EncodersToDegrees(steps); + double de = 0; + if (m_IsWedge) + de = degrees; + else if ((isNorthHemisphere() && pierSide == PIER_WEST) || (!isNorthHemisphere() && pierSide == PIER_EAST)) + de = degrees - 270; + else + de = 90 - degrees; + + return rangeDec(de); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +double CelestronAUX::DEToEncoders(double de) +{ + double degrees = 0; + if (m_IsWedge) + degrees = de; + else if ((isNorthHemisphere() && m_TargetPierSide == PIER_WEST) || (!isNorthHemisphere() && m_TargetPierSide == PIER_EAST)) + degrees = 270 + de; + else + degrees = 90 - de; + return DegreesToEncoders(degrees); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::isSlewing() +{ + return m_AxisStatus[AXIS_AZ] == SLEWING || m_AxisStatus[AXIS_ALT] == SLEWING; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::slewTo(INDI_HO_AXIS axis, uint32_t steps, bool fast) +{ + // Stop first. + trackByRate(axis, 0); + AUXCommand command(fast ? MC_GOTO_FAST : MC_GOTO_SLOW, APP, axis == AXIS_AZ ? AZM : ALT); + m_AxisStatus[axis] = SLEWING; + command.setData(steps, 3); + sendAUXCommand(command); + readAUXResponse(command); + return true; +}; + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::slewByRate(INDI_HO_AXIS axis, int8_t rate) +{ + // Stop first. + trackByRate(axis, 0); + AUXCommand command(rate >= 0 ? MC_MOVE_POS : MC_MOVE_NEG, APP, axis == AXIS_AZ ? AZM : ALT); + command.setData(std::abs(rate), 1); + sendAUXCommand(command); + readAUXResponse(command); + return true; +}; + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::goHome(INDI_HO_AXIS axis) +{ + AUXCommand command(axis == AXIS_AZ ? MC_SEEK_INDEX : MC_LEVEL_START, APP, axis == AXIS_AZ ? AZM : ALT); + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::isHomingDone(INDI_HO_AXIS axis) +{ + AUXCommand command(axis == AXIS_AZ ? MC_SEEK_DONE : MC_LEVEL_DONE, APP, axis == AXIS_AZ ? AZM : ALT); + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::getVersion(AUXTargets target) +{ + AUXCommand firmver(GET_VER, APP, target); + if (! sendAUXCommand(firmver)) + return false; + if (! readAUXResponse(firmver)) + return false; + return true; +}; + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::getVersions() +{ + if (!m_isHandController) + { + // Do not ask HC/MB for the version over AUX channel + // We got HC version from detectHC + getVersion(MB); + getVersion(HC); + getVersion(HCP); + } + getVersion(AZM); + getVersion(ALT); + getVersion(GPS); + getVersion(WiFi); + getVersion(BAT); + + // These are the same as battery controller + // Probably the same chip inside the mount + //getVersion(CHG); + //getVersion(LIGHT); + //getVersion(ANY); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::setCordWrapEnabled(bool enable) +{ + + AUXCommand command(enable ? MC_ENABLE_CORDWRAP : MC_DISABLE_CORDWRAP, APP, AZM); + sendAUXCommand(command); + readAUXResponse(command); + return true; +}; + +bool CelestronAUX::getCordWrapEnabled() +{ + AUXCommand command(MC_POLL_CORDWRAP, APP, AZM); + sendAUXCommand(command); + readAUXResponse(command); + return m_CordWrapActive; +}; + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::setCordWrapPosition(uint32_t steps) +{ + AUXCommand command(MC_SET_CORDWRAP_POS, APP, AZM); + command.setData(steps, 3); + sendAUXCommand(command); + readAUXResponse(command); + return true; +}; + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +uint32_t CelestronAUX::getCordWrapPosition() +{ + AUXCommand command(MC_GET_CORDWRAP_POS, APP, AZM); + sendAUXCommand(command); + readAUXResponse(command); + return m_CordWrapPosition; +}; + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::stopAxis(INDI_HO_AXIS axis) +{ + m_AxisStatus[axis] = STOPPED; + trackByRate(axis, 0); + AUXCommand command(MC_MOVE_POS, APP, (axis == AXIS_ALT) ? ALT : AZM); + command.setData(0, 1); + sendAUXCommand(command); + readAUXResponse(command); + return true; + +} +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::Abort() +{ + // getEncoder(AXIS_AZ); + // getEncoder(AXIS_ALT); + // double ms = m_TrackingElapsedTimer.elapsed(); + // LOGF_INFO("*** Elapsed %.f ms", ms); + // LOGF_INFO("*** Axis1 start: %.f finish: %.f steps/s: %.4f", m_TrackStartSteps[AXIS_AZ], EncoderNP[AXIS_AZ].getValue(), std::abs(EncoderNP[AXIS_AZ].getValue() - m_TrackStartSteps[AXIS_AZ]) / (ms/1000.)); + // LOGF_INFO("*** Axis2 start: %.f finish: %.f steps/s: %.4f", m_TrackStartSteps[AXIS_ALT], EncoderNP[AXIS_ALT].getValue(), std::abs(EncoderNP[AXIS_ALT].getValue() - m_TrackStartSteps[AXIS_ALT]) / (ms/1000.)); + stopAxis(AXIS_AZ); + stopAxis(AXIS_ALT); + m_GuideOffset[AXIS_AZ] = m_GuideOffset[AXIS_ALT] = 0; + TrackState = SCOPE_IDLE; + + if (HorizontalCoordsNP.getState() != IPS_IDLE) + { + HorizontalCoordsNP.setState(IPS_IDLE); + HorizontalCoordsNP.apply(); + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// Rate is Celestron specific and roughly equals 80 ticks per 1 motor step +/// rate = 80 would cause the motor to spin at a rate of 1 step/s +/// Have to check if 80 is specific to my Evolution 6" or not. +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::trackByRate(INDI_HO_AXIS axis, int32_t rate) +{ + if (std::abs(rate) > 0 && rate == m_LastTrackRate[axis]) + return true; + + m_LastTrackRate[axis] = rate; + AUXCommand command(rate < 0 ? MC_SET_NEG_GUIDERATE : MC_SET_POS_GUIDERATE, APP, axis == AXIS_AZ ? AZM : ALT); + // 24bit rate + command.setData(std::abs(rate), 3); + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::trackByMode(INDI_HO_AXIS axis, uint8_t mode) +{ + AUXCommand command(isNorthHemisphere() ? MC_SET_POS_GUIDERATE : MC_SET_NEG_GUIDERATE, APP, axis == AXIS_AZ ? AZM : ALT); + switch (mode) + { + case TRACK_SOLAR: + command.setData(AUX_SOLAR, 2); + break; + case TRACK_LUNAR: + command.setData(AUX_LUNAR, 2); + break; + case TRACK_SIDEREAL: + default: + command.setData(AUX_SIDEREAL, 2); + break; + } + + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::SetTrackEnabled(bool enabled) +{ + if (enabled) + { + TrackState = SCOPE_TRACKING; + resetTracking(); + m_SkyTrackingTarget.rightascension = EqN[AXIS_RA].value; + m_SkyTrackingTarget.declination = EqN[AXIS_DE].value; + + if (IUFindOnSwitchIndex(&TrackModeSP) == TRACK_CUSTOM) + return SetTrackRate(TrackRateN[AXIS_AZ].value, TrackRateN[AXIS_ALT].value); + else + return SetTrackMode(IUFindOnSwitchIndex(&TrackModeSP)); + } + else + { + TrackState = SCOPE_IDLE; + trackByRate(AXIS_AZ, 0); + trackByRate(AXIS_ALT, 0); + + if (HorizontalCoordsNP.getState() != IPS_IDLE) + { + HorizontalCoordsNP.setState(IPS_IDLE); + HorizontalCoordsNP.apply(); + } + } + + return true; +}; + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::SetTrackRate(double raRate, double deRate) +{ + m_TrackRates[AXIS_AZ] = raRate; + m_TrackRates[AXIS_ALT] = deRate; + + if (TrackState == SCOPE_TRACKING) + { + + double steps[2] = {0, 0}; + // rate = (steps) * gain + steps[AXIS_AZ] = raRate * STEPS_PER_ARCSEC * GAIN_STEPS; + steps[AXIS_ALT] = deRate * STEPS_PER_ARCSEC * GAIN_STEPS; + trackByRate(AXIS_AZ, steps[AXIS_AZ]); + trackByRate(AXIS_ALT, steps[AXIS_ALT]); + } + return true; +} + +///////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::SetTrackMode(uint8_t mode) +{ + if (mode == TRACK_SIDEREAL) + m_TrackRates[AXIS_AZ] = TRACKRATE_SIDEREAL; + else if (mode == TRACK_SOLAR) + m_TrackRates[AXIS_AZ] = TRACKRATE_SOLAR; + else if (mode == TRACK_LUNAR) + m_TrackRates[AXIS_AZ] = TRACKRATE_LUNAR; + else if (mode == TRACK_CUSTOM) + { + m_TrackRates[AXIS_AZ] = TrackRateN[AXIS_RA].value; + m_TrackRates[AXIS_ALT] = TrackRateN[AXIS_DE].value; + } + + if (TrackState == SCOPE_TRACKING) + { + if (mode == TRACK_CUSTOM) + { + double steps[2] = {0, 0}; + // rate = (steps) * gain + steps[AXIS_AZ] = m_TrackRates[AXIS_AZ] * STEPS_PER_ARCSEC * GAIN_STEPS; + steps[AXIS_ALT] = m_TrackRates[AXIS_ALT] * STEPS_PER_ARCSEC * GAIN_STEPS; + trackByRate(AXIS_AZ, steps[AXIS_AZ]); + trackByRate(AXIS_ALT, steps[AXIS_ALT]); + } + else + trackByMode(AXIS_AZ, mode); + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::getStatus(INDI_HO_AXIS axis) +{ + if (m_AxisStatus[axis] == SLEWING && ScopeStatus != SLEWING_MANUAL) + { + AUXCommand command(MC_SLEW_DONE, APP, axis == AXIS_AZ ? AZM : ALT); + sendAUXCommand(command); + readAUXResponse(command); + } + + return true; +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::getEncoder(INDI_HO_AXIS axis) +{ + AUXCommand command(MC_GET_POSITION, APP, axis == AXIS_AZ ? AZM : ALT); + sendAUXCommand(command); + readAUXResponse(command); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// This is simple GPS emulation for HC. +/// If HC asks for the GPS we reply with data from our GPS/Site info. +/// We send reply blind (not reading any response) to avoid processing loop. +/// That is why the readAUXResponse calls are commented out. +/// This is OK since we are not going to do anything with the response anyway. +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::emulateGPS(AUXCommand &m) +{ + if (m.destination() != GPS) + return; + + LOGF_DEBUG("GPS: Got 0x%02x", m.command()); + if (m_GPSEmulation == false) + return; + + switch (m.command()) + { + case GET_VER: + { + LOGF_DEBUG("GPS: GET_VER from 0x%02x", m.source()); + AUXBuffer dat(2); + dat[0] = 0x01; + dat[1] = 0x02; + AUXCommand cmd(GET_VER, GPS, m.source(), dat); + sendAUXCommand(cmd); + //readAUXResponse(cmd); + break; + } + case GPS_GET_LAT: + case GPS_GET_LONG: + { + LOGF_DEBUG("GPS: Sending LAT/LONG Lat:%f Lon:%f", LocationN[LOCATION_LATITUDE].value, + LocationN[LOCATION_LONGITUDE].value); + AUXCommand cmd(m.command(), GPS, m.source()); + if (m.command() == GPS_GET_LAT) + cmd.setData(STEPS_PER_DEGREE * LocationN[LOCATION_LATITUDE].value); + else + cmd.setData(STEPS_PER_DEGREE * LocationN[LOCATION_LONGITUDE].value); + sendAUXCommand(cmd); + //readAUXResponse(cmd); + break; + } + case GPS_GET_TIME: + { + LOGF_DEBUG("GPS: GET_TIME from 0x%02x", m.source()); + time_t gmt; + struct tm *ptm; + AUXBuffer dat(3); + + time(&gmt); + ptm = gmtime(&gmt); + dat[0] = unsigned(ptm->tm_hour); + dat[1] = unsigned(ptm->tm_min); + dat[2] = unsigned(ptm->tm_sec); + AUXCommand cmd(GPS_GET_TIME, GPS, m.source(), dat); + sendAUXCommand(cmd); + //readAUXResponse(cmd); + break; + } + case GPS_GET_DATE: + { + LOGF_DEBUG("GPS: GET_DATE from 0x%02x", m.source()); + time_t gmt; + struct tm *ptm; + AUXBuffer dat(2); + + time(&gmt); + ptm = gmtime(&gmt); + dat[0] = unsigned(ptm->tm_mon + 1); + dat[1] = unsigned(ptm->tm_mday); + AUXCommand cmd(GPS_GET_DATE, GPS, m.source(), dat); + sendAUXCommand(cmd); + //readAUXResponse(cmd); + break; + } + case GPS_GET_YEAR: + { + LOGF_DEBUG("GPS: GET_YEAR from 0x%02x", m.source()); + time_t gmt; + struct tm *ptm; + AUXBuffer dat(2); + + time(&gmt); + ptm = gmtime(&gmt); + dat[0] = unsigned(ptm->tm_year + 1900) >> 8; + dat[1] = unsigned(ptm->tm_year + 1900) & 0xFF; + LOGF_DEBUG("GPS: Sending: %d [%d,%d]", ptm->tm_year, dat[0], dat[1]); + AUXCommand cmd(GPS_GET_YEAR, GPS, m.source(), dat); + sendAUXCommand(cmd); + //readAUXResponse(cmd); + break; + } + case GPS_LINKED: + { + LOGF_DEBUG("GPS: LINKED from 0x%02x", m.source()); + AUXBuffer dat(1); + + dat[0] = unsigned(1); + AUXCommand cmd(GPS_LINKED, GPS, m.source(), dat); + sendAUXCommand(cmd); + //readAUXResponse(cmd); + break; + } + default: + LOGF_DEBUG("GPS: Got 0x%02x", m.command()); + break; + } +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::processResponse(AUXCommand &m) +{ + m.logResponse(); + + if ((m.destination() == GPS) && (m.source() != APP)) + { + // Avoid infinite loop by not responding to ourselves + emulateGPS(m); + } + else if (m.destination() == APP) + switch (m.command()) + { + case MC_GET_POSITION: + switch (m.source()) + { + case ALT: + EncoderNP[AXIS_ALT].setValue(m.getData()); + break; + case AZM: + EncoderNP[AXIS_AZ].setValue(m.getData()); + break; + default: + break; + } + break; + case MC_SLEW_DONE: + switch (m.source()) + { + case ALT: + m_AxisStatus[AXIS_ALT] = (m.getData() == 0xff) ? STOPPED : SLEWING; + break; + case AZM: + m_AxisStatus[AXIS_AZ] = (m.getData() == 0xff) ? STOPPED : SLEWING; + break; + default: + break; + } + break; + case MC_POLL_CORDWRAP: + if (m.source() == AZM) + m_CordWrapActive = m.getData() == 0xff; + break; + case MC_GET_CORDWRAP_POS: + if (m.source() == AZM) + m_CordWrapPosition = m.getData(); + break; + + case MC_GET_AUTOGUIDE_RATE: + switch (m.source()) + { + case ALT: + GuideRateNP[AXIS_ALT].setValue(m.getData() / 255.); + break; + case AZM: + GuideRateNP[AXIS_AZ].setValue(m.getData() * 255.); + break; + default: + break; + } + break; + + case MC_SET_AUTOGUIDE_RATE: + // Nothing to do. + break; + + case MC_AUX_GUIDE: + // Nothing to do + break; + + case MC_LEVEL_DONE: + m_HomingProgress[AXIS_ALT] = m.getData() == 0x00; + break; + + case MC_SEEK_DONE: + m_HomingProgress[AXIS_AZ] = m.getData() == 0x00; + break; + + case MC_AUX_GUIDE_ACTIVE: + switch (m.source()) + { + case ALT: + if (m.getData() == 0x00) + GuideComplete(AXIS_DE); + break; + case AZM: + if (m.getData() == 0x00) + GuideComplete(AXIS_RA); + break; + default: + break; + } + break; + + case GET_VER: + { + uint8_t *verBuf = nullptr; + switch (m.source()) + { + case MB: + verBuf = m_MainBoardVersion; + break; + case ALT: + verBuf = m_AltitudeVersion; + break; + case AZM: + verBuf = m_AzimuthVersion; + break; + case HCP: + case HC: + verBuf = m_HCVersion; + break; + case BAT: + verBuf = m_BATVersion; + break; + case WiFi: + verBuf = m_WiFiVersion; + break; + case GPS: + verBuf = m_GPSVersion; + break; + case APP: + LOGF_DEBUG("Got echo of GET_VERSION from %s", m.moduleName(m.destination())); + break; + default: + break; + } + if (verBuf != nullptr) + { + size_t verBuflen = 4; + if ( verBuflen != m.dataSize()) + { + LOGF_DEBUG("Data and buffer size mismatch for GET_VER: buf[%d] vs data[%d]", verBuflen, m.dataSize()); + } + for (int i = 0; i < (int)std::min(verBuflen, m.dataSize()); i++) + verBuf[i] = m.data()[i]; + } + } + break; + default: + break; + + } + else + { + DEBUGF(DBG_CAUX, "Got msg not for me (%s). Ignoring.", m.moduleName(m.destination())); + } + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::serialReadResponse(AUXCommand c) +{ + int n; + unsigned char buf[32]; + char hexbuf[24]; + AUXCommand cmd; + + // We are not connected. Nothing to do. + if ( PortFD <= 0 ) + return false; + + if (m_IsRTSCTS || !m_isHandController) + { + // if connected to AUX or PC ports, receive AUX command response. + // search for packet preamble (0x3b) + do + { + if (aux_tty_read((char*)buf, 1, READ_TIMEOUT, &n) != TTY_OK) + return false; + } + while (buf[0] != 0x3b); + + // packet preamble is found, now read packet length. + if (aux_tty_read((char*)(buf + 1), 1, READ_TIMEOUT, &n) != TTY_OK) + return false; + + // now packet length is known, read the rest of the packet. + if (aux_tty_read((char*)(buf + 2), buf[1] + 1, READ_TIMEOUT, &n) + != TTY_OK || n != buf[1] + 1) + { + LOG_DEBUG("Did not got whole packet. Dropping out."); + return false; + } + + AUXBuffer b(buf, buf + (n + 2)); + hex_dump(hexbuf, b, b.size()); + DEBUGF(DBG_SERIAL, "RES <%s>", hexbuf); + cmd.parseBuf(b); + } + else + { + // if connected to HC serial, build up the AUX command response from + // given AUX command and passthrough response without checksum. + // read passthrough response + if ((tty_read(PortFD, (char *)buf + 5, response_data_size + 1, READ_TIMEOUT, &n) != + TTY_OK) || (n != response_data_size + 1)) + return false; + + // if last char is not '#', there was an error. + if (buf[response_data_size + 5] != '#') + { + LOGF_ERROR("Resp. char %d is %2.2x ascii %c", n, buf[n + 5], (char)buf[n + 5]); + AUXBuffer b(buf, buf + (response_data_size + 5)); + hex_dump(hexbuf, b, b.size()); + LOGF_ERROR("RES <%s>", hexbuf); + return false; + } + + buf[0] = 0x3b; + buf[1] = response_data_size + 1; + buf[2] = c.destination(); + buf[3] = c.source(); + buf[4] = c.command(); + + AUXBuffer b(buf, buf + (response_data_size + 5)); + hex_dump(hexbuf, b, b.size()); + DEBUGF(DBG_SERIAL, "RES (%d B): <%s>", (int)b.size(), hexbuf); + cmd.parseBuf(b, false); + } + + // Got the packet, process it + // n:length field >=3 + // The buffer of n+2>=5 bytes contains: + // 0x3b =3> + + DEBUGF(DBG_SERIAL, "Got %d bytes: ; payload length field: %d ; MSG:", n, buf[1]); + logBytes(buf, n + 2, getDeviceName(), DBG_SERIAL); + processResponse(cmd); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::tcpReadResponse() +{ + int n, i; + unsigned char buf[BUFFER_SIZE] = {0}; + AUXCommand cmd; + + // We are not connected. Nothing to do. + if ( PortFD <= 0 ) + return false; + + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 50000; + setsockopt(PortFD, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); + + // Drain the channel + while ((n = recv(PortFD, buf, sizeof(buf), MSG_DONTWAIT | MSG_PEEK)) > 0) + { + // DEBUGF(DBG_CAUX, "Got %d bytes: ", n); + // for (i = 0; i < n; i++) + // IDLog("%02x ", buf[i]); + + for (i = 0; i < n;) + { + if (buf[i] == 0x3b) + { + int shft; + shft = i + buf[i + 1] + 3; + if (shft <= n) + { + AUXBuffer b(buf + i, buf + shft); + cmd.parseBuf(b); + + char hexbuf[32 * 3] = {0}; + hex_dump(hexbuf, b, b.size()); + DEBUGF(DBG_SERIAL, "RES <%s>", hexbuf); + + processResponse(cmd); + } + else + { + DEBUGF(DBG_SERIAL, "Partial message recv. dropping (i=%d %d/%d)", i, shft, n); + logBytes(buf + i, n - i, getDeviceName(), DBG_SERIAL); + recv(PortFD, buf, n, MSG_DONTWAIT); + break; + } + i = shft; + } + else + { + i++; + } + } + // Actually consume data we parsed. Leave the rest for later. + if (i > 0) + { + n = recv(PortFD, buf, i, MSG_DONTWAIT); + //DEBUGF(DBG_CAUX, "Consumed %d/%d bytes", n, i); + } + } + return true; +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::readAUXResponse(AUXCommand c) +{ + if (getActiveConnection() == serialConnection) + return serialReadResponse(c); + else + return tcpReadResponse(); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +int CelestronAUX::sendBuffer(AUXBuffer buf) +{ + if ( PortFD > 0 ) + { + int n; + + if (aux_tty_write((char*)buf.data(), buf.size(), CTS_TIMEOUT, &n) != TTY_OK) + return 0; + + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + if (n == -1) + LOG_ERROR("CAUX::sendBuffer"); + if ((unsigned)n != buf.size()) + LOGF_WARN("sendBuffer: incomplete send n=%d size=%d", n, (int)buf.size()); + + char hexbuf[32 * 3] = {0}; + hex_dump(hexbuf, buf, buf.size()); + DEBUGF(DBG_SERIAL, "CMD <%s>", hexbuf); + + return n; + } + else + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::sendAUXCommand(AUXCommand &command) +{ + AUXBuffer buf; + command.logCommand(); + + if (m_IsRTSCTS || !m_isHandController || getActiveConnection() != serialConnection) + // Direct connection (AUX/PC/USB port) + command.fillBuf(buf); + else + { + // connection is through HC serial and destination is not HC, + // convert AUX command to a passthrough command + + // fixed len = 8 + buf.resize(8); + // prefix + buf[0] = 0x50; + // length + buf[1] = 1 + command.dataSize(); + // destination + buf[2] = command.destination(); + buf[3] = command.command(); // command id + for (size_t i = 0; i < command.dataSize(); i++) // payload + { + buf[i + 4] = command.data()[i]; + } + buf[7] = response_data_size = command.responseDataSize(); + } + + tcflush(PortFD, TCIOFLUSH); + return (sendBuffer(buf) == static_cast(buf.size())); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Wrap functions around the standard driver communication functions tty_read +// and tty_write. +// When the communication is serial, these wrap functions implement the +// Celestron hardware handshake used by telescope serial ports AUX and PC. +// When the communication is by network, these wrap functions are trasparent. +// Read and write calls are passed, as is, to the standard functions tty_read +// and tty_write. +// 16-Feb-2020 Fabrizio Pollastri +//////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::setRTS(bool rts) +{ + if (ioctl(PortFD, TIOCMGET, &m_ModemControl) == -1) + LOGF_ERROR("Error getting handshake lines %s(%d).", strerror(errno), errno); + if (rts) + m_ModemControl |= TIOCM_RTS; + else + m_ModemControl &= ~TIOCM_RTS; + if (ioctl(PortFD, TIOCMSET, &m_ModemControl) == -1) + LOGF_ERROR("Error setting handshake lines %s(%d).", strerror(errno), errno); +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::waitCTS(float timeout) +{ + float step = timeout / 20.; + for (; timeout >= 0; timeout -= step) + { + std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(step))); + if (ioctl(PortFD, TIOCMGET, &m_ModemControl) == -1) + { + LOGF_ERROR("Error getting handshake lines %s(%d).", strerror(errno), errno); + return 0; + } + if (m_ModemControl & TIOCM_CTS) + return 1; + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::detectRTSCTS() +{ + setRTS(1); + bool retval = waitCTS(300.); + setRTS(0); + return retval; +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::detectHC(char *version, size_t size) +{ + AUXBuffer b; + char buf[3]; + + b.resize(1); + b[0] = 'V'; + + // We are not connected. Nothing to do. + if ( PortFD <= 0 ) + return false; + + // send get firmware version command + if (sendBuffer(b) != (int)b.size()) + return false; + + // read response + int n; + if (aux_tty_read((char*)buf, 3, READ_TIMEOUT, &n) != TTY_OK) + return false; + + // non error response must end with '#' + if (buf[2] != '#') + return false; + + // return printable HC version + // fill in the version field + m_HCVersion[0] = static_cast(buf[0]); + m_HCVersion[1] = static_cast(buf[1]); + m_HCVersion[2] = 0; + m_HCVersion[3] = 0; + snprintf(version, size, "%d.%02d", static_cast(buf[0]), static_cast(buf[1])); + + return true; +} + + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +int CelestronAUX::aux_tty_read(char *buf, int bufsiz, int timeout, int *n) +{ + int errcode; + DEBUGF(DBG_SERIAL, "aux_tty_read: %d", PortFD); + + // if hardware flow control is required, set RTS to off to receive: PC port + // bahaves as half duplex. + if (m_IsRTSCTS) + setRTS(0); + + if((errcode = tty_read(PortFD, buf, bufsiz, timeout, n)) != TTY_OK) + { + char errmsg[MAXRBUF] = {0}; + tty_error_msg(errcode, errmsg, MAXRBUF); + LOGF_ERROR("%s", errmsg); + } + + return errcode; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +int CelestronAUX::aux_tty_write(char *buf, int bufsiz, float timeout, int *n) +{ + int errcode, ne; + char errmsg[MAXRBUF]; + + //DEBUGF(DBG_CAUX, "aux_tty_write: %d", PortFD); + + // if hardware flow control is required, set RTS to on then wait for CTS + // on to write: PC port bahaves as half duplex. RTS may be already on. + if (m_IsRTSCTS) + { + DEBUG(DBG_SERIAL, "aux_tty_write: set RTS"); + setRTS(1); + DEBUG(DBG_SERIAL, "aux_tty_write: wait CTS"); + if (!waitCTS(timeout)) + { + LOGF_ERROR("Error getting handshake lines %s(%d).\n", strerror(errno), errno); + return TTY_TIME_OUT; + } + } + + errcode = tty_write(PortFD, buf, bufsiz, n); + + if (errcode != TTY_OK) + { + tty_error_msg(errcode, errmsg, MAXRBUF); + LOGF_ERROR("%s", errmsg); + return errcode; + } + + // if hardware flow control is required, Wait for tx complete, set RTS to + // off, to receive (half duplex). + if (m_IsRTSCTS) + { + DEBUG(DBG_SERIAL, "aux_tty_write: clear RTS"); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + setRTS(0); + + // ports requiring hardware flow control echo all sent characters, + // verify them. + DEBUG(DBG_SERIAL, "aux_tty_write: verify echo"); + if ((errcode = tty_read(PortFD, errmsg, *n, READ_TIMEOUT, &ne)) != TTY_OK) + { + tty_error_msg(errcode, errmsg, MAXRBUF); + LOGF_ERROR("%s", errmsg); + return errcode; + } + + if (*n != ne) + return TTY_WRITE_ERROR; + + for (int i = 0; i < ne; i++) + if (buf[i] != errmsg[i]) + return TTY_WRITE_ERROR; + } + + return TTY_OK; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +bool CelestronAUX::tty_set_speed(speed_t speed) +{ + struct termios tty_setting; + + if (tcgetattr(PortFD, &tty_setting)) + { + LOGF_ERROR("Error getting tty attributes %s(%d).", strerror(errno), errno); + return false; + } + + if (cfsetspeed(&tty_setting, speed)) + { + LOGF_ERROR("Error setting serial speed %s(%d).", strerror(errno), errno); + return false; + } + + if (tcsetattr(PortFD, TCSANOW, &tty_setting)) + { + LOGF_ERROR("Error setting tty attributes %s(%d).", strerror(errno), errno); + return false; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// +/// +///////////////////////////////////////////////////////////////////////////////////// +void CelestronAUX::hex_dump(char *buf, AUXBuffer data, size_t size) +{ + for (size_t i = 0; i < size; i++) + sprintf(buf + 3 * i, "%02X ", data[i]); + + if (size > 0) + buf[3 * size - 1] = '\0'; +} + diff --git a/indi-celestronaux/celestronaux.h b/indi-celestronaux/celestronaux.h new file mode 100644 index 0000000..6a79280 --- /dev/null +++ b/indi-celestronaux/celestronaux.h @@ -0,0 +1,442 @@ +/* + Celestron Aux Mount Driver. + + Copyright (C) 2020 Paweł T. Jochym + Copyright (C) 2020 Fabrizio Pollastri + Copyright (C) 2020-2022 Jasem Mutlaq + + 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 + + JM 2022.07.07: Added Wedge support. +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "auxproto.h" + +class CelestronAUX : + public INDI::Telescope, + public INDI::GuiderInterface, + public INDI::AlignmentSubsystem::AlignmentSubsystemForDrivers +{ + public: + CelestronAUX(); + ~CelestronAUX() override; + + virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], + char *formats[], char *names[], int n) override; + virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override; + virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; + virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override; + virtual bool ISSnoopDevice(XMLEle *root) override; + + // Type defs + enum ScopeStatus_t + { + IDLE, + SLEWING_FAST, + APPROACH, + SLEWING_SLOW, + SLEWING_MANUAL, + TRACKING + }; + ScopeStatus_t ScopeStatus; + + enum AxisStatus + { + STOPPED, + SLEWING + }; + + enum AxisDirection + { + FORWARD, + REVERSE + }; + + // Previous motion direction + // TODO: Switch to AltAz from N-S/W-E + typedef enum + { + PREVIOUS_NS_MOTION_NORTH = DIRECTION_NORTH, + PREVIOUS_NS_MOTION_SOUTH = DIRECTION_SOUTH, + PREVIOUS_NS_MOTION_UNKNOWN = -1 + } PreviousNSMotion_t; + typedef enum + { + PREVIOUS_WE_MOTION_WEST = DIRECTION_WEST, + PREVIOUS_WE_MOTION_EAST = DIRECTION_EAST, + PREVIOUS_WE_MOTION_UNKNOWN = -1 + } PreviousWEMotion_t; + + // Public to enable setting from ISSnoop + void syncCoordWrapPosition(); + + protected: + virtual void ISGetProperties(const char *dev) override; + virtual bool initProperties() override; + virtual bool updateProperties() override; + virtual bool saveConfigItems(FILE *fp) override; + virtual bool Handshake() override; + virtual bool Disconnect() override; + + virtual const char *getDefaultName() override; + INDI::IHorizontalCoordinates AltAzFromRaDec(double ra, double dec, double ts); + + virtual bool Sync(double ra, double dec) override; + virtual bool Goto(double ra, double dec) override; + virtual bool Abort() override; + virtual bool Park() override; + virtual bool UnPark() override; + + virtual IPState GuideNorth(uint32_t ms) override; + virtual IPState GuideSouth(uint32_t ms) override; + virtual IPState GuideEast(uint32_t ms) override; + virtual IPState GuideWest(uint32_t ms) override; + + //virtual bool HandleGetAutoguideRate(INDI_HO_AXIS axis, uint8_t rate); + //virtual bool HandleSetAutoguideRate(INDI_EQ_AXIS axis); + //virtual bool HandleGuidePulse(INDI_EQ_AXIS axis); + //virtual bool HandleGuidePulseDone(INDI_EQ_AXIS axis, bool done); + + // TODO: Switch to AltAz from N-S/W-E + virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override; + virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override; + + virtual bool ReadScopeStatus() override; + virtual void TimerHit() override; + virtual bool updateLocation(double latitude, double longitude, double elevation) override; + + ///////////////////////////////////////////////////////////////////////////////////// + /// Motion Control + ///////////////////////////////////////////////////////////////////////////////////// + bool stopAxis(INDI_HO_AXIS axis); + bool isSlewing(); + + /** + * @brief SlewTo Go to a 24bit encoder position. + * @param axis AZ or ALT + * @param steps Encoder microsteps + * @param fast If true, use fast command to reach target. If false, use slow command. + * @return True if successful, false otherwise. + */ + bool slewTo(INDI_HO_AXIS axis, uint32_t steps, bool fast = true); + + /** + * @brief SlewByRate Slew an axis using variable rate speed. + * @param axis AZ or ALT + * @param rate -9 to +9. 0 means stop. + * For AZ, negative means left while positive means right. + * For Alt, negative is down while positive is up. + * @return True if successful, false otherwise. + */ + bool slewByRate(INDI_HO_AXIS axis, int8_t rate); + + // Go to index position or level + bool goHome(INDI_HO_AXIS axis); + bool isHomingDone(INDI_HO_AXIS axis); + bool m_HomingProgress[2] = {false, false}; + + ///////////////////////////////////////////////////////////////////////////////////// + /// Tracking + ///////////////////////////////////////////////////////////////////////////////////// + bool SetTrackEnabled(bool enabled) override; + bool SetTrackMode(uint8_t mode) override; + bool SetTrackRate(double raRate, double deRate) override; + void resetTracking(); + + /** + * @brief TrackByRate Set axis tracking rate in arcsecs/sec. + * @param axis AZ or ALT + * @param rate arcsecs/s. Zero would stop tracking. + * For AZ, negative means left while positive means right. + * For Alt, negative is down while positive is up. + * @return True if successful, false otherwise. + */ + bool trackByRate(INDI_HO_AXIS axis, int32_t rate); + + /** + * @brief trackByRate Track using specific mode (sidereal, solar, or lunar) + * @param axis AZ or ALT + * @param mode sidereal, solar, or lunar + * @return True if successful, false otherwise. + */ + bool trackByMode(INDI_HO_AXIS axis, uint8_t mode); + bool isTrackingRequested(); + + bool getStatus(INDI_HO_AXIS axis); + bool getEncoder(INDI_HO_AXIS axis); + + ///////////////////////////////////////////////////////////////////////////////////// + /// Coord Wrap + ///////////////////////////////////////////////////////////////////////////////////// + bool setCordWrapEnabled(bool enable); + bool getCordWrapEnabled(); + bool setCordWrapPosition(uint32_t steps); + uint32_t getCordWrapPosition(); + + private: + ///////////////////////////////////////////////////////////////////////////////////// + /// Misc + ///////////////////////////////////////////////////////////////////////////////////// + double getNorthAz(); + bool isNorthHemisphere() const + { + return m_Location.latitude >= 0; + } + bool getVersion(AUXTargets target); + void getVersions(); + void hex_dump(char *buf, AUXBuffer data, size_t size); + + + double AzimuthToDegrees(double degree); + double DegreesToAzimuth(double degree); + + double EncodersToDegrees(uint32_t steps); + uint32_t DegreesToEncoders(double degrees); + + double EncodersToHours(uint32_t steps); + uint32_t HoursToEncoders(double hour); + + double EncodersToDE(uint32_t steps, TelescopePierSide pierSide); + double DEToEncoders(double de); + + void EncodersToAltAz(INDI::IHorizontalCoordinates &coords); + void EncodersToRADE(INDI::IEquatorialCoordinates &coords, TelescopePierSide &pierSide); + void RADEToEncoders(const INDI::IEquatorialCoordinates &coords, uint32_t &haEncoder, uint32_t &deEncoder); + + /** + * @brief mountToSkyCoords Convert mount coordinates to equatorial sky coordinates + * @return True if successful, false otherwise. + * @note This works for both Alt-Az and Equatorial Mounts. + */ + bool mountToSkyCoords(); + ///////////////////////////////////////////////////////////////////////////////////// + /// Guiding + ///////////////////////////////////////////////////////////////////////////////////// + bool guidePulse(INDI_EQ_AXIS axis, uint32_t ms, int8_t rate); + + + private: + // Axis Information + AxisStatus m_AxisStatus[2] {STOPPED, STOPPED}; + AxisDirection m_AxisDirection[2] {FORWARD, FORWARD}; + + // Guiding offset in steps + // For each pulse, we modify the offset so that we can add it to our current tracking traget + int32_t m_GuideOffset[2] = {0, 0}; + double m_TrackRates[2] = {TRACKRATE_SIDEREAL, 0}; + + // approach distance + double Approach {1}; + TelescopePierSide m_TargetPierSide {PIER_UNKNOWN}; + + // Tracking targets + INDI::IEquatorialCoordinates m_SkyTrackingTarget { 0, 0 }; + INDI::IEquatorialCoordinates m_SkyGOTOTarget { 0, 0 }; + + // Actual Sky Equatorial Coordinates + INDI::IEquatorialCoordinates m_SkyCurrentRADE {0, 0}; + + // Current Mount Alt/Az or RA/DE + INDI::IEquatorialCoordinates m_MountCurrentRADE {0, 0}; + INDI::IHorizontalCoordinates m_MountCurrentAltAz {0, 0}; + + INDI::ElapsedTimer m_TrackingElapsedTimer; + + + ///////////////////////////////////////////////////////////////////////////////////// + /// Auxiliary Command Communication + ///////////////////////////////////////////////////////////////////////////////////// + bool sendAUXCommand(AUXCommand &command); + void closeConnection(); + void emulateGPS(AUXCommand &m); + bool serialReadResponse(AUXCommand c); + bool tcpReadResponse(); + bool readAUXResponse(AUXCommand c); + bool processResponse(AUXCommand &cmd); + int sendBuffer(AUXBuffer buf); + void formatVersionString(char *s, int n, uint8_t *verBuf); + + // GPS Emulation + bool m_GPSEmulation {false}; + + // Firmware + uint8_t m_MainBoardVersion[4] {0}; + uint8_t m_AltitudeVersion[4] {0}; + uint8_t m_AzimuthVersion[4] {0}; + uint8_t m_HCVersion[4] {0}; + uint8_t m_BATVersion[4] {0}; + uint8_t m_WiFiVersion[4] {0}; + uint8_t m_GPSVersion[4] {0}; + + // Coord Wrap + bool m_CordWrapActive {false}; + int32_t m_CordWrapPosition {0}; + uint32_t m_RequestedCordwrapPos; + + // Manual Slewing NSWE + bool m_ManualMotionActive { false }; + + // Debug + uint32_t DBG_CAUX {0}; + uint32_t DBG_SERIAL {0}; + + /////////////////////////////////////////////////////////////////////////////// + /// Communication + /////////////////////////////////////////////////////////////////////////////// + int m_ModemControl {0}; + void setRTS(bool rts); + bool waitCTS(float timeout); + bool detectRTSCTS(); + bool detectHC(char *version, size_t size); + int response_data_size; + int aux_tty_read(char *buf, int bufsiz, int timeout, int *n); + int aux_tty_write (char *buf, int bufsiz, float timeout, int *n); + bool tty_set_speed(speed_t speed); + + // connection + bool m_IsRTSCTS {false}; + bool m_isHandController {false}; + + /////////////////////////////////////////////////////////////////////////////// + /// Celestron AUX Properties + /////////////////////////////////////////////////////////////////////////////// + + // Firmware + INDI::PropertyText FirmwareTP {7}; + enum {FW_HC, FW_MB, FW_AZM, FW_ALT, FW_WiFi, FW_BAT, FW_GPS}; + // Mount type + INDI::PropertySwitch MountTypeSP {2}; + enum + { + MOUNT_EQUATORIAL, + MOUNT_ALTAZ + }; + + // Mount Cord wrap Toogle + INDI::PropertySwitch CordWrapToggleSP {2}; + + // Mount Coord wrap Position + INDI::PropertySwitch CordWrapPositionSP {4}; + enum { CORDWRAP_N, CORDWRAP_E, CORDWRAP_S, CORDWRAP_W }; + + // Cordwrap base (0-encoder/True directions) + // Use 0-encoders / Sky directions as base for parking and cordwrap + INDI::PropertySwitch CordWrapBaseSP {2}; + enum {CW_BASE_ENC, CW_BASE_SKY}; + + // GPS emulator + INDI::PropertySwitch GPSEmuSP {2}; + enum { GPSEMU_OFF, GPSEMU_ON }; + + // Horizontal Coords + INDI::PropertyNumber HorizontalCoordsNP {2}; + + // Guide Rate + INDI::PropertyNumber GuideRateNP {2}; + + // Encoders + INDI::PropertyNumber EncoderNP {2}; + // Angles + INDI::PropertyNumber AngleNP {2}; + + int32_t m_LastTrackRate[2] = {-1, -1}; + double m_TrackStartSteps[2] = {0, 0}; + double m_LastOffset[2] = {0, 0}; + uint8_t m_OffsetSwitchSettle[2] = {0, 0}; + bool m_IsWedge {false}; + + // PID controllers + INDI::PropertyNumber Axis1PIDNP {3}; + INDI::PropertyNumber Axis2PIDNP {3}; + enum + { + Propotional, + Derivative, + Integral + }; + + std::unique_ptr m_Controllers[2]; + + INDI::PropertySwitch PortTypeSP {2}; + enum + { + PORT_AUX_PC, + PORT_HC_USB, + }; + + int m_ConfigPortType {PORT_AUX_PC}; + + // Home/Level + INDI::PropertySwitch HomeSP {3}; + enum + { + HOME_AXIS1, + HOME_AXIS2, + HOME_ALL + }; + //INDI::PropertyNumber GainNP {2}; + /////////////////////////////////////////////////////////////////////////////// + /// Static Const Private Variables + /////////////////////////////////////////////////////////////////////////////// + + private: + + // One definition rule (ODR) constants + // AUX commands use 24bit integer as a representation of angle in units of + // fractional revolutions. Thus 2^24 steps makes full revolution. + static constexpr int32_t STEPS_PER_REVOLUTION {16777216}; + static constexpr double STEPS_PER_DEGREE {STEPS_PER_REVOLUTION / 360.0}; + static constexpr double STEPS_PER_ARCSEC {STEPS_PER_DEGREE / 3600.0}; + static constexpr double DEGREES_PER_STEP {360.0 / STEPS_PER_REVOLUTION}; + + static constexpr double STEPS_PER_HOUR {STEPS_PER_REVOLUTION / 24.0}; + static constexpr double HOURS_PER_STEP {24.0 / STEPS_PER_REVOLUTION}; + + // Measured rate that would result in 1 step/sec + static constexpr uint32_t GAIN_STEPS {80}; + + // MC_SET_POS_GUIDERATE & MC_SET_NEG_GUIDERATE use 24bit number rate in + static constexpr uint8_t RATE_PER_ARCSEC {4}; + + static constexpr uint32_t BUFFER_SIZE {10240}; + // seconds + static constexpr uint8_t READ_TIMEOUT {1}; + // ms + static constexpr uint8_t CTS_TIMEOUT {100}; + // Coord Wrap + static constexpr const char *CORDWRAP_TAB {"Coord Wrap"}; + static constexpr const char *MOUNTINFO_TAB {"Mount Info"}; + // Track modes + static constexpr uint16_t AUX_SIDEREAL {0xffff}; + static constexpr uint16_t AUX_SOLAR {0xfffe}; + static constexpr uint16_t AUX_LUNAR {0xfffd}; + + +}; diff --git a/indi-celestronaux/config.h.cmake b/indi-celestronaux/config.h.cmake new file mode 100644 index 0000000..be71a44 --- /dev/null +++ b/indi-celestronaux/config.h.cmake @@ -0,0 +1,10 @@ +#ifndef CONFIG_H +#define CONFIG_H + +/* Define INDI Data Dir */ +#cmakedefine INDI_DATA_DIR "@INDI_DATA_DIR@" +/* Define Driver version */ +#define CAUX_VERSION_MAJOR @CAUX_VERSION_MAJOR@ +#define CAUX_VERSION_MINOR @CAUX_VERSION_MINOR@ + +#endif // CONFIG_H diff --git a/indi-celestronaux/indi-celestronaux.spec b/indi-celestronaux/indi-celestronaux.spec new file mode 100644 index 0000000..20ba305 --- /dev/null +++ b/indi-celestronaux/indi-celestronaux.spec @@ -0,0 +1,79 @@ +%define __cmake_in_source_build %{_vpath_builddir} +Name: indi-celestronaux +Version:1.9.8.git +Release: %(date -u +%%Y%%m%%d%%H%%M%%S)%{?dist} +Summary: Instrument Neutral Distributed Interface 3rd party drivers + +License: LGPLv2 +# See COPYRIGHT file for a description of the licenses and files covered + +URL: https://indilib.org +Source0: https://github.com/indilib/indi-3rdparty/archive/master.tar.gz + +BuildRequires: cmake +BuildRequires: libfli-devel +BuildRequires: libnova-devel +BuildRequires: qt5-qtbase-devel +BuildRequires: systemd +BuildRequires: gphoto2-devel +BuildRequires: LibRaw-devel +BuildRequires: indi-libs +BuildRequires: indi-devel +BuildRequires: libtiff-devel +BuildRequires: cfitsio-devel +BuildRequires: zlib-devel +BuildRequires: gsl-devel +BuildRequires: libcurl-devel +BuildRequires: libjpeg-turbo-devel +BuildRequires: fftw-devel +BuildRequires: libftdi-devel +BuildRequires: gpsd-devel +BuildRequires: libdc1394-devel +BuildRequires: boost-devel +BuildRequires: boost-regex + +BuildRequires: gmock + +BuildRequires: pkgconfig(fftw3) +BuildRequires: pkgconfig(cfitsio) +BuildRequires: pkgconfig(libcurl) +BuildRequires: pkgconfig(gsl) +BuildRequires: pkgconfig(libjpeg) +BuildRequires: pkgconfig(libusb-1.0) +BuildRequires: pkgconfig(zlib) + + +%description +INDI is a distributed control protocol designed to operate +astronomical instrumentation. INDI is small, flexible, easy to parse, +and scalable. It supports common DCS functions such as remote control, +data acquisition, monitoring, and a lot more. This is a 3rd party driver. + + +%prep -v +%autosetup -v -p1 -n indi-3rdparty-master + +%build +# This package tries to mix and match PIE and PIC which is wrong and will +# trigger link errors when LTO is enabled. +# Disable LTO +%define _lto_cflags %{nil} + +cd indi-celestronaux +%cmake -DINDI_DATA_DIR=/usr/share/indi . +make VERBOSE=1 %{?_smp_mflags} -j4 + +%install +cd indi-celestronaux +make DESTDIR=%{buildroot} install + +%files +%license LICENSE +%{_bindir}/* +%{_datadir}/indi/indi_celestronaux.xml + + +%changelog +* Sun Jul 19 2020 Jim Howard 1.8.7.git-1 +- update to build from git for copr, credit to Sergio Pascual and Christian Dersch for prior work on spec files + diff --git a/indi-celestronaux/indi_celestronaux.xml.cmake b/indi-celestronaux/indi_celestronaux.xml.cmake new file mode 100644 index 0000000..749b0e2 --- /dev/null +++ b/indi-celestronaux/indi_celestronaux.xml.cmake @@ -0,0 +1,33 @@ + + + + + indi_celestron_aux + @CAUX_VERSION_MAJOR@.@CAUX_VERSION_MINOR@ + + + indi_celestron_aux + @CAUX_VERSION_MAJOR@.@CAUX_VERSION_MINOR@ + + + indi_celestron_aux + @CAUX_VERSION_MAJOR@.@CAUX_VERSION_MINOR@ + + + indi_celestron_aux + @CAUX_VERSION_MAJOR@.@CAUX_VERSION_MINOR@ + + + indi_celestron_aux + @CAUX_VERSION_MAJOR@.@CAUX_VERSION_MINOR@ + + + indi_celestron_aux + @CAUX_VERSION_MAJOR@.@CAUX_VERSION_MINOR@ + + + indi_celestron_aux + @CAUX_VERSION_MAJOR@.@CAUX_VERSION_MINOR@ + + + diff --git a/indi-celestronaux/simulator/nse_simulator.py b/indi-celestronaux/simulator/nse_simulator.py new file mode 100644 index 0000000..5a3ceb6 --- /dev/null +++ b/indi-celestronaux/simulator/nse_simulator.py @@ -0,0 +1,259 @@ +#!/bin/env python3 + +import asyncio +import signal +import socket +import sys +from socket import SOL_SOCKET, SO_BROADCAST, SO_REUSEADDR +from nse_telescope import NexStarScope, repr_angle + +import curses + +telescope=None + +async def broadcast(sport=2000, dport=55555, host='255.255.255.255', seconds_to_sleep=5): + sck = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sck.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) + sck.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) + # Fake msg. The app does not care for the payload + msg = 110*b'X' + sck.bind(('',sport)) + telescope.print_msg('Broadcasting to port {0}'.format(dport)) + telescope.print_msg('sleeping for: {0} seconds'.format(seconds_to_sleep)) + while True : + bn = sck.sendto(msg,(host,dport)) + await asyncio.sleep(seconds_to_sleep) + telescope.print_msg('Stopping broadcast') + +async def timer(seconds_to_sleep=1,telescope=None): + from time import time + t=time() + while True : + await asyncio.sleep(seconds_to_sleep) + if telescope : + telescope.tick(time()-t) + t=time() + +async def handle_port2000(reader, writer): + ''' + This function handles initial communication with the WiFly module and + delegates the real job of simulating the scope to the NexStarScope class. + It also handles all the dirty details of actual communication. + ''' + + # The WiFly module is initially in the transparent mode and just passes + # the data to the serial connection. Unless the '$$$' sequence is detected. + # Then it switches to the command mode until the exit command is issued. + # The $$$ should be guarded by the 1s silence. + transparent=True + retry = 5 + global telescope + # Endless comm loop. + connected=False + while True : + data = await reader.read(1024) + if not data : + writer.close() + telescope.print_msg('Connection closed. Closing server.') + return + elif not connected : + telescope.print_msg('App from {0} connected.'.format(writer.get_extra_info('peername'))) + connected=True + retry = 5 + addr = writer.get_extra_info('peername') + #print("-> Scope received %r from %r." % (data, addr)) + resp = b'' + if transparent : + if data[:3]==b'$$$' : + # Enter command mode + transparent = False + telescope.print_msg('App from {0} connected.'.format(addr)) + resp = b'CMD\r\n' + else : + # pass it on to the scope for handling + resp = telescope.handle_msg(data) + else : + # We are in command mode detect exit and get out. + # Otherwise just echo what we got and ack. + message = b'' + try : + message = data.decode('ascii').strip() + except UnicodeError : + # The data is invalid ascii - ignore it + pass + if message == 'exit' : + # get out of the command mode + transparent = True + resp = data + b'\r\nEXIT\r\n' + else : + resp = data + b'\r\nAOK\r\n<2.40-CEL> ' + if resp : + #print("<- Server sending: %r" % resp ) + writer.write(resp) + await writer.drain() + +#def signal_handler(signal, frame): +# loop.stop() +# sys.exit(0) + +#signal.signal(signal.SIGINT, signal_handler) + +def to_be(n, size): + b=bytearray(size) + i=size-1 + while i >= 0: + b[i] = n % 256 + n = n >> 8 + i -= 1 + return b +def from_be(b): + n=0 + for i in range(len(b)): + n = (n << 8) + b[i] + return n +def to_le(n, size): + b=bytearray(size) + i=0 + while i < size: + b[i] = n % 256 + n = n >> 8 + i += 1 + return b +def from_le(b): + n=0 + for i in range(len(b)-1, -1, -1): + n = (n << 8) + b[i] + return n + + +def handle_stellarium_cmd(tel, d): + import time + p=0 + while p < len(d)-2: + psize=from_le(d[p:p+2]) + if (psize > len(d) - p): + break + ptype=from_le(d[p+2:p+4]) + if ptype == 0: + micros=from_le(d[p+4:p+12]) + if abs((micros/1000000.0) - int(time.time())) > 60.0: + tel.print_msg('Client clock differs for more than one minute: '+str(int(micros/1000000.0))+'/'+str(int(time.time()))) + targetraint=from_le(d[p+12:p+16]) + targetdecint=from_le(d[p+16:p+20]) + if (targetdecint > (4294967296 / 2)): + targetdecint = - (4294967296 - targetdecint) + targetra=(targetraint * 24.0) / 4294967296.0 + targetdec=(targetdecint * 360.0) / 4294967296.0 + tel.print_msg('GoTo {} {}'.format(repr_angle(targetra/360), + repr_angle(targetdec/360))) + p+=psize + else: + # No such cmd + tel.print_msg('Stellarium: unknown command ({})'.format(ptype)) + p+=psize + return p + +def make_stellarium_status(tel,obs): + import math + import time + import ephem + from math import pi + + alt=tel.alt + azm=tel.azm + obs.date=ephem.now() + rajnow, decjnow=obs.radec_of(azm*2*pi, alt*2*pi) + rajnow/=2*pi + decjnow/=2*pi + status=0 + msg=bytearray(24) + msg[0:2]=to_le(24, 2) + msg[2:4]=to_le(0, 2) + tstamp=int(time.time()) + msg[4:12]=to_le(tstamp, 8) + msg[12:16]=to_le(int(math.floor(rajnow * 4294967296.0)), 4) + msg[16:20]=to_le(int(math.floor(decjnow * 4294967296.0)), 4) + msg[20:24]=to_le(status, 4) + return msg + + +connections = [] + +async def report_scope_pos(sleep=0.1, scope=None, obs=None): + while True: + await asyncio.sleep(sleep) + for tr in connections: + tr.write(make_stellarium_status(scope,obs)) + + +class StellariumServer(asyncio.Protocol): + + def __init__(self, *arg, **kwarg): + import ephem + global telescope + + self.obs = ephem.Observer() + self.obs.lon, self.obs.lat = '20:02', '50:05' + self.telescope=telescope + asyncio.Protocol.__init__(self,*arg,**kwarg) + + def connection_made(self, transport): + peername = transport.get_extra_info('peername') + if self.telescope is not None: + self.telescope.print_msg('Stellarium from {}\n'.format(peername)) + self.transport = transport + connections.append(transport) + + def connection_lost(self, exc): + try: + connections.remove(self.transport) + self.telescope.print_msg('Stellarium connection closed\n') + except ValueError: + pass + + def data_received(self,data): + if self.telescope is not None: + handle_stellarium_cmd(telescope,data) + +def main(stdscr): + import ephem + + global telescope + + obs = ephem.Observer() + obs.lon, obs.lat = '20:02', '50:05' + + if len(sys.argv) >1 and sys.argv[1]=='t': + telescope = NexStarScope(stdscr=None) + else : + telescope = NexStarScope(stdscr=stdscr) + + loop = asyncio.get_event_loop() + + scope = loop.run_until_complete( + asyncio.start_server(handle_port2000, host='', port=2000)) + + stell = loop.run_until_complete( + loop.create_server(StellariumServer,host='',port=10001)) + + telescope.print_msg('NSE simulator strted on {}.'.format(scope.sockets[0].getsockname())) + telescope.print_msg('Hit CTRL-C to stop.') + + asyncio.ensure_future(broadcast()) + asyncio.ensure_future(timer(0.1,telescope)) + asyncio.ensure_future(report_scope_pos(0.1,telescope,obs)) + + try : + loop.run_forever() + except KeyboardInterrupt : + pass + telescope.print_msg('Simulator shutting down') + scope.close() + loop.run_until_complete(scope.wait_closed()) + stell.close() + loop.run_until_complete(stell.wait_closed()) + + #loop.run_until_complete(asyncio.wait([broadcast(), timer(0.2), scope])) + loop.close() + +curses.wrapper(main) diff --git a/indi-celestronaux/simulator/nse_telescope.py b/indi-celestronaux/simulator/nse_telescope.py new file mode 100644 index 0000000..bd54ba9 --- /dev/null +++ b/indi-celestronaux/simulator/nse_telescope.py @@ -0,0 +1,760 @@ +#!/bin/env python3 + +import struct +import sys +from math import pi + +import curses +from collections import deque +import binascii + +# ID tables +targets={'ANY':0x00, + 'MB' :0x01, + 'HC' :0x04, + 'UKN1':0x05, + 'HC+':0x0d, + 'AZM':0x10, + 'ALT':0x11, + 'APP':0x20, + 'GPS':0xb0, + 'UKN2': 0xb4, + 'WiFi':0xb5, + 'BAT':0xb6, + 'CHG':0xb7, + 'LIGHT':0xbf + } +trg_names={value:key for key, value in targets.items()} + +control={ + 'HC' :0x04, + 'HC+':0x0d, + 'APP':0x20, + } + +commands={ + 'MC_GET_POSITION':0x01, + 'MC_GOTO_FAST':0x02, + 'MC_SET_POSITION':0x04, + 'MC_GET_???':0x05, + 'MC_SET_POS_GUIDERATE':0x06, + 'MC_SET_NEG_GUIDERATE':0x07, + 'MC_LEVEL_START':0x0b, + 'MC_SET_POS_BACKLASH':0x10, + 'MC_SET_NEG_BACKLASH':0x11, + 'MC_SLEW_DONE':0x13, + 'MC_GOTO_SLOW':0x17, + 'MC_AT_INDEX':0x18, + 'MC_SEEK_INDEX':0x19, + 'MC_SET_MAXRATE':0x20, + 'MC_GET_MAXRATE':0x21, + 'MC_ENABLE_MAXRATE':0x22, + 'MC_MAXRATE_ENABLED':0x23, + 'MC_MOVE_POS':0x24, + 'MC_MOVE_NEG':0x25, + 'MC_ENABLE_CORDWRAP':0x38, + 'MC_DISABLE_CORDWRAP':0x39, + 'MC_SET_CORDWRAP_POS':0x3a, + 'MC_POLL_CORDWRAP':0x3b, + 'MC_GET_CORDWRAP_POS':0x3c, + 'MC_GET_POS_BACKLASH':0x40, + 'MC_GET_NEG_BACKLASH':0x41, + 'MC_GET_AUTOGUIDE_RATE':0x47, + 'MC_GET_APPROACH':0xfc, + 'MC_SET_APPROACH':0xfd, + 'GET_VER':0xfe, + } +cmd_names={value:key for key, value in commands.items()} + +ACK_CMDS=[0x02,0x04,0x06,0x24,] + +MC_ALT=0x11 +MC_AZM=0x10 + +trg_cmds = { + 'BAT': { + 0x10:'GET_VOLTAGE', + 0x18:'GET_SET_CURRENT', + }, + 'CHG': { + 0x10: 'GET_SET_MODE', + }, + 'LIGHT': { + 0x10:'GET_SET_LEVEL', + }, +} + +RATES = { + 0 : 0.0, + 1 : 1/(360*60), + 2 : 2/(360*60), + 3 : 5/(360*60), + 4 : 15/(360*60), + 5 : 30/(360*60), + 6 : 1/360, + 7 : 2/360, + 8 : 5/360, + 9 : 10/360 +} + +def print_command(cmd): + if cmd[2] in (0x10, 0x20): + try : + return 'Command: %s->%s [%s] len:%d: data:%r' % ( + trg_names[cmd[1]], + trg_names[cmd[2]], + cmd_names[cmd[3]], cmd[0], cmd[4:-1]) + except KeyError : + pass + try : + return 'Command: %s->%s [%02x] len:%d: data:%r' % ( + trg_names[cmd[1]], + trg_names[cmd[2]], + cmd[3], cmd[0], cmd[4:-1]) + except KeyError : + pass + + return 'Command: %02x->%02x [%02x] len:%d: data:%r' % ( + cmd[1], cmd[2], cmd[3], cmd[0], cmd[4:-1]) + + +def decode_command(cmd): + return (cmd[3], cmd[1], cmd[2], cmd[0], cmd[4:-1], cmd[-1]) + +def split_cmds(data): + # split the data to commands + # the initial byte b'\03b' is removed from commands + cmds = [] + b = 0 + while True : + try : + p = data.index(b';', b) + cmds.append(data[p+1:p+abs(int(data[p+1]))+3]) + b += abs(int(data[p+1]))+3 + except ValueError: + return cmds + +def make_checksum(data): + return ((~sum([c for c in bytes(data)]) + 1) ) & 0xFF + + +def ack_cmd(cmd): + c,f,t,l,d,cs=decode_command(cmd) + rsp=b'' + if c in ACK_CMDS : + rsp=b';\x03'+bytes((t,f,c)) + rsp+=bytes((make_checksum(rsp[1:]),)) + return rsp + +def f2dms(f): + ''' + Convert fraction of the full rotation to DMS triple (degrees). + ''' + s= 1 if f>0 else -1 + d=360*abs(f) + dd=int(d) + mm=int((d-dd)*60) + ss=(d-dd-mm/60)*3600 + return dd,mm,ss + +def parse_pos(d): + ''' + Parse first three bytes into the DMS string + ''' + if len(d)>=3 : + pos=struct.unpack('!i',b'\x00'+d[:3])[0]/2**24 + return u'%03d°%02d\'%04.1f"' % f2dms(pos) + else : + return u'' + +def repr_pos(alt,azm): + return u'(%03d°%02d\'%04.1f", %03d°%02d\'%04.1f")' % (f2dms(alt) + f2dms(azm)) + +def repr_angle(a): + return u'%03d°%02d\'%04.1f"' % f2dms(a) + + +def unpack_int3(d): + return struct.unpack('!i',b'\x00'+d[:3])[0]/2**24 + +def pack_int3(f): + return struct.pack('!i',int(f*(2**24)))[1:] + +def unpack_int2(d): + return struct.unpack('!i',b'\x00\x00'+d[:2])[0] + +def pack_int2(v): + return struct.pack('!i',int(v))[-2:] + + + +class NexStarScope: + + __mcfw_ver=(7,11,5100//256,5100%256) + __hcfw_ver=(5,28,5300//256,5300%256) + __mbfw_ver=(1,0,0,1) + + trg=('MB', 'HC', 'UKN1', 'HC+', 'AZM', 'ALT', 'APP', + 'GPS', 'WiFi', 'BAT', 'CHG', 'LIGHT') + + def __init__(self, ALT=0.0, AZM=0.0, tui=True, stdscr=None): + self.tui=tui + self.alt=ALT + self.azm=AZM + self.trg_alt=self.alt + self.trg_azm=self.azm + self.alt_rate=0 + self.azm_rate=0 + self.alt_approach=0 + self.azm_approach=0 + self.last_cmd='' + self.slewing=False + self.guiding=False + self.goto=False + self.alt_guiderate=0.0 + self.azm_guiderate=0.0 + self.alt_maxrate=4000 + self.azm_maxrate=4000 + self.use_maxrate=False + self.cmd_log=deque(maxlen=30) + self.msg_log=deque(maxlen=10) + self.bat_current=2468 + self.bat_voltage=12345678 + self.lt_logo=64 + self.lt_tray=128 + self.lt_wifi=255 + self.charge=False + self.cordwrap = False + self.cordwrap_pos = 0 + self._other_handlers = { + 0x10: NexStarScope.cmd_0x10, + 0x18: NexStarScope.cmd_0x18, + 0xfe: NexStarScope.fw_version, + } + self._mc_handlers = { + 0x01 : NexStarScope.get_position, + 0x02 : NexStarScope.goto_fast, + 0x04 : NexStarScope.set_position, + 0x05 : NexStarScope.cmd_0x05, + 0x06 : NexStarScope.set_pos_guiderate, + 0x07 : NexStarScope.set_neg_guiderate, + 0x0b : NexStarScope.level_start, + 0x10 : NexStarScope.set_pos_backlash, + 0x11 : NexStarScope.set_neg_backlash, + 0x13 : NexStarScope.slew_done, + 0x17 : NexStarScope.goto_slow, + 0x18 : NexStarScope.at_index, + 0x19 : NexStarScope.seek_index, + 0x20 : NexStarScope.set_maxrate, + 0x21 : NexStarScope.get_maxrate, + 0x22 : NexStarScope.enable_maxrate, + 0x23 : NexStarScope.maxrate_enabled, + 0x24 : NexStarScope.move_pos, + 0x25 : NexStarScope.move_neg, + 0x38 : NexStarScope.enable_cordwrap, + 0x39 : NexStarScope.disable_cordwrap, + 0x3a : NexStarScope.set_cordwrap_pos, + 0x3b : NexStarScope.get_cordwrap, + 0x3c : NexStarScope.get_cordwrap_pos, + 0x40 : NexStarScope.get_pos_backlash, + 0x41 : NexStarScope.get_neg_backlash, + 0x47 : NexStarScope.get_autoguide_rate, + 0xfc : NexStarScope.get_approach, + 0xfd : NexStarScope.set_approach, + 0xfe : NexStarScope.fw_version, + } + if tui : self.init_dsp(stdscr) + + def send_ack(self, data, snd, rcv): + return b'' + + def set_maxrate(self, data, snd, rcv): + if rcv==0x10 : + self.alt_maxrate=unpack_int2(data) + else : + self.azm_maxrate=unpack_int2(data) + return b'' + + def get_maxrate(self, data, snd, rcv): + if len(data) == 0 : + #return pack_int2(self.alt_maxrate) + pack_int2(self.azm_maxrate) + return bytes.fromhex('0fa01194') + else : + return b'' + + def enable_maxrate(self, data, snd, rcv): + self.use_maxrate=bool(data[0]) + return b'' + + def maxrate_enabled(self, data, snd, rcv): + if self.use_maxrate : + return b'\x01' + else : + return b'\x00' + + def cmd_0x10(self, data, snd, rcv): + if rcv == 0xbf : # LIGHT + if len(data)==2 : # Set level + if data[0]==0 : + self.lt_tray=data[1] + elif data[0]==1 : + self.lt_logo=data[1] + else : + self.lt_wifi=data[1] + return b'' + elif len(data)==1: # Get level + if data[0]==0 : + return bytes([int(self.lt_tray%256)]) + elif data[0]==1 : + return bytes([int(self.lt_logo%256)]) + else : + return bytes([int(self.lt_wifi%256)]) + else : + return b'' + elif rcv == 0xb7 : # CHG + if len(data): + self.charge = bool(data[0]) + return b'' + else : + return bytes([int(self.charge)]) + elif rcv == 0xb6 : # BAT + self.bat_voltage*=0.99 + v=struct.pack('!i',int(self.bat_voltage)) + return bytes.fromhex('0102') + v + else : + return b'' + + def cmd_0x18(self, data, snd, rcv): + if rcv == 0xb6 : # BAT + if len(data): + i=data[0]*256+data[1] + i=min(5000,i) + i=max(2000,i) + self.bat_current=i + return struct.pack('!i',int(self.bat_current))[-2:] + + + def get_position(self, data, snd, rcv): + try : + trg = trg_names[rcv] + except KeyError : + trg = '???' + if trg == 'ALT': + return pack_int3(self.alt) + else : + return pack_int3(self.azm) + + def goto_fast(self, data, snd, rcv): + self.last_cmd='GOTO_FAST' + self.slewing=True + self.goto=True + self.guiding=False + self.alt_guiderate=0 + self.azm_guiderate=0 + if rcv==MC_ALT : + r=self.alt_maxrate/(360e3) + else : + r=self.azm_maxrate/(360e3) + a=unpack_int3(data) + if trg_names[rcv] == 'ALT': + self.trg_alt=a + if a-self.alt < 0 : + r = -r + self.alt_rate = r + else : + self.trg_azm=a%1.0 + if self.trg_azm - self.azm < 0 : + r = -r + if abs(self.trg_azm - self.azm) > 0.5 : + r = -r + self.azm_rate = r + return b'' + + def set_position(self,data, snd, rcv): + return b'' + + def cmd_0x05(self, data, snd, rcv): + return bytes.fromhex('1685') + + def set_pos_guiderate(self, data, snd, rcv): + # The 1.1 factor is experimental to fit the actual hardware + a=1.1*(2**24/1000/360/60/60)*unpack_int3(data) # (transform to rot/sec) + self.guiding = a>0 + if trg_names[rcv] == 'ALT': + self.alt_guiderate=a + else : + self.azm_guiderate=a + return b'' + + def set_neg_guiderate(self, data, snd, rcv): + # The 1.1 factor is experimental to fit the actual hardware + a=1.1*(2**24/1000/360/60/60)*unpack_int3(data) # (transform to rot/sec) + self.guiding = a>0 + if trg_names[rcv] == 'ALT': + self.alt_guiderate=-a + else : + self.azm_guiderate=-a + return b'' + + def level_start(self, data, snd, rcv): + return b'' + + def set_pos_backlash(self, data, snd, rcv): + return b'' + + def set_neg_backlash(self, data, snd, rcv): + return b'' + + def goto_slow(self, data, snd, rcv): + self.last_cmd='GOTO_SLOW' + self.slewing=True + self.goto=True + self.guiding=False + self.alt_guiderate=0 + self.azm_guiderate=0 + r=0.2/360 + a=unpack_int3(data) + if trg_names[rcv] == 'ALT': + self.trg_alt=a + if self.alt < a : + self.alt_rate = r + else : + self.alt_rate = -r + else : + self.trg_azm=a%1.0 + f = 1 if abs(self.azm - self.trg_azm)<0.5 else -1 + if self.azm < self.trg_azm : + self.azm_rate = f*r + else : + self.azm_rate = -f*r + return b'' + + def slew_done(self, data, snd, rcv): + if rcv == MC_ALT : + return b'\x00' if self.alt_rate else b'\xff' + if rcv == MC_AZM : + return b'\x00' if self.azm_rate else b'\xff' + + def at_index(self, data, snd, rcv): + return b'\x00' + + def seek_index(self, data, snd, rcv): + return b'' + + def move_pos(self, data, snd, rcv): + self.last_cmd='MOVE_POS' + self.slewing=True + self.goto=False + r=RATES[int(data[0])] + if trg_names[rcv] == 'ALT': + self.alt_rate = r + else : + self.azm_rate = r + return b'' + + def move_neg(self, data, snd, rcv): + self.last_cmd='MOVE_NEG' + self.slewing=True + self.goto=False + r=RATES[int(data[0])] + if trg_names[rcv] == 'ALT': + self.alt_rate = -r + else : + self.azm_rate = -r + return b'' + + def enable_cordwrap(self, data, snd, rcv): + self.cordwrap = True + return b'' + + def disable_cordwrap(self, data, snd, rcv): + self.cordwrap = False + return b'' + + def set_cordwrap_pos(self, data, snd, rcv): + self.cordwrap_pos=struct.unpack('!i',b'\x00'+data[:3])[0] + return b'' + + def get_cordwrap(self, data, snd, rcv): + return b'\xFF' if self.cordwrap else b'\x00' + + def get_cordwrap_pos(self, data, snd, rcv): + return pack_int3(self.cordwrap_pos) + + def get_pos_backlash(self, data, snd, rcv): + return b'\x00' + + def get_neg_backlash(self, data, snd, rcv): + return b'\x00' + + def get_autoguide_rate(self, data, snd, rcv): + return b'\xf0' + + def get_approach(self, data, snd, rcv): + try : + trg = trg_names[rcv] + except KeyError : + trg = '???' + if trg == 'ALT': + return bytes((self.alt_approach,)) + else : + return bytes((self.azm_approach,)) + + def set_approach(self, data, snd, rcv): + try : + trg = trg_names[rcv] + except KeyError : + trg = '???' + if trg == 'ALT': + self.alt_approach=data[0] + else : + self.azm_approach=data[0] + return b'' + + def fw_version(self, data, snd, rcv): + try : + trg = trg_names[rcv] + except KeyError : + trg = '???' + if trg in ('ALT','AZM'): + return bytes(NexStarScope.__mcfw_ver) + elif trg in ('MB', ): + return bytes(NexStarScope.__mbfw_ver) + elif trg in ('HC', 'HC+'): + return bytes(NexStarScope.__hcfw_ver) + else : + return b'' + + def init_dsp(self,stdscr): + self.scr=stdscr + if stdscr : + self.cmd_log_w=curses.newwin(self.cmd_log.maxlen+2,60,0,50) + self.state_w=curses.newwin(1,80,0,0) + self.state_w.border() + self.pos_w=curses.newwin(4,25,1,0) + self.pos_w.border() + self.trg_w=curses.newwin(4,25,1,25) + self.trg_w.border() + self.rate_w=curses.newwin(4,25,5,0) + self.guide_w=curses.newwin(4,25,5,25) + self.other_w=curses.newwin(8,50,9,0) + self.msg_w=curses.newwin(self.msg_log.maxlen+2,50,17,0) + stdscr.refresh() + + def update_dsp(self): + if self.scr : + mode = 'Idle' + if self.guiding : mode = 'Guiding' + if self.slewing : mode = 'Slewing' + self.state_w.clear() + self.state_w.addstr(0,1,'State: %8s' % mode) + self.state_w.refresh() + self.pos_w.clear() + self.pos_w.border() + self.pos_w.addstr(0,1,'Position:') + self.pos_w.addstr(1,3,'Alt: ' + repr_angle(self.alt)) + self.pos_w.addstr(2,3,'Azm: ' + repr_angle(self.azm)) + self.pos_w.refresh() + self.trg_w.clear() + self.trg_w.border() + self.trg_w.addstr(0,1,'Target:') + self.trg_w.addstr(1,3,'Alt: ' + repr_angle(self.trg_alt)) + self.trg_w.addstr(2,3,'Azm: ' + repr_angle(self.trg_azm)) + self.trg_w.refresh() + self.rate_w.clear() + self.rate_w.border() + self.rate_w.addstr(0,1,'Move rate:') + self.rate_w.addstr(1,3,'Alt: %+8.4f °/s' % (self.alt_rate*360)) + self.rate_w.addstr(2,3,'Azm: %+8.4f °/s' % (self.azm_rate*360)) + self.rate_w.refresh() + self.guide_w.clear() + self.guide_w.border() + self.guide_w.addstr(0,1,'Guide rate:') + self.guide_w.addstr(1,3,'Alt: %+8.4f "/s' % (self.alt_guiderate*360*60*60)) + self.guide_w.addstr(2,3,'Azm: %+8.4f "/s' % (self.azm_guiderate*360*60*60)) + self.guide_w.refresh() + self.other_w.clear() + self.other_w.border() + self.other_w.addstr(0,1,'Other:') + self.other_w.addstr(1,3,'BAT: %9.6f V' % (self.bat_voltage/1e6)) + self.other_w.addstr(2,3,'CHG: %5.3f A' % (self.bat_current/1e3)) + self.other_w.addstr(3,3,'LIGHTS: Logo: %d Tray: %d WiFi: %d' % (self.lt_logo, self.lt_tray, self.lt_wifi)) + self.other_w.addstr(4,3,'Charge: %s' % ('On' if self.charge else 'Auto')) + if self.use_maxrate : + self.other_w.addstr(5,1,'*') + self.other_w.addstr(5,3,'Max rate ALT:%.2f AZM:%.2f' % (self.alt_maxrate/1e3, self.azm_maxrate/1e3)) + self.other_w.addstr(6,3,'Cordwrap: %3s' % ('On' if self.cordwrap else 'Off')) + self.other_w.addstr(6,20,'Pos: ' + repr_angle(self.cordwrap_pos)) + self.other_w.refresh() + self.cmd_log_w.clear() + self.cmd_log_w.border() + self.cmd_log_w.addstr(0,1,'Commands log') + for n,cmd in enumerate(self.cmd_log) : + self.cmd_log_w.addstr(n+1,1,cmd) + self.cmd_log_w.refresh() + self.msg_w.border() + self.msg_w.addstr(0,1,'Msg:') + for n,cmd in enumerate(self.msg_log) : + self.msg_w.addstr(n+1,1,cmd) + self.msg_w.refresh() + + def show_status(self): + if self.tui and self.scr: + self.update_dsp() + else : + mode = 'Idle' + if self.guiding : mode = 'Guiding' + if self.slewing : mode = 'Slewing' + print('\r%8s: %s -> %s S(%+5.2f %+5.2f) G(%+.4f %+.4f) CMD: %10s' % ( + mode, repr_pos(self.alt, self.azm), + repr_pos(self.trg_alt, self.trg_azm), + self.alt_rate*360, self.azm_rate*360, # deg/sec + self.alt_guiderate*360*60*60, self.azm_guiderate*360*60*60, # arcsec/sec + self.last_cmd), end='') + sys.stdout.flush() + + def tick(self, interval): + eps=1e-6 # 0.1" precission + maxrate = 5/360 + if self.last_cmd=='GOTO_FAST' : + eps*=100 + + self.alt += (self.alt_rate + self.alt_guiderate)*interval + self.azm += (self.azm_rate + self.azm_guiderate)*interval + if self.slewing and self.goto: + # AZM + r=self.trg_azm - self.azm + if abs(r)>0.5 : + r = -r + s=1 if r>0 else -1 + mr=min(maxrate,abs(self.azm_rate)) + if mr*interval > abs(r) : + mr/=2 + self.azm_rate=s*min(mr,abs(r)) + self.azm_rate=s*mr + + # ALT + r=self.trg_alt - self.alt + s=1 if r>0 else -1 + mr=min(maxrate,abs(self.alt_rate)) + if mr*interval > abs(r) : + mr/=2 + self.alt_rate=s*min(mr,abs(r)) + self.alt_rate=s*mr + + if abs(self.azm_rate) < eps and abs(self.alt_rate) < eps : + self.slewing=False + self.goto=False + if abs(self.azm_rate) < eps : + self.azm_rate=0 + if abs(self.alt_rate) < eps : + self.alt_rate=0 + self.show_status() + + @property + def alt(self): + return self.__alt + + @alt.setter + def alt(self,ALT): + self.__alt=ALT + # Altitude movement limits + #self.__alt = min(self.__alt,0.23) + #self.__alt = max(self.__alt,-0.03) + + @property + def azm(self): + return self.__azm + + @azm.setter + def azm(self,AZM): + self.__azm=AZM % 1.0 + + @property + def trg_alt(self): + return self.__trg_alt + + @trg_alt.setter + def trg_alt(self,ALT): + self.__trg_alt=ALT + # Altitude movement limits + #self.__trg_alt = min(self.__trg_alt,0.24) + #self.__trg_alt = max(self.__trg_alt,-0.01) + + @property + def trg_azm(self): + return self.__trg_azm + + @trg_azm.setter + def trg_azm(self,AZM): + self.__trg_azm=AZM % 1.0 + + def handle_cmd(self, cmd): + #print("-> Scope received %s." % (print_command(cmd))) + try : + c,f,t,l,d,s=decode_command(cmd) + except IndexError : + self.print_msg("Malformed command: %r" % (cmd,)) + return b'' + resp=b'' + if make_checksum(cmd[:-1]) != s : + self.print_msg("Wrong checksum. Ignoring.") + else : + resp = b';' + cmd + if t in (0x10, 0x11): + handlers=self._mc_handlers + try : + s=('%s[%s] ' % (trg_names[t], cmd_names[c])) + ''.join('%02x' % b for b in d) + except KeyError : + s=('MC[%02x]' % c) + ' ' + ''.join('%02x' % b for b in d) + else : + handlers=self._other_handlers + try : + s=('%s[%s]' % (trg_names[t],trg_cmds[trg_names[t]][c])) + ' ' + ''.join('%02x' % b for b in d) + except KeyError : + s=('%02x[%02x]' % (t,c)) + ' ' + ''.join('%02x' % b for b in d) + sr=b'' + if c in handlers : + r = handlers[c](self,d,f,t) + sr = r + r = bytes((len(r)+3,t,f,c)) + r + resp += b';' + r + bytes((make_checksum(r),)) + #print('Response: %r' % resp) + else : + #print('Scope got unknown command %02x' % c) + #print("-> Scope received %s." % (print_command(cmd))) + s = '** ' + s + pass + + if 'MC_GET_POSITION' in s : + return resp + + s += '-> ' + ''.join('%02x' % x for x in sr) + + if self.cmd_log : + if s != self.cmd_log[-1] : + self.cmd_log.append(s) + else : + self.cmd_log.append(s) + + return resp + + def print_msg(self, msg): + if self.msg_log : + if msg != self.msg_log[-1] : + self.msg_log.append(msg) + else : + self.msg_log.append(msg) + + + + def handle_msg(self, msg): + ''' + React to message. Get AUX command(s) in the message and react to it. + Return a message simulating real AUX scope response. + ''' + return b''.join([self.handle_cmd(cmd) for cmd in split_cmds(msg)]) + + + + -- cgit v1.2.3