From 2c885b272f96fc2d12e757ea6a91352f0509c4f9 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 3 Jan 2016 15:39:29 -0500 Subject: [PATCH] Import hamlib setup from SoapyAudio, prep new RigThread --- CMakeLists.txt | 35 +++++++++++ cmake/Modules/Findhamlib.cmake | 59 ++++++++++++++++++ cmake/Modules/LibFindMacros.cmake | 99 +++++++++++++++++++++++++++++++ src/rig/RigThread.cpp | 80 +++++++++++++++++++++++++ src/rig/RigThread.h | 41 +++++++++++++ 5 files changed, 314 insertions(+) create mode 100644 cmake/Modules/Findhamlib.cmake create mode 100644 cmake/Modules/LibFindMacros.cmake create mode 100644 src/rig/RigThread.cpp create mode 100644 src/rig/RigThread.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ab7f52..06f143e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,25 @@ ENDIF() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") +option(USE_HAMLIB ON "Support hamlib for radio control functions.") + +if (USE_HAMLIB) + find_package(hamlib REQUIRED) + + if (NOT hamlib_FOUND) + message(FATAL_ERROR "hamlib development files not found...") + endif () + + include_directories(${hamlib_INCLUDE_DIRS}) + if (${hamlib_STATIC_FOUND}) + link_libraries(${hamlib_STATIC_LIBRARIES}) + else() + link_libraries(${hamlib_LIBRARIES}) + endif() + + ADD_DEFINITIONS(-DUSE_HAMLIB) +endif () + macro(configure_files srcDir destDir globStr) message(STATUS "Copying ${srcDir}/${globStr} to directory ${destDir}") make_directory(${destDir}) @@ -433,6 +452,19 @@ IF(ENABLE_LIQUID_EXPERIMENTAL) ENDIF() ENDIF() + +IF (USE_HAMLIB) + SET (cubicsdr_headers + ${cubicsdr_headers} + src/rig/RigThread.h + ) + SET (cubicsdr_sources + ${cubicsdr_sources} + src/rig/RigThread.cpp + ) +ENDIF() + + SET (CUBICSDR_RESOURCES ${PROJECT_SOURCE_DIR}/font/vera_sans_mono12.fnt ${PROJECT_SOURCE_DIR}/font/vera_sans_mono16.fnt @@ -453,6 +485,9 @@ set(REG_EXT "[^/]*([.]cpp|[.]c|[.]h|[.]hpp)$") SOURCE_GROUP("Base" REGULAR_EXPRESSION "src/${REG_EXT}") SOURCE_GROUP("Forms\\SDRDevices" REGULAR_EXPRESSION "src/forms/SDRDevices/${REG_EXT}") SOURCE_GROUP("SDR" REGULAR_EXPRESSION "src/sdr/${REG_EXT}") +IF(USE_HAMLIB) + SOURCE_GROUP("Rig" REGULAR_EXPRESSION "src/rig/${REG_EXT}") +ENDIF() SOURCE_GROUP("Demodulator" REGULAR_EXPRESSION "src/demod/${REG_EXT}") SOURCE_GROUP("Modem" REGULAR_EXPRESSION "src/modules/modem/${REG_EXT}") SOURCE_GROUP("Modem\\Analog" REGULAR_EXPRESSION "src/modules/modem/analog/${REG_EXT}") diff --git a/cmake/Modules/Findhamlib.cmake b/cmake/Modules/Findhamlib.cmake new file mode 100644 index 0000000..abed74b --- /dev/null +++ b/cmake/Modules/Findhamlib.cmake @@ -0,0 +1,59 @@ +# - Try to find hamlib +# Once done, this will define: +# +# hamlib_FOUND - system has Hamlib-2 +# hamlib_INCLUDE_DIRS - the Hamlib-2 include directories +# hamlib_LIBRARIES - link these to use Hamlib-2 +# hamlib_STATIC_FOUND - system has Hamlib-2 static archive +# hamlib_STATIC_LIBRARIES - link these to use Hamlib-2 static archive + +include (LibFindMacros) + +# pkg-config? +find_path (__hamlib_pc_path NAMES hamlib.pc + PATH_SUFFIXES lib/pkgconfig +) +if (__hamlib_pc_path) + set (ENV{PKG_CONFIG_PATH} "${__hamlib_pc_path}" "$ENV{PKG_CONFIG_PATH}") + unset (__hamlib_pc_path CACHE) +endif () + +# Use pkg-config to get hints about paths, libs and, flags +unset (__pkg_config_checked_hamlib CACHE) +libfind_pkg_check_modules (PC_HAMLIB hamlib) + +if (NOT PC_HAMLIB_STATIC_LIBRARIES) + if (WIN32) + set (PC_HAMLIB_STATIC_LIBRARIES hamlib ws2_32) + else () + set (PC_HAMLIB_STATIC_LIBRARIES hamlib m dl usb) + endif () +endif () + +# The libraries +libfind_library (hamlib hamlib) +libfind_library (hamlib_STATIC libhamlib.a) + +find_path (hamlib_INCLUDE_DIR hamlib/rig.h) + +# Set the include dir variables and the libraries and let libfind_process do the rest +set (hamlib_PROCESS_INCLUDES hamlib_INCLUDE_DIR) +set (hamlib_PROCESS_LIBS hamlib_LIBRARY) +libfind_process (hamlib) + +set (hamlib_STATIC_PROCESS_INCLUDES hamlib_STATIC_INCLUDE_DIR) +set (hamlib_STATIC_PROCESS_LIBS hamlib_STATIC_LIBRARY PC_HAMLIB_STATIC_LIBRARIES) +libfind_process (hamlib_STATIC) + +# make sure we return a full path for the library we return +if (hamlib_FOUND) + list (REMOVE_ITEM hamlib_LIBRARIES hamlib) + if (hamlib_STATIC_LIBRARIES) + list (REMOVE_ITEM hamlib_STATIC_LIBRARIES hamlib) + endif () +endif () + +# Handle the QUIETLY and REQUIRED arguments and set HAMLIB_FOUND to +# TRUE if all listed variables are TRUE +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args (hamlib DEFAULT_MSG hamlib_INCLUDE_DIRS hamlib_LIBRARY hamlib_LIBRARIES) diff --git a/cmake/Modules/LibFindMacros.cmake b/cmake/Modules/LibFindMacros.cmake new file mode 100644 index 0000000..69975c5 --- /dev/null +++ b/cmake/Modules/LibFindMacros.cmake @@ -0,0 +1,99 @@ +# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments +# used for the current package. For this to work, the first parameter must be the +# prefix of the current package, then the prefix of the new package etc, which are +# passed to find_package. +macro (libfind_package PREFIX) + set (LIBFIND_PACKAGE_ARGS ${ARGN}) + if (${PREFIX}_FIND_QUIETLY) + set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} QUIET) + endif (${PREFIX}_FIND_QUIETLY) + if (${PREFIX}_FIND_REQUIRED) + set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} REQUIRED) + endif (${PREFIX}_FIND_REQUIRED) + find_package(${LIBFIND_PACKAGE_ARGS}) +endmacro (libfind_package) + +# CMake developers made the UsePkgConfig system deprecated in the same release (2.6) +# where they added pkg_check_modules. Consequently I need to support both in my scripts +# to avoid those deprecated warnings. Here's a helper that does just that. +# Works identically to pkg_check_modules, except that no checks are needed prior to use. +macro (libfind_pkg_check_modules PREFIX PKGNAME) + if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) + include(UsePkgConfig) + pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS) + else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(${PREFIX} ${PKGNAME}) + endif (PKG_CONFIG_FOUND) + endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) +endmacro (libfind_pkg_check_modules) + +# Do the final processing once the paths have been detected. +# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain +# all the variables, each of which contain one include directory. +# Ditto for ${PREFIX}_PROCESS_LIBS and library files. +# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES. +# Also handles errors in case library detection was required, etc. +macro (libfind_process PREFIX) + # Skip processing if already processed during this run + if (NOT ${PREFIX}_FOUND) + # Start with the assumption that the library was found + set (${PREFIX}_FOUND TRUE) + + # Process all includes and set _FOUND to false if any are missing + foreach (i ${${PREFIX}_PROCESS_INCLUDES}) + if (${i}) + set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}}) + mark_as_advanced(${i}) + else (${i}) + set (${PREFIX}_FOUND FALSE) + endif (${i}) + endforeach (i) + + # Process all libraries and set _FOUND to false if any are missing + foreach (i ${${PREFIX}_PROCESS_LIBS}) + if (${i}) + set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}}) + mark_as_advanced(${i}) + else (${i}) + set (${PREFIX}_FOUND FALSE) + endif (${i}) + endforeach (i) + + # Print message and/or exit on fatal error + if (${PREFIX}_FOUND) + if (NOT ${PREFIX}_FIND_QUIETLY) + message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}") + endif (NOT ${PREFIX}_FIND_QUIETLY) + else (${PREFIX}_FOUND) + if (${PREFIX}_FIND_REQUIRED) + foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS}) + message("${i}=${${i}}") + endforeach (i) + message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.") + endif (${PREFIX}_FIND_REQUIRED) + endif (${PREFIX}_FOUND) + endif (NOT ${PREFIX}_FOUND) +endmacro (libfind_process) + +macro(libfind_library PREFIX basename) + set(TMP "") + if(MSVC80) + set(TMP -vc80) + endif(MSVC80) + if(MSVC90) + set(TMP -vc90) + endif(MSVC90) + set(${PREFIX}_LIBNAMES ${basename}${TMP}) + if(${ARGC} GREATER 2) + set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2}) + string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES}) + set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP}) + endif(${ARGC} GREATER 2) + find_library(${PREFIX}_LIBRARY + NAMES ${${PREFIX}_LIBNAMES} + PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS} + ) +endmacro(libfind_library) + diff --git a/src/rig/RigThread.cpp b/src/rig/RigThread.cpp new file mode 100644 index 0000000..e186363 --- /dev/null +++ b/src/rig/RigThread.cpp @@ -0,0 +1,80 @@ +#include "RigThread.h" + +std::vector RigThread::rigCaps; + +RigThread::RigThread() { + terminated.store(true); +} + +RigThread::~RigThread() { + +} + +void RigThread::enumerate() { + rig_set_debug(RIG_DEBUG_ERR); + rig_load_all_backends(); + RigThread::rigCaps.clear(); + rig_list_foreach(RigThread::add_hamlib_rig, 0); + std::sort(RigThread::rigCaps.begin(), RigThread::rigCaps.end(), rigGreater()); +} + +int RigThread::add_hamlib_rig(const struct rig_caps *rc, void* f) +{ + rigCaps.push_back(rc); + return 1; +} + +void RigThread::initRig(rig_model_t rig_model, std::string rig_file, int serial_rate) { + rigModel = rig_model; + rigFile = rig_file; + serialRate = serial_rate; +}; + +void RigThread::run() { + int retcode, status; + + std::cout << "Rig thread starting." << std::endl; + + rig = rig_init(rigModel); + strncpy(rig->state.rigport.pathname, rigFile.c_str(), FILPATHLEN - 1); + rig->state.rigport.parm.serial.rate = serialRate; + retcode = rig_open(rig); + char *info_buf = (char *)rig_get_info(rig); + std::cout << "Rig info: " << info_buf << std::endl; + + while (!terminated.load()) { + std::this_thread::sleep_for(std::chrono::milliseconds(150)); + if (freqChanged.load()) { + status = rig_get_freq(rig, RIG_VFO_CURR, &freq); + if (freq != newFreq) { + freq = newFreq; + rig_set_freq(rig, RIG_VFO_CURR, freq); + std::cout << "Set Rig Freq: %f" << newFreq << std::endl; + } + + freqChanged.store(false); + } else { + status = rig_get_freq(rig, RIG_VFO_CURR, &freq); + } + + std::cout << "Rig Freq: " << freq << std::endl; + } + + rig_close(rig); + + std::cout << "Rig thread exiting." << std::endl; +}; + +freq_t RigThread::getFrequency() { + if (freqChanged.load()) { + return newFreq; + } else { + return freq; + } +} + +void RigThread::setFrequency(freq_t new_freq) { + newFreq = new_freq; + freqChanged.store(true); +} + diff --git a/src/rig/RigThread.h b/src/rig/RigThread.h new file mode 100644 index 0000000..60c4c85 --- /dev/null +++ b/src/rig/RigThread.h @@ -0,0 +1,41 @@ +#pragma once + +#include "IOThread.h" +#include "CubicSDR.h" +#include +#include + +struct rigGreater +{ + bool operator()( const struct rig_caps *lx, const struct rig_caps *rx ) const { + std::string ln(std::string(std::string(lx->mfg_name) + " " + std::string(lx->model_name))); + std::string rn(std::string(std::string(rx->mfg_name) + " " + std::string(rx->model_name))); + return ln.compare(rn)<0; + } +}; + +class RigThread : public IOThread { +public: + RigThread(); + ~RigThread(); + + void initRig(rig_model_t rig_model, std::string rig_file, int serial_rate); + void run(); + + freq_t getFrequency(); + void setFrequency(freq_t new_freq); + + static void enumerate(); + static int add_hamlib_rig(const struct rig_caps *rc, void* f); + +private: + RIG *rig; + rig_model_t rigModel; + std::string rigFile; + int serialRate; + + freq_t freq; + freq_t newFreq; + std::atomic_bool freqChanged; + static std::vector rigCaps; +}; \ No newline at end of file